Advertisement
Guest User

Untitled

a guest
Sep 23rd, 2014
168
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 62.13 KB | None | 0 0
  1. #include common_scripts\utility;
  2. #include animscripts\utility;
  3. #include maps\_utility;
  4. #using_animtree( "generic_human" );
  5.  
  6.  
  7. //
  8. // Damage Yaw
  9. //
  10. // front
  11. // /----|----\
  12. // / 180 \
  13. // /\ | /\
  14. // / -135 | 135 \
  15. // | \ | / |
  16. // left|-90----+----90-|right
  17. // | / | \ |
  18. // \ -45 | 45 /
  19. // \/ | \/
  20. // \ 0 /
  21. // \----|----/
  22. // back
  23.  
  24. main()
  25. {
  26. self trackScriptState( "Death Main", "code" );
  27. self endon( "killanimscript" );
  28. self stopsounds();
  29.  
  30. // MikeD( 10/9/2007 ): Stop flamethrower, if shooting it.
  31. self flamethrower_stop_shoot();
  32. wpn_check = maps\_blst_custom_ammo::blst_shock( self.damageweapon, self.damagemod ); // Shock Ammo
  33. if( wpn_check && level.zombie_vars["zombie_insta_kill"] == 0 )
  34. {
  35. self.deathanim = random( level._zombie_tesla_death[self.animname] );
  36. Playfxontag (level._effect["tesla_shock_eyes"], self, "J_Eyeball_LE" );
  37. Playfxontag (level._effect["tesla_shock"], self, "J_SpineUpper" );
  38. }
  39.  
  40. wpn_check = maps\_blst_custom_ammo::blst_flame( self.damageweapon, self.damagemod ); // Flame Ammo
  41. if( wpn_check && level.zombie_vars["zombie_insta_kill"] == 0 )
  42. {
  43. if( !isdefined( self.is_on_fire ) || isdefined( self.is_on_fire ) && !self.is_on_fire )
  44. {
  45. self thread flame_death_fx();
  46. }
  47. }
  48.  
  49. wpn_check = maps\_blst_custom_ammo::blst_explosive( self.damageweapon, self.damagemod ); // Explosive Ammo
  50. if( wpn_check && level.zombie_vars["zombie_insta_kill"] == 0 )
  51. {
  52. expl_anim = maps\_blst_custom_ammo::death_anim_yaw( self.damageyaw );
  53. self.deathanim = expl_anim;
  54. }
  55.  
  56. if( isdefined( level.missionCallbacks ) )
  57. {
  58. maps\_challenges_coop::doMissionCallback( "actorKilled", self );
  59. }
  60.  
  61. // don't abort at this point unless you're going to play another animation!
  62. // just playing ragdoll isn't sufficient because sometimes ragdoll fails, and then
  63. // you'll just have a corpse standing around in limbo.
  64.  
  65. if( self.a.nodeath == true )
  66. {
  67. // need to wait a little bit, as soon as this script is done the actor becomes
  68. // an actor_corpse and is available for deletion. If it gets deleted too soon
  69. // before the actor gets to 'think' at least once then the game can crash.
  70. wait 0.1;
  71. return;
  72. }
  73.  
  74. if( isdefined( self.deathFunction ) )
  75. {
  76. successful_death = self[[self.deathFunction]]();
  77.  
  78. if( !IsDefined( successful_death ) || successful_death )
  79. {
  80. return;
  81. }
  82. }
  83.  
  84. /#
  85. // MikeD( 2/12/2008 ): Used for animation testmaps.
  86. if( IsDefined( self.deathtestfunction ) )
  87. {
  88. self[[self.deathtestfunction]]();
  89. }
  90. #/
  91.  
  92. // make sure the guy doesn't keep doing facial animation after death
  93. changeTime = 0.3;
  94. self clearanim( %scripted_look_straight, changeTime );
  95. self clearanim( %scripted_talking, changeTime );
  96.  
  97. animscripts\utility::initialize( "death" );
  98.  
  99. // Stop any lookats that are happening and make sure no new ones occur while death animation is playing.
  100. self notify( "never look at anything again" );
  101.  
  102. // should move this to squad manager somewhere...
  103. removeSelfFrom_SquadLastSeenEnemyPos( self.origin );
  104.  
  105. anim.numDeathsUntilCrawlingPain--;
  106. anim.numDeathsUntilCornerGrenadeDeath--;
  107.  
  108. if( isDefined( self.deathanim ) )
  109. {
  110. if( !animHasNoteTrack( self.deathanim, "dropgun" ) && !animHasNoteTrack( self.deathanim, "fire_spray" ) ) // && !animHasNotetrack( deathAnim, "gun keep" )
  111. {
  112. self animscripts\shared::DropAllAIWeapons();
  113. }
  114.  
  115. self thread do_gib();
  116.  
  117. //thread[[anim.println]]( "Playing special death as set by self.deathanim" ); #/
  118. self SetFlaggedAnimKnobAll( "deathanim", self.deathanim, %root, 1, .05, 1 );
  119.  
  120. if( !animHasNotetrack( self.deathanim, "start_ragdoll" ) )
  121. {
  122. self thread waitForRagdoll( getanimlength( self.deathanim ) * 0.35 );
  123. }
  124.  
  125. if( IsDefined(self.is_zombie) && (!IsDefined(self.in_the_ground) || !self.in_the_ground)) //BB (12.17.08): don't short the death anim if the zombie is in the ground
  126. {
  127. self thread death_anim_short_circuit();
  128. }
  129.  
  130. self animscripts\shared::DoNoteTracks( "deathanim" );
  131. if( isDefined( self.deathanimloop ) )
  132. {
  133. // "Playing special dead/wounded loop animation as set by self.deathanimloop" ); #/
  134. self SetFlaggedAnimKnobAll( "deathanim", self.deathanimloop, %root, 1, .05, 1 );
  135. for( ;; )
  136. {
  137. self animscripts\shared::DoNoteTracks( "deathanim" );
  138. }
  139. }
  140.  
  141. // Added so that I can do special stuff in Level scripts on an ai
  142. if( isdefined( self.deathanimscript ) )
  143. {
  144. self[[self.deathanimscript]]();
  145. }
  146.  
  147. return;
  148. }
  149.  
  150. explosiveDamage = self animscripts\pain::wasDamagedByExplosive();
  151.  
  152. if( self.damageLocation == "helmet" )
  153. {
  154. self helmetPop();
  155. }
  156. else if( explosiveDamage && randomint( 2 ) == 0 )
  157. {
  158. self helmetPop();
  159. }
  160.  
  161. self clearanim( %root, 0.3 );
  162. //self thread animscripts\pain::PlayHitAnimation();
  163.  
  164. if( !damageLocationIsAny( "head", "helmet" ) )
  165. {
  166. if( !IsDefined( self.dieQuietly ) || !self.dieQuietly )
  167. {
  168. PlayDeathSound();
  169. }
  170. }
  171.  
  172. // SRS 7/9/2008: added crunchy headshot sounds
  173. if( damageLocationIsAny( "head", "helmet" ) )
  174. {
  175. if( self.damageLocation == "helmet" && isdefined( self.hatModel ) &&
  176. ModelHasPhysPreset( self.hatModel ) &&
  177. issubstr(self.hatmodel, "helm") )
  178. {
  179. self PlaySound( "bullet_impact_headshot_helmet" );
  180. }
  181. else
  182. {
  183. self PlaySound( "bullet_impact_headshot" );
  184. }
  185. }
  186.  
  187. //deathFace = animscripts\face::ChooseAnimFromSet( anim.deathFace );
  188. //self animscripts\face::SaySpecificDialogue( deathFace, undefined, 1.0 );
  189.  
  190. // CODER_MOD - Austin( 7/3/08 ): added collectible_thunder
  191. if( maps\_collectibles::has_collectible( "collectible_thunder" ) )
  192. {
  193. if( damageLocationIsAny( "head", "helmet" ) )
  194. {
  195. if( !IsDefined( self.attacker ) || !IsPlayer( self.attacker ) )
  196. {
  197. }
  198. else if( !IsDefined( self.team ) || self.team != "axis" )
  199. {
  200. }
  201. else if( self.damagemod == "MOD_PISTOL_BULLET" || self.damagemod == "MOD_RIFLE_BULLET" || self.damagemod == "MOD_IMPACT" )
  202. {
  203. playfxontag( level._effect["thunder"], self, "j_head" );
  204. self startragdoll();
  205. self launchragdoll( ( 0, 0, 100 ) );
  206.  
  207. self.thunder_death = true;
  208. self.gib_override = true;
  209. }
  210. }
  211. }
  212.  
  213. if( explosiveDamage && play_explosion_death() )
  214. {
  215. return;
  216. }
  217.  
  218. if( special_death() )
  219. {
  220. return;
  221. }
  222.  
  223. // CODER MOD: 3/27/08 moved this above explosive damage to get the molotov to burn the guy instead of gibbing him.
  224. if( play_flame_death_anim() )
  225. {
  226. return;
  227. }
  228.  
  229. if( play_bulletgibbed_death_anim() )
  230. {
  231. return;
  232. }
  233.  
  234. if( play_bayonet_death_anim() )
  235. {
  236. return;
  237. }
  238.  
  239. deathAnim = get_death_anim();
  240.  
  241. /#
  242. if( getdvarint( "scr_paindebug" ) == 1 )
  243. {
  244. println( "^2Playing death: ", deathAnim, " ; pose is ", self.a.pose );
  245. }
  246. #/
  247.  
  248. play_death_anim( deathAnim );
  249. }
  250.  
  251.  
  252. waitForRagdoll( time )
  253. {
  254. wait( time );
  255.  
  256. do_ragdoll = true;
  257. if( IsDefined( self.nodeathragdoll ) && self.nodeathragdoll )
  258. {
  259. do_ragdoll = false;
  260. }
  261.  
  262. if( IsDefined( self ) && do_ragdoll )
  263. {
  264. self StartRagDoll();
  265. }
  266.  
  267. if( isdefined( self ) )
  268. {
  269. self animscripts\shared::DropAllAIWeapons();
  270. }
  271. }
  272.  
  273. get_extended_death_seq( deathAnim )
  274. {
  275. deathSeq = [];
  276. if( deathAnim == %ai_deadly_wounded_flamedA_hit )
  277. {
  278. deathSeq[0] = %ai_deadly_wounded_flamedA_hit;
  279. deathSeq[1] = %ai_deadly_wounded_flamedA_loop;
  280. deathSeq[2] = %ai_deadly_wounded_flamedA_die;
  281. //IPrintLn( "ai_deadly_wounded_flamedA_hit" );
  282. }
  283. else if( deathAnim == %ai_deadly_wounded_flamedB_hit )
  284. {
  285. deathSeq[0] = %ai_deadly_wounded_flamedB_hit;
  286. deathSeq[1] = %ai_deadly_wounded_flamedB_loop;
  287. deathSeq[2] = %ai_deadly_wounded_flamedB_die;
  288. //IPrintLn( "ai_deadly_wounded_flamedB_hit" );
  289. }
  290. else if( deathAnim == %ai_deadly_wounded_leg_L_hit )
  291. {
  292. deathSeq[0] = %ai_deadly_wounded_leg_L_hit;
  293. deathSeq[1] = %ai_deadly_wounded_leg_L_loop;
  294. deathSeq[2] = %ai_deadly_wounded_leg_L_die;
  295. //IPrintLn( "ai_deadly_wounded_leg_L_hit" );
  296. }
  297. else if( deathAnim == %ai_deadly_wounded_leg_R_hit )
  298. {
  299. deathSeq[0] = %ai_deadly_wounded_leg_R_hit;
  300. deathSeq[1] = %ai_deadly_wounded_leg_R_loop;
  301. deathSeq[2] = %ai_deadly_wounded_leg_R_die;
  302. //IPrintLn( "ai_deadly_wounded_leg_R_hit" );
  303. }
  304. else if( deathAnim == %ai_deadly_wounded_torso_hit )
  305. {
  306. deathSeq[0] = %ai_deadly_wounded_torso_hit;
  307. deathSeq[1] = %ai_deadly_wounded_torso_loop;
  308. deathSeq[2] = %ai_deadly_wounded_torso_die;
  309. //IPrintLn( "ai_deadly_wounded_torso_hit" );
  310. }
  311.  
  312. if( deathSeq.size == 3 )
  313. {
  314. return deathSeq;
  315. }
  316. return undefined;
  317. }
  318.  
  319. play_death_anim( deathAnim )
  320. {
  321. deathSeq = get_extended_death_seq( deathAnim );
  322. if( isdefined( deathSeq ) )
  323. {
  324. do_extended_death( deathSeq );
  325.  
  326. return;
  327. }
  328.  
  329. self thread death_anim_short_circuit();
  330.  
  331. if( !animHasNoteTrack( deathAnim, "dropgun" ) && !animHasNoteTrack( deathAnim, "fire_spray" ) ) // && !animHasNotetrack( deathAnim, "gun keep" )
  332. {
  333. self animscripts\shared::DropAllAIWeapons();
  334. }
  335.  
  336. if( animHasNoteTrack( deathAnim, "death_neckgrab_spurt" ) && is_mature() )
  337. {
  338. PlayFXOnTag( anim._effect["death_neckgrab_spurt"], self, "j_neck" );
  339. }
  340.  
  341. if( IsDefined( self.skipDeathAnim ) && self.skipDeathAnim )
  342. {
  343. self thread do_gib();
  344. self launch_ragdoll_based_on_damage_type();
  345. wait 0.5;
  346.  
  347. return;
  348. }
  349. else
  350. {
  351. self setFlaggedAnimKnobAllRestart( "deathanim", deathAnim, %body, 1, .1 );
  352. }
  353.  
  354. self thread do_gib();
  355.  
  356. if( !animHasNotetrack( deathanim, "start_ragdoll" ) )
  357. {
  358. self thread waitForRagdoll( getanimlength( deathanim ) * 0.35 );
  359. }
  360.  
  361.  
  362. // do we really need this anymore?
  363. /#
  364. if( getdebugdvar( "debug_grenadehand" ) == "on" )
  365. {
  366. if( animhasnotetrack( deathAnim, "bodyfall large" ) )
  367. {
  368. return;
  369. }
  370.  
  371. if( animhasnotetrack( deathAnim, "bodyfall small" ) )
  372. {
  373. return;
  374. }
  375.  
  376. println( "Death animation ", deathAnim, " does not have a bodyfall notetrack" );
  377. iprintlnbold( "Death animation needs fixing( check console and report bug in the animation to Boon )" );
  378. }
  379. #/
  380.  
  381. self animscripts\shared::DoNoteTracks( "deathanim" );
  382. self animscripts\shared::DropAllAIWeapons();
  383. }
  384.  
  385.  
  386. testPrediction()
  387. {
  388. self BeginPrediction();
  389.  
  390. self animscripts\predict::start();
  391.  
  392. self animscripts\predict::_setAnim( %balcony_stumble_forward, 1, .05, 1 );
  393. if( self animscripts\predict::stumbleWall( 1 ) )
  394. {
  395. self animMode( "nogravity" );
  396.  
  397. self animscripts\predict::_setFlaggedAnimKnobAll( "deathanim", %balcony_tumble_railing36_forward, %root, 1, 0.05, 1 );
  398. if( self animscripts\predict::tumbleWall( "deathanim" ) )
  399. {
  400. self EndPrediction();
  401. return true;
  402. }
  403. }
  404.  
  405. self EndPrediction();
  406. self BeginPrediction();
  407.  
  408. self animscripts\predict::start();
  409.  
  410. self animscripts\predict::_setAnim( %balcony_stumble_forward, 1, .05, 1 );
  411. if( self animscripts\predict::stumbleWall( 1 ) )
  412. {
  413. self animMode( "nogravity" );
  414.  
  415. self animscripts\predict::_setFlaggedAnimKnobAll( "deathanim", %balcony_tumble_railing44_forward, %root, 1, 0.05, 1 );
  416. if( self animscripts\predict::tumbleWall( "deathanim" ) )
  417. {
  418. self EndPrediction();
  419. return true;
  420. }
  421. }
  422.  
  423. self EndPrediction();
  424.  
  425. self animscripts\predict::end();
  426.  
  427. return false;
  428. }
  429.  
  430. // Special death is for corners, rambo behavior, mg42's, anything out of the ordinary stand, crouch and prone.
  431. // It returns true if it handles the death for the special animation state, or false if it wants the regular
  432. // death function to handle it.
  433. special_death()
  434. {
  435. if( self.a.special == "none" )
  436. {
  437. return false;
  438. }
  439.  
  440. switch( self.a.special )
  441. {
  442. case "cover_right":
  443. if( self.a.pose == "stand" )
  444. {
  445. deathArray = [];
  446. deathArray[0] = %corner_standr_deathA;
  447. deathArray[1] = %corner_standr_deathB;
  448. DoDeathFromArray( deathArray );
  449. }
  450. else
  451. {
  452. assert( self.a.pose == "crouch" );
  453. return false;
  454. }
  455. return true;
  456.  
  457. case "cover_left":
  458. if( self.a.pose == "stand" )
  459. {
  460. deathArray = [];
  461. deathArray[0] = %corner_standl_deathA;
  462. deathArray[1] = %corner_standl_deathB;
  463. DoDeathFromArray( deathArray );
  464. }
  465. else
  466. {
  467. assert( self.a.pose == "crouch" );
  468. return false;
  469. }
  470. return true;
  471.  
  472. case "cover_stand":
  473. deathArray = [];
  474. deathArray[0] = %coverstand_death_left;
  475. deathArray[1] = %coverstand_death_right;
  476. DoDeathFromArray( deathArray );
  477. return true;
  478.  
  479. case "cover_crouch":
  480. deathArray = [];
  481. if( damageLocationIsAny( "head", "neck" ) &&( self.damageyaw > 135 || self.damageyaw <= -45 ) ) // Front/Left quadrant
  482. {
  483. deathArray[deathArray.size] = %covercrouch_death_1;
  484. }
  485.  
  486. if( ( self.damageyaw > -45 ) &&( self.damageyaw <= 45 ) ) // Back quadrant
  487. {
  488. deathArray[deathArray.size] = %covercrouch_death_3;
  489. }
  490.  
  491. deathArray[deathArray.size] = %covercrouch_death_2;
  492.  
  493. DoDeathFromArray( deathArray );
  494. return true;
  495.  
  496. case "saw":
  497. if( self.a.pose == "stand" )
  498. {
  499. DoDeathFromArray( array( %saw_gunner_death ) );
  500. }
  501. else if( self.a.pose == "crouch" )
  502. {
  503. DoDeathFromArray( array( %saw_gunner_lowwall_death ) );
  504. }
  505. else
  506. {
  507. DoDeathFromArray( array( %saw_gunner_prone_death ) );
  508. }
  509. return true;
  510.  
  511. case "dying_crawl":
  512. if( self.a.pose == "back" )
  513. {
  514. deathArray = array( %dying_back_death_v2, %dying_back_death_v3, %dying_back_death_v4 );
  515. DoDeathFromArray( deathArray );
  516. }
  517. else
  518. {
  519. assertex( self.a.pose == "prone", self.a.pose );
  520. deathArray = array( %dying_crawl_death_v1, %dying_crawl_death_v2 );
  521. DoDeathFromArray( deathArray );
  522. }
  523. return true;
  524. }
  525. return false;
  526. }
  527.  
  528.  
  529. DoDeathFromArray( deathArray )
  530. {
  531. deathAnim = deathArray[randomint( deathArray.size )];
  532.  
  533. play_death_anim( deathAnim );
  534. //nate - adding my own special death flag on top of special death.
  535. if( isdefined( self.deathanimscript ) )
  536. {
  537. self[[self.deathanimscript]]();
  538. }
  539. }
  540.  
  541.  
  542. PlayDeathSound()
  543. {
  544. // if( self.team == "allies" )
  545. // self playsound( "allied_death" );
  546. // else
  547. // self playsound( "german_death" );
  548. self animscripts\face::SayGenericDialogue( "death" );
  549. }
  550.  
  551. print3dfortime( place, text, time )
  552. {
  553. numframes = time * 20;
  554. for( i = 0; i < numframes; i++ )
  555. {
  556. print3d( place, text );
  557. wait .05;
  558. }
  559. }
  560.  
  561. helmetPop()
  562. {
  563. if( !isdefined( self ) )
  564. {
  565. return;
  566. }
  567.  
  568. if( !isdefined( self.hatModel ) || !ModelHasPhysPreset( self.hatModel ) )
  569. {
  570. return;
  571. }
  572.  
  573. if( self is_zombie() )
  574. {
  575. return;
  576. }
  577.  
  578. // used to check self removableHat() in cod2... probably not necessary though
  579.  
  580. partName = GetPartName( self.hatModel, 0 );
  581.  
  582. origin = self GetTagOrigin( partName ); //self . origin +( 0, 0, 64 );
  583. angles = self GetTagAngles( partName ); //( -90, 0 + randomint( 90 ), 0 + randomint( 90 ) );
  584.  
  585. helmetLaunch( self.hatModel, origin, angles, self.damageDir );
  586.  
  587. hatModel = self.hatModel;
  588. self.hatModel = undefined;
  589. self.helmetPopper = self.attacker;
  590.  
  591. wait 0.05;
  592.  
  593. if( !isdefined( self ) )
  594. {
  595. return;
  596. }
  597.  
  598. self detach( hatModel, "" );
  599. }
  600.  
  601. helmetLaunch( model, origin, angles, damageDir )
  602. {
  603. launchForce = damageDir;
  604.  
  605. launchForce = launchForce * randomFloatRange( 1100, 4000 );
  606.  
  607. forcex = launchForce[0];
  608. forcey = launchForce[1];
  609. forcez = randomFloatRange( 800, 3000 );
  610.  
  611. contactPoint = self.origin +( randomfloatrange( -1, 1 ), randomfloatrange( -1, 1 ), randomfloatrange( -1, 1 ) ) * 5;
  612.  
  613. CreateDynEntAndLaunch( model, origin, angles, contactPoint, ( forcex, forcey, forcez ) );
  614. }
  615.  
  616. removeSelfFrom_SquadLastSeenEnemyPos( org )
  617. {
  618. for( i = 0; i < anim.squadIndex.size; i++ )
  619. {
  620. anim.squadIndex[i] clearSightPosNear( org );
  621. }
  622. }
  623.  
  624.  
  625. clearSightPosNear( org )
  626. {
  627. if( !isdefined( self.sightPos ) )
  628. {
  629. return;
  630. }
  631.  
  632. if( distance( org, self.sightPos ) < 80 )
  633. {
  634. self.sightPos = undefined;
  635. self.sightTime = gettime();
  636. }
  637. }
  638.  
  639.  
  640. shouldDoRunningForwardDeath()
  641. {
  642. if( self.a.movement != "run" )
  643. {
  644. return false;
  645. }
  646.  
  647. if( self getMotionAngle() > 60 || self getMotionAngle() < -60 )
  648. {
  649. return false;
  650. }
  651.  
  652. if( ( self.damageyaw >= 135 ) ||( self.damageyaw <= -135 ) ) // Front quadrant
  653. {
  654. return true;
  655. }
  656.  
  657. if( ( self.damageyaw >= -45 ) &&( self.damageyaw <= 45 ) ) // Back quadrant
  658. {
  659. return true;
  660. }
  661.  
  662. return false;
  663. }
  664.  
  665.  
  666. get_death_anim()
  667. {
  668. if( self.a.pose == "stand" )
  669. {
  670. if( shouldDoRunningForwardDeath() )
  671. {
  672. return getRunningForwardDeathAnim();
  673. }
  674.  
  675. return getStandDeathAnim();
  676. }
  677. else if( self.a.pose == "crouch" )
  678. {
  679. return getCrouchDeathAnim();
  680. }
  681. else if( self.a.pose == "prone" )
  682. {
  683. return getProneDeathAnim();
  684. }
  685. else
  686. {
  687. assert( self.a.pose == "back" );
  688. return getBackDeathAnim();
  689. }
  690. }
  691.  
  692.  
  693. getRunningForwardDeathAnim()
  694. {
  695. deathArray = [];
  696. deathArray[deathArray.size] = tryAddDeathAnim( %run_death_facedown );
  697. deathArray[deathArray.size] = tryAddDeathAnim( %run_death_roll );
  698.  
  699. if( ( self.damageyaw >= 135 ) ||( self.damageyaw <= -135 ) ) // Front quadrant
  700. {
  701. deathArray[deathArray.size] = tryAddDeathAnim( %run_death_fallonback );
  702. deathArray[deathArray.size] = tryAddDeathAnim( %run_death_fallonback_02 );
  703. }
  704. else if( ( self.damageyaw >= -45 ) &&( self.damageyaw <= 45 ) ) // Back quadrant
  705. {
  706. deathArray[deathArray.size] = tryAddDeathAnim( %run_death_roll );
  707. deathArray[deathArray.size] = tryAddDeathAnim( %run_death_facedown );
  708. }
  709.  
  710. deathArray = tempClean( deathArray );
  711. deathArray = animscripts\pain::removeBlockedAnims( deathArray );
  712.  
  713. if( !deathArray.size )
  714. {
  715. return getStandDeathAnim();
  716. }
  717.  
  718. return deathArray[randomint( deathArray.size )];
  719. }
  720.  
  721. // temp fix for arrays containing undefined
  722. tempClean( array )
  723. {
  724. newArray = [];
  725. for( index = 0; index < array.size; index++ )
  726. {
  727. if( !isDefined( array[index] ) )
  728. {
  729. continue;
  730. }
  731.  
  732. newArray[newArray.size] = array[index];
  733. }
  734. return newArray;
  735. }
  736.  
  737. // TODO: proper location damage tracking
  738. getStandDeathAnim()
  739. {
  740. deathArray = [];
  741.  
  742. if( weaponAnims() == "pistol" )
  743. {
  744. if( abs( self.damageYaw ) < 50 )
  745. {
  746. deathArray[deathArray.size] = %pistol_death_2; // falls forwards
  747. }
  748. else
  749. {
  750. if( abs( self.damageYaw ) < 110 )
  751. {
  752. deathArray[deathArray.size] = %pistol_death_2; // falls forwards
  753. }
  754.  
  755. if( damageLocationIsAny( "torso_lower", "torso_upper", "left_leg_upper", "left_leg_lower", "right_leg_upper", "right_leg_lower" ) )
  756. {
  757. deathArray[deathArray.size] = %pistol_death_3; // hit in groin from front
  758. if( !damageLocationIsAny( "torso_upper" ) )
  759. {
  760. deathArray[deathArray.size] = %pistol_death_3; //( twice as likely )
  761. }
  762. }
  763.  
  764. if( !damageLocationIsAny( "head", "neck", "helmet", "left_foot", "right_foot", "left_hand", "right_hand", "gun" ) && randomint( 2 ) == 0 )
  765. {
  766. deathArray[deathArray.size] = %pistol_death_4; // hit at top and falls backwards, but more dragged out
  767. }
  768.  
  769. if( deathArray.size == 0 || damageLocationIsAny( "torso_lower", "torso_upper", "neck", "head", "helmet", "right_arm_upper", "left_arm_upper" ) )
  770. {
  771. deathArray[deathArray.size] = %pistol_death_1; // falls backwards
  772. }
  773. }
  774. }
  775.  
  776. if( self usingGasWeapon() )
  777. {
  778. deathArray[deathArray.size] = %ai_flamethrower_stand_death;
  779. }
  780. else
  781. {
  782. // common ones
  783. if( randomint( 3 ) < 2 )
  784. {
  785. deathArray[deathArray.size] = tryAddDeathAnim( %exposed_death );
  786. }
  787. if( randomint( 3 ) < 2 )
  788. {
  789. deathArray[deathArray.size] = tryAddDeathAnim( %exposed_death_firing_02 );
  790. }
  791.  
  792. // torso or legs
  793. if( damageLocationIsAny( "torso_lower", "left_leg_upper", "left_leg_lower", "right_leg_lower", "right_leg_lower" ) )
  794. {
  795. deathArray[deathArray.size] = tryAddDeathAnim( %exposed_death_groin );
  796. }
  797.  
  798. if( damageLocationIsAny( "left_leg_upper", "left_leg_lower", "left_foot" ) )
  799. {
  800. deathArray[deathArray.size] = tryAddDeathAnim( %ai_deadly_wounded_leg_L_hit );
  801. }
  802. else if( damageLocationIsAny( "right_leg_upper", "right_leg_lower", "right_foot" ) )
  803. {
  804. deathArray[deathArray.size] = tryAddDeathAnim( %ai_deadly_wounded_leg_R_hit );
  805. }
  806. else if( damageLocationIsAny( "torso_upper", "torso_lower" ) )
  807. {
  808. deathArray[deathArray.size] = tryAddDeathAnim( %ai_deadly_wounded_torso_hit );
  809. }
  810.  
  811. if( damageLocationIsAny( "head", "neck", "helmet" ) )
  812. {
  813. deathArray[deathArray.size] = tryAddDeathAnim( %exposed_death_headshot );
  814. deathArray[deathArray.size] = tryAddDeathAnim( %exposed_death_headtwist );
  815. }
  816.  
  817. // neck torso
  818. if( damageLocationIsAny( "torso_upper", "neck" ) )
  819. {
  820. deathArray[deathArray.size] = tryAddDeathAnim( %exposed_death_nerve );
  821. if( self.damageTaken <= 70 ) // lots of damage means it probably wasn't just a bullet
  822. {
  823. deathArray[deathArray.size] = tryAddDeathAnim( %exposed_death_neckgrab );
  824. }
  825. }
  826.  
  827. if( ( self.damageyaw > 135 ) ||( self.damageyaw <= -135 ) ) // Front quadrant
  828. {
  829. deathArray[deathArray.size] = tryAddDeathAnim( %exposed_death_02 );
  830. if( damageLocationIsAny( "torso_upper", "left_arm_upper", "right_arm_upper" ) )
  831. {
  832. deathArray[deathArray.size] = tryAddDeathAnim( %exposed_death_firing );
  833. }
  834.  
  835. if( damageLocationIsAny( "torso_upper", "neck", "head", "helmet" ) )
  836. {
  837. deathArray[deathArray.size] = tryAddDeathAnim( %exposed_death_falltoknees_02 );
  838. }
  839. }
  840. else if( ( self.damageyaw > 45 ) &&( self.damageyaw <= 135 ) ) // Right quadrant
  841. {
  842. deathArray[deathArray.size] = tryAddDeathAnim( %exposed_death_falltoknees_02 );
  843. }
  844. else if( ( self.damageyaw > -45 ) &&( self.damageyaw <= 45 ) ) // Back quadrant
  845. {
  846. // MikeD( 9/19/2007 ): Flamethrower specific deaths if shot in the back.
  847. if( usingGasWeapon() )
  848. {
  849. deathArray = [];
  850. deathArray[0] = tryAddDeathAnim( %death_explosion_up10 );
  851. }
  852. else
  853. {
  854. deathArray[deathArray.size] = tryAddDeathAnim( %exposed_death_falltoknees );
  855. deathArray[deathArray.size] = tryAddDeathAnim( %exposed_death_falltoknees_02 );
  856. }
  857. }
  858. else // Left quadrant
  859. {
  860. if( damageLocationIsAny( "torso_upper", "left_arm_upper", "head" ) )
  861. {
  862. deathArray[deathArray.size] = tryAddDeathAnim( %exposed_death_twist );
  863. }
  864.  
  865. deathArray[deathArray.size] = tryAddDeathAnim( %exposed_death_falltoknees_02 );
  866. }
  867.  
  868. assertex( deathArray.size > 0, deathArray.size );
  869. }
  870.  
  871. deathArray = tempClean( deathArray );
  872.  
  873. if( deathArray.size == 0 )
  874. {
  875. deathArray[deathArray.size] = %exposed_death;
  876. }
  877.  
  878. return deathArray[randomint( deathArray.size )];
  879. }
  880.  
  881.  
  882. getCrouchDeathAnim()
  883. {
  884. deathArray = [];
  885.  
  886. if( self usingGasWeapon() )
  887. {
  888. deathArray[deathArray.size] = %ai_flamethrower_crouch_death;
  889. }
  890. else
  891. {
  892. if( damageLocationIsAny( "head", "neck" ) ) // Front/Left quadrant
  893. {
  894. deathArray[deathArray.size] = tryAddDeathAnim( %exposed_crouch_death_fetal );
  895. }
  896.  
  897. if( damageLocationIsAny( "torso_upper", "torso_lower", "left_arm_upper", "right_arm_upper", "neck" ) )
  898. {
  899. deathArray[deathArray.size] = tryAddDeathAnim( %exposed_crouch_death_flip );
  900. }
  901.  
  902. if( deathArray.size < 2 )
  903. {
  904. deathArray[deathArray.size] = tryAddDeathAnim( %exposed_crouch_death_twist );
  905. }
  906.  
  907. if( deathArray.size < 2 )
  908. {
  909. deathArray[deathArray.size] = tryAddDeathAnim( %exposed_crouch_death_flip );
  910. }
  911. }
  912.  
  913. deathArray = tempClean( deathArray );
  914. assertex( deathArray.size > 0, deathArray.size );
  915. return deathArray[randomint( deathArray.size )];
  916. }
  917.  
  918. getProneDeathAnim()
  919. {
  920. return %prone_death_quickdeath;
  921. }
  922.  
  923.  
  924. getBackDeathAnim()
  925. {
  926. deathArray = array( %dying_back_death_v1, %dying_back_death_v2, %dying_back_death_v3, %dying_back_death_v4 );
  927. return deathArray[randomint( deathArray.size )];
  928. }
  929.  
  930.  
  931. tryAddDeathAnim( animName )
  932. {
  933. if( !animHasNoteTrack( animName, "fire" ) && !animHasNoteTrack( animName, "fire_spray" ) )
  934. {
  935. return animName;
  936. }
  937.  
  938. if( self.a.weaponPos["right"] == "none" )
  939. {
  940. return undefined;
  941. }
  942.  
  943. if( weaponIsSemiAuto( self.weapon ) )
  944. {
  945. return undefined;
  946. }
  947.  
  948. if( WeaponAnims() != "rifle" )
  949. {
  950. return undefined;
  951. }
  952.  
  953. if( isDefined( self.dieQuietly ) && self.dieQuietly )
  954. {
  955. return undefined;
  956. }
  957.  
  958. return animName;
  959. }
  960.  
  961.  
  962. play_explosion_death()
  963. {
  964. /#
  965. if( GetDvar( "gib_test" ) != "" )
  966. {
  967. deathAnim = %death_explosion_up10;
  968. get_gib_ref( "right" );
  969.  
  970. localDeltaVector = getMoveDelta( deathAnim, 0, 1 );
  971. endPoint = self localToWorldCoords( localDeltaVector );
  972.  
  973. if( !self mayMoveToPoint( endPoint ) )
  974. {
  975. return false;
  976. }
  977.  
  978. // this should really be in the notetracks
  979. self animMode( "nogravity" );
  980.  
  981. play_death_anim( deathAnim );
  982. return true;
  983. }
  984. #/
  985.  
  986. if( self.damageLocation != "none" )
  987. {
  988. return false;
  989. }
  990.  
  991. deathArray = [];
  992.  
  993. if( self.a.movement != "run" )
  994. {
  995. if( self.mayDoUpwardsDeath && getTime() > anim.lastUpwardsDeathTime + 6000 )
  996. {
  997. deathArray[deathArray.size] = tryAddDeathAnim( %death_explosion_stand_UP_v1 );
  998. deathArray[deathArray.size] = tryAddDeathAnim( %death_explosion_stand_UP_v2 );
  999. anim.lastUpwardsDeathTime = getTime();
  1000.  
  1001. // MikeD( 10/23/2007 10:37:48 ): Gib support
  1002. get_gib_ref( "up" );
  1003. }
  1004. else
  1005. {
  1006. if( ( self.damageyaw > 135 ) ||( self.damageyaw <= -135 ) ) // Front quadrant
  1007. {
  1008. deathArray[deathArray.size] = tryAddDeathAnim( %death_explosion_stand_B_v1 );
  1009. deathArray[deathArray.size] = tryAddDeathAnim( %death_explosion_stand_B_v2 );
  1010. deathArray[deathArray.size] = tryAddDeathAnim( %death_explosion_stand_B_v3 );
  1011. deathArray[deathArray.size] = tryAddDeathAnim( %death_explosion_stand_B_v4 );
  1012.  
  1013. // MikeD( 10/23/2007 10:37:48 ): Gib support
  1014. get_gib_ref( "back" );
  1015. }
  1016. else if( ( self.damageyaw > 45 ) &&( self.damageyaw <= 135 ) ) // Right quadrant
  1017. {
  1018. deathArray[deathArray.size] = tryAddDeathAnim( %death_explosion_stand_L_v1 );
  1019. deathArray[deathArray.size] = tryAddDeathAnim( %death_explosion_stand_L_v2 );
  1020. deathArray[deathArray.size] = tryAddDeathAnim( %death_explosion_stand_L_v3 );
  1021.  
  1022. // MikeD( 10/23/2007 10:37:48 ): Gib support
  1023. get_gib_ref( "left" );
  1024. }
  1025. else if( ( self.damageyaw > -45 ) &&( self.damageyaw <= 45 ) ) // Back quadrant
  1026. {
  1027. deathArray[deathArray.size] = tryAddDeathAnim( %death_explosion_stand_F_v1 );
  1028. deathArray[deathArray.size] = tryAddDeathAnim( %death_explosion_stand_F_v2 );
  1029. deathArray[deathArray.size] = tryAddDeathAnim( %death_explosion_stand_F_v3 );
  1030. deathArray[deathArray.size] = tryAddDeathAnim( %death_explosion_stand_F_v4 );
  1031.  
  1032. // MikeD( 10/23/2007 10:37:48 ): Gib support
  1033. get_gib_ref( "forward" );
  1034. }
  1035. else
  1036. { // Left quadrant
  1037. deathArray[deathArray.size] = tryAddDeathAnim( %death_explosion_stand_R_v1 );
  1038. deathArray[deathArray.size] = tryAddDeathAnim( %death_explosion_stand_R_v2 );
  1039.  
  1040. // MikeD( 10/23/2007 10:37:48 ): Gib support
  1041. get_gib_ref( "right" );
  1042. }
  1043. }
  1044. }
  1045. else
  1046. {
  1047. if( self.mayDoUpwardsDeath && getTime() > anim.lastUpwardsDeathTime + 2000 )
  1048. {
  1049. deathArray[deathArray.size] = tryAddDeathAnim( %death_explosion_stand_UP_v1 );
  1050. deathArray[deathArray.size] = tryAddDeathAnim( %death_explosion_stand_UP_v2 );
  1051. anim.lastUpwardsDeathTime = getTime();
  1052.  
  1053. // MikeD( 10/23/2007 10:37:48 ): Gib support
  1054. get_gib_ref( "up" );
  1055. }
  1056. else
  1057. {
  1058. if( ( self.damageyaw > 135 ) ||( self.damageyaw <= -135 ) ) // Front quadrant
  1059. {
  1060. deathArray[deathArray.size] = tryAddDeathAnim( %death_explosion_run_B_v1 );
  1061. deathArray[deathArray.size] = tryAddDeathAnim( %death_explosion_run_B_v2 );
  1062.  
  1063. // MikeD( 10/23/2007 10:37:48 ): Gib support
  1064. get_gib_ref( "back" );
  1065. }
  1066. else if( ( self.damageyaw > 45 ) &&( self.damageyaw <= 135 ) ) // Right quadrant
  1067. {
  1068. deathArray[deathArray.size] = tryAddDeathAnim( %death_explosion_run_L_v1 );
  1069. deathArray[deathArray.size] = tryAddDeathAnim( %death_explosion_run_L_v2 );
  1070.  
  1071. // MikeD( 10/23/2007 10:37:48 ): Gib support
  1072. get_gib_ref( "left" );
  1073. }
  1074. else if( ( self.damageyaw > -45 ) &&( self.damageyaw <= 45 ) ) // Back quadrant
  1075. {
  1076. deathArray[deathArray.size] = tryAddDeathAnim( %death_explosion_run_F_v1 );
  1077. deathArray[deathArray.size] = tryAddDeathAnim( %death_explosion_run_F_v2 );
  1078. deathArray[deathArray.size] = tryAddDeathAnim( %death_explosion_run_F_v3 );
  1079. deathArray[deathArray.size] = tryAddDeathAnim( %death_explosion_run_F_v4 );
  1080.  
  1081. // MikeD( 10/23/2007 10:37:48 ): Gib support
  1082. get_gib_ref( "forward" );
  1083. }
  1084. else
  1085. { // Left quadrant
  1086. deathArray[deathArray.size] = tryAddDeathAnim( %death_explosion_run_R_v1 );
  1087. deathArray[deathArray.size] = tryAddDeathAnim( %death_explosion_run_R_v2 );
  1088.  
  1089. // MikeD( 10/23/2007 10:37:48 ): Gib support
  1090. get_gib_ref( "right" );
  1091. }
  1092. }
  1093. }
  1094.  
  1095. deathAnim = deathArray[randomint( deathArray.size )];
  1096.  
  1097. if( getdvar( "scr_expDeathMayMoveCheck" ) == "on" )
  1098. {
  1099. localDeltaVector = getMoveDelta( deathAnim, 0, 1 );
  1100. endPoint = self localToWorldCoords( localDeltaVector );
  1101.  
  1102. if( !self mayMoveToPoint( endPoint, false ) )
  1103. {
  1104. return false;
  1105. }
  1106. }
  1107.  
  1108. // this should really be in the notetracks
  1109. self animMode( "nogravity" );
  1110.  
  1111. if( try_gib_extended_death( 50 ) )
  1112. {
  1113. return true;
  1114. }
  1115.  
  1116. play_death_anim( deathAnim );
  1117.  
  1118. return true;
  1119. }
  1120.  
  1121.  
  1122. // MikeD( 9/30/2007 ): New on-fire death animations.
  1123. play_flame_death_anim()
  1124. {
  1125. if(self.damagemod =="MOD_MELEE" )
  1126. return false;
  1127.  
  1128. if( is_german_build() ) // these are too violent for those . .
  1129. return false;
  1130.  
  1131. if(self.team == "axis")
  1132. {
  1133. level.bcOnFireTime = gettime();
  1134. level.bcOnFireOrg = self.origin;
  1135. }
  1136.  
  1137. if( !IsDefined( self.a.forceflamedeath ) || !self.a.forceflamedeath )
  1138. {
  1139. if( WeaponClass( self.damageWeapon ) == "turret" )
  1140. {
  1141. if( !IsDefined( WeaponType( self.damageWeapon ) ) || WeaponType( self.damageWeapon ) != "gas" )
  1142. {
  1143. return false;
  1144. }
  1145. }
  1146. else if( weaponClass( self.damageWeapon ) != "gas" && self.damageWeapon != "molotov" && WeaponType( self.damageWeapon ) != "gas" )
  1147. {
  1148. return false;
  1149. }
  1150. }
  1151.  
  1152. // TODO: Check for if self has a flamethrower already, if so, play a different set of anims.
  1153.  
  1154. deathArray = [];
  1155. if( self usingGasWeapon() )
  1156. {
  1157. if( self.a.pose == "crouch" )
  1158. {
  1159. deathArray[0] = %ai_flame_death_crouch_a;
  1160. deathArray[1] = %ai_flame_death_crouch_b;
  1161. deathArray[2] = %ai_flame_death_crouch_c;
  1162. deathArray[3] = %ai_flame_death_crouch_d;
  1163. deathArray[4] = %ai_flame_death_crouch_e;
  1164. deathArray[5] = %ai_flame_death_crouch_f;
  1165. deathArray[6] = %ai_flame_death_crouch_g;
  1166. deathArray[7] = %ai_flame_death_crouch_h;
  1167. }
  1168. else
  1169. {
  1170. deathArray[0] = %ai_flamethrower_death_b;
  1171. }
  1172. }
  1173. else
  1174. {
  1175. if( self.a.pose == "prone" )
  1176. {
  1177. deathArray[0] = get_death_anim();
  1178. }
  1179. else if( self.a.pose == "back" )
  1180. {
  1181. deathArray[0] = get_death_anim();
  1182. }
  1183. else if( self.a.pose == "crouch" )
  1184. {
  1185. deathArray[0] = %ai_flame_death_crouch_a;
  1186. deathArray[1] = %ai_flame_death_crouch_b;
  1187. deathArray[2] = %ai_flame_death_crouch_c;
  1188. deathArray[3] = %ai_flame_death_crouch_d;
  1189. deathArray[4] = %ai_flame_death_crouch_e;
  1190. deathArray[5] = %ai_flame_death_crouch_f;
  1191. deathArray[6] = %ai_flame_death_crouch_g;
  1192. deathArray[7] = %ai_flame_death_crouch_h;
  1193. }
  1194. else
  1195. {
  1196. deathArray[0] = %ai_flame_death_A;
  1197. deathArray[1] = %ai_flame_death_B;
  1198. deathArray[2] = %ai_flame_death_C;
  1199. deathArray[3] = %ai_flame_death_D;
  1200. deathArray[4] = %ai_flame_death_E;
  1201. deathArray[5] = %ai_flame_death_F;
  1202. deathArray[6] = %ai_flame_death_G;
  1203. deathArray[7] = %ai_flame_death_H;
  1204. deathArray[8] = %ai_deadly_wounded_flamedA_hit;
  1205. deathArray[9] = %ai_deadly_wounded_flamedB_hit;
  1206. }
  1207. }
  1208.  
  1209. self.fire_footsteps = true;
  1210.  
  1211. // MikeD( 10/9/2007 ): If deatharray is 0, then return false and play a normal death anim;
  1212. if( deathArray.size == 0 )
  1213. {
  1214. /#
  1215. println( "^3ANIMSCRIPT WARNING: None of the Flame-Deaths exist!!" );
  1216. #/
  1217. return false;
  1218. }
  1219.  
  1220. deathArray = animscripts\pain::removeBlockedAnims( deathArray );
  1221.  
  1222. // MikeD( 10/9/2007 ): If deatharray is 0, then return false and play a normal death anim;
  1223. if( deathArray.size == 0 )
  1224. {
  1225. /#
  1226. println( "^3ANIMSCRIPT WARNING: All of the Flame-Death Animations are blocked by geometry, cannot use any!!" );
  1227. #/
  1228. return false;
  1229. }
  1230.  
  1231. randomChoice = randomint( deathArray.size );
  1232.  
  1233. self thread flame_death_fx();
  1234.  
  1235. deathAnim = deathArray[randomChoice];
  1236. play_death_anim( deathAnim );
  1237.  
  1238. return true;
  1239. }
  1240.  
  1241. flame_death_fx()
  1242. {
  1243. self endon( "death" );
  1244.  
  1245. //rand = RandomIntRange( 3, tagArray.size );
  1246.  
  1247. if (isdefined(self.is_on_fire) && self.is_on_fire )
  1248. {
  1249. return;
  1250. }
  1251.  
  1252.  
  1253. if( self is_zombie() )
  1254. {
  1255. if( !isDefined( level.num_flaming_zombies ) )
  1256. {
  1257. level.num_flaming_zombies = 0;
  1258. }
  1259. if( level.num_flaming_zombies >= 15 )
  1260. {
  1261. return;
  1262. }
  1263. level.num_flaming_zombies++;
  1264. level thread wait_for_zombie_flame_fx();
  1265. }
  1266.  
  1267. self.is_on_fire = true;
  1268.  
  1269. self thread on_fire_timeout();
  1270.  
  1271. // JamesS - this will darken the burning body
  1272. self StartTanning();
  1273.  
  1274. if(self.team == "axis")
  1275. {
  1276. level.bcOnFireTime = gettime();
  1277. level.bcOnFireOrg = self.origin;
  1278. }
  1279.  
  1280. if( IsDefined( level._effect ) && IsDefined( level._effect["character_fire_death_torso"] ) )
  1281. {
  1282. if(self.classname != "actor_zombie_dog")
  1283. {
  1284. PlayFxOnTag( level._effect["character_fire_death_torso"], self, "J_SpineLower" );
  1285. }
  1286.  
  1287. }
  1288. else
  1289. {
  1290. /#
  1291. println( "^3ANIMSCRIPT WARNING: You are missing level._effect[\"character_fire_death_torso\"], please set it in your levelname_fx.gsc. Use \"env/fire/fx_fire_player_torso\"" );
  1292. #/
  1293. }
  1294.  
  1295. if( IsDefined( level._effect ) && IsDefined( level._effect["character_fire_death_sm"] ) && (!isDefined( self.is_zombie ) || !self.is_zombie) )
  1296. {
  1297. wait 1;
  1298.  
  1299. tagArray = [];
  1300. tagArray[0] = "J_Elbow_LE";
  1301. tagArray[1] = "J_Elbow_RI";
  1302. tagArray[2] = "J_Knee_RI";
  1303. tagArray[3] = "J_Knee_LE";
  1304. tagArray = randomize_array( tagArray );
  1305.  
  1306. PlayFxOnTag( level._effect["character_fire_death_sm"], self, tagArray[0] );
  1307.  
  1308. wait 1;
  1309.  
  1310. tagArray[0] = "J_Wrist_RI";
  1311. tagArray[1] = "J_Wrist_LE";
  1312. if( !IsDefined( self.a.gib_ref ) || self.a.gib_ref != "no_legs" )
  1313. {
  1314. tagArray[2] = "J_Ankle_RI";
  1315. tagArray[3] = "J_Ankle_LE";
  1316. }
  1317. tagArray = randomize_array( tagArray );
  1318.  
  1319. PlayFxOnTag( level._effect["character_fire_death_sm"], self, tagArray[0] );
  1320. PlayFxOnTag( level._effect["character_fire_death_sm"], self, tagArray[1] );
  1321. }
  1322. else
  1323. {
  1324. /#
  1325. println( "^3ANIMSCRIPT WARNING: You are missing level._effect[\"character_fire_death_sm\"], please set it in your levelname_fx.gsc. Use \"env/fire/fx_fire_player_sm\"" );
  1326. #/
  1327. }
  1328. }
  1329.  
  1330. // LDS - This is a throttling function to keep zombie flame fx from bringing the framerate to its knees
  1331. wait_for_zombie_flame_fx()
  1332. {
  1333. // This is the length of the character_fire_death_torso
  1334. wait( 16 );
  1335. level.num_flaming_zombies--;
  1336. }
  1337. on_fire_timeout()
  1338. {
  1339. self endon ("death");
  1340.  
  1341. // about the length of the flame fx
  1342. wait 12;
  1343.  
  1344. if (isdefined(self) && isalive(self))
  1345. {
  1346. self.is_on_fire = false;
  1347. self notify ("stop_flame_damage");
  1348. }
  1349.  
  1350. }
  1351.  
  1352. play_bulletgibbed_death_anim()
  1353. {
  1354. maxDist = 300;
  1355.  
  1356. if( self.damagemod == "MOD_MELEE" )
  1357. {
  1358. return false;
  1359. }
  1360.  
  1361. // Sumeet - allows script to turn off gibbing.
  1362. if ( IsDefined( self.no_gib ) && ( self.no_gib == 1 ) )
  1363. {
  1364. return false;
  1365. }
  1366.  
  1367. gib_chance = 75;
  1368. shotty_gib = false;
  1369. if( WeaponClass( self.damageWeapon ) == "spread" ) // shotgun
  1370. {
  1371. // this stuff is far from set in stone, feel free to tweak - JRS
  1372. maxDist = 300;
  1373. shotty_gib = true;
  1374. distSquared = DistanceSquared( self.origin, self.attacker.origin );
  1375. if( distSquared < 110*110 )
  1376. {
  1377. gib_chance = 100;
  1378. }
  1379. else if( distSquared < 200*200 )
  1380. {
  1381. gib_chance = 75;
  1382. }
  1383. else if( distSquared < 270*270 )
  1384. {
  1385. gib_chance = 50;
  1386. }
  1387. else if( distSquared < 330*330 )
  1388. {
  1389. if( RandomInt( 100 ) < 50 )
  1390. {
  1391. gib_chance = 50;
  1392. }
  1393. else
  1394. {
  1395. return false;
  1396. }
  1397. }
  1398. else
  1399. {
  1400. return false;
  1401. }
  1402. }
  1403. else if( WeaponClass( self.damageWeapon ) == "turret" || WeaponMountable( self.damageWeapon ) )
  1404. {
  1405. maxDist = 750;
  1406. }
  1407. else if( self.damageWeapon == "dp28" || self.damageWeapon == "dp28_wet" ||
  1408. self.damageWeapon == "type99_lmg" || self.damageWeapon == "type99_lmg_wet" ||
  1409. self.damageWeapon == "30cal" || self.damageWeapon == "30cal_wet" ||
  1410. self.damageWeapon == "mg42" || self.damageWeapon == "fg42" ||
  1411. self.damageWeapon == "30cal_bipod" || self.damageWeapon == "30cal_bipod_wet" ) // heavy weapons
  1412. {
  1413. maxDist = 1000;
  1414. }
  1415. else if( self.damageWeapon == "ptrs41" )
  1416. {
  1417. maxDist = 3500;
  1418. }
  1419. else if( self.damageWeapon == "triple25_turret" )
  1420. {
  1421. maxDist = 3500;
  1422. gib_chance = 100;
  1423. // force triple25 to gib everytime
  1424. anim.lastGibTime = anim.lastGibTime - 3000;
  1425. }
  1426. else if( isdefined( self.gib_override ) && self.gib_override )
  1427. {
  1428. maxDist = 6000;
  1429. }
  1430. else
  1431. {
  1432. return false;
  1433. }
  1434.  
  1435. if( !IsDefined( self.attacker ) || !isdefined( self.damageLocation ) )
  1436. {
  1437. return false;
  1438. }
  1439.  
  1440. // shotgun damage is less than 50
  1441. if( self.damagetaken < 50 && !shotty_gib )
  1442. {
  1443. return false;
  1444. }
  1445.  
  1446. self.a.gib_ref = undefined;
  1447.  
  1448. distSquared = DistanceSquared( self.origin, self.attacker.origin );
  1449.  
  1450. if( RandomInt( 100 ) < gib_chance && distSquared < maxDist*maxDist && GetTime() > anim.lastGibTime + anim.gibDelay )
  1451. {
  1452. anim.lastGibTime = GetTime();
  1453.  
  1454. refs = [];
  1455. switch( self.damageLocation )
  1456. {
  1457. case "torso_upper":
  1458. case "torso_lower":
  1459. refs[refs.size] = "guts";
  1460. refs[refs.size] = "right_arm";
  1461. refs[refs.size] = "left_arm";
  1462. break;
  1463. case "right_arm_upper":
  1464. case "right_arm_lower":
  1465. case "right_hand":
  1466. refs[refs.size] = "right_arm";
  1467. break;
  1468. case "left_arm_upper":
  1469. case "left_arm_lower":
  1470. case "left_hand":
  1471. refs[refs.size] = "left_arm";
  1472. break;
  1473. case "right_leg_upper":
  1474. case "right_leg_lower":
  1475. case "right_foot":
  1476. refs[refs.size] = "right_leg";
  1477. refs[refs.size] = "no_legs";
  1478. break;
  1479. case "left_leg_upper":
  1480. case "left_leg_lower":
  1481. case "left_foot":
  1482. refs[refs.size] = "left_leg";
  1483. refs[refs.size] = "no_legs";
  1484. break;
  1485. case "helmet":
  1486. case "head":
  1487. refs[refs.size] = "head";
  1488. break;
  1489. }
  1490.  
  1491. // CODER_MOD: Austin( 7/16/08 ): override gib refs if a thunder death
  1492. if( IsDefined( self.thunder_death ) && self.thunder_death )
  1493. {
  1494. refs = [];
  1495. refs[refs.size] = "guts";
  1496. refs[refs.size] = "right_arm";
  1497. refs[refs.size] = "left_arm";
  1498. refs[refs.size] = "right_leg";
  1499. refs[refs.size] = "left_leg";
  1500. refs[refs.size] = "no_legs";
  1501. refs[refs.size] = "head";
  1502. }
  1503.  
  1504. if( refs.size )
  1505. {
  1506. self.a.gib_ref = get_random( refs );
  1507. }
  1508. }
  1509.  
  1510. range = 600;
  1511. nrange = -600;
  1512. self.gib_vel = self.damagedir * RandomIntRange( 500, 900 );
  1513. self.gib_vel += ( RandomIntRange( nrange, range ), RandomIntRange( nrange, range ), RandomIntRange( 400, 1000 ) );
  1514.  
  1515. if( try_gib_extended_death( 50 ) )
  1516. {
  1517. return true;
  1518. }
  1519.  
  1520. self thread do_gib();
  1521.  
  1522. self animscripts\shared::DropAllAIWeapons();
  1523.  
  1524. // play a death anim just in case
  1525. deathAnim = get_death_anim();
  1526. self setFlaggedAnimKnobAllRestart( "deathanim", deathAnim, %body, 1, .1 );
  1527.  
  1528. wait 0.05;
  1529.  
  1530. self launch_ragdoll_based_on_damage_type( 2.0 );
  1531. self thread death_anim_short_circuit(); // do this just for consistency
  1532.  
  1533. // wait here so that the client can get the model changes before it becomes an AI_CORPSE
  1534. wait 0.5;
  1535.  
  1536. return true;
  1537. }
  1538.  
  1539. try_gib_extended_death( chance )
  1540. {
  1541. if( RandomInt( 100 ) >= chance )
  1542. {
  1543. return false;
  1544. }
  1545.  
  1546. if( self.a.pose == "prone" || self.a.pose == "back" )
  1547. {
  1548. return false;
  1549. }
  1550.  
  1551. if( ( !IsDefined( self.dieQuietly ) || !self.dieQuietly ) && self.type == "human" )
  1552. {
  1553. self thread animscripts\face::SaySpecificDialogue( undefined, "generic_gib_" + self.voice, 1.0 );
  1554. }
  1555.  
  1556. //self animscripts\shared::DropAllAIWeapons();
  1557. //self thread do_gib();
  1558.  
  1559. //possibleGibRefs = [];
  1560. //possibleGibRefs[0] = "guts";
  1561. //possibleGibRefs[1] = "left_arm";
  1562. //possibleGibRefs[2] = "right_arm";
  1563. //possibleGibRefs[3] = "left_leg";
  1564. //possibleGibRefs[4] = "right_leg";
  1565. //possibleGibRefs[5] = "no_legs";
  1566.  
  1567. //for( i = 0; i < 6; i++ )
  1568. //{
  1569. //self.a.gib_ref = possibleGibRefs[i];
  1570. deathseq = get_gib_extended_death_anims();
  1571.  
  1572. if( deathSeq.size == 3 )
  1573. {
  1574. do_extended_death( deathSeq );
  1575. return true;
  1576. }
  1577.  
  1578. //}
  1579.  
  1580. //return true;
  1581.  
  1582. return false;
  1583. }
  1584.  
  1585.  
  1586. do_extended_death( deathSeq )
  1587. {
  1588. self animscripts\shared::DropAllAIWeapons();
  1589.  
  1590. self thread do_gib();
  1591.  
  1592. self thread death_anim_short_circuit();
  1593. self setFlaggedAnimKnobAllRestart( "deathhitanim", deathSeq[0], %body, 1, .1 );
  1594. self animscripts\shared::DoNoteTracks( "deathhitanim" );
  1595. self notify( "stop_death_anim_short_circuit" );
  1596.  
  1597. self thread end_extended_death( deathSeq );
  1598.  
  1599. numDeathLoops = RandomInt( 2 ) + 1;
  1600. self thread extended_death_loop( deathSeq, numDeathLoops );
  1601.  
  1602. // We must wait for the sequence to end, or else self will get removed before we're done.
  1603. self waittill( "extended_death_ended" );
  1604. }
  1605.  
  1606. end_extended_death( deathSeq )
  1607. {
  1608. assert( IsDefined( deathSeq[2] ) );
  1609.  
  1610. // Normally, the final death anim runs at the end of the loop, but the loop
  1611. // can also be cut short by further damage to self.
  1612. self waittill_any( "damage", "ending_extended_death" );
  1613.  
  1614. self setFlaggedAnimKnobAllRestart( "deathdieanim", deathSeq[2], %body, 1, .1 );
  1615. self animscripts\shared::DoNoteTracks( "deathdieanim" );
  1616.  
  1617. // All done with extended death sequence.
  1618. self notify( "extended_death_ended" );
  1619. }
  1620.  
  1621. extended_death_loop( deathSeq, numLoops )
  1622. {
  1623. // If someone shoots or damages self in any way, play final death immediately.
  1624. self endon( "damage" );
  1625.  
  1626. assert( IsDefined( deathSeq[1] ) );
  1627.  
  1628. animLength = GetAnimLength( deathSeq[1] );
  1629. for( i = 0; i < numLoops; i++ )
  1630. {
  1631. self setFlaggedAnimKnobAllRestart( "deathloopanim", deathSeq[1], %body, 1, .1 );
  1632. self animscripts\shared::DoNoteTracks( "deathloopanim" );
  1633. }
  1634.  
  1635. // If the loop hasn't already been cut short by the actor taking further damage,
  1636. // go into the final death anim.
  1637. self notify( "ending_extended_death" );
  1638. }
  1639.  
  1640. get_gib_extended_death_anims()
  1641. {
  1642. hitfrom = undefined;
  1643.  
  1644. if( ( self.damageyaw > 90 ) ||( self.damageyaw <= -90 ) )
  1645. {
  1646. hitfrom = "front";
  1647. }
  1648. else
  1649. {
  1650. hitfrom = "back";
  1651. }
  1652.  
  1653. gib_ref = self.a.gib_ref;
  1654.  
  1655. deathSeq = [];
  1656. if( IsDefined( hitfrom ) && IsDefined( gib_ref ) )
  1657. {
  1658. hitIndex = 0;
  1659. loopIndex = 1;
  1660. dieIndex = 2;
  1661.  
  1662. switch( gib_ref )
  1663. {
  1664. case "guts":
  1665. deathSeq[hitIndex] = %ai_gib_torso_gib;
  1666. deathSeq[loopIndex] = %ai_gib_torso_loop;
  1667. deathSeq[dieIndex] = %ai_gib_torso_death;
  1668. break;
  1669.  
  1670. case "no_legs":
  1671. deathSeq[hitIndex] = %ai_gib_bothlegs_gib;
  1672. deathSeq[loopIndex] = %ai_gib_bothlegs_loop;
  1673. deathSeq[dieIndex] = %ai_gib_bothlegs_death;
  1674. break;
  1675.  
  1676. case "left_leg":
  1677. if( hitfrom == "front" )
  1678. {
  1679. deathSeq[hitIndex] = %ai_gib_leftleg_front_gib;
  1680. deathSeq[loopIndex] = %ai_gib_leftleg_front_loop;
  1681. deathSeq[dieIndex] = %ai_gib_leftleg_front_death;
  1682. }
  1683. else
  1684. {
  1685. deathSeq[hitIndex] = %ai_gib_leftleg_back_gib;
  1686. deathSeq[loopIndex] = %ai_gib_leftleg_back_loop;
  1687. deathSeq[dieIndex] = %ai_gib_leftleg_back_death;
  1688. }
  1689. break;
  1690.  
  1691. case "right_leg":
  1692. if( hitfrom == "front" )
  1693. {
  1694. deathSeq[hitIndex] = %ai_gib_rightleg_front_gib;
  1695. deathSeq[loopIndex] = %ai_gib_rightleg_front_loop;
  1696. deathSeq[dieIndex] = %ai_gib_rightleg_front_death;
  1697. }
  1698. else
  1699. {
  1700. deathSeq[hitIndex] = %ai_gib_rightleg_back_gib;
  1701. deathSeq[loopIndex] = %ai_gib_rightleg_back_loop;
  1702. deathSeq[dieIndex] = %ai_gib_rightleg_back_death;
  1703. }
  1704. break;
  1705.  
  1706. case "left_arm":
  1707. if( hitfrom == "front" )
  1708. {
  1709. deathSeq[hitIndex] = %ai_gib_leftarm_front_gib;
  1710. deathSeq[loopIndex] = %ai_gib_leftarm_front_loop;
  1711. deathSeq[dieIndex] = %ai_gib_leftarm_front_death;
  1712. }
  1713. else
  1714. {
  1715. deathSeq[hitIndex] = %ai_gib_leftarm_back_gib;
  1716. deathSeq[loopIndex] = %ai_gib_leftarm_back_loop;
  1717. deathSeq[dieIndex] = %ai_gib_leftarm_back_death;
  1718. }
  1719. break;
  1720.  
  1721. case "right_arm":
  1722. if( hitfrom == "front" )
  1723. {
  1724. deathSeq[hitIndex] = %ai_gib_rightarm_front_gib;
  1725. deathSeq[loopIndex] = %ai_gib_rightarm_front_loop;
  1726. deathSeq[dieIndex] = %ai_gib_rightarm_front_death;
  1727. }
  1728. else
  1729. {
  1730. deathSeq[hitIndex] = %ai_gib_rightarm_back_gib;
  1731. deathSeq[loopIndex] = %ai_gib_rightarm_back_loop;
  1732. deathSeq[dieIndex] = %ai_gib_rightarm_back_death;
  1733. }
  1734. break;
  1735. }
  1736. }
  1737.  
  1738. return deathSeq;
  1739. }
  1740.  
  1741. // MikeD( 9/30/2007 ): Taken from maps\_utility "array_randomize:, for some reason maps\_utility is included in a animscript
  1742. // somewhere, but I can't call it within in this... So I made a new one.
  1743. randomize_array( array )
  1744. {
  1745. for( i = 0; i < array.size; i++ )
  1746. {
  1747. j = RandomInt( array.size );
  1748. temp = array[i];
  1749. array[i] = array[j];
  1750. array[j] = temp;
  1751. }
  1752. return array;
  1753. }
  1754.  
  1755. play_bayonet_death_anim()
  1756. {
  1757. if( self.damagemod != "MOD_BAYONET" )
  1758. {
  1759. return false;
  1760. }
  1761.  
  1762. // CODER_MOD: Austin( 10/31/2007 ): only play bayonet death if target is standing
  1763. if( self.a.pose != "stand" )
  1764. {
  1765. return false;
  1766. }
  1767.  
  1768. // CODER_MOD: Austin( 10/31/2007 ): add additional bayonet death anims, remove facing target to player
  1769. deathAnim = "";
  1770. side = "front";
  1771.  
  1772. if( ( self.damageyaw > -45 ) &&( self.damageyaw <= 45 ) ) // Back quadrant
  1773. {
  1774. deathAnim = %ai_bayonet_back_death;
  1775. side = "back";
  1776. }
  1777. else if( ( self.damageyaw > 45 ) &&( self.damageyaw <= 135 ) ) // Right quadrant
  1778. {
  1779. deathAnim = %ai_bayonet_right_death;
  1780. side = "right";
  1781. }
  1782. else if( ( self.damageyaw < -45 ) &&( self.damageyaw >= -135 ) ) // Left quadrant
  1783. {
  1784. deathAnim = %ai_bayonet_left_death;
  1785. side = "left";
  1786. }
  1787. else if( damageLocationIsAny( "helmet", "head", "neck", "torso_upper" ) )
  1788. {
  1789. deathAnim = %ai_bayonet_shoulder_death;
  1790. side = "front";
  1791. }
  1792. else
  1793. {
  1794. deathAnim = %ai_bayonet_thrust_death;
  1795. side = "front";
  1796. }
  1797.  
  1798. // CODER MOD: 3/27/08 - Added blood fx to bayonet attack - JRS
  1799. if( GetDvarInt( "cg_blood" ) > 0 )
  1800. {
  1801. self thread bayonet_death_fx( side );
  1802. }
  1803.  
  1804. play_death_anim( deathAnim );
  1805.  
  1806. return true;
  1807. }
  1808.  
  1809. get_tag_for_damage_location()
  1810. {
  1811. tag = "J_SpineLower";
  1812.  
  1813. if( self.damagelocation == "helmet" )
  1814. {
  1815. tag = "j_head";
  1816. }
  1817. else if( self.damagelocation == "head" )
  1818. {
  1819. tag = "j_head";
  1820. }
  1821. else if( self.damagelocation == "neck" )
  1822. {
  1823. tag = "j_neck";
  1824. }
  1825. else if( self.damagelocation == "torso_upper" )
  1826. {
  1827. tag = "j_spineupper";
  1828. }
  1829. else if( self.damagelocation == "torso_lower" )
  1830. {
  1831. tag = "j_spinelower";
  1832. }
  1833. else if( self.damagelocation == "right_arm_upper" )
  1834. {
  1835. tag = "j_elbow_ri";
  1836. }
  1837. else if( self.damagelocation == "left_arm_upper" )
  1838. {
  1839. tag = "j_elbow_le";
  1840. }
  1841. else if( self.damagelocation == "right_arm_lower" )
  1842. {
  1843. tag = "j_wrist_ri";
  1844. }
  1845. else if( self.damagelocation == "left_arm_lower" )
  1846. {
  1847. tag = "j_wrist_le";
  1848. }
  1849.  
  1850. return tag;
  1851. }
  1852.  
  1853. bayonet_death_fx( side )
  1854. {
  1855. tag = self get_tag_for_damage_location();
  1856.  
  1857. if( IsDefined( level._effect ) && IsDefined( level._effect["character_bayonet_blood_in"] ) )
  1858. {
  1859. PlayFxOnTag( level._effect["character_bayonet_blood_in"], self, tag );
  1860. }
  1861. else
  1862. {
  1863. /#
  1864. println( "^3ANIMSCRIPT WARNING: You are missing level._effect[\"character_bayonet_blood_in\"], please set it in your levelname_fx.gsc. Use \"impacts/fx_flesh_bayonet_impact\"" );
  1865. #/
  1866. }
  1867.  
  1868. wait 0.2;
  1869.  
  1870. if( IsDefined( level._effect ) )
  1871. {
  1872. if( !IsDefined( level._effect["character_bayonet_blood_front"] ) ||
  1873. !IsDefined( level._effect["character_bayonet_blood_back"] ) ||
  1874. !IsDefined( level._effect["character_bayonet_blood_left"] ) ||
  1875. !IsDefined( level._effect["character_bayonet_blood_right"] ) )
  1876. {
  1877. println( "^3ANIMSCRIPT WARNING: You are missing level._effect[\"character_bayonet_blood_out\"], please set it in your levelname_fx.gsc." );
  1878. println( "^3\"impacts/fx_flesh_bayonet_fatal_fr\" and " );
  1879. println( "^3\"impacts/fx_flesh_bayonet_fatal_bk\" and " );
  1880. println( "^3\"impacts/fx_flesh_bayonet_fatal_rt\" and " );
  1881. println( "^3\"impacts/fx_flesh_bayonet_fatal_lf\"." );
  1882. }
  1883. else
  1884. {
  1885. if( side == "front" )
  1886. {
  1887. PlayFxOnTag( level._effect["character_bayonet_blood_front"], self, "j_spine4" );
  1888. }
  1889. else if( side == "back" )
  1890. {
  1891. PlayFxOnTag( level._effect["character_bayonet_blood_back"], self, "j_spine4" );
  1892. }
  1893. else if( side == "right" )
  1894. {
  1895. PlayFxOnTag( level._effect["character_bayonet_blood_right"], self, "j_spine4" );
  1896. }
  1897. else if( side == "left" )
  1898. {
  1899. PlayFxOnTag( level._effect["character_bayonet_blood_left"], self, "j_spine4" );
  1900. }
  1901. }
  1902. }
  1903. else
  1904. {
  1905. /#
  1906. println( "^3ANIMSCRIPT WARNING: You are missing level._effect" );
  1907. #/
  1908. }
  1909. }
  1910.  
  1911. get_gib_ref( direction )
  1912. {
  1913. /#
  1914. // Dvars for testing bigs.
  1915. if( GetDvarInt( "gib_delay" ) > 0 )
  1916. {
  1917. anim.gibDelay = GetDvarInt( "gib_delay" );
  1918. }
  1919.  
  1920. if( GetDvar( "gib_test" ) != "" )
  1921. {
  1922. self.a.gib_ref = GetDvar( "gib_test" );
  1923. return;
  1924. }
  1925. #/
  1926.  
  1927. // If already set, then use it. Useful for canned gib deaths.
  1928. if( IsDefined( self.a.gib_ref ) )
  1929. {
  1930. return;
  1931. }
  1932.  
  1933. // Don't gib if we haven't taken enough damage by the explosive
  1934. // Grenade damage usually range from 160 - 250, so we go above teh minimum
  1935. // so if the splash damage is near it's lowest, don't gib.
  1936. if( self.damageTaken < 165 )
  1937. {
  1938. return;
  1939. }
  1940.  
  1941. if( GetTime() > anim.lastGibTime + anim.gibDelay && anim.totalGibs > 0 )
  1942. {
  1943. anim.totalGibs--;
  1944.  
  1945. // MikeD( 5/5/2008 ): Allows multiple guys to GIB at once.
  1946. // anim.lastGibTime = GetTime();
  1947. anim thread set_last_gib_time();
  1948.  
  1949. refs = [];
  1950. switch( direction )
  1951. {
  1952. case "right":
  1953. refs[refs.size] = "left_arm";
  1954. refs[refs.size] = "left_leg";
  1955.  
  1956. gib_ref = get_random( refs );
  1957. break;
  1958.  
  1959. case "left":
  1960. refs[refs.size] = "right_arm";
  1961. refs[refs.size] = "right_leg";
  1962.  
  1963. gib_ref = get_random( refs );
  1964. break;
  1965.  
  1966. case "forward":
  1967. refs[refs.size] = "right_arm";
  1968. refs[refs.size] = "left_arm";
  1969. refs[refs.size] = "right_leg";
  1970. refs[refs.size] = "left_leg";
  1971. refs[refs.size] = "guts";
  1972. refs[refs.size] = "no_legs";
  1973.  
  1974. gib_ref = get_random( refs );
  1975. break;
  1976.  
  1977. case "back":
  1978. refs[refs.size] = "right_arm";
  1979. refs[refs.size] = "left_arm";
  1980. refs[refs.size] = "right_leg";
  1981. refs[refs.size] = "left_leg";
  1982. refs[refs.size] = "no_legs";
  1983.  
  1984. gib_ref = get_random( refs );
  1985. break;
  1986.  
  1987. default: // "up"
  1988. refs[refs.size] = "right_arm";
  1989. refs[refs.size] = "left_arm";
  1990. refs[refs.size] = "right_leg";
  1991. refs[refs.size] = "left_leg";
  1992. refs[refs.size] = "no_legs";
  1993. refs[refs.size] = "guts";
  1994.  
  1995. gib_ref = get_random( refs );
  1996. break;
  1997. }
  1998.  
  1999.  
  2000. self.a.gib_ref = gib_ref;
  2001. }
  2002. else
  2003. {
  2004. self.a.gib_ref = undefined;
  2005. }
  2006. }
  2007.  
  2008. set_last_gib_time()
  2009. {
  2010. anim notify( "stop_last_gib_time" );
  2011. anim endon( "stop_last_gib_time" );
  2012.  
  2013. wait( 0.05 );
  2014. anim.lastGibTime = GetTime();
  2015. anim.totalGibs = RandomIntRange( anim.minGibs, anim.maxGibs );
  2016. }
  2017.  
  2018. get_random( array )
  2019. {
  2020. return array[RandomInt( array.size )];
  2021. }
  2022.  
  2023. network_gib_manager()
  2024. {
  2025. level.max_gibs_per_network_frame = 5;
  2026. while( true )
  2027. {
  2028. level.gibs_this_network_frame = 0;
  2029. wait_network_frame();
  2030. }
  2031. }
  2032.  
  2033. do_gib()
  2034. {
  2035. if( !is_mature() )
  2036. {
  2037. return;
  2038. }
  2039.  
  2040. if( is_german_build() )
  2041. {
  2042. return;
  2043. }
  2044.  
  2045. if( !IsDefined( self.a.gib_ref ) )
  2046. {
  2047. return;
  2048. }
  2049.  
  2050. if (self is_zombie() && isdefined(self.is_on_fire) && self.is_on_fire)
  2051. {
  2052. return;
  2053. }
  2054.  
  2055. // CODER_MOD: Austin( 7/21/08 ): added to prevent zombies from gibbing more than once
  2056. if( self is_zombie_gibbed() )
  2057. {
  2058. return;
  2059. }
  2060.  
  2061. if( !isDefined( level.gibs_this_network_frame ) )
  2062. {
  2063. level thread network_gib_manager();
  2064. }
  2065.  
  2066. if ( IsDefined(self.damageWeapon) )
  2067. {
  2068. if (isSubStr( self.damageWeapon, "flame" ) || isSubStr( self.damageWeapon, "molotov" ) || isSubStr( self.damageWeapon, "napalmblob" ) )
  2069. {
  2070. return;
  2071. }
  2072. }
  2073.  
  2074. self set_zombie_gibbed();
  2075.  
  2076. //CODER_MOD: Jay( 6/18/2008 ): callback to challenge system
  2077. maps\_challenges_coop::doMissionCallback( "playerGib", self );
  2078.  
  2079. gib_ref = self.a.gib_ref;
  2080.  
  2081. limb_data = get_limb_data( gib_ref );
  2082.  
  2083. if( !IsDefined( limb_data ) )
  2084. {
  2085. /#
  2086. println( "^3animscripts\death.gsc - limb_data is not setup for gib_ref on model: " + self.model + " and gib_ref of: " + self.a.gib_ref );
  2087. #/
  2088.  
  2089. return;
  2090. }
  2091.  
  2092. forward = undefined;
  2093. velocity = undefined;
  2094.  
  2095. pos1 = [];
  2096. pos2 = [];
  2097. velocities = [];
  2098.  
  2099. // level thread draw_line( self GetTagOrigin( limb_data["spawn_tags"] ), self GetTagOrigin( limb_data["spawn_tags"] ) + velocity );
  2100.  
  2101. if( gib_ref == "head" )
  2102. {
  2103. self Detach( self.headModel, "" );
  2104. self helmetPop();
  2105.  
  2106. if( isdefined( self.hatModel ) )
  2107. {
  2108. self detach( self.hatModel, "" );
  2109. self.hatModel = undefined;
  2110. }
  2111. }
  2112.  
  2113. if( limb_data["spawn_tags"][0] != "" )
  2114. {
  2115. if( isdefined( self.gib_vel ) )
  2116. {
  2117. for( i = 0; i < limb_data["spawn_tags"].size; i++ )
  2118. {
  2119. velocities[i] = self.gib_vel;
  2120. }
  2121. }
  2122. else
  2123. {
  2124. for( i = 0; i < limb_data["spawn_tags"].size; i++ )
  2125. {
  2126. pos1[pos1.size] = self GetTagOrigin( limb_data["spawn_tags"][i] );
  2127. }
  2128.  
  2129. wait( 0.05 );
  2130.  
  2131. for( i = 0; i < limb_data["spawn_tags"].size; i++ )
  2132. {
  2133. pos2[pos2.size] = self GetTagOrigin( limb_data["spawn_tags"][i] );
  2134. }
  2135.  
  2136. for( i = 0; i < pos1.size; i++ )
  2137. {
  2138. forward = VectorNormalize( pos2[i] - pos1[i] );
  2139. velocities[i] = forward * RandomIntRange( 600, 1000 );
  2140. velocities[i] = velocities[i] +( 0, 0, RandomIntRange( 400, 700 ) );
  2141. }
  2142. }
  2143. }
  2144.  
  2145. if( IsDefined( limb_data["fx"] ) )
  2146. {
  2147. for( i = 0; i < limb_data["spawn_tags"].size; i++ )
  2148. {
  2149. if( limb_data["spawn_tags"][i] == "" )
  2150. {
  2151. continue;
  2152. }
  2153.  
  2154. PlayFxOnTag( anim._effect[limb_data["fx"]], self, limb_data["spawn_tags"][i] );
  2155. }
  2156. }
  2157.  
  2158. if( level.gibs_this_network_frame + limb_data["spawn_models"].size < level.max_gibs_per_network_frame )
  2159. {
  2160. PlaySoundAtPosition( "death_gibs", self.origin );
  2161. level.gibs_this_network_frame += limb_data["spawn_models"].size;
  2162. self thread throw_gib( limb_data["spawn_models"], limb_data["spawn_tags"], velocities );
  2163. }
  2164.  
  2165. // Set the upperbody model
  2166. self SetModel( limb_data["body_model"] );
  2167.  
  2168. // Attach the legs
  2169. self Attach( limb_data["legs_model"] );
  2170. }
  2171.  
  2172. precache_gib_fx()
  2173. {
  2174. anim._effect["animscript_gib_fx"] = LoadFx( "weapon/bullet/fx_flesh_gib_fatal_01" );
  2175. anim._effect["animscript_gibtrail_fx"] = LoadFx( "trail/fx_trail_blood_streak" );
  2176.  
  2177. // Not gib; split out into another function before this gets out of hand.
  2178. anim._effect["death_neckgrab_spurt"] = LoadFx( "impacts/flesh_hit_neck_fatal" );
  2179. }
  2180.  
  2181. get_limb_data( gib_ref )
  2182. {
  2183. temp_array = [];
  2184.  
  2185. // Slightly faster, store the isdefined stuff before checking, which will be less code-calls.
  2186. torsoDmg1_defined = IsDefined( self.torsoDmg1 );
  2187. torsoDmg2_defined = IsDefined( self.torsoDmg2 );
  2188. torsoDmg3_defined = IsDefined( self.torsoDmg3 );
  2189. torsoDmg4_defined = IsDefined( self.torsoDmg4 );
  2190. torsoDmg5_defined = IsDefined( self.torsoDmg5 );
  2191. legDmg1_defined = IsDefined( self.legDmg1 );
  2192. legDmg2_defined = IsDefined( self.legDmg2 );
  2193. legDmg3_defined = IsDefined( self.legDmg3 );
  2194. legDmg4_defined = IsDefined( self.legDmg4 );
  2195.  
  2196. gibSpawn1_defined = IsDefined( self.gibSpawn1 );
  2197. gibSpawn2_defined = IsDefined( self.gibSpawn2 );
  2198. gibSpawn3_defined = IsDefined( self.gibSpawn3 );
  2199. gibSpawn4_defined = IsDefined( self.gibSpawn4 );
  2200. gibSpawn5_defined = IsDefined( self.gibSpawn5 );
  2201.  
  2202. gibSpawnTag1_defined = IsDefined( self.gibSpawnTag1 );
  2203. gibSpawnTag2_defined = IsDefined( self.gibSpawnTag2 );
  2204. gibSpawnTag3_defined = IsDefined( self.gibSpawnTag3 );
  2205. gibSpawnTag4_defined = IsDefined( self.gibSpawnTag4 );
  2206. gibSpawnTag5_defined = IsDefined( self.gibSpawnTag5 );
  2207.  
  2208. // Right arm is getting blown off! /////////////////////////////////////////////////////
  2209. if( torsoDmg2_defined && legDmg1_defined && gibSpawn1_defined && gibSpawnTag1_defined )
  2210. {
  2211. temp_array["right_arm"]["body_model"] = self.torsoDmg2;
  2212. temp_array["right_arm"]["legs_model"] = self.legDmg1;
  2213. temp_array["right_arm"]["spawn_models"][0] = self.gibSpawn1;
  2214.  
  2215. temp_array["right_arm"]["spawn_tags"][0] = self.gibSpawnTag1;
  2216. temp_array["right_arm"]["fx"] = "animscript_gib_fx";
  2217. }
  2218.  
  2219. // Left arm is getting blown off! //////////////////////////////////////////////////////
  2220. if( torsoDmg3_defined && legDmg1_defined && gibSpawn2_defined && gibSpawnTag2_defined )
  2221. {
  2222. temp_array["left_arm"]["body_model"] = self.torsoDmg3;
  2223. temp_array["left_arm"]["legs_model"] = self.legDmg1;
  2224. temp_array["left_arm"]["spawn_models"][0] = self.gibSpawn2;
  2225.  
  2226. temp_array["left_arm"]["spawn_tags"][0] = self.gibSpawnTag2;
  2227. temp_array["left_arm"]["fx"] = "animscript_gib_fx";
  2228. }
  2229.  
  2230. // Right leg is getting blown off! ////////////////////////////////////////////////////
  2231. if( torsoDmg1_defined && legDmg2_defined && gibSpawn3_defined && gibSpawnTag3_defined )
  2232. {
  2233. temp_array["right_leg"]["body_model"] = self.torsoDmg1;
  2234. temp_array["right_leg"]["legs_model"] = self.legDmg2;
  2235. temp_array["right_leg"]["spawn_models"][0] = self.gibSpawn3;
  2236.  
  2237. temp_array["right_leg"]["spawn_tags"][0] = self.gibSpawnTag3;
  2238. temp_array["right_leg"]["fx"] = "animscript_gib_fx";
  2239. }
  2240.  
  2241.  
  2242. // Left leg is getting blown off! /////////////////////////////////////////////////////
  2243. if( torsoDmg1_defined && legDmg3_defined && gibSpawn4_defined && gibSpawnTag4_defined )
  2244. {
  2245. temp_array["left_leg"]["body_model"] = self.torsoDmg1;
  2246. temp_array["left_leg"]["legs_model"] = self.legDmg3;
  2247. temp_array["left_leg"]["spawn_models"][0] = self.gibSpawn4;
  2248.  
  2249. temp_array["left_leg"]["spawn_tags"][0] = self.gibSpawnTag4;
  2250. temp_array["left_leg"]["fx"] = "animscript_gib_fx";
  2251. }
  2252.  
  2253. // No legs! ///////////////////////////////////////////////////////////////////////////
  2254. if( torsoDmg1_defined && legDmg4_defined && gibSpawn4_defined && gibSpawn3_defined && gibSpawnTag3_defined && gibSpawnTag4_defined )
  2255. {
  2256. temp_array["no_legs"]["body_model"] = self.torsoDmg1;
  2257. temp_array["no_legs"]["legs_model"] = self.legDmg4;
  2258. temp_array["no_legs"]["spawn_models"][0] = self.gibSpawn4;
  2259. temp_array["no_legs"]["spawn_models"][1] = self.gibSpawn3;
  2260.  
  2261. temp_array["no_legs"]["spawn_tags"][0] = self.gibSpawnTag4;
  2262. temp_array["no_legs"]["spawn_tags"][1] = self.gibSpawnTag3;
  2263. temp_array["no_legs"]["fx"] = "animscript_gib_fx";
  2264. }
  2265.  
  2266. // Guts! //////////////////////////////////////////////////////////////////////////////
  2267. if( torsoDmg4_defined && legDmg1_defined )
  2268. {
  2269. temp_array["guts"]["body_model"] = self.torsoDmg4;
  2270. temp_array["guts"]["legs_model"] = self.legDmg1;
  2271.  
  2272. temp_array["guts"]["spawn_models"][0] = "";
  2273. // temp_array["guts"]["spawn_tags"][0] = "J_SpineLower";
  2274. temp_array["guts"]["spawn_tags"][0] = "";
  2275. temp_array["guts"]["fx"] = "animscript_gib_fx";
  2276. }
  2277.  
  2278. // Head! //////////////////////////////////////////////////////////////////////////////
  2279. if( torsoDmg5_defined && legDmg1_defined )
  2280. {
  2281. temp_array["head"]["body_model"] = self.torsoDmg5;
  2282. temp_array["head"]["legs_model"] = self.legDmg1;
  2283.  
  2284. if( gibSpawn5_defined && gibSpawnTag5_defined )
  2285. {
  2286. temp_array["head"]["spawn_models"][0] = self.gibSpawn5;
  2287. temp_array["head"]["spawn_tags"][0] = self.gibSpawnTag5;
  2288. }
  2289. else
  2290. {
  2291. temp_array["head"]["spawn_models"][0] = "";
  2292. temp_array["head"]["spawn_tags"][0] = "";
  2293. }
  2294. temp_array["head"]["fx"] = "animscript_gib_fx";
  2295. }
  2296.  
  2297. if( IsDefined( temp_array[gib_ref] ) )
  2298. {
  2299. return temp_array[gib_ref];
  2300. }
  2301. else
  2302. {
  2303. return undefined;
  2304. }
  2305. }
  2306.  
  2307. throw_gib( spawn_models, spawn_tags, velocities )
  2308. {
  2309. if( velocities.size < 1 ) // For guts
  2310. {
  2311. return;
  2312. }
  2313.  
  2314. for( i = 0; i < spawn_models.size; i++ )
  2315. {
  2316. origin = self GetTagOrigin( spawn_tags[i] );
  2317. angles = self GetTagAngles( spawn_tags[i] );
  2318. CreateDynEntAndLaunch( spawn_models[i], origin, angles, origin, velocities[i], anim._effect["animscript_gibtrail_fx"], 1 );
  2319.  
  2320. //gib = Spawn( "script_model", self GetTagOrigin( spawn_tags[i] ) );
  2321. //gib.angles = self GetTagAngles( spawn_tags[i] );
  2322. //gib SetModel( spawn_models[i] );
  2323.  
  2324. //// Play trail fX
  2325. //PlayFxOnTag( anim._effect["animscript_gibtrail_fx"], gib, "tag_fx" );
  2326.  
  2327. //gib PhysicsLaunch( self.origin, velocities[i] );
  2328.  
  2329. //gib thread gib_delete();
  2330. }
  2331. }
  2332.  
  2333. gib_delete()
  2334. {
  2335. wait( 10 + RandomFloat( 5 ) );
  2336. for( i = 0; i < 100; i++ )
  2337. {
  2338. if( !self IsBeingWatched() )
  2339. {
  2340. break;
  2341. }
  2342.  
  2343. wait( 1 );
  2344. }
  2345. self Delete();
  2346. }
  2347.  
  2348. death_anim_short_circuit()
  2349. {
  2350. self endon( "stop_death_anim_short_circuit" );
  2351.  
  2352. wait 0.3;
  2353.  
  2354. totalDamageTaken = 0;
  2355. while( 1 )
  2356. {
  2357. self waittill( "damage", damagetaken, attacker, dir, point, mod );
  2358.  
  2359. waittillframeend; // do this to allow the code to update self.damage* vars - JRS
  2360.  
  2361. if( isdefined( self.damageMod ) && self.damageMod != "MOD_BURNED" )
  2362. {
  2363. totalDamageTaken += self.damageTaken;
  2364. if( totalDamageTaken > 100 )
  2365. {
  2366. self launch_ragdoll_based_on_damage_type();
  2367. break;
  2368. }
  2369. }
  2370. }
  2371. }
  2372.  
  2373. launch_ragdoll_based_on_damage_type( bullet_scale )
  2374. {
  2375. if( self animscripts\pain::wasDamagedByExplosive() )
  2376. {
  2377. force = 1.6;
  2378. }
  2379. else if( WeaponClass( self.damageWeapon ) == "spread" ) // shotgun
  2380. {
  2381. distSquared = DistanceSquared( self.origin, self.attacker.origin );
  2382. force = .3;
  2383. force += .7 *( 1.0 -( distSquared /( 300*300 ) ) );
  2384. }
  2385. else // everything else
  2386. {
  2387. if( self.damagetaken < 75 )
  2388. {
  2389. force = .35;
  2390. }
  2391. else
  2392. {
  2393. force = .45;
  2394. }
  2395. if( isdefined( bullet_scale ) )
  2396. {
  2397. force *= bullet_scale;
  2398. }
  2399. }
  2400.  
  2401. initial_force = self.damagedir + ( 0, 0, 0.2 );
  2402. initial_force *= 60 * force;
  2403.  
  2404. if( damageLocationIsAny( "head", "helmet", "neck" ) )
  2405. {
  2406. initial_force *= 0.5;
  2407. }
  2408.  
  2409. self startragdoll();
  2410. self launchragdoll( initial_force, self.damageLocation );
  2411. }
  2412.  
  2413. draw_line( pos1, pos2 )
  2414. {
  2415. /#
  2416. while( 1 )
  2417. {
  2418. line( pos1, pos2 );
  2419. wait( 0.05 );
  2420. }
  2421. #/
  2422. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement