mirror of
https://github.com/1dot13/source.git
synced 2026-07-22 13:40:22 +02:00
- new feature: ramming people - set with Tactical Gameplay Settings > ALLOW_CARS_DRIVING_OVER_PEOPLE and Tactical Gameplay Settings > ALLOW_TANKS_DRIVING_OVER_PEOPLE - when shift is pressed planned vehicle route will go through people. Those who will stay on its path will be hit, causing wounds and knock-outs. - new feature: ramming structures - when shift is pressed planned vehicle route will go through obstacles. When vehicle hits the structure on its path it will be destroyed, causing small damage to vehicle too (with exception of tank). Tactical Gameplay Settings > CARS_RAMMING_MAX_STRUCTURE_ARMOUR and Tactical Gameplay Settings > TANKS_RAMMING_MAX_STRUCTURE_ARMOUR settings control how well armoured structure can be driven through and amount of potential damage for vehicle. - see: http://www.ja-galaxy-forum.com/ubbthreads.php/topics/333829/Drivable_Vehicles#Post333829 git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@7284 3b4a5df2-a311-0410-b5c6-a8a6f20db521
4881 lines
154 KiB
C++
4881 lines
154 KiB
C++
#ifdef PRECOMPILEDHEADERS
|
|
#include "Tactical All.h"
|
|
#else
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include "stdlib.h"
|
|
#include "debug.h"
|
|
#include "MemMan.h"
|
|
#include "Overhead Types.h"
|
|
#include "Soldier Control.h" // I need this here - SANDRO
|
|
#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"
|
|
#include "Food.h"
|
|
#include "CampaignStats.h" // added by Flugente
|
|
#endif
|
|
|
|
// anv: for enemy taunts
|
|
#include "Civ Quotes.h"
|
|
|
|
//forward declarations of common classes to eliminate includes
|
|
class OBJECTTYPE;
|
|
class SOLDIERTYPE;
|
|
#include "connect.h"
|
|
#include "fresh_header.h"
|
|
#define NO_JUMP 0
|
|
#define MAX_ANIFRAMES_PER_FLASH 2
|
|
//#define TIME_FOR_RANDOM_ANIM_CHECK 10
|
|
#define TIME_FOR_RANDOM_ANIM_CHECK 1
|
|
|
|
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, INT32 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, BOOLEAN fHipStance );
|
|
|
|
// 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;
|
|
INT32 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->stats.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->flags.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
|
|
pSoldier->ConvertAniCodeToAniFrame( (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->flags.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->ubDirection == NORTH )
|
|
{
|
|
pSoldier->SetSoldierHeight( (FLOAT)(pSoldier->sHeightAdjustment + 2 ) );
|
|
}
|
|
else
|
|
{
|
|
pSoldier->SetSoldierHeight( (FLOAT)( pSoldier->sHeightAdjustment + 3 ) );
|
|
}
|
|
break;
|
|
|
|
case 408:
|
|
|
|
// CODE: SPECIAL MOVE CLIMB UP ROOF EVENT
|
|
|
|
// Moved here because this represents "already on the roof", so breath collapses and interrupts should
|
|
// keep the soldier on the roof where he belongs
|
|
// Move merc up specific height
|
|
pSoldier->SetSoldierHeight( (FLOAT)50 );
|
|
|
|
{
|
|
INT16 sXPos, sYPos;
|
|
|
|
//sNewGridNo = NewGridNo( pSoldier->sGridNo, (UINT16)DirectionInc( pSoldier->ubDirection ) );
|
|
ConvertMapPosToWorldTileCenter( pSoldier->sTempNewGridNo, &sXPos, &sYPos );
|
|
pSoldier->EVENT_SetSoldierPosition( (FLOAT)sXPos, (FLOAT)sYPos );
|
|
}
|
|
|
|
// re-enable sight
|
|
gTacticalStatus.uiFlags &= (~DISALLOW_SIGHT);
|
|
|
|
// Move two CC directions
|
|
pSoldier->EVENT_SetSoldierDirection( gTwoCCDirection[ pSoldier->ubDirection ] );
|
|
|
|
pSoldier->EVENT_SetSoldierDesiredDirection( pSoldier->ubDirection );
|
|
|
|
// Set desired anim height!
|
|
pSoldier->ubDesiredHeight = ANIM_CROUCH;
|
|
|
|
// Madd
|
|
usUIMovementMode = pSoldier->GetMoveStateBasedOnStance( gAnimControl[ pSoldier->usAnimState ].ubEndHeight );
|
|
pSoldier->usUIMovementMode = usUIMovementMode;
|
|
|
|
// 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
|
|
pSoldier->SetSoldierHeight( (FLOAT)( pSoldier->sHeightAdjustment - 2 ) );
|
|
break;
|
|
|
|
case 410:
|
|
|
|
// Move merc down specific height
|
|
pSoldier->SetSoldierHeight( (FLOAT)0 );
|
|
break;
|
|
|
|
case 411:
|
|
|
|
// CODE: SPECIALMOVE CLIMB DOWN EVENT
|
|
// Move two C directions
|
|
pSoldier->EVENT_SetSoldierDirection( gTwoCDirection[ pSoldier->ubDirection ] );
|
|
|
|
// Remove the roof marker
|
|
HandlePlacingRoofMarker( pSoldier, pSoldier->sGridNo, FALSE, TRUE );
|
|
|
|
pSoldier->EVENT_SetSoldierDesiredDirection( pSoldier->ubDirection );
|
|
// Adjust height
|
|
pSoldier->SetSoldierHeight( (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;
|
|
if((is_server && pSoldier->ubID<120) || (!is_server && is_client && pSoldier->ubID<20) || (!is_server && !is_client) )
|
|
{
|
|
//only carry on if own werc
|
|
AddGameEvent( S_FIREWEAPON, 0, &SFireWeapon );
|
|
|
|
//hayden
|
|
if(is_server || (is_client && pSoldier->ubID <20) )
|
|
send_fireweapon( &SFireWeapon );
|
|
}
|
|
|
|
OBJECTTYPE* pObjHand = pSoldier->GetUsedWeapon( &pSoldier->inv[HANDPOS] );
|
|
|
|
//DIGICRAB: Burst UnCap
|
|
//Loop around in the animation if we still have burst rounds to fire
|
|
if (pSoldier->bDoBurst && !(pSoldier->IsValidSecondHandBurst())
|
|
&& ( pSoldier->bDoBurst <= ( (pSoldier->bDoAutofire)?(pSoldier->bDoAutofire):(GetShotsPerBurst( pObjHand )) )
|
|
|| (( pSoldier->bWeaponMode == WM_ATTACHED_GL_BURST && pSoldier->bDoBurst <= Weapon[GetAttachedGrenadeLauncher(&pSoldier->inv[HANDPOS])].ubShotsPerBurst)) ))
|
|
{
|
|
if(pSoldier->usAnimState == STANDING_BURST || pSoldier->usAnimState == CROUCHED_BURST || pSoldier->usAnimState == PRONE_BURST || pSoldier->usAnimState == BURST_ALTERNATIVE_STAND && pSoldier->usAniCode == 33) //we are standing, crounching or prone, firing the fast shot
|
|
pSoldier->usAniCode = 3;
|
|
else if(pSoldier->usAnimState == FIRE_BURST_LOW_STAND || pSoldier->usAnimState == LOW_BURST_ALTERNATIVE_STAND && pSoldier->usAniCode == 37) //we are firing down to something very close, last shot
|
|
pSoldier->usAniCode = 14;
|
|
else if(pSoldier->usAnimState == TANK_BURST)//dnl ch64 280813 fix 6 round burst limitation
|
|
{
|
|
if(pSoldier->bDoBurst < pSoldier->bDoAutofire)//!!! this will be fine as long you not decide to equip tank with other weapons add limitted ammo, weapon jam, etc.
|
|
pSoldier->usAniCode = 4;
|
|
else
|
|
pSoldier->usAniCode = 34;
|
|
}
|
|
else if(pSoldier->usAnimState == ROBOT_BURST_SHOOT) //silversurfer: Bugfix JaggZilla #532 6 round burst limitation
|
|
{
|
|
if(pSoldier->bDoBurst < pSoldier->bDoAutofire)
|
|
pSoldier->usAniCode = 4;
|
|
else
|
|
pSoldier->usAniCode = 34;
|
|
}
|
|
}
|
|
|
|
OBJECTTYPE* pObjUsed = pSoldier->GetUsedWeapon( &pSoldier->inv[ pSoldier->ubAttackingHand ] );
|
|
UINT16 usedGun = pSoldier->GetUsedWeaponNumber( &pSoldier->inv[ pSoldier->ubAttackingHand ] );
|
|
//DIGICRAB: Burst Sound
|
|
//This code is stolen from Tactical\Weapons.c - UseGun(...)
|
|
if (pSoldier->bDoBurst && pSoldier->iBurstSoundID == NO_SAMPLE && Weapon[ usedGun ].sSound != 0 && Item[ usedGun ].usItemClass != IC_THROWING_KNIFE )
|
|
{
|
|
// Switch on silencer...
|
|
INT16 noisefactor = GetPercentNoiseVolume( pObjUsed );
|
|
if( noisefactor < gGameExternalOptions.gubMaxPercentNoiseSilencedSound || Weapon[ usedGun ].ubAttackVolume <= 10 )
|
|
{
|
|
INT32 uiSound;
|
|
|
|
uiSound = Weapon [ usedGun ].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[ usedGun ].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
|
|
// pSoldier->DoMercBattleSound( 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;
|
|
pSoldier->ChangeSoldierState( 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
|
|
pSoldier->ChangeSoldierState( (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
|
|
pSoldier->ChangeSoldierState( usOldAnimState, 0, FALSE );
|
|
return( TRUE );
|
|
}
|
|
break;
|
|
|
|
case 437:
|
|
|
|
// CHANGE DIRECTION AND GET-UP
|
|
//sGridNo = NewGridNo( pSoldier->sGridNo, (UINT16)(-1 * DirectionInc( pSoldier->ubDirection ) ) );
|
|
//ConvertMapPosToWorldTileCenter( pSoldier->sGridNo, &sXPos, &sYPos );
|
|
//SetSoldierPosition( pSoldier, (FLOAT)sXPos, (FLOAT)sYPos );
|
|
|
|
|
|
// Reverse direction
|
|
pSoldier->EVENT_SetSoldierDirection( gOppositeDirection[ pSoldier->ubDirection ] );
|
|
pSoldier->EVENT_SetSoldierDesiredDirection( pSoldier->ubDirection );
|
|
|
|
pSoldier->ChangeSoldierState( GETUP_FROM_ROLLOVER, 0 , FALSE );
|
|
return( TRUE );
|
|
|
|
case 438:
|
|
|
|
//CODE: START HOLD FLASH
|
|
pSoldier->flags.fForceShade = TRUE;
|
|
break;
|
|
|
|
case 439:
|
|
|
|
//CODE: END HOLD FLASH
|
|
pSoldier->flags.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->aiData.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->flags.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
|
|
{
|
|
INT32 usNewGridNo;
|
|
INT16 sXPos, sYPos;
|
|
|
|
usNewGridNo = NewGridNo( pSoldier->sGridNo, DirectionInc( pSoldier->ubDirection ) );
|
|
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->flags.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 || pSoldier->usAnimState == START_COWER_CROUCHED || pSoldier->usAnimState == START_COWER_PRONE )
|
|
{
|
|
UnSetUIBusy( pSoldier->ubID );
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// SANDRO - if pending interrupt flag was set for after-attack type of interupt, try to resolve it now
|
|
else if ( gGameOptions.fImprovedInterruptSystem )
|
|
{
|
|
if ( ResolvePendingInterrupt( pSoldier, AFTERACTION_INTERRUPT ) )
|
|
{
|
|
pSoldier->usPendingAnimation = NO_PENDING_ANIMATION;
|
|
pSoldier->ubPendingDirection = NO_PENDING_DIRECTION;
|
|
// "artificially" set lock ui flag in this case
|
|
if (pSoldier->bTeam == gbPlayerNum)
|
|
{
|
|
//AddTopMessage( COMPUTER_INTERRUPT_MESSAGE, Message[STR_INTERRUPT] );
|
|
guiPendingOverrideEvent = LU_BEGINUILOCK;
|
|
HandleTacticalUI( );
|
|
}
|
|
return( TRUE );
|
|
}
|
|
}
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
break;
|
|
|
|
case 443:
|
|
|
|
// MOVE GUY FORWARD FOR FENCE HOP ANIMATION
|
|
switch( pSoldier->ubDirection )
|
|
{
|
|
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 );
|
|
|
|
pSoldier->EVENT_InternalSetSoldierPosition( (FLOAT) sX, (FLOAT) sY, FALSE, FALSE, FALSE );
|
|
pSoldier->EVENT_SetSoldierDirection( gTwoCDirection[ pSoldier->ubDirection ] );
|
|
pSoldier->sZLevelOverride = -1;
|
|
pSoldier->EVENT_SetSoldierDesiredDirection( pSoldier->ubDirection );
|
|
|
|
if ( gTacticalStatus.bBoxingState == BOXING_WAITING_FOR_PLAYER || gTacticalStatus.bBoxingState == PRE_BOXING || gTacticalStatus.bBoxingState == BOXING )
|
|
{
|
|
BoxingMovementCheck( pSoldier );
|
|
}
|
|
|
|
if ( SetOffBombsInGridNo( pSoldier->ubID, pSoldier->sGridNo, FALSE, pSoldier->pathing.bLevel ))
|
|
{
|
|
pSoldier->EVENT_StopMerc( pSoldier->sGridNo, pSoldier->ubDirection );
|
|
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->pathing.sFinalDestination )
|
|
{
|
|
if ( gAnimControl[ pSoldier->usAnimState ].ubEndHeight != gAnimControl[ pSoldier->usUIMovementMode ].ubEndHeight )
|
|
{
|
|
// Goto Stance...
|
|
pSoldier->flags.fDontChargeAPsForStanceChange = TRUE;
|
|
pSoldier->ChangeSoldierStance( gAnimControl[ pSoldier->usUIMovementMode ].ubEndHeight );
|
|
return( TRUE );
|
|
}
|
|
else
|
|
{
|
|
//pSoldier->SoldierGotoStationaryStance( );
|
|
|
|
// 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->ubDirection )
|
|
{
|
|
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->flags.uiStatusFlags |= SOLDIER_PAUSEANIMOVE;
|
|
break;
|
|
|
|
case 447:
|
|
|
|
// TRY TO FALL!!!
|
|
if ( pSoldier->flags.fTryingToFall )
|
|
{
|
|
INT16 sLastAniFrame;
|
|
|
|
// TRY FORWARDS...
|
|
// FIRST GRIDNO
|
|
sNewGridNo = NewGridNo( pSoldier->sGridNo, DirectionInc( pSoldier->ubDirection ) );
|
|
|
|
if ( OKFallDirection( pSoldier, sNewGridNo, pSoldier->pathing.bLevel, pSoldier->ubDirection, FALLFORWARD_HITDEATH_STOP ) )
|
|
{
|
|
// SECOND GRIDNO
|
|
// sNewGridNo = NewGridNo( sNewGridNo, (UINT16)( DirectionInc( pSoldier->ubDirection ) ) );
|
|
|
|
// if ( OKFallDirection( pSoldier, sNewGridNo, pSoldier->pathing.bLevel, pSoldier->ubDirection, FALLFORWARD_HITDEATH_STOP ) )
|
|
{
|
|
// ALL'S OK HERE...
|
|
pSoldier->flags.fTryingToFall = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
// IF HERE, INCREMENT DIRECTION
|
|
// ATE: Added Feb1 - can be either direction....
|
|
if ( pSoldier->flags.fFallClockwise )
|
|
{
|
|
pSoldier->EVENT_SetSoldierDirection( gOneCDirection[ pSoldier->ubDirection ] );
|
|
}
|
|
else
|
|
{
|
|
pSoldier->EVENT_SetSoldierDirection( gOneCCDirection[ pSoldier->ubDirection ] );
|
|
}
|
|
pSoldier->EVENT_SetSoldierDesiredDirection( pSoldier->ubDirection );
|
|
sLastAniFrame = gusAnimInst[ pSoldier->usAnimState ][ ( pSoldier->usAniCode - 2 ) ];
|
|
pSoldier->ConvertAniCodeToAniFrame( (INT16)( sLastAniFrame ) );
|
|
|
|
if ( pSoldier->ubDirection == pSoldier->bStartFallDir )
|
|
{
|
|
// GO FORWARD HERE...
|
|
pSoldier->flags.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;
|
|
|
|
OBJECTTYPE* pObjHand = pSoldier->GetUsedWeapon( &pSoldier->inv[HANDPOS] );
|
|
|
|
if ( ( pSoldier->bWeaponMode == WM_ATTACHED_GL_BURST && pSoldier->bDoBurst > Weapon[GetAttachedGrenadeLauncher(&pSoldier->inv[HANDPOS])].ubShotsPerBurst) )
|
|
{
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,"AdjustToNextAnimationFrame: Burst case 448, stopping because gl max burst size reached");
|
|
fStop = TRUE;
|
|
fFreeUpAttacker = TRUE;
|
|
}
|
|
else if (pSoldier->bWeaponMode != WM_ATTACHED_GL_BURST && !(pSoldier->IsValidSecondHandBurst()) && (pSoldier->bDoBurst > ((pSoldier->bDoAutofire)?(pSoldier->bDoAutofire):(GetShotsPerBurst( pObjHand )))))
|
|
{
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,"AdjustToNextAnimationFrame: Burst case 448, stopping because gun max burst size reached");
|
|
fStop = TRUE;
|
|
fFreeUpAttacker = TRUE;
|
|
}
|
|
else if (pSoldier->bWeaponMode != WM_ATTACHED_GL_BURST && pSoldier->IsValidSecondHandBurst() && (pSoldier->bDoBurst > ((pSoldier->bDoAutofire)?(2*pSoldier->bDoAutofire):(2*GetShotsPerBurst( pObjHand )))))
|
|
{
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,"AdjustToNextAnimationFrame: Burst case 448, stopping because dual max burst size reached");
|
|
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->flags.autofireLastStep = FALSE;
|
|
pSoldier->bDoAutofire = 1;
|
|
}
|
|
|
|
pSoldier->flags.fDoSpread = FALSE;
|
|
pSoldier->bDoBurst = 1;
|
|
// pSoldier->flags.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 ) )
|
|
{
|
|
pSoldier->ChangeSoldierState( STANDING, 0 , FALSE );
|
|
}
|
|
else
|
|
{
|
|
switch ( gAnimControl[ pSoldier->usAnimState ].ubEndHeight )
|
|
{
|
|
case ANIM_STAND:
|
|
if ( pSoldier->usAnimState == BURST_DUAL_STAND )
|
|
pSoldier->ChangeSoldierState( AIM_DUAL_STAND, 0 , FALSE );
|
|
else if ( pSoldier->usAnimState == BURST_ALTERNATIVE_STAND || pSoldier->usAnimState == LOW_BURST_ALTERNATIVE_STAND )
|
|
pSoldier->ChangeSoldierState( AIM_ALTERNATIVE_STAND, 0 , FALSE );
|
|
else
|
|
pSoldier->ChangeSoldierState( AIM_RIFLE_STAND, 0 , FALSE );
|
|
break;
|
|
|
|
case ANIM_PRONE:
|
|
if ( pSoldier->usAnimState == BURST_DUAL_PRONE )
|
|
pSoldier->ChangeSoldierState( AIM_DUAL_PRONE, 0 , FALSE );
|
|
else
|
|
pSoldier->ChangeSoldierState( AIM_RIFLE_PRONE, 0 , FALSE );
|
|
break;
|
|
|
|
case ANIM_CROUCH:
|
|
if ( pSoldier->usAnimState == BURST_DUAL_CROUCH )
|
|
pSoldier->ChangeSoldierState( AIM_DUAL_CROUCH, 0 , FALSE );
|
|
else
|
|
pSoldier->ChangeSoldierState( AIM_RIFLE_CROUCH, 0 , FALSE );
|
|
break;
|
|
|
|
}
|
|
}
|
|
return( TRUE );
|
|
}
|
|
|
|
// MOVETO CURRENT SPREAD LOCATION
|
|
if ( pSoldier->flags.fDoSpread )
|
|
{
|
|
if ( pSoldier->sSpreadLocations[ pSoldier->flags.fDoSpread - 1 ] != 0 )
|
|
{
|
|
pSoldier->EVENT_SetSoldierDirection( (INT8)GetDirectionToGridNoFromGridNo( pSoldier->sGridNo, pSoldier->sSpreadLocations[ pSoldier->flags.fDoSpread - 1 ] ) );
|
|
pSoldier->EVENT_SetSoldierDesiredDirection( pSoldier->ubDirection );
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 449:
|
|
|
|
//CODE: FINISH BURST
|
|
pSoldier->flags.fDoSpread = FALSE;
|
|
pSoldier->bDoBurst = 1;
|
|
// pSoldier->flags.fBurstCompleted = TRUE;
|
|
break;
|
|
|
|
case 450:
|
|
|
|
//CODE: BEGINHOPFENCE
|
|
// MOVE TWO FACGIN GRIDNOS
|
|
sNewGridNo = NewGridNo( pSoldier->sGridNo, (UINT16)( DirectionInc( pSoldier->ubDirection ) ) );
|
|
//ddd window{
|
|
if ( gubWorldMovementCosts[ sNewGridNo ][ (UINT8)pSoldier->pathing.usPathingData[ pSoldier->pathing.usPathIndex ] ][ pSoldier->pathing.bLevel ] == TRAVELCOST_FENCE )
|
|
sNewGridNo = NewGridNo( sNewGridNo, (UINT16)( DirectionInc( pSoldier->ubDirection ) ) );
|
|
//ddd window}
|
|
|
|
//comm by ddd
|
|
//sNewGridNo = NewGridNo( sNewGridNo, (UINT16)( DirectionInc( pSoldier->ubDirection ) ) );
|
|
pSoldier->sForcastGridno = sNewGridNo;
|
|
break;
|
|
|
|
|
|
case 451:
|
|
|
|
// CODE: MANAGE START z-buffer override
|
|
switch( pSoldier->ubDirection )
|
|
{
|
|
case NORTH:
|
|
case WEST:
|
|
|
|
pSoldier->sZLevelOverride = TOPMOST_Z_LEVEL;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 452:
|
|
|
|
// CODE: MANAGE END z-buffer override
|
|
switch( pSoldier->ubDirection )
|
|
{
|
|
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->ubDirection == NORTH )
|
|
{
|
|
pSoldier->SetSoldierHeight( (FLOAT)(pSoldier->aiData.dHeightAdjustment + gClimbUpRoofDist[ pSoldier->ubBodyType ] ) );
|
|
}
|
|
else
|
|
{
|
|
pSoldier->SetSoldierHeight( (FLOAT)(pSoldier->aiData.dHeightAdjustment + gClimbUpRoofDist[ pSoldier->ubBodyType ] ) );
|
|
}
|
|
break;
|
|
|
|
case 455:
|
|
|
|
// MOVE GUY FORWARD SOME VALUE
|
|
MoveMercFacingDirection( pSoldier, FALSE, (FLOAT)gClimbUpRoofLATDist[ pSoldier->ubBodyType ] );
|
|
|
|
// MOVE DOWN SOME VALUE TOO!
|
|
pSoldier->SetSoldierHeight( (FLOAT)(pSoldier->aiData.dHeightAdjustment - gClimbUpRoofDistGoingLower[ pSoldier->ubBodyType ] ) );
|
|
|
|
break;
|
|
|
|
case 456:
|
|
|
|
// CODE: HANDLE CLIMBING ROOF,
|
|
// Move merc DOWN
|
|
if ( pSoldier->ubDirection == NORTH )
|
|
{
|
|
pSoldier->SetSoldierHeight( (FLOAT)(pSoldier->aiData.dHeightAdjustment - gClimbUpRoofDist[ pSoldier->ubBodyType ] ) );
|
|
}
|
|
else
|
|
{
|
|
pSoldier->SetSoldierHeight( (FLOAT)(pSoldier->aiData.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->flags.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->flags.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, AFTERACTION_INTERRUPT );
|
|
}
|
|
else
|
|
{
|
|
// ATE: Deduct points!
|
|
DeductPoints( pSoldier, APBPConstants[AP_TOSS_ITEM], 0, AFTERACTION_INTERRUPT );
|
|
}
|
|
|
|
INT32 iRealObjectID = 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 );
|
|
|
|
// OJW - 20091002 - Explosives
|
|
if (is_networked && is_client)
|
|
{
|
|
if (pSoldier->bTeam == 0 || (pSoldier->bTeam == 1 && is_server))
|
|
{
|
|
send_grenade( pSoldier->pTempObject , pSoldier->pThrowParams->dLifeSpan, pSoldier->pThrowParams->dX, pSoldier->pThrowParams->dY, pSoldier->pThrowParams->dZ, pSoldier->pThrowParams->dForceX, pSoldier->pThrowParams->dForceY, pSoldier->pThrowParams->dForceZ, pSoldier->sTargetGridNo, pSoldier->ubID, pSoldier->pThrowParams->ubActionCode, pSoldier->pThrowParams->uiActionData, iRealObjectID , true);
|
|
}
|
|
}
|
|
|
|
// Remove object
|
|
//RemoveObjFrom( &(pSoldier->inv[ HANDPOS ] ), 0 );
|
|
|
|
// Update UI
|
|
DirtyMercPanelInterface( pSoldier, DIRTYLEVEL2 );
|
|
|
|
OBJECTTYPE::DeleteMe( &pSoldier->pTempObject );
|
|
|
|
MemFree( pSoldier->pThrowParams );
|
|
pSoldier->pThrowParams = NULL;
|
|
}
|
|
break;
|
|
|
|
case 462:
|
|
|
|
// CODE: MOVE UP FROM CLIFF CLIMB
|
|
pSoldier->aiData.dHeightAdjustment += (float)2.1;
|
|
pSoldier->sHeightAdjustment = (INT16)pSoldier->aiData.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->aiData.dHeightAdjustment = (float)0;
|
|
pSoldier->sHeightAdjustment = (INT16)pSoldier->aiData.dHeightAdjustment;
|
|
|
|
// Set new gridno
|
|
{
|
|
INT32 sTempGridNo;
|
|
INT16 sNewX, sNewY;
|
|
|
|
//Get Next GridNo;
|
|
sTempGridNo = NewGridNo( pSoldier->sGridNo, DirectionInc(pSoldier->ubDirection ) );
|
|
|
|
// Get center XY
|
|
ConvertGridNoToCenterCellXY( sTempGridNo, &sNewX, &sNewY );
|
|
|
|
// Set position
|
|
pSoldier->EVENT_SetSoldierPosition( sNewX, sNewY );
|
|
|
|
// Move two CC directions
|
|
pSoldier->EVENT_SetSoldierDirection( gTwoCCDirection[ pSoldier->ubDirection ] );
|
|
pSoldier->EVENT_SetSoldierDesiredDirection( pSoldier->ubDirection );
|
|
|
|
// Set desired anim height!
|
|
pSoldier->ubDesiredHeight = ANIM_CROUCH;
|
|
pSoldier->pathing.sFinalDestination = pSoldier->sGridNo;
|
|
|
|
}
|
|
break;
|
|
|
|
case 465:
|
|
|
|
// CODE: SET GUY TO LIFE OF 0
|
|
pSoldier->stats.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!
|
|
pSoldier->SetSoldierHeight( (FLOAT)(pSoldier->aiData.dHeightAdjustment - 2 ) );
|
|
}
|
|
else
|
|
{
|
|
// Adjust!
|
|
pSoldier->SetSoldierHeight( (FLOAT)(pSoldier->aiData.dHeightAdjustment + 2 ) );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Adjust!
|
|
pSoldier->SetSoldierHeight( (FLOAT)(pSoldier->sDesiredHeight) );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Goto eating animation
|
|
if ( pSoldier->sDesiredHeight == 0 )
|
|
{
|
|
pSoldier->ChangeSoldierState( CROW_EAT, 0 , FALSE );
|
|
}
|
|
else
|
|
{
|
|
// We should leave now!
|
|
TacticalRemoveSoldier( pSoldier->ubID );
|
|
return( FALSE );
|
|
}
|
|
return( TRUE );
|
|
}
|
|
break;
|
|
|
|
case 467:
|
|
|
|
///CODE: FOR HELIDROP, SET DIRECTION
|
|
pSoldier->EVENT_SetSoldierDirection( EAST );
|
|
pSoldier->EVENT_SetSoldierDesiredDirection( pSoldier->ubDirection );
|
|
|
|
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!
|
|
pSoldier->EVENT_GetNewSoldierPath( sNewGridNo, WALKING );
|
|
|
|
return( TRUE );
|
|
break;
|
|
|
|
case 468:
|
|
|
|
// CODE: End PUNCH
|
|
{
|
|
BOOLEAN fNPCPunch = FALSE;
|
|
|
|
// ATE: Put some code in for NPC punches...
|
|
if ( pSoldier->flags.uiStatusFlags & SOLDIER_NPC_DOING_PUNCH )
|
|
{
|
|
fNPCPunch = TRUE;
|
|
|
|
// Turn off
|
|
pSoldier->flags.uiStatusFlags &= (~SOLDIER_NPC_DOING_PUNCH );
|
|
|
|
// Trigger approach...
|
|
TriggerNPCWithGivenApproach( pSoldier->ubProfile, (UINT8)pSoldier->aiData.uiPendingActionData4, FALSE );
|
|
}
|
|
|
|
|
|
// Are we a martial artist?
|
|
{
|
|
BOOLEAN fMartialArtist = FALSE;
|
|
|
|
if ( pSoldier->ubProfile != NO_PROFILE && pSoldier->ubBodyType == REGMALE ) // SANDRO - added check for body type
|
|
{
|
|
// SANDRO - old/new traits
|
|
if (gGameOptions.fNewTraitSystem)
|
|
{
|
|
if ( NUM_SKILL_TRAITS( pSoldier, MARTIAL_ARTS_NT ) >= ((gSkillTraitValues.fPermitExtraAnimationsOnlyToMA) ? 2 : 1 ) )
|
|
{
|
|
fMartialArtist = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( ProfileHasSkillTrait( pSoldier->ubProfile, MARTIALARTS_OT ) > 0 )
|
|
{
|
|
fMartialArtist = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( gAnimControl[ pSoldier->usAnimState ].ubHeight == ANIM_CROUCH )
|
|
{
|
|
if ( fNPCPunch )
|
|
{
|
|
pSoldier->ChangeSoldierStance( ANIM_STAND );
|
|
return( TRUE );
|
|
}
|
|
else
|
|
{
|
|
pSoldier->ChangeSoldierState( CROUCHING, 0, FALSE );
|
|
return( TRUE );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
#ifdef JA2UB
|
|
//Ja25 No meanwhiles
|
|
if ( fMartialArtist )
|
|
#else
|
|
if ( fMartialArtist && !AreInMeanwhile( ) )
|
|
|
|
#endif
|
|
{
|
|
pSoldier->ChangeSoldierState( NINJA_BREATH, 0, FALSE );
|
|
return( TRUE );
|
|
}
|
|
else
|
|
{
|
|
pSoldier->ChangeSoldierState( PUNCH_BREATH, 0, FALSE );
|
|
return( TRUE );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 469:
|
|
|
|
// CODE: Begin martial artist attack
|
|
pSoldier->DoNinjaAttack( );
|
|
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->flags.uiStatusFlags &= (~SOLDIER_PAUSEANIMOVE);
|
|
break;
|
|
|
|
case 472:
|
|
|
|
{
|
|
INT8 bGoBackToAimAfterHit;
|
|
|
|
// Save old flag, then reset. If we do nothing special here, at least go back
|
|
// to aim if we were.
|
|
bGoBackToAimAfterHit = pSoldier->flags.bGoBackToAimAfterHit;
|
|
pSoldier->flags.bGoBackToAimAfterHit = NO_SPEC_STANCE_AFTER_HIT;
|
|
|
|
// CODE: HANDLE ANY RANDOM HIT VARIATIONS WE WISH TO DO.....
|
|
if ( pSoldier->stats.bLife >= OKLIFE && bGoBackToAimAfterHit)
|
|
{
|
|
if ( bGoBackToAimAfterHit == GO_TO_AIM_AFTER_HIT )
|
|
{
|
|
pSoldier->InternalSoldierReadyWeapon(pSoldier->ubDirection, FALSE, FALSE );
|
|
}
|
|
else if ( bGoBackToAimAfterHit == GO_TO_ALTERNATIVE_AIM_AFTER_HIT && (gAnimControl[ pSoldier->usAnimState ].ubEndHeight == ANIM_STAND) )
|
|
{
|
|
pSoldier->InternalSoldierReadyWeapon(pSoldier->ubDirection, FALSE, TRUE );
|
|
}
|
|
else if ( bGoBackToAimAfterHit == GO_TO_HTH_BREATH_AFTER_HIT && (gAnimControl[ pSoldier->usAnimState ].ubEndHeight == ANIM_STAND))
|
|
{
|
|
if ( Item[ pSoldier->inv[HANDPOS].usItem ].usItemClass & (IC_NONE | IC_PUNCH) )
|
|
{
|
|
if ((((NUM_SKILL_TRAITS( pSoldier, MARTIAL_ARTS_NT ) >= ((gSkillTraitValues.fPermitExtraAnimationsOnlyToMA) ? 2 : 1 )) && gGameOptions.fNewTraitSystem ) ||
|
|
(HAS_SKILL_TRAIT( pSoldier, MARTIALARTS_OT ) && !gGameOptions.fNewTraitSystem ) ) && pSoldier->ubBodyType == REGMALE )
|
|
{
|
|
if(is_networked)
|
|
pSoldier->ChangeSoldierState( NINJA_BREATH, 0 , FALSE );
|
|
else
|
|
pSoldier->EVENT_InitNewSoldierAnim( NINJA_BREATH, 0 , FALSE );
|
|
}
|
|
else
|
|
{
|
|
if(is_networked)
|
|
pSoldier->ChangeSoldierState( PUNCH_BREATH, 0 , FALSE );
|
|
else
|
|
pSoldier->EVENT_InitNewSoldierAnim( PUNCH_BREATH, 0 , FALSE );
|
|
}
|
|
}
|
|
else if ( Item[ pSoldier->inv[HANDPOS].usItem ].usItemClass & (IC_BLADE) )
|
|
{
|
|
if(is_networked)
|
|
pSoldier->ChangeSoldierState( KNIFE_BREATH, 0 , FALSE );
|
|
else
|
|
pSoldier->EVENT_InitNewSoldierAnim( KNIFE_BREATH, 0 , FALSE );
|
|
}
|
|
}
|
|
else if ( bGoBackToAimAfterHit == GO_TO_COWERING_AFTER_HIT )
|
|
{
|
|
if (gAnimControl[ pSoldier->usAnimState ].ubEndHeight == ANIM_CROUCH)
|
|
{
|
|
if(is_networked)
|
|
pSoldier->ChangeSoldierState( START_COWER_CROUCHED, 0 , FALSE );
|
|
else
|
|
pSoldier->EVENT_InitNewSoldierAnim( START_COWER_CROUCHED, 0 , FALSE );
|
|
}
|
|
else if (gAnimControl[ pSoldier->usAnimState ].ubEndHeight == ANIM_PRONE)
|
|
{
|
|
if(is_networked)
|
|
pSoldier->ChangeSoldierState( START_COWER_PRONE, 0 , FALSE );
|
|
else
|
|
pSoldier->EVENT_InitNewSoldierAnim( START_COWER_PRONE, 0 , 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
|
|
pSoldier->ChangeSoldierStance( ANIM_STAND );
|
|
return( TRUE );
|
|
|
|
case 475:
|
|
|
|
// CODE: END CLIMB DOWN ROOF
|
|
pSoldier->ubDesiredHeight = ANIM_STAND;
|
|
pSoldier->pathing.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
|
|
pSoldier->ChangeSoldierState( ( pSoldier->aiData.sPendingActionData2 ), (UINT8)( pSoldier->aiData.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->stats.bLife >= OKLIFE && pSoldier->bBreath > 0 && pSoldier->pathing.bLevel == 0 )
|
|
{
|
|
// Save old direction
|
|
pSoldier->aiData.uiPendingActionData1 = pSoldier->ubDirection;
|
|
|
|
// 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->ubDirection ];
|
|
}
|
|
// 30 % chance to change direction the other way
|
|
else if ( uiChance >= 30 && uiChance < 60 )
|
|
{
|
|
bNewDirection = gOneCCDirection[ pSoldier->ubDirection ];
|
|
}
|
|
// 30 % normal....
|
|
else
|
|
{
|
|
bNewDirection = pSoldier->ubDirection;
|
|
}
|
|
|
|
pSoldier->EVENT_SetSoldierDirection( bNewDirection );
|
|
pSoldier->EVENT_SetSoldierDesiredDirection( pSoldier->ubDirection );
|
|
|
|
}
|
|
else
|
|
{
|
|
// OK, 50% chance here to turn...
|
|
uiChance = Random( 100 );
|
|
|
|
if ( uiChance < 50 )
|
|
{
|
|
// OK, pick a larger direction to goto....
|
|
pSoldier->flags.uiStatusFlags |= SOLDIER_TURNINGFROMHIT;
|
|
// This becomes an attack busy situation
|
|
// 0verhaul: There is an attack busy problem with this. The soldier could be in mid-turn
|
|
// when another bullet is fired (auto-fire or dual-wield, for instance), and the soldier is
|
|
// knocked down in the middle of the turn. In such a case, the attack busy does not get
|
|
// cancelled. So if we indeed need to keep the attack busy (which may not be the case),
|
|
// we will need to find a more reliable method. For now, I'm going to cancel out the
|
|
// ABC adjustment here and we'll see if there needs to be something in its place.
|
|
//gTacticalStatus.ubAttackBusyCount++;
|
|
DebugAttackBusy( String( "Soldier turning from a hit. Not Increasing attack busy. Now %d\n", gTacticalStatus.ubAttackBusyCount ) );
|
|
|
|
// Pick evenly between both
|
|
if ( Random( 50 ) < 25 )
|
|
{
|
|
bNewDirection = gOneCDirection[ pSoldier->ubDirection ];
|
|
bNewDirection = gOneCDirection[ bNewDirection ];
|
|
bNewDirection = gOneCDirection[ bNewDirection ];
|
|
}
|
|
else
|
|
{
|
|
bNewDirection = gOneCCDirection[ pSoldier->ubDirection ];
|
|
bNewDirection = gOneCCDirection[ bNewDirection ];
|
|
bNewDirection = gOneCCDirection[ bNewDirection ];
|
|
}
|
|
|
|
pSoldier->EVENT_SetSoldierDesiredDirection( bNewDirection );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
case 479:
|
|
|
|
// CODE: Return to old direction......
|
|
if ( pSoldier->ubBodyType <= REGFEMALE )
|
|
{
|
|
// Secondly, don't if we are going to collapse
|
|
//if ( pSoldier->stats.bLife >= OKLIFE && pSoldier->bBreath > 0 )
|
|
//{
|
|
/// if ( !( pSoldier->flags.uiStatusFlags & SOLDIER_TURNINGFROMHIT ) )
|
|
// {
|
|
/// pSoldier->ubDirection = (INT8)pSoldier->aiData.uiPendingActionData1;
|
|
// pSoldier->pathing.bDesiredDirection = (INT8)pSoldier->aiData.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->flags.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->aiData.sPendingActionData2 );
|
|
break;
|
|
|
|
case 484:
|
|
|
|
// CODE: HANDLE REMOTE...
|
|
HandleSoldierUseRemote( pSoldier, pSoldier->aiData.sPendingActionData2 );
|
|
break;
|
|
|
|
case 485:
|
|
|
|
// CODE: Try steal.....
|
|
// UnSetUIBusy( pSoldier->ubID);
|
|
UseHandToHand( pSoldier, pSoldier->aiData.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 )
|
|
//new profiles by Jazz
|
|
if (pSoldier->ubProfile != NO_PROFILE && (gProfilesNPC[pSoldier->ubProfile].ProfilId == pSoldier->ubProfile ||
|
|
gProfilesRPC[pSoldier->ubProfile].ProfilId == pSoldier->ubProfile ||
|
|
gProfilesVehicle[pSoldier->ubProfile].ProfilId == pSoldier->ubProfile))
|
|
{
|
|
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
|
|
//pSoldier->ChangeSoldierState( 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 ].exists() == true )
|
|
{
|
|
// CHECK IF GUN
|
|
if ( Item[ pSoldier->inv[ HANDPOS ].usItem ].usItemClass == IC_GUN )
|
|
{
|
|
if ( Weapon[ pSoldier->inv[ HANDPOS ].usItem ].ubWeaponClass != HANDGUNCLASS )
|
|
{
|
|
// RAISE
|
|
pSoldier->ChangeSoldierState( RAISE_RIFLE, 0 , FALSE );
|
|
return( TRUE );
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
*/
|
|
break;
|
|
|
|
case 491:
|
|
// SANDRO - I've been here, messing with stuff...
|
|
|
|
// CODE: HANDLE RANDOM BREATH ANIMATION
|
|
//if ( pSoldier->stats.bLife > INJURED_CHANGE_THREASHOLD )
|
|
if ( pSoldier->stats.bLife >= OKLIFE )
|
|
{
|
|
// Increment time from last update
|
|
pSoldier->uiTimeOfLastRandomAction++;
|
|
|
|
if ( pSoldier->uiTimeOfLastRandomAction > TIME_FOR_RANDOM_ANIM_CHECK || pSoldier->stats.bLife < INJURED_CHANGE_THREASHOLD || GetDrunkLevel( pSoldier ) >= BORDERLINE )
|
|
{
|
|
pSoldier->uiTimeOfLastRandomAction = 0;
|
|
|
|
// Don't play these generally if this is the guy selected by player, as this one is "awaiting orders"
|
|
if (pSoldier->ubID != (UINT8)gusSelectedSoldier || Random( 10 ) == 0 )
|
|
{
|
|
// Don't do any in water!
|
|
// Also don't play if we are in the middle of something
|
|
if ( !pSoldier->MercInWater( ) && !pSoldier->flags.fTurningUntilDone )
|
|
{
|
|
// 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 ( pSoldier->inv[ HANDPOS ].exists() == true )
|
|
{
|
|
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;
|
|
// ubRandomHandIndex = RANDOM_ANIM_NOTHINGORPISTOLINHAND;
|
|
//}
|
|
}
|
|
}
|
|
|
|
// Check which animation to play....
|
|
for ( cnt = 0; cnt < MAX_RANDOM_ANIMS_PER_BODYTYPE; cnt++ )
|
|
{
|
|
pAnimDef = &( gRandomAnimDefs[ pSoldier->ubBodyType ][ cnt ] );
|
|
|
|
if ( pAnimDef->sAnimID != 0 )
|
|
{
|
|
BOOLEAN fStarving = FALSE;
|
|
UINT8 foodsituation;
|
|
UINT8 watersituation;
|
|
GetFoodSituation( pSoldier, &foodsituation, &watersituation );
|
|
if ( foodsituation >= FOOD_VERY_LOW || watersituation >= FOOD_VERY_LOW )
|
|
fStarving = TRUE;
|
|
|
|
// If it's an injured animation and we are not in the threashold....
|
|
if ( ( pAnimDef->ubFlags & RANDOM_ANIM_INJURED ) && pSoldier->stats.bLife >= INJURED_CHANGE_THREASHOLD && pSoldier->bPoisonSum <= 0 && !fStarving )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// If we need to do an injured one, don't do any others...
|
|
if ( !( pAnimDef->ubFlags & RANDOM_ANIM_INJURED ) && (pSoldier->stats.bLife < INJURED_CHANGE_THREASHOLD || pSoldier->bPoisonSum > 0 || fStarving) )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// If it's a drunk animation and we are not in the threashold....
|
|
if ( ( pAnimDef->ubFlags & RANDOM_ANIM_DRUNK ) && GetDrunkLevel( pSoldier ) < BORDERLINE && pSoldier->bPoisonSum <= 0 && !fStarving )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// If we need to do an injured one, don't do any others...
|
|
if ( !( pAnimDef->ubFlags & RANDOM_ANIM_DRUNK ) && (GetDrunkLevel( pSoldier ) >= BORDERLINE || pSoldier->bPoisonSum > 0 || fStarving) )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// Check if it's our hand
|
|
/*if ( pAnimDef->ubHandRestriction != RANDOM_ANIM_IRRELEVENTINHAND && pAnimDef->ubHandRestriction != ubRandomHandIndex )
|
|
{
|
|
continue;
|
|
}*/
|
|
|
|
// Don't do this if a pistol in hand
|
|
if ( ubRandomHandIndex == RANDOM_ANIM_RIFLEINHAND && pAnimDef->sAnimID == BIGGUY_STONE )
|
|
{
|
|
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 it is lookaround animation, don't play it if we see at least one enemy
|
|
if ( pAnimDef->ubFlags & RANDOM_ANIM_LOOKAROUND )
|
|
{
|
|
// enemy on sight, don't pretend we don't see him!
|
|
if ( pSoldier->aiData.bOppCnt > 0 )
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
|
|
// If it is lookaround animation, don't play it if we see at least one enemy
|
|
if ( pAnimDef->ubFlags & RANDOM_ANIM_SHOWOFF )
|
|
{
|
|
// enemy on sight, don't pretend we don't see him!
|
|
if ( pSoldier->ubProfile != NO_PROFILE )
|
|
{
|
|
if ( gMercProfiles[ pSoldier->ubProfile ].bCharacterTrait != CHAR_TRAIT_SHOWOFF && Random( 10 ) < 9 )
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( Random( 10 ) < 7 )
|
|
{
|
|
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 ) )
|
|
if ( ( pAnimDef->ubFlags & RANDOM_ANIM_FIRSTBIGMERC ) && !( DecideAltAnimForBigMerc( pSoldier )) )
|
|
{
|
|
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 ) )
|
|
if ( ( pAnimDef->ubFlags & RANDOM_ANIM_SECONDBIGMERC ) && ( DecideAltAnimForBigMerc( pSoldier )) )
|
|
{
|
|
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( 10 ) == 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 if ( pSoldier->ubBodyType == CROW )
|
|
{
|
|
if ( Random( 4 ) == 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
|
|
{
|
|
if ( pAnimDef->ubHandRestriction != RANDOM_ANIM_IRRELEVENTINHAND && pAnimDef->ubHandRestriction != ubRandomHandIndex )
|
|
{
|
|
// only if we are told to play an anim without rifle and we have a rifle (we can lower it for an instance), not vice versa
|
|
if ( pAnimDef->ubHandRestriction == RANDOM_ANIM_RIFLEINHAND && ubRandomHandIndex != RANDOM_ANIM_RIFLEINHAND )
|
|
{
|
|
continue;
|
|
}
|
|
// this is not for enemy fools, only for cool mercs
|
|
if ( pSoldier->bTeam != gbPlayerNum )
|
|
{
|
|
continue;
|
|
}
|
|
// these funny moves are not likely to be used in combat
|
|
if ( ( gTacticalStatus.uiFlags & INCOMBAT ) )
|
|
{
|
|
if ( pSoldier->aiData.bMorale < 95 ) // .. unless we are really confident about ourselves
|
|
{
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
if ( Random( 2 ) == 1 ) // even if we are, still make them show seldomly
|
|
continue;
|
|
}
|
|
}
|
|
if ( Random( 4 ) == 1 ) // make this rare as we need to lower the weapon -> make the move -> raise the weapon again... rather show off
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
// generally make funny moves less common in combat, we need to focus!
|
|
if ( ( gTacticalStatus.uiFlags & INCOMBAT ) && !( pAnimDef->ubFlags & ( RANDOM_ANIM_INJURED )) && !( pAnimDef->ubFlags & ( RANDOM_ANIM_DRUNK )) && !( pAnimDef->ubFlags & ( RANDOM_ANIM_LOOKAROUND )) )
|
|
{
|
|
if ( Random( 3 ) == 1 )
|
|
continue;
|
|
}
|
|
// finally if we got here, send state change
|
|
pSoldier->ChangeSoldierState( pAnimDef->sAnimID, 0 , FALSE );
|
|
}
|
|
return( TRUE );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 492:
|
|
|
|
|
|
// SIGNAL DODGE!
|
|
// ATE: Only do if we're not inspecial case...
|
|
if ( !( pSoldier->flags.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->aiData.bOppList[ pSoldier->ubID ] != 0 || pTSoldier->bTeam == pSoldier->bTeam )
|
|
{
|
|
if ( gAnimControl[ pTSoldier->usAnimState ].ubHeight == ANIM_STAND )
|
|
{
|
|
// OK, stop merc....
|
|
pTSoldier->EVENT_StopMerc( pTSoldier->sGridNo, pTSoldier->ubDirection );
|
|
|
|
if ( pTSoldier->bTeam != gbPlayerNum )
|
|
{
|
|
CancelAIAction( pTSoldier, TRUE );
|
|
}
|
|
|
|
// SANDRO - Set goback to aim after hit flag
|
|
if (( Item[ pTSoldier->inv[HANDPOS].usItem ].usItemClass & (IC_BLADE | IC_PUNCH | IC_NONE) ) && pTSoldier->stats.bLife > 30 && pTSoldier->bBreath > 25 && (gAnimControl[ pTSoldier->usAnimState ].ubEndHeight == ANIM_STAND) )
|
|
{
|
|
if ( pTSoldier->stats.bLife > 30 && pTSoldier->bBreath > 25 )
|
|
{
|
|
pTSoldier->flags.bGoBackToAimAfterHit = GO_TO_HTH_BREATH_AFTER_HIT;
|
|
}
|
|
}
|
|
// If we were aiming
|
|
// actually no... favor htH a bit more, by making the opponent drop his readied stance when attacked in close combat, regardless he will dodge it or not
|
|
//else if ( gAnimControl[ pTSoldier->usAnimState ].uiFlags & ANIM_FIREREADY )
|
|
//{
|
|
// if ( gAnimControl[ pTSoldier->usAnimState ].uiFlags & ANIM_ALT_WEAPON_HOLDING ) // alternative weapon holding stance
|
|
// pTSoldier->flags.bGoBackToAimAfterHit = GO_TO_ALTERNATIVE_AIM_AFTER_HIT;
|
|
// else // standard
|
|
// pTSoldier->flags.bGoBackToAimAfterHit = GO_TO_AIM_AFTER_HIT;
|
|
//}
|
|
// if we were cowering (this is different from the bellow, we don't use that status flag for this animation)
|
|
else if ( pTSoldier->usAnimState == COWERING )
|
|
{
|
|
pTSoldier->flags.bGoBackToAimAfterHit = GO_TO_COWERING_AFTER_HIT;
|
|
}
|
|
else
|
|
{
|
|
pTSoldier->flags.bGoBackToAimAfterHit = NO_SPEC_STANCE_AFTER_HIT;
|
|
}
|
|
|
|
// Turn towards the person!
|
|
pTSoldier->EVENT_SetSoldierDesiredDirection( GetDirectionFromGridNo( pSoldier->sGridNo, pTSoldier ) );
|
|
|
|
// PLAY SOLDIER'S DODGE ANIMATION
|
|
pTSoldier->ChangeSoldierState( DODGE_ONE, 0 , FALSE );
|
|
|
|
// SANDRO - after dodging melee attack go to apropriate stance
|
|
//if ( (gAnimControl[ pTSoldier->usAnimState ].ubHeight == ANIM_STAND) && pTSoldier->stats.bLife > 30 && pTSoldier->bBreath > 25 && (Item[pTSoldier->inv[HANDPOS].usItem].usItemClass == IC_PUNCH || Item[pTSoldier->inv[HANDPOS].usItem].usItemClass == IC_NONE))
|
|
//{
|
|
// if ((((NUM_SKILL_TRAITS( pTSoldier, MARTIAL_ARTS_NT ) >= ((gSkillTraitValues.fPermitExtraAnimationsOnlyToMA) ? 2 : 1 )) && gGameOptions.fNewTraitSystem ) ||
|
|
// (HAS_SKILL_TRAIT( pTSoldier, MARTIALARTS_OT ) && !gGameOptions.fNewTraitSystem ) ) &&
|
|
// pTSoldier->ubBodyType == REGMALE )
|
|
// {
|
|
// //pTSoldier->usPendingAnimation = NINJA_GOTOBREATH;
|
|
// pTSoldier->usPendingAnimation = NINJA_BREATH ;
|
|
// }
|
|
// else
|
|
// {
|
|
// pTSoldier->usPendingAnimation = PUNCH_BREATH ;
|
|
// }
|
|
//}
|
|
//else if ( (gAnimControl[ pTSoldier->usAnimState ].ubHeight == ANIM_STAND) && pTSoldier->stats.bLife > 30 && pTSoldier->bBreath > 25 && (Item[pTSoldier->inv[HANDPOS].usItem].usItemClass == IC_BLADE))
|
|
//{
|
|
// //pTSoldier->usPendingAnimation = KNIFE_GOTOBREATH;
|
|
// pTSoldier->usPendingAnimation = KNIFE_BREATH ;
|
|
//}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 493:
|
|
|
|
//CODE: PICKUP ITEM!
|
|
// CHECK IF THIS EVENT HAS BEEN SETUP
|
|
//if ( pSoldier->aiData.ubPendingAction == MERC_PICKUPITEM )
|
|
//{
|
|
// DROP ITEM
|
|
HandleSoldierPickupItem( pSoldier, pSoldier->aiData.uiPendingActionData1, pSoldier->aiData.uiPendingActionData4, pSoldier->aiData.bPendingActionData3 );
|
|
// EVENT HAS BEEN HANDLED
|
|
pSoldier->aiData.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->aiData.ubPendingAction == MERC_OPENSTRUCT )
|
|
//{
|
|
SoldierHandleInteractiveObject( pSoldier );
|
|
|
|
// EVENT HAS BEEN HANDLED
|
|
pSoldier->aiData.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->aiData.bAction == AI_ACTION_UNLOCK_DOOR || (pSoldier->aiData.bAction == AI_ACTION_LOCK_DOOR && !(pSoldier->aiData.fAIFlags & AI_LOCK_DOOR_INCLUDES_CLOSE) ) )
|
|
{
|
|
// EVENT HAS BEEN HANDLED
|
|
pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION;
|
|
|
|
// do nothing here
|
|
}
|
|
else
|
|
{
|
|
|
|
pSoldier->aiData.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->pathing.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->aiData.ubPendingAction = NO_PENDING_ACTION;
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
case 496:
|
|
// CODE: GOTO PREVIOUS ANIMATION
|
|
pSoldier->ChangeSoldierState( 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->stats.bLife == 0 )
|
|
{
|
|
|
|
//HandleSoldierDeath( pSoldier );
|
|
|
|
// If guy is now dead, and we have not played death sound before, play
|
|
if ( pSoldier->stats.bLife == 0 && !pSoldier->flags.fDeadSoundPlayed )
|
|
{
|
|
if ( pSoldier->usAnimState != JFK_HITDEATH )
|
|
{
|
|
pSoldier->DoMercBattleSound( BATTLE_SOUND_DIE1 );
|
|
pSoldier->flags.fDeadSoundPlayed = TRUE;
|
|
}
|
|
}
|
|
|
|
if ( gGameSettings.fOptions[ TOPTION_BLOOD_N_GORE ] )
|
|
{
|
|
// If we are dead, play some death animations!!
|
|
switch( pSoldier->usAnimState )
|
|
{
|
|
case FLYBACK_HIT:
|
|
pSoldier->ChangeSoldierState( FLYBACK_HIT_DEATH, 0, FALSE );
|
|
break;
|
|
|
|
case GENERIC_HIT_DEATHTWITCHNB:
|
|
case FALLFORWARD_FROMHIT_STAND:
|
|
case ENDFALLFORWARD_FROMHIT_CROUCH:
|
|
|
|
pSoldier->ChangeSoldierState( GENERIC_HIT_DEATH, 0, FALSE );
|
|
break;
|
|
|
|
case FALLBACK_HIT_DEATHTWITCHNB:
|
|
case FALLBACK_HIT_STAND:
|
|
pSoldier->ChangeSoldierState( FALLBACK_HIT_DEATH, 0, FALSE );
|
|
break;
|
|
|
|
case PRONE_HIT_DEATHTWITCHNB:
|
|
case PRONE_LAY_FROMHIT:
|
|
|
|
pSoldier->ChangeSoldierState( PRONE_HIT_DEATH, 0, FALSE );
|
|
break;
|
|
|
|
case FALLOFF:
|
|
pSoldier->ChangeSoldierState( FALLOFF_DEATH, 0, FALSE );
|
|
break;
|
|
|
|
case FALLFORWARD_ROOF:
|
|
pSoldier->ChangeSoldierState( FALLOFF_FORWARD_DEATH, 0, FALSE);
|
|
break;
|
|
|
|
case ADULTMONSTER_DYING:
|
|
pSoldier->ChangeSoldierState( ADULTMONSTER_DYING_STOP, 0, FALSE);
|
|
break;
|
|
|
|
case LARVAE_DIE:
|
|
pSoldier->ChangeSoldierState( LARVAE_DIE_STOP, 0, FALSE);
|
|
break;
|
|
|
|
case QUEEN_DIE:
|
|
pSoldier->ChangeSoldierState( QUEEN_DIE_STOP, 0, FALSE);
|
|
break;
|
|
|
|
case INFANT_DIE:
|
|
pSoldier->ChangeSoldierState( INFANT_DIE_STOP, 0, FALSE);
|
|
break;
|
|
|
|
case CRIPPLE_DIE:
|
|
pSoldier->ChangeSoldierState( CRIPPLE_DIE_STOP, 0, FALSE);
|
|
break;
|
|
|
|
case ROBOTNW_DIE:
|
|
pSoldier->ChangeSoldierState( ROBOTNW_DIE_STOP, 0, FALSE);
|
|
break;
|
|
|
|
case CRIPPLE_DIE_FLYBACK:
|
|
pSoldier->ChangeSoldierState( 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->flags.fGettingHit = FALSE;
|
|
}
|
|
|
|
HandleCheckForDeathCommonCode( pSoldier );
|
|
|
|
return( TRUE );
|
|
}
|
|
break;
|
|
|
|
case 498:
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// SANDRO - if pending interrupt flag was set for before-attack type of interupt, try to resolve it now
|
|
if ( gGameOptions.fImprovedInterruptSystem )
|
|
{
|
|
if ( ResolvePendingInterrupt( pSoldier, BEFORESHOT_INTERRUPT ) )
|
|
{
|
|
if ( pSoldier->flags.fTurningToShoot )
|
|
pSoldier->flags.fTurningToShoot = FALSE;
|
|
|
|
pSoldier->usPendingAnimation = NO_PENDING_ANIMATION;
|
|
pSoldier->ubPendingDirection = NO_PENDING_DIRECTION;
|
|
// "artificially" set lock ui flag in this case
|
|
if (pSoldier->bTeam == gbPlayerNum)
|
|
{
|
|
//AddTopMessage( COMPUTER_INTERRUPT_MESSAGE, Message[STR_INTERRUPT] );
|
|
guiPendingOverrideEvent = LU_BEGINUILOCK;
|
|
HandleTacticalUI( );
|
|
}
|
|
return( TRUE );
|
|
break;
|
|
}
|
|
}
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// CONDITONAL JUMP
|
|
// If we have a pending animation, play it, else continue
|
|
if ( pSoldier->usPendingAnimation != NO_PENDING_ANIMATION )
|
|
{
|
|
pSoldier->ChangeSoldierState( pSoldier->usPendingAnimation, 0, FALSE );
|
|
pSoldier->usPendingAnimation = NO_PENDING_ANIMATION;
|
|
return( TRUE );
|
|
}
|
|
break;
|
|
|
|
// JUMP TO NEXT STATIONARY ANIMATION ACCORDING TO HEIGHT
|
|
case 499:
|
|
|
|
if (!(pSoldier->flags.uiStatusFlags & SOLDIER_PC))
|
|
{
|
|
if ( pSoldier->aiData.bAction == AI_ACTION_PULL_TRIGGER )
|
|
{
|
|
if ( pSoldier->usAnimState == AI_PULL_SWITCH && gTacticalStatus.ubAttackBusyCount == 0 && gubElementsOnExplosionQueue == 0 )
|
|
{
|
|
FreeUpNPCFromPendingAction( pSoldier );
|
|
}
|
|
}
|
|
else if ( pSoldier->aiData.bAction == AI_ACTION_PENDING_ACTION
|
|
|| pSoldier->aiData.bAction == AI_ACTION_OPEN_OR_CLOSE_DOOR
|
|
|| pSoldier->aiData.bAction == AI_ACTION_YELLOW_ALERT
|
|
|| pSoldier->aiData.bAction == AI_ACTION_RED_ALERT
|
|
|| pSoldier->aiData.bAction == AI_ACTION_PULL_TRIGGER
|
|
|| pSoldier->aiData.bAction == AI_ACTION_CREATURE_CALL
|
|
|| pSoldier->aiData.bAction == AI_ACTION_UNLOCK_DOOR
|
|
|| pSoldier->aiData.bAction == AI_ACTION_LOCK_DOOR )
|
|
{
|
|
if ( pSoldier->usAnimState == PICKUP_ITEM || pSoldier->usAnimState == ADJACENT_GET_ITEM || pSoldier->usAnimState == ADJACENT_GET_ITEM_CROUCHED || 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->flags.fContinueMoveAfterStanceChange )
|
|
{
|
|
usUIMovementMode = pSoldier->GetMoveStateBasedOnStance( 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;
|
|
}
|
|
}
|
|
|
|
if (pSoldier->usAnimState == DODGE_ONE && pSoldier->usPendingAnimation == NO_PENDING_ANIMATION )
|
|
{
|
|
INT8 bGoBackToAimAfterHit = pSoldier->flags.bGoBackToAimAfterHit;
|
|
pSoldier->flags.bGoBackToAimAfterHit = NO_SPEC_STANCE_AFTER_HIT;
|
|
|
|
// CODE: HANDLE ANY RANDOM HIT VARIATIONS WE WISH TO DO.....
|
|
if ( pSoldier->stats.bLife >= OKLIFE && bGoBackToAimAfterHit )
|
|
{
|
|
if ( bGoBackToAimAfterHit == GO_TO_AIM_AFTER_HIT )
|
|
{
|
|
pSoldier->InternalSoldierReadyWeapon(pSoldier->ubDirection, FALSE, FALSE );
|
|
}
|
|
else if ( bGoBackToAimAfterHit == GO_TO_ALTERNATIVE_AIM_AFTER_HIT && (gAnimControl[ pSoldier->usAnimState ].ubEndHeight == ANIM_STAND) )
|
|
{
|
|
pSoldier->InternalSoldierReadyWeapon(pSoldier->ubDirection, FALSE, TRUE );
|
|
}
|
|
else if ( bGoBackToAimAfterHit == GO_TO_HTH_BREATH_AFTER_HIT && (gAnimControl[ pSoldier->usAnimState ].ubEndHeight == ANIM_STAND))
|
|
{
|
|
if ( Item[ pSoldier->inv[HANDPOS].usItem ].usItemClass & (IC_NONE | IC_PUNCH) )
|
|
{
|
|
if ((((NUM_SKILL_TRAITS( pSoldier, MARTIAL_ARTS_NT ) >= ((gSkillTraitValues.fPermitExtraAnimationsOnlyToMA) ? 2 : 1 )) && gGameOptions.fNewTraitSystem ) ||
|
|
(HAS_SKILL_TRAIT( pSoldier, MARTIALARTS_OT ) && !gGameOptions.fNewTraitSystem ) ) && pSoldier->ubBodyType == REGMALE )
|
|
{
|
|
if(is_networked)
|
|
pSoldier->ChangeSoldierState( NINJA_BREATH, 0 , FALSE );
|
|
else
|
|
pSoldier->EVENT_InitNewSoldierAnim( NINJA_BREATH, 0 , FALSE );
|
|
}
|
|
else
|
|
{
|
|
if(is_networked)
|
|
pSoldier->ChangeSoldierState( PUNCH_BREATH, 0 , FALSE );
|
|
else
|
|
pSoldier->EVENT_InitNewSoldierAnim( PUNCH_BREATH, 0 , FALSE );
|
|
}
|
|
}
|
|
else if ( Item[ pSoldier->inv[HANDPOS].usItem ].usItemClass & (IC_BLADE) )
|
|
{
|
|
if(is_networked)
|
|
pSoldier->ChangeSoldierState( KNIFE_BREATH, 0 , FALSE );
|
|
else
|
|
pSoldier->EVENT_InitNewSoldierAnim( KNIFE_BREATH, 0 , FALSE );
|
|
}
|
|
}
|
|
else if ( bGoBackToAimAfterHit == GO_TO_COWERING_AFTER_HIT )
|
|
{
|
|
if (gAnimControl[ pSoldier->usAnimState ].ubEndHeight == ANIM_CROUCH)
|
|
{
|
|
if(is_networked)
|
|
pSoldier->ChangeSoldierState( START_COWER_CROUCHED, 0 , FALSE );
|
|
else
|
|
pSoldier->EVENT_InitNewSoldierAnim( START_COWER_CROUCHED, 0 , FALSE );
|
|
}
|
|
else if (gAnimControl[ pSoldier->usAnimState ].ubEndHeight == ANIM_PRONE)
|
|
{
|
|
if(is_networked)
|
|
pSoldier->ChangeSoldierState( START_COWER_PRONE, 0 , FALSE );
|
|
else
|
|
pSoldier->EVENT_InitNewSoldierAnim( START_COWER_PRONE, 0 , FALSE );
|
|
}
|
|
}
|
|
return( TRUE );
|
|
}
|
|
}
|
|
|
|
pSoldier->ubDesiredHeight = NO_DESIRED_HEIGHT;
|
|
|
|
// 0verhaul: This is moved to the animation state transition code to make sure it isn't sidestepped.
|
|
// if (pSoldier->flags.fChangingStanceDueToSuppression)
|
|
// {
|
|
// pSoldier->flags.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->flags.bTurningFromPronePosition != TURNING_FROM_PRONE_ENDING_UP_FROM_MOVE ) &&
|
|
( pSoldier->flags.bTurningFromPronePosition != TURNING_FROM_PRONE_ON ) )
|
|
{
|
|
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->flags.bTurningFromPronePosition != TURNING_FROM_PRONE_ENDING_UP_FROM_MOVE &&
|
|
pSoldier->flags.bTurningFromPronePosition != TURNING_FROM_PRONE_ON )
|
|
{
|
|
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?
|
|
// 0verhaul: Added additional check: Are we told to stop at this point, maybe due to being interrupted?
|
|
if ( !pSoldier->flags.fNoAPToFinishMove &&
|
|
(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..
|
|
pSoldier->EVENT_GetNewSoldierPath( pSoldier->pathing.sFinalDestination, pSoldier->usUIMovementMode );
|
|
|
|
if ( !( gAnimControl[ pSoldier->usAnimState ].uiFlags & ( ANIM_MOVING ) ) )
|
|
{
|
|
if (!TileIsOutOfBounds(pSoldier->sAbsoluteFinalDestination))
|
|
{
|
|
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;
|
|
pSoldier->ChangeSoldierState( usPendingAnimation, 0, FALSE );
|
|
return( TRUE );
|
|
}
|
|
|
|
// Alrighty, do we wish to continue
|
|
if ( pSoldier->flags.fContinueMoveAfterStanceChange )
|
|
{
|
|
// OK, if the code is == 2, get the path and try to move....
|
|
if ( pSoldier->flags.fContinueMoveAfterStanceChange == 2 )
|
|
{
|
|
pSoldier->pathing.usPathIndex++;
|
|
|
|
if ( pSoldier->pathing.usPathIndex > pSoldier->pathing.usPathDataSize )
|
|
{
|
|
pSoldier->pathing.usPathIndex = pSoldier->pathing.usPathDataSize;
|
|
}
|
|
|
|
if ( pSoldier->pathing.usPathIndex == pSoldier->pathing.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->pathing.sFinalDestination)
|
|
{
|
|
if ( !pSoldier->EVENT_InternalGetNewSoldierPath( pSoldier->pathing.sFinalDestination, pSoldier->usUIMovementMode, 2, FALSE ) )
|
|
{
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pSoldier->EVENT_InitNewSoldierAnim( pSoldier->usUIMovementMode, 0 , FALSE );
|
|
|
|
// UNSET LOCK PENDING ACTION COUNTER FLAG
|
|
pSoldier->flags.uiStatusFlags &= ( ~SOLDIER_LOCKPENDINGACTIONCOUNTER );
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SelectMoveAnimationFromStance( pSoldier );
|
|
}
|
|
|
|
pSoldier->flags.fContinueMoveAfterStanceChange = FALSE;
|
|
return( TRUE );
|
|
}
|
|
pSoldier->SoldierGotoStationaryStance( );
|
|
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
|
|
pSoldier->ChangeSoldierState( KNEEL_UP, 0 , FALSE );
|
|
return( TRUE );
|
|
}
|
|
if ( ubDesiredHeight == ANIM_CROUCH && ubCurrentHeight == ANIM_STAND )
|
|
{
|
|
// Return here because if now, we will skipp a few frames
|
|
pSoldier->ChangeSoldierState( 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
|
|
pSoldier->ChangeSoldierState( 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
|
|
pSoldier->ChangeSoldierState( 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
|
|
|
|
pSoldier->SoldierGotoStationaryStance( );
|
|
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 )
|
|
{
|
|
// SANDRO - added some hacking in here, so I don't need to overwrite all those animation frame scripts
|
|
switch(pSoldier->usAnimState)
|
|
{
|
|
// go to apropriate stance for alternative weapon holding
|
|
case READY_ALTERNATIVE_STAND:
|
|
case SHOOT_ALTERNATIVE_STAND:
|
|
case BURST_ALTERNATIVE_STAND:
|
|
case LOW_SHOT_ALTERNATIVE_STAND:
|
|
case LOW_BURST_ALTERNATIVE_STAND:
|
|
pSoldier->EVENT_InitNewSoldierAnim( AIM_ALTERNATIVE_STAND, 0 , FALSE );
|
|
return( TRUE );
|
|
break;
|
|
// hack to raise rifle after using idle animation without one in hand
|
|
case REG_SQUISH:
|
|
case REG_PULL:
|
|
case BIGBUY_FLEX:
|
|
case BIGBUY_STRECH:
|
|
case FEM_KICKSN:
|
|
case FEM_WIPE:
|
|
if ( pSoldier->inv[ HANDPOS ].exists() == true && Item[ pSoldier->inv[ HANDPOS ].usItem ].usItemClass == IC_GUN && Item[ pSoldier->inv[ HANDPOS ].usItem ].twohanded )
|
|
{
|
|
pSoldier->EVENT_InitNewSoldierAnim( RAISE_RIFLE, 0 , FALSE );
|
|
return( TRUE );
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
// Jump, to animation script
|
|
pSoldier->EVENT_InitNewSoldierAnim( (UINT16)(sNewAniFrame - 600 ), 0 , FALSE );
|
|
return( TRUE );
|
|
}
|
|
else if ( sNewAniFrame > 799 && sNewAniFrame <= 899 )
|
|
{
|
|
// Jump, to animation script ( But in the 100's range )
|
|
pSoldier->EVENT_InitNewSoldierAnim( (UINT16)(sNewAniFrame - 700 ), 0 , FALSE );
|
|
return( TRUE );
|
|
}
|
|
else if ( sNewAniFrame > 899 && sNewAniFrame <= 999 )
|
|
{
|
|
// Jump, to animation script ( But in the 200's range )
|
|
pSoldier->EVENT_InitNewSoldierAnim( (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;
|
|
|
|
OBJECTTYPE* pObjUsed = pSoldier->GetUsedWeapon( &pSoldier->inv[ HANDPOS ] );
|
|
UINT16 usItemUsemUsed = pSoldier->GetUsedWeaponNumber( &pSoldier->inv[ HANDPOS ] );
|
|
|
|
if ( pObjUsed->exists() == true )
|
|
{
|
|
usSoundID = Weapon[ usItemUsemUsed ].sLocknLoadSound;
|
|
|
|
if ( usSoundID != 0 )
|
|
{
|
|
PlayJA2Sample( usSoundID, RATE_11025, SoundVolume( HIGHVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ) );
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 709:
|
|
|
|
// Knife throw sound...
|
|
// anv: possiblity to use custom sounds for throwing knives
|
|
{
|
|
UINT16 usedWeapon = pSoldier->GetUsedWeaponNumber( &pSoldier->inv[ pSoldier->ubAttackingHand ] );
|
|
if ( Weapon[ usedWeapon ].sSound != 0 )
|
|
{
|
|
PlayJA2Sample( Weapon[ usedWeapon ].sSound, 44100-Random(5000)-Random(5000)-Random(5000), SoundVolume( HIGHVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ) );
|
|
}
|
|
else
|
|
{
|
|
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->aiData.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
|
|
// anv: possiblity to use custom sounds for melee weapons
|
|
{
|
|
UINT16 usedWeapon = pSoldier->GetUsedWeaponNumber( &pSoldier->inv[ pSoldier->ubAttackingHand ] );
|
|
if ( Weapon[ usedWeapon ].sSound != 0 )
|
|
{
|
|
PlayJA2Sample( Weapon[ usedWeapon ].sSound, 44100-Random(5000)-Random(5000)-Random(5000), SoundVolume( HIGHVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ) );
|
|
}
|
|
else
|
|
{
|
|
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
|
|
pSoldier->DoMercBattleSound( BATTLE_SOUND_DIE1 );
|
|
pSoldier->flags.fDeadSoundPlayed = TRUE;
|
|
break;
|
|
|
|
case 750:
|
|
|
|
// CODE: Move Vehicle UP
|
|
if ( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE )
|
|
{
|
|
// pSoldier->SetSoldierHeight( (FLOAT)( pSoldier->sHeightAdjustment + 1 ) );
|
|
}
|
|
break;
|
|
|
|
case 751:
|
|
|
|
// CODE: Move vehicle down
|
|
if ( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE )
|
|
{
|
|
// pSoldier->SetSoldierHeight( (FLOAT)( pSoldier->sHeightAdjustment - 1 ) );
|
|
}
|
|
break;
|
|
|
|
case 752:
|
|
|
|
// Code: decapitate
|
|
//DecapitateCorpse( pSoldier, pSoldier->sTargetGridNo, pSoldier->bTargetLevel );
|
|
|
|
// Flugente: instead of jsut decapitating, we call a selection window where we can choose what to do with the corpse
|
|
HandleSoldierUseCorpse( pSoldier, pSoldier->sTargetGridNo, pSoldier->bTargetLevel ); // Flugente: handle corpses
|
|
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 );
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// SANDRO - if pending interrupt flag was set for after-attack type of interupt, try to resolve it now
|
|
if ( gGameOptions.fImprovedInterruptSystem )
|
|
{
|
|
ResolvePendingInterrupt( pSoldier, AFTERACTION_INTERRUPT );
|
|
}
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
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->aiData.sPendingActionData2, pSoldier->pathing.bLevel );
|
|
|
|
if ( ubPerson != NOBODY && MercPtrs[ ubPerson ]->flags.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->exists() == true )
|
|
{
|
|
// Add to inv..
|
|
AutoPlaceObject( pSoldier, pSoldier->pTempObject, TRUE );
|
|
}
|
|
|
|
OBJECTTYPE::DeleteMe( &pSoldier->pTempObject );
|
|
}
|
|
}
|
|
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 )
|
|
{
|
|
pTarget->EVENT_InitNewSoldierAnim( 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!
|
|
MercPtrs[ pSoldier->aiData.uiPendingActionData4 ]->EVENT_SoldierGotHit( TAKE_DAMAGE_BLADE, (INT16) 25, (INT16) 25, gOppositeDirection[ pSoldier->ubDirection ], 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->flags.bHasKeys = pSoldier->flags.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->aiData.sPendingActionData2, pSoldier->pTempObject, 1, pSoldier->pathing.bLevel, 0 , -1 );
|
|
NotifySoldiersToLookforItems( );
|
|
|
|
OBJECTTYPE::DeleteMe( &pSoldier->pTempObject );
|
|
}
|
|
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...
|
|
{
|
|
INT32 sNewGridNo;
|
|
|
|
InternalDropBlood( pSoldier->sGridNo, pSoldier->pathing.bLevel, 0, (UINT8)(MAXBLOODQUANTITY), 1 );
|
|
|
|
// Move forward one gridno....
|
|
sNewGridNo = NewGridNo( pSoldier->sGridNo, DirectionInc( gOppositeDirection[ pSoldier->ubDirection ] ) );
|
|
|
|
InternalDropBlood( sNewGridNo, pSoldier->pathing.bLevel, 0, (UINT8)(MAXBLOODQUANTITY), 1 );
|
|
|
|
}
|
|
break;
|
|
|
|
case 766:
|
|
|
|
// Say COOL quote
|
|
pSoldier->DoMercBattleSound( 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...
|
|
pSoldier->ChangeSoldierStance( 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->aiData.sPendingActionData2, pSoldier->pathing.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->flags.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;
|
|
|
|
case 792:
|
|
|
|
|
|
break;
|
|
}
|
|
// Adjust frame control pos, and try again
|
|
pSoldier->usAniCode++;
|
|
}
|
|
else if ( sNewAniFrame == 999 )
|
|
{
|
|
|
|
// Go to start, by default
|
|
pSoldier->usAniCode = 0;
|
|
|
|
}
|
|
else if ( sNewAniFrame > 999 && sNewAniFrame <= 1099 )
|
|
{
|
|
// Jump, to animation script ( in the 300+ range )
|
|
pSoldier->EVENT_InitNewSoldierAnim( (UINT16)(sNewAniFrame - 700 ), 0 , FALSE );
|
|
return( TRUE );
|
|
}
|
|
else if ( sNewAniFrame > 1099 )
|
|
{
|
|
switch( sNewAniFrame )
|
|
{
|
|
|
|
case 1101:
|
|
// SANDRO - dual burst check for repeating animation
|
|
{
|
|
OBJECTTYPE* pObjHand = pSoldier->GetUsedWeapon( &pSoldier->inv[pSoldier->ubAttackingHand] );
|
|
|
|
if (pSoldier->bDoBurst && ( pSoldier->bDoBurst <= ( (pSoldier->bDoAutofire)?(2*pSoldier->bDoAutofire):(2*GetShotsPerBurst( pObjHand )) ) ))
|
|
{
|
|
if ( pSoldier->usAnimState == BURST_DUAL_PRONE )
|
|
pSoldier->usAniCode = 2;
|
|
else
|
|
pSoldier->usAniCode = 1;
|
|
}
|
|
else
|
|
{
|
|
pSoldier->usAniCode++;
|
|
}
|
|
break;
|
|
}
|
|
case 1102:
|
|
// SANDRO - end dual burst check for going to proper aim state
|
|
|
|
switch ( gAnimControl[ pSoldier->usAnimState ].ubEndHeight )
|
|
{
|
|
case ANIM_STAND:
|
|
pSoldier->EVENT_InitNewSoldierAnim( AIM_DUAL_STAND, 0 , FALSE );
|
|
break;
|
|
case ANIM_CROUCH:
|
|
pSoldier->EVENT_InitNewSoldierAnim( AIM_DUAL_CROUCH, 0 , FALSE );
|
|
break;
|
|
case ANIM_PRONE:
|
|
pSoldier->EVENT_InitNewSoldierAnim( AIM_DUAL_PRONE, 0 , FALSE );
|
|
break;
|
|
}
|
|
return( TRUE );
|
|
break;
|
|
}
|
|
}
|
|
|
|
// 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[ pSoldier->ubProfile ].QuoteExpGotGunOrUsedGun == 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, INT32 sGridNo, INT8 bLevel )
|
|
{
|
|
// WDS - make number of mercenaries, etc. be configurable
|
|
std::vector<UINT8> ubMercsInSector (CODE_MAXIMUM_NUMBER_OF_PLAYER_SLOTS, 0);
|
|
// UINT8 ubMercsInSector[ CODE_MAXIMUM_NUMBER_OF_PLAYER_SLOTS ] = { 0 };
|
|
std::vector<INT8> bBuddyIndex (CODE_MAXIMUM_NUMBER_OF_PLAYER_SLOTS, -1);
|
|
// INT8 bBuddyIndex[ CODE_MAXIMUM_NUMBER_OF_PLAYER_SLOTS ] = { -1 };
|
|
INT8 bTempBuddyIndex;
|
|
UINT8 ubNumMercs = 0;
|
|
UINT8 ubChosenMerc;
|
|
SOLDIERTYPE *pTeamSoldier;
|
|
INT32 cnt;
|
|
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->flags.uiStatusFlags & SOLDIER_GASSED ) && !(AM_A_ROBOT( pTeamSoldier )) && !pTeamSoldier->flags.fMercAsleep && !TileIsOutOfBounds(pTeamSoldier->sGridNo))
|
|
{
|
|
// 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;
|
|
|
|
case 3:
|
|
if ( pTeamSoldier->usQuoteSaidExtFlags & SOLDIER_QUOTE_SAID_BUDDY_4_WITNESSED )
|
|
{
|
|
continue;
|
|
}
|
|
break;
|
|
|
|
case 4:
|
|
if ( pTeamSoldier->usQuoteSaidExtFlags & SOLDIER_QUOTE_SAID_BUDDY_5_WITNESSED )
|
|
{
|
|
continue;
|
|
}
|
|
break;
|
|
|
|
case 5:
|
|
if ( pTeamSoldier->usQuoteSaidExtFlags & SOLDIER_QUOTE_SAID_BUDDY_6_WITNESSED )
|
|
{
|
|
continue;
|
|
}
|
|
break;
|
|
}
|
|
|
|
// TO LOS check to killed
|
|
// Can we see location of killer?
|
|
if ( SoldierTo3DLocationLineOfSightTest( pTeamSoldier, pKillerSoldier->sGridNo, pKillerSoldier->pathing.bLevel, 3, TRUE, CALC_FROM_ALL_DIRS ) == 0 )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
|
|
// Can we see location of killed?
|
|
if ( SoldierTo3DLocationLineOfSightTest( pTeamSoldier, sGridNo, bLevel, 3, TRUE, CALC_FROM_ALL_DIRS ) == 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:
|
|
if( MercPtrs[ ubMercsInSector[ ubChosenMerc ] ]->ubWhatKindOfMercAmI == MERC_TYPE__AIM_MERC )
|
|
usQuoteNum = QUOTE_AIM_BUDDY_3_GOOD;
|
|
else
|
|
usQuoteNum = QUOTE_NON_AIM_BUDDY_3_GOOD;
|
|
MercPtrs[ ubMercsInSector[ ubChosenMerc ] ]->usQuoteSaidExtFlags |= SOLDIER_QUOTE_SAID_BUDDY_3_WITNESSED;
|
|
break;
|
|
|
|
case 3:
|
|
if( MercPtrs[ ubMercsInSector[ ubChosenMerc ] ]->ubWhatKindOfMercAmI == MERC_TYPE__AIM_MERC )
|
|
usQuoteNum = QUOTE_AIM_BUDDY_4_GOOD;
|
|
else
|
|
usQuoteNum = QUOTE_NON_AIM_BUDDY_4_GOOD;
|
|
MercPtrs[ ubMercsInSector[ ubChosenMerc ] ]->usQuoteSaidExtFlags |= SOLDIER_QUOTE_SAID_BUDDY_4_WITNESSED;
|
|
break;
|
|
|
|
case 4:
|
|
if( MercPtrs[ ubMercsInSector[ ubChosenMerc ] ]->ubWhatKindOfMercAmI == MERC_TYPE__AIM_MERC )
|
|
usQuoteNum = QUOTE_AIM_BUDDY_5_GOOD;
|
|
else
|
|
usQuoteNum = QUOTE_NON_AIM_BUDDY_5_GOOD;
|
|
MercPtrs[ ubMercsInSector[ ubChosenMerc ] ]->usQuoteSaidExtFlags |= SOLDIER_QUOTE_SAID_BUDDY_5_WITNESSED;
|
|
break;
|
|
|
|
case 5:
|
|
usQuoteNum = QUOTE_LEARNED_TO_LIKE_WITNESSED;
|
|
MercPtrs[ ubMercsInSector[ ubChosenMerc ] ]->usQuoteSaidExtFlags |= SOLDIER_QUOTE_SAID_BUDDY_6_WITNESSED;
|
|
break;
|
|
}
|
|
TacticalCharacterDialogue( MercPtrs[ ubMercsInSector[ ubChosenMerc ] ], usQuoteNum );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void HandleKilledQuote( SOLDIERTYPE *pKilledSoldier, SOLDIERTYPE *pKillerSoldier, INT32 sGridNo, INT8 bLevel )
|
|
{
|
|
SOLDIERTYPE *pTeamSoldier;
|
|
INT32 cnt;
|
|
// WDS - make number of mercenaries, etc. be configurable
|
|
std::vector<UINT8> ubMercsInSector (CODE_MAXIMUM_NUMBER_OF_PLAYER_SLOTS, 0);
|
|
// UINT8 ubMercsInSector[ CODE_MAXIMUM_NUMBER_OF_PLAYER_SLOTS ] = { 0 };
|
|
UINT8 ubNumMercs = 0;
|
|
UINT8 ubChosenMerc;
|
|
BOOLEAN fDoSomeoneElse = FALSE;
|
|
|
|
gfLastMercTalkedAboutKillingID = pKilledSoldier->ubID;
|
|
|
|
// Can we see location?
|
|
BOOLEAN fCanWeSeeLocation = ( SoldierTo3DLocationLineOfSightTest( pKillerSoldier, sGridNo, bLevel, 3, TRUE, CALC_FROM_ALL_DIRS ) != 0 );
|
|
|
|
// Are we killing mike?
|
|
if ( pKilledSoldier->ubProfile == MIKE && ( pKillerSoldier->ubWhatKindOfMercAmI == MERC_TYPE__AIM_MERC || ( pKillerSoldier->ubWhatKindOfMercAmI == MERC_TYPE__MERC && gMercProfiles[pKillerSoldier->ubProfile].bLearnToHate == 255 ) ) )
|
|
{
|
|
// Can we see?
|
|
if ( fCanWeSeeLocation )
|
|
{
|
|
TacticalCharacterDialogue( pKillerSoldier, QUOTE_AIM_KILLED_MIKE );
|
|
}
|
|
}
|
|
// Are we killing factory mamager?
|
|
else if ( pKilledSoldier->ubProfile == DOREEN )
|
|
{
|
|
// 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->flags.uiStatusFlags & SOLDIER_GASSED ) && !AM_AN_EPC( pTeamSoldier ) )
|
|
{
|
|
// Can we see location?
|
|
if ( SoldierTo3DLocationLineOfSightTest( pTeamSoldier, sGridNo, bLevel, 3, TRUE, CALC_FROM_ALL_DIRS ) )
|
|
{
|
|
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->flags.uiStatusFlags & SOLDIER_MONSTER )
|
|
{
|
|
TacticalCharacterDialogue( pKillerSoldier, QUOTE_KILLED_A_CREATURE );
|
|
}
|
|
else
|
|
{
|
|
TacticalCharacterDialogue( pKillerSoldier, QUOTE_KILLED_AN_ENEMY );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( Random( 50 ) == 25 )
|
|
{
|
|
pKillerSoldier->DoMercBattleSound( (INT8)( BATTLE_SOUND_LAUGH1 ) );
|
|
}
|
|
else
|
|
{
|
|
pKillerSoldier->DoMercBattleSound( (INT8)( BATTLE_SOUND_COOL1 ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
// Buddy witnessed?
|
|
SayBuddyWitnessedQuoteFromKill( pKillerSoldier, sGridNo, bLevel );
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN HandleSoldierDeath( SOLDIERTYPE *pSoldier , BOOLEAN *pfMadeCorpse )
|
|
{
|
|
BOOLEAN fBuddyJustDead = FALSE;
|
|
*pfMadeCorpse = FALSE;
|
|
|
|
if ( pSoldier->stats.bLife == 0 && !( pSoldier->flags.uiStatusFlags & SOLDIER_DEAD ) )
|
|
{
|
|
// Haydent/send death info
|
|
if (is_networked)
|
|
{
|
|
if(pSoldier->bTeam==0)
|
|
send_death(pSoldier);
|
|
else if(pSoldier->bTeam <6 && ((gTacticalStatus.ubTopMessageType == PLAYER_TURN_MESSAGE) || (gTacticalStatus.ubTopMessageType == PLAYER_INTERRUPT_MESSAGE)))
|
|
send_death(pSoldier);
|
|
}
|
|
|
|
// anv: enemy taunts after kill
|
|
SOLDIERTYPE *pKillerSoldier = NULL;
|
|
if(pSoldier->ubAttackerID != NOBODY)
|
|
{
|
|
pKillerSoldier = MercPtrs[pSoldier->ubAttackerID];
|
|
}
|
|
else if(pSoldier->ubPreviousAttackerID != NOBODY)
|
|
{
|
|
pKillerSoldier = MercPtrs[pSoldier->ubPreviousAttackerID];
|
|
}
|
|
if(pKillerSoldier != NULL)
|
|
{
|
|
if( pSoldier->usAnimState == JFK_HITDEATH )
|
|
PossiblyStartEnemyTaunt( pKillerSoldier, TAUNT_HEAD_POP, pSoldier->ubID );
|
|
else if( Item[pKillerSoldier->usAttackingWeapon].usItemClass & IC_GUN )
|
|
PossiblyStartEnemyTaunt( pKillerSoldier, TAUNT_KILL_GUNFIRE, pSoldier->ubID );
|
|
else if( Item[pKillerSoldier->usAttackingWeapon].usItemClass & IC_BLADE )
|
|
PossiblyStartEnemyTaunt( pKillerSoldier, TAUNT_KILL_BLADE, pSoldier->ubID );
|
|
else if( Item[pKillerSoldier->usAttackingWeapon].usItemClass & IC_PUNCH )
|
|
PossiblyStartEnemyTaunt( pKillerSoldier, TAUNT_KILL_HTH, pSoldier->ubID );
|
|
else if( Item[pKillerSoldier->usAttackingWeapon].usItemClass & IC_THROWING_KNIFE )
|
|
PossiblyStartEnemyTaunt( pKillerSoldier, TAUNT_KILL_THROWING_KNIFE, pSoldier ->ubID);
|
|
else
|
|
PossiblyStartEnemyTaunt( pKillerSoldier, TAUNT_KILL, pSoldier->ubID );
|
|
}
|
|
|
|
// Cancel services here...
|
|
pSoldier->ReceivingSoldierCancelServices( );
|
|
pSoldier->GivingSoldierCancelServices( );
|
|
|
|
if ( pSoldier->iMuzFlash != -1 )
|
|
{
|
|
LightSpriteDestroy( pSoldier->iMuzFlash );
|
|
pSoldier->iMuzFlash = -1;
|
|
}
|
|
if ( pSoldier->iLight != -1 )
|
|
{
|
|
LightSpriteDestroy( pSoldier->iLight );
|
|
}
|
|
|
|
//FREEUP GETTING HIT FLAG
|
|
pSoldier->flags.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->flags.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->flags.uiStatusFlags |= SOLDIER_DEAD;
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//////////////////////////////////////////////////////////////
|
|
// SANDRO - some changes here
|
|
UINT8 ubAttacker = pSoldier->ubAttackerID;
|
|
UINT8 ubAssister = pSoldier->ubPreviousAttackerID;
|
|
// If attacker is nobody, and we died, then set the last attacker(if exists) as our killer
|
|
if ( ubAttacker == NOBODY )
|
|
{
|
|
if ( ubAssister != NOBODY )
|
|
{
|
|
ubAttacker = pSoldier->ubPreviousAttackerID;
|
|
ubAssister = pSoldier->ubNextToPreviousAttackerID;
|
|
}
|
|
else if ( pSoldier->ubNextToPreviousAttackerID != NOBODY )
|
|
{
|
|
ubAttacker = pSoldier->ubNextToPreviousAttackerID;
|
|
ubAssister = NOBODY;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( ubAssister == NOBODY )
|
|
{
|
|
ubAssister = pSoldier->ubNextToPreviousAttackerID;
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////
|
|
|
|
{
|
|
// anv: note that ubAttacker can be already different from pSoldier->ubAttackerID
|
|
// IF this guy has an attacker and he's a good guy, play sound
|
|
if ( pSoldier->ubAttackerID != NOBODY )
|
|
{
|
|
if ( MercPtrs[ pSoldier->ubAttackerID ] != NULL && MercPtrs[ pSoldier->ubAttackerID ]->bTeam == gbPlayerNum && gTacticalStatus.ubAttackBusyCount > 0 )
|
|
{
|
|
gTacticalStatus.fKilledEnemyOnAttack = TRUE;
|
|
gTacticalStatus.ubEnemyKilledOnAttack = pSoldier->ubID;
|
|
gTacticalStatus.ubEnemyKilledOnAttackLocation = pSoldier->sGridNo;
|
|
gTacticalStatus.bEnemyKilledOnAttackLevel = pSoldier->pathing.bLevel;
|
|
gTacticalStatus.ubEnemyKilledOnAttackKiller = ubAttacker;
|
|
|
|
// 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[ ubAttacker ] ) )
|
|
{
|
|
MercPtrs[ ubAttacker ]->DoMercBattleSound( BATTLE_SOUND_LAUGH1 );
|
|
}
|
|
}
|
|
}
|
|
|
|
// Handle NPC Dead
|
|
HandleNPCTeamMemberDeath( pSoldier );
|
|
|
|
// if a friendly with a profile, increment kills
|
|
// militia also now track kills...
|
|
if ( ubAttacker != NOBODY )
|
|
{
|
|
if ( MercPtrs[ ubAttacker ]->bTeam == gbPlayerNum )
|
|
{
|
|
// increment kills
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
// SANDRO - experimental - more specific statistics of mercs
|
|
switch(pSoldier->ubSoldierClass)
|
|
{
|
|
case SOLDIER_CLASS_ELITE :
|
|
gMercProfiles[ MercPtrs[ ubAttacker ]->ubProfile ].records.usKillsElites++;
|
|
break;
|
|
case SOLDIER_CLASS_ARMY :
|
|
gMercProfiles[ MercPtrs[ ubAttacker ]->ubProfile ].records.usKillsRegulars++;
|
|
break;
|
|
case SOLDIER_CLASS_ADMINISTRATOR :
|
|
gMercProfiles[ MercPtrs[ ubAttacker ]->ubProfile ].records.usKillsAdmins++;
|
|
break;
|
|
case SOLDIER_CLASS_CREATURE :
|
|
gMercProfiles[ MercPtrs[ ubAttacker ]->ubProfile ].records.usKillsCreatures++;
|
|
break;
|
|
#ifdef ENABLE_ZOMBIES
|
|
case SOLDIER_CLASS_ZOMBIE :
|
|
gMercProfiles[ MercPtrs[ ubAttacker ]->ubProfile ].records.usKillsZombies++;
|
|
break;
|
|
#endif
|
|
default :
|
|
if ( CREATURE_OR_BLOODCAT( pSoldier ) )
|
|
gMercProfiles[ MercPtrs[ ubAttacker ]->ubProfile ].records.usKillsCreatures++;
|
|
else if ( TANK( pSoldier ) )
|
|
gMercProfiles[ MercPtrs[ ubAttacker ]->ubProfile ].records.usKillsTanks++;
|
|
else if ( pSoldier->bTeam == CIV_TEAM && !pSoldier->aiData.bNeutral && pSoldier->bSide != gbPlayerNum )
|
|
gMercProfiles[ MercPtrs[ ubAttacker ]->ubProfile ].records.usKillsHostiles++;
|
|
else
|
|
{
|
|
gMercProfiles[ MercPtrs[ ubAttacker ]->ubProfile ].records.usKillsOthers++;
|
|
|
|
// Flugente: dynamic opinions
|
|
HandleDynamicOpinionCivKill( MercPtrs[ubAttacker] );
|
|
}
|
|
break;
|
|
}
|
|
//gMercProfiles[ MercPtrs[ pSoldier->ubAttackerID ]->ubProfile ].usKills++;
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
gStrategicStatus.usPlayerKills++;
|
|
}
|
|
else if ( MercPtrs[ ubAttacker ]->bTeam == MILITIA_TEAM )
|
|
{
|
|
// get a kill! 2 points!
|
|
MercPtrs[ ubAttacker ]->ubMilitiaKills += 2;
|
|
}
|
|
|
|
}
|
|
|
|
if ( ubAssister != NOBODY && ubAssister != ubAttacker )
|
|
{
|
|
if ( MercPtrs[ ubAssister ]->bTeam == gbPlayerNum )
|
|
{
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
// SANDRO - new mercs' records
|
|
if( MercPtrs[ ubAttacker ] != NULL )
|
|
{
|
|
if( MercPtrs[ ubAttacker ]->bTeam == gbPlayerNum )
|
|
gMercProfiles[ MercPtrs[ ubAssister ]->ubProfile ].records.usAssistsMercs++;
|
|
else if ( MercPtrs[ ubAttacker ]->bTeam == MILITIA_TEAM )
|
|
gMercProfiles[ MercPtrs[ ubAssister ]->ubProfile ].records.usAssistsMilitia++;
|
|
else
|
|
gMercProfiles[ MercPtrs[ ubAssister ]->ubProfile ].records.usAssistsOthers++;
|
|
}
|
|
else
|
|
{
|
|
gMercProfiles[ MercPtrs[ ubAssister ]->ubProfile ].records.usAssistsOthers++;
|
|
}
|
|
//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;
|
|
}
|
|
}
|
|
*/
|
|
}
|
|
}
|
|
|
|
// Flugente: campaign stats
|
|
gCurrentIncident.AddStat( pSoldier, CAMPAIGNHISTORY_TYPE_KILL );
|
|
|
|
if ( TurnSoldierIntoCorpse( pSoldier, TRUE, TRUE ) )
|
|
{
|
|
*pfMadeCorpse = TRUE;
|
|
}
|
|
|
|
// Flugente: VIPs
|
|
if ( pSoldier->usSoldierFlagMask & SOLDIER_VIP )
|
|
{
|
|
DeleteVIP( pSoldier->sSectorX, pSoldier->sSectorY );
|
|
}
|
|
|
|
// 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->flags.fDoingExternalDeath )
|
|
// {
|
|
// // Release attacker
|
|
// DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("@@@@@@@ Releasesoldierattacker, code 497 = handle soldier death") );
|
|
// ReleaseSoldiersAttacker( pSoldier );
|
|
// }
|
|
// }
|
|
|
|
if ( !( *pfMadeCorpse ) )
|
|
{
|
|
fBuddyJustDead = TRUE;
|
|
}
|
|
|
|
}
|
|
|
|
if ( pSoldier->stats.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->flags.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:
|
|
pSoldier->ChangeSoldierState( FLYBACK_HITDEATH_STOP, 0, FALSE );
|
|
break;
|
|
|
|
case GENERIC_HIT_DEATH:
|
|
pSoldier->ChangeSoldierState( FALLFORWARD_HITDEATH_STOP, 0, FALSE );
|
|
break;
|
|
|
|
case FALLBACK_HIT_DEATH:
|
|
pSoldier->ChangeSoldierState( FALLBACK_HITDEATH_STOP, 0, FALSE );
|
|
break;
|
|
|
|
case PRONE_HIT_DEATH:
|
|
pSoldier->ChangeSoldierState( PRONE_HITDEATH_STOP, 0, FALSE );
|
|
break;
|
|
|
|
case JFK_HITDEATH:
|
|
pSoldier->ChangeSoldierState( JFK_HITDEATH_STOP, 0, FALSE );
|
|
break;
|
|
|
|
case FALLOFF_DEATH:
|
|
pSoldier->ChangeSoldierState( FALLOFF_DEATH_STOP, 0, FALSE );
|
|
break;
|
|
|
|
case FALLOFF_FORWARD_DEATH:
|
|
pSoldier->ChangeSoldierState( FALLOFF_FORWARD_DEATH_STOP, 0, FALSE );
|
|
break;
|
|
|
|
case WATER_DIE:
|
|
pSoldier->ChangeSoldierState( WATER_DIE_STOP, 0, FALSE );
|
|
break;
|
|
|
|
case DEEP_WATER_DIE:
|
|
pSoldier->ChangeSoldierState( DEEP_WATER_DIE_STOPPING, 0, FALSE );
|
|
break;
|
|
|
|
case COW_DYING:
|
|
pSoldier->ChangeSoldierState( COW_DYING_STOP, 0, FALSE);
|
|
break;
|
|
|
|
case BLOODCAT_DYING:
|
|
pSoldier->ChangeSoldierState( 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 )
|
|
{
|
|
INT32 sNewGridNo;
|
|
|
|
if ( pSoldier->stats.bLife < OKLIFE )
|
|
{
|
|
// Cancel services here...
|
|
pSoldier->ReceivingSoldierCancelServices( );
|
|
pSoldier->GivingSoldierCancelServices( );
|
|
|
|
|
|
// 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->stats.bLife = 0;
|
|
break;
|
|
}
|
|
|
|
// OK, if we are in a meanwhile and this is elliot...
|
|
#ifdef JA2UB
|
|
//ja25: No queen
|
|
#else
|
|
if ( AreInMeanwhile( ) )
|
|
{
|
|
SOLDIERTYPE *pQueen;
|
|
|
|
pQueen = FindSoldierByProfileID( QUEEN, FALSE );
|
|
|
|
if ( pQueen )
|
|
{
|
|
TriggerNPCWithGivenApproach( QUEEN, APPROACH_DONE_SLAPPED, FALSE );
|
|
}
|
|
}
|
|
#endif
|
|
// We are unconscious now, play randomly, this animation continued, or a new death
|
|
if ( pSoldier->CheckSoldierHitRoof( ) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// If guy is now dead, play sound!
|
|
if ( pSoldier->stats.bLife == 0 )
|
|
{
|
|
#ifdef JA2UB
|
|
//Ja25 No meanwhiles
|
|
#else
|
|
if ( !AreInMeanwhile() )
|
|
#endif
|
|
{
|
|
pSoldier->DoMercBattleSound( BATTLE_SOUND_DIE1 );
|
|
pSoldier->flags.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->ubDirection;
|
|
BOOLEAN fForceDirection = FALSE;
|
|
BOOLEAN fDoFallback = FALSE;
|
|
BOOLEAN fAlwaysFallBack = FALSE; // added by SANDRO
|
|
|
|
|
|
// 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
|
|
// SANDRO - if Martial Artist took someone down, always fall back if possible (for the fun)
|
|
if ( pSoldier->ubAttackerID != NOBODY && gGameOptions.fNewTraitSystem )
|
|
{
|
|
if ( HAS_SKILL_TRAIT( MercPtrs[ pSoldier->ubAttackerID ], MARTIAL_ARTS_NT ) && (!MercPtrs[ pSoldier->ubAttackerID ]->usAttackingWeapon || Item[MercPtrs[ pSoldier->ubAttackerID ]->inv[HANDPOS].usItem].brassknuckles ) )
|
|
{
|
|
fAlwaysFallBack = TRUE;
|
|
}
|
|
}
|
|
if ( (Random(100 ) > 40 || fAlwaysFallBack) && 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( pSoldier->sGridNo, DirectionInc( gOppositeDirection[ bTestDirection ] ) );
|
|
|
|
if ( OKFallDirection( pSoldier, sNewGridNo, pSoldier->pathing.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
|
|
pSoldier->BeginTyingToFall( );
|
|
pSoldier->ChangeSoldierState( FALLFORWARD_FROMHIT_STAND, 0, FALSE );
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
// ALL'S OK HERE..... IF WE FORCED DIRECTION, SET!
|
|
if ( fForceDirection )
|
|
{
|
|
pSoldier->EVENT_SetSoldierDesiredDirection( bTestDirection );
|
|
pSoldier->EVENT_SetSoldierDirection( bTestDirection );
|
|
}
|
|
pSoldier->ChangeToFallbackAnimation( pSoldier->ubDirection );
|
|
return;
|
|
}
|
|
}
|
|
else if ( pSoldier->usAnimState == GENERIC_HIT_CROUCH || pSoldier->usAnimState == CIV_COWER_HIT)
|
|
{
|
|
pSoldier->ChangeSoldierState( FALLFORWARD_FROMHIT_CROUCH, 0 , FALSE);
|
|
pSoldier->BeginTyingToFall( );
|
|
return;
|
|
}
|
|
else if ( pSoldier->usAnimState == GENERIC_HIT_PRONE )
|
|
{
|
|
pSoldier->ChangeSoldierState( PRONE_LAY_FROMHIT, 0 , FALSE );
|
|
return;
|
|
}
|
|
else if ( pSoldier->usAnimState == ADULTMONSTER_HIT )
|
|
{
|
|
pSoldier->ChangeSoldierState( ADULTMONSTER_DYING, 0 , FALSE );
|
|
return;
|
|
}
|
|
else if ( pSoldier->usAnimState == LARVAE_HIT )
|
|
{
|
|
pSoldier->ChangeSoldierState( LARVAE_DIE, 0 , FALSE );
|
|
return;
|
|
}
|
|
else if ( pSoldier->usAnimState == QUEEN_HIT )
|
|
{
|
|
pSoldier->ChangeSoldierState( QUEEN_DIE, 0 , FALSE );
|
|
return;
|
|
}
|
|
else if ( pSoldier->usAnimState == CRIPPLE_HIT )
|
|
{
|
|
pSoldier->ChangeSoldierState( CRIPPLE_DIE, 0 , FALSE );
|
|
return;
|
|
}
|
|
else if ( pSoldier->usAnimState == ROBOTNW_HIT )
|
|
{
|
|
pSoldier->ChangeSoldierState( ROBOTNW_DIE, 0 , FALSE );
|
|
return;
|
|
}
|
|
else if ( pSoldier->usAnimState == INFANT_HIT )
|
|
{
|
|
pSoldier->ChangeSoldierState( INFANT_DIE, 0 , FALSE );
|
|
return;
|
|
}
|
|
else if ( pSoldier->usAnimState == COW_HIT )
|
|
{
|
|
pSoldier->ChangeSoldierState( COW_DYING, 0 , FALSE );
|
|
return;
|
|
}
|
|
else if ( pSoldier->usAnimState == BLOODCAT_HIT )
|
|
{
|
|
pSoldier->ChangeSoldierState( BLOODCAT_DYING, 0 , FALSE );
|
|
return;
|
|
}
|
|
else if ( pSoldier->usAnimState == WATER_HIT )
|
|
{
|
|
pSoldier->ChangeSoldierState( WATER_DIE, 0 , FALSE );
|
|
return;
|
|
}
|
|
else if ( pSoldier->usAnimState == DEEP_WATER_HIT )
|
|
{
|
|
pSoldier->ChangeSoldierState( 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->stats.bLife == 0 )
|
|
{
|
|
pSoldier->DoMercBattleSound( BATTLE_SOUND_DIE1 );
|
|
pSoldier->flags.fDeadSoundPlayed = TRUE;
|
|
|
|
// 0verhaul: The bBeingAttackedCount is now obsolete.
|
|
// Increment being attacked count
|
|
// pSoldier->bBeingAttackedCount++;
|
|
|
|
// OJW - Send bleeding death
|
|
if (is_networked)
|
|
{
|
|
if(pSoldier->bTeam==0) send_death(pSoldier);
|
|
else if(pSoldier->bTeam <6 && ((gTacticalStatus.ubTopMessageType == PLAYER_TURN_MESSAGE) || (gTacticalStatus.ubTopMessageType == PLAYER_INTERRUPT_MESSAGE)))send_death(pSoldier);
|
|
else if (pSoldier->bTeam < 6 && (is_server)) send_death(pSoldier);
|
|
}
|
|
if ( gGameSettings.fOptions[ TOPTION_BLOOD_N_GORE ] )
|
|
{
|
|
switch( pSoldier->usAnimState )
|
|
{
|
|
case FLYBACKHIT_STOP:
|
|
pSoldier->ChangeSoldierState( FLYBACK_HIT_DEATH, 0, FALSE );
|
|
break;
|
|
|
|
case FALLFORWARD_FROMHIT_STAND:
|
|
case FALLFORWARD_FROMHIT_CROUCH:
|
|
case STAND_FALLFORWARD_STOP:
|
|
pSoldier->ChangeSoldierState( GENERIC_HIT_DEATH, 0, FALSE );
|
|
break;
|
|
|
|
case FALLBACKHIT_STOP:
|
|
pSoldier->ChangeSoldierState( FALLBACK_HIT_DEATH, 0, FALSE );
|
|
break;
|
|
|
|
case PRONE_LAYFROMHIT_STOP:
|
|
case PRONE_LAY_FROMHIT:
|
|
|
|
pSoldier->ChangeSoldierState( PRONE_HIT_DEATH, 0, FALSE );
|
|
break;
|
|
|
|
case FALLOFF_STOP:
|
|
pSoldier->ChangeSoldierState( FALLOFF_DEATH, 0, FALSE );
|
|
break;
|
|
|
|
case FALLOFF_FORWARD_STOP:
|
|
pSoldier->ChangeSoldierState( FALLOFF_FORWARD_DEATH, 0, FALSE);
|
|
break;
|
|
|
|
case ADULTMONSTER_HIT:
|
|
pSoldier->ChangeSoldierState( ADULTMONSTER_DYING, 0 , FALSE );
|
|
break;
|
|
|
|
case LARVAE_HIT:
|
|
pSoldier->ChangeSoldierState( LARVAE_DIE, 0 , FALSE );
|
|
break;
|
|
|
|
case QUEEN_HIT:
|
|
pSoldier->ChangeSoldierState( QUEEN_DIE, 0 , FALSE );
|
|
break;
|
|
|
|
case CRIPPLE_HIT:
|
|
pSoldier->ChangeSoldierState( CRIPPLE_DIE, 0 , FALSE );
|
|
break;
|
|
|
|
case ROBOTNW_HIT:
|
|
pSoldier->ChangeSoldierState( ROBOTNW_DIE, 0 , FALSE );
|
|
break;
|
|
|
|
case INFANT_HIT:
|
|
pSoldier->ChangeSoldierState( INFANT_DIE, 0 , FALSE );
|
|
break;
|
|
|
|
case COW_HIT:
|
|
pSoldier->ChangeSoldierState( COW_DYING, 0 , FALSE );
|
|
break;
|
|
|
|
case BLOODCAT_HIT:
|
|
pSoldier->ChangeSoldierState( 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 );
|
|
}
|
|
|
|
//dnl ch72 260913
|
|
OBJECTTYPE *pObjHand;
|
|
if(pSoldier->bWeaponMode == WM_ATTACHED_GL || pSoldier->bWeaponMode == WM_ATTACHED_GL_BURST || pSoldier->bWeaponMode == WM_ATTACHED_GL_AUTO)
|
|
pObjHand = FindAttachment_GrenadeLauncher(&pSoldier->inv[HANDPOS]);
|
|
else
|
|
pObjHand = pSoldier->GetUsedWeapon(&pSoldier->inv[HANDPOS]);
|
|
|
|
// Check single hand for jammed status, ( or ammo is out.. )
|
|
if ( (*pObjHand)[0]->data.gun.bGunAmmoStatus < 0 || (*pObjHand)[0]->data.gun.ubGunShotsLeft == 0 )
|
|
{
|
|
// If we have 2 pistols, donot go back!
|
|
if ( Item[ pSoldier->inv[ SECONDHANDPOS ].usItem ].usItemClass != IC_GUN )
|
|
{
|
|
// OK, put gun down....
|
|
pSoldier->InternalSoldierReadyWeapon(pSoldier->ubDirection, TRUE, FALSE );
|
|
return( TRUE );
|
|
}
|
|
}
|
|
|
|
// SANDRO: if we are holding up a very heavy gun, and can't do it anymore, lower it
|
|
if ( gGameExternalOptions.ubEnergyCostForWeaponWeight && pSoldier->bBreath < OKBREATH )
|
|
{
|
|
// Check for breath collapse, though this should rarely happen
|
|
if ( pSoldier->CheckForBreathCollapse( ) )
|
|
{
|
|
UnSetUIBusy( pSoldier->ubID );
|
|
SoldierCollapse( pSoldier );
|
|
pSoldier->bBreathCollapsed = FALSE;
|
|
return( TRUE );
|
|
}
|
|
// ok, if this gun is rather heavy, and cost us at least 3 energy points per turn, and we got very low on breath
|
|
else if ( (GetBPCostPer10APsForGunHolding( pSoldier ) * 10) >= (300 * gGameExternalOptions.ubEnergyCostForWeaponWeight / 100) )
|
|
{
|
|
// throw quote
|
|
if ( !(pSoldier->usQuoteSaidFlags & SOLDIER_QUOTE_SAID_LOW_BREATH ) )
|
|
{
|
|
TacticalCharacterDialogue( pSoldier, QUOTE_OUT_OF_BREATH );
|
|
pSoldier->usQuoteSaidFlags |= SOLDIER_QUOTE_SAID_LOW_BREATH;
|
|
}
|
|
// Put gun down....
|
|
pSoldier->InternalSoldierReadyWeapon(pSoldier->ubDirection, TRUE, FALSE );
|
|
return( TRUE );
|
|
}
|
|
}
|
|
|
|
return( FALSE );
|
|
|
|
}
|
|
|
|
|
|
BOOLEAN OKHeightDest( SOLDIERTYPE *pSoldier, INT32 sNewGridNo )
|
|
{
|
|
if ( pSoldier->pathing.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->aiData.uiPendingActionData1 = pSoldier->usAniCode;
|
|
pSoldier->aiData.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
|
|
pSoldier->ChangeSoldierState( STANDING_SHOOT_UNJAM, 0 , FALSE );
|
|
return( TRUE );
|
|
|
|
case PRONE_BURST:
|
|
case SHOOT_RIFLE_PRONE:
|
|
|
|
// Normal shoot rifle.... play
|
|
pSoldier->ChangeSoldierState( PRONE_SHOOT_UNJAM, 0 , FALSE );
|
|
return( TRUE );
|
|
|
|
case CROUCHED_BURST:
|
|
case SHOOT_RIFLE_CROUCH:
|
|
|
|
// Normal shoot rifle.... play
|
|
pSoldier->ChangeSoldierState( CROUCH_SHOOT_UNJAM, 0 , FALSE );
|
|
return( TRUE );
|
|
|
|
case SHOOT_DUAL_STAND:
|
|
case BURST_DUAL_STAND:
|
|
|
|
// Normal shoot rifle.... play
|
|
pSoldier->ChangeSoldierState( STANDING_SHOOT_DWEL_UNJAM, 0 , FALSE );
|
|
return( TRUE );
|
|
|
|
case SHOOT_DUAL_PRONE:
|
|
case BURST_DUAL_PRONE:
|
|
|
|
// Normal shoot rifle.... play
|
|
pSoldier->ChangeSoldierState( PRONE_SHOOT_DWEL_UNJAM, 0 , FALSE );
|
|
return( TRUE );
|
|
|
|
case SHOOT_DUAL_CROUCH:
|
|
case BURST_DUAL_CROUCH:
|
|
|
|
// Normal shoot rifle.... play
|
|
pSoldier->ChangeSoldierState( CROUCH_SHOOT_DWEL_UNJAM, 0 , FALSE );
|
|
return( TRUE );
|
|
|
|
case FIRE_LOW_STAND:
|
|
case FIRE_BURST_LOW_STAND:
|
|
|
|
// Normal shoot rifle.... play
|
|
pSoldier->ChangeSoldierState( STANDING_SHOOT_LOW_UNJAM, 0 , FALSE );
|
|
return( TRUE );
|
|
|
|
case SHOOT_ALTERNATIVE_STAND:
|
|
case BURST_ALTERNATIVE_STAND:
|
|
|
|
// Normal shoot rifle.... play
|
|
pSoldier->ChangeSoldierState( UNJAM_ALTERNATIVE_STAND, 0 , FALSE );
|
|
return( TRUE );
|
|
|
|
case LOW_SHOT_ALTERNATIVE_STAND:
|
|
case LOW_BURST_ALTERNATIVE_STAND:
|
|
|
|
// Normal shoot rifle.... play
|
|
pSoldier->ChangeSoldierState( LOW_UNJAM_ALTERNATIVE_STAND, 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->stats.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->ubDirection;
|
|
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( pSoldier->sGridNo, (UINT16)(-1 * DirectionInc( bTestDirection ) ) );
|
|
|
|
if ( NewOKDestination( pSoldier, sNewGridNo, TRUE, pSoldier->pathing.bLevel ) && OKHeightDest( pSoldier, sNewGridNo ) )
|
|
{
|
|
// ALL'S OK HERE..... IF WE FORCED DIRECTION, SET!
|
|
if ( fForceDirection )
|
|
{
|
|
pSoldier->EVENT_SetSoldierDirection( bTestDirection );
|
|
pSoldier->EVENT_SetSoldierDesiredDirection( bTestDirection );
|
|
}
|
|
pSoldier->ChangeSoldierState( FALLBACK_HIT_STAND, 0, FALSE );
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
BOOLEAN OKFallDirection( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel, UINT8 ubTestDirection, UINT16 usAnimState )
|
|
{
|
|
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"OKFallDirection");
|
|
STRUCTURE_FILE_REF * pStructureFileRef;
|
|
UINT16 usAnimSurface;
|
|
UINT8 bOverTerrainType;
|
|
|
|
// WANNE - MP: MP crashed here, so I added the prevention
|
|
if (TileIsOutOfBounds(sGridNo))
|
|
return ( FALSE );
|
|
|
|
// How are the movement costs?
|
|
if ( gubWorldMovementCosts[ sGridNo ][ ubTestDirection ][ bLevel ] > TRAVELCOST_SHORE )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
bOverTerrainType = GetTerrainType( sGridNo);
|
|
|
|
// WANNE.WATER: If our soldier is not on the ground level and the tile is a "water" tile, then simply set the tile to "FLAT_GROUND"
|
|
// This should fix "problems" for special modified maps
|
|
if ( TERRAIN_IS_WATER( bOverTerrainType) && bLevel > 0 )
|
|
bOverTerrainType = FLAT_GROUND;
|
|
|
|
//NOT ok if in water....
|
|
if ( TERRAIN_IS_WATER( bOverTerrainType) )
|
|
{
|
|
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;
|
|
INT32 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, DirectionInc( gOppositeDirection[ ubTestDirection ] ) );
|
|
|
|
if ( ! OkayToAddStructureToWorld( sTestGridNo, bLevel, &(pStructureFileRef->pDBStructureRef[ gOneCDirection[ ubTestDirection ] ]), 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 )
|
|
{
|
|
pSoldier->ChangeSoldierState( 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 )
|
|
{
|
|
pSoldier->ChangeSoldierState( 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...
|
|
pSoldier->BeginSoldierGetup( );
|
|
|
|
// Check this to see if above worked
|
|
if ( !pSoldier->bCollapsed )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
}
|
|
|
|
switch( pSoldier->usAnimState )
|
|
{
|
|
case FLYBACK_HIT:
|
|
pSoldier->ChangeSoldierState( FLYBACKHIT_STOP, 0, FALSE );
|
|
break;
|
|
|
|
case GENERIC_HIT_DEATHTWITCHNB:
|
|
case FALLFORWARD_FROMHIT_STAND:
|
|
case ENDFALLFORWARD_FROMHIT_CROUCH:
|
|
|
|
pSoldier->ChangeSoldierState( STAND_FALLFORWARD_STOP, 0, FALSE );
|
|
break;
|
|
|
|
case FALLBACK_HIT_DEATHTWITCHNB:
|
|
case FALLBACK_HIT_STAND:
|
|
pSoldier->ChangeSoldierState( FALLBACKHIT_STOP, 0, FALSE );
|
|
break;
|
|
|
|
case PRONE_HIT_DEATHTWITCHNB:
|
|
case PRONE_LAY_FROMHIT:
|
|
|
|
pSoldier->ChangeSoldierState( PRONE_LAYFROMHIT_STOP, 0, FALSE );
|
|
break;
|
|
|
|
case FALLOFF:
|
|
pSoldier->ChangeSoldierState( FALLOFF_STOP, 0, FALSE );
|
|
break;
|
|
|
|
case FALLFORWARD_ROOF:
|
|
pSoldier->ChangeSoldierState( 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...
|
|
pSoldier->BeginSoldierGetup( );
|
|
|
|
// Check this to see if above worked
|
|
if ( !pSoldier->bCollapsed )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
}
|
|
|
|
switch( pSoldier->usAnimState )
|
|
{
|
|
case FLYBACK_HIT:
|
|
pSoldier->ChangeSoldierState( FLYBACKHIT_STOP, 0, FALSE );
|
|
break;
|
|
|
|
case GENERIC_HIT_DEATHTWITCHNB:
|
|
case FALLFORWARD_FROMHIT_STAND:
|
|
case ENDFALLFORWARD_FROMHIT_CROUCH:
|
|
|
|
pSoldier->ChangeSoldierState( STAND_FALLFORWARD_STOP, 0, FALSE );
|
|
break;
|
|
|
|
case FALLBACK_HIT_DEATHTWITCHNB:
|
|
case FALLBACK_HIT_STAND:
|
|
pSoldier->ChangeSoldierState( FALLBACKHIT_STOP, 0, FALSE );
|
|
break;
|
|
|
|
case PRONE_HIT_DEATHTWITCHNB:
|
|
case PRONE_LAY_FROMHIT:
|
|
|
|
pSoldier->ChangeSoldierState( PRONE_LAYFROMHIT_STOP, 0, FALSE );
|
|
break;
|
|
|
|
case FALLOFF:
|
|
pSoldier->ChangeSoldierState( FALLOFF_STOP, 0, FALSE );
|
|
break;
|
|
|
|
case FALLFORWARD_ROOF:
|
|
pSoldier->ChangeSoldierState( 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 )
|
|
{
|
|
INT32 sNewGridNo;
|
|
|
|
// Move forward one gridno....
|
|
sNewGridNo = NewGridNo( pSoldier->sGridNo, DirectionInc( pSoldier->ubDirection ) );
|
|
|
|
// ATE: Make sure that the gridno is unoccupied!
|
|
if ( !NewOKDestination( pSoldier, sNewGridNo, TRUE, pSoldier->pathing.bLevel ) )
|
|
{
|
|
// We should just stay put - will look kind of funny but nothing I can do!
|
|
sNewGridNo = pSoldier->sGridNo;
|
|
}
|
|
|
|
pSoldier->EVENT_StopMerc( sNewGridNo, pSoldier->ubDirection );
|
|
pSoldier->ubBodyType = REGMALE;
|
|
if ( pSoldier->ubProfile == SLAY && pSoldier->bTeam == CIV_TEAM && !pSoldier->aiData.bNeutral )
|
|
{
|
|
HandleNPCDoAction( pSoldier->ubProfile, NPC_ACTION_THREATENINGLY_RAISE_GUN, 0 );
|
|
}
|
|
else
|
|
{
|
|
pSoldier->EVENT_InitNewSoldierAnim( 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;
|
|
}
|
|
|
|
}
|