summaryrefslogtreecommitdiff
path: root/sourcemod/scripting/include/smlib/teams.inc
diff options
context:
space:
mode:
Diffstat (limited to 'sourcemod/scripting/include/smlib/teams.inc')
-rw-r--r--sourcemod/scripting/include/smlib/teams.inc317
1 files changed, 317 insertions, 0 deletions
diff --git a/sourcemod/scripting/include/smlib/teams.inc b/sourcemod/scripting/include/smlib/teams.inc
new file mode 100644
index 0000000..621c8b1
--- /dev/null
+++ b/sourcemod/scripting/include/smlib/teams.inc
@@ -0,0 +1,317 @@
+#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).
+ */
+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;
+}