gameobjmanager.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655
  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/gameobjmanager.cpp $*
  25. * *
  26. * $Author:: Byon_g $*
  27. * *
  28. * $Modtime:: 12/21/01 3:43p $*
  29. * *
  30. * $Revision:: 76 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. #include "gameobjmanager.h"
  36. #include "wwdebug.h"
  37. #include "smartgameobj.h"
  38. #include "combatchunkid.h"
  39. #include "saveloadsubsystem.h"
  40. #include "persistfactory.h"
  41. #include "debug.h"
  42. #include "combat.h"
  43. #include "scripts.h"
  44. #include "soldier.h"
  45. #include "building.h"
  46. #include "wwphysids.h"
  47. #include "scriptzone.h"
  48. #include "wwprofile.h"
  49. #include "networkobjectmgr.h"
  50. #include "networkobjectmgr.h"
  51. #include "vehicle.h"
  52. #include "persistentgameobjobserver.h"
  53. #include "weapons.h"
  54. /*
  55. ** Create an instance of the game object manager list. Since all
  56. ** memeber functions are static, no one needs to see it
  57. */
  58. SList<BaseGameObj> GameObjManager::GameObjList;
  59. SList<SmartGameObj> GameObjManager::SmartGameObjList; // list of all render game objs
  60. SList<SoldierGameObj> GameObjManager::StarGameObjList;
  61. SList<BuildingGameObj> GameObjManager::BuildingGameObjList;
  62. bool GameObjManager::CinematicFreezeActive;
  63. /*
  64. **
  65. */
  66. void GameObjManager::Init(void)
  67. {
  68. Destroy_All();
  69. CinematicFreezeActive = false;
  70. }
  71. void GameObjManager::Shutdown(void)
  72. {
  73. Destroy_All();
  74. PersistentGameObjObserverManager::Reset();
  75. }
  76. /*
  77. **
  78. */
  79. enum {
  80. CHUNKID_OBJECTS = 916991653,
  81. CHUNKID_VARIABLES,
  82. MICROCHUNKID_GENERATED_ID = 1,
  83. MICROCHUNKID_GLOBAL_SIGHT_RANGE_SCALE,
  84. MICROCHUNKID_CINEMATIC_FREEZE,
  85. };
  86. bool GameObjManager::Save( ChunkSaveClass &csave )
  87. {
  88. csave.Begin_Chunk( CHUNKID_OBJECTS );
  89. // Allow each object in the master list to save
  90. SLNode<BaseGameObj> *objnode;
  91. for ( objnode = GameObjManager::Get_Game_Obj_List()->Head(); objnode; objnode = objnode->Next()) {
  92. BaseGameObj * obj = objnode->Data();
  93. csave.Begin_Chunk( obj->Get_Factory().Chunk_ID() );
  94. obj->Get_Factory().Save( csave, obj );
  95. csave.End_Chunk();
  96. }
  97. csave.End_Chunk();
  98. csave.Begin_Chunk( CHUNKID_VARIABLES );
  99. int next_id = NetworkObjectMgrClass::Get_Current_Dynamic_ID ();
  100. WRITE_MICRO_CHUNK( csave, MICROCHUNKID_GENERATED_ID, next_id );
  101. float scale = SmartGameObj::Get_Global_Sight_Range_Scale();
  102. WRITE_MICRO_CHUNK( csave, MICROCHUNKID_GLOBAL_SIGHT_RANGE_SCALE, scale );
  103. WRITE_MICRO_CHUNK( csave, MICROCHUNKID_CINEMATIC_FREEZE, CinematicFreezeActive );
  104. csave.End_Chunk();
  105. return true;
  106. }
  107. bool GameObjManager::Load( ChunkLoadClass &cload )
  108. {
  109. float sight_scale = 1.0f;
  110. while (cload.Open_Chunk()) {
  111. switch(cload.Cur_Chunk_ID()) {
  112. case CHUNKID_OBJECTS:
  113. while (cload.Open_Chunk()) {
  114. PersistFactoryClass * factory = SaveLoadSystemClass::Find_Persist_Factory( cload.Cur_Chunk_ID() );
  115. if ( factory ) {
  116. factory->Load( cload );
  117. }
  118. cload.Close_Chunk();
  119. }
  120. break;
  121. case CHUNKID_VARIABLES:
  122. while (cload.Open_Micro_Chunk()) {
  123. switch(cload.Cur_Micro_Chunk_ID()) {
  124. READ_MICRO_CHUNK( cload, MICROCHUNKID_GLOBAL_SIGHT_RANGE_SCALE, sight_scale );
  125. READ_MICRO_CHUNK( cload, MICROCHUNKID_CINEMATIC_FREEZE, CinematicFreezeActive );
  126. case MICROCHUNKID_GENERATED_ID:
  127. {
  128. /*TSS091001*/
  129. int next_id = NETID_DYNAMIC_OBJECT_MIN;
  130. LOAD_MICRO_CHUNK( cload, next_id )
  131. NetworkObjectMgrClass::Set_New_Dynamic_ID( next_id );
  132. Debug_Say(( "NetworkObjectMgrClass::Set_New_Dynamic_ID to %d\n", next_id ));
  133. /**/
  134. break;
  135. }
  136. default:
  137. Debug_Say(( "Unrecognized GameObjManager Variable chunkID %d\n", cload.Cur_Micro_Chunk_ID() ));
  138. break;
  139. }
  140. cload.Close_Micro_Chunk();
  141. }
  142. break;
  143. default:
  144. Debug_Say(( "Unrecognized GameObjManager chunkID %d\n", cload.Cur_Chunk_ID() ));
  145. break;
  146. }
  147. cload.Close_Chunk();
  148. }
  149. SmartGameObj::Set_Global_Sight_Range_Scale( sight_scale );
  150. return true;
  151. }
  152. void GameObjManager::Add( BaseGameObj *obj )
  153. {
  154. // Make sure we have no duplicate IDs
  155. PhysicalGameObj *pobj = obj->As_PhysicalGameObj();
  156. if ( pobj ) {
  157. WWASSERT( Find_PhysicalGameObj(pobj->Get_ID()) == NULL );
  158. }
  159. // Cinematic scripts wanted objects not to progress on the frame they were created,
  160. // and wanted the ability to set a frame number without haveing it bumped.
  161. // So, make new things at the head of the list, so the oldest thinks last.
  162. // GameObjList.Add_Tail( obj );
  163. GameObjList.Add_Head( obj );
  164. }
  165. void GameObjManager::Init_All()
  166. {
  167. #if 0
  168. SLNode<BaseGameObj> *objnode;
  169. for ( objnode = GameObjList.Head(); objnode; objnode = objnode->Next()) {
  170. objnode->Data()->Init();
  171. }
  172. #endif
  173. }
  174. /*
  175. ** GameObjectManager::Destroy_All
  176. ** This static routine destroys all objects
  177. */
  178. void GameObjManager::Destroy_All() // Destroy each object in the list
  179. {
  180. ScriptManager::Enable_Script_Creation( false ); // Disable new scripts
  181. SLNode<BaseGameObj> *objnode;
  182. for ( objnode = GameObjList.Head(); objnode; objnode = objnode->Next()) {
  183. objnode->Data()->Set_Delete_Pending();
  184. }
  185. #pragma message ("Disabling Think and Post_Think in GameObjManager::Destroy_All()")
  186. #if 0
  187. Think();
  188. Post_Think();
  189. #endif
  190. NetworkObjectMgrClass::Delete_Pending ();
  191. // we do it twice in case any new objects got created
  192. for ( objnode = GameObjList.Head(); objnode; objnode = objnode->Next()) {
  193. objnode->Data()->Set_Delete_Pending();
  194. }
  195. #if 0
  196. Think();
  197. Post_Think();
  198. #endif
  199. NetworkObjectMgrClass::Delete_Pending ();
  200. WWASSERT( GameObjList.Head() == NULL );
  201. WWASSERT( SmartGameObjList.Head() == NULL );
  202. WWASSERT( StarGameObjList.Head() == NULL );
  203. WWASSERT( BuildingGameObjList.Head() == NULL );
  204. ScriptManager::Enable_Script_Creation( true ); // turn it back on
  205. }
  206. /*
  207. ** GameObjectManager::Update_Control()
  208. ** This routine allows each SmartGameObject to generate input controls
  209. */
  210. int GameObjManager::Generate_Control()
  211. {
  212. SLNode<SmartGameObj> *objnode;
  213. for ( objnode = SmartGameObjList.Head(); objnode; objnode = objnode->Next()) {
  214. // Don't genreate_control when cinematic frozen
  215. if ( Is_Cinematic_Freeze_Active() && objnode->Data()->Is_Cinematic_Freeze_Enabled() ) {
  216. continue;
  217. }
  218. if ( !objnode->Data()->Is_Hibernating() ) {
  219. objnode->Data()->Generate_Control();
  220. }
  221. }
  222. return 0;
  223. }
  224. int _AwakeSoldiers = 0;
  225. int _HibernatingSoldiers = 0;
  226. /*
  227. ** This static routine allows each GameObject to think
  228. */
  229. int GameObjManager::Think()
  230. {
  231. // Allow each object in the master list to think
  232. SLNode<BaseGameObj> *objnode;
  233. for ( objnode = GameObjList.Head(); objnode; objnode = objnode->Next()) {
  234. // Don't think when cinematic frozen
  235. if ( Is_Cinematic_Freeze_Active() && objnode->Data()->Is_Cinematic_Freeze_Enabled() ) {
  236. // Stop the physics motion
  237. if ( objnode->Data()->As_SmartGameObj() != NULL ) {
  238. objnode->Data()->As_SmartGameObj()->Reset_Controller();
  239. // And the weapon (flames, etc)
  240. if ( objnode->Data()->As_SmartGameObj()->Get_Weapon() != NULL ) {
  241. objnode->Data()->As_SmartGameObj()->Get_Weapon()->Deselect();
  242. }
  243. }
  244. continue;
  245. }
  246. if ( !objnode->Data()->Is_Hibernating() ) {
  247. objnode->Data()->Think();
  248. }
  249. if ( objnode->Data()->As_SmartGameObj() ) {
  250. if ( objnode->Data()->As_SmartGameObj()->As_SoldierGameObj() ) {
  251. if ( objnode->Data()->Is_Hibernating() ) {
  252. _HibernatingSoldiers++;
  253. } else {
  254. _AwakeSoldiers++;
  255. }
  256. }
  257. }
  258. }
  259. return 0;
  260. }
  261. /*
  262. ** GameObjectManager::PostThink()
  263. ** This static routine allows each GameObject to think after the rest
  264. */
  265. int GameObjManager::Post_Think()
  266. {
  267. // Allow each object in the master list to think
  268. SLNode<BaseGameObj> *objnode;
  269. for ( objnode = GameObjList.Head(); objnode; objnode = objnode->Next()) {
  270. // Don't post_think when cinematic frozen
  271. if ( Is_Cinematic_Freeze_Active() && objnode->Data()->Is_Cinematic_Freeze_Enabled() ) {
  272. continue;
  273. }
  274. if ( !objnode->Data()->Is_Hibernating() && objnode->Data()->Is_Post_Think_Allowed() ) {
  275. objnode->Data()->Post_Think();
  276. }
  277. }
  278. //Destroy_Pending();
  279. GameObjObserverManager::Delete_Pending();
  280. ScriptManager::Destroy_Pending();
  281. return 0;
  282. }
  283. /*
  284. ** searches the commando with this client id
  285. */
  286. SoldierGameObj * GameObjManager::Find_Soldier_Of_Client_ID(int client_id)
  287. {
  288. {
  289. WWPROFILE( "FSOC id" );
  290. for (
  291. SLNode<SmartGameObj> * objnode = Get_Smart_Game_Obj_List()->Head();
  292. objnode;
  293. objnode = objnode->Next()) {
  294. SoldierGameObj * p_soldier = objnode->Data()->As_SoldierGameObj();
  295. if (p_soldier != NULL &&
  296. !p_soldier->Is_Delete_Pending() &&
  297. p_soldier->Get_Control_Owner() == client_id) {
  298. return p_soldier;
  299. }
  300. }
  301. }
  302. return NULL;
  303. }
  304. /*
  305. ** searches for a player commando other than my own
  306. */
  307. SoldierGameObj * GameObjManager::Find_Different_Player_Soldier(int my_id)
  308. {
  309. for (
  310. SLNode<SmartGameObj> * objnode = Get_Smart_Game_Obj_List()->Head();
  311. objnode;
  312. objnode = objnode->Next()) {
  313. SoldierGameObj * p_soldier = objnode->Data()->As_SoldierGameObj();
  314. if (p_soldier != NULL &&
  315. !p_soldier->Is_Delete_Pending() &&
  316. p_soldier->Is_Human_Controlled() &&
  317. p_soldier->Get_Control_Owner() != my_id) {
  318. return p_soldier;
  319. }
  320. }
  321. return NULL;
  322. }
  323. SoldierGameObj * GameObjManager::Find_Soldier_Of_Player_Type(int player_type)
  324. {
  325. for (
  326. SLNode<SmartGameObj> * objnode = Get_Smart_Game_Obj_List()->Head();
  327. objnode;
  328. objnode = objnode->Next()) {
  329. SoldierGameObj * p_soldier = objnode->Data()->As_SoldierGameObj();
  330. if (p_soldier != NULL &&
  331. !p_soldier->Is_Delete_Pending() &&
  332. p_soldier->Get_Player_Type() == player_type) {
  333. return p_soldier;
  334. }
  335. }
  336. return NULL;
  337. }
  338. /*
  339. ** searches the game object list for the object with this id
  340. */
  341. PhysicalGameObj * GameObjManager::Find_PhysicalGameObj( int id )
  342. {
  343. SLNode<BaseGameObj> * objnode;
  344. for ( objnode = GameObjList.Head(); objnode; objnode = objnode->Next()) {
  345. PhysicalGameObj *obj = objnode->Data()->As_PhysicalGameObj();
  346. if ( obj && (obj->Get_ID() == id) ) {
  347. return obj; // found it
  348. }
  349. }
  350. return NULL; // Not found
  351. }
  352. /*
  353. ** searches the game object list for the object with this id
  354. */
  355. ScriptableGameObj * GameObjManager::Find_ScriptableGameObj( int id )
  356. {
  357. SLNode<BaseGameObj> * objnode;
  358. for ( objnode = GameObjList.Head(); objnode; objnode = objnode->Next()) {
  359. ScriptableGameObj *obj = objnode->Data()->As_ScriptableGameObj();
  360. if ( obj && (obj->Get_ID() == id) ) {
  361. return obj; // found it
  362. }
  363. }
  364. return NULL; // Not found
  365. }
  366. /*
  367. ** searches the game object list for a vehicle occupied by the given soldier.
  368. */
  369. VehicleGameObj * GameObjManager::Find_Vehicle_Occupied_By( SoldierGameObj * p_soldier )
  370. {
  371. WWASSERT(p_soldier != NULL);
  372. SLNode<BaseGameObj> * objnode;
  373. for ( objnode = GameObjList.Head(); objnode; objnode = objnode->Next()) {
  374. VehicleGameObj *obj = objnode->Data()->As_VehicleGameObj();
  375. //if ( obj && (obj->Get_Driver() == p_soldier) ) {
  376. if ( obj && obj->Contains_Occupant( p_soldier) ) {
  377. return obj; // found it
  378. }
  379. }
  380. return NULL; // Not found
  381. }
  382. /*
  383. ** searches the smart game object list for the object with this id
  384. */
  385. SmartGameObj * GameObjManager::Find_SmartGameObj( int id )
  386. {
  387. SLNode<SmartGameObj> * objnode;
  388. for ( objnode = SmartGameObjList.Head(); objnode; objnode = objnode->Next()) {
  389. SmartGameObj *obj = objnode->Data();
  390. if ( obj->Is_Delete_Pending() ) continue; // Perhaps not find things that will be dieing?
  391. if ( obj->Get_ID() == id ) {
  392. return obj; // found it
  393. }
  394. }
  395. return NULL; // Not found
  396. }
  397. /*
  398. ** Buildings
  399. */
  400. void GameObjManager::Init_Buildings( void )
  401. {
  402. /*
  403. ** Ask each building to build its list of aggregates, meshes, and lights
  404. */
  405. SLNode<BuildingGameObj> *objnode = NULL;
  406. for ( objnode = BuildingGameObjList.Head(); objnode; objnode = objnode->Next() ) {
  407. BuildingGameObj *obj = objnode->Data()->As_BuildingGameObj();
  408. if (obj != NULL) {
  409. obj->Collect_Building_Components();
  410. }
  411. }
  412. return ;
  413. }
  414. /*
  415. ** Update_Building_Collection_Spheres
  416. */
  417. void GameObjManager::Update_Building_Collection_Spheres( void )
  418. {
  419. SLNode<BuildingGameObj> *objnode = NULL;
  420. for ( objnode = BuildingGameObjList.Head(); objnode; objnode = objnode->Next()) {
  421. BuildingGameObj *obj = objnode->Data()->As_BuildingGameObj();
  422. if (obj != NULL) {
  423. //
  424. // Get some information about the current building
  425. //
  426. const char *prefix = obj->Get_Name_Prefix ();
  427. float max_radius = 50.0F;
  428. Vector3 position;
  429. obj->Get_Position (&position);
  430. //
  431. // Test this building with all other buildings that have the same prefix
  432. //
  433. SLNode<BuildingGameObj> *test_node = NULL;
  434. for ( test_node = BuildingGameObjList.Head(); test_node; test_node = test_node->Next()) {
  435. BuildingGameObj *test_obj = test_node->Data()->As_BuildingGameObj();
  436. //
  437. // Is this a building with the same prefix?
  438. //
  439. if ( test_obj != NULL && test_obj != obj &&
  440. ::stricmp (test_obj->Get_Name_Prefix (), prefix) == 0)
  441. {
  442. //
  443. // Get the test object's position
  444. //
  445. Vector3 test_position;
  446. test_obj->Get_Position (&test_position);
  447. //
  448. // Minimize the collection radius for this building (if necessary)
  449. //
  450. float distance = (position - test_position).Length ();
  451. max_radius = min (distance, max_radius);
  452. }
  453. }
  454. //
  455. // Set this object's collection radius
  456. //
  457. obj->CollectionSphere.Radius = max_radius;
  458. }
  459. }
  460. return ;
  461. }
  462. /*
  463. ** Debug_Set_All_Building_States
  464. */
  465. void GameObjManager::Debug_Set_All_Building_States(float health_percentage,bool power_on)
  466. {
  467. SLNode<BuildingGameObj> * objnode;
  468. for ( objnode = BuildingGameObjList.Head(); objnode; objnode = objnode->Next()) {
  469. BuildingGameObj *building = objnode->Data()->As_BuildingGameObj();
  470. building->Enable_Power(power_on);
  471. building->Set_Normalized_Health(health_percentage / 100.0f);
  472. }
  473. }
  474. /*
  475. ** Environment Zones
  476. */
  477. bool GameObjManager::Is_In_Environment_Zone( Vector3 & pos )
  478. {
  479. WWPROFILE( "Is_In_Environment_Zone" );
  480. // Allow each object in the master list to think
  481. SLNode<BaseGameObj> *objnode;
  482. for ( objnode = GameObjList.Head(); objnode; objnode = objnode->Next()) {
  483. ScriptableGameObj * scriptable = objnode->Data()->As_ScriptableGameObj();
  484. if ( scriptable ) {
  485. ScriptZoneGameObj * script_zone = scriptable->As_ScriptZoneGameObj();
  486. if ( script_zone && script_zone->Is_Environment_Zone() ) {
  487. if ( CollisionMath::Overlap_Test( script_zone->Get_Bounding_Box(), pos ) == CollisionMath::INSIDE ) {
  488. return true;
  489. }
  490. }
  491. }
  492. }
  493. return false;
  494. }
  495. /*
  496. ** GameObjectManager::Destroy_Pending
  497. ** This static routine destroys all objects with destroy bit set
  498. */
  499. /*void GameObjManager::Destroy_Pending()
  500. {
  501. // Remove the wishing to be dead ones
  502. SLNode<BaseGameObj> *objnode;
  503. for ( objnode = GameObjList.Head(); objnode; ) {
  504. WWASSERT(objnode != NULL);
  505. BaseGameObj *obj = objnode->Data();
  506. objnode = objnode->Next();
  507. WWASSERT(obj != NULL);
  508. if ( obj->Is_Destroy() ) {
  509. // If I'm a server, notify all others to destroy this object if this is a physical game obj!
  510. if ( CombatManager::I_Am_Server() ) {
  511. CombatManager::Object_Destroyed(obj);
  512. }
  513. delete obj;
  514. }
  515. }
  516. }*/