clintlib.h 68 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774
  1. #ifndef _CLINTLIB_
  2. #define _CLINTLIB_
  3. class MissionInfo;
  4. class SideInfo;
  5. class PlayerInfo;
  6. class ChatInfo;
  7. class IClientEventSink;
  8. class IClientEventSource;
  9. class IAutoDownload;
  10. class IAutoUpdateSink;
  11. struct CachedPart
  12. {
  13. TRef<IpartTypeIGC> ppt;
  14. Mount mount;
  15. bool bDuplicated;
  16. };
  17. typedef Slist_utl<CachedPart> CachedPartList;
  18. typedef Slink_utl<CachedPart> CachedPartLink;
  19. struct CachedLoadout
  20. {
  21. TRef<IhullTypeIGC> pht;
  22. CachedPartList cpl;
  23. };
  24. typedef Slist_utl<CachedLoadout> CachedLoadoutList;
  25. typedef Slink_utl<CachedLoadout> CachedLoadoutLink;
  26. /////////////////////////////////////////////////////////////////////////////
  27. // IClientEventSource
  28. class IClientEventSource : public IObject
  29. {
  30. public:
  31. virtual void AddSink(IClientEventSink* psink) = 0;
  32. virtual void RemoveSink(IClientEventSink* psink) = 0;
  33. // mission events
  34. virtual void OnAddMission(MissionInfo* pMissionDef) = 0;
  35. virtual void OnDelMission(MissionInfo* pMissionDef) = 0;
  36. virtual void OnMissionCountdown(MissionInfo* pMissionDef) = 0;
  37. virtual void OnMissionStarted(MissionInfo* pMissionDef) = 0;
  38. virtual void OnMissionEnded(MissionInfo* pMissionDef) = 0;
  39. virtual void OnLockLobby(bool bLock) = 0;
  40. virtual void OnLockSides(bool bLock) = 0;
  41. virtual void OnFoundPlayer(MissionInfo* pMissionDef) = 0;
  42. virtual void OnEnterMission() = 0;
  43. // team events
  44. virtual void OnAddPlayer(MissionInfo* pMissionDef, SideID sideID, PlayerInfo* pPlayerInfo) = 0;
  45. virtual void OnDelPlayer(MissionInfo* pMissionDef, SideID sideID, PlayerInfo* pPlayerInfo, QuitSideReason reason, const char* szMessageParam = NULL) = 0;
  46. virtual void OnAddRequest(MissionInfo* pMissionDef, SideID sideID, PlayerInfo* pPlayerInfo) = 0;
  47. virtual void OnDelRequest(MissionInfo* pMissionDef, SideID sideID, PlayerInfo* pPlayerInfo, DelPositionReqReason reason) = 0;
  48. virtual void OnTeamInactive(MissionInfo* pMissionDef, SideID sideID) = 0;
  49. virtual void OnTeamReadyChange(MissionInfo* pMissionDef, SideID sideID, bool fTeamReady) = 0;
  50. virtual void OnTeamForceReadyChange(MissionInfo* pMissionDef, SideID sideID, bool fTeamForceReady) = 0;
  51. virtual void OnTeamAutoAcceptChange(MissionInfo* pMissionDef, SideID sideID, bool fAutoAccept) = 0;
  52. virtual void OnTeamCivChange(MissionInfo* pMissionDef, SideID sideID, CivID civID) = 0;
  53. virtual void OnTeamNameChange(MissionInfo* pMissionDef, SideID sideID) = 0;
  54. // player events
  55. virtual void OnPlayerStatusChange(MissionInfo* pMissionDef, SideID sideID, PlayerInfo* pPlayerInfo) = 0;
  56. virtual void OnMoneyChange(PlayerInfo* pPlayerInfo) = 0;
  57. // gameplay events
  58. virtual void OnBucketChange(BucketChange bc, IbucketIGC* b) = 0;
  59. virtual void OnTechTreeChanged(SideID sid) = 0;
  60. virtual void OnStationCaptured(StationID stationID, SideID sideID) = 0;
  61. virtual void OnModelTerminated(ImodelIGC* pmodel) = 0;
  62. virtual void OnLoadoutChanged(IpartIGC* ppart, LoadoutChange lc) = 0;
  63. virtual void OnPurchaseCompleted(bool bAllPartsBought) = 0;
  64. virtual void OnTurretStateChanging(bool bTurret) = 0;
  65. virtual void OnShipStatusChange(PlayerInfo* pplayer) = 0;
  66. virtual void OnBoardShip(IshipIGC* pshipChild, IshipIGC* pshipParent) = 0;
  67. virtual void OnBoardFailed(IshipIGC* pshipRequestedParent) = 0;
  68. virtual void OnDiscoveredStation(IstationIGC* pstation) = 0;
  69. virtual void OnDiscoveredAsteroid(IasteroidIGC* pasteroid) = 0;
  70. virtual void OnClusterChanged(IclusterIGC* pcluster) = 0;
  71. virtual void OnGameoverStats() = 0;
  72. virtual void OnGameoverPlayers() = 0;
  73. // chat events
  74. virtual void OnDeleteChatMessage(ChatInfo* pchatInfo) = 0;
  75. virtual void OnNewChatMessage() = 0;
  76. virtual void OnClearChat() = 0;
  77. virtual void OnChatMessageChange() = 0;
  78. // system events
  79. virtual void OnLostConnection(const char * szReason) = 0;
  80. virtual void OnEnterModalState() = 0;
  81. virtual void OnLeaveModalState() = 0;
  82. virtual void OnLogonClub() = 0;
  83. virtual void OnLogonClubFailed(bool bRetry, const char * szReason) = 0;
  84. virtual void OnLogonLobby() = 0;
  85. virtual void OnLogonLobbyFailed(bool bRetry, const char * szReason) = 0;
  86. virtual void OnLogonGameServer() = 0;
  87. virtual void OnLogonGameServerFailed(bool bRetry, const char * szReason) = 0;
  88. };
  89. /////////////////////////////////////////////////////////////////////////////
  90. // IClientEventSink
  91. class IClientEventSink : public IObject
  92. {
  93. public:
  94. static TRef<IClientEventSink> CreateDelegate(IClientEventSink* psink);
  95. // mission events
  96. virtual void OnAddMission(MissionInfo* pMissionDef) {};
  97. virtual void OnDelMission(MissionInfo* pMissionDef) {};
  98. virtual void OnMissionCountdown(MissionInfo* pMissionDef) {};
  99. virtual void OnMissionStarted(MissionInfo* pMissionDef) {};
  100. virtual void OnMissionEnded(MissionInfo* pMissionDef) {};
  101. virtual void OnLockLobby(bool bLock) {};
  102. virtual void OnLockSides(bool bLock) {};
  103. virtual void OnFoundPlayer(MissionInfo* pMissionDef) {};
  104. virtual void OnEnterMission() {};
  105. // team events
  106. virtual void OnAddPlayer(MissionInfo* pMissionDef, SideID sideID, PlayerInfo* pPlayerInfo) {};
  107. virtual void OnDelPlayer(MissionInfo* pMissionDef, SideID sideID, PlayerInfo* pPlayerInfo, QuitSideReason reason, const char* szMessageParam = NULL) {};
  108. virtual void OnAddRequest(MissionInfo* pMissionDef, SideID sideID, PlayerInfo* pPlayerInfo) {};
  109. virtual void OnDelRequest(MissionInfo* pMissionDef, SideID sideID, PlayerInfo* pPlayerInfo, DelPositionReqReason reason) {};
  110. virtual void OnTeamInactive(MissionInfo* pMissionDef, SideID sideID) {};
  111. virtual void OnTeamReadyChange(MissionInfo* pMissionDef, SideID sideID, bool fTeamReady) {};
  112. virtual void OnTeamForceReadyChange(MissionInfo* pMissionDef, SideID sideID, bool fTeamForceReady) {};
  113. virtual void OnTeamAutoAcceptChange(MissionInfo* pMissionDef, SideID sideID, bool fAutoAccept) {};
  114. virtual void OnTeamCivChange(MissionInfo* pMissionDef, SideID sideID, CivID civID) {};
  115. virtual void OnTeamNameChange(MissionInfo* pMissionDef, SideID sideID) {};
  116. // player events
  117. virtual void OnPlayerStatusChange(MissionInfo* pMissionDef, SideID sideID, PlayerInfo* pPlayerInfo) {};
  118. virtual void OnMoneyChange(PlayerInfo* pPlayerInfo) {};
  119. // gameplay events
  120. virtual void OnBucketChange(BucketChange bc, IbucketIGC* b){};
  121. virtual void OnTechTreeChanged(SideID sid){};
  122. virtual void OnStationCaptured(StationID stationID, SideID sideID) {};
  123. virtual void OnModelTerminated(ImodelIGC* pmodel) {};
  124. virtual void OnLoadoutChanged(IpartIGC* ppart, LoadoutChange lc) {};
  125. virtual void OnPurchaseCompleted(bool bAllPartsBought) {};
  126. virtual void OnTurretStateChanging(bool bTurret) {}
  127. virtual void OnShipStatusChange(PlayerInfo* pplayer) {};
  128. virtual void OnBoardShip(IshipIGC* pshipChild, IshipIGC* pshipParent) {};
  129. virtual void OnBoardFailed(IshipIGC* pshipRequestedParent) {};
  130. virtual void OnDiscoveredStation(IstationIGC* pstation) {};
  131. virtual void OnDiscoveredAsteroid(IasteroidIGC* pasteroid) {};
  132. virtual void OnClusterChanged(IclusterIGC* pcluster) {};
  133. virtual void OnGameoverStats() {};
  134. virtual void OnGameoverPlayers() {};
  135. // chat events
  136. virtual void OnDeleteChatMessage(ChatInfo* pchatInfo) {};
  137. virtual void OnNewChatMessage() {};
  138. virtual void OnClearChat() {};
  139. virtual void OnChatMessageChange() {};
  140. // system events
  141. virtual void OnLostConnection(const char * szReason) {};
  142. virtual void OnEnterModalState() {};
  143. virtual void OnLeaveModalState() {};
  144. virtual void OnLogonClub() {};
  145. virtual void OnLogonClubFailed(bool bRetry, const char * szReason) {};
  146. virtual void OnLogonLobby() {};
  147. virtual void OnLogonLobbyFailed(bool bRetry, const char * szReason) {};
  148. virtual void OnLogonGameServer() {};
  149. virtual void OnLogonGameServerFailed(bool bRetry, const char * szReason) {};
  150. };
  151. /////////////////////////////////////////////////////////////////////////////
  152. // ChatInfo
  153. class ChatInfo : public IObject
  154. {
  155. private:
  156. ZString m_strMessage;
  157. Color m_colorMessage;
  158. TRef<ImodelIGC> m_pmodelTarget;
  159. CommandID m_cidCommand;
  160. ChatTarget m_ctRecipient;
  161. bool m_bFromPlayer;
  162. bool m_bFromObjectModel;
  163. bool m_bFromLeader;
  164. public:
  165. void SetChat(ChatTarget ctRecipient,
  166. const ZString& strText,
  167. CommandID cid,
  168. ImodelIGC* pmodelTarget,
  169. const Color& color,
  170. bool bFromPlayer,
  171. bool bFromObjectModel,
  172. bool bFromLeader);
  173. ChatTarget GetChatTarget(void) const { return m_ctRecipient; }
  174. const ZString& GetMessage(void) const { return m_strMessage; }
  175. const Color& GetColor(void) const { return m_colorMessage; }
  176. CommandID GetCommandID(void) const { return m_cidCommand; }
  177. ImodelIGC* GetTarget(void) const { return m_pmodelTarget; }
  178. bool IsFromPlayer(void) const { return m_bFromPlayer; }
  179. bool IsFromLeader(void) const { return m_bFromLeader; }
  180. bool IsFromObjectModel(void) const { return m_bFromObjectModel; }
  181. void ClearTarget(void);
  182. };
  183. typedef Slist_utl<ChatInfo> ChatList;
  184. typedef Slink_utl<ChatInfo> ChatLink;
  185. /////////////////////////////////////////////////////////////////////////////
  186. // BallotInfo
  187. class BallotInfo
  188. {
  189. ZString m_strBallotText;
  190. BallotID m_ballotID;
  191. Time m_timeExpiration;
  192. public:
  193. BallotInfo(const ZString& strBallotText, BallotID ballotID, Time timeExpiration)
  194. : m_strBallotText(strBallotText), m_ballotID(ballotID), m_timeExpiration(timeExpiration) {};
  195. const ZString& GetBallotText() const { return m_strBallotText; }
  196. Time GetBallotExpirationTime() const { return m_timeExpiration; }
  197. BallotID GetBallotID() const { return m_ballotID; }
  198. };
  199. typedef TList<BallotInfo> BallotList;
  200. /////////////////////////////////////////////////////////////////////////////
  201. // PlayerInfo
  202. class PlayerInfo : public IObject
  203. {
  204. FMD_S_PLAYERINFO m_fmPlayerInfo;
  205. TRef<IshipIGC> m_pship;
  206. ImissionIGC* m_pmission;
  207. ShipStatus m_shipStatus;
  208. PersistPlayerScoreObject* m_vPersistPlayerScores;
  209. int m_cPersistPlayerScores;
  210. PersistPlayerScoreObject m_persist; // default new score
  211. bool m_bMute;
  212. public:
  213. PlayerInfo(void);
  214. ~PlayerInfo();
  215. IshipIGC* GetShip(void) const
  216. {
  217. return m_pship;
  218. }
  219. void SetShip(IshipIGC* pship)
  220. {
  221. m_pship = pship;
  222. if (pship)
  223. pship->SetPrivateData((DWORD)this);
  224. }
  225. void SetMission(ImissionIGC* pmission)
  226. {
  227. m_pmission = pmission;
  228. }
  229. bool GetMute(void) const
  230. {
  231. return m_bMute;
  232. }
  233. void SetMute(bool bMute)
  234. {
  235. m_bMute = bMute;
  236. }
  237. void Set(FMD_S_PLAYERINFO* pfmPlayerInfo);
  238. void Update(FMD_CS_PLAYER_READY* pfmPlayerReady) { m_fmPlayerInfo.fReady = pfmPlayerReady->fReady; }
  239. bool IsMissionOwner(void) const { return m_fmPlayerInfo.fMissionOwner; }
  240. void SetMissionOwner(bool fMissionOwner) { m_fmPlayerInfo.fMissionOwner = fMissionOwner; }
  241. bool IsTeamLeader(void) const { return m_fmPlayerInfo.fTeamLeader; }
  242. void SetTeamLeader(bool fTeamLeader) { m_fmPlayerInfo.fTeamLeader = fTeamLeader; }
  243. bool IsReady(void) const { return m_fmPlayerInfo.fReady; }
  244. void SetReady(bool fReady) { m_fmPlayerInfo.fReady = fReady; }
  245. bool IsHuman(void) const { return m_fmPlayerInfo.dtidDrone == NA; }
  246. DroneTypeID GetDroneTypeID(void) const { return m_fmPlayerInfo.dtidDrone; }
  247. short MissionKills(void) const { return m_pship->GetKills(); }
  248. short MissionDeaths(void) const { return m_pship->GetDeaths(); }
  249. short MissionEjections(void) const { return m_pship->GetEjections(); }
  250. void AddDeath() {
  251. m_pship->AddDeath();
  252. }
  253. void AddEjection() {
  254. m_pship->AddEjection();
  255. }
  256. void AddKill() {
  257. m_pship->AddKill();
  258. }
  259. RankID Rank() const {
  260. return GetPersistScore().GetRank();
  261. }
  262. const PersistPlayerScoreObject& GetPersistScore() const { return GetPersistScore(GetCivID()); }
  263. const PersistPlayerScoreObject& GetPersistScore(CivID civId) const;
  264. void UpdateScore(PersistPlayerScoreObject& ppso);
  265. CivID GetCivID() const;
  266. SideID SideID() const { return m_fmPlayerInfo.iSide; }
  267. void SetSideID(::SideID sideID) { m_fmPlayerInfo.iSide = sideID; };
  268. ShipID ShipID() const { return m_fmPlayerInfo.shipID; }
  269. LPCSTR CharacterName() const { return m_fmPlayerInfo.CharacterName; }
  270. Money GetMoney() const { return m_fmPlayerInfo.money; }
  271. void SetMoney(Money money) { m_fmPlayerInfo.money = money; }
  272. const ShipStatus& GetShipStatus(void) const { return m_shipStatus; }
  273. void SetShipStatus(const ShipStatus& ss)
  274. {
  275. ShipStatus ssOld = m_shipStatus;
  276. m_shipStatus = ss;
  277. //If we were known and the sector is changing ... remove the threat/asset
  278. if ((ssOld.GetSectorID() != ss.GetSectorID()) ||
  279. ((ssOld.GetState() == c_ssFlying) != (ss.GetState() == c_ssFlying)) ||
  280. (ssOld.GetUnknown() != ss.GetUnknown()))
  281. {
  282. if ((!ssOld.GetUnknown()) && (ssOld.GetSectorID() != NA))
  283. {
  284. IclusterIGC* pcluster = m_pmission->GetCluster(ssOld.GetSectorID());
  285. assert (pcluster);
  286. if (pcluster)
  287. pcluster->GetClusterSite()->MoveShip();
  288. else
  289. assert(false);
  290. }
  291. if ((!ss.GetUnknown()) && (ss.GetSectorID() != NA))
  292. {
  293. IclusterIGC* pcluster = m_pmission->GetCluster(ss.GetSectorID());
  294. assert (pcluster);
  295. if (pcluster)
  296. pcluster->GetClusterSite()->MoveShip();
  297. else
  298. {
  299. assert(false);
  300. m_shipStatus.SetSectorID(NA);
  301. }
  302. }
  303. }
  304. }
  305. void ResetShipStatus(void)
  306. {
  307. ShipStatus ssOld = m_shipStatus;
  308. m_shipStatus.Reset();
  309. if ((!ssOld.GetUnknown()) && (ssOld.GetSectorID() != NA))
  310. {
  311. IclusterIGC* pcluster = m_pmission->GetCluster(ssOld.GetSectorID());
  312. if (pcluster)
  313. pcluster->GetClusterSite()->MoveShip();
  314. }
  315. }
  316. void Reset(bool bFull)
  317. {
  318. SetMoney(0);
  319. GetShip()->Reset(bFull);
  320. ResetShipStatus();
  321. }
  322. HullID LastSeenShipType() const { return m_shipStatus.GetHullID(); };
  323. SectorID LastSeenSector() const { return m_shipStatus.GetSectorID(); };
  324. StationID LastSeenStation() const { return m_shipStatus.GetStationID(); };
  325. ::ShipID LastSeenParent() const { return m_shipStatus.GetParentID(); };
  326. ShipState LastSeenState() const { return m_shipStatus.GetState(); };
  327. bool StatusIsCurrent() const { return !m_shipStatus.GetUnknown(); }
  328. bool GetDetected() const { return !m_shipStatus.GetDetected(); }
  329. };
  330. typedef Slist_utlListWrapper<PlayerInfo> PlayerList;
  331. typedef Slist_utlListWrapper<PlayerInfo>::Link PlayerLink;
  332. typedef TListListWrapper<IntItemIDWrapper<ShipID> > ShipList;
  333. /////////////////////////////////////////////////////////////////////////////
  334. // SideInfo
  335. class SideInfo
  336. {
  337. protected:
  338. ShipList m_listShipIDMembers;
  339. ShipList m_listShipIDRequests;
  340. SideID m_sideID;
  341. public:
  342. SideInfo(SideID sideID)
  343. { m_sideID = sideID; }
  344. ~SideInfo(){}
  345. void AddPlayer(ShipID shipID) { m_listShipIDMembers.PushEnd(shipID); };
  346. void RemovePlayer(ShipID shipID) { m_listShipIDMembers.Remove(shipID); };
  347. bool FindPlayer(ShipID shipID) { return m_listShipIDMembers.Find(shipID); };
  348. void AddRequest(ShipID shipID) { m_listShipIDRequests.PushEnd(shipID); };
  349. void RemoveRequest(ShipID shipID) { m_listShipIDRequests.Remove(shipID); };
  350. bool FindRequest(ShipID shipID) { return m_listShipIDRequests.Find(shipID); };
  351. ShipList& GetMembers() { return m_listShipIDMembers; }
  352. List* GetMemberList() { return new ListDelegate(&m_listShipIDMembers); }
  353. ShipList& GetRequests() { return m_listShipIDRequests; }
  354. List* GetRequestList() { return new ListDelegate(&m_listShipIDRequests); }
  355. SideID GetSideID() { return m_sideID; };
  356. };
  357. /////////////////////////////////////////////////////////////////////////////
  358. // MissionInfo
  359. class MissionInfo
  360. {
  361. protected:
  362. FMD_S_MISSIONDEF* m_pfmMissionDef;
  363. TMapListWrapper<SideID, SideInfo*> m_mapSideInfo;
  364. SideInfo m_sideLobby;
  365. int m_nNumPlayers;
  366. ZString m_strGameDetailsFiles;
  367. SquadID squadIDs[c_cSidesMax];
  368. bool m_fGuaranteedSlotsAvailable;
  369. bool m_fAnySlotsAvailable;
  370. bool m_fCountdownStarted;
  371. public:
  372. MissionInfo(DWORD dwCookie);
  373. ~MissionInfo();
  374. // Operations
  375. void Update(FMD_S_MISSIONDEF* pfmMissionDef);
  376. void Update(FMD_LS_LOBBYMISSIONINFO* pfmLobbyMissionInfo);
  377. void UpdateStartTime(Time timeStart);
  378. void SetInProgress(bool fInProgress) { m_pfmMissionDef->fInProgress = fInProgress; }
  379. void SetCountdownStarted(bool fCountdownStarted) { m_fCountdownStarted = fCountdownStarted; }
  380. STAGE GetStage() { return m_pfmMissionDef->stage; }
  381. void SetStage(STAGE stage) { m_pfmMissionDef->stage = stage; };
  382. void AddPlayer(PlayerInfo* pPlayerInfo);
  383. void RemovePlayer(PlayerInfo* pPlayerInfo);
  384. bool FindPlayer(SideID sideID, ShipID shipID);
  385. void AddRequest(SideID sideID, ShipID shipID);
  386. void RemoveRequest(SideID sideID, ShipID shipID);
  387. bool FindRequest(SideID sideID, ShipID shipID);
  388. bool GetAnySlotsAreAvailable() { return m_fAnySlotsAvailable; };
  389. bool GetGuaranteedSlotsAreAvailable() { return m_fGuaranteedSlotsAvailable; };
  390. void SetLockLobby(bool bLock) { m_pfmMissionDef->misparms.bLockLobby = bLock; };
  391. bool GetLockLobby() { return m_pfmMissionDef->misparms.bLockLobby; };
  392. void SetLockSides(bool bLock) { m_pfmMissionDef->misparms.bLockSides = bLock; };
  393. bool GetLockSides() { return m_pfmMissionDef->misparms.bLockSides; };
  394. // Mission Accessors
  395. SideID NumSides() { return m_pfmMissionDef->misparms.nTeams; }
  396. bool InProgress() { return !!m_pfmMissionDef->fInProgress; }
  397. bool CountdownStarted() { return m_fCountdownStarted; }
  398. LPCSTR Name() { return m_pfmMissionDef->misparms.strGameName; }
  399. LPCSTR Description() { return m_pfmMissionDef->szDescription; }
  400. DWORD GetCookie() { return m_pfmMissionDef->dwCookie; }
  401. SideID MissionOwnerSideID() { return m_pfmMissionDef->iSideMissionOwner; }
  402. ShipID MissionOwnerShipID() { return SideLeaderShipID( MissionOwnerSideID() ); }
  403. bool AutoAcceptLeaders() { return m_pfmMissionDef->fAutoAcceptLeaders; }
  404. int MaxPlayers() { return m_pfmMissionDef->misparms.nTotalMaxPlayersPerGame; }
  405. int NumPlayers() { return m_nNumPlayers; };
  406. int AvailablePositions() { return MaxPlayers() - NumPlayers(); }
  407. int GuaranteedPositions();
  408. unsigned char MinPlayersPerTeam() { return m_pfmMissionDef->misparms.nMinPlayersPerTeam; }
  409. unsigned char MaxPlayersPerTeam() { return m_pfmMissionDef->misparms.nMaxPlayersPerTeam; }
  410. short MaxImbalance() { return m_pfmMissionDef->misparms.iMaxImbalance; }
  411. bool ScoresCount() { return m_pfmMissionDef->misparms.bScoresCount; }
  412. bool GoalConquest() { return m_pfmMissionDef->misparms.IsConquestGame(); }
  413. bool GoalDeathMatch() { return m_pfmMissionDef->misparms.IsDeathMatchGame(); }
  414. bool GoalCountdown() { return m_pfmMissionDef->misparms.IsCountdownGame(); }
  415. bool GoalProsperity() { return m_pfmMissionDef->misparms.IsProsperityGame(); }
  416. bool GoalArtifacts() { return m_pfmMissionDef->misparms.IsArtifactsGame(); }
  417. bool GoalFlags() { return m_pfmMissionDef->misparms.IsFlagsGame(); }
  418. bool GoalTerritory() { return m_pfmMissionDef->misparms.IsTerritoryGame(); }
  419. bool WasObjectModelCreated() { return m_pfmMissionDef->misparms.bObjectModelCreated; }
  420. bool AllowDevelopments() { return m_pfmMissionDef->misparms.bAllowDevelopments; }
  421. bool LimitedLives() { return m_pfmMissionDef->misparms.iLives != 0x7fff; }
  422. Time StartTime() { assert(InProgress()); return m_pfmMissionDef->misparms.timeStart; }
  423. const MissionParams& GetMissionParams() { return m_pfmMissionDef->misparms; }
  424. const FMD_S_MISSIONDEF& GetMissionDef() { return *m_pfmMissionDef; }
  425. void PurgePlayers();
  426. short GetMinRank() { return m_pfmMissionDef->misparms.iMinRank; };
  427. short GetMaxRank() { return m_pfmMissionDef->misparms.iMaxRank; };
  428. int GetSlotsLeft() { return m_pfmMissionDef->misparms.nMaxPlayersPerTeam
  429. * m_pfmMissionDef->misparms.nTeams
  430. - m_nNumPlayers; };
  431. const ZString& GetDetailsFiles() { return m_strGameDetailsFiles; }
  432. // Team Accessors
  433. LPCSTR SideName(SideID sideID) { return (sideID == SIDE_TEAMLOBBY) ? "Not on a team" : m_pfmMissionDef->rgszName[sideID]; }
  434. //CivID SideCivID(SideID sideID) { return (sideID == SIDE_TEAMLOBBY) ? NA : m_pfmMissionDef->rgCivID[sideID]; }
  435. ShipID SideLeaderShipID(SideID sideID) { return (sideID == SIDE_TEAMLOBBY) ? NA : m_pfmMissionDef->rgShipIDLeaders[sideID]; }
  436. bool SideAutoAccept(SideID sideID) { return (sideID == SIDE_TEAMLOBBY) ? true : !!m_pfmMissionDef->rgfAutoAccept[sideID]; }
  437. bool SideReady(SideID sideID) { return (sideID == SIDE_TEAMLOBBY) ? true : !!m_pfmMissionDef->rgfReady[sideID]; }
  438. bool SideForceReady(SideID sideID) { return (sideID == SIDE_TEAMLOBBY) ? true : !!m_pfmMissionDef->rgfForceReady[sideID]; }
  439. char SideMaxPlayers(SideID sideID) { return (sideID == SIDE_TEAMLOBBY) ? 1000 : m_pfmMissionDef->misparms.nMaxPlayersPerTeam; }
  440. char SideNumPlayers(SideID sideID) { return (sideID == SIDE_TEAMLOBBY) ? 0 : m_pfmMissionDef->rgcPlayers[sideID]; }
  441. int SideAvailablePositions(SideID sideID) { return (sideID == SIDE_TEAMLOBBY) ? 1000 : (SideMaxPlayers(sideID) - SideNumPlayers(sideID)); }
  442. int SideActive(SideID sideID) { return (sideID == SIDE_TEAMLOBBY) ? true : (m_pfmMissionDef->rgfActive[sideID] != 0); }
  443. bool HasSquad(SquadID squadID);
  444. // Team Operations
  445. void SetSideActive(SideID sideID, bool fActive)
  446. { assert(sideID != SIDE_TEAMLOBBY); m_pfmMissionDef->rgfActive[sideID] = fActive; }
  447. void SetSideAutoAccept(SideID sideID, bool fAutoAccept)
  448. { assert(sideID != SIDE_TEAMLOBBY); m_pfmMissionDef->rgfAutoAccept[sideID] = fAutoAccept; }
  449. void SetSideReady(SideID sideID, bool fReady)
  450. { assert(sideID != SIDE_TEAMLOBBY); m_pfmMissionDef->rgfReady[sideID] = fReady; }
  451. void SetSideForceReady(SideID sideID, bool fForceReady)
  452. { assert(sideID != SIDE_TEAMLOBBY); m_pfmMissionDef->rgfForceReady[sideID] = fForceReady; }
  453. void SetSideLeader(PlayerInfo* pPlayerInfo);
  454. /*void SetSideCivID(SideID sideID, CivID civID)
  455. { assert(sideID != SIDE_TEAMLOBBY); m_pfmMissionDef->rgCivID[sideID] = civID;
  456. GetSideInfo(sideID)->GetMembers().GetSink()(); m_mapSideInfo.GetSink()(); }*/
  457. void SetSideName(SideID sideID, const char* szName)
  458. { assert(sideID != SIDE_TEAMLOBBY); strcpy(m_pfmMissionDef->rgszName[sideID], szName);
  459. m_mapSideInfo.GetSink()(); }
  460. void SetSideSquadID(SideID sideID, SquadID squadID)
  461. { assert(sideID != SIDE_TEAMLOBBY); squadIDs[sideID] = squadID; m_mapSideInfo.GetSink()(); }
  462. SideInfo* GetSideInfo(SideID sideID);
  463. List* GetSideList();
  464. const char * GetIGCStaticFile()
  465. { return m_pfmMissionDef->misparms.szIGCStaticFile; }
  466. int GetIGCStaticVer()
  467. { return m_pfmMissionDef->misparms.verIGCcore;}
  468. };
  469. /////////////////////////////////////////////////////////////////////////////
  470. // BucketStatusArray
  471. typedef TVector<Money> MoneyVector;
  472. class BucketStatusArray : public MoneyVector, public IObjectSingle
  473. {
  474. };
  475. class CfgInfo
  476. {
  477. public:
  478. void Load(const char * szConfig);
  479. ZString strClubLobby;
  480. ZString strPublicLobby;
  481. ZString strClub;
  482. ZString strZAuth;
  483. ZString strClubMessageURL;
  484. ZString strPublicMessageURL;
  485. ZString strZoneEventsURL;
  486. ZString strZoneEventDetailsURL;
  487. ZString strTrainingURL;
  488. ZString strPassportUpdateURL;
  489. GUID guidZoneAuth;
  490. int crcFileList;
  491. int nFilelistSize;
  492. ZString strFilelistSite;
  493. ZString strFilelistDirectory;
  494. int crcClubMessageFile;
  495. int crcPublicMessageFile;
  496. bool bUsePassport;
  497. };
  498. struct LANServerInfo : public IObject
  499. {
  500. LANServerInfo(REFGUID guidSession_, const ZString& strGameName_, short nNumPlayers_, short nMaxPlayers_)
  501. : strGameName(strGameName_), nNumPlayers(nNumPlayers_), nMaxPlayers(nMaxPlayers_)
  502. { memcpy(&guidSession, &guidSession_, sizeof(GUID)); }
  503. GUID guidSession;
  504. ZString strGameName;
  505. short nNumPlayers;
  506. short nMaxPlayers;
  507. };
  508. /////////////////////////////////////////////////////////////////////////////
  509. // BaseClient
  510. class BaseClient :
  511. public IIgcSite,
  512. IFedMessagingSite
  513. {
  514. public:
  515. enum
  516. {
  517. lockdownDonating = 1,
  518. lockdownLoadout = 2,
  519. lockdownTeleporting = 4
  520. };
  521. typedef int LockdownCriteria;
  522. private:
  523. PlayerInfo* m_pPlayerInfo;
  524. IshipIGC* m_ship;
  525. IclusterIGC* m_viewCluster;
  526. bool m_bInGame;
  527. bool m_bWaitingForGameRestart;
  528. ZString m_strLockDownReason;
  529. bool m_bLaunchAfterDisembark;
  530. ShipID m_sidBoardAfterDisembark;
  531. StationID m_sidTeleportAfterDisembark;
  532. TRef<ImodelIGC> m_pmodelServerTarget;
  533. LockdownCriteria m_lockdownCriteria;
  534. TRef<IshipIGC> m_pshipLastSender;
  535. CfgInfo m_cfginfo;
  536. Money m_money;
  537. Money m_moneyLastRequest;
  538. RankInfo* m_vRankInfo;
  539. short m_cRankInfo;
  540. StaticMapInfo* m_vStaticMapInfo;
  541. short m_cStaticMapInfo;
  542. ZString m_strCDKey;
  543. BallotList m_listBallots;
  544. public: //todo: make protected
  545. // messaging
  546. enum MessageType
  547. {
  548. c_mtNone,
  549. c_mtGuaranteed,
  550. c_mtNonGuaranteed
  551. };
  552. struct ConnectInfo // everything we need to connect and log on to the server
  553. {
  554. public:
  555. ConnectInfo() :
  556. pZoneTicket(NULL),
  557. cbZoneTicket(0)
  558. {
  559. ZeroMemory(&ftLastArtUpdate, sizeof(ftLastArtUpdate));
  560. ZeroMemory(szName, sizeof(szName));
  561. }
  562. FILETIME ftLastArtUpdate;
  563. ZString strServer;
  564. char szName [c_cbName];
  565. LPBYTE pZoneTicket;
  566. CB cbZoneTicket;
  567. GUID guidSession;
  568. };
  569. bool m_fLoggedOn : 1;
  570. bool m_fZoneClub : 1;
  571. bool m_fIsLobbied : 1;
  572. bool m_fLoggedOnToLobby : 1;
  573. bool m_fLoggedOnToClub : 1;
  574. bool m_serverOffsetValidF : 1;
  575. bool m_terminatedF : 1;
  576. FedMessaging m_fm;
  577. FedMessaging m_fmLobby;
  578. FedMessaging m_fmClub;
  579. ConnectInfo m_ci; // we're just going to remember this from when they log into the lobby, and reuse it when they log into the game server
  580. DWORD m_serverLag;
  581. DWORD m_serverOffset;
  582. DWORD m_lobbyServerOffset;
  583. Time m_timeLastPing;
  584. Time m_timeLastPingServer;
  585. Time m_timeLastServerMessage;
  586. Time m_lastSend;
  587. Time m_lastLagCheck;
  588. int m_cUnansweredPings;
  589. float m_sync;
  590. Cookie m_cookie;
  591. MessageType m_messageType;
  592. char m_szCharName[c_cbName];
  593. char m_szClubCharName[c_cbName]; // name specified when logging into Club server
  594. char m_szLobbyCharName[c_cbName];// name specified when logging into Lobby server
  595. char m_szIGCStaticFile[30];
  596. int m_nMemberID; // For Zone Club server
  597. // igc
  598. ImissionIGC* m_pCoreIGC;
  599. // client state information
  600. MissionInfo* m_pMissionInfo;
  601. DWORD m_dwCookieToJoin;
  602. char m_strPasswordToJoin[c_cbGamePassword];
  603. Mount m_selectedWeapon;
  604. int m_oldStateM;
  605. ZString m_strBriefingText;
  606. bool m_bGenerateCivBriefing;
  607. //IclusterIGC* m_cluster;
  608. //TRef<IsideIGC> m_side;
  609. //ShipID m_shipID;
  610. //StationID m_stationID;
  611. bool bInitTrekJoyStick; // moved from trekClient to here
  612. // cached time for all messages from a single FedMessaging::ReceiveMessages call
  613. Time m_lastUpdate;
  614. Time m_now;
  615. // tech advancement
  616. TMap<StationID, TRef<BucketStatusArray> > m_mapBucketStatusArray;
  617. // missions
  618. TMapListWrapper<DWORD, MissionInfo*> m_mapMissions;
  619. TRef<ListDelegate> m_plistMissions;
  620. // players
  621. PlayerList m_listPlayers;
  622. // event notification
  623. TRef<IClientEventSource> m_pClientEventSource;
  624. // chat
  625. ChatList m_chatList;
  626. ChatLink* m_plinkSelectedChat;
  627. TRef<IchaffIGC> m_pchaffLastCreated;
  628. CachedLoadoutList m_loadouts;
  629. IAutoDownload * m_pAutoDownload;
  630. #ifdef USEAUTH
  631. TRef<IZoneAuthClient> m_pzac;
  632. #endif
  633. TList<TRef<LANServerInfo> >* m_plistFindServerResults;
  634. public:
  635. BaseClient();
  636. virtual ~BaseClient();
  637. virtual void Initialize(Time timeNow);
  638. virtual void Reinitialize(Time timeNow);
  639. virtual void Terminate();
  640. virtual void FlushGameState();
  641. virtual void CreateMissionReq();
  642. virtual void JoinMission(MissionInfo * pMission, const char* szMissionPassword);
  643. // AutoDownload functions
  644. virtual IAutoUpdateSink * OnBeginAutoUpdate(IAutoUpdateSink * pSink, bool bConnectToLobby) { return NULL; }
  645. virtual bool ShouldCheckFiles() { return false; }
  646. void HandleAutoDownload(DWORD dwTimeAlloted);
  647. virtual const char* GetArtPath() { return NULL; } // This should be overridden in Wintrek/PIGS
  648. virtual bool ResetStaticData(const char * szIGCStaticFile, ImissionIGC** ppStaticIGC, Time tNow, bool bEncrypt);
  649. virtual Time ServerTimeFromClientTime(Time timeClient)
  650. {
  651. ShouldBe(!GetNetwork() || m_serverOffsetValidF);
  652. return Time(timeClient.clock() + m_serverOffset);
  653. }
  654. virtual Time ClientTimeFromServerTime(Time timeServer)
  655. {
  656. ShouldBe(!GetNetwork() || m_serverOffsetValidF);
  657. return Time(timeServer.clock() - m_serverOffset);
  658. }
  659. // messaging
  660. virtual HRESULT ConnectToLobby(ConnectInfo * pci); // pci is NULL if relogging in
  661. virtual HRESULT ConnectToServer(ConnectInfo & ci, DWORD dwCookie, Time now, const char* szPassword, bool bStandalonePrivate);
  662. virtual HRESULT ConnectToClub(ConnectInfo * pci);
  663. virtual void FindStandaloneServersByName(const char* szName, TList<TRef<LANServerInfo> >& listResults);
  664. bool LoggedOn()
  665. {
  666. return m_fLoggedOn;
  667. }
  668. bool LoggedOnToLobby()
  669. {
  670. return m_fLoggedOnToLobby;
  671. }
  672. bool LoggedOnToClub()
  673. {
  674. return m_fLoggedOnToClub;
  675. }
  676. virtual void OverrideCamera(ImodelIGC* pmodel) {}
  677. const ZString& GetCDKey()
  678. {
  679. return m_strCDKey;
  680. }
  681. virtual void SetCDKey(const ZString& strCDKey);
  682. virtual void OnLogonAck(bool fValidated, bool bRetry, LPCSTR szFailureReason) = 0;
  683. virtual void OnLogonLobbyAck(bool fValidated, bool bRetry, LPCSTR szFailureReason) = 0;
  684. virtual void OnLogonClubAck(bool fValidated, bool bRetry, LPCSTR szFailureReason) {};
  685. virtual void Disconnect();
  686. virtual void DisconnectLobby();
  687. virtual void DisconnectClub();
  688. void SetCookie(Cookie cookie)
  689. {
  690. m_cookie = cookie;
  691. }
  692. Cookie GetCookie()
  693. {
  694. return m_cookie;
  695. }
  696. void SetMessageType(MessageType mt);
  697. void SendMessages();
  698. void SendLobbyMessages()
  699. {
  700. m_fmLobby.SendMessages(m_fmLobby.GetServerConnection(), FM_GUARANTEED, FM_FLUSH);
  701. }
  702. void SendClubMessages()
  703. {
  704. m_fmClub.SendMessages(m_fmClub.GetServerConnection(), FM_GUARANTEED, FM_FLUSH);
  705. }
  706. virtual HRESULT ReceiveMessages(void);
  707. virtual HRESULT OnSessionLost(char * szReason, FedMessaging * pthis);
  708. virtual void OnSessionFound(FedMessaging * pthis, FMSessionDesc * pSessionDesc);
  709. virtual HRESULT HandleMsg(FEDMESSAGE* pfm, Time lastUpdate, Time now);
  710. bool GetIsZoneClub()
  711. {
  712. return m_fZoneClub;
  713. }
  714. void SetIsZoneClub(bool fzc)
  715. {
  716. m_fZoneClub = fzc;
  717. }
  718. bool GetIsLobbied()
  719. {
  720. return m_fIsLobbied;
  721. }
  722. void SetIsLobbied(bool fzc)
  723. {
  724. m_fIsLobbied = fzc;
  725. }
  726. #ifdef USEAUTH
  727. TRef<IZoneAuthClient> GetZoneAuthClient()
  728. {
  729. return m_pzac;
  730. }
  731. TRef<IZoneAuthClient> CreateZoneAuthClient()
  732. {
  733. m_pzac = ::CreateZoneAuthClient();
  734. return m_pzac;
  735. }
  736. void FreeZoneAuthClient()
  737. {
  738. m_pzac = NULL;
  739. }
  740. #endif
  741. //HRESULT HandleShipUpdate(Time timeUpdate, const LightShipUpdate& shipupdate);
  742. //HRESULT HandleShipUpdate(Time timeUpdate, const HeavyShipUpdate& shipupdate);
  743. // FedMessagingSite
  744. virtual HRESULT OnSessionLost(FedMessaging * pthis);
  745. virtual void OnMessageNAK(FedMessaging * pthis, DWORD dwTime, CFMRecipient * prcp);
  746. // game state
  747. inline ImissionIGC* GetCore() { return m_pCoreIGC; }
  748. PlayerInfo* MyPlayerInfo() { return m_pPlayerInfo; }
  749. MissionInfo* MyMission() { return m_pMissionInfo; }
  750. bool MyMissionInProgress();
  751. inline bool IsInGame(void) const { return m_bInGame; };
  752. inline bool IsWaitingForGameRestart(void) const { return m_bWaitingForGameRestart; };
  753. const ZString& GetBriefingText(void) const { return m_strBriefingText; }
  754. inline bool GenerateCivBriefing(void) const { return m_bGenerateCivBriefing; }
  755. inline IsideIGC* GetSide(void) const { return m_ship->GetSide(); }
  756. inline SideID GetSideID(void) const { IsideIGC* s = GetSide(); return s ? s->GetObjectID() : NA; }
  757. TList<SquadMembership>& GetSquadMemberships() { return m_squadmemberships; }
  758. virtual void SaveSquadMemberships(const char* szCharacterName);
  759. virtual void RestoreSquadMemberships(const char* szCharacterName);
  760. bool HasPlayerSquad(MissionInfo* pMission);
  761. void SetPlayerInfo(PlayerInfo* ppinfo);
  762. inline PlayerInfo* GetPlayerInfo(void) const { return m_pPlayerInfo; }
  763. PlayerList * GetPlayerList() { return(&m_listPlayers); }
  764. List* PlayerList() { return new ListDelegate(&m_listPlayers); }
  765. void SetMoney(Money m);
  766. inline Money GetMoney() const { return m_pPlayerInfo ? m_pPlayerInfo->GetMoney() : 0; }
  767. inline ShipID GetShipID() const { return m_ship->GetObjectID(); }
  768. inline IshipIGC* GetShip() const { return m_ship; }
  769. inline IclusterIGC* GetCluster() const {assert (m_ship); return m_viewCluster ? m_viewCluster : (m_ship ? m_ship->GetCluster() : NULL); }
  770. IclusterIGC* GetChatCluster() const
  771. {
  772. IclusterIGC* pcluster = GetCluster();
  773. if (!pcluster)
  774. {
  775. IstationIGC* pstation = m_ship->GetStation();
  776. assert (pstation);
  777. if (pstation)
  778. pcluster = pstation->GetCluster();
  779. }
  780. assert (pcluster);
  781. return pcluster;
  782. }
  783. void CreateBuildingEffect(Time now, IasteroidIGC* pasteroid, IshipIGC* pshipBuilder)
  784. {
  785. assert (pasteroid);
  786. assert (pshipBuilder);
  787. assert (pshipBuilder->GetPilotType() == c_ptBuilder);
  788. assert (pshipBuilder->GetBaseData());
  789. assert (pshipBuilder->GetCluster());
  790. IbuildingEffectIGC* pbe = pshipBuilder->GetCluster()->CreateBuildingEffect(now,
  791. pasteroid,
  792. NULL,
  793. pshipBuilder,
  794. pasteroid->GetRadius(),
  795. ((IstationTypeIGC*)(pshipBuilder->GetBaseData()))->GetRadius(),
  796. pshipBuilder->GetPosition() - pshipBuilder->GetOrientation().GetBackward() * pshipBuilder->GetRadius(),
  797. pasteroid->GetPosition());
  798. }
  799. IclusterIGC* GetCluster(IshipIGC* pship, ImodelIGC* pmodel)
  800. {
  801. IclusterIGC* pcluster = pmodel->GetCluster();
  802. if (pcluster == NULL)
  803. {
  804. if (pmodel->GetObjectType() == OT_ship)
  805. {
  806. PlayerInfo* ppi = (PlayerInfo*)(((IshipIGC*)pmodel)->GetPrivateData());
  807. if (ppi->StatusIsCurrent())
  808. pcluster = m_pCoreIGC->GetCluster(ppi->LastSeenSector());
  809. }
  810. }
  811. else if (!pship->CanSee(pmodel))
  812. pcluster = NULL;
  813. return pcluster;
  814. }
  815. IclusterIGC* GetRipcordCluster(IshipIGC* pship, HullAbilityBitMask habm)
  816. {
  817. PlayerInfo* ppi = (PlayerInfo*)(pship->GetPrivateData());
  818. if (ppi->StatusIsCurrent() && (ppi->LastSeenState() == c_ssFlying))
  819. {
  820. SectorID sid = ppi->LastSeenSector();
  821. if (sid != NA)
  822. {
  823. IhullTypeIGC* pht = m_pCoreIGC->GetHullType(ppi->LastSeenShipType());
  824. if (pht && pht->HasCapability(habm))
  825. {
  826. IclusterIGC* pcluster = pship->GetCluster();
  827. return pcluster
  828. ? pcluster
  829. : m_pCoreIGC->GetCluster(ppi->LastSeenSector());
  830. }
  831. }
  832. }
  833. return NULL;
  834. }
  835. void SetWing(WingID wid, IshipIGC* pship = NULL)
  836. {
  837. if (pship == NULL)
  838. pship = m_ship;
  839. pship->SetWingID(wid);
  840. if (m_fm.IsConnected())
  841. {
  842. SetMessageType(BaseClient::c_mtGuaranteed);
  843. BEGIN_PFM_CREATE(m_fm, pfmSetWingID, CS, SET_WINGID)
  844. END_PFM_CREATE
  845. pfmSetWingID->shipID = pship->GetObjectID();
  846. pfmSetWingID->wingID = wid;
  847. }
  848. }
  849. void RequestRipcord(IshipIGC* pship, IclusterIGC* pcluster)
  850. {
  851. if (pship == m_ship)
  852. {
  853. SetMessageType(BaseClient::c_mtGuaranteed);
  854. BEGIN_PFM_CREATE(m_fm, pfmRequest, C, RIPCORD_REQUEST)
  855. END_PFM_CREATE;
  856. pfmRequest->sidRipcord = pcluster ? pcluster->GetObjectID() : NA;
  857. }
  858. }
  859. IclusterIGC* GetViewCluster() const { return m_viewCluster; }
  860. virtual void SetViewCluster(IclusterIGC* pcluster, const Vector* pposition = NULL);
  861. virtual void RequestViewCluster(IclusterIGC* pcluster, ImodelIGC* pmodelTarget = NULL) { SetViewCluster(pcluster); }
  862. virtual void ResetShip(void);
  863. virtual void ResetClusterScanners(IsideIGC* pside);
  864. virtual void BuyLoadout(IshipIGC* pshipLoadout, bool bLaunch);
  865. virtual IshipIGC* CreateEmptyShip(ShipID sid = -2);
  866. virtual IshipIGC* CopyCurrentShip(void);
  867. virtual void PreviousWeapon();
  868. virtual bool SendUpdate(Time now);
  869. IweaponIGC* GetWeapon();
  870. virtual void NextWeapon();
  871. virtual void SetSelectedWeapon(Mount id);
  872. bool flyingF(void) const
  873. {
  874. return
  875. (m_ship != NULL)
  876. && (m_ship->GetCluster() != NULL);
  877. }
  878. bool autoPilot() { return m_ship->GetAutopilot(); }
  879. void SetAutoPilot(bool autoPilot);
  880. void CheckServerLag(Time now);
  881. ChatList* GetChatList(void) { return &m_chatList; }
  882. // Helpers
  883. MissionInfo* GetLobbyMission(DWORD dwCookie);
  884. PlayerLink* FindPlayerLink(ShipID shipID);
  885. PlayerInfo* FindAndCreatePlayerLink (ShipID shipID);
  886. PlayerInfo* FindPlayer(ShipID shipID);
  887. PlayerInfo* FindPlayer(const char* szName);
  888. PlayerInfo* FindPlayerByPrefix(const char* szNamePrefix);
  889. ZString LookupRankName(RankID rank, CivID civ = -1);
  890. const StaticMapInfo& GetStaticMapInfo(int index) { assert(index >= 0 && index < m_cStaticMapInfo); return m_vStaticMapInfo[index]; };
  891. int GetNumStaticMaps() { return m_cStaticMapInfo; };
  892. List* GetMissionList();
  893. void QuitMission();
  894. Money GetBucketStatus(StationID stationID, short iBucket);
  895. Money AddMoneyToBucket(IbucketIGC* b, Money m);
  896. void DonateMoney(PlayerInfo* pPlayerInfo, Money money);
  897. FedMessaging* GetNetwork()
  898. {
  899. return &m_fm;
  900. }
  901. FedMessaging* GetFMLobby()
  902. {
  903. return &m_fmLobby;
  904. }
  905. // Chat message handling
  906. bool ParseShellCommand(const char* pszCommand);
  907. virtual void SendChat(IshipIGC* pshipSender,
  908. ChatTarget ctRecipient,
  909. ObjectID oidRecipient,
  910. SoundID soundID,
  911. const char* pszText,
  912. CommandID cid = c_cidNone,
  913. ObjectType otTarget = NA,
  914. ObjectID oidTarget = NA,
  915. ImodelIGC* pmodelTarget = NULL,
  916. bool bObjectModel = false);
  917. virtual void ReceiveChat(IshipIGC* pshipSender,
  918. ChatTarget ctRecipient,
  919. ObjectID oidRecipient,
  920. SoundID voiceOver,
  921. const char* szText,
  922. CommandID cid,
  923. ObjectType otTarget,
  924. ObjectID oidTarget,
  925. ImodelIGC* pmodelTarget = NULL,
  926. bool bObjectModel = false);
  927. void ScrollChatUp(void);
  928. void ScrollChatDown(void);
  929. ChatInfo* GetCurrentMessage(void);
  930. BallotInfo* GetCurrentBallot();
  931. void Vote(bool bAgree);
  932. void SkipCurrentBallot();
  933. // event notification
  934. IClientEventSource* GetClientEventSource() { return m_pClientEventSource; }
  935. void SendAllMissions(IClientEventSink* pSink);
  936. void SendAllPlayers(IClientEventSink* pSink, MissionInfo* pMissionInfo, SideID sideID);
  937. void SendAllRequests(IClientEventSink* pSink, MissionInfo* pMissionInfo, SideID sideID);
  938. void SendAllBucketStatus(IClientEventSink* pSink, StationID stationID);
  939. //
  940. // IGC Site Implementation
  941. //
  942. virtual void TerminateModelEvent(ImodelIGC* model);
  943. virtual void KillAsteroidEvent(IasteroidIGC* pasteroid, bool explodeF);
  944. virtual void KillProbeEvent(IprobeIGC* pprobe);
  945. virtual void KillMineEvent(ImineIGC* pmine);
  946. virtual void KillMissileEvent(ImissileIGC* pmissile, const Vector& position);
  947. virtual void KillShipEvent(Time now, IshipIGC* ship, ImodelIGC* launcher, float amount, const Vector& p1, const Vector& p2);
  948. virtual void DamageStationEvent(IstationIGC* station, ImodelIGC* launcher, DamageTypeID type, float amount, float leakage);
  949. virtual void KillStationEvent(IstationIGC* station, ImodelIGC* launcher, float amount, float leakage);
  950. virtual void FireMissile(IshipIGC* pship, ImagazineIGC* pmagazine,
  951. Time timeFired, ImodelIGC* pTarget, float lock);
  952. virtual void FireExpendable(IshipIGC* pShip,
  953. IdispenserIGC* pDispenser,
  954. Time timeFired);
  955. virtual void BucketChangeEvent(BucketChange bc, IbucketIGC* b);
  956. virtual void SideBuildingTechChange(IsideIGC* s);
  957. virtual void SideDevelopmentTechChange(IsideIGC* s);
  958. virtual void StationTypeChange(IstationIGC* s);
  959. virtual void LoadoutChangeEvent(IshipIGC* pship, IpartIGC* ppart, LoadoutChange lc);
  960. virtual bool Reload(IshipIGC* pship, IlauncherIGC* plauncher, EquipmentType type);
  961. static short BuyPartOnBudget(IshipIGC* pship,
  962. IpartTypeIGC* ppt,
  963. Mount mount,
  964. Money* pbudget)
  965. {
  966. Money price = ppt->GetPrice();
  967. short amount;
  968. if (price != 0)
  969. {
  970. if (IlauncherTypeIGC::IsLauncherType(ppt->GetEquipmentType()))
  971. {
  972. amount = ppt->GetAmount(pship);
  973. if (price * amount > *pbudget)
  974. {
  975. assert (price > 0);
  976. amount = *pbudget / price;
  977. }
  978. price *= amount;
  979. }
  980. else
  981. amount = (*pbudget >= price) ? 0x7fff : 0;
  982. }
  983. else
  984. amount = 0x7fff;
  985. if (amount != 0)
  986. {
  987. *pbudget -= price;
  988. pship->CreateAndAddPart(ppt, mount, amount);
  989. }
  990. return amount;
  991. }
  992. static void TryToBuyParts(IshipIGC* pship,
  993. IstationIGC* pstation,
  994. Money* pbudget,
  995. IhullTypeIGC* pht,
  996. const PartTypeListIGC* ppartsShip)
  997. {
  998. assert (pship);
  999. assert (pstation);
  1000. assert (*pbudget >= 0);
  1001. assert (pship->GetBaseHullType() == pht);
  1002. for (PartTypeLinkIGC* ptl = ppartsShip->first();
  1003. (ptl != NULL);
  1004. ptl = ptl->next())
  1005. {
  1006. IpartTypeIGC* ppt = ptl->data();
  1007. if (pstation->CanBuy(ppt))
  1008. {
  1009. ppt = (IpartTypeIGC*)(pstation->GetSuccessor(ppt));
  1010. assert (pstation->CanBuy(ppt));
  1011. //We can buy this part ... try mounting it somewhere
  1012. EquipmentType et = ppt->GetEquipmentType();
  1013. Mount iMountMax = (et == ET_Weapon)
  1014. ? pht->GetMaxWeapons()
  1015. : 1;
  1016. for (Mount i = 0; (i < iMountMax); i++)
  1017. {
  1018. //If the slot is empty and we can mount the part in the slot
  1019. if ((pship->GetMountedPart(et, i) == NULL) && pht->CanMount(ppt, i))
  1020. {
  1021. if (BuyPartOnBudget(pship, ppt, i, pbudget) == 0)
  1022. break; //Ran out of money ... don't try to mount any more instances of this part
  1023. }
  1024. }
  1025. }
  1026. }
  1027. }
  1028. void ClearLoadout(void)
  1029. {
  1030. m_loadouts.purge();
  1031. m_bLaunchAfterDisembark = false;
  1032. m_sidBoardAfterDisembark = NA;
  1033. m_sidTeleportAfterDisembark = NA;
  1034. }
  1035. void DisembarkAndLaunch()
  1036. {
  1037. m_bLaunchAfterDisembark = true;
  1038. BoardShip(NULL);
  1039. }
  1040. void DisembarkAndBuy(IshipIGC* pship, bool fLaunch)
  1041. {
  1042. CachedLoadoutLink* pcll = SaveLoadout(pship);
  1043. //Hack ... make sure this is first in the list of loadouts (so it is picked when
  1044. //we need a default configuration)
  1045. m_loadouts.first(pcll);
  1046. m_bLaunchAfterDisembark = fLaunch;
  1047. BoardShip(NULL);
  1048. }
  1049. void DisembarkAndBoard(IshipIGC* pship)
  1050. {
  1051. m_sidBoardAfterDisembark = pship->GetObjectID();
  1052. BoardShip(NULL);
  1053. }
  1054. void DisembarkAndTeleport(IstationIGC* pstation)
  1055. {
  1056. m_sidTeleportAfterDisembark = pstation->GetObjectID();
  1057. BoardShip(NULL);
  1058. }
  1059. void SaveLoadout(void)
  1060. {
  1061. SaveLoadout(m_ship);
  1062. }
  1063. CachedLoadoutLink* SaveLoadout(IshipIGC* pship)
  1064. {
  1065. IhullTypeIGC* pht = pship->GetBaseHullType();
  1066. CachedLoadoutLink* pcll = GetLoadoutLink(pht);
  1067. if (pcll)
  1068. {
  1069. pcll->data().cpl.purge();
  1070. pcll->unlink();
  1071. }
  1072. else
  1073. {
  1074. pcll = new CachedLoadoutLink;
  1075. pcll->data().pht = pht;
  1076. }
  1077. assert (pcll);
  1078. m_loadouts.first(pcll);
  1079. {
  1080. for (PartLinkIGC* ppl = pship->GetParts()->first(); (ppl != NULL); ppl = ppl->next())
  1081. {
  1082. CachedPartLink* cpl = new CachedPartLink;
  1083. cpl->data().ppt = ppl->data()->GetPartType();
  1084. cpl->data().mount = ppl->data()->GetMountID();
  1085. //Keep the parts sorted by mount
  1086. CachedPartLink* cplAfter;
  1087. for (cplAfter = pcll->data().cpl.first(); ((cplAfter != NULL) &&
  1088. (cplAfter->data().mount < cpl->data().mount)); cplAfter = cplAfter->next())
  1089. {
  1090. }
  1091. if (cplAfter != NULL)
  1092. cplAfter->txen(cpl);
  1093. else
  1094. pcll->data().cpl.last(cpl);
  1095. }
  1096. }
  1097. return pcll;
  1098. }
  1099. Money RestoreLoadout(IshipIGC* pshipSource,
  1100. IshipIGC* pshipSink,
  1101. IstationIGC* pstation,
  1102. Money budget)
  1103. {
  1104. assert (pshipSink->GetBaseHullType() == NULL);
  1105. assert (pshipSink->GetParts()->n() == 0);
  1106. assert (pshipSink->GetChildShips()->n() == 0);
  1107. CachedLoadoutLink* pcll = m_loadouts.first();
  1108. IhullTypeIGC* phtBase = pshipSource->GetBaseHullType();
  1109. if (pcll && (pcll->data().pht == phtBase))
  1110. {
  1111. IhullTypeIGC* pht = pcll->data().pht;
  1112. //We have the same hull as the saved loaded ... try to preserve as much
  1113. //of the old loadout as possible
  1114. const PartListIGC* pparts = pshipSource->GetParts();
  1115. //Upgrade the hull if possible
  1116. IhullTypeIGC* phtSuccessor = (pstation->CanBuy(pht))
  1117. ? (IhullTypeIGC*)(pstation->GetSuccessor(pht))
  1118. : pht;
  1119. assert (pht->GetPrice() == phtSuccessor->GetPrice());
  1120. budget -= phtSuccessor->GetPrice();
  1121. pshipSink->SetBaseHullType(phtSuccessor);
  1122. {
  1123. //Mark all the parts in the cached loadout as not duplicated
  1124. for (CachedPartLink* l = pcll->data().cpl.first(); (l != NULL); l = l->next())
  1125. l->data().bDuplicated = false;
  1126. }
  1127. //Copy over the parts that were mounted on the old hull
  1128. {
  1129. for (PartLinkIGC* l = pparts->first(); (l != NULL); l = l->next())
  1130. {
  1131. IpartIGC* ppart = l->data();
  1132. Mount mount = ppart->GetMountID();
  1133. if (mount >= 0)
  1134. {
  1135. IpartTypeIGC* ppt = ppart->GetPartType();
  1136. if (phtSuccessor->CanMount(ppt, mount))
  1137. {
  1138. if (pstation->CanBuy(ppt))
  1139. BuyPartOnBudget(pshipSink, (IpartTypeIGC*)(pstation->GetSuccessor(ppt)), mount, &budget);
  1140. else
  1141. {
  1142. //Re-use the old part
  1143. Money price = ppt->GetPrice();
  1144. short amount = ppart->GetAmount();
  1145. if (price != 0)
  1146. {
  1147. if (IlauncherTypeIGC::IsLauncherType(ppt->GetEquipmentType()))
  1148. {
  1149. if (price * amount > budget)
  1150. {
  1151. assert (price > 0);
  1152. amount = budget / price;
  1153. }
  1154. price *= amount;
  1155. }
  1156. else if (budget >= price)
  1157. amount = 0;
  1158. }
  1159. if (amount != 0)
  1160. {
  1161. budget -= price;
  1162. pshipSink->CreateAndAddPart(ppt, mount, amount);
  1163. }
  1164. }
  1165. //Mark the corresponding part in the cached loadout as having been duplicated
  1166. {
  1167. for (CachedPartLink* l = pcll->data().cpl.last(); (l != NULL); l = l->txen())
  1168. {
  1169. if ((l->data().ppt == ppt) && !l->data().bDuplicated)
  1170. {
  1171. l->data().bDuplicated = true;
  1172. break;
  1173. }
  1174. }
  1175. }
  1176. }
  1177. else
  1178. debugf("**** successor unable to mount %s/%s\n", phtSuccessor->GetName(), ppt->GetName());
  1179. }
  1180. }
  1181. }
  1182. //Fill all of the cargo slots with what was there before.
  1183. Mount cargo = -c_maxCargo;
  1184. for (CachedPartLink* l = pcll->data().cpl.first(); (l != NULL); l = l->next())
  1185. {
  1186. CachedPart& cpl = l->data();
  1187. if (!cpl.bDuplicated)
  1188. {
  1189. IpartTypeIGC* ppt;
  1190. if (pstation->CanBuy(cpl.ppt))
  1191. {
  1192. //We have an empty slot and a part we can buy ... now see if there is an instance
  1193. //of this part in the available instance of this part in the new loadout
  1194. ppt = (IpartTypeIGC*)(pstation->GetSuccessor(cpl.ppt));
  1195. }
  1196. else
  1197. ppt = pstation->GetSimilarPart(cpl.ppt);
  1198. if (ppt)
  1199. {
  1200. EquipmentType et = ppt->GetEquipmentType();
  1201. if ((cpl.mount == 0) && //Hack alert: all launchers are mountID 0
  1202. IlauncherTypeIGC::IsLauncherType(et) &&
  1203. (pshipSink->GetMountedPart(et, 0) == NULL)) //Hack alert: see above
  1204. {
  1205. BuyPartOnBudget(pshipSink, ppt, 0, &budget); //Hack alert: see above
  1206. }
  1207. else if (cargo < 0)
  1208. {
  1209. BuyPartOnBudget(pshipSink, ppt, cargo++, &budget);
  1210. }
  1211. }
  1212. }
  1213. }
  1214. if (pht != phtSuccessor)
  1215. {
  1216. //Fill any remaining slots with the default items
  1217. TryToBuyParts(pshipSink, pstation, &budget, phtSuccessor, phtSuccessor->GetPreferredPartTypes());
  1218. }
  1219. }
  1220. else if (phtBase && !phtBase->HasCapability(c_habmLifepod))
  1221. budget = ReplaceLoadout(pshipSink, pstation, phtBase, budget);
  1222. else
  1223. budget = ReplaceLoadout(pshipSink, pstation, (CachedLoadout*)NULL, budget);
  1224. return budget;
  1225. }
  1226. Money ReplaceLoadout(IshipIGC* pship,
  1227. IstationIGC* pstation,
  1228. IhullTypeIGC* phulltype,
  1229. Money budget)
  1230. {
  1231. CachedLoadoutLink* pcll = GetLoadoutLink(phulltype);
  1232. if (pcll)
  1233. budget = ReplaceLoadout(pship, pstation, &(pcll->data()), budget);
  1234. else //No cached loadout ...
  1235. BuyDefaultLoadout(pship, pstation, phulltype, &budget);
  1236. return budget;
  1237. }
  1238. Money ReplaceLoadout(IshipIGC* pship,
  1239. IstationIGC* pstation,
  1240. CachedLoadout* pcl,
  1241. Money budget)
  1242. {
  1243. assert (pship->GetChildShips()->n() == 0);
  1244. assert (pship->GetParts()->n() == 0);
  1245. if (pcl == NULL)
  1246. pcl = m_loadouts.first() ? &(m_loadouts.first()->data()) : NULL;
  1247. if (pcl && pcl->pht && pstation->CanBuy(pcl->pht) && (pcl->pht->GetPrice() <= budget))
  1248. {
  1249. IhullTypeIGC* pht = (IhullTypeIGC*)(pstation->GetSuccessor(pcl->pht));
  1250. budget -= pht->GetPrice();
  1251. assert (budget >= 0);
  1252. pship->SetBaseHullType(pht);
  1253. //Clone the previous loadout
  1254. for (CachedPartLink* l = pcl->cpl.first(); (l != NULL); l = l->next())
  1255. {
  1256. CachedPart& cpl = l->data();
  1257. IpartTypeIGC* ppt;
  1258. if (pstation->CanBuy(cpl.ppt))
  1259. {
  1260. ppt = (IpartTypeIGC*)(pstation->GetSuccessor(cpl.ppt));
  1261. }
  1262. else
  1263. ppt = pstation->GetSimilarPart(ppt);
  1264. if (ppt)
  1265. {
  1266. if (pht->CanMount(ppt, cpl.mount))
  1267. BuyPartOnBudget(pship, ppt, cpl.mount, &budget);
  1268. else
  1269. debugf("**** successor unable to mount %s/%s\n", pht->GetName(), ppt->GetName());
  1270. }
  1271. }
  1272. }
  1273. else
  1274. {
  1275. //No saved hull or one we can't buy ... get a reasonable default
  1276. HullTypeLinkIGC* phtl = m_pCoreIGC->GetHullTypes()->first();
  1277. while (true)
  1278. {
  1279. assert (phtl != NULL);
  1280. IhullTypeIGC* pht = phtl->data();
  1281. if ((pht->GetGroupID() >= 0) && pstation->CanBuy(pht) && (pht->GetPrice() <= budget))
  1282. {
  1283. pht = (IhullTypeIGC*)(pstation->GetSuccessor(pht));
  1284. budget -= pht->GetPrice();
  1285. assert (budget >= 0);
  1286. BuyDefaultLoadout(pship, pstation, pht, &budget);
  1287. break;
  1288. }
  1289. phtl = phtl->next();
  1290. }
  1291. }
  1292. return budget;
  1293. }
  1294. void RestoreLoadout(IstationIGC* pstation)
  1295. {
  1296. IshipIGC* pship = CreateEmptyShip(-3);
  1297. assert (pship);
  1298. RestoreLoadout(m_ship, pship, pstation, m_ship->GetValue() + GetMoney());
  1299. //NYI disable loadout till we get an ack
  1300. BuyLoadout(pship, false);
  1301. pship->Terminate();
  1302. pship->Release();
  1303. }
  1304. void ReplaceLoadout(IstationIGC* pstation, bool bLaunch = false)
  1305. {
  1306. IshipIGC* pship = CreateEmptyShip(-3);
  1307. assert (pship);
  1308. ReplaceLoadout(pship, pstation, (CachedLoadout*)NULL, GetMoney());
  1309. BuyLoadout(pship, bLaunch);
  1310. pship->Terminate();
  1311. pship->Release();
  1312. }
  1313. void BuyDefaultLoadout(IshipIGC* pship, IstationIGC* pstation, IhullTypeIGC* pht, Money* pbudget)
  1314. {
  1315. assert (pship);
  1316. assert (pship->GetChildShips()->n() == 0);
  1317. {
  1318. const PartListIGC* pparts = pship->GetParts();
  1319. PartLinkIGC* ppl;
  1320. while (ppl = pparts->first()) //Intentional =
  1321. ppl->data()->Terminate();
  1322. }
  1323. assert (pship->GetParts()->n() == 0);
  1324. assert (pht);
  1325. pship->SetBaseHullType(pht);
  1326. assert (pstation);
  1327. TryToBuyParts(pship, pstation, pbudget, pht, pht->GetPreferredPartTypes());
  1328. //Default loadout for cargo
  1329. // If a magazine ... then a duplicate in cargo
  1330. // If a dispenser ... then a duplicate in cargo
  1331. // Split remaining spaces between fuel and ammo (but no fuel unless an afterburner and no ammo unless
  1332. // a particle weapon)
  1333. Mount cargo = -c_maxCargo;
  1334. {
  1335. IpartIGC* ppart = pship->GetMountedPart(ET_Magazine, 0);
  1336. if (ppart)
  1337. BuyPartOnBudget(pship, ppart->GetPartType(), cargo++, pbudget);
  1338. }
  1339. {
  1340. IpartIGC* ppart = pship->GetMountedPart(ET_Dispenser, 0);
  1341. if (ppart)
  1342. BuyPartOnBudget(pship, ppart->GetPartType(), cargo++, pbudget);
  1343. }
  1344. IpartTypeIGC* pptFuel;
  1345. if (pship->GetMountedPart(ET_Afterburner, 0) != NULL)
  1346. {
  1347. pptFuel = m_pCoreIGC->GetFuelPack();
  1348. assert (pptFuel);
  1349. assert (pptFuel->GetGroupID() >= 0);
  1350. if (!pstation->CanBuy(pptFuel))
  1351. pptFuel = NULL;
  1352. }
  1353. else
  1354. pptFuel = NULL;
  1355. IpartTypeIGC* pptAmmo;
  1356. {
  1357. bool bCarryAmmo = false;
  1358. for (Mount i = 0; (i < pht->GetMaxWeapons()); i++)
  1359. {
  1360. IweaponIGC* pweapon = (IweaponIGC*)(pship->GetMountedPart(ET_Weapon, i));
  1361. if (pweapon && (pweapon->GetAmmoPerShot() > 0))
  1362. {
  1363. bCarryAmmo = true;
  1364. break;
  1365. }
  1366. }
  1367. if (bCarryAmmo)
  1368. {
  1369. pptAmmo = m_pCoreIGC->GetAmmoPack();
  1370. assert (pptAmmo);
  1371. assert (pptAmmo->GetGroupID() >= 0);
  1372. if (!pstation->CanBuy(pptAmmo))
  1373. pptAmmo = NULL;
  1374. }
  1375. else
  1376. pptAmmo = NULL;
  1377. }
  1378. bool bBuyFuel = true;
  1379. do
  1380. {
  1381. if (pptFuel && bBuyFuel)
  1382. {
  1383. //Buying fuel packs
  1384. pship->CreateAndAddPart(pptFuel, cargo++, 0x7fff);
  1385. bBuyFuel = (pptAmmo == NULL);
  1386. }
  1387. else if (pptAmmo)
  1388. {
  1389. pship->CreateAndAddPart(pptAmmo, cargo++, 0x7fff);
  1390. bBuyFuel = true;
  1391. }
  1392. else
  1393. break;
  1394. }
  1395. while (cargo < 0);
  1396. }
  1397. CachedLoadoutLink* GetLoadoutLink(IhullTypeIGC* pht)
  1398. {
  1399. for (CachedLoadoutLink* pcll = m_loadouts.first(); (pcll != NULL); pcll = pcll->next())
  1400. {
  1401. if (pcll->data().pht == pht)
  1402. return pcll;
  1403. }
  1404. return NULL;
  1405. }
  1406. virtual void DropPart(IpartIGC* ppart)
  1407. {
  1408. assert (ppart);
  1409. assert (m_ship->GetStation() == NULL);
  1410. assert (m_ship->GetCluster());
  1411. assert (ppart->GetShip() == m_ship);
  1412. if (m_fm.IsConnected())
  1413. {
  1414. SetMessageType(BaseClient::c_mtGuaranteed);
  1415. BEGIN_PFM_CREATE(m_fm, pdata, CS, DROP_PART)
  1416. END_PFM_CREATE
  1417. pdata->et = ppart->GetEquipmentType();
  1418. pdata->mount = ppart->GetMountID();
  1419. }
  1420. ppart->Terminate();
  1421. }
  1422. virtual void SwapPart(IpartIGC* ppart, Mount mountNew)
  1423. {
  1424. assert (ppart);
  1425. assert (mountNew >= -c_maxCargo);
  1426. assert (ppart->GetShip() == m_ship);
  1427. EquipmentType et = ppart->GetEquipmentType();
  1428. Mount mountOld = ppart->GetMountID();
  1429. IpartIGC* ppartNew = m_ship->GetMountedPart(et, mountNew);
  1430. if (ppartNew)
  1431. {
  1432. ppart->SetMountID(c_mountNA);
  1433. ppartNew->SetMountID(mountOld);
  1434. }
  1435. ppart->SetMountID(mountNew);
  1436. if (m_fm.IsConnected())
  1437. {
  1438. SetMessageType(BaseClient::c_mtGuaranteed);
  1439. BEGIN_PFM_CREATE(m_fm, pdata, CS, SWAP_PART)
  1440. END_PFM_CREATE
  1441. pdata->etOld = et;
  1442. pdata->mountOld = mountOld;
  1443. pdata->mountNew = mountNew;
  1444. }
  1445. }
  1446. virtual void ForwardSquadMessage(FEDMESSAGE* pSquadMessage) {} // forward message to squads screen
  1447. virtual void ForwardCharInfoMessage(FEDMESSAGE* pCharInfoMessage) {} // forward message to character info screen
  1448. virtual void ForwardLeaderBoardMessage(FEDMESSAGE* pLeaderBoardMessage) {} // forward message to leader board screen
  1449. virtual void OnReload(IpartIGC* ppart, bool bConsumed) {};
  1450. virtual void OnQuitSide();
  1451. virtual void OnJoinSide();
  1452. virtual void OnEnterGame();
  1453. virtual void OnQuitMission(QuitSideReason reason, const char* szMessageParam = NULL);
  1454. virtual void AddPlayerToMission(PlayerInfo* pPlayer);
  1455. virtual void AddPlayerToSide(PlayerInfo* pPlayerInfo, SideID sideID);
  1456. virtual void RemovePlayerFromMission(PlayerInfo* pPlayerInfo, QuitSideReason reason, const char* szMessageParam = NULL);
  1457. virtual void RemovePlayerFromSide(PlayerInfo* pPlayerInfo, QuitSideReason reason, const char* szMessageParam = NULL);
  1458. void SetZoneClubID(int nMemberID) { m_nMemberID = nMemberID; }
  1459. int GetZoneClubID() { return m_nMemberID; }
  1460. IshipIGC* GetLastSender(void) const
  1461. {
  1462. return m_pshipLastSender;
  1463. }
  1464. void SetLastSender(IshipIGC* pship)
  1465. {
  1466. m_pshipLastSender = pship;
  1467. }
  1468. Money GetLastMoneyRequest(void) const
  1469. {
  1470. return m_moneyLastRequest;
  1471. }
  1472. void SetLastMoneyRequest(Money m)
  1473. {
  1474. m_moneyLastRequest = m;
  1475. }
  1476. //
  1477. // Loadout lock downs
  1478. //
  1479. virtual void StartLockDown(const ZString& strReason, LockdownCriteria criteria);
  1480. virtual void EndLockDown(LockdownCriteria criteria);
  1481. bool IsLockedDown()
  1482. {
  1483. return m_lockdownCriteria != 0;
  1484. };
  1485. const ZString& GetLockDownReason()
  1486. {
  1487. assert(IsLockedDown());
  1488. return m_strLockDownReason;
  1489. };
  1490. void BoardShip(IshipIGC* pshipBoard);
  1491. CfgInfo & GetCfgInfo()
  1492. {
  1493. return m_cfginfo;
  1494. }
  1495. protected:
  1496. TList<SquadMembership> m_squadmemberships;
  1497. virtual void CreateDummyShip();
  1498. virtual void DestroyDummyShip();
  1499. virtual void ModifyShipData(DataShipIGC* pds) {}
  1500. };
  1501. #endif