Make VTOLs finish patrolling/scouting before returning to rearm.

git-svn-id: https://warzone2100.svn.sourceforge.net/svnroot/warzone2100/trunk@8862 4a71c877-e1ca-e34f-864e-861f7616d084
master
Guangcong Luo 2009-12-30 05:07:37 +00:00 committed by Git SVN Gateway
parent f2cf35f791
commit 8c6ca5cb91
4 changed files with 109 additions and 47 deletions

View File

@ -1012,15 +1012,23 @@ void actionUpdateDroid(DROID *psDroid)
setDroidActionTarget(psDroid, NULL, i);
if (i == 0)
{
if ( (psDroid->action != DACTION_MOVEFIRE) &&
(psDroid->action != DACTION_TRANSPORTIN) &&
(psDroid->action != DACTION_TRANSPORTOUT) )
if (psDroid->action != DACTION_MOVEFIRE &&
psDroid->action != DACTION_TRANSPORTIN &&
psDroid->action != DACTION_TRANSPORTOUT)
{
psDroid->action = DACTION_NONE;
//if Vtol - return to rearm pad
// if VTOL - return to rearm pad if not patrolling
if (isVtolDroid(psDroid))
{
moveToRearm(psDroid);
if (psDroid->order == DORDER_PATROL)
{
// Back to the patrol.
actionDroidLoc(psDroid, DACTION_MOVE, psDroid->orderX,psDroid->orderY);
}
else
{
moveToRearm(psDroid);
}
}
}
}

View File

@ -3982,13 +3982,10 @@ BOOL isVtolDroid(const DROID* psDroid)
&& psDroid->droidType != DROID_TRANSPORTER;
}
/*returns true if a VTOL Weapon Droid which has completed all runs*/
/* returns true if it's a VTOL weapon droid which has completed all runs */
BOOL vtolEmpty(DROID *psDroid)
{
UBYTE i;
UBYTE numVtolWeaps = 0;
UBYTE emptyWeaps = 0;
BOOL bEmpty = true;
CHECK_DROID(psDroid);
@ -4001,30 +3998,44 @@ BOOL vtolEmpty(DROID *psDroid)
return false;
}
if (psDroid->numWeaps > 0)
for (i = 0; i < psDroid->numWeaps; i++)
{
for (i = 0;i < psDroid->numWeaps;i++)
if (asWeaponStats[psDroid->asWeaps[i].nStat].vtolAttackRuns > 0 &&
psDroid->sMove.iAttackRuns[i] < getNumAttackRuns(psDroid, i))
{
if (asWeaponStats[psDroid->asWeaps[i].nStat].vtolAttackRuns > 0)
{
numVtolWeaps += (1 << (1 + i));
if (psDroid->sMove.iAttackRuns[i] >= getNumAttackRuns(psDroid, i))
{
emptyWeaps += (1 << (1 + i));
}
}
return false;
}
}
for (i = 0;i < psDroid->numWeaps;i++)
return true;
}
/* returns true if it's a VTOL weapon droid which still has full ammo */
BOOL vtolFull(DROID *psDroid)
{
UBYTE i;
CHECK_DROID(psDroid);
if (!isVtolDroid(psDroid))
{
if ((numVtolWeaps & (1 << (1 + i))) && !(emptyWeaps & (1 << (1 + i))))
return false;
}
if (psDroid->droidType != DROID_WEAPON)
{
return false;
}
for (i = 0; i < psDroid->numWeaps; i++)
{
if (asWeaponStats[psDroid->asWeaps[i].nStat].vtolAttackRuns > 0 &&
psDroid->sMove.iAttackRuns[i] > 0)
{
bEmpty = false;
break;
return false;
}
}
return bEmpty;
return true;
}
// true if a vtol is waiting to be rearmed by a particular rearm pad
@ -4223,6 +4234,10 @@ void updateVtolAttackRun(DROID *psDroid , int weapon_slot)
if (asWeaponStats[psDroid->asWeaps[weapon_slot].nStat].vtolAttackRuns > 0)
{
psDroid->sMove.iAttackRuns[weapon_slot]++;
if (psDroid->sMove.iAttackRuns[weapon_slot] == getNumAttackRuns(psDroid, weapon_slot))
{
psDroid->asWeaps[weapon_slot].ammo = 0;
}
//quick check doesn't go over limit
ASSERT( psDroid->sMove.iAttackRuns[weapon_slot] < UWORD_MAX, "too many attack runs");
}

View File

@ -334,8 +334,10 @@ extern BASE_OBJECT * checkForRepairRange(DROID *psDroid,DROID *psTarget);
//access function
extern BOOL isVtolDroid(const DROID* psDroid);
/*returns true if a VTOL Weapon Droid which has completed all runs*/
/*returns true if a VTOL weapon droid which has completed all runs*/
extern BOOL vtolEmpty(DROID *psDroid);
/*returns true if a VTOL weapon droid which still has full ammo*/
extern BOOL vtolFull(DROID *psDroid);
/*Checks a vtol for being fully armed and fully repaired to see if ready to
leave reArm pad */
extern BOOL vtolHappy(const DROID* psDroid);

