Page Menu
Home
Phabricator (Chris)
Search
Configure Global Search
Log In
Files
F626581
anomalies.as
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Authored By
Unknown
Size
11 KB
Referenced Files
None
Subscribers
None
anomalies.as
View Options
#
priority
init
2000
import
hooks
;
import
saving
;
export
AnomalyType
,
AnomalyOption
,
AnomalyState
;
export
getAnomalyType
,
getAnomalyTypeCount
;
export
getDistributedAnomalyType
;
export
Targets
;
tidy
final
class
AnomalyOption
{
uint
id
=
0
;
Sprite
icon
;
string
ident
,
desc
;
string
blurb
;
bool
isSafe
=
true
;
double
chance
=
1.0
;
array
<
IAnomalyHook
@
>
hooks
;
array
<
AnomalyResult
@
>
results
;
double
resultTotal
=
0.0
;
Targets
targets
;
bool
checkTargets
(
Empire
@
emp
,
const
Targets
@
check
)
const
{
if
(
check
is
null
)
{
if
(
targets
.
targets
.
length
==
0
)
return
true
;
else
return
false
;
}
if
(
check
.
targets
.
length
!=
targets
.
targets
.
length
)
return
false
;
for
(
uint
i
=
0
,
cnt
=
check
.
targets
.
length
;
i
<
cnt
;
++
i
)
{
if
(!
isValidTarget
(
emp
,
i
,
check
.
targets
[
i
]))
return
false
;
}
return
true
;
}
bool
isValidTarget
(
Empire
@
emp
,
uint
index
,
const
Target
@
targ
)
const
{
if
(
index
>=
targets
.
targets
.
length
)
return
false
;
if
(
targ
.
type
!=
targets
.
targets
[
index
].
type
)
return
false
;
if
(!
targ
.
filled
)
return
false
;
if
(
targets
.
targets
[
index
].
filled
&&
targets
.
targets
[
index
]
!=
targ
)
return
false
;
for
(
uint
i
=
0
,
cnt
=
hooks
.
length
;
i
<
cnt
;
++
i
)
{
if
(!
hooks
[
i
].
isValidTarget
(
emp
,
index
,
targ
))
return
false
;
}
return
true
;
}
#
section
server
void
choose
(
Anomaly
@
anomaly
,
Empire
@
emp
,
Targets
@
targets
)
const
{
if
(!
checkTargets
(
emp
,
targets
))
return
;
for
(
uint
i
=
0
,
cnt
=
hooks
.
length
;
i
<
cnt
;
++
i
)
hooks
[
i
].
choose
(
anomaly
,
emp
,
targets
);
double
roll
=
randomd
(
0.0
,
resultTotal
);
for
(
uint
i
=
0
,
cnt
=
results
.
length
;
i
<
cnt
;
++
i
)
{
if
(
roll
<=
results
[
i
].
chance
)
{
results
[
i
].
choose
(
anomaly
,
emp
,
targets
);
break
;
}
roll
-=
results
[
i
].
chance
;
}
}
bool
giveOption
(
Anomaly
@
anomaly
,
Empire
@
emp
)
const
{
for
(
uint
i
=
0
,
cnt
=
hooks
.
length
;
i
<
cnt
;
++
i
)
{
if
(!
hooks
[
i
].
giveOption
(
anomaly
,
emp
))
return
false
;
}
return
true
;
}
#
section
all
};
tidy
class
AnomalyResult
{
double
chance
=
1.0
;
array
<
IAnomalyHook
@
>
hooks
;
void
choose
(
Anomaly
@
anomaly
,
Empire
@
emp
,
Targets
@
targets
)
const
{
for
(
uint
i
=
0
,
cnt
=
hooks
.
length
;
i
<
cnt
;
++
i
)
hooks
[
i
].
choose
(
anomaly
,
emp
,
targets
);
}
};
interface
IAnomalyHook
{
void
init
(
AnomalyType
@
type
);
void
choose
(
Anomaly
@
obj
,
Empire
@
emp
,
Targets
@
targets
)
const
;
bool
giveOption
(
Anomaly
@
obj
,
Empire
@
emp
)
const
;
bool
isValidTarget
(
Empire
@
emp
,
uint
index
,
const
Target
@
targ
)
const
;
};
tidy
class
AnomalyHook
:
Hook
,
IAnomalyHook
{
void
init
(
AnomalyType
@
type
)
{}
void
choose
(
Anomaly
@
obj
,
Empire
@
emp
,
Targets
@
targets
)
const
{}
bool
giveOption
(
Anomaly
@
obj
,
Empire
@
emp
)
const
{
return
true
;
}
bool
isValidTarget
(
Empire
@
emp
,
uint
index
,
const
Target
@
targ
)
const
{
return
true
;
}
};
tidy
class
AnomalyType
{
uint
id
=
0
;
string
ident
,
name
=
locale
::
ANOMALY
,
desc
,
narrative
;
string
modelName
=
"Debris"
,
matName
=
"Asteroid"
;
double
frequency
=
1.0
;
double
scanTime
=
60.0
;
bool
unique
=
false
;
double
stateTotal
=
0.0
;
array
<
AnomalyState
@
>
states
;
array
<
AnomalyOption
@
>
options
;
const
AnomalyState
@
getState
()
const
{
if
(
states
.
length
==
0
)
return
null
;
double
value
=
randomd
(
0.0
,
stateTotal
);
for
(
uint
i
=
0
,
cnt
=
states
.
length
;
i
<
cnt
;
++
i
)
{
if
(
value
<=
states
[
i
].
frequency
)
return
states
[
i
];
value
-=
states
[
i
].
frequency
;
}
return
states
[
states
.
length
-
1
];
}
const
AnomalyOption
@
getOption
(
const
string
&
ident
)
const
{
for
(
uint
i
=
0
,
cnt
=
options
.
length
;
i
<
cnt
;
++
i
)
{
if
(
options
[
i
].
ident
==
ident
)
return
options
[
i
];
}
return
null
;
}
const
AnomalyState
@
getState
(
const
string
&
ident
)
const
{
for
(
uint
i
=
0
,
cnt
=
states
.
length
;
i
<
cnt
;
++
i
)
{
if
(
states
[
i
].
ident
==
ident
)
return
states
[
i
];
}
return
null
;
}
};
tidy
class
AnomalyState
{
uint
id
=
0
;
string
ident
;
string
narrative
;
string
modelName
=
"Debris"
,
matName
=
"Asteroid"
;
array
<
const
AnomalyOption
@
>
options
;
array
<
double
>
option_chances
;
array
<
string
>
def_options
;
double
frequency
=
1.0
;
};
void
parseLine
(
string
&
line
,
AnomalyType
@
anomaly
,
AnomalyResult
@
result
,
ReadFile
@
file
)
{
//Try to find the design
if
(
line
.
findFirst
(
"("
)
==
-
1
)
{
error
(
"Invalid line during "
+
anomaly
.
ident
+
": "
+
escape
(
line
));
}
else
{
if
(
anomaly
.
options
.
length
==
0
)
{
error
(
"Missing 'Pickup:' line for: "
+
escape
(
line
));
return
;
}
//Hook line
auto
@
hook
=
cast
<
IAnomalyHook
>(
parseHook
(
line
,
"anomaly_effects::"
,
instantiate
=
false
,
file
=
file
));
if
(
hook
!
is
null
)
{
if
(
result
!
is
null
)
result
.
hooks
.
insertLast
(
hook
);
else
anomaly
.
options
[
anomaly
.
options
.
length
-
1
].
hooks
.
insertLast
(
hook
);
}
}
}
void
loadAnomaly
(
const
string
&
filename
)
{
ReadFile
file
(
filename
,
true
);
string
key
,
value
;
AnomalyType
@
anomaly
;
AnomalyOption
@
opt
;
AnomalyState
@
state
;
AnomalyResult
@
result
;
uint
index
=
0
;
while
(
file
++)
{
key
=
file
.
key
;
value
=
file
.
value
;
if
(
file
.
fullLine
)
{
if
(
anomaly
is
null
)
{
error
(
"Missing 'Anomaly: ID' line in "
+
filename
);
continue
;
}
if
(
opt
is
null
)
{
error
(
"Missing 'Option: ID' line in "
+
filename
);
continue
;
}
string
line
=
file
.
line
;
parseLine
(
line
,
anomaly
,
result
,
file
);
}
else
if
(
key
==
"Anomaly"
)
{
if
(
anomaly
!
is
null
)
addAnomalyType
(
anomaly
);
@
state
=
null
;
@
opt
=
null
;
@
result
=
null
;
@
anomaly
=
AnomalyType
();
anomaly
.
ident
=
value
;
if
(
anomaly
.
ident
.
length
==
0
)
anomaly
.
ident
=
filename
+
"__"
+
index
;
@
opt
=
null
;
++
index
;
}
else
if
(
anomaly
is
null
)
{
error
(
"Missing 'Anomaly: ID' line in "
+
filename
);
}
else
if
(
key
==
"Name"
)
{
anomaly
.
name
=
localize
(
value
);
}
else
if
(
key
==
"Scan Time"
)
{
anomaly
.
scanTime
=
toDouble
(
value
);
}
else
if
(
key
==
"Unique"
)
{
anomaly
.
unique
=
toBool
(
value
);
}
else
if
(
key
==
"Model"
)
{
if
(
state
!
is
null
)
state
.
modelName
=
value
;
else
anomaly
.
modelName
=
value
;
}
else
if
(
key
==
"Material"
)
{
if
(
state
!
is
null
)
state
.
matName
=
value
;
else
anomaly
.
matName
=
value
;
}
else
if
(
key
==
"Description"
)
{
if
(
anomaly
.
desc
.
length
==
0
)
anomaly
.
desc
=
localize
(
value
);
else
if
(
opt
!
is
null
)
opt
.
desc
=
localize
(
value
);
else
error
(
"Duplicate Description for "
+
anomaly
.
ident
+
". Missing Option line?"
);
}
else
if
(
key
==
"Blurb"
)
{
if
(
opt
!
is
null
)
opt
.
blurb
=
localize
(
value
);
}
else
if
(
key
==
"Narrative"
)
{
if
(
state
!
is
null
)
state
.
narrative
=
localize
(
value
);
else
anomaly
.
narrative
=
localize
(
value
);
}
else
if
(
key
==
"Frequency"
)
{
if
(
state
!
is
null
)
state
.
frequency
=
toDouble
(
value
);
else
anomaly
.
frequency
=
toDouble
(
value
);
}
else
if
(
key
==
"Icon"
)
{
if
(
opt
!
is
null
)
opt
.
icon
=
getSprite
(
value
);
else
file
.
error
(
"Icon outside option block."
);
}
else
if
(
key
==
"Option"
)
{
@
state
=
null
;
@
result
=
null
;
@
opt
=
AnomalyOption
();
opt
.
id
=
anomaly
.
options
.
length
;
opt
.
ident
=
value
;
if
(
opt
.
ident
.
length
==
0
)
opt
.
ident
=
anomaly
.
ident
+
"__opt__"
+
anomaly
.
options
.
length
;
anomaly
.
options
.
insertLast
(
opt
);
}
else
if
(
key
==
"Safe"
)
{
if
(
opt
!
is
null
)
opt
.
isSafe
=
toBool
(
value
);
}
else
if
(
key
==
"State"
)
{
@
opt
=
null
;
@
result
=
null
;
@
state
=
AnomalyState
();
state
.
id
=
anomaly
.
states
.
length
;
state
.
ident
=
value
;
state
.
modelName
=
anomaly
.
modelName
;
state
.
matName
=
anomaly
.
matName
;
if
(
state
.
ident
.
length
==
0
)
state
.
ident
=
anomaly
.
ident
+
"__state__"
+
anomaly
.
states
.
length
;
anomaly
.
states
.
insertLast
(
state
);
}
else
if
(
key
==
"Result"
)
{
if
(
opt
is
null
)
{
file
.
error
(
"Result outside option block."
);
continue
;
}
@
state
=
null
;
@
result
=
AnomalyResult
();
if
(
value
.
length
==
0
)
result
.
chance
=
1.0
;
else
result
.
chance
=
toDouble
(
value
);
opt
.
resultTotal
+=
result
.
chance
;
opt
.
results
.
insertLast
(
result
);
}
else
if
(
key
==
"Chance"
)
{
if
(
opt
is
null
)
{
file
.
error
(
"Chance outside option block."
);
continue
;
}
double
chance
=
0.0
;
if
(
value
.
findFirst
(
"%"
)
==
-
1
)
chance
=
toDouble
(
value
);
else
chance
=
toDouble
(
value
)
/
100.0
;
opt
.
chance
=
chance
;
}
else
if
(
key
==
"Choice"
)
{
if
(
state
is
null
)
{
file
.
error
(
"Choice outside state block."
);
continue
;
}
int
pos
=
value
.
findFirst
(
"="
);
if
(
pos
==
-
1
)
{
state
.
def_options
.
insertLast
(
value
);
state
.
option_chances
.
insertLast
(
1.0
);
}
else
{
state
.
def_options
.
insertLast
(
value
.
substr
(
0
,
pos
).
trimmed
());
state
.
option_chances
.
insertLast
(
toDouble
(
value
.
substr
(
pos
+
1
))
/
100.0
);
}
}
else
if
(
file
.
key
==
"Target"
)
{
if
(
opt
is
null
)
{
file
.
error
(
"Target outside option block."
);
continue
;
}
parseTarget
(
opt
.
targets
,
file
.
value
);
}
else
{
string
line
=
file
.
line
;
parseLine
(
line
,
anomaly
,
result
,
file
);
}
}
if
(
anomaly
!
is
null
)
addAnomalyType
(
anomaly
);
}
void
preInit
()
{
//Load anomaly types
FileList
list
(
"data/anomalies"
,
"*.txt"
,
true
);
for
(
uint
i
=
0
,
cnt
=
list
.
length
;
i
<
cnt
;
++
i
)
loadAnomaly
(
list
.
path
[
i
]);
}
void
init
()
{
auto
@
list
=
anomalyTypes
;
for
(
uint
i
=
0
,
cnt
=
list
.
length
;
i
<
cnt
;
++
i
)
{
auto
@
type
=
list
[
i
];
type
.
stateTotal
=
0
;
for
(
uint
o
=
0
,
ocnt
=
type
.
options
.
length
;
o
<
ocnt
;
++
o
)
{
auto
@
opt
=
type
.
options
[
o
];
for
(
uint
n
=
0
,
ncnt
=
opt
.
hooks
.
length
;
n
<
ncnt
;
++
n
)
{
if
(!
cast
<
Hook
>(
opt
.
hooks
[
n
]).
instantiate
())
error
(
"Could not instantiate hook: "
+
addrstr
(
opt
.
hooks
[
n
])+
" in "
+
type
.
ident
);
cast
<
Hook
>(
opt
.
hooks
[
n
]).
initTargets
(
opt
.
targets
);
opt
.
hooks
[
n
].
init
(
type
);
}
for
(
uint
n
=
0
,
ncnt
=
opt
.
results
.
length
;
n
<
ncnt
;
++
n
)
{
auto
@
res
=
opt
.
results
[
n
];
for
(
uint
j
=
0
,
jcnt
=
res
.
hooks
.
length
;
j
<
jcnt
;
++
j
)
{
if
(!
cast
<
Hook
>(
res
.
hooks
[
j
]).
instantiate
())
error
(
"Could not instantiate hook: "
+
addrstr
(
res
.
hooks
[
j
])+
" in "
+
type
.
ident
);
cast
<
Hook
>(
res
.
hooks
[
j
]).
initTargets
(
opt
.
targets
);
res
.
hooks
[
j
].
init
(
type
);
}
}
}
for
(
uint
o
=
0
,
ocnt
=
type
.
states
.
length
;
o
<
ocnt
;
++
o
)
{
auto
@
state
=
type
.
states
[
o
];
type
.
stateTotal
+=
state
.
frequency
;
for
(
uint
n
=
0
,
ncnt
=
state
.
def_options
.
length
;
n
<
ncnt
;
++
n
)
{
auto
@
opt
=
type
.
getOption
(
state
.
def_options
[
n
]);
if
(
opt
!
is
null
)
state
.
options
.
insertLast
(
opt
);
else
error
(
"Could not find option: "
+
state
.
def_options
[
n
]);
}
}
}
}
AnomalyType
@
[]
anomalyTypes
;
dictionary
idents
;
double
totalFrequency
=
0
;
const
AnomalyType
@
getAnomalyType
(
uint
id
)
{
if
(
id
>=
anomalyTypes
.
length
)
return
null
;
return
anomalyTypes
[
id
];
}
const
AnomalyType
@
getAnomalyType
(
const
string
&
ident
)
{
AnomalyType
@
anomaly
;
if
(
idents
.
get
(
ident
,
@
anomaly
))
return
anomaly
;
return
null
;
}
uint
getAnomalyTypeCount
()
{
return
anomalyTypes
.
length
;
}
const
AnomalyType
@
getDistributedAnomalyType
()
{
uint
count
=
anomalyTypes
.
length
;
double
num
=
randomd
(
0
,
totalFrequency
);
for
(
uint
i
=
0
,
cnt
=
anomalyTypes
.
length
;
i
<
cnt
;
++
i
)
{
AnomalyType
@
type
=
anomalyTypes
[
i
];
double
freq
=
type
.
frequency
;
if
(
num
<=
freq
)
{
if
(
type
.
unique
)
{
totalFrequency
-=
type
.
frequency
;
type
.
frequency
=
0
;
}
return
type
;
}
num
-=
freq
;
}
return
anomalyTypes
[
anomalyTypes
.
length
-
1
];
}
void
addAnomalyType
(
AnomalyType
@
type
)
{
type
.
id
=
anomalyTypes
.
length
;
anomalyTypes
.
insertLast
(
type
);
idents
.
set
(
type
.
ident
,
@
type
);
totalFrequency
+=
type
.
frequency
;
}
void
saveIdentifiers
(
SaveFile
&
file
)
{
for
(
uint
i
=
0
,
cnt
=
anomalyTypes
.
length
;
i
<
cnt
;
++
i
)
{
auto
type
=
anomalyTypes
[
i
];
file
.
addIdentifier
(
SI_AnomalyType
,
type
.
id
,
type
.
ident
);
}
}
File Metadata
Details
Attached
Mime Type
text/x-java
Expires
Sun, Nov 15, 12:53 AM (1 d, 18 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
133813
Default Alt Text
anomalies.as (11 KB)
Attached To
Mode
R80 StarRuler2-Source
Attached
Detach File
Event Timeline