/* This file is part of Warzone 2100. Copyright (C) 1999-2004 Eidos Interactive Copyright (C) 2005-2007 Warzone Resurrection Project Warzone 2100 is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Warzone 2100 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Warzone 2100; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* * Power.c * * Store PlayerPower and other power related stuff! * */ #include "objectdef.h" #include "power.h" #include "hci.h" #include "lib/gamelib/gtime.h" #include "lib/sound/audio.h" #include "audio_id.h" #include "objmem.h" #include "frontend.h" #include "multiplay.h" #include "multiint.h" #include "feature.h" #include "structure.h" #include "mission.h" #include "research.h" #include "intdisplay.h" #include "action.h" #include "difficulty.h" #include "powercrypt.h" #define EXTRACT_POINTS 1 #define EASY_POWER_MOD 110 #define NORMAL_POWER_MOD 100 #define HARD_POWER_MOD 90 //arbitary high value - needs to allow all structures to be built at start of any game #define MAX_POWER 100000 //flag used to check for power calculations to be done or not BOOL powerCalculated; /*Update the capcity and available power if necessary */ //static void availablePowerUpdate(STRUCTURE *psBuilding); /*looks through the player's list of droids and structures to see what power has been used*/ //static UDWORD calcPlayerUsedPower(UDWORD player); /* Updates the current power based on the extracted power and a Power Generator*/ static void updateCurrentPower(POWER_GEN *psPowerGen, UDWORD player); /*accrue the power in the facilities that require it*/ //static void accruePower(STRUCTURE *psStructure); //returns the relevant list based on OffWorld or OnWorld static STRUCTURE* powerStructList(UBYTE player); //returns the relevant list based on OffWorld or OnWorld for the accruePower function //static STRUCTURE* powerUpdateStructList(UBYTE player); PLAYER_POWER *asPower[MAX_PLAYERS]; /*allocate the space for the playerPower*/ BOOL allocPlayerPower(void) { UDWORD player; //allocate the space for the structure for (player = 0; player < MAX_PLAYERS; player++) { asPower[player] = (PLAYER_POWER *) MALLOC (sizeof(PLAYER_POWER)); if (asPower[player] == NULL) { debug( LOG_ERROR, "Out of memory" ); abort(); return FALSE; } } clearPlayerPower(); powerCalculated = TRUE; return TRUE; } /*clear the playerPower */ void clearPlayerPower(void) { UDWORD player; //check power has been allocated! if (asPower[0] == NULL) { return; } for (player = 0; player < MAX_PLAYERS; player++) { memset(asPower[player], 0, sizeof(PLAYER_POWER)); pwrcSetPlayerCryptPower(player,0); } } /*Free the space used for playerPower */ void releasePlayerPower(void) { UDWORD player; //check power has been allocated! if (asPower[0] == NULL) { return; } for (player = 0; player < MAX_PLAYERS; player++) { if (asPower[player]) { FREE(asPower[player]); } } } /*check the current power - if enough return true, else return false */ BOOL checkPower(UDWORD player, UDWORD quantity, BOOL playAudio) { //if not doing a check on the power - just return TRUE if (!powerCalculated) { return TRUE; } if (!pwrcCheckPlayerCryptPower(player, asPower[player]->currentPower)) { return FALSE; } if (asPower[player]->currentPower >= quantity) { return TRUE; } //Not playing the power low message anymore - 6/1/99 /*else if (player == selectedPlayer) { //#ifdef PSX //#warning POWER LOW IS DISABLED // return TRUE; //#endif if (playAudio && player == selectedPlayer) { audio_QueueTrack( ID_SOUND_POWER_LOW ); return FALSE; } }*/ return FALSE; } /*check the current power - if enough subtracts the amount required to perform the task and returns true, else returns false */ BOOL usePower(UDWORD player, UDWORD quantity) { //if not doing a check on the power - just return TRUE if (!powerCalculated) { return TRUE; } if (!pwrcCheckPlayerCryptPower(player, asPower[player]->currentPower)) { return FALSE; } //check there is enough first if (asPower[player]->currentPower >= quantity) { asPower[player]->currentPower -= quantity; pwrcSetPlayerCryptPower(player, asPower[player]->currentPower); return TRUE; } else if (player == selectedPlayer) { //#ifdef PSX //#warning POWER LOW IS DISABLED // return TRUE; //#endif if(titleMode == FORCESELECT) //|| (titleMode == DESIGNSCREEN)) { return FALSE; } //Not playing the power low message anymore - 6/1/99 //audio_QueueTrack( ID_SOUND_POWER_LOW ); } return FALSE; } //return the power when a structure/droid is deliberately destroyed void addPower(UDWORD player, UDWORD quantity) { if (!pwrcCheckPlayerCryptPower(player, asPower[player]->currentPower)) { return; } asPower[player]->currentPower += quantity; pwrcSetPlayerCryptPower(player, asPower[player]->currentPower); } /*resets the power calc flag for all players*/ void powerCalc(BOOL on) { if (on) { powerCalculated = TRUE; } else { powerCalculated = FALSE; } } /* Each Resource Extractor yields EXTRACT_POINTS per second until there are none left in the resource. */ UDWORD updateExtractedPower(STRUCTURE *psBuilding) { RES_EXTRACTOR *pResExtractor; UDWORD pointsToAdd, extractedPoints, timeDiff; UBYTE modifier; pResExtractor = (RES_EXTRACTOR *) psBuilding->pFunctionality; extractedPoints = 0; //only extracts points whilst its active ie associated with a power gen //and has got some power to extract if (pResExtractor->active AND pResExtractor->power) { timeDiff = gameTime - pResExtractor->timeLastUpdated; //add modifier according to difficulty level if (getDifficultyLevel() == DL_EASY) { modifier = EASY_POWER_MOD; } else if (getDifficultyLevel() == DL_HARD) { modifier = HARD_POWER_MOD; } else { modifier = NORMAL_POWER_MOD; } //include modifier as a % pointsToAdd = (modifier * EXTRACT_POINTS * timeDiff) / (GAME_TICKS_PER_SEC * 100); if (pointsToAdd) { //lose a lot on rounding this way pResExtractor->timeLastUpdated = gameTime; //pResExtractor->timeLastUpdated = gameTime - (timeDiff - GAME_TICKS_PER_SEC); if (pResExtractor->power > pointsToAdd) { extractedPoints += pointsToAdd; pResExtractor->power -= pointsToAdd; } else { extractedPoints += pResExtractor->power; pResExtractor->power = 0; } if (pResExtractor->power == 0) { //if not having unlimited power, put the 2 lines below back in //set the extractor to be inactive //pResExtractor->active = FALSE; //break the link between the power gen and the res extractor //releaseResExtractor(psBuilding); //for now, when the power = 0 set it back to the max level! pResExtractor->power = ((RESOURCE_FUNCTION*)psBuilding->pStructureType-> asFuncList[0])->maxPower; } } } return extractedPoints; } /* Each Resource Extractor yields EXTRACT_POINTS per second until there are none left in the resource. */ /*void updateExtractedPower(STRUCTURE *psBuilding) { RES_EXTRACTOR *pResExtractor; UDWORD pointsToAdd; pResExtractor = (RES_EXTRACTOR *) psBuilding->pFunctionality; //only extracts points whilst its active ie associated with a power gen if (pResExtractor->active) { pointsToAdd = EXTRACT_POINTS * (gameTime - pResExtractor->timeLastUpdated) / GAME_TICKS_PER_SEC; if (pointsToAdd) { pResExtractor->timeLastUpdated = gameTime; if (pResExtractor->power > pointsToAdd) { asPower[psBuilding->player]->extractedPower += pointsToAdd; pResExtractor->power -= pointsToAdd; } else { asPower[psBuilding->player]->extractedPower += pResExtractor->power; pResExtractor->power = 0; } //for now, when the power = 0 set it back to the max level! if (pResExtractor->power == 0) { pResExtractor->power = ((POWER_REG_FUNCTION*)psBuilding->pStructureType-> asFuncList[0])->maxPower; } } } }*/ //returns the relevant list based on OffWorld or OnWorld STRUCTURE* powerStructList(UBYTE player) { if (offWorldKeepLists) { return (mission.apsStructLists[player]); } else { return (apsStructLists[player]); } } //returns the relevant list based on OffWorld or OnWorld for the accruePower function /*STRUCTURE* powerUpdateStructList(UBYTE player) { static BYTE first[MAX_PLAYERS] = {TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE}; if (offWorldKeepLists) { if (first[player]) { first[player] = FALSE; return (mission.apsStructLists[player]); } else { first[player] = TRUE; return (apsStructLists[player]); } } else { return (apsStructLists[player]); } }*/ /* Update current power based on what Power Generators exist */ void updatePlayerPower(UDWORD player) { STRUCTURE *psStruct;//, *psList; /*if (offWorldKeepLists) { psList = mission.apsStructLists[player]; } else { psList = apsStructLists[player]; }*/ //for (psStruct = psList; psStruct != NULL; psStruct = psStruct->psNext) for (psStruct = powerStructList((UBYTE)player); psStruct != NULL; psStruct = psStruct->psNext) { if (psStruct->pStructureType->type == REF_POWER_GEN AND psStruct-> status == SS_BUILT) { updateCurrentPower((POWER_GEN *)psStruct->pFunctionality, player); } } //check that the psLastPowered hasn't died if (asPower[player]->psLastPowered AND asPower[player]->psLastPowered->died) { asPower[player]->psLastPowered = NULL; } } /* Update current power based on what was extracted during the last cycle and what Power Generators exist */ /*void updatePlayerPower(UDWORD player) { STRUCTURE *psStruct; if (asPower[player]->extractedPower == 0) { return; } //may need to order the structures so that the Power Gen with the highest //multiplier is used first so that the player gets maximum power output. For now //all multiplier are the same for (psStruct = apsStructLists[player]; psStruct != NULL AND asPower[player]->extractedPower != 0; psStruct = psStruct->psNext) { if (psStruct->pStructureType->type == REF_POWER_GEN AND psStruct-> status == SS_BUILT) { updateCurrentPower((POWER_GEN *)psStruct->pFunctionality, player); } } }*/ /* Updates the current power based on the extracted power and a Power Generator*/ void updateCurrentPower(POWER_GEN *psPowerGen, UDWORD player) { UDWORD power, i, extractedPower; if (!pwrcCheckPlayerCryptPower(player, asPower[player]->currentPower)) { return; } //each power gen can cope with its associated resource extractors extractedPower = 0; //for (i=0; i < (NUM_POWER_MODULES + 1); i++) //each Power Gen can cope with 4 extractors now - 9/6/98 AB for (i=0; i < NUM_POWER_MODULES; i++) { if (psPowerGen->apResExtractors[i]) { //check not died if (psPowerGen->apResExtractors[i]->died) { psPowerGen->apResExtractors[i] = NULL; } else { extractedPower += updateExtractedPower(psPowerGen->apResExtractors[i]); } } } asPower[player]->extractedPower += extractedPower ; power = (asPower[player]->extractedPower * psPowerGen->multiplier) / 100; if (power) { asPower[player]->currentPower += power; asPower[player]->extractedPower = 0; pwrcSetPlayerCryptPower(player, asPower[player]->currentPower); } } /* Updates the current power based on the extracted power and a Power Generator*/ /*void updateCurrentPower(POWER_GEN *psPowerGen, UDWORD player) { UDWORD power; //each power gen can cope with a set amount of power power = (asPower[player]->extractedPower * psPowerGen->multiplier) / 100; if (power) { if (power > psPowerGen->power) { power = psPowerGen->power; asPower[player]->extractedPower -= ((power / psPowerGen->multiplier)/100); } else { //no power left over asPower[player]->extractedPower = 0; } if (power) { asPower[player]->currentPower += power; } } }*/ // only used in multiplayer games. void setPower(UDWORD player, UDWORD avail) { if (!pwrcCheckPlayerCryptPower(player, asPower[player]->currentPower)) { return; } asPower[player]->currentPower = avail; pwrcSetPlayerCryptPower(player, asPower[player]->currentPower); } /*sets the initial value for the power*/ void setPlayerPower(UDWORD power, UDWORD player) { if (!pwrcCheckPlayerCryptPower(player, asPower[player]->currentPower)) { return; } //asPower[player]->initialPower = power; asPower[player]->currentPower = power; pwrcSetPlayerCryptPower(player, asPower[player]->currentPower); } /*Temp function to give all players some power when a new game has been loaded*/ void newGameInitPower(void) { UDWORD inc; for (inc=0; inc < MAX_PLAYERS; inc++) { //setPlayerPower(400, inc); //add as opposed to set addPower(inc, 400); } } /*this keeps track of which object was the last to receive power. Power is passed through the object lists each cycle whilst there is some*/ /*void spreadPower(UBYTE player) { STRUCTURE *psLastPowered = NULL, *psStartStruct; UDWORD lastPower = asPower[player]->currentPower; UBYTE first = TRUE, warning = 0; psStartStruct = asPower[player]->psLastPowered; //if (!psStartStruct OR psStartStruct->died) //if (!psStartStruct) //{ // psStartStruct = powerUpdateStructList(player); //} //got to have the minimum power while ((asPower[player]->currentPower > POWER_PER_CYCLE) OR (!powerCalculated)) { //little test to see if we're looping indefinately! warning++; if (warning > 1000) { ASSERT( FALSE, "spreading power round more than 1000 buildings for player %d?", player ); warning = 0; } //if haven't used any power and been through the whole list of //structures then jump out if (!first) { if (psStartStruct == asPower[player]->psLastPowered) { //back to the start struct if (lastPower == asPower[player]->currentPower) { return; } lastPower = asPower[player]->currentPower; } } first = FALSE; //determine which object is to receive the power //check for last in list or nothing available if (asPower[player]->psLastPowered == NULL) { //back to top of list psNextPowered = powerUpdateStructList(player); psStartStruct = psNextPowered; warning = 0; } else { //get the next in the list psNextPowered = asPower[player]->psLastPowered->psNext; //check for last in list if (psNextPowered == NULL) { psNextPowered = powerUpdateStructList(player); warning = 0; } } if (psNextPowered) { accruePower(psNextPowered); asPower[player]->psLastPowered = psNextPowered; } } }*/ /*accrue the power in the facilities that require it - returns TRUE if use some power*/ BOOL accruePower(BASE_OBJECT *psObject) { FACTORY *psFactory; RESEARCH_FACILITY *psResearch; REPAIR_FACILITY *psRepair; SDWORD powerDiff; UDWORD count; BOOL bPowerUsed = FALSE; STRUCTURE *psStructure; DROID *psDroid, *psTarget; switch(psObject->type) { case OBJ_STRUCTURE: psStructure = (STRUCTURE *)psObject; //see if it needs power switch(psStructure->pStructureType->type) { case REF_FACTORY: case REF_CYBORG_FACTORY: case REF_VTOL_FACTORY: psFactory = (FACTORY *)psStructure->pFunctionality; //check the factory is not on hold if (psFactory->timeStartHold) { break; } //check the factory is active if (psFactory->psSubject) { //check needs power powerDiff = ((DROID_TEMPLATE *)psFactory->psSubject)->powerPoints - psFactory->powerAccrued; //if equal then don't need power if (powerDiff) { if (POWER_PER_CYCLE >= powerDiff) { usePower(psStructure->player, powerDiff); psFactory->powerAccrued += powerDiff; bPowerUsed = TRUE; } else if (powerDiff > POWER_PER_CYCLE) { usePower(psStructure->player, POWER_PER_CYCLE); psFactory->powerAccrued += POWER_PER_CYCLE; bPowerUsed = TRUE; } } } break; case REF_RESEARCH: //check the structure is active psResearch = (RESEARCH_FACILITY *)psStructure->pFunctionality; //check the research facility is not on hold if (psResearch->timeStartHold) { break; } if (psResearch->psSubject) { //check the research hasn't been cancelled count = ((RESEARCH *)psResearch->psSubject)->ref - REF_RESEARCH_START; if (IsResearchCancelled(asPlayerResList[selectedPlayer] + count)==FALSE) { //check needs power powerDiff = ((RESEARCH *)psResearch->psSubject)->researchPower - psResearch->powerAccrued; //if equal then don't need power if (powerDiff) { //use the power if appropriate if (POWER_PER_CYCLE >= powerDiff) { usePower(psStructure->player, powerDiff); psResearch->powerAccrued += powerDiff; bPowerUsed = TRUE; } else if (powerDiff > POWER_PER_CYCLE) { usePower(psStructure->player, POWER_PER_CYCLE); psResearch->powerAccrued += POWER_PER_CYCLE; bPowerUsed = TRUE; } } } } break; case REF_REPAIR_FACILITY: //POWER REQUIRMENTS REMOVED - AB 22/09/98 - BACK IN - AB 07/01/99 psRepair = (REPAIR_FACILITY *)psStructure->pFunctionality; psDroid = (DROID *)psRepair->psObj; //check the droid hasn't died in the meantime if (psRepair->psObj AND psRepair->psObj->died) { psRepair->psObj = NULL; } if (psRepair->psObj) { //check if need power powerDiff = powerReqForDroidRepair(psDroid) - psDroid->powerAccrued; //if equal then don't need power if (powerDiff > 0) { powerDiff /= POWER_FACTOR; if (POWER_PER_CYCLE >= powerDiff) { usePower(psStructure->player, powerDiff); //the unit accrues the power so more than one thing can be working on it psDroid->powerAccrued += (powerDiff * POWER_FACTOR); bPowerUsed = TRUE; } else if (powerDiff > POWER_PER_CYCLE) { usePower(psStructure->player, POWER_PER_CYCLE); psDroid->powerAccrued += (POWER_PER_CYCLE * POWER_FACTOR); bPowerUsed = TRUE; } } } break; default: //no need for power bPowerUsed = FALSE; break; } break; case OBJ_DROID: psDroid = (DROID *)psObject; switch (psDroid->droidType) { case DROID_CONSTRUCT: case DROID_CYBORG_CONSTRUCT: //check trying to build something (and that hasn't been blown up) if (DroidIsBuilding(psDroid) AND psDroid->psTarget AND !psDroid->psTarget->died) { //powerDiff = ((STRUCTURE *)psDroid->psTarget)->pStructureType-> // powerToBuild - ((STRUCTURE *)psDroid->psTarget)-> // currentPowerAccrued; powerDiff = structPowerToBuild((STRUCTURE *)psDroid->psTarget) - ((STRUCTURE *)psDroid->psTarget)->currentPowerAccrued; //if equal then don't need power if (powerDiff) { if (POWER_PER_CYCLE >= powerDiff) { usePower(psDroid->player, powerDiff); ((STRUCTURE *)psDroid->psTarget)->currentPowerAccrued += powerDiff; bPowerUsed = TRUE; } else if (powerDiff > POWER_PER_CYCLE) { usePower(psDroid->player, POWER_PER_CYCLE); ((STRUCTURE *)psDroid->psTarget)->currentPowerAccrued += POWER_PER_CYCLE; bPowerUsed = TRUE; } } } break; case DROID_REPAIR: case DROID_CYBORG_REPAIR: //check trying to repair something psTarget = NULL; if (DroidIsRepairing(psDroid)) { psTarget = (DROID *)psDroid->psTarget; } else { //might have guard order but action of repair if (orderState(psDroid, DORDER_GUARD) AND psDroid->action == DACTION_DROIDREPAIR) { psTarget = (DROID *)psDroid->psActionTarget; } } //check the droid hasn't died in the meantime if (psTarget AND psTarget->died) { psDroid->psTarget = NULL; psTarget = NULL; } if (psTarget) { powerDiff = powerReqForDroidRepair(psTarget) - psTarget->powerAccrued; //if equal then don't need power if (powerDiff > 0) { powerDiff /= POWER_FACTOR; if (POWER_PER_CYCLE >= powerDiff) { usePower(psDroid->player, powerDiff); //the unit accrues the power so more than one thing can be working on it psTarget->powerAccrued += (powerDiff * POWER_FACTOR); bPowerUsed = TRUE; } else if (powerDiff > POWER_PER_CYCLE) { usePower(psDroid->player, POWER_PER_CYCLE); psTarget->powerAccrued += (POWER_PER_CYCLE * POWER_FACTOR); bPowerUsed = TRUE; } } } break; default: //no need for power bPowerUsed = FALSE; break; } break; default: ASSERT( FALSE, "accruePower: Invalid object type" ); } return bPowerUsed; } //informs the power array that a object has been destroyed void powerDestroyObject(BASE_OBJECT *psObject) { //check that this wasn't the last object that received the power if (asPower[psObject->player]->psLastPowered == psObject) { updateLastPowered(NULL, psObject->player); } } /*checks if the Object to be powered next - returns TRUE if power*/ BOOL getLastPowered(BASE_OBJECT *psObject) { ASSERT( psObject != NULL, "getLastPowered - invalid object" ); if (asPower[psObject->player]->psLastPowered == NULL) { return TRUE; } /*if we've got round to the last object again, by setting to NULL will enable the next object to get some power*/ if (asPower[psObject->player]->psLastPowered == psObject) { asPower[psObject->player]->psLastPowered = NULL; } return FALSE; } /*inform the players power struct that the last object to receive power has changed*/ void updateLastPowered(BASE_OBJECT *psObject, UBYTE player) { asPower[player]->psLastPowered = psObject; } STRUCTURE *getRExtractor(STRUCTURE *psStruct) { STRUCTURE *psCurr; STRUCTURE *psFirst; BOOL bGonePastIt; for(psCurr = apsStructLists[selectedPlayer],psFirst = NULL,bGonePastIt = FALSE; psCurr; psCurr = psCurr->psNext) { if( psCurr->pStructureType->type == REF_RESOURCE_EXTRACTOR ) { if(!psFirst) { psFirst = psCurr; } if(!psStruct) { return(psCurr); } else if(psCurr!=psStruct AND bGonePastIt) { return(psCurr); } if(psCurr==psStruct) { bGonePastIt = TRUE; } } } return(psFirst); } /*defines which structure types draw power - returns TRUE if use power*/ BOOL structUsesPower(STRUCTURE *psStruct) { BOOL bUsesPower = FALSE; ASSERT( PTRVALID(psStruct, sizeof(STRUCTURE)), "structUsesPower: Invalid Structure pointer" ); switch(psStruct->pStructureType->type) { case REF_FACTORY: case REF_CYBORG_FACTORY: case REF_VTOL_FACTORY: case REF_RESEARCH: case REF_REPAIR_FACILITY: bUsesPower = TRUE; break; default: bUsesPower = FALSE; break; } return bUsesPower; } /*defines which droid types draw power - returns TRUE if use power*/ BOOL droidUsesPower(DROID *psDroid) { BOOL bUsesPower = FALSE; ASSERT( PTRVALID(psDroid, sizeof(DROID)), "unitUsesPower: Invalid unit pointer" ); switch(psDroid->droidType) { case DROID_CONSTRUCT: case DROID_REPAIR: case DROID_CYBORG_CONSTRUCT: case DROID_CYBORG_REPAIR: bUsesPower = TRUE; break; default: bUsesPower = FALSE; break; } return bUsesPower; } //won't bother with this on PSX unless starts being used too much! //this is a check cos there is a problem with the power but not sure where!! void powerCheck(BOOL bBeforePowerUsed, UBYTE player) { static BASE_OBJECT *psLastPowered = NULL; static BOOL bPowerBefore = FALSE; if (bBeforePowerUsed) { //set what the lastPowered object is before using any power psLastPowered = asPower[player]->psLastPowered; bPowerBefore = FALSE; //check that there is power available at start of loop if (asPower[player]->currentPower > POWER_PER_CYCLE) { bPowerBefore = TRUE; } } else { /*check to see if we've been thru the whole list of structures and droids and not reset the lastPowered object in the power structure and there was some power at the start of the loop to use*/ if (psLastPowered != NULL AND psLastPowered == asPower[player]-> psLastPowered AND bPowerBefore) { ASSERT( FALSE, "powerCheck: trouble at mill!" ); //initialise so something can have some power next cycle asPower[player]->psLastPowered = NULL; } } } /*initialise the PlayerPower based on what structures are available*/ /*BOOL initPlayerPower(void) { UDWORD player, usedPower; STRUCTURE *psBuilding; //total up the resources for (player = 0; player < MAX_PLAYERS; player++) { asPower[player]->extractedPower = 0; for (psBuilding = apsStructLists[player]; psBuilding != NULL; psBuilding = psBuilding->psNext) { if (psBuilding->pStructureType->type == REF_RESOURCE_EXTRACTOR OR psBuilding->pStructureType->type == REF_HQ) { extractedPowerUpdate(psBuilding); } } } //calculate the total available and capacity for (player = 0; player < MAX_PLAYERS; player++) { asPower[player]->availablePower = 0; asPower[player]->capacity = 0; for (psBuilding = apsStructLists[player]; psBuilding != NULL; psBuilding = psBuilding->psNext) { if (psBuilding->pStructureType->type == REF_POWER_GEN OR psBuilding->pStructureType->type == REF_HQ) { capacityUpdate(psBuilding); } } } //adjust for the power already used for (player = 0; player < MAX_PLAYERS; player++) { usedPower = calcPlayerUsedPower(player); if (usedPower > 0) { if ((SDWORD)asPower[player]->availablePower < usedPower) { asPower[player]->usedPower = asPower[player]->availablePower - usedPower; asPower[player]->availablePower = 0; // audio_PlayTrack( ID_SOUND_POWER_LOW ); } else { asPower[player]->availablePower -= usedPower; asPower[player]->usedPower = usedPower; } } } return TRUE; }*/ /*check the available power - if enough return true, else return false */ /*BOOL checkPower(UDWORD player, UDWORD quantity, BOOL playAudio) { //if not doing a check on the power - just return TRUE if (!powerCalculated) { return TRUE; } if (asPower[player]->availablePower >= quantity) { return TRUE; } else if (player == selectedPlayer) { #ifdef PSX #warning POWER LOW IS DISABLED return TRUE; #endif if (playAudio && player == selectedPlayer) { audio_QueueTrack( ID_SOUND_POWER_LOW ); return FALSE; } } return FALSE; }*/ /*check the available power - if enough subtracts the amount required to perform the task and returns true, else returns false */ /*BOOL usePower(UDWORD player, UDWORD quantity) { //if not doing a check on the power - just use the power and return TRUE if (!powerCalculated) { if (asPower[player]->usedPower >= 0) { asPower[player]->usedPower += quantity; } else { asPower[player]->usedPower -= quantity; } return TRUE; } //check there is enough first if (asPower[player]->availablePower >= quantity) { asPower[player]->availablePower -= quantity; asPower[player]->usedPower += quantity; return TRUE; } else if (player == selectedPlayer) { #ifdef PSX #warning POWER LOW IS DISABLED return TRUE; #endif if(titleMode == FORCESELECT) //|| (titleMode == DESIGNSCREEN)) { return FALSE; } if(player == selectedPlayer) { audio_QueueTrack( ID_SOUND_POWER_LOW ); } return FALSE; } }*/ //return the power when a structure/droid is destroyed /*void returnPower(UDWORD player, UDWORD quantity) { if (asPower[player]->usedPower < 0) { asPower[player]->usedPower += quantity; } else { asPower[player]->usedPower -= quantity; asPower[player]->availablePower += quantity; } }*/ /*Update the available power if necessary */ /*void availablePowerUpdate(STRUCTURE *psBuilding) { UDWORD power; //check its the correct type of building if (psBuilding->pStructureType->type == REF_POWER_GEN OR psBuilding->pStructureType->type == REF_HQ) { if ((SDWORD)(asPower[psBuilding->player]->extractedPower) > asPower[psBuilding-> player]->capacity) { power = asPower[psBuilding->player]->capacity; asPower[psBuilding->player]->extractedPower -= power; } else { power = asPower[psBuilding->player]->extractedPower; asPower[psBuilding->player]->extractedPower = 0; } //for power gens need to use the multiplier //if (psBuilding->pStructureType->type == REF_POWER_GEN) //{ // power = power * ((POWER_GEN *)psBuilding->pFunctionality)->multiplier; //} asPower[psBuilding->player]->capacity -= power; asPower[psBuilding->player]->availablePower += power ; } }*/ /*Update the extracted power if necessary */ /*void extractedPowerUpdate(STRUCTURE *psBuilding) { STRUCTURE *psStruct; UDWORD power = 0; if (psBuilding->pStructureType->type == REF_RESOURCE_EXTRACTOR) { power = ((RES_EXTRACTOR *)psBuilding->pFunctionality)->power; } if (psBuilding->pStructureType->type == REF_HQ) { power = ((HQ_FUNCTION *)psBuilding->pStructureType->asFuncList[0])->power; } if (power) { asPower[psBuilding->player]->extractedPower += power; //increase in extracted power might lead to more power being available. if (asPower[psBuilding->player]->capacity != 0) { for (psStruct = apsStructLists[psBuilding->player]; psStruct != NULL AND asPower[psBuilding->player]->extractedPower != 0; psStruct = psStruct->psNext) { if (psStruct->pStructureType->type == REF_POWER_GEN OR psStruct->pStructureType->type == REF_HQ) { availablePowerUpdate(psStruct); } } } } }*/ /*update the generator capacity if necessary. This function is called whenever a Power Generator or Power Module is built or HQ is built*/ /*void capacityUpdate(STRUCTURE * psBuilding) { UDWORD power = 0; if (psBuilding->pStructureType->type == REF_POWER_GEN) { //only add on module power if this is what has been built BIT OF A HACK REALLY! if (((POWER_GEN*)psBuilding->pFunctionality)->power != ((POWER_GEN_FUNCTION*) psBuilding->pStructureType->asFuncList[0])->powerOutput) { //subtract the power output without modules asPower[psBuilding->player]->capacity -= ((POWER_GEN_FUNCTION*) psBuilding->pStructureType->asFuncList[0])->powerOutput; } //asPower[psBuilding->player]->capacity += (((POWER_GEN *)psBuilding-> // pFunctionality)->power * ((POWER_GEN *)psBuilding->pFunctionality)-> // multiplier); power = (((POWER_GEN *)psBuilding->pFunctionality)->power * ((POWER_GEN *)psBuilding->pFunctionality)->multiplier); } else { if (psBuilding->pStructureType->type == REF_HQ) { power = ((HQ_FUNCTION *)psBuilding->pStructureType->asFuncList[0])->power; } } if (power) { asPower[psBuilding->player]->capacity += power; //now check if there is any spare extracted power if (asPower[psBuilding->player]->extractedPower != 0) { availablePowerUpdate(psBuilding); } } }*/ /*reset the power levels when a power_gen or resource_extractor is destroyed */ /*BOOL resetPlayerPower(UDWORD player, STRUCTURE *psStruct) { STRUCTURE *psBuilding; UDWORD usedPower; asPower[player]->extractedPower = 0; asPower[player]->capacity = 0; //total up the resources for (psBuilding = apsStructLists[player]; psBuilding != NULL; psBuilding = psBuilding->psNext) { if (psStruct != psBuilding) { if (psBuilding->pStructureType->type == REF_RESOURCE_EXTRACTOR OR psBuilding->pStructureType->type == REF_HQ) { extractedPowerUpdate(psBuilding); } } } asPower[player]->availablePower = 0; // add multiplayer allowances if a multiplayer game. #ifndef PSX if(bMultiPlayer && (game.dmatch || game.base == CAMP_CLEAN)) { asPower[player]->availablePower = game.power+RESIDUAL_POW; } #endif //calculate the total available and capacity for (psBuilding = apsStructLists[player]; psBuilding != NULL; psBuilding = psBuilding->psNext) { if (psStruct != psBuilding) { if (psBuilding->pStructureType->type == REF_POWER_GEN OR psBuilding->pStructureType->type == REF_HQ) { capacityUpdate(psBuilding); } } } //adjust for the power already used usedPower = calcPlayerUsedPower(player); if ((SDWORD)asPower[player]->availablePower < usedPower) { asPower[player]->usedPower = asPower[player]->availablePower - usedPower; asPower[player]->availablePower = 0; if (player == selectedPlayer) { audio_QueueTrack( ID_SOUND_POWER_LOW ); } } else { asPower[player]->availablePower -= usedPower; asPower[player]->usedPower = usedPower; } return TRUE; }*/ /*looks through the player's list of droids and structures to see what power has been used*/ /*UDWORD calcPlayerUsedPower(UDWORD player) { DROID *psDroid; STRUCTURE *psStruct; UDWORD used = 0; for (psDroid = apsDroidLists[player]; psDroid != NULL; psDroid = psDroid-> psNext) { used += psDroid->power; } for (psStruct = apsStructLists[player]; psStruct != NULL; psStruct = psStruct->psNext) { used += psStruct->pStructureType->powerToBuild; } return used; }*/ /*resets the power levels for all players when power is turned back on*/ /*void powerCalc(BOOL on) { UDWORD inc; if (on) { powerCalculated = TRUE; for (inc=0; inc < MAX_PLAYERS; inc++) { resetPlayerPower(inc, NULL); } } else { powerCalculated = FALSE; } }*/