import empire_ai.weasel.WeaselAI; import empire_ai.weasel.Budget; import empire_ai.weasel.Systems; from ai.orbitals import AIOrbitals, OrbitalAIHook, OrbitalUse; import ai.consider; import orbitals; import saving; final class OrbitalAI { Object@ obj; const OrbitalModule@ type; double prevTick = 0; Object@ around; void init(AI& ai, Orbitals& orbitals) { if(obj.isOrbital) @type = getOrbitalModule(cast(obj).coreModule); } void save(Orbitals& orbitals, SaveFile& file) { file << obj; } void load(Orbitals& orbitals, SaveFile& file) { file >> obj; } void remove(AI& ai, Orbitals& orbitals) { } void tick(AI& ai, Orbitals& orbitals, double time) { //Deal with losing planet ownership if(obj is null || !obj.valid || obj.owner !is ai.empire) { orbitals.remove(this); return; } //Record what we're orbiting around if(around !is null) { if(!obj.isOrbitingAround(around)) @around = obj.getOrbitingAround(); } else { if(obj.hasOrbitCenter) @around = obj.getOrbitingAround(); } } }; class Orbitals : AIComponent, AIOrbitals { Budget@ budget; Systems@ systems; array orbitals; uint orbIdx = 0; void create() { @budget = cast(ai.budget); @systems = cast(ai.systems); //Register specialized orbital types for(uint i = 0, cnt = getOrbitalModuleCount(); i < cnt; ++i) { auto@ type = getOrbitalModule(i); for(uint n = 0, ncnt = type.ai.length; n < ncnt; ++n) { auto@ hook = cast(type.ai[n]); if(hook !is null) hook.register(this, type); } } } Empire@ get_empire() { return ai.empire; } Considerer@ get_consider() { return cast(ai.consider); } OrbitalAI@ getInSystem(const OrbitalModule@ module, Region@ reg) { if(module is null) return null; for(uint i = 0, cnt = orbitals.length; i < cnt; ++i) { if(orbitals[i].type is module) { if(orbitals[i].obj.region is reg) return orbitals[i]; } } return null; } bool haveInSystem(const OrbitalModule@ module, Region@ reg) { if(module is null) return false; for(uint i = 0, cnt = orbitals.length; i < cnt; ++i) { if(orbitals[i].type is module) { if(orbitals[i].obj.region is reg) return true; } } return false; } bool haveAround(const OrbitalModule@ module, Object@ around) { if(module is null) return false; for(uint i = 0, cnt = orbitals.length; i < cnt; ++i) { if(orbitals[i].type is module) { if(orbitals[i].around is around) return true; } } return false; } void registerUse(OrbitalUse use, const OrbitalModule& type) { switch(use) { case OU_Shipyard: @ai.defs.Shipyard = type; break; } } void save(SaveFile& file) { uint cnt = orbitals.length; file << cnt; for(uint i = 0; i < cnt; ++i) { auto@ data = orbitals[i]; saveAI(file, data); data.save(this, file); } } void load(SaveFile& file) { uint cnt = 0; file >> cnt; for(uint i = 0; i < cnt; ++i) { auto@ data = loadAI(file); if(data !is null) data.load(this, file); else OrbitalAI().load(this, file); } } OrbitalAI@ loadAI(SaveFile& file) { Object@ obj; file >> obj; if(obj is null) return null; OrbitalAI@ data = getAI(obj); if(data is null) { @data = OrbitalAI(); @data.obj = obj; data.prevTick = gameTime; orbitals.insertLast(data); } return data; } void saveAI(SaveFile& file, OrbitalAI@ ai) { Object@ obj; if(ai !is null) @obj = ai.obj; file << obj; } void start() { checkForOrbitals(); } void checkForOrbitals() { auto@ data = ai.empire.getOrbitals(); Object@ obj; while(receive(data, obj)) { if(obj !is null) register(obj); } } void tick(double time) { double curTime = gameTime; if(orbitals.length != 0) { orbIdx = (orbIdx+1) % orbitals.length; auto@ data = orbitals[orbIdx]; data.tick(ai, this, curTime - data.prevTick); data.prevTick = curTime; } } uint prevCount = 0; double checkTimer = 0; void focusTick(double time) override { //Check for any newly obtained planets uint curCount = ai.empire.orbitalCount; checkTimer += time; if(curCount != prevCount || checkTimer > 60.0) { checkForOrbitals(); prevCount = curCount; checkTimer = 0; } } OrbitalAI@ getAI(Object& obj) { for(uint i = 0, cnt = orbitals.length; i < cnt; ++i) { if(orbitals[i].obj is obj) return orbitals[i]; } return null; } OrbitalAI@ register(Object& obj) { OrbitalAI@ data = getAI(obj); if(data is null) { @data = OrbitalAI(); @data.obj = obj; data.prevTick = gameTime; orbitals.insertLast(data); data.init(ai, this); } return data; } void remove(OrbitalAI@ data) { data.remove(ai, this); orbitals.remove(data); } }; AIComponent@ createOrbitals() { return Orbitals(); }