mirror of
https://github.com/1dot13/source.git
synced 2026-07-29 13:52:17 +02:00
MERGED source code from development trunk revision 4545 up to latest current revision 4882
Development Trunk: https://ja2svn.dyndns.org/source/ja2/branches/Wanne/JA2%201.13%20MP A detailed list of all the features (changes) is visible in the history log of the development trunk: INFO: The source code for the official 2011 release (4870) has been branched here: https://ja2svn.dyndns.org/source/ja2/branches/JA2_rev.4870_2011 This commit contains the following features: *** Externalized Vehicles *** o Now with this feature we can add/remove vehicles o New XML File: TableData\Vehicles.xml o Added a new function parameter to lua file Scripts\Overhead lua to set up the helicopter in method: SetUpHelicopterForPlayer() o Added example mini (Docs\Externalized Vehicles Example.zip) mod which adds 2 additional vehicles (hummer and ice-cream truck to sector A9) *** Up to 255 save slots *** - There is a "Next" and "Prev" button where you can scroll through the save slots - It is now possible to load the automatic save (SAVE_EVERY_N_HOURS) from the load screen. This is the first slot after the quickload slot - Added the 2 alternate players end turn saves (which can be enabled/disabled in option screen) to the save/load game form *** New Feature: Externalized emails from Emails.edt to XML*** o This feature can be enabled/disabled in the Source: --> See email.cpp: If "ReadXMLEmail" == FALSE, then normal way (read from Email.edt) otherwise read from XML files o 2 new XML files: TableData\Email\EmailMercAvailable.xml and EmailMercLevelUp.xml o Renamed SenderNamesList.xml to EmailSenderNamesList.xml and moved from TableData folder to TableData\Email folder o Names for mercenaries are get from the file MercProfiles.xml and different names get from the file EmailSenderNamesList.xml *** Externalized Hidden Towns (Tixa, Orta) *** o Now it is possible to add new hidden towns (locations) o See file: TableData/Map/Cities.xml o New variable in TableData/Map/Cities.xml - hiddenTown: 0 = show on strategy map, 1 = Hide on strategy map - townIcon: 1 = on, 0 = off (This is the icon you see on the strategy map) - szIconFile: The path to the sti icon file (eg: interface\prison.sti, interface\my_icon.sti) - iconPosition: The x,y position of the icon on the strategy map *** Encyclopedia and Briefing Room, reachable from the laptop *** o 2 new ja2_options.ini properties: BRIEFING_ROOM, ENCYCLOPEDIA o demonstration video: http://www.youtube.com/watch?v=7CIXdXWLrAo o Added Example usage of the Briefing Room - Extract it in your JA2 1.13 folder and use the latest development executable - The briefing room can be reached from the laptop. Enter SN5631 for the code and then click the "Exit" button - See "Info_BriefingRoom.txt" and "BriefingRoom_Mission1.png" *** Improved interrupt system (IIS) *** o This system changes the way interrupts work. See: http://www.ja-galaxy-forum.com/board/ubbthreads.php?ubb=showflat&Number=290787#Post290787 o Option system (see ja2_options.ini: IMPROVED_INTERRUPT_SYSTEM) o A few more settings for the interrupt system in ja2_options.ini o INFO: Multiplayer games always use the "old" interrupt system, not matter what the user selects in the ja2_options.ini *** Walking and sidestepping with weapon raised *** o Enable/disable the walking/sidestepping with raised weapon in ja2_options.ini: ALLOW_WALKING_WITH_WEAPON_RAISED o You can set an AP/BP modifier when walking/sidestepping with weapon raised in APBPConstants.ini: AP_MODIFIER_WEAPON_READY o The following feature apply when you walk/sidestep with weapon raised: -> limited angle of view, but you can see more farther when the weapon has a scope -> better change for interrupts if you see an enemy -> less APs and BPs when shooting, because the weapon is already raised -> It should cost more APs when walking. Maybe you can export the additional AP and BP modifier to the APBPConstants.ini *** Increase squad size to 8 (800x600) and 8 and 10 (1024x768) *** o Squad sizes (dependend on the screen resolution) can be selected in the start new game screen o In a multiplayer game, the squad size will always be 6, because it does not work with more soldiers/squad *** Added UB-1.13 source code *** o Merged the UB-1.13 source code (Revision: 4721) from svn: http://subversion.assembla.com/svn/ub-source113 o If you want to build UB-EXE or UB-MapEditor, just enable the 2 defines (JA2UB and JA2UBMAPS) in "builddefines.h" o The UB-Verion reads from "ja2_UB.ini" instead of "ja2.ini" o There are 2 new XML files - Layout\LayoutMainMenu.xml - MapAction\ActionItems.xml o There are 2 new LUA-Script files - Scripts\ExplosionControl.lua - Scripts\InterfaceDialogue.lua *** Hide enemy health text / enemy hit count *** o ja2_options.ini: HIDE_ENEMY_HEALTH_TEXT, HIDE_ENEMY_HIT_COUNT o both new settings only have effect in a singleplayer game o see: http://www.ja-galaxy-forum.com/board/ubbthreads.php?ubb=showflat&Number=128840&page=1 git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@4885 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
+454
-45
@@ -99,6 +99,13 @@
|
||||
#include "LOS.h" // added by SANDRO
|
||||
#endif
|
||||
|
||||
#include "ub_config.h"
|
||||
|
||||
#ifdef JA2UB
|
||||
#include "Ja25_Tactical.h"
|
||||
#include "Ja25 Strategic Ai.h"
|
||||
#endif
|
||||
|
||||
#include "fresh_header.h"
|
||||
|
||||
#include "Dialogue Control.h"
|
||||
@@ -2884,6 +2891,8 @@ BOOLEAN SOLDIERTYPE::EVENT_InitNewSoldierAnim( UINT16 usNewState, UINT16 usStart
|
||||
// If we are NOT loading a game, continue normally
|
||||
if( !(gTacticalStatus.uiFlags & LOADING_SAVED_GAME ) )
|
||||
{
|
||||
usItem = this->inv[ HANDPOS ].usItem;
|
||||
|
||||
// CHECK IF WE ARE TRYING TO INTURRUPT A SCRIPT WHICH WE DO NOT WANT INTERRUPTED!
|
||||
if ( this->flags.fInNonintAnim )
|
||||
{
|
||||
@@ -3039,7 +3048,7 @@ BOOLEAN SOLDIERTYPE::EVENT_InitNewSoldierAnim( UINT16 usNewState, UINT16 usStart
|
||||
// We are told that we need to rasie weapon
|
||||
// Do so only if
|
||||
// 1) We have a rifle in hand...
|
||||
usItem = this->inv[ HANDPOS ].usItem;
|
||||
//usItem = this->inv[ HANDPOS ].usItem;
|
||||
|
||||
if ( this->inv[ HANDPOS ].exists() == true && (Item[ usItem ].twohanded ) && !Item[usItem].rocketlauncher )
|
||||
{
|
||||
@@ -3062,7 +3071,7 @@ BOOLEAN SOLDIERTYPE::EVENT_InitNewSoldierAnim( UINT16 usNewState, UINT16 usStart
|
||||
// We are told that we need to rasie weapon
|
||||
// Do so only if
|
||||
// 1) We have a rifle in hand...
|
||||
usItem = this->inv[ HANDPOS ].usItem;
|
||||
//usItem = this->inv[ HANDPOS ].usItem;
|
||||
|
||||
if ( this->inv[ HANDPOS ].exists() == true && (Item[ usItem ].twohanded ) && !Item[usItem].rocketlauncher )
|
||||
{
|
||||
@@ -3125,7 +3134,8 @@ BOOLEAN SOLDIERTYPE::EVENT_InitNewSoldierAnim( UINT16 usNewState, UINT16 usStart
|
||||
}
|
||||
|
||||
// OK.......
|
||||
if ( this->ubBodyType > REGFEMALE )
|
||||
// SANDRO - removing unused code
|
||||
/*if ( this->ubBodyType > REGFEMALE )
|
||||
{
|
||||
if ( this->stats.bLife < INJURED_CHANGE_THREASHOLD )
|
||||
{
|
||||
@@ -3135,7 +3145,7 @@ BOOLEAN SOLDIERTYPE::EVENT_InitNewSoldierAnim( UINT16 usNewState, UINT16 usStart
|
||||
// usNewState = FROM_INJURED_TRANSITION;
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
// Alrighty, check if we should free buddy up!
|
||||
if ( usNewState == GIVING_AID )
|
||||
@@ -3161,10 +3171,10 @@ BOOLEAN SOLDIERTYPE::EVENT_InitNewSoldierAnim( UINT16 usNewState, UINT16 usStart
|
||||
{
|
||||
if ( usNewState == KNEEL_DOWN && this->usAnimState != BIGMERC_CROUCH_TRANS_INTO )
|
||||
{
|
||||
UINT16 usItem;
|
||||
//UINT16 usItem;
|
||||
|
||||
// Do we have a rifle?
|
||||
usItem = this->inv[ HANDPOS ].usItem;
|
||||
//usItem = this->inv[ HANDPOS ].usItem;
|
||||
|
||||
if ( this->inv[ HANDPOS ].exists() == true )
|
||||
{
|
||||
@@ -3181,10 +3191,10 @@ BOOLEAN SOLDIERTYPE::EVENT_InitNewSoldierAnim( UINT16 usNewState, UINT16 usStart
|
||||
|
||||
if ( usNewState == KNEEL_UP && this->usAnimState != BIGMERC_CROUCH_TRANS_OUTOF )
|
||||
{
|
||||
UINT16 usItem;
|
||||
//UINT16 usItem;
|
||||
|
||||
// Do we have a rifle?
|
||||
usItem = this->inv[ HANDPOS ].usItem;
|
||||
//usItem = this->inv[ HANDPOS ].usItem;
|
||||
|
||||
if ( this->inv[ HANDPOS ].exists() == true )
|
||||
{
|
||||
@@ -3211,15 +3221,39 @@ BOOLEAN SOLDIERTYPE::EVENT_InitNewSoldierAnim( UINT16 usNewState, UINT16 usStart
|
||||
if ( this->ubDirection == gPurpendicularDirection[ this->ubDirection ][ this->pathing.usPathingData[ this->pathing.usPathIndex ] ] )
|
||||
{
|
||||
// We are perpendicular!
|
||||
usNewState = SIDE_STEP;
|
||||
// SANDRO - wait wait wait!!! We need to determine if gonna sidestep with weapon raised
|
||||
if (( (gAnimControl[ this->usAnimState ].uiFlags & ANIM_FIREREADY ) ||
|
||||
(gAnimControl[ this->usAnimState ].uiFlags & ANIM_FIRE ) ) && gGameExternalOptions.fAllowWalkingWithWeaponRaised )
|
||||
//if ( WeaponReady( this ) )
|
||||
{
|
||||
if ( this->inv[ HANDPOS ].exists() == true && Item[ usItem ].usItemClass == IC_GUN && !Item[usItem].rocketlauncher)
|
||||
{
|
||||
if ( !(Item[ usItem ].twohanded ) )
|
||||
{
|
||||
if ( this->IsValidSecondHandShot() )
|
||||
{
|
||||
usNewState = SIDE_STEP_DUAL_RDY;
|
||||
}
|
||||
else
|
||||
{
|
||||
usNewState = SIDE_STEP_PISTOL_RDY;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
usNewState = SIDE_STEP_RIFLE_RDY;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
usNewState = SIDE_STEP;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( gAnimControl[ this->usAnimState ].ubEndHeight == ANIM_CROUCH )
|
||||
{
|
||||
//*** ddd
|
||||
UINT16 usItem = this->inv[ HANDPOS ].usItem;
|
||||
|
||||
{
|
||||
if( this->inv[ HANDPOS ].exists() == true && Item[ usItem ].usItemClass == IC_GUN && Item[ usItem ].twohanded && !Item[usItem].rocketlauncher)
|
||||
usNewState = SWAT_BACKWARDS;
|
||||
else
|
||||
@@ -3288,6 +3322,29 @@ BOOLEAN SOLDIERTYPE::EVENT_InitNewSoldierAnim( UINT16 usNewState, UINT16 usStart
|
||||
usNewState = WALKING;
|
||||
}
|
||||
}
|
||||
// SANDRO - check if we are gonna move with weapon raised
|
||||
else if (( (gAnimControl[ this->usAnimState ].uiFlags & ANIM_FIREREADY ) ||
|
||||
(gAnimControl[ this->usAnimState ].uiFlags & ANIM_FIRE ) ) && ( usNewState == WALKING ) && gGameExternalOptions.fAllowWalkingWithWeaponRaised )
|
||||
{
|
||||
if ( this->inv[ HANDPOS ].exists() == true && Item[ usItem ].usItemClass == IC_GUN && !Item[usItem].rocketlauncher)
|
||||
{
|
||||
if ( !(Item[ usItem ].twohanded ) )
|
||||
{
|
||||
if ( this->IsValidSecondHandShot() )
|
||||
{
|
||||
usNewState = WALKING_DUAL_RDY;
|
||||
}
|
||||
else
|
||||
{
|
||||
usNewState = WALKING_PISTOL_RDY;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
usNewState = WALKING_RIFLE_RDY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Turn off anipause flag for any anim!
|
||||
this->flags.uiStatusFlags &= (~SOLDIER_PAUSEANIMOVE);
|
||||
@@ -3540,7 +3597,7 @@ BOOLEAN SOLDIERTYPE::EVENT_InitNewSoldierAnim( UINT16 usNewState, UINT16 usStart
|
||||
if ( !this->flags.fDontChargeReadyAPs )
|
||||
{
|
||||
sAPCost = GetAPsToReadyWeapon( this, usNewState );
|
||||
DeductPoints( this, sAPCost, sBPCost );
|
||||
DeductPoints( this, sAPCost, sBPCost, BEFORESHOT_INTERRUPT );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3549,6 +3606,9 @@ BOOLEAN SOLDIERTYPE::EVENT_InitNewSoldierAnim( UINT16 usNewState, UINT16 usStart
|
||||
break;
|
||||
|
||||
case WALKING:
|
||||
case WALKING_PISTOL_RDY:
|
||||
case WALKING_RIFLE_RDY:
|
||||
case WALKING_DUAL_RDY:
|
||||
|
||||
this->usPendingAnimation = NO_PENDING_ANIMATION;
|
||||
this->aiData.ubPendingActionAnimCount = 0;
|
||||
@@ -3581,7 +3641,7 @@ BOOLEAN SOLDIERTYPE::EVENT_InitNewSoldierAnim( UINT16 usNewState, UINT16 usStart
|
||||
}
|
||||
else
|
||||
sAPCost = GetAPsStartRun( this ); // changed by SANDRO
|
||||
DeductPoints( this, sAPCost, sBPCost );
|
||||
DeductPoints( this, sAPCost, sBPCost, MOVEMENT_INTERRUPT );
|
||||
}
|
||||
// Set pending action count to 0
|
||||
this->aiData.ubPendingActionAnimCount = 0;
|
||||
@@ -3679,7 +3739,7 @@ BOOLEAN SOLDIERTYPE::EVENT_InitNewSoldierAnim( UINT16 usNewState, UINT16 usStart
|
||||
break;
|
||||
|
||||
case CUTTING_FENCE:
|
||||
DeductPoints( this, APBPConstants[AP_USEWIRECUTTERS], APBPConstants[BP_USEWIRECUTTERS] );
|
||||
DeductPoints( this, APBPConstants[AP_USEWIRECUTTERS], APBPConstants[BP_USEWIRECUTTERS], AFTERACTION_INTERRUPT );
|
||||
break;
|
||||
|
||||
case PLANT_BOMB:
|
||||
@@ -3721,7 +3781,7 @@ BOOLEAN SOLDIERTYPE::EVENT_InitNewSoldierAnim( UINT16 usNewState, UINT16 usStart
|
||||
|
||||
case USE_REMOTE:
|
||||
|
||||
DeductPoints( this, APBPConstants[AP_USE_REMOTE], 0 );
|
||||
DeductPoints( this, APBPConstants[AP_USE_REMOTE], 0, AFTERACTION_INTERRUPT );
|
||||
break;
|
||||
|
||||
//case PUNCH:
|
||||
@@ -3736,28 +3796,28 @@ BOOLEAN SOLDIERTYPE::EVENT_InitNewSoldierAnim( UINT16 usNewState, UINT16 usStart
|
||||
// CHRISL
|
||||
// SANDRO - changed this a bit
|
||||
if((UsingNewInventorySystem() == true) && FindBackpackOnSoldier( this ) != ITEM_NOT_FOUND )
|
||||
DeductPoints( this, GetAPsToJumpFence( this, TRUE ), GetBPsToJumpFence( this, TRUE ) );
|
||||
DeductPoints( this, GetAPsToJumpFence( this, TRUE ), GetBPsToJumpFence( this, TRUE ), SP_MOVEMENT_INTERRUPT );
|
||||
else
|
||||
DeductPoints( this, GetAPsToJumpFence( this, FALSE ), GetBPsToJumpFence( this, FALSE ) );
|
||||
DeductPoints( this, GetAPsToJumpFence( this, FALSE ), GetBPsToJumpFence( this, FALSE ), SP_MOVEMENT_INTERRUPT );
|
||||
break;
|
||||
|
||||
case JUMPWINDOWS:
|
||||
if((UsingNewInventorySystem() == true) && FindBackpackOnSoldier( this ) != ITEM_NOT_FOUND )
|
||||
DeductPoints( this, GetAPsToJumpThroughWindows( this, TRUE ), GetBPsToJumpThroughWindows( this, TRUE ) );
|
||||
DeductPoints( this, GetAPsToJumpThroughWindows( this, TRUE ), GetBPsToJumpThroughWindows( this, TRUE ), SP_MOVEMENT_INTERRUPT );
|
||||
else
|
||||
DeductPoints( this, GetAPsToJumpThroughWindows( this, FALSE ), GetBPsToJumpThroughWindows( this, FALSE ) );
|
||||
DeductPoints( this, GetAPsToJumpThroughWindows( this, FALSE ), GetBPsToJumpThroughWindows( this, FALSE ), SP_MOVEMENT_INTERRUPT );
|
||||
break;
|
||||
|
||||
// Deduct aps for falling down....
|
||||
case FALLBACK_HIT_STAND:
|
||||
case FALLFORWARD_FROMHIT_STAND:
|
||||
|
||||
DeductPoints( this, APBPConstants[AP_FALL_DOWN], APBPConstants[BP_FALL_DOWN] );
|
||||
DeductPoints( this, APBPConstants[AP_FALL_DOWN], APBPConstants[BP_FALL_DOWN], DISABLED_INTERRUPT );
|
||||
break;
|
||||
|
||||
case FALLFORWARD_FROMHIT_CROUCH:
|
||||
|
||||
DeductPoints( this, (APBPConstants[AP_FALL_DOWN]/2), (APBPConstants[BP_FALL_DOWN]/2) );
|
||||
DeductPoints( this, (APBPConstants[AP_FALL_DOWN]/2), (APBPConstants[BP_FALL_DOWN]/2), DISABLED_INTERRUPT );
|
||||
break;
|
||||
|
||||
case QUEEN_SWIPE:
|
||||
@@ -3771,7 +3831,7 @@ BOOLEAN SOLDIERTYPE::EVENT_InitNewSoldierAnim( UINT16 usNewState, UINT16 usStart
|
||||
// disable sight
|
||||
gTacticalStatus.uiFlags |= DISALLOW_SIGHT;
|
||||
|
||||
DeductPoints( this, GetAPsToClimbRoof( this, TRUE), GetBPsToClimbRoof( this, TRUE) ); // changed by SANDRO
|
||||
DeductPoints( this, GetAPsToClimbRoof( this, TRUE), GetBPsToClimbRoof( this, TRUE), SP_MOVEMENT_INTERRUPT ); // changed by SANDRO
|
||||
break;
|
||||
|
||||
case CLIMBUPROOF:
|
||||
@@ -3779,7 +3839,7 @@ BOOLEAN SOLDIERTYPE::EVENT_InitNewSoldierAnim( UINT16 usNewState, UINT16 usStart
|
||||
// disable sight
|
||||
gTacticalStatus.uiFlags |= DISALLOW_SIGHT;
|
||||
|
||||
DeductPoints( this, GetAPsToClimbRoof( this, FALSE), GetBPsToClimbRoof( this, FALSE) ); // changed by SANDRO
|
||||
DeductPoints( this, GetAPsToClimbRoof( this, FALSE), GetBPsToClimbRoof( this, FALSE), SP_MOVEMENT_INTERRUPT ); // changed by SANDRO
|
||||
break;
|
||||
|
||||
case JUMPDOWNWALL:
|
||||
@@ -3787,7 +3847,7 @@ BOOLEAN SOLDIERTYPE::EVENT_InitNewSoldierAnim( UINT16 usNewState, UINT16 usStart
|
||||
// disable sight
|
||||
gTacticalStatus.uiFlags |= DISALLOW_SIGHT;
|
||||
|
||||
DeductPoints( this, GetAPsToJumpWall( this, TRUE), GetBPsToJumpWall( this, TRUE) );
|
||||
DeductPoints( this, GetAPsToJumpWall( this, TRUE), GetBPsToJumpWall( this, TRUE), SP_MOVEMENT_INTERRUPT );
|
||||
break;
|
||||
|
||||
case JUMPUPWALL:
|
||||
@@ -3795,7 +3855,7 @@ BOOLEAN SOLDIERTYPE::EVENT_InitNewSoldierAnim( UINT16 usNewState, UINT16 usStart
|
||||
// disable sight
|
||||
gTacticalStatus.uiFlags |= DISALLOW_SIGHT;
|
||||
|
||||
DeductPoints( this, GetAPsToJumpWall( this, FALSE), GetBPsToJumpWall( this, FALSE) );
|
||||
DeductPoints( this, GetAPsToJumpWall( this, FALSE), GetBPsToJumpWall( this, FALSE), SP_MOVEMENT_INTERRUPT );
|
||||
break;
|
||||
|
||||
case JUMP_OVER_BLOCKING_PERSON:
|
||||
@@ -3804,7 +3864,7 @@ BOOLEAN SOLDIERTYPE::EVENT_InitNewSoldierAnim( UINT16 usNewState, UINT16 usStart
|
||||
{
|
||||
INT32 usNewGridNo;
|
||||
|
||||
DeductPoints( this, GetAPsToJumpOver( this ), APBPConstants[BP_JUMP_OVER] ); // changed by SANDRO
|
||||
DeductPoints( this, GetAPsToJumpOver( this ), APBPConstants[BP_JUMP_OVER], SP_MOVEMENT_INTERRUPT ); // changed by SANDRO
|
||||
|
||||
usNewGridNo = NewGridNo( this->sGridNo, DirectionInc( this->ubDirection ) );
|
||||
usNewGridNo = NewGridNo( usNewGridNo, DirectionInc( this->ubDirection ) );
|
||||
@@ -4451,6 +4511,9 @@ void SOLDIERTYPE::SetSoldierGridNo( INT32 sNewGridNo, BOOLEAN fForceRemove )
|
||||
switch( this->usAnimState )
|
||||
{
|
||||
case WALKING:
|
||||
case WALKING_PISTOL_RDY:
|
||||
case WALKING_RIFLE_RDY:
|
||||
case WALKING_DUAL_RDY:
|
||||
case RUNNING:
|
||||
|
||||
// IN deep water, swim!
|
||||
@@ -4637,6 +4700,27 @@ void SOLDIERTYPE::EVENT_FireSoldierWeapon( INT32 sTargetGridNo )
|
||||
// Ready weapon
|
||||
this->SoldierReadyWeapon( sTargetXPos, sTargetYPos, FALSE );
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// SANDRO - hack! - an interrupt pending before shot
|
||||
if ( gGameExternalOptions.fImprovedInterruptSystem )
|
||||
{
|
||||
if ( ResolvePendingInterrupt( this, BEFORESHOT_INTERRUPT ) )
|
||||
{
|
||||
this->usPendingAnimation = NO_PENDING_ANIMATION;
|
||||
this->ubPendingDirection = NO_PENDING_DIRECTION;
|
||||
// "artificially" set lock ui flag
|
||||
if (this->bTeam == gbPlayerNum)
|
||||
{
|
||||
AddTopMessage( COMPUTER_INTERRUPT_MESSAGE, Message[STR_INTERRUPT] );
|
||||
guiPendingOverrideEvent = LU_BEGINUILOCK;
|
||||
HandleTacticalUI( );
|
||||
}
|
||||
// return as we are not gonna shoot if interrupted
|
||||
return;
|
||||
}
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// IF WE ARE AN NPC, SLIDE VIEW TO SHOW WHO IS SHOOTING
|
||||
{
|
||||
//if ( this->flags.fDoSpread )
|
||||
@@ -5408,11 +5492,15 @@ void SOLDIERTYPE::EVENT_SoldierGotHit( UINT16 usWeaponIndex, INT16 sDamage, INT1
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
sDamage = sDamage / PUNCH_REAL_DAMAGE_PORTION;
|
||||
#ifdef JA2UB
|
||||
//Ja25: No meanwhiles
|
||||
#else
|
||||
if ( AreInMeanwhile() && gCurrentMeanwhileDef.ubMeanwhileID == INTERROGATION )
|
||||
{
|
||||
sBreathLoss = 0;
|
||||
sDamage /= 2;
|
||||
}
|
||||
#endif
|
||||
ubReason = TAKE_DAMAGE_HANDTOHAND;
|
||||
}
|
||||
// marke added one 'or' for explosive ammo. variation of: AmmoTypes[this->inv[this->ubAttackingHand ][0]->data.gun.ubGunAmmoType].explosionSize > 1
|
||||
@@ -6013,7 +6101,7 @@ void SoldierGotHitGunFire( SOLDIERTYPE *pSoldier, UINT16 usWeaponIndex, INT16 sD
|
||||
// HEADROCK HAM 3.2: Critical legshots cost an extra number of APs, based on shot damage.
|
||||
if (gGameExternalOptions.fCriticalLegshotCausesAPLoss)
|
||||
{
|
||||
DeductPoints( pSoldier, APBPConstants[AP_LOSS_PER_LEGSHOT_DAMAGE]*sDamage, 0);
|
||||
DeductPoints( pSoldier, APBPConstants[AP_LOSS_PER_LEGSHOT_DAMAGE]*sDamage, 0, DISABLED_INTERRUPT);
|
||||
}
|
||||
SoldierCollapse( pSoldier );
|
||||
return;
|
||||
@@ -6457,7 +6545,16 @@ BOOLEAN SOLDIERTYPE::EVENT_InternalGetNewSoldierPath( INT32 sDestGridNo, UINT16
|
||||
}
|
||||
|
||||
// If we were aiming, end aim!
|
||||
usAnimState = PickSoldierReadyAnimation( this, TRUE );
|
||||
// SANDRO - we may try to move with raised weapon, so don't end aim after
|
||||
if ( (gAnimControl[ this->usAnimState ].uiFlags & ( ANIM_FIREREADY | ANIM_FIRE )) &&
|
||||
(usMoveAnimState == WALKING || usMoveAnimState == SIDE_STEP ) && !( this->MercInWater( )) )
|
||||
{
|
||||
usAnimState = INVALID_ANIMATION;
|
||||
}
|
||||
else
|
||||
{
|
||||
usAnimState = PickSoldierReadyAnimation( this, TRUE );
|
||||
}
|
||||
|
||||
// Add a pending animation first!
|
||||
// Only if we were standing!
|
||||
@@ -6649,7 +6746,8 @@ void SOLDIERTYPE::EVENT_InternalSetSoldierDestination( UINT16 usNewDirection, BO
|
||||
|
||||
|
||||
// OK, ATE: If we are side_stepping, calculate a NEW desired direction....
|
||||
if ( this->bReverse && (usAnimState == SIDE_STEP || usAnimState == ROLL_PRONE_R || usAnimState == ROLL_PRONE_L) )
|
||||
if ( this->bReverse && (usAnimState == SIDE_STEP || usAnimState == ROLL_PRONE_R || usAnimState == ROLL_PRONE_L
|
||||
|| usAnimState == SIDE_STEP_PISTOL_RDY || usAnimState == SIDE_STEP_RIFLE_RDY || usAnimState == SIDE_STEP_DUAL_RDY ) )
|
||||
{
|
||||
UINT8 ubPerpDirection;
|
||||
|
||||
@@ -6757,7 +6855,8 @@ INT8 MultiTiledTurnDirection( SOLDIERTYPE * pSoldier, INT8 bStartDirection, INT8
|
||||
void EVENT_InternalSetSoldierDesiredDirection( SOLDIERTYPE *pSoldier, UINT8 ubNewDirection, BOOLEAN fInitalMove, UINT16 usAnimState )
|
||||
{
|
||||
//if ( usAnimState == WALK_BACKWARDS )
|
||||
if ( pSoldier->bReverse && (usAnimState != SIDE_STEP && usAnimState != ROLL_PRONE_R && usAnimState != ROLL_PRONE_L) )
|
||||
if ( pSoldier->bReverse && (usAnimState != SIDE_STEP && usAnimState != ROLL_PRONE_R && usAnimState != ROLL_PRONE_L
|
||||
&& usAnimState != SIDE_STEP_PISTOL_RDY && usAnimState != SIDE_STEP_RIFLE_RDY && usAnimState != SIDE_STEP_DUAL_RDY ) )
|
||||
{
|
||||
// OK, check if we are going to go in the exact opposite than our facing....
|
||||
ubNewDirection = gOppositeDirection[ ubNewDirection ];
|
||||
@@ -7055,6 +7154,9 @@ void SOLDIERTYPE::EVENT_BeginMercTurn( BOOLEAN fFromRealTime, INT32 iRealTimeCou
|
||||
}
|
||||
|
||||
this->CalcNewActionPoints( );
|
||||
|
||||
// SANDRO - Improved Interrupt System - reset interrupt counter
|
||||
memset(this->aiData.ubInterruptCounter,0,sizeof(this->aiData.ubInterruptCounter));
|
||||
|
||||
// HEADROCK HAM 3.6: If this soldier is in a "moving" animation, but has not moved any tiles
|
||||
// in the previous turn, then the player has apparently forgotten that he was moving.
|
||||
@@ -7978,6 +8080,9 @@ void CalculateSoldierAniSpeed( SOLDIERTYPE *pSoldier, SOLDIERTYPE *pStatsSoldier
|
||||
return;
|
||||
|
||||
case WALKING:
|
||||
case WALKING_PISTOL_RDY:
|
||||
case WALKING_RIFLE_RDY:
|
||||
case WALKING_DUAL_RDY:
|
||||
|
||||
// Adjust based on body type
|
||||
bAdditional = (UINT8)( gubAnimWalkSpeeds[ pStatsSoldier->ubBodyType ].sSpeed );
|
||||
@@ -8700,13 +8805,15 @@ void SOLDIERTYPE::BeginSoldierGetup( void )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef JA2UB
|
||||
//Ja25: No meanwhiles
|
||||
#else
|
||||
// ATE: Don't getup if we are in a meanwhile
|
||||
if ( AreInMeanwhile( ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
if ( this->bCollapsed )
|
||||
{
|
||||
if ( this->stats.bLife >= OKLIFE && this->bBreath >= OKBREATH && (this->bSleepDrugCounter == 0) )
|
||||
@@ -8945,13 +9052,15 @@ UINT8 SOLDIERTYPE::SoldierTakeDamage( INT8 bHeight, INT16 sLifeDeduct, INT16 sBr
|
||||
// Turn off
|
||||
this->flags.uiStatusFlags &= ( ~SOLDIER_NPC_SHOOTING );
|
||||
}
|
||||
|
||||
#ifdef JA2UB
|
||||
//Ja25: No meanwhiles
|
||||
#else
|
||||
// CJC: make sure Elliot doesn't bleed to death!
|
||||
if ( ubReason == TAKE_DAMAGE_BLOODLOSS && AreInMeanwhile() )
|
||||
{
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// Calculate bandage
|
||||
bBandage = this->stats.bLifeMax - this->stats.bLife - this->bBleeding;
|
||||
@@ -9136,7 +9245,7 @@ UINT8 SOLDIERTYPE::SoldierTakeDamage( INT8 bHeight, INT16 sLifeDeduct, INT16 sBr
|
||||
// ATE: if the robot, do not deduct
|
||||
if ( !AM_A_ROBOT( this ) )
|
||||
{
|
||||
DeductPoints( this, sAPCost, sBreathLoss , FALSE);
|
||||
DeductPoints( this, sAPCost, sBreathLoss, DISABLED_INTERRUPT );
|
||||
}
|
||||
|
||||
ubCombinedLoss = (UINT8) sLifeDeduct / 10 + sBreathLoss / 2000;
|
||||
@@ -9352,7 +9461,39 @@ UINT8 SOLDIERTYPE::SoldierTakeDamage( INT8 bHeight, INT16 sLifeDeduct, INT16 sBr
|
||||
{
|
||||
DecayIndividualOpplist( this );
|
||||
}
|
||||
|
||||
#ifdef JA2UB
|
||||
//if the attacker is MORRIS, AND he didnt kill the person
|
||||
if( Menptr[ ubAttacker ].ubProfile == 75 ) //MORRIS
|
||||
{
|
||||
//if the soldier is hurt, but not dead
|
||||
if( this->stats.bLife < bOldLife && this->stats.bLife > 0 )
|
||||
{
|
||||
//if he hasnt said his quote #1 before
|
||||
if( !( Menptr[ ubAttacker ].usQuoteSaidExtFlags & SOLDIER_QUOTE_SAID_THOUGHT_KILLED_YOU ) )
|
||||
{
|
||||
//said a flag so morris can say this quote next turn
|
||||
gJa25SaveStruct.fMorrisToSayHurtPlayerQuoteNextTurn = TRUE;
|
||||
|
||||
//Remeber who Morris is saying the quote too
|
||||
gJa25SaveStruct.ubPlayerMorrisHurt = this->ubProfile;
|
||||
}
|
||||
}
|
||||
|
||||
// else if morris is to say the quote, he hasnt said it yet and he just killed the person he WAS going to say it to
|
||||
else if( gJa25SaveStruct.fMorrisToSayHurtPlayerQuoteNextTurn &&
|
||||
gJa25SaveStruct.ubPlayerMorrisHurt == this->ubProfile &&
|
||||
this->stats.bLife <= 0 &&
|
||||
!( Menptr[ ubAttacker ].usQuoteSaidExtFlags & SOLDIER_QUOTE_SAID_THOUGHT_KILLED_YOU ) )
|
||||
{
|
||||
//said a flag so morris can say this quote next turn
|
||||
gJa25SaveStruct.fMorrisToSayHurtPlayerQuoteNextTurn = FALSE;
|
||||
|
||||
//Remeber who Morris is saying the quote too
|
||||
gJa25SaveStruct.ubPlayerMorrisHurt = NO_PROFILE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return( ubCombinedLoss );
|
||||
}
|
||||
@@ -11173,7 +11314,12 @@ void SOLDIERTYPE::EVENT_SoldierBeginPunchAttack( INT32 sGridNo, UINT8 ubDirectio
|
||||
fMartialArtist = TRUE;
|
||||
}
|
||||
|
||||
//Ja25 No meanwhiles
|
||||
#ifdef JA2UB
|
||||
if ( fMartialArtist && !Item[usItem].crowbar && this->ubBodyType == REGMALE)
|
||||
#else
|
||||
if ( fMartialArtist && !AreInMeanwhile( ) && !Item[usItem].crowbar && this->ubBodyType == REGMALE ) // SANDRO - added check for body type
|
||||
#endif
|
||||
{
|
||||
// Are we in attack mode yet?
|
||||
if ( this->usAnimState != NINJA_BREATH && gAnimControl[ this->usAnimState ].ubHeight == ANIM_STAND && gAnimControl[ pTSoldier->usAnimState ].ubHeight != ANIM_PRONE )
|
||||
@@ -11269,6 +11415,7 @@ void SOLDIERTYPE::EVENT_SoldierBeginKnifeThrowAttack( INT32 sGridNo, UINT8 ubDir
|
||||
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("!!!!!!! Starting knifethrow attack, bullets left %d", this->bBulletsLeft) );
|
||||
DebugAttackBusy( String( "Begin knife throwing attack: ATB %d\n", gTacticalStatus.ubAttackBusyCount) );
|
||||
|
||||
// SANDRO - new animation for throwing for big mercs by PasHancock
|
||||
if ( this->ubBodyType == BIGMALE && ((this->ubProfile != NO_PROFILE && gMercProfiles[ this->ubProfile ].bCharacterTrait == CHAR_TRAIT_SHOWOFF) || (HAS_SKILL_TRAIT( this, THROWING_NT ) && gGameOptions.fNewTraitSystem) || (HAS_SKILL_TRAIT( this, THROWING_OT ) && !gGameOptions.fNewTraitSystem) ) )
|
||||
{
|
||||
this->EVENT_InitNewSoldierAnim( THROW_KNIFE_SP_BM, 0 , FALSE );
|
||||
@@ -11963,7 +12110,7 @@ void SOLDIERTYPE::HaultSoldierFromSighting( BOOLEAN fFromSightingEnemy )
|
||||
SStopMerc.sXPos=this->sX;
|
||||
SStopMerc.sYPos=this->sY;
|
||||
//AddGameEvent( S_STOP_MERC, 0, &SStopMerc ); //hayden.
|
||||
if(this->ubID>=120 || (!is_server && this->ubID >=20)) return;//hayden
|
||||
if((is_networked) && (this->ubID>=120 || (!is_server && this->ubID >=20))) return;//hayden
|
||||
if(is_client)send_stop(&SStopMerc);
|
||||
|
||||
// If we are a 'specialmove... ignore...
|
||||
@@ -13734,7 +13881,7 @@ BOOLEAN SOLDIERTYPE::PlayerSoldierStartTalking( UINT8 ubTargetID, BOOLEAN fValid
|
||||
else
|
||||
{
|
||||
// Deduct points from our guy....
|
||||
DeductPoints( this, sAPCost, 0 );
|
||||
DeductPoints( this, sAPCost, 0, UNTRIGGERED_INTERRUPT );
|
||||
apsDeducted = TRUE;
|
||||
|
||||
StartCivQuote( pTSoldier );
|
||||
@@ -13745,7 +13892,7 @@ BOOLEAN SOLDIERTYPE::PlayerSoldierStartTalking( UINT8 ubTargetID, BOOLEAN fValid
|
||||
// WANNE: This fixes the bug, that APs for talking are not always deducted.
|
||||
if (!apsDeducted)
|
||||
{
|
||||
DeductPoints( this, sAPCost, 0 );
|
||||
DeductPoints( this, sAPCost, 0, UNTRIGGERED_INTERRUPT );
|
||||
apsDeducted = TRUE;
|
||||
}
|
||||
|
||||
@@ -14440,11 +14587,19 @@ BOOLEAN HAS_SKILL_TRAIT( SOLDIERTYPE * pSoldier, UINT8 uiSkillTraitNumber )
|
||||
return( FALSE );
|
||||
|
||||
INT8 bNumMajorTraitsCounted = 0;
|
||||
INT8 bMaxTraits = gSkillTraitValues.ubMaxNumberOfTraits;
|
||||
INT8 bMaxMajorTraits = gSkillTraitValues.ubNumberOfMajorTraitsAllowed;
|
||||
// special case for Dr.Q - he's allowed to have 3 major traits and one minor for total by default
|
||||
if ( pSoldier->ubProfile == 33 && gSkillTraitValues.fAllowDrQTraitsException )
|
||||
{
|
||||
bMaxTraits++;
|
||||
bMaxMajorTraits++;
|
||||
}
|
||||
|
||||
// check old/new traits
|
||||
if (gGameOptions.fNewTraitSystem)
|
||||
{
|
||||
for ( INT8 bCnt = 0; bCnt < gSkillTraitValues.ubMaxNumberOfTraits; bCnt++ )
|
||||
for ( INT8 bCnt = 0; bCnt < min(30,bMaxTraits); bCnt++ )
|
||||
{
|
||||
if ( uiSkillTraitNumber > 0 && uiSkillTraitNumber <= NUM_MAJOR_TRAITS )
|
||||
{
|
||||
@@ -14457,7 +14612,7 @@ BOOLEAN HAS_SKILL_TRAIT( SOLDIERTYPE * pSoldier, UINT8 uiSkillTraitNumber )
|
||||
bNumMajorTraitsCounted++;
|
||||
}
|
||||
// if we exceeded the allowed number of major traits, ignore the rest of them
|
||||
if ( bNumMajorTraitsCounted >= gSkillTraitValues.ubNumberOfMajorTraitsAllowed )
|
||||
if ( bNumMajorTraitsCounted >= min(20,bMaxMajorTraits) )
|
||||
{
|
||||
break;
|
||||
}
|
||||
@@ -14488,11 +14643,19 @@ INT8 NUM_SKILL_TRAITS( SOLDIERTYPE * pSoldier, UINT8 uiSkillTraitNumber )
|
||||
|
||||
INT8 bNumberOfTraits = 0;
|
||||
INT8 bNumMajorTraitsCounted = 0;
|
||||
INT8 bMaxTraits = gSkillTraitValues.ubMaxNumberOfTraits;
|
||||
INT8 bMaxMajorTraits = gSkillTraitValues.ubNumberOfMajorTraitsAllowed;
|
||||
// special case for Dr.Q - he's allowed to have 3 major traits and one minor for total by default
|
||||
if ( pSoldier->ubProfile == 33 && gSkillTraitValues.fAllowDrQTraitsException )
|
||||
{
|
||||
bMaxTraits++;
|
||||
bMaxMajorTraits++;
|
||||
}
|
||||
|
||||
// check old/new traits
|
||||
if (gGameOptions.fNewTraitSystem)
|
||||
{
|
||||
for ( INT8 bCnt = 0; bCnt < gSkillTraitValues.ubMaxNumberOfTraits; bCnt++ )
|
||||
for ( INT8 bCnt = 0; bCnt < min(30,bMaxTraits); bCnt++ )
|
||||
{
|
||||
if ( uiSkillTraitNumber > 0 && uiSkillTraitNumber <= NUM_MAJOR_TRAITS )
|
||||
{
|
||||
@@ -14506,7 +14669,7 @@ INT8 NUM_SKILL_TRAITS( SOLDIERTYPE * pSoldier, UINT8 uiSkillTraitNumber )
|
||||
bNumMajorTraitsCounted++;
|
||||
}
|
||||
// if we exceeded the allowed number of major traits, ignore the rest of them
|
||||
if ( bNumMajorTraitsCounted >= gSkillTraitValues.ubNumberOfMajorTraitsAllowed )
|
||||
if ( bNumMajorTraitsCounted >= min(20,bMaxMajorTraits) )
|
||||
{
|
||||
break;
|
||||
}
|
||||
@@ -14761,4 +14924,250 @@ UINT8 RegainDamagedStats( SOLDIERTYPE * pSoldier, UINT16 usAmountRegainedHundred
|
||||
// Done, return what we healed
|
||||
return( bStatsReturned );
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// SANDRO - Improved Interrupt System
|
||||
/////////////////////////////////////////
|
||||
BOOLEAN ResolvePendingInterrupt( SOLDIERTYPE * pSoldier, UINT8 ubInterruptType )
|
||||
{
|
||||
// real time or not in combat? disable and clear
|
||||
if (!(gTacticalStatus.uiFlags & TURNBASED) ||
|
||||
!(gTacticalStatus.uiFlags & INCOMBAT) )
|
||||
{
|
||||
gTacticalStatus.ubInterruptPending = DISABLED_INTERRUPT;
|
||||
ClearIntList();
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
// invalid guy
|
||||
if ( pSoldier == NULL )
|
||||
{
|
||||
//ClearIntList();
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
// can't be interrupted if it's not our turn at all
|
||||
if ( gTacticalStatus.ubCurrentTeam != pSoldier->bTeam )
|
||||
{
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
// no interrupt called or not gonna trigger it now
|
||||
if ( gTacticalStatus.ubInterruptPending == DISABLED_INTERRUPT ||
|
||||
gTacticalStatus.ubInterruptPending == UNTRIGGERED_INTERRUPT )
|
||||
{
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
// if the interrupt called match the type we are trying to resolve..
|
||||
if ( gTacticalStatus.ubInterruptPending == ubInterruptType || ubInterruptType == INSTANT_INTERRUPT )
|
||||
{
|
||||
/////////////////////////////
|
||||
// Gather all interrupters //
|
||||
/////////////////////////////
|
||||
SOLDIERTYPE *pInterrupter;
|
||||
UINT8 ubInterruptersFound = 0;
|
||||
UINT8 ubaInterruptersList[64];
|
||||
UINT16 uCnt = 0, uiReactionTime;
|
||||
INT16 iInjuryPenalty;
|
||||
|
||||
for ( uCnt = 0; uCnt <= MAX_NUM_SOLDIERS; uCnt++ )
|
||||
{
|
||||
// first find all guys who can see us
|
||||
pInterrupter = MercPtrs[ uCnt ];
|
||||
if ( pInterrupter == NULL )
|
||||
continue; // not valid
|
||||
if ( pInterrupter->stats.bLife < OKLIFE || pInterrupter->bCollapsed || !pInterrupter->bActive || !pInterrupter->bInSector || pInterrupter->bActionPoints < 4 )
|
||||
continue; // not active
|
||||
if ( pSoldier->bTeam == pInterrupter->bTeam )
|
||||
continue; // same team
|
||||
if ( pSoldier->bSide == pInterrupter->bSide )
|
||||
continue; // not enemy
|
||||
if ( CONSIDERED_NEUTRAL( pSoldier, pInterrupter ) )
|
||||
continue; // neutral
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Calculate Reaction Time (i.e. interrupt counter length) //
|
||||
/////////////////////////////////////////////////////////////
|
||||
|
||||
// set base value ( interrupt per every X APs an enemy uses )
|
||||
if ( pInterrupter->aiData.bOppList[pSoldier->ubID] == SEEN_CURRENTLY ) // if we see him
|
||||
{
|
||||
uiReactionTime = gGameExternalOptions.ubBasicReactionTimeLengthIIS;
|
||||
}
|
||||
else // if not seen the length is higher (we don't want to interrupt in most cases here)
|
||||
{
|
||||
uiReactionTime = (gGameExternalOptions.ubBasicReactionTimeLengthIIS * 2);
|
||||
}
|
||||
uiReactionTime = uiReactionTime * 10; // x10 ... we will divide by 10 after all adjustments done
|
||||
// adjust based on Agility
|
||||
if ( pInterrupter->stats.bAgility >= 80 )
|
||||
{
|
||||
uiReactionTime = (uiReactionTime * (100 - (2 * (pInterrupter->stats.bAgility - 80)))/100);
|
||||
}
|
||||
else if ( pInterrupter->stats.bAgility < 80 && pInterrupter->stats.bAgility > 50 )
|
||||
{
|
||||
uiReactionTime = (uiReactionTime * (100 + (2 * (80 - pInterrupter->stats.bAgility)))/100);
|
||||
}
|
||||
else
|
||||
{
|
||||
uiReactionTime = (uiReactionTime * 8/5);
|
||||
}
|
||||
// adjust based on APs left
|
||||
// at full possible APs no adjustement (100% applies), +1% length per every 2% of APs down from full
|
||||
uiReactionTime = (uiReactionTime * (100 + (50 - (50 * pInterrupter->bActionPoints / pInterrupter->CalcActionPoints())) ) /100);
|
||||
// adjust based on injuries
|
||||
if (pInterrupter->stats.bLife < pInterrupter->stats.bLifeMax)
|
||||
{
|
||||
// OK, this looks a bit complicated..
|
||||
// our HP lost minus half of the bandaged part gives us 2% longer reaction time per 1% of our health down from full health
|
||||
// this penalty is however slightly reduced by our experience level
|
||||
iInjuryPenalty = ( 200 * (pInterrupter->stats.bLifeMax - pInterrupter->stats.bLife + ((pInterrupter->stats.bLifeMax - pInterrupter->stats.bLife - pInterrupter->bBleeding) / 2))) / (pInterrupter->stats.bLifeMax);
|
||||
uiReactionTime = (uiReactionTime * (100 + iInjuryPenalty * (100 - (3 * EffectiveExpLevel( pInterrupter ))) / 100) / 100);
|
||||
}
|
||||
// adjust by breath down
|
||||
if (pSoldier->bBreath < 100)
|
||||
{
|
||||
// +1% per 2 points of breath down
|
||||
uiReactionTime = (uiReactionTime * (100 + ((100 - pSoldier->bBreath)/2)) /100);
|
||||
}
|
||||
// adjust for getting aid, being in gas or being in shock
|
||||
if ( pInterrupter->flags.uiStatusFlags & SOLDIER_GASSED )
|
||||
uiReactionTime = (uiReactionTime * (100 + AIM_PENALTY_GASSED) /100);
|
||||
if (pInterrupter->ubServiceCount > 0)
|
||||
uiReactionTime = (uiReactionTime * (100 + AIM_PENALTY_GETTINGAID) /100);
|
||||
if (pInterrupter->aiData.bShock)
|
||||
uiReactionTime = (uiReactionTime * (100 + (pInterrupter->aiData.bShock * 20)) /100); // this is severe, 20% per point
|
||||
// Phlegmatic characters has slightly longer reaction time
|
||||
if ( pSoldier->ubProfile != NO_PROFILE )
|
||||
{
|
||||
if ( gMercProfiles[ pSoldier->ubProfile ].bCharacterTrait == CHAR_TRAIT_PHLEGMATIC )
|
||||
{
|
||||
uiReactionTime = ((uiReactionTime * 110) / 100);
|
||||
}
|
||||
}
|
||||
// finally divide back by 10 to get the needed result (round properly)
|
||||
uiReactionTime = ((uiReactionTime + 5) / 10);
|
||||
|
||||
/////////////////////////////////////////////
|
||||
// Check if we reached reaction time value //
|
||||
/////////////////////////////////////////////
|
||||
|
||||
// if we have hit the needed amount, the actual interrupt occurs for the observer
|
||||
if ( pInterrupter->aiData.ubInterruptCounter[pSoldier->ubID] >= uiReactionTime )
|
||||
{
|
||||
///////////////////////////
|
||||
// Success! Add to list! //
|
||||
///////////////////////////
|
||||
|
||||
// the soldier to be interrupted is added to the list (once only)
|
||||
if ( ubInterruptersFound == 0)
|
||||
{
|
||||
AddToIntList( pSoldier->ubID, FALSE, TRUE);
|
||||
}
|
||||
ubaInterruptersList[ubInterruptersFound] = pInterrupter->ubID;
|
||||
ubInterruptersFound++;
|
||||
|
||||
// add the observer who got the interrupt
|
||||
AddToIntList( pInterrupter->ubID, TRUE, TRUE);
|
||||
// reset the counter
|
||||
pInterrupter->aiData.ubInterruptCounter[pSoldier->ubID] = 0;
|
||||
}
|
||||
}
|
||||
if ( ubInterruptersFound > 0 )
|
||||
{
|
||||
////////////////////////////////////////////////
|
||||
// Check for possible "Collective Interrupts" //
|
||||
////////////////////////////////////////////////
|
||||
if ( gGameExternalOptions.fAllowCollectiveInterrupts )
|
||||
{
|
||||
SOLDIERTYPE *pTeammate;
|
||||
UINT16 uCnt2 = 0, usColIntChance = 0;
|
||||
UINT8 ubOriginalInterruptersCount = ubInterruptersFound, uCnt3 = 0;
|
||||
BOOLEAN fAlreadyIn;
|
||||
|
||||
for ( uCnt = 0; uCnt < ubOriginalInterruptersCount; uCnt++ )
|
||||
{
|
||||
pInterrupter = MercPtrs[ ubaInterruptersList[uCnt] ];
|
||||
|
||||
uCnt2 = gTacticalStatus.Team[ pInterrupter->bTeam ].bFirstID;
|
||||
for ( pTeammate = MercPtrs[ uCnt2 ]; uCnt2 <= gTacticalStatus.Team[ pInterrupter->bTeam ].bLastID; uCnt2++,pTeammate++)
|
||||
{
|
||||
if ( pTeammate == NULL )
|
||||
continue; // not valid
|
||||
if ( pTeammate->bTeam != pInterrupter->bTeam )
|
||||
continue; // little paranoya check here
|
||||
if ( pTeammate->stats.bLife < OKLIFE || pTeammate->bCollapsed || !pTeammate->bActive || !pTeammate->bInSector || pTeammate->bActionPoints < 4 )
|
||||
continue; // not active
|
||||
|
||||
// check if we haven't been added to the list already
|
||||
fAlreadyIn = FALSE;
|
||||
for ( uCnt3 = 0; uCnt3 < ubInterruptersFound; uCnt3++ )
|
||||
{
|
||||
if ( pTeammate->ubID == ubaInterruptersList[uCnt3] )
|
||||
{
|
||||
fAlreadyIn = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// if we are close enough
|
||||
if ( !fAlreadyIn && PythSpacesAway( pInterrupter->sGridNo, pTeammate->sGridNo ) <= 5 )
|
||||
{
|
||||
// calculate the chance
|
||||
// we would have base chance 100% (if both have maxed stats)
|
||||
// 0-30% is determined by Leadership of the original interrupted - i.e. how well and if he can "inform" us
|
||||
// 0-20% is determined by his Experience Level
|
||||
// 0-20% is determined by our Experience Level - i.e how well can we realize that we must act
|
||||
// 0-20% is determined by our Agility - can our body react so swiftly at all
|
||||
// 0-10% is determined by our Wisdom - do we have enough mental agility as well?
|
||||
usColIntChance = 10*( ( (pInterrupter->stats.bLeadership * 3) +
|
||||
(EffectiveExpLevel( pInterrupter ) * 20) +
|
||||
(EffectiveExpLevel( pTeammate ) * 20) +
|
||||
(pTeammate->stats.bAgility * 2) +
|
||||
(pTeammate->stats.bWisdom) ) / 100 );
|
||||
// add bonus per Squadleader trait of the original interrupter
|
||||
if ( HAS_SKILL_TRAIT( pInterrupter, SQUADLEADER_NT ) && gGameOptions.fNewTraitSystem )
|
||||
{
|
||||
usColIntChance += gSkillTraitValues.ubSLCollectiveInterruptsBonus * NUM_SKILL_TRAITS( pInterrupter, SQUADLEADER_NT );
|
||||
}
|
||||
if ( PreChance(usColIntChance))
|
||||
{
|
||||
ubaInterruptersList[ubInterruptersFound] = pTeammate->ubID;
|
||||
ubInterruptersFound++;
|
||||
// if he can react on collective interrupt, give it to him
|
||||
AddToIntList( pTeammate->ubID, TRUE, TRUE);
|
||||
// reset the counter for him
|
||||
pTeammate->aiData.ubInterruptCounter[pSoldier->ubID] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////
|
||||
// OK, done, all interrupters added, SEND! //
|
||||
/////////////////////////////////////////////
|
||||
|
||||
// remove AI control from the interrupted guy just in case may not be neccessary, but it's harmless anyway
|
||||
if ( (gTacticalStatus.ubCurrentTeam != pSoldier->bTeam) && !(gTacticalStatus.Team[ gTacticalStatus.ubCurrentTeam ].bHuman) )
|
||||
{
|
||||
if ( pSoldier->flags.uiStatusFlags & SOLDIER_UNDERAICONTROL )
|
||||
{
|
||||
pSoldier->flags.uiStatusFlags &= (~SOLDIER_UNDERAICONTROL);
|
||||
}
|
||||
}
|
||||
// reset
|
||||
gTacticalStatus.ubInterruptPending = DISABLED_INTERRUPT;
|
||||
// start interrupt
|
||||
DoneAddingToIntList( pSoldier, TRUE, 1 );
|
||||
|
||||
return( TRUE );
|
||||
}
|
||||
else // no interrupters found, reset until next occasion
|
||||
{
|
||||
// reset
|
||||
gTacticalStatus.ubInterruptPending = DISABLED_INTERRUPT;
|
||||
}
|
||||
}
|
||||
return( FALSE );
|
||||
}
|
||||
Reference in New Issue
Block a user