2022-12-17 13:32:43 +01:00
|
|
|
/***
|
2013-08-30 13:34:05 -07:00
|
|
|
*
|
|
|
|
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
|
|
|
|
*
|
|
|
|
* This product contains software technology licensed from Id
|
|
|
|
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
|
|
|
* All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Use, distribution, and modification of this source code and/or resulting
|
|
|
|
* object code is restricted to non-commercial enhancements to products from
|
|
|
|
* Valve LLC. All other use, distribution, or modification is prohibited
|
|
|
|
* without written permission from Valve LLC.
|
|
|
|
*
|
|
|
|
****/
|
|
|
|
//
|
|
|
|
// teamplay_gamerules.cpp
|
|
|
|
//
|
2021-11-28 16:54:48 +01:00
|
|
|
#include "extdll.h"
|
|
|
|
#include "util.h"
|
|
|
|
#include "cbase.h"
|
|
|
|
#include "player.h"
|
|
|
|
#include "weapons.h"
|
|
|
|
#include "gamerules.h"
|
|
|
|
#include "teamplay_gamerules.h"
|
|
|
|
#include "game.h"
|
2021-02-17 17:10:14 +01:00
|
|
|
#include "UserMessages.h"
|
2013-08-30 13:34:05 -07:00
|
|
|
|
2021-11-28 20:40:56 +01:00
|
|
|
//TODO: these should be members of CHalfLifeTeamplay
|
2013-08-30 13:34:05 -07:00
|
|
|
static char team_names[MAX_TEAMS][MAX_TEAMNAME_LENGTH];
|
|
|
|
static int team_scores[MAX_TEAMS];
|
|
|
|
static int num_teams = 0;
|
|
|
|
|
2021-11-29 20:31:17 +01:00
|
|
|
CHalfLifeTeamplay::CHalfLifeTeamplay()
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-19 13:43:33 +01:00
|
|
|
m_DisableDeathMessages = false;
|
|
|
|
m_DisableDeathPenalty = false;
|
2013-08-30 13:34:05 -07:00
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
memset(team_names, 0, sizeof(team_names));
|
|
|
|
memset(team_scores, 0, sizeof(team_scores));
|
2013-08-30 13:34:05 -07:00
|
|
|
num_teams = 0;
|
|
|
|
|
|
|
|
// Copy over the team from the server config
|
|
|
|
m_szTeamList[0] = 0;
|
|
|
|
|
|
|
|
// Cache this because the team code doesn't want to deal with changing this in the middle of a game
|
2021-11-28 16:54:48 +01:00
|
|
|
strncpy(m_szTeamList, teamlist.string, TEAMPLAY_TEAMLISTLENGTH);
|
2013-08-30 13:34:05 -07:00
|
|
|
|
2023-02-02 13:17:24 +01:00
|
|
|
edict_t* pWorld = CWorld::World->edict();
|
2021-11-28 16:54:48 +01:00
|
|
|
if (pWorld && !FStringNull(pWorld->v.team))
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
if (0 != teamoverride.value)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
const char* pTeamList = STRING(pWorld->v.team);
|
|
|
|
if (pTeamList && 0 != strlen(pTeamList))
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
strncpy(m_szTeamList, pTeamList, TEAMPLAY_TEAMLISTLENGTH);
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Has the server set teams
|
2021-11-28 16:54:48 +01:00
|
|
|
if (0 != strlen(m_szTeamList))
|
2021-11-19 13:45:16 +01:00
|
|
|
m_teamLimit = true;
|
2013-08-30 13:34:05 -07:00
|
|
|
else
|
2021-11-19 13:43:33 +01:00
|
|
|
m_teamLimit = false;
|
2013-08-30 13:34:05 -07:00
|
|
|
|
|
|
|
RecountTeams();
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "voice_gamemgr.h"
|
2021-11-28 16:54:48 +01:00
|
|
|
extern CVoiceGameMgr g_VoiceGameMgr;
|
2013-08-30 13:34:05 -07:00
|
|
|
|
2021-11-29 20:31:17 +01:00
|
|
|
void CHalfLifeTeamplay::Think()
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
///// Check game rules /////
|
|
|
|
static int last_frags;
|
|
|
|
static int last_time;
|
|
|
|
|
|
|
|
int frags_remaining = 0;
|
|
|
|
int time_remaining = 0;
|
|
|
|
|
|
|
|
g_VoiceGameMgr.Update(gpGlobals->frametime);
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
if (g_fGameOver) // someone else quit the game already
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
CHalfLifeMultiplay::Think();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
float flTimeLimit = CVAR_GET_FLOAT("mp_timelimit") * 60;
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
time_remaining = (int)(0 != flTimeLimit ? (flTimeLimit - gpGlobals->time) : 0);
|
|
|
|
|
|
|
|
if (flTimeLimit != 0 && gpGlobals->time >= flTimeLimit)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
GoToIntermission();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
float flFragLimit = fraglimit.value;
|
2021-11-28 16:54:48 +01:00
|
|
|
if (0 != flFragLimit)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
int bestfrags = 9999;
|
|
|
|
int remain;
|
|
|
|
|
|
|
|
// check if any team is over the frag limit
|
2021-11-28 16:54:48 +01:00
|
|
|
for (int i = 0; i < num_teams; i++)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
if (team_scores[i] >= flFragLimit)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
GoToIntermission();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
remain = flFragLimit - team_scores[i];
|
2021-11-28 16:54:48 +01:00
|
|
|
if (remain < bestfrags)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
bestfrags = remain;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
frags_remaining = bestfrags;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Updates when frags change
|
2021-11-28 16:54:48 +01:00
|
|
|
if (frags_remaining != last_frags)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
g_engfuncs.pfnCvar_DirectSet(&fragsleft, UTIL_VarArgs("%i", frags_remaining));
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Updates once per second
|
2021-11-28 16:54:48 +01:00
|
|
|
if (timeleft.value != last_time)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
g_engfuncs.pfnCvar_DirectSet(&timeleft, UTIL_VarArgs("%i", time_remaining));
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
last_frags = frags_remaining;
|
2021-11-28 16:54:48 +01:00
|
|
|
last_time = time_remaining;
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
//=========================================================
|
|
|
|
// ClientCommand
|
|
|
|
// the user has typed a command which is unrecognized by everything else;
|
|
|
|
// this check to see if the gamerules knows anything about the command
|
|
|
|
//=========================================================
|
2021-11-29 20:31:17 +01:00
|
|
|
bool CHalfLifeTeamplay::ClientCommand(CBasePlayer* pPlayer, const char* pcmd)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
if (g_VoiceGameMgr.ClientCommand(pPlayer, pcmd))
|
2021-11-19 13:45:16 +01:00
|
|
|
return true;
|
2013-08-30 13:34:05 -07:00
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
if (FStrEq(pcmd, "menuselect"))
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
if (CMD_ARGC() < 2)
|
2021-11-19 13:45:16 +01:00
|
|
|
return true;
|
2013-08-30 13:34:05 -07:00
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
int slot = atoi(CMD_ARGV(1));
|
2013-08-30 13:34:05 -07:00
|
|
|
|
|
|
|
// select the item from the current menu
|
|
|
|
|
2021-11-19 13:45:16 +01:00
|
|
|
return true;
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
|
2021-11-19 13:43:33 +01:00
|
|
|
return false;
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
|
2021-11-29 20:31:17 +01:00
|
|
|
void CHalfLifeTeamplay::UpdateGameMode(CBasePlayer* pPlayer)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
MESSAGE_BEGIN(MSG_ONE, gmsgGameMode, NULL, pPlayer->edict());
|
|
|
|
WRITE_BYTE(1); // game mode teamplay
|
2013-08-30 13:34:05 -07:00
|
|
|
MESSAGE_END();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
const char* CHalfLifeTeamplay::SetDefaultPlayerTeam(CBasePlayer* pPlayer)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
// copy out the team name from the model
|
2021-11-28 16:54:48 +01:00
|
|
|
char* mdls = g_engfuncs.pfnInfoKeyValue(g_engfuncs.pfnGetInfoKeyBuffer(pPlayer->edict()), "model");
|
|
|
|
strncpy(pPlayer->m_szTeamName, mdls, TEAM_NAME_LENGTH);
|
2013-08-30 13:34:05 -07:00
|
|
|
|
|
|
|
RecountTeams();
|
|
|
|
|
|
|
|
// update the current player of the team he is joining
|
2021-11-28 16:54:48 +01:00
|
|
|
if (pPlayer->m_szTeamName[0] == '\0' || !IsValidTeam(pPlayer->m_szTeamName) || 0 != defaultteam.value)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
const char* pTeamName = NULL;
|
|
|
|
|
|
|
|
if (0 != defaultteam.value)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
pTeamName = team_names[0];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pTeamName = TeamWithFewestPlayers();
|
|
|
|
}
|
2021-11-28 16:54:48 +01:00
|
|
|
strncpy(pPlayer->m_szTeamName, pTeamName, TEAM_NAME_LENGTH);
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return pPlayer->m_szTeamName;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//=========================================================
|
|
|
|
// InitHUD
|
|
|
|
//=========================================================
|
2021-11-28 16:54:48 +01:00
|
|
|
void CHalfLifeTeamplay::InitHUD(CBasePlayer* pPlayer)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
SetDefaultPlayerTeam(pPlayer);
|
|
|
|
CHalfLifeMultiplay::InitHUD(pPlayer);
|
2013-08-30 13:34:05 -07:00
|
|
|
|
|
|
|
// Send down the team names
|
2021-11-28 16:54:48 +01:00
|
|
|
MESSAGE_BEGIN(MSG_ONE, gmsgTeamNames, NULL, pPlayer->edict());
|
|
|
|
WRITE_BYTE(num_teams);
|
|
|
|
for (i = 0; i < num_teams; i++)
|
|
|
|
{
|
|
|
|
WRITE_STRING(team_names[i]);
|
|
|
|
}
|
2013-08-30 13:34:05 -07:00
|
|
|
MESSAGE_END();
|
|
|
|
|
|
|
|
RecountTeams();
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
char* mdls = g_engfuncs.pfnInfoKeyValue(g_engfuncs.pfnGetInfoKeyBuffer(pPlayer->edict()), "model");
|
2013-08-30 13:34:05 -07:00
|
|
|
// update the current player of the team he is joining
|
|
|
|
char text[1024];
|
2021-11-28 16:54:48 +01:00
|
|
|
if (0 == strcmp(mdls, pPlayer->m_szTeamName))
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
sprintf(text, "* you are on team \'%s\'\n", pPlayer->m_szTeamName);
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
sprintf(text, "* assigned to team %s\n", pPlayer->m_szTeamName);
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
ChangePlayerTeam(pPlayer, pPlayer->m_szTeamName, false, false);
|
|
|
|
UTIL_SayText(text, pPlayer);
|
2013-08-30 13:34:05 -07:00
|
|
|
int clientIndex = pPlayer->entindex();
|
|
|
|
RecountTeams();
|
|
|
|
// update this player with all the other players team info
|
|
|
|
// loop through all active players and send their team info to the new client
|
2021-11-28 16:54:48 +01:00
|
|
|
for (i = 1; i <= gpGlobals->maxClients; i++)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
CBaseEntity* plr = UTIL_PlayerByIndex(i);
|
|
|
|
if (plr && IsValidTeam(plr->TeamID()))
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
MESSAGE_BEGIN(MSG_ONE, gmsgTeamInfo, NULL, pPlayer->edict());
|
|
|
|
WRITE_BYTE(plr->entindex());
|
|
|
|
WRITE_STRING(plr->TeamID());
|
2013-08-30 13:34:05 -07:00
|
|
|
MESSAGE_END();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
void CHalfLifeTeamplay::ChangePlayerTeam(CBasePlayer* pPlayer, const char* pTeamName, bool bKill, bool bGib)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
int damageFlags = DMG_GENERIC;
|
|
|
|
int clientIndex = pPlayer->entindex();
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
if (!bGib)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
damageFlags |= DMG_NEVERGIB;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
damageFlags |= DMG_ALWAYSGIB;
|
|
|
|
}
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
if (bKill)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
// kill the player, remove a death, and let them start on the new team
|
2021-11-19 13:45:16 +01:00
|
|
|
m_DisableDeathMessages = true;
|
|
|
|
m_DisableDeathPenalty = true;
|
2013-08-30 13:34:05 -07:00
|
|
|
|
2023-02-02 13:17:24 +01:00
|
|
|
pPlayer->TakeDamage(CWorld::World->pev, CWorld::World->pev, 900, damageFlags);
|
2013-08-30 13:34:05 -07:00
|
|
|
|
2021-11-19 13:43:33 +01:00
|
|
|
m_DisableDeathMessages = false;
|
|
|
|
m_DisableDeathPenalty = false;
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// copy out the team name from the model
|
2021-11-28 16:54:48 +01:00
|
|
|
strncpy(pPlayer->m_szTeamName, pTeamName, TEAM_NAME_LENGTH);
|
2013-08-30 13:34:05 -07:00
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
g_engfuncs.pfnSetClientKeyValue(clientIndex, g_engfuncs.pfnGetInfoKeyBuffer(pPlayer->edict()), "model", pPlayer->m_szTeamName);
|
|
|
|
g_engfuncs.pfnSetClientKeyValue(clientIndex, g_engfuncs.pfnGetInfoKeyBuffer(pPlayer->edict()), "team", pPlayer->m_szTeamName);
|
2013-08-30 13:34:05 -07:00
|
|
|
|
|
|
|
// notify everyone's HUD of the team change
|
2021-11-28 16:54:48 +01:00
|
|
|
MESSAGE_BEGIN(MSG_ALL, gmsgTeamInfo);
|
|
|
|
WRITE_BYTE(clientIndex);
|
|
|
|
WRITE_STRING(pPlayer->m_szTeamName);
|
2013-08-30 13:34:05 -07:00
|
|
|
MESSAGE_END();
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
MESSAGE_BEGIN(MSG_ALL, gmsgScoreInfo);
|
|
|
|
WRITE_BYTE(clientIndex);
|
|
|
|
WRITE_SHORT(pPlayer->pev->frags);
|
|
|
|
WRITE_SHORT(pPlayer->m_iDeaths);
|
|
|
|
WRITE_SHORT(0);
|
|
|
|
WRITE_SHORT(g_pGameRules->GetTeamIndex(pPlayer->m_szTeamName) + 1);
|
2013-08-30 13:34:05 -07:00
|
|
|
MESSAGE_END();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//=========================================================
|
|
|
|
// ClientUserInfoChanged
|
|
|
|
//=========================================================
|
2021-11-28 16:54:48 +01:00
|
|
|
void CHalfLifeTeamplay::ClientUserInfoChanged(CBasePlayer* pPlayer, char* infobuffer)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
char text[1024];
|
|
|
|
|
|
|
|
// prevent skin/color/model changes
|
2021-11-28 16:54:48 +01:00
|
|
|
char* mdls = g_engfuncs.pfnInfoKeyValue(infobuffer, "model");
|
2013-08-30 13:34:05 -07:00
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
if (!stricmp(mdls, pPlayer->m_szTeamName))
|
2013-08-30 13:34:05 -07:00
|
|
|
return;
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
if (0 != defaultteam.value)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
int clientIndex = pPlayer->entindex();
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
g_engfuncs.pfnSetClientKeyValue(clientIndex, g_engfuncs.pfnGetInfoKeyBuffer(pPlayer->edict()), "model", pPlayer->m_szTeamName);
|
|
|
|
g_engfuncs.pfnSetClientKeyValue(clientIndex, g_engfuncs.pfnGetInfoKeyBuffer(pPlayer->edict()), "team", pPlayer->m_szTeamName);
|
|
|
|
sprintf(text, "* Not allowed to change teams in this game!\n");
|
|
|
|
UTIL_SayText(text, pPlayer);
|
2013-08-30 13:34:05 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
if (0 != defaultteam.value || !IsValidTeam(mdls))
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
int clientIndex = pPlayer->entindex();
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
g_engfuncs.pfnSetClientKeyValue(clientIndex, g_engfuncs.pfnGetInfoKeyBuffer(pPlayer->edict()), "model", pPlayer->m_szTeamName);
|
|
|
|
sprintf(text, "* Can't change team to \'%s\'\n", mdls);
|
|
|
|
UTIL_SayText(text, pPlayer);
|
|
|
|
sprintf(text, "* Server limits teams to \'%s\'\n", m_szTeamList);
|
|
|
|
UTIL_SayText(text, pPlayer);
|
2013-08-30 13:34:05 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
// notify everyone of the team change
|
2021-11-28 16:54:48 +01:00
|
|
|
sprintf(text, "* %s has changed to team \'%s\'\n", STRING(pPlayer->pev->netname), mdls);
|
|
|
|
UTIL_SayTextAll(text, pPlayer);
|
2013-08-30 13:34:05 -07:00
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
UTIL_LogPrintf("\"%s<%i><%s><%s>\" joined team \"%s\"\n",
|
2013-08-30 13:34:05 -07:00
|
|
|
STRING(pPlayer->pev->netname),
|
2021-11-28 16:54:48 +01:00
|
|
|
GETPLAYERUSERID(pPlayer->edict()),
|
|
|
|
GETPLAYERAUTHID(pPlayer->edict()),
|
2013-08-30 13:34:05 -07:00
|
|
|
pPlayer->m_szTeamName,
|
2021-11-28 16:54:48 +01:00
|
|
|
mdls);
|
2013-08-30 13:34:05 -07:00
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
ChangePlayerTeam(pPlayer, mdls, true, true);
|
2013-08-30 13:34:05 -07:00
|
|
|
// recound stuff
|
2021-11-28 16:54:48 +01:00
|
|
|
RecountTeams(true);
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
//=========================================================
|
2021-11-28 16:54:48 +01:00
|
|
|
// Deathnotice.
|
2013-08-30 13:34:05 -07:00
|
|
|
//=========================================================
|
2021-11-28 16:54:48 +01:00
|
|
|
void CHalfLifeTeamplay::DeathNotice(CBasePlayer* pVictim, entvars_t* pKiller, entvars_t* pevInflictor)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
if (m_DisableDeathMessages)
|
2013-08-30 13:34:05 -07:00
|
|
|
return;
|
2021-11-28 16:54:48 +01:00
|
|
|
|
|
|
|
if (pVictim && pKiller && (pKiller->flags & FL_CLIENT) != 0)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
CBasePlayer* pk = (CBasePlayer*)CBaseEntity::Instance(pKiller);
|
2013-08-30 13:34:05 -07:00
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
if (pk)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
if ((pk != pVictim) && (PlayerRelationship(pVictim, pk) == GR_TEAMMATE))
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
MESSAGE_BEGIN(MSG_ALL, gmsgDeathMsg);
|
|
|
|
WRITE_BYTE(ENTINDEX(ENT(pKiller))); // the killer
|
|
|
|
WRITE_BYTE(ENTINDEX(pVictim->edict())); // the victim
|
|
|
|
WRITE_STRING("teammate"); // flag this as a teammate kill
|
2013-08-30 13:34:05 -07:00
|
|
|
MESSAGE_END();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
CHalfLifeMultiplay::DeathNotice(pVictim, pKiller, pevInflictor);
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
//=========================================================
|
|
|
|
//=========================================================
|
2021-11-29 20:31:17 +01:00
|
|
|
void CHalfLifeTeamplay::PlayerKilled(CBasePlayer* pVictim, entvars_t* pKiller, entvars_t* pInflictor)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
if (!m_DisableDeathPenalty)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
CHalfLifeMultiplay::PlayerKilled(pVictim, pKiller, pInflictor);
|
2013-08-30 13:34:05 -07:00
|
|
|
RecountTeams();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//=========================================================
|
|
|
|
// IsTeamplay
|
|
|
|
//=========================================================
|
2021-11-19 14:31:11 +01:00
|
|
|
bool CHalfLifeTeamplay::IsTeamplay()
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-19 13:45:16 +01:00
|
|
|
return true;
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
bool CHalfLifeTeamplay::FPlayerCanTakeDamage(CBasePlayer* pPlayer, CBaseEntity* pAttacker)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
if (pAttacker && PlayerRelationship(pPlayer, pAttacker) == GR_TEAMMATE)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
// my teammate hit me.
|
2021-11-28 16:54:48 +01:00
|
|
|
if ((friendlyfire.value == 0) && (pAttacker != pPlayer))
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
// friendly fire is off, and this hit came from someone other than myself, then don't get hurt
|
2021-11-19 13:43:33 +01:00
|
|
|
return false;
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
return CHalfLifeMultiplay::FPlayerCanTakeDamage(pPlayer, pAttacker);
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
//=========================================================
|
|
|
|
//=========================================================
|
2021-11-28 16:54:48 +01:00
|
|
|
int CHalfLifeTeamplay::PlayerRelationship(CBaseEntity* pPlayer, CBaseEntity* pTarget)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
// half life multiplay has a simple concept of Player Relationships.
|
|
|
|
// you are either on another player's team, or you are not.
|
2021-11-28 16:54:48 +01:00
|
|
|
if (!pPlayer || !pTarget || !pTarget->IsPlayer())
|
2013-08-30 13:34:05 -07:00
|
|
|
return GR_NOTTEAMMATE;
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
if ((*GetTeamID(pPlayer) != '\0') && (*GetTeamID(pTarget) != '\0') && !stricmp(GetTeamID(pPlayer), GetTeamID(pTarget)))
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
return GR_TEAMMATE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return GR_NOTTEAMMATE;
|
|
|
|
}
|
|
|
|
|
|
|
|
//=========================================================
|
|
|
|
//=========================================================
|
2021-11-28 16:54:48 +01:00
|
|
|
bool CHalfLifeTeamplay::ShouldAutoAim(CBasePlayer* pPlayer, edict_t* target)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
// always autoaim, unless target is a teammate
|
2021-11-28 16:54:48 +01:00
|
|
|
CBaseEntity* pTgt = CBaseEntity::Instance(target);
|
|
|
|
if (pTgt && pTgt->IsPlayer())
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
if (PlayerRelationship(pPlayer, pTgt) == GR_TEAMMATE)
|
2021-11-19 13:43:33 +01:00
|
|
|
return false; // don't autoaim at teammates
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
return CHalfLifeMultiplay::ShouldAutoAim(pPlayer, target);
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
//=========================================================
|
|
|
|
//=========================================================
|
2021-11-28 16:54:48 +01:00
|
|
|
int CHalfLifeTeamplay::IPointsForKill(CBasePlayer* pAttacker, CBasePlayer* pKilled)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
if (!pKilled)
|
2013-08-30 13:34:05 -07:00
|
|
|
return 0;
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
if (!pAttacker)
|
2013-08-30 13:34:05 -07:00
|
|
|
return 1;
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
if (pAttacker != pKilled && PlayerRelationship(pAttacker, pKilled) == GR_TEAMMATE)
|
2013-08-30 13:34:05 -07:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
//=========================================================
|
|
|
|
//=========================================================
|
2021-11-28 16:54:48 +01:00
|
|
|
const char* CHalfLifeTeamplay::GetTeamID(CBaseEntity* pEntity)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
if (pEntity == NULL || pEntity->pev == NULL)
|
2013-08-30 13:34:05 -07:00
|
|
|
return "";
|
|
|
|
|
|
|
|
// return their team name
|
|
|
|
return pEntity->TeamID();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
int CHalfLifeTeamplay::GetTeamIndex(const char* pTeamName)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
if (pTeamName && *pTeamName != 0)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
// try to find existing team
|
2021-11-28 16:54:48 +01:00
|
|
|
for (int tm = 0; tm < num_teams; tm++)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
if (!stricmp(team_names[tm], pTeamName))
|
2013-08-30 13:34:05 -07:00
|
|
|
return tm;
|
|
|
|
}
|
|
|
|
}
|
2021-11-28 16:54:48 +01:00
|
|
|
|
|
|
|
return -1; // No match
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
const char* CHalfLifeTeamplay::GetIndexedTeamName(int teamIndex)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
if (teamIndex < 0 || teamIndex >= num_teams)
|
2013-08-30 13:34:05 -07:00
|
|
|
return "";
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
return team_names[teamIndex];
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
bool CHalfLifeTeamplay::IsValidTeam(const char* pTeamName)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
if (!m_teamLimit) // Any team is valid if the teamlist isn't set
|
2021-11-19 13:45:16 +01:00
|
|
|
return true;
|
2013-08-30 13:34:05 -07:00
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
return (GetTeamIndex(pTeamName) != -1) ? true : false;
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
const char* CHalfLifeTeamplay::TeamWithFewestPlayers()
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int minPlayers = MAX_TEAMS;
|
2021-11-28 16:54:48 +01:00
|
|
|
int teamCount[MAX_TEAMS];
|
|
|
|
char* pTeamName = NULL;
|
|
|
|
|
|
|
|
memset(teamCount, 0, MAX_TEAMS * sizeof(int));
|
2013-08-30 13:34:05 -07:00
|
|
|
|
|
|
|
// loop through all clients, count number of players on each team
|
2021-11-28 16:54:48 +01:00
|
|
|
for (i = 1; i <= gpGlobals->maxClients; i++)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
CBaseEntity* plr = UTIL_PlayerByIndex(i);
|
2013-08-30 13:34:05 -07:00
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
if (plr)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
int team = GetTeamIndex(plr->TeamID());
|
|
|
|
if (team >= 0)
|
|
|
|
teamCount[team]++;
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Find team with least players
|
2021-11-28 16:54:48 +01:00
|
|
|
for (i = 0; i < num_teams; i++)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
if (teamCount[i] < minPlayers)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
minPlayers = teamCount[i];
|
|
|
|
pTeamName = team_names[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return pTeamName;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//=========================================================
|
|
|
|
//=========================================================
|
2021-11-28 16:54:48 +01:00
|
|
|
void CHalfLifeTeamplay::RecountTeams(bool bResendInfo)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
char* pName;
|
|
|
|
char teamlist[TEAMPLAY_TEAMLISTLENGTH];
|
2013-08-30 13:34:05 -07:00
|
|
|
|
|
|
|
// loop through all teams, recounting everything
|
|
|
|
num_teams = 0;
|
|
|
|
|
|
|
|
// Copy all of the teams from the teamlist
|
|
|
|
// make a copy because strtok is destructive
|
2021-11-28 16:54:48 +01:00
|
|
|
strcpy(teamlist, m_szTeamList);
|
2013-08-30 13:34:05 -07:00
|
|
|
pName = teamlist;
|
2021-11-28 16:54:48 +01:00
|
|
|
pName = strtok(pName, ";");
|
|
|
|
while (pName != NULL && '\0' != *pName)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
if (GetTeamIndex(pName) < 0)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
strcpy(team_names[num_teams], pName);
|
2013-08-30 13:34:05 -07:00
|
|
|
num_teams++;
|
|
|
|
}
|
2021-11-28 16:54:48 +01:00
|
|
|
pName = strtok(NULL, ";");
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
if (num_teams < 2)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
num_teams = 0;
|
2021-11-19 13:43:33 +01:00
|
|
|
m_teamLimit = false;
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Sanity check
|
2021-11-28 16:54:48 +01:00
|
|
|
memset(team_scores, 0, sizeof(team_scores));
|
2013-08-30 13:34:05 -07:00
|
|
|
|
|
|
|
// loop through all clients
|
2021-11-28 16:54:48 +01:00
|
|
|
for (int i = 1; i <= gpGlobals->maxClients; i++)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
CBaseEntity* plr = UTIL_PlayerByIndex(i);
|
2013-08-30 13:34:05 -07:00
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
if (plr)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
const char* pTeamName = plr->TeamID();
|
2013-08-30 13:34:05 -07:00
|
|
|
// try add to existing team
|
2021-11-28 16:54:48 +01:00
|
|
|
int tm = GetTeamIndex(pTeamName);
|
|
|
|
|
|
|
|
if (tm < 0) // no team match found
|
|
|
|
{
|
|
|
|
if (!m_teamLimit)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
// add to new team
|
|
|
|
tm = num_teams;
|
|
|
|
num_teams++;
|
|
|
|
team_scores[tm] = 0;
|
2021-11-28 16:54:48 +01:00
|
|
|
strncpy(team_names[tm], pTeamName, MAX_TEAMNAME_LENGTH);
|
2013-08-30 13:34:05 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
if (tm >= 0)
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
|
|
|
team_scores[tm] += plr->pev->frags;
|
|
|
|
}
|
|
|
|
|
2021-11-28 16:54:48 +01:00
|
|
|
if (bResendInfo) //Someone's info changed, let's send the team info again.
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
if (plr && IsValidTeam(plr->TeamID()))
|
2013-08-30 13:34:05 -07:00
|
|
|
{
|
2021-11-28 16:54:48 +01:00
|
|
|
MESSAGE_BEGIN(MSG_ALL, gmsgTeamInfo, NULL);
|
|
|
|
WRITE_BYTE(plr->entindex());
|
|
|
|
WRITE_STRING(plr->TeamID());
|
2013-08-30 13:34:05 -07:00
|
|
|
MESSAGE_END();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|