mirror of
https://github.com/1dot13/source.git
synced 2026-07-22 13:40:22 +02:00
Added missing #includes Added LUA scripting and console Changed the way tracers are visualized, so they work more like real tracers instead of a light fountain Fixed signedness of many grid variables used in GetMouseMapPos calls Fixed enemy weapon choosing: Sometimes a mortar is chosen but later rejected, but the grenade class was not reset. Caused assertion failure Added checks so enemies don't try to chuck RPG grenades with their hands Now possible to shoot a someone in the head if he's in water Fixed InitSightArrays to also clear soldier interrupt duel points. This was causing an assertion failure elsewhere in the code because the interrupt list still had soldiers on it sometimes when this function was called. Soldiers are much less willing to forfeit their turn over an attempt to use more APs than they have Removed early setting of muzzle flash. This would allow enemies to get an interrupt before you even fired. Fixed item dropping by AI. If AI tried to drop something while standing it would cause deadlock Change to greatly speed up closing the sector inventory window in an unloaded sector Added conditional compile flag to always give robot weapon ready advantage, even for 360 degree sighting Check builddefines.h for the conditional flags. Of greatest interest might be LUA_CONSOLE. This will cause the game to bring up a command console when run. However this console is severely lacking in many areas. If anybody knows of an open-source terminal/console that could be used instead, it would be appreciated. The existing console does bad things when you try to close it, and since it counts as a separate app, it pauses the game while it has focus. LUA scripting is very limited, basically just proof of concept. There is one global variable, the Soldiers array. An array index gives you the soldier in that slot in the currently loaded sector. The soldier has a few things that can be accessed: name (short name); fullname (long name); grid (current grid #, can be changed); walkto(grid) (function to walk to another grid); runto(grid) (function to run to another grid) git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@924 3b4a5df2-a311-0410-b5c6-a8a6f20db521
1213 lines
39 KiB
C++
1213 lines
39 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 "types.h"
|
|
#include "mousesystem.h"
|
|
#include "Button System.h"
|
|
#include "input.h"
|
|
#include "english.h"
|
|
#include "debug.h"
|
|
#include "vsurface.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 "Font Control.h"
|
|
#include "overhead.h"
|
|
#include "Render Dirty.h"
|
|
#include "sysutil.h"
|
|
#include "PreBattle Interface.h"
|
|
#include "Soldier Profile.h"
|
|
#include "Map Edgepoints.h"
|
|
#include "strategic.h"
|
|
#include "strategicmap.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 "assignments.h"
|
|
#include "text.h"
|
|
#include "WordWrap.h"
|
|
#include "Game Clock.h"
|
|
#endif
|
|
|
|
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 ];
|
|
|
|
extern BOOLEAN gfOverheadMapDirty;
|
|
extern BOOLEAN GetOverheadMouseGridNo( INT16 *psGridNo );
|
|
|
|
extern int iOffsetHorizontal;
|
|
extern int iOffsetVertical;
|
|
|
|
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};
|
|
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;
|
|
|
|
BOOLEAN gfNorth, gfEast, gfSouth, gfWest;
|
|
|
|
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();
|
|
|
|
#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();
|
|
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
|
|
|
|
|
|
void InitTacticalPlacementGUI()
|
|
{
|
|
VOBJECT_DESC VObjectDesc;
|
|
INT32 i, xp, yp;
|
|
UINT8 ubFaceIndex;
|
|
gfTacticalPlacementGUIActive = TRUE;
|
|
gfTacticalPlacementGUIDirty = TRUE;
|
|
gfValidLocationsChanged = TRUE;
|
|
gfTacticalPlacementFirstTime = TRUE;
|
|
gfNorth = gfEast = gfSouth = gfWest = FALSE;
|
|
#ifdef JA2BETAVERSION
|
|
gfNorthValid = gfEastValid = gfSouthValid = gfWestValid = FALSE;
|
|
gfChangedEntrySide = FALSE;
|
|
#endif
|
|
|
|
//Enter overhead map
|
|
GoIntoOverheadMap();
|
|
|
|
//Load the images
|
|
VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE;
|
|
|
|
if (iResolution == 0)
|
|
{
|
|
sprintf( VObjectDesc.ImageFile, "Interface\\OverheadInterface.sti" );
|
|
if( !AddVideoObject( &VObjectDesc, (UINT32 *)&giOverheadPanelImage ) )
|
|
{
|
|
AssertMsg( 0, "Failed to load Interface\\OverheadInterface.sti" );
|
|
}
|
|
}
|
|
else if (iResolution == 1)
|
|
{
|
|
sprintf( VObjectDesc.ImageFile, "Interface\\OverheadInterface_800x600.sti" );
|
|
if( !AddVideoObject( &VObjectDesc, (UINT32 *)&giOverheadPanelImage ) )
|
|
{
|
|
AssertMsg( 0, "Failed to load Interface\\OverheadInterface_800x600.sti" );
|
|
}
|
|
}
|
|
else if (iResolution == 2)
|
|
{
|
|
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, 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, 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, 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, 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 ]->fBetweenSectors &&
|
|
MercPtrs[ i ]->sSectorX == gpBattleGroup->ubSectorX &&
|
|
MercPtrs[ i ]->sSectorY == gpBattleGroup->ubSectorY &&
|
|
!( MercPtrs[ i ]->uiStatusFlags & ( SOLDIER_VEHICLE ) ) && // ATE Ignore vehicles
|
|
MercPtrs[ i ]->bAssignment != ASSIGNMENT_POW &&
|
|
MercPtrs[ i ]->bAssignment != IN_TRANSIT &&
|
|
!MercPtrs[ i ]->bSectorZ )
|
|
{
|
|
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 ]->bLife && !MercPtrs[ i ]->fBetweenSectors &&
|
|
MercPtrs[ i ]->sSectorX == gpBattleGroup->ubSectorX &&
|
|
MercPtrs[ i ]->sSectorY == gpBattleGroup->ubSectorY &&
|
|
MercPtrs[ i ]->bAssignment != ASSIGNMENT_POW &&
|
|
MercPtrs[ i ]->bAssignment != IN_TRANSIT &&
|
|
!( MercPtrs[ i ]->uiStatusFlags & ( SOLDIER_VEHICLE ) ) && // ATE Ignore vehicles
|
|
!MercPtrs[ i ]->bSectorZ )
|
|
{
|
|
|
|
// ATE: If we are in a vehicle - remove ourselves from it!
|
|
//if ( MercPtrs[ i ]->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;
|
|
#ifdef JA2BETAVERSION
|
|
CheckForValidMapEdge( &MercPtrs[ i ]->ubStrategicInsertionCode );
|
|
#endif
|
|
switch( MercPtrs[ i ]->ubStrategicInsertionCode )
|
|
{
|
|
case INSERTION_CODE_NORTH:
|
|
gfNorth = TRUE;
|
|
break;
|
|
case INSERTION_CODE_EAST:
|
|
gfEast = TRUE;
|
|
break;
|
|
case INSERTION_CODE_SOUTH:
|
|
gfSouth = TRUE;
|
|
break;
|
|
case INSERTION_CODE_WEST:
|
|
gfWest = TRUE;
|
|
break;
|
|
}
|
|
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 )
|
|
sprintf( VObjectDesc.ImageFile, "Faces\\65Face\\%02d.sti", ubFaceIndex );
|
|
else
|
|
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 = 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 );
|
|
}
|
|
|
|
PlaceMercs();
|
|
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
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 = 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, 0, SCREEN_HEIGHT - 160, VO_BLT_SRCTRANSPARENCY, 0 );
|
|
InvalidateRegion( 0, SCREEN_HEIGHT - 160, 320, SCREEN_HEIGHT );
|
|
gfTacticalPlacementGUIDirty = FALSE;
|
|
MarkButtonsDirty();
|
|
//DisableHilightsAndHelpText();
|
|
//RenderButtons();
|
|
//EnableHilightsAndHelpText();
|
|
for( i = 0; i < giPlacements; i++ )
|
|
{ //Render the mercs
|
|
pSoldier = gMercPlacement[ i ].pSoldier;
|
|
|
|
|
|
xp = 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->bLife )
|
|
continue;
|
|
//yellow one for bleeding
|
|
iStartY = yp + 29 - 27*pSoldier->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 += 27*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->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->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, 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--;
|
|
BlitBufferToBuffer( guiSAVEBUFFER, FRAME_BUFFER, iOffsetHorizontal, iOffsetVertical, 640, 320 );
|
|
InvalidateRegion( iOffsetHorizontal, iOffsetVertical, iOffsetHorizontal + 640, iOffsetVertical + 320 );
|
|
if( gbCursorMercID == -1 )
|
|
{
|
|
// WANNE 2
|
|
gTPClipRect.iLeft = gfWest ? iOffsetHorizontal + 30 : iOffsetHorizontal;
|
|
gTPClipRect.iTop = gfNorth ? iOffsetVertical + 30 + 3 : iOffsetVertical + 3;
|
|
gTPClipRect.iRight = gfEast ? iOffsetHorizontal + 610 : iOffsetHorizontal + 634; // 636
|
|
gTPClipRect.iBottom = gfSouth ? iOffsetVertical + 290 : iOffsetVertical + 320;
|
|
}
|
|
else
|
|
{
|
|
gTPClipRect.iLeft = iOffsetHorizontal;
|
|
gTPClipRect.iTop = iOffsetVertical + 3;
|
|
// WANNE 2
|
|
//gTPClipRect.iRight = iOffsetHorizontal + 640;
|
|
gTPClipRect.iRight = iOffsetHorizontal + 634; // 635
|
|
gTPClipRect.iBottom = iOffsetVertical + 320;
|
|
switch( gMercPlacement[ gbCursorMercID ].ubStrategicInsertionCode )
|
|
{
|
|
case INSERTION_CODE_NORTH: gTPClipRect.iTop = iOffsetVertical + 30 + 3; break;
|
|
case INSERTION_CODE_EAST: gTPClipRect.iRight = iOffsetHorizontal + 610; break;
|
|
case INSERTION_CODE_SOUTH: gTPClipRect.iBottom = iOffsetVertical + 290; break;
|
|
case INSERTION_CODE_WEST: gTPClipRect.iLeft = iOffsetHorizontal + 30; break;
|
|
}
|
|
}
|
|
pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES );
|
|
Blt16BPPBufferLooseHatchRectWithColor( (UINT16*)pDestBuf, uiDestPitchBYTES, &gTPClipRect, usHatchColor );
|
|
SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT );
|
|
RectangleDraw( TRUE, gTPClipRect.iLeft, gTPClipRect.iTop, gTPClipRect.iRight, gTPClipRect.iBottom, usHatchColor, pDestBuf );
|
|
UnLockVideoSurface( FRAME_BUFFER );
|
|
}
|
|
for( i = 0; i < giPlacements; i++ )
|
|
{ //Render the merc's names
|
|
pSoldier = gMercPlacement[ i ].pSoldier;
|
|
|
|
xp = 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 TacticalPlacementHandle()
|
|
{
|
|
InputAtom InputEvent;
|
|
|
|
EnsureDoneButtonStatus();
|
|
|
|
RenderTacticalPlacementGUI();
|
|
|
|
if( gfRightButtonState )
|
|
{
|
|
gbSelectedMercID = -1;
|
|
gubSelectedGroupID = 0;
|
|
gpTacticalPlacementSelectedSoldier = NULL;
|
|
}
|
|
|
|
while( DequeueEvent( &InputEvent ) )
|
|
{
|
|
if( InputEvent.usEvent == KEY_DOWN )
|
|
{
|
|
switch( InputEvent.usParam )
|
|
{
|
|
#ifdef JA2TESTVERSION
|
|
case ESC:
|
|
KillTacticalPlacementGUI();
|
|
break;
|
|
#endif
|
|
case ENTER:
|
|
if( ButtonList[ iTPButtons[ DONE_BUTTON ] ]->uiFlags & BUTTON_ENABLED )
|
|
{
|
|
KillTacticalPlacementGUI();
|
|
}
|
|
break;
|
|
case 'c':
|
|
ClearPlacementsCallback( ButtonList[ iTPButtons[ CLEAR_BUTTON ] ], MSYS_CALLBACK_REASON_LBUTTON_UP );
|
|
break;
|
|
case 'g':
|
|
GroupPlacementsCallback( ButtonList[ iTPButtons[ GROUP_BUTTON ] ], MSYS_CALLBACK_REASON_LBUTTON_UP );
|
|
break;
|
|
case 's':
|
|
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))
|
|
{
|
|
switch( gMercPlacement[ gbCursorMercID ].ubStrategicInsertionCode )
|
|
{
|
|
case INSERTION_CODE_NORTH:
|
|
if( gusMouseYPos <= (iOffsetVertical + 30) ) // 40
|
|
gfValidCursor = TRUE;
|
|
break;
|
|
case INSERTION_CODE_EAST:
|
|
if( gusMouseXPos >= (iOffsetHorizontal + 610) ) // 600
|
|
gfValidCursor = TRUE;
|
|
break;
|
|
case INSERTION_CODE_SOUTH:
|
|
if( gusMouseYPos >= (iOffsetVertical + 290) ) // 280
|
|
gfValidCursor = TRUE;
|
|
break;
|
|
case INSERTION_CODE_WEST:
|
|
if( gusMouseXPos <= (iOffsetHorizontal + 30) ) // 40
|
|
gfValidCursor = TRUE;
|
|
break;
|
|
}
|
|
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 )
|
|
{
|
|
KillTacticalPlacementGUI();
|
|
}
|
|
else if( gfKillTacticalGUI == 2 )
|
|
{
|
|
gfKillTacticalGUI = 1;
|
|
}
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
void ChooseRandomEdgepoints()
|
|
{
|
|
INT32 i;
|
|
for( i = 0; i < giPlacements; i++ )
|
|
{
|
|
if ( !( gMercPlacement[ i ].pSoldier->uiStatusFlags & SOLDIER_VEHICLE ) )
|
|
{
|
|
gMercPlacement[ i ].pSoldier->usStrategicInsertionData = ChooseMapEdgepoint( gMercPlacement[ i ].ubStrategicInsertionCode );
|
|
if( gMercPlacement[ i ].pSoldier->usStrategicInsertionData != NOWHERE )
|
|
{
|
|
gMercPlacement[ i ].pSoldier->ubStrategicInsertionCode = INSERTION_CODE_GRIDNO;
|
|
}
|
|
else
|
|
{
|
|
if( gMercPlacement[ i ].pSoldier->usStrategicInsertionData < 0 || gMercPlacement[ i ].pSoldier->usStrategicInsertionData > WORLD_MAX )
|
|
{
|
|
i = i;
|
|
}
|
|
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 );
|
|
}
|
|
gubSelectedGroupID = 0;
|
|
gbSelectedMercID = 0;
|
|
SetCursorMerc( 0 );
|
|
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;
|
|
gubDefaultButton = CLEAR_BUTTON;
|
|
gubSelectedGroupID = 0;
|
|
}
|
|
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( reason & MSYS_CALLBACK_REASON_LBUTTON_DWN )
|
|
{
|
|
INT8 i;
|
|
for( i = 0; i < giPlacements; i++ )
|
|
{
|
|
if( &gMercPlacement[ i ].region == reg )
|
|
{
|
|
if( gbSelectedMercID != i )
|
|
{
|
|
gbSelectedMercID = i;
|
|
gpTacticalPlacementSelectedSoldier = gMercPlacement[ i ].pSoldier;
|
|
if( gubDefaultButton == GROUP_BUTTON )
|
|
{
|
|
gubSelectedGroupID = gpTacticalPlacementSelectedSoldier->ubGroupID;
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void SelectNextUnplacedUnit()
|
|
{
|
|
INT32 i;
|
|
if( gbSelectedMercID == -1 )
|
|
return;
|
|
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;
|
|
INT16 sGridNo;
|
|
BOOLEAN fInvalidArea = FALSE;
|
|
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( 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 );
|
|
if( gMercPlacement[ i ].pSoldier->usStrategicInsertionData == NOWHERE )
|
|
{
|
|
fInvalidArea = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
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( gMercPlacement[ gbSelectedMercID ].pSoldier->usStrategicInsertionData != NOWHERE )
|
|
{
|
|
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, 100, SCREEN_WIDTH - 100, 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, 100, SCREEN_WIDTH - 100, 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 )
|
|
{
|
|
INT16 sGridNo, 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;
|
|
default:
|
|
Assert( 0 );
|
|
break;
|
|
}
|
|
if( gMercPlacement[ iPlacement ].fPlaced )
|
|
PickUpMercPiece( iPlacement );
|
|
sGridNo = FindGridNoFromSweetSpot( pSoldier, pSoldier->sInsertionGridNo, 4, &ubDirection );
|
|
if( sGridNo != NOWHERE )
|
|
{
|
|
ConvertGridNoToCellXY( sGridNo, &sCellX, &sCellY );
|
|
EVENT_SetSoldierPosition( pSoldier, (FLOAT)sCellX, (FLOAT)sCellY );
|
|
EVENT_SetSoldierDirection( pSoldier, ubDirection );
|
|
pSoldier->ubInsertionDirection = pSoldier->bDirection;
|
|
gMercPlacement[ iPlacement ].fPlaced = TRUE;
|
|
gMercPlacement[ iPlacement ].pSoldier->bInSector = TRUE;
|
|
}
|
|
}
|
|
|
|
void PickUpMercPiece( INT32 iPlacement )
|
|
{
|
|
RemoveSoldierFromGridNo( gMercPlacement[ iPlacement ].pSoldier );
|
|
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;
|
|
}
|