SidesList.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. /*
  2. ** Command & Conquer Generals Zero Hour(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. ////////////////////////////////////////////////////////////////////////////////
  19. // //
  20. // (c) 2001-2003 Electronic Arts Inc. //
  21. // //
  22. ////////////////////////////////////////////////////////////////////////////////
  23. // SidesList.h
  24. // Class to encapsulate Sides and Build Lists for maps.
  25. // Author: John Ahlquist, November 2001
  26. #pragma once
  27. #ifndef SIDESLIST_H
  28. #define SIDESLIST_H
  29. #include "Common/Dict.h"
  30. #include "Common/Errors.h"
  31. #include "Common/GameType.h"
  32. #include "Common/Snapshot.h"
  33. #include "Common/GameMemory.h"
  34. #include "Common/STLTypedefs.h"
  35. class DataChunkInput;
  36. struct DataChunkInfo;
  37. class DataChunkOutput;
  38. class BuildListInfo;
  39. class RenderObjClass;
  40. class ScriptList;
  41. class Shadow;
  42. // ----------------------------------------------------------------------------------------------
  43. /**
  44. This is a class that describes a Side, including build list.
  45. Note that a side corresponds to a Player in the game. The lightweight
  46. Side is used to give the WB Editor somewhere to hang build lists.
  47. */
  48. class SidesInfo
  49. {
  50. protected:
  51. BuildListInfo* m_pBuildList; ///< linked list.
  52. Dict m_dict; ///< general player dict.
  53. ScriptList *m_scripts; ///< linked list.
  54. public:
  55. SidesInfo(void);
  56. SidesInfo(const SidesInfo& thatref);
  57. ~SidesInfo(void);
  58. void init(const Dict* d);
  59. void clear() { init(NULL); }
  60. Dict* getDict() { return &m_dict; }
  61. void addToBuildList(BuildListInfo *pBuildList, Int position);
  62. Int removeFromBuildList(BuildListInfo *pBuildList);
  63. void reorderInBuildList(BuildListInfo *pBuildList, Int newPosition);
  64. BuildListInfo* getBuildList(void) {return m_pBuildList;} ///< Gets the build list.
  65. void releaseBuildList(void) {m_pBuildList=NULL;} ///< Used when the build list is passed to class Player.
  66. ScriptList *getScriptList(void) {return(m_scripts);};
  67. void setScriptList(ScriptList *pScriptList) {m_scripts = pScriptList;};
  68. // ug, I hate having to overload stuff, but this makes it a lot easier to make copies safely
  69. SidesInfo& operator=(const SidesInfo& that);
  70. };
  71. // ----------------------------------------------------------------------------------------------
  72. class TeamsInfo
  73. {
  74. private:
  75. Dict m_dict;
  76. public:
  77. Dict* getDict() { return &m_dict; }
  78. void init(const Dict* d) { m_dict.clear(); if (d) m_dict = *d; }
  79. void clear() { init(NULL); }
  80. };
  81. // ----------------------------------------------------------------------------------------------
  82. // a wrapper class to make this a little cleaner.
  83. class TeamsInfoRec
  84. {
  85. private:
  86. Int m_numTeams;
  87. Int m_numTeamsAllocated;
  88. TeamsInfo* m_teams;
  89. public:
  90. TeamsInfoRec();
  91. TeamsInfoRec(const TeamsInfoRec& thatref);
  92. ~TeamsInfoRec();
  93. TeamsInfoRec& operator=(const TeamsInfoRec& thatref);
  94. void clear();
  95. TeamsInfo *findTeamInfo(AsciiString name, Int* index);
  96. void addTeam(const Dict* d);
  97. void removeTeam(Int i);
  98. Int getNumTeams() const { return m_numTeams; }
  99. TeamsInfo * getTeamInfo(Int team)
  100. {
  101. if (team>=0&&team<m_numTeams)
  102. {
  103. return(&m_teams[team]);
  104. }
  105. DEBUG_CRASH(("Out of range."));
  106. throw ERROR_BAD_ARG;
  107. return NULL;
  108. }
  109. };
  110. // ----------------------------------------------------------------------------------------------
  111. /**
  112. This is a singleton class that maintains the list of Sides.
  113. In RTS it is associated with the Player singleton.
  114. Note that a side corresponds to a Player in the game. The lightweight
  115. Side is used to give the WB Editor somewhere to hang build lists, as
  116. it doesn't instantiate the Player subsystem
  117. jba.
  118. */
  119. class SidesList : public SubsystemInterface,
  120. public Snapshot
  121. {
  122. public:
  123. SidesList();
  124. ~SidesList();
  125. void init() { }
  126. void update() { }
  127. void reset();
  128. /// Reads sides (including build list info && player dicts.)
  129. static Bool ParseSidesDataChunk(DataChunkInput &file, DataChunkInfo *info, void *userData);
  130. /// Writes sides (including build list info.)
  131. static void WriteSidesDataChunk(DataChunkOutput &chunkWriter);
  132. Int getNumSides() { return m_numSides; }
  133. void emptySides();
  134. void addSide(const Dict* d);
  135. void removeSide(Int i);
  136. inline SidesInfo *getSideInfo(Int side);
  137. inline SidesInfo *getSkirmishSideInfo(Int side);
  138. Int getNumSkirmishSides() { return m_numSkirmishSides; }
  139. SidesInfo *findSideInfo(AsciiString name, Int* index = NULL);
  140. SidesInfo *findSkirmishSideInfo(AsciiString name, Int* index = NULL);
  141. void prepareForMP_or_Skirmish(void); // After a map is loaded, save & clear any players.
  142. Int getNumTeams() { return m_teamrec.getNumTeams(); }
  143. void emptyTeams();
  144. void addTeam(const Dict* d);
  145. void removeTeam(Int i);
  146. inline TeamsInfo *getTeamInfo(Int team);
  147. inline TeamsInfo *getSkirmishTeamInfo(Int team);
  148. Int getNumSkirmishTeams() { return m_skirmishTeamrec.getNumTeams(); }
  149. void addSkirmishTeam(const Dict* d);
  150. TeamsInfo *findTeamInfo(AsciiString name, Int* index = NULL);
  151. Bool isPlayerDefaultTeam(TeamsInfo *t);
  152. void clear();
  153. Bool validateSides(void);
  154. void addPlayerByTemplate(AsciiString playerTemplateName);
  155. enum
  156. {
  157. MAX_TEAM_DEPTH = 3
  158. };
  159. protected:
  160. // snapshot methods
  161. virtual void crc( Xfer *xfer );
  162. virtual void xfer( Xfer *xfer );
  163. virtual void loadPostProcess( void );
  164. Int m_numSides;
  165. SidesInfo m_sides[MAX_PLAYER_COUNT];
  166. Int m_numSkirmishSides;
  167. SidesInfo m_skirmishSides[MAX_PLAYER_COUNT];
  168. TeamsInfoRec m_teamrec;
  169. TeamsInfoRec m_skirmishTeamrec;
  170. Bool validateAllyEnemyList(const AsciiString& tname, AsciiString& allies);
  171. };
  172. inline TeamsInfo * SidesList::getTeamInfo(Int team)
  173. {
  174. return m_teamrec.getTeamInfo(team);
  175. }
  176. inline TeamsInfo * SidesList::getSkirmishTeamInfo(Int team)
  177. {
  178. return m_skirmishTeamrec.getTeamInfo(team);
  179. }
  180. inline SidesInfo * SidesList::getSideInfo(Int side)
  181. {
  182. if (side>=0&&side<m_numSides)
  183. {
  184. return(&m_sides[side]);
  185. }
  186. DEBUG_CRASH(("Out of range."));
  187. throw ERROR_BAD_ARG;
  188. return NULL;
  189. }
  190. inline SidesInfo * SidesList::getSkirmishSideInfo(Int side)
  191. {
  192. if (side>=0&&side<m_numSkirmishSides)
  193. {
  194. return(&m_skirmishSides[side]);
  195. }
  196. DEBUG_CRASH(("Out of range."));
  197. throw ERROR_BAD_ARG;
  198. return NULL;
  199. }
  200. // ----------------------------------------------------------------------------------------------
  201. extern SidesList *TheSidesList; ///< singleton instance of SidesList
  202. // ----------------------------------------------------------------------------------------------
  203. /**
  204. This is a class that describes an entry in the build list.
  205. */
  206. class BuildListInfo : public MemoryPoolObject, public Snapshot
  207. {
  208. MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(BuildListInfo, "BuildListInfo")
  209. // friend doesn't play well with MPO... it reveals delete, which shouldn't be visible, even to friends (srj)
  210. //friend class SidesInfo; // This is essentially a component of the SidesInfo data structure.
  211. //friend class SidesList; // This is essentially a component of the SidesInfo data structure.
  212. //friend class BuildList; // This is the class in WB that edits build lists.
  213. //friend class BuildListTool; // Other class in wb that edits build lists.
  214. //friend class WBDocUndoable; // Other class in wb that edits build lists.
  215. //friend class Player;
  216. //friend class AISideBuildList;
  217. //friend class AISkirmishPlayer;
  218. public:
  219. enum {UNLIMITED_REBUILDS=0xFFFFFFFF};
  220. enum {MAX_RESOURCE_GATHERERS = 10};
  221. BuildListInfo(void);
  222. //~BuildListInfo(void); ///< Note that deleting the head of a list deletes all linked objects in the list.
  223. static void parseStructure(INI *ini, void *instance, void* /*store*/, const void* /*userData*/);
  224. protected:
  225. // snapshot methods
  226. virtual void crc( Xfer *xfer );
  227. virtual void xfer( Xfer *xfer );
  228. virtual void loadPostProcess( void );
  229. AsciiString m_buildingName; ///< The name of this building.
  230. AsciiString m_templateName; ///< The thing template name for this model's info.
  231. Coord3D m_location; ///< The location of the object.
  232. Coord2D m_rallyPointOffset; ///< Offset to the natural rally point.
  233. Real m_angle; ///< Initial orientation of the building.
  234. Bool m_isInitiallyBuilt; ///< Whether the building is built at the start of the game.
  235. UnsignedInt m_numRebuilds; ///< Number of rebuilds allowed.
  236. BuildListInfo* m_nextBuildList; ///< linked list.
  237. AsciiString m_script;
  238. Int m_health;
  239. Bool m_whiner;
  240. Bool m_unsellable;
  241. Bool m_repairable;
  242. Bool m_automaticallyBuild; ///< If true, the ai will build. If false, script has to enable this.
  243. // For WorldBuilder use only:
  244. RenderObjClass *m_renderObj; ///< object that renders in the 3d scene.
  245. Shadow *m_shadowObj; ///< object that renders shadows in the 3d scane.
  246. Bool m_selected; ///< True if the obj is selected in the editor.
  247. // For solo AI use only:
  248. ObjectID m_objectID; ///< the object on the map instantiated by this info
  249. UnsignedInt m_objectTimestamp; ///< frame when object was built
  250. Bool m_underConstruction; ///< True if being constructed by dozer.
  251. ObjectID m_resourceGatherers[MAX_RESOURCE_GATHERERS]; ///< gatherers for this supply center type building.
  252. Bool m_isSupplyBuilding; ///< Uses gatherers to get supplies.
  253. Int m_desiredGatherers; ///< Number of gatherers desired.
  254. Int m_currentGatherers; ///< Number of gatherers available.
  255. Bool m_priorityBuild; ///< Is priority build.
  256. public:
  257. // srj sez: naughty public access to avoid 'friend' -- should be friend for JUST THESE, but hey
  258. void setNumRebuilds(UnsignedInt numRebuilds) {m_numRebuilds = numRebuilds;}
  259. void setNextBuildList(BuildListInfo *pNext) {m_nextBuildList = pNext;}
  260. void setLocation(Coord3D loc) {m_location = loc;}
  261. void setAngle(Real angle) {m_angle = angle;}
  262. void setInitiallyBuilt(Bool built) {m_isInitiallyBuilt = built;}
  263. void setBuildingName(AsciiString name) {m_buildingName = name;}
  264. void setScript(AsciiString script) {m_script = script;}
  265. void setHealth(Int health) {m_health = health;}
  266. void setWhiner(Bool whiner) {m_whiner = whiner;}
  267. void setUnsellable(Bool unsellable) {m_unsellable = unsellable;}
  268. void setRepairable(Bool repairable) {m_repairable = repairable;}
  269. public:
  270. BuildListInfo *getNext(void) const {return m_nextBuildList;}
  271. AsciiString getBuildingName(void) const {return m_buildingName;} ///< Gets the name.
  272. AsciiString getTemplateName(void) const {return m_templateName;} ///< Gets the name.
  273. void setTemplateName(AsciiString name) {m_templateName = name;}
  274. Int getNumRebuilds(void) {return m_numRebuilds;}
  275. void decrementNumRebuilds(void);
  276. void incrementNumRebuilds(void);
  277. const Coord3D *getLocation(void) const {return &m_location;}
  278. const Coord2D *getRallyOffset(void) const {return &m_rallyPointOffset;}
  279. Real getAngle(void) const {return m_angle;}
  280. Bool isInitiallyBuilt(void) {return m_isInitiallyBuilt;}
  281. AsciiString getScript(void) {return m_script;}
  282. Int getHealth(void) {return m_health;}
  283. Bool getWhiner(void) {return m_whiner;}
  284. Bool getUnsellable(void) {return m_unsellable;}
  285. Bool getRepairable(void) {return m_repairable;}
  286. void setRenderObj(RenderObjClass *pObj) {m_renderObj = pObj;}
  287. RenderObjClass *getRenderObj(void) {return m_renderObj;}
  288. void setShadowObj(Shadow *pObj) {m_shadowObj = pObj;}
  289. Shadow *getShadowObj(void) {return m_shadowObj;}
  290. void setSelected(Bool sel) {m_selected = sel;}
  291. Bool isSelected(void) {return m_selected;}
  292. // used by the solo AI
  293. void setObjectID( ObjectID objID ) { m_objectID = objID; }
  294. ObjectID getObjectID( void ) const { return m_objectID; }
  295. void setObjectTimestamp( UnsignedInt frame ) { m_objectTimestamp = frame; }
  296. UnsignedInt getObjectTimestamp( void ) const { return m_objectTimestamp; }
  297. Bool isBuildable( void ); ///< returns true if has enough rebuilds left to build again
  298. Bool isUnderConstruction(void) {return m_underConstruction;}
  299. void setUnderConstruction(Bool construction) { m_underConstruction=construction;}
  300. void markPriorityBuild(void) {m_priorityBuild = true; }
  301. Bool isPriorityBuild(void) {return m_priorityBuild;}
  302. Bool isAutomaticBuild(void) {return m_automaticallyBuild;}
  303. Bool isSupplyBuilding(void) {return m_isSupplyBuilding;}
  304. void setSupplyBuilding(Bool isSupply) {m_isSupplyBuilding = isSupply;}
  305. ObjectID getGathererID(Int ndx) {if (ndx>=0 && ndx < MAX_RESOURCE_GATHERERS) return m_resourceGatherers[ndx]; return INVALID_ID;}
  306. void setGathererID(Int ndx, ObjectID id) {if (ndx>=0 && ndx < MAX_RESOURCE_GATHERERS) m_resourceGatherers[ndx] = id;}
  307. Int getDesiredGatherers(void) {return m_desiredGatherers;};
  308. void setDesiredGatherers(Int desired) {m_desiredGatherers = desired;}
  309. Int getCurrentGatherers(void) {return m_currentGatherers;};
  310. void setCurrentGatherers(Int cur) {m_currentGatherers = cur;}
  311. BuildListInfo *duplicate(void);
  312. };
  313. inline void BuildListInfo::decrementNumRebuilds(void)
  314. {
  315. if (m_numRebuilds > 0 && m_numRebuilds != UNLIMITED_REBUILDS)
  316. m_numRebuilds--;
  317. }
  318. inline void BuildListInfo::incrementNumRebuilds(void)
  319. {
  320. if (m_numRebuilds != UNLIMITED_REBUILDS)
  321. m_numRebuilds++;
  322. }
  323. inline Bool BuildListInfo::isBuildable( void )
  324. {
  325. if (getNumRebuilds() > 0 || getNumRebuilds() == BuildListInfo::UNLIMITED_REBUILDS)
  326. return true;
  327. return false;
  328. }
  329. #endif