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
+2 -1
View File
@@ -21,6 +21,7 @@ extern CHAR16 zTrackingNumber[16];
// Keeps track of the saved game version. Increment the saved game version whenever // Keeps track of the saved game version. Increment the saved game version whenever
// you will invalidate the saved game file // you will invalidate the saved game file
#define HACKABLE_SAMS 172 // Flugente: SAM sites now have a status for hacking
#define LUA_MODDERDATA 171 // Flugente: modders can set and use data in an exclusive array #define LUA_MODDERDATA 171 // Flugente: modders can set and use data in an exclusive array
#define WORKERS 170 // Flugente: train workers for facilities #define WORKERS 170 // Flugente: train workers for facilities
#define WEATHER_CHANGE 169 // Flugente: sector-specific weather & more weather types #define WEATHER_CHANGE 169 // Flugente: sector-specific weather & more weather types
@@ -90,7 +91,7 @@ extern CHAR16 zTrackingNumber[16];
#define AP100_SAVEGAME_DATATYPE_CHANGE 105 // Before this, we didn't have the 100AP structure changes #define AP100_SAVEGAME_DATATYPE_CHANGE 105 // Before this, we didn't have the 100AP structure changes
#define NIV_SAVEGAME_DATATYPE_CHANGE 102 // Before this, we used the old structure system #define NIV_SAVEGAME_DATATYPE_CHANGE 102 // Before this, we used the old structure system
#define SAVE_GAME_VERSION LUA_MODDERDATA #define SAVE_GAME_VERSION HACKABLE_SAMS
//#define RUSSIANGOLD //#define RUSSIANGOLD
#ifdef __cplusplus #ifdef __cplusplus
+70 -65
View File
@@ -59,8 +59,6 @@ extern INT32 giReinforcementPool;
extern BOOLEAN gfTacticalDoHeliRun; extern BOOLEAN gfTacticalDoHeliRun;
extern UINT8 ubSAMControlledSectors[MAP_WORLD_Y][MAP_WORLD_X];
// Arulco special division decision code // Arulco special division decision code
// ASD savegame variables // ASD savegame variables
@@ -1007,69 +1005,75 @@ void EnemyHeliSAMCheck( INT16 id )
INT8 heli_y = SECTORY( heli.sector_current ); INT8 heli_y = SECTORY( heli.sector_current );
// is the airspace in our current sector player-controlled and operational? // is the airspace in our current sector player-controlled and operational?
if ( StrategicMap[CALCULATE_STRATEGIC_INDEX( heli_x, heli_y )].usAirType == AIRSPACE_PLAYER_ACTIVE ) if ( StrategicMap[CALCULATE_STRATEGIC_INDEX( heli_x, heli_y )].usAirType & AIRSPACE_PLAYER_ACTIVE )
{ {
UINT8 ubControllingSAM = ubSAMControlledSectors[heli_y][heli_x]; for ( int i = 0; i < NUMBER_OF_SAMS; ++i )
StrategicMapElement *pSAMStrategicMap = &(StrategicMap[SECTOR_INFO_TO_STRATEGIC_INDEX( pSamList[ubControllingSAM - 1] )]);
if ( pSAMStrategicMap )
{ {
UINT16 ubBestSAMOperatorID = NOBODY; BOOLEAN samworking = FALSE;
FLOAT samcth = GetBestSAMOperatorCTH_Player( gpSamSectorX[ubControllingSAM - 1], gpSamSectorY[ubControllingSAM - 1], 0, &ubBestSAMOperatorID ); if ( DoesSamCoverSector( i, heli.sector_current, &samworking ) && samworking )
// cth is reduced if SAM is damaged, even if it can still operate
samcth = (samcth * pSAMStrategicMap->bSAMCondition) / 100.0f;
// determine distance from SAM to heli
FLOAT distance = sqrt(FLOAT(abs( heli_x - gpSamSectorX[ubControllingSAM - 1] ) * abs( heli_x - gpSamSectorX[ubControllingSAM - 1] ) + abs( heli_y - gpSamSectorY[ubControllingSAM - 1] ) * abs( heli_y - gpSamSectorY[ubControllingSAM - 1] ) ));
// distance penalty
samcth = (samcth * (100.0f - 8 * distance)) / 100.0f;
// if cth is too low, we don't fire
if ( samcth > 0.01 )
{ {
CHAR16 pStrSectorName[128]; StrategicMapElement *pSAMStrategicMap = &(StrategicMap[SECTOR_INFO_TO_STRATEGIC_INDEX( pSamList[i] )]);
GetSectorIDString( heli_x, heli_y, 0, pStrSectorName, FALSE );
CHAR16 pStrSectorName_SAM[128]; // also check whether this sector is not enemy-controlled - we can't have the AI shooting at its own helis
GetSectorIDString( gpSamSectorX[ubControllingSAM - 1], gpSamSectorY[ubControllingSAM - 1], 0, pStrSectorName_SAM, FALSE ); if ( pSAMStrategicMap && !pSAMStrategicMap->fEnemyControlled )
MapScreenMessage( FONT_MCOLOR_LTRED, MSG_INTERFACE, szEnemyHeliText[8], pStrSectorName_SAM, pStrSectorName );
// if we hit, damage the heli
BOOLEAN fHit = FALSE;
BOOLEAN fDestroyed = FALSE;
if ( Chance( (UINT32)(samcth) ) )
{ {
fHit = TRUE; UINT16 ubBestSAMOperatorID = NOBODY;
FLOAT samcth = GetBestSAMOperatorCTH_Player( gpSamSectorX[i], gpSamSectorY[i], 0, &ubBestSAMOperatorID );
UINT8 damage = gGameExternalOptions.gEnemyHeliSAMDamage_Base + Random( gGameExternalOptions.gEnemyHeliSAMDamage_Var ); // cth is reduced if SAM is damaged, even if it can still operate
samcth = (samcth * pSAMStrategicMap->bSAMCondition) / 100.0f;
MapScreenMessage( FONT_MCOLOR_LTRED, MSG_INTERFACE, szEnemyHeliText[6], pStrSectorName ); // determine distance from SAM to heli
FLOAT distance = sqrt( FLOAT( abs( heli_x - gpSamSectorX[i] ) * abs( heli_x - gpSamSectorX[i] ) + abs( heli_y - gpSamSectorY[i] ) * abs( heli_y - gpSamSectorY[i] ) ) );
heli.hp = max( 0, heli.hp - damage ); // distance penalty
samcth = (samcth * (100.0f - 8 * distance)) / 100.0f;
if ( !heli.hp ) // if cth is too low, we don't fire
if ( samcth > 0.01 )
{ {
fDestroyed = TRUE; CHAR16 pStrSectorName[128];
GetSectorIDString( heli_x, heli_y, 0, pStrSectorName, FALSE );
heli.flagmask |= ENEMYHELI_SHOTDOWN; CHAR16 pStrSectorName_SAM[128];
GetSectorIDString( gpSamSectorX[i], gpSamSectorY[i], 0, pStrSectorName_SAM, FALSE );
heli.Destroy( ); MapScreenMessage( FONT_MCOLOR_LTRED, MSG_INTERFACE, szEnemyHeliText[8], pStrSectorName_SAM, pStrSectorName );
// if we hit, damage the heli
BOOLEAN fHit = FALSE;
BOOLEAN fDestroyed = FALSE;
if ( Chance( (UINT32)(samcth) ) )
{
fHit = TRUE;
UINT8 damage = gGameExternalOptions.gEnemyHeliSAMDamage_Base + Random( gGameExternalOptions.gEnemyHeliSAMDamage_Var );
MapScreenMessage( FONT_MCOLOR_LTRED, MSG_INTERFACE, szEnemyHeliText[6], pStrSectorName );
heli.hp = max( 0, heli.hp - damage );
if ( !heli.hp )
{
fDestroyed = TRUE;
heli.flagmask |= ENEMYHELI_SHOTDOWN;
heli.Destroy( );
}
}
// depending on our result, award experience to the operator
if ( ubBestSAMOperatorID != NOBODY )
{
if ( fHit )
StatChange( MercPtrs[ubBestSAMOperatorID], EXPERAMT, fDestroyed ? 30 : 10, TRUE );
StatChange( MercPtrs[ubBestSAMOperatorID], MECHANAMT, 5, TRUE );
}
} }
} }
// depending on our result, award experience to the operator
if ( ubBestSAMOperatorID != NOBODY )
{
if ( fHit )
StatChange( MercPtrs[ubBestSAMOperatorID], EXPERAMT, fDestroyed ? 30 : 10, TRUE );
StatChange( MercPtrs[ubBestSAMOperatorID], MECHANAMT, 5, TRUE );
}
} }
} }
} }
@@ -1230,17 +1234,23 @@ void EnemyHeliCheckPlayerKnowledge( INT16 id )
} }
// is the airspace in our current sector player-controlled and operational? // is the airspace in our current sector player-controlled and operational?
if ( StrategicMap[CALCULATE_STRATEGIC_INDEX( current_x, current_y )].usAirType == AIRSPACE_PLAYER_ACTIVE ) if ( StrategicMap[CALCULATE_STRATEGIC_INDEX( current_x, current_y )].usAirType & AIRSPACE_PLAYER_ACTIVE )
{ {
UINT8 ubControllingSAM = ubSAMControlledSectors[current_y][current_x]; for ( int i = 0; i < NUMBER_OF_SAMS; ++i )
// if mercs man the SAM, they will let us know of the new SAM
if ( PlayerMercsInSector( gpSamSectorX[ubControllingSAM - 1], gpSamSectorY[ubControllingSAM - 1], 0 ) )
{ {
// if we previously did not know of the heli, our mercs will alert us if ( DoesSamCoverSector( i, heli.sector_current ) )
if ( !(heli.flagmask & ENEMYHELI_KNOWNTOPLAYER) )
{ {
SayQuoteFromAnyBodyInThisSector( gpSamSectorX[ubControllingSAM - 1], gpSamSectorY[ubControllingSAM - 1], 0, QUOTE_AIR_RAID ); // if mercs man the SAM, they will let us know of the new SAM
if ( PlayerMercsInSector( gpSamSectorX[i], gpSamSectorY[i], 0 ) )
{
// if we previously did not know of the heli, our mercs will alert us
if ( !(heli.flagmask & ENEMYHELI_KNOWNTOPLAYER) )
{
SayQuoteFromAnyBodyInThisSector( gpSamSectorX[i], gpSamSectorY[i], 0, QUOTE_AIR_RAID );
break;
}
}
} }
} }
@@ -1265,11 +1275,6 @@ void RepairSamSite( UINT8 aSector )
} }
} }
BOOLEAN IsSectorAirSpacePlayerControlled( UINT8 aSector )
{
return (StrategicMap[SECTOR_INFO_TO_STRATEGIC_INDEX( aSector )].usAirType == AIRSPACE_PLAYER_ACTIVE);
}
UINT8 NumPlayerAirSpaceOnHeliPath( UINT8 aStart, UINT8 aEnd ) UINT8 NumPlayerAirSpaceOnHeliPath( UINT8 aStart, UINT8 aEnd )
{ {
UINT8 samcontacts = 0; UINT8 samcontacts = 0;
@@ -1280,7 +1285,7 @@ UINT8 NumPlayerAirSpaceOnHeliPath( UINT8 aStart, UINT8 aEnd )
{ {
tmpsect = GetNextEnemyHeliSector( tmpsect, aEnd ); tmpsect = GetNextEnemyHeliSector( tmpsect, aEnd );
if ( IsSectorAirSpacePlayerControlled( tmpsect ) ) if ( StrategicMap[SECTOR_INFO_TO_STRATEGIC_INDEX( tmpsect )].usAirType & AIRSPACE_PLAYER_ACTIVE )
++samcontacts; ++samcontacts;
} }
-2
View File
@@ -101,8 +101,6 @@ void EnemyHeliCheckPlayerKnowledge( INT16 id );
void RepairSamSite( UINT8 aSector ); void RepairSamSite( UINT8 aSector );
BOOLEAN IsSectorAirSpacePlayerControlled( UINT8 aSector );
UINT8 NumPlayerAirSpaceOnHeliPath( UINT8 aStart, UINT8 aEnd ); UINT8 NumPlayerAirSpaceOnHeliPath( UINT8 aStart, UINT8 aEnd );
// get the next sector in an enemy heli flight path. // get the next sector in an enemy heli flight path.
+52 -1
View File
@@ -860,6 +860,10 @@ static int l_GetUsedLanguage( lua_State *L );
static int l_DoInteractiveActionDefaultResult( lua_State *L ); static int l_DoInteractiveActionDefaultResult( lua_State *L );
static int l_GiveExp( lua_State *L ); static int l_GiveExp( lua_State *L );
static int l_NumNonPlayerTeamInSector( lua_State *L );
static int l_SetSamSiteHackStatus( lua_State *L );
static int l_GetSamSiteHackStatus( lua_State *L );
using namespace std; using namespace std;
UINT16 idProfil; UINT16 idProfil;
@@ -1728,6 +1732,10 @@ void IniFunction(lua_State *L, BOOLEAN bQuests )
lua_register( L, "DoInteractiveActionDefaultResult", l_DoInteractiveActionDefaultResult ); lua_register( L, "DoInteractiveActionDefaultResult", l_DoInteractiveActionDefaultResult );
lua_register( L, "GiveExp", l_GiveExp ); lua_register( L, "GiveExp", l_GiveExp );
lua_register( L, "NumNonPlayerTeamInSector", l_NumNonPlayerTeamInSector );
lua_register( L, "SetSamSiteHackStatus", l_SetSamSiteHackStatus );
lua_register( L, "GetSamSiteHackStatus", l_GetSamSiteHackStatus );
} }
#ifdef NEWMUSIC #ifdef NEWMUSIC
BOOLEAN LetLuaMusicControl(UINT8 Init) BOOLEAN LetLuaMusicControl(UINT8 Init)
@@ -7252,7 +7260,7 @@ static int l_ACTION_ITEM_LOCAL_ALARM (lua_State *L)
{ {
if ( lua_gettop(L) >= 1 ) if ( lua_gettop(L) >= 1 )
{ {
UINT32 sGridNo = lua_tointeger(L, 1); INT32 sGridNo = lua_tointeger(L, 1);
// Flugente: check for valid sGridNo // Flugente: check for valid sGridNo
if ( TileIsOutOfBounds(sGridNo) ) if ( TileIsOutOfBounds(sGridNo) )
@@ -13296,3 +13304,46 @@ static int l_GiveExp( lua_State *L )
return 0; return 0;
} }
static int l_NumNonPlayerTeamInSector( lua_State *L )
{
if ( lua_gettop( L ) >= 3 )
{
INT16 sSectorX = lua_tointeger( L, 1 );
INT16 sSectorY = lua_tointeger( L, 2 );
UINT8 ubTeam = lua_tointeger( L, 3 );
UINT16 numteam = NumNonPlayerTeamMembersInSector( sSectorX, sSectorY, ubTeam );
lua_pushinteger( L, numteam );
}
return 1;
}
static int l_SetSamSiteHackStatus( lua_State *L )
{
if ( lua_gettop( L ) >= 3 )
{
INT16 sSectorX = lua_tointeger( L, 1 );
INT16 sSectorY = lua_tointeger( L, 2 );
INT8 sStatus = lua_tointeger( L, 3 );
SetSamHackStatus( sSectorX, sSectorY, sStatus );
}
return 0;
}
static int l_GetSamSiteHackStatus( lua_State *L )
{
if ( lua_gettop( L ) >= 2 )
{
INT16 sSectorX = lua_tointeger( L, 1 );
INT16 sSectorY = lua_tointeger( L, 2 );
lua_pushinteger( L, StrategicMap[CALCULATE_STRATEGIC_INDEX( sSectorX, sSectorY )].sSamHackStatus );
}
return 1;
}
+106 -140
View File
@@ -81,8 +81,6 @@ extern UINT8 gubCurrentTalkingID;
// current temp path for dest char // current temp path for dest char
extern PathStPtr pTempHelicopterPath; extern PathStPtr pTempHelicopterPath;
extern UINT8 ubSAMControlledSectors[ MAP_WORLD_Y ][ MAP_WORLD_X ];
// the seating capacities // the seating capacities
//extern INT32 iSeatingCapacities[]; //extern INT32 iSeatingCapacities[];
@@ -1131,17 +1129,14 @@ INT32 GetCostOfPassageForHelicopter( INT16 sX, INT16 sY )
INT32 iCost = 0; INT32 iCost = 0;
// HEADROCK HAM 3.5: Costs externalized // HEADROCK HAM 3.5: Costs externalized
INT32 iBaseCostPerGreenTile = gGameExternalOptions.usHelicopterBaseCostPerGreenTile;
INT32 iBaseCostPerRedTile = gGameExternalOptions.usHelicopterBaseCostPerRedTile;
// if they don't control it // if they don't control it
if ( StrategicMap[CALCULATE_STRATEGIC_INDEX( sX, sY )].usAirType != AIRSPACE_ENEMY_ACTIVE ) if ( !(StrategicMap[CALCULATE_STRATEGIC_INDEX( sX, sY )].usAirType & AIRSPACE_ENEMY_ACTIVE) )
{ {
iCost = iBaseCostPerGreenTile; iCost = gGameExternalOptions.usHelicopterBaseCostPerGreenTile;
} }
else else
{ {
iCost = iBaseCostPerRedTile; iCost = gGameExternalOptions.usHelicopterBaseCostPerRedTile;
} }
// HEADROCK HAM 3.5: Apply facility-based modifiers from global integer recalculated hourly // HEADROCK HAM 3.5: Apply facility-based modifiers from global integer recalculated hourly
@@ -1349,7 +1344,7 @@ void HandleHeliHoverForAMinute( void )
gubHelicopterHoverTime = 0; gubHelicopterHoverTime = 0;
iTotalHeliDistanceSinceRefuel++; iTotalHeliDistanceSinceRefuel++;
if ( StrategicMap[CALCULATE_STRATEGIC_INDEX( sX, sY )].usAirType != AIRSPACE_ENEMY_ACTIVE ) if ( !(StrategicMap[CALCULATE_STRATEGIC_INDEX( sX, sY )].usAirType & AIRSPACE_ENEMY_ACTIVE) )
{ {
iTotalAccumulatedCostByPlayer += gGameExternalOptions.usHelicopterHoverCostOnGreenTile; iTotalAccumulatedCostByPlayer += gGameExternalOptions.usHelicopterHoverCostOnGreenTile;
} }
@@ -2412,63 +2407,44 @@ BOOLEAN IsHelicopterOnGroundAtRefuelingSite( UINT8 ubRefuelingSite )
BOOLEAN WillAirRaidBeStopped( INT16 sSectorX, INT16 sSectorY ) BOOLEAN WillAirRaidBeStopped( INT16 sSectorX, INT16 sSectorY )
{ {
UINT8 ubSamNumber = 0;
INT8 bSAMCondition;
UINT8 ubChance; UINT8 ubChance;
if ( !StrategicMap[(AIRPORT_X + (MAP_WORLD_X * AIRPORT_Y))].fEnemyControlled && !StrategicMap[(AIRPORT2_X + (MAP_WORLD_X * AIRPORT2_Y))].fEnemyControlled )
{
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String( "WillAirRaidBeStopped: enemy has no more airports" ) );
return(TRUE);
}
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String( "WillAirRaidBeStopped: enemy air controlled = %d", StrategicMap[CALCULATE_STRATEGIC_INDEX( sSectorX, sSectorY )].usAirType ) ); DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String( "WillAirRaidBeStopped: enemy air controlled = %d", StrategicMap[CALCULATE_STRATEGIC_INDEX( sSectorX, sSectorY )].usAirType ) );
// if enemy controls this SAM site, then it can't stop an air raid // if enemy controls this SAM site, then it can't stop an air raid
if ( StrategicMap[CALCULATE_STRATEGIC_INDEX( sSectorX, sSectorY )].usAirType != AIRSPACE_PLAYER_ACTIVE ) if ( !(StrategicMap[CALCULATE_STRATEGIC_INDEX( sSectorX, sSectorY )].usAirType & AIRSPACE_PLAYER_ACTIVE) )
{ {
return( FALSE ); return( FALSE );
} }
if( !StrategicMap[ ( AIRPORT_X + ( MAP_WORLD_X * AIRPORT_Y ) ) ].fEnemyControlled && !StrategicMap[ ( AIRPORT2_X + ( MAP_WORLD_X * AIRPORT2_Y ) ) ].fEnemyControlled )
{
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("WillAirRaidBeStopped: enemy has no more airports"));
return( TRUE );
}
// which SAM controls this sector?
ubSamNumber = ubSAMControlledSectors[ sSectorY ][ sSectorX ];
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("WillAirRaidBeStopped: SAM number = %d",ubSamNumber));
// if none of them
if (ubSamNumber == 0)
{
return( FALSE);
}
// get the condition of that SAM site (NOTE: SAM #s are 1-4, but indexes are 0-3!!!)
Assert( ubSamNumber <= NUMBER_OF_SAMS );
bSAMCondition = StrategicMap[ SECTOR_INFO_TO_STRATEGIC_INDEX( pSamList[ ubSamNumber - 1 ] ) ].bSAMCondition;
// if it's too busted to work, then it can't stop an air raid
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("WillAirRaidBeStopped: SAM condition = %d",bSAMCondition));
if( bSAMCondition < MIN_CONDITION_FOR_SAM_SITE_TO_WORK )
{
// no problem, SAM site not working
return( FALSE );
}
// Friendly airspace controlled by a working SAM site, so SAM site fires a SAM at air raid bomber // Friendly airspace controlled by a working SAM site, so SAM site fires a SAM at air raid bomber
// calc chance that chopper will be shot down for ( int i = 0; i < NUMBER_OF_SAMS; ++i )
ubChance = bSAMCondition;
// there's a fair chance of a miss even if the SAM site is in perfect working order
if (ubChance > gHelicopterSettings.ubHelicopterSAMSiteAccuracy * 3) // Madd - since this is only used for enemy air raids, we'll say that good guy SAMs can have a max of 99% to hit instead of 33%
{ {
ubChance = gHelicopterSettings.ubHelicopterSAMSiteAccuracy * 3; BOOLEAN samworking = FALSE;
} if ( DoesSamCoverSector( i, SECTOR( sSectorX, sSectorY ), &samworking ) && samworking )
{
// calc chance that chopper will be shot down
ubChance = StrategicMap[SECTOR_INFO_TO_STRATEGIC_INDEX( pSamList[i] )].bSAMCondition;
if( PreRandom( 100 ) < ubChance) // there's a fair chance of a miss even if the SAM site is in perfect working order
{ if ( ubChance > gHelicopterSettings.ubHelicopterSAMSiteAccuracy * 3 ) // Madd - since this is only used for enemy air raids, we'll say that good guy SAMs can have a max of 99% to hit instead of 33%
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("WillAirRaidBeStopped: return true")); {
return( TRUE ); ubChance = gHelicopterSettings.ubHelicopterSAMSiteAccuracy * 3;
}
if ( PreRandom( 100 ) < ubChance )
{
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String( "WillAirRaidBeStopped: return true" ) );
return(TRUE);
}
}
} }
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("WillAirRaidBeStopped: return false")); DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("WillAirRaidBeStopped: return false"));
@@ -2483,104 +2459,94 @@ void HeliCrashSoundStopCallback( void *pData )
BOOLEAN HandleSAMSiteAttackOfHelicopterInSector( INT16 sSectorX, INT16 sSectorY ) BOOLEAN HandleSAMSiteAttackOfHelicopterInSector( INT16 sSectorX, INT16 sSectorY )
{ {
UINT8 ubSamNumber = 0; UINT32 ubSamNumber = 0;
INT8 bSAMCondition; INT8 bSAMCondition;
UINT8 ubChance; UINT8 ubChance;
#ifdef JA2TESTVERSION
if ( fSAMSitesDisabledFromAttackingPlayer == TRUE )
{
return(FALSE);
}
#endif
// if this sector is in friendly airspace, we're safe // if this sector is in friendly airspace, we're safe
if ( StrategicMap[CALCULATE_STRATEGIC_INDEX( sSectorX, sSectorY )].usAirType != AIRSPACE_ENEMY_ACTIVE ) if ( !(StrategicMap[CALCULATE_STRATEGIC_INDEX( sSectorX, sSectorY )].usAirType & AIRSPACE_ENEMY_ACTIVE) )
{ {
// no problem, friendly airspace // no problem, friendly airspace
return( FALSE ); return( FALSE );
} }
// which SAM controls this sector?
ubSamNumber = ubSAMControlledSectors[ sSectorY ][ sSectorX ];
// if none of them
if (ubSamNumber == 0)
{
return( FALSE);
}
// get the condition of that SAM site (NOTE: SAM #s are 1-4, but indexes are 0-3!!!)
Assert( ubSamNumber <= NUMBER_OF_SAMS );
bSAMCondition = StrategicMap[ SECTOR_INFO_TO_STRATEGIC_INDEX( pSamList[ ubSamNumber - 1 ] ) ].bSAMCondition;
// if the SAM site is too damaged to be a threat
if( bSAMCondition < MIN_CONDITION_FOR_SAM_SITE_TO_WORK )
{
// no problem, SAM site not working
return( FALSE );
}
#ifdef JA2TESTVERSION
if( fSAMSitesDisabledFromAttackingPlayer == TRUE )
{
return( FALSE );
}
#endif
// Hostile airspace controlled by a working SAM site, so SAM site fires a SAM at Skyrider!!! // Hostile airspace controlled by a working SAM site, so SAM site fires a SAM at Skyrider!!!
// calc chance that chopper will be shot down for ( int i = 0; i < NUMBER_OF_SAMS; ++i )
ubChance = bSAMCondition;
// there's a fair chance of a miss even if the SAM site is in perfect working order
if (ubChance > gHelicopterSettings.ubHelicopterSAMSiteAccuracy)
{ {
ubChance = gHelicopterSettings.ubHelicopterSAMSiteAccuracy; BOOLEAN samworking = FALSE;
} if ( DoesSamCoverSector( i, SECTOR( sSectorX, sSectorY ), &samworking ) && samworking )
if( PreRandom( 100 ) < ubChance)
{
// another hit!
gubHelicopterHitsTaken++;
// Took a hit! Pause time so player can reconsider
StopTimeCompression();
// first hit?
if ( gubHelicopterHitsTaken == 1 )
{ {
HeliCharacterDialogue( pSkyRider, HELI_TOOK_MINOR_DAMAGE ); bSAMCondition = StrategicMap[SECTOR_INFO_TO_STRATEGIC_INDEX( pSamList[i] )].bSAMCondition;
if( gGameExternalOptions.fHelicopterPassengersCanGetHit == TRUE )
HurtPassengersInHelicopter( iHelicopterVehicleId );
}
// second hit?
else if ( gubHelicopterHitsTaken == 2 )
{
// going back to base (no choice, dialogue says so)
HeliCharacterDialogue( pSkyRider, HELI_TOOK_MAJOR_DAMAGE );
MakeHeliReturnToBase( HELICOPTER_RETURN_REASON_DAMAGE );
if( gGameExternalOptions.fHelicopterPassengersCanGetHit == TRUE )
HurtPassengersInHelicopter( iHelicopterVehicleId );
}
// third hit!
else
{
// Important: Skyrider must still be alive when he talks, so must do this before heli is destroyed!
HeliCharacterDialogue( pSkyRider, HELI_GOING_DOWN );
// everyone die die die // calc chance that chopper will be shot down
// play sound ubChance = bSAMCondition;
// if ( PlayJA2StreamingSampleFromFile( "stsounds\\blah2.wav", RATE_11025, HIGHVOLUME, 1, MIDDLEPAN, HeliCrashSoundStopCallback ) == SOUND_ERROR )
//{
//// Destroy here if we cannot play streamed sound sample....
// SkyriderDestroyed( );
//}
//else
//{
//// otherwise it's handled in the callback
//// remove any arrival events for the helicopter's group
//DeleteStrategicEvent( EVENT_GROUP_ARRIVAL, pVehicleList[ iHelicopterVehicleId ].ubMovementGroup );
//}
// anv - calling SkyriderDestroyed() in callback from playing sound causes sound system to crash, as SkyriderDestroyed causes new sounds (hit battlesnds) to play while blah2 is not removed yet
// + if there's a pause while falling heli sound is played, it's possible to cheat by changing passengers assignments
PlayJA2StreamingSampleFromFile( "stsounds\\blah2.wav", RATE_11025, HIGHVOLUME, 1, MIDDLEPAN, HeliCrashSoundStopCallback );
SkyriderDestroyed( );
// special return code indicating heli was destroyed // there's a fair chance of a miss even if the SAM site is in perfect working order
return( TRUE ); if ( ubChance > gHelicopterSettings.ubHelicopterSAMSiteAccuracy )
{
ubChance = gHelicopterSettings.ubHelicopterSAMSiteAccuracy;
}
if ( PreRandom( 100 ) < ubChance )
{
// another hit!
++gubHelicopterHitsTaken;
// Took a hit! Pause time so player can reconsider
StopTimeCompression( );
// first hit?
if ( gubHelicopterHitsTaken == 1 )
{
HeliCharacterDialogue( pSkyRider, HELI_TOOK_MINOR_DAMAGE );
if ( gGameExternalOptions.fHelicopterPassengersCanGetHit == TRUE )
HurtPassengersInHelicopter( iHelicopterVehicleId );
}
// second hit?
else if ( gubHelicopterHitsTaken == 2 )
{
// going back to base (no choice, dialogue says so)
HeliCharacterDialogue( pSkyRider, HELI_TOOK_MAJOR_DAMAGE );
MakeHeliReturnToBase( HELICOPTER_RETURN_REASON_DAMAGE );
if ( gGameExternalOptions.fHelicopterPassengersCanGetHit == TRUE )
HurtPassengersInHelicopter( iHelicopterVehicleId );
}
// third hit!
else
{
// Important: Skyrider must still be alive when he talks, so must do this before heli is destroyed!
HeliCharacterDialogue( pSkyRider, HELI_GOING_DOWN );
// everyone die die die
// play sound
// if ( PlayJA2StreamingSampleFromFile( "stsounds\\blah2.wav", RATE_11025, HIGHVOLUME, 1, MIDDLEPAN, HeliCrashSoundStopCallback ) == SOUND_ERROR )
//{
//// Destroy here if we cannot play streamed sound sample....
// SkyriderDestroyed( );
//}
//else
//{
//// otherwise it's handled in the callback
//// remove any arrival events for the helicopter's group
//DeleteStrategicEvent( EVENT_GROUP_ARRIVAL, pVehicleList[ iHelicopterVehicleId ].ubMovementGroup );
//}
// anv - calling SkyriderDestroyed() in callback from playing sound causes sound system to crash, as SkyriderDestroyed causes new sounds (hit battlesnds) to play while blah2 is not removed yet
// + if there's a pause while falling heli sound is played, it's possible to cheat by changing passengers assignments
PlayJA2StreamingSampleFromFile( "stsounds\\blah2.wav", RATE_11025, HIGHVOLUME, 1, MIDDLEPAN, HeliCrashSoundStopCallback );
SkyriderDestroyed( );
// special return code indicating heli was destroyed
return(TRUE);
}
}
} }
} }
@@ -2833,7 +2799,7 @@ INT16 GetNumSafeSectorsInPath( void )
{ {
uiLocation = pNode->uiSectorId; uiLocation = pNode->uiSectorId;
if ( StrategicMap[uiLocation].usAirType != AIRSPACE_ENEMY_ACTIVE ) if ( !(StrategicMap[uiLocation].usAirType & AIRSPACE_ENEMY_ACTIVE) )
{ {
++uiCount; ++uiCount;
} }
@@ -2861,7 +2827,7 @@ INT16 GetNumSafeSectorsInPath( void )
{ {
uiLocation = pNode->uiSectorId; uiLocation = pNode->uiSectorId;
if ( StrategicMap[uiLocation].usAirType != AIRSPACE_ENEMY_ACTIVE ) if ( !(StrategicMap[uiLocation].usAirType & AIRSPACE_ENEMY_ACTIVE) )
{ {
++uiCount; ++uiCount;
} }
@@ -2915,7 +2881,7 @@ INT16 GetNumUnSafeSectorsInPath( void )
{ {
uiLocation = pNode->uiSectorId; uiLocation = pNode->uiSectorId;
if ( StrategicMap[uiLocation].usAirType == AIRSPACE_ENEMY_ACTIVE ) if ( StrategicMap[uiLocation].usAirType & AIRSPACE_ENEMY_ACTIVE )
{ {
++uiCount; ++uiCount;
} }
@@ -2942,7 +2908,7 @@ INT16 GetNumUnSafeSectorsInPath( void )
{ {
uiLocation = pNode->uiSectorId; uiLocation = pNode->uiSectorId;
if ( StrategicMap[uiLocation].usAirType == AIRSPACE_ENEMY_ACTIVE ) if ( StrategicMap[uiLocation].usAirType & AIRSPACE_ENEMY_ACTIVE )
{ {
++uiCount; ++uiCount;
} }
+10 -6
View File
@@ -775,7 +775,7 @@ void ToggleShowTeamsMode( void )
void ToggleAirspaceMode( void ) void ToggleAirspaceMode( void )
{ {
if ( gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE ) if ( gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE_COLOURED_SAMS )
{ {
// turn airspace OFF // turn airspace OFF
gusMapDisplayColourMode = MAP_DISPLAY_NORMAL; gusMapDisplayColourMode = MAP_DISPLAY_NORMAL;
@@ -1006,23 +1006,26 @@ void TurnOnAirSpaceMode( void )
{ {
// if mode already on, leave, else set and redraw // if mode already on, leave, else set and redraw
if ( gusMapDisplayColourMode != MAP_DISPLAY_AIRSPACE ) if ( gusMapDisplayColourMode != MAP_DISPLAY_AIRSPACE && gusMapDisplayColourMode != MAP_DISPLAY_AIRSPACE_COLOURED_SAMS )
{
gusMapDisplayColourMode = MAP_DISPLAY_AIRSPACE; gusMapDisplayColourMode = MAP_DISPLAY_AIRSPACE;
else if ( gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE )
gusMapDisplayColourMode = MAP_DISPLAY_AIRSPACE_COLOURED_SAMS;
if ( gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE || gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE_COLOURED_SAMS )
{
MapBorderButtonOn( MAP_BORDER_AIRSPACE_BTN ); MapBorderButtonOn( MAP_BORDER_AIRSPACE_BTN );
MapBorderButtonOff( MAP_BORDER_MOBILE_BTN ); MapBorderButtonOff( MAP_BORDER_MOBILE_BTN );
MapBorderButtonOff( MAP_BORDER_DISEASE_BTN ); MapBorderButtonOff( MAP_BORDER_DISEASE_BTN );
MapBorderButtonOff( MAP_BORDER_WEATHER_BTN ); MapBorderButtonOff( MAP_BORDER_WEATHER_BTN );
// Turn off towns & mines (mostly because town/mine names overlap SAM site names) // Turn off towns & mines (mostly because town/mine names overlap SAM site names)
if( fShowTownFlag == TRUE ) if( fShowTownFlag )
{ {
fShowTownFlag = FALSE; fShowTownFlag = FALSE;
MapBorderButtonOff( MAP_BORDER_TOWN_BTN ); MapBorderButtonOff( MAP_BORDER_TOWN_BTN );
} }
if( fShowMineFlag == TRUE ) if( fShowMineFlag )
{ {
fShowMineFlag = FALSE; fShowMineFlag = FALSE;
MapBorderButtonOff( MAP_BORDER_MINE_BTN ); MapBorderButtonOff( MAP_BORDER_MINE_BTN );
@@ -1044,7 +1047,7 @@ void TurnOnAirSpaceMode( void )
*/ */
// Turn off items // Turn off items
if( fShowItemsFlag == TRUE ) if( fShowItemsFlag )
{ {
fShowItemsFlag = FALSE; fShowItemsFlag = FALSE;
MapBorderButtonOff( MAP_BORDER_ITEM_BTN ); MapBorderButtonOff( MAP_BORDER_ITEM_BTN );
@@ -1390,6 +1393,7 @@ void InitializeMapBorderButtonStates( void )
switch ( gusMapDisplayColourMode ) switch ( gusMapDisplayColourMode )
{ {
case MAP_DISPLAY_AIRSPACE: case MAP_DISPLAY_AIRSPACE:
case MAP_DISPLAY_AIRSPACE_COLOURED_SAMS:
MapBorderButtonOn( MAP_BORDER_AIRSPACE_BTN ); MapBorderButtonOn( MAP_BORDER_AIRSPACE_BTN );
MapBorderButtonOff( MAP_BORDER_MOBILE_BTN ); MapBorderButtonOff( MAP_BORDER_MOBILE_BTN );
MapBorderButtonOff( MAP_BORDER_DISEASE_BTN ); MapBorderButtonOff( MAP_BORDER_DISEASE_BTN );
+1
View File
@@ -56,6 +56,7 @@ enum
{ {
MAP_DISPLAY_NORMAL, MAP_DISPLAY_NORMAL,
MAP_DISPLAY_AIRSPACE, MAP_DISPLAY_AIRSPACE,
MAP_DISPLAY_AIRSPACE_COLOURED_SAMS,
MAP_DISPLAY_MOBILEMILITIARESTRICTIONS, MAP_DISPLAY_MOBILEMILITIARESTRICTIONS,
MAP_DISPLAY_DISEASE, MAP_DISPLAY_DISEASE,
MAP_DISPLAY_WEATHER, MAP_DISPLAY_WEATHER,
+114 -31
View File
@@ -693,7 +693,6 @@ void HandleShowingOfEnemiesWithMilitiaOn( void )
} }
} }
UINT32 DrawMap( void ) UINT32 DrawMap( void )
{ {
HVSURFACE hSrcVSurface; HVSURFACE hSrcVSurface;
@@ -731,6 +730,11 @@ UINT32 DrawMap( void )
UnLockVideoSurface( guiBIGMAP ); UnLockVideoSurface( guiBIGMAP );
UnLockVideoSurface( guiSAVEBUFFER ); UnLockVideoSurface( guiSAVEBUFFER );
// draw SAM sites
//ShowSAMSitesOnStrategicMap( );
//UpdateAirspaceControl();
if ( !iCurrentMapSectorZ ) if ( !iCurrentMapSectorZ )
{ {
// shade map sectors (must be done after Tixa/Orta/Mine icons have been blitted, but before icons!) // shade map sectors (must be done after Tixa/Orta/Mine icons have been blitted, but before icons!)
@@ -744,41 +748,98 @@ UINT32 DrawMap( void )
switch ( gusMapDisplayColourMode ) switch ( gusMapDisplayColourMode )
{ {
case MAP_DISPLAY_AIRSPACE: case MAP_DISPLAY_AIRSPACE:
if ( GetSectorFlagStatus( cnt, cnt2, (UINT8)iCurrentMapSectorZ, SF_ALREADY_VISITED ) == FALSE )
{ {
if ( StrategicMap[cnt + cnt2 * WORLD_MAP_X].usAirType == AIRSPACE_PLAYER_ACTIVE ) BOOLEAN fAlreadyVisited = GetSectorFlagStatus( cnt, cnt2, (UINT8)iCurrentMapSectorZ, SF_ALREADY_VISITED );
if ( StrategicMap[cnt + cnt2 * WORLD_MAP_X].usAirType & AIRSPACE_PLAYER_ACTIVE )
{ {
// sector not visited but air controlled if ( StrategicMap[cnt + cnt2 * WORLD_MAP_X].usAirType & AIRSPACE_ENEMY_ACTIVE )
ShadeMapElem( cnt, cnt2, MAP_SHADE_DK_GREEN ); {
// sector not visited and not air controlled
ShadeMapElem( cnt, cnt2, fAlreadyVisited ? MAP_SHADE_LT_YELLOW : MAP_SHADE_DK_YELLOW );
}
else
{
// sector not visited but air controlled
ShadeMapElem( cnt, cnt2, fAlreadyVisited ? MAP_SHADE_LT_GREEN : MAP_SHADE_DK_GREEN );
}
} }
else if ( StrategicMap[cnt + cnt2 * WORLD_MAP_X].usAirType == AIRSPACE_ENEMY_ACTIVE ) else if ( StrategicMap[cnt + cnt2 * WORLD_MAP_X].usAirType & AIRSPACE_ENEMY_ACTIVE )
{ {
// sector not visited and not air controlled // sector not visited and not air controlled
ShadeMapElem( cnt, cnt2, MAP_SHADE_DK_RED ); ShadeMapElem( cnt, cnt2, fAlreadyVisited ? MAP_SHADE_LT_RED : MAP_SHADE_DK_RED );
} }
else else
{ {
// sector not visited, currently nobody controls the airspace // sector not visited, currently nobody controls the airspace
ShadeMapElem( cnt, cnt2, MAP_SHADE_MD_BLUE ); //ShadeMapElem( cnt, cnt2, fAlreadyVisited ? MAP_SHADE_LT_BLUE : MAP_SHADE_MD_BLUE );
} }
} }
else break;
case MAP_DISPLAY_AIRSPACE_COLOURED_SAMS:
{ {
if ( StrategicMap[cnt + cnt2 * WORLD_MAP_X].usAirType == AIRSPACE_PLAYER_ACTIVE ) CHAR16 sString[20];
swprintf( sString, L"%d", ubSAMControlledSectors[cnt2][cnt] );
BOOLEAN a = FALSE;
BOOLEAN b = FALSE;
BOOLEAN c = FALSE;
BOOLEAN d = FALSE;
{ {
// sector visited and air controlled for ( int i = 0; i < NUMBER_OF_SAMS; ++i )
ShadeMapElem( cnt, cnt2, MAP_SHADE_LT_GREEN ); {
} BOOLEAN samworking = FALSE;
else if ( StrategicMap[cnt + cnt2 * WORLD_MAP_X].usAirType == AIRSPACE_ENEMY_ACTIVE ) if ( DoesSamCoverSector( i, SECTOR( cnt, cnt2 ), &samworking ) && samworking )
{ {
// sector visited but not air controlled if ( i == 0 ) a = TRUE;
ShadeMapElem( cnt, cnt2, MAP_SHADE_LT_RED ); if ( i == 1 ) b = TRUE;
} if ( i == 2 ) c = TRUE;
else if ( i == 3 ) d = TRUE;
{ }
// sector visited, currently nobody controls the airspace }
ShadeMapElem( cnt, cnt2, MAP_SHADE_LT_BLUE );
} }
if ( a && !b && !c && !d)
ShadeMapElem( cnt, cnt2, MAP_SHADE_MIX_RED );
else if ( !a && b && !c && !d )
ShadeMapElem( cnt, cnt2, MAP_SHADE_MIX_GREEN );
else if ( !a && !b && c && !d )
ShadeMapElem( cnt, cnt2, MAP_SHADE_MIX_BLUE );
else if ( !a && !b && !c && d )
ShadeMapElem( cnt, cnt2, MAP_SHADE_MIX_YELLOW );
else if ( a && b && !c && !d )
ShadeMapElem( cnt, cnt2, MAP_SHADE_MIX_RED_GREEN );
else if ( a && !b && c && !d )
ShadeMapElem( cnt, cnt2, MAP_SHADE_MIX_RED_BLUE );
else if ( a && !b && !c && d )
ShadeMapElem( cnt, cnt2, MAP_SHADE_MIX_RED_YELLOW );
else if ( !a && b && c && !d )
ShadeMapElem( cnt, cnt2, MAP_SHADE_MIX_GREEN_BLUE );
else if ( !a && b && !c && d )
ShadeMapElem( cnt, cnt2, MAP_SHADE_MIX_GREEN_YELLOW );
else if ( !a && !b && c && d )
ShadeMapElem( cnt, cnt2, MAP_SHADE_MIX_BLUE_YELLOW );
else if ( a && b && c && !d )
ShadeMapElem( cnt, cnt2, MAP_SHADE_MIX_RED_GREEN_BLUE );
else if ( a && b && !c && d )
ShadeMapElem( cnt, cnt2, MAP_SHADE_MIX_RED_GREEN_YELLOW );
else if ( a && !b && c && d )
ShadeMapElem( cnt, cnt2, MAP_SHADE_MIX_RED_BLUE_YELLOW );
else if ( !a && b && c && d )
ShadeMapElem( cnt, cnt2, MAP_SHADE_MIX_GREEN_BLUE_YELLOW );
else if ( a && b && c && d )
ShadeMapElem( cnt, cnt2, MAP_SHADE_MIX_RED_GREEN_BLUE_YELLOW );
INT16 sXCorner = (INT16)(MAP_VIEW_START_X + (cnt * MAP_GRID_X));
INT16 sYCorner = (INT16)(MAP_VIEW_START_Y + (cnt2 * MAP_GRID_Y));
INT16 usXPos, usYPos;
FindFontCenterCoordinates( sXCorner, sYCorner, MAP_GRID_X, MAP_GRID_Y, sString, FONT14ARIAL, &usXPos, &usYPos );
gprintfdirty( usXPos, usYPos, sString );
mprintf( usXPos, usYPos, sString );
} }
break; break;
@@ -905,7 +966,7 @@ UINT32 DrawMap( void )
DrawTownMilitiaForcesOnMap( ); DrawTownMilitiaForcesOnMap( );
} }
if ( gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE && !gfInChangeArrivalSectorMode ) if ( ( gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE || gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE_COLOURED_SAMS ) && !gfInChangeArrivalSectorMode )
{ {
DrawBullseye(); DrawBullseye();
} }
@@ -1172,7 +1233,7 @@ INT32 ShowAssignedTeam(INT16 sMapX, INT16 sMapY, INT32 iCount)
( !PlayerIDGroupInMotion( pSoldier->ubGroupID ) ) ) ( !PlayerIDGroupInMotion( pSoldier->ubGroupID ) ) )
{ {
// skip mercs inside the helicopter if we're showing airspace level - they show up inside chopper icon instead // skip mercs inside the helicopter if we're showing airspace level - they show up inside chopper icon instead
if ( gusMapDisplayColourMode != MAP_DISPLAY_AIRSPACE || (pSoldier->bAssignment != VEHICLE) || (pSoldier->iVehicleId != iHelicopterVehicleId) ) if ( (gusMapDisplayColourMode != MAP_DISPLAY_AIRSPACE && gusMapDisplayColourMode != MAP_DISPLAY_AIRSPACE_COLOURED_SAMS) || (pSoldier->bAssignment != VEHICLE) || (pSoldier->iVehicleId != iHelicopterVehicleId) )
{ {
++sNumberOfAssigned; ++sNumberOfAssigned;
} }
@@ -1578,6 +1639,28 @@ BOOLEAN InitializePalettesForMap( void )
pMapPalette[MAP_SHADE_LT_PINK] = Create16BPPPaletteShaded( pPalette, 200, 40, 175, TRUE ); pMapPalette[MAP_SHADE_LT_PINK] = Create16BPPPaletteShaded( pPalette, 200, 40, 175, TRUE );
pMapPalette[MAP_SHADE_ORANGE] = Create16BPPPaletteShaded( pPalette, 255, 127, 40, TRUE ); pMapPalette[MAP_SHADE_ORANGE] = Create16BPPPaletteShaded( pPalette, 255, 127, 40, TRUE );
pMapPalette[MAP_SHADE_MIX_RED] = Create16BPPPaletteShaded( pPalette, 400, 0, 0, TRUE );
pMapPalette[MAP_SHADE_MIX_GREEN] = Create16BPPPaletteShaded( pPalette, 0, 400, 0, TRUE );
pMapPalette[MAP_SHADE_MIX_BLUE] = Create16BPPPaletteShaded( pPalette, 0, 0, 400, TRUE );
pMapPalette[MAP_SHADE_MIX_YELLOW] = Create16BPPPaletteShaded( pPalette, 200, 200, 0, TRUE );
pMapPalette[MAP_SHADE_MIX_RED_GREEN] = Create16BPPPaletteShaded( pPalette, 200, 200, 0, TRUE );
pMapPalette[MAP_SHADE_MIX_RED_BLUE] = Create16BPPPaletteShaded( pPalette, 200, 0, 200, TRUE );
pMapPalette[MAP_SHADE_MIX_RED_YELLOW] = Create16BPPPaletteShaded( pPalette, 300, 100, 0, TRUE );
pMapPalette[MAP_SHADE_MIX_GREEN_BLUE] = Create16BPPPaletteShaded( pPalette, 0, 200, 200, TRUE );
pMapPalette[MAP_SHADE_MIX_GREEN_YELLOW] = Create16BPPPaletteShaded( pPalette, 100, 300, 0, TRUE );
pMapPalette[MAP_SHADE_MIX_BLUE_YELLOW] = Create16BPPPaletteShaded( pPalette, 100, 100, 200, TRUE );
pMapPalette[MAP_SHADE_MIX_RED_GREEN_BLUE] = Create16BPPPaletteShaded( pPalette, 133, 133, 133, TRUE );
pMapPalette[MAP_SHADE_MIX_RED_GREEN_YELLOW] = Create16BPPPaletteShaded( pPalette, 200, 200, 0, TRUE );
pMapPalette[MAP_SHADE_MIX_RED_BLUE_YELLOW] = Create16BPPPaletteShaded( pPalette, 200, 66, 133, TRUE );
pMapPalette[MAP_SHADE_MIX_GREEN_BLUE_YELLOW] = Create16BPPPaletteShaded( pPalette, 66, 200, 133, TRUE );
pMapPalette[MAP_SHADE_MIX_RED_GREEN_BLUE_YELLOW] = Create16BPPPaletteShaded( pPalette, 150, 150, 100, TRUE );
// delete image // delete image
DeleteVideoSurfaceFromIndex(uiTempMap); DeleteVideoSurfaceFromIndex(uiTempMap);
@@ -2007,7 +2090,7 @@ void PlotPathForHelicopter( INT16 sX, INT16 sY )
// will plot the path for the helicopter // will plot the path for the helicopter
// no heli...go back // no heli...go back
if ( gusMapDisplayColourMode != MAP_DISPLAY_AIRSPACE || !fHelicopterAvailable ) if ( (gusMapDisplayColourMode != MAP_DISPLAY_AIRSPACE && gusMapDisplayColourMode != MAP_DISPLAY_AIRSPACE_COLOURED_SAMS) || !fHelicopterAvailable )
{ {
return; return;
} }
@@ -2943,9 +3026,9 @@ void DisplayThePotentialPathForHelicopter(INT16 sMapX, INT16 sMapY )
static INT16 sOldMapX, sOldMapY; static INT16 sOldMapX, sOldMapY;
INT32 iDifference = 0; INT32 iDifference = 0;
if ( fOldShowAirCraft != (gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE) ) if ( fOldShowAirCraft != (gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE || gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE_COLOURED_SAMS) )
{ {
fOldShowAirCraft = (gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE); fOldShowAirCraft = (gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE || gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE_COLOURED_SAMS);
giPotHeliPathBaseTime = GetJA2Clock( ); giPotHeliPathBaseTime = GetJA2Clock( );
sOldMapX = sMapX; sOldMapX = sMapX;
@@ -4396,7 +4479,7 @@ BOOLEAN CheckForClickOverHelicopterIcon( INT16 sClickedSectorX, INT16 sClickedSe
fIgnoreClick = TRUE; fIgnoreClick = TRUE;
} }
if ( !fHelicopterAvailable || gusMapDisplayColourMode != MAP_DISPLAY_AIRSPACE ) if ( !fHelicopterAvailable || (gusMapDisplayColourMode != MAP_DISPLAY_AIRSPACE && gusMapDisplayColourMode != MAP_DISPLAY_AIRSPACE_COLOURED_SAMS) )
{ {
return( FALSE ); return( FALSE );
} }
@@ -6813,7 +6896,7 @@ void ShowSAMSitesOnStrategicMap( void )
INT8 ubVidObjIndex = 0; INT8 ubVidObjIndex = 0;
CHAR16 wString[ 40 ]; CHAR16 wString[ 40 ];
if ( gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE ) if ( gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE || gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE_COLOURED_SAMS )
{ {
BlitSAMGridMarkers( ); BlitSAMGridMarkers( );
} }
@@ -6843,7 +6926,7 @@ void ShowSAMSitesOnStrategicMap( void )
GetVideoObject( &hHandle, guiSAMICON); GetVideoObject( &hHandle, guiSAMICON);
BltVideoObject( guiSAVEBUFFER, hHandle, ubVidObjIndex, sIconX, sIconY, VO_BLT_SRCTRANSPARENCY, NULL ); BltVideoObject( guiSAVEBUFFER, hHandle, ubVidObjIndex, sIconX, sIconY, VO_BLT_SRCTRANSPARENCY, NULL );
if ( gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE ) if ( gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE || gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE_COLOURED_SAMS )
{ {
// write "SAM Site" centered underneath // write "SAM Site" centered underneath
@@ -6911,7 +6994,7 @@ void ShowSAMSitesOnStrategicMap( void )
sX += 5; sX += 5;
sY += 3; sY += 3;
if ( gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE ) if ( gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE || gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE_COLOURED_SAMS )
{ {
// write "Refuel Site" centered underneath // write "Refuel Site" centered underneath
+23
View File
@@ -61,6 +61,29 @@ enum{
MAP_SHADE_ORANGE, MAP_SHADE_ORANGE,
// Flugente: more colours
MAP_SHADE_MIX_RED,
MAP_SHADE_MIX_GREEN,
MAP_SHADE_MIX_BLUE,
MAP_SHADE_MIX_YELLOW,
MAP_SHADE_MIX_RED_GREEN,
MAP_SHADE_MIX_RED_BLUE,
MAP_SHADE_MIX_RED_YELLOW,
MAP_SHADE_MIX_GREEN_BLUE,
MAP_SHADE_MIX_GREEN_YELLOW,
MAP_SHADE_MIX_BLUE_YELLOW,
MAP_SHADE_MIX_RED_GREEN_BLUE,
MAP_SHADE_MIX_RED_GREEN_YELLOW,
MAP_SHADE_MIX_RED_BLUE_YELLOW,
MAP_SHADE_MIX_GREEN_BLUE_YELLOW,
MAP_SHADE_MIX_RED_GREEN_BLUE_YELLOW,
MAP_SHADE_MAX, MAP_SHADE_MAX,
}; };
@@ -949,6 +949,21 @@ void AddCommonInfoToBox(void)
} }
AddSecondColumnMonoString( &hStringHandle, wString ); AddSecondColumnMonoString( &hStringHandle, wString );
// Flugente: if this is a SAM site we know about, display (hack-)status
for ( UINT16 x = 0; x < MAX_NUMBER_OF_SAMS; ++x )
{
if ( pSamList[x] == usSectorValue && fSamSiteFound[x] )
{
swprintf( wString, pwMiscSectorStrings[7] );
AddMonoString( &hStringHandle, wString );
swprintf( wString, L"%d / %d", StrategicMap[SECTOR_INFO_TO_STRATEGIC_INDEX( usSectorValue )].bSAMCondition, StrategicMap[SECTOR_INFO_TO_STRATEGIC_INDEX( usSectorValue )].sSamHackStatus );
AddSecondColumnMonoString( &hStringHandle, wString );
break;
}
}
} }
+1 -1
View File
@@ -6659,7 +6659,7 @@ void TurnOnSectorLocator( UINT8 ubProfileID )
{ {
// if helicopter position is being shown, don't do this, too, cause the helicopter icon is on top and it looks // if helicopter position is being shown, don't do this, too, cause the helicopter icon is on top and it looks
// like crap. I tried moving the heli icon blit to before, but that screws up it's blitting. // like crap. I tried moving the heli icon blit to before, but that screws up it's blitting.
if ( gusMapDisplayColourMode != MAP_DISPLAY_AIRSPACE ) if ( gusMapDisplayColourMode != MAP_DISPLAY_AIRSPACE && gusMapDisplayColourMode != MAP_DISPLAY_AIRSPACE_COLOURED_SAMS )
{ {
// can't use his profile, he's where his chopper is // can't use his profile, he's where his chopper is
Assert( iHelicopterVehicleId != -1 ); Assert( iHelicopterVehicleId != -1 );
+1
View File
@@ -2251,6 +2251,7 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Strategic5");
if( IsThisSectorASAMSector( pGroup->ubSectorX, pGroup->ubSectorY, 0 ) ) if( IsThisSectorASAMSector( pGroup->ubSectorX, pGroup->ubSectorY, 0 ) )
{ {
StrategicMap[ pGroup->ubSectorX + pGroup->ubSectorY * MAP_WORLD_X ].bSAMCondition = 100; StrategicMap[ pGroup->ubSectorX + pGroup->ubSectorY * MAP_WORLD_X ].bSAMCondition = 100;
StrategicMap[ pGroup->ubSectorX + pGroup->ubSectorY * MAP_WORLD_X ].sSamHackStatus = 100;
StrategicMap[ pGroup->ubSectorX + pGroup->ubSectorY * MAP_WORLD_X ].usFlags &= ~SAMSITE_REPAIR_ORDERED; StrategicMap[ pGroup->ubSectorX + pGroup->ubSectorY * MAP_WORLD_X ].usFlags &= ~SAMSITE_REPAIR_ORDERED;
UpdateSAMDoneRepair( pGroup->ubSectorX, pGroup->ubSectorY, 0 ); UpdateSAMDoneRepair( pGroup->ubSectorX, pGroup->ubSectorY, 0 );
+1 -1
View File
@@ -3806,7 +3806,7 @@ BOOLEAN PlayersBetweenTheseSectors( INT16 sSource, INT16 sDest, INT32 *iCountEnt
// if this group is aboard the helicopter and we're showing the airspace layer, don't count any mercs aboard the // if this group is aboard the helicopter and we're showing the airspace layer, don't count any mercs aboard the
// chopper, because the chopper icon itself serves the function of showing the location/size of this group // chopper, because the chopper icon itself serves the function of showing the location/size of this group
if ( !fHelicopterGroup || gusMapDisplayColourMode != MAP_DISPLAY_AIRSPACE ) if ( !fHelicopterGroup || !(gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE || gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE_COLOURED_SAMS) )
{ {
// if only showing retreat paths, ignore groups not in the battle sector // if only showing retreat paths, ignore groups not in the battle sector
// if NOT showing retreat paths, ignore groups not between sectors // if NOT showing retreat paths, ignore groups not between sectors
+1 -1
View File
@@ -335,7 +335,7 @@ INT32 FindStratPath(INT16 sStart, INT16 sDestination, INT16 sMvtGroupNumber, BOO
{ {
// is a heli, its pathing is determined not by time (it's always the same) but by total cost // is a heli, its pathing is determined not by time (it's always the same) but by total cost
// Skyrider will avoid uncontrolled airspace as much as possible... // Skyrider will avoid uncontrolled airspace as much as possible...
if ( StrategicMap[curLoc].usAirType == AIRSPACE_ENEMY_ACTIVE ) if ( StrategicMap[curLoc].usAirType & AIRSPACE_ENEMY_ACTIVE )
{ {
nextCost = COST_AIRSPACE_UNSAFE; nextCost = COST_AIRSPACE_UNSAFE;
} }
+12 -18
View File
@@ -5641,14 +5641,14 @@ UINT32 MapScreenHandle(void)
// if heli is around, show it // if heli is around, show it
if ( fHelicopterAvailable && (gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE || fShowTeamFlag) && (iCurrentMapSectorZ == 0) && !fShowMapInventoryPool ) if ( fHelicopterAvailable && ( (gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE || gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE_COLOURED_SAMS) || fShowTeamFlag) && (iCurrentMapSectorZ == 0) && !fShowMapInventoryPool )
{ {
// this is done on EVERY frame, I guess it beats setting entire map dirty all the time while he's moving... // this is done on EVERY frame, I guess it beats setting entire map dirty all the time while he's moving...
DisplayPositionOfHelicopter( ); DisplayPositionOfHelicopter( );
} }
// Flugente: enemy helicopter // Flugente: enemy helicopter
if ( gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE && (iCurrentMapSectorZ == 0) && !fShowMapInventoryPool ) if ( (gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE || gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE_COLOURED_SAMS) && (iCurrentMapSectorZ == 0) && !fShowMapInventoryPool )
{ {
DisplayPositionOfEnemyHelicopter(); DisplayPositionOfEnemyHelicopter();
} }
@@ -6625,7 +6625,7 @@ UINT32 HandleMapUI( )
if( SectorInfo[ ( SECTOR( sMapX, sMapY ) ) ].ubTraversability[ THROUGH_STRATEGIC_MOVE ] != GROUNDBARRIER ) if( SectorInfo[ ( SECTOR( sMapX, sMapY ) ) ].ubTraversability[ THROUGH_STRATEGIC_MOVE ] != GROUNDBARRIER )
{ {
// if it's not enemy air controlled // if it's not enemy air controlled
if ( StrategicMap[CALCULATE_STRATEGIC_INDEX( sMapX, sMapY )].usAirType != AIRSPACE_ENEMY_ACTIVE ) if ( !(StrategicMap[CALCULATE_STRATEGIC_INDEX( sMapX, sMapY )].usAirType & AIRSPACE_ENEMY_ACTIVE) )
{ {
CHAR16 sMsgString[ 128 ], sMsgSubString[ 64 ]; CHAR16 sMsgString[ 128 ], sMsgSubString[ 64 ];
@@ -6730,7 +6730,7 @@ UINT32 HandleMapUI( )
// if we're in airspace mode // if we're in airspace mode
if ( gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE ) if ( gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE || gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE_COLOURED_SAMS )
{ {
// if not moving soldiers, and not yet plotting the helicopter // if not moving soldiers, and not yet plotting the helicopter
if ( (bSelectedDestChar == -1) && !fPlotForHelicopter && !fPlotForMilitia ) if ( (bSelectedDestChar == -1) && !fPlotForHelicopter && !fPlotForMilitia )
@@ -11700,7 +11700,7 @@ void PlotTemporaryPaths( void )
{ {
if ( fPlotForHelicopter ) if ( fPlotForHelicopter )
{ {
Assert( gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE ); Assert( gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE || gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE_COLOURED_SAMS );
// plot temp path // plot temp path
PlotATemporaryPathForHelicopter( sMapX, sMapY); PlotATemporaryPathForHelicopter( sMapX, sMapY);
@@ -11979,7 +11979,7 @@ void CheckIfPlottingForCharacterWhileAirCraft( void )
// if the plotting modes are inconsistent, stop plotting // if the plotting modes are inconsistent, stop plotting
BOOLEAN fAbort = FALSE; BOOLEAN fAbort = FALSE;
if ( gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE ) if ( gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE || gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE_COLOURED_SAMS )
{ {
if ( (bSelectedDestChar != -1 || fPlotForMilitia) && !fPlotForHelicopter ) if ( (bSelectedDestChar != -1 || fPlotForMilitia) && !fPlotForHelicopter )
fAbort = TRUE; fAbort = TRUE;
@@ -12762,7 +12762,7 @@ void UpdateCursorIfInLastSector( void )
{ {
GetMouseMapXY(&sMapX, &sMapY); GetMouseMapXY(&sMapX, &sMapY);
if ( gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE ) if ( gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE || gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE_COLOURED_SAMS )
{ {
// check for helicopter // check for helicopter
if ( fPlotForHelicopter ) if ( fPlotForHelicopter )
@@ -14592,7 +14592,6 @@ void CheckForInventoryModeCancellation()
} }
} }
void ChangeSelectedMapSector( INT16 sMapX, INT16 sMapY, INT8 bMapZ ) void ChangeSelectedMapSector( INT16 sMapX, INT16 sMapY, INT8 bMapZ )
{ {
// ignore while map inventory pool is showing, or else items can be replicated, since sector inventory always applies // ignore while map inventory pool is showing, or else items can be replicated, since sector inventory always applies
@@ -14610,13 +14609,12 @@ void ChangeSelectedMapSector( INT16 sMapX, INT16 sMapY, INT8 bMapZ )
if ( ( bMapZ != 0 ) && ( ( bSelectedDestChar != -1 ) || fPlotForHelicopter ) ) if ( ( bMapZ != 0 ) && ( ( bSelectedDestChar != -1 ) || fPlotForHelicopter ) )
return; return;
sSelMapX = sMapX; sSelMapX = sMapX;
sSelMapY = sMapY; sSelMapY = sMapY;
iCurrentMapSectorZ = bMapZ; iCurrentMapSectorZ = bMapZ;
// if going underground while in airspace mode // if going underground while in airspace mode
if ( (bMapZ > 0) && (gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE) ) if ( (bMapZ > 0) && (gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE || gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE_COLOURED_SAMS) )
{ {
// turn off airspace mode // turn off airspace mode
ToggleAirspaceMode( ); ToggleAirspaceMode( );
@@ -14629,8 +14627,6 @@ void ChangeSelectedMapSector( INT16 sMapX, INT16 sMapY, INT8 bMapZ )
fTeamPanelDirty = TRUE; fTeamPanelDirty = TRUE;
} }
BOOLEAN CanChangeDestinationForCharSlot( INT8 bCharNumber, BOOLEAN fShowErrorMessage ) BOOLEAN CanChangeDestinationForCharSlot( INT8 bCharNumber, BOOLEAN fShowErrorMessage )
{ {
SOLDIERTYPE *pSoldier = NULL; SOLDIERTYPE *pSoldier = NULL;
@@ -14786,7 +14782,7 @@ void CancelOrShortenPlottedPath( void )
GetMouseMapXY(&sMapX, &sMapY); GetMouseMapXY(&sMapX, &sMapY);
// check if we are in aircraft mode // check if we are in aircraft mode
if ( gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE ) if ( gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE || gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE_COLOURED_SAMS )
{ {
// check for helicopter path being plotted // check for helicopter path being plotted
if( !fPlotForHelicopter ) if( !fPlotForHelicopter )
@@ -14830,7 +14826,6 @@ void CancelOrShortenPlottedPath( void )
uiReturnValue = ClearPathAfterThisSectorForCharacter( &Menptr[gCharactersList[bSelectedDestChar].usSolID], sMapX, sMapY ); uiReturnValue = ClearPathAfterThisSectorForCharacter( &Menptr[gCharactersList[bSelectedDestChar].usSolID], sMapX, sMapY );
} }
switch ( uiReturnValue ) switch ( uiReturnValue )
{ {
case ABORT_PLOTTING: case ABORT_PLOTTING:
@@ -15312,7 +15307,6 @@ void MakeMapModesSuitableForDestPlotting( INT8 bCharNumber )
{ {
SOLDIERTYPE *pSoldier = NULL; SOLDIERTYPE *pSoldier = NULL;
if( gCharactersList[ bCharNumber ].fValid == TRUE ) if( gCharactersList[ bCharNumber ].fValid == TRUE )
{ {
pSoldier = MercPtrs[ gCharactersList[ bCharNumber ].usSolID ]; pSoldier = MercPtrs[ gCharactersList[ bCharNumber ].usSolID ];
@@ -15323,7 +15317,7 @@ void MakeMapModesSuitableForDestPlotting( INT8 bCharNumber )
if ( ( pSoldier->bAssignment == VEHICLE ) && ( pSoldier->iVehicleId == iHelicopterVehicleId ) ) if ( ( pSoldier->bAssignment == VEHICLE ) && ( pSoldier->iVehicleId == iHelicopterVehicleId ) )
{ {
if ( gusMapDisplayColourMode != MAP_DISPLAY_AIRSPACE ) if ( gusMapDisplayColourMode != MAP_DISPLAY_AIRSPACE && gusMapDisplayColourMode != MAP_DISPLAY_AIRSPACE_COLOURED_SAMS )
{ {
// turn on airspace mode automatically // turn on airspace mode automatically
ToggleAirspaceMode(); ToggleAirspaceMode();
@@ -15331,7 +15325,7 @@ void MakeMapModesSuitableForDestPlotting( INT8 bCharNumber )
} }
else else
{ {
if ( gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE ) if ( gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE || gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE_COLOURED_SAMS )
{ {
// turn off airspace mode automatically // turn off airspace mode automatically
ToggleAirspaceMode(); ToggleAirspaceMode();
@@ -15791,7 +15785,7 @@ void StartChangeSectorArrivalMode( void )
BOOLEAN CanMoveBullseyeAndClickedOnIt( INT16 sMapX, INT16 sMapY ) BOOLEAN CanMoveBullseyeAndClickedOnIt( INT16 sMapX, INT16 sMapY )
{ {
// if in airspace mode, and not plotting paths // if in airspace mode, and not plotting paths
if ( (gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE) && (bSelectedDestChar == -1) && (fPlotForHelicopter == FALSE) ) if ( (gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE || gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE_COLOURED_SAMS) && (bSelectedDestChar == -1) && (fPlotForHelicopter == FALSE) )
{ {
if (is_networked) if (is_networked)
{ {
+6 -11
View File
@@ -5,14 +5,9 @@
#include "mapscreen.h" #include "mapscreen.h"
#include "soldier control.h" #include "soldier control.h"
// different states for airspace control // Flugente: airspace flags
enum #define AIRSPACE_ENEMY_ACTIVE 0x01 //1 // controlled by enemy and active
{ #define AIRSPACE_PLAYER_ACTIVE 0x02 //2 // controlled by enemy and active
AIRSPACE_PLAYER_ACTIVE, // controlled by player and active
AIRSPACE_ENEMY_ACTIVE, // controlled by enemy and active
AIRSPACE_PLAYER_INACTIVE, // controlled by player but not active
AIRSPACE_ENEMY_INACTIVE, // controlled by enemy but not active
};
struct strategicmapelement{ struct strategicmapelement{
UINT8 UNUSEDuiFootEta[4]; // eta/mvt costs for feet UINT8 UNUSEDuiFootEta[4]; // eta/mvt costs for feet
@@ -21,11 +16,11 @@ struct strategicmapelement{
UINT8 uiBadVehicleSector[4]; // blocking mvt from vehicles UINT8 uiBadVehicleSector[4]; // blocking mvt from vehicles
INT8 bNameId; INT8 bNameId;
BOOLEAN fEnemyControlled; // enemy controlled or not BOOLEAN fEnemyControlled; // enemy controlled or not
UINT8 usAirType; UINT8 usAirType; // Flugente: This will now be used as a flagmask
BOOLEAN UNUSEDfLostControlAtSomeTime; BOOLEAN UNUSEDfLostControlAtSomeTime;
INT8 bSAMCondition; // SAM Condition .. 0 - 100, just like an item's status INT8 bSAMCondition; // SAM Condition .. 0 - 100, just like an item's status
INT8 sSamHackStatus; // this status influences a SAM's max radius
INT8 bFillupforPadding[ 3 ]; // necessary for padding INT8 bFillupforPadding[ 2 ]; // necessary for padding
UINT32 usFlags; // Flugente: various flags UINT32 usFlags; // Flugente: various flags
INT8 bPadding[ 20 ]; INT8 bPadding[ 20 ];
}; };
+113 -36
View File
@@ -238,7 +238,7 @@ INT8 gbMercIsNewInThisSector[MAX_NUM_SOLDIERS];
BOOLEAN localizedMapTextOnly; 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 // 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, // 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 ) 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])].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 // 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 ) 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); 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 ) BOOLEAN CanGoToTacticalInSector( INT16 sX, INT16 sY, UINT8 ubZ )
{ {
@@ -5222,47 +5232,40 @@ INT32 SAMSitesUnderPlayerControl( INT16 sX, INT16 sY )
void UpdateAirspaceControl( void ) void UpdateAirspaceControl( void )
{ {
UINT8 ubControllingSAM;
StrategicMapElement *pSAMStrategicMap = NULL; StrategicMapElement *pSAMStrategicMap = NULL;
for ( INT32 iCounterA = 1; iCounterA < (INT32)(MAP_WORLD_X - 1); ++iCounterA ) for ( INT32 iCounterA = 1; iCounterA < (INT32)(MAP_WORLD_X - 1); ++iCounterA )
{ {
for ( INT32 iCounterB = 1; iCounterB < (INT32)(MAP_WORLD_Y - 1); ++iCounterB ) 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 networked, disable SAM airspace restrictions...
if ( is_networked ) if ( is_networked )
{ {
StrategicMap[CALCULATE_STRATEGIC_INDEX( iCounterA, iCounterB )].usAirType = AIRSPACE_ENEMY_INACTIVE;
continue; continue;
} }
// IMPORTANT: B and A are reverse here, since the table is stored transposed for ( int samcnt = 0; samcnt < NUMBER_OF_SAMS; ++samcnt )
ubControllingSAM = ubSAMControlledSectors[iCounterB][iCounterA];
if ( ubControllingSAM >= 1 && ubControllingSAM <= NUMBER_OF_SAMS )
{ {
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 // different status depending on who controls the SAM sector, and whether the SAM is operational
if ( pSAMStrategicMap->fEnemyControlled ) if ( pSAMStrategicMap->fEnemyControlled )
{ {
if ( pSAMStrategicMap->bSAMCondition >= MIN_CONDITION_FOR_SAM_SITE_TO_WORK ) StrategicMap[CALCULATE_STRATEGIC_INDEX( iCounterA, iCounterB )].usAirType |= AIRSPACE_ENEMY_ACTIVE;
StrategicMap[CALCULATE_STRATEGIC_INDEX( iCounterA, iCounterB )].usAirType = AIRSPACE_ENEMY_ACTIVE; }
else else
StrategicMap[CALCULATE_STRATEGIC_INDEX( iCounterA, iCounterB )].usAirType = AIRSPACE_ENEMY_INACTIVE; {
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 // check if currently selected arrival sector still has secure airspace
// if it's not enemy air controlled // 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! // NOPE!
CHAR16 sMsgString[256], sMsgSubString1[64], sMsgSubString2[64]; CHAR16 sMsgString[256], sMsgSubString1[64], sMsgSubString2[64];
@@ -5280,7 +5283,7 @@ void UpdateAirspaceControl( void )
// move the landing zone over to Omerta // move the landing zone over to Omerta
// HEADROCK HAM 3.5: Externalized coordinates // 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; gsMercArriveSectorX = gGameExternalOptions.ubDefaultArrivalSectorX;
gsMercArriveSectorY = gGameExternalOptions.ubDefaultArrivalSectorY; gsMercArriveSectorY = gGameExternalOptions.ubDefaultArrivalSectorY;
@@ -5291,7 +5294,7 @@ void UpdateAirspaceControl( void )
{ {
for ( UINT8 ubSectorY = 1; ubSectorY <= 16; ++ubSectorY ) 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; gsMercArriveSectorX = ubSectorX;
gsMercArriveSectorY = ubSectorY; gsMercArriveSectorY = ubSectorY;
@@ -5324,6 +5327,72 @@ void UpdateAirspaceControl( void )
UpdateRefuelSiteAvailability( ); 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 ) 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 ) if ( StrategicMap[CALCULATE_STRATEGIC_INDEX( sSectorX, sSectorY )].bSAMCondition < MIN_CONDITION_FOR_SAM_SITE_TO_WORK )
{
return(FALSE); return(FALSE);
}
if ( StrategicMap[CALCULATE_STRATEGIC_INDEX( sSectorX, sSectorY )].sSamHackStatus <= 0 )
return(FALSE);
return(TRUE); return(TRUE);
} }
BOOLEAN IsThisSectorASAMSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ ) BOOLEAN IsThisSectorASAMSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ )
{ {
INT32 cnt;
// is the sector above ground? // is the sector above ground?
if ( bSectorZ != 0 ) if ( bSectorZ != 0 )
{ {
return(FALSE); 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]) ) if ( (sSectorX == gpSamSectorX[cnt]) && (sSectorY == gpSamSectorY[cnt]) )
return(TRUE); return(TRUE);
@@ -5447,6 +5515,15 @@ BOOLEAN LoadStrategicInfoFromSavedFile( HWFILE hFile )
StrategicMap[i].usFlags = 0; 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 // Load the Sector Info
uiSize = sizeof(SECTORINFO); uiSize = sizeof(SECTORINFO);
if ( guiCurrentSaveGameVersion < ENEMY_JEEPS ) if ( guiCurrentSaveGameVersion < ENEMY_JEEPS )
+5
View File
@@ -119,8 +119,12 @@ void JumpIntoAdjacentSector( UINT8 ubDirection, UINT8 ubJumpCode, INT32 sAdditio
BOOLEAN CanGoToTacticalInSector( INT16 sX, INT16 sY, UINT8 ubZ ); BOOLEAN CanGoToTacticalInSector( INT16 sX, INT16 sY, UINT8 ubZ );
extern UINT32 ubSAMControlledSectors[MAP_WORLD_Y][MAP_WORLD_X];
void UpdateAirspaceControl( void ); void UpdateAirspaceControl( void );
BOOLEAN DoesSamCoverSector( UINT8 usSam, UINT8 usSector, BOOLEAN* apSamIsWorking = NULL );
BOOLEAN IsThisSectorASAMSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ ); BOOLEAN IsThisSectorASAMSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ );
// init sam sites // init sam sites
@@ -186,6 +190,7 @@ BOOLEAN IsSectorRoad( INT16 sSectorX, INT16 sSectorY ); // added by Flugente
INT32 SAMSitesUnderPlayerControl( INT16 sX, INT16 sY ); INT32 SAMSitesUnderPlayerControl( INT16 sX, INT16 sY );
INT8 GetSAMIdFromSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ ); INT8 GetSAMIdFromSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ );
void SetSamHackStatus( INT16 sSectorX, INT16 sSectorY, INT8 sStatus );
void SetupProfileInsertionDataForSoldier( SOLDIERTYPE *pSoldier ); void SetupProfileInsertionDataForSoldier( SOLDIERTYPE *pSoldier );
+1 -1
View File
@@ -872,7 +872,7 @@ void CheckForValidArrivalSector( )
if( sSectorGridNo2 >=1 && sSectorGridNo2 < ( ( MAP_WORLD_X - 1 ) * ( MAP_WORLD_X - 1 ) ) && sSectorGridNo2 >= leftmost && sSectorGridNo2 < ( leftmost + MAP_WORLD_X ) ) if( sSectorGridNo2 >=1 && sSectorGridNo2 < ( ( MAP_WORLD_X - 1 ) * ( MAP_WORLD_X - 1 ) ) && sSectorGridNo2 >= leftmost && sSectorGridNo2 < ( leftmost + MAP_WORLD_X ) )
{ {
if ( !StrategicMap[ sSectorGridNo2 ].fEnemyControlled && !StrategicMap[ sSectorGridNo2 ].usAirType != AIRSPACE_ENEMY_ACTIVE ) if ( !StrategicMap[ sSectorGridNo2 ].fEnemyControlled && (StrategicMap[ sSectorGridNo2 ].usAirType & AIRSPACE_ENEMY_ACTIVE) )
{ {
uiRange = StrategicPythSpacesAway( sSectorGridNo2, sSectorGridNo ); uiRange = StrategicPythSpacesAway( sSectorGridNo2, sSectorGridNo );
+2
View File
@@ -4227,9 +4227,11 @@ STR16 pwMiscSectorStrings[] =
L"分区", L"分区",
L"物品数量", L"物品数量",
L"未知", L"未知",
L"已占领", L"已占领",
L"", L"",
L"", L"",
L"Status/Software status:", // TODO.Translate
}; };
// error strings for inventory // error strings for inventory
+2
View File
@@ -4229,9 +4229,11 @@ STR16 pwMiscSectorStrings[] =
L"Sector", L"Sector",
L"# Items", L"# Items",
L"Onbekend", L"Onbekend",
L"Gecontrolleerd", L"Gecontrolleerd",
L"Ja", L"Ja",
L"Nee", L"Nee",
L"Status/Software status:", // TODO.Translate
}; };
// error strings for inventory // error strings for inventory
+2
View File
@@ -4227,9 +4227,11 @@ STR16 pwMiscSectorStrings[] =
L"Sector", L"Sector",
L"# of Items", L"# of Items",
L"Unknown", L"Unknown",
L"Controlled", L"Controlled",
L"Yes", L"Yes",
L"No", L"No",
L"Status/Software status:",
}; };
// error strings for inventory // error strings for inventory
+2
View File
@@ -4233,9 +4233,11 @@ STR16 pwMiscSectorStrings[] =
L"Secteur ", L"Secteur ",
L"Nombre d'objets ", L"Nombre d'objets ",
L"Inconnu", L"Inconnu",
L"Contrôlé ", L"Contrôlé ",
L"Oui", L"Oui",
L"Non", L"Non",
L"Status/Software status:", // TODO.Translate
}; };
// error strings for inventory // error strings for inventory
+2
View File
@@ -4225,9 +4225,11 @@ STR16 pwMiscSectorStrings[] =
L"Sektor", L"Sektor",
L"# der Gegenstände", L"# der Gegenstände",
L"Unbekannt", L"Unbekannt",
L"Kontrolliert", L"Kontrolliert",
L"Ja", L"Ja",
L"Nein", L"Nein",
L"Status/Software Status:",
}; };
// error strings for inventory // error strings for inventory
+2
View File
@@ -4223,9 +4223,11 @@ STR16 pwMiscSectorStrings[] =
L"Settore", L"Settore",
L"# di oggetti", L"# di oggetti",
L"Sconosciuto", L"Sconosciuto",
L"Controllato", L"Controllato",
L"", L"",
L"No", L"No",
L"Status/Software status:", // TODO.Translate
}; };
// error strings for inventory // error strings for inventory
+2
View File
@@ -4234,9 +4234,11 @@ STR16 pwMiscSectorStrings[] =
L"Sektor", L"Sektor",
L"Przedmiotów", L"Przedmiotów",
L"Nieznane", L"Nieznane",
L"Pod kontrolą", L"Pod kontrolą",
L"Tak", L"Tak",
L"Nie", L"Nie",
L"Status/Software status:", // TODO.Translate
}; };
// error strings for inventory // error strings for inventory
+2
View File
@@ -4227,9 +4227,11 @@ STR16 pwMiscSectorStrings[] =
L"Сектор", L"Сектор",
L"Количество предметов", L"Количество предметов",
L"Неизвестно", L"Неизвестно",
L"Под контролем", L"Под контролем",
L"Да", L"Да",
L"Нет", L"Нет",
L"Status/Software status:", // TODO.Translate
}; };
// error strings for inventory // error strings for inventory