Brief: //dnl ch63

- Fixing AI problems when they use launchers.
Details:
- Seems from implementation of 100AP system and new attachment system and new kind of GL launchers, AI use them improperly or not used at all. Bugs was:
- Bursting grenades from non burst launcher.
- Not use GL if grenade is already in it
- Not firing from rocket launcher if couldn't find hand grenade.
- Refusing to launch grenade from attached GL if couldn't find grenade in other pockets.
- Never fire from single rocket launchers like LAW.
- Incorrect chance to throw calculation for GLs which lead into no decision to throw.
- Whole cylinder of grenades was permanently remove from pocket after reloading launcher.


git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@6321 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
Kriplo
2013-08-25 20:30:46 +00:00
parent 29beae22d5
commit 571a2940e6
4 changed files with 65 additions and 32 deletions
+7 -2
View File
@@ -3713,7 +3713,12 @@ INT8 FindAmmoToReload( SOLDIERTYPE * pSoldier, INT8 bWeaponIn, INT8 bExcludeSlot
{
return( NO_SLOT );
}
if(pSoldier->bWeaponMode == WM_ATTACHED_GL || pSoldier->bWeaponMode == WM_ATTACHED_GL_BURST || pSoldier->bWeaponMode == WM_ATTACHED_GL_AUTO)//dnl ch63 230813
{
pObj = FindAttachment_GrenadeLauncher(&pSoldier->inv[bWeaponIn]);
}
else
{
// Flugente: check for underbarrel weapons and use that object if necessary
pObj = pSoldier->GetUsedWeapon( &(pSoldier->inv[bWeaponIn]) );
@@ -3721,7 +3726,7 @@ INT8 FindAmmoToReload( SOLDIERTYPE * pSoldier, INT8 bWeaponIn, INT8 bExcludeSlot
if ((*pObj)[0]->data.gun.ubGunShotsLeft && !((*pObj)[0]->data.gun.ubGunState & GS_CARTRIDGE_IN_CHAMBER) )
return bWeaponIn;
//</SB>
}
if ( Item[pObj->usItem].usItemClass == IC_GUN && !Item[pObj->usItem].cannon )
{
//MM: make reload use crates/boxes if not in combat...
+7 -4
View File
@@ -2330,11 +2330,11 @@ INT16 MinAPsToShootOrStab(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 bAimTime,
else
bAPCost += APBPConstants[AP_CHANGE_TARGET];
}
#if 0//dnl ch63 240813 this seems very wrong, in most case (pSoldier->bActionPoints > bFullAps) and this will return less points then is actually required and could cancel some AI actions, like throwing grenades
// the minimum AP cost of ANY shot can NEVER be more than merc's maximum APs!
if ( bAPCost > bFullAPs )
bAPCost = bFullAPs;
#endif
// this SHOULD be impossible, but nevertheless...
if ( bAPCost < 1 )
bAPCost = 1;
@@ -3478,8 +3478,11 @@ INT16 MinAPsToThrow( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 ubAddTurningCos
UINT32 uiMercFlags;
UINT8 ubDirection;
// make sure the guy's actually got a throwable item in his hand!
usInHand = pSoldier->inv[ HANDPOS ].usItem;
if(pSoldier->bWeaponMode == WM_ATTACHED_GL || pSoldier->bWeaponMode == WM_ATTACHED_GL_BURST || pSoldier->bWeaponMode == WM_ATTACHED_GL_AUTO)//dnl ch63 240813
usInHand = GetAttachedGrenadeLauncher(&pSoldier->inv[HANDPOS]);
else
// make sure the guy's actually got a throwable item in his hand!
usInHand = pSoldier->inv[HANDPOS].usItem;
if ( ( !(Item[ usInHand ].usItemClass & IC_GRENADE) &&
!(Item[ usInHand ].usItemClass & IC_LAUNCHER)) )
+49 -24
View File
@@ -112,7 +112,13 @@ void LoadWeaponIfNeeded(SOLDIERTYPE *pSoldier)
pSoldier->inv[HANDPOS].AttachObject(pSoldier,&gTempObject,FALSE);
}
else if (pSoldier->inv[bPayloadPocket].MoveThisObjectTo(gTempObject, 1) == 0) {
pSoldier->inv[HANDPOS].AttachObject( pSoldier,&gTempObject,FALSE);
if(pSoldier->inv[HANDPOS].AttachObject(pSoldier, &gTempObject, FALSE))//dnl ch63 250813 return back rest of object or drop it if not proper attachment
{
if(gTempObject.ubNumberOfObjects == 1 && gTempObject[0]->data.objectStatus > 0)
gTempObject.MoveThisObjectTo(pSoldier->inv[bPayloadPocket], 1);
}
else
AddItemToPool(pSoldier->sGridNo, &gTempObject, 0, pSoldier->pathing.bLevel, WORLD_ITEM_DROPPED_FROM_ENEMY, -1);
}
}
@@ -607,6 +613,7 @@ void CalcBestThrow(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
UINT8 ubSafetyMargin = 0;
UINT8 ubDiff;
INT8 bEndLevel;
OBJECTTYPE *pObjGL = NULL;//dnl ch63 240813
usInHand = pSoldier->inv[HANDPOS].usItem;
usGrenade = NOTHING;
@@ -642,18 +649,28 @@ void CalcBestThrow(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
{
// use up pocket 2 first, they get left as drop items
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"calcbestthrow: buddy's got a GL");
bPayloadPocket = FindGLGrenade( pSoldier );
if (bPayloadPocket == NO_SLOT)
//dnl ch63 240813 Check if grenade is already attach or find one in pockets
bPayloadPocket = HANDPOS;
pObjGL = FindAttachment_GrenadeLauncher(&pSoldier->inv[bPayloadPocket]);
OBJECTTYPE *pAttachment = FindLaunchableAttachment(&pSoldier->inv[bPayloadPocket], usInHand);
if(pAttachment->exists())
{
return; // no grenades, can't fire the GLAUNCHER
ubSafetyMargin = (UINT8)Explosive[Item[pAttachment->usItem].ubClassIndex].ubRadius;
usGrenade = pAttachment->usItem;
}
ubSafetyMargin = (UINT8)Explosive[ Item[ pSoldier->inv[ bPayloadPocket ].usItem ].ubClassIndex ].ubRadius;
usGrenade = pSoldier->inv[ bPayloadPocket ].usItem;
else if((bPayloadPocket=FindAmmoToReload(pSoldier, bPayloadPocket, NO_SLOT)) != NO_SLOT)
{
ubSafetyMargin = (UINT8)Explosive[Item[pSoldier->inv[bPayloadPocket].usItem].ubClassIndex].ubRadius;
usGrenade = pSoldier->inv[bPayloadPocket].usItem;
}
else
return;
}
else if ( Item[usInHand].rocketlauncher )
{
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"calcbestthrow: buddy's got a rocket launcher");
// put in hand
bPayloadPocket = HANDPOS;//dnl ch63 240813
if ( Item[usInHand].singleshotrocketlauncher )
// as C1
ubSafetyMargin = (UINT8)Explosive[ Item[ C1 ].ubClassIndex ].ubRadius;
@@ -1146,7 +1163,8 @@ void CalcBestThrow(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
else
{
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"calcbestthrow: checking chance for launcher to beat cover");
ubChanceToGetThrough = 100 * CalculateLaunchItemChanceToGetThrough( pSoldier, &(pSoldier->inv[ bPayloadPocket ] ), sGridNo, bOpponentLevel[ubLoop], 0, &sEndGridNo, TRUE, &bEndLevel, FALSE ); //NumMessage("Chance to get through = ",ubChanceToGetThrough);
ubChanceToGetThrough = 100 * CalculateLaunchItemChanceToGetThrough( pSoldier, (pObjGL ? pObjGL : &pSoldier->inv[bPayloadPocket]), sGridNo, bOpponentLevel[ubLoop], 0, &sEndGridNo, TRUE, &bEndLevel, FALSE );//dnl ch63 240813
//NumMessage("Chance to get through = ",ubChanceToGetThrough);
// if we can't possibly get through all the cover
if (ubChanceToGetThrough == 0 )
{
@@ -1185,7 +1203,7 @@ void CalcBestThrow(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
// calculate the maximum possible aiming time
// HEADROCK HAM 4: Required for new Aiming Level Limits function
ubMaxPossibleAimTime = min( AllowedAimingLevels(pSoldier, sGridNo), pSoldier->bActionPoints - ubMinAPcost);
ubMaxPossibleAimTime = CalcAimingLevelsAvailableWithAP(pSoldier, sGridNo, pSoldier->bActionPoints-ubMinAPcost);//dnl ch63 250813
DebugMsg(TOPIC_JA2 , DBG_LEVEL_3 , String("Max Possible Aim Time = %d",ubMaxPossibleAimTime ));
// calc next attack's minimum AP cost (excludes readying & turning)
@@ -1201,6 +1219,7 @@ void CalcBestThrow(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
}
else
{
ubMaxPossibleAimTime = APBPConstants[AP_MIN_AIM_ATTACK];//dnl ch63 240813
// NB grenade launcher is NOT a direct fire weapon!
ubRawAPCost = (UINT8) MinAPsToThrow( pSoldier, sGridNo, FALSE );
DebugMsg(TOPIC_JA2 , DBG_LEVEL_3 , String("Raw AP Cost = %d",ubRawAPCost ));
@@ -1259,7 +1278,7 @@ void CalcBestThrow(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
pBestThrow->ubChanceToReallyHit = ubChanceToReallyHit;
pBestThrow->sTarget = sGridNo;
pBestThrow->iAttackValue = iAttackValue;
pBestThrow->ubAPCost = ubMinAPcost + ubMaxPossibleAimTime;
pBestThrow->ubAPCost = CalcTotalAPsToAttack(pSoldier, pBestThrow->sTarget, TRUE, pBestThrow->ubAimTime);//dnl ch63 240813
pBestThrow->bTargetLevel = bOpponentLevel[ubLoop];
//sprintf(tempstr,"new best THROW AttackValue = %d at grid #%d",iAttackValue/100000,gridno);
@@ -1875,6 +1894,14 @@ INT32 EstimateThrowDamage( SOLDIERTYPE *pSoldier, UINT8 ubItemPos, SOLDIERTYPE *
else
return 0;
}
else if(IsGrenadeLauncherAttached(&pSoldier->inv[ubItemPos]))//dnl ch63 240813 situation when grenade is already in launcher
{
OBJECTTYPE *pAttachment = FindLaunchableAttachment(&pSoldier->inv[ubItemPos], GetAttachedGrenadeLauncher(&pSoldier->inv[ubItemPos]));
if(pAttachment->exists())
ubExplosiveIndex = Item[pAttachment->usItem].ubClassIndex;
else
return(0);
}
else if ( Explosive[Item[pSoldier->inv[ ubItemPos ].usItem].ubClassIndex].ubType == EXPLOSV_SMOKE )
return 5;
else
@@ -2311,33 +2338,30 @@ void CheckIfTossPossible(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
{
// Consider rocket launcher/cannon
pBestThrow->bWeaponIn = FindRocketLauncherOrCannon( pSoldier );
if ( pBestThrow->bWeaponIn == NO_SLOT || ( !EnoughAmmo( pSoldier, FALSE, pBestThrow->bWeaponIn) && FindAmmoToReload( pSoldier, pBestThrow->bWeaponIn, NO_SLOT) == NO_SLOT) )
if ( pBestThrow->bWeaponIn == NO_SLOT || ( !EnoughAmmo( pSoldier, FALSE, pBestThrow->bWeaponIn) && FindAmmoToReload( pSoldier, pBestThrow->bWeaponIn, NO_SLOT) == NO_SLOT) )
{
//no rocket launcher (or empty) -- let's look for an underslung/attached GL
// AND a launchable grenade!
INT8 bOldWeaponMode = pSoldier->bWeaponMode;
pSoldier->bWeaponMode = WM_ATTACHED_GL; // So that EnoughAmmo will check for a grenade not a bullet
INT8 bGunSlot = FindAIUsableObjClass( pSoldier, IC_GUN );
if ( bGunSlot != NO_SLOT &&
IsGrenadeLauncherAttached(&pSoldier->inv[bGunSlot]) &&
( EnoughAmmo( pSoldier, FALSE, bGunSlot) || FindGLGrenade( pSoldier) == NO_SLOT) )
{
//dnl ch63 240813
// no rocket launcher (or empty) -- let's look for an underslung/attached GL and a launchable grenade!
INT8 bGunSlot = FindAIUsableObjClass(pSoldier, IC_GUN);
pSoldier->bWeaponMode = WM_ATTACHED_GL;// So that EnoughAmmo will check for a grenade not a bullet, also need in calculation during CalcBestThrow
if(bGunSlot != NO_SLOT && IsGrenadeLauncherAttached(&pSoldier->inv[bGunSlot]) && (EnoughAmmo(pSoldier, FALSE, bGunSlot) || FindAmmoToReload(pSoldier, bGunSlot, NO_SLOT) != NO_SLOT))
pBestThrow->bWeaponIn = bGunSlot;
}
else
{
// no rocket launcher or attached GL, consider grenades
pBestThrow->bWeaponIn = FindThrowableGrenade( pSoldier );
pBestThrow->bWeaponIn = FindThrowableGrenade(pSoldier);
pSoldier->bWeaponMode = WM_NORMAL;
}
pSoldier->bWeaponMode = bOldWeaponMode;
}
else
{
// Have rocket launcher... maybe have grenades as well. which one to use?
if ( pSoldier->aiData.bAIMorale > MORALE_WORRIED && PreRandom( 2 ) )
{
pBestThrow->bWeaponIn = FindThrowableGrenade( pSoldier );
//dnl ch63 240813 use grenade if have one
INT8 bGrenadeIn = FindThrowableGrenade(pSoldier);
if(bGrenadeIn != NO_SLOT)
pBestThrow->bWeaponIn = bGrenadeIn;
}
}
}
@@ -2372,6 +2396,7 @@ void CheckIfTossPossible(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
RearrangePocket( pSoldier, HANDPOS, pBestThrow->bWeaponIn, TEMPORARILY );
}
}
pSoldier->bWeaponMode = WM_NORMAL;//dnl ch63 240813
}
INT8 CountAdjacentSpreadTargets( SOLDIERTYPE * pSoldier, INT16 sFirstTarget, INT8 bTargetLevel )
+2 -2
View File
@@ -5484,8 +5484,8 @@ INT16 ubMinAPCost;
}
}
}
if(ubBestAttackAction == AI_ACTION_TOSS_PROJECTILE && IsGrenadeLauncherAttached(&pSoldier->inv[HANDPOS]))//dnl ch63 240813
pSoldier->bWeaponMode = WM_ATTACHED_GL;
return(ubBestAttackAction);
}