Files
source/Strategic/Strategic Mines.cpp
T
BeatAroundTheBuscherandGitHub ed00830202 Fixes Upper/Lower Casing for include paths (#487)
* Fixing upper/lower case for includes

types.h, zconf.h and zlib.h were renamed so that global includes like Types.h
are not used.
2025-08-16 22:01:12 -03:00

1446 lines
43 KiB
C++

#include <string.h>
#include "Strategic Mines.h"
#include "finances.h"
#include "Strategic Town Loyalty.h"
#include "strategic.h"
#include "Game Clock.h"
#include "strategicmap.h"
#include "random.h"
#include "Soldier Profile.h"
#include "Dialogue Control.h"
#include "Map Screen Interface.h"
#include "Quests.h"
#include "Creature Spreading.h"
#include "message.h"
#include "Text.h"
#include "Game Event Hook.h"
#include "GameSettings.h"
#include "Strategic AI.h"
#include "Campaign Types.h"
#include "history.h"
#include "Facilities.h"
#include "ASD.h" // added by Flugente
#include "Rebel Command.h"
#include "GameInitOptionsScreen.h"
#include "Strategic Mines LUA.h"
#include <vector>
// this .c file will handle the strategic level of mines and income from them
#define REMOVAL_RATE_INCREMENT 250 // the smallest increment by which removal rate change during depletion (use round #s)
#define LOW_MINE_LOYALTY_THRESHOLD 50 // below this the head miner considers his town's population disloyal
// Mine production is being processed 4x daily: 9am ,noon, 3pm, and 6pm.
// This is loosely based on a 6am-6pm working day of 4 "shifts".
#define MINE_PRODUCTION_NUMBER_OF_PERIODS 4 // how many times a day mine production is processed
#define MINE_PRODUCTION_START_TIME (9 * 60) // hour of first daily mine production event (in minutes)
#define MINE_PRODUCTION_PERIOD (3 * 60) // time seperating daily mine production events (in minutes)
// PRIVATE PROTOTYPES
// mine this mine
INT32 MineAMine( INT8 bMineIndex );
// remove actual ore from mine
UINT32 ExtractOreFromMine( INT8 bMineIndex, UINT32 uiAmount );
// get available workforce for the mine
INT32 GetAvailableWorkForceForMineForPlayer( INT8 bMineIndex );
// get workforce conscripted by enemy for mine
INT32 GetAvailableWorkForceForMineForEnemy( INT8 bMineIndex );
// how fast is the mine's workforce working for you?
INT32 GetCurrentWorkRateOfMineForPlayer( INT8 bMineIndex );
// how fast is workforce working for the enemy
INT32 GetCurrentWorkRateOfMineForEnemy( INT8 bMineIndex );
// DATA TABLES
// this table holds mine values that change during the course of the game and must be saved
//MINE_STATUS_TYPE gMineStatus[ MAX_NUMBER_OF_MINES ];
std::vector<MINE_STATUS_TYPE> gMineStatus;
INT32 MAX_NUMBER_OF_MINES; // equals gMineStatus.size()
std::vector<AssociatedMineSector> associatedMineSectors;
// this table holds mine values that never change and don't need to be saved
//MINE_LOCATION_TYPE gMineLocation[MAX_NUMBER_OF_MINES] =
//{
// { 4, 4, SAN_MONA },
// { 13, 4, DRASSEN },
// { 14, 9, ALMA },
// { 8, 8, CAMBRIA },
// { 2, 2, CHITZENA },
// { 3, 8, GRUMM },
//};
// the are not being randomized at all at this time
//UINT8 gubMineTypes[]={
// GOLD_MINE, // SAN MONA
// SILVER_MINE, // DRASSEN
// SILVER_MINE, // ALMA
// SILVER_MINE, // CAMBRIA
// SILVER_MINE, // CHITZENA
// GOLD_MINE, // GRUMM
//};
// These values also determine the most likely ratios of mine sizes after random production increases are done
//UINT32 guiMinimumMineProduction[]={
// 0, // SAN MONA
// 1000, // DRASSEN
// 1500, // ALMA
// 1500, // CAMBRIA
// 500, // CHITZENA
// 2000, // GRUMM
//};
std::vector<HEAD_MINER_TYPE> gHeadMinerData;
INT32 NUM_HEAD_MINERS; // equals gHeadMinerData.size()
//HEAD_MINER_TYPE gHeadMinerData[NUM_HEAD_MINERS] =
//{
// // Profile # running out creatures! all dead! creatures again! external face graphic
// { FRED, 17, 18, 27, 26, MINER_FRED_EXTERNAL_FACE },
// { MATT, -1, 18, 32, 31, MINER_MATT_EXTERNAL_FACE },
// { OSWALD, 14, 15, 24, 23, MINER_OSWALD_EXTERNAL_FACE },
// { CALVIN, 14, 15, 24, 23, MINER_CALVIN_EXTERNAL_FACE },
// { CARL, 14, 15, 24, 23, MINER_CARL_EXTERNAL_FACE },
//};
/* gradual monster infestation concept was ditched, now simply IN PRODUCTION or SHUT DOWN
// percentage of workers working depends on level of mine infestation
UINT8 gubMonsterMineInfestation[]={
100,
99,
95,
70,
30,
1,
0,
};
*/
// the static NPC dialogue faces
//extern UINT32 uiExternalStaticNPCFaces[];
extern FACETYPE *gpCurrentTalkingFace;
extern UINT8 gubCurrentTalkingID;
void InitializeMines( void )
{
INT32 i;
// Don't execute hardcoded logic. Leave initialization to the Lua script.
g_luaMines.InitializeMines();
// Buggler: set mining site flag for AI Viewer.cpp
for (i=0; i < MAX_NUMBER_OF_MINES; i++)
{
SectorInfo[ SECTOR( gMineStatus[i].sSectorX, gMineStatus[i].sSectorY ) ].uiFlags |= SF_MINING_SITE;
}
#if 0
UINT8 ubMineIndex;
MINE_STATUS_TYPE *pMineStatus;
UINT8 ubMineProductionIncreases;
UINT8 ubDepletedMineIndex;
UINT8 ubMinDaysBeforeDepletion = 20;
// set up initial mine status
for( ubMineIndex = 0; ubMineIndex < MAX_NUMBER_OF_MINES; ubMineIndex++ )
{
pMineStatus = &(gMineStatus[ ubMineIndex ]);
memset( pMineStatus, 0, sizeof( *pMineStatus ) );
pMineStatus->ubMineType = gubMineTypes[ ubMineIndex ];
pMineStatus->uiMaxRemovalRate = guiMinimumMineProduction[ ubMineIndex ];
pMineStatus->fEmpty = (pMineStatus->uiMaxRemovalRate == 0) ? TRUE : FALSE;
pMineStatus->fRunningOut = FALSE;
pMineStatus->fWarnedOfRunningOut = FALSE;
// pMineStatus->bMonsters = MINES_NO_MONSTERS;
pMineStatus->fShutDown = FALSE;
pMineStatus->fPrevInvadedByMonsters = FALSE;
pMineStatus->fSpokeToHeadMiner = FALSE;
pMineStatus->fMineHasProducedForPlayer = FALSE;
pMineStatus->fQueenRetookProducingMine = FALSE;
gMineStatus->fShutDownIsPermanent = FALSE;
}
// randomize the exact size each mine. The total production is always the same and depends on the game difficulty,
// but some mines will produce more in one game than another, while others produce less
// adjust for game difficulty
switch( gGameOptions.ubDifficultyLevel )
{
case DIF_LEVEL_EASY:
case DIF_LEVEL_MEDIUM:
ubMineProductionIncreases = 25;
break;
case DIF_LEVEL_HARD:
ubMineProductionIncreases = 20;
break;
case DIF_LEVEL_INSANE:
ubMineProductionIncreases = 15;
break;
default:
ubMineProductionIncreases = 25;
//Assert( 0 );
return;
}
while (ubMineProductionIncreases > 0)
{
// pick a producing mine at random and increase its production
do
{
ubMineIndex = ( UINT8 ) Random(MAX_NUMBER_OF_MINES);
} while (gMineStatus[ubMineIndex].fEmpty);
// increase mine production by 20% of the base (minimum) rate
gMineStatus[ubMineIndex].uiMaxRemovalRate += (guiMinimumMineProduction[ubMineIndex] / 5);
ubMineProductionIncreases--;
}
// choose which mine will run out of production. This will never be the Alma mine or an empty mine (San Mona)...
do
{
ubDepletedMineIndex = ( UINT8 ) Random(MAX_NUMBER_OF_MINES);
// Alma mine can't run out for quest-related reasons (see Ian)
} while (gMineStatus[ubDepletedMineIndex].fEmpty || (ubDepletedMineIndex == MINE_ALMA));
// HEADROCK HAM 3.1: We can now select which mine runs out, or disable mine shutdown.
// Make sure selection isn't 0 (no mine runs out) or invalid (San Mona, Alma)
if (gGameExternalOptions.bWhichMineRunsOut > 0 &&
gGameExternalOptions.bWhichMineRunsOut < MAX_NUMBER_OF_MINES &&
gGameExternalOptions.bWhichMineRunsOut-1 != MINE_SAN_MONA &&
gGameExternalOptions.bWhichMineRunsOut-1 != MINE_ALMA )
{
// Set depleted mine index.
ubDepletedMineIndex = (gGameExternalOptions.bWhichMineRunsOut-1);
}
for( ubMineIndex = 0; ubMineIndex < MAX_NUMBER_OF_MINES; ubMineIndex++ )
{
pMineStatus = &(gMineStatus[ ubMineIndex ]);
// HEADROCK HAM 3.1: We can disable mine shutdown, so make sure the settings aren't telling us to do so.
if (gGameExternalOptions.bWhichMineRunsOut != 0 && ubMineIndex == ubDepletedMineIndex)
{
if ( ubDepletedMineIndex == MINE_DRASSEN )
{
ubMinDaysBeforeDepletion = 20;
}
else
{
ubMinDaysBeforeDepletion = 10;
}
// the mine that runs out has only enough ore for this many days of full production
pMineStatus->uiRemainingOreSupply = ubMinDaysBeforeDepletion * (MINE_PRODUCTION_NUMBER_OF_PERIODS * pMineStatus->uiMaxRemovalRate);
// ore starts running out when reserves drop to less than 25% of the initial supply
pMineStatus->uiOreRunningOutPoint = pMineStatus->uiRemainingOreSupply / 4;
}
else
if (!pMineStatus->fEmpty)
{
// never runs out...
pMineStatus->uiRemainingOreSupply = 999999999; // essentially unlimited
pMineStatus->uiOreRunningOutPoint = 0;
}
else
{
// already empty
pMineStatus->uiRemainingOreSupply = 0;
pMineStatus->uiOreRunningOutPoint = 0;
}
}
#endif
}
void HourlyMinesUpdate(void)
{
UINT8 ubMineIndex;
MINE_STATUS_TYPE *pMineStatus;
UINT8 ubQuoteType;
// check every non-empty mine
for( ubMineIndex = 0; ubMineIndex < MAX_NUMBER_OF_MINES; ubMineIndex++ )
{
pMineStatus = &(gMineStatus[ ubMineIndex ]);
if (pMineStatus->fEmpty)
{
// nobody is working that mine, so who cares
continue;
}
// check if the mine has any monster creatures in it
if (MineClearOfMonsters( ubMineIndex ))
{
// if it's shutdown, but not permanently
if (IsMineShutDown( ubMineIndex ) && !pMineStatus->fShutDownIsPermanent)
{
// if we control production in it
if (PlayerControlsMine( ubMineIndex ))
{
IssueHeadMinerQuote( ubMineIndex, HEAD_MINER_STRATEGIC_QUOTE_CREATURES_GONE );
}
//Force the creatures to avoid the mine for a period of time. This gives the
//player a chance to rest and decide how to deal with the problem.
ForceCreaturesToAvoidMineTemporarily( ubMineIndex );
// put mine back in service
RestartMineProduction( ubMineIndex );
}
}
else // mine is monster infested
{
// 'Der be monsters crawling around in there, lad!!!
// if it's still producing
if (!IsMineShutDown( ubMineIndex ))
{
// gotta put a stop to that!
// if we control production in it
if (PlayerControlsMine( ubMineIndex ))
{
// 2 different quotes, depends whether or not it's the first time this has happened
if (pMineStatus->fPrevInvadedByMonsters)
{
ubQuoteType = HEAD_MINER_STRATEGIC_QUOTE_CREATURES_AGAIN;
}
else
{
ubQuoteType = HEAD_MINER_STRATEGIC_QUOTE_CREATURES_ATTACK;
pMineStatus->fPrevInvadedByMonsters = TRUE;
if ( gubQuest[ QUEST_CREATURES ] == QUESTNOTSTARTED )
{
// start it now!
//StartQuest( QUEST_CREATURES, gMineLocation[ ubMineIndex ].sSectorX, gMineLocation[ ubMineIndex ].sSectorY );
StartQuest( QUEST_CREATURES, gMineStatus[ ubMineIndex ].sSectorX, gMineStatus[ ubMineIndex ].sSectorY );
}
}
// tell player the good news...
IssueHeadMinerQuote( ubMineIndex, ubQuoteType );
}
// and immediately halt all work at the mine (whether it's ours or the queen's). This is a temporary shutdown
ShutOffMineProduction( ubMineIndex );
}
}
}
}
INT32 GetTotalLeftInMine( INT8 bMineIndex )
{
// returns the value of the mine
Assert( ( bMineIndex >= 0 ) && ( bMineIndex < MAX_NUMBER_OF_MINES ) );
return ( gMineStatus[ bMineIndex ].uiRemainingOreSupply );
}
UINT32 GetMaxPeriodicRemovalFromMine( INT8 bMineIndex )
{
// returns max amount that can be mined in a time period
Assert( ( bMineIndex >= 0 ) && ( bMineIndex < MAX_NUMBER_OF_MINES ) );
// if mine is shut down
if ( gMineStatus[ bMineIndex ].fShutDown)
{
return ( 0 );
}
// HEADROCK HAM B1: Affected by external INI option.
return(( gMineStatus[ bMineIndex ].uiMaxRemovalRate * gGameExternalOptions.usMineIncomePercentage ) / 100);
}
UINT32 GetMaxDailyRemovalFromMine( INT8 bMineIndex )
{
UINT32 uiAmtExtracted;
// returns max amount that can be mined in one day
Assert( ( bMineIndex >= 0 ) && ( bMineIndex < MAX_NUMBER_OF_MINES ) );
// if mine is shut down
if ( gMineStatus[ bMineIndex ].fShutDown)
{
return ( 0 );
}
uiAmtExtracted = MINE_PRODUCTION_NUMBER_OF_PERIODS * gMineStatus[ bMineIndex ].uiMaxRemovalRate;
// check if we will take more than there is
if( uiAmtExtracted > gMineStatus[ bMineIndex ].uiRemainingOreSupply )
{
// yes, reduce to value of mine
uiAmtExtracted = gMineStatus[ bMineIndex ].uiRemainingOreSupply;
}
// HEADROCK HAM B1: Affected by external INI option.
uiAmtExtracted = (uiAmtExtracted * gGameExternalOptions.usMineIncomePercentage) / 100;
return(uiAmtExtracted);
}
INT8 GetTownAssociatedWithMine( INT8 bMineIndex )
{
Assert( ( bMineIndex >= 0 ) && ( bMineIndex < MAX_NUMBER_OF_MINES ) );
//return ( gMineLocation[ bMineIndex ].bAssociatedTown );
return ( gMineStatus[ bMineIndex ].bAssociatedTown );
}
UINT32 ExtractOreFromMine( INT8 bMineIndex, UINT32 uiAmount )
{
// will remove the ore from the mine and return the amount that was removed
UINT32 uiAmountExtracted = 0;
INT16 sSectorX, sSectorY;
Assert( ( bMineIndex >= 0 ) && ( bMineIndex < MAX_NUMBER_OF_MINES ) );
// if mine is shut down
if ( gMineStatus[ bMineIndex ].fShutDown)
{
return ( 0 );
}
// if not capable of extracting anything, bail now
if (uiAmount == 0)
{
return ( 0 );
}
// will this exhaust the ore in this mine?
if( uiAmount >= gMineStatus[ bMineIndex ].uiRemainingOreSupply )
{
// exhaust remaining ore
uiAmountExtracted = gMineStatus[ bMineIndex ].uiRemainingOreSupply;
gMineStatus[ bMineIndex ].uiRemainingOreSupply = 0;
gMineStatus[ bMineIndex ].uiMaxRemovalRate = 0;
gMineStatus[ bMineIndex ].fEmpty = TRUE;
gMineStatus[ bMineIndex ].fRunningOut = FALSE;
// tell the strategic AI about this, that mine's and town's value is greatly reduced
GetMineSector( bMineIndex, &sSectorX, &sSectorY );
StrategicHandleMineThatRanOut( ( UINT8 ) SECTOR( sSectorX, sSectorY ) );
//AddHistoryToPlayersLog( HISTORY_MINE_RAN_OUT, gMineLocation[ bMineIndex ].bAssociatedTown, GetWorldTotalMin( ), gMineLocation[ bMineIndex ].sSectorX, gMineLocation[ bMineIndex ].sSectorY );
AddHistoryToPlayersLog( HISTORY_MINE_RAN_OUT, gMineStatus[ bMineIndex ].bAssociatedTown, GetWorldTotalMin( ), gMineStatus[ bMineIndex ].sSectorX, gMineStatus[ bMineIndex ].sSectorY );
}
else // still some left after this extraction
{
// set amount used, and decrement ore remaining in mine
uiAmountExtracted = uiAmount;
gMineStatus[ bMineIndex ].uiRemainingOreSupply -= uiAmount;
// one of the mines (randomly chosen) will start running out eventually, check if we're there yet
if (gMineStatus[ bMineIndex ].uiRemainingOreSupply < gMineStatus[ bMineIndex ].uiOreRunningOutPoint)
{
gMineStatus[ bMineIndex ].fRunningOut = TRUE;
// round all fractions UP to the next REMOVAL_RATE_INCREMENT
gMineStatus[ bMineIndex ].uiMaxRemovalRate = (UINT32) (((FLOAT) gMineStatus[ bMineIndex ].uiRemainingOreSupply / 10) / REMOVAL_RATE_INCREMENT + 0.9999) * REMOVAL_RATE_INCREMENT;
// if we control it
if (PlayerControlsMine(bMineIndex))
{
// and haven't yet been warned that it's running out
if (!gMineStatus[ bMineIndex ].fWarnedOfRunningOut)
{
// that mine's head miner tells player that the mine is running out
IssueHeadMinerQuote( bMineIndex, HEAD_MINER_STRATEGIC_QUOTE_RUNNING_OUT );
gMineStatus[ bMineIndex ].fWarnedOfRunningOut = TRUE;
//AddHistoryToPlayersLog( HISTORY_MINE_RUNNING_OUT, gMineLocation[ bMineIndex ].bAssociatedTown, GetWorldTotalMin( ), gMineLocation[ bMineIndex ].sSectorX, gMineLocation[ bMineIndex ].sSectorY );
AddHistoryToPlayersLog( HISTORY_MINE_RUNNING_OUT, gMineStatus[ bMineIndex ].bAssociatedTown, GetWorldTotalMin( ), gMineStatus[ bMineIndex ].sSectorX, gMineStatus[ bMineIndex ].sSectorY );
}
}
}
}
return( uiAmountExtracted );
}
INT32 GetAvailableWorkForceForMineForPlayer( INT8 bMineIndex )
{
// look for available workforce in the town associated with the mine
INT32 iWorkForceSize = 0;
INT8 bTownId = 0;
// return the loyalty of the town associated with the mine
Assert( ( bMineIndex >= 0 ) && ( bMineIndex < MAX_NUMBER_OF_MINES ) );
// if mine is shut down
if ( gMineStatus[ bMineIndex ].fShutDown)
{
return ( 0 );
}
// until the player contacts the head miner, production in mine ceases if in player's control
if ( !gMineStatus[ bMineIndex ].fSpokeToHeadMiner)
{
return ( 0 );
}
//bTownId = gMineLocation[ bMineIndex ].bAssociatedTown;
bTownId = gMineStatus[ bMineIndex ].bAssociatedTown;
Assert ( GetTownSectorSize( bTownId ) != 0 );
// get workforce size (is 0-100 based on local town's loyalty)
iWorkForceSize = gTownLoyalty[ bTownId ].ubRating;
/*
// adjust for monster infestation
iWorkForceSize *= gubMonsterMineInfestation[ gMineStatus[ bMineIndex ].bMonsters ];
iWorkForceSize /= 100;
*/
// Flugente: if strategic disease is active, disease can affect out workforce, so the calculation gets slightly more complicated
iWorkForceSize = (INT32)(iWorkForceSize * GetWorkforceEffectivenessWithDisease(bTownId, OUR_TEAM));
// now adjust for town size.. the number of sectors you control
iWorkForceSize *= GetTownSectorsUnderControl( bTownId );
iWorkForceSize /= GetTownSectorSize( bTownId );
// Flugente: workforce
if ( gGameExternalOptions.fMineRequiresWorkers )
{
UINT16 maxworkforce = 0;
UINT16 workforce = GetTownWorkers( bTownId, maxworkforce);
if ( maxworkforce > 0 )
{
iWorkForceSize *= workforce;
iWorkForceSize /= maxworkforce;
}
}
return ( iWorkForceSize );
}
INT32 GetAvailableWorkForceForMineForEnemy( INT8 bMineIndex )
{
// look for available workforce in the town associated with the mine
INT32 iWorkForceSize = 0;
INT8 bTownId = 0;
// return the loyalty of the town associated with the mine
Assert( ( bMineIndex >= 0 ) && ( bMineIndex < MAX_NUMBER_OF_MINES ) );
// if mine is shut down
if ( gMineStatus[ bMineIndex ].fShutDown)
return ( 0 );
bTownId = gMineStatus[ bMineIndex ].bAssociatedTown;
UINT8 townsize = GetTownSectorSize( bTownId );
if ( !townsize )
return 0;
// get workforce size (is 0-100 based on REVERSE of local town's loyalty)
iWorkForceSize = 100 - gTownLoyalty[ bTownId ].ubRating;
/*
// adjust for monster infestation
iWorkForceSize *= gubMonsterMineInfestation[ gMineStatus[ bMineIndex ].bMonsters ];
iWorkForceSize /= 100;
*/
// now adjust for town size.. the number of sectors you control
iWorkForceSize *= (townsize - GetTownSectorsUnderControl( bTownId ));
iWorkForceSize /= townsize;
return iWorkForceSize;
}
INT32 GetCurrentWorkRateOfMineForPlayer( INT8 bMineIndex )
{
INT32 iWorkRate = 0;
// multiply maximum possible removal rate by the percentage of workforce currently working
iWorkRate = (gMineStatus[ bMineIndex ].uiMaxRemovalRate * GetAvailableWorkForceForMineForPlayer( bMineIndex )) / 100;
return( iWorkRate );
}
INT32 GetCurrentWorkRateOfMineForEnemy( INT8 bMineIndex )
{
INT32 iWorkRate = 0;
// multiply maximum possible removal rate by the percentage of workforce currently working
iWorkRate = (gMineStatus[ bMineIndex ].uiMaxRemovalRate * GetAvailableWorkForceForMineForEnemy( bMineIndex )) / 100;
return( iWorkRate );
}
INT32 MineAMine( INT8 bMineIndex )
{
// will extract ore based on available workforce, and increment players income based on amount
INT8 bMineType = 0;
INT32 iAmtExtracted = 0;
Assert( ( bMineIndex >= 0 ) && ( bMineIndex < MAX_NUMBER_OF_MINES ) );
// is mine is empty
if( gMineStatus[ bMineIndex ].fEmpty)
{
return 0;
}
// if mine is shut down
if ( gMineStatus[ bMineIndex ].fShutDown)
{
return 0;
}
// who controls the PRODUCTION in the mine ? (Queen receives production unless player has spoken to the head miner)
if( PlayerControlsMine(bMineIndex) )
{
// player controlled
iAmtExtracted = ExtractOreFromMine( bMineIndex , GetCurrentWorkRateOfMineForPlayer( bMineIndex ) );
// SHOW ME THE MONEY!!!!
if( iAmtExtracted > 0 )
{
// debug message
// ScreenMsg( MSG_FONT_RED, MSG_DEBUG, L"%s - Mine income from %s = $%d", WORLDTIMESTR, pTownNames[ GetTownAssociatedWithMine( bMineIndex ) ], iAmtExtracted );
// check type of mine
bMineType = gMineStatus[ bMineIndex ].ubMineType;
// if this is the first time this mine has produced income for the player in the game
if ( !gMineStatus[ bMineIndex ].fMineHasProducedForPlayer )
{
// remember that we've earned income from this mine during the game
gMineStatus[ bMineIndex ].fMineHasProducedForPlayer = TRUE;
// and when we started to do so...
gMineStatus[ bMineIndex ].uiTimePlayerProductionStarted = GetWorldTotalMin();
}
}
}
else // queen controlled
{
// we didn't want mines to run out without player ever even going to them, so now the queen doesn't reduce the
// amount remaining until the mine has produced for the player first (so she'd have to capture it).
/*// WANNE: We do not want to give money to the player, when the queen has captured the mine!
if ( gMineStatus[ bMineIndex ].fMineHasProducedForPlayer )
{
// don't actually give her money, just take production away
//iAmtExtracted = ExtractOreFromMine( bMineIndex , GetCurrentWorkRateOfMineForEnemy( bMineIndex ) );
iAmtExtracted = 0;
}*/
// Flugente: if the enemy controls a mine, simply don't lower the amount of ore in the mine, so it can still run out when the player controls it
iAmtExtracted = GetCurrentWorkRateOfMineForEnemy( bMineIndex );
}
return iAmtExtracted;
}
void PostEventsForMineProduction(void)
{
UINT8 ubShift;
for (ubShift = 0; ubShift < MINE_PRODUCTION_NUMBER_OF_PERIODS; ubShift++)
{
AddStrategicEvent( EVENT_HANDLE_MINE_INCOME, GetWorldDayInMinutes() + MINE_PRODUCTION_START_TIME + (ubShift * MINE_PRODUCTION_PERIOD), 0 );
}
}
void HandleIncomeFromMines( void )
{
INT32 iIncome = 0;
INT32 iIncome_Enemy = 0; // Flugente: new AI gets money from mines
INT32 iModifier = 0;
// mine each mine, check if we own it and such
for ( INT8 bCounter = 0; bCounter < MAX_NUMBER_OF_MINES; ++bCounter )
{
if ( PlayerControlsMine( bCounter ) )
{
// HEADROCK HAM 3.6: Add facility modifier as a percentage
// add rebel command bonus
iModifier = 100 + MineIncomeModifierFromFacility( bCounter ) + RebelCommand::GetMiningPolicyBonus(gMineStatus[bCounter].bAssociatedTown);
// mine this mine
iIncome += (MineAMine( bCounter ) * iModifier) / 100;
}
else
{
// mine this mine
iIncome_Enemy += MineAMine( bCounter );
}
}
// HEADROCK HAM B1: Affected by external INI Option.
iIncome = (iIncome * gGameExternalOptions.usMineIncomePercentage) / 100;
iIncome_Enemy = (iIncome_Enemy * gGameExternalOptions.usMineIncomePercentage) / 100;
RebelCommand::RaidMines(iIncome, iIncome_Enemy);
if( iIncome )
{
AddTransactionToPlayersBook( DEPOSIT_FROM_SILVER_MINE, 0, GetWorldTotalMin( ), iIncome );
}
if ( iIncome_Enemy )
{
AddStrategicAIResources( ASD_MONEY, iIncome_Enemy );
}
}
UINT32 PredictDailyIncomeFromAMine( INT8 bMineIndex, BOOLEAN fIncludeFacilities )
{
// predict income from this mine, estimate assumes mining situation will not change during next 4 income periods
// (miner loyalty, % town controlled, monster infestation level, and current max removal rate may all in fact change)
UINT32 uiAmtExtracted = 0;
// HEADROCK HAM 3.6: Facilities can now modify income
INT32 iModifier = 0;
if(PlayerControlsMine(bMineIndex))
{
// get daily income for this mine (regardless of what time of day it currently is)
uiAmtExtracted = MINE_PRODUCTION_NUMBER_OF_PERIODS * GetCurrentWorkRateOfMineForPlayer( bMineIndex );
// check if we will take more than there is
if( uiAmtExtracted > gMineStatus[ bMineIndex ].uiRemainingOreSupply )
{
// yes reduce to value of mine
uiAmtExtracted = gMineStatus[ bMineIndex ].uiRemainingOreSupply;
}
if (bMineIndex && fIncludeFacilities)
{
// HEADROCK HAM 3.6: Facility modifier applied as a percentage
// add rebel command bonus
iModifier = 100 + MineIncomeModifierFromFacility( bMineIndex ) + RebelCommand::GetMiningPolicyBonus(gMineStatus[bMineIndex].bAssociatedTown);
uiAmtExtracted = (uiAmtExtracted * iModifier) / 100;
}
}
// HEADROCK HAM B1: Affected by external INI Option.
return( ( uiAmtExtracted * gGameExternalOptions.usMineIncomePercentage ) / 100 ) ;
}
INT32 PredictIncomeFromPlayerMines( BOOLEAN fIncludeFacilities )
{
INT32 iTotal = 0;
INT8 bCounter = 0;
for( bCounter = 0; bCounter < MAX_NUMBER_OF_MINES; bCounter++ )
{
// add up the total
iTotal += PredictDailyIncomeFromAMine( bCounter, fIncludeFacilities );
}
return( iTotal );
}
INT32 CalcMaxPlayerIncomeFromMines( void )
{
INT32 iTotal = 0;
INT8 bCounter = 0;
// calculate how much player could make daily if he owned all mines with 100% control and 100% loyalty
for( bCounter = 0; bCounter < MAX_NUMBER_OF_MINES; bCounter++ )
{
// add up the total
iTotal += (MINE_PRODUCTION_NUMBER_OF_PERIODS * gMineStatus[bCounter].uiMaxRemovalRate);
}
// HEADROCK HAM B1: Affected by external INI Option.
iTotal = (iTotal * gGameExternalOptions.usMineIncomePercentage) / 100;
return( iTotal );
}
// get index of this mine, return -1 if no mine found
INT8 GetMineIndexForSector( INT16 sX, INT16 sY )
{
UINT8 ubMineIndex = 0;
for( ubMineIndex = 0; ubMineIndex < MAX_NUMBER_OF_MINES; ubMineIndex++ )
{
//if( ( gMineLocation[ ubMineIndex ].sSectorX == sX ) && ( gMineLocation[ ubMineIndex ].sSectorY == sY ) )
if( ( gMineStatus[ ubMineIndex ].sSectorX == sX ) && ( gMineStatus[ ubMineIndex ].sSectorY == sY ) )
{
// yep mine here
return( ubMineIndex );
}
}
return( -1 );
}
void GetMineSector( UINT8 ubMineIndex, INT16 * psX, INT16 * psY )
{
Assert(ubMineIndex < MAX_NUMBER_OF_MINES);
//*psX = gMineLocation[ ubMineIndex ].sSectorX;
//*psY = gMineLocation[ ubMineIndex ].sSectorY;
*psX = gMineStatus[ ubMineIndex ].sSectorX;
*psY = gMineStatus[ ubMineIndex ].sSectorY;
}
// get the index of the mine associated with this town
INT8 GetMineIndexForTown( INT8 bTownId )
{
UINT8 ubMineIndex = 0;
// given town id, send sector value of mine, a 0 means no mine for this town
for( ubMineIndex = 0; ubMineIndex < MAX_NUMBER_OF_MINES; ubMineIndex++ )
{
//if( gMineLocation[ ubMineIndex ].bAssociatedTown == bTownId )
if( gMineStatus[ ubMineIndex ].bAssociatedTown == bTownId )
{
return( ubMineIndex );
}
}
return( -1 );
}
// get the sector value for the mine associated with this town
INT16 GetMineSectorForTown( INT8 bTownId )
{
INT8 ubMineIndex;
INT16 sMineSector = -1;
// given town id, send sector value of mine, a 0 means no mine for this town
for( ubMineIndex = 0; ubMineIndex < MAX_NUMBER_OF_MINES; ubMineIndex++ )
{
//if( gMineLocation[ ubMineIndex ].bAssociatedTown == bTownId )
if( gMineStatus[ ubMineIndex ].bAssociatedTown == bTownId )
{
//sMineSector = gMineLocation[ ubMineIndex ].sSectorX + ( gMineLocation[ ubMineIndex ].sSectorY * MAP_WORLD_X );
sMineSector = CALCULATE_STRATEGIC_INDEX(gMineStatus[ ubMineIndex ].sSectorX, gMineStatus[ ubMineIndex ].sSectorY );
break;
}
}
// -1 returned if the town doesn't have a mine
return( sMineSector );
}
BOOLEAN IsThereAMineInThisSector( INT16 sX, INT16 sY )
{
UINT8 ubMineIndex;
// run through the list...if a mine here, great
for( ubMineIndex = 0; ubMineIndex < MAX_NUMBER_OF_MINES; ubMineIndex++ )
{
//if( ( gMineLocation[ ubMineIndex ].sSectorX == sX ) && ( gMineLocation[ ubMineIndex ].sSectorY == sY ) )
if( ( gMineStatus[ ubMineIndex ].sSectorX == sX ) && ( gMineStatus[ ubMineIndex ].sSectorY == sY ) )
{
return( TRUE );
}
}
return( FALSE );
}
BOOLEAN PlayerControlsMine(INT8 bMineIndex)
{
// a value of TRUE is from the enemy's point of view
//if (StrategicMap[( gMineLocation[ bMineIndex ].sSectorX ) + ( MAP_WORLD_X * ( gMineLocation[ bMineIndex ].sSectorY ) )].fEnemyControlled == TRUE )
if (StrategicMap[CALCULATE_STRATEGIC_INDEX( gMineStatus[bMineIndex].sSectorX, gMineStatus[bMineIndex].sSectorY )].fEnemyControlled == TRUE )
return(FALSE);
else
{
// player only controls the actual mine after he has made arrangements to do so with the head miner there
if (gMineStatus[ bMineIndex ].fSpokeToHeadMiner)
{
return(TRUE);
}
else
{
return(FALSE);
}
}
}
BOOLEAN SaveMineStatusToSaveGameFile( HWFILE hFile )
{
return g_luaMines.Save(hFile);
#if 0
UINT32 uiNumBytesWritten;
//Save the MineStatus
FileWrite( hFile, gMineStatus, sizeof( MINE_STATUS_TYPE ) * MAX_NUMBER_OF_MINES, &uiNumBytesWritten );
if( uiNumBytesWritten != sizeof( MINE_STATUS_TYPE ) * MAX_NUMBER_OF_MINES )
{
return( FALSE );
}
return( TRUE );
#endif
}
BOOLEAN LoadMineStatusFromSavedGameFile( HWFILE hFile )
{
return g_luaMines.Load(hFile);
#if 0
UINT32 uiNumBytesRead;
//Load the MineStatus
FileRead( hFile, gMineStatus, sizeof( MINE_STATUS_TYPE ) * MAX_NUMBER_OF_MINES, &uiNumBytesRead );
if( uiNumBytesRead != sizeof( MINE_STATUS_TYPE ) * MAX_NUMBER_OF_MINES )
{
return( FALSE );
}
return( TRUE );
#endif
}
void ShutOffMineProduction( INT8 bMineIndex )
{
Assert( ( bMineIndex >= 0 ) && ( bMineIndex < MAX_NUMBER_OF_MINES ) );
if ( !gMineStatus[ bMineIndex ].fShutDown )
{
gMineStatus[ bMineIndex ].fShutDown = TRUE;
//AddHistoryToPlayersLog( HISTORY_MINE_SHUTDOWN, gMineLocation[ bMineIndex ].bAssociatedTown, GetWorldTotalMin( ), gMineLocation[ bMineIndex ].sSectorX, gMineLocation[ bMineIndex ].sSectorY );
AddHistoryToPlayersLog( HISTORY_MINE_SHUTDOWN, gMineStatus[ bMineIndex ].bAssociatedTown, GetWorldTotalMin( ), gMineStatus[ bMineIndex ].sSectorX, gMineStatus[ bMineIndex ].sSectorY );
}
}
void RestartMineProduction( INT8 bMineIndex )
{
Assert( ( bMineIndex >= 0 ) && ( bMineIndex < MAX_NUMBER_OF_MINES ) );
if ( !gMineStatus[ bMineIndex ].fShutDownIsPermanent )
{
if ( gMineStatus[ bMineIndex ].fShutDown )
{
gMineStatus[ bMineIndex ].fShutDown = FALSE;
//AddHistoryToPlayersLog( HISTORY_MINE_REOPENED, gMineLocation[ bMineIndex ].bAssociatedTown, GetWorldTotalMin( ), gMineLocation[ bMineIndex ].sSectorX, gMineLocation[ bMineIndex ].sSectorY );
AddHistoryToPlayersLog( HISTORY_MINE_REOPENED, gMineStatus[ bMineIndex ].bAssociatedTown, GetWorldTotalMin( ), gMineStatus[ bMineIndex ].sSectorX, gMineStatus[ bMineIndex ].sSectorY );
}
}
}
void MineShutdownIsPermanent( INT8 bMineIndex )
{
Assert( ( bMineIndex >= 0 ) && ( bMineIndex < MAX_NUMBER_OF_MINES ) );
gMineStatus[ bMineIndex ].fShutDownIsPermanent = TRUE;
}
BOOLEAN IsMineShutDown( INT8 bMineIndex )
{
Assert( ( bMineIndex >= 0 ) && ( bMineIndex < MAX_NUMBER_OF_MINES ) );
return(gMineStatus[ bMineIndex ].fShutDown);
}
UINT8 GetHeadMinerIndexForMine( INT8 bMineIndex )
{
UINT8 ubMinerIndex = 0;
UINT16 usProfileId = 0;
Assert( ( bMineIndex >= 0 ) && ( bMineIndex < MAX_NUMBER_OF_MINES ) );
// loop through all head miners, checking which town they're associated with, looking for one that matches this mine
for (ubMinerIndex = 0; ubMinerIndex < NUM_HEAD_MINERS; ubMinerIndex++)
{
usProfileId = gHeadMinerData[ ubMinerIndex ].usProfileId;
//if (gMercProfiles[ usProfileId ].bTown == gMineLocation[ bMineIndex ].bAssociatedTown)
if (gMercProfiles[ usProfileId ].bTown == gMineStatus[ bMineIndex ].bAssociatedTown)
{
return(ubMinerIndex);
}
}
// not found - yack!
//Assert( FALSE );
//return( 0 );
// Do not assert but use an error code instead,
// as a mod might intentionally want to not have a head miner at every mine.
return -1;
}
//UINT16 GetHeadMinerProfileIdForMine( INT8 bMineIndex )
//{
// return(gHeadMinerData[ GetHeadMinerIndexForMine( bMineIndex ) ].usProfileId);
//}
void IssueHeadMinerQuote( INT8 bMineIndex, UINT8 ubQuoteType )
{
UINT8 ubHeadMinerIndex = 0;
UINT16 usHeadMinerProfileId = 0;
INT8 bQuoteNum = 0;
UINT8 ubFaceIndex = 0;
BOOLEAN fForceMapscreen = FALSE;
INT16 sXPos, sYPos;
Assert( ( bMineIndex >= 0 ) && ( bMineIndex < MAX_NUMBER_OF_MINES ) );
Assert( ubQuoteType < NUM_HEAD_MINER_STRATEGIC_QUOTES );
Assert( CheckFact( FACT_MINERS_PLACED, 0 ) );
ubHeadMinerIndex = GetHeadMinerIndexForMine( bMineIndex );
if (ubHeadMinerIndex == -1)
return;
usHeadMinerProfileId = gHeadMinerData[ ubHeadMinerIndex ].usProfileId;
// make sure the miner ain't dead
if (gMercProfiles[ usHeadMinerProfileId ].bLife < OKLIFE)
{
// debug message
ScreenMsg( MSG_FONT_RED, MSG_DEBUG, L"Head Miner #%s can't talk (quote #%d)", gMercProfiles[ usHeadMinerProfileId ].zNickname, ubQuoteType);
return;
}
bQuoteNum = gHeadMinerData[ ubHeadMinerIndex ].bQuoteNum[ ubQuoteType ];
//Assert( bQuoteNum != -1 );
if (bQuoteNum == -1)
return;
ubFaceIndex = ( UINT8 ) uiExternalStaticNPCFaces[ gHeadMinerData[ ubHeadMinerIndex ].ubExternalFaceIndex ];
// transition to mapscreen is not necessary for "creatures gone" quote - player is IN that mine, so he'll know
if ( ubQuoteType != HEAD_MINER_STRATEGIC_QUOTE_CREATURES_GONE )
{
fForceMapscreen = TRUE;
}
// decide where the miner's face and text box should be positioned in order to not obscure the mine he's in as it flashes
switch ( bMineIndex )
{
case MINE_GRUMM:
sXPos = DEFAULT_EXTERN_PANEL_X_POS;
sYPos = DEFAULT_EXTERN_PANEL_Y_POS;
break;
case MINE_CAMBRIA:
sXPos = DEFAULT_EXTERN_PANEL_X_POS;
sYPos = DEFAULT_EXTERN_PANEL_Y_POS;
break;
case MINE_ALMA:
sXPos = DEFAULT_EXTERN_PANEL_X_POS;
sYPos = DEFAULT_EXTERN_PANEL_Y_POS;
break;
case MINE_DRASSEN:
sXPos = DEFAULT_EXTERN_PANEL_X_POS;
sYPos = 135;
break;
case MINE_CHITZENA:
sXPos = DEFAULT_EXTERN_PANEL_X_POS;
sYPos = 117;
break;
// there's no head miner in San Mona, this is an error!
case MINE_SAN_MONA:
default:
//Assert( FALSE );
sXPos = DEFAULT_EXTERN_PANEL_X_POS;
sYPos = DEFAULT_EXTERN_PANEL_Y_POS;
break;
}
SetExternMapscreenSpeechPanelXY( sXPos, sYPos );
// cause this quote to come up for this profile id and an indicator to flash over the mine sector
//HandleMinerEvent( gHeadMinerData[ ubHeadMinerIndex ].ubExternalFace, gMineLocation[ bMineIndex ].sSectorX, gMineLocation[ bMineIndex ].sSectorY, (INT16) bQuoteNum, fForceMapscreen );
//HandleMinerEvent( gHeadMinerData[ ubHeadMinerIndex ].ubExternalFace, gMineStatus[ bMineIndex ].sSectorX, gMineStatus[ bMineIndex ].sSectorY, (INT16) bQuoteNum, fForceMapscreen );
HandleMinerEvent( ubHeadMinerIndex, gMineStatus[ bMineIndex ].sSectorX, gMineStatus[ bMineIndex ].sSectorY, (INT16) bQuoteNum, fForceMapscreen );
// stop time compression with any miner quote - these are important events.
StopTimeCompression();
}
UINT8 GetHeadMinersMineIndex( UINT8 ubMinerProfileId)
{
UINT8 ubMineIndex;
// find which mine this guy represents
for( ubMineIndex = 0; ubMineIndex < MAX_NUMBER_OF_MINES; ubMineIndex++ )
{
//if (gMineLocation[ ubMineIndex ].bAssociatedTown == gMercProfiles[ ubMinerProfileId ].bTown)
if (gMineStatus[ ubMineIndex ].bAssociatedTown == gMercProfiles[ ubMinerProfileId ].bTown)
{
return(ubMineIndex);
}
}
// not found! Illegal profile id receieved or something is very wrong
Assert(FALSE);
return( 0 );
}
void PlayerSpokeToHeadMiner( UINT8 ubMinerProfileId )
{
UINT8 ubMineIndex;
ubMineIndex = GetHeadMinersMineIndex( ubMinerProfileId );
// if this is our first time set a history fact
if( gMineStatus[ ubMineIndex ].fSpokeToHeadMiner == FALSE )
{
//AddHistoryToPlayersLog( HISTORY_TALKED_TO_MINER, gMineLocation[ ubMineIndex ].bAssociatedTown, GetWorldTotalMin( ), gMineLocation[ ubMineIndex ].sSectorX, gMineLocation[ ubMineIndex ].sSectorY );
AddHistoryToPlayersLog( HISTORY_TALKED_TO_MINER, gMineStatus[ ubMineIndex ].bAssociatedTown, GetWorldTotalMin( ), gMineStatus[ ubMineIndex ].sSectorX, gMineStatus[ ubMineIndex ].sSectorY );
gMineStatus[ ubMineIndex ].fSpokeToHeadMiner = TRUE;
}
}
BOOLEAN IsHisMineRunningOut( UINT8 ubMinerProfileId )
{
UINT8 ubMineIndex;
ubMineIndex = GetHeadMinersMineIndex( ubMinerProfileId );
return(gMineStatus[ ubMineIndex ].fRunningOut);
}
BOOLEAN IsHisMineEmpty( UINT8 ubMinerProfileId )
{
UINT8 ubMineIndex;
ubMineIndex = GetHeadMinersMineIndex( ubMinerProfileId );
return(gMineStatus[ ubMineIndex ].fEmpty);
}
BOOLEAN IsHisMineDisloyal( UINT8 ubMinerProfileId )
{
UINT8 ubMineIndex;
ubMineIndex = GetHeadMinersMineIndex( ubMinerProfileId );
//if (gTownLoyalty[ gMineLocation[ ubMineIndex ].bAssociatedTown ].ubRating < LOW_MINE_LOYALTY_THRESHOLD)
if (gTownLoyalty[ gMineStatus[ ubMineIndex ].bAssociatedTown ].ubRating < LOW_MINE_LOYALTY_THRESHOLD)
{
// pretty disloyal
return(TRUE);
}
else
{
// pretty loyal
return(FALSE);
}
}
BOOLEAN IsHisMineInfested( UINT8 ubMinerProfileId )
{
UINT8 ubMineIndex;
ubMineIndex = GetHeadMinersMineIndex( ubMinerProfileId );
return(!MineClearOfMonsters( ubMineIndex ));
}
BOOLEAN IsHisMineLostAndRegained( UINT8 ubMinerProfileId )
{
UINT8 ubMineIndex;
ubMineIndex = GetHeadMinersMineIndex( ubMinerProfileId );
if (PlayerControlsMine(ubMineIndex) && gMineStatus[ ubMineIndex ].fQueenRetookProducingMine)
{
return(TRUE);
}
else
{
return(FALSE);
}
}
void ResetQueenRetookMine( UINT8 ubMinerProfileId )
{
UINT8 ubMineIndex;
ubMineIndex = GetHeadMinersMineIndex( ubMinerProfileId );
gMineStatus[ ubMineIndex ].fQueenRetookProducingMine = FALSE;
}
BOOLEAN IsHisMineAtMaxProduction( UINT8 ubMinerProfileId )
{
UINT8 ubMineIndex;
ubMineIndex = GetHeadMinersMineIndex( ubMinerProfileId );
if (GetAvailableWorkForceForMineForPlayer( ubMineIndex ) == 100)
{
// loyalty is 100% and control is 100%
return(TRUE);
}
else
{
// something not quite perfect yet
return(FALSE);
}
}
void QueenHasRegainedMineSector(INT8 bMineIndex)
{
Assert( ( bMineIndex >= 0 ) && ( bMineIndex < MAX_NUMBER_OF_MINES ) );
if (gMineStatus[ bMineIndex ].fMineHasProducedForPlayer)
{
gMineStatus[ bMineIndex ].fQueenRetookProducingMine = TRUE;
}
}
BOOLEAN HasAnyMineBeenAttackedByMonsters(void)
{
UINT8 ubMineIndex;
// find which mine this guy represents
for( ubMineIndex = 0; ubMineIndex < MAX_NUMBER_OF_MINES; ubMineIndex++ )
{
if (!MineClearOfMonsters( ubMineIndex ) || gMineStatus[ ubMineIndex ].fPrevInvadedByMonsters)
{
return(TRUE);
}
}
return(FALSE);
}
void PlayerAttackedHeadMiner( UINT8 ubMinerProfileId )
{
UINT8 ubMineIndex;
INT8 bTownId;
// get the index of his mine
ubMineIndex = GetHeadMinersMineIndex( ubMinerProfileId );
// if it's the first time he's been attacked
if ( gMineStatus[ ubMineIndex ].fAttackedHeadMiner == FALSE )
{
// shut off production at his mine (Permanently!)
ShutOffMineProduction( ubMineIndex );
MineShutdownIsPermanent( ubMineIndex );
// get the index of his town
bTownId = GetTownAssociatedWithMine( ubMineIndex );
// penalize associated town's loyalty
DecrementTownLoyalty( bTownId, LOYALTY_PENALTY_HEAD_MINER_ATTACKED );
// don't allow this more than once
gMineStatus[ ubMineIndex ].fAttackedHeadMiner = TRUE;
}
}
BOOLEAN HasHisMineBeenProducingForPlayerForSomeTime( UINT8 ubMinerProfileId )
{
UINT8 ubMineIndex;
ubMineIndex = GetHeadMinersMineIndex( ubMinerProfileId );
if ( gMineStatus[ ubMineIndex ].fMineHasProducedForPlayer &&
( ( GetWorldTotalMin() - gMineStatus[ ubMineIndex ].uiTimePlayerProductionStarted ) >= ( 24 * 60 ) ) )
{
return ( TRUE );
}
return( FALSE );
}
// get the id of the mine for this sector x,y,z...-1 is invalid
INT8 GetIdOfMineForSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ )
{
INT8 bMineIndex = -1;
//INT16 sSectorValue;
// are we even on the right level?
if (bSectorZ < MINIMUM_VALID_Z_COORDINATE || bSectorZ > MAXIMUM_VALID_Z_COORDINATE)
{
// nope
return( -1 );
}
// now get the sectorvalue
//sSectorValue = SECTOR( sSectorX, sSectorY );
// support surface
if( bSectorZ == 0 )
{
bMineIndex = GetMineIndexForSector( sSectorX, sSectorY );
}
#if 0
// handle for first level
else if( bSectorZ == 1 )
{
switch( sSectorValue )
{
// grumm
case( SEC_H3 ):
case( SEC_I3 ):
bMineIndex = MINE_GRUMM;
break;
// cambria
case( SEC_H8 ):
case( SEC_H9 ):
bMineIndex = MINE_CAMBRIA;
break;
// alma
case( SEC_I14 ):
case( SEC_J14 ):
bMineIndex = MINE_ALMA;
break;
// drassen
case( SEC_D13 ):
case( SEC_E13 ):
bMineIndex = MINE_DRASSEN;
break;
// chitzena
case( SEC_B2 ):
bMineIndex = MINE_CHITZENA;
break;
// san mona
case( SEC_D4 ):
case( SEC_D5 ):
bMineIndex = MINE_SAN_MONA;
break;
}
}
else
{
// level 2
switch( sSectorValue )
{
case( SEC_I3 ):
case( SEC_H3 ):
case( SEC_H4 ):
bMineIndex = MINE_GRUMM;
break;
}
}
#endif
for (std::vector<AssociatedMineSector>::iterator it = associatedMineSectors.begin();
it != associatedMineSectors.end(); ++it)
{
if (it->x == sSectorX && it->y == sSectorY && bSectorZ == it->z)
{
return it->mineID;
}
}
return( bMineIndex ); // == -1
}
// use this for miner (civilian) quotes when *underground* in a mine
//BOOLEAN PlayerForgotToTakeOverMine( UINT8 ubMineIndex )
//{
// MINE_STATUS_TYPE *pMineStatus;
//
//
// Assert( ( ubMineIndex >= 0 ) && ( ubMineIndex < MAX_NUMBER_OF_MINES ) );
//
// pMineStatus = &(gMineStatus[ ubMineIndex ]);
//
// // mine surface sector is player controlled
// // mine not empty
// // player hasn't spoken to the head miner, but hasn't attacked him either
// // miner is alive
// //if ( (StrategicMap[( gMineLocation[ ubMineIndex ].sSectorX ) + ( MAP_WORLD_X * ( gMineLocation[ ubMineIndex ].sSectorY ) )].fEnemyControlled == FALSE ) &&
// if ( (StrategicMap[( gMineStatus[ ubMineIndex ].sSectorX ) + ( MAP_WORLD_X * ( gMineStatus[ ubMineIndex ].sSectorY ) )].fEnemyControlled == FALSE ) &&
// ( !pMineStatus->fEmpty ) &&
// ( !pMineStatus->fSpokeToHeadMiner ) &&
// ( !pMineStatus->fAttackedHeadMiner ) &&
// ( gMercProfiles[ GetHeadMinerProfileIdForMine( ubMineIndex ) ].bLife > 0 ) )
// {
// return( TRUE );
// }
//
// return( FALSE );
//}
// use this to determine whether or not to place miners into a underground mine level
BOOLEAN AreThereMinersInsideThisMine( UINT8 ubMineIndex )
{
MINE_STATUS_TYPE *pMineStatus;
Assert(ubMineIndex < MAX_NUMBER_OF_MINES);
pMineStatus = &(gMineStatus[ ubMineIndex ]);
// mine not empty
// mine clear of any monsters
// the "shutdown permanently" flag is only used for the player never receiving the income - miners will keep mining
if ( ( !pMineStatus->fEmpty ) && MineClearOfMonsters( ubMineIndex ) )
{
return( TRUE );
}
return( FALSE );
}
// returns whether or not we've spoken to the head miner of a particular mine
BOOLEAN SpokenToHeadMiner( UINT8 ubMineIndex )
{
return( gMineStatus[ ubMineIndex ].fSpokeToHeadMiner );
}