/* ---------------------------------------- DeadThink ---------------------------------------- */ static void DeadThink ( void ) { trace_t trace; //HACKHACKHACKHACKHACK //We should really have a seperate G2 bounding box (seperate from the physics bbox) for G2 collisions only //FIXME: don't ever inflate back up? NPC->r.maxs.z = NPC->client->renderInfo.eyePoint.z - NPC->r.currentOrigin.z + 4; if ( NPC->r.maxs.z < -8 ) { NPC->r.maxs.z = -8; } if ( VectorCompare( &NPC->client->ps.velocity, &vec3_origin ) ) {//not flying through the air if ( NPC->r.mins.x > -32 ) { NPC->r.mins.x -= 1; trap->Trace (&trace, &NPC->r.currentOrigin, &NPC->r.mins, &NPC->r.maxs, &NPC->r.currentOrigin, NPC->s.number, NPC->clipmask, qfalse, 0, 0 ); if ( trace.allsolid ) { NPC->r.mins.x += 1; } } if ( NPC->r.maxs.x < 32 ) { NPC->r.maxs.x += 1; trap->Trace (&trace, &NPC->r.currentOrigin, &NPC->r.mins, &NPC->r.maxs, &NPC->r.currentOrigin, NPC->s.number, NPC->clipmask, qfalse, 0, 0 ); if ( trace.allsolid ) { NPC->r.maxs.x -= 1; } } if ( NPC->r.mins.y > -32 ) { NPC->r.mins.y -= 1; trap->Trace (&trace, &NPC->r.currentOrigin, &NPC->r.mins, &NPC->r.maxs, &NPC->r.currentOrigin, NPC->s.number, NPC->clipmask, qfalse, 0, 0 ); if ( trace.allsolid ) { NPC->r.mins.y += 1; } } if ( NPC->r.maxs.y < 32 ) { NPC->r.maxs.y += 1; trap->Trace (&trace, &NPC->r.currentOrigin, &NPC->r.mins, &NPC->r.maxs, &NPC->r.currentOrigin, NPC->s.number, NPC->clipmask, qfalse, 0, 0 ); if ( trace.allsolid ) { NPC->r.maxs.y -= 1; } } } //HACKHACKHACKHACKHACK //FIXME: tilt and fall off of ledges? //NPC_PostDeathThink(); /* if ( !NPCInfo->timeOfDeath && NPC->client != NULL && NPCInfo != NULL ) { //haven't finished death anim yet and were NOT given a specific amount of time to wait before removal int legsAnim = NPC->client->ps.legsAnim; animation_t *animations = knownAnimFileSets[NPC->client->clientInfo.animFileIndex].animations; NPC->bounceCount = -1; // This is a cheap hack for optimizing the pointcontents check below //ghoul doesn't tell us this anymore //if ( NPC->client->renderInfo.legsFrame == animations[legsAnim].firstFrame + (animations[legsAnim].numFrames - 1) ) { //reached the end of the death anim NPCInfo->timeOfDeath = level.time + BodyRemovalPadTime( NPC ); } } else */ { //death anim done (or were given a specific amount of time to wait before removal), wait the requisite amount of time them remove if ( level.time >= NPCInfo->timeOfDeath + BodyRemovalPadTime( NPC ) ) { if ( NPC->client->ps.eFlags & EF_NODRAW ) { if (!trap->ICARUS_IsRunning(NPC->s.number)) //if ( !NPC->taskManager || !NPC->taskManager->IsRunning() ) { NPC->think = G_FreeEntity; NPC->nextthink = level.time + FRAMETIME; } } else { class_t npc_class; // Start the body effect first, then delay 400ms before ditching the corpse NPC_RemoveBodyEffect(); //FIXME: keep it running through physics somehow? NPC->think = NPC_RemoveBody; NPC->nextthink = level.time + FRAMETIME; // if ( NPC->client->playerTeam == NPCTEAM_FORGE ) // NPCInfo->timeOfDeath = level.time + FRAMETIME * 8; // else if ( NPC->client->playerTeam == NPCTEAM_BOTS ) npc_class = NPC->client->NPC_class; // check for droids if ( npc_class == CLASS_SEEKER || npc_class == CLASS_REMOTE || npc_class == CLASS_PROBE || npc_class == CLASS_MOUSE || npc_class == CLASS_GONK || npc_class == CLASS_R2D2 || npc_class == CLASS_R5D2 || npc_class == CLASS_MARK2 || npc_class == CLASS_SENTRY )//npc_class == CLASS_PROTOCOL || { NPC->client->ps.eFlags |= EF_NODRAW; NPCInfo->timeOfDeath = level.time + FRAMETIME * 8; } else NPCInfo->timeOfDeath = level.time + FRAMETIME * 4; } return; } } // If the player is on the ground and the resting position contents haven't been set yet...(BounceCount tracks the contents) if ( NPC->bounceCount < 0 && NPC->s.groundEntityNum >= 0 ) { // if client is in a nodrop area, make him/her nodraw int contents = NPC->bounceCount = trap->PointContents( &NPC->r.currentOrigin, -1 ); if ( ( contents & CONTENTS_NODROP ) ) { NPC->client->ps.eFlags |= EF_NODRAW; } } CorpsePhysics( NPC ); }
/* ---------------------------------------- DeadThink ---------------------------------------- */ static void DeadThink ( void ) { trace_t trace; //HACKHACKHACKHACKHACK //We should really have a seperate G2 bounding box (seperate from the physics bbox) for G2 collisions only //FIXME: don't ever inflate back up? NPC->r.maxs[2] = NPC->client->renderInfo.eyePoint[2] - NPC->r.currentOrigin[2] + 4; if ( NPC->r.maxs[2] < -8 ) { NPC->r.maxs[2] = -8; } if ( VectorCompare( NPC->client->ps.velocity, vec3_origin ) ) {//not flying through the air if ( NPC->r.mins[0] > -32 ) { NPC->r.mins[0] -= 1; trap_Trace (&trace, NPC->r.currentOrigin, NPC->r.mins, NPC->r.maxs, NPC->r.currentOrigin, NPC->s.number, NPC->clipmask ); if ( trace.allsolid ) { NPC->r.mins[0] += 1; } } if ( NPC->r.maxs[0] < 32 ) { NPC->r.maxs[0] += 1; trap_Trace (&trace, NPC->r.currentOrigin, NPC->r.mins, NPC->r.maxs, NPC->r.currentOrigin, NPC->s.number, NPC->clipmask ); if ( trace.allsolid ) { NPC->r.maxs[0] -= 1; } } if ( NPC->r.mins[1] > -32 ) { NPC->r.mins[1] -= 1; trap_Trace (&trace, NPC->r.currentOrigin, NPC->r.mins, NPC->r.maxs, NPC->r.currentOrigin, NPC->s.number, NPC->clipmask ); if ( trace.allsolid ) { NPC->r.mins[1] += 1; } } if ( NPC->r.maxs[1] < 32 ) { NPC->r.maxs[1] += 1; trap_Trace (&trace, NPC->r.currentOrigin, NPC->r.mins, NPC->r.maxs, NPC->r.currentOrigin, NPC->s.number, NPC->clipmask ); if ( trace.allsolid ) { NPC->r.maxs[1] -= 1; } } } //HACKHACKHACKHACKHACK { //death anim done (or were given a specific amount of time to wait before removal), wait the requisite amount of time them remove if ( level.time >= NPCInfo->timeOfDeath + BodyRemovalPadTime( NPC ) ) { if ( NPC->client->ps.eFlags & EF_NODRAW ) { if (!trap_ICARUS_IsRunning(NPC->s.number)) { NPC->think = G_FreeEntity; NPC->nextthink = level.time + level.frameTime; } } else { class_t npc_class; // Start the body effect first, then delay 400ms before ditching the corpse NPC_RemoveBodyEffect(); //FIXME: keep it running through physics somehow? NPC->think = NPC_RemoveBody; NPC->nextthink = level.time + level.frameTime; npc_class = NPC->client->NPC_class; // check for droids if ( npc_class == CLASS_SEEKER || npc_class == CLASS_REMOTE || npc_class == CLASS_PROBE || npc_class == CLASS_MOUSE || npc_class == CLASS_GONK || npc_class == CLASS_R2D2 || npc_class == CLASS_R5D2 || npc_class == CLASS_MARK2 || npc_class == CLASS_SENTRY ) { NPC->client->ps.eFlags |= EF_NODRAW; NPCInfo->timeOfDeath = level.time + level.frameTime * 8; } else NPCInfo->timeOfDeath = level.time + level.frameTime * 4; } return; } } // If the player is on the ground and the resting position contents haven't been set yet...(BounceCount tracks the contents) if ( NPC->bounceCount < 0 && NPC->s.groundEntityNum >= 0 ) { // if client is in a nodrop area, make him/her nodraw int contents = NPC->bounceCount = trap_PointContents( NPC->r.currentOrigin, -1 ); if ( ( contents & CONTENTS_NODROP ) ) { NPC->client->ps.eFlags |= EF_NODRAW; } } CorpsePhysics( NPC ); }
void NPC_RemoveBody( gentity_t *self ) { CorpsePhysics( self ); self->nextthink = level.time + FRAMETIME; if ( self->NPC->nextBStateThink <= level.time ) { trap->ICARUS_MaintainTaskManager(self->s.number); } self->NPC->nextBStateThink = level.time + FRAMETIME; if ( self->message ) {//I still have a key return; } // I don't consider this a hack, it's creative coding . . . // I agree, very creative... need something like this for ATST and GALAKMECH too! if (self->client->NPC_class == CLASS_MARK1) { Mark1_dying( self ); } // Since these blow up, remove the bounding box. if ( self->client->NPC_class == CLASS_REMOTE || self->client->NPC_class == CLASS_SENTRY || self->client->NPC_class == CLASS_PROBE || self->client->NPC_class == CLASS_INTERROGATOR || self->client->NPC_class == CLASS_PROBE || self->client->NPC_class == CLASS_MARK2 ) { //if ( !self->taskManager || !self->taskManager->IsRunning() ) if (!trap->ICARUS_IsRunning(self->s.number)) { if ( !self->activator || !self->activator->client || !(self->activator->client->ps.eFlags2&EF2_HELD_BY_MONSTER) ) {//not being held by a Rancor G_FreeEntity( self ); } } return; } //FIXME: don't ever inflate back up? self->r.maxs.z = self->client->renderInfo.eyePoint.z - self->r.currentOrigin.z + 4; if ( self->r.maxs.z < -8 ) { self->r.maxs.z = -8; } if ( self->client->NPC_class == CLASS_GALAKMECH ) {//never disappears return; } if ( self->NPC && self->NPC->timeOfDeath <= level.time ) { self->NPC->timeOfDeath = level.time + 1000; // Only do all of this nonsense for Scav boys ( and girls ) /// if ( self->client->playerTeam == NPCTEAM_SCAVENGERS || self->client->playerTeam == NPCTEAM_KLINGON // || self->client->playerTeam == NPCTEAM_HIROGEN || self->client->playerTeam == NPCTEAM_MALON ) // should I check NPC_class here instead of TEAM ? - dmv if( self->client->playerTeam == NPCTEAM_ENEMY || self->client->NPC_class == CLASS_PROTOCOL ) { self->nextthink = level.time + FRAMETIME; // try back in a second /* if ( DistanceSquared( g_entities[0].r.currentOrigin, self->r.currentOrigin ) <= REMOVE_DISTANCE_SQR ) { return; } if ( (InFOV( self, &g_entities[0], 110, 90 )) ) // generous FOV check { if ( (NPC_ClearLOS2( &g_entities[0], self->r.currentOrigin )) ) { return; } } */ //Don't care about this for MP I guess. } //FIXME: there are some conditions - such as heavy combat - in which we want // to remove the bodies... but in other cases it's just weird, like // when they're right behind you in a closed room and when they've been // placed as dead NPCs by a designer... // For now we just assume that a corpse with no enemy was // placed in the map as a corpse if ( self->enemy ) { //if ( !self->taskManager || !self->taskManager->IsRunning() ) if (!trap->ICARUS_IsRunning(self->s.number)) { if ( !self->activator || !self->activator->client || !(self->activator->client->ps.eFlags2&EF2_HELD_BY_MONSTER) ) {//not being held by a Rancor if ( self->client && self->client->ps.saberEntityNum > 0 && self->client->ps.saberEntityNum < ENTITYNUM_WORLD ) { gentity_t *saberent = &g_entities[self->client->ps.saberEntityNum]; if ( saberent ) { G_FreeEntity( saberent ); } } G_FreeEntity( self ); } } } } }
void NPC_RemoveBody( gentity_t *self ) { CorpsePhysics( self ); self->nextthink = level.time + level.frameTime; if ( self->NPC->nextBStateThink <= level.time ) { trap_ICARUS_MaintainTaskManager(self->s.number); } self->NPC->nextBStateThink = level.time + level.frameTime; if ( self->message ) {//I still have a key return; } // I don't consider this a hack, it's creative coding . . . // I agree, very creative... need something like this for ATST and GALAKMECH too! if (self->client->NPC_class == CLASS_MARK1) { Mark1_dying( self ); } // Since these blow up, remove the bounding box. if ( self->client->NPC_class == CLASS_REMOTE || self->client->NPC_class == CLASS_SENTRY || self->client->NPC_class == CLASS_PROBE || self->client->NPC_class == CLASS_INTERROGATOR || self->client->NPC_class == CLASS_PROBE || self->client->NPC_class == CLASS_MARK2 ) { //if ( !self->taskManager || !self->taskManager->IsRunning() ) if (!trap_ICARUS_IsRunning(self->s.number)) { if ( !self->activator || !self->activator->client || !(self->activator->client->ps.eFlags2&EF2_HELD_BY_MONSTER) ) {//not being held by a Rancor G_FreeEntity( self ); } } return; } //FIXME: don't ever inflate back up? self->r.maxs[2] = self->client->renderInfo.eyePoint[2] - self->r.currentOrigin[2] + 4; if ( self->r.maxs[2] < -8 ) { self->r.maxs[2] = -8; } if ( self->client->NPC_class == CLASS_GALAKMECH ) {//never disappears return; } if ( self->NPC && self->NPC->timeOfDeath <= level.time ) { self->NPC->timeOfDeath = level.time + 1000; // Only do all of this nonsense for Scav boys ( and girls ) if( self->client->playerTeam == NPCTEAM_ENEMY || self->client->NPC_class == CLASS_PROTOCOL ) { self->nextthink = level.time + level.frameTime; // try back in a second } //FIXME: there are some conditions - such as heavy combat - in which we want // to remove the bodies... but in other cases it's just weird, like // when they're right behind you in a closed room and when they've been // placed as dead NPCs by a designer... // For now we just assume that a corpse with no enemy was // placed in the map as a corpse if ( self->enemy ) { //if ( !self->taskManager || !self->taskManager->IsRunning() ) if (!trap_ICARUS_IsRunning(self->s.number)) { if ( !self->activator || !self->activator->client || !(self->activator->client->ps.eFlags2&EF2_HELD_BY_MONSTER) ) {//not being held by a Rancor if ( self->client && self->client->ps.saberEntityNum > 0 && self->client->ps.saberEntityNum < ENTITYNUM_WORLD ) { gentity_t *saberent = &g_entities[self->client->ps.saberEntityNum]; if ( saberent ) { G_FreeEntity( saberent ); } } G_FreeEntity( self ); } } } } }