/* ================== G_LeaveTeam ================== */ void G_LeaveTeam( gentity_t *self ) { team_t team = self->client->pers.teamSelection; gentity_t *ent; int i; if ( team == TEAM_ALIENS ) { G_RemoveFromSpawnQueue( &level.alienSpawnQueue, self->client->ps.clientNum ); } else if ( team == TEAM_HUMANS ) { G_RemoveFromSpawnQueue( &level.humanSpawnQueue, self->client->ps.clientNum ); } else { if ( self->client->sess.spectatorState == SPECTATOR_FOLLOW ) { G_StopFollowing( self ); } return; } // stop any following clients G_StopFromFollowing( self ); G_Vote( self, team, qfalse ); self->suicideTime = 0; for ( i = 0; i < level.num_entities; i++ ) { ent = &g_entities[ i ]; if ( !ent->inuse ) { continue; } if ( ent->client && ent->client->pers.connected == CON_CONNECTED ) { // cure poison if ( ent->client->ps.stats[ STAT_STATE ] & SS_POISONED && ent->client->lastPoisonClient == self ) { ent->client->ps.stats[ STAT_STATE ] &= ~SS_POISONED; } } else if ( ent->s.eType == ET_MISSILE && ent->r.ownerNum == self->s.number ) { G_FreeEntity( ent ); } } // cut all relevant zap beams G_ClearPlayerZapEffects( self ); G_namelog_update_score( self->client ); }
void G_BotSpectatorThink( gentity_t *self ) { char buf[MAX_STRING_CHARS]; //hacky ping fix self->client->ps.ping = rand() % 50 + 50; //acknowledge recieved console messages //MUST be done while ( trap_BotGetServerCommand( self->client->ps.clientNum, buf, sizeof( buf ) ) ); if ( self->client->ps.pm_flags & PMF_QUEUED ) { //we're queued to spawn, all good //check for humans in the spawn que { spawnQueue_t *sq; if ( self->client->pers.team != TEAM_NONE ) { sq = &level.team[ self->client->pers.team ].spawnQueue; } else { sq = nullptr; } if ( sq && PlayersBehindBotInSpawnQueue( self ) ) { G_RemoveFromSpawnQueue( sq, self->s.number ); G_PushSpawnQueue( sq, self->s.number ); } } return; } //reset stuff BotSetTarget( &self->botMind->goal, nullptr, nullptr ); self->botMind->bestEnemy.ent = nullptr; BotResetEnemyQueue( &self->botMind->enemyQueue ); self->botMind->currentNode = nullptr; memset( &self->botMind->nav, 0, sizeof( self->botMind->nav ) ); self->botMind->futureAimTime = 0; self->botMind->futureAimTimeInterval = 0; self->botMind->numRunningNodes = 0; memset( self->botMind->runningNodes, 0, sizeof( self->botMind->runningNodes ) ); if ( self->client->sess.restartTeam == TEAM_NONE ) { int teamnum = self->client->pers.team; int clientNum = self->client->ps.clientNum; if ( teamnum == TEAM_HUMANS ) { self->client->pers.classSelection = PCL_HUMAN_NAKED; self->client->ps.stats[STAT_CLASS] = PCL_HUMAN_NAKED; BotSetNavmesh( self, PCL_HUMAN_NAKED ); //we want to spawn with rifle unless it is disabled or we need to build if ( g_bot_rifle.integer ) { self->client->pers.humanItemSelection = WP_MACHINEGUN; } else { self->client->pers.humanItemSelection = WP_HBUILD; } } else if ( teamnum == TEAM_ALIENS ) { self->client->pers.classSelection = PCL_ALIEN_LEVEL0; self->client->ps.stats[STAT_CLASS] = PCL_ALIEN_LEVEL0; BotSetNavmesh( self, PCL_ALIEN_LEVEL0 ); } G_PushSpawnQueue( &level.team[ teamnum ].spawnQueue, clientNum ); } }
/* ================= SpectatorThink ================= */ void SpectatorThink( gentity_t *ent, usercmd_t *ucmd ) { pmove_t pm; gclient_t *client; client = ent->client; client->oldbuttons = client->buttons; client->buttons = ucmd->buttons; if( client->sess.spectatorState != SPECTATOR_FOLLOW ) { if( client->sess.spectatorState == SPECTATOR_LOCKED ) client->ps.pm_type = PM_FREEZE; else client->ps.pm_type = PM_SPECTATOR; client->ps.speed = BG_FindSpeedForClass( client->ps.stats[ STAT_PCLASS ] ); client->ps.stats[ STAT_STAMINA ] = 0; client->ps.stats[ STAT_MISC ] = 0; client->ps.stats[ STAT_BUILDABLE ] = 0; client->ps.stats[ STAT_PCLASS ] = PCL_NONE; client->ps.weapon = WP_NONE; // set up for pmove memset( &pm, 0, sizeof( pm ) ); pm.ps = &client->ps; pm.cmd = *ucmd; pm.tracemask = MASK_PLAYERSOLID & ~CONTENTS_BODY; // spectators can fly through bodies pm.trace = trap_Trace; pm.pointcontents = trap_PointContents; // perform a pmove Pmove( &pm ); // save results of pmove VectorCopy( client->ps.origin, ent->s.origin ); G_TouchTriggers( ent ); trap_UnlinkEntity( ent ); if( ( client->buttons & BUTTON_ATTACK ) && !( client->oldbuttons & BUTTON_ATTACK ) ) { //if waiting in a queue remove from the queue if( client->ps.pm_flags & PMF_QUEUED ) { if( client->ps.stats[ STAT_PTEAM ] == PTE_ALIENS ) G_RemoveFromSpawnQueue( &level.alienSpawnQueue, client->ps.clientNum ); else if( client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS ) G_RemoveFromSpawnQueue( &level.humanSpawnQueue, client->ps.clientNum ); client->pers.classSelection = PCL_NONE; client->ps.stats[ STAT_PCLASS ] = PCL_NONE; } else if( client->pers.classSelection == PCL_NONE ) { if( client->pers.teamSelection == PTE_NONE ) G_TriggerMenu( client->ps.clientNum, MN_TEAM ); else if( client->pers.teamSelection == PTE_ALIENS ) G_TriggerMenu( client->ps.clientNum, MN_A_CLASS ); else if( client->pers.teamSelection == PTE_HUMANS ) G_TriggerMenu( client->ps.clientNum, MN_H_SPAWN ); } } //set the queue position for the client side if( client->ps.pm_flags & PMF_QUEUED ) { if( client->ps.stats[ STAT_PTEAM ] == PTE_ALIENS ) { client->ps.persistant[ PERS_QUEUEPOS ] = G_GetPosInSpawnQueue( &level.alienSpawnQueue, client->ps.clientNum ); } else if( client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS ) { client->ps.persistant[ PERS_QUEUEPOS ] = G_GetPosInSpawnQueue( &level.humanSpawnQueue, client->ps.clientNum ); } } } if( ( client->buttons & BUTTON_USE_HOLDABLE ) && !( client->oldbuttons & BUTTON_USE_HOLDABLE ) ) Cmd_Follow_f( ent, qtrue ); }
void G_LeaveTeam( gentity_t *self ) { team_t team = (team_t) self->client->pers.team; gentity_t *ent; int i; #ifdef UNREALARENA if ( TEAM_Q == team || TEAM_U == team ) #else if ( TEAM_ALIENS == team || TEAM_HUMANS == team ) #endif { G_RemoveFromSpawnQueue( &level.team[ team ].spawnQueue, self->client->ps.clientNum ); } else { if ( self->client->sess.spectatorState == SPECTATOR_FOLLOW ) { G_StopFollowing( self ); } return; } // stop any following clients G_StopFromFollowing( self ); G_Vote( self, team, false ); #ifndef UNREALARENA self->suicideTime = 0; #endif for ( i = 0; i < level.num_entities; i++ ) { ent = &g_entities[ i ]; if ( !ent->inuse ) { continue; } if ( ent->client && ent->client->pers.connected == CON_CONNECTED ) { #ifndef UNREALARENA // cure poison if ( ( ent->client->ps.stats[ STAT_STATE ] & SS_POISONED ) && ent->client->lastPoisonClient == self ) { ent->client->ps.stats[ STAT_STATE ] &= ~SS_POISONED; } #endif } else if ( ent->s.eType == entityType_t::ET_MISSILE && ent->r.ownerNum == self->s.number ) { G_FreeEntity( ent ); } } // cut all relevant zap beams G_ClearPlayerZapEffects( self ); Beacon::DeleteTags( self ); Beacon::RemoveOrphaned( self->s.number ); G_namelog_update_score( self->client ); }