From 8c6ca5cb914f460b88ef0697ac8f0d1dea1c638d Mon Sep 17 00:00:00 2001 From: Guangcong Luo Date: Wed, 30 Dec 2009 05:07:37 +0000 Subject: [PATCH] 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 --- src/action.c | 18 ++++++++---- src/droid.c | 53 ++++++++++++++++++++++------------ src/droid.h | 4 ++- src/order.c | 81 ++++++++++++++++++++++++++++++++++++++-------------- 4 files changed, 109 insertions(+), 47 deletions(-) diff --git a/src/action.c b/src/action.c index d0b8d6ba9..673a011bd 100644 --- a/src/action.c +++ b/src/action.c @@ -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); + } } } } diff --git a/src/droid.c b/src/droid.c index a450e06eb..b45299bcd 100644 --- a/src/droid.c +++ b/src/droid.c @@ -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"); } diff --git a/src/droid.h b/src/droid.h index 5430bec4e..4be2c609b 100644 --- a/src/droid.h +++ b/src/droid.h @@ -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); diff --git a/src/order.c b/src/order.c index 197ac572f..0e918ca28 100644 --- a/src/order.c +++ b/src/order.c @@ -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