* spawn/speed optimisation for NSPhysicsEntity

* pick a better dmgDir for hitscan NSProjectiles so physics ent feedback is accurate

* fix NSPhysicsEntities not becoming invulnerable after breaking
This commit is contained in:
Marco Cawthorne 2024-09-03 12:15:16 -07:00
parent b60d420692
commit bf567da9ba
Signed by: eukara
GPG key ID: CE2032F0A2882A22
6 changed files with 59 additions and 38 deletions

View file

@ -472,7 +472,7 @@ NSItem::PredictPreFrame(void)
/* relink */ /* relink */
if (m_nextItem == __NULL__ && chain_entnum) if (m_nextItem == __NULL__ && chain_entnum)
m_nextItem = findentity(world, ::entnum, chain_entnum); m_nextItem = (NSItem)findentity(world, ::entnum, chain_entnum);
if (owner == __NULL__ && owner_entnum) { if (owner == __NULL__ && owner_entnum) {
owner = findentity(world, ::entnum, owner_entnum); owner = findentity(world, ::entnum, owner_entnum);

View file

@ -509,6 +509,7 @@ NSPhysicsEntity::_TouchThink(void)
/* continue testing next frame */ /* continue testing next frame */
nextthink = time; nextthink = time;
effects &= ~EF_NOSHADOW; effects &= ~EF_NOSHADOW;
solid = SOLID_BSP;
} }
#ifdef SERVER #ifdef SERVER
@ -518,19 +519,21 @@ NSPhysicsEntity::Pain(entity inflictor, entity attacker, int damage, vector dir,
vector forceDir; vector forceDir;
float force; float force;
if (m_strOnDamaged) if (m_strOnDamaged) {
UseOutput(this, m_strOnDamaged); UseOutput(this, m_strOnDamaged);
}
if (m_iFlags & BPHY_NODMGPUSH) if (m_iFlags & BPHY_NODMGPUSH) {
return; return;
}
Wake(); Wake();
forceDir = normalize(GetOrigin() - g_dmg_vecLocation); force = CalculateImpactDamage(damage, g_dmg_iFlags);
force = CalculateImpactDamage(g_dmg_iDamage, g_dmg_iFlags);
if (force > 0.0f) if (force > 0.0f) {
ApplyForceOffset(forceDir * force, g_dmg_vecLocation); ApplyForceOffset(dir * force, g_dmg_vecLocation);
}
/* HACK: */ /* HACK: */
if (m_bInvincible) { if (m_bInvincible) {
@ -546,16 +549,6 @@ NSPhysicsEntity::Death(entity inflictor, entity attacker, int damage, vector dir
{ {
Pain(inflictor, attacker, damage, dir, location); Pain(inflictor, attacker, damage, dir, location);
super::Death(inflictor, attacker, damage, dir, location); super::Death(inflictor, attacker, damage, dir, location);
if (takedamage != DAMAGE_YES) {
takedamage = (DAMAGE_YES);
}
/* HACK: */
if (m_bInvincible) {
health = 10000;
}
/* make sure touch think is called */ /* make sure touch think is called */
nextthink = time; nextthink = time;
} }
@ -584,7 +577,7 @@ NSPhysicsEntity::Respawn(void)
bouncefactor = 0.0f; bouncefactor = 0.0f;
bouncestop = 0.0f; bouncestop = 0.0f;
geomtype = GEOMTYPE_TRIMESH; geomtype = GEOMTYPE_BOX;
friction = 1.0f; friction = 1.0f;
m_flBuoyancyRatio = 1.0f; m_flBuoyancyRatio = 1.0f;
@ -965,6 +958,14 @@ NSPhysicsEntity::Wake(void)
if (physics_supported() == TRUE) { if (physics_supported() == TRUE) {
SetMovetype(MOVETYPE_PHYSICS); SetMovetype(MOVETYPE_PHYSICS);
SetSolid(SOLID_BSP); SetSolid(SOLID_BSP);
/* Don't need a lot of precision during this */
if (time < 5.0) {
geomtype = GEOMTYPE_BOX;
} else {
geomtype = GEOMTYPE_TRIMESH;
}
physics_enable(this, TRUE); physics_enable(this, TRUE);
} else { } else {
SetMovetype(MOVETYPE_BOUNCE); SetMovetype(MOVETYPE_BOUNCE);
@ -980,6 +981,7 @@ NSPhysicsEntity::Sleep(void)
ClearVelocity(); ClearVelocity();
physics_enable(this, FALSE); physics_enable(this, FALSE);
SetMovetype(MOVETYPE_NONE); SetMovetype(MOVETYPE_NONE);
SetSolid(SOLID_CORPSE);
} else { } else {
SetMovetype(MOVETYPE_NONE); SetMovetype(MOVETYPE_NONE);
SetSolid(SOLID_BBOX); SetSolid(SOLID_BBOX);

View file

@ -790,6 +790,7 @@ NSProjectile::_LaunchHitscan(vector startPos, vector launchDir, float dmgMultipl
} }
if (m_eMultiTarget) { if (m_eMultiTarget) {
angles = launchDir;
_ApplyDamage(); _ApplyDamage();
} }
} }
@ -811,7 +812,7 @@ NSProjectile::_ApplyDamage(void)
NSDict damageDecl = spawn(NSDict); NSDict damageDecl = spawn(NSDict);
damageDecl.AddKey("hitbody", itos(trace_surface_id)); damageDecl.AddKey("hitbody", itos(trace_surface_id));
damageDecl.AddKey("damage", itos(m_iMultiValue)); damageDecl.AddKey("damage", itos(m_iMultiValue));
vector dmgDir = dirFromTarget(GetOrigin(), m_eMultiTarget.origin); vector dmgDir = normalize(angles);
entityDamage(m_eMultiTarget, owner, owner, damageDecl.GetDeclBody(), GetWeaponOwner().classname, GetOrigin(), dmgDir, trace_endpos); entityDamage(m_eMultiTarget, owner, owner, damageDecl.GetDeclBody(), GetWeaponOwner().classname, GetOrigin(), dmgDir, trace_endpos);
remove(damageDecl); remove(damageDecl);
@ -897,6 +898,7 @@ NSProjectile::_FireSingle(vector vecPos, vector vecAngles, float flDamage, float
if (trace_ent.takedamage != DAMAGE_NO) { if (trace_ent.takedamage != DAMAGE_NO) {
if (trace_ent != m_eMultiTarget) { if (trace_ent != m_eMultiTarget) {
trace_endpos = endPos; trace_endpos = endPos;
angles = vecAngles;
_ApplyDamage(); _ApplyDamage();
m_eMultiTarget = (NSSurfacePropEntity)trace_ent; m_eMultiTarget = (NSSurfacePropEntity)trace_ent;
m_iMultiValue = flDamage; m_iMultiValue = flDamage;

View file

@ -334,20 +334,22 @@ NSSurfacePropEntity::Extinguish(void)
void void
NSSurfacePropEntity::Respawn(void) NSSurfacePropEntity::Respawn(void)
{ {
float sh = GetSpawnHealth(); float sh = GetSpawnFloat("health");
NSRenderableEntity::Respawn();
super::Respawn();
/* only use spawndata's health if we aren't overriding it */ /* only use spawndata's health if we aren't overriding it */
if (HasPropData() != false && sh <= 0) { if (HasPropData() != false && sh <= 0) {
health = (float)GetPropData(PROPINFO_HEALTH); SetHealth((float)GetPropData(PROPINFO_HEALTH));
} else { } else {
health = sh; SetHealth(sh);
} }
if (health > 0) if (GetHealth() > 0) {
takedamage = DAMAGE_YES; MakeVulnerable();
else } else {
takedamage = DAMAGE_NO; MakeInvulnerable();
}
} }
void void
@ -504,6 +506,7 @@ NSSurfacePropEntity::BreakModel(int damage, vector dir, int location)
{ {
m_flDeathTime = time; m_flDeathTime = time;
MakeInvulnerable();
UseOutput(g_dmg_eAttacker, m_strOnBreak); UseOutput(g_dmg_eAttacker, m_strOnBreak);
if (HasPropData() == false) { if (HasPropData() == false) {
@ -516,7 +519,6 @@ NSSurfacePropEntity::BreakModel(int damage, vector dir, int location)
string gibeffect = GetPropData(PROPINFO_BREAKMODEL); string gibeffect = GetPropData(PROPINFO_BREAKMODEL);
int breakcount = GetPropData(PROPINFO_BREAKCOUNT); int breakcount = GetPropData(PROPINFO_BREAKCOUNT);
BreakModel_Entity(this, dir, g_dmg_iDamage); BreakModel_Entity(this, dir, g_dmg_iDamage);
//BreakModel_Spawn(absmin, absmax, [0,0,0], 100, breakcount, gibeffect);
Disappear(); Disappear();
} else { } else {
Disappear(); Disappear();
@ -528,8 +530,9 @@ NSSurfacePropEntity::BreakModel(int damage, vector dir, int location)
flExplodeRad = GetPropData(PROPINFO_EXPLOSIVE_RADIUS); flExplodeRad = GetPropData(PROPINFO_EXPLOSIVE_RADIUS);
if (flExplodeMag) { if (flExplodeMag) {
if (!flExplodeRad) if (!flExplodeRad) {
flExplodeRad = flExplodeMag * 2.5f; flExplodeRad = flExplodeMag * 2.5f;
}
pointparticles(particleeffectnum("fx_explosion.main"), origin, angles, 1); pointparticles(particleeffectnum("fx_explosion.main"), origin, angles, 1);
radiusDamage(origin, flExplodeRad, 0i, (int)flExplodeMag, this); radiusDamage(origin, flExplodeRad, 0i, (int)flExplodeMag, this);
@ -555,28 +558,31 @@ NSSurfacePropEntity::_SurfaceDataFinish(void)
{ {
SurfData_SetStage(m_strSurfData); SurfData_SetStage(m_strSurfData);
if (m_strSurfData) if (m_strSurfData) {
m_iMaterial = SurfData_Finish(); m_iMaterial = SurfData_Finish();
else } else {
m_iMaterial = -1i; m_iMaterial = -1i;
} }
}
void void
NSSurfacePropEntity::_PropDataFinish(void) NSSurfacePropEntity::_PropDataFinish(void)
{ {
PropData_SetStage(m_strPropData); PropData_SetStage(m_strPropData);
if (m_strPropData) if (m_strPropData) {
m_iPropData = PropData_Finish(); m_iPropData = PropData_Finish();
else } else {
m_iPropData = -1i; m_iPropData = -1i;
} }
}
float float
NSSurfacePropEntity::TimeSinceDeath(void) NSSurfacePropEntity::TimeSinceDeath(void)
{ {
if (IsAlive()) if (IsAlive()) {
return (-1); return (-1.0f);
}
return (time - m_flDeathTime); return (time - m_flDeathTime);
} }

View file

@ -14,11 +14,14 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
static string g_lastSpawnData;
static entityDef_t g_entDefTable[ENTITYDEF_MAX]; static entityDef_t g_entDefTable[ENTITYDEF_MAX];
static int g_entDefCount; static int g_entDefCount;
static string g_entDefInclude; static string g_entDefInclude;
#ifdef SERVER
static string g_lastSpawnData;
#endif
void void
EntityDef_ReadFile(string filePath) EntityDef_ReadFile(string filePath)
{ {

View file

@ -259,6 +259,12 @@ PropData_ParsePhyFile(int i, string line, string type)
case "fadetime": case "fadetime":
gibFadeTime = argv(x+1); gibFadeTime = argv(x+1);
break; break;
case "health":
/* TODO: what's this? */
break;
case "burst":
/* TODO: what's this? */
break;
} }
} else if (braced == 0i) { } else if (braced == 0i) {
t_name = strtolower(key); t_name = strtolower(key);
@ -845,8 +851,9 @@ BreakModel_Spawn(vector smins, vector smaxs, vector dir, float speed, int count,
vector pvsPosition; vector pvsPosition;
index = (int)hash_get(g_hashbreakmodel, type, -1); index = (int)hash_get(g_hashbreakmodel, type, -1);
if (index == -1) if (index == -1) {
return; return;
}
pvsPosition = (smins + ( 0.5 * ( smaxs - smins ))); pvsPosition = (smins + ( 0.5 * ( smaxs - smins )));
@ -875,8 +882,9 @@ BreakModel_Entity(NSSurfacePropEntity target, vector dir, float speed)
int index = (int)hash_get(g_hashbreakmodel, type, -1); int index = (int)hash_get(g_hashbreakmodel, type, -1);
vector pos = target.GetOrigin(); vector pos = target.GetOrigin();
if not (index) if not (index) {
return; return;
}
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET); WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
WriteByte(MSG_MULTICAST, EV_BREAKMODEL); WriteByte(MSG_MULTICAST, EV_BREAKMODEL);