mirror of
https://github.com/1dot13/source.git
synced 2026-07-22 13:40:22 +02:00
Development Trunk (now obsolete): https://ja2svn.dyndns.org/source/ja2/branches/Wanne/JA2%201.13%20MP A detailed list of all the features (changes) is visible in the history log of the development trunk: INFO: There will be no further development in the development source trunk, so is obsolete from now on! This commit contains the following features (bugfixes are not listed): - New Feature: Show merc ranks in Strategy Screen before merc name o Toggle on/off in the ingame options screen o For each experience level (0-10) there are defined rank names in the language specific text files o Additional language text that is not translated yet is marked with // TODO.Translate - New Feature: Faster Bobby Ray Shipments o This feature is selectable in the ja2_options.ini o When activated Bobby Ray shipments will be really fast -> Overnight Express: 5 - 7 hours -> Air Service: 10, 12 or 14 hours -> Standard Service: 15, 18 or 21 hours o In a multiplayer game, this feature is disabled (because shipment arrive immediately in the destination sector) - New Feature: AP cost for manipulating the merc inventory o This feature is selectable in the start new game screen o For example, putting a weapon from hand in the backpack costs APs o The AP costs are defined in the APBPConstants.ini o In a multiplayer game, this feature is disabled - New Feature: Added possibility to set individual Gear Kit names o Set individual names in the optional new tag <mGearKitName> inside the <GEARKIT> root element (File: TableData\MercStartingGear.xml) - New Feature: Externalized the maximum purchase amount (JA2 vanilla: 10) for Bobby Rays purchases per shipment o Define the max. amount in the ja2_options.ini: BOBBY_RAY_MAX_PURCHASE_AMOUNT, Range: 10 - 100) o Nice scrolling bars to scroll through all the purchases - New Feature: Now it is possible to walk on "water" tiles or handle those tiles like "normal" tiles o (instead of showing the swimming animation and counting the APs for swimming), when the soldier is located on the second level (level > 0) - New Feature: Externalized AIM Veterans laptop site o Add maximum of 4 pages o Add new AIM to veterans page, and remove AIM from veterans page. o New XML file: OldAIMArchive.xml (language specific XML files: *.OldAIMArchive.xml) - New Feature: Added possibility to choose from 254 IMP faces o Modified IMPPortraits.xml o Added new GameDir folder "IMPFaces" which contains the IMP face portraits o Moved IMP faces in the new "IMPFaces" folder - New Feature: ARSP - All Resolution Support Project o See here: http://www.ja-galaxy-forum.com/board/ubbthreads.php?ubb=showflat&Number=298698&page=1 o Support any kind of screen resolution. This works by choosing the matching full supported resolution (640x480, 800x600, 1024x768) and then centering the graphics o See ja2.ini for defining the screen resolution - New Feature: AI Turn Speed Up (FF-MOD) o see here: http://www.ja-galaxy-forum.com/board/ubbthreads.php?ubb=showflat&Number=298699#Post298699 o When this feature is activated it allows fast enemy turns o New entry in ja2.ini to enable this feature: HIGHSPEED_TIMER = TRUE o Turn on/off auto fast turns in ingame options o New ja2_options.ini settings for fine tuning: [Clock Settings] ini block - New Feature: "Lock" / "Release" mouse cursor in tactical windowed mode, so the mouse can stay within window boundary o This is very helpful for doing scrolling with the mouse (by moving the mouse to the window edge) in windowed mode o You can toggle on/off the feature by pressing CTRL + Z. It is also possible to press CTRL + Y. So the user can decide which fits better :) o Whenever you toggle on/off a screen message appears on the tactical log to notify the player - New Feature: Weapon overheating o Basically, every shot fired from a gun increases its temperature. On higher temperatures, the gun jams more frequently o On/off toggle in the ingame options o Graphical thermometer indication on the weapon picture o New ja2_options.ini section with a few options, Section: [Tactical Weapon Overheating Settings] o XML changes (New Tags) --> AmmoTypes.xml: <temperatureModificator> --> Items.xml: <barrel>, <usOverheatingCooldownFactor> --> Weapons.xml: <usOverheatingJamThreshold>, <usOverheatingDamageThreshold>, <usOverheatingSingleShotTemperature> o Added a few barells to Items.xml (end of the file) o more infos: http://www.ja-galaxy-forum.com/board/ubbthreads.php?ubb=showflat&Number=301059&page=1 - New Feature: Resting weapons on a surfaces o You can now rest your weapon on crates, low walls, rocks, debris, open windows etc. while you are crouched. Resting will give yu the superior gun handling modifiers from PRONE position. o A little 'A' on your gun indicates if you are resting it or not. o Both settings can be turned on and off in Ja2_Options.ini under 'Tactical Gameplay Settings' - New Feature: Externalized option on whether mercs can exit sector using grid exit in turn based mode o new ja2_options.ini property: GRID_EXIT_IN_TURNBASED o This ini setting does not affect leaving sectors on map edges - Rework/Update: Ammo boxes and Ammo crates o Ammo crate items added for remaining calibers. Tweaked prices to correspond to magazines, tweaked capacities and weights to be reasonable (~800 or less). o Shift-R reload now looks at both boxes and crates in sector items and merc's inventory to reload, and tops off magazines in inventory as well. Only possible outside of combat. o Ctrl-Shift-A still creates crates as per usual, with some fixes to ensure all ammo is caught on the first press. o Shift-A now creates ammo boxes in the same loop. They mostly behave like crates, but fit in mercs inventories. o Ammo boxes are available to purchase at BR and tony, sam, etc. Individual magazines/drums/etc are no longer available. o Removed ammo crate xml tag. Added ubMagType tag to Magazines array. This allows us to differentiate between magazines, bullets, boxes and crates. o Changed ammo filtering in BR's to display boxes appropriately. Added back the "Mag:" display (changed text to "Size:") o Added ja2set.dat.xml file (WF map version in WF maps folder) to be used instead of ja2set.dat file (ja2.ini setting added) For now, if you want to play vanilla instead, just change the setting in the ini (see comments in file). o Added P4-P9Items image files (up to 5k images each) and tileslots. 1.13 core items will continue to use Guns and P1-P3Items for the foreseeable future. P4-P9 can be used by customizers/modders to avoid conflicts with Guns/P1-P3 items. TODO: Need to discuss a strategy for this in the forums. o Added in Ambient/0.bad and 32.bad to avoid an exception in the code. o Updated the XML Editor o Standardized the text on all the ammo items. - New Multiplayer Feature: Sharing same FOV (field of view) in a coop/team-dm (for friendly teams) game o You will also see enemies, that your teammate sees git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@5108 3b4a5df2-a311-0410-b5c6-a8a6f20db521
6652 lines
175 KiB
C++
6652 lines
175 KiB
C++
#ifdef PRECOMPILEDHEADERS
|
|
#include "Strategic All.h"
|
|
#else
|
|
#include "Map Screen Interface.h"
|
|
#include "string.h"
|
|
#include "Map Screen Interface Map.h"
|
|
#include "Render Dirty.h"
|
|
#include "Font Control.h"
|
|
#include "Assignments.h"
|
|
#include "Soldier Control.h"
|
|
#include "Overhead.h"
|
|
#include "Squads.h"
|
|
#include "Sound Control.h"
|
|
#include "Soundman.h"
|
|
#include "Message.h"
|
|
#include "PopUpBox.h"
|
|
#include "Game Clock.h"
|
|
#include "Handle Items.h"
|
|
#include "Interface Items.h"
|
|
#include "Isometric Utils.h"
|
|
#include "Interface.h"
|
|
#include "Game Event Hook.h"
|
|
#include "Tactical Save.h"
|
|
#include "Quests.h"
|
|
#include "Strategicmap.h"
|
|
#include "Soldier Profile.h"
|
|
#include "Strategic Movement.h"
|
|
#include "Dialogue Control.h"
|
|
#include "Map Screen Interface Border.h"
|
|
#include "Map Screen Interface Bottom.h"
|
|
#include "Vehicles.h"
|
|
#include "LINE.H"
|
|
#include "Text.h"
|
|
#include "gameloop.h"
|
|
#include "Map Screen Helicopter.h"
|
|
#include "PreBattle Interface.h"
|
|
#include "WordWrap.h"
|
|
#include "interface control.h"
|
|
#include "GameSettings.h"
|
|
#include "Campaign Types.h"
|
|
#include "Map Screen Interface Map Inventory.h"
|
|
#include "strategic.h"
|
|
#include "Keys.h"
|
|
#include "Soldier macros.h"
|
|
#include "Militia Control.h"
|
|
#include "Random.h"
|
|
#include "Cursor Control.h"
|
|
#include "renderworld.h"
|
|
#include "Game Init.h"
|
|
#include "Strategic Mines.h"
|
|
#include "finances.h"
|
|
#include "strategic.h"
|
|
#include "Air Raid.h"
|
|
#include "Queen Command.h"
|
|
#include "Render Fun.h"
|
|
#endif
|
|
|
|
#include "connect.h"
|
|
|
|
//forward declarations of common classes to eliminate includes
|
|
class OBJECTTYPE;
|
|
class SOLDIERTYPE;
|
|
|
|
// marke strogg more mercs
|
|
extern UINT8 FIRSTmercTOdisplay = 0 ;
|
|
extern UINT8 maxNumberOfMercVisibleInStrategyList = 0; // WANNE: Max merc displayed in the list depends on the resolution
|
|
|
|
// inventory pool position on screen
|
|
#define MAP_INVEN_POOL_X 300
|
|
#define MAP_INVEN_POOL_Y 300
|
|
|
|
// the number of help region messages
|
|
#define NUMBER_OF_MAPSCREEN_HELP_MESSAGES 5
|
|
|
|
// WDS - make number of mercenaries, etc. be configurable
|
|
// number of LINKED LISTS for sets of leave items (each slot holds an unlimited # of items)
|
|
#define NUM_LEAVE_LIST_SLOTS CODE_MAXIMUM_NUMBER_OF_PLAYER_SLOTS
|
|
|
|
#define SIZE_OF_UPDATE_BOX 20
|
|
|
|
// as deep as the map goes
|
|
#define MAX_DEPTH_OF_MAP 3
|
|
|
|
|
|
// number of merc columns for four wide mode
|
|
#define NUMBER_OF_MERC_COLUMNS_FOR_FOUR_WIDE_MODE 4
|
|
|
|
// number of merc columns for 2 wide mode
|
|
#define NUMBER_OF_MERC_COLUMNS_FOR_TWO_WIDE_MODE 2
|
|
|
|
// number needed for 4 wide mode to activate
|
|
#define NUMBER_OF_MERCS_FOR_FOUR_WIDTH_UPDATE_PANEL 4
|
|
|
|
#define DBL_CLICK_DELAY_FOR_MOVE_MENU 200
|
|
|
|
|
|
#define TIMER_FOR_SHOW_EXIT_TO_TACTICAL_MESSAGE 15000
|
|
|
|
#define REASON_FOR_SOLDIER_UPDATE_OFFSET_Y (14)
|
|
|
|
#define MAX_MAPSCREEN_FAST_HELP 100
|
|
|
|
#define VEHICLE_ONLY FALSE
|
|
#define AND_ALL_ON_BOARD TRUE
|
|
|
|
|
|
// the regions int he movemenu
|
|
enum{
|
|
SQUAD_REGION = 0,
|
|
VEHICLE_REGION,
|
|
SOLDIER_REGION,
|
|
DONE_REGION,
|
|
CANCEL_REGION,
|
|
OTHER_REGION,
|
|
};
|
|
|
|
UINT16 usVehicleY = 0;
|
|
|
|
// waiting list for update box
|
|
INT32 iUpdateBoxWaitingList[ CODE_MAXIMUM_NUMBER_OF_PLAYER_SLOTS ];
|
|
|
|
FASTHELPREGION pFastHelpMapScreenList[ MAX_MAPSCREEN_FAST_HELP ];
|
|
|
|
// the move menu region
|
|
MOUSE_REGION gMoveMenuRegion[ MAX_POPUP_BOX_STRING_COUNT ];
|
|
|
|
MOUSE_REGION gMapScreenHelpTextMask;
|
|
|
|
BOOLEAN fShowMapScreenHelpText = FALSE;
|
|
BOOLEAN fScreenMaskForMoveCreated = FALSE;
|
|
BOOLEAN fLockOutMapScreenInterface = FALSE;
|
|
|
|
extern INT32 giMercPanelImage;
|
|
extern BOOLEAN fShowDescriptionFlag;
|
|
extern BOOLEAN fInMapMode;
|
|
extern GROUP *gpBattleGroup;
|
|
|
|
CHAR16 gsCustomErrorString[ 128 ];
|
|
|
|
BOOLEAN fShowUpdateBox = FALSE;
|
|
BOOLEAN fInterfaceFastHelpTextActive = FALSE;
|
|
BOOLEAN fReBuildCharacterList = FALSE;
|
|
INT32 giSizeOfInterfaceFastHelpTextList = 0;
|
|
|
|
//Animated sector locator icon variables.
|
|
INT16 gsSectorLocatorX;
|
|
INT16 gsSectorLocatorY;
|
|
UINT8 gubBlitSectorLocatorCode; //color
|
|
UINT32 guiSectorLocatorGraphicID; //icon graphic ID
|
|
// the animate time per frame in milliseconds
|
|
#define ANIMATED_BATTLEICON_FRAME_TIME 80
|
|
#define MAX_FRAME_COUNT_FOR_ANIMATED_BATTLE_ICON 12
|
|
|
|
|
|
|
|
SGPPoint pMapScreenFastHelpLocationList[]={
|
|
{ 25,200 },
|
|
{ 150,200 },
|
|
{ 450,430 },
|
|
{ 400,200 },
|
|
{ 250,100 },
|
|
{ 100,100 },
|
|
{ 100,100 },
|
|
{ 100,100 },
|
|
{ 100,100 },
|
|
{ 150,200 },
|
|
{ 100,100 },
|
|
};
|
|
|
|
INT32 pMapScreenFastHelpWidthList[]={
|
|
100,
|
|
100,
|
|
100,
|
|
100,
|
|
100,
|
|
100,
|
|
100,
|
|
100,
|
|
100,
|
|
300,
|
|
};
|
|
|
|
// number of mercs in sector capable of moving
|
|
INT32 giNumberOfSoldiersInSectorMoving = 0;
|
|
|
|
// number of squads capable of moving
|
|
INT32 giNumberOfSquadsInSectorMoving = 0;
|
|
|
|
// number of vehicles in sector moving
|
|
INT32 giNumberOfVehiclesInSectorMoving = 0;
|
|
|
|
INT32 iHeightOfInitFastHelpText = 0;
|
|
|
|
extern INT32 giMapContractButton;
|
|
extern INT32 giCharInfoButton[];
|
|
extern STR16 pUpdatePanelButtons[];
|
|
|
|
// the list of soldiers that are moving
|
|
SOLDIERTYPE * pSoldierMovingList[ CODE_MAXIMUM_NUMBER_OF_PLAYER_SLOTS ];
|
|
BOOLEAN fSoldierIsMoving[ CODE_MAXIMUM_NUMBER_OF_PLAYER_SLOTS ];
|
|
|
|
SOLDIERTYPE *pUpdateSoldierBox[ SIZE_OF_UPDATE_BOX ];
|
|
|
|
INT32 giUpdateSoldierFaces[ SIZE_OF_UPDATE_BOX ];
|
|
|
|
// the squads thata re moving
|
|
INT32 iSquadMovingList[ NUMBER_OF_SQUADS ];
|
|
INT32 fSquadIsMoving[ NUMBER_OF_SQUADS ];
|
|
|
|
// the vehicles thata re moving
|
|
INT32 iVehicleMovingList[ NUMBER_OF_SQUADS ];
|
|
INT32 fVehicleIsMoving[ NUMBER_OF_SQUADS ];
|
|
|
|
MOUSE_REGION gMoveBoxScreenMask;
|
|
|
|
// the save buffer
|
|
extern UINT32 guiSAVEBUFFER;
|
|
|
|
extern BOOLEAN fShowInventoryFlag;
|
|
extern FACETYPE *gpCurrentTalkingFace;
|
|
extern UINT8 gubCurrentTalkingID;
|
|
extern BOOLEAN fMapScreenBottomDirty;
|
|
extern MOUSE_REGION gMPanelRegion;
|
|
|
|
|
|
// has the inventory pool been selected to be on or off?
|
|
BOOLEAN fMapInventoryPoolInited = FALSE;
|
|
BOOLEAN fShowMapScreenMovementList = FALSE;
|
|
|
|
|
|
MapScreenCharacterSt gCharactersList[ CODE_MAXIMUM_NUMBER_OF_PLAYER_SLOTS+1];
|
|
|
|
extern MOUSE_REGION gCharInfoHandRegion;
|
|
MOUSE_REGION gMapStatusBarsRegion;
|
|
|
|
SGPPoint MovePosition={450, 100 };
|
|
|
|
// which lines are selected? .. for assigning groups of mercs to the same thing
|
|
BOOLEAN fSelectedListOfMercsForMapScreen[ CODE_MAXIMUM_NUMBER_OF_PLAYER_SLOTS ];
|
|
BOOLEAN fResetTimerForFirstEntryIntoMapScreen = FALSE;
|
|
INT32 iReasonForSoldierUpDate = NO_REASON_FOR_UPDATE;
|
|
|
|
// sam and mine icons
|
|
UINT32 guiSAMICON;
|
|
|
|
|
|
// disable team info panels due to battle roster
|
|
BOOLEAN fDisableDueToBattleRoster = FALSE;
|
|
|
|
// track old contract times
|
|
INT32 iOldContractTimes[ CODE_MAXIMUM_NUMBER_OF_PLAYER_SLOTS ];
|
|
|
|
// position of pop up box
|
|
INT32 giBoxY = 0;
|
|
|
|
// screen mask for inventory pop up
|
|
MOUSE_REGION gInventoryScreenMask;
|
|
|
|
MOUSE_REGION gContractIconRegion;
|
|
MOUSE_REGION gInsuranceIconRegion;
|
|
MOUSE_REGION gDepositIconRegion;
|
|
|
|
// general line..current and old
|
|
INT32 giHighLine=-1;
|
|
|
|
// assignment's line...glow box
|
|
INT32 giAssignHighLine=-1;
|
|
|
|
// destination plot line....glow box
|
|
INT32 giDestHighLine=-1;
|
|
|
|
// contract selection glow box
|
|
INT32 giContractHighLine = -1;
|
|
|
|
// the sleep column glow box
|
|
INT32 giSleepHighLine = -1;
|
|
|
|
// pop up box textures
|
|
UINT32 guiPOPUPTEX;
|
|
UINT32 guiPOPUPBORDERS;
|
|
|
|
// the currently selected character arrow
|
|
UINT32 guiSelectedCharArrow;
|
|
|
|
INT32 guiUpdatePanelButtonsImage[ 2 ];
|
|
INT32 guiUpdatePanelButtons[ 2 ];
|
|
|
|
// the update panel
|
|
UINT32 guiUpdatePanel;
|
|
UINT32 guiUpdatePanelTactical;
|
|
|
|
// the leave item list
|
|
MERC_LEAVE_ITEM *gpLeaveListHead[ NUM_LEAVE_LIST_SLOTS ];
|
|
|
|
// holds ids of mercs who left stuff behind
|
|
UINT32 guiLeaveListOwnerProfileId[ NUM_LEAVE_LIST_SLOTS ];
|
|
|
|
// flag to reset contract region glow
|
|
BOOLEAN fResetContractGlow = FALSE;
|
|
|
|
// timers for double click
|
|
INT32 giDblClickTimersForMoveBoxMouseRegions[ MAX_POPUP_BOX_STRING_COUNT ];
|
|
|
|
INT32 giExitToTactBaseTime = 0;
|
|
UINT32 guiSectorLocatorBaseTime = 0;
|
|
|
|
|
|
// which menus are we showing
|
|
BOOLEAN fShowAssignmentMenu = FALSE;
|
|
BOOLEAN fShowTrainingMenu = FALSE;
|
|
BOOLEAN fShowAttributeMenu = FALSE;
|
|
BOOLEAN fShowSquadMenu = FALSE;
|
|
BOOLEAN fShowContractMenu = FALSE;
|
|
BOOLEAN fShowRemoveMenu = FALSE;
|
|
BOOLEAN fShowMilitiaControlMenu = FALSE; //lal
|
|
//BOOLEAN fShowTalkToAllMenu = FALSE;//lal
|
|
BOOLEAN fShowFacilityMenu = FALSE; // HEADROCK HAM 3.6: Facility Menu
|
|
BOOLEAN fShowFacilityAssignmentMenu = FALSE; // HEADROCK HAM 3.6: Facility Sub-menu
|
|
|
|
BOOLEAN fRebuildMoveBox = FALSE;
|
|
|
|
// positions for all the pop up boxes
|
|
SGPRect ContractDimensions={0,0,140,60};
|
|
SGPPoint ContractPosition={120,50};
|
|
SGPRect AttributeDimensions={0,0,100,95};
|
|
SGPPoint AttributePosition={220,150};
|
|
SGPRect TrainDimensions={0,0,100,95};
|
|
SGPPoint TrainPosition={160,150};
|
|
SGPRect VehicleDimensions={0,0,80,60};
|
|
SGPPoint VehiclePosition={160,150};
|
|
// HEADROCK HAM 3.6: Facility Menu Position/Size:
|
|
SGPRect FacilityDimensions={0,0,80,60};
|
|
SGPPoint FacilityPosition={160,150};
|
|
// HEADROCK HAM 3.6: Facility Sub-menu Position/Size:
|
|
SGPRect FacilityAssignmentDimensions={0,0,80,60};
|
|
SGPPoint FacilityAssignmentPosition={220,150};
|
|
|
|
SGPPoint RepairPosition={160,150};
|
|
SGPRect RepairDimensions={0,0,80,80};
|
|
|
|
//lal
|
|
SGPPoint MilitiaControlPosition={120,150};
|
|
SGPRect MilitiaControlDimensions={0,0,100,95};
|
|
|
|
//SGPPoint TalkToAllPosition={160,150};
|
|
//SGPRect TalkToAllDimensions={0,0,100,95};
|
|
//lal
|
|
|
|
SGPPoint AssignmentPosition = { 120, 150 };
|
|
SGPRect AssignmentDimensions = { 0,0, 100, 95};
|
|
|
|
SGPPoint SquadPosition ={ 160, 150 };
|
|
SGPRect SquadDimensions ={ 0, 0, 140, 60 };
|
|
|
|
SGPPoint OrigContractPosition={120,50};
|
|
SGPPoint OrigAttributePosition={220,150};
|
|
SGPPoint OrigSquadPosition ={ 160, 150 };
|
|
SGPPoint OrigAssignmentPosition = { 120, 150 };
|
|
SGPPoint OrigTrainPosition={160,150};
|
|
SGPPoint OrigVehiclePosition={160,150};
|
|
SGPPoint OrigMilitiaControlPosition = { 120, 150 }; //lal
|
|
SGPPoint OrigFacilityPosition = { 160, 150 }; // HEADROCK HAM 3.6
|
|
SGPPoint OrigFacilityAssignmentPosition = { 220,150 }; // HEADROCK HAM 3.6
|
|
//SGPPoint OrigTalkToAllPosition = { 160, 150 };
|
|
|
|
//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 < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS ) );
|
|
|
|
// set this entry to selected
|
|
fSelectedListOfMercsForMapScreen[ bEntry ] = TRUE ;
|
|
|
|
return;
|
|
}
|
|
|
|
void ResetEntryForSelectedList( INT8 bEntry )
|
|
{
|
|
Assert( ( bEntry >= 0 ) && ( bEntry < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS ) );
|
|
|
|
// set this entry to selected
|
|
fSelectedListOfMercsForMapScreen[ bEntry ] = FALSE;
|
|
|
|
return;
|
|
}
|
|
|
|
void ResetSelectedListForMapScreen( void )
|
|
{
|
|
// WDS - make number of mercenaries, etc. be configurable
|
|
// set all the entries int he selected list to false
|
|
memset( fSelectedListOfMercsForMapScreen, FALSE, sizeof(fSelectedListOfMercsForMapScreen) );
|
|
|
|
// if we still have a valid dude selected
|
|
if ( ( bSelectedInfoChar != -1 ) && ( gCharactersList[ bSelectedInfoChar ].fValid == TRUE ) )
|
|
{
|
|
// then keep him selected
|
|
SetEntryInSelectedCharacterList( bSelectedInfoChar );
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
BOOLEAN IsEntryInSelectedListSet( INT8 bEntry )
|
|
{
|
|
Assert( ( bEntry >= 0 ) && ( bEntry < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS ) );
|
|
|
|
// is this entry in the selected list set?
|
|
|
|
return( fSelectedListOfMercsForMapScreen[ bEntry ] );
|
|
|
|
}
|
|
|
|
|
|
void ToggleEntryInSelectedList( INT8 bEntry )
|
|
{
|
|
Assert( ( bEntry >= 0 ) && ( bEntry < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS ) );
|
|
|
|
// toggle the value in the selected list
|
|
fSelectedListOfMercsForMapScreen[ bEntry ] = !( fSelectedListOfMercsForMapScreen[ bEntry ] );
|
|
|
|
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 < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; iCounter++ )
|
|
{
|
|
if( fSelectedListOfMercsForMapScreen[iCounter] == TRUE )
|
|
{
|
|
ubSelectedCnt++;
|
|
}
|
|
}
|
|
|
|
if( ubSelectedCnt > 1 )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
else
|
|
{
|
|
return( FALSE );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void ResetAssignmentsForMercsTrainingUnpaidSectorsInSelectedList( UINT8 ubMilitiaType )
|
|
{
|
|
INT32 iCounter = 0;
|
|
SOLDIERTYPE *pSoldier = NULL;
|
|
|
|
for( iCounter = 0; iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; iCounter++ )
|
|
{
|
|
// valid character?
|
|
if( gCharactersList[ iCounter ].fValid == FALSE )
|
|
{
|
|
// nope
|
|
continue;
|
|
}
|
|
|
|
pSoldier = &Menptr[ gCharactersList[ iCounter ].usSolID ];
|
|
|
|
if( pSoldier->bActive == FALSE )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (ubMilitiaType == TOWN_MILITIA)
|
|
{
|
|
if( pSoldier->bAssignment == TRAIN_TOWN )
|
|
{
|
|
if ( SectorInfo[ SECTOR( pSoldier->sSectorX, pSoldier->sSectorY ) ].fMilitiaTrainingPaid == FALSE )
|
|
{
|
|
ResumeOldAssignment( pSoldier );
|
|
}
|
|
}
|
|
}
|
|
else if (ubMilitiaType == MOBILE_MILITIA)
|
|
{
|
|
if( pSoldier->bAssignment == TRAIN_MOBILE )
|
|
{
|
|
if ( SectorInfo[ SECTOR( pSoldier->sSectorX, pSoldier->sSectorY ) ].fMobileMilitiaTrainingPaid == FALSE )
|
|
{
|
|
ResumeOldAssignment( pSoldier );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// HEADROCK HAM 3.6: Added argument for Militia Type
|
|
void ResetAssignmentOfMercsThatWereTrainingMilitiaInThisSector( INT16 sSectorX, INT16 sSectorY, UINT8 ubMilitiaType )
|
|
{
|
|
INT32 iCounter = 0;
|
|
SOLDIERTYPE *pSoldier = NULL;
|
|
|
|
for( iCounter = 0; iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; iCounter++ )
|
|
{
|
|
// valid character?
|
|
if( gCharactersList[ iCounter ].fValid == FALSE )
|
|
{
|
|
// nope
|
|
continue;
|
|
}
|
|
|
|
pSoldier = &Menptr[ gCharactersList[ iCounter ].usSolID ];
|
|
|
|
if( pSoldier->bActive == FALSE )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if( ubMilitiaType == TOWN_MILITIA )
|
|
{
|
|
if( pSoldier->bAssignment == TRAIN_TOWN )
|
|
{
|
|
if( ( pSoldier->sSectorX == sSectorX ) && ( pSoldier->sSectorY == sSectorY ) && ( pSoldier->bSectorZ == 0 ) )
|
|
{
|
|
ResumeOldAssignment( pSoldier );
|
|
}
|
|
}
|
|
}
|
|
else if (ubMilitiaType == MOBILE_MILITIA )
|
|
{
|
|
if( pSoldier->bAssignment == TRAIN_MOBILE )
|
|
{
|
|
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 < CODE_MAXIMUM_NUMBER_OF_PLAYER_SLOTS; 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 < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; iCounter++ )
|
|
{
|
|
if( gCharactersList[ iCounter ].fValid == TRUE )
|
|
{
|
|
if( fSelectedListOfMercsForMapScreen[ iCounter ] == TRUE )
|
|
{
|
|
pSoldier2 = &( Menptr[ gCharactersList[ iCounter ].usSolID ] );
|
|
|
|
// skip the guy we are
|
|
if ( pSoldier == pSoldier2 )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
|
|
// NOTE ABOUT THE VEHICLE TESTS BELOW:
|
|
// Vehicles and foot squads can't plot movement together!
|
|
// The ETAs are different, and unlike squads, vehicles can't travel everywhere!
|
|
// However, different vehicles CAN plot together, since they all travel at the same rates now
|
|
|
|
// if anchor guy is IN a vehicle
|
|
if( pSoldier->bAssignment == VEHICLE )
|
|
{
|
|
if ( !CanSoldierMoveWithVehicleId( pSoldier2, pSoldier->iVehicleId ) )
|
|
{
|
|
// reset entry for selected list
|
|
ResetEntryForSelectedList( ( INT8 )iCounter );
|
|
}
|
|
}
|
|
// if anchor guy IS a vehicle
|
|
else if ( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE )
|
|
{
|
|
if ( !CanSoldierMoveWithVehicleId( pSoldier2, pSoldier->bVehicleID ) )
|
|
{
|
|
// reset entry for selected list
|
|
ResetEntryForSelectedList( ( INT8 )iCounter );
|
|
}
|
|
}
|
|
// if this guy is IN a vehicle
|
|
else if( pSoldier2->bAssignment == VEHICLE )
|
|
{
|
|
if ( !CanSoldierMoveWithVehicleId( pSoldier, pSoldier2->iVehicleId ) )
|
|
{
|
|
// reset entry for selected list
|
|
ResetEntryForSelectedList( ( INT8 )iCounter );
|
|
}
|
|
}
|
|
// if this guy IS a vehicle
|
|
else if ( pSoldier2->flags.uiStatusFlags & SOLDIER_VEHICLE )
|
|
{
|
|
if ( !CanSoldierMoveWithVehicleId( pSoldier, pSoldier2->bVehicleID ) )
|
|
{
|
|
// reset entry for selected list
|
|
ResetEntryForSelectedList( ( INT8 )iCounter );
|
|
}
|
|
}
|
|
// reject those not a squad (vehicle handled above)
|
|
else if( pSoldier2->bAssignment >= ON_DUTY )
|
|
{
|
|
ResetEntryForSelectedList( ( INT8 )iCounter );
|
|
}
|
|
else
|
|
{
|
|
// reject those not in the same sector
|
|
if( ( pSoldier->sSectorX != pSoldier2->sSectorX ) ||
|
|
( pSoldier->sSectorY != pSoldier2->sSectorY ) ||
|
|
( pSoldier->bSectorZ != pSoldier2->bSectorZ ) )
|
|
{
|
|
ResetEntryForSelectedList( ( INT8 )iCounter );
|
|
}
|
|
|
|
// if either is between sectors, they must be in the same movement group
|
|
if ( ( pSoldier->flags.fBetweenSectors || pSoldier2->flags.fBetweenSectors ) &&
|
|
( pSoldier->ubGroupID != pSoldier2->ubGroupID ) )
|
|
{
|
|
ResetEntryForSelectedList( ( INT8 )iCounter );
|
|
}
|
|
}
|
|
|
|
// different movement groups in same sector is OK, even if they're not travelling together
|
|
}
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
void SelectUnselectedMercsWhoMustMoveWithThisGuy( void )
|
|
{
|
|
INT32 iCounter = 0;
|
|
SOLDIERTYPE *pSoldier = NULL;
|
|
|
|
|
|
for( iCounter = 0; iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; iCounter++ )
|
|
{
|
|
if( gCharactersList[ iCounter ].fValid == TRUE )
|
|
{
|
|
// if not already selected
|
|
if( fSelectedListOfMercsForMapScreen[ iCounter ] == FALSE )
|
|
{
|
|
pSoldier = &( Menptr[ gCharactersList[ iCounter ].usSolID ] );
|
|
|
|
// if on a squad or in a vehicle
|
|
if ( ( pSoldier->bAssignment < ON_DUTY ) || ( pSoldier->bAssignment == VEHICLE ) )
|
|
{
|
|
// and a member of that squad or vehicle is selected
|
|
if ( AnyMercInSameSquadOrVehicleIsSelected( pSoldier ) )
|
|
{
|
|
// then also select this guy
|
|
SetEntryInSelectedCharacterList( ( INT8 ) iCounter );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN AnyMercInSameSquadOrVehicleIsSelected( SOLDIERTYPE *pSoldier )
|
|
{
|
|
INT32 iCounter = 0;
|
|
SOLDIERTYPE *pSoldier2 = NULL;
|
|
|
|
|
|
for( iCounter = 0; iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; iCounter++ )
|
|
{
|
|
if( gCharactersList[ iCounter ].fValid == TRUE )
|
|
{
|
|
// if selected
|
|
if( fSelectedListOfMercsForMapScreen[ iCounter ] == TRUE )
|
|
{
|
|
pSoldier2 = &( Menptr[ gCharactersList[ iCounter ].usSolID ] );
|
|
|
|
// if they have the same assignment
|
|
if( pSoldier->bAssignment == pSoldier2->bAssignment )
|
|
{
|
|
// same squad?
|
|
if ( pSoldier->bAssignment < ON_DUTY )
|
|
{
|
|
return ( TRUE );
|
|
}
|
|
|
|
// same vehicle?
|
|
if ( ( pSoldier->bAssignment == VEHICLE ) && ( pSoldier->iVehicleId == pSoldier2->iVehicleId ) )
|
|
{
|
|
return ( TRUE );
|
|
}
|
|
}
|
|
|
|
// target guy is in a vehicle, and this guy IS that vehicle
|
|
if( ( pSoldier->bAssignment == VEHICLE ) && ( pSoldier2->flags.uiStatusFlags & SOLDIER_VEHICLE ) &&
|
|
( pSoldier->iVehicleId == pSoldier2->bVehicleID ) )
|
|
{
|
|
return ( TRUE );
|
|
}
|
|
|
|
// this guy is in a vehicle, and the target guy IS that vehicle
|
|
if( ( pSoldier2->bAssignment == VEHICLE ) && ( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) &&
|
|
( pSoldier2->iVehicleId == pSoldier->bVehicleID ) )
|
|
{
|
|
return ( TRUE );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return ( FALSE );
|
|
}
|
|
|
|
// WANNE: Get the refreshing high depending on the resolution and on the game type (single or multiplayer)
|
|
INT16 GetRefreshHeightForMercList( void )
|
|
{
|
|
INT16 yHeight = ( INT16 )( ( ( giMAXIMUM_NUMBER_OF_PLAYER_SLOTS + 1 ) * ( Y_SIZE + 2 ) ) + 1 );
|
|
|
|
// WANNE: Get maximum refresh height depending on the resolution!
|
|
if (iResolution >= _640x480 && iResolution < _800x600)
|
|
{
|
|
if (!is_networked)
|
|
{
|
|
if (yHeight > 224)
|
|
yHeight = 224;
|
|
}
|
|
else
|
|
{
|
|
if (yHeight > 131)
|
|
yHeight = 131;
|
|
}
|
|
}
|
|
else if (iResolution < _1024x768)
|
|
{
|
|
if (!is_networked)
|
|
{
|
|
if (yHeight > 340)
|
|
yHeight = 340;
|
|
}
|
|
else
|
|
{
|
|
if (yHeight > 249)
|
|
yHeight = 249;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!is_networked)
|
|
{
|
|
if (yHeight > 510)
|
|
yHeight = 510;
|
|
}
|
|
else
|
|
{
|
|
if (yHeight > 415)
|
|
yHeight = 415;
|
|
}
|
|
}
|
|
|
|
return yHeight;
|
|
}
|
|
|
|
void RestoreBackgroundForAssignmentGlowRegionList( void )
|
|
{
|
|
static INT32 iOldAssignmentLine = -1;
|
|
|
|
// will restore the background region of the assignment list after a glow has ceased
|
|
// ( a _LOST_MOUSE reason to the assignment region mvt callback handler )
|
|
|
|
if( fShowAssignmentMenu == TRUE )
|
|
{
|
|
// force update
|
|
ForceUpDateOfBox( ghAssignmentBox );
|
|
ForceUpDateOfBox( ghEpcBox );
|
|
ForceUpDateOfBox( ghRemoveMercAssignBox );
|
|
if( fShowSquadMenu == TRUE )
|
|
{
|
|
ForceUpDateOfBox( ghSquadBox );
|
|
}
|
|
else if( fShowTrainingMenu == TRUE )
|
|
{
|
|
ForceUpDateOfBox( ghTrainingBox );
|
|
}
|
|
|
|
}
|
|
|
|
if( fDisableDueToBattleRoster )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if( iOldAssignmentLine != giAssignHighLine )
|
|
{
|
|
INT16 yHeight = GetRefreshHeightForMercList();
|
|
|
|
// restore background
|
|
RestoreExternBackgroundRect( 66 + xResOffset, Y_START - 1, 118 + 1 - 67, yHeight );
|
|
|
|
// ARM: not good enough! must reblit the whole panel to erase glow chunk restored by help text disappearing!!!
|
|
fTeamPanelDirty = TRUE;
|
|
|
|
// set old to current
|
|
iOldAssignmentLine = giAssignHighLine;
|
|
}
|
|
|
|
// 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 )
|
|
{
|
|
INT16 yHeight = GetRefreshHeightForMercList();
|
|
|
|
// restore background
|
|
RestoreExternBackgroundRect( 182 + xResOffset, Y_START - 1, 217 + 1 - 182, yHeight );
|
|
|
|
// ARM: not good enough! must reblit the whole panel to erase glow chunk restored by help text disappearing!!!
|
|
fTeamPanelDirty = TRUE;
|
|
|
|
// set old to current
|
|
iOldDestinationLine = giDestHighLine;
|
|
}
|
|
|
|
// leave
|
|
return;
|
|
}
|
|
|
|
void RestoreBackgroundForContractGlowRegionList( void )
|
|
{
|
|
static INT32 iOldContractLine = -1;
|
|
|
|
// will restore the background region of the destinationz list after a glow has ceased
|
|
// ( a _LOST_MOUSE reason to the assignment region mvt callback handler )
|
|
|
|
if( fDisableDueToBattleRoster )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if( iOldContractLine != giContractHighLine )
|
|
{
|
|
INT16 yHeight = GetRefreshHeightForMercList();
|
|
|
|
// restore background
|
|
RestoreExternBackgroundRect( 222 + xResOffset, Y_START - 1, 250 + 1 - 222, yHeight ) ;
|
|
|
|
// ARM: not good enough! must reblit the whole panel to erase glow chunk restored by help text disappearing!!!
|
|
fTeamPanelDirty = TRUE;
|
|
|
|
// set old to current
|
|
iOldContractLine = giContractHighLine;
|
|
|
|
// reset color rotation
|
|
fResetContractGlow = TRUE;
|
|
}
|
|
|
|
// leave
|
|
return;
|
|
}
|
|
|
|
|
|
void RestoreBackgroundForSleepGlowRegionList( void )
|
|
{
|
|
static INT32 iOldSleepHighLine = -1;
|
|
|
|
// will restore the background region of the destinations list after a glow has ceased
|
|
// ( a _LOST_MOUSE reason to the assignment region mvt callback handler )
|
|
|
|
if( fDisableDueToBattleRoster )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if( iOldSleepHighLine != giSleepHighLine )
|
|
{
|
|
INT16 yHeight = GetRefreshHeightForMercList();
|
|
|
|
// restore background
|
|
RestoreExternBackgroundRect( 123 + xResOffset, Y_START - 1, 142 + 1 - 123, yHeight ) ;
|
|
|
|
// ARM: not good enough! must reblit the whole panel to erase glow chunk restored by help text disappearing!!!
|
|
fTeamPanelDirty = TRUE;
|
|
|
|
// set old to current
|
|
iOldSleepHighLine = giSleepHighLine;
|
|
|
|
// reset color rotation
|
|
fResetContractGlow = TRUE;
|
|
}
|
|
|
|
// leave
|
|
return;
|
|
}
|
|
|
|
void PlayGlowRegionSound( void )
|
|
{
|
|
// play a new message sound, if there is one playing, do nothing
|
|
static UINT32 uiSoundId = 0;
|
|
|
|
if( uiSoundId != 0 )
|
|
{
|
|
// is sound playing?..don't play new one
|
|
if( SoundIsPlaying( uiSoundId ) == TRUE )
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
// otherwise no sound playing, play one
|
|
uiSoundId = PlayJA2SampleFromFile( "Sounds\\glowclick.wav", RATE_11025, MIDVOLUME, 1 , MIDDLEPAN );
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
INT16 CharacterIsGettingPathPlotted( INT16 sCharNumber )
|
|
{
|
|
// valid character number?
|
|
if( ( sCharNumber < 0 ) || ( sCharNumber >= giMAXIMUM_NUMBER_OF_PLAYER_SLOTS ) )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
// is the character a valid one?
|
|
if( gCharactersList[ sCharNumber + FIRSTmercTOdisplay ].fValid == FALSE )
|
|
{
|
|
return ( FALSE );
|
|
}
|
|
|
|
// if the highlighted line character is also selected
|
|
if ( ( ( giDestHighLine != -1 ) && IsEntryInSelectedListSet ( ( INT8 ) giDestHighLine + FIRSTmercTOdisplay ) ) ||
|
|
( ( bSelectedDestChar != -1 ) && IsEntryInSelectedListSet ( bSelectedDestChar ) ) )
|
|
{
|
|
// then ALL selected lines will be affected
|
|
if( IsEntryInSelectedListSet( ( INT8 ) sCharNumber + FIRSTmercTOdisplay ) )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// if he is *the* selected dude
|
|
if( bSelectedDestChar == sCharNumber + FIRSTmercTOdisplay )
|
|
{
|
|
return ( TRUE );
|
|
}
|
|
|
|
// ONLY the highlighted line will be affected
|
|
if ( sCharNumber == giDestHighLine )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
}
|
|
|
|
return ( FALSE );
|
|
}
|
|
|
|
BOOLEAN IsCharacterSelectedForAssignment( INT16 sCharNumber )
|
|
{
|
|
// valid character number?
|
|
if( ( sCharNumber < 0 ) || ( sCharNumber >= giMAXIMUM_NUMBER_OF_PLAYER_SLOTS ) )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
// is the character a valid one?
|
|
if( gCharactersList[ sCharNumber + FIRSTmercTOdisplay ].fValid == FALSE )
|
|
{
|
|
return ( FALSE );
|
|
}
|
|
|
|
// if the highlighted line character is also selected
|
|
// marke strogg more mercs
|
|
if ( ( giAssignHighLine != -1 ) && IsEntryInSelectedListSet ( ( INT8 ) giAssignHighLine + FIRSTmercTOdisplay ) )
|
|
{
|
|
// then ALL selected lines will be affected
|
|
// marke strogg more mercs
|
|
if( IsEntryInSelectedListSet( ( INT8 ) sCharNumber + FIRSTmercTOdisplay ) )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// ONLY the highlighted line will be affected
|
|
if ( sCharNumber == giAssignHighLine )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
}
|
|
|
|
return( FALSE );
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN IsCharacterSelectedForSleep( INT16 sCharNumber )
|
|
{
|
|
// valid character number?
|
|
if( ( sCharNumber < 0 ) || ( sCharNumber >= giMAXIMUM_NUMBER_OF_PLAYER_SLOTS ) )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
// marke strogg more mercs
|
|
// is the character a valid one?
|
|
if( gCharactersList[ sCharNumber + FIRSTmercTOdisplay ].fValid == FALSE )
|
|
{
|
|
return ( FALSE );
|
|
}
|
|
|
|
// if the highlighted line character is also selected
|
|
if ( ( giSleepHighLine != -1 ) && IsEntryInSelectedListSet ( ( INT8 ) giSleepHighLine + FIRSTmercTOdisplay ) )
|
|
{
|
|
// then ALL selected lines will be affected
|
|
if( IsEntryInSelectedListSet( ( INT8 ) sCharNumber + FIRSTmercTOdisplay ) )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// ONLY the highlighted line will be affected
|
|
if ( sCharNumber == giSleepHighLine )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
}
|
|
|
|
return( FALSE );
|
|
}
|
|
|
|
void DisableTeamInfoPanels( void )
|
|
{
|
|
// disable team info panel
|
|
fDisableDueToBattleRoster = TRUE;
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void EnableTeamInfoPanels( void )
|
|
{
|
|
// enable team info panel
|
|
fDisableDueToBattleRoster = FALSE;
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/*
|
|
void ActivateSoldierPopup( SOLDIERTYPE *pSoldier, UINT8 ubPopupType, INT16 xp, INT16 yp )
|
|
{
|
|
// will activate the pop up for prebattle interface
|
|
|
|
// get the soldier id number
|
|
INT8 bCounter = 0;
|
|
INT8 bCharacter = -1;
|
|
|
|
|
|
for( bCounter = 0; bCounter < CODE_MAXIMUM_NUMBER_OF_PLAYER_SLOTS; bCounter++ )
|
|
{
|
|
if( gCharactersList[ bCounter ].fValid == TRUE )
|
|
{
|
|
// is this guy the passed soldier?
|
|
if( pSoldier == &( Menptr[ gCharactersList[ bCounter ].usSolID ] ) )
|
|
{
|
|
bCharacter = bCounter;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
giBoxY = ( INT32 ) yp;
|
|
// which type of box do we show?
|
|
switch( ubPopupType )
|
|
{
|
|
case( ASSIGNMENT_POPUP ):
|
|
bSelectedDestChar = -1;
|
|
bSelectedContractChar = -1;
|
|
bSelectedAssignChar = bCharacter;
|
|
if( ( pSoldier->stats.bLife > 0 ) &&( pSoldier->bAssignment != ASSIGNMENT_POW ) )
|
|
{
|
|
fShowAssignmentMenu = TRUE;
|
|
}
|
|
else
|
|
{
|
|
fShowRemoveMenu = TRUE;
|
|
}
|
|
|
|
// set box y positions
|
|
AssignmentPosition.iY = giBoxY;
|
|
TrainPosition.iY = AssignmentPosition.iY + GetFontHeight( MAP_SCREEN_FONT )* ASSIGN_MENU_TRAIN;
|
|
AttributePosition.iY = TrainPosition.iY;
|
|
SquadPosition.iY = AssignmentPosition.iY;
|
|
break;
|
|
case( DESTINATION_POPUP ):
|
|
bSelectedDestChar = bCharacter;
|
|
bSelectedContractChar = -1;
|
|
bSelectedAssignChar = -1;
|
|
|
|
// set box y value
|
|
ContractPosition.iY = giBoxY;
|
|
break;
|
|
case( CONTRACT_POPUP ):
|
|
bSelectedDestChar = -1;
|
|
bSelectedContractChar = bCharacter;
|
|
bSelectedAssignChar = -1;
|
|
RebuildContractBoxForMerc( pSoldier );
|
|
|
|
if( ( pSoldier->stats.bLife > 0 ) &&( pSoldier->bAssignment != ASSIGNMENT_POW ) )
|
|
{
|
|
fShowContractMenu = TRUE;
|
|
}
|
|
else
|
|
{
|
|
fShowRemoveMenu = TRUE;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
*/
|
|
|
|
|
|
|
|
INT32 DoMapMessageBoxWithRect( UINT8 ubStyle, const STR16 zString, UINT32 uiExitScreen, 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 )
|
|
{
|
|
SGPRect CenteringRect= {0 + xResOffset, 0, SCREEN_WIDTH - xResOffset, 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 < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; iCounter++ )
|
|
{
|
|
if( gCharactersList[iCounter].fValid == TRUE )
|
|
{
|
|
// what kind of merc
|
|
if(Menptr[gCharactersList[iCounter].usSolID].ubWhatKindOfMercAmI == MERC_TYPE__AIM_MERC)
|
|
{
|
|
// amount of time left on contract
|
|
iTimeRemaining=Menptr[gCharactersList[iCounter].usSolID].iEndofContractTime-GetWorldTotalMin();
|
|
if(iTimeRemaining >60*24)
|
|
{
|
|
// more than a day, display in green
|
|
iTimeRemaining/=(60*24);
|
|
|
|
// check if real change in contract time
|
|
if( iTimeRemaining != iOldContractTimes[ iCounter ])
|
|
{
|
|
iOldContractTimes[ iCounter ] = iTimeRemaining;
|
|
|
|
// dirty screen
|
|
fTeamPanelDirty = TRUE;
|
|
fCharacterInfoPanelDirty = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// less than a day, display hours left in red
|
|
iTimeRemaining/=60;
|
|
|
|
// check if real change in contract time
|
|
if( iTimeRemaining != iOldContractTimes[ iCounter ])
|
|
{
|
|
iOldContractTimes[ iCounter ] = iTimeRemaining;
|
|
// dirty screen
|
|
fTeamPanelDirty = TRUE;
|
|
fCharacterInfoPanelDirty = TRUE;
|
|
}
|
|
}
|
|
}
|
|
else if( Menptr[gCharactersList[iCounter].usSolID].ubWhatKindOfMercAmI == MERC_TYPE__MERC )
|
|
{
|
|
iTimeRemaining = Menptr[gCharactersList[iCounter].usSolID].iTotalContractLength;
|
|
|
|
if( iTimeRemaining != iOldContractTimes[ iCounter ])
|
|
{
|
|
iOldContractTimes[ iCounter ] = iTimeRemaining;
|
|
|
|
// dirty screen
|
|
fTeamPanelDirty = TRUE;
|
|
fCharacterInfoPanelDirty = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void HandleDisplayOfSelectedMercArrows( void )
|
|
{
|
|
INT16 sYPosition = 0;
|
|
HVOBJECT hHandle;
|
|
UINT8 ubCount = 0;
|
|
|
|
UINT16 selectedCharArrowX = xResOffset + 1;
|
|
|
|
// blit an arrow by the name of each merc in a selected list
|
|
if( bSelectedInfoChar == -1 )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// is the character valid?
|
|
if( gCharactersList[ bSelectedInfoChar ].fValid == FALSE )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if( fShowInventoryFlag == TRUE )
|
|
{
|
|
return;
|
|
}
|
|
// marke strogg more merc
|
|
if ( bSelectedInfoChar - FIRSTmercTOdisplay >= maxNumberOfMercVisibleInStrategyList )
|
|
{
|
|
FIRSTmercTOdisplay = bSelectedInfoChar - (maxNumberOfMercVisibleInStrategyList - 1) ;
|
|
}
|
|
|
|
// now blit one by the selected merc
|
|
// marke strogg more mercs
|
|
sYPosition = Y_START+( ( bSelectedInfoChar - FIRSTmercTOdisplay ) * ( Y_SIZE + 2 ) ) - 1;
|
|
|
|
GetVideoObject( &hHandle, guiSelectedCharArrow );
|
|
BltVideoObject( guiSAVEBUFFER , hHandle, 0,selectedCharArrowX, sYPosition , VO_BLT_SRCTRANSPARENCY,NULL );
|
|
|
|
// now run through the selected list of guys, an arrow for each
|
|
|
|
// marke strogg more mercs
|
|
for( ubCount = 0; ubCount < maxNumberOfMercVisibleInStrategyList; ubCount++ )
|
|
{
|
|
// marke strogg more mercs
|
|
if( gCharactersList[ ubCount + FIRSTmercTOdisplay ].fValid == TRUE )
|
|
{
|
|
// are they in the selected list or int he same mvt group as this guy
|
|
if( ( IsEntryInSelectedListSet( ubCount + FIRSTmercTOdisplay ) == TRUE ) || ( ( bSelectedDestChar != - 1 ) ? ( ( Menptr[ gCharactersList[ ubCount + FIRSTmercTOdisplay ].usSolID ].ubGroupID != 0 ) ? ( Menptr[ gCharactersList[ bSelectedDestChar ].usSolID ].ubGroupID == Menptr[ gCharactersList[ ubCount + FIRSTmercTOdisplay ].usSolID ].ubGroupID ) : FALSE ) : FALSE ) )
|
|
{
|
|
sYPosition = Y_START+( ubCount * ( Y_SIZE + 2) ) - 1;
|
|
|
|
GetVideoObject( &hHandle, guiSelectedCharArrow );
|
|
BltVideoObject( guiSAVEBUFFER , hHandle, 0,selectedCharArrowX, sYPosition , VO_BLT_SRCTRANSPARENCY,NULL );
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
void HandleDisplayOfItemPopUpForSector( INT16 sMapX, INT16 sMapY, INT16 sMapZ )
|
|
{
|
|
// handle display of item pop up for this sector
|
|
// check if anyone alive in this sector
|
|
ITEM_POOL *pItemPool = NULL;
|
|
static BOOLEAN fWasInited = FALSE;
|
|
|
|
if( bSelectedInfoChar == -1 )
|
|
{
|
|
return;
|
|
}
|
|
|
|
|
|
if( ( fWasInited == FALSE ) && ( fMapInventoryPoolInited ) )
|
|
{
|
|
if( gCharactersList[ bSelectedInfoChar ].fValid == TRUE )
|
|
{
|
|
if( ( Menptr[ gCharactersList[ bSelectedInfoChar ].usSolID].sSectorX == sMapX ) && ( Menptr[ gCharactersList[ bSelectedInfoChar ].usSolID].sSectorY == sMapY ) && ( Menptr[ gCharactersList[ bSelectedInfoChar ].usSolID].bSectorZ == sMapZ ) && ( Menptr[ gCharactersList[ bSelectedInfoChar ].usSolID].bActive ) && ( Menptr[ gCharactersList[ bSelectedInfoChar ].usSolID].stats.bLife >= OKLIFE ) )
|
|
{
|
|
// valid character
|
|
InitializeItemPickupMenu( &( Menptr[ gCharactersList[ bSelectedInfoChar ].usSolID] ), NOWHERE , pItemPool, MAP_INVEN_POOL_X, MAP_INVEN_POOL_Y, -1 );
|
|
fWasInited = TRUE;
|
|
|
|
CreateScreenMaskForInventoryPoolPopUp( );
|
|
}
|
|
}
|
|
}
|
|
else if( ( fWasInited == TRUE ) && ( fMapInventoryPoolInited == FALSE ) )
|
|
{
|
|
fWasInited = FALSE;
|
|
|
|
// now clear up the box
|
|
RemoveItemPickupMenu( );
|
|
|
|
// remove screen mask
|
|
RemoveScreenMaskForInventoryPoolPopUp( );
|
|
|
|
// drity nessacary regions
|
|
fMapPanelDirty = TRUE;
|
|
|
|
}
|
|
|
|
// showing it
|
|
if( ( fMapInventoryPoolInited ) && ( fWasInited ) )
|
|
{
|
|
SetPickUpMenuDirtyLevel( DIRTYLEVEL2 );
|
|
RenderItemPickupMenu( );
|
|
}
|
|
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
void CreateScreenMaskForInventoryPoolPopUp( void )
|
|
{
|
|
// a screen mask for the inventory pop up
|
|
MSYS_DefineRegion( &gInventoryScreenMask, 0, 0 , SCREEN_WIDTH, SCREEN_HEIGHT, MSYS_PRIORITY_HIGH - 1,
|
|
MSYS_NO_CURSOR, MSYS_NO_CALLBACK, InventoryScreenMaskBtnCallback );
|
|
|
|
}
|
|
|
|
void RemoveScreenMaskForInventoryPoolPopUp( void )
|
|
{
|
|
// remove screen mask
|
|
MSYS_RemoveRegion( &gInventoryScreenMask );
|
|
}
|
|
|
|
|
|
// invnetory screen mask btn callback
|
|
void InventoryScreenMaskBtnCallback(MOUSE_REGION * pRegion, INT32 iReason )
|
|
{
|
|
// inventory screen mask btn callback
|
|
if(iReason & MSYS_CALLBACK_REASON_LBUTTON_UP)
|
|
{
|
|
fMapInventoryPoolInited = FALSE;
|
|
}
|
|
}
|
|
|
|
void GetMoraleString( SOLDIERTYPE *pSoldier, STR16 sString )
|
|
{
|
|
INT8 bMorale = pSoldier->aiData.bMorale;
|
|
|
|
if ( pSoldier->flags.uiStatusFlags & SOLDIER_DEAD )
|
|
{
|
|
wcscpy( sString, pMoralStrings[ 5 ] );
|
|
}
|
|
else if( bMorale > 80 )
|
|
{
|
|
wcscpy( sString, pMoralStrings[ 0 ] );
|
|
}
|
|
else if( bMorale > 65 )
|
|
{
|
|
wcscpy( sString, pMoralStrings[ 1 ] );
|
|
}
|
|
else if( bMorale > 35 )
|
|
{
|
|
wcscpy( sString, pMoralStrings[ 2 ] );
|
|
}
|
|
else if( bMorale > 20 )
|
|
{
|
|
wcscpy( sString, pMoralStrings[ 3 ] );
|
|
}
|
|
else
|
|
{
|
|
wcscpy( sString, pMoralStrings[ 4 ] );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// NOTE: This doesn't use the "LeaveList" system at all!
|
|
void HandleLeavingOfEquipmentInCurrentSector( UINT32 uiMercId )
|
|
{
|
|
// just drop the stuff in the current sector
|
|
//INT32 iCounter = 0;
|
|
INT32 sGridNo, sTempGridNo;
|
|
|
|
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 && !TileIsOutOfBounds(Menptr[ uiMercId ].usStrategicInsertionData) )
|
|
{
|
|
sGridNo = Menptr[ uiMercId ].usStrategicInsertionData;
|
|
}
|
|
else
|
|
{
|
|
// Set flag for item...
|
|
sGridNo = RandomGridNo();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// ATE: Mercs can have a gridno of NOWHERE.....
|
|
sGridNo = Menptr[ uiMercId ].sGridNo;
|
|
|
|
if (TileIsOutOfBounds(sGridNo))
|
|
{
|
|
sGridNo = RandomGridNo();
|
|
|
|
sTempGridNo = FindNearestAvailableGridNoForItem( sGridNo, 5 );
|
|
|
|
if(TileIsOutOfBounds(sTempGridNo))
|
|
sTempGridNo = FindNearestAvailableGridNoForItem( sGridNo, 15 );
|
|
else
|
|
{
|
|
sGridNo = sTempGridNo;
|
|
}
|
|
}
|
|
}
|
|
|
|
for( UINT32 iCounter = 0; iCounter < Menptr[ uiMercId ].inv.size(); iCounter++ )
|
|
{
|
|
// slot found,
|
|
// check if actual item
|
|
if( Menptr[ uiMercId ].inv[ iCounter ].exists() == true )
|
|
{
|
|
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 ].pathing.bLevel, WOLRD_ITEM_FIND_SWEETSPOT_FROM_GRIDNO | WORLD_ITEM_REACHABLE, 0, 1, FALSE );
|
|
}
|
|
else
|
|
{
|
|
AddItemToPool( sGridNo, &( Menptr[ uiMercId ].inv[ iCounter ] ) , 1, Menptr[ uiMercId ].pathing.bLevel, WORLD_ITEM_REACHABLE, 0 );
|
|
}
|
|
}
|
|
}
|
|
|
|
DropKeysInKeyRing( MercPtrs[ uiMercId ], sGridNo, MercPtrs[ uiMercId ]->pathing.bLevel, 1, FALSE, 0, FALSE );
|
|
|
|
}
|
|
|
|
|
|
|
|
void HandleMercLeavingEquipmentInOmerta( UINT32 uiMercId )
|
|
{
|
|
INT32 iSlotIndex = 0;
|
|
|
|
// stash the items into a linked list hanging of a free "leave item list" slot
|
|
if( ( iSlotIndex = SetUpDropItemListForMerc( uiMercId ) ) != -1 )
|
|
{
|
|
// post event to drop it there 6 hours later
|
|
AddStrategicEvent( EVENT_MERC_LEAVE_EQUIP_IN_OMERTA, GetWorldTotalMin() + ( 6 * 60 ), iSlotIndex );
|
|
}
|
|
else
|
|
{
|
|
// otherwise there's no free slots left (shouldn't ever happen)
|
|
AssertMsg( FALSE, "HandleMercLeavingEquipmentInOmerta: No more free slots, equipment lost" );
|
|
}
|
|
}
|
|
|
|
|
|
void HandleMercLeavingEquipmentInDrassen( UINT32 uiMercId )
|
|
{
|
|
INT32 iSlotIndex = 0;
|
|
|
|
// stash the items into a linked list hanging of a free "leave item list" slot
|
|
if( ( iSlotIndex = SetUpDropItemListForMerc( uiMercId ) ) != -1 )
|
|
{
|
|
// post event to drop it there 6 hours later
|
|
AddStrategicEvent( EVENT_MERC_LEAVE_EQUIP_IN_DRASSEN, GetWorldTotalMin() + ( 6 * 60 ), iSlotIndex );
|
|
}
|
|
else
|
|
{
|
|
// otherwise there's no free slots left (shouldn't ever happen)
|
|
AssertMsg( FALSE, "HandleMercLeavingEquipmentInDrassen: No more free slots, equipment lost" );
|
|
}
|
|
}
|
|
|
|
|
|
void HandleEquipmentLeftInOmerta( UINT32 uiSlotIndex )
|
|
{
|
|
MERC_LEAVE_ITEM *pItem;
|
|
CHAR16 sString[ 128 ];
|
|
|
|
|
|
Assert( uiSlotIndex < NUM_LEAVE_LIST_SLOTS );
|
|
|
|
pItem = gpLeaveListHead[ uiSlotIndex ];
|
|
|
|
if( pItem )
|
|
{
|
|
if ( guiLeaveListOwnerProfileId[ uiSlotIndex ] != NO_PROFILE )
|
|
{
|
|
swprintf( sString, pLeftEquipmentString[ 0 ], gMercProfiles[ guiLeaveListOwnerProfileId[ uiSlotIndex ] ].zNickname );
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, sString);
|
|
}
|
|
else
|
|
{
|
|
swprintf( sString, L"A departing merc has left their equipment in Omerta." );
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, sString);
|
|
}
|
|
}
|
|
|
|
while( pItem )
|
|
{
|
|
if( gWorldSectorX != OMERTA_LEAVE_EQUIP_SECTOR_X || gWorldSectorY != OMERTA_LEAVE_EQUIP_SECTOR_Y || gbWorldSectorZ != OMERTA_LEAVE_EQUIP_SECTOR_Z )
|
|
{
|
|
// given this slot value, add to sector item list
|
|
AddItemsToUnLoadedSector( OMERTA_LEAVE_EQUIP_SECTOR_X, OMERTA_LEAVE_EQUIP_SECTOR_Y, OMERTA_LEAVE_EQUIP_SECTOR_Z, OMERTA_LEAVE_EQUIP_GRIDNO, 1, &( pItem->object ) , 0, WORLD_ITEM_REACHABLE, 0, 1, FALSE );
|
|
}
|
|
else
|
|
{
|
|
AddItemToPool( OMERTA_LEAVE_EQUIP_GRIDNO, &( pItem->object ), 1, 0, WORLD_ITEM_REACHABLE, 0 );
|
|
}
|
|
pItem = pItem->pNext;
|
|
}
|
|
|
|
FreeLeaveListSlot( uiSlotIndex );
|
|
}
|
|
|
|
|
|
|
|
void HandleEquipmentLeftInDrassen( UINT32 uiSlotIndex )
|
|
{
|
|
MERC_LEAVE_ITEM *pItem;
|
|
CHAR16 sString[ 128 ];
|
|
|
|
|
|
Assert( uiSlotIndex < NUM_LEAVE_LIST_SLOTS );
|
|
|
|
pItem = gpLeaveListHead[ uiSlotIndex ];
|
|
|
|
if( pItem )
|
|
{
|
|
if ( guiLeaveListOwnerProfileId[ uiSlotIndex ] != NO_PROFILE )
|
|
{
|
|
swprintf( sString, pLeftEquipmentString[ 1 ], gMercProfiles[ guiLeaveListOwnerProfileId[ uiSlotIndex ] ].zNickname );
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, sString);
|
|
}
|
|
else
|
|
{
|
|
swprintf( sString, L"A departing merc has left their equipment in Drassen." );
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, sString);
|
|
}
|
|
}
|
|
|
|
while( pItem )
|
|
{
|
|
if( gWorldSectorX != 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->object ) , 0, WORLD_ITEM_REACHABLE, 0, 1, FALSE );
|
|
}
|
|
else
|
|
{
|
|
AddItemToPool( 10433, &( pItem->object ), 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 *object, UINT32 uiSlotIndex )
|
|
{
|
|
MERC_LEAVE_ITEM *pItem, *pCurrentItem;
|
|
|
|
Assert( uiSlotIndex < NUM_LEAVE_LIST_SLOTS );
|
|
|
|
|
|
if( object == NULL )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
// allocate space
|
|
pItem = new MERC_LEAVE_ITEM;
|
|
|
|
// copy object
|
|
pItem->object = *object;
|
|
|
|
// nobody afterwards
|
|
pItem->pNext = NULL;
|
|
|
|
// now add to list in this index slot
|
|
pCurrentItem = gpLeaveListHead[ uiSlotIndex ];
|
|
|
|
if( pCurrentItem == NULL )
|
|
{
|
|
gpLeaveListHead[ uiSlotIndex ] = pItem;
|
|
return( TRUE );
|
|
}
|
|
|
|
// move through list
|
|
while( pCurrentItem->pNext )
|
|
{
|
|
pCurrentItem = pCurrentItem->pNext;
|
|
}
|
|
|
|
// found
|
|
pCurrentItem->pNext = pItem;
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
// release memory for all items in this slot's leave item list
|
|
void FreeLeaveListSlot( UINT32 uiSlotIndex )
|
|
{
|
|
MERC_LEAVE_ITEM *pCurrent = NULL, *pTemp = NULL;
|
|
|
|
Assert( uiSlotIndex < NUM_LEAVE_LIST_SLOTS );
|
|
|
|
pCurrent = gpLeaveListHead[ uiSlotIndex ];
|
|
|
|
// go through nodes and free them
|
|
while( pCurrent )
|
|
{
|
|
pTemp = pCurrent->pNext;
|
|
MemFree( pCurrent );
|
|
pCurrent = pTemp;
|
|
}
|
|
|
|
gpLeaveListHead[ uiSlotIndex ] = NULL;
|
|
}
|
|
|
|
|
|
|
|
INT32 FindFreeSlotInLeaveList( void )
|
|
{
|
|
INT32 iCounter = 0;
|
|
|
|
for( iCounter = 0; iCounter < NUM_LEAVE_LIST_SLOTS; iCounter++ )
|
|
{
|
|
if( gpLeaveListHead[ iCounter ] == NULL )
|
|
{
|
|
return( iCounter );
|
|
}
|
|
}
|
|
|
|
return( -1 );
|
|
}
|
|
|
|
|
|
INT32 SetUpDropItemListForMerc( UINT32 uiMercId )
|
|
{
|
|
// will set up a drop list for this grunt, remove items from inventory, and profile
|
|
INT32 iSlotIndex = -1;
|
|
|
|
iSlotIndex = FindFreeSlotInLeaveList( );
|
|
if( iSlotIndex == -1 )
|
|
{
|
|
return( -1 );
|
|
}
|
|
|
|
for( UINT32 iCounter = 0; iCounter < Menptr[ uiMercId ].inv.size(); iCounter++ )
|
|
{
|
|
// slot found,
|
|
// check if actual item
|
|
if( Menptr[ uiMercId ].inv[ iCounter ].exists() == true )
|
|
{
|
|
// make a linked list of the items left behind, with the ptr to its head in this free slot
|
|
AddItemToLeaveIndex( &( Menptr[ uiMercId ].inv[ iCounter ] ), iSlotIndex );
|
|
|
|
// store owner's profile id for the items added to this leave slot index
|
|
SetUpMercAboutToLeaveEquipment( Menptr[ uiMercId ].ubProfile, iSlotIndex );
|
|
}
|
|
}
|
|
|
|
// ATE: Added this to drop keyring keys - the 2nd last paramter says to add it to a leave list...
|
|
// the gridno, level and visiblity are ignored
|
|
DropKeysInKeyRing( MercPtrs[ uiMercId ], NOWHERE, 0, 0, TRUE, iSlotIndex, FALSE );
|
|
|
|
// zero out profiles
|
|
gMercProfiles[ Menptr[ uiMercId ].ubProfile ].clearInventory();
|
|
|
|
return( iSlotIndex );
|
|
}
|
|
|
|
|
|
// store owner's profile id for the items added to this leave slot index
|
|
void SetUpMercAboutToLeaveEquipment( UINT32 ubProfileId, UINT32 uiSlotIndex )
|
|
{
|
|
Assert( uiSlotIndex < NUM_LEAVE_LIST_SLOTS );
|
|
|
|
// store the profile ID of this merc in the same slot that the items are gonna be dropped in
|
|
guiLeaveListOwnerProfileId[ uiSlotIndex ] = ubProfileId;
|
|
|
|
}
|
|
|
|
void HandleGroupAboutToArrive( void )
|
|
{
|
|
// reblit map to change the color of the "people in motion" marker
|
|
fMapPanelDirty = TRUE;
|
|
|
|
return;
|
|
}
|
|
|
|
void CreateMapStatusBarsRegion( void )
|
|
{
|
|
MSYS_DefineRegion( &gMapStatusBarsRegion, BAR_INFO_X + xResOffset - 3, BAR_INFO_Y - 42,(INT16)( BAR_INFO_X + xResOffset + 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->stats.bLife != 0 )
|
|
{
|
|
if ( AM_A_ROBOT( MercPtrs[ gCharactersList[ bSelectedInfoChar ].usSolID ] ) )
|
|
{
|
|
// robot (condition only)
|
|
swprintf( sString, L"%s: %d/%d",
|
|
pMapScreenStatusStrings[ 3 ], pSoldier->stats.bLife, pSoldier->stats.bLifeMax );
|
|
}
|
|
else if ( Menptr[ gCharactersList[ bSelectedInfoChar ].usSolID ].flags.uiStatusFlags & SOLDIER_VEHICLE )
|
|
{
|
|
// vehicle (condition/fuel)
|
|
swprintf( sString, L"%s: %d/%d, %s: %d/%d",
|
|
pMapScreenStatusStrings[ 3 ], pSoldier->stats.bLife, pSoldier->stats.bLifeMax,
|
|
pMapScreenStatusStrings[ 4 ], pSoldier->bBreath, pSoldier->bBreathMax );
|
|
}
|
|
else
|
|
{
|
|
// person (health/energy/morale)
|
|
GetMoraleString( pSoldier, pMoraleStr );
|
|
swprintf( sString, L"%s: %d/%d, %s: %d/%d, %s: %s",
|
|
pMapScreenStatusStrings[ 0 ], pSoldier->stats.bLife, pSoldier->stats.bLifeMax,
|
|
pMapScreenStatusStrings[ 1 ], pSoldier->bBreath, pSoldier->bBreathMax,
|
|
pMapScreenStatusStrings[ 2 ], pMoraleStr );
|
|
}
|
|
}
|
|
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 < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; iCounter++ )
|
|
{
|
|
if( gCharactersList[ iCounter].fValid == TRUE )
|
|
{
|
|
if( gCharactersList[ iCounter].usSolID == pSoldier->ubID )
|
|
{
|
|
ChangeSelectedInfoChar( ( INT8 )iCounter, TRUE );
|
|
bSelectedContractChar = ( INT8 )iCounter;
|
|
fShowContractMenu = TRUE;
|
|
|
|
// create
|
|
RebuildContractBoxForMerc( pSoldier );
|
|
|
|
fTeamPanelDirty = TRUE;
|
|
fCharacterInfoPanelDirty = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void HandleMAPUILoseCursorFromOtherScreen( void )
|
|
{
|
|
// rerender map without cursors
|
|
fMapPanelDirty = TRUE;
|
|
|
|
if ( fInMapMode )
|
|
{
|
|
RenderMapRegionBackground( );
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
void UpdateMapScreenAssignmentPositions( void )
|
|
{
|
|
// set the position of the pop up boxes
|
|
SGPPoint pPoint;
|
|
|
|
|
|
if( guiCurrentScreen != MAP_SCREEN )
|
|
{
|
|
return;
|
|
}
|
|
|
|
|
|
if( bSelectedAssignChar == -1 )
|
|
{
|
|
if( gfPreBattleInterfaceActive == FALSE )
|
|
{
|
|
giBoxY = 0;
|
|
}
|
|
return;
|
|
}
|
|
|
|
if( gCharactersList[ bSelectedAssignChar ].fValid == FALSE )
|
|
{
|
|
if( gfPreBattleInterfaceActive == FALSE )
|
|
{
|
|
giBoxY = 0;
|
|
}
|
|
return;
|
|
}
|
|
|
|
if( gfPreBattleInterfaceActive )
|
|
{
|
|
// do nothing
|
|
}
|
|
else
|
|
{
|
|
// marke strogg more mercs
|
|
giBoxY = ( Y_START + ( bSelectedAssignChar - FIRSTmercTOdisplay ) * ( Y_SIZE + 2 ) );
|
|
}
|
|
|
|
AssignmentPosition.iY = giBoxY;
|
|
|
|
AttributePosition.iY = TrainPosition.iY = AssignmentPosition.iY + ( GetFontHeight( MAP_SCREEN_FONT ) + 2 )* ASSIGN_MENU_TRAIN;
|
|
|
|
VehiclePosition.iY = AssignmentPosition.iY + ( GetFontHeight( MAP_SCREEN_FONT ) + 2 ) * ASSIGN_MENU_VEHICLE;
|
|
SquadPosition.iY = AssignmentPosition.iY;
|
|
|
|
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 );
|
|
}
|
|
|
|
// HEADROCK HAM 3.6: Facility Menu
|
|
if( fShowFacilityMenu )
|
|
{
|
|
GetBoxPosition( ghFacilityBox, &pPoint);
|
|
pPoint.iY = giBoxY + ( GetFontHeight( MAP_SCREEN_FONT ) + 2 ) * ASSIGN_MENU_FACILITY;
|
|
|
|
SetBoxPosition( ghFacilityBox, pPoint );
|
|
}
|
|
|
|
// HEADROCK HAM 3.6: Facility Sub-menu
|
|
if( fShowFacilityAssignmentMenu )
|
|
{
|
|
GetBoxPosition( ghFacilityAssignmentBox, &pPoint);
|
|
|
|
pPoint.iY = giBoxY + ( GetFontHeight( MAP_SCREEN_FONT ) + 2 ) * ASSIGN_MENU_FACILITY;
|
|
|
|
SetBoxPosition( ghFacilityAssignmentBox, pPoint );
|
|
}
|
|
|
|
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[ CODE_MAXIMUM_NUMBER_OF_PLAYER_SLOTS ];
|
|
UINT8 ubNumMercs = 0;
|
|
UINT8 ubChosenMerc;
|
|
|
|
|
|
// if traversing tactically, don't do this, unless time compression was required for some reason (don't go to sector)
|
|
if ( ( gfTacticalTraversal || ( pGroup->ubSectorZ > 0 ) ) && !IsTimeBeingCompressed() )
|
|
{
|
|
return;
|
|
}
|
|
|
|
|
|
// Let's choose somebody in group.....
|
|
pPlayer = pGroup->pPlayerList;
|
|
|
|
while( pPlayer != NULL )
|
|
{
|
|
pSoldier = pPlayer->pSoldier;
|
|
Assert( pSoldier );
|
|
|
|
if ( pSoldier->stats.bLife >= OKLIFE && !( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) &&
|
|
!AM_A_ROBOT( pSoldier ) && !AM_AN_EPC( pSoldier ) && !pSoldier->flags.fMercAsleep )
|
|
{
|
|
ubMercsInGroup[ ubNumMercs ] = pSoldier->ubID;
|
|
ubNumMercs++;
|
|
}
|
|
|
|
pPlayer = pPlayer->next;
|
|
}
|
|
|
|
// At least say quote....
|
|
if ( ubNumMercs > 0 )
|
|
{
|
|
ubChosenMerc = (UINT8)Random( ubNumMercs );
|
|
pSoldier = MercPtrs[ ubMercsInGroup[ ubChosenMerc ] ];
|
|
|
|
TacticalCharacterDialogue( pSoldier, usQuoteNum );
|
|
}
|
|
}
|
|
|
|
|
|
INT32 GetNumberOfPeopleInCharacterList( void )
|
|
{
|
|
INT32 iCounter = 0, iCount = 0;
|
|
|
|
// get the number of valid mercs in the mapscreen character list
|
|
for( iCounter = 0; iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; iCounter++ )
|
|
{
|
|
if( gCharactersList[ iCounter].fValid == TRUE )
|
|
{
|
|
// another valid character
|
|
iCount++;
|
|
}
|
|
}
|
|
|
|
return( iCount );
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN ValidSelectableCharForNextOrPrev( INT32 iNewCharSlot )
|
|
{
|
|
BOOLEAN fHoldingItem = FALSE;
|
|
|
|
// if holding an item
|
|
if ( ( gMPanelRegion.Cursor == EXTERN_CURSOR ) || gpItemPointer || fMapInventoryItem )
|
|
{
|
|
fHoldingItem = TRUE;
|
|
}
|
|
|
|
|
|
// if showing merc inventory, or holding an item
|
|
if ( fShowInventoryFlag || fHoldingItem )
|
|
{
|
|
// the new guy must have accessible inventory
|
|
if ( !MapCharacterHasAccessibleInventory( ( INT8 ) iNewCharSlot ) )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
}
|
|
|
|
|
|
if ( fHoldingItem )
|
|
{
|
|
return ( MapscreenCanPassItemToCharNum( iNewCharSlot ) );
|
|
}
|
|
else
|
|
{
|
|
return( TRUE );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN MapscreenCanPassItemToCharNum( INT32 iNewCharSlot )
|
|
{
|
|
SOLDIERTYPE *pNewSoldier;
|
|
SOLDIERTYPE *pOldSoldier;
|
|
|
|
|
|
// assumes we're holding an item
|
|
Assert( ( gMPanelRegion.Cursor == EXTERN_CURSOR ) || gpItemPointer || fMapInventoryItem );
|
|
|
|
|
|
// if in a hostile sector, disallow
|
|
if ( gTacticalStatus.fEnemyInSector )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
// can't pass items to nobody!
|
|
if ( iNewCharSlot == -1 )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
|
|
pNewSoldier = MercPtrs[ gCharactersList[ iNewCharSlot ].usSolID ];
|
|
|
|
|
|
// if showing sector inventory, and the item came from there
|
|
if ( fShowMapInventoryPool && !gpItemPointerSoldier && fMapInventoryItem )
|
|
{
|
|
// disallow passing items to anyone not in that sector
|
|
if ( pNewSoldier->sSectorX != sSelMapX ||
|
|
pNewSoldier->sSectorY != sSelMapY ||
|
|
pNewSoldier->bSectorZ != ( INT8 )( iCurrentMapSectorZ ) )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
if ( pNewSoldier->flags.fBetweenSectors )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
}
|
|
|
|
|
|
// if we know who it came from
|
|
if ( gpItemPointerSoldier )
|
|
{
|
|
pOldSoldier = gpItemPointerSoldier;
|
|
}
|
|
else
|
|
{
|
|
// it came from either the currently selected merc, or the sector inventory
|
|
if ( fMapInventoryItem || ( bSelectedInfoChar == -1 ) )
|
|
{
|
|
pOldSoldier = NULL;
|
|
}
|
|
else
|
|
{
|
|
pOldSoldier = MercPtrs[ gCharactersList[ bSelectedInfoChar ].usSolID ];
|
|
}
|
|
}
|
|
|
|
|
|
// if another merc had it previously
|
|
if ( pOldSoldier != NULL )
|
|
{
|
|
// disallow passing items to a merc not in the same sector
|
|
if ( pNewSoldier->sSectorX != pOldSoldier->sSectorX ||
|
|
pNewSoldier->sSectorY != pOldSoldier->sSectorY ||
|
|
pNewSoldier->bSectorZ != pOldSoldier->bSectorZ )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
// if on the road
|
|
if ( pNewSoldier->flags.fBetweenSectors )
|
|
{
|
|
// other guy must also be on the road...
|
|
if ( !pOldSoldier->flags.fBetweenSectors )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
// only exchanges between those is the same squad or vehicle are permitted
|
|
if ( pNewSoldier->bAssignment != pOldSoldier->bAssignment )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
// if in vehicles, make sure it's the same one
|
|
if ( ( pNewSoldier->bAssignment == VEHICLE ) && ( pNewSoldier->iVehicleId != pOldSoldier->iVehicleId ) )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// passed all tests
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
|
|
void GoToNextCharacterInList( void )
|
|
{
|
|
INT32 iCounter = 0, iCount = 0;
|
|
|
|
|
|
if( fShowDescriptionFlag == TRUE )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if( ( bSelectedDestChar != -1 ) || ( fPlotForHelicopter == TRUE ) )
|
|
{
|
|
AbortMovementPlottingMode( );
|
|
}
|
|
|
|
// is the current guy invalid or the first one?
|
|
if( ( bSelectedInfoChar == -1 )|| ( bSelectedInfoChar == giMAXIMUM_NUMBER_OF_PLAYER_SLOTS ) )
|
|
{
|
|
iCount = 0;
|
|
}
|
|
else
|
|
{
|
|
iCount = bSelectedInfoChar + 1;
|
|
}
|
|
|
|
for( iCounter = 0; iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; iCounter++ )
|
|
{
|
|
if ( ( gCharactersList[ iCount ].fValid ) && ( iCount < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS ) && ValidSelectableCharForNextOrPrev( iCount ) )
|
|
{
|
|
ChangeSelectedInfoChar( ( INT8 )iCount, TRUE );
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
iCount++;
|
|
|
|
if( iCount >= giMAXIMUM_NUMBER_OF_PLAYER_SLOTS )
|
|
{
|
|
iCount = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// WANNE: Jump to first character in list when pressing PageUp
|
|
void GoToFirstCharacterInList( void )
|
|
{
|
|
INT32 iCounter = 0, iCount = 0;
|
|
|
|
if( fShowDescriptionFlag == TRUE )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if( ( bSelectedDestChar != -1 ) || ( fPlotForHelicopter == TRUE ) )
|
|
{
|
|
AbortMovementPlottingMode( );
|
|
}
|
|
|
|
// now run through the list and find first prev guy
|
|
for( iCounter = 0; iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; iCounter++ )
|
|
{
|
|
if ( ( gCharactersList[ iCounter ].fValid ) && ( iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS ) && ValidSelectableCharForNextOrPrev( iCounter ) )
|
|
{
|
|
ChangeSelectedInfoChar( ( INT8 )iCounter, TRUE );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// WANNE: Jump to last character in list when pressing PageDown
|
|
void GoToLastCharacterInList( void )
|
|
{
|
|
INT32 iCounter = 0, iCount = 0;
|
|
|
|
if( fShowDescriptionFlag == TRUE )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if( ( bSelectedDestChar != -1 ) || ( fPlotForHelicopter == TRUE ) )
|
|
{
|
|
AbortMovementPlottingMode( );
|
|
}
|
|
|
|
// now run through the list and find first prev guy
|
|
for( iCounter = giMAXIMUM_NUMBER_OF_PLAYER_SLOTS - 1; iCounter > 0; iCounter-- )
|
|
{
|
|
if ( ( gCharactersList[ iCounter ].fValid ) && ( iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS ) && ValidSelectableCharForNextOrPrev( iCounter ) )
|
|
{
|
|
ChangeSelectedInfoChar( ( INT8 )iCounter, TRUE );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void GoToPrevCharacterInList( void )
|
|
{
|
|
INT32 iCounter = 0, iCount = 0;
|
|
|
|
|
|
if( fShowDescriptionFlag == TRUE )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if( ( bSelectedDestChar != -1 ) || ( fPlotForHelicopter == TRUE ) )
|
|
{
|
|
AbortMovementPlottingMode( );
|
|
}
|
|
|
|
// is the current guy invalid or the first one?
|
|
if( ( bSelectedInfoChar == -1 ) || ( bSelectedInfoChar == 0 ) )
|
|
{
|
|
iCount = giMAXIMUM_NUMBER_OF_PLAYER_SLOTS;
|
|
}
|
|
else
|
|
{
|
|
iCount = bSelectedInfoChar - 1;
|
|
}
|
|
|
|
// now run through the list and find first prev guy
|
|
for( iCounter = 0; iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; iCounter++ )
|
|
{
|
|
if ( ( gCharactersList[ iCount ].fValid ) && ( iCount < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS ) && ValidSelectableCharForNextOrPrev( iCount ) )
|
|
{
|
|
ChangeSelectedInfoChar( ( INT8 )iCount, TRUE );
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
iCount--;
|
|
|
|
if( iCount < 0 )
|
|
{
|
|
iCount = giMAXIMUM_NUMBER_OF_PLAYER_SLOTS;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//void HandleMinerEvent( UINT8 bMinerNumber, INT16 sSectorX, INT16 sSectorY, INT16 sQuoteNumber, BOOLEAN fForceMapscreen )
|
|
void HandleMinerEvent( UINT8 ubHeadMinerIndex, INT16 sSectorX, INT16 sSectorY, INT16 sQuoteNumber, BOOLEAN fForceMapscreen )
|
|
{
|
|
BOOLEAN fFromMapscreen = FALSE;
|
|
|
|
|
|
if ( guiCurrentScreen == MAP_SCREEN )
|
|
{
|
|
fFromMapscreen = TRUE;
|
|
}
|
|
else
|
|
{
|
|
// if transition to mapscreen is required
|
|
if ( fForceMapscreen )
|
|
{
|
|
// switch to mapscreen so we can flash the mine sector the guy is talking about
|
|
EnterMapScreen( );
|
|
fFromMapscreen = TRUE;
|
|
}
|
|
}
|
|
|
|
HEAD_MINER_TYPE* miner = &gHeadMinerData[ubHeadMinerIndex];
|
|
|
|
if ( fFromMapscreen )
|
|
{
|
|
// if not showing map surface level
|
|
if ( iCurrentMapSectorZ != 0 )
|
|
{
|
|
// switch to it, because the miner locators wouldn't show up if we're underground while they speak
|
|
ChangeSelectedMapSector( sSelMapX, sSelMapY, 0 );
|
|
}
|
|
|
|
// set up the mine sector flasher
|
|
gsSectorLocatorX = sSectorX;
|
|
gsSectorLocatorY = sSectorY;
|
|
|
|
fMapPanelDirty = TRUE;
|
|
|
|
// post dialogue events for miners to say this quote and flash the sector where his mine is
|
|
//CharacterDialogueWithSpecialEvent( ( UINT8 )uiExternalFaceProfileIds[ bMinerNumber ], sQuoteNumber, bMinerNumber , DIALOGUE_EXTERNAL_NPC_UI , FALSE , FALSE , DIALOGUE_SPECIAL_EVENT_MINESECTOREVENT, START_RED_SECTOR_LOCATOR, 1 );
|
|
//CharacterDialogue( ( UINT8 )uiExternalFaceProfileIds[ bMinerNumber ], sQuoteNumber, ( UINT8 )( UINT8 )uiExternalStaticNPCFaces[ bMinerNumber ], DIALOGUE_EXTERNAL_NPC_UI, FALSE , FALSE );
|
|
//CharacterDialogueWithSpecialEvent( ( UINT8 )uiExternalFaceProfileIds[ bMinerNumber ], sQuoteNumber, bMinerNumber , DIALOGUE_EXTERNAL_NPC_UI , FALSE , FALSE , DIALOGUE_SPECIAL_EVENT_MINESECTOREVENT, STOP_RED_SECTOR_LOCATOR, 1 );
|
|
CharacterDialogueWithSpecialEvent( ( UINT8 )miner->usProfileId, sQuoteNumber, miner->ubExternalFaceIndex, DIALOGUE_EXTERNAL_NPC_UI, FALSE, FALSE, DIALOGUE_SPECIAL_EVENT_MINESECTOREVENT, START_RED_SECTOR_LOCATOR, 1 );
|
|
CharacterDialogue( ( UINT8 )miner->usProfileId, sQuoteNumber, ( UINT8 )uiExternalStaticNPCFaces[miner->ubExternalFaceIndex], DIALOGUE_EXTERNAL_NPC_UI, FALSE, FALSE );
|
|
CharacterDialogueWithSpecialEvent( ( UINT8 )miner->usProfileId, sQuoteNumber, miner->ubExternalFaceIndex, DIALOGUE_EXTERNAL_NPC_UI, FALSE, FALSE, DIALOGUE_SPECIAL_EVENT_MINESECTOREVENT, STOP_RED_SECTOR_LOCATOR, 1 );
|
|
}
|
|
else // stay in tactical
|
|
{
|
|
// no need to to highlight mine sector
|
|
//CharacterDialogue( ( UINT8 )uiExternalFaceProfileIds[ bMinerNumber ], sQuoteNumber, ( UINT8 )( UINT8 )uiExternalStaticNPCFaces[ bMinerNumber ], DIALOGUE_EXTERNAL_NPC_UI, FALSE , FALSE );
|
|
CharacterDialogue( ( UINT8 )miner->usProfileId, sQuoteNumber, ( UINT8 )uiExternalStaticNPCFaces[miner->ubExternalFaceIndex], DIALOGUE_EXTERNAL_NPC_UI, FALSE , FALSE );
|
|
}
|
|
}
|
|
|
|
|
|
void SetUpAnimationOfMineSectors( INT32 iEvent )
|
|
{
|
|
// set up the animation of mine sectors
|
|
switch( iEvent )
|
|
{
|
|
case START_RED_SECTOR_LOCATOR:
|
|
gubBlitSectorLocatorCode = LOCATOR_COLOR_RED;
|
|
break;
|
|
|
|
case START_YELLOW_SECTOR_LOCATOR:
|
|
gubBlitSectorLocatorCode = LOCATOR_COLOR_YELLOW;
|
|
break;
|
|
|
|
case STOP_RED_SECTOR_LOCATOR:
|
|
case STOP_YELLOW_SECTOR_LOCATOR:
|
|
TurnOffSectorLocator();
|
|
break;
|
|
}
|
|
}
|
|
|
|
void ShutDownUserDefineHelpTextRegions( void )
|
|
{
|
|
// dirty the tactical panel
|
|
fInterfacePanelDirty = DIRTYLEVEL2;
|
|
SetRenderFlags( RENDER_FLAG_FULL );
|
|
|
|
//dirty the map panel
|
|
StopMapScreenHelpText( );
|
|
|
|
//r eset tactical flag too
|
|
StopShowingInterfaceFastHelpText( );
|
|
}
|
|
|
|
|
|
// thsi will setup the fast help text regions that are unrelated to mouse regions
|
|
// user is to pass in the x,y position of the box, the width to wrap the strings and the string itself
|
|
BOOLEAN SetUpFastHelpListRegions( INT32 iXPosition[], INT32 iYPosition[], INT32 iWidth[], STR16 sString[], INT32 iSize )
|
|
{
|
|
INT32 iCounter = 0;
|
|
|
|
// reset the size
|
|
giSizeOfInterfaceFastHelpTextList = 0;
|
|
|
|
for( iCounter = 0; iCounter < iSize; iCounter++ )
|
|
{
|
|
|
|
// forgiving way of making sure we don't go too far
|
|
CHECKF( iCounter < MAX_MAPSCREEN_FAST_HELP );
|
|
|
|
// now copy over info
|
|
pFastHelpMapScreenList[ iCounter ].iX = iXPosition[ iCounter ];
|
|
pFastHelpMapScreenList[ iCounter ].iY = iYPosition[ iCounter ];
|
|
pFastHelpMapScreenList[ iCounter ].iW = iWidth[ iCounter ];
|
|
|
|
// copy string
|
|
wcscpy( pFastHelpMapScreenList[ iCounter ].FastHelpText, sString[ iCounter ] );
|
|
|
|
// update the size
|
|
giSizeOfInterfaceFastHelpTextList = iCounter + 1;
|
|
}
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
// handle the actual showing of the interface fast help text
|
|
void HandleShowingOfTacticalInterfaceFastHelpText( void )
|
|
{
|
|
static BOOLEAN fTextActive = FALSE;
|
|
|
|
if( fInterfaceFastHelpTextActive )
|
|
{
|
|
DisplayFastHelpRegions( pFastHelpMapScreenList, giSizeOfInterfaceFastHelpTextList );
|
|
|
|
PauseGame();
|
|
|
|
// lock out the screen
|
|
SetUpShutDownMapScreenHelpTextScreenMask( );
|
|
|
|
gfIgnoreScrolling = TRUE;
|
|
|
|
// the text is active
|
|
fTextActive = TRUE;
|
|
|
|
}
|
|
else if( ( fInterfaceFastHelpTextActive == FALSE ) && ( fTextActive ) )
|
|
{
|
|
fTextActive = FALSE;
|
|
UnPauseGame();
|
|
gfIgnoreScrolling = FALSE;
|
|
|
|
// shut down
|
|
ShutDownUserDefineHelpTextRegions( );
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
// start showing fast help text
|
|
void StartShowingInterfaceFastHelpText( void )
|
|
{
|
|
fInterfaceFastHelpTextActive = TRUE;
|
|
}
|
|
|
|
// stop showing interface fast help text
|
|
void StopShowingInterfaceFastHelpText( void )
|
|
{
|
|
fInterfaceFastHelpTextActive = FALSE;
|
|
}
|
|
|
|
|
|
// is the interface text up?
|
|
BOOLEAN IsTheInterfaceFastHelpTextActive( void )
|
|
{
|
|
return( fInterfaceFastHelpTextActive );
|
|
}
|
|
|
|
|
|
// display all the regions in the list
|
|
void DisplayFastHelpRegions( FASTHELPREGION *pRegion, INT32 iSize )
|
|
{
|
|
INT32 iCounter = 0;
|
|
|
|
// run through and show all the regions
|
|
for( iCounter = 0; iCounter < iSize; iCounter++ )
|
|
{
|
|
DisplayUserDefineHelpTextRegions( &( pRegion[ iCounter ] ) );
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
// show one region
|
|
void DisplayUserDefineHelpTextRegions( FASTHELPREGION *pRegion )
|
|
{
|
|
UINT16 usFillColor;
|
|
INT32 iX,iY,iW,iH;
|
|
UINT8 *pDestBuf;
|
|
UINT32 uiDestPitchBYTES;
|
|
|
|
|
|
// grab the color for the background region
|
|
usFillColor = Get16BPPColor(FROMRGB(250, 240, 188));
|
|
|
|
|
|
iX = pRegion->iX;
|
|
iY = pRegion->iY;
|
|
// get the width and height of the string
|
|
iW = (INT32)( pRegion->iW ) + 14;
|
|
iH = IanWrappedStringHeight( ( UINT16 )iX, ( UINT16 )iY, ( UINT16 )( pRegion->iW ), 0, FONT10ARIAL, FONT_BLACK, pRegion->FastHelpText, FONT_BLACK, TRUE, 0 );
|
|
|
|
// tack on the outer border
|
|
iH += 14;
|
|
|
|
// gone not far enough?
|
|
if ( iX < 0 )
|
|
iX = 0;
|
|
|
|
// gone too far
|
|
if ( ( pRegion->iX + iW ) >= SCREEN_WIDTH )
|
|
iX = (SCREEN_WIDTH - iW - 4);
|
|
|
|
// what about the y value?
|
|
iY = (INT32)pRegion->iY - ( iH * 3 / 4);
|
|
|
|
// not far enough
|
|
if (iY < 0)
|
|
iY = 0;
|
|
|
|
// too far
|
|
if ( (iY + iH) >= SCREEN_HEIGHT )
|
|
iY = (SCREEN_HEIGHT - iH - 15);
|
|
|
|
pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES );
|
|
SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT );
|
|
RectangleDraw( TRUE, iX + 1, iY + 1, iX + iW - 1, iY + iH - 1, Get16BPPColor( FROMRGB( 65, 57, 15 ) ), pDestBuf );
|
|
RectangleDraw( TRUE, iX, iY, iX + iW - 2, iY + iH - 2, Get16BPPColor( FROMRGB( 227, 198, 88 ) ), pDestBuf );
|
|
UnLockVideoSurface( FRAME_BUFFER );
|
|
ShadowVideoSurfaceRect( FRAME_BUFFER, iX + 2, iY + 2, iX + iW - 3, iY + iH - 3 );
|
|
ShadowVideoSurfaceRect( FRAME_BUFFER, iX + 2, iY + 2, iX + iW - 3, iY + iH - 3 );
|
|
|
|
// fillt he video surface areas
|
|
//ColorFillVideoSurfaceArea(FRAME_BUFFER, iX, iY, (iX + iW), (iY + iH), 0);
|
|
//ColorFillVideoSurfaceArea(FRAME_BUFFER, (iX + 1), (iY + 1), (iX + iW - 1), (iY + iH - 1), usFillColor);
|
|
|
|
SetFont( FONT10ARIAL );
|
|
SetFontForeground( FONT_BEIGE );
|
|
|
|
iH = ( INT32 )DisplayWrappedString( ( INT16 )( iX + 10 ), ( INT16 )( iY + 6 ), ( INT16 )pRegion->iW, 0, FONT10ARIAL, FONT_BEIGE, pRegion->FastHelpText, FONT_NEARBLACK, TRUE, 0 );
|
|
|
|
iHeightOfInitFastHelpText = iH + 20;
|
|
|
|
InvalidateRegion( iX, iY, (iX + iW) , (iY + iH + 20 ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
extern void DisplayHelpTokenizedString( const STR16 pStringA, INT16 sX, INT16 sY );
|
|
extern INT16 GetNumberOfLinesInHeight( const STR16 pStringA );
|
|
extern INT16 GetWidthOfString( const STR16 pStringA );
|
|
|
|
void DisplaySoldierToolTip( FASTHELPREGION *pRegion )
|
|
{
|
|
UINT16 usFillColor;
|
|
INT32 iX,iY,iW,iH;
|
|
UINT8 *pDestBuf;
|
|
UINT32 uiDestPitchBYTES;
|
|
|
|
|
|
// grab the color for the background region
|
|
usFillColor = Get16BPPColor(FROMRGB(250, 240, 188));
|
|
|
|
|
|
iX = pRegion->iX;
|
|
iY = pRegion->iY;
|
|
// get the width and height of the string
|
|
//iW = (INT32)( pRegion->iW ) + 14;
|
|
iW = (INT32)GetWidthOfString( pRegion->FastHelpText ) + 10;
|
|
|
|
//iH = IanWrappedStringHeight( ( UINT16 )iX, ( UINT16 )iY, ( UINT16 )( pRegion->iW ), 0, FONT10ARIAL, FONT_BLACK, pRegion->FastHelpText, FONT_BLACK, TRUE, 0 );
|
|
iH = (INT32)( GetNumberOfLinesInHeight( pRegion->FastHelpText ) * (GetFontHeight(FONT10ARIAL)+1) + 8 );
|
|
|
|
// tack on the outer border
|
|
iH += 14;
|
|
|
|
// gone not far enough?
|
|
if ( iX < 0 )
|
|
iX = 0;
|
|
|
|
// gone too far
|
|
if ( ( pRegion->iX + iW ) >= SCREEN_WIDTH )
|
|
iX = (SCREEN_WIDTH - iW - 4);
|
|
|
|
// what about the y value?
|
|
iY = (INT32)pRegion->iY - ( iH * 3 / 4);
|
|
|
|
// not far enough
|
|
if (iY < 0)
|
|
iY = 0;
|
|
|
|
// too far
|
|
if ( (iY + iH) >= SCREEN_HEIGHT )
|
|
iY = (SCREEN_HEIGHT - iH - 15);
|
|
|
|
pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES );
|
|
SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT );
|
|
RectangleDraw( TRUE, iX + 1, iY + 1, iX + iW - 1, iY + iH - 1, Get16BPPColor( FROMRGB( 65, 57, 15 ) ), pDestBuf );
|
|
RectangleDraw( TRUE, iX, iY, iX + iW - 2, iY + iH - 2, Get16BPPColor( FROMRGB( 227, 198, 88 ) ), pDestBuf );
|
|
UnLockVideoSurface( FRAME_BUFFER );
|
|
ShadowVideoSurfaceRect( FRAME_BUFFER, iX + 2, iY + 2, iX + iW - 3, iY + iH - 3 );
|
|
ShadowVideoSurfaceRect( FRAME_BUFFER, iX + 2, iY + 2, iX + iW - 3, iY + iH - 3 );
|
|
|
|
// fillt he video surface areas
|
|
//ColorFillVideoSurfaceArea(FRAME_BUFFER, iX, iY, (iX + iW), (iY + iH), 0);
|
|
//ColorFillVideoSurfaceArea(FRAME_BUFFER, (iX + 1), (iY + 1), (iX + iW - 1), (iY + iH - 1), usFillColor);
|
|
|
|
SetFont( FONT10ARIAL );
|
|
SetFontForeground( FONT_BEIGE );
|
|
|
|
//iH = ( INT32 )DisplayWrappedString( ( INT16 )( iX + 10 ), ( INT16 )( iY + 6 ), ( INT16 )pRegion->iW, 0, FONT10ARIAL, FONT_BEIGE, pRegion->FastHelpText, FONT_NEARBLACK, TRUE, 0 );
|
|
|
|
DisplayHelpTokenizedString( pRegion->FastHelpText ,( INT16 )( iX + 5 ), ( INT16 )( iY + 5 ) );
|
|
|
|
iHeightOfInitFastHelpText = iH + 20;
|
|
|
|
InvalidateRegion( iX, iY, (iX + iW) , (iY + iH + 20 ) );
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DisplayFastHelpForInitialTripInToMapScreen( FASTHELPREGION *pRegion )
|
|
{
|
|
if( gTacticalStatus.fDidGameJustStart )
|
|
{
|
|
if( AnyMercsHired() == FALSE )
|
|
{
|
|
return;
|
|
}
|
|
|
|
HandleDisplayOfExitToTacticalMessageForFirstEntryToMapScreen( );
|
|
// DEF: removed cause the help screen will replace the help screen
|
|
// DisplayFastHelpRegions( &pFastHelpMapScreenList[ 9 ], 1 );
|
|
|
|
}
|
|
else
|
|
{
|
|
DisplayFastHelpRegions( pFastHelpMapScreenList, giSizeOfInterfaceFastHelpTextList );
|
|
}
|
|
|
|
SetUpShutDownMapScreenHelpTextScreenMask( );
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void DisplayMapScreenFastHelpList( void )
|
|
{
|
|
INT32 iCounter = 0;
|
|
|
|
DisplayFastHelpForInitialTripInToMapScreen( &pFastHelpMapScreenList[ iCounter ] );
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void SetUpMapScreenFastHelpText( void )
|
|
{
|
|
INT32 iCounter = 0;
|
|
|
|
// now run through and display all the fast help text for the mapscreen functional regions
|
|
for( iCounter = 0; iCounter < NUMBER_OF_MAPSCREEN_HELP_MESSAGES; iCounter++ )
|
|
{
|
|
pFastHelpMapScreenList[ iCounter ].iX = pMapScreenFastHelpLocationList[ iCounter ].iX;
|
|
pFastHelpMapScreenList[ iCounter ].iY = pMapScreenFastHelpLocationList[ iCounter ].iY;
|
|
pFastHelpMapScreenList[ iCounter ].iW = pMapScreenFastHelpWidthList[ iCounter ];
|
|
wcscpy( pFastHelpMapScreenList[ iCounter ].FastHelpText, pMapScreenFastHelpTextList[ iCounter ] );
|
|
}
|
|
|
|
// DEF: removed cause the help screen will replace the help screen
|
|
/*
|
|
pFastHelpMapScreenList[ 9 ].iX = pMapScreenFastHelpLocationList[ 9 ].iX;
|
|
pFastHelpMapScreenList[ 9 ].iY = pMapScreenFastHelpLocationList[ 9 ].iY;
|
|
pFastHelpMapScreenList[ 9 ].iW = pMapScreenFastHelpWidthList[ 9 ];
|
|
wcscpy( pFastHelpMapScreenList[ 9 ].FastHelpText, pMapScreenFastHelpTextList[ 9 ] );
|
|
*/
|
|
return;
|
|
}
|
|
|
|
void StopMapScreenHelpText( void )
|
|
{
|
|
fShowMapScreenHelpText = FALSE;
|
|
fTeamPanelDirty = TRUE;
|
|
fMapPanelDirty = TRUE;
|
|
fCharacterInfoPanelDirty = TRUE;
|
|
fMapScreenBottomDirty = TRUE;
|
|
|
|
SetUpShutDownMapScreenHelpTextScreenMask( );
|
|
return;
|
|
}
|
|
|
|
BOOLEAN IsMapScreenHelpTextUp( void )
|
|
{
|
|
return( fShowMapScreenHelpText );
|
|
}
|
|
|
|
void SetUpShutDownMapScreenHelpTextScreenMask( void )
|
|
{
|
|
static BOOLEAN fCreated = FALSE;
|
|
|
|
// create or destroy the screen mask as needed
|
|
if( ( ( fShowMapScreenHelpText == TRUE ) || ( fInterfaceFastHelpTextActive == TRUE ) ) && ( fCreated == FALSE ) )
|
|
{
|
|
if( gTacticalStatus.fDidGameJustStart )
|
|
{
|
|
MSYS_DefineRegion( &gMapScreenHelpTextMask , ( INT16 )( pMapScreenFastHelpLocationList[ 9 ].iX ), ( INT16 )( pMapScreenFastHelpLocationList[ 9 ].iY ), ( INT16 )( pMapScreenFastHelpLocationList[ 9 ].iX + pMapScreenFastHelpWidthList[ 9 ] ), ( INT16 )( pMapScreenFastHelpLocationList[ 9 ].iY + iHeightOfInitFastHelpText ), MSYS_PRIORITY_HIGHEST,
|
|
MSYS_NO_CURSOR, MSYS_NO_CALLBACK, MapScreenHelpTextScreenMaskBtnCallback );
|
|
}
|
|
else
|
|
{
|
|
MSYS_DefineRegion( &gMapScreenHelpTextMask , 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, MSYS_PRIORITY_HIGHEST,
|
|
MSYS_NO_CURSOR, MSYS_NO_CALLBACK, MapScreenHelpTextScreenMaskBtnCallback );
|
|
}
|
|
|
|
fCreated = TRUE;
|
|
|
|
}
|
|
else if( ( fShowMapScreenHelpText == FALSE ) && ( fInterfaceFastHelpTextActive == FALSE ) && ( fCreated == TRUE ) )
|
|
{
|
|
MSYS_RemoveRegion( &gMapScreenHelpTextMask );
|
|
|
|
fCreated = FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
void MapScreenHelpTextScreenMaskBtnCallback( MOUSE_REGION * pRegion, INT32 iReason )
|
|
{
|
|
if( iReason & MSYS_CALLBACK_REASON_RBUTTON_UP )
|
|
{
|
|
// stop showing
|
|
ShutDownUserDefineHelpTextRegions( );
|
|
}
|
|
else if( iReason & MSYS_CALLBACK_REASON_LBUTTON_UP )
|
|
{
|
|
// stop showing
|
|
ShutDownUserDefineHelpTextRegions( );
|
|
}
|
|
}
|
|
|
|
|
|
BOOLEAN IsSoldierSelectedForMovement( SOLDIERTYPE *pSoldier )
|
|
{
|
|
INT32 iCounter = 0;
|
|
|
|
// run through the list and turn this soldiers value on
|
|
for( iCounter = 0; iCounter < giNumberOfSoldiersInSectorMoving; iCounter++ )
|
|
{
|
|
if( ( pSoldierMovingList[ iCounter ] == pSoldier ) && ( fSoldierIsMoving[ iCounter ] ) )
|
|
{
|
|
return ( TRUE );
|
|
}
|
|
}
|
|
return( FALSE );
|
|
}
|
|
|
|
BOOLEAN IsSquadSelectedForMovement( INT32 iSquadNumber )
|
|
{
|
|
INT32 iCounter = 0;
|
|
|
|
// run through squad list and set them on
|
|
for( iCounter = 0; iCounter < giNumberOfSquadsInSectorMoving; iCounter++ )
|
|
{
|
|
if( ( iSquadMovingList[ iCounter ] == iSquadNumber ) && ( fSquadIsMoving[ iCounter ] ) )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
}
|
|
|
|
return( FALSE );
|
|
}
|
|
|
|
|
|
BOOLEAN IsVehicleSelectedForMovement( INT32 iVehicleId )
|
|
{
|
|
INT32 iCounter = 0;
|
|
|
|
// run through squad list and set them on
|
|
for( iCounter = 0; iCounter < giNumberOfVehiclesInSectorMoving; iCounter++ )
|
|
{
|
|
if( ( iVehicleMovingList[ iCounter ] == iVehicleId ) && ( fVehicleIsMoving[ iCounter ] ) )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
}
|
|
return( FALSE );
|
|
}
|
|
|
|
|
|
|
|
void SelectSoldierForMovement( SOLDIERTYPE *pSoldier )
|
|
{
|
|
INT32 iCounter = 0;
|
|
|
|
if( pSoldier == NULL )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// run through the list and turn this soldiers value on
|
|
for( iCounter = 0; iCounter < giNumberOfSoldiersInSectorMoving; iCounter++ )
|
|
{
|
|
if( pSoldierMovingList[ iCounter ] == pSoldier )
|
|
{
|
|
// turn the selected soldier ON
|
|
fSoldierIsMoving[ iCounter ] = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void DeselectSoldierForMovement( SOLDIERTYPE *pSoldier )
|
|
{
|
|
INT32 iCounter = 0;
|
|
|
|
if( pSoldier == NULL )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// run through the list and turn this soldier's value on
|
|
for( iCounter = 0; iCounter < giNumberOfSoldiersInSectorMoving; iCounter++ )
|
|
{
|
|
if( pSoldierMovingList[ iCounter ] == pSoldier )
|
|
{
|
|
// turn the selected soldier off
|
|
fSoldierIsMoving[ iCounter ] = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void SelectSquadForMovement( INT32 iSquadNumber )
|
|
{
|
|
INT32 iCounter = 0, iCount = 0;
|
|
BOOLEAN fSomeCantMove = FALSE;
|
|
SOLDIERTYPE *pSoldier = NULL;
|
|
BOOLEAN fFirstFailure;
|
|
|
|
|
|
// run through squad list and set them on
|
|
for( iCounter = 0; iCounter < giNumberOfSquadsInSectorMoving; iCounter++ )
|
|
{
|
|
if( iSquadMovingList[ iCounter ] == iSquadNumber )
|
|
{
|
|
// found it
|
|
|
|
fFirstFailure = TRUE;
|
|
|
|
// try to select everyone in squad
|
|
for( iCount = 0; iCount < NUMBER_OF_SOLDIERS_PER_SQUAD; iCount++ )
|
|
{
|
|
pSoldier = Squad[ iSquadNumber ][ iCount ];
|
|
|
|
if ( pSoldier && pSoldier->bActive )
|
|
{
|
|
// is he able & allowed to move? (Report only the first reason for failure encountered)
|
|
if ( CanMoveBoxSoldierMoveStrategically( pSoldier, fFirstFailure ) )
|
|
{
|
|
SelectSoldierForMovement( pSoldier );
|
|
}
|
|
else
|
|
{
|
|
fSomeCantMove = TRUE;
|
|
fFirstFailure = FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( !fSomeCantMove )
|
|
{
|
|
fSquadIsMoving[ iCounter ] = TRUE;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void DeselectSquadForMovement( INT32 iSquadNumber )
|
|
{
|
|
INT32 iCounter = 0, iCount = 0;
|
|
SOLDIERTYPE *pSoldier = NULL;
|
|
|
|
// run through squad list and set them off
|
|
for( iCounter = 0; iCounter < giNumberOfSquadsInSectorMoving; iCounter++ )
|
|
{
|
|
if( iSquadMovingList[ iCounter ] == iSquadNumber )
|
|
{
|
|
// found it
|
|
fSquadIsMoving[ iCounter ] = FALSE;
|
|
|
|
// now deselect everyone in squad
|
|
for( iCount = 0; iCount < NUMBER_OF_SOLDIERS_PER_SQUAD; iCount++ )
|
|
{
|
|
pSoldier = Squad[ iSquadNumber ][ iCount ];
|
|
|
|
if ( pSoldier && pSoldier->bActive )
|
|
{
|
|
DeselectSoldierForMovement( pSoldier );
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
BOOLEAN AllSoldiersInSquadSelected( INT32 iSquadNumber )
|
|
{
|
|
INT32 iCounter = 0;
|
|
|
|
// is everyone on this squad moving?
|
|
for( iCounter = 0; iCounter < giNumberOfSoldiersInSectorMoving; iCounter++ )
|
|
{
|
|
if( pSoldierMovingList[ iCounter ]->bAssignment == ( INT8 )iSquadNumber )
|
|
{
|
|
if( fSoldierIsMoving[ iCounter ] == FALSE )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
}
|
|
}
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
|
|
void SelectVehicleForMovement( INT32 iVehicleId, BOOLEAN fAndAllOnBoard )
|
|
{
|
|
INT32 iCounter = 0, iCount = 0;
|
|
SOLDIERTYPE *pPassenger = NULL;
|
|
BOOLEAN fHasDriver = FALSE;
|
|
BOOLEAN fFirstFailure;
|
|
|
|
|
|
// run through vehicle list and set them on
|
|
for( iCounter = 0; iCounter < giNumberOfVehiclesInSectorMoving; iCounter++ )
|
|
{
|
|
if( iVehicleMovingList[ iCounter ] == iVehicleId )
|
|
{
|
|
// found it
|
|
|
|
fFirstFailure = TRUE;
|
|
|
|
for( iCount = 0; iCount < 10; iCount++ )
|
|
{
|
|
pPassenger = pVehicleList[ iVehicleId ].pPassengers[ iCount ];
|
|
|
|
if ( fAndAllOnBoard )
|
|
{
|
|
// try to select everyone in vehicle
|
|
|
|
if ( pPassenger && pPassenger->bActive )
|
|
{
|
|
// is he able & allowed to move?
|
|
if ( CanMoveBoxSoldierMoveStrategically( pPassenger, fFirstFailure ) )
|
|
{
|
|
SelectSoldierForMovement( pPassenger );
|
|
}
|
|
else
|
|
{
|
|
fFirstFailure = FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( IsSoldierSelectedForMovement( pPassenger ) )
|
|
{
|
|
fHasDriver = TRUE;
|
|
}
|
|
}
|
|
|
|
// vehicle itself can only move if at least one passenger can move and is moving!
|
|
if ( fHasDriver )
|
|
{
|
|
fVehicleIsMoving[ iCounter ] = TRUE;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void DeselectVehicleForMovement( INT32 iVehicleId )
|
|
{
|
|
INT32 iCounter = 0, iCount = 0;
|
|
SOLDIERTYPE *pPassenger = NULL;
|
|
|
|
|
|
// run through vehicle list and set them off
|
|
for( iCounter = 0; iCounter < giNumberOfVehiclesInSectorMoving; iCounter++ )
|
|
{
|
|
if( iVehicleMovingList[ iCounter ] == iVehicleId )
|
|
{
|
|
// found it
|
|
fVehicleIsMoving[ iCounter ] = FALSE;
|
|
|
|
// now deselect everyone in vehicle
|
|
for( iCount = 0; iCount < MAXPASSENGERS ; iCount++ )
|
|
{
|
|
pPassenger = pVehicleList[ iVehicleId ].pPassengers[ iCount ];
|
|
|
|
if ( pPassenger && pPassenger->bActive )
|
|
{
|
|
DeselectSoldierForMovement( pPassenger );
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
INT32 HowManyMovingSoldiersInVehicle( INT32 iVehicleId )
|
|
{
|
|
INT32 iNumber = 0, iCounter = 0;
|
|
|
|
for( iCounter = 0; iCounter < giNumberOfSoldiersInSectorMoving; iCounter++ )
|
|
{
|
|
// is he in the right vehicle
|
|
if( ( pSoldierMovingList[ iCounter ]->bAssignment == VEHICLE )&&( pSoldierMovingList[ iCounter ]->iVehicleId == iVehicleId ) )
|
|
{
|
|
// if he moving?
|
|
if ( fSoldierIsMoving[ iCounter ] )
|
|
{
|
|
// ok, another one in the vehicle that is going to move
|
|
iNumber++;
|
|
}
|
|
}
|
|
}
|
|
|
|
return( iNumber );
|
|
}
|
|
|
|
INT32 HowManyMovingSoldiersInSquad( INT32 iSquadNumber )
|
|
{
|
|
INT32 iNumber = 0, iCounter = 0;
|
|
|
|
for( iCounter = 0; iCounter < giNumberOfSoldiersInSectorMoving; iCounter++ )
|
|
{
|
|
// is he in the right squad
|
|
if( pSoldierMovingList[ iCounter ]->bAssignment == iSquadNumber )
|
|
{
|
|
// if he moving?
|
|
if ( fSoldierIsMoving[ iCounter ] )
|
|
{
|
|
// ok, another one in the squad that is going to move
|
|
iNumber++;
|
|
}
|
|
}
|
|
}
|
|
|
|
return( iNumber );
|
|
}
|
|
|
|
|
|
// try to add this soldier to the moving lists
|
|
void AddSoldierToMovingLists( SOLDIERTYPE *pSoldier )
|
|
{
|
|
INT32 iCounter = 0;
|
|
|
|
for( iCounter = 0; iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; iCounter++ )
|
|
{
|
|
if( pSoldierMovingList[ iCounter ] == pSoldier )
|
|
{
|
|
// found
|
|
return;
|
|
}
|
|
else if( pSoldierMovingList[ iCounter ] == NULL )
|
|
{
|
|
// found a free slot
|
|
pSoldierMovingList[ iCounter ] = pSoldier;
|
|
fSoldierIsMoving[ iCounter ] = FALSE;
|
|
|
|
giNumberOfSoldiersInSectorMoving++;
|
|
return;
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
// try to add this soldier to the moving lists
|
|
void AddSquadToMovingLists( INT32 iSquadNumber )
|
|
{
|
|
INT32 iCounter = 0;
|
|
|
|
if( iSquadNumber == -1 )
|
|
{
|
|
// invalid squad
|
|
return;
|
|
}
|
|
|
|
for( iCounter = 0; iCounter < NUMBER_OF_SQUADS; iCounter++ )
|
|
{
|
|
if( iSquadMovingList[ iCounter ] == iSquadNumber )
|
|
{
|
|
// found
|
|
return;
|
|
}
|
|
if( iSquadMovingList[ iCounter ] == -1 )
|
|
{
|
|
// found a free slot
|
|
iSquadMovingList[ iCounter ] = iSquadNumber;
|
|
fSquadIsMoving[ iCounter ] = FALSE;
|
|
|
|
giNumberOfSquadsInSectorMoving++;
|
|
return;
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
// try to add this soldier to the moving lists
|
|
void AddVehicleToMovingLists( INT32 iVehicleId )
|
|
{
|
|
INT32 iCounter = 0;
|
|
|
|
if( iVehicleId == -1 )
|
|
{
|
|
// invalid squad
|
|
return;
|
|
}
|
|
|
|
for( iCounter = 0; iCounter < NUMBER_OF_SQUADS; iCounter++ )
|
|
{
|
|
if( iVehicleMovingList[ iCounter ] == iVehicleId )
|
|
{
|
|
// found
|
|
return;
|
|
}
|
|
if( iVehicleMovingList[ iCounter ] == -1 )
|
|
{
|
|
// found a free slot
|
|
iVehicleMovingList[ iCounter ] = iVehicleId;
|
|
fVehicleIsMoving[ iCounter ] = FALSE;
|
|
|
|
giNumberOfVehiclesInSectorMoving++;
|
|
return;
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
void InitializeMovingLists( void )
|
|
{
|
|
INT32 iCounter = 0;
|
|
|
|
|
|
giNumberOfSoldiersInSectorMoving = 0;
|
|
giNumberOfSquadsInSectorMoving = 0;
|
|
giNumberOfVehiclesInSectorMoving = 0;
|
|
|
|
// init the soldiers
|
|
for( iCounter = 0; iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; iCounter++ )
|
|
{
|
|
// soldier is NOT moving
|
|
pSoldierMovingList[ iCounter ] = NULL;
|
|
// turn the selected soldier off
|
|
fSoldierIsMoving[ iCounter ] = FALSE;
|
|
}
|
|
|
|
|
|
// init the squads
|
|
for( iCounter = 0; iCounter < NUMBER_OF_SQUADS; iCounter++ )
|
|
{
|
|
// reset squad value
|
|
iSquadMovingList[ iCounter ] = -1;
|
|
// turn it off
|
|
fSquadIsMoving[ iCounter ] = FALSE;
|
|
}
|
|
|
|
// init the vehicles
|
|
for( iCounter = 0; iCounter < NUMBER_OF_SQUADS; iCounter++ )
|
|
{
|
|
// reset squad value
|
|
iVehicleMovingList[ iCounter ] = -1;
|
|
// turn it off
|
|
fVehicleIsMoving[ iCounter ] = FALSE;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN IsAnythingSelectedForMoving( void )
|
|
{
|
|
INT32 iCounter = 0;
|
|
|
|
|
|
// check soldiers
|
|
for( iCounter = 0; iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; iCounter++ )
|
|
{
|
|
if ( ( pSoldierMovingList[ iCounter ] != NULL ) && fSoldierIsMoving[ iCounter ] )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
}
|
|
|
|
|
|
// init the squads
|
|
for( iCounter = 0; iCounter < NUMBER_OF_SQUADS; iCounter++ )
|
|
{
|
|
if ( ( iSquadMovingList[ iCounter ] != -1 ) && fSquadIsMoving[ iCounter ] )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
}
|
|
|
|
// init the vehicles
|
|
for( iCounter = 0; iCounter < NUMBER_OF_SQUADS; iCounter++ )
|
|
{
|
|
if ( ( iVehicleMovingList[ iCounter ] != -1 ) && fVehicleIsMoving[ iCounter ] )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
}
|
|
|
|
return( FALSE );
|
|
}
|
|
|
|
|
|
|
|
void CreateDestroyMovementBox( INT16 sSectorX, INT16 sSectorY, INT16 sSectorZ )
|
|
{
|
|
static BOOLEAN fCreated = FALSE;
|
|
|
|
|
|
// not allowed for underground movement!
|
|
Assert( sSectorZ == 0 );
|
|
|
|
if( ( fShowMapScreenMovementList == TRUE ) && ( fCreated == FALSE ) )
|
|
{
|
|
fCreated = TRUE;
|
|
|
|
// create the box and mouse regions
|
|
CreatePopUpBoxForMovementBox( );
|
|
BuildMouseRegionsForMoveBox( );
|
|
CreateScreenMaskForMoveBox( );
|
|
fMapPanelDirty = TRUE;
|
|
}
|
|
else if( ( fShowMapScreenMovementList == FALSE ) && ( fCreated == TRUE ) )
|
|
{
|
|
fCreated = FALSE;
|
|
|
|
// destroy the box and mouse regions
|
|
ClearMouseRegionsForMoveBox( );
|
|
RemoveBox( ghMoveBox );
|
|
ghMoveBox = -1;
|
|
RemoveScreenMaskForMoveBox( );
|
|
fMapPanelDirty = TRUE;
|
|
fMapScreenBottomDirty = TRUE; // really long move boxes can overlap bottom panel
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetUpMovingListsForSector( INT16 sSectorX, INT16 sSectorY, INT16 sSectorZ )
|
|
{
|
|
INT32 iCounter = 0;
|
|
SOLDIERTYPE *pSoldier = NULL;
|
|
|
|
|
|
// not allowed for underground movement!
|
|
Assert( sSectorZ == 0 );
|
|
|
|
|
|
// clear the lists
|
|
InitializeMovingLists();
|
|
|
|
|
|
// note that Skyrider can't be moved using the move box, and won't appear because the helicoprer is not in the char list
|
|
|
|
for( iCounter = 0; iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; iCounter++ )
|
|
{
|
|
if( gCharactersList[ iCounter ].fValid )
|
|
{
|
|
pSoldier = MercPtrs[ gCharactersList[ iCounter ].usSolID ];
|
|
|
|
if( ( pSoldier->bActive ) &&
|
|
( pSoldier->bAssignment != IN_TRANSIT ) && ( pSoldier->bAssignment != ASSIGNMENT_POW ) &&
|
|
( pSoldier->sSectorX == sSectorX ) && ( pSoldier->sSectorY == sSectorY ) && ( pSoldier->bSectorZ == sSectorZ ) )
|
|
{
|
|
if ( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE )
|
|
{
|
|
// vehicle
|
|
// if it can move (can't be empty)
|
|
if ( GetNumberInVehicle( pSoldier->bVehicleID ) > 0 )
|
|
{
|
|
// add vehicle
|
|
AddVehicleToMovingLists( pSoldier->bVehicleID );
|
|
}
|
|
}
|
|
else // soldier
|
|
{
|
|
// alive, not aboard Skyrider (airborne or not!)
|
|
if ( ( pSoldier->stats.bLife >= OKLIFE ) &&
|
|
( ( pSoldier->bAssignment != VEHICLE ) || ( pSoldier->iVehicleId != iHelicopterVehicleId ) ) )
|
|
{
|
|
// add soldier
|
|
AddSoldierToMovingLists( pSoldier );
|
|
|
|
// if on a squad,
|
|
if ( pSoldier->bAssignment < ON_DUTY )
|
|
{
|
|
// add squad (duplicates ok, they're ignored inside the function)
|
|
AddSquadToMovingLists( pSoldier->bAssignment );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fShowMapScreenMovementList = TRUE;
|
|
CreateDestroyMovementBox( sSectorX, sSectorY, sSectorZ );
|
|
}
|
|
|
|
|
|
|
|
void CreatePopUpBoxForMovementBox( void )
|
|
{
|
|
SGPPoint 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 ] );
|
|
swprintf( sString, L"*%s*", gNewVehicle[ pVehicleList[ iVehicleMovingList[ iCount ] ].ubVehicleType ].NewVehicleStrings );
|
|
}
|
|
else
|
|
{
|
|
// swprintf( sString, L"%s", pVehicleStrings[ pVehicleList[ iVehicleMovingList[ iCount ] ].ubVehicleType ] );
|
|
swprintf( sString, L"%s", gNewVehicle[ pVehicleList[ iVehicleMovingList[ iCount ] ].ubVehicleType ].NewVehicleStrings);
|
|
}
|
|
AddMonoString(&hStringHandle, sString );
|
|
|
|
// now add all the grunts in it
|
|
for( iCountB = 0; iCountB < giNumberOfSoldiersInSectorMoving; iCountB++ )
|
|
{
|
|
if( ( pSoldierMovingList[ iCountB ]->bAssignment == VEHICLE ) &&( pSoldierMovingList[ iCountB ]->iVehicleId == iVehicleMovingList[ iCount ] ) )
|
|
{
|
|
// add mercs in vehicles
|
|
if( IsSoldierSelectedForMovement( pSoldierMovingList[ iCountB ] ) == TRUE )
|
|
{
|
|
swprintf( sString, L" *%s*", pSoldierMovingList[ iCountB ]->name );
|
|
}
|
|
else
|
|
{
|
|
swprintf( sString, L" %s", pSoldierMovingList[ iCountB ]->name );
|
|
}
|
|
AddMonoString(&hStringHandle, sString );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
fFirstOne = TRUE;
|
|
|
|
// add "other" soldiers heading, once, if there are any
|
|
for( iCount = 0; iCount < giNumberOfSoldiersInSectorMoving; iCount++ )
|
|
{
|
|
// not on duty, not in a vehicle
|
|
if( ( pSoldierMovingList[ iCount ]->bAssignment >= ON_DUTY ) && ( pSoldierMovingList[ iCount ]->bAssignment != VEHICLE ) )
|
|
{
|
|
if ( fFirstOne )
|
|
{
|
|
// add OTHER header line
|
|
if( AllOtherSoldiersInListAreSelected( ) )
|
|
{
|
|
swprintf( sString, L"*%s*", pMovementMenuStrings[ 3 ] );
|
|
}
|
|
else
|
|
{
|
|
swprintf( sString, L"%s", pMovementMenuStrings[ 3 ] );
|
|
}
|
|
AddMonoString(&hStringHandle, sString );
|
|
|
|
fFirstOne = FALSE;
|
|
}
|
|
|
|
// add OTHER soldiers (not on duty nor in a vehicle)
|
|
if( IsSoldierSelectedForMovement( pSoldierMovingList[ iCount ] ) == TRUE )
|
|
{
|
|
swprintf( sString, L" *%s ( %s )*", pSoldierMovingList[ iCount ]->name, pAssignmentStrings[ pSoldierMovingList[ iCount ]->bAssignment ] );
|
|
}
|
|
else
|
|
{
|
|
swprintf( sString, L" %s ( %s )", pSoldierMovingList[ iCount ]->name, pAssignmentStrings[ pSoldierMovingList[ iCount ]->bAssignment ] );
|
|
}
|
|
AddMonoString(&hStringHandle, sString );
|
|
}
|
|
}
|
|
|
|
|
|
// blank line
|
|
AddMonoString(&hStringHandle, L"" );
|
|
|
|
|
|
if ( IsAnythingSelectedForMoving() )
|
|
{
|
|
// add PLOT MOVE line
|
|
swprintf( sString, L"%s", pMovementMenuStrings[ 1 ] );
|
|
AddMonoString(&hStringHandle, sString );
|
|
}
|
|
else
|
|
{
|
|
// blank line
|
|
AddMonoString(&hStringHandle, L"" );
|
|
}
|
|
|
|
|
|
// add cancel line
|
|
swprintf( sString, L"%s", pMovementMenuStrings[ 2 ] );
|
|
AddMonoString(&hStringHandle, sString );
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void BuildMouseRegionsForMoveBox( void )
|
|
{
|
|
INT32 iCounter = 0, iTotalNumberOfLines = 0, iCount = 0, iCountB = 0;
|
|
SGPPoint pPosition;
|
|
INT32 iBoxWidth = 0;
|
|
SGPRect Dimensions;
|
|
INT32 iFontHeight = 0;
|
|
INT32 iBoxXPosition = 0;
|
|
INT32 iBoxYPosition = 0;
|
|
BOOLEAN fDefinedOtherRegion = FALSE;
|
|
|
|
|
|
// grab height of font
|
|
iFontHeight = GetLineSpace( ghMoveBox ) + GetFontHeight( GetBoxFont( ghMoveBox ) );
|
|
|
|
// get x.y position of box
|
|
GetBoxPosition( ghMoveBox, &pPosition);
|
|
|
|
// grab box x and y position
|
|
iBoxXPosition = pPosition.iX;
|
|
iBoxYPosition = pPosition.iY + GetTopMarginSize( ghMoveBox ) - 2; // -2 to improve highlighting accuracy between lines
|
|
|
|
|
|
// get dimensions..mostly for width
|
|
GetBoxSize( ghMoveBox, &Dimensions );
|
|
|
|
// get width
|
|
iBoxWidth = Dimensions.iRight;
|
|
|
|
SetCurrentBox( ghMoveBox );
|
|
|
|
|
|
// box heading
|
|
MSYS_DefineRegion( &gMoveMenuRegion[ iCounter ], ( INT16 )( iBoxXPosition ), ( INT16 )( iBoxYPosition + iFontHeight * iCounter ), ( INT16 )( iBoxXPosition + iBoxWidth ), ( INT16 )( iBoxYPosition + iFontHeight * ( iCounter + 1 ) ), MSYS_PRIORITY_HIGHEST,
|
|
MSYS_NO_CURSOR, MSYS_NO_CALLBACK, MSYS_NO_CALLBACK );
|
|
iCounter++;
|
|
|
|
// blank line
|
|
MSYS_DefineRegion( &gMoveMenuRegion[ iCounter ], ( INT16 )( iBoxXPosition ), ( INT16 )( iBoxYPosition + iFontHeight * iCounter ), ( INT16 )( iBoxXPosition + iBoxWidth ), ( INT16 )( iBoxYPosition + iFontHeight * ( iCounter + 1 ) ), MSYS_PRIORITY_HIGHEST,
|
|
MSYS_NO_CURSOR, MSYS_NO_CALLBACK, MSYS_NO_CALLBACK );
|
|
iCounter++;
|
|
|
|
// calc total number of "moving" lines in the box
|
|
iTotalNumberOfLines = giNumberOfSoldiersInSectorMoving + giNumberOfSquadsInSectorMoving + giNumberOfVehiclesInSectorMoving;
|
|
// add the blank lines
|
|
iTotalNumberOfLines += iCounter;
|
|
|
|
|
|
// now add the strings
|
|
while( iCounter < iTotalNumberOfLines )
|
|
{
|
|
// define regions for squad lines
|
|
for( iCount = 0; iCount < giNumberOfSquadsInSectorMoving; iCount++ )
|
|
{
|
|
MSYS_DefineRegion( &gMoveMenuRegion[ iCounter ], ( INT16 )( iBoxXPosition ), ( INT16 )( iBoxYPosition + iFontHeight * iCounter ), ( INT16 )( iBoxXPosition + iBoxWidth ), ( INT16 )( iBoxYPosition + iFontHeight * ( iCounter + 1 ) ), MSYS_PRIORITY_HIGHEST,
|
|
MSYS_NO_CURSOR, MoveMenuMvtCallback, MoveMenuBtnCallback );
|
|
|
|
// set user defines
|
|
MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 0, iCounter );
|
|
MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 1, SQUAD_REGION );
|
|
MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 2, iCount );
|
|
iCounter++;
|
|
|
|
for( iCountB = 0; iCountB < giNumberOfSoldiersInSectorMoving; iCountB++ )
|
|
{
|
|
if( pSoldierMovingList[ iCountB ]->bAssignment == iSquadMovingList[ iCount ] )
|
|
{
|
|
MSYS_DefineRegion( &gMoveMenuRegion[ iCounter ], ( INT16 )( iBoxXPosition ), ( INT16 )( iBoxYPosition + iFontHeight * iCounter ), ( INT16 )( iBoxXPosition + iBoxWidth ), ( INT16 )( iBoxYPosition + iFontHeight * ( iCounter + 1 ) ), MSYS_PRIORITY_HIGHEST,
|
|
MSYS_NO_CURSOR, MoveMenuMvtCallback, MoveMenuBtnCallback );
|
|
|
|
// set user defines
|
|
MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 0, iCounter );
|
|
MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 1, SOLDIER_REGION );
|
|
MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 2, iCountB );
|
|
iCounter++;
|
|
}
|
|
}
|
|
}
|
|
|
|
for( iCount = 0; iCount < giNumberOfVehiclesInSectorMoving; iCount++ )
|
|
{
|
|
// define regions for vehicle lines
|
|
MSYS_DefineRegion( &gMoveMenuRegion[ iCounter ], ( INT16 )( iBoxXPosition ), ( INT16 )( iBoxYPosition + iFontHeight * iCounter ), ( INT16 )( iBoxXPosition + iBoxWidth ), ( INT16 )( iBoxYPosition + iFontHeight * ( iCounter + 1 ) ), MSYS_PRIORITY_HIGHEST,
|
|
MSYS_NO_CURSOR, MoveMenuMvtCallback, MoveMenuBtnCallback );
|
|
|
|
// set user defines
|
|
MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 0, iCounter );
|
|
MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 1, VEHICLE_REGION );
|
|
MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 2, iCount );
|
|
iCounter++;
|
|
|
|
for( iCountB = 0; iCountB < giNumberOfSoldiersInSectorMoving; iCountB++ )
|
|
{
|
|
if( ( pSoldierMovingList[ iCountB ]->bAssignment == VEHICLE ) &&( pSoldierMovingList[ iCountB ]->iVehicleId == iVehicleMovingList[ iCount ] ) )
|
|
{
|
|
MSYS_DefineRegion( &gMoveMenuRegion[ iCounter ], ( INT16 )( iBoxXPosition ), ( INT16 )( iBoxYPosition + iFontHeight * iCounter ), ( INT16 )( iBoxXPosition + iBoxWidth ), ( INT16 )( iBoxYPosition + iFontHeight * ( iCounter + 1 ) ), MSYS_PRIORITY_HIGHEST,
|
|
MSYS_NO_CURSOR, MoveMenuMvtCallback, MoveMenuBtnCallback );
|
|
|
|
// set user defines
|
|
MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 0, iCounter );
|
|
MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 1, SOLDIER_REGION );
|
|
MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 2, iCountB );
|
|
iCounter++;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// define regions for "other" soldiers
|
|
for( iCount = 0; iCount < giNumberOfSoldiersInSectorMoving; iCount++ )
|
|
{
|
|
// this guy is not in a squad or vehicle
|
|
if( ( pSoldierMovingList[ iCount ]->bAssignment >= ON_DUTY )&&( pSoldierMovingList[ iCount ]->bAssignment != VEHICLE ) )
|
|
{
|
|
// this line gets place only once...
|
|
if( !fDefinedOtherRegion )
|
|
{
|
|
MSYS_DefineRegion( &gMoveMenuRegion[ iCounter ], ( INT16 )( iBoxXPosition ), ( INT16 )( iBoxYPosition + iFontHeight * iCounter ), ( INT16 )( iBoxXPosition + iBoxWidth ), ( INT16 )( iBoxYPosition + iFontHeight * ( iCounter + 1 ) ), MSYS_PRIORITY_HIGHEST,
|
|
MSYS_NO_CURSOR, MoveMenuMvtCallback, MoveMenuBtnCallback );
|
|
|
|
// set user defines
|
|
MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 0, iCounter );
|
|
MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 1, OTHER_REGION );
|
|
MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 2, 0 );
|
|
iCounter++;
|
|
|
|
fDefinedOtherRegion = TRUE;
|
|
}
|
|
|
|
MSYS_DefineRegion( &gMoveMenuRegion[ iCounter ], ( INT16 )( iBoxXPosition ), ( INT16 )( iBoxYPosition + iFontHeight * iCounter ), ( INT16 )( iBoxXPosition + iBoxWidth ), ( INT16 )( iBoxYPosition + iFontHeight * ( iCounter + 1 ) ), MSYS_PRIORITY_HIGHEST,
|
|
MSYS_NO_CURSOR, MoveMenuMvtCallback, MoveMenuBtnCallback );
|
|
|
|
// set user defines
|
|
MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 0, iCounter );
|
|
MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 1, SOLDIER_REGION );
|
|
MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 2, iCount );
|
|
iCounter++;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// blank line
|
|
MSYS_DefineRegion( &gMoveMenuRegion[ iCounter ], ( INT16 )( iBoxXPosition ), ( INT16 )( iBoxYPosition + iFontHeight * iCounter ), ( INT16 )( iBoxXPosition + iBoxWidth ), ( INT16 )( iBoxYPosition + iFontHeight * ( iCounter + 1 ) ), MSYS_PRIORITY_HIGHEST,
|
|
MSYS_NO_CURSOR, MSYS_NO_CALLBACK, MSYS_NO_CALLBACK );
|
|
iCounter++;
|
|
|
|
|
|
if ( IsAnythingSelectedForMoving() )
|
|
{
|
|
// DONE line
|
|
MSYS_DefineRegion( &gMoveMenuRegion[ iCounter ], ( INT16 )( iBoxXPosition ), ( INT16 )( iBoxYPosition + iFontHeight * iCounter ), ( INT16 )( iBoxXPosition + iBoxWidth ), ( INT16 )( iBoxYPosition + iFontHeight * ( iCounter + 1 ) ), MSYS_PRIORITY_HIGHEST,
|
|
MSYS_NO_CURSOR, MoveMenuMvtCallback, MoveMenuBtnCallback );
|
|
|
|
// set user defines
|
|
MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 0, iCounter );
|
|
MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 1, DONE_REGION );
|
|
MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 2, 0 );
|
|
iCounter++;
|
|
}
|
|
else
|
|
{
|
|
// blank line
|
|
MSYS_DefineRegion( &gMoveMenuRegion[ iCounter ], ( INT16 )( iBoxXPosition ), ( INT16 )( iBoxYPosition + iFontHeight * iCounter ), ( INT16 )( iBoxXPosition + iBoxWidth ), ( INT16 )( iBoxYPosition + iFontHeight * ( iCounter + 1 ) ), MSYS_PRIORITY_HIGHEST,
|
|
MSYS_NO_CURSOR, MSYS_NO_CALLBACK, MSYS_NO_CALLBACK );
|
|
iCounter++;
|
|
}
|
|
|
|
// CANCEL line
|
|
MSYS_DefineRegion( &gMoveMenuRegion[ iCounter ], ( INT16 )( iBoxXPosition ), ( INT16 )( iBoxYPosition + iFontHeight * iCounter ), ( INT16 )( iBoxXPosition + iBoxWidth ), ( INT16 )( iBoxYPosition + iFontHeight * ( iCounter + 1 ) ), MSYS_PRIORITY_HIGHEST,
|
|
MSYS_NO_CURSOR, MoveMenuMvtCallback, MoveMenuBtnCallback );
|
|
|
|
// set user defines
|
|
MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 0, iCounter );
|
|
MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 1, CANCEL_REGION );
|
|
MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 2, 0 );
|
|
iCounter++;
|
|
}
|
|
|
|
void ClearMouseRegionsForMoveBox( void )
|
|
{
|
|
INT32 iCounter = 0;
|
|
|
|
// run through list of mouse regions
|
|
for( iCounter = 0; iCounter < ( INT32 )GetNumberOfLinesOfTextInBox( ghMoveBox ); iCounter++ )
|
|
{
|
|
// remove this region
|
|
MSYS_RemoveRegion( &gMoveMenuRegion[ iCounter ] );
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
void MoveMenuMvtCallback(MOUSE_REGION * pRegion, INT32 iReason )
|
|
{
|
|
// mvt callback handler for move box line regions
|
|
INT32 iValue = -1;
|
|
|
|
|
|
iValue = MSYS_GetRegionUserData( pRegion, 0 );
|
|
|
|
if (iReason & MSYS_CALLBACK_REASON_GAIN_MOUSE )
|
|
{
|
|
// highlight string
|
|
HighLightBoxLine( ghMoveBox, iValue );
|
|
}
|
|
else if (iReason & MSYS_CALLBACK_REASON_LOST_MOUSE )
|
|
{
|
|
// unhighlight all strings in box
|
|
UnHighLightBox( ghMoveBox );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void MoveMenuBtnCallback(MOUSE_REGION * pRegion, INT32 iReason )
|
|
{
|
|
// btn callback handler for move box line regions
|
|
INT32 iMoveBoxLine = -1, iRegionType = -1, iListIndex = -1, iClickTime = 0;
|
|
SOLDIERTYPE *pSoldier = NULL;
|
|
|
|
|
|
iMoveBoxLine = MSYS_GetRegionUserData( pRegion, 0 );
|
|
iRegionType = MSYS_GetRegionUserData( pRegion, 1 );
|
|
iListIndex = MSYS_GetRegionUserData( pRegion, 2 );
|
|
iClickTime = GetJA2Clock();
|
|
|
|
if( ( iReason & MSYS_CALLBACK_REASON_LBUTTON_UP ) )
|
|
{
|
|
if( iClickTime - giDblClickTimersForMoveBoxMouseRegions[ iMoveBoxLine ] < DBL_CLICK_DELAY_FOR_MOVE_MENU )
|
|
{
|
|
// dbl click, and something is selected?
|
|
if ( IsAnythingSelectedForMoving() )
|
|
{
|
|
// treat like DONE
|
|
HandleMoveoutOfSectorMovementTroops( );
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
giDblClickTimersForMoveBoxMouseRegions[ iMoveBoxLine ] = iClickTime;
|
|
|
|
if( iRegionType == SQUAD_REGION )
|
|
{
|
|
// is the squad moving
|
|
if( fSquadIsMoving[ iListIndex ] == TRUE )
|
|
{
|
|
// squad stays
|
|
DeselectSquadForMovement( iSquadMovingList[ iListIndex ] );
|
|
}
|
|
else
|
|
{
|
|
// squad goes
|
|
SelectSquadForMovement( iSquadMovingList[ iListIndex ] );
|
|
}
|
|
}
|
|
else if( iRegionType == VEHICLE_REGION )
|
|
{
|
|
// is the vehicle moving
|
|
if( fVehicleIsMoving[ iListIndex ] == TRUE )
|
|
{
|
|
// vehicle stays
|
|
DeselectVehicleForMovement( iVehicleMovingList[ iListIndex ] );
|
|
}
|
|
else
|
|
{
|
|
// vehicle goes
|
|
SelectVehicleForMovement( iVehicleMovingList[ iListIndex ], AND_ALL_ON_BOARD );
|
|
}
|
|
}
|
|
else if( iRegionType == OTHER_REGION )
|
|
{
|
|
if( AllOtherSoldiersInListAreSelected( ) == TRUE )
|
|
{
|
|
// deselect all others in the list
|
|
DeselectAllOtherSoldiersInList( );
|
|
}
|
|
else
|
|
{
|
|
// select all others in the list
|
|
SelectAllOtherSoldiersInList( );
|
|
}
|
|
}
|
|
else if( iRegionType == SOLDIER_REGION )
|
|
{
|
|
pSoldier = pSoldierMovingList[ iListIndex ];
|
|
|
|
if ( pSoldier->flags.fBetweenSectors )
|
|
{
|
|
// we don't allow mercs to change squads or get out of vehicles between sectors, easiest way to handle this
|
|
// is to prevent any toggling of individual soldiers on the move at the outset.
|
|
DoScreenIndependantMessageBox( pMapErrorString[ 41 ], MSG_BOX_FLAG_OK, NULL );
|
|
return;
|
|
}
|
|
|
|
// if soldier is currently selected to move
|
|
if( IsSoldierSelectedForMovement( pSoldier ) )
|
|
{
|
|
// change him to NOT move instead
|
|
|
|
if( pSoldier->bAssignment == VEHICLE )
|
|
{
|
|
// if he's the only one left moving in the vehicle, deselect whole vehicle
|
|
if( HowManyMovingSoldiersInVehicle( pSoldier->iVehicleId ) == 1 )
|
|
{
|
|
// whole vehicle stays
|
|
DeselectVehicleForMovement( pSoldier->iVehicleId );
|
|
}
|
|
else
|
|
{
|
|
// soldier is staying behind
|
|
DeselectSoldierForMovement( pSoldier );
|
|
}
|
|
}
|
|
else if( pSoldier->bAssignment < ON_DUTY )
|
|
{
|
|
// if he's the only one left moving in the squad, deselect whole squad
|
|
if( HowManyMovingSoldiersInSquad( pSoldier->bAssignment ) == 1 )
|
|
{
|
|
// whole squad stays
|
|
DeselectSquadForMovement( pSoldier->bAssignment );
|
|
}
|
|
else
|
|
{
|
|
// soldier is staying behind
|
|
DeselectSoldierForMovement( pSoldier );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// soldier is staying behind
|
|
DeselectSoldierForMovement( pSoldier );
|
|
}
|
|
}
|
|
else // currently NOT moving
|
|
{
|
|
// is he able & allowed to move? (Errors with a reason are reported within)
|
|
if ( CanMoveBoxSoldierMoveStrategically( pSoldier, TRUE ) )
|
|
{
|
|
// change him to move instead
|
|
SelectSoldierForMovement( pSoldier );
|
|
|
|
if( pSoldier->bAssignment < ON_DUTY )
|
|
{
|
|
// if everyone in the squad is now selected, select the squad itself
|
|
if( AllSoldiersInSquadSelected( pSoldier->bAssignment ) )
|
|
{
|
|
SelectSquadForMovement( pSoldier->bAssignment );
|
|
}
|
|
}
|
|
/* ARM: it's more flexible without this - player can take the vehicle along or not without having to exit it.
|
|
else if( pSoldier->bAssignment == VEHICLE )
|
|
{
|
|
// his vehicle MUST also go while he's moving, but not necessarily others on board
|
|
SelectVehicleForMovement( pSoldier->iVehicleId, VEHICLE_ONLY );
|
|
}
|
|
*/
|
|
}
|
|
}
|
|
}
|
|
else if( iRegionType == DONE_REGION )
|
|
{
|
|
// is something selected?
|
|
if ( IsAnythingSelectedForMoving() )
|
|
{
|
|
HandleMoveoutOfSectorMovementTroops( );
|
|
return;
|
|
}
|
|
}
|
|
else if( iRegionType == CANCEL_REGION )
|
|
{
|
|
fShowMapScreenMovementList = FALSE;
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
AssertMsg( 0, String( "MoveMenuBtnCallback: Invalid regionType %d, moveBoxLine %d", iRegionType, iMoveBoxLine ) );
|
|
return;
|
|
}
|
|
|
|
fRebuildMoveBox = TRUE;
|
|
fTeamPanelDirty = TRUE;
|
|
fMapPanelDirty = TRUE;
|
|
fCharacterInfoPanelDirty = TRUE;
|
|
MarkAllBoxesAsAltered( );
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN CanMoveBoxSoldierMoveStrategically( SOLDIERTYPE *pSoldier, BOOLEAN fShowErrorMessage )
|
|
{
|
|
INT8 bErrorNumber = -1;
|
|
|
|
// valid soldier?
|
|
Assert( pSoldier );
|
|
Assert( pSoldier->bActive );
|
|
|
|
|
|
if( CanCharacterMoveInStrategic( pSoldier, &bErrorNumber ) )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
else
|
|
{
|
|
// function may fail without returning any specific error # (-1).
|
|
// if it gave us the # of an error msg, and we were told to display it
|
|
if ( ( bErrorNumber != -1 ) && fShowErrorMessage )
|
|
{
|
|
ReportMapScreenMovementError( bErrorNumber );
|
|
}
|
|
|
|
return( FALSE );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void SelectAllOtherSoldiersInList( void )
|
|
{
|
|
INT32 iCounter = 0;
|
|
BOOLEAN fSomeCantMove = FALSE;
|
|
|
|
|
|
for( iCounter = 0; iCounter < giNumberOfSoldiersInSectorMoving; iCounter++ )
|
|
{
|
|
if( ( pSoldierMovingList[ iCounter ]->bAssignment >= ON_DUTY ) && ( pSoldierMovingList[ iCounter ]->bAssignment != VEHICLE ) )
|
|
{
|
|
if ( CanMoveBoxSoldierMoveStrategically( pSoldierMovingList[ iCounter ], FALSE ) )
|
|
{
|
|
fSoldierIsMoving[ iCounter ] = TRUE;
|
|
}
|
|
else
|
|
{
|
|
fSomeCantMove = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( fSomeCantMove )
|
|
{
|
|
// can't - some of the OTHER soldiers can't move
|
|
ReportMapScreenMovementError( 46 );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void DeselectAllOtherSoldiersInList( void )
|
|
{
|
|
INT32 iCounter = 0;
|
|
|
|
for( iCounter = 0; iCounter < giNumberOfSoldiersInSectorMoving; iCounter++ )
|
|
{
|
|
if( ( pSoldierMovingList[ iCounter ]->bAssignment >= ON_DUTY ) && ( pSoldierMovingList[ iCounter ]->bAssignment != VEHICLE ) )
|
|
{
|
|
fSoldierIsMoving[ iCounter ] = FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void HandleMoveoutOfSectorMovementTroops( void )
|
|
{
|
|
INT32 iCounter = 0;
|
|
SOLDIERTYPE *pSoldier = 0;
|
|
INT32 iSquadNumber = -1;
|
|
BOOLEAN fCheckForCompatibleSquad = FALSE;
|
|
|
|
|
|
// cancel move box
|
|
fShowMapScreenMovementList = FALSE;
|
|
|
|
|
|
for( iCounter = 0; iCounter < giNumberOfSoldiersInSectorMoving; iCounter++ )
|
|
{
|
|
pSoldier = pSoldierMovingList[ iCounter ];
|
|
|
|
fCheckForCompatibleSquad = FALSE;
|
|
|
|
// if he is on a valid squad
|
|
if( pSoldier->bAssignment < ON_DUTY )
|
|
{
|
|
// if he and his squad are parting ways (soldier is staying behind, but squad is leaving, or vice versa)
|
|
if( fSoldierIsMoving[ iCounter ] != IsSquadSelectedForMovement( pSoldier->bAssignment ) )
|
|
{
|
|
// split the guy from his squad to any other compatible squad
|
|
fCheckForCompatibleSquad = TRUE;
|
|
}
|
|
}
|
|
// if in a vehicle
|
|
else if( pSoldier->bAssignment == VEHICLE )
|
|
{
|
|
// if he and his vehicle are parting ways (soldier is staying behind, but vehicle is leaving, or vice versa)
|
|
if( fSoldierIsMoving[ iCounter ] != IsVehicleSelectedForMovement( pSoldier->iVehicleId ) )
|
|
{
|
|
// split the guy from his vehicle to any other compatible squad
|
|
fCheckForCompatibleSquad = TRUE;
|
|
}
|
|
}
|
|
else // on his own - not on a squad or in a vehicle
|
|
{
|
|
// if he's going anywhere
|
|
if( fSoldierIsMoving[ iCounter ] )
|
|
{
|
|
// find out if anyone is going with this guy...see if he can tag along
|
|
fCheckForCompatibleSquad = TRUE;
|
|
}
|
|
}
|
|
|
|
|
|
if ( fCheckForCompatibleSquad )
|
|
{
|
|
// look for a squad that's doing the same thing as this guy is and has room for him
|
|
iSquadNumber = FindSquadThatSoldierCanJoin( pSoldier );
|
|
if( iSquadNumber != -1 )
|
|
{
|
|
if ( !AddCharacterToSquad( pSoldier, ( INT8 )( iSquadNumber ) ) )
|
|
{
|
|
AssertMsg( 0, String( "HandleMoveoutOfSectorMovementTroops: AddCharacterToSquad %d failed, iCounter %d", iSquadNumber, iCounter ) );
|
|
// toggle whether he's going or not to try and recover somewhat gracefully
|
|
fSoldierIsMoving[ iCounter ] = !fSoldierIsMoving[ iCounter ];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// no existing squad is compatible, will have to start his own new squad
|
|
iSquadNumber = AddCharacterToUniqueSquad( pSoldier );
|
|
if ( iSquadNumber != -1 )
|
|
{
|
|
// It worked. Add his new squad to the "moving squads" list so others can join it, too!
|
|
AddSquadToMovingLists( iSquadNumber );
|
|
|
|
// If this guy is moving
|
|
if( fSoldierIsMoving[ iCounter ] )
|
|
{
|
|
// mark this new squad as moving too, so those moving can join it
|
|
SelectSquadForMovement( iSquadNumber );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// failed - should never happen!
|
|
AssertMsg( 0, String( "HandleMoveoutOfSectorMovementTroops: AddCharacterToUniqueSquad failed, iCounter %d", iCounter ) );
|
|
// toggle whether he's going or not to try and recover somewhat gracefully
|
|
fSoldierIsMoving[ iCounter ] = !fSoldierIsMoving[ iCounter ];
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
// now actually set the list
|
|
HandleSettingTheSelectedListOfMercs( );
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void HandleSettingTheSelectedListOfMercs( void )
|
|
{
|
|
BOOLEAN fFirstOne = TRUE;
|
|
INT32 iCounter = 0;
|
|
SOLDIERTYPE *pSoldier = NULL;
|
|
BOOLEAN fSelected;
|
|
|
|
|
|
// reset the selected character
|
|
bSelectedDestChar = -1;
|
|
|
|
// run through the list of grunts
|
|
for( iCounter = 0; iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; iCounter++ )
|
|
{
|
|
// is the current guy a valid character?
|
|
if( gCharactersList[ iCounter ].fValid == TRUE )
|
|
{
|
|
pSoldier = MercPtrs[ gCharactersList[ iCounter ].usSolID ];
|
|
|
|
if ( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE )
|
|
{
|
|
fSelected = IsVehicleSelectedForMovement( pSoldier->bVehicleID );
|
|
}
|
|
else
|
|
{
|
|
fSelected = IsSoldierSelectedForMovement( pSoldier );
|
|
}
|
|
|
|
// is he/she selected for movement?
|
|
if( fSelected )
|
|
{
|
|
// yes, are they the first one to be selected?
|
|
if( fFirstOne == TRUE )
|
|
{
|
|
// yes, then set them as the destination plotting character for movement arrow purposes
|
|
fFirstOne = FALSE;
|
|
|
|
bSelectedDestChar = ( INT8 )iCounter;
|
|
// make DEST column glow
|
|
giDestHighLine = iCounter;
|
|
|
|
ChangeSelectedInfoChar( ( INT8 ) iCounter, TRUE );
|
|
}
|
|
|
|
// add this guy to the selected list of grunts
|
|
SetEntryInSelectedCharacterList( ( INT8 )iCounter );
|
|
}
|
|
}
|
|
}
|
|
|
|
if( bSelectedDestChar != -1 )
|
|
{
|
|
// set cursor
|
|
SetUpCursorForStrategicMap( );
|
|
fTeamPanelDirty = TRUE;
|
|
fMapPanelDirty = TRUE;
|
|
fCharacterInfoPanelDirty = TRUE;
|
|
|
|
DeselectSelectedListMercsWhoCantMoveWithThisGuy( &( Menptr[ gCharactersList[ bSelectedDestChar ].usSolID ] ) );
|
|
|
|
// remember the current paths for all selected characters so we can restore them if need be
|
|
RememberPreviousPathForAllSelectedChars();
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
INT32 GetSquadListIndexForSquadNumber( INT32 iSquadNumber )
|
|
{
|
|
INT32 iCounter = 0;
|
|
|
|
for( iCounter = 0; iCounter < giNumberOfSquadsInSectorMoving; iCounter++ )
|
|
{
|
|
if( iSquadMovingList[ iCounter ] == iSquadNumber )
|
|
{
|
|
return( iCounter );
|
|
}
|
|
}
|
|
|
|
return( -1 );
|
|
}
|
|
*/
|
|
|
|
|
|
BOOLEAN AllOtherSoldiersInListAreSelected( void )
|
|
{
|
|
INT32 iCounter = 0, iCount = 0;
|
|
|
|
for( iCounter = 0; iCounter < giNumberOfSoldiersInSectorMoving; iCounter++ )
|
|
{
|
|
if( ( pSoldierMovingList[ iCounter ]->bAssignment >= ON_DUTY ) && ( pSoldierMovingList[ iCounter ]->bAssignment >= VEHICLE ) )
|
|
{
|
|
if( fSoldierIsMoving[ iCounter ] == FALSE )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
iCount++;
|
|
}
|
|
}
|
|
|
|
// some merc on other assignments and no result?
|
|
if( iCount )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
|
|
return( FALSE );
|
|
}
|
|
|
|
|
|
BOOLEAN IsThisSquadInThisSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, INT8 bSquadValue )
|
|
{
|
|
INT16 sX = 0, sY = 0;
|
|
INT8 bZ = 0;
|
|
|
|
// check if the squad is empty
|
|
if( SquadIsEmpty( bSquadValue ) == FALSE )
|
|
{
|
|
// now grab the squad location
|
|
GetLocationOfSquad( &sX, &sY, &bZ, bSquadValue );
|
|
|
|
// check if this non-empty squad is in this sector
|
|
if( ( sX == sSectorX ) && ( sY == sSectorY ) && ( bSectorZ == bZ ) )
|
|
{
|
|
// a squad that's between sectors isn't *in* this sector
|
|
if( !IsThisSquadOnTheMove( bSquadValue ) )
|
|
{
|
|
// yep
|
|
return( TRUE );
|
|
}
|
|
}
|
|
}
|
|
|
|
// nope
|
|
return( FALSE );
|
|
}
|
|
|
|
|
|
INT8 FindSquadThatSoldierCanJoin( SOLDIERTYPE *pSoldier )
|
|
{
|
|
// look for a squad that isn't full that can take this character
|
|
INT8 bCounter = 0;
|
|
|
|
// run through the list of squads
|
|
for( bCounter = 0; bCounter < NUMBER_OF_SQUADS; bCounter++ )
|
|
{
|
|
// is this squad in this sector
|
|
if( IsThisSquadInThisSector( pSoldier->sSectorX, pSoldier->sSectorY, pSoldier->bSectorZ, bCounter ) )
|
|
{
|
|
// does it have room?
|
|
if( IsThisSquadFull( bCounter ) == FALSE )
|
|
{
|
|
// is it doing the same thing as the soldier is (staying or going) ?
|
|
if( IsSquadSelectedForMovement( bCounter ) == IsSoldierSelectedForMovement( pSoldier ) )
|
|
{
|
|
// go ourselves a match, then
|
|
return( bCounter );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return( -1 );
|
|
}
|
|
|
|
void ReBuildMoveBox( void )
|
|
{
|
|
// check to see if we need to rebuild the movement box and mouse regions
|
|
if( fRebuildMoveBox == FALSE )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// reset the fact
|
|
fRebuildMoveBox = FALSE;
|
|
fTeamPanelDirty = TRUE;
|
|
fMapPanelDirty = TRUE;
|
|
fCharacterInfoPanelDirty = TRUE;
|
|
|
|
// stop showing the box
|
|
fShowMapScreenMovementList = FALSE;
|
|
CreateDestroyMovementBox( sSelMapX, sSelMapY, ( INT16 )iCurrentMapSectorZ );
|
|
|
|
// show the box
|
|
fShowMapScreenMovementList = TRUE;
|
|
CreateDestroyMovementBox( sSelMapX, sSelMapY, ( INT16 )iCurrentMapSectorZ );
|
|
ShowBox( ghMoveBox );
|
|
MarkAllBoxesAsAltered( );
|
|
}
|
|
|
|
|
|
void CreateScreenMaskForMoveBox( void )
|
|
{
|
|
if( fScreenMaskForMoveCreated == FALSE )
|
|
{
|
|
// set up the screen mask
|
|
MSYS_DefineRegion( &gMoveBoxScreenMask, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, MSYS_PRIORITY_HIGHEST - 4,
|
|
MSYS_NO_CURSOR, MSYS_NO_CALLBACK, MoveScreenMaskBtnCallback );
|
|
|
|
fScreenMaskForMoveCreated = TRUE;
|
|
}
|
|
}
|
|
|
|
void RemoveScreenMaskForMoveBox( void )
|
|
{
|
|
if( fScreenMaskForMoveCreated == TRUE )
|
|
{
|
|
// remove the screen mask
|
|
MSYS_RemoveRegion( &gMoveBoxScreenMask );
|
|
fScreenMaskForMoveCreated = FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
void MoveScreenMaskBtnCallback(MOUSE_REGION * pRegion, INT32 iReason )
|
|
{
|
|
// btn callback handler for move box screen mask region
|
|
if( ( iReason & MSYS_CALLBACK_REASON_LBUTTON_UP ) )
|
|
{
|
|
fShowMapScreenMovementList = FALSE;
|
|
}
|
|
else if( iReason & MSYS_CALLBACK_REASON_RBUTTON_UP )
|
|
{
|
|
sSelectedMilitiaTown = 0;
|
|
|
|
// are we showing the update box
|
|
if( fShowUpdateBox )
|
|
{
|
|
fShowUpdateBox = FALSE;
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void ResetSoldierUpdateBox( void )
|
|
{
|
|
INT32 iCounter = 0;
|
|
|
|
// delete any loaded faces
|
|
for( iCounter = 0; iCounter < SIZE_OF_UPDATE_BOX; iCounter++ )
|
|
{
|
|
if( pUpdateSoldierBox[ iCounter ] != NULL )
|
|
{
|
|
DeleteVideoObjectFromIndex( giUpdateSoldierFaces[ iCounter ] );
|
|
}
|
|
}
|
|
|
|
if( giMercPanelImage != 0 )
|
|
{
|
|
DeleteVideoObjectFromIndex( giMercPanelImage );
|
|
}
|
|
|
|
// reset the soldier ptrs in the update box
|
|
for( iCounter = 0; iCounter < SIZE_OF_UPDATE_BOX; iCounter++ )
|
|
{
|
|
pUpdateSoldierBox[ iCounter ] = NULL;
|
|
}
|
|
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
INT32 GetNumberOfMercsInUpdateList( void )
|
|
{
|
|
INT32 iCounter = 0, iCount = 0;
|
|
|
|
// run through the non-empty slots
|
|
for( iCounter = 0; iCounter < SIZE_OF_UPDATE_BOX; iCounter++ )
|
|
{
|
|
// valid guy here
|
|
if( pUpdateSoldierBox[ iCounter ] != NULL )
|
|
{
|
|
iCount++;
|
|
}
|
|
}
|
|
|
|
return( iCount );
|
|
}
|
|
|
|
BOOLEAN IsThePopUpBoxEmpty( void )
|
|
{
|
|
INT32 iCounter = 0;
|
|
BOOLEAN fEmpty = TRUE;
|
|
|
|
// run through the non-empty slots
|
|
for( iCounter = 0; iCounter < SIZE_OF_UPDATE_BOX; iCounter++ )
|
|
{
|
|
// valid guy here
|
|
if( pUpdateSoldierBox[ iCounter ] != NULL )
|
|
{
|
|
fEmpty = FALSE;
|
|
}
|
|
}
|
|
|
|
return( fEmpty );
|
|
}
|
|
|
|
|
|
void AddSoldierToWaitingListQueue( SOLDIERTYPE *pSoldier )
|
|
{
|
|
INT32 iSoldierId = 0;
|
|
|
|
|
|
// get soldier profile
|
|
iSoldierId = pSoldier->ubID;
|
|
|
|
SpecialCharacterDialogueEvent( DIALOGUE_ADD_EVENT_FOR_SOLDIER_UPDATE_BOX, UPDATE_BOX_REASON_ADDSOLDIER, iSoldierId, 0, 0, 0 );
|
|
return;
|
|
}
|
|
|
|
|
|
void AddReasonToWaitingListQueue( INT32 iReason )
|
|
{
|
|
SpecialCharacterDialogueEvent( DIALOGUE_ADD_EVENT_FOR_SOLDIER_UPDATE_BOX, UPDATE_BOX_REASON_SET_REASON, iReason, 0, 0, 0 );
|
|
return;
|
|
}
|
|
|
|
|
|
void AddDisplayBoxToWaitingQueue( void )
|
|
{
|
|
SpecialCharacterDialogueEvent( DIALOGUE_ADD_EVENT_FOR_SOLDIER_UPDATE_BOX, UPDATE_BOX_REASON_SHOW_BOX, 0, 0, 0, 0 );
|
|
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void ShowUpdateBox( void )
|
|
{
|
|
// we want to show the box
|
|
fShowUpdateBox = TRUE;
|
|
}
|
|
|
|
void AddSoldierToUpdateBox( SOLDIERTYPE *pSoldier )
|
|
{
|
|
INT32 iCounter = 0;
|
|
VOBJECT_DESC VObjectDesc;
|
|
|
|
|
|
|
|
// going to load face
|
|
VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE;
|
|
|
|
if( pSoldier->stats.bLife == 0 )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if( pSoldier->bActive == FALSE )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// if update
|
|
if( pUpdateSoldierBox[ iCounter ] == NULL )
|
|
{
|
|
sprintf( VObjectDesc.ImageFile, "Interface\\panels.sti" );
|
|
if( !AddVideoObject( &VObjectDesc, (UINT32 *)&giMercPanelImage ) )
|
|
{
|
|
AssertMsg( 0, "Failed to load Interface\\panels.sti" );
|
|
}
|
|
}
|
|
|
|
// run thought list of update soldiers
|
|
for( iCounter = 0; iCounter < SIZE_OF_UPDATE_BOX; iCounter++ )
|
|
{
|
|
// find a free slot
|
|
if( pUpdateSoldierBox[ iCounter ] == NULL )
|
|
{
|
|
// add to box
|
|
pUpdateSoldierBox[ iCounter ] = pSoldier;
|
|
|
|
|
|
|
|
if ( ( gMercProfiles[ pSoldier->ubProfile ].ubFaceIndex < 100 ) && ( gProfilesIMP[ pSoldier->ubProfile ].ProfilId == pSoldier->ubProfile ) )
|
|
{
|
|
sprintf( VObjectDesc.ImageFile, "IMPFaces\\65Face\\%02d.sti", gMercProfiles[ pSoldier->ubProfile ].ubFaceIndex );
|
|
}
|
|
else if ( ( gMercProfiles[ pSoldier->ubProfile ].ubFaceIndex > 99 ) && ( gProfilesIMP[ pSoldier->ubProfile ].ProfilId == pSoldier->ubProfile ) )
|
|
{
|
|
sprintf( VObjectDesc.ImageFile, "IMPFaces\\65Face\\%03d.sti", gMercProfiles[ pSoldier->ubProfile ].ubFaceIndex );
|
|
}
|
|
else if( gMercProfiles[ pSoldier->ubProfile ].ubFaceIndex < 100 )
|
|
{
|
|
sprintf( VObjectDesc.ImageFile, "Faces\\65Face\\%02d.sti", gMercProfiles[ pSoldier->ubProfile ].ubFaceIndex );
|
|
}
|
|
else if( gMercProfiles[ pSoldier->ubProfile ].ubFaceIndex > 99 )
|
|
{
|
|
sprintf( VObjectDesc.ImageFile, "Faces\\65Face\\%03d.sti", gMercProfiles[ pSoldier->ubProfile ].ubFaceIndex );
|
|
}
|
|
|
|
|
|
/*
|
|
if( gMercProfiles[ pSoldier->ubProfile ].ubFaceIndex < 100 )
|
|
{
|
|
// grab filename of face
|
|
sprintf( VObjectDesc.ImageFile, "Faces\\65Face\\%02d.sti", gMercProfiles[ pSoldier->ubProfile ].ubFaceIndex );
|
|
}
|
|
else
|
|
{
|
|
// grab filename of face
|
|
sprintf( VObjectDesc.ImageFile, "Faces\\65Face\\%03d.sti", gMercProfiles[ pSoldier->ubProfile ].ubFaceIndex );
|
|
}
|
|
*/
|
|
// load the face
|
|
AddVideoObject( &VObjectDesc, (UINT32 *)&giUpdateSoldierFaces[ iCounter ] );
|
|
|
|
return;
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
void SetSoldierUpdateBoxReason( INT32 iReason )
|
|
{
|
|
//set the reason for the update
|
|
iReasonForSoldierUpDate = iReason;
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void DisplaySoldierUpdateBox( )
|
|
{
|
|
INT32 iNumberOfMercsOnUpdatePanel = 0;
|
|
INT32 iNumberHigh = 0, iNumberWide = 0;
|
|
INT32 iUpdatePanelWidth = 0, iUpdatePanelHeight = 0;
|
|
INT32 iX = 0, iY = 0;
|
|
INT32 iFaceX = 0, iFaceY = 0;
|
|
BOOLEAN fFourWideMode = FALSE;
|
|
HVOBJECT hBackGroundHandle;
|
|
INT32 iCounter = 0;
|
|
CHAR16 sString[ 32 ];
|
|
INT32 iUpperLimit = 0;
|
|
|
|
|
|
if( fShowUpdateBox == FALSE )
|
|
{
|
|
return;
|
|
}
|
|
|
|
|
|
// get the number of mercs
|
|
iNumberOfMercsOnUpdatePanel = GetNumberOfMercsInUpdateList( );
|
|
|
|
if( iNumberOfMercsOnUpdatePanel == 0 )
|
|
{
|
|
// nobody home
|
|
fShowUpdateBox = FALSE;
|
|
// unpause
|
|
UnPauseDialogueQueue( );
|
|
return;
|
|
}
|
|
|
|
giSleepHighLine = -1;
|
|
giDestHighLine = -1;
|
|
giContractHighLine = -1;
|
|
giAssignHighLine = -1;
|
|
|
|
|
|
//InterruptTime();
|
|
PauseGame( );
|
|
LockPauseState( 4 );
|
|
|
|
PauseDialogueQueue( );
|
|
|
|
// do we have enough for 4 wide, or just 2 wide?
|
|
if( iNumberOfMercsOnUpdatePanel > NUMBER_OF_MERCS_FOR_FOUR_WIDTH_UPDATE_PANEL )
|
|
{
|
|
fFourWideMode = TRUE;
|
|
}
|
|
|
|
// get number of rows
|
|
iNumberHigh = ( fFourWideMode ? iNumberOfMercsOnUpdatePanel / NUMBER_OF_MERC_COLUMNS_FOR_FOUR_WIDE_MODE
|
|
: iNumberOfMercsOnUpdatePanel / NUMBER_OF_MERC_COLUMNS_FOR_TWO_WIDE_MODE);
|
|
|
|
//number of columns
|
|
iNumberWide = ( fFourWideMode ? NUMBER_OF_MERC_COLUMNS_FOR_FOUR_WIDE_MODE
|
|
: NUMBER_OF_MERC_COLUMNS_FOR_TWO_WIDE_MODE );
|
|
|
|
|
|
|
|
// get the height and width of the box .. will need to add in stuff for borders, lower panel...etc
|
|
if( fFourWideMode )
|
|
{
|
|
// do we need an extra row for left overs
|
|
if( iNumberOfMercsOnUpdatePanel % NUMBER_OF_MERC_COLUMNS_FOR_FOUR_WIDE_MODE )
|
|
{
|
|
iNumberHigh++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// do we need an extra row for left overs
|
|
if( iNumberOfMercsOnUpdatePanel % NUMBER_OF_MERC_COLUMNS_FOR_TWO_WIDE_MODE )
|
|
{
|
|
iNumberHigh++;
|
|
}
|
|
}
|
|
|
|
// round off
|
|
if( fFourWideMode )
|
|
{
|
|
if(iNumberOfMercsOnUpdatePanel % NUMBER_OF_MERC_COLUMNS_FOR_FOUR_WIDE_MODE )
|
|
{
|
|
iNumberOfMercsOnUpdatePanel += NUMBER_OF_MERC_COLUMNS_FOR_FOUR_WIDE_MODE - ( iNumberOfMercsOnUpdatePanel % NUMBER_OF_MERC_COLUMNS_FOR_FOUR_WIDE_MODE );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(iNumberOfMercsOnUpdatePanel % NUMBER_OF_MERC_COLUMNS_FOR_TWO_WIDE_MODE )
|
|
{
|
|
iNumberOfMercsOnUpdatePanel += NUMBER_OF_MERC_COLUMNS_FOR_TWO_WIDE_MODE - ( iNumberOfMercsOnUpdatePanel % NUMBER_OF_MERC_COLUMNS_FOR_TWO_WIDE_MODE );
|
|
}
|
|
}
|
|
|
|
iUpdatePanelWidth = iNumberWide * TACT_WIDTH_OF_UPDATE_PANEL_BLOCKS;
|
|
|
|
iUpdatePanelHeight = ( iNumberHigh + 1 ) * TACT_HEIGHT_OF_UPDATE_PANEL_BLOCKS;
|
|
|
|
iX = (MAP_BORDER_X + ((SCREEN_WIDTH - MAP_BORDER_X) / 2)) - (iUpdatePanelWidth / 2);
|
|
iY = (MAP_BORDER_Y + ((SCREEN_HEIGHT - 121) / 2)) - (iUpdatePanelHeight / 2);
|
|
|
|
GetVideoObject( &hBackGroundHandle, guiUpdatePanelTactical );
|
|
|
|
//Display the 2 TOP corner pieces
|
|
BltVideoObject( guiSAVEBUFFER, hBackGroundHandle, 0, iX-4, iY - 4 , VO_BLT_SRCTRANSPARENCY,NULL );
|
|
BltVideoObject( guiSAVEBUFFER, hBackGroundHandle, 2, iX+iUpdatePanelWidth, iY - 4 , VO_BLT_SRCTRANSPARENCY,NULL );
|
|
|
|
if( fFourWideMode )
|
|
{
|
|
//Display 2 vertical lines starting at the bottom
|
|
BltVideoObject( guiSAVEBUFFER , hBackGroundHandle, 3, iX - 4, iY + iUpdatePanelHeight - 3 - 70, VO_BLT_SRCTRANSPARENCY,NULL );
|
|
BltVideoObject( guiSAVEBUFFER , hBackGroundHandle, 5, iX + iUpdatePanelWidth, iY + iUpdatePanelHeight - 3 - 70, VO_BLT_SRCTRANSPARENCY,NULL );
|
|
|
|
//Display the 2 bottom corner pieces
|
|
BltVideoObject( guiSAVEBUFFER, hBackGroundHandle, 0, iX-4, iY + iUpdatePanelHeight - 3, VO_BLT_SRCTRANSPARENCY,NULL );
|
|
BltVideoObject( guiSAVEBUFFER, hBackGroundHandle, 2, iX+iUpdatePanelWidth, iY + iUpdatePanelHeight - 3, VO_BLT_SRCTRANSPARENCY,NULL );
|
|
}
|
|
|
|
|
|
SetFontDestBuffer( guiSAVEBUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, FALSE );
|
|
|
|
iUpperLimit = fFourWideMode ? ( iNumberOfMercsOnUpdatePanel + NUMBER_OF_MERC_COLUMNS_FOR_FOUR_WIDE_MODE ) : ( iNumberOfMercsOnUpdatePanel + NUMBER_OF_MERC_COLUMNS_FOR_TWO_WIDE_MODE );
|
|
|
|
//need to put the background down first
|
|
for( iCounter = 0; iCounter < iUpperLimit; iCounter++ )
|
|
{
|
|
// blt the face and name
|
|
|
|
// get the face x and y
|
|
iFaceX = iX + ( iCounter % iNumberWide ) * TACT_UPDATE_MERC_FACE_X_WIDTH;
|
|
iFaceY = iY + ( iCounter / iNumberWide ) * TACT_UPDATE_MERC_FACE_X_HEIGHT;
|
|
|
|
BltVideoObject( guiSAVEBUFFER , hBackGroundHandle, 20, iFaceX, iFaceY , VO_BLT_SRCTRANSPARENCY,NULL );
|
|
}
|
|
|
|
//loop through the mercs to be displayed
|
|
for( iCounter = 0; iCounter < ( iNumberOfMercsOnUpdatePanel <= NUMBER_OF_MERC_COLUMNS_FOR_TWO_WIDE_MODE ? NUMBER_OF_MERC_COLUMNS_FOR_TWO_WIDE_MODE : iNumberOfMercsOnUpdatePanel ); iCounter++ )
|
|
{
|
|
//
|
|
// blt the face and name
|
|
//
|
|
|
|
// get the face x and y
|
|
iFaceX = iX + ( iCounter % iNumberWide ) * TACT_UPDATE_MERC_FACE_X_WIDTH;
|
|
iFaceY = iY + ( iCounter / iNumberWide ) * TACT_UPDATE_MERC_FACE_X_HEIGHT + REASON_FOR_SOLDIER_UPDATE_OFFSET_Y;
|
|
|
|
// now get the face
|
|
if( pUpdateSoldierBox[ iCounter ] )
|
|
{
|
|
iFaceX += TACT_UPDATE_MERC_FACE_X_OFFSET;
|
|
iFaceY += TACT_UPDATE_MERC_FACE_Y_OFFSET;
|
|
|
|
// there is a face
|
|
RenderSoldierSmallFaceForUpdatePanel( iCounter, iFaceX, iFaceY );
|
|
|
|
// display the mercs name
|
|
swprintf( sString, L"%s", pUpdateSoldierBox[ iCounter ]->name );
|
|
DrawTextToScreen( sString, (UINT16)(iFaceX-5), (UINT16)(iFaceY + 31), 57, TINYFONT1, FONT_LTRED, FONT_BLACK, 0, CENTER_JUSTIFIED );
|
|
}
|
|
}
|
|
|
|
// the button container box
|
|
if( fFourWideMode )
|
|
{
|
|
//def: 3/1/99 WAS SUBINDEX 6,
|
|
BltVideoObject( guiSAVEBUFFER , hBackGroundHandle, 19, iX - 4 + TACT_UPDATE_MERC_FACE_X_WIDTH, iY + iNumberHigh * TACT_UPDATE_MERC_FACE_X_HEIGHT + REASON_FOR_SOLDIER_UPDATE_OFFSET_Y+3, VO_BLT_SRCTRANSPARENCY,NULL );
|
|
|
|
// ATE: Display string for time compression
|
|
DisplayWrappedString( ( UINT16 )( iX ), ( UINT16 )( iY + iNumberHigh * TACT_UPDATE_MERC_FACE_X_HEIGHT + 5 + REASON_FOR_SOLDIER_UPDATE_OFFSET_Y + 3), ( UINT16 )( iUpdatePanelWidth ), 0, MAP_SCREEN_FONT, FONT_WHITE, gzLateLocalizedString[49], FONT_BLACK, 0, CENTER_JUSTIFIED );
|
|
}
|
|
else
|
|
{
|
|
//def: 3/1/99 WAS SUBINDEX 6,
|
|
BltVideoObject( guiSAVEBUFFER , hBackGroundHandle, 19, iX - 4 , iY + iNumberHigh * TACT_UPDATE_MERC_FACE_X_HEIGHT + REASON_FOR_SOLDIER_UPDATE_OFFSET_Y+3, VO_BLT_SRCTRANSPARENCY,NULL );
|
|
|
|
// ATE: Display string for time compression
|
|
DisplayWrappedString( ( UINT16 )( iX ), ( UINT16 )( iY + iNumberHigh * TACT_UPDATE_MERC_FACE_X_HEIGHT + 5 + REASON_FOR_SOLDIER_UPDATE_OFFSET_Y+3 ), ( UINT16 )( iUpdatePanelWidth ), 0, MAP_SCREEN_FONT, FONT_WHITE, gzLateLocalizedString[49], FONT_BLACK, 0, CENTER_JUSTIFIED );
|
|
}
|
|
|
|
iCounter = 0;
|
|
|
|
// now wrap the border
|
|
for( iCounter = 0; iCounter < iNumberHigh ; iCounter++ )
|
|
{
|
|
// the sides
|
|
BltVideoObject( guiSAVEBUFFER , hBackGroundHandle, 3, iX - 4, iY + ( iCounter ) * TACT_UPDATE_MERC_FACE_X_HEIGHT, VO_BLT_SRCTRANSPARENCY,NULL );
|
|
BltVideoObject( guiSAVEBUFFER , hBackGroundHandle, 5, iX + iUpdatePanelWidth, iY + ( iCounter ) * TACT_UPDATE_MERC_FACE_X_HEIGHT, VO_BLT_SRCTRANSPARENCY,NULL );
|
|
}
|
|
|
|
//big horizontal line
|
|
for( iCounter = 0; iCounter < iNumberWide; iCounter++ )
|
|
{
|
|
// the top bottom
|
|
BltVideoObject( guiSAVEBUFFER , hBackGroundHandle, 1, iX + TACT_UPDATE_MERC_FACE_X_WIDTH * (iCounter ) , iY - 4 , VO_BLT_SRCTRANSPARENCY,NULL );
|
|
BltVideoObject( guiSAVEBUFFER , hBackGroundHandle, 1, iX + TACT_UPDATE_MERC_FACE_X_WIDTH * (iCounter ) , iY + iUpdatePanelHeight - 3 , VO_BLT_SRCTRANSPARENCY,NULL );
|
|
}
|
|
|
|
|
|
//Display the reason for the update box
|
|
if( fFourWideMode )
|
|
{
|
|
DisplayWrappedString( ( INT16 )( iX ), ( INT16 )( iY + 6 ), (INT16)iUpdatePanelWidth, 0, MAP_SCREEN_FONT, FONT_WHITE, pUpdateMercStrings[ iReasonForSoldierUpDate ], FONT_BLACK, 0, CENTER_JUSTIFIED );
|
|
}
|
|
else
|
|
{
|
|
DisplayWrappedString( ( INT16 )( iX ), ( INT16 )( iY + 3 ), (INT16)iUpdatePanelWidth, 0, MAP_SCREEN_FONT, FONT_WHITE, pUpdateMercStrings[ iReasonForSoldierUpDate ], FONT_BLACK, 0, CENTER_JUSTIFIED );
|
|
}
|
|
|
|
|
|
SetFontDestBuffer( FRAME_BUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, FALSE );
|
|
|
|
// restore extern background rect
|
|
RestoreExternBackgroundRect( ( INT16 )( iX - 5 ), ( INT16 )( iY - 5 ), ( INT16 )( iUpdatePanelWidth + 10 ), ( INT16 )(iUpdatePanelHeight + 6 ) );
|
|
|
|
CreateDestroyUpdatePanelButtons( iX, ( iY + iUpdatePanelHeight - 18 ), fFourWideMode );
|
|
MarkAButtonDirty( guiUpdatePanelButtons[ 0 ] );
|
|
MarkAButtonDirty( guiUpdatePanelButtons[ 1 ] );
|
|
return;
|
|
}
|
|
|
|
|
|
void CreateDestroyUpdatePanelButtons(INT32 iX, INT32 iY, BOOLEAN fFourWideMode )
|
|
{
|
|
static BOOLEAN fCreated = FALSE;
|
|
|
|
if( ( fShowUpdateBox == TRUE ) && ( fCreated == FALSE ) )
|
|
{
|
|
// set to created
|
|
fCreated = TRUE;
|
|
|
|
fShowAssignmentMenu = FALSE;
|
|
fShowContractMenu = FALSE;
|
|
|
|
// guiUpdatePanelButtonsImage[ 0 ]= LoadButtonImage( "INTERFACE\\group_confirm.sti" ,-1,7,-1,8,-1 );
|
|
// guiUpdatePanelButtonsImage[ 1 ] = LoadButtonImage( "INTERFACE\\group_confirm.sti" ,-1,7,-1,8,-1 );
|
|
guiUpdatePanelButtonsImage[ 0 ]= LoadButtonImage( "INTERFACE\\group_confirm_tactical.sti" ,-1,7,-1,8,-1 );
|
|
guiUpdatePanelButtonsImage[ 1 ] = LoadButtonImage( "INTERFACE\\group_confirm_tactical.sti" ,-1,7,-1,8,-1 );
|
|
|
|
if( fFourWideMode )
|
|
{
|
|
guiUpdatePanelButtons[ 0 ] = QuickCreateButton( guiUpdatePanelButtonsImage[ 0 ], ( INT16 )( iX - 4 + TACT_UPDATE_MERC_FACE_X_WIDTH + 4), (INT16)iY,
|
|
BUTTON_TOGGLE, MSYS_PRIORITY_HIGHEST - 1,
|
|
(GUI_CALLBACK)BtnGenericMouseMoveButtonCallback, (GUI_CALLBACK)ContinueUpdateButtonCallback );
|
|
|
|
guiUpdatePanelButtons[ 1 ] = QuickCreateButton( guiUpdatePanelButtonsImage[ 1 ], ( INT16 ) ( iX - 4 + 2 * TACT_UPDATE_MERC_FACE_X_WIDTH + 4 ), (INT16)iY,
|
|
BUTTON_TOGGLE, MSYS_PRIORITY_HIGHEST - 1,
|
|
(GUI_CALLBACK)BtnGenericMouseMoveButtonCallback, (GUI_CALLBACK)StopUpdateButtonCallback);
|
|
}
|
|
else
|
|
{
|
|
guiUpdatePanelButtons[ 0 ] = QuickCreateButton( guiUpdatePanelButtonsImage[ 0 ], ( INT16 )( iX), (INT16)iY,
|
|
BUTTON_TOGGLE, MSYS_PRIORITY_HIGHEST -1,
|
|
(GUI_CALLBACK)BtnGenericMouseMoveButtonCallback, (GUI_CALLBACK)ContinueUpdateButtonCallback);
|
|
|
|
guiUpdatePanelButtons[ 1 ] = QuickCreateButton( guiUpdatePanelButtonsImage[ 1 ], ( INT16 )( iX + TACT_UPDATE_MERC_FACE_X_WIDTH ), (INT16)iY,
|
|
BUTTON_TOGGLE, MSYS_PRIORITY_HIGHEST - 1,
|
|
(GUI_CALLBACK)BtnGenericMouseMoveButtonCallback, (GUI_CALLBACK)StopUpdateButtonCallback);
|
|
|
|
}
|
|
|
|
SpecifyButtonText( guiUpdatePanelButtons[ 0 ], pUpdatePanelButtons[ 0 ] );
|
|
SpecifyButtonFont( guiUpdatePanelButtons[ 0 ], MAP_SCREEN_FONT );
|
|
SpecifyButtonUpTextColors( guiUpdatePanelButtons[ 0 ], FONT_MCOLOR_BLACK, FONT_BLACK );
|
|
SpecifyButtonDownTextColors( guiUpdatePanelButtons[ 0 ], FONT_MCOLOR_BLACK, FONT_BLACK );
|
|
SetButtonFastHelpText( guiUpdatePanelButtons[ 0 ], gzLateLocalizedString[51] );
|
|
|
|
SpecifyButtonText( guiUpdatePanelButtons[ 1 ], pUpdatePanelButtons[ 1 ] );
|
|
SpecifyButtonFont( guiUpdatePanelButtons[ 1 ], MAP_SCREEN_FONT );
|
|
SpecifyButtonUpTextColors( guiUpdatePanelButtons[ 1 ], FONT_MCOLOR_BLACK, FONT_BLACK );
|
|
SpecifyButtonDownTextColors( guiUpdatePanelButtons[ 1 ], FONT_MCOLOR_BLACK, FONT_BLACK );
|
|
SetButtonFastHelpText( guiUpdatePanelButtons[ 1 ], gzLateLocalizedString[52] );
|
|
}
|
|
else if( ( fShowUpdateBox == FALSE ) && ( fCreated == TRUE ) )
|
|
{
|
|
// set to uncreated
|
|
fCreated = FALSE;
|
|
|
|
// get rid of the buttons and images
|
|
RemoveButton( guiUpdatePanelButtons[ 0 ] );
|
|
RemoveButton( guiUpdatePanelButtons[ 1 ] );
|
|
|
|
UnloadButtonImage( guiUpdatePanelButtonsImage[ 0 ]);
|
|
UnloadButtonImage( guiUpdatePanelButtonsImage[ 1 ]);
|
|
|
|
// unpause
|
|
UnPauseDialogueQueue( );
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
void CreateUpdateBox( void )
|
|
{
|
|
// create basic box
|
|
CreatePopUpBox(&ghUpdateBox, AssignmentDimensions, MovePosition, (POPUP_BOX_FLAG_CLIP_TEXT|POPUP_BOX_FLAG_RESIZE ));
|
|
|
|
// which buffer will box render to
|
|
SetBoxBuffer(ghUpdateBox, FRAME_BUFFER);
|
|
|
|
// border type?
|
|
SetBorderType(ghUpdateBox,guiPOPUPBORDERS);
|
|
|
|
// background texture
|
|
SetBackGroundSurface(ghUpdateBox, guiPOPUPTEX);
|
|
|
|
// margin sizes
|
|
SetMargins( ghUpdateBox, 6, 6, 4, 4 );
|
|
|
|
// space between lines
|
|
SetLineSpace(ghUpdateBox, 2);
|
|
|
|
// set current box to this one
|
|
SetCurrentBox( ghUpdateBox );
|
|
|
|
// add strings
|
|
CreateUpdateBoxStrings( );
|
|
|
|
// set font type
|
|
SetBoxFont(ghUpdateBox, MAP_SCREEN_FONT);
|
|
|
|
// set highlight color
|
|
SetBoxHighLight(ghUpdateBox, FONT_WHITE);
|
|
|
|
// unhighlighted color
|
|
SetBoxForeground(ghUpdateBox, FONT_LTGREEN);
|
|
|
|
// background color
|
|
SetBoxBackground(ghUpdateBox, FONT_BLACK);
|
|
|
|
// shaded color..for darkened text
|
|
SetBoxShade( ghUpdateBox, FONT_BLACK );
|
|
|
|
// resize box to text
|
|
ResizeBoxToText( ghUpdateBox );
|
|
|
|
// create screen mask
|
|
CreateScreenMaskForMoveBox( );
|
|
|
|
ShowBox( ghUpdateBox );
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void CreateUpdateBoxStrings( void )
|
|
{
|
|
INT32 iCounter = 0;
|
|
CHAR16 sString[ 64 ];
|
|
INT32 hStringHandle;
|
|
|
|
swprintf( sString, L"%s", pUpdateMercStrings[ iReasonForSoldierUpDate ] );
|
|
AddMonoString(&hStringHandle, sString );
|
|
|
|
for( iCounter = 0; iCounter < SIZE_OF_UPDATE_BOX; iCounter++ )
|
|
{
|
|
// find valid soldier, add name
|
|
if( pUpdateSoldierBox[ iCounter ] )
|
|
{
|
|
swprintf( sString, L"%s", pUpdateSoldierBox[ iCounter ]->name );
|
|
AddMonoString(&hStringHandle, sString );
|
|
}
|
|
}
|
|
|
|
// add a few blank lines
|
|
sString[ 0 ] = 0;
|
|
|
|
AddMonoString(&hStringHandle, sString );
|
|
AddMonoString(&hStringHandle, sString );
|
|
AddMonoString(&hStringHandle, sString );
|
|
AddMonoString(&hStringHandle, sString );
|
|
}
|
|
|
|
|
|
|
|
void RemoveUpdateBox( void )
|
|
{
|
|
// remove the box
|
|
RemoveBox( ghUpdateBox );
|
|
ghUpdateBox = -1;
|
|
|
|
iReasonForSoldierUpDate = NO_REASON_FOR_UPDATE;
|
|
|
|
// remove the screen mask
|
|
RemoveScreenMaskForMoveBox( );
|
|
|
|
// reset mercs that are in progress of being updated
|
|
ResetSoldierUpdateBox( );
|
|
}
|
|
|
|
|
|
|
|
void DisplayUpdateBox( void )
|
|
{
|
|
if( fShowUpdateBox )
|
|
{
|
|
// show the box
|
|
ShowBox( ghUpdateBox );
|
|
PauseTime( TRUE );
|
|
}
|
|
return;
|
|
}
|
|
*/
|
|
|
|
|
|
|
|
void CreateDestroyTheUpdateBox( void )
|
|
{
|
|
static BOOLEAN fCreated = FALSE;
|
|
|
|
if( ( fCreated == FALSE ) && ( fShowUpdateBox == TRUE ) )
|
|
{
|
|
|
|
if( GetNumberOfMercsInUpdateList( ) == 0 )
|
|
{
|
|
fShowUpdateBox = FALSE;
|
|
return;
|
|
}
|
|
|
|
fCreated = TRUE;
|
|
|
|
//InterruptTime();
|
|
// create screen mask
|
|
CreateScreenMaskForMoveBox( );
|
|
|
|
// lock it paused
|
|
PauseGame( /*TRUE*/ ); // doesn't take parameters (jonathanl)
|
|
LockPauseState( 5 );
|
|
|
|
// display the box
|
|
DisplaySoldierUpdateBox( );
|
|
|
|
// Do beep
|
|
PlayJA2SampleFromFile( "Sounds\\newbeep.wav", RATE_11025, MIDVOLUME, 1 , MIDDLEPAN );
|
|
}
|
|
else if( ( fCreated == TRUE ) && ( fShowUpdateBox == FALSE ) )
|
|
{
|
|
fCreated = FALSE;
|
|
|
|
UnLockPauseState( );
|
|
UnPauseGame( /*FALSE*/ ); // doesn't take parameters (jonathanl)
|
|
|
|
// dirty screen
|
|
fMapPanelDirty = TRUE;
|
|
fTeamPanelDirty = TRUE;
|
|
fCharacterInfoPanelDirty = TRUE;
|
|
|
|
// remove screen mask
|
|
RemoveScreenMaskForMoveBox( );
|
|
|
|
ResetSoldierUpdateBox( );
|
|
|
|
CreateDestroyUpdatePanelButtons( 0, 0, FALSE );
|
|
}
|
|
}
|
|
|
|
|
|
void UpdateButtonsDuringCharacterDialoguePicture( void )
|
|
{
|
|
// stop showing buttons during certain instances of dialogue
|
|
if ( (guiTacticalInterfaceFlags & INTERFACE_MAPSCREEN ) )
|
|
{
|
|
UnMarkButtonDirty( giCharInfoButton[ 0 ] );
|
|
UnMarkButtonDirty( giCharInfoButton[ 1 ] );
|
|
}
|
|
|
|
}
|
|
|
|
void UpdateButtonsDuringCharacterDialogueSubTitles( void )
|
|
{
|
|
if( (guiTacticalInterfaceFlags & INTERFACE_MAPSCREEN ) && ( gGameSettings.fOptions[ TOPTION_SUBTITLES ] ) )
|
|
{
|
|
UnMarkButtonDirty( giMapContractButton );
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void RenderSoldierSmallFaceForUpdatePanel( INT32 iIndex, INT32 iX, INT32 iY )
|
|
{
|
|
INT32 iStartY = 0;
|
|
SOLDIERTYPE *pSoldier = NULL;
|
|
|
|
// fill the background for the info bars black
|
|
ColorFillVideoSurfaceArea( guiSAVEBUFFER, iX+36, iY+2, iX+44, iY+30, 0 );
|
|
|
|
// put down the background
|
|
BltVideoObjectFromIndex( guiSAVEBUFFER, giMercPanelImage, 0, iX, iY, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
|
|
// grab the face
|
|
BltVideoObjectFromIndex( guiSAVEBUFFER , giUpdateSoldierFaces[ iIndex ], 0, iX+2, iY+2, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
|
|
//HEALTH BAR
|
|
pSoldier = pUpdateSoldierBox[ iIndex ];
|
|
|
|
// is the merc alive?
|
|
if( !pSoldier->stats.bLife )
|
|
return;
|
|
|
|
|
|
//yellow one for bleeding
|
|
iStartY = iY + 29 - 27*pSoldier->stats.bLifeMax/100;
|
|
ColorFillVideoSurfaceArea( guiSAVEBUFFER, iX+36, iStartY, iX+37, iY+29, Get16BPPColor( FROMRGB( 107, 107, 57 ) ) );
|
|
ColorFillVideoSurfaceArea( guiSAVEBUFFER, iX+37, iStartY, iX+38, iY+29, Get16BPPColor( FROMRGB( 222, 181, 115 ) ) );
|
|
|
|
//pink one for bandaged.
|
|
iStartY += 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->stats.bLife/100;
|
|
ColorFillVideoSurfaceArea( guiSAVEBUFFER, iX+36, iStartY, iX+37, iY+29, Get16BPPColor( FROMRGB( 107, 8, 8 ) ) );
|
|
ColorFillVideoSurfaceArea( guiSAVEBUFFER, iX+37, iStartY, iX+38, iY+29, Get16BPPColor( FROMRGB( 206, 0, 0 ) ) );
|
|
|
|
//BREATH BAR
|
|
iStartY = iY + 29 - 27*pSoldier->bBreathMax/100;
|
|
ColorFillVideoSurfaceArea( guiSAVEBUFFER, iX+39, iStartY, iX+40, iY+29, Get16BPPColor( FROMRGB( 8, 8, 132 ) ) );
|
|
ColorFillVideoSurfaceArea( guiSAVEBUFFER, iX+40, iStartY, iX+41, iY+29, Get16BPPColor( FROMRGB( 8, 8, 107 ) ) );
|
|
|
|
//MORALE BAR
|
|
iStartY = iY + 29 - 27*pSoldier->aiData.bMorale/100;
|
|
ColorFillVideoSurfaceArea( guiSAVEBUFFER, iX+42, iStartY, iX+43, iY+29, Get16BPPColor( FROMRGB( 8, 156, 8 ) ) );
|
|
ColorFillVideoSurfaceArea( guiSAVEBUFFER, iX+43, iStartY, iX+44, iY+29, Get16BPPColor( FROMRGB( 8, 107, 8 ) ) );
|
|
|
|
|
|
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 + xResOffset, CHAR_ICON_CONTRACT_Y, CHAR_ICON_X + xResOffset + 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 + xResOffset, CHAR_ICON_CONTRACT_Y + CHAR_ICON_SPACING, CHAR_ICON_X + xResOffset + 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 + xResOffset, CHAR_ICON_CONTRACT_Y + ( 2 * CHAR_ICON_SPACING ), CHAR_ICON_X + xResOffset + 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;
|
|
}
|
|
}
|
|
|
|
BOOLEAN HandleTimeCompressWithTeamJackedInAndGearedToGo( void )
|
|
{
|
|
// check a team is ready to go
|
|
if( !( AnyMercsHired( ) ) )
|
|
{
|
|
// no mercs, leave
|
|
return( FALSE );
|
|
}
|
|
|
|
// make sure the game just started
|
|
if( gTacticalStatus.fDidGameJustStart == FALSE )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
if (!is_networked)
|
|
// select starting sector (A9 - Omerta)
|
|
// HEADROCK HAM 3.5: Externalized.
|
|
ChangeSelectedMapSector( gGameExternalOptions.ubDefaultArrivalSectorX, gGameExternalOptions.ubDefaultArrivalSectorY, startingZ );
|
|
|
|
if (is_networked)
|
|
{
|
|
// load starting sector
|
|
if ( !SetCurrentWorldSector( gsMercArriveSectorX, gsMercArriveSectorY, 0 ) )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
gubPBSectorX = (UINT8)gsMercArriveSectorX;
|
|
gubPBSectorY = (UINT8)gsMercArriveSectorY;
|
|
}
|
|
else
|
|
{
|
|
// load starting sector
|
|
// Externalized
|
|
if ( !SetCurrentWorldSector( gGameExternalOptions.ubDefaultArrivalSectorX, gGameExternalOptions.ubDefaultArrivalSectorY, startingZ ) )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
gubPBSectorX = (UINT8)gGameExternalOptions.ubDefaultArrivalSectorX;
|
|
gubPBSectorY = (UINT8)gGameExternalOptions.ubDefaultArrivalSectorY;
|
|
}
|
|
gubPBSectorZ = 0;
|
|
|
|
//Setup variables in the PBI for this first battle. We need to support the
|
|
//non-persistant PBI in case the user goes to mapscreen.
|
|
// HEADROCK HAM 3.5: Arrival sector externalized. Fix for entering non-hostile sector/
|
|
if ( NumEnemiesInAnySector( gubPBSectorX, gubPBSectorY, 0 ) > 0 )
|
|
{
|
|
gfBlitBattleSectorLocator = TRUE;
|
|
gubEnemyEncounterCode = ENTERING_ENEMY_SECTOR_CODE;
|
|
}
|
|
else
|
|
{
|
|
gfBlitBattleSectorLocator = FALSE;
|
|
gubEnemyEncounterCode = NO_ENCOUNTER_CODE;
|
|
}
|
|
|
|
InitHelicopterEntranceByMercs( );
|
|
|
|
FadeInGameScreen( );
|
|
|
|
SetUpShutDownMapScreenHelpTextScreenMask( );
|
|
#ifdef JA2UB
|
|
//no ja25 UB
|
|
#else
|
|
// Add e-mail message
|
|
AddEmail(ENRICO_CONGRATS,ENRICO_CONGRATS_LENGTH,MAIL_ENRICO, GetWorldTotalMin(), -1, -1, TYPE_EMAIL_EMAIL_EDT);
|
|
|
|
#endif
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
void HandleDisplayOfExitToTacticalMessageForFirstEntryToMapScreen( void )
|
|
{
|
|
INT32 iTime = 0, iDifference = 0;
|
|
|
|
if( gTacticalStatus.fDidGameJustStart == FALSE )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if( AnyMercsHired() == FALSE )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if( fResetTimerForFirstEntryIntoMapScreen )
|
|
{
|
|
giExitToTactBaseTime = 0;
|
|
fResetTimerForFirstEntryIntoMapScreen = FALSE;
|
|
}
|
|
|
|
// is this the first time in?
|
|
if( giExitToTactBaseTime == 0 )
|
|
{
|
|
// gte the clock, for initing
|
|
giExitToTactBaseTime = GetJA2Clock();
|
|
}
|
|
|
|
iTime = GetJA2Clock();
|
|
|
|
iDifference = iTime - giExitToTactBaseTime;
|
|
|
|
if( iDifference > TIMER_FOR_SHOW_EXIT_TO_TACTICAL_MESSAGE )
|
|
{
|
|
fShowMapScreenHelpText = FALSE;
|
|
fMapPanelDirty = TRUE;
|
|
fTeamPanelDirty = TRUE;
|
|
fCharacterInfoPanelDirty = TRUE;
|
|
giExitToTactBaseTime = 0;
|
|
}
|
|
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
BOOLEAN NotifyPlayerWhenEnemyTakesControlOfImportantSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, BOOLEAN fContested )
|
|
{
|
|
CHAR16 sString[ 128 ], sStringA[ 64 ], sStringB[ 256 ], sStringC[ 64 ];
|
|
INT32 iValue = 0;
|
|
INT8 bTownId = 0;
|
|
INT16 sSector = 0;
|
|
INT8 bMineIndex;
|
|
|
|
|
|
// are we below ground?
|
|
if( bSectorZ != 0 )
|
|
{
|
|
// yes we are..there is nothing important to player here
|
|
return( FALSE );
|
|
}
|
|
|
|
// get the name of the sector
|
|
GetSectorIDString( sSectorX, sSectorY, bSectorZ, sString, TRUE );
|
|
|
|
bTownId = GetTownIdForSector( sSectorX, sSectorY );
|
|
|
|
// check if SAM site here
|
|
if( IsThisSectorASAMSector( sSectorX, sSectorY, bSectorZ ) )
|
|
{
|
|
swprintf( sStringB, pMapErrorString[ 15 ], sString );
|
|
|
|
// put up the message informing the player of the event
|
|
DoScreenIndependantMessageBox( sStringB, MSG_BOX_FLAG_OK, MapScreenDefaultOkBoxCallback );
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
// check if a mine is here
|
|
if( IsThereAMineInThisSector( sSectorX, sSectorY ) )
|
|
{
|
|
bMineIndex = GetMineIndexForSector( sSectorX, sSectorY );
|
|
|
|
// if it was producing for us
|
|
if ( ( GetMaxDailyRemovalFromMine( bMineIndex ) > 0 ) && SpokenToHeadMiner( bMineIndex ) )
|
|
{
|
|
// get how much we now will get from the mines
|
|
iValue = GetProjectedTotalDailyIncome( );
|
|
|
|
// parse the string
|
|
swprintf( sStringC, L"%d", iValue );
|
|
|
|
// insert
|
|
InsertCommasForDollarFigure( sStringC );
|
|
InsertDollarSignInToString( sStringC );
|
|
|
|
swprintf( sStringB, pMapErrorString[ 16 ], sString, sStringC );
|
|
|
|
// put up the message informing the player of the event
|
|
DoScreenIndependantMessageBox( sStringB, MSG_BOX_FLAG_OK, MapScreenDefaultOkBoxCallback );
|
|
return( TRUE );
|
|
}
|
|
}
|
|
|
|
|
|
if( fContested && bTownId )
|
|
{
|
|
#ifdef JA2UB
|
|
// no UB
|
|
#else
|
|
if( bTownId == SAN_MONA )
|
|
{ //San Mona isn't important.
|
|
return( TRUE );
|
|
}
|
|
#endif
|
|
swprintf( sStringB, pMapErrorString[ 25 ], sString );
|
|
|
|
#ifdef JA2UB
|
|
HandleDisplayingOfPlayerLostDialogue( );
|
|
#endif
|
|
// put up the message informing the player of the event
|
|
DoScreenIndependantMessageBox( sStringB, MSG_BOX_FLAG_OK, MapScreenDefaultOkBoxCallback );
|
|
return( TRUE );
|
|
}
|
|
|
|
// get the strategic sector value
|
|
sSector = sSectorX + MAP_WORLD_X * sSectorY;
|
|
|
|
if( StrategicMap[ sSector ].bNameId == BLANK_SECTOR )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
// get the name of the sector
|
|
GetSectorIDString( sSectorX, sSectorY, bSectorZ, sStringA, TRUE );
|
|
|
|
// now build the string
|
|
swprintf( sString, pMapErrorString[ 17 ], sStringA );
|
|
|
|
// put up the message box
|
|
DoScreenIndependantMessageBox( sString, MSG_BOX_FLAG_OK, NULL );
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
void NotifyPlayerOfInvasionByEnemyForces( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, MSGBOX_CALLBACK ReturnCallback )
|
|
{
|
|
INT16 sSector = 0;
|
|
INT8 bTownId = 0;
|
|
CHAR16 sString[ 128 ], sStringA[ 128 ];
|
|
|
|
|
|
// check if below ground
|
|
if( bSectorZ != 0 )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// grab sector value
|
|
sSector = sSectorX + MAP_WORLD_X * sSectorY;
|
|
|
|
if( StrategicMap[ sSector ].fEnemyControlled == TRUE )
|
|
{
|
|
// enemy controlled any ways, leave
|
|
return;
|
|
}
|
|
|
|
// get the town id
|
|
bTownId = StrategicMap[ sSector ].bNameId;
|
|
|
|
// check if SAM site here
|
|
if( IsThisSectorASAMSector( sSectorX, sSectorY, bSectorZ ) )
|
|
{
|
|
// get sector id value
|
|
GetShortSectorString( sSectorX, sSectorY, sStringA );
|
|
|
|
swprintf( sString, pMapErrorString[ 22 ], sStringA );
|
|
DoScreenIndependantMessageBox( sString, MSG_BOX_FLAG_OK, ReturnCallback );
|
|
}
|
|
else if( bTownId )
|
|
{
|
|
// get the name of the sector
|
|
GetSectorIDString( sSectorX, sSectorY, bSectorZ, sStringA, TRUE );
|
|
|
|
swprintf( sString, pMapErrorString[ 23 ], sStringA );
|
|
DoScreenIndependantMessageBox( sString, MSG_BOX_FLAG_OK, ReturnCallback );
|
|
}
|
|
else
|
|
{
|
|
// get sector id value
|
|
GetShortSectorString( sSectorX, sSectorY, sStringA );
|
|
|
|
swprintf( sString, pMapErrorString[ 24 ], sStringA );
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, sString );
|
|
}
|
|
}
|
|
|
|
|
|
BOOLEAN CanCharacterMoveInStrategic( SOLDIERTYPE *pSoldier, INT8 *pbErrorNumber )
|
|
{
|
|
INT16 sSector = 0;
|
|
BOOLEAN fProblemExists = FALSE;
|
|
|
|
|
|
// valid soldier?
|
|
Assert( pSoldier );
|
|
Assert( pSoldier->bActive);
|
|
|
|
|
|
// NOTE: Check for the most permanent conditions first, and the most easily remedied ones last!
|
|
// In case several cases apply, only the reason found first will be given, so make it a good one!
|
|
|
|
|
|
// still in transit?
|
|
if( IsCharacterInTransit( pSoldier ) == TRUE )
|
|
{
|
|
*pbErrorNumber = 8;
|
|
return( FALSE );
|
|
}
|
|
|
|
// a POW?
|
|
if( pSoldier->bAssignment == ASSIGNMENT_POW )
|
|
{
|
|
*pbErrorNumber = 5;
|
|
return( FALSE );
|
|
}
|
|
|
|
|
|
// underground? (can't move strategically, must use tactical traversal )
|
|
if( pSoldier->bSectorZ != 0 )
|
|
{
|
|
*pbErrorNumber = 1;
|
|
return( FALSE );
|
|
}
|
|
|
|
|
|
// vehicle checks
|
|
if ( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE )
|
|
{
|
|
// empty (needs a driver!)?
|
|
if ( GetNumberInVehicle( pSoldier->bVehicleID ) == 0 )
|
|
{
|
|
*pbErrorNumber = 32;
|
|
return( FALSE );
|
|
}
|
|
|
|
// too damaged?
|
|
if ( pSoldier->stats.bLife < OKLIFE )
|
|
{
|
|
*pbErrorNumber = 47;
|
|
return( FALSE );
|
|
}
|
|
|
|
// out of fuel?
|
|
if ( !VehicleHasFuel( pSoldier ) )
|
|
{
|
|
*pbErrorNumber = 42;
|
|
return( FALSE );
|
|
}
|
|
}
|
|
else // non-vehicle
|
|
{
|
|
// dead?
|
|
if ( pSoldier->stats.bLife <= 0 )
|
|
{
|
|
swprintf( gsCustomErrorString, pMapErrorString[ 35 ], pSoldier->name );
|
|
*pbErrorNumber = -99; // customized error message!
|
|
return( FALSE );
|
|
}
|
|
|
|
// too injured?
|
|
if ( pSoldier->stats.bLife < OKLIFE )
|
|
{
|
|
swprintf( gsCustomErrorString, pMapErrorString[ 33 ], pSoldier->name );
|
|
*pbErrorNumber = -99; // customized error message!
|
|
return( FALSE );
|
|
}
|
|
}
|
|
|
|
|
|
// if merc is in a particular sector, not somewhere in between
|
|
if ( pSoldier->flags.fBetweenSectors == FALSE )
|
|
{
|
|
// and he's NOT flying above it all in a working helicopter
|
|
if( !SoldierAboardAirborneHeli( pSoldier ) )
|
|
{
|
|
// and that sector is loaded...
|
|
if( ( pSoldier->sSectorX == gWorldSectorX ) && ( pSoldier->sSectorY == gWorldSectorY ) &&
|
|
( pSoldier->bSectorZ == gbWorldSectorZ ) )
|
|
{
|
|
// in combat?
|
|
if( gTacticalStatus.uiFlags & INCOMBAT )
|
|
{
|
|
*pbErrorNumber = 11;
|
|
return( FALSE );
|
|
}
|
|
|
|
// hostile sector?
|
|
if ( gTacticalStatus.fEnemyInSector )
|
|
{
|
|
*pbErrorNumber = 2;
|
|
return( FALSE );
|
|
}
|
|
|
|
// air raid in loaded sector where character is?
|
|
if( InAirRaid( ) )
|
|
{
|
|
*pbErrorNumber = 10;
|
|
return( FALSE );
|
|
}
|
|
}
|
|
|
|
// not necessarily loaded - if there are any hostiles there
|
|
if( NumHostilesInSector( pSoldier->sSectorX, pSoldier->sSectorY, pSoldier->bSectorZ ) > 0 )
|
|
{
|
|
*pbErrorNumber = 2;
|
|
return( FALSE );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// if in L12 museum, and the museum alarm went off, and Eldin still around?
|
|
if ( ( pSoldier->sSectorX == 12 ) && ( pSoldier->sSectorY == MAP_ROW_L ) && ( pSoldier->bSectorZ == 0 ) &&
|
|
( !pSoldier->flags.fBetweenSectors ) && gMercProfiles[ ELDIN ].bMercStatus != MERC_IS_DEAD )
|
|
{
|
|
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->flags.uiStatusFlags & SOLDIER_VEHICLE )
|
|
{
|
|
// IS a vehicle - use vehicle's group
|
|
ubGroup = pVehicleList[ pSoldier->bVehicleID ].ubMovementGroup;
|
|
}
|
|
else if( pSoldier->bAssignment == VEHICLE )
|
|
{
|
|
// IN a vehicle - use vehicle's group
|
|
ubGroup = pVehicleList[ pSoldier->iVehicleId ].ubMovementGroup;
|
|
}
|
|
else
|
|
{
|
|
ubGroup = pSoldier->ubGroupID;
|
|
}
|
|
|
|
// even if group is 0 (not that that should happen, should it?) still loop through for other mercs selected to move
|
|
|
|
// if anyone in the merc's group or also selected cannot move for whatever reason return false
|
|
for( iCounter = 0; iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; iCounter++ )
|
|
{
|
|
if( gCharactersList[ iCounter ].fValid == TRUE )
|
|
{
|
|
// get soldier
|
|
pCurrentSoldier = &( Menptr[ gCharactersList[ iCounter ].usSolID ] );
|
|
|
|
// skip inactive grunts
|
|
if( pCurrentSoldier->bActive == FALSE )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// skip the same guy we did already
|
|
if ( pCurrentSoldier == pSoldier )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// does character have group?
|
|
if( pCurrentSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE )
|
|
{
|
|
// IS a vehicle
|
|
ubCurrentGroup = pVehicleList[ pCurrentSoldier->bVehicleID ].ubMovementGroup;
|
|
}
|
|
else if( pCurrentSoldier->bAssignment == VEHICLE )
|
|
{
|
|
// IN a vehicle
|
|
ubCurrentGroup = pVehicleList[ pCurrentSoldier->iVehicleId ].ubMovementGroup;
|
|
}
|
|
else
|
|
{
|
|
ubCurrentGroup = pCurrentSoldier->ubGroupID;
|
|
}
|
|
|
|
// if he is in the same movement group (i.e. squad), or he is still selected to go with us (legal?)
|
|
if( ( ubCurrentGroup == ubGroup ) || ( fSelectedListOfMercsForMapScreen[ iCounter ] == TRUE ) )
|
|
{
|
|
// can this character also move strategically?
|
|
if( CanCharacterMoveInStrategic( pCurrentSoldier, pbErrorNumber ) == FALSE )
|
|
{
|
|
// cannot move, fail, and don't bother checking anyone else, either
|
|
return( FALSE );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// everybody can move... Yey! :-)
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
|
|
void ReportMapScreenMovementError( INT8 bErrorNumber )
|
|
{
|
|
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->flags.uiStatusFlags & SOLDIER_VEHICLE )
|
|
{
|
|
iVehicle2Id = pSoldier->bVehicleID;
|
|
}
|
|
|
|
|
|
// if also (in) a vehicle
|
|
if ( iVehicle2Id != -1 )
|
|
{
|
|
// if it's the same vehicle
|
|
if ( iVehicle1Id == iVehicle2Id )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
|
|
// helicopter can't move together with ground vehicles!
|
|
if ( ( iVehicle1Id == iHelicopterVehicleId ) || ( iVehicle2Id == iHelicopterVehicleId ) )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
// CHRISL: Certain vehicles now have different valid sectors so we don't want to allow try to path for two different vehicles
|
|
if ( iVehicle1Id != iVehicle2Id )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
pVehicle1 = &( pVehicleList[ iVehicle1Id ] );
|
|
pVehicle2 = &( pVehicleList[ iVehicle2Id ] );
|
|
|
|
// as long as they're in the same location, amd neither is between sectors, different vehicles is also ok
|
|
if( ( pVehicle1->sSectorX == pVehicle2->sSectorX ) &&
|
|
( pVehicle1->sSectorY == pVehicle2->sSectorY ) &&
|
|
( pVehicle1->sSectorZ == pVehicle2->sSectorZ ) &&
|
|
!pVehicle1->fBetweenSectors &&
|
|
!pVehicle2->fBetweenSectors )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
}
|
|
|
|
|
|
// not in/is a vehicle, or in a different vehicle that isn't in the same location
|
|
return ( FALSE );
|
|
}
|
|
|
|
|
|
BOOLEAN SaveLeaveItemList( HWFILE hFile )
|
|
{
|
|
INT32 iCounter = 0;
|
|
MERC_LEAVE_ITEM *pCurrentItem;
|
|
UINT32 uiCount=0;
|
|
UINT32 uiNumBytesWritten = 0;
|
|
BOOLEAN fNodeExists = FALSE;
|
|
UINT32 uiCnt;
|
|
|
|
for( iCounter = 0; iCounter < NUM_LEAVE_LIST_SLOTS; iCounter++ )
|
|
{
|
|
// go through nodes and save them
|
|
if ( gpLeaveListHead[ iCounter ] != NULL )
|
|
{
|
|
fNodeExists = TRUE;
|
|
|
|
// Save the to specify that a node DOES exist
|
|
FileWrite( hFile, &fNodeExists, sizeof(BOOLEAN), &uiNumBytesWritten );
|
|
if( uiNumBytesWritten != sizeof(BOOLEAN) )
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
uiCount = 1;
|
|
pCurrentItem = gpLeaveListHead[ iCounter ];
|
|
|
|
//loop through all the nodes to see how many there are
|
|
while( pCurrentItem->pNext )
|
|
{
|
|
pCurrentItem = pCurrentItem->pNext;
|
|
uiCount++;
|
|
}
|
|
|
|
// Save the number specifing how many items there are in the list
|
|
FileWrite( hFile, &uiCount, sizeof(UINT32), &uiNumBytesWritten );
|
|
if( uiNumBytesWritten != sizeof(UINT32) )
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
pCurrentItem = gpLeaveListHead[ iCounter ];
|
|
|
|
//loop through all the nodes to see how many there are
|
|
for( uiCnt=0; uiCnt<uiCount; uiCnt++)
|
|
{
|
|
// Save the items
|
|
if ( !pCurrentItem->Save(hFile) )
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
pCurrentItem = pCurrentItem->pNext;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
fNodeExists = FALSE;
|
|
// Save the to specify that a node DOENST exist
|
|
FileWrite( hFile, &fNodeExists, sizeof(BOOLEAN), &uiNumBytesWritten );
|
|
if( uiNumBytesWritten != sizeof(BOOLEAN) )
|
|
{
|
|
return(FALSE);
|
|
}
|
|
}
|
|
}
|
|
|
|
//Save the leave list profile id's
|
|
for( iCounter = 0; iCounter < NUM_LEAVE_LIST_SLOTS; iCounter++ )
|
|
{
|
|
FileWrite( hFile, &guiLeaveListOwnerProfileId[ iCounter ], sizeof(UINT32), &uiNumBytesWritten );
|
|
if( uiNumBytesWritten != sizeof(UINT32) )
|
|
{
|
|
return(FALSE);
|
|
}
|
|
}
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN LoadLeaveItemList( HWFILE hFile )
|
|
{
|
|
INT32 iCounter = 0;
|
|
MERC_LEAVE_ITEM *pCurrentItem;
|
|
MERC_LEAVE_ITEM *pItem;
|
|
UINT32 uiCount=0;
|
|
UINT32 uiNumBytesRead = 0;
|
|
BOOLEAN fNodeExists = FALSE;
|
|
UINT32 uiSubItem;
|
|
|
|
//Shutdown the list
|
|
ShutDownLeaveList( );
|
|
|
|
//init the list
|
|
InitLeaveList( );
|
|
|
|
//loop through all the lists
|
|
for( iCounter = 0; iCounter < NUM_LEAVE_LIST_SLOTS; iCounter++ )
|
|
{
|
|
// load the flag that specifis that a node DOES exist
|
|
FileRead( hFile, &fNodeExists, sizeof(BOOLEAN), &uiNumBytesRead );
|
|
if( uiNumBytesRead != sizeof(BOOLEAN) )
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
// if a root node is supposed to exist
|
|
if( fNodeExists )
|
|
{
|
|
// load the number specifing how many items there are in the list
|
|
FileRead( hFile, &uiCount, sizeof(UINT32), &uiNumBytesRead );
|
|
if( uiNumBytesRead != sizeof(UINT32) )
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
// Sanity check
|
|
if (uiCount > 1000) {
|
|
return(FALSE);
|
|
}
|
|
|
|
// allocate space
|
|
gpLeaveListHead[ iCounter ] = new MERC_LEAVE_ITEM;
|
|
if( gpLeaveListHead[ iCounter ] == NULL )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
pCurrentItem = gpLeaveListHead[ iCounter ];
|
|
|
|
for( uiSubItem=0; uiSubItem< uiCount; uiSubItem++ )
|
|
{
|
|
// allocate space
|
|
pItem = new MERC_LEAVE_ITEM;
|
|
if( pItem == NULL )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
// Load the items
|
|
if ( !pItem->Load(hFile) )
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
pItem->pNext = NULL;
|
|
|
|
//add the node to the list
|
|
if( uiSubItem == 0 )
|
|
{
|
|
gpLeaveListHead[ iCounter ] = pItem;
|
|
pCurrentItem = gpLeaveListHead[ iCounter ];
|
|
}
|
|
else
|
|
{
|
|
pCurrentItem->pNext = pItem;
|
|
pCurrentItem = pCurrentItem->pNext;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//Load the leave list profile id's
|
|
for( iCounter = 0; iCounter < NUM_LEAVE_LIST_SLOTS; iCounter++ )
|
|
{
|
|
FileRead( hFile, &guiLeaveListOwnerProfileId[ iCounter ], sizeof(UINT32), &uiNumBytesRead );
|
|
if( uiNumBytesRead != sizeof(UINT32) )
|
|
{
|
|
return(FALSE);
|
|
}
|
|
}
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
|
|
void TurnOnSectorLocator( UINT8 ubProfileID )
|
|
{
|
|
SOLDIERTYPE *pSoldier;
|
|
|
|
Assert( ubProfileID != NO_PROFILE );
|
|
|
|
pSoldier = FindSoldierByProfileID( ubProfileID, FALSE );
|
|
if( pSoldier )
|
|
{
|
|
gsSectorLocatorX = pSoldier->sSectorX;
|
|
gsSectorLocatorY = pSoldier->sSectorY;
|
|
}
|
|
else
|
|
{
|
|
// if it's Skyrider (when he's not on our team), and his chopper has been setup
|
|
if ( ( ubProfileID == SKYRIDER ) && fSkyRiderSetUp )
|
|
{
|
|
// if helicopter position is being shown, don't do this, too, cause the helicopter icon is on top and it looks
|
|
// like crap. I tried moving the heli icon blit to before, but that screws up it's blitting.
|
|
if ( !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->flags.fContractPriceHasIncreased )
|
|
{
|
|
if ( fTriggerContractMenu )
|
|
{
|
|
// have him say so first - post the dialogue event with the contract menu event
|
|
SpecialCharacterDialogueEvent( DIALOGUE_SPECIAL_EVENT_ENTER_MAPSCREEN,0,0,0,0,0 );
|
|
HandleImportantMercQuote( pSoldier, QUOTE_MERC_GONE_UP_IN_PRICE );
|
|
TacticalCharacterDialogueWithSpecialEvent( pSoldier, 0, DIALOGUE_SPECIAL_EVENT_SHOW_CONTRACT_MENU, 0,0 );
|
|
}
|
|
else
|
|
{
|
|
// now post the dialogue event and the contratc menu event
|
|
HandleImportantMercQuote( pSoldier, QUOTE_MERC_GONE_UP_IN_PRICE );
|
|
}
|
|
|
|
pSoldier->flags.fContractPriceHasIncreased = FALSE;
|
|
|
|
// said quote / triggered contract menu
|
|
return( TRUE );
|
|
}
|
|
else
|
|
{
|
|
// nope, nothing to do
|
|
return( FALSE );
|
|
}
|
|
}
|