shavit-credits/scripting/include/smlib/teams.inc

318 lines
6.5 KiB
SourcePawn

#if defined _smlib_teams_included
#endinput
#endif
#define _smlib_teams_included
#include <sourcemod>
#include <smlib/clients>
#include <smlib/entities>
#define MAX_TEAMS 32 // Max number of teams in a game
#define MAX_TEAM_NAME_LENGTH 32 // Max length of a team's name
// Team Defines
#define TEAM_INVALID -1
#define TEAM_UNASSIGNED 0
#define TEAM_SPECTATOR 1
#define TEAM_ONE 2
#define TEAM_TWO 3
#define TEAM_THREE 4
#define TEAM_FOUR 5
/*
* If one team is empty its assumed single team mode is enabled and the game won't start.
*
* @noparam
* @return True if one team is empty, false otherwise.
*/
stock bool Team_HaveAllPlayers(bool countFakeClients=true) {
int teamCount = GetTeamCount();
for (int i=2; i < teamCount; i++) {
if (Team_GetClientCount(i, ((countFakeClients) ? CLIENTFILTER_ALL : CLIENTFILTER_NOBOTS)) == 0) {
return false;
}
}
return true;
}
/*
* Returns the client count of the players in a team.
*
* @param team Team Index.
* @param flags Client Filter Flags (Use the CLIENTFILTER_ constants).
* @return Client count in the server.
*/
stock int Team_GetClientCount(int team, int flags=0)
{
flags |= CLIENTFILTER_INGAME;
int numClients = 0;
for (int client=1; client <= MaxClients; client++) {
if (!Client_MatchesFilter(client, flags)) {
continue;
}
if (GetClientTeam(client) == team) {
numClients++;
}
}
return numClients;
}
/*
* Returns the client counts of the first two teams (eg.: Terrorists - Counter).
* Use this function for optimization if you have to get the counts of both teams,
* otherwise use Team_GetClientCount().
*
* @param team1 Pass an integer variable by reference
* @param team2 Pass an integer variable by reference
* @param flags Client Filter Flags (Use the CLIENTFILTER_ constants).
* @noreturn
*/
stock void Team_GetClientCounts(int &team1=0, int &team2=0, int flags=0)
{
flags |= CLIENTFILTER_INGAME;
for (int client=1; client <= MaxClients; client++) {
if (!Client_MatchesFilter(client, flags)) {
continue;
}
if (GetClientTeam(client) == TEAM_ONE) {
team1++;
}
else if (GetClientTeam(client) == TEAM_TWO) {
team2++;
}
}
}
/*
* Gets the name of a team.
* Don't call this before OnMapStart()
*
* @param index Team Index.
* @param str String buffer
* @param size String Buffer Size
* @return True on success, false otherwise
*/
stock bool Team_GetName(int index, char[] str, int size)
{
int edict = Team_GetEdict(index);
if (edict == -1) {
str[0] = '\0';
return false;
}
GetEntPropString(edict, Prop_Send, "m_szTeamname", str, size);
return true;
}
/*
* Changes a team's name.
* Use this carefully !
* Only set the teamname OnMapStart() or OnEntityCreated()
* when no players are ingame, otherwise it can crash the server.
*
* @param index Team Index.
* @param name New Name String
* @return True on success, false otherwise
*/
stock bool Team_SetName(int index, const char[] name)
{
int edict = Team_GetEdict(index);
if (edict == -1) {
return false;
}
SetEntPropString(edict, Prop_Send, "m_szTeamname", name);
ChangeEdictState(edict, GetEntSendPropOffs(edict, "m_szTeamname", true));
return true;
}
/*
* Changes a team's score.
* Don't use this before OnMapStart().
*
* @param index Team Index.
* @return Team Score or -1 if the team is not valid.
*/
stock int Team_GetScore(int index)
{
int edict = Team_GetEdict(index);
if (edict == -1) {
return -1;
}
return GetEntProp(edict, Prop_Send, "m_iScore");
}
/*
* Changes a team's score.
* Don't use this before OnMapStart().
*
* @param index Team Index.
* @param score Score value.
* @return True on success, false otherwise
*/
stock bool Team_SetScore(int index, int score)
{
int edict = Team_GetEdict(index);
if (edict == -1) {
return false;
}
SetEntProp(edict, Prop_Send, "m_iScore", score);
ChangeEdictState(edict, GetEntSendPropOffs(edict, "m_iScore", true));
return true;
}
/*
* Gets a team's edict (*team_manager) Team Index.
* Don't call this before OnMapStart()
*
* @param edict Edict
* @return Team Index
*/
stock int Team_EdictGetNum(int edict)
{
return GetEntProp(edict, Prop_Send, "m_iTeamNum");
}
/*
* Check's whether the index is a valid team index or not.
* Don't call this before OnMapStart()
*
* @param index Index.
* @return True if the Index is a valid team, false otherwise.
*/
stock bool Team_IsValid(int index)
{
return (Team_GetEdict(index) != -1);
}
/*
* Gets a team's edict (team_manager) Team Index.
* Don't call this before OnMapStart()
*
* @param index Edict
* @return Team Index
*/
stock int Team_EdictIsValid(int edict)
{
return GetEntProp(edict, Prop_Send, "m_iTeamNum");
}
/*
* Gets a team's edict (team_manager).
* This function caches found team edicts.
* Don't call this before OnMapStart()
*
* @param index Team Index.
* @return Team edict or -1 if not found
*/
stock int Team_GetEdict(int index)
{
static int teams[MAX_TEAMS] = { INVALID_ENT_REFERENCE, ... };
if (index < 0 || index > MAX_TEAMS) {
return -1;
}
int edict = teams[index];
if (Entity_IsValid(edict)) {
return edict;
}
bool foundTeamManager = false;
int maxEntities = GetMaxEntities();
for (int entity=MaxClients+1; entity < maxEntities; entity++) {
if (!IsValidEntity(entity)) {
continue;
}
if (Entity_ClassNameMatches(entity, "team_manager", true)) {
foundTeamManager = true;
}
// Do not continue when no team managers are found anymore (for optimization)
else if (foundTeamManager) {
return -1;
}
else {
continue;
}
int num = Team_EdictGetNum(entity);
if (num >= 0 && num <= MAX_TEAMS) {
teams[num] = EntIndexToEntRef(entity);
}
if (num == index) {
return entity;
}
}
return -1;
}
/*
* Trys to find a client in the specified team.
* This function is NOT random, it returns the first
* or the cached player (Use Client_GetRandom() instead).
*
* @param index Team Index.
* @return Client Index or -1 if no client was found in the specified team.
*/
stock int Team_GetAnyClient(int index)
{
static int client_cache[MAX_TEAMS] = -1;
int client;
if (index > 0) {
client = client_cache[index];
if (client > 0 && client <= MaxClients) {
if (IsClientInGame(client) && GetClientTeam(client) == index) {
return client;
}
}
else {
client = -1;
}
}
for (client=1; client <= MaxClients; client++) {
if (!IsClientInGame(client)) {
continue;
}
if (GetClientTeam(client) != index) {
continue;
}
client_cache[index] = client;
return client;
}
return -1;
}