Files
source/Strategic/Map Screen Interface.cpp
T
Overhaul 7a27e7105d New attack busy system
Added missing #includes

Added LUA scripting and console

Changed the way tracers are visualized, so they work more like real tracers instead of a light fountain

Fixed signedness of many grid variables used in GetMouseMapPos calls

Fixed enemy weapon choosing:  Sometimes a mortar is chosen but later rejected, but the grenade class was not reset.  Caused assertion failure

Added checks so enemies don't try to chuck RPG grenades with their hands

Now possible to shoot a someone in the head if he's in water

Fixed InitSightArrays to also clear soldier interrupt duel points.  This was causing an assertion failure elsewhere in the code because the interrupt list still had soldiers on it sometimes when this function was called.

Soldiers are much less willing to forfeit their turn over an attempt to use more APs than they have

Removed early setting of muzzle flash.  This would allow enemies to get an interrupt before you even fired.

Fixed item dropping by AI.  If AI tried to drop something while standing it would cause deadlock

Change to greatly speed up closing the sector inventory window in an unloaded sector

Added conditional compile flag to always give robot weapon ready advantage, even for 360 degree sighting


Check builddefines.h for the conditional flags.  Of greatest interest might be LUA_CONSOLE.  This will cause the game to bring up a command console when run.  However this console is severely lacking in many areas.  If anybody knows of an open-source terminal/console that could be used instead, it would be appreciated.  The existing console does bad things when you try to close it, and since it counts as a separate app, it pauses the game while it has focus.

