Fix for knife and punch attacks attack from GridNo (by Shadooow).

This fixes punching and stabbing target through door and improves attacking at prone target which was previously calculating shortest route only to the "main" GridNo of the prone target despite he occupies two in this position. It also removes the possibility of attacking from diagonal tile - it was never intended to happen and was calculating APs incorrectly.

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@9024 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
Sevenfm
2021-05-14 19:50:22 +00:00
parent 5fb5520380
commit 09ea9f3fb7
4 changed files with 171 additions and 214 deletions
+12 -67
View File
@@ -858,57 +858,20 @@ INT32 HandleItem( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel, UINT16 usHa
//TRY PUNCHING
if ( Item[ usHandItem ].usItemClass == IC_PUNCH )
{
//INT16 sCnt;
INT32 sSpot;
UINT8 ubGuyThere;
INT32 sGotLocation = NOWHERE;
BOOLEAN fGotAdjacent = FALSE;
for ( INT8 sCnt = 0; sCnt < NUM_WORLD_DIRECTIONS; sCnt++ )
// See if we can get there to stab
sActionGridNo = FindAdjacentGridEx(pSoldier, sGridNo, &ubDirection, &sAdjustedGridNo, TRUE, FALSE);
if (sActionGridNo == -1)
{
sSpot = NewGridNo( pSoldier->sGridNo, DirectionInc( sCnt ) );
// Make sure movement costs are OK....
if ( gubWorldMovementCosts[ sSpot ][ sCnt ][ bLevel ] >= TRAVELCOST_BLOCKED )
{
continue;
}
// Check for who is there...
ubGuyThere = WhoIsThere2( sSpot, pSoldier->pathing.bLevel );
if ( pTargetSoldier != NULL && ubGuyThere == pTargetSoldier->ubID )
{
// We've got a guy here....
// Who is the one we want......
sGotLocation = sSpot;
sAdjustedGridNo = pTargetSoldier->sGridNo;
ubDirection = ( UINT8 )sCnt;
break;
}
sActionGridNo = FindAdjacentGridEx(pSoldier, usMapPos, &ubDirection, &sAdjustedGridNo, TRUE, FALSE);
}
if (TileIsOutOfBounds(sGotLocation))
{
// See if we can get there to punch
sActionGridNo = FindAdjacentGridEx( pSoldier, sGridNo, &ubDirection, &sAdjustedGridNo, TRUE, FALSE );
if ( sActionGridNo != -1 )
{
// OK, we've got somebody...
sGotLocation = sActionGridNo;
fGotAdjacent = TRUE;
}
}
// Did we get a loaction?
if (!TileIsOutOfBounds(sGotLocation))
if (sActionGridNo != NOWHERE)
{
pSoldier->sTargetGridNo = sGridNo;
pSoldier->aiData.usActionData = sGridNo;
// CHECK IF WE ARE AT THIS GRIDNO NOW
if ( pSoldier->sGridNo != sGotLocation && fGotAdjacent )
if ( pSoldier->sGridNo != sActionGridNo )
{
// SEND PENDING ACTION
pSoldier->aiData.ubPendingAction = MERC_PUNCH;
@@ -917,7 +880,7 @@ INT32 HandleItem( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel, UINT16 usHa
pSoldier->aiData.ubPendingActionAnimCount = 0;
// WALK UP TO DEST FIRST
pSoldier->EVENT_InternalGetNewSoldierPath( sGotLocation, pSoldier->usUIMovementMode, FALSE, TRUE );
pSoldier->EVENT_InternalGetNewSoldierPath(sActionGridNo, pSoldier->usUIMovementMode, FALSE, TRUE );
}
else
{
@@ -1858,7 +1821,6 @@ INT32 HandleItem( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel, UINT16 usHa
//USING THE BLADE
if ( Item[ usHandItem ].usItemClass == IC_BLADE )
{
BOOLEAN fGotAdjacent = TRUE;//dnl ch73 290913
// See if we can get there to stab
if ( pSoldier->ubBodyType == BLOODCAT )
{
@@ -1874,28 +1836,11 @@ INT32 HandleItem( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel, UINT16 usHa
}
else
{
//dnl ch73 290913
fGotAdjacent = FALSE;
sActionGridNo = NOWHERE;
if(pTargetSoldier)
for(INT8 sCnt=0; sCnt<NUM_WORLD_DIRECTIONS; sCnt++)
{
INT32 sSpot = NewGridNo(pSoldier->sGridNo, DirectionInc(sCnt));
if(gubWorldMovementCosts[sSpot][sCnt][bLevel] >= TRAVELCOST_BLOCKED)
continue;
if(WhoIsThere2(sSpot, pSoldier->pathing.bLevel) == pTargetSoldier->ubID)
{
sActionGridNo = sSpot;
sAdjustedGridNo = pTargetSoldier->sGridNo;
ubDirection = (UINT8)sCnt;
break;
}
}
if(TileIsOutOfBounds(sActionGridNo))
// See if we can get there to stab
sActionGridNo = FindAdjacentGridEx(pSoldier, sGridNo, &ubDirection, &sAdjustedGridNo, TRUE, FALSE);
if (sActionGridNo == -1)
{
sActionGridNo = FindAdjacentGridEx(pSoldier, sGridNo, &ubDirection, &sAdjustedGridNo, TRUE, FALSE);
if(sActionGridNo != NOWHERE)
fGotAdjacent = TRUE;
sActionGridNo = FindAdjacentGridEx(pSoldier, usMapPos, &ubDirection, &sAdjustedGridNo, TRUE, FALSE);
}
}
@@ -1904,7 +1849,7 @@ INT32 HandleItem( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel, UINT16 usHa
pSoldier->aiData.usActionData = sActionGridNo;
// CHECK IF WE ARE AT THIS GRIDNO NOW
if ( pSoldier->sGridNo != sActionGridNo && fGotAdjacent )//dnl ch73 290913
if ( pSoldier->sGridNo != sActionGridNo )
{
// SEND PENDING ACTION
pSoldier->aiData.ubPendingAction = MERC_KNIFEATTACK;
+17 -56
View File
@@ -4509,81 +4509,42 @@ INT8 DrawUIMovementPath( SOLDIERTYPE *pSoldier, INT32 usMapPos, UINT32 uiFlags )
}
else if ( uiFlags == MOVEUI_TARGET_MERCS )
{
INT32 sGotLocation = NOWHERE;
BOOLEAN fGotAdjacent = FALSE;
// Check if we are on a target
if ( gfUIFullTargetFound )
{
INT32 cnt;
INT32 sSpot;
UINT8 ubGuyThere;
for ( cnt = 0; cnt < NUM_WORLD_DIRECTIONS; cnt++ )
// See if we can get there to stab
if (pSoldier->ubBodyType == BLOODCAT)
{
sSpot = NewGridNo( pSoldier->sGridNo, DirectionInc( (INT8)cnt ) );
// Make sure movement costs are OK....
if ( gubWorldMovementCosts[ sSpot ][ cnt ][ gsInterfaceLevel ] >= TRAVELCOST_BLOCKED )
sActionGridNo = FindNextToAdjacentGridEx(pSoldier, usMapPos, &ubDirection, &sAdjustedGridNo, TRUE, FALSE);
}
else if (CREATURE_OR_BLOODCAT(pSoldier) && PythSpacesAway(pSoldier->sGridNo, usMapPos) > 1)
{
sActionGridNo = FindNextToAdjacentGridEx(pSoldier, usMapPos, &ubDirection, &sAdjustedGridNo, TRUE, FALSE);
if (sActionGridNo == -1)
{
continue;
}
// Check for who is there...
ubGuyThere = WhoIsThere2( sSpot, pSoldier->pathing.bLevel );
if ( ubGuyThere == MercPtrs[ gusUIFullTargetID ]->ubID )
{
// We've got a guy here....
// Who is the one we want......
sGotLocation = sSpot;
sAdjustedGridNo = MercPtrs[ gusUIFullTargetID ]->sGridNo;
ubDirection = ( UINT8 )cnt;
break;
sActionGridNo = FindAdjacentGridEx(pSoldier, usMapPos, &ubDirection, &sAdjustedGridNo, TRUE, FALSE);
}
}
if (TileIsOutOfBounds(sGotLocation))
else
{
sActionGridNo = FindAdjacentGridEx( pSoldier, MercPtrs[ gusUIFullTargetID ]->sGridNo, &ubDirection, &sAdjustedGridNo, TRUE, FALSE );
if ( sActionGridNo == -1 )
{
sGotLocation = NOWHERE;
}
else
{
sGotLocation = sActionGridNo;
}
fGotAdjacent = TRUE;
// See if we can get there to stab
sActionGridNo = FindAdjacentGridEx(pSoldier, usMapPos, &ubDirection, &sAdjustedGridNo, TRUE, FALSE);
}
}
else
{
sAdjustedGridNo = usMapPos;
sGotLocation = sActionGridNo;
fGotAdjacent = TRUE;
}
if (!TileIsOutOfBounds(sGotLocation))
if (!TileIsOutOfBounds(sActionGridNo))
{
#if 0//dnl ch73 021013 don't add turnover cost if we are moving, in the future this should be calculated by UIPlotPath
sAPCost += MinAPsToAttack( pSoldier, sAdjustedGridNo, TRUE, pSoldier->aiData.bShownAimTime, 0 );
// WANNE: Turn around APs were missing, I think ....
//sAPCost += APsToTurnAround(pSoldier, sAdjustedGridNo);
sAPCost += UIPlotPath( pSoldier, sGotLocation, NO_COPYROUTE, fPlot, TEMPORARY, (UINT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints);
#else
sAPCost = UIPlotPath(pSoldier, sGotLocation, NO_COPYROUTE, fPlot, TEMPORARY, (UINT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints);
sAPCost += MinAPsToAttack(pSoldier, sAdjustedGridNo, sAPCost>0?FALSE:TRUE, pSoldier->aiData.bShownAimTime, 0);
#endif
if ( sGotLocation != pSoldier->sGridNo && fGotAdjacent )
if (sActionGridNo != pSoldier->sGridNo )
{
sAPCost = UIPlotPath(pSoldier, sActionGridNo, NO_COPYROUTE, fPlot, TEMPORARY, (UINT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints);
gfUIHandleShowMoveGrid = TRUE;
gsUIHandleShowMoveGridLocation = sGotLocation;
gsUIHandleShowMoveGridLocation = sActionGridNo;
}
sAPCost += MinAPsToAttack(pSoldier, sAdjustedGridNo, TRUE, pSoldier->aiData.bShownAimTime, 0);
}
}
else if ( uiFlags == MOVEUI_TARGET_STEAL )
+100 -3
View File
@@ -5452,7 +5452,7 @@ INT32 FindAdjacentGridEx( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 *pubDirect
// fForceToPerson: forces the grid under consideration to be the one occupiedby any target
// in that location, because we could be passed a gridno based on the overlap of soldier's graphic
// fDoor determines whether special door-handling code should be used (for interacting with doors)
INT32 sGridNoProne = -1;
INT32 sFourGrids[4], sDistance=0;
static const UINT8 sDirs[4] = { NORTH, EAST, SOUTH, WEST };
//INT32 cnt;
@@ -5537,7 +5537,20 @@ INT32 FindAdjacentGridEx( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 *pubDirect
{
if ( FindSoldier( sGridNo, &usSoldierIndex, &uiMercFlags, FIND_SOLDIER_GRIDNO ) )
{
sGridNo = MercPtrs[ usSoldierIndex ]->sGridNo;
SOLDIERTYPE *pTargetSoldier = MercPtrs[usSoldierIndex];
sGridNo = pTargetSoldier->sGridNo;
if (gAnimControl[pTargetSoldier->usAnimState].ubEndHeight == ANIM_PRONE)
{
// prone; could be the base tile is inaccessible but the rest isn't...
for (INT8 cnt = 0; cnt < NUM_WORLD_DIRECTIONS; cnt++)
{
if (WhoIsThere2(sGridNo + DirectionInc(cnt), pTargetSoldier->pathing.bLevel) == usSoldierIndex)
{
sGridNoProne = sGridNo + DirectionInc(cnt);
break;
}
}
}
if ( psAdjustedGridNo != NULL )
{
*psAdjustedGridNo = sGridNo;
@@ -5664,8 +5677,92 @@ INT32 FindAdjacentGridEx( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 *pubDirect
}
}
}
if (sGridNoProne != -1)
{
for (INT8 cnt = 0; cnt < 4; ++cnt)
{
// MOVE OUT TWO DIRECTIONS
sFourGrids[cnt] = sSpot = NewGridNo(sGridNoProne, DirectionInc(sDirs[cnt]));
if ( !TileIsOutOfBounds( sClosest ) )
ubTestDirection = sDirs[cnt];
// For switches, ALLOW them to walk through walls to reach it....
if (pDoor && pDoor->fFlags & STRUCTURE_SWITCH)
{
ubTestDirection = gOppositeDirection[ubTestDirection];
}
if (fDoor)
{
if (gubWorldMovementCosts[sSpot][ubTestDirection][pSoldier->pathing.bLevel] >= TRAVELCOST_BLOCKED)
{
// obstacle or wall there!
continue;
}
}
else
{
// this function returns original MP cost if not a door cost
if (DoorTravelCost(pSoldier, sSpot, gubWorldMovementCosts[sSpot][ubTestDirection][pSoldier->pathing.bLevel], FALSE, NULL) >= TRAVELCOST_BLOCKED)
{
// obstacle or wall there!
continue;
}
}
// Eliminate some directions if we are looking at doors!
if (pDoor != NULL)
{
// Get orinetation
ubWallOrientation = pDoor->ubWallOrientation;
// Refuse the south and north and west directions if our orientation is top-right
if (ubWallOrientation == OUTSIDE_TOP_RIGHT || ubWallOrientation == INSIDE_TOP_RIGHT)
{
if (sDirs[cnt] == NORTH || sDirs[cnt] == WEST || sDirs[cnt] == SOUTH)
continue;
}
// Refuse the north and west and east directions if our orientation is top-right
if (ubWallOrientation == OUTSIDE_TOP_LEFT || ubWallOrientation == INSIDE_TOP_LEFT)
{
if (sDirs[cnt] == NORTH || sDirs[cnt] == WEST || sDirs[cnt] == EAST)
continue;
}
}
// If this spot is our soldier's gridno use that!
if (sSpot == pSoldier->sGridNo)
{
// Use default diurection ) soldier's direction )
// OK, at least get direction to face......
// Defaults to soldier's facing dir unless we change it!
// Use direction to the door!
if (pubDirection)
(*pubDirection) = (UINT8)GetDirectionFromGridNo(sGridNoProne, pSoldier);
if (psAdjustedGridNo) *psAdjustedGridNo = sGridNoProne;
return(sSpot);
}
// don't store path, just measure it
ubDir = (UINT8)GetDirectionToGridNoFromGridNo(sSpot, sGridNoProne);
if ((NewOKDestinationAndDirection(pSoldier, sSpot, ubDir, TRUE, pSoldier->pathing.bLevel) > 0) &&
((sDistance = PlotPath(pSoldier, sSpot, NO_COPYROUTE, NO_PLOT, TEMPORARY, (INT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints)) > 0))
{
if (sDistance < sClosest)
{
sClosest = sDistance;
sCloseGridNo = sSpot;
sGridNo = sGridNoProne;//this will ensure correct direction calculation
if (psAdjustedGridNo) *psAdjustedGridNo = sGridNoProne;
}
}
}
}
if (sClosest != NOWHERE)
{
// Take last direction and use opposite!
// This will be usefull for ours and AI mercs
+42 -88
View File
@@ -1916,100 +1916,68 @@ INT16 CalcTotalAPsToAttack( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 ubAddTur
if ( uiItemClass == IC_PUNCH || uiItemClass == IC_BLADE || uiItemClass == IC_TENTACLES )//dnl ch73 031013, silversurfer: tentacles are melee too
{
// IF we are at this gridno, calc min APs but if not, calc cost to goto this lication
// IF we are at this gridno, calc min APs but if not, calc cost to goto this location
if ( pSoldier->sGridNo != sGridNo )
{
sAdjustedGridNo = NOWHERE;
// OK, in order to avoid path calculations here all the time... save and check if it's changed!
if ( pSoldier->sWalkToAttackGridNo == sGridNo )
// See if we can get there to stab
if (pSoldier->ubBodyType == BLOODCAT)
{
sAdjustedGridNo = sGridNo;
sAPCost += (UINT8)( pSoldier->sWalkToAttackWalkToCost );
sActionGridNo = FindNextToAdjacentGridEx(pSoldier, sGridNo, &ubDirection, &sAdjustedGridNo, TRUE, FALSE);
}
else if (CREATURE_OR_BLOODCAT(pSoldier) && PythSpacesAway(pSoldier->sGridNo, sGridNo) > 1)
{
sActionGridNo = FindNextToAdjacentGridEx(pSoldier, sGridNo, &ubDirection, &sAdjustedGridNo, TRUE, FALSE);
if (sActionGridNo == -1)
{
sActionGridNo = FindAdjacentGridEx(pSoldier, sGridNo, &ubDirection, &sAdjustedGridNo, TRUE, FALSE);
}
}
else
{
//INT32 cnt;
//INT16 sSpot;
UINT8 ubGuyThere;
INT32 sGotLocation = NOWHERE;
BOOLEAN fGotAdjacent = FALSE;
SOLDIERTYPE *pTarget;
ubGuyThere = WhoIsThere2( sGridNo, pSoldier->pathing.bLevel );
if ( ubGuyThere != NOBODY )
{
pTarget = MercPtrs[ ubGuyThere ];
if ( pSoldier->ubBodyType == BLOODCAT )
{
sGotLocation = FindNextToAdjacentGridEx( pSoldier, sGridNo, &ubDirection, &sAdjustedGridNo, TRUE, FALSE );
if ( sGotLocation == -1 )
{
sGotLocation = NOWHERE;
}
}
else
{
sGotLocation = FindAdjacentPunchTarget( pSoldier, pTarget, &sAdjustedGridNo, &ubDirection );
}
}
// See if we can get there to stab
sActionGridNo = FindAdjacentGridEx(pSoldier, sGridNo, &ubDirection, &sAdjustedGridNo, TRUE, FALSE);
}
if (TileIsOutOfBounds(sGotLocation) && pSoldier->ubBodyType != BLOODCAT )
if (!TileIsOutOfBounds(sActionGridNo))
{
if (pSoldier->sGridNo == sActionGridNo)
{
sActionGridNo = FindAdjacentGridEx( pSoldier, sGridNo, &ubDirection, &sAdjustedGridNo, TRUE, FALSE );
if ( sActionGridNo == -1 )
{
sGotLocation = NOWHERE;
}
else
{
sGotLocation = sActionGridNo;
}
fGotAdjacent = TRUE;
pSoldier->sWalkToAttackWalkToCost = 0;
}
if (!TileIsOutOfBounds(sGotLocation))
else
{
if (pSoldier->sGridNo == sGotLocation || !fGotAdjacent )
// OK, in order to avoid path calculations here all the time... save and check if it's changed!
if (pSoldier->sWalkToAttackGridNo == sActionGridNo)
{
pSoldier->sWalkToAttackWalkToCost = 0;
sAPCost += (UINT8)(pSoldier->sWalkToAttackWalkToCost);
}
else
{
// Save for next time...
pSoldier->sWalkToAttackWalkToCost = PlotPath( pSoldier, sGotLocation, NO_COPYROUTE, NO_PLOT, TEMPORARY, (UINT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints );
pSoldier->sWalkToAttackWalkToCost = PlotPath(pSoldier, sActionGridNo, NO_COPYROUTE, NO_PLOT, TEMPORARY, (UINT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints);
if (pSoldier->sWalkToAttackWalkToCost == 0)
{
return( 99 );
return(99);
}
sAPCost += pSoldier->sWalkToAttackWalkToCost;
}
}
else
{
return( 0 );
}
sAPCost += pSoldier->sWalkToAttackWalkToCost;
}
else
{
return( 0 );
}
// Save old location!
pSoldier->sWalkToAttackGridNo = sGridNo;
pSoldier->sWalkToAttackGridNo = sActionGridNo;
// Add points to attack
sAPCost += MinAPsToAttack(pSoldier, sAdjustedGridNo, sAPCost>0?FALSE:ubAddTurningCost, bAimTime, 0);//dnl ch73 031013
//sAPCost += APsToTurnAround(pSoldier, sAdjustedGridNo);
}
else
{
// Add points to attack
// Use our gridno
sAPCost += MinAPsToAttack( pSoldier, sGridNo, ubAddTurningCost, bAimTime, 0 );
}
// Add points to attack
sAPCost += MinAPsToPunch(pSoldier, sAdjustedGridNo, ubAddTurningCost);
// Add aim time...
sAPCost += (bAimTime*APBPConstants[AP_CLICK_AIM]);
@@ -2706,29 +2674,15 @@ INT16 MinAPsToPunch(SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 ubAddTurningCost
{
// ATE: Use standing turn cost....
UINT8 ubDirection = GetDirectionFromGridNo(sGridNo, pSoldier);
INT32 sSpot = sGridNo;
if(usTargID != NOBODY && gAnimControl[MercPtrs[usTargID]->usAnimState].ubEndHeight == ANIM_PRONE)
for(INT8 sCnt=0; sCnt<NUM_WORLD_DIRECTIONS; sCnt++)
{
sSpot = NewGridNo(pSoldier->sGridNo, DirectionInc(sCnt));
if(gubWorldMovementCosts[sSpot][sCnt][pSoldier->bTargetLevel] >= TRAVELCOST_BLOCKED)
continue;
if(WhoIsThere2(sSpot, pSoldier->bTargetLevel) == usTargID)
{
ubDirection = (UINT8)sCnt;
break;
}
}
// Is it the same as he's facing?
// Buggler: actual melee ap deduction for turning applies only when target is 1 tile away
//UINT16 usRange = GetRangeFromGridNoDiff(pSoldier->sGridNo, sSpot);
if(/*usRange == 1 && */ubDirection != pSoldier->ubDirection)
{
if(gAnimControl[pSoldier->usAnimState].ubEndHeight == ANIM_PRONE)
bAPCost += CalculateTurningCost(pSoldier, usItem, TRUE, ANIM_CROUCH);
else
bAPCost += CalculateTurningCost(pSoldier, usItem, TRUE);
}
// Is it the same as he's facing?
if(ubDirection != pSoldier->ubDirection)
{
if(gAnimControl[pSoldier->usAnimState].ubEndHeight == ANIM_PRONE)
bAPCost += CalculateTurningCost(pSoldier, usItem, TRUE, ANIM_CROUCH);
else
bAPCost += CalculateTurningCost(pSoldier, usItem, TRUE);
}
}
}