shipIGC.h 86 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355
  1. /*
  2. ** Copyright (C) 1996, 1997 Microsoft Corporation. All Rights Reserved.
  3. **
  4. ** File: shipIGC.h
  5. **
  6. ** Author:
  7. **
  8. ** Description:
  9. ** Header for the CshipIGC class. This file was initially created by
  10. ** the ATL wizard.
  11. **
  12. ** History:
  13. */
  14. // shipIGC.h : Declaration of the CshipIGC
  15. #ifndef __SHIPIGC_H_
  16. #define __SHIPIGC_H_
  17. #include "modelIGC.h"
  18. const float c_dtCheckRunaway = 31.0f; //Must be slightly longer than ripcord time for drones.
  19. class CshipIGC;
  20. class MyHullType : public IhullTypeIGC
  21. {
  22. public:
  23. MyHullType(CshipIGC* pship)
  24. :
  25. m_pship(pship),
  26. m_pHullType(NULL)
  27. {
  28. }
  29. ~MyHullType(void)
  30. {
  31. if (m_pHullType)
  32. m_pHullType->Release();
  33. }
  34. //IbaseIGC
  35. virtual HRESULT Initialize(ImissionIGC* pMission, Time now, const void* data, int length);
  36. virtual void Terminate(void);
  37. virtual void Update(Time now);
  38. virtual ObjectType GetObjectType(void) const;
  39. virtual ObjectID GetObjectID(void) const;
  40. //ItypeIGC
  41. virtual const void* GetData(void) const;
  42. //IbuyableIGC
  43. virtual const char* GetName(void) const;
  44. virtual const char* GetDescription(void) const;
  45. virtual const char* GetModelName(void) const;
  46. virtual const TechTreeBitMask& GetRequiredTechs(void) const;
  47. virtual const TechTreeBitMask& GetEffectTechs(void) const;
  48. virtual Money GetPrice(void) const;
  49. virtual DWORD GetTimeToBuild(void) const;
  50. virtual BuyableGroupID GetGroupID(void) const;
  51. //IhullTypeIGC
  52. virtual float GetLength(void) const;
  53. virtual float GetMaxSpeed(void) const;
  54. virtual float GetMaxTurnRate(Axis axis) const;
  55. virtual float GetTurnTorque(Axis axis) const;
  56. virtual float GetThrust(void) const;
  57. virtual float GetSideMultiplier(void) const;
  58. virtual float GetBackMultiplier(void) const;
  59. virtual float GetScannerRange(void) const;
  60. virtual float GetMaxEnergy(void) const;
  61. virtual float GetRechargeRate(void) const;
  62. virtual HitPoints GetHitPoints(void) const;
  63. virtual DefenseTypeID GetDefenseType(void) const;
  64. virtual bool CanMount(IpartTypeIGC* ppt, Mount mountID) const;
  65. virtual PartMask GetPartMask(EquipmentType et, Mount mountID) const;
  66. virtual short GetCapacity(EquipmentType et) const;
  67. virtual Mount GetMaxWeapons(void) const;
  68. virtual Mount GetMaxFixedWeapons(void) const;
  69. virtual const HardpointData& GetHardpointData(Mount hardpointID) const;
  70. virtual const char* GetTextureName(void) const;
  71. virtual const char* GetIconName(void) const;
  72. virtual float GetMass(void) const;
  73. virtual float GetSignature(void) const;
  74. virtual HullAbilityBitMask GetCapabilities(void) const;
  75. virtual bool HasCapability(HullAbilityBitMask habm) const;
  76. virtual const Vector& GetCockpit(void) const;
  77. virtual const Vector& GetWeaponPosition(Mount mount) const;
  78. virtual const Orientation& GetWeaponOrientation(Mount mount) const;
  79. virtual float GetScale() const;
  80. virtual short GetMaxAmmo(void) const;
  81. virtual float GetMaxFuel(void) const;
  82. virtual float GetECM(void) const;
  83. virtual float GetRipcordSpeed(void) const;
  84. virtual float GetRipcordCost(void) const;
  85. virtual IhullTypeIGC* GetSuccessorHullType(void) const;
  86. /*
  87. virtual const char* GetPilotHUDName(void) const;
  88. virtual const char* GetObserverHUDName(void) const;
  89. */
  90. virtual SoundID GetInteriorSound(void) const;
  91. virtual SoundID GetExteriorSound(void) const;
  92. virtual SoundID GetMainThrusterInteriorSound(void) const;
  93. virtual SoundID GetMainThrusterExteriorSound(void) const;
  94. virtual SoundID GetManuveringThrusterInteriorSound(void) const;
  95. virtual SoundID GetManuveringThrusterExteriorSound(void) const;
  96. virtual const PartTypeListIGC* GetPreferredPartTypes(void) const;
  97. virtual IObject* GetIcon(void) const;
  98. virtual int GetLaunchSlots(void) const;
  99. virtual const Vector& GetLaunchPosition(int slotID) const;
  100. virtual const Vector& GetLaunchDirection(int slotID) const;
  101. virtual int GetLandSlots(void) const;
  102. virtual int GetLandPlanes(int slotID) const;
  103. virtual const Vector& GetLandPosition(int slotID, int planeID) const;
  104. virtual const Vector& GetLandDirection(int slotID, int planeID) const;
  105. private:
  106. IhullTypeIGC* GetHullType(void) const
  107. {
  108. return m_pHullType;
  109. }
  110. void SetHullType(IhullTypeIGC* pht)
  111. {
  112. if (m_pHullType)
  113. m_pHullType->Release();
  114. m_pHullType = pht;
  115. if (pht)
  116. {
  117. pht->AddRef();
  118. m_pHullData = (DataHullTypeIGC*)(pht->GetData());
  119. }
  120. else
  121. m_pHullData = NULL;
  122. }
  123. const CshipIGC* m_pship;
  124. IhullTypeIGC* m_pHullType;
  125. const DataHullTypeIGC* m_pHullData;
  126. friend class CshipIGC;
  127. };
  128. class CshipIGC : public TmodelIGC<IshipIGC>
  129. {
  130. public:
  131. CshipIGC(void);
  132. /*
  133. DWORD __stdcall AddRef(void)
  134. {
  135. return TmodelIGC<IshipIGC>::AddRef();
  136. }
  137. DWORD __stdcall Release(void)
  138. {
  139. return TmodelIGC<IshipIGC>::Release();
  140. }
  141. */
  142. public:
  143. // IbaseIGC
  144. virtual HRESULT Initialize(ImissionIGC* pMission, Time now, const void* data, int length);
  145. virtual void Terminate(void);
  146. virtual void Update(Time now);
  147. virtual int Export(void* data) const;
  148. virtual ObjectType GetObjectType(void) const
  149. {
  150. return OT_ship;
  151. }
  152. virtual ObjectID GetObjectID(void) const
  153. {
  154. return m_shipID;
  155. }
  156. // ImodelIGC
  157. virtual void SetCluster(IclusterIGC* cluster)
  158. {
  159. IclusterIGC* pclusterOld = GetCluster();
  160. if (cluster || pclusterOld)
  161. {
  162. //Can't move to a cluster or move to a cluster without a hull
  163. assert ((!cluster) || (m_myHullType.GetHullType() != NULL) || (m_pshipParent != NULL));
  164. assert (GetSide() != NULL);
  165. SetRipcordModel(NULL);
  166. if (cluster != pclusterOld)
  167. {
  168. if (pclusterOld)
  169. pclusterOld->DeleteShip(this);
  170. TmodelIGC<IshipIGC>::SetCluster(cluster);
  171. if (cluster)
  172. {
  173. //Can't be in a cluster and in a station simultaneously
  174. assert (m_station == NULL);
  175. cluster->AddShip(this);
  176. m_maxMineAmount = 0.0f;
  177. m_maxMineLauncher = NULL;
  178. }
  179. }
  180. if (cluster)
  181. {
  182. //Do this even if the cluster does not change: the ship
  183. //mostly likely teleported to a new position.
  184. Time lastUpdate = cluster->GetLastUpdate();
  185. SetMyLastUpdate(lastUpdate);
  186. SetBB(lastUpdate, lastUpdate, 0.0f);
  187. }
  188. SetStateBits(oneWeaponIGC | allWeaponsIGC, 0); //Stop shooting any weapons.
  189. {
  190. //Move the children of this ship to the new cluster as well
  191. for (ShipLinkIGC* psl = m_shipsChildren.first();
  192. (psl != NULL);
  193. psl = psl->next())
  194. {
  195. psl->data()->SetCluster(cluster);
  196. }
  197. }
  198. GetMyMission()->GetIgcSite()->ChangeCluster(this, pclusterOld, cluster);
  199. if (pclusterOld == NULL)
  200. ResetWaypoint();
  201. }
  202. }
  203. virtual void HandleCollision(Time timeCollision,
  204. float tCollision,
  205. const CollisionEntry& entry,
  206. ImodelIGC* pModel);
  207. virtual void SetSide(IsideIGC* pside); //override the default SetSide method
  208. virtual float GetSignature(void) const
  209. {
  210. return TmodelIGC<IshipIGC>::GetSignature() * m_cloaking;
  211. }
  212. virtual void Move(float t)
  213. {
  214. if (m_pshipParent == NULL)
  215. TmodelIGC<IshipIGC>::Move(t);
  216. }
  217. virtual void Move(void)
  218. {
  219. if (m_pshipParent == NULL)
  220. TmodelIGC<IshipIGC>::Move();
  221. }
  222. virtual void SetBB(Time tStart, Time tStop, float dt)
  223. {
  224. if (m_pshipParent == NULL)
  225. TmodelIGC<IshipIGC>::SetBB(tStart, tStop, dt);
  226. }
  227. virtual SideID GetFlag(void) const
  228. {
  229. return m_sidFlag;
  230. }
  231. virtual void SetFlag(SideID sid)
  232. {
  233. m_sidFlag = sid;
  234. }
  235. // IdamageIGC
  236. virtual DamageResult ReceiveDamage(DamageTypeID type,
  237. float amount,
  238. Time timeCollision,
  239. const Vector& position1,
  240. const Vector& position2,
  241. ImodelIGC* launcher);
  242. virtual float GetFraction(void) const
  243. {
  244. return m_fraction;
  245. }
  246. virtual void SetFraction(float newVal)
  247. {
  248. assert (newVal >= 0.0f);
  249. assert (newVal <= 1.0f);
  250. m_fraction = newVal;
  251. if (newVal > m_fractionLastOrder)
  252. m_fractionLastOrder = newVal;
  253. GetThingSite ()->RemoveDamage (m_fraction);
  254. }
  255. virtual float GetHitPoints(void) const
  256. {
  257. return m_fraction * m_myHullType.GetHitPoints();
  258. }
  259. // IscannerIGC
  260. bool InScannerRange(ImodelIGC* pModel) const
  261. {
  262. assert (pModel);
  263. bool rc;
  264. if (m_pshipParent == NULL)
  265. {
  266. IclusterIGC* pcluster = GetCluster();
  267. if (pcluster && (pModel->GetCluster() == pcluster))
  268. {
  269. if (pModel->GetFlag() == NA)
  270. {
  271. float m = m_myHullType.GetScannerRange() * pModel->GetSignature();
  272. {
  273. IsideIGC* pside = pModel->GetSide();
  274. if (pside)
  275. m /= pside->GetGlobalAttributeSet().GetAttribute(c_gaSignature);
  276. }
  277. float r = GetRadius() + pModel->GetRadius() + m;
  278. //Get the difference in positions in the local coordinate space.
  279. Vector deltaP = GetOrientation().TimesInverse(GetPosition() - pModel->GetPosition());
  280. if (deltaP.z < 0.0f)
  281. deltaP.z *= 4.0f;
  282. rc = (deltaP.LengthSquared() <= r * r) && LineOfSightExist(pcluster, this, pModel);
  283. }
  284. else
  285. rc = true;
  286. }
  287. else
  288. rc = false;
  289. }
  290. else
  291. rc = false;
  292. return rc;
  293. }
  294. bool CanSee(ImodelIGC* pModel) const
  295. {
  296. assert (pModel);
  297. IsideIGC* side = GetSide();
  298. return (pModel->GetSide() == side) || //Always see things on our side
  299. pModel->SeenBySide(side) ||
  300. InScannerRange(pModel); //or we can see it ourselves
  301. }
  302. // IshipIGC
  303. virtual void SetObjectID(ObjectID id)
  304. {
  305. m_shipID = id;
  306. }
  307. virtual Money GetValue(void) const
  308. {
  309. //Money for the hull
  310. Money money = m_myHullType.GetHullType() ? m_myHullType.GetPrice() : 0;
  311. //Money for the parts
  312. for (PartLinkIGC* ppartlink = m_parts.first(); ppartlink; ppartlink = ppartlink->next())
  313. money += ppartlink->data()->GetPrice();
  314. return money;
  315. }
  316. virtual void SetMission(ImissionIGC* pMission);
  317. virtual void ReInitialize(DataShipIGC * dataShip, Time now);
  318. virtual void SetShipID(ShipID shipID)
  319. {
  320. m_shipID = shipID;
  321. }
  322. virtual IstationIGC* GetStation(void) const
  323. {
  324. return m_station;
  325. }
  326. virtual void SetStation(IstationIGC* s)
  327. {
  328. IstationIGC* pstationOld = m_station;
  329. if (pstationOld != s)
  330. {
  331. if (m_station)
  332. {
  333. m_station->DeleteShip(this);
  334. m_station->Release();
  335. }
  336. m_station = s;
  337. if (s)
  338. {
  339. if (m_pshipParent == NULL)
  340. {
  341. IafterburnerIGC* pafter = (IafterburnerIGC*)(m_mountedOthers[ET_Afterburner]);
  342. if (pafter)
  343. pafter->Deactivate(); //The station is a no smoking area
  344. if ((m_fOre > 0.0f) && (s->GetStationType()->HasCapability(c_sabmUnload)))
  345. {
  346. IsideIGC* pside = GetSide();
  347. GetMyMission()->GetIgcSite()->PaydayEvent(pside,
  348. m_fOre *
  349. GetMyMission()->GetFloatConstant(c_fcidValueHe3) *
  350. pside->GetGlobalAttributeSet().GetAttribute(c_gaMiningYield));
  351. m_fOre = 0.0f;
  352. }
  353. ResetDamageTrack();
  354. }
  355. s->AddRef();
  356. s->AddShip(this); //This also sets the ship's cluster to NULL
  357. assert (GetCluster() == NULL);
  358. if (m_bAutopilot)
  359. {
  360. if (m_pilotType >= c_ptPlayer)
  361. {
  362. //Players always exit autopilot when docking
  363. m_bAutopilot = false;
  364. }
  365. else
  366. {
  367. if ((m_commandTargets[c_cmdAccepted] == s) && (m_commandIDs[c_cmdAccepted] == c_cidGoto))
  368. {
  369. //We docked with the station under autopilot ... that order is complete
  370. SetCommand(c_cmdAccepted, NULL, c_cidNone);
  371. }
  372. else
  373. {
  374. SetCommand(c_cmdPlan, NULL, c_cidNone);
  375. }
  376. }
  377. }
  378. }
  379. GetMyMission()->GetIgcSite()->ChangeStation(this, pstationOld, s);
  380. }
  381. }
  382. virtual void Reset(bool bFull)
  383. {
  384. m_nKills = 0;
  385. if (bFull)
  386. {
  387. m_nDeaths = 0;
  388. m_nEjections = 0;
  389. }
  390. m_experience = bFull ? 1.0f : 0.0f;
  391. SetFlag(NA);
  392. ResetDamageTrack();
  393. SetAutoDonate(NULL);
  394. SetCommand(c_cmdQueued, NULL, c_cidNone);
  395. SetCommand(c_cmdAccepted, NULL, c_cidNone);
  396. SetCommand(c_cmdCurrent, NULL, c_cidNone);
  397. SetCommand(c_cmdPlan, NULL, c_cidNone);
  398. if (m_station)
  399. {
  400. m_station->DeleteShip(this);
  401. m_station->Release();
  402. m_station = NULL;
  403. }
  404. SetRipcordModel(NULL);
  405. SetCluster(NULL);
  406. //TmodelIGC<IshipIGC>::SetCluster(NULL);
  407. assert (m_station == NULL);
  408. if (m_pshipParent != NULL)
  409. {
  410. SetParentShip(NULL);
  411. assert (m_myHullType.GetHullType() == NULL);
  412. }
  413. else
  414. {
  415. PartLinkIGC* pl;
  416. while (pl = m_parts.first()) //intentional assignment
  417. pl->data()->Terminate();
  418. //Blow away the children
  419. ShipLinkIGC* psl;
  420. while (psl = m_shipsChildren.first()) //intentional assignment
  421. {
  422. psl->data()->SetParentShip(NULL);
  423. }
  424. }
  425. SetBaseHullType(GetSide()->GetCivilization()->GetLifepod());
  426. }
  427. virtual float GetTorqueMultiplier(void) const
  428. {
  429. static const float c_fMultiplierAtZero = 0.50f;
  430. float fraction = GetVelocity().Length() / m_myHullType.GetMaxSpeed();
  431. return c_fMultiplierAtZero + (1.0f - c_fMultiplierAtZero) * 2.0f * fraction / (fraction + 1.0f);
  432. }
  433. virtual float GetCurrentTurnRate(Axis axis) const
  434. {
  435. return m_turnRates[axis];
  436. }
  437. virtual void SetCurrentTurnRate(Axis axis, float newVal)
  438. {
  439. m_turnRates[axis] = newVal;
  440. }
  441. virtual const IhullTypeIGC* GetHullType(void) const
  442. {
  443. return &m_myHullType;
  444. }
  445. virtual IhullTypeIGC* GetBaseHullType(void) const
  446. {
  447. return m_myHullType.GetHullType();
  448. }
  449. virtual void SetBaseHullType(IhullTypeIGC* newVal);
  450. virtual void AddPart(IpartIGC* part);
  451. virtual void DeletePart(IpartIGC* part);
  452. virtual const PartListIGC* GetParts(void) const
  453. {
  454. return &m_parts;
  455. }
  456. virtual IpartIGC* GetMountedPart(EquipmentType type, Mount mount) const;
  457. virtual void MountPart(IpartIGC* p, Mount mountNew, Mount* pmountOld);
  458. virtual const Vector& GetCockpit(void) const
  459. {
  460. return m_cockpit;
  461. }
  462. virtual short GetAmmo(void) const
  463. {
  464. return m_ammo;
  465. }
  466. virtual void SetAmmo(short newVal)
  467. {
  468. short maxAmmo = m_myHullType.GetMaxAmmo();
  469. if (newVal > maxAmmo)
  470. newVal = maxAmmo;
  471. short oldAmmo = m_ammo;
  472. m_ammo = newVal;
  473. if ((newVal == 0) && (oldAmmo > 0) && (GetMyLastUpdate() >= m_timeReloadAmmo))
  474. {
  475. m_timeReloadAmmo = GetMyLastUpdate() + 0.5f / GetMyMission()->GetFloatConstant(c_fcidMountRate);
  476. IIgcSite* pigc = GetMyMission()->GetIgcSite();
  477. if (!pigc->Reload(this, NULL, ET_Weapon))
  478. {
  479. pigc->PostNotificationText(this, false, "Ammo depleted.");
  480. }
  481. else
  482. {
  483. pigc->PlayNotificationSound(salReloadingAmmoSound, this);
  484. pigc->PlayNotificationSound(startReloadSound, this);
  485. pigc->PostNotificationText(this, false, "Reloading ammo...");
  486. }
  487. }
  488. }
  489. virtual float GetFuel(void) const
  490. {
  491. return m_fuel;
  492. }
  493. virtual void SetFuel(float newVal)
  494. {
  495. float maxFuel = m_myHullType.GetMaxFuel();
  496. if (newVal > maxFuel)
  497. newVal = maxFuel;
  498. float oldFuel = m_fuel;
  499. m_fuel = newVal;
  500. if ((newVal == 0.0f) && (oldFuel > 0.0f) && (GetMyLastUpdate() >= m_timeReloadFuel))
  501. {
  502. m_timeReloadFuel = GetMyLastUpdate() + 0.5f / GetMyMission()->GetFloatConstant(c_fcidMountRate);
  503. IIgcSite* pigc = GetMyMission()->GetIgcSite();
  504. if (!pigc->Reload(this, NULL, ET_Afterburner))
  505. {
  506. pigc->PostNotificationText(this, false, "Fuel depleted.");
  507. }
  508. else
  509. {
  510. pigc->PlayNotificationSound(salReloadingFuelSound, this);
  511. pigc->PlayNotificationSound(startReloadSound, this);
  512. pigc->PostNotificationText(this, false, "Reloading fuel...");
  513. }
  514. }
  515. }
  516. virtual float GetEnergy(void) const
  517. {
  518. return m_energy;
  519. }
  520. virtual void SetEnergy(float newVal)
  521. {
  522. m_energy = newVal;
  523. }
  524. virtual float GetCloaking(void) const
  525. {
  526. return m_cloaking;
  527. }
  528. virtual void SetCloaking(float newVal)
  529. {
  530. m_cloaking = newVal;
  531. }
  532. virtual bool GetVectorLock(void) const
  533. {
  534. return (m_stateM & coastButtonIGC) ? true : false;
  535. }
  536. virtual void SetVectorLock(bool bVectorLock)
  537. {
  538. if (bVectorLock)
  539. m_stateM |= coastButtonIGC;
  540. else
  541. m_stateM &= ~coastButtonIGC;
  542. }
  543. virtual const ControlData& GetControls(void) const
  544. {
  545. return m_controls;
  546. }
  547. virtual void SetControls(const ControlData& newVal)
  548. {
  549. m_controls = newVal;
  550. }
  551. virtual const Vector& GetEngineVector(void) const
  552. {
  553. return m_engineVector;
  554. }
  555. virtual int GetStateM(void) const
  556. {
  557. return m_stateM;
  558. }
  559. virtual void SetStateM(int newVal);
  560. virtual void SetStateBits(int mask, int newBits)
  561. {
  562. SetStateM((m_stateM & (~mask)) | (newBits & mask));
  563. }
  564. virtual ImodelIGC* GetCommandTarget(Command i) const
  565. {
  566. assert (i >= 0);
  567. assert (i < c_cmdMax);
  568. return m_commandTargets[i];
  569. }
  570. virtual CommandID GetCommandID(Command i) const
  571. {
  572. assert (i >= 0);
  573. assert (i < c_cmdMax);
  574. return m_commandIDs[i];
  575. }
  576. virtual void SetCommand(Command i, ImodelIGC* target, CommandID cid)
  577. {
  578. assert (i >= 0);
  579. assert (i < c_cmdMax);
  580. CommandID cidOld = m_commandIDs[i];
  581. ImodelIGC* pmodelOld = m_commandTargets[i];
  582. //if ((target != pmodelOld) || (cid != m_commandIDs[i]))
  583. {
  584. m_commandTargets[i] = target;
  585. if (target)
  586. {
  587. target->AddRef();
  588. if (target->GetObjectType() == OT_buoy)
  589. ((IbuoyIGC*)target)->AddConsumer();
  590. }
  591. m_commandIDs[i] = cid;
  592. switch (i)
  593. {
  594. case c_cmdCurrent:
  595. {
  596. if ((pmodelOld != target) && m_mountedOthers[ET_Magazine])
  597. ((ImagazineIGC*)m_mountedOthers[ET_Magazine])->SetLock(0.0f);
  598. }
  599. break;
  600. case c_cmdPlan:
  601. {
  602. //Clear the drilling mask (either it wasn't set or it no longer applies).
  603. m_stateM &= ~drillingMaskIGC;
  604. ResetWaypoint();
  605. m_fractionLastOrder = m_fraction;
  606. m_timeRanAway = GetMyLastUpdate();
  607. m_bRunningAway = false;
  608. }
  609. break;
  610. case c_cmdAccepted:
  611. {
  612. if (m_bAutopilot && (m_pilotType < c_ptPlayer))
  613. {
  614. SetCommand(c_cmdCurrent, target, cid);
  615. SetCommand(c_cmdPlan, target, cid);
  616. }
  617. }
  618. break;
  619. }
  620. if (pmodelOld)
  621. {
  622. if (pmodelOld->GetObjectType() == OT_buoy)
  623. ((IbuoyIGC*)pmodelOld)->ReleaseConsumer();
  624. pmodelOld->Release();
  625. }
  626. if ((i == c_cmdAccepted || i == c_cmdCurrent) &&
  627. (cidOld != cid || pmodelOld != target))
  628. GetMyMission()->GetIgcSite()->CommandChangedEvent(i, this, target, cid);
  629. }
  630. }
  631. virtual void ExecuteTurretMove(Time timeStart,
  632. Time timeStop,
  633. Orientation* pOrientation);
  634. virtual void PreplotShipMove(Time timeStop);
  635. virtual void PlotShipMove(Time timeStop);
  636. virtual void ExecuteShipMove(Time timeStop);
  637. virtual void ExecuteShipMove(Time timeStart,
  638. Time timeStop,
  639. Vector* pVelocity,
  640. Orientation* pOrientation);
  641. virtual short ExportShipLoadout(ShipLoadout* ploadout)
  642. {
  643. if (ploadout)
  644. {
  645. ploadout->hullID = m_myHullType.GetObjectID();
  646. assert (ploadout->hullID != NA);
  647. ExpandedPartData* ppd = ploadout->PartData0();
  648. for (PartLinkIGC* ppl = m_parts.first(); (ppl != NULL); ppl = ppl->next())
  649. {
  650. IpartIGC* ppart = ppl->data();
  651. ppd->partID = ppart->GetPartType()->GetObjectID();
  652. ppd->mountID = ppart->GetMountID();
  653. ppd->amount = ppart->GetAmount();
  654. (ppd++)->fractionMounted = ppart->GetMountedFraction();
  655. }
  656. }
  657. return sizeof(ShipLoadout) + sizeof(ExpandedPartData) * m_parts.n();
  658. }
  659. virtual bool EquivalentShip(IshipIGC* pship) const
  660. {
  661. if (m_myHullType.GetHullType() != pship->GetBaseHullType())
  662. return false;
  663. else
  664. {
  665. Mount maxWeapons = m_myHullType.GetMaxWeapons();
  666. for (Mount i = 0; (i < maxWeapons); i++)
  667. {
  668. IpartIGC* p1 = m_mountedWeapons[i];
  669. IpartIGC* p2 = pship->GetMountedPart(ET_Weapon, i);
  670. if ((p1 != NULL) || (p2 != NULL))
  671. {
  672. if ((p1 == NULL) || (p2 == NULL) ||
  673. (p1->GetPartType() != p2->GetPartType()))
  674. {
  675. return false;
  676. }
  677. }
  678. }
  679. for (Mount j = 0; (j < ET_MAX); j++)
  680. {
  681. IpartIGC* p1 = GetMountedPart(j, 0);
  682. IpartIGC* p2 = pship->GetMountedPart(j, 0);
  683. if ((p1 != NULL) || (p2 != NULL))
  684. {
  685. if ((p1 == NULL) || (p2 == NULL) ||
  686. (p1->GetPartType() != p2->GetPartType()) ||
  687. (p1->GetAmount() != p2->GetAmount()))
  688. {
  689. return false;
  690. }
  691. }
  692. }
  693. for (Mount k = -1; (k >= -c_maxCargo); k--)
  694. {
  695. IpartIGC* p1 = m_mountedCargos[k + c_maxCargo];
  696. IpartIGC* p2 = pship->GetMountedPart(NA, k);
  697. if ((p1 != NULL) || (p2 != NULL))
  698. {
  699. if ((p1 == NULL) || (p2 == NULL) ||
  700. (p1->GetPartType() != p2->GetPartType()) ||
  701. (p1->GetAmount() != p2->GetAmount()))
  702. {
  703. return false;
  704. }
  705. }
  706. }
  707. }
  708. return true;
  709. }
  710. virtual void ProcessShipLoadout(short cbLoadout,
  711. const ShipLoadout* ploadout,
  712. bool bReady)
  713. {
  714. //Did the hull change?
  715. {
  716. IhullTypeIGC* pht = m_myHullType.GetHullType();
  717. if ((pht == NULL) || (ploadout->hullID != pht->GetObjectID()))
  718. {
  719. //Yes ... change it. Trash all the parts first, though
  720. {
  721. PartLinkIGC* ppl;
  722. while (ppl = m_parts.first()) //Intentional
  723. ppl->data()->Terminate();
  724. }
  725. SetBaseHullType(GetMyMission()->GetHullType(ploadout->hullID));
  726. }
  727. }
  728. const ExpandedPartData* ppartLC = ploadout->PartData0();
  729. const ExpandedPartData* ppdLastPart = ploadout->PartDataN(cbLoadout);
  730. PartLinkIGC* pplShip = m_parts.first();
  731. //Walk both lists in parallel, looking for differences
  732. while (true)
  733. {
  734. if (ppartLC != ppdLastPart)
  735. {
  736. //We have a part in the message
  737. if (pplShip)
  738. {
  739. //We have a corresponding part on the ship ... are they the same part?
  740. IpartIGC* ppart = pplShip->data();
  741. if (ppart->GetPartType()->GetObjectID() == ppartLC->partID)
  742. {
  743. //Yes
  744. //has the mount changed?
  745. if (ppart->GetMountID() != ppartLC->mountID)
  746. {
  747. //Is there another part already mounted in the desired slot?
  748. //If so, remove it
  749. IpartIGC* ppartMounted = GetMountedPart(ppart->GetEquipmentType(), ppartLC->mountID);
  750. if (ppartMounted)
  751. ppartMounted->Terminate();
  752. ppart->SetMountID(ppartLC->mountID);
  753. }
  754. //has the quantity changed (for parts where that matters)?
  755. ObjectType type = ppart->GetObjectType();
  756. if (ppartLC->amount != ppart->GetAmount())
  757. {
  758. ppart->SetAmount(ppartLC->amount);
  759. }
  760. //In any case ... set the mounted fraction to agree with the fraction specified in the part definition
  761. if (bReady)
  762. ppart->Arm();
  763. else
  764. ppart->SetMountedFraction(ppartLC->fractionMounted);
  765. //Go to the next part pair.
  766. pplShip = pplShip->next();
  767. ppartLC++;
  768. }
  769. else
  770. {
  771. //No ... delete this part and go to the next part on the ship
  772. //while not advancing the ppartLC pointer
  773. pplShip = pplShip->next();
  774. ppart->Terminate();
  775. }
  776. }
  777. else
  778. {
  779. //No corresponding part on the ship: create one
  780. IpartIGC* ppart = CreateAndAddPart(ppartLC);
  781. if (bReady)
  782. ppart->Arm();
  783. else
  784. ppart->SetMountedFraction(ppartLC->fractionMounted);
  785. ppartLC++;
  786. }
  787. }
  788. else if (pplShip)
  789. {
  790. //No part in the message but one on the ship. Nuke it.
  791. IpartIGC* ppart = pplShip->data();
  792. //Go to the next part before the nuke
  793. pplShip = pplShip->next();
  794. ppart->Terminate();
  795. }
  796. else
  797. {
  798. //No parts in either the message or the ship
  799. //All done.
  800. break;
  801. }
  802. }
  803. }
  804. virtual bool PurchaseShipLoadout(short cbLoadout,
  805. const ShipLoadout* ploadout)
  806. {
  807. assert (m_station);
  808. //Did the hull change?
  809. IhullTypeIGC* pht = m_myHullType.GetHullType();
  810. if ((pht == NULL) || (ploadout->hullID != pht->GetObjectID()))
  811. {
  812. pht = GetMyMission()->GetHullType(ploadout->hullID);
  813. if (!(pht && m_station->CanBuy(pht)))
  814. return false; //Can't buy the hull: abort
  815. //Select the successor of the part.
  816. pht = (IhullTypeIGC*)(m_station->GetSuccessor(pht));
  817. }
  818. //So far so good ... trash the parts
  819. PartListIGC partsOld;
  820. {
  821. PartLinkIGC* ppl;
  822. while (ppl = m_parts.first()) //Intentional
  823. {
  824. IpartIGC* ppart = ppl->data();
  825. ppart->AddRef();
  826. ppart->SetShip(NULL, NA);
  827. partsOld.last(ppart);
  828. }
  829. }
  830. if (pht != m_myHullType.GetHullType())
  831. SetBaseHullType(pht);
  832. const ExpandedPartData* ppdNext = ploadout->PartData0();
  833. const ExpandedPartData* ppdLastPart = ploadout->PartDataN(cbLoadout);
  834. bool bComplete = true;
  835. while (ppdNext < ppdLastPart)
  836. {
  837. IpartTypeIGC* ppt = GetMyMission()->GetPartType(ppdNext->partID);
  838. if (ppt &&
  839. m_myHullType.CanMount(ppt, ppdNext->mountID) &&
  840. (GetMountedPart(ppt->GetEquipmentType(), ppdNext->mountID) == NULL))
  841. {
  842. //Use an upgraded version if available
  843. if (m_station->CanBuy(ppt))
  844. {
  845. ppt = (IpartTypeIGC*)(m_station->GetSuccessor(ppt));
  846. assert (m_myHullType.CanMount(ppt, ppdNext->mountID));
  847. IpartIGC* ppart = CreateAndAddPart(ppt, ppdNext->mountID, ppdNext->amount);
  848. ppart->Arm();
  849. }
  850. else
  851. {
  852. //Can't buy the part: can we re-use an existing part?
  853. for (PartLinkIGC* pplOld = partsOld.first(); (pplOld != NULL); pplOld = pplOld->next())
  854. {
  855. if (ppt == pplOld->data()->GetPartType())
  856. {
  857. IpartIGC* ppart = pplOld->data();
  858. ppart->SetShip(this, ppdNext->mountID);
  859. ppart->Arm();
  860. ppart->Release();
  861. delete pplOld;
  862. //If this is an expendable ... scavenge all the old parts to fill it up
  863. if (IlauncherTypeIGC::IsLauncherType(ppt->GetEquipmentType()))
  864. {
  865. short maxAmmo = ppdNext->amount;
  866. short ammo = ppart->GetAmount();
  867. if (ammo < maxAmmo)
  868. {
  869. PartLinkIGC* pplNext;
  870. for (PartLinkIGC* pplOther = partsOld.first(); (pplOther != NULL); pplOther = pplNext)
  871. {
  872. pplNext = pplOther->next();
  873. IpartIGC* ppartOther = pplOther->data();
  874. if (ppartOther->GetPartType() == ppt)
  875. {
  876. short newAmmo = ammo + ppartOther->GetAmount();
  877. if (newAmmo > maxAmmo)
  878. {
  879. ppartOther->SetAmount(maxAmmo - newAmmo);
  880. newAmmo = maxAmmo;
  881. }
  882. else
  883. {
  884. ppartOther->Terminate();
  885. ppartOther->Release();
  886. delete pplOther;
  887. }
  888. ppart->SetAmount(newAmmo);
  889. }
  890. }
  891. }
  892. }
  893. break;
  894. }
  895. }
  896. }
  897. }
  898. else
  899. bComplete = false;
  900. ppdNext++;
  901. }
  902. {
  903. PartLinkIGC* ppl;
  904. while (ppl = partsOld.first()) //Intentional
  905. {
  906. ppl->data()->Terminate();
  907. ppl->data()->Release();
  908. delete ppl;
  909. }
  910. }
  911. return bComplete;
  912. }
  913. virtual void ExportFractions(CompactShipFractions* pfractions) const
  914. {
  915. pfractions->SetHullFraction(m_fraction);
  916. {
  917. IshieldIGC* s = (IshieldIGC*)(m_mountedOthers[ET_Shield]);
  918. pfractions->SetShieldFraction(s ? s->GetFraction() : 0.0f);
  919. }
  920. pfractions->SetFuel(m_myHullType.GetMaxFuel(), m_fuel);
  921. pfractions->SetAmmo(m_myHullType.GetMaxAmmo(), m_ammo);
  922. pfractions->SetEnergy(m_myHullType.GetMaxEnergy(), m_energy);
  923. }
  924. #define SetSC pshipupdate->stateM.Set(m_stateM); \
  925. pshipupdate->controls.Set(m_controls);
  926. #define SetOVTP pshipupdate->orientation.Set(GetOrientation()); \
  927. pshipupdate->velocity.Set(GetVelocity()); \
  928. pshipupdate->turnRates.Set(m_turnRates); \
  929. { \
  930. IafterburnerIGC* p = (IafterburnerIGC*)(m_mountedOthers[ET_Afterburner]); \
  931. pshipupdate->power = (p ? BytePercentage(p->GetPower()) : BytePercentage(0.0f)); \
  932. }
  933. #define SetF pshipupdate->fractions.SetHullFraction(m_fraction); \
  934. { \
  935. IshieldIGC* s = (IshieldIGC*)(m_mountedOthers[ET_Shield]); \
  936. pshipupdate->fractions.SetShieldFraction(s ? s->GetFraction() : 0.0f); \
  937. } \
  938. pshipupdate->fractions.SetFuel(m_myHullType.GetMaxFuel(), m_fuel); \
  939. pshipupdate->fractions.SetAmmo(m_myHullType.GetMaxAmmo(), m_ammo); \
  940. pshipupdate->fractions.SetEnergy(m_myHullType.GetMaxEnergy(), m_energy);
  941. virtual void ExportShipUpdate(ServerLightShipUpdate* pshipupdate) const
  942. {
  943. pshipupdate->shipID = m_shipID;
  944. SetSC;
  945. }
  946. virtual void ExportShipUpdate(Time timeReference,
  947. const Vector& positionReference,
  948. ServerHeavyShipUpdate* pshipupdate) const
  949. {
  950. assert (GetPosition().LengthSquared() != 0.0f);
  951. pshipupdate->shipID = m_shipID;
  952. pshipupdate->time.Set(timeReference, GetMyLastUpdate());
  953. pshipupdate->position.Set(positionReference, GetPosition());
  954. SetSC;
  955. SetOVTP;
  956. SetF;
  957. }
  958. virtual void ExportShipUpdate(ClientShipUpdate* pshipupdate) const
  959. {
  960. assert (GetPosition().LengthSquared() != 0.0f);
  961. //Message generated on the client so convert to server time
  962. pshipupdate->time = GetMyMission()->GetIgcSite()->ServerTimeFromClientTime(GetMyLastUpdate());
  963. pshipupdate->position = GetPosition();
  964. SetSC;
  965. SetOVTP;
  966. pshipupdate->orientation.Validate();
  967. }
  968. virtual void ExportShipUpdate(ServerSingleShipUpdate* pshipupdate) const
  969. {
  970. pshipupdate->shipID = m_shipID;
  971. pshipupdate->time = GetMyLastUpdate();
  972. pshipupdate->position = GetPosition();
  973. SetSC;
  974. SetOVTP;
  975. SetF;
  976. }
  977. #undef SetSC
  978. #undef SetOVTP
  979. #undef SetF
  980. virtual void ExportShipUpdate(ClientActiveTurretUpdate* pshipupdate) const
  981. {
  982. pshipupdate->time = GetMyMission()->GetIgcSite()->ServerTimeFromClientTime(GetMyLastUpdate());
  983. pshipupdate->controls.Set(m_controls);
  984. pshipupdate->orientation.Set(GetOrientation());
  985. }
  986. virtual void ProcessFractions(const CompactShipFractions& fractions);
  987. virtual ShipUpdateStatus ProcessShipUpdate(const ServerLightShipUpdate& shipupdate);
  988. virtual ShipUpdateStatus ProcessShipUpdate(Time timeReference,
  989. Vector positionReference,
  990. const ServerHeavyShipUpdate& shipupdate);
  991. virtual ShipUpdateStatus ProcessShipUpdate(const ClientShipUpdate& shipupdate);
  992. virtual ShipUpdateStatus ProcessShipUpdate(const ServerSingleShipUpdate& shipupdate, bool bOrient = true);
  993. virtual ShipUpdateStatus ProcessShipUpdate(Time timeReference,
  994. const ServerActiveTurretUpdate& shipupdate);
  995. virtual ShipUpdateStatus ProcessShipUpdate(const ClientActiveTurretUpdate& shipupdate);
  996. virtual void SetPrivateData(DWORD dwPrivate)
  997. {
  998. m_dwPrivate = dwPrivate;
  999. }
  1000. virtual DWORD GetPrivateData(void) const
  1001. {
  1002. return m_dwPrivate;
  1003. }
  1004. Mount HitTreasure(TreasureCode treasureCode, ObjectID objectID, short amount)
  1005. {
  1006. assert (m_myHullType.GetHullType());
  1007. switch (treasureCode)
  1008. {
  1009. case c_tcPart:
  1010. {
  1011. IpartTypeIGC* ppt = GetMyMission()->GetPartType(objectID);
  1012. assert (ppt);
  1013. //Can we carry the thing?
  1014. EquipmentType et = ppt->GetEquipmentType();
  1015. Mount maxMounts = (et == ET_Weapon)
  1016. ? m_myHullType.GetMaxWeapons()
  1017. : 1;
  1018. //Try to mount the part in each possible location
  1019. IpartIGC* ppart;
  1020. Mount mount;
  1021. short a;
  1022. for (mount = 0; (mount < maxMounts); mount++)
  1023. {
  1024. if (m_myHullType.CanMount(ppt, mount))
  1025. {
  1026. ppart = *PartLocation(et, mount);
  1027. if (ppart == NULL)
  1028. break;
  1029. if ((ppart->GetPartType() == ppt) &&
  1030. IlauncherIGC::IsLauncher(ppart->GetObjectType()))
  1031. {
  1032. short maxAmount = ppt->GetAmount(this);
  1033. a = ppart->GetAmount();
  1034. if ((a < maxAmount) && ((a + amount) <= maxAmount))
  1035. break;
  1036. }
  1037. }
  1038. }
  1039. if (mount == maxMounts)
  1040. {
  1041. //No place to mount it ... see if there is room in cargo
  1042. for (mount = -1; (mount >= -c_maxCargo); mount--)
  1043. {
  1044. ppart = *PartLocation(NA, mount);
  1045. if (ppart == NULL)
  1046. break;
  1047. if ((ppart->GetPartType() == ppt) &&
  1048. IlauncherIGC::IsLauncher(ppart->GetObjectType()))
  1049. {
  1050. short maxAmount = ppt->GetAmount(this);
  1051. a = ppart->GetAmount();
  1052. if ((a < maxAmount) && ((a + amount) <= maxAmount))
  1053. break;
  1054. }
  1055. }
  1056. if (mount < -c_maxCargo)
  1057. {
  1058. //No place to put it in cargo
  1059. GetMyMission()->GetIgcSite()->PlayNotificationSound(salCargoFullSound, this);
  1060. return c_mountNA;
  1061. }
  1062. }
  1063. GetMyMission()->GetIgcSite()->PlayNotificationSound(pickUpPartSound, this);
  1064. if (ppart)
  1065. ppart->SetAmount(a + amount);
  1066. else
  1067. CreateAndAddPart(ppt, mount, amount);
  1068. return mount;
  1069. }
  1070. break;
  1071. case c_tcDevelopment:
  1072. {
  1073. IbucketIGC* pb = (IbucketIGC*)GetIbaseIGC((BaseListIGC*)(GetSide()->GetBuckets()), objectID);
  1074. if (pb && !pb->GetCompleteF())
  1075. {
  1076. pb->ForceComplete(GetMyLastUpdate());
  1077. }
  1078. }
  1079. break;
  1080. case c_tcPowerup:
  1081. {
  1082. if (objectID & c_pcHull)
  1083. SetFraction(1.0f);
  1084. if (objectID & c_pcShield)
  1085. {
  1086. IshieldIGC* pshield = (IshieldIGC*)(m_mountedOthers[ET_Shield]);
  1087. if (pshield)
  1088. pshield->SetFraction(1.0f);
  1089. }
  1090. if (objectID & c_pcEnergy)
  1091. m_energy = m_myHullType.GetMaxEnergy();
  1092. if (objectID & c_pcFuel)
  1093. SetFuel(FLT_MAX);
  1094. if (objectID & c_pcAmmo)
  1095. SetAmmo(0x7fff);
  1096. }
  1097. break;
  1098. case c_tcFlag:
  1099. {
  1100. assert (m_sidFlag == NA);
  1101. assert (objectID != NA);
  1102. m_sidFlag = objectID;
  1103. }
  1104. break;
  1105. }
  1106. return c_mountNA;
  1107. }
  1108. virtual ImissileIGC* GetLastMissileFired(void) const
  1109. {
  1110. return m_pmissileLast;
  1111. }
  1112. virtual void SetLastMissileFired(ImissileIGC* pmissile)
  1113. {
  1114. if (m_pmissileLast)
  1115. m_pmissileLast->Release();
  1116. m_pmissileLast = pmissile;
  1117. if (pmissile)
  1118. pmissile->AddRef();
  1119. }
  1120. virtual void Promote(void);
  1121. virtual void SetParentShip(IshipIGC* pship);
  1122. virtual IshipIGC* GetParentShip(void) const
  1123. {
  1124. return m_pshipParent;
  1125. }
  1126. virtual Mount GetTurretID(void) const
  1127. {
  1128. return m_turretID;
  1129. }
  1130. virtual void SetTurretID(Mount turretID)
  1131. {
  1132. if (m_turretID != turretID)
  1133. {
  1134. assert (m_pshipParent);
  1135. if (m_turretID != NA)
  1136. {
  1137. assert (!m_pshipParent->GetHullType()->GetHardpointData(m_turretID).bFixed);
  1138. IweaponIGC* pw = (IweaponIGC*)(m_pshipParent->GetMountedPart(ET_Weapon, m_turretID));
  1139. if (pw)
  1140. {
  1141. assert (pw->GetGunner() == this);
  1142. pw->SetGunner(NULL);
  1143. }
  1144. }
  1145. m_turretID = turretID;
  1146. if (m_turretID != NA)
  1147. {
  1148. IweaponIGC* pw = (IweaponIGC*)(m_pshipParent->GetMountedPart(ET_Weapon, m_turretID));
  1149. if (pw)
  1150. {
  1151. assert (!m_pshipParent->GetHullType()->GetHardpointData(m_turretID).bFixed);
  1152. pw->SetGunner(this);
  1153. }
  1154. }
  1155. GetMyMission()->GetIgcSite()->LoadoutChangeEvent(this, NULL, c_lcTurretChange);
  1156. GetMyMission()->GetIgcSite()->LoadoutChangeEvent(m_pshipParent, NULL, c_lcPassengerMove);
  1157. }
  1158. }
  1159. virtual IshipIGC* GetGunner(Mount turretID) const
  1160. {
  1161. IweaponIGC* pweapon = (IweaponIGC*)*PartLocation(ET_Weapon, turretID);
  1162. if (pweapon)
  1163. {
  1164. return pweapon->GetGunner();
  1165. }
  1166. else
  1167. {
  1168. // we have to manually walk through the child ships
  1169. for (ShipLinkIGC* psl = m_shipsChildren.first();
  1170. (psl != NULL);
  1171. psl = psl->next())
  1172. {
  1173. IshipIGC* pshipChild = psl->data();
  1174. if (pshipChild->GetTurretID() == turretID)
  1175. return pshipChild;
  1176. }
  1177. return NULL;
  1178. }
  1179. }
  1180. virtual const ShipListIGC* GetChildShips(void) const
  1181. {
  1182. return &m_shipsChildren;
  1183. }
  1184. virtual void AddChildShip(IshipIGC* pship)
  1185. {
  1186. assert (pship);
  1187. AddIbaseIGC((BaseListIGC*)&m_shipsChildren, pship);
  1188. }
  1189. virtual void DeleteChildShip(IshipIGC* pship)
  1190. {
  1191. assert (pship);
  1192. DeleteIbaseIGC((BaseListIGC*)&m_shipsChildren, pship);
  1193. }
  1194. virtual IshipIGC* GetSourceShip(void)
  1195. {
  1196. return m_pshipParent ? m_pshipParent : this;
  1197. }
  1198. virtual IpartIGC* CreateAndAddPart(const PartData* ppd)
  1199. {
  1200. return CreateAndAddPart(GetMyMission()->GetPartType(ppd->partID), ppd->mountID, ppd->amount);
  1201. }
  1202. virtual IpartIGC* CreateAndAddPart(IpartTypeIGC* ppt, Mount mount, short amount)
  1203. {
  1204. assert (ppt);
  1205. assert (GetMountedPart(ppt->GetEquipmentType(), mount) == NULL);
  1206. assert (m_myHullType.CanMount(ppt, mount));
  1207. IpartIGC* part = GetMyMission()->CreatePart(GetMyLastUpdate(), ppt);
  1208. assert (part);
  1209. part->SetShip(this, mount);
  1210. assert (part->GetShip() == this);
  1211. assert (part->GetMountID() == mount);
  1212. part->SetAmount(amount);
  1213. part->Release();
  1214. return part; //Bad form to return after a release but it is not dead since the ship holds a pointer
  1215. }
  1216. virtual WingID GetWingID(void) const
  1217. {
  1218. return m_wingID;
  1219. }
  1220. virtual void SetWingID(WingID wid)
  1221. {
  1222. m_wingID = wid;
  1223. }
  1224. virtual bool fRipcordActive(void) const
  1225. {
  1226. return m_pmodelRipcord != NULL;
  1227. }
  1228. virtual float GetRipcordTimeLeft(void) const
  1229. {
  1230. assert(fRipcordActive());
  1231. return m_dtRipcordCountdown;
  1232. }
  1233. virtual void ResetRipcordTimeLeft(void)
  1234. {
  1235. assert (m_myHullType.GetHullType());
  1236. m_dtRipcordCountdown = m_myHullType.GetRipcordSpeed();
  1237. }
  1238. virtual PilotType GetPilotType(void) const
  1239. {
  1240. return m_pilotType;
  1241. }
  1242. virtual AbilityBitMask GetOrdersABM(void) const
  1243. {
  1244. return m_abmOrders;
  1245. }
  1246. virtual bool GetAutopilot(void) const
  1247. {
  1248. return m_bAutopilot;
  1249. }
  1250. virtual void SetAutopilot(bool bAutopilot);
  1251. virtual bool LegalCommand(CommandID cid) const
  1252. {
  1253. bool bLegal = true;
  1254. switch (m_pilotType)
  1255. {
  1256. case c_ptCarrier:
  1257. {
  1258. bLegal = (cid == c_cidDefault) || (cid == c_cidGoto) || (cid == c_cidJoin) || (cid == c_cidDoNothing);
  1259. }
  1260. break;
  1261. case c_ptMiner:
  1262. {
  1263. bLegal = (cid == c_cidDefault) || (cid == c_cidGoto) || (cid == c_cidJoin) || (cid == c_cidDoNothing) || (cid == c_cidMine);
  1264. }
  1265. break;
  1266. case c_ptLayer:
  1267. {
  1268. bLegal = (cid == c_cidDefault) || (cid == c_cidGoto) || (cid == c_cidJoin) || (cid == c_cidDoNothing) || (cid == c_cidBuild);
  1269. }
  1270. break;
  1271. case c_ptBuilder:
  1272. {
  1273. bLegal = ((m_stateM & (drillingMaskIGC | buildingMaskIGC)) == 0) &&
  1274. ((cid == c_cidDefault) || (cid == c_cidGoto) || (cid == c_cidJoin) || (cid == c_cidDoNothing) || (cid == c_cidBuild));
  1275. }
  1276. break;
  1277. case c_ptWingman:
  1278. {
  1279. bLegal = (cid == c_cidDefault) || (cid == c_cidGoto) || (cid == c_cidAttack) || (cid == c_cidPickup) || (cid == c_cidDoNothing);
  1280. }
  1281. break;
  1282. case c_ptPlayer:
  1283. case c_ptCheatPlayer:
  1284. {
  1285. bLegal = (cid >= c_cidDefault) && (cid < c_cidMine);
  1286. }
  1287. }
  1288. return bLegal;
  1289. }
  1290. virtual bool LegalCommand(CommandID cid,
  1291. ImodelIGC* pmodel) const
  1292. {
  1293. bool bLegal = true;
  1294. if ((pmodel == NULL) ||
  1295. ((m_stateM & buildingMaskIGC) != 0) ||
  1296. (pmodel == (ImodelIGC*)this) ||
  1297. (pmodel->GetMission() != GetMyMission()) ||
  1298. (pmodel->GetObjectType() == OT_buoy &&
  1299. ((IbuoyIGC*)pmodel)->GetBuoyType() == c_buoyCluster &&
  1300. ((IbuoyIGC*)pmodel)->GetCluster() == GetCluster()))
  1301. {
  1302. bLegal = (cid == c_cidDoNothing);
  1303. }
  1304. else
  1305. {
  1306. ObjectType type = pmodel->GetObjectType();
  1307. bool bFriendly = pmodel->GetSide() == GetSide();
  1308. switch (cid)
  1309. {
  1310. case c_cidNone:
  1311. {
  1312. bLegal = false;
  1313. }
  1314. break;
  1315. case c_cidDefault:
  1316. case c_cidGoto:
  1317. {
  1318. bLegal = (m_pilotType >= c_ptPlayer) || (type != OT_station) || bFriendly;
  1319. }
  1320. break;
  1321. case c_cidAttack:
  1322. {
  1323. bLegal = ((m_pilotType == c_ptWingman) ||
  1324. (m_pilotType >= c_ptPlayer)) && (type != OT_warp) && (type != OT_treasure) && !bFriendly;
  1325. }
  1326. break;
  1327. case c_cidCapture:
  1328. {
  1329. bLegal = (m_pilotType >= c_ptPlayer) && (type == OT_station) && !bFriendly;
  1330. }
  1331. break;
  1332. case c_cidDefend:
  1333. {
  1334. bLegal = (m_pilotType >= c_ptPlayer);
  1335. }
  1336. break;
  1337. case c_cidPickup:
  1338. {
  1339. if (((m_pilotType == c_ptWingman) || (m_pilotType >= c_ptPlayer)) && (m_pshipParent == NULL))
  1340. {
  1341. if (type == OT_ship)
  1342. {
  1343. IhullTypeIGC* pht = ((IshipIGC*)pmodel)->GetBaseHullType();
  1344. bLegal = (pht && m_myHullType.GetHullType() &&
  1345. ((pht->HasCapability(c_habmLifepod) && m_myHullType.GetHullType()->HasCapability(c_habmRescue)) ||
  1346. (pht->HasCapability(c_habmRescue) && m_myHullType.GetHullType()->HasCapability(c_habmLifepod))));
  1347. }
  1348. else if (type != OT_treasure)
  1349. bLegal = false;
  1350. }
  1351. else
  1352. bLegal = false;
  1353. }
  1354. break;
  1355. case c_cidRepair:
  1356. {
  1357. //Can only repair friendly ships or stations
  1358. bLegal = (m_pilotType >= c_ptPlayer) && ((type == OT_ship) || (type == OT_station)) && bFriendly;
  1359. }
  1360. break;
  1361. case c_cidJoin:
  1362. {
  1363. //Can only join other ships
  1364. bLegal = type == OT_ship;
  1365. }
  1366. break;
  1367. case c_cidBuild:
  1368. {
  1369. if (m_pilotType == c_ptLayer)
  1370. bLegal = (type == OT_buoy) || (type == OT_warp);
  1371. else if (m_pilotType == c_ptBuilder)
  1372. {
  1373. bLegal = (type == OT_asteroid) &&
  1374. ((IasteroidIGC*)pmodel)->HasCapability(m_abmOrders);
  1375. }
  1376. else
  1377. bLegal = false;
  1378. }
  1379. break;
  1380. case c_cidMine:
  1381. {
  1382. if (m_pilotType == c_ptMiner)
  1383. bLegal = (type == OT_asteroid) &&
  1384. ((IasteroidIGC*)pmodel)->HasCapability(m_abmOrders);
  1385. else
  1386. bLegal = false;
  1387. }
  1388. }
  1389. }
  1390. return bLegal;
  1391. }
  1392. virtual void Complain(SoundID sid, const char* pszMsg)
  1393. {
  1394. if (GetMyLastUpdate() >= m_timeLastComplaint + m_dtTimeBetweenComplaints)
  1395. {
  1396. //There is another side here at the asteroid ... complain
  1397. m_timeLastComplaint = GetMyLastUpdate();
  1398. if (m_dtTimeBetweenComplaints < 600.0f)
  1399. m_dtTimeBetweenComplaints *= random(1.5f, 2.5f);
  1400. GetMyMission()->GetIgcSite()->SendChat(this, CHAT_TEAM, GetSide()->GetObjectID(),
  1401. sid, pszMsg);
  1402. }
  1403. }
  1404. virtual IshipIGC* GetAutoDonate(void) const
  1405. {
  1406. return m_pshipAutoDonate;
  1407. }
  1408. virtual void SetAutoDonate(IshipIGC* pship)
  1409. {
  1410. assert (pship != this);
  1411. //Anyone donating to me now donates to my new target
  1412. if (pship)
  1413. {
  1414. IsideIGC* pside = GetSide();
  1415. assert (pside);
  1416. assert (pship->GetSide() == pside);
  1417. assert (pship->GetAutoDonate() == NULL);
  1418. //Was anyone on my ide donating to me ... if so, they start donating to the new person
  1419. for (ShipLinkIGC* psl = pside->GetShips()->first();
  1420. (psl != NULL);
  1421. psl = psl->next())
  1422. {
  1423. if (psl->data()->GetAutoDonate() == this)
  1424. psl->data()->SetAutoDonate(pship == psl->data() ? NULL : pship);
  1425. }
  1426. }
  1427. m_pshipAutoDonate = pship;
  1428. }
  1429. virtual short GetKills(void) const
  1430. {
  1431. return m_nKills;
  1432. }
  1433. virtual void SetKills(short n)
  1434. {
  1435. m_nKills = n;
  1436. }
  1437. virtual void AddKill(void)
  1438. {
  1439. m_nKills++;
  1440. GetSide()->AddKill();
  1441. }
  1442. virtual short GetDeaths(void) const
  1443. {
  1444. return m_nDeaths;
  1445. }
  1446. virtual void SetDeaths(short n)
  1447. {
  1448. m_nDeaths = n;
  1449. }
  1450. virtual void AddDeath(void)
  1451. {
  1452. m_nDeaths++;
  1453. GetSide()->AddDeath();
  1454. }
  1455. virtual short GetEjections(void) const
  1456. {
  1457. return m_nEjections;
  1458. }
  1459. virtual void SetEjections(short n)
  1460. {
  1461. m_nEjections = n;
  1462. }
  1463. virtual void AddEjection(void)
  1464. {
  1465. m_nEjections++;
  1466. GetSide()->AddEjection();
  1467. }
  1468. virtual float GetExperienceMultiplier(void) const
  1469. {
  1470. const float c_maxBonus = 0.5f;
  1471. const float c_halfExperience = 4.0f;
  1472. return 1.0f + c_maxBonus * m_experience / (m_experience + c_halfExperience);
  1473. }
  1474. virtual float GetExperience(void) const
  1475. {
  1476. return m_experience;
  1477. }
  1478. virtual void SetExperience(float f)
  1479. {
  1480. m_experience = f;
  1481. }
  1482. virtual void AddExperience(void)
  1483. {
  1484. m_experience += 1.0f;
  1485. }
  1486. virtual ImodelIGC* GetRipcordModel(void) const
  1487. {
  1488. return m_pmodelRipcord;
  1489. }
  1490. virtual void SetRipcordModel(ImodelIGC* pmodel)
  1491. {
  1492. //Turn off cloak if ripcording
  1493. if (pmodel && (m_stateM & cloakActiveIGC))
  1494. SetStateM(m_stateM & ~cloakActiveIGC);
  1495. if (m_pmodelRipcord && (m_pmodelRipcord->GetObjectType() == OT_ship))
  1496. ((IshipIGC*)(ImodelIGC*)m_pmodelRipcord)->AdjustRipcordDebt(-m_ripcordCost);
  1497. m_pmodelRipcord = pmodel;
  1498. if (m_pmodelRipcord && (m_pmodelRipcord->GetObjectType() == OT_ship))
  1499. ((IshipIGC*)(ImodelIGC*)m_pmodelRipcord)->AdjustRipcordDebt(m_ripcordCost);
  1500. }
  1501. virtual ImodelIGC* FindRipcordModel(IclusterIGC* pcluster);
  1502. virtual float GetRipcordDebt(void) const
  1503. {
  1504. return m_ripcordDebt;
  1505. }
  1506. virtual void AdjustRipcordDebt(float delta)
  1507. {
  1508. m_ripcordDebt += delta;
  1509. }
  1510. virtual bool OkToLaunch(Time now)
  1511. {
  1512. //Spend 10 seconds docked (MyLastUpdate is not being updated while docked)
  1513. if (now > GetMyLastUpdate() + 10.0f)
  1514. {
  1515. IclusterIGC* pcluster = m_station->GetCluster();
  1516. const Vector& positionMe = m_station->GetPosition();
  1517. if (LegalCommand(m_commandIDs[c_cmdAccepted], m_commandTargets[c_cmdAccepted]) ||
  1518. PickDefaultOrder(pcluster, positionMe, true))
  1519. {
  1520. assert (m_station);
  1521. IsideIGC* psideMe = GetSide();
  1522. int cEnemy = 0;
  1523. int cFriend = 0;
  1524. float d2Enemy = FLT_MAX;
  1525. float d2Friend = FLT_MAX;
  1526. for (ShipLinkIGC* psl = m_station->GetCluster()->GetShips()->first(); (psl != NULL); psl = psl->next())
  1527. {
  1528. IshipIGC* pship = psl->data();
  1529. if ((pship->GetPilotType() >= c_ptPlayer) && (pship->GetParentShip() == NULL) &&
  1530. !pship->GetBaseHullType()->HasCapability(c_habmLifepod))
  1531. {
  1532. IsideIGC* pside = pship->GetSide();
  1533. if (pside == psideMe)
  1534. {
  1535. cFriend++;
  1536. float d2 = (positionMe - pship->GetPosition()).LengthSquared();
  1537. if (d2 < d2Friend)
  1538. d2Friend = d2;
  1539. }
  1540. else if (pship->SeenBySide(psideMe))
  1541. {
  1542. cEnemy++;
  1543. float d2 = (positionMe - pship->GetPosition()).LengthSquared();
  1544. if (d2 < d2Enemy)
  1545. d2Enemy = d2;
  1546. }
  1547. }
  1548. }
  1549. if (cFriend >= cEnemy)
  1550. return true;
  1551. else
  1552. {
  1553. static const float c_d2AlwaysRun = 1000.0f;
  1554. if ((d2Enemy > c_d2AlwaysRun * c_d2AlwaysRun) &&
  1555. (d2Enemy >= d2Friend))
  1556. {
  1557. return true;
  1558. }
  1559. }
  1560. }
  1561. SetMyLastUpdate(now);
  1562. }
  1563. return false;
  1564. }
  1565. virtual DamageTrack* GetDamageTrack(void)
  1566. {
  1567. return m_damageTrack;
  1568. }
  1569. virtual void CreateDamageTrack(void)
  1570. {
  1571. delete m_damageTrack;
  1572. m_damageTrack = GetMyMission()->CreateDamageTrack();
  1573. }
  1574. virtual void DeleteDamageTrack(void)
  1575. {
  1576. delete m_damageTrack;
  1577. m_damageTrack = NULL;
  1578. }
  1579. virtual void ResetDamageTrack(void)
  1580. {
  1581. if (m_damageTrack)
  1582. m_damageTrack->Reset();
  1583. }
  1584. virtual void AddMineDamage(DamageTypeID type,
  1585. float amount,
  1586. Time timeCollision,
  1587. ImodelIGC* pmodelLauncher,
  1588. const Vector& position1,
  1589. const Vector& position2)
  1590. {
  1591. if (amount > m_maxMineAmount)
  1592. {
  1593. m_maxMineType = type;
  1594. m_maxMineAmount = amount;
  1595. m_maxMineTime = timeCollision;
  1596. m_maxMineP1 = position1;
  1597. m_maxMineP2 = position2;
  1598. m_maxMineLauncher = pmodelLauncher;
  1599. }
  1600. }
  1601. virtual void ApplyMineDamage(void)
  1602. {
  1603. if (m_maxMineAmount > 0.0f)
  1604. {
  1605. if (m_maxMineTime > m_timeLastMineExplosion + 0.5f)
  1606. {
  1607. m_timeLastMineExplosion = m_maxMineTime;
  1608. GetCluster()->GetClusterSite()->AddExplosion(m_maxMineP2, 1.5f, c_etMine);
  1609. }
  1610. TRef<ImodelIGC> pmodelLauncher = m_maxMineLauncher;
  1611. m_maxMineLauncher = NULL;
  1612. float amount = m_maxMineAmount;
  1613. m_maxMineAmount = 0.0f;
  1614. ReceiveDamage(m_maxMineType, amount, m_maxMineTime, m_maxMineP1, m_maxMineP2, pmodelLauncher);
  1615. }
  1616. }
  1617. virtual WarningMask GetWarningMask(void) const
  1618. {
  1619. return m_warningMask;
  1620. }
  1621. virtual void SetWarningMaskBit(WarningMask wm)
  1622. {
  1623. m_warningMask |= wm;
  1624. }
  1625. virtual void ClearWarningMaskBit(WarningMask wm)
  1626. {
  1627. m_warningMask &= ~wm;
  1628. }
  1629. //Builders ...
  1630. virtual void SetBaseData(IbaseIGC* pbase)
  1631. {
  1632. m_pbaseData = pbase;
  1633. if (m_pilotType == c_ptBuilder)
  1634. {
  1635. assert (pbase->GetObjectType() == OT_stationType);
  1636. m_abmOrders = ((IstationTypeIGC*)pbase)->GetBuildAABM();
  1637. }
  1638. else
  1639. {
  1640. assert (m_pilotType == c_ptLayer);
  1641. assert ((pbase->GetObjectType() == OT_mineType) ||
  1642. (pbase->GetObjectType() == OT_probeType));
  1643. }
  1644. }
  1645. virtual IbaseIGC* GetBaseData(void) const
  1646. {
  1647. return m_pbaseData;
  1648. }
  1649. virtual CommandID GetDefaultOrder(ImodelIGC* pmodel)
  1650. {
  1651. IsideIGC* psideHim = pmodel->GetSide();
  1652. ObjectType type = pmodel->GetObjectType();
  1653. CommandID cid = c_cidGoto;
  1654. switch (m_pilotType)
  1655. {
  1656. case c_ptMiner:
  1657. case c_ptBuilder:
  1658. {
  1659. if ((psideHim == NULL) &&
  1660. (type == OT_asteroid) &&
  1661. ((IasteroidIGC*)pmodel)->HasCapability(m_abmOrders))
  1662. {
  1663. cid = (m_pilotType == c_ptMiner) ? c_cidMine : c_cidBuild;
  1664. }
  1665. }
  1666. break;
  1667. case c_ptLayer:
  1668. {
  1669. if ((type == OT_buoy) || (type == OT_warp))
  1670. cid = c_cidBuild;
  1671. }
  1672. break;
  1673. case c_ptWingman:
  1674. case c_ptPlayer:
  1675. case c_ptCheatPlayer:
  1676. {
  1677. if (psideHim == GetSide())
  1678. {
  1679. cid = c_cidDefend;
  1680. if (m_pshipParent == NULL)
  1681. {
  1682. if (type == OT_ship)
  1683. {
  1684. IhullTypeIGC* pht = ((IshipIGC*)pmodel)->GetBaseHullType();
  1685. if (pht && m_myHullType.GetHullType())
  1686. {
  1687. if ( (pht->HasCapability(c_habmLifepod) && m_myHullType.GetHullType()->HasCapability(c_habmRescue)) ||
  1688. (pht->HasCapability(c_habmRescue) && m_myHullType.GetHullType()->HasCapability(c_habmLifepod)) )
  1689. cid = c_cidPickup;
  1690. }
  1691. }
  1692. else if (m_myHullType.GetHullType())
  1693. {
  1694. if (type == OT_station)
  1695. {
  1696. StationAbilityBitMask sabm = ((IstationIGC*)pmodel)->GetStationType()->GetCapabilities();
  1697. HullAbilityBitMask habm = m_myHullType.GetCapabilities();
  1698. if ((habm & c_habmFighter) == 0)
  1699. {
  1700. if (sabm & c_sabmCapLand)
  1701. cid = c_cidGoto;
  1702. }
  1703. else if (habm & c_habmLifepod)
  1704. {
  1705. if (sabm & (c_sabmRescue | c_sabmLand))
  1706. cid = c_cidGoto;
  1707. }
  1708. else if (sabm & c_sabmLand)
  1709. cid = c_cidGoto;
  1710. }
  1711. else if (type == OT_probe)
  1712. {
  1713. if (m_myHullType.HasCapability(c_habmLifepod) &&
  1714. ((IprobeIGC*)pmodel)->GetProbeType()->HasCapability(c_eabmRescue | c_eabmRescueAny))
  1715. {
  1716. cid = c_cidGoto;
  1717. }
  1718. }
  1719. }
  1720. }
  1721. }
  1722. else if (type == OT_treasure)
  1723. cid = c_cidPickup;
  1724. else if (type == OT_probe)
  1725. {
  1726. cid = c_cidAttack;
  1727. if (m_myHullType.GetHullType() && m_myHullType.HasCapability(c_habmLifepod) &&
  1728. ((IprobeIGC*)pmodel)->GetProbeType()->HasCapability(c_eabmRescueAny))
  1729. {
  1730. cid = c_cidGoto;
  1731. }
  1732. }
  1733. else if (psideHim != NULL)
  1734. cid = c_cidAttack;
  1735. }
  1736. }
  1737. return cid;
  1738. }
  1739. virtual short GetLaunchSlot(void)
  1740. {
  1741. m_nextLaunchSlot = (m_nextLaunchSlot + 1) % m_myHullType.GetHullType()->GetLaunchSlots();
  1742. return m_nextLaunchSlot;
  1743. }
  1744. //Miners
  1745. virtual float GetOre(void) const
  1746. {
  1747. return m_fOre;
  1748. }
  1749. bool PickDefaultOrder(IclusterIGC* pcluster,
  1750. const Vector& position,
  1751. bool bDocked)
  1752. {
  1753. bool fGaveOrder = false;
  1754. //No orders ... pick something
  1755. switch (m_pilotType)
  1756. {
  1757. case c_ptMiner:
  1758. {
  1759. float capacity = GetMyMission()->GetFloatConstant(c_fcidCapacityHe3) *
  1760. GetSide()->GetGlobalAttributeSet().GetAttribute(c_gaMiningCapacity);
  1761. if (m_fOre < capacity / 2.0f)
  1762. {
  1763. ImodelIGC* pmodel = FindTarget(this,
  1764. c_ttNeutral | c_ttAsteroid | c_ttNearest |
  1765. c_ttLeastTargeted | c_ttAnyCluster | c_ttCowardly,
  1766. NULL, pcluster, &position, NULL,
  1767. m_abmOrders);
  1768. if (pmodel)
  1769. {
  1770. SetCommand(c_cmdAccepted, pmodel, c_cidMine);
  1771. fGaveOrder = true;
  1772. }
  1773. }
  1774. if ((!m_commandTargets[c_cmdCurrent]) && ((m_fOre > 0.0f) || !bDocked))
  1775. {
  1776. ImodelIGC* pmodel = NULL;
  1777. if (m_fOre > 0.0f)
  1778. pmodel = FindTarget(this, c_ttFriendly | c_ttStation | c_ttNearest | c_ttAnyCluster,
  1779. NULL, pcluster, &position, NULL,
  1780. c_sabmUnload);
  1781. if (pmodel == NULL)
  1782. pmodel = FindTarget(this, c_ttFriendly | c_ttStation | c_ttNearest | c_ttAnyCluster,
  1783. NULL, pcluster, &position, NULL,
  1784. c_sabmLand);
  1785. if (pmodel)
  1786. {
  1787. SetCommand(c_cmdAccepted, pmodel, c_cidGoto);
  1788. fGaveOrder = true;
  1789. }
  1790. }
  1791. }
  1792. break;
  1793. case c_ptBuilder:
  1794. {
  1795. if ((m_abmOrders == c_aabmBuildable) && !bDocked)
  1796. break;
  1797. ImodelIGC* pmodel = FindTarget(this,
  1798. c_ttNeutral | c_ttAsteroid | c_ttNearest |
  1799. c_ttLeastTargeted | c_ttAnyCluster | c_ttCowardly,
  1800. NULL, pcluster, &position, NULL,
  1801. m_abmOrders);
  1802. if (pmodel)
  1803. {
  1804. assert (m_pbaseData);
  1805. CommandID cid = (m_abmOrders != c_aabmBuildable) ? c_cidBuild : c_cidGoto;
  1806. SetCommand(c_cmdAccepted, pmodel, cid);
  1807. fGaveOrder = true;
  1808. if (cid == c_cidBuild)
  1809. GetMyMission()->GetIgcSite()->SendChatf(this, CHAT_TEAM, GetSide()->GetObjectID(),
  1810. droneInTransitSound,
  1811. "Building %s at %s",
  1812. ((IstationTypeIGC*)(IbaseIGC*)m_pbaseData)->GetName(),
  1813. GetModelName(pmodel));
  1814. }
  1815. }
  1816. break;
  1817. case c_ptLayer:
  1818. {
  1819. if (!bDocked)
  1820. break;
  1821. ImodelIGC* pmodel = FindTarget(this,
  1822. c_ttNeutral | c_ttAsteroid | c_ttNearest |
  1823. c_ttLeastTargeted | c_ttAnyCluster | c_ttCowardly,
  1824. NULL, pcluster, &position, NULL,
  1825. 0);
  1826. if (pmodel)
  1827. {
  1828. SetCommand(c_cmdAccepted, pmodel, c_cidGoto);
  1829. fGaveOrder = true;
  1830. }
  1831. }
  1832. break;
  1833. case c_ptWingman:
  1834. {
  1835. ImodelIGC* pmodel = FindTarget(this,
  1836. c_ttEnemy | c_ttShip | c_ttNearest,
  1837. NULL, pcluster, &position, NULL, 0);
  1838. if (pmodel)
  1839. {
  1840. SetCommand(c_cmdAccepted, pmodel, c_cidAttack);
  1841. fGaveOrder = true;
  1842. GetMyMission()->GetIgcSite()->SendChatf(this, CHAT_TEAM, GetSide()->GetObjectID(),
  1843. droneInTransitSound,
  1844. "Attacking %s", GetModelName(pmodel));
  1845. }
  1846. }
  1847. break;
  1848. }
  1849. if (!fGaveOrder)
  1850. SetCommand(c_cmdAccepted, NULL, c_cidNone);
  1851. return (m_commandIDs[c_cmdAccepted] != c_cidNone);
  1852. }
  1853. bool IsGhost(void) const
  1854. {
  1855. assert (GetMyMission());
  1856. return m_nDeaths > GetMyMission()->GetMissionParams()->iLives;
  1857. }
  1858. virtual bool InGarage(IshipIGC* pship, float tCollision) const;
  1859. float GetEndurance(void) const
  1860. {
  1861. float e;
  1862. if (m_myHullType.GetHullType() &&
  1863. m_myHullType.GetHullType()->HasCapability(c_habmLifepod) &&
  1864. GetCluster())
  1865. {
  1866. e = (m_timeToDie - GetLastUpdate()) / GetMyMission()->GetFloatConstant(c_fcidLifepodEndurance);
  1867. if (e < 0.0f)
  1868. e = 0.0f;
  1869. else if (e > 1.0f)
  1870. e = 1.0f;
  1871. }
  1872. else
  1873. e = 1.0f;
  1874. return e;
  1875. }
  1876. bool IsUsingAreaOfEffectWeapon(void) const
  1877. {
  1878. if (m_pshipParent != NULL)
  1879. {
  1880. if (m_turretID != NA)
  1881. {
  1882. IweaponIGC* pweapon = (IweaponIGC*)(m_pshipParent->GetMountedPart(ET_Weapon, m_turretID));
  1883. if (pweapon && pweapon->GetProjectileType()->GetBlastRadius() > 0.0f)
  1884. return true;
  1885. }
  1886. }
  1887. else
  1888. {
  1889. IhullTypeIGC* pht = m_myHullType.GetHullType();
  1890. if (pht)
  1891. {
  1892. for (Mount mount = 0; mount < pht->GetMaxFixedWeapons(); ++mount)
  1893. {
  1894. IweaponIGC* pweapon = m_mountedWeapons[mount];
  1895. if (pweapon && pweapon->GetProjectileType()->GetBlastRadius() > 0.0f)
  1896. return true;
  1897. }
  1898. }
  1899. }
  1900. return false;
  1901. }
  1902. private:
  1903. bool bShouldUseRipcord(IclusterIGC* pcluster);
  1904. void WarpShip(Time timeUpdate,
  1905. float deltaT,
  1906. Vector* position,
  1907. Vector* velocity,
  1908. Orientation* orientation);
  1909. void CalculateShip(Time timeUpdate,
  1910. float deltaT,
  1911. Vector* position,
  1912. Vector* velocity,
  1913. Orientation* orientation);
  1914. bool IsSafeToRipcord(void);
  1915. void ResetWaypoint(void);
  1916. IpartIGC* const* PartLocation(EquipmentType type, Mount mount) const;
  1917. DWORD m_dwPrivate; // private data for consumer
  1918. MyHullType m_myHullType;
  1919. IstationIGC* m_station;
  1920. TRef<ImodelIGC> m_pmodelRipcord;
  1921. IshipIGC* m_pshipParent;
  1922. ShipListIGC m_shipsChildren;
  1923. PartListIGC m_parts;
  1924. IweaponIGC* m_mountedWeapons[c_maxMountedWeapons];
  1925. IpartIGC* m_mountedOthers[ET_MAX];
  1926. IpartIGC* m_mountedCargos[c_maxCargo];
  1927. TRef<IclusterIGC> m_pclusterRequestRipcord;
  1928. DamageTrack* m_damageTrack;
  1929. TRef<IshipIGC> m_pshipAutoDonate;
  1930. TRef<IbaseIGC> m_pbaseData;
  1931. Vector m_cockpit;
  1932. GotoPlan m_gotoplan;
  1933. ControlData m_controls;
  1934. int m_stateM;
  1935. float m_energy;
  1936. float m_cloaking;
  1937. float m_turnRates[3];
  1938. float m_dtRipcordCountdown;
  1939. float m_fraction;
  1940. float m_fractionLastOrder;
  1941. float m_fuel;
  1942. float m_ripcordDebt;
  1943. float m_ripcordCost;
  1944. Vector m_engineVector;
  1945. Time m_timeLastComplaint;
  1946. Time m_timeRanAway;
  1947. Time m_timeLastMineExplosion;
  1948. Time m_timeReloadAmmo;
  1949. Time m_timeReloadFuel;
  1950. Time m_timeToDie;
  1951. Time m_timeRequestRipcord;
  1952. float m_experience;
  1953. float m_maxMineAmount;
  1954. Time m_maxMineTime;
  1955. Vector m_maxMineP1;
  1956. Vector m_maxMineP2;
  1957. TRef<ImodelIGC> m_maxMineLauncher;
  1958. DamageTypeID m_maxMineType;
  1959. short m_nKills;
  1960. short m_nDeaths;
  1961. short m_nEjections;
  1962. short m_ammo;
  1963. ImissileIGC* m_pmissileLast;
  1964. ImodelIGC* m_commandTargets[c_cmdMax];
  1965. float m_dtTimeBetweenComplaints;
  1966. float m_fOre;
  1967. AbilityBitMask m_abmOrders;
  1968. WingID m_wingID;
  1969. CommandID m_commandIDs[c_cmdMax];
  1970. ShipID m_shipID;
  1971. SideID m_sidFlag;
  1972. Mount m_turretID;
  1973. short m_nextLaunchSlot;
  1974. PilotType m_pilotType;
  1975. bool m_bAutopilot;
  1976. bool m_bRunningAway;
  1977. WarningMask m_warningMask;
  1978. };
  1979. #endif //__SHIPIGC_H_