/* * Copyright (c) 2016-2024 Vera Visions LLC. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ void NSSurfacePropEntity::NSSurfacePropEntity(void) { m_flBurnNext = 0.0f; #ifdef SERVER m_iPropData = -1i; m_iMaterial = -1i; max_health = 100; m_strOnBreak = __NULL__; m_eBurner= __NULL__; m_iBurnWeapon = 0i; m_flBurnTime = 0.0f; m_flBurnDmgTime = 0.0f; m_oldHealth = 0; m_strSurfData = __NULL__; m_strPropData = __NULL__; m_vecBloodColor = [0.5f, 0.0f, 0.0f]; #endif } void NSSurfacePropEntity::Spawned(void) { super::Spawned(); #ifdef SERVER /* tokenization complete, now we can load propdata */ _SurfaceDataFinish(); _PropDataFinish(); /* Input/Output system */ if (m_strOnBreak) m_strOnBreak = CreateOutput(m_strOnBreak); #endif } bool NSSurfacePropEntity::IsOnFire(void) { return (effects & EF_ONFIRE) ? true : false; } /* networking */ #ifdef SERVER void NSSurfacePropEntity::SetBloodColor(vector newColor) { m_vecBloodColor = newColor; } vector NSSurfacePropEntity::GetBloodColor(void) { return (m_vecBloodColor); } bool NSSurfacePropEntity::IsAlive(void) { return (health > 0) ? true : false; } bool NSSurfacePropEntity::IsVulnerable(void) { return (m_bTakesDamage); } void NSSurfacePropEntity::EnableBleeding(void) { iBleeds = true; } void NSSurfacePropEntity::DisableBleeding(void) { iBleeds = false; } void NSSurfacePropEntity::EnableAimAssist(void) { m_bAutoAim = true; _UpdateTakedamage(); } void NSSurfacePropEntity::DisableAimAssist(void) { m_bAutoAim = false; _UpdateTakedamage(); } void NSSurfacePropEntity::MakeVulnerable(void) { m_bTakesDamage = true; _UpdateTakedamage(); } void NSSurfacePropEntity::MakeInvulnerable(void) { m_bTakesDamage = false; _UpdateTakedamage(); } void NSSurfacePropEntity::_UpdateTakedamage(void) { if (!m_bTakesDamage) { takedamage = DAMAGE_NO; } else { if (m_bAutoAim) { takedamage = DAMAGE_AIM; } else { takedamage = DAMAGE_YES; } } } bool NSSurfacePropEntity::CanBleed(void) { return (iBleeds); } void NSSurfacePropEntity::SetHealth(float new_health) { if (max_health > 0) health = min(new_health, max_health); else health = new_health; } void NSSurfacePropEntity::SetMaxHealth(float new_health) { max_health = new_health; health = min(health, max_health); } float NSSurfacePropEntity::GetHealth(void) { return (health); } float NSSurfacePropEntity::GetMaxHealth(void) { return (max_health); } float NSSurfacePropEntity::GetSpawnHealth(void) { return (m_oldHealth); } void NSSurfacePropEntity::SetArmor(float new_armor) { armor = new_armor; } float NSSurfacePropEntity::GetArmor(void) { return (armor); } bool NSSurfacePropEntity::HasPropData(void) { return (m_iPropData != -1) ? true : false; } __variant NSSurfacePropEntity::GetPropData(int type) { return Prop_GetInfo(m_iPropData, type); } bool NSSurfacePropEntity::HasSurfaceData(void) { return (m_iMaterial != -1) ? true : false; } __variant NSSurfacePropEntity::GetSurfaceData(int type) { return SurfData_GetInfo(m_iMaterial, type); } void NSSurfacePropEntity::ParentUpdate(void) { /* TODO: Move out */ if (IsOnFire()) { if (m_flBurnNext < GetTime()) { if (GetTime() > m_flBurnTime) { Extinguish(); } health -= 5; if (health <= 0) { Death(m_eBurner, m_eBurner, 5i, g_vec_null, 0i); } else { Pain(m_eBurner, m_eBurner, 5i, g_vec_null, 0i); } m_flBurnNext = GetTime() + 0.5f; } } super::ParentUpdate(); } void NSSurfacePropEntity::Damage(entity inflictor, entity attacker, NSDict damageDecl, float damageScale, vector dmgDir, vector hitLocation) { if (IsVulnerable() == false) { return; } string damageString = ReadString(damageDecl.GetString("damage")); float knockBack = damageDecl.GetFloat("knockback"); #if 0 float randomDamage = GetSubDefFloat(m_defDamage, "damage_random"); damageVal = (baseDamage + randomDamage); #endif float damagePoints = (float)rint(stof(damageString) * damageScale); NSSurfacePropEntity ourAttacker = (NSSurfacePropEntity)attacker; EntLog("applying %d damage by %s", damagePoints, attacker.classname); /* apply knockback */ if (knockBack >= 0) { SetVelocity(dmgDir * knockBack); } /* notify them */ if (isSentient(attacker)) { ourAttacker.DamageFeedback(this, inflictor, damagePoints); } if (damagePoints != 0) { health = rint(health - damagePoints); if (health <= 0) { Death(inflictor, attacker, (int)damagePoints, dmgDir, 0i); } else if (damagePoints > 0) { Pain(inflictor, attacker, (int)damagePoints, dmgDir, 0i); } } } /* Burning, fire, flames, etc. */ void NSSurfacePropEntity::Ignite(entity attacker, float flLifetime, int iWeapon) { effects |= EF_ONFIRE; m_eBurner = attacker; m_iBurnWeapon = iWeapon; m_flBurnTime = GetTime() + flLifetime; if (m_flBurnDmgTime < time) { NSDict damageDecl = spawn(NSDict); damageDecl.AddKey("damage", "5"); damageDecl.AddKey("skip_armor", "1"); damageDecl.AddKey("type", "burn"); Damage(m_eBurner, m_eBurner, damageDecl, 1.0f, g_vec_null, origin); remove(damageDecl); m_flBurnDmgTime = time + 0.25f; } } bool NSSurfacePropEntity::CanBeDamaged(vector damageOrigin, vector hitLocation) { vector testCenter = WorldSpaceCenter(); traceline(hitLocation, testCenter, MOVE_NORMAL, this); if (trace_fraction == 1.0f) { return (true); } traceline(hitLocation, testCenter + [15.0f, 15.0f, 0.0f], MOVE_NORMAL, this); if (trace_fraction == 1.0f) { return (true); } traceline(hitLocation, testCenter + [-15.0f, -15.0f, 0.0f], MOVE_NORMAL, this); if (trace_fraction == 1.0f) { return (true); } traceline(hitLocation, testCenter + [-15.0f, 15.0f, 0.0f], MOVE_NORMAL, this); if (trace_fraction == 1.0f) { return (true); } traceline(hitLocation, testCenter + [15.0f, -15.0f, 0.0f], MOVE_NORMAL, this); if (trace_fraction == 1.0f) { return (true); } return (false); } void NSSurfacePropEntity::Extinguish(void) { effects &= ~EF_ONFIRE; m_eBurner = __NULL__; m_iBurnWeapon = m_flBurnTime = 0; } void NSSurfacePropEntity::Respawn(void) { float sh = GetSpawnFloat("health"); super::Respawn(); /* only use spawndata's health if we aren't overriding it */ if (HasPropData() != false && sh <= 0) { SetHealth((float)GetPropData(PROPINFO_HEALTH)); } else { SetHealth(sh); } if (GetHealth() > 0) { MakeVulnerable(); } else { MakeInvulnerable(); } } void NSSurfacePropEntity::Save(float handle) { super::Save(handle); SaveFloat(handle, "m_flBurnNext", m_flBurnNext); SaveFloat(handle, "armor", armor); SaveFloat(handle, "health", health); SaveFloat(handle, "m_eBurner", num_for_edict(m_eBurner)); SaveInt(handle, "m_iBurnWeapon", m_iBurnWeapon); SaveFloat(handle,"m_flBurnTime", m_flBurnTime); SaveFloat(handle, "m_flBurnDmgTime", m_flBurnDmgTime); SaveString(handle, "m_strOnBreak", m_strOnBreak); SaveFloat(handle, "m_oldHealth", m_oldHealth); SaveVector(handle, "m_vecBloodColor", m_vecBloodColor); SaveInt(handle, "m_iMaterial", m_iMaterial); SaveInt(handle, "m_iPropData", m_iPropData); SaveFloat(handle, "m_flDeathTime", m_flDeathTime); } void NSSurfacePropEntity::Restore(string keyName, string savedValue) { switch (keyName) { case "m_flBurnNext": m_flBurnNext = ReadFloat(savedValue); break; case "armor": armor = ReadFloat(savedValue); break; case "health": health = ReadFloat(savedValue); break; case "m_eBurner": m_eBurner = edict_num(ReadFloat(savedValue)); break; case "m_iBurnWeapon": m_iBurnWeapon = ReadInt(savedValue); break; case "m_flBurnTime": m_flBurnTime = ReadFloat(savedValue); break; case "m_flBurnDmgTime": m_flBurnDmgTime = ReadFloat(savedValue); break; case "m_strOnBreak": m_strOnBreak = ReadString(savedValue); break; case "m_oldHealth": m_oldHealth = ReadFloat(savedValue); break; case "m_vecBloodColor": m_vecBloodColor = ReadVector(savedValue); break; case "m_iMaterial": m_iMaterial = ReadInt(savedValue); break; case "m_iPropData": m_iPropData = ReadInt(savedValue); break; case "m_flDeathTime": m_flDeathTime = ReadFloat(savedValue); break; default: super::Restore(keyName, savedValue); } } void NSSurfacePropEntity::Input(entity entityActivator, string inputName, string dataField) { switch (inputName) { case "Ignite": Ignite(entityActivator, 5000, 0); break; case "IgniteLifetime": float lifeTime = stof(dataField); Ignite(entityActivator, lifeTime, 0); break; case "Extinguish": Extinguish(); break; case "Damage": NSDict damageDecl = spawn(NSDict); float damagePoints = stof(dataField); damageDecl.AddKey("damage", dataField); Damage(this, this, damageDecl, 1.0, g_vec_null, GetOrigin()); remove(damageDecl); break; default: super::Input(entityActivator, inputName, dataField); } } void NSSurfacePropEntity::SpawnKey(string keyName, string setValue) { switch (keyName) { case "bleed": bool query = ReadBool(setValue); if (query) EnableBleeding(); else DisableBleeding(); case "health": max_health = health = ReadFloat(setValue); m_oldHealth = health; break; case "propdata": m_strPropData = ReadString(setValue); break; case "surfdata": case "materialdata": m_strSurfData = ReadString(setValue); break; /* entityDef */ case "blood_color": m_vecBloodColor = ReadVector(setValue); break; /* Input/Output system */ case "OnBreak": m_strOnBreak = PrepareOutput(m_strOnBreak, ReadString(setValue)); break; default: super::SpawnKey(keyName, setValue); break; } } void NSSurfacePropEntity::Pain(entity inflictor, entity attacker, int damage, vector dir, int location) { /* implemented in sub-class */ } void NSSurfacePropEntity::Death(entity inflictor, entity attacker, int damage, vector dir, int location) { BreakModel(damage, dir, location); } void NSSurfacePropEntity::DamageFeedback(entity theVictim, entity theInflictor, int desiredDamage) { /* implemented in sub-class */ } void NSSurfacePropEntity::BreakModel(int damage, vector dir, int location) { m_flDeathTime = time; MakeInvulnerable(); UseOutput(g_dmg_eAttacker, m_strOnBreak); if (HasPropData() == false) { return; } if (GetPropData(PROPINFO_SKIN) != 0) { SetSkin(GetPropData(PROPINFO_SKIN)); } else if (GetPropData(PROPINFO_BREAKMODEL) != __NULL__) { string gibeffect = GetPropData(PROPINFO_BREAKMODEL); int breakcount = GetPropData(PROPINFO_BREAKCOUNT); BreakModel_Entity(this, dir, g_dmg_iDamage); string sndBreak = GetSurfaceData(SURFDATA_SND_BREAK); Sound_PlayAt(GetOrigin(), sndBreak); Disappear(); } else { Disappear(); } /* handle explosions */ float flExplodeMag, flExplodeRad; flExplodeMag = GetPropData(PROPINFO_EXPLOSIVE_DMG); flExplodeRad = GetPropData(PROPINFO_EXPLOSIVE_RADIUS); if (flExplodeMag) { if (!flExplodeRad) { flExplodeRad = flExplodeMag * 2.5f; } pointparticles(particleeffectnum("fx_explosion.main"), origin, angles, 1); radiusDamage(origin, flExplodeRad, 0i, (int)flExplodeMag, this); } } void NSSurfacePropEntity::SetSurfaceData(string type) { m_strSurfData = type; _SurfaceDataFinish(); } void NSSurfacePropEntity::SetPropData(string type) { m_strPropData = type; _PropDataFinish(); /* no surfdata? maybe the propdata has got one set. */ if (m_iMaterial == -1i) { string propDataSurf = GetPropData(PROPINFO_SURFACEPROP); if (propDataSurf != "") { SetSurfaceData(propDataSurf); } } } void NSSurfacePropEntity::_SurfaceDataFinish(void) { SurfData_SetStage(m_strSurfData); if (m_strSurfData) { m_iMaterial = SurfData_Finish(); } else { m_iMaterial = -1i; } } void NSSurfacePropEntity::_PropDataFinish(void) { PropData_SetStage(m_strPropData); if (m_strPropData) { m_iPropData = PropData_Finish(); } else { m_iPropData = -1i; } } float NSSurfacePropEntity::TimeSinceDeath(void) { if (IsAlive()) { return (-1.0f); } return (time - m_flDeathTime); } void NSSurfacePropEntity::EvaluateEntity(void) { EVALUATE_VECTOR(origin, 0, SRFENT_CHANGED_ORIGIN_X) EVALUATE_VECTOR(origin, 1, SRFENT_CHANGED_ORIGIN_Y) EVALUATE_VECTOR(origin, 2, SRFENT_CHANGED_ORIGIN_Z) EVALUATE_VECTOR(angles, 0, SRFENT_CHANGED_ANGLES_X) EVALUATE_VECTOR(angles, 1, SRFENT_CHANGED_ANGLES_Y) EVALUATE_VECTOR(angles, 2, SRFENT_CHANGED_ANGLES_Z) EVALUATE_FIELD(modelindex, SRFENT_CHANGED_MODELINDEX) EVALUATE_FIELD(solid, SRFENT_CHANGED_SOLIDMOVETYPE) EVALUATE_FIELD(movetype, SRFENT_CHANGED_SOLIDMOVETYPE) EVALUATE_FIELD(flags, SRFENT_CHANGED_FLAGS) EVALUATE_VECTOR(mins, 0, SRFENT_CHANGED_SIZE) EVALUATE_VECTOR(mins, 1, SRFENT_CHANGED_SIZE) EVALUATE_VECTOR(mins, 2, SRFENT_CHANGED_SIZE) EVALUATE_VECTOR(maxs, 0, SRFENT_CHANGED_SIZE) EVALUATE_VECTOR(maxs, 1, SRFENT_CHANGED_SIZE) EVALUATE_VECTOR(maxs, 2, SRFENT_CHANGED_SIZE) EVALUATE_FIELD(frame, SRFENT_CHANGED_FRAME) EVALUATE_FIELD(skin, SRFENT_CHANGED_SKIN) EVALUATE_FIELD(effects, SRFENT_CHANGED_EFFECTS) EVALUATE_FIELD(m_iBody, SRFENT_CHANGED_BODY) EVALUATE_FIELD(scale, SRFENT_CHANGED_SCALE) EVALUATE_VECTOR(m_vecAxialScale, 0, SRFENT_CHANGED_SCALE) EVALUATE_VECTOR(m_vecAxialScale, 1, SRFENT_CHANGED_SCALE) EVALUATE_VECTOR(m_vecAxialScale, 2, SRFENT_CHANGED_SCALE) EVALUATE_VECTOR(velocity, 0, SRFENT_CHANGED_VELOCITY) EVALUATE_VECTOR(velocity, 1, SRFENT_CHANGED_VELOCITY) EVALUATE_VECTOR(velocity, 2, SRFENT_CHANGED_VELOCITY) EVALUATE_VECTOR(avelocity, 0, SRFENT_CHANGED_ANGULARVELOCITY) EVALUATE_VECTOR(avelocity, 1, SRFENT_CHANGED_ANGULARVELOCITY) EVALUATE_VECTOR(avelocity, 2, SRFENT_CHANGED_ANGULARVELOCITY) EVALUATE_FIELD(m_iRenderMode, SRFENT_CHANGED_RENDERMODE) EVALUATE_FIELD(m_iRenderFX, SRFENT_CHANGED_RENDERMODE) EVALUATE_VECTOR(m_vecRenderColor, 0, SRFENT_CHANGED_RENDERCOLOR) EVALUATE_VECTOR(m_vecRenderColor, 1, SRFENT_CHANGED_RENDERCOLOR) EVALUATE_VECTOR(m_vecRenderColor, 2, SRFENT_CHANGED_RENDERCOLOR) EVALUATE_FIELD(m_flRenderAmt, SRFENT_CHANGED_RENDERAMT) EVALUATE_FIELD(m_flBoneControl1, SRFENT_CHANGED_CONTROLLER) EVALUATE_FIELD(m_flBoneControl2, SRFENT_CHANGED_CONTROLLER) EVALUATE_FIELD(m_flBoneControl3, SRFENT_CHANGED_CONTROLLER) EVALUATE_FIELD(m_flBoneControl4, SRFENT_CHANGED_CONTROLLER) EVALUATE_FIELD(m_flBoneControl5, SRFENT_CHANGED_CONTROLLER) } /* Make sure StartFrame calls this */ float NSSurfacePropEntity::SendEntity(entity ePEnt, float flChanged) { if (!modelindex) return (0); if (clienttype(ePEnt) != CLIENTTYPE_REAL) return (0); WriteByte(MSG_ENTITY, ENT_SURFPROP); /* broadcast how much data is expected to be read */ WriteFloat(MSG_ENTITY, flChanged); SENDENTITY_COORD(origin[0], SRFENT_CHANGED_ORIGIN_X) SENDENTITY_COORD(origin[1], SRFENT_CHANGED_ORIGIN_Y) SENDENTITY_COORD(origin[2], SRFENT_CHANGED_ORIGIN_Z) SENDENTITY_ANGLE(angles[0], SRFENT_CHANGED_ANGLES_X) SENDENTITY_ANGLE(angles[1], SRFENT_CHANGED_ANGLES_Y) SENDENTITY_ANGLE(angles[2], SRFENT_CHANGED_ANGLES_Z) SENDENTITY_SHORT(modelindex, SRFENT_CHANGED_MODELINDEX) SENDENTITY_BYTE(solid, SRFENT_CHANGED_SOLIDMOVETYPE) SENDENTITY_BYTE(movetype, SRFENT_CHANGED_SOLIDMOVETYPE) SENDENTITY_INT(flags, SRFENT_CHANGED_FLAGS) SENDENTITY_COORD(mins[0], SRFENT_CHANGED_SIZE) SENDENTITY_COORD(mins[1], SRFENT_CHANGED_SIZE) SENDENTITY_COORD(mins[2], SRFENT_CHANGED_SIZE) SENDENTITY_COORD(maxs[0], SRFENT_CHANGED_SIZE) SENDENTITY_COORD(maxs[1], SRFENT_CHANGED_SIZE) SENDENTITY_COORD(maxs[2], SRFENT_CHANGED_SIZE) SENDENTITY_BYTE(frame, SRFENT_CHANGED_FRAME) SENDENTITY_FLOAT(skin, SRFENT_CHANGED_SKIN) SENDENTITY_FLOAT(effects, SRFENT_CHANGED_EFFECTS) SENDENTITY_SHORT(m_iBody, SRFENT_CHANGED_BODY) SENDENTITY_FLOAT(scale, SRFENT_CHANGED_SCALE) SENDENTITY_FLOAT(m_vecAxialScale[0], SRFENT_CHANGED_SCALE) SENDENTITY_FLOAT(m_vecAxialScale[1], SRFENT_CHANGED_SCALE) SENDENTITY_FLOAT(m_vecAxialScale[2], SRFENT_CHANGED_SCALE) SENDENTITY_COORD(velocity[0], SRFENT_CHANGED_VELOCITY) SENDENTITY_COORD(velocity[1], SRFENT_CHANGED_VELOCITY) SENDENTITY_COORD(velocity[2], SRFENT_CHANGED_VELOCITY) SENDENTITY_COORD(avelocity[0], SRFENT_CHANGED_ANGULARVELOCITY) SENDENTITY_COORD(avelocity[1], SRFENT_CHANGED_ANGULARVELOCITY) SENDENTITY_COORD(avelocity[2], SRFENT_CHANGED_ANGULARVELOCITY) SENDENTITY_BYTE(m_iRenderMode, SRFENT_CHANGED_RENDERMODE) SENDENTITY_BYTE(m_iRenderFX, SRFENT_CHANGED_RENDERMODE) SENDENTITY_BYTE(m_vecRenderColor[0], SRFENT_CHANGED_RENDERCOLOR) SENDENTITY_BYTE(m_vecRenderColor[1], SRFENT_CHANGED_RENDERCOLOR) SENDENTITY_BYTE(m_vecRenderColor[2], SRFENT_CHANGED_RENDERCOLOR) SENDENTITY_BYTE(m_flRenderAmt, SRFENT_CHANGED_RENDERAMT) SENDENTITY_ANGLE(m_flBoneControl1, SRFENT_CHANGED_CONTROLLER) SENDENTITY_ANGLE(m_flBoneControl2, SRFENT_CHANGED_CONTROLLER) SENDENTITY_ANGLE(m_flBoneControl3, SRFENT_CHANGED_CONTROLLER) SENDENTITY_ANGLE(m_flBoneControl4, SRFENT_CHANGED_CONTROLLER) SENDENTITY_ANGLE(m_flBoneControl5, SRFENT_CHANGED_CONTROLLER) return (1); } #else /* ============ NSSurfacePropEntity::ReceiveEntity ============ */ void NSSurfacePropEntity::ReceiveEntity(float flNew, float flChanged) { READENTITY_COORD(origin[0], SRFENT_CHANGED_ORIGIN_X) READENTITY_COORD(origin[1], SRFENT_CHANGED_ORIGIN_Y) READENTITY_COORD(origin[2], SRFENT_CHANGED_ORIGIN_Z) READENTITY_ANGLE(angles[0], SRFENT_CHANGED_ANGLES_X) READENTITY_ANGLE(angles[1], SRFENT_CHANGED_ANGLES_Y) READENTITY_ANGLE(angles[2], SRFENT_CHANGED_ANGLES_Z) READENTITY_SHORT(modelindex, SRFENT_CHANGED_MODELINDEX) READENTITY_BYTE(solid, SRFENT_CHANGED_SOLIDMOVETYPE) READENTITY_BYTE(movetype, SRFENT_CHANGED_SOLIDMOVETYPE) READENTITY_INT(flags, SRFENT_CHANGED_FLAGS) READENTITY_COORD(mins[0], SRFENT_CHANGED_SIZE) READENTITY_COORD(mins[1], SRFENT_CHANGED_SIZE) READENTITY_COORD(mins[2], SRFENT_CHANGED_SIZE) READENTITY_COORD(maxs[0], SRFENT_CHANGED_SIZE) READENTITY_COORD(maxs[1], SRFENT_CHANGED_SIZE) READENTITY_COORD(maxs[2], SRFENT_CHANGED_SIZE) READENTITY_BYTE(frame, SRFENT_CHANGED_FRAME) READENTITY_FLOAT(skin, SRFENT_CHANGED_SKIN) READENTITY_FLOAT(effects, SRFENT_CHANGED_EFFECTS) READENTITY_SHORT(m_iBody, SRFENT_CHANGED_BODY) READENTITY_FLOAT(scale, SRFENT_CHANGED_SCALE) READENTITY_FLOAT(m_vecAxialScale[0], SRFENT_CHANGED_SCALE) READENTITY_FLOAT(m_vecAxialScale[1], SRFENT_CHANGED_SCALE) READENTITY_FLOAT(m_vecAxialScale[2], SRFENT_CHANGED_SCALE) READENTITY_COORD(velocity[0], SRFENT_CHANGED_VELOCITY) READENTITY_COORD(velocity[1], SRFENT_CHANGED_VELOCITY) READENTITY_COORD(velocity[2], SRFENT_CHANGED_VELOCITY) READENTITY_COORD(avelocity[0], SRFENT_CHANGED_ANGULARVELOCITY) READENTITY_COORD(avelocity[1], SRFENT_CHANGED_ANGULARVELOCITY) READENTITY_COORD(avelocity[2], SRFENT_CHANGED_ANGULARVELOCITY) READENTITY_BYTE(m_iRenderMode, SRFENT_CHANGED_RENDERMODE) READENTITY_BYTE(m_iRenderFX, SRFENT_CHANGED_RENDERMODE) READENTITY_BYTE(m_vecRenderColor[0], SRFENT_CHANGED_RENDERCOLOR) READENTITY_BYTE(m_vecRenderColor[1], SRFENT_CHANGED_RENDERCOLOR) READENTITY_BYTE(m_vecRenderColor[2], SRFENT_CHANGED_RENDERCOLOR) READENTITY_BYTE(m_flRenderAmt, SRFENT_CHANGED_RENDERAMT) READENTITY_ANGLE(m_flBoneControl1, SRFENT_CHANGED_CONTROLLER) READENTITY_ANGLE(m_flBoneControl2, SRFENT_CHANGED_CONTROLLER) READENTITY_ANGLE(m_flBoneControl3, SRFENT_CHANGED_CONTROLLER) READENTITY_ANGLE(m_flBoneControl4, SRFENT_CHANGED_CONTROLLER) READENTITY_ANGLE(m_flBoneControl5, SRFENT_CHANGED_CONTROLLER) /* this shall never be valid. use Hide() */ if (scale == 0.0f) { scale = 1.0f; } /* other post-eval operations happen here */ if (flChanged & SRFENT_CHANGED_SIZE) { setsize(this, mins * scale, maxs * scale); } if (flChanged & SRFENT_CHANGED_BODY) { setcustomskin(this, "", sprintf("geomset 0 %i\ngeomset 1 %i\n", m_iBody, m_iBody)); } } void NSSurfacePropEntity::RenderFire(void) { if (IsOnFire()) { vector randomOrg; if (m_flBurnNext < time) { randomOrg[0] = absmin[0] + ( random() * ( absmax[0] - absmin[0] ) ); randomOrg[1] = absmin[1] + ( random() * ( absmax[1] - absmin[1] ) ); randomOrg[2] = absmin[2] + ( random() * ( absmax[2] - absmin[2] ) ); pointparticles(PART_BURNING, randomOrg, g_vec_null, 1); m_flBurnNext = time + 0.1f; } } } float NSSurfacePropEntity::predraw(void) { float returnValue = super::predraw(); if (returnValue) { RenderFire(); } return returnValue; } void NSSurfacePropEntity_ReadEntity(bool isNew) { float networkFlags; NSSurfacePropEntity rendEnt = (NSSurfacePropEntity)self; if (isNew) { spawnfunc_NSSurfacePropEntity(); } networkFlags = readfloat(); rendEnt.ReceiveEntity(isNew, networkFlags); } #endif void NSSurfacePropEntity::SetModel(string newModel) { NSRenderableEntity::SetModel(newModel); #ifdef SERVER if (model && HasPropData() == false) { m_iPropData = PropData_ForModel(model); } #endif } /* helper functions */ void entityDamage(entity targetEnt, entity inflictingEnt, entity attackingEnt, string damageDef, string weaponDef, vector damageOrigin, vector damageDir, vector hitLocation) { #ifdef SERVER NSSurfacePropEntity theTarget; /* common filters */ if (targetEnt.takedamage == DAMAGE_NO) { return; } if (isGodMode(targetEnt) == true) { return; } theTarget = (NSSurfacePropEntity)targetEnt; /* don't use IsAlive(), else we can't gib */ if (!theTarget.GetHealth()) { return; } NSDict damageDecl = NSDict::InitWithSpawnData(damageDef); damageDecl.AddKey("weapon", weaponDef); theTarget.Damage(inflictingEnt, attackingEnt, damageDecl, 1.0, damageDir, hitLocation); remove(damageDecl); #endif } void radiusDamage(vector damageCenter, float damageRange, int damageMin, int damageMax, entity attackingEnt) { #ifdef SERVER vector entPos = g_vec_null; float entDistance = 0.0f; int newDamage = 0i; float damageFrac = 0.0f; vector dmgDir = g_vec_null; for (NSSurfacePropEntity e = __NULL__; (e = (NSSurfacePropEntity)nextent(e));) { if (e.takedamage == DAMAGE_NO) { continue; } if (isGodMode(e) == true) { return; } entPos = e.WorldSpaceCenter(); /* don't bother if it's not anywhere near us */ entDistance = length(damageCenter - entPos); if (entDistance > damageRange) { continue; } /* can we physically hit this thing? */ if (damageMax > 0i) { if (e.CanBeDamaged(damageCenter, entPos) == false) { continue; } } /* calculate new damage values */ damageFrac = (damageRange - entDistance) / damageRange; newDamage = (int)lerp(fabs((float)damageMin), (float)damageMax, damageFrac); dmgDir = dirFromTarget(damageCenter, entPos); if (newDamage > 0i) { g_dmg_vecLocation = trace_endpos; e.health = rint(e.health - newDamage); if (e.health <= 0) { e.Death(attackingEnt, attackingEnt, newDamage, dmgDir, 0i); } else if (newDamage > 0) { e.Pain(attackingEnt, attackingEnt, newDamage, dmgDir, 0i); } } } #endif }