humanstate.cpp 46 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511
  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/humanstate.cpp $*
  25. * *
  26. * $Author:: Patrick $*
  27. * *
  28. * $Modtime:: 2/26/02 11:47a $*
  29. * *
  30. * $Revision:: 169 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. /*
  36. ** Includes
  37. */
  38. #include "humanstate.h"
  39. #include "debug.h"
  40. #include "animcontrol.h"
  41. #include "humanphys.h"
  42. #include "weapons.h"
  43. #include "assets.h"
  44. #include "combat.h"
  45. #include "combat.h"
  46. #include "physcoltest.h"
  47. #include "pscene.h"
  48. #include <stdio.h>
  49. #include "timemgr.h"
  50. #include "definitionclassids.h"
  51. #include "pathfind.h"
  52. #include "encoderlist.h"
  53. #include "bitpackids.h"
  54. #include "humanrecoil.h"
  55. #include "globalsettings.h"
  56. #include "combatchunkid.h"
  57. #include "wwprofile.h"
  58. #include "surfaceeffects.h"
  59. #include "crandom.h"
  60. #include "gametype.h"
  61. #include "soldier.h"
  62. #include "damage.h"
  63. #include "transitioneffect.h"
  64. #include "combatmaterialeffectmanager.h"
  65. /*
  66. ** Static instance of HumanRecoilClass for recoil calculations
  67. */
  68. static HumanRecoilClass _TheRecoiler;
  69. /******************************************************************************************
  70. **
  71. ** HumanStateClass Implementation
  72. **
  73. ******************************************************************************************/
  74. HumanStateClass::HumanStateClass( void ) :
  75. State( UPRIGHT ),
  76. StateFlags( 0 ),
  77. StateTimer( 0 ),
  78. SubState( 0 ),
  79. StateLocked( false ),
  80. AnimControl( NULL ),
  81. WeaponHoldStyle(WEAPON_HOLD_STYLE_EMPTY_HANDS),
  82. HumanPhys( NULL ),
  83. TurnVelocity( 0 ),
  84. AimingTilt( 0 ),
  85. AimingTurn( 0 ),
  86. RecoilTimer( 0.0f ),
  87. RecoilScale( 1.0f ),
  88. LoiterDelay( 0 ),
  89. LoitersAllowed( true ),
  90. LegRotation( 0 ),
  91. WeaponHoldTimer( 0 ),
  92. NoAnimBlend( false ),
  93. HumanAnimOverride( NULL ),
  94. HumanLoiterCollection( NULL ),
  95. WeaponFired( false )
  96. {
  97. Reset_Loiter_Delay();
  98. }
  99. HumanStateClass::~HumanStateClass( void )
  100. {
  101. if ( HumanPhys != NULL ) {
  102. HumanPhys->Release_Ref();
  103. HumanPhys = NULL;
  104. }
  105. }
  106. void HumanStateClass::Init( HumanPhysClass * human_phys )
  107. {
  108. WWASSERT( HumanPhys == NULL );
  109. WWASSERT( human_phys != NULL );
  110. HumanPhys = human_phys;
  111. HumanPhys->Add_Ref();
  112. }
  113. void HumanStateClass::Reset( void )
  114. {
  115. REF_PTR_RELEASE( HumanPhys );
  116. // Clear the sniping flag
  117. if ( Get_State_Flag( SNIPING_FLAG ) ) {
  118. Toggle_State_Flag( SNIPING_FLAG );
  119. }
  120. }
  121. void HumanStateClass::Set_Anim_Control( HumanAnimControlClass * anim_control )
  122. {
  123. WWASSERT( AnimControl == NULL || AnimControl == anim_control );
  124. WWASSERT( anim_control != NULL );
  125. AnimControl = anim_control;
  126. AnimControl->Set_Model( HumanPhys->Peek_Model() );
  127. }
  128. void HumanStateClass::Set_Human_Anim_Override( const char * name )
  129. {
  130. HumanAnimOverride = (HumanAnimOverrideDef *)DefinitionMgrClass::Find_Typed_Definition( name,
  131. CLASSID_GLOBAL_SETTINGS_DEF_HUMAN_ANIM_OVERRIDE );
  132. }
  133. void HumanStateClass::Set_Human_Anim_Override( int def_id )
  134. {
  135. HumanAnimOverride = (HumanAnimOverrideDef *)DefinitionMgrClass::Find_Definition( def_id );
  136. }
  137. void HumanStateClass::Set_Human_Loiter_Collection( int def_id )
  138. {
  139. HumanLoiterCollection = (HumanLoiterGlobalSettingsDef *)DefinitionMgrClass::Find_Definition( def_id );
  140. }
  141. /*
  142. ** CommandoHumanState Save and Load
  143. */
  144. enum {
  145. CHUNKID_VARIABLES = 915991207,
  146. XXX_CHUNKID_ANIM_CONTROL,
  147. MICROCHUNKID_STATE = 1,
  148. MICROCHUNKID_SUB_STATE,
  149. MICROCHUNKID_STATE_LOCKED,
  150. MICROCHUNKID_WEAPON_HOLD_STYLE,
  151. XXXMICROCHUNKID_WEAPON_STATE,
  152. MICROCHUNKID_AIMING_TILT,
  153. MICROCHUNKID_AIMING_TURN,
  154. MICROCHUNKID_TURN_VELOCITY,
  155. MICROCHUNKID_PHYSOBJ,
  156. MICROCHUNKID_LOITER_DELAY,
  157. MICROCHUNKID_STATE_FLAGS,
  158. MICROCHUNKID_JUMP_TM,
  159. MICROCHUNKID_STATE_TIMER,
  160. MICROCHUNKID_LOITERS_ALLOWED,
  161. MICROCHUNKID_WEAPON_HOLD_TIMER,
  162. MICROCHUNKID_HUMAN_ANIM_OVERRIDE_DEF_ID,
  163. MICROCHUNKID_HUMAN_LOITER_COLLECTION_DEF_ID,
  164. };
  165. bool HumanStateClass::Save( ChunkSaveClass & csave )
  166. {
  167. csave.Begin_Chunk( CHUNKID_VARIABLES );
  168. WRITE_MICRO_CHUNK( csave, MICROCHUNKID_STATE, State );
  169. WRITE_MICRO_CHUNK( csave, MICROCHUNKID_STATE_FLAGS, StateFlags );
  170. WRITE_MICRO_CHUNK( csave, MICROCHUNKID_SUB_STATE, SubState );
  171. WRITE_MICRO_CHUNK( csave, MICROCHUNKID_STATE_LOCKED, StateLocked );
  172. WRITE_MICRO_CHUNK( csave, MICROCHUNKID_WEAPON_HOLD_STYLE, WeaponHoldStyle );
  173. WRITE_MICRO_CHUNK( csave, MICROCHUNKID_AIMING_TILT, AimingTilt );
  174. WRITE_MICRO_CHUNK( csave, MICROCHUNKID_AIMING_TURN, AimingTurn );
  175. WRITE_MICRO_CHUNK( csave, MICROCHUNKID_TURN_VELOCITY, TurnVelocity );
  176. WRITE_MICRO_CHUNK( csave, MICROCHUNKID_PHYSOBJ, HumanPhys );
  177. WRITE_MICRO_CHUNK( csave, MICROCHUNKID_LOITER_DELAY, LoiterDelay );
  178. WRITE_MICRO_CHUNK( csave, MICROCHUNKID_LOITERS_ALLOWED, LoitersAllowed );
  179. WRITE_MICRO_CHUNK( csave, MICROCHUNKID_JUMP_TM, JumpTM );
  180. WRITE_MICRO_CHUNK( csave, MICROCHUNKID_STATE_TIMER, StateTimer );
  181. WRITE_MICRO_CHUNK( csave, MICROCHUNKID_WEAPON_HOLD_TIMER, WeaponHoldTimer );
  182. if ( HumanAnimOverride != NULL ) {
  183. int id = HumanAnimOverride->Get_ID();
  184. WRITE_MICRO_CHUNK( csave, MICROCHUNKID_HUMAN_ANIM_OVERRIDE_DEF_ID, id );
  185. }
  186. if ( HumanLoiterCollection != NULL ) {
  187. int id = HumanLoiterCollection->Get_ID();
  188. WRITE_MICRO_CHUNK( csave, MICROCHUNKID_HUMAN_LOITER_COLLECTION_DEF_ID, id );
  189. }
  190. csave.End_Chunk();
  191. // Don't need to save AnimControl, it gets set externally
  192. // We don't save recoil states
  193. return true;
  194. }
  195. bool HumanStateClass::Load( ChunkLoadClass &cload )
  196. {
  197. int human_anim_override_def_id = 0;
  198. int human_loiter_collection_def_id = 0;
  199. WWASSERT( HumanPhys == NULL );
  200. while (cload.Open_Chunk()) {
  201. switch(cload.Cur_Chunk_ID()) {
  202. case CHUNKID_VARIABLES:
  203. WWASSERT( HumanPhys == NULL );
  204. while (cload.Open_Micro_Chunk()) {
  205. WWASSERT(SubState >= 0 && SubState <= HIGHEST_HUMAN_SUB_STATE);
  206. switch(cload.Cur_Micro_Chunk_ID()) {
  207. READ_MICRO_CHUNK( cload, MICROCHUNKID_STATE, State );
  208. READ_MICRO_CHUNK( cload, MICROCHUNKID_STATE_FLAGS, StateFlags );
  209. READ_MICRO_CHUNK( cload, MICROCHUNKID_SUB_STATE, SubState );
  210. READ_MICRO_CHUNK( cload, MICROCHUNKID_STATE_LOCKED, StateLocked );
  211. READ_MICRO_CHUNK( cload, MICROCHUNKID_WEAPON_HOLD_STYLE, WeaponHoldStyle );
  212. READ_MICRO_CHUNK( cload, MICROCHUNKID_AIMING_TILT, AimingTilt );
  213. READ_MICRO_CHUNK( cload, MICROCHUNKID_AIMING_TURN, AimingTurn );
  214. READ_MICRO_CHUNK( cload, MICROCHUNKID_TURN_VELOCITY, TurnVelocity );
  215. READ_MICRO_CHUNK( cload, MICROCHUNKID_PHYSOBJ, HumanPhys );
  216. READ_MICRO_CHUNK( cload, MICROCHUNKID_LOITER_DELAY, LoiterDelay );
  217. READ_MICRO_CHUNK( cload, MICROCHUNKID_LOITERS_ALLOWED, LoitersAllowed );
  218. READ_MICRO_CHUNK( cload, MICROCHUNKID_JUMP_TM, JumpTM );
  219. READ_MICRO_CHUNK( cload, MICROCHUNKID_STATE_TIMER, StateTimer );
  220. READ_MICRO_CHUNK( cload, MICROCHUNKID_WEAPON_HOLD_TIMER, WeaponHoldTimer );
  221. READ_MICRO_CHUNK( cload, MICROCHUNKID_HUMAN_ANIM_OVERRIDE_DEF_ID, human_anim_override_def_id );
  222. READ_MICRO_CHUNK( cload, MICROCHUNKID_HUMAN_LOITER_COLLECTION_DEF_ID, human_loiter_collection_def_id );
  223. default:
  224. Debug_Say(( "Unrecognized Human Variable chunkID\n" ));
  225. break;
  226. }
  227. cload.Close_Micro_Chunk();
  228. }
  229. WWASSERT( HumanPhys != NULL );
  230. if ( HumanPhys != NULL ) {
  231. REQUEST_REF_COUNTED_POINTER_REMAP( (RefCountClass **)&HumanPhys );
  232. }
  233. break;
  234. default:
  235. Debug_Say(( "Unrecognized Human chunkID\n" ));
  236. break;
  237. }
  238. cload.Close_Chunk();
  239. }
  240. if ( human_anim_override_def_id != 0 ) {
  241. Set_Human_Anim_Override( human_anim_override_def_id );
  242. }
  243. if ( human_loiter_collection_def_id != 0 ) {
  244. Set_Human_Loiter_Collection( human_loiter_collection_def_id );
  245. }
  246. return true;
  247. }
  248. /*
  249. **
  250. */
  251. void HumanStateClass::Update_Weapon( WeaponClass * weapon, bool new_weapon )
  252. {
  253. WWPROFILE( "Human Weapon" );
  254. Update_Recoil(weapon);
  255. int new_hold_style = WeaponHoldStyle;
  256. WeaponFired = false;
  257. if ( weapon ) {
  258. if ( weapon->Is_Reloading() ) {
  259. Raise_Weapon();
  260. }
  261. weapon->Set_Safety( WeaponHoldStyle > WEAPON_HOLD_STYLE_EMPTY_HANDS );
  262. // Only humans can cansider weapons firing in state
  263. if ( weapon->Get_Owner() &&
  264. weapon->Get_Owner()->As_SoldierGameObj() &&
  265. weapon->Get_Owner()->As_SoldierGameObj()->Is_Human_Controlled() ) {
  266. WeaponFired = weapon->Is_Firing();
  267. }
  268. if ( weapon->Is_Triggered() || new_weapon || Get_State_Flag( CROUCHED_FLAG ) ) {
  269. if ( weapon->Is_Safety_Set() ) { // Don't blend anim when un-safetying
  270. NoAnimBlend = true;
  271. }
  272. Raise_Weapon(); // Reset the drop timer
  273. new_hold_style = weapon->Get_Style(); // Take the new style
  274. }
  275. if ( WeaponHoldTimer > 0 ) {
  276. if ( WeaponHoldStyle > WEAPON_HOLD_STYLE_EMPTY_HANDS ) {
  277. new_hold_style = weapon->Get_Style(); // Take the new style
  278. }
  279. }
  280. } else {
  281. new_hold_style = WEAPON_HOLD_STYLE_EMPTY_HANDS;
  282. }
  283. if ( new_hold_style == WeaponHoldStyle ) {
  284. return;
  285. }
  286. WeaponHoldStyle = new_hold_style;
  287. if ( !StateLocked ) {
  288. Update_Animation();
  289. }
  290. }
  291. void HumanStateClass::Update_Aiming( float tilt, float turn )
  292. {
  293. if ( (AimingTilt == tilt) && (AimingTurn == turn) ) {
  294. return;
  295. }
  296. AimingTilt = tilt;
  297. AimingTurn = turn;
  298. if ( !StateLocked ) {
  299. Update_Animation();
  300. }
  301. }
  302. void HumanStateClass::Update_Recoil(WeaponClass * weapon)
  303. {
  304. // Programatic Recoil System. This code needs to run once per frame.
  305. if ((weapon != NULL) && (weapon->Is_Firing())) {
  306. // Set our recoil timer and capture all of the necessary bones
  307. // I'm copying all necessary data out of the weapon in case the weapon goes
  308. // away before our recoil is finished.
  309. RecoilTimer = weapon->Get_Recoil_Time();
  310. RecoilScale = weapon->Get_Recoil_Scale();
  311. if (RecoilTimer > 0.0f) {
  312. RecoilScale *= 1.0f / RecoilTimer;
  313. _TheRecoiler.Capture_Bones(HumanPhys->Peek_Model());
  314. }
  315. }
  316. if (RecoilTimer > 0.0f) {
  317. // Apply the recoil effect.
  318. Matrix3D recoil_tm(1);
  319. recoil_tm.Rotate_Z( HumanPhys->Get_Facing() );
  320. recoil_tm.Rotate_Y( -AimingTilt );
  321. float recoil_scale = RecoilScale * RecoilTimer;
  322. _TheRecoiler.Apply_Recoil( recoil_tm,HumanPhys->Peek_Model(),recoil_scale);
  323. // Decrement the recoil timer and release the bones if it expires
  324. RecoilTimer -= TimeManager::Get_Frame_Seconds();
  325. if (RecoilTimer <= 0.0f) {
  326. RecoilTimer = 0.0f;
  327. _TheRecoiler.Release_Bones(HumanPhys->Peek_Model());
  328. }
  329. }
  330. }
  331. void HumanStateClass::Set_State( HumanStateType state, int sub_state )
  332. {
  333. // Special case for death
  334. if (( State == DEATH ) || ( State == DESTROY )) {
  335. if ( state != DESTROY ) {
  336. return;
  337. }
  338. }
  339. if ( ( State != DEATH ) && ( state == DEATH ) ) {
  340. StateLocked = false;
  341. }
  342. if ( StateLocked ) {
  343. if ( state != DEATH ) {
  344. // Temp Test
  345. // Debug_Say(( "State is Locked. Can't change from %d to %d\n", State, state ));
  346. // return;
  347. }
  348. #pragma MESSAGE( "StateLocked Hack" )
  349. if ( !IS_SOLOPLAY ) { // E3 HACK
  350. StateLocked = false;
  351. }
  352. }
  353. if ( State == state && SubState == sub_state ) {
  354. if (CombatManager::I_Am_Server()) {
  355. Debug_Say(( "Already in this state\n" ));
  356. }
  357. return;
  358. }
  359. // Debug_Say(( "%p Set State %d, %x from %d\n", this, state, sub_state, State ));
  360. State = state;
  361. SubState = sub_state;
  362. StateTimer = 0;
  363. if (( State == LADDER ) || ( State == IN_VEHICLE ) ||
  364. ( State == TRANSITION ) || ( State == TRANSITION_COMPLETE ) ||
  365. ( State == DEBUG_FLY ) ) {
  366. HumanPhys->Enable_User_Control( true );
  367. } else {
  368. HumanPhys->Enable_User_Control( false );
  369. }
  370. // Turn off shadows in vehicles
  371. #pragma message ("(gth) shadow review hacking")
  372. #if 0
  373. if ( State == IN_VEHICLE ) {
  374. HumanPhys->Enable_Shadow_Generation( false );
  375. } else {
  376. HumanPhys->Enable_Shadow_Generation( true );
  377. }
  378. #endif
  379. if ( ( State == IN_VEHICLE ) || ( State == TRANSITION ) || ( State == TRANSITION_COMPLETE ) ) {
  380. HumanPhys->Set_Collision_Group( BULLET_ONLY_COLLISION_GROUP );
  381. HumanPhys->Set_Immovable( true );
  382. } else if ( ( State == DESTROY ) || ( State == DEATH ) ) {
  383. HumanPhys->Set_Collision_Group( TERRAIN_ONLY_COLLISION_GROUP );
  384. HumanPhys->Set_Immovable( true );
  385. } else {
  386. HumanPhys->Set_Collision_Group( SOLDIER_COLLISION_GROUP );
  387. HumanPhys->Set_Immovable( false );
  388. }
  389. Update_Animation();
  390. }
  391. bool HumanStateClass::Is_State_Interruptable( void )
  392. {
  393. return (State == UPRIGHT) || (State == WOUNDED) || (State == LAND) || (State == LOITER) || (State == ANIMATION);
  394. }
  395. #define ADD_CASE(exp) case exp: return #exp; break;
  396. const char * HumanStateClass::Get_State_Name( void )
  397. {
  398. switch (State) {
  399. ADD_CASE(UPRIGHT);
  400. ADD_CASE(LAND);
  401. ADD_CASE(ANIMATION);
  402. ADD_CASE(WOUNDED);
  403. ADD_CASE(LOITER);
  404. ADD_CASE(AIRBORNE);
  405. ADD_CASE(DIVE);
  406. ADD_CASE(DEATH);
  407. ADD_CASE(LADDER);
  408. ADD_CASE(IN_VEHICLE);
  409. ADD_CASE(TRANSITION);
  410. ADD_CASE(TRANSITION_COMPLETE);
  411. ADD_CASE(DESTROY);
  412. ADD_CASE(DEBUG_FLY);
  413. ADD_CASE(ON_FIRE);
  414. ADD_CASE(ON_CHEM);
  415. ADD_CASE(ON_ELECTRIC);
  416. ADD_CASE(ON_CNC_FIRE);
  417. ADD_CASE(ON_CNC_CHEM);
  418. ADD_CASE(LOCKED_ANIMATION);
  419. default:
  420. WWASSERT(0);
  421. return ""; // to avoid compiler warning
  422. }
  423. }
  424. void HumanStateClass::Set_Sub_State( int sub_state )
  425. {
  426. if ( Is_Sub_State_Adjustable() ) {
  427. if ( SubState != sub_state ) {
  428. WWASSERT(sub_state >= 0 && sub_state <= HIGHEST_HUMAN_SUB_STATE);
  429. SubState = sub_state;
  430. Update_Animation();
  431. }
  432. } else {
  433. Debug_Say(( "Can't adjust state %s", Get_State_Name() ));
  434. }
  435. }
  436. bool HumanStateClass::Is_Sub_State_Adjustable( void )
  437. {
  438. return (State == UPRIGHT) || (State == LADDER);
  439. }
  440. void HumanStateClass::Start_Transition_Animation( const char * anim_name, bool blend )
  441. {
  442. if ( StateLocked ) {
  443. Debug_Say(( "State is Locked. Can't Start Transition Anim %s\n", anim_name ));
  444. return;
  445. }
  446. //Debug_Say(("Start_Transition_Animation %s\n", anim_name));
  447. if (( Get_State() == DEATH ) || ( Get_State() == DESTROY ) ) {
  448. return;
  449. }
  450. Set_State( TRANSITION );
  451. float blend_time = blend ? 0.2 : 0;
  452. AnimControl->Set_Animation( anim_name, blend_time );
  453. AnimControl->Set_Mode( ANIM_MODE_ONCE );
  454. AnimControl->Update( 0 ); // update
  455. StateLocked = true;
  456. }
  457. void HumanStateClass::Start_Scripted_Animation( const char * anim_name, bool blend, bool looping )
  458. {
  459. #if 0
  460. if ( StateLocked ) {
  461. Debug_Say(( "State is Locked. Can't Start Transition Anim %s\n", anim_name ));
  462. return;
  463. }
  464. #endif
  465. //Debug_Say(("Start_Scripted_Animation %s\n", anim_name));
  466. // We used to not start a scripted anim when wounded, but then the scripts couldn't set
  467. // up custom events well. So I am gonna try to remove the wounded check
  468. // 8/17/01 Byon
  469. // if (( Get_State() == DEATH ) || ( Get_State() == DESTROY ) || ( Get_State() == WOUNDED )) {
  470. if (( Get_State() == DEATH ) || ( Get_State() == DESTROY ) ) {
  471. return;
  472. }
  473. Set_State( ANIMATION );
  474. float blend_time = blend ? 0.2 : 0;
  475. AnimControl->Set_Animation( anim_name, blend_time );
  476. AnimControl->Set_Mode( looping ? ANIM_MODE_LOOP : ANIM_MODE_ONCE );
  477. AnimControl->Update( 0 ); // update
  478. StateLocked = true;
  479. }
  480. void HumanStateClass::Stop_Scripted_Animation( void )
  481. {
  482. if ( State != ANIMATION && State != LOCKED_ANIMATION ) {
  483. // Debug_Say(( "Not in a Scripted Animation to stop\n" ));
  484. // Better clear the locked state. This was keeping us in the place beacon mode
  485. StateLocked = false;
  486. return;
  487. }
  488. StateLocked = false;
  489. Set_State( UPRIGHT );
  490. // AnimControl->Lock_Animation();
  491. }
  492. void HumanStateClass::Force_Animation( const char * anim_name, bool blend )
  493. {
  494. //Debug_Say(( "Forcing Animation to %s\n", anim_name ));
  495. float blend_time = blend ? 0.2 : 0;
  496. AnimControl->Set_Animation( anim_name, blend_time );
  497. AnimControl->Update( 0 ); // update
  498. }
  499. /*
  500. **
  501. */
  502. typedef enum {
  503. LEG_STYLE_STAND, // A0
  504. LEG_STYLE_RUN_FORWARD, // A1
  505. LEG_STYLE_RUN_BACKWARD, // A2
  506. LEG_STYLE_RUN_LEFT, // A3
  507. LEG_STYLE_RUN_RIGHT, // A4
  508. LEG_STYLE_TURN_LEFT, // A5
  509. LEG_STYLE_TURN_RIGHT, // A6
  510. LEG_STYLE_WALK_FORWARD, // B1
  511. LEG_STYLE_WALK_BACKWARD, // B2
  512. LEG_STYLE_WALK_LEFT, // B3
  513. LEG_STYLE_WALK_RIGHT, // B4
  514. LEG_STYLE_CROUCH, // C0
  515. LEG_STYLE_CROUCH_MOVE_FORWARD, // C1
  516. LEG_STYLE_CROUCH_MOVE_BACKWARD, // C2
  517. LEG_STYLE_CROUCH_MOVE_LEFT, // C3
  518. LEG_STYLE_CROUCH_MOVE_RIGHT, // C4
  519. LEG_STYLE_CROUCH_TURN_LEFT, // C3
  520. LEG_STYLE_CROUCH_TURN_RIGHT, // C4
  521. LEG_STYLE_JUMP_UP, // D0
  522. LEG_STYLE_JUMP_FORWARD, // D1
  523. LEG_STYLE_JUMP_BACKWARD, // D2
  524. LEG_STYLE_JUMP_LEFT, // D3
  525. LEG_STYLE_JUMP_RIGHT, // D4
  526. } HUMAN_ANIM_LEG_STYLE;
  527. static const char * LegAnimNames[] = {
  528. "A0", // LEG_STYLE_STAND,
  529. "A1", // LEG_STYLE_RUN_FORWARD,
  530. "A2", // LEG_STYLE_RUN_BACKWARD,
  531. "A3", // LEG_STYLE_RUN_LEFT,
  532. "A4", // LEG_STYLE_RUN_RIGHT,
  533. "A5", // LEG_STYLE_TURN_LEFT,
  534. "A6", // LEG_STYLE_TURN_RIGHT,
  535. "B1", // LEG_STYLE_WALK_FORWARD,
  536. "B2", // LEG_STYLE_WALK_BACKWARD,
  537. "B3", // LEG_STYLE_WALK_LEFT,
  538. "B4", // LEG_STYLE_WALK_RIGHT,
  539. "C0", // LEG_STYLE_CROUCH,
  540. "C1", // LEG_STYLE_CROUCH_MOVE_FORWARD,
  541. "C2", // LEG_STYLE_CROUCH_MOVE_BACKWARD,
  542. "C3", // LEG_STYLE_CROUCH_MOVE_LEFT,
  543. "C4", // LEG_STYLE_CROUCH_MOVE_RIGHT,
  544. "C5", // LEG_STYLE_CROUCH_TURN_LEFT,
  545. "C6", // LEG_STYLE_CROUCH_TURN_RIGHT,
  546. "J0", // LEG_STYLE_JUMP_UP,
  547. "J1", // LEG_STYLE_JUMP_FORWARD,
  548. "J2", // LEG_STYLE_JUMP_BACKWARD,
  549. "J3", // LEG_STYLE_JUMP_LEFT,
  550. "J4", // LEG_STYLE_JUMP_RIGHT,
  551. };
  552. static const char * _weapon_style_names[ NUM_WEAPON_HOLD_STYLES ] = {
  553. "A0", //WEAPON_HOLD_STYLE_C4 = 0,
  554. "A0", //WEAPON_HOLD_STYLE_NOT_USED,
  555. "C2", //WEAPON_HOLD_STYLE_AT_SHOULDER, // 2
  556. "D2", //WEAPON_HOLD_STYLE_AT_HIP,
  557. "E2", //WEAPON_HOLD_STYLE_LAUNCHER,
  558. "F2", //WEAPON_HOLD_STYLE_HANDGUN,
  559. "A0", //WEAPON_HOLD_STYLE_BEACON
  560. "A0", //WEAPON_HOLD_STYLE_EMPTY_HANDS,
  561. "B0", //WEAPON_HOLD_STYLE_AT_CHEST,
  562. "A0", //WEAPON_HOLD_STYLE_HANDS_DOWN,
  563. };
  564. static const char * _dive_anims[ 4 * 2 ] = {
  565. // Forwrd Anims
  566. "S_A_HUMAN.H_A_SLD1_01",
  567. "S_A_HUMAN.H_A_SLD1_02",
  568. // Backward anims
  569. "S_A_HUMAN.H_A_SLD2_01",
  570. "S_A_HUMAN.H_A_SLD2_02",
  571. // Left anims
  572. "S_A_HUMAN.H_A_SLD3_01",
  573. "S_A_HUMAN.H_A_SLD3_02",
  574. // Right Anims
  575. "S_A_HUMAN.H_A_SLD4_01",
  576. "S_A_HUMAN.H_A_SLD4_02",
  577. };
  578. // Weapons style, weapon action, recoil, blend, vehicle, mix/math, aiming tilt
  579. void HumanStateClass::Update_Animation( void )
  580. {
  581. WWPROFILE( "Human Animation" );
  582. // no updates for visceroids
  583. if ( AnimControl->Get_Skeleton() == 'V' ) {
  584. StateLocked = true;
  585. return;
  586. }
  587. if ( StateLocked ) {
  588. // Debug_Say(( "ERROR: updating animation when locked\n" ));
  589. return;
  590. // if you change your animn when locked, death state may clear a scripted anim
  591. }
  592. int hold_style = WeaponHoldStyle;
  593. // Setup animation for state, substate, weapon, tilt, etc.
  594. if ( (State == UPRIGHT) || (State == AIRBORNE) ) {
  595. // determine leg style
  596. int leg_style = LEG_STYLE_STAND;
  597. if ( State == AIRBORNE ) {
  598. leg_style = LEG_STYLE_JUMP_UP;
  599. if ( SubState & SUB_STATE_LEFT ) leg_style = LEG_STYLE_JUMP_LEFT;
  600. if ( SubState & SUB_STATE_RIGHT ) leg_style = LEG_STYLE_JUMP_RIGHT;
  601. if ( SubState & SUB_STATE_FORWARD ) leg_style = LEG_STYLE_JUMP_FORWARD;
  602. if ( SubState & SUB_STATE_BACKWARD ) leg_style = LEG_STYLE_JUMP_BACKWARD;
  603. } else {
  604. if ( SubState & SUB_STATE_TURN_LEFT ) leg_style = LEG_STYLE_TURN_LEFT;
  605. if ( SubState & SUB_STATE_TURN_RIGHT ) leg_style = LEG_STYLE_TURN_RIGHT;
  606. if ( SubState & SUB_STATE_LEFT ) leg_style = LEG_STYLE_RUN_LEFT;
  607. if ( SubState & SUB_STATE_RIGHT ) leg_style = LEG_STYLE_RUN_RIGHT;
  608. if ( SubState & SUB_STATE_FORWARD ) leg_style = LEG_STYLE_RUN_FORWARD;
  609. if ( SubState & SUB_STATE_BACKWARD ) leg_style = LEG_STYLE_RUN_BACKWARD;
  610. if ( Get_State_Flag( CROUCHED_FLAG ) ) {
  611. // Tend to hold at chest when crouched
  612. if ( ( hold_style == WEAPON_HOLD_STYLE_HANDS_DOWN ) ||
  613. ( hold_style == WEAPON_HOLD_STYLE_C4 ) ||
  614. ( hold_style == WEAPON_HOLD_STYLE_BEACON ) ) {
  615. hold_style = WEAPON_HOLD_STYLE_AT_CHEST;
  616. }
  617. leg_style += LEG_STYLE_CROUCH - LEG_STYLE_STAND;
  618. } else if ( SubState & SUB_STATE_SLOW ) {
  619. if ( ( leg_style >= LEG_STYLE_RUN_FORWARD ) &&
  620. ( leg_style <= LEG_STYLE_RUN_RIGHT ) ) {
  621. leg_style += LEG_STYLE_WALK_FORWARD - LEG_STYLE_RUN_FORWARD;
  622. }
  623. }
  624. }
  625. const char * leg_anim_name = LegAnimNames[ leg_style ];
  626. const char * torso_anim_name = _weapon_style_names[hold_style];
  627. bool single_anim = true;
  628. float blend_time = 0.2f;
  629. if ( NoAnimBlend ) {
  630. blend_time = 0;
  631. NoAnimBlend = false;
  632. }
  633. if ( torso_anim_name[1] == '2' ) {
  634. // Lets try aiming
  635. StringClass anim1_name(0,true);
  636. StringClass anim2_name(0,true);
  637. StringClass anim3_name(0,true);
  638. anim1_name.Format( "S_A_HUMAN.H_A_%c1%s", 'A' + hold_style, leg_anim_name );
  639. anim2_name.Format( "S_A_HUMAN.H_A_%c2%s", 'A' + hold_style, leg_anim_name );
  640. anim3_name.Format( "S_A_HUMAN.H_A_%c3%s", 'A' + hold_style, leg_anim_name );
  641. // See if we have the tilting data
  642. HAnimClass * anim = WW3DAssetManager::Get_Instance()->Get_HAnim( anim3_name );
  643. if ( anim != NULL ) {
  644. anim->Release_Ref();
  645. single_anim = false;
  646. float tilt_blend = WWMath::Clamp( (AimingTilt / DEG_TO_RADF( 65 )), -1, 1 );
  647. float frame = AnimControl->Get_Frame(); // Maintain the frame number for moving
  648. if ( tilt_blend < 0 ) {
  649. AnimControl->Set_Animation( anim1_name, anim2_name, 1+tilt_blend, blend_time );
  650. } else {
  651. AnimControl->Set_Animation( anim3_name, anim2_name, 1-tilt_blend, blend_time );
  652. }
  653. AnimControl->Set_Mode( ANIM_MODE_LOOP, frame );
  654. }
  655. }
  656. if ( single_anim ) {
  657. StringClass anim_name(0,true);
  658. anim_name.Format( "S_A_HUMAN.H_A_%s%s", torso_anim_name, leg_anim_name );
  659. // Human Anim Override
  660. if ( HumanAnimOverride != NULL ) {
  661. if ( hold_style == WEAPON_HOLD_STYLE_EMPTY_HANDS ) {
  662. if ( leg_style == LEG_STYLE_RUN_FORWARD ) {
  663. anim_name = HumanAnimOverride->RunEmptyHands;
  664. }
  665. if ( leg_style == LEG_STYLE_WALK_FORWARD ) {
  666. anim_name = HumanAnimOverride->WalkEmptyHands;
  667. }
  668. }
  669. if ( hold_style == WEAPON_HOLD_STYLE_AT_CHEST ) {
  670. if ( leg_style == LEG_STYLE_RUN_FORWARD ) {
  671. anim_name = HumanAnimOverride->RunAtChest;
  672. }
  673. if ( leg_style == LEG_STYLE_WALK_FORWARD ) {
  674. anim_name = HumanAnimOverride->WalkAtChest;
  675. }
  676. }
  677. if ( hold_style == WEAPON_HOLD_STYLE_AT_HIP ) {
  678. if ( leg_style == LEG_STYLE_RUN_FORWARD ) {
  679. anim_name = HumanAnimOverride->RunAtHip;
  680. }
  681. if ( leg_style == LEG_STYLE_WALK_FORWARD ) {
  682. anim_name = HumanAnimOverride->WalkAtHip;
  683. }
  684. }
  685. }
  686. // Saftey check anim
  687. // Debug_Say(( "Anim name %s\n", (const char *)anim_name ));
  688. // float frame = AnimControl->Get_Frame(); // Maintain the frame number for moving
  689. AnimControl->Set_Animation( anim_name, blend_time );
  690. // AnimControl->Set_Mode( ANIM_MODE_LOOP, frame );
  691. AnimControl->Set_Mode( ANIM_MODE_LOOP );
  692. }
  693. } else if ( State == DIVE ) {
  694. const char * anim_name = NULL;
  695. #if 0
  696. if ( SubState & SUB_STATE_LEFT ) anim_name = "S_A_HUMAN.H_A_DIV3";
  697. if ( SubState & SUB_STATE_RIGHT ) anim_name = "S_A_HUMAN.H_A_DIV4";
  698. if ( SubState & SUB_STATE_FORWARD ) anim_name = "S_A_HUMAN.H_A_DIV1";
  699. if ( SubState & SUB_STATE_BACKWARD ) anim_name = "S_A_HUMAN.H_A_DIV2";
  700. #else
  701. int offset = FreeRandom.Get_Int( 2 );
  702. if ( !IS_SOLOPLAY ) {
  703. offset = 0;
  704. }
  705. if ( SubState & SUB_STATE_FORWARD ) offset += 0;
  706. if ( SubState & SUB_STATE_BACKWARD ) offset += 2;
  707. if ( SubState & SUB_STATE_LEFT ) offset += 4;
  708. if ( SubState & SUB_STATE_RIGHT ) offset += 6;
  709. anim_name = _dive_anims[offset];
  710. #endif
  711. AnimControl->Set_Animation( anim_name, 0.2f );
  712. AnimControl->Set_Mode( ANIM_MODE_ONCE );
  713. StateLocked = true;
  714. } else if ( State == LAND ) {
  715. int dir = 0;
  716. if ( SubState & SUB_STATE_LEFT ) dir = 3;
  717. if ( SubState & SUB_STATE_RIGHT ) dir = 4;
  718. if ( SubState & SUB_STATE_FORWARD ) dir = 1;
  719. if ( SubState & SUB_STATE_BACKWARD ) dir = 2;
  720. StringClass anim_name(0,true);
  721. anim_name.Format( "S_A_HUMAN.H_A_A0L%d", dir );
  722. AnimControl->Set_Animation( anim_name, 0.2f );
  723. AnimControl->Set_Mode( ANIM_MODE_ONCE );
  724. } else if ( State == WOUNDED ) {
  725. AnimControl->Set_Animation( Get_Wound_Anim( SubState ), 0.2f );
  726. AnimControl->Set_Mode( ANIM_MODE_ONCE );
  727. } else if ( State == DEATH ) {
  728. AnimControl->Set_Animation( Get_Death_Anim( SubState ), 0.2f );
  729. AnimControl->Set_Mode( ANIM_MODE_ONCE );
  730. StateLocked = true;
  731. } else if ( State == LADDER ) {
  732. const char * anim_name = "S_A_HUMAN.H_A_412A";
  733. if ( SubState & SUB_STATE_UP ) anim_name = "S_A_HUMAN.H_A_422A";
  734. if ( SubState & SUB_STATE_DOWN ) anim_name = "S_A_HUMAN.H_A_432A";
  735. AnimControl->Set_Animation( anim_name, 0.2f );
  736. AnimControl->Set_Mode( ANIM_MODE_LOOP );
  737. } else if ( State == ANIMATION ) {
  738. } else if ( State == LOITER ) {
  739. } else if ( State == DESTROY ) {
  740. } else if ( State == TRANSITION ) {
  741. } else if ( State == TRANSITION_COMPLETE ) {
  742. } else if ( State == ON_FIRE ) {
  743. AnimControl->Set_Animation( "S_A_HUMAN.H_A_FLMA", 0.2f );
  744. AnimControl->Set_Mode( ANIM_MODE_LOOP );
  745. } else if ( State == ON_CHEM ) {
  746. AnimControl->Set_Animation( "S_A_HUMAN.h_a_6x01", 0.2f );
  747. AnimControl->Set_Mode( ANIM_MODE_LOOP );
  748. } else if ( State == ON_CNC_FIRE ) {
  749. AnimControl->Set_Animation( "S_A_HUMAN.H_A_FLMA", 0.2f );
  750. AnimControl->Set_Mode( ANIM_MODE_LOOP );
  751. } else if ( State == ON_CNC_CHEM ) {
  752. AnimControl->Set_Animation( "S_A_HUMAN.h_a_6x01", 0.2f );
  753. AnimControl->Set_Mode( ANIM_MODE_LOOP );
  754. } else if ( State == ON_ELECTRIC ) {
  755. AnimControl->Set_Animation( "S_A_HUMAN.h_a_6x05", 0.2f );
  756. AnimControl->Set_Mode( ANIM_MODE_LOOP );
  757. } else if ( State == DEBUG_FLY ) {
  758. } else {
  759. Debug_Say(( "Uncoded Human State %d\n", State ));
  760. AnimControl->Set_Animation( (const char *)NULL );
  761. }
  762. }
  763. #define MOVING_THRESHHOLD 0.2
  764. //#define WALKING_THRESHHOLD 4.5
  765. #define WALKING_THRESHHOLD 3.21f
  766. void HumanStateClass::Reset_Loiter_Delay( void )
  767. {
  768. LoiterDelay = FreeRandom.Get_Float( 6 ) - 3;
  769. }
  770. // Must deal with LAND, ANIMATIONS, DEATH, WOUNDS, TRANSITIONS, JUMP, DEATH FALLS, LADDER
  771. void HumanStateClass::Update_State( void )
  772. {
  773. WWPROFILE( "Human State" );
  774. StateTimer += TimeManager::Get_Frame_Seconds();
  775. if ( AnimControl && AnimControl->Get_Skeleton() == 'V' ) {
  776. LoitersAllowed = false;
  777. }
  778. if ( State == UPRIGHT && LoitersAllowed ) {
  779. // Don't loiter when crouched or moving
  780. if ( SubState != 0 ) {
  781. Reset_Loiter_Delay();
  782. }
  783. LoiterDelay += TimeManager::Get_Frame_Seconds();
  784. HumanLoiterGlobalSettingsDef * loiter_def = HumanLoiterCollection;
  785. if ( loiter_def == NULL ) {
  786. loiter_def = HumanLoiterGlobalSettingsDef::Get_Default_Loiters();
  787. }
  788. #if 0
  789. // loiter based on holding a weapon
  790. if ( WeaponHoldStyle == WEAPON_HOLD_STYLE_EMPTY_HANDS ) {
  791. loiter_def = HumanLoiterGlobalSettingsDef::Get_Weaponless_Loiters();
  792. } else {
  793. loiter_def = HumanLoiterGlobalSettingsDef::Get_Weapon_Loiters();
  794. }
  795. #endif
  796. if ( loiter_def != NULL ) {
  797. if ( LoiterDelay > loiter_def->Get_Activation_Delay() ) {
  798. Set_State( LOITER, Get_Sub_State() );
  799. StringClass anim(loiter_def->Pick_Animation(),true);
  800. // Debug_Say(( "Start loiter %s\n", anim ));
  801. if ( !anim.Is_Empty() ) {
  802. StringClass new_anim(true);
  803. ::Strip_Path_From_Filename( new_anim, anim );
  804. // remove the .W3D
  805. if ( new_anim.Get_Length() >= 5 ) {
  806. new_anim.Erase( new_anim.Get_Length()-4, 4 );
  807. }
  808. AnimControl->Set_Animation( new_anim, 0.2f );
  809. AnimControl->Set_Mode( ANIM_MODE_ONCE );
  810. AnimControl->Update( 0 ); // update
  811. }
  812. }
  813. } else {
  814. Debug_Say(( "Failed to find Loiter Def\n" ));
  815. }
  816. } else {
  817. Reset_Loiter_Delay();
  818. }
  819. // Get out of locked states
  820. if ( AnimControl->Is_Complete() ) { // Time to unlock
  821. // if ( StateLocked && State != LOCKED_ANIMATION ) {
  822. if ( (StateLocked && State != LOCKED_ANIMATION) || (State == DEATH) ) {
  823. StateLocked = false;
  824. if ( State == DIVE ) {
  825. Set_State( UPRIGHT );
  826. } else if ( State == ANIMATION ) {
  827. Set_State( UPRIGHT );
  828. } else if ( State == DEATH ) {
  829. Set_State( DESTROY );
  830. TransitionEffectClass * effect = CombatMaterialEffectManager::Get_Death_Effect();
  831. this->HumanPhys->Add_Effect_To_Me(effect);
  832. REF_PTR_RELEASE(effect);
  833. } else if ( State == TRANSITION ) {
  834. Set_State( TRANSITION_COMPLETE );
  835. } else if ( State != LOCKED_ANIMATION ) {
  836. Debug_Say(( "Unsupported locked state %s\n", Get_State_Name() ));
  837. }
  838. } else {
  839. // Debug_Say(( "Anim Complete %s\n", Get_State_Name() ));
  840. if ( State == LOITER ) {
  841. Set_State( UPRIGHT );
  842. } else if ( State == LAND ) {
  843. Set_State( UPRIGHT, Get_Sub_State() );
  844. } else if ( State == WOUNDED ) {
  845. Set_State( UPRIGHT );
  846. }
  847. }
  848. }
  849. /*
  850. ** Handle Jump and landing
  851. */
  852. if ( !HumanPhys->Is_In_Contact() ) { // If I am not in contact with the ground
  853. if ( State == UPRIGHT ) { // If I am currently UPRIGHT
  854. Begin_Jump(); // Begin a jump
  855. }
  856. } else if ( State == AIRBORNE ) { // If I am in contact, and in the , I just landed
  857. Complete_Jump(); // So complete the jump
  858. }
  859. if ( WeaponHoldTimer > 0 && !Get_State_Flag( CROUCHED_FLAG ) ) {
  860. Reset_Loiter_Delay();
  861. WeaponHoldTimer -= TimeManager::Get_Frame_Seconds();
  862. if ( WeaponHoldTimer <= 0 ) {
  863. if ( WeaponHoldStyle == WEAPON_HOLD_STYLE_HANDGUN ||
  864. WeaponHoldStyle == WEAPON_HOLD_STYLE_C4 ||
  865. WeaponHoldStyle == WEAPON_HOLD_STYLE_BEACON )
  866. {
  867. WeaponHoldStyle = WEAPON_HOLD_STYLE_HANDS_DOWN; // Lower the weapon
  868. } else {
  869. WeaponHoldStyle = WEAPON_HOLD_STYLE_AT_CHEST; // Lower the weapon
  870. }
  871. Update_Animation();
  872. }
  873. }
  874. }
  875. /*
  876. **
  877. */
  878. void HumanStateClass::Post_Think( void )
  879. {
  880. // Update sub_state per movement
  881. // do it for upright, land, ladder, airborne,
  882. if ( Is_Sub_State_Adjustable() || Is_State_Interruptable() ) {
  883. // Update the SubState
  884. int new_sub_state = 0;
  885. // Get our current move vector
  886. Vector3 move_vector;
  887. HumanPhys->Get_Animation_Move( &move_vector );
  888. if ( TimeManager::Get_Frame_Seconds() > 0 ) {
  889. move_vector /= TimeManager::Get_Frame_Seconds();
  890. }
  891. move_vector = HumanPhys->Get_Transform().Inverse_Rotate_Vector( move_vector );
  892. // When walking running diagonally, use forward/backward legs.
  893. // Unless you are crouched, then use straffe legs
  894. float direction_ratio = 0.75f;
  895. if ( Get_State_Flag( CROUCHED_FLAG ) ) {
  896. direction_ratio = 2;
  897. }
  898. // Convert to SubMode
  899. if ( WWMath::Fabs( move_vector[0] ) > direction_ratio * WWMath::Fabs( move_vector[1] ) ) {
  900. if ( move_vector[0] > MOVING_THRESHHOLD ) new_sub_state |= SUB_STATE_FORWARD;
  901. else if ( move_vector[0] < -MOVING_THRESHHOLD ) new_sub_state |= SUB_STATE_BACKWARD;
  902. } else {
  903. if ( move_vector[1] > MOVING_THRESHHOLD ) new_sub_state |= SUB_STATE_LEFT;
  904. else if ( move_vector[1] < -MOVING_THRESHHOLD ) new_sub_state |= SUB_STATE_RIGHT;
  905. }
  906. if ( new_sub_state == 0 ) {
  907. if ( move_vector[2] > MOVING_THRESHHOLD ) new_sub_state |= SUB_STATE_UP;
  908. else if ( move_vector[2] < -MOVING_THRESHHOLD ) new_sub_state |= SUB_STATE_DOWN;
  909. }
  910. if ( new_sub_state != 0 ) {
  911. if ( move_vector.Length() < WALKING_THRESHHOLD ) new_sub_state |= SUB_STATE_SLOW;
  912. //Debug_Say(( "%f %f\n", move_vector.Length(), WALKING_THRESHHOLD ));
  913. }
  914. #if 0 // No turn anims!!!
  915. // Get our current turn vector
  916. if ( TurnVelocity > 0 ) new_sub_state |= SUB_STATE_TURN_LEFT;
  917. else if ( TurnVelocity < 0 ) new_sub_state |= SUB_STATE_TURN_RIGHT;
  918. TurnVelocity = 0;
  919. #endif
  920. // Get him out of WOUNDED, LAND, LOITER states if moving or shooting
  921. if ( Is_State_Interruptable() && Get_State() != UPRIGHT ) {
  922. // if ( new_sub_state != 0 || WeaponState > WeaponClass::STATE_READY ) {
  923. if ( new_sub_state != 0 || WeaponFired ) {
  924. if ( Get_State() == LAND && Get_Sub_State() == new_sub_state ) {
  925. // don't interrupt lands for the same direction
  926. } else {
  927. // Debug_Say(( "Interrupt State %s\n", Get_State_Name() ));
  928. Set_State( UPRIGHT );
  929. }
  930. }
  931. }
  932. if ( Is_Sub_State_Adjustable() ) {
  933. if ( new_sub_state != Get_Sub_State() ) {
  934. Set_Sub_State( (HumanSubStateType)new_sub_state );
  935. }
  936. #if 0 // Disable all leg twisting
  937. // =================================================================== // LEG TWIST!!!!!
  938. // Don't leg twist for crouched
  939. if ( Get_State() == UPRIGHT && !Get_State_Flag( CROUCHED_FLAG ) ) {
  940. float legs_rotation = 0;
  941. // Compare the facing to the motion, set leg_racing to the difference
  942. if ( move_vector.Length() > 0 ) {
  943. float move_direction = WWMath::Atan2( -move_vector.Y, move_vector.X );
  944. if ( new_sub_state & SUB_STATE_FORWARD ) {
  945. legs_rotation = -move_direction;
  946. } else if ( new_sub_state & SUB_STATE_BACKWARD ) {
  947. legs_rotation = -move_direction + DEG_TO_RAD( 180 );
  948. } else if ( new_sub_state & SUB_STATE_LEFT ) {
  949. legs_rotation = -move_direction + DEG_TO_RAD( 270 );
  950. } else if ( new_sub_state & SUB_STATE_RIGHT ) {
  951. legs_rotation = -move_direction + DEG_TO_RAD( 90 );
  952. }
  953. legs_rotation = WWMath::Wrap( legs_rotation, DEG_TO_RADF( -180 ), DEG_TO_RADF( 180 ) );
  954. // legs_rotation = WWMath::Clamp( legs_rotation, DEG_TO_RADF( -45 ), DEG_TO_RADF( 45 ) );
  955. legs_rotation = WWMath::Clamp( legs_rotation, DEG_TO_RADF( -30 ), DEG_TO_RADF( 30 ) );
  956. if ( WWMath::Fabs( legs_rotation ) < DEG_TO_RAD( 25 ) ) {
  957. legs_rotation = 0;
  958. }
  959. }
  960. // Move LegRotation toward leg_rotation
  961. float rot_diff = legs_rotation - LegRotation;
  962. float max_mov = DEG_TO_RAD( 180 ) * TimeManager::Get_Frame_Seconds();
  963. // float max_mov = DEG_TO_RAD( 90 ) * TimeManager::Get_Frame_Seconds();
  964. rot_diff = WWMath::Clamp( rot_diff, -max_mov, max_mov );
  965. LegRotation += rot_diff;
  966. legs_rotation = LegRotation;
  967. // I'm making this staic for now, because all human
  968. // skeletons have the bone at the same index
  969. static int root_bone = -1;
  970. if ( root_bone == -1 ) { // Get root bone index
  971. root_bone = HumanPhys->Peek_Model()->Get_Bone_Index( "c spine" );
  972. }
  973. static int torso_bone = -1;
  974. if ( torso_bone == -1 ) { // Get torso bone index
  975. torso_bone = HumanPhys->Peek_Model()->Get_Bone_Index( "c spine1" );
  976. }
  977. if ( legs_rotation != 0 ) {
  978. WWASSERT( root_bone != -1 );
  979. WWASSERT( torso_bone != -1 );
  980. if ( !HumanPhys->Peek_Model()->Is_Bone_Captured( root_bone ) ) {
  981. HumanPhys->Peek_Model()->Capture_Bone( root_bone );
  982. }
  983. if ( !HumanPhys->Peek_Model()->Is_Bone_Captured( torso_bone ) ) {
  984. HumanPhys->Peek_Model()->Capture_Bone( torso_bone );
  985. }
  986. Matrix3D root_adjust(1); // adjust it
  987. root_adjust.Rotate_X( legs_rotation );
  988. HumanPhys->Peek_Model()->Control_Bone( root_bone, root_adjust );
  989. Matrix3D legs_adjust(1); // adjust it
  990. legs_adjust.Rotate_X( -legs_rotation );
  991. HumanPhys->Peek_Model()->Control_Bone( torso_bone, legs_adjust );
  992. } else { // no adjustment, release
  993. if ( HumanPhys->Peek_Model()->Is_Bone_Captured( root_bone ) ) {
  994. HumanPhys->Peek_Model()->Release_Bone( root_bone );
  995. }
  996. if ( HumanPhys->Peek_Model()->Is_Bone_Captured( torso_bone ) ) {
  997. HumanPhys->Peek_Model()->Release_Bone( torso_bone );
  998. }
  999. }
  1000. }
  1001. #endif
  1002. }
  1003. // Scale animation speed
  1004. float ideal_speed = 0;
  1005. if ( !(new_sub_state & SUB_STATE_SLOW) ) {
  1006. if ( new_sub_state & SUB_STATE_FORWARD ) ideal_speed = 5.5f;
  1007. if ( new_sub_state & SUB_STATE_BACKWARD ) ideal_speed = 4.5f;
  1008. if ( new_sub_state & SUB_STATE_LEFT ) ideal_speed = 4.5f;
  1009. if ( new_sub_state & SUB_STATE_RIGHT ) ideal_speed = 5.5f;
  1010. } else {
  1011. if ( new_sub_state & SUB_STATE_FORWARD ) ideal_speed = 1.6f;
  1012. if ( new_sub_state & SUB_STATE_BACKWARD ) ideal_speed = 1.5f;
  1013. if ( new_sub_state & SUB_STATE_LEFT ) ideal_speed = 1.5f;
  1014. if ( new_sub_state & SUB_STATE_RIGHT ) ideal_speed = 1.6f;
  1015. }
  1016. if ( State == LADDER ) {
  1017. if ( new_sub_state & SUB_STATE_UP ) ideal_speed = 0.15f;
  1018. if ( new_sub_state & SUB_STATE_DOWN ) ideal_speed = 0.15f;
  1019. }
  1020. // Turning is at speed 1
  1021. bool turning = ( new_sub_state & (SUB_STATE_TURN_LEFT | SUB_STATE_TURN_RIGHT ) &&
  1022. !( new_sub_state & (SUB_STATE_FORWARD | SUB_STATE_BACKWARD )));
  1023. if ( !turning && ideal_speed != 0 ) {
  1024. // Get Anim_Speed_Scale
  1025. Vector3 vel;
  1026. HumanPhys->Get_Animation_Move( &vel );
  1027. if ( TimeManager::Get_Frame_Seconds() > 0 ) {
  1028. vel /= TimeManager::Get_Frame_Seconds();
  1029. }
  1030. float speed = WWMath::Clamp( vel.Length() / ideal_speed, 0.33f, 3 );
  1031. AnimControl->Set_Anim_Speed_Scale( speed );
  1032. } else {
  1033. AnimControl->Set_Anim_Speed_Scale( 1 );
  1034. }
  1035. HumanPhys->Reset_Animation_Move();
  1036. }
  1037. }
  1038. /*
  1039. **
  1040. */
  1041. bool HumanStateClass::Get_Leg_Mode( void )
  1042. {
  1043. return AnimControl->Get_Progress() > 0.5f;
  1044. }
  1045. /*
  1046. **
  1047. */
  1048. struct BoneToOuchType {
  1049. const char * bone_name;
  1050. int ouch_type;
  1051. };
  1052. BoneToOuchType _BoneToOuchTypeList[] = {
  1053. { "K_HEAD", HumanStateClass::HEAD_FROM_BEHIND },
  1054. { "K_NECK", HumanStateClass::HEAD_FROM_BEHIND },
  1055. { "K_CHEST", HumanStateClass::HEAD_FROM_BEHIND },
  1056. { "K_ABDOMEN", HumanStateClass::TORSO_FROM_BEHIND },
  1057. { "K_PELVIS", HumanStateClass::GROIN },
  1058. { "K_L THIGH", HumanStateClass::LEFT_LEG_FROM_BEHIND },
  1059. { "K_L CALF", HumanStateClass::LEFT_LEG_FROM_BEHIND },
  1060. { "K_L FOOT", HumanStateClass::LEFT_LEG_FROM_BEHIND },
  1061. { "K_L HAND", HumanStateClass::LEFT_ARM_FROM_BEHIND },
  1062. { "K_L FOREARM", HumanStateClass::LEFT_ARM_FROM_BEHIND },
  1063. { "K_L UPPERARM", HumanStateClass::LEFT_ARM_FROM_BEHIND },
  1064. { "K_R THIGH", HumanStateClass::RIGHT_LEG_FROM_BEHIND },
  1065. { "K_R CALF", HumanStateClass::RIGHT_LEG_FROM_BEHIND },
  1066. { "K_R FOOT", HumanStateClass::RIGHT_LEG_FROM_BEHIND },
  1067. { "K_R HAND", HumanStateClass::RIGHT_ARM_FROM_BEHIND },
  1068. { "K_R FOREARM", HumanStateClass::RIGHT_ARM_FROM_BEHIND },
  1069. { "K_R UPPERARM", HumanStateClass::RIGHT_ARM_FROM_BEHIND },
  1070. };
  1071. #define BONE_LIST_COUNT ( sizeof(_BoneToOuchTypeList) / sizeof(_BoneToOuchTypeList[0]) )
  1072. int HumanStateClass::Get_Ouch_Type( const Vector3 & direction, const char * collision_box_name )
  1073. {
  1074. // Initialize ouch_type to a default value
  1075. int ouch_type = TORSO_FROM_FRONT;
  1076. const char * base_name = NULL;
  1077. if ( collision_box_name != NULL ) {
  1078. base_name = ::strchr( collision_box_name, '.' );
  1079. } else {
  1080. return ouch_type;
  1081. }
  1082. if ( base_name != NULL ) {
  1083. base_name++;
  1084. for ( int i = 0; i < BONE_LIST_COUNT; i++ ) {
  1085. if ( ::strcmp( _BoneToOuchTypeList[i].bone_name, base_name ) == 0 ) {
  1086. ouch_type = _BoneToOuchTypeList[i].ouch_type;
  1087. }
  1088. }
  1089. }
  1090. if ( ouch_type != -1 ) {
  1091. // Set direction
  1092. Vector3 relative_direction = HumanPhys->Get_Transform().Inverse_Rotate_Vector( direction );
  1093. if ( ouch_type != HumanStateClass::GROIN ) { // but not for the groin shot
  1094. if ( relative_direction.X < 0 ) {
  1095. ouch_type += 1;
  1096. }
  1097. }
  1098. } else {
  1099. Debug_Say(( "Bad human collision box name %s\n", collision_box_name ));
  1100. }
  1101. return ouch_type;
  1102. }
  1103. /*
  1104. **
  1105. */
  1106. const char * _WoundAnims[] =
  1107. {
  1108. "S_A_HUMAN.H_A_811A", // HEAD_FROM_BEHIND,
  1109. "S_A_HUMAN.H_A_812A", // HEAD_FROM_FRONT,
  1110. "S_A_HUMAN.H_A_821A", // TORSO_FROM_BEHIND,
  1111. "S_A_HUMAN.H_A_822A", // TORSO_FROM_FRONT,
  1112. "S_A_HUMAN.H_A_831A", // LEFT_ARM_FROM_BEHIND,
  1113. "S_A_HUMAN.H_A_832A", // LEFT_ARM_FROM_FRONT,
  1114. "S_A_HUMAN.H_A_841A", // RIGHT_ARM_FROM_BEHIND,
  1115. "S_A_HUMAN.H_A_842A", // RIGHT_ARM_FROM_FRONT,
  1116. "S_A_HUMAN.H_A_851A", // LEFT_LEG_FROM_BEHIND,
  1117. "S_A_HUMAN.H_A_852A", // LEFT_LEG_FROM_FRONT,
  1118. "S_A_HUMAN.H_A_861A", // RIGHT_LEG_FROM_BEHIND,
  1119. "S_A_HUMAN.H_A_862A", // RIGHT_LEG_FROM_FRONT,
  1120. "S_A_HUMAN.H_A_871A", // GROIN,
  1121. };
  1122. const char * HumanStateClass::Get_Wound_Anim( int ouch_type )
  1123. {
  1124. return _WoundAnims[ ouch_type ];
  1125. }
  1126. /*
  1127. **
  1128. */
  1129. const char * _DeathAnims[] =
  1130. {
  1131. "S_A_HUMAN.H_A_622A", // HEAD_FROM_BEHIND,
  1132. "S_A_HUMAN.H_A_635A", // HEAD_FROM_FRONT,
  1133. "S_A_HUMAN.H_A_622A", // TORSO_FROM_BEHIND,
  1134. "S_A_HUMAN.H_A_632A", // TORSO_FROM_FRONT,
  1135. "S_A_HUMAN.H_A_623A", // LEFT_ARM_FROM_BEHIND,
  1136. "S_A_HUMAN.H_A_634A", // LEFT_ARM_FROM_FRONT,
  1137. "S_A_HUMAN.H_A_624A", // RIGHT_ARM_FROM_BEHIND,
  1138. "S_A_HUMAN.H_A_633A", // RIGHT_ARM_FROM_FRONT,
  1139. "S_A_HUMAN.H_A_623A", // LEFT_LEG_FROM_BEHIND,
  1140. "S_A_HUMAN.H_A_634A", // LEFT_LEG_FROM_FRONT,
  1141. "S_A_HUMAN.H_A_624A", // RIGHT_LEG_FROM_BEHIND,
  1142. "S_A_HUMAN.H_A_633A", // RIGHT_LEG_FROM_FRONT,
  1143. "S_A_HUMAN.H_A_612A", // GROIN,
  1144. "S_A_HUMAN.H_A_FLMB", // ON_FIRE,
  1145. "S_A_HUMAN.H_A_FLMB", // ON_CHEM,
  1146. "S_A_HUMAN.H_A_FLMB", // ON_ELECTRIC,
  1147. "S_A_HUMAN.H_A_FLMB", // ON_CNC_FIRE,
  1148. "S_A_HUMAN.H_A_FLMB", // ON_CNC_CHEM,
  1149. };
  1150. const char * HumanStateClass::Get_Death_Anim( int ouch_type )
  1151. {
  1152. WWASSERT( ouch_type <= OUCH_SUPER_FIRE );
  1153. return _DeathAnims[ ouch_type ];
  1154. }
  1155. /*
  1156. **
  1157. */
  1158. void HumanStateClass::Set_Precision(void)
  1159. {
  1160. cEncoderList::Set_Precision(BITPACK_HUMAN_STATE, 0, (int) HIGHEST_HUMAN_STATE);
  1161. cEncoderList::Set_Precision(BITPACK_HUMAN_SUB_STATE, 0, (int) HIGHEST_HUMAN_SUB_STATE);
  1162. }
  1163. /*
  1164. **
  1165. */
  1166. void HumanStateClass::Get_Information( StringClass & string )
  1167. {
  1168. StringClass temp(0,true);
  1169. temp.Format( "%s\n", Get_State_Name() );
  1170. string += temp;
  1171. AnimControl->Get_Information( string );
  1172. }
  1173. /*
  1174. ** Begin_Jump is called when we first become airborne
  1175. */
  1176. void HumanStateClass::Begin_Jump( void )
  1177. {
  1178. // Store some information about the jump
  1179. JumpTM = HumanPhys->Get_Transform();
  1180. // Set my state to Jump, with a direction of my current relative velocity
  1181. Vector3 move_vector;
  1182. HumanPhys->Get_Velocity( &move_vector );
  1183. move_vector = HumanPhys->Get_Transform().Inverse_Rotate_Vector( move_vector );
  1184. int sub_state = 0;
  1185. if ( move_vector[0] > MOVING_THRESHHOLD ) sub_state |= SUB_STATE_FORWARD;
  1186. else if ( move_vector[0] < -MOVING_THRESHHOLD ) sub_state |= SUB_STATE_BACKWARD;
  1187. if ( move_vector[1] > MOVING_THRESHHOLD ) sub_state |= SUB_STATE_LEFT;
  1188. else if ( move_vector[1] < -MOVING_THRESHHOLD ) sub_state |= SUB_STATE_RIGHT;
  1189. Set_State( AIRBORNE, sub_state );
  1190. // Whenever a jump starts, play a jump surface effect
  1191. Matrix3D tm = HumanPhys->Get_Transform();
  1192. int ground_type = HumanPhys->Get_Contact_Surface_Type();
  1193. SurfaceEffectsManager::Apply_Effect( ground_type, SurfaceEffectsManager::HITTER_TYPE_FOOTSTEP_JUMP, tm );
  1194. }
  1195. /*
  1196. ** Complete_Jump is called when we land
  1197. */
  1198. void HumanStateClass::Complete_Jump( void )
  1199. {
  1200. Vector3 fall = JumpTM.Get_Translation() - HumanPhys->Get_Transform().Get_Translation();
  1201. GlobalSettingsDef * settings = GlobalSettingsDef::Get_Global_Settings();
  1202. // Debug_Say(( "Fall Distance %f\n", fall.Z ));
  1203. bool add_portal = true;
  1204. //
  1205. // Don't do this in the level editor
  1206. //
  1207. #ifndef PARAM_EDITING_ON
  1208. if ( fall.Z > settings->Get_Falling_Damage_Min_Distance() ) {
  1209. add_portal = false;
  1210. float scale = (fall.Z - settings->Get_Falling_Damage_Min_Distance()) /
  1211. (settings->Get_Falling_Damage_Max_Distance() - settings->Get_Falling_Damage_Min_Distance());
  1212. scale = WWMath::Clamp( scale, 0, 1 );
  1213. // (gth) don't take damage when falling onto an elevator (because we have
  1214. // super-fast elevators...)
  1215. if ( (HumanPhys->Peek_Ground_Object() != NULL) &&
  1216. (HumanPhys->Peek_Ground_Object()->As_ElevatorPhysClass() != NULL))
  1217. {
  1218. Debug_Say(( "Fell onto an elevator, no damage!\n", scale ));
  1219. scale = 0.0f;
  1220. }
  1221. Debug_Say(( "Fall Damage Scale %f\n", scale ));
  1222. SoldierGameObj * owner = (SoldierGameObj *)HumanPhys->Get_Observer();
  1223. if ( owner != NULL ) {
  1224. DefenseObjectClass * defense = owner->Get_Defense_Object();
  1225. float damage = defense->Get_Health_Max();
  1226. // AI's get notified
  1227. // if ( !owner->Is_Human_Controlled() ) {
  1228. const GameObjObserverList & observer_list = owner->Get_Observers();
  1229. for( int index = 0; index < observer_list.Count(); index++ ) {
  1230. observer_list[ index ]->Custom( owner, CUSTOM_EVENT_FALLING_DAMAGE, damage*scale, NULL );
  1231. }
  1232. // }
  1233. // All get the damage
  1234. OffenseObjectClass offense( damage, settings->Get_Falling_Damage_Warhead(), NULL );
  1235. owner->Apply_Damage_Extended( offense, scale, fall, NULL );
  1236. }
  1237. }
  1238. #endif // PARAM_EDITING_ON
  1239. // Find the sector the human jumped from and the sector the human jumped to.
  1240. /*Vector3 curr_pos = HumanPhys->Get_Position ();
  1241. PathfindSectorClass *start_sector = PathfindClass::Get_Instance ()->Find_Sector (JumpTM.Get_Translation (), 2.0F);
  1242. PathfindSectorClass *end_sector = PathfindClass::Get_Instance ()->Find_Sector (curr_pos, 2.0F);
  1243. // Make a temporary pathfind connection between these sectors (if necessary)
  1244. if (add_portal && start_sector != NULL && end_sector != NULL && start_sector != end_sector) {
  1245. PathfindClass::Get_Instance ()->Add_Temporary_Portal (start_sector, end_sector, JumpTM.Get_Translation (), curr_pos);
  1246. }*/
  1247. // Set me state to Land, with a direction of my current velocity
  1248. Vector3 move_vector;
  1249. HumanPhys->Get_Velocity( &move_vector );
  1250. move_vector = HumanPhys->Get_Transform().Inverse_Rotate_Vector( move_vector );
  1251. int sub_state = 0;
  1252. if ( move_vector[0] > MOVING_THRESHHOLD ) sub_state |= SUB_STATE_FORWARD;
  1253. else if ( move_vector[0] < -MOVING_THRESHHOLD ) sub_state |= SUB_STATE_BACKWARD;
  1254. if ( move_vector[1] > MOVING_THRESHHOLD ) sub_state |= SUB_STATE_LEFT;
  1255. else if ( move_vector[1] < -MOVING_THRESHHOLD ) sub_state |= SUB_STATE_RIGHT;
  1256. Set_State( LAND, sub_state );
  1257. // Whenever a jump ends, play a land surface effect
  1258. Matrix3D tm = HumanPhys->Get_Transform();
  1259. int ground_type = HumanPhys->Get_Contact_Surface_Type();
  1260. SurfaceEffectsManager::Apply_Effect( ground_type, SurfaceEffectsManager::HITTER_TYPE_FOOTSTEP_LAND, tm );
  1261. }