294 lines
8.4 KiB
ActionScript
294 lines
8.4 KiB
ActionScript
import buildings;
|
|
from buildings import BuildingHook;
|
|
from bonus_effects import BonusEffect;
|
|
import planet_effects;
|
|
import listed_values;
|
|
import requirement_effects;
|
|
import consume_effects;
|
|
|
|
tidy final class TriggerStartConstruction : BuildingHook {
|
|
Document doc("Triggers another hook when construction of a building starts.");
|
|
Argument hook("Hook", AT_Hook, "bonus_effects::BonusEffect", doc="Hook to run.");
|
|
BonusEffect@ eff;
|
|
|
|
bool instantiate() override {
|
|
@eff = cast<BonusEffect>(parseHook(hook.str, "bonus_effects::", required=false));
|
|
if(eff is null) {
|
|
error("TriggerStartConstruction(): could not find inner hook: "+escape(hook.str));
|
|
return false;
|
|
}
|
|
return BuildingHook::instantiate();
|
|
}
|
|
|
|
#section server
|
|
void startConstruction(Object& obj, SurfaceBuilding@ bld) const {
|
|
if(eff !is null)
|
|
eff.activate(obj, obj.owner);
|
|
}
|
|
#section all
|
|
};
|
|
|
|
tidy final class TriggerCancelConstruction : BuildingHook {
|
|
Document doc("Triggers another hook when construction of a building is cancelled.");
|
|
Argument hook("Hook", AT_Hook, "bonus_effects::BonusEffect", doc="Hook to run.");
|
|
BonusEffect@ eff;
|
|
|
|
bool instantiate() override {
|
|
@eff = cast<BonusEffect>(parseHook(hook.str, "bonus_effects::", required=false));
|
|
if(eff is null) {
|
|
error("TriggerCancelConstruction(): could not find inner hook: "+escape(hook.str));
|
|
return false;
|
|
}
|
|
return BuildingHook::instantiate();
|
|
}
|
|
|
|
#section server
|
|
void cancelConstruction(Object& obj, SurfaceBuilding@ bld) const {
|
|
if(eff !is null)
|
|
eff.activate(obj, obj.owner);
|
|
}
|
|
#section all
|
|
};
|
|
|
|
tidy final class TriggerConstructed : BuildingHook {
|
|
Document doc("Triggers another hook when construction of a building is finished.");
|
|
Argument hook("Hook", AT_Hook, "bonus_effects::BonusEffect", doc="Hook to run.");
|
|
BonusEffect@ eff;
|
|
|
|
bool instantiate() override {
|
|
@eff = cast<BonusEffect>(parseHook(hook.str, "bonus_effects::", required=false));
|
|
if(eff is null) {
|
|
error("TriggerConstructed(): could not find inner hook: "+escape(hook.str));
|
|
return false;
|
|
}
|
|
return BuildingHook::instantiate();
|
|
}
|
|
|
|
#section server
|
|
void complete(Object& obj, SurfaceBuilding@ bld) const {
|
|
if(eff !is null)
|
|
eff.activate(obj, obj.owner);
|
|
}
|
|
#section all
|
|
};
|
|
|
|
class ConstructibleIfAttributeGTE : BuildingHook {
|
|
Document doc("Only constructible if an empire attribute is greater than or equal to the specified value.");
|
|
Argument attribute("Attribute", AT_EmpAttribute, doc="Attribute to test, can be set to any arbitrary name to be created as a new attribute with starting value 0.");
|
|
Argument value("Value", AT_Decimal, doc="Value to test against.");
|
|
|
|
bool canBuildOn(Object& obj, bool ignoreState = false) const override {
|
|
Empire@ emp = obj.owner;
|
|
if(emp is null)
|
|
return false;
|
|
if(emp.getAttribute(attribute.integer) < value.decimal)
|
|
return false;
|
|
return true;
|
|
}
|
|
};
|
|
|
|
class ConstructibleIfAttribute : BuildingHook {
|
|
Document doc("Only constructible if an empire attribute is equal to the specified value.");
|
|
Argument attribute("Attribute", AT_EmpAttribute, doc="Attribute to test, can be set to any arbitrary name to be created as a new attribute with starting value 0.");
|
|
Argument value("Value", AT_Decimal, doc="Value to test against.");
|
|
|
|
bool canBuildOn(Object& obj, bool ignoreState = false) const override {
|
|
Empire@ emp = obj.owner;
|
|
if(emp is null)
|
|
return false;
|
|
if(abs(emp.getAttribute(attribute.integer) - value.decimal) >= 0.001)
|
|
return false;
|
|
return true;
|
|
}
|
|
};
|
|
|
|
class CannotBuildManually : BuildingHook {
|
|
Document doc("Indicates that the building cannot be manually constructed.");
|
|
|
|
bool canBuildOn(Object& obj, bool ignoreState = false) const override {
|
|
return false;
|
|
}
|
|
};
|
|
|
|
class CannotRemove : BuildingHook {
|
|
Document doc("Indicates that the building cannot be removed by the player.");
|
|
|
|
bool canRemove(Object& obj) const override {
|
|
return false;
|
|
}
|
|
};
|
|
|
|
class ModBuildSpeedAttribute : BuildingHook {
|
|
Document doc("Multiply the build speed of this building by an attribute.");
|
|
Argument attribute(AT_EmpAttribute, doc="Attribute to modify build speed by.");
|
|
|
|
void modBuildTime(Object& obj, double& time) const {
|
|
time /= obj.owner.getAttribute(attribute.integer);
|
|
}
|
|
};
|
|
|
|
tidy final class ActiveWhenCargoConsumed : GenericEffect {
|
|
Document doc("This hook applies while a particular amount of cargo can be consumed every interval.");
|
|
Argument cargo_type(AT_Cargo, doc="Type of cargo to consume.");
|
|
Argument amount(AT_Decimal, doc="Amount of cargo to consume per interval.");
|
|
Argument interval(AT_Decimal, doc="Interval to consume cargo at.");
|
|
Argument hookID(AT_Hook, "planet_effects::GenericEffect");
|
|
Argument labor_use_linked(AT_Boolean, "False", doc="Don't require the cargo consumption when no labor is currently being used.");
|
|
Argument inactive_status(AT_Status, EMPTY_DEFAULT, doc="Status to add when this building is inactive.");
|
|
Argument inactive_status_count(AT_Integer, "1", doc="How many statuses to add when this building is inactive.");
|
|
GenericEffect@ hook;
|
|
|
|
bool instantiate() override {
|
|
if(!withHook(hookID.str))
|
|
return false;
|
|
return GenericEffect::instantiate();
|
|
}
|
|
|
|
bool withHook(const string& str) {
|
|
@hook = cast<GenericEffect>(parseHook(str, "planet_effects::"));
|
|
if(hook is null) {
|
|
error("If<>(): could not find inner hook: "+escape(str));
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool condition(Object& obj) const {
|
|
return false;
|
|
}
|
|
|
|
#section server
|
|
void complete(Object& obj, SurfaceBuilding@ bld) const {
|
|
auto@ data = bld.data[hookIndex];
|
|
ConsumeData info;
|
|
info.enabled = false;
|
|
data.store(@info);
|
|
|
|
bld.disabled = !info.enabled;
|
|
bld.delta = true;
|
|
|
|
if(info.enabled) {
|
|
hook.enable(obj, info.data);
|
|
}
|
|
else if(inactive_status.integer != -1) {
|
|
for(int n = 0; n < inactive_status_count.integer; ++n)
|
|
obj.addStatus(inactive_status.integer);
|
|
}
|
|
}
|
|
|
|
void disable(Object& obj, any@ data) const override {
|
|
ConsumeData@ info;
|
|
data.retrieve(@info);
|
|
|
|
if(info.enabled)
|
|
hook.disable(obj, info.data);
|
|
}
|
|
|
|
void tick(Object& obj, SurfaceBuilding@ bld, double time) const {
|
|
auto@ data = bld.data[hookIndex];
|
|
ConsumeData@ info;
|
|
data.retrieve(@info);
|
|
|
|
bool cond = info.enabled;
|
|
info.timer -= time;
|
|
if(info.timer <= 0) {
|
|
if(!obj.hasCargo) {
|
|
cond = false;
|
|
info.timer += interval.decimal;
|
|
}
|
|
else if(labor_use_linked.boolean && !obj.isUsingLabor) {
|
|
cond = obj.getCargoStored(cargo_type.integer) >= amount.decimal;
|
|
}
|
|
else {
|
|
double consAmt = obj.consumeCargo(cargo_type.integer, amount.decimal, partial=false);
|
|
if(consAmt < amount.decimal - 0.001) {
|
|
cond = false;
|
|
info.timer += interval.decimal;
|
|
}
|
|
else {
|
|
cond = true;
|
|
info.timer += interval.decimal;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(cond != info.enabled) {
|
|
if(info.enabled)
|
|
hook.disable(obj, info.data);
|
|
else
|
|
hook.enable(obj, info.data);
|
|
info.enabled = cond;
|
|
|
|
bld.disabled = !cond;
|
|
bld.delta = true;
|
|
|
|
if(inactive_status.integer != -1) {
|
|
for(int n = 0; n < inactive_status_count.integer; ++n) {
|
|
if(bld.disabled)
|
|
obj.addStatus(inactive_status.integer);
|
|
else
|
|
obj.removeStatusInstanceOfType(inactive_status.integer);
|
|
}
|
|
}
|
|
}
|
|
if(info.enabled)
|
|
hook.tick(obj, info.data, time);
|
|
}
|
|
|
|
void ownerChange(Object& obj, any@ data, Empire@ prevOwner, Empire@ newOwner) const {
|
|
ConsumeData@ info;
|
|
data.retrieve(@info);
|
|
|
|
if(info.enabled)
|
|
hook.ownerChange(obj, info.data, prevOwner, newOwner);
|
|
}
|
|
|
|
void regionChange(Object& obj, any@ data, Region@ fromRegion, Region@ toRegion) const {
|
|
ConsumeData@ info;
|
|
data.retrieve(@info);
|
|
|
|
if(info.enabled)
|
|
hook.regionChange(obj, info.data, fromRegion, toRegion);
|
|
}
|
|
|
|
void save(any@ data, SaveFile& file) const {
|
|
ConsumeData@ info;
|
|
data.retrieve(@info);
|
|
|
|
if(info is null) {
|
|
bool enabled = false;
|
|
file << enabled;
|
|
double timer = 0.0;
|
|
file << timer;
|
|
}
|
|
else {
|
|
file << info.enabled;
|
|
file << info.timer;
|
|
if(info.enabled)
|
|
hook.save(info.data, file);
|
|
}
|
|
}
|
|
|
|
void load(any@ data, SaveFile& file) const {
|
|
ConsumeData info;
|
|
data.store(@info);
|
|
|
|
file >> info.enabled;
|
|
file >> info.timer;
|
|
if(info.enabled)
|
|
hook.load(info.data, file);
|
|
}
|
|
#section all
|
|
};
|
|
|
|
class RequireStatusToProgress : Requirement {
|
|
Document doc("Require that a particular status is present for this building to progress construction.");
|
|
Argument status(AT_Status, doc="Status type to check for.");
|
|
|
|
bool canProgress(Object& obj) const override {
|
|
if(!obj.hasStatuses)
|
|
return false;
|
|
return obj.getStatusStackCountAny(status.integer) > 0;
|
|
}
|
|
};
|