static void G_UpdateTeamMapData_DisguisedPlayer( gentity_t* spotter, gentity_t* ent, qboolean forceAllied, qboolean forceAxis ) { int num = ent - g_entities; mapEntityData_Team_t* teamList; mapEntityData_t *mEnt; if ( ent->client ) { switch ( ent->client->sess.sessionTeam ) { case TEAM_AXIS: forceAxis = qtrue; break; case TEAM_ALLIES: forceAllied = qtrue; break; default: break; } } if ( ent->client && !( ent->client->ps.pm_flags & PMF_LIMBO ) ) { if ( forceAxis ) { teamList = &mapEntityData[0]; mEnt = G_FindMapEntityDataSingleClient( teamList, NULL, num, spotter->s.clientNum ); if ( !mEnt ) { mEnt = G_AllocMapEntityData( teamList ); mEnt->entNum = num; mEnt->singleClient = spotter->s.clientNum; } VectorCopy( ent->client->ps.origin, mEnt->org ); mEnt->yaw = ent->client->ps.viewangles[YAW]; mEnt->data = num; mEnt->startTime = level.time; mEnt->type = ME_PLAYER_DISGUISED; } if ( forceAllied ) { teamList = &mapEntityData[1]; mEnt = G_FindMapEntityDataSingleClient( teamList, NULL, num, spotter->s.clientNum ); if ( !mEnt ) { mEnt = G_AllocMapEntityData( teamList ); mEnt->entNum = num; mEnt->singleClient = spotter->s.clientNum; } VectorCopy( ent->client->ps.origin, mEnt->org ); mEnt->yaw = ent->client->ps.viewangles[YAW]; mEnt->data = num; mEnt->startTime = level.time; mEnt->type = ME_PLAYER_DISGUISED; } } }
void player_die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int damage, int meansOfDeath ) { int contents = 0, i, killer = ENTITYNUM_WORLD; char *killerName = "<world>"; qboolean nogib = qtrue; gitem_t *item = NULL; gentity_t *ent; qboolean killedintank = qfalse; //float timeLived; weapon_t weap = BG_WeaponForMOD( meansOfDeath ); // G_Printf( "player_die\n" ); if(attacker == self) { if(self->client) { self->client->pers.playerStats.suicides++; trap_PbStat ( self - g_entities , "suicide" , va ( "%d %d %d" , self->client->sess.sessionTeam , self->client->sess.playerType , weap ) ) ; } } else if(OnSameTeam( self, attacker )) { G_LogTeamKill( attacker, weap ); } else { G_LogDeath( self, weap ); G_LogKill( attacker, weap ); if( g_gamestate.integer == GS_PLAYING ) { if( attacker->client ) { attacker->client->combatState |= (1<<COMBATSTATE_KILLEDPLAYER); } } } // RF, record this death in AAS system so that bots avoid areas which have high death rates if( !OnSameTeam( self, attacker ) ) { // LC - not needed // BotRecordTeamDeath( self->s.number ); self->isProp = qfalse; // were we teamkilled or not? } else { self->isProp = qtrue; } // if we got killed by a landmine, update our map if( self->client && meansOfDeath == MOD_LANDMINE ) { // if it's an enemy mine, update both teamlists /*int teamNum; mapEntityData_t *mEnt; mapEntityData_Team_t *teamList; teamNum = inflictor->s.teamNum % 4; teamList = self->client->sess.sessionTeam == TEAM_AXIS ? &mapEntityData[0] : &mapEntityData[1]; if((mEnt = G_FindMapEntityData(teamList, inflictor-g_entities)) != NULL) { G_FreeMapEntityData( teamList, mEnt ); } if( teamNum != self->client->sess.sessionTeam ) { teamList = self->client->sess.sessionTeam == TEAM_AXIS ? &mapEntityData[1] : &mapEntityData[0]; if((mEnt = G_FindMapEntityData(teamList, inflictor-g_entities)) != NULL) { G_FreeMapEntityData( teamList, mEnt ); } }*/ mapEntityData_t *mEnt; if((mEnt = G_FindMapEntityData(&mapEntityData[0], inflictor-g_entities)) != NULL) { G_FreeMapEntityData( &mapEntityData[0], mEnt ); } if((mEnt = G_FindMapEntityData(&mapEntityData[1], inflictor-g_entities)) != NULL) { G_FreeMapEntityData( &mapEntityData[1], mEnt ); } } { mapEntityData_t *mEnt; mapEntityData_Team_t *teamList = self->client->sess.sessionTeam == TEAM_AXIS ? &mapEntityData[1] : &mapEntityData[0]; // swapped, cause enemy team mEnt = G_FindMapEntityDataSingleClient( teamList, NULL, self->s.number, -1 ); while( mEnt ) { if( mEnt->type == ME_PLAYER_DISGUISED ) { mapEntityData_t* mEntFree = mEnt; mEnt = G_FindMapEntityDataSingleClient( teamList, mEnt, self->s.number, -1 ); G_FreeMapEntityData( teamList, mEntFree ); } else { mEnt = G_FindMapEntityDataSingleClient( teamList, mEnt, self->s.number, -1 ); } } } if( self->tankLink ) { G_LeaveTank( self, qfalse ); killedintank = qtrue; } if( self->client->ps.pm_type == PM_DEAD || g_gamestate.integer == GS_INTERMISSION ) { return; } // OSP - death stats handled out-of-band of G_Damage for external calls G_addStats(self, attacker, damage, meansOfDeath); // OSP self->client->ps.pm_type = PM_DEAD; G_AddEvent( self, EV_STOPSTREAMINGSOUND, 0); if(attacker) { killer = attacker->s.number; killerName = (attacker->client) ? attacker->client->pers.netname : "<non-client>"; } if(attacker == 0 || killer < 0 || killer >= MAX_CLIENTS) { killer = ENTITYNUM_WORLD; killerName = "<world>"; } if(g_gamestate.integer == GS_PLAYING) { char *obit; if(meansOfDeath < 0 || meansOfDeath >= sizeof(modNames) / sizeof(modNames[0])) { obit = "<bad obituary>"; } else { obit = modNames[meansOfDeath]; } G_LogPrintf("Kill: %i %i %i: %s killed %s by %s\n", killer, self->s.number, meansOfDeath, killerName, self->client->pers.netname, obit ); } // broadcast the death event to everyone ent = G_TempEntity( self->r.currentOrigin, EV_OBITUARY ); ent->s.eventParm = meansOfDeath; ent->s.otherEntityNum = self->s.number; ent->s.otherEntityNum2 = killer; ent->r.svFlags = SVF_BROADCAST; // send to everyone self->enemy = attacker; self->client->ps.persistant[PERS_KILLED]++; // JPW NERVE -- if player is holding ticking grenade, drop it if ((self->client->ps.grenadeTimeLeft) && (self->s.weapon != WP_DYNAMITE) && (self->s.weapon != WP_LANDMINE) && (self->s.weapon != WP_SATCHEL) && (self->s.weapon != WP_TRIPMINE)) { vec3_t launchvel, launchspot; launchvel[0] = crandom(); launchvel[1] = crandom(); launchvel[2] = random(); VectorScale( launchvel, 160, launchvel ); VectorCopy(self->r.currentOrigin, launchspot); launchspot[2] += 40; { // Gordon: fixes premature grenade explosion, ta bani ;) gentity_t *m = fire_grenade(self, launchspot, launchvel, self->s.weapon); m->damage = 0; } } if (attacker && attacker->client) { if ( attacker == self || OnSameTeam (self, attacker ) ) { // DHM - Nerve :: Complaint lodging if( attacker != self && level.warmupTime <= 0 && g_gamestate.integer == GS_PLAYING) { if( attacker->client->pers.localClient ) { trap_SendServerCommand( self-g_entities, "complaint -4" ); } else { if( meansOfDeath != MOD_CRUSH_CONSTRUCTION && meansOfDeath != MOD_CRUSH_CONSTRUCTIONDEATH && meansOfDeath != MOD_CRUSH_CONSTRUCTIONDEATH_NOATTACKER ) { if( g_complaintlimit.integer ) { if( !(meansOfDeath == MOD_LANDMINE && g_disableComplaints.integer & TKFL_MINES ) && !((meansOfDeath == MOD_ARTY || meansOfDeath == MOD_AIRSTRIKE) && g_disableComplaints.integer & TKFL_AIRSTRIKE ) && !(meansOfDeath == MOD_MORTAR && g_disableComplaints.integer & TKFL_MORTAR ) ) { trap_SendServerCommand( self-g_entities, va( "complaint %i", attacker->s.number ) ); self->client->pers.complaintClient = attacker->s.clientNum; self->client->pers.complaintEndTime = level.time + 20500; } } } } } // high penalty to offset medic heal /* AddScore( attacker, WOLF_FRIENDLY_PENALTY ); */ if( g_gametype.integer == GT_WOLF_LMS ) { AddKillScore( attacker, WOLF_FRIENDLY_PENALTY ); } } else { //G_AddExperience( attacker, 1 ); // JPW NERVE -- mostly added as conveneience so we can tweak from the #defines all in one place AddScore(attacker, WOLF_FRAG_BONUS); if( g_gametype.integer == GT_WOLF_LMS ) { if( level.firstbloodTeam == -1 ) level.firstbloodTeam = attacker->client->sess.sessionTeam; AddKillScore( attacker, WOLF_FRAG_BONUS ); } attacker->client->lastKillTime = level.time; } } else { AddScore( self, -1 ); if( g_gametype.integer == GT_WOLF_LMS ) AddKillScore( self, -1 ); } // Add team bonuses Team_FragBonuses(self, inflictor, attacker); // drop flag regardless if (self->client->ps.powerups[PW_REDFLAG]) { item = BG_FindItem("Red Flag"); if (!item) item = BG_FindItem("Objective"); self->client->ps.powerups[PW_REDFLAG] = 0; } if (self->client->ps.powerups[PW_BLUEFLAG]) { item = BG_FindItem("Blue Flag"); if (!item) item = BG_FindItem("Objective"); self->client->ps.powerups[PW_BLUEFLAG] = 0; } if (item) { vec3_t launchvel = { 0, 0, 0 }; gentity_t *flag = LaunchItem(item, self->r.currentOrigin, launchvel, self->s.number); flag->s.modelindex2 = self->s.otherEntityNum2;// JPW NERVE FIXME set player->otherentitynum2 with old modelindex2 from flag and restore here flag->message = self->message; // DHM - Nerve :: also restore item name // Clear out player's temp copies self->s.otherEntityNum2 = 0; self->message = NULL; } // send a fancy "MEDIC!" scream. Sissies, ain' they? if (self->client != NULL) { if( self->health > GIB_HEALTH && meansOfDeath != MOD_SUICIDE && meansOfDeath != MOD_SWITCHTEAM ) { G_AddEvent( self, EV_MEDIC_CALL, 0 ); } } Cmd_Score_f( self ); // show scores // send updated scores to any clients that are following this one, // or they would get stale scoreboards for(i=0; i<level.numConnectedClients; i++) { gclient_t *client = &level.clients[level.sortedClients[i]]; if(client->pers.connected != CON_CONNECTED) continue; if(client->sess.sessionTeam != TEAM_SPECTATOR) continue; if(client->sess.spectatorClient == self->s.number) { Cmd_Score_f(g_entities + level.sortedClients[i]); } } self->takedamage = qtrue; // can still be gibbed self->r.contents = CONTENTS_CORPSE; //self->s.angles[2] = 0; self->s.powerups = 0; self->s.loopSound = 0; self->client->limboDropWeapon = self->s.weapon; // store this so it can be dropped in limbo LookAtKiller( self, inflictor, attacker ); self->client->ps.viewangles[0] = 0; self->client->ps.viewangles[2] = 0; //VectorCopy( self->s.angles, self->client->ps.viewangles ); // trap_UnlinkEntity( self ); self->r.maxs[2] = self->client->ps.crouchMaxZ; //% 0; // ydnar: so bodies don't clip into world self->client->ps.maxs[2] = self->client->ps.crouchMaxZ; //% 0; // ydnar: so bodies don't clip into world trap_LinkEntity( self ); // don't allow respawn until the death anim is done // g_forcerespawn may force spawning at some later time self->client->respawnTime = level.timeCurrent + 800; // remove powerups memset( self->client->ps.powerups, 0, sizeof(self->client->ps.powerups) ); // never gib in a nodrop // FIXME: contents is always 0 here if ( self->health <= GIB_HEALTH && !(contents & CONTENTS_NODROP) ) { GibEntity( self, killer ); nogib = qfalse; } if(nogib){ // normal death // for the no-blood option, we need to prevent the health // from going to gib level if ( self->health <= GIB_HEALTH ) { self->health = GIB_HEALTH + 1; } // Arnout: re-enable this for flailing /* if( self->client->ps.groundEntityNum == ENTITYNUM_NONE ) { self->client->ps.pm_flags |= PMF_FLAILING; self->client->ps.pm_time = 750; BG_AnimScriptAnimation( &self->client->ps, ANIM_MT_FLAILING, qtrue ); // Face explosion directory { vec3_t angles; vectoangles( self->client->ps.velocity, angles ); self->client->ps.viewangles[YAW] = angles[YAW]; SetClientViewAngle( self, self->client->ps.viewangles ); } } else*/ // DHM - Play death animation, and set pm_time to delay 'fallen' animation //if( G_IsSinglePlayerGame() && self->client->sess.sessionTeam == TEAM_ALLIES ) { // // play "falldown" animation since allies bots won't ever die completely // self->client->ps.pm_time = BG_AnimScriptEvent( &self->client->ps, self->client->pers.character->animModelInfo, ANIM_ET_FALLDOWN, qfalse, qtrue ); // G_StartPlayerAppropriateSound(self, "death"); //} else { self->client->ps.pm_time = BG_AnimScriptEvent( &self->client->ps, self->client->pers.character->animModelInfo, ANIM_ET_DEATH, qfalse, qtrue ); // death animation script already contains sound //} // record the death animation to be used later on by the corpse self->client->torsoDeathAnim = self->client->ps.torsoAnim; self->client->legsDeathAnim = self->client->ps.legsAnim; G_AddEvent( self, EV_DEATH1 + 1, killer ); // the body can still be gibbed self->die = body_die; } if( meansOfDeath == MOD_MACHINEGUN ) { switch( self->client->sess.sessionTeam ) { case TEAM_AXIS: level.axisMG42Counter = level.time; break; case TEAM_ALLIES: level.alliesMG42Counter = level.time; break; } } G_FadeItems( self, MOD_SATCHEL ); CalculateRanks(); if( killedintank /*Gordon: automatically go to limbo from tank*/ ) { limbo( self, qfalse ); // but no corpse } else if ( (meansOfDeath == MOD_SUICIDE && g_gamestate.integer == GS_PLAYING) ) { limbo( self, qtrue ); } else if( g_gametype.integer == GT_WOLF_LMS ) { if( !G_CountTeamMedics( self->client->sess.sessionTeam, qtrue ) ) { limbo( self, qtrue ); } } }
void G_UpdateTeamMapData( void ) { int i, j/*, k*/; gentity_t *ent, *ent2; mapEntityData_t *mEnt; if(level.time - level.lastMapEntityUpdate < 500) { return; } level.lastMapEntityUpdate = level.time; for(i = 0, ent = g_entities; i < level.num_entities; i++, ent++) { if(!ent->inuse) { // mapEntityData[0][i].valid = qfalse; // mapEntityData[1][i].valid = qfalse; continue; } switch(ent->s.eType) { case ET_PLAYER: G_UpdateTeamMapData_Player( ent, qfalse, qfalse ); for( j = 0; j < 2; j++ ) { mapEntityData_Team_t *teamList = &mapEntityData[j]; mEnt = G_FindMapEntityDataSingleClient( teamList, NULL, ent->s.number, -1 ); while( mEnt ) { VectorCopy( ent->client->ps.origin, mEnt->org ); mEnt->yaw = ent->client->ps.viewangles[YAW]; mEnt = G_FindMapEntityDataSingleClient( teamList, mEnt, ent->s.number, -1 ); } } break; case ET_CONSTRUCTIBLE_INDICATOR: if( ent->parent && ent->parent->entstate == STATE_DEFAULT ) { G_UpdateTeamMapData_Construct(ent); } break; case ET_EXPLOSIVE_INDICATOR: if( ent->parent && ent->parent->entstate == STATE_DEFAULT ) { G_UpdateTeamMapData_Destruct(ent); } break; case ET_TANK_INDICATOR: case ET_TANK_INDICATOR_DEAD: G_UpdateTeamMapData_Tank(ent); break; case ET_MISSILE: if( ent->methodOfDeath == MOD_LANDMINE) { G_UpdateTeamMapData_LandMine(ent, qfalse, qfalse); } break; case ET_COMMANDMAP_MARKER: G_UpdateTeamMapData_CommandmapMarker( ent ); break; default: break; } } //for(i = 0, ent = g_entities; i < MAX_CLIENTS; i++, ent++) { for( i = 0, ent = g_entities; i < level.num_entities; i++, ent++ ) { qboolean f1, f2; if( !ent->inuse || !ent->client ) { continue; } if( ent->client->sess.playerType == PC_RECON ) { if( ent->health > 0 ) { f1 = ent->client->sess.sessionTeam == TEAM_ALLIES ? qtrue : qfalse; f2 = ent->client->sess.sessionTeam == TEAM_AXIS ? qtrue : qfalse; G_SetupFrustum( ent ); for( j = 0, ent2 = g_entities; j < level.num_entities; j++, ent2++ ) { if( !ent2->inuse || ent2 == ent ) { continue; } switch(ent2->s.eType) { case ET_PLAYER: { vec3_t pos[3]; VectorCopy( ent2->client->ps.origin, pos[0] ); pos[0][2] += ent2->client->ps.mins[2]; VectorCopy( ent2->client->ps.origin, pos[1] ); VectorCopy( ent2->client->ps.origin, pos[2] ); pos[2][2] += ent2->client->ps.maxs[2]; if(ent2->health > 0 && (G_VisibleFromBinoculars( ent, ent2, pos[0] ) || G_VisibleFromBinoculars( ent, ent2, pos[1] ) || G_VisibleFromBinoculars( ent, ent2, pos[2] ) ) ) { if(ent2->client->sess.sessionTeam != ent->client->sess.sessionTeam) { int k; switch(ent2->client->sess.sessionTeam) { case TEAM_AXIS: mEnt = G_FindMapEntityData( &mapEntityData[0], ent2-g_entities ); if( mEnt && level.time - mEnt->startTime > 5000) { for( k = 0; k < MAX_CLIENTS; k++ ) { if(g_entities[k].inuse && g_entities[k].client && g_entities[k].client->sess.sessionTeam == ent->client->sess.sessionTeam) { trap_SendServerCommand( k, va( "tt \"ENEMY SPOTTED <STOP> CHECK COMMAND MAP FOR DETAILS <STOP>\"\n" )); } } } break; case TEAM_ALLIES: mEnt = G_FindMapEntityData( &mapEntityData[1], ent2-g_entities ); if( mEnt && level.time - mEnt->startTime > 5000) { for( k = 0; k < MAX_CLIENTS; k++ ) { if(g_entities[k].inuse && g_entities[k].client && g_entities[k].client->sess.sessionTeam == ent->client->sess.sessionTeam) { trap_SendServerCommand( k, va( "tt \"ENEMY SPOTTED <STOP> CHECK COMMAND MAP FOR DETAILS <STOP>\"\n" )); } } } break; } } G_UpdateTeamMapData_Player(ent2, f1, f2); } break; } default: break; } } if(ent->client->ps.eFlags & EF_ZOOMING) { G_SetupFrustum_ForBinoculars( ent ); for(j = 0, ent2 = g_entities; j < level.num_entities; j++, ent2++) { if(!ent2->inuse || ent2 == ent) { continue; } switch(ent2->s.eType) { case ET_MISSILE: if( ent2->methodOfDeath == MOD_LANDMINE) { if( (ent2->s.teamNum < 4 || ent2->s.teamNum >= 8) && (ent2->s.teamNum%4 != ent->client->sess.sessionTeam) ) { // TAT - as before, we can only detect a mine if we can see it from our binoculars if (G_VisibleFromBinoculars( ent, ent2, ent2->r.currentOrigin )) { G_UpdateTeamMapData_LandMine(ent2, f1, f2); switch(ent2->s.teamNum%4) { case TEAM_AXIS: if( !ent2->s.modelindex2 ) { ent->client->landmineSpottedTime = level.time; ent->client->landmineSpotted = ent2; ent2->s.density = ent-g_entities+1; ent2->missionLevel = level.time; ent->client->landmineSpotted->count2 += 50; if(ent->client->landmineSpotted->count2 >= 250) { // int k; ent->client->landmineSpotted->count2 = 250; ent->client->landmineSpotted->s.modelindex2 = 1; // for marker ent->client->landmineSpotted->s.frame = rand() % 20; ent->client->landmineSpotted->r.contents = CONTENTS_CORPSE; trap_LinkEntity( ent->client->landmineSpotted ); { gentity_t* pm = G_PopupMessage( PM_MINES ); VectorCopy( ent->client->landmineSpotted->r.currentOrigin, pm->s.origin ); pm->s.effect2Time = TEAM_AXIS; pm->s.effect3Time = ent-g_entities; } /* for( k = 0; k < MAX_CLIENTS; k++ ) { if(g_entities[k].inuse && g_entities[k].client && g_entities[k].client->sess.sessionTeam == ent->client->sess.sessionTeam) { trap_SendServerCommand( k, va( "tt \"LANDMINES SPOTTED BY %s^0<STOP> CHECK COMMAND MAP FOR DETAILS <STOP>\"\n", ent->client->pers.netname)); } }*/ trap_SendServerCommand( ent-g_entities, "cp \"Landmine Revealed\n\"" ); AddScore( ent, 1 ); //G_AddExperience( ent, 1.f ); G_AddSkillPoints( ent, SK_MILITARY_INTELLIGENCE_AND_SCOPED_WEAPONS, 3.f ); G_DebugAddSkillPoints( ent, SK_MILITARY_INTELLIGENCE_AND_SCOPED_WEAPONS, 3.f, "spotting a landmine" ); } } break; case TEAM_ALLIES: if( !ent2->s.modelindex2 ) { ent->client->landmineSpottedTime = level.time; ent->client->landmineSpotted = ent2; ent2->s.density = ent-g_entities+1; ent2->missionLevel = level.time; ent->client->landmineSpotted->count2 += 50; if(ent->client->landmineSpotted->count2 >= 250) { // int k; ent->client->landmineSpotted->count2 = 250; ent->client->landmineSpotted->s.modelindex2 = 1; // for marker ent->client->landmineSpotted->s.frame = rand() % 20; ent->client->landmineSpotted->r.contents = CONTENTS_CORPSE; trap_LinkEntity( ent->client->landmineSpotted ); { gentity_t* pm = G_PopupMessage( PM_MINES ); VectorCopy( ent->client->landmineSpotted->r.currentOrigin, pm->s.origin ); pm->s.effect2Time = TEAM_ALLIES; pm->s.effect3Time = ent-g_entities; } /* for( k = 0; k < MAX_CLIENTS; k++ ) { if(g_entities[k].inuse && g_entities[k].client && g_entities[k].client->sess.sessionTeam == ent->client->sess.sessionTeam) { trap_SendServerCommand( k, va( "tt \"LANDMINES SPOTTED BY %s^0<STOP> CHECK COMMAND MAP FOR DETAILS <STOP>\"\n", ent->client->pers.netname)); } }*/ trap_SendServerCommand( ent-g_entities, "cp \"Landmine Revealed\n\"" ); AddScore( ent, 1 ); //G_AddExperience( ent, 1.f ); G_AddSkillPoints( ent, SK_MILITARY_INTELLIGENCE_AND_SCOPED_WEAPONS, 3.f ); G_DebugAddSkillPoints( ent, SK_MILITARY_INTELLIGENCE_AND_SCOPED_WEAPONS, 3.f, "spotting a landmine" ); } } break; } // end switch } // end (G_VisibleFromBinoculars( ent, ent2, ent2->r.currentOrigin )) else { // TAT - if we can't see the mine from our binoculars, make sure we clear out the landmineSpotted ptr, // because bots looking for mines are getting confused ent->client->landmineSpotted = NULL; } } } break; default: break; } } /* if(ent->client->landmineSpotted && !ent->client->landmineSpotted->s.modelindex2) { ent->client->landmineSpotted->count2 += 10; if(ent->client->landmineSpotted->count2 >= 250) { int k; ent->client->landmineSpotted->count2 = 250; ent->client->landmineSpotted->s.modelindex2 = 1; // for marker ent->client->landmineSpotted->s.frame = rand() % 20; for( k = 0; k < MAX_CLIENTS; k++ ) { if(g_entities[k].inuse && g_entities[k].client && g_entities[k].client->sess.sessionTeam == ent->client->sess.sessionTeam) { trap_SendServerCommand( k, va( "tt \"LANDMINES SPOTTED <STOP> CHECK COMMAND MAP FOR DETAILS <STOP>\"\n" )); } } trap_SendServerCommand( ent-g_entities, "cp \"Landmine Revealed\n\"" ); AddScore( ent, 1 ); //G_AddExperience( ent, 1.f ); G_AddSkillPoints( ent, SK_MILITARY_INTELLIGENCE_AND_SCOPED_WEAPONS, 3.f ); G_DebugAddSkillPoints( ent, SK_MILITARY_INTELLIGENCE_AND_SCOPED_WEAPONS, 3.f, "spotting a landmine" ); } }*/ /* { // find any landmines that don't actually exist anymore, see if the covert ops can see the spot and if so - wipe them mapEntityData_Team_t *teamList = ent->client->sess.sessionTeam == TEAM_AXIS ? &mapEntityData[0] : &mapEntityData[1]; mEnt = teamList->activeMapEntityData.next; while( mEnt && mEnt != &teamList->activeMapEntityData ) { if( mEnt->type == ME_LANDMINE && mEnt->entNum == -1 ) { if( G_VisibleFromBinoculars( ent, NULL, mEnt->org ) ) { mEnt = G_FreeMapEntityData( teamList, mEnt ); trap_SendServerCommand( ent-g_entities, "print \"Old Landmine Cleared\n\"" ); AddScore( ent, 1 ); continue; } } mEnt = mEnt->next; } }*/ } } } } // G_SendAllMapEntityInfo(); }
void G_UpdateTeamMapData(void) { int i, j; gentity_t *ent, *ent2; mapEntityData_t *mEnt; qboolean f1, f2; G_CheckSpottedLandMines(); if (level.time - level.lastMapEntityUpdate < 1000) { return; } level.lastMapEntityUpdate = level.time; // all ents - comon update for (i = 0; i < level.num_entities; i++) { ent = &g_entities[i]; if (!ent->inuse) { //mapEntityData[0][i].valid = qfalse; //mapEntityData[1][i].valid = qfalse; continue; } switch (ent->s.eType) { case ET_PLAYER: G_UpdateTeamMapData_Player(ent, qfalse, qfalse); for (j = 0; j < 2; j++) { mapEntityData_Team_t *teamList = &mapEntityData[j]; mEnt = G_FindMapEntityDataSingleClient(teamList, NULL, ent->s.number, -1); while (mEnt) { VectorCopy(ent->client->ps.origin, mEnt->org); mEnt->yaw = ent->client->ps.viewangles[YAW]; mEnt = G_FindMapEntityDataSingleClient(teamList, mEnt, ent->s.number, -1); } } break; case ET_CONSTRUCTIBLE_INDICATOR: if (ent->parent && ent->parent->entstate == STATE_DEFAULT) { G_UpdateTeamMapData_Construct(ent); } break; case ET_EXPLOSIVE_INDICATOR: if (ent->parent && ent->parent->entstate == STATE_DEFAULT) { G_UpdateTeamMapData_Destruct(ent); } break; case ET_TANK_INDICATOR: case ET_TANK_INDICATOR_DEAD: G_UpdateTeamMapData_Tank(ent); break; case ET_MISSILE: if (ent->methodOfDeath == MOD_LANDMINE) { G_UpdateTeamMapData_LandMine(ent); } break; case ET_COMMANDMAP_MARKER: G_UpdateTeamMapData_CommandmapMarker(ent); break; default: break; } } // clients again - do special stuff for field- and covert ops for (i = 0; i < level.numConnectedClients; i++) { ent = &g_entities[level.sortedClients[i]]; f1 = ent->client->sess.sessionTeam == TEAM_ALLIES ? qtrue : qfalse; f2 = ent->client->sess.sessionTeam == TEAM_AXIS ? qtrue : qfalse; if (!ent->inuse) { continue; } if (ent->health <= 0) { continue; } // must be in a valid team if (ent->client->sess.sessionTeam == TEAM_SPECTATOR || ent->client->sess.sessionTeam == TEAM_FREE) { continue; } if (ent->client->ps.pm_flags & PMF_LIMBO) { continue; } if (ent->client->sess.playerType == PC_FIELDOPS && (ent->client->ps.eFlags & EF_ZOOMING) && ent->client->sess.skill[SK_SIGNALS] >= 4) { vec3_t pos[3]; G_SetupFrustum_ForBinoculars(ent); for (j = 0; j < level.numConnectedClients; j++) { ent2 = &g_entities[level.sortedClients[j]]; if (!ent2->inuse || ent2 == ent) { continue; } // players are sometimes of type ET_GENERAL if (ent2->s.eType != ET_PLAYER) { continue; } if (ent2->client->sess.sessionTeam == TEAM_SPECTATOR) { continue; } if (ent2->health <= 0 || ent2->client->sess.sessionTeam == ent->client->sess.sessionTeam || !ent2->client->ps.powerups[PW_OPS_DISGUISED]) { continue; } VectorCopy(ent2->client->ps.origin, pos[0]); VectorCopy(ent2->client->ps.mins, pos[1]); VectorCopy(ent2->client->ps.maxs, pos[2]); if (G_VisibleFromBinoculars_Box(ent, ent2, pos[0], pos[1], pos[2])) { G_UpdateTeamMapData_DisguisedPlayer(ent, ent2, f1, f2); } } } else if (ent->client->sess.playerType == PC_COVERTOPS) { vec3_t pos[3]; G_SetupFrustum(ent); for (j = 0; j < level.numConnectedClients; j++) { ent2 = &g_entities[level.sortedClients[j]]; if (!ent2->inuse || ent2 == ent) { continue; } // players are sometimes of type ET_GENERAL if (ent2->s.eType != ET_PLAYER) { continue; } // no spectators thanks if (ent2->client->sess.sessionTeam == TEAM_SPECTATOR || ent2->client->sess.sessionTeam == TEAM_FREE) { continue; } // do not add 'dead' players if (ent2->health <= 0) { continue; } // we will only add other team members here if (ent2->client->sess.sessionTeam == ent->client->sess.sessionTeam) { continue; } VectorCopy(ent2->client->ps.origin, pos[0]); VectorCopy(ent2->client->ps.mins, pos[1]); VectorCopy(ent2->client->ps.maxs, pos[2]); if (G_VisibleFromBinoculars_Box(ent, ent2, pos[0], pos[1], pos[2])) { G_UpdateTeamMapData_Player(ent2, f1, f2); } } } } }
/* =========== ClientDisconnect Called when a player drops from the server. Will not be called between levels. This should NOT be called directly by any game logic, call trap_DropClient(), which will call this and do server system housekeeping. ============ */ void ClientDisconnect(int clientNum) { gentity_t *ent; gentity_t *flag = NULL; gitem_t *item = NULL; vec3_t launchvel; int i; ent = g_entities + clientNum; if (!ent->client) { return; } G_RemoveClientFromFireteams(clientNum, qtrue, qfalse); G_RemoveFromAllIgnoreLists(clientNum); G_LeaveTank(ent, qfalse); // Nico, remove the client from all specInvited lists for (i = 0; i < level.numConnectedClients; ++i) { COM_BitClear(level.clients[level.sortedClients[i]].sess.specInvitedClients, clientNum); } // stop any following clients for (i = 0 ; i < level.numConnectedClients ; i++) { flag = g_entities + level.sortedClients[i]; if (flag->client->sess.sessionTeam == TEAM_SPECTATOR && flag->client->sess.spectatorState == SPECTATOR_FOLLOW && flag->client->sess.spectatorClient == clientNum) { StopFollowing(flag); } if (flag->client->ps.pm_flags & PMF_LIMBO && flag->client->sess.spectatorClient == clientNum) { Cmd_FollowCycle_f(flag, 1); } } G_FadeItems(ent, MOD_SATCHEL); // remove ourself from teamlists { mapEntityData_t *mEnt; mapEntityData_Team_t *teamList; for (i = 0; i < 2; i++) { teamList = &mapEntityData[i]; if ((mEnt = G_FindMapEntityData(&mapEntityData[0], ent - g_entities)) != NULL) { G_FreeMapEntityData(teamList, mEnt); } mEnt = G_FindMapEntityDataSingleClient(teamList, NULL, ent->s.number, -1); while (mEnt) { mapEntityData_t *mEntFree = mEnt; mEnt = G_FindMapEntityDataSingleClient(teamList, mEnt, ent->s.number, -1); G_FreeMapEntityData(teamList, mEntFree); } } } // send effect if they were completely connected if (ent->client->pers.connected == CON_CONNECTED && ent->client->sess.sessionTeam != TEAM_SPECTATOR && !(ent->client->ps.pm_flags & PMF_LIMBO)) { // They don't get to take powerups with them! // Especially important for stuff like CTF flags // New code for tossing flags if (ent->client->ps.powerups[PW_REDFLAG]) { item = BG_FindItem("Red Flag"); if (!item) { item = BG_FindItem("Objective"); } ent->client->ps.powerups[PW_REDFLAG] = 0; } if (ent->client->ps.powerups[PW_BLUEFLAG]) { item = BG_FindItem("Blue Flag"); if (!item) { item = BG_FindItem("Objective"); } ent->client->ps.powerups[PW_BLUEFLAG] = 0; } if (item) { // OSP - fix for suicide drop exploit through walls/gates launchvel[0] = 0; //crandom()*20; launchvel[1] = 0; //crandom()*20; launchvel[2] = 0; //10+random()*10; flag = LaunchItem(item, ent->r.currentOrigin, launchvel, ent - g_entities); flag->s.modelindex2 = ent->s.otherEntityNum2; // JPW NERVE FIXME set player->otherentitynum2 with old modelindex2 from flag and restore here flag->message = ent->message; // DHM - Nerve :: also restore item name // Clear out player's temp copies ent->s.otherEntityNum2 = 0; ent->message = NULL; } } G_LogPrintf("ClientDisconnect: %i\n", clientNum); trap_UnlinkEntity(ent); ent->s.modelindex = 0; ent->inuse = qfalse; ent->classname = "disconnected"; ent->client->pers.connected = CON_DISCONNECTED; ent->client->ps.persistant[PERS_TEAM] = TEAM_FREE; i = ent->client->sess.sessionTeam; ent->client->sess.sessionTeam = TEAM_FREE; ent->active = 0; trap_SetConfigstring(CS_PLAYERS + clientNum, ""); CalculateRanks(); }
void G_UpdateTeamMapData(void) { int i, j; gentity_t *ent, *ent2; mapEntityData_t *mEnt; if (level.time - level.lastMapEntityUpdate < 500) { return; } level.lastMapEntityUpdate = level.time; for (i = 0, ent = g_entities; i < level.num_entities; i++, ent++) { if (!ent->inuse) { continue; } switch (ent->s.eType) { case ET_PLAYER: G_UpdateTeamMapData_Player(ent, qfalse, qfalse); for (j = 0; j < 2; j++) { mapEntityData_Team_t *teamList = &mapEntityData[j]; mEnt = G_FindMapEntityDataSingleClient(teamList, NULL, ent->s.number, -1); while (mEnt) { VectorCopy(ent->client->ps.origin, mEnt->org); mEnt->yaw = ent->client->ps.viewangles[YAW]; mEnt = G_FindMapEntityDataSingleClient(teamList, mEnt, ent->s.number, -1); } } break; case ET_CONSTRUCTIBLE_INDICATOR: if (ent->parent && ent->parent->entstate == STATE_DEFAULT) { G_UpdateTeamMapData_Construct(ent); } break; case ET_EXPLOSIVE_INDICATOR: if (ent->parent && ent->parent->entstate == STATE_DEFAULT) { G_UpdateTeamMapData_Destruct(ent); } break; case ET_TANK_INDICATOR: case ET_TANK_INDICATOR_DEAD: G_UpdateTeamMapData_Tank(ent); break; case ET_MISSILE: break; case ET_COMMANDMAP_MARKER: G_UpdateTeamMapData_CommandmapMarker(ent); break; default: break; } } for (i = 0, ent = g_entities; i < level.num_entities; i++, ent++) { qboolean f1, f2; if (!ent->inuse || !ent->client) { continue; } if (ent->client->sess.playerType == PC_COVERTOPS && ent->health > 0) { f1 = ent->client->sess.sessionTeam == TEAM_ALLIES ? qtrue : qfalse; f2 = ent->client->sess.sessionTeam == TEAM_AXIS ? qtrue : qfalse; G_SetupFrustum(ent); for (j = 0, ent2 = g_entities; j < level.num_entities; j++, ent2++) { if (!ent2->inuse || ent2 == ent) { continue; } switch (ent2->s.eType) { case ET_PLAYER: { vec3_t pos[3]; VectorCopy(ent2->client->ps.origin, pos[0]); pos[0][2] += ent2->client->ps.mins[2]; VectorCopy(ent2->client->ps.origin, pos[1]); VectorCopy(ent2->client->ps.origin, pos[2]); pos[2][2] += ent2->client->ps.maxs[2]; if (ent2->health > 0 && (G_VisibleFromBinoculars(ent, ent2, pos[0]) || G_VisibleFromBinoculars(ent, ent2, pos[1]) || G_VisibleFromBinoculars(ent, ent2, pos[2]))) { if (ent2->client->sess.sessionTeam != ent->client->sess.sessionTeam) { int k; switch (ent2->client->sess.sessionTeam) { case TEAM_AXIS: mEnt = G_FindMapEntityData(&mapEntityData[0], ent2 - g_entities); if (mEnt && level.time - mEnt->startTime > 5000) { for (k = 0; k < MAX_CLIENTS; k++) { if (g_entities[k].inuse && g_entities[k].client && g_entities[k].client->sess.sessionTeam == ent->client->sess.sessionTeam) { trap_SendServerCommand(k, va("tt \"ENEMY SPOTTED <STOP> CHECK COMMAND MAP FOR DETAILS <STOP>\"\n")); } } } break; case TEAM_ALLIES: mEnt = G_FindMapEntityData(&mapEntityData[1], ent2 - g_entities); if (mEnt && level.time - mEnt->startTime > 5000) { for (k = 0; k < MAX_CLIENTS; k++) { if (g_entities[k].inuse && g_entities[k].client && g_entities[k].client->sess.sessionTeam == ent->client->sess.sessionTeam) { trap_SendServerCommand(k, va("tt \"ENEMY SPOTTED <STOP> CHECK COMMAND MAP FOR DETAILS <STOP>\"\n")); } } } break; default: break; } } G_UpdateTeamMapData_Player(ent2, f1, f2); } break; } default: break; } } if (ent->client->ps.eFlags & EF_ZOOMING) { G_SetupFrustum_ForBinoculars(ent); for (j = 0, ent2 = g_entities; j < level.num_entities; j++, ent2++) { if (!ent2->inuse || ent2 == ent) { continue; } switch (ent2->s.eType) { case ET_MISSILE: break; default: break; } } } } } }