Brief: //dnl ch64

- Fixing Tank bursting shells problem, and some other tank related bugs.
Details:
- There are several problem with Tank handling, main was forcing to use gun although already decide to use machinegun which lead to bursting shells.
- Another one was related to machinegun usage as current autofire handling is not supported by TANK BURST animation which had limit to 6 rounds, so decision to fire anything different then 6 lead to complete wrong APs deduction.
- Fix some invalid animation decision as current tank cannot raise gun or move or check for cover.
- Fix problem with wrong return (INT8) although after introduction of 100AP system APs variables are INT16 which create bad APs calculation for tank.
- Fix general problem with burst and autofire when soldier decide to when swap weapons.


git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@6340 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
Kriplo
2013-08-31 10:22:25 +00:00
parent 1bb3f5a56a
commit f68f6131b9
8 changed files with 66 additions and 41 deletions
+1 -1
View File
@@ -3157,7 +3157,7 @@ void SwapObjs(SOLDIERTYPE* pSoldier, int leftSlot, int rightSlot, BOOLEAN fPerma
{
SwapObjs(&pSoldier->inv[ leftSlot ], &pSoldier->inv[ rightSlot ]);
if (fPermanent)
if(fPermanent && !TANK(pSoldier))//dnl ch64 290813 for current tank don't go further as it lead to invalid animation
{
//old usItem for the left slot is now stored in the right slot, and vice versa
HandleTacticalEffectsOfEquipmentChange(pSoldier, leftSlot, pSoldier->inv[ rightSlot ].usItem, pSoldier->inv[ leftSlot ].usItem);
+7 -7
View File
@@ -1960,7 +1960,7 @@ void GetAPChargeForShootOrStabWRTGunRaises( SOLDIERTYPE *pSoldier, INT32 sGridNo
ubDirection = (UINT8)GetDirectionFromGridNo( sGridNo, pSoldier );
// Is it the same as he's facing?
if ( ubDirection != pSoldier->ubDirection )
if ( ubDirection != pSoldier->ubDirection && !(ubDirection == pSoldier->pathing.bDesiredDirection && pSoldier->aiData.bLastAction == AI_ACTION_CHANGE_FACING) )//dnl ch64 310813 sometimes turning is in progress and APs already deducted
{
fAddingTurningCost = TRUE;
}
@@ -2285,7 +2285,7 @@ INT16 MinAPsToShootOrStab(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 bAimTime,
}
}
if ( AM_A_ROBOT( pSoldier ) )
if ( AM_A_ROBOT( pSoldier ) || TANK( pSoldier ) )//dnl ch64 300813 robots and tanks cannot do this
{
fAddingRaiseGunCost = FALSE;
}
@@ -2416,13 +2416,13 @@ INT16 MinPtsToMove(SOLDIERTYPE *pSoldier)
{
// look around all 8 directions and return lowest terrain cost
UINT8 cnt;
INT16 sLowest=127;
INT16 sLowest=32767;//dnl ch64 290813 100AP made return of INT8 or 127 obsolete as other variables are INT16
INT16 sCost;
INT32 sGridNo;
if ( TANK( pSoldier ) )
{
return( (INT8)sLowest);
return(sLowest);//dnl ch64 290813 100AP made INT8 return obsolete
}
// WANNE - BMP: FIX: Valid directions are only from 0-7!!
@@ -2438,7 +2438,7 @@ INT16 MinPtsToMove(SOLDIERTYPE *pSoldier)
}
}
}
return( (INT8)sLowest);
return(sLowest);//dnl ch64 290813 100AP made INT8 return obsolete
}
INT8 PtsToMoveDirection(SOLDIERTYPE *pSoldier, INT8 bDirection )
@@ -3763,7 +3763,7 @@ INT16 GetAPsToJumpOver( SOLDIERTYPE *pSoldier )
// HEADROCK HAM 3.6: Calculate the actual AP cost to add this many Extra Aiming levels, taking into account
// APBP Constants and extra game features.
INT32 CalcAPCostForAiming( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo, INT8 bAimTime )
INT32 CalcAPCostForAiming( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo, INT8 bAimTime, UINT8 ubAddRaiseGunCost )//dnl ch64 310813
{
INT16 sAPCost = 0;
UINT16 usItemNum = pSoldier->inv[HANDPOS].usItem;
@@ -3771,7 +3771,7 @@ INT32 CalcAPCostForAiming( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo, INT8 bAim
Assert(pSoldier != NULL);
Assert(&pSoldier->inv[HANDPOS] != NULL);
if (!( gAnimControl[ pSoldier->usAnimState ].uiFlags & ( ANIM_FIREREADY | ANIM_FIRE )))
if (ubAddRaiseGunCost && !TANK(pSoldier) && !( gAnimControl[ pSoldier->usAnimState ].uiFlags & ( ANIM_FIREREADY | ANIM_FIRE )))//dnl ch64 310813
{
// Weapon not ready, check aiming from hip, else add raise gun cost
//if (!pSoldier->IsValidShotFromHip(bAimTime,sTargetGridNo))
+1 -1
View File
@@ -368,7 +368,7 @@ UINT16 GetAPsToReloadRobot( SOLDIERTYPE *pSoldier, SOLDIERTYPE *pRobot );
INT16 GetAPsToReloadGunWithAmmo( SOLDIERTYPE *pSoldier, OBJECTTYPE * pGun, OBJECTTYPE * pAmmo, BOOLEAN usAllAPs = TRUE );
INT16 GetAPsToAutoReload( SOLDIERTYPE * pSoldier );
INT32 CalcAPCostForAiming( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo, INT8 bAimTime );
INT32 CalcAPCostForAiming( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo, INT8 bAimTime, UINT8 ubAddRaiseGunCost=TRUE );//dnl ch64 310813
INT8 CalcAimingLevelsAvailableWithAP( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo, INT8 bAPsLeft );
// SANDRO - added these:
+7
View File
@@ -389,6 +389,13 @@ BOOLEAN AdjustToNextAnimationFrame( SOLDIERTYPE *pSoldier )
pSoldier->usAniCode = 3;
else if(pSoldier->usAnimState == FIRE_BURST_LOW_STAND || pSoldier->usAnimState == LOW_BURST_ALTERNATIVE_STAND && pSoldier->usAniCode == 37) //we are firing down to something very close, last shot
pSoldier->usAniCode = 14;
else if(pSoldier->usAnimState == TANK_BURST)//dnl ch64 280813 fix 6 round burst limitation
{
if(pSoldier->bDoBurst < pSoldier->bDoAutofire)//!!! this will be fine as long you not decide to equip tank with other weapons add limitted ammo, weapon jam, etc.
pSoldier->usAniCode = 4;
else
pSoldier->usAniCode = 34;
}
}
OBJECTTYPE* pObjUsed = pSoldier->GetUsedWeapon( &pSoldier->inv[ pSoldier->ubAttackingHand ] );
+5 -5
View File
@@ -3656,7 +3656,7 @@ BOOLEAN SOLDIERTYPE::EVENT_InitNewSoldierAnim( UINT16 usNewState, UINT16 usStart
{
// ATE: Also check for the transition anims to not reset this
// this should have used a flag but we're out of them....
if ( usNewState != READY_ALTERNATIVE_STAND && usNewState != READY_RIFLE_STAND && usNewState != READY_RIFLE_PRONE && usNewState != READY_RIFLE_CROUCH && usNewState != ROBOT_SHOOT )
if ( usNewState != READY_ALTERNATIVE_STAND && usNewState != READY_RIFLE_STAND && usNewState != READY_RIFLE_PRONE && usNewState != READY_RIFLE_CROUCH && usNewState != ROBOT_SHOOT && usNewState != TANK_SHOOT && usNewState != TANK_BURST )//dnl ch64 300813
{
this->sLastTarget = NOWHERE;
}
@@ -18154,8 +18154,8 @@ BOOLEAN SOLDIERTYPE::IsValidShotFromHip( INT16 bAimTime, INT32 iTrgGridNo )
{
return( FALSE );
}
// robots cannot do this
if ( AM_A_ROBOT( this ) )
// robots and tanks cannot do this
if ( AM_A_ROBOT( this ) || TANK( this ) )//dnl ch64 300813
{
return( FALSE );
}
@@ -18206,8 +18206,8 @@ BOOLEAN SOLDIERTYPE::IsValidPistolFastShot( INT16 bAimTime, INT32 iTrgGridNo )
{
return( FALSE );
}
// robots cannot do this
if ( AM_A_ROBOT( this ) )
// robots and tanks cannot do this
if ( AM_A_ROBOT( this ) || TANK( this ) )//dnl ch64 300813
{
return( FALSE );
}
+8 -4
View File
@@ -1233,7 +1233,8 @@ void CancelAIAction(SOLDIERTYPE *pSoldier, UINT8 ubForce)
#endif
// re-enable cover checking, something is new or something strange happened
SkipCoverCheck = FALSE;
if(!TANK(pSoldier))//dnl ch64 290813
SkipCoverCheck = FALSE;
// turn off new situation flag to stop this from repeating all the time!
if ( pSoldier->aiData.bNewSituation == IS_NEW_SITUATION )
@@ -1502,6 +1503,8 @@ void RefreshAI(SOLDIERTYPE *pSoldier)
if (pSoldier->aiData.bAlertStatus == STATUS_YELLOW)
SkipCoverCheck = FALSE;
if(TANK(pSoldier))//dnl ch64 290813 tanks don't have move animations
SkipCoverCheck = TRUE;
// if he's in battle or knows opponents are here
if (gfTurnBasedAI)
@@ -1591,7 +1594,8 @@ INT8 ExecuteAction(SOLDIERTYPE *pSoldier)
// in most cases, merc will change location, or may cause damage to opponents,
// so a new cover check will be necessary. Exceptions handled individually.
SkipCoverCheck = FALSE;
if(!TANK(pSoldier))//dnl ch64 290813
SkipCoverCheck = FALSE;
// reset this field, too
pSoldier->aiData.bLastAttackHit = FALSE;
@@ -1600,7 +1604,7 @@ INT8 ExecuteAction(SOLDIERTYPE *pSoldier)
UINT16 usHandItem = pSoldier->inv[HANDPOS].usItem;
INT8 bSlot;
#if 0//dnl ch64 260813 decision to use machinegun or cannon is done in DecideAction, this here will just lead into burst with cannon if decision was use machinegun
if (TANK(pSoldier))
{
// No cannon selected to fire
@@ -1618,7 +1622,7 @@ INT8 ExecuteAction(SOLDIERTYPE *pSoldier)
}
}
}
#endif
UINT16 usSoldierIndex; // added by SANDRO
#ifdef TESTAICONTROL
+21 -15
View File
@@ -164,7 +164,7 @@ void CalcBestShot(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestShot, BOOLEAN shootUns
UINT8 ubChanceToReallyHit = 0;
INT16 ubChanceToHit,ubChanceToHit2,ubBestAimTime,ubChanceToGetThrough,ubBestChanceToHit;
SOLDIERTYPE *pOpponent;
INT16 ubBurstAPs;
//INT16 ubBurstAPs;//dnl ch64 270813
INT8 bScopeMode;
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"CalcBestShot");
@@ -174,7 +174,7 @@ void CalcBestShot(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestShot, BOOLEAN shootUns
pSoldier->usAttackingWeapon = pSoldier->inv[HANDPOS].usItem;
pSoldier->bWeaponMode = WM_NORMAL;
ubBurstAPs = CalcAPsToBurst( pSoldier->CalcActionPoints( ), &(pSoldier->inv[HANDPOS]), pSoldier );
//ubBurstAPs = CalcAPsToBurst( pSoldier->CalcActionPoints( ), &(pSoldier->inv[HANDPOS]), pSoldier );//dnl ch64 270813
InitAttackType(pBestShot); // set all structure fields to defaults
@@ -357,7 +357,7 @@ void CalcBestShot(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestShot, BOOLEAN shootUns
ubRawAPCost = MinAPsToShootOrStab(pSoldier,pOpponent->sGridNo,0,FALSE);
// calculate the maximum possible aiming time
#if 0//dnl ch64 270813 maybe I'm wrong but don't see purpose of this
if ( TANK( pSoldier ) )
{
ubMaxPossibleAimTime = pSoldier->bActionPoints - ubMinAPcost;
@@ -373,6 +373,7 @@ void CalcBestShot(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestShot, BOOLEAN shootUns
}
else
#endif
{
// HEADROCK HAM 3.6: Calculation must take into account APBP constants and other aiming modifications!
INT8 bAPsLeft = pSoldier->bActionPoints - ubMinAPcost;
@@ -389,11 +390,13 @@ void CalcBestShot(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestShot, BOOLEAN shootUns
//NumMessage("ubAimTime = ",ubAimTime);
//dnl ch59 180813 Find true best chance to hit depending of stance so AI would be more eager to attack
ubChanceToHit = AICalcChanceToHitGun(pSoldier, pOpponent->sGridNo,ubAimTime, AIM_SHOT_TORSO, pOpponent->pathing.bLevel, STANDING);
if((ubChanceToHit2=AICalcChanceToHitGun(pSoldier, pOpponent->sGridNo, ubAimTime, AIM_SHOT_TORSO, pOpponent->pathing.bLevel, CROUCHING)) > ubChanceToHit)
ubChanceToHit = ubChanceToHit2;
if((ubChanceToHit2=AICalcChanceToHitGun(pSoldier, pOpponent->sGridNo, ubAimTime, AIM_SHOT_TORSO, pOpponent->pathing.bLevel, PRONE)) > ubChanceToHit)
ubChanceToHit = ubChanceToHit2;
if(!TANK(pSoldier))//dnl ch64 270813
{
if((ubChanceToHit2=AICalcChanceToHitGun(pSoldier, pOpponent->sGridNo, ubAimTime, AIM_SHOT_TORSO, pOpponent->pathing.bLevel, CROUCHING)) > ubChanceToHit)
ubChanceToHit = ubChanceToHit2;
if((ubChanceToHit2=AICalcChanceToHitGun(pSoldier, pOpponent->sGridNo, ubAimTime, AIM_SHOT_TORSO, pOpponent->pathing.bLevel, PRONE)) > ubChanceToHit)
ubChanceToHit = ubChanceToHit2;
}
// ExtMen[pOpponent->ubID].haveStats = TRUE;
//NumMessage("chance to Hit = ",ubChanceToHit);
@@ -417,10 +420,13 @@ void CalcBestShot(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestShot, BOOLEAN shootUns
ubAimTime = APBPConstants[AP_MIN_AIM_ATTACK];
//dnl ch59 180813 Find true best chance to hit depending of stance for autofire
ubChanceToHit = AICalcChanceToHitGun(pSoldier, pOpponent->sGridNo, ubAimTime, AIM_SHOT_TORSO, pOpponent->pathing.bLevel, STANDING);
if((ubChanceToHit2=AICalcChanceToHitGun(pSoldier, pOpponent->sGridNo, ubAimTime, AIM_SHOT_TORSO, pOpponent->pathing.bLevel, CROUCHING)) > ubChanceToHit)
ubChanceToHit = ubChanceToHit2;
if((ubChanceToHit2=AICalcChanceToHitGun(pSoldier, pOpponent->sGridNo, ubAimTime, AIM_SHOT_TORSO, pOpponent->pathing.bLevel, PRONE)) > ubChanceToHit)
ubChanceToHit = ubChanceToHit2;
if(!TANK(pSoldier))//dnl ch64 270813
{
if((ubChanceToHit2=AICalcChanceToHitGun(pSoldier, pOpponent->sGridNo, ubAimTime, AIM_SHOT_TORSO, pOpponent->pathing.bLevel, CROUCHING)) > ubChanceToHit)
ubChanceToHit = ubChanceToHit2;
if((ubChanceToHit2=AICalcChanceToHitGun(pSoldier, pOpponent->sGridNo, ubAimTime, AIM_SHOT_TORSO, pOpponent->pathing.bLevel, PRONE)) > ubChanceToHit)
ubChanceToHit = ubChanceToHit2;
}
Assert( ubRawAPCost > 0);
iHitRate = (pSoldier->bActionPoints * ubChanceToHit) / (ubRawAPCost + ubAimTime);
iBestHitRate = iHitRate;
@@ -1276,10 +1282,10 @@ void CalcBestThrow(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
pBestThrow->ubOpponent = ubOpponentID[ubLoop];
pBestThrow->ubAimTime = ubMaxPossibleAimTime;
pBestThrow->ubChanceToReallyHit = ubChanceToReallyHit;
pBestThrow->sTarget = sGridNo;
pBestThrow->sTarget = sGridNo;
pBestThrow->iAttackValue = iAttackValue;
pBestThrow->ubAPCost = CalcTotalAPsToAttack(pSoldier, pBestThrow->sTarget, TRUE, pBestThrow->ubAimTime);//dnl ch63 240813
pBestThrow->bTargetLevel = bOpponentLevel[ubLoop];
pBestThrow->ubAPCost = ubMinAPcost + CalcAPCostForAiming(pSoldier, sGridNo, ubMaxPossibleAimTime, FALSE);//dnl ch64 310813
pBestThrow->bTargetLevel = bOpponentLevel[ubLoop];
//sprintf(tempstr,"new best THROW AttackValue = %d at grid #%d",iAttackValue/100000,gridno);
//PopMessage(tempstr);
+16 -8
View File
@@ -4766,7 +4766,7 @@ INT16 ubMinAPCost;
}
////////////////////////////////////////////////////////////////////////////////////
}
if (BestThrow.ubPossible && ((BestThrow.iAttackValue > BestAttack.iAttackValue) || (ubBestAttackAction == AI_ACTION_NONE)))
if (BestThrow.ubPossible && ((BestThrow.iAttackValue > BestAttack.iAttackValue) || (ubBestAttackAction == AI_ACTION_NONE)) && !(TANK(pSoldier) && ubBestAttackAction == AI_ACTION_FIRE_GUN && BestShot.ubChanceToReallyHit > 20 && Random(2)))//dnl ch64 290813 tank always had better chance to fire from cannon so this will increase probabilty to use machinegun too
{
ubBestAttackAction = AI_ACTION_TOSS_PROJECTILE;
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"best action = throw something");
@@ -5175,17 +5175,14 @@ INT16 ubMinAPCost;
dTotalRecoil += AICalcRecoilForShot( pSoldier, &(pSoldier->inv[BestShot.bWeaponIn]), pSoldier->bDoAutofire );
ubBurstAPs = CalcAPsToAutofire( pSoldier->CalcActionPoints(), &(pSoldier->inv[BestShot.bWeaponIn]), pSoldier->bDoAutofire, pSoldier );
}
while( pSoldier->bActionPoints >= BestShot.ubAPCost + ubBurstAPs + sActualAimTime && pSoldier->inv[ pSoldier->ubAttackingHand ][0]->data.gun.ubGunShotsLeft >= pSoldier->bDoAutofire
&& dTotalRecoil <= 10.0f );
while( pSoldier->bActionPoints >= BestShot.ubAPCost + ubBurstAPs + sActualAimTime && pSoldier->inv[ BestAttack.bWeaponIn ][0]->data.gun.ubGunShotsLeft >= pSoldier->bDoAutofire && dTotalRecoil <= 10.0f );//dnl ch64 260813 pSoldier->ubAttackingHand is wrong because decision is to use BestAttack.bWeaponIn
} else {
do
{
pSoldier->bDoAutofire++;
ubBurstAPs = CalcAPsToAutofire( pSoldier->CalcActionPoints(), &(pSoldier->inv[BestAttack.bWeaponIn]), pSoldier->bDoAutofire, pSoldier );
}
while( pSoldier->bActionPoints >= BestAttack.ubAPCost + ubBurstAPs &&
pSoldier->inv[ pSoldier->ubAttackingHand ][0]->data.gun.ubGunShotsLeft >= pSoldier->bDoAutofire &&
GetAutoPenalty(&pSoldier->inv[ BestAttack.bWeaponIn ], gAnimControl[ pSoldier->usAnimState ].ubEndHeight == ANIM_PRONE)*pSoldier->bDoAutofire <= 80);
while( pSoldier->bActionPoints >= BestAttack.ubAPCost + ubBurstAPs && pSoldier->inv[ BestAttack.bWeaponIn ][0]->data.gun.ubGunShotsLeft >= pSoldier->bDoAutofire && GetAutoPenalty(&pSoldier->inv[ BestAttack.bWeaponIn ], gAnimControl[ pSoldier->usAnimState ].ubEndHeight == ANIM_PRONE)*pSoldier->bDoAutofire <= 80);//dnl ch64 260813 pSoldier->ubAttackingHand is wrong because decision is to use BestAttack.bWeaponIn
}
pSoldier->bDoAutofire--;
@@ -5251,7 +5248,7 @@ INT16 ubMinAPCost;
pSoldier->bDoBurst = 1;
INT16 ubHalfBurstAPs = CalcAPsToAutofire(pSoldier->CalcActionPoints(), &pSoldier->inv[BestAttack.bWeaponIn], 4, pSoldier);
if(Weapon[pSoldier->inv[BestAttack.bWeaponIn].usItem].NoSemiAuto)
iChance += 25;
iChance = 35;
if(pSoldier->bActionPoints > (2 * BestAttack.ubAPCost + ubHalfBurstAPs) && PreRandom(100) < iChance)
{
// Try short autofire to enhance chance of hitting
@@ -5400,13 +5397,24 @@ INT16 ubMinAPCost;
//////////////////////////////////////////////////////////////////////////
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"OTHERWISE, JUST GO AHEAD & ATTACK!");
//dnl ch64 270813 must be as below RearrangePocket with FOREVER will screw already decided BURST or AUTOFIRE
INT8 bDoBurst = pSoldier->bDoBurst;
UINT8 bDoAutofire = pSoldier->bDoAutofire;
// swap weapon to hand if necessary
if (BestAttack.bWeaponIn != HANDPOS)
{
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"decideactionblack: swap weapon into hand");
RearrangePocket(pSoldier,HANDPOS,BestAttack.bWeaponIn,FOREVER);
}
if(ubBestAttackAction == AI_ACTION_FIRE_GUN && bDoBurst == 1)//dnl ch64 270813
{
pSoldier->bDoAutofire = bDoAutofire;
pSoldier->bDoBurst = bDoBurst;
if(bDoAutofire > 1)
pSoldier->bWeaponMode = WM_AUTOFIRE;
else
pSoldier->bWeaponMode = WM_BURST;
}
if (fChangeStanceFirst)
{ // currently only for guns...