import generic_hooks; tidy class GenericRepeatHook : EmpireEffect { EmpireEffect@ empHook; GenericEffect@ hook; uint getRepeats(Empire& emp, any@ data) const { return 0; } uint getRepeats(Object& obj, any@ data) const { return getRepeats(obj.owner, data); } bool withHook(const string& str) { @hook = cast(parseHook(str, "planet_effects::", required = false)); @empHook = cast(parseHook(str, "empire_effects::", required = false)); if(hook is null && empHook is null) { error("Repeat<>(): could not find inner hook: "+escape(str)); return false; } return true; } void enable(Empire& emp, any@ data) const override { array datlist; data.store(@datlist); } void tick(Empire& emp, any@ data, double time) const override { array@ datlist; data.retrieve(@datlist); if(datlist is null) return; uint oldCnt = datlist.length; uint newCnt = getRepeats(emp, data); for(uint i = newCnt; i < oldCnt; ++i) empHook.disable(emp, datlist[i]); datlist.length = newCnt; for(uint i = oldCnt; i < newCnt; ++i) empHook.enable(emp, datlist[i]); for(uint i = 0; i < newCnt; ++i) empHook.tick(emp, datlist[i], time); } void disable(Empire& emp, any@ data) const override { array@ datlist; data.retrieve(@datlist); if(datlist is null) return; for(uint i = 0, cnt = datlist.length; i < cnt; ++i) empHook.disable(emp, datlist[i]); datlist.length = 0; @datlist = null; data.store(@datlist); } void enable(Object& obj, any@ data) const override { if(hook is null) { enable(obj.owner, data); return; } array datlist; data.store(@datlist); } void tick(Object& obj, any@ data, double time) const override { if(hook is null) { tick(obj.owner, data, time); return; } array@ datlist; data.retrieve(@datlist); if(datlist is null) return; uint oldCnt = datlist.length; uint newCnt = getRepeats(obj, data); for(uint i = newCnt; i < oldCnt; ++i) hook.disable(obj, datlist[i]); datlist.length = newCnt; for(uint i = oldCnt; i < newCnt; ++i) hook.enable(obj, datlist[i]); for(uint i = 0; i < newCnt; ++i) hook.tick(obj, datlist[i], time); } void disable(Object& obj, any@ data) const override { if(hook is null) { disable(obj.owner, data); return; } array@ datlist; data.retrieve(@datlist); if(datlist is null) return; for(uint i = 0, cnt = datlist.length; i < cnt; ++i) hook.disable(obj, datlist[i]); datlist.length = 0; @datlist = null; data.store(@datlist); } void ownerChange(Object& obj, any@ data, Empire@ prevOwner, Empire@ newOwner) const override { if(hook is null) { disable(prevOwner, data); enable(newOwner, data); return; } array@ datlist; data.retrieve(@datlist); if(datlist is null) return; for(uint i = 0, cnt = datlist.length; i < cnt; ++i) hook.ownerChange(obj, datlist[i], prevOwner, newOwner); } void regionChange(Object& obj, any@ data, Region@ fromRegion, Region@ toRegion) const override { array@ datlist; data.retrieve(@datlist); if(datlist is null) return; for(uint i = 0, cnt = datlist.length; i < cnt; ++i) hook.regionChange(obj, datlist[i], fromRegion, toRegion); } void save(any@ data, SaveFile& file) const override { array@ datlist; data.retrieve(@datlist); uint cnt = 0; if(datlist is null) { file << cnt; return; } cnt = datlist.length; file << cnt; for(uint i = 0; i < cnt; ++i) { if(hook !is null) hook.save(datlist[i], file); else if(empHook !is null) empHook.save(datlist[i], file); } } void load(any@ data, SaveFile& file) const override { array datlist; uint cnt = 0; file >> cnt; datlist.length = cnt; for(uint i = 0; i < cnt; ++i) { if(hook !is null) hook.load(datlist[i], file); else if(empHook !is null) empHook.load(datlist[i], file); } data.store(@datlist); } }; tidy final class Repeat : GenericRepeatHook { Document doc("Repeat an inner hook multiple times."); Argument amount(AT_Integer, doc="Amount of times to repeat."); Argument hookID("Hook", AT_Hook, "planet_effects::GenericEffect"); Argument per_import(AT_Integer, "0", doc="Additional repeats to add for every imported resource."); bool instantiate() override { if(!withHook(hookID.str)) return false; return GenericEffect::instantiate(); } #section server uint getRepeats(Object& obj, any@ data) const override { uint newCnt = arguments[0].integer; uint perImport = arguments[2].integer; if(perImport != 0) newCnt += obj.usableResourceCount * perImport; return newCnt; } uint getRepeats(Empire& emp, any@ data) const override { uint newCnt = arguments[0].integer; return newCnt; } #section all }; tidy final class RepeatEmpireAttribute : GenericRepeatHook { Document doc("Repeat a hook an amount of times as stored in an empire attribute of the owner."); Argument attribute(AT_EmpAttribute, doc="Attribute to take repeats from. Naming a new attribute will create it with a default value of 0."); Argument hookID("Hook", AT_Hook, "planet_effects::GenericEffect"); bool instantiate() override { if(!withHook(hookID.str)) return false; return GenericEffect::instantiate(); } #section server uint getRepeats(Empire& emp, any@ data) const override { return uint(emp.getAttribute(attribute.integer)); } #section all }; tidy final class RepeatPlanetLevel : GenericRepeatHook { Document doc("Repeat a hook for every planet level."); Argument hookID("Hook", AT_Hook, "planet_effects::GenericEffect"); Argument base(AT_Decimal, "0", doc="Base amount of repeats to add regardless of level."); Argument per_level_bonus(AT_Decimal, "1", doc="Amount of repeats to add per planet level."); bool instantiate() override { @hook = cast(parseHook(hookID.str, "planet_effects::")); if(hook is null) { error("Repeat(): could not find inner hook: "+escape(hookID.str)); return false; } return GenericEffect::instantiate(); } #section server uint getRepeats(Object& obj, any@ data) const override { double cnt = base.decimal; if(per_level_bonus.decimal != 0 && obj.isPlanet) cnt += per_level_bonus.decimal * obj.level; return cnt; } #section all }; tidy final class RepeatExtended : GenericRepeatHook { Document doc("Repeat a hook an amount of times as stored in an empire attribute of the owner."); Argument hookID("Hook", AT_Hook, "planet_effects::GenericEffect"); Argument base_attribute(AT_EmpAttribute, EMPTY_DEFAULT, doc="Attribute to add to new repeats."); Argument multiply_attribute(AT_EmpAttribute, EMPTY_DEFAULT, doc="Attribute to multiply the whole repeat amount by."); Argument base(AT_Decimal, "0", doc="Base amount of repeats to add."); Argument multiplier(AT_Decimal, "1", doc="Multiplication to empire attribute before taking the repeats."); Argument per_level_bonus(AT_Decimal, "0", doc="If this is applied to a planet, add this many repeats per planet level."); Argument per_gametime_bonus(AT_Decimal, "0", doc="Adds more repeats for every minute of gametime that has passed since the beginning of the game."); bool instantiate() override { if(!withHook(hookID.str)) return false; return GenericEffect::instantiate(); } #section server uint getRepeats(Object& obj, any@ data) const override { double cnt = base.decimal; if(base_attribute.integer != -1) cnt += obj.owner.getAttribute(base_attribute.integer); if(per_level_bonus.decimal != 0 && obj.isPlanet) cnt += per_level_bonus.decimal * obj.level; cnt += per_gametime_bonus.decimal * (gameTime / 60.0); cnt *= multiplier.decimal; if(multiply_attribute.integer != -1) cnt *= obj.owner.getAttribute(multiply_attribute.integer); return cnt; } uint getRepeats(Empire& emp, any@ data) const override { double cnt = base.decimal; if(base_attribute.integer != -1) cnt += emp.getAttribute(base_attribute.integer); cnt += per_gametime_bonus.decimal * (gameTime / 60.0); cnt *= multiplier.decimal; if(multiply_attribute.integer != -1) cnt *= emp.getAttribute(multiply_attribute.integer); return cnt; } #section all }; tidy final class RepeatEmpirePopulation : GenericRepeatHook { Document doc("Repeat a hook based on the difference between an attribute value and the total empire population."); Argument interval(AT_Decimal, doc="Repeat the hook once for every population the empire has."); Argument hookID("Hook", AT_Hook, "planet_effects::GenericEffect"); bool instantiate() override { if(!withHook(hookID.str)) return false; return GenericEffect::instantiate(); } #section server uint getRepeats(Empire& emp, any@ data) const override { return floor(double(emp.TotalPopulation) / interval.decimal); } #section all }; tidy final class RepeatPopulationCoverage : GenericRepeatHook { Document doc("Repeat a hook based on the difference between an attribute value and the total empire population."); Argument attribute(AT_EmpAttribute, doc="Attribute to require covering of population."); Argument interval(AT_Decimal, doc="Repeat the hook once for every population that is not covered by the attribute."); Argument hookID("Hook", AT_Hook, "planet_effects::GenericEffect"); bool instantiate() override { if(!withHook(hookID.str)) return false; return GenericEffect::instantiate(); } #section server uint getRepeats(Empire& emp, any@ data) const override { double diff = emp.TotalPopulation - emp.getAttribute(attribute.integer); if(diff <= 0) return 0; return ceil(diff / interval.decimal); } #section all }; tidy final class RepeatPressure : GenericRepeatHook { Document doc("Repeat a hook based on how much of a particular pressure is available locally."); Argument type(AT_TileResource, doc="Resource of pressure to check."); Argument hookID("Hook", AT_Hook, "planet_effects::GenericEffect"); Argument multiplier(AT_Decimal, "1", doc="How many repeats per pressure."); bool instantiate() override { if(!withHook(hookID.str)) return false; return GenericEffect::instantiate(); } #section server uint getRepeats(Object& obj, any@ data) const override { return round(double(obj.resourcePressure[type.integer]) * multiplier.decimal); } #section all }; tidy final class RepeatFoodCount : GenericRepeatHook { Document doc("Repeat a hook for every food resource present."); Argument hookID("Hook", AT_Hook, "planet_effects::GenericEffect"); bool instantiate() override { if(!withHook(hookID.str)) return false; return GenericEffect::instantiate(); } #section server uint getRepeats(Object& obj, any@ data) const override { return obj.getFoodCount(); } #section all }; tidy final class RepeatEnergyStored : GenericRepeatHook { Document doc("Repeat a hook depending on how much energy is stored."); Argument step(AT_Decimal, doc="How much energy should be stored per repeat."); Argument hookID("Hook", AT_Hook, "planet_effects::GenericEffect"); bool instantiate() override { if(!withHook(hookID.str)) return false; return GenericEffect::instantiate(); } #section server uint getRepeats(Empire& emp, any@ data) const { return floor(emp.EnergyStored / step.decimal); } #section all }; tidy final class RepeatEmpireContacts : GenericRepeatHook { Document doc("Repeat a hook with the amount of empires that have been contacted."); Argument hookID("Hook", AT_Hook, "planet_effects::GenericEffect"); Argument maximum(AT_Integer, "-1", doc="Maximum contact count."); bool instantiate() override { if(!withHook(hookID.str)) return false; return GenericEffect::instantiate(); } #section server uint getRepeats(Empire& emp, any@ data) const { uint contacts = 0; for(uint i = 0, cnt = getEmpireCount(); i < cnt; ++i) { Empire@ other = getEmpire(i); if(emp is other || !other.major) continue; if(emp.ContactMask & other.mask != 0) contacts += 1; } if(contacts > uint(maximum.integer)) contacts = uint(maximum.integer); return contacts; } #section all };