New feature: SAM site cover can now overlap, and SAM sites can be hacked to lower their radius. For more info, see http://thepit.ja-galaxy-forum.com/index.php?t=msg&th=23211&goto=347188&#msg_347188

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@8309 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
Flugente
2016-10-05 22:22:50 +00:00
parent 8523a1dead
commit 258e9c24a0
27 changed files with 554 additions and 319 deletions
+114 -37
View File
@@ -238,7 +238,7 @@ INT8 gbMercIsNewInThisSector[MAX_NUM_SOLDIERS];
BOOLEAN localizedMapTextOnly;
UINT8 ubSAMControlledSectors[MAP_WORLD_Y][MAP_WORLD_X];// = {
UINT32 ubSAMControlledSectors[MAP_WORLD_Y][MAP_WORLD_X];// = {
// 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
//
@@ -1973,7 +1973,8 @@ void InitializeSAMSites( void )
for ( UINT32 cnt = 0; cnt < NUMBER_OF_SAMS; ++cnt )
{
StrategicMap[gpSamSectorX[cnt] + (MAP_WORLD_X * gpSamSectorY[cnt])].bSAMCondition = 100;
};
StrategicMap[gpSamSectorX[cnt] + (MAP_WORLD_X * gpSamSectorY[cnt])].sSamHackStatus = 100;
}
// Flugente, bizarrely enough, this structure is not NULLED when starting a new campaign. For now, we NULL the flagmask to clear at least that
for ( INT32 cnt = 0; cnt < MAP_WORLD_X*MAP_WORLD_Y; ++cnt )
@@ -5147,6 +5148,15 @@ INT8 GetSAMIdFromSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ )
return(-1);
}
void SetSamHackStatus( INT16 sSectorX, INT16 sSectorY, INT8 sStatus )
{
if ( IsThisSectorASAMSector( sSectorX, sSectorY, 0 ) )
{
StrategicMap[CALCULATE_STRATEGIC_INDEX( sSectorX, sSectorY )].sSamHackStatus = sStatus;
UpdateAirspaceControl();
}
}
BOOLEAN CanGoToTacticalInSector( INT16 sX, INT16 sY, UINT8 ubZ )
{
@@ -5222,47 +5232,40 @@ INT32 SAMSitesUnderPlayerControl( INT16 sX, INT16 sY )
void UpdateAirspaceControl( void )
{
UINT8 ubControllingSAM;
StrategicMapElement *pSAMStrategicMap = NULL;
for ( INT32 iCounterA = 1; iCounterA < (INT32)(MAP_WORLD_X - 1); ++iCounterA )
{
for ( INT32 iCounterB = 1; iCounterB < (INT32)(MAP_WORLD_Y - 1); ++iCounterB )
{
StrategicMap[CALCULATE_STRATEGIC_INDEX( iCounterA, iCounterB )].usAirType = 0;
// if networked, disable SAM airspace restrictions...
if ( is_networked )
{
StrategicMap[CALCULATE_STRATEGIC_INDEX( iCounterA, iCounterB )].usAirType = AIRSPACE_ENEMY_INACTIVE;
continue;
}
// IMPORTANT: B and A are reverse here, since the table is stored transposed
ubControllingSAM = ubSAMControlledSectors[iCounterB][iCounterA];
if ( ubControllingSAM >= 1 && ubControllingSAM <= NUMBER_OF_SAMS )
for ( int samcnt = 0; samcnt < NUMBER_OF_SAMS; ++samcnt )
{
pSAMStrategicMap = &(StrategicMap[SECTOR_INFO_TO_STRATEGIC_INDEX( pSamList[ubControllingSAM - 1] )]);
BOOLEAN samworking = FALSE;
if ( DoesSamCoverSector( samcnt, SECTOR( iCounterA, iCounterB ), &samworking ) )
{
if ( samworking )
{
pSAMStrategicMap = &(StrategicMap[SECTOR_INFO_TO_STRATEGIC_INDEX( pSamList[samcnt] )]);
// different status depending on who controls the SAM sector, and whether the SAM is operational
if ( pSAMStrategicMap->fEnemyControlled )
{
if ( pSAMStrategicMap->bSAMCondition >= MIN_CONDITION_FOR_SAM_SITE_TO_WORK )
StrategicMap[CALCULATE_STRATEGIC_INDEX( iCounterA, iCounterB )].usAirType = AIRSPACE_ENEMY_ACTIVE;
else
StrategicMap[CALCULATE_STRATEGIC_INDEX( iCounterA, iCounterB )].usAirType = AIRSPACE_ENEMY_INACTIVE;
// different status depending on who controls the SAM sector, and whether the SAM is operational
if ( pSAMStrategicMap->fEnemyControlled )
{
StrategicMap[CALCULATE_STRATEGIC_INDEX( iCounterA, iCounterB )].usAirType |= AIRSPACE_ENEMY_ACTIVE;
}
else
{
StrategicMap[CALCULATE_STRATEGIC_INDEX( iCounterA, iCounterB )].usAirType |= AIRSPACE_PLAYER_ACTIVE;
}
}
}
else
{
if ( pSAMStrategicMap->bSAMCondition >= MIN_CONDITION_FOR_SAM_SITE_TO_WORK )
StrategicMap[CALCULATE_STRATEGIC_INDEX( iCounterA, iCounterB )].usAirType = AIRSPACE_PLAYER_ACTIVE;
else
StrategicMap[CALCULATE_STRATEGIC_INDEX( iCounterA, iCounterB )].usAirType = AIRSPACE_PLAYER_INACTIVE;
}
}
else
{
// no controlling SAM site
StrategicMap[CALCULATE_STRATEGIC_INDEX( iCounterA, iCounterB )].usAirType = AIRSPACE_ENEMY_INACTIVE;
}
}
}
@@ -5270,7 +5273,7 @@ void UpdateAirspaceControl( void )
// check if currently selected arrival sector still has secure airspace
// if it's not enemy air controlled
if ( StrategicMap[CALCULATE_STRATEGIC_INDEX( gsMercArriveSectorX, gsMercArriveSectorY )].usAirType == AIRSPACE_ENEMY_ACTIVE )
if ( StrategicMap[CALCULATE_STRATEGIC_INDEX( gsMercArriveSectorX, gsMercArriveSectorY )].usAirType & AIRSPACE_ENEMY_ACTIVE )
{
// NOPE!
CHAR16 sMsgString[256], sMsgSubString1[64], sMsgSubString2[64];
@@ -5280,7 +5283,7 @@ void UpdateAirspaceControl( void )
// move the landing zone over to Omerta
// HEADROCK HAM 3.5: Externalized coordinates
if ( StrategicMap[CALCULATE_STRATEGIC_INDEX( gGameExternalOptions.ubDefaultArrivalSectorX, gGameExternalOptions.ubDefaultArrivalSectorY )].usAirType != AIRSPACE_ENEMY_ACTIVE )
if ( !(StrategicMap[CALCULATE_STRATEGIC_INDEX( gGameExternalOptions.ubDefaultArrivalSectorX, gGameExternalOptions.ubDefaultArrivalSectorY )].usAirType & AIRSPACE_ENEMY_ACTIVE) )
{
gsMercArriveSectorX = gGameExternalOptions.ubDefaultArrivalSectorX;
gsMercArriveSectorY = gGameExternalOptions.ubDefaultArrivalSectorY;
@@ -5291,7 +5294,7 @@ void UpdateAirspaceControl( void )
{
for ( UINT8 ubSectorY = 1; ubSectorY <= 16; ++ubSectorY )
{
if ( StrategicMap[CALCULATE_STRATEGIC_INDEX( ubSectorX, ubSectorY )].usAirType != AIRSPACE_ENEMY_ACTIVE && !sBadSectorsList[ubSectorX][ubSectorY] )
if ( !(StrategicMap[CALCULATE_STRATEGIC_INDEX( ubSectorX, ubSectorY )].usAirType & AIRSPACE_ENEMY_ACTIVE) && !sBadSectorsList[ubSectorX][ubSectorY] )
{
gsMercArriveSectorX = ubSectorX;
gsMercArriveSectorY = ubSectorY;
@@ -5324,6 +5327,72 @@ void UpdateAirspaceControl( void )
UpdateRefuelSiteAvailability( );
}
// get the maximum distance from a SAM to its covered sectors (in principle, not taking into account status)
FLOAT GetSAMMaxDistanceToCoveredSector( UINT8 usSam )
{
FLOAT maxdist = 0.0f;
if ( usSam < NUMBER_OF_SAMS )
{
UINT8 samsector = pSamList[usSam];
UINT8 sam_x = SECTORX( samsector );
UINT8 sam_y = SECTORY( samsector );
for ( int x = 1; x < MAP_WORLD_X - 1; ++x )
{
for ( int y = 1; y < MAP_WORLD_Y - 1; ++y )
{
if ( ubSAMControlledSectors[y][x] & (1 << usSam) )
{
FLOAT dist = std::sqrt( (sam_x - x)*(sam_x - x) + (sam_y - y)*(sam_y - y) );
if ( maxdist < dist )
maxdist = dist;
}
}
}
}
return maxdist;
}
BOOLEAN DoesSamCoverSector( UINT8 usSam, UINT8 usSector, BOOLEAN* apSamIsWorking )
{
if ( apSamIsWorking )
*apSamIsWorking = FALSE;
if ( usSam < NUMBER_OF_SAMS )
{
// can this sam control this sector in principle?
if ( ubSAMControlledSectors[SECTORY( usSector )][SECTORX( usSector )] & (1 << usSam) )
{
UINT8 samsector = pSamList[usSam];
if ( StrategicMap[SECTOR_INFO_TO_STRATEGIC_INDEX( samsector )].bSAMCondition >= MIN_CONDITION_FOR_SAM_SITE_TO_WORK && StrategicMap[SECTOR_INFO_TO_STRATEGIC_INDEX( samsector )].sSamHackStatus > 0 )
{
if ( apSamIsWorking )
*apSamIsWorking = TRUE;
}
FLOAT dist = std::sqrt( (SECTORX( samsector ) - SECTORX( usSector ))*(SECTORX( samsector ) - SECTORX( usSector )) + (SECTORY( samsector ) - SECTORY( usSector ))*(SECTORY( samsector ) - SECTORY( usSector )) );
// determine max distance SAM has to cover
FLOAT sammaxdistance = GetSAMMaxDistanceToCoveredSector( usSam );
// allowed range ratio according to status and hacking
FLOAT samrangeratio = StrategicMap[SECTOR_INFO_TO_STRATEGIC_INDEX( samsector )].bSAMCondition * StrategicMap[SECTOR_INFO_TO_STRATEGIC_INDEX( samsector )].sSamHackStatus / 10000.0f;
// can this SAM currently cover this sector?
if ( dist <= sammaxdistance * samrangeratio )
{
return TRUE;
}
}
}
return FALSE;
}
BOOLEAN IsThereAFunctionalSAMSiteInSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ )
{
@@ -5333,24 +5402,23 @@ BOOLEAN IsThereAFunctionalSAMSiteInSector( INT16 sSectorX, INT16 sSectorY, INT8
}
if ( StrategicMap[CALCULATE_STRATEGIC_INDEX( sSectorX, sSectorY )].bSAMCondition < MIN_CONDITION_FOR_SAM_SITE_TO_WORK )
{
return(FALSE);
}
if ( StrategicMap[CALCULATE_STRATEGIC_INDEX( sSectorX, sSectorY )].sSamHackStatus <= 0 )
return(FALSE);
return(TRUE);
}
BOOLEAN IsThisSectorASAMSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ )
{
INT32 cnt;
// is the sector above ground?
if ( bSectorZ != 0 )
{
return(FALSE);
}
for ( cnt = 0; cnt < NUMBER_OF_SAMS; cnt++ )
for ( INT32 cnt = 0; cnt < NUMBER_OF_SAMS; ++cnt )
{
if ( (sSectorX == gpSamSectorX[cnt]) && (sSectorY == gpSamSectorY[cnt]) )
return(TRUE);
@@ -5446,6 +5514,15 @@ BOOLEAN LoadStrategicInfoFromSavedFile( HWFILE hFile )
if ( guiCurrentSaveGameVersion < MILITIA_MOVEMENT )
StrategicMap[i].usFlags = 0;
}
if ( guiCurrentSaveGameVersion < HACKABLE_SAMS )
{
// all SAM sites start game in perfect working condition
for ( UINT32 cnt = 0; cnt < NUMBER_OF_SAMS; ++cnt )
{
StrategicMap[gpSamSectorX[cnt] + (MAP_WORLD_X * gpSamSectorY[cnt])].sSamHackStatus = 100;
}
}
// Load the Sector Info
uiSize = sizeof(SECTORINFO);