diff --git a/rts/Sim/Projectiles/ExpGenSpawner.cpp b/rts/Sim/Projectiles/ExpGenSpawner.cpp index ee2683ddc6e..712afe02caf 100644 --- a/rts/Sim/Projectiles/ExpGenSpawner.cpp +++ b/rts/Sim/Projectiles/ExpGenSpawner.cpp @@ -17,11 +17,7 @@ CR_REG_METADATA(CExpGenSpawner, )) -CExpGenSpawner::CExpGenSpawner() : - CProjectile(), - delay(1), - damage(0.0f), - explosionGenerator(nullptr) +CExpGenSpawner::CExpGenSpawner() : CProjectile() { checkCol = false; deleteMe = false; @@ -29,26 +25,26 @@ CExpGenSpawner::CExpGenSpawner() : void CExpGenSpawner::Serialize(creg::ISerializer* s) { int generatorID; + if (s->IsWriting()) generatorID = explosionGenerator->GetGeneratorID(); s->SerializeInt(&generatorID, sizeof(generatorID)); - if (!s->IsWriting()) - explosionGenerator = explGenHandler.GetGenerator(generatorID); -} + if (s->IsWriting()) + return; -void CExpGenSpawner::Update() -{ - if ((deleteMe |= ((delay--) <= 0))) { - explosionGenerator->Explosion(pos, dir, damage, 0.0f, 0.0f, owner(), nullptr); - } + // NOTE: + // projectiles are serialized, but ExplosionGeneratorHandler itself is not + // as such generator-id can be invalid when this spawner gets deserialized + // (if additional generators were loaded at runtime before game was saved) + explosionGenerator = explGenHandler.GetGenerator(generatorID); } - -int CExpGenSpawner::GetProjectilesCount() const +void CExpGenSpawner::Update() { - return 0; + if ((deleteMe |= ((delay--) <= 0))) + explosionGenerator->Explosion(pos, dir, damage, 0.0f, 0.0f, owner(), nullptr); } @@ -59,6 +55,7 @@ bool CExpGenSpawner::GetMemberInfo(SExpGenSpawnableMemberInfo& memberInfo) CHECK_MEMBER_INFO_INT (CExpGenSpawner, delay ) CHECK_MEMBER_INFO_FLOAT(CExpGenSpawner, damage) + // TODO: much nicer to load cegID directly via LoadGeneratorID callback CHECK_MEMBER_INFO_PTR (CExpGenSpawner, explosionGenerator, explGenHandler.LoadGenerator) return false; diff --git a/rts/Sim/Projectiles/ExpGenSpawner.h b/rts/Sim/Projectiles/ExpGenSpawner.h index 22d77174b40..fb7e2c4a1b3 100644 --- a/rts/Sim/Projectiles/ExpGenSpawner.h +++ b/rts/Sim/Projectiles/ExpGenSpawner.h @@ -18,15 +18,15 @@ class CExpGenSpawner : public CProjectile virtual void Update() override; - virtual int GetProjectilesCount() const override; + virtual int GetProjectilesCount() const override { return 0; } static bool GetMemberInfo(SExpGenSpawnableMemberInfo& memberInfo); private: - int delay; - float damage; + int delay = 1; + float damage = 0.0f; - IExplosionGenerator* explosionGenerator; + IExplosionGenerator* explosionGenerator = nullptr; }; #endif // EXP_GEN_SPAWNER_H diff --git a/rts/Sim/Projectiles/ExplosionGenerator.cpp b/rts/Sim/Projectiles/ExplosionGenerator.cpp index a27c3fb2262..42d7b2b308c 100644 --- a/rts/Sim/Projectiles/ExplosionGenerator.cpp +++ b/rts/Sim/Projectiles/ExplosionGenerator.cpp @@ -154,11 +154,15 @@ std::string ClassAliasList::FindAlias(const std::string& className) const void CExplosionGeneratorHandler::Init() { egMemPool.clear(); - egMemPool.reserve(32); + egMemPool.reserve(512); + + explosionGenerators.reserve(512); + explosionGenerators.push_back(egMemPool.alloc()); // id=0 (shared standard EG) + explosionGenerators.push_back(egMemPool.alloc< IExplosionGenerator>()); // id=1 (dummy fallback EG) + + explosionGenerators[EXPGEN_ID_STANDARD]->SetGeneratorID(EXPGEN_ID_STANDARD); + explosionGenerators[EXPGEN_ID_FALLBACK]->SetGeneratorID(EXPGEN_ID_FALLBACK); - explosionGenerators.reserve(32); - explosionGenerators.push_back(egMemPool.alloc()); // id=0 - explosionGenerators[0]->SetGeneratorID(EXPGEN_ID_STANDARD); exploParser = nullptr; aliasParser = nullptr; @@ -331,8 +335,9 @@ IExplosionGenerator* CExplosionGeneratorHandler::GetGenerator(unsigned int expGe { if (expGenID == EXPGEN_ID_INVALID) return nullptr; + // can happen after save/load for spawners if (expGenID >= explosionGenerators.size()) - return nullptr; + return explosionGenerators[EXPGEN_ID_FALLBACK]; return explosionGenerators[expGenID]; } diff --git a/rts/Sim/Projectiles/ExplosionGenerator.h b/rts/Sim/Projectiles/ExplosionGenerator.h index 27c34c0d4eb..af88c70cd4f 100644 --- a/rts/Sim/Projectiles/ExplosionGenerator.h +++ b/rts/Sim/Projectiles/ExplosionGenerator.h @@ -42,6 +42,7 @@ class CExplosionGeneratorHandler enum { EXPGEN_ID_INVALID = -1u, EXPGEN_ID_STANDARD = 0u, + EXPGEN_ID_FALLBACK = 1u, }; void Init(); @@ -93,7 +94,7 @@ class IExplosionGenerator IExplosionGenerator(): generatorID(CExplosionGeneratorHandler::EXPGEN_ID_INVALID) {} virtual ~IExplosionGenerator() {} - virtual bool Load(CExplosionGeneratorHandler* handler, const char* tag) = 0; + virtual bool Load(CExplosionGeneratorHandler* handler, const char* tag) { return false; } virtual bool Reload(CExplosionGeneratorHandler* handler, const char* tag) { return true; } virtual bool Explosion( const float3& pos, @@ -103,7 +104,7 @@ class IExplosionGenerator float gfxMod, CUnit* owner, CUnit* hit - ) = 0; + ) { return false; } unsigned int GetGeneratorID() const { return generatorID; } void SetGeneratorID(unsigned int id) { generatorID = id; }