combat.cpp 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374
  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/combat.cpp $*
  25. * *
  26. * $Author:: Bhayes $*
  27. * *
  28. * $Modtime:: 2/17/02 10:25a $*
  29. * *
  30. * $Revision:: 265 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. #include "combat.h"
  36. #include "ccamera.h"
  37. #include "gameobjmanager.h"
  38. #include "input.h"
  39. #include "weaponmanager.h"
  40. #include "wwprofile.h"
  41. #include "scripts.h"
  42. #include "pscene.h"
  43. #include "damage.h"
  44. #include "ww3d.h"
  45. #include "assets.h"
  46. #include "timemgr.h"
  47. #include "soldier.h"
  48. #include "SoundScene.H"
  49. #include "weapons.h"
  50. #include "vehicle.h"
  51. #include "bones.h"
  52. #include "humanstate.h"
  53. #include "surfaceeffects.h"
  54. #include "debug.h"
  55. #include "backgroundmgr.h"
  56. #include "cover.h"
  57. #include "spawn.h"
  58. #include "vehiclephys.h"
  59. #include "building.h"
  60. #include "objectives.h"
  61. #include "conversationmgr.h"
  62. #include "bullet.h"
  63. #include "dazzle.h"
  64. #include "messagewindow.h"
  65. #include "hudinfo.h"
  66. #include "weathermgr.h"
  67. #include "thread.h"
  68. #include "savegame.h"
  69. #include "assetdep.h"
  70. #include "saveloadstatus.h"
  71. #include <stdio.h>
  72. #include "soundenvironment.h"
  73. #include "weaponview.h"
  74. #include "hud.h"
  75. #include "mapmgr.h"
  76. #include "gametype.h"
  77. #include "staticnetworkobject.h"
  78. #include "diaglog.h"
  79. #include "combatdazzle.h"
  80. #include "ffactorylist.h"
  81. #include "definitionfactorymgr.h"
  82. #include "definitionfactory.h"
  83. #include "globalsettings.h"
  84. #include "dx8wrapper.h"
  85. #include "except.h"
  86. #include "cheatmgr.h"
  87. #include "systeminfolog.h"
  88. #include "assetstatus.h"
  89. #include "wwmemlog.h"
  90. #include "unitcoordinationzonemgr.h"
  91. #include "fastallocator.h"
  92. #include "screenfademanager.h"
  93. #include "animatedsoundmgr.h"
  94. #include "render2dsentence.h"
  95. #include "stylemgr.h"
  96. #include "translatedb.h"
  97. #include "string_ids.h"
  98. const int DEFAULT_MAX_SHADOWS = 4;
  99. /*
  100. **
  101. */
  102. CCameraClass * CombatManager::MainCamera = NULL;
  103. SimpleSceneClass * CombatManager::BackgroundScene = NULL;
  104. SoundEnvironmentClass * CombatManager::SoundEnvironment = NULL;
  105. DazzleLayerClass * CombatManager::DazzleLayer = NULL;
  106. GameObjReference CombatManager::TheStar;
  107. bool CombatManager::IsStarDeterminingTarget = true;
  108. //bool CombatManager::IAmServer = true;
  109. //bool CombatManager::IAmClient = true;
  110. bool CombatManager::IAmServer = false;
  111. bool CombatManager::IAmClient = false;
  112. bool CombatManager::IAmOnlyClient = false;
  113. bool CombatManager::IAmOnlyServer = false;
  114. int CombatManager::MyId = 0;
  115. int CombatManager::SyncTime = 0;
  116. CombatNetworkHandlerClass * CombatManager::NetworkHandler = NULL;
  117. CombatMiscHandlerClass * CombatManager::MiscHandler = NULL;
  118. MessageWindowClass * CombatManager::MessageWindow = NULL;
  119. bool CombatManager::EnableSkeletonSliderDemo = false;
  120. int CombatManager::DifficultyLevel = 1;
  121. bool CombatManager::AutoTransitions = true;
  122. int CombatManager::StarDamageDirection = 0;
  123. bool CombatManager::AreObserversActive = true;
  124. bool CombatManager::FirstPerson = true;
  125. bool CombatManager::FirstPersonDefault = true;
  126. bool CombatManager::IsFirstLoad = false;
  127. int CombatManager::StarKillerID = 0;
  128. bool CombatManager::IsGamePaused = false;
  129. bool CombatManager::IsLevelInitialized = false;
  130. StringClass CombatManager::StartScript;
  131. StringClass CombatManager::RespawnScript;
  132. bool CombatManager::AutosaveRequested = false;
  133. DWORD CombatManager::LastRoundTripPingMs = 0;
  134. DWORD CombatManager::AvgRoundTripPingMs = 0;
  135. bool CombatManager::FriendlyFirePermitted = false;
  136. bool CombatManager::BeaconPlacementEndsGame = false;
  137. bool CombatManager::HitReticleEnabled = true;
  138. bool CombatManager::IsGameplayPermitted = false;
  139. int CombatManager::CombatMode = CombatManager::COMBAT_MODE_NONE;
  140. int CombatManager::ReloadCount = 0;
  141. StringClass CombatManager::LastLSDName;
  142. int CombatManager::LoadProgress;
  143. bool CombatManager::MultiplayRenderingAllowed = true;
  144. static PhysicsSceneClass * GameScene = NULL;
  145. /*
  146. **
  147. */
  148. void CombatManager::Init( bool render_available )
  149. {
  150. // Debug_Say(("CombatManager::Init\n"));
  151. IsGameplayPermitted=false;
  152. ConversationMgrClass::Initialize ();
  153. MessageWindow = new MessageWindowClass;
  154. MessageWindow->Initialize ();
  155. ScriptManager::Init();
  156. BonesManager::Init();
  157. ArmorWarheadManager::Init();
  158. CCameraClass::Init();
  159. SurfaceEffectsManager::Init();
  160. ObjectiveManager::Init();
  161. CombatSoundManager::Init();
  162. // create THE camera
  163. MainCamera = new CCameraClass();
  164. // create the dazzle layer
  165. if (render_available) {
  166. DazzleLayer = new DazzleLayerClass;
  167. DazzleRenderObjClass::Set_Current_Dazzle_Layer(DazzleLayer);
  168. } else {
  169. DazzleRenderObjClass::Set_Current_Dazzle_Layer(NULL);
  170. }
  171. // Pass the main camera onto the 3D audio library as the
  172. // listener's position.
  173. SoundSceneClass *sound_scene = WWAudioClass::Get_Instance ()->Get_Sound_Scene ();
  174. if (sound_scene != NULL) {
  175. sound_scene->Attach_Listener_To_Obj (MainCamera);
  176. }
  177. HUDClass::Init(render_available);
  178. ScreenFadeManager::Init();
  179. FirstPerson = FirstPersonDefault;
  180. }
  181. /*
  182. **
  183. */
  184. void CombatManager::Shutdown( void )
  185. {
  186. // Debug_Say(("CombatManager::Shutdown\n"));
  187. ScreenFadeManager::Shutdown();
  188. HUDClass::Shutdown();
  189. if ( GameScene != NULL ) {
  190. // Debug_Say(( "Releasing the PScene with %d Refs\n", GameScene->Num_Refs() ));
  191. GameScene->Release_Ref();
  192. GameScene = NULL;
  193. }
  194. //
  195. // Reset the audio library
  196. //
  197. if (WWAudioClass::Get_Instance () != NULL) {
  198. SoundSceneClass *sound_scene = WWAudioClass::Get_Instance ()->Get_Sound_Scene ();
  199. if (sound_scene != NULL) {
  200. sound_scene->Attach_Listener_To_Obj (NULL);
  201. }
  202. }
  203. if (DazzleLayer != NULL) {
  204. delete DazzleLayer;
  205. DazzleLayer = NULL;
  206. DazzleRenderObjClass::Set_Current_Dazzle_Layer(NULL);
  207. }
  208. MainCamera->Release_Ref();
  209. MainCamera = NULL;
  210. CombatSoundManager::Shutdown();
  211. ObjectiveManager::Shutdown();
  212. SurfaceEffectsManager::Shutdown();
  213. CCameraClass::Shutdown();
  214. ArmorWarheadManager::Shutdown();
  215. BonesManager::Shutdown();
  216. ScriptManager::Shutdown();
  217. if (MessageWindow != NULL) {
  218. MessageWindow->Shutdown ();
  219. delete MessageWindow;
  220. MessageWindow = NULL;
  221. }
  222. ConversationMgrClass::Shutdown ();
  223. // Debug_Say(( "Combat Shutdown %d refs\n", RefCountClass::Total_Refs() ));
  224. }
  225. void CombatManager::Scene_Init( void )
  226. {
  227. // Game scene is where the main action occurs!
  228. GameScene = new PhysicsSceneClass;
  229. GameScene->Set_Ambient_Light(Vector3(0.55f,0.55f,0.55f));
  230. GameScene->Set_Ambient_Light(Vector3(1,1,1));
  231. GameScene->Set_Fog_Color(Vector3(0.6f,0.6f,0.6f)); //Vector3(80.0f/255.0f,130.0f/255.0f,180.0f/255.0f));
  232. // Do all 'Enable_All's, then all 'Disable_All's, then the individual pairs
  233. COMBAT_SCENE->Enable_All_Collision_Detections( DEFAULT_COLLISION_GROUP );
  234. COMBAT_SCENE->Enable_All_Collision_Detections( BULLET_COLLISION_GROUP );
  235. COMBAT_SCENE->Enable_All_Collision_Detections( TERRAIN_COLLISION_GROUP );
  236. COMBAT_SCENE->Enable_All_Collision_Detections( PhysicsSceneClass::COLLISION_GROUP_WORLD );
  237. COMBAT_SCENE->Enable_All_Collision_Detections( SOLDIER_GHOST_COLLISION_GROUP );
  238. COMBAT_SCENE->Enable_All_Collision_Detections( SOLDIER_COLLISION_GROUP );
  239. COMBAT_SCENE->Disable_All_Collision_Detections( UNCOLLIDEABLE_GROUP );
  240. COMBAT_SCENE->Disable_All_Collision_Detections( TERRAIN_ONLY_COLLISION_GROUP );
  241. COMBAT_SCENE->Disable_All_Collision_Detections( TERRAIN_AND_BULLET_COLLISION_GROUP );
  242. COMBAT_SCENE->Disable_All_Collision_Detections( BULLET_ONLY_COLLISION_GROUP );
  243. COMBAT_SCENE->Enable_Collision_Detection( TERRAIN_ONLY_COLLISION_GROUP, TERRAIN_COLLISION_GROUP );
  244. COMBAT_SCENE->Enable_Collision_Detection( TERRAIN_AND_BULLET_COLLISION_GROUP, TERRAIN_COLLISION_GROUP );
  245. COMBAT_SCENE->Enable_Collision_Detection( TERRAIN_AND_BULLET_COLLISION_GROUP, BULLET_COLLISION_GROUP );
  246. COMBAT_SCENE->Disable_Collision_Detection( BULLET_COLLISION_GROUP, BULLET_COLLISION_GROUP );
  247. COMBAT_SCENE->Enable_Collision_Detection( BULLET_ONLY_COLLISION_GROUP, BULLET_COLLISION_GROUP );
  248. COMBAT_SCENE->Disable_Collision_Detection( PhysicsSceneClass::COLLISION_GROUP_WORLD,PhysicsSceneClass::COLLISION_GROUP_WORLD );
  249. COMBAT_SCENE->Disable_Collision_Detection( SOLDIER_GHOST_COLLISION_GROUP, SOLDIER_COLLISION_GROUP );
  250. COMBAT_SCENE->Disable_Collision_Detection( SOLDIER_GHOST_COLLISION_GROUP, SOLDIER_GHOST_COLLISION_GROUP );
  251. }
  252. /*
  253. ** Note: The editor calls these per level functions only once per program execution.
  254. ** If you have code that requires a init/shutdown/reset call with each level load,
  255. ** notify Pat so he can add those calls manually
  256. **
  257. */
  258. void CombatManager::Pre_Load_Level( bool render_available )
  259. {
  260. MultiplayRenderingAllowed = true;
  261. if ( !IS_MISSION && !I_Am_Server() ) {
  262. MultiplayRenderingAllowed = false;
  263. }
  264. HUDClass::Enable( true );
  265. HUDClass::Reset();
  266. IsGamePaused = false;
  267. GameObjObserverManager::Reset();
  268. CoverManager::Init();
  269. GameObjManager::Init();
  270. BulletManager::Init();
  271. cEncoderList::Clear_Entries();
  272. cPacket::Init_Encoder();
  273. BackgroundScene = NEW_REF (SimpleSceneClass, ());
  274. SoundEnvironment = NEW_REF (SoundEnvironmentClass, ());
  275. BackgroundMgrClass::Init (BackgroundScene, SoundEnvironment, render_available);
  276. WeatherMgrClass::Init (SoundEnvironment);
  277. WeaponViewClass::Init();
  278. SmartGameObj::Set_Global_Sight_Range_Scale( 1.0f );
  279. // SoundSystem::Set_Global_Listener_Scale( 1.0f );
  280. //
  281. // Map initialization (temporary -- until its more data driven)
  282. //
  283. /*MapMgrClass::Set_Map_Texture ("L1-MAP.TGA");
  284. MapMgrClass::Set_Map_Center (Vector2 (308.0F, 414.0F));
  285. MapMgrClass::Set_Map_Scale (Vector2 (0.53F, 0.54F));
  286. MapMgrClass::Cloud_All_Cells ();*/
  287. ScreenFadeManager::Enable_Letterbox( 0, 0 );
  288. ScreenFadeManager::Set_Screen_Overlay_Opacity( 0, 0 );
  289. HUDInfo::Set_HUD_Help_Text( L"" ); // Clear text
  290. }
  291. bool _preload_assets;
  292. StringClass _load_map_name;
  293. static class LoadThreadClass : public ThreadClass
  294. {
  295. public:
  296. LoadThreadClass(const char *thread_name = "Game loader thread") : ThreadClass(thread_name, &Exception_Handler) {}
  297. void Thread_Function() {
  298. CombatManager::Set_Load_Progress( 0 );
  299. WWMEMLOG(MEM_GAMEDATA);
  300. WWLOG_PREPARE_TIME_AND_MEMORY("Game loader thread");
  301. #ifndef PARAM_EDITING_ON
  302. // Tell the datasafe to expect calls from this thread now.
  303. GenericDataSafeClass::Set_Preferred_Thread(GetCurrentThreadId());
  304. #endif // PARAM_EDITING_ON
  305. CombatManager::Inc_Load_Progress();
  306. // Reload the definition databases (to support level-specific temp ddb's)
  307. INIT_STATUS("Free definition databases");
  308. DefinitionMgrClass::Free_Definitions();
  309. WWLOG_INTERMEDIATE("Free definitions");
  310. INIT_STATUS("Load definition databases");
  311. SaveGameManager::Load_Definitions();
  312. WWLOG_INTERMEDIATE("Load definitions");
  313. CombatManager::Inc_Load_Progress();
  314. //
  315. // Make sure the animated-sound system is setup. This needs
  316. // to be done after the definition databases are loaded...
  317. //
  318. AnimatedSoundMgrClass::Initialize ();
  319. StringClass filename_to_load( _load_map_name, true );
  320. StringClass lsd_filename( _load_map_name,true );
  321. // Prep the level loading
  322. INIT_STATUS("Pre Load level");
  323. PlayerInfoLog::Set_Current_Map_Name(_load_map_name);
  324. SaveGameManager::Pre_Load_Game(_load_map_name, filename_to_load, lsd_filename);
  325. CombatManager::Set_Last_LSD_Name( lsd_filename );
  326. WWLOG_INTERMEDIATE("Preload game");
  327. CombatManager::Inc_Load_Progress();
  328. //
  329. // Preload the assets
  330. //
  331. if ( _preload_assets ) {
  332. INIT_STATUS("Preload assets");
  333. AssetDependencyManager::Load_Always_Assets();
  334. WWLOG_INTERMEDIATE("Preload always assets");
  335. CombatManager::Inc_Load_Progress();
  336. AssetDependencyManager::Load_Level_Assets( lsd_filename );
  337. WWLOG_INTERMEDIATE("Preload level assets");
  338. } else {
  339. CombatManager::Inc_Load_Progress();
  340. }
  341. CombatManager::Inc_Load_Progress();
  342. // Now load the level
  343. INIT_STATUS("Load level");
  344. SaveGameManager::Load_Game( filename_to_load );
  345. WWLOG_INTERMEDIATE("Load game");
  346. CombatManager::Inc_Load_Progress();
  347. }
  348. } thread;
  349. void CombatManager::Load_Level_Threaded( const char * map_name, bool preload_assets )
  350. {
  351. //
  352. // Turn off music and sound effects while loading
  353. //
  354. IsLevelInitialized = false;
  355. WWAudioClass::Get_Instance ()->Enable_New_Sounds (false);
  356. _preload_assets = preload_assets;
  357. _load_map_name = map_name;
  358. WWASSERT(!thread.Is_Running());
  359. thread.Execute();
  360. }
  361. bool CombatManager::Is_Load_Level_Complete( void )
  362. {
  363. ThreadClass::Sleep_Ms(50);
  364. return (thread.Is_Running() == false);
  365. }
  366. bool CombatManager::Is_Loading_Level( void )
  367. {
  368. return (thread.Is_Running());
  369. }
  370. /*
  371. ** Note: The editor calls these per level functions only once per program execution.
  372. ** If you have code that requires a init/shutdown/reset call with each level load,
  373. ** notify Pat so he can add those calls manually
  374. **
  375. */
  376. void CombatManager::Post_Load_Level( void )
  377. {
  378. // Dont reset SyncTime. Level from the editor should have it at 0, and levels from
  379. // the game need it set to continue cinematics
  380. // SyncTime = 0;
  381. CombatMode = COMBAT_MODE_NONE;
  382. Input::Flush();
  383. HitReticleEnabled = true; // Default for on when you start each level
  384. Clear_Star_Damage_Direction();
  385. #if 0
  386. // Re-init all objects loaded from editor
  387. if ( CombatManager::Is_First_Load() ) {
  388. Debug_Say(( "Re-Initing all game objects\n" ));
  389. GameObjManager::Init_All();
  390. }
  391. #endif
  392. //
  393. // Build network wrappers for every static anim object in the level
  394. //
  395. StaticNetworkObjectClass::Generate_Static_Network_Objects ();
  396. // Debug code to create a definition
  397. #if 0
  398. DefinitionFactoryClass * def_factory = (DefinitionFactoryClass *)DefinitionFactoryMgrClass::Find_Factory( CLASSID_GLOBAL_SETTINGS_DEF_HUMAN_ANIM_OVERRIDE );
  399. if ( def_factory != NULL ) {
  400. HumanAnimOverrideDef * def = (HumanAnimOverrideDef *)def_factory->Create();
  401. if ( def != NULL ) {
  402. def->Set_Name( "HAO Test" );
  403. def->Set_ID (DefinitionMgrClass::Get_New_ID (def->Get_Class_ID ()));
  404. def->WalkEmptyHands = "H_A_432A";
  405. def->RunEmptyHands = "H_A_J43B";
  406. DefinitionMgrClass::Register_Definition( def );
  407. }
  408. }
  409. #endif
  410. if (IsLevelInitialized == false && TheStar != NULL) {
  411. IsLevelInitialized = true;
  412. //
  413. // Turn music and sound effects back on...
  414. //
  415. WWAudioClass::Get_Instance ()->Enable_New_Sounds (true);
  416. }
  417. //
  418. // Generate the unit coordination zones
  419. //
  420. UnitCoordinationZoneMgr::Build_Zones ();
  421. return ;
  422. }
  423. /*
  424. ** Note: The editor calls these per level functions only once per program execution.
  425. ** If you have code that requires a init/shutdown/reset call with each level load,
  426. ** notify Pat so he can add those calls manually
  427. **
  428. */
  429. void CombatManager::Unload_Level( void )
  430. {
  431. // Display please wait screen.....
  432. Render2DSentenceClass backdropText;
  433. backdropText.Set_Texture_Size_Hint( 256 );
  434. FontCharsClass *font = StyleMgrClass::Peek_Font( StyleMgrClass::FONT_INGAME_BIG_TXT );
  435. if (font != NULL) {
  436. backdropText.Set_Font( font );
  437. WideStringClass wide_str = TRANSLATE( IDS_MP_LOADING );
  438. backdropText.Build_Sentence( wide_str );
  439. Vector2 extents = backdropText.Get_Text_Extents( wide_str );
  440. float x = (Render2DClass::Get_Screen_Resolution().Right - extents.X) / 2.0f;
  441. float y = (Render2DClass::Get_Screen_Resolution().Bottom - extents.Y) / 2.0f;
  442. backdropText.Set_Location( Vector2( (int)x, (int)y ) );
  443. backdropText.Draw_Sentence( 0xFF00FF00 ); // Green
  444. WW3D::Begin_Render( true, true, Vector3(0.0f,0.0f,0.0f), NULL);
  445. backdropText.Render();
  446. WW3D::End_Render();
  447. }
  448. WWLOG_PREPARE_TIME_AND_MEMORY("Unload level");
  449. WWDEBUG_SAY(("CombatManager::Unload_Level\n"));
  450. SystemInfoLog::Set_State_Exiting();
  451. WWLOG_INTERMEDIATE("SystemInfoLog::Set_State_Exiting()");
  452. // Don't log load-on-demands after the game is over
  453. AssetStatusClass::Peek_Instance()->Enable_Load_On_Demand_Reporting(false);
  454. WWLOG_INTERMEDIATE("AssetStatusClass::Peek_Instance()->Enable_Load_On_Demand_Reporting(false)");
  455. //
  456. // Free the static anim phys object network wrappers
  457. //
  458. StaticNetworkObjectClass::Free_Static_Network_Objects ();
  459. WWLOG_INTERMEDIATE("StaticNetworkObjectClass::Free_Static_Network_Objects ()");
  460. WeaponViewClass::Shutdown();
  461. WWLOG_INTERMEDIATE("WeaponViewClass::Shutdown()");
  462. GameObjManager::Shutdown();
  463. WWLOG_INTERMEDIATE("GameObjManager::Shutdown()");
  464. CoverManager::Shutdown();
  465. WWLOG_INTERMEDIATE("CoverManager::Shutdown()");
  466. BulletManager::Shutdown();
  467. WWLOG_INTERMEDIATE("BulletManager::Shutdown()");
  468. ObjectiveManager::Reset();
  469. WWLOG_INTERMEDIATE("ObjectiveManager::Reset()");
  470. WeatherMgrClass::Shutdown();
  471. WWLOG_INTERMEDIATE("WeatherMgrClass::Shutdown()");
  472. BackgroundMgrClass::Shutdown();
  473. WWLOG_INTERMEDIATE("BackgroundMgrClass::Shutdown()");
  474. REF_PTR_RELEASE (SoundEnvironment);
  475. WWLOG_INTERMEDIATE("REF_PTR_RELEASE (SoundEnvironment)");
  476. REF_PTR_RELEASE (BackgroundScene);
  477. WWLOG_INTERMEDIATE("REF_PTR_RELEASE (BackgroundScene)");
  478. WW3DAssetManager::Get_Instance()->Free_Assets(); // Free all assets
  479. WWLOG_INTERMEDIATE("WW3DAssetManager::Get_Instance()->Free_Assets()");
  480. WWLOG_INTERMEDIATE("Delete factories");
  481. //
  482. // Kill the background music and flush the cache
  483. //
  484. if (WWAudioClass::Get_Instance () != NULL) {
  485. WWAudioClass::Get_Instance ()->Set_Background_Music (NULL);
  486. WWAudioClass::Get_Instance ()->Flush_Cache ();
  487. }
  488. WWLOG_INTERMEDIATE("Flush audio cache");
  489. SystemInfoLog::Reset_State();
  490. WWLOG_INTERMEDIATE("SystemInfoLog::Reset_State()");
  491. if (MessageWindow != NULL) {
  492. MessageWindow->Clear();
  493. MessageWindow->Clear_Log();
  494. }
  495. //
  496. // Shutdown the animated-sound system
  497. //
  498. AnimatedSoundMgrClass::Shutdown();
  499. WWLOG_INTERMEDIATE("AnimatedSoundMgrClass::Shutdown");
  500. return ;
  501. }
  502. /*
  503. **
  504. */
  505. PhysicsSceneClass * CombatManager::Get_Scene( void )
  506. {
  507. return PhysicsSceneClass::Get_Instance();
  508. }
  509. /*
  510. ** Note: Generate_Control and Think are separated because network update needs
  511. ** to happen in-between them.
  512. */
  513. /*
  514. **
  515. */
  516. void CombatManager::Generate_Control( void )
  517. {
  518. WWPROFILE( "Generate Control" );
  519. // First, generate input control for all necessary game objects and
  520. // possibly send those control to the server
  521. GameObjManager::Generate_Control();
  522. }
  523. /*
  524. **
  525. */
  526. void CombatManager::Handle_Input()
  527. {
  528. if ( Input::Get_State( INPUT_FUNCTION_FIRST_PERSON_TOGGLE ) ) {
  529. Set_First_Person( !Is_First_Person() );
  530. if ( COMBAT_STAR ) {
  531. Vector3 pos;
  532. COMBAT_STAR->Get_Position( &pos );
  533. DIAG_LOG(( "SWPE", "%1.2f; %1.2f; %1.2f; %s ", pos.X, pos.Y, pos.Z, Is_First_Person() ? "First" : "Third" ));
  534. }
  535. }
  536. }
  537. /*
  538. **
  539. */
  540. void CombatManager::Think()
  541. {
  542. SyncTime += (int)((TimeManager::Get_Frame_Seconds() * 1000.0f) + 0.5f);
  543. WWPROFILE( "CombatManager Think" );
  544. IsGameplayPermitted=NetworkHandler->Is_Gameplay_Permitted();
  545. { WWPROFILE( "Input" );
  546. Handle_Input();
  547. }
  548. // GroupControllerManager::Update();
  549. //
  550. // Display debug boxes for the coordinate zones as necessary
  551. //
  552. if ( SoldierGameObj::Is_Ghost_Collision_Debug_Display_Enabled() ) {
  553. UnitCoordinationZoneMgr::Display_Debug_Boxes();
  554. }
  555. { WWPROFILE( "Bullets" );
  556. BulletManager::Update();
  557. }
  558. ObjectiveManager::Update( TimeManager::Get_Frame_Seconds() );
  559. // Now, Process all objects logically
  560. ConversationMgrClass::Think();
  561. { WWPROFILE( "Game Obj Think" );
  562. GameObjManager::Think();
  563. // Now, Process all objects physically
  564. }{ WWPROFILE( "Scene" );
  565. COMBAT_SCENE->Update( TimeManager::Get_Frame_Seconds(), 0 );
  566. }{ WWPROFILE( "Star" );
  567. Update_Star();
  568. // In normal mode, the camera must think before Post_Think, since the
  569. // camera update calls Set_Targeting on the star, which must feed Update_Animation
  570. }{ WWPROFILE( "Camera 1" );
  571. if ( !MainCamera->Is_Using_Host_Model() ) {
  572. MainCamera->Update();
  573. }
  574. // Now, Post Process all objects logically
  575. }{ WWPROFILE( "Post Think" );
  576. GameObjManager::Post_Think();
  577. }
  578. // In host_model mode, the camera must think after Post_Think, so the host model has
  579. // a chance to determine where the camera should be
  580. if ( MainCamera->Is_Using_Host_Model() ) {
  581. MainCamera->Update();
  582. }
  583. // The targeting comes from the update weapons in the post_think
  584. Update_Star_Targeting();
  585. Do_Skeleton_Slider_Demo();
  586. { WWPROFILE( "Message Window" );
  587. MessageWindow->On_Frame_Update();
  588. }
  589. SpawnManager::Update();
  590. { WWPROFILE( "Sound Environment" );
  591. if ( SoundEnvironment != NULL ) {
  592. SoundEnvironment->Update (COMBAT_SCENE, MainCamera);
  593. }
  594. }
  595. { WWPROFILE( "Background" );
  596. BackgroundMgrClass::Update (COMBAT_SCENE, MainCamera);
  597. }
  598. { WWPROFILE( "Weather" );
  599. WeatherMgrClass::Update (COMBAT_SCENE, MainCamera);
  600. }
  601. HUDClass::Think();
  602. WeaponViewClass::Think();
  603. ScreenFadeManager::Think();
  604. }
  605. /*
  606. **
  607. */
  608. void CombatManager::Render()
  609. {
  610. if ( COMBAT_STAR != NULL ) {
  611. MultiplayRenderingAllowed = true;
  612. }
  613. if ( MultiplayRenderingAllowed ) {
  614. SystemInfoLog::Record_Frame();
  615. {
  616. WWPROFILE( "Camera Shakes" );
  617. COMBAT_SCENE->Apply_Camera_Shakes (*MainCamera);
  618. }
  619. DazzleRenderObjClass::Install_Dazzle_Visibility_Handler(&_TheCombatDazzleHandler);
  620. {
  621. WWPROFILE( "Combat Render BG" );
  622. WW3D::Render (BackgroundScene, MainCamera);
  623. }
  624. {
  625. WWPROFILE( "Combat Render FG" );
  626. WW3D::Render(COMBAT_SCENE, MainCamera);
  627. }
  628. {
  629. WWPROFILE( "DazzleRenderer" );
  630. DazzleLayerClass * dlayer = COMBAT_DAZZLE_LAYER;
  631. if (dlayer != NULL) {
  632. dlayer->Render(COMBAT_CAMERA);
  633. }
  634. }
  635. DazzleRenderObjClass::Install_Dazzle_Visibility_Handler(NULL);
  636. HUDClass::Render();
  637. ScreenFadeManager::Render();
  638. }
  639. }
  640. /*
  641. **
  642. */
  643. enum {
  644. CHUNKID_THE_STAR = 916991712,
  645. CHUNKID_FIRST_LOAD,
  646. CHUNKID_NOT_FIRST_LOAD, // Delete this one, ( and change default to false )
  647. CHUNKID_VARIABLES,
  648. CHUNKID_CCAMERA,
  649. MICROCHUNKID_FIRST_LOAD = 1,
  650. MICROCHUNKID_DIFFICULTY_LEVEL = 2,
  651. MICROCHUNKID_SYNC_TIME = 3,
  652. MICROCHUNKID_START_SCRIPT,
  653. MICROCHUNKID_RESPAWN_SCRIPT,
  654. MICROCHUNKID_RELOAD_COUNT,
  655. MICROCHUNKID_CHEAT_HISTORY,
  656. MICROCHUNKID_FIRST_PERSON,
  657. };
  658. bool CombatManager::Save( ChunkSaveClass &csave )
  659. {
  660. csave.Begin_Chunk( CHUNKID_THE_STAR );
  661. TheStar.Save( csave );
  662. csave.End_Chunk();
  663. csave.Begin_Chunk( CHUNKID_VARIABLES );
  664. bool first_load = !Are_Observers_Active();
  665. WRITE_MICRO_CHUNK( csave, MICROCHUNKID_FIRST_LOAD, first_load );
  666. if ( !first_load ) {
  667. WRITE_MICRO_CHUNK( csave, MICROCHUNKID_DIFFICULTY_LEVEL, DifficultyLevel );
  668. WRITE_MICRO_CHUNK( csave, MICROCHUNKID_FIRST_PERSON, FirstPerson );
  669. }
  670. WRITE_MICRO_CHUNK( csave, MICROCHUNKID_SYNC_TIME, SyncTime );
  671. WRITE_MICRO_CHUNK_WWSTRING( csave, MICROCHUNKID_START_SCRIPT, StartScript );
  672. WRITE_MICRO_CHUNK_WWSTRING( csave, MICROCHUNKID_RESPAWN_SCRIPT, RespawnScript );
  673. WRITE_MICRO_CHUNK( csave, MICROCHUNKID_RELOAD_COUNT, ReloadCount );
  674. #ifndef PARAM_EDITING_ON
  675. int cheat_history = CheatMgrClass::Get_Instance()->Get_History();
  676. WRITE_MICRO_CHUNK( csave, MICROCHUNKID_CHEAT_HISTORY, cheat_history );
  677. #endif //PARAM_EDITING_ON
  678. csave.End_Chunk();
  679. if ( COMBAT_CAMERA != NULL ) {
  680. csave.Begin_Chunk( CHUNKID_CCAMERA );
  681. COMBAT_CAMERA->Save( csave );
  682. csave.End_Chunk();
  683. }
  684. return true;
  685. }
  686. bool CombatManager::Load( ChunkLoadClass &cload )
  687. {
  688. ReloadCount = 0; // Legacy
  689. IsFirstLoad = true; // Default
  690. int legacy_dificulty_level = DifficultyLevel;
  691. int cheat_history = 0;
  692. FirstPerson = FirstPersonDefault;
  693. while (cload.Open_Chunk()) {
  694. switch(cload.Cur_Chunk_ID()) {
  695. case CHUNKID_THE_STAR:
  696. TheStar.Load( cload );
  697. break;
  698. case CHUNKID_VARIABLES:
  699. while (cload.Open_Micro_Chunk()) {
  700. switch(cload.Cur_Micro_Chunk_ID()) {
  701. READ_MICRO_CHUNK( cload, MICROCHUNKID_FIRST_LOAD, IsFirstLoad );
  702. READ_MICRO_CHUNK( cload, MICROCHUNKID_DIFFICULTY_LEVEL, DifficultyLevel );
  703. READ_MICRO_CHUNK( cload, MICROCHUNKID_SYNC_TIME, SyncTime );
  704. READ_MICRO_CHUNK_WWSTRING( cload, MICROCHUNKID_START_SCRIPT, StartScript );
  705. READ_MICRO_CHUNK_WWSTRING( cload, MICROCHUNKID_RESPAWN_SCRIPT, RespawnScript );
  706. READ_MICRO_CHUNK( cload, MICROCHUNKID_RELOAD_COUNT, ReloadCount );
  707. READ_MICRO_CHUNK( cload, MICROCHUNKID_CHEAT_HISTORY, cheat_history );
  708. READ_MICRO_CHUNK( cload, MICROCHUNKID_FIRST_PERSON, FirstPerson );
  709. default:
  710. Debug_Say(( "Unrecognized CombatManager variable chunkID\n" ));
  711. break;
  712. }
  713. cload.Close_Micro_Chunk();
  714. }
  715. break;
  716. case CHUNKID_CCAMERA:
  717. if ( COMBAT_CAMERA != NULL ) {
  718. COMBAT_CAMERA->Load( cload );
  719. }
  720. break;
  721. default:
  722. Debug_Say(( "Unrecognized CombatManager chunkID\n" ));
  723. break;
  724. }
  725. cload.Close_Chunk();
  726. }
  727. if ( IsFirstLoad ) {
  728. DifficultyLevel = legacy_dificulty_level;
  729. ReloadCount = 0;
  730. CheatMgrClass::Get_Instance()->Reset_History();
  731. } else {
  732. ReloadCount++; // Count another load!
  733. CheatMgrClass::Get_Instance()->Set_History( cheat_history );
  734. CheatMgrClass::Get_Instance()->Update_History();
  735. }
  736. return true;
  737. }
  738. /*
  739. **
  740. */
  741. bool CombatManager::Can_Damage(ArmedGameObj * p_armed_damager, PhysicalGameObj * p_phys_victim)
  742. {
  743. if (NetworkHandler != NULL) {
  744. return NetworkHandler->Can_Damage(p_armed_damager, p_phys_victim);
  745. } else {
  746. return true;
  747. }
  748. }
  749. float CombatManager::Get_Damage_Factor(ArmedGameObj * p_armed_damager, PhysicalGameObj * p_phys_victim)
  750. {
  751. if (NetworkHandler != NULL) {
  752. return NetworkHandler->Get_Damage_Factor(p_armed_damager, p_phys_victim);
  753. } else {
  754. return 1.0f;
  755. }
  756. }
  757. void CombatManager::On_Soldier_Kill(SoldierGameObj * p_soldier, SoldierGameObj * p_victim)
  758. {
  759. WWASSERT(p_soldier != NULL);
  760. WWASSERT(p_victim != NULL);
  761. if (NetworkHandler != NULL) {
  762. NetworkHandler->On_Soldier_Kill(p_soldier, p_victim);
  763. }
  764. }
  765. void CombatManager::On_Soldier_Death(SoldierGameObj * p_soldier)
  766. {
  767. WWASSERT(p_soldier != NULL);
  768. if (NetworkHandler != NULL) {
  769. NetworkHandler->On_Soldier_Death(p_soldier);
  770. }
  771. }
  772. bool CombatManager::Is_Gameplay_Permitted(void)
  773. {
  774. if (NetworkHandler == NULL) {
  775. return true;
  776. } else {
  777. return IsGameplayPermitted;
  778. // return NetworkHandler->Is_Gameplay_Permitted();
  779. }
  780. }
  781. /*
  782. ** Misc Handler
  783. */
  784. void CombatManager::Mission_Complete( bool success )
  785. {
  786. if (MiscHandler != NULL) {
  787. MiscHandler->Mission_Complete( success );
  788. }
  789. }
  790. void CombatManager::Star_Killed( void )
  791. {
  792. if (MiscHandler != NULL) {
  793. MiscHandler->Star_Killed();
  794. }
  795. }
  796. /*
  797. **
  798. */
  799. void CombatManager::Set_Camera_Profile( const char * profile_name )
  800. {
  801. if ( profile_name == NULL ) {
  802. COMBAT_CAMERA->Use_Default_Profile();
  803. } else {
  804. COMBAT_CAMERA->Use_Profile( profile_name );
  805. }
  806. }
  807. /*
  808. **
  809. */
  810. void CombatManager::Set_The_Star( SoldierGameObj *target, bool is_star_determining_target )
  811. {
  812. if ( TheStar != target ) {
  813. HUDClass::Reset(); // Reset the HUD (clear damage and powerups)
  814. }
  815. TheStar = target;
  816. IsStarDeterminingTarget = is_star_determining_target;
  817. if ( target != NULL ) {
  818. COMBAT_CAMERA->Force_Heading( target->Get_Facing() );
  819. }
  820. HUDClass::Force_Weapon_Chart_Update();
  821. WeaponViewClass::Reset();
  822. if (IsLevelInitialized == false) {
  823. IsLevelInitialized = true;
  824. //
  825. // Turn music and sound effects back on...
  826. //
  827. WWAudioClass::Get_Instance ()->Enable_New_Sounds (true);
  828. }
  829. }
  830. /*
  831. **
  832. */
  833. void CombatManager::Update_Star( void )
  834. {
  835. SoldierGameObj * star = COMBAT_STAR;
  836. if ( star == NULL ) {
  837. return;
  838. }
  839. if ( star->Is_Destroyed() ) {
  840. Set_Combat_Mode( COMBAT_MODE_CORPSE );
  841. } else if ( star->Is_Dead() ) {
  842. Set_Combat_Mode( COMBAT_MODE_DIEING );
  843. } else if ( star->Get_Profile_Vehicle() != NULL ) {
  844. Set_Combat_Mode( COMBAT_MODE_IN_VEHICLE );
  845. } else if ( star->Is_Sniping() ) {
  846. Set_Combat_Mode( COMBAT_MODE_SNIPING );
  847. } else if ( star->Use_Ladder_View() ) {
  848. Set_Combat_Mode( COMBAT_MODE_ON_LADDER );
  849. } else if ( Is_First_Person() ) {
  850. Set_Combat_Mode( COMBAT_MODE_FIRST_PERSON );
  851. } else {
  852. Set_Combat_Mode( COMBAT_MODE_THIRD_PERSON );
  853. }
  854. Update_Combat_Mode();
  855. //
  856. // Update the map
  857. //
  858. Vector3 star_pos;
  859. star->Get_Position (&star_pos);
  860. MapMgrClass::Clear_Cloud_Cell (star_pos);
  861. return ;
  862. }
  863. void CombatManager::Update_Star_Targeting( void )
  864. {
  865. WWPROFILE( "Targeting" );
  866. SmartGameObj * star = NULL;
  867. if ( COMBAT_STAR != NULL ) {
  868. SoldierGameObj * soldier = COMBAT_STAR;
  869. WWASSERT(soldier != NULL);
  870. star = soldier;
  871. if ( soldier->Get_Vehicle() ) {
  872. star = soldier->Get_Vehicle();
  873. }
  874. // Now, if the star has a weapon, gather the information needing to be displayed
  875. // such as where the bullets will hit, what we are targeting, distance, etc.
  876. HUDInfo::Set_Weapon_Target_Object( NULL );
  877. WeaponClass * weapon = star->Get_Weapon();
  878. if ( weapon ) {
  879. WWPROFILE( "Display_Targeting" );
  880. weapon->Display_Targeting();
  881. }
  882. }
  883. }
  884. bool CombatManager::Is_In_Camera_Frustrum(Vector3 & position)
  885. {
  886. WWASSERT(COMBAT_CAMERA != NULL);
  887. Vector3 projected_mid_point;
  888. bool is_visible = (COMBAT_CAMERA->Project(projected_mid_point, position) == CameraClass::INSIDE_FRUSTUM);
  889. return is_visible;
  890. }
  891. void CombatManager::Do_Skeleton_Slider_Demo( void )
  892. {
  893. if (( EnableSkeletonSliderDemo == false ) ||
  894. ( COMBAT_CAMERA->Is_2D_Targeting() == false )) {
  895. return;
  896. }
  897. if ( COMBAT_STAR != NULL ) {
  898. Vector2 sliders = COMBAT_CAMERA->Get_Camera_Target_2D_Offset();
  899. // Slide is 0-1, height * widht should be -scale - scale
  900. sliders.X = (sliders.X - 0.5f) * 2;
  901. sliders.Y = (sliders.Y - 0.5f) * -2;
  902. float scale = 1;
  903. float height = sliders.Y * scale;
  904. float width = sliders.X * scale;
  905. // Debug_Say(( "Height %f, width %f\n", height, width ));
  906. COMBAT_STAR->Adjust_Skeleton( height, width );
  907. }
  908. }
  909. /*
  910. **
  911. */
  912. void Vehicle_Panic( VehicleGameObj * vehicle )
  913. {
  914. VehiclePhysClass * rbody = vehicle->Peek_Vehicle_Phys();
  915. if (rbody != NULL) {
  916. #if 1
  917. // Try to put the vehicle up-right in its current position
  918. Matrix3D tm = rbody->Get_Transform();
  919. Vector3 position;
  920. Vector3 forward;
  921. tm.Get_Translation(&position);
  922. tm.Get_X_Vector(&forward);
  923. if (forward.Z > 0.707f) {
  924. tm.Get_Z_Vector(&forward);
  925. }
  926. forward.Z = 0.0f;
  927. position.Z += 3.0f;
  928. Matrix3D new_tm;
  929. new_tm.Obj_Look_At(position,position+forward,0.0f);
  930. rbody->Set_Transform(new_tm);
  931. #endif
  932. }
  933. }
  934. /*
  935. ** Combat Mode Management
  936. */
  937. void CombatManager::Set_Combat_Mode( int mode )
  938. {
  939. // I don't know how to handle loading a saved game in cinematics, so postpone
  940. // this mode change until the camera is not host controlled?
  941. if ( COMBAT_CAMERA && COMBAT_CAMERA->Is_Using_Host_Model() ) {
  942. return;
  943. }
  944. if ( mode != CombatMode ) {
  945. //Debug_Say(( "Switching CombatMode to %d\n", mode ));
  946. // When changing to or from ladder, lerp
  947. if ( ( CombatMode == COMBAT_MODE_ON_LADDER ) || ( mode == COMBAT_MODE_ON_LADDER ) ) {
  948. COMBAT_CAMERA->Set_Lerp_Time( 0.5f );
  949. }
  950. CombatMode = mode;
  951. // Pause game in single player corpse mode
  952. // IsGamePaused = (CombatMode == COMBAT_MODE_CORPSE) && IS_SOLOPLAY;
  953. SoldierGameObj * star = COMBAT_STAR;
  954. switch ( CombatMode ) {
  955. case COMBAT_MODE_NONE:
  956. break;
  957. case COMBAT_MODE_FIRST_PERSON:
  958. COMBAT_CAMERA->Set_Is_Star_Sniping( false );
  959. COMBAT_CAMERA->Use_Profile( "First_Person" );
  960. COMBAT_CAMERA->Set_Profile_Distance( 0 );
  961. star->Peek_Model()->Set_Hidden( true );
  962. WeaponViewClass::Enable( true );
  963. break;
  964. case COMBAT_MODE_ON_LADDER:
  965. case COMBAT_MODE_THIRD_PERSON:
  966. star->Peek_Model()->Set_Hidden( false );
  967. COMBAT_CAMERA->Set_Is_Star_Sniping( false );
  968. COMBAT_CAMERA->Use_Default_Profile();
  969. WeaponViewClass::Enable( false );
  970. break;
  971. case COMBAT_MODE_SNIPING:
  972. COMBAT_CAMERA->Set_Is_Star_Sniping( true );
  973. star->Peek_Model()->Set_Hidden( true );
  974. COMBAT_CAMERA->Use_Profile( "Sniper" );
  975. COMBAT_CAMERA->Set_Profile_Height( star->Get_Weapon_Height() );
  976. COMBAT_CAMERA->Set_Profile_Distance( -star->Get_Weapon_Length() );
  977. COMBAT_CAMERA->Enable_2D_Targeting( false );
  978. WeaponViewClass::Enable( false );
  979. break;
  980. case COMBAT_MODE_IN_VEHICLE:
  981. {
  982. VehicleGameObj * vehicle = star->Get_Profile_Vehicle();
  983. WWASSERT( vehicle );
  984. COMBAT_CAMERA->Set_Is_Star_Sniping( false );
  985. if ( vehicle->Get_Profile() != NULL ) {
  986. COMBAT_CAMERA->Use_Profile( vehicle->Get_Profile() );
  987. } else {
  988. COMBAT_CAMERA->Use_Default_Profile();
  989. }
  990. WeaponViewClass::Enable( false );
  991. }
  992. break;
  993. case COMBAT_MODE_DIEING:
  994. star->Peek_Model()->Set_Hidden( false );
  995. COMBAT_CAMERA->Set_Is_Star_Sniping( false );
  996. COMBAT_CAMERA->Use_Profile( "Death" );
  997. COMBAT_CAMERA->Set_Lerp_Time( 0.5f );
  998. WeaponViewClass::Enable( false );
  999. break;
  1000. case COMBAT_MODE_CORPSE:
  1001. break;
  1002. case COMBAT_MODE_SNAP_SHOT:
  1003. break;
  1004. default:
  1005. Debug_Say(( "Bad CombatMode %d\n", CombatMode ));
  1006. CombatMode = COMBAT_MODE_NONE;
  1007. break;
  1008. }
  1009. }
  1010. }
  1011. void CombatManager::Update_Combat_Mode( void )
  1012. {
  1013. SoldierGameObj * star = COMBAT_STAR;
  1014. Vector3 pos;
  1015. star->Get_Position( &pos );
  1016. COMBAT_CAMERA->Set_Anchor_Position( pos );
  1017. //XXX
  1018. //COMBAT_CAMERA->Enable_2D_Targeting(true);
  1019. switch ( CombatMode ) {
  1020. case COMBAT_MODE_NONE:
  1021. break;
  1022. case COMBAT_MODE_FIRST_PERSON:
  1023. star->Peek_Model()->Set_Hidden( true ); // Putting it here, because vehicles are turning it back on
  1024. COMBAT_CAMERA->Set_Profile_Height( star->Get_Weapon_Height() ); // This is every frame for crouching
  1025. // COMBAT_CAMERA->Enable_2D_Targeting( Input::Get_State(INPUT_FUNCTION_CURSOR_TARGETING) );
  1026. COMBAT_CAMERA->Enable_2D_Targeting( false );
  1027. break;
  1028. case COMBAT_MODE_ON_LADDER:
  1029. case COMBAT_MODE_THIRD_PERSON:
  1030. COMBAT_CAMERA->Enable_2D_Targeting( Input::Get_State(INPUT_FUNCTION_CURSOR_TARGETING ) );
  1031. if ( star->Is_On_Ladder() ) {
  1032. COMBAT_CAMERA->Force_Heading( star->Get_Facing() );
  1033. }
  1034. break;
  1035. case COMBAT_MODE_SNIPING:
  1036. COMBAT_CAMERA->Set_Profile_Height( star->Get_Weapon_Height() ); // This is every frame for crouching
  1037. break;
  1038. case COMBAT_MODE_IN_VEHICLE:
  1039. {
  1040. VehicleGameObj * vehicle = star->Get_Profile_Vehicle();
  1041. WWASSERT( vehicle );
  1042. #ifdef WWDEBUG
  1043. if ( Input::Get_State( INPUT_FUNCTION_PANIC ) ) {
  1044. Vehicle_Panic( vehicle );
  1045. }
  1046. #endif
  1047. Vector3 pos;
  1048. vehicle->Get_Position( &pos );
  1049. COMBAT_CAMERA->Set_Anchor_Position( pos );
  1050. // bool target_2d = ( !vehicle->Use_2D_Aiming() ^ Input::Get_State(INPUT_FUNCTION_CURSOR_TARGETING) ^ VehicleGameObj::Is_Target_Steering() );
  1051. bool target_2d = (Input::Get_State(INPUT_FUNCTION_CURSOR_TARGETING) ^ VehicleGameObj::Is_Target_Steering() );
  1052. // This can be used to always for the V key down for vehicles
  1053. if ( VehicleGameObj::Get_Camera_Locked_To_Turret() ) {
  1054. target_2d = !target_2d;
  1055. }
  1056. if ( !vehicle->Use_2D_Aiming() ) {
  1057. target_2d = true;
  1058. }
  1059. if ( vehicle->Get_Gunner() == COMBAT_STAR ) {
  1060. target_2d = true;
  1061. }
  1062. if ( target_2d ) {
  1063. COMBAT_CAMERA->Enable_2D_Targeting( false );
  1064. } else {
  1065. COMBAT_CAMERA->Enable_2D_Targeting( true );
  1066. // Lateral velocity offset camera code
  1067. float desired_heading = vehicle->Get_Facing();;
  1068. VehiclePhysClass * vehiclephys = vehicle->Peek_Physical_Object()->As_VehiclePhysClass();
  1069. if (vehiclephys != NULL) {
  1070. Vector3 vel,localvel;
  1071. vehiclephys->Get_Velocity(&vel);
  1072. Matrix3D invtm;
  1073. vehiclephys->Get_Transform().Get_Orthogonal_Inverse(invtm);
  1074. Matrix3D::Rotate_Vector(invtm,vel,&localvel);
  1075. // float lateralvel = localvel.Y;
  1076. float heading_offset = WWMath::Atan2(localvel.Y,localvel.X);
  1077. heading_offset = WWMath::Clamp(heading_offset,DEG_TO_RADF(-45.0f),DEG_TO_RADF(45.0f));
  1078. float offset_scale = localvel.X / 5.0f;
  1079. offset_scale = WWMath::Clamp(offset_scale,0.0f,1.0f);
  1080. heading_offset *= offset_scale;
  1081. desired_heading += heading_offset;
  1082. }
  1083. COMBAT_CAMERA->Force_Heading( desired_heading );
  1084. COMBAT_CAMERA->Set_Tilt( 0 );
  1085. }
  1086. }
  1087. break;
  1088. case COMBAT_MODE_DIEING:
  1089. // Make the camera look towards the star killer
  1090. if ( StarKillerID != 0 ) {
  1091. PhysicalGameObj * killer = GameObjManager::Find_PhysicalGameObj( StarKillerID );
  1092. if ( killer ) {
  1093. Vector3 star_pos;
  1094. Vector3 killer_pos;
  1095. COMBAT_STAR->Get_Position( &star_pos );
  1096. killer->Get_Position( &killer_pos );
  1097. Vector3 dif = killer_pos - star_pos;
  1098. float heading = WWMath::Atan2(dif.Y,dif.X);
  1099. COMBAT_CAMERA->Force_Heading( heading );
  1100. }
  1101. }
  1102. break;
  1103. case COMBAT_MODE_CORPSE:
  1104. break;
  1105. case COMBAT_MODE_SNAP_SHOT:
  1106. break;
  1107. }
  1108. }
  1109. void CombatManager::Register_Star_Killer( ArmedGameObj * killer )
  1110. {
  1111. if ( killer != NULL ) {
  1112. StarKillerID = killer->Get_ID();
  1113. } else {
  1114. StarKillerID = 0;
  1115. }
  1116. }