mirror of
https://github.com/1dot13/source.git
synced 2026-07-22 13:40:22 +02:00
Fix for civilians trying to climb the roof to seek noise Fix for punching and stabbing Transparent change: Gave names to anonymous structs in OBJECTTYPE git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@1225 3b4a5df2-a311-0410-b5c6-a8a6f20db521
4107 lines
119 KiB
C++
4107 lines
119 KiB
C++
#ifdef PRECOMPILEDHEADERS
|
|
#include "Tactical All.h"
|
|
#else
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include "wcheck.h"
|
|
#include "stdlib.h"
|
|
#include "debug.h"
|
|
#include "MemMan.h"
|
|
#include "Overhead Types.h"
|
|
#include "Soldier Control.h"
|
|
#include "Animation Cache.h"
|
|
#include "Animation Data.h"
|
|
#include "Animation Control.h"
|
|
#include "weapons.h"
|
|
#include "soldier ani.h"
|
|
#include "Random.h"
|
|
#include "video.h"
|
|
#include "vobject_blitters.h"
|
|
#include "Sound Control.h"
|
|
#include "isometric utils.h"
|
|
#include "Handle UI.h"
|
|
#include "Event Pump.h"
|
|
#include "opplist.h"
|
|
#include "lighting.h"
|
|
#include "ai.h"
|
|
#include "renderworld.h"
|
|
#include "interactive tiles.h"
|
|
#include "points.h"
|
|
#include "message.h"
|
|
#include "world items.h"
|
|
#include "physics.h"
|
|
#include "soldier create.h"
|
|
#include "dialogue control.h"
|
|
#include "soldier functions.h"
|
|
#include "rotting corpses.h"
|
|
#include "merc entering.h"
|
|
#include "soldier add.h"
|
|
#include "soldier profile.h"
|
|
#include "soldier functions.h"
|
|
#include "interface.h"
|
|
#include "qarray.h"
|
|
#include "soldier macros.h"
|
|
#include "Strategic Town Loyalty.h"
|
|
#include "Squads.h"
|
|
#include "worldman.h"
|
|
#include "structure wrap.h"
|
|
#include "pathai.h"
|
|
#include "pits.h"
|
|
#include "text.h"
|
|
#include "npc.h"
|
|
#include "meanwhile.h"
|
|
#include "Explosion Control.h"
|
|
#include "fov.h"
|
|
#include "campaign.h"
|
|
#include "los.h"
|
|
#include "GameSettings.h"
|
|
#include "Boxing.h"
|
|
#include "drugs and alcohol.h"
|
|
#include "Smell.h"
|
|
#include "GameSettings.h"
|
|
#include "interface dialogue.h"
|
|
#include "Strategic Status.h"
|
|
#endif
|
|
|
|
#define NO_JUMP 0
|
|
#define MAX_ANIFRAMES_PER_FLASH 2
|
|
//#define TIME_FOR_RANDOM_ANIM_CHECK 10
|
|
#define TIME_FOR_RANDOM_ANIM_CHECK 2
|
|
|
|
BOOLEAN gfLastMercTalkedAboutKillingID = NOBODY;
|
|
|
|
extern void AddFuelToVehicle( SOLDIERTYPE *pSoldier, SOLDIERTYPE *pVehicle );
|
|
|
|
|
|
DOUBLE gHopFenceForwardSEDist[ NUMSOLDIERBODYTYPES ] = { 2.2, 0.7, 3.2, 0.7 };
|
|
DOUBLE gHopFenceForwardNWDist[ NUMSOLDIERBODYTYPES ] = { 2.7, 1.0, 2.7, 1.0 };
|
|
DOUBLE gHopFenceForwardFullSEDist[ NUMSOLDIERBODYTYPES ] = { 1.1, 1.0, 2.1, 1.1 };
|
|
DOUBLE gHopFenceForwardFullNWDist[ NUMSOLDIERBODYTYPES ] = { 0.8, 0.2, 2.7, 0.8 };
|
|
DOUBLE gFalloffBackwardsDist[ NUMSOLDIERBODYTYPES ] = { 1, 0.8, 1, 1 };
|
|
DOUBLE gClimbUpRoofDist[ NUMSOLDIERBODYTYPES ] = { 2, 0.1, 2, 2 };
|
|
DOUBLE gClimbUpRoofLATDist[ NUMSOLDIERBODYTYPES ] = { 0.7, 0.5, 0.7, 0.5 };
|
|
DOUBLE gClimbDownRoofStartDist[ NUMSOLDIERBODYTYPES ] = { 5.0, 1.0, 1, 1 };
|
|
DOUBLE gClimbUpRoofDistGoingLower[ NUMSOLDIERBODYTYPES ] = { 0.9, 0.1, 1, 1 };
|
|
|
|
|
|
|
|
BOOLEAN HandleSoldierDeath( SOLDIERTYPE *pSoldier , BOOLEAN *pfMadeCorpse );
|
|
|
|
void CheckForAndHandleSoldierIncompacitated( SOLDIERTYPE *pSoldier );
|
|
BOOLEAN CheckForImproperFireGunEnd( SOLDIERTYPE *pSoldier );
|
|
BOOLEAN OKHeightDest( SOLDIERTYPE *pSoldier, INT16 sNewGridNo );
|
|
BOOLEAN HandleUnjamAnimation( SOLDIERTYPE *pSoldier );
|
|
|
|
extern void HandleSystemNewAISituation( SOLDIERTYPE *pSoldier, BOOLEAN fResetABC );
|
|
extern void PlaySoldierFootstepSound( SOLDIERTYPE *pSoldier );
|
|
extern UINT8 NumCapableEnemyInSector( );
|
|
extern BOOLEAN gfKillingGuysForLosingBattle;
|
|
|
|
extern UINT8 gubInterruptProvoker;
|
|
|
|
extern UINT16 PickSoldierReadyAnimation( SOLDIERTYPE *pSoldier, BOOLEAN fEndReady );
|
|
|
|
// Animation code explanations!
|
|
//
|
|
// 0-399: Actual animation frame indices
|
|
// 400-499: Object manipulation codes
|
|
// 500-598: Jump to frame x-501, same state. Obvious limit 0-97
|
|
// 600-699: Jump to new state x-600, frame 0
|
|
// 700-798: Play sound
|
|
// 800-999: Jump to new state x-700, frame 0 (starts with 100)
|
|
//
|
|
|
|
BOOLEAN AdjustToNextAnimationFrame( SOLDIERTYPE *pSoldier )
|
|
{
|
|
EV_S_FIREWEAPON SFireWeapon;
|
|
|
|
UINT16 sNewAniFrame, anAniFrame;
|
|
INT8 ubCurrentHeight;
|
|
UINT16 usOldAnimState;
|
|
static UINT32 uiJumpAddress = NO_JUMP;
|
|
INT16 sNewGridNo;
|
|
INT16 sX, sY;
|
|
BOOLEAN fStop;
|
|
UINT32 cnt;
|
|
UINT8 ubDiceRoll; // Percentile dice roll
|
|
UINT8 ubRandomHandIndex; // Index value into random animation table to use base don what is in the guys hand...
|
|
UINT16 usItem;
|
|
RANDOM_ANI_DEF *pAnimDef;
|
|
UINT8 ubNewDirection;
|
|
UINT8 ubDesiredHeight;
|
|
BOOLEAN bOKFireWeapon;
|
|
BOOLEAN bWeaponJammed;
|
|
BOOLEAN fFreeUpAttacker=FALSE;
|
|
UINT16 usUIMovementMode;
|
|
|
|
do
|
|
{
|
|
// Get new frame code
|
|
sNewAniFrame = gusAnimInst[ pSoldier->usAnimState ][ pSoldier->usAniCode ];
|
|
|
|
// Handle muzzle flashes
|
|
if ( pSoldier->bMuzFlashCount > 0 )
|
|
{
|
|
// FLash for about 3 frames
|
|
if ( pSoldier->bMuzFlashCount > MAX_ANIFRAMES_PER_FLASH )
|
|
{
|
|
pSoldier->bMuzFlashCount = 0;
|
|
if ( pSoldier->iMuzFlash != -1 )
|
|
{
|
|
LightSpriteDestroy( pSoldier->iMuzFlash );
|
|
pSoldier->iMuzFlash = -1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pSoldier->bMuzFlashCount++;
|
|
}
|
|
|
|
}
|
|
|
|
if ( pSoldier->bBreathCollapsed )
|
|
{
|
|
// ATE: If we have fallen, and we can't get up... no
|
|
// really, if we were told to collapse but have been hit after, don't
|
|
// do anything...
|
|
if ( gAnimControl[ pSoldier->usAnimState ].uiFlags & ( ANIM_HITSTOP | ANIM_HITFINISH ) )
|
|
{
|
|
pSoldier->bBreathCollapsed = FALSE;
|
|
}
|
|
else if ( pSoldier->bLife == 0 )
|
|
{
|
|
// Death takes precedence...
|
|
pSoldier->bBreathCollapsed = FALSE;
|
|
}
|
|
else if ( pSoldier->usPendingAnimation == FALLFORWARD_ROOF || pSoldier->usPendingAnimation == FALLOFF || pSoldier->usAnimState == FALLFORWARD_ROOF || pSoldier->usAnimState == FALLOFF )
|
|
{
|
|
pSoldier->bBreathCollapsed = FALSE;
|
|
}
|
|
else
|
|
{
|
|
// Wait here until we are free....
|
|
if ( !pSoldier->fInNonintAnim )
|
|
{
|
|
// UNset UI
|
|
UnSetUIBusy( pSoldier->ubID );
|
|
|
|
SoldierCollapse( pSoldier );
|
|
|
|
pSoldier->bBreathCollapsed = FALSE;
|
|
|
|
return( TRUE );
|
|
}
|
|
}
|
|
}
|
|
|
|
// Check for special code
|
|
if ( sNewAniFrame < 399 )
|
|
{
|
|
|
|
// Adjust / set true ani frame
|
|
// Use -1 because ani files are 1-based, these are 0-based
|
|
ConvertAniCodeToAniFrame( pSoldier, (INT16)( sNewAniFrame - 1 ) );
|
|
|
|
// Adjust frame control pos, and try again
|
|
pSoldier->usAniCode++;
|
|
break;
|
|
}
|
|
else if ( sNewAniFrame < 500 )
|
|
{
|
|
// Switch on special code
|
|
switch( sNewAniFrame )
|
|
{
|
|
case 402:
|
|
|
|
// DO NOT MOVE FOR THIS FRAME
|
|
pSoldier->fPausedMove = TRUE;
|
|
break;
|
|
|
|
case 403:
|
|
|
|
// MOVE GUY FORWARD SOME VALUE
|
|
MoveMercFacingDirection( pSoldier, FALSE, (FLOAT)0.7 );
|
|
|
|
break;
|
|
|
|
case 404:
|
|
|
|
// MOVE GUY BACKWARD SOME VALUE
|
|
// Use same function as forward, but is -ve values!
|
|
MoveMercFacingDirection( pSoldier , TRUE, (FLOAT)1 );
|
|
break;
|
|
|
|
case 405:
|
|
|
|
return( TRUE );
|
|
|
|
case 406:
|
|
|
|
// Move merc up
|
|
if ( pSoldier->bDirection == NORTH )
|
|
{
|
|
SetSoldierHeight( pSoldier, (FLOAT)(pSoldier->sHeightAdjustment + 2 ) );
|
|
}
|
|
else
|
|
{
|
|
SetSoldierHeight( pSoldier, (FLOAT)( pSoldier->sHeightAdjustment + 3 ) );
|
|
}
|
|
break;
|
|
|
|
case 408:
|
|
|
|
// CODE: SPECIAL MOVE CLIMB UP ROOF EVENT
|
|
|
|
// re-enable sight
|
|
gTacticalStatus.uiFlags &= (~DISALLOW_SIGHT);
|
|
{
|
|
INT16 sXPos, sYPos;
|
|
|
|
//usNewGridNo = NewGridNo( (UINT16)pSoldier->sGridNo, (UINT16)DirectionInc( pSoldier->bDirection ) );
|
|
ConvertMapPosToWorldTileCenter( pSoldier->sTempNewGridNo, &sXPos, &sYPos );
|
|
EVENT_SetSoldierPosition( pSoldier, (FLOAT)sXPos, (FLOAT)sYPos );
|
|
}
|
|
// Move two CC directions
|
|
EVENT_SetSoldierDirection( pSoldier, gTwoCCDirection[ pSoldier->bDirection ] );
|
|
|
|
EVENT_SetSoldierDesiredDirection( pSoldier, pSoldier->bDirection );
|
|
|
|
// Set desired anim height!
|
|
pSoldier->ubDesiredHeight = ANIM_CROUCH;
|
|
|
|
// Madd
|
|
usUIMovementMode = GetMoveStateBasedOnStance( pSoldier, gAnimControl[ pSoldier->usAnimState ].ubEndHeight );
|
|
pSoldier->usUIMovementMode = usUIMovementMode;
|
|
|
|
// Move merc up specific height
|
|
SetSoldierHeight( pSoldier, (FLOAT)50 );
|
|
|
|
// ATE: Change interface level.....
|
|
// CJC: only if we are a player merc
|
|
if (pSoldier->bTeam == gbPlayerNum)
|
|
{
|
|
|
|
if (gTacticalStatus.fAutoBandageMode)
|
|
{
|
|
// in autobandage, handle as AI, but add roof marker too
|
|
FreeUpNPCFromRoofClimb( pSoldier );
|
|
HandlePlacingRoofMarker( pSoldier, pSoldier->sGridNo, TRUE, TRUE );
|
|
}
|
|
else
|
|
{
|
|
// OK, UNSET INTERFACE FIRST
|
|
UnSetUIBusy( pSoldier->ubID );
|
|
|
|
if ( pSoldier->ubID == gusSelectedSoldier )
|
|
{
|
|
ChangeInterfaceLevel( 1 );
|
|
}
|
|
HandlePlacingRoofMarker( pSoldier, pSoldier->sGridNo, TRUE, TRUE );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
FreeUpNPCFromRoofClimb( pSoldier );
|
|
}
|
|
|
|
// ATE: Handle sight...
|
|
HandleSight( pSoldier,SIGHT_LOOK | SIGHT_RADIO | SIGHT_INTERRUPT );
|
|
break;
|
|
|
|
case 409:
|
|
|
|
//CODE: MOVE DOWN
|
|
SetSoldierHeight( pSoldier, (FLOAT)( pSoldier->sHeightAdjustment - 2 ) );
|
|
break;
|
|
|
|
case 410:
|
|
|
|
// Move merc down specific height
|
|
SetSoldierHeight( pSoldier, (FLOAT)0 );
|
|
break;
|
|
|
|
case 411:
|
|
|
|
// CODE: SPECIALMOVE CLIMB DOWN EVENT
|
|
// Move two C directions
|
|
EVENT_SetSoldierDirection( pSoldier, gTwoCDirection[ pSoldier->bDirection ] );
|
|
|
|
EVENT_SetSoldierDesiredDirection( pSoldier, pSoldier->bDirection );
|
|
// Adjust height
|
|
SetSoldierHeight( pSoldier, (FLOAT)gClimbDownRoofStartDist[ pSoldier->ubBodyType ] );
|
|
// Adjust position
|
|
MoveMercFacingDirection( pSoldier , TRUE, (FLOAT)3.5 );
|
|
break;
|
|
|
|
case 412:
|
|
|
|
// CODE: HANDLING PRONE DOWN - NEED TO MOVE GUY BACKWARDS!
|
|
MoveMercFacingDirection( pSoldier , FALSE, (FLOAT).2 );
|
|
break;
|
|
|
|
case 413:
|
|
|
|
// CODE: HANDLING PRONE UP - NEED TO MOVE GUY FORWARDS!
|
|
MoveMercFacingDirection( pSoldier , TRUE, (FLOAT).2 );
|
|
break;
|
|
|
|
case 430:
|
|
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,"AdjustToNextAnimationFrame: case 430");
|
|
// SHOOT GUN
|
|
// MAKE AN EVENT, BUT ONLY DO STUFF IF WE OWN THE GUY!
|
|
SFireWeapon.usSoldierID = pSoldier->ubID;
|
|
SFireWeapon.uiUniqueId = pSoldier->uiUniqueSoldierIdValue;
|
|
SFireWeapon.sTargetGridNo = pSoldier->sTargetGridNo;
|
|
SFireWeapon.bTargetLevel = pSoldier->bTargetLevel;
|
|
SFireWeapon.bTargetCubeLevel= pSoldier->bTargetCubeLevel;
|
|
AddGameEvent( S_FIREWEAPON, 0, &SFireWeapon );
|
|
|
|
//DIGICRAB: Burst UnCap
|
|
//Loop around in the animation if we still have burst rounds to fire
|
|
if (pSoldier->bDoBurst && (pSoldier->bDoBurst <= ((pSoldier->bDoAutofire)?(pSoldier->bDoAutofire):(GetShotsPerBurst(&pSoldier->inv[HANDPOS]))) || (( pSoldier->bWeaponMode == WM_ATTACHED_GL_BURST && pSoldier->bDoBurst <= Weapon[GetAttachedGrenadeLauncher(&pSoldier->inv[HANDPOS])].ubShotsPerBurst)) ))
|
|
{
|
|
if(pSoldier->usAnimState == 44 || pSoldier->usAnimState == 109 || pSoldier->usAnimState == 108 && pSoldier->usAniCode == 33) //we are standing, crounching or prone, firing the fast shot
|
|
pSoldier->usAniCode = 3;
|
|
else if(pSoldier->usAnimState == 175 && pSoldier->usAniCode == 37) //we are firing down to something very close, last shot
|
|
pSoldier->usAniCode = 14;
|
|
}
|
|
|
|
//DIGICRAB: Burst Sound
|
|
//This code is stolen from Tactical\Weapons.c - UseGun(...)
|
|
if (pSoldier->bDoBurst && pSoldier->iBurstSoundID == NO_SAMPLE && Weapon[ pSoldier->usAttackingWeapon ].sSound != 0 && Item[ pSoldier->usAttackingWeapon ].usItemClass != IC_THROWING_KNIFE )
|
|
{
|
|
// Switch on silencer...
|
|
INT16 noisefactor = GetPercentNoiseVolume( &pSoldier->inv[ pSoldier->ubAttackingHand ] );
|
|
if( noisefactor < MAX_PERCENT_NOISE_VOLUME_FOR_SILENCED_SOUND || Weapon[ pSoldier->usAttackingWeapon ].ubAttackVolume <= 10 )
|
|
{
|
|
INT32 uiSound;
|
|
|
|
uiSound = Weapon [ pSoldier->usAttackingWeapon ].silencedSound;
|
|
//if ( Weapon[ pSoldier->usAttackingWeapon ].ubCalibre == AMMO9 || Weapon[ pSoldier->usAttackingWeapon ].ubCalibre == AMMO38 || Weapon[ pSoldier->usAttackingWeapon ].ubCalibre == AMMO57 )
|
|
//{
|
|
// uiSound = S_SILENCER_1;
|
|
//}
|
|
//else
|
|
//{
|
|
// uiSound = S_SILENCER_2;
|
|
//}
|
|
|
|
//randomize the rate a bit so that the sound is more believable
|
|
PlayJA2Sample( uiSound, 44100-Random(5000)-Random(5000)-Random(5000), SoundVolume( HIGHVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ) );
|
|
|
|
}
|
|
else
|
|
{
|
|
INT8 volume = HIGHVOLUME;
|
|
if ( noisefactor < 100 ) volume = (volume * noisefactor) / 100;
|
|
//randomize the rate a bit so that the sound is more believable
|
|
PlayJA2Sample( Weapon[ pSoldier->usAttackingWeapon ].sSound, 44100-Random(5000)-Random(5000)-Random(5000), SoundVolume( volume, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ) );
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
case 431:
|
|
|
|
// FLASH FRAME WHITE
|
|
pSoldier->pForcedShade = White16BPPPalette;
|
|
break;
|
|
|
|
case 432:
|
|
|
|
// PLAY RANDOM IMPACT SOUND!
|
|
// PlayJA2Sample( (UINT8)( BULLET_IMPACT_1 + Random(3) ), RATE_11025, MIDVOLUME, 1, MIDDLEPAN );
|
|
|
|
// PLAY RANDOM GETTING HIT SOUND
|
|
// DoMercBattleSound( pSoldier, BATTLE_SOUND_HIT1 );
|
|
|
|
break;
|
|
|
|
case 433:
|
|
|
|
// CODE: GENERIC HIT!
|
|
|
|
CheckForAndHandleSoldierIncompacitated( pSoldier );
|
|
|
|
|
|
break;
|
|
|
|
case 434:
|
|
|
|
// JUMP TO ANOTHER ANIMATION ( BLOOD ) IF WE WANT BLOOD
|
|
uiJumpAddress = pSoldier->usAnimState;
|
|
ChangeSoldierState( pSoldier, FLYBACK_HIT_BLOOD_STAND, 0, FALSE );
|
|
return( TRUE );
|
|
break;
|
|
|
|
case 435:
|
|
|
|
// HOOK FOR A RETURN JUMP
|
|
break;
|
|
|
|
case 436:
|
|
|
|
// Loop through script to find entry address
|
|
if ( uiJumpAddress == NO_JUMP )
|
|
{
|
|
break;
|
|
}
|
|
usOldAnimState = pSoldier->usAnimState;
|
|
pSoldier->usAniCode = 0;
|
|
|
|
do
|
|
{
|
|
// Get new frame code
|
|
anAniFrame = gusAnimInst[ uiJumpAddress ][ pSoldier->usAniCode ];
|
|
|
|
if ( anAniFrame == 435 )
|
|
{
|
|
// START PROCESSING HERE
|
|
ChangeSoldierState( pSoldier, (UINT16)uiJumpAddress, pSoldier->usAniCode, FALSE );
|
|
return( TRUE );
|
|
}
|
|
// Adjust frame control pos, and try again
|
|
pSoldier->usAniCode++;
|
|
}
|
|
while( anAniFrame != 999 );
|
|
|
|
uiJumpAddress = NO_JUMP;
|
|
|
|
if ( anAniFrame == 999 )
|
|
{
|
|
// Fail jump, re-load old anim
|
|
ChangeSoldierState( pSoldier, usOldAnimState, 0, FALSE );
|
|
return( TRUE );
|
|
}
|
|
break;
|
|
|
|
case 437:
|
|
|
|
// CHANGE DIRECTION AND GET-UP
|
|
//sGridNo = NewGridNo( (UINT16)pSoldier->sGridNo, (UINT16)(-1 * DirectionInc( pSoldier->bDirection ) ) );
|
|
//ConvertMapPosToWorldTileCenter( pSoldier->sGridNo, &sXPos, &sYPos );
|
|
//SetSoldierPosition( pSoldier, (FLOAT)sXPos, (FLOAT)sYPos );
|
|
|
|
|
|
// Reverse direction
|
|
EVENT_SetSoldierDirection( pSoldier, gOppositeDirection[ pSoldier->bDirection ] );
|
|
EVENT_SetSoldierDesiredDirection( pSoldier, pSoldier->bDirection );
|
|
|
|
ChangeSoldierState( pSoldier, GETUP_FROM_ROLLOVER, 0 , FALSE );
|
|
return( TRUE );
|
|
|
|
case 438:
|
|
|
|
//CODE: START HOLD FLASH
|
|
pSoldier->fForceShade = TRUE;
|
|
break;
|
|
|
|
case 439:
|
|
|
|
//CODE: END HOLD FLASH
|
|
pSoldier->fForceShade = FALSE;
|
|
break;
|
|
|
|
case 440:
|
|
//CODE: Set buddy as dead!
|
|
{
|
|
BOOLEAN fMadeCorpse;
|
|
|
|
// ATE: Piggyback here on stopping the burn sound...
|
|
if ( pSoldier->usAnimState == CHARIOTS_OF_FIRE ||
|
|
pSoldier->usAnimState == BODYEXPLODING )
|
|
{
|
|
SoundStop( pSoldier->uiPendingActionData1 );
|
|
}
|
|
|
|
|
|
CheckForAndHandleSoldierDeath( pSoldier, &fMadeCorpse );
|
|
|
|
if ( fMadeCorpse )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
else
|
|
{
|
|
return( TRUE );
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 441:
|
|
// CODE: Show muzzle flash
|
|
if ( pSoldier->bVisible == -1 )
|
|
{
|
|
break;
|
|
}
|
|
|
|
if ( !pSoldier->fMuzzleFlash )
|
|
{
|
|
break;
|
|
}
|
|
|
|
// DO ONLY IF WE'RE AT A GOOD LEVEL
|
|
if ( ubAmbientLightLevel < MIN_AMB_LEVEL_FOR_MERC_LIGHTS )
|
|
{
|
|
break;
|
|
}
|
|
|
|
if( ( pSoldier->iMuzFlash=LightSpriteCreate("L-R03.LHT", 0 ) )==(-1))
|
|
{
|
|
return( TRUE );
|
|
}
|
|
|
|
LightSpritePower(pSoldier->iMuzFlash, TRUE);
|
|
// Get one move forward
|
|
{
|
|
UINT16 usNewGridNo;
|
|
INT16 sXPos, sYPos;
|
|
|
|
usNewGridNo = NewGridNo( (UINT16)pSoldier->sGridNo, DirectionInc( pSoldier->bDirection ) );
|
|
ConvertGridNoToCenterCellXY( usNewGridNo, &sXPos, &sYPos );
|
|
LightSpritePosition( pSoldier->iMuzFlash, (INT16)(sXPos/CELL_X_SIZE), (INT16)(sYPos/CELL_Y_SIZE));
|
|
|
|
// Start count
|
|
pSoldier->bMuzFlashCount = 1;
|
|
}
|
|
break;
|
|
|
|
case 442:
|
|
|
|
//CODE: FOR A NON-INTERRUPTABLE SCRIPT - SIGNAL DONE
|
|
pSoldier->fInNonintAnim = FALSE;
|
|
|
|
// ATE: if it's the begin cower animation, unset ui, cause it could
|
|
// be from player changin stance
|
|
if ( pSoldier->usAnimState == START_COWER )
|
|
{
|
|
UnSetUIBusy( pSoldier->ubID );
|
|
}
|
|
break;
|
|
|
|
case 443:
|
|
|
|
// MOVE GUY FORWARD FOR FENCE HOP ANIMATION
|
|
switch( pSoldier->bDirection )
|
|
{
|
|
case SOUTH:
|
|
case EAST:
|
|
|
|
MoveMercFacingDirection( pSoldier, FALSE, (FLOAT)gHopFenceForwardSEDist[ pSoldier->ubBodyType ] );
|
|
break;
|
|
|
|
case NORTH:
|
|
case WEST:
|
|
MoveMercFacingDirection( pSoldier, FALSE, (FLOAT)gHopFenceForwardNWDist[ pSoldier->ubBodyType ] );
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 444:
|
|
|
|
// CODE: End Hop Fence
|
|
// MOVE TO FORCASTED GRIDNO
|
|
sX = CenterX( pSoldier->sForcastGridno );
|
|
sY = CenterY( pSoldier->sForcastGridno );
|
|
|
|
EVENT_InternalSetSoldierPosition( pSoldier, (FLOAT) sX, (FLOAT) sY, FALSE, FALSE, FALSE );
|
|
EVENT_SetSoldierDirection( pSoldier, gTwoCDirection[ pSoldier->bDirection ] );
|
|
pSoldier->sZLevelOverride = -1;
|
|
EVENT_SetSoldierDesiredDirection( pSoldier, pSoldier->bDirection );
|
|
|
|
|
|
if ( gTacticalStatus.bBoxingState == BOXING_WAITING_FOR_PLAYER || gTacticalStatus.bBoxingState == PRE_BOXING || gTacticalStatus.bBoxingState == BOXING )
|
|
{
|
|
BoxingMovementCheck( pSoldier );
|
|
}
|
|
|
|
if ( SetOffBombsInGridNo( pSoldier->ubID, pSoldier->sGridNo, FALSE, pSoldier->bLevel ))
|
|
{
|
|
EVENT_StopMerc( pSoldier, pSoldier->sGridNo, pSoldier->bDirection );
|
|
return( TRUE );
|
|
}
|
|
|
|
// If we are at our final destination, goto stance of our movement stance...
|
|
// Only in realtime...
|
|
//if ( !( gTacticalStatus.uiFlags & INCOMBAT ) )
|
|
// This has to be here to make guys continue along fence path
|
|
#if 0
|
|
if ( pSoldier->sGridNo == pSoldier->sFinalDestination )
|
|
{
|
|
if ( gAnimControl[ pSoldier->usAnimState ].ubEndHeight != gAnimControl[ pSoldier->usUIMovementMode ].ubEndHeight )
|
|
{
|
|
// Goto Stance...
|
|
pSoldier->fDontChargeAPsForStanceChange = TRUE;
|
|
ChangeSoldierStance( pSoldier, gAnimControl[ pSoldier->usUIMovementMode ].ubEndHeight );
|
|
return( TRUE );
|
|
}
|
|
else
|
|
{
|
|
//SoldierGotoStationaryStance( pSoldier );
|
|
|
|
// Set UI Busy
|
|
UnSetUIBusy( pSoldier->ubID );
|
|
|
|
//return( TRUE );
|
|
}
|
|
}
|
|
#endif
|
|
break;
|
|
|
|
case 445:
|
|
|
|
// CODE: MOVE GUY FORWARD ONE TILE, BASED ON WHERE WE ARE FACING
|
|
switch( pSoldier->bDirection )
|
|
{
|
|
case SOUTH:
|
|
case EAST:
|
|
|
|
MoveMercFacingDirection( pSoldier, FALSE, (FLOAT)gHopFenceForwardFullSEDist[ pSoldier->ubBodyType ] );
|
|
break;
|
|
|
|
case NORTH:
|
|
case WEST:
|
|
|
|
MoveMercFacingDirection( pSoldier, FALSE, (FLOAT)gHopFenceForwardFullNWDist[ pSoldier->ubBodyType ] );
|
|
break;
|
|
|
|
}
|
|
break;
|
|
|
|
case 446:
|
|
|
|
// CODE: Turn pause move flag on
|
|
pSoldier->uiStatusFlags |= SOLDIER_PAUSEANIMOVE;
|
|
break;
|
|
|
|
case 447:
|
|
|
|
// TRY TO FALL!!!
|
|
if ( pSoldier ->fTryingToFall )
|
|
{
|
|
INT16 sLastAniFrame;
|
|
|
|
// TRY FORWARDS...
|
|
// FIRST GRIDNO
|
|
sNewGridNo = NewGridNo( (UINT16)pSoldier->sGridNo, (UINT16)( DirectionInc( pSoldier->bDirection ) ) );
|
|
|
|
if ( OKFallDirection( pSoldier, sNewGridNo, pSoldier->bLevel, pSoldier->bDirection, FALLFORWARD_HITDEATH_STOP ) )
|
|
{
|
|
// SECOND GRIDNO
|
|
// sNewGridNo = NewGridNo( (UINT16)sNewGridNo, (UINT16)( DirectionInc( pSoldier->bDirection ) ) );
|
|
|
|
// if ( OKFallDirection( pSoldier, sNewGridNo, pSoldier->bLevel, pSoldier->bDirection, FALLFORWARD_HITDEATH_STOP ) )
|
|
{
|
|
// ALL'S OK HERE...
|
|
pSoldier->fTryingToFall = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
// IF HERE, INCREMENT DIRECTION
|
|
// ATE: Added Feb1 - can be either direction....
|
|
if ( pSoldier->fFallClockwise )
|
|
{
|
|
EVENT_SetSoldierDirection( pSoldier, gOneCDirection[ pSoldier->bDirection ] );
|
|
}
|
|
else
|
|
{
|
|
EVENT_SetSoldierDirection( pSoldier, gOneCCDirection[ pSoldier->bDirection ] );
|
|
}
|
|
EVENT_SetSoldierDesiredDirection( pSoldier, pSoldier->bDirection );
|
|
sLastAniFrame = gusAnimInst[ pSoldier->usAnimState ][ ( pSoldier->usAniCode - 2 ) ];
|
|
ConvertAniCodeToAniFrame( pSoldier, (INT16)( sLastAniFrame ) );
|
|
|
|
if ( pSoldier->bDirection == pSoldier->bStartFallDir )
|
|
{
|
|
// GO FORWARD HERE...
|
|
pSoldier ->fTryingToFall = FALSE;
|
|
break;;
|
|
}
|
|
// IF HERE, RETURN SO WE DONOT INCREMENT DIR
|
|
return( TRUE );
|
|
}
|
|
break;
|
|
|
|
|
|
case 448:
|
|
|
|
// CODE: HANDLE BURST
|
|
// FIRST CHECK IF WE'VE REACHED MAX FOR GUN
|
|
fStop = FALSE;
|
|
|
|
if ( ( pSoldier->bWeaponMode == WM_ATTACHED_GL_BURST && pSoldier->bDoBurst > Weapon[GetAttachedGrenadeLauncher(&pSoldier->inv[HANDPOS])].ubShotsPerBurst) || (pSoldier->bWeaponMode != WM_ATTACHED_GL_BURST && pSoldier->bDoBurst > ((pSoldier->bDoAutofire)?(pSoldier->bDoAutofire):(GetShotsPerBurst(&pSoldier->inv[HANDPOS])))) )
|
|
{
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,"AdjustToNextAnimationFrame: Burst case 448, stopping because burst size too large");
|
|
fStop = TRUE;
|
|
fFreeUpAttacker = TRUE;
|
|
}
|
|
|
|
// CHECK IF WE HAVE AMMO LEFT, IF NOT, END ANIMATION!
|
|
if ( !EnoughAmmo( pSoldier, FALSE, pSoldier->ubAttackingHand ) )
|
|
{
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,"AdjustToNextAnimationFrame: Burst case 448, stopping because not enough ammo");
|
|
fStop = TRUE;
|
|
fFreeUpAttacker = TRUE;
|
|
if ( pSoldier->bTeam == gbPlayerNum )
|
|
{
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, TacticalStr[ BURST_FIRE_DEPLETED_CLIP_STR ] );
|
|
}
|
|
}
|
|
// Why only check for a jam on the first bullet?
|
|
else if (pSoldier->bDoBurst == 1)
|
|
{
|
|
// CHECK FOR GUN JAM
|
|
bWeaponJammed = CheckForGunJam( pSoldier );
|
|
if ( bWeaponJammed == TRUE )
|
|
{
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,"AdjustToNextAnimationFrame: Burst case 448, stopping because weapon jammed");
|
|
fStop = TRUE;
|
|
fFreeUpAttacker = TRUE;
|
|
// stop shooting!
|
|
// Yeah, but what does this have to do with that?
|
|
// pSoldier->bBulletsLeft = 0;
|
|
|
|
// OK, Stop burst sound...
|
|
if ( pSoldier->iBurstSoundID != NO_SAMPLE )
|
|
{
|
|
SoundStop( pSoldier->iBurstSoundID );
|
|
}
|
|
|
|
if ( pSoldier->bTeam == gbPlayerNum )
|
|
{
|
|
PlayJA2Sample( S_DRYFIRE1, RATE_11025, SoundVolume( MIDVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ) );
|
|
//ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Gun jammed!" );
|
|
}
|
|
|
|
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("@@@@@@@ Freeing up attacker - aborting start of attack due to burst gun jam") );
|
|
FreeUpAttacker( );
|
|
}
|
|
else if ( bWeaponJammed == 255 )
|
|
{
|
|
// Play intermediate animation...
|
|
if ( HandleUnjamAnimation( pSoldier ) )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( fStop )
|
|
{
|
|
if(pSoldier->bDoAutofire) //reset the autofire cursor after firing
|
|
{
|
|
pSoldier->autofireLastStep = FALSE;
|
|
pSoldier->bDoAutofire = 1;
|
|
}
|
|
|
|
pSoldier->fDoSpread = FALSE;
|
|
pSoldier->bDoBurst = 1;
|
|
// pSoldier->fBurstCompleted = TRUE;
|
|
if ( fFreeUpAttacker )
|
|
{
|
|
// DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("@@@@@@@ Freeing up attacker - aborting start of attack") );
|
|
// FreeUpAttacker( pSoldier->ubID );
|
|
}
|
|
|
|
// ATE; Reduce it due to animation being stopped...
|
|
// 0verhaul: No longer necessary or desired
|
|
// DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("@@@@@@@ Freeing up attacker - Burst animation ended") );
|
|
// ReduceAttackBusyCount( pSoldier->ubID, FALSE );
|
|
|
|
|
|
if ( CheckForImproperFireGunEnd( pSoldier ) )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
|
|
// END: GOTO AIM STANCE BASED ON HEIGHT
|
|
// If we are a robot - we need to do stuff different here
|
|
// 0verhaul: Ya know, if the robot simply used the same animation for standing and rifle standing,
|
|
// we probably wouldn't need this special case code.
|
|
if ( AM_A_ROBOT( pSoldier ) )
|
|
{
|
|
ChangeSoldierState( pSoldier, STANDING, 0 , FALSE );
|
|
}
|
|
else
|
|
{
|
|
switch ( gAnimControl[ pSoldier->usAnimState ].ubEndHeight )
|
|
{
|
|
case ANIM_STAND:
|
|
ChangeSoldierState( pSoldier, AIM_RIFLE_STAND, 0 , FALSE );
|
|
break;
|
|
|
|
case ANIM_PRONE:
|
|
ChangeSoldierState( pSoldier, AIM_RIFLE_PRONE, 0 , FALSE );
|
|
break;
|
|
|
|
case ANIM_CROUCH:
|
|
ChangeSoldierState( pSoldier, AIM_RIFLE_CROUCH, 0 , FALSE );
|
|
break;
|
|
|
|
}
|
|
}
|
|
return( TRUE );
|
|
}
|
|
|
|
// MOVETO CURRENT SPREAD LOCATION
|
|
if ( pSoldier->fDoSpread )
|
|
{
|
|
if ( pSoldier->sSpreadLocations[ pSoldier->fDoSpread - 1 ] != 0 )
|
|
{
|
|
EVENT_SetSoldierDirection( pSoldier, (INT8)GetDirectionToGridNoFromGridNo( pSoldier->sGridNo, pSoldier->sSpreadLocations[ pSoldier->fDoSpread - 1 ] ) );
|
|
EVENT_SetSoldierDesiredDirection( pSoldier, pSoldier->bDirection );
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 449:
|
|
|
|
//CODE: FINISH BURST
|
|
pSoldier->fDoSpread = FALSE;
|
|
pSoldier->bDoBurst = 1;
|
|
// pSoldier->fBurstCompleted = TRUE;
|
|
break;
|
|
|
|
case 450:
|
|
|
|
//CODE: BEGINHOPFENCE
|
|
// MOVE TWO FACGIN GRIDNOS
|
|
sNewGridNo = NewGridNo( (UINT16)pSoldier->sGridNo, (UINT16)( DirectionInc( pSoldier->bDirection ) ) );
|
|
sNewGridNo = NewGridNo( (UINT16)sNewGridNo, (UINT16)( DirectionInc( pSoldier->bDirection ) ) );
|
|
pSoldier->sForcastGridno = sNewGridNo;
|
|
break;
|
|
|
|
|
|
case 451:
|
|
|
|
// CODE: MANAGE START z-buffer override
|
|
switch( pSoldier->bDirection )
|
|
{
|
|
case NORTH:
|
|
case WEST:
|
|
|
|
pSoldier->sZLevelOverride = TOPMOST_Z_LEVEL;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 452:
|
|
|
|
// CODE: MANAGE END z-buffer override
|
|
switch( pSoldier->bDirection )
|
|
{
|
|
case SOUTH:
|
|
case EAST:
|
|
|
|
pSoldier->sZLevelOverride = TOPMOST_Z_LEVEL;
|
|
break;
|
|
|
|
case NORTH:
|
|
case WEST:
|
|
|
|
pSoldier->sZLevelOverride = -1;
|
|
break;
|
|
|
|
}
|
|
break;
|
|
|
|
case 453:
|
|
|
|
//CODE: FALLOFF ROOF ( BACKWARDS ) - MOVE BACK SOME!
|
|
// Use same function as forward, but is -ve values!
|
|
MoveMercFacingDirection( pSoldier , TRUE, (FLOAT)gFalloffBackwardsDist[ pSoldier->ubBodyType ] );
|
|
break;
|
|
|
|
case 454:
|
|
|
|
// CODE: HANDLE CLIMBING ROOF,
|
|
// Move merc up
|
|
if ( pSoldier->bDirection == NORTH )
|
|
{
|
|
SetSoldierHeight( pSoldier, (FLOAT)(pSoldier->dHeightAdjustment + gClimbUpRoofDist[ pSoldier->ubBodyType ] ) );
|
|
}
|
|
else
|
|
{
|
|
SetSoldierHeight( pSoldier, (FLOAT)(pSoldier->dHeightAdjustment + gClimbUpRoofDist[ pSoldier->ubBodyType ] ) );
|
|
}
|
|
break;
|
|
|
|
case 455:
|
|
|
|
// MOVE GUY FORWARD SOME VALUE
|
|
MoveMercFacingDirection( pSoldier, FALSE, (FLOAT)gClimbUpRoofLATDist[ pSoldier->ubBodyType ] );
|
|
|
|
// MOVE DOWN SOME VALUE TOO!
|
|
SetSoldierHeight( pSoldier, (FLOAT)(pSoldier->dHeightAdjustment - gClimbUpRoofDistGoingLower[ pSoldier->ubBodyType ] ) );
|
|
|
|
break;
|
|
|
|
case 456:
|
|
|
|
// CODE: HANDLE CLIMBING ROOF,
|
|
// Move merc DOWN
|
|
if ( pSoldier->bDirection == NORTH )
|
|
{
|
|
SetSoldierHeight( pSoldier, (FLOAT)(pSoldier->dHeightAdjustment - gClimbUpRoofDist[ pSoldier->ubBodyType ] ) );
|
|
}
|
|
else
|
|
{
|
|
SetSoldierHeight( pSoldier, (FLOAT)(pSoldier->dHeightAdjustment - gClimbUpRoofDist[ pSoldier->ubBodyType ] ) );
|
|
}
|
|
break;
|
|
|
|
case 457:
|
|
|
|
// CODE: CHANGCE STANCE TO STANDING
|
|
SendChangeSoldierStanceEvent( pSoldier, ANIM_STAND );
|
|
break;
|
|
|
|
case 459:
|
|
|
|
// CODE: CHANGE ATTACKING TO FIRST HAND
|
|
pSoldier->ubAttackingHand = HANDPOS;
|
|
pSoldier->usAttackingWeapon = pSoldier->inv[pSoldier->ubAttackingHand].usItem;
|
|
// Adjust fReloading to FALSE
|
|
pSoldier->fReloading = FALSE;
|
|
break;
|
|
|
|
case 458:
|
|
|
|
// CODE: CHANGE ATTACKING TO SECOND HAND
|
|
pSoldier->ubAttackingHand = SECONDHANDPOS;
|
|
pSoldier->usAttackingWeapon = pSoldier->inv[pSoldier->ubAttackingHand].usItem;
|
|
// Adjust fReloading to FALSE
|
|
pSoldier->fReloading = FALSE;
|
|
break;
|
|
|
|
case 460:
|
|
case 461:
|
|
|
|
//CODE: THORW ITEM
|
|
// Launch ITem!
|
|
if ( pSoldier->pTempObject != NULL && pSoldier->pThrowParams != NULL )
|
|
{
|
|
// ATE: If we are armmed...
|
|
if ( pSoldier->pThrowParams->ubActionCode == THROW_ARM_ITEM )
|
|
{
|
|
//AXP 25.03.2007: MinAPsToThrow now actually returns the real cost, not 0
|
|
// ATE: Deduct points!
|
|
DeductPoints( pSoldier, MinAPsToThrow( pSoldier, pSoldier->sTargetGridNo, FALSE ), 0 );
|
|
}
|
|
else
|
|
{
|
|
// ATE: Deduct points!
|
|
DeductPoints( pSoldier, AP_TOSS_ITEM, 0 );
|
|
}
|
|
|
|
CreatePhysicalObject( pSoldier->pTempObject, pSoldier->pThrowParams->dLifeSpan, pSoldier->pThrowParams->dX, pSoldier->pThrowParams->dY, pSoldier->pThrowParams->dZ, pSoldier->pThrowParams->dForceX, pSoldier->pThrowParams->dForceY, pSoldier->pThrowParams->dForceZ, pSoldier->ubID, pSoldier->pThrowParams->ubActionCode, pSoldier->pThrowParams->uiActionData, FALSE );
|
|
|
|
// Remove object
|
|
//RemoveObjFrom( &(pSoldier->inv[ HANDPOS ] ), 0 );
|
|
|
|
// Update UI
|
|
DirtyMercPanelInterface( pSoldier, DIRTYLEVEL2 );
|
|
|
|
MemFree( pSoldier->pTempObject );
|
|
pSoldier->pTempObject = NULL;
|
|
|
|
MemFree( pSoldier->pThrowParams );
|
|
pSoldier->pThrowParams = NULL;
|
|
}
|
|
break;
|
|
|
|
case 462:
|
|
|
|
// CODE: MOVE UP FROM CLIFF CLIMB
|
|
pSoldier->dHeightAdjustment += (float)2.1;
|
|
pSoldier->sHeightAdjustment = (INT16)pSoldier->dHeightAdjustment;
|
|
// Move over some...
|
|
//MoveMercFacingDirection( pSoldier , FALSE, (FLOAT)0.5 );
|
|
break;
|
|
|
|
case 463:
|
|
|
|
// MOVE GUY FORWARD SOME VALUE
|
|
// Creature move
|
|
MoveMercFacingDirection( pSoldier, FALSE, (FLOAT)1.5 );
|
|
break;
|
|
|
|
case 464:
|
|
|
|
// CODE: END CLIFF CLIMB
|
|
pSoldier->dHeightAdjustment = (float)0;
|
|
pSoldier->sHeightAdjustment = (INT16)pSoldier->dHeightAdjustment;
|
|
|
|
// Set new gridno
|
|
{
|
|
INT16 sTempGridNo, sNewX, sNewY;
|
|
|
|
//Get Next GridNo;
|
|
sTempGridNo = NewGridNo( (UINT16)pSoldier->sGridNo, (INT16)( DirectionInc(pSoldier->bDirection ) ) );
|
|
|
|
// Get center XY
|
|
ConvertGridNoToCenterCellXY( sTempGridNo, &sNewX, &sNewY );
|
|
|
|
// Set position
|
|
EVENT_SetSoldierPosition( pSoldier, sNewX, sNewY );
|
|
|
|
// Move two CC directions
|
|
EVENT_SetSoldierDirection( pSoldier, gTwoCCDirection[ pSoldier->bDirection ] );
|
|
EVENT_SetSoldierDesiredDirection( pSoldier, pSoldier->bDirection );
|
|
|
|
// Set desired anim height!
|
|
pSoldier->ubDesiredHeight = ANIM_CROUCH;
|
|
pSoldier->sFinalDestination = pSoldier->sGridNo;
|
|
|
|
}
|
|
break;
|
|
|
|
case 465:
|
|
|
|
// CODE: SET GUY TO LIFE OF 0
|
|
pSoldier->bLife = 0;
|
|
break;
|
|
|
|
case 466:
|
|
|
|
// CODE: ADJUST TO OUR DEST HEIGHT
|
|
if ( pSoldier->sHeightAdjustment != pSoldier->sDesiredHeight )
|
|
{
|
|
INT16 sDiff = pSoldier->sHeightAdjustment - pSoldier->sDesiredHeight;
|
|
|
|
if ( abs( sDiff ) > 4 )
|
|
{
|
|
if ( sDiff > 0 )
|
|
{
|
|
// Adjust!
|
|
SetSoldierHeight( pSoldier, (FLOAT)(pSoldier->dHeightAdjustment - 2 ) );
|
|
}
|
|
else
|
|
{
|
|
// Adjust!
|
|
SetSoldierHeight( pSoldier, (FLOAT)(pSoldier->dHeightAdjustment + 2 ) );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Adjust!
|
|
SetSoldierHeight( pSoldier, (FLOAT)(pSoldier->sDesiredHeight) );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Goto eating animation
|
|
if ( pSoldier->sDesiredHeight == 0 )
|
|
{
|
|
ChangeSoldierState( pSoldier, CROW_EAT, 0 , FALSE );
|
|
}
|
|
else
|
|
{
|
|
// We should leave now!
|
|
TacticalRemoveSoldier( pSoldier->ubID );
|
|
return( FALSE );
|
|
}
|
|
return( TRUE );
|
|
}
|
|
break;
|
|
|
|
case 467:
|
|
|
|
///CODE: FOR HELIDROP, SET DIRECTION
|
|
EVENT_SetSoldierDirection( pSoldier, EAST );
|
|
EVENT_SetSoldierDesiredDirection( pSoldier, pSoldier->bDirection );
|
|
|
|
gfIngagedInDrop = FALSE;
|
|
|
|
// OK, now get a sweetspot ( not the place we are now! )
|
|
// sNewGridNo = FindGridNoFromSweetSpotExcludingSweetSpot( pSoldier, pSoldier->sGridNo, 5, &ubNewDirection );
|
|
//sNewGridNo = FindRandomGridNoFromSweetSpotExcludingSweetSpot( pSoldier, pSoldier->sGridNo, 3, &ubNewDirection );
|
|
|
|
sNewGridNo = FindGridNoFromSweetSpotExcludingSweetSpotInQuardent( pSoldier, pSoldier->sGridNo, 3, &ubNewDirection, SOUTHEAST );
|
|
|
|
// Check for merc arrives quotes...
|
|
HandleMercArrivesQuotes( pSoldier );
|
|
|
|
// Find a path to it!
|
|
EVENT_GetNewSoldierPath( pSoldier, sNewGridNo, WALKING );
|
|
|
|
return( TRUE );
|
|
break;
|
|
|
|
case 468:
|
|
|
|
// CODE: End PUNCH
|
|
{
|
|
BOOLEAN fNPCPunch = FALSE;
|
|
|
|
// ATE: Put some code in for NPC punches...
|
|
if ( pSoldier->uiStatusFlags & SOLDIER_NPC_DOING_PUNCH )
|
|
{
|
|
fNPCPunch = TRUE;
|
|
|
|
// Turn off
|
|
pSoldier->uiStatusFlags &= (~SOLDIER_NPC_DOING_PUNCH );
|
|
|
|
// Trigger approach...
|
|
TriggerNPCWithGivenApproach( pSoldier->ubProfile, (UINT8)pSoldier->uiPendingActionData4, FALSE );
|
|
}
|
|
|
|
|
|
// Are we a martial artist?
|
|
{
|
|
BOOLEAN fMartialArtist = FALSE;
|
|
|
|
if ( pSoldier->ubProfile != NO_PROFILE )
|
|
{
|
|
if ( gMercProfiles[ pSoldier->ubProfile ].bSkillTrait == MARTIALARTS || gMercProfiles[ pSoldier->ubProfile ].bSkillTrait2 == MARTIALARTS )
|
|
{
|
|
fMartialArtist = TRUE;
|
|
}
|
|
}
|
|
|
|
if ( gAnimControl[ pSoldier->usAnimState ].ubHeight == ANIM_CROUCH )
|
|
{
|
|
if ( fNPCPunch )
|
|
{
|
|
ChangeSoldierStance( pSoldier, ANIM_STAND );
|
|
return( TRUE );
|
|
}
|
|
else
|
|
{
|
|
ChangeSoldierState( pSoldier, CROUCHING, 0, FALSE );
|
|
return( TRUE );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( fMartialArtist && !AreInMeanwhile( ) )
|
|
{
|
|
ChangeSoldierState( pSoldier, NINJA_BREATH, 0, FALSE );
|
|
return( TRUE );
|
|
}
|
|
else
|
|
{
|
|
ChangeSoldierState( pSoldier, PUNCH_BREATH, 0, FALSE );
|
|
return( TRUE );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 469:
|
|
|
|
// CODE: Begin martial artist attack
|
|
DoNinjaAttack( pSoldier );
|
|
return( TRUE );
|
|
break;
|
|
|
|
case 470:
|
|
|
|
// CODE: CHECK FOR OK WEAPON SHOT!
|
|
bOKFireWeapon = OKFireWeapon( pSoldier );
|
|
|
|
if ( bOKFireWeapon == FALSE )
|
|
{
|
|
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("Fire Weapon: Gun Cannot fire, code 470") );
|
|
|
|
// OK, SKIP x # OF FRAMES
|
|
// Skip 3 frames, ( a third ia added at the end of switch.. ) For a total of 4
|
|
pSoldier->usAniCode += 4;
|
|
|
|
// Reduce by a bullet...
|
|
// pSoldier->bBulletsLeft--;
|
|
|
|
PlayJA2Sample( S_DRYFIRE1, RATE_11025, SoundVolume( MIDVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ) );
|
|
|
|
// Free-up!
|
|
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("@@@@@@@ Freeing up attacker - gun failed to fire") );
|
|
FreeUpAttacker( );
|
|
|
|
}
|
|
else if ( bOKFireWeapon == 255 )
|
|
{
|
|
// Play intermediate animation...
|
|
if ( HandleUnjamAnimation( pSoldier ) )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 471:
|
|
|
|
// CODE: Turn pause move flag off
|
|
pSoldier->uiStatusFlags &= (~SOLDIER_PAUSEANIMOVE);
|
|
break;
|
|
|
|
case 472:
|
|
|
|
{
|
|
BOOLEAN fGoBackToAimAfterHit;
|
|
|
|
// Save old flag, then reset. If we do nothing special here, at least go back
|
|
// to aim if we were.
|
|
fGoBackToAimAfterHit = pSoldier->fGoBackToAimAfterHit;
|
|
pSoldier->fGoBackToAimAfterHit = FALSE;
|
|
|
|
if ( !( pSoldier->uiStatusFlags & SOLDIER_TURNINGFROMHIT ) )
|
|
{
|
|
switch( gAnimControl[ pSoldier->usAnimState ].ubEndHeight )
|
|
{
|
|
case ANIM_STAND:
|
|
|
|
// OK, we can do some cool things here - first is to make guy walkl back a bit...
|
|
// ChangeSoldierState( pSoldier, STANDING_HIT_BEGINCROUCHDOWN, 0, FALSE );
|
|
// return( TRUE );
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
// CODE: HANDLE ANY RANDOM HIT VARIATIONS WE WISH TO DO.....
|
|
if ( fGoBackToAimAfterHit )
|
|
{
|
|
if ( pSoldier->bLife >= OKLIFE )
|
|
{
|
|
InternalSoldierReadyWeapon( pSoldier, pSoldier->bDirection, FALSE );
|
|
}
|
|
return( TRUE );
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 473:
|
|
|
|
// CODE: CHECK IF WE HAVE JUST JAMMED / OUT OF AMMO, DONOT CONTINUE, BUT
|
|
// GOTO STATIONARY ANIM
|
|
if ( CheckForImproperFireGunEnd( pSoldier ) )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
break;
|
|
|
|
case 474:
|
|
|
|
// CODE: GETUP FROM SLEEP
|
|
ChangeSoldierStance( pSoldier, ANIM_STAND );
|
|
return( TRUE );
|
|
|
|
case 475:
|
|
|
|
// CODE: END CLIMB DOWN ROOF
|
|
pSoldier->ubDesiredHeight = ANIM_STAND;
|
|
pSoldier->sFinalDestination = pSoldier->sGridNo;
|
|
|
|
// re-enable sight
|
|
gTacticalStatus.uiFlags &= (~DISALLOW_SIGHT);
|
|
|
|
// ATE: Change interface level.....
|
|
// CJC: only if we are a player merc
|
|
if ( (pSoldier->bTeam == gbPlayerNum) && !gTacticalStatus.fAutoBandageMode)
|
|
{
|
|
if ( pSoldier->ubID == gusSelectedSoldier )
|
|
{
|
|
ChangeInterfaceLevel( 0 );
|
|
}
|
|
// OK, UNSET INTERFACE FIRST
|
|
UnSetUIBusy( pSoldier->ubID );
|
|
}
|
|
else
|
|
{
|
|
FreeUpNPCFromRoofClimb( pSoldier );
|
|
}
|
|
pSoldier->usUIMovementMode = WALKING;
|
|
|
|
// ATE: Handle sight...
|
|
HandleSight( pSoldier,SIGHT_LOOK | SIGHT_RADIO | SIGHT_INTERRUPT );
|
|
break;
|
|
|
|
case 476:
|
|
|
|
// CODE: GOTO PREVIOUS ANIMATION
|
|
ChangeSoldierState( pSoldier, ( pSoldier->sPendingActionData2 ), (UINT8)( pSoldier->uiPendingActionData1 + 1 ), FALSE );
|
|
return( TRUE );
|
|
break;
|
|
|
|
|
|
case 477:
|
|
|
|
// CODE: Locate to target ( if an AI guy.. )
|
|
if ( gTacticalStatus.uiFlags & TURNBASED && (gTacticalStatus.uiFlags & INCOMBAT ) )
|
|
{
|
|
if ( pSoldier->bTeam != gbPlayerNum )
|
|
{
|
|
// only locate if the enemy is visible or he's aiming at a player
|
|
if ( pSoldier->bVisible != -1 || (pSoldier->ubTargetID != NOBODY && MercPtrs[ pSoldier->ubTargetID ]->bTeam == gbPlayerNum) )
|
|
{
|
|
LocateGridNo( pSoldier->sTargetGridNo );
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 478:
|
|
|
|
// CODE: Decide to turn from hit.......
|
|
{
|
|
INT8 bNewDirection;
|
|
UINT32 uiChance;
|
|
|
|
// ONLY DO THIS IF CERTAIN CONDITIONS ARISE!
|
|
// For one, only do for mercs!
|
|
if ( pSoldier->ubBodyType <= REGFEMALE )
|
|
{
|
|
// Secondly, don't if we are going to collapse
|
|
if ( pSoldier->bLife >= OKLIFE && pSoldier->bBreath > 0 && pSoldier->bLevel == 0 )
|
|
{
|
|
// Save old direction
|
|
pSoldier->uiPendingActionData1 = pSoldier->bDirection;
|
|
|
|
// If we got a head shot...more chance of turning...
|
|
if ( pSoldier->ubHitLocation != AIM_SHOT_HEAD )
|
|
{
|
|
uiChance = Random( 100 );
|
|
|
|
// 30 % chance to change direction one way
|
|
if ( uiChance < 30 )
|
|
{
|
|
bNewDirection = gOneCDirection[ pSoldier->bDirection ];
|
|
}
|
|
// 30 % chance to change direction the other way
|
|
else if ( uiChance >= 30 && uiChance < 60 )
|
|
{
|
|
bNewDirection = gOneCCDirection[ pSoldier->bDirection ];
|
|
}
|
|
// 30 % normal....
|
|
else
|
|
{
|
|
bNewDirection = pSoldier->bDirection;
|
|
}
|
|
|
|
EVENT_SetSoldierDirection( pSoldier, bNewDirection );
|
|
EVENT_SetSoldierDesiredDirection( pSoldier, pSoldier->bDirection );
|
|
|
|
}
|
|
else
|
|
{
|
|
// OK, 50% chance here to turn...
|
|
uiChance = Random( 100 );
|
|
|
|
if ( uiChance < 50 )
|
|
{
|
|
// OK, pick a larger direction to goto....
|
|
pSoldier->uiStatusFlags |= SOLDIER_TURNINGFROMHIT;
|
|
// This becomes an attack busy situation
|
|
gTacticalStatus.ubAttackBusyCount++;
|
|
DebugAttackBusy( String( "Soldier turning from a hit. Increasing attack busy. Now %d\n", gTacticalStatus.ubAttackBusyCount ) );
|
|
|
|
// Pick evenly between both
|
|
if ( Random( 50 ) < 25 )
|
|
{
|
|
bNewDirection = gOneCDirection[ pSoldier->bDirection ];
|
|
bNewDirection = gOneCDirection[ bNewDirection ];
|
|
bNewDirection = gOneCDirection[ bNewDirection ];
|
|
}
|
|
else
|
|
{
|
|
bNewDirection = gOneCCDirection[ pSoldier->bDirection ];
|
|
bNewDirection = gOneCCDirection[ bNewDirection ];
|
|
bNewDirection = gOneCCDirection[ bNewDirection ];
|
|
}
|
|
|
|
EVENT_SetSoldierDesiredDirection( pSoldier, bNewDirection );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
case 479:
|
|
|
|
// CODE: Return to old direction......
|
|
if ( pSoldier->ubBodyType <= REGFEMALE )
|
|
{
|
|
// Secondly, don't if we are going to collapse
|
|
//if ( pSoldier->bLife >= OKLIFE && pSoldier->bBreath > 0 )
|
|
//{
|
|
/// if ( !( pSoldier->uiStatusFlags & SOLDIER_TURNINGFROMHIT ) )
|
|
// {
|
|
/// pSoldier->bDirection = (INT8)pSoldier->uiPendingActionData1;
|
|
// pSoldier->bDesiredDirection = (INT8)pSoldier->uiPendingActionData1;
|
|
// }
|
|
//}
|
|
}
|
|
break;
|
|
|
|
case 480:
|
|
|
|
// 0verhaul: This is handled in the ReduceAttackBusyCount call
|
|
// CODE: FORCE FREE ATTACKER
|
|
// Release attacker
|
|
//DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("@@@@@@@ Releasesoldierattacker, code 480") );
|
|
|
|
//ReleaseSoldiersAttacker( pSoldier );
|
|
|
|
//FREEUP GETTING HIT FLAG
|
|
//pSoldier->fGettingHit = FALSE;
|
|
break;
|
|
|
|
case 481:
|
|
|
|
// CODE: CUT FENCE...
|
|
CutWireFence( pSoldier->sTargetGridNo );
|
|
break;
|
|
|
|
case 482:
|
|
|
|
// CODE: END CRIPPLE KICKOUT...
|
|
KickOutWheelchair( pSoldier );
|
|
break;
|
|
|
|
case 483:
|
|
|
|
// CODE: HANDLE DROP BOMB...
|
|
HandleSoldierDropBomb( pSoldier, pSoldier->sPendingActionData2 );
|
|
break;
|
|
|
|
case 484:
|
|
|
|
// CODE: HANDLE REMOTE...
|
|
HandleSoldierUseRemote( pSoldier, pSoldier->sPendingActionData2 );
|
|
break;
|
|
|
|
case 485:
|
|
|
|
// CODE: Try steal.....
|
|
// UnSetUIBusy( pSoldier->ubID);
|
|
UseHandToHand( pSoldier, pSoldier->sPendingActionData2, TRUE );
|
|
//jackaians:
|
|
//if we are not waiting for the pickup menu to be displayed
|
|
// if (guiPendingOverrideEvent != G_GETTINGITEM)
|
|
// {
|
|
// PreventFromTheFreezingBug(pSoldier);
|
|
// }
|
|
break;
|
|
|
|
case 486:
|
|
|
|
// CODE: GIVE ITEM
|
|
SoldierGiveItemFromAnimation( pSoldier );
|
|
if (pSoldier->ubProfile != NO_PROFILE && pSoldier->ubProfile >= FIRST_NPC )
|
|
{
|
|
TriggerNPCWithGivenApproach( pSoldier->ubProfile, APPROACH_DONE_GIVING_ITEM, FALSE );
|
|
}
|
|
break;
|
|
|
|
case 487:
|
|
|
|
// CODE: DROP ITEM
|
|
SoldierHandleDropItem( pSoldier );
|
|
break;
|
|
|
|
case 489:
|
|
|
|
|
|
//CODE: REMOVE GUY FRMO WORLD DUE TO EXPLOSION
|
|
//ChangeSoldierState( pSoldier, RAISE_RIFLE, 0 , FALSE );
|
|
//return( TRUE );
|
|
//Delete guy
|
|
//TacticalRemoveSoldier( pSoldier->ubID );
|
|
//return( FALSE );
|
|
break;
|
|
|
|
case 490:
|
|
|
|
// CODE: HANDLE END ITEM PICKUP
|
|
//LOOK INTO HAND, RAISE RIFLE IF WE HAVE ONE....
|
|
/*
|
|
if ( pSoldier->inv[ HANDPOS ].usItem != NOTHING )
|
|
{
|
|
// CHECK IF GUN
|
|
if ( Item[ pSoldier->inv[ HANDPOS ].usItem ].usItemClass == IC_GUN )
|
|
{
|
|
if ( Weapon[ pSoldier->inv[ HANDPOS ].usItem ].ubWeaponClass != HANDGUNCLASS )
|
|
{
|
|
// RAISE
|
|
ChangeSoldierState( pSoldier, RAISE_RIFLE, 0 , FALSE );
|
|
return( TRUE );
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
*/
|
|
break;
|
|
|
|
case 491:
|
|
|
|
// CODE: HANDLE RANDOM BREATH ANIMATION
|
|
//if ( pSoldier->bLife > INJURED_CHANGE_THREASHOLD )
|
|
if ( pSoldier->bLife >= OKLIFE )
|
|
{
|
|
// Increment time from last update
|
|
pSoldier->uiTimeOfLastRandomAction++;
|
|
|
|
if ( pSoldier->uiTimeOfLastRandomAction > TIME_FOR_RANDOM_ANIM_CHECK || pSoldier->bLife < INJURED_CHANGE_THREASHOLD || GetDrunkLevel( pSoldier ) >= BORDERLINE )
|
|
{
|
|
pSoldier->uiTimeOfLastRandomAction = 0;
|
|
|
|
// Don't do any in water!
|
|
if ( !MercInWater( pSoldier ) )
|
|
{
|
|
// OK, make a dice roll
|
|
ubDiceRoll = (UINT8)Random( 100 );
|
|
|
|
// Determine what is in our hand;
|
|
usItem = pSoldier->inv[ HANDPOS ].usItem;
|
|
|
|
// Default to nothing in hand ( nothing in quotes, we do have something but not just visible )
|
|
ubRandomHandIndex = RANDOM_ANIM_NOTHINGINHAND;
|
|
|
|
if ( usItem != NOTHING )
|
|
{
|
|
if ( Item[ usItem ].usItemClass == IC_GUN )
|
|
{
|
|
// if ( (Item[ usItem ].fFlags & ITEM_TWO_HANDED) )
|
|
if ( (Item[ usItem ].twohanded ) )
|
|
{
|
|
// Set to rifle
|
|
ubRandomHandIndex = RANDOM_ANIM_RIFLEINHAND;
|
|
}
|
|
else
|
|
{
|
|
// Don't EVER do a trivial anim...
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Check which animation to play....
|
|
for ( cnt = 0; cnt < MAX_RANDOM_ANIMS_PER_BODYTYPE; cnt++ )
|
|
{
|
|
pAnimDef = &( gRandomAnimDefs[ pSoldier->ubBodyType ][ cnt ] );
|
|
|
|
if ( pAnimDef->sAnimID != 0 )
|
|
{
|
|
// If it's an injured animation and we are not in the threashold....
|
|
if ( ( pAnimDef->ubFlags & RANDOM_ANIM_INJURED ) && pSoldier->bLife >= INJURED_CHANGE_THREASHOLD )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// If we need to do an injured one, don't do any others...
|
|
if ( !( pAnimDef->ubFlags & RANDOM_ANIM_INJURED ) && pSoldier->bLife < INJURED_CHANGE_THREASHOLD )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// If it's a drunk animation and we are not in the threashold....
|
|
if ( ( pAnimDef->ubFlags & RANDOM_ANIM_DRUNK ) && GetDrunkLevel( pSoldier ) < BORDERLINE )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// If we need to do an injured one, don't do any others...
|
|
if ( !( pAnimDef->ubFlags & RANDOM_ANIM_DRUNK ) && GetDrunkLevel( pSoldier ) >= BORDERLINE )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// Check if it's our hand
|
|
if ( pAnimDef->ubHandRestriction != RANDOM_ANIM_IRRELEVENTINHAND && pAnimDef->ubHandRestriction != ubRandomHandIndex )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// Check if it's casual and we're in combat and it's not our guy
|
|
if ( ( pAnimDef->ubFlags & RANDOM_ANIM_CASUAL ) )
|
|
{
|
|
// If he's a bad guy, do not do it!
|
|
if ( pSoldier->bTeam != gbPlayerNum || ( gTacticalStatus.uiFlags & INCOMBAT ) )
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
|
|
// If we are an alternate big guy and have been told to use a normal big merc ani...
|
|
if ( ( pAnimDef->ubFlags & RANDOM_ANIM_FIRSTBIGMERC ) && ( pSoldier->uiAnimSubFlags & SUB_ANIM_BIGGUYTHREATENSTANCE ) )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// If we are a normal big guy and have been told to use an alternate big merc ani...
|
|
if ( ( pAnimDef->ubFlags & RANDOM_ANIM_SECONDBIGMERC ) && !( pSoldier->uiAnimSubFlags & SUB_ANIM_BIGGUYTHREATENSTANCE ) )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// Check if it's the proper height
|
|
if ( pAnimDef->ubAnimHeight == gAnimControl[ pSoldier->usAnimState ].ubEndHeight )
|
|
{
|
|
// OK, If we rolled a value that lies within the range for this random animation, use this one!
|
|
if ( ubDiceRoll >= pAnimDef->ubStartRoll && ubDiceRoll <= pAnimDef->ubEndRoll )
|
|
{
|
|
// Are we playing a sound
|
|
if ( pAnimDef->sAnimID == RANDOM_ANIM_SOUND )
|
|
{
|
|
if ( pSoldier->ubBodyType == COW )
|
|
{
|
|
if ( Random( 2 ) == 1 )
|
|
{
|
|
if ( ( gTacticalStatus.uiFlags & INCOMBAT ) && pSoldier->bVisible == -1 )
|
|
{
|
|
// DO this every 10th time or so...
|
|
if ( Random( 100 ) < 10 )
|
|
{
|
|
// Play sound
|
|
PlayJA2SampleFromFile( pAnimDef->zSoundFile, RATE_11025, SoundVolume( MIDVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ) );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
// Play sound
|
|
PlayJA2SampleFromFile( pAnimDef->zSoundFile, RATE_11025, SoundVolume( MIDVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ) );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Play sound
|
|
PlayJA2SampleFromFile( pAnimDef->zSoundFile, RATE_11025, SoundVolume( MIDVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ) );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ChangeSoldierState( pSoldier, pAnimDef->sAnimID, 0 , FALSE );
|
|
}
|
|
return( TRUE );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 492:
|
|
|
|
|
|
// SIGNAL DODGE!
|
|
// ATE: Only do if we're not inspecial case...
|
|
if ( !( pSoldier->uiStatusFlags & SOLDIER_NPC_DOING_PUNCH ) )
|
|
{
|
|
SOLDIERTYPE *pTSoldier;
|
|
UINT32 uiMercFlags;
|
|
UINT16 usSoldierIndex;
|
|
|
|
if ( FindSoldier( pSoldier->sTargetGridNo, &usSoldierIndex, &uiMercFlags, FIND_SOLDIER_GRIDNO ) )
|
|
{
|
|
GetSoldier( &pTSoldier, usSoldierIndex );
|
|
|
|
// IF WE ARE AN ANIMAL, CAR, MONSTER, DONT'T DODGE
|
|
if ( IS_MERC_BODY_TYPE( pTSoldier ) )
|
|
{
|
|
// ONLY DODGE IF WE ARE SEEN
|
|
if ( pTSoldier->bOppList[ pSoldier->ubID ] != 0 || pTSoldier->bTeam == pSoldier->bTeam )
|
|
{
|
|
if ( gAnimControl[ pTSoldier->usAnimState ].ubHeight == ANIM_STAND )
|
|
{
|
|
// OK, stop merc....
|
|
EVENT_StopMerc( pTSoldier, pTSoldier->sGridNo, pTSoldier->bDirection );
|
|
|
|
if ( pTSoldier->bTeam != gbPlayerNum )
|
|
{
|
|
CancelAIAction( pTSoldier, TRUE );
|
|
}
|
|
|
|
// Turn towards the person!
|
|
EVENT_SetSoldierDesiredDirection( pTSoldier, GetDirectionFromGridNo( pSoldier->sGridNo, pTSoldier ) );
|
|
|
|
// PLAY SOLDIER'S DODGE ANIMATION
|
|
ChangeSoldierState( pTSoldier, DODGE_ONE, 0 , FALSE );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 493:
|
|
|
|
//CODE: PICKUP ITEM!
|
|
// CHECK IF THIS EVENT HAS BEEN SETUP
|
|
//if ( pSoldier->ubPendingAction == MERC_PICKUPITEM )
|
|
//{
|
|
// DROP ITEM
|
|
HandleSoldierPickupItem( pSoldier, pSoldier->uiPendingActionData1, (INT16)(pSoldier->uiPendingActionData4 ), pSoldier->bPendingActionData3 );
|
|
// EVENT HAS BEEN HANDLED
|
|
pSoldier->ubPendingAction = NO_PENDING_ACTION;
|
|
|
|
//}
|
|
//else
|
|
//{
|
|
// DebugMsg( TOPIC_JA2, DBG_LEVEL_3, "Soldier Ani: CODE 493 Error, Pickup item action called but not setup" );
|
|
//}
|
|
break;
|
|
|
|
case 494:
|
|
|
|
//CODE: OPEN STRUCT!
|
|
// CHECK IF THIS EVENT HAS BEEN SETUP
|
|
//if ( pSoldier->ubPendingAction == MERC_OPENSTRUCT )
|
|
//{
|
|
SoldierHandleInteractiveObject( pSoldier );
|
|
|
|
// EVENT HAS BEEN HANDLED
|
|
pSoldier->ubPendingAction = NO_PENDING_ACTION;
|
|
|
|
//}
|
|
//else
|
|
//{
|
|
// DebugMsg( TOPIC_JA2, DBG_LEVEL_3, "Soldier Ani: CODE 494 Error, OPen door action called but not setup" );
|
|
//}
|
|
break;
|
|
|
|
case 495:
|
|
|
|
if (pSoldier->bAction == AI_ACTION_UNLOCK_DOOR || (pSoldier->bAction == AI_ACTION_LOCK_DOOR && !(pSoldier->fAIFlags & AI_LOCK_DOOR_INCLUDES_CLOSE) ) )
|
|
{
|
|
// EVENT HAS BEEN HANDLED
|
|
pSoldier->ubPendingAction = NO_PENDING_ACTION;
|
|
|
|
// do nothing here
|
|
}
|
|
else
|
|
{
|
|
|
|
pSoldier->fAIFlags &= ~(AI_LOCK_DOOR_INCLUDES_CLOSE);
|
|
|
|
pSoldier->ubDoorOpeningNoise = DoorOpeningNoise( pSoldier );
|
|
|
|
if ( SoldierHandleInteractiveObject( pSoldier ) )
|
|
{
|
|
// HANDLE SIGHT!
|
|
//HandleSight(pSoldier,SIGHT_LOOK | SIGHT_RADIO | SIGHT_INTERRUPT );
|
|
|
|
InitOpplistForDoorOpening();
|
|
|
|
MakeNoise( pSoldier->ubID, pSoldier->sGridNo, pSoldier->bLevel, gpWorldLevelData[pSoldier->sGridNo].ubTerrainID, pSoldier->ubDoorOpeningNoise, NOISE_CREAKING );
|
|
// gfDelayResolvingBestSighting = FALSE;
|
|
|
|
gubInterruptProvoker = pSoldier->ubID;
|
|
AllTeamsLookForAll( TRUE );
|
|
|
|
// ATE: Now, check AI guy to cancel what he was going....
|
|
HandleSystemNewAISituation( pSoldier, TRUE );
|
|
}
|
|
|
|
// EVENT HAS BEEN HANDLED
|
|
pSoldier->ubPendingAction = NO_PENDING_ACTION;
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
case 496:
|
|
// CODE: GOTO PREVIOUS ANIMATION
|
|
ChangeSoldierState( pSoldier, pSoldier->usOldAniState, pSoldier->sOldAniCode, FALSE );
|
|
return( TRUE );
|
|
|
|
case 497:
|
|
|
|
// CODE: CHECK FOR UNCONSCIOUS OR DEATH
|
|
// IF 496 - GOTO PREVIOUS ANIMATION, OTHERWISE PAUSE ANIMATION
|
|
if ( pSoldier->bLife == 0 )
|
|
{
|
|
|
|
//HandleSoldierDeath( pSoldier );
|
|
|
|
// If guy is now dead, and we have not played death sound before, play
|
|
if ( pSoldier->bLife == 0 && !pSoldier->fDeadSoundPlayed )
|
|
{
|
|
if ( pSoldier->usAnimState != JFK_HITDEATH )
|
|
{
|
|
DoMercBattleSound( pSoldier, BATTLE_SOUND_DIE1 );
|
|
pSoldier->fDeadSoundPlayed = TRUE;
|
|
}
|
|
}
|
|
|
|
if ( gGameSettings.fOptions[ TOPTION_BLOOD_N_GORE ] )
|
|
{
|
|
// If we are dead, play some death animations!!
|
|
switch( pSoldier->usAnimState )
|
|
{
|
|
case FLYBACK_HIT:
|
|
ChangeSoldierState( pSoldier, FLYBACK_HIT_DEATH, 0, FALSE );
|
|
break;
|
|
|
|
case GENERIC_HIT_DEATHTWITCHNB:
|
|
case FALLFORWARD_FROMHIT_STAND:
|
|
case ENDFALLFORWARD_FROMHIT_CROUCH:
|
|
|
|
ChangeSoldierState( pSoldier, GENERIC_HIT_DEATH, 0, FALSE );
|
|
break;
|
|
|
|
case FALLBACK_HIT_DEATHTWITCHNB:
|
|
case FALLBACK_HIT_STAND:
|
|
ChangeSoldierState( pSoldier, FALLBACK_HIT_DEATH, 0, FALSE );
|
|
break;
|
|
|
|
case PRONE_HIT_DEATHTWITCHNB:
|
|
case PRONE_LAY_FROMHIT:
|
|
|
|
ChangeSoldierState( pSoldier, PRONE_HIT_DEATH, 0, FALSE );
|
|
break;
|
|
|
|
case FALLOFF:
|
|
ChangeSoldierState( pSoldier, FALLOFF_DEATH, 0, FALSE );
|
|
break;
|
|
|
|
case FALLFORWARD_ROOF:
|
|
ChangeSoldierState( pSoldier, FALLOFF_FORWARD_DEATH, 0, FALSE);
|
|
break;
|
|
|
|
case ADULTMONSTER_DYING:
|
|
ChangeSoldierState( pSoldier, ADULTMONSTER_DYING_STOP, 0, FALSE);
|
|
break;
|
|
|
|
case LARVAE_DIE:
|
|
ChangeSoldierState( pSoldier, LARVAE_DIE_STOP, 0, FALSE);
|
|
break;
|
|
|
|
case QUEEN_DIE:
|
|
ChangeSoldierState( pSoldier, QUEEN_DIE_STOP, 0, FALSE);
|
|
break;
|
|
|
|
case INFANT_DIE:
|
|
ChangeSoldierState( pSoldier, INFANT_DIE_STOP, 0, FALSE);
|
|
break;
|
|
|
|
case CRIPPLE_DIE:
|
|
ChangeSoldierState( pSoldier, CRIPPLE_DIE_STOP, 0, FALSE);
|
|
break;
|
|
|
|
case ROBOTNW_DIE:
|
|
ChangeSoldierState( pSoldier, ROBOTNW_DIE_STOP, 0, FALSE);
|
|
break;
|
|
|
|
case CRIPPLE_DIE_FLYBACK:
|
|
ChangeSoldierState( pSoldier, CRIPPLE_DIE_FLYBACK_STOP, 0, FALSE);
|
|
break;
|
|
|
|
default:
|
|
// IF we are here - something is wrong - we should have a death animation here
|
|
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String( "Soldier Ani: Death sequence needed for animation %d", pSoldier->usAnimState ) );
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
BOOLEAN fMadeCorpse;
|
|
|
|
CheckForAndHandleSoldierDeath( pSoldier, &fMadeCorpse );
|
|
|
|
// ATE: Needs to be FALSE!
|
|
return( FALSE );
|
|
}
|
|
return( TRUE );
|
|
|
|
}
|
|
else
|
|
{
|
|
// We can safely be here as well.. ( ie - next turn we may be able to get up )
|
|
// DO SOME CHECKS HERE TO FREE UP ATTACKERS IF WE ARE WAITING AT SPECIFIC ANIMATIONS
|
|
if ( ( gAnimControl[ pSoldier->usAnimState ].uiFlags & ANIM_HITFINISH ) )
|
|
{
|
|
gfPotentialTeamChangeDuringDeath = TRUE;
|
|
|
|
// 0verhaul: This is now already handled
|
|
// Release attacker
|
|
// DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("@@@@@@@ Releasesoldierattacker, code 497 = check for death") );
|
|
// ReleaseSoldiersAttacker( pSoldier );
|
|
|
|
// ATE: OK - the above call can potentially
|
|
// render the soldier bactive to false - check heare
|
|
if ( !pSoldier->bActive )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
gfPotentialTeamChangeDuringDeath = FALSE;
|
|
|
|
// FREEUP GETTING HIT FLAG
|
|
pSoldier->fGettingHit = FALSE;
|
|
}
|
|
|
|
HandleCheckForDeathCommonCode( pSoldier );
|
|
|
|
return( TRUE );
|
|
}
|
|
break;
|
|
|
|
case 498:
|
|
|
|
// CONDITONAL JUMP
|
|
// If we have a pending animation, play it, else continue
|
|
if ( pSoldier->usPendingAnimation != NO_PENDING_ANIMATION )
|
|
{
|
|
ChangeSoldierState( pSoldier, pSoldier->usPendingAnimation, 0, FALSE );
|
|
pSoldier->usPendingAnimation = NO_PENDING_ANIMATION;
|
|
return( TRUE );
|
|
}
|
|
break;
|
|
|
|
// JUMP TO NEXT STATIONARY ANIMATION ACCORDING TO HEIGHT
|
|
case 499:
|
|
|
|
if (!(pSoldier->uiStatusFlags & SOLDIER_PC))
|
|
{
|
|
if ( pSoldier->bAction == AI_ACTION_PULL_TRIGGER )
|
|
{
|
|
if ( pSoldier->usAnimState == AI_PULL_SWITCH && gTacticalStatus.ubAttackBusyCount == 0 && gubElementsOnExplosionQueue == 0 )
|
|
{
|
|
FreeUpNPCFromPendingAction( pSoldier );
|
|
}
|
|
}
|
|
else if ( pSoldier->bAction == AI_ACTION_PENDING_ACTION
|
|
|| pSoldier->bAction == AI_ACTION_OPEN_OR_CLOSE_DOOR
|
|
|| pSoldier->bAction == AI_ACTION_YELLOW_ALERT
|
|
|| pSoldier->bAction == AI_ACTION_RED_ALERT
|
|
|| pSoldier->bAction == AI_ACTION_PULL_TRIGGER
|
|
|| pSoldier->bAction == AI_ACTION_CREATURE_CALL
|
|
|| pSoldier->bAction == AI_ACTION_UNLOCK_DOOR
|
|
|| pSoldier->bAction == AI_ACTION_LOCK_DOOR )
|
|
{
|
|
if ( pSoldier->usAnimState == PICKUP_ITEM || pSoldier->usAnimState == ADJACENT_GET_ITEM || pSoldier->usAnimState == DROP_ITEM || pSoldier->usAnimState == END_OPEN_DOOR || pSoldier->usAnimState == END_OPEN_DOOR_CROUCHED || pSoldier->usAnimState == CLOSE_DOOR || pSoldier->usAnimState == MONSTER_UP || pSoldier->usAnimState == AI_RADIO || pSoldier->usAnimState == AI_CR_RADIO || pSoldier->usAnimState == END_OPENSTRUCT || pSoldier->usAnimState == END_OPENSTRUCT_CROUCHED || pSoldier->usAnimState == QUEEN_CALL )
|
|
{
|
|
FreeUpNPCFromPendingAction( pSoldier );
|
|
}
|
|
}
|
|
}
|
|
|
|
ubDesiredHeight = pSoldier->ubDesiredHeight;
|
|
|
|
// Check if we are at the desired height
|
|
if ( pSoldier->ubDesiredHeight == gAnimControl[ pSoldier->usAnimState ].ubEndHeight || pSoldier->ubDesiredHeight == NO_DESIRED_HEIGHT )
|
|
{
|
|
// Adjust movement mode......
|
|
if ( pSoldier->bTeam == gbPlayerNum && !pSoldier->fContinueMoveAfterStanceChange )
|
|
{
|
|
usUIMovementMode = GetMoveStateBasedOnStance( pSoldier, gAnimControl[ pSoldier->usAnimState ].ubEndHeight );
|
|
|
|
// ATE: if we are currently running but have been told to walk, don't!
|
|
if ( pSoldier->usUIMovementMode == RUNNING && usUIMovementMode == WALKING )
|
|
{
|
|
// No!
|
|
}
|
|
else
|
|
{
|
|
pSoldier->usUIMovementMode = usUIMovementMode;
|
|
}
|
|
}
|
|
|
|
|
|
pSoldier->ubDesiredHeight = NO_DESIRED_HEIGHT;
|
|
|
|
// 0verhaul: This is moved to the animation state transition code to make sure it isn't sidestepped.
|
|
// if (pSoldier->fChangingStanceDueToSuppression)
|
|
// {
|
|
// pSoldier->fChangingStanceDueToSuppression = FALSE;
|
|
// DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("@@@@@@@ Freeing up attacker - end of suppression stance change") );
|
|
// ReduceAttackBusyCount( pSoldier->ubSuppressorID, FALSE );
|
|
// }
|
|
|
|
if ( pSoldier->usPendingAnimation == NO_PENDING_ANIMATION && ( pSoldier->fTurningFromPronePosition != 3 ) && ( pSoldier->fTurningFromPronePosition != 1 ) )
|
|
{
|
|
if ( gTacticalStatus.ubAttackBusyCount == 0 )
|
|
{
|
|
// OK, UNSET INTERFACE FIRST
|
|
UnSetUIBusy( pSoldier->ubID );
|
|
// ( before we could get interrupted potentially by an interrupt )
|
|
}
|
|
}
|
|
|
|
// Check to see if we have changed stance and need to update visibility
|
|
if ( gAnimControl[ pSoldier->usAnimState ].uiFlags & ANIM_STANCECHANGEANIM)
|
|
{
|
|
if ( pSoldier->usPendingAnimation == NO_PENDING_ANIMATION && gTacticalStatus.ubAttackBusyCount == 0 && pSoldier->fTurningFromPronePosition != 3 && pSoldier->fTurningFromPronePosition != 1 )
|
|
{
|
|
HandleSight(pSoldier,SIGHT_LOOK | SIGHT_RADIO | SIGHT_INTERRUPT );
|
|
}
|
|
else
|
|
{
|
|
HandleSight(pSoldier,SIGHT_LOOK | SIGHT_RADIO );
|
|
}
|
|
|
|
// Keep ui busy if we are now in a hidden interrupt
|
|
// say we're prone and we crouch, we may get a hidden
|
|
// interrupt and in such a case we'd really like the UI
|
|
// still locked
|
|
if ( gfHiddenInterrupt )
|
|
{
|
|
guiPendingOverrideEvent = LA_BEGINUIOURTURNLOCK;
|
|
HandleTacticalUI( );
|
|
}
|
|
|
|
// ATE: Now, check AI guy to cancel what he was going....
|
|
HandleSystemNewAISituation( pSoldier, TRUE );
|
|
}
|
|
|
|
// Have we finished opening doors?
|
|
if ( pSoldier->usAnimState == END_OPEN_DOOR || pSoldier->usAnimState == END_OPEN_DOOR_CROUCHED || pSoldier->usAnimState == CRIPPLE_CLOSE_DOOR || pSoldier->usAnimState == CRIPPLE_END_OPEN_DOOR )
|
|
{
|
|
// Are we told to continue movement...?
|
|
if ( pSoldier->bEndDoorOpenCode == 1 )
|
|
{
|
|
// OK, set this value to 2 such that once we are into a new gridno,
|
|
// we close the door!
|
|
pSoldier->bEndDoorOpenCode = 2;
|
|
|
|
// yes..
|
|
EVENT_GetNewSoldierPath( pSoldier, pSoldier->sFinalDestination, pSoldier->usUIMovementMode );
|
|
|
|
if ( !( gAnimControl[ pSoldier->usAnimState ].uiFlags & ( ANIM_MOVING ) ) )
|
|
{
|
|
if ( pSoldier->sAbsoluteFinalDestination != NOWHERE )
|
|
{
|
|
CancelAIAction( pSoldier, FORCE );
|
|
}
|
|
}
|
|
|
|
// OK, this code, pSoldier->bEndDoorOpenCode will be set to 0 if anythiing
|
|
// cuases guy to stop - StopMerc() will set it...
|
|
|
|
return( TRUE );
|
|
}
|
|
}
|
|
|
|
// Check if we should contine into a moving animation
|
|
if ( pSoldier->usPendingAnimation != NO_PENDING_ANIMATION )
|
|
{
|
|
UINT16 usPendingAnimation = pSoldier->usPendingAnimation;
|
|
|
|
pSoldier->usPendingAnimation = NO_PENDING_ANIMATION;
|
|
ChangeSoldierState( pSoldier, usPendingAnimation, 0, FALSE );
|
|
return( TRUE );
|
|
}
|
|
|
|
// Alrighty, do we wish to continue
|
|
if ( pSoldier->fContinueMoveAfterStanceChange )
|
|
{
|
|
// OK, if the code is == 2, get the path and try to move....
|
|
if ( pSoldier->fContinueMoveAfterStanceChange == 2 )
|
|
{
|
|
pSoldier->usPathIndex++;
|
|
|
|
if ( pSoldier->usPathIndex > pSoldier->usPathDataSize )
|
|
{
|
|
pSoldier->usPathIndex = pSoldier->usPathDataSize;
|
|
}
|
|
|
|
if ( pSoldier->usPathIndex == pSoldier->usPathDataSize )
|
|
{
|
|
// Stop, don't do anything.....
|
|
// 0verhaul: Only if not at the final destination
|
|
// Another reason for rebuilding the animation system. This should be part of a common
|
|
// path continuation code so that any other bug fixes won't need to be duplicated in other areas.
|
|
if ( pSoldier->sGridNo != pSoldier->sFinalDestination)
|
|
{
|
|
if ( !EVENT_InternalGetNewSoldierPath( pSoldier, pSoldier->sFinalDestination, pSoldier->usUIMovementMode, 2, FALSE ) )
|
|
{
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
EVENT_InitNewSoldierAnim( pSoldier, pSoldier->usUIMovementMode, 0 , FALSE );
|
|
|
|
// UNSET LOCK PENDING ACTION COUNTER FLAG
|
|
pSoldier->uiStatusFlags &= ( ~SOLDIER_LOCKPENDINGACTIONCOUNTER );
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SelectMoveAnimationFromStance( pSoldier );
|
|
}
|
|
|
|
pSoldier->fContinueMoveAfterStanceChange = FALSE;
|
|
return( TRUE );
|
|
}
|
|
SoldierGotoStationaryStance( pSoldier );
|
|
return( TRUE );
|
|
}
|
|
else
|
|
{
|
|
ubCurrentHeight = gAnimControl[ pSoldier->usAnimState ].ubEndHeight;
|
|
|
|
// We need to go more, continue
|
|
if ( ubDesiredHeight == ANIM_STAND && ubCurrentHeight == ANIM_CROUCH )
|
|
{
|
|
// Return here because if now, we will skipp a few frames
|
|
ChangeSoldierState( pSoldier, KNEEL_UP, 0 , FALSE );
|
|
return( TRUE );
|
|
}
|
|
if ( ubDesiredHeight == ANIM_CROUCH && ubCurrentHeight == ANIM_STAND )
|
|
{
|
|
// Return here because if now, we will skipp a few frames
|
|
ChangeSoldierState( pSoldier, KNEEL_DOWN, 0 , FALSE );
|
|
return( TRUE );
|
|
}
|
|
else if ( ubDesiredHeight == ANIM_PRONE && ubCurrentHeight == ANIM_CROUCH )
|
|
{
|
|
// Return here because if now, we will skipp a few frames
|
|
ChangeSoldierState( pSoldier, PRONE_DOWN, 0 , FALSE );
|
|
return( TRUE );
|
|
}
|
|
else if ( ubDesiredHeight == ANIM_CROUCH && ubCurrentHeight == ANIM_PRONE )
|
|
{
|
|
// Return here because if now, we will skipp a few frames
|
|
ChangeSoldierState( pSoldier, PRONE_UP, 0 , FALSE );
|
|
return( TRUE );
|
|
}
|
|
}
|
|
// IF we are here - something is wrong - we should have a death animation here
|
|
#ifdef JA2BETAVERSION
|
|
ScreenMsg( FONT_ORANGE, MSG_BETAVERSION, L"Soldier Ani: GOTO Stance not chained properly: %d %d %d", ubDesiredHeight, ubCurrentHeight, pSoldier->usAnimState );
|
|
#endif
|
|
|
|
SoldierGotoStationaryStance( pSoldier );
|
|
return( TRUE );
|
|
}
|
|
|
|
// Adjust frame control pos, and try again
|
|
pSoldier->usAniCode++;
|
|
|
|
}
|
|
else if ( sNewAniFrame > 499 && sNewAniFrame < 599 )
|
|
{
|
|
// Jump,
|
|
// Do not adjust, just try again
|
|
pSoldier->usAniCode = sNewAniFrame - 501;
|
|
}
|
|
else if ( sNewAniFrame > 599 && sNewAniFrame <= 699 )
|
|
{
|
|
// Jump, to animation script
|
|
EVENT_InitNewSoldierAnim( pSoldier, (UINT16)(sNewAniFrame - 600 ), 0 , FALSE );
|
|
return( TRUE );
|
|
}
|
|
else if ( sNewAniFrame > 799 && sNewAniFrame <= 899 )
|
|
{
|
|
// Jump, to animation script ( But in the 100's range )
|
|
EVENT_InitNewSoldierAnim( pSoldier, (UINT16)(sNewAniFrame - 700 ), 0 , FALSE );
|
|
return( TRUE );
|
|
}
|
|
else if ( sNewAniFrame > 899 && sNewAniFrame <= 999 )
|
|
{
|
|
// Jump, to animation script ( But in the 200's range )
|
|
EVENT_InitNewSoldierAnim( pSoldier, (UINT16)(sNewAniFrame - 700 ), 0 , FALSE );
|
|
return( TRUE );
|
|
}
|
|
else if ( sNewAniFrame > 699 && sNewAniFrame < 799 )
|
|
{
|
|
switch( sNewAniFrame )
|
|
{
|
|
case 702:
|
|
// Play fall to knees sound
|
|
PlaySoldierJA2Sample( pSoldier->ubID, (UINT8)( FALL_1 + Random(2) ), RATE_11025, SoundVolume( HIGHVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ), FALSE );
|
|
break;
|
|
|
|
case 703:
|
|
case 704:
|
|
|
|
// Play footprints
|
|
PlaySoldierFootstepSound( pSoldier );
|
|
break;
|
|
|
|
case 705:
|
|
// PLay body splat sound
|
|
PlaySoldierJA2Sample( pSoldier->ubID, (UINT8)BODY_SPLAT_1, RATE_11025, SoundVolume( HIGHVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ), TRUE );
|
|
break;
|
|
|
|
case 706:
|
|
// PLay head splat
|
|
PlaySoldierJA2Sample( pSoldier->ubID, (UINT8)HEADSPLAT_1, RATE_11025, SoundVolume( HIGHVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ) , TRUE );
|
|
break;
|
|
|
|
case 707:
|
|
// PLay creature battle cry
|
|
PlayJA2StreamingSample( (UINT8)CREATURE_BATTLECRY_1, RATE_11025, SoundVolume( HIGHVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ) );
|
|
break;
|
|
|
|
case 708:
|
|
|
|
// PLay lock n' load sound for gun....
|
|
// Get LNL sound for current gun
|
|
{
|
|
UINT16 usItem;
|
|
UINT16 usSoundID;
|
|
|
|
usItem = pSoldier->inv[ HANDPOS ].usItem;
|
|
|
|
if ( usItem != NOTHING )
|
|
{
|
|
usSoundID = Weapon[ usItem ].sLocknLoadSound;
|
|
|
|
if ( usSoundID != 0 )
|
|
{
|
|
PlayJA2Sample( usSoundID, RATE_11025, SoundVolume( HIGHVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ) );
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 709:
|
|
|
|
// Knife throw sound...
|
|
PlayJA2Sample( Weapon[ THROWING_KNIFE ].sSound, RATE_11025, SoundVolume( HIGHVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ) );
|
|
break;
|
|
|
|
case 710:
|
|
|
|
// Monster footstep in
|
|
if ( SoldierOnScreen( pSoldier->ubID ) )
|
|
{
|
|
PlaySoldierJA2Sample( pSoldier->ubID, ACR_STEP_1, RATE_11025, SoundVolume( MIDVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ), TRUE );
|
|
}
|
|
break;
|
|
|
|
case 711:
|
|
|
|
// Monster footstep in
|
|
if ( SoldierOnScreen( pSoldier->ubID ) )
|
|
{
|
|
PlaySoldierJA2Sample( pSoldier->ubID, ACR_STEP_2, RATE_11025, SoundVolume( MIDVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ), TRUE );
|
|
}
|
|
break;
|
|
|
|
case 712:
|
|
|
|
// Monster footstep in
|
|
if ( SoldierOnScreen( pSoldier->ubID ) )
|
|
{
|
|
PlaySoldierJA2Sample( pSoldier->ubID, LCR_MOVEMENT, RATE_11025, SoundVolume( MIDVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ), TRUE );
|
|
}
|
|
break;
|
|
|
|
case 713:
|
|
|
|
// Monster footstep in
|
|
if ( pSoldier->ubBodyType == INFANT_MONSTER )
|
|
{
|
|
if ( SoldierOnScreen( pSoldier->ubID ) )
|
|
{
|
|
PlaySoldierJA2Sample( pSoldier->ubID, BCR_DRAGGING, RATE_11025, SoundVolume( MIDVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ), TRUE );
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 714:
|
|
|
|
// Lunges....
|
|
PlaySoldierJA2Sample( pSoldier->ubID, ACR_LUNGE, RATE_11025, SoundVolume( HIGHVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ), TRUE );
|
|
break;
|
|
|
|
case 715:
|
|
|
|
// Swipe
|
|
PlaySoldierJA2Sample( pSoldier->ubID, ACR_SWIPE, RATE_11025, SoundVolume( HIGHVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ), TRUE );
|
|
break;
|
|
|
|
case 716:
|
|
|
|
// Eat flesh
|
|
PlaySoldierJA2Sample( pSoldier->ubID, ACR_EATFLESH, RATE_11025, SoundVolume( HIGHVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ), TRUE );
|
|
break;
|
|
|
|
case 717:
|
|
|
|
// Battle cry
|
|
{
|
|
INT32 iSoundID=0;
|
|
BOOLEAN fDoCry = FALSE;
|
|
|
|
//if ( SoldierOnScreen( pSoldier->ubID ) )
|
|
{
|
|
switch( pSoldier->usActionData )
|
|
{
|
|
case CALL_1_PREY:
|
|
|
|
if ( pSoldier->ubBodyType == QUEENMONSTER )
|
|
{
|
|
iSoundID = LQ_SMELLS_THREAT;
|
|
}
|
|
else
|
|
{
|
|
iSoundID = ACR_SMEEL_PREY;
|
|
}
|
|
fDoCry = TRUE;
|
|
break;
|
|
|
|
case CALL_MULTIPLE_PREY:
|
|
|
|
if ( pSoldier->ubBodyType == QUEENMONSTER )
|
|
{
|
|
iSoundID = LQ_SMELLS_THREAT;
|
|
}
|
|
else
|
|
{
|
|
iSoundID = ACR_SMELL_THREAT;
|
|
}
|
|
fDoCry = TRUE;
|
|
break;
|
|
|
|
case CALL_ATTACKED:
|
|
|
|
if ( pSoldier->ubBodyType == QUEENMONSTER )
|
|
{
|
|
iSoundID = LQ_ENRAGED_ATTACK;
|
|
}
|
|
else
|
|
{
|
|
iSoundID = ACR_SMELL_THREAT;
|
|
}
|
|
fDoCry = TRUE;
|
|
break;
|
|
|
|
case CALL_CRIPPLED:
|
|
|
|
if ( pSoldier->ubBodyType == QUEENMONSTER )
|
|
{
|
|
iSoundID = LQ_CRIPPLED;
|
|
}
|
|
else
|
|
{
|
|
iSoundID = ACR_CRIPPLED;
|
|
}
|
|
fDoCry = TRUE;
|
|
break;
|
|
}
|
|
|
|
if ( fDoCry )
|
|
{
|
|
PlayJA2Sample( iSoundID, RATE_11025, SoundVolume( HIGHVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ) );
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 718:
|
|
|
|
|
|
PlaySoldierJA2Sample( pSoldier->ubID, LQ_RUPTURING, RATE_11025, SoundVolume( HIGHVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ), TRUE );
|
|
break;
|
|
|
|
case 719:
|
|
|
|
// Spit attack start sound...
|
|
PlaySoldierJA2Sample( pSoldier->ubID, LQ_ENRAGED_ATTACK, RATE_11025, SoundVolume( HIGHVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ), TRUE );
|
|
break;
|
|
|
|
case 720:
|
|
|
|
// Spit attack start sound...
|
|
PlaySoldierJA2Sample( pSoldier->ubID, LQ_WHIP_ATTACK, RATE_11025, SoundVolume( HIGHVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ), TRUE );
|
|
break;
|
|
|
|
case 721:
|
|
// Play fall from knees to ground...
|
|
PlaySoldierJA2Sample( pSoldier->ubID, (UINT8)( FALL_TO_GROUND_1 + Random(3) ), RATE_11025, SoundVolume( HIGHVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ), FALSE );
|
|
if ( pSoldier->usAnimState == FALLFORWARD_FROMHIT_STAND )
|
|
{
|
|
CheckEquipmentForFragileItemDamage( pSoldier, 20 );
|
|
}
|
|
break;
|
|
|
|
case 722:
|
|
// Play fall heavy
|
|
PlaySoldierJA2Sample( pSoldier->ubID, (UINT8)( HEAVY_FALL_1 ), RATE_11025, SoundVolume( HIGHVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ), FALSE );
|
|
if ( pSoldier->usAnimState == FALLFORWARD_FROMHIT_CROUCH )
|
|
{
|
|
CheckEquipmentForFragileItemDamage( pSoldier, 15 );
|
|
}
|
|
break;
|
|
|
|
case 723:
|
|
|
|
// Play armpit noise...
|
|
PlaySoldierJA2Sample( pSoldier->ubID, (UINT8)( IDLE_ARMPIT ), RATE_11025, SoundVolume( LOWVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ), TRUE );
|
|
break;
|
|
|
|
case 724:
|
|
|
|
// Play ass scratch
|
|
// PlaySoldierJA2Sample( pSoldier->ubID, (UINT8)( IDLE_SCRATCH ), RATE_11025, SoundVolume( HIGHVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ), TRUE );
|
|
break;
|
|
|
|
case 725:
|
|
|
|
// Play back crack
|
|
PlaySoldierJA2Sample( pSoldier->ubID, (UINT8)( IDLE_BACKCRACK ), RATE_11025, SoundVolume( LOWVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ), TRUE );
|
|
break;
|
|
|
|
case 726:
|
|
|
|
// Kickin door
|
|
PlaySoldierJA2Sample( pSoldier->ubID, (UINT8)( KICKIN_DOOR ), RATE_11025, SoundVolume( HIGHVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ), TRUE );
|
|
break;
|
|
|
|
case 727:
|
|
|
|
// Swoosh
|
|
PlaySoldierJA2Sample( pSoldier->ubID, (UINT8)( SWOOSH_1 + Random( 6 ) ), RATE_11025, SoundVolume( HIGHVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ), TRUE );
|
|
break;
|
|
|
|
case 728:
|
|
|
|
// Creature fall
|
|
PlaySoldierJA2Sample( pSoldier->ubID, (UINT8)( ACR_FALL_1 ), RATE_11025, SoundVolume( HIGHVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ), TRUE );
|
|
break;
|
|
|
|
case 729:
|
|
|
|
// grab roof....
|
|
PlaySoldierJA2Sample( pSoldier->ubID, (UINT8)( GRAB_ROOF ), RATE_11025, SoundVolume( HIGHVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ), TRUE );
|
|
break;
|
|
|
|
case 730:
|
|
|
|
// end climb roof....
|
|
PlaySoldierJA2Sample( pSoldier->ubID, (UINT8)( LAND_ON_ROOF ), RATE_11025, SoundVolume( HIGHVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ), TRUE );
|
|
break;
|
|
|
|
case 731:
|
|
|
|
// Stop climb roof..
|
|
PlaySoldierJA2Sample( pSoldier->ubID, (UINT8)( FALL_TO_GROUND_1 + Random(3) ), RATE_11025, SoundVolume( HIGHVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ), TRUE );
|
|
break;
|
|
|
|
case 732:
|
|
|
|
// Play die sound
|
|
DoMercBattleSound( pSoldier, BATTLE_SOUND_DIE1 );
|
|
pSoldier->fDeadSoundPlayed = TRUE;
|
|
break;
|
|
|
|
case 750:
|
|
|
|
// CODE: Move Vehicle UP
|
|
if ( pSoldier->uiStatusFlags & SOLDIER_VEHICLE )
|
|
{
|
|
// SetSoldierHeight( pSoldier, (FLOAT)( pSoldier->sHeightAdjustment + 1 ) );
|
|
}
|
|
break;
|
|
|
|
case 751:
|
|
|
|
// CODE: Move vehicle down
|
|
if ( pSoldier->uiStatusFlags & SOLDIER_VEHICLE )
|
|
{
|
|
// SetSoldierHeight( pSoldier, (FLOAT)( pSoldier->sHeightAdjustment - 1 ) );
|
|
}
|
|
break;
|
|
|
|
case 752:
|
|
|
|
// Code: decapitate
|
|
DecapitateCorpse( pSoldier, pSoldier->sTargetGridNo, pSoldier->bTargetLevel );
|
|
break;
|
|
|
|
case 753:
|
|
|
|
// code: freeup attcker
|
|
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("@@@@@@@ Reducing attacker busy count..., CODE FROM ANIMATION %s ( %d )", gAnimControl[ pSoldier->usAnimState ].zAnimStr, pSoldier->usAnimState ) );
|
|
DebugAttackBusy( String("@@@@@@@ Reducing attacker busy count..., CODE FROM ANIMATION %s ( %d )\n", gAnimControl[ pSoldier->usAnimState ].zAnimStr, pSoldier->usAnimState ) );
|
|
// ReduceAttackBusyCount( pSoldier->ubID, FALSE );
|
|
|
|
// ATE: Here, reduce again if creaturequeen tentical attack...
|
|
// Uh, why not add a second 753 code to the queen swipe instead of adding code to make things more complex?
|
|
if ( pSoldier->usAnimState == QUEEN_SWIPE )
|
|
{
|
|
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("@@@@@@@ Reducing attacker busy count for end of queen swipe\n" ) );
|
|
DebugAttackBusy( "@@@@@@@ Reducing attacker busy count for end of queen swipe" );
|
|
// ReduceAttackBusyCount( pSoldier->ubID, FALSE );
|
|
}
|
|
break;
|
|
|
|
case 754:
|
|
|
|
HandleFallIntoPitFromAnimation( pSoldier->ubID );
|
|
break;
|
|
|
|
case 755 :
|
|
|
|
DishoutQueenSwipeDamage( pSoldier );
|
|
break;
|
|
|
|
case 756:
|
|
|
|
// Reload robot....
|
|
{
|
|
UINT8 ubPerson;
|
|
SOLDIERTYPE *pRobot;
|
|
|
|
// Get pointer...
|
|
ubPerson = WhoIsThere2( pSoldier->sPendingActionData2, pSoldier->bLevel );
|
|
|
|
if ( ubPerson != NOBODY && MercPtrs[ ubPerson ]->uiStatusFlags & SOLDIER_ROBOT )
|
|
{
|
|
pRobot = MercPtrs[ ubPerson ];
|
|
|
|
ReloadGun( pRobot, &(pRobot->inv[ HANDPOS ] ), pSoldier->pTempObject );
|
|
|
|
// OK, check what was returned and place in inventory if it's non-zero
|
|
if ( pSoldier->pTempObject->usItem != NOTHING )
|
|
{
|
|
// Add to inv..
|
|
AutoPlaceObject( pSoldier, pSoldier->pTempObject, TRUE );
|
|
}
|
|
|
|
MemFree( pSoldier->pTempObject );
|
|
pSoldier->pTempObject = NULL;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 757:
|
|
|
|
// INcrement attacker busy count....
|
|
// gTacticalStatus.ubAttackBusyCount++;
|
|
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("!!!!! Incrementing attacker busy count..., CODE FROM ANIMATION %s ( %d ) : Count now %d", gAnimControl[ pSoldier->usAnimState ].zAnimStr, pSoldier->usAnimState, gTacticalStatus.ubAttackBusyCount ) );
|
|
DebugAttackBusy( String("!!!!! CODE FROM ANIMATION %s ( %d )\n", gAnimControl[ pSoldier->usAnimState ].zAnimStr, pSoldier->usAnimState ) );
|
|
break;
|
|
|
|
case 758:
|
|
|
|
// Trigger after slap...
|
|
TriggerNPCWithGivenApproach( QUEEN, APPROACH_DONE_SLAPPED , TRUE );
|
|
break;
|
|
|
|
case 759:
|
|
|
|
// Getting hit by slap
|
|
{
|
|
SOLDIERTYPE *pTarget;
|
|
|
|
pTarget = FindSoldierByProfileID( ELLIOT, FALSE );
|
|
|
|
if ( pTarget )
|
|
{
|
|
EVENT_InitNewSoldierAnim( pTarget, SLAP_HIT, 0 , FALSE );
|
|
|
|
// Play noise....
|
|
//PlaySoldierJA2Sample( pTarget->ubID, ( S_SLAP_IMPACT ), RATE_11025, SoundVolume( HIGHVOLUME, pTarget->sGridNo ), 1, SoundDir( pTarget->sGridNo ), TRUE );
|
|
|
|
//DoMercBattleSound( pTarget, (INT8)( BATTLE_SOUND_HIT1 + Random( 2 ) ) );
|
|
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 760:
|
|
|
|
// Get some blood.....
|
|
// Corpse Id is from pending action data
|
|
GetBloodFromCorpse( pSoldier );
|
|
// Dirty interface....
|
|
DirtyMercPanelInterface( pSoldier, DIRTYLEVEL2 );
|
|
break;
|
|
|
|
case 761:
|
|
|
|
{
|
|
// Dish out damage!
|
|
EVENT_SoldierGotHit( MercPtrs[ pSoldier->uiPendingActionData4 ], TAKE_DAMAGE_BLADE, (INT16) 25, (INT16) 25, gOppositeDirection[ pSoldier->bDirection ], 50, pSoldier->ubID, 0, ANIM_PRONE, 0, 0 );
|
|
}
|
|
break;
|
|
|
|
case 762:
|
|
{
|
|
// CODE: Set off Trigger
|
|
INT8 bPanicTrigger;
|
|
|
|
bPanicTrigger = ClosestPanicTrigger( pSoldier );
|
|
SetOffPanicBombs( pSoldier->ubID, bPanicTrigger );
|
|
// any AI guy has been specially given keys for this, now take them
|
|
// away
|
|
pSoldier->bHasKeys = pSoldier->bHasKeys >> 1;
|
|
|
|
}
|
|
break;
|
|
|
|
case 763:
|
|
|
|
// CODE: Drop item at gridno
|
|
if ( pSoldier->pTempObject != NULL )
|
|
{
|
|
if ( pSoldier->bVisible != -1 )
|
|
{
|
|
PlayJA2Sample( THROW_IMPACT_2, RATE_11025, SoundVolume( MIDVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ) );
|
|
}
|
|
|
|
AddItemToPool( pSoldier->sPendingActionData2, pSoldier->pTempObject, 1, pSoldier->bLevel, 0 , -1 );
|
|
NotifySoldiersToLookforItems( );
|
|
|
|
MemFree( pSoldier->pTempObject );
|
|
pSoldier->pTempObject = NULL;
|
|
}
|
|
break;
|
|
|
|
case 764:
|
|
|
|
PlaySoldierJA2Sample( pSoldier->ubID, PICKING_LOCK, RATE_11025, SoundVolume( HIGHVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ), TRUE );
|
|
break;
|
|
|
|
case 765:
|
|
|
|
// Flyback hit - do blood!
|
|
// PLace in existing tile and one back...
|
|
{
|
|
INT16 sNewGridNo;
|
|
|
|
InternalDropBlood( pSoldier->sGridNo, pSoldier->bLevel, 0, (UINT8)(MAXBLOODQUANTITY), 1 );
|
|
|
|
// Move forward one gridno....
|
|
sNewGridNo = NewGridNo( (UINT16)pSoldier->sGridNo, (UINT16)( DirectionInc( gOppositeDirection[ pSoldier->bDirection ] ) ) );
|
|
|
|
InternalDropBlood( sNewGridNo, pSoldier->bLevel, 0, (UINT8)(MAXBLOODQUANTITY), 1 );
|
|
|
|
}
|
|
break;
|
|
|
|
case 766:
|
|
|
|
// Say COOL quote
|
|
DoMercBattleSound( pSoldier, BATTLE_SOUND_COOL1 );
|
|
break;
|
|
|
|
case 767:
|
|
|
|
// Slap sound effect
|
|
PlaySoldierJA2Sample( pSoldier->ubID, SLAP_2, RATE_11025, SoundVolume( HIGHVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ), FALSE );
|
|
break;
|
|
|
|
case 768:
|
|
|
|
// OK, after ending first aid, stand up if not in combat....
|
|
if ( NumCapableEnemyInSector( ) == 0 )
|
|
{
|
|
// Stand up...
|
|
ChangeSoldierStance( pSoldier, ANIM_STAND );
|
|
return( FALSE );
|
|
}
|
|
break;
|
|
|
|
case 769:
|
|
|
|
// ATE: LOOK HERE FOR CODE IN INTERNALS FOR
|
|
// REFUELING A VEHICLE
|
|
// THE GAS_CAN IS IN THE MERCS MAIN HAND AT THIS TIME
|
|
{
|
|
UINT8 ubPerson;
|
|
SOLDIERTYPE *pVehicle;
|
|
|
|
// Get pointer to vehicle...
|
|
ubPerson = WhoIsThere2( pSoldier->sPendingActionData2, pSoldier->bLevel );
|
|
pVehicle = MercPtrs[ ubPerson ];
|
|
|
|
// this is a ubID for soldiertype....
|
|
AddFuelToVehicle( pSoldier, pVehicle );
|
|
|
|
fInterfacePanelDirty = DIRTYLEVEL2;
|
|
}
|
|
break;
|
|
|
|
case 770:
|
|
|
|
PlayJA2Sample( USE_WIRE_CUTTERS, RATE_11025, HIGHVOLUME, 1, MIDDLEPAN );
|
|
break;
|
|
|
|
case 771:
|
|
|
|
PlayJA2Sample( BLOODCAT_ATTACK, RATE_11025, HIGHVOLUME, 1, MIDDLEPAN );
|
|
break;
|
|
|
|
case 772:
|
|
|
|
//CODE: FOR A REALTIME NON-INTERRUPTABLE SCRIPT - SIGNAL DONE
|
|
pSoldier->fRTInNonintAnim = FALSE;
|
|
break;
|
|
|
|
case 773:
|
|
|
|
// Kneel up...
|
|
if ( !pSoldier->bStealthMode )
|
|
{
|
|
PlaySoldierJA2Sample( pSoldier->ubID, KNEEL_UP_SOUND, RATE_11025, SoundVolume( MIDVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ), TRUE );
|
|
}
|
|
break;
|
|
|
|
case 774:
|
|
|
|
// Kneel down..
|
|
if ( !pSoldier->bStealthMode )
|
|
{
|
|
PlaySoldierJA2Sample( pSoldier->ubID, KNEEL_DOWN_SOUND, RATE_11025, SoundVolume( MIDVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ), TRUE );
|
|
}
|
|
break;
|
|
|
|
case 775:
|
|
|
|
// prone up..
|
|
if ( !pSoldier->bStealthMode )
|
|
{
|
|
PlaySoldierJA2Sample( pSoldier->ubID, PRONE_UP_SOUND, RATE_11025, SoundVolume( MIDVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ), TRUE );
|
|
}
|
|
break;
|
|
|
|
case 776:
|
|
|
|
// prone down..
|
|
if ( !pSoldier->bStealthMode )
|
|
{
|
|
PlaySoldierJA2Sample( pSoldier->ubID, PRONE_DOWN_SOUND, RATE_11025, SoundVolume( MIDVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ), TRUE );
|
|
}
|
|
break;
|
|
|
|
case 777:
|
|
|
|
// picking something up
|
|
if ( !pSoldier->bStealthMode )
|
|
{
|
|
PlaySoldierJA2Sample( pSoldier->ubID, PICKING_SOMETHING_UP, RATE_11025, SoundVolume( HIGHVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ), TRUE );
|
|
}
|
|
break;
|
|
|
|
case 778:
|
|
if ( !pSoldier->bStealthMode )
|
|
{
|
|
PlaySoldierJA2Sample( pSoldier->ubID, ENTER_DEEP_WATER_1, RATE_11025, SoundVolume( HIGHVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ), TRUE );
|
|
}
|
|
break;
|
|
|
|
case 779:
|
|
|
|
PlaySoldierJA2Sample( pSoldier->ubID, COW_FALL, RATE_11025, SoundVolume( HIGHVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ), TRUE );
|
|
break;
|
|
|
|
case 780:
|
|
|
|
PlaySoldierJA2Sample( pSoldier->ubID, COW_HIT_SND, RATE_11025, SoundVolume( HIGHVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ), TRUE );
|
|
break;
|
|
|
|
case 781:
|
|
|
|
PlaySoldierJA2Sample( pSoldier->ubID, ACR_DIE_PART2, RATE_11025, SoundVolume( HIGHVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ), FALSE );
|
|
break;
|
|
|
|
case 782:
|
|
|
|
PlaySoldierJA2Sample( pSoldier->ubID, CREATURE_DISSOLVE_1, RATE_11025, SoundVolume( HIGHVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ), FALSE );
|
|
break;
|
|
|
|
case 784:
|
|
|
|
PlaySoldierJA2Sample( pSoldier->ubID, CREATURE_FALL, RATE_11025, SoundVolume( HIGHVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ), FALSE );
|
|
break;
|
|
|
|
case 785:
|
|
|
|
if ( Random( 5 ) == 0 )
|
|
{
|
|
PlaySoldierJA2Sample( pSoldier->ubID, CROW_PECKING_AT_FLESH, RATE_11025, SoundVolume( MIDVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ), TRUE );
|
|
}
|
|
break;
|
|
|
|
case 786:
|
|
|
|
PlaySoldierJA2Sample( pSoldier->ubID, CROW_FLYING_AWAY, RATE_11025, SoundVolume( MIDVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ), TRUE );
|
|
break;
|
|
|
|
case 787:
|
|
|
|
PlaySoldierJA2Sample( pSoldier->ubID, SLAP_1, RATE_11025, SoundVolume( HIGHVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ), FALSE );
|
|
break;
|
|
|
|
case 788:
|
|
|
|
PlaySoldierJA2Sample( pSoldier->ubID, MORTAR_START, RATE_11025, SoundVolume( HIGHVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ), TRUE );
|
|
break;
|
|
|
|
case 789:
|
|
|
|
PlaySoldierJA2Sample( pSoldier->ubID, MORTAR_LOAD, RATE_11025, SoundVolume( HIGHVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ), TRUE );
|
|
break;
|
|
|
|
case 790:
|
|
|
|
PlaySoldierJA2Sample( pSoldier->ubID, COW_FALL_2, RATE_11025, SoundVolume( HIGHVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ), TRUE );
|
|
break;
|
|
|
|
case 791:
|
|
|
|
PlaySoldierJA2Sample( pSoldier->ubID, FENCE_OPEN, RATE_11025, SoundVolume( HIGHVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ), TRUE );
|
|
break;
|
|
|
|
}
|
|
// Adjust frame control pos, and try again
|
|
pSoldier->usAniCode++;
|
|
}
|
|
else if ( sNewAniFrame == 999 )
|
|
{
|
|
|
|
// Go to start, by default
|
|
pSoldier->usAniCode = 0;
|
|
|
|
}
|
|
|
|
// Loop here until we break on a real item!
|
|
} while ( TRUE );
|
|
|
|
// We're done
|
|
return( TRUE );
|
|
}
|
|
|
|
#define MIN_DEADLINESS_FOR_LIKE_GUN_QUOTE 20
|
|
|
|
BOOLEAN ShouldMercSayHappyWithGunQuote( SOLDIERTYPE *pSoldier )
|
|
{
|
|
// How do we do this....
|
|
|
|
if ( QuoteExp_GotGunOrUsedGun[ pSoldier->ubProfile ] == QUOTE_SATISFACTION_WITH_GUN_AFTER_KILL )
|
|
{
|
|
// For one, only once a day...
|
|
if ( pSoldier->usQuoteSaidFlags & SOLDIER_QUOTE_SAID_LIKESGUN )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
// is it a gun?
|
|
if ( Item[ pSoldier->usAttackingWeapon ].usItemClass & IC_GUN )
|
|
{
|
|
// Is our weapon powerfull enough?
|
|
if ( Weapon[ pSoldier->usAttackingWeapon ].ubDeadliness > MIN_DEADLINESS_FOR_LIKE_GUN_QUOTE )
|
|
{
|
|
// 20 % chance?
|
|
if ( Random( 100 ) < 20 )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return( FALSE );
|
|
}
|
|
|
|
|
|
void SayBuddyWitnessedQuoteFromKill( SOLDIERTYPE *pKillerSoldier, INT16 sGridNo, INT8 bLevel )
|
|
{
|
|
UINT8 ubMercsInSector[ 20 ] = { 0 };
|
|
INT8 bBuddyIndex[ 20 ] = { -1 };
|
|
INT8 bTempBuddyIndex;
|
|
UINT8 ubNumMercs = 0;
|
|
UINT8 ubChosenMerc;
|
|
SOLDIERTYPE *pTeamSoldier;
|
|
INT32 cnt;
|
|
INT16 sDistVisible = FALSE;
|
|
UINT16 usQuoteNum;
|
|
|
|
// Loop through all our guys and randomly say one from someone in our sector
|
|
|
|
// set up soldier ptr as first element in mercptrs list
|
|
cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
|
|
|
|
// run through list
|
|
for ( pTeamSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++,pTeamSoldier++ )
|
|
{
|
|
// Add guy if he's a candidate...
|
|
if ( OK_INSECTOR_MERC( pTeamSoldier ) && !AM_AN_EPC( pTeamSoldier ) && !( pTeamSoldier->uiStatusFlags & SOLDIER_GASSED ) && !(AM_A_ROBOT( pTeamSoldier )) && !pTeamSoldier->fMercAsleep && pTeamSoldier->sGridNo != NOWHERE )
|
|
{
|
|
// Are we a buddy of killer?
|
|
bTempBuddyIndex = WhichBuddy( pTeamSoldier->ubProfile, pKillerSoldier->ubProfile );
|
|
|
|
if ( bTempBuddyIndex != -1 )
|
|
{
|
|
switch( bTempBuddyIndex )
|
|
{
|
|
case 0:
|
|
if ( pTeamSoldier->usQuoteSaidExtFlags & SOLDIER_QUOTE_SAID_BUDDY_1_WITNESSED )
|
|
{
|
|
continue;
|
|
}
|
|
break;
|
|
|
|
case 1:
|
|
if ( pTeamSoldier->usQuoteSaidExtFlags & SOLDIER_QUOTE_SAID_BUDDY_2_WITNESSED )
|
|
{
|
|
continue;
|
|
}
|
|
break;
|
|
|
|
case 2:
|
|
if ( pTeamSoldier->usQuoteSaidExtFlags & SOLDIER_QUOTE_SAID_BUDDY_3_WITNESSED )
|
|
{
|
|
continue;
|
|
}
|
|
break;
|
|
}
|
|
|
|
// TO LOS check to killed
|
|
// Can we see location of killer?
|
|
sDistVisible = DistanceVisible( pTeamSoldier, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, pKillerSoldier->sGridNo, pKillerSoldier->bLevel, pKillerSoldier );
|
|
if ( SoldierTo3DLocationLineOfSightTest( pTeamSoldier, pKillerSoldier->sGridNo, pKillerSoldier->bLevel, (UINT8)3, (UINT8) sDistVisible, TRUE ) == 0 )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
|
|
// Can we see location of killed?
|
|
sDistVisible = DistanceVisible( pTeamSoldier, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, sGridNo, bLevel, pTeamSoldier );
|
|
if ( SoldierTo3DLocationLineOfSightTest( pTeamSoldier, sGridNo, bLevel, (UINT8)3, (UINT8) sDistVisible, TRUE ) == 0 )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// OK, a good candidate...
|
|
ubMercsInSector[ ubNumMercs ] = (UINT8)cnt;
|
|
bBuddyIndex[ ubNumMercs ] = bTempBuddyIndex;
|
|
ubNumMercs++;
|
|
}
|
|
}
|
|
}
|
|
|
|
// If we are > 0
|
|
if ( ubNumMercs > 0 )
|
|
{
|
|
// Do random check here...
|
|
if ( Random( 100 ) < 20 )
|
|
{
|
|
ubChosenMerc = (UINT8)Random( ubNumMercs );
|
|
|
|
switch( bBuddyIndex[ ubChosenMerc ] )
|
|
{
|
|
case 0:
|
|
usQuoteNum = QUOTE_BUDDY_1_GOOD;
|
|
MercPtrs[ ubMercsInSector[ ubChosenMerc ] ]->usQuoteSaidExtFlags |= SOLDIER_QUOTE_SAID_BUDDY_1_WITNESSED;
|
|
break;
|
|
|
|
case 1:
|
|
usQuoteNum = QUOTE_BUDDY_2_GOOD;
|
|
MercPtrs[ ubMercsInSector[ ubChosenMerc ] ]->usQuoteSaidExtFlags |= SOLDIER_QUOTE_SAID_BUDDY_2_WITNESSED;
|
|
break;
|
|
|
|
case 2:
|
|
usQuoteNum = QUOTE_LEARNED_TO_LIKE_WITNESSED;
|
|
MercPtrs[ ubMercsInSector[ ubChosenMerc ] ]->usQuoteSaidExtFlags |= SOLDIER_QUOTE_SAID_BUDDY_3_WITNESSED;
|
|
break;
|
|
}
|
|
TacticalCharacterDialogue( MercPtrs[ ubMercsInSector[ ubChosenMerc ] ], usQuoteNum );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void HandleKilledQuote( SOLDIERTYPE *pKilledSoldier, SOLDIERTYPE *pKillerSoldier, INT16 sGridNo, INT8 bLevel )
|
|
{
|
|
SOLDIERTYPE *pTeamSoldier;
|
|
INT32 cnt;
|
|
UINT8 ubMercsInSector[ 20 ] = { 0 };
|
|
UINT8 ubNumMercs = 0;
|
|
UINT8 ubChosenMerc;
|
|
BOOLEAN fDoSomeoneElse = FALSE;
|
|
BOOLEAN fCanWeSeeLocation = FALSE;
|
|
INT16 sDistVisible = FALSE;
|
|
|
|
gfLastMercTalkedAboutKillingID = pKilledSoldier->ubID;
|
|
|
|
// Can we see location?
|
|
sDistVisible = DistanceVisible( pKillerSoldier, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, sGridNo, bLevel, pKillerSoldier );
|
|
|
|
fCanWeSeeLocation = ( SoldierTo3DLocationLineOfSightTest( pKillerSoldier, sGridNo, bLevel, (UINT8)3, (UINT8) sDistVisible, TRUE ) != 0 );
|
|
|
|
|
|
// Are we killing mike?
|
|
if ( pKilledSoldier->ubProfile == 149 && pKillerSoldier->ubWhatKindOfMercAmI == MERC_TYPE__AIM_MERC )
|
|
{
|
|
// Can we see?
|
|
if ( fCanWeSeeLocation )
|
|
{
|
|
TacticalCharacterDialogue( pKillerSoldier, QUOTE_AIM_KILLED_MIKE );
|
|
}
|
|
}
|
|
// Are we killing factory mamager?
|
|
else if ( pKilledSoldier->ubProfile == 139 )
|
|
{
|
|
// Can we see?
|
|
//f ( fCanWeSeeLocation )
|
|
{
|
|
TacticalCharacterDialogue( pKillerSoldier, QUOTE_KILLED_FACTORY_MANAGER );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Steps here...
|
|
|
|
// If not head shot, just say killed quote
|
|
|
|
// If head shot...
|
|
|
|
// If we have a head shot saying,, randomly try that one
|
|
|
|
// If not doing that one, search for anybody who can see person
|
|
|
|
// If somebody did, play his quote plus attackers killed quote.
|
|
|
|
// Checkf for headhot!
|
|
if ( pKilledSoldier->usAnimState == JFK_HITDEATH )
|
|
{
|
|
//Randomliy say it!
|
|
if ( Random( 100 ) < 40 )
|
|
{
|
|
TacticalCharacterDialogue( pKillerSoldier, QUOTE_HEADSHOT );
|
|
}
|
|
else
|
|
{
|
|
fDoSomeoneElse = TRUE;
|
|
}
|
|
|
|
if ( fDoSomeoneElse )
|
|
{
|
|
// Check if a person is here that has this quote....
|
|
cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
|
|
|
|
// run through list
|
|
for ( pTeamSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++,pTeamSoldier++ )
|
|
{
|
|
if ( cnt != pKillerSoldier->ubID )
|
|
{
|
|
if ( OK_INSECTOR_MERC( pTeamSoldier ) && !( pTeamSoldier->uiStatusFlags & SOLDIER_GASSED ) && !AM_AN_EPC( pTeamSoldier ) )
|
|
{
|
|
// Can we see location?
|
|
sDistVisible = DistanceVisible( pTeamSoldier, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, sGridNo, bLevel, pTeamSoldier );
|
|
|
|
if ( SoldierTo3DLocationLineOfSightTest( pTeamSoldier, sGridNo, bLevel, 3, (UINT8) sDistVisible, TRUE ) )
|
|
{
|
|
ubMercsInSector[ ubNumMercs ] = (UINT8)cnt;
|
|
ubNumMercs++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Did we find anybody?
|
|
if ( ubNumMercs > 0 )
|
|
{
|
|
ubChosenMerc = (UINT8)Random( ubNumMercs );
|
|
|
|
// We have a random chance of not saying our we killed a guy quote
|
|
if ( Random( 100 ) < 50 )
|
|
{
|
|
// Say this guys quote but the killer's quote as well....
|
|
// if killed was not a plain old civ, say quote
|
|
if (pKilledSoldier->bTeam != CIV_TEAM || pKilledSoldier->ubCivilianGroup != 0)
|
|
{
|
|
TacticalCharacterDialogue( pKillerSoldier, QUOTE_KILLED_AN_ENEMY );
|
|
}
|
|
}
|
|
|
|
TacticalCharacterDialogue( MercPtrs[ ubMercsInSector[ ubChosenMerc ] ], QUOTE_HEADSHOT );
|
|
}
|
|
else
|
|
{
|
|
// Can we see?
|
|
if ( fCanWeSeeLocation )
|
|
{
|
|
// Say this guys quote but the killer's quote as well....
|
|
// if killed was not a plain old civ, say quote
|
|
if (pKilledSoldier->bTeam != CIV_TEAM || pKilledSoldier->ubCivilianGroup != 0)
|
|
{
|
|
TacticalCharacterDialogue( pKillerSoldier, QUOTE_KILLED_AN_ENEMY );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Can we see?
|
|
if ( fCanWeSeeLocation )
|
|
{
|
|
// if killed was not a plain old civ, say quote
|
|
if (pKilledSoldier->bTeam != CIV_TEAM || pKilledSoldier->ubCivilianGroup != 0)
|
|
{
|
|
// Are we happy with our gun?
|
|
if ( ShouldMercSayHappyWithGunQuote( pKillerSoldier ) )
|
|
{
|
|
TacticalCharacterDialogue( pKillerSoldier, QUOTE_SATISFACTION_WITH_GUN_AFTER_KILL );
|
|
pKillerSoldier->usQuoteSaidFlags |= SOLDIER_QUOTE_SAID_LIKESGUN;
|
|
}
|
|
else
|
|
// Randomize between laugh, quote...
|
|
{
|
|
if ( Random( 100 ) < 33 && pKilledSoldier->ubBodyType != BLOODCAT )
|
|
{
|
|
// If it's a creature......
|
|
if ( pKilledSoldier->uiStatusFlags & SOLDIER_MONSTER )
|
|
{
|
|
TacticalCharacterDialogue( pKillerSoldier, QUOTE_KILLED_A_CREATURE );
|
|
}
|
|
else
|
|
{
|
|
TacticalCharacterDialogue( pKillerSoldier, QUOTE_KILLED_AN_ENEMY );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( Random( 50 ) == 25 )
|
|
{
|
|
DoMercBattleSound( pKillerSoldier, (INT8)( BATTLE_SOUND_LAUGH1 ) );
|
|
}
|
|
else
|
|
{
|
|
DoMercBattleSound( pKillerSoldier, (INT8)( BATTLE_SOUND_COOL1 ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
// Buddy witnessed?
|
|
SayBuddyWitnessedQuoteFromKill( pKillerSoldier, sGridNo, bLevel );
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN HandleSoldierDeath( SOLDIERTYPE *pSoldier , BOOLEAN *pfMadeCorpse )
|
|
{
|
|
BOOLEAN fBuddyJustDead = FALSE;
|
|
|
|
*pfMadeCorpse = FALSE;
|
|
|
|
if ( pSoldier->bLife == 0 && !( pSoldier->uiStatusFlags & SOLDIER_DEAD ) )
|
|
{
|
|
// Cancel services here...
|
|
ReceivingSoldierCancelServices( pSoldier );
|
|
GivingSoldierCancelServices( pSoldier );
|
|
|
|
if ( pSoldier->iMuzFlash != -1 )
|
|
{
|
|
LightSpriteDestroy( pSoldier->iMuzFlash );
|
|
pSoldier->iMuzFlash = -1;
|
|
}
|
|
if ( pSoldier->iLight != -1 )
|
|
{
|
|
LightSpriteDestroy( pSoldier->iLight );
|
|
}
|
|
|
|
//FREEUP GETTING HIT FLAG
|
|
pSoldier->fGettingHit = FALSE;
|
|
|
|
// Find next closest team member!
|
|
if ( pSoldier->bTeam == gbPlayerNum )
|
|
{
|
|
// Set guy to close panel!
|
|
// ONLY IF VISIBLE ON SCREEN
|
|
if ( IsMercPortraitVisible( pSoldier->ubID ) )
|
|
{
|
|
fInterfacePanelDirty = DIRTYLEVEL2;
|
|
}
|
|
pSoldier->fUIdeadMerc = TRUE;
|
|
|
|
if ( !gfKillingGuysForLosingBattle )
|
|
{
|
|
// ATE: THIS IS S DUPLICATE SETTING OF SOLDIER_DEAD. Is set in StrategicHandlePlayerTeamMercDeath()
|
|
// also, but here it's needed to tell tectical to ignore this dude...
|
|
// until StrategicHandlePlayerTeamMercDeath() can get called after death skull interface is done
|
|
pSoldier->uiStatusFlags |= SOLDIER_DEAD;
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
UINT8 ubAssister;
|
|
|
|
// IF this guy has an attacker and he's a good guy, play sound
|
|
if ( pSoldier->ubAttackerID != NOBODY )
|
|
{
|
|
if ( MercPtrs[ pSoldier->ubAttackerID ]->bTeam == gbPlayerNum && gTacticalStatus.ubAttackBusyCount > 0 )
|
|
{
|
|
gTacticalStatus.fKilledEnemyOnAttack = TRUE;
|
|
gTacticalStatus.ubEnemyKilledOnAttack = pSoldier->ubID;
|
|
gTacticalStatus.ubEnemyKilledOnAttackLocation = pSoldier->sGridNo;
|
|
gTacticalStatus.bEnemyKilledOnAttackLevel = pSoldier->bLevel;
|
|
gTacticalStatus.ubEnemyKilledOnAttackKiller = pSoldier->ubAttackerID;
|
|
|
|
// also check if we are in mapscreen, if so update soldier's list
|
|
if( guiCurrentScreen == MAP_SCREEN )
|
|
{
|
|
ReBuildCharactersList( );
|
|
}
|
|
}
|
|
else if ( pSoldier->bVisible == TRUE )
|
|
{
|
|
// We were a visible enemy, say laugh!
|
|
if ( Random(3) == 0 && !CREATURE_OR_BLOODCAT( MercPtrs[ pSoldier->ubAttackerID ] ) )
|
|
{
|
|
DoMercBattleSound( MercPtrs[ pSoldier->ubAttackerID ], BATTLE_SOUND_LAUGH1 );
|
|
}
|
|
}
|
|
}
|
|
|
|
// Handle NPC Dead
|
|
HandleNPCTeamMemberDeath( pSoldier );
|
|
|
|
// if a friendly with a profile, increment kills
|
|
// militia also now track kills...
|
|
if ( pSoldier->ubAttackerID != NOBODY )
|
|
{
|
|
if ( MercPtrs[ pSoldier->ubAttackerID ]->bTeam == gbPlayerNum )
|
|
{
|
|
// increment kills
|
|
gMercProfiles[ MercPtrs[ pSoldier->ubAttackerID ]->ubProfile ].usKills++;
|
|
gStrategicStatus.usPlayerKills++;
|
|
}
|
|
else if ( MercPtrs[ pSoldier->ubAttackerID ]->bTeam == MILITIA_TEAM )
|
|
{
|
|
// get a kill! 2 points!
|
|
MercPtrs[ pSoldier->ubAttackerID ]->ubMilitiaKills += 2;
|
|
}
|
|
|
|
}
|
|
|
|
// JA2 Gold: if previous and current attackers are the same, the next-to-previous attacker gets the assist
|
|
if (pSoldier->ubPreviousAttackerID == pSoldier->ubAttackerID)
|
|
{
|
|
ubAssister = pSoldier->ubNextToPreviousAttackerID;
|
|
}
|
|
else
|
|
{
|
|
ubAssister = pSoldier->ubPreviousAttackerID;
|
|
}
|
|
|
|
if ( ubAssister != NOBODY && ubAssister != pSoldier->ubAttackerID )
|
|
{
|
|
if ( MercPtrs[ ubAssister ]->bTeam == gbPlayerNum )
|
|
{
|
|
gMercProfiles[ MercPtrs[ ubAssister ]->ubProfile ].usAssists++;
|
|
}
|
|
else if ( MercPtrs[ ubAssister ]->bTeam == MILITIA_TEAM )
|
|
{
|
|
// get an assist - 1 points
|
|
MercPtrs[ ubAssister ]->ubMilitiaKills += 1;
|
|
}
|
|
}
|
|
/*
|
|
// handle assist
|
|
// if killer is assister, don't increment
|
|
if ( pSoldier->ubPreviousAttackerID != NOBODY && pSoldier->ubPreviousAttackerID != pSoldier->ubAttackerID )
|
|
{
|
|
if ( MercPtrs[ pSoldier->ubPreviousAttackerID ]->bTeam == gbPlayerNum )
|
|
{
|
|
gMercProfiles[ MercPtrs[ pSoldier->ubPreviousAttackerID ]->ubProfile ].usAssists++;
|
|
}
|
|
else if ( MercPtrs[ pSoldier->ubPreviousAttackerID ]->bTeam == MILITIA_TEAM )
|
|
{
|
|
// get an assist - 1 points
|
|
MercPtrs[ pSoldier->ubPreviousAttackerID ]->ubMilitiaKills += 1;
|
|
}
|
|
}
|
|
*/
|
|
}
|
|
|
|
if ( TurnSoldierIntoCorpse( pSoldier, TRUE, TRUE ) )
|
|
{
|
|
*pfMadeCorpse = TRUE;
|
|
}
|
|
|
|
// Remove mad as target, one he has died!
|
|
RemoveManAsTarget( pSoldier );
|
|
|
|
// Re-evaluate visiblitiy for the team!
|
|
BetweenTurnsVisibilityAdjustments();
|
|
|
|
// 0verhaul: This is now handled in the death state transitions
|
|
// if ( pSoldier->bTeam != gbPlayerNum )
|
|
// {
|
|
// if ( !pSoldier->fDoingExternalDeath )
|
|
// {
|
|
// // Release attacker
|
|
// DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("@@@@@@@ Releasesoldierattacker, code 497 = handle soldier death") );
|
|
// ReleaseSoldiersAttacker( pSoldier );
|
|
// }
|
|
// }
|
|
|
|
if ( !( *pfMadeCorpse ) )
|
|
{
|
|
fBuddyJustDead = TRUE;
|
|
}
|
|
|
|
}
|
|
|
|
if ( pSoldier->bLife > 0 )
|
|
{
|
|
// If we are here - something funny has heppende
|
|
// We either have played a death animation when we are not dead, or we are calling
|
|
// this ani code in an animation which is not a death animation
|
|
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, "Soldier Ani: Death animation called when not dead..." );
|
|
}
|
|
|
|
return( fBuddyJustDead );
|
|
}
|
|
|
|
|
|
void HandlePlayerTeamMemberDeathAfterSkullAnimation( SOLDIERTYPE *pSoldier )
|
|
{
|
|
// 0verhaul: This is now handled in the death state transition.
|
|
// Release attacker
|
|
// if ( !pSoldier->fDoingExternalDeath )
|
|
// {
|
|
// DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("@@@@@@@ Releasesoldierattacker, code 497 = handle soldier death") );
|
|
// ReleaseSoldiersAttacker( pSoldier );
|
|
// }
|
|
|
|
HandlePlayerTeamMemberDeath( pSoldier );
|
|
|
|
// now remove character from a squad
|
|
RemoveCharacterFromSquads( pSoldier );
|
|
}
|
|
|
|
BOOLEAN CheckForAndHandleSoldierDeath( SOLDIERTYPE *pSoldier, BOOLEAN *pfMadeCorpse )
|
|
{
|
|
|
|
if ( HandleSoldierDeath( pSoldier, pfMadeCorpse ) )
|
|
{
|
|
// Select approriate death
|
|
switch( pSoldier->usAnimState )
|
|
{
|
|
case FLYBACK_HIT_DEATH:
|
|
ChangeSoldierState( pSoldier, FLYBACK_HITDEATH_STOP, 0, FALSE );
|
|
break;
|
|
|
|
case GENERIC_HIT_DEATH:
|
|
ChangeSoldierState( pSoldier, FALLFORWARD_HITDEATH_STOP, 0, FALSE );
|
|
break;
|
|
|
|
case FALLBACK_HIT_DEATH:
|
|
ChangeSoldierState( pSoldier, FALLBACK_HITDEATH_STOP, 0, FALSE );
|
|
break;
|
|
|
|
case PRONE_HIT_DEATH:
|
|
ChangeSoldierState( pSoldier, PRONE_HITDEATH_STOP, 0, FALSE );
|
|
break;
|
|
|
|
case JFK_HITDEATH:
|
|
ChangeSoldierState( pSoldier, JFK_HITDEATH_STOP, 0, FALSE );
|
|
break;
|
|
|
|
case FALLOFF_DEATH:
|
|
ChangeSoldierState( pSoldier, FALLOFF_DEATH_STOP, 0, FALSE );
|
|
break;
|
|
|
|
case FALLOFF_FORWARD_DEATH:
|
|
ChangeSoldierState( pSoldier, FALLOFF_FORWARD_DEATH_STOP, 0, FALSE );
|
|
break;
|
|
|
|
case WATER_DIE:
|
|
ChangeSoldierState( pSoldier, WATER_DIE_STOP, 0, FALSE );
|
|
break;
|
|
|
|
case DEEP_WATER_DIE:
|
|
ChangeSoldierState( pSoldier, DEEP_WATER_DIE_STOPPING, 0, FALSE );
|
|
break;
|
|
|
|
case COW_DYING:
|
|
ChangeSoldierState( pSoldier, COW_DYING_STOP, 0, FALSE);
|
|
break;
|
|
|
|
case BLOODCAT_DYING:
|
|
ChangeSoldierState( pSoldier, BLOODCAT_DYING_STOP, 0, FALSE);
|
|
break;
|
|
|
|
default:
|
|
|
|
// IF we are here - something is wrong - we should have an animation stop here
|
|
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, "Soldier Ani: CODE 440 Error, Death STOP not handled" );
|
|
}
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
return( FALSE );
|
|
}
|
|
|
|
|
|
//#define TESTFALLBACK
|
|
//#define TESTFALLFORWARD
|
|
|
|
void CheckForAndHandleSoldierIncompacitated( SOLDIERTYPE *pSoldier )
|
|
{
|
|
INT16 sNewGridNo;
|
|
|
|
if ( pSoldier->bLife < OKLIFE )
|
|
{
|
|
// Cancel services here...
|
|
ReceivingSoldierCancelServices( pSoldier );
|
|
GivingSoldierCancelServices( pSoldier );
|
|
|
|
|
|
// If we are a monster, set life to zero ( no unconscious )
|
|
switch( pSoldier->ubBodyType )
|
|
{
|
|
case ADULTFEMALEMONSTER:
|
|
case AM_MONSTER:
|
|
case YAF_MONSTER:
|
|
case YAM_MONSTER:
|
|
case LARVAE_MONSTER:
|
|
case INFANT_MONSTER:
|
|
case CRIPPLECIV:
|
|
case ROBOTNOWEAPON:
|
|
case QUEENMONSTER:
|
|
case TANK_NW:
|
|
case TANK_NE:
|
|
|
|
pSoldier->bLife = 0;
|
|
break;
|
|
}
|
|
|
|
// OK, if we are in a meanwhile and this is elliot...
|
|
if ( AreInMeanwhile( ) )
|
|
{
|
|
SOLDIERTYPE *pQueen;
|
|
|
|
pQueen = FindSoldierByProfileID( QUEEN, FALSE );
|
|
|
|
if ( pQueen )
|
|
{
|
|
TriggerNPCWithGivenApproach( QUEEN, APPROACH_DONE_SLAPPED, FALSE );
|
|
}
|
|
}
|
|
|
|
// We are unconscious now, play randomly, this animation continued, or a new death
|
|
if ( CheckSoldierHitRoof( pSoldier ) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// If guy is now dead, play sound!
|
|
if ( pSoldier->bLife == 0 )
|
|
{
|
|
if ( !AreInMeanwhile() )
|
|
{
|
|
DoMercBattleSound( pSoldier, BATTLE_SOUND_DIE1 );
|
|
pSoldier->fDeadSoundPlayed = TRUE;
|
|
}
|
|
}
|
|
|
|
// Randomly fall back or forward, if we are in the standing hit animation
|
|
if ( pSoldier->usAnimState == GENERIC_HIT_STAND || pSoldier->usAnimState == STANDING_BURST_HIT || pSoldier->usAnimState == RIFLE_STAND_HIT )
|
|
{
|
|
INT8 bTestDirection = pSoldier->bDirection;
|
|
BOOLEAN fForceDirection = FALSE;
|
|
BOOLEAN fDoFallback = FALSE;
|
|
|
|
|
|
// Lesh: lets fix dead humans fallback through obstacles
|
|
|
|
// TRY FALLING BACKWARDS, ( ONLY IF WE ARE A MERC! )
|
|
#ifdef TESTFALLBACK
|
|
if ( IS_MERC_BODY_TYPE( pSoldier ) )
|
|
#elif defined ( TESTFALLFORWARD )
|
|
if ( 0 )
|
|
#else
|
|
if ( Random(100 ) > 40 && IS_MERC_BODY_TYPE( pSoldier ) && !IsProfileATerrorist( pSoldier->ubProfile ) )
|
|
#endif
|
|
{
|
|
// CHECK IF WE HAVE AN ATTACKER, TAKE OPPOSITE DIRECTION!
|
|
if ( pSoldier->ubAttackerID != NOBODY )
|
|
{
|
|
// Find direction!
|
|
bTestDirection = (INT8)GetDirectionFromGridNo( MercPtrs[ pSoldier->ubAttackerID ]->sGridNo, pSoldier );
|
|
fForceDirection = TRUE;
|
|
}
|
|
|
|
sNewGridNo = NewGridNo( (UINT16)pSoldier->sGridNo, DirectionInc( gOppositeDirection[ bTestDirection ] ) );
|
|
|
|
if ( OKFallDirection( pSoldier, sNewGridNo, pSoldier->bLevel, bTestDirection, FLYBACK_HIT ) )
|
|
{
|
|
// CHECKED BEHIND GRIDS - OK
|
|
fDoFallback = TRUE;
|
|
}
|
|
else
|
|
{
|
|
fDoFallback = FALSE;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
fDoFallback = FALSE;
|
|
}
|
|
|
|
if ( !fDoFallback )
|
|
{
|
|
// 1 ) REC DIRECTION
|
|
// 2 ) SET FLAG FOR STARTING TO FALL
|
|
BeginTyingToFall( pSoldier );
|
|
ChangeSoldierState( pSoldier, FALLFORWARD_FROMHIT_STAND, 0, FALSE );
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
// ALL'S OK HERE..... IF WE FORCED DIRECTION, SET!
|
|
if ( fForceDirection )
|
|
{
|
|
EVENT_SetSoldierDesiredDirection( pSoldier, bTestDirection );
|
|
EVENT_SetSoldierDirection( pSoldier, bTestDirection );
|
|
}
|
|
ChangeToFallbackAnimation( pSoldier, pSoldier->bDirection );
|
|
return;
|
|
}
|
|
}
|
|
else if ( pSoldier->usAnimState == GENERIC_HIT_CROUCH )
|
|
{
|
|
ChangeSoldierState( pSoldier, FALLFORWARD_FROMHIT_CROUCH, 0 , FALSE);
|
|
BeginTyingToFall( pSoldier );
|
|
return;
|
|
}
|
|
else if ( pSoldier->usAnimState == GENERIC_HIT_PRONE )
|
|
{
|
|
ChangeSoldierState( pSoldier, PRONE_LAY_FROMHIT, 0 , FALSE );
|
|
return;
|
|
}
|
|
else if ( pSoldier->usAnimState == ADULTMONSTER_HIT )
|
|
{
|
|
ChangeSoldierState( pSoldier, ADULTMONSTER_DYING, 0 , FALSE );
|
|
return;
|
|
}
|
|
else if ( pSoldier->usAnimState == LARVAE_HIT )
|
|
{
|
|
ChangeSoldierState( pSoldier, LARVAE_DIE, 0 , FALSE );
|
|
return;
|
|
}
|
|
else if ( pSoldier->usAnimState == QUEEN_HIT )
|
|
{
|
|
ChangeSoldierState( pSoldier, QUEEN_DIE, 0 , FALSE );
|
|
return;
|
|
}
|
|
else if ( pSoldier->usAnimState == CRIPPLE_HIT )
|
|
{
|
|
ChangeSoldierState( pSoldier, CRIPPLE_DIE, 0 , FALSE );
|
|
return;
|
|
}
|
|
else if ( pSoldier->usAnimState == ROBOTNW_HIT )
|
|
{
|
|
ChangeSoldierState( pSoldier, ROBOTNW_DIE, 0 , FALSE );
|
|
return;
|
|
}
|
|
else if ( pSoldier->usAnimState == INFANT_HIT )
|
|
{
|
|
ChangeSoldierState( pSoldier, INFANT_DIE, 0 , FALSE );
|
|
return;
|
|
}
|
|
else if ( pSoldier->usAnimState == COW_HIT )
|
|
{
|
|
ChangeSoldierState( pSoldier, COW_DYING, 0 , FALSE );
|
|
return;
|
|
}
|
|
else if ( pSoldier->usAnimState == BLOODCAT_HIT )
|
|
{
|
|
ChangeSoldierState( pSoldier, BLOODCAT_DYING, 0 , FALSE );
|
|
return;
|
|
}
|
|
else if ( pSoldier->usAnimState == WATER_HIT )
|
|
{
|
|
ChangeSoldierState( pSoldier, WATER_DIE, 0 , FALSE );
|
|
return;
|
|
}
|
|
else if ( pSoldier->usAnimState == DEEP_WATER_HIT )
|
|
{
|
|
ChangeSoldierState( pSoldier, DEEP_WATER_DIE, 0 , FALSE );
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
// We have missed something here - send debug msg
|
|
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, "Soldier Ani: Genmeric hit not chained" );
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
BOOLEAN CheckForAndHandleSoldierDyingNotFromHit( SOLDIERTYPE *pSoldier )
|
|
{
|
|
if ( pSoldier->bLife == 0 )
|
|
{
|
|
DoMercBattleSound( pSoldier, BATTLE_SOUND_DIE1 );
|
|
pSoldier->fDeadSoundPlayed = TRUE;
|
|
|
|
// 0verhaul: The bBeingAttackedCount is now obsolete.
|
|
// Increment being attacked count
|
|
// pSoldier->bBeingAttackedCount++;
|
|
|
|
if ( gGameSettings.fOptions[ TOPTION_BLOOD_N_GORE ] )
|
|
{
|
|
switch( pSoldier->usAnimState )
|
|
{
|
|
case FLYBACKHIT_STOP:
|
|
ChangeSoldierState( pSoldier, FLYBACK_HIT_DEATH, 0, FALSE );
|
|
break;
|
|
|
|
case FALLFORWARD_FROMHIT_STAND:
|
|
case FALLFORWARD_FROMHIT_CROUCH:
|
|
case STAND_FALLFORWARD_STOP:
|
|
ChangeSoldierState( pSoldier, GENERIC_HIT_DEATH, 0, FALSE );
|
|
break;
|
|
|
|
case FALLBACKHIT_STOP:
|
|
ChangeSoldierState( pSoldier, FALLBACK_HIT_DEATH, 0, FALSE );
|
|
break;
|
|
|
|
case PRONE_LAYFROMHIT_STOP:
|
|
case PRONE_LAY_FROMHIT:
|
|
|
|
ChangeSoldierState( pSoldier, PRONE_HIT_DEATH, 0, FALSE );
|
|
break;
|
|
|
|
case FALLOFF_STOP:
|
|
ChangeSoldierState( pSoldier, FALLOFF_DEATH, 0, FALSE );
|
|
break;
|
|
|
|
case FALLOFF_FORWARD_STOP:
|
|
ChangeSoldierState( pSoldier, FALLOFF_FORWARD_DEATH, 0, FALSE);
|
|
break;
|
|
|
|
case ADULTMONSTER_HIT:
|
|
ChangeSoldierState( pSoldier, ADULTMONSTER_DYING, 0 , FALSE );
|
|
break;
|
|
|
|
case LARVAE_HIT:
|
|
ChangeSoldierState( pSoldier, LARVAE_DIE, 0 , FALSE );
|
|
break;
|
|
|
|
case QUEEN_HIT:
|
|
ChangeSoldierState( pSoldier, QUEEN_DIE, 0 , FALSE );
|
|
break;
|
|
|
|
case CRIPPLE_HIT:
|
|
ChangeSoldierState( pSoldier, CRIPPLE_DIE, 0 , FALSE );
|
|
break;
|
|
|
|
case ROBOTNW_HIT:
|
|
ChangeSoldierState( pSoldier, ROBOTNW_DIE, 0 , FALSE );
|
|
break;
|
|
|
|
case INFANT_HIT:
|
|
ChangeSoldierState( pSoldier, INFANT_DIE, 0 , FALSE );
|
|
break;
|
|
|
|
case COW_HIT:
|
|
ChangeSoldierState( pSoldier, COW_DYING, 0 , FALSE );
|
|
break;
|
|
|
|
case BLOODCAT_HIT:
|
|
ChangeSoldierState( pSoldier, BLOODCAT_DYING, 0 , FALSE );
|
|
break;
|
|
|
|
default:
|
|
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String( "Soldier Control: Death state %d has no death hit", pSoldier->usAnimState ) );
|
|
{
|
|
BOOLEAN fMadeCorpse;
|
|
CheckForAndHandleSoldierDeath( pSoldier, &fMadeCorpse );
|
|
}
|
|
break;
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
BOOLEAN fMadeCorpse;
|
|
|
|
CheckForAndHandleSoldierDeath( pSoldier, &fMadeCorpse );
|
|
}
|
|
return( TRUE );
|
|
}
|
|
|
|
return( FALSE );
|
|
}
|
|
|
|
|
|
BOOLEAN CheckForImproperFireGunEnd( SOLDIERTYPE *pSoldier )
|
|
{
|
|
|
|
if ( AM_A_ROBOT( pSoldier ) )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
// Check single hand for jammed status, ( or ammo is out.. )
|
|
if ( pSoldier->inv[ HANDPOS ].ItemData.Gun.bGunAmmoStatus < 0 || pSoldier->inv[ HANDPOS ].ItemData.Gun.ubGunShotsLeft == 0 )
|
|
{
|
|
// If we have 2 pistols, donot go back!
|
|
if ( Item[ pSoldier->inv[ SECONDHANDPOS ].usItem ].usItemClass != IC_GUN )
|
|
{
|
|
// OK, put gun down....
|
|
InternalSoldierReadyWeapon( pSoldier, pSoldier->bDirection, TRUE );
|
|
return( TRUE );
|
|
}
|
|
}
|
|
|
|
return( FALSE );
|
|
|
|
}
|
|
|
|
|
|
BOOLEAN OKHeightDest( SOLDIERTYPE *pSoldier, INT16 sNewGridNo )
|
|
{
|
|
if ( pSoldier->bLevel == 0 )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
|
|
// Check if there is a lower place here....
|
|
if ( IsLowerLevel( sNewGridNo ) )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
BOOLEAN HandleUnjamAnimation( SOLDIERTYPE *pSoldier )
|
|
{
|
|
// OK, play intermediate animation here..... save in pending animation data, the current
|
|
// code we are at!
|
|
pSoldier->uiPendingActionData1 = pSoldier->usAniCode;
|
|
pSoldier->sPendingActionData2 = pSoldier->usAnimState;
|
|
// Check what animatnion we should do.....
|
|
switch( pSoldier->usAnimState )
|
|
{
|
|
case SHOOT_RIFLE_STAND:
|
|
case STANDING_BURST:
|
|
case FIRE_STAND_BURST_SPREAD:
|
|
// Normal shoot rifle.... play
|
|
ChangeSoldierState( pSoldier, STANDING_SHOOT_UNJAM, 0 , FALSE );
|
|
return( TRUE );
|
|
|
|
case PRONE_BURST:
|
|
case SHOOT_RIFLE_PRONE:
|
|
|
|
// Normal shoot rifle.... play
|
|
ChangeSoldierState( pSoldier, PRONE_SHOOT_UNJAM, 0 , FALSE );
|
|
return( TRUE );
|
|
|
|
case CROUCHED_BURST:
|
|
case SHOOT_RIFLE_CROUCH:
|
|
|
|
// Normal shoot rifle.... play
|
|
ChangeSoldierState( pSoldier, CROUCH_SHOOT_UNJAM, 0 , FALSE );
|
|
return( TRUE );
|
|
|
|
case SHOOT_DUAL_STAND:
|
|
|
|
// Normal shoot rifle.... play
|
|
ChangeSoldierState( pSoldier, STANDING_SHOOT_DWEL_UNJAM, 0 , FALSE );
|
|
return( TRUE );
|
|
|
|
case SHOOT_DUAL_PRONE:
|
|
|
|
// Normal shoot rifle.... play
|
|
ChangeSoldierState( pSoldier, PRONE_SHOOT_DWEL_UNJAM, 0 , FALSE );
|
|
return( TRUE );
|
|
|
|
case SHOOT_DUAL_CROUCH:
|
|
|
|
// Normal shoot rifle.... play
|
|
ChangeSoldierState( pSoldier, CROUCH_SHOOT_DWEL_UNJAM, 0 , FALSE );
|
|
return( TRUE );
|
|
|
|
case FIRE_LOW_STAND:
|
|
case FIRE_BURST_LOW_STAND:
|
|
|
|
// Normal shoot rifle.... play
|
|
ChangeSoldierState( pSoldier, STANDING_SHOOT_LOW_UNJAM, 0 , FALSE );
|
|
return( TRUE );
|
|
|
|
}
|
|
|
|
return( FALSE );
|
|
}
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
//OK, if here, if our health is still good, but we took a lot of damage, try to fall down!
|
|
if ( pSoldier->bLife >= OKLIFE )
|
|
{
|
|
// Randomly fall back or forward, if we are in the standing hit animation
|
|
if ( pSoldier->usAnimState == GENERIC_HIT_STAND || pSoldier->usAnimState == RIFLE_STAND_HIT )
|
|
{
|
|
INT8 bTestDirection = pSoldier->bDirection;
|
|
BOOLEAN fForceDirection = FALSE;
|
|
BOOLEAN fDoFallback = FALSE;
|
|
|
|
// As the damage pretty brutal?
|
|
|
|
// TRY FALLING BACKWARDS, ( ONLY IF WE ARE A MERC! )
|
|
if ( Random( 1000 ) > 40 && IS_MERC_BODY_TYPE( pSoldier ) )
|
|
{
|
|
// CHECK IF WE HAVE AN ATTACKER, TAKE OPPOSITE DIRECTION!
|
|
if ( pSoldier->ubAttackerID != NOBODY )
|
|
{
|
|
// Find direction!
|
|
bTestDirection = (INT8)GetDirectionFromGridNo( MercPtrs[ pSoldier->ubAttackerID ]->sGridNo, pSoldier );
|
|
fForceDirection = TRUE;
|
|
}
|
|
|
|
sNewGridNo = NewGridNo( (UINT16)pSoldier->sGridNo, (UINT16)(-1 * DirectionInc( bTestDirection ) ) );
|
|
|
|
if ( NewOKDestination( pSoldier, sNewGridNo, TRUE, pSoldier->bLevel ) && OKHeightDest( pSoldier, sNewGridNo ) )
|
|
{
|
|
// ALL'S OK HERE..... IF WE FORCED DIRECTION, SET!
|
|
if ( fForceDirection )
|
|
{
|
|
EVENT_SetSoldierDirection( pSoldier, bTestDirection );
|
|
EVENT_SetSoldierDesiredDirection( pSoldier, bTestDirection );
|
|
}
|
|
ChangeSoldierState( pSoldier, FALLBACK_HIT_STAND, 0, FALSE );
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
BOOLEAN OKFallDirection( SOLDIERTYPE *pSoldier, INT16 sGridNo, INT8 bLevel, INT8 bTestDirection, UINT16 usAnimState )
|
|
{
|
|
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"OKFallDirection");
|
|
STRUCTURE_FILE_REF * pStructureFileRef;
|
|
UINT16 usAnimSurface;
|
|
|
|
// How are the movement costs?
|
|
if ( gubWorldMovementCosts[ sGridNo ][ bTestDirection ][ bLevel ] > TRAVELCOST_SHORE )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
//NOT ok if in water....
|
|
if ( GetTerrainType( sGridNo ) == MED_WATER || GetTerrainType( sGridNo ) == DEEP_WATER || GetTerrainType( sGridNo ) == LOW_WATER )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
// How are we for OK dest?
|
|
if (!NewOKDestination( pSoldier, sGridNo, TRUE, bLevel ) )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
usAnimSurface = DetermineSoldierAnimationSurface( pSoldier, usAnimState );
|
|
pStructureFileRef = GetAnimationStructureRef( pSoldier->ubID, usAnimSurface, usAnimState );
|
|
|
|
if ( pStructureFileRef )
|
|
{
|
|
UINT16 usStructureID;
|
|
INT16 sTestGridNo;
|
|
|
|
// must make sure that structure data can be added in the direction of the target
|
|
|
|
usStructureID = pSoldier->ubID;
|
|
|
|
// Okay this is really SCREWY but it's due to the way this function worked before and must
|
|
// work now. The function is passing in an adjacent gridno but we need to place the structure
|
|
// data in the tile BEFORE. So we take one step back in the direction opposite to bTestDirection
|
|
// and use that gridno
|
|
sTestGridNo = NewGridNo( sGridNo, (UINT16)( DirectionInc( gOppositeDirection[ bTestDirection ] ) ) );
|
|
|
|
if ( ! OkayToAddStructureToWorld( sTestGridNo, bLevel, &(pStructureFileRef->pDBStructureRef[ gOneCDirection[ bTestDirection ] ]), usStructureID ) )
|
|
{
|
|
// can't go in that dir!
|
|
return( FALSE );
|
|
}
|
|
}
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
BOOLEAN HandleCheckForDeathCommonCode( SOLDIERTYPE *pSoldier )
|
|
{
|
|
// Do we have a primary pending animation?
|
|
if ( pSoldier->usPendingAnimation2 != NO_PENDING_ANIMATION )
|
|
{
|
|
ChangeSoldierState( pSoldier, pSoldier->usPendingAnimation2, 0, FALSE );
|
|
pSoldier->usPendingAnimation2 = NO_PENDING_ANIMATION;
|
|
return( TRUE );
|
|
}
|
|
|
|
// CHECK IF WE HAVE A PENDING ANIMATION HERE
|
|
if ( pSoldier->usPendingAnimation != NO_PENDING_ANIMATION )
|
|
{
|
|
ChangeSoldierState( pSoldier, pSoldier->usPendingAnimation, 0, FALSE );
|
|
pSoldier->usPendingAnimation = NO_PENDING_ANIMATION;
|
|
return( TRUE );
|
|
}
|
|
|
|
// OTHERWISE, GOTO APPROPRIATE STOPANIMATION!
|
|
pSoldier->bCollapsed = TRUE;
|
|
|
|
// CC has requested - handle sight here...
|
|
HandleSight( pSoldier, SIGHT_LOOK );
|
|
|
|
// ATE: If it is our turn, make them try to getup...
|
|
if ( gTacticalStatus.ubCurrentTeam == pSoldier->bTeam )
|
|
{
|
|
// Try to getup...
|
|
BeginSoldierGetup( pSoldier );
|
|
|
|
// Check this to see if above worked
|
|
if ( !pSoldier->bCollapsed )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
}
|
|
|
|
switch( pSoldier->usAnimState )
|
|
{
|
|
case FLYBACK_HIT:
|
|
ChangeSoldierState( pSoldier, FLYBACKHIT_STOP, 0, FALSE );
|
|
break;
|
|
|
|
case GENERIC_HIT_DEATHTWITCHNB:
|
|
case FALLFORWARD_FROMHIT_STAND:
|
|
case ENDFALLFORWARD_FROMHIT_CROUCH:
|
|
|
|
ChangeSoldierState( pSoldier, STAND_FALLFORWARD_STOP, 0, FALSE );
|
|
break;
|
|
|
|
case FALLBACK_HIT_DEATHTWITCHNB:
|
|
case FALLBACK_HIT_STAND:
|
|
ChangeSoldierState( pSoldier, FALLBACKHIT_STOP, 0, FALSE );
|
|
break;
|
|
|
|
case PRONE_HIT_DEATHTWITCHNB:
|
|
case PRONE_LAY_FROMHIT:
|
|
|
|
ChangeSoldierState( pSoldier, PRONE_LAYFROMHIT_STOP, 0, FALSE );
|
|
break;
|
|
|
|
case FALLOFF:
|
|
ChangeSoldierState( pSoldier, FALLOFF_STOP, 0, FALSE );
|
|
break;
|
|
|
|
case FALLFORWARD_ROOF:
|
|
ChangeSoldierState( pSoldier, FALLOFF_FORWARD_STOP, 0, FALSE);
|
|
break;
|
|
|
|
default:
|
|
// IF we are here - something is wrong - we should have a death animation here
|
|
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String( "Soldier Ani: unconscious hit sequence needed for animation %d", pSoldier->usAnimState ) );
|
|
|
|
}
|
|
// OTHERWISE, GOTO APPROPRIATE STOPANIMATION!
|
|
pSoldier->bCollapsed = TRUE;
|
|
|
|
// ATE: If it is our turn, make them try to getup...
|
|
if ( gTacticalStatus.ubCurrentTeam == pSoldier->bTeam )
|
|
{
|
|
// Try to getup...
|
|
BeginSoldierGetup( pSoldier );
|
|
|
|
// Check this to see if above worked
|
|
if ( !pSoldier->bCollapsed )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
}
|
|
|
|
switch( pSoldier->usAnimState )
|
|
{
|
|
case FLYBACK_HIT:
|
|
ChangeSoldierState( pSoldier, FLYBACKHIT_STOP, 0, FALSE );
|
|
break;
|
|
|
|
case GENERIC_HIT_DEATHTWITCHNB:
|
|
case FALLFORWARD_FROMHIT_STAND:
|
|
case ENDFALLFORWARD_FROMHIT_CROUCH:
|
|
|
|
ChangeSoldierState( pSoldier, STAND_FALLFORWARD_STOP, 0, FALSE );
|
|
break;
|
|
|
|
case FALLBACK_HIT_DEATHTWITCHNB:
|
|
case FALLBACK_HIT_STAND:
|
|
ChangeSoldierState( pSoldier, FALLBACKHIT_STOP, 0, FALSE );
|
|
break;
|
|
|
|
case PRONE_HIT_DEATHTWITCHNB:
|
|
case PRONE_LAY_FROMHIT:
|
|
|
|
ChangeSoldierState( pSoldier, PRONE_LAYFROMHIT_STOP, 0, FALSE );
|
|
break;
|
|
|
|
case FALLOFF:
|
|
ChangeSoldierState( pSoldier, FALLOFF_STOP, 0, FALSE );
|
|
break;
|
|
|
|
case FALLFORWARD_ROOF:
|
|
ChangeSoldierState( pSoldier, FALLOFF_FORWARD_STOP, 0, FALSE);
|
|
break;
|
|
|
|
default:
|
|
// IF we are here - something is wrong - we should have a death animation here
|
|
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String( "Soldier Ani: unconscious hit sequence needed for animation %d", pSoldier->usAnimState ) );
|
|
|
|
}
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
void KickOutWheelchair( SOLDIERTYPE *pSoldier )
|
|
{
|
|
INT16 sNewGridNo;
|
|
|
|
// Move forward one gridno....
|
|
sNewGridNo = NewGridNo( (UINT16)pSoldier->sGridNo, (UINT16)( DirectionInc( pSoldier->bDirection ) ) );
|
|
|
|
// ATE: Make sure that the gridno is unoccupied!
|
|
if ( !NewOKDestination( pSoldier, sNewGridNo, TRUE, pSoldier->bLevel ) )
|
|
{
|
|
// We should just stay put - will look kind of funny but nothing I can do!
|
|
sNewGridNo = pSoldier->sGridNo;
|
|
}
|
|
|
|
EVENT_StopMerc( pSoldier, sNewGridNo, pSoldier->bDirection );
|
|
pSoldier->ubBodyType = REGMALE;
|
|
if ( pSoldier->ubProfile == SLAY && pSoldier->bTeam == CIV_TEAM && !pSoldier->bNeutral )
|
|
{
|
|
HandleNPCDoAction( pSoldier->ubProfile, NPC_ACTION_THREATENINGLY_RAISE_GUN, 0 );
|
|
}
|
|
else
|
|
{
|
|
EVENT_InitNewSoldierAnim( pSoldier, STANDING, 0 , TRUE );
|
|
}
|
|
|
|
// If this person has a profile ID, set body type to regmale
|
|
if ( pSoldier->ubProfile != NO_PROFILE )
|
|
{
|
|
gMercProfiles[ pSoldier->ubProfile ].ubBodyType = REGMALE;
|
|
}
|
|
|
|
}
|