Files
source/TileEngine/Tactical Placement GUI.cpp
T
2022-11-04 22:32:23 -07:00

1871 lines
65 KiB
C++

#include "builddefines.h"
// WANNE 2 <changed some lines>
#ifdef PRECOMPILEDHEADERS
#include "TileEngine All.h"
#include "PreBattle Interface.h"
#include "vehicles.h"
#else
//sgp
#include "english.h"
#include "debug.h"
#include "video.h"
#include "vobject_blitters.h"
#include "line.h"
//ja2
#include "Tactical Placement GUI.h"
#include "Overhead Map.h"
#include "strategicmap.h"
#include "Interface.h"
#include "overhead.h"
#include "Render Dirty.h"
#include "sysutil.h"
#include "PreBattle Interface.h"
#include "Soldier Profile.h"
#include "Map Edgepoints.h"
#include "gameloop.h"
#include "message.h"
#include "Map Information.h"
#include "Soldier Add.h"
#include "cursors.h"
#include "Cursor Control.h"
#include "MessageBoxScreen.h"
#include "text.h"
#include "WordWrap.h"
#include "Game Clock.h"
#include "Isometric Utils.h"
#endif
#include "connect.h"
#include "renderworld.h"//dnl ch45 051009
#include "merc entering.h"
#include "CampaignStats.h" // added by Flugente
#include "Rebel Command.h"
typedef struct MERCPLACEMENT
{
SOLDIERTYPE *pSoldier;
UINT32 uiVObjectID;
MOUSE_REGION region;
UINT8 ubStrategicInsertionCode;
BOOLEAN fPlaced;
}MERCPLACEMENT;
MERCPLACEMENT *gMercPlacement = NULL;
enum
{
DONE_BUTTON,
SPREAD_BUTTON,
GROUP_BUTTON,
CLEAR_BUTTON,
NUM_TP_BUTTONS
};
UINT32 iTPButtons[ NUM_TP_BUTTONS ];
//dnl ch45 051009
#define PLACEMENT_OFFSET 150
extern INT32 giXA, giYA;
extern BOOLEAN gfOverheadMapDirty;
extern BOOLEAN GetOverheadMouseGridNo( INT32 *psGridNo );
extern UINT16 iOffsetHorizontal;
extern UINT16 iOffsetVertical;
int islocked;
UINT8 gubDefaultButton = CLEAR_BUTTON;
BOOLEAN gfTacticalPlacementGUIActive = FALSE;
BOOLEAN gfTacticalPlacementFirstTime = FALSE;
BOOLEAN gfEnterTacticalPlacementGUI = FALSE;
BOOLEAN gfKillTacticalGUI = FALSE;
INT32 giOverheadPanelImage = 0;
INT32 giOverheadButtonImages[ NUM_TP_BUTTONS ];
INT32 giMercPanelImage = 0;
INT32 giPlacements = 0;
BOOLEAN gfTacticalPlacementGUIDirty = FALSE;
BOOLEAN gfValidLocationsChanged = FALSE;
SGPRect gTPClipRect = {0,0,0,0};
// WANNE - MP: Center
SGPRect gTPClipRectCenterLeft = {0,0,0,0};
SGPRect gTPClipRectCenterTop = {0,0,0,0};
SGPRect gTPClipRectCenterRight = {0,0,0,0};
SGPRect gTPClipRectCenterBottom = {0,0,0,0};
BOOLEAN gfValidCursor = FALSE;
BOOLEAN gfEveryonePlaced = FALSE;
UINT8 gubSelectedGroupID = 0;
UINT8 gubHilightedGroupID = 0;
UINT8 gubCursorGroupID = 0;
INT8 gbSelectedMercID = -1;
INT8 gbHilightedMercID = -1;
INT8 gbCursorMercID = -1;
SOLDIERTYPE *gpTacticalPlacementSelectedSoldier = NULL;
SOLDIERTYPE *gpTacticalPlacementHilightedSoldier = NULL;
// WANNE - MP: Center
BOOLEAN gfCenter;
extern BOOLEAN GetOverheadScreenXYFromGridNo( INT32 sGridNo, INT16* psScreenX, INT16* psScreenY );
void DoneOverheadPlacementClickCallback( GUI_BUTTON *btn, INT32 reason );
void SpreadPlacementsCallback ( GUI_BUTTON *btn, INT32 reason );
void GroupPlacementsCallback( GUI_BUTTON *btn, INT32 reason );
void ClearPlacementsCallback( GUI_BUTTON *btn, INT32 reason );
void MercMoveCallback( MOUSE_REGION *reg, INT32 reason );
void MercClickCallback( MOUSE_REGION *reg, INT32 reason );
void PlaceMercs();
void FastHelpRemovedCallback();
void FastHelpRemoved2Callback();
void DialogRemoved( UINT8 ubResult );
void PutDownMercPiece( INT32 iPlacement );
void PickUpMercPiece( INT32 iPlacement );
void SetCursorMerc( INT8 bPlacementID );
void SelectNextUnplacedUnit();
// WANNE: Made methods available for Release build, because we need them in multiplayer
//#ifdef JA2BETAVERSION
BOOLEAN gfNorthValid, gfEastValid, gfSouthValid, gfWestValid;
BOOLEAN gfChangedEntrySide = FALSE;
void FindValidInsertionCode( UINT8 *pubStrategicInsertionCode )
{
if( gMapInformation.sNorthGridNo == -1 &&
gMapInformation.sEastGridNo == -1 &&
gMapInformation.sSouthGridNo == -1 &&
gMapInformation.sWestGridNo == -1 )
{
AssertMsg( 0, "Map has no entry points at all. Can't generate edge points. LC:1" );
}
if( gMapInformation.sNorthGridNo != -1 && !gps1stNorthEdgepointArray ||
gMapInformation.sEastGridNo != -1 && !gps1stEastEdgepointArray ||
gMapInformation.sSouthGridNo != -1 && !gps1stSouthEdgepointArray ||
gMapInformation.sWestGridNo != -1 && !gps1stWestEdgepointArray )
{
InvalidateScreen();
DrawTextToScreen( L"Map doesn't has entrypoints without corresponding edgepoints. LC:1",
iOffsetHorizontal + 30, iOffsetVertical + 150, 600, FONT10ARIALBOLD, FONT_RED, FONT_MCOLOR_BLACK, TRUE, LEFT_JUSTIFIED );
DrawTextToScreen( L"GENERATING MAP EDGEPOINTS! Please wait...",
iOffsetHorizontal + 30, iOffsetVertical + 160, 600, FONT10ARIALBOLD, FONT_YELLOW, FONT_MCOLOR_BLACK, TRUE, LEFT_JUSTIFIED );
RefreshScreen( NULL );
GenerateMapEdgepoints(TRUE);//dnl ch43 290909
switch( *pubStrategicInsertionCode )
{
case INSERTION_CODE_NORTH:
if( !gps1stNorthEdgepointArray )
AssertMsg( 0, "Map Edgepoint generation failed. KM : 0 -- send map" );
break;
case INSERTION_CODE_EAST:
if( !gps1stEastEdgepointArray )
AssertMsg( 0, "Map Edgepoint generation failed. KM : 0 -- send map" );
break;
case INSERTION_CODE_SOUTH:
if( !gps1stSouthEdgepointArray )
AssertMsg( 0, "Map Edgepoint generation failed. KM : 0 -- send map" );
break;
case INSERTION_CODE_WEST:
if( !gps1stWestEdgepointArray )
AssertMsg( 0, "Map Edgepoint generation failed. KM : 0 -- send map" );
break;
}
return;
}
if( gMapInformation.sNorthGridNo != -1 )
{
*pubStrategicInsertionCode = INSERTION_CODE_NORTH;
gfChangedEntrySide = TRUE;
}
else if( gMapInformation.sEastGridNo != -1 )
{
*pubStrategicInsertionCode = INSERTION_CODE_EAST;
gfChangedEntrySide = TRUE;
}
else if( gMapInformation.sSouthGridNo != -1 )
{
*pubStrategicInsertionCode = INSERTION_CODE_SOUTH;
gfChangedEntrySide = TRUE;
}
else if( gMapInformation.sWestGridNo != -1 )
{
*pubStrategicInsertionCode = INSERTION_CODE_WEST;
gfChangedEntrySide = TRUE;
}
else
{
AssertMsg( 0, "No maps edgepoints at all! KM, LC : 1" );
}
}
void CheckForValidMapEdge( UINT8 *pubStrategicInsertionCode )
{
switch( *pubStrategicInsertionCode )
{
case INSERTION_CODE_NORTH:
if( !gps1stNorthEdgepointArray )
FindValidInsertionCode( pubStrategicInsertionCode );
break;
case INSERTION_CODE_EAST:
if( !gps1stEastEdgepointArray )
FindValidInsertionCode( pubStrategicInsertionCode );
break;
case INSERTION_CODE_SOUTH:
if( !gps1stSouthEdgepointArray )
FindValidInsertionCode( pubStrategicInsertionCode );
break;
case INSERTION_CODE_WEST:
if( !gps1stWestEdgepointArray )
FindValidInsertionCode( pubStrategicInsertionCode );
break;
}
}
//#endif
extern BOOLEAN gfTacticalDoHeliRun;
void InitTacticalPlacementGUI()
{
islocked=0;//hayden
VOBJECT_DESC VObjectDesc;
INT32 i, xp, yp;
UINT8 ubFaceIndex;
gfTacticalPlacementGUIActive = TRUE;
gfTacticalPlacementGUIDirty = TRUE;
gfValidLocationsChanged = TRUE;
gfTacticalPlacementFirstTime = TRUE;
// WANNE - MP: Center
gfCenter = FALSE;
#ifdef JA2BETAVERSION
gfNorthValid = gfEastValid = gfSouthValid = gfWestValid = FALSE;
gfChangedEntrySide = FALSE;
#endif
// WANNE: Make a black background color for the whole screen
ColorFillVideoSurfaceArea( FRAME_BUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, Get16BPPColor( FROMRGB( 0, 0, 0 ) ) );
//Enter overhead map
GoIntoOverheadMap();
//Load the images
VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE;
if (iResolution >= _640x480 && iResolution < _800x600)
{
sprintf( VObjectDesc.ImageFile, "Interface\\OverheadInterface.sti" );
if( !AddVideoObject( &VObjectDesc, (UINT32 *)&giOverheadPanelImage ) )
{
AssertMsg( 0, "Failed to load Interface\\OverheadInterface.sti" );
}
}
else if (iResolution < _1024x768)
{
sprintf( VObjectDesc.ImageFile, "Interface\\OverheadInterface_800x600.sti" );
if( !AddVideoObject( &VObjectDesc, (UINT32 *)&giOverheadPanelImage ) )
{
AssertMsg( 0, "Failed to load Interface\\OverheadInterface_800x600.sti" );
}
}
else
{
sprintf( VObjectDesc.ImageFile, "Interface\\OverheadInterface_1024x768.sti" );
if( !AddVideoObject( &VObjectDesc, (UINT32 *)&giOverheadPanelImage ) )
{
AssertMsg( 0, "Failed to load Interface\\OverheadInterface_1024x768.sti" );
}
}
sprintf( VObjectDesc.ImageFile, "Interface\\panels.sti" );
if( !AddVideoObject( &VObjectDesc, (UINT32 *)&giMercPanelImage ) )
{
AssertMsg( 0, "Failed to load Interface\\panels.sti" );
}
giOverheadButtonImages[ DONE_BUTTON ] = LoadButtonImage( "Interface\\OverheadUIButtons.sti", -1, 0, -1, 1, -1 );
if( giOverheadButtonImages[ DONE_BUTTON ] == -1 )
{
AssertMsg( 0, "Failed to load Interface\\OverheadUIButtons.sti" );
}
giOverheadButtonImages[ SPREAD_BUTTON ] = UseLoadedButtonImage( giOverheadButtonImages[ DONE_BUTTON ], -1, 0, -1, 1, -1 );
giOverheadButtonImages[ GROUP_BUTTON ] = UseLoadedButtonImage( giOverheadButtonImages[ DONE_BUTTON ], -1, 0, -1, 1, -1 );
giOverheadButtonImages[ CLEAR_BUTTON ] = UseLoadedButtonImage( giOverheadButtonImages[ DONE_BUTTON ], -1, 0, -1, 1, -1 );
//Create the buttons which provide automatic placements.
iTPButtons[ CLEAR_BUTTON ] =
QuickCreateButton( giOverheadButtonImages[ CLEAR_BUTTON ], 11 + xResOffset, SCREEN_HEIGHT - 148, BUTTON_NO_TOGGLE, MSYS_PRIORITY_HIGH,
DEFAULT_MOVE_CALLBACK, ClearPlacementsCallback );
SpecifyGeneralButtonTextAttributes( iTPButtons[ CLEAR_BUTTON ], gpStrategicString[ STR_TP_CLEAR ], BLOCKFONT, FONT_BEIGE, 141 );
SetButtonFastHelpText( iTPButtons[ CLEAR_BUTTON ], gpStrategicString[ STR_TP_CLEARHELP ] );
SetBtnHelpEndCallback( iTPButtons[ CLEAR_BUTTON ], FastHelpRemoved2Callback );
iTPButtons[ SPREAD_BUTTON ] =
QuickCreateButton( giOverheadButtonImages[ SPREAD_BUTTON ], 11 + xResOffset, SCREEN_HEIGHT - 113, BUTTON_NO_TOGGLE, MSYS_PRIORITY_HIGH,
DEFAULT_MOVE_CALLBACK, SpreadPlacementsCallback );
SpecifyGeneralButtonTextAttributes( iTPButtons[ SPREAD_BUTTON ], gpStrategicString[ STR_TP_SPREAD ], BLOCKFONT, FONT_BEIGE, 141 );
SetButtonFastHelpText( iTPButtons[ SPREAD_BUTTON ], gpStrategicString[ STR_TP_SPREADHELP ] );
SetBtnHelpEndCallback( iTPButtons[ SPREAD_BUTTON ], FastHelpRemovedCallback );
iTPButtons[ GROUP_BUTTON ] =
QuickCreateButton( giOverheadButtonImages[ GROUP_BUTTON ], 11 + xResOffset, SCREEN_HEIGHT - 78, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH,
DEFAULT_MOVE_CALLBACK, GroupPlacementsCallback );
SpecifyGeneralButtonTextAttributes( iTPButtons[ GROUP_BUTTON ], gpStrategicString[ STR_TP_GROUP ], BLOCKFONT, FONT_BEIGE, 141 );
SetButtonFastHelpText( iTPButtons[ GROUP_BUTTON ], gpStrategicString[ STR_TP_GROUPHELP ] );
SetBtnHelpEndCallback( iTPButtons[ GROUP_BUTTON ], FastHelpRemovedCallback );
iTPButtons[ DONE_BUTTON ] =
QuickCreateButton( giOverheadButtonImages[ DONE_BUTTON ], 11 + xResOffset, SCREEN_HEIGHT - 43, BUTTON_NO_TOGGLE, MSYS_PRIORITY_HIGH,
DEFAULT_MOVE_CALLBACK, DoneOverheadPlacementClickCallback );
SpecifyGeneralButtonTextAttributes( iTPButtons[ DONE_BUTTON ], gpStrategicString[ STR_TP_DONE ], BLOCKFONT, FONT_BEIGE, 141 );
SetButtonFastHelpText( iTPButtons[ DONE_BUTTON ], gpStrategicString[ STR_TP_DONEHELP ] );
SetBtnHelpEndCallback( iTPButtons[ DONE_BUTTON ], FastHelpRemovedCallback );
AllowDisabledButtonFastHelp( iTPButtons[ DONE_BUTTON ], TRUE );
SpecifyButtonHilitedTextColors( iTPButtons[ CLEAR_BUTTON ], FONT_WHITE, FONT_NEARBLACK );
SpecifyButtonHilitedTextColors( iTPButtons[ SPREAD_BUTTON ], FONT_WHITE, FONT_NEARBLACK );
SpecifyButtonHilitedTextColors( iTPButtons[ GROUP_BUTTON ], FONT_WHITE, FONT_NEARBLACK );
SpecifyButtonHilitedTextColors( iTPButtons[ DONE_BUTTON ], FONT_WHITE, FONT_NEARBLACK );
//First pass: Count the number of mercs that are going to be placed by the player.
// This determines the size of the array we will allocate.
giPlacements = 0;
for( i = gTacticalStatus.Team[ OUR_TEAM ].bFirstID; i <= gTacticalStatus.Team[ OUR_TEAM ].bLastID; ++i )
{
if( MercPtrs[ i ]->bActive && !MercPtrs[ i ]->flags.fBetweenSectors &&
CurrentBattleSectorIs( MercPtrs[i]->sSectorX, MercPtrs[i]->sSectorY, MercPtrs[i]->bSectorZ ) &&
!( MercPtrs[ i ]->flags.uiStatusFlags & ( SOLDIER_VEHICLE ) ) && // ATE Ignore vehicles
MercPtrs[ i ]->bAssignment != ASSIGNMENT_POW &&
MercPtrs[ i ]->bAssignment != ASSIGNMENT_MINIEVENT &&
MercPtrs[ i ]->bAssignment != ASSIGNMENT_REBELCOMMAND &&
!( MercPtrs[i]->usSoldierFlagMask2 & SOLDIER_CONCEALINSERTION ) &&
MercPtrs[ i ]->bAssignment != IN_TRANSIT )
{
++giPlacements;
}
}
//Allocate the array based on how many mercs there are.
gMercPlacement = (MERCPLACEMENT*)MemAlloc( sizeof( MERCPLACEMENT ) * giPlacements );
Assert( gMercPlacement );
//Second pass: Assign the mercs to their respective slots.
giPlacements = 0;
for( i = gTacticalStatus.Team[ OUR_TEAM ].bFirstID; i <= gTacticalStatus.Team[ OUR_TEAM ].bLastID; ++i )
{
if( MercPtrs[ i ]->bActive && MercPtrs[ i ]->stats.bLife && !MercPtrs[ i ]->flags.fBetweenSectors &&
CurrentBattleSectorIs( MercPtrs[i]->sSectorX, MercPtrs[i]->sSectorY, MercPtrs[i]->bSectorZ ) &&
MercPtrs[ i ]->bAssignment != ASSIGNMENT_POW &&
MercPtrs[ i ]->bAssignment != ASSIGNMENT_MINIEVENT &&
MercPtrs[ i ]->bAssignment != ASSIGNMENT_REBELCOMMAND &&
!( MercPtrs[i]->usSoldierFlagMask2 & SOLDIER_CONCEALINSERTION ) &&
MercPtrs[ i ]->bAssignment != IN_TRANSIT &&
!( MercPtrs[ i ]->flags.uiStatusFlags & ( SOLDIER_VEHICLE ) ) ) // ATE Ignore vehicles
{
// Flugente: if options allow it and we entered this sector - in combat - via helicopter, then allow us free selection of our entry point, and drop us from the helicopter
if ( MercPtrs[ i ]->bTeam == gbPlayerNum && (gGameExternalOptions.ubSkyriderHotLZ == 1 || gGameExternalOptions.ubSkyriderHotLZ == 3) && MercPtrs[ i ]->usSoldierFlagMask & SOLDIER_AIRDROP )
{
AddMercToHeli( MercPtrs[ i ]->ubID );
DisableButton(iTPButtons[SPREAD_BUTTON]);
gMercPlacement[ giPlacements ].ubStrategicInsertionCode = INSERTION_CODE_CHOPPER;
MercPtrs[ i ]->ubStrategicInsertionCode = INSERTION_CODE_CHOPPER;
gfCenter = TRUE;
}
if ( GetEnemyEncounterCode() == ENEMY_AMBUSH_DEPLOYMENT_CODE )
{
gMercPlacement[giPlacements].ubStrategicInsertionCode = INSERTION_CODE_CENTER;
MercPtrs[i]->ubStrategicInsertionCode = INSERTION_CODE_CENTER;
gfCenter = TRUE;
}
// WANNE - MP: Check if the desired insertion direction is valid on the map. If not, choose another entry direction!
if (is_networked)
{
MercPtrs[ i ]->ubStrategicInsertionCode = GetValidInsertionDirectionForMP(MercPtrs[ i ]->ubStrategicInsertionCode);
}
// ATE: If we are in a vehicle - remove ourselves from it!
//if ( MercPtrs[ i ]->flags.uiStatusFlags & ( SOLDIER_DRIVER | SOLDIER_PASSENGER ) )
//{
// RemoveSoldierFromVehicle( MercPtrs[ i ], MercPtrs[ i ]->bVehicleID );
//}
if( MercPtrs[ i ]->ubStrategicInsertionCode == INSERTION_CODE_PRIMARY_EDGEINDEX ||
MercPtrs[ i ]->ubStrategicInsertionCode == INSERTION_CODE_SECONDARY_EDGEINDEX )
{
MercPtrs[ i ]->ubStrategicInsertionCode = (UINT8)MercPtrs[ i ]->usStrategicInsertionData;
}
gMercPlacement[ giPlacements ].pSoldier = MercPtrs[ i ];
gMercPlacement[ giPlacements ].ubStrategicInsertionCode = MercPtrs[ i ]->ubStrategicInsertionCode;
gMercPlacement[ giPlacements ].fPlaced = FALSE;
// WANNE: We always want to have edgepoints
CheckForValidMapEdge( &MercPtrs[ i ]->ubStrategicInsertionCode );
// Flugente: campaign stats
switch( MercPtrs[ i ]->ubStrategicInsertionCode )
{
case INSERTION_CODE_NORTH:
gCurrentIncident.usIncidentFlags |= INCIDENT_ATTACKDIR_NORTH;
break;
case INSERTION_CODE_EAST:
gCurrentIncident.usIncidentFlags |= INCIDENT_ATTACKDIR_EAST;
break;
case INSERTION_CODE_SOUTH:
gCurrentIncident.usIncidentFlags |= INCIDENT_ATTACKDIR_SOUTH;
break;
case INSERTION_CODE_WEST:
gCurrentIncident.usIncidentFlags |= INCIDENT_ATTACKDIR_WEST;
break;
}
// WANNE - MP: Center
if (is_networked && MercPtrs[ i ]->ubStrategicInsertionCode == INSERTION_CODE_CENTER)
{
gfCenter = TRUE;
}
++giPlacements;
}
}
//add all the faces now
for( i = 0; i < giPlacements; ++i )
{
VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE;
//Load the faces
{
ubFaceIndex = gMercProfiles[ gMercPlacement[ i ].pSoldier->ubProfile ].ubFaceIndex;
if ( ( ubFaceIndex < 100 ) && gMercProfiles[gMercPlacement[i].pSoldier->ubProfile].Type == PROFILETYPE_IMP )
{
sprintf( VObjectDesc.ImageFile, "IMPFaces\\65Face\\%02d.sti", ubFaceIndex );
}
else if ( ( ubFaceIndex > 99 ) && gMercProfiles[gMercPlacement[i].pSoldier->ubProfile].Type == PROFILETYPE_IMP )
{
sprintf( VObjectDesc.ImageFile, "IMPFaces\\65Face\\%03d.sti", ubFaceIndex );
}
else if( ubFaceIndex < 100 )
{
sprintf( VObjectDesc.ImageFile, "Faces\\65Face\\%02d.sti", ubFaceIndex );
}
else if( ubFaceIndex > 99 )
{
sprintf( VObjectDesc.ImageFile, "Faces\\65Face\\%03d.sti", ubFaceIndex );
}
}
if( !AddVideoObject( &VObjectDesc, &gMercPlacement[ i ].uiVObjectID ) )
{
sprintf( VObjectDesc.ImageFile, "Faces\\65Face\\speck.sti" );
if( !AddVideoObject( &VObjectDesc, &gMercPlacement[ i ].uiVObjectID ) )
{
AssertMsg( 0, String("Failed to load %Faces\\65Face\\%03d.sti or it's placeholder, speck.sti", gMercProfiles[ gMercPlacement[ i ].pSoldier->ubProfile ].ubFaceIndex) );
}
}
xp = (xResOffset) + 91 + (i / 2) * 54;
if (i % 2)
{
yp = SCREEN_HEIGHT - 68;
}
else
{
yp = SCREEN_HEIGHT - 119;
}
//yp = (i % 2) ? 412 : 361;
MSYS_DefineRegion( &gMercPlacement[ i ].region, (UINT16)xp, (UINT16)yp, (UINT16)(xp + 54), (UINT16)(yp + 62), MSYS_PRIORITY_HIGH, 0, MercMoveCallback, MercClickCallback );
}
if(!is_client)
PlaceMercs();//hayden
if( gubDefaultButton == GROUP_BUTTON )
{
ButtonList[ iTPButtons[ GROUP_BUTTON ] ]->uiFlags |= BUTTON_CLICKED_ON;
for( i = 0; i < giPlacements; ++i )
{ //go from the currently selected soldier to the end
if( !gMercPlacement[ i ].fPlaced )
{ //Found an unplaced merc. Select him.
gbSelectedMercID = (INT8)i;
if( gubDefaultButton == GROUP_BUTTON )
gubSelectedGroupID = gMercPlacement[ i ].pSoldier->ubGroupID;
gfTacticalPlacementGUIDirty = TRUE;
SetCursorMerc( (INT8)i );
gpTacticalPlacementSelectedSoldier = gMercPlacement[ i ].pSoldier;
break;
}
}
}
}
// WANNE - MP: This method checks, if the desired entry direction (N, E, S, W) on the map is valid. If not it chooses the next valid diretion
UINT8 GetValidInsertionDirectionForMP(UINT8 currentInsertionPoint)
{
bool foundValidDirection = false;
UINT8 validInsertionDirection = currentInsertionPoint;
// Check if current insertion direction is valid
switch (currentInsertionPoint)
{
case INSERTION_CODE_NORTH:
if (gus1stNorthEdgepointArraySize > 0 || gus2ndNorthEdgepointArraySize > 0)
{
foundValidDirection = true;
validInsertionDirection = INSERTION_CODE_NORTH;
}
break;
case INSERTION_CODE_SOUTH:
if (gus1stSouthEdgepointArraySize > 0 || gus2ndSouthEdgepointArraySize > 0)
{
foundValidDirection = true;
validInsertionDirection = INSERTION_CODE_SOUTH;
}
break;
case INSERTION_CODE_EAST:
if (gus1stEastEdgepointArraySize > 0 || gus2ndEastEdgepointArraySize > 0)
{
foundValidDirection = true;
validInsertionDirection = INSERTION_CODE_EAST;
}
break;
case INSERTION_CODE_WEST:
if (gus1stWestEdgepointArraySize > 0 || gus2ndWestEdgepointArraySize > 0)
{
foundValidDirection = true;
validInsertionDirection = INSERTION_CODE_WEST;
}
break;
// WANNE - MP: Center
case INSERTION_CODE_CENTER:
foundValidDirection = true;
validInsertionDirection = INSERTION_CODE_CENTER;
break;
case INSERTION_CODE_CHOPPER:
foundValidDirection = true;
validInsertionDirection = INSERTION_CODE_CHOPPER;
break;
}
// Find alternate insertion direction by looping through all directions (N, S, E, W)
if (!foundValidDirection)
{
UINT8 direction = 0;
// Find NEXT valid direction
for (int i = currentInsertionPoint; (i < currentInsertionPoint + 4); i++)
{
// First iteration, start with current insertion direction
if (i == currentInsertionPoint)
direction = i;
else
{
if (i <= 3)
direction = i;
else
{
direction = 4 - i;
}
}
switch (direction)
{
case INSERTION_CODE_NORTH:
if (gus1stNorthEdgepointArraySize > 0 || gus2ndNorthEdgepointArraySize > 0)
{
foundValidDirection = true;
validInsertionDirection = INSERTION_CODE_NORTH;
}
break;
case INSERTION_CODE_SOUTH:
if (gus1stSouthEdgepointArraySize > 0 || gus2ndSouthEdgepointArraySize > 0)
{
foundValidDirection = true;
validInsertionDirection = INSERTION_CODE_SOUTH;
}
break;
case INSERTION_CODE_EAST:
if (gus1stEastEdgepointArraySize > 0 || gus2ndEastEdgepointArraySize > 0)
{
foundValidDirection = true;
validInsertionDirection = INSERTION_CODE_EAST;
}
break;
case INSERTION_CODE_WEST:
if (gus1stWestEdgepointArraySize > 0 || gus2ndWestEdgepointArraySize > 0)
{
foundValidDirection = true;
validInsertionDirection = INSERTION_CODE_WEST;
}
break;
}
// Exit loop condition
if (foundValidDirection)
break;
}
}
return validInsertionDirection;
}
void RenderTacticalPlacementGUI()
{
INT32 i, xp, yp, width, height;
INT32 iStartY;
SOLDIERTYPE *pSoldier;
UINT32 uiDestPitchBYTES;
UINT16 usHatchColor;
CHAR16 str[ 128 ];
UINT8 *pDestBuf;
UINT8 ubColor;
if( gfTacticalPlacementFirstTime )
{
gfTacticalPlacementFirstTime = FALSE;
DisableScrollMessages();
}
//Check to make sure that if we have a hilighted merc (not selected) and the mouse has moved out
//of it's region, then we will clear the hilighted ID, and refresh the display.
if( !gfTacticalPlacementGUIDirty && gbHilightedMercID != -1 )
{
xp = xResOffset + 91 + (gbHilightedMercID / 2) * 54;
if (gbHilightedMercID % 2)
{
yp = SCREEN_HEIGHT - 68;
}
else
{
yp = SCREEN_HEIGHT - 119;
}
//yp = (gbHilightedMercID % 2) ? 412 : 361;
if( gusMouseXPos < xp || gusMouseXPos > xp + 54 || gusMouseYPos < yp || gusMouseYPos > yp + 62 )
{
gbHilightedMercID = -1;
gubHilightedGroupID = 0;
SetCursorMerc( gbSelectedMercID );
gpTacticalPlacementHilightedSoldier = NULL;
}
}
//If the display is dirty render the entire panel.
if( gfTacticalPlacementGUIDirty )
{
BltVideoObjectFromIndex( FRAME_BUFFER, giOverheadPanelImage, 0, xResOffset, SCREEN_HEIGHT - 160, VO_BLT_SRCTRANSPARENCY, 0 );
InvalidateRegion( 0 + xResOffset, SCREEN_HEIGHT - 160, 320 + xResOffset, SCREEN_HEIGHT );
gfTacticalPlacementGUIDirty = FALSE;
MarkButtonsDirty();
//DisableHilightsAndHelpText();
//RenderButtons();
//EnableHilightsAndHelpText();
for( i = 0; i < giPlacements; ++i )
{
//Render the mercs
pSoldier = gMercPlacement[ i ].pSoldier;
xp = xResOffset + 95 + (i / 2) * 54;
if (i % 2)
{
yp = SCREEN_HEIGHT - 58;
}
else
{
yp = SCREEN_HEIGHT - 109;
}
//yp = (i % 2) ? 422 : 371;
ColorFillVideoSurfaceArea( FRAME_BUFFER, xp+36, yp+2, xp+44, yp+30, 0 );
BltVideoObjectFromIndex( FRAME_BUFFER, giMercPanelImage, 0, xp, yp, VO_BLT_SRCTRANSPARENCY, NULL );
BltVideoObjectFromIndex( FRAME_BUFFER, gMercPlacement[ i ].uiVObjectID, 0, xp+2, yp+2, VO_BLT_SRCTRANSPARENCY, NULL );
//HEALTH BAR
if( !pSoldier->stats.bLife )
continue;
//yellow one for bleeding
iStartY = yp + 29 - 27*pSoldier->stats.bLifeMax/100;
ColorFillVideoSurfaceArea( FRAME_BUFFER, xp+36, iStartY, xp+37, yp+29, Get16BPPColor( FROMRGB( 107, 107, 57 ) ) );
ColorFillVideoSurfaceArea( FRAME_BUFFER, xp+37, iStartY, xp+38, yp+29, Get16BPPColor( FROMRGB( 222, 181, 115 ) ) );
//pink one for bandaged.
iStartY = yp + 29 - 27*(pSoldier->stats.bLifeMax - pSoldier->bBleeding)/100;
ColorFillVideoSurfaceArea( FRAME_BUFFER, xp+36, iStartY, xp+37, yp+29, Get16BPPColor( FROMRGB( 156, 57, 57 ) ) );
ColorFillVideoSurfaceArea( FRAME_BUFFER, xp+37, iStartY, xp+38, yp+29, Get16BPPColor( FROMRGB( 222, 132, 132 ) ) );
//red one for actual health
iStartY = yp + 29 - 27*pSoldier->stats.bLife/100;
ColorFillVideoSurfaceArea( FRAME_BUFFER, xp+36, iStartY, xp+37, yp+29, Get16BPPColor( FROMRGB( 107, 8, 8 ) ) );
ColorFillVideoSurfaceArea( FRAME_BUFFER, xp+37, iStartY, xp+38, yp+29, Get16BPPColor( FROMRGB( 206, 0, 0 ) ) );
//BREATH BAR
iStartY = yp + 29 - 27*pSoldier->bBreathMax/100;
ColorFillVideoSurfaceArea( FRAME_BUFFER, xp+39, iStartY, xp+40, yp+29, Get16BPPColor( FROMRGB( 8, 8, 132 ) ) );
ColorFillVideoSurfaceArea( FRAME_BUFFER, xp+40, iStartY, xp+41, yp+29, Get16BPPColor( FROMRGB( 8, 8, 107 ) ) );
//MORALE BAR
iStartY = yp + 29 - 27*pSoldier->aiData.bMorale/100;
ColorFillVideoSurfaceArea( FRAME_BUFFER, xp+42, iStartY, xp+43, yp+29, Get16BPPColor( FROMRGB( 8, 156, 8 ) ) );
ColorFillVideoSurfaceArea( FRAME_BUFFER, xp+43, iStartY, xp+44, yp+29, Get16BPPColor( FROMRGB( 8, 107, 8 ) ) );
}
SetFont( BLOCKFONT );
SetFontForeground( FONT_BEIGE );
SetFontShadow( 141 );
GetSectorIDString( gubPBSectorX, gubPBSectorY, gubPBSectorZ, str, TRUE );
mprintf(120 + xResOffset, SCREEN_HEIGHT - 145, L"%s %s -- %s...", gpStrategicString[ STR_TP_SECTOR ], str, gpStrategicString[ STR_TP_CHOOSEENTRYPOSITIONS ] );
//Shade out the part of the tactical map that isn't considered placable.
BlitBufferToBuffer(FRAME_BUFFER, guiSAVEBUFFER, 0, SCREEN_HEIGHT - 160, SCREEN_WIDTH, 160);
}
if( gfValidLocationsChanged )
{
if( DayTime() )
{ //6AM to 9PM is black
usHatchColor = 0; //Black
}
else
{ //9PM to 6AM is gray (black is too dark to distinguish)
usHatchColor = Get16BPPColor( FROMRGB( 63, 31, 31 ) );
}
--gfValidLocationsChanged;
//DBrot bigger map code
if(gfUseBiggerOverview)
{
BlitBufferToBuffer( guiSAVEBUFFER, FRAME_BUFFER, iOffsetHorizontal, iOffsetVertical, 1434, 716 );
InvalidateRegion( iOffsetHorizontal, iOffsetVertical, iOffsetHorizontal + 1434, iOffsetVertical + 716 );
gTPClipRect.iLeft = iOffsetHorizontal + 1;
gTPClipRect.iTop = iOffsetVertical + 1;
gTPClipRect.iBottom = iOffsetVertical + 716;// 318;
gTPClipRect.iRight = iOffsetHorizontal + 1434; //634;
}
else
{
BlitBufferToBuffer( guiSAVEBUFFER, FRAME_BUFFER, iOffsetHorizontal, iOffsetVertical, 640, 320 );
InvalidateRegion( iOffsetHorizontal, iOffsetVertical, iOffsetHorizontal + 640, iOffsetVertical + 320 );
//dnl ch45 051009
gTPClipRect.iLeft = iOffsetHorizontal + 1;
gTPClipRect.iTop = iOffsetVertical + 1;
gTPClipRect.iBottom = iOffsetVertical + 318;
gTPClipRect.iRight = iOffsetHorizontal + 634;
}
if( gbCursorMercID == -1 )
{
if ( GetEnemyEncounterCode() == ENEMY_AMBUSH_DEPLOYMENT_CODE || (gfCenter && gGameExternalOptions.ubSkyriderHotLZ == 1))
{
INT16 sCellX = 0;
INT16 sCellY = 0;
GetOverheadScreenXYFromGridNo( gMapInformation.sCenterGridNo, &sCellX, &sCellY );
// Left black border
gTPClipRectCenterLeft.iLeft = iOffsetHorizontal;
gTPClipRectCenterLeft.iTop = iOffsetVertical + 3;
gTPClipRectCenterLeft.iBottom = iOffsetVertical + 320;
gTPClipRectCenterLeft.iRight = iOffsetHorizontal + sCellX - 5 * gGameExternalOptions.usAmbushSpreadRadiusMercs;
// Top black border
gTPClipRectCenterTop.iLeft = iOffsetHorizontal;
gTPClipRectCenterTop.iTop = iOffsetVertical + 3;
gTPClipRectCenterTop.iBottom = iOffsetVertical + sCellY - 3 * gGameExternalOptions.usAmbushSpreadRadiusMercs;
gTPClipRectCenterTop.iRight = iOffsetHorizontal + 634;
// Right black border
gTPClipRectCenterRight.iLeft = iOffsetHorizontal + sCellX + 5 * gGameExternalOptions.usAmbushSpreadRadiusMercs;
gTPClipRectCenterRight.iTop = iOffsetVertical + 3;
gTPClipRectCenterRight.iBottom = iOffsetVertical + 320;
gTPClipRectCenterRight.iRight = iOffsetHorizontal + 634;
// Bottom black border
gTPClipRectCenterBottom.iLeft = iOffsetHorizontal;
gTPClipRectCenterBottom.iTop = iOffsetVertical + sCellY + 3 * gGameExternalOptions.usAmbushSpreadRadiusMercs;
gTPClipRectCenterBottom.iBottom = iOffsetVertical + 320;
gTPClipRectCenterBottom.iRight = iOffsetHorizontal + 634;
}
// WANNE - MP: Center
else if (is_networked && gfCenter)
{
// Left black border
gTPClipRectCenterLeft.iLeft = iOffsetHorizontal;
gTPClipRectCenterLeft.iTop = iOffsetVertical + 3;
gTPClipRectCenterLeft.iBottom = iOffsetVertical + 320;
gTPClipRectCenterLeft.iRight = iOffsetHorizontal + CENTERENTRYPTS_LEFT_X;
// Top black border
gTPClipRectCenterTop.iLeft = iOffsetHorizontal;
gTPClipRectCenterTop.iTop = iOffsetVertical + 3;
gTPClipRectCenterTop.iBottom = iOffsetVertical + CENTERENTRYPTS_TOP_Y;
gTPClipRectCenterTop.iRight = iOffsetHorizontal + 634;
// Right black border
gTPClipRectCenterRight.iLeft = iOffsetHorizontal + CENTERENTRYPTS_RIGHT_X;
gTPClipRectCenterRight.iTop = iOffsetVertical + 3;
gTPClipRectCenterRight.iBottom = iOffsetVertical + 320;
gTPClipRectCenterRight.iRight = iOffsetHorizontal + 634;
// Bottom black border
gTPClipRectCenterBottom.iLeft = iOffsetHorizontal;
gTPClipRectCenterBottom.iTop = iOffsetVertical + CENTERENTRYPTS_BOTTOM_Y;
gTPClipRectCenterBottom.iBottom = iOffsetVertical + 320;
gTPClipRectCenterBottom.iRight = iOffsetHorizontal + 634;
}
// Flugente airdrop
else if ( gfCenter && gGameExternalOptions.ubSkyriderHotLZ == 3 )
{
// Left black border
gTPClipRectCenterLeft.iLeft = iOffsetHorizontal;
gTPClipRectCenterLeft.iTop = iOffsetVertical + 3;
gTPClipRectCenterLeft.iBottom = iOffsetVertical + 320;
gTPClipRectCenterLeft.iRight = iOffsetHorizontal + AIRDROPENTRYPTS_LEFT_X;
// Top black border
gTPClipRectCenterTop.iLeft = iOffsetHorizontal;
gTPClipRectCenterTop.iTop = iOffsetVertical + 3;
gTPClipRectCenterTop.iBottom = iOffsetVertical + AIRDROPENTRYPTS_TOP_Y;
gTPClipRectCenterTop.iRight = iOffsetHorizontal + 634;
// Right black border
gTPClipRectCenterRight.iLeft = iOffsetHorizontal + AIRDROPENTRYPTS_RIGHT_X;
gTPClipRectCenterRight.iTop = iOffsetVertical + 3;
gTPClipRectCenterRight.iBottom = iOffsetVertical + 320;
gTPClipRectCenterRight.iRight = iOffsetHorizontal + 634;
// Bottom black border
gTPClipRectCenterBottom.iLeft = iOffsetHorizontal;
gTPClipRectCenterBottom.iTop = iOffsetVertical + AIRDROPENTRYPTS_BOTTOM_Y;
gTPClipRectCenterBottom.iBottom = iOffsetVertical + 320;
gTPClipRectCenterBottom.iRight = iOffsetHorizontal + 634;
}
}
else
{
if (is_networked)
{
gMercPlacement[ gbCursorMercID ].ubStrategicInsertionCode = GetValidInsertionDirectionForMP(gMercPlacement[ gbCursorMercID ].ubStrategicInsertionCode);
}
//dnl ch45 051009
INT16 sWorldScreenX, sX;
INT16 sWorldScreenY, sY;
sX = giXA;
sY = giYA;
GetWorldXYAbsoluteScreenXY(sX, sY, &sWorldScreenX, &sWorldScreenY);
sWorldScreenX += 20;// Correction from invisible area X
sWorldScreenY += 35;// Correction from invisible area Y
//DBrot: adjust offsets for big maps
if(gfUseBiggerOverview)
{
switch(gMercPlacement[gbCursorMercID].ubStrategicInsertionCode)
{
case INSERTION_CODE_NORTH:
//if(sWorldScreenY <= PLACEMENT_OFFSET){
//sY = (PLACEMENT_OFFSET - sWorldScreenY) / 5;
//gTPClipRect.iTop += sY;
gTPClipRect.iTop += PLACEMENT_OFFSET/5;
//}
break;
case INSERTION_CODE_EAST:
//if((sWorldScreenX + NORMAL_MAP_SCREEN_WIDTH) >= (MAPWIDTH - PLACEMENT_OFFSET)){
//sX = ((sWorldScreenX + NORMAL_MAP_SCREEN_WIDTH) - (MAPWIDTH - PLACEMENT_OFFSET)) / 5;
//gTPClipRect.iRight -= sX;
gTPClipRect.iRight -= PLACEMENT_OFFSET/5;
//}
break;
case INSERTION_CODE_SOUTH:
//if((sWorldScreenY + NORMAL_MAP_SCREEN_HEIGHT) >= (MAPHEIGHT - PLACEMENT_OFFSET)){
//sY = ((sWorldScreenY + NORMAL_MAP_SCREEN_HEIGHT) - (MAPHEIGHT - PLACEMENT_OFFSET)) / 5;
//gTPClipRect.iBottom -= sY;
gTPClipRect.iBottom -= PLACEMENT_OFFSET/5;
//}
break;
case INSERTION_CODE_WEST:
//if(sWorldScreenX <= PLACEMENT_OFFSET){
//sX = (PLACEMENT_OFFSET - sWorldScreenX) / 5;
//gTPClipRect.iLeft += sX;
gTPClipRect.iLeft += PLACEMENT_OFFSET/5;
//}
break;
}
}
else
{
switch(gMercPlacement[gbCursorMercID].ubStrategicInsertionCode)
{
case INSERTION_CODE_NORTH:
if(sWorldScreenY <= PLACEMENT_OFFSET)
{
sY = (PLACEMENT_OFFSET - sWorldScreenY) / 5;
sY += RebelCommand::GetAdditionalDeployRange(INSERTION_CODE_NORTH)/5;
gTPClipRect.iTop += sY;
}
break;
case INSERTION_CODE_EAST:
if((sWorldScreenX + NORMAL_MAP_SCREEN_WIDTH) >= (MAPWIDTH - PLACEMENT_OFFSET))
{
sX = ((sWorldScreenX + NORMAL_MAP_SCREEN_WIDTH) - (MAPWIDTH - PLACEMENT_OFFSET)) / 5;
sX += RebelCommand::GetAdditionalDeployRange(INSERTION_CODE_EAST)/5;
gTPClipRect.iRight -= sX;
}
break;
case INSERTION_CODE_SOUTH:
if((sWorldScreenY + NORMAL_MAP_SCREEN_HEIGHT) >= (MAPHEIGHT - PLACEMENT_OFFSET))
{
sY = ((sWorldScreenY + NORMAL_MAP_SCREEN_HEIGHT) - (MAPHEIGHT - PLACEMENT_OFFSET)) / 5;
sY += RebelCommand::GetAdditionalDeployRange(INSERTION_CODE_SOUTH)/5;
gTPClipRect.iBottom -= sY;
}
break;
case INSERTION_CODE_WEST:
if(sWorldScreenX <= PLACEMENT_OFFSET)
{
sX = (PLACEMENT_OFFSET - sWorldScreenX) / 5;
sX += RebelCommand::GetAdditionalDeployRange(INSERTION_CODE_WEST)/5;
gTPClipRect.iLeft += sX;
}
break;
}
}
if ( GetEnemyEncounterCode() == ENEMY_AMBUSH_DEPLOYMENT_CODE || (gfCenter && gGameExternalOptions.ubSkyriderHotLZ == 1 && gbSelectedMercID >= 0 && gMercPlacement[gbSelectedMercID].pSoldier->usSoldierFlagMask & SOLDIER_AIRDROP))
{
INT16 sCellX = 0;
INT16 sCellY = 0;
GetOverheadScreenXYFromGridNo( gMapInformation.sCenterGridNo, &sCellX, &sCellY );
// Left black border
gTPClipRectCenterLeft.iLeft = iOffsetHorizontal;
gTPClipRectCenterLeft.iTop = iOffsetVertical + 3;
gTPClipRectCenterLeft.iBottom = iOffsetVertical + 320;
gTPClipRectCenterLeft.iRight = iOffsetHorizontal + sCellX - 5 * gGameExternalOptions.usAmbushSpreadRadiusMercs;
// Top black border
gTPClipRectCenterTop.iLeft = iOffsetHorizontal;
gTPClipRectCenterTop.iTop = iOffsetVertical + 3;
gTPClipRectCenterTop.iBottom = iOffsetVertical + sCellY - 3 * gGameExternalOptions.usAmbushSpreadRadiusMercs;
gTPClipRectCenterTop.iRight = iOffsetHorizontal + 634;
// Right black border
gTPClipRectCenterRight.iLeft = iOffsetHorizontal + sCellX + 5 * gGameExternalOptions.usAmbushSpreadRadiusMercs;
gTPClipRectCenterRight.iTop = iOffsetVertical + 3;
gTPClipRectCenterRight.iBottom = iOffsetVertical + 320;
gTPClipRectCenterRight.iRight = iOffsetHorizontal + 634;
// Bottom black border
gTPClipRectCenterBottom.iLeft = iOffsetHorizontal;
gTPClipRectCenterBottom.iTop = iOffsetVertical + sCellY + 3 * gGameExternalOptions.usAmbushSpreadRadiusMercs;
gTPClipRectCenterBottom.iBottom = iOffsetVertical + 320;
gTPClipRectCenterBottom.iRight = iOffsetHorizontal + 634;
}
// WANNE - MP: Center
else if (is_networked && gfCenter)
{
// Left black border
gTPClipRectCenterLeft.iLeft = iOffsetHorizontal;
gTPClipRectCenterLeft.iTop = iOffsetVertical + 3;
gTPClipRectCenterLeft.iBottom = iOffsetVertical + 320;
gTPClipRectCenterLeft.iRight = iOffsetHorizontal + CENTERENTRYPTS_LEFT_X;
// Top black border
gTPClipRectCenterTop.iLeft = iOffsetHorizontal;
gTPClipRectCenterTop.iTop = iOffsetVertical + 3;
gTPClipRectCenterTop.iBottom = iOffsetVertical + CENTERENTRYPTS_TOP_Y;
gTPClipRectCenterTop.iRight = iOffsetHorizontal + 634;
// Right black border
gTPClipRectCenterRight.iLeft = iOffsetHorizontal + CENTERENTRYPTS_RIGHT_X;
gTPClipRectCenterRight.iTop = iOffsetVertical + 3;
gTPClipRectCenterRight.iBottom = iOffsetVertical + 320;
gTPClipRectCenterRight.iRight = iOffsetHorizontal + 634;
// Bottom black border
gTPClipRectCenterBottom.iLeft = iOffsetHorizontal;
gTPClipRectCenterBottom.iTop = iOffsetVertical + CENTERENTRYPTS_BOTTOM_Y;
gTPClipRectCenterBottom.iBottom = iOffsetVertical + 320;
gTPClipRectCenterBottom.iRight = iOffsetHorizontal + 634;
}
// Flugente airdrop
else if ( gfCenter && gGameExternalOptions.ubSkyriderHotLZ == 3 && gbSelectedMercID >= 0 && gMercPlacement[ gbSelectedMercID ].pSoldier->usSoldierFlagMask & SOLDIER_AIRDROP )
{
// Left black border
gTPClipRectCenterLeft.iLeft = iOffsetHorizontal;
gTPClipRectCenterLeft.iTop = iOffsetVertical + 3;
gTPClipRectCenterLeft.iBottom = iOffsetVertical + 320;
gTPClipRectCenterLeft.iRight = iOffsetHorizontal + AIRDROPENTRYPTS_LEFT_X;
// Top black border
gTPClipRectCenterTop.iLeft = iOffsetHorizontal;
gTPClipRectCenterTop.iTop = iOffsetVertical + 3;
gTPClipRectCenterTop.iBottom = iOffsetVertical + AIRDROPENTRYPTS_TOP_Y;
gTPClipRectCenterTop.iRight = iOffsetHorizontal + 634;
// Right black border
gTPClipRectCenterRight.iLeft = iOffsetHorizontal + AIRDROPENTRYPTS_RIGHT_X;
gTPClipRectCenterRight.iTop = iOffsetVertical + 3;
gTPClipRectCenterRight.iBottom = iOffsetVertical + 320;
gTPClipRectCenterRight.iRight = iOffsetHorizontal + 634;
// Bottom black border
gTPClipRectCenterBottom.iLeft = iOffsetHorizontal;
gTPClipRectCenterBottom.iTop = iOffsetVertical + AIRDROPENTRYPTS_BOTTOM_Y;
gTPClipRectCenterBottom.iBottom = iOffsetVertical + 320;
gTPClipRectCenterBottom.iRight = iOffsetHorizontal + 634;
}
}
pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES );
if (!gfCenter || ((gGameExternalOptions.ubSkyriderHotLZ == 1 || gGameExternalOptions.ubSkyriderHotLZ == 3) && gbSelectedMercID >= 0 && !(gMercPlacement[ gbSelectedMercID ].pSoldier->usSoldierFlagMask & SOLDIER_AIRDROP)) )
Blt16BPPBufferLooseHatchRectWithColor( (UINT16*)pDestBuf, uiDestPitchBYTES, &gTPClipRect, usHatchColor );
// WANNE - MP: Center
else
{
Blt16BPPBufferLooseHatchRectWithColor( (UINT16*)pDestBuf, uiDestPitchBYTES, &gTPClipRectCenterLeft, usHatchColor );
Blt16BPPBufferLooseHatchRectWithColor( (UINT16*)pDestBuf, uiDestPitchBYTES, &gTPClipRectCenterTop, usHatchColor );
Blt16BPPBufferLooseHatchRectWithColor( (UINT16*)pDestBuf, uiDestPitchBYTES, &gTPClipRectCenterRight, usHatchColor );
Blt16BPPBufferLooseHatchRectWithColor( (UINT16*)pDestBuf, uiDestPitchBYTES, &gTPClipRectCenterBottom, usHatchColor );
}
SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT );
if (!gfCenter || ((gGameExternalOptions.ubSkyriderHotLZ == 1 || gGameExternalOptions.ubSkyriderHotLZ == 3) && gbSelectedMercID >= 0 && !(gMercPlacement[ gbSelectedMercID ].pSoldier->usSoldierFlagMask & SOLDIER_AIRDROP)) )
RectangleDraw( TRUE, gTPClipRect.iLeft, gTPClipRect.iTop, gTPClipRect.iRight, gTPClipRect.iBottom, usHatchColor, pDestBuf );
else
{
RectangleDraw( TRUE, gTPClipRectCenterLeft.iLeft, gTPClipRectCenterLeft.iTop, gTPClipRectCenterLeft.iRight, gTPClipRectCenterLeft.iBottom, usHatchColor, pDestBuf );
RectangleDraw( TRUE, gTPClipRectCenterTop.iLeft, gTPClipRectCenterTop.iTop, gTPClipRectCenterTop.iRight, gTPClipRectCenterTop.iBottom, usHatchColor, pDestBuf );
RectangleDraw( TRUE, gTPClipRectCenterRight.iLeft, gTPClipRectCenterRight.iTop, gTPClipRectCenterRight.iRight, gTPClipRectCenterRight.iBottom, usHatchColor, pDestBuf );
RectangleDraw( TRUE, gTPClipRectCenterBottom.iLeft, gTPClipRectCenterBottom.iTop, gTPClipRectCenterBottom.iRight, gTPClipRectCenterBottom.iBottom, usHatchColor, pDestBuf );
}
UnLockVideoSurface( FRAME_BUFFER );
}
for( i = 0; i < giPlacements; ++i )
{
//Render the merc's names
pSoldier = gMercPlacement[ i ].pSoldier;
xp = xResOffset + 95 + (i / 2) * 54;
if (i % 2)
{
yp = SCREEN_HEIGHT - 58;
}
else
{
yp = SCREEN_HEIGHT - 109;
}
//yp = (i % 2) ? 422 : 371;
//NAME
if( gubDefaultButton == GROUP_BUTTON && gMercPlacement[ i ].pSoldier->ubGroupID == gubSelectedGroupID ||
gubDefaultButton != GROUP_BUTTON && i == gbSelectedMercID )
{
ubColor = FONT_YELLOW;
}
else if( gubDefaultButton == GROUP_BUTTON && gMercPlacement[ i ].pSoldier->ubGroupID == gubHilightedGroupID ||
gubDefaultButton != GROUP_BUTTON && i == gbHilightedMercID )
{
ubColor = FONT_WHITE;
}
else
{
ubColor = FONT_GRAY3;
}
SetFont( FONT10ARIALBOLD );
SetFontForeground( ubColor );
SetFontShadow( 141 );
//Render the question mark over the face if the merc hasn't yet been placed.
if( gMercPlacement[ i ].fPlaced )
{
RegisterBackgroundRect( BGND_FLAG_SINGLE, NULL, (INT16)(xp + 16), (INT16)(yp + 14), (INT16)(xp + 24), (INT16)(yp + 22) );
}
else
{
mprintf( xp + 16, yp + 14, L"?" );
InvalidateRegion( xp + 16, yp + 14, xp + 24, yp + 22 );
}
SetFont( BLOCKFONT );
width = StringPixLength( pSoldier->name, BLOCKFONT );
height = GetFontHeight( BLOCKFONT );
xp = xp + ( 48 - width ) / 2;
yp = yp + 33;
mprintf( xp, yp, pSoldier->name );
InvalidateRegion( xp, yp, xp + width, yp + width );
}
}
void EnsureDoneButtonStatus()
{
INT32 i;
//static BOOLEAN fInside = FALSE;
//BOOLEAN fChanged = FALSE;
for( i = 0; i < giPlacements; i++ )
{
if( !gMercPlacement[ i ].fPlaced )
{
if( ButtonList[ iTPButtons[ DONE_BUTTON ] ]->uiFlags & BUTTON_ENABLED )
{
DisableButton( iTPButtons[ DONE_BUTTON ] );
SetButtonFastHelpText( iTPButtons[ DONE_BUTTON ], gpStrategicString[ STR_TP_DISABLED_DONEHELP ] );
}
return;
}
}
if( !(ButtonList[ iTPButtons[ DONE_BUTTON ] ]->uiFlags & BUTTON_ENABLED ) )
{ //only enable it when it is disabled, otherwise the button will stay down!
EnableButton( iTPButtons[ DONE_BUTTON ] );
SetButtonFastHelpText( iTPButtons[ DONE_BUTTON ], gpStrategicString[ STR_TP_DONEHELP ] );
}
}
void lockui (bool unlock) //lock onluck ui for lan //hayden
{
if(unlock==0 && islocked==0 && is_client)
{
islocked=1;
DisableButton( iTPButtons[ DONE_BUTTON ] );
DisableButton( iTPButtons[ SPREAD_BUTTON ] );
DisableButton( iTPButtons[ GROUP_BUTTON ] );
DisableButton( iTPButtons[ CLEAR_BUTTON ] );
SGPRect CenterRect = { 100 + xResOffset, 100, SCREEN_WIDTH - 100 - xResOffset, 300 };
DoMessageBox( MSG_BOX_BASIC_STYLE, MPServerMessage[8], guiCurrentScreen, MSG_BOX_FLAG_OK | MSG_BOX_FLAG_USE_CENTERING_RECT, DialogRemoved, &CenterRect );
//send loaded
send_loaded();
}
if(unlock) //oh yeah ! :)
{
islocked=3;
EnableButton( iTPButtons[ SPREAD_BUTTON ] );
EnableButton( iTPButtons[ GROUP_BUTTON ] );
EnableButton( iTPButtons[ CLEAR_BUTTON ] );
ButtonList[ iTPButtons[ GROUP_BUTTON ] ]->uiFlags &= ~BUTTON_CLICKED_ON;
ButtonList[ iTPButtons[ GROUP_BUTTON ] ]->uiFlags |= BUTTON_DIRTY;
gubDefaultButton = CLEAR_BUTTON;
PlaceMercs();
gMsgBox.bHandled = MSG_BOX_RETURN_OK; //close if still open
}
}
void TacticalPlacementHandle()
{
InputAtom InputEvent;
EnsureDoneButtonStatus();
RenderTacticalPlacementGUI();
if (is_networked)
lockui(0);//lockui before placement while clients loading //hayden
if( gfRightButtonState )
{
gbSelectedMercID = -1;
gubSelectedGroupID = 0;
gpTacticalPlacementSelectedSoldier = NULL;
}
while (DequeueEvent(&InputEvent) == TRUE)
{
if( InputEvent.usEvent == KEY_DOWN )
{
switch( InputEvent.usParam )
{
#ifdef JA2TESTVERSION
case ESC:
//if (!is_networked)
KillTacticalPlacementGUI();
break;
#endif
case ENTER:
if( ButtonList[ iTPButtons[ DONE_BUTTON ] ]->uiFlags & BUTTON_ENABLED )
{
if(!is_client)KillTacticalPlacementGUI();
if(is_client)send_donegui(0);
}
break;
case 'c':
if(islocked!=1)ClearPlacementsCallback( ButtonList[ iTPButtons[ CLEAR_BUTTON ] ], MSYS_CALLBACK_REASON_LBUTTON_UP );
break;
case 'g':
if(islocked!=1)GroupPlacementsCallback( ButtonList[ iTPButtons[ GROUP_BUTTON ] ], MSYS_CALLBACK_REASON_LBUTTON_UP );
break;
case 's':
if(islocked!=1 && ButtonList[iTPButtons[SPREAD_BUTTON]]->uiFlags & BUTTON_ENABLED) SpreadPlacementsCallback( ButtonList[ iTPButtons[ SPREAD_BUTTON ] ], MSYS_CALLBACK_REASON_LBUTTON_UP );
break;
case 'x':
if( InputEvent.usKeyState & ALT_DOWN )
{
HandleShortCutExitState();
}
break;
}
}
}
gfValidCursor = FALSE;
if(gbSelectedMercID != -1 && ((gusMouseYPos < (iOffsetVertical + 320) && gusMouseYPos > iOffsetVertical && gusMouseXPos > iOffsetHorizontal && gusMouseXPos < (iOffsetHorizontal + 640))||(gfUseBiggerOverview && (gusMouseYPos < (iOffsetVertical + 716) && gusMouseYPos > iOffsetVertical && gusMouseXPos > iOffsetHorizontal && gusMouseXPos < (iOffsetHorizontal + 1432) ))))
{
//dnl ch45 051009
INT16 sWorldScreenX = (gusMouseXPos - iOffsetHorizontal) * 5;
INT16 sWorldScreenY = (gusMouseYPos - iOffsetVertical) * 5;
INT32 iCellX, iCellY;
GetFromAbsoluteScreenXYWorldXY(&iCellX, &iCellY, sWorldScreenX, sWorldScreenY);
iCellX = (iCellX / CELL_X_SIZE) + (giXA - 0);
iCellY = (iCellY / CELL_Y_SIZE) + (giYA - WORLD_ROWS/2);
GetWorldXYAbsoluteScreenXY(iCellX, iCellY, &sWorldScreenX, &sWorldScreenY);
switch(gMercPlacement[gbCursorMercID].ubStrategicInsertionCode)
{
case INSERTION_CODE_NORTH:
if(sWorldScreenY <= (PLACEMENT_OFFSET + RebelCommand::GetAdditionalDeployRange(INSERTION_CODE_NORTH)))
gfValidCursor = TRUE;
break;
case INSERTION_CODE_EAST:
if(sWorldScreenX >= ((MAPWIDTH - PLACEMENT_OFFSET - RebelCommand::GetAdditionalDeployRange(INSERTION_CODE_EAST))))
gfValidCursor = TRUE;
break;
case INSERTION_CODE_SOUTH:
if(sWorldScreenY >= ((MAPHEIGHT - PLACEMENT_OFFSET - RebelCommand::GetAdditionalDeployRange(INSERTION_CODE_SOUTH))))
gfValidCursor = TRUE;
break;
case INSERTION_CODE_WEST:
if(sWorldScreenX <= (PLACEMENT_OFFSET + RebelCommand::GetAdditionalDeployRange(INSERTION_CODE_WEST)))
gfValidCursor = TRUE;
break;
}
// WANNE - MP: Center
if ( gfCenter && (is_networked ||
GetEnemyEncounterCode() == ENEMY_AMBUSH_DEPLOYMENT_CODE ||
((gGameExternalOptions.ubSkyriderHotLZ == 1 || gGameExternalOptions.ubSkyriderHotLZ == 3) && gMercPlacement[gbSelectedMercID].pSoldier->usSoldierFlagMask & SOLDIER_AIRDROP )) )
{
if ( GetEnemyEncounterCode() == ENEMY_AMBUSH_DEPLOYMENT_CODE )
{
INT32 testgridno = NOWHERE;
if ( GetOverheadMouseGridNo( &testgridno ) && PythSpacesAway( testgridno, gMapInformation.sCenterGridNo ) < gGameExternalOptions.usAmbushSpreadRadiusMercs )
{
gfValidCursor = TRUE;
}
}
else if( gMercPlacement[gbCursorMercID].ubStrategicInsertionCode == INSERTION_CODE_CENTER || (gGameExternalOptions.ubSkyriderHotLZ == 1 && gMercPlacement[gbCursorMercID].ubStrategicInsertionCode == INSERTION_CODE_CHOPPER))
{
if (gusMouseYPos >= (iOffsetVertical + CENTERENTRYPTS_TOP_Y) && // N
gusMouseYPos <= (iOffsetVertical + CENTERENTRYPTS_BOTTOM_Y) && // S
gusMouseXPos >= (iOffsetHorizontal + CENTERENTRYPTS_LEFT_X) && // W
gusMouseXPos <= (iOffsetHorizontal + CENTERENTRYPTS_RIGHT_X)) // E
{
gfValidCursor = TRUE;
}
}
else if ( gMercPlacement[ gbCursorMercID ].ubStrategicInsertionCode == INSERTION_CODE_CHOPPER )
{
if (gusMouseYPos >= (iOffsetVertical + AIRDROPENTRYPTS_TOP_Y) && // N
gusMouseYPos <= (iOffsetVertical + AIRDROPENTRYPTS_BOTTOM_Y) && // S
gusMouseXPos >= (iOffsetHorizontal + AIRDROPENTRYPTS_LEFT_X) && // W
gusMouseXPos <= (iOffsetHorizontal + AIRDROPENTRYPTS_RIGHT_X)) // E
{
gfValidCursor = TRUE;
}
}
}
if( gubDefaultButton == GROUP_BUTTON )
{
if( gfValidCursor )
{
SetCurrentCursorFromDatabase( CURSOR_PLACEGROUP );
}
else
{
SetCurrentCursorFromDatabase( CURSOR_DPLACEGROUP );
}
}
else
{
if( gfValidCursor )
{
SetCurrentCursorFromDatabase( CURSOR_PLACEMERC );
}
else
{
SetCurrentCursorFromDatabase( CURSOR_DPLACEMERC );
}
}
}
else
{
SetCurrentCursorFromDatabase( CURSOR_NORMAL );
}
if( gfKillTacticalGUI == 1 )
{
if(is_client)
{
gfKillTacticalGUI = FALSE;
send_donegui(0);
}
if(!is_client)KillTacticalPlacementGUI();
}
else if( gfKillTacticalGUI == 2 )
{
gfKillTacticalGUI = 1;
}
ScrollOverheadMap();//dnl ch45 021009
}
void KillTacticalPlacementGUI()
{
INT32 i;
gbHilightedMercID = -1;
gbSelectedMercID = -1;
gubSelectedGroupID = 0;
gubHilightedGroupID = 0;
gbCursorMercID = -1;
gpTacticalPlacementHilightedSoldier = NULL;
gpTacticalPlacementSelectedSoldier = NULL;
//Destroy the tactical placement gui.
gfEnterTacticalPlacementGUI = FALSE;
gfTacticalPlacementGUIActive = FALSE;
gfKillTacticalGUI = FALSE;
//Delete video objects
DeleteVideoObjectFromIndex( giOverheadPanelImage );
DeleteVideoObjectFromIndex( giMercPanelImage );
//Delete buttons
for( i = 0; i < NUM_TP_BUTTONS; i++ )
{
UnloadButtonImage( giOverheadButtonImages[ i ] );
RemoveButton( iTPButtons[ i ] );
}
//Delete faces and regions
for( i = 0; i < giPlacements; i++ )
{
DeleteVideoObjectFromIndex( gMercPlacement[ i ].uiVObjectID );
MSYS_RemoveRegion( &gMercPlacement[ i ].region );
}
if( gsCurInterfacePanel < 0 || gsCurInterfacePanel >= NUM_UI_PANELS )
gsCurInterfacePanel = TEAM_PANEL;
SetCurrentInterfacePanel( (UINT8)gsCurInterfacePanel );
//Leave the overhead map.
KillOverheadMap();
//Recreate the tactical panel.
MSYS_EnableRegion(&gRadarRegion);
SetCurrentInterfacePanel( TEAM_PANEL );
//Initialize the rest of the map (AI, enemies, civs, etc.)
for( i = 0; i < giPlacements; i++ )
{
PickUpMercPiece( i );
}
PrepareLoadedSector();
EnableScrollMessages();
#ifdef JA2BETAVERSION
if( gfChangedEntrySide )
{
ScreenMsg( FONT_RED, MSG_ERROR, L"Substituted different entry side due to invalid entry points or map edgepoints. KM, LC : 1" );
}
#endif
MemFree( gMercPlacement);
}
void ChooseRandomEdgepoints()
{
INT32 i;
UINT8 lastValidICode = INSERTION_CODE_GRIDNO;
for( i = 0; i < giPlacements; i++ )
{
if ( !( gMercPlacement[ i ].pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) )
{
if ( GetEnemyEncounterCode() == ENEMY_AMBUSH_DEPLOYMENT_CODE )
{
UINT8 ubDirection;
gMercPlacement[i].pSoldier->usStrategicInsertionData = FindRandomGridNoFromSweetSpotExcludingSweetSpot( gMercPlacement[i].pSoldier, gMapInformation.sCenterGridNo, gGameExternalOptions.usAmbushSpreadRadiusMercs, &ubDirection );
// have the merc look outward. We add + 100 because later on we use this to signify that we want really enforce this direction
gMercPlacement[i].pSoldier->ubInsertionDirection = (UINT8)GetDirectionToGridNoFromGridNo( gMapInformation.sCenterGridNo, gMercPlacement[i].pSoldier->usStrategicInsertionData ) + 100;
}
else
{
gMercPlacement[ i ].pSoldier->usStrategicInsertionData = ChooseMapEdgepoint( &gMercPlacement[ i ].ubStrategicInsertionCode, lastValidICode );
}
if( !TileIsOutOfBounds(gMercPlacement[ i ].pSoldier->usStrategicInsertionData))
{
gMercPlacement[ i ].pSoldier->ubStrategicInsertionCode = INSERTION_CODE_GRIDNO;
lastValidICode = gMercPlacement[ i ].ubStrategicInsertionCode;
}
else
{
gMercPlacement[ i ].pSoldier->ubStrategicInsertionCode = gMercPlacement[ i ].ubStrategicInsertionCode;
}
}
PutDownMercPiece( i );
}
gfEveryonePlaced = TRUE;
}
void PlaceMercs()
{
INT32 i;
switch( gubDefaultButton )
{
case SPREAD_BUTTON: //Place mercs randomly along their side using map edgepoints.
ChooseRandomEdgepoints();
break;
case CLEAR_BUTTON:
for( i = 0; i < giPlacements; i++ )
{
PickUpMercPiece( i );
}
if (ButtonList[iTPButtons[SPREAD_BUTTON]]->uiFlags & BUTTON_ENABLED)
{
gubSelectedGroupID = 0;
gbSelectedMercID = 0;
SetCursorMerc(0);
}
else//spread button disabled mean hotdrop
{
gubSelectedGroupID = gMercPlacement[0].pSoldier->ubGroupID;
ButtonList[iTPButtons[GROUP_BUTTON]]->uiFlags |= BUTTON_CLICKED_ON | BUTTON_DIRTY;
gubDefaultButton = GROUP_BUTTON;
gbSelectedMercID = 0;
SetCursorMerc(gbSelectedMercID);
}
gfEveryonePlaced = FALSE;
break;
default:
return;
}
gfTacticalPlacementGUIDirty = TRUE;
}
void DoneOverheadPlacementClickCallback( GUI_BUTTON *btn, INT32 reason )
{
if( reason & MSYS_CALLBACK_REASON_LBUTTON_UP )
{
gfKillTacticalGUI = 2;
}
}
void SpreadPlacementsCallback ( GUI_BUTTON *btn, INT32 reason )
{
if( reason & MSYS_CALLBACK_REASON_LBUTTON_UP )
{
gubDefaultButton = SPREAD_BUTTON;
ButtonList[ iTPButtons[ GROUP_BUTTON ] ]->uiFlags &= ~BUTTON_CLICKED_ON;
ButtonList[ iTPButtons[ GROUP_BUTTON ] ]->uiFlags |= BUTTON_DIRTY;
PlaceMercs();
gubSelectedGroupID = 0;
gbSelectedMercID = -1;
SetCursorMerc( -1 );
}
}
void GroupPlacementsCallback( GUI_BUTTON *btn, INT32 reason )
{
if( reason & MSYS_CALLBACK_REASON_LBUTTON_UP )
{
if( gubDefaultButton == GROUP_BUTTON )
{
btn->uiFlags &= ~BUTTON_CLICKED_ON;
btn->uiFlags |= BUTTON_DIRTY;
if (ButtonList[iTPButtons[SPREAD_BUTTON]]->uiFlags & BUTTON_ENABLED)
{
gubDefaultButton = CLEAR_BUTTON;
gubSelectedGroupID = 0;
}
else//spread button disabled mean hotdrop
{
gubDefaultButton = CLEAR_BUTTON;
gubSelectedGroupID = 0;
gbSelectedMercID = -1;
SetCursorMerc(gbSelectedMercID);
}
}
else
{
btn->uiFlags |= BUTTON_CLICKED_ON | BUTTON_DIRTY;
gubDefaultButton = GROUP_BUTTON;
gbSelectedMercID = 0;
SetCursorMerc( gbSelectedMercID );
gubSelectedGroupID = gMercPlacement[ gbSelectedMercID ].pSoldier->ubGroupID;
}
}
}
void ClearPlacementsCallback( GUI_BUTTON *btn, INT32 reason )
{
if( reason & MSYS_CALLBACK_REASON_LBUTTON_UP )
{
ButtonList[ iTPButtons[ GROUP_BUTTON ] ]->uiFlags &= ~BUTTON_CLICKED_ON;
ButtonList[ iTPButtons[ GROUP_BUTTON ] ]->uiFlags |= BUTTON_DIRTY;
gubDefaultButton = CLEAR_BUTTON;
PlaceMercs();
}
}
void MercMoveCallback( MOUSE_REGION *reg, INT32 reason )
{
if( reg->uiFlags & MSYS_MOUSE_IN_AREA )
{
INT8 i;
for( i = 0; i < giPlacements; i++ )
{
if( &gMercPlacement[ i ].region == reg )
{
if( gbHilightedMercID != i )
{
gbHilightedMercID = i;
if( gubDefaultButton == GROUP_BUTTON )
gubHilightedGroupID = gMercPlacement[ i ].pSoldier->ubGroupID;
SetCursorMerc( i );
gpTacticalPlacementHilightedSoldier = gMercPlacement[ i ].pSoldier;
}
return;
}
}
}
}
void MercClickCallback( MOUSE_REGION *reg, INT32 reason )
{
if(islocked != 1)//hayden
{
if( reason & MSYS_CALLBACK_REASON_LBUTTON_DWN )
{
INT8 i;
for( i = 0; i < giPlacements; i++ )
{
if( &gMercPlacement[ i ].region == reg )
{
if( gbSelectedMercID != i )
{
if ((gGameExternalOptions.ubSkyriderHotLZ == 1 || gGameExternalOptions.ubSkyriderHotLZ == 3) && gMercPlacement[ i ].pSoldier->usSoldierFlagMask & SOLDIER_AIRDROP )
gubDefaultButton = GROUP_BUTTON;
gbSelectedMercID = i;
gpTacticalPlacementSelectedSoldier = gMercPlacement[ i ].pSoldier;
if( gubDefaultButton == GROUP_BUTTON )
{
gubSelectedGroupID = gpTacticalPlacementSelectedSoldier->ubGroupID;
}
}
return;
}
}
}
}
}
void SelectNextUnplacedUnit()
{
INT32 i;
if( gbSelectedMercID == -1 )
return;
if ((gGameExternalOptions.ubSkyriderHotLZ == 1 || gGameExternalOptions.ubSkyriderHotLZ == 3) && gMercPlacement[ gbSelectedMercID ].pSoldier->usSoldierFlagMask & SOLDIER_AIRDROP )
gubDefaultButton = GROUP_BUTTON;
for( i = gbSelectedMercID; i < giPlacements; ++i )
{ //go from the currently selected soldier to the end
if( !gMercPlacement[ i ].fPlaced )
{ //Found an unplaced merc. Select him.
gbSelectedMercID = (INT8)i;
if( gubDefaultButton == GROUP_BUTTON )
gubSelectedGroupID = gMercPlacement[ i ].pSoldier->ubGroupID;
gfTacticalPlacementGUIDirty = TRUE;
SetCursorMerc( (INT8)i );
gpTacticalPlacementSelectedSoldier = gMercPlacement[ i ].pSoldier;
return;
}
}
for( i = 0; i < gbSelectedMercID; ++i )
{ //go from the beginning to the currently selected soldier
if( !gMercPlacement[ i ].fPlaced )
{ //Found an unplaced merc. Select him.
gbSelectedMercID = (INT8)i;
if( gubDefaultButton == GROUP_BUTTON )
gubSelectedGroupID = gMercPlacement[ i ].pSoldier->ubGroupID;
gfTacticalPlacementGUIDirty = TRUE;
SetCursorMerc( (INT8)i );
gpTacticalPlacementSelectedSoldier = gMercPlacement[ i ].pSoldier;
return;
}
}
//checked the whole array, and everybody has been placed. Select nobody.
if( !gfEveryonePlaced )
{
gfEveryonePlaced = TRUE;
SetCursorMerc( -1 );
gbSelectedMercID = -1;
gubSelectedGroupID = 0;
gfTacticalPlacementGUIDirty = TRUE;
gfValidLocationsChanged = TRUE;
gpTacticalPlacementSelectedSoldier = gMercPlacement[ i ].pSoldier;
}
}
void HandleTacticalPlacementClicksInOverheadMap( MOUSE_REGION *reg, INT32 reason )
{
INT32 i;
INT32 sGridNo;
BOOLEAN fInvalidArea = FALSE;
UINT8 lastValidICode = INSERTION_CODE_GRIDNO;
if( reason & MSYS_CALLBACK_REASON_LBUTTON_UP )
{ //if we have a selected merc, move him to the new closest map edgepoint of his side.
if( gfValidCursor )
{
if( gbSelectedMercID != -1 )
{
if ((gGameExternalOptions.ubSkyriderHotLZ == 1 || gGameExternalOptions.ubSkyriderHotLZ == 3) && gMercPlacement[ gbSelectedMercID ].pSoldier->usSoldierFlagMask & SOLDIER_AIRDROP )
gubDefaultButton = GROUP_BUTTON;
if( GetOverheadMouseGridNo( &sGridNo ) )
{ //we have clicked within a valid part of the map.
BeginMapEdgepointSearch();
if( gubDefaultButton == GROUP_BUTTON )
{ //We are placing a whole group.
for( i = 0; i < giPlacements; i++ )
{ //Find locations of each member of the group, but don't place them yet. If
//one of the mercs can't be placed, then we won't place any, and tell the user
//the problem. If everything's okay, we will place them all.
if( gMercPlacement[ i ].pSoldier->ubGroupID == gubSelectedGroupID )
{
gMercPlacement[ i ].pSoldier->usStrategicInsertionData = SearchForClosestPrimaryMapEdgepoint( sGridNo, gMercPlacement[ i ].ubStrategicInsertionCode, lastValidICode, &gMercPlacement[ i ].ubStrategicInsertionCode );
if(TileIsOutOfBounds(gMercPlacement[ i ].pSoldier->usStrategicInsertionData))
{
fInvalidArea = TRUE;
break;
}
else
lastValidICode = gMercPlacement[ i ].ubStrategicInsertionCode;
}
}
if( !fInvalidArea )
{ //One or more of the mercs in the group didn't get gridno assignments, so we
//report an error.
for( i = 0; i < giPlacements; i++ )
{
gMercPlacement[ i ].pSoldier->ubStrategicInsertionCode = INSERTION_CODE_GRIDNO;
if( gMercPlacement[ i ].pSoldier->ubGroupID == gubSelectedGroupID )
{
PutDownMercPiece( i );
}
}
}
}
else
{ //This is a single merc placement. If valid, then place him, else report error.
gMercPlacement[ gbSelectedMercID ].pSoldier->usStrategicInsertionData = SearchForClosestPrimaryMapEdgepoint( sGridNo, gMercPlacement[ gbSelectedMercID ].ubStrategicInsertionCode );
if( !TileIsOutOfBounds(gMercPlacement[ gbSelectedMercID ].pSoldier->usStrategicInsertionData))
{
gMercPlacement[ gbSelectedMercID ].pSoldier->ubStrategicInsertionCode = INSERTION_CODE_GRIDNO;
PutDownMercPiece( gbSelectedMercID );
}
else
{
fInvalidArea = TRUE;
}
//gbSelectedMercID++;
//if( gbSelectedMercID == giPlacements )
// gbSelectedMercID = 0;
//gpTacticalPlacementSelectedSoldier = gMercPlacement[ gbSelectedMercID ].pSoldier;
gfTacticalPlacementGUIDirty = TRUE;
//SetCursorMerc( gbSelectedMercID );
}
EndMapEdgepointSearch();
if( fInvalidArea )
{
// Only display the error message, when the cursor is on the overview map
if (gusMouseYPos < (iOffsetVertical + 320) && gusMouseYPos > iOffsetVertical
&& gusMouseXPos > iOffsetHorizontal && gusMouseXPos < (iOffsetHorizontal + 640))
{
//Report error due to invalid placement.
SGPRect CenterRect = { 100 + xResOffset, 100 + 0, SCREEN_WIDTH - 100 - xResOffset, 300 };
DoMessageBox( MSG_BOX_BASIC_STYLE, gpStrategicString[ STR_TP_INACCESSIBLE_MESSAGE ], guiCurrentScreen, MSG_BOX_FLAG_OK | MSG_BOX_FLAG_USE_CENTERING_RECT, DialogRemoved, &CenterRect );
}
}
else
{ //Placement successful, so select the next unplaced unit (single or group).
SelectNextUnplacedUnit();
}
}
}
}
else
{ //not a valid cursor location...
if( gbCursorMercID != - 1 )
{
// Only display the error message, when the cursor is on the overview map
if (gusMouseYPos < (iOffsetVertical + 320) && gusMouseYPos > iOffsetVertical
&& gusMouseXPos > iOffsetHorizontal && gusMouseXPos < (iOffsetHorizontal + 640))
{
SGPRect CenterRect = { 100 + xResOffset, 100, SCREEN_WIDTH - 100 - xResOffset, 300 };
DoMessageBox( MSG_BOX_BASIC_STYLE, gpStrategicString[ STR_TP_INVALID_MESSAGE ], guiCurrentScreen, MSG_BOX_FLAG_OK | MSG_BOX_FLAG_USE_CENTERING_RECT, DialogRemoved, &CenterRect );
}
}
}
}
}
void SetCursorMerc( INT8 bPlacementID )
{
if( gbCursorMercID != bPlacementID )
{
if( gbCursorMercID == -1 || bPlacementID == -1 ||
gMercPlacement[ gbCursorMercID ].ubStrategicInsertionCode != gMercPlacement[ bPlacementID ].ubStrategicInsertionCode )
gfValidLocationsChanged = TRUE;
gbCursorMercID = bPlacementID;
}
}
void PutDownMercPiece( INT32 iPlacement )
{
INT32 sGridNo;
INT16 sCellX, sCellY;
UINT8 ubDirection;
SOLDIERTYPE *pSoldier;
pSoldier = gMercPlacement[ iPlacement ].pSoldier;
switch( pSoldier->ubStrategicInsertionCode )
{
case INSERTION_CODE_NORTH:
pSoldier->sInsertionGridNo = gMapInformation.sNorthGridNo;
break;
case INSERTION_CODE_SOUTH:
pSoldier->sInsertionGridNo = gMapInformation.sSouthGridNo;
break;
case INSERTION_CODE_EAST:
pSoldier->sInsertionGridNo = gMapInformation.sEastGridNo;
break;
case INSERTION_CODE_WEST:
pSoldier->sInsertionGridNo = gMapInformation.sWestGridNo;
break;
case INSERTION_CODE_GRIDNO:
pSoldier->sInsertionGridNo = pSoldier->usStrategicInsertionData;
break;
case INSERTION_CODE_CHOPPER:
pSoldier->sInsertionGridNo = pSoldier->usStrategicInsertionData;
break;
default:
Assert( 0 );
break;
}
if( gMercPlacement[ iPlacement ].fPlaced )
PickUpMercPiece( iPlacement );
sGridNo = FindGridNoFromSweetSpot( pSoldier, pSoldier->sInsertionGridNo, 4, &ubDirection );
if(!TileIsOutOfBounds(sGridNo))
{
// Flugente: initiate airdrop, place merc on roof if necessary
if ((gGameExternalOptions.ubSkyriderHotLZ == 1 || gGameExternalOptions.ubSkyriderHotLZ == 3) && pSoldier->usSoldierFlagMask & SOLDIER_AIRDROP )
{
// hideous hack
gfTacticalDoHeliRun = TRUE;
SetHelicopterDroppoint(sGridNo);
pSoldier->usStrategicInsertionData = sGridNo;
if ( FindStructure( sGridNo, STRUCTURE_NORMAL_ROOF ) != NULL && NewOKDestination( pSoldier, sGridNo, false, 1 ) )
{
pSoldier->SetSoldierHeight( (FLOAT)58 );
}
}
ConvertGridNoToCellXY( sGridNo, &sCellX, &sCellY );
FLOAT scX = (FLOAT)sCellX;
FLOAT scY = (FLOAT)sCellY;//hayden
if (is_networked)
{
pSoldier->EVENT_SetSoldierPosition( scX, scY );
}
else
{
pSoldier->EVENT_SetSoldierPosition( (FLOAT)sCellX, (FLOAT)sCellY );
}
if ( GetEnemyEncounterCode() == ENEMY_AMBUSH_DEPLOYMENT_CODE )
{
ubDirection = (UINT8)GetDirectionToGridNoFromGridNo( gMapInformation.sCenterGridNo, sGridNo );
}
pSoldier->EVENT_SetSoldierDirection( ubDirection );
ubDirection += 100;
pSoldier->ubInsertionDirection = ubDirection;
gMercPlacement[ iPlacement ].fPlaced = TRUE;
gMercPlacement[ iPlacement ].pSoldier->bInSector = TRUE;
//hayden
if(is_client)send_gui_pos(pSoldier, scX, scY);
if(is_client)send_gui_dir(pSoldier, ubDirection);
}
}
void PickUpMercPiece( INT32 iPlacement )
{
gMercPlacement[ iPlacement ].pSoldier->RemoveSoldierFromGridNo( );
gMercPlacement[ iPlacement ].fPlaced = FALSE;
gMercPlacement[ iPlacement ].pSoldier->bInSector = FALSE;
}
void FastHelpRemovedCallback()
{
gfTacticalPlacementGUIDirty = TRUE;
}
void FastHelpRemoved2Callback()
{
gfTacticalPlacementGUIDirty = TRUE;
gfValidLocationsChanged = 2; //because fast help text covers it.
}
void DialogRemoved( UINT8 ubResult )
{
gfTacticalPlacementGUIDirty = TRUE;
gfValidLocationsChanged = TRUE;
}