// ALL changes of control to enemy must be funneled through here! BOOLEAN SetThisSectorAsEnemyControlled( INT16 sMapX, INT16 sMapY, INT8 bMapZ, BOOLEAN fContested ) { UINT16 usMapSector = 0; BOOLEAN fWasPlayerControlled = FALSE; INT8 bTownId = 0; UINT8 ubTheftChance; UINT8 ubSectorID; //KM : August 6, 1999 Patch fix // This check was added because this function gets called when player mercs retreat from an unresolved // battle between militia and enemies. It will get called again AFTER autoresolve is finished. if( gfAutomaticallyStartAutoResolve ) { return( FALSE ); } if( bMapZ == 0 ) { usMapSector = sMapX + ( sMapY * MAP_WORLD_X ); fWasPlayerControlled = !StrategicMap[ usMapSector ].fEnemyControlled; StrategicMap[ usMapSector ].fEnemyControlled = TRUE; // if player lost control to the enemy if ( fWasPlayerControlled ) { if( PlayerMercsInSector( (UINT8)sMapX, (UINT8)sMapY, (UINT8)bMapZ ) ) { //too premature: Player mercs still in sector. return FALSE; } // check if there's a town in the sector bTownId = StrategicMap[ usMapSector ].bNameId; SectorInfo[ SECTOR( sMapX, sMapY ) ].fPlayer[ bMapZ ] = FALSE; // and it's a town if ((bTownId >= FIRST_TOWN) && (bTownId < NUM_TOWNS)) { ubSectorID = (UINT8)SECTOR( sMapX, sMapY ); if( !bMapZ && ubSectorID != SEC_J9 && ubSectorID != SEC_K4 ) { HandleMoraleEvent( NULL, MORALE_TOWN_LOST, sMapX, sMapY, bMapZ ); HandleGlobalLoyaltyEvent( GLOBAL_LOYALTY_LOSE_TOWN_SECTOR, sMapX, sMapY, bMapZ ); CheckIfEntireTownHasBeenLost( bTownId, sMapX, sMapY ); } } // if the sector has a mine which is still worth something if ( IsThereAMineInThisSector( sMapX, sMapY ) ) { // if it isn't empty if ( GetTotalLeftInMine( GetMineIndexForSector( sMapX, sMapY ) ) > 0) { QueenHasRegainedMineSector(GetMineIndexForSector (sMapX, sMapY)); HandleMoraleEvent( NULL, MORALE_MINE_LOST, sMapX, sMapY, bMapZ ); HandleGlobalLoyaltyEvent( GLOBAL_LOYALTY_LOSE_MINE, sMapX, sMapY, bMapZ ); } } // if it's a SAM site sector if( IsThisSectorASAMSector( sMapX, sMapY, bMapZ ) ) { HandleMoraleEvent( NULL, MORALE_SAM_SITE_LOST, sMapX, sMapY, bMapZ ); HandleGlobalLoyaltyEvent( GLOBAL_LOYALTY_LOSE_SAM, sMapX, sMapY, bMapZ ); } // if it's a helicopter refueling site sector if( IsRefuelSiteInSector( sMapX, sMapY) ) { UpdateRefuelSiteAvailability( ); } // ARM: this must be AFTER all resulting loyalty effects are resolved, or reduced mine income shown won't be accurate NotifyPlayerWhenEnemyTakesControlOfImportantSector( sMapX, sMapY, 0, fContested ); } // NOTE: Stealing is intentionally OUTSIDE the fWasPlayerControlled branch. This function gets called if new // enemy reinforcements arrive, and they deserve another crack at stealing what the first group missed! :-) // stealing should fail anyway 'cause there shouldn't be a temp file for unvisited sectors, but let's check anyway if ( GetSectorFlagStatus( sMapX, sMapY, ( UINT8 ) bMapZ, SF_ALREADY_VISITED ) == TRUE ) { // enemies can steal items left lying about (random chance). The more there are, the more they take! ubTheftChance = 5 * NumEnemiesInAnySector( sMapX, sMapY, bMapZ ); // max 90%, some stuff may just simply not get found if (ubTheftChance > 90 ) { ubTheftChance = 90; } RemoveRandomItemsInSector( sMapX, sMapY, bMapZ, ubTheftChance ); } // don't touch fPlayer flag for a surface sector lost to the enemies! // just because player has lost the sector doesn't mean he realizes it - that's up to our caller to decide! } else { // underground sector control is always up to date, because we don't track control down there SectorInfo[ SECTOR( sMapX, sMapY ) ].fPlayer[ bMapZ ] = FALSE; } //KM : Aug 11, 1999 -- Patch fix: Relocated this check so it gets called everytime a sector changes hands, // even if the sector isn't a SAM site. There is a bug _somewhere_ that fails to update the airspace, // even though the player controls it. UpdateAirspaceControl( ); // redraw map/income if in mapscreen fMapPanelDirty = TRUE; fMapScreenBottomDirty = TRUE; return fWasPlayerControlled; }
// adds text to mine info box void AddTextToMineBox( void ) { UINT8 ubMineIndex; UINT8 ubTown; UINT32 hStringHandle; CHAR16 wString[ 64 ]; ubMineIndex = GetMineIndexForSector( bCurrentTownMineSectorX, bCurrentTownMineSectorY ); // name of town followed by "mine" //swprintf( wString, L"%s %s", pTownNames[ GetTownAssociatedWithMine( ubMineIndex ) ], pwMineStrings[ 0 ] ); swprintf( wString, L"%s %s", pTownNames[ GetTownAssociatedWithMine( ubMineIndex ) ], MineralsName[gMineStatus[ubMineIndex].ubMineType].sType ); AddMonoString( &hStringHandle, wString ); // blank line AddMonoString( &hStringHandle, L"" ); // sector AddSectorToBox(); // mine status swprintf( wString, L"%s:", pwMineStrings[ 9 ]); AddMonoString( &hStringHandle, wString ); // check if mine is empty (abandoned) or running out if (gMineStatus[ ubMineIndex ].fEmpty) { // abandonded wcscpy( wString, pwMineStrings[ 5 ] ); } else if (gMineStatus[ ubMineIndex ].fShutDown) { // shut down wcscpy( wString, pwMineStrings[ 6 ] ); } else if (gMineStatus[ ubMineIndex ].fRunningOut) { // running out wcscpy( wString, pwMineStrings[ 7 ] ); } else { // producing wcscpy( wString, pwMineStrings[ 8 ] ); } AddSecondColumnMonoString( &hStringHandle, wString ); // if still producing if (!gMineStatus[ ubMineIndex ].fEmpty) { // current production swprintf( wString, L"%s:", pwMineStrings[ 3 ]); AddMonoString( &hStringHandle, wString ); swprintf( wString, L"%d", PredictDailyIncomeFromAMine( ubMineIndex, TRUE ) ); InsertCommasForDollarFigure( wString ); InsertDollarSignInToString( wString ); AddSecondColumnMonoString( &hStringHandle, wString ); // potential production swprintf( wString, L"%s:", pwMineStrings[ 4 ]); AddMonoString( &hStringHandle, wString ); swprintf( wString, L"%d", GetMaxDailyRemovalFromMine( ubMineIndex ) ); InsertCommasForDollarFigure( wString ); InsertDollarSignInToString( wString ); AddSecondColumnMonoString( &hStringHandle, wString ); // if potential is not nil if (GetMaxPeriodicRemovalFromMine(ubMineIndex) > 0) { // production rate (current production as a percentage of potential production) swprintf( wString, L"%s:", pwMineStrings[ 10 ]); AddMonoString( &hStringHandle, wString ); swprintf( wString, L"%d%%%%", (PredictDailyIncomeFromAMine(ubMineIndex, TRUE) * 100 ) / GetMaxDailyRemovalFromMine(ubMineIndex) ); AddSecondColumnMonoString( &hStringHandle, wString ); } // town control percentage swprintf( wString, L"%s:", pwMineStrings[ 12 ]); AddMonoString( &hStringHandle, wString ); //swprintf( wString, L"%d%%%%", (GetTownSectorsUnderControl( gMineLocation[ ubMineIndex ].bAssociatedTown ) * 100) / GetTownSectorSize( gMineLocation[ ubMineIndex ].bAssociatedTown )); swprintf( wString, L"%d%%%%", (GetTownSectorsUnderControl( gMineStatus[ ubMineIndex ].bAssociatedTown ) * 100) / GetTownSectorSize( gMineStatus[ ubMineIndex ].bAssociatedTown )); AddSecondColumnMonoString( &hStringHandle, wString ); //ubTown = gMineLocation[ ubMineIndex ].bAssociatedTown; ubTown = gMineStatus[ ubMineIndex ].bAssociatedTown; if( gTownLoyalty[ ubTown ].fStarted && gfTownUsesLoyalty[ ubTown ]) { // town loyalty percentage swprintf( wString, L"%s:", pwMineStrings[ 13 ]); AddMonoString( &hStringHandle, wString ); //swprintf( wString, L"%d%%%%", gTownLoyalty[ gMineLocation[ ubMineIndex ].bAssociatedTown ].ubRating); swprintf( wString, L"%d%%%%", gTownLoyalty[ gMineStatus[ ubMineIndex ].bAssociatedTown ].ubRating); AddSecondColumnMonoString( &hStringHandle, wString ); } /* gradual monster infestation concept was ditched, now simply IN PRODUCTION or SHUT DOWN // percentage of miners working swprintf( wString, L"%s:", pwMineStrings[ 14 ]); AddMonoString( &hStringHandle, wString ); swprintf( wString, L"%d%%%%", gubMonsterMineInfestation[ gMineStatus[ ubMineIndex ].bMonsters ]); AddSecondColumnMonoString( &hStringHandle, wString ); */ // ore type (silver/gold swprintf( wString, L"%s:", pwMineStrings[ 11 ]); AddMonoString( &hStringHandle, wString ); AddSecondColumnMonoString( &hStringHandle, MineralsName[gMineStatus[ubMineIndex].ubMineType].sMinerals ); //AddSecondColumnMonoString( &hStringHandle, (gMineStatus[ubMineIndex].ubMineType == SILVER_MINE) ? pwMineStrings[ 1 ] : pwMineStrings[ 2 ] ); } #ifdef _DEBUG // dollar amount remaining in mine wcscpy( wString, L"Remaining (DEBUG):"); AddMonoString( &hStringHandle, wString ); swprintf( wString, L"%d", GetTotalLeftInMine( ubMineIndex ) ); InsertCommasForDollarFigure( wString ); InsertDollarSignInToString( wString ); AddSecondColumnMonoString( &hStringHandle, wString ); #endif }
// ALL changes of control to player must be funneled through here! BOOLEAN SetThisSectorAsPlayerControlled( INT16 sMapX, INT16 sMapY, INT8 bMapZ, BOOLEAN fContested ) { // NOTE: MapSector must be 16-bit, cause MAX_WORLD_X is actually 18, so the sector numbers exceed 256 although we use only 16x16 UINT16 usMapSector = 0; BOOLEAN fWasEnemyControlled = FALSE; INT8 bTownId = 0; UINT8 ubSectorID; if( AreInMeanwhile( ) ) { return FALSE; } if( bMapZ == 0 ) { usMapSector = sMapX + ( sMapY * MAP_WORLD_X ); /* // if enemies formerly controlled this sector if (StrategicMap[ usMapSector ].fEnemyControlled) { // remember that the enemies have lost it StrategicMap[ usMapSector ].fLostControlAtSomeTime = TRUE; } */ if( NumHostilesInSector( sMapX, sMapY, bMapZ ) ) { //too premature: enemies still in sector. return FALSE; } // check if we ever grabbed drassen airport, if so, set fact we can go to BR's if( ( sMapX == BOBBYR_SHIPPING_DEST_SECTOR_X ) && ( sMapY == BOBBYR_SHIPPING_DEST_SECTOR_Y ) ) { LaptopSaveInfo.fBobbyRSiteCanBeAccessed = TRUE; //If the player has been to Bobbyr when it was down, and we havent already sent email, send him an email if( LaptopSaveInfo.ubHaveBeenToBobbyRaysAtLeastOnceWhileUnderConstruction == BOBBYR_BEEN_TO_SITE_ONCE && LaptopSaveInfo.ubHaveBeenToBobbyRaysAtLeastOnceWhileUnderConstruction != BOBBYR_ALREADY_SENT_EMAIL ) { AddEmail( BOBBYR_NOW_OPEN, BOBBYR_NOW_OPEN_LENGTH, BOBBY_R, GetWorldTotalMin()); LaptopSaveInfo.ubHaveBeenToBobbyRaysAtLeastOnceWhileUnderConstruction = BOBBYR_ALREADY_SENT_EMAIL; } } fWasEnemyControlled = StrategicMap[ usMapSector ].fEnemyControlled; StrategicMap[ usMapSector ].fEnemyControlled = FALSE; SectorInfo[ SECTOR( sMapX, sMapY ) ].fPlayer[ bMapZ ] = TRUE; bTownId = StrategicMap[ usMapSector ].bNameId; // check if there's a town in the sector if ((bTownId >= FIRST_TOWN) && (bTownId < NUM_TOWNS)) { // yes, start tracking (& displaying) this town's loyalty if not already doing so StartTownLoyaltyIfFirstTime( bTownId ); } // if player took control away from enemy if( fWasEnemyControlled && fContested ) { // and it's a town if ((bTownId >= FIRST_TOWN) && (bTownId < NUM_TOWNS)) { // don't do these for takeovers of Omerta sectors at the beginning of the game if ((bTownId != OMERTA) || (GetWorldDay() != 1)) { ubSectorID = (UINT8)SECTOR( sMapX, sMapY ); if( !bMapZ && ubSectorID != SEC_J9 && ubSectorID != SEC_K4 ) { HandleMoraleEvent( NULL, MORALE_TOWN_LIBERATED, sMapX, sMapY, bMapZ ); HandleGlobalLoyaltyEvent( GLOBAL_LOYALTY_GAIN_TOWN_SECTOR, sMapX, sMapY, bMapZ ); // liberation by definition requires that the place was enemy controlled in the first place CheckIfEntireTownHasBeenLiberated( bTownId, sMapX, sMapY ); } } } // if it's a mine that's still worth something if ( IsThereAMineInThisSector( sMapX, sMapY ) ) { if ( GetTotalLeftInMine( GetMineIndexForSector( sMapX, sMapY ) ) > 0) { HandleMoraleEvent( NULL, MORALE_MINE_LIBERATED, sMapX, sMapY, bMapZ ); HandleGlobalLoyaltyEvent( GLOBAL_LOYALTY_GAIN_MINE, sMapX, sMapY, bMapZ ); } } // if it's a SAM site sector if( IsThisSectorASAMSector( sMapX, sMapY, bMapZ ) ) { if ( 1 /*!GetSectorFlagStatus( sMapX, sMapY, bMapZ, SF_SECTOR_HAS_BEEN_LIBERATED_ONCE ) */) { // SAM site liberated for first time, schedule meanwhile HandleMeanWhileEventPostingForSAMLiberation( GetSAMIdFromSector( sMapX, sMapY, bMapZ ) ); } HandleMoraleEvent( NULL, MORALE_SAM_SITE_LIBERATED, sMapX, sMapY, bMapZ ); HandleGlobalLoyaltyEvent( GLOBAL_LOYALTY_GAIN_SAM, sMapX, sMapY, bMapZ ); // if Skyrider has been delivered to chopper, and already mentioned Drassen SAM site, but not used this quote yet if ( IsHelicopterPilotAvailable() && ( guiHelicopterSkyriderTalkState >= 1 ) && ( !gfSkyriderSaidCongratsOnTakingSAM ) ) { SkyRiderTalk( SAM_SITE_TAKEN ); gfSkyriderSaidCongratsOnTakingSAM = TRUE; } if ( !SectorInfo[ SECTOR( sMapX, sMapY ) ].fSurfaceWasEverPlayerControlled ) { // grant grace period if ( gGameOptions.ubDifficultyLevel >= DIF_LEVEL_HARD ) { UpdateLastDayOfPlayerActivity( ( UINT16 ) ( GetWorldDay() + 2 ) ); } else { UpdateLastDayOfPlayerActivity( ( UINT16 ) ( GetWorldDay() + 1 ) ); } } } // if it's a helicopter refueling site sector if( IsRefuelSiteInSector( sMapX, sMapY) ) { UpdateRefuelSiteAvailability( ); } // SetSectorFlag( sMapX, sMapY, bMapZ, SF_SECTOR_HAS_BEEN_LIBERATED_ONCE ); if ( bMapZ == 0 && ( ( sMapY == MAP_ROW_M && (sMapX >= 2 && sMapX <= 6) ) || sMapY == MAP_ROW_N && sMapX == 6) ) { HandleOutskirtsOfMedunaMeanwhileScene(); } } if( fContested ) { StrategicHandleQueenLosingControlOfSector( (UINT8)sMapX, (UINT8)sMapY, (UINT8)bMapZ ); } } else { if( sMapX == 3 && sMapY == 16 && bMapZ == 1 ) { //Basement sector (P3_b1) gfUseAlternateQueenPosition = TRUE; } } // also set fact the player knows they own it SectorInfo[ SECTOR( sMapX, sMapY ) ].fPlayer[ bMapZ ] = TRUE; if ( bMapZ == 0 ) { SectorInfo[ SECTOR( sMapX, sMapY ) ].fSurfaceWasEverPlayerControlled = TRUE; } //KM : Aug 11, 1999 -- Patch fix: Relocated this check so it gets called everytime a sector changes hands, // even if the sector isn't a SAM site. There is a bug _somewhere_ that fails to update the airspace, // even though the player controls it. UpdateAirspaceControl( ); // redraw map/income if in mapscreen fMapPanelDirty = TRUE; fMapScreenBottomDirty = TRUE; return fWasEnemyControlled; }
// gte 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 < 0 ) && ( bSectorZ > 2 ) ) { // nope return( -1 ); } // now get the sectorvalue sSectorValue = SECTOR( sSectorX, sSectorY ); // support surface if( bSectorZ == 0 ) { bMineIndex = GetMineIndexForSector( sSectorX, sSectorY ); } // 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; } } return( bMineIndex ); }