305 lines
7.5 KiB
ActionScript
305 lines
7.5 KiB
ActionScript
#priority init 2000
|
|
import abilities;
|
|
import saving;
|
|
import hooks;
|
|
|
|
export ArtifactType;
|
|
export getArtifactType, getArtifactTypeCount;
|
|
export getDistributedArtifactType;
|
|
export getSeedArtifactType;
|
|
|
|
tidy final class ArtifactType {
|
|
uint id = 0;
|
|
string ident;
|
|
string name;
|
|
string description;
|
|
Sprite icon = Sprite(spritesheet::ArtifactIcon, 0);
|
|
Sprite strategicIcon = Sprite(spritesheet::ArtifactIcon, 0);
|
|
double iconSize = 0.02;
|
|
double frequency = 1.0;
|
|
double timeFrequency = 0.0;
|
|
double mass = 300.0;
|
|
bool singleUse = true;
|
|
bool orbit = false;
|
|
bool unique = false;
|
|
bool natural = false;
|
|
bool collapses = true;
|
|
bool canDonate = true;
|
|
bool canOwn = true;
|
|
string spreadVariable;
|
|
double requireContestation = -INFINITY;
|
|
|
|
const Model@ model = model::Artifact;
|
|
const Material@ material = material::VolkurGenericPBR;
|
|
double physicalSize = 5.0;
|
|
|
|
array<string> ability_defs;
|
|
array<const AbilityType@> abilities;
|
|
array<Hook@> ai;
|
|
array<Hook@> secondaryAI;
|
|
double secondaryChance = 0.0;
|
|
array<string> tags;
|
|
|
|
bool hasTag(const string& tag) const {
|
|
for(uint i = 0, cnt = tags.length; i < cnt; ++i) {
|
|
if(tags[i] == tag)
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
};
|
|
|
|
array<ArtifactType@> artifacts;
|
|
dictionary artifactIdents;
|
|
double totalFrequency = 1.0;
|
|
|
|
int getArtifactID(const string& ident) {
|
|
ArtifactType@ type;
|
|
artifactIdents.get(ident, @type);
|
|
if(type !is null)
|
|
return int(type.id);
|
|
return -1;
|
|
}
|
|
|
|
string getArtifactIdent(int id) {
|
|
if(id < 0 || id >= int(artifacts.length))
|
|
return "-";
|
|
return artifacts[id].ident;
|
|
}
|
|
|
|
uint getArtifactTypeCount() {
|
|
return artifacts.length;
|
|
}
|
|
|
|
const ArtifactType@ getArtifactType(uint id) {
|
|
if(id < artifacts.length)
|
|
return artifacts[id];
|
|
else
|
|
return null;
|
|
}
|
|
|
|
const ArtifactType@ getArtifactType(const string& name) {
|
|
ArtifactType@ abl;
|
|
artifactIdents.get(name, @abl);
|
|
return abl;
|
|
}
|
|
|
|
void addArtifactType(ArtifactType@ abl) {
|
|
abl.id = artifacts.length;
|
|
artifacts.insertLast(abl);
|
|
artifactIdents.set(abl.ident, @abl);
|
|
}
|
|
|
|
void saveIdentifiers(SaveFile& file) {
|
|
for(uint i = 0, cnt = artifacts.length; i < cnt; ++i) {
|
|
ArtifactType@ type = artifacts[i];
|
|
file.addIdentifier(SI_Artifact, type.id, type.ident);
|
|
}
|
|
}
|
|
|
|
void loadArtifacts(const string& filename) {
|
|
ReadFile file(filename, false);
|
|
|
|
string key, value;
|
|
ArtifactType@ type;
|
|
|
|
uint index = 0;
|
|
while(file++) {
|
|
key = file.key;
|
|
value = file.value;
|
|
|
|
if(key.equals_nocase("Artifact")) {
|
|
if(type !is null)
|
|
addArtifactType(type);
|
|
@type = ArtifactType();
|
|
type.ident = value;
|
|
}
|
|
else if(type is null) {
|
|
file.error("Missing Artifact ID line");
|
|
}
|
|
else if(key.equals_nocase("Name")) {
|
|
type.name = localize(value);
|
|
}
|
|
else if(key.equals_nocase("Description")) {
|
|
type.description = localize(value);
|
|
}
|
|
else if(key.equals_nocase("Icon")) {
|
|
type.icon = getSprite(value);
|
|
}
|
|
else if(key.equals_nocase("Tag")) {
|
|
type.tags.insertLast(value);
|
|
}
|
|
else if(key.equals_nocase("Ability")) {
|
|
type.ability_defs.insertLast(value);
|
|
}
|
|
else if(key.equals_nocase("Frequency")) {
|
|
type.frequency = toDouble(value);
|
|
}
|
|
else if(key.equals_nocase("Time Frequency")) {
|
|
type.timeFrequency = toDouble(value);
|
|
}
|
|
else if(key.equals_nocase("Single Use")) {
|
|
type.singleUse = toBool(value);
|
|
}
|
|
else if(key.equals_nocase("Size")) {
|
|
type.physicalSize = toDouble(value);
|
|
}
|
|
else if(key.equals_nocase("Icon Size")) {
|
|
type.iconSize = toDouble(value);
|
|
}
|
|
else if(key.equals_nocase("Strategic Icon")) {
|
|
type.strategicIcon = getSprite(value);
|
|
}
|
|
else if(key.equals_nocase("Model")) {
|
|
@type.model = getModel(value);
|
|
}
|
|
else if(key.equals_nocase("Material")) {
|
|
@type.material = getMaterial(value);
|
|
}
|
|
else if(key.equals_nocase("Orbit")) {
|
|
type.orbit = toBool(value);
|
|
}
|
|
else if(key.equals_nocase("Unique")) {
|
|
type.unique = toBool(value);
|
|
}
|
|
else if(key.equals_nocase("Natural")) {
|
|
type.natural = toBool(value);
|
|
}
|
|
else if(key.equals_nocase("Collapses")) {
|
|
type.collapses = toBool(value);
|
|
}
|
|
else if(key.equals_nocase("Mass")) {
|
|
type.mass = toDouble(value);
|
|
}
|
|
else if(key.equals_nocase("Can Donate")) {
|
|
type.canDonate = toBool(value);
|
|
}
|
|
else if(key.equals_nocase("Can Own")) {
|
|
type.canOwn = toBool(value);
|
|
}
|
|
else if(key.equals_nocase("AI")) {
|
|
auto@ hook = parseHook(value, "ai.artifacts::", instantiate=false, file=file);
|
|
if(hook !is null)
|
|
type.ai.insertLast(hook);
|
|
}
|
|
else if(key.equals_nocase("Secondary AI")) {
|
|
auto@ hook = parseHook(value, "ai.artifacts::", instantiate=false, file=file);
|
|
if(hook !is null)
|
|
type.secondaryAI.insertLast(hook);
|
|
}
|
|
else if(key.equals_nocase("Secondary Chance")) {
|
|
type.secondaryChance = toDouble(value);
|
|
}
|
|
else if(key.equals_nocase("Require Contestation")) {
|
|
type.requireContestation = toDouble(value);
|
|
}
|
|
else if(key.equals_nocase("Spread Variable")) {
|
|
type.spreadVariable = value;
|
|
type.frequency = 0;
|
|
type.canDonate = false;
|
|
type.canOwn = false;
|
|
}
|
|
else {
|
|
file.error("Invalid line");
|
|
}
|
|
}
|
|
|
|
if(type !is null)
|
|
addArtifactType(type);
|
|
}
|
|
|
|
ArtifactType@ getRandomArtifactType() {
|
|
uint count = artifacts.length;
|
|
double num = randomd(0, totalFrequency);
|
|
ArtifactType@ type;
|
|
for(uint i = 0, cnt = artifacts.length; i < cnt; ++i) {
|
|
@type = artifacts[i];
|
|
double freq = type.frequency;
|
|
if(num <= freq)
|
|
break;
|
|
num -= freq;
|
|
}
|
|
if(type is null)
|
|
@type = artifacts[artifacts.length-1];
|
|
return type;
|
|
}
|
|
|
|
const ArtifactType@ getDistributedArtifactType(bool isUse = true) {
|
|
auto@ type = getRandomArtifactType();
|
|
if(type.unique && isUse) {
|
|
totalFrequency -= type.frequency;
|
|
type.frequency = 0;
|
|
}
|
|
return type;
|
|
}
|
|
|
|
const ArtifactType@ getDistributedArtifactType(double contestation, bool isUse = true) {
|
|
uint tries = 0;
|
|
ArtifactType@ type;
|
|
while(tries < 10) {
|
|
@type = getRandomArtifactType();
|
|
if(type.requireContestation <= contestation)
|
|
break;
|
|
tries += 1;
|
|
}
|
|
if(type.unique && isUse) {
|
|
totalFrequency -= type.frequency;
|
|
type.frequency = 0;
|
|
}
|
|
return type;
|
|
}
|
|
|
|
const ArtifactType@ getSeedArtifactType(bool isUse = true) {
|
|
double total = 0.0;
|
|
for(uint i = 0, cnt = artifacts.length; i < cnt; ++i) {
|
|
auto@ type = artifacts[i];
|
|
if(type.frequency <= 0 || !type.singleUse || type.natural)
|
|
continue;
|
|
double freq = type.frequency + type.timeFrequency * (gameTime / 1200.0);
|
|
total += freq;
|
|
}
|
|
double num = randomd(0, total);
|
|
ArtifactType@ type;
|
|
for(uint i = 0, cnt = artifacts.length; i < cnt; ++i) {
|
|
@type = artifacts[i];
|
|
if(type.frequency <= 0 || !type.singleUse || type.natural)
|
|
continue;
|
|
double freq = type.frequency + type.timeFrequency * (gameTime / 1200.0);
|
|
if(num <= freq)
|
|
break;
|
|
num -= freq;
|
|
}
|
|
if(type is null)
|
|
@type = artifacts[artifacts.length-1];
|
|
if(type !is null && type.unique && isUse) {
|
|
totalFrequency -= type.frequency;
|
|
type.frequency = 0;
|
|
}
|
|
return type;
|
|
}
|
|
|
|
void preInit() {
|
|
FileList list("data/artifacts", "*.txt", true);
|
|
for(uint i = 0, cnt = list.length; i < cnt; ++i)
|
|
loadArtifacts(list.path[i]);
|
|
}
|
|
|
|
void init() {
|
|
totalFrequency = 0.0;
|
|
for(uint i = 0, cnt = artifacts.length; i < cnt; ++i) {
|
|
auto@ type = artifacts[i];
|
|
totalFrequency += type.frequency;
|
|
for(uint j = 0, jcnt = type.ability_defs.length; j < jcnt; ++j) {
|
|
auto@ abl = getAbilityType(type.ability_defs[j]);
|
|
if(abl !is null)
|
|
type.abilities.insertLast(abl);
|
|
else
|
|
error("Error: could not find ability "+type.ability_defs[j]+" in artifact "+type.ident);
|
|
}
|
|
for(uint n = 0, ncnt = type.ai.length; n < ncnt; ++n) {
|
|
if(!type.ai[n].instantiate())
|
|
error("Could not instantiate AI hook: "+addrstr(type.ai[n])+" in artifact "+type.ident);
|
|
}
|
|
}
|
|
}
|