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"
set g_respawn_ghosts_maxtime 6 "maximum amount of time a respawn ghost can last, minimum time is half this value. 0 disables and ghosts fade when the body would"
+set cl_deathglow 0.8 "number of seconds during which dead bodies glow out"
set sv_gibhealth 100 "Minus health a dead body must have in order to get gibbed"
float autocvar__cl_playerskin;
string autocvar__cl_playermodel;
float autocvar_cl_precacheplayermodels;
+float autocvar_cl_deathglow;
self.frame4 = CSQCPlayer_FallbackFrame(self.frame4);
}
-// FEATURE: auto glowmod
-.vector glowmod;
-void CSQCPlayer_GlowMod_Apply(void)
-{
- if(self.colormap > 0)
- self.glowmod = colormapPaletteColor(((self.colormap >= 1024) ? self.colormap : stof(getplayerkeyvalue(self.colormap - 1, "colors"))) & 0x0F, TRUE) * 2;
- else
- self.glowmod = '1 1 1';
-}
-
// FEATURE: auto tag_index
.entity tag_entity;
.float tag_entity_lastmodelindex;
void CSQCModel_Effects_Apply(void)
{
float eff = self.csqcmodel_effects;
+ eff &~= CSQCMODEL_EF_RESPAWNGHOST;
self.renderflags &~= (RF_DEPTHHACK | RF_ADDITIVE | RF_FULLBRIGHT | EF_NOSHADOW | RF_USEAXIS);
self.effects = 0;
Projectile_DrawTrail(self.origin);
else
Projectile_ResetTrail(self.origin);
+
+ if(self.csqcmodel_effects & CSQCMODEL_EF_RESPAWNGHOST)
+ self.renderflags |= RF_ADDITIVE;
+ // also special in CSQCPlayer_GlowMod_Apply
+}
+
+// FEATURE: auto glowmod
+.vector glowmod;
+void CSQCPlayer_GlowMod_Apply(void)
+{
+ float cm = self.colormap;
+
+ if(self.csqcmodel_effects & CSQCMODEL_EF_RESPAWNGHOST)
+ cm = 1024;
+
+ if(self.colormap > 0)
+ self.glowmod = colormapPaletteColor(((self.colormap >= 1024) ? self.colormap : stof(getplayerkeyvalue(self.colormap - 1, "colors"))) & 0x0F, TRUE) * 2;
+ else
+ self.glowmod = '1 1 1';
+
+ if(autocvar_cl_deathglow > 0)
+ if(self.csqcmodel_isdead)
+ {
+ self.glowmod = self.glowmod * bound(0, 1 - (time - self.death_time) / autocvar_cl_deathglow, 1);
+ // prevent the zero vector
+ if(self.glowmod_x == 0)
+ self.glowmod_x = -1;
+ }
}
// general functions
# endif
#endif
-#define CSQCMODEL_EF_INVISIBLE EF_SELECTABLE
+#define CSQCMODEL_EF_RESPAWNGHOST EF_SELECTABLE
#ifdef SVQC
void WriteApproxPastTime(float dst, float t)
{
- float dt = t - time;
+ float dt = time - t;
// warning: this is approximate; do not resend when you don't have to!
// be careful with sendflags here!
// map from range...PPROXPASTTIME_MAX / 256
dt = (APPROXPASTTIME_MAX / 256) * (dt / (256 - dt));
- return servertime + dt;
+ return servertime - dt;
}
#endif
self.movetype = MOVETYPE_FLY;
self.velocity = '0 0 1' * autocvar_g_respawn_ghosts_speed;
self.avelocity = randomvec() * autocvar_g_respawn_ghosts_speed * 3 - randomvec() * autocvar_g_respawn_ghosts_speed * 3;
- self.effects |= EF_ADDITIVE;
+ self.effects |= CSQCMODEL_EF_RESPAWNGHOST;
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);
self.animstate_endtime = oldself.animstate_endtime;
self.animstate_override = oldself.animstate_override;
self.animstate_looping = oldself.animstate_looping;
+ self.death_time = oldself.death_time;
self.frame = oldself.frame;
self.pain_finished = oldself.pain_finished;
self.health = oldself.health;