From 30df6c350ad94e495415df4a7b78546a9806dc05 Mon Sep 17 00:00:00 2001 From: Sevenfm Date: Thu, 3 Oct 2019 16:49:04 +0000 Subject: [PATCH] CalcTargetMovementOffset: better integer calculation for max tiles penalty. SOLDIERTYPE::initialize: initialize additional data. EVENT_FireSoldierWeapon: if shooting soldier is invisible, locate screen to target spot. CancelAIAction: reset next AI action. FindBestPath: improved gas avoiding code. InGas: improved code, also check the spot itself. LegalNPCDestination: disabled additional checks to prevent AI deadlock. git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@8695 3b4a5df2-a311-0410-b5c6-a8a6f20db521 --- Tactical/LOS.cpp | 4 ++- Tactical/PATHAI.cpp | 7 +++-- Tactical/Soldier Control.cpp | 32 ++++++++++++++++++---- TacticalAI/AIInternals.h | 1 + TacticalAI/AIMain.cpp | 5 ++++ TacticalAI/AIUtils.cpp | 53 ++++++++++++++++++++++++++---------- TacticalAI/Movement.cpp | 10 +++---- 7 files changed, 83 insertions(+), 29 deletions(-) diff --git a/Tactical/LOS.cpp b/Tactical/LOS.cpp index bd5ac78ec..6dfd8d17b 100644 --- a/Tactical/LOS.cpp +++ b/Tactical/LOS.cpp @@ -9098,7 +9098,9 @@ void CalcTargetMovementOffset( SOLDIERTYPE *pShooter, SOLDIERTYPE *pTarget, OBJE // Again, if the shooter is skilled, this will occur after fewer tiles have been moved. // If the target moves *more* tiles than this, the movement penalty will begin to diminish. That's our shooter // beginning to compensate for the target's speed, pointing the gun ahead of the target ("Leading the target"). - INT16 uiTilesForMaxPenalty = (INT16)((100-uiCombinedSkill) / (100 / gGameCTHConstants.MOVEMENT_TRACKING_DIFFICULTY)); + // sevenfm: better integer calculation + //INT16 uiTilesForMaxPenalty = (INT16)((100-uiCombinedSkill) / (100 / gGameCTHConstants.MOVEMENT_TRACKING_DIFFICULTY)); + INT16 uiTilesForMaxPenalty = (INT16)((100 - uiCombinedSkill) * gGameCTHConstants.MOVEMENT_TRACKING_DIFFICULTY / 100); UINT8 stance = gAnimControl[ pShooter->usAnimState ].ubEndHeight; diff --git a/Tactical/PATHAI.cpp b/Tactical/PATHAI.cpp index b306d8e28..949334350 100644 --- a/Tactical/PATHAI.cpp +++ b/Tactical/PATHAI.cpp @@ -62,6 +62,7 @@ extern UINT16 gubAnimSurfaceIndex[ TOTALBODYTYPES ][ NUMANIMATIONSTATES ]; // sevenfm: extern BOOLEAN InGas( SOLDIERTYPE *pSoldier, INT32 sGridNo ); +extern BOOLEAN InGasSpot(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel); //extern UINT8 gubDiagCost[20]; // skiplist has extra level of pointers every 4 elements, so a level 5is optimized for @@ -3144,9 +3145,9 @@ if(!GridNoOnVisibleWorldTile(iDestination)) } // sevenfm: skip gas if not in gas already - if( !(s->flags.uiStatusFlags & SOLDIER_PC) && - InGas(s, newLoc) && - !InGas(s, s->sGridNo) ) + if (!(s->flags.uiStatusFlags & SOLDIER_PC) && + InGasSpot(s, newLoc, ubLevel) && + !InGasSpot(s, s->sGridNo, ubLevel)) { goto NEXTDIR; } diff --git a/Tactical/Soldier Control.cpp b/Tactical/Soldier Control.cpp index ec25cea85..2fd1403eb 100644 --- a/Tactical/Soldier Control.cpp +++ b/Tactical/Soldier Control.cpp @@ -1114,6 +1114,19 @@ void SOLDIERTYPE::initialize( ) memset( &newdrugs, 0, sizeof(DRUGS) ); memset( &stats, 0, sizeof(STRUCT_Statistics) ); memset( &pathing, 0, sizeof(STRUCT_Pathing) ); + + // sevenfm:initialize additional data + this->ubLastShock = 0; + this->ubLastSuppression = 0; + this->ubLastAP = 0; + this->ubLastMorale = 0; + this->ubLastShockFromHit = 0; + this->ubLastMoraleFromHit = 0; + this->ubLastAPFromHit = 0; + this->iLastBulletImpact = 0; + this->iLastArmourProtection = 0; + this->usQuickItemId = 0; + this->ubQuickItemSlot = 0; } bool SOLDIERTYPE::exists( ) @@ -5084,12 +5097,21 @@ void SOLDIERTYPE::EVENT_FireSoldierWeapon( INT32 sTargetGridNo ) } else { - // Set flag indicating we are about to shoot once destination direction is hit - this->flags.fTurningToShoot = TRUE; - - if ( this->bTeam != gbPlayerNum && this->bVisible != -1 ) + if (this->bTeam != gbPlayerNum) { - LocateSoldier( this->ubID, DONTSETLOCATOR ); + if (this->bVisible != -1) + { + LocateSoldier(this->ubID, DONTSETLOCATOR); + } + else if (!TileIsOutOfBounds(sTargetGridNo) && !GridNoOnScreen(sTargetGridNo)) + { + INT16 sNewCenterWorldX = CenterX(sTargetGridNo); + INT16 sNewCenterWorldY = CenterY(sTargetGridNo); + SetRenderCenter(sNewCenterWorldX, sNewCenterWorldY); + + // Plot new path! + gfPlotNewMovement = TRUE; + } } } } diff --git a/TacticalAI/AIInternals.h b/TacticalAI/AIInternals.h index 7ba6597f9..d0a81528b 100644 --- a/TacticalAI/AIInternals.h +++ b/TacticalAI/AIInternals.h @@ -243,6 +243,7 @@ INT8 HeadForTheStairCase( SOLDIERTYPE * pSoldier ); BOOLEAN InGas( SOLDIERTYPE *pSoldier, INT32 sGridNo ); BOOLEAN InGasOrSmoke( SOLDIERTYPE *pSoldier, INT32 sGridNo ); BOOLEAN InWaterGasOrSmoke( SOLDIERTYPE *pSoldier, INT32 sGridNo ); +BOOLEAN InGasSpot(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel); INT32 InternalGoAsFarAsPossibleTowards(SOLDIERTYPE *pSoldier, INT32 sDesGrid, INT16 bReserveAPs, INT8 bAction, INT8 fFlags ); diff --git a/TacticalAI/AIMain.cpp b/TacticalAI/AIMain.cpp index c5aed9831..b2ba33a32 100644 --- a/TacticalAI/AIMain.cpp +++ b/TacticalAI/AIMain.cpp @@ -1250,6 +1250,11 @@ void CancelAIAction(SOLDIERTYPE *pSoldier, UINT8 ubForce) pSoldier->aiData.bBypassToGreen = FALSE; ActionDone(pSoldier); + + // sevenfm: reset next action + pSoldier->aiData.bNextAction = AI_ACTION_NONE; + pSoldier->aiData.usNextActionData = 0; + pSoldier->aiData.bNextTargetLevel = 0; } diff --git a/TacticalAI/AIUtils.cpp b/TacticalAI/AIUtils.cpp index 51f586585..801182b59 100644 --- a/TacticalAI/AIUtils.cpp +++ b/TacticalAI/AIUtils.cpp @@ -2010,27 +2010,50 @@ INT16 InWaterOrGas(SOLDIERTYPE *pSoldier, INT32 sGridNo) return (INT16)InGas( pSoldier, sGridNo ); } -BOOLEAN InGas( SOLDIERTYPE *pSoldier, INT32 sGridNo ) +BOOLEAN InGasSpot(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel) { + CHECKF(pSoldier); + + if (TileIsOutOfBounds(sGridNo)) + return FALSE; + + // tear gas + if ((gpWorldLevelData[sGridNo].ubExtFlags[bLevel] & MAPELEMENT_EXT_TEARGAS) && + !DoesSoldierWearGasMask(pSoldier)) + { + return(TRUE); + } + // fire/creature/mustard gas + // sevenfm: avoid mustard gas even when wearing gas mask + if (gpWorldLevelData[sGridNo].ubExtFlags[bLevel] & (MAPELEMENT_EXT_BURNABLEGAS | MAPELEMENT_EXT_CREATUREGAS | MAPELEMENT_EXT_MUSTARDGAS)) + { + return(TRUE); + } + return FALSE; +} + +BOOLEAN InGas(SOLDIERTYPE *pSoldier, INT32 sGridNo) +{ + CHECKF(pSoldier); + + if (TileIsOutOfBounds(sGridNo)) + return FALSE; + + if (InGasSpot(pSoldier, sGridNo, pSoldier->pathing.bLevel)) + { + return TRUE; + } + //WarmSteel - One square away from gas is still considered in gas, because it could expand any moment. //Note: this only works for gas that expands with one tile, but hey it's better than nothing! int iNeighbourGridNo; - for(int iDir = 0; iDir < NUM_WORLD_DIRECTIONS; ++iDir) - { + for (int iDir = 0; iDir < NUM_WORLD_DIRECTIONS; ++iDir) + { iNeighbourGridNo = sGridNo + DirectionInc(iDir); - if(!TileIsOutOfBounds(iNeighbourGridNo)) + + if (!TileIsOutOfBounds(iNeighbourGridNo) && InGasSpot(pSoldier, iNeighbourGridNo, pSoldier->pathing.bLevel)) { - // tear/mustard gas - if((gpWorldLevelData[iNeighbourGridNo].ubExtFlags[pSoldier->pathing.bLevel] & (MAPELEMENT_EXT_TEARGAS)) && !DoesSoldierWearGasMask(pSoldier))//dnl ch40 200909 - { - return(TRUE); - } - // sevenfm: avoid mustard gas even when wearing gas mask - // fire/creature gas - if(gpWorldLevelData[iNeighbourGridNo].ubExtFlags[pSoldier->pathing.bLevel] & (MAPELEMENT_EXT_MUSTARDGAS|MAPELEMENT_EXT_BURNABLEGAS|MAPELEMENT_EXT_CREATUREGAS))//dnl ch62 240813 - { - return(TRUE); - } + return TRUE; } } diff --git a/TacticalAI/Movement.cpp b/TacticalAI/Movement.cpp index e131935d6..1d3ea73e1 100644 --- a/TacticalAI/Movement.cpp +++ b/TacticalAI/Movement.cpp @@ -66,10 +66,10 @@ int LegalNPCDestination(SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 ubPathMode, // AND the gridno hasn't been black-listed for us // Nov 28 98: skip people in destination tile if in turnbased - // sevenfm: also check for bomb nearby + // sevenfm: disabled additional checks to prevent AI deadlock if ( NewOKDestination(pSoldier, sGridNo, fSkipTilesWithMercs, pSoldier->pathing.bLevel ) && - !InGas( pSoldier, sGridNo ) && - !FindBombNearby(pSoldier, sGridNo, DAY_VISION_RANGE/8 ) && + //!InGas( pSoldier, sGridNo ) && + //!FindBombNearby(pSoldier, sGridNo, DAY_VISION_RANGE/8 ) && sGridNo != pSoldier->sGridNo && sGridNo != pSoldier->pathing.sBlackList ) { @@ -78,7 +78,7 @@ int LegalNPCDestination(SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 ubPathMode, return(FALSE); //Madd: added to prevent people from running into gas and fire - if ( (gpWorldLevelData[sGridNo].ubExtFlags[pSoldier->pathing.bLevel] & (MAPELEMENT_EXT_TEARGAS | MAPELEMENT_EXT_MUSTARDGAS)) && + /*if ( (gpWorldLevelData[sGridNo].ubExtFlags[pSoldier->pathing.bLevel] & (MAPELEMENT_EXT_TEARGAS | MAPELEMENT_EXT_MUSTARDGAS)) && !DoesSoldierWearGasMask( pSoldier ) ) { return( FALSE ); @@ -87,7 +87,7 @@ int LegalNPCDestination(SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 ubPathMode, if ( gpWorldLevelData[sGridNo].ubExtFlags[pSoldier->pathing.bLevel] & MAPELEMENT_EXT_BURNABLEGAS ) { return( FALSE ); - } + }*/ // passed all checks, now try to make sure we can get there! switch (ubPathMode)