1 /* 2 * OpenClonk, http://www.openclonk.org 3 * 4 * Copyright (c) 2005-2009, RedWolf Design GmbH, http://www.clonk.de/ 5 * Copyright (c) 2011-2016, The OpenClonk Team and contributors 6 * 7 * Distributed under the terms of the ISC license; see accompanying file 8 * "COPYING" for details. 9 * 10 * "Clonk" is a registered trademark of Matthes Bender, used with permission. 11 * See accompanying file "TRADEMARK" for details. 12 * 13 * To redistribute this file separately, substitute the full license texts 14 * for the above references. 15 */ 16 // player team management for teamwork melees 17 18 #ifndef INC_C4Teams 19 #define INC_C4Teams 20 21 #include "lib/C4InputValidation.h" 22 23 // constant used by lobby to indicate invisible, random team 24 const int32_t TEAMID_Unknown = -1; 25 26 // constant used by InitScenarioPlayer() to indicate creation of a new team 27 const int32_t TEAMID_New = -1; 28 29 // one player team 30 class C4Team 31 { 32 private: 33 // std::vector... 34 // containing player info IDs 35 int32_t *piPlayers{nullptr}; 36 int32_t iPlayerCount{0}; 37 int32_t iPlayerCapacity{0}; 38 39 public: 40 // copying 41 C4Team(const C4Team &rCopy); 42 C4Team &operator = (const C4Team &rCopy); 43 44 protected: 45 // team identification; usually > 0 for a valid team 46 int32_t iID{0}; 47 char Name[C4MaxName+1]; 48 int32_t iPlrStartIndex{0}; // 0 for unassigned; 1 to 4 if all players of that team shall be assigned a specific [Player*]-section in the Scenario.txt 49 uint32_t dwClr{0}; // team color 50 StdCopyStrBuf sIconSpec; // icon drawing specification for offline or runtime team selection dialog 51 int32_t iMaxPlayer{0}; // maximum number of players allowed in this team - 0 for infinite 52 53 friend class C4TeamList; 54 55 public: C4Team()56 C4Team() { *Name=0; } ~C4Team()57 ~C4Team() { Clear(); } 58 59 void Clear(); 60 void AddPlayer(class C4PlayerInfo &rInfo, bool fAdjustPlayer); // add player by info; adjusts ID in info and at any joined player 61 void RemoveIndexedPlayer(int32_t iIndex); // remove info at index; this changes the local list only 62 void RemovePlayerByID(int32_t iID); 63 GetPlayerCount()64 int32_t GetPlayerCount() const { return iPlayerCount; } GetName()65 const char *GetName() const { return Name; } GetID()66 int32_t GetID() const { return iID; } 67 bool IsPlayerIDInTeam(int32_t iID); // search list for a player with the given ID 68 int32_t GetFirstUnjoinedPlayerID() const; // search for a player that does not have the join-flag set GetPlrStartIndex()69 int32_t GetPlrStartIndex() const { return iPlrStartIndex; } GetColor()70 uint32_t GetColor() const { return dwClr; } GetIconSpec()71 const char *GetIconSpec() const { return sIconSpec.getData(); } IsFull()72 bool IsFull() const { return iMaxPlayer && (iPlayerCount >= iMaxPlayer); } // whether no more players may join this team 73 StdStrBuf GetNameWithParticipants() const; // compose team name like "Team 1 (boni, GhostBear, Clonko)" 74 bool HasWon() const; // return true if any member player of the team has won 75 GetIndexedPlayer(int32_t iIndex)76 int32_t GetIndexedPlayer(int32_t iIndex) const { return Inside<int32_t>(iIndex, 0, iPlayerCount-1) ? piPlayers[iIndex] : 0; } 77 78 void CompileFunc(StdCompiler *pComp); 79 80 // this rechecks teams for all (not removed) players; sets players here by team selection in player infos 81 void RecheckPlayers(); 82 83 // this assigns a team color if it's still zero 84 void RecheckColor(C4TeamList &rForList); 85 }; 86 87 // global team list 88 class C4TeamList 89 { 90 public: 91 // team config constants 92 enum ConfigValue 93 { 94 TEAM_None = 0, 95 TEAM_Custom = 1, 96 TEAM_Active = 2, 97 TEAM_AllowHostilityChange = 3, 98 TEAM_Dist = 4, 99 TEAM_AllowTeamSwitch = 5, 100 TEAM_AutoGenerateTeams = 6, 101 TEAM_TeamColors = 7 102 }; 103 104 // team distribution configuration 105 enum TeamDist 106 { 107 TEAMDIST_First = 0, 108 TEAMDIST_Free = 0, // anyone can choose teams 109 TEAMDIST_Host = 1, // host decides teams 110 TEAMDIST_None = 2, // no teams 111 TEAMDIST_Random = 3, // fixed random teams 112 TEAMDIST_RandomInv = 4, // fixed random teams invisible in lobby 113 TEAMDIST_Last = 4, 114 }; 115 116 private: 117 // std::vector... 118 C4Team **ppList{nullptr}; 119 int32_t iTeamCount{0}; 120 int32_t iTeamCapacity{0}; 121 122 int32_t iLastTeamID{0}; 123 bool fAllowHostilityChange{true}; // hostility not fixed 124 bool fAllowTeamSwitch{false}; // teams not fixed 125 bool fActive{true}; 126 bool fCustom{false}; // set if read from team file or changed in scenario 127 bool fTeamColors{false}; // if set, player colors are determined by team colors 128 bool fAutoGenerateTeams{false}; // teams are generated automatically so there's enough teams for everyone 129 TeamDist eTeamDist{TEAMDIST_Free}; 130 int32_t iMaxScriptPlayers{0}; // maximum number of script players to be added in the lobby 131 StdStrBuf sScriptPlayerNames; // default script player names 132 133 public: 134 C4TeamList() = default; ~C4TeamList()135 ~C4TeamList() { Clear(); } 136 void Clear(); 137 138 C4TeamList &operator =(const C4TeamList &rCopy); 139 140 private: 141 // no copying 142 C4TeamList(const C4TeamList &rCopy); 143 144 private: 145 void AddTeam(C4Team *pNewTeam); // add a team; grow list if necessary 146 void ClearTeams(); // delete all teams 147 int32_t GetFreeTeamID(); 148 bool GenerateDefaultTeams(int32_t iUpToID); // generate Team 1, Team 2, etc. 149 150 public: 151 C4Team *GetTeamByID(int32_t iID) const; // get team by ID 152 C4Team *GetGenerateTeamByID(int32_t iID); // get team by ID; generate if not existant. Always generate for TEAMID_New. 153 C4Team *GetTeamByIndex(int32_t iIndex) const; // get team by list index, to enumerate all teams 154 C4Team *GetTeamByName(const char *szName) const; // match team name; case sensitive and not trimmed 155 C4Team *GetTeamByPlayerID(int32_t iID) const; // get team by player ID (not number!) 156 int32_t GetLargestTeamID() const; 157 C4Team *GetRandomSmallestTeam() const; // get team with least amount of players in it GetTeamCount()158 int32_t GetTeamCount() const { return iTeamCount; } 159 160 C4Team *CreateTeam(const char *szName); // create a custom team 161 IsMultiTeams()162 bool IsMultiTeams() const { return fActive; } // teams can be selected IsCustom()163 bool IsCustom() const { return fCustom; } // whether teams are not generated as default IsHostilityChangeAllowed()164 bool IsHostilityChangeAllowed() const { return fAllowHostilityChange; } // allow (temporary) hostility changes at runtime IsTeamSwitchAllowed()165 bool IsTeamSwitchAllowed() const { return fAllowTeamSwitch; } // allow permanent team changes at runtime 166 bool CanLocalChooseTeam() const; // whether the local host can determine teams (e.g., not if teams are random, or if all except the player's current team are full) 167 bool CanLocalChooseTeam(int32_t idPlayer) const; // whether the local host can determine teams (e.g., not if teams are random, or if all except the player's current team are full) 168 bool CanLocalSeeTeam() const; IsTeamColors()169 bool IsTeamColors() const { return fTeamColors; } // whether team colors are enabled IsRandomTeam()170 bool IsRandomTeam() const { return eTeamDist==TEAMDIST_Random ||eTeamDist==TEAMDIST_RandomInv; } // whether a random team mode is selected 171 bool IsJoin2TeamAllowed(int32_t idTeam, C4PlayerType plrType); // checks whether a team ID is valid and still available for new joins IsAutoGenerateTeams()172 bool IsAutoGenerateTeams() const { return fAutoGenerateTeams; } IsRuntimeJoinTeamChoice()173 bool IsRuntimeJoinTeamChoice() const { return IsCustom() && IsMultiTeams(); } // whether players joining at runtime must select a team first GetMaxScriptPlayers()174 int32_t GetMaxScriptPlayers() const { return iMaxScriptPlayers; } // return max number of script players to be added inthe lobby 175 int32_t GetForcedTeamSelection(int32_t idForPlayer) const; // if there's only one team for the player to join, return that team ID 176 StdStrBuf GetScriptPlayerName() const; // get a name to assign to a new script player. Try to avoid name conflicts 177 bool IsTeamVisible() const; // teams invisible during lobby time if TEAMDIST_RandomInv 178 179 void EnforceLeagueRules(); // enforce some league settings, such as disallowing runtime team change 180 181 // assign a team ID to player info; recheck if any user-set team infos are valid within the current team options 182 // creates a new team for melee; assigns the least-used team for teamwork melee 183 // host/single-call only; using UnsyncedRandom! 184 bool RecheckPlayerInfoTeams(C4PlayerInfo &rNewJoin, bool fByHost); 185 186 // compiler 187 void CompileFunc(StdCompiler *pComp); 188 bool Load(C4Group &hGroup, class C4Scenario *pInitDefault, class C4LangStringTable *pLang); // clear self and load from group file (C4CFN_Teams); init default by scen if no team fiel is present 189 bool Save(C4Group &hGroup); // save to group file (C4CFN_Teams) 190 191 // this rechecks teams for all (not removed) players; sets players here by team selection in player infos 192 void RecheckPlayers(); 193 194 // this reorders any unjoined players to teams if they are unevenly filled and team distribution is random 195 // any changed players will be flagged "updated" 196 void RecheckTeams(); 197 198 // marks all unjoined players as not-in-team and reassigns a team for them 199 // also automatically flags all affected player infos as updated 200 void ReassignAllTeams(); 201 202 private: 203 // team distribution configuration 204 StdStrBuf GetTeamDistName(TeamDist eTeamDist) const; 205 public: 206 void FillTeamDistOptions(C4GUI::ComboBox_FillCB *pFiller) const; 207 void SendSetTeamDist(TeamDist eNewDist); GetTeamDist()208 TeamDist GetTeamDist() const { return eTeamDist; } 209 StdStrBuf GetTeamDistString() const; 210 bool HasTeamDistOptions() const; 211 void SetTeamDistribution(TeamDist eToVal); 212 void SendSetTeamColors(bool fEnabled); 213 void SetTeamColors(bool fEnabled); 214 215 // return number of non-empty teams. if players have not been assigned, project a guess on future team count. 216 int32_t GetStartupTeamCount(int32_t startup_player_count); 217 }; 218 219 #endif // INC_C4Teams 220