beacongameobj.cpp 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /***********************************************************************************************
  19. *** Confidential - Westwood Studios ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : Commando *
  23. * *
  24. * $Archive:: /Commando/Code/Combat/beacongameobj.cpp $*
  25. * *
  26. * $Author:: Greg_h $*
  27. * *
  28. * $Modtime:: 6/14/02 1:59p $*
  29. * *
  30. * $Revision:: 41 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. #include "beacongameobj.h"
  36. #include "debug.h"
  37. #include "phys.h"
  38. #include "combat.h"
  39. #include "soldier.h"
  40. #include "persistfactory.h"
  41. #include "combatchunkid.h"
  42. #include "weaponmanager.h"
  43. #include "simpledefinitionfactory.h"
  44. #include "wwhack.h"
  45. #include "decophys.h"
  46. #include "assets.h"
  47. #include "gameobjmanager.h"
  48. #include "wwaudio.h"
  49. #include "wwprofile.h"
  50. #include "cinematicgameobj.h"
  51. #include "basecontroller.h"
  52. #include "playertype.h"
  53. #include "colmath.h"
  54. #include "wwaudio.h"
  55. #include "audiblesound.h"
  56. #include "translateobj.h"
  57. #include "translatedb.h"
  58. #include "messagewindow.h"
  59. #include "weaponbag.h"
  60. #include "objlibrary.h"
  61. #include "hudinfo.h"
  62. #include "explosion.h"
  63. #include "backgroundmgr.h"
  64. #include "weathermgr.h"
  65. #include "persistentgameobjobserver.h"
  66. #include "apppackettypes.h"
  67. #include "weapons.h"
  68. ////////////////////////////////////////////////////////////////
  69. // Hacks
  70. ////////////////////////////////////////////////////////////////
  71. DECLARE_FORCE_LINK (Beacon)
  72. ////////////////////////////////////////////////////////////////
  73. // Editable and persist factories
  74. ////////////////////////////////////////////////////////////////
  75. SimplePersistFactoryClass <BeaconGameObjDef, CHUNKID_GAME_OBJECT_DEF_BEACON> _BeaconGameObjDefPersistFactory;
  76. SimplePersistFactoryClass <BeaconGameObj, CHUNKID_GAME_OBJECT_BEACON> _BeaconGameObjPersistFactory;
  77. DECLARE_DEFINITION_FACTORY (BeaconGameObjDef, CLASSID_GAME_OBJECT_DEF_BEACON, "Beacon") _BeaconGameObjDefDefFactory;
  78. ////////////////////////////////////////////////////////////////
  79. // Save/Load constants
  80. ////////////////////////////////////////////////////////////////
  81. enum
  82. {
  83. CHUNKID_MONITOR_PARENT = 0x07250256,
  84. };
  85. enum
  86. {
  87. CHUNKID_DEF_PARENT = 0x02190435,
  88. CHUNKID_DEF_VARIABLES,
  89. MICROCHUNKID_DEF_BROADCAST_TIME = 1,
  90. MICROCHUNKID_DEF_ARM_TIME,
  91. MICROCHUNKID_DEF_DISARM_TIME,
  92. MICROCHUNKID_DEF_DETONATE_TIME,
  93. MICROCHUNKID_DEF_ARMED_SOUNDID,
  94. MICROCHUNKID_DEF_DISARMING_TEXTID,
  95. MICROCHUNKID_DEF_DISARMED_TEXTID,
  96. MICROCHUNKID_DEF_ARMING_TEXTID,
  97. MICROCHUNKID_DEF_POST_CINEMATIC_DEFID,
  98. MICROCHUNKID_DEF_ARM_INTERRUPT_TEXTID,
  99. MICROCHUNKID_DEF_DISARM_INTERRUPT_TEXTID,
  100. MICROCHUNKID_DEF_ARMING_ANIM_NAME,
  101. MICROCHUNKID_DEF_PRE_CINEMATIC_DEFID,
  102. MICROCHUNKID_DEF_EXPLOSION_DEFID,
  103. MICROCHUNKID_DEF_POST_DETONATE_TIME,
  104. MICROCHUNKID_DEF_PRE_DETONATE_CINEMATIC_DELAY,
  105. MICROCHUNKID_DEF_IS_NUKE,
  106. };
  107. enum
  108. {
  109. CHUNKID_PARENT = 0x0219043,
  110. CHUNKID_VARIABLES,
  111. CHUNKID_OWNER,
  112. CHUNKID_CINEMATIC,
  113. MICROCHUNKID_STATE = 1,
  114. MICROCHUNKID_STATE_TIMER,
  115. MICROCHUNKID_DETONATE_TIMER,
  116. MICROCHUNKID_PRE_DETONATE_TIMER,
  117. MICROCHUNKID_IS_ARMED,
  118. };
  119. ////////////////////////////////////////////////////////////////
  120. //
  121. // BeaconGameObjDef
  122. //
  123. ////////////////////////////////////////////////////////////////
  124. BeaconGameObjDef::BeaconGameObjDef (void) :
  125. BroadcastToAllTime (5.0F),
  126. ArmTime (10.0F),
  127. DisarmTime (10.0F),
  128. PreDetonateCinematicDelay(0),
  129. DetonateTime (30.0F),
  130. PostDetonateTime (10.0F),
  131. ArmedSoundDefID (0),
  132. DisarmingTextID (0),
  133. DisarmedTextID (0),
  134. ArmingTextID (0),
  135. ArmingInterruptedTextID (0),
  136. DisarmingInterruptedTextID (0),
  137. PreDetonateCinematicDefID (0),
  138. PostDetonateCinematicDefID (0),
  139. ExplosionDefID (0),
  140. IsNuke( true )
  141. {
  142. //
  143. // Editable support
  144. //
  145. EDITABLE_PARAM (BeaconGameObjDef, ParameterClass::TYPE_STRING, ArmingAnimationName);
  146. EDITABLE_PARAM (BeaconGameObjDef, ParameterClass::TYPE_FLOAT, BroadcastToAllTime);
  147. EDITABLE_PARAM (BeaconGameObjDef, ParameterClass::TYPE_FLOAT, ArmTime);
  148. EDITABLE_PARAM (BeaconGameObjDef, ParameterClass::TYPE_FLOAT, DisarmTime);
  149. EDITABLE_PARAM (BeaconGameObjDef, ParameterClass::TYPE_FLOAT, PreDetonateCinematicDelay);
  150. EDITABLE_PARAM (BeaconGameObjDef, ParameterClass::TYPE_FLOAT, DetonateTime);
  151. EDITABLE_PARAM (BeaconGameObjDef, ParameterClass::TYPE_FLOAT, PostDetonateTime);
  152. EDITABLE_PARAM (BeaconGameObjDef, ParameterClass::TYPE_SOUNDDEFINITIONID, ArmedSoundDefID);
  153. EDITABLE_PARAM (BeaconGameObjDef, ParameterClass::TYPE_STRINGSDB_ID, ArmingTextID);
  154. EDITABLE_PARAM (BeaconGameObjDef, ParameterClass::TYPE_STRINGSDB_ID, ArmingInterruptedTextID);
  155. EDITABLE_PARAM (BeaconGameObjDef, ParameterClass::TYPE_STRINGSDB_ID, DisarmingTextID);
  156. EDITABLE_PARAM (BeaconGameObjDef, ParameterClass::TYPE_STRINGSDB_ID, DisarmingInterruptedTextID);
  157. EDITABLE_PARAM (BeaconGameObjDef, ParameterClass::TYPE_STRINGSDB_ID, DisarmedTextID);
  158. EDITABLE_PARAM (BeaconGameObjDef, ParameterClass::TYPE_BOOL, IsNuke);
  159. #ifdef PARAM_EDITING_ON
  160. GenericDefParameterClass *param = new GenericDefParameterClass (&PreDetonateCinematicDefID);
  161. param->Set_Class_ID (CLASSID_GAME_OBJECT_DEF_CINEMATIC);
  162. param->Set_Name ("Pre-Detonate Cinematic Obj");
  163. GENERIC_EDITABLE_PARAM (BeaconGameObjDef, param)
  164. param = new GenericDefParameterClass (&PostDetonateCinematicDefID);
  165. param->Set_Class_ID (CLASSID_GAME_OBJECT_DEF_CINEMATIC);
  166. param->Set_Name ("Post-Detonate Cinematic Obj");
  167. GENERIC_EDITABLE_PARAM (BeaconGameObjDef, param)
  168. param = new GenericDefParameterClass (&ExplosionDefID);
  169. param->Set_Class_ID (CLASSID_DEF_EXPLOSION);
  170. param->Set_Name ("Explosion Obj");
  171. GENERIC_EDITABLE_PARAM (BeaconGameObjDef, param)
  172. #endif //PARAM_EDITING_ON
  173. return ;
  174. }
  175. ////////////////////////////////////////////////////////////////
  176. //
  177. // ~BeaconGameObjDef
  178. //
  179. ////////////////////////////////////////////////////////////////
  180. BeaconGameObjDef::~BeaconGameObjDef (void)
  181. {
  182. return ;
  183. }
  184. ////////////////////////////////////////////////////////////////
  185. //
  186. // Get_Class_ID
  187. //
  188. ////////////////////////////////////////////////////////////////
  189. uint32
  190. BeaconGameObjDef::Get_Class_ID (void) const
  191. {
  192. return CLASSID_GAME_OBJECT_DEF_BEACON;
  193. }
  194. ////////////////////////////////////////////////////////////////
  195. //
  196. // Create
  197. //
  198. ////////////////////////////////////////////////////////////////
  199. PersistClass *
  200. BeaconGameObjDef::Create (void) const
  201. {
  202. BeaconGameObj *beacon = new BeaconGameObj;
  203. beacon->Init (*this);
  204. return beacon;
  205. }
  206. ////////////////////////////////////////////////////////////////
  207. //
  208. // Create
  209. //
  210. ////////////////////////////////////////////////////////////////
  211. bool
  212. BeaconGameObjDef::Save (ChunkSaveClass &csave)
  213. {
  214. csave.Begin_Chunk (CHUNKID_DEF_PARENT);
  215. SimpleGameObjDef::Save (csave);
  216. csave.End_Chunk ();
  217. csave.Begin_Chunk (CHUNKID_DEF_VARIABLES);
  218. WRITE_MICRO_CHUNK_WWSTRING (csave, MICROCHUNKID_DEF_ARMING_ANIM_NAME, ArmingAnimationName);
  219. WRITE_MICRO_CHUNK (csave, MICROCHUNKID_DEF_BROADCAST_TIME, BroadcastToAllTime);
  220. WRITE_MICRO_CHUNK (csave, MICROCHUNKID_DEF_ARM_TIME, ArmTime);
  221. WRITE_MICRO_CHUNK (csave, MICROCHUNKID_DEF_DISARM_TIME, DisarmTime);
  222. WRITE_MICRO_CHUNK (csave, MICROCHUNKID_DEF_PRE_DETONATE_CINEMATIC_DELAY,PreDetonateCinematicDelay);
  223. WRITE_MICRO_CHUNK (csave, MICROCHUNKID_DEF_DETONATE_TIME, DetonateTime);
  224. WRITE_MICRO_CHUNK (csave, MICROCHUNKID_DEF_POST_DETONATE_TIME, PostDetonateTime);
  225. WRITE_MICRO_CHUNK (csave, MICROCHUNKID_DEF_ARMED_SOUNDID, ArmedSoundDefID);
  226. WRITE_MICRO_CHUNK (csave, MICROCHUNKID_DEF_DISARMING_TEXTID, DisarmingTextID);
  227. WRITE_MICRO_CHUNK (csave, MICROCHUNKID_DEF_DISARMED_TEXTID, DisarmedTextID);
  228. WRITE_MICRO_CHUNK (csave, MICROCHUNKID_DEF_ARMING_TEXTID, ArmingTextID);
  229. WRITE_MICRO_CHUNK (csave, MICROCHUNKID_DEF_ARM_INTERRUPT_TEXTID, ArmingInterruptedTextID);
  230. WRITE_MICRO_CHUNK (csave, MICROCHUNKID_DEF_DISARM_INTERRUPT_TEXTID, DisarmingInterruptedTextID);
  231. WRITE_MICRO_CHUNK (csave, MICROCHUNKID_DEF_PRE_CINEMATIC_DEFID, PreDetonateCinematicDefID);
  232. WRITE_MICRO_CHUNK (csave, MICROCHUNKID_DEF_POST_CINEMATIC_DEFID, PostDetonateCinematicDefID);
  233. WRITE_MICRO_CHUNK (csave, MICROCHUNKID_DEF_EXPLOSION_DEFID, ExplosionDefID);
  234. WRITE_MICRO_CHUNK (csave, MICROCHUNKID_DEF_IS_NUKE, IsNuke);
  235. csave.End_Chunk ();
  236. return true;
  237. }
  238. ////////////////////////////////////////////////////////////////
  239. //
  240. // Load
  241. //
  242. ////////////////////////////////////////////////////////////////
  243. bool
  244. BeaconGameObjDef::Load (ChunkLoadClass &cload)
  245. {
  246. while (cload.Open_Chunk ())
  247. {
  248. switch (cload.Cur_Chunk_ID ())
  249. {
  250. case CHUNKID_DEF_PARENT:
  251. SimpleGameObjDef::Load (cload);
  252. break;
  253. case CHUNKID_DEF_VARIABLES:
  254. Load_Variables (cload);
  255. break;
  256. default:
  257. Debug_Say (("Unrecognized Beacon Def chunkID\n"));
  258. break;
  259. }
  260. cload.Close_Chunk ();
  261. }
  262. return true;
  263. }
  264. ////////////////////////////////////////////////////////////////
  265. //
  266. // Load_Variables
  267. //
  268. ////////////////////////////////////////////////////////////////
  269. void
  270. BeaconGameObjDef::Load_Variables (ChunkLoadClass &cload)
  271. {
  272. while (cload.Open_Micro_Chunk ()) {
  273. switch (cload.Cur_Micro_Chunk_ID ())
  274. {
  275. READ_MICRO_CHUNK_WWSTRING (cload, MICROCHUNKID_DEF_ARMING_ANIM_NAME, ArmingAnimationName);
  276. READ_MICRO_CHUNK (cload, MICROCHUNKID_DEF_BROADCAST_TIME, BroadcastToAllTime);
  277. READ_MICRO_CHUNK (cload, MICROCHUNKID_DEF_ARM_TIME, ArmTime);
  278. READ_MICRO_CHUNK (cload, MICROCHUNKID_DEF_DISARM_TIME, DisarmTime);
  279. READ_MICRO_CHUNK (cload, MICROCHUNKID_DEF_PRE_DETONATE_CINEMATIC_DELAY, PreDetonateCinematicDelay);
  280. READ_MICRO_CHUNK (cload, MICROCHUNKID_DEF_DETONATE_TIME, DetonateTime);
  281. READ_MICRO_CHUNK (cload, MICROCHUNKID_DEF_POST_DETONATE_TIME, PostDetonateTime);
  282. READ_MICRO_CHUNK (cload, MICROCHUNKID_DEF_ARMED_SOUNDID, ArmedSoundDefID);
  283. READ_MICRO_CHUNK (cload, MICROCHUNKID_DEF_DISARMING_TEXTID, DisarmingTextID);
  284. READ_MICRO_CHUNK (cload, MICROCHUNKID_DEF_DISARMED_TEXTID, DisarmedTextID);
  285. READ_MICRO_CHUNK (cload, MICROCHUNKID_DEF_ARMING_TEXTID, ArmingTextID);
  286. READ_MICRO_CHUNK (cload, MICROCHUNKID_DEF_ARM_INTERRUPT_TEXTID, ArmingInterruptedTextID);
  287. READ_MICRO_CHUNK (cload, MICROCHUNKID_DEF_DISARM_INTERRUPT_TEXTID, DisarmingInterruptedTextID);
  288. READ_MICRO_CHUNK (cload, MICROCHUNKID_DEF_PRE_CINEMATIC_DEFID, PreDetonateCinematicDefID);
  289. READ_MICRO_CHUNK (cload, MICROCHUNKID_DEF_POST_CINEMATIC_DEFID, PostDetonateCinematicDefID);
  290. READ_MICRO_CHUNK (cload, MICROCHUNKID_DEF_EXPLOSION_DEFID, ExplosionDefID);
  291. READ_MICRO_CHUNK (cload, MICROCHUNKID_DEF_IS_NUKE, IsNuke);
  292. default:
  293. Debug_Say (("Unrecognized Beacon Def Variable chunkID\n"));
  294. break;
  295. }
  296. cload.Close_Micro_Chunk();
  297. }
  298. return ;
  299. }
  300. ////////////////////////////////////////////////////////////////
  301. //
  302. // Get_Factory
  303. //
  304. ////////////////////////////////////////////////////////////////
  305. const PersistFactoryClass &
  306. BeaconGameObjDef::Get_Factory (void) const
  307. {
  308. return _BeaconGameObjDefPersistFactory;
  309. }
  310. ////////////////////////////////////////////////////////////////
  311. //
  312. // BeaconGameObj
  313. //
  314. ////////////////////////////////////////////////////////////////
  315. BeaconGameObj::BeaconGameObj (void) :
  316. StateTimer (0),
  317. PreDetonateTimer (0),
  318. DetonateTimer (0),
  319. WarningTimer(0.0f),
  320. State (0),
  321. IsArmed (false),
  322. WeaponDefinition (NULL),
  323. MessageSound (NULL),
  324. ArmedSound (NULL),
  325. OwnerBackup( NULL )
  326. {
  327. Set_App_Packet_Type(APPPACKETTYPE_BEACON);
  328. return ;
  329. }
  330. ////////////////////////////////////////////////////////////////
  331. //
  332. // ~BeaconGameObj
  333. //
  334. ////////////////////////////////////////////////////////////////
  335. BeaconGameObj::~BeaconGameObj (void)
  336. {
  337. Stop_Current_Message_Sound ();
  338. Stop_Armed_Sound ();
  339. Stop_Owner_Animation ();
  340. CinematicObject = NULL;
  341. return ;
  342. }
  343. ////////////////////////////////////////////////////////////////
  344. //
  345. // Get_Factory
  346. //
  347. ////////////////////////////////////////////////////////////////
  348. const PersistFactoryClass &
  349. BeaconGameObj::Get_Factory (void) const
  350. {
  351. return _BeaconGameObjPersistFactory;
  352. }
  353. ////////////////////////////////////////////////////////////////
  354. //
  355. // Init
  356. //
  357. ////////////////////////////////////////////////////////////////
  358. void BeaconGameObj::Init( void )
  359. {
  360. Init( Get_Definition() );
  361. }
  362. ////////////////////////////////////////////////////////////////
  363. //
  364. // Init
  365. //
  366. ////////////////////////////////////////////////////////////////
  367. void
  368. BeaconGameObj::Init (const BeaconGameObjDef &definition)
  369. {
  370. SimpleGameObj::Init (definition);
  371. //
  372. // Make the object so its targettable and it collides with the terrain
  373. //
  374. Peek_Physical_Object()->Set_Collision_Group (TERRAIN_AND_BULLET_COLLISION_GROUP);
  375. return ;
  376. }
  377. ////////////////////////////////////////////////////////////////
  378. //
  379. // Get_Definition
  380. //
  381. ////////////////////////////////////////////////////////////////
  382. const BeaconGameObjDef &
  383. BeaconGameObj::Get_Definition (void) const
  384. {
  385. return (const BeaconGameObjDef &)BaseGameObj::Get_Definition ();
  386. }
  387. ////////////////////////////////////////////////////////////////
  388. //
  389. // Init_Beacon
  390. //
  391. ////////////////////////////////////////////////////////////////
  392. void
  393. BeaconGameObj::Init_Beacon
  394. (
  395. const WeaponDefinitionClass * definition,
  396. SoldierGameObj * owner,
  397. const Vector3 & position
  398. )
  399. {
  400. WeaponDefinition = definition;
  401. Owner = owner;
  402. Set_Position (position);
  403. if ( owner ) {
  404. OwnerBackup = owner->Get_Player_Data();
  405. }
  406. //
  407. // Become part of the same team as the player who is
  408. // dropping us
  409. //
  410. if (Owner != NULL) {
  411. Set_Player_Type (Owner.Get_Ptr ()->As_SmartGameObj ()->Get_Player_Type ());
  412. }
  413. return ;
  414. }
  415. ////////////////////////////////////////////////////////////////
  416. //
  417. // Save
  418. //
  419. ////////////////////////////////////////////////////////////////
  420. bool
  421. BeaconGameObj::Save (ChunkSaveClass &csave)
  422. {
  423. csave.Begin_Chunk (CHUNKID_PARENT);
  424. SimpleGameObj::Save (csave);
  425. csave.End_Chunk ();
  426. csave.Begin_Chunk (CHUNKID_VARIABLES);
  427. WRITE_MICRO_CHUNK (csave, MICROCHUNKID_STATE, State);
  428. WRITE_MICRO_CHUNK (csave, MICROCHUNKID_STATE_TIMER, StateTimer);
  429. WRITE_MICRO_CHUNK (csave, MICROCHUNKID_DETONATE_TIMER, DetonateTimer);
  430. WRITE_MICRO_CHUNK (csave, MICROCHUNKID_PRE_DETONATE_TIMER, PreDetonateTimer);
  431. WRITE_MICRO_CHUNK (csave, MICROCHUNKID_IS_ARMED, IsArmed);
  432. csave.End_Chunk ();
  433. //
  434. // Save the owner (if necessary)
  435. //
  436. if (Owner != NULL) {
  437. csave.Begin_Chunk (CHUNKID_OWNER);
  438. Owner.Save (csave);
  439. csave.End_Chunk ();
  440. }
  441. if (CinematicObject != NULL) {
  442. csave.Begin_Chunk (CHUNKID_CINEMATIC);
  443. CinematicObject.Save (csave);
  444. csave.End_Chunk ();
  445. }
  446. return true;
  447. }
  448. ////////////////////////////////////////////////////////////////
  449. //
  450. // Load
  451. //
  452. ////////////////////////////////////////////////////////////////
  453. bool
  454. BeaconGameObj::Load (ChunkLoadClass &cload)
  455. {
  456. while (cload.Open_Chunk ()) {
  457. switch (cload.Cur_Chunk_ID ()) {
  458. case CHUNKID_PARENT:
  459. SimpleGameObj::Load (cload);
  460. break;
  461. case CHUNKID_VARIABLES:
  462. Load_Variables (cload);
  463. break;
  464. case CHUNKID_OWNER:
  465. Owner.Load (cload);
  466. break;
  467. case CHUNKID_CINEMATIC:
  468. CinematicObject.Load (cload);
  469. break;
  470. default:
  471. Debug_Say (("Unrecognized Beacon chunkID\n"));
  472. break;
  473. }
  474. cload.Close_Chunk();
  475. }
  476. return true;
  477. }
  478. ////////////////////////////////////////////////////////////////
  479. //
  480. // Load_Variables
  481. //
  482. ////////////////////////////////////////////////////////////////
  483. void
  484. BeaconGameObj::Load_Variables (ChunkLoadClass &cload)
  485. {
  486. while (cload.Open_Micro_Chunk ()) {
  487. switch (cload.Cur_Micro_Chunk_ID ())
  488. {
  489. READ_MICRO_CHUNK (cload, MICROCHUNKID_STATE, State);
  490. READ_MICRO_CHUNK (cload, MICROCHUNKID_STATE_TIMER, StateTimer);
  491. READ_MICRO_CHUNK (cload, MICROCHUNKID_DETONATE_TIMER, DetonateTimer);
  492. READ_MICRO_CHUNK (cload, MICROCHUNKID_PRE_DETONATE_TIMER, PreDetonateTimer);
  493. READ_MICRO_CHUNK (cload, MICROCHUNKID_IS_ARMED, IsArmed);
  494. default:
  495. Debug_Say (("Unrecognized Beacon Variable chunkID\n"));
  496. break;
  497. }
  498. cload.Close_Micro_Chunk();
  499. }
  500. return ;
  501. }
  502. ////////////////////////////////////////////////////////////////
  503. //
  504. // Think
  505. //
  506. ////////////////////////////////////////////////////////////////
  507. void
  508. BeaconGameObj::Think (void)
  509. {
  510. WWPROFILE ("Beacon Think");
  511. Restore_Owner();
  512. //
  513. // Let the state think a little
  514. //
  515. Update_State ();
  516. //
  517. // Check to see if we need to break out of the
  518. // arming or disarming state
  519. //
  520. if ( CombatManager::I_Am_Server() && State == STATE_ARMING )
  521. {
  522. //
  523. // Was the owner interrupted while performing his action?
  524. //
  525. if (Was_Owner_Interrupted ()) {
  526. Stop_Owner_Animation ();
  527. //
  528. // Let the player know that the arming operation was cancelled
  529. //
  530. Display_Message (Get_Definition ().ArmingInterruptedTextID);
  531. //
  532. // If the arming state was interrupted, then
  533. // return the ammo that created the beacon to its owner.
  534. //
  535. SoldierGameObj *soldier = Get_Owner ();
  536. if (soldier != NULL) {
  537. WeaponBagClass *weapon_bag = soldier->Get_Weapon_Bag ();
  538. weapon_bag->Add_Weapon (WeaponDefinition, 1, false);
  539. //
  540. // If the user is still holding the beacon weapon then stop its firing
  541. // sound.
  542. //
  543. WeaponClass *curr_weapon = weapon_bag->Get_Weapon ();
  544. if (curr_weapon != NULL && curr_weapon->Get_ID () == WeaponDefinition->Get_ID ()) {
  545. curr_weapon->Stop_Firing_Sound ();
  546. }
  547. }
  548. //
  549. // Now destroy ourselves
  550. //
  551. Set_Delete_Pending ();
  552. }
  553. }
  554. return ;
  555. }
  556. ////////////////////////////////////////////////////////////////
  557. //
  558. // Get_Information
  559. //
  560. ////////////////////////////////////////////////////////////////
  561. void
  562. BeaconGameObj::Get_Information (StringClass &string)
  563. {
  564. SimpleGameObj::Get_Information( string );
  565. return ;
  566. }
  567. ////////////////////////////////////////////////////////////////
  568. //
  569. // Start_Cinematic
  570. //
  571. ////////////////////////////////////////////////////////////////
  572. void
  573. BeaconGameObj::Start_Cinematic ( int id )
  574. {
  575. //
  576. // Create the cinematic controller
  577. //
  578. if ( id != 0 ) {
  579. PhysicalGameObj *game_obj = ObjectLibraryManager::Create_Object ( id );
  580. if (game_obj != NULL) {
  581. game_obj->Start_Observers ();
  582. //
  583. // Position the cinematic controller in the world
  584. //
  585. Vector3 position;
  586. Get_Position (&position);
  587. game_obj->Set_Position (position);
  588. CinematicObject = game_obj;
  589. Debug_Say(( "Beacon Cinematic Started\n" ));
  590. }
  591. }
  592. return ;
  593. }
  594. ////////////////////////////////////////////////////////////////
  595. //
  596. // Stop_Armed_Sound
  597. //
  598. ////////////////////////////////////////////////////////////////
  599. void
  600. BeaconGameObj::Stop_Armed_Sound (void)
  601. {
  602. if (ArmedSound != NULL) {
  603. ArmedSound->Remove_From_Scene ();
  604. REF_PTR_RELEASE (ArmedSound);
  605. }
  606. return ;
  607. }
  608. ////////////////////////////////////////////////////////////////
  609. //
  610. // Set_State
  611. //
  612. ////////////////////////////////////////////////////////////////
  613. void
  614. BeaconGameObj::Set_State (int state)
  615. {
  616. if (State == state) {
  617. return ;
  618. }
  619. Restore_Owner();
  620. if ( CombatManager::I_Am_Server() ) {
  621. //
  622. // "Dirty" the object for networking
  623. //
  624. Set_Object_Dirty_Bit( NetworkObjectClass::BIT_RARE, true );
  625. }
  626. bool is_nuke = !!Get_Definition().IsNuke;
  627. switch (state) {
  628. case STATE_NULL:
  629. Stop_Armed_Sound ();
  630. Display_Message (Get_Definition ().ArmingInterruptedTextID);
  631. break;
  632. case STATE_ARMING:
  633. StateTimer = Get_Definition ().ArmTime;
  634. Display_Message (Get_Definition ().ArmingTextID);
  635. Start_Owner_Animation ();
  636. break;
  637. case STATE_ARMED:
  638. if (IsArmed == false) {
  639. Stop_Owner_Animation ();
  640. //
  641. // Set the detonation timer
  642. //
  643. DetonateTimer = Get_Definition ().DetonateTime;
  644. WarningTimer = Get_Definition().BroadcastToAllTime;
  645. //
  646. // Create the "armed" sound
  647. //
  648. ArmedSound = WWAudioClass::Get_Instance ()->Create_Continuous_Sound (Get_Definition ().ArmedSoundDefID);
  649. if (ArmedSound != NULL) {
  650. //
  651. // Insert the sound object into the world
  652. //
  653. ArmedSound->Set_Transform (Get_Transform ());
  654. ArmedSound->Add_To_Scene ();
  655. }
  656. // Only on Server
  657. if ( CombatManager::I_Am_Server() ) {
  658. // switch to pre detonate weather
  659. Debug_Say(( "Pre-Detonate weather override\n" ));
  660. if ( is_nuke ) {
  661. BackgroundMgrClass::Override_Sky_Tint ( 0.8f, DetonateTimer/2 );
  662. WeatherMgrClass::Override_Wind (0, 3, 1, DetonateTimer/2 );
  663. } else {
  664. BackgroundMgrClass::Override_Clouds(1.0f, 1.0f, DetonateTimer/2);
  665. BackgroundMgrClass::Override_Lightning( 0.8f, 0.2f, 0.8f, 0, 1.0f, DetonateTimer/2);
  666. WeatherMgrClass::Override_Precipitation (WeatherMgrClass::PRECIPITATION_RAIN, 2.0f, DetonateTimer/2);
  667. }
  668. }
  669. // Notify base controllers the beacon is armed
  670. BaseControllerClass* base = BaseControllerClass::Find_Base(Get_Player_Type());
  671. if (base) {
  672. base->On_Beacon_Armed(this);
  673. }
  674. PreDetonateTimer = max( Get_Definition ().PreDetonateCinematicDelay, 0.001f );
  675. IsArmed = true;
  676. }
  677. break;
  678. case STATE_DISARMED: {
  679. Display_Message (Get_Definition ().DisarmedTextID);
  680. Stop_Armed_Sound ();
  681. Stop_Owner_Animation ();
  682. // Only on Server
  683. if ( CombatManager::I_Am_Server() ) {
  684. // cancel weather override
  685. Debug_Say(( "Cancelling weather override\n" ));
  686. if ( is_nuke ) {
  687. BackgroundMgrClass::Restore_Sky_Tint ( 5 );
  688. WeatherMgrClass::Restore_Wind( 5 );
  689. } else {
  690. BackgroundMgrClass::Restore_Clouds( 5 );
  691. BackgroundMgrClass::Restore_Lightning( 5 );
  692. WeatherMgrClass::Restore_Precipitation( 5 );
  693. }
  694. }
  695. // Notify base that the beacon is disarmed
  696. BaseControllerClass* base = BaseControllerClass::Find_Base(Get_Player_Type());
  697. if (base) {
  698. base->On_Beacon_Disarmed(this);
  699. }
  700. // Stop cinematic
  701. if ( CinematicObject.Get_Ptr() != NULL ) {
  702. CinematicObject.Get_Ptr()->Set_Delete_Pending();
  703. CinematicObject = NULL;
  704. }
  705. Set_Delete_Pending ();
  706. break;
  707. }
  708. case STATE_DETONATING:
  709. Stop_Armed_Sound ();
  710. Debug_Say(( "Detonate!\n" ));
  711. IsArmed = false;
  712. StateTimer = Get_Definition ().PostDetonateTime;
  713. // Only on Server
  714. if ( CombatManager::I_Am_Server() ) {
  715. // Create the cinematic controller
  716. Start_Cinematic( Get_Definition ().PostDetonateCinematicDefID );
  717. // switch to post detonate weather
  718. Debug_Say(( "Post-Detonate weather override\n" ));
  719. if ( is_nuke ) {
  720. WeatherMgrClass::Override_Precipitation (WeatherMgrClass::PRECIPITATION_ASH, 0.3f);
  721. }
  722. /*
  723. // Create the explosion, if not in the enemy base
  724. if ( !Is_In_Enemy_Base() && Get_Definition ().ExplosionDefID != 0 ) {
  725. Create_Explosion ();
  726. }
  727. */
  728. }
  729. // Create the explosion, if not in the enemy base
  730. // if ( !Is_In_Enemy_Base() && Get_Definition ().ExplosionDefID != 0 ) {
  731. if ( Get_Definition ().ExplosionDefID != 0 ) {
  732. Create_Explosion ();
  733. }
  734. // Hide our model
  735. if ( Peek_Model() ) {
  736. Peek_Model()->Set_Hidden( true );
  737. }
  738. break;
  739. }
  740. State = state;
  741. return ;
  742. }
  743. ////////////////////////////////////////////////////////////////
  744. //
  745. // Update_State
  746. //
  747. ////////////////////////////////////////////////////////////////
  748. void
  749. BeaconGameObj::Update_State (void)
  750. {
  751. StateTimer -= TimeManager::Get_Frame_Seconds ();
  752. if (IsArmed) {
  753. //
  754. // Tweak the pitch of the armed sound
  755. //
  756. if (ArmedSound != NULL) {
  757. float percent = (1.0F - DetonateTimer / Get_Definition ().DetonateTime);
  758. ArmedSound->Set_Pitch_Factor (1.0F + (percent * 5.0F));
  759. }
  760. //
  761. // Check to see if we've exploded
  762. //
  763. DetonateTimer -= TimeManager::Get_Frame_Seconds ();
  764. if (DetonateTimer <= 0) {
  765. Set_State (STATE_DETONATING);
  766. }
  767. if ( PreDetonateTimer != 0 ) {
  768. PreDetonateTimer -= TimeManager::Get_Frame_Seconds ();
  769. if ( PreDetonateTimer <= 0 ) {
  770. PreDetonateTimer = 0;
  771. // Only on Server
  772. if ( CombatManager::I_Am_Server() ) {
  773. Start_Cinematic( Get_Definition ().PreDetonateCinematicDefID );
  774. }
  775. }
  776. }
  777. }
  778. //
  779. // Handle each state independently
  780. //
  781. switch (State) {
  782. case STATE_NULL:
  783. break;
  784. case STATE_ARMING: {
  785. //
  786. // Update the action bar in the HUD
  787. //
  788. float percent = (1.0F - StateTimer / Get_Definition ().ArmTime);
  789. HUDInfo::Set_Action_Status_Value (percent);
  790. //
  791. // Did the player successfully arm the beacon?
  792. //
  793. if (StateTimer <= 0) {
  794. Set_State (STATE_ARMED);
  795. }
  796. }
  797. break;
  798. case STATE_ARMED:
  799. if (WarningTimer != 0.0f) {
  800. WarningTimer -= TimeManager::Get_Frame_Seconds();
  801. if (WarningTimer <= 0.0f) {
  802. WarningTimer = 0.0f;
  803. // Notify base controller beacon is disarmed
  804. BaseControllerClass* base = BaseControllerClass::Find_Base(Get_Player_Type());
  805. if (base) {
  806. base->On_Beacon_Warning(this);
  807. }
  808. }
  809. }
  810. break;
  811. case STATE_DISARMED:
  812. break;
  813. case STATE_DETONATING:
  814. // Wait for post-detonate timer
  815. if (StateTimer <= 0) {
  816. // Only on Server
  817. if ( CombatManager::I_Am_Server() ) {
  818. if ( CombatManager::Does_Beacon_Placement_Ends_Game() && Is_In_Enemy_Base() ) {
  819. BaseControllerClass *base = Get_Enemy_Base ();
  820. if (base != NULL) {
  821. //
  822. // Destroy the enemy base
  823. //
  824. base->Destroy_Base ();
  825. base->Set_Beacon_Destroyed_Base(true);
  826. }
  827. }
  828. // cancel weather override
  829. Debug_Say(( "restore weather override\n" ));
  830. bool is_nuke = !!Get_Definition().IsNuke;
  831. if ( is_nuke ) {
  832. BackgroundMgrClass::Restore_Sky_Tint ( 5 );
  833. WeatherMgrClass::Restore_Wind( 5 );
  834. WeatherMgrClass::Restore_Precipitation( 5 );
  835. } else {
  836. BackgroundMgrClass::Restore_Clouds( 5 );
  837. BackgroundMgrClass::Restore_Lightning( 5 );
  838. WeatherMgrClass::Restore_Precipitation( 5 );
  839. }
  840. }
  841. Set_Delete_Pending();
  842. }
  843. break;
  844. }
  845. return ;
  846. }
  847. ////////////////////////////////////////////////////////////////
  848. //
  849. // Get_Enemy_Base
  850. //
  851. ////////////////////////////////////////////////////////////////
  852. BaseControllerClass *
  853. BeaconGameObj::Get_Enemy_Base (void)
  854. {
  855. //
  856. // Lookup the team that this object is associated with
  857. //
  858. int player_type = PLAYERTYPE_GDI;
  859. if (Get_Player_Type () == PLAYERTYPE_GDI) {
  860. player_type = PLAYERTYPE_NOD;
  861. }
  862. return BaseControllerClass::Find_Base (player_type);
  863. }
  864. ////////////////////////////////////////////////////////////////
  865. //
  866. // Can_Place_Here
  867. //
  868. ////////////////////////////////////////////////////////////////
  869. bool
  870. BeaconGameObj::Can_Place_Here (const Vector3 &position)
  871. {
  872. // always return true;
  873. return true;
  874. }
  875. ////////////////////////////////////////////////////////////////
  876. //
  877. // Is_In_Enemy_Base (CnC mode only)
  878. //
  879. ////////////////////////////////////////////////////////////////
  880. bool
  881. BeaconGameObj::Is_In_Enemy_Base( void )
  882. {
  883. bool retval = false;
  884. //
  885. // Lookup the enemy's base
  886. //
  887. BaseControllerClass *base = Get_Enemy_Base ();
  888. if (base != NULL) {
  889. //
  890. // Check to see if the point is inside the beacon's zone
  891. //
  892. Vector3 position;
  893. Get_Position (&position);
  894. const OBBoxClass &zone = base->Get_Beacon_Zone ();
  895. if (CollisionMath::Overlap_Test (zone, position) != CollisionMath::OUTSIDE) {
  896. retval = true;
  897. }
  898. }
  899. return retval;
  900. }
  901. ////////////////////////////////////////////////////////////////
  902. //
  903. // Stop_Current_Message_Sound
  904. //
  905. ////////////////////////////////////////////////////////////////
  906. void
  907. BeaconGameObj::Stop_Current_Message_Sound (void)
  908. {
  909. if (MessageSound != NULL) {
  910. MessageSound->Remove_From_Scene ();
  911. REF_PTR_RELEASE (MessageSound);
  912. }
  913. return ;
  914. }
  915. ////////////////////////////////////////////////////////////////
  916. //
  917. // Display_Message
  918. //
  919. ////////////////////////////////////////////////////////////////
  920. void
  921. BeaconGameObj::Display_Message (int text_id)
  922. {
  923. Stop_Current_Message_Sound ();
  924. //
  925. // Lookup the translation object from the strings database
  926. //
  927. TDBObjClass *translate_obj = TranslateDBClass::Find_Object (text_id);
  928. if (translate_obj != NULL) {
  929. const WCHAR *string = translate_obj->Get_String ();
  930. int sound_def_id = (int)translate_obj->Get_Sound_ID ();
  931. float duration = 2.0F;
  932. //
  933. // Play the sound effect
  934. //
  935. bool display_text = true;
  936. if (sound_def_id > 0) {
  937. //
  938. // Create the sound object
  939. //
  940. MessageSound = WWAudioClass::Get_Instance ()->Create_Sound (sound_def_id);
  941. if (MessageSound != NULL) {
  942. duration = (MessageSound->Get_Duration () / 1000.0F);
  943. //
  944. // Play the sound effect at the lcoation of the beacon
  945. //
  946. MessageSound->Set_Transform (Get_Transform ());
  947. MessageSound->Add_To_Scene ();
  948. display_text = (MessageSound->Is_Sound_Culled () == false);
  949. }
  950. }
  951. //
  952. // Display the text on the screen
  953. //
  954. if (display_text && string != NULL) {
  955. float message_duration = max (duration, 5.0F);
  956. CombatManager::Get_Message_Window ()->Add_Message (string, Vector3 (1, 1, 1),
  957. NULL, message_duration);
  958. }
  959. }
  960. return ;
  961. }
  962. ////////////////////////////////////////////////////////////////
  963. //
  964. // Begin_Arming
  965. //
  966. ////////////////////////////////////////////////////////////////
  967. void
  968. BeaconGameObj::Begin_Arming (void)
  969. {
  970. //
  971. // Switch states
  972. //
  973. Set_State (STATE_ARMING);
  974. return ;
  975. }
  976. ////////////////////////////////////////////////////////////////
  977. //
  978. // Start_Owner_Animation
  979. //
  980. ////////////////////////////////////////////////////////////////
  981. void
  982. BeaconGameObj::Start_Owner_Animation (void)
  983. {
  984. Restore_Owner();
  985. //
  986. // Release control of the human's animation (if possible)
  987. //
  988. SoldierGameObj *soldier = Get_Owner ();
  989. if (soldier != NULL) {
  990. //
  991. // Play the animation looped until we detect its time to stop
  992. //
  993. soldier->Set_Animation (Get_Definition ().ArmingAnimationName, true, 0);
  994. }
  995. // Only show the HUD if the owner if the star
  996. if ( soldier == COMBAT_STAR ) {
  997. HUDInfo::Display_Action_Status_Bar (true);
  998. }
  999. return ;
  1000. }
  1001. ////////////////////////////////////////////////////////////////
  1002. //
  1003. // Stop_Owner_Animation
  1004. //
  1005. ////////////////////////////////////////////////////////////////
  1006. void
  1007. BeaconGameObj::Stop_Owner_Animation (void)
  1008. {
  1009. Restore_Owner();
  1010. //
  1011. // Release control of the human's animation (if possible)
  1012. //
  1013. SoldierGameObj *soldier = Get_Owner ();
  1014. if (soldier != NULL) {
  1015. //
  1016. // Stop the animation
  1017. //
  1018. soldier->Set_Animation (NULL);
  1019. }
  1020. // Only show the HUD if the owner if the star
  1021. if ( soldier == COMBAT_STAR ) {
  1022. HUDInfo::Display_Action_Status_Bar (false);
  1023. }
  1024. return ;
  1025. }
  1026. ////////////////////////////////////////////////////////////////
  1027. //
  1028. // Was_Owner_Interrupted
  1029. //
  1030. ////////////////////////////////////////////////////////////////
  1031. bool
  1032. BeaconGameObj::Was_Owner_Interrupted (void)
  1033. {
  1034. Restore_Owner();
  1035. bool retval = false;
  1036. //
  1037. // The owner is interrupted if he's dead
  1038. //
  1039. SoldierGameObj *soldier = Get_Owner ();
  1040. if (soldier == NULL || soldier->Is_Dead ()) {
  1041. retval = true;
  1042. } else {
  1043. //
  1044. // The owner is also interrupted if he moves
  1045. //
  1046. //
  1047. // Check each movement control
  1048. //
  1049. ControlClass &control = soldier->Get_Control ();
  1050. // Ignore up/down and turning
  1051. // for (int index = 0; index < ControlClass::ANALOG_CONTROL_COUNT; index ++) {
  1052. for (int index = 0; index < ControlClass::ANALOG_MOVE_LEFT+1; index ++) {
  1053. //
  1054. // Check this input to see if the soldier is moving
  1055. //
  1056. if (control.Get_Analog ((ControlClass::AnalogControl)index) != 0) {
  1057. retval = true;
  1058. break;
  1059. }
  1060. }
  1061. //
  1062. // Check each "boolean" control (jumping, etc)
  1063. //
  1064. if (retval == false) {
  1065. for ( index = ControlClass::BOOLEAN_ONE_TIME_FIRST;
  1066. index <= ControlClass::BOOLEAN_DROP_FLAG;
  1067. index ++)
  1068. {
  1069. //
  1070. // Check this input to see if the soldier is moving
  1071. //
  1072. if (control.Get_Boolean ((ControlClass::BooleanControl)index)) {
  1073. retval = true;
  1074. break;
  1075. }
  1076. }
  1077. }
  1078. }
  1079. return retval;
  1080. }
  1081. ////////////////////////////////////////////////////////////////
  1082. //
  1083. // Get_Owner
  1084. //
  1085. ////////////////////////////////////////////////////////////////
  1086. SoldierGameObj *
  1087. BeaconGameObj::Get_Owner (void)
  1088. {
  1089. SoldierGameObj *soldier = NULL;
  1090. //
  1091. // Dig the soldier pointer out of the referencer object
  1092. //
  1093. if (Owner != NULL) {
  1094. PhysicalGameObj *physical_obj = Owner.Get_Ptr ()->As_PhysicalGameObj ();
  1095. if (physical_obj != NULL) {
  1096. soldier = physical_obj->As_SoldierGameObj ();
  1097. }
  1098. }
  1099. return soldier;
  1100. }
  1101. ////////////////////////////////////////////////////////////////
  1102. //
  1103. // Completely_Damaged
  1104. //
  1105. ////////////////////////////////////////////////////////////////
  1106. void
  1107. BeaconGameObj::Completely_Damaged (const OffenseObjectClass &damager)
  1108. {
  1109. if (!Is_Delete_Pending()) {
  1110. Set_State (STATE_DISARMED);
  1111. Set_Delete_Pending ();
  1112. }
  1113. }
  1114. ////////////////////////////////////////////////////////////////
  1115. //
  1116. // Create_Explosion
  1117. //
  1118. ////////////////////////////////////////////////////////////////
  1119. void
  1120. BeaconGameObj::Create_Explosion (void)
  1121. {
  1122. if (CombatManager::I_Am_Server())
  1123. {
  1124. Restore_Owner();
  1125. }
  1126. Debug_Say (("Create Explosion\n"));
  1127. //
  1128. // Create the explosion...
  1129. //
  1130. Vector3 position;
  1131. Get_Position (&position);
  1132. //
  1133. // (gth) don't explode if the owner is gone
  1134. //
  1135. if (Get_Owner() != NULL) {
  1136. ExplosionManager::Create_Explosion_At (Get_Definition ().ExplosionDefID, Get_Transform (), Get_Owner ());
  1137. if (CombatManager::I_Am_Server())
  1138. {
  1139. //
  1140. // Look-up the explosion that this beacon will create
  1141. //
  1142. ExplosionDefinitionClass *explosion_def = (ExplosionDefinitionClass *)DefinitionMgrClass::Find_Definition (Get_Definition ().ExplosionDefID);
  1143. if (explosion_def != NULL) {
  1144. float outter_radius = explosion_def->DamageRadius;
  1145. float outter_radius2 = outter_radius * outter_radius;
  1146. //
  1147. // Loop over all the buildings in the level
  1148. //
  1149. SLNode<BuildingGameObj> *obj_node = NULL;
  1150. for ( obj_node = GameObjManager::Get_Building_Game_Obj_List()->Head ();
  1151. obj_node != NULL;
  1152. obj_node = obj_node->Next ())
  1153. {
  1154. WWASSERT (obj_node->Data () != NULL);
  1155. BuildingGameObj *building = obj_node->Data ();
  1156. if (building != NULL) {
  1157. //
  1158. // Check to see if any part of the building is inside our damage sphere
  1159. //
  1160. float dist2 = 0;
  1161. building->Find_Closest_Poly (position, &dist2);
  1162. if (dist2 <= outter_radius2) {
  1163. //
  1164. // Determine the strength of the explosion at this location
  1165. //
  1166. float percent = (WWMath::Sqrt (dist2) / outter_radius);
  1167. percent = 1.0F - WWMath::Clamp (percent, 0.0F, 1.0F);
  1168. float strength = percent * explosion_def->DamageStrength;
  1169. //
  1170. // Apply the damage to this building
  1171. //
  1172. OffenseObjectClass offense (strength, explosion_def->DamageWarhead, Get_Owner ());
  1173. building->Apply_Damage_Building (offense, true);
  1174. }
  1175. }
  1176. }
  1177. }
  1178. }
  1179. }
  1180. return ;
  1181. }
  1182. /*
  1183. **
  1184. */
  1185. void BeaconGameObj::Export_Rare( BitStreamClass &packet )
  1186. {
  1187. Restore_Owner();
  1188. SimpleGameObj::Export_Rare( packet );
  1189. packet.Add( State );
  1190. int owner_id = 0;
  1191. if ( Get_Owner() ) {
  1192. owner_id = Get_Owner()->Get_ID();
  1193. }
  1194. packet.Add( owner_id );
  1195. }
  1196. /*
  1197. **
  1198. */
  1199. void BeaconGameObj::Import_Rare( BitStreamClass &packet )
  1200. {
  1201. SimpleGameObj::Import_Rare( packet );
  1202. int state;
  1203. packet.Get( state );
  1204. int owner_id;
  1205. packet.Get( owner_id );
  1206. if ( owner_id != 0 ) {
  1207. Owner = GameObjManager::Find_SmartGameObj( owner_id );
  1208. }
  1209. Set_State( state );
  1210. return ;
  1211. }
  1212. void BeaconGameObj::Restore_Owner( void )
  1213. {
  1214. if ( Get_Owner() == NULL && OwnerBackup != NULL ) {
  1215. // Try and find a smart game obj with the same playerdata
  1216. SLNode<SmartGameObj> * smart_objnode;
  1217. for (smart_objnode = GameObjManager::Get_Smart_Game_Obj_List()->Head(); smart_objnode; smart_objnode = smart_objnode->Next()) {
  1218. SmartGameObj * obj = smart_objnode->Data();
  1219. if ( obj->Get_Player_Data() == OwnerBackup ) {
  1220. Owner = obj;
  1221. Debug_Say(( "Found Beacon owner\n" ));
  1222. }
  1223. }
  1224. if ( Get_Owner() == NULL ) {
  1225. Debug_Say(( "Didn't find Beacon owner\n" ));
  1226. }
  1227. }
  1228. }