void G_PlayerAward( edict_t *ent, const char *awardMsg ) { edict_t *other; char cmd[MAX_STRING_CHARS]; gameaward_t *ga; int i, size; score_stats_t *stats; if( !awardMsg || !awardMsg[0] || !ent->r.client ) return; Q_snprintfz( cmd, sizeof( cmd ), "aw \"%s\"", awardMsg ); trap_GameCmd( ent, cmd ); if( dedicated->integer ) G_Printf( "%s", COM_RemoveColorTokens( va( "%s receives a '%s' award.\n", ent->r.client->netname, awardMsg ) ) ); ent->r.client->level.stats.awards++; teamlist[ent->s.team].stats.awards++; G_Gametype_ScoreEvent( ent->r.client, "award", awardMsg ); stats = &ent->r.client->level.stats; if( !stats->awardAllocator ) stats->awardAllocator = LinearAllocator( sizeof( gameaward_t ), 0, _G_LevelMalloc, _G_LevelFree ); // ch : this doesnt work for race right? if( GS_MatchState() == MATCH_STATE_PLAYTIME || GS_MatchState() == MATCH_STATE_POSTMATCH ) { // ch : we store this locally to send to MM // first check if we already have this one on the clients list size = LA_Size( stats->awardAllocator ); ga = NULL; for( i = 0; i < size; i++ ) { ga = ( gameaward_t * )LA_Pointer( stats->awardAllocator, i ); if( !strncmp( ga->name, awardMsg, sizeof(ga->name)-1 ) ) break; } if( i >= size ) { ga = ( gameaward_t * )LA_Alloc( stats->awardAllocator ); memset( ga, 0, sizeof(*ga) ); ga->name = G_RegisterLevelString( awardMsg ); } if( ga ) ga->count++; } // add it to every player who's chasing this player for( other = game.edicts + 1; PLAYERNUM( other ) < gs.maxclients; other++ ) { if( !other->r.client || !other->r.inuse || !other->r.client->resp.chase.active ) continue; if( other->r.client->resp.chase.target == ENTNUM( ent ) ) trap_GameCmd( other, cmd ); } }
/* * G_Match_NotReady */ void G_Match_NotReady( edict_t *ent ) { if( ent->s.team == TEAM_SPECTATOR ) { G_PrintMsg( ent, "Join the game first\n" ); return; } if( GS_MatchState() != MATCH_STATE_WARMUP && GS_MatchState() != MATCH_STATE_COUNTDOWN ) { G_PrintMsg( ent, "A match is not being setup.\n" ); return; } if( !level.ready[PLAYERNUM( ent )] ) { G_PrintMsg( ent, "You weren't ready.\n" ); return; } level.ready[PLAYERNUM( ent )] = false; G_PrintMsg( NULL, "%s%s is no longer ready.\n", ent->r.client->netname, S_COLOR_WHITE ); G_UpdatePlayerMatchMsg( ent ); G_Match_CheckReadys(); }
static void G_Gametype_GENERIC_ThinkRules( void ) { if( G_Match_ScorelimitHit() || G_Match_TimelimitHit() || G_Match_SuddenDeathFinished() ) G_Match_LaunchState( GS_MatchState() + 1 ); if( GS_MatchState() >= MATCH_STATE_POSTMATCH ) return; }
/* * G_Teams_ExecuteChallengersQueue */ void G_Teams_ExecuteChallengersQueue( void ) { edict_t *ent; edict_t **challengers; bool restartmatch = false; // Medar fixme: this is only really makes sense, if playerlimit per team is one if( GS_MatchState() == MATCH_STATE_PLAYTIME ) return; if( !GS_HasChallengers() ) return; if( game.realtime < level.spawnedTimeStamp + G_CHALLENGERS_MIN_JOINTEAM_MAPTIME ) { static int time, lasttime; time = (int)( ( G_CHALLENGERS_MIN_JOINTEAM_MAPTIME - ( game.realtime - level.spawnedTimeStamp ) )*0.001 ); if( lasttime && time == lasttime ) return; lasttime = time; if( lasttime ) G_CenterPrintFormatMsg( NULL, "Waiting... %s", va( "%i", lasttime ), NULL ); else G_CenterPrintMsg( NULL, "" ); return; } // pick players in join order and try to put them in the // game until we get the first refused one. challengers = G_Teams_ChallengersQueue(); if( challengers ) { int i; for( i = 0; challengers[i]; i++ ) { ent = challengers[i]; if( !G_Teams_JoinAnyTeam( ent, true ) ) break; // if we successfully execute the challengers queue during the countdown, revert to warmup if( GS_MatchState() == MATCH_STATE_COUNTDOWN ) { restartmatch = true; } } } if( restartmatch == true ) { G_Match_Autorecord_Cancel(); G_Match_LaunchState( MATCH_STATE_WARMUP ); } }
static bool G_Gametype_GENERIC_MatchStateFinished( int incomingMatchState ) { if( GS_MatchState() <= MATCH_STATE_WARMUP && incomingMatchState > MATCH_STATE_WARMUP && incomingMatchState < MATCH_STATE_POSTMATCH ) G_Match_Autorecord_Start(); if( GS_MatchState() == MATCH_STATE_POSTMATCH ) G_Match_Autorecord_Stop(); return true; }
static void G_Gametype_GENERIC_ThinkRules( void ) { if( G_Match_ScorelimitHit() || G_Match_TimelimitHit() || G_Match_SuddenDeathFinished() ) { G_CenterPrintMsg( NULL, "ENDOOOOOOOOOOOOOOOOO saaaaan!!!!!!!!!!\n" ); G_Match_LaunchState( GS_MatchState() + 1 ); } if( GS_MatchState() >= MATCH_STATE_POSTMATCH ) return; }
/* * ClientDisconnect * Called when a player drops from the server. * Will not be called between levels. */ void ClientDisconnect( edict_t *ent, const char *reason ) { int team; if( !ent->r.client || !ent->r.inuse ) return; // always report in RACE mode if( GS_RaceGametype() || ( ent->r.client->team != TEAM_SPECTATOR && ( GS_MatchState() == MATCH_STATE_PLAYTIME || GS_MatchState() == MATCH_STATE_POSTMATCH ) ) ) G_AddPlayerReport( ent, GS_MatchState() == MATCH_STATE_POSTMATCH ); for( team = TEAM_PLAYERS; team < GS_MAX_TEAMS; team++ ) G_Teams_UnInvitePlayer( team, ent ); if( !level.gametype.disableObituaries || !(ent->r.svflags & SVF_FAKECLIENT ) ) { if( !reason ) G_PrintMsg( NULL, "%s" S_COLOR_WHITE " disconnected\n", ent->r.client->netname ); else G_PrintMsg( NULL, "%s" S_COLOR_WHITE " disconnected (%s" S_COLOR_WHITE ")\n", ent->r.client->netname, reason ); } // send effect if( ent->s.team > TEAM_SPECTATOR ) G_TeleportEffect( ent, false ); ent->r.client->team = TEAM_SPECTATOR; G_ClientRespawn( ent, true ); // respawn as ghost ent->movetype = MOVETYPE_NOCLIP; // allow freefly // let the gametype scripts know this client just disconnected G_Gametype_ScoreEvent( ent->r.client, "disconnect", NULL ); G_FreeAI( ent ); AI_EnemyRemoved( ent ); ent->r.inuse = false; ent->r.svflags = SVF_NOCLIENT; memset( ent->r.client, 0, sizeof( *ent->r.client ) ); ent->r.client->ps.playerNum = PLAYERNUM( ent ); trap_ConfigString( CS_PLAYERINFOS+PLAYERNUM( ent ), "" ); GClip_UnlinkEntity( ent ); G_Match_CheckReadys(); }
/* * Cmd_Say_f */ void Cmd_Say_f( edict_t *ent, bool arg0, bool checkflood ) { char *p; char text[2048]; size_t arg0len = 0; #ifdef AUTHED_SAY if( sv_mm_enable->integer && ent->r.client && ent->r.client->mm_session <= 0 ) { // unauthed players are only allowed to chat to public at non play-time if( GS_MatchState() == MATCH_STATE_PLAYTIME ) { G_PrintMsg( ent, "%s", S_COLOR_YELLOW "You must authenticate to be able to communicate to other players during the match.\n"); return; } } #endif if( checkflood ) { if( CheckFlood( ent, false ) ) return; } if( ent->r.client && ( ent->r.client->muted & 1 ) ) return; if( trap_Cmd_Argc() < 2 && !arg0 ) return; text[0] = 0; if( arg0 ) { Q_strncatz( text, trap_Cmd_Argv( 0 ), sizeof( text ) ); Q_strncatz( text, " ", sizeof( text ) ); arg0len = strlen( text ); Q_strncatz( text, trap_Cmd_Args(), sizeof( text ) ); } else { p = trap_Cmd_Args(); if( *p == '"' ) { if( p[strlen( p )-1] == '"' ) p[strlen( p )-1] = 0; p++; } Q_strncatz( text, p, sizeof( text ) ); } // don't let text be too long for malicious reasons text[arg0len + (MAX_CHAT_BYTES - 1)] = 0; if( !Q_stricmp( text, "gg" ) || !Q_stricmp( text, "good game" ) ) G_AwardFairPlay( ent ); G_ChatMsg( NULL, ent, false, "%s", text ); }
void SetRespawn( edict_t *ent, int delay ) { if( !ent->item ) return; if( delay < 0 ) { G_FreeEdict( ent ); return; } ent->r.solid = SOLID_NOT; ent->nextThink = level.time + delay; ent->think = DoRespawn; if( GS_MatchState() == MATCH_STATE_WARMUP ) { ent->s.effects |= EF_GHOST; } else { ent->r.svflags |= SVF_NOCLIENT; } // megahealth is different if( ( ent->spawnflags & ITEM_TIMED ) && ent->r.owner ) { if( ent->item->type == IT_HEALTH ) { ent->think = MegaHealth_think; ent->nextThink = level.time + 1; } } GClip_LinkEntity( ent ); }
void G_AwardFairPlay( edict_t *ent ) { // only award during postmatch if( GS_MatchState() != MATCH_STATE_POSTMATCH ) { return; } if( level.finalMatchDuration <= SIGNIFICANT_MATCH_DURATION ) { return; } gclient_t *client = ent->r.client; // don't try to give the award to the server console if( !client ) { return; } // already awarded if( client->resp.awardInfo.fairplay_award ) { return; } // the player must not be muted during the match if( client->level.stats.muted_count > 0 ) { return; } // has he actually played? if( !client->level.stats.had_playtime ) { return; } client->level.stats.fairplay_count++; client->resp.awardInfo.fairplay_award = true; G_PlayerAward( ent, S_COLOR_CYAN "Fair Play!" ); }
/* * G_Teams_SetTeam - sets clients team without any checking */ void G_Teams_SetTeam( edict_t *ent, int team ) { assert( ent && ent->r.inuse && ent->r.client ); assert( team >= TEAM_SPECTATOR && team < GS_MAX_TEAMS ); // if player was on a team, send partial report to matchmaker if( ent->r.client->team != TEAM_SPECTATOR && ent->r.client->team != team && GS_MatchState() == MATCH_STATE_PLAYTIME ) { G_Printf("Sending teamchange to MM, team %d to team %d\n", ent->r.client->team, team ); G_AddPlayerReport( ent, false ); // trap_MR_SendPartialReport(); } // clear scores at changing team memset( &ent->r.client->level.stats, 0, sizeof( ent->r.client->level.stats ) ); memset( &ent->r.client->teamstate, 0, sizeof( ent->r.client->teamstate ) ); ent->r.client->team = team; ent->r.client->teamstate.timeStamp = level.time; G_Teams_UnInvitePlayer( team, ent ); G_ClientRespawn( ent, true ); // make ghost using G_ClientRespawn so team is updated at ghosting G_SpawnQueue_AddClient( ent ); level.ready[PLAYERNUM( ent )] = false; G_Match_CheckReadys(); G_UpdatePlayerMatchMsg( ent ); }
/* * G_Match_ScorelimitHit */ bool G_Match_ScorelimitHit( void ) { edict_t *e; if( GS_MatchState() != MATCH_STATE_PLAYTIME ) return false; if( g_scorelimit->integer ) { if( !GS_TeamBasedGametype() ) { for( e = game.edicts+1; PLAYERNUM( e ) < gs.maxclients; e++ ) { if( !e->r.inuse ) continue; if( e->r.client->level.stats.score >= g_scorelimit->integer ) return true; } } else { int team; for( team = TEAM_ALPHA; team < GS_MAX_TEAMS; team++ ) { if( teamlist[team].stats.score >= g_scorelimit->integer ) return true; } } } return false; }
/* * G_Match_Ready */ void G_Match_Ready( edict_t *ent ) { if( ent->r.svflags & SVF_FAKECLIENT && level.ready[PLAYERNUM( ent )] == true ) return; if( ent->s.team == TEAM_SPECTATOR ) { G_PrintMsg( ent, "Join the game first\n" ); return; } if( GS_MatchState() != MATCH_STATE_WARMUP ) { if( !( ent->r.svflags & SVF_FAKECLIENT ) ) G_PrintMsg( ent, "We're not in warmup.\n" ); return; } if( level.ready[PLAYERNUM( ent )] ) { G_PrintMsg( ent, "You are already ready.\n" ); return; } level.ready[PLAYERNUM( ent )] = true; G_PrintMsg( NULL, "%s%s is ready!\n", ent->r.client->netname, S_COLOR_WHITE ); G_UpdatePlayerMatchMsg( ent ); G_Match_CheckReadys(); }
/* * G_Match_TimelimitHit */ bool G_Match_TimelimitHit( void ) { // check for timelimit hit if( !GS_MatchDuration() || game.serverTime < GS_MatchEndTime() ) return false; if( GS_MatchState() == MATCH_STATE_WARMUP ) level.forceStart = true; // force match starting when timelimit is up, even if someone goes unready if( GS_MatchState() == MATCH_STATE_WAITEXIT ) { level.exitNow = true; return false; // don't advance into next state. The match will be restarted } return true; }
/* * G_ClientEndSnapFrame * * Called for each player at the end of the server frame * and right after spawning */ void G_ClientEndSnapFrame( edict_t *ent ) { gclient_t *client; int i; if( trap_GetClientState( PLAYERNUM( ent ) ) < CS_SPAWNED ) return; client = ent->r.client; // set fov if( !client->ps.pmove.stats[PM_STAT_ZOOMTIME] ) client->ps.fov = ent->r.client->fov; else { float frac = (float)client->ps.pmove.stats[PM_STAT_ZOOMTIME] / (float)ZOOMTIME; client->ps.fov = client->fov - ( (float)( client->fov - client->zoomfov ) * frac ); } // If the end of unit layout is displayed, don't give // the player any normal movement attributes if( GS_MatchState() >= MATCH_STATE_POSTMATCH ) { G_SetClientStats( ent ); } else { if( G_IsDead( ent ) && !level.gametype.customDeadBodyCam ) { G_Client_DeadView( ent ); } G_PlayerWorldEffects( ent ); // burn from lava, etc G_ClientDamageFeedback( ent ); // show damage taken along the snap G_SetClientStats( ent ); G_SetClientEffects( ent ); G_SetClientSound( ent ); G_SetClientFrame( ent ); client->ps.plrkeys = client->resp.snap.plrkeys; } G_ReleaseClientPSEvent( client ); // set the delta angle for( i = 0; i < 3; i++ ) client->ps.pmove.delta_angles[i] = ANGLE2SHORT( client->ps.viewangles[i] ) - client->ucmd.angles[i]; // this is pretty hackish. We exploit the fact that servers *do not* transmit // origin2/old_origin for ET_PLAYER/ET_CORPSE entities, and we use it for sending the player velocity if( !G_ISGHOSTING( ent ) ) { ent->r.svflags |= SVF_TRANSMITORIGIN2; VectorCopy( ent->velocity, ent->s.origin2 ); } else ent->r.svflags &= ~SVF_TRANSMITORIGIN2; }
void G_Gametype_GENERIC_ClientRespawn( edict_t *self, int old_team, int new_team ) { int i; gclient_t *client = self->r.client; gs_weapon_definition_t *weapondef; if( G_ISGHOSTING( self ) ) return; //give default items if( self->s.team != TEAM_SPECTATOR ) { if( GS_Instagib() ) { client->ps.inventory[WEAP_INSTAGUN] = 1; client->ps.inventory[AMMO_INSTAS] = 1; client->ps.inventory[AMMO_WEAK_INSTAS] = 1; } else { if( GS_MatchState() <= MATCH_STATE_WARMUP ) { for( i = WEAP_GUNBLADE; i < WEAP_TOTAL; i++ ) { if( i == WEAP_INSTAGUN ) // dont add instagun... continue; weapondef = GS_GetWeaponDef( i ); client->ps.inventory[i] = 1; if( weapondef->firedef_weak.ammo_id ) client->ps.inventory[weapondef->firedef_weak.ammo_id] = weapondef->firedef_weak.ammo_max; if( weapondef->firedef.ammo_id ) client->ps.inventory[weapondef->firedef.ammo_id] = weapondef->firedef.ammo_max; } client->resp.armor = GS_Armor_MaxCountForTag( ARMOR_YA ); } else { weapondef = GS_GetWeaponDef( WEAP_GUNBLADE ); client->ps.inventory[WEAP_GUNBLADE] = 1; client->ps.inventory[AMMO_GUNBLADE] = weapondef->firedef.ammo_max;; client->ps.inventory[AMMO_WEAK_GUNBLADE] = 0; } } } // select rocket launcher if available if( GS_CheckAmmoInWeapon( &client->ps, WEAP_ROCKETLAUNCHER ) ) client->ps.stats[STAT_PENDING_WEAPON] = WEAP_ROCKETLAUNCHER; else client->ps.stats[STAT_PENDING_WEAPON] = GS_SelectBestWeapon( &client->ps ); // add a teleportation effect if( self->r.solid != SOLID_NOT ) G_RespawnEffect( self ); }
/* * G_GameTypes_DenyJoinTeam */ static int G_GameTypes_DenyJoinTeam( edict_t *ent, int team ) { if( team < 0 || team >= GS_MAX_TEAMS ) { G_Printf( "WARNING: 'G_GameTypes_CanJoinTeam' parsing a unrecognized team value\n" ); return ER_TEAM_INVALID; } if( team == TEAM_SPECTATOR ) return ER_TEAM_OK; if( GS_MatchState() > MATCH_STATE_PLAYTIME ) return ER_TEAM_MATCHSTATE; // waiting for chanllengers queue to be executed if( GS_HasChallengers() && game.realtime < level.spawnedTimeStamp + (unsigned)( G_CHALLENGERS_MIN_JOINTEAM_MAPTIME + game.snapFrameTime ) ) return ER_TEAM_CHALLENGERS; // force eveyone to go through queue so things work on map change if( GS_HasChallengers() && !ent->r.client->queueTimeStamp ) return ER_TEAM_CHALLENGERS; //see if team is locked if( G_Teams_TeamIsLocked( team ) && !G_Teams_PlayerIsInvited( team, ent ) ) return ER_TEAM_LOCKED; if( GS_TeamBasedGametype() ) { if( team >= TEAM_ALPHA && team < GS_MAX_TEAMS ) { // see if team is full int count = teamlist[team].numplayers; if( ( count + 1 > level.gametype.maxPlayersPerTeam && level.gametype.maxPlayersPerTeam > 0 ) || ( count + 1 > g_teams_maxplayers->integer && g_teams_maxplayers->integer > 0 ) ) return ER_TEAM_FULL; if( !g_teams_allow_uneven->integer && !G_Teams_CanKeepEvenTeam( ent->s.team, team ) ) return ER_TEAM_UNEVEN; return ER_TEAM_OK; } else { return ER_TEAM_INVALID; } } else if( team == TEAM_PLAYERS ) { return ER_TEAM_OK; } return ER_TEAM_INVALID; }
/* * SelectSpawnPoint * * Chooses a player start, deathmatch start, etc */ void SelectSpawnPoint( edict_t *ent, edict_t **spawnpoint, vec3_t origin, vec3_t angles ) { edict_t *spot = NULL; if( GS_MatchState() >= MATCH_STATE_POSTMATCH ) { spot = G_SelectIntermissionSpawnPoint(); } else { if( game.asEngine != NULL ) spot = GT_asCallSelectSpawnPoint( ent ); if( !spot ) spot = SelectDeathmatchSpawnPoint( ent ); } // find a single player start spot if( !spot ) { spot = G_Find( spot, FOFS( classname ), "info_player_start" ); if( !spot ) { spot = G_Find( spot, FOFS( classname ), "team_CTF_alphaspawn" ); if( !spot ) spot = G_Find( spot, FOFS( classname ), "team_CTF_betaspawn" ); if( !spot ) spot = world; } } *spawnpoint = spot; VectorCopy( spot->s.origin, origin ); VectorCopy( spot->s.angles, angles ); if( !Q_stricmp( spot->classname, "info_player_intermission" ) ) { // if it has a target, look towards it if( spot->target ) { vec3_t dir; edict_t *target; target = G_PickTarget( spot->target ); if( target ) { VectorSubtract( target->s.origin, origin, dir ); VecToAngles( dir, angles ); } } } // SPAWN TELEFRAGGING PROTECTION. if( ent->r.solid == SOLID_YES && ( level.gametype.spawnpointRadius > ( playerbox_stand_maxs[0] - playerbox_stand_mins[0] ) ) ) G_OffsetSpawnPoint( origin, playerbox_stand_mins, playerbox_stand_maxs, level.gametype.spawnpointRadius, !( spot->spawnflags & 1 ) ? true : false ); }
void Bot::ActiveFrame() { //get ready if in the game if(GS_MatchState() <= MATCH_STATE_WARMUP && !IsReady() && self->r.client->teamstate.timeStamp + 4000 < level.time) G_Match_Ready(self); ApplyPendingTurnToLookAtPoint(); const CombatTask &combatTask = botBrain.combatTask; bool inhibitShooting, inhibitCombatMove; SetCombatInhibitionFlags(&inhibitShooting, &inhibitCombatMove); // ucmd modification in FireWeapon() will be overwritten by MoveFrame() bool fireButtonPressed = false; if (!inhibitShooting) { SetCloakEnabled(false); // If bot fired builtin or script weapon, save builtin fire button status FireWeapon(&fireButtonPressed); } else { if (!combatTask.Empty()) { SetCloakEnabled(true); } else if (botBrain.HasGoal()) { if (botBrain.IsCloseToAnyGoal(768.0f, true)) SetCloakEnabled(true); else if (botBrain.IsCloseToAnyGoal(384.0f, false)) SetCloakEnabled(true); else SetCloakEnabled(false); } else { SetCloakEnabled(false); } } bool beSilent = ShouldBeSilent(inhibitShooting); // Do not modify pmove features by beSilent value, features may be changed dynamically by script. usercmd_t ucmd; memset(&ucmd, 0, sizeof(ucmd)); MoveFrame(&ucmd, inhibitCombatMove, beSilent); if (fireButtonPressed) ucmd.buttons |= BUTTON_ATTACK; CallActiveClientThink(&ucmd); SayVoiceMessages(); }
/* * G_Match_SuddenDeathFinished */ bool G_Match_SuddenDeathFinished( void ) { if( GS_MatchState() != MATCH_STATE_PLAYTIME ) return false; if( !GS_MatchExtended() || GS_MatchDuration() ) return false; return G_Match_Tied() ? false : true; }
/* * G_PlayerCanTeleport * * Checks if the player can be teleported. */ bool G_PlayerCanTeleport( edict_t *player ) { if ( !player->r.client ) return false; if ( player->r.client->ps.pmove.pm_type > PM_SPECTATOR ) return false; if ( GS_MatchState( ) == MATCH_STATE_COUNTDOWN ) // match countdown return false; return true; }
/** * Checks if the scoreboard column of the specific type needs to be skipped. * * @param type the column type * @return whether the column needs to be skipped */ static bool SCR_SkipColumn( char type ) { switch( type ) { case 'r': return GS_MatchState() != MATCH_STATE_WARMUP; } return false; }
/* * G_Killed */ void G_Killed( edict_t *targ, edict_t *inflictor, edict_t *attacker, int damage, const vec3_t point, int mod ) { if( targ->health < -999 ) targ->health = -999; if( targ->deadflag == DEAD_DEAD ) return; targ->deadflag = DEAD_DEAD; targ->enemy = attacker; if( targ->r.client ) { if( attacker && targ != attacker ) { if( GS_IsTeamDamage( &targ->s, &attacker->s ) ) attacker->snap.teamkill = qtrue; else attacker->snap.kill = qtrue; } // count stats if( GS_MatchState() == MATCH_STATE_PLAYTIME ) { targ->r.client->level.stats.deaths++; teamlist[targ->s.team].stats.deaths++; if( !attacker || !attacker->r.client || attacker == targ || attacker == world ) { targ->r.client->level.stats.suicides++; teamlist[targ->s.team].stats.suicides++; } else { if( GS_IsTeamDamage( &targ->s, &attacker->s ) ) { attacker->r.client->level.stats.teamfrags++; teamlist[attacker->s.team].stats.teamfrags++; } else { attacker->r.client->level.stats.frags++; teamlist[attacker->s.team].stats.frags++; G_AwardPlayerKilled( targ, inflictor, attacker, mod ); } } } } G_Gametype_ScoreEvent( attacker ? attacker->r.client : NULL, "kill", va( "%i %i %i", targ->s.number, ( inflictor == world ) ? -1 : ENTNUM( inflictor ), ENTNUM( attacker ) ) ); G_CallDie( targ, inflictor, attacker, damage, point ); }
/* * CG_IsScoreboardShown */ bool CG_IsScoreboardShown( void ) { if( !cgs.configStrings[CS_SCB_PLAYERTAB_LAYOUT][0] ) // no layout defined return false; if( scoreboardString[0] != '&' ) // nothing to draw return false; if( cgs.demoPlaying || cg.frame.multipov || cgs.tv ) return cg.showScoreboard || ( GS_MatchState() > MATCH_STATE_PLAYTIME ); return ( cg.predictedPlayerState.stats[STAT_LAYOUTS] & STAT_LAYOUT_SCOREBOARD ) ? true : false; }
char *G_Gametype_GENERIC_ScoreboardMessage( void ) { char entry[MAX_TOKEN_CHARS]; size_t len; int i; edict_t *e; int carrierIcon; *scoreboardString = 0; len = 0; Q_snprintfz( entry, sizeof(entry), "&t %i 0 0 ", TEAM_PLAYERS ); if( SCOREBOARD_MSG_MAXSIZE - len > strlen( entry ) ) { Q_strncatz( scoreboardString, entry, sizeof( scoreboardString ) ); len = strlen( scoreboardString ); } // players for( i = 0; i < teamlist[TEAM_PLAYERS].numplayers; i++ ) { e = game.edicts + teamlist[TEAM_PLAYERS].playerIndices[i]; if( e->s.effects & EF_CARRIER ) carrierIcon = trap_ImageIndex( ( e->s.team == TEAM_BETA ) ? PATH_ALPHAFLAG_ICON : PATH_BETAFLAG_ICON ); else if( e->s.effects & EF_QUAD ) carrierIcon = trap_ImageIndex( PATH_QUAD_ICON ); else if( e->s.effects & EF_SHELL ) carrierIcon = trap_ImageIndex( PATH_SHELL_ICON ); else if( e->s.effects & EF_REGEN ) carrierIcon = trap_ImageIndex( PATH_REGEN_ICON ); else carrierIcon = 0; Q_snprintfz( entry, sizeof( entry ), "&p %i %i %i %i %i ", PLAYERNUM( e ), e->r.client->level.stats.score, e->r.client->r.ping > 999 ? 999 : e->r.client->r.ping, carrierIcon, ( level.ready[PLAYERNUM( e )] || GS_MatchState() >= MATCH_STATE_PLAYTIME ) ? trap_ImageIndex( PATH_VSAY_YES_ICON ) : 0 ); if( SCOREBOARD_MSG_MAXSIZE - len > strlen( entry ) ) { Q_strncatz( scoreboardString, entry, sizeof( scoreboardString ) ); len = strlen( scoreboardString ); } } return scoreboardString; }
/* * G_SetClientEffects */ static void G_SetClientEffects( edict_t *ent ) { gclient_t *client = ent->r.client; if( G_IsDead( ent ) || GS_MatchState() >= MATCH_STATE_POSTMATCH ) return; if( client->ps.inventory[POWERUP_QUAD] > 0 ) { ent->s.effects |= EF_QUAD; if( client->ps.inventory[POWERUP_QUAD] < 6 ) ent->s.effects |= EF_EXPIRING_QUAD; } if( client->ps.inventory[POWERUP_SHELL] > 0 ) { ent->s.effects |= EF_SHELL; if( client->ps.inventory[POWERUP_SHELL] < 6 ) ent->s.effects |= EF_EXPIRING_SHELL; } if( client->ps.inventory[POWERUP_REGEN] > 0 ) { ent->s.effects |= EF_REGEN; if( client->ps.inventory[POWERUP_REGEN] < 6 ) ent->s.effects |= EF_EXPIRING_REGEN; } if( ent->s.weapon ) { firedef_t *firedef = GS_FiredefForPlayerState( &client->ps, ent->s.weapon ); if( firedef && firedef->fire_mode == FIRE_MODE_STRONG ) ent->s.effects |= EF_STRONG_WEAPON; } if( client->ps.pmove.stats[PM_STAT_STUN] ) ent->s.effects |= EF_PLAYER_STUNNED; else ent->s.effects &= ~EF_PLAYER_STUNNED; // show cheaters!!! if( ent->flags & FL_GODMODE ) ent->s.effects |= EF_GODMODE; // add chatting icon effect if( ent->r.client->resp.snap.buttons & BUTTON_BUSYICON ) ent->s.effects |= EF_BUSYICON; }
/* * G_Client_InactivityRemove */ void G_Client_InactivityRemove( gclient_t *client ) { if( !client ) return; // racesow if( !level.gametype.autoInactivityRemove ) return; // !racesow if( client->ps.pmove.pm_type != PM_NORMAL ) return; if( g_inactivity_maxtime->modified ) { if( g_inactivity_maxtime->value <= 0.0f ) trap_Cvar_ForceSet( "g_inactivity_maxtime", "0.0" ); else if( g_inactivity_maxtime->value < 15.0f ) trap_Cvar_ForceSet( "g_inactivity_maxtime", "15.0" ); g_inactivity_maxtime->modified = false; } if( g_inactivity_maxtime->value == 0.0f ) return; if( ( GS_MatchState() != MATCH_STATE_PLAYTIME ) || !level.gametype.removeInactivePlayers ) return; // inactive for too long if( client->level.last_activity && client->level.last_activity + ( g_inactivity_maxtime->value * 1000 ) < level.time ) { if( client->team >= TEAM_PLAYERS && client->team < GS_MAX_TEAMS ) { edict_t *ent = &game.edicts[ client - game.clients + 1 ]; // move to spectators and reset the queue time, effectively removing from the challengers queue G_Teams_SetTeam( ent, TEAM_SPECTATOR ); G_SpawnQueue_RemoveClient( ent ); // racesow - set player in free-view client->queueTimeStamp = 0; G_PrintMsg( NULL, "%s" S_COLOR_YELLOW " has been moved to spectator after %.1f seconds of inactivity\n", client->netname, g_inactivity_maxtime->value ); } } }
void G_PlayerMetaAward( edict_t *ent, const char *awardMsg ) { int i, size; gameaward_t *ga; score_stats_t *stats; /* * ch : meta-award is an award that isn't announced but * it is sent to MM */ if( !awardMsg || !awardMsg[0] || !ent->r.client ) return; stats = &ent->r.client->level.stats; if( !stats->awardAllocator ) stats->awardAllocator = LinearAllocator( sizeof( gameaward_t ), 0, _G_LevelMalloc, _G_LevelFree ); // ch : this doesnt work for race right? if( GS_MatchState() == MATCH_STATE_PLAYTIME ) { // ch : we store this locally to send to MM // first check if we already have this one on the clients list size = LA_Size( stats->awardAllocator ); ga = NULL; for( i = 0; i < size; i++ ) { ga = LA_Pointer( stats->awardAllocator, i ); if( !strncmp( ga->name, awardMsg, sizeof(ga->name)-1 ) ) break; } if( i >= size ) { ga = LA_Alloc( stats->awardAllocator ); memset( ga, 0, sizeof(*ga) ); ga->name = G_RegisterLevelString( awardMsg ); } if( ga ) ga->count++; } }
void G_Teams_Coach( edict_t *ent ) { if( GS_TeamBasedGametype() && !GS_InvidualGameType() && ent->s.team != TEAM_SPECTATOR ) { if( !teamlist[ent->s.team].has_coach ) { if( GS_MatchState() > MATCH_STATE_WARMUP && !GS_MatchPaused() ) { G_PrintMsg( ent, "Can't set coach mode with the match in progress\n" ); } else { // move to coach mode ent->r.client->teamstate.is_coach = true; G_GhostClient( ent ); ent->health = ent->max_health; ent->deadflag = DEAD_NO; G_ChasePlayer( ent, NULL, true, 0 ); //clear up his scores G_Match_Ready( ent ); // set ready and check readys memset( &ent->r.client->level.stats, 0, sizeof( ent->r.client->level.stats ) ); teamlist[ent->s.team].has_coach = true; G_PrintMsg( NULL, "%s%s is now team %s coach \n", ent->r.client->netname, S_COLOR_WHITE, GS_TeamName( ent->s.team ) ); } } else if( ent->r.client->teamstate.is_coach ) { // if you are this team coach, resign ent->r.client->teamstate.is_coach = false; G_PrintMsg( NULL, "%s%s is no longer team %s coach \n", ent->r.client->netname, S_COLOR_WHITE, GS_TeamName( ent->s.team ) ); G_Teams_SetTeam( ent, ent->s.team ); } else G_PrintMsg( ent, "Your team already has a coach.\n" ); } else G_PrintMsg( ent, "Coaching only valid while on a team in Team based Gametypes.\n" ); }
static void G_Gametype_GENERIC_MatchStateStarted( void ) { switch( GS_MatchState() ) { // case MATCH_STATE_WAITING: case MATCH_STATE_WARMUP: G_Gametype_GENERIC_SetUpWarmup(); break; case MATCH_STATE_COUNTDOWN: G_Gametype_GENERIC_SetUpCountdown(); break; case MATCH_STATE_PLAYTIME: G_Gametype_GENERIC_SetUpMatch(); break; case MATCH_STATE_POSTMATCH: G_Gametype_GENERIC_SetUpEndMatch(); break; default: break; } }