|
Quake Style - Quake 3 Tutorials Freeze Tag - Freeze Tag Part 1 Starting off the freeze tag tuts.. |
self->r.maxs[2] = -8;
// don't allow respawn until the death anim is done
// g_forcerespawn may force spawning at some later time
/*freeze
self->client->respawnTime = level.time + 1700;
freeze*/
// remove powerups
memset( self->client->ps.powerups, 0, sizeof(self->client->ps.powerups) );
//freeze
player_freeze( self, attacker, meansOfDeath );
self->client->respawnTime = level.time + 1700;
//freeze
// never gib in a nodrop
if ( self->health <= GIB_HEALTH && !(contents & CONTENTS_NODROP) && g_blood.integer ) {
// gib death
GibEntity( self, killer );
} else {
// normal death
static int i;
void player_freeze( gentity_t *targ, gentity_t *attacker, int mod )
{
// Don't freeze anyone if we're not in team play or during warmup time
if ( g_gametype.integer < GT_TEAM || level.warmupTime ) {
return;
}
// If they just (3 sec) respawned then don't freeze them
// Note we check their respawnTime so earlier I made sure this didn't get reset until after player_freeze was called
if ( level.time - targ->client->respawnTime < 3000 ) {
return;
}
// Don't freeze someone for certain cases
switch ( mod ) {
case MOD_WATER:
case MOD_CRUSH:
case MOD_TELEFRAG:
case MOD_FALLING:
case MOD_SUICIDE:
case MOD_TARGET_LASER:
case MOD_TRIGGER_HURT:
case MOD_GRAPPLE:
return;
}
// Did a teammate kill us or did we kill ourselves?
if ( OnSameTeam( targ, attacker ) && targ != attacker ) {
return;
}
targ->client->ps.powerups[ PW_BALL ] = INT_MAX;
targ->client->noclip = qtrue;
targ->health = 0;
G_AddEvent( targ, EV_DEATH1, 0 );
targ->client->ps.pm_time = 4000;
}
qboolean IsFrozen( gentity_t *ent ) {
// For clients and bots
if ( ent->client && ent->client->ps.powerups[ PW_BALL ] ) {
return qtrue;
// For my fake bodies
} else if ( ent->s.powerups & ( 1 << PW_BALL ) ) {
return qtrue;
}
return qfalse;
}
case EV_DEATH1:
//freeze
if ( es->number == cg.snap->ps.clientNum ) {
cg.powerupTime = cg.time;
}
break;
//freeze
case EV_DEATH2:
case EV_DEATH3:
DEBUGNAME("EV_DEATHx");
trap_S_StartSound( NULL, es->number, CHAN_VOICE,
CG_CustomSound( es->number, va("*death%i.wav", event - EV_DEATH1 + 1) ) );
break;
if ( cg.showScores || cg.predictedPlayerState.pm_type == PM_DEAD ||
//freeze
( cg.predictedPlayerState.pm_type == PM_NOCLIP && cg.powerupTime + 4000 > cg.time ) ||
//freeze
cg.predictedPlayerState.pm_type == PM_INTERMISSION ) {
fade = 1.0;
fadeColor = colorWhite;
}
else {
self->client->ps.torsoAnim =
( ( self->client->ps.torsoAnim & ANIM_TOGGLEBIT ) ^ ANIM_TOGGLEBIT ) | anim;
//freeze
if ( IsFrozen( self ) ) {
CopyToBody( self );
} else {
//freeze
G_AddEvent( self, EV_DEATH1 + 1, killer );
//freeze
}
//freeze
// the body can still be gibbed
self->die = body_die;
void CopyToBody( gentity_t *ent ) {
gentity_t *body;
// Create a game entity (our lovely frozen body)
body = G_Spawn();
if ( !body ) {
return;
}
body->classname = "body";
// This is basically a copy of g_client.c CopyToBodyQue (normal body created when dead player respawns)
body->s = ent->s;
body->s.eFlags = EF_DEAD;
// This body's frozen
body->s.powerups = ( 1 << PW_BALL );
body->s.loopSound = 0;
body->s.number = body - g_entities;
body->timestamp = level.time;
body->physicsObject = qtrue;
body->physicsBounce = 0;
// This is special
// This means we can shoot and bounce this body around
G_SetOrigin( body, ent->r.currentOrigin );
body->s.pos.trType = TR_GRAVITY;
body->s.pos.trTime = level.time;
// Make sure to copy dead player's velocity to our body so it goes flying
VectorCopy( ent->client->ps.velocity, body->s.pos.trDelta );
body->s.event = 0;
switch ( body->s.legsAnim & ~ANIM_TOGGLEBIT ) {
case BOTH_DEATH1:
case BOTH_DEAD1:
body->s.torsoAnim = body->s.legsAnim = BOTH_DEAD1;
break;
case BOTH_DEATH2:
case BOTH_DEAD2:
body->s.torsoAnim = body->s.legsAnim = BOTH_DEAD2;
break;
case BOTH_DEATH3:
case BOTH_DEAD3:
default:
body->s.torsoAnim = body->s.legsAnim = BOTH_DEAD3;
break;
}
body->r.svFlags = ent->r.svFlags;
// I am making the body have the default player's bounding box
// This isn't right though
// Could put body outside map so I need to fix this for later version
VectorSet ( body->r.mins, -15, -15, -24 );
VectorSet ( body->r.maxs, 15, 15, 32 );
VectorCopy( ent->r.absmin, body->r.absmin );
VectorCopy( ent->r.absmax, body->r.absmax );
body->clipmask = CONTENTS_SOLID | CONTENTS_PLAYERCLIP;
// Make the body something solid
body->r.contents = CONTENTS_BODY;
body->r.ownerNum = ent->s.number;
body->nextthink = level.time + FRAMETIME;
body->think = BodyThink;
body->die = Body_die;
body->takedamage = qtrue;
trap_LinkEntity( body );
body->noise_index = G_SoundIndex( "sound/player/tankjr/jump1.wav" );
// I use splashDamage to remember what team this body is on
body->splashDamage = level.clients[ ent->s.clientNum ].sess.sessionTeam;
// This will be used for when you look at the body and see a player's name
body->s.otherEntityNum = ent->s.number;
ent->health = GIB_HEALTH;
// Don't let bullets and rockets hit us
ent->r.contents = 0;
// So they don't move after free to move around (push from explosion they died from)
VectorClear( ent->client->ps.velocity );
}
if ( ps->pm_type == PM_INTERMISSION || ps->pm_type == PM_SPECTATOR ) {
s->eType = ET_INVISIBLE;
} else if ( ps->stats[STAT_HEALTH] <= GIB_HEALTH ) {
s->eType = ET_INVISIBLE;
} else {
s->eType = ET_PLAYER;
}