mirror of
https://github.com/1dot13/source.git
synced 2026-08-26 14:30:26 +02:00
Migrate +AI features
* Drink canteen * Jump through window * Use explosives * Use wirecutters
This commit is contained in:
@@ -758,6 +758,29 @@ void EatFromInventory( SOLDIERTYPE *pSoldier, BOOLEAN fcanteensonly )
|
||||
}
|
||||
}
|
||||
|
||||
void DrinkFromInventory(SOLDIERTYPE* pSoldier)
|
||||
{
|
||||
if ( !pSoldier )
|
||||
return;
|
||||
|
||||
INT8 invsize = pSoldier->inv.size();
|
||||
|
||||
for ( INT8 bLoop = 0; bLoop < invsize; ++bLoop )
|
||||
{
|
||||
if ( pSoldier->inv[bLoop].exists() && ItemIsCanteen(pSoldier->inv[bLoop].usItem) )
|
||||
{
|
||||
OBJECTTYPE* pObj = &(pSoldier->inv[bLoop]);
|
||||
|
||||
if ( pObj && TotalPoints(pObj) > 1 )
|
||||
{
|
||||
//ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, Message[STR_DRINKS], pSoldier->GetName());
|
||||
ApplyConsumable(pSoldier, pObj, false, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HourlyFoodUpdate( void )
|
||||
{
|
||||
SoldierID bMercID, bLastTeamID;
|
||||
|
||||
@@ -108,5 +108,6 @@ void SoldierAutoFillCanteens(SOLDIERTYPE *pSoldier);
|
||||
BOOLEAN HasFoodInInventory( SOLDIERTYPE *pSoldier, BOOLEAN fCheckFood, BOOLEAN fCheckDrink );
|
||||
|
||||
void DrinkFromWaterTap( SOLDIERTYPE *pSoldier );
|
||||
void DrinkFromInventory(SOLDIERTYPE* pSoldier);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -12426,6 +12426,51 @@ INT8 FindCamoKit( SOLDIERTYPE * pSoldier )
|
||||
return( NO_SLOT );
|
||||
}
|
||||
|
||||
INT8 FindCanteen(SOLDIERTYPE* pSoldier)
|
||||
{
|
||||
const INT8 invsize = pSoldier->inv.size();
|
||||
for ( INT8 bLoop = 0; bLoop < invsize; ++bLoop )
|
||||
{
|
||||
if ( pSoldier->inv[bLoop].exists() && ItemIsCanteen(pSoldier->inv[bLoop].usItem) )
|
||||
{
|
||||
OBJECTTYPE* pObj = &(pSoldier->inv[bLoop]);
|
||||
if ( pObj && TotalPoints(pObj) > 1 )
|
||||
{
|
||||
return(bLoop);
|
||||
}
|
||||
}
|
||||
}
|
||||
return(NO_SLOT);
|
||||
}
|
||||
|
||||
INT8 FindWirecutters(SOLDIERTYPE* pSoldier)
|
||||
{
|
||||
const INT8 invsize = pSoldier->inv.size();
|
||||
for ( INT8 bLoop = 0; bLoop < invsize; ++bLoop )
|
||||
{
|
||||
if ( pSoldier->inv[bLoop].exists() && ItemIsWirecutters(pSoldier->inv[bLoop].usItem) )
|
||||
{
|
||||
return(bLoop);
|
||||
}
|
||||
}
|
||||
|
||||
return NO_SLOT;
|
||||
}
|
||||
|
||||
INT8 FindTNT(SOLDIERTYPE* pSoldier)
|
||||
{
|
||||
const INT8 invsize = pSoldier->inv.size();
|
||||
for ( INT8 bLoop = 0; bLoop < invsize; ++bLoop )
|
||||
{
|
||||
if ( pSoldier->inv[bLoop].exists() && ItemIsTNT(pSoldier->inv[bLoop].usItem) )
|
||||
{
|
||||
return(bLoop);
|
||||
}
|
||||
}
|
||||
|
||||
return NO_SLOT;
|
||||
}
|
||||
|
||||
//JMich_SkillModifiers: Adding a function to see if we have an item with disarm bonus
|
||||
INT8 FindDisarmKit( SOLDIERTYPE * pSoldier )
|
||||
{
|
||||
@@ -16045,6 +16090,20 @@ BOOLEAN FindAttachmentRange(UINT16 usAttachment, UINT32* pStartIndex, UINT32* pE
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
BOOLEAN ItemIsTNT(UINT16 usItem)
|
||||
{
|
||||
if ( Item[usItem].usItemClass == IC_BOMB &&
|
||||
!ItemIsMine(usItem) &&
|
||||
!ItemIsTripwire(usItem) &&
|
||||
Explosive[Item[usItem].ubClassIndex].ubType == EXPLOSV_NORMAL &&
|
||||
Explosive[Item[usItem].ubClassIndex].ubDamage > 40 &&
|
||||
GetLauncherFromLaunchable(usItem) == NOTHING )
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
////////////////////////////////////
|
||||
// Item flagmask utility functions
|
||||
// Just to improve readability
|
||||
|
||||
@@ -249,6 +249,7 @@ BOOLEAN ItemIsOnlyInDisease(UINT16 usItem);
|
||||
BOOLEAN ItemProvidesRobotCamo(UINT16 usItem);
|
||||
BOOLEAN ItemProvidesRobotNightvision(UINT16 usItem);
|
||||
BOOLEAN ItemProvidesRobotLaserBonus(UINT16 usItem);
|
||||
BOOLEAN ItemIsTNT(UINT16 usItem);
|
||||
|
||||
//Existing functions without header def's, added them here, just incase I'll need to call
|
||||
//them from the editor.
|
||||
@@ -479,9 +480,13 @@ INT8 FindFirstAidKit( SOLDIERTYPE * pSoldier );
|
||||
INT8 FindDisarmKit( SOLDIERTYPE * pSoldier ); //JMich_SkillsModifiers: Added function to check for disarm bonus
|
||||
INT8 FindLocksmithKit( SOLDIERTYPE * pSoldier );
|
||||
INT8 FindCamoKit( SOLDIERTYPE * pSoldier );
|
||||
INT8 FindCanteen(SOLDIERTYPE* pSoldier);
|
||||
INT8 FindWalkman( SOLDIERTYPE * pSoldier );
|
||||
INT8 FindTrigger( SOLDIERTYPE * pSoldier );
|
||||
INT8 FindRemoteControl( SOLDIERTYPE * pSoldier );
|
||||
INT8 FindWirecutters(SOLDIERTYPE* pSoldier);
|
||||
INT8 FindTNT(SOLDIERTYPE* pSoldier);
|
||||
|
||||
INT16 GetWornCamo( SOLDIERTYPE * pSoldier );
|
||||
INT16 GetCamoBonus( OBJECTTYPE * pObj );
|
||||
INT16 GetWornStealth( SOLDIERTYPE * pSoldier );
|
||||
|
||||
+33
-5
@@ -5031,11 +5031,11 @@ BOOLEAN NewOKDestination( SOLDIERTYPE * pCurrSoldier, INT32 sGridNo, BOOLEAN fPe
|
||||
BOOLEAN fOKCheckStruct;
|
||||
|
||||
// Allow civilians and NPCs with profile to go off screen, and also enemies if tactical retreat is enabled
|
||||
auto destinationOffscreen = !(GridNoOnVisibleWorldTile(sGridNo));
|
||||
auto hasProfile = pCurrSoldier->ubProfile != NO_PROFILE;
|
||||
auto isCivilian = pCurrSoldier->bTeam == CIV_TEAM;
|
||||
auto isEnemy = pCurrSoldier->bTeam == ENEMY_TEAM;
|
||||
auto retreatAllowed = gGameExternalOptions.fAITacticalRetreat == true;
|
||||
const auto destinationOffscreen = !(GridNoOnVisibleWorldTile(sGridNo));
|
||||
const auto hasProfile = pCurrSoldier->ubProfile != NO_PROFILE;
|
||||
const auto isCivilian = pCurrSoldier->bTeam == CIV_TEAM;
|
||||
const auto isEnemy = pCurrSoldier->bTeam == ENEMY_TEAM;
|
||||
const auto retreatAllowed = gGameExternalOptions.fAITacticalRetreat == TRUE;
|
||||
|
||||
if (destinationOffscreen && !(isCivilian || hasProfile || (isEnemy && retreatAllowed)))
|
||||
{
|
||||
@@ -5400,6 +5400,34 @@ BOOLEAN TeamMemberNear( INT8 bTeam, INT32 sGridNo, INT32 iRange )
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
BOOLEAN NotDeafTeamMemberNear(INT8 bTeam, INT32 sGridNo, INT32 iRange)
|
||||
{
|
||||
for ( SoldierID pSoldier = gTacticalStatus.Team[bTeam].bFirstID; pSoldier <= gTacticalStatus.Team[bTeam].bLastID; ++pSoldier )
|
||||
{
|
||||
if ( pSoldier->bActive &&
|
||||
pSoldier->bInSector &&
|
||||
pSoldier->stats.bLife >= OKLIFE &&
|
||||
pSoldier->bDeafenedCounter == 0 )
|
||||
{
|
||||
if ( PythSpacesAway(pSoldier->sGridNo, sGridNo) <= iRange )
|
||||
{
|
||||
return(TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
BOOLEAN PlayerCanHearNoise(SOLDIERTYPE* pSoldier)
|
||||
{
|
||||
if ( pSoldier &&
|
||||
(pSoldier->bVisible == TRUE || NotDeafTeamMemberNear(gbPlayerNum, pSoldier->sGridNo, TACTICAL_RANGE / 2) || NightLight() && !(gTacticalStatus.uiFlags & TURNBASED && gTacticalStatus.uiFlags & INCOMBAT) && NotDeafTeamMemberNear(gbPlayerNum, pSoldier->sGridNo, TACTICAL_RANGE)) )
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
INT32 FindAdjacentGridEx( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 *pubDirection, INT32 *psAdjustedGridNo, BOOLEAN fForceToPerson, BOOLEAN fDoor, bool allow_diagonal )
|
||||
{
|
||||
// psAdjustedGridNo gets the original gridno or the new one if updated
|
||||
|
||||
+3
-1
@@ -261,6 +261,9 @@ void SelectNextAvailSoldier( SOLDIERTYPE *pSoldier );
|
||||
BOOLEAN TeamMemberNear(INT8 bTeam, INT32 sGridNo, INT32 iRange);
|
||||
BOOLEAN IsValidTargetMerc( SoldierID ubSoldierID );
|
||||
|
||||
BOOLEAN NotDeafTeamMemberNear(INT8 bTeam, INT32 sGridNo, INT32 iRange);
|
||||
BOOLEAN PlayerCanHearNoise(SOLDIERTYPE* pSoldier);
|
||||
|
||||
// FUNCTIONS FOR MANIPULATING MERC SLOTS - A LIST OF ALL ACTIVE MERCS
|
||||
INT32 GetFreeMercSlot( );
|
||||
INT32 AddMercSlot( SOLDIERTYPE *pSoldier );
|
||||
@@ -433,4 +436,3 @@ BOOLEAN IsFreeSlotAvailable( int aTeam );
|
||||
void AttemptToCapturePlayerSoldiers();
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -9700,6 +9700,85 @@ void SOLDIERTYPE::BeginSoldierClimbWallUp( void )
|
||||
}
|
||||
//------------------------------------------------------------------------------------------
|
||||
|
||||
void SOLDIERTYPE::BeginSoldierJumpWindowAI(void)
|
||||
{
|
||||
DebugAI(AI_MSG_INFO, this, String("check if we can jump through window"));
|
||||
|
||||
//UINT8 ubDirection = this->aiData.usActionData;
|
||||
UINT8 ubDirection = this->ubDirection;
|
||||
|
||||
INT32 sWindowGridNo = this->sGridNo;
|
||||
if ( ubDirection == NORTH || ubDirection == WEST )
|
||||
sWindowGridNo = NewGridNo(this->sGridNo, (UINT16)DirectionInc((UINT8)ubDirection));
|
||||
|
||||
DebugAI(AI_MSG_INFO, this, String("sWindowGridNo %d direction %d", sWindowGridNo, ubDirection));
|
||||
|
||||
if (//CheckWindow(this->sGridNo, ubDirection, gGameExternalOptions.fCanJumpThroughClosedWindows) &&
|
||||
IsJumpableWindowPresentAtGridNo(sWindowGridNo, ubDirection, gGameExternalOptions.fCanJumpThroughClosedWindows) &&
|
||||
//FindWindowJumpDirection(this, this->sGridNo, bDirection, &bDirection) &&
|
||||
this->pathing.bLevel == 0 &&
|
||||
(ubDirection == NORTH || ubDirection == EAST || ubDirection == SOUTH || ubDirection == WEST) )
|
||||
{
|
||||
// Flugente: if we are jumping through an intact window, smash it during our animation
|
||||
if ( gGameExternalOptions.fCanJumpThroughClosedWindows )
|
||||
{
|
||||
// is there really an intact window that we jump through?
|
||||
if ( IsJumpableWindowPresentAtGridNo(sWindowGridNo, ubDirection, TRUE) && !IsJumpableWindowPresentAtGridNo(sWindowGridNo, ubDirection, FALSE) )
|
||||
{
|
||||
STRUCTURE* pStructure = FindStructure(sWindowGridNo, STRUCTURE_WALLNWINDOW);
|
||||
if ( pStructure && !(pStructure->fFlags & STRUCTURE_OPEN) )
|
||||
{
|
||||
DebugAI(AI_MSG_INFO, this, String("jumping through closed window, damage soldier"));
|
||||
// intact window found. Smash it!
|
||||
WindowHit(sWindowGridNo, pStructure->usStructureID, (ubDirection == SOUTH || ubDirection == EAST), TRUE, PlayerCanHearNoise(this));
|
||||
|
||||
// we get a bit of damage for jumping through a window
|
||||
this->SoldierTakeDamage(0, 2 + 2 * Random(4), 0, 1000, TAKE_DAMAGE_ELECTRICITY, NOBODY, sWindowGridNo, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this->sTempNewGridNo = NewGridNo(this->sGridNo, (UINT16)DirectionInc(ubDirection));
|
||||
this->flags.fDontChargeTurningAPs = TRUE;
|
||||
EVENT_InternalSetSoldierDesiredDirection(this, ubDirection, FALSE, this->usAnimState);
|
||||
this->flags.fTurningUntilDone = TRUE;
|
||||
// ATE: Reset flag to go back to prone...
|
||||
|
||||
// Flugente: In case an animation is missing (civilian bodytypes), we TELEPORT instead
|
||||
if ( IsAnimationValidForBodyType(this, JUMPWINDOWS) == FALSE )
|
||||
{
|
||||
DebugAI(AI_MSG_INFO, this, String("teleport soldier to %d", this->sTempNewGridNo));
|
||||
|
||||
// sevenfm: deduct APs for jumping
|
||||
if ( UsingNewInventorySystem() && FindBackpackOnSoldier(this) != ITEM_NOT_FOUND )
|
||||
DeductPoints(this, GetAPsToJumpThroughWindows(this, TRUE), GetBPsToJumpThroughWindows(this, TRUE), SP_MOVEMENT_INTERRUPT);
|
||||
else
|
||||
DeductPoints(this, GetAPsToJumpThroughWindows(this, FALSE), GetBPsToJumpThroughWindows(this, FALSE), SP_MOVEMENT_INTERRUPT);
|
||||
|
||||
TeleportSoldier(this, this->sTempNewGridNo, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugAI(AI_MSG_INFO, this, String("start jumping"));
|
||||
this->flags.bTurningFromPronePosition = TURNING_FROM_PRONE_OFF;
|
||||
this->EVENT_InitNewSoldierAnim(JUMPWINDOWS, 0, FALSE);
|
||||
//this->usPendingAnimation = JUMPWINDOWS;
|
||||
//EndAIGuysTurn(this);
|
||||
}
|
||||
|
||||
// Flugente: should be fixed now, re-enable if not
|
||||
// Flugente: if an AI guy, end turn (weird endless clock syndrome)
|
||||
//if ( this->bTeam != OUR_TEAM )
|
||||
//EndAIGuysTurn( this);
|
||||
}
|
||||
else
|
||||
{
|
||||
ScreenMsg(FONT_LTRED, MSG_INTERFACE, L"[%d] %s cannot jump", this->ubID, this->GetName());
|
||||
DebugAI(AI_MSG_INFO, this, String("CancelAIAction: cannot jump"));
|
||||
CancelAIAction(this, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
UINT32 SleepDartSuccumbChance( SOLDIERTYPE * pSoldier )
|
||||
{
|
||||
UINT32 uiChance;
|
||||
@@ -26297,3 +26376,13 @@ void SOLDIERTYPE::InitializeExtraData(void)
|
||||
|
||||
this->delayedDamageFunction = nullptr;
|
||||
}
|
||||
|
||||
UINT8 SOLDIERTYPE::AnimHeight(void) const
|
||||
{
|
||||
return gAnimControl[this->usAnimState].ubHeight;
|
||||
}
|
||||
|
||||
UINT8 SOLDIERTYPE::AnimEndHeight(void) const
|
||||
{
|
||||
return gAnimControl[this->usAnimState].ubEndHeight;
|
||||
}
|
||||
|
||||
@@ -1788,10 +1788,13 @@ public:
|
||||
void ChangeToFallbackAnimation( UINT8 fallBackDirection );
|
||||
|
||||
// sevenfm
|
||||
void BeginSoldierJumpWindowAI(void);
|
||||
void BreakWindow(void);
|
||||
BOOLEAN CanBreakWindow(void);
|
||||
BOOLEAN CanStartDrag(void);
|
||||
void StartDrag(void);
|
||||
UINT8 AnimHeight(void) const;
|
||||
UINT8 AnimEndHeight(void) const;
|
||||
|
||||
void UpdateRobotControllerGivenController( void );
|
||||
void UpdateRobotControllerGivenRobot( void );
|
||||
|
||||
@@ -6089,7 +6089,7 @@ void StructureHit( INT32 iBullet, UINT16 usWeaponIndex, INT16 bWeaponStatus, Sol
|
||||
}
|
||||
}
|
||||
|
||||
void WindowHit( INT32 sGridNo, UINT16 usStructureID, BOOLEAN fBlowWindowSouth, BOOLEAN fLargeForce )
|
||||
void WindowHit( INT32 sGridNo, UINT16 usStructureID, BOOLEAN fBlowWindowSouth, BOOLEAN fLargeForce, BOOLEAN fSound)
|
||||
{
|
||||
STRUCTURE * pWallAndWindow;
|
||||
DB_STRUCTURE * pWallAndWindowInDB;
|
||||
@@ -6210,10 +6210,12 @@ void WindowHit( INT32 sGridNo, UINT16 usStructureID, BOOLEAN fBlowWindowSouth, B
|
||||
|
||||
pNode = CreateAnimationTile( &AniParams );
|
||||
//ddd window{
|
||||
CompileWorldMovementCosts();
|
||||
//ddd window}
|
||||
PlayJA2Sample( GLASS_SHATTER1 + Random(2), RATE_11025, MIDVOLUME, 1, SoundDir( sGridNo ) );
|
||||
|
||||
CompileWorldMovementCosts();
|
||||
//ddd window}
|
||||
if ( fSound )
|
||||
{
|
||||
PlayJA2Sample(GLASS_SHATTER1 + Random(2), RATE_11025, MIDVOLUME, 1, SoundDir(sGridNo));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -456,7 +456,7 @@ INT16 ArmourVersusFirePercent( SOLDIERTYPE * pSoldier );
|
||||
extern BOOLEAN FireWeapon( SOLDIERTYPE *pSoldier , INT32 sTargetGridNo );
|
||||
extern void WeaponHit( SoldierID usSoldierID, UINT16 usWeaponIndex, INT16 sDamage, INT16 sBreathLoss, UINT16 usDirection, INT16 sXPos, INT16 sYPos, INT16 sZPos, INT16 sRange, SoldierID ubAttackerID, BOOLEAN fHit, UINT8 ubSpecial, UINT8 ubHitLocation );
|
||||
extern void StructureHit( INT32 iBullet, UINT16 usWeaponIndex, INT16 bWeaponStatus, SoldierID ubAttackerID, UINT16 sXPos, INT16 sYPos, INT16 sZPos, UINT16 usStructureID, INT32 iImpact, BOOLEAN fStopped );
|
||||
extern void WindowHit( INT32 sGridNo, UINT16 usStructureID, BOOLEAN fBlowWindowSouth, BOOLEAN fLargeForce );
|
||||
void WindowHit(INT32 sGridNo, UINT16 usStructureID, BOOLEAN fBlowWindowSouth, BOOLEAN fLargeForce, BOOLEAN fSound = TRUE);
|
||||
// HEADROCK HAM 5.1: Moved to Bullets.h
|
||||
extern BOOLEAN InRange( SOLDIERTYPE *pSoldier, INT32 sGridNo );
|
||||
extern void ShotMiss( SoldierID ubAttackerID, INT32 iBullet );
|
||||
|
||||
Reference in New Issue
Block a user