Compare commits
8 Commits
2f56725160
...
ee58089a55
Author | SHA1 | Date |
---|---|---|
Marco Cawthorne | ee58089a55 | |
Marco Cawthorne | 34884b68a3 | |
Marco Cawthorne | e2ee6987de | |
Marco Cawthorne | 7d58b4a96a | |
Marco Cawthorne | 8a18c2e992 | |
Marco Cawthorne | 0f86ba61a1 | |
Marco Cawthorne | 5c90692873 | |
Marco Cawthorne | 6319f6166e |
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2022 Vera Visions LLC.
|
||||
* Copyright (c) 2016-2023 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
|
||||
|
@ -14,17 +14,16 @@
|
|||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
enumflags
|
||||
enum
|
||||
{
|
||||
ENVEXPLO_NODAMAGE,
|
||||
ENVEXPLO_REPEATABLE,
|
||||
ENVEXPLO_NOBALL,
|
||||
ENVEXPLO_NOSMOKE,
|
||||
ENVEXPLO_NODECAL,
|
||||
ENVEXPLO_NOSPARKS
|
||||
ENVEXPLO_NODAMAGE = 1,
|
||||
ENVEXPLO_REPEATABLE = 2,
|
||||
ENVEXPLO_NOSOUND = 64,
|
||||
ENVEXPLO_NOTUNDERWATER = 8192,
|
||||
ENVEXPLO_GENERICDAMAGE = 16384
|
||||
};
|
||||
|
||||
/*!QUAKED env_explosion (1 .5 0) (-8 -8 -8) (8 8 8) ENVEXPLO_NODAMAGE ENVEXPLO_REPEATABLE ENVEXPLO_NOBALL ENVEXPLO_NOSMOKE ENVEXPLO_NODECAL ENVEXPLO_NOSPARKS
|
||||
/*!QUAKED env_explosion (1 .5 0) (-8 -8 -8) (8 8 8) NO_DAMAGE REPEATABLE x x x NO_SOUND
|
||||
# OVERVIEW
|
||||
When triggered, creates an explosion at its location.
|
||||
|
||||
|
@ -33,14 +32,18 @@ When triggered, creates an explosion at its location.
|
|||
- "target" : Target when triggered.
|
||||
- "killtarget" : Target to kill when triggered.
|
||||
- "iMagnitude" : Magnitude of the explosion.
|
||||
- "explosion_custom_effect" : Sets a custom explosion particle effect to appear.
|
||||
- "explosion_custom_sound" : Sets a custom explosion sound to play.
|
||||
|
||||
# INPUTS
|
||||
- "Explode" : Triggers the explosion effect.
|
||||
|
||||
# SPAWNFLAGS
|
||||
- ENVEXPLO_NODAMAGE (1) : Make this explosion purely decorative, without radius damage.
|
||||
- ENVEXPLO_REPEATABLE (2) : Makes this explosion triggerable more than once.
|
||||
- ENVEXPLO_NOBALL (4) : Spawn no fireball.
|
||||
- ENVEXPLO_NOSMOKE (8) : Spawn no smoke.
|
||||
- ENVEXPLO_NODECAL (16) : Leave no decal upon explosion.
|
||||
- ENVEXPLO_NOSPARKS (32) : Don't spawn any sparks upon exploding.
|
||||
- NO_DAMAGE (1) : Make this explosion purely decorative, without radius damage.
|
||||
- REPEATABLE (2) : Makes this explosion triggerable more than once.
|
||||
- NO_SOUND (64) : Do not play the sound effect.
|
||||
- NOTUNDERWATER (8192) : Don't cause damage underwater.
|
||||
- GENERIC_DAMAGE (16384) : Act as if damage wasn't caused by an explosion type, making gibbing more difficult - some games may ignore it however.
|
||||
|
||||
# TRIVIA
|
||||
This entity was introduced in Half-Life (1998).
|
||||
|
@ -52,23 +55,74 @@ public:
|
|||
void env_explosion(void);
|
||||
|
||||
/* overrides */
|
||||
virtual void SpawnKey(string,string);
|
||||
virtual void Spawned(void);
|
||||
virtual void Respawn(void);
|
||||
virtual void Save(float);
|
||||
virtual void Restore(string,string);
|
||||
virtual void Trigger(entity, triggermode_t);
|
||||
virtual void SpawnKey(string,string);
|
||||
virtual void Respawn(void);
|
||||
virtual void Input(entity, string, string);
|
||||
|
||||
/** Returns the radius of the explosion. */
|
||||
nonvirtual float GetExplosionRadius(void);
|
||||
/** Returns the maximum damage the explosion delivers. */
|
||||
nonvirtual int GetExplosionDamage(void);
|
||||
|
||||
private:
|
||||
int m_iMagnitude;
|
||||
float m_flMaxDelay;
|
||||
int m_flRadiusOverride;
|
||||
bool m_bEnabled;
|
||||
string m_strExplosionParticle;
|
||||
string m_strExplosionSound;
|
||||
int m_iExplosionParticle;
|
||||
};
|
||||
|
||||
void
|
||||
env_explosion::env_explosion(void)
|
||||
{
|
||||
m_iMagnitude = 0;
|
||||
m_flMaxDelay = 0.0f;
|
||||
m_iMagnitude = 0i;
|
||||
m_flRadiusOverride = -1;
|
||||
m_bEnabled = true;
|
||||
|
||||
m_strExplosionParticle = "fx_explosion.main";
|
||||
m_strExplosionSound = "fx.explosion";
|
||||
m_iExplosionParticle = 0i;
|
||||
}
|
||||
|
||||
void
|
||||
env_explosion::SpawnKey(string strKey, string strValue)
|
||||
{
|
||||
switch (strKey) {
|
||||
case "iMagnitude":
|
||||
m_iMagnitude = ReadInt(strValue);
|
||||
break;
|
||||
case "iRadiusOverride":
|
||||
m_flRadiusOverride = ReadFloat(strValue);
|
||||
break;
|
||||
case "explosion_custom_effect":
|
||||
m_strExplosionParticle = ReadString(strValue);
|
||||
break;
|
||||
case "explosion_custom_sound":
|
||||
m_strExplosionSound = ReadString(strValue);
|
||||
break;
|
||||
default:
|
||||
super::SpawnKey(strKey, strValue);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
env_explosion::Spawned(void)
|
||||
{
|
||||
super::Spawned();
|
||||
|
||||
m_iExplosionParticle = particleeffectnum(m_strExplosionParticle);
|
||||
Sound_Precache(m_strExplosionSound);
|
||||
}
|
||||
|
||||
void
|
||||
env_explosion::Respawn(void)
|
||||
{
|
||||
InitPointTrigger();
|
||||
m_bEnabled = true;
|
||||
}
|
||||
|
||||
|
@ -77,8 +131,11 @@ env_explosion::Save(float handle)
|
|||
{
|
||||
super::Save(handle);
|
||||
SaveInt(handle, "m_iMagnitude", m_iMagnitude);
|
||||
SaveFloat(handle, "m_flMaxDelay", m_flMaxDelay);
|
||||
SaveBool(handle, "m_bEnabled", m_bEnabled);
|
||||
SaveFloat(handle, "m_flRadiusOverride", m_flRadiusOverride);
|
||||
SaveString(handle, "m_strExplosionParticle", m_strExplosionParticle);
|
||||
SaveString(handle, "m_strExplosionSound", m_strExplosionSound);
|
||||
SaveInt(handle, "m_iExplosionParticle", m_iExplosionParticle);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -88,45 +145,79 @@ env_explosion::Restore(string strKey, string strValue)
|
|||
case "m_iMagnitude":
|
||||
m_iMagnitude = ReadInt(strValue);
|
||||
break;
|
||||
case "m_flMaxDelay":
|
||||
m_flMaxDelay = ReadFloat(strValue);
|
||||
break;
|
||||
case "m_bEnabled":
|
||||
m_bEnabled = ReadBool(strValue);
|
||||
break;
|
||||
case "m_flRadiusOverride":
|
||||
m_flRadiusOverride = ReadFloat(strValue);
|
||||
break;
|
||||
case "m_strExplosionParticle":
|
||||
m_strExplosionParticle = ReadString(strValue);
|
||||
break;
|
||||
case "m_strExplosionSound":
|
||||
m_strExplosionSound = ReadString(strValue);
|
||||
break;
|
||||
case "m_iExplosionParticle":
|
||||
m_iExplosionParticle = ReadInt(strValue);
|
||||
break;
|
||||
default:
|
||||
super::Restore(strKey, strValue);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
env_explosion::SpawnKey(string strKey, string strValue)
|
||||
{
|
||||
switch (strKey) {
|
||||
case "iMagnitude":
|
||||
m_iMagnitude = stoi(strValue);
|
||||
break;
|
||||
default:
|
||||
super::SpawnKey(strKey, strValue);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
env_explosion::Respawn(void)
|
||||
{
|
||||
m_bEnabled = true;
|
||||
}
|
||||
|
||||
void
|
||||
env_explosion::Trigger(entity act, triggermode_t state)
|
||||
{
|
||||
pointparticles(particleeffectnum("fx_explosion.main"), origin, [0,0,0], 1);
|
||||
bool shouldDamage = true;
|
||||
|
||||
if (!HasSpawnFlags(ENVEXPLO_NODAMAGE)) {
|
||||
Damage_Radius(origin, this, m_iMagnitude, m_iMagnitude * 2.5f, TRUE, 0);
|
||||
if (HasSpawnFlags(ENVEXPLO_NOTUNDERWATER) == true && WaterLevel() > 0) {
|
||||
shouldDamage = false;
|
||||
} else if (HasSpawnFlags(ENVEXPLO_NODAMAGE) == true) {
|
||||
shouldDamage = false;
|
||||
}
|
||||
|
||||
if (!HasSpawnFlags(ENVEXPLO_REPEATABLE)) {
|
||||
/* TODO: Should be pass the nearest surface normal? Just an idea. */
|
||||
pointparticles(m_iExplosionParticle, GetOrigin(), [0,0,0], 1);
|
||||
|
||||
if (HasSpawnFlags(ENVEXPLO_NOSOUND) == false) {
|
||||
StartSoundDef(m_strExplosionSound, CHAN_BODY, true);
|
||||
}
|
||||
|
||||
if (shouldDamage == true) {
|
||||
damageType_t damageType = DMG_EXPLODE;
|
||||
|
||||
if (HasSpawnFlags(ENVEXPLO_GENERICDAMAGE) == true) {
|
||||
damageType = DMG_GENERIC;
|
||||
}
|
||||
|
||||
Damage_Radius(GetOrigin(), this, GetExplosionDamage(), GetExplosionRadius(), damageType, 0);
|
||||
}
|
||||
|
||||
if (HasSpawnFlags(ENVEXPLO_REPEATABLE) == false) {
|
||||
m_bEnabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
env_explosion::Input(entity entityActivator, string inputName, string dataField)
|
||||
{
|
||||
switch (inputName) {
|
||||
case "Explode":
|
||||
Trigger(entityActivator, TRIG_TOGGLE);
|
||||
break;
|
||||
default:
|
||||
super::Input(entityActivator, inputName, dataField);
|
||||
}
|
||||
}
|
||||
|
||||
float
|
||||
env_explosion::GetExplosionRadius(void)
|
||||
{
|
||||
return (m_flRadiusOverride == -1) ? (float)m_iMagnitude * 2.5f : m_flRadiusOverride;
|
||||
}
|
||||
|
||||
int
|
||||
env_explosion::GetExplosionDamage(void)
|
||||
{
|
||||
return (m_iMagnitude);
|
||||
}
|
||||
|
|
|
@ -240,9 +240,9 @@ ambient_generic::Respawn(void)
|
|||
if (HasSpawnFlags(AS_ARADIUS)) {
|
||||
m_flRadius = ATTN_NONE;
|
||||
} else if (HasSpawnFlags(AS_SRADIUS)) {
|
||||
m_flRadius = ATTN_IDLE;
|
||||
} else if (HasSpawnFlags(AS_MRADIUS)) {
|
||||
m_flRadius = ATTN_STATIC;
|
||||
} else if (HasSpawnFlags(AS_MRADIUS)) {
|
||||
m_flRadius = ATTN_IDLE;
|
||||
} else if (HasSpawnFlags(AS_LRADIUS)) {
|
||||
m_flRadius = ATTN_NORM;
|
||||
} else {
|
||||
|
|
|
@ -140,6 +140,8 @@ void
|
|||
NSTraceAttack::_FireSingle(vector vecPos, vector vecAngles, float flDamage, float flRange)
|
||||
{
|
||||
vector range;
|
||||
vector planeNormal;
|
||||
vector endPos;
|
||||
|
||||
if (flRange <= 0)
|
||||
return;
|
||||
|
@ -157,6 +159,8 @@ NSTraceAttack::_FireSingle(vector vecPos, vector vecAngles, float flDamage, floa
|
|||
m_eOwner.hitcontentsmaski = CONTENTBITS_POINTSOLID | CONTENTBIT_CORPSE | CONTENTBIT_WATER | CONTENTBIT_SLIME | CONTENTBIT_LAVA | CONTENTBIT_PROJECTILE;
|
||||
traceline(vecPos, vecPos + range, MOVE_LAGGED | MOVE_HITMODEL, m_eOwner);
|
||||
m_eOwner.hitcontentsmaski = oldhitcontents;
|
||||
planeNormal = trace_plane_normal;
|
||||
endPos = trace_endpos;
|
||||
|
||||
flRange -= trace_plane_dist;
|
||||
|
||||
|
@ -170,14 +174,14 @@ NSTraceAttack::_FireSingle(vector vecPos, vector vecAngles, float flDamage, floa
|
|||
|
||||
/* water impact */
|
||||
if (trace_endcontentsi & CONTENTBIT_WATER) {
|
||||
SurfData_ImpactOfNamedType("water", trace_endpos, trace_plane_normal);
|
||||
_FireSingle(trace_endpos + (v_forward * 2), vecAngles, flDamage / 2, flRange);
|
||||
SurfData_ImpactOfNamedType("water", endPos, planeNormal);
|
||||
_FireSingle(endPos + (v_forward * 2), vecAngles, flDamage / 2, flRange);
|
||||
} else if (trace_endcontentsi & CONTENTBIT_SLIME) {
|
||||
SurfData_ImpactOfNamedType("slime", trace_endpos, trace_plane_normal);
|
||||
_FireSingle(trace_endpos + (v_forward * 2), vecAngles, flDamage / 2, flRange);
|
||||
SurfData_ImpactOfNamedType("slime", endPos, planeNormal);
|
||||
_FireSingle(endPos + (v_forward * 2), vecAngles, flDamage / 2, flRange);
|
||||
} else if (trace_endcontentsi & CONTENTBIT_LAVA) {
|
||||
SurfData_ImpactOfNamedType("lama", trace_endpos, trace_plane_normal);
|
||||
_FireSingle(trace_endpos + (v_forward * 2), vecAngles, flDamage / 2, flRange);
|
||||
SurfData_ImpactOfNamedType("lama", endPos, planeNormal);
|
||||
_FireSingle(endPos + (v_forward * 2), vecAngles, flDamage / 2, flRange);
|
||||
}
|
||||
|
||||
if (trace_ent.takedamage != DAMAGE_NO && trace_ent.iBleeds) {
|
||||
|
@ -219,21 +223,22 @@ NSTraceAttack::_FireSingle(vector vecPos, vector vecAngles, float flDamage, floa
|
|||
#ifdef WASTES
|
||||
player pl1 = (player)self;
|
||||
if (pl1.m_iWillpowerValue > 0) {
|
||||
FX_Crit(trace_endpos, vectoangles(trace_endpos - pl1.origin), 0);
|
||||
FX_Crit(endPos, vectoangles(endPos - pl1.origin), 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* impact per bullet */
|
||||
if (trace_ent.iBleeds == 0) {
|
||||
if (m_strDecalGroup)
|
||||
DecalGroups_Place(m_strDecalGroup, trace_endpos + (v_forward * -2));
|
||||
DecalGroups_Place(m_strDecalGroup, endPos + (v_forward * -2));
|
||||
|
||||
SurfData_Impact(trace_ent, trace_endpos, trace_plane_normal);
|
||||
SurfData_Impact(trace_ent, endPos, planeNormal);
|
||||
}
|
||||
|
||||
/* combine them into one single Damage_Apply call later */
|
||||
if (trace_ent.takedamage != DAMAGE_NO) {
|
||||
if (trace_ent != m_eMultiTarget) {
|
||||
trace_endpos = endPos;
|
||||
_ApplyDamage();
|
||||
m_eMultiTarget = (NSSurfacePropEntity)trace_ent;
|
||||
m_iMultiValue = flDamage;
|
||||
|
@ -251,16 +256,16 @@ NSTraceAttack::_FireSingle(vector vecPos, vector vecAngles, float flDamage, floa
|
|||
|
||||
/* check if this wall is 6 units thick... */
|
||||
if (m_iTotalPenetrations > 0) {
|
||||
cont = pointcontents(trace_endpos + v_forward * 5);
|
||||
cont = pointcontents(endPos + v_forward * 5);
|
||||
|
||||
if (cont == CONTENT_SOLID)
|
||||
m_iTotalPenetrations -= 1; /* deduct 1 penetration power */
|
||||
}
|
||||
|
||||
cont = pointcontents(trace_endpos + v_forward * m_flMaxThickness);
|
||||
cont = pointcontents(endPos + v_forward * m_flMaxThickness);
|
||||
|
||||
if (cont == CONTENT_EMPTY)
|
||||
_FireSingle(trace_endpos + (v_forward * 2), vecAngles, flDamage / 2, flRange);
|
||||
_FireSingle(endPos + (v_forward * 2), vecAngles, flDamage / 2, flRange);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -463,7 +463,7 @@ initents(void)
|
|||
g_ents_initialized = TRUE;
|
||||
|
||||
/* engine hacks for dedicated servers */
|
||||
cvar_set("s_nominaldistance", "2048");
|
||||
cvar_set("s_nominaldistance", "1024");
|
||||
|
||||
/* other engine hacks */
|
||||
cvar_set("sv_nqplayerphysics", "0");
|
||||
|
|
|
@ -16,4 +16,7 @@
|
|||
*/
|
||||
|
||||
void Skill_Init(void);
|
||||
|
||||
/** Return a skill variable's value or return a defaultvalue if it's undefined. */
|
||||
float Skill_GetValue(string, float);
|
||||
bool Skill_ParseConfig(string fileName);
|
|
@ -27,21 +27,19 @@ This will almost always result in them using default values, or (worst case) 0.
|
|||
void
|
||||
Skill_Init(void)
|
||||
{
|
||||
/* sometimes we have extra overrides that the original does not
|
||||
provide. so we execute our mod-specific config here */
|
||||
readcmd(sprintf("exec skill_%s.cfg\n", cvar_string("game")));
|
||||
readcmd(sprintf("exec maps/%s_skl.cfg\n", mapname));
|
||||
Skill_ParseConfig("cfg/skill_manifest.cfg");
|
||||
Skill_ParseConfig(sprintf("maps/%s_skl.cfg", mapname));
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Skill_GetValue
|
||||
|
||||
Return a skill variable's value or return a defaultvalue if it's undefined.
|
||||
Return a skill variable's value or return a defaultValue if it's undefined.
|
||||
=================
|
||||
*/
|
||||
float
|
||||
Skill_GetValue(string variable, float defaultvalue)
|
||||
Skill_GetValue(string variable, float defaultValue)
|
||||
{
|
||||
float skill = cvar("skill");
|
||||
|
||||
|
@ -49,7 +47,7 @@ Skill_GetValue(string variable, float defaultvalue)
|
|||
skill = 2; /* default to medium */
|
||||
|
||||
float val = fabs(cvar(sprintf("sk_%s%d", variable, skill)));
|
||||
return (val == 0) ? defaultvalue : val;
|
||||
return (val == 0) ? defaultValue : val;
|
||||
}
|
||||
|
||||
/* input string is potentially a skill variable */
|
||||
|
@ -61,4 +59,33 @@ Skill_GetDefValue(string variable)
|
|||
}
|
||||
|
||||
return stof(variable);
|
||||
}
|
||||
|
||||
bool
|
||||
Skill_ParseConfig(string fileName)
|
||||
{
|
||||
string tempString;
|
||||
filestream configFile = fopen(fileName, FILE_READ);
|
||||
|
||||
if (configFile < 0) {
|
||||
print(sprintf("^1Warning: Unable to exec %S for parsing.\n", fileName));
|
||||
return (false);
|
||||
}
|
||||
|
||||
while ((tempString = fgets(configFile))) {
|
||||
int argCount = (int)tokenize_console(tempString);
|
||||
string firstArg = argv(0);
|
||||
|
||||
if (argCount == 2i) {
|
||||
if (firstArg == "exec") {
|
||||
Skill_ParseConfig(sprintf("cfg/%s", argv(1)));
|
||||
}
|
||||
} else if (argCount == 3i) {
|
||||
if (firstArg == "set" || firstArg == "seta")
|
||||
cvar_set(argv(1), argv(2));
|
||||
}
|
||||
}
|
||||
|
||||
fclose(configFile);
|
||||
return (true);
|
||||
}
|
|
@ -113,12 +113,9 @@ NSRenderableEntity::EvaluateEntity(void)
|
|||
EVALUATE_VECTOR(origin, 0, RDENT_CHANGED_ORIGIN_X)
|
||||
EVALUATE_VECTOR(origin, 1, RDENT_CHANGED_ORIGIN_Y)
|
||||
EVALUATE_VECTOR(origin, 2, RDENT_CHANGED_ORIGIN_Z)
|
||||
|
||||
angles = Math_FixDeltaVector(angles);
|
||||
EVALUATE_VECTOR(angles, 0, RDENT_CHANGED_ANGLES_X)
|
||||
EVALUATE_VECTOR(angles, 1, RDENT_CHANGED_ANGLES_Y)
|
||||
EVALUATE_VECTOR(angles, 2, RDENT_CHANGED_ANGLES_Z)
|
||||
|
||||
EVALUATE_FIELD(modelindex, RDENT_CHANGED_MODELINDEX)
|
||||
EVALUATE_FIELD(colormap, RDENT_CHANGED_MODELINDEX)
|
||||
EVALUATE_FIELD(solid, RDENT_CHANGED_SOLIDMOVETYPE)
|
||||
|
|
|
@ -194,12 +194,17 @@ DecalGroups_NumForName(string group)
|
|||
void
|
||||
DecalGroups_Place(string group, vector org)
|
||||
{
|
||||
int index;
|
||||
int index = -1i;
|
||||
|
||||
if (g_decalgroup_count <= 0i)
|
||||
if (g_decalgroup_count <= 0i) {
|
||||
return;
|
||||
}
|
||||
|
||||
index = (int)hash_get(g_hashdecalgroup, strtolower(group), -1);
|
||||
index = (int)hash_get(g_hashdecalgroup, strtolower(group), -1i);
|
||||
|
||||
if (index == -1i) {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef SERVER
|
||||
/* on the server we only need to tell the clients in the PVS
|
||||
|
|
|
@ -738,8 +738,9 @@ BreakModel_SpawnID(vector smins, vector smaxs, vector dir, float speed, int coun
|
|||
gib.SetRenderAmt(renderamt);
|
||||
gib.SetRenderMode(rendermode);
|
||||
gib.SetRenderFX(renderfx);
|
||||
gib.SetSize([0,0,0], [0,0,0]);
|
||||
gib.SetSize([-8,-8,-8],[8,8,8]);
|
||||
gib.SetOrigin(endpos);
|
||||
gib.SetScale(1.0f);
|
||||
|
||||
if (usePhysics == false) {
|
||||
makevectors(dir);
|
||||
|
@ -747,9 +748,9 @@ BreakModel_SpawnID(vector smins, vector smaxs, vector dir, float speed, int coun
|
|||
gib.velocity[0] += (random() - 0.5) * (speed * 0.25);
|
||||
gib.velocity[1] += (random() - 0.5) * (speed * 0.25);
|
||||
gib.velocity[2] += (random() - 0.5) * (speed * 0.25);
|
||||
gib.SetAngularVelocity(vectoangles(gib.velocity));
|
||||
gib.SetAngularVelocity([300,300,300]);
|
||||
gib.SetMovetype(MOVETYPE_BOUNCE);
|
||||
gib.SetSolid(SOLID_BBOX);
|
||||
gib.SetSolid(SOLID_NOT);
|
||||
} else {
|
||||
gib.SetMovetype(MOVETYPE_PHYSICS);
|
||||
gib.SetSolid(SOLID_NOT);
|
||||
|
|
|
@ -456,14 +456,18 @@ void
|
|||
SurfData_Impact_Parse(void)
|
||||
{
|
||||
entity surfnum = __NULL__;
|
||||
vector impactorg = [0.0f, 0.0f, 0.0f];
|
||||
vector impactorg = g_vec_null;
|
||||
vector impactang = g_vec_null;
|
||||
float impactSurface;
|
||||
|
||||
impactorg[0] = readcoord();
|
||||
impactorg[1] = readcoord();
|
||||
impactorg[2] = readcoord();
|
||||
surfnum = findfloat(world, ::entnum, readentitynum()-1);
|
||||
|
||||
string tex_name = getsurfacetexture(surfnum, getsurfacenearpoint(surfnum, impactorg));
|
||||
impactSurface = getsurfacenearpoint(surfnum, impactorg);
|
||||
impactang = getsurfacenormal(surfnum, impactSurface);
|
||||
string tex_name = getsurfacetexture(surfnum, impactSurface);
|
||||
|
||||
string impactsfx = SurfData_GetInfo(SurfData_TexToSurfData(tex_name), SURFDATA_SND_BULLETIMPACT);
|
||||
|
||||
|
@ -476,7 +480,7 @@ SurfData_Impact_Parse(void)
|
|||
NSLog("\temitting impact fx %S at %v", impactfx, impactorg);
|
||||
|
||||
Sound_PlayAt(impactorg, impactsfx);
|
||||
pointparticles( impactid, impactorg, [0,0,0], 1 );
|
||||
pointparticles( impactid, impactorg, impactang, 1 );
|
||||
}
|
||||
|
||||
/** Called by EV_SURFIMPACTID */
|
||||
|
|
Loading…
Reference in New Issue