mirror of
https://github.com/1dot13/source.git
synced 2026-07-22 13:40:22 +02:00
- added flag to display messagebox buttons horizontally instead of vertically git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@8661 3b4a5df2-a311-0410-b5c6-a8a6f20db521
6770 lines
180 KiB
C++
6770 lines
180 KiB
C++
#ifdef PRECOMPILEDHEADERS
|
|
#include "Strategic All.h"
|
|
#else
|
|
#include "Map Screen Interface.h"
|
|
#include "string.h"
|
|
#include "Map Screen Interface Map.h"
|
|
#include "Render Dirty.h"
|
|
#include "Font Control.h"
|
|
#include "Assignments.h"
|
|
#include "Soldier Control.h"
|
|
#include "Overhead.h"
|
|
#include "Squads.h"
|
|
#include "Sound Control.h"
|
|
#include "Soundman.h"
|
|
#include "Message.h"
|
|
#include "PopUpBox.h"
|
|
#include "Game Clock.h"
|
|
#include "Handle Items.h"
|
|
#include "Interface Items.h"
|
|
#include "Isometric Utils.h"
|
|
#include "Interface.h"
|
|
#include "Game Event Hook.h"
|
|
#include "Tactical Save.h"
|
|
#include "Quests.h"
|
|
#include "Strategicmap.h"
|
|
#include "Soldier Profile.h"
|
|
#include "Strategic Movement.h"
|
|
#include "Dialogue Control.h"
|
|
#include "Map Screen Interface Border.h"
|
|
#include "Map Screen Interface Bottom.h"
|
|
#include "Vehicles.h"
|
|
#include "LINE.H"
|
|
#include "Text.h"
|
|
#include "gameloop.h"
|
|
#include "Map Screen Helicopter.h"
|
|
#include "PreBattle Interface.h"
|
|
#include "WordWrap.h"
|
|
#include "interface control.h"
|
|
#include "GameSettings.h"
|
|
#include "Campaign Types.h"
|
|
#include "Map Screen Interface Map Inventory.h"
|
|
#include "strategic.h"
|
|
#include "Keys.h"
|
|
#include "Soldier macros.h"
|
|
#include "Militia Control.h"
|
|
#include "Random.h"
|
|
#include "Cursor Control.h"
|
|
#include "renderworld.h"
|
|
#include "Game Init.h"
|
|
#include "Strategic Mines.h"
|
|
#include "finances.h"
|
|
#include "strategic.h"
|
|
#include "Air Raid.h"
|
|
#include "Queen Command.h"
|
|
#include "Render Fun.h"
|
|
#include "Food.h"
|
|
#include "Personnel.h"
|
|
#include "mapscreen.h"
|
|
#endif
|
|
|
|
#include "connect.h"
|
|
|
|
//forward declarations of common classes to eliminate includes
|
|
class OBJECTTYPE;
|
|
class SOLDIERTYPE;
|
|
|
|
// marke strogg more mercs
|
|
extern UINT8 FIRSTmercTOdisplay = 0 ;
|
|
extern UINT8 maxNumberOfMercVisibleInStrategyList = 0; // WANNE: Max merc displayed in the list depends on the resolution
|
|
|
|
// inventory pool position on screen
|
|
#define MAP_INVEN_POOL_X 300
|
|
#define MAP_INVEN_POOL_Y 300
|
|
|
|
// the number of help region messages
|
|
#define NUMBER_OF_MAPSCREEN_HELP_MESSAGES 5
|
|
|
|
// WDS - make number of mercenaries, etc. be configurable
|
|
// number of LINKED LISTS for sets of leave items (each slot holds an unlimited # of items)
|
|
#define NUM_LEAVE_LIST_SLOTS CODE_MAXIMUM_NUMBER_OF_PLAYER_SLOTS
|
|
|
|
#define SIZE_OF_UPDATE_BOX 20
|
|
|
|
// as deep as the map goes
|
|
#define MAX_DEPTH_OF_MAP 3
|
|
|
|
|
|
// number of merc columns for four wide mode
|
|
#define NUMBER_OF_MERC_COLUMNS_FOR_FOUR_WIDE_MODE 4
|
|
|
|
// number of merc columns for 2 wide mode
|
|
#define NUMBER_OF_MERC_COLUMNS_FOR_TWO_WIDE_MODE 2
|
|
|
|
// number needed for 4 wide mode to activate
|
|
#define NUMBER_OF_MERCS_FOR_FOUR_WIDTH_UPDATE_PANEL 4
|
|
|
|
#define DBL_CLICK_DELAY_FOR_MOVE_MENU 200
|
|
|
|
|
|
#define TIMER_FOR_SHOW_EXIT_TO_TACTICAL_MESSAGE 15000
|
|
|
|
#define REASON_FOR_SOLDIER_UPDATE_OFFSET_Y (14)
|
|
|
|
#define MAX_MAPSCREEN_FAST_HELP 100
|
|
|
|
#define VEHICLE_ONLY FALSE
|
|
#define AND_ALL_ON_BOARD TRUE
|
|
|
|
|
|
// the regions int he movemenu
|
|
enum{
|
|
SQUAD_REGION = 0,
|
|
VEHICLE_REGION,
|
|
SOLDIER_REGION,
|
|
DONE_REGION,
|
|
CANCEL_REGION,
|
|
OTHER_REGION,
|
|
};
|
|
|
|
UINT16 usVehicleY = 0;
|
|
|
|
// waiting list for update box
|
|
INT32 iUpdateBoxWaitingList[ CODE_MAXIMUM_NUMBER_OF_PLAYER_SLOTS ];
|
|
|
|
FASTHELPREGION pFastHelpMapScreenList[ MAX_MAPSCREEN_FAST_HELP ];
|
|
|
|
// the move menu region
|
|
MOUSE_REGION gMoveMenuRegion[ MAX_POPUP_BOX_STRING_COUNT ];
|
|
|
|
MOUSE_REGION gMapScreenHelpTextMask;
|
|
|
|
BOOLEAN fShowMapScreenHelpText = FALSE;
|
|
BOOLEAN fScreenMaskForMoveCreated = FALSE;
|
|
BOOLEAN fLockOutMapScreenInterface = FALSE;
|
|
|
|
extern INT32 giMercPanelImage;
|
|
extern BOOLEAN fShowDescriptionFlag;
|
|
extern BOOLEAN fInMapMode;
|
|
extern GROUP *gpBattleGroup;
|
|
|
|
CHAR16 gsCustomErrorString[ 128 ];
|
|
|
|
BOOLEAN fShowUpdateBox = FALSE;
|
|
BOOLEAN fInterfaceFastHelpTextActive = FALSE;
|
|
BOOLEAN fReBuildCharacterList = FALSE;
|
|
INT32 giSizeOfInterfaceFastHelpTextList = 0;
|
|
|
|
//Animated sector locator icon variables.
|
|
INT16 gsSectorLocatorX;
|
|
INT16 gsSectorLocatorY;
|
|
UINT8 gubBlitSectorLocatorCode; //color
|
|
UINT32 guiSectorLocatorGraphicID; //icon graphic ID
|
|
// the animate time per frame in milliseconds
|
|
#define ANIMATED_BATTLEICON_FRAME_TIME 80
|
|
#define MAX_FRAME_COUNT_FOR_ANIMATED_BATTLE_ICON 12
|
|
|
|
|
|
|
|
SGPPoint pMapScreenFastHelpLocationList[]={
|
|
{ 25,200 },
|
|
{ 150,200 },
|
|
{ 450,430 },
|
|
{ 400,200 },
|
|
{ 250,100 },
|
|
{ 100,100 },
|
|
{ 100,100 },
|
|
{ 100,100 },
|
|
{ 100,100 },
|
|
{ 150,200 },
|
|
{ 100,100 },
|
|
};
|
|
|
|
INT32 pMapScreenFastHelpWidthList[]={
|
|
100,
|
|
100,
|
|
100,
|
|
100,
|
|
100,
|
|
100,
|
|
100,
|
|
100,
|
|
100,
|
|
300,
|
|
};
|
|
|
|
// number of mercs in sector capable of moving
|
|
INT32 giNumberOfSoldiersInSectorMoving = 0;
|
|
|
|
// number of squads capable of moving
|
|
INT32 giNumberOfSquadsInSectorMoving = 0;
|
|
|
|
// number of vehicles in sector moving
|
|
INT32 giNumberOfVehiclesInSectorMoving = 0;
|
|
|
|
INT32 iHeightOfInitFastHelpText = 0;
|
|
|
|
extern INT32 giMapContractButton;
|
|
extern INT32 giCharInfoButton[];
|
|
extern STR16 pUpdatePanelButtons[];
|
|
|
|
// the list of soldiers that are moving
|
|
SOLDIERTYPE * pSoldierMovingList[ CODE_MAXIMUM_NUMBER_OF_PLAYER_SLOTS ];
|
|
BOOLEAN fSoldierIsMoving[ CODE_MAXIMUM_NUMBER_OF_PLAYER_SLOTS ];
|
|
|
|
SOLDIERTYPE *pUpdateSoldierBox[ SIZE_OF_UPDATE_BOX ];
|
|
|
|
INT32 giUpdateSoldierFaces[ SIZE_OF_UPDATE_BOX ];
|
|
|
|
// the squads thata re moving
|
|
INT32 iSquadMovingList[ NUMBER_OF_SQUADS ];
|
|
INT32 fSquadIsMoving[ NUMBER_OF_SQUADS ];
|
|
|
|
// the vehicles thata re moving
|
|
INT32 iVehicleMovingList[ NUMBER_OF_SQUADS ];
|
|
INT32 fVehicleIsMoving[ NUMBER_OF_SQUADS ];
|
|
|
|
MOUSE_REGION gMoveBoxScreenMask;
|
|
|
|
// the save buffer
|
|
extern UINT32 guiSAVEBUFFER;
|
|
|
|
extern BOOLEAN fShowInventoryFlag;
|
|
extern FACETYPE *gpCurrentTalkingFace;
|
|
extern UINT8 gubCurrentTalkingID;
|
|
extern BOOLEAN fMapScreenBottomDirty;
|
|
extern MOUSE_REGION gMPanelRegion;
|
|
|
|
|
|
// has the inventory pool been selected to be on or off?
|
|
BOOLEAN fMapInventoryPoolInited = FALSE;
|
|
BOOLEAN fShowMapScreenMovementList = FALSE;
|
|
|
|
|
|
MapScreenCharacterSt gCharactersList[ CODE_MAXIMUM_NUMBER_OF_PLAYER_SLOTS+1];
|
|
|
|
extern MOUSE_REGION gCharInfoHandRegion;
|
|
extern MOUSE_REGION gCharInfoFaceRegion;
|
|
MOUSE_REGION gMapStatusBarsRegion;
|
|
|
|
// which lines are selected? .. for assigning groups of mercs to the same thing
|
|
BOOLEAN fSelectedListOfMercsForMapScreen[ CODE_MAXIMUM_NUMBER_OF_PLAYER_SLOTS ];
|
|
BOOLEAN fResetTimerForFirstEntryIntoMapScreen = FALSE;
|
|
INT32 iReasonForSoldierUpDate = NO_REASON_FOR_UPDATE;
|
|
|
|
// sam and mine icons
|
|
UINT32 guiSAMICON;
|
|
|
|
|
|
// disable team info panels due to battle roster
|
|
BOOLEAN fDisableDueToBattleRoster = FALSE;
|
|
|
|
// track old contract times
|
|
INT32 iOldContractTimes[ CODE_MAXIMUM_NUMBER_OF_PLAYER_SLOTS ];
|
|
|
|
// position of pop up box
|
|
INT32 giBoxY = 0;
|
|
|
|
// screen mask for inventory pop up
|
|
MOUSE_REGION gInventoryScreenMask;
|
|
|
|
MOUSE_REGION gContractIconRegion;
|
|
MOUSE_REGION gInsuranceIconRegion;
|
|
MOUSE_REGION gDepositIconRegion;
|
|
|
|
// general line..current and old
|
|
INT32 giHighLine=-1;
|
|
|
|
// assignment's line...glow box
|
|
INT32 giAssignHighLine=-1;
|
|
|
|
// destination plot line....glow box
|
|
INT32 giDestHighLine=-1;
|
|
|
|
// contract selection glow box
|
|
INT32 giContractHighLine = -1;
|
|
|
|
// the sleep column glow box
|
|
INT32 giSleepHighLine = -1;
|
|
|
|
// pop up box textures
|
|
UINT32 guiPOPUPTEX;
|
|
UINT32 guiPOPUPBORDERS;
|
|
|
|
// the currently selected character arrow
|
|
UINT32 guiSelectedCharArrow;
|
|
|
|
INT32 guiUpdatePanelButtonsImage[ 2 ];
|
|
INT32 guiUpdatePanelButtons[ 2 ];
|
|
|
|
// the update panel
|
|
UINT32 guiUpdatePanel;
|
|
UINT32 guiUpdatePanelTactical;
|
|
|
|
// the leave item list
|
|
MERC_LEAVE_ITEM *gpLeaveListHead[ NUM_LEAVE_LIST_SLOTS ];
|
|
|
|
// holds ids of mercs who left stuff behind
|
|
UINT32 guiLeaveListOwnerProfileId[ NUM_LEAVE_LIST_SLOTS ];
|
|
|
|
// flag to reset contract region glow
|
|
BOOLEAN fResetContractGlow = FALSE;
|
|
|
|
// timers for double click
|
|
INT32 giDblClickTimersForMoveBoxMouseRegions[ MAX_POPUP_BOX_STRING_COUNT ];
|
|
|
|
INT32 giExitToTactBaseTime = 0;
|
|
UINT32 guiSectorLocatorBaseTime = 0;
|
|
|
|
// which menus are we showing
|
|
BOOLEAN fShowAssignmentMenu = FALSE;
|
|
BOOLEAN fShowAttributeMenu = FALSE;
|
|
BOOLEAN fShowContractMenu = FALSE;
|
|
BOOLEAN fShowRemoveMenu = FALSE;
|
|
BOOLEAN fShowMilitiaControlMenu = FALSE; //lal
|
|
BOOLEAN fShowFacilityAssignmentMenu = FALSE; // HEADROCK HAM 3.6: Facility Sub-menu
|
|
|
|
BOOLEAN fRebuildMoveBox = FALSE;
|
|
|
|
// positions for all the pop up boxes
|
|
SGPRect ContractDimensions={0,0,140,60};
|
|
SGPPoint ContractPosition={120,50};
|
|
SGPRect AttributeDimensions={0,0,100,95};
|
|
SGPPoint AttributePosition={220,150};
|
|
SGPRect TrainDimensions={0,0,100,95};
|
|
SGPPoint TrainPosition={160,150};
|
|
SGPRect VehicleDimensions={0,0,80,60};
|
|
SGPPoint VehiclePosition={160,150};
|
|
// HEADROCK HAM 3.6: Facility Menu Position/Size:
|
|
SGPRect FacilityDimensions={0,0,80,60};
|
|
SGPPoint FacilityPosition={160,150};
|
|
// HEADROCK HAM 3.6: Facility Sub-menu Position/Size:
|
|
SGPRect FacilityAssignmentDimensions={0,0,80,60};
|
|
SGPPoint FacilityAssignmentPosition={220,150};
|
|
|
|
SGPPoint RepairPosition={160,150};
|
|
SGPRect RepairDimensions={0,0,80,80};
|
|
|
|
SGPPoint SnitchPosition={160,150};
|
|
SGPRect SnitchDimensions={0,0,80,80};
|
|
SGPPoint SnitchTogglePosition={320,150};
|
|
SGPRect SnitchToggleDimensions={0,0,80,80};
|
|
SGPPoint SnitchSectorPosition={320,150};
|
|
SGPRect SnitchSectorDimensions={0,0,80,80};
|
|
|
|
SGPPoint PrisonerPosition = {320, 150};
|
|
SGPRect PrisonerDimensions = {0, 0, 80, 80};
|
|
|
|
//lal
|
|
SGPPoint MilitiaControlPosition={120,150};
|
|
SGPRect MilitiaControlDimensions={0,0,100,95};
|
|
|
|
//SGPPoint TalkToAllPosition={160,150};
|
|
//SGPRect TalkToAllDimensions={0,0,100,95};
|
|
//lal
|
|
|
|
SGPPoint AssignmentPosition = { 120, 150 };
|
|
SGPRect AssignmentDimensions = { 0,0, 100, 95};
|
|
|
|
SGPPoint SquadPosition ={ 160, 150 };
|
|
SGPRect SquadDimensions ={ 0, 0, 140, 60 };
|
|
|
|
SGPPoint OrigContractPosition={120,50};
|
|
SGPPoint OrigAttributePosition={220,150};
|
|
SGPPoint OrigSquadPosition ={ 160, 150 };
|
|
SGPPoint OrigAssignmentPosition = { 120, 150 };
|
|
SGPPoint OrigTrainPosition={160,150};
|
|
SGPPoint OrigVehiclePosition={160,150};
|
|
SGPPoint OrigMilitiaControlPosition = { 120, 150 }; //lal
|
|
SGPPoint OrigFacilityPosition = { 160, 150 }; // HEADROCK HAM 3.6
|
|
SGPPoint OrigFacilityAssignmentPosition = { 220,150 }; // HEADROCK HAM 3.6
|
|
//SGPPoint OrigTalkToAllPosition = { 160, 150 };
|
|
SGPPoint OrigSnitchPosition={160,150};
|
|
SGPPoint OrigSnitchTogglePosition={320,150};
|
|
SGPPoint OrigSnitchSectorPosition={320,150};
|
|
|
|
SGPPoint OrigPrisonerPosition = {320, 150};
|
|
|
|
SQUAD_NAMES SquadNames[20];
|
|
|
|
//extern BOOLEAN fMapExitDueToMessageBox;
|
|
|
|
// at least one merc was hired at some time
|
|
BOOLEAN gfAtLeastOneMercWasHired = FALSE;
|
|
|
|
// rebuild contract box this character
|
|
extern void RebuildContractBoxForMerc( SOLDIERTYPE *pCharacter );
|
|
|
|
extern void SetUpCursorForStrategicMap( void );
|
|
|
|
extern void MapScreenDefaultOkBoxCallback( UINT8 bExitValue );
|
|
|
|
extern BOOLEAN PlayerSoldierTooTiredToTravel( SOLDIERTYPE *pSoldier );
|
|
|
|
extern void RememberPreviousPathForAllSelectedChars( void );
|
|
|
|
|
|
// the screen mask functions
|
|
void CreateScreenMaskForInventoryPoolPopUp( void );
|
|
void RemoveScreenMaskForInventoryPoolPopUp( void );
|
|
void InventoryScreenMaskBtnCallback(MOUSE_REGION * pRegion, INT32 iReason );
|
|
|
|
void MapScreenHelpTextScreenMaskBtnCallback( MOUSE_REGION * pRegion, INT32 iReason );
|
|
void SetUpShutDownMapScreenHelpTextScreenMask( void );
|
|
void DisplayFastHelpRegions( FASTHELPREGION *pRegion, INT32 iSize );
|
|
void DisplayUserDefineHelpTextRegions( FASTHELPREGION *pRegion );
|
|
|
|
|
|
// how many people does the player have?
|
|
//INT32 GetNumberOfCharactersOnPlayersTeam( void );
|
|
|
|
void AddStringsToMoveBox( void );
|
|
void CreatePopUpBoxForMovementBox( void );
|
|
void MoveMenuMvtCallback(MOUSE_REGION * pRegion, INT32 iReason );
|
|
void MoveMenuBtnCallback(MOUSE_REGION * pRegion, INT32 iReason );
|
|
void SelectAllOtherSoldiersInList( void );
|
|
void DeselectAllOtherSoldiersInList( void );
|
|
void HandleMoveoutOfSectorMovementTroops( void );
|
|
void HandleSettingTheSelectedListOfMercs( void );
|
|
void BuildMouseRegionsForMoveBox( void );
|
|
INT32 HowManyMovingSoldiersInVehicle( INT32 iVehicleId );
|
|
INT32 HowManyMovingSoldiersInSquad( INT32 iSquadNumber );
|
|
void ClearMouseRegionsForMoveBox( void );
|
|
BOOLEAN AllOtherSoldiersInListAreSelected( void );
|
|
BOOLEAN AllSoldiersInSquadSelected( INT32 iSquadNumber );
|
|
|
|
void MoveScreenMaskBtnCallback(MOUSE_REGION * pRegion, INT32 iReason );
|
|
/*
|
|
void CreateUpdateBoxStrings( void );
|
|
void CreateUpdateBox( void );
|
|
void RemoveUpdateBox( void );
|
|
void DisplayUpdateBox( void );
|
|
*/
|
|
void CreateDestroyUpdatePanelButtons(INT32 iX, INT32 iY, BOOLEAN fFourWideMode );
|
|
void RenderSoldierSmallFaceForUpdatePanel( INT32 iIndex, INT32 iX, INT32 iY );
|
|
void ContinueUpdateButtonCallback(GUI_BUTTON *btn,INT32 reason);
|
|
void StopUpdateButtonCallback(GUI_BUTTON *btn,INT32 reason);
|
|
//INT32 GetSquadListIndexForSquadNumber( INT32 iSquadNumber );
|
|
INT8 FindSquadThatSoldierCanJoin( SOLDIERTYPE *pSoldier );
|
|
BOOLEAN CanSoldierMoveWithVehicleId( SOLDIERTYPE *pSoldier, INT32 iVehicle1Id );
|
|
BOOLEAN IsAnythingSelectedForMoving( void );
|
|
BOOLEAN CanMoveBoxSoldierMoveStrategically( SOLDIERTYPE *pSoldier, BOOLEAN fShowErrorMessage );
|
|
|
|
BOOLEAN ValidSelectableCharForNextOrPrev( INT32 iNewCharSlot );
|
|
|
|
extern void ResumeOldAssignment( SOLDIERTYPE *pSoldier );
|
|
|
|
void InitalizeVehicleAndCharacterList( void )
|
|
{
|
|
// will init the vehicle and character lists to zero
|
|
memset(&gCharactersList, 0, sizeof( gCharactersList ));
|
|
}
|
|
|
|
void SetEntryInSelectedCharacterList( INT8 bEntry )
|
|
{
|
|
Assert( ( bEntry >= 0 ) && ( bEntry < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS ) );
|
|
|
|
// set this entry to selected
|
|
fSelectedListOfMercsForMapScreen[ bEntry ] = TRUE;
|
|
}
|
|
|
|
void ResetEntryForSelectedList( INT8 bEntry )
|
|
{
|
|
Assert( ( bEntry >= 0 ) && ( bEntry < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS ) );
|
|
|
|
// set this entry to selected
|
|
fSelectedListOfMercsForMapScreen[ bEntry ] = FALSE;
|
|
}
|
|
|
|
void ResetSelectedListForMapScreen( void )
|
|
{
|
|
// WDS - make number of mercenaries, etc. be configurable
|
|
// set all the entries int he selected list to false
|
|
memset( fSelectedListOfMercsForMapScreen, FALSE, sizeof(fSelectedListOfMercsForMapScreen) );
|
|
|
|
// if we still have a valid dude selected
|
|
if ( ( bSelectedInfoChar != -1 ) && ( gCharactersList[ bSelectedInfoChar ].fValid == TRUE ) )
|
|
{
|
|
// then keep him selected
|
|
SetEntryInSelectedCharacterList( bSelectedInfoChar );
|
|
}
|
|
}
|
|
|
|
BOOLEAN IsEntryInSelectedListSet( INT8 bEntry )
|
|
{
|
|
Assert( ( bEntry >= 0 ) && ( bEntry < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS ) );
|
|
|
|
// is this entry in the selected list set?
|
|
|
|
return( fSelectedListOfMercsForMapScreen[ bEntry ] );
|
|
}
|
|
|
|
void ToggleEntryInSelectedList( INT8 bEntry )
|
|
{
|
|
Assert( ( bEntry >= 0 ) && ( bEntry < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS ) );
|
|
|
|
// toggle the value in the selected list
|
|
fSelectedListOfMercsForMapScreen[ bEntry ] = !( fSelectedListOfMercsForMapScreen[ bEntry ] );
|
|
}
|
|
|
|
void BuildSelectedListFromAToB( INT8 bA, INT8 bB )
|
|
{
|
|
INT8 bStart =0, bEnd = 0;
|
|
|
|
// run from a to b..set slots as selected
|
|
|
|
if( bA > bB )
|
|
{
|
|
bStart = bB;
|
|
bEnd = bA;
|
|
}
|
|
else
|
|
{
|
|
bStart = bA;
|
|
bEnd = bB;
|
|
}
|
|
|
|
// run through list and set all intermediaries to true
|
|
|
|
for( bStart; bStart <= bEnd; ++bStart )
|
|
{
|
|
SetEntryInSelectedCharacterList( bStart );
|
|
}
|
|
}
|
|
|
|
BOOLEAN MultipleCharacterListEntriesSelected( void )
|
|
{
|
|
UINT8 ubSelectedCnt = 0;
|
|
|
|
// check if more than one person is selected in the selected list
|
|
for( INT32 iCounter = 0; iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; ++iCounter )
|
|
{
|
|
if( fSelectedListOfMercsForMapScreen[iCounter] == TRUE )
|
|
{
|
|
++ubSelectedCnt;
|
|
}
|
|
}
|
|
|
|
return ( ubSelectedCnt > 1 );
|
|
}
|
|
|
|
void ResetAssignmentsForMercsTrainingUnpaidSectorsInSelectedList( UINT8 ubMilitiaType )
|
|
{
|
|
SOLDIERTYPE *pSoldier = NULL;
|
|
|
|
for( INT32 iCounter = 0; iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; ++iCounter )
|
|
{
|
|
// valid character?
|
|
if( gCharactersList[ iCounter ].fValid == FALSE )
|
|
{
|
|
// nope
|
|
continue;
|
|
}
|
|
|
|
pSoldier = &Menptr[ gCharactersList[ iCounter ].usSolID ];
|
|
|
|
if( pSoldier->bActive == FALSE )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (ubMilitiaType == TOWN_MILITIA)
|
|
{
|
|
if( pSoldier->bAssignment == TRAIN_TOWN )
|
|
{
|
|
if ( SectorInfo[ SECTOR( pSoldier->sSectorX, pSoldier->sSectorY ) ].fMilitiaTrainingPaid == FALSE )
|
|
{
|
|
ResumeOldAssignment( pSoldier );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// HEADROCK HAM 3.6: Added argument for Militia Type
|
|
void ResetAssignmentOfMercsThatWereTrainingMilitiaInThisSector( INT16 sSectorX, INT16 sSectorY, UINT8 ubMilitiaType )
|
|
{
|
|
SOLDIERTYPE *pSoldier = NULL;
|
|
|
|
for( INT32 iCounter = 0; iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; ++iCounter )
|
|
{
|
|
// valid character?
|
|
if( gCharactersList[ iCounter ].fValid == FALSE )
|
|
{
|
|
// nope
|
|
continue;
|
|
}
|
|
|
|
pSoldier = &Menptr[ gCharactersList[ iCounter ].usSolID ];
|
|
|
|
if( pSoldier->bActive == FALSE )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if( ubMilitiaType == TOWN_MILITIA )
|
|
{
|
|
if( pSoldier->bAssignment == TRAIN_TOWN )
|
|
{
|
|
if( ( pSoldier->sSectorX == sSectorX ) && ( pSoldier->sSectorY == sSectorY ) && ( pSoldier->bSectorZ == 0 ) )
|
|
{
|
|
ResumeOldAssignment( pSoldier );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// check if the members of the selected list move with this guy... are they in the same mvt group?
|
|
void DeselectSelectedListMercsWhoCantMoveWithThisGuy( SOLDIERTYPE *pSoldier )
|
|
{
|
|
SOLDIERTYPE *pSoldier2 = NULL;
|
|
|
|
// deselect any other selected mercs that can't travel together with pSoldier
|
|
for( INT32 iCounter = 0; iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; iCounter++ )
|
|
{
|
|
if( gCharactersList[ iCounter ].fValid == TRUE )
|
|
{
|
|
if( fSelectedListOfMercsForMapScreen[ iCounter ] == TRUE )
|
|
{
|
|
pSoldier2 = &( Menptr[ gCharactersList[ iCounter ].usSolID ] );
|
|
|
|
// skip the guy we are
|
|
if ( pSoldier == pSoldier2 )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// NOTE ABOUT THE VEHICLE TESTS BELOW:
|
|
// Vehicles and foot squads can't plot movement together!
|
|
// The ETAs are different, and unlike squads, vehicles can't travel everywhere!
|
|
// However, different vehicles CAN plot together, since they all travel at the same rates now
|
|
|
|
// if anchor guy is IN a vehicle
|
|
if( pSoldier->bAssignment == VEHICLE )
|
|
{
|
|
if ( !CanSoldierMoveWithVehicleId( pSoldier2, pSoldier->iVehicleId ) )
|
|
{
|
|
// reset entry for selected list
|
|
ResetEntryForSelectedList( ( INT8 )iCounter );
|
|
}
|
|
}
|
|
// if anchor guy IS a vehicle
|
|
else if ( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE )
|
|
{
|
|
if ( !CanSoldierMoveWithVehicleId( pSoldier2, pSoldier->bVehicleID ) )
|
|
{
|
|
// reset entry for selected list
|
|
ResetEntryForSelectedList( ( INT8 )iCounter );
|
|
}
|
|
}
|
|
// if this guy is IN a vehicle
|
|
else if( pSoldier2->bAssignment == VEHICLE )
|
|
{
|
|
if ( !CanSoldierMoveWithVehicleId( pSoldier, pSoldier2->iVehicleId ) )
|
|
{
|
|
// reset entry for selected list
|
|
ResetEntryForSelectedList( ( INT8 )iCounter );
|
|
}
|
|
}
|
|
// if this guy IS a vehicle
|
|
else if ( pSoldier2->flags.uiStatusFlags & SOLDIER_VEHICLE )
|
|
{
|
|
if ( !CanSoldierMoveWithVehicleId( pSoldier, pSoldier2->bVehicleID ) )
|
|
{
|
|
// reset entry for selected list
|
|
ResetEntryForSelectedList( ( INT8 )iCounter );
|
|
}
|
|
}
|
|
// reject those not a squad (vehicle handled above)
|
|
else if( pSoldier2->bAssignment >= ON_DUTY )
|
|
{
|
|
ResetEntryForSelectedList( ( INT8 )iCounter );
|
|
}
|
|
else
|
|
{
|
|
// reject those not in the same sector
|
|
if( ( pSoldier->sSectorX != pSoldier2->sSectorX ) ||
|
|
( pSoldier->sSectorY != pSoldier2->sSectorY ) ||
|
|
( pSoldier->bSectorZ != pSoldier2->bSectorZ ) )
|
|
{
|
|
ResetEntryForSelectedList( ( INT8 )iCounter );
|
|
}
|
|
|
|
// if either is between sectors, they must be in the same movement group
|
|
if ( ( pSoldier->flags.fBetweenSectors || pSoldier2->flags.fBetweenSectors ) &&
|
|
( pSoldier->ubGroupID != pSoldier2->ubGroupID ) )
|
|
{
|
|
ResetEntryForSelectedList( ( INT8 )iCounter );
|
|
}
|
|
}
|
|
|
|
// different movement groups in same sector is OK, even if they're not travelling together
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void SelectUnselectedMercsWhoMustMoveWithThisGuy( void )
|
|
{
|
|
SOLDIERTYPE *pSoldier = NULL;
|
|
|
|
for( INT32 iCounter = 0; iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; ++iCounter )
|
|
{
|
|
if( gCharactersList[ iCounter ].fValid == TRUE )
|
|
{
|
|
// if not already selected
|
|
if( fSelectedListOfMercsForMapScreen[ iCounter ] == FALSE )
|
|
{
|
|
pSoldier = &( Menptr[ gCharactersList[ iCounter ].usSolID ] );
|
|
|
|
// if on a squad or in a vehicle
|
|
if ( ( pSoldier->bAssignment < ON_DUTY ) || ( pSoldier->bAssignment == VEHICLE ) )
|
|
{
|
|
// and a member of that squad or vehicle is selected
|
|
if ( AnyMercInSameSquadOrVehicleIsSelected( pSoldier ) )
|
|
{
|
|
// then also select this guy
|
|
SetEntryInSelectedCharacterList( ( INT8 ) iCounter );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
BOOLEAN AnyMercInSameSquadOrVehicleIsSelected( SOLDIERTYPE *pSoldier )
|
|
{
|
|
SOLDIERTYPE *pSoldier2 = NULL;
|
|
|
|
for( INT32 iCounter = 0; iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; ++iCounter )
|
|
{
|
|
if( gCharactersList[ iCounter ].fValid == TRUE )
|
|
{
|
|
// if selected
|
|
if( fSelectedListOfMercsForMapScreen[ iCounter ] == TRUE )
|
|
{
|
|
pSoldier2 = &( Menptr[ gCharactersList[ iCounter ].usSolID ] );
|
|
|
|
// if they have the same assignment
|
|
if( pSoldier->bAssignment == pSoldier2->bAssignment )
|
|
{
|
|
// same squad?
|
|
if ( pSoldier->bAssignment < ON_DUTY )
|
|
{
|
|
return ( TRUE );
|
|
}
|
|
|
|
// same vehicle?
|
|
if ( ( pSoldier->bAssignment == VEHICLE ) && ( pSoldier->iVehicleId == pSoldier2->iVehicleId ) )
|
|
{
|
|
return ( TRUE );
|
|
}
|
|
}
|
|
|
|
// target guy is in a vehicle, and this guy IS that vehicle
|
|
if( ( pSoldier->bAssignment == VEHICLE ) && ( pSoldier2->flags.uiStatusFlags & SOLDIER_VEHICLE ) &&
|
|
( pSoldier->iVehicleId == pSoldier2->bVehicleID ) )
|
|
{
|
|
return ( TRUE );
|
|
}
|
|
|
|
// this guy is in a vehicle, and the target guy IS that vehicle
|
|
if( ( pSoldier2->bAssignment == VEHICLE ) && ( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) &&
|
|
( pSoldier2->iVehicleId == pSoldier->bVehicleID ) )
|
|
{
|
|
return ( TRUE );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return ( FALSE );
|
|
}
|
|
|
|
// WANNE: Get the refreshing high depending on the resolution and on the game type (single or multiplayer)
|
|
INT16 GetRefreshHeightForMercList( void )
|
|
{
|
|
INT16 yHeight = ( INT16 )( ( ( giMAXIMUM_NUMBER_OF_PLAYER_SLOTS + 1 ) * ( Y_SIZE + 2 ) ) + 1 );
|
|
|
|
// WANNE: Get maximum refresh height depending on the resolution!
|
|
if (iResolution >= _640x480 && iResolution < _800x600)
|
|
{
|
|
if (!is_networked)
|
|
{
|
|
if (yHeight > 224)
|
|
yHeight = 224;
|
|
}
|
|
else
|
|
{
|
|
if (yHeight > 131)
|
|
yHeight = 131;
|
|
}
|
|
}
|
|
else if (iResolution < _1024x768)
|
|
{
|
|
if (!is_networked)
|
|
{
|
|
if (yHeight > 340)
|
|
yHeight = 340;
|
|
}
|
|
else
|
|
{
|
|
if (yHeight > 249)
|
|
yHeight = 249;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!is_networked)
|
|
{
|
|
if (yHeight > 510)
|
|
yHeight = 510;
|
|
}
|
|
else
|
|
{
|
|
if (yHeight > 415)
|
|
yHeight = 415;
|
|
}
|
|
}
|
|
|
|
return yHeight;
|
|
}
|
|
|
|
void RestoreBackgroundForAssignmentGlowRegionList( void )
|
|
{
|
|
static INT32 iOldAssignmentLine = -1;
|
|
|
|
// will restore the background region of the assignment list after a glow has ceased
|
|
// ( a _LOST_MOUSE reason to the assignment region mvt callback handler )
|
|
|
|
if( fShowAssignmentMenu == TRUE )
|
|
{
|
|
// force update
|
|
ForceUpDateOfBox( ghAssignmentBox );
|
|
ForceUpDateOfBox( ghEpcBox );
|
|
ForceUpDateOfBox( ghRemoveMercAssignBox );
|
|
|
|
if( gAssignMenuState == ASMENU_SQUAD )
|
|
{
|
|
ForceUpDateOfBox( ghSquadBox );
|
|
}
|
|
else if( gAssignMenuState == ASMENU_TRAIN )
|
|
{
|
|
ForceUpDateOfBox( ghTrainingBox );
|
|
}
|
|
else if ( gAssignMenuState == ASMENU_SNITCH )
|
|
{
|
|
ForceUpDateOfBox( ghSnitchBox );
|
|
|
|
if( fShowSnitchToggleMenu == TRUE )
|
|
{
|
|
ForceUpDateOfBox( ghSnitchToggleBox );
|
|
}
|
|
else if( fShowSnitchSectorMenu == TRUE )
|
|
{
|
|
ForceUpDateOfBox( ghSnitchSectorBox );
|
|
}
|
|
}
|
|
else if ( fShowPrisonerMenu )
|
|
{
|
|
ForceUpDateOfBox( ghPrisonerBox );
|
|
}
|
|
}
|
|
|
|
if( fDisableDueToBattleRoster )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if( iOldAssignmentLine != giAssignHighLine )
|
|
{
|
|
INT16 yHeight = GetRefreshHeightForMercList();
|
|
|
|
// restore background
|
|
RestoreExternBackgroundRect( 66 + xResOffset, Y_START - 1, 118 + 1 - 67, yHeight );
|
|
|
|
// ARM: not good enough! must reblit the whole panel to erase glow chunk restored by help text disappearing!!!
|
|
fTeamPanelDirty = TRUE;
|
|
|
|
// set old to current
|
|
iOldAssignmentLine = giAssignHighLine;
|
|
}
|
|
}
|
|
|
|
void RestoreBackgroundForDestinationGlowRegionList( void )
|
|
{
|
|
static INT32 iOldDestinationLine = -1;
|
|
|
|
// will restore the background region of the destinationz list after a glow has ceased
|
|
// ( a _LOST_MOUSE reason to the assignment region mvt callback handler )
|
|
|
|
if( fDisableDueToBattleRoster )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if( iOldDestinationLine != giDestHighLine )
|
|
{
|
|
INT16 yHeight = GetRefreshHeightForMercList();
|
|
|
|
// restore background
|
|
RestoreExternBackgroundRect( 182 + xResOffset, Y_START - 1, 217 + 1 - 182, yHeight );
|
|
|
|
// ARM: not good enough! must reblit the whole panel to erase glow chunk restored by help text disappearing!!!
|
|
fTeamPanelDirty = TRUE;
|
|
|
|
// set old to current
|
|
iOldDestinationLine = giDestHighLine;
|
|
}
|
|
|
|
// leave
|
|
return;
|
|
}
|
|
|
|
void RestoreBackgroundForContractGlowRegionList( void )
|
|
{
|
|
static INT32 iOldContractLine = -1;
|
|
|
|
// will restore the background region of the destinationz list after a glow has ceased
|
|
// ( a _LOST_MOUSE reason to the assignment region mvt callback handler )
|
|
|
|
if( fDisableDueToBattleRoster )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if( iOldContractLine != giContractHighLine )
|
|
{
|
|
INT16 yHeight = GetRefreshHeightForMercList();
|
|
|
|
// restore background
|
|
RestoreExternBackgroundRect( 222 + xResOffset, Y_START - 1, 250 + 1 - 222, yHeight ) ;
|
|
|
|
// ARM: not good enough! must reblit the whole panel to erase glow chunk restored by help text disappearing!!!
|
|
fTeamPanelDirty = TRUE;
|
|
|
|
// set old to current
|
|
iOldContractLine = giContractHighLine;
|
|
|
|
// reset color rotation
|
|
fResetContractGlow = TRUE;
|
|
}
|
|
|
|
// leave
|
|
return;
|
|
}
|
|
|
|
|
|
void RestoreBackgroundForSleepGlowRegionList( void )
|
|
{
|
|
static INT32 iOldSleepHighLine = -1;
|
|
|
|
// will restore the background region of the destinations list after a glow has ceased
|
|
// ( a _LOST_MOUSE reason to the assignment region mvt callback handler )
|
|
|
|
if( fDisableDueToBattleRoster )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if( iOldSleepHighLine != giSleepHighLine )
|
|
{
|
|
INT16 yHeight = GetRefreshHeightForMercList();
|
|
|
|
// restore background
|
|
RestoreExternBackgroundRect( 123 + xResOffset, Y_START - 1, 142 + 1 - 123, yHeight ) ;
|
|
|
|
// ARM: not good enough! must reblit the whole panel to erase glow chunk restored by help text disappearing!!!
|
|
fTeamPanelDirty = TRUE;
|
|
|
|
// set old to current
|
|
iOldSleepHighLine = giSleepHighLine;
|
|
|
|
// reset color rotation
|
|
fResetContractGlow = TRUE;
|
|
}
|
|
|
|
// leave
|
|
return;
|
|
}
|
|
|
|
void PlayGlowRegionSound( void )
|
|
{
|
|
// play a new message sound, if there is one playing, do nothing
|
|
static UINT32 uiSoundId = 0;
|
|
|
|
if( uiSoundId != 0 )
|
|
{
|
|
// is sound playing?..don't play new one
|
|
if( SoundIsPlaying( uiSoundId ) == TRUE )
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
// otherwise no sound playing, play one
|
|
uiSoundId = PlayJA2SampleFromFile( "Sounds\\glowclick.wav", RATE_11025, MIDVOLUME, 1 , MIDDLEPAN );
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
INT16 CharacterIsGettingPathPlotted( INT16 sCharNumber )
|
|
{
|
|
// valid character number?
|
|
if( ( sCharNumber < 0 ) || ( sCharNumber >= giMAXIMUM_NUMBER_OF_PLAYER_SLOTS ) )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
// is the character a valid one?
|
|
if( gCharactersList[ sCharNumber + FIRSTmercTOdisplay ].fValid == FALSE )
|
|
{
|
|
return ( FALSE );
|
|
}
|
|
|
|
// if the highlighted line character is also selected
|
|
if ( ( ( giDestHighLine != -1 ) && IsEntryInSelectedListSet ( ( INT8 ) giDestHighLine + FIRSTmercTOdisplay ) ) ||
|
|
( ( bSelectedDestChar != -1 ) && IsEntryInSelectedListSet ( bSelectedDestChar ) ) )
|
|
{
|
|
// then ALL selected lines will be affected
|
|
if( IsEntryInSelectedListSet( ( INT8 ) sCharNumber + FIRSTmercTOdisplay ) )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// if he is *the* selected dude
|
|
if( bSelectedDestChar == sCharNumber + FIRSTmercTOdisplay )
|
|
{
|
|
return ( TRUE );
|
|
}
|
|
|
|
// ONLY the highlighted line will be affected
|
|
if ( sCharNumber == giDestHighLine )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
}
|
|
|
|
return ( FALSE );
|
|
}
|
|
|
|
BOOLEAN IsCharacterSelectedForAssignment( INT16 sCharNumber )
|
|
{
|
|
// valid character number?
|
|
if( ( sCharNumber < 0 ) || ( sCharNumber >= giMAXIMUM_NUMBER_OF_PLAYER_SLOTS ) )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
// is the character a valid one?
|
|
if( gCharactersList[ sCharNumber + FIRSTmercTOdisplay ].fValid == FALSE )
|
|
{
|
|
return ( FALSE );
|
|
}
|
|
|
|
// if the highlighted line character is also selected
|
|
// marke strogg more mercs
|
|
if ( ( giAssignHighLine != -1 ) && IsEntryInSelectedListSet ( ( INT8 ) giAssignHighLine + FIRSTmercTOdisplay ) )
|
|
{
|
|
// then ALL selected lines will be affected
|
|
// marke strogg more mercs
|
|
if( IsEntryInSelectedListSet( ( INT8 ) sCharNumber + FIRSTmercTOdisplay ) )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// ONLY the highlighted line will be affected
|
|
if ( sCharNumber == giAssignHighLine )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
}
|
|
|
|
return( FALSE );
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN IsCharacterSelectedForSleep( INT16 sCharNumber )
|
|
{
|
|
// valid character number?
|
|
if( ( sCharNumber < 0 ) || ( sCharNumber >= giMAXIMUM_NUMBER_OF_PLAYER_SLOTS ) )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
// marke strogg more mercs
|
|
// is the character a valid one?
|
|
if( gCharactersList[ sCharNumber + FIRSTmercTOdisplay ].fValid == FALSE )
|
|
{
|
|
return ( FALSE );
|
|
}
|
|
|
|
// if the highlighted line character is also selected
|
|
if ( ( giSleepHighLine != -1 ) && IsEntryInSelectedListSet ( ( INT8 ) giSleepHighLine + FIRSTmercTOdisplay ) )
|
|
{
|
|
// then ALL selected lines will be affected
|
|
if( IsEntryInSelectedListSet( ( INT8 ) sCharNumber + FIRSTmercTOdisplay ) )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// ONLY the highlighted line will be affected
|
|
if ( sCharNumber == giSleepHighLine )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
}
|
|
|
|
return( FALSE );
|
|
}
|
|
|
|
void DisableTeamInfoPanels( void )
|
|
{
|
|
// disable team info panel
|
|
fDisableDueToBattleRoster = TRUE;
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void EnableTeamInfoPanels( void )
|
|
{
|
|
// enable team info panel
|
|
fDisableDueToBattleRoster = FALSE;
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/*
|
|
void ActivateSoldierPopup( SOLDIERTYPE *pSoldier, UINT8 ubPopupType, INT16 xp, INT16 yp )
|
|
{
|
|
// will activate the pop up for prebattle interface
|
|
|
|
// get the soldier id number
|
|
INT8 bCounter = 0;
|
|
INT8 bCharacter = -1;
|
|
|
|
|
|
for( bCounter = 0; bCounter < CODE_MAXIMUM_NUMBER_OF_PLAYER_SLOTS; bCounter++ )
|
|
{
|
|
if( gCharactersList[ bCounter ].fValid == TRUE )
|
|
{
|
|
// is this guy the passed soldier?
|
|
if( pSoldier == &( Menptr[ gCharactersList[ bCounter ].usSolID ] ) )
|
|
{
|
|
bCharacter = bCounter;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
giBoxY = ( INT32 ) yp;
|
|
// which type of box do we show?
|
|
switch( ubPopupType )
|
|
{
|
|
case( ASSIGNMENT_POPUP ):
|
|
bSelectedDestChar = -1;
|
|
bSelectedContractChar = -1;
|
|
bSelectedAssignChar = bCharacter;
|
|
if( ( pSoldier->stats.bLife > 0 ) &&( pSoldier->bAssignment != ASSIGNMENT_POW ) )
|
|
{
|
|
fShowAssignmentMenu = TRUE;
|
|
}
|
|
else
|
|
{
|
|
fShowRemoveMenu = TRUE;
|
|
}
|
|
|
|
// set box y positions
|
|
AssignmentPosition.iY = giBoxY;
|
|
TrainPosition.iY = AssignmentPosition.iY + GetFontHeight( MAP_SCREEN_FONT )* ASSIGN_MENU_TRAIN;
|
|
AttributePosition.iY = TrainPosition.iY;
|
|
SquadPosition.iY = AssignmentPosition.iY;
|
|
break;
|
|
case( DESTINATION_POPUP ):
|
|
bSelectedDestChar = bCharacter;
|
|
bSelectedContractChar = -1;
|
|
bSelectedAssignChar = -1;
|
|
|
|
// set box y value
|
|
ContractPosition.iY = giBoxY;
|
|
break;
|
|
case( CONTRACT_POPUP ):
|
|
bSelectedDestChar = -1;
|
|
bSelectedContractChar = bCharacter;
|
|
bSelectedAssignChar = -1;
|
|
RebuildContractBoxForMerc( pSoldier );
|
|
|
|
if( ( pSoldier->stats.bLife > 0 ) &&( pSoldier->bAssignment != ASSIGNMENT_POW ) )
|
|
{
|
|
fShowContractMenu = TRUE;
|
|
}
|
|
else
|
|
{
|
|
fShowRemoveMenu = TRUE;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
*/
|
|
|
|
|
|
|
|
INT32 DoMapMessageBoxWithRect( UINT8 ubStyle, const STR16 zString, UINT32 uiExitScreen, UINT32 usFlags, MSGBOX_CALLBACK ReturnCallback, SGPRect *pCenteringRect )
|
|
{
|
|
// reset the highlighted line
|
|
giHighLine = -1;
|
|
return DoMessageBox( ubStyle, zString, uiExitScreen, ( usFlags | MSG_BOX_FLAG_USE_CENTERING_RECT ), ReturnCallback, pCenteringRect );
|
|
}
|
|
|
|
|
|
INT32 DoMapMessageBox( UINT8 ubStyle, STR16 zString, UINT32 uiExitScreen, UINT32 usFlags, MSGBOX_CALLBACK ReturnCallback )
|
|
{
|
|
SGPRect CenteringRect= {0 + xResOffset, 0 + yResOffset, SCREEN_WIDTH - xResOffset, INV_INTERFACE_START_Y };
|
|
|
|
// reset the highlighted line
|
|
giHighLine = -1;
|
|
|
|
// do message box and return
|
|
return DoMessageBox( ubStyle, zString, uiExitScreen, ( usFlags| MSG_BOX_FLAG_USE_CENTERING_RECT ), ReturnCallback, &CenteringRect );
|
|
}
|
|
|
|
|
|
|
|
void GoDownOneLevelInMap( void )
|
|
{
|
|
JumpToLevel( iCurrentMapSectorZ + 1 );
|
|
}
|
|
|
|
|
|
void GoUpOneLevelInMap( void )
|
|
{
|
|
JumpToLevel( iCurrentMapSectorZ - 1 );
|
|
}
|
|
|
|
|
|
void JumpToLevel( INT32 iLevel )
|
|
{
|
|
if( IsMapScreenHelpTextUp() )
|
|
{
|
|
// stop mapscreen text
|
|
StopMapScreenHelpText( );
|
|
return;
|
|
}
|
|
|
|
if( gfPreBattleInterfaceActive == TRUE )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// disable level-changes while in inventory pool (for keyboard equivalents!)
|
|
if( fShowMapInventoryPool )
|
|
return;
|
|
|
|
|
|
if ( (bSelectedDestChar != -1) || fPlotForHelicopter || fPlotForMilitia )
|
|
{
|
|
AbortMovementPlottingMode( );
|
|
}
|
|
|
|
if( iLevel < 0 )
|
|
{
|
|
iLevel = 0;
|
|
}
|
|
|
|
if( iLevel > MAX_DEPTH_OF_MAP )
|
|
{
|
|
iLevel = MAX_DEPTH_OF_MAP;
|
|
}
|
|
|
|
// set current sector Z to level passed
|
|
ChangeSelectedMapSector( sSelMapX, sSelMapY, ( INT8 )iLevel );
|
|
}
|
|
|
|
|
|
// check against old contract times, update as nessacary
|
|
void CheckAndUpdateBasedOnContractTimes( void )
|
|
{
|
|
INT32 iCounter = 0;
|
|
INT32 iTimeRemaining = 0;
|
|
|
|
for( iCounter = 0; iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; iCounter++ )
|
|
{
|
|
if( gCharactersList[iCounter].fValid == TRUE )
|
|
{
|
|
// what kind of merc
|
|
if(Menptr[gCharactersList[iCounter].usSolID].ubWhatKindOfMercAmI == MERC_TYPE__AIM_MERC)
|
|
{
|
|
// amount of time left on contract
|
|
iTimeRemaining=Menptr[gCharactersList[iCounter].usSolID].iEndofContractTime-GetWorldTotalMin();
|
|
if(iTimeRemaining >60*24)
|
|
{
|
|
// more than a day, display in green
|
|
iTimeRemaining/=(60*24);
|
|
|
|
// check if real change in contract time
|
|
if( iTimeRemaining != iOldContractTimes[ iCounter ])
|
|
{
|
|
iOldContractTimes[ iCounter ] = iTimeRemaining;
|
|
|
|
// dirty screen
|
|
fTeamPanelDirty = TRUE;
|
|
fCharacterInfoPanelDirty = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// less than a day, display hours left in red
|
|
iTimeRemaining/=60;
|
|
|
|
// check if real change in contract time
|
|
if( iTimeRemaining != iOldContractTimes[ iCounter ])
|
|
{
|
|
iOldContractTimes[ iCounter ] = iTimeRemaining;
|
|
// dirty screen
|
|
fTeamPanelDirty = TRUE;
|
|
fCharacterInfoPanelDirty = TRUE;
|
|
}
|
|
}
|
|
}
|
|
else if( Menptr[gCharactersList[iCounter].usSolID].ubWhatKindOfMercAmI == MERC_TYPE__MERC )
|
|
{
|
|
iTimeRemaining = Menptr[gCharactersList[iCounter].usSolID].iTotalContractLength;
|
|
|
|
if( iTimeRemaining != iOldContractTimes[ iCounter ])
|
|
{
|
|
iOldContractTimes[ iCounter ] = iTimeRemaining;
|
|
|
|
// dirty screen
|
|
fTeamPanelDirty = TRUE;
|
|
fCharacterInfoPanelDirty = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void HandleDisplayOfSelectedMercArrows( void )
|
|
{
|
|
INT16 sYPosition = 0;
|
|
HVOBJECT hHandle;
|
|
UINT8 ubCount = 0;
|
|
|
|
UINT16 selectedCharArrowX = xResOffset + 1;
|
|
|
|
// blit an arrow by the name of each merc in a selected list
|
|
if( bSelectedInfoChar == -1 )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// is the character valid?
|
|
if( gCharactersList[ bSelectedInfoChar ].fValid == FALSE )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if( fShowInventoryFlag == TRUE )
|
|
{
|
|
return;
|
|
}
|
|
// marke strogg more merc
|
|
if ( bSelectedInfoChar - FIRSTmercTOdisplay >= maxNumberOfMercVisibleInStrategyList )
|
|
{
|
|
FIRSTmercTOdisplay = bSelectedInfoChar - (maxNumberOfMercVisibleInStrategyList - 1) ;
|
|
}
|
|
|
|
// now blit one by the selected merc
|
|
// marke strogg more mercs
|
|
sYPosition = Y_START+( ( bSelectedInfoChar - FIRSTmercTOdisplay ) * ( Y_SIZE + 2 ) ) - 1;
|
|
|
|
GetVideoObject( &hHandle, guiSelectedCharArrow );
|
|
BltVideoObject( guiSAVEBUFFER , hHandle, 0,selectedCharArrowX, sYPosition , VO_BLT_SRCTRANSPARENCY,NULL );
|
|
|
|
// now run through the selected list of guys, an arrow for each
|
|
|
|
// marke strogg more mercs
|
|
for( ubCount = 0; ubCount < maxNumberOfMercVisibleInStrategyList; ubCount++ )
|
|
{
|
|
// marke strogg more mercs
|
|
if( gCharactersList[ ubCount + FIRSTmercTOdisplay ].fValid == TRUE )
|
|
{
|
|
// are they in the selected list or int he same mvt group as this guy
|
|
if( ( IsEntryInSelectedListSet( ubCount + FIRSTmercTOdisplay ) == TRUE ) || ( ( bSelectedDestChar != - 1 ) ? ( ( Menptr[ gCharactersList[ ubCount + FIRSTmercTOdisplay ].usSolID ].ubGroupID != 0 ) ? ( Menptr[ gCharactersList[ bSelectedDestChar ].usSolID ].ubGroupID == Menptr[ gCharactersList[ ubCount + FIRSTmercTOdisplay ].usSolID ].ubGroupID ) : FALSE ) : FALSE ) )
|
|
{
|
|
sYPosition = Y_START+( ubCount * ( Y_SIZE + 2) ) - 1;
|
|
|
|
GetVideoObject( &hHandle, guiSelectedCharArrow );
|
|
BltVideoObject( guiSAVEBUFFER , hHandle, 0,selectedCharArrowX, sYPosition , VO_BLT_SRCTRANSPARENCY,NULL );
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
void HandleDisplayOfItemPopUpForSector( INT16 sMapX, INT16 sMapY, INT16 sMapZ )
|
|
{
|
|
// handle display of item pop up for this sector
|
|
// check if anyone alive in this sector
|
|
ITEM_POOL *pItemPool = NULL;
|
|
static BOOLEAN fWasInited = FALSE;
|
|
|
|
if( bSelectedInfoChar == -1 )
|
|
{
|
|
return;
|
|
}
|
|
|
|
|
|
if( ( fWasInited == FALSE ) && ( fMapInventoryPoolInited ) )
|
|
{
|
|
if( gCharactersList[ bSelectedInfoChar ].fValid == TRUE )
|
|
{
|
|
if( ( Menptr[ gCharactersList[ bSelectedInfoChar ].usSolID].sSectorX == sMapX ) && ( Menptr[ gCharactersList[ bSelectedInfoChar ].usSolID].sSectorY == sMapY ) && ( Menptr[ gCharactersList[ bSelectedInfoChar ].usSolID].bSectorZ == sMapZ ) && ( Menptr[ gCharactersList[ bSelectedInfoChar ].usSolID].bActive ) && ( Menptr[ gCharactersList[ bSelectedInfoChar ].usSolID].stats.bLife >= OKLIFE ) )
|
|
{
|
|
// valid character
|
|
InitializeItemPickupMenu( &( Menptr[ gCharactersList[ bSelectedInfoChar ].usSolID] ), NOWHERE , pItemPool, MAP_INVEN_POOL_X, MAP_INVEN_POOL_Y, -1 );
|
|
fWasInited = TRUE;
|
|
|
|
CreateScreenMaskForInventoryPoolPopUp( );
|
|
}
|
|
}
|
|
}
|
|
else if( ( fWasInited == TRUE ) && ( fMapInventoryPoolInited == FALSE ) )
|
|
{
|
|
fWasInited = FALSE;
|
|
|
|
// now clear up the box
|
|
RemoveItemPickupMenu( );
|
|
|
|
// remove screen mask
|
|
RemoveScreenMaskForInventoryPoolPopUp( );
|
|
|
|
// drity nessacary regions
|
|
fMapPanelDirty = TRUE;
|
|
|
|
}
|
|
|
|
// showing it
|
|
if( ( fMapInventoryPoolInited ) && ( fWasInited ) )
|
|
{
|
|
SetPickUpMenuDirtyLevel( DIRTYLEVEL2 );
|
|
RenderItemPickupMenu( );
|
|
}
|
|
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
void CreateScreenMaskForInventoryPoolPopUp( void )
|
|
{
|
|
// a screen mask for the inventory pop up
|
|
MSYS_DefineRegion( &gInventoryScreenMask, 0, 0 , SCREEN_WIDTH, SCREEN_HEIGHT, MSYS_PRIORITY_HIGH - 1,
|
|
MSYS_NO_CURSOR, MSYS_NO_CALLBACK, InventoryScreenMaskBtnCallback );
|
|
|
|
}
|
|
|
|
void RemoveScreenMaskForInventoryPoolPopUp( void )
|
|
{
|
|
// remove screen mask
|
|
MSYS_RemoveRegion( &gInventoryScreenMask );
|
|
}
|
|
|
|
|
|
// invnetory screen mask btn callback
|
|
void InventoryScreenMaskBtnCallback(MOUSE_REGION * pRegion, INT32 iReason )
|
|
{
|
|
// inventory screen mask btn callback
|
|
if(iReason & MSYS_CALLBACK_REASON_LBUTTON_UP)
|
|
{
|
|
fMapInventoryPoolInited = FALSE;
|
|
}
|
|
}
|
|
|
|
void GetMoraleString( SOLDIERTYPE *pSoldier, STR16 sString )
|
|
{
|
|
INT8 bMorale = pSoldier->aiData.bMorale;
|
|
|
|
if ( pSoldier->flags.uiStatusFlags & SOLDIER_DEAD )
|
|
{
|
|
wcscpy( sString, pMoralStrings[ 5 ] );
|
|
}
|
|
else if( bMorale > 80 )
|
|
{
|
|
wcscpy( sString, pMoralStrings[ 0 ] );
|
|
}
|
|
else if( bMorale > 65 )
|
|
{
|
|
wcscpy( sString, pMoralStrings[ 1 ] );
|
|
}
|
|
else if( bMorale > 35 )
|
|
{
|
|
wcscpy( sString, pMoralStrings[ 2 ] );
|
|
}
|
|
else if( bMorale > 20 )
|
|
{
|
|
wcscpy( sString, pMoralStrings[ 3 ] );
|
|
}
|
|
else
|
|
{
|
|
wcscpy( sString, pMoralStrings[ 4 ] );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// NOTE: This doesn't use the "LeaveList" system at all!
|
|
void HandleLeavingOfEquipmentInCurrentSector( UINT32 uiMercId )
|
|
{
|
|
// just drop the stuff in the current sector
|
|
//INT32 iCounter = 0;
|
|
INT32 sGridNo, sTempGridNo;
|
|
|
|
INT8 sectorz = Menptr[uiMercId].bSectorZ;
|
|
if ( SPY_LOCATION( Menptr[uiMercId].bAssignment ) )
|
|
sectorz = max( 0, sectorz - 10 );
|
|
|
|
if( Menptr[ uiMercId ].sSectorX != gWorldSectorX || Menptr[ uiMercId ].sSectorY != gWorldSectorY || sectorz != gbWorldSectorZ )
|
|
{
|
|
// ATE: Use insertion gridno if not nowhere and insertion is gridno
|
|
if ( Menptr[ uiMercId ].ubStrategicInsertionCode == INSERTION_CODE_GRIDNO && !TileIsOutOfBounds(Menptr[ uiMercId ].usStrategicInsertionData) )
|
|
{
|
|
sGridNo = Menptr[ uiMercId ].usStrategicInsertionData;
|
|
}
|
|
else
|
|
{
|
|
// Set flag for item...
|
|
sGridNo = RandomGridNo();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// ATE: Mercs can have a gridno of NOWHERE.....
|
|
sGridNo = Menptr[ uiMercId ].sGridNo;
|
|
|
|
if (TileIsOutOfBounds(sGridNo))
|
|
{
|
|
sGridNo = RandomGridNo();
|
|
|
|
sTempGridNo = FindNearestAvailableGridNoForItem( sGridNo, 5 );
|
|
|
|
if(TileIsOutOfBounds(sTempGridNo))
|
|
sTempGridNo = FindNearestAvailableGridNoForItem( sGridNo, 15 );
|
|
else
|
|
{
|
|
sGridNo = sTempGridNo;
|
|
}
|
|
}
|
|
}
|
|
|
|
UINT32 invsize = Menptr[ uiMercId ].inv.size();
|
|
UINT32 uiFoundItems = 0;
|
|
Inventory invTemporaryBeforeDrop;
|
|
|
|
if( Menptr[ uiMercId ].sSectorX != gWorldSectorX || Menptr[ uiMercId ].sSectorY != gWorldSectorY || sectorz != gbWorldSectorZ )
|
|
{
|
|
for( UINT32 iCounter = 0; iCounter < invsize; ++iCounter )
|
|
{
|
|
// slot found,
|
|
// check if actual item
|
|
if( Menptr[ uiMercId ].inv[ iCounter ].exists() == true )
|
|
{
|
|
invTemporaryBeforeDrop[uiFoundItems] = Menptr[ uiMercId ].inv[ iCounter ];
|
|
uiFoundItems++;
|
|
}
|
|
}
|
|
// anv: add all items at once (less file operations = less lag)
|
|
AddItemsToUnLoadedSector( Menptr[ uiMercId ].sSectorX, Menptr[ uiMercId ].sSectorY, sectorz, sGridNo, uiFoundItems, &(invTemporaryBeforeDrop[0]) , Menptr[ uiMercId ].pathing.bLevel, WOLRD_ITEM_FIND_SWEETSPOT_FROM_GRIDNO | WORLD_ITEM_REACHABLE, 0, 1, FALSE );
|
|
}
|
|
else
|
|
{
|
|
for( UINT32 iCounter = 0; iCounter < invsize; ++iCounter )
|
|
{
|
|
// slot found,
|
|
// check if actual item
|
|
if( Menptr[ uiMercId ].inv[ iCounter ].exists() == true )
|
|
{
|
|
AddItemToPool( sGridNo, &( Menptr[ uiMercId ].inv[ iCounter ] ) , 1, Menptr[ uiMercId ].pathing.bLevel, WORLD_ITEM_REACHABLE, 0 );
|
|
}
|
|
}
|
|
}
|
|
|
|
DropKeysInKeyRing( MercPtrs[ uiMercId ], sGridNo, MercPtrs[ uiMercId ]->pathing.bLevel, 1, FALSE, 0, FALSE );
|
|
}
|
|
|
|
|
|
|
|
void HandleMercLeavingEquipmentInOmerta( UINT32 uiMercId )
|
|
{
|
|
INT32 iSlotIndex = 0;
|
|
|
|
// stash the items into a linked list hanging of a free "leave item list" slot
|
|
if( ( iSlotIndex = SetUpDropItemListForMerc( uiMercId ) ) != -1 )
|
|
{
|
|
// post event to drop it there 6 hours later
|
|
AddStrategicEvent( EVENT_MERC_LEAVE_EQUIP_IN_OMERTA, GetWorldTotalMin() + ( 6 * 60 ), iSlotIndex );
|
|
}
|
|
else
|
|
{
|
|
// otherwise there's no free slots left (shouldn't ever happen)
|
|
AssertMsg( FALSE, "HandleMercLeavingEquipmentInOmerta: No more free slots, equipment lost" );
|
|
}
|
|
}
|
|
|
|
|
|
void HandleMercLeavingEquipmentInDrassen( UINT32 uiMercId )
|
|
{
|
|
INT32 iSlotIndex = 0;
|
|
|
|
// stash the items into a linked list hanging of a free "leave item list" slot
|
|
if( ( iSlotIndex = SetUpDropItemListForMerc( uiMercId ) ) != -1 )
|
|
{
|
|
// post event to drop it there 6 hours later
|
|
AddStrategicEvent( EVENT_MERC_LEAVE_EQUIP_IN_DRASSEN, GetWorldTotalMin() + ( 6 * 60 ), iSlotIndex );
|
|
}
|
|
else
|
|
{
|
|
// otherwise there's no free slots left (shouldn't ever happen)
|
|
AssertMsg( FALSE, "HandleMercLeavingEquipmentInDrassen: No more free slots, equipment lost" );
|
|
}
|
|
}
|
|
|
|
|
|
void HandleEquipmentLeftInOmerta( UINT32 uiSlotIndex )
|
|
{
|
|
MERC_LEAVE_ITEM *pItem;
|
|
CHAR16 sString[ 128 ];
|
|
|
|
|
|
Assert( uiSlotIndex < NUM_LEAVE_LIST_SLOTS );
|
|
|
|
pItem = gpLeaveListHead[ uiSlotIndex ];
|
|
|
|
if( pItem )
|
|
{
|
|
if ( guiLeaveListOwnerProfileId[ uiSlotIndex ] != NO_PROFILE )
|
|
{
|
|
swprintf( sString, pLeftEquipmentString[ 0 ], gMercProfiles[ guiLeaveListOwnerProfileId[ uiSlotIndex ] ].zNickname );
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, sString);
|
|
}
|
|
else
|
|
{
|
|
swprintf( sString, L"A departing merc has left their equipment in Omerta." );
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, sString);
|
|
}
|
|
}
|
|
|
|
while( pItem )
|
|
{
|
|
if( gWorldSectorX != OMERTA_LEAVE_EQUIP_SECTOR_X || gWorldSectorY != OMERTA_LEAVE_EQUIP_SECTOR_Y || gbWorldSectorZ != OMERTA_LEAVE_EQUIP_SECTOR_Z )
|
|
{
|
|
// given this slot value, add to sector item list
|
|
AddItemsToUnLoadedSector( OMERTA_LEAVE_EQUIP_SECTOR_X, OMERTA_LEAVE_EQUIP_SECTOR_Y, OMERTA_LEAVE_EQUIP_SECTOR_Z, OMERTA_LEAVE_EQUIP_GRIDNO, 1, &( pItem->object ) , 0, WORLD_ITEM_REACHABLE, 0, 1, FALSE );
|
|
}
|
|
else
|
|
{
|
|
AddItemToPool( OMERTA_LEAVE_EQUIP_GRIDNO, &( pItem->object ), 1, 0, WORLD_ITEM_REACHABLE, 0 );
|
|
}
|
|
pItem = pItem->pNext;
|
|
}
|
|
|
|
FreeLeaveListSlot( uiSlotIndex );
|
|
}
|
|
|
|
|
|
|
|
void HandleEquipmentLeftInDrassen( UINT32 uiSlotIndex )
|
|
{
|
|
MERC_LEAVE_ITEM *pItem;
|
|
CHAR16 sString[ 128 ];
|
|
|
|
|
|
Assert( uiSlotIndex < NUM_LEAVE_LIST_SLOTS );
|
|
|
|
pItem = gpLeaveListHead[ uiSlotIndex ];
|
|
|
|
if( pItem )
|
|
{
|
|
if ( guiLeaveListOwnerProfileId[ uiSlotIndex ] != NO_PROFILE )
|
|
{
|
|
swprintf( sString, pLeftEquipmentString[ 1 ], gMercProfiles[ guiLeaveListOwnerProfileId[ uiSlotIndex ] ].zNickname );
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, sString);
|
|
}
|
|
else
|
|
{
|
|
swprintf( sString, L"A departing merc has left their equipment in Drassen." );
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, sString);
|
|
}
|
|
}
|
|
|
|
while( pItem )
|
|
{
|
|
if( gWorldSectorX != AIRPORT_X || gWorldSectorY != AIRPORT_Y || gbWorldSectorZ != 0 )
|
|
{
|
|
// given this slot value, add to sector item list
|
|
AddItemsToUnLoadedSector( AIRPORT_X, AIRPORT_Y, 0,
|
|
gModSettings.iAirportDropOff, 1, &( pItem->object ) , 0, WORLD_ITEM_REACHABLE, 0, 1, FALSE ); //10433
|
|
}
|
|
else
|
|
{
|
|
AddItemToPool( gModSettings.iAirportDropOff, &( pItem->object ), 1, 0, WORLD_ITEM_REACHABLE, 0 ); //10433
|
|
}
|
|
pItem = pItem->pNext;
|
|
}
|
|
|
|
FreeLeaveListSlot( uiSlotIndex );
|
|
}
|
|
|
|
|
|
void InitLeaveList( void )
|
|
{
|
|
INT32 iCounter = 0;
|
|
|
|
// init leave list with NULLS/zeroes
|
|
for( iCounter = 0; iCounter < NUM_LEAVE_LIST_SLOTS; iCounter++ )
|
|
{
|
|
gpLeaveListHead[ iCounter ] = NULL;
|
|
guiLeaveListOwnerProfileId[ iCounter ] = NO_PROFILE;
|
|
}
|
|
}
|
|
|
|
|
|
void ShutDownLeaveList( void )
|
|
{
|
|
INT32 iCounter = 0;
|
|
|
|
for( iCounter = 0; iCounter < NUM_LEAVE_LIST_SLOTS; iCounter++ )
|
|
{
|
|
// go through nodes and free them
|
|
if ( gpLeaveListHead[ iCounter ] != NULL )
|
|
{
|
|
FreeLeaveListSlot( iCounter );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
BOOLEAN AddItemToLeaveIndex( OBJECTTYPE *object, UINT32 uiSlotIndex )
|
|
{
|
|
MERC_LEAVE_ITEM *pItem, *pCurrentItem;
|
|
|
|
Assert( uiSlotIndex < NUM_LEAVE_LIST_SLOTS );
|
|
|
|
|
|
if( object == NULL )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
// allocate space
|
|
pItem = new MERC_LEAVE_ITEM;
|
|
|
|
// copy object
|
|
pItem->object = *object;
|
|
|
|
// nobody afterwards
|
|
pItem->pNext = NULL;
|
|
|
|
// now add to list in this index slot
|
|
pCurrentItem = gpLeaveListHead[ uiSlotIndex ];
|
|
|
|
if( pCurrentItem == NULL )
|
|
{
|
|
gpLeaveListHead[ uiSlotIndex ] = pItem;
|
|
return( TRUE );
|
|
}
|
|
|
|
// move through list
|
|
while( pCurrentItem->pNext )
|
|
{
|
|
pCurrentItem = pCurrentItem->pNext;
|
|
}
|
|
|
|
// found
|
|
pCurrentItem->pNext = pItem;
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
// release memory for all items in this slot's leave item list
|
|
void FreeLeaveListSlot( UINT32 uiSlotIndex )
|
|
{
|
|
MERC_LEAVE_ITEM *pCurrent = NULL, *pTemp = NULL;
|
|
|
|
Assert( uiSlotIndex < NUM_LEAVE_LIST_SLOTS );
|
|
|
|
pCurrent = gpLeaveListHead[ uiSlotIndex ];
|
|
|
|
// go through nodes and free them
|
|
while( pCurrent )
|
|
{
|
|
pTemp = pCurrent->pNext;
|
|
MemFree( pCurrent );
|
|
pCurrent = pTemp;
|
|
}
|
|
|
|
gpLeaveListHead[ uiSlotIndex ] = NULL;
|
|
}
|
|
|
|
|
|
|
|
INT32 FindFreeSlotInLeaveList( void )
|
|
{
|
|
INT32 iCounter = 0;
|
|
|
|
for( iCounter = 0; iCounter < NUM_LEAVE_LIST_SLOTS; iCounter++ )
|
|
{
|
|
if( gpLeaveListHead[ iCounter ] == NULL )
|
|
{
|
|
return( iCounter );
|
|
}
|
|
}
|
|
|
|
return( -1 );
|
|
}
|
|
|
|
|
|
INT32 SetUpDropItemListForMerc( UINT32 uiMercId )
|
|
{
|
|
// will set up a drop list for this grunt, remove items from inventory, and profile
|
|
INT32 iSlotIndex = -1;
|
|
|
|
iSlotIndex = FindFreeSlotInLeaveList( );
|
|
if( iSlotIndex == -1 )
|
|
{
|
|
return( -1 );
|
|
}
|
|
|
|
UINT32 invsize = Menptr[ uiMercId ].inv.size();
|
|
for( UINT32 iCounter = 0; iCounter < invsize; ++iCounter )
|
|
{
|
|
// slot found,
|
|
// check if actual item
|
|
if( Menptr[ uiMercId ].inv[ iCounter ].exists() == true )
|
|
{
|
|
// make a linked list of the items left behind, with the ptr to its head in this free slot
|
|
AddItemToLeaveIndex( &( Menptr[ uiMercId ].inv[ iCounter ] ), iSlotIndex );
|
|
|
|
// store owner's profile id for the items added to this leave slot index
|
|
SetUpMercAboutToLeaveEquipment( Menptr[ uiMercId ].ubProfile, iSlotIndex );
|
|
}
|
|
}
|
|
|
|
// ATE: Added this to drop keyring keys - the 2nd last paramter says to add it to a leave list...
|
|
// the gridno, level and visiblity are ignored
|
|
DropKeysInKeyRing( MercPtrs[ uiMercId ], NOWHERE, 0, 0, TRUE, iSlotIndex, FALSE );
|
|
|
|
// zero out profiles
|
|
gMercProfiles[ Menptr[ uiMercId ].ubProfile ].clearInventory();
|
|
|
|
return( iSlotIndex );
|
|
}
|
|
|
|
|
|
// store owner's profile id for the items added to this leave slot index
|
|
void SetUpMercAboutToLeaveEquipment( UINT32 ubProfileId, UINT32 uiSlotIndex )
|
|
{
|
|
Assert( uiSlotIndex < NUM_LEAVE_LIST_SLOTS );
|
|
|
|
// store the profile ID of this merc in the same slot that the items are gonna be dropped in
|
|
guiLeaveListOwnerProfileId[ uiSlotIndex ] = ubProfileId;
|
|
|
|
}
|
|
|
|
void HandleGroupAboutToArrive( void )
|
|
{
|
|
// reblit map to change the color of the "people in motion" marker
|
|
fMapPanelDirty = TRUE;
|
|
|
|
return;
|
|
}
|
|
|
|
void CreateMapStatusBarsRegion( void )
|
|
{
|
|
MSYS_DefineRegion( &gMapStatusBarsRegion, BAR_INFO_X + xResOffset - 3, BAR_INFO_Y + yResOffset - 42,(INT16)( BAR_INFO_X + xResOffset + 17), (INT16)(BAR_INFO_Y + yResOffset), MSYS_PRIORITY_HIGH + 5,
|
|
MSYS_NO_CURSOR, MSYS_NO_CALLBACK, MSYS_NO_CALLBACK );
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void RemoveMapStatusBarsRegion( void )
|
|
{
|
|
// remove the bSelectedInfoCharacter helath, breath and morale bars info region
|
|
MSYS_RemoveRegion( &gMapStatusBarsRegion );
|
|
|
|
return;
|
|
}
|
|
|
|
void UpdateCharRegionHelpText( void )
|
|
{
|
|
CHAR16 sString[ 6000 ], sTemp[ 20 ];
|
|
CHAR16 pMoraleStr[ 128 ];
|
|
SOLDIERTYPE *pSoldier = NULL;
|
|
|
|
if( ( bSelectedInfoChar != -1 ) && ( gCharactersList[ bSelectedInfoChar ].fValid == TRUE ) )
|
|
{
|
|
// valid soldier selected
|
|
pSoldier = MercPtrs[ gCharactersList[ bSelectedInfoChar ].usSolID ];
|
|
|
|
// health/energy/morale
|
|
if( pSoldier->bAssignment != ASSIGNMENT_POW )
|
|
{
|
|
if ( pSoldier->stats.bLife != 0 )
|
|
{
|
|
if ( AM_A_ROBOT( MercPtrs[ gCharactersList[ bSelectedInfoChar ].usSolID ] ) )
|
|
{
|
|
// robot (condition only)
|
|
swprintf( sString, L"%s: %d/%d", pMapScreenStatusStrings[ 3 ], pSoldier->stats.bLife, pSoldier->stats.bLifeMax );
|
|
}
|
|
else if ( Menptr[ gCharactersList[ bSelectedInfoChar ].usSolID ].flags.uiStatusFlags & SOLDIER_VEHICLE )
|
|
{
|
|
// vehicle (condition/fuel)
|
|
swprintf( sString, L"%s: %d/%d, %s: %d/%d",
|
|
pMapScreenStatusStrings[ 3 ], pSoldier->stats.bLife, pSoldier->stats.bLifeMax,
|
|
pMapScreenStatusStrings[ 4 ], pSoldier->bBreath, pSoldier->bBreathMax );
|
|
}
|
|
else
|
|
{
|
|
// person (health/energy/morale)
|
|
GetMoraleString( pSoldier, pMoraleStr );
|
|
|
|
{
|
|
swprintf( sString, L"%s: %d/%d, %s: %d/%d, %s: %s",
|
|
pMapScreenStatusStrings[ 0 ], pSoldier->stats.bLife, pSoldier->stats.bLifeMax,
|
|
pMapScreenStatusStrings[ 1 ], pSoldier->bBreath, pSoldier->bBreathMax,
|
|
pMapScreenStatusStrings[ 2 ], pMoraleStr );
|
|
}
|
|
|
|
pSoldier->PrintFoodDesc( sString, TRUE );
|
|
|
|
pSoldier->PrintDiseaseDesc( sString, TRUE );
|
|
|
|
pSoldier->PrintSleepDesc( sString );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
wcscpy( sString, L"" );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// POW - stats unknown
|
|
swprintf( sString, L"%s: ??, %s: ??, %s: ??", pMapScreenStatusStrings[ 0 ], pMapScreenStatusStrings[ 1 ], pMapScreenStatusStrings[ 2 ] );
|
|
}
|
|
|
|
SetRegionFastHelpText( &gMapStatusBarsRegion, sString );
|
|
|
|
// Buggler: skills/traits tooltip on merc portrait
|
|
if( ( pSoldier->stats.bLife != 0 ) && !AM_A_ROBOT( pSoldier ) && !IsVehicle( pSoldier ) )
|
|
{
|
|
// clear pStr value
|
|
swprintf( sString, L"");
|
|
|
|
if (gGameOptions.fNewTraitSystem) // SANDRO - old/new traits check
|
|
{
|
|
UINT8 ubTempSkillArray[30];
|
|
INT8 bNumSkillTraits = 0;
|
|
|
|
// lets rearrange our skills to a temp array
|
|
// we also get the number of lines (skills) to be displayed
|
|
for ( UINT8 ubCnt = 1; ubCnt < NUM_SKILLTRAITS_NT; ++ubCnt )
|
|
{
|
|
if ( ProfileHasSkillTrait( pSoldier->ubProfile, ubCnt ) == 2 )
|
|
{
|
|
ubTempSkillArray[bNumSkillTraits] = (ubCnt + NEWTRAIT_MERCSKILL_EXPERTOFFSET);
|
|
++bNumSkillTraits;
|
|
}
|
|
else if ( ProfileHasSkillTrait( pSoldier->ubProfile, ubCnt ) == 1 )
|
|
{
|
|
ubTempSkillArray[bNumSkillTraits] = ubCnt;
|
|
++bNumSkillTraits;
|
|
}
|
|
}
|
|
|
|
if ( bNumSkillTraits == 0 )
|
|
{
|
|
swprintf( sString, L"%s", pPersonnelScreenStrings[ PRSNL_TXT_NOSKILLS ] );
|
|
}
|
|
else
|
|
{
|
|
for ( UINT8 ubCnt = 0; ubCnt < bNumSkillTraits; ubCnt++ )
|
|
{
|
|
swprintf( sTemp, L"%s\n", gzMercSkillTextNew[ ubTempSkillArray[ubCnt] ] );
|
|
wcscat( sString, sTemp );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
INT8 bSkill1 = 0, bSkill2 = 0;
|
|
bSkill1 = gMercProfiles[ pSoldier->ubProfile ].bSkillTraits[0];
|
|
bSkill2 = gMercProfiles[ pSoldier->ubProfile ].bSkillTraits[1];
|
|
|
|
if ( bSkill1 == 0 && bSkill2 == 0 )
|
|
{
|
|
swprintf( sString, L"%s", pPersonnelScreenStrings[ PRSNL_TXT_NOSKILLS ] );
|
|
}
|
|
else
|
|
{
|
|
//if the 2 skills are the same, add the '(expert)' at the end
|
|
if( bSkill1 == bSkill2 )
|
|
{
|
|
swprintf( sString, L"%s %s", gzMercSkillText[bSkill1], gzMercSkillText[EXPERT] );
|
|
}
|
|
else
|
|
{
|
|
//Display the first skill
|
|
if( bSkill1 != 0 )
|
|
{
|
|
swprintf( sString, L"%s\n", gzMercSkillText[bSkill1] );
|
|
}
|
|
|
|
if( bSkill2 != 0 )
|
|
{
|
|
swprintf( sTemp, L"%s", gzMercSkillText[bSkill2] );
|
|
wcscat( sString, sTemp );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
SetRegionFastHelpText( &gCharInfoFaceRegion, sString );
|
|
}
|
|
else
|
|
{
|
|
SetRegionFastHelpText( &gCharInfoFaceRegion, L"" );
|
|
}
|
|
|
|
// update CONTRACT button help text
|
|
if ( CanExtendContractForCharSlot( bSelectedInfoChar ) )
|
|
{
|
|
SetButtonFastHelpText( giMapContractButton, pMapScreenMouseRegionHelpText[ 3 ] );
|
|
EnableButton( giMapContractButton );
|
|
}
|
|
else
|
|
{
|
|
SetButtonFastHelpText( giMapContractButton, L"" );
|
|
DisableButton( giMapContractButton );
|
|
}
|
|
|
|
if ( CanToggleSelectedCharInventory( ) )
|
|
{
|
|
// inventory
|
|
if( fShowInventoryFlag )
|
|
{
|
|
SetRegionFastHelpText( &gCharInfoHandRegion, pMiscMapScreenMouseRegionHelpText[ 2 ] );
|
|
}
|
|
else
|
|
{
|
|
SetRegionFastHelpText( &gCharInfoHandRegion, pMiscMapScreenMouseRegionHelpText[ 0 ] );
|
|
}
|
|
}
|
|
else // can't toggle it, don't show any inventory help text
|
|
{
|
|
SetRegionFastHelpText( &gCharInfoHandRegion, L"" );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// invalid soldier
|
|
SetRegionFastHelpText( &(gMapStatusBarsRegion), L"" );
|
|
SetButtonFastHelpText( giMapContractButton, L"" );
|
|
SetRegionFastHelpText( &gCharInfoHandRegion, L"" );
|
|
DisableButton( giMapContractButton );
|
|
}
|
|
}
|
|
|
|
|
|
// find this merc in the mapscreen list and set as selected
|
|
void FindAndSetThisContractSoldier( SOLDIERTYPE *pSoldier )
|
|
{
|
|
INT32 iCounter = 0;
|
|
|
|
fShowContractMenu = FALSE;
|
|
|
|
for( iCounter = 0; iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; iCounter++ )
|
|
{
|
|
if( gCharactersList[ iCounter].fValid == TRUE )
|
|
{
|
|
if( gCharactersList[ iCounter].usSolID == pSoldier->ubID )
|
|
{
|
|
ChangeSelectedInfoChar( ( INT8 )iCounter, TRUE );
|
|
bSelectedContractChar = ( INT8 )iCounter;
|
|
fShowContractMenu = TRUE;
|
|
|
|
// create
|
|
RebuildContractBoxForMerc( pSoldier );
|
|
|
|
fTeamPanelDirty = TRUE;
|
|
fCharacterInfoPanelDirty = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void HandleMAPUILoseCursorFromOtherScreen( void )
|
|
{
|
|
// rerender map without cursors
|
|
fMapPanelDirty = TRUE;
|
|
|
|
if ( fInMapMode )
|
|
{
|
|
RenderMapRegionBackground( );
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
void UpdateMapScreenAssignmentPositions( void )
|
|
{
|
|
// set the position of the pop up boxes
|
|
SGPPoint pPoint;
|
|
SGPPoint pNewPoint;
|
|
SGPRect pDimensions;
|
|
|
|
if( guiCurrentScreen != MAP_SCREEN )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if( bSelectedAssignChar == -1 )
|
|
{
|
|
if( gfPreBattleInterfaceActive == FALSE )
|
|
{
|
|
giBoxY = 0;
|
|
}
|
|
return;
|
|
}
|
|
|
|
if( gCharactersList[ bSelectedAssignChar ].fValid == FALSE )
|
|
{
|
|
if( gfPreBattleInterfaceActive == FALSE )
|
|
{
|
|
giBoxY = 0;
|
|
}
|
|
return;
|
|
}
|
|
|
|
if( gfPreBattleInterfaceActive )
|
|
{
|
|
// do nothing
|
|
}
|
|
else
|
|
{
|
|
// marke strogg more mercs
|
|
giBoxY = ( Y_START + ( bSelectedAssignChar - FIRSTmercTOdisplay ) * ( Y_SIZE + 2 ) );
|
|
}
|
|
|
|
AssignmentPosition.iY = giBoxY;
|
|
|
|
AttributePosition.iY = TrainPosition.iY = AssignmentPosition.iY + ( GetFontHeight( MAP_SCREEN_FONT ) + 2 )* ASSIGN_MENU_TRAIN;
|
|
|
|
VehiclePosition.iY = AssignmentPosition.iY + ( GetFontHeight( MAP_SCREEN_FONT ) + 2 ) * ASSIGN_MENU_VEHICLE;
|
|
SquadPosition.iY = AssignmentPosition.iY;
|
|
|
|
pNewPoint.iX = AssignmentPosition.iX;
|
|
pNewPoint.iY = AssignmentPosition.iY;
|
|
|
|
if( fShowAssignmentMenu )
|
|
{
|
|
GetBoxPosition( ghAssignmentBox, &pPoint);
|
|
GetBoxSize( ghAssignmentBox, &pDimensions );
|
|
pPoint.iY = giBoxY;
|
|
|
|
SetBoxPosition( ghAssignmentBox, pPoint );
|
|
|
|
// hang it right beside the assignment/EPC box menu
|
|
pNewPoint.iX = pPoint.iX + pDimensions.iRight;
|
|
pNewPoint.iY = pPoint.iY;
|
|
|
|
GetBoxPosition( ghEpcBox, &pPoint);
|
|
pPoint.iY = giBoxY;
|
|
|
|
SetBoxPosition( ghEpcBox, pPoint );
|
|
}
|
|
|
|
switch ( gAssignMenuState )
|
|
{
|
|
case ASMENU_REPAIR:
|
|
{
|
|
GetBoxPosition( ghRepairBox, &pPoint );
|
|
pPoint.iY = giBoxY + ( GetFontHeight( MAP_SCREEN_FONT ) + 2 ) * ASSIGN_MENU_REPAIR;
|
|
|
|
SetBoxPosition( ghRepairBox, pPoint );
|
|
}
|
|
break;
|
|
|
|
case ASMENU_VEHICLE:
|
|
{
|
|
|
|
}
|
|
break;
|
|
|
|
case ASMENU_DISEASE:
|
|
{
|
|
GetBoxPosition( ghDiseaseBox, &pPoint );
|
|
pPoint.iY = giBoxY + ( GetFontHeight( MAP_SCREEN_FONT ) + 2 ) * ASSIGN_MENU_DOCTOR_DIAGNOSIS;
|
|
|
|
SetBoxPosition( ghDiseaseBox, pPoint );
|
|
}
|
|
break;
|
|
|
|
case ASMENU_SPY:
|
|
{
|
|
GetBoxPosition( ghSpyBox, &pPoint );
|
|
pPoint.iY = giBoxY + ( GetFontHeight( MAP_SCREEN_FONT ) + 2 ) * ASSIGN_MENU_SPY;
|
|
|
|
SetBoxPosition( ghSpyBox, pPoint );
|
|
}
|
|
break;
|
|
|
|
case ASMENU_MOVEITEM:
|
|
{
|
|
GetBoxPosition( ghMoveItemBox, &pPoint );
|
|
pPoint.iY = giBoxY + ( GetFontHeight( MAP_SCREEN_FONT ) + 2 ) * ASSIGN_MENU_MOVE_ITEMS;
|
|
|
|
SetBoxPosition( ghMoveItemBox, pPoint );
|
|
}
|
|
break;
|
|
|
|
case ASMENU_FACILITY:
|
|
{
|
|
//GetBoxPosition( ghFacilityBox, &pPoint );
|
|
|
|
pPoint.iX = pNewPoint.iX;
|
|
pPoint.iY = pNewPoint.iY + ( GetFontHeight( MAP_SCREEN_FONT ) + 2 ) * ASSIGN_MENU_FACILITY;
|
|
|
|
SetBoxPosition( ghFacilityBox, pPoint );
|
|
}
|
|
break;
|
|
|
|
case ASMENU_MILITIA:
|
|
{
|
|
GetBoxPosition( ghMilitiaBox, &pPoint );
|
|
pPoint.iY = giBoxY + ( GetFontHeight( MAP_SCREEN_FONT ) + 2 ) * ASSIGN_MENU_MILITIA;
|
|
|
|
SetBoxPosition( ghMilitiaBox, pPoint );
|
|
}
|
|
break;
|
|
}
|
|
|
|
if( fShowAttributeMenu )
|
|
{
|
|
GetBoxPosition( ghAttributeBox, &pPoint);
|
|
|
|
pPoint.iY = giBoxY + ( GetFontHeight( MAP_SCREEN_FONT ) + 2 ) * ASSIGN_MENU_TRAIN;
|
|
|
|
SetBoxPosition( ghAttributeBox, pPoint );
|
|
}
|
|
|
|
// HEADROCK HAM 3.6: Facility Sub-menu
|
|
if( fShowFacilityAssignmentMenu )
|
|
{
|
|
GetBoxPosition( ghFacilityAssignmentBox, &pPoint);
|
|
|
|
pPoint.iY = giBoxY + ( GetFontHeight( MAP_SCREEN_FONT ) + 2 ) * ASSIGN_MENU_FACILITY;
|
|
|
|
SetBoxPosition( ghFacilityAssignmentBox, pPoint );
|
|
}
|
|
|
|
if ( fShowPrisonerMenu )
|
|
{
|
|
GetBoxPosition( ghPrisonerBox, &pPoint );
|
|
pPoint.iY = giBoxY + (GetFontHeight( MAP_SCREEN_FONT ) + 2) * ASSIGN_MENU_FACILITY;
|
|
|
|
SetBoxPosition( ghPrisonerBox, pPoint );
|
|
}
|
|
}
|
|
|
|
|
|
//lal
|
|
void UpdateMapScreenMilitiaControlPositions( void )
|
|
{
|
|
// set the position of the pop up boxes
|
|
SGPPoint pPoint;
|
|
|
|
if( guiCurrentScreen != MAP_SCREEN )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if( bSelectedAssignChar == -1 )
|
|
{
|
|
if( gfPreBattleInterfaceActive == FALSE )
|
|
{
|
|
giBoxY = 0;
|
|
}
|
|
return;
|
|
}
|
|
|
|
if( gCharactersList[ bSelectedAssignChar ].fValid == FALSE )
|
|
{
|
|
if( gfPreBattleInterfaceActive == FALSE )
|
|
{
|
|
giBoxY = 0;
|
|
}
|
|
return;
|
|
}
|
|
|
|
if( gfPreBattleInterfaceActive )
|
|
{
|
|
// do nothing
|
|
}
|
|
else
|
|
{
|
|
giBoxY = ( Y_START + ( bSelectedAssignChar ) * ( Y_SIZE + 2 ) );
|
|
}
|
|
|
|
MilitiaControlPosition.iY = giBoxY;
|
|
|
|
//TalkToAllPosition.iY = MilitiaControlPosition.iY + ( GetFontHeight( MAP_SCREEN_FONT ) + 2 )* MILCON_MENU_ALL;
|
|
|
|
|
|
|
|
if( fShowMilitiaControlMenu )
|
|
{
|
|
GetBoxPosition( ghMilitiaControlBox, &pPoint);
|
|
pPoint.iY = giBoxY;
|
|
|
|
SetBoxPosition( ghMilitiaControlBox, pPoint );
|
|
}
|
|
|
|
return;
|
|
}
|
|
//lal
|
|
|
|
|
|
|
|
|
|
|
|
void RandomMercInGroupSaysQuote( GROUP *pGroup, UINT16 usQuoteNum )
|
|
{
|
|
PLAYERGROUP *pPlayer;
|
|
SOLDIERTYPE *pSoldier;
|
|
UINT8 ubMercsInGroup[ CODE_MAXIMUM_NUMBER_OF_PLAYER_SLOTS ];
|
|
UINT8 ubNumMercs = 0;
|
|
UINT8 ubChosenMerc;
|
|
|
|
|
|
// if traversing tactically, don't do this, unless time compression was required for some reason (don't go to sector)
|
|
if ( ( gfTacticalTraversal || ( pGroup->ubSectorZ > 0 ) ) && !IsTimeBeingCompressed() )
|
|
{
|
|
return;
|
|
}
|
|
|
|
|
|
// Let's choose somebody in group.....
|
|
pPlayer = pGroup->pPlayerList;
|
|
|
|
while( pPlayer != NULL )
|
|
{
|
|
pSoldier = pPlayer->pSoldier;
|
|
Assert( pSoldier );
|
|
|
|
if ( pSoldier->stats.bLife >= OKLIFE && !( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) &&
|
|
!AM_A_ROBOT( pSoldier ) && !AM_AN_EPC( pSoldier ) && !pSoldier->flags.fMercAsleep )
|
|
{
|
|
ubMercsInGroup[ ubNumMercs ] = pSoldier->ubID;
|
|
ubNumMercs++;
|
|
}
|
|
|
|
pPlayer = pPlayer->next;
|
|
}
|
|
|
|
// At least say quote....
|
|
if ( ubNumMercs > 0 )
|
|
{
|
|
ubChosenMerc = (UINT8)Random( ubNumMercs );
|
|
pSoldier = MercPtrs[ ubMercsInGroup[ ubChosenMerc ] ];
|
|
|
|
TacticalCharacterDialogue( pSoldier, usQuoteNum );
|
|
}
|
|
}
|
|
|
|
|
|
INT32 GetNumberOfPeopleInCharacterList( void )
|
|
{
|
|
INT32 iCounter = 0, iCount = 0;
|
|
|
|
// get the number of valid mercs in the mapscreen character list
|
|
for( iCounter = 0; iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; iCounter++ )
|
|
{
|
|
if( gCharactersList[ iCounter].fValid == TRUE )
|
|
{
|
|
// another valid character
|
|
iCount++;
|
|
}
|
|
}
|
|
|
|
return( iCount );
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN ValidSelectableCharForNextOrPrev( INT32 iNewCharSlot )
|
|
{
|
|
BOOLEAN fHoldingItem = FALSE;
|
|
|
|
// not in popup
|
|
if ( InItemStackPopup( ) || InSectorStackPopup( ) || InKeyRingPopup( ) )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
// if holding an item
|
|
if ( ( gMPanelRegion.Cursor == EXTERN_CURSOR ) || gpItemPointer || fMapInventoryItem )
|
|
{
|
|
fHoldingItem = TRUE;
|
|
}
|
|
|
|
|
|
// if showing merc inventory, or holding an item
|
|
if ( fShowInventoryFlag || fHoldingItem )
|
|
{
|
|
// the new guy must have accessible inventory
|
|
if ( !MapCharacterHasAccessibleInventory( ( INT8 ) iNewCharSlot ) )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
}
|
|
|
|
|
|
if ( fHoldingItem )
|
|
{
|
|
return ( MapscreenCanPassItemToCharNum( iNewCharSlot ) );
|
|
}
|
|
else
|
|
{
|
|
return( TRUE );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN MapscreenCanPassItemToCharNum( INT32 iNewCharSlot )
|
|
{
|
|
SOLDIERTYPE *pNewSoldier;
|
|
SOLDIERTYPE *pOldSoldier;
|
|
|
|
|
|
// assumes we're holding an item
|
|
Assert( ( gMPanelRegion.Cursor == EXTERN_CURSOR ) || gpItemPointer || fMapInventoryItem );
|
|
|
|
|
|
// if in a hostile sector, disallow
|
|
if ( gTacticalStatus.fEnemyInSector )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
// can't pass items to nobody!
|
|
if ( iNewCharSlot == -1 )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
|
|
pNewSoldier = MercPtrs[ gCharactersList[ iNewCharSlot ].usSolID ];
|
|
|
|
|
|
// if showing sector inventory, and the item came from there
|
|
if ( fShowMapInventoryPool && !gpItemPointerSoldier && fMapInventoryItem )
|
|
{
|
|
// disallow passing items to anyone not in that sector
|
|
if ( pNewSoldier->sSectorX != sSelMapX ||
|
|
pNewSoldier->sSectorY != sSelMapY ||
|
|
pNewSoldier->bSectorZ != ( INT8 )( iCurrentMapSectorZ ) )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
if ( pNewSoldier->flags.fBetweenSectors )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
}
|
|
|
|
|
|
// if we know who it came from
|
|
if ( gpItemPointerSoldier )
|
|
{
|
|
pOldSoldier = gpItemPointerSoldier;
|
|
}
|
|
else
|
|
{
|
|
// it came from either the currently selected merc, or the sector inventory
|
|
if ( fMapInventoryItem || ( bSelectedInfoChar == -1 ) )
|
|
{
|
|
pOldSoldier = NULL;
|
|
}
|
|
else
|
|
{
|
|
pOldSoldier = MercPtrs[ gCharactersList[ bSelectedInfoChar ].usSolID ];
|
|
}
|
|
}
|
|
|
|
|
|
// if another merc had it previously
|
|
if ( pOldSoldier != NULL )
|
|
{
|
|
// disallow passing items to a merc not in the same sector
|
|
if ( pNewSoldier->sSectorX != pOldSoldier->sSectorX ||
|
|
pNewSoldier->sSectorY != pOldSoldier->sSectorY ||
|
|
pNewSoldier->bSectorZ != pOldSoldier->bSectorZ )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
// if on the road
|
|
if ( pNewSoldier->flags.fBetweenSectors )
|
|
{
|
|
// other guy must also be on the road...
|
|
if ( !pOldSoldier->flags.fBetweenSectors )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
// only exchanges between those is the same squad or vehicle are permitted
|
|
if ( pNewSoldier->bAssignment != pOldSoldier->bAssignment )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
// if in vehicles, make sure it's the same one
|
|
if ( ( pNewSoldier->bAssignment == VEHICLE ) && ( pNewSoldier->iVehicleId != pOldSoldier->iVehicleId ) )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// passed all tests
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
|
|
void GoToNextCharacterInList( void )
|
|
{
|
|
INT32 iCounter = 0, iCount = 0;
|
|
|
|
|
|
if( fShowDescriptionFlag == TRUE )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if( ( bSelectedDestChar != -1 ) || fPlotForHelicopter || fPlotForMilitia )
|
|
{
|
|
AbortMovementPlottingMode( );
|
|
}
|
|
|
|
// is the current guy invalid or the first one?
|
|
if( ( bSelectedInfoChar == -1 )|| ( bSelectedInfoChar == giMAXIMUM_NUMBER_OF_PLAYER_SLOTS ) )
|
|
{
|
|
iCount = 0;
|
|
}
|
|
else
|
|
{
|
|
iCount = bSelectedInfoChar + 1;
|
|
}
|
|
|
|
for( iCounter = 0; iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; ++iCounter )
|
|
{
|
|
if ( ( gCharactersList[ iCount ].fValid ) && ( iCount < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS ) && ValidSelectableCharForNextOrPrev( iCount ) )
|
|
{
|
|
ChangeSelectedInfoChar( ( INT8 )iCount, TRUE );
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
++iCount;
|
|
|
|
if( iCount >= giMAXIMUM_NUMBER_OF_PLAYER_SLOTS )
|
|
{
|
|
iCount = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// WANNE: Jump to first character in list when pressing PageUp
|
|
void GoToFirstCharacterInList( void )
|
|
{
|
|
INT32 iCounter = 0, iCount = 0;
|
|
|
|
if( fShowDescriptionFlag == TRUE )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ( (bSelectedDestChar != -1) || fPlotForHelicopter || fPlotForMilitia )
|
|
{
|
|
AbortMovementPlottingMode( );
|
|
}
|
|
|
|
// now run through the list and find first prev guy
|
|
for( iCounter = 0; iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; iCounter++ )
|
|
{
|
|
if ( ( gCharactersList[ iCounter ].fValid ) && ( iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS ) && ValidSelectableCharForNextOrPrev( iCounter ) )
|
|
{
|
|
ChangeSelectedInfoChar( ( INT8 )iCounter, TRUE );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// WANNE: Jump to last character in list when pressing PageDown
|
|
void GoToLastCharacterInList( void )
|
|
{
|
|
INT32 iCounter = 0, iCount = 0;
|
|
|
|
if( fShowDescriptionFlag == TRUE )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ( (bSelectedDestChar != -1) || fPlotForHelicopter || fPlotForMilitia )
|
|
{
|
|
AbortMovementPlottingMode( );
|
|
}
|
|
|
|
// now run through the list and find first prev guy
|
|
for( iCounter = giMAXIMUM_NUMBER_OF_PLAYER_SLOTS - 1; iCounter > 0; iCounter-- )
|
|
{
|
|
if ( ( gCharactersList[ iCounter ].fValid ) && ( iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS ) && ValidSelectableCharForNextOrPrev( iCounter ) )
|
|
{
|
|
ChangeSelectedInfoChar( ( INT8 )iCounter, TRUE );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void GoToPrevCharacterInList( void )
|
|
{
|
|
INT32 iCounter = 0, iCount = 0;
|
|
|
|
|
|
if( fShowDescriptionFlag == TRUE )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ( (bSelectedDestChar != -1) || fPlotForHelicopter || fPlotForMilitia )
|
|
{
|
|
AbortMovementPlottingMode( );
|
|
}
|
|
|
|
// is the current guy invalid or the first one?
|
|
if( ( bSelectedInfoChar == -1 ) || ( bSelectedInfoChar == 0 ) )
|
|
{
|
|
iCount = giMAXIMUM_NUMBER_OF_PLAYER_SLOTS;
|
|
}
|
|
else
|
|
{
|
|
iCount = bSelectedInfoChar - 1;
|
|
}
|
|
|
|
// now run through the list and find first prev guy
|
|
for( iCounter = 0; iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; iCounter++ )
|
|
{
|
|
if ( ( gCharactersList[ iCount ].fValid ) && ( iCount < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS ) && ValidSelectableCharForNextOrPrev( iCount ) )
|
|
{
|
|
ChangeSelectedInfoChar( ( INT8 )iCount, TRUE );
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
iCount--;
|
|
|
|
if( iCount < 0 )
|
|
{
|
|
iCount = giMAXIMUM_NUMBER_OF_PLAYER_SLOTS;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//void HandleMinerEvent( UINT8 bMinerNumber, INT16 sSectorX, INT16 sSectorY, INT16 sQuoteNumber, BOOLEAN fForceMapscreen )
|
|
void HandleMinerEvent( UINT8 ubHeadMinerIndex, INT16 sSectorX, INT16 sSectorY, INT16 sQuoteNumber, BOOLEAN fForceMapscreen )
|
|
{
|
|
BOOLEAN fFromMapscreen = FALSE;
|
|
|
|
|
|
if ( guiCurrentScreen == MAP_SCREEN )
|
|
{
|
|
fFromMapscreen = TRUE;
|
|
}
|
|
else
|
|
{
|
|
// if transition to mapscreen is required
|
|
if ( fForceMapscreen )
|
|
{
|
|
// switch to mapscreen so we can flash the mine sector the guy is talking about
|
|
EnterMapScreen( );
|
|
fFromMapscreen = TRUE;
|
|
}
|
|
}
|
|
|
|
HEAD_MINER_TYPE* miner = &gHeadMinerData[ubHeadMinerIndex];
|
|
|
|
if ( fFromMapscreen )
|
|
{
|
|
// if not showing map surface level
|
|
if ( iCurrentMapSectorZ != 0 )
|
|
{
|
|
// switch to it, because the miner locators wouldn't show up if we're underground while they speak
|
|
ChangeSelectedMapSector( sSelMapX, sSelMapY, 0 );
|
|
}
|
|
|
|
// set up the mine sector flasher
|
|
gsSectorLocatorX = sSectorX;
|
|
gsSectorLocatorY = sSectorY;
|
|
|
|
fMapPanelDirty = TRUE;
|
|
|
|
// post dialogue events for miners to say this quote and flash the sector where his mine is
|
|
//CharacterDialogueWithSpecialEvent( ( UINT8 )uiExternalFaceProfileIds[ bMinerNumber ], sQuoteNumber, bMinerNumber , DIALOGUE_EXTERNAL_NPC_UI , FALSE , FALSE , DIALOGUE_SPECIAL_EVENT_MINESECTOREVENT, START_RED_SECTOR_LOCATOR, 1 );
|
|
//CharacterDialogue( ( UINT8 )uiExternalFaceProfileIds[ bMinerNumber ], sQuoteNumber, ( UINT8 )( UINT8 )uiExternalStaticNPCFaces[ bMinerNumber ], DIALOGUE_EXTERNAL_NPC_UI, FALSE , FALSE );
|
|
//CharacterDialogueWithSpecialEvent( ( UINT8 )uiExternalFaceProfileIds[ bMinerNumber ], sQuoteNumber, bMinerNumber , DIALOGUE_EXTERNAL_NPC_UI , FALSE , FALSE , DIALOGUE_SPECIAL_EVENT_MINESECTOREVENT, STOP_RED_SECTOR_LOCATOR, 1 );
|
|
CharacterDialogueWithSpecialEvent( ( UINT8 )miner->usProfileId, sQuoteNumber, miner->ubExternalFaceIndex, DIALOGUE_EXTERNAL_NPC_UI, FALSE, FALSE, DIALOGUE_SPECIAL_EVENT_MINESECTOREVENT, START_RED_SECTOR_LOCATOR, 1 );
|
|
CharacterDialogue( ( UINT8 )miner->usProfileId, sQuoteNumber, ( UINT8 )uiExternalStaticNPCFaces[miner->ubExternalFaceIndex], DIALOGUE_EXTERNAL_NPC_UI, FALSE, FALSE );
|
|
CharacterDialogueWithSpecialEvent( ( UINT8 )miner->usProfileId, sQuoteNumber, miner->ubExternalFaceIndex, DIALOGUE_EXTERNAL_NPC_UI, FALSE, FALSE, DIALOGUE_SPECIAL_EVENT_MINESECTOREVENT, STOP_RED_SECTOR_LOCATOR, 1 );
|
|
}
|
|
else // stay in tactical
|
|
{
|
|
// no need to to highlight mine sector
|
|
//CharacterDialogue( ( UINT8 )uiExternalFaceProfileIds[ bMinerNumber ], sQuoteNumber, ( UINT8 )( UINT8 )uiExternalStaticNPCFaces[ bMinerNumber ], DIALOGUE_EXTERNAL_NPC_UI, FALSE , FALSE );
|
|
CharacterDialogue( ( UINT8 )miner->usProfileId, sQuoteNumber, ( UINT8 )uiExternalStaticNPCFaces[miner->ubExternalFaceIndex], DIALOGUE_EXTERNAL_NPC_UI, FALSE , FALSE );
|
|
}
|
|
}
|
|
|
|
|
|
void SetUpAnimationOfMineSectors( INT32 iEvent )
|
|
{
|
|
// set up the animation of mine sectors
|
|
switch( iEvent )
|
|
{
|
|
case START_RED_SECTOR_LOCATOR:
|
|
gubBlitSectorLocatorCode = LOCATOR_COLOR_RED;
|
|
break;
|
|
|
|
case START_YELLOW_SECTOR_LOCATOR:
|
|
gubBlitSectorLocatorCode = LOCATOR_COLOR_YELLOW;
|
|
break;
|
|
|
|
case STOP_RED_SECTOR_LOCATOR:
|
|
case STOP_YELLOW_SECTOR_LOCATOR:
|
|
TurnOffSectorLocator();
|
|
break;
|
|
}
|
|
}
|
|
|
|
void ShutDownUserDefineHelpTextRegions( void )
|
|
{
|
|
// dirty the tactical panel
|
|
fInterfacePanelDirty = DIRTYLEVEL2;
|
|
SetRenderFlags( RENDER_FLAG_FULL );
|
|
|
|
//dirty the map panel
|
|
StopMapScreenHelpText( );
|
|
|
|
//r eset tactical flag too
|
|
StopShowingInterfaceFastHelpText( );
|
|
}
|
|
|
|
|
|
// thsi will setup the fast help text regions that are unrelated to mouse regions
|
|
// user is to pass in the x,y position of the box, the width to wrap the strings and the string itself
|
|
BOOLEAN SetUpFastHelpListRegions( INT32 iXPosition[], INT32 iYPosition[], INT32 iWidth[], STR16 sString[], INT32 iSize )
|
|
{
|
|
INT32 iCounter = 0;
|
|
|
|
// reset the size
|
|
giSizeOfInterfaceFastHelpTextList = 0;
|
|
|
|
for( iCounter = 0; iCounter < iSize; iCounter++ )
|
|
{
|
|
|
|
// forgiving way of making sure we don't go too far
|
|
CHECKF( iCounter < MAX_MAPSCREEN_FAST_HELP );
|
|
|
|
// now copy over info
|
|
pFastHelpMapScreenList[ iCounter ].iX = iXPosition[ iCounter ];
|
|
pFastHelpMapScreenList[ iCounter ].iY = iYPosition[ iCounter ];
|
|
pFastHelpMapScreenList[ iCounter ].iW = iWidth[ iCounter ];
|
|
|
|
// copy string
|
|
wcscpy( pFastHelpMapScreenList[ iCounter ].FastHelpText, sString[ iCounter ] );
|
|
|
|
// update the size
|
|
giSizeOfInterfaceFastHelpTextList = iCounter + 1;
|
|
}
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
// handle the actual showing of the interface fast help text
|
|
void HandleShowingOfTacticalInterfaceFastHelpText( void )
|
|
{
|
|
static BOOLEAN fTextActive = FALSE;
|
|
|
|
if( fInterfaceFastHelpTextActive )
|
|
{
|
|
DisplayFastHelpRegions( pFastHelpMapScreenList, giSizeOfInterfaceFastHelpTextList );
|
|
|
|
PauseGame();
|
|
|
|
// lock out the screen
|
|
SetUpShutDownMapScreenHelpTextScreenMask( );
|
|
|
|
gfIgnoreScrolling = TRUE;
|
|
|
|
// the text is active
|
|
fTextActive = TRUE;
|
|
|
|
}
|
|
else if( ( fInterfaceFastHelpTextActive == FALSE ) && ( fTextActive ) )
|
|
{
|
|
fTextActive = FALSE;
|
|
UnPauseGame();
|
|
gfIgnoreScrolling = FALSE;
|
|
|
|
// shut down
|
|
ShutDownUserDefineHelpTextRegions( );
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
// start showing fast help text
|
|
void StartShowingInterfaceFastHelpText( void )
|
|
{
|
|
fInterfaceFastHelpTextActive = TRUE;
|
|
}
|
|
|
|
// stop showing interface fast help text
|
|
void StopShowingInterfaceFastHelpText( void )
|
|
{
|
|
fInterfaceFastHelpTextActive = FALSE;
|
|
}
|
|
|
|
|
|
// is the interface text up?
|
|
BOOLEAN IsTheInterfaceFastHelpTextActive( void )
|
|
{
|
|
return( fInterfaceFastHelpTextActive );
|
|
}
|
|
|
|
|
|
// display all the regions in the list
|
|
void DisplayFastHelpRegions( FASTHELPREGION *pRegion, INT32 iSize )
|
|
{
|
|
INT32 iCounter = 0;
|
|
|
|
// run through and show all the regions
|
|
for( iCounter = 0; iCounter < iSize; iCounter++ )
|
|
{
|
|
DisplayUserDefineHelpTextRegions( &( pRegion[ iCounter ] ) );
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
// show one region
|
|
void DisplayUserDefineHelpTextRegions( FASTHELPREGION *pRegion )
|
|
{
|
|
UINT16 usFillColor;
|
|
INT32 iX,iY,iW,iH;
|
|
UINT8 *pDestBuf;
|
|
UINT32 uiDestPitchBYTES;
|
|
|
|
|
|
// grab the color for the background region
|
|
usFillColor = Get16BPPColor(FROMRGB(250, 240, 188));
|
|
|
|
|
|
iX = pRegion->iX;
|
|
iY = pRegion->iY;
|
|
// get the width and height of the string
|
|
iW = (INT32)( pRegion->iW ) + 14;
|
|
iH = IanWrappedStringHeight( ( UINT16 )iX, ( UINT16 )iY, ( UINT16 )( pRegion->iW ), 0, FONT10ARIAL, FONT_BLACK, pRegion->FastHelpText, FONT_BLACK, TRUE, 0 );
|
|
|
|
// tack on the outer border
|
|
iH += 14;
|
|
|
|
// gone not far enough?
|
|
if ( iX < 0 )
|
|
iX = 0;
|
|
|
|
// gone too far
|
|
if ( ( pRegion->iX + iW ) >= SCREEN_WIDTH )
|
|
iX = (SCREEN_WIDTH - iW - 4);
|
|
|
|
// what about the y value?
|
|
iY = (INT32)pRegion->iY - ( iH * 3 / 4);
|
|
|
|
// not far enough
|
|
if (iY < 0)
|
|
iY = 0;
|
|
|
|
// too far
|
|
if ( (iY + iH) >= SCREEN_HEIGHT )
|
|
iY = (SCREEN_HEIGHT - iH - 15);
|
|
|
|
pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES );
|
|
SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT );
|
|
RectangleDraw( TRUE, iX + 1, iY + 1, iX + iW - 1, iY + iH - 1, Get16BPPColor( FROMRGB( 65, 57, 15 ) ), pDestBuf );
|
|
RectangleDraw( TRUE, iX, iY, iX + iW - 2, iY + iH - 2, Get16BPPColor( FROMRGB( 227, 198, 88 ) ), pDestBuf );
|
|
UnLockVideoSurface( FRAME_BUFFER );
|
|
ShadowVideoSurfaceRect( FRAME_BUFFER, iX + 2, iY + 2, iX + iW - 3, iY + iH - 3 );
|
|
ShadowVideoSurfaceRect( FRAME_BUFFER, iX + 2, iY + 2, iX + iW - 3, iY + iH - 3 );
|
|
|
|
// fillt he video surface areas
|
|
//ColorFillVideoSurfaceArea(FRAME_BUFFER, iX, iY, (iX + iW), (iY + iH), 0);
|
|
//ColorFillVideoSurfaceArea(FRAME_BUFFER, (iX + 1), (iY + 1), (iX + iW - 1), (iY + iH - 1), usFillColor);
|
|
|
|
SetFont( FONT10ARIAL );
|
|
SetFontForeground( FONT_BEIGE );
|
|
|
|
iH = ( INT32 )DisplayWrappedString( ( INT16 )( iX + 10 ), ( INT16 )( iY + 6 ), ( INT16 )pRegion->iW, 0, FONT10ARIAL, FONT_BEIGE, pRegion->FastHelpText, FONT_NEARBLACK, TRUE, 0 );
|
|
|
|
iHeightOfInitFastHelpText = iH + 20;
|
|
|
|
InvalidateRegion( iX, iY, (iX + iW) , (iY + iH + 20 ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
extern void DisplayHelpTokenizedString( const STR16 pStringA, INT16 sX, INT16 sY );
|
|
extern INT16 GetNumberOfLinesInHeight( const STR16 pStringA );
|
|
extern INT16 GetWidthOfString( const STR16 pStringA );
|
|
|
|
void DisplaySoldierToolTip( FASTHELPREGION *pRegion )
|
|
{
|
|
UINT16 usFillColor;
|
|
INT32 iX,iY,iW,iH;
|
|
UINT8 *pDestBuf;
|
|
UINT32 uiDestPitchBYTES;
|
|
|
|
|
|
// grab the color for the background region
|
|
usFillColor = Get16BPPColor(FROMRGB(250, 240, 188));
|
|
|
|
|
|
iX = pRegion->iX;
|
|
iY = pRegion->iY;
|
|
// get the width and height of the string
|
|
//iW = (INT32)( pRegion->iW ) + 14;
|
|
iW = (INT32)GetWidthOfString( pRegion->FastHelpText ) + 10;
|
|
|
|
//iH = IanWrappedStringHeight( ( UINT16 )iX, ( UINT16 )iY, ( UINT16 )( pRegion->iW ), 0, FONT10ARIAL, FONT_BLACK, pRegion->FastHelpText, FONT_BLACK, TRUE, 0 );
|
|
iH = (INT32)( GetNumberOfLinesInHeight( pRegion->FastHelpText ) * (GetFontHeight(FONT10ARIAL)+1) + 8 );
|
|
|
|
// tack on the outer border
|
|
iH += 14;
|
|
|
|
// gone not far enough?
|
|
if ( iX < 0 )
|
|
iX = 0;
|
|
|
|
// gone too far
|
|
if ( ( pRegion->iX + iW ) >= SCREEN_WIDTH )
|
|
iX = (SCREEN_WIDTH - iW - 4);
|
|
|
|
// what about the y value?
|
|
iY = (INT32)pRegion->iY - ( iH * 3 / 4);
|
|
|
|
// not far enough
|
|
if (iY < 0)
|
|
iY = 0;
|
|
|
|
// too far
|
|
if ( (iY + iH) >= SCREEN_HEIGHT )
|
|
iY = (SCREEN_HEIGHT - iH - 15);
|
|
|
|
pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES );
|
|
SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT );
|
|
RectangleDraw( TRUE, iX + 1, iY + 1, iX + iW - 1, iY + iH - 1, Get16BPPColor( FROMRGB( 65, 57, 15 ) ), pDestBuf );
|
|
RectangleDraw( TRUE, iX, iY, iX + iW - 2, iY + iH - 2, Get16BPPColor( FROMRGB( 227, 198, 88 ) ), pDestBuf );
|
|
UnLockVideoSurface( FRAME_BUFFER );
|
|
ShadowVideoSurfaceRect( FRAME_BUFFER, iX + 2, iY + 2, iX + iW - 3, iY + iH - 3 );
|
|
ShadowVideoSurfaceRect( FRAME_BUFFER, iX + 2, iY + 2, iX + iW - 3, iY + iH - 3 );
|
|
|
|
// fillt he video surface areas
|
|
//ColorFillVideoSurfaceArea(FRAME_BUFFER, iX, iY, (iX + iW), (iY + iH), 0);
|
|
//ColorFillVideoSurfaceArea(FRAME_BUFFER, (iX + 1), (iY + 1), (iX + iW - 1), (iY + iH - 1), usFillColor);
|
|
|
|
SetFont( FONT10ARIAL );
|
|
SetFontForeground( FONT_BEIGE );
|
|
|
|
//iH = ( INT32 )DisplayWrappedString( ( INT16 )( iX + 10 ), ( INT16 )( iY + 6 ), ( INT16 )pRegion->iW, 0, FONT10ARIAL, FONT_BEIGE, pRegion->FastHelpText, FONT_NEARBLACK, TRUE, 0 );
|
|
|
|
DisplayHelpTokenizedString( pRegion->FastHelpText ,( INT16 )( iX + 5 ), ( INT16 )( iY + 5 ) );
|
|
|
|
iHeightOfInitFastHelpText = iH + 20;
|
|
|
|
InvalidateRegion( iX, iY, (iX + iW) , (iY + iH + 20 ) );
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DisplayFastHelpForInitialTripInToMapScreen( FASTHELPREGION *pRegion )
|
|
{
|
|
if( gTacticalStatus.fDidGameJustStart )
|
|
{
|
|
if( AnyMercsHired() == FALSE )
|
|
{
|
|
return;
|
|
}
|
|
|
|
HandleDisplayOfExitToTacticalMessageForFirstEntryToMapScreen( );
|
|
// DEF: removed cause the help screen will replace the help screen
|
|
// DisplayFastHelpRegions( &pFastHelpMapScreenList[ 9 ], 1 );
|
|
|
|
}
|
|
else
|
|
{
|
|
DisplayFastHelpRegions( pFastHelpMapScreenList, giSizeOfInterfaceFastHelpTextList );
|
|
}
|
|
|
|
SetUpShutDownMapScreenHelpTextScreenMask( );
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void DisplayMapScreenFastHelpList( void )
|
|
{
|
|
INT32 iCounter = 0;
|
|
|
|
DisplayFastHelpForInitialTripInToMapScreen( &pFastHelpMapScreenList[ iCounter ] );
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void SetUpMapScreenFastHelpText( void )
|
|
{
|
|
INT32 iCounter = 0;
|
|
|
|
// now run through and display all the fast help text for the mapscreen functional regions
|
|
for( iCounter = 0; iCounter < NUMBER_OF_MAPSCREEN_HELP_MESSAGES; iCounter++ )
|
|
{
|
|
pFastHelpMapScreenList[ iCounter ].iX = pMapScreenFastHelpLocationList[ iCounter ].iX;
|
|
pFastHelpMapScreenList[ iCounter ].iY = pMapScreenFastHelpLocationList[ iCounter ].iY;
|
|
pFastHelpMapScreenList[ iCounter ].iW = pMapScreenFastHelpWidthList[ iCounter ];
|
|
wcscpy( pFastHelpMapScreenList[ iCounter ].FastHelpText, pMapScreenFastHelpTextList[ iCounter ] );
|
|
}
|
|
|
|
// DEF: removed cause the help screen will replace the help screen
|
|
/*
|
|
pFastHelpMapScreenList[ 9 ].iX = pMapScreenFastHelpLocationList[ 9 ].iX;
|
|
pFastHelpMapScreenList[ 9 ].iY = pMapScreenFastHelpLocationList[ 9 ].iY;
|
|
pFastHelpMapScreenList[ 9 ].iW = pMapScreenFastHelpWidthList[ 9 ];
|
|
wcscpy( pFastHelpMapScreenList[ 9 ].FastHelpText, pMapScreenFastHelpTextList[ 9 ] );
|
|
*/
|
|
return;
|
|
}
|
|
|
|
void StopMapScreenHelpText( void )
|
|
{
|
|
fShowMapScreenHelpText = FALSE;
|
|
fTeamPanelDirty = TRUE;
|
|
fMapPanelDirty = TRUE;
|
|
fCharacterInfoPanelDirty = TRUE;
|
|
fMapScreenBottomDirty = TRUE;
|
|
|
|
SetUpShutDownMapScreenHelpTextScreenMask( );
|
|
return;
|
|
}
|
|
|
|
BOOLEAN IsMapScreenHelpTextUp( void )
|
|
{
|
|
return( fShowMapScreenHelpText );
|
|
}
|
|
|
|
void SetUpShutDownMapScreenHelpTextScreenMask( void )
|
|
{
|
|
static BOOLEAN fCreated = FALSE;
|
|
|
|
// create or destroy the screen mask as needed
|
|
if( ( ( fShowMapScreenHelpText == TRUE ) || ( fInterfaceFastHelpTextActive == TRUE ) ) && ( fCreated == FALSE ) )
|
|
{
|
|
if( gTacticalStatus.fDidGameJustStart )
|
|
{
|
|
MSYS_DefineRegion( &gMapScreenHelpTextMask , ( INT16 )( pMapScreenFastHelpLocationList[ 9 ].iX ), ( INT16 )( pMapScreenFastHelpLocationList[ 9 ].iY ), ( INT16 )( pMapScreenFastHelpLocationList[ 9 ].iX + pMapScreenFastHelpWidthList[ 9 ] ), ( INT16 )( pMapScreenFastHelpLocationList[ 9 ].iY + iHeightOfInitFastHelpText ), MSYS_PRIORITY_HIGHEST,
|
|
MSYS_NO_CURSOR, MSYS_NO_CALLBACK, MapScreenHelpTextScreenMaskBtnCallback );
|
|
}
|
|
else
|
|
{
|
|
MSYS_DefineRegion( &gMapScreenHelpTextMask , 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, MSYS_PRIORITY_HIGHEST,
|
|
MSYS_NO_CURSOR, MSYS_NO_CALLBACK, MapScreenHelpTextScreenMaskBtnCallback );
|
|
}
|
|
|
|
fCreated = TRUE;
|
|
|
|
}
|
|
else if( ( fShowMapScreenHelpText == FALSE ) && ( fInterfaceFastHelpTextActive == FALSE ) && ( fCreated == TRUE ) )
|
|
{
|
|
MSYS_RemoveRegion( &gMapScreenHelpTextMask );
|
|
|
|
fCreated = FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
void MapScreenHelpTextScreenMaskBtnCallback( MOUSE_REGION * pRegion, INT32 iReason )
|
|
{
|
|
if( iReason & MSYS_CALLBACK_REASON_RBUTTON_UP )
|
|
{
|
|
// stop showing
|
|
ShutDownUserDefineHelpTextRegions( );
|
|
}
|
|
else if( iReason & MSYS_CALLBACK_REASON_LBUTTON_UP )
|
|
{
|
|
// stop showing
|
|
ShutDownUserDefineHelpTextRegions( );
|
|
}
|
|
}
|
|
|
|
|
|
BOOLEAN IsSoldierSelectedForMovement( SOLDIERTYPE *pSoldier )
|
|
{
|
|
INT32 iCounter = 0;
|
|
|
|
// run through the list and turn this soldiers value on
|
|
for( iCounter = 0; iCounter < giNumberOfSoldiersInSectorMoving; iCounter++ )
|
|
{
|
|
if( ( pSoldierMovingList[ iCounter ] == pSoldier ) && ( fSoldierIsMoving[ iCounter ] ) )
|
|
{
|
|
return ( TRUE );
|
|
}
|
|
}
|
|
return( FALSE );
|
|
}
|
|
|
|
BOOLEAN IsSquadSelectedForMovement( INT32 iSquadNumber )
|
|
{
|
|
INT32 iCounter = 0;
|
|
|
|
// run through squad list and set them on
|
|
for( iCounter = 0; iCounter < giNumberOfSquadsInSectorMoving; iCounter++ )
|
|
{
|
|
if( ( iSquadMovingList[ iCounter ] == iSquadNumber ) && ( fSquadIsMoving[ iCounter ] ) )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
}
|
|
|
|
return( FALSE );
|
|
}
|
|
|
|
|
|
BOOLEAN IsVehicleSelectedForMovement( INT32 iVehicleId )
|
|
{
|
|
INT32 iCounter = 0;
|
|
|
|
// run through squad list and set them on
|
|
for( iCounter = 0; iCounter < giNumberOfVehiclesInSectorMoving; iCounter++ )
|
|
{
|
|
if( ( iVehicleMovingList[ iCounter ] == iVehicleId ) && ( fVehicleIsMoving[ iCounter ] ) )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
}
|
|
return( FALSE );
|
|
}
|
|
|
|
|
|
|
|
void SelectSoldierForMovement( SOLDIERTYPE *pSoldier )
|
|
{
|
|
INT32 iCounter = 0;
|
|
|
|
if( pSoldier == NULL )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// run through the list and turn this soldiers value on
|
|
for( iCounter = 0; iCounter < giNumberOfSoldiersInSectorMoving; iCounter++ )
|
|
{
|
|
if( pSoldierMovingList[ iCounter ] == pSoldier )
|
|
{
|
|
// turn the selected soldier ON
|
|
fSoldierIsMoving[ iCounter ] = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void DeselectSoldierForMovement( SOLDIERTYPE *pSoldier )
|
|
{
|
|
INT32 iCounter = 0;
|
|
|
|
if( pSoldier == NULL )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// run through the list and turn this soldier's value on
|
|
for( iCounter = 0; iCounter < giNumberOfSoldiersInSectorMoving; iCounter++ )
|
|
{
|
|
if( pSoldierMovingList[ iCounter ] == pSoldier )
|
|
{
|
|
// turn the selected soldier off
|
|
fSoldierIsMoving[ iCounter ] = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void SelectSquadForMovement( INT32 iSquadNumber )
|
|
{
|
|
INT32 iCounter = 0, iCount = 0;
|
|
BOOLEAN fSomeCantMove = FALSE;
|
|
SOLDIERTYPE *pSoldier = NULL;
|
|
BOOLEAN fFirstFailure;
|
|
|
|
|
|
// run through squad list and set them on
|
|
for( iCounter = 0; iCounter < giNumberOfSquadsInSectorMoving; iCounter++ )
|
|
{
|
|
if( iSquadMovingList[ iCounter ] == iSquadNumber )
|
|
{
|
|
// found it
|
|
|
|
fFirstFailure = TRUE;
|
|
|
|
// try to select everyone in squad
|
|
for( iCount = 0; iCount < NUMBER_OF_SOLDIERS_PER_SQUAD; iCount++ )
|
|
{
|
|
pSoldier = Squad[ iSquadNumber ][ iCount ];
|
|
|
|
if ( pSoldier && pSoldier->bActive )
|
|
{
|
|
// is he able & allowed to move? (Report only the first reason for failure encountered)
|
|
if ( CanMoveBoxSoldierMoveStrategically( pSoldier, fFirstFailure ) )
|
|
{
|
|
SelectSoldierForMovement( pSoldier );
|
|
}
|
|
else
|
|
{
|
|
fSomeCantMove = TRUE;
|
|
fFirstFailure = FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( !fSomeCantMove )
|
|
{
|
|
fSquadIsMoving[ iCounter ] = TRUE;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void DeselectSquadForMovement( INT32 iSquadNumber )
|
|
{
|
|
INT32 iCounter = 0, iCount = 0;
|
|
SOLDIERTYPE *pSoldier = NULL;
|
|
|
|
// run through squad list and set them off
|
|
for( iCounter = 0; iCounter < giNumberOfSquadsInSectorMoving; iCounter++ )
|
|
{
|
|
if( iSquadMovingList[ iCounter ] == iSquadNumber )
|
|
{
|
|
// found it
|
|
fSquadIsMoving[ iCounter ] = FALSE;
|
|
|
|
// now deselect everyone in squad
|
|
for( iCount = 0; iCount < NUMBER_OF_SOLDIERS_PER_SQUAD; iCount++ )
|
|
{
|
|
pSoldier = Squad[ iSquadNumber ][ iCount ];
|
|
|
|
if ( pSoldier && pSoldier->bActive )
|
|
{
|
|
DeselectSoldierForMovement( pSoldier );
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
BOOLEAN AllSoldiersInSquadSelected( INT32 iSquadNumber )
|
|
{
|
|
INT32 iCounter = 0;
|
|
|
|
// is everyone on this squad moving?
|
|
for( iCounter = 0; iCounter < giNumberOfSoldiersInSectorMoving; iCounter++ )
|
|
{
|
|
if( pSoldierMovingList[ iCounter ]->bAssignment == ( INT8 )iSquadNumber )
|
|
{
|
|
if( fSoldierIsMoving[ iCounter ] == FALSE )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
}
|
|
}
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
|
|
void SelectVehicleForMovement( INT32 iVehicleId, BOOLEAN fAndAllOnBoard )
|
|
{
|
|
INT32 iCounter = 0, iCount = 0;
|
|
SOLDIERTYPE *pPassenger = NULL;
|
|
BOOLEAN fHasDriver = FALSE;
|
|
BOOLEAN fFirstFailure;
|
|
|
|
|
|
// run through vehicle list and set them on
|
|
for( iCounter = 0; iCounter < giNumberOfVehiclesInSectorMoving; iCounter++ )
|
|
{
|
|
if( iVehicleMovingList[ iCounter ] == iVehicleId )
|
|
{
|
|
// found it
|
|
|
|
fFirstFailure = TRUE;
|
|
|
|
for( iCount = 0; iCount < 10; iCount++ )
|
|
{
|
|
pPassenger = pVehicleList[ iVehicleId ].pPassengers[ iCount ];
|
|
|
|
if ( fAndAllOnBoard )
|
|
{
|
|
// try to select everyone in vehicle
|
|
|
|
if ( pPassenger && pPassenger->bActive )
|
|
{
|
|
// is he able & allowed to move?
|
|
if ( CanMoveBoxSoldierMoveStrategically( pPassenger, fFirstFailure ) )
|
|
{
|
|
SelectSoldierForMovement( pPassenger );
|
|
}
|
|
else
|
|
{
|
|
fFirstFailure = FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( IsSoldierSelectedForMovement( pPassenger ) )
|
|
{
|
|
fHasDriver = TRUE;
|
|
}
|
|
}
|
|
|
|
// vehicle itself can only move if at least one passenger can move and is moving!
|
|
if ( fHasDriver )
|
|
{
|
|
fVehicleIsMoving[ iCounter ] = TRUE;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void DeselectVehicleForMovement( INT32 iVehicleId )
|
|
{
|
|
INT32 iCounter = 0, iCount = 0;
|
|
SOLDIERTYPE *pPassenger = NULL;
|
|
|
|
|
|
// run through vehicle list and set them off
|
|
for( iCounter = 0; iCounter < giNumberOfVehiclesInSectorMoving; iCounter++ )
|
|
{
|
|
if( iVehicleMovingList[ iCounter ] == iVehicleId )
|
|
{
|
|
// found it
|
|
fVehicleIsMoving[ iCounter ] = FALSE;
|
|
|
|
// now deselect everyone in vehicle
|
|
for( iCount = 0; iCount < MAXPASSENGERS ; iCount++ )
|
|
{
|
|
pPassenger = pVehicleList[ iVehicleId ].pPassengers[ iCount ];
|
|
|
|
if ( pPassenger && pPassenger->bActive )
|
|
{
|
|
DeselectSoldierForMovement( pPassenger );
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
INT32 HowManyMovingSoldiersInVehicle( INT32 iVehicleId )
|
|
{
|
|
INT32 iNumber = 0, iCounter = 0;
|
|
|
|
for( iCounter = 0; iCounter < giNumberOfSoldiersInSectorMoving; iCounter++ )
|
|
{
|
|
// is he in the right vehicle
|
|
if( ( pSoldierMovingList[ iCounter ]->bAssignment == VEHICLE )&&( pSoldierMovingList[ iCounter ]->iVehicleId == iVehicleId ) )
|
|
{
|
|
// if he moving?
|
|
if ( fSoldierIsMoving[ iCounter ] )
|
|
{
|
|
// ok, another one in the vehicle that is going to move
|
|
iNumber++;
|
|
}
|
|
}
|
|
}
|
|
|
|
return( iNumber );
|
|
}
|
|
|
|
INT32 HowManyMovingSoldiersInSquad( INT32 iSquadNumber )
|
|
{
|
|
INT32 iNumber = 0, iCounter = 0;
|
|
|
|
for( iCounter = 0; iCounter < giNumberOfSoldiersInSectorMoving; iCounter++ )
|
|
{
|
|
// is he in the right squad
|
|
if( pSoldierMovingList[ iCounter ]->bAssignment == iSquadNumber )
|
|
{
|
|
// if he moving?
|
|
if ( fSoldierIsMoving[ iCounter ] )
|
|
{
|
|
// ok, another one in the squad that is going to move
|
|
iNumber++;
|
|
}
|
|
}
|
|
}
|
|
|
|
return( iNumber );
|
|
}
|
|
|
|
|
|
// try to add this soldier to the moving lists
|
|
void AddSoldierToMovingLists( SOLDIERTYPE *pSoldier )
|
|
{
|
|
INT32 iCounter = 0;
|
|
|
|
for( iCounter = 0; iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; iCounter++ )
|
|
{
|
|
if( pSoldierMovingList[ iCounter ] == pSoldier )
|
|
{
|
|
// found
|
|
return;
|
|
}
|
|
else if( pSoldierMovingList[ iCounter ] == NULL )
|
|
{
|
|
// found a free slot
|
|
pSoldierMovingList[ iCounter ] = pSoldier;
|
|
fSoldierIsMoving[ iCounter ] = FALSE;
|
|
|
|
giNumberOfSoldiersInSectorMoving++;
|
|
return;
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
// try to add this soldier to the moving lists
|
|
void AddSquadToMovingLists( INT32 iSquadNumber )
|
|
{
|
|
INT32 iCounter = 0;
|
|
|
|
if( iSquadNumber == -1 )
|
|
{
|
|
// invalid squad
|
|
return;
|
|
}
|
|
|
|
for( iCounter = 0; iCounter < NUMBER_OF_SQUADS; iCounter++ )
|
|
{
|
|
if( iSquadMovingList[ iCounter ] == iSquadNumber )
|
|
{
|
|
// found
|
|
return;
|
|
}
|
|
if( iSquadMovingList[ iCounter ] == -1 )
|
|
{
|
|
// found a free slot
|
|
iSquadMovingList[ iCounter ] = iSquadNumber;
|
|
fSquadIsMoving[ iCounter ] = FALSE;
|
|
|
|
giNumberOfSquadsInSectorMoving++;
|
|
return;
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
// try to add this soldier to the moving lists
|
|
void AddVehicleToMovingLists( INT32 iVehicleId )
|
|
{
|
|
INT32 iCounter = 0;
|
|
|
|
if( iVehicleId == -1 )
|
|
{
|
|
// invalid squad
|
|
return;
|
|
}
|
|
|
|
for( iCounter = 0; iCounter < NUMBER_OF_SQUADS; iCounter++ )
|
|
{
|
|
if( iVehicleMovingList[ iCounter ] == iVehicleId )
|
|
{
|
|
// found
|
|
return;
|
|
}
|
|
if( iVehicleMovingList[ iCounter ] == -1 )
|
|
{
|
|
// found a free slot
|
|
iVehicleMovingList[ iCounter ] = iVehicleId;
|
|
fVehicleIsMoving[ iCounter ] = FALSE;
|
|
|
|
giNumberOfVehiclesInSectorMoving++;
|
|
return;
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
void InitializeMovingLists( void )
|
|
{
|
|
INT32 iCounter = 0;
|
|
|
|
|
|
giNumberOfSoldiersInSectorMoving = 0;
|
|
giNumberOfSquadsInSectorMoving = 0;
|
|
giNumberOfVehiclesInSectorMoving = 0;
|
|
|
|
// init the soldiers
|
|
for( iCounter = 0; iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; iCounter++ )
|
|
{
|
|
// soldier is NOT moving
|
|
pSoldierMovingList[ iCounter ] = NULL;
|
|
// turn the selected soldier off
|
|
fSoldierIsMoving[ iCounter ] = FALSE;
|
|
}
|
|
|
|
|
|
// init the squads
|
|
for( iCounter = 0; iCounter < NUMBER_OF_SQUADS; iCounter++ )
|
|
{
|
|
// reset squad value
|
|
iSquadMovingList[ iCounter ] = -1;
|
|
// turn it off
|
|
fSquadIsMoving[ iCounter ] = FALSE;
|
|
}
|
|
|
|
// init the vehicles
|
|
for( iCounter = 0; iCounter < NUMBER_OF_SQUADS; iCounter++ )
|
|
{
|
|
// reset squad value
|
|
iVehicleMovingList[ iCounter ] = -1;
|
|
// turn it off
|
|
fVehicleIsMoving[ iCounter ] = FALSE;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN IsAnythingSelectedForMoving( void )
|
|
{
|
|
INT32 iCounter = 0;
|
|
|
|
|
|
// check soldiers
|
|
for( iCounter = 0; iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; iCounter++ )
|
|
{
|
|
if ( ( pSoldierMovingList[ iCounter ] != NULL ) && fSoldierIsMoving[ iCounter ] )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
}
|
|
|
|
|
|
// init the squads
|
|
for( iCounter = 0; iCounter < NUMBER_OF_SQUADS; iCounter++ )
|
|
{
|
|
if ( ( iSquadMovingList[ iCounter ] != -1 ) && fSquadIsMoving[ iCounter ] )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
}
|
|
|
|
// init the vehicles
|
|
for( iCounter = 0; iCounter < NUMBER_OF_SQUADS; iCounter++ )
|
|
{
|
|
if ( ( iVehicleMovingList[ iCounter ] != -1 ) && fVehicleIsMoving[ iCounter ] )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
}
|
|
|
|
return( FALSE );
|
|
}
|
|
|
|
|
|
|
|
void CreateDestroyMovementBox( INT16 sSectorX, INT16 sSectorY, INT16 sSectorZ )
|
|
{
|
|
static BOOLEAN fCreated = FALSE;
|
|
|
|
|
|
// not allowed for underground movement!
|
|
Assert( sSectorZ == 0 );
|
|
|
|
if( ( fShowMapScreenMovementList == TRUE ) && ( fCreated == FALSE ) )
|
|
{
|
|
fCreated = TRUE;
|
|
|
|
// create the box and mouse regions
|
|
CreatePopUpBoxForMovementBox( );
|
|
BuildMouseRegionsForMoveBox( );
|
|
CreateScreenMaskForMoveBox( );
|
|
fMapPanelDirty = TRUE;
|
|
}
|
|
else if( ( fShowMapScreenMovementList == FALSE ) && ( fCreated == TRUE ) )
|
|
{
|
|
fCreated = FALSE;
|
|
|
|
// destroy the box and mouse regions
|
|
ClearMouseRegionsForMoveBox( );
|
|
RemoveBox( ghMoveBox );
|
|
ghMoveBox = -1;
|
|
RemoveScreenMaskForMoveBox( );
|
|
fMapPanelDirty = TRUE;
|
|
fMapScreenBottomDirty = TRUE; // really long move boxes can overlap bottom panel
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetUpMovingListsForSector( INT16 sSectorX, INT16 sSectorY, INT16 sSectorZ )
|
|
{
|
|
INT32 iCounter = 0;
|
|
SOLDIERTYPE *pSoldier = NULL;
|
|
|
|
|
|
// not allowed for underground movement!
|
|
Assert( sSectorZ == 0 );
|
|
|
|
|
|
// clear the lists
|
|
InitializeMovingLists();
|
|
|
|
|
|
// note that Skyrider can't be moved using the move box, and won't appear because the helicoprer is not in the char list
|
|
|
|
for( iCounter = 0; iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; iCounter++ )
|
|
{
|
|
if( gCharactersList[ iCounter ].fValid )
|
|
{
|
|
pSoldier = MercPtrs[ gCharactersList[ iCounter ].usSolID ];
|
|
|
|
if( ( pSoldier->bActive ) &&
|
|
( pSoldier->bAssignment != IN_TRANSIT ) && ( pSoldier->bAssignment != ASSIGNMENT_POW ) && !SPY_LOCATION( pSoldier->bAssignment ) &&
|
|
( pSoldier->sSectorX == sSectorX ) && ( pSoldier->sSectorY == sSectorY ) && ( pSoldier->bSectorZ == sSectorZ ) )
|
|
{
|
|
if ( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE )
|
|
{
|
|
// vehicle
|
|
// if it can move (can't be empty)
|
|
if ( GetNumberInVehicle( pSoldier->bVehicleID ) > 0 )
|
|
{
|
|
// add vehicle
|
|
AddVehicleToMovingLists( pSoldier->bVehicleID );
|
|
}
|
|
}
|
|
else // soldier
|
|
{
|
|
// alive, not aboard Skyrider (airborne or not!)
|
|
if ( ( pSoldier->stats.bLife >= OKLIFE ) &&
|
|
( ( pSoldier->bAssignment != VEHICLE ) || ( pSoldier->iVehicleId != iHelicopterVehicleId ) ) )
|
|
{
|
|
// add soldier
|
|
AddSoldierToMovingLists( pSoldier );
|
|
|
|
// if on a squad,
|
|
if ( pSoldier->bAssignment < ON_DUTY )
|
|
{
|
|
// add squad (duplicates ok, they're ignored inside the function)
|
|
AddSquadToMovingLists( pSoldier->bAssignment );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fShowMapScreenMovementList = TRUE;
|
|
CreateDestroyMovementBox( sSectorX, sSectorY, sSectorZ );
|
|
}
|
|
|
|
|
|
|
|
void CreatePopUpBoxForMovementBox( void )
|
|
{
|
|
SGPPoint MovePosition = {450 + xResOffset, 100 + yResOffset};
|
|
SGPPoint Position;
|
|
SGPRect Dimensions;
|
|
|
|
// create the pop up box and mouse regions for movement list
|
|
|
|
// create basic box
|
|
CreatePopUpBox(&ghMoveBox, AssignmentDimensions, MovePosition, (POPUP_BOX_FLAG_CLIP_TEXT|POPUP_BOX_FLAG_RESIZE ));
|
|
|
|
// which buffer will box render to
|
|
SetBoxBuffer(ghMoveBox, FRAME_BUFFER);
|
|
|
|
// border type?
|
|
SetBorderType(ghMoveBox,guiPOPUPBORDERS);
|
|
|
|
// background texture
|
|
SetBackGroundSurface(ghMoveBox, guiPOPUPTEX);
|
|
|
|
// margin sizes
|
|
SetMargins( ghMoveBox, 6, 6, 4, 4 );
|
|
|
|
// space between lines
|
|
SetLineSpace(ghMoveBox, 2);
|
|
|
|
// set current box to this one
|
|
SetCurrentBox( ghMoveBox );
|
|
|
|
// add strings
|
|
AddStringsToMoveBox( );
|
|
|
|
|
|
// set font type
|
|
SetBoxFont(ghMoveBox, MAP_SCREEN_FONT);
|
|
|
|
// set highlight color
|
|
SetBoxHighLight(ghMoveBox, FONT_WHITE);
|
|
|
|
// unhighlighted color
|
|
SetBoxForeground(ghMoveBox, FONT_LTGREEN);
|
|
|
|
// make the header line WHITE
|
|
SetBoxLineForeground( ghMoveBox, 0, FONT_WHITE );
|
|
|
|
// make the done and cancel lines YELLOW
|
|
SetBoxLineForeground( ghMoveBox, GetNumberOfLinesOfTextInBox( ghMoveBox ) - 1, FONT_YELLOW );
|
|
|
|
if ( IsAnythingSelectedForMoving() )
|
|
{
|
|
SetBoxLineForeground( ghMoveBox, GetNumberOfLinesOfTextInBox( ghMoveBox ) - 2, FONT_YELLOW );
|
|
}
|
|
|
|
// background color
|
|
SetBoxBackground(ghMoveBox, FONT_BLACK);
|
|
|
|
// shaded color..for darkened text
|
|
SetBoxShade( ghMoveBox, FONT_BLACK );
|
|
|
|
|
|
// resize box to text
|
|
ResizeBoxToText( ghMoveBox );
|
|
|
|
GetBoxPosition( ghMoveBox, &Position);
|
|
GetBoxSize( ghMoveBox, &Dimensions );
|
|
|
|
// adjust position to try to keep it in the map area as best as possible
|
|
if ( Position.iX + Dimensions.iRight >= ( MAP_VIEW_START_X + MAP_VIEW_WIDTH ) )
|
|
{
|
|
Position.iX = max( MAP_VIEW_START_X, ( MAP_VIEW_START_X + MAP_VIEW_WIDTH ) - Dimensions.iRight );
|
|
SetBoxPosition( ghMoveBox, Position );
|
|
}
|
|
|
|
if ( Position.iY + Dimensions.iBottom >= ( MAP_VIEW_START_Y + MAP_VIEW_HEIGHT ) )
|
|
{
|
|
Position.iY = max( MAP_VIEW_START_Y, ( MAP_VIEW_START_Y + MAP_VIEW_HEIGHT ) - Dimensions.iBottom );
|
|
SetBoxPosition( ghMoveBox, Position );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void AddStringsToMoveBox( void )
|
|
{
|
|
INT32 iCount = 0, iCountB = 0;
|
|
CHAR16 sString[ 128 ], sStringB[ 128 ];
|
|
UINT32 hStringHandle;
|
|
BOOLEAN fFirstOne = TRUE;
|
|
|
|
|
|
// set the current box
|
|
SetCurrentBox( ghMoveBox );
|
|
|
|
// clear all the strings out of the box
|
|
RemoveAllCurrentBoxStrings();
|
|
|
|
|
|
// add title
|
|
GetShortSectorString( sSelMapX, sSelMapY, sStringB );
|
|
swprintf( sString, L"%s %s", pMovementMenuStrings[ 0 ], sStringB );
|
|
AddMonoString(&hStringHandle, sString );
|
|
|
|
|
|
// blank line
|
|
AddMonoString(&hStringHandle, L"" );
|
|
|
|
|
|
// add squads
|
|
for( iCount = 0; iCount < giNumberOfSquadsInSectorMoving; iCount++ )
|
|
{
|
|
// add this squad, now add all the grunts in it
|
|
if( fSquadIsMoving[ iCount ] )
|
|
{
|
|
if ( gGameExternalOptions.fUseXMLSquadNames )
|
|
swprintf( sString, L"*%s*", SquadNames[ iSquadMovingList[ iCount ] ].squadname );
|
|
else
|
|
swprintf( sString, L"*%s*", pSquadMenuStrings[iSquadMovingList[ iCount ] ] );
|
|
}
|
|
else
|
|
{
|
|
if ( gGameExternalOptions.fUseXMLSquadNames )
|
|
swprintf( sString, L"%s", SquadNames[ iSquadMovingList[ iCount ] ].squadname );
|
|
else
|
|
swprintf( sString, L"%s", pSquadMenuStrings[iSquadMovingList[ iCount ] ] );
|
|
}
|
|
AddMonoString(&hStringHandle, sString );
|
|
|
|
// now add all the grunts in it
|
|
for( iCountB = 0; iCountB < giNumberOfSoldiersInSectorMoving; iCountB++ )
|
|
{
|
|
if( pSoldierMovingList[ iCountB ]->bAssignment == iSquadMovingList[ iCount ] )
|
|
{
|
|
// add mercs in squads
|
|
if( IsSoldierSelectedForMovement( pSoldierMovingList[ iCountB ] ) == TRUE )
|
|
{
|
|
swprintf( sString, L" *%s*", pSoldierMovingList[ iCountB ]->name );
|
|
}
|
|
else
|
|
{
|
|
swprintf( sString, L" %s", pSoldierMovingList[ iCountB ]->name );
|
|
}
|
|
AddMonoString(&hStringHandle, sString );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// add vehicles
|
|
for( iCount = 0; iCount < giNumberOfVehiclesInSectorMoving; iCount++ )
|
|
{
|
|
// add this vehicle
|
|
if( fVehicleIsMoving[ iCount ] )
|
|
{
|
|
// swprintf( sString, L"*%s*", pVehicleStrings[ pVehicleList[ iVehicleMovingList[ iCount ] ].ubVehicleType ] );
|
|
swprintf( sString, L"*%s*", gNewVehicle[ pVehicleList[ iVehicleMovingList[ iCount ] ].ubVehicleType ].NewVehicleStrings );
|
|
}
|
|
else
|
|
{
|
|
// swprintf( sString, L"%s", pVehicleStrings[ pVehicleList[ iVehicleMovingList[ iCount ] ].ubVehicleType ] );
|
|
swprintf( sString, L"%s", gNewVehicle[ pVehicleList[ iVehicleMovingList[ iCount ] ].ubVehicleType ].NewVehicleStrings);
|
|
}
|
|
AddMonoString(&hStringHandle, sString );
|
|
|
|
// now add all the grunts in it
|
|
for( iCountB = 0; iCountB < giNumberOfSoldiersInSectorMoving; iCountB++ )
|
|
{
|
|
if( ( pSoldierMovingList[ iCountB ]->bAssignment == VEHICLE ) &&( pSoldierMovingList[ iCountB ]->iVehicleId == iVehicleMovingList[ iCount ] ) )
|
|
{
|
|
// add mercs in vehicles
|
|
if( IsSoldierSelectedForMovement( pSoldierMovingList[ iCountB ] ) == TRUE )
|
|
{
|
|
swprintf( sString, L" *%s*", pSoldierMovingList[ iCountB ]->name );
|
|
}
|
|
else
|
|
{
|
|
swprintf( sString, L" %s", pSoldierMovingList[ iCountB ]->name );
|
|
}
|
|
AddMonoString(&hStringHandle, sString );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
fFirstOne = TRUE;
|
|
|
|
// add "other" soldiers heading, once, if there are any
|
|
for( iCount = 0; iCount < giNumberOfSoldiersInSectorMoving; iCount++ )
|
|
{
|
|
// not on duty, not in a vehicle
|
|
if( ( pSoldierMovingList[ iCount ]->bAssignment >= ON_DUTY ) && ( pSoldierMovingList[ iCount ]->bAssignment != VEHICLE ) )
|
|
{
|
|
if ( fFirstOne )
|
|
{
|
|
// add OTHER header line
|
|
if( AllOtherSoldiersInListAreSelected( ) )
|
|
{
|
|
swprintf( sString, L"*%s*", pMovementMenuStrings[ 3 ] );
|
|
}
|
|
else
|
|
{
|
|
swprintf( sString, L"%s", pMovementMenuStrings[ 3 ] );
|
|
}
|
|
AddMonoString(&hStringHandle, sString );
|
|
|
|
fFirstOne = FALSE;
|
|
}
|
|
|
|
// add OTHER soldiers (not on duty nor in a vehicle)
|
|
if( IsSoldierSelectedForMovement( pSoldierMovingList[ iCount ] ) == TRUE )
|
|
{
|
|
swprintf( sString, L" *%s ( %s )*", pSoldierMovingList[ iCount ]->name, pAssignmentStrings[ pSoldierMovingList[ iCount ]->bAssignment ] );
|
|
}
|
|
else
|
|
{
|
|
swprintf( sString, L" %s ( %s )", pSoldierMovingList[ iCount ]->name, pAssignmentStrings[ pSoldierMovingList[ iCount ]->bAssignment ] );
|
|
}
|
|
AddMonoString(&hStringHandle, sString );
|
|
}
|
|
}
|
|
|
|
|
|
// blank line
|
|
AddMonoString(&hStringHandle, L"" );
|
|
|
|
|
|
if ( IsAnythingSelectedForMoving() )
|
|
{
|
|
// add PLOT MOVE line
|
|
swprintf( sString, L"%s", pMovementMenuStrings[ 1 ] );
|
|
AddMonoString(&hStringHandle, sString );
|
|
}
|
|
else
|
|
{
|
|
// blank line
|
|
AddMonoString(&hStringHandle, L"" );
|
|
}
|
|
|
|
|
|
// add cancel line
|
|
swprintf( sString, L"%s", pMovementMenuStrings[ 2 ] );
|
|
AddMonoString(&hStringHandle, sString );
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void BuildMouseRegionsForMoveBox( void )
|
|
{
|
|
INT32 iCounter = 0, iTotalNumberOfLines = 0, iCount = 0, iCountB = 0;
|
|
SGPPoint pPosition;
|
|
INT32 iBoxWidth = 0;
|
|
SGPRect Dimensions;
|
|
INT32 iFontHeight = 0;
|
|
INT32 iBoxXPosition = 0;
|
|
INT32 iBoxYPosition = 0;
|
|
BOOLEAN fDefinedOtherRegion = FALSE;
|
|
|
|
|
|
// grab height of font
|
|
iFontHeight = GetLineSpace( ghMoveBox ) + GetFontHeight( GetBoxFont( ghMoveBox ) );
|
|
|
|
// get x.y position of box
|
|
GetBoxPosition( ghMoveBox, &pPosition);
|
|
|
|
// grab box x and y position
|
|
iBoxXPosition = pPosition.iX;
|
|
iBoxYPosition = pPosition.iY + GetTopMarginSize( ghMoveBox ) - 2; // -2 to improve highlighting accuracy between lines
|
|
|
|
|
|
// get dimensions..mostly for width
|
|
GetBoxSize( ghMoveBox, &Dimensions );
|
|
|
|
// get width
|
|
iBoxWidth = Dimensions.iRight;
|
|
|
|
SetCurrentBox( ghMoveBox );
|
|
|
|
|
|
// box heading
|
|
MSYS_DefineRegion( &gMoveMenuRegion[ iCounter ], ( INT16 )( iBoxXPosition ), ( INT16 )( iBoxYPosition + iFontHeight * iCounter ), ( INT16 )( iBoxXPosition + iBoxWidth ), ( INT16 )( iBoxYPosition + iFontHeight * ( iCounter + 1 ) ), MSYS_PRIORITY_HIGHEST,
|
|
MSYS_NO_CURSOR, MSYS_NO_CALLBACK, MSYS_NO_CALLBACK );
|
|
iCounter++;
|
|
|
|
// blank line
|
|
MSYS_DefineRegion( &gMoveMenuRegion[ iCounter ], ( INT16 )( iBoxXPosition ), ( INT16 )( iBoxYPosition + iFontHeight * iCounter ), ( INT16 )( iBoxXPosition + iBoxWidth ), ( INT16 )( iBoxYPosition + iFontHeight * ( iCounter + 1 ) ), MSYS_PRIORITY_HIGHEST,
|
|
MSYS_NO_CURSOR, MSYS_NO_CALLBACK, MSYS_NO_CALLBACK );
|
|
iCounter++;
|
|
|
|
// calc total number of "moving" lines in the box
|
|
iTotalNumberOfLines = giNumberOfSoldiersInSectorMoving + giNumberOfSquadsInSectorMoving + giNumberOfVehiclesInSectorMoving;
|
|
// add the blank lines
|
|
iTotalNumberOfLines += iCounter;
|
|
|
|
|
|
// now add the strings
|
|
while( iCounter < iTotalNumberOfLines )
|
|
{
|
|
// define regions for squad lines
|
|
for( iCount = 0; iCount < giNumberOfSquadsInSectorMoving; iCount++ )
|
|
{
|
|
MSYS_DefineRegion( &gMoveMenuRegion[ iCounter ], ( INT16 )( iBoxXPosition ), ( INT16 )( iBoxYPosition + iFontHeight * iCounter ), ( INT16 )( iBoxXPosition + iBoxWidth ), ( INT16 )( iBoxYPosition + iFontHeight * ( iCounter + 1 ) ), MSYS_PRIORITY_HIGHEST,
|
|
MSYS_NO_CURSOR, MoveMenuMvtCallback, MoveMenuBtnCallback );
|
|
|
|
// set user defines
|
|
MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 0, iCounter );
|
|
MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 1, SQUAD_REGION );
|
|
MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 2, iCount );
|
|
iCounter++;
|
|
|
|
for( iCountB = 0; iCountB < giNumberOfSoldiersInSectorMoving; iCountB++ )
|
|
{
|
|
if( pSoldierMovingList[ iCountB ]->bAssignment == iSquadMovingList[ iCount ] )
|
|
{
|
|
MSYS_DefineRegion( &gMoveMenuRegion[ iCounter ], ( INT16 )( iBoxXPosition ), ( INT16 )( iBoxYPosition + iFontHeight * iCounter ), ( INT16 )( iBoxXPosition + iBoxWidth ), ( INT16 )( iBoxYPosition + iFontHeight * ( iCounter + 1 ) ), MSYS_PRIORITY_HIGHEST,
|
|
MSYS_NO_CURSOR, MoveMenuMvtCallback, MoveMenuBtnCallback );
|
|
|
|
// set user defines
|
|
MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 0, iCounter );
|
|
MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 1, SOLDIER_REGION );
|
|
MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 2, iCountB );
|
|
iCounter++;
|
|
}
|
|
}
|
|
}
|
|
|
|
for( iCount = 0; iCount < giNumberOfVehiclesInSectorMoving; iCount++ )
|
|
{
|
|
// define regions for vehicle lines
|
|
MSYS_DefineRegion( &gMoveMenuRegion[ iCounter ], ( INT16 )( iBoxXPosition ), ( INT16 )( iBoxYPosition + iFontHeight * iCounter ), ( INT16 )( iBoxXPosition + iBoxWidth ), ( INT16 )( iBoxYPosition + iFontHeight * ( iCounter + 1 ) ), MSYS_PRIORITY_HIGHEST,
|
|
MSYS_NO_CURSOR, MoveMenuMvtCallback, MoveMenuBtnCallback );
|
|
|
|
// set user defines
|
|
MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 0, iCounter );
|
|
MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 1, VEHICLE_REGION );
|
|
MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 2, iCount );
|
|
iCounter++;
|
|
|
|
for( iCountB = 0; iCountB < giNumberOfSoldiersInSectorMoving; iCountB++ )
|
|
{
|
|
if( ( pSoldierMovingList[ iCountB ]->bAssignment == VEHICLE ) &&( pSoldierMovingList[ iCountB ]->iVehicleId == iVehicleMovingList[ iCount ] ) )
|
|
{
|
|
MSYS_DefineRegion( &gMoveMenuRegion[ iCounter ], ( INT16 )( iBoxXPosition ), ( INT16 )( iBoxYPosition + iFontHeight * iCounter ), ( INT16 )( iBoxXPosition + iBoxWidth ), ( INT16 )( iBoxYPosition + iFontHeight * ( iCounter + 1 ) ), MSYS_PRIORITY_HIGHEST,
|
|
MSYS_NO_CURSOR, MoveMenuMvtCallback, MoveMenuBtnCallback );
|
|
|
|
// set user defines
|
|
MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 0, iCounter );
|
|
MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 1, SOLDIER_REGION );
|
|
MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 2, iCountB );
|
|
iCounter++;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// define regions for "other" soldiers
|
|
for( iCount = 0; iCount < giNumberOfSoldiersInSectorMoving; iCount++ )
|
|
{
|
|
// this guy is not in a squad or vehicle
|
|
if( ( pSoldierMovingList[ iCount ]->bAssignment >= ON_DUTY )&&( pSoldierMovingList[ iCount ]->bAssignment != VEHICLE ) )
|
|
{
|
|
// this line gets place only once...
|
|
if( !fDefinedOtherRegion )
|
|
{
|
|
MSYS_DefineRegion( &gMoveMenuRegion[ iCounter ], ( INT16 )( iBoxXPosition ), ( INT16 )( iBoxYPosition + iFontHeight * iCounter ), ( INT16 )( iBoxXPosition + iBoxWidth ), ( INT16 )( iBoxYPosition + iFontHeight * ( iCounter + 1 ) ), MSYS_PRIORITY_HIGHEST,
|
|
MSYS_NO_CURSOR, MoveMenuMvtCallback, MoveMenuBtnCallback );
|
|
|
|
// set user defines
|
|
MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 0, iCounter );
|
|
MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 1, OTHER_REGION );
|
|
MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 2, 0 );
|
|
iCounter++;
|
|
|
|
fDefinedOtherRegion = TRUE;
|
|
}
|
|
|
|
MSYS_DefineRegion( &gMoveMenuRegion[ iCounter ], ( INT16 )( iBoxXPosition ), ( INT16 )( iBoxYPosition + iFontHeight * iCounter ), ( INT16 )( iBoxXPosition + iBoxWidth ), ( INT16 )( iBoxYPosition + iFontHeight * ( iCounter + 1 ) ), MSYS_PRIORITY_HIGHEST,
|
|
MSYS_NO_CURSOR, MoveMenuMvtCallback, MoveMenuBtnCallback );
|
|
|
|
// set user defines
|
|
MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 0, iCounter );
|
|
MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 1, SOLDIER_REGION );
|
|
MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 2, iCount );
|
|
iCounter++;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// blank line
|
|
MSYS_DefineRegion( &gMoveMenuRegion[ iCounter ], ( INT16 )( iBoxXPosition ), ( INT16 )( iBoxYPosition + iFontHeight * iCounter ), ( INT16 )( iBoxXPosition + iBoxWidth ), ( INT16 )( iBoxYPosition + iFontHeight * ( iCounter + 1 ) ), MSYS_PRIORITY_HIGHEST,
|
|
MSYS_NO_CURSOR, MSYS_NO_CALLBACK, MSYS_NO_CALLBACK );
|
|
iCounter++;
|
|
|
|
|
|
if ( IsAnythingSelectedForMoving() )
|
|
{
|
|
// DONE line
|
|
MSYS_DefineRegion( &gMoveMenuRegion[ iCounter ], ( INT16 )( iBoxXPosition ), ( INT16 )( iBoxYPosition + iFontHeight * iCounter ), ( INT16 )( iBoxXPosition + iBoxWidth ), ( INT16 )( iBoxYPosition + iFontHeight * ( iCounter + 1 ) ), MSYS_PRIORITY_HIGHEST,
|
|
MSYS_NO_CURSOR, MoveMenuMvtCallback, MoveMenuBtnCallback );
|
|
|
|
// set user defines
|
|
MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 0, iCounter );
|
|
MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 1, DONE_REGION );
|
|
MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 2, 0 );
|
|
iCounter++;
|
|
}
|
|
else
|
|
{
|
|
// blank line
|
|
MSYS_DefineRegion( &gMoveMenuRegion[ iCounter ], ( INT16 )( iBoxXPosition ), ( INT16 )( iBoxYPosition + iFontHeight * iCounter ), ( INT16 )( iBoxXPosition + iBoxWidth ), ( INT16 )( iBoxYPosition + iFontHeight * ( iCounter + 1 ) ), MSYS_PRIORITY_HIGHEST,
|
|
MSYS_NO_CURSOR, MSYS_NO_CALLBACK, MSYS_NO_CALLBACK );
|
|
iCounter++;
|
|
}
|
|
|
|
// CANCEL line
|
|
MSYS_DefineRegion( &gMoveMenuRegion[ iCounter ], ( INT16 )( iBoxXPosition ), ( INT16 )( iBoxYPosition + iFontHeight * iCounter ), ( INT16 )( iBoxXPosition + iBoxWidth ), ( INT16 )( iBoxYPosition + iFontHeight * ( iCounter + 1 ) ), MSYS_PRIORITY_HIGHEST,
|
|
MSYS_NO_CURSOR, MoveMenuMvtCallback, MoveMenuBtnCallback );
|
|
|
|
// set user defines
|
|
MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 0, iCounter );
|
|
MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 1, CANCEL_REGION );
|
|
MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 2, 0 );
|
|
iCounter++;
|
|
}
|
|
|
|
void ClearMouseRegionsForMoveBox( void )
|
|
{
|
|
INT32 iCounter = 0;
|
|
|
|
// run through list of mouse regions
|
|
for( iCounter = 0; iCounter < ( INT32 )GetNumberOfLinesOfTextInBox( ghMoveBox ); iCounter++ )
|
|
{
|
|
// remove this region
|
|
MSYS_RemoveRegion( &gMoveMenuRegion[ iCounter ] );
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
void MoveMenuMvtCallback(MOUSE_REGION * pRegion, INT32 iReason )
|
|
{
|
|
// mvt callback handler for move box line regions
|
|
INT32 iValue = -1;
|
|
|
|
|
|
iValue = MSYS_GetRegionUserData( pRegion, 0 );
|
|
|
|
if (iReason & MSYS_CALLBACK_REASON_GAIN_MOUSE )
|
|
{
|
|
// highlight string
|
|
HighLightBoxLine( ghMoveBox, iValue );
|
|
}
|
|
else if (iReason & MSYS_CALLBACK_REASON_LOST_MOUSE )
|
|
{
|
|
// unhighlight all strings in box
|
|
UnHighLightBox( ghMoveBox );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void MoveMenuBtnCallback(MOUSE_REGION * pRegion, INT32 iReason )
|
|
{
|
|
// btn callback handler for move box line regions
|
|
INT32 iMoveBoxLine = -1, iRegionType = -1, iListIndex = -1, iClickTime = 0;
|
|
SOLDIERTYPE *pSoldier = NULL;
|
|
|
|
|
|
iMoveBoxLine = MSYS_GetRegionUserData( pRegion, 0 );
|
|
iRegionType = MSYS_GetRegionUserData( pRegion, 1 );
|
|
iListIndex = MSYS_GetRegionUserData( pRegion, 2 );
|
|
iClickTime = GetJA2Clock();
|
|
|
|
if( ( iReason & MSYS_CALLBACK_REASON_LBUTTON_UP ) )
|
|
{
|
|
if( iClickTime - giDblClickTimersForMoveBoxMouseRegions[ iMoveBoxLine ] < DBL_CLICK_DELAY_FOR_MOVE_MENU )
|
|
{
|
|
// dbl click, and something is selected?
|
|
if ( IsAnythingSelectedForMoving() )
|
|
{
|
|
// treat like DONE
|
|
HandleMoveoutOfSectorMovementTroops( );
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
giDblClickTimersForMoveBoxMouseRegions[ iMoveBoxLine ] = iClickTime;
|
|
|
|
if( iRegionType == SQUAD_REGION )
|
|
{
|
|
// is the squad moving
|
|
if( fSquadIsMoving[ iListIndex ] == TRUE )
|
|
{
|
|
// squad stays
|
|
DeselectSquadForMovement( iSquadMovingList[ iListIndex ] );
|
|
}
|
|
else
|
|
{
|
|
// squad goes
|
|
SelectSquadForMovement( iSquadMovingList[ iListIndex ] );
|
|
}
|
|
}
|
|
else if( iRegionType == VEHICLE_REGION )
|
|
{
|
|
// is the vehicle moving
|
|
if( fVehicleIsMoving[ iListIndex ] == TRUE )
|
|
{
|
|
// vehicle stays
|
|
DeselectVehicleForMovement( iVehicleMovingList[ iListIndex ] );
|
|
}
|
|
else
|
|
{
|
|
// vehicle goes
|
|
SelectVehicleForMovement( iVehicleMovingList[ iListIndex ], AND_ALL_ON_BOARD );
|
|
}
|
|
}
|
|
else if( iRegionType == OTHER_REGION )
|
|
{
|
|
if( AllOtherSoldiersInListAreSelected( ) == TRUE )
|
|
{
|
|
// deselect all others in the list
|
|
DeselectAllOtherSoldiersInList( );
|
|
}
|
|
else
|
|
{
|
|
// select all others in the list
|
|
SelectAllOtherSoldiersInList( );
|
|
}
|
|
}
|
|
else if( iRegionType == SOLDIER_REGION )
|
|
{
|
|
pSoldier = pSoldierMovingList[ iListIndex ];
|
|
|
|
if ( pSoldier->flags.fBetweenSectors )
|
|
{
|
|
// we don't allow mercs to change squads or get out of vehicles between sectors, easiest way to handle this
|
|
// is to prevent any toggling of individual soldiers on the move at the outset.
|
|
DoScreenIndependantMessageBox( pMapErrorString[ 41 ], MSG_BOX_FLAG_OK, NULL );
|
|
return;
|
|
}
|
|
|
|
// if soldier is currently selected to move
|
|
if( IsSoldierSelectedForMovement( pSoldier ) )
|
|
{
|
|
// change him to NOT move instead
|
|
|
|
if( pSoldier->bAssignment == VEHICLE )
|
|
{
|
|
// if he's the only one left moving in the vehicle, deselect whole vehicle
|
|
if( HowManyMovingSoldiersInVehicle( pSoldier->iVehicleId ) == 1 )
|
|
{
|
|
// whole vehicle stays
|
|
DeselectVehicleForMovement( pSoldier->iVehicleId );
|
|
}
|
|
else
|
|
{
|
|
// soldier is staying behind
|
|
DeselectSoldierForMovement( pSoldier );
|
|
}
|
|
}
|
|
else if( pSoldier->bAssignment < ON_DUTY )
|
|
{
|
|
// if he's the only one left moving in the squad, deselect whole squad
|
|
if( HowManyMovingSoldiersInSquad( pSoldier->bAssignment ) == 1 )
|
|
{
|
|
// whole squad stays
|
|
DeselectSquadForMovement( pSoldier->bAssignment );
|
|
}
|
|
else
|
|
{
|
|
// soldier is staying behind
|
|
DeselectSoldierForMovement( pSoldier );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// soldier is staying behind
|
|
DeselectSoldierForMovement( pSoldier );
|
|
}
|
|
}
|
|
else // currently NOT moving
|
|
{
|
|
// is he able & allowed to move? (Errors with a reason are reported within)
|
|
if ( CanMoveBoxSoldierMoveStrategically( pSoldier, TRUE ) )
|
|
{
|
|
// change him to move instead
|
|
SelectSoldierForMovement( pSoldier );
|
|
|
|
if( pSoldier->bAssignment < ON_DUTY )
|
|
{
|
|
// if everyone in the squad is now selected, select the squad itself
|
|
if( AllSoldiersInSquadSelected( pSoldier->bAssignment ) )
|
|
{
|
|
SelectSquadForMovement( pSoldier->bAssignment );
|
|
}
|
|
}
|
|
/* ARM: it's more flexible without this - player can take the vehicle along or not without having to exit it.
|
|
else if( pSoldier->bAssignment == VEHICLE )
|
|
{
|
|
// his vehicle MUST also go while he's moving, but not necessarily others on board
|
|
SelectVehicleForMovement( pSoldier->iVehicleId, VEHICLE_ONLY );
|
|
}
|
|
*/
|
|
}
|
|
}
|
|
}
|
|
else if( iRegionType == DONE_REGION )
|
|
{
|
|
// is something selected?
|
|
if ( IsAnythingSelectedForMoving() )
|
|
{
|
|
HandleMoveoutOfSectorMovementTroops( );
|
|
return;
|
|
}
|
|
}
|
|
else if( iRegionType == CANCEL_REGION )
|
|
{
|
|
fShowMapScreenMovementList = FALSE;
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
AssertMsg( 0, String( "MoveMenuBtnCallback: Invalid regionType %d, moveBoxLine %d", iRegionType, iMoveBoxLine ) );
|
|
return;
|
|
}
|
|
|
|
fRebuildMoveBox = TRUE;
|
|
fTeamPanelDirty = TRUE;
|
|
fMapPanelDirty = TRUE;
|
|
fCharacterInfoPanelDirty = TRUE;
|
|
MarkAllBoxesAsAltered( );
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN CanMoveBoxSoldierMoveStrategically( SOLDIERTYPE *pSoldier, BOOLEAN fShowErrorMessage )
|
|
{
|
|
INT8 bErrorNumber = -1;
|
|
|
|
// valid soldier?
|
|
Assert( pSoldier );
|
|
Assert( pSoldier->bActive );
|
|
|
|
|
|
if( CanCharacterMoveInStrategic( pSoldier, &bErrorNumber ) )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
else
|
|
{
|
|
// function may fail without returning any specific error # (-1).
|
|
// if it gave us the # of an error msg, and we were told to display it
|
|
if ( ( bErrorNumber != -1 ) && fShowErrorMessage )
|
|
{
|
|
ReportMapScreenMovementError( bErrorNumber );
|
|
}
|
|
|
|
return( FALSE );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void SelectAllOtherSoldiersInList( void )
|
|
{
|
|
INT32 iCounter = 0;
|
|
BOOLEAN fSomeCantMove = FALSE;
|
|
|
|
|
|
for( iCounter = 0; iCounter < giNumberOfSoldiersInSectorMoving; iCounter++ )
|
|
{
|
|
if( ( pSoldierMovingList[ iCounter ]->bAssignment >= ON_DUTY ) && ( pSoldierMovingList[ iCounter ]->bAssignment != VEHICLE ) )
|
|
{
|
|
if ( CanMoveBoxSoldierMoveStrategically( pSoldierMovingList[ iCounter ], FALSE ) )
|
|
{
|
|
fSoldierIsMoving[ iCounter ] = TRUE;
|
|
}
|
|
else
|
|
{
|
|
fSomeCantMove = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( fSomeCantMove )
|
|
{
|
|
// can't - some of the OTHER soldiers can't move
|
|
ReportMapScreenMovementError( 46 );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void DeselectAllOtherSoldiersInList( void )
|
|
{
|
|
INT32 iCounter = 0;
|
|
|
|
for( iCounter = 0; iCounter < giNumberOfSoldiersInSectorMoving; iCounter++ )
|
|
{
|
|
if( ( pSoldierMovingList[ iCounter ]->bAssignment >= ON_DUTY ) && ( pSoldierMovingList[ iCounter ]->bAssignment != VEHICLE ) )
|
|
{
|
|
fSoldierIsMoving[ iCounter ] = FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void HandleMoveoutOfSectorMovementTroops( void )
|
|
{
|
|
INT32 iCounter = 0;
|
|
SOLDIERTYPE *pSoldier = 0;
|
|
INT32 iSquadNumber = -1;
|
|
BOOLEAN fCheckForCompatibleSquad = FALSE;
|
|
|
|
|
|
// cancel move box
|
|
fShowMapScreenMovementList = FALSE;
|
|
|
|
|
|
for( iCounter = 0; iCounter < giNumberOfSoldiersInSectorMoving; iCounter++ )
|
|
{
|
|
pSoldier = pSoldierMovingList[ iCounter ];
|
|
|
|
fCheckForCompatibleSquad = FALSE;
|
|
|
|
// if he is on a valid squad
|
|
if( pSoldier->bAssignment < ON_DUTY )
|
|
{
|
|
// if he and his squad are parting ways (soldier is staying behind, but squad is leaving, or vice versa)
|
|
if( fSoldierIsMoving[ iCounter ] != IsSquadSelectedForMovement( pSoldier->bAssignment ) )
|
|
{
|
|
// split the guy from his squad to any other compatible squad
|
|
fCheckForCompatibleSquad = TRUE;
|
|
}
|
|
}
|
|
// if in a vehicle
|
|
else if( pSoldier->bAssignment == VEHICLE )
|
|
{
|
|
// if he and his vehicle are parting ways (soldier is staying behind, but vehicle is leaving, or vice versa)
|
|
if( fSoldierIsMoving[ iCounter ] != IsVehicleSelectedForMovement( pSoldier->iVehicleId ) )
|
|
{
|
|
// split the guy from his vehicle to any other compatible squad
|
|
fCheckForCompatibleSquad = TRUE;
|
|
}
|
|
}
|
|
else // on his own - not on a squad or in a vehicle
|
|
{
|
|
// if he's going anywhere
|
|
if( fSoldierIsMoving[ iCounter ] )
|
|
{
|
|
// find out if anyone is going with this guy...see if he can tag along
|
|
fCheckForCompatibleSquad = TRUE;
|
|
}
|
|
}
|
|
|
|
|
|
if ( fCheckForCompatibleSquad )
|
|
{
|
|
// look for a squad that's doing the same thing as this guy is and has room for him
|
|
iSquadNumber = FindSquadThatSoldierCanJoin( pSoldier );
|
|
if( iSquadNumber != -1 )
|
|
{
|
|
if ( !AddCharacterToSquad( pSoldier, ( INT8 )( iSquadNumber ) ) )
|
|
{
|
|
AssertMsg( 0, String( "HandleMoveoutOfSectorMovementTroops: AddCharacterToSquad %d failed, iCounter %d", iSquadNumber, iCounter ) );
|
|
// toggle whether he's going or not to try and recover somewhat gracefully
|
|
fSoldierIsMoving[ iCounter ] = !fSoldierIsMoving[ iCounter ];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// no existing squad is compatible, will have to start his own new squad
|
|
iSquadNumber = AddCharacterToUniqueSquad( pSoldier );
|
|
if ( iSquadNumber != -1 )
|
|
{
|
|
// It worked. Add his new squad to the "moving squads" list so others can join it, too!
|
|
AddSquadToMovingLists( iSquadNumber );
|
|
|
|
// If this guy is moving
|
|
if( fSoldierIsMoving[ iCounter ] )
|
|
{
|
|
// mark this new squad as moving too, so those moving can join it
|
|
SelectSquadForMovement( iSquadNumber );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// failed - should never happen!
|
|
AssertMsg( 0, String( "HandleMoveoutOfSectorMovementTroops: AddCharacterToUniqueSquad failed, iCounter %d", iCounter ) );
|
|
// toggle whether he's going or not to try and recover somewhat gracefully
|
|
fSoldierIsMoving[ iCounter ] = !fSoldierIsMoving[ iCounter ];
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
// now actually set the list
|
|
HandleSettingTheSelectedListOfMercs( );
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void HandleSettingTheSelectedListOfMercs( void )
|
|
{
|
|
BOOLEAN fFirstOne = TRUE;
|
|
INT32 iCounter = 0;
|
|
SOLDIERTYPE *pSoldier = NULL;
|
|
BOOLEAN fSelected;
|
|
|
|
// reset the selected character
|
|
bSelectedDestChar = -1;
|
|
|
|
// run through the list of grunts
|
|
for( iCounter = 0; iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; iCounter++ )
|
|
{
|
|
// is the current guy a valid character?
|
|
if( gCharactersList[ iCounter ].fValid == TRUE )
|
|
{
|
|
pSoldier = MercPtrs[ gCharactersList[ iCounter ].usSolID ];
|
|
|
|
if ( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE )
|
|
{
|
|
fSelected = IsVehicleSelectedForMovement( pSoldier->bVehicleID );
|
|
}
|
|
else
|
|
{
|
|
fSelected = IsSoldierSelectedForMovement( pSoldier );
|
|
}
|
|
|
|
// is he/she selected for movement?
|
|
if( fSelected )
|
|
{
|
|
// yes, are they the first one to be selected?
|
|
if( fFirstOne == TRUE )
|
|
{
|
|
// yes, then set them as the destination plotting character for movement arrow purposes
|
|
fFirstOne = FALSE;
|
|
|
|
bSelectedDestChar = ( INT8 )iCounter;
|
|
// make DEST column glow
|
|
giDestHighLine = iCounter;
|
|
|
|
ChangeSelectedInfoChar( ( INT8 ) iCounter, TRUE );
|
|
}
|
|
|
|
// add this guy to the selected list of grunts
|
|
SetEntryInSelectedCharacterList( ( INT8 )iCounter );
|
|
}
|
|
}
|
|
}
|
|
|
|
if( bSelectedDestChar != -1 )
|
|
{
|
|
// set cursor
|
|
SetUpCursorForStrategicMap( );
|
|
fTeamPanelDirty = TRUE;
|
|
fMapPanelDirty = TRUE;
|
|
fCharacterInfoPanelDirty = TRUE;
|
|
|
|
DeselectSelectedListMercsWhoCantMoveWithThisGuy( &( Menptr[ gCharactersList[ bSelectedDestChar ].usSolID ] ) );
|
|
|
|
// remember the current paths for all selected characters so we can restore them if need be
|
|
RememberPreviousPathForAllSelectedChars();
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
INT32 GetSquadListIndexForSquadNumber( INT32 iSquadNumber )
|
|
{
|
|
INT32 iCounter = 0;
|
|
|
|
for( iCounter = 0; iCounter < giNumberOfSquadsInSectorMoving; iCounter++ )
|
|
{
|
|
if( iSquadMovingList[ iCounter ] == iSquadNumber )
|
|
{
|
|
return( iCounter );
|
|
}
|
|
}
|
|
|
|
return( -1 );
|
|
}
|
|
*/
|
|
|
|
|
|
BOOLEAN AllOtherSoldiersInListAreSelected( void )
|
|
{
|
|
INT32 iCounter = 0, iCount = 0;
|
|
|
|
for( iCounter = 0; iCounter < giNumberOfSoldiersInSectorMoving; iCounter++ )
|
|
{
|
|
if( ( pSoldierMovingList[ iCounter ]->bAssignment >= ON_DUTY ) && ( pSoldierMovingList[ iCounter ]->bAssignment >= VEHICLE ) )
|
|
{
|
|
if( fSoldierIsMoving[ iCounter ] == FALSE )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
iCount++;
|
|
}
|
|
}
|
|
|
|
// some merc on other assignments and no result?
|
|
if( iCount )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
|
|
return( FALSE );
|
|
}
|
|
|
|
|
|
BOOLEAN IsThisSquadInThisSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, INT8 bSquadValue )
|
|
{
|
|
INT16 sX = 0, sY = 0;
|
|
INT8 bZ = 0;
|
|
|
|
// check if the squad is empty
|
|
if( SquadIsEmpty( bSquadValue ) == FALSE )
|
|
{
|
|
// now grab the squad location
|
|
GetLocationOfSquad( &sX, &sY, &bZ, bSquadValue );
|
|
|
|
// check if this non-empty squad is in this sector
|
|
if( ( sX == sSectorX ) && ( sY == sSectorY ) && ( bSectorZ == bZ ) )
|
|
{
|
|
// a squad that's between sectors isn't *in* this sector
|
|
if( !IsThisSquadOnTheMove( bSquadValue ) )
|
|
{
|
|
// yep
|
|
return( TRUE );
|
|
}
|
|
}
|
|
}
|
|
|
|
// nope
|
|
return( FALSE );
|
|
}
|
|
|
|
|
|
INT8 FindSquadThatSoldierCanJoin( SOLDIERTYPE *pSoldier )
|
|
{
|
|
// look for a squad that isn't full that can take this character
|
|
INT8 bCounter = 0;
|
|
|
|
// run through the list of squads
|
|
for( bCounter = 0; bCounter < NUMBER_OF_SQUADS; bCounter++ )
|
|
{
|
|
// is this squad in this sector
|
|
if( IsThisSquadInThisSector( pSoldier->sSectorX, pSoldier->sSectorY, pSoldier->bSectorZ, bCounter ) )
|
|
{
|
|
// does it have room?
|
|
if( IsThisSquadFull( bCounter ) == FALSE )
|
|
{
|
|
// is it doing the same thing as the soldier is (staying or going) ?
|
|
if( IsSquadSelectedForMovement( bCounter ) == IsSoldierSelectedForMovement( pSoldier ) )
|
|
{
|
|
// go ourselves a match, then
|
|
return( bCounter );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return( -1 );
|
|
}
|
|
|
|
void ReBuildMoveBox( void )
|
|
{
|
|
// check to see if we need to rebuild the movement box and mouse regions
|
|
if( fRebuildMoveBox == FALSE )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// reset the fact
|
|
fRebuildMoveBox = FALSE;
|
|
fTeamPanelDirty = TRUE;
|
|
fMapPanelDirty = TRUE;
|
|
fCharacterInfoPanelDirty = TRUE;
|
|
|
|
// stop showing the box
|
|
fShowMapScreenMovementList = FALSE;
|
|
CreateDestroyMovementBox( sSelMapX, sSelMapY, ( INT16 )iCurrentMapSectorZ );
|
|
|
|
// show the box
|
|
fShowMapScreenMovementList = TRUE;
|
|
CreateDestroyMovementBox( sSelMapX, sSelMapY, ( INT16 )iCurrentMapSectorZ );
|
|
ShowBox( ghMoveBox );
|
|
MarkAllBoxesAsAltered( );
|
|
}
|
|
|
|
|
|
void CreateScreenMaskForMoveBox( void )
|
|
{
|
|
if( fScreenMaskForMoveCreated == FALSE )
|
|
{
|
|
// set up the screen mask
|
|
MSYS_DefineRegion( &gMoveBoxScreenMask, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, MSYS_PRIORITY_HIGHEST - 4,
|
|
MSYS_NO_CURSOR, MSYS_NO_CALLBACK, MoveScreenMaskBtnCallback );
|
|
|
|
fScreenMaskForMoveCreated = TRUE;
|
|
}
|
|
}
|
|
|
|
void RemoveScreenMaskForMoveBox( void )
|
|
{
|
|
if( fScreenMaskForMoveCreated == TRUE )
|
|
{
|
|
// remove the screen mask
|
|
MSYS_RemoveRegion( &gMoveBoxScreenMask );
|
|
fScreenMaskForMoveCreated = FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
void MoveScreenMaskBtnCallback(MOUSE_REGION * pRegion, INT32 iReason )
|
|
{
|
|
// btn callback handler for move box screen mask region
|
|
if( ( iReason & MSYS_CALLBACK_REASON_LBUTTON_UP ) )
|
|
{
|
|
fShowMapScreenMovementList = FALSE;
|
|
}
|
|
else if( iReason & MSYS_CALLBACK_REASON_RBUTTON_UP )
|
|
{
|
|
sSelectedMilitiaTown = 0;
|
|
|
|
// are we showing the update box
|
|
if( fShowUpdateBox )
|
|
{
|
|
fShowUpdateBox = FALSE;
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void ResetSoldierUpdateBox( void )
|
|
{
|
|
INT32 iCounter = 0;
|
|
|
|
// delete any loaded faces
|
|
for( iCounter = 0; iCounter < SIZE_OF_UPDATE_BOX; iCounter++ )
|
|
{
|
|
if( pUpdateSoldierBox[ iCounter ] != NULL )
|
|
{
|
|
DeleteVideoObjectFromIndex( giUpdateSoldierFaces[ iCounter ] );
|
|
}
|
|
}
|
|
|
|
if( giMercPanelImage != 0 )
|
|
{
|
|
DeleteVideoObjectFromIndex( giMercPanelImage );
|
|
}
|
|
|
|
// reset the soldier ptrs in the update box
|
|
for( iCounter = 0; iCounter < SIZE_OF_UPDATE_BOX; iCounter++ )
|
|
{
|
|
pUpdateSoldierBox[ iCounter ] = NULL;
|
|
}
|
|
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
INT32 GetNumberOfMercsInUpdateList( void )
|
|
{
|
|
INT32 iCounter = 0, iCount = 0;
|
|
|
|
// run through the non-empty slots
|
|
for( iCounter = 0; iCounter < SIZE_OF_UPDATE_BOX; iCounter++ )
|
|
{
|
|
// valid guy here
|
|
if( pUpdateSoldierBox[ iCounter ] != NULL )
|
|
{
|
|
iCount++;
|
|
}
|
|
}
|
|
|
|
return( iCount );
|
|
}
|
|
|
|
BOOLEAN IsThePopUpBoxEmpty( void )
|
|
{
|
|
INT32 iCounter = 0;
|
|
BOOLEAN fEmpty = TRUE;
|
|
|
|
// run through the non-empty slots
|
|
for( iCounter = 0; iCounter < SIZE_OF_UPDATE_BOX; iCounter++ )
|
|
{
|
|
// valid guy here
|
|
if( pUpdateSoldierBox[ iCounter ] != NULL )
|
|
{
|
|
fEmpty = FALSE;
|
|
}
|
|
}
|
|
|
|
return( fEmpty );
|
|
}
|
|
|
|
|
|
void AddSoldierToWaitingListQueue( SOLDIERTYPE *pSoldier )
|
|
{
|
|
INT32 iSoldierId = 0;
|
|
|
|
|
|
// get soldier profile
|
|
iSoldierId = pSoldier->ubID;
|
|
|
|
SpecialCharacterDialogueEvent( DIALOGUE_ADD_EVENT_FOR_SOLDIER_UPDATE_BOX, UPDATE_BOX_REASON_ADDSOLDIER, iSoldierId, 0, 0, 0 );
|
|
return;
|
|
}
|
|
|
|
|
|
void AddReasonToWaitingListQueue( INT32 iReason )
|
|
{
|
|
SpecialCharacterDialogueEvent( DIALOGUE_ADD_EVENT_FOR_SOLDIER_UPDATE_BOX, UPDATE_BOX_REASON_SET_REASON, iReason, 0, 0, 0 );
|
|
return;
|
|
}
|
|
|
|
|
|
void AddDisplayBoxToWaitingQueue( void )
|
|
{
|
|
SpecialCharacterDialogueEvent( DIALOGUE_ADD_EVENT_FOR_SOLDIER_UPDATE_BOX, UPDATE_BOX_REASON_SHOW_BOX, 0, 0, 0, 0 );
|
|
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void ShowUpdateBox( void )
|
|
{
|
|
// we want to show the box
|
|
fShowUpdateBox = TRUE;
|
|
}
|
|
|
|
void AddSoldierToUpdateBox( SOLDIERTYPE *pSoldier )
|
|
{
|
|
INT32 iCounter = 0;
|
|
VOBJECT_DESC VObjectDesc;
|
|
|
|
|
|
|
|
// going to load face
|
|
VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE;
|
|
|
|
if( pSoldier->stats.bLife == 0 )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if( pSoldier->bActive == FALSE )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// if update
|
|
if( pUpdateSoldierBox[ iCounter ] == NULL )
|
|
{
|
|
sprintf( VObjectDesc.ImageFile, "Interface\\panels.sti" );
|
|
if( !AddVideoObject( &VObjectDesc, (UINT32 *)&giMercPanelImage ) )
|
|
{
|
|
AssertMsg( 0, "Failed to load Interface\\panels.sti" );
|
|
}
|
|
}
|
|
|
|
// run thought list of update soldiers
|
|
for( iCounter = 0; iCounter < SIZE_OF_UPDATE_BOX; iCounter++ )
|
|
{
|
|
// find a free slot
|
|
if( pUpdateSoldierBox[ iCounter ] == NULL )
|
|
{
|
|
// add to box
|
|
pUpdateSoldierBox[ iCounter ] = pSoldier;
|
|
|
|
|
|
|
|
if ( ( gMercProfiles[ pSoldier->ubProfile ].ubFaceIndex < 100 ) && gMercProfiles[pSoldier->ubProfile].Type == PROFILETYPE_IMP )
|
|
{
|
|
sprintf( VObjectDesc.ImageFile, "IMPFaces\\65Face\\%02d.sti", gMercProfiles[ pSoldier->ubProfile ].ubFaceIndex );
|
|
}
|
|
else if ( ( gMercProfiles[ pSoldier->ubProfile ].ubFaceIndex > 99 ) && gMercProfiles[pSoldier->ubProfile].Type == PROFILETYPE_IMP )
|
|
{
|
|
sprintf( VObjectDesc.ImageFile, "IMPFaces\\65Face\\%03d.sti", gMercProfiles[ pSoldier->ubProfile ].ubFaceIndex );
|
|
}
|
|
else if( gMercProfiles[ pSoldier->ubProfile ].ubFaceIndex < 100 )
|
|
{
|
|
sprintf( VObjectDesc.ImageFile, "Faces\\65Face\\%02d.sti", gMercProfiles[ pSoldier->ubProfile ].ubFaceIndex );
|
|
}
|
|
else if( gMercProfiles[ pSoldier->ubProfile ].ubFaceIndex > 99 )
|
|
{
|
|
sprintf( VObjectDesc.ImageFile, "Faces\\65Face\\%03d.sti", gMercProfiles[ pSoldier->ubProfile ].ubFaceIndex );
|
|
}
|
|
|
|
|
|
/*
|
|
if( gMercProfiles[ pSoldier->ubProfile ].ubFaceIndex < 100 )
|
|
{
|
|
// grab filename of face
|
|
sprintf( VObjectDesc.ImageFile, "Faces\\65Face\\%02d.sti", gMercProfiles[ pSoldier->ubProfile ].ubFaceIndex );
|
|
}
|
|
else
|
|
{
|
|
// grab filename of face
|
|
sprintf( VObjectDesc.ImageFile, "Faces\\65Face\\%03d.sti", gMercProfiles[ pSoldier->ubProfile ].ubFaceIndex );
|
|
}
|
|
*/
|
|
// load the face
|
|
AddVideoObject( &VObjectDesc, (UINT32 *)&giUpdateSoldierFaces[ iCounter ] );
|
|
|
|
return;
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
void SetSoldierUpdateBoxReason( INT32 iReason )
|
|
{
|
|
//set the reason for the update
|
|
iReasonForSoldierUpDate = iReason;
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void DisplaySoldierUpdateBox( )
|
|
{
|
|
INT32 iNumberOfMercsOnUpdatePanel = 0;
|
|
INT32 iNumberHigh = 0, iNumberWide = 0;
|
|
INT32 iUpdatePanelWidth = 0, iUpdatePanelHeight = 0;
|
|
INT32 iX = 0, iY = 0;
|
|
INT32 iFaceX = 0, iFaceY = 0;
|
|
BOOLEAN fFourWideMode = FALSE;
|
|
HVOBJECT hBackGroundHandle;
|
|
INT32 iCounter = 0;
|
|
CHAR16 sString[ 32 ];
|
|
INT32 iUpperLimit = 0;
|
|
|
|
|
|
if( fShowUpdateBox == FALSE )
|
|
{
|
|
return;
|
|
}
|
|
|
|
|
|
// get the number of mercs
|
|
iNumberOfMercsOnUpdatePanel = GetNumberOfMercsInUpdateList( );
|
|
|
|
if( iNumberOfMercsOnUpdatePanel == 0 )
|
|
{
|
|
// nobody home
|
|
fShowUpdateBox = FALSE;
|
|
// unpause
|
|
UnPauseDialogueQueue( );
|
|
return;
|
|
}
|
|
|
|
giSleepHighLine = -1;
|
|
giDestHighLine = -1;
|
|
giContractHighLine = -1;
|
|
giAssignHighLine = -1;
|
|
|
|
|
|
//InterruptTime();
|
|
PauseGame( );
|
|
LockPauseState( 4 );
|
|
|
|
PauseDialogueQueue( );
|
|
|
|
// do we have enough for 4 wide, or just 2 wide?
|
|
if( iNumberOfMercsOnUpdatePanel > NUMBER_OF_MERCS_FOR_FOUR_WIDTH_UPDATE_PANEL )
|
|
{
|
|
fFourWideMode = TRUE;
|
|
}
|
|
|
|
// get number of rows
|
|
iNumberHigh = ( fFourWideMode ? iNumberOfMercsOnUpdatePanel / NUMBER_OF_MERC_COLUMNS_FOR_FOUR_WIDE_MODE
|
|
: iNumberOfMercsOnUpdatePanel / NUMBER_OF_MERC_COLUMNS_FOR_TWO_WIDE_MODE);
|
|
|
|
//number of columns
|
|
iNumberWide = ( fFourWideMode ? NUMBER_OF_MERC_COLUMNS_FOR_FOUR_WIDE_MODE
|
|
: NUMBER_OF_MERC_COLUMNS_FOR_TWO_WIDE_MODE );
|
|
|
|
|
|
|
|
// get the height and width of the box .. will need to add in stuff for borders, lower panel...etc
|
|
if( fFourWideMode )
|
|
{
|
|
// do we need an extra row for left overs
|
|
if( iNumberOfMercsOnUpdatePanel % NUMBER_OF_MERC_COLUMNS_FOR_FOUR_WIDE_MODE )
|
|
{
|
|
iNumberHigh++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// do we need an extra row for left overs
|
|
if( iNumberOfMercsOnUpdatePanel % NUMBER_OF_MERC_COLUMNS_FOR_TWO_WIDE_MODE )
|
|
{
|
|
iNumberHigh++;
|
|
}
|
|
}
|
|
|
|
// round off
|
|
if( fFourWideMode )
|
|
{
|
|
if(iNumberOfMercsOnUpdatePanel % NUMBER_OF_MERC_COLUMNS_FOR_FOUR_WIDE_MODE )
|
|
{
|
|
iNumberOfMercsOnUpdatePanel += NUMBER_OF_MERC_COLUMNS_FOR_FOUR_WIDE_MODE - ( iNumberOfMercsOnUpdatePanel % NUMBER_OF_MERC_COLUMNS_FOR_FOUR_WIDE_MODE );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(iNumberOfMercsOnUpdatePanel % NUMBER_OF_MERC_COLUMNS_FOR_TWO_WIDE_MODE )
|
|
{
|
|
iNumberOfMercsOnUpdatePanel += NUMBER_OF_MERC_COLUMNS_FOR_TWO_WIDE_MODE - ( iNumberOfMercsOnUpdatePanel % NUMBER_OF_MERC_COLUMNS_FOR_TWO_WIDE_MODE );
|
|
}
|
|
}
|
|
|
|
iUpdatePanelWidth = iNumberWide * TACT_WIDTH_OF_UPDATE_PANEL_BLOCKS;
|
|
|
|
iUpdatePanelHeight = ( iNumberHigh + 1 ) * TACT_HEIGHT_OF_UPDATE_PANEL_BLOCKS;
|
|
|
|
iX = (MAP_BORDER_X + ((SCREEN_WIDTH - MAP_BORDER_X) / 2)) - (iUpdatePanelWidth / 2);
|
|
iY = (MAP_BORDER_Y + ((SCREEN_HEIGHT - 121) / 2)) - (iUpdatePanelHeight / 2);
|
|
|
|
GetVideoObject( &hBackGroundHandle, guiUpdatePanelTactical );
|
|
|
|
//Display the 2 TOP corner pieces
|
|
BltVideoObject( guiSAVEBUFFER, hBackGroundHandle, 0, iX-4, iY - 4 , VO_BLT_SRCTRANSPARENCY,NULL );
|
|
BltVideoObject( guiSAVEBUFFER, hBackGroundHandle, 2, iX+iUpdatePanelWidth, iY - 4 , VO_BLT_SRCTRANSPARENCY,NULL );
|
|
|
|
if( fFourWideMode )
|
|
{
|
|
//Display 2 vertical lines starting at the bottom
|
|
BltVideoObject( guiSAVEBUFFER , hBackGroundHandle, 3, iX - 4, iY + iUpdatePanelHeight - 3 - 70, VO_BLT_SRCTRANSPARENCY,NULL );
|
|
BltVideoObject( guiSAVEBUFFER , hBackGroundHandle, 5, iX + iUpdatePanelWidth, iY + iUpdatePanelHeight - 3 - 70, VO_BLT_SRCTRANSPARENCY,NULL );
|
|
|
|
//Display the 2 bottom corner pieces
|
|
BltVideoObject( guiSAVEBUFFER, hBackGroundHandle, 0, iX-4, iY + iUpdatePanelHeight - 3, VO_BLT_SRCTRANSPARENCY,NULL );
|
|
BltVideoObject( guiSAVEBUFFER, hBackGroundHandle, 2, iX+iUpdatePanelWidth, iY + iUpdatePanelHeight - 3, VO_BLT_SRCTRANSPARENCY,NULL );
|
|
}
|
|
|
|
|
|
SetFontDestBuffer( guiSAVEBUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, FALSE );
|
|
|
|
iUpperLimit = fFourWideMode ? ( iNumberOfMercsOnUpdatePanel + NUMBER_OF_MERC_COLUMNS_FOR_FOUR_WIDE_MODE ) : ( iNumberOfMercsOnUpdatePanel + NUMBER_OF_MERC_COLUMNS_FOR_TWO_WIDE_MODE );
|
|
|
|
//need to put the background down first
|
|
for( iCounter = 0; iCounter < iUpperLimit; iCounter++ )
|
|
{
|
|
// blt the face and name
|
|
|
|
// get the face x and y
|
|
iFaceX = iX + ( iCounter % iNumberWide ) * TACT_UPDATE_MERC_FACE_X_WIDTH;
|
|
iFaceY = iY + ( iCounter / iNumberWide ) * TACT_UPDATE_MERC_FACE_X_HEIGHT;
|
|
|
|
BltVideoObject( guiSAVEBUFFER , hBackGroundHandle, 20, iFaceX, iFaceY , VO_BLT_SRCTRANSPARENCY,NULL );
|
|
}
|
|
|
|
//loop through the mercs to be displayed
|
|
for( iCounter = 0; iCounter < ( iNumberOfMercsOnUpdatePanel <= NUMBER_OF_MERC_COLUMNS_FOR_TWO_WIDE_MODE ? NUMBER_OF_MERC_COLUMNS_FOR_TWO_WIDE_MODE : iNumberOfMercsOnUpdatePanel ); iCounter++ )
|
|
{
|
|
//
|
|
// blt the face and name
|
|
//
|
|
|
|
// get the face x and y
|
|
iFaceX = iX + ( iCounter % iNumberWide ) * TACT_UPDATE_MERC_FACE_X_WIDTH;
|
|
iFaceY = iY + ( iCounter / iNumberWide ) * TACT_UPDATE_MERC_FACE_X_HEIGHT + REASON_FOR_SOLDIER_UPDATE_OFFSET_Y;
|
|
|
|
// now get the face
|
|
if( pUpdateSoldierBox[ iCounter ] )
|
|
{
|
|
iFaceX += TACT_UPDATE_MERC_FACE_X_OFFSET;
|
|
iFaceY += TACT_UPDATE_MERC_FACE_Y_OFFSET;
|
|
|
|
// there is a face
|
|
RenderSoldierSmallFaceForUpdatePanel( iCounter, iFaceX, iFaceY );
|
|
|
|
// display the mercs name
|
|
swprintf( sString, L"%s", pUpdateSoldierBox[ iCounter ]->name );
|
|
DrawTextToScreen( sString, (UINT16)(iFaceX-5), (UINT16)(iFaceY + 31), 57, TINYFONT1, FONT_LTRED, FONT_BLACK, 0, CENTER_JUSTIFIED );
|
|
}
|
|
}
|
|
|
|
// the button container box
|
|
if( fFourWideMode )
|
|
{
|
|
//def: 3/1/99 WAS SUBINDEX 6,
|
|
BltVideoObject( guiSAVEBUFFER , hBackGroundHandle, 19, iX - 4 + TACT_UPDATE_MERC_FACE_X_WIDTH, iY + iNumberHigh * TACT_UPDATE_MERC_FACE_X_HEIGHT + REASON_FOR_SOLDIER_UPDATE_OFFSET_Y+3, VO_BLT_SRCTRANSPARENCY,NULL );
|
|
|
|
// ATE: Display string for time compression
|
|
DisplayWrappedString( ( UINT16 )( iX ), ( UINT16 )( iY + iNumberHigh * TACT_UPDATE_MERC_FACE_X_HEIGHT + 5 + REASON_FOR_SOLDIER_UPDATE_OFFSET_Y + 3), ( UINT16 )( iUpdatePanelWidth ), 0, MAP_SCREEN_FONT, FONT_WHITE, gzLateLocalizedString[49], FONT_BLACK, 0, CENTER_JUSTIFIED );
|
|
}
|
|
else
|
|
{
|
|
//def: 3/1/99 WAS SUBINDEX 6,
|
|
BltVideoObject( guiSAVEBUFFER , hBackGroundHandle, 19, iX - 4 , iY + iNumberHigh * TACT_UPDATE_MERC_FACE_X_HEIGHT + REASON_FOR_SOLDIER_UPDATE_OFFSET_Y+3, VO_BLT_SRCTRANSPARENCY,NULL );
|
|
|
|
// ATE: Display string for time compression
|
|
DisplayWrappedString( ( UINT16 )( iX ), ( UINT16 )( iY + iNumberHigh * TACT_UPDATE_MERC_FACE_X_HEIGHT + 5 + REASON_FOR_SOLDIER_UPDATE_OFFSET_Y+3 ), ( UINT16 )( iUpdatePanelWidth ), 0, MAP_SCREEN_FONT, FONT_WHITE, gzLateLocalizedString[49], FONT_BLACK, 0, CENTER_JUSTIFIED );
|
|
}
|
|
|
|
iCounter = 0;
|
|
|
|
// now wrap the border
|
|
for( iCounter = 0; iCounter < iNumberHigh ; iCounter++ )
|
|
{
|
|
// the sides
|
|
BltVideoObject( guiSAVEBUFFER , hBackGroundHandle, 3, iX - 4, iY + ( iCounter ) * TACT_UPDATE_MERC_FACE_X_HEIGHT, VO_BLT_SRCTRANSPARENCY,NULL );
|
|
BltVideoObject( guiSAVEBUFFER , hBackGroundHandle, 5, iX + iUpdatePanelWidth, iY + ( iCounter ) * TACT_UPDATE_MERC_FACE_X_HEIGHT, VO_BLT_SRCTRANSPARENCY,NULL );
|
|
}
|
|
|
|
//big horizontal line
|
|
for( iCounter = 0; iCounter < iNumberWide; iCounter++ )
|
|
{
|
|
// the top bottom
|
|
BltVideoObject( guiSAVEBUFFER , hBackGroundHandle, 1, iX + TACT_UPDATE_MERC_FACE_X_WIDTH * (iCounter ) , iY - 4 , VO_BLT_SRCTRANSPARENCY,NULL );
|
|
BltVideoObject( guiSAVEBUFFER , hBackGroundHandle, 1, iX + TACT_UPDATE_MERC_FACE_X_WIDTH * (iCounter ) , iY + iUpdatePanelHeight - 3 , VO_BLT_SRCTRANSPARENCY,NULL );
|
|
}
|
|
|
|
|
|
//Display the reason for the update box
|
|
if( fFourWideMode )
|
|
{
|
|
DisplayWrappedString( ( INT16 )( iX ), ( INT16 )( iY + 6 ), (INT16)iUpdatePanelWidth, 0, MAP_SCREEN_FONT, FONT_WHITE, pUpdateMercStrings[ iReasonForSoldierUpDate ], FONT_BLACK, 0, CENTER_JUSTIFIED );
|
|
}
|
|
else
|
|
{
|
|
DisplayWrappedString( ( INT16 )( iX ), ( INT16 )( iY + 3 ), (INT16)iUpdatePanelWidth, 0, MAP_SCREEN_FONT, FONT_WHITE, pUpdateMercStrings[ iReasonForSoldierUpDate ], FONT_BLACK, 0, CENTER_JUSTIFIED );
|
|
}
|
|
|
|
|
|
SetFontDestBuffer( FRAME_BUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, FALSE );
|
|
|
|
// restore extern background rect
|
|
RestoreExternBackgroundRect( ( INT16 )( iX - 5 ), ( INT16 )( iY - 5 ), ( INT16 )( iUpdatePanelWidth + 10 ), ( INT16 )(iUpdatePanelHeight + 6 ) );
|
|
|
|
CreateDestroyUpdatePanelButtons( iX, ( iY + iUpdatePanelHeight - 18 ), fFourWideMode );
|
|
MarkAButtonDirty( guiUpdatePanelButtons[ 0 ] );
|
|
MarkAButtonDirty( guiUpdatePanelButtons[ 1 ] );
|
|
return;
|
|
}
|
|
|
|
|
|
void CreateDestroyUpdatePanelButtons(INT32 iX, INT32 iY, BOOLEAN fFourWideMode )
|
|
{
|
|
static BOOLEAN fCreated = FALSE;
|
|
|
|
if( ( fShowUpdateBox == TRUE ) && ( fCreated == FALSE ) )
|
|
{
|
|
// set to created
|
|
fCreated = TRUE;
|
|
|
|
fShowAssignmentMenu = FALSE;
|
|
fShowContractMenu = FALSE;
|
|
|
|
// guiUpdatePanelButtonsImage[ 0 ]= LoadButtonImage( "INTERFACE\\group_confirm.sti" ,-1,7,-1,8,-1 );
|
|
// guiUpdatePanelButtonsImage[ 1 ] = LoadButtonImage( "INTERFACE\\group_confirm.sti" ,-1,7,-1,8,-1 );
|
|
guiUpdatePanelButtonsImage[ 0 ]= LoadButtonImage( "INTERFACE\\group_confirm_tactical.sti" ,-1,7,-1,8,-1 );
|
|
guiUpdatePanelButtonsImage[ 1 ] = LoadButtonImage( "INTERFACE\\group_confirm_tactical.sti" ,-1,7,-1,8,-1 );
|
|
|
|
if( fFourWideMode )
|
|
{
|
|
guiUpdatePanelButtons[ 0 ] = QuickCreateButton( guiUpdatePanelButtonsImage[ 0 ], ( INT16 )( iX - 4 + TACT_UPDATE_MERC_FACE_X_WIDTH + 4), (INT16)iY,
|
|
BUTTON_TOGGLE, MSYS_PRIORITY_HIGHEST - 1,
|
|
(GUI_CALLBACK)BtnGenericMouseMoveButtonCallback, (GUI_CALLBACK)ContinueUpdateButtonCallback );
|
|
|
|
guiUpdatePanelButtons[ 1 ] = QuickCreateButton( guiUpdatePanelButtonsImage[ 1 ], ( INT16 ) ( iX - 4 + 2 * TACT_UPDATE_MERC_FACE_X_WIDTH + 4 ), (INT16)iY,
|
|
BUTTON_TOGGLE, MSYS_PRIORITY_HIGHEST - 1,
|
|
(GUI_CALLBACK)BtnGenericMouseMoveButtonCallback, (GUI_CALLBACK)StopUpdateButtonCallback);
|
|
}
|
|
else
|
|
{
|
|
guiUpdatePanelButtons[ 0 ] = QuickCreateButton( guiUpdatePanelButtonsImage[ 0 ], ( INT16 )( iX), (INT16)iY,
|
|
BUTTON_TOGGLE, MSYS_PRIORITY_HIGHEST -1,
|
|
(GUI_CALLBACK)BtnGenericMouseMoveButtonCallback, (GUI_CALLBACK)ContinueUpdateButtonCallback);
|
|
|
|
guiUpdatePanelButtons[ 1 ] = QuickCreateButton( guiUpdatePanelButtonsImage[ 1 ], ( INT16 )( iX + TACT_UPDATE_MERC_FACE_X_WIDTH ), (INT16)iY,
|
|
BUTTON_TOGGLE, MSYS_PRIORITY_HIGHEST - 1,
|
|
(GUI_CALLBACK)BtnGenericMouseMoveButtonCallback, (GUI_CALLBACK)StopUpdateButtonCallback);
|
|
|
|
}
|
|
|
|
SpecifyButtonText( guiUpdatePanelButtons[ 0 ], pUpdatePanelButtons[ 0 ] );
|
|
SpecifyButtonFont( guiUpdatePanelButtons[ 0 ], MAP_SCREEN_FONT );
|
|
SpecifyButtonUpTextColors( guiUpdatePanelButtons[ 0 ], FONT_MCOLOR_BLACK, FONT_BLACK );
|
|
SpecifyButtonDownTextColors( guiUpdatePanelButtons[ 0 ], FONT_MCOLOR_BLACK, FONT_BLACK );
|
|
SetButtonFastHelpText( guiUpdatePanelButtons[ 0 ], gzLateLocalizedString[51] );
|
|
|
|
SpecifyButtonText( guiUpdatePanelButtons[ 1 ], pUpdatePanelButtons[ 1 ] );
|
|
SpecifyButtonFont( guiUpdatePanelButtons[ 1 ], MAP_SCREEN_FONT );
|
|
SpecifyButtonUpTextColors( guiUpdatePanelButtons[ 1 ], FONT_MCOLOR_BLACK, FONT_BLACK );
|
|
SpecifyButtonDownTextColors( guiUpdatePanelButtons[ 1 ], FONT_MCOLOR_BLACK, FONT_BLACK );
|
|
SetButtonFastHelpText( guiUpdatePanelButtons[ 1 ], gzLateLocalizedString[52] );
|
|
}
|
|
else if( ( fShowUpdateBox == FALSE ) && ( fCreated == TRUE ) )
|
|
{
|
|
// set to uncreated
|
|
fCreated = FALSE;
|
|
|
|
// get rid of the buttons and images
|
|
RemoveButton( guiUpdatePanelButtons[ 0 ] );
|
|
RemoveButton( guiUpdatePanelButtons[ 1 ] );
|
|
|
|
UnloadButtonImage( guiUpdatePanelButtonsImage[ 0 ]);
|
|
UnloadButtonImage( guiUpdatePanelButtonsImage[ 1 ]);
|
|
|
|
// unpause
|
|
UnPauseDialogueQueue( );
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
void CreateUpdateBox( void )
|
|
{
|
|
SGPPoint MovePosition = {450 + xResOffset, 100 + yResOffset};
|
|
|
|
// create basic box
|
|
CreatePopUpBox(&ghUpdateBox, AssignmentDimensions, MovePosition, (POPUP_BOX_FLAG_CLIP_TEXT|POPUP_BOX_FLAG_RESIZE ));
|
|
|
|
// which buffer will box render to
|
|
SetBoxBuffer(ghUpdateBox, FRAME_BUFFER);
|
|
|
|
// border type?
|
|
SetBorderType(ghUpdateBox,guiPOPUPBORDERS);
|
|
|
|
// background texture
|
|
SetBackGroundSurface(ghUpdateBox, guiPOPUPTEX);
|
|
|
|
// margin sizes
|
|
SetMargins( ghUpdateBox, 6, 6, 4, 4 );
|
|
|
|
// space between lines
|
|
SetLineSpace(ghUpdateBox, 2);
|
|
|
|
// set current box to this one
|
|
SetCurrentBox( ghUpdateBox );
|
|
|
|
// add strings
|
|
CreateUpdateBoxStrings( );
|
|
|
|
// set font type
|
|
SetBoxFont(ghUpdateBox, MAP_SCREEN_FONT);
|
|
|
|
// set highlight color
|
|
SetBoxHighLight(ghUpdateBox, FONT_WHITE);
|
|
|
|
// unhighlighted color
|
|
SetBoxForeground(ghUpdateBox, FONT_LTGREEN);
|
|
|
|
// background color
|
|
SetBoxBackground(ghUpdateBox, FONT_BLACK);
|
|
|
|
// shaded color..for darkened text
|
|
SetBoxShade( ghUpdateBox, FONT_BLACK );
|
|
|
|
// resize box to text
|
|
ResizeBoxToText( ghUpdateBox );
|
|
|
|
// create screen mask
|
|
CreateScreenMaskForMoveBox( );
|
|
|
|
ShowBox( ghUpdateBox );
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void CreateUpdateBoxStrings( void )
|
|
{
|
|
INT32 iCounter = 0;
|
|
CHAR16 sString[ 64 ];
|
|
INT32 hStringHandle;
|
|
|
|
swprintf( sString, L"%s", pUpdateMercStrings[ iReasonForSoldierUpDate ] );
|
|
AddMonoString(&hStringHandle, sString );
|
|
|
|
for( iCounter = 0; iCounter < SIZE_OF_UPDATE_BOX; iCounter++ )
|
|
{
|
|
// find valid soldier, add name
|
|
if( pUpdateSoldierBox[ iCounter ] )
|
|
{
|
|
swprintf( sString, L"%s", pUpdateSoldierBox[ iCounter ]->name );
|
|
AddMonoString(&hStringHandle, sString );
|
|
}
|
|
}
|
|
|
|
// add a few blank lines
|
|
sString[ 0 ] = 0;
|
|
|
|
AddMonoString(&hStringHandle, sString );
|
|
AddMonoString(&hStringHandle, sString );
|
|
AddMonoString(&hStringHandle, sString );
|
|
AddMonoString(&hStringHandle, sString );
|
|
}
|
|
|
|
|
|
|
|
void RemoveUpdateBox( void )
|
|
{
|
|
// remove the box
|
|
RemoveBox( ghUpdateBox );
|
|
ghUpdateBox = -1;
|
|
|
|
iReasonForSoldierUpDate = NO_REASON_FOR_UPDATE;
|
|
|
|
// remove the screen mask
|
|
RemoveScreenMaskForMoveBox( );
|
|
|
|
// reset mercs that are in progress of being updated
|
|
ResetSoldierUpdateBox( );
|
|
}
|
|
|
|
|
|
|
|
void DisplayUpdateBox( void )
|
|
{
|
|
if( fShowUpdateBox )
|
|
{
|
|
// show the box
|
|
ShowBox( ghUpdateBox );
|
|
PauseTime( TRUE );
|
|
}
|
|
return;
|
|
}
|
|
*/
|
|
|
|
|
|
|
|
void CreateDestroyTheUpdateBox( void )
|
|
{
|
|
static BOOLEAN fCreated = FALSE;
|
|
|
|
if( ( fCreated == FALSE ) && ( fShowUpdateBox == TRUE ) )
|
|
{
|
|
|
|
if( GetNumberOfMercsInUpdateList( ) == 0 )
|
|
{
|
|
fShowUpdateBox = FALSE;
|
|
return;
|
|
}
|
|
|
|
fCreated = TRUE;
|
|
|
|
//InterruptTime();
|
|
// create screen mask
|
|
CreateScreenMaskForMoveBox( );
|
|
|
|
// lock it paused
|
|
PauseGame( /*TRUE*/ ); // doesn't take parameters (jonathanl)
|
|
LockPauseState( 5 );
|
|
|
|
// display the box
|
|
DisplaySoldierUpdateBox( );
|
|
|
|
// Do beep
|
|
PlayJA2SampleFromFile( "Sounds\\newbeep.wav", RATE_11025, MIDVOLUME, 1 , MIDDLEPAN );
|
|
}
|
|
else if( ( fCreated == TRUE ) && ( fShowUpdateBox == FALSE ) )
|
|
{
|
|
fCreated = FALSE;
|
|
|
|
UnLockPauseState( );
|
|
UnPauseGame( /*FALSE*/ ); // doesn't take parameters (jonathanl)
|
|
|
|
// dirty screen
|
|
fMapPanelDirty = TRUE;
|
|
fTeamPanelDirty = TRUE;
|
|
fCharacterInfoPanelDirty = TRUE;
|
|
|
|
// remove screen mask
|
|
RemoveScreenMaskForMoveBox( );
|
|
|
|
ResetSoldierUpdateBox( );
|
|
|
|
CreateDestroyUpdatePanelButtons( 0, 0, FALSE );
|
|
}
|
|
}
|
|
|
|
|
|
void UpdateButtonsDuringCharacterDialoguePicture( void )
|
|
{
|
|
// stop showing buttons during certain instances of dialogue
|
|
if ( (guiTacticalInterfaceFlags & INTERFACE_MAPSCREEN ) )
|
|
{
|
|
UnMarkButtonDirty( giCharInfoButton[ 0 ] );
|
|
UnMarkButtonDirty( giCharInfoButton[ 1 ] );
|
|
}
|
|
|
|
}
|
|
|
|
void UpdateButtonsDuringCharacterDialogueSubTitles( void )
|
|
{
|
|
if( (guiTacticalInterfaceFlags & INTERFACE_MAPSCREEN ) && ( gGameSettings.fOptions[ TOPTION_SUBTITLES ] ) )
|
|
{
|
|
UnMarkButtonDirty( giMapContractButton );
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void RenderSoldierSmallFaceForUpdatePanel( INT32 iIndex, INT32 iX, INT32 iY )
|
|
{
|
|
INT32 iStartY = 0;
|
|
SOLDIERTYPE *pSoldier = NULL;
|
|
|
|
// fill the background for the info bars black
|
|
ColorFillVideoSurfaceArea( guiSAVEBUFFER, iX+36, iY+2, iX+44, iY+30, 0 );
|
|
|
|
// put down the background
|
|
BltVideoObjectFromIndex( guiSAVEBUFFER, giMercPanelImage, 0, iX, iY, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
|
|
// grab the face
|
|
BltVideoObjectFromIndex( guiSAVEBUFFER , giUpdateSoldierFaces[ iIndex ], 0, iX+2, iY+2, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
|
|
//HEALTH BAR
|
|
pSoldier = pUpdateSoldierBox[ iIndex ];
|
|
|
|
// is the merc alive?
|
|
if( !pSoldier->stats.bLife )
|
|
return;
|
|
|
|
//yellow one for bleeding
|
|
iStartY = iY + 29 - 27*pSoldier->stats.bLifeMax/100;
|
|
ColorFillVideoSurfaceArea( guiSAVEBUFFER, iX+36, iStartY, iX+37, iY+29, Get16BPPColor( FROMRGB( 107, 107, 57 ) ) );
|
|
ColorFillVideoSurfaceArea( guiSAVEBUFFER, iX+37, iStartY, iX+38, iY+29, Get16BPPColor( FROMRGB( 222, 181, 115 ) ) );
|
|
|
|
//pink one for bandaged.
|
|
iStartY = iY + 29 - 27*(pSoldier->stats.bLifeMax - pSoldier->bBleeding)/100;
|
|
ColorFillVideoSurfaceArea( guiSAVEBUFFER, iX+36, iStartY, iX+37, iY+29, Get16BPPColor( FROMRGB( 156, 57, 57 ) ) );
|
|
ColorFillVideoSurfaceArea( guiSAVEBUFFER, iX+37, iStartY, iX+38, iY+29, Get16BPPColor( FROMRGB( 222, 132, 132 ) ) );
|
|
|
|
//red one for actual health
|
|
iStartY = iY + 29 - 27*pSoldier->stats.bLife/100;
|
|
ColorFillVideoSurfaceArea( guiSAVEBUFFER, iX+36, iStartY, iX+37, iY+29, Get16BPPColor( FROMRGB( 107, 8, 8 ) ) );
|
|
ColorFillVideoSurfaceArea( guiSAVEBUFFER, iX+37, iStartY, iX+38, iY+29, Get16BPPColor( FROMRGB( 206, 0, 0 ) ) );
|
|
|
|
//BREATH BAR
|
|
iStartY = iY + 29 - 27*pSoldier->bBreathMax/100;
|
|
ColorFillVideoSurfaceArea( guiSAVEBUFFER, iX+39, iStartY, iX+40, iY+29, Get16BPPColor( FROMRGB( 8, 8, 132 ) ) );
|
|
ColorFillVideoSurfaceArea( guiSAVEBUFFER, iX+40, iStartY, iX+41, iY+29, Get16BPPColor( FROMRGB( 8, 8, 107 ) ) );
|
|
|
|
//MORALE BAR
|
|
iStartY = iY + 29 - 27*pSoldier->aiData.bMorale/100;
|
|
ColorFillVideoSurfaceArea( guiSAVEBUFFER, iX+42, iStartY, iX+43, iY+29, Get16BPPColor( FROMRGB( 8, 156, 8 ) ) );
|
|
ColorFillVideoSurfaceArea( guiSAVEBUFFER, iX+43, iStartY, iX+44, iY+29, Get16BPPColor( FROMRGB( 8, 107, 8 ) ) );
|
|
}
|
|
|
|
void ContinueUpdateButtonCallback(GUI_BUTTON *btn,INT32 reason)
|
|
{
|
|
if(reason & MSYS_CALLBACK_REASON_LBUTTON_DWN )
|
|
{
|
|
btn->uiFlags|=(BUTTON_CLICKED_ON);
|
|
}
|
|
else if(reason & MSYS_CALLBACK_REASON_LBUTTON_UP )
|
|
{
|
|
if (btn->uiFlags & BUTTON_CLICKED_ON)
|
|
{
|
|
btn->uiFlags&=~(BUTTON_CLICKED_ON);
|
|
|
|
EndUpdateBox( TRUE ); // restart time compression
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void StopUpdateButtonCallback(GUI_BUTTON *btn,INT32 reason)
|
|
{
|
|
if(reason & MSYS_CALLBACK_REASON_LBUTTON_DWN )
|
|
{
|
|
btn->uiFlags|=(BUTTON_CLICKED_ON);
|
|
}
|
|
else if(reason & MSYS_CALLBACK_REASON_LBUTTON_UP )
|
|
{
|
|
if (btn->uiFlags & BUTTON_CLICKED_ON)
|
|
{
|
|
btn->uiFlags&=~(BUTTON_CLICKED_ON);
|
|
|
|
EndUpdateBox( FALSE ); // stop time compression
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
void EndUpdateBox( BOOLEAN fContinueTimeCompression )
|
|
{
|
|
fShowUpdateBox = FALSE;
|
|
|
|
CreateDestroyTheUpdateBox();
|
|
|
|
if ( fContinueTimeCompression )
|
|
{
|
|
StartTimeCompression();
|
|
}
|
|
else
|
|
{
|
|
StopTimeCompression();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void SetUpdateBoxFlag( BOOLEAN fFlag )
|
|
{
|
|
// set the flag
|
|
fShowUpdateBox = fFlag;
|
|
return;
|
|
}
|
|
|
|
|
|
void SetTixaAsFound( void )
|
|
{
|
|
// set the town of Tixa as found by the player
|
|
fFoundTixa = TRUE;
|
|
gfHiddenTown[ TIXA ] = TRUE;
|
|
gfDrawHiddenTown[ TIXA ] = TRUE;
|
|
fMapPanelDirty = TRUE;
|
|
}
|
|
|
|
void SetOrtaAsFound( void )
|
|
{
|
|
// set the town of Orta as found by the player
|
|
fFoundOrta = TRUE;
|
|
gfHiddenTown[ ORTA ] = TRUE;
|
|
gfDrawHiddenTown[ ORTA ] = TRUE;
|
|
fMapPanelDirty = TRUE;
|
|
}
|
|
|
|
void SetSAMSiteAsFound( UINT8 uiSamIndex )
|
|
{
|
|
// set this SAM site as being found by the player
|
|
fSamSiteFound[ uiSamIndex ] = TRUE;
|
|
fMapPanelDirty = TRUE;
|
|
}
|
|
|
|
|
|
// ste up the timers for move menu in mapscreen for double click detection
|
|
void InitTimersForMoveMenuMouseRegions( void )
|
|
{
|
|
INT32 iCounter = 0;
|
|
|
|
for( iCounter = 0; iCounter < MAX_POPUP_BOX_STRING_COUNT; iCounter++ )
|
|
{
|
|
giDblClickTimersForMoveBoxMouseRegions[ iCounter ] = 0;
|
|
}
|
|
}
|
|
|
|
void UpdateHelpTextForMapScreenMercIcons( void )
|
|
{
|
|
if( ( bSelectedInfoChar == -1 ) || ( gCharactersList[ bSelectedInfoChar ].fValid == FALSE ) )
|
|
{
|
|
SetRegionFastHelpText( &(gContractIconRegion), L"" );
|
|
SetRegionFastHelpText( &(gInsuranceIconRegion), L"" );
|
|
SetRegionFastHelpText( &(gDepositIconRegion), L"" );
|
|
}
|
|
else
|
|
{
|
|
// if merc is an AIM merc
|
|
if( Menptr[ gCharactersList[ bSelectedInfoChar ].usSolID ].ubWhatKindOfMercAmI == MERC_TYPE__AIM_MERC )
|
|
{
|
|
SetRegionFastHelpText( &(gContractIconRegion), zMarksMapScreenText[ 22 ] );
|
|
}
|
|
else
|
|
{
|
|
SetRegionFastHelpText( &(gContractIconRegion), L"" );
|
|
}
|
|
|
|
// if merc has life insurance
|
|
if( Menptr[ gCharactersList[ bSelectedInfoChar ].usSolID ].usLifeInsurance > 0 )
|
|
{
|
|
SetRegionFastHelpText( &(gInsuranceIconRegion), zMarksMapScreenText[ 3 ] );
|
|
}
|
|
else
|
|
{
|
|
SetRegionFastHelpText( &(gInsuranceIconRegion), L"" );
|
|
}
|
|
|
|
// if merc has a medical deposit
|
|
if( Menptr[ gCharactersList[ bSelectedInfoChar ].usSolID ].usMedicalDeposit > 0 )
|
|
{
|
|
SetRegionFastHelpText( &(gDepositIconRegion), zMarksMapScreenText[ 12 ] );
|
|
}
|
|
else
|
|
{
|
|
SetRegionFastHelpText( &(gDepositIconRegion), L"" );
|
|
}
|
|
}
|
|
}
|
|
|
|
void CreateDestroyInsuranceMouseRegionForMercs( BOOLEAN fCreate )
|
|
{
|
|
static BOOLEAN fCreated = FALSE;
|
|
|
|
if( ( fCreated == FALSE ) && ( fCreate == TRUE ) )
|
|
{
|
|
MSYS_DefineRegion( &gContractIconRegion, CHAR_ICON_X + xResOffset, CHAR_ICON_CONTRACT_Y + yResOffset, CHAR_ICON_X + xResOffset + CHAR_ICON_WIDTH, CHAR_ICON_CONTRACT_Y + yResOffset + CHAR_ICON_HEIGHT,
|
|
MSYS_PRIORITY_HIGH - 1, MSYS_NO_CURSOR, MSYS_NO_CALLBACK, MSYS_NO_CALLBACK );
|
|
|
|
MSYS_DefineRegion( &gInsuranceIconRegion, CHAR_ICON_X + xResOffset, CHAR_ICON_CONTRACT_Y + CHAR_ICON_SPACING + yResOffset, CHAR_ICON_X + xResOffset + CHAR_ICON_WIDTH, CHAR_ICON_CONTRACT_Y + CHAR_ICON_SPACING + yResOffset + CHAR_ICON_HEIGHT,
|
|
MSYS_PRIORITY_HIGH - 1, MSYS_NO_CURSOR, MSYS_NO_CALLBACK, MSYS_NO_CALLBACK );
|
|
|
|
MSYS_DefineRegion( &gDepositIconRegion, CHAR_ICON_X + xResOffset, CHAR_ICON_CONTRACT_Y + ( 2 * CHAR_ICON_SPACING ) + yResOffset, CHAR_ICON_X + xResOffset + CHAR_ICON_WIDTH, CHAR_ICON_CONTRACT_Y + ( 2 * CHAR_ICON_SPACING ) + yResOffset + CHAR_ICON_HEIGHT,
|
|
MSYS_PRIORITY_HIGH - 1, MSYS_NO_CURSOR, MSYS_NO_CALLBACK, MSYS_NO_CALLBACK );
|
|
|
|
fCreated = TRUE;
|
|
}
|
|
else if( ( fCreated == TRUE ) && ( fCreate == FALSE ) )
|
|
{
|
|
MSYS_RemoveRegion( &gContractIconRegion );
|
|
MSYS_RemoveRegion( &gInsuranceIconRegion );
|
|
MSYS_RemoveRegion( &gDepositIconRegion );
|
|
fCreated = FALSE;
|
|
}
|
|
}
|
|
|
|
BOOLEAN HandleTimeCompressWithTeamJackedInAndGearedToGo( void )
|
|
{
|
|
// check a team is ready to go
|
|
if( !( AnyMercsHired( ) ) )
|
|
{
|
|
// no mercs, leave
|
|
return( FALSE );
|
|
}
|
|
|
|
// make sure the game just started
|
|
if( gTacticalStatus.fDidGameJustStart == FALSE )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
if (!is_networked)
|
|
// select starting sector (A9 - Omerta)
|
|
// HEADROCK HAM 3.5: Externalized.
|
|
ChangeSelectedMapSector( gGameExternalOptions.ubDefaultArrivalSectorX, gGameExternalOptions.ubDefaultArrivalSectorY, startingZ );
|
|
|
|
if (is_networked)
|
|
{
|
|
// load starting sector
|
|
if ( !SetCurrentWorldSector( gsMercArriveSectorX, gsMercArriveSectorY, 0 ) )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
gubPBSectorX = (UINT8)gsMercArriveSectorX;
|
|
gubPBSectorY = (UINT8)gsMercArriveSectorY;
|
|
}
|
|
else
|
|
{
|
|
// load starting sector
|
|
// Externalized
|
|
if ( !SetCurrentWorldSector( gGameExternalOptions.ubDefaultArrivalSectorX, gGameExternalOptions.ubDefaultArrivalSectorY, startingZ ) )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
gubPBSectorX = (UINT8)gGameExternalOptions.ubDefaultArrivalSectorX;
|
|
gubPBSectorY = (UINT8)gGameExternalOptions.ubDefaultArrivalSectorY;
|
|
}
|
|
gubPBSectorZ = 0;
|
|
|
|
//Setup variables in the PBI for this first battle. We need to support the
|
|
//non-persistant PBI in case the user goes to mapscreen.
|
|
// HEADROCK HAM 3.5: Arrival sector externalized. Fix for entering non-hostile sector/
|
|
if ( NumNonPlayerTeamMembersInSector( gubPBSectorX, gubPBSectorY, ENEMY_TEAM ) > 0 )
|
|
{
|
|
gfBlitBattleSectorLocator = TRUE;
|
|
SetEnemyEncounterCode(ENTERING_ENEMY_SECTOR_CODE);
|
|
}
|
|
else
|
|
{
|
|
gfBlitBattleSectorLocator = FALSE;
|
|
SetEnemyEncounterCode(NO_ENCOUNTER_CODE);
|
|
}
|
|
|
|
InitHelicopterEntranceByMercs( );
|
|
|
|
FadeInGameScreen( );
|
|
|
|
SetUpShutDownMapScreenHelpTextScreenMask( );
|
|
#ifdef JA2UB
|
|
//no ja25 UB
|
|
#else
|
|
// Add e-mail message
|
|
AddEmail(ENRICO_CONGRATS,ENRICO_CONGRATS_LENGTH,MAIL_ENRICO, GetWorldTotalMin(), -1, -1, TYPE_EMAIL_EMAIL_EDT);
|
|
#endif
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
void HandleDisplayOfExitToTacticalMessageForFirstEntryToMapScreen( void )
|
|
{
|
|
INT32 iTime = 0, iDifference = 0;
|
|
|
|
if( gTacticalStatus.fDidGameJustStart == FALSE )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if( AnyMercsHired() == FALSE )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if( fResetTimerForFirstEntryIntoMapScreen )
|
|
{
|
|
giExitToTactBaseTime = 0;
|
|
fResetTimerForFirstEntryIntoMapScreen = FALSE;
|
|
}
|
|
|
|
// is this the first time in?
|
|
if( giExitToTactBaseTime == 0 )
|
|
{
|
|
// gte the clock, for initing
|
|
giExitToTactBaseTime = GetJA2Clock();
|
|
}
|
|
|
|
iTime = GetJA2Clock();
|
|
|
|
iDifference = iTime - giExitToTactBaseTime;
|
|
|
|
if( iDifference > TIMER_FOR_SHOW_EXIT_TO_TACTICAL_MESSAGE )
|
|
{
|
|
fShowMapScreenHelpText = FALSE;
|
|
fMapPanelDirty = TRUE;
|
|
fTeamPanelDirty = TRUE;
|
|
fCharacterInfoPanelDirty = TRUE;
|
|
giExitToTactBaseTime = 0;
|
|
}
|
|
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
BOOLEAN NotifyPlayerWhenEnemyTakesControlOfImportantSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, BOOLEAN fContested )
|
|
{
|
|
CHAR16 sString[ 128 ], sStringA[ 64 ], sStringB[ 256 ], sStringC[ 64 ];
|
|
INT32 iValue = 0;
|
|
INT8 bTownId = 0;
|
|
INT16 sSector = 0;
|
|
INT8 bMineIndex;
|
|
|
|
|
|
// are we below ground?
|
|
if( bSectorZ != 0 )
|
|
{
|
|
// yes we are..there is nothing important to player here
|
|
return( FALSE );
|
|
}
|
|
|
|
// get the name of the sector
|
|
GetSectorIDString( sSectorX, sSectorY, bSectorZ, sString, TRUE );
|
|
|
|
bTownId = GetTownIdForSector( sSectorX, sSectorY );
|
|
|
|
// check if SAM site here
|
|
if( IsThisSectorASAMSector( sSectorX, sSectorY, bSectorZ ) )
|
|
{
|
|
swprintf( sStringB, pMapErrorString[ 15 ], sString );
|
|
|
|
// put up the message informing the player of the event
|
|
DoScreenIndependantMessageBox( sStringB, MSG_BOX_FLAG_OK, MapScreenDefaultOkBoxCallback );
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
// check if a mine is here
|
|
if( IsThereAMineInThisSector( sSectorX, sSectorY ) )
|
|
{
|
|
bMineIndex = GetMineIndexForSector( sSectorX, sSectorY );
|
|
|
|
// if it was producing for us
|
|
if ( ( GetMaxDailyRemovalFromMine( bMineIndex ) > 0 ) && SpokenToHeadMiner( bMineIndex ) )
|
|
{
|
|
// get how much we now will get from the mines
|
|
iValue = GetProjectedTotalDailyIncome( );
|
|
|
|
// parse the string
|
|
swprintf( sStringC, L"%d", iValue );
|
|
|
|
// insert
|
|
InsertCommasForDollarFigure( sStringC );
|
|
InsertDollarSignInToString( sStringC );
|
|
|
|
swprintf( sStringB, pMapErrorString[ 16 ], sString, sStringC );
|
|
|
|
// put up the message informing the player of the event
|
|
DoScreenIndependantMessageBox( sStringB, MSG_BOX_FLAG_OK, MapScreenDefaultOkBoxCallback );
|
|
return( TRUE );
|
|
}
|
|
}
|
|
|
|
|
|
if( fContested && bTownId )
|
|
{
|
|
#ifdef JA2UB
|
|
// no UB
|
|
#else
|
|
if( bTownId == SAN_MONA )
|
|
{ //San Mona isn't important.
|
|
return( TRUE );
|
|
}
|
|
#endif
|
|
swprintf( sStringB, pMapErrorString[ 25 ], sString );
|
|
|
|
#ifdef JA2UB
|
|
HandleDisplayingOfPlayerLostDialogue( );
|
|
#endif
|
|
// put up the message informing the player of the event
|
|
DoScreenIndependantMessageBox( sStringB, MSG_BOX_FLAG_OK, MapScreenDefaultOkBoxCallback );
|
|
return( TRUE );
|
|
}
|
|
|
|
// get the strategic sector value
|
|
sSector = sSectorX + MAP_WORLD_X * sSectorY;
|
|
|
|
if( StrategicMap[ sSector ].bNameId == BLANK_SECTOR )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
// get the name of the sector
|
|
GetSectorIDString( sSectorX, sSectorY, bSectorZ, sStringA, TRUE );
|
|
|
|
// now build the string
|
|
swprintf( sString, pMapErrorString[ 17 ], sStringA );
|
|
|
|
// put up the message box
|
|
DoScreenIndependantMessageBox( sString, MSG_BOX_FLAG_OK, NULL );
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
void NotifyPlayerOfInvasionByEnemyForces( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, MSGBOX_CALLBACK ReturnCallback )
|
|
{
|
|
INT16 sSector = 0;
|
|
INT8 bTownId = 0;
|
|
CHAR16 sString[ 128 ], sStringA[ 128 ];
|
|
|
|
|
|
// check if below ground
|
|
if( bSectorZ != 0 )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// grab sector value
|
|
sSector = sSectorX + MAP_WORLD_X * sSectorY;
|
|
|
|
if( StrategicMap[ sSector ].fEnemyControlled == TRUE )
|
|
{
|
|
// enemy controlled any ways, leave
|
|
return;
|
|
}
|
|
|
|
// get the town id
|
|
bTownId = StrategicMap[ sSector ].bNameId;
|
|
|
|
// check if SAM site here
|
|
if( IsThisSectorASAMSector( sSectorX, sSectorY, bSectorZ ) )
|
|
{
|
|
// get sector id value
|
|
GetShortSectorString( sSectorX, sSectorY, sStringA );
|
|
|
|
swprintf( sString, pMapErrorString[ 22 ], sStringA );
|
|
DoScreenIndependantMessageBox( sString, MSG_BOX_FLAG_OK, ReturnCallback );
|
|
}
|
|
else if( bTownId )
|
|
{
|
|
// get the name of the sector
|
|
GetSectorIDString( sSectorX, sSectorY, bSectorZ, sStringA, TRUE );
|
|
|
|
swprintf( sString, pMapErrorString[ 23 ], sStringA );
|
|
DoScreenIndependantMessageBox( sString, MSG_BOX_FLAG_OK, ReturnCallback );
|
|
}
|
|
else
|
|
{
|
|
// get sector id value
|
|
GetShortSectorString( sSectorX, sSectorY, sStringA );
|
|
|
|
swprintf( sString, pMapErrorString[ 24 ], sStringA );
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, sString );
|
|
}
|
|
}
|
|
|
|
|
|
BOOLEAN CanCharacterMoveInStrategic( SOLDIERTYPE *pSoldier, INT8 *pbErrorNumber )
|
|
{
|
|
INT16 sSector = 0;
|
|
BOOLEAN fProblemExists = FALSE;
|
|
|
|
// valid soldier?
|
|
Assert( pSoldier );
|
|
Assert( pSoldier->bActive);
|
|
|
|
// NOTE: Check for the most permanent conditions first, and the most easily remedied ones last!
|
|
// In case several cases apply, only the reason found first will be given, so make it a good one!
|
|
|
|
// still in transit?
|
|
if( IsCharacterInTransit( pSoldier ) == TRUE )
|
|
{
|
|
*pbErrorNumber = 8;
|
|
return( FALSE );
|
|
}
|
|
|
|
// a POW?
|
|
if( pSoldier->bAssignment == ASSIGNMENT_POW )
|
|
{
|
|
*pbErrorNumber = 5;
|
|
return( FALSE );
|
|
}
|
|
|
|
// underground? (can't move strategically, must use tactical traversal )
|
|
if( pSoldier->bSectorZ != 0 )
|
|
{
|
|
*pbErrorNumber = 1;
|
|
return( FALSE );
|
|
}
|
|
|
|
// vehicle checks
|
|
if ( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE )
|
|
{
|
|
// empty (needs a driver!)?
|
|
if ( GetNumberInVehicle( pSoldier->bVehicleID ) == 0 )
|
|
{
|
|
*pbErrorNumber = 32;
|
|
return( FALSE );
|
|
}
|
|
|
|
// too damaged?
|
|
if ( pSoldier->stats.bLife < OKLIFE )
|
|
{
|
|
*pbErrorNumber = 47;
|
|
return( FALSE );
|
|
}
|
|
|
|
// out of fuel?
|
|
if ( !VehicleHasFuel( pSoldier ) )
|
|
{
|
|
*pbErrorNumber = 42;
|
|
return( FALSE );
|
|
}
|
|
}
|
|
else // non-vehicle
|
|
{
|
|
// dead?
|
|
if ( pSoldier->stats.bLife <= 0 )
|
|
{
|
|
swprintf( gsCustomErrorString, pMapErrorString[ 35 ], pSoldier->name );
|
|
*pbErrorNumber = -99; // customized error message!
|
|
return( FALSE );
|
|
}
|
|
|
|
// too injured?
|
|
if ( pSoldier->stats.bLife < OKLIFE )
|
|
{
|
|
swprintf( gsCustomErrorString, pMapErrorString[ 33 ], pSoldier->name );
|
|
*pbErrorNumber = -99; // customized error message!
|
|
return( FALSE );
|
|
}
|
|
}
|
|
|
|
// if merc is in a particular sector, not somewhere in between
|
|
if ( pSoldier->flags.fBetweenSectors == FALSE )
|
|
{
|
|
// and he's NOT flying above it all in a working helicopter
|
|
if( !SoldierAboardAirborneHeli( pSoldier ) )
|
|
{
|
|
// and that sector is loaded...
|
|
if( ( pSoldier->sSectorX == gWorldSectorX ) && ( pSoldier->sSectorY == gWorldSectorY ) &&
|
|
( pSoldier->bSectorZ == gbWorldSectorZ ) )
|
|
{
|
|
// in combat?
|
|
if( gTacticalStatus.uiFlags & INCOMBAT )
|
|
{
|
|
*pbErrorNumber = 11;
|
|
return( FALSE );
|
|
}
|
|
|
|
// hostile sector?
|
|
if ( gTacticalStatus.fEnemyInSector )
|
|
{
|
|
*pbErrorNumber = 2;
|
|
return( FALSE );
|
|
}
|
|
|
|
// air raid in loaded sector where character is?
|
|
if( InAirRaid( ) )
|
|
{
|
|
*pbErrorNumber = 10;
|
|
return( FALSE );
|
|
}
|
|
}
|
|
|
|
// not necessarily loaded - if there are any hostiles there
|
|
if( NumHostilesInSector( pSoldier->sSectorX, pSoldier->sSectorY, pSoldier->bSectorZ ) > 0 )
|
|
{
|
|
*pbErrorNumber = 2;
|
|
return( FALSE );
|
|
}
|
|
}
|
|
}
|
|
|
|
// if in L12 museum, and the museum alarm went off, and Eldin still around?
|
|
if ( ( pSoldier->sSectorX == 12 ) && ( pSoldier->sSectorY == MAP_ROW_L ) && ( pSoldier->bSectorZ == 0 ) &&
|
|
( !pSoldier->flags.fBetweenSectors ) && gMercProfiles[ ELDIN ].bMercStatus != MERC_IS_DEAD )
|
|
{
|
|
//DBrot: More Rooms
|
|
UINT8 /*ubRoom,*/ cnt;
|
|
UINT16 usRoom;
|
|
SOLDIERTYPE * pSoldier2;
|
|
|
|
if ( InARoom( pSoldier->sGridNo, &usRoom ) && usRoom >= 22 && usRoom <= 41 )
|
|
{
|
|
cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
|
|
|
|
for ( pSoldier2 = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++,pSoldier2++)
|
|
{
|
|
if ( pSoldier2->bActive )
|
|
{
|
|
if ( FindObj( pSoldier2, CHALICE ) != ITEM_NOT_FOUND )
|
|
{
|
|
*pbErrorNumber = 34;
|
|
return( FALSE );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// on assignment, other than just in a VEHICLE?
|
|
if( ( pSoldier->bAssignment >= ON_DUTY ) && ( pSoldier->bAssignment != VEHICLE ) )
|
|
{
|
|
*pbErrorNumber = 3;
|
|
return( FALSE );
|
|
}
|
|
|
|
// if he's walking/driving, and so tired that he would just stop the group anyway in the next sector,
|
|
// or already asleep and can't be awakened
|
|
if ( PlayerSoldierTooTiredToTravel( pSoldier ) )
|
|
{
|
|
// too tired
|
|
swprintf( gsCustomErrorString, pMapErrorString[ 43 ], pSoldier->name );
|
|
*pbErrorNumber = -99; // customized error message!
|
|
return( FALSE );
|
|
}
|
|
|
|
// a robot?
|
|
if ( AM_A_ROBOT( pSoldier ) )
|
|
{
|
|
// going alone?
|
|
if ( ( ( pSoldier->bAssignment == VEHICLE ) && ( !IsRobotControllerInVehicle( pSoldier->iVehicleId ) ) ) ||
|
|
( ( pSoldier->bAssignment < ON_DUTY ) && ( !IsRobotControllerInSquad( pSoldier->bAssignment ) ) ) )
|
|
{
|
|
*pbErrorNumber = 49;
|
|
return( FALSE );
|
|
}
|
|
}
|
|
// an Escorted NPC?
|
|
else if( pSoldier->ubWhatKindOfMercAmI == MERC_TYPE__EPC )
|
|
{
|
|
// going alone?
|
|
if ( ( ( pSoldier->bAssignment == VEHICLE ) && ( GetNumberOfNonEPCsInVehicle( pSoldier->iVehicleId ) == 0 ) ) ||
|
|
( ( pSoldier->bAssignment < ON_DUTY ) && ( NumberOfNonEPCsInSquad( pSoldier->bAssignment ) == 0 ) ) )
|
|
{
|
|
// are they male or female
|
|
if( gMercProfiles[ pSoldier->ubProfile ].bSex == MALE )
|
|
{
|
|
swprintf( gsCustomErrorString, L"%s %s", pSoldier->name ,pMapErrorString[ 6 ] );
|
|
}
|
|
else
|
|
{
|
|
swprintf( gsCustomErrorString, L"%s %s", pSoldier->name ,pMapErrorString[ 7 ] );
|
|
}
|
|
|
|
*pbErrorNumber = -99; // customized error message!
|
|
return( FALSE );
|
|
}
|
|
}
|
|
|
|
// assume there's no problem
|
|
fProblemExists = FALSE;
|
|
|
|
// find out if this particular character can't move for some reason
|
|
switch( pSoldier->ubProfile )
|
|
{
|
|
case( MARIA ):
|
|
// Maria can't move if she's in sector C5
|
|
sSector = SECTOR( pSoldier->sSectorX, pSoldier->sSectorY );
|
|
if( sSector == SEC_C5 )
|
|
{
|
|
// can't move at this time
|
|
fProblemExists = TRUE;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if ( fProblemExists )
|
|
{
|
|
// inform user this specific merc cannot be moved out of the sector
|
|
swprintf( gsCustomErrorString, pMapErrorString[ 29 ], pSoldier->name );
|
|
*pbErrorNumber = -99; // customized error message!
|
|
return( FALSE );
|
|
}
|
|
|
|
// passed all checks - this character may move strategically!
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
BOOLEAN CanEntireMovementGroupMercIsInMove( SOLDIERTYPE *pSoldier, INT8 *pbErrorNumber )
|
|
{
|
|
SOLDIERTYPE *pCurrentSoldier = NULL;
|
|
INT32 iCounter = 0;
|
|
UINT8 ubGroup = 0;
|
|
UINT8 ubCurrentGroup = 0;
|
|
|
|
// first check the requested character himself
|
|
if( CanCharacterMoveInStrategic( pSoldier, pbErrorNumber ) == FALSE )
|
|
{
|
|
// failed no point checking anyone else
|
|
return( FALSE );
|
|
}
|
|
|
|
// now check anybody who would be travelling with him
|
|
|
|
// does character have group?
|
|
if( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE )
|
|
{
|
|
// IS a vehicle - use vehicle's group
|
|
ubGroup = pVehicleList[ pSoldier->bVehicleID ].ubMovementGroup;
|
|
}
|
|
else if( pSoldier->bAssignment == VEHICLE )
|
|
{
|
|
// IN a vehicle - use vehicle's group
|
|
ubGroup = pVehicleList[ pSoldier->iVehicleId ].ubMovementGroup;
|
|
}
|
|
else
|
|
{
|
|
ubGroup = pSoldier->ubGroupID;
|
|
}
|
|
|
|
// even if group is 0 (not that that should happen, should it?) still loop through for other mercs selected to move
|
|
|
|
// if anyone in the merc's group or also selected cannot move for whatever reason return false
|
|
for( iCounter = 0; iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; iCounter++ )
|
|
{
|
|
if( gCharactersList[ iCounter ].fValid == TRUE )
|
|
{
|
|
// get soldier
|
|
pCurrentSoldier = &( Menptr[ gCharactersList[ iCounter ].usSolID ] );
|
|
|
|
// skip inactive grunts
|
|
if( pCurrentSoldier->bActive == FALSE )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// skip the same guy we did already
|
|
if ( pCurrentSoldier == pSoldier )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// does character have group?
|
|
if( pCurrentSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE )
|
|
{
|
|
// IS a vehicle
|
|
ubCurrentGroup = pVehicleList[ pCurrentSoldier->bVehicleID ].ubMovementGroup;
|
|
}
|
|
else if( pCurrentSoldier->bAssignment == VEHICLE )
|
|
{
|
|
// IN a vehicle
|
|
ubCurrentGroup = pVehicleList[ pCurrentSoldier->iVehicleId ].ubMovementGroup;
|
|
}
|
|
else
|
|
{
|
|
ubCurrentGroup = pCurrentSoldier->ubGroupID;
|
|
}
|
|
|
|
// if he is in the same movement group (i.e. squad), or he is still selected to go with us (legal?)
|
|
if( ( ubCurrentGroup == ubGroup ) || ( fSelectedListOfMercsForMapScreen[ iCounter ] == TRUE ) )
|
|
{
|
|
// can this character also move strategically?
|
|
if( CanCharacterMoveInStrategic( pCurrentSoldier, pbErrorNumber ) == FALSE )
|
|
{
|
|
// cannot move, fail, and don't bother checking anyone else, either
|
|
return( FALSE );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// everybody can move... Yey! :-)
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
|
|
void ReportMapScreenMovementError( INT8 bErrorNumber )
|
|
{
|
|
CHAR16 sString[ 1024 ];
|
|
|
|
switch( bErrorNumber )
|
|
{
|
|
case -99:
|
|
// - 99 is a special message # indicating a customized message
|
|
DoMapMessageBox( MSG_BOX_BASIC_STYLE, gsCustomErrorString, MAP_SCREEN, MSG_BOX_FLAG_OK, MapScreenDefaultOkBoxCallback );
|
|
break;
|
|
case 8:
|
|
swprintf( sString, pMapErrorString[ 8 ], pCountryNames[COUNTRY_NAME] );
|
|
DoMapMessageBox( MSG_BOX_BASIC_STYLE, sString, MAP_SCREEN, MSG_BOX_FLAG_OK, MapScreenDefaultOkBoxCallback );
|
|
break;
|
|
default:
|
|
DoMapMessageBox( MSG_BOX_BASIC_STYLE, pMapErrorString[ bErrorNumber ], MAP_SCREEN, MSG_BOX_FLAG_OK, MapScreenDefaultOkBoxCallback );
|
|
}
|
|
}
|
|
|
|
|
|
// we are checking to see if we need to in fact rebuild the characterlist for mapscreen
|
|
void HandleRebuildingOfMapScreenCharacterList( void )
|
|
{
|
|
// check if we need to rebuild the list?
|
|
if( fReBuildCharacterList )
|
|
{
|
|
// do the actual rebuilding
|
|
ReBuildCharactersList( );
|
|
|
|
// reset the flag
|
|
fReBuildCharacterList = FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
void RequestToggleTimeCompression( void )
|
|
{
|
|
if( !IsTimeBeingCompressed( ) )
|
|
{
|
|
StartTimeCompression();
|
|
}
|
|
else // currently compressing
|
|
{
|
|
StopTimeCompression();
|
|
}
|
|
}
|
|
|
|
|
|
void RequestIncreaseInTimeCompression( void )
|
|
{
|
|
if ( IsTimeBeingCompressed( ) )
|
|
{
|
|
IncreaseGameTimeCompressionRate();
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
// start compressing
|
|
StartTimeCompression();
|
|
*/
|
|
// ARM Change: start over at 5x compression
|
|
SetGameTimeCompressionLevel( TIME_COMPRESS_5MINS );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void RequestDecreaseInTimeCompression( void )
|
|
{
|
|
if ( IsTimeBeingCompressed( ) )
|
|
{
|
|
DecreaseGameTimeCompressionRate();
|
|
}
|
|
else
|
|
{
|
|
// check that we can
|
|
if ( !AllowedToTimeCompress( ) )
|
|
{
|
|
// not allowed to compress time
|
|
TellPlayerWhyHeCantCompressTime();
|
|
return;
|
|
}
|
|
|
|
// ARM Change: do nothing
|
|
/*
|
|
// if compression mode is set, just restart time so player can see it
|
|
if ( giTimeCompressMode > TIME_COMPRESS_X1 )
|
|
{
|
|
StartTimeCompression();
|
|
}
|
|
*/
|
|
}
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN CanSoldierMoveWithVehicleId( SOLDIERTYPE *pSoldier, INT32 iVehicle1Id )
|
|
{
|
|
INT32 iVehicle2Id = -1;
|
|
VEHICLETYPE *pVehicle1, *pVehicle2;
|
|
|
|
|
|
Assert( iVehicle1Id != -1 );
|
|
|
|
// if soldier is IN a vehicle
|
|
if( pSoldier->bAssignment == VEHICLE )
|
|
{
|
|
iVehicle2Id = pSoldier->iVehicleId;
|
|
}
|
|
else
|
|
// if soldier IS a vehicle
|
|
if( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE )
|
|
{
|
|
iVehicle2Id = pSoldier->bVehicleID;
|
|
}
|
|
|
|
|
|
// if also (in) a vehicle
|
|
if ( iVehicle2Id != -1 )
|
|
{
|
|
// if it's the same vehicle
|
|
if ( iVehicle1Id == iVehicle2Id )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
|
|
// helicopter can't move together with ground vehicles!
|
|
if ( ( iVehicle1Id == iHelicopterVehicleId ) || ( iVehicle2Id == iHelicopterVehicleId ) )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
// CHRISL: Certain vehicles now have different valid sectors so we don't want to allow try to path for two different vehicles
|
|
if ( iVehicle1Id != iVehicle2Id )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
pVehicle1 = &( pVehicleList[ iVehicle1Id ] );
|
|
pVehicle2 = &( pVehicleList[ iVehicle2Id ] );
|
|
|
|
// as long as they're in the same location, amd neither is between sectors, different vehicles is also ok
|
|
if( ( pVehicle1->sSectorX == pVehicle2->sSectorX ) &&
|
|
( pVehicle1->sSectorY == pVehicle2->sSectorY ) &&
|
|
( pVehicle1->sSectorZ == pVehicle2->sSectorZ ) &&
|
|
!pVehicle1->fBetweenSectors &&
|
|
!pVehicle2->fBetweenSectors )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
}
|
|
|
|
|
|
// not in/is a vehicle, or in a different vehicle that isn't in the same location
|
|
return ( FALSE );
|
|
}
|
|
|
|
|
|
BOOLEAN SaveLeaveItemList( HWFILE hFile )
|
|
{
|
|
INT32 iCounter = 0;
|
|
MERC_LEAVE_ITEM *pCurrentItem;
|
|
UINT32 uiCount=0;
|
|
UINT32 uiNumBytesWritten = 0;
|
|
BOOLEAN fNodeExists = FALSE;
|
|
UINT32 uiCnt;
|
|
|
|
for( iCounter = 0; iCounter < NUM_LEAVE_LIST_SLOTS; iCounter++ )
|
|
{
|
|
// go through nodes and save them
|
|
if ( gpLeaveListHead[ iCounter ] != NULL )
|
|
{
|
|
fNodeExists = TRUE;
|
|
|
|
// Save the to specify that a node DOES exist
|
|
FileWrite( hFile, &fNodeExists, sizeof(BOOLEAN), &uiNumBytesWritten );
|
|
if( uiNumBytesWritten != sizeof(BOOLEAN) )
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
uiCount = 1;
|
|
pCurrentItem = gpLeaveListHead[ iCounter ];
|
|
|
|
//loop through all the nodes to see how many there are
|
|
while( pCurrentItem->pNext )
|
|
{
|
|
pCurrentItem = pCurrentItem->pNext;
|
|
uiCount++;
|
|
}
|
|
|
|
// Save the number specifing how many items there are in the list
|
|
FileWrite( hFile, &uiCount, sizeof(UINT32), &uiNumBytesWritten );
|
|
if( uiNumBytesWritten != sizeof(UINT32) )
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
pCurrentItem = gpLeaveListHead[ iCounter ];
|
|
|
|
//loop through all the nodes to see how many there are
|
|
for( uiCnt=0; uiCnt<uiCount; uiCnt++)
|
|
{
|
|
// Save the items
|
|
if ( !pCurrentItem->Save(hFile) )
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
pCurrentItem = pCurrentItem->pNext;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
fNodeExists = FALSE;
|
|
// Save the to specify that a node DOENST exist
|
|
FileWrite( hFile, &fNodeExists, sizeof(BOOLEAN), &uiNumBytesWritten );
|
|
if( uiNumBytesWritten != sizeof(BOOLEAN) )
|
|
{
|
|
return(FALSE);
|
|
}
|
|
}
|
|
}
|
|
|
|
//Save the leave list profile id's
|
|
for( iCounter = 0; iCounter < NUM_LEAVE_LIST_SLOTS; iCounter++ )
|
|
{
|
|
FileWrite( hFile, &guiLeaveListOwnerProfileId[ iCounter ], sizeof(UINT32), &uiNumBytesWritten );
|
|
if( uiNumBytesWritten != sizeof(UINT32) )
|
|
{
|
|
return(FALSE);
|
|
}
|
|
}
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN LoadLeaveItemList( HWFILE hFile )
|
|
{
|
|
INT32 iCounter = 0;
|
|
MERC_LEAVE_ITEM *pCurrentItem;
|
|
MERC_LEAVE_ITEM *pItem;
|
|
UINT32 uiCount=0;
|
|
UINT32 uiNumBytesRead = 0;
|
|
BOOLEAN fNodeExists = FALSE;
|
|
UINT32 uiSubItem;
|
|
|
|
//Shutdown the list
|
|
ShutDownLeaveList( );
|
|
|
|
//init the list
|
|
InitLeaveList( );
|
|
|
|
//loop through all the lists
|
|
for( iCounter = 0; iCounter < NUM_LEAVE_LIST_SLOTS; iCounter++ )
|
|
{
|
|
// load the flag that specifis that a node DOES exist
|
|
FileRead( hFile, &fNodeExists, sizeof(BOOLEAN), &uiNumBytesRead );
|
|
if( uiNumBytesRead != sizeof(BOOLEAN) )
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
// if a root node is supposed to exist
|
|
if( fNodeExists )
|
|
{
|
|
// load the number specifing how many items there are in the list
|
|
FileRead( hFile, &uiCount, sizeof(UINT32), &uiNumBytesRead );
|
|
if( uiNumBytesRead != sizeof(UINT32) )
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
// Sanity check
|
|
if (uiCount > 1000) {
|
|
return(FALSE);
|
|
}
|
|
|
|
// allocate space
|
|
gpLeaveListHead[ iCounter ] = new MERC_LEAVE_ITEM;
|
|
if( gpLeaveListHead[ iCounter ] == NULL )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
pCurrentItem = gpLeaveListHead[ iCounter ];
|
|
|
|
for( uiSubItem=0; uiSubItem< uiCount; uiSubItem++ )
|
|
{
|
|
// allocate space
|
|
pItem = new MERC_LEAVE_ITEM;
|
|
if( pItem == NULL )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
// Load the items
|
|
if ( !pItem->Load(hFile) )
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
pItem->pNext = NULL;
|
|
|
|
//add the node to the list
|
|
if( uiSubItem == 0 )
|
|
{
|
|
gpLeaveListHead[ iCounter ] = pItem;
|
|
pCurrentItem = gpLeaveListHead[ iCounter ];
|
|
}
|
|
else
|
|
{
|
|
pCurrentItem->pNext = pItem;
|
|
pCurrentItem = pCurrentItem->pNext;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//Load the leave list profile id's
|
|
for( iCounter = 0; iCounter < NUM_LEAVE_LIST_SLOTS; iCounter++ )
|
|
{
|
|
FileRead( hFile, &guiLeaveListOwnerProfileId[ iCounter ], sizeof(UINT32), &uiNumBytesRead );
|
|
if( uiNumBytesRead != sizeof(UINT32) )
|
|
{
|
|
return(FALSE);
|
|
}
|
|
}
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
|
|
void TurnOnSectorLocator( UINT8 ubProfileID )
|
|
{
|
|
SOLDIERTYPE *pSoldier;
|
|
|
|
Assert( ubProfileID != NO_PROFILE );
|
|
|
|
pSoldier = FindSoldierByProfileID( ubProfileID, FALSE );
|
|
if( pSoldier )
|
|
{
|
|
gsSectorLocatorX = pSoldier->sSectorX;
|
|
gsSectorLocatorY = pSoldier->sSectorY;
|
|
}
|
|
else
|
|
{
|
|
// if it's Skyrider (when he's not on our team), and his chopper has been setup
|
|
if ( ( ubProfileID == SKYRIDER ) && fSkyRiderSetUp )
|
|
{
|
|
// if helicopter position is being shown, don't do this, too, cause the helicopter icon is on top and it looks
|
|
// like crap. I tried moving the heli icon blit to before, but that screws up it's blitting.
|
|
if ( gusMapDisplayColourMode != MAP_DISPLAY_AIRSPACE && gusMapDisplayColourMode != MAP_DISPLAY_AIRSPACE_COLOURED_SAMS )
|
|
{
|
|
// can't use his profile, he's where his chopper is
|
|
Assert( iHelicopterVehicleId != -1 );
|
|
gsSectorLocatorX = pVehicleList[ iHelicopterVehicleId ].sSectorX;
|
|
gsSectorLocatorY = pVehicleList[ iHelicopterVehicleId ].sSectorY;
|
|
}
|
|
else
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
gsSectorLocatorX = gMercProfiles[ ubProfileID ].sSectorX;
|
|
gsSectorLocatorY = gMercProfiles[ ubProfileID ].sSectorY;
|
|
}
|
|
}
|
|
gubBlitSectorLocatorCode = LOCATOR_COLOR_YELLOW;
|
|
}
|
|
|
|
|
|
void TurnOffSectorLocator()
|
|
{
|
|
gubBlitSectorLocatorCode = LOCATOR_COLOR_NONE;
|
|
fMapPanelDirty = TRUE;
|
|
}
|
|
|
|
|
|
|
|
void HandleBlitOfSectorLocatorIcon( INT16 sSectorX, INT16 sSectorY, INT16 sSectorZ, UINT8 ubLocatorID )
|
|
{
|
|
static UINT8 ubFrame = 0;
|
|
UINT8 ubBaseFrame = 0;
|
|
UINT32 uiTimer = 0;
|
|
HVOBJECT hHandle;
|
|
INT16 sScreenX, sScreenY;
|
|
|
|
|
|
// blits at 0,0 had been observerd...
|
|
Assert( ( sSectorX >= 1 ) && ( sSectorX <= 16 ) );
|
|
Assert( ( sSectorY >= 1 ) && ( sSectorY <= 16 ) );
|
|
Assert( ( sSectorZ >= 0 ) && ( sSectorZ <= 3 ) );
|
|
|
|
if( sSectorZ != iCurrentMapSectorZ )
|
|
{ //if the z level of the map screen renderer is different than the
|
|
//sector z that we wish to locate, then don't render it
|
|
return;
|
|
}
|
|
|
|
// if showing sector inventory, don't do this
|
|
if( fShowMapInventoryPool )
|
|
{
|
|
return;
|
|
}
|
|
|
|
|
|
GetVideoObject( &hHandle, guiSectorLocatorGraphicID );
|
|
|
|
switch( ubLocatorID )
|
|
{
|
|
// grab zoomed out icon
|
|
case LOCATOR_COLOR_RED:
|
|
ubBaseFrame = 0;
|
|
ubFrame = (UINT8)(ubFrame % 13);
|
|
break;
|
|
case LOCATOR_COLOR_YELLOW:
|
|
ubBaseFrame = 13;
|
|
ubFrame = (UINT8)(13 + (ubFrame % 13) );
|
|
break;
|
|
default:
|
|
//not supported
|
|
return;
|
|
}
|
|
|
|
//Convert the sector value into screen values.
|
|
GetScreenXYFromMapXY( sSectorX, sSectorY, &sScreenX, &sScreenY );
|
|
// make sure we are on the border
|
|
if( sScreenX < MAP_GRID_X )
|
|
{
|
|
sScreenX = MAP_GRID_X;
|
|
}
|
|
sScreenY--; //Carterism ritual
|
|
if( sScreenY < MAP_GRID_Y )
|
|
{
|
|
sScreenY = MAP_GRID_Y;
|
|
}
|
|
|
|
uiTimer = GetJA2Clock();
|
|
|
|
// if first time in, reset value
|
|
if( guiSectorLocatorBaseTime == 0 )
|
|
{
|
|
guiSectorLocatorBaseTime = GetJA2Clock( );
|
|
}
|
|
|
|
// check if enough time has passed to update the frame counter
|
|
if( ANIMATED_BATTLEICON_FRAME_TIME < ( uiTimer - guiSectorLocatorBaseTime ) )
|
|
{
|
|
guiSectorLocatorBaseTime = uiTimer;
|
|
ubFrame++;
|
|
|
|
if( ubFrame > ubBaseFrame + MAX_FRAME_COUNT_FOR_ANIMATED_BATTLE_ICON )
|
|
{
|
|
ubFrame = ubBaseFrame;
|
|
}
|
|
}
|
|
|
|
RestoreExternBackgroundRect( (INT16)(sScreenX + 1), (INT16)(sScreenY - 1), MAP_GRID_X , MAP_GRID_Y );
|
|
|
|
// blit object to frame buffer
|
|
BltVideoObject( FRAME_BUFFER, hHandle, ubFrame, sScreenX, sScreenY, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
|
|
// invalidate region on frame buffer
|
|
InvalidateRegion( sScreenX, sScreenY - 1, sScreenX + MAP_GRID_X , sScreenY + MAP_GRID_Y );
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN CheckIfSalaryIncreasedAndSayQuote( SOLDIERTYPE *pSoldier, BOOLEAN fTriggerContractMenu )
|
|
{
|
|
Assert( pSoldier );
|
|
|
|
// OK, check if their price has gone up
|
|
if( pSoldier->flags.fContractPriceHasIncreased )
|
|
{
|
|
if ( fTriggerContractMenu )
|
|
{
|
|
// have him say so first - post the dialogue event with the contract menu event
|
|
SpecialCharacterDialogueEvent( DIALOGUE_SPECIAL_EVENT_ENTER_MAPSCREEN,0,0,0,0,0 );
|
|
HandleImportantMercQuote( pSoldier, QUOTE_MERC_GONE_UP_IN_PRICE );
|
|
TacticalCharacterDialogueWithSpecialEvent( pSoldier, 0, DIALOGUE_SPECIAL_EVENT_SHOW_CONTRACT_MENU, 0,0 );
|
|
}
|
|
else
|
|
{
|
|
// now post the dialogue event and the contratc menu event
|
|
HandleImportantMercQuote( pSoldier, QUOTE_MERC_GONE_UP_IN_PRICE );
|
|
}
|
|
|
|
pSoldier->flags.fContractPriceHasIncreased = FALSE;
|
|
|
|
// said quote / triggered contract menu
|
|
return( TRUE );
|
|
}
|
|
else
|
|
{
|
|
// nope, nothing to do
|
|
return( FALSE );
|
|
}
|
|
}
|