Merge branch 'master' into ExtraMercs

This commit is contained in:
Asdow
2024-11-09 13:44:53 +02:00
371 changed files with 6539 additions and 13390 deletions
+170 -114
View File
@@ -12,7 +12,6 @@
#include "Animation Cache.h"
#include "Animation Data.h"
#include "Animation Control.h"
#include "container.h"
#define _USE_MATH_DEFINES // for C
#include <math.h>
#include "pathai.h"
@@ -379,6 +378,10 @@ unsigned int Inventory::size( ) const {
return inv.size( );
}
auto Inventory::get() const -> const std::vector<OBJECTTYPE>& {
return inv;
}
// Assignment operator
Inventory& Inventory::operator=(const Inventory& src)
{
@@ -1339,7 +1342,7 @@ MERCPROFILESTRUCT& MERCPROFILESTRUCT::operator=(const OLD_MERCPROFILESTRUCT_101&
this->bSex = src.bSex;
this->bArmourAttractiveness = src.bArmourAttractiveness;
this->ubMiscFlags2 = src.ubMiscFlags2;
this->bEvolution = src.bEvolution;
this->fRegresses = src.bEvolution == 2; // formerly, 2 == CharacterEvolution::DEVOLVES
this->ubMiscFlags = src.ubMiscFlags;
this->bSexist = src.bSexist;
this->bLearnToHate = src.bLearnToHate;
@@ -3014,7 +3017,7 @@ BOOLEAN SOLDIERTYPE::EVENT_InitNewSoldierAnim( UINT16 usNewState, UINT16 usStart
}
else
{
if (Item[usItem].flare ||
if (ItemIsFlare(usItem) ||
Explosive[Item[usItem].ubClassIndex].ubType == EXPLOSV_SIGNAL_SMOKE ||
Explosive[Item[usItem].ubClassIndex].ubType == EXPLOSV_FLARE)
{
@@ -3156,7 +3159,7 @@ BOOLEAN SOLDIERTYPE::EVENT_InitNewSoldierAnim( UINT16 usNewState, UINT16 usStart
// Going from shoulder stance to hip stance
else if ( usNewState == READY_ALTERNATIVE_STAND && (gAnimControl[this->usAnimState].uiFlags & (ANIM_FIREREADY | ANIM_FIRE)) )
{
if ( Item[this->inv[HANDPOS].usItem].twohanded )
if (ItemIsTwoHanded(this->inv[HANDPOS].usItem))
usStartingAniCode = 1;
else
usStartingAniCode = 2;
@@ -3275,7 +3278,7 @@ BOOLEAN SOLDIERTYPE::EVENT_InitNewSoldierAnim( UINT16 usNewState, UINT16 usStart
// 1) We have a rifle in hand...
//usItem = this->inv[ HANDPOS ].usItem;
if ( this->inv[HANDPOS].exists( ) == true && (Item[usItem].twohanded) && !Item[usItem].rocketlauncher )
if ( this->inv[HANDPOS].exists( ) == true && ItemIsTwoHanded(usItem) && !ItemIsRocketLauncher(usItem) )
{
// Switch on height!
switch ( gAnimControl[this->usAnimState].ubEndHeight )
@@ -3298,7 +3301,7 @@ BOOLEAN SOLDIERTYPE::EVENT_InitNewSoldierAnim( UINT16 usNewState, UINT16 usStart
// 1) We have a rifle in hand...
//usItem = this->inv[ HANDPOS ].usItem;
if ( this->inv[HANDPOS].exists( ) == true && (Item[usItem].twohanded) && !Item[usItem].rocketlauncher )
if ( this->inv[HANDPOS].exists( ) == true && ItemIsTwoHanded(usItem) && !ItemIsRocketLauncher(usItem) )
{
// Switch on height!
switch ( gAnimControl[this->usAnimState].ubEndHeight )
@@ -3426,10 +3429,10 @@ BOOLEAN SOLDIERTYPE::EVENT_InitNewSoldierAnim( UINT16 usNewState, UINT16 usStart
if ( this->inv[HANDPOS].exists( ) == true )
{
if ( Item[usItem].usItemClass == IC_GUN && !Item[usItem].rocketlauncher )
if ( Item[usItem].usItemClass == IC_GUN && !ItemIsRocketLauncher(usItem) )
{
// if ( (Item[ usItem ].fFlags & ITEM_TWO_HANDED) )
if ( (Item[usItem].twohanded) )
if (ItemIsTwoHanded(usItem))
{
usNewState = BIGMERC_CROUCH_TRANS_INTO;
}
@@ -3446,10 +3449,10 @@ BOOLEAN SOLDIERTYPE::EVENT_InitNewSoldierAnim( UINT16 usNewState, UINT16 usStart
if ( this->inv[HANDPOS].exists( ) == true )
{
if ( Item[usItem].usItemClass == IC_GUN && !Item[usItem].rocketlauncher )
if ( Item[usItem].usItemClass == IC_GUN && !ItemIsRocketLauncher(usItem) )
{
// if ( (Item[ usItem ].fFlags & ITEM_TWO_HANDED) )
if ( (Item[usItem].twohanded) )
if (ItemIsTwoHanded(usItem))
{
usNewState = BIGMERC_CROUCH_TRANS_OUTOF;
}
@@ -3474,7 +3477,7 @@ BOOLEAN SOLDIERTYPE::EVENT_InitNewSoldierAnim( UINT16 usNewState, UINT16 usStart
if ( ((gAnimControl[this->usAnimState].uiFlags & ANIM_FIREREADY) ||
(gAnimControl[this->usAnimState].uiFlags & ANIM_FIRE)) && gGameExternalOptions.fAllowWalkingWithWeaponRaised )
{
if ( this->inv[HANDPOS].exists( ) == true && Item[usItem].usItemClass == IC_GUN && !Item[usItem].rocketlauncher )
if ( this->inv[HANDPOS].exists( ) == true && Item[usItem].usItemClass == IC_GUN && !ItemIsRocketLauncher(usItem) )
{
if ( gAnimControl[this->usAnimState].ubEndHeight == ANIM_STAND )
{
@@ -3521,7 +3524,7 @@ BOOLEAN SOLDIERTYPE::EVENT_InitNewSoldierAnim( UINT16 usNewState, UINT16 usStart
{
if ( gAnimControl[this->usAnimState].ubEndHeight == ANIM_CROUCH )
{
if ( this->inv[HANDPOS].exists( ) == true && Item[usItem].usItemClass == IC_GUN && Item[usItem].twohanded && !Item[usItem].rocketlauncher )
if ( this->inv[HANDPOS].exists( ) == true && Item[usItem].usItemClass == IC_GUN && ItemIsTwoHanded(usItem) && !ItemIsRocketLauncher(usItem) )
usNewState = SWAT_BACKWARDS;
else
usNewState = SWAT_BACKWARDS_NOTHING;
@@ -3592,7 +3595,7 @@ BOOLEAN SOLDIERTYPE::EVENT_InitNewSoldierAnim( UINT16 usNewState, UINT16 usStart
// SANDRO - check if we are gonna move with weapon raised
else if ( gGameExternalOptions.fAllowWalkingWithWeaponRaised && ( (gAnimControl[this->usAnimState].uiFlags & ANIM_FIREREADY) || (gAnimControl[this->usAnimState].uiFlags & ANIM_FIRE) ) )
{
if ( this->inv[HANDPOS].exists( ) == true && Item[usItem].usItemClass == IC_GUN && !Item[usItem].rocketlauncher )
if ( this->inv[HANDPOS].exists( ) == true && Item[usItem].usItemClass == IC_GUN && !ItemIsRocketLauncher(usItem) )
{
if ( usNewState == WALKING )
{
@@ -3615,7 +3618,7 @@ BOOLEAN SOLDIERTYPE::EVENT_InitNewSoldierAnim( UINT16 usNewState, UINT16 usStart
{
usNewState = CROUCHEDMOVE_DUAL_READY;
}
else if ( !Item[this->inv[HANDPOS].usItem].twohanded )
else if (!ItemIsTwoHanded(this->inv[HANDPOS].usItem))
{
usNewState = CROUCHEDMOVE_PISTOL_READY;
}
@@ -3988,7 +3991,7 @@ BOOLEAN SOLDIERTYPE::EVENT_InitNewSoldierAnim( UINT16 usNewState, UINT16 usStart
case PLANT_BOMB:
if ( Item[this->inv[HANDPOS].usItem].mine == 1 ) // bury a mine
if (ItemIsMine(this->inv[HANDPOS].usItem)) // bury a mine
DeductPoints( this, GetAPsToPlantMine( this ), APBPConstants[BP_BURY_MINE] ); // changed by SANDRO
else
DeductPoints( this, GetAPsToDropBomb( this ), APBPConstants[BP_DROP_BOMB] ); // changed by SANDRO
@@ -4957,9 +4960,9 @@ void SOLDIERTYPE::EVENT_FireSoldierWeapon( INT32 sTargetGridNo )
usItem = GetAttachedGrenadeLauncher( &this->inv[HANDPOS] );
else
usItem = this->inv[HANDPOS].usItem;
if ( Item[usItem].rocketlauncher || Item[usItem].grenadelauncher || Item[usItem].mortar )
if (ItemIsRocketLauncher(usItem) || ItemIsGrenadeLauncher(usItem) || ItemIsMortar(usItem) )
{
if ( gAnimControl[this->usAnimState].ubEndHeight == ANIM_PRONE || Item[usItem].mortar && gAnimControl[this->usAnimState].ubEndHeight == ANIM_STAND )
if ( gAnimControl[this->usAnimState].ubEndHeight == ANIM_PRONE || ItemIsMortar(usItem) && gAnimControl[this->usAnimState].ubEndHeight == ANIM_STAND )
SendChangeSoldierStanceEvent( this, ANIM_CROUCH );
fDoFireRightAway = TRUE;
}
@@ -5041,8 +5044,10 @@ void SOLDIERTYPE::EVENT_FireSoldierWeapon( INT32 sTargetGridNo )
}
else if (!TileIsOutOfBounds(sTargetGridNo) && !GridNoOnScreen(sTargetGridNo))
{
INT16 sNewCenterWorldX = CenterX(sTargetGridNo);
INT16 sNewCenterWorldY = CenterY(sTargetGridNo);
INT16 sNewCenterWorldX;
INT16 sNewCenterWorldY;
ConvertGridNoToCenterCellXY(sTargetGridNo, &sNewCenterWorldX, &sNewCenterWorldY);
SetRenderCenter(sNewCenterWorldX, sNewCenterWorldY);
// Plot new path!
@@ -5113,7 +5118,7 @@ UINT16 SelectFireAnimation( SOLDIERTYPE *pSoldier, UINT8 ubHeight )
}
// Check for rocket laucncher....
if ( Item[pSoldier->inv[HANDPOS].usItem].rocketlauncher )
if (ItemIsRocketLauncher(pSoldier->inv[HANDPOS].usItem))
{
//***ddd if shoot crouched
if ( ubHeight == ANIM_STAND )
@@ -5123,14 +5128,14 @@ UINT16 SelectFireAnimation( SOLDIERTYPE *pSoldier, UINT8 ubHeight )
}
// Check for mortar....
if ( Item[pSoldier->inv[HANDPOS].usItem].mortar )
if (ItemIsMortar(pSoldier->inv[HANDPOS].usItem))
{
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, "SelectFireAnimation: shoot_mortar" );
return(SHOOT_MORTAR);
}
// Check for tank cannon
if ( Item[pSoldier->inv[HANDPOS].usItem].cannon )
if (ItemIsCannon(pSoldier->inv[HANDPOS].usItem))
{
return(TANK_SHOOT);
}
@@ -5442,7 +5447,7 @@ BOOLEAN SOLDIERTYPE::InternalSoldierReadyWeapon( UINT8 sFacingDir, BOOLEAN fEndR
}
//dnl ch72 270913 ugly but fast fix for not charging turning APs as there is no fire ready animation for mortars and rocket launchers
UINT16 usItem = this->inv[HANDPOS].usItem;
if ( Item[usItem].rocketlauncher || Item[usItem].mortar )
if (ItemIsRocketLauncher(usItem) || ItemIsMortar(usItem) )
usForceAnimState = this->usAnimState;
EVENT_InternalSetSoldierDesiredDirection( this, sFacingDir, FALSE, usAnimState );
usForceAnimState = INVALID_ANIMATION;
@@ -5530,12 +5535,12 @@ UINT16 PickSoldierReadyAnimation( SOLDIERTYPE *pSoldier, BOOLEAN fEndReady, BOOL
}
// Check if we have a gun.....
if ( Item[pSoldier->inv[HANDPOS].usItem].usItemClass != IC_GUN && !Item[pSoldier->inv[HANDPOS].usItem].grenadelauncher )
if ( Item[pSoldier->inv[HANDPOS].usItem].usItemClass != IC_GUN && !ItemIsGrenadeLauncher(pSoldier->inv[HANDPOS].usItem) )
{
return(INVALID_ANIMATION);
}
if ( Item[pSoldier->inv[HANDPOS].usItem].rocketlauncher )
if (ItemIsRocketLauncher(pSoldier->inv[HANDPOS].usItem))
{
return(INVALID_ANIMATION);
}
@@ -5616,7 +5621,7 @@ UINT16 PickSoldierReadyAnimation( SOLDIERTYPE *pSoldier, BOOLEAN fEndReady, BOOL
// this is a specific situation when we have a gun in standard holding (shouldered rifle/two-hand pistol) and was told to go to alternative holding
else if ( (gAnimControl[pSoldier->usAnimState].uiFlags & (ANIM_FIREREADY | ANIM_FIRE)) && !(gAnimControl[pSoldier->usAnimState].uiFlags & (ANIM_ALT_WEAPON_HOLDING))
&& fAltWeaponHolding && gGameExternalOptions.ubAllowAlternativeWeaponHolding == 3 && pSoldier->bScopeMode == -1 && gAnimControl[pSoldier->usAnimState].ubEndHeight == ANIM_STAND
&& ((!Item[pSoldier->inv[HANDPOS].usItem].twohanded && !pSoldier->IsValidSecondHandShot( ) && !pSoldier->MercInWater( )) || Item[pSoldier->inv[HANDPOS].usItem].twohanded) )
&& ((!ItemIsTwoHanded(pSoldier->inv[HANDPOS].usItem) && !pSoldier->IsValidSecondHandShot( ) && !pSoldier->MercInWater( )) || ItemIsTwoHanded(pSoldier->inv[HANDPOS].usItem)) )
{
return(READY_ALTERNATIVE_STAND);
}
@@ -5636,7 +5641,7 @@ UINT16 PickSoldierReadyAnimation( SOLDIERTYPE *pSoldier, BOOLEAN fEndReady, BOOL
{
if ( gGameExternalOptions.ubAllowAlternativeWeaponHolding )
{
if ( fAltWeaponHolding || (Weapon[pSoldier->inv[pSoldier->ubAttackingHand].usItem].HeavyGun && Item[pSoldier->inv[HANDPOS].usItem].twohanded) )
if ( fAltWeaponHolding || (Weapon[pSoldier->inv[pSoldier->ubAttackingHand].usItem].HeavyGun && ItemIsTwoHanded(pSoldier->inv[HANDPOS].usItem)) )
{
return(READY_ALTERNATIVE_STAND);
}
@@ -5872,7 +5877,7 @@ void SOLDIERTYPE::EVENT_SoldierGotHit( UINT16 usWeaponIndex, INT16 sDamage, INT1
{
if ( ubAttackerID != NOBODY )
{
if ( !(MercPtrs[ubAttackerID]->inv[HANDPOS].exists( )) || Item[MercPtrs[ubAttackerID]->inv[HANDPOS].usItem].brassknuckles )
if ( !(MercPtrs[ubAttackerID]->inv[HANDPOS].exists( )) || ItemIsBrassKnuckles(MercPtrs[ubAttackerID]->inv[HANDPOS].usItem) )
{
// with enhanced CCS, make the lost breath harder to regenerate, which makes CQC more usable
if ( gGameExternalOptions.fEnhancedCloseCombatSystem )
@@ -5939,7 +5944,7 @@ void SOLDIERTYPE::EVENT_SoldierGotHit( UINT16 usWeaponIndex, INT16 sDamage, INT1
if ( HasItemFlag( usWeaponIndex, TASER ) )
{
// tasers need batteries, because I say so
if ( Item[usWeaponIndex].needsbatteries )
if (ItemNeedsBatteries(usWeaponIndex))
{
// check for batteries
OBJECTTYPE* pBatteries = FindAttachedBatteries( &(MercPtrs[ubAttackerID]->inv[HANDPOS]) );
@@ -7359,7 +7364,7 @@ void SOLDIERTYPE::EVENT_InternalSetSoldierDestination( UINT16 usNewDirection, BO
// Get dest gridno, convert to center coords
sNewGridNo = NewGridNo( this->sGridNo, DirectionInc( (UINT8)usNewDirection ) );
ConvertMapPosToWorldTileCenter( sNewGridNo, &sXPos, &sYPos );
ConvertGridNoToCenterCellXY( sNewGridNo, &sXPos, &sYPos );
// Save new dest gridno, x, y
this->pathing.sDestination = sNewGridNo;
@@ -9729,7 +9734,7 @@ BOOLEAN SOLDIERTYPE::CanClimbWithCurrentBackpack()
// only apply backpack climbing limitations to player mercs
if (UsingNewInventorySystem() == true && this->inv[BPACKPOCKPOS].exists() == true && this->bTeam == OUR_TEAM
&& ((gGameExternalOptions.sBackpackWeightToClimb == -1) || (INT16)this->inv[BPACKPOCKPOS].GetWeightOfObjectInStack() + Item[this->inv[BPACKPOCKPOS].usItem].sBackpackWeightModifier > gGameExternalOptions.sBackpackWeightToClimb)
&& ((gGameExternalOptions.fUseGlobalBackpackSettings == TRUE) || (Item[this->inv[BPACKPOCKPOS].usItem].fAllowClimbing == FALSE)))
&& ((gGameExternalOptions.fUseGlobalBackpackSettings == TRUE) || !ItemAllowsClimbing(this->inv[BPACKPOCKPOS].usItem)))
return FALSE;
return TRUE;
@@ -10434,7 +10439,7 @@ UINT8 SOLDIERTYPE::SoldierTakeDamage( INT8 bHeight, INT16 sLifeDeduct, INT16 sBr
&& this->HasDiseaseWithFlag( DISEASE_PROPERTY_LIMITED_USE_ARMS ) )
{
// drop item in main hand if twohanded
if ( this->inv[HANDPOS].exists() == true && TwoHandedItem( this->inv[HANDPOS].usItem ) )
if ( this->inv[HANDPOS].exists() == true && ItemIsTwoHanded( this->inv[HANDPOS].usItem ) )
dropiteminmainhand = true;
// we can only use one hand, so drop items in second hand
@@ -10700,6 +10705,22 @@ UINT8 SOLDIERTYPE::SoldierTakeDamage( INT8 bHeight, INT16 sLifeDeduct, INT16 sBr
return(ubCombinedLoss);
}
void SOLDIERTYPE::SoldierTakeDelayedDamage(INT8 bHeight, INT16 sLifeDeduct, INT16 sBreathLoss, UINT8 ubReason, UINT8 ubAttacker, INT32 sSourceGrid, INT16 sSubsequent, BOOLEAN fShowDamage)
{
delayedDamageFunction = [this, bHeight, sLifeDeduct, sBreathLoss, ubReason, ubAttacker, sSourceGrid, sSubsequent, fShowDamage]()
{
this->SoldierTakeDamage(bHeight, sLifeDeduct, sBreathLoss, ubReason, ubAttacker, sSourceGrid, sSubsequent, fShowDamage);
};
}
void SOLDIERTYPE::ResolveDelayedDamage()
{
if (delayedDamageFunction)
{
delayedDamageFunction();
delayedDamageFunction = nullptr;
}
}
extern BOOLEAN IsMercSayingDialogue( UINT8 ubProfileID );
@@ -11499,6 +11520,8 @@ void SOLDIERTYPE::MoveMerc( FLOAT dMovementChange, FLOAT dAngle, BOOLEAN fCheckR
// OK, set new position
this->EVENT_InternalSetSoldierPosition( dXPos, dYPos, FALSE, FALSE, FALSE );
this->ResolveDelayedDamage();
// Flugente: drag people
if ( currentlydragging )
{
@@ -11526,7 +11549,7 @@ void SOLDIERTYPE::MoveMerc( FLOAT dMovementChange, FLOAT dAngle, BOOLEAN fCheckR
{
INT16 this_base_x = 0;
INT16 this_base_y = 0;
ConvertMapPosToWorldTileCenter( this->sGridNo, &this_base_x, &this_base_y );
ConvertGridNoToCenterCellXY( this->sGridNo, &this_base_x, &this_base_y );
dx = this->dXPos - this_base_x;
dy = this->dYPos - this_base_y;
@@ -11534,7 +11557,7 @@ void SOLDIERTYPE::MoveMerc( FLOAT dMovementChange, FLOAT dAngle, BOOLEAN fCheckR
INT16 base_x = 0;
INT16 base_y = 0;
ConvertMapPosToWorldTileCenter( gridnotouse, &base_x, &base_y );
ConvertGridNoToCenterCellXY( gridnotouse, &base_x, &base_y );
pSoldier->EVENT_InternalSetSoldierPosition( base_x + dx, base_y + dy, FALSE, FALSE, FALSE );
}
@@ -11568,27 +11591,33 @@ void SOLDIERTYPE::MoveMerc( FLOAT dMovementChange, FLOAT dAngle, BOOLEAN fCheckR
// adjust both gridno and x,y coordinates
if (sOldGridNo != this->sGridNo)
{
CorpseDef.sGridNo = sOldGridNo;
CorpseDef.dXPos = CenterX(CorpseDef.sGridNo);
CorpseDef.dYPos = CenterY(CorpseDef.sGridNo);
INT16 sX, sY;
ConvertGridNoToCenterCellXY(sOldGridNo, &sX, &sY);
CorpseDef.sGridNo = sOldGridNo;
CorpseDef.dXPos = sX;
CorpseDef.dYPos = sY;
}
else
{
// move corpse a bit
INT16 this_base_x = 0;
INT16 this_base_y = 0;
ConvertMapPosToWorldTileCenter(this->sGridNo, &this_base_x, &this_base_y);
ConvertGridNoToCenterCellXY(this->sGridNo, &this_base_x, &this_base_y);
FLOAT dx = this->dXPos - this_base_x;
FLOAT dy = this->dYPos - this_base_y;
INT16 base_x = 0;
INT16 base_y = 0;
ConvertMapPosToWorldTileCenter(pCorpse->def.sGridNo, &base_x, &base_y);
ConvertGridNoToCenterCellXY(pCorpse->def.sGridNo, &base_x, &base_y);
INT16 sX, sY;
ConvertGridNoToCenterCellXY(pCorpse->def.sGridNo, &sX, &sY);
CorpseDef.sGridNo = pCorpse->def.sGridNo;
CorpseDef.dXPos = CenterX(CorpseDef.sGridNo) + dx;
CorpseDef.dYPos = CenterY(CorpseDef.sGridNo) + dy;
CorpseDef.dXPos = sX + dx;
CorpseDef.dYPos = sY + dy;
}
CorpseDef.usFlags |= ROTTING_CORPSE_USE_XY_PROVIDED;
@@ -11750,6 +11779,17 @@ UINT8 GetDirectionFromXY( INT16 sXPos, INT16 sYPos, SOLDIERTYPE *pSoldier )
return(atan8( sXPos2, sYPos2, sXPos, sYPos ));
}
INT16 GetDirectionFromCenterCellXYGridNo(INT32 EndGridNo, INT32 StartGridNo)
{
INT16 sXPos2, sYPos2;
INT16 sXPos, sYPos;
ConvertGridNoToCenterCellXY(StartGridNo, &sXPos, &sYPos);
ConvertGridNoToCenterCellXY(EndGridNo, &sXPos2, &sYPos2);
return(atan8(sXPos2, sYPos2, sXPos, sYPos));
}
//#if 0
UINT8 atan8( INT16 sXPos, INT16 sYPos, INT16 sXPos2, INT16 sYPos2 )
@@ -12243,8 +12283,7 @@ void SOLDIERTYPE::ReviveSoldier( void )
this->BeginSoldierGetup( );
// Makesure center of tile
sX = CenterX( this->sGridNo );
sY = CenterY( this->sGridNo );
ConvertGridNoToCenterCellXY(this->sGridNo, &sX, &sY);
this->EVENT_SetSoldierPosition( (FLOAT)sX, (FLOAT)sY );
@@ -12724,9 +12763,9 @@ void SOLDIERTYPE::EVENT_SoldierBeginPunchAttack( INT32 sGridNo, UINT8 ubDirectio
//Ja25 No meanwhiles
#ifdef JA2UB
if ( fMartialArtist && !Item[usItem].crowbar && this->ubBodyType == REGMALE )
if ( fMartialArtist && !ItemIsCrowbar(usItem) && this->ubBodyType == REGMALE )
#else
if ( fMartialArtist && !AreInMeanwhile( ) && !Item[usItem].crowbar && this->ubBodyType == REGMALE && !IsZombie( )
if ( fMartialArtist && !AreInMeanwhile( ) && !ItemIsCrowbar(usItem) && this->ubBodyType == REGMALE && !IsZombie( )
&& !( gGameExternalOptions.fDiseaseSevereLimitations && this->HasDiseaseWithFlag( DISEASE_PROPERTY_LIMITED_USE_LEGS )) ) // SANDRO - added check for body type
#endif
{
@@ -12832,7 +12871,7 @@ void SOLDIERTYPE::EVENT_SoldierBeginPunchAttack( INT32 sGridNo, UINT8 ubDirectio
case ANIM_STAND:
case ANIM_CROUCH:
if ( !Item[usItem].crowbar )
if ( !ItemIsCrowbar(usItem) )
{
BOOLEAN fCannotKick = (ubDirection & 1);
// SANDRO - we will determine here what type of punch we are gonna use
@@ -13056,7 +13095,7 @@ void SOLDIERTYPE::EVENT_SoldierBeginDropBomb( )
void SOLDIERTYPE::EVENT_SoldierDefuseTripwire( INT32 sGridNo, INT32 sItem )
{
// Flugente: if item is tripwireactivated and is a planted bomb, call the defuse dialogue. We obviously know about the item's existence already...
if ( gWorldItems[sItem].object.exists( ) && gWorldItems[sItem].object.fFlags & OBJECT_ARMED_BOMB && Item[gWorldItems[sItem].object.usItem].tripwire == 1 )
if ( gWorldItems[sItem].object.exists( ) && gWorldItems[sItem].object.fFlags & OBJECT_ARMED_BOMB && ItemIsTripwire(gWorldItems[sItem].object.usItem) )
{
// Increment the number of people busy doing stuff because of an attack
switch ( gAnimControl[this->usAnimState].ubHeight )
@@ -13109,7 +13148,7 @@ void SOLDIERTYPE::EVENT_SoldierBeginFirstAid( INT32 sGridNo, UINT8 ubDirection )
//SANDRO - hack! Find out if we are a doctor with medical bag trying to make a surgery
this->fDoingSurgery = FALSE;
if ( (NUM_SKILL_TRAITS( this, DOCTOR_NT ) >= gSkillTraitValues.ubDONumberTraitsNeededForSurgery) && Item[this->inv[HANDPOS].usItem].medicalkit && gGameOptions.fNewTraitSystem )
if ( (NUM_SKILL_TRAITS( this, DOCTOR_NT ) >= gSkillTraitValues.ubDONumberTraitsNeededForSurgery) && ItemIsMedicalKit(this->inv[HANDPOS].usItem) && gGameOptions.fNewTraitSystem )
{
if ( ((pTSoldier->bTeam == OUR_TEAM) || (pTSoldier->bTeam == MILITIA_TEAM))
&& (IS_MERC_BODY_TYPE( pTSoldier ) || IS_CIV_BODY_TYPE( pTSoldier ))
@@ -13281,7 +13320,7 @@ UINT32 SOLDIERTYPE::SoldierDressWound( SOLDIERTYPE *pVictim, INT16 sKitPts, INT1
// Flugente: AI medics are allowed to perform surgery without first aid kits, and can do this on themselves
if ( pVictim->iHealableInjury > 0 && this->fDoingSurgery && (this->ubID != pVictim->ubID || (gGameExternalOptions.fEnemyMedicsHealSelf && this->bTeam == ENEMY_TEAM))
&& gGameOptions.fNewTraitSystem && (NUM_SKILL_TRAITS( this, DOCTOR_NT ) >= gSkillTraitValues.ubDONumberTraitsNeededForSurgery)
&& (Item[this->inv[HANDPOS].usItem].medicalkit || this->bTeam == ENEMY_TEAM) )
&& (ItemIsMedicalKit(this->inv[HANDPOS].usItem) || this->bTeam == ENEMY_TEAM) )
{
fOnSurgery = TRUE;
}
@@ -13320,7 +13359,7 @@ UINT32 SOLDIERTYPE::SoldierDressWound( SOLDIERTYPE *pVictim, INT16 sKitPts, INT1
return(0);
// using the GOOD medic stuff
if ( Item[this->inv[HANDPOS].usItem].medicalkit && !(fOnSurgery) ) // added check
if (ItemIsMedicalKit(this->inv[HANDPOS].usItem) && !(fOnSurgery) ) // added check
{
uiPossible += (uiPossible / 2); // add extra 50 %
}
@@ -13378,7 +13417,7 @@ UINT32 SOLDIERTYPE::SoldierDressWound( SOLDIERTYPE *pVictim, INT16 sKitPts, INT1
}
// now make sure we HAVE that much
if ( Item[this->inv[HANDPOS].usItem].medicalkit )
if (ItemIsMedicalKit(this->inv[HANDPOS].usItem))
{
if ( fOnSurgery )
uiMedcost = (uiActual * gSkillTraitValues.usDOSurgeryMedBagConsumption) / 100; // surgery drains the kit a lot
@@ -13626,7 +13665,7 @@ UINT32 SOLDIERTYPE::SoldierDressWound( SOLDIERTYPE *pVictim, INT16 sKitPts, INT1
// usedAPs equals (actionPts) * (%of possible points actually used)
uiUsedAPs = (uiActual * uiAvailAPs) / uiPossible;
if ( Item[this->inv[HANDPOS].usItem].medicalkit && !(fOnSurgery) ) // using the GOOD medic stuff
if (ItemIsMedicalKit(this->inv[HANDPOS].usItem) && !(fOnSurgery) ) // using the GOOD medic stuff
{
uiUsedAPs = (uiUsedAPs * 2) / 3; // reverse 50% bonus by taking 2/3rds
}
@@ -13944,8 +13983,7 @@ void SOLDIERTYPE::EVENT_StopMerc( INT32 sGridNo, INT8 bDirection )
// MOVE GUY TO GRIDNO--- SHOULD BE THE SAME UNLESS IN MULTIPLAYER
// Makesure center of tile
sX = CenterX( sGridNo );
sY = CenterY( sGridNo );
ConvertGridNoToCenterCellXY(sGridNo, &sX, &sY);
//Cancel pending events
if ( !this->flags.fDelayedMovement )
@@ -14033,7 +14071,7 @@ void SOLDIERTYPE::ReLoadSoldierAnimationDueToHandItemChange( UINT16 usOldItem, U
this->bWeaponMode = WM_ATTACHED_GL;
}
if ( Item[usNewItem].twohanded && Weapon[usNewItem].HeavyGun && gGameExternalOptions.ubAllowAlternativeWeaponHolding == 3 )
if (ItemIsTwoHanded(usNewItem) && Weapon[usNewItem].HeavyGun && gGameExternalOptions.ubAllowAlternativeWeaponHolding == 3 )
this->bScopeMode = USE_ALT_WEAPON_HOLD;
else
this->bScopeMode = USE_BEST_SCOPE;
@@ -14056,8 +14094,7 @@ void SOLDIERTYPE::ReLoadSoldierAnimationDueToHandItemChange( UINT16 usOldItem, U
{
if ( Item[usOldItem].usItemClass == IC_GUN )
{
// if ( (Item[ usOldItem ].fFlags & ITEM_TWO_HANDED) && usOldItem != ROCKET_LAUNCHER )
if ( (Item[usOldItem].twohanded) && !Item[usOldItem].rocketlauncher )
if (ItemIsTwoHanded(usOldItem) && !ItemIsRocketLauncher(usOldItem))
{
fOldRifle = TRUE;
}
@@ -14068,8 +14105,7 @@ void SOLDIERTYPE::ReLoadSoldierAnimationDueToHandItemChange( UINT16 usOldItem, U
{
if ( Item[usNewItem].usItemClass == IC_GUN )
{
// if ( (Item[ usNewItem ].fFlags & ITEM_TWO_HANDED) && usNewItem != ROCKET_LAUNCHER )
if ( (Item[usNewItem].twohanded) && !Item[usNewItem].rocketlauncher )
if (ItemIsTwoHanded(usNewItem) && !ItemIsRocketLauncher(usNewItem))
{
fNewRifle = TRUE;
}
@@ -14594,7 +14630,7 @@ BOOLEAN SOLDIERTYPE::SoldierCarriesTwoHandedWeapon( void )
usItem = this->inv[HANDPOS].usItem;
if ( this->inv[HANDPOS].exists( ) == true && (Item[usItem].twohanded) )
if ( this->inv[HANDPOS].exists( ) == true && ItemIsTwoHanded(usItem) )
{
return(TRUE);
}
@@ -15491,7 +15527,7 @@ BOOLEAN SOLDIERTYPE::LooksLikeACivilian( void )
{
// if that item is a gun, explosives, military armour or facewear, we're screwed
if ( (Item[this->inv[bLoop].usItem].usItemClass & (IC_WEAPON | IC_GRENADE | IC_BOMB)) ||
((Item[this->inv[bLoop].usItem].usItemClass & (IC_ARMOUR)) && !Item[this->inv[bLoop].usItem].leatherjacket && Armour[Item[this->inv[bLoop].usItem].ubClassIndex].ubProtection > 10) ||
((Item[this->inv[bLoop].usItem].usItemClass & (IC_ARMOUR)) && !ItemIsLeatherJacket(this->inv[bLoop].usItem) && Armour[Item[this->inv[bLoop].usItem].ubClassIndex].ubProtection > 10) ||
(Item[this->inv[bLoop].usItem].nightvisionrangebonus > 0 || Item[this->inv[bLoop].usItem].hearingrangebonus > 0)
)
{
@@ -15513,7 +15549,7 @@ BOOLEAN SOLDIERTYPE::LooksLikeACivilian( void )
{
// if that item is a gun, explosives, military armour or facewear, we're screwed
if ( (Item[this->inv[bLoop].usItem].usItemClass & (IC_WEAPON | IC_GRENADE | IC_BOMB)) ||
((Item[this->inv[bLoop].usItem].usItemClass & (IC_ARMOUR)) && !Item[this->inv[bLoop].usItem].leatherjacket && Armour[Item[this->inv[bLoop].usItem].ubClassIndex].ubProtection > 10) ||
((Item[this->inv[bLoop].usItem].usItemClass & (IC_ARMOUR)) && !ItemIsLeatherJacket(this->inv[bLoop].usItem) && Armour[Item[this->inv[bLoop].usItem].ubClassIndex].ubProtection > 10) ||
(Item[this->inv[bLoop].usItem].nightvisionrangebonus > 0 || Item[this->inv[bLoop].usItem].hearingrangebonus > 0)
)
{
@@ -15844,7 +15880,7 @@ BOOLEAN SOLDIERTYPE::SeemsLegit( UINT16 ubObserverID )
}
UINT8 covertlevel = NUM_SKILL_TRAITS( this, COVERT_NT ); // our level in covert operations
INT32 distance = GetRangeFromGridNoDiff( this->sGridNo, pSoldier->sGridNo );
INT32 distance = PythSpacesAway( this->sGridNo, pSoldier->sGridNo );
// if we are closer than this, our cover will always break if we do not have the skill
// if we have the skill, our cover will blow if we dress up as a soldier, but not if we are dressed like a civilian
@@ -16810,7 +16846,7 @@ void SOLDIERTYPE::DropSectorEquipment( )
if ( pObj->exists( ) )
{
// Check if it's supposed to be dropped
if ( !((*pObj).fFlags & OBJECT_UNDROPPABLE) && !(Item[pObj->usItem].defaultundroppable) && (*pObj)[0]->data.sObjectFlag & TAKEN_BY_MILITIA )
if ( !((*pObj).fFlags & OBJECT_UNDROPPABLE) && !ItemIsUndroppableByDefault(pObj->usItem) && (*pObj)[0]->data.sObjectFlag & TAKEN_BY_MILITIA )
{
(*pObj)[0]->data.sObjectFlag &= ~TAKEN_BY_MILITIA;
@@ -16836,7 +16872,7 @@ void SOLDIERTYPE::DropSectorEquipment( )
if ( pObj->exists( ) )
{
// Check if it's supposed to be dropped
if ( !((*pObj).fFlags & OBJECT_UNDROPPABLE) && !(Item[pObj->usItem].defaultundroppable) && (*pObj)[0]->data.sObjectFlag & TAKEN_BY_MILITIA )
if ( !((*pObj).fFlags & OBJECT_UNDROPPABLE) && !ItemIsUndroppableByDefault(pObj->usItem) && (*pObj)[0]->data.sObjectFlag & TAKEN_BY_MILITIA )
{
(*pObj)[0]->data.sObjectFlag &= ~TAKEN_BY_MILITIA;
@@ -16906,12 +16942,13 @@ void SOLDIERTYPE::TakeNewBombFromInventory( UINT16 usItem )
// take tripwire-activated item only if used item is tripwire activated
for ( i = 0; i < invsize; i++ )
{
UINT16 usItem = this->inv[i].usItem;
if ( this->inv[i].exists( ) == true &&
Item[this->inv[i].usItem].usItemClass == IC_BOMB &&
Item[this->inv[i].usItem].ubCursor == BOMBCURS &&
!Item[this->inv[i].usItem].tripwire &&
((Item[this->inv[i].usItem].tripwireactivation && Item[usItem].tripwireactivation) ||
(!Item[this->inv[i].usItem].tripwireactivation && !Item[usItem].tripwireactivation)) )
Item[usItem].usItemClass == IC_BOMB &&
Item[usItem].ubCursor == BOMBCURS &&
!ItemIsTripwire(usItem) &&
((ItemHasTripwireActivation(usItem) && ItemHasTripwireActivation(usItem)) ||
(!ItemHasTripwireActivation(usItem) && !ItemHasTripwireActivation(usItem))) )
{
this->inv[i].MoveThisObjectTo( this->inv[HANDPOS], 1, this );
return;
@@ -17034,7 +17071,7 @@ void SOLDIERTYPE::SwitchWeapons( BOOLEAN fKnife, BOOLEAN fSideArm )
else
handCanMove = (CanItemFitInPosition( this, &this->inv[HANDPOS], handobjstorageslot, FALSE ) || (this->inv[HANDPOS].exists( ) == false && this->inv[SECONDHANDPOS].exists( ) == false));
if ( Item[this->inv[retrieveslot].usItem].twohanded && this->inv[SECONDHANDPOS].exists( ) == true )
if ( ItemIsTwoHanded(this->inv[retrieveslot].usItem) && this->inv[SECONDHANDPOS].exists( ) == true )
searchitemCanMove = FALSE;
else
searchitemCanMove = (CanItemFitInPosition( this, &this->inv[retrieveslot], HANDPOS, FALSE ) || this->inv[retrieveslot].exists( ) == false);
@@ -17133,7 +17170,7 @@ INT8 SOLDIERTYPE::GetTraitCTHModifier( UINT16 usItem, INT16 ubAimTime, UINT8 ubT
{
// Bonus for heavy weapons moved here from above to get instant CtH bonus and not marksmanship bonus,
// which is supressed by weapon condition
if ( Item[usItem].rocketlauncher || Item[usItem].singleshotrocketlauncher )
if (ItemIsRocketLauncher(usItem) || ItemIsSingleShotRocketLauncher(usItem))
{
modifier += gSkillTraitValues.bCtHModifierRocketLaunchers; // -25% for untrained mercs !!!
@@ -17587,6 +17624,24 @@ INT16 SOLDIERTYPE::GetBackgroundValue( UINT16 aNr )
return 0;
}
const std::vector<INT16>& SOLDIERTYPE::GetBackgroundValueVector(BackgroundVectorTypes backgroundVectorType) const
{
static const std::vector<INT16> emptyVector;
if (UsingBackGroundSystem() && this->ubProfile != NO_PROFILE)
{
const BACKGROUND_VALUES& background = zBackground[gMercProfiles[this->ubProfile].usBackground];
auto iterator = background.valueVectors.find(backgroundVectorType);
if (iterator != background.valueVectors.end())
{
return iterator->second;
}
}
return emptyVector;
}
INT8 SOLDIERTYPE::GetSuppressionResistanceBonus( )
{
INT8 bonus = 0;
@@ -17811,7 +17866,7 @@ void SOLDIERTYPE::SoldierPropertyUpkeep( )
if ( this->usSkillCooldown[SOLDIER_COOLDOWN_DRUGUSER_COMBAT] )
this->usSkillCooldown[SOLDIER_COOLDOWN_DRUGUSER_COMBAT]--;
if (AM_A_ROBOT(this) && Item[this->inv[ROBOT_UTILITY_SLOT].usItem].xray == 1)
if (AM_A_ROBOT(this) && ItemHasXRay(this->inv[ROBOT_UTILITY_SLOT].usItem))
{
if (this->usSkillCooldown[SOLDIER_COOLDOWN_ROBOT_XRAY])
this->usSkillCooldown[SOLDIER_COOLDOWN_ROBOT_XRAY]--;
@@ -18499,7 +18554,7 @@ BOOLEAN SOLDIERTYPE::HasMortar( )
INT8 invsize = (INT8)inv.size( ); // remember inventorysize, so we don't call size() repeatedly
for ( INT8 bLoop = 0; bLoop < invsize; ++bLoop )
{
if ( inv[bLoop].exists( ) == true && Item[inv[bLoop].usItem].mortar )
if ( inv[bLoop].exists( ) == true && ItemIsMortar(inv[bLoop].usItem) )
{
return TRUE;
}
@@ -18515,7 +18570,7 @@ BOOLEAN SOLDIERTYPE::GetSlotOfSignalShellIfMortar( UINT8* pbLoop )
INT8 invsize = (INT8)inv.size( ); // remember inventorysize, so we don't call size() repeatedly
for ( INT8 bLoop = 0; bLoop < invsize; ++bLoop )
{
if ( inv[bLoop].exists( ) == true && Item[inv[bLoop].usItem].mortar )
if ( inv[bLoop].exists( ) == true && ItemIsMortar(inv[bLoop].usItem) )
{
mortaritem = inv[bLoop].usItem;
break;
@@ -18534,7 +18589,7 @@ BOOLEAN SOLDIERTYPE::GetSlotOfSignalShellIfMortar( UINT8* pbLoop )
return TRUE;
}
if ( Item[inv[bLoop].usItem].mortar )
if (ItemIsMortar(inv[bLoop].usItem))
{
OBJECTTYPE* pAttObj = FindAttachmentByClass( &(inv[bLoop]), IC_BOMB );
@@ -18823,7 +18878,7 @@ BOOLEAN SOLDIERTYPE::OrderArtilleryStrike( UINT32 usSectorNr, INT32 sTargetGridN
for ( INT8 bLoop = 0; (bLoop < invsize) && (mortaritemcnt < maxFiringMortarsAmount); ++bLoop )
{
if ( pSoldier->inv[bLoop].exists( ) == true && Item[pSoldier->inv[bLoop].usItem].mortar )
if ( pSoldier->inv[bLoop].exists( ) == true && ItemIsMortar(pSoldier->inv[bLoop].usItem))
{
// if not already in list, remember this mortar
bool alreadyInList = false;
@@ -18868,7 +18923,7 @@ BOOLEAN SOLDIERTYPE::OrderArtilleryStrike( UINT32 usSectorNr, INT32 sTargetGridN
{
if ( pSoldier->inv[bLoop].exists( ) == true )
{
if ( Item[pSoldier->inv[bLoop].usItem].mortar )
if (ItemIsMortar(pSoldier->inv[bLoop].usItem))
{
OBJECTTYPE* pAttObj = FindAttachmentByClass( &(pSoldier->inv[bLoop]), IC_BOMB );
@@ -19883,22 +19938,19 @@ FLOAT SOLDIERTYPE::GetDiseaseContactProtection( )
// if we wear special equipment, lower our chances of being infected
FLOAT bestfacegear = 0.0f;
FLOAT bestprotectivegear = 0.0f;
INT8 invsize = (INT8)inv.size( ); // remember inventorysize, so we don't call size() repeatedly
for ( INT8 bLoop = 0; bLoop < invsize; ++bLoop )
for ( const auto &item : inv.get() )
{
if ( inv[bLoop].exists( ) )
if ( item.exists( ) )
{
OBJECTTYPE* pObj = &(inv[bLoop]);
if ( pObj && (*pObj)[0]->data.objectStatus >= USABLE )
if ( item[0]->data.objectStatus >= USABLE )
{
if ( HasItemFlag( pObj->usItem, DISEASEPROTECTION_1 ) )
if ( HasItemFlag( item.usItem, DISEASEPROTECTION_1 ) )
{
bestfacegear = max( bestfacegear, (FLOAT)((*pObj)[0]->data.objectStatus / 100) );
bestfacegear = max( bestfacegear, (FLOAT)(item[0]->data.objectStatus / 100) );
}
if ( HasItemFlag( pObj->usItem, DISEASEPROTECTION_2 ) )
if ( HasItemFlag( item.usItem, DISEASEPROTECTION_2 ) )
{
bestprotectivegear = max( bestprotectivegear, (FLOAT)((*pObj)[0]->data.objectStatus / 100) );
bestprotectivegear = max( bestprotectivegear, (FLOAT)(item[0]->data.objectStatus / 100) );
}
}
}
@@ -20830,7 +20882,7 @@ void SOLDIERTYPE::CancelDrag()
{
INT16 base_x = 0;
INT16 base_y = 0;
ConvertMapPosToWorldTileCenter(pSoldier->sGridNo, &base_x, &base_y);
ConvertGridNoToCenterCellXY(pSoldier->sGridNo, &base_x, &base_y);
pSoldier->EVENT_InternalSetSoldierPosition(base_x, base_y, FALSE, FALSE, FALSE);
}
@@ -21820,6 +21872,8 @@ void SoldierCollapse( SOLDIERTYPE *pSoldier )
pSoldier->bCollapsed = TRUE;
pSoldier->usUIMovementMode = CRAWLING;
pSoldier->ReceivingSoldierCancelServices( );
// CC has requested - handle sight here...
@@ -22375,7 +22429,7 @@ void SOLDIERTYPE::EVENT_SoldierBeginAttachCan( INT32 sGridNo, UINT8 ubDirection
// OK, find door, attach to door, do animation...., remove item....
// First make sure we still have item in hand....
if ( !Item[this->inv[HANDPOS].usItem].canandstring )
if ( !ItemIsCanAndString(this->inv[HANDPOS].usItem))
{
return;
}
@@ -22687,7 +22741,7 @@ void SOLDIERTYPE::EVENT_SoldierApplyItemToPerson( INT32 sGridNo, UINT8 ubDirecti
if ( success )
{
if ( Item[usItem].gasmask )
if (ItemIsGasmask(usItem))
{
// put this item into a (at best empty) faceslot if no gasmask is been worn
INT8 bSlot = FindGasMask( pSoldier );
@@ -23162,7 +23216,7 @@ BOOLEAN SOLDIERTYPE::PlayerSoldierStartTalking( UINT16 ubTargetID, BOOLEAN fVali
return(FALSE);
}
uiRange = GetRangeFromGridNoDiff( this->sGridNo, pTSoldier->sGridNo );
uiRange = PythSpacesAway( this->sGridNo, pTSoldier->sGridNo );
if ( uiRange > (NPC_TALK_RADIUS * 2) )
{
@@ -23308,11 +23362,11 @@ BOOLEAN SOLDIERTYPE::PlayerSoldierStartTalking( UINT16 ubTargetID, BOOLEAN fVali
BOOLEAN SOLDIERTYPE::IsValidSecondHandShot( void )
{
if ( Item[this->inv[SECONDHANDPOS].usItem].usItemClass == IC_GUN &&
!(Item[this->inv[SECONDHANDPOS].usItem].twohanded) &&
!ItemIsTwoHanded(this->inv[SECONDHANDPOS].usItem) &&
(!this->bDoBurst || this->IsValidSecondHandBurst( )) &&
!Item[this->inv[HANDPOS].usItem].grenadelauncher &&
!ItemIsGrenadeLauncher(this->inv[HANDPOS].usItem) &&
Item[this->inv[HANDPOS].usItem].usItemClass == IC_GUN &&
!(Item[this->inv[HANDPOS].usItem].twohanded) &&
!ItemIsTwoHanded(this->inv[HANDPOS].usItem) &&
this->inv[SECONDHANDPOS][0]->data.gun.bGunStatus >= USABLE &&
this->inv[SECONDHANDPOS][0]->data.gun.ubGunShotsLeft > 0 )
{
@@ -23326,11 +23380,11 @@ BOOLEAN SOLDIERTYPE::IsValidSecondHandBurst( void )
{
// SANDRO - a function to determine if we can autofire with both weapons
if ( Item[this->inv[SECONDHANDPOS].usItem].usItemClass == IC_GUN &&
!(Item[this->inv[SECONDHANDPOS].usItem].twohanded) &&
!Item[this->inv[HANDPOS].usItem].grenadelauncher &&
!ItemIsTwoHanded(this->inv[SECONDHANDPOS].usItem) &&
!ItemIsGrenadeLauncher(this->inv[HANDPOS].usItem) &&
this->bDoBurst &&
Item[this->inv[HANDPOS].usItem].usItemClass == IC_GUN &&
!(Item[this->inv[HANDPOS].usItem].twohanded) &&
!ItemIsTwoHanded(this->inv[HANDPOS].usItem) &&
this->inv[SECONDHANDPOS][0]->data.gun.bGunStatus >= USABLE &&
this->inv[SECONDHANDPOS][0]->data.gun.ubGunShotsLeft > 0 )
{
@@ -23362,7 +23416,7 @@ BOOLEAN SOLDIERTYPE::IsValidSecondHandShotForReloadingPurposes( void )
// about ammo taken out!
if ( Item[this->inv[SECONDHANDPOS].usItem].usItemClass == IC_GUN &&
//!this->bDoBurst &&
!Item[this->inv[HANDPOS].usItem].grenadelauncher &&
!ItemIsGrenadeLauncher(this->inv[HANDPOS].usItem) &&
Item[this->inv[HANDPOS].usItem].usItemClass == IC_GUN &&
this->inv[SECONDHANDPOS][0]->data.gun.bGunStatus >= USABLE //&&
// this->inv[SECONDHANDPOS][0]->data.gun.ubGunShotsLeft > 0 &&
@@ -23398,7 +23452,7 @@ BOOLEAN SOLDIERTYPE::IsValidShotFromHip( INT16 bAimTime, INT32 iTrgGridNo )
return(FALSE);
}
// must be two handed for this
if ( !Item[this->inv[HANDPOS].usItem].twohanded )
if ( !ItemIsTwoHanded(this->inv[HANDPOS].usItem) )
{
return(FALSE);
}
@@ -23455,7 +23509,7 @@ BOOLEAN SOLDIERTYPE::IsValidPistolFastShot( INT16 bAimTime, INT32 iTrgGridNo )
return(FALSE);
}
// must be one handed for this
if ( Item[this->inv[HANDPOS].usItem].twohanded )
if (ItemIsTwoHanded(this->inv[HANDPOS].usItem))
{
return(FALSE);
}
@@ -24124,8 +24178,8 @@ void SOLDIERTYPE::BreakWindow(void)
{
if (this->inv[HANDPOS].exists() &&
this->inv[HANDPOS][0]->data.objectStatus >= USABLE &&
(Item[this->inv[HANDPOS].usItem].crowbar && Item[this->inv[HANDPOS].usItem].usItemClass & (IC_PUNCH) ||
Item[this->inv[HANDPOS].usItem].usItemClass & IC_GUN && Item[this->inv[HANDPOS].usItem].twohanded && Item[this->inv[HANDPOS].usItem].metal))
(ItemIsCrowbar(this->inv[HANDPOS].usItem) && Item[this->inv[HANDPOS].usItem].usItemClass & (IC_PUNCH) ||
Item[this->inv[HANDPOS].usItem].usItemClass & IC_GUN && ItemIsTwoHanded(this->inv[HANDPOS].usItem) && ItemIsMetal(this->inv[HANDPOS].usItem) ))
{
this->usAttackingWeapon = this->inv[HANDPOS].usItem;
this->aiData.bAction = AI_ACTION_KNIFE_STAB;
@@ -24149,8 +24203,8 @@ BOOLEAN SOLDIERTYPE::CanBreakWindow(void)
IS_MERC_BODY_TYPE(this) &&
this->inv[HANDPOS].exists() &&
this->inv[HANDPOS][0]->data.objectStatus >= USABLE &&
(Item[this->inv[HANDPOS].usItem].crowbar && Item[this->inv[HANDPOS].usItem].usItemClass & (IC_PUNCH) ||
Item[this->inv[HANDPOS].usItem].usItemClass & IC_GUN && Item[this->inv[HANDPOS].usItem].twohanded && Item[this->inv[HANDPOS].usItem].metal))
(ItemIsCrowbar(this->inv[HANDPOS].usItem) && Item[this->inv[HANDPOS].usItem].usItemClass & (IC_PUNCH) ||
Item[this->inv[HANDPOS].usItem].usItemClass & IC_GUN && ItemIsTwoHanded(this->inv[HANDPOS].usItem) && ItemIsMetal(this->inv[HANDPOS].usItem) ))
{
//INT32 sWindowGridNo = this->sTargetGridNo;
INT32 sWindowGridNo = this->sGridNo;
@@ -25009,7 +25063,7 @@ BOOLEAN AIDecideHipOrShoulderStance( SOLDIERTYPE * pSoldier, INT32 iGridNo )
UINT16 usInHand = pSoldier->usAttackingWeapon;
// not 2-handed or not standing
if ( gAnimControl[pSoldier->usAnimState].ubEndHeight != ANIM_STAND || !Item[pSoldier->inv[HANDPOS].usItem].twohanded )
if ( gAnimControl[pSoldier->usAnimState].ubEndHeight != ANIM_STAND || !ItemIsTwoHanded(pSoldier->inv[HANDPOS].usItem) )
{
return FALSE;
}
@@ -25542,7 +25596,7 @@ UINT32 VirtualSoldierDressWound( SOLDIERTYPE *pSoldier, SOLDIERTYPE *pVictim, OB
if ( !uiPossible )
return 0;
if ( Item[pSoldier->inv[0].usItem].medicalkit && !(fOnSurgery) ) // using the GOOD medic stuff
if (ItemIsMedicalKit(pSoldier->inv[0].usItem) && !(fOnSurgery) ) // using the GOOD medic stuff
uiPossible += (uiPossible / 2); // add extra 50 %
// Doctor trait improves basic bandaging ability
@@ -25578,7 +25632,7 @@ UINT32 VirtualSoldierDressWound( SOLDIERTYPE *pSoldier, SOLDIERTYPE *pVictim, OB
uiActual = uiDeficiency; // reduce actual not to waste anything
// now make sure we HAVE that much
if ( Item[pKit->usItem].medicalkit )
if (ItemIsMedicalKit(pKit->usItem))
{
if ( fOnSurgery )
uiMedcost = (uiActual * gSkillTraitValues.usDOSurgeryMedBagConsumption) / 100; // surgery drains the kit a lot
@@ -25797,7 +25851,7 @@ UINT32 VirtualSoldierDressWound( SOLDIERTYPE *pSoldier, SOLDIERTYPE *pVictim, OB
// usedAPs equals (actionPts) * (%of possible points actually used)
uiUsedAPs = (uiActual * uiAvailAPs) / uiPossible;
if ( Item[pSoldier->inv[0].usItem].medicalkit && !(fOnSurgery) ) // using the GOOD medic stuff
if (ItemIsMedicalKit(pSoldier->inv[0].usItem) && !(fOnSurgery) ) // using the GOOD medic stuff
uiUsedAPs = (uiUsedAPs * 2) / 3; // reverse 50% bonus by taking 2/3rds
// surgery is harder so cost more BPs
@@ -25929,7 +25983,7 @@ BOOLEAN ApplyConsumable(SOLDIERTYPE* pSoldier, OBJECTTYPE *pObj, BOOLEAN fForce,
// how much of this item do we use up
UINT16 statusused = min(portionsize, (*pObj)[0]->data.objectStatus);
if (!statusused || (statusused == 1 && Item[pObj->usItem].canteen))
if (!statusused || (statusused == 1 && ItemIsCanteen(pObj->usItem)))
return FALSE;
INT16 apcost = 0;
@@ -25946,12 +26000,12 @@ BOOLEAN ApplyConsumable(SOLDIERTYPE* pSoldier, OBJECTTYPE *pObj, BOOLEAN fForce,
apcost = max( apcost, (APBPConstants[AP_CAMOFLAGE] / 2) );
}
if ( Item[pObj->usItem].camouflagekit )
if (ItemIsCamoKit(pObj->usItem))
{
apcost = max( apcost, APBPConstants[AP_CAMOFLAGE] );
}
if ( Item[pObj->usItem].canteen )
if (ItemIsCanteen(pObj->usItem))
{
apcost = max( apcost, APBPConstants[AP_DRINK] );
}
@@ -25998,7 +26052,7 @@ BOOLEAN ApplyConsumable(SOLDIERTYPE* pSoldier, OBJECTTYPE *pObj, BOOLEAN fForce,
}
// some mercs will refuse to smoke
if ( Item[pObj->usItem].cigarette && pSoldier->GetBackgroundValue( BG_SMOKERTYPE ) == 2 )
if (ItemIsCigarette(pObj->usItem) && pSoldier->GetBackgroundValue( BG_SMOKERTYPE ) == 2 )
{
// merc gets slightly pissed by the player even suggesting this
TacticalCharacterDialogue( pSoldier, QUOTE_REFUSE_TO_SMOKE );
@@ -26054,7 +26108,7 @@ BOOLEAN ApplyConsumable(SOLDIERTYPE* pSoldier, OBJECTTYPE *pObj, BOOLEAN fForce,
fSuccess = TRUE;
// no sound on consuming cigarettes, as that is very annoying
if ( !Item[pObj->usItem].cigarette )
if ( !ItemIsCigarette(pObj->usItem) )
{
fDoSound = TRUE;
}
@@ -26235,4 +26289,6 @@ void SOLDIERTYPE::InitializeExtraData(void)
this->ubQuickItemSlot = 0;
this->usGrenadeItem = 0;
this->delayedDamageFunction = nullptr;
}