samsite.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  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/samsite.cpp $*
  25. * *
  26. * $Author:: Tom_s $*
  27. * *
  28. * $Modtime:: 9/17/01 4:18p $*
  29. * *
  30. * $Revision:: 36 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. #include "samsite.h"
  36. #include "decophys.h"
  37. #include "combat.h"
  38. #include "animcontrol.h"
  39. #include "wwpacket.h"
  40. #include "debug.h"
  41. #include "gameobjmanager.h"
  42. #include "vehicle.h"
  43. #include "persistfactory.h"
  44. #include "combatchunkid.h"
  45. #include "simpledefinitionfactory.h"
  46. #include "wwhack.h"
  47. #include "wwprofile.h"
  48. /*
  49. ** SAMSiteGameObjDef
  50. */
  51. DECLARE_FORCE_LINK( SAMSite )
  52. SimplePersistFactoryClass<SAMSiteGameObjDef, CHUNKID_GAME_OBJECT_DEF_SAMSITE> _SAMSiteGameObjDefPersistFactory;
  53. DECLARE_DEFINITION_FACTORY(SAMSiteGameObjDef, CLASSID_GAME_OBJECT_DEF_SAMSITE, "SAMSite") _SAMSiteGameObjDefDefFactory;
  54. SAMSiteGameObjDef::SAMSiteGameObjDef( void )
  55. {
  56. MODEL_DEF_PARAM( SAMSiteGameObjDef, PhysDefID, "DecorationPhysDef" );
  57. }
  58. uint32 SAMSiteGameObjDef::Get_Class_ID (void) const
  59. {
  60. return CLASSID_GAME_OBJECT_DEF_SAMSITE;
  61. }
  62. PersistClass * SAMSiteGameObjDef::Create( void ) const
  63. {
  64. SAMSiteGameObj * obj = new SAMSiteGameObj;
  65. obj->Init( *this );
  66. return obj;
  67. }
  68. enum {
  69. CHUNKID_DEF_PARENT = 930991800,
  70. };
  71. bool SAMSiteGameObjDef::Save( ChunkSaveClass & csave )
  72. {
  73. csave.Begin_Chunk( CHUNKID_DEF_PARENT );
  74. SmartGameObjDef::Save( csave );
  75. csave.End_Chunk();
  76. return true;
  77. }
  78. bool SAMSiteGameObjDef::Load( ChunkLoadClass &cload )
  79. {
  80. while (cload.Open_Chunk()) {
  81. switch(cload.Cur_Chunk_ID()) {
  82. case CHUNKID_DEF_PARENT:
  83. SmartGameObjDef::Load( cload );
  84. break;
  85. default:
  86. Debug_Say(( "Unrecognized SimpleDef chunkID\n" ));
  87. break;
  88. }
  89. cload.Close_Chunk();
  90. }
  91. return true;
  92. }
  93. const PersistFactoryClass & SAMSiteGameObjDef::Get_Factory (void) const
  94. {
  95. return _SAMSiteGameObjDefPersistFactory;
  96. }
  97. /*
  98. **
  99. */
  100. SimplePersistFactoryClass<SAMSiteGameObj, CHUNKID_GAME_OBJECT_SAMSITE> _SAMSiteGameObjPersistFactory;
  101. const PersistFactoryClass & SAMSiteGameObj::Get_Factory (void) const
  102. {
  103. return _SAMSiteGameObjPersistFactory;
  104. }
  105. typedef enum {
  106. SAMSITE_STATE_DOWN,
  107. SAMSITE_STATE_UP,
  108. SAMSITE_STATE_RISING,
  109. SAMSITE_STATE_DROPPING,
  110. };
  111. /*
  112. ** SAMSiteGameObject
  113. */
  114. SAMSiteGameObj::SAMSiteGameObj() :
  115. TurretBone( -1 ),
  116. BarrelBone( -1 ),
  117. State( SAMSITE_STATE_DOWN )
  118. {
  119. }
  120. SAMSiteGameObj::~SAMSiteGameObj()
  121. {
  122. if ( Peek_Model() ) {
  123. if ( TurretBone != -1 ) {
  124. if ( Peek_Model()->Is_Bone_Captured( TurretBone ) ) {
  125. Peek_Model()->Release_Bone( TurretBone );
  126. TurretBone = -1;
  127. }
  128. }
  129. if ( BarrelBone != -1 ) {
  130. if ( Peek_Model()->Is_Bone_Captured( BarrelBone ) ) {
  131. Peek_Model()->Release_Bone( BarrelBone );
  132. BarrelBone = -1;
  133. }
  134. }
  135. }
  136. }
  137. /*
  138. **
  139. */
  140. void SAMSiteGameObj::Init( void )
  141. {
  142. Init( Get_Definition() );
  143. }
  144. void SAMSiteGameObj::Init( const SAMSiteGameObjDef & definition )
  145. {
  146. SmartGameObj::Init( definition );
  147. }
  148. const SAMSiteGameObjDef & SAMSiteGameObj::Get_Definition( void ) const
  149. {
  150. return (const SAMSiteGameObjDef &)BaseGameObj::Get_Definition();
  151. }
  152. /*
  153. ** SAMSiteGameObj Save and Load
  154. */
  155. enum {
  156. CHUNKID_PARENT = 922991750,
  157. CHUNKID_VARIABLES,
  158. XXXCHUNKID_SAM_TIMER,
  159. XXXCHUNKID_ANIM_CONTROL,
  160. XXXMICROCHUNKID_PHYSOBJ = 1,
  161. MICROCHUNKID_STATE,
  162. MICROCHUNKID_TIMER,
  163. };
  164. bool SAMSiteGameObj::Save( ChunkSaveClass & csave )
  165. {
  166. csave.Begin_Chunk( CHUNKID_PARENT );
  167. SmartGameObj::Save( csave );
  168. csave.End_Chunk();
  169. csave.Begin_Chunk( CHUNKID_VARIABLES );
  170. WRITE_MICRO_CHUNK( csave, MICROCHUNKID_STATE, State );
  171. WRITE_MICRO_CHUNK( csave, MICROCHUNKID_TIMER, Timer );
  172. csave.End_Chunk();
  173. return true;
  174. }
  175. bool SAMSiteGameObj::Load( ChunkLoadClass &cload )
  176. {
  177. while (cload.Open_Chunk()) {
  178. switch(cload.Cur_Chunk_ID()) {
  179. case CHUNKID_PARENT:
  180. SmartGameObj::Load( cload );
  181. break;
  182. case CHUNKID_VARIABLES:
  183. {
  184. while (cload.Open_Micro_Chunk()) {
  185. switch(cload.Cur_Micro_Chunk_ID()) {
  186. READ_MICRO_CHUNK( cload, MICROCHUNKID_STATE, State );
  187. READ_MICRO_CHUNK( cload, MICROCHUNKID_TIMER, Timer );
  188. default:
  189. Debug_Say(( "Unrecognized SimpleGameObj Variable chunkID\n" ));
  190. break;
  191. }
  192. cload.Close_Micro_Chunk();
  193. }
  194. break;
  195. }
  196. default:
  197. Debug_Say(( "Unrecognized SimpleGameObj chunkID\n" ));
  198. break;
  199. }
  200. cload.Close_Chunk();
  201. }
  202. return true;
  203. }
  204. /*
  205. **
  206. */
  207. void SAMSiteGameObj::Import_Frequent( BitStreamClass & packet )
  208. {
  209. WWASSERT(CombatManager::I_Am_Only_Client());
  210. SmartGameObj::Import_Frequent( packet );
  211. WWASSERT(packet.Is_Flushed());
  212. }
  213. void SAMSiteGameObj::Export_Frequent( BitStreamClass & packet )
  214. {
  215. SmartGameObj::Export_Frequent( packet );
  216. }
  217. void SAMSiteGameObj::Update_Turret( float weapon_turn, float weapon_tilt )
  218. {
  219. if ( TurretBone == -1 ) {
  220. TurretBone = Peek_Model()->Get_Bone_Index( "turret" );
  221. if ( TurretBone != -1 ) {
  222. Peek_Model()->Capture_Bone( TurretBone );
  223. if ( !Peek_Model()->Is_Bone_Captured( TurretBone ) ) {
  224. Debug_Say(( "SAMSiteGameObj : Turret Bone not captured\n" ));
  225. TurretBone = -1;
  226. }
  227. } else {
  228. Debug_Say(( "SAMSiteGameObj : Turret Bone not found\n" ));
  229. }
  230. }
  231. if ( BarrelBone == -1 ) {
  232. BarrelBone = Peek_Model()->Get_Bone_Index( "barrel" );
  233. if ( BarrelBone != -1 ) {
  234. Peek_Model()->Capture_Bone( BarrelBone );
  235. if ( !Peek_Model()->Is_Bone_Captured( BarrelBone ) ) {
  236. BarrelBone = -1;
  237. Debug_Say(( "Barrel Bone not captured\n" ));
  238. }
  239. } else {
  240. Debug_Say(( "Barrel Bone not found\n" ));
  241. }
  242. }
  243. if ( TurretBone != -1 ) {
  244. Matrix3D facing(1);
  245. facing.Rotate_Z( weapon_turn );
  246. if ( BarrelBone == -1 ) { // if no barrel bone
  247. facing.Rotate_Y( -weapon_tilt ); // neg rotate y tilts up
  248. }
  249. Peek_Model()->Control_Bone( TurretBone, facing );
  250. }
  251. if ( BarrelBone != -1 ) {
  252. Matrix3D facing(1);
  253. facing.Rotate_Y( -weapon_tilt ); // neg rotate y tilts up
  254. Peek_Model()->Control_Bone( BarrelBone, facing );
  255. }
  256. }
  257. bool SAMSiteGameObj::Set_Targeting( const Vector3 & target_pos, bool do_tilt )
  258. {
  259. // Should add slow turning
  260. SmartGameObj::Set_Targeting( target_pos );
  261. Vector3 muzzle_pos = Peek_Model()->Get_Bone_Transform( "muzzle" ).Get_Translation();
  262. Matrix3D tm;
  263. tm.Obj_Look_At( muzzle_pos, target_pos, 0 );
  264. float weapon_tilt = -tm.Get_Y_Rotation();
  265. tm.Rotate_Y( weapon_tilt );
  266. float weapon_turn = tm.Get_Z_Rotation();
  267. if ( do_tilt == false ) {
  268. weapon_tilt = 0;
  269. }
  270. Update_Turret( weapon_turn, weapon_tilt );
  271. return true;
  272. }
  273. void SAMSiteGameObj::Generate_Control( void )
  274. {
  275. if ( State == SAMSITE_STATE_UP ) {
  276. SmartGameObj::Generate_Control();
  277. }
  278. }
  279. static char * _profile_name = "SAMSite Think";
  280. void SAMSiteGameObj::Think( void )
  281. {
  282. SmartGameObj *target = NULL;
  283. { WWPROFILE( _profile_name );
  284. // Find Nearest Emeny
  285. Vector3 my_pos;
  286. Get_Position( &my_pos );
  287. SLNode<SmartGameObj> *node;
  288. for ( node = GameObjManager::Get_Smart_Game_Obj_List()->Head(); node; node = node->Next()) {
  289. VehicleGameObj *obj = node->Data()->As_VehicleGameObj();
  290. if ( !obj || !obj->Is_Aircraft() ) continue;
  291. Vector3 vehicle_pos;
  292. obj->Get_Position( &vehicle_pos );
  293. vehicle_pos -= my_pos;
  294. target = obj;
  295. // Debug_Say(( "Vehicle is %f away\n", distance ));
  296. }
  297. if ( target ) {
  298. ActionParamsStruct parameters;
  299. parameters.Priority = 100;
  300. parameters.AttackObject = target;
  301. parameters.AttackRange = 40;
  302. parameters.MoveLocation = my_pos;
  303. parameters.MoveArrivedDistance = 10000;
  304. Get_Action()->Attack( parameters );
  305. } else {
  306. Get_Action()->Reset( 100 );
  307. }
  308. }
  309. SmartGameObj::Think();
  310. { WWPROFILE( _profile_name );
  311. if ( State == SAMSITE_STATE_DOWN ) {
  312. if ( target ) {
  313. Set_Animation( "B_samsiteL1.M_samrise" );
  314. Get_Anim_Control()->Set_Mode( ANIM_MODE_ONCE, 0 );
  315. State = SAMSITE_STATE_RISING;
  316. }
  317. } else if ( State == SAMSITE_STATE_UP ) {
  318. Timer -= TimeManager::Get_Frame_Seconds();
  319. if ( Timer <= 0 ) {
  320. Set_Animation( "B_samsitel1.M_samdrop" );
  321. Get_Anim_Control()->Set_Mode( ANIM_MODE_ONCE, 0 );
  322. State = SAMSITE_STATE_DROPPING;
  323. }
  324. } else {
  325. // If rising of dropping, check for completion, then set timer and state
  326. if( Get_Anim_Control()->Is_Complete() ) {
  327. State = ( State == SAMSITE_STATE_RISING ) ? SAMSITE_STATE_UP : SAMSITE_STATE_DOWN;
  328. Timer = 5;
  329. }
  330. }
  331. }
  332. }