set g_telefrags_avoid 1 "when teleporters have a random destination, avoid teleporting to locations where a telefrag would happen"
set g_teleport_maxspeed 0 "maximum speed that a player can keep when going through a teleporter (if a misc_teleporter_dest also has a cap the smallest one of these will be used), 0 = don't limit, -1 = keep no speed"
-set sv_damageeffect_tick 0.05 "how often the damage effect is updated (particles per second), low values might cause lag"
-set sv_damageeffect_lifetime 0.04 "how much a damage effect lasts, multiplied by damage amount"
-set sv_damageeffect_lifetime_max 5 "maximum amount of lifetime a damage effect may have at a time"
set cl_damageeffect 1 "enable weapon damage effects on players, values between 0 and 1 specify probability of the effect showing on players each tick (used to reduce the effect)"
set cl_damageeffect_gibs 0.15 "probability of the effect showing on gibs each tick (used to reduce the effect)"
+set cl_damageeffect_tick 0.05 "how often the damage effect is updated (particles per second), low values might cause lag"
+set cl_damageeffect_lifetime 0.04 "how much a damage effect lasts, multiplied by damage amount"
+set cl_damageeffect_lifetime_max 5 "maximum amount of lifetime a damage effect may have at a time"
set g_respawn_ghosts 1 "if 1 dead bodies become ghosts and float away when the player respawns"
set g_respawn_ghosts_speed 5 "the speed with which respawn ghosts float and rotate"
for(i = WEP_FIRST; i <= WEP_LAST; ++i)
(get_weaponinfo(i)).weapon_func(WR_PRECACHE);
}
+
+.entity dmgeffect;
+.string dmgparticles;
+
+void Ent_DamageEffect_Think()
+{
+ self.nextthink = time;
+
+ entity entcs;
+ entcs = entcs_receiver[self.team];
+ if(!entcs)
+ return;
+
+ // Scan the owner of all gibs in the world. If a gib owner is the same as the player we're applying the
+ // effect to, it means our player is gibbed. Therefore, apply the particles to the gibs as well.
+ if(autocvar_cl_damageeffect_gibs)
+ {
+ entity head;
+ for(head = world; (head = find(head, classname, "gib")); )
+ {
+ if(head.team == self.team)
+ if(random() < autocvar_cl_damageeffect_gibs)
+ pointparticles(particleeffectnum(self.dmgparticles), head.origin, '0 0 0', 1);
+ }
+ }
+
+ // if we aren't in third person mode, hide our own damage effect
+ if(self.team == player_localentnum)
+ if(!autocvar_chase_active)
+ return;
+
+ // Now apply the effect to the actual player.
+ if(random() < autocvar_cl_damageeffect)
+ pointparticles(particleeffectnum(self.dmgparticles), entcs.origin, '0 0 0', 1);
+}
+
+void Ent_DamageEffect()
+{
+ float dmg, type, specnum1, specnum2, entnumber;
+ vector org;
+ string specstr, effectnum;
+ entity e;
+
+ dmg = ReadByte(); // damage amount
+ type = ReadByte(); // damage weapon
+ specnum1 = ReadByte(); // player species
+ entnumber = ReadByte(); // player entnum
+
+ if not(autocvar_cl_damageeffect)
+ return;
+ if(autocvar_cl_gentle || autocvar_cl_gentle_damage)
+ return;
+
+ specnum2 = (specnum1 & 0x78) / 8; // blood type: using four bits (0..7, bit indexes 3,4,5)
+ specstr = species_prefix(specnum2);
+
+ e = get_weaponinfo(type);
+ effectnum = strcat("weapondamage_", e.netname);
+ // If the weapon is a bullet weapon, its damage effect is blood.
+ // Since blood is species dependent, we make this effect per-species.
+ if(type == WEP_SHOTGUN || type == WEP_UZI || type == WEP_RIFLE)
+ if(specstr != "")
+ {
+ effectnum = strcat(effectnum, "_", specstr);
+ effectnum = substring(effectnum, 0, strlen(effectnum) - 1); // remove the _ symbol at the end of the species name
+ }
+
+ // if the player already has a damage effect, replace it with the new one
+ entity head;
+ for(head = world; (head = find(head, classname, "dmgeffect")); )
+ {
+ if(head.team == entnumber)
+ {
+ remove(head);
+ head = world;
+ }
+ }
+
+ entity e;
+ e = spawn();
+ e.classname = "dmgeffect";
+ e.team = entnumber;
+ e.dmgparticles = effectnum;
+ e.think = Ent_DamageEffect_Think;
+ e.nextthink = time;
+}
precache_sound ("misc/gib_splat03.wav");
precache_sound ("misc/gib_splat04.wav");
}
-
-void Ent_DamageEffect()
-{
- float type, specnum1, specnum2, entnumber, body;
- vector org;
- string specstr, effectnum;
- entity e;
-
- type = ReadByte(); // damage weapon
- specnum1 = ReadByte(); // player species
- entnumber = ReadByte(); // player entnum
- body = ReadByte(); // is dead body / gibbed
- org_x = ReadCoord();
- org_y = ReadCoord();
- org_z = ReadCoord();
-
- if not(autocvar_cl_damageeffect)
- return;
- if(autocvar_cl_gentle || autocvar_cl_gentle_damage)
- return;
-
- e = get_weaponinfo(type);
-
- specnum2 = (specnum1 & 0x78) / 8; // blood type: using four bits (0..7, bit indexes 3,4,5)
- specstr = species_prefix(specnum2);
-
- effectnum = strcat("weapondamage_", e.netname);
- // If the weapon is a bullet weapon, its damage effect is blood.
- // Since blood is species dependent, we make this effect per-species.
- if(type == WEP_SHOTGUN || type == WEP_UZI || type == WEP_RIFLE)
- if(specstr != "")
- {
- effectnum = strcat(effectnum, "_", specstr);
- effectnum = substring(effectnum, 0, strlen(effectnum) - 1); // remove the _ symbol at the end of the species name
- }
-
- entity head;
-
- // Scan the owner of all gibs in the world. If a gib owner is the same as the player we're applying the
- // effect to, it means our player is gibbed. Therefore, apply the particles to the gibs as well.
- if(autocvar_cl_damageeffect_gibs && body > 1)
- for(head = world; (head = find(head, classname, "gib")); )
- {
- if(head.team == entnumber)
- if(random() < autocvar_cl_damageeffect_gibs)
- pointparticles(particleeffectnum(effectnum), head.origin, '0 0 0', 1);
- }
-
- // if we aren't in third person mode, hide our own damage effect
- if(entnumber == player_localentnum && !body)
- if(!autocvar_chase_active)
- return;
- // if this is a gibbed dead body, don't apply the effects to it, only the gibs as done above
- if(body > 1)
- return;
-
- // Now apply the effect to the actual player.
- if(random() < autocvar_cl_damageeffect)
- pointparticles(particleeffectnum(effectnum), org, '0 0 0', 1);
-}
float autocvar_sv_warsowbunny_turnaccel;
string autocvar_sv_weaponstats_file;
float autocvar_sv_gibhealth;
-float autocvar_sv_damageeffect_tick;
-float autocvar_sv_damageeffect_lifetime;
-float autocvar_sv_damageeffect_lifetime_max;
float autocvar_sys_ticrate;
float autocvar_teamplay_lockonrestart;
float autocvar_teamplay_mode;
RemoveGrapplingHook(self); // Wazat's Grappling Hook
- Violence_DamageEffect_Remove(self);
-
self.classname = "player";
self.wasplayer = TRUE;
self.iscreature = TRUE;
pointparticles(particleeffectnum("respawn_ghost"), self.origin, '0 0 0', 1);
if(autocvar_g_respawn_ghosts_maxtime)
SUB_SetFade (self, time + autocvar_g_respawn_ghosts_maxtime / 2 + random () * (autocvar_g_respawn_ghosts_maxtime - autocvar_g_respawn_ghosts_maxtime / 2), 1.5);
- Violence_DamageEffect_Remove(self);
}
CopyBody(1);
Drag_MoveDrag(oldself, self);
- Violence_DamageEffect_Copy(oldself, self);
-
self.owner = oldself;
self = oldself;
}
{
// if the target is a player or dead body, activate damage effects
if(targ.classname == "player" || targ.classname == "body")
- Violence_DamageEffect_SetRepeat(targ, damage, DEATH_WEAPONOF(deathtype));
+ Violence_DamageEffect(targ, damage, DEATH_WEAPONOF(deathtype));
float mirrordamage;
float mirrorforce;
// damage effect
-.float damageeffect_lifetime;
-.entity damageeffect_repeater;
-
float Violence_DamageEffect_SendEntity(entity to, float sf)
{
- // if the client doesn't have the effect enabled, don't send to him and waste bandwidth
if not(to.cvar_cl_damageeffect)
- return FALSE;
- // if the client cannot see the damaged player, avoid sending and further save bandwidth
- if not(checkpvs(to.origin + to.view_ofs, self))
- return FALSE;
+ return FALSE; // if the client doesn't have the effect enabled, don't send to him and waste bandwidth
WriteByte(MSG_ENTITY, ENT_CLIENT_DAMAGEEFFECT);
- WriteByte(MSG_ENTITY, self.cnt); // damage weapon
+ WriteByte(MSG_ENTITY, self.cnt); // damage amount
+ WriteByte(MSG_ENTITY, self.weapon); // damage weapon
WriteByte(MSG_ENTITY, self.state); // player species
WriteByte(MSG_ENTITY, self.team); // player entnum
- WriteByte(MSG_ENTITY, self.deadflag); // is dead body / gibbed
- WriteCoord(MSG_ENTITY, floor(self.origin_x));
- WriteCoord(MSG_ENTITY, floor(self.origin_y));
- WriteCoord(MSG_ENTITY, floor(self.origin_z));
return TRUE;
}
-void Violence_DamageEffect(entity pl, float type)
+void Violence_DamageEffect(entity pl, float damage, float type)
{
- entity e;
+ if(sv_gentle || !type)
+ return; // return if gentle mode is enabled or the damage was not caused by a weapon
+ entity e;
e = spawn();
- e.classname = "damageeffect";
- e.cnt = type;
+ e.cnt = damage;
+ e.weapon = type;
e.state |= 8 * pl.species; // gib type, ranges from 0 to 15
// if this is a copied dead body, send the num of its player instead
else
e.team = num_for_edict(pl);
- // is this a whole dead body, or a gibbed body / player?
- if(!pl.modelindex) // gibbed
- e.deadflag = 2;
- else if(pl.classname == "body")
- e.deadflag = 1;
-
- // if the player is dead, show the effect lower, else it appears floating above the body
- if(pl.health <= 0)
- setorigin(e, pl.origin - '0 0 25');
- else
- setorigin(e, pl.origin);
-
Net_LinkEntity(e, FALSE, 0.2, Violence_DamageEffect_SendEntity);
}
-
-void Violence_DamageEffect_Remove(entity pl);
-void Violence_DamageEffect_DoRepeat()
-{
- if(time > self.damageeffect_lifetime || (self.owner.classname != "player" && self.owner.classname != "body"))
- {
- Violence_DamageEffect_Remove(self.owner);
- return;
- }
-
- Violence_DamageEffect(self.owner, self.cnt);
- self.nextthink = time + autocvar_sv_damageeffect_tick;
-}
-
-void Violence_DamageEffect_SetRepeat(entity pl, float damage, float type)
-{
- if not(autocvar_sv_damageeffect_tick && autocvar_sv_damageeffect_lifetime)
- return;
- if(sv_gentle || !type)
- return; // return if gentle mode is enabled or the damage was not caused by a weapon
-
- // if a repeater doesn't exist, spawn one, else update the existing one
- if(pl.damageeffect_repeater == world)
- {
- pl.damageeffect_repeater = spawn();
- pl.damageeffect_repeater.classname = "damageeffect_repeater";
- pl.damageeffect_repeater.owner = pl;
- pl.damageeffect_repeater.think = Violence_DamageEffect_DoRepeat;
-
- pl.damageeffect_repeater.damageeffect_lifetime = time + (autocvar_sv_damageeffect_lifetime * damage);
- }
- else
- {
- // if the repeater is being updated, increase its lifetime instead of re-setting it entirely
- // this fixes the shotgun among other things, where only the damage of one bullet would be taken into account
- pl.damageeffect_repeater.damageeffect_lifetime += (autocvar_sv_damageeffect_lifetime * damage);
- }
-
- if(autocvar_sv_damageeffect_lifetime_max)
- pl.damageeffect_repeater.damageeffect_lifetime = bound(0, pl.damageeffect_repeater.damageeffect_lifetime, time + autocvar_sv_damageeffect_lifetime_max);
-
- pl.damageeffect_repeater.cnt = type;
- pl.damageeffect_repeater.nextthink = time;
-}
-
-void Violence_DamageEffect_Remove(entity pl)
-{
- pl.damageeffect_repeater.nextthink = 0;
- remove(pl.damageeffect_repeater);
- pl.damageeffect_repeater = world;
-}
-
-void Violence_DamageEffect_Copy(entity old_pl, entity pl)
-{
- if(pl.damageeffect_repeater != world)
- Violence_DamageEffect_Remove(pl);
-
- Violence_DamageEffect_SetRepeat(pl, 0, old_pl.damageeffect_repeater.cnt); // spawn a new repeater
- pl.damageeffect_repeater.damageeffect_lifetime = old_pl.damageeffect_repeater.damageeffect_lifetime; // copy the lifetime
-}