View File

@ -521,28 +521,59 @@ void orderUpdateDroid(DROID *psDroid)
case DORDER_SCOUT:
case DORDER_PATROL:
// if there is an enemy around, attack it
if ( (psDroid->action == DACTION_MOVE) && CAN_UPDATE_NAYBORS(psDroid) &&
(secondaryGetState(psDroid, DSO_ATTACK_LEVEL) == DSS_ALEV_ALWAYS) &&
(aiBestNearestTarget(psDroid, &psObj, 0, NULL) >= 0) )
if (psDroid->action == DACTION_MOVE || (psDroid->action == DACTION_NONE && isVtolDroid(psDroid)))
{
switch (psDroid->droidType)
bool tooFarFromPath = false;
if (isVtolDroid(psDroid) && psDroid->order == DORDER_PATROL)
{
case DROID_WEAPON:
case DROID_CYBORG:
case DROID_CYBORG_SUPER:
case DROID_PERSON:
case DROID_COMMAND:
actionDroidObj(psDroid, DACTION_ATTACK, psObj);
break;
case DROID_SENSOR:
actionDroidObj(psDroid, DACTION_OBSERVE, psObj);
break;
default:
actionDroid(psDroid, DACTION_NONE);
break;
// Don't stray too far from the patrol path - only attack if we're near it
// A fun algorithm to detect if we're near the path
SDWORD deltaX, deltaY;
deltaX = (SDWORD)psDroid->orderX - (SDWORD)psDroid->orderX2;
deltaY = (SDWORD)psDroid->orderY - (SDWORD)psDroid->orderY2;
if (deltaX >= deltaY &&
(SDWORD)MIN(psDroid->orderX, psDroid->orderX2)-SCOUT_DIST <= psDroid->pos.x &&
psDroid->pos.x <= (SDWORD)MAX(psDroid->orderX, psDroid->orderX2)+SCOUT_DIST)
{
tooFarFromPath = (abs(((SDWORD)psDroid->pos.x - (SDWORD)psDroid->orderX) * deltaY/deltaX +
(SDWORD)psDroid->orderY - (SDWORD)psDroid->pos.y) > SCOUT_DIST);
}
if (deltaX <= deltaY &&
(SDWORD)MIN(psDroid->orderY, psDroid->orderY2)-SCOUT_DIST <= psDroid->pos.y &&
psDroid->pos.y <= (SDWORD)MAX(psDroid->orderY, psDroid->orderY2)+SCOUT_DIST)
{
tooFarFromPath = (abs(((SDWORD)psDroid->pos.y - (SDWORD)psDroid->orderY) * deltaX/deltaY +
(SDWORD)psDroid->orderX - (SDWORD)psDroid->pos.x) > SCOUT_DIST);
}
else
{
tooFarFromPath = true;
}
}
if (!tooFarFromPath &&
CAN_UPDATE_NAYBORS(psDroid) &&
(secondaryGetState(psDroid, DSO_ATTACK_LEVEL) == DSS_ALEV_ALWAYS) &&
(aiBestNearestTarget(psDroid, &psObj, 0, NULL) >= 0))
{
switch (psDroid->droidType)
{
case DROID_WEAPON:
case DROID_CYBORG:
case DROID_CYBORG_SUPER:
case DROID_PERSON:
case DROID_COMMAND:
actionDroidObj(psDroid, DACTION_ATTACK, psObj);
break;
case DROID_SENSOR:
actionDroidObj(psDroid, DACTION_OBSERVE, psObj);
break;
default:
actionDroid(psDroid, DACTION_NONE);
break;
}
}
}
else if (psDroid->action == DACTION_NONE)
if (psDroid->action == DACTION_NONE)
{
xdiff = (SDWORD)psDroid->pos.x - (SDWORD)psDroid->orderX;
ydiff = (SDWORD)psDroid->pos.y - (SDWORD)psDroid->orderY;
@ -550,19 +581,25 @@ void orderUpdateDroid(DROID *psDroid)
{
if (psDroid->order == DORDER_PATROL)
{
UDWORD tempCoord;
// see if we have anything queued up
if (orderDroidList(psDroid))
{
// started a new order, quit
break;
}
if (isVtolDroid(psDroid) && !vtolFull(psDroid))
{
moveToRearm(psDroid);
break;
}
// head back to the other point
temp = psDroid->orderX;
tempCoord = psDroid->orderX;
psDroid->orderX = psDroid->orderX2;
psDroid->orderX2 = (UWORD)temp;
temp = psDroid->orderY;
psDroid->orderX2 = tempCoord;
tempCoord = psDroid->orderY;
psDroid->orderY = psDroid->orderY2;
psDroid->orderY2 = (UWORD)temp;
psDroid->orderY2 = tempCoord;
actionDroidLoc(psDroid, DACTION_MOVE, psDroid->orderX,psDroid->orderY);
}
else