Brief: //dnl ch58

- Fix several problems which lead into bad or no AI decisions, add optional decision of short autofire.

Details:
- Avoid use of last two locations per turn 
- Fix problems with improper APs calculations for burst and autofire which lead into AI to forcably cancel and end turn for those actions.
- Add option for decide to use short autofire instead of one long to enchance chance to hit.
- After taking cover change facing toward closest enemy to avoid going in status red and rather take proper black decisions.
- Fix bad public noise processing after AI investigate closest disturbance and find nothing, also erase all same noise points in team members if one of them already investigated.


git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@6310 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
Kriplo
2013-08-23 16:27:36 +00:00
parent e49412eae9
commit 1adc9c542c
4 changed files with 51 additions and 12 deletions
+1 -1
View File
@@ -7351,7 +7351,7 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 ubAimTime,
iChance = gGameExternalOptions.ubMinimumCTH; iChance = gGameExternalOptions.ubMinimumCTH;
if ( gGameExternalOptions.ubMinimumCTH == 0 ) if ( gGameExternalOptions.ubMinimumCTH == 0 )
{ {
if ( PreRandom( gGameExternalOptions.usMinimumCTHDivisor ) == (gGameExternalOptions.usMinimumCTHDivisor - 1) ) if ( PreRandom( gGameExternalOptions.usMinimumCTHDivisor ) == (gGameExternalOptions.usMinimumCTHDivisor - 1) && fCalculateCTHDuringGunfire == TRUE )//dnl ch58 271009 Any Random function must not be used during calculation, only allow when you actually FireGun because AI became confused and sometimes do nothing
{ {
iChance = 1; iChance = 1;
} }
+13 -1
View File
@@ -1035,6 +1035,15 @@ INT32 ClosestReachableDisturbance(SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK,
// if we are there (at the noise gridno) // if we are there (at the noise gridno)
if (sGridNo == pSoldier->sGridNo) if (sGridNo == pSoldier->sGridNo)
{ {
for(uiLoop=0; uiLoop<guiNumMercSlots; uiLoop++)//dnl ch58 160813
{
pOpp = MercSlots[uiLoop];
if(pSoldier->bSide == pOpp->bSide && pSoldier->ubID != pOpp->ubID&& pSoldier->aiData.sNoiseGridno == pOpp->aiData.sNoiseGridno)
{
pOpp->aiData.sNoiseGridno = NOWHERE;// Erase for all from the same team as it not useful anymore, this will avoid others to check already tested location
pOpp->aiData.ubNoiseVolume = 0;
}
}
pSoldier->aiData.sNoiseGridno = NOWHERE; // wipe it out, not useful anymore pSoldier->aiData.sNoiseGridno = NOWHERE; // wipe it out, not useful anymore
pSoldier->aiData.ubNoiseVolume = 0; pSoldier->aiData.ubNoiseVolume = 0;
} }
@@ -1092,7 +1101,10 @@ INT32 ClosestReachableDisturbance(SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK,
else else
{ {
// degrade our public noise a bit // degrade our public noise a bit
*pusNoiseGridNo -= 2; //dnl ch58 160813
//*pusNoiseGridNo -= 2;
if(*pubNoiseVolume > 1)
(*pubNoiseVolume)--;
} }
} }
+32 -10
View File
@@ -54,7 +54,7 @@ UINT32 guiRedSeekTimeTotal = 0, guiRedHelpTimeTotal = 0, guiRedHideTimeTotal = 0
UINT32 guiRedSeekCounter = 0, guiRedHelpCounter = 0; guiRedHideCounter = 0; UINT32 guiRedSeekCounter = 0, guiRedHelpCounter = 0; guiRedHideCounter = 0;
#endif #endif
#define CENTER_OF_RING 11237 #define CENTER_OF_RING 11237//dnl!!!
#define MAX_FLANKS_RED 15 #define MAX_FLANKS_RED 15
#define MAX_FLANKS_YELLOW 25 #define MAX_FLANKS_YELLOW 25
@@ -3993,7 +3993,7 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK)
INT8 DecideActionBlack(SOLDIERTYPE *pSoldier) INT8 DecideActionBlack(SOLDIERTYPE *pSoldier)
{ {
INT32 iCoverPercentBetter, iOffense, iDefense, iChance; INT32 iCoverPercentBetter, iOffense, iDefense, iChance;
INT32 sClosestOpponent,sBestCover = NOWHERE; INT32 sClosestOpponent = NOWHERE,sBestCover = NOWHERE;//dnl ch58 160813
INT32 sClosestDisturbance; INT32 sClosestDisturbance;
INT16 ubMinAPCost; INT16 ubMinAPCost;
UINT8 ubCanMove; UINT8 ubCanMove;
@@ -5118,13 +5118,16 @@ INT16 ubMinAPCost;
if ( (INT32) PreRandom( 100 ) < iChance) if ( (INT32) PreRandom( 100 ) < iChance)
{ {
BestAttack.ubAimTime = BURSTING;
BestAttack.ubAPCost = BestAttack.ubAPCost + ubBurstAPs; BestAttack.ubAPCost = BestAttack.ubAPCost + ubBurstAPs;
// check for spread burst possibilities // check for spread burst possibilities
if (pSoldier->aiData.bAttitude != ATTACKSLAYONLY) if (pSoldier->aiData.bAttitude != ATTACKSLAYONLY)
{ {
CalcSpreadBurst( pSoldier, BestAttack.sTarget, BestAttack.bTargetLevel ); CalcSpreadBurst( pSoldier, BestAttack.sTarget, BestAttack.bTargetLevel );
} }
//dnl ch58 180813 After HAM 4 BURSTING is not in use any more, for burst bAimTime and bDoAutofire must be set to 0
pSoldier->aiData.bAimTime = 0;
pSoldier->bDoBurst = 1;
pSoldier->bDoAutofire = 0;
} }
} }
} }
@@ -5218,9 +5221,22 @@ INT16 ubMinAPCost;
if ((INT32) PreRandom( 100 ) < iChance || Weapon[pSoldier->inv[BestAttack.bWeaponIn].usItem].NoSemiAuto) if ((INT32) PreRandom( 100 ) < iChance || Weapon[pSoldier->inv[BestAttack.bWeaponIn].usItem].NoSemiAuto)
{ {
pSoldier->aiData.bAimTime = BestAttack.ubAimTime ; //dnl ch58 180813 After HAM 4 AUTOFIRING and sActualAimTime is not used in burst or autofire mode calculations and pSoldier->aiData.bAimTime must be 0
pSoldier->aiData.bAimTime = 0;
pSoldier->bDoBurst = 1; pSoldier->bDoBurst = 1;
BestAttack.ubAPCost = BestAttack.ubAPCost + CalcAPsToAutofire( pSoldier->CalcActionPoints(), &(pSoldier->inv[BestAttack.bWeaponIn]), pSoldier->bDoAutofire, pSoldier ) + sActualAimTime; INT16 ubHalfBurstAPs = CalcAPsToAutofire(pSoldier->CalcActionPoints(), &pSoldier->inv[BestAttack.bWeaponIn], 4, pSoldier);
if(Weapon[pSoldier->inv[BestAttack.bWeaponIn].usItem].NoSemiAuto)
iChance += 25;
if(pSoldier->bActionPoints > (2 * BestAttack.ubAPCost + ubHalfBurstAPs) && PreRandom(100) < iChance)
{
// Try short autofire to enhance chance of hitting
pSoldier->bDoAutofire = 4;
BestAttack.ubAPCost += ubHalfBurstAPs;
}
else
{
BestAttack.ubAPCost += ubBurstAPs;
}
} }
else else
{ {
@@ -5430,15 +5446,16 @@ INT16 ubMinAPCost;
if ( (INT32) PreRandom( 100 ) < iChance) if ( (INT32) PreRandom( 100 ) < iChance)
{ {
DebugMsg(TOPIC_JA2, DBG_LEVEL_3, "DecideActionBlack: Doing GL burst"); DebugMsg(TOPIC_JA2, DBG_LEVEL_3, "DecideActionBlack: Doing GL burst");
BestAttack.ubAimTime = BURSTING;
BestAttack.ubAPCost = BestAttack.ubAPCost + CalcAPsToBurst( pSoldier->CalcActionPoints(), &(pSoldier->inv[HANDPOS]), pSoldier ); BestAttack.ubAPCost = BestAttack.ubAPCost + CalcAPsToBurst( pSoldier->CalcActionPoints(), &(pSoldier->inv[HANDPOS]), pSoldier );
// check for spread burst possibilities // check for spread burst possibilities
if (pSoldier->aiData.bAttitude != ATTACKSLAYONLY) if (pSoldier->aiData.bAttitude != ATTACKSLAYONLY)
{ {
CalcSpreadBurst( pSoldier, BestAttack.sTarget, BestAttack.bTargetLevel ); CalcSpreadBurst( pSoldier, BestAttack.sTarget, BestAttack.bTargetLevel );
} }
//dnl ch58 200813 After HAM 4 BURSTING is not in use any more, for burst bAimTime and bDoAutofire must be set to 0
pSoldier->aiData.bAimTime = 0;
pSoldier->bDoBurst = 1; pSoldier->bDoBurst = 1;
pSoldier->bDoAutofire = 0;
} }
} }
} }
@@ -5590,7 +5607,11 @@ INT16 ubMinAPCost;
#endif #endif
//ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_TESTVERSION, L"AI %d taking cover, morale %d, from %d to %d", pSoldier->ubID, pSoldier->aiData.bAIMorale, pSoldier->sGridNo, sBestCover ); //ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_TESTVERSION, L"AI %d taking cover, morale %d, from %d to %d", pSoldier->ubID, pSoldier->aiData.bAIMorale, pSoldier->sGridNo, sBestCover );
pSoldier->aiData.usActionData = sBestCover; pSoldier->aiData.usActionData = sBestCover;
if(!TileIsOutOfBounds(sClosestOpponent))//dnl ch58 160813 After taking cover change facing toward closest enemy, currently such turn not charge APs and seems because AI is still in moving animation from take cover action
{
pSoldier->aiData.bNextAction = AI_ACTION_CHANGE_FACING;
pSoldier->aiData.usNextActionData = atan8(CenterX(sBestCover),CenterY(sBestCover),CenterX(sClosestOpponent),CenterY(sClosestOpponent));
}
return(AI_ACTION_TAKE_COVER); return(AI_ACTION_TAKE_COVER);
} }
@@ -7905,15 +7926,16 @@ void DecideAlertStatus( SOLDIERTYPE *pSoldier )
if ( (INT32) PreRandom( 100 ) < iChance) if ( (INT32) PreRandom( 100 ) < iChance)
{ {
DebugMsg(TOPIC_JA2, DBG_LEVEL_3, "DecideActionBlack: Doing GL burst"); DebugMsg(TOPIC_JA2, DBG_LEVEL_3, "DecideActionBlack: Doing GL burst");
BestAttack.ubAimTime = BURSTING;
BestAttack.ubAPCost = BestAttack.ubAPCost + CalcAPsToBurst( pSoldier->CalcActionPoints(), &(pSoldier->inv[HANDPOS]), pSoldier ); BestAttack.ubAPCost = BestAttack.ubAPCost + CalcAPsToBurst( pSoldier->CalcActionPoints(), &(pSoldier->inv[HANDPOS]), pSoldier );
// check for spread burst possibilities // check for spread burst possibilities
if (pSoldier->aiData.bAttitude != ATTACKSLAYONLY) if (pSoldier->aiData.bAttitude != ATTACKSLAYONLY)
{ {
CalcSpreadBurst( pSoldier, BestAttack.sTarget, BestAttack.bTargetLevel ); CalcSpreadBurst( pSoldier, BestAttack.sTarget, BestAttack.bTargetLevel );
} }
//dnl ch58 200813 After HAM 4 BURSTING is not in use any more, for burst bAimTime and bDoAutofire must be set to 0
pSoldier->aiData.bAimTime = 0;
pSoldier->bDoBurst = 1; pSoldier->bDoBurst = 1;
pSoldier->bDoAutofire = 0;
} }
} }
} }
+5
View File
@@ -1311,6 +1311,11 @@ INT32 FindSpotMaxDistFromOpponents(SOLDIERTYPE *pSoldier)
// Turn off the "reachable" flag for his current location // Turn off the "reachable" flag for his current location
// so we don't consider it // so we don't consider it
gpWorldLevelData[pSoldier->sGridNo].uiFlags &= ~(MAPELEMENT_REACHABLE); gpWorldLevelData[pSoldier->sGridNo].uiFlags &= ~(MAPELEMENT_REACHABLE);
//dnl ch58 170813 also don't use last two locations to avoid looping same decisions per turn
if(!TileIsOutOfBounds(pSoldier->sLastTwoLocations[0]))
gpWorldLevelData[pSoldier->sLastTwoLocations[0]].uiFlags &= ~(MAPELEMENT_REACHABLE);
else if(!TileIsOutOfBounds(pSoldier->sLastTwoLocations[1]))
gpWorldLevelData[pSoldier->sLastTwoLocations[1]].uiFlags &= ~(MAPELEMENT_REACHABLE);
for (sYOffset = -sMaxUp; sYOffset <= sMaxDown; sYOffset++) for (sYOffset = -sMaxUp; sYOffset <= sMaxDown; sYOffset++)
{ {