optimizations + bugfixes

* Bombs explode on damage/explosion
* Orbits spell fixed
* Performance: implemented shared component indexes,
compiled Lua caching, and updates only for changed projectile fields.
Also removed accumulating hidden entity slots.
This commit is contained in:
Gaël committed 2026-10-20 11:02:18 +02:00
1 parent 87bff164f1
commit a34f42d53e
17 files changed
+727 -131

No files matched your search

+25 -1
View File
@@ -24,6 +24,20 @@ constexpr double kDeg = 3.14159265358979323846 / 180.0;
} // namespace
std::string ProjectileSim::script_definition_key(const EntityDef& entity) {
std::string state = entity.tags;
for (const auto& c : entity.comps) {
state += c.type;
if (c.type == "VariableStorageComponent") continue;
for (const auto& [key, value] : c.attrs) {
// _ng_next and _ng_img_t are emitter clocks, not changes to its effect definition.
if (key.rfind("_ng_", 0) == 0 || key == "mWhoShot" || key == "mEntityThatShot" || key == "mShooterHerdId" || key.rfind("mVelocity", 0) == 0) continue;
state += key + "=" + value + ";";
}
}
return entity.path + "#script" + std::to_string(std::hash<std::string>()(state));
}
const ProjDef* ProjectileSim::def(const std::string& file) {
auto it = defs_.find(file);
if (it != defs_.end()) return &it->second;
@@ -41,6 +55,7 @@ void ProjectileSim::disable_gpu_lua() {
// The entity has components the GPU does not simulate (CellEater, MagicConvertMaterial, area effects, scripts...): the host keeps a runtime twin of the projectile
static bool host_runs(const EntityDef& e, bool gpu_script = false) {
if (!e.all("DamageModelComponent").empty()) return true;
for (const char* rich : {"CellEaterComponent", "MagicConvertMaterialComponent", "GameAreaEffectComponent", "AreaDamageComponent", "LightningComponent", "LaserEmitterComponent", "MaterialSeaSpawnerComponent", "TeleportProjectileComponent", "EnergyShieldComponent", "ExplosionComponent", "LooseGroundComponent", "ArcComponent", "LightningComponent", "BlackHoleComponent", "MaterialSuckerComponent"})
if (!e.all(rich).empty()) return true;
if (!gpu_script) for (const EntityComponent* lc : e.all("LuaComponent")) for (const auto& kv : lc->attrs) if (kv.first.rfind("script_", 0) == 0 && !kv.second.empty()) return true;
@@ -94,7 +109,11 @@ const ProjDef* ProjectileSim::def_from(const std::string& file, const EntityDef&
std::istringstream tags(entity.tags);std::string tag;
while(std::getline(tags,tag,',')) {
auto begin=tag.find_first_not_of(' '), end=tag.find_last_not_of(' ');
if(begin!=std::string::npos&&tag.substr(begin,end-begin+1)=="projectile")d.query_projectile=true;
if(begin!=std::string::npos) {
const auto token = tag.substr(begin,end-begin+1);
if(token=="projectile")d.query_projectile=true;
if(token=="orbit_projectile")d.orbiting=true;
}
}
unsigned velocity_count=0;
for(const auto* component:entity.all("VelocityComponent"))if(component->get("_enabled","1")!="0")++velocity_count;
@@ -160,6 +179,11 @@ const ProjDef* ProjectileSim::def_from(const std::string& file, const EntityDef&
d.friendly_fire = attr(pc, "friendly_fire", 0) != 0;
d.dont_hit_player = attr(pc, "dont_hit_player", 0) != 0;
d.collide_with_shooter_frames = (int)attr(pc, "collide_with_shooter_frames", -1); // (-1: never hits its shooter)
if (d.orbiting) {
d.friendly_fire = true;
d.dont_hit_player = false;
d.collide_with_shooter_frames = 6;
}
d.physics = !e->all("PhysicsBodyComponent").empty();
if (d.physics) d.on_collision_die = false;
d.explode_on_death = attr(pc, "on_death_explode", 0) != 0 || attr(pc, "on_lifetime_out_explode", 0) != 0;