You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1256 lines
34 KiB
1256 lines
34 KiB
//++ BulliT |
|
|
|
#include "extdll.h" |
|
#include "util.h" |
|
#include "cbase.h" |
|
#include "gamerules.h" |
|
#include "player.h" |
|
#include "weapons.h" |
|
#include "skill.h" |
|
#include "agglobal.h" |
|
#include "agcommand.h" |
|
#include "agvote.h" |
|
#include "agclient.h" |
|
#include "aggamerules.h" |
|
#if AGSTATS |
|
#include "agstats.h" |
|
#endif |
|
|
|
////////////////////////////////////////////////////////////////////// |
|
// Construction/Destruction |
|
////////////////////////////////////////////////////////////////////// |
|
extern int gmsgTeamInfo; |
|
extern int gmsgScoreInfo; |
|
extern int gmsgAllowSpec; |
|
extern int gmsgServerName; |
|
extern int gmsgSpikeCheck; |
|
extern int gmsgGametype; |
|
extern int g_teamplay; |
|
extern int gmsgGameMode; |
|
extern int gmsgAuthID; |
|
extern int gmsgMapList; |
|
|
|
AgGameRules::AgGameRules() |
|
{ |
|
g_bPaused = false; |
|
m_bProxyConnected = false; |
|
g_bUseTeamColors = CVAR_GET_FLOAT( "mp_teamplay" ) > 0; |
|
m_sHostname = CVAR_GET_STRING("hostname"); |
|
AdminCache.Load(); |
|
#if AG_NO_CLIENT_DLL |
|
m_LocationCache.Load(); |
|
#endif |
|
#if AGSTATS |
|
Stats.Reset(); |
|
#endif |
|
} |
|
|
|
AgGameRules::~AgGameRules() |
|
{ |
|
AdminCache.Save(); |
|
} |
|
|
|
bool AgGameRules::AgThink() |
|
{ |
|
//Check if gamerules are correct. |
|
if (!m_Settings.Think()) |
|
//Dont do anything more. |
|
return false; |
|
|
|
//Check if game over. |
|
if (g_fGameOver) |
|
return true; |
|
|
|
//Update HUD timer and effective time. |
|
m_Timer.Think(); |
|
|
|
//Update vote status. |
|
//Handled globally m_Vote.Think(); |
|
|
|
if (CTF == AgGametype()) |
|
m_CTF.Think(); |
|
//++ muphicks |
|
else if (DOM == AgGametype()) |
|
m_DOM.Think(); |
|
//-- muphicks |
|
|
|
if (LMS == AgGametype()) |
|
{ |
|
//Arena status. |
|
m_LMS.Think(); |
|
} |
|
else if (ARENA == AgGametype()) |
|
{ |
|
//Arena status. |
|
m_Arena.Think(); |
|
} |
|
else |
|
{ |
|
//Update match status. |
|
m_Match.Think(); |
|
//Scorelog |
|
m_ScoreLog.Think(); |
|
} |
|
|
|
//Init intermission spots. |
|
m_InfoInterMission.Think(); |
|
|
|
//Check gamemode |
|
GameMode.Think(); |
|
return true; |
|
} |
|
|
|
BOOL AgGameRules::ClientCommand(CBasePlayer* pPlayer, const char *pcmd) |
|
{ |
|
ASSERT(NULL != pPlayer); |
|
if (!pPlayer) |
|
return FALSE; |
|
ASSERT(NULL != pPlayer->pev); |
|
if (!pPlayer->pev) |
|
return FALSE; |
|
|
|
//First check if its a client command. weaponswith,say etc. |
|
if (m_Client.HandleCommand(pPlayer)) |
|
return TRUE; |
|
|
|
//Server command? |
|
if (Command.HandleCommand(pPlayer)) |
|
return TRUE; |
|
|
|
//Gamemode? |
|
if (GameMode.HandleCommand(pPlayer)) |
|
return TRUE; |
|
|
|
//Vote? |
|
if (m_Vote.HandleCommand(pPlayer)) |
|
return TRUE; |
|
|
|
#if AGSTATS |
|
if (Stats.HandleCommand(pPlayer)) |
|
return TRUE; |
|
#endif |
|
|
|
//We didn't handle it |
|
return FALSE; |
|
} |
|
|
|
void AgGameRules::Start(const AgString& sSpawn) |
|
{ |
|
if (ARENA != AgGametype() && LMS != AgGametype()) |
|
m_Match.Start(sSpawn); |
|
} |
|
|
|
|
|
int AgGameRules::DeadPlayerWeapons( CBasePlayer *pPlayer ) |
|
{ |
|
if (ARENA == AgGametype() || ARCADE == AgGametype()) |
|
return GR_PLR_DROP_GUN_NO; |
|
else |
|
return GR_PLR_DROP_GUN_ACTIVE; |
|
} |
|
|
|
int AgGameRules::DeadPlayerAmmo( CBasePlayer *pPlayer ) |
|
{ |
|
if (ARENA == AgGametype() || ARCADE == AgGametype()) |
|
return GR_PLR_DROP_AMMO_NO; |
|
else |
|
return GR_PLR_DROP_AMMO_ACTIVE; |
|
} |
|
|
|
BOOL AgGameRules::FPlayerCanRespawn(CBasePlayer* pPlayer) |
|
{ |
|
ASSERT(NULL != pPlayer); |
|
if (!pPlayer) |
|
return FALSE; |
|
ASSERT(NULL != pPlayer->pev); |
|
if (!pPlayer->pev) |
|
return FALSE; |
|
|
|
return pPlayer->IsIngame(); |
|
} |
|
|
|
|
|
void AgGameRules::PlayerSpawn(CBasePlayer* pPlayer) |
|
{ |
|
ASSERT(NULL != pPlayer); |
|
if (!pPlayer) |
|
return; |
|
ASSERT(NULL != pPlayer->pev); |
|
if (!pPlayer->pev) |
|
return; |
|
|
|
if (!FPlayerCanRespawn(pPlayer) && !pPlayer->IsProxy()) |
|
{ |
|
if (!pPlayer->m_bDoneFirstSpawn) |
|
{ |
|
pPlayer->m_bDoneFirstSpawn = true; |
|
} |
|
|
|
if (!pPlayer->IsSpectator()) |
|
{ |
|
//Check if we boot him. |
|
int iSpectators = 0; |
|
for ( int i = 1; i <= gpGlobals->maxClients; i++ ) |
|
{ |
|
CBasePlayer* pPlayerLoop = AgPlayerByIndex(i); |
|
if (pPlayerLoop && pPlayer != pPlayerLoop ) |
|
{ |
|
if (pPlayerLoop->IsSpectator()) |
|
iSpectators++; |
|
} |
|
} |
|
|
|
if (iSpectators >= ag_max_spectators.value && ARENA != AgGametype() && LMS != AgGametype() && !pPlayer->IsAdmin()) |
|
{ |
|
//He has to go. |
|
AgConsole("To many spectators, kicking him."); |
|
char szCommand[128]; |
|
sprintf(szCommand,"kick \"%s\"\n",(const char*)pPlayer->GetName()); |
|
SERVER_COMMAND( szCommand ); |
|
return; |
|
} |
|
|
|
//Go specmode |
|
pPlayer->Spectate_Start(true); |
|
} |
|
ClientPrint(pPlayer->pev,HUD_PRINTCENTER,"Match is running, you are not allowed to enter the game.\n"); |
|
return; |
|
} |
|
|
|
if (pPlayer->IsProxy() || pPlayer->pev->flags & FL_FAKECLIENT) |
|
pPlayer->m_bDoneFirstSpawn = true; |
|
//if (1 == pPlayer->pev->iuser3) |
|
//pPlayer->m_bDoneFirstSpawn = true; |
|
if (!pPlayer->m_bDoneFirstSpawn) |
|
{ |
|
pPlayer->m_bDoneFirstSpawn = true; |
|
pPlayer->pev->takedamage = DAMAGE_NO; |
|
pPlayer->pev->flags |= FL_SPECTATOR; |
|
pPlayer->pev->flags |= FL_NOTARGET; |
|
pPlayer->pev->effects |= EF_NODRAW; |
|
pPlayer->pev->solid = SOLID_NOT; |
|
pPlayer->pev->movetype = MOVETYPE_NOCLIP; |
|
pPlayer->pev->modelindex = 0; |
|
pPlayer->m_pGoalEnt = NULL; |
|
|
|
//Move player to info intermission spot |
|
edict_t* pSpot = m_InfoInterMission.GetRandomSpot(); |
|
ASSERT(NULL != pSpot); |
|
if (pSpot) |
|
pPlayer->MoveToInfoIntermission(pSpot); |
|
|
|
//Display Gamemode |
|
pPlayer->SetDisplayGamemode(5); |
|
|
|
//Display greeting message |
|
AgDisplayGreetingMessage(pPlayer->GetAuthID()); |
|
|
|
return; |
|
} |
|
|
|
BOOL addDefault; |
|
CBaseEntity *pWeaponEntity = NULL; |
|
|
|
pPlayer->pev->weapons |= (1<<WEAPON_SUIT); |
|
|
|
addDefault = TRUE; |
|
|
|
while( ( pWeaponEntity = UTIL_FindEntityByClassname( pWeaponEntity, "game_player_equip" ) ) ) |
|
{ |
|
pWeaponEntity->Touch( pPlayer ); |
|
addDefault = FALSE; |
|
} |
|
|
|
pPlayer->m_bInSpawn = true; |
|
|
|
if ( addDefault ) |
|
{ |
|
if (pPlayer->GetSpawnFull()) |
|
{ |
|
//American spawn mode... Start with full load of everything. |
|
pPlayer->SetSpawnFull(false); |
|
|
|
pPlayer->pev->health = MAX_NORMAL_BATTERY; |
|
pPlayer->pev->armorvalue = MAX_NORMAL_BATTERY; |
|
|
|
if (1 > ag_ban_longjump.value) |
|
{ |
|
pPlayer->m_fLongJump = TRUE; |
|
g_engfuncs.pfnSetPhysicsKeyValue( pPlayer->edict(), "slj", "1" ); |
|
pPlayer->OnPickupLongjump(); |
|
} |
|
if (1 > ag_ban_glock.value) |
|
pPlayer->GiveNamedItem( "weapon_9mmhandgun" ); |
|
if (1 > ag_ban_crowbar.value) |
|
pPlayer->GiveNamedItem( "weapon_crowbar" ); |
|
if (1 > ag_ban_shotgun.value) |
|
pPlayer->GiveNamedItem( "weapon_shotgun" ); |
|
if (1 > ag_ban_mp5.value) |
|
pPlayer->GiveNamedItem( "weapon_9mmAR" ); |
|
if (1 > ag_ban_gauss.value) |
|
pPlayer->GiveNamedItem( "weapon_gauss" ); |
|
if (1 > ag_ban_hgrenade.value) |
|
pPlayer->GiveNamedItem( "weapon_handgrenade" ); |
|
if (1 > ag_ban_tripmine.value) |
|
pPlayer->GiveNamedItem( "weapon_tripmine" ); |
|
if (1 > ag_ban_egon.value) |
|
pPlayer->GiveNamedItem( "weapon_egon" ); |
|
if (1 > ag_ban_crossbow.value) |
|
pPlayer->GiveNamedItem( "weapon_crossbow" ); |
|
if (1 > ag_ban_357.value) |
|
pPlayer->GiveNamedItem( "weapon_357" ); |
|
if (1 > ag_ban_rpg.value) |
|
pPlayer->GiveNamedItem( "weapon_rpg" ); |
|
if (1 > ag_ban_satchel.value) |
|
pPlayer->GiveNamedItem( "weapon_satchel" ); |
|
if (1 > ag_ban_snark.value) |
|
pPlayer->GiveNamedItem( "weapon_snark" ); |
|
if (1 > ag_ban_hornet.value) |
|
pPlayer->GiveNamedItem( "weapon_hornetgun" ); |
|
|
|
if (1 > ag_ban_hgrenade.value) |
|
pPlayer->GiveAmmo( HANDGRENADE_MAX_CARRY, "Hand Grenade", HANDGRENADE_MAX_CARRY ); |
|
if (1 > ag_ban_satchel.value) |
|
pPlayer->GiveAmmo( SATCHEL_MAX_CARRY, "Satchel Charge", SATCHEL_MAX_CARRY ); |
|
if (1 > ag_ban_tripmine.value) |
|
pPlayer->GiveAmmo( TRIPMINE_MAX_CARRY, "Trip Mine", TRIPMINE_MAX_CARRY ); |
|
if (1 > ag_ban_snark.value) |
|
pPlayer->GiveAmmo( SNARK_MAX_CARRY, "Snarks", SNARK_MAX_CARRY ); |
|
if (1 > ag_ban_hornet.value) |
|
pPlayer->GiveAmmo( HORNET_MAX_CARRY, "Hornets", HORNET_MAX_CARRY ); |
|
if (1 > ag_ban_m203.value) |
|
pPlayer->GiveAmmo( M203_GRENADE_MAX_CARRY, "ARgrenades", M203_GRENADE_MAX_CARRY ); |
|
if (1 > ag_ban_egon.value && 1 > ag_ban_gauss.value) |
|
pPlayer->GiveAmmo( URANIUM_MAX_CARRY, "uranium", URANIUM_MAX_CARRY ); |
|
if (1 > ag_ban_glock.value && 1 > ag_ban_9mmar.value) |
|
pPlayer->GiveAmmo( _9MM_MAX_CARRY, "9mm", _9MM_MAX_CARRY ); |
|
if (1 > ag_ban_357.value) |
|
pPlayer->GiveAmmo( _357_MAX_CARRY, "357", _357_MAX_CARRY ); |
|
if (1 > ag_ban_shotgun.value) |
|
pPlayer->GiveAmmo( BUCKSHOT_MAX_CARRY, "buckshot", BUCKSHOT_MAX_CARRY ); |
|
if (1 > ag_ban_crossbow.value) |
|
pPlayer->GiveAmmo( BOLT_MAX_CARRY, "bolts", BOLT_MAX_CARRY ); |
|
if (1 > ag_ban_rpg.value) |
|
pPlayer->GiveAmmo( ROCKET_MAX_CARRY, "rockets", ROCKET_MAX_CARRY ); |
|
} |
|
else |
|
{ |
|
//Normal spawn. |
|
pPlayer->pev->health = ag_start_health.value; |
|
pPlayer->pev->armorvalue = ag_start_armour.value; |
|
|
|
if (0 < ag_start_longjump.value) |
|
{ |
|
pPlayer->m_fLongJump = TRUE; |
|
g_engfuncs.pfnSetPhysicsKeyValue( pPlayer->edict(), "slj", "1" ); |
|
pPlayer->OnPickupLongjump(); |
|
} |
|
if (0 < ag_start_glock.value) |
|
pPlayer->GiveNamedItem( "weapon_9mmhandgun" ); |
|
if (0 < ag_start_crowbar.value) |
|
pPlayer->GiveNamedItem( "weapon_crowbar" ); |
|
if (0 < ag_start_shotgun.value) |
|
pPlayer->GiveNamedItem( "weapon_shotgun" ); |
|
if (0 < ag_start_mp5.value) |
|
pPlayer->GiveNamedItem( "weapon_9mmAR" ); |
|
if (0 < ag_start_gauss.value) |
|
pPlayer->GiveNamedItem( "weapon_gauss" ); |
|
if (0 < ag_start_hgrenade.value) |
|
pPlayer->GiveNamedItem( "weapon_handgrenade" ); |
|
if (0 < ag_start_tripmine.value) |
|
pPlayer->GiveNamedItem( "weapon_tripmine" ); |
|
if (0 < ag_start_egon.value) |
|
pPlayer->GiveNamedItem( "weapon_egon" ); |
|
if (0 < ag_start_crossbow.value) |
|
pPlayer->GiveNamedItem( "weapon_crossbow" ); |
|
if (0 < ag_start_357.value) |
|
pPlayer->GiveNamedItem( "weapon_357" ); |
|
if (0 < ag_start_rpg.value) |
|
pPlayer->GiveNamedItem( "weapon_rpg" ); |
|
if (0 < ag_start_satchel.value) |
|
pPlayer->GiveNamedItem( "weapon_satchel" ); |
|
if (0 < ag_start_snark.value) |
|
pPlayer->GiveNamedItem( "weapon_snark" ); |
|
if (0 < ag_start_hornet.value) |
|
pPlayer->GiveNamedItem( "weapon_hornetgun" ); |
|
|
|
if (0 < ag_start_hgrenade.value) |
|
pPlayer->GiveAmmo( ag_start_hgrenade.value, "Hand Grenade", HANDGRENADE_MAX_CARRY ); |
|
if (0 < ag_start_satchel.value) |
|
pPlayer->GiveAmmo( ag_start_satchel.value, "Satchel Charge", SATCHEL_MAX_CARRY ); |
|
if (0 < ag_start_tripmine.value) |
|
pPlayer->GiveAmmo( ag_start_tripmine.value, "Trip Mine", TRIPMINE_MAX_CARRY ); |
|
if (0 < ag_start_snark.value) |
|
pPlayer->GiveAmmo( ag_start_snark.value, "Snarks", SNARK_MAX_CARRY ); |
|
if (0 < ag_start_hornet.value) |
|
pPlayer->GiveAmmo( ag_start_hornet.value, "Hornets", HORNET_MAX_CARRY ); |
|
if (0 < ag_start_m203.value) |
|
pPlayer->GiveAmmo( ag_start_m203.value, "ARgrenades", M203_GRENADE_MAX_CARRY ); |
|
if (0 < ag_start_uranium.value) |
|
pPlayer->GiveAmmo( ag_start_uranium.value, "uranium", URANIUM_MAX_CARRY ); |
|
if (0 < ag_start_9mmar.value) |
|
pPlayer->GiveAmmo( ag_start_9mmar.value, "9mm", _9MM_MAX_CARRY ); |
|
if (0 < ag_start_357ammo.value) |
|
pPlayer->GiveAmmo( ag_start_357ammo.value, "357", _357_MAX_CARRY ); |
|
if (0 < ag_start_bockshot.value) |
|
pPlayer->GiveAmmo( ag_start_bockshot.value, "buckshot", BUCKSHOT_MAX_CARRY ); |
|
if (0 < ag_start_bolts.value) |
|
pPlayer->GiveAmmo( ag_start_bolts.value, "bolts", BOLT_MAX_CARRY ); |
|
if (0 < ag_start_rockets.value) |
|
pPlayer->GiveAmmo( ag_start_rockets.value, "rockets", ROCKET_MAX_CARRY ); |
|
} |
|
} |
|
pPlayer->m_bInSpawn = false; |
|
|
|
/* |
|
//Quake1 teleport splash around him. |
|
MESSAGE_BEGIN( MSG_BROADCAST, SVC_TEMPENTITY ); |
|
WRITE_BYTE( TE_TELEPORT ); |
|
WRITE_COORD(pPlayer->pev->origin.x); |
|
WRITE_COORD(pPlayer->pev->origin.y); |
|
WRITE_COORD(pPlayer->pev->origin.z); |
|
MESSAGE_END(); |
|
*/ |
|
} |
|
|
|
BOOL AgGameRules::FShouldSwitchWeapon( CBasePlayer *pPlayer, CBasePlayerItem *pWeapon ) |
|
{ |
|
ASSERT(NULL != pPlayer); |
|
if (!pPlayer) |
|
return FALSE; |
|
ASSERT(NULL != pPlayer->pev); |
|
if (!pPlayer->pev) |
|
return FALSE; |
|
|
|
ASSERT(NULL != pWeapon); |
|
if (!pWeapon) |
|
return FALSE; |
|
|
|
if ( !pWeapon->CanDeploy() ) |
|
{ |
|
// that weapon can't deploy anyway. |
|
return FALSE; |
|
} |
|
|
|
if ( !pPlayer->m_pActiveItem ) |
|
{ |
|
// player doesn't have an active item! |
|
return TRUE; |
|
} |
|
|
|
if ( !pPlayer->m_pActiveItem->CanHolster() ) |
|
{ |
|
// can't put away the active item. |
|
return FALSE; |
|
} |
|
|
|
if (pPlayer->ShouldWeaponSwitch() && (pPlayer->GetWeaponWeight(pWeapon) > pPlayer->GetWeaponWeight(pPlayer->m_pActiveItem))) |
|
{ |
|
return TRUE; |
|
} |
|
return FALSE; |
|
} |
|
|
|
|
|
BOOL AgGameRules::GetNextBestWeapon( CBasePlayer *pPlayer, CBasePlayerItem *pCurrentWeapon ) |
|
{ |
|
ASSERT(NULL != pPlayer); |
|
if (!pPlayer) |
|
return FALSE; |
|
ASSERT(NULL != pPlayer->pev); |
|
if (!pPlayer->pev) |
|
return FALSE; |
|
|
|
ASSERT(NULL != pCurrentWeapon); |
|
if (!pCurrentWeapon) |
|
return FALSE; |
|
|
|
|
|
CBasePlayerItem *pCheck; |
|
CBasePlayerItem *pBest;// this will be used in the event that we don't find a weapon in the same category. |
|
int iBestWeight; |
|
int i; |
|
|
|
iBestWeight = -1;// no weapon lower than -1 can be autoswitched to |
|
pBest = NULL; |
|
|
|
if ( !pCurrentWeapon->CanHolster() ) |
|
{ |
|
// can't put this gun away right now, so can't switch. |
|
return FALSE; |
|
} |
|
|
|
for ( i = 0 ; i < MAX_ITEM_TYPES ; i++ ) |
|
{ |
|
pCheck = pPlayer->m_rgpPlayerItems[ i ]; |
|
|
|
while ( pCheck ) |
|
{ |
|
if ( pPlayer->GetWeaponWeight(pCheck) > -1 && pPlayer->GetWeaponWeight(pCheck) == pPlayer->GetWeaponWeight(pCurrentWeapon) && pCheck != pCurrentWeapon ) |
|
{ |
|
// this weapon is from the same category. |
|
if ( pCheck->CanDeploy() ) |
|
{ |
|
if ( pPlayer->SwitchWeapon( pCheck ) ) |
|
{ |
|
return TRUE; |
|
} |
|
} |
|
} |
|
else if ( pPlayer->GetWeaponWeight(pCheck) > iBestWeight && pCheck != pCurrentWeapon )// don't reselect the weapon we're trying to get rid of |
|
{ |
|
//ALERT ( at_console, "Considering %s\n", STRING( pCheck->pev->classname ) ); |
|
// we keep updating the 'best' weapon just in case we can't find a weapon of the same weight |
|
// that the player was using. This will end up leaving the player with his heaviest-weighted |
|
// weapon. |
|
if ( pCheck->CanDeploy() ) |
|
{ |
|
// if this weapon is useable, flag it as the best |
|
iBestWeight = pPlayer->GetWeaponWeight(pCheck); |
|
pBest = pCheck; |
|
} |
|
} |
|
|
|
pCheck = pCheck->m_pNext; |
|
} |
|
} |
|
|
|
// if we make it here, we've checked all the weapons and found no useable |
|
// weapon in the same catagory as the current weapon. |
|
|
|
// if pBest is null, we didn't find ANYTHING. Shouldn't be possible- should always |
|
// at least get the crowbar, but ya never know. |
|
if ( !pBest ) |
|
{ |
|
return FALSE; |
|
} |
|
|
|
pPlayer->SwitchWeapon( pBest ); |
|
|
|
return TRUE; |
|
} |
|
|
|
const char* AgGameRules::GetIPAddress(edict_t *pEntity) |
|
{ |
|
if (0 == m_mapIPAddress.size()) |
|
return ""; |
|
AgIPAddress::iterator itrIPAddress = m_mapIPAddress.find(ENTINDEX(pEntity)); |
|
if (itrIPAddress != m_mapIPAddress.end()) |
|
return (*itrIPAddress).second.c_str(); |
|
return ""; |
|
|
|
} |
|
|
|
BOOL AgGameRules :: ClientConnected( edict_t *pEntity, const char *pszName, const char *pszAddress, char szRejectReason[ 128 ] ) |
|
{ |
|
if (0 != strcmp("127.0.0.1", pszAddress)) |
|
{ |
|
if (0 == m_mapIPAddress.size()) |
|
{ |
|
m_mapIPAddress.insert(AgIPAddress::value_type(ENTINDEX(pEntity), pszAddress)); |
|
return TRUE; |
|
} |
|
|
|
AgIPAddress::iterator itrIPAddress = m_mapIPAddress.find(ENTINDEX(pEntity)); |
|
if (itrIPAddress == m_mapIPAddress.end()) |
|
m_mapIPAddress.insert(AgIPAddress::value_type(ENTINDEX(pEntity), pszAddress)); |
|
else |
|
(*itrIPAddress).second = ENTINDEX(pEntity); |
|
} |
|
return TRUE; |
|
} |
|
|
|
void AgGameRules::ClientDisconnected( edict_t *pClient ) |
|
{ |
|
ASSERT(NULL != pClient); |
|
if ( pClient ) |
|
{ |
|
CBasePlayer *pPlayer = (CBasePlayer *)CBaseEntity::Instance( pClient ); |
|
ASSERT(NULL != pPlayer); |
|
if (pPlayer) |
|
{ |
|
ASSERT(NULL != pPlayer->pev); |
|
if (!pPlayer->pev) |
|
return; |
|
|
|
UTIL_LogPrintf("\"%s<%d><%s><%s>\" disconnected (score \"%.0f\")\n", |
|
pPlayer->GetName(), GETPLAYERUSERID( pPlayer->edict() ), GETPLAYERAUTHID( pPlayer->edict() ), pPlayer->TeamID(), |
|
(double)pPlayer->pev->frags ); |
|
|
|
// Tell all clients this player isn't a spectator anymore |
|
MESSAGE_BEGIN( MSG_ALL, gmsgSpectator ); |
|
WRITE_BYTE( ENTINDEX(pPlayer->edict()) ); |
|
WRITE_BYTE( 0 ); |
|
MESSAGE_END(); |
|
|
|
for ( int i = 1; i <= gpGlobals->maxClients; i++ ) |
|
{ |
|
CBasePlayer* pPlayerLoop = AgPlayerByIndex(i); |
|
if (pPlayerLoop && pPlayer != pPlayerLoop ) |
|
{ |
|
//Send score to others. |
|
ClientPrint(pPlayerLoop->pev, HUD_PRINTNOTIFY, UTIL_VarArgs("%s left with score %.0f\n", pPlayer->GetName(), (double)pPlayer->pev->frags)); |
|
|
|
if ((CBaseEntity*)pPlayerLoop->m_hSpectateTarget == pPlayer) |
|
{ |
|
//Move to next player. |
|
pPlayerLoop->Spectate_Nextplayer(false); |
|
} |
|
} |
|
} |
|
|
|
if (ARENA == AgGametype()) |
|
m_Arena.ClientDisconnected(pPlayer); |
|
else if (LMS == AgGametype()) |
|
m_LMS.ClientDisconnected(pPlayer); |
|
else if (CTF == AgGametype()) |
|
m_CTF.ClientDisconnected(pPlayer); |
|
//++ muphicks |
|
else if (DOM == AgGametype()) |
|
m_DOM.ClientDisconnected(pPlayer); |
|
//-- muphicks |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
int AgGameRules::IPointsForKill( CBasePlayer *pAttacker, CBasePlayer *pKilled ) |
|
{ |
|
ASSERT(NULL != pAttacker); |
|
ASSERT(NULL != pKilled); |
|
if (!pAttacker || !pKilled) |
|
return 1; |
|
|
|
if (ARCADE == AgGametype() || INSTAGIB == AgGametype()) |
|
{ |
|
if (pAttacker && pKilled && pAttacker != pKilled && pAttacker->IsAlive() && pAttacker->pev) |
|
{ |
|
//As a reward for your kill you get full health and ammo. |
|
pAttacker->pev->armorvalue = MAX_NORMAL_BATTERY; |
|
pAttacker->pev->health = MAX_NORMAL_BATTERY; |
|
|
|
//Fill clip in all weapons weapon |
|
for (int i = 0 ; i < MAX_ITEM_TYPES; i++) |
|
{ |
|
if (pAttacker->m_rgpPlayerItems[i]) |
|
{ |
|
CBasePlayerItem* pPlayerItem = pAttacker->m_rgpPlayerItems[i]; |
|
while (pPlayerItem) |
|
{ |
|
CBasePlayerWeapon* pWeapon = (CBasePlayerWeapon*)pPlayerItem->GetWeaponPtr(); |
|
if (pWeapon) |
|
pWeapon->m_iClip = pWeapon->iMaxClip(); |
|
pPlayerItem = pPlayerItem->m_pNext; |
|
} |
|
} |
|
} |
|
|
|
if (0 < ag_start_hgrenade.value) |
|
pAttacker->GiveAmmo( ag_start_hgrenade.value, "Hand Grenade", HANDGRENADE_MAX_CARRY ); |
|
if (0 < ag_start_satchel.value) |
|
pAttacker->GiveAmmo( ag_start_satchel.value, "Satchel Charge", SATCHEL_MAX_CARRY ); |
|
if (0 < ag_start_tripmine.value) |
|
pAttacker->GiveAmmo( ag_start_tripmine.value, "Trip Mine", TRIPMINE_MAX_CARRY ); |
|
if (0 < ag_start_snark.value) |
|
pAttacker->GiveAmmo( ag_start_snark.value, "Snarks", SNARK_MAX_CARRY ); |
|
if (0 < ag_start_hornet.value) |
|
pAttacker->GiveAmmo( ag_start_hornet.value, "Hornets", HORNET_MAX_CARRY ); |
|
if (0 < ag_start_m203.value) |
|
pAttacker->GiveAmmo( ag_start_m203.value, "ARgrenades", M203_GRENADE_MAX_CARRY ); |
|
if (0 < ag_start_uranium.value) |
|
pAttacker->GiveAmmo( ag_start_uranium.value, "uranium", URANIUM_MAX_CARRY ); |
|
if (0 < ag_start_9mmar.value) |
|
pAttacker->GiveAmmo( ag_start_9mmar.value, "9mm", _9MM_MAX_CARRY ); |
|
if (0 < ag_start_357ammo.value) |
|
pAttacker->GiveAmmo( ag_start_357ammo.value, "357", _357_MAX_CARRY ); |
|
if (0 < ag_start_bockshot.value) |
|
pAttacker->GiveAmmo( ag_start_bockshot.value, "buckshot", BUCKSHOT_MAX_CARRY ); |
|
if (0 < ag_start_bolts.value) |
|
pAttacker->GiveAmmo( ag_start_bolts.value, "bolts", BOLT_MAX_CARRY ); |
|
if (0 < ag_start_rockets.value) |
|
pAttacker->GiveAmmo( ag_start_rockets.value, "rockets", ROCKET_MAX_CARRY ); |
|
} |
|
} |
|
|
|
return 1; |
|
} |
|
|
|
void AgGameRules::PlayerKilled( CBasePlayer *pVictim, entvars_t *pKiller, entvars_t *pInflictor) |
|
{ |
|
if (!pVictim || !pKiller || !pInflictor) |
|
return; |
|
|
|
CBaseEntity* pKillerBE = CBaseEntity::Instance(pKiller); |
|
CBasePlayer* pKillerPlayer = NULL; |
|
if (pKillerBE && CLASS_PLAYER == pKillerBE->Classify()) |
|
pKillerPlayer = ((CBasePlayer*)pKillerBE); |
|
|
|
#if AGSTATS |
|
if (pKillerPlayer && pVictim) |
|
Stats.PlayerKilled(pKillerPlayer, pVictim); |
|
#endif |
|
|
|
//Update the score cache. |
|
m_ScoreCache.UpdateScore(pVictim); |
|
if (pKillerPlayer && pVictim != pKillerPlayer ) |
|
m_ScoreCache.UpdateScore(pKillerPlayer); |
|
} |
|
|
|
|
|
struct BANWEAPON |
|
{ |
|
char szWeapon[20]; |
|
cvar_t* pBan; |
|
}; |
|
FILE_GLOBAL BANWEAPON s_Bans[] = |
|
{ |
|
"weapon_crowbar",&ag_ban_crowbar, |
|
"weapon_9mmhandgun",&ag_ban_glock, |
|
"weapon_shotgun",&ag_ban_357, |
|
"weapon_9mmAR",&ag_ban_mp5, |
|
"weapon_shotgun",&ag_ban_shotgun, |
|
"weapon_crossbow",&ag_ban_crossbow, |
|
"weapon_357",&ag_ban_357, |
|
"weapon_rpg",&ag_ban_rpg, |
|
"weapon_gauss",&ag_ban_gauss, |
|
"weapon_egon",&ag_ban_egon, |
|
"weapon_hornetgun",&ag_ban_hornet, |
|
"weapon_handgrenade",&ag_ban_hgrenade, |
|
"weapon_satchel",&ag_ban_satchel, |
|
"weapon_tripmine",&ag_ban_tripmine, |
|
"weapon_snark",&ag_ban_snark, |
|
"item_longjump",&ag_ban_longjump, |
|
"ammo_ARgrenades",&ag_ban_m203, |
|
"ammo_9mmclip",&ag_ban_9mmar, |
|
"ammo_9mmAR",&ag_ban_9mmar, |
|
"ammo_mp5clip",&ag_ban_9mmar, |
|
"ammo_9mmbox",&ag_ban_9mmar, |
|
"ammo_buckshot",&ag_ban_bockshot, |
|
"ammo_gaussclip",&ag_ban_uranium, |
|
"ammo_crossbow",&ag_ban_bolts, |
|
"ammo_rpgclip",&ag_ban_rockets, |
|
"ammo_357",&ag_ban_357ammo, |
|
"item_battery",&ag_ban_armour, |
|
"item_healthkit",&ag_ban_health, |
|
}; |
|
|
|
|
|
BOOL AgGameRules::CanHavePlayerItem( CBasePlayer *pPlayer, CBasePlayerItem *pItem ) |
|
{ |
|
ASSERT(NULL != pPlayer); |
|
if (!pPlayer) |
|
return FALSE; |
|
ASSERT(NULL != pPlayer->pev); |
|
if (!pPlayer->pev) |
|
return FALSE; |
|
ASSERT(NULL != pItem); |
|
if (!pItem) |
|
return FALSE; |
|
if (!pPlayer->IsAlive()) |
|
return FALSE; |
|
|
|
if (ARENA == AgGametype() && m_Arena.CanHaveItem()) |
|
return TRUE; |
|
|
|
const char* pszClass = STRING(pItem->pev->classname); |
|
if (0 == strncmp( pszClass, "weapon_", 7 ) || |
|
0 == strncmp( pszClass, "ammo_", 5 ) || |
|
0 == strncmp( pszClass, "item_", 5 ) ) |
|
{ |
|
int iCount = sizeof(s_Bans)/sizeof(s_Bans[0]); |
|
for (int i = 0; i < iCount; i++) |
|
{ |
|
if (FStrEq(pszClass,s_Bans[i].szWeapon)) |
|
{ |
|
if (1 > s_Bans[i].pBan->value) |
|
return CGameRules::CanHavePlayerItem(pPlayer,pItem); |
|
else |
|
return FALSE; |
|
} |
|
} |
|
} |
|
|
|
return CGameRules::CanHavePlayerItem(pPlayer,pItem); |
|
} |
|
|
|
BOOL AgGameRules::CanHaveItem( CBasePlayer *pPlayer, CItem *pItem ) |
|
{ |
|
ASSERT(NULL != pPlayer); |
|
if (!pPlayer) |
|
return FALSE; |
|
ASSERT(NULL != pPlayer->pev); |
|
if (!pPlayer->pev) |
|
return FALSE; |
|
ASSERT(NULL != pItem); |
|
if (!pItem) |
|
return FALSE; |
|
if (!pPlayer->IsAlive()) |
|
return FALSE; |
|
|
|
if (ARENA == AgGametype() && m_Arena.CanHaveItem()) |
|
return TRUE; |
|
|
|
const char* pszClass = STRING(pItem->pev->classname); |
|
if (0 == strncmp( pszClass, "item_", 5 ) ) |
|
{ |
|
int iCount = sizeof(s_Bans)/sizeof(s_Bans[0]); |
|
for (int i = 0; i < iCount; i++) |
|
{ |
|
if (FStrEq(pszClass,s_Bans[i].szWeapon)) |
|
return 1 > s_Bans[i].pBan->value; |
|
} |
|
} |
|
return TRUE; |
|
} |
|
|
|
BOOL AgGameRules::IsAllowedToSpawn( const char* pszClass ) |
|
{ |
|
//Check if item is banned. |
|
if (0 == strncmp( pszClass, "weapon_", 7 ) || |
|
0 == strncmp( pszClass, "ammo_", 5 ) || |
|
0 == strncmp( pszClass, "item_", 5 ) ) |
|
{ |
|
int iCount = sizeof(s_Bans)/sizeof(s_Bans[0]); |
|
for (int i = 0; i < iCount; i++) |
|
{ |
|
if (FStrEq(pszClass,s_Bans[i].szWeapon)) |
|
return 1 > s_Bans[i].pBan->value; |
|
} |
|
} |
|
|
|
return TRUE; |
|
} |
|
|
|
BOOL AgGameRules::IsAllowedToSpawn( CBaseEntity *pEntity ) |
|
{ |
|
ASSERT(NULL != pEntity); |
|
if (!pEntity) |
|
return FALSE; |
|
|
|
if (ARENA == AgGametype() && m_Arena.CanHaveItem()) |
|
return TRUE; |
|
|
|
return IsAllowedToSpawn(STRING(pEntity->pev->classname)); |
|
} |
|
|
|
|
|
void AgGameRules::DeathNotice( CBasePlayer *pVictim, entvars_t *pKiller, entvars_t *pevInflictor ) |
|
{ |
|
} |
|
|
|
void AgGameRules::ClientUserInfoChanged(CBasePlayer *pPlayer, char *infobuffer ) |
|
{ |
|
#if AG_USE_CHEATPROTECTION |
|
const char* pszModel = g_engfuncs.pfnInfoKeyValue( infobuffer, "model" ); |
|
if (pszModel && strlen(pszModel) && 0 != strcmp(pPlayer->m_szModel,pszModel)) |
|
{ |
|
strncpy(pPlayer->m_szModel, pszModel, sizeof(pPlayer->m_szModel) - 1); |
|
pPlayer->m_szModel[sizeof(pPlayer->m_szModel) - 1] = '\0'; |
|
|
|
MESSAGE_BEGIN( MSG_ALL, gmsgSpikeCheck); |
|
WRITE_STRING(pszModel); |
|
MESSAGE_END(); |
|
} |
|
#endif //AG_USE_CHEATPROTECTION |
|
|
|
char* pszAutoWepSwitch = g_engfuncs.pfnInfoKeyValue( infobuffer, "cl_autowepswitch"); |
|
if (strlen(pszAutoWepSwitch)) |
|
pPlayer->m_iAutoWepSwitch = atoi(pszAutoWepSwitch); |
|
|
|
char* pszDisableSpecs = g_engfuncs.pfnInfoKeyValue( infobuffer, "cl_disablespecs"); |
|
if (strlen(pszDisableSpecs)) |
|
pPlayer->m_iDisableSpecs = atoi(pszDisableSpecs); |
|
|
|
/* |
|
char* pszWeaponWeights = g_engfuncs.pfnInfoKeyValue( infobuffer, "cl_weaponweights" ); |
|
if (strlen(pszWeaponWeights)) |
|
pPlayer->SetWeaponWeights(pszWeaponWeights); |
|
*/ |
|
} |
|
|
|
void AgGameRules::InitHUD( CBasePlayer *pPlayer ) |
|
{ |
|
ASSERT(NULL != pPlayer); |
|
if (!pPlayer) |
|
return; |
|
ASSERT(NULL != pPlayer->pev); |
|
if (!pPlayer->pev) |
|
return; |
|
|
|
//Send server name. |
|
MESSAGE_BEGIN( MSG_ONE, gmsgServerName, NULL, pPlayer->edict() ); |
|
WRITE_STRING( m_sHostname.substr(0,30).c_str() ); |
|
MESSAGE_END(); |
|
|
|
#ifndef AG_NO_CLIENT_DLL |
|
MESSAGE_BEGIN( MSG_ONE, gmsgGametype, NULL, pPlayer->edict() ); |
|
WRITE_BYTE( AgGametype()); |
|
MESSAGE_END(); |
|
|
|
MESSAGE_BEGIN( MSG_ALL, gmsgAuthID); |
|
WRITE_BYTE( pPlayer->entindex() ); |
|
WRITE_STRING(pPlayer->GetAuthID()); |
|
MESSAGE_END(); |
|
#endif |
|
|
|
#if AG_USE_CHEATPROTECTION |
|
const char* pszModel = g_engfuncs.pfnInfoKeyValue( g_engfuncs.pfnGetInfoKeyBuffer( pPlayer->edict() ), "model" ); |
|
if (pszModel && strlen(pszModel)) |
|
{ |
|
MESSAGE_BEGIN( MSG_ALL, gmsgSpikeCheck); |
|
WRITE_STRING(pszModel); |
|
MESSAGE_END(); |
|
} |
|
#endif //AG_USE_CHEATPROTECTION |
|
} |
|
|
|
void AgGameRules::GoToIntermission() |
|
{ |
|
//Log scores |
|
if (ARENA != AgGametype() && LMS != AgGametype()) |
|
{ |
|
m_ScoreLog.End(); |
|
CVAR_SET_FLOAT("sv_ag_match_running",0); |
|
CVAR_SET_FLOAT("sv_ag_show_gibs",1); |
|
CVAR_SET_FLOAT("ag_spectalk",1); |
|
} |
|
} |
|
|
|
BOOL AgGameRules::FPlayerCanTakeDamage( CBasePlayer *pPlayer, CBaseEntity *pAttacker ) |
|
{ |
|
ASSERT(NULL != pPlayer); |
|
if (!pPlayer) |
|
return FALSE; |
|
ASSERT(NULL != pPlayer->pev); |
|
if (!pPlayer->pev) |
|
return FALSE; |
|
|
|
if (!g_bPaused && INSTAGIB == AgGametype()) |
|
{ |
|
ASSERT(NULL != pAttacker); |
|
if (!pAttacker) |
|
return FALSE; |
|
ASSERT(NULL != pAttacker->pev); |
|
if (!pAttacker->pev) |
|
return FALSE; |
|
|
|
if (CLASS_PLAYER == pAttacker->Classify()) |
|
{ |
|
//This dude is instant dead! |
|
pPlayer->pev->health = -200; |
|
pPlayer->Killed(pAttacker->pev, GIB_NEVER); |
|
return FALSE; |
|
} |
|
} |
|
|
|
if (ARENA == AgGametype()) |
|
return (m_Arena.CanTakeDamage() && !g_bPaused); |
|
else if (LMS == AgGametype()) |
|
return (m_LMS.CanTakeDamage() && !g_bPaused); |
|
|
|
return !g_bPaused; |
|
} |
|
|
|
void AgGameRules::ChangeNextLevel() |
|
{ |
|
m_Settings.ChangeNextLevel(); |
|
} |
|
|
|
void AgGameRules::ResendScoreBoard() |
|
{ |
|
if (g_pGameRules->IsTeamplay()) |
|
{ |
|
for ( int i = 1; i <= gpGlobals->maxClients; i++ ) |
|
{ |
|
CBasePlayer* plr = AgPlayerByIndex( i ); |
|
if ( plr ) |
|
{ |
|
//Team |
|
if ( plr && g_pGameRules->IsValidTeam( plr->TeamID() ) ) |
|
{ |
|
MESSAGE_BEGIN( MSG_ALL, gmsgTeamInfo ); |
|
WRITE_BYTE( plr->entindex() ); |
|
WRITE_STRING( plr->TeamID() ); |
|
MESSAGE_END(); |
|
} |
|
} |
|
} |
|
} |
|
|
|
for ( int i = 1; i <= gpGlobals->maxClients; i++ ) |
|
{ |
|
CBasePlayer* plr = AgPlayerByIndex( i ); |
|
if ( plr ) |
|
{ |
|
//Score |
|
MESSAGE_BEGIN( MSG_ALL, gmsgScoreInfo ); |
|
WRITE_BYTE( ENTINDEX(plr->edict()) ); |
|
WRITE_SHORT( plr->pev->frags ); |
|
WRITE_SHORT( plr->m_iDeaths ); |
|
//++ BulliT |
|
WRITE_SHORT( g_teamplay ); |
|
WRITE_SHORT( g_pGameRules->GetTeamIndex( plr->m_szTeamName ) + 1 ); |
|
//-- Martin Webrant |
|
MESSAGE_END(); |
|
|
|
//Spectator |
|
MESSAGE_BEGIN(MSG_ALL,gmsgSpectator); |
|
WRITE_BYTE(ENTINDEX(plr->edict())); |
|
WRITE_BYTE(plr->IsSpectator() ? 1 : 0); |
|
MESSAGE_END(); |
|
} |
|
} |
|
} |
|
|
|
void AgGameRules::RefreshSkillData( void ) |
|
{ |
|
// load all default values |
|
CGameRules::RefreshSkillData(); |
|
|
|
// override some values for multiplay. |
|
// suitcharger |
|
gSkillData.suitchargerCapacity = 30; |
|
|
|
// Crowbar whack |
|
gSkillData.plrDmgCrowbar = ag_dmg_crowbar.value; |
|
|
|
// Glock Round |
|
gSkillData.plrDmg9MM = ag_dmg_glock.value; |
|
|
|
// 357 Round |
|
gSkillData.plrDmg357 = ag_dmg_357.value; |
|
|
|
// MP5 Round |
|
gSkillData.plrDmgMP5 = ag_dmg_mp5.value; |
|
|
|
// M203 grenade |
|
gSkillData.plrDmgM203Grenade = ag_dmg_m203.value; |
|
|
|
// Shotgun buckshot |
|
gSkillData.plrDmgBuckshot = ag_dmg_shotgun.value; |
|
|
|
// Crossbow |
|
gSkillData.plrDmgCrossbowClient = ag_dmg_crossbow.value; |
|
gSkillData.plrDmgCrossbowMonster = ag_dmg_bolts.value; |
|
|
|
// RPG |
|
gSkillData.plrDmgRPG = ag_dmg_rpg.value; |
|
|
|
// Egon |
|
gSkillData.plrDmgEgonWide = ag_dmg_egon_wide.value; |
|
gSkillData.plrDmgEgonNarrow = ag_dmg_egon_narrow.value; |
|
|
|
// Hand Grendade |
|
gSkillData.plrDmgHandGrenade = ag_dmg_hgrenade.value; |
|
|
|
// Satchel Charge |
|
gSkillData.plrDmgSatchel = ag_dmg_satchel.value; |
|
|
|
// Tripmine |
|
gSkillData.plrDmgTripmine = ag_dmg_tripmine.value; |
|
|
|
// hornet |
|
gSkillData.plrDmgHornet = ag_dmg_hornet.value; |
|
|
|
// Head |
|
gSkillData.plrHead = ag_headshot.value; |
|
} |
|
|
|
|
|
void AgGameRules::HLTV_ResendScoreBoard() |
|
{ |
|
if (!m_bProxyConnected) |
|
return; |
|
|
|
if (g_pGameRules->IsTeamplay()) |
|
{ |
|
for ( int i = 1; i <= gpGlobals->maxClients; i++ ) |
|
{ |
|
CBasePlayer* plr = AgPlayerByIndex( i ); |
|
if ( plr ) |
|
{ |
|
//Team |
|
if ( plr && g_pGameRules->IsValidTeam( plr->TeamID() ) ) |
|
{ |
|
MESSAGE_BEGIN( MSG_SPEC, gmsgTeamInfo ); |
|
WRITE_BYTE( plr->entindex() ); |
|
WRITE_STRING( plr->TeamID() ); |
|
MESSAGE_END(); |
|
} |
|
} |
|
} |
|
} |
|
|
|
for ( int i = 1; i <= gpGlobals->maxClients; i++ ) |
|
{ |
|
CBasePlayer* plr = AgPlayerByIndex( i ); |
|
if ( plr ) |
|
{ |
|
//Score |
|
MESSAGE_BEGIN( MSG_SPEC, gmsgScoreInfo ); |
|
WRITE_BYTE( ENTINDEX(plr->edict()) ); |
|
WRITE_SHORT( plr->pev->frags ); |
|
WRITE_SHORT( plr->m_iDeaths ); |
|
//++ BulliT |
|
WRITE_SHORT( g_teamplay ); |
|
WRITE_SHORT( g_pGameRules->GetTeamIndex( plr->m_szTeamName ) + 1 ); |
|
//-- Martin Webrant |
|
MESSAGE_END(); |
|
|
|
//Spectator |
|
MESSAGE_BEGIN(MSG_SPEC,gmsgSpectator); |
|
WRITE_BYTE(ENTINDEX(plr->edict())); |
|
WRITE_BYTE(plr->IsSpectator() ? 1 : 0); |
|
MESSAGE_END(); |
|
} |
|
} |
|
|
|
MESSAGE_BEGIN(MSG_SPEC,gmsgGameMode); |
|
WRITE_BYTE(g_teamplay); |
|
MESSAGE_END(); |
|
} |
|
|
|
/* |
|
class AgTeam |
|
{ |
|
public: |
|
AgTeam(const char* pszTeam) |
|
{ |
|
m_strName = pszTeam; |
|
m_iCount = 0; |
|
} |
|
|
|
AgString m_strName; |
|
|
|
int m_iCount; |
|
}; |
|
|
|
struct lessagteam : binary_function<AgTeam, AgTeam, bool> { |
|
bool operator()(const AgTeam& x, const AgTeam& y) const |
|
{ |
|
if (x.m_strName.compare(y.m_strName) < 0) |
|
return true; |
|
else |
|
return false; |
|
} |
|
}; |
|
|
|
AgString CHalfLifeTeamplay::GetTeamWithFewestPlayers() |
|
{ |
|
//++ BulliT |
|
if (CTF == AgGametype()) |
|
{ |
|
if (GetTeamIndex(CTF_TEAM1_NAME) == -1) |
|
return CTF_TEAM1_NAME; |
|
else if (GetTeamIndex(CTF_TEAM2_NAME) == -1) |
|
return CTF_TEAM2_NAME; |
|
} |
|
//-- Martin Webrant |
|
|
|
char *pName; |
|
char szTeamList[TEAMPLAY_TEAMLISTLENGTH]; |
|
typedef set<AgTeam, lessagteam > AgTeamSet; |
|
|
|
AgTeamSet setTeams; |
|
|
|
// Copy all of the teams from the teamlist |
|
// make a copy because strtok is destructive |
|
strcpy( szTeamList, m_szTeamList ); |
|
pName = szTeamList; |
|
pName = strtok( pName, ";" ); |
|
while ( pName != NULL && *pName ) |
|
{ |
|
setTeams.insert(AgTeam(pName)); |
|
pName = strtok( NULL, ";" ); |
|
} |
|
|
|
int i; |
|
int minPlayers = MAX_TEAMS; |
|
int teamCount[ MAX_TEAMS ]; |
|
char *pTeamName = NULL; |
|
|
|
memset( teamCount, 0, MAX_TEAMS * sizeof(int) ); |
|
|
|
// loop through all clients, count number of players on each team |
|
for ( i = 1; i <= gpGlobals->maxClients; i++ ) |
|
{ |
|
CBasePlayer* pPlayerLoop = AgPlayerByIndex(i); |
|
if (pPlayerLoop) |
|
{ |
|
AgTeamSet::iterator itrTeams = setTeams.find(pPlayerLoop->m_szTeamName); |
|
(*itrTeams).m_iCount++; |
|
} |
|
} |
|
|
|
AgTeamSet::iterator itrTeams; |
|
int iMinPlayers = MAX_TEAMS; |
|
AgString strTeam; |
|
for (itrTeams = setTeams.begin() ;itrTeams != setTeams.end(); ++itrTeams) |
|
{ |
|
if ((*itrTeams).m_iCount < iMinPlayers) |
|
{ |
|
iMinPlayers = (*itrTeams).m_iCount; |
|
strTeam = (*itrTeams).m_strName; |
|
} |
|
} |
|
|
|
return strTeam; |
|
} |
|
*/ |
|
|
|
#define MAX_MAPLIST_CHUNK 190 |
|
|
|
AgString g_sMapList; |
|
void AgGameRules::SendMapListToClient(CBasePlayer* pPlayer, bool bStart) |
|
{ |
|
if (-1 == pPlayer->m_iMapListSent) |
|
{ |
|
if (bStart) |
|
pPlayer->m_iMapListSent = 0; |
|
else |
|
return; |
|
} |
|
|
|
if (0 == g_sMapList.size()) |
|
{ |
|
char szDirAG[MAX_PATH]; |
|
char szDirVALVE[MAX_PATH]; |
|
sprintf(szDirAG, "%s/maps", AgGetDirectory()); |
|
sprintf(szDirVALVE, "%s/maps", AgGetDirectoryValve()); |
|
|
|
AgStringSet setFiles; |
|
AgStringSet::iterator itrFiles; |
|
|
|
AgDirList(szDirAG,setFiles); |
|
AgDirList(szDirVALVE,setFiles); |
|
|
|
for (itrFiles = setFiles.begin() ;itrFiles != setFiles.end(); ++itrFiles) |
|
{ |
|
AgString sFile = *itrFiles; |
|
AgToLower(sFile); |
|
if (!strstr(sFile.c_str(),".bsp")) |
|
continue; |
|
sFile = sFile.substr(0,sFile.size()-4); |
|
AgTrim(sFile); |
|
g_sMapList += sFile + "#"; |
|
} |
|
|
|
} |
|
|
|
//Send it over in chunks. |
|
int iDataToSend = min((int)g_sMapList.size()-pPlayer->m_iMapListSent,MAX_MAPLIST_CHUNK); |
|
AgString sChunk = g_sMapList.substr(pPlayer->m_iMapListSent,iDataToSend); |
|
pPlayer->m_iMapListSent += iDataToSend; |
|
MESSAGE_BEGIN( MSG_ONE, gmsgMapList, NULL, pPlayer->edict() ); |
|
WRITE_BYTE( pPlayer->m_iMapListSent < (int)g_sMapList.size() ); |
|
WRITE_STRING( sChunk.c_str() ); |
|
MESSAGE_END(); |
|
|
|
if (pPlayer->m_iMapListSent >= (int)g_sMapList.size()) |
|
pPlayer->m_iMapListSent = -1; |
|
} |
|
|
|
|
|
//-- Martin Webrant |
|
|
|
|