harvester.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479
  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. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : Combat *
  23. * *
  24. * $Archive:: /Commando/Code/Combat/harvester.cpp $*
  25. * *
  26. * Author:: Patrick Smith *
  27. * *
  28. * $Modtime:: 1/18/02 11:16p $*
  29. * *
  30. * $Revision:: 11 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. #include "harvester.h"
  36. #include "vehicle.h"
  37. #include "refinerygameobj.h"
  38. #include "animcontrol.h"
  39. #include "vehiclephys.h"
  40. ////////////////////////////////////////////////////////////////
  41. // Local constants
  42. ////////////////////////////////////////////////////////////////
  43. enum
  44. {
  45. ACTIONID_GOTO_TIBERIUM = 1000,
  46. ACTIONID_DOCK,
  47. };
  48. ////////////////////////////////////////////////////////////////
  49. //
  50. // HarvesterClass
  51. //
  52. ////////////////////////////////////////////////////////////////
  53. HarvesterClass::HarvesterClass (void) :
  54. Refinery (NULL),
  55. DockLocation (0, 0, 0),
  56. DockEntrance (0, 0, 0),
  57. StateTimer (0),
  58. State (STATE_UNINITIALIZED),
  59. Vehicle (NULL),
  60. IsHarvesting (false)
  61. {
  62. Set_ID (GameObjObserverManager::Get_Next_Observer_ID ());
  63. return ;
  64. }
  65. ////////////////////////////////////////////////////////////////
  66. //
  67. // ~HarvesterClass
  68. //
  69. ////////////////////////////////////////////////////////////////
  70. HarvesterClass::~HarvesterClass (void)
  71. {
  72. return ;
  73. }
  74. ////////////////////////////////////////////////////////////////
  75. //
  76. // Initialize
  77. //
  78. ////////////////////////////////////////////////////////////////
  79. void
  80. HarvesterClass::Initialize (void)
  81. {
  82. Go_Harvest ();
  83. return ;
  84. }
  85. ////////////////////////////////////////////////////////////////
  86. //
  87. // Go_Harvest
  88. //
  89. ////////////////////////////////////////////////////////////////
  90. void
  91. HarvesterClass::Go_Harvest (void)
  92. {
  93. //
  94. // Bail if the vehicle pointer is invalid, or if the vehicle
  95. // isn't on the ground...
  96. //
  97. if (Vehicle == NULL || Vehicle->Peek_Vehicle_Phys ()->Is_In_Contact () == false) {
  98. return ;
  99. }
  100. State = STATE_GOING_TO_HARVEST;
  101. //
  102. // Choose a random offset into the tiberium box
  103. //
  104. Vector3 rand_offset;
  105. rand_offset.X = WWMath::Random_Float (0, TiberiumRegion.Extent.X - 5);
  106. rand_offset.Y = WWMath::Random_Float (0, TiberiumRegion.Extent.Y - 5);
  107. rand_offset.Z = 0;
  108. //
  109. // Tranform this random offset into a world space position
  110. //
  111. Vector3 rand_pos = TiberiumRegion.Center + (TiberiumRegion.Basis * rand_offset);
  112. //
  113. // Setup an action to instruct the vehicle to goto that location
  114. //
  115. ActionParamsStruct parameters;
  116. parameters.Priority = 99;
  117. parameters.ActionID = ACTIONID_GOTO_TIBERIUM;
  118. parameters.ObserverID = Get_ID ();
  119. parameters.Set_Movement (rand_pos, 1.0F, 1.0F);
  120. Vehicle->Get_Action ()->Goto (parameters);
  121. return ;
  122. }
  123. ////////////////////////////////////////////////////////////////
  124. //
  125. // Go_Unload_Tiberium
  126. //
  127. ////////////////////////////////////////////////////////////////
  128. void
  129. HarvesterClass::Go_Unload_Tiberium (void)
  130. {
  131. Play_Harvest_Animation (false);
  132. //
  133. // Switch states
  134. //
  135. IsHarvesting = false;
  136. State = STATE_GOING_TO_UNLOAD;
  137. //
  138. // Setup an action to instruct the vehicle to dock in its refinery
  139. //
  140. ActionParamsStruct parameters;
  141. parameters.Priority = 99;
  142. parameters.ActionID = ACTIONID_DOCK;
  143. parameters.ObserverID = Get_ID ();
  144. parameters.Dock_Vehicle (DockLocation, DockEntrance);
  145. parameters.MoveSpeed = 1.0F;
  146. Vehicle->Get_Action ()->Dock_Vehicle (parameters);
  147. return ;
  148. }
  149. ////////////////////////////////////////////////////////////////
  150. //
  151. // Unload_Tiberium
  152. //
  153. ////////////////////////////////////////////////////////////////
  154. void
  155. HarvesterClass::Unload_Tiberium (void)
  156. {
  157. Refinery->On_Harvester_Docked ();
  158. State = STATE_UNLOADING;
  159. return ;
  160. }
  161. ////////////////////////////////////////////////////////////////
  162. //
  163. // Harvest_Tiberium
  164. //
  165. ////////////////////////////////////////////////////////////////
  166. void
  167. HarvesterClass::Harvest_Tiberium (void)
  168. {
  169. //
  170. // Reset the harvesting timer (if necessary)
  171. //
  172. if (IsHarvesting == false) {
  173. HarvestTimer = 15.0F;
  174. IsHarvesting = true;
  175. }
  176. //
  177. // Harvest the tiberium for a few seconds
  178. //
  179. State = STATE_HARVESTING;
  180. StateTimer = WWMath::Random_Float (3.0F, 7.0F);
  181. //
  182. // Start playing the harvest animation
  183. //
  184. Play_Harvest_Animation (true);
  185. return ;
  186. }
  187. ////////////////////////////////////////////////////////////////
  188. //
  189. // Action_Complete
  190. //
  191. ////////////////////////////////////////////////////////////////
  192. void
  193. HarvesterClass::Action_Complete
  194. (
  195. GameObject * game_obj,
  196. int action_id,
  197. ActionCompleteReason complete_reason
  198. )
  199. {
  200. //
  201. // Check to ensure the harvester successfully completed
  202. // its action...
  203. //
  204. if (complete_reason == ACTION_COMPLETE_NORMAL) {
  205. //
  206. // Which action was completed?
  207. //
  208. if (action_id == ACTIONID_GOTO_TIBERIUM) {
  209. //
  210. // Check to ensure we were going to harvest the
  211. // tiberium before actually start harvesting
  212. //
  213. if (State == STATE_GOING_TO_HARVEST) {
  214. Harvest_Tiberium ();
  215. }
  216. } else if (action_id == ACTIONID_DOCK) {
  217. Unload_Tiberium ();
  218. }
  219. }
  220. return ;
  221. }
  222. ////////////////////////////////////////////////////////////////
  223. //
  224. // Animation_Complete
  225. //
  226. ////////////////////////////////////////////////////////////////
  227. void
  228. HarvesterClass::Animation_Complete
  229. (
  230. GameObject * game_obj,
  231. const char * animation_name
  232. )
  233. {
  234. return ;
  235. }
  236. ////////////////////////////////////////////////////////////////
  237. //
  238. // Attach
  239. //
  240. ////////////////////////////////////////////////////////////////
  241. void
  242. HarvesterClass::Attach (GameObject *game_obj)
  243. {
  244. WWASSERT (game_obj != NULL);
  245. if (game_obj != NULL) {
  246. //
  247. // See if this game object is a vehicle (it better be)
  248. //
  249. PhysicalGameObj *physical_obj = game_obj->As_PhysicalGameObj ();
  250. if (physical_obj != NULL) {
  251. Vehicle = physical_obj->As_VehicleGameObj ();
  252. }
  253. }
  254. return ;
  255. }
  256. ////////////////////////////////////////////////////////////////
  257. //
  258. // Detach
  259. //
  260. ////////////////////////////////////////////////////////////////
  261. void
  262. HarvesterClass::Detach (GameObject * /*game_obj*/)
  263. {
  264. //
  265. // Remove ourselves from the refinery
  266. //
  267. if (Refinery != NULL) {
  268. Refinery->Set_Harvester (NULL);
  269. }
  270. Vehicle = NULL;
  271. return ;
  272. }
  273. ////////////////////////////////////////////////////////////////
  274. //
  275. // Think
  276. //
  277. ////////////////////////////////////////////////////////////////
  278. void
  279. HarvesterClass::Think (void)
  280. {
  281. if (IsHarvesting) {
  282. //
  283. // If we are harvesting, check to see if its time to go unload
  284. // the tiberium.
  285. //
  286. HarvestTimer -= TimeManager::Get_Frame_Seconds ();
  287. if (HarvestTimer <= 0) {
  288. Go_Unload_Tiberium ();
  289. }
  290. }
  291. switch (State)
  292. {
  293. case STATE_HARVESTING:
  294. //
  295. // Check to see if we should harvest in a new location
  296. //
  297. StateTimer -= TimeManager::Get_Frame_Seconds ();
  298. if (StateTimer <= 0) {
  299. Go_Harvest ();
  300. }
  301. break;
  302. case STATE_UNINITIALIZED:
  303. if (Vehicle != NULL) {
  304. Go_Harvest ();
  305. }
  306. break;
  307. case STATE_GOING_TO_HARVEST:
  308. case STATE_GOING_TO_UNLOAD:
  309. case STATE_UNLOADING:
  310. default:
  311. break;
  312. }
  313. return ;
  314. }
  315. ////////////////////////////////////////////////////////////////
  316. //
  317. // Stop
  318. //
  319. ////////////////////////////////////////////////////////////////
  320. void
  321. HarvesterClass::Stop (void)
  322. {
  323. //
  324. // Stopt the harvester from moving
  325. //
  326. if (Vehicle != NULL) {
  327. Vehicle->Get_Action ()->Reset (100);
  328. Vehicle->Enable_Engine (false);
  329. }
  330. return ;
  331. }
  332. ////////////////////////////////////////////////////////////////
  333. //
  334. // Play_Harvest_Animation
  335. //
  336. ////////////////////////////////////////////////////////////////
  337. void
  338. HarvesterClass::Play_Harvest_Animation (bool onoff)
  339. {
  340. if (onoff) {
  341. //
  342. // Play the animation looped...
  343. //
  344. Vehicle->Set_Animation (HarvestAnimationName, true);
  345. } else {
  346. //
  347. // Stop the animation
  348. //
  349. AnimControlClass *anim_control = Vehicle->Get_Anim_Control ();
  350. if (anim_control != NULL) {
  351. anim_control->Set_Animation( (const char *)NULL );
  352. }
  353. }
  354. return ;
  355. }
  356. ////////////////////////////////////////////////////////////////
  357. //
  358. // Custom
  359. //
  360. ////////////////////////////////////////////////////////////////
  361. void
  362. HarvesterClass::Custom
  363. (
  364. GameObject * game_obj,
  365. int type,
  366. int param,
  367. GameObject * sender
  368. )
  369. {
  370. //
  371. // Are we backing into the docking bay?
  372. //
  373. if (type == CUSTOM_EVENT_DOCK_BACKING_IN) {
  374. Refinery->Play_Unloading_Animation (true);
  375. }
  376. return ;
  377. }
  378. void HarvesterClass::Damaged(GameObject* damaged, GameObject* killer, float amount)
  379. {
  380. // Only report damage not heal
  381. if (amount > 0.0f) {
  382. VehicleGameObj* vehicle = static_cast<VehicleGameObj*>(damaged);
  383. assert(Vehicle == vehicle);
  384. // If the unit has been damaged to the point of being destroyed
  385. // then do not report the damaged event. A killed event will be sent
  386. // later.
  387. DefenseObjectClass* defense = vehicle->Get_Defense_Object();
  388. if (defense && (defense->Get_Health() <= 0.0f)) {
  389. return;
  390. }
  391. DamageableGameObj* damager = NULL;
  392. if (killer) {
  393. damager = killer->As_DamageableGameObj();
  394. }
  395. bool friendlyFire = (damager && (damager->Get_Player_Type() == vehicle->Get_Player_Type()));
  396. // Notify the building
  397. if (!friendlyFire) {
  398. assert(Refinery != NULL);
  399. Refinery->On_Harvester_Damaged(vehicle);
  400. }
  401. }
  402. }
  403. void HarvesterClass::Destroyed(GameObject* destroyed)
  404. {
  405. VehicleGameObj* vehicle = static_cast<VehicleGameObj*>(destroyed);
  406. assert(Vehicle == vehicle);
  407. Refinery->On_Harvester_Destroyed(vehicle);
  408. }