LUA scripting is very limited, basically just proof of concept.  There is one global variable, the Soldiers array.  An array index gives you the soldier in that slot in the currently loaded sector.  The soldier has a few things that can be accessed:  name (short name); fullname (long name); grid (current grid #, can be changed); walkto(grid) (function to walk to another grid); runto(grid) (function to run to another grid)


git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@924 3b4a5df2-a311-0410-b5c6-a8a6f20db521
2007-06-09 09:01:04 +00:00

6649 lines
171 KiB
C++

// WANNE 2 <changed some lines>
#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"
#endif
// 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
// number of LINKED LISTS for sets of leave items (each slot holds an unlimited # of items)
#define NUM_LEAVE_LIST_SLOTS 20
// WANNE 2 <change 2>
#define SELECTED_CHAR_ARROW_X 1 //8
#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,
};
// WANNE 2
UINT16 usVehicleY = 0;
// waiting list for update box
INT32 iUpdateBoxWaitingList[ MAX_CHARACTER_COUNT ];
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[ MAX_CHARACTER_COUNT ];
BOOLEAN fSoldierIsMoving[ MAX_CHARACTER_COUNT ];
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[ MAX_CHARACTER_COUNT+1];
extern MOUSE_REGION gCharInfoHandRegion;
MOUSE_REGION gMapStatusBarsRegion;
SGPPoint MovePosition={450, 100 };
// which lines are selected? .. for assigning groups of mercs to the same thing
BOOLEAN fSelectedListOfMercsForMapScreen[ MAX_CHARACTER_COUNT ];
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[ MAX_CHARACTER_COUNT ];
// 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 fShowTrainingMenu = FALSE;
BOOLEAN fShowAttributeMenu = FALSE;
BOOLEAN fShowSquadMenu = FALSE;
BOOLEAN fShowContractMenu = FALSE;
BOOLEAN fShowRemoveMenu = FALSE;
BOOLEAN fShowMilitiaControlMenu = FALSE; //lal
//BOOLEAN fShowTalkToAllMenu = FALSE;//lal
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};
SGPPoint RepairPosition={160,150};
SGPRect RepairDimensions={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 OrigTalkToAllPosition = { 160, 150 };
//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 ));
return;
}
void SetEntryInSelectedCharacterList( INT8 bEntry )
{
Assert( ( bEntry >= 0 ) && ( bEntry < MAX_CHARACTER_COUNT ) );
// set this entry to selected
fSelectedListOfMercsForMapScreen[ bEntry ] = TRUE ;
return;
}
void ResetEntryForSelectedList( INT8 bEntry )
{
Assert( ( bEntry >= 0 ) && ( bEntry < MAX_CHARACTER_COUNT ) );
// set this entry to selected
fSelectedListOfMercsForMapScreen[ bEntry ] = FALSE;
return;
}
void ResetSelectedListForMapScreen( void )
{
// set all the entries int he selected list to false
memset( &fSelectedListOfMercsForMapScreen, FALSE, MAX_CHARACTER_COUNT * sizeof( BOOLEAN ) );
// if we still have a valid dude selected
if ( ( bSelectedInfoChar != -1 ) && ( gCharactersList[ bSelectedInfoChar ].fValid == TRUE ) )
{
// then keep him selected
SetEntryInSelectedCharacterList( bSelectedInfoChar );
}
return;
}
BOOLEAN IsEntryInSelectedListSet( INT8 bEntry )
{
Assert( ( bEntry >= 0 ) && ( bEntry < MAX_CHARACTER_COUNT ) );
// is this entry in the selected list set?
return( fSelectedListOfMercsForMapScreen[ bEntry ] );
}
void ToggleEntryInSelectedList( INT8 bEntry )
{
Assert( ( bEntry >= 0 ) && ( bEntry < MAX_CHARACTER_COUNT ) );
// toggle the value in the selected list
fSelectedListOfMercsForMapScreen[ bEntry ] = !( fSelectedListOfMercsForMapScreen[ bEntry ] );
return;
}
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 );
}
return;
}
BOOLEAN MultipleCharacterListEntriesSelected( void )
{
UINT8 ubSelectedCnt = 0;
INT32 iCounter = 0;
// check if more than one person is selected in the selected list
for( iCounter = 0; iCounter < MAX_CHARACTER_COUNT; iCounter++ )
{
if( fSelectedListOfMercsForMapScreen[iCounter] == TRUE )
{
ubSelectedCnt++;
}
}
if( ubSelectedCnt > 1 )
{
return( TRUE );
}
else
{
return( FALSE );
}
}
void ResetAssignmentsForMercsTrainingUnpaidSectorsInSelectedList( INT8 bAssignment )
{
INT32 iCounter = 0;
SOLDIERTYPE *pSoldier = NULL;
for( iCounter = 0; iCounter < MAX_CHARACTER_COUNT; iCounter++ )
{
// valid character?
if( gCharactersList[ iCounter ].fValid == FALSE )
{
// nope
continue;
}
pSoldier = &Menptr[ gCharactersList[ iCounter ].usSolID ];
if( pSoldier->bActive == FALSE )
{
continue;
}
if( pSoldier->bAssignment == TRAIN_TOWN )
{
if ( SectorInfo[ SECTOR( pSoldier->sSectorX, pSoldier->sSectorY ) ].fMilitiaTrainingPaid == FALSE )
{
ResumeOldAssignment( pSoldier );
}
}
}
}
void ResetAssignmentOfMercsThatWereTrainingMilitiaInThisSector( INT16 sSectorX, INT16 sSectorY )
{
INT32 iCounter = 0;
SOLDIERTYPE *pSoldier = NULL;
for( iCounter = 0; iCounter < MAX_CHARACTER_COUNT; iCounter++ )
{
// valid character?
if( gCharactersList[ iCounter ].fValid == FALSE )
{
// nope
continue;
}
pSoldier = &Menptr[ gCharactersList[ iCounter ].usSolID ];
if( pSoldier->bActive == FALSE )
{
continue;
}
if( pSoldier->bAssignment == TRAIN_TOWN )
{
if( ( pSoldier->sSectorX == sSectorX ) && ( pSoldier->sSectorY == sSectorY ) && ( pSoldier->bSectorZ == 0 ) )
{
ResumeOldAssignment( pSoldier );
}
}
}
}
/*
void PlotPathForSelectedCharacterList( INT16 sX, INT16 sY )
{
INT32 iCounter = 0;
// run through list and build paths for each character
for( iCounter = 0; iCounter < MAX_CHARACTER_COUNT; iCounter++ )
{
if( ( fSelectedListOfMercsForMapScreen[ iCounter ] == TRUE )&&( bSelectedDestChar != iCounter ) )
{
// character is valid.. do this for every one not the bSelectedDestChar
PlotPathForCharacter( &Menptr[ gCharactersList[ iCounter ].usSolID ], sX, sY, FALSE );
}
}
}
*/
// check if the members of the selected list move with this guy... are they in the same mvt group?
void DeselectSelectedListMercsWhoCantMoveWithThisGuy( SOLDIERTYPE *pSoldier )
{
INT32 iCounter = 0;
SOLDIERTYPE *pSoldier2 = NULL;
// deselect any other selected mercs that can't travel together with pSoldier
for( iCounter = 0; iCounter < MAX_CHARACTER_COUNT; 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->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->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->fBetweenSectors || pSoldier2->fBetweenSectors ) &&
( pSoldier->ubGroupID != pSoldier2->ubGroupID ) )
{
ResetEntryForSelectedList( ( INT8 )iCounter );
}
}
// different movement groups in same sector is OK, even if they're not travelling together
}
}
}
return;
}
void SelectUnselectedMercsWhoMustMoveWithThisGuy( void )
{
INT32 iCounter = 0;
SOLDIERTYPE *pSoldier = NULL;
for( iCounter = 0; iCounter < MAX_CHARACTER_COUNT; 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 )
{
INT32 iCounter = 0;
SOLDIERTYPE *pSoldier2 = NULL;
for( iCounter = 0; iCounter < MAX_CHARACTER_COUNT; 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->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->uiStatusFlags & SOLDIER_VEHICLE ) &&
( pSoldier2->iVehicleId == pSoldier->bVehicleID ) )
{
return ( TRUE );
}
}
}
}
return ( FALSE );
}
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( fShowSquadMenu == TRUE )
{
ForceUpDateOfBox( ghSquadBox );
}
else if( fShowTrainingMenu == TRUE )
{
ForceUpDateOfBox( ghTrainingBox );
}
}
if( fDisableDueToBattleRoster )
{
return;
}
if( iOldAssignmentLine != giAssignHighLine )
{
// restore background
RestoreExternBackgroundRect( 66, Y_START - 1, 118 + 1 - 67, ( INT16 )( ( ( MAX_CHARACTER_COUNT + 1 ) * ( Y_SIZE + 2 ) ) + 1 ) );
// 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;
}
// leave
return;
}
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 )
{
// restore background
RestoreExternBackgroundRect( 182, Y_START - 1, 217 + 1 - 182, ( INT16 )( ( ( MAX_CHARACTER_COUNT + 1 ) * ( Y_SIZE + 2 ) ) + 1 ) );
// 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 )
{
// restore background
RestoreExternBackgroundRect( 222, Y_START - 1, 250 + 1 - 222, ( INT16 )( ( ( MAX_CHARACTER_COUNT + 1 ) * ( Y_SIZE + 2 ) ) + 1 ) ) ;
// 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 )
{
// restore background
RestoreExternBackgroundRect( 123, Y_START - 1, 142 + 1 - 123, ( INT16 )( ( ( MAX_CHARACTER_COUNT + 1 ) * ( Y_SIZE + 2 ) ) + 1 ) ) ;
// 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 >= MAX_CHARACTER_COUNT ) )
{
return( FALSE );
}
// is the character a valid one?
if( gCharactersList[ sCharNumber ].fValid == FALSE )
{
return ( FALSE );
}
// if the highlighted line character is also selected
if ( ( ( giDestHighLine != -1 ) && IsEntryInSelectedListSet ( ( INT8 ) giDestHighLine ) ) ||
( ( bSelectedDestChar != -1 ) && IsEntryInSelectedListSet ( bSelectedDestChar ) ) )
{
// then ALL selected lines will be affected
if( IsEntryInSelectedListSet( ( INT8 ) sCharNumber ) )
{
return( TRUE );
}
}
else
{
// if he is *the* selected dude
if( bSelectedDestChar == sCharNumber )
{
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 >= MAX_CHARACTER_COUNT ) )
{
return( FALSE );
}
// is the character a valid one?
if( gCharactersList[ sCharNumber ].fValid == FALSE )
{
return ( FALSE );
}
// if the highlighted line character is also selected
if ( ( giAssignHighLine != -1 ) && IsEntryInSelectedListSet ( ( INT8 ) giAssignHighLine ) )
{
// then ALL selected lines will be affected
if( IsEntryInSelectedListSet( ( INT8 ) sCharNumber ) )
{
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 >= MAX_CHARACTER_COUNT ) )
{
return( FALSE );
}
// is the character a valid one?
if( gCharactersList[ sCharNumber ].fValid == FALSE )
{
return ( FALSE );
}
// if the highlighted line character is also selected
if ( ( giSleepHighLine != -1 ) && IsEntryInSelectedListSet ( ( INT8 ) giSleepHighLine ) )
{
// then ALL selected lines will be affected
if( IsEntryInSelectedListSet( ( INT8 ) sCharNumber ) )
{
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 < MAX_CHARACTER_COUNT; 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->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->bLife > 0 ) &&( pSoldier->bAssignment != ASSIGNMENT_POW ) )
{
fShowContractMenu = TRUE;
}
else
{
fShowRemoveMenu = TRUE;
}
break;
}
}
*/
INT32 DoMapMessageBoxWithRect( UINT8 ubStyle, const STR16 zString, UINT32 uiExitScreen, UINT16 usFlags, MSGBOX_CALLBACK ReturnCallback, SGPRect *pCenteringRect )
{ // reset the highlighted line
giHighLine = -1;
return DoMessageBox( ubStyle, zString, uiExitScreen, ( UINT16 ) ( usFlags | MSG_BOX_FLAG_USE_CENTERING_RECT ), ReturnCallback, pCenteringRect );
}
INT32 DoMapMessageBox( UINT8 ubStyle, STR16 zString, UINT32 uiExitScreen, UINT16 usFlags, MSGBOX_CALLBACK ReturnCallback )
{
// WANNE 2
SGPRect CenteringRect= {0, 0, SCREEN_WIDTH, INV_INTERFACE_START_Y };
// reset the highlighted line
giHighLine = -1;
// do message box and return
return DoMessageBox( ubStyle, zString, uiExitScreen, ( UINT16 ) ( 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 == TRUE ) )
{
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 < MAX_CHARACTER_COUNT; 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;
INT16 usVehicleCount = 0;
// 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;
}
// now blit one by the selected merc
sYPosition = Y_START+( bSelectedInfoChar * ( Y_SIZE + 2 ) ) - 1;
if( bSelectedInfoChar >= FIRST_VEHICLE )
{
// WANNE 2 <fixed>
usVehicleCount = bSelectedInfoChar - FIRST_VEHICLE;
sYPosition = usVehicleY+( usVehicleCount * ( Y_SIZE + 2) ) - 1;;
}
GetVideoObject( &hHandle, guiSelectedCharArrow );
BltVideoObject( guiSAVEBUFFER , hHandle, 0,SELECTED_CHAR_ARROW_X, sYPosition , VO_BLT_SRCTRANSPARENCY,NULL );
// now run through the selected list of guys, an arrow for each
for( ubCount = 0; ubCount < MAX_CHARACTER_COUNT; ubCount++ )
{
if( gCharactersList[ ubCount ].fValid == TRUE )
{
// are they in the selected list or int he same mvt group as this guy
if( ( IsEntryInSelectedListSet( ubCount ) == TRUE ) || ( ( bSelectedDestChar != - 1 ) ? ( ( Menptr[ gCharactersList[ ubCount ].usSolID ].ubGroupID != 0 ) ? ( Menptr[ gCharactersList[ bSelectedDestChar ].usSolID ].ubGroupID == Menptr[ gCharactersList[ ubCount ].usSolID ].ubGroupID ) : FALSE ) : FALSE ) )
{
sYPosition = Y_START+( ubCount * ( Y_SIZE + 2) ) - 1;
if( ubCount >= FIRST_VEHICLE )
{
// WANNE 2 <fixed>
usVehicleCount = ubCount - FIRST_VEHICLE;
sYPosition = usVehicleY+( usVehicleCount * ( Y_SIZE + 2) ) - 1;;
}
GetVideoObject( &hHandle, guiSelectedCharArrow );
BltVideoObject( guiSAVEBUFFER , hHandle, 0,SELECTED_CHAR_ARROW_X, 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].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->bMorale;
if ( pSoldier->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;
INT16 sGridNo, sTempGridNo;
if( Menptr[ uiMercId ].sSectorX != gWorldSectorX || Menptr[ uiMercId ].sSectorY != gWorldSectorY || Menptr[ uiMercId ].bSectorZ != gbWorldSectorZ )
{
// ATE: Use insertion gridno if not nowhere and insertion is gridno
if ( Menptr[ uiMercId ].ubStrategicInsertionCode == INSERTION_CODE_GRIDNO && Menptr[ uiMercId ].usStrategicInsertionData != NOWHERE )
{
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 ( sGridNo == NOWHERE )
{
sGridNo = RandomGridNo();
sTempGridNo = FindNearestAvailableGridNoForItem( sGridNo, 5 );
if( sTempGridNo == NOWHERE )
sTempGridNo = FindNearestAvailableGridNoForItem( sGridNo, 15 );
if ( sTempGridNo != NOWHERE )
{
sGridNo = sTempGridNo;
}
}
}
for( iCounter = 0; iCounter < NUM_INV_SLOTS; iCounter++ )
{
// slot found,
// check if actual item
if( Menptr[ uiMercId ].inv[ iCounter ].ubNumberOfObjects > 0 )
{
if( Menptr[ uiMercId ].sSectorX != gWorldSectorX || Menptr[ uiMercId ].sSectorY != gWorldSectorY || Menptr[ uiMercId ].bSectorZ != gbWorldSectorZ )
{
// Set flag for item...
AddItemsToUnLoadedSector( Menptr[ uiMercId ].sSectorX, Menptr[ uiMercId ].sSectorY, Menptr[ uiMercId ].bSectorZ , sGridNo, 1, &( Menptr[ uiMercId ].inv[ iCounter ]) , Menptr[ uiMercId ].bLevel, WOLRD_ITEM_FIND_SWEETSPOT_FROM_GRIDNO | WORLD_ITEM_REACHABLE, 0, 1, FALSE );
}
else
{
AddItemToPool( sGridNo, &( Menptr[ uiMercId ].inv[ iCounter ] ) , 1, Menptr[ uiMercId ].bLevel, WORLD_ITEM_REACHABLE, 0 );
}
}
}
DropKeysInKeyRing( MercPtrs[ uiMercId ], sGridNo, MercPtrs[ uiMercId ]->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 -> o ) , 0, WORLD_ITEM_REACHABLE, 0, 1, FALSE );
}
else
{
AddItemToPool( OMERTA_LEAVE_EQUIP_GRIDNO, &( pItem->o ), 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 != BOBBYR_SHIPPING_DEST_SECTOR_X || gWorldSectorY != BOBBYR_SHIPPING_DEST_SECTOR_Y || gbWorldSectorZ != BOBBYR_SHIPPING_DEST_SECTOR_Z )
{
// given this slot value, add to sector item list
AddItemsToUnLoadedSector( BOBBYR_SHIPPING_DEST_SECTOR_X, BOBBYR_SHIPPING_DEST_SECTOR_Y, BOBBYR_SHIPPING_DEST_SECTOR_Z, 10433, 1, &( pItem -> o ) , 0, WORLD_ITEM_REACHABLE, 0, 1, FALSE );
}
else
{
AddItemToPool( 10433, &( pItem->o ), 1, 0, WORLD_ITEM_REACHABLE, 0 );
}
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 *o, UINT32 uiSlotIndex )
{
MERC_LEAVE_ITEM *pItem, *pCurrentItem;
Assert( uiSlotIndex < NUM_LEAVE_LIST_SLOTS );
if( o == NULL )
{
return( FALSE );
}
// allocate space
pItem = (MERC_LEAVE_ITEM *) MemAlloc( sizeof( MERC_LEAVE_ITEM ) );
// copy object
memcpy( &( pItem->o ), o, sizeof( OBJECTTYPE ) );
// 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;
INT32 iCounter = 0;
iSlotIndex = FindFreeSlotInLeaveList( );
if( iSlotIndex == -1 )
{
return( -1 );
}
for( iCounter = 0; iCounter < NUM_INV_SLOTS; iCounter++ )
{
// slot found,
// check if actual item
if( Menptr[ uiMercId ].inv[ iCounter ].ubNumberOfObjects > 0 )
{
// 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
memset( ( gMercProfiles[ Menptr[ uiMercId ].ubProfile ].bInvStatus ), 0, sizeof( UINT8 ) * 19 );
memset( ( gMercProfiles[ Menptr[ uiMercId ].ubProfile ].bInvNumber ), 0, sizeof( UINT8 ) * 19 );
memset( ( gMercProfiles[ Menptr[ uiMercId ].ubProfile ].inv ), 0, sizeof( UINT16 ) * 19 );
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;
}
/*
BOOLEAN RemoveItemFromLeaveIndex( MERC_LEAVE_ITEM *pItem, UINT32 uiSlotIndex )
{
MERC_LEAVE_ITEM *pCurrentItem = NULL;
Assert( uiSlotIndex < NUM_LEAVE_LIST_SLOTS );
if( pItem == NULL )
{
return( FALSE );
}
// item is head of list?
//ARM: THIS DOESN'T MAKE SENSE, pCurrentItem is always NULL at this stage!
if( pItem == pCurrentItem )
{
gpLeaveListHead[ uiSlotIndex ] = pCurrentItem ->pNext;
MemFree( pItem );
pItem = NULL;
return( TRUE );
}
// in the body
while( ( pCurrentItem->pNext != pItem ) && ( pCurrentItem -> pNext != NULL ) )
{
pCurrentItem = pCurrentItem -> pNext;
}
// item not found
if( pCurrentItem->pNext == NULL )
{
return( FALSE );
}
// set to next after next
pCurrentItem->pNext = pCurrentItem->pNext->pNext;
// free space and null ptr
MemFree( pItem );
pItem = NULL;
return( TRUE );
}
*/
void HandleGroupAboutToArrive( void )
{
// reblit map to change the color of the "people in motion" marker
fMapPanelDirty = TRUE;
// ARM - commented out - don't see why this is needed
// fTeamPanelDirty = TRUE;
// fCharacterInfoPanelDirty = TRUE;
return;
}
/*
void HandleMapScreenUpArrow( void )
{
INT32 iValue = 0;
INT32 iHighLine = 0;
// check state and update
if( fShowAssignmentMenu == TRUE )
{
if( GetBoxShadeFlag( ghAssignmentBox, iValue ) == FALSE )
{
if( iHighLine == 0)
{
iHighLine = ( INT32 )GetNumberOfLinesOfTextInBox( ghAssignmentBox );
}
else
{
iHighLine++;
}
}
}
else
{
if( ( giHighLine == 0 ) || ( giHighLine == -1 ) )
{
giHighLine = GetNumberOfCharactersOnPlayersTeam( ) - 1;
fTeamPanelDirty = TRUE;
}
else
{
giHighLine--;
fTeamPanelDirty = TRUE;
}
}
}
void HandleMapScreenDownArrow( void )
{
INT32 iValue = 0;
INT32 iHighLine = 0;
// check state and update
if( fShowContractMenu == TRUE )
{
if( iHighLine == ( INT32 )GetNumberOfLinesOfTextInBox( ghContractBox ) - 1 )
{
iHighLine = 0;
}
else
{
iHighLine++;
}
HighLightBoxLine( ghContractBox, iHighLine );
}
else if( fShowAssignmentMenu == TRUE )
{
if( GetBoxShadeFlag( ghAssignmentBox, iValue ) == FALSE )
{
if( iHighLine == ( INT32 )GetNumberOfLinesOfTextInBox( ghAssignmentBox ) - 1 )
{
iHighLine = 0;
}
else
{
iHighLine--;
}
}
}
else
{
if( ( giHighLine == GetNumberOfCharactersOnPlayersTeam( ) - 1 ) || ( giHighLine == -1 ) )
{
giHighLine = 0;
fTeamPanelDirty = TRUE;
}
else
{
giHighLine++;
fTeamPanelDirty = TRUE;
}
}
}
INT32 GetNumberOfCharactersOnPlayersTeam( void )
{
INT32 iNumberOfPeople = 0, iCounter = 0;
for(iCounter = 0; iCounter < MAX_CHARACTER_COUNT; iCounter++ )
{
if( gCharactersList[ iCounter ].fValid == TRUE )
{
iNumberOfPeople++;
}
}
return( iNumberOfPeople );
}
*/
void CreateMapStatusBarsRegion( void )
{
// create the status region over the bSelectedCharacter info region, to get quick rundown of merc's status
MSYS_DefineRegion( &gMapStatusBarsRegion, BAR_INFO_X - 3, BAR_INFO_Y - 42,(INT16)( BAR_INFO_X + 17), (INT16)(BAR_INFO_Y ), 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[ 128 ];
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->bLife != 0 )
{
if ( AM_A_ROBOT( MercPtrs[ gCharactersList[ bSelectedInfoChar ].usSolID ] ) )
{
// robot (condition only)
swprintf( sString, L"%s: %d/%d",
pMapScreenStatusStrings[ 3 ], pSoldier->bLife, pSoldier->bLifeMax );
}
else if ( Menptr[ gCharactersList[ bSelectedInfoChar ].usSolID ].uiStatusFlags & SOLDIER_VEHICLE )
{
// vehicle (condition/fuel)
swprintf( sString, L"%s: %d/%d, %s: %d/%d",
pMapScreenStatusStrings[ 3 ], pSoldier->bLife, pSoldier->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->bLife, pSoldier->bLifeMax,
pMapScreenStatusStrings[ 1 ], pSoldier->bBreath, pSoldier->bBreathMax,
pMapScreenStatusStrings[ 2 ], pMoraleStr );
}
}
else
{
wcscpy( sString, L"" );
}
}
else
{
// POW - stats unknown
swprintf( sString, L"%s: ??, %s: ??, %s: ??", pMapScreenStatusStrings[ 0 ], pMapScreenStatusStrings[ 1 ], pMapScreenStatusStrings[ 2 ] );
}
SetRegionFastHelpText( &gMapStatusBarsRegion, sString );
// 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 < MAX_CHARACTER_COUNT; 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;
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 ) );
/* ARM: Removed this - refreshes fine without it, apparently
// make sure the menus don't overlap the map screen bottom panel (but where did 102 come from?)
if( giBoxY >= ( MAP_BOTTOM_Y - 102 ) )
giBoxY = MAP_BOTTOM_Y - 102;
*/
}
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;
if( fShowAssignmentMenu )
{
GetBoxPosition( ghAssignmentBox, &pPoint);
pPoint.iY = giBoxY;
SetBoxPosition( ghAssignmentBox, pPoint );
GetBoxPosition( ghEpcBox, &pPoint);
pPoint.iY = giBoxY;
SetBoxPosition( ghEpcBox, pPoint );
}
if( fShowAttributeMenu )
{
GetBoxPosition( ghAttributeBox, &pPoint);
pPoint.iY = giBoxY + ( GetFontHeight( MAP_SCREEN_FONT ) + 2 ) * ASSIGN_MENU_TRAIN;
SetBoxPosition( ghAttributeBox, pPoint );
}
if( fShowRepairMenu )
{
GetBoxPosition( ghRepairBox, &pPoint);
pPoint.iY = giBoxY + ( GetFontHeight( MAP_SCREEN_FONT ) + 2 ) * ASSIGN_MENU_REPAIR;
SetBoxPosition( ghRepairBox, pPoint );
}
return;
}
//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[ 20 ];
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->bLife >= OKLIFE && !( pSoldier->uiStatusFlags & SOLDIER_VEHICLE ) &&
!AM_A_ROBOT( pSoldier ) && !AM_AN_EPC( pSoldier ) && !pSoldier->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 < MAX_CHARACTER_COUNT; iCounter++ )
{
if( gCharactersList[ iCounter].fValid == TRUE )
{
// another valid character
iCount++;
}
}
return( iCount );
}
BOOLEAN ValidSelectableCharForNextOrPrev( INT32 iNewCharSlot )
{
BOOLEAN fHoldingItem = 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->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->fBetweenSectors )
{
// other guy must also be on the road...
if ( !pOldSoldier->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 == TRUE ) )
{
AbortMovementPlottingMode( );
}
// is the current guy invalid or the first one?
if( ( bSelectedInfoChar == -1 )|| ( bSelectedInfoChar == MAX_CHARACTER_COUNT ) )
{
iCount = 0;
}
else
{
iCount = bSelectedInfoChar + 1;
}
for( iCounter = 0; iCounter < MAX_CHARACTER_COUNT; iCounter++ )
{
if ( ( gCharactersList[ iCount ].fValid ) && ( iCount < MAX_CHARACTER_COUNT ) && ValidSelectableCharForNextOrPrev( iCount ) )
{
ChangeSelectedInfoChar( ( INT8 )iCount, TRUE );
break;
}
else
{
iCount++;
if( iCount >= MAX_CHARACTER_COUNT )
{
iCount = 0;
}
}
}
}
void GoToPrevCharacterInList( void )
{
INT32 iCounter = 0, iCount = 0;
if( fShowDescriptionFlag == TRUE )
{
return;
}
if( ( bSelectedDestChar != -1 ) || ( fPlotForHelicopter == TRUE ) )
{
AbortMovementPlottingMode( );
}
// is the current guy invalid or the first one?
if( ( bSelectedInfoChar == -1 ) || ( bSelectedInfoChar == 0 ) )
{
iCount = MAX_CHARACTER_COUNT;
}
else
{
iCount = bSelectedInfoChar - 1;
}
// now run through the list and find first prev guy
for( iCounter = 0; iCounter < MAX_CHARACTER_COUNT; iCounter++ )
{
if ( ( gCharactersList[ iCount ].fValid ) && ( iCount < MAX_CHARACTER_COUNT ) && ValidSelectableCharForNextOrPrev( iCount ) )
{
ChangeSelectedInfoChar( ( INT8 )iCount, TRUE );
break;
}
else
{
iCount--;
if( iCount < 0 )
{
// was FIRST_VEHICLE
iCount = MAX_CHARACTER_COUNT;
}
}
}
}
void HandleMinerEvent( UINT8 bMinerNumber, 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;
}
}
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 );
}
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 );
}
}
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;
INT32 iNumberOfLines = 1;
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;
INT32 iNumberOfLines = 1;
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, iCount = 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 < 10 ; 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 < MAX_CHARACTER_COUNT; 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 < MAX_CHARACTER_COUNT; 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 < MAX_CHARACTER_COUNT; 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 < MAX_CHARACTER_COUNT; iCounter++ )
{
if( gCharactersList[ iCounter ].fValid )
{
pSoldier = MercPtrs[ gCharactersList[ iCounter ].usSolID ];
if( ( pSoldier->bActive ) &&
( pSoldier->bAssignment != IN_TRANSIT ) && ( pSoldier->bAssignment != ASSIGNMENT_POW ) &&
( pSoldier->sSectorX == sSectorX ) && ( pSoldier->sSectorY == sSectorY ) && ( pSoldier->bSectorZ == sSectorZ ) )
{
if ( pSoldier->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->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 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 ] )
{
swprintf( sString, L"*%s*", pSquadMenuStrings[iSquadMovingList[ iCount ] ] );
}
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 ] );
}
else
{
swprintf( sString, L"%s", pVehicleStrings[ pVehicleList[ iVehicleMovingList[ iCount ] ].ubVehicleType ] );
}
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->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 < MAX_CHARACTER_COUNT; iCounter++ )
{
// is the current guy a valid character?
if( gCharactersList[ iCounter ].fValid == TRUE )
{
pSoldier = MercPtrs[ gCharactersList[ iCounter ].usSolID ];
if ( pSoldier->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->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 )
{
// 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 ];
INT16 sX = 0, sY = 0;
INT32 iHeightOfString = 0;
INT32 iCounterB = 0;
INT32 iOrigNumberHigh = 0, iOrigY = 0;
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;
// WANNE 2
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 );
}
// WANNE 2
//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;
}
// WANNE 2
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 )
{
// 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->bLife )
return;
//yellow one for bleeding
iStartY = iY + 29 - 27*pSoldier->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 += 27*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->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->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 ) ) );
return;
}
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;
fMapPanelDirty = TRUE;
}
void SetOrtaAsFound( void )
{
// set the town of Orta as found by the player
fFoundOrta = 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, CHAR_ICON_CONTRACT_Y, CHAR_ICON_X + CHAR_ICON_WIDTH, CHAR_ICON_CONTRACT_Y + CHAR_ICON_HEIGHT,
MSYS_PRIORITY_HIGH - 1, MSYS_NO_CURSOR, MSYS_NO_CALLBACK, MSYS_NO_CALLBACK );
MSYS_DefineRegion( &gInsuranceIconRegion, CHAR_ICON_X, CHAR_ICON_CONTRACT_Y + CHAR_ICON_SPACING, CHAR_ICON_X + CHAR_ICON_WIDTH, CHAR_ICON_CONTRACT_Y + CHAR_ICON_SPACING + CHAR_ICON_HEIGHT,
MSYS_PRIORITY_HIGH - 1, MSYS_NO_CURSOR, MSYS_NO_CALLBACK, MSYS_NO_CALLBACK );
MSYS_DefineRegion( &gDepositIconRegion, CHAR_ICON_X, CHAR_ICON_CONTRACT_Y + ( 2 * CHAR_ICON_SPACING ), CHAR_ICON_X + CHAR_ICON_WIDTH, CHAR_ICON_CONTRACT_Y + ( 2 * CHAR_ICON_SPACING ) + 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;
}
}
/*
void HandlePlayerEnteringMapScreenBeforeGoingToTactical( void )
{
CHAR16 sString[ 256 ];
if( !( AnyMercsHired( ) ) )
{
// no mercs hired inform player they must hire mercs
swprintf( sString, pMapScreenJustStartedHelpText[ 0 ] );
DoMapMessageBox( MSG_BOX_BASIC_STYLE, sString, MAP_SCREEN, MSG_BOX_FLAG_OK, DoneHandlePlayerFirstEntryToMapScreen );
}
else
{
// player has mercs hired, tell them to time compress to get things underway
swprintf( sString, pMapScreenJustStartedHelpText[ 1 ] );
fShowMapScreenHelpText = TRUE;
}
// now inform the player
if( fShowMapScreenHelpText )
{
fShowMapScreenHelpText = FALSE;
SetUpShutDownMapScreenHelpTextScreenMask( );
fShowMapScreenHelpText = TRUE;
}
return;
}
void DoneHandlePlayerFirstEntryToMapScreen( UINT8 bExitValue )
{
static BOOLEAN fFirstTime = TRUE;
if( bExitValue == MSG_BOX_RETURN_OK )
{
if( fFirstTime == TRUE )
{
fFirstTime = FALSE;
fShowMapScreenHelpText = TRUE;
}
}
}
*/
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 );
}
// select starting sector (A9 - Omerta)
ChangeSelectedMapSector( 9, 1, 0 );
// load starting sector
if ( !SetCurrentWorldSector( 9, 1, 0 ) )
{
return( FALSE );
}
//Setup variables in the PBI for this first battle. We need to support the
//non-persistant PBI in case the user goes to mapscreen.
gfBlitBattleSectorLocator = TRUE;
gubPBSectorX = 9;
gubPBSectorY = 1;
gubPBSectorZ = 0;
gubEnemyEncounterCode = ENTERING_ENEMY_SECTOR_CODE;
InitHelicopterEntranceByMercs( );
FadeInGameScreen( );
SetUpShutDownMapScreenHelpTextScreenMask( );
// Add e-mail message
AddEmail(ENRICO_CONGRATS,ENRICO_CONGRATS_LENGTH,MAIL_ENRICO, GetWorldTotalMin(), -1);
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 )
{
if( bTownId == SAN_MONA )
{ //San Mona isn't important.
return( TRUE );
}
swprintf( sStringB, pMapErrorString[ 25 ], sString );
// 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 )
{
BOOLEAN fCanMove = TRUE;
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->uiStatusFlags & SOLDIER_VEHICLE )
{
// empty (needs a driver!)?
if ( GetNumberInVehicle( pSoldier->bVehicleID ) == 0 )
{
*pbErrorNumber = 32;
return( FALSE );
}
// too damaged?
if ( pSoldier->bLife < OKLIFE )
{
*pbErrorNumber = 47;
return( FALSE );
}
// out of fuel?
if ( !VehicleHasFuel( pSoldier ) )
{
*pbErrorNumber = 42;
return( FALSE );
}
}
else // non-vehicle
{
// dead?
if ( pSoldier->bLife <= 0 )
{
swprintf( gsCustomErrorString, pMapErrorString[ 35 ], pSoldier->name );
*pbErrorNumber = -99; // customized error message!
return( FALSE );
}
// too injured?
if ( pSoldier->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->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->fBetweenSectors ) && gMercProfiles[ ELDIN ].bMercStatus != MERC_IS_DEAD )
{
UINT8 ubRoom, cnt;
SOLDIERTYPE * pSoldier2;
if ( InARoom( pSoldier->sGridNo, &ubRoom ) && ubRoom >= 22 && ubRoom <= 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->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 < MAX_CHARACTER_COUNT; 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->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 )
{
if ( bErrorNumber == -99 )
{
// - 99 is a special message # indicating a customized message
DoMapMessageBox( MSG_BOX_BASIC_STYLE, gsCustomErrorString, MAP_SCREEN, MSG_BOX_FLAG_OK, MapScreenDefaultOkBoxCallback );
}
else
{
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->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 );
}
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
FileWrite( hFile, pCurrentItem, sizeof( MERC_LEAVE_ITEM ), &uiNumBytesWritten );
if( uiNumBytesWritten != sizeof( MERC_LEAVE_ITEM ) )
{
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);
}
// allocate space
gpLeaveListHead[ iCounter ] = (MERC_LEAVE_ITEM *) MemAlloc( sizeof( MERC_LEAVE_ITEM ) );
if( gpLeaveListHead[ iCounter ] == NULL )
{
return( FALSE );
}
memset( gpLeaveListHead[ iCounter ], 0, sizeof( MERC_LEAVE_ITEM ) );
pCurrentItem = gpLeaveListHead[ iCounter ];
for( uiSubItem=0; uiSubItem< uiCount; uiSubItem++ )
{
// allocate space
pItem = (MERC_LEAVE_ITEM *) MemAlloc( sizeof( MERC_LEAVE_ITEM ) );
if( pItem == NULL )
{
return( FALSE );
}
memset( pItem, 0, sizeof( MERC_LEAVE_ITEM ) );
// Load the items
FileRead( hFile, pItem, sizeof( MERC_LEAVE_ITEM ), &uiNumBytesRead );
if( uiNumBytesRead != sizeof( MERC_LEAVE_ITEM ) )
{
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 ( !fShowAircraftFlag )
{
// 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->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->fContractPriceHasIncreased = FALSE;
// said quote / triggered contract menu
return( TRUE );
}
else
{
// nope, nothing to do
return( FALSE );
}
}