#include "mapscreen.h" #include #include #include #include "gameloop.h" #include "sgp.h" #include "vobject.h" #include "WCheck.h" #include "worlddef.h" #include "input.h" #include "Font.h" #include "screenids.h" #include "Screens.h" #include "Overhead.h" #include "sysutil.h" #include "Event Pump.h" #include "Font Control.h" #include "Timer Control.h" #include "Interface.h" #include "Handle UI.h" #include "Interface Items.h" #include "Interface Utils.h" #include "lighting.h" #include #include #include "Cursors.h" #include "Soldier Profile.h" #include "Interface Panels.h" #include "Interface Control.h" #include "Sys Globals.h" #include "Radar Screen.h" #include "Render Dirty.h" #include "Utilities.h" #include "Game Init.h" #include "renderworld.h" #include "finances.h" #include "message.h" #include "math.h" #include "vsurface.h" #include "vobject_blitters.h" #include "faces.h" #include "PopUpBox.h" #include "Game Clock.h" #include "Items.h" #include "Cursor Control.h" #include "Text.h" #include "strategic.h" #include "strategicmap.h" #include "Strategic Pathing.h" #include "Map Screen Interface Bottom.h" #include "Map Screen Interface Border.h" #include "Map Screen Interface Map.h" #include "Map Screen Interface.h" #include "Assignments.h" #include "Points.h" #include "Squads.h" #include "Merc Contract.h" #include "Sound Control.h" #include "Strategic Turns.h" #include "Dialogue Control.h" #include "Map Screen Interface TownMine Info.h" #include "PreBattle Interface.h" #include "personnel.h" #include "Animated ProgressBar.h" #include "Queen Command.h" #include "LaptopSave.h" #include "Map Screen Interface Map Inventory.h" #include "Vehicles.h" #include "Map Screen Helicopter.h" #include "gamescreen.h" #include "line.h" #include "english.h" #include "Fade Screen.h" #include "Strategic Mines.h" #include "SaveLoadScreen.h" #include "Options Screen.h" #include "Auto Resolve.h" #include "Meanwhile.h" #include "Campaign.h" #include "random.h" #include "Air Raid.h" #include "Quests.h" #include "Town Militia.h" #include "Weapons.h" #include "Player Command.h" #include "Multi Language Graphic Utils.h" #include "HelpScreen.h" #include "Soldier macros.h" #include "Map Information.h" #include "Cheats.h" #include "Strategic Town Loyalty.h" #include "GameSettings.h" #include "Militia Control.h" #include "Tactical Save.h" #include "Explosion Control.h" #include "Creature Spreading.h" #include "email.h" #include "Strategic Status.h" #include "Soldier Create.h" #include "Animation Control.h" // HEADROCK HAM 3.6: Include facilities for assignment display #include "Facilities.h" // HEADROCK HAM 4: Include Militia Squads for Manual Militia Restrictions toggle. #include "MilitiaSquads.h" #include "Auto Bandage.h" // added by Flugente #include "Food.h" // added by Flugente #include "Drugs And Alcohol.h" // added by Flugente #include "WordWrap.h" #include "connect.h" //hayden #include "InterfaceItemImages.h" #include #ifdef JA2UB #include "laptop.h" #include "Strategic Movement.h" //#include "Strategic Movement Costs.h" // DEFINES #include "Ja25 Strategic Ai.h" #include "MapScreen Quotes.h" #include "ub_config.h" #include "LuaInitNPCs.h" #endif std::vector gSelectedSoldiers{}; // Flugente: militia movement // plot BOOLEAN fPlotForMilitia = FALSE; UINT32 gMilitiaPlotStartSector = 0; extern INT8 gbCompatibleApplyItem; #define MAX_SORT_METHODS 6 // Cursors #define SCREEN_CURSOR CURSOR_NORMAL // Fonts #define CHAR_FONT BLOCKFONT2 // COMPFONT //#define ETA_FONT BLOCKFONT2 // Colors #define CHAR_INFO_PANEL_BLOCK_COLOR 60 #define FONT_MAP_DKYELLOW 170 #define CHAR_TITLE_FONT_COLOR 6 #define CHAR_TEXT_FONT_COLOR 5 #define STARTING_COLOR_NUM 5 #define MAP_TIME_UNDER_THIS_DISPLAY_AS_HOURS ( 3 * 24 * 60 ) #define MIN_KB_TO_DO_PRE_LOAD ( 32 * 1024 ) #define DELAY_PER_FLASH_FOR_DEPARTING_PERSONNEL 500 #define GLOW_DELAY 70 #define ASSIGNMENT_DONE_FLASH_TIME 500 #define MINS_TO_FLASH_CONTRACT_TIME (4 * 60) #include "GameInitOptionsScreen.h" #ifdef JA2UB void MakeBadSectorListFromMapsOnHardDrive( BOOLEAN fDisplayMessages ); // ja25 UB #endif struct UILayout_CharStatusBars { INT32 x; INT32 y; INT32 offset; }; struct UILayout_CharPanelButtons { SGPPoint Up; SGPPoint Down; SGPPoint Contract; }; struct UILayout_CharPanelTextLocations { SGPRectangle CurrentAssignment; SGPRectangle CurrentHealth; SGPRectangle CurrentHitpoints; SGPRectangle CurrentMorale; SGPRectangle Pay; SGPRectangle Salary; SGPRectangle TimeRemaining; SGPRectangle Medical; SGPPoint Assignment; SGPPoint Attributes; SGPPoint Attributes2; SGPPoint Health; SGPPoint Morale; SGPPoint Condition; int CurrentAssignment_Y2; }; struct UILayout_CharPanelAttributes { SGPPoint AGL; SGPPoint DEX; SGPPoint STR; SGPPoint LDR; SGPPoint WIS; SGPPoint LVL; SGPPoint MRK; SGPPoint MEC; SGPPoint EXP; SGPPoint MED; int width; int height; }; struct UILayout_CharPanel { SGPRectangle Region; SGPRectangle FacePicture; SGPRectangle FullName; SGPRectangle NickName; SGPRectangle HandItem; UILayout_CharStatusBars Statusbars; UILayout_CharPanelButtons Button; UILayout_CharPanelTextLocations Text; UILayout_CharPanelAttributes Attr; UILayout_CharPanelIconRegion Icon; }; struct UILayout_CharInvButtons { SGPRectangle Trashcan; SGPPoint Done; }; struct UILayout_CharInvText { SGPPoint Armor; SGPPoint ArmorLabel; SGPPoint ArmorPercent; SGPPoint Weight; SGPPoint WeightLabel; SGPPoint WeightPercent; SGPPoint Camo; SGPPoint CamoLabel; SGPPoint CamoPercent; INT32 PercentWidth; INT32 PercentHeight; SGPPoint RobotWeaponLabel; SGPPoint RobotAmmoLabel; SGPPoint RobotTargetingLabel; SGPPoint RobotTargetingBonus; SGPPoint RobotChassisLabel; SGPPoint RobotChassisBonus; SGPPoint RobotUtilityLabel; SGPPoint RobotUtilityBonus; SGPPoint RobotInventoryLabel; }; struct UILayout_CharInv { SGPRectangle Region; SGPPoint BodyPanel; UILayout_CharInvButtons Button; UILayout_CharInvText Text; }; UILayout_Map UI_MAP; UILayout_CharPanel UI_CHARPANEL; UILayout_CharPanelIconRegion UI_CHAR_Icon; UILayout_CharInv UI_CHARINV; int UI_CHARINV_REGION_X; int UI_CHARINV_REGION_Y; int UI_CHARINV_REGION_W; int UI_CHARINV_REGION_H; UILayout_CharList UI_CHARLIST; extern UINT16 MAP_BOTTOM_LAPTOP_X; extern UINT16 MAP_BOTTOM_LAPTOP_Y; int CHAR_BAR_INFO_X; int CHAR_BAR_INFO_Y; int PLAYER_INFO_X; int PLAYER_INFO_Y; // item description int MAP_ITEMDESC_START_X; int MAP_ITEMDESC_START_Y; int INV_REGION_Y; int MAP_INV_STATS_TITLE_FONT_COLOR; // keyring int MAP_KEYRING_X; int MAP_KEYRING_Y; // The boxes defines int POP_UP_BOX_X; // OJW: MP POSITIONS int MP_BTN_Y; int MP_ROWSTART_Y; int MP_PLAYER_X; int MP_PLAYER_W; int MP_TEAM_X; int MP_TEAM_W; int MP_COMPASS_X; int MP_COMPASS_W; int MP_GAMEINFO_X; int MP_GAMEINFO_W; #define MAX_MP_BUTTONS 4 INT gMapMPButtonsX[ MAX_MP_BUTTONS ] = {5 , 84 , 130 , 154 }; #define MP_BTN_STARTGAME 4 #define MP_BTN_READY 3 INT32 giMapMPButtonImage[ MAX_MP_BUTTONS+1 ] = { -1, -1, -1, -1 ,-1}; INT32 giMapMPButton[ MAX_MP_BUTTONS ] = { -1, -1, -1, -1}; // Compass Drowndown INT32 ghMPCompassBox; INT32 ghMPTeamBox; MOUSE_REGION gMPReadyButtonRegion; MOUSE_REGION gCompassMenuRegion[MAX_EDGES]; MOUSE_REGION gTeamMenuRegion[MAX_MP_TEAMS]; bool is_compass_box_open = false; bool is_team_box_open = false; #define RGB_WHITE ( FROMRGB( 255, 255, 255 ) ) #define RGB_YELLOW ( FROMRGB( 255, 255, 0 ) ) #define RGB_NEAR_BLACK ( FROMRGB( 0, 0, 1 ) ) // ENUMS // ARM: NOTE that these map "events" are never actually saved in a player's game in any way enum { MAP_EVENT_NONE, MAP_EVENT_CLICK_SECTOR, MAP_EVENT_PLOT_PATH, MAP_EVENT_CANCEL_PATH, #ifdef JA2BETAVERSION MAP_EVENT_VIEWAI #endif }; // STRUCTURES / TYPEDEFS struct rgbcolor { UINT8 ubRed; UINT8 ubGreen; UINT8 ubBlue; }; typedef struct rgbcolor RGBCOLOR; struct lineoftext { STR16 pLineText; UINT32 uiFont; struct lineoftext *pNext; }; typedef struct lineoftext LineText; typedef LineText *LineTextPtr; struct popbox { UINT16 usTopX; UINT16 usTopY; UINT16 usWidth; UINT16 usHeight; LineTextPtr pBoxText; struct popbox *pNext; }; typedef struct popbox PopUpBox; typedef PopUpBox *PopUpBoxPtr; // TABLES RGBCOLOR GlowColorsA[]={ {0,0,0}, {25,0,0}, {50,0,0}, {75,0,0}, {100,0,0}, {125,0,0}, {150,0,0}, {175,0,0}, {200,0,0}, {225,0,0}, {250,0,0}, }; SGPPoint gMapSortButtons[ MAX_SORT_METHODS ]={ {5,113}, {61,113}, {117,113}, {141,113}, {178,113}, {216,113}, }; // map screen's inventory panel pockets - top right corner coordinates INV_REGION_DESC gMapScreenInvPocketXY[NUM_INV_SLOTS]; // ARRAY FOR INV PANEL INTERFACE ITEM POSITIONS INV_REGION_DESC gSCamoXY; void BtnMessageUpMapScreenCallback( GUI_BUTTON *btn,INT32 reason ); void BeginSellAllCallBack( UINT8 bExitValue ); void BeginDeleteAllCallBack( UINT8 bExitValue ); BOOLEAN fScrollButtonsInitialized = FALSE; BOOLEAN fFlashAssignDone = FALSE; BOOLEAN fInMapMode = FALSE; BOOLEAN fMapPanelDirty=TRUE; BOOLEAN fTeamPanelDirty = TRUE; BOOLEAN fCharacterInfoPanelDirty = TRUE; BOOLEAN gfLoadPending = FALSE; BOOLEAN fReDrawFace=FALSE; BOOLEAN fFirstTimeInMapScreen = TRUE; BOOLEAN fShowInventoryFlag = FALSE; BOOLEAN fMapInventoryItem=FALSE; BOOLEAN fShowDescriptionFlag=FALSE; BOOLEAN fResetMapCoords = FALSE; // are the graphics for mapscreen preloaded? BOOLEAN fPreLoadedMapGraphics = FALSE; BOOLEAN gfHotKeyEnterSector = FALSE; BOOLEAN fOneFrame = FALSE; BOOLEAN fShowFaceHightLight = FALSE; BOOLEAN fShowItemHighLight = FALSE; BOOLEAN gfAllowSkyriderTooFarQuote = FALSE; BOOLEAN fJustFinishedPlotting = FALSE; // for the flashing of the contract departure time...for when mercs are leaving in an hour or less BOOLEAN fFlashContractFlag = FALSE; BOOLEAN fShowTrashCanHighLight = FALSE; // the flags for display of pop up boxes/menus BOOLEAN fEndPlotting = FALSE; BOOLEAN gfInConfirmMapMoveMode = FALSE; BOOLEAN gfInChangeArrivalSectorMode = FALSE; // redraw character list BOOLEAN fDrawCharacterList = TRUE; // was the cursor set to the checkmark? BOOLEAN fCheckCursorWasSet = FALSE; BOOLEAN fShowingMapDisableBox = FALSE; BOOLEAN fShowFrameRate = FALSE; //BOOLEAN fMapExitDueToMessageBox = FALSE; BOOLEAN fEndShowInventoryFlag = FALSE; // draw the temp path BOOLEAN fDrawTempPath = TRUE; BOOLEAN gfCharacterListInited = FALSE; BOOLEAN gfGlowTimerExpired = FALSE; //not required to be saved. The flag is set to allow mapscreen to render once, then transition the //current tactical battle into autoresolve. BOOLEAN gfTransitionMapscreenToAutoResolve = FALSE; BOOLEAN gfSkyriderEmptyHelpGiven = FALSE; BOOLEAN gfRequestGiveSkyriderNewDestination = FALSE; BOOLEAN gfFirstMapscreenFrame = FALSE; BOOLEAN gfMapPanelWasRedrawn = FALSE; UINT8 gubMAP_HandInvDispText[ NUM_INV_SLOTS ]; // currently selected character's list index INT16 bSelectedInfoChar = -1; // map sort button images INT32 giMapSortButtonImage[ MAX_SORT_METHODS ] = { -1, -1, -1, -1, -1, -1 }; INT32 giMapSortButton[ MAX_SORT_METHODS ] = { -1, -1, -1, -1, -1, -1 }; INT32 giCharInfoButtonImage[ 2 ]; INT32 giCharInfoButton[ 2 ] = { -1, -1 }; INT32 giMapInvButtonDoneImage; INT32 giMapInvDoneButton = -1; INT32 giMapContractButton = -1; INT32 giMapContractButtonImage; INT32 giSortStateForMapScreenList = 0; BOOLEAN giSortOrderAscending = TRUE; INT32 giCommonGlowBaseTime = 0; INT32 giFlashAssignBaseTime = 0; INT32 giFlashContractBaseTime = 0; UINT32 guiFlashCursorBaseTime = 0; INT32 giPotCharPathBaseTime = 0; extern UINT32 guiVObjectSize; extern UINT32 guiVSurfaceSize; extern UINT8 gubHandPos; extern UINT16 gusOldItemIndex; extern UINT16 gusNewItemIndex; extern BOOLEAN gfDeductPoints; extern INT32 iLastHandPos; extern void CleanUpStack( OBJECTTYPE * pObj, OBJECTTYPE * pCursorObj ); extern void SwapGoggles(SOLDIERTYPE *pTeamSoldier); // HEADROCK HAM B2.8: Function to switch team's goggles uniformly extern void SwapGogglesUniformly(SOLDIERTYPE *pTeamSoldier, BOOLEAN fToNightVision); extern void InternalMAPBeginItemPointer( SOLDIERTYPE *pSoldier ); extern BOOLEAN ValidSelectableCharForNextOrPrev(INT32 iNewCharSlot); UINT32 guiCHARLIST; UINT32 guiCHARINFO; UINT32 guiSleepIcon; UINT32 guiCROSS; UINT32 guiMAPINV; UINT32 guiMapInvSecondHandBlockout; UINT32 guiULICONS; UINT32 guiNewMailIcons; UINT32 guiLEVELMARKER; // the white rectangle highlighting the current level on the map border UINT32 guiMapScreenAttachmentSlot; // misc mouse regions MOUSE_REGION gCharInfoFaceRegion; MOUSE_REGION gCharInfoHandRegion; MOUSE_REGION gMPanelRegion; MOUSE_REGION gMapViewRegion; MOUSE_REGION gMapScreenMaskRegion; MOUSE_REGION gTrashCanRegion; MOUSE_REGION gMapMercWeightRegion; MOUSE_REGION gMapMercCamoRegion; extern MOUSE_REGION gMapMessageRegion; extern MOUSE_REGION gMapMessageScrollBarRegion; // mouse regions for team info panel MOUSE_REGION gTeamListNameRegion[ CODE_MAXIMUM_NUMBER_OF_PLAYER_SLOTS ]; MOUSE_REGION gTeamListAssignmentRegion[ CODE_MAXIMUM_NUMBER_OF_PLAYER_SLOTS ]; MOUSE_REGION gTeamListSleepRegion[ CODE_MAXIMUM_NUMBER_OF_PLAYER_SLOTS ]; MOUSE_REGION gTeamListLocationRegion[ CODE_MAXIMUM_NUMBER_OF_PLAYER_SLOTS ]; MOUSE_REGION gTeamListDestinationRegion[ CODE_MAXIMUM_NUMBER_OF_PLAYER_SLOTS ]; MOUSE_REGION gTeamListContractRegion[ CODE_MAXIMUM_NUMBER_OF_PLAYER_SLOTS ]; OBJECTTYPE gItemPointer; SOLDIERTYPE *gpItemPointerSoldier; PathStPtr gpCharacterPreviousMercPath[ CODE_MAXIMUM_NUMBER_OF_PLAYER_SLOTS ]; PathStPtr gpHelicopterPreviousMercPath = NULL; // this is not a group id, but the internal militia group id. You can get the currently used group via gMilitiaPath[gMilitiaGroupId].sGroupid UINT8 gMilitiaGroupId = 0; PathStPtr gpMilitiaPreviousMercPath = NULL; // this is used to note which is the 'new' group created while plotting UINT8 gNewMilitiaGroupId = 0; MILITIA_PATH gMilitiaPath[MILITIA_PATROLS_MAX]; // GLOBAL VARIABLES (EXTERNAL) extern BOOLEAN fHoveringHelicopter; extern BOOLEAN fDeletedNode; extern BOOLEAN gfRenderPBInterface; extern BOOLEAN fMapScreenBottomDirty; extern BOOLEAN fResetTimerForFirstEntryIntoMapScreen; extern BOOLEAN gfStartedFromMapScreen; extern BOOLEAN gfUsePersistantPBI; extern BOOLEAN gfOneFramePauseOnExit; // the selected list of mercs extern BOOLEAN fSelectedListOfMercsForMapScreen[ CODE_MAXIMUM_NUMBER_OF_PLAYER_SLOTS ]; extern INT32 iDialogueBox; extern INT32 giMapInvDescButton; // HEADROCK HAM 4: Extern tab buttons for UDB extern INT32 giInvDescTabButton[3]; extern UINT32 guiBrownBackgroundForTeamPanel; // the town mine info box extern INT32 ghTownMineBox; // border and bottom buttons extern INT32 giMapBorderButtons[]; extern UINT32 guiMapButtonInventory[]; // the mine icon extern UINT32 guiMINEICON; extern UINT32 guiSecItemHiddenVO; extern UINT32 guiUIMessageTimeDelay; extern PathStPtr pTempCharacterPath; extern PathStPtr pTempHelicopterPath; extern PathStPtr pTempMilitiaPath; extern BOOLEAN gfAutoAIAware; extern void HandlePreBattleInterfaceStates(); // the title for the contract button on the character info panel in the upper left portion of the mapscreen extern STR16 pContractButtonString[]; extern STR16 pBullseyeStrings[]; extern OBJECTTYPE *gpItemDescObject; extern SOLDIERTYPE *pProcessingSoldier; // faces stuff extern FACETYPE *gpCurrentTalkingFace; // externs for highlighting of ammo/weapons extern UINT32 guiMouseOverItemTime; extern BOOLEAN gfCheckForMouseOverItem; extern INT8 gbCheckForMouseOverItemPos; //Autoresolve sets this variable which defaults to -1 when not needed. extern INT16 gsEnemyGainedControlOfSectorID; extern INT16 gsCiviliansEatenByMonsters; extern BOOLEAN gfFadeOutDone; extern UINT32 guiPendingScreen; extern CHAR16 gzUserDefinedButton1[ 128 ]; extern CHAR16 gzUserDefinedButton2[ 128 ]; extern BOOLEAN gfMilitiaPopupCreated; #ifdef JA2TESTVERSION extern INT16 MSYS_CurrentMX; extern INT16 MSYS_CurrentMY; #endif // PROTOTYPES // basic input void GetMapKeyboardInput( UINT32 *puiNewEvent ); void PollWheelInMapView(UINT32 *puiNewEvent); void PollLeftButtonInMapView( UINT32 *puiNewEvent ); void PollRightButtonInMapView( UINT32 *puiNewEvent ); // background render void BlitBackgroundToSaveBuffer( void ); // Drawing the Map UINT32 HandleMapUI( ); void RenderMapCursorsIndexesAnims( void ); BOOLEAN GetMapXY( INT16 sX, INT16 sY, INT16 *psMapWorldX, INT16 *psMapWorldY ); BOOLEAN GetMouseMapXY( INT16 *psMapWorldX, INT16 *psMapWorldY ); void StartConfirmMapMoveMode( INT16 sMapY ); void EndConfirmMapMoveMode( void ); void CancelMapUIMessage( void ); void MonitorMapUIMessage( void ); void RenderMapHighlight( INT16 sMapX, INT16 sMapY, UINT16 usLineColor, BOOLEAN fStationary ); void ShadeMapElem( INT16 sMapX, INT16 sMapY ); void PopupText( UINT16 *pFontString, ... ); void DrawString(STR16 pString, UINT16 uiX, UINT16 uiY, UINT32 uiFont); // Clock void SetClock(STR16 pString); void SetClockMin(STR16, ...); void SetClockHour(STR16 pStringA, ...); void SetHourAlternate(STR16 pStringA, ...); void SetDayAlternate(STR16 pStringA, ...); void RenderIconsForUpperLeftCornerPiece( INT8 bCharNumber ); void RenderAttributeStringsForUpperLeftHandCorner( UINT32 uiBufferToRenderTo ); void DisplayThePotentialPathForCurrentDestinationCharacterForMapScreenInterface( INT16 sMapX, INT16 sMapY ); void HandleCursorOverRifleAmmo( );//shadooow: function is now unused and can be deleted void SetUpCursorForStrategicMap( void ); void HandleAnimatedCursorsForMapScreen( ); void CheckToSeeIfMouseHasLeftMapRegionDuringPathPlotting( ); // handle change in info char void HandleChangeOfInfoChar( void ); // update town mine pop up void UpdateTownMinePopUpDisplay( void ); // Map Buttons void GlowFace( void ); void ResetMapButtons(); //Drawing Strings void DrawName( STR16 pName, INT16 sRowIndex, INT32 iFont ); void DrawAssignment( INT16 sCharNumber, INT16 sRowIndex, INT32 iFont ); void DrawLocation( INT16 sCharNumber, INT16 sRowIndex, INT32 iFont ); void DrawDestination( INT16 sCharNumber, INT16 sRowIndex, INT32 iFont ); void DrawTimeRemaining( INT16 sCharNumber, INT32 iFont, UINT8 ubFontColor ); void HandleAssignmentsDoneAndAwaitingFurtherOrders( void ); void HandleCommonGlowTimer( void ); void CheckIfPlottingForCharacterWhileAirCraft( void ); // handle highlighting of team panel lines void HandleChangeOfHighLightedLine( void ); // automatically pause/unpause time compression during certain events void UpdatePausedStatesDueToTimeCompression( void ); // handle pre battle interface in relation to inventory void HandlePreBattleInterfaceWithInventoryPanelUp( void ); void CreateDestroyMapCharacterScrollButtons( void ); // sort buttons for team list void AddTeamPanelSortButtonsForMapScreen( void ); void RemoveTeamPanelSortButtonsForMapScreen( void ); void SortListOfMercsInTeamPanel( BOOLEAN fRetainSelectedMercs, BOOLEAN fReverse = FALSE ); // OJW - buttons and boxes for MP interface void AddMPButtonsForMapScreen( void ); void RemoveMPButtonsForMapScreen( void ); void InitializeMPCoordinates( void ); void CreateMPCompassBox( void ); void DestroyMPCompassBox( void ); void CreateMPTeamBox( void ); void DestroyMPTeamBox( void ); void MPReadyButtonCallback( GUI_BUTTON *btn, INT32 reason ); void MPCompassChangeCallback( MOUSE_REGION * pReason, INT32 iReason); void CreateDestroyMouseRegionsForCompassBox(); void CompassBoxMvtCallback ( MOUSE_REGION* pRegion, INT32 iReason); void CompassBoxBtnCallback ( MOUSE_REGION* pRegion, INT32 iReason); void MPTeamChangeCallback( MOUSE_REGION * pReason, INT32 iReason); void CreateDestroyMouseRegionsForTeamBox(); void TeamBoxMvtCallback ( MOUSE_REGION* pRegion, INT32 iReason); void TeamBoxBtnCallback ( MOUSE_REGION* pRegion, INT32 iReason); // Rendering void RenderCharacterInfoBackground( void ); void RenderTeamRegionBackground( void ); void RenderMapRegionBackground( void ); void HandleHighLightingOfLinesInTeamPanel( void ); void ClearTeamPanel(); void PlotTemporaryPaths( void ); void PlotPermanentPaths( void ); void RenderHandPosItem( void ); void ContractListRegionBoxGlow( UINT16 usCount ); // void DisplayDestinationOfCurrentDestMerc( void ); void HandleCharBarRender( void ); // rebuild waypoints for selected character list void RebuildWayPointsForAllSelectedCharsGroups( void ); extern BOOLEAN HandleNailsVestFetish( SOLDIERTYPE *pSoldier, UINT32 uiHandPos, UINT16 usReplaceItem ); BOOLEAN CharacterIsInTransitAndHasItemPickedUp( INT8 bCharacterNumber ); void InterruptTimeForMenus( void ); // Pop Up Boxes void CreateAttributeBox( void ); void CreateVehicleBox( void ); void CreateContractBox( SOLDIERTYPE *pCharacter ); void CreateContractBoxMultiSelect(INT32 DailySalaries, INT32 WeeklySalaries, INT32 BiweeklySalaries); void CreateAssignmentsBox( void ); void CreateTrainingBox( void ); void CreateMercRemoveAssignBox( void ); void DetermineWhichAssignmentMenusCanBeShown( void ); void DetermineWhichMilitiaControlMenusCanBeShown( void ); //lal void DetermineIfContractMenuCanBeShown( void ); void ContractRegionBtnCallback( MOUSE_REGION * pRegion, INT32 iReason ); void ContractRegionMvtCallback( MOUSE_REGION * pRegion, INT32 iReason ); void HandleShadingOfLinesForContractMenu( void ); void UpdateStatusOfMapSortButtons( void ); void DisplayIconsForMercsAsleep( void ); BOOLEAN CharacterIsInLoadedSectorAndWantsToMoveInventoryButIsNotAllowed( INT16 bCharId ); void HandlePostAutoresolveMessages(); // screen mask for pop up menus void ClearScreenMaskForMapScreenExit( void ); void ResetAllSelectedCharacterModes( void ); // The Mouse/Btn Creation/Destruction // destroy regions/buttons void DestroyMouseRegionsForTeamList( void ); // create new regions/buttons void CreateMouseRegionsForTeamList( void ); void EnableDisableTeamListRegionsAndHelpText( void ); // merc about to leave, flash contract time BOOLEAN AnyMercsLeavingRealSoon(); void HandleContractTimeFlashForMercThatIsAboutLeave( void ); // Mouse Region Callbacks // team list void TeamListInfoRegionBtnCallBack(MOUSE_REGION *pRegion, INT32 iReason ); void TeamListInfoRegionMvtCallBack(MOUSE_REGION *pRegion, INT32 iReason ); void TeamListAssignmentRegionBtnCallBack(MOUSE_REGION *pRegion, INT32 iReason ); void TeamListAssignmentRegionMvtCallBack(MOUSE_REGION *pRegion, INT32 iReason ); void TeamListDestinationRegionBtnCallBack(MOUSE_REGION *pRegion, INT32 iReason ); void TeamListDestinationRegionMvtCallBack(MOUSE_REGION *pRegion, INT32 iReason ); void TeamListContractRegionBtnCallBack( MOUSE_REGION *pRegion, INT32 iReason ); void TeamListContractRegionMvtCallBack( MOUSE_REGION *pRegion, INT32 iReason ); void TeamListSleepRegionBtnCallBack( MOUSE_REGION *pRegion, INT32 iReason ); void TeamListSleepRegionMvtCallBack( MOUSE_REGION *pRegion, INT32 iReason ); void FaceRegionBtnCallback( MOUSE_REGION *pRegion, INT32 iReason ); void FaceRegionMvtCallback( MOUSE_REGION *pRegion, INT32 iReason ); void ItemRegionBtnCallback( MOUSE_REGION *pRegion, INT32 iReason ); void ItemRegionMvtCallback( MOUSE_REGION *pRegion, INT32 iReason ); // mapscreen mouse region screen mask btn callback void MapScreenMarkRegionBtnCallback(MOUSE_REGION *pRegion, INT32 iReason ); // inventory mvt and click callbacks void MAPInvMoveCallback( MOUSE_REGION *pRegion, INT32 iReason ); void MAPInvClickCallback( MOUSE_REGION *pRegion, INT32 iReason ); void MAPInvClickCamoCallback( MOUSE_REGION *pRegion, INT32 iReason ); void MAPInvMoveCamoCallback( MOUSE_REGION *pRegion, INT32 iReason ); void InvmaskRegionBtnCallBack( MOUSE_REGION *pRegion, INT32 iReason ); void TrashCanBtnCallback( MOUSE_REGION *pRegion, INT32 iReason); extern void KeyRingItemPanelButtonCallback( MOUSE_REGION *pRegion, INT32 iReason ); extern BOOLEAN CanPlayerUseSectorInventory( SOLDIERTYPE *pSelectedSoldier ); // handle talking void HandleSpontanousTalking( void ); BOOLEAN ContinueDialogue(SoldierID id, BOOLEAN fDone ); extern void CreateDestroyMilitiaSectorButtons( void ); extern void CreateDestroySupplySectorButtons(); // mouse position test BOOLEAN IsCursorWithInRegion(INT16 sLeft, INT16 sRight, INT16 sTop, INT16 sBottom ); // pop up boxes void CreateVehicleBox( ); void TestMessageSystem( void ); BOOLEAN CheckIfClickOnLastSectorInPath( INT16 sX, INT16 sY ); //update any bad assignments..error checking void UpdateBadAssignments( void ); // hwo many on team, if less than 2, disable prev/next merc buttons void UpdateTheStateOfTheNextPrevMapScreenCharacterButtons( void ); // inventory void CreateDestroyTrashCanRegion( void ); void DoneInventoryMapBtnCallback( GUI_BUTTON *btn,INT32 reason ); // handle cursor for invenetory mode..update to object selected, if needed void HandleMapInventoryCursor( ); void MAPEndItemPointer( ); void MAPBeginItemPointer( SOLDIERTYPE *pSoldier, UINT8 ubHandPos ); // create/destroy inventory button as needed void CreateDestroyMapInvButton(); void PrevInventoryMapBtnCallback( GUI_BUTTON *btn, INT32 reason ); void NextInventoryMapBtnCallback( GUI_BUTTON *btn, INT32 reason ); void CreateMapCharInvIOregions(); void DestroyMapCharInvIOregions(); // check if cursor needs to be set to checkmark or to the walking guy? void UpdateCursorIfInLastSector( void ); void ContractButtonCallback(GUI_BUTTON *btn,INT32 reason); void MapScreenDefaultOkBoxCallback( UINT8 bExitValue ); // blt inventory panel void BltCharInvPanel(); // show character information void DrawCharacterInfo(INT16 sCharNumber); void DisplayCharacterInfo( void ); void UpDateStatusOfContractBox( void ); void DrawMPPlayerList (); // OJW - 20081201 // get which index in the mapscreen character list is this guy INT32 GetIndexForthis( SOLDIERTYPE *pSoldier ); void CheckForAndRenderNewMailOverlay(); void CheckForInventoryModeCancellation(); void ChangeMapScreenMaskCursor( UINT16 usCursor ); void CancelOrShortenPlottedPath( void ); // HEADROCK HAM B2.8: Added argument to enable multi-selecting entire squads BOOLEAN HandleCtrlOrShiftInTeamPanel( INT16 bCharNumber, BOOLEAN fFromRightClickAssignments ); INT32 GetContractExpiryTime( SOLDIERTYPE *pSoldier ); INT32 GetGroundTravelTimeOfCharacter( INT8 bCharNumber ); INT16 CalcLocationValueForChar( INT32 iCounter ); void CancelChangeArrivalSectorMode( ); void MakeMapModesSuitableForDestPlotting( INT8 bCharNumber ); BOOLEAN AnyMovableCharsInOrBetweenThisSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ ); void SwapCharactersInList( INT32 iCharA, INT32 iCharB ); BOOLEAN CanChangeDestinationForCharSlot( INT16 bCharNumber, BOOLEAN fShowErrorMessage ); BOOLEAN RequestGiveSkyriderNewDestination( void ); void ExplainWhySkyriderCantFly( void ); UINT8 PlayerMercsInHelicopterSector( void ); void HandleNewDestConfirmation( INT16 sMapX, INT16 sMapY ); void RandomAwakeSelectedMercConfirmsStrategicMove( void ); void DestinationPlottingCompleted( void ); void HandleMilitiaRedistributionClick( void ); void StartChangeSectorArrivalMode( void ); BOOLEAN CanMoveBullseyeAndClickedOnIt( INT16 sMapX, INT16 sMapY ); void CreateBullsEyeOrChopperSelectionPopup( void ); void BullsEyeOrChopperSelectionPopupCallback( UINT8 ubExitValue ); void WakeUpAnySleepingSelectedMercsOnFootOrDriving( void ); void GetMapscreenMercAssignmentString( SOLDIERTYPE *pSoldier, CHAR16 sString[] ); void GetMapscreenMercLocationString( SOLDIERTYPE *pSoldier, CHAR16 sString[] ); void GetMapscreenMercDestinationString( SOLDIERTYPE *pSoldier, CHAR16 sString[] ); void GetMapscreenMercDepartureString( SOLDIERTYPE *pSoldier, CHAR16 sString[], UINT8 *pubFontColor ); void InitPreviousPaths( void ); void RememberPreviousPathForAllSelectedChars( void ); void RestorePreviousPaths( void ); void ClearPreviousPaths( void ); void SelectAllCharactersInSquad( INT8 bSquadNumber ); BOOLEAN CanDrawSectorCursor( void ); void RestoreMapSectorCursor( INT16 sMapX, INT16 sMapY ); void RequestToggleMercInventoryPanel( void ); void RequestContractMenu( void ); void ChangeCharacterListSortMethod( INT32 iValue ); void MapscreenMarkButtonsDirty(); // Bob: functions for packing vehicles with filled LBE items void moveSectorInventoryToVehicle(SOLDIERTYPE *pSoldier); void fillCurrentSectorLBEItems(SOLDIERTYPE *pSoldier); void fillLBEWithSectorItems(OBJECTTYPE * LBEObject); void moveCurrentSectorItemsToVehicle(SOLDIERTYPE *pSoldier); bool placeItemInVehicle(SOLDIERTYPE *pSoldier, WORLDITEM &worldItem); bool placeItemInVehicle(SOLDIERTYPE *pSoldier, OBJECTTYPE &item); extern BOOLEAN CanRedistributeMilitiaInSector( INT16 sClickedSectorX, INT16 sClickedSectorY, INT8 bClickedTownId ); extern INT32 GetNumberOfMercsInUpdateList( void ); extern INT32 SellItem( OBJECTTYPE& object, BOOLEAN fAll, BOOLEAN useModifier = TRUE ); #ifdef INVFIX_Moa//dnl ch85 050214 void DeleteAllItemsInInventoryPool(); #endif #ifdef JA2UB void HandleWhenPlayerHasNoMercsAndNoLaptop(); #endif #ifdef JA2TESTVERSION void TestDumpStatChanges( void ); void DumpSectorDifficultyInfo( void ); void DumpItemsList( void ); #endif BOOLEAN IsMercInActiveSector(SOLDIERTYPE * pSoldier) { if(pSoldier->sSectorX != sSelMapX) return( FALSE ); if(pSoldier->sSectorY != sSelMapY) return( FALSE ); if(pSoldier->bSectorZ != iCurrentMapSectorZ) return( FALSE ); return( TRUE ); } void BeginSellAllCallBack( UINT8 bExitValue ) { INT32 iPrice = 0; bool anythingSold = false; if( bExitValue == MSG_BOX_RETURN_YES ) { fRestoreBackgroundForMessageBox = TRUE; if ( gpItemPointer != NULL || InSectorStackPopup( ) || InItemStackPopup( ) || InItemDescriptionBox( ) || InKeyRingPopup( ) ) { return; } for(UINT32 wItem = 0; wItem < pInventoryPoolList.size(); wItem++) //CHRISL: It's safer to use pInventoryPoolList.size() versus guiNumWorldItems as it avoids any possibility of a vector size error { if(pInventoryPoolList[wItem].object.exists() == true && (pInventoryPoolList[wItem].usFlags & WORLD_ITEM_REACHABLE)) { if(0 == pInventoryPoolList[wItem].object.MoveThisObjectTo(gItemPointer,-1,0,NUM_INV_SLOTS,MAX_OBJECTS_PER_SLOT)) { if (pInventoryPoolList[wItem].object.exists() == false) { pInventoryPoolList[wItem].object.initialize(); } // Dirty interface fMapPanelDirty = TRUE; gpItemPointer = &gItemPointer; // Sell Item // HEADROCK HAM 5: Added argument iPrice += SellItem( gItemPointer, TRUE ); gpItemPointer = NULL; fMapInventoryItem = FALSE; // HEADROCK HAM 5: Sale of $0 now re-enabled. //if (iPrice == 0) { // iPrice = 1; //} anythingSold = true; HandleButtonStatesWhileMapInventoryActive(); } } } // HEADROCK HAM 5: No transaction if no money. if(anythingSold == true && iPrice > 0) AddTransactionToPlayersBook( SOLD_ITEMS, 0, GetWorldTotalMin(), iPrice ); } } void BeginDeleteAllCallBack( UINT8 bExitValue ) { if( bExitValue == MSG_BOX_RETURN_YES ) { fRestoreBackgroundForMessageBox = TRUE; #ifdef INVFIX_Moa//dnl ch85 050214 if ( gpItemPointer != NULL || InSectorStackPopup( ) || InItemStackPopup( ) || InItemDescriptionBox( ) || InKeyRingPopup( ) ) { return; } for(UINT32 wItem = 0; wItem < guiNumWorldItems; wItem++) //WS TODO: is "for(UINT32 wItem = 0; wItem < pInventoryPoolList.size(); wItem++)" { if(0 == pInventoryPoolList[wItem].object.MoveThisObjectTo(gItemPointer,-1,0,NUM_INV_SLOTS,MAX_OBJECTS_PER_SLOT)) { if (pInventoryPoolList[wItem].object.exists() == false) { pInventoryPoolList[wItem].object.initialize(); } // Dirty interface fMapPanelDirty = TRUE; gpItemPointer = &gItemPointer; // Delete Item gpItemPointer = NULL; fMapInventoryItem = FALSE; } } } #else for(UINT32 i=0; i= _1024x768) { UI_CHARPANEL.Region = { UI_MAP.BorderRegion.x - 260, UI_MAP.BorderRegion.y, 262, 106 }; UI_CHARINV.Region = { UI_CHARPANEL.Region.x, UI_CHARPANEL.Region.y + UI_CHARPANEL.Region.height, 262, 490 }; UI_CHARLIST.Region = { UI_CHARINV.Region.x, UI_CHARINV.Region.y, 262, 540 }; } else if (iResolution >= _800x600) { UI_CHARPANEL.Region = { UI_MAP.BorderRegion.x - 260, UI_MAP.BorderRegion.y, 262, 106 }; UI_CHARINV.Region = { UI_CHARPANEL.Region.x, UI_CHARPANEL.Region.y + UI_CHARPANEL.Region.height, 262, 373 }; UI_CHARLIST.Region = { UI_CHARINV.Region.x, UI_CHARINV.Region.y, 262, 372 }; } else { UI_CHARPANEL.Region = { UI_MAP.BorderRegion.x - 260, UI_MAP.BorderRegion.y, 262, 106 }; UI_CHARINV.Region = { UI_CHARPANEL.Region.x, UI_CHARPANEL.Region.y + UI_CHARPANEL.Region.height, 262, 252 }; UI_CHARLIST.Region = { UI_CHARINV.Region.x, UI_CHARINV.Region.y, 262, 254 }; } { //UI_CHARPANEL.Region = { // UI_MAP.BorderRegion.x - 261, // 0, // 261, 106 //}; const auto x = UI_CHARPANEL.Region.x; const auto y = UI_CHARPANEL.Region.y; UI_CHARPANEL.FacePicture = { x + 9, y + 20, 60, 63 }; UI_CHARPANEL.NickName = { x + 8, y + 69, 52, 6 }; UI_CHARPANEL.FullName = { x + 14, y + 5, 150, 6 }; UI_CHARPANEL.HandItem = { x + 6, y + 81, 59, 20 }; UI_CHARPANEL.Statusbars = { x + 66, y + 61, 6 }; // For extern use CHAR_BAR_INFO_X = UI_CHARPANEL.Statusbars.x; CHAR_BAR_INFO_Y = UI_CHARPANEL.Statusbars.y; UI_CHARPANEL.Button.Up = { x + 67, y + 68 }; UI_CHARPANEL.Button.Down = { x + 67, y + 87 }; UI_CHARPANEL.Button.Contract = { x + 185, y + 50 }; UI_CHARPANEL.Text.Assignment = { x + 220, y + 4 }; UI_CHARPANEL.Text.Attributes = { x + 88, y + 22 }; UI_CHARPANEL.Text.Attributes2 = { x + 133, y + 22 }; UI_CHARPANEL.Text.Health = { x + 87, y + 80 }; UI_CHARPANEL.Text.Morale = { x + 87, y + 94 }; UI_CHARPANEL.Text.Condition = { x + 87, y + 80 }; UI_CHARPANEL.Icon = { x + 187, y + 64, 10, 10, 13 }; // For extern use UI_CHAR_Icon = UI_CHARPANEL.Icon; { const int x1 = x + 112; const int x2 = x + 159; const int y1 = y + 22; const int yOffset = 10; // First column UI_CHARPANEL.Attr.AGL = { x1, y1 }; UI_CHARPANEL.Attr.DEX = { x1, y1 + yOffset }; UI_CHARPANEL.Attr.STR = { x1, y1 + yOffset * 2 }; UI_CHARPANEL.Attr.LDR = { x1, y1 + yOffset * 3 }; UI_CHARPANEL.Attr.WIS = { x1, y1 + yOffset * 4 }; // Second column UI_CHARPANEL.Attr.LVL = { x2, y1 }; UI_CHARPANEL.Attr.MRK = { x2, y1 + yOffset }; UI_CHARPANEL.Attr.MEC = { x2, y1 + yOffset * 2 }; UI_CHARPANEL.Attr.EXP = { x2, y1 + yOffset * 3 }; UI_CHARPANEL.Attr.MED = { x2, y1 + yOffset * 4 }; UI_CHARPANEL.Attr.width = 15; UI_CHARPANEL.Attr.height = GetFontHeight(CHAR_FONT); } UI_CHARPANEL.Text.CurrentHitpoints = { x + 133, y + 80, 42, 10 }; UI_CHARPANEL.Text.CurrentMorale = { x + 133, y + 94, 42, 7 }; UI_CHARPANEL.Text.Pay = { x + 150, y + 84, 45, GetFontHeight(CHAR_FONT) }; UI_CHARPANEL.Text.TimeRemaining = { x + 207, y + 65, 51, GetFontHeight(CHAR_FONT) }; UI_CHARPANEL.Text.Salary = { UI_CHARPANEL.Text.TimeRemaining.x, y + 79, UI_CHARPANEL.Text.TimeRemaining.width - 8, UI_CHARPANEL.Text.TimeRemaining.height }; UI_CHARPANEL.Text.Medical = { UI_CHARPANEL.Text.TimeRemaining.x, y + 93, UI_CHARPANEL.Text.TimeRemaining.width - 8, UI_CHARPANEL.Text.TimeRemaining.height }; UI_CHARPANEL.Text.CurrentAssignment = { x + 182, y + 18, 79, 10 }; UI_CHARPANEL.Text.CurrentAssignment_Y2 = y + 31; } // END Charpanel // BEGIN Strategic merc inventory { //UI_CHARINV.Region = { // UI_MAP.BorderRegion.x - 262, // UI_CHARPANEL.Region.y + UI_CHARPANEL.Region.height, // 262, 490 //}; const auto x = UI_CHARINV.Region.x; const auto y = UI_CHARINV.Region.y; // For extern use PLAYER_INFO_X = x; PLAYER_INFO_Y = y; // item description region MAP_ITEMDESC_START_X = x; MAP_ITEMDESC_START_Y = y; UI_CHARINV.Button.Done = { x + 217, y + 210 }; UI_CHARINV.Button.Trashcan = { x + 177, y + 210, 29, 24 }; UI_CHARINV.Text.Armor = { x + 210, y + 81 }; UI_CHARINV.Text.ArmorLabel = { x + 209, y + 71 }; UI_CHARINV.Text.ArmorPercent = { x + 231, y + 81 }; UI_CHARINV.Text.Weight = { x + 177, y + 158 }; UI_CHARINV.Text.WeightLabel = { x + 174, y + 147 }; UI_CHARINV.Text.WeightPercent = { x + 197, y + 158 }; UI_CHARINV.Text.Camo = { x + 177, y + 185 }; UI_CHARINV.Text.CamoLabel = { x + 177, y + 174 }; UI_CHARINV.Text.CamoPercent = { x + 197, y + 185 }; UI_CHARINV.Text.PercentWidth = 20; UI_CHARINV.Text.PercentHeight = 10; UI_CHARINV.BodyPanel = { x + 71, y + 9 }; // X, Y Location of Map screen's Camouflage region gSCamoXY.sX = UI_CHARINV.BodyPanel.iX; gSCamoXY.sY = UI_CHARINV.BodyPanel.iY; //For extern use MAP_KEYRING_X = x + 218; MAP_KEYRING_Y = y + 165; // Inventory slots gMapScreenInvPocketXY[HELMETPOS].sX = x + 204; gMapScreenInvPocketXY[HELMETPOS].sY = y + 9; // HELMETPOS gMapScreenInvPocketXY[VESTPOS].sX = x + 204; gMapScreenInvPocketXY[VESTPOS].sY = y + 38; // VESTPOS gMapScreenInvPocketXY[LEGPOS].sX = x + 204; gMapScreenInvPocketXY[LEGPOS].sY = y + 98; // LEGPOS, gMapScreenInvPocketXY[HEAD1POS].sX = x + 21; gMapScreenInvPocketXY[HEAD1POS].sY = y + 9; // HEAD1POS gMapScreenInvPocketXY[HEAD2POS].sX = x + 21; gMapScreenInvPocketXY[HEAD2POS].sY = y + 33; // HEAD2POS gMapScreenInvPocketXY[HANDPOS].sX = x + 21; gMapScreenInvPocketXY[HANDPOS].sY = y + 87; // HANDPOS, gMapScreenInvPocketXY[SECONDHANDPOS].sX = x + 21; gMapScreenInvPocketXY[SECONDHANDPOS].sY = y + 111; // SECONDHANDPOS gMapScreenInvPocketXY[BIGPOCK1POS].sX = x + 98; gMapScreenInvPocketXY[BIGPOCK1POS].sY = y + 144; // BIGPOCK1 gMapScreenInvPocketXY[BIGPOCK2POS].sX = x + 98; gMapScreenInvPocketXY[BIGPOCK2POS].sY = y + 168; // BIGPOCK2 gMapScreenInvPocketXY[BIGPOCK3POS].sX = x + 98; gMapScreenInvPocketXY[BIGPOCK3POS].sY = y + 192; // BIGPOCK3 gMapScreenInvPocketXY[BIGPOCK4POS].sX = x + 98; gMapScreenInvPocketXY[BIGPOCK4POS].sY = y + 216; // BIGPOCK4 gMapScreenInvPocketXY[SMALLPOCK1POS].sX = x + 22; gMapScreenInvPocketXY[SMALLPOCK1POS].sY = y + 144; // SMALLPOCK1 gMapScreenInvPocketXY[SMALLPOCK2POS].sX = x + 22; gMapScreenInvPocketXY[SMALLPOCK2POS].sY = y + 168; // SMALLPOCK2 gMapScreenInvPocketXY[SMALLPOCK3POS].sX = x + 22; gMapScreenInvPocketXY[SMALLPOCK3POS].sY = y + 192; // SMALLPOCK3 gMapScreenInvPocketXY[SMALLPOCK4POS].sX = x + 22; gMapScreenInvPocketXY[SMALLPOCK4POS].sY = y + 216; // SMALLPOCK4 gMapScreenInvPocketXY[SMALLPOCK5POS].sX = x + 60; gMapScreenInvPocketXY[SMALLPOCK5POS].sY = y + 144; // SMALLPOCK5 gMapScreenInvPocketXY[SMALLPOCK6POS].sX = x + 60; gMapScreenInvPocketXY[SMALLPOCK6POS].sY = y + 168; // SMALLPOCK6 gMapScreenInvPocketXY[SMALLPOCK7POS].sX = x + 60; gMapScreenInvPocketXY[SMALLPOCK7POS].sY = y + 192; // SMALLPOCK7 gMapScreenInvPocketXY[SMALLPOCK8POS].sX = x + 60; gMapScreenInvPocketXY[SMALLPOCK8POS].sY = y + 216; // SMALLPOCK8 } // END Strategic merc inventory // BEGIN Character list { //UI_CHARLIST.Region = { 0, 0, 254, 600 }; const auto x = UI_CHARLIST.Region.x; UI_CHARLIST.y = UI_CHARLIST.Region.y + 26; UI_CHARLIST.yOffset = 2; UI_CHARLIST.Title = { x, UI_CHARLIST.Region.y + 5 - 113 }; // 113 comes from gMapSortButtons y-coordinate UI_CHARLIST.xName = x + 4; UI_CHARLIST.widthName = 51; UI_CHARLIST.xAssignment = x + 60; UI_CHARLIST.widthAssignment = 51; UI_CHARLIST.xSleep = x + 116; UI_CHARLIST.widthSleep = 19; UI_CHARLIST.xLocation = x + 140; UI_CHARLIST.widthLocation = 32; UI_CHARLIST.xETA = x + 177; UI_CHARLIST.widthETA = 33; UI_CHARLIST.xTimeRemaining = x + 215; UI_CHARLIST.widthTimeRemaining = 28; //For extern use POP_UP_BOX_X = x + 120; } MAP_INV_STATS_TITLE_FONT_COLOR = 6; //OJW - MP interface changes InitializeMPCoordinates(); return TRUE; } BOOLEAN InitializeInvPanelCoordsNew() { if (isWidescreenUI()) { UI_CHARPANEL.Region = { UI_MAP.BorderRegion.x - 262, UI_MAP.BorderRegion.y, 262, 106 }; UI_CHARINV.Region = { UI_CHARPANEL.Region.x, UI_CHARPANEL.Region.y + UI_CHARPANEL.Region.height, 262, 490 }; UI_CHARLIST.Region = { 0, 0, 254, 600 }; } else if (iResolution >= _1024x768) { UI_CHARPANEL.Region = { UI_MAP.BorderRegion.x - 260, UI_MAP.BorderRegion.y, 262, 106 }; UI_CHARINV.Region = { UI_CHARPANEL.Region.x, UI_CHARPANEL.Region.y + UI_CHARPANEL.Region.height, 262, 490 }; UI_CHARLIST.Region = { UI_CHARINV.Region.x, UI_CHARINV.Region.y, 262, 540}; } else if (iResolution >= _800x600) { UI_CHARPANEL.Region = { UI_MAP.BorderRegion.x - 260, UI_MAP.BorderRegion.y, 262, 106 }; UI_CHARINV.Region = { UI_CHARPANEL.Region.x, UI_CHARPANEL.Region.y + UI_CHARPANEL.Region.height, 262, 490 }; UI_CHARLIST.Region = { UI_CHARINV.Region.x, UI_CHARINV.Region.y, 262, 372 }; } else { UI_CHARPANEL.Region = { UI_MAP.BorderRegion.x - 260, UI_MAP.BorderRegion.y, 262, 106 }; UI_CHARINV.Region = { UI_CHARPANEL.Region.x, UI_CHARPANEL.Region.y + UI_CHARPANEL.Region.height, 262, 490 }; UI_CHARLIST.Region = { UI_CHARINV.Region.x, UI_CHARINV.Region.y, 262, 254 }; } InitializeInvPanelCoords(); //OJW - MP interface changes InitializeMPCoordinates(); return TRUE; } void InitializeMPCoordinates() { //OJW - MP interface changes const auto x = UI_CHARLIST.Region.x; const auto y = UI_CHARLIST.Region.y; if (isWidescreenUI()) { MP_BTN_Y = y + 507; } else if (iResolution >= _1024x768) { MP_BTN_Y = 448 + y; } else if (iResolution >= _800x600) { MP_BTN_Y = 280 + y; } else { MP_BTN_Y = 162 + y; } MP_ROWSTART_Y = MP_BTN_Y + 21; MP_PLAYER_X = 5 + x; MP_PLAYER_W = 75 + x; MP_TEAM_X = 84 + x; MP_TEAM_W = 40 + x; MP_COMPASS_X = 130 + x; MP_COMPASS_W = 19 + x; MP_GAMEINFO_X = 154 + x; MP_GAMEINFO_W = 81 + x; // End of MP interface changes } BOOLEAN InitializeInvPanelCoordsVehicle( ) { InitializeInvPanelCoordsNew(); const auto x = UI_CHARINV.Region.x; const auto y = UI_CHARINV.Region.y; // Inventory slots if (iResolution >= _640x480 && iResolution < _800x600) { gMapScreenInvPocketXY[14].sX = x + 37; gMapScreenInvPocketXY[14].sY = y + 89; gMapScreenInvPocketXY[15].sX = x + 104; gMapScreenInvPocketXY[15].sY = y + 89; gMapScreenInvPocketXY[16].sX = x + 171; gMapScreenInvPocketXY[16].sY = y + 89; gMapScreenInvPocketXY[17].sX = x + 37; gMapScreenInvPocketXY[17].sY = y + 110; gMapScreenInvPocketXY[18].sX = x + 104; gMapScreenInvPocketXY[18].sY = y + 110; gMapScreenInvPocketXY[19].sX = x + 171; gMapScreenInvPocketXY[19].sY = y + 110; gMapScreenInvPocketXY[20].sX = x + 37; gMapScreenInvPocketXY[20].sY = y + 131; gMapScreenInvPocketXY[21].sX = x + 104; gMapScreenInvPocketXY[21].sY = y + 131; gMapScreenInvPocketXY[22].sX = x + 171; gMapScreenInvPocketXY[22].sY = y + 131; gMapScreenInvPocketXY[23].sX = x + 37; gMapScreenInvPocketXY[23].sY = y + 152; gMapScreenInvPocketXY[24].sX = x + 104; gMapScreenInvPocketXY[24].sY = y + 152; gMapScreenInvPocketXY[25].sX = x + 171; gMapScreenInvPocketXY[25].sY = y + 152; gMapScreenInvPocketXY[26].sX = x + 37; gMapScreenInvPocketXY[26].sY = y + 173; gMapScreenInvPocketXY[27].sX = x + 104; gMapScreenInvPocketXY[27].sY = y + 173; gMapScreenInvPocketXY[28].sX = x + 171; gMapScreenInvPocketXY[28].sY = y + 173; gMapScreenInvPocketXY[29].sX = x + 37; gMapScreenInvPocketXY[29].sY = y + 194; gMapScreenInvPocketXY[30].sX = x + 104; gMapScreenInvPocketXY[30].sY = y + 194; gMapScreenInvPocketXY[31].sX = x + 171; gMapScreenInvPocketXY[31].sY = y + 194; gMapScreenInvPocketXY[32].sX = x + 37; gMapScreenInvPocketXY[32].sY = y + 215; gMapScreenInvPocketXY[33].sX = x + 104; gMapScreenInvPocketXY[33].sY = y + 215; gMapScreenInvPocketXY[34].sX = x + 171; gMapScreenInvPocketXY[34].sY = y + 215; gMapScreenInvPocketXY[35].sX = x + 37; gMapScreenInvPocketXY[35].sY = y + 236; gMapScreenInvPocketXY[36].sX = x + 104; gMapScreenInvPocketXY[36].sY = y + 236; gMapScreenInvPocketXY[37].sX = x + 171; gMapScreenInvPocketXY[37].sY = y + 236; gMapScreenInvPocketXY[38].sX = x + 37; gMapScreenInvPocketXY[38].sY = y + 257; gMapScreenInvPocketXY[39].sX = x + 104; gMapScreenInvPocketXY[39].sY = y + 257; gMapScreenInvPocketXY[40].sX = x + 171; gMapScreenInvPocketXY[40].sY = y + 257; gMapScreenInvPocketXY[41].sX = x + 37; gMapScreenInvPocketXY[41].sY = y + 278; gMapScreenInvPocketXY[42].sX = x + 104; gMapScreenInvPocketXY[42].sY = y + 278; gMapScreenInvPocketXY[43].sX = x + 171; gMapScreenInvPocketXY[43].sY = y + 278; gMapScreenInvPocketXY[44].sX = x + 37; gMapScreenInvPocketXY[44].sY = y + 299; gMapScreenInvPocketXY[45].sX = x + 104; gMapScreenInvPocketXY[45].sY = y + 299; gMapScreenInvPocketXY[46].sX = x + 171; gMapScreenInvPocketXY[46].sY = y + 299; gMapScreenInvPocketXY[47].sX = x + 37; gMapScreenInvPocketXY[47].sY = y + 320; gMapScreenInvPocketXY[48].sX = x + 104; gMapScreenInvPocketXY[48].sY = y + 320; gMapScreenInvPocketXY[49].sX = x + 171; gMapScreenInvPocketXY[49].sY = y + 320; gMapScreenInvPocketXY[50].sX = x + 37; gMapScreenInvPocketXY[50].sY = y + 341; gMapScreenInvPocketXY[51].sX = x + 104; gMapScreenInvPocketXY[51].sY = y + 341; gMapScreenInvPocketXY[52].sX = x + 171; gMapScreenInvPocketXY[52].sY = y + 341; } else { gMapScreenInvPocketXY[14].sX = x + 37; gMapScreenInvPocketXY[14].sY = y + 156; gMapScreenInvPocketXY[15].sX = x + 104; gMapScreenInvPocketXY[15].sY = y + 156; gMapScreenInvPocketXY[16].sX = x + 171; gMapScreenInvPocketXY[16].sY = y + 156; gMapScreenInvPocketXY[17].sX = x + 37; gMapScreenInvPocketXY[17].sY = y + 180; gMapScreenInvPocketXY[18].sX = x + 104; gMapScreenInvPocketXY[18].sY = y + 180; gMapScreenInvPocketXY[19].sX = x + 171; gMapScreenInvPocketXY[19].sY = y + 180; gMapScreenInvPocketXY[20].sX = x + 37; gMapScreenInvPocketXY[20].sY = y + 204; gMapScreenInvPocketXY[21].sX = x + 104; gMapScreenInvPocketXY[21].sY = y + 204; gMapScreenInvPocketXY[22].sX = x + 171; gMapScreenInvPocketXY[22].sY = y + 204; gMapScreenInvPocketXY[23].sX = x + 37; gMapScreenInvPocketXY[23].sY = y + 228; gMapScreenInvPocketXY[24].sX = x + 104; gMapScreenInvPocketXY[24].sY = y + 228; gMapScreenInvPocketXY[25].sX = x + 171; gMapScreenInvPocketXY[25].sY = y + 228; gMapScreenInvPocketXY[26].sX = x + 37; gMapScreenInvPocketXY[26].sY = y + 252; gMapScreenInvPocketXY[27].sX = x + 104; gMapScreenInvPocketXY[27].sY = y + 252; gMapScreenInvPocketXY[28].sX = x + 171; gMapScreenInvPocketXY[28].sY = y + 252; gMapScreenInvPocketXY[29].sX = x + 37; gMapScreenInvPocketXY[29].sY = y + 276; gMapScreenInvPocketXY[30].sX = x + 104; gMapScreenInvPocketXY[30].sY = y + 276; gMapScreenInvPocketXY[31].sX = x + 171; gMapScreenInvPocketXY[31].sY = y + 276; gMapScreenInvPocketXY[32].sX = x + 37; gMapScreenInvPocketXY[32].sY = y + 300; gMapScreenInvPocketXY[33].sX = x + 104; gMapScreenInvPocketXY[33].sY = y + 300; gMapScreenInvPocketXY[34].sX = x + 171; gMapScreenInvPocketXY[34].sY = y + 300; gMapScreenInvPocketXY[35].sX = x + 37; gMapScreenInvPocketXY[35].sY = y + 324; gMapScreenInvPocketXY[36].sX = x + 104; gMapScreenInvPocketXY[36].sY = y + 324; gMapScreenInvPocketXY[37].sX = x + 171; gMapScreenInvPocketXY[37].sY = y + 324; gMapScreenInvPocketXY[38].sX = x + 37; gMapScreenInvPocketXY[38].sY = y + 348; gMapScreenInvPocketXY[39].sX = x + 104; gMapScreenInvPocketXY[39].sY = y + 348; gMapScreenInvPocketXY[40].sX = x + 171; gMapScreenInvPocketXY[40].sY = y + 348; gMapScreenInvPocketXY[41].sX = x + 37; gMapScreenInvPocketXY[41].sY = y + 372; gMapScreenInvPocketXY[42].sX = x + 104; gMapScreenInvPocketXY[42].sY = y + 372; gMapScreenInvPocketXY[43].sX = x + 171; gMapScreenInvPocketXY[43].sY = y + 372; gMapScreenInvPocketXY[44].sX = x + 37; gMapScreenInvPocketXY[44].sY = y + 396; gMapScreenInvPocketXY[45].sX = x + 104; gMapScreenInvPocketXY[45].sY = y + 396; gMapScreenInvPocketXY[46].sX = x + 171; gMapScreenInvPocketXY[46].sY = y + 396; gMapScreenInvPocketXY[47].sX = x + 37; gMapScreenInvPocketXY[47].sY = y + 420; gMapScreenInvPocketXY[48].sX = x + 104; gMapScreenInvPocketXY[48].sY = y + 420; gMapScreenInvPocketXY[49].sX = x + 171; gMapScreenInvPocketXY[49].sY = y + 420; gMapScreenInvPocketXY[50].sX = x + 37; gMapScreenInvPocketXY[50].sY = y + 444; gMapScreenInvPocketXY[51].sX = x + 104; gMapScreenInvPocketXY[51].sY = y + 444; gMapScreenInvPocketXY[52].sX = x + 171; gMapScreenInvPocketXY[52].sY = y + 444; } return ( TRUE ); } BOOLEAN InitializeInvPanelCoordsRobot() { InitializeInvPanelCoordsNew(); const auto x = UI_CHARINV.Region.x; const auto y = UI_CHARINV.Region.y; // Inventory slots if (iResolution >= _640x480 && iResolution < _800x600) { // NIV is not usable at 640x480, so nothing happens } else { gMapScreenInvPocketXY[HANDPOS].sX = x + 21; gMapScreenInvPocketXY[HANDPOS].sY = y + 150; gMapScreenInvPocketXY[14].sX = x + 146; gMapScreenInvPocketXY[14].sY = y + 150; gMapScreenInvPocketXY[15].sX = x + 21; gMapScreenInvPocketXY[15].sY = y + 200; gMapScreenInvPocketXY[16].sX = x + 21; gMapScreenInvPocketXY[16].sY = y + 250; gMapScreenInvPocketXY[17].sX = x + 21; gMapScreenInvPocketXY[17].sY = y + 300; gMapScreenInvPocketXY[18].sX = x + 21; gMapScreenInvPocketXY[18].sY = y + 350; } return TRUE; } // the tries to select a mapscreen character by his soldier ID BOOLEAN SetInfoChar( SoldierID ubID ) { for (INT16 bCounter = 0; bCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; bCounter++) { // skip invalid characters if ( gCharactersList[ bCounter ].fValid == TRUE ) { if ( gCharactersList[ bCounter ].usSolID == ubID ) { ChangeSelectedInfoChar( bCounter, TRUE ); return( TRUE ); } } } return ( FALSE ); } void ContractBoxGlow( void ) { /* Why not? static INT32 iColorNum=10; static BOOLEAN fDelta=FALSE; static BOOLEAN fOldContractGlow = FALSE; UINT16 usColor; UINT32 uiDestPitchBYTES; UINT8 *pDestBuf; // stopped glowing? if( ( fGlowContractRegion == FALSE )&&( ( fOldContractGlow == TRUE )||( fResetContractGlow== TRUE ) ) ) { // restore background // RestoreExternBackgroundRect( CONTRACT_X, CONTRACT_Y, CONTRACT_WIDTH+1, CONTRACT_HEIGHT+1 ); // reset old fOldContractGlow = FALSE; } // not glowing right now, leave if( ( fGlowContractRegion == FALSE )||( fResetContractGlow == TRUE ) ) { // reset color rotation iColorNum =0; fDelta = TRUE; // reset fResetContractGlow = FALSE; return; } // if not ready to change glow phase yet, leave if ( !gfGlowTimerExpired ) return; // change direction of glow? if((iColorNum==0)||(iColorNum==10)) { fDelta=!fDelta; } // increment color if(!fDelta) iColorNum++; else iColorNum--; usColor=Get16BPPColor( FROMRGB( GlowColorsA[iColorNum].ubRed, GlowColorsA[iColorNum].ubGreen, GlowColorsA[iColorNum].ubBlue ) ); pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES ); SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, 640, 480); RectangleDraw( TRUE, CONTRACT_X, CONTRACT_Y, CONTRACT_X+CONTRACT_WIDTH, CONTRACT_Y+CONTRACT_HEIGHT, usColor, pDestBuf ); InvalidateRegion(CONTRACT_X, CONTRACT_Y, CONTRACT_X+CONTRACT_WIDTH+1, CONTRACT_Y+CONTRACT_HEIGHT+1); UnLockVideoSurface( FRAME_BUFFER ); // restore background if((iColorNum==0)||(iColorNum==1)) RestoreExternBackgroundRect( CONTRACT_X, CONTRACT_Y, CONTRACT_WIDTH+1, CONTRACT_HEIGHT+1 ); */ } void ContractListRegionBoxGlow( UINT16 usCount ) { static INT32 iColorNum =10; static BOOLEAN fDelta=FALSE; UINT16 usColor; UINT32 uiDestPitchBYTES; UINT8 *pDestBuf; INT16 usY = 0; INT16 sYAdd = 0; // if not glowing right now, leave if( ( giContractHighLine == -1 )||( fResetContractGlow == TRUE ) || fShowInventoryFlag ) { iColorNum = 0; fDelta = TRUE; return; } // if not ready to change glow phase yet, leave if ( !gfGlowTimerExpired ) return; // change direction of glow? if((iColorNum==0)||(iColorNum==10)) { fDelta=!fDelta; } // increment color if(!fDelta) iColorNum++; else iColorNum--; sYAdd = 0; // y start position of box usY = ( UI_CHARLIST.yOffset * usCount - 1 ) + (UI_CHARLIST.y + (usCount * Y_SIZE) + sYAdd ); // glow contract box usColor=Get16BPPColor( FROMRGB( GlowColorsA[iColorNum].ubRed, GlowColorsA[iColorNum].ubGreen, GlowColorsA[iColorNum].ubBlue ) ); pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES ); SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); const auto x = UI_CHARLIST.xTimeRemaining; const auto width = UI_CHARLIST.widthTimeRemaining; RectangleDraw( TRUE, x, usY, x + width, usY + GetFontHeight( MAP_SCREEN_FONT ) + 2, usColor, pDestBuf ); InvalidateRegion(x - 1, usY, x + width + 1, usY + GetFontHeight( MAP_SCREEN_FONT ) + 3 ); UnLockVideoSurface( FRAME_BUFFER ); } void GlowFace( void ) { static INT32 iColorNum =10; static BOOLEAN fDelta=FALSE; static BOOLEAN fOldFaceGlow = FALSE; const auto xStart = UI_CHARPANEL.FacePicture.x; const auto yStart = UI_CHARPANEL.FacePicture.y; const auto xEnd = UI_CHARPANEL.FacePicture.x + UI_CHARPANEL.FacePicture.width; const auto yEnd = UI_CHARPANEL.FacePicture.y + UI_CHARPANEL.FacePicture.height; const auto Width = UI_CHARPANEL.FacePicture.width; const auto Height = UI_CHARPANEL.FacePicture.height; // not glowing right now, leave if( fShowFaceHightLight == FALSE ) { iColorNum =0; fDelta = TRUE; if( fOldFaceGlow == TRUE ) { RestoreExternBackgroundRect(xStart, yStart, Width + 1, Height + 1); } fOldFaceGlow = FALSE; return; } // if not ready to change glow phase yet, leave if ( !gfGlowTimerExpired ) return; fOldFaceGlow = TRUE; // change direction of glow? if((iColorNum==0)||(iColorNum==10)) { fDelta=!fDelta; } // increment color if(!fDelta) iColorNum++; else iColorNum--; // glow contract box UINT16 usColor=Get16BPPColor( FROMRGB( GlowColorsA[iColorNum].ubRed, GlowColorsA[iColorNum].ubGreen, GlowColorsA[iColorNum].ubBlue ) ); UINT32 uiDestPitchBYTES; UINT8 *pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES ); SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); RectangleDraw( TRUE, xStart, yStart, xEnd, yEnd, usColor, pDestBuf ); InvalidateRegion(xStart, yStart, xEnd + 1 , yEnd + 1 ); UnLockVideoSurface( FRAME_BUFFER ); // restore background if((iColorNum==0)||(iColorNum==1)) RestoreExternBackgroundRect(xStart, yStart, Width + 1, Height + 1); } // Draws the pulsating red rectangle around the character panel inventory slot void GlowItem( void ) { static INT32 iColorNum =10; static BOOLEAN fDelta=FALSE; static BOOLEAN fOldItemGlow = FALSE; UINT16 usColor; UINT32 uiDestPitchBYTES; UINT8 *pDestBuf; // not glowing right now, leave if( fShowItemHighLight == FALSE ) { iColorNum =0; fDelta = TRUE; if( fOldItemGlow == TRUE ) { // this caused the attachment/burst/grenade star to disappear behind the item image //RestoreExternBackgroundRect( 3, 80, ( UINT16 )( 65 - 3 ), ( UINT16 )( 105 - 80 ) ); } fOldItemGlow = FALSE; return; } // if not ready to change glow phase yet, leave if ( !gfGlowTimerExpired ) return; fOldItemGlow = TRUE; // change direction of glow? if((iColorNum==0)||(iColorNum==10)) { fDelta=!fDelta; } // increment color if(!fDelta) iColorNum++; else iColorNum--; // restore background const auto x = UI_CHARPANEL.HandItem.x; const auto y = UI_CHARPANEL.HandItem.y; const auto width = UI_CHARPANEL.HandItem.width; const auto height = UI_CHARPANEL.HandItem.height; if((iColorNum==0)||(iColorNum==1)) { RestoreExternBackgroundRect(x, y, width + 1, height + 1 ); RenderHandPosItem(); } usColor=Get16BPPColor( FROMRGB( GlowColorsA[iColorNum].ubRed, GlowColorsA[iColorNum].ubGreen, GlowColorsA[iColorNum].ubBlue ) ); pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES ); SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); const auto xEnd = x + width; const auto yEnd = y + height; RectangleDraw( TRUE, x, y, xEnd, yEnd, usColor, pDestBuf ); InvalidateRegion(x, y, xEnd + 1, yEnd + 1); UnLockVideoSurface( FRAME_BUFFER ); } void GlowTrashCan( void ) { static INT32 iColorNum =10; static BOOLEAN fDelta=FALSE; static BOOLEAN fOldTrashCanGlow = FALSE; const auto x = UI_CHARINV.Button.Trashcan.x; const auto y = UI_CHARINV.Button.Trashcan.y; const auto width = UI_CHARINV.Button.Trashcan.width; const auto height = UI_CHARINV.Button.Trashcan.height; if( fShowInventoryFlag == FALSE ) { fShowTrashCanHighLight = FALSE; } // not glowing right now, leave if( fShowTrashCanHighLight == FALSE ) { iColorNum =0; fDelta = TRUE; if( fOldTrashCanGlow == TRUE ) { RestoreExternBackgroundRect(x, y, ( UINT16 )(width + 2 ), ( UINT16 )(height + 2 ) ); } fOldTrashCanGlow = FALSE; return; } // if not ready to change glow phase yet, leave if ( !gfGlowTimerExpired ) return; fOldTrashCanGlow = TRUE; // glow contract box UINT16 usColor=Get16BPPColor( FROMRGB( GlowColorsA[iColorNum].ubRed, GlowColorsA[iColorNum].ubGreen, GlowColorsA[iColorNum].ubBlue ) ); UINT32 uiDestPitchBYTES; UINT8* pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES ); SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); RectangleDraw( TRUE, x, y, x + width, y + height, usColor, pDestBuf ); InvalidateRegion( x, y, x + width + 1, y + height + 1 ); UnLockVideoSurface( FRAME_BUFFER ); // restore background if((iColorNum==0)||(iColorNum==1)) RestoreExternBackgroundRect( x, y, ( UINT16 )( width + 2 ), ( UINT16 )( height + 2 ) ); } void DrawFace( INT16 sCharNumber ) { SOLDIERTYPE *pSoldier = NULL; static SoldierID sOldId = NOBODY; // draws the face of the currently selected merc, being displayed int he upper left hand corner // grab the soldier if( bSelectedInfoChar != -1 ) { if( gCharactersList[ bSelectedInfoChar ].fValid ) { GetSoldier( &pSoldier, gCharactersList[ bSelectedInfoChar ].usSolID ); } } if( pSoldier == NULL ) { return; } if( ( gCharactersList[ bSelectedInfoChar ].usSolID == sOldId )&&( fReDrawFace == FALSE ) ) { // are the same, return return; } // get old id value sOldId = gCharactersList[ bSelectedInfoChar ].usSolID; // reset redraw of face fReDrawFace = FALSE; // render their face RenderSoldierFace( pSoldier, UI_CHARPANEL.FacePicture.x, UI_CHARPANEL.FacePicture.y, TRUE ); return; } void RenderHandPosItem( void ) { SOLDIERTYPE *pSoldier = NULL; // renders the inventory item in char's right hand // ARM: if already in the inventory panel, don't show the item again here, seeing it twice is confusing. Same for widescreen UI, where the inventory panel is always visible. if ( fShowInventoryFlag || isWidescreenUI()) { return; } // grab the soldier if( bSelectedInfoChar != -1 ) { if( gCharactersList[ bSelectedInfoChar ].fValid ) { GetSoldier( &pSoldier, gCharactersList[ bSelectedInfoChar ].usSolID ); } } if( pSoldier == NULL ) { return; } // check if still alive? if( pSoldier->stats.bLife == 0 ) { return; } SetFont(BLOCKFONT2); SetFontForeground(CHAR_INFO_PANEL_BLOCK_COLOR); SetFontBackground(FONT_BLACK); INVRenderItem( guiSAVEBUFFER, pSoldier, &(pSoldier->inv[HANDPOS]), UI_CHARPANEL.HandItem.x, UI_CHARPANEL.HandItem.y, 58, 23, DIRTYLEVEL2, NULL, 0, FALSE, 0); } void RenderIconsForUpperLeftCornerPiece( INT8 bCharNumber ) { const auto x = UI_CHARPANEL.Icon.x; const auto y = UI_CHARPANEL.Icon.y; const auto height = UI_CHARPANEL.Icon.height; const auto spacing = UI_CHARPANEL.Icon.spacing; HVOBJECT hHandle; GetVideoObject(&hHandle, guiULICONS); // if merc is an AIM merc if( gCharactersList[ bCharNumber ].usSolID->ubWhatKindOfMercAmI == MERC_TYPE__AIM_MERC ) { // finite contract length icon BltVideoObject( guiSAVEBUFFER, hHandle, 0, x, y, VO_BLT_SRCTRANSPARENCY, NULL ); } // if merc has life insurance if( gCharactersList[ bCharNumber ].usSolID->usLifeInsurance > 0 ) { // draw life insurance icon BltVideoObject( guiSAVEBUFFER, hHandle, 2, x, y + spacing, VO_BLT_SRCTRANSPARENCY, NULL ); } // if merc has a medical deposit if( gCharactersList[ bCharNumber ].usSolID->usMedicalDeposit > 0 ) { // draw medical deposit icon BltVideoObject( guiSAVEBUFFER, hHandle, 1, x, y + ( 2 * spacing), VO_BLT_SRCTRANSPARENCY, NULL ); } } void DrawPay(INT16 sCharNumber) { // will draw the pay INT32 uiSalary; CHAR16 sString[7]; INT16 usX, usY; UINT8 usMercProfileID; // get merc id usMercProfileID = gCharactersList[ sCharNumber ].usSolID->ubProfile; // grab salary uiSalary=( ( UINT32 ) gMercProfiles[ usMercProfileID ].sSalary ); // font stuff SetFontForeground( CHAR_TITLE_FONT_COLOR ); SetFontBackground( FONT_BLACK ); // parse salary swprintf( sString, L"%d", uiSalary ); // right justify salary const auto x = UI_CHARPANEL.Text.Pay.x; const auto y = UI_CHARPANEL.Text.Pay.y; const auto w = UI_CHARPANEL.Text.Pay.width; const auto h = UI_CHARPANEL.Text.Pay.height; FindFontRightCoordinates(x, y, w, h, sString, CHAR_FONT, &usX, &usY); // draw salary DrawString(sString,usX, usY, CHAR_FONT); } void DrawCharBars( void ) { SoldierID usSoldierID; SOLDIERTYPE *pSoldier; // will draw the heath, morale and breath bars for a character being displayed in the upper left hand corner if ( ( bSelectedInfoChar == -1 ) && ( GetSelectedDestChar() == -1 ) ) { // error, no character to display right now return; } else { // valid character if( bSelectedInfoChar != -1 ) { usSoldierID = gCharactersList[ bSelectedInfoChar ].usSolID; } else { usSoldierID = gCharactersList[GetSelectedDestChar()].usSolID; } // grab soldier's id number GetSoldier( &pSoldier, usSoldierID ); if( pSoldier == NULL ) { // no soldier return; } // skip POWs, dead guys, mini events if( ( pSoldier->stats.bLife == 0 ) || ( pSoldier->bAssignment == ASSIGNMENT_DEAD ) || ( pSoldier->bAssignment == ASSIGNMENT_POW ) || ( pSoldier->bAssignment == ASSIGNMENT_MINIEVENT ) || ( pSoldier->bAssignment == ASSIGNMENT_REBELCOMMAND ) ) { return; } // current health DrawLifeUIBarEx( pSoldier, UI_CHARPANEL.Statusbars.x, UI_CHARPANEL.Statusbars.y, 3, 42, TRUE, FRAME_BUFFER ); // robot doesn't have energy/fuel if ( !AM_A_ROBOT( pSoldier ) ) { // current energy/fuel DrawBreathUIBarEx( pSoldier, UI_CHARPANEL.Statusbars.x + UI_CHARPANEL.Statusbars.offset, UI_CHARPANEL.Statusbars.y, 3,42, TRUE, FRAME_BUFFER ); } // vehicles and robot don't have morale if ( !( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) && !AM_A_ROBOT( pSoldier ) ) { // draw morale bar DrawMoraleUIBarEx( pSoldier, UI_CHARPANEL.Statusbars.x + UI_CHARPANEL.Statusbars.offset*2, UI_CHARPANEL.Statusbars.y, 3,42, TRUE, FRAME_BUFFER ); } } return; } void DrawCharStats( INT16 sCharNum ) { // will draw the characters stats, max life, strength, dex, and skills CHAR16 sString[9]; INT16 usX, usY; //HVOBJECT hCrossHandle; SOLDIERTYPE *pSoldier = NULL; pSoldier = gCharactersList[sCharNum].usSolID; // set up font SetFont(CHAR_FONT); SetFontForeground(CHAR_TEXT_FONT_COLOR); SetFontBackground(FONT_BLACK); // strength swprintf( sString, L"%d", pSoldier->stats.bStrength + pSoldier->bExtraStrength ); // SANDRO - if damaged stat we could regain, show in red until repaired if ( ( gGameOptions.fNewTraitSystem && ( pSoldier->ubCriticalStatDamage[DAMAGED_STAT_STRENGTH] > 0 )) || ( UsingFoodSystem() && pSoldier->usStarveDamageStrength > 0) ) { SetFontForeground( FONT_RED ); } else if( ( GetJA2Clock() < CHANGE_STAT_RECENTLY_DURATION + pSoldier->timeChanges.uiChangeStrengthTime)&& ( pSoldier->timeChanges.uiChangeStrengthTime != 0 ) ) { if( pSoldier->usValueGoneUp & STRENGTH_INCREASE ) { SetFontForeground( FONT_LTGREEN ); } else { SetFontForeground( FONT_RED ); } } else if ( pSoldier->bExtraStrength ) { SetRGBFontForeground( 250, 5, 250 ); } else { SetFontForeground(CHAR_TEXT_FONT_COLOR); } // right justify FindFontRightCoordinates( UI_CHARPANEL.Attr.STR.iX, UI_CHARPANEL.Attr.STR.iY, UI_CHARPANEL.Attr.width, UI_CHARPANEL.Attr.height, sString, CHAR_FONT, &usX, &usY ); DrawString(sString,usX, UI_CHARPANEL.Attr.STR.iY,CHAR_FONT ); // dexterity swprintf( sString, L"%d", pSoldier->stats.bDexterity + pSoldier->bExtraDexterity ); // SANDRO - if damaged stat we could regain, show in red until repaired if( gGameOptions.fNewTraitSystem && ( pSoldier->ubCriticalStatDamage[DAMAGED_STAT_DEXTERITY] > 0 )) { SetFontForeground( FONT_RED ); } else if( ( GetJA2Clock() < CHANGE_STAT_RECENTLY_DURATION + pSoldier->timeChanges.uiChangeDexterityTime ) && ( pSoldier->timeChanges.uiChangeDexterityTime != 0 ) ) { if( pSoldier->usValueGoneUp & DEX_INCREASE ) { SetFontForeground( FONT_LTGREEN ); } else { SetFontForeground( FONT_RED ); } } else if ( pSoldier->bExtraDexterity ) { SetRGBFontForeground( 250, 5, 250 ); } else { SetFontForeground(CHAR_TEXT_FONT_COLOR); } // right justify FindFontRightCoordinates( UI_CHARPANEL.Attr.DEX.iX, UI_CHARPANEL.Attr.DEX.iY, UI_CHARPANEL.Attr.width, UI_CHARPANEL.Attr.height, sString , CHAR_FONT, &usX, &usY ); DrawString(sString,usX, UI_CHARPANEL.Attr.DEX.iY,CHAR_FONT ); // agility swprintf( sString, L"%d", pSoldier->stats.bAgility + pSoldier->bExtraAgility ); // SANDRO - if damaged stat we could regain, show in red until repaired if( gGameOptions.fNewTraitSystem && ( pSoldier->ubCriticalStatDamage[DAMAGED_STAT_AGILITY] > 0 )) { SetFontForeground( FONT_RED ); } else if( ( GetJA2Clock() < CHANGE_STAT_RECENTLY_DURATION + pSoldier->timeChanges.uiChangeAgilityTime)&& ( pSoldier->timeChanges.uiChangeAgilityTime != 0 ) ) { if( pSoldier->usValueGoneUp & AGIL_INCREASE ) { SetFontForeground( FONT_LTGREEN ); } else { SetFontForeground( FONT_RED ); } } else if ( pSoldier->bExtraAgility ) { SetRGBFontForeground( 250, 5, 250 ); } else { SetFontForeground(CHAR_TEXT_FONT_COLOR); } // right justify FindFontRightCoordinates( UI_CHARPANEL.Attr.AGL.iX, UI_CHARPANEL.Attr.AGL.iY, UI_CHARPANEL.Attr.width, UI_CHARPANEL.Attr.height, sString , CHAR_FONT, &usX, &usY ); DrawString(sString,usX, UI_CHARPANEL.Attr.AGL.iY,CHAR_FONT ); // wisdom swprintf( sString, L"%d", pSoldier->stats.bWisdom + pSoldier->bExtraWisdom ); // SANDRO - if damaged stat we could regain, show in red until repaired if( gGameOptions.fNewTraitSystem && ( pSoldier->ubCriticalStatDamage[DAMAGED_STAT_WISDOM] > 0 )) { SetFontForeground( FONT_RED ); } else if( ( GetJA2Clock() < CHANGE_STAT_RECENTLY_DURATION + pSoldier->timeChanges.uiChangeWisdomTime )&&( pSoldier->timeChanges.uiChangeWisdomTime != 0 )) { if( pSoldier->usValueGoneUp & WIS_INCREASE ) { SetFontForeground( FONT_LTGREEN ); } else { SetFontForeground( FONT_RED ); } } else if ( pSoldier->bExtraWisdom ) { SetRGBFontForeground( 250, 5, 250 ); } else { SetFontForeground(CHAR_TEXT_FONT_COLOR); } // right justify FindFontRightCoordinates( UI_CHARPANEL.Attr.WIS.iX, UI_CHARPANEL.Attr.WIS.iY, UI_CHARPANEL.Attr.width, UI_CHARPANEL.Attr.height, sString , CHAR_FONT, &usX, &usY ); DrawString(sString,usX, UI_CHARPANEL.Attr.WIS.iY,CHAR_FONT ); // leadership swprintf( sString, L"%d", pSoldier->stats.bLeadership ); // SANDRO - if damaged stat we could regain, show in red until repaired if( gGameOptions.fNewTraitSystem && ( pSoldier->ubCriticalStatDamage[DAMAGED_STAT_LEADERSHIP] > 0 )) { SetFontForeground( FONT_RED ); } else if( ( GetJA2Clock() < CHANGE_STAT_RECENTLY_DURATION + pSoldier->timeChanges.uiChangeLeadershipTime ) && ( pSoldier->timeChanges.uiChangeLeadershipTime != 0 ) ) { if( pSoldier->usValueGoneUp & LDR_INCREASE ) { SetFontForeground( FONT_LTGREEN ); } else { SetFontForeground( FONT_RED ); } } else { SetFontForeground(CHAR_TEXT_FONT_COLOR); } // right justify FindFontRightCoordinates( UI_CHARPANEL.Attr.LDR.iX, UI_CHARPANEL.Attr.LDR.iY, UI_CHARPANEL.Attr.width, UI_CHARPANEL.Attr.height, sString , CHAR_FONT, &usX, &usY ); DrawString(sString,usX, UI_CHARPANEL.Attr.LDR.iY,CHAR_FONT ); // experience level swprintf( sString, L"%d", pSoldier->stats.bExpLevel + pSoldier->bExtraExpLevel ); if( ( GetJA2Clock() < CHANGE_STAT_RECENTLY_DURATION + pSoldier->timeChanges.uiChangeLevelTime)&&( pSoldier->timeChanges.uiChangeLevelTime != 0 ) ) { if( pSoldier->usValueGoneUp & LVL_INCREASE ) { SetFontForeground( FONT_LTGREEN ); } else { SetFontForeground( FONT_RED ); } } else if ( pSoldier->bExtraExpLevel ) { SetRGBFontForeground( 250, 5, 250 ); } else { SetFontForeground(CHAR_TEXT_FONT_COLOR); } // right justify FindFontRightCoordinates( UI_CHARPANEL.Attr.LVL.iX, UI_CHARPANEL.Attr.LVL.iY, UI_CHARPANEL.Attr.width, UI_CHARPANEL.Attr.height, sString , CHAR_FONT, &usX, &usY ); DrawString(sString,usX, UI_CHARPANEL.Attr.LVL.iY,CHAR_FONT ); // marksmanship swprintf( sString, L"%d", pSoldier->stats.bMarksmanship ); // SANDRO - if damaged stat we could regain, show in red until repaired if( gGameOptions.fNewTraitSystem && ( pSoldier->ubCriticalStatDamage[DAMAGED_STAT_MARKSMANSHIP] > 0 )) { SetFontForeground( FONT_RED ); } else if( ( GetJA2Clock() < CHANGE_STAT_RECENTLY_DURATION + pSoldier->timeChanges.uiChangeMarksmanshipTime) && ( pSoldier->timeChanges.uiChangeMarksmanshipTime != 0 ) ) { if( pSoldier->usValueGoneUp & MRK_INCREASE ) { SetFontForeground( FONT_LTGREEN ); } else { SetFontForeground( FONT_RED ); } } else { SetFontForeground(CHAR_TEXT_FONT_COLOR); } // right justify FindFontRightCoordinates( UI_CHARPANEL.Attr.MRK.iX, UI_CHARPANEL.Attr.MRK.iY, UI_CHARPANEL.Attr.width, UI_CHARPANEL.Attr.height, sString , CHAR_FONT, &usX, &usY ); DrawString(sString,usX, UI_CHARPANEL.Attr.MRK.iY,CHAR_FONT ); // mechanical swprintf( sString, L"%d", pSoldier->stats.bMechanical ); // SANDRO - if damaged stat we could regain, show in red until repaired if( gGameOptions.fNewTraitSystem && ( pSoldier->ubCriticalStatDamage[DAMAGED_STAT_MECHANICAL] > 0 )) { SetFontForeground( FONT_RED ); } else if( ( GetJA2Clock() < CHANGE_STAT_RECENTLY_DURATION + pSoldier->timeChanges.uiChangeMechanicalTime )&& ( pSoldier->timeChanges.uiChangeMechanicalTime != 0 ) ) { if( pSoldier->usValueGoneUp & MECH_INCREASE ) { SetFontForeground( FONT_LTGREEN ); } else { SetFontForeground( FONT_RED ); } } else { SetFontForeground(CHAR_TEXT_FONT_COLOR); } // right justify FindFontRightCoordinates( UI_CHARPANEL.Attr.MEC.iX, UI_CHARPANEL.Attr.MEC.iY, UI_CHARPANEL.Attr.width, UI_CHARPANEL.Attr.height, sString , CHAR_FONT, &usX, &usY ); DrawString(sString,usX, UI_CHARPANEL.Attr.MEC.iY,CHAR_FONT ); // explosives swprintf( sString, L"%d", pSoldier->stats.bExplosive ); // SANDRO - if damaged stat we could regain, show in red until repaired if( gGameOptions.fNewTraitSystem && ( pSoldier->ubCriticalStatDamage[DAMAGED_STAT_EXPLOSIVES] > 0 )) { SetFontForeground( FONT_RED ); } else if( ( GetJA2Clock() < CHANGE_STAT_RECENTLY_DURATION + pSoldier->timeChanges.uiChangeExplosivesTime)&& ( pSoldier->timeChanges.uiChangeExplosivesTime != 0 ) ) { if( pSoldier->usValueGoneUp & EXP_INCREASE ) { SetFontForeground( FONT_LTGREEN ); } else { SetFontForeground( FONT_RED ); } } else { SetFontForeground(CHAR_TEXT_FONT_COLOR); } // right justify FindFontRightCoordinates( UI_CHARPANEL.Attr.EXP.iX, UI_CHARPANEL.Attr.EXP.iY, UI_CHARPANEL.Attr.width, UI_CHARPANEL.Attr.height, sString , CHAR_FONT, &usX, &usY ); DrawString(sString,usX, UI_CHARPANEL.Attr.EXP.iY,CHAR_FONT ); // medical swprintf( sString, L"%d", pSoldier->stats.bMedical ); // SANDRO - if damaged stat we could regain, show in red until repaired if( gGameOptions.fNewTraitSystem && ( pSoldier->ubCriticalStatDamage[DAMAGED_STAT_MEDICAL] > 0 )) { SetFontForeground( FONT_RED ); } else if( ( GetJA2Clock() < CHANGE_STAT_RECENTLY_DURATION + pSoldier->timeChanges.uiChangeMedicalTime)&& ( pSoldier->timeChanges.uiChangeMedicalTime != 0 ) ) { if( pSoldier->usValueGoneUp & MED_INCREASE ) { SetFontForeground( FONT_LTGREEN ); } else { SetFontForeground( FONT_RED ); } } else { SetFontForeground(CHAR_TEXT_FONT_COLOR); } // right justify FindFontRightCoordinates( UI_CHARPANEL.Attr.MED.iX, UI_CHARPANEL.Attr.MED.iY, UI_CHARPANEL.Attr.width, UI_CHARPANEL.Attr.height, sString , CHAR_FONT, &usX, &usY ); DrawString(sString, usX, UI_CHARPANEL.Attr.MED.iY, CHAR_FONT ); SetFontForeground(CHAR_TEXT_FONT_COLOR); return; } void DrawCharHealth( INT16 sCharNum ) { UINT32 uiHealthPercent = 0; CHAR16 sString[9]; INT16 usX, usY; SOLDIERTYPE *pSoldier = NULL; const auto x = UI_CHARPANEL.Text.CurrentHitpoints.x; const auto y = UI_CHARPANEL.Text.CurrentHitpoints.y; const auto width = UI_CHARPANEL.Text.CurrentHitpoints.width; const auto height = UI_CHARPANEL.Text.CurrentHitpoints.height; pSoldier = gCharactersList[sCharNum].usSolID; if( pSoldier->bAssignment != ASSIGNMENT_POW && pSoldier->bAssignment != ASSIGNMENT_MINIEVENT && pSoldier->bAssignment != ASSIGNMENT_REBELCOMMAND ) { // find starting X coordinate by centering all 3 substrings together, then print them separately (different colors)! swprintf( sString, L"%d/%d", pSoldier->stats.bLife, pSoldier->stats.bLifeMax ); FindFontCenterCoordinates(x, y, width, height, sString, CHAR_FONT, &usX, &usY); if ( pSoldier->stats.bLifeMax > 0 ) { uiHealthPercent = ( pSoldier->stats.bLife * 100 ) / pSoldier->stats.bLifeMax; } // how is characters life? if (uiHealthPercent == 0) { // he's dead, Jim SetFontForeground(FONT_METALGRAY); } else if (uiHealthPercent < 25) { // very bad SetFontForeground(FONT_RED); } else if (uiHealthPercent < 50) { // not good SetFontForeground(FONT_YELLOW); } else { // ok SetFontForeground(CHAR_TEXT_FONT_COLOR); } // current life swprintf( sString, L"%d", pSoldier->stats.bLife ); DrawString( sString, usX, y, CHAR_FONT ); usX += StringPixLength( sString, CHAR_FONT ); // slash SetFontForeground(CHAR_TEXT_FONT_COLOR); wcscpy( sString, L"/" ); DrawString( sString, usX, y, CHAR_FONT ); usX += StringPixLength( sString, CHAR_FONT ); if (gGameOptions.fNewTraitSystem && pSoldier->ubCriticalStatDamage[DAMAGED_STAT_HEALTH] > 0) { SetFontForeground(FONT_RED); } else if( ( GetJA2Clock() < CHANGE_STAT_RECENTLY_DURATION + pSoldier->timeChanges.uiChangeHealthTime)&& ( pSoldier->timeChanges.uiChangeHealthTime != 0 ) ) { if( pSoldier->usValueGoneUp & HEALTH_INCREASE ) { SetFontForeground( FONT_LTGREEN ); } else { SetFontForeground( FONT_RED ); } } else { SetFontForeground(CHAR_TEXT_FONT_COLOR); } // maximum life swprintf( sString, L"%d", pSoldier->stats.bLifeMax ); DrawString( sString, usX, y, CHAR_FONT ); } else { // POW - health unknown SetFontForeground(CHAR_TEXT_FONT_COLOR); swprintf( sString, pPOWStrings[ 1 ] ); FindFontCenterCoordinates(x, y, width, height, sString, CHAR_FONT, &usX, &usY); DrawString(sString, usX, y, CHAR_FONT); } SetFontForeground(CHAR_TEXT_FONT_COLOR); } CHAR16* GetRankTitle(INT8 explevel) { if (explevel < 1) explevel = 0; if (explevel > 10) explevel = 10; return ranks[explevel]; } // "character" refers to hired people AND vehicles void DrawCharacterInfo(INT16 sCharNumber) { CHAR16 sString[80]; INT16 usX, usY; INT16 usMercProfileID; INT32 iTimeRemaining=0; INT32 iDailyCost = 0; SOLDIERTYPE *pSoldier = NULL; UINT32 uiArrivalTime; if( gCharactersList[sCharNumber].fValid == FALSE ) { return; } pSoldier = gCharactersList[sCharNumber].usSolID; if( pSoldier->ubProfile == NO_PROFILE ) { return; } // draw particular info about a character that are neither attributes nor skills // get profile information usMercProfileID = pSoldier->ubProfile; // set font stuff SetFont(CHAR_FONT); SetFontForeground(CHAR_TEXT_FONT_COLOR); SetFontBackground(FONT_BLACK); // Nickname (beneath Picture) if( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) { // vehicle // wcscpy(sString, pShortVehicleStrings[ pVehicleList[ pSoldier->bVehicleID ].ubVehicleType ]); wcscpy(sString, gNewVehicle[ pVehicleList[ pSoldier->bVehicleID ].ubVehicleType ].NewShortVehicleStrings); } else { // soldier wcscpy(sString, gMercProfiles[usMercProfileID].zNickname); } FindFontCenterCoordinates(UI_CHARPANEL.NickName.x, UI_CHARPANEL.NickName.y, UI_CHARPANEL.NickName.width, UI_CHARPANEL.NickName.height, sString, CHAR_FONT, &usX, &usY); DrawString(sString, usX, usY, CHAR_FONT); // Full name (Top Box) if( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) { // vehicle //wcscpy(sString, pVehicleStrings[ pVehicleList[ pSoldier->bVehicleID ].ubVehicleType ]); wcscpy(sString, gNewVehicle[ pVehicleList[ pSoldier->bVehicleID ].ubVehicleType ].NewVehicleStrings); } else { // soldier //Jenilee: this works if (!gGameSettings.fOptions[TOPTION_SHOW_MERC_RANKS]) { wcscpy(sString, gMercProfiles[usMercProfileID].zName); } else { swprintf(sString, L"%s%s", GetRankTitle(pSoldier->stats.bExpLevel), gMercProfiles[usMercProfileID].zName); } } FindFontCenterCoordinates(UI_CHARPANEL.FullName.x, UI_CHARPANEL.FullName.y, UI_CHARPANEL.FullName.width, UI_CHARPANEL.FullName.height, sString, CHAR_FONT, &usX, &usY); DrawString(sString, usX, usY, CHAR_FONT); // Assignment if( pSoldier->bAssignment == VEHICLE ) { // show vehicle type // wcscpy( sString, pShortVehicleStrings[ pVehicleList[ pSoldier->iVehicleId ].ubVehicleType ] ); wcscpy( sString, gNewVehicle[ pVehicleList[ pSoldier->iVehicleId ].ubVehicleType ].NewShortVehicleStrings ); } else { if ( gGameExternalOptions.fUseXMLSquadNames && pSoldier->bAssignment < min(ON_DUTY, gSquadNameVector.size()) ) swprintf( sString, L"%s", gSquadNameVector[pSoldier->bAssignment].c_str() ); else wcscpy( sString, pAssignmentStrings[ pSoldier->bAssignment ] ); } { const auto x = UI_CHARPANEL.Text.CurrentAssignment.x; const auto y = UI_CHARPANEL.Text.CurrentAssignment.y; const auto w = UI_CHARPANEL.Text.CurrentAssignment.width; const auto h = UI_CHARPANEL.Text.CurrentAssignment.height; FindFontCenterCoordinates(x, y, w, h, sString, CHAR_FONT, &usX, &usY); DrawString(sString, usX, usY, CHAR_FONT); } // second assignment line // HEADROCK HAM 3.6: Operating a facility? if (pSoldier->sFacilityTypeOperated != -1) { UINT8 ubFacilityType = (UINT8)pSoldier->sFacilityTypeOperated; // Print sector ID string GetShortSectorString( pSoldier->sSectorX, pSoldier->sSectorY, sString ); wcscat( sString, L": " ); wcscat( sString, gFacilityTypes[ubFacilityType].szFacilityShortName ); //wcscpy(sString, gFacilityTypes[ pSoldier->sFacilityTypeOperated ].szFacilityName); } // train self / teammate / by other ? else if( ( pSoldier->bAssignment == TRAIN_SELF ) || ( pSoldier->bAssignment == TRAIN_TEAMMATE ) || ( pSoldier->bAssignment == TRAIN_BY_OTHER ) ) { wcscpy(sString, pAttributeMenuStrings[pSoldier->bTrainStat]); } // train town? else if( pSoldier->bAssignment == TRAIN_TOWN ) { wcscpy(sString,pTownNames[GetTownIdForSector( pSoldier->sSectorX, pSoldier->sSectorY ) ] ); } // repairing? else if( pSoldier->bAssignment == REPAIR ) { if ( pSoldier->flags.fFixingRobot ) { // robot wcscpy( sString, pRepairStrings[ 3 ] ); } else if ( pSoldier->flags.fFixingSAMSite ) { // SAM site wcscpy( sString, pRepairStrings[ 1 ] ); } else if ( pSoldier->bVehicleUnderRepairID != -1 ) { // vehicle // wcscpy( sString, pShortVehicleStrings[ pVehicleList[ pSoldier->bVehicleUnderRepairID ].ubVehicleType ] ); wcscpy( sString, gNewVehicle[ pVehicleList[ pSoldier->bVehicleUnderRepairID ].ubVehicleType ].NewShortVehicleStrings ); } else { // items wcscpy( sString, pRepairStrings[ 0 ] ); } } // in transit? else if( pSoldier->bAssignment == IN_TRANSIT ) { // show ETA ConvertMinTimeToETADayHourMinString( pSoldier->uiTimeSoldierWillArrive, sString ); } // traveling ? else if ( PlayerIDGroupInMotion( GetSoldierGroupId( pSoldier ) ) ) { // show ETA uiArrivalTime = GetWorldTotalMin( ) + CalculateTravelTimeOfGroupId( GetSoldierGroupId( pSoldier ) ); ConvertMinTimeToETADayHourMinString( uiArrivalTime, sString ); } else { // show location GetMapscreenMercLocationString( pSoldier, sString ); } if ( wcslen( sString ) > 0 ) { const auto x = UI_CHARPANEL.Text.CurrentAssignment.x; const auto y = UI_CHARPANEL.Text.CurrentAssignment_Y2; const auto w = UI_CHARPANEL.Text.CurrentAssignment.width; const auto h = UI_CHARPANEL.Text.CurrentAssignment.height; FindFontCenterCoordinates(x, y, w, h, sString, CHAR_FONT, &usX, &usY); DrawString(sString, usX, usY, CHAR_FONT ); } // draw health/condition DrawCharHealth( sCharNumber ); // if a vehicle or robot if( ( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) || AM_A_ROBOT( pSoldier ) ) { // we're done - the remainder applies only to people return; } // draw attributes & skills for currently displayed character DrawCharStats(sCharNumber); // remaining contract length // dead? if( pSoldier->stats.bLife <= 0 ) { swprintf( sString, L"%s", gpStrategicString[ STR_PB_NOTAPPLICABLE_ABBREVIATION ] ); } // what kind of merc else if(pSoldier->ubWhatKindOfMercAmI == MERC_TYPE__AIM_MERC || pSoldier->ubProfile == SLAY ) { FLOAT dTimeLeft = 0.0; // amount of time left on contract iTimeRemaining = pSoldier->iEndofContractTime-GetWorldTotalMin(); //if the merc is in transit if( pSoldier->bAssignment == IN_TRANSIT ) { //and if the ttime left on the cotract is greater then the contract time if( iTimeRemaining > (INT32)( pSoldier->iTotalContractLength * NUM_MIN_IN_DAY ) ) { iTimeRemaining = ( pSoldier->iTotalContractLength * NUM_MIN_IN_DAY ); } } if(iTimeRemaining >= ( 24 * 60 ) ) { //calculate the exact time left on the contract ( ex 1.8 days ) dTimeLeft = (FLOAT)(iTimeRemaining / (60*24.0) ); // more than a day, display in green iTimeRemaining /= (60*24); if( pSoldier->stats.bLife > 0 ) { SetFontForeground(FONT_LTGREEN); } swprintf(sString, L"%.1f%s/%d%s", dTimeLeft, gpStrategicString[ STR_PB_DAYS_ABBREVIATION ], pSoldier->iTotalContractLength, gpStrategicString[ STR_PB_DAYS_ABBREVIATION ]); } else { // less than a day, display hours left in red if( iTimeRemaining > 5 ) { BOOLEAN fNeedToIncrement = FALSE; if( iTimeRemaining % 60 != 0 ) fNeedToIncrement = TRUE; iTimeRemaining /= 60; if( fNeedToIncrement ) iTimeRemaining++; } else { iTimeRemaining /= 60; } if( pSoldier->stats.bLife > 0 ) { SetFontForeground(FONT_RED); } swprintf(sString, L"%d%s/%d%s",iTimeRemaining, gpStrategicString[ STR_PB_HOURS_ABBREVIATION ], pSoldier->iTotalContractLength, gpStrategicString[ STR_PB_DAYS_ABBREVIATION ]); } } else if( pSoldier->ubWhatKindOfMercAmI == MERC_TYPE__MERC ) { INT32 iBeenHiredFor = ( GetWorldTotalMin( ) / NUM_MIN_IN_DAY ) - pSoldier->iStartContractTime; swprintf(sString, L"%d%s/%d%s",gMercProfiles[ pSoldier->ubProfile ].iMercMercContractLength, gpStrategicString[ STR_PB_DAYS_ABBREVIATION ], iBeenHiredFor, gpStrategicString[ STR_PB_DAYS_ABBREVIATION ] ); } else { swprintf( sString, L"%s", gpStrategicString[ STR_PB_NOTAPPLICABLE_ABBREVIATION ] ); } // set font stuff SetFontForeground(CHAR_TEXT_FONT_COLOR); SetFontBackground(FONT_BLACK); // center and draw { const auto x = UI_CHARPANEL.Text.TimeRemaining.x; const auto y = UI_CHARPANEL.Text.TimeRemaining.y; const auto w = UI_CHARPANEL.Text.TimeRemaining.width; const auto h = UI_CHARPANEL.Text.TimeRemaining.height; FindFontCenterCoordinates(x, y, w, h, sString, CHAR_FONT, &usX, &usY); DrawString(sString, usX, usY, CHAR_FONT); } // salary if( pSoldier->ubWhatKindOfMercAmI == MERC_TYPE__AIM_MERC ) { // daily rate if( pSoldier->bTypeOfLastContract == CONTRACT_EXTEND_2_WEEK ) { iDailyCost = ( gMercProfiles[ pSoldier->ubProfile ].uiBiWeeklySalary / 14 ); } if( pSoldier->bTypeOfLastContract == CONTRACT_EXTEND_1_WEEK ) { iDailyCost = ( gMercProfiles[ pSoldier->ubProfile ].uiWeeklySalary / 7 ); } else { iDailyCost = gMercProfiles[ pSoldier->ubProfile ].sSalary; } } else { iDailyCost = gMercProfiles[ pSoldier->ubProfile ].sSalary; } swprintf(sString, L"%d", iDailyCost ); // insert commas and dollar sign InsertCommasForDollarFigure( sString ); InsertDollarSignInToString( sString ); { const auto x = UI_CHARPANEL.Text.Salary.x; const auto y = UI_CHARPANEL.Text.Salary.y; const auto w = UI_CHARPANEL.Text.Salary.width; const auto h = UI_CHARPANEL.Text.Salary.height; FindFontRightCoordinates(x, y, w, h, sString, CHAR_FONT, &usX, &usY); DrawString(sString, usX, usY, CHAR_FONT); } // medical deposit if( gMercProfiles[ gCharactersList[ sCharNumber ].usSolID->ubProfile ].sMedicalDepositAmount > 0 ) { swprintf(sString, L"%d", gMercProfiles[ gCharactersList[ sCharNumber ].usSolID->ubProfile ].sMedicalDepositAmount ); // insert commas and dollar sign InsertCommasForDollarFigure( sString ); InsertDollarSignInToString( sString ); { const auto x = UI_CHARPANEL.Text.Medical.x; const auto y = UI_CHARPANEL.Text.Medical.y; const auto w = UI_CHARPANEL.Text.Medical.width; const auto h = UI_CHARPANEL.Text.Medical.height; FindFontRightCoordinates(x, y, w, h, sString, CHAR_FONT, &usX, &usY); DrawString(sString, usX, y, CHAR_FONT); } } /* // life insurance swprintf(sString, L"%d", Menptr[ gCharactersList[ sCharNumber ].usSolID ].usLifeInsuranceAmount ); InsertCommasForDollarFigure( sString ); InsertDollarSignInToString( sString ); FindFontRightCoordinates(CHAR_LIFE_INSUR_X, CHAR_LIFE_INSUR_Y, CHAR_LIFE_INSUR_WID, CHAR_LIFE_INSUR_HEI, sString, CHAR_FONT, &usX, &usY); DrawString(sString,usX,usY, CHAR_FONT); */ // morale if( pSoldier->bAssignment != ASSIGNMENT_POW ) { if ( pSoldier->stats.bLife != 0 ) { GetMoraleString( gCharactersList[sCharNumber].usSolID, sString ); } else { wcscpy( sString, L"" ); } } else { // POW - morale unknown swprintf( sString, pPOWStrings[ 1 ] ); } { const auto x = UI_CHARPANEL.Text.CurrentMorale.x; const auto y = UI_CHARPANEL.Text.CurrentMorale.y; const auto w = UI_CHARPANEL.Text.CurrentMorale.width; const auto h = UI_CHARPANEL.Text.CurrentMorale.height; FindFontCenterCoordinates(x, y, w, h, sString, CHAR_FONT, &usX, &usY); DrawString(sString, usX, y, CHAR_FONT); } return; } // this character is in transit has an item picked up BOOLEAN CharacterIsInTransitAndHasItemPickedUp( INT8 bCharacterNumber ) { // valid character? if( bCharacterNumber == -1 ) { // nope return( FALSE ); } // second validity check if( gCharactersList[ bCharacterNumber ].fValid == FALSE ) { // nope return( FALSE ); } // character in transit? if( gCharactersList[ bCharacterNumber ].usSolID->bAssignment != IN_TRANSIT ) { // nope return( FALSE ); } // item picked up? if( gMPanelRegion.Cursor != EXTERN_CURSOR) { return( FALSE ); } return( TRUE ); } void DisplayCharacterInfo( void ) { Assert( bSelectedInfoChar < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS ); Assert( gCharactersList[ bSelectedInfoChar ].fValid ); // set font buffer SetFontDestBuffer( guiSAVEBUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, FALSE ); // HEADROCK HAM 3.6: "progress" bars showing how near the character is to "leveling up" in any stat. The bar // is displayed behind the current stat value, as see on the character's info panel. // This section draws STRATEGIC info pages. Another section is in Interface Panels.cpp and draws TACTICAL info pages. // The feature is toggled by Options-Menu switch, and its color is determined in the INI files. { SOLDIERTYPE *pSoldier = gCharactersList[bSelectedInfoChar].usSolID; UINT8 *pDestBuf; UINT32 uiDestPitchBYTES = 0; SGPRect ClipRect; UINT8 ubBarWidth = 0; UINT16 usColor = Get16BPPColor( FROMRGB( gGameExternalOptions.ubStatProgressBarsRed, gGameExternalOptions.ubStatProgressBarsGreen, gGameExternalOptions.ubStatProgressBarsBlue ) ); //pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES ); pDestBuf = LockVideoSurface( guiSAVEBUFFER, &uiDestPitchBYTES ); const auto STAT_WIDTH = UI_CHARPANEL.Attr.width; const auto STAT_HEIGHT = UI_CHARPANEL.Attr.height; // AGI if (gMercProfiles[ pSoldier->ubProfile ].sAgilityGain) { const auto x = UI_CHARPANEL.Attr.AGL.iX; const auto y = UI_CHARPANEL.Attr.AGL.iY; ubBarWidth = (STAT_WIDTH * (gMercProfiles[ pSoldier->ubProfile ].sAgilityGain+1)) / SubpointsPerPoint(AGILAMT, &gMercProfiles[pSoldier->ubProfile]); ubBarWidth = __max(0, __min(ubBarWidth, STAT_WIDTH)); ClipRect.iTop = (y-1); ClipRect.iBottom = (y-1) + STAT_HEIGHT; ClipRect.iLeft = x; ClipRect.iRight = x + ubBarWidth; Blt16BPPBufferHatchRectWithColor( (UINT16*)pDestBuf, uiDestPitchBYTES, &ClipRect, usColor ); } // DEX if (gMercProfiles[ pSoldier->ubProfile ].sDexterityGain) { const auto x = UI_CHARPANEL.Attr.DEX.iX; const auto y = UI_CHARPANEL.Attr.DEX.iY; ubBarWidth = (STAT_WIDTH * (gMercProfiles[ pSoldier->ubProfile ].sDexterityGain+1)) / SubpointsPerPoint(DEXTAMT, &gMercProfiles[pSoldier->ubProfile]); ubBarWidth = __max(0, __min(ubBarWidth, STAT_WIDTH)); ClipRect.iTop = (y-1); ClipRect.iBottom = (y-1) + STAT_HEIGHT; ClipRect.iLeft = x; ClipRect.iRight = x + ubBarWidth; Blt16BPPBufferHatchRectWithColor( (UINT16*)pDestBuf, uiDestPitchBYTES, &ClipRect, usColor ); } // STR if (gMercProfiles[ pSoldier->ubProfile ].sStrengthGain) { const auto x = UI_CHARPANEL.Attr.STR.iX; const auto y = UI_CHARPANEL.Attr.STR.iY; ubBarWidth = (STAT_WIDTH * (gMercProfiles[ pSoldier->ubProfile ].sStrengthGain+1)) / SubpointsPerPoint(STRAMT, &gMercProfiles[pSoldier->ubProfile]); ubBarWidth = __max(0, __min(ubBarWidth, STAT_WIDTH)); ClipRect.iTop = (y-1); ClipRect.iBottom = (y-1) + STAT_HEIGHT; ClipRect.iLeft = x; ClipRect.iRight = x + ubBarWidth; Blt16BPPBufferHatchRectWithColor( (UINT16*)pDestBuf, uiDestPitchBYTES, &ClipRect, usColor ); } // WIS if (gMercProfiles[ pSoldier->ubProfile ].sWisdomGain) { const auto x = UI_CHARPANEL.Attr.WIS.iX; const auto y = UI_CHARPANEL.Attr.WIS.iY; ubBarWidth = (STAT_WIDTH * (gMercProfiles[ pSoldier->ubProfile ].sWisdomGain+1)) / SubpointsPerPoint(WISDOMAMT, &gMercProfiles[pSoldier->ubProfile]); ubBarWidth = __max(0, __min(ubBarWidth, STAT_WIDTH)); ClipRect.iTop = (y-1); ClipRect.iBottom = (y-1) + STAT_HEIGHT; ClipRect.iLeft = x; ClipRect.iRight = x + ubBarWidth; Blt16BPPBufferHatchRectWithColor( (UINT16*)pDestBuf, uiDestPitchBYTES, &ClipRect, usColor ); } // MRK if (gMercProfiles[ pSoldier->ubProfile ].sMarksmanshipGain) { const auto x = UI_CHARPANEL.Attr.MRK.iX; const auto y = UI_CHARPANEL.Attr.MRK.iY; ubBarWidth = (STAT_WIDTH * (gMercProfiles[ pSoldier->ubProfile ].sMarksmanshipGain+1)) / SubpointsPerPoint(MARKAMT, &gMercProfiles[pSoldier->ubProfile]); ubBarWidth = __max(0, __min(ubBarWidth, STAT_WIDTH)); ClipRect.iTop = (y-1); ClipRect.iBottom = (y-1) + STAT_HEIGHT; ClipRect.iLeft = x; ClipRect.iRight = x + ubBarWidth; Blt16BPPBufferHatchRectWithColor( (UINT16*)pDestBuf, uiDestPitchBYTES, &ClipRect, usColor ); } // LDR if (gMercProfiles[ pSoldier->ubProfile ].sLeadershipGain) { const auto x = UI_CHARPANEL.Attr.LDR.iX; const auto y = UI_CHARPANEL.Attr.LDR.iY; ubBarWidth = (STAT_WIDTH * (gMercProfiles[ pSoldier->ubProfile ].sLeadershipGain+1)) / SubpointsPerPoint(LDRAMT, &gMercProfiles[pSoldier->ubProfile]); ubBarWidth = __max(0, __min(ubBarWidth, STAT_WIDTH)); ClipRect.iTop = (y-1); ClipRect.iBottom = (y-1) + STAT_HEIGHT; ClipRect.iLeft = x; ClipRect.iRight = x + ubBarWidth; Blt16BPPBufferHatchRectWithColor( (UINT16*)pDestBuf, uiDestPitchBYTES, &ClipRect, usColor ); } // MECH if (gMercProfiles[ pSoldier->ubProfile ].sMechanicGain) { const auto x = UI_CHARPANEL.Attr.MEC.iX; const auto y = UI_CHARPANEL.Attr.MEC.iY; ubBarWidth = (STAT_WIDTH * (gMercProfiles[ pSoldier->ubProfile ].sMechanicGain+1)) / SubpointsPerPoint(MECHANAMT, &gMercProfiles[pSoldier->ubProfile]); ubBarWidth = __max(0, __min(ubBarWidth, STAT_WIDTH)); ClipRect.iTop = (y-1); ClipRect.iBottom = (y-1) + STAT_HEIGHT; ClipRect.iLeft = x; ClipRect.iRight = x + ubBarWidth; Blt16BPPBufferHatchRectWithColor( (UINT16*)pDestBuf, uiDestPitchBYTES, &ClipRect, usColor ); } // EXPLO if (gMercProfiles[ pSoldier->ubProfile ].sExplosivesGain) { const auto x = UI_CHARPANEL.Attr.EXP.iX; const auto y = UI_CHARPANEL.Attr.EXP.iY; ubBarWidth = (STAT_WIDTH * (gMercProfiles[ pSoldier->ubProfile ].sExplosivesGain+1)) / SubpointsPerPoint(EXPLODEAMT, &gMercProfiles[pSoldier->ubProfile]); ubBarWidth = __max(0, __min(ubBarWidth, STAT_WIDTH)); ClipRect.iTop = (y-1); ClipRect.iBottom = (y-1) + STAT_HEIGHT; ClipRect.iLeft = x; ClipRect.iRight = x + ubBarWidth; Blt16BPPBufferHatchRectWithColor( (UINT16*)pDestBuf, uiDestPitchBYTES, &ClipRect, usColor ); } // MED if (gMercProfiles[ pSoldier->ubProfile ].sMedicalGain) { const auto x = UI_CHARPANEL.Attr.MED.iX; const auto y = UI_CHARPANEL.Attr.MED.iY; ubBarWidth = (STAT_WIDTH * (gMercProfiles[ pSoldier->ubProfile ].sMedicalGain+1)) / SubpointsPerPoint(MEDICALAMT, &gMercProfiles[pSoldier->ubProfile]); ubBarWidth = __max(0, __min(ubBarWidth, STAT_WIDTH)); ClipRect.iTop = (y-1); ClipRect.iBottom = (y-1) + STAT_HEIGHT; ClipRect.iLeft = x; ClipRect.iRight = x + ubBarWidth; Blt16BPPBufferHatchRectWithColor( (UINT16*)pDestBuf, uiDestPitchBYTES, &ClipRect, usColor ); } // EXPLEVEL if (gMercProfiles[ pSoldier->ubProfile ].sExpLevelGain) { const auto x = UI_CHARPANEL.Attr.LVL.iX; const auto y = UI_CHARPANEL.Attr.LVL.iY; ubBarWidth = (STAT_WIDTH * (gMercProfiles[ pSoldier->ubProfile ].sExpLevelGain+1)) / SubpointsPerPoint(EXPERAMT, &gMercProfiles[pSoldier->ubProfile]); ubBarWidth = __max(0, __min(ubBarWidth, STAT_WIDTH)); ClipRect.iTop = (y-1); ClipRect.iBottom = (y-1) + STAT_HEIGHT; ClipRect.iLeft = x; ClipRect.iRight = x + ubBarWidth; Blt16BPPBufferHatchRectWithColor( (UINT16*)pDestBuf, uiDestPitchBYTES, &ClipRect, usColor ); } UnLockVideoSurface( guiSAVEBUFFER ); } // draw character info and face DrawCharacterInfo( bSelectedInfoChar ); RenderHandPosItem(); SetFontDestBuffer( FRAME_BUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, FALSE ); RenderIconsForUpperLeftCornerPiece( bSelectedInfoChar ); // mark all pop ups as dirty MarkAllBoxesAsAltered( ); } INT32 GetPathTravelTimeDuringPlotting( PathStPtr pPath ) { INT32 iTravelTime = 0; WAYPOINT pCurrent; WAYPOINT pNext; GROUP *pGroup = NULL; UINT8 ubGroupId = 0; BOOLEAN fSkipFirstNode = FALSE; if ( ( GetSelectedDestChar() == -1) && !fPlotForHelicopter && !fPlotForMilitia ) { return( 0 ); } if( fTempPathAlreadyDrawn == FALSE ) { return( 0 ); } if( pPath == NULL ) { return( 0 ); } pPath = MoveToBeginningOfPathList( pPath ); if( fPlotForHelicopter ) { ubGroupId = pVehicleList[iHelicopterVehicleId].ubMovementGroup; pGroup = GetGroup( ubGroupId ); AssertNotNIL( pGroup ); } else if ( fPlotForMilitia ) { if ( gMilitiaPath[gMilitiaGroupId].sGroupid > -1 ) { ubGroupId = (UINT8)gMilitiaPath[gMilitiaGroupId].sGroupid; pGroup = GetGroup( ubGroupId ); } AssertNotNIL( pGroup ); } else { // plotting for a character... SOLDIERTYPE* pSoldier = gCharactersList[GetSelectedDestChar()].usSolID; if( pSoldier->bAssignment == VEHICLE ) { ubGroupId = pVehicleList[ pSoldier->iVehicleId ].ubMovementGroup; pGroup = GetGroup( ubGroupId ); if( pGroup == NULL ) { SetUpMvtGroupForVehicle( pSoldier ); // get vehicle id ubGroupId = pVehicleList[ pSoldier->iVehicleId ].ubMovementGroup; pGroup = GetGroup( ubGroupId ); AssertNotNIL(pGroup); } } else if( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) { ubGroupId = pVehicleList[ pSoldier->bVehicleID ].ubMovementGroup; pGroup = GetGroup( ubGroupId ); if( pGroup == NULL ) { SetUpMvtGroupForVehicle( pSoldier ); // get vehicle id ubGroupId = pVehicleList[ pSoldier->bVehicleID ].ubMovementGroup; pGroup = GetGroup( ubGroupId ); AssertNotNIL(pGroup); } } else { ubGroupId = pSoldier->ubGroupID; pGroup = GetGroup( ( UINT8 )( ubGroupId ) ); AssertNotNIL(pGroup); } } // if between sectors if ( pGroup->fBetweenSectors ) { // arrival time should always be legal! Assert( pGroup->uiArrivalTime >= GetWorldTotalMin( ) ); // start with time to finish arriving in any traversal already in progress iTravelTime = pGroup->uiArrivalTime - GetWorldTotalMin(); fSkipFirstNode = TRUE; } else { iTravelTime = 0; } while( pPath->pNext ) { if ( !fSkipFirstNode ) { // grab the current location pCurrent.x = ( UINT8 )( pPath->uiSectorId % MAP_WORLD_X ); pCurrent.y = ( UINT8 )( pPath->uiSectorId / MAP_WORLD_X ); // grab the next location pNext.x = ( UINT8 )( pPath->pNext->uiSectorId % MAP_WORLD_X ); pNext.y = ( UINT8 )( pPath->pNext->uiSectorId / MAP_WORLD_X ); iTravelTime += FindTravelTimeBetweenWaypoints( &pCurrent, &pNext, pGroup ); } else { fSkipFirstNode = FALSE; } pPath = pPath->pNext; } return( iTravelTime ); } void DisplayGroundEta( void ) { UINT32 iTotalTime = 0; if( fPlotForHelicopter ) return; if ( fPlotForMilitia ) { iTotalTime = GetGroundTravelTimeOfMilitia( ); } else { if( GetSelectedDestChar() == -1 ) return; if( !gCharactersList[GetSelectedDestChar()].fValid ) return; iTotalTime = GetGroundTravelTimeOfCharacter( GetSelectedDestChar() ); } // now display it SetFont( ETA_FONT ); SetFontForeground( FONT_LTGREEN ); SetFontBackground( FONT_BLACK ); mprintf(UI_MAP.ETA.Clock_X, UI_MAP.ETA.Start_Y, pEtaString[ 0 ] ); // if less than one day if( ( iTotalTime / ( 60 * 24 ) ) < 1 ) { // show hours and minutes SetClockMin( L"%d", iTotalTime % 60 ); SetClockHour(L"%d", iTotalTime / 60); } else { // show days and hours SetHourAlternate(L"%d", ( iTotalTime / 60 ) % 24 ); SetDayAlternate( L"%d", iTotalTime / ( 60 * 24 ) ); } } void HighLightAssignLine() { UINT32 uiDestPitchBYTES; UINT8 *pDestBuf; UINT16 usColor; static INT32 iColorNum = STARTING_COLOR_NUM; static BOOLEAN fDelta=FALSE; static INT32 uiOldHighlight = giMAXIMUM_NUMBER_OF_PLAYER_SLOTS + 1; INT16 usCount = 0; UINT16 usY; INT16 usVehicleCount = 0; // is this a valid line? if( ( giAssignHighLine == -1 ) || fShowInventoryFlag ) { uiOldHighlight = giMAXIMUM_NUMBER_OF_PLAYER_SLOTS + 1; return; } // if not ready to change glow phase yet, leave if ( !gfGlowTimerExpired ) return; // check if we have moved lines, if so, reset if( uiOldHighlight != giAssignHighLine ) { iColorNum = STARTING_COLOR_NUM; fDelta = FALSE; uiOldHighlight = giAssignHighLine; } if((iColorNum==0)||(iColorNum==10)) { fDelta=!fDelta; } if(!fDelta) iColorNum++; else iColorNum--; const auto yStart = UI_CHARLIST.y; const auto yOffset = UI_CHARLIST.yOffset; usY = (yOffset * giAssignHighLine - 1 ) + (yStart + ( giAssignHighLine * Y_SIZE ) ); pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES ); SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); // marke strogg more mercs const auto usX = UI_CHARLIST.xAssignment; const auto width = UI_CHARLIST.widthAssignment; for( usCount = 0; usCount < maxNumberOfMercVisibleInStrategyList; usCount++ ) { if( IsCharacterSelectedForAssignment( usCount ) == TRUE ) { usY=(yOffset * usCount-1)+(yStart +(usCount*Y_SIZE)); usColor=Get16BPPColor( FROMRGB( GlowColorsA[iColorNum].ubRed, GlowColorsA[iColorNum].ubGreen, GlowColorsA[iColorNum].ubBlue ) ); LineDraw(TRUE, usX, usY, usX, usY+GetFontHeight(MAP_SCREEN_FONT)+2, usColor, pDestBuf); LineDraw(TRUE, usX + width, usY, usX + width, usY+GetFontHeight(MAP_SCREEN_FONT)+2, usColor, pDestBuf); if( ( usCount == 0 ) || ( usCount != 0 ? !( IsCharacterSelectedForAssignment( ( UINT16 )( usCount - 1 ) ) ) : 0 ) ) { LineDraw( TRUE, usX, usY, usX + width, usY, usColor,pDestBuf); } if( ( ( usCount == giMAXIMUM_NUMBER_OF_PLAYER_SLOTS - 1 ) ) || ( usCount != ( giMAXIMUM_NUMBER_OF_PLAYER_SLOTS - 1 ) ? !( IsCharacterSelectedForAssignment( ( UINT16 )( usCount + 1 ) ) ) : 0) ) { LineDraw(TRUE, usX, usY+GetFontHeight(MAP_SCREEN_FONT)+2, usX + width, usY+GetFontHeight(MAP_SCREEN_FONT)+2, usColor, pDestBuf); } InvalidateRegion( usX, usY, usX + width + 1, usY+GetFontHeight(MAP_SCREEN_FONT)+3); } } UnLockVideoSurface( FRAME_BUFFER ); } void HighLightDestLine() { UINT32 uiDestPitchBYTES; UINT8 *pDestBuf; UINT16 usColor; static INT32 iColorNum = STARTING_COLOR_NUM; static BOOLEAN fDelta=FALSE; static INT32 uiOldHighlight = giMAXIMUM_NUMBER_OF_PLAYER_SLOTS + 1; UINT16 usCount = 0; UINT16 usY; //UINT16 usVehicleCont = 0; if( ( giDestHighLine == -1 ) || fShowInventoryFlag ) { uiOldHighlight = giMAXIMUM_NUMBER_OF_PLAYER_SLOTS + 1; return; } // if not ready to change glow phase yet, leave if ( !gfGlowTimerExpired ) return; // check if we have moved lines, if so, reset if( uiOldHighlight != giDestHighLine ) { iColorNum = STARTING_COLOR_NUM; fDelta = FALSE; uiOldHighlight = giDestHighLine; } if((iColorNum==0)||(iColorNum==10)) { fDelta=!fDelta; } if(!fDelta) iColorNum++; else iColorNum--; pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES ); SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); // marke strogg more mercs const auto usX = UI_CHARLIST.xETA; const auto width = UI_CHARLIST.widthETA; for( usCount = 0; usCount < maxNumberOfMercVisibleInStrategyList; usCount++ ) { if( CharacterIsGettingPathPlotted( usCount ) == TRUE ) { usY=(UI_CHARLIST.yOffset*usCount-1)+(UI_CHARLIST.y +(usCount*Y_SIZE)); usColor=Get16BPPColor( FROMRGB( GlowColorsA[iColorNum].ubRed, GlowColorsA[iColorNum].ubGreen, GlowColorsA[iColorNum].ubBlue ) ); if( ( usCount == 0 ) || ( usCount != 0 ? !( CharacterIsGettingPathPlotted( ( UINT16 )( usCount - 1 ) ) ) : 0 )) { LineDraw( TRUE, usX, usY, usX + width, usY, usColor,pDestBuf); } if( ( ( usCount == giMAXIMUM_NUMBER_OF_PLAYER_SLOTS - 1 ) ) || ( usCount != ( giMAXIMUM_NUMBER_OF_PLAYER_SLOTS - 1 ) ? !( CharacterIsGettingPathPlotted( ( UINT16 )( usCount + 1 ) ) ) : 0) ) { LineDraw(TRUE, usX, usY+GetFontHeight(MAP_SCREEN_FONT)+2, usX + width, usY+GetFontHeight(MAP_SCREEN_FONT)+2, usColor, pDestBuf); } LineDraw(TRUE, usX, usY, usX, usY+GetFontHeight(MAP_SCREEN_FONT)+2, usColor, pDestBuf); LineDraw(TRUE, usX+ width, usY, usX + width, usY+GetFontHeight(MAP_SCREEN_FONT)+2, usColor, pDestBuf); InvalidateRegion( usX - 4, usY, usX + width + 1, usY + GetFontHeight(MAP_SCREEN_FONT)+3 ); } } //InvalidateRegion( usX+4, usY, width-10, usY+GetFontHeight(MAP_SCREEN_FONT)+3); //InvalidateRegion( usX+10, usY, usX+ASSIGN_WIDTH, usY+GetFontHeight(MAP_SCREEN_FONT)+3); UnLockVideoSurface( FRAME_BUFFER ); } void HighLightSleepLine() { UINT32 uiDestPitchBYTES; UINT8 *pDestBuf; UINT16 usColor; static INT32 iColorNum = STARTING_COLOR_NUM; static BOOLEAN fDelta=FALSE; static INT32 uiOldHighlight = giMAXIMUM_NUMBER_OF_PLAYER_SLOTS + 1; UINT16 usCount = 0; UINT16 usY; //UINT16 usVehicleCount = 0; // is this a valid line? if( ( giSleepHighLine == -1 ) || fShowInventoryFlag ) { uiOldHighlight = giMAXIMUM_NUMBER_OF_PLAYER_SLOTS + 1; return; } // if not ready to change glow phase yet, leave if ( !gfGlowTimerExpired ) return; // check if we have moved lines, if so, reset if( uiOldHighlight != giSleepHighLine ) { iColorNum = STARTING_COLOR_NUM; fDelta = FALSE; uiOldHighlight = giSleepHighLine; } if((iColorNum==0)||(iColorNum==10)) { fDelta=!fDelta; } if(!fDelta) iColorNum++; else iColorNum--; pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES ); SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); // marke strogg more mercs Ok, we have to watch for to use only 18 display lines insedead of MAX_CHARACTER_COUNT const auto x = UI_CHARLIST.xSleep; const auto xEnd = UI_CHARLIST.xSleep + UI_CHARLIST.widthSleep; const auto y = UI_CHARLIST.y; const auto yOffset = UI_CHARLIST.yOffset; for( usCount = 0; usCount < maxNumberOfMercVisibleInStrategyList; usCount++ ) { if( IsCharacterSelectedForSleep( usCount ) == TRUE ) { usY=(yOffset*usCount-1)+(y +(usCount*Y_SIZE)); usColor=Get16BPPColor( FROMRGB( GlowColorsA[iColorNum].ubRed, GlowColorsA[iColorNum].ubGreen, GlowColorsA[iColorNum].ubBlue ) ); if( ( usCount == 0 ) || ( usCount != 0 ? !( IsCharacterSelectedForSleep( ( UINT16 )( usCount - 1 ) ) ) : 0 ) ) { LineDraw( TRUE, x, usY, xEnd, usY, usColor,pDestBuf); } if( ( ( usCount == giMAXIMUM_NUMBER_OF_PLAYER_SLOTS - 1 ) ) || ( usCount != ( giMAXIMUM_NUMBER_OF_PLAYER_SLOTS - 1 ) ? !( IsCharacterSelectedForSleep( ( UINT16 )( usCount + 1 ) ) ) : 0) ) { LineDraw(TRUE, x, usY+GetFontHeight(MAP_SCREEN_FONT)+2, xEnd, usY+GetFontHeight(MAP_SCREEN_FONT)+2, usColor, pDestBuf); } LineDraw(TRUE, x, usY, x, usY+GetFontHeight(MAP_SCREEN_FONT)+2, usColor, pDestBuf); LineDraw(TRUE, xEnd, usY, xEnd, usY+GetFontHeight(MAP_SCREEN_FONT)+2, usColor, pDestBuf); InvalidateRegion( x - 4, usY, xEnd + 5, usY + GetFontHeight(MAP_SCREEN_FONT)+3 ); } } UnLockVideoSurface( FRAME_BUFFER ); } void AddCharacter( SOLDIERTYPE *pCharacter ) { UINT16 usCount=0; UINT16 usVehicleCount = 0, usVehicleLoop = 0; // is character valid? if( pCharacter == NULL) { // not valid, leave return; } // valid character? if( pCharacter->bActive == FALSE ) { return; } // go through character list until a blank is reached while( (gCharactersList[usCount].fValid)&&(usCount < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS) ) { usCount++; } Assert( usCount < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS ); if (usCount >= giMAXIMUM_NUMBER_OF_PLAYER_SLOTS ) { return; } // copy over soldier id value gCharactersList[usCount].usSolID = pCharacter->ubID; // valid character gCharactersList[usCount].fValid = TRUE; return; } /* void MoveCharacter(UINT16 uiInitialPosition, UINT16 uiFinalPosition) { if (!gCharactersList[uiInitialPosition].fValid) return; else memcpy(&gCharactersList[uiFinalPosition], &gCharactersList[uiInitialPosition], sizeof(MapScreenCharacterSt)); } void SwapCharacters(UINT16 uiInitialPosition, UINT16 uiFinalPosition) { MapScreenCharacterSt pTempChar; memcpy(&pTempChar, &gCharactersList[uiInitialPosition], sizeof(MapScreenCharacterSt)); memcpy(&gCharactersList[uiInitialPosition], &gCharactersList[uiFinalPosition], sizeof(MapScreenCharacterSt)); memcpy(&gCharactersList[uiFinalPosition], &pTempChar, sizeof(MapScreenCharacterSt)); } void RemoveCharacter(UINT16 uiCharPosition) { memset(&gCharactersList[uiCharPosition], 0, sizeof( MapScreenCharacterSt )); } */ void LoadCharacters( void ) { UINT16 uiCount=0; SOLDIERTYPE *pSoldier, *pTeamSoldier; INT32 cnt=0; pSoldier = MercPtrs[ 0 ]; // fills array with pressence of player controlled characters for ( pTeamSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ pSoldier->bTeam ].bLastID; cnt++,pTeamSoldier++) { if(pTeamSoldier->bActive) { AddCharacter( pTeamSoldier ); uiCount++; } } // set info char if no selected if( bSelectedInfoChar == -1 ) { if( DialogueActive() == FALSE ) { ChangeSelectedInfoChar( 0, TRUE ); } } // check if ANYONE was available if( uiCount == 0 ) { // no one to show ChangeSelectedInfoChar( -1, TRUE ); SetSelectedDestChar( -1 ); bSelectedAssignChar = -1; bSelectedContractChar = -1; fPlotForHelicopter = FALSE; fPlotForMilitia = FALSE; } } void DisplayCharacterList() { SOLDIERTYPE *pSoldier; INT16 sCount=0; UINT8 ubForegroundColor = 0; if( ( fShowAssignmentMenu == TRUE ) && ( fTeamPanelDirty == FALSE ) ) { SetFontDestBuffer(FRAME_BUFFER ,0,0,SCREEN_WIDTH,SCREEN_HEIGHT,FALSE); return; } // set dest buffer SetFontDestBuffer(guiSAVEBUFFER,0,0,SCREEN_WIDTH,SCREEN_HEIGHT,FALSE); SetFont( MAP_SCREEN_FONT ); SetFontBackground(FONT_BLACK); for (sCount = 0; sCount < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; sCount++) { if ( sCount == maxNumberOfMercVisibleInStrategyList ) // marke strogg more mercs // skip until at the VEHICLES // later - simply break for now break ; // sCount = 87 ; // skip invalid characters if ( gCharactersList[( sCount + FIRSTmercTOdisplay )].fValid == TRUE ) { pSoldier = gCharactersList[(sCount + FIRSTmercTOdisplay)].usSolID; if( sCount == ( INT16 ) giHighLine ) { ubForegroundColor = FONT_WHITE; } // check to see if character is still alive else if(pSoldier->stats.bLife == 0 ) { ubForegroundColor = FONT_METALGRAY; } else if( CharacterIsGettingPathPlotted( sCount ) == TRUE ) { ubForegroundColor = FONT_LTBLUE; } // in current sector? else if ( pSoldier->sSectorX == sSelMapX && pSoldier->sSectorY == sSelMapY && pSoldier->bSectorZ == iCurrentMapSectorZ ) { // mobile ? if( ( pSoldier->bAssignment < ON_DUTY ) || ( pSoldier->bAssignment == VEHICLE ) ) ubForegroundColor = FONT_YELLOW; else ubForegroundColor = FONT_MAP_DKYELLOW; } else { // not in current sector ubForegroundColor = 5; } SetFontForeground( ubForegroundColor ); DrawName( pSoldier->name, sCount, MAP_SCREEN_FONT); DrawLocation( sCount + FIRSTmercTOdisplay , sCount, MAP_SCREEN_FONT); DrawDestination( sCount + FIRSTmercTOdisplay, sCount, MAP_SCREEN_FONT); DrawAssignment( sCount + FIRSTmercTOdisplay, sCount, MAP_SCREEN_FONT); DrawTimeRemaining(sCount, MAP_SCREEN_FONT, ubForegroundColor ); } } // draw multiplayer player list if (is_networked && is_client) DrawMPPlayerList(); HandleDisplayOfSelectedMercArrows( ); SetFontDestBuffer(FRAME_BUFFER ,0,0,SCREEN_WIDTH,SCREEN_HEIGHT,FALSE); EnableDisableTeamListRegionsAndHelpText( ); // mark all pop ups as dirty, so that any open assigment menus get reblitted over top of the team list MarkAllBoxesAsAltered( ); return; } // OJW - Added 081201 // Draw Lan clients in the vehicle slots // change the graphics, add more relevant info... // this is just a temp test void DrawMPPlayerList () { INT16 usX=0; INT16 usY=0; static UINT8 pbar_id_player[4]; if (is_networked && is_client && is_connected) { wchar_t szPlayerName[30]; wchar_t szTeam[20]; wchar_t szCompass[2]; int row=0; for(int i=0; i < 4; i++) { if (client_names[i] != NULL) { // setup bouds for player dirty rect and progress bar int l,t,b,r; l = MP_PLAYER_X+1; r = l + MP_PLAYER_W - 1; t = MP_ROWSTART_Y+(row*Y_SIZE); b = t + Y_SIZE - 1; // set up or destroy progress bar if needed if (client_downloading[i] == 1 && pbar_id_player[i] == 0) { fTeamPanelDirty = true; CreateProgressBarNoBorder(i,l,t,r,b); SetProgressBarColor(i,112,154,209); SetProgressBarRenderBuffer(i,guiSAVEBUFFER); pbar_id_player[i] = 1; } else if (client_downloading[i] == 0 && pbar_id_player[i] == 1) { fTeamPanelDirty = true; RemoveProgressBar(i); pbar_id_player[i] = 0; } // render the progress bar if needed if (client_downloading[i] == 1 && pbar_id_player[i] == 1) { RenderProgressBar(i,client_progress[i]); } if (client_ready[i]==1) { SetFontForeground( FONT_GREEN ); } else { SetFontForeground( FONT_WHITE ); } if (strcmp(client_names[i],"")!=0) { // valid player memset(szPlayerName,0,30*sizeof(wchar_t)); mbstowcs( szPlayerName,client_names[i],30); FindFontCenterCoordinates((short)MP_PLAYER_X + 1, (short)(MP_ROWSTART_Y+(row*Y_SIZE)), (short)MP_PLAYER_W, (short)Y_SIZE, szPlayerName, (long)MAP_SCREEN_FONT, &usX, &usY); // do it manually here so as DrawString overrides the dirty rects // we want the dirty rect to include progress bar as well as player text SetFont(MAP_SCREEN_FONT); mprintf(usX,usY,(STR16)szPlayerName); int iBack = RegisterBackgroundRect(BGND_FLAG_SINGLE, NULL, l, t, r, b); SetBackgroundRectFilled( iBack ); //DrawString( (STR16)szPlayerName , usX,usY, MAP_SCREEN_FONT); // WANNE: No team selection in DM or COOP if (cGameType == MP_TYPE_DEATHMATCH || cGameType == MP_TYPE_COOP) wcscpy(szTeam, gszMPTeamNames[4]); else wcscpy(szTeam,gszMPTeamNames[client_teams[i]]); FindFontCenterCoordinates((short)MP_TEAM_X + 1, (short)(MP_ROWSTART_Y+(row*Y_SIZE)), (short)MP_TEAM_W, (short)Y_SIZE, szTeam, (long)MAP_SCREEN_FONT, &usX, &usY); DrawString( szTeam,usX,(short)usY, MAP_SCREEN_FONT); wcscpy(szCompass,(gRandomStartingEdge==1 ? L"?" : gszMPEdgesText[client_edges[i]])); FindFontCenterCoordinates((short)MP_COMPASS_X + 1, (short)(MP_ROWSTART_Y+(row*Y_SIZE)), (short)MP_COMPASS_W, (short)Y_SIZE, szCompass, (long)MAP_SCREEN_FONT, &usX, &usY); DrawString(szCompass , usX,(short)usY, MAP_SCREEN_FONT); row++; } } } // Draw the Server Info // Server name // change this text to wrap /*wchar_t szServerName[30]; memset(szServerName,0,30*sizeof(wchar_t)); mbstowcs( szServerName,cServerName,30); SetFontForeground( FONT_YELLOW ); DrawString( L"Server Name:" , MP_GAMEINFO_X ,MP_ROWSTART_Y, MAP_SCREEN_FONT); SetFontForeground( FONT_WHITE ); DrawString( (STR16)szServerName , MP_GAMEINFO_X ,MP_ROWSTART_Y+(1*Y_SIZE), MAP_SCREEN_FONT);*/ // Game Type SetFontForeground( FONT_YELLOW ); DrawString( gszMPMapscreenText[0] , MP_GAMEINFO_X ,MP_ROWSTART_Y, MAP_SCREEN_FONT); SetFontForeground( FONT_WHITE ); switch(cGameType) { case MP_TYPE_DEATHMATCH: DrawString( gzMPHScreenText[MPH_DEATHMATCH_TEXT] , MP_GAMEINFO_X ,MP_ROWSTART_Y+(1*Y_SIZE), MAP_SCREEN_FONT); break; case MP_TYPE_TEAMDEATMATCH: DrawString( gzMPHScreenText[MPH_TEAMDM_TEXT] , MP_GAMEINFO_X ,MP_ROWSTART_Y+(1*Y_SIZE), MAP_SCREEN_FONT); break; case MP_TYPE_COOP: DrawString( gzMPHScreenText[MPH_COOP_TEXT] , MP_GAMEINFO_X ,MP_ROWSTART_Y+(1*Y_SIZE), MAP_SCREEN_FONT); break; } // Max Players SetFontForeground( FONT_YELLOW ); DrawString( gszMPMapscreenText[1] , MP_GAMEINFO_X ,MP_ROWSTART_Y+(2*Y_SIZE), MAP_SCREEN_FONT); SetFontForeground( FONT_WHITE ); wchar_t szMaxPlayers[10]; swprintf(szMaxPlayers,L"%i",cMaxClients); DrawString( szMaxPlayers , MP_GAMEINFO_X + StringPixLength(gszMPMapscreenText[1],MAP_SCREEN_FONT),MP_ROWSTART_Y+(2*Y_SIZE), MAP_SCREEN_FONT); // Number of Mercs SetFontForeground( FONT_YELLOW ); DrawString( gszMPMapscreenText[2] , MP_GAMEINFO_X ,MP_ROWSTART_Y+(3*Y_SIZE), MAP_SCREEN_FONT); SetFontForeground( FONT_WHITE ); wchar_t szSquadSize[10]; swprintf(szSquadSize,L"%i",cMaxMercs); DrawString( szSquadSize , MP_GAMEINFO_X + StringPixLength(gszMPMapscreenText[2],MAP_SCREEN_FONT),MP_ROWSTART_Y+(3*Y_SIZE), MAP_SCREEN_FONT); row = 4; if (gRandomMercs) { // Random Mercs SetFontForeground( FONT_YELLOW ); DrawString( gszMPMapscreenText[5] , MP_GAMEINFO_X ,MP_ROWSTART_Y+(row*Y_SIZE), MAP_SCREEN_FONT); SetFontForeground( FONT_WHITE ); DrawString( gszMPMapscreenText[6] , MP_GAMEINFO_X + StringPixLength(gszMPMapscreenText[5],MAP_SCREEN_FONT),MP_ROWSTART_Y+(row*Y_SIZE), MAP_SCREEN_FONT); row++; } // Server Version SetFontForeground( FONT_YELLOW ); DrawString( gszMPMapscreenText[8] , MP_GAMEINFO_X ,MP_ROWSTART_Y+(row*Y_SIZE), MAP_SCREEN_FONT); row++; wchar_t szServerVer[30]; memset(szServerVer,0,30*sizeof(wchar_t)); mbstowcs( szServerVer,MPVERSION,30); SetFontForeground( FONT_WHITE ); DrawString( szServerVer , MP_GAMEINFO_X ,MP_ROWSTART_Y+(row*Y_SIZE), MAP_SCREEN_FONT); } } void DestroyMPCompassBox( void ) { RemoveBox(ghMPCompassBox); ghMPCompassBox = -1; } void CreateMPCompassBox( void ) { UINT32 hStringHandle; UINT32 uiCounter; // will create attribute pop up menu for mapscreen assignments SGPPoint CompassPosition = { MP_COMPASS_X, MP_ROWSTART_Y }; SGPRect CompassDimensions = { 0,0, 100, 95}; // create basic box CreatePopUpBox(&ghMPCompassBox, CompassDimensions, CompassPosition, (POPUP_BOX_FLAG_CLIP_TEXT|POPUP_BOX_FLAG_CENTER_TEXT|POPUP_BOX_FLAG_RESIZE )); // which buffer will box render to SetBoxBuffer(ghMPCompassBox, FRAME_BUFFER); // border type? SetBorderType(ghMPCompassBox,guiPOPUPBORDERS); // background texture SetBackGroundSurface(ghMPCompassBox, guiPOPUPTEX); // margin sizes SetMargins(ghMPCompassBox, 6, 6, 4, 4 ); // space between lines SetLineSpace(ghMPCompassBox, 2); // set current box to this one SetCurrentBox( ghMPCompassBox ); // add strings for box for(uiCounter=0; uiCounter < MAX_EDGES; uiCounter++) { AddMonoString(&hStringHandle, gszMPEdgesText[uiCounter] ); // make sure it is unhighlighted UnHighLightLine(hStringHandle); } // set font type SetBoxFont(ghMPCompassBox, MAP_SCREEN_FONT); // set highlight color SetBoxHighLight(ghMPCompassBox, FONT_WHITE); // unhighlighted color SetBoxForeground(ghMPCompassBox, FONT_LTGREEN); // background color SetBoxBackground(ghMPCompassBox, FONT_BLACK); // shaded color..for darkened text SetBoxShade( ghMPCompassBox, FONT_GRAY7 ); SetBoxSecondaryShade( ghMPCompassBox, FONT_YELLOW ); // resize box to text ResizeBoxToText( ghMPCompassBox ); //DetermineBoxPositions( ); } void CreateDestroyMouseRegionsForCompassBox() { INT32 iFontHeight = 0; INT32 iBoxXPosition = 0; INT32 iBoxYPosition = 0; INT32 iCounter = 0; SGPPoint pPosition; INT32 iBoxWidth = 0; SGPRect pDimensions; if (!is_compass_box_open) { // grab height of font iFontHeight = GetLineSpace( ghMPCompassBox ) + GetFontHeight( GetBoxFont( ghMPCompassBox ) ); // get x.y position of box GetBoxPosition( ghMPCompassBox, &pPosition); // grab box x and y position iBoxXPosition = pPosition.iX; iBoxYPosition = pPosition.iY; // get dimensions..mostly for width GetBoxSize( ghMPCompassBox, &pDimensions ); // get width iBoxWidth = pDimensions.iRight; SetCurrentBox( ghMPCompassBox ); // define regions for( iCounter = 0; iCounter < MAX_EDGES; iCounter++ ) { // add mouse region for each line of text..and set user data MSYS_DefineRegion( &gCompassMenuRegion[ iCounter ], ( INT16 )( iBoxXPosition ), ( INT16 )( iBoxYPosition + GetTopMarginSize( ghMPCompassBox ) + ( iFontHeight ) * iCounter ), ( INT16 )( iBoxXPosition + iBoxWidth ), ( INT16 )( iBoxYPosition + GetTopMarginSize( ghMPCompassBox ) + ( iFontHeight ) * ( iCounter + 1 ) ), MSYS_PRIORITY_HIGHEST - 4 , MSYS_NO_CURSOR, CompassBoxMvtCallback, CompassBoxBtnCallback ); MSYS_SetRegionUserData( &gCompassMenuRegion[ iCounter ], 0, iCounter ); } } else { // destroy regions for( iCounter = 0; iCounter < MAX_EDGES; iCounter++ ) { // add mouse region for each line of text..and set user data MSYS_RemoveRegion( &gCompassMenuRegion[ iCounter ] ); } } } void CompassBoxMvtCallback ( MOUSE_REGION* pRegion, INT32 iReason) { // mvt callback handler for assignment region INT32 iValue = -1; iValue = MSYS_GetRegionUserData( pRegion, 0 ); if (iReason & MSYS_CALLBACK_REASON_GAIN_MOUSE ) { if( GetBoxShadeFlag( ghMPCompassBox, iValue ) == FALSE ) { HighLightBoxLine( ghMPCompassBox, iValue ); } } else if (iReason & MSYS_CALLBACK_REASON_LOST_MOUSE ) { // unhighlight all strings in box UnHighLightBox( ghMPCompassBox ); } } void CompassBoxBtnCallback ( MOUSE_REGION* pRegion, INT32 iReason) { INT32 iValue = -1; iValue = MSYS_GetRegionUserData( pRegion, 0 ); if (iReason & MSYS_CALLBACK_REASON_LBUTTON_UP) { UnHighLightBox( ghMPCompassBox ); /*switch( iValue ) { case MP_EDGE_NORTH: break; case MP_EDGE_SOUTH: break; case MP_EDGE_EAST: break; case MP_EDGE_WEST: break; }*/ // send edge change to all clients, if allowed :) send_edgechange(iValue); // close the box CreateDestroyMouseRegionsForCompassBox(); HideBox(ghMPCompassBox); is_compass_box_open = false; fTeamPanelDirty = true; } else if( iReason & MSYS_CALLBACK_REASON_RBUTTON_UP ) { // close the box CreateDestroyMouseRegionsForCompassBox(); HideBox(ghMPCompassBox); is_compass_box_open = false; fTeamPanelDirty = true; } } void DestroyMPTeamBox( void ) { RemoveBox(ghMPTeamBox); ghMPTeamBox = -1; } void CreateMPTeamBox( void ) { UINT32 hStringHandle; UINT32 uiCounter; // will create attribute pop up menu for mapscreen assignments SGPPoint TeamPosition = { MP_TEAM_X, MP_ROWSTART_Y }; SGPRect TeamDimensions = { 0,0, 100, 95}; // create basic box CreatePopUpBox(&ghMPTeamBox, TeamDimensions, TeamPosition, (POPUP_BOX_FLAG_CLIP_TEXT|POPUP_BOX_FLAG_CENTER_TEXT|POPUP_BOX_FLAG_RESIZE )); // which buffer will box render to SetBoxBuffer(ghMPTeamBox, FRAME_BUFFER); // border type? SetBorderType(ghMPTeamBox,guiPOPUPBORDERS); // background texture SetBackGroundSurface(ghMPTeamBox, guiPOPUPTEX); // margin sizes SetMargins(ghMPTeamBox, 6, 6, 4, 4 ); // space between lines SetLineSpace(ghMPTeamBox, 2); // set current box to this one SetCurrentBox( ghMPTeamBox ); // add strings for box for(uiCounter=0; uiCounter < MAX_MP_TEAMS; uiCounter++) { AddMonoString(&hStringHandle, gszMPTeamNames[uiCounter] ); // make sure it is unhighlighted UnHighLightLine(hStringHandle); } // set font type SetBoxFont(ghMPTeamBox, MAP_SCREEN_FONT); // set highlight color SetBoxHighLight(ghMPTeamBox, FONT_WHITE); // unhighlighted color SetBoxForeground(ghMPTeamBox, FONT_LTGREEN); // background color SetBoxBackground(ghMPTeamBox, FONT_BLACK); // shaded color..for darkened text SetBoxShade( ghMPTeamBox, FONT_GRAY7 ); SetBoxSecondaryShade( ghMPTeamBox, FONT_YELLOW ); // resize box to text ResizeBoxToText( ghMPTeamBox ); //DetermineBoxPositions( ); } void CreateDestroyMouseRegionsForTeamBox() { INT32 iFontHeight = 0; INT32 iBoxXPosition = 0; INT32 iBoxYPosition = 0; INT32 iCounter = 0; SGPPoint pPosition; INT32 iBoxWidth = 0; SGPRect pDimensions; if (!is_team_box_open) { // grab height of font iFontHeight = GetLineSpace( ghMPTeamBox ) + GetFontHeight( GetBoxFont( ghMPTeamBox ) ); // get x.y position of box GetBoxPosition( ghMPTeamBox, &pPosition); // grab box x and y position iBoxXPosition = pPosition.iX; iBoxYPosition = pPosition.iY; // get dimensions..mostly for width GetBoxSize( ghMPTeamBox, &pDimensions ); // get width iBoxWidth = pDimensions.iRight; SetCurrentBox( ghMPTeamBox ); // define regions for( iCounter = 0; iCounter < MAX_MP_TEAMS; iCounter++ ) { // add mouse region for each line of text..and set user data MSYS_DefineRegion( &gTeamMenuRegion[ iCounter ], ( INT16 )( iBoxXPosition ), ( INT16 )( iBoxYPosition + GetTopMarginSize( ghMPTeamBox ) + ( iFontHeight ) * iCounter ), ( INT16 )( iBoxXPosition + iBoxWidth ), ( INT16 )( iBoxYPosition + GetTopMarginSize( ghMPTeamBox ) + ( iFontHeight ) * ( iCounter + 1 ) ), MSYS_PRIORITY_HIGHEST - 4 , MSYS_NO_CURSOR, TeamBoxMvtCallback, TeamBoxBtnCallback ); MSYS_SetRegionUserData( &gTeamMenuRegion[ iCounter ], 0, iCounter ); } } else { // destroy regions for( iCounter = 0; iCounter < MAX_MP_TEAMS; iCounter++ ) { // add mouse region for each line of text..and set user data MSYS_RemoveRegion( &gTeamMenuRegion[ iCounter ] ); } } } void TeamBoxMvtCallback ( MOUSE_REGION* pRegion, INT32 iReason) { // mvt callback handler for assignment region INT32 iValue = -1; iValue = MSYS_GetRegionUserData( pRegion, 0 ); if (iReason & MSYS_CALLBACK_REASON_GAIN_MOUSE ) { if( GetBoxShadeFlag( ghMPTeamBox, iValue ) == FALSE ) { HighLightBoxLine( ghMPTeamBox, iValue ); } } else if (iReason & MSYS_CALLBACK_REASON_LOST_MOUSE ) { // unhighlight all strings in box UnHighLightBox( ghMPTeamBox ); } } void TeamBoxBtnCallback ( MOUSE_REGION* pRegion, INT32 iReason) { INT32 iValue = -1; iValue = MSYS_GetRegionUserData( pRegion, 0 ); if (iReason & MSYS_CALLBACK_REASON_LBUTTON_UP) { UnHighLightBox( ghMPTeamBox ); /*switch( iValue ) { case MP_EDGE_NORTH: break; case MP_EDGE_SOUTH: break; case MP_EDGE_EAST: break; case MP_EDGE_WEST: break; }*/ // send team change to all clients, if allowed :) send_teamchange(iValue); // close the box CreateDestroyMouseRegionsForTeamBox(); HideBox(ghMPTeamBox); is_team_box_open = false; fTeamPanelDirty = true; } else if( iReason & MSYS_CALLBACK_REASON_RBUTTON_UP ) { // close the box CreateDestroyMouseRegionsForTeamBox(); HideBox(ghMPTeamBox); is_team_box_open = false; fTeamPanelDirty = true; } } // THIS IS STUFF THAT RUNS *ONCE* DURING APPLICATION EXECUTION, AT INITIAL STARTUP UINT32 MapScreenInit(void) { VOBJECT_DESC VObjectDesc; // setup message box system InitGlobalMessageList( ); // init palettes for big map InitializePalettesForMap( ); // set up mapscreen fast help text SetUpMapScreenFastHelpText( ); // set up leave list arrays for dismissed mercs InitLeaveList( ); InitializeMilitiaPopup(); VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE; FilenameForBPP("INTERFACE\\group_confirm.sti", VObjectDesc.ImageFile); CHECKF( AddVideoObject( &VObjectDesc, &guiUpdatePanel ) ); VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE; FilenameForBPP("INTERFACE\\group_confirm_tactical.sti", VObjectDesc.ImageFile); CHECKF( AddVideoObject( &VObjectDesc, &guiUpdatePanelTactical ) ); return TRUE; } UINT32 MapScreenShutdown(void) { // destroy some popup boxes fShowAssignmentMenu = FALSE; CreateDestroyAssignmentPopUpBoxes( ); // OJW if (is_networked) { DestroyMPCompassBox(); DestroyMPTeamBox(); } fShowContractMenu = FALSE; DetermineIfContractMenuCanBeShown( ); RemoveBox(ghContractBox); ghContractBox = -1; if ( ghRemoveMercAssignBox != -1 ) { fShowRemoveMenu = FALSE; RemoveBox( ghRemoveMercAssignBox ); ghRemoveMercAssignBox = -1; } // free up alloced mapscreen messages FreeGlobalMessageList( ); ShutDownPalettesForMap( ); // free memory for leave list arrays for dismissed mercs ShutDownLeaveList( ); DeleteVideoObjectFromIndex(guiUpdatePanel ); DeleteVideoObjectFromIndex(guiUpdatePanelTactical); return TRUE; } UINT32 MapScreenHandle(void) { UINT32 uiNewScreen; VSURFACE_DESC vs_desc; VOBJECT_DESC VObjectDesc; // static BOOLEAN fSecondFrame = FALSE; INT32 iCounter = 0; INT32 iCounter2 = 0; ShowLoadScreenHintInStrategicLog(); //DO NOT MOVE THIS FUNCTION CALL!!! //This determines if the help screen should be active if( ShouldTheHelpScreenComeUp( HelpScreenDetermineWhichMapScreenHelpToShow(), FALSE ) ) { // handle the help screen HelpScreenHandler(); return( MAP_SCREEN ); } MoveRadarScreen(); // shaded screen, leave if ( gfLoadPending == 2 ) { gfLoadPending = FALSE; // Load Sector // BigCheese if ( !SetCurrentWorldSector( sSelMapX, sSelMapY , ( INT8 )iCurrentMapSectorZ ) ) { // Cannot load! } else { if (isWidescreenUI()) { CreateMapCharInvIOregions(); } else { CreateDestroyMapInvButton(); } } return( MAP_SCREEN ); } if ( !fInMapMode ) { gfFirstMapscreenFrame = TRUE; InitPreviousPaths(); // if arrival sector is invalid, reset to A9 if ( ( gsMercArriveSectorX < 1 ) || ( gsMercArriveSectorY < 1 ) || ( gsMercArriveSectorX > 16 ) || ( gsMercArriveSectorY > 16 ) ) { // HEADROCK HAM 3.5: Externalized coordinates gsMercArriveSectorX = gGameExternalOptions.ubDefaultArrivalSectorX; gsMercArriveSectorY = gGameExternalOptions.ubDefaultArrivalSectorY; } gfInConfirmMapMoveMode = FALSE; gfInChangeArrivalSectorMode = FALSE; fLeavingMapScreen = FALSE; fResetTimerForFirstEntryIntoMapScreen = TRUE; fFlashAssignDone = FALSE; gfEnteringMapScreen = 0; guiTacticalInterfaceFlags |= INTERFACE_MAPSCREEN; // handle the sort buttons AddTeamPanelSortButtonsForMapScreen( ); // OJW - 20081204 if (is_networked) AddMPButtonsForMapScreen(); // load bottom graphics LoadMapScreenInterfaceBottom( ); MoveToEndOfMapScreenMessageList( ); // if the current time compression mode is something legal in mapscreen, keep it if ( ( giTimeCompressMode >= TIME_COMPRESS_5MINS ) && ( giTimeCompressMode <= TIME_COMPRESS_60MINS ) ) { // leave the current time compression mode set, but DO stop it StopTimeCompression(); } else { // set compressed mode to X0 (which also stops time compression) SetGameTimeCompressionLevel( TIME_COMPRESS_X0 ); } // disable video overlay for tactical scroll messages EnableDisableScrollStringVideoOverlay( FALSE ); CreateDestroyInsuranceMouseRegionForMercs( TRUE ); // ATE: Init tactical interface interface ( always to team panel ) //SetCurrentInterfacePanel( TEAM_PANEL ); // Do some things to this now that it's initialized //MSYS_DisableRegion( &gViewportRegion ); //MSYS_DisableRegion( &gRadarRegion ); //Disable all faces SetAllAutoFacesInactive( ); if(fPreLoadedMapGraphics == FALSE ) { vs_desc.fCreateFlags = VSURFACE_CREATE_FROMFILE | VSURFACE_SYSTEM_MEM_USAGE; if (isWidescreenUI()) { strcpy(vs_desc.ImageFile, "INTERFACE\\b_map_1280x720.pcx"); } else if (iResolution < _800x600) { // ------------ // 336 x 288 (size without the black area on top and left // Important: The size (including black area on top and left) of the PCX file has to be an even number for width and height, // otherwise the blitting method which shrinks the image by 50% does not work. // ------------ strcpy(vs_desc.ImageFile, "INTERFACE\\b_map.pcx"); } else if (iResolution < _1024x768) { // ------------ // 480 x 400 // ------------ strcpy(vs_desc.ImageFile, "INTERFACE\\b_map_800x600.pcx"); } else { // ------------ // 688 x 560 // ------------ strcpy(vs_desc.ImageFile, "INTERFACE\\b_map_1024x768.pcx"); } initMapViewAndBorderCoordinates(); LoadMapBorderGraphics( ); //fInterfacePanelDirty=DIRTYLEVEL2; //RenderTacticalInterface(); // Grab the Map image CHECKF(AddVideoSurface(&vs_desc, &guiBIGMAP)); vs_desc.fCreateFlags = VSURFACE_CREATE_FROMFILE | VSURFACE_SYSTEM_MEM_USAGE; strcpy(vs_desc.ImageFile, "INTERFACE\\popupbackground.pcx"); CHECKF(AddVideoSurface(&vs_desc, &guiPOPUPTEX)); VObjectDesc.fCreateFlags=VOBJECT_CREATE_FROMFILE; FilenameForBPP("INTERFACE\\SAM.sti", VObjectDesc.ImageFile); CHECKF(AddVideoObject(&VObjectDesc, &guiSAMICON)); // VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE; // FilenameForBPP("INTERFACE\\s_map.sti", VObjectDesc.ImageFile); // CHECKF( AddVideoObject( &VObjectDesc, &guiMAP ) ); VObjectDesc.fCreateFlags=VOBJECT_CREATE_FROMFILE; FilenameForBPP("INTERFACE\\mapcursr.sti", VObjectDesc.ImageFile); CHECKF(AddVideoObject(&VObjectDesc, &guiMAPCURSORS)); // HEADROCK HAM 5: New pathing arrows may replace the above eventually, but for now a separate variable will do. VObjectDesc.fCreateFlags=VOBJECT_CREATE_FROMFILE; if (isWidescreenUI() || iResolution >= _1024x768) FilenameForBPP("INTERFACE\\map_pathing_arrows_1024.sti", VObjectDesc.ImageFile); else if (iResolution >= _800x600) FilenameForBPP("INTERFACE\\map_pathing_arrows_800.sti", VObjectDesc.ImageFile); else FilenameForBPP("INTERFACE\\map_pathing_arrows_640.sti", VObjectDesc.ImageFile); CHECKF(AddVideoObject(&VObjectDesc, &guiMapPathingArrows)); VObjectDesc.fCreateFlags=VOBJECT_CREATE_FROMFILE; FilenameForBPP("INTERFACE\\Mine_1.sti", VObjectDesc.ImageFile); CHECKF(AddVideoObject(&VObjectDesc, &guiSubLevel1)); VObjectDesc.fCreateFlags=VOBJECT_CREATE_FROMFILE; FilenameForBPP("INTERFACE\\Mine_2.sti", VObjectDesc.ImageFile); CHECKF(AddVideoObject(&VObjectDesc, &guiSubLevel2)); VObjectDesc.fCreateFlags=VOBJECT_CREATE_FROMFILE; FilenameForBPP("INTERFACE\\Mine_3.sti", VObjectDesc.ImageFile); CHECKF(AddVideoObject(&VObjectDesc, &guiSubLevel3)); //VObjectDesc.fCreateFlags=VOBJECT_CREATE_FROMFILE; //FilenameForBPP("INTERFACE\\addonslcp.sti", VObjectDesc.ImageFile); //CHECKF(AddVideoObject(&VObjectDesc, &guiCORNERADDONS)); //VObjectDesc.fCreateFlags=VOBJECT_CREATE_FROMFILE; //FilenameForBPP("INTERFACE\\mapborder.sti", VObjectDesc.ImageFile); //CHECKF(AddVideoObject(&VObjectDesc, &guiMAPBORDER)); VObjectDesc.fCreateFlags=VOBJECT_CREATE_FROMFILE; FilenameForBPP("INTERFACE\\sleepicon.sti", VObjectDesc.ImageFile); CHECKF(AddVideoObject(&VObjectDesc, &guiSleepIcon)); VObjectDesc.fCreateFlags=VOBJECT_CREATE_FROMFILE; FilenameForBPP("INTERFACE\\charinfo.sti", VObjectDesc.ImageFile); CHECKF(AddVideoObject(&VObjectDesc, &guiCHARINFO)); /*strcpy(vs_desc.ImageFile, "INTERFACE\\playlist3.pcx"); CHECKF(AddVideoSurface( &vs_desc, &guiCHARLIST ));*/ VObjectDesc.fCreateFlags=VOBJECT_CREATE_FROMFILE; if (!is_networked) { if (isWidescreenUI()) { FilenameForBPP("INTERFACE\\newgoldpiece3_1280x720.sti", VObjectDesc.ImageFile); } else if (iResolution >= _1024x768) { FilenameForBPP("INTERFACE\\newgoldpiece3_1024x768.sti", VObjectDesc.ImageFile ); } else if (iResolution >= _800x600) { FilenameForBPP("INTERFACE\\newgoldpiece3_800x600.sti", VObjectDesc.ImageFile ); } else { FilenameForBPP("INTERFACE\\newgoldpiece3.sti", VObjectDesc.ImageFile ); } } else { // OJW - 20081204 - change mapscreen interface for MP games if (isWidescreenUI()) { FilenameForBPP("INTERFACE\\mpgoldpiece3_1280x720.sti", VObjectDesc.ImageFile); } else if (iResolution >= _1024x768) { FilenameForBPP("INTERFACE\\mpgoldpiece3_1024x768.sti", VObjectDesc.ImageFile ); } else if (iResolution >= _800x600) { FilenameForBPP("INTERFACE\\mpgoldpiece3_800x600.sti", VObjectDesc.ImageFile ); } else { FilenameForBPP("INTERFACE\\mpgoldpiece3.sti", VObjectDesc.ImageFile ); } } CHECKF(AddVideoObject(&VObjectDesc, &guiCHARLIST)); VObjectDesc.fCreateFlags=VOBJECT_CREATE_FROMFILE; if (isWidescreenUI() || iResolution >= _1024x768) FilenameForBPP("INTERFACE\\boxes_1024x768.sti", VObjectDesc.ImageFile); else if (iResolution >= _800x600) FilenameForBPP("INTERFACE\\boxes_800x600.sti", VObjectDesc.ImageFile); else FilenameForBPP("INTERFACE\\boxes.sti", VObjectDesc.ImageFile); CHECKF(AddVideoObject(&VObjectDesc, &guiCHARICONS)); VObjectDesc.fCreateFlags=VOBJECT_CREATE_FROMFILE; FilenameForBPP("INTERFACE\\incross.sti", VObjectDesc.ImageFile); CHECKF(AddVideoObject(&VObjectDesc, &guiCROSS)); VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE; FilenameForBPP( "INTERFACE\\IntelMapSymbols.sti", VObjectDesc.ImageFile ); CHECKF( AddVideoObject( &VObjectDesc, &guiINTEL ) ); VObjectDesc.fCreateFlags=VOBJECT_CREATE_FROMFILE; if (isWidescreenUI() || iResolution >= _1024x768) { FilenameForBPP("INTERFACE\\mapinv_1024x768.sti", VObjectDesc.ImageFile); } else if (iResolution >= _800x600) { FilenameForBPP("INTERFACE\\mapinv_800x600.sti", VObjectDesc.ImageFile); } else { FilenameForBPP("INTERFACE\\mapinv.sti", VObjectDesc.ImageFile); } if(!AddVideoObject(&VObjectDesc, &guiMAPINV)) { FilenameForBPP("INTERFACE\\mapinv.sti", VObjectDesc.ImageFile); CHECKF(AddVideoObject(&VObjectDesc, &guiMAPINV)); } VObjectDesc.fCreateFlags=VOBJECT_CREATE_FROMFILE; FilenameForBPP("INTERFACE\\map_inv_2nd_gun_cover.sti", VObjectDesc.ImageFile); CHECKF(AddVideoObject(&VObjectDesc, &guiMapInvSecondHandBlockout)); // the upper left corner piece icons VObjectDesc.fCreateFlags=VOBJECT_CREATE_FROMFILE; FilenameForBPP("INTERFACE\\top_left_corner_icons.sti", VObjectDesc.ImageFile); CHECKF(AddVideoObject(&VObjectDesc, &guiULICONS)); VObjectDesc.fCreateFlags=VOBJECT_CREATE_FROMFILE; FilenameForBPP("INTERFACE\\map_item.sti", VObjectDesc.ImageFile); CHECKF(AddVideoObject(&VObjectDesc, &guiORTAICON)); VObjectDesc.fCreateFlags=VOBJECT_CREATE_FROMFILE; FilenameForBPP("INTERFACE\\prison.sti", VObjectDesc.ImageFile); CHECKF(AddVideoObject(&VObjectDesc, &guiTIXAICON)); for( iCounter2 = 1; iCounter2 < NUM_TOWNS; iCounter2++ ) { VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE; if ( gfIconTown[iCounter2] == TRUE ) { strcpy(VObjectDesc.ImageFile, gHiddenIcon[iCounter2].IconSti); } else { FilenameForBPP("INTERFACE\\PRISON.sti", VObjectDesc.ImageFile); } if (!FileExists(VObjectDesc.ImageFile)) { FilenameForBPP("INTERFACE\\PRISON.sti", VObjectDesc.ImageFile); } CHECKF(AddVideoObject(&VObjectDesc, &guiIcon2[iCounter2])); } VObjectDesc.fCreateFlags=VOBJECT_CREATE_FROMFILE; // HEADROCK HAM 5.4: Larger icons for merc movement if (isWidescreenUI() || iResolution >= _1024x768) FilenameForBPP("INTERFACE\\merc_between_sector_icons_1024.sti", VObjectDesc.ImageFile); else if (iResolution >= _800x600) FilenameForBPP("INTERFACE\\merc_between_sector_icons_800.sti", VObjectDesc.ImageFile); else FilenameForBPP("INTERFACE\\merc_between_sector_icons_640.sti", VObjectDesc.ImageFile); CHECKF(AddVideoObject(&VObjectDesc, &guiCHARBETWEENSECTORICONS)); // HEADROCK HAM 5.1: Enemies between sectors VObjectDesc.fCreateFlags=VOBJECT_CREATE_FROMFILE; if (isWidescreenUI() || iResolution >= _1024x768) FilenameForBPP("INTERFACE\\enemy_between_sector_icons_1024.sti", VObjectDesc.ImageFile); else if (iResolution >= _800x600) FilenameForBPP("INTERFACE\\enemy_between_sector_icons_800.sti", VObjectDesc.ImageFile); else FilenameForBPP("INTERFACE\\enemy_between_sector_icons_640.sti", VObjectDesc.ImageFile); CHECKF(AddVideoObject(&VObjectDesc, &guiENEMYBETWEENSECTORICONS)); VObjectDesc.fCreateFlags=VOBJECT_CREATE_FROMFILE; FilenameForBPP("INTERFACE\\GreenArr.sti", VObjectDesc.ImageFile); CHECKF(AddVideoObject(&VObjectDesc, &guiLEVELMARKER)); VObjectDesc.fCreateFlags=VOBJECT_CREATE_FROMFILE; // HEADROCK HAM 5: Resolution-dependent icon if (isWidescreenUI() || iResolution >= _1024x768) FilenameForBPP("INTERFACE\\Helicopter_Map_Icon_1024.sti", VObjectDesc.ImageFile); else if (iResolution >= _800x600) FilenameForBPP("INTERFACE\\Helicopter_Map_Icon_800.sti", VObjectDesc.ImageFile); else FilenameForBPP("INTERFACE\\Helicopter_Map_Icon_640.sti", VObjectDesc.ImageFile); CHECKF(AddVideoObject(&VObjectDesc, &guiHelicopterIcon)); if (isWidescreenUI() || iResolution >= _1024x768) FilenameForBPP( "INTERFACE\\Helicopter_Map_Icon_Enemy_1024.sti", VObjectDesc.ImageFile ); else if ( iResolution >= _800x600) FilenameForBPP( "INTERFACE\\Helicopter_Map_Icon_Enemy_800.sti", VObjectDesc.ImageFile ); else FilenameForBPP( "INTERFACE\\Helicopter_Map_Icon_Enemy_640.sti", VObjectDesc.ImageFile ); CHECKF( AddVideoObject( &VObjectDesc, &guiEnemyHelicopterIcon ) ); VObjectDesc.fCreateFlags=VOBJECT_CREATE_FROMFILE; FilenameForBPP("INTERFACE\\eta_pop_up.sti", VObjectDesc.ImageFile); CHECKF(AddVideoObject(&VObjectDesc, &guiMapBorderEtaPopUp)); VObjectDesc.fCreateFlags=VOBJECT_CREATE_FROMFILE; FilenameForBPP("INTERFACE\\pos2.sti", VObjectDesc.ImageFile); CHECKF(AddVideoObject(&VObjectDesc, &guiMapBorderHeliSectors)); VObjectDesc.fCreateFlags=VOBJECT_CREATE_FROMFILE; FilenameForBPP("INTERFACE\\pos2_alternate.sti", VObjectDesc.ImageFile); CHECKF(AddVideoObject(&VObjectDesc, &guiMapBorderHeliSectorsAlternate)); VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE; FilenameForBPP("INTERFACE\\secondary_gun_hidden.sti", VObjectDesc.ImageFile); CHECKF( AddVideoObject( &VObjectDesc, &guiSecItemHiddenVO ) ); VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE; FilenameForBPP("INTERFACE\\selectedchararrow.sti", VObjectDesc.ImageFile); CHECKF( AddVideoObject( &VObjectDesc, &guiSelectedCharArrow ) ); VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE; FilenameForBPP("INTERFACE\\mine.sti", VObjectDesc.ImageFile); CHECKF( AddVideoObject( &VObjectDesc, &guiMINEICON ) ); VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE; if (isWidescreenUI() || iResolution >= _1024x768) sprintf( VObjectDesc.ImageFile, "INTERFACE\\hilite_1024x768.sti" ); else if (iResolution >= _800x600) sprintf( VObjectDesc.ImageFile, "INTERFACE\\hilite_800x600.sti" ); else sprintf( VObjectDesc.ImageFile, "INTERFACE\\hilite.sti" ); AddVideoObject( &VObjectDesc, &guiSectorLocatorGraphicID ); VObjectDesc.fCreateFlags=VOBJECT_CREATE_FROMFILE; FilenameForBPP("INTERFACE\\BullsEye.sti", VObjectDesc.ImageFile); CHECKF(AddVideoObject(&VObjectDesc, &guiBULLSEYE)); VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE; FilenameForBPP("INTERFACE\\ATTACHMENT_SLOT.STI", VObjectDesc.ImageFile); CHECKF(AddVideoObject( &VObjectDesc, &guiMapScreenAttachmentSlot)); HandleLoadOfMapBottomGraphics( ); // load the militia pop up box LoadMilitiaPopUpBox( ); // graphic for pool inventory LoadInventoryPoolGraphic( ); //Kris: Added this because I need to blink the icons button. VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE; sprintf( VObjectDesc.ImageFile, "INTERFACE\\newemail.sti" ); AddVideoObject( &VObjectDesc, &guiNewMailIcons ); } // create buttons CreateButtonsForMapBorder( ); // create mouse regions for level markers CreateMouseRegionsForLevelMarkers( ); // change selected sector/level if necessary // NOTE: Must come after border buttons are created, since it may toggle them! if( AnyMercsHired( ) == FALSE ) { // select starting sector (A9 - Omerta) // HEADROCK HAM 3.5: Externalized! ChangeSelectedMapSector( gGameExternalOptions.ubDefaultArrivalSectorX, gGameExternalOptions.ubDefaultArrivalSectorY, startingZ ); } else if( ( gWorldSectorX > 0 ) && ( gWorldSectorY > 0 ) && ( gbWorldSectorZ != -1 ) ) { // select currently loaded sector as the map sector ChangeSelectedMapSector( gWorldSectorX, gWorldSectorY, gbWorldSectorZ ); } else // no loaded sector { // only select A9 - Omerta IF there is no current selection, otherwise leave it as is if ( ( sSelMapX == 0 ) || ( sSelMapY == 0 ) || ( iCurrentMapSectorZ == -1 ) ) { // HEADROCK HAM 3.5: Externalized! ChangeSelectedMapSector( gGameExternalOptions.ubDefaultArrivalSectorX, gGameExternalOptions.ubDefaultArrivalSectorY, startingZ ); } } VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE; FilenameForBPP("INTERFACE\\Bars.sti", VObjectDesc.ImageFile); CHECKF( AddVideoObject( &VObjectDesc, &guiBrownBackgroundForTeamPanel ) ); // we are in fact in the map, do not repeat this sequence fInMapMode = TRUE; // dirty map fMapPanelDirty=TRUE; // dirty team region fTeamPanelDirty = TRUE; // dirty info region fCharacterInfoPanelDirty = TRUE; // direty map bottom region fMapScreenBottomDirty = TRUE; // tactical scroll of messages not allowed to beep until new message is added in tactical fOkToBeepNewMessage = FALSE; // not in laptop, not about to go there either fLapTop=FALSE; // reset show aircraft flag //gusMapDisplayColourMode == MAP_DISPLAY_NORMAL; // reset fact we are showing white bounding box around face fShowFaceHightLight = FALSE; fShowItemHighLight = FALSE; // reset all selected character flags ResetAllSelectedCharacterModes( ); if( fFirstTimeInMapScreen == TRUE ) { fFirstTimeInMapScreen = FALSE; // fShowMapScreenHelpText = TRUE; #ifdef JA2UB //JA25 UB //Get Jerry Milo to say his opening quote, if he hasnt said it before if( !HasJerryMiloSaidQuoteBefore( MILO_QUOTE__OPENING_GREETING_PART_1 ) ) JerryMiloDelayedTalk( MILO_QUOTE__OPENING_GREETING_PART_1, 1100 ); } //Should Jerry popup a new quote now else if( DidPlayerInitiallyHaveLessThen6MercsAndNowHaveExactly6AndHasntSaidFullLoadQuote() ) { //Get Jerry Milo to say his opening quote JerryMiloDelayedTalk( MILO_QUOTE__ALREADY_HAS_6_MERCS, 500 ); #endif } fShowMapInventoryPool = FALSE; // init character list - set all values in the list to 0 InitalizeVehicleAndCharacterList( ); // deselect all entries ResetSelectedListForMapScreen( ); LoadCharacters(); // set up regions MSYS_DefineRegion( &gMapViewRegion, UI_MAP.ViewRegion.x + UI_MAP.GridSize.iX, UI_MAP.ViewRegion.y + UI_MAP.GridSize.iY, UI_MAP.ViewRegion.x + UI_MAP.ViewRegion.width+UI_MAP.GridSize.iX-1, UI_MAP.ViewRegion.y + UI_MAP.ViewRegion.height-1 + 8, MSYS_PRIORITY_HIGH - 3, MSYS_NO_CURSOR, MSYS_NO_CALLBACK, MSYS_NO_CALLBACK ); // No enter or exit merc inventory in strategic map on widescreen UI if (!isWidescreenUI()) { MSYS_DefineRegion(&gCharInfoHandRegion, UI_CHARPANEL.HandItem.x, UI_CHARPANEL.HandItem.y, UI_CHARPANEL.HandItem.x + UI_CHARPANEL.HandItem.width, UI_CHARPANEL.HandItem.y + UI_CHARPANEL.HandItem.height, MSYS_PRIORITY_HIGH, MSYS_NO_CURSOR, ItemRegionMvtCallback, ItemRegionBtnCallback ); } MSYS_DefineRegion( &gCharInfoFaceRegion, UI_CHARPANEL.FacePicture.x, UI_CHARPANEL.FacePicture.y, UI_CHARPANEL.FacePicture.x + UI_CHARPANEL.FacePicture.width, UI_CHARPANEL.FacePicture.y + UI_CHARPANEL.FacePicture.height, MSYS_PRIORITY_HIGH, MSYS_NO_CURSOR, MSYS_NO_CALLBACK, FaceRegionBtnCallback ); MSYS_DefineRegion(&gMPanelRegion, UI_CHARINV.Region.x, UI_CHARINV.Region.y, UI_CHARINV.Region.x + UI_CHARINV.Region.width, UI_CHARINV.Region.y + UI_CHARINV.Region.height, MSYS_PRIORITY_HIGH, MSYS_NO_CURSOR, MSYS_NO_CALLBACK,InvmaskRegionBtnCallBack ); // screen mask for animated cursors MSYS_DefineRegion( &gMapScreenMaskRegion, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, MSYS_PRIORITY_LOW, CURSOR_NORMAL, MSYS_NO_CALLBACK, MapScreenMarkRegionBtnCallback); // set help text for item glow region SetRegionFastHelpText( &gCharInfoHandRegion, pMiscMapScreenMouseRegionHelpText[ 0 ] ); // init the timer menus InitTimersForMoveMenuMouseRegions( ); giMapContractButtonImage = LoadButtonImage( "INTERFACE\\contractbutton.sti" ,-1,0,-1,1,-1 ); // buttonmake giMapContractButton= QuickCreateButton( giMapContractButtonImage, UI_CHARPANEL.Button.Contract.iX + 5, UI_CHARPANEL.Button.Contract.iY - 1, BUTTON_TOGGLE, MSYS_PRIORITY_HIGHEST - 5, (GUI_CALLBACK)BtnGenericMouseMoveButtonCallback, (GUI_CALLBACK)ContractButtonCallback ); SpecifyButtonText( giMapContractButton, pContractButtonString[ 0 ] ); SpecifyButtonFont( giMapContractButton, MAP_SCREEN_FONT ); SpecifyButtonUpTextColors( giMapContractButton, CHAR_TEXT_FONT_COLOR, FONT_BLACK ); SpecifyButtonDownTextColors( giMapContractButton, CHAR_TEXT_FONT_COLOR, FONT_BLACK ); // create mouse region for pause clock CreateMouseRegionForPauseOfClock( INTERFACE_CLOCK_X, INTERFACE_CLOCK_Y ); // WANNE: The number of merc we can display in the list, depends on the resolution if (isWidescreenUI()) { if (giMAXIMUM_NUMBER_OF_PLAYER_SLOTS <= 57) maxNumberOfMercVisibleInStrategyList = giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; else maxNumberOfMercVisibleInStrategyList = 57; } else if (iResolution >= _1024x768) { if (giMAXIMUM_NUMBER_OF_PLAYER_SLOTS <= 51) maxNumberOfMercVisibleInStrategyList = giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; else maxNumberOfMercVisibleInStrategyList = 51; } else if ( iResolution >= _800x600 && iResolution < _1024x768) { maxNumberOfMercVisibleInStrategyList = 34; } else { maxNumberOfMercVisibleInStrategyList = 22; } // create mouse regions CreateMouseRegionsForTeamList( ); ReBuildCharactersList( ); // create status bar region CreateMapStatusBarsRegion( ); // Add region MSYS_AddRegion( &gMapViewRegion ); MSYS_AddRegion( &gCharInfoFaceRegion ); MSYS_AddRegion( &gMPanelRegion ); MSYS_AddRegion( &gMapMercWeightRegion ); MSYS_AddRegion( &gMapMercCamoRegion ); if ( !gfFadeOutDone && !gfFadeIn ) { MSYS_SetCurrentCursor(SCREEN_CURSOR); } MSYS_DisableRegion(&gMPanelRegion); // create contract box CreateContractBox( NULL ); // create the permanent boxes for assignment and its submenus fShowAssignmentMenu = TRUE; CreateDestroyAssignmentPopUpBoxes( ); fShowAssignmentMenu = FALSE; // OJW if (is_networked) { CreateMPCompassBox(); CreateMPTeamBox(); } // create merc remove box CreateMercRemoveAssignBox( ); // test message // TestMessageSystem( ); // fill in ColorFillVideoSurfaceArea( guiSAVEBUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, Get16BPPColor( RGB_NEAR_BLACK ) ); ColorFillVideoSurfaceArea( FRAME_BUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, Get16BPPColor( RGB_NEAR_BLACK ) ); if (isWidescreenUI()) { CreateMapCharInvIOregions(); } if( ( fFirstTimeInMapScreen == TRUE ) && ( AnyMercsHired( ) == FALSE ) ) { // render both panels for the restore RenderMapRegionBackground( ); RenderTeamRegionBackground( ); // now do the warning box DoMapMessageBox( MSG_BOX_BASIC_STYLE, pMapErrorString[ 4 ], MAP_SCREEN, MSG_BOX_FLAG_OK, MapScreenDefaultOkBoxCallback ); } fFirstTimeInMapScreen = FALSE; if( gpCurrentTalkingFace != NULL ) { // GO FROM GAMESCREEN TO MAPSCREEN // REMOVE OLD UI // Set face inactive! //gpCurrentTalkingFace->fCanHandleInactiveNow = TRUE; //SetAutoFaceInActive( gpCurrentTalkingFace->iID ); //gfFacePanelActive = FALSE; // make him continue talking ContinueDialogue( gpCurrentTalkingFace->ubSoldierID, FALSE ); // reset diabled flag //gpCurrentTalkingFace->fDisabled = FALSE; // Continue his talking! } fOneFrame = FALSE; if( fEnterMapDueToContract == TRUE ) { if( pContractReHireSoldier ) { FindAndSetThisContractSoldier( pContractReHireSoldier ); } fEnterMapDueToContract = FALSE; } } // if not going anywhere else if ( guiPendingScreen == NO_PENDING_SCREEN ) { if ( HandleFadeOutCallback( ) ) { // force mapscreen to be reinitialized even though we're already in it EndMapScreen( TRUE ); return( MAP_SCREEN ); } if ( HandleBeginFadeOut( MAP_SCREEN ) ) { return( MAP_SCREEN ); } } #ifdef JA2UB //Ja25 UB if ( gfProcessCustomMaps ) { MakeBadSectorListFromMapsOnHardDrive( TRUE ); LetLuaMakeBadSectorListFromMapsOnHardDrive( 0 ); gfProcessCustomMaps = FALSE; } #endif // check to see if we need to rebuild the characterlist for map screen HandleRebuildingOfMapScreenCharacterList( ); HandleStrategicTurn( ); // Flugente: bandaging during retreat if ( RetreatBandagingPending() ) { // now do the warning box DoScreenIndependantMessageBox( TacticalStr[ATTEMPT_BANDAGE_DURING_TRAVEL], MSG_BOX_FLAG_OK, RetreatBandageCallback ); } /* // update cursor based on state if( ( bSelectedDestChar == -1 ) && ( fPlotForHelicopter == FALSE ) && ( gfInChangeArrivalSectorMode == FALSE ) ) { // reset cursor if ( !gfFadeIn ) { ChangeMapScreenMaskCursor( CURSOR_NORMAL ); } } */ // check if we are going to create or destroy map border graphics? CreateDestroyMapInventoryPoolButtons( FALSE ); // don't process any input until we've been through here once if( gfFirstMapscreenFrame == FALSE ) { // OJW - 20081129 // Auto-start server or join server if (is_networked) { // this function does nothing if // already connected NetworkAutoStart(); // handle changing picture on start game button // for server if (is_server) { if (allowlaptop && ButtonList [ giMapMPButton[3] ]->ImageNum == giMapMPButtonImage [4]) { // Change server's button to "ready" SpecifyButtonImage( giMapMPButton [3] , giMapMPButtonImage [3] ); } } } // Handle Interface uiNewScreen = HandleMapUI( ); if ( uiNewScreen != MAP_SCREEN ) { return( MAP_SCREEN ); } } // handle flashing of contract column for any mercs leaving very soon HandleContractTimeFlashForMercThatIsAboutLeave( ); if( ( fShownAssignmentMenu == FALSE ) && ( fShowAssignmentMenu == TRUE ) ) { // need a one frame pause fShownAssignmentMenu = fShowAssignmentMenu; fShowAssignmentMenu = FALSE; fOneFrame = TRUE; } else if( ( fShownContractMenu == FALSE ) && ( fShowContractMenu == TRUE ) ) { fShownContractMenu = fShowContractMenu; fShowContractMenu = FALSE; fOneFrame = TRUE; } else if( fOneFrame ) { // one frame passed fShowContractMenu = fShownContractMenu; fShowAssignmentMenu = fShownAssignmentMenu; fOneFrame = FALSE; } if( ( fShownAssignmentMenu == FALSE ) && ( fShowAssignmentMenu == FALSE ) ) { bSelectedAssignChar = -1; } HandlePostAutoresolveMessages(); // NOTE: This must happen *before* UpdateTheStateOfTheNextPrevMapScreenCharacterButtons() CreateDestroyMapCharacterScrollButtons( ); // update the prev next merc buttons UpdateTheStateOfTheNextPrevMapScreenCharacterButtons( ); // check contract times, update screen if they do change CheckAndUpdateBasedOnContractTimes( ); // handle flashing of assignment strings when merc's assignment is done HandleAssignmentsDoneAndAwaitingFurtherOrders( ); // handle timing for the various glowing higlights HandleCommonGlowTimer( ); // are we attempting to plot a foot/vehicle path during aircraft mode..if so, stop it CheckIfPlottingForCharacterWhileAirCraft( ); // check to see if helicopter is available //CheckIfHelicopterAvailable( ); if( fShowMapInventoryPool ) { HandleFlashForHighLightedItem( ); } // CreateDestroyMovementBox( 0,0,0 ); // Deque all game events DequeAllGameEvents( TRUE ); // Handle Interface Stuff SetUpInterface( ); // reset time compress has occured ResetTimeCompressHasOccured( ); // handle change in info char HandleChangeOfInfoChar( ); // update status of contract box UpDateStatusOfContractBox( ); // error check of assignments UpdateBadAssignments( ); // if cursor has left map..will need to update temp path plotting and cursor CheckToSeeIfMouseHasLeftMapRegionDuringPathPlotting( ); // update assignment menus and submenus HandleShadingOfLinesForAssignmentMenus( ); // check which menus can be shown right now DetermineWhichAssignmentMenusCanBeShown( ); DetermineWhichMilitiaControlMenusCanBeShown( ); //lal // determine if contract menu can be shown DetermineIfContractMenuCanBeShown( ); // if pre battle and inventory up?..get rid of inventory HandlePreBattleInterfaceWithInventoryPanelUp( ); // create destroy trash can region if (!isWidescreenUI()) { CreateDestroyTrashCanRegion(); // update these buttons UpdateStatusOfMapSortButtons( ); } // if in inventory mode, make sure it's still ok CheckForInventoryModeCancellation(); // restore background rects RestoreBackgroundRects( ); InterruptTimeForMenus( ); #ifdef JA2UB //JA25 UB //Handle Jerry Milo quotes if ( gGameUBOptions.JerryQuotes == TRUE ) HandleJerryMiloQuotes( FALSE ); #endif // place down background BlitBackgroundToSaveBuffer( ); if( fLeavingMapScreen == TRUE ) { #ifdef JA2UB //JA25 UB //specify that we are leaving mapscreen if ( gGameUBOptions.JerryQuotes == TRUE ) HandleJerryMiloQuotes( TRUE ); #endif return( MAP_SCREEN ); } if( fDisableDueToBattleRoster == FALSE ) { /* // ATE: OK mark is rendering the item every frame - which isn't good // however, don't want to break the world here.. // this line was added so that when the ItemGlow() is on, // we're not rendering also, else glow looks bad if ( !fShowItemHighLight ) { RenderHandPosItem(); } */ if( fDrawCharacterList ) { if ( !fShowInventoryFlag ) { // if we are not in inventory mode, show character list HandleHighLightingOfLinesInTeamPanel( ); DisplayCharacterList(); } fDrawCharacterList = FALSE; } } if( !fShowMapInventoryPool && !gfPauseDueToPlayerGamePause && !IsMapScreenHelpTextUp( ) ) { RenderMapCursorsIndexesAnims( ); } if( fDisableDueToBattleRoster == FALSE ) { // render status bar HandleCharBarRender( ); } if( ( fShowInventoryFlag || fDisableDueToBattleRoster ) && !isWidescreenUI() ) { for( iCounter = 0; iCounter < MAX_SORT_METHODS; iCounter++ ) { UnMarkButtonDirty( giMapSortButton[ iCounter ] ); } } if( fShowContractMenu || fDisableDueToBattleRoster ) { UnMarkButtonDirty( giMapContractButton ); } // handle any old messages ScrollString( ); HandleSpontanousTalking( ); if( ( fDisableDueToBattleRoster == FALSE ) ) { // remove the move box once user leaves it CreateDestroyMovementBox( 0,0,0 ); // this updates the move box contents when changes took place ReBuildMoveBox( ); } if( ( fDisableDueToBattleRoster == FALSE )&&( ( fShowAssignmentMenu == TRUE )||( fShowContractMenu == TRUE ) ) ) { // highlight lines? HandleHighLightingOfLinesInTeamPanel( ); // render glow for contract region ContractBoxGlow( ); GlowTrashCan( ); // handle changing of highlighted lines HandleChangeOfHighLightedLine( ); } if( fDisableDueToBattleRoster == FALSE ) { // render face of current info char, for animation DrawFace( bSelectedInfoChar ); // handle autofaces HandleAutoFaces( ); HandleTalkingAutoFaces( ); /* GlowFace( ); GlowItem( ); */ } // automatically turns off mapscreen ui overlay messages when appropriate MonitorMapUIMessage( ); // if heli is around, show it if ( fHelicopterAvailable && ( (gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE || gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE_COLOURED_SAMS) || fShowTeamFlag) && (iCurrentMapSectorZ == 0) && !fShowMapInventoryPool ) { // this is done on EVERY frame, I guess it beats setting entire map dirty all the time while he's moving... DisplayPositionOfHelicopter( ); } // Flugente: enemy helicopter if ( (gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE || gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE_COLOURED_SAMS) && (iCurrentMapSectorZ == 0) && !fShowMapInventoryPool ) { DisplayPositionOfEnemyHelicopter(); } // Flugente: intel else if ( gusMapDisplayColourMode == MAP_DISPLAY_INTEL && !fShowMapInventoryPool ) { extern void ShowIntelOnMap(); ShowIntelOnMap(); } // display town info DisplayTownInfo( sSelMapX, sSelMapY, ( INT8 ) iCurrentMapSectorZ ); if( fShowTownInfo == TRUE ) { // force update of town mine info boxes ForceUpDateOfBox( ghTownMineBox ); MapscreenMarkButtonsDirty(); } // update town mine pop up display UpdateTownMinePopUpDisplay( ); if( fShowAttributeMenu ) { // mark all popups as dirty MarkAllBoxesAsAltered( ); } // if plotting path if ( ( GetSelectedDestChar() != -1) || fPlotForHelicopter || fPlotForMilitia ) { // plot out paths PlotPermanentPaths( ); PlotTemporaryPaths( ); // show ETA RenderMapBorderEtaPopUp( ); DisplayGroundEta(); //DisplayDestinationOfCurrentDestMerc( ); } HandleContractRenewalSequence( ); // handle display of inventory pop up // HEADROCK HAM 3.5: Externalize! HandleDisplayOfItemPopUpForSector( gGameExternalOptions.ubDefaultArrivalSectorX, gGameExternalOptions.ubDefaultArrivalSectorY, startingZ ); // Display Framerate DisplayFrameRate( ); // update paused states UpdatePausedStatesDueToTimeCompression( ); // is there a description to be displayed? // BOB : if we're displaying the attachment popup, don't redraw the IDB if (giActiveAttachmentPopup > -1) { gItemDescAttachmentPopups[giActiveAttachmentPopup]->show(); } // HEADROCK HAM 5: So... we need a separate case for each popup that we have? That's not too bright. else if (gfItemDescTransformPopupVisible) { gItemDescTransformPopup->show(); } else { RenderItemDescriptionBox( ); } // render clock // WANNE: Renders the clock in the strategy screen RenderClock(INTERFACE_CLOCK_X, INTERFACE_CLOCK_Y); #ifdef JA2TESTVERSION if( !gfWorldLoaded ) { SetFont( FONT10ARIAL ); if( GetJA2Clock() % 1000 < 500 ) SetFontForeground( FONT_DKRED ); else SetFontForeground( FONT_RED ); mprintf( SCREEN_WIDTH - 110, 2, L"TESTVERSION MSG" ); if( GetJA2Clock() % 1000 < 500 ) SetFontForeground( FONT_DKYELLOW ); else SetFontForeground( FONT_YELLOW ); mprintf( SCREEN_WIDTH - 110, 12, L"NO WORLD LOADED" ); InvalidateRegion( SCREEN_WIDTH - 110, 2, SCREEN_WIDTH, 23 ); } #endif if( fEndShowInventoryFlag == TRUE ) { if( InKeyRingPopup( ) == TRUE ) { DeleteKeyRingPopup( ); } else { fShowInventoryFlag = FALSE; // CHRISL: Added call to re-render the bottom panel RenderMapScreenInterfaceBottom ( TRUE ); // set help text for item glow region SetRegionFastHelpText( &gCharInfoHandRegion, pMiscMapScreenMouseRegionHelpText[ 0 ] ); } fCharacterInfoPanelDirty=TRUE; fMapPanelDirty = TRUE; fMapScreenBottomDirty = TRUE; fTeamPanelDirty = TRUE; fEndShowInventoryFlag = FALSE; } // handle animated cursor update if ( !gfFadeIn ) { HandleAnimatedCursorsForMapScreen( ); } // if inventory is being manipulated, update cursor HandleMapInventoryCursor(); if( fShowDescriptionFlag == TRUE ) { // unmark done button if( gpItemDescObject->usItem == MONEY ) { MapscreenMarkButtonsDirty(); } if( Item[ gpItemDescObject->usItem ].usItemClass & IC_GUN ) { MapscreenMarkButtonsDirty(); } UnMarkButtonDirty( giMapInvDoneButton ); //UnMarkButtonDirty( giCharInfoButton[ 0 ] ); //UnMarkButtonDirty( giCharInfoButton[ 1 ] ); MarkAButtonDirty( giMapInvDescButton ); // HEADROCK HAM 4: Makes sure the Tab Buttons are always redrawn on top. for (UINT8 cnt = 0; cnt < 3; cnt++) { if (giInvDescTabButton[cnt] != -1) { MarkAButtonDirty( giInvDescTabButton[ cnt ] ); } } } else { if( fShowInventoryFlag == TRUE ) { MarkAButtonDirty( giMapInvDoneButton ); MarkAButtonDirty( giCharInfoButton[ 1 ] ); MarkAButtonDirty( giCharInfoButton[ 0 ] ); } } DrawMilitiaPopUpBox( ); DisplayMilitiaGroupBox(); if( fDisableDueToBattleRoster == FALSE ) { CreateDestroyTheUpdateBox( ); DisplaySoldierUpdateBox( ); } // pop up display boxes DisplayBoxes(FRAME_BUFFER); // render buttons RenderButtons( ); if( fShowMapScreenMovementList ) { // redisplay Movement box to blit it over any border buttons, since if long enough it can overlap them ForceUpDateOfBox( ghMoveBox ); DisplayOnePopupBox( ghMoveBox, FRAME_BUFFER ); } if( fShowContractMenu ) { // redisplay Contract box to blit it over any map sort buttons, since they overlap ForceUpDateOfBox( ghContractBox ); DisplayOnePopupBox( ghContractBox, FRAME_BUFFER ); } //If we have new email, blink the email icon on top of the laptop button. CheckForAndRenderNewMailOverlay(); // handle video overlays ExecuteVideoOverlays( ); if ( InItemStackPopup( ) || InSectorStackPopup( ) ) { RenderItemStackPopup( FALSE ); } if( InKeyRingPopup() ) { RenderKeyRingPopup( FALSE ); } #ifdef JA2UB /* UB */ #else CheckForMeanwhileOKStart( ); #endif // save background rects // ATE: DO this BEFORE rendering help text.... SaveBackgroundRects( ); if( ( fDisableDueToBattleRoster == FALSE ) && ( fShowAssignmentMenu == FALSE )&&( fShowContractMenu == FALSE ) ) { // highlight lines? HandleHighLightingOfLinesInTeamPanel( ); // render glow for contract region ContractBoxGlow( ); GlowTrashCan( ); // handle changing of highlighted lines HandleChangeOfHighLightedLine( ); GlowFace( ); GlowItem( ); } if( fShowMapScreenHelpText ) { // display map screen fast help DisplayMapScreenFastHelpList( ); } else { // render help RenderButtonsFastHelp( ); } /* if( fSecondFrame ) { if( gTacticalStatus.fDidGameJustStart ) { // game just started, check what state player is in...... HandlePlayerEnteringMapScreenBeforeGoingToTactical( ); } } fSecondFrame = FALSE; */ // execute dirty ExecuteBaseDirtyRectQueue( ); // update cursor UpdateCursorIfInLastSector( ); // about to leave for new map if ( gfLoadPending == 1 ) { gfLoadPending++; // Shade this frame! // Remove cursor SetCurrentCursorFromDatabase( VIDEO_NO_CURSOR ); //Shadow area ShadowVideoSurfaceRect( FRAME_BUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT ); InvalidateScreen( ); } //InvalidateRegion( 0,0, 640, 480); EndFrameBufferRender( ); // handle dialog HandleDialogue(); // if not going anywhere else if ( guiPendingScreen == NO_PENDING_SCREEN ) { if ( HandleFadeInCallback( ) ) { // force mapscreen to be reinitialized even though we're already in it EndMapScreen( TRUE ); } if ( HandleBeginFadeIn( MAP_SCREEN ) ) { } } HandlePreBattleInterfaceStates(); if( gfHotKeyEnterSector ) { gfHotKeyEnterSector = FALSE; ActivatePreBattleEnterSectorAction(); } #ifdef JA2BETAVERSION DebugValidateSoldierData( ); #endif if ( gfRequestGiveSkyriderNewDestination ) { RequestGiveSkyriderNewDestination(); gfRequestGiveSkyriderNewDestination = FALSE; } if( gfFirstMapscreenFrame ) { // fSecondFrame = TRUE; gfFirstMapscreenFrame = FALSE; } else { // handle exiting from mapscreen due to both exit button clicks and keyboard equivalents HandleExitsFromMapScreen( ); } #ifdef JA2UB //Ja25 ub //Handle the strategic AI JA25_HandleUpdateOfStrategicAi(); //Should the msg box come up telling the user that they lost? if (gGameUBOptions.InGameHeliCrash == TRUE ) HandleWhenPlayerHasNoMercsAndNoLaptop(); //AA #endif return( MAP_SCREEN ); } void DrawString(STR16 pString, UINT16 uiX, UINT16 uiY, UINT32 uiFont) { // draw monochrome string SetFont(uiFont); gprintfdirty(uiX,uiY,pString); mprintf(uiX,uiY,pString); } void SetDayAlternate(STR16 pStringA, ...) { // this sets the clock counter, unwind loop UINT16 uiX=0; UINT16 uiY=0; CHAR16 String[80]; va_list argptr; va_start(argptr, pStringA); // Set up variable argument pointer vswprintf(String, pStringA, argptr); // process gprintf string (get output str) va_end(argptr); if (String[1]==0) { String[1]=String[0]; String[0]=L' '; } String[2]=gsTimeStrings[ 3 ][ 0 ]; String[3]=L' '; String[4]=0; uiX= UI_MAP.ETA.Hour_X - 9; uiY= UI_MAP.ETA.Start_Y; SetFont( ETA_FONT ); SetFontForeground( FONT_LTGREEN ); SetFontBackground( FONT_BLACK ); mprintf( uiX, uiY, String ); } void SetHourAlternate(STR16 pStringA, ...) { // this sets the clock counter, unwind loop UINT16 uiX=0; UINT16 uiY=0; CHAR16 String[80]; va_list argptr; va_start(argptr, pStringA); // Set up variable argument pointer vswprintf(String, pStringA, argptr); // process gprintf string (get output str) va_end(argptr); if (String[1]==0) { String[1]=String[0]; String[0]=L' '; } String[2]=gsTimeStrings[ 0 ][ 0 ]; String[3]=L' '; String[4]= 0; uiX = UI_MAP.ETA.Min_X - 5; uiY = UI_MAP.ETA.Start_Y; DrawString(String, uiX, uiY, ETA_FONT); SetFont( ETA_FONT ); SetFontForeground( FONT_LTGREEN ); SetFontBackground( FONT_BLACK ); mprintf( uiX, uiY, String ); } void SetClockHour(STR16 pStringA, ...) { // this sets the clock counter, unwind loop UINT16 uiX=0; UINT16 uiY=0; CHAR16 String[80]; va_list argptr; va_start(argptr, pStringA); // Set up variable argument pointer vswprintf(String, pStringA, argptr); // process gprintf string (get output str) va_end(argptr); if (String[1]==0) { String[1]=String[0]; String[0]=L' '; } String[2]=gsTimeStrings[ 0 ][ 0 ]; String[3]=L' '; String[4]=0; uiX = UI_MAP.ETA.Hour_X - 8; uiY = UI_MAP.ETA.Start_Y; SetFont( ETA_FONT ); SetFontForeground( FONT_LTGREEN ); SetFontBackground( FONT_BLACK ); mprintf( uiX, uiY, String ); } void SetClockMin(STR16 pStringA, ...) { // this sets the clock counter, unwind loop CHAR16 String[10]; va_list argptr; va_start(argptr, pStringA); // Set up variable argument pointer vswprintf(String, pStringA, argptr); // process gprintf string (get output str) va_end(argptr); if (String[1]==0) { String[1]=String[0]; String[0]=L' '; } String[2]=gsTimeStrings[ 1 ][ 0 ]; String[3]=L' '; String[4]=0; SetFont( ETA_FONT ); SetFontForeground( FONT_LTGREEN ); SetFontBackground( FONT_BLACK ); mprintf(UI_MAP.ETA.Min_X - 5, UI_MAP.ETA.Start_Y, String ); } void DrawName(STR16 pName, INT16 sRowIndex, INT32 iFont) { INT16 usX=0; INT16 usY=0; const auto x = UI_CHARLIST.xName + 1; const auto y = UI_CHARLIST.y + (sRowIndex * Y_SIZE); const auto yOffset = UI_CHARLIST.yOffset; const auto width = UI_CHARLIST.widthName; FindFontCenterCoordinates(x, y, width, (short)Y_SIZE, pName, (long)iFont, &usX, &usY); DrawString( pName, (UINT16)usX, ((UINT16)(usY+(yOffset*sRowIndex+1))), iFont); } void DrawAssignment(INT16 sCharNumber, INT16 sRowIndex, INT32 iFont) { INT16 usX=0; INT16 usY=0; CHAR16 sString[32]; SOLDIERTYPE* pSoldier = gCharactersList[sCharNumber].usSolID; GetMapscreenMercAssignmentString( pSoldier, sString ); FindFontCenterCoordinates((short)UI_CHARLIST.xAssignment + 1, (short)(UI_CHARLIST.y + (sRowIndex*Y_SIZE)), (short)UI_CHARLIST.widthAssignment, (short)Y_SIZE, sString, (long)iFont, &usX, &usY); if( fFlashAssignDone == TRUE ) { if( pSoldier->flags.fDoneAssignmentAndNothingToDoFlag ) { SetFontForeground( FONT_RED ); } } if ( pSoldier->bAssignment >= TRAIN_SELF && pSoldier->bAssignment <= TRAIN_BY_OTHER && pSoldier->bAssignment != TRAIN_TEAMMATE ) { // HEADROCK HAM 3.6: Draw militia training progress bar UINT32 uiDestBuffer; UINT8 *pDestBuf; UINT32 uiDestPitchBYTES = 0; SGPRect ClipRect; UINT8 ubBarWidth; UINT16 usColor = Get16BPPColor( FROMRGB( gGameExternalOptions.ubStatProgressBarsRed, gGameExternalOptions.ubStatProgressBarsGreen, gGameExternalOptions.ubStatProgressBarsBlue ) ); if( ( fShowAssignmentMenu == TRUE ) && ( fTeamPanelDirty == FALSE ) ) { uiDestBuffer = FRAME_BUFFER; } else { uiDestBuffer = guiSAVEBUFFER; } pDestBuf = LockVideoSurface( uiDestBuffer, &uiDestPitchBYTES ); UINT8 ubProgress = 0; UINT16 usMaxProgress = 100; UINT8 sMapX = (UINT8)pSoldier->sSectorX; UINT8 sMapY = (UINT8)pSoldier->sSectorY; if ( pSoldier->bAssignment == TRAIN_TOWN ) { ubProgress = SectorInfo[SECTOR(sMapX, sMapY)].ubMilitiaTrainingPercentDone; usMaxProgress = 100; } else if ( pSoldier->bAssignment == TRAIN_SELF || pSoldier->bAssignment == TRAIN_BY_OTHER ) { switch (pSoldier->bTrainStat) { case STRENGTH: ubProgress = gMercProfiles[ pSoldier->ubProfile ].sStrengthGain+1; usMaxProgress = gGameExternalOptions.usStrengthSubpointsToImprove; break; case AGILITY: ubProgress = gMercProfiles[ pSoldier->ubProfile ].sAgilityGain+1; usMaxProgress = gGameExternalOptions.usAgilitySubpointsToImprove; break; case DEXTERITY: ubProgress = gMercProfiles[ pSoldier->ubProfile ].sDexterityGain+1; usMaxProgress = gGameExternalOptions.usDexteritySubpointsToImprove; break; case HEALTH: ubProgress = gMercProfiles[ pSoldier->ubProfile ].sLifeGain+1; usMaxProgress = gGameExternalOptions.usHealthSubpointsToImprove; break; case MARKSMANSHIP: ubProgress = gMercProfiles[ pSoldier->ubProfile ].sMarksmanshipGain+1; usMaxProgress = gGameExternalOptions.usMarksmanshipSubpointsToImprove; break; case LEADERSHIP: ubProgress = gMercProfiles[ pSoldier->ubProfile ].sLeadershipGain+1; usMaxProgress = gGameExternalOptions.usLeadershipSubpointsToImprove; break; case MECHANICAL: ubProgress = gMercProfiles[ pSoldier->ubProfile ].sMechanicGain+1; usMaxProgress = gGameExternalOptions.usMechanicalSubpointsToImprove; break; case MEDICAL: ubProgress = gMercProfiles[ pSoldier->ubProfile ].sMedicalGain+1; usMaxProgress = gGameExternalOptions.usMedicalSubpointsToImprove; break; case EXPLOSIVE_ASSIGN: ubProgress = gMercProfiles[ pSoldier->ubProfile ].sExplosivesGain+1; usMaxProgress = gGameExternalOptions.usExplosivesSubpointsToImprove; break; } } ubBarWidth = (UI_CHARLIST.widthAssignment * ubProgress) / usMaxProgress; ubBarWidth = __max(0, __min(ubBarWidth, UI_CHARLIST.widthAssignment)); ClipRect.iTop = (usY+(UI_CHARLIST.yOffset *sRowIndex+1))-1; ClipRect.iBottom = ClipRect.iTop + Y_SIZE; ClipRect.iLeft = UI_CHARLIST.xAssignment + 2; ClipRect.iRight = UI_CHARLIST.xAssignment + ubBarWidth; Blt16BPPBufferHatchRectWithColor( (UINT16*)pDestBuf, uiDestPitchBYTES, &ClipRect, usColor ); UnLockVideoSurface( uiDestBuffer ); } DrawString(sString, (UINT16)usX, ((UINT16)(usY+(UI_CHARLIST.yOffset *sRowIndex+1))), iFont); } void DrawLocation(INT16 sCharNumber, INT16 sRowIndex, INT32 iFont) { INT16 usX=0; INT16 usY=0; CHAR16 sString[32]; GetMapscreenMercLocationString( gCharactersList[ sCharNumber ].usSolID, sString ); FindFontCenterCoordinates((short)UI_CHARLIST.xLocation + 1, (short)(UI_CHARLIST.y + (sRowIndex*Y_SIZE)), (short)UI_CHARLIST.widthLocation, (short)Y_SIZE, sString, (long)iFont, &usX, &usY); // draw string DrawString( sString,((UINT16)(usX)), ((UINT16)(usY+(UI_CHARLIST.yOffset *sRowIndex+1))), ((UINT32)iFont)); } void DrawDestination(INT16 sCharNumber, INT16 sRowIndex, INT32 iFont) { INT16 usX=0; INT16 usY=0; CHAR16 sString[32]; GetMapscreenMercDestinationString( gCharactersList[ sCharNumber ].usSolID, sString ); if ( wcslen( sString ) == 0 ) { return; } FindFontCenterCoordinates((short)UI_CHARLIST.xETA + 1, (short)(UI_CHARLIST.y + (sRowIndex*Y_SIZE)), (short)UI_CHARLIST.widthETA, (short)Y_SIZE, sString, (long)iFont, &usX, &usY); DrawString( sString,((UINT16)(usX)), ((UINT16)(usY+(UI_CHARLIST.yOffset *sRowIndex+1))), ((UINT32)iFont)); } void DrawTimeRemaining( INT16 sCharNumber, INT32 iFont, UINT8 ubFontColor ) { INT16 usX=0; INT16 usY=0; CHAR16 sString[32]; // marke strogg more mercs MUST override pointer into array by number of skipped mercs GetMapscreenMercDepartureString( gCharactersList[ sCharNumber + FIRSTmercTOdisplay ].usSolID, sString, &ubFontColor ); // if merc is highlighted, override the color decided above with bright white if( sCharNumber == ( INT16 ) giHighLine ) { ubFontColor = FONT_WHITE; } SetFont(iFont); SetFontForeground( ubFontColor ); FindFontCenterCoordinates((short)UI_CHARLIST.xTimeRemaining + 1, (short)(UI_CHARLIST.y + (sCharNumber*Y_SIZE)), (short)UI_CHARLIST.widthTimeRemaining, (short)Y_SIZE, sString, (long)iFont, &usX, &usY); DrawString(sString,((UINT16)(usX)), ((UINT16)(usY+(UI_CHARLIST.yOffset *sCharNumber+1))), ((UINT32)iFont)); } void RenderMapCursorsIndexesAnims( ) { BOOLEAN fSelectedSectorHighlighted = FALSE; BOOLEAN fSelectedCursorIsYellow = TRUE; UINT16 usCursorColor; UINT32 uiDeltaTime; static INT16 sPrevHighlightedMapX = -1, sPrevHighlightedMapY = -1; static INT16 sPrevSelectedMapX = -1, sPrevSelectedMapY = -1; static BOOLEAN fFlashCursorIsYellow = FALSE; BOOLEAN fDrawCursors; BOOLEAN fHighlightChanged = FALSE; HandleAnimationOfSectors( ); if( gfBlitBattleSectorLocator ) { HandleBlitOfSectorLocatorIcon( gubPBSectorX, gubPBSectorY, gubPBSectorZ, LOCATOR_COLOR_RED ); } fDrawCursors = CanDrawSectorCursor( ); // if mouse cursor is over a map sector if ( fDrawCursors && ( GetMouseMapXY( &gsHighlightSectorX, &gsHighlightSectorY ) ) ) { // handle highlighting of sector pointed at ( WHITE ) // if we're over a different sector than when we previously blitted this if ( ( gsHighlightSectorX != sPrevHighlightedMapX ) || ( gsHighlightSectorY != sPrevHighlightedMapY ) || gfMapPanelWasRedrawn ) { if ( sPrevHighlightedMapX != -1 && sPrevHighlightedMapY != -1 ) { RestoreMapSectorCursor( sPrevHighlightedMapX, sPrevHighlightedMapY ); } // draw WHITE highlight rectangle RenderMapHighlight( gsHighlightSectorX, gsHighlightSectorY, Get16BPPColor( RGB_WHITE ), FALSE ); sPrevHighlightedMapX = gsHighlightSectorX; sPrevHighlightedMapY = gsHighlightSectorY; fHighlightChanged = TRUE; } } else { // nothing now highlighted gsHighlightSectorX = -1; gsHighlightSectorY = -1; if ( sPrevHighlightedMapX != -1 && sPrevHighlightedMapY != -1 ) { RestoreMapSectorCursor( sPrevHighlightedMapX, sPrevHighlightedMapY ); fHighlightChanged = TRUE; } sPrevHighlightedMapX = -1; sPrevHighlightedMapY = -1; } // handle highlighting of selected sector ( YELLOW ) - don't show it while plotting movement if ( fDrawCursors && ( GetSelectedDestChar() == -1) && !fPlotForHelicopter && !fPlotForMilitia ) { // if mouse cursor is over the currently selected sector if( ( gsHighlightSectorX == sSelMapX ) && ( gsHighlightSectorY == sSelMapY ) ) { fSelectedSectorHighlighted = TRUE; // do we need to flash the cursor? get the delta in time uiDeltaTime = GetJA2Clock( ) - guiFlashCursorBaseTime; if ( uiDeltaTime > 300 ) { guiFlashCursorBaseTime = GetJA2Clock(); fFlashCursorIsYellow = !fFlashCursorIsYellow; fHighlightChanged = TRUE; } } if ( !fSelectedSectorHighlighted || fFlashCursorIsYellow ) { // draw YELLOW highlight rectangle usCursorColor = Get16BPPColor( RGB_YELLOW ); } else { // draw WHITE highlight rectangle usCursorColor = Get16BPPColor( RGB_WHITE ); // index letters will also be white instead of yellow so that they flash in synch with the cursor fSelectedCursorIsYellow = FALSE; } // always render this one, it's too much of a pain detecting overlaps with the white cursor otherwise RenderMapHighlight( sSelMapX, sSelMapY, usCursorColor, TRUE ); if ( ( sPrevSelectedMapX != sSelMapX ) || ( sPrevSelectedMapY != sSelMapY ) ) { sPrevSelectedMapX = sSelMapX; sPrevSelectedMapY = sSelMapY; fHighlightChanged = TRUE; } } else { // erase yellow highlight cursor if ( sPrevSelectedMapX != -1 && sPrevSelectedMapY != -1 ) { RestoreMapSectorCursor( sPrevSelectedMapX, sPrevSelectedMapY ); fHighlightChanged = TRUE; } sPrevSelectedMapX = -1; sPrevSelectedMapY = -1; } if ( fHighlightChanged || gfMapPanelWasRedrawn ) { // redraw sector index letters and numbers DrawMapIndexBigMap( fSelectedCursorIsYellow ); } } UINT32 HandleMapUI( ) { UINT32 uiNewEvent = MAP_EVENT_NONE; INT16 sMapX = 0, sMapY = 0; INT16 sX, sY; POINT MousePos; UINT32 uiNewScreen = MAP_SCREEN; BOOLEAN fWasAlreadySelected; // Get Input from keyboard GetMapKeyboardInput( &uiNewEvent ); if (!isWidescreenUI()) { CreateDestroyMapInvButton(); } // Get mouse PollLeftButtonInMapView( &uiNewEvent ); PollRightButtonInMapView( &uiNewEvent ); PollWheelInMapView(&uiNewEvent); // Switch on event switch( uiNewEvent ) { case MAP_EVENT_NONE: break; case MAP_EVENT_PLOT_PATH: GetMouseMapXY(&sMapX, &sMapY); // plotting for the chopper? if( fPlotForHelicopter ) { if( IsSectorOutOfTheWay( sMapX, sMapY ) ) { if( gfAllowSkyriderTooFarQuote ) { SkyRiderTalk( DESTINATION_TOO_FAR ); } return( MAP_SCREEN ); } PlotPathForHelicopter( sMapX, sMapY ); fTeamPanelDirty = TRUE; } else if ( fPlotForMilitia ) { /*f ( IsSectorOutOfTheWay( sMapX, sMapY ) ) { if ( gfAllowSkyriderTooFarQuote ) { SkyRiderTalk( DESTINATION_TOO_FAR ); } return(MAP_SCREEN); }*/ PlotPathForMilitia( sMapX, sMapY ); fTeamPanelDirty = TRUE; } else { // plot for character // check for valid character Assert ( GetSelectedDestChar() != -1 ); if ( GetSelectedDestChar() == -1 ) break; // check if last sector in character's path is same as where mouse is if( GetLastSectorIdInCharactersPath( gCharactersList[GetSelectedDestChar()].usSolID ) != CALCULATE_STRATEGIC_INDEX( sMapX, sMapY ) ) { sX = ( GetLastSectorIdInCharactersPath( gCharactersList[GetSelectedDestChar()].usSolID ) % MAP_WORLD_X ); sY = ( GetLastSectorIdInCharactersPath( gCharactersList[GetSelectedDestChar()].usSolID ) / MAP_WORLD_X ); GetCursorPos(&MousePos); ScreenToClient(ghWindow, &MousePos); // In window coords! RestoreBackgroundForMapGrid( sX, sY ); // fMapPanelDirty = TRUE; } //SetFontDestBuffer( FRAME_BUFFER, 0, 0, 640, 480, FALSE ); if( ( IsTheCursorAllowedToHighLightThisSector( sMapX, sMapY ) == TRUE ) && ( SectorInfo[ ( SECTOR( sMapX, sMapY ) ) ].ubTraversability[ THROUGH_STRATEGIC_MOVE ] != GROUNDBARRIER ) ) { // Can we get go there? (NULL temp character path) if ( GetLengthOfPath( pTempCharacterPath ) > 0 ) { PlotPathForCharacter( gCharactersList[GetSelectedDestChar()].usSolID, sMapX, sMapY, FALSE ); // copy the path to every other selected character CopyPathToAllSelectedCharacters( GetSoldierMercPathPtr( gCharactersList[GetSelectedDestChar()].usSolID ) ); StartConfirmMapMoveMode( sMapY ); fMapPanelDirty = TRUE; fTeamPanelDirty = TRUE; // update team panel desinations } else { // means it's a vehicle and we've clicked an off-road sector MapScreenMessage( FONT_MCOLOR_LTYELLOW, MSG_MAP_UI_POSITION_MIDDLE, pMapErrorString[ 40 ] ); } } } break; case MAP_EVENT_CANCEL_PATH: CancelOrShortenPlottedPath( ); break; /* case MAP_EVENT_SELECT_SECTOR: // will select the sector the selected merc is in sMapX=gCharactersList[bSelectedInfoChar].usSolID.sSectorX; sMapY=gCharactersList[bSelectedInfoChar].usSolID.sSectorY; bMapZ=gCharactersList[bSelectedInfoChar].usSolID.bSectorZ; if( ( sSelMapX != sMapX || sSelMapY != sMapY || iCurrentMapSectorZ != bMapZ ) && ( gTacticalStatus.fDidGameJustStart == FALSE ) && ( gfPreBattleInterfaceActive == FALSE ) ) { ChangeSelectedMapSector( sMapX, sMapY, bMapZ ); fTeamPanelDirty = TRUE; fMapScreenBottomDirty = TRUE; bSelectedDestChar=-1; } break; */ case MAP_EVENT_CLICK_SECTOR: // Get Current mouse position if ( GetMouseMapXY( &sMapX, &sMapY) ) { // make sure this is a valid sector if( IsTheCursorAllowedToHighLightThisSector( sMapX, sMapY ) == FALSE ) { // do nothing, return return( MAP_SCREEN ); } // while item in hand if ( fMapInventoryItem ) { // if not showing item counts on the map if ( !fShowItemsFlag ) { // turn that on ToggleItemsFilter( ); } // if item's owner is known if ( gpItemPointerSoldier != NULL ) { // make sure it's the owner's sector that's selected if ( ( gpItemPointerSoldier->sSectorX != sSelMapX ) || ( gpItemPointerSoldier->sSectorY != sSelMapY ) || ( gpItemPointerSoldier->bSectorZ != iCurrentMapSectorZ ) ) { ChangeSelectedMapSector( gpItemPointerSoldier->sSectorX, gpItemPointerSoldier->sSectorY, gpItemPointerSoldier->bSectorZ ); } } // if not already in sector inventory if ( !fShowMapInventoryPool ) { // start it up ( NOTE: for the item OWNER'S sector, regardless of which sector player clicks ) fShowMapInventoryPool = TRUE; CreateDestroyMapInventoryPoolButtons( TRUE ); } return( MAP_SCREEN ); } // don't permit other click handling while item is in cursor (entering PBI would permit item teleports, etc.) Assert( !fMapInventoryItem ); // this doesn't change selected sector if ( gfInChangeArrivalSectorMode ) { if( SectorInfo[ ( SECTOR( sMapX, sMapY ) ) ].ubTraversability[ THROUGH_STRATEGIC_MOVE ] != GROUNDBARRIER ) { // if it's not enemy air controlled if ( !(StrategicMap[CALCULATE_STRATEGIC_INDEX( sMapX, sMapY )].usAirType & AIRSPACE_ENEMY_ACTIVE) ) { CHAR16 sMsgString[ 128 ], sMsgSubString[ 64 ]; // move the landing zone over here gsMercArriveSectorX = sMapX; gsMercArriveSectorY = sMapY; // change arrival sector for all mercs currently in transit who are showing up at the landing zone UpdateAnyInTransitMercsWithGlobalArrivalSector(); // we're done, cancel this mode CancelChangeArrivalSectorMode(); // get the name of the sector GetSectorIDString( sMapX, sMapY, 0, sMsgSubString, FALSE ); // now build the string swprintf( sMsgString, pBullseyeStrings[ 1 ], sMsgSubString ); // confirm the change with overlay message MapScreenMessage( FONT_MCOLOR_LTYELLOW, MSG_MAP_UI_POSITION_MIDDLE, sMsgString ); // update destination column for any mercs in transit fTeamPanelDirty = TRUE; // added by haydent if (is_networked) { ChangeSelectedMapSector( sMapX, sMapY, ( INT8 )iCurrentMapSectorZ ); // OJW - 20081201 - change this state away from allowlaptop to its own field // or something more seperate from that concept if (is_server && !allowlaptop) { InitializeWorldSize(sMapX, sMapY, 0); send_mapchange(); } } } else { // message: not allowed, don't have airspace secured MapScreenMessage( FONT_MCOLOR_LTYELLOW, MSG_MAP_UI_POSITION_MIDDLE, pBullseyeStrings[ 2 ] ); } } return( MAP_SCREEN ); } else // not already changing arrival sector { if ( CanMoveBullseyeAndClickedOnIt( sMapX, sMapY ) ) { // if the click is ALSO over the helicopter icon // NOTE: The helicopter icon is NOT necessarily directly over the helicopter's current sector!!! if( CheckForClickOverHelicopterIcon( sMapX, sMapY ) == TRUE ) { CreateBullsEyeOrChopperSelectionPopup(); } else { StartChangeSectorArrivalMode(); } return( MAP_SCREEN ); } } // if new map sector was clicked on if( ( sSelMapX != sMapX ) || ( sSelMapY != sMapY ) ) { fWasAlreadySelected = FALSE; // select the clicked sector, retaining the same sublevel depth ChangeSelectedMapSector( sMapX, sMapY, ( INT8 )iCurrentMapSectorZ ); } else { fWasAlreadySelected = TRUE; } // if showing item counts on the map, and not already in sector inventory if ( fShowItemsFlag && !fShowMapInventoryPool ) { // show sector inventory for this clicked sector ChangeSelectedMapSector( sMapX, sMapY, ( INT8 ) iCurrentMapSectorZ ); fShowMapInventoryPool = TRUE; CreateDestroyMapInventoryPoolButtons( TRUE ); return( MAP_SCREEN ); } if( gfBlitBattleSectorLocator && sMapX == gubPBSectorX && sMapY == gubPBSectorY && iCurrentMapSectorZ == gubPBSectorZ ) { //Bring up a non-persistant version of mapscreen if the user clicks on the sector where a //battle is taking place. InitPreBattleInterface( NULL, FALSE ); return( MAP_SCREEN ); } // if we're in airspace mode if ( gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE || gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE_COLOURED_SAMS ) { // if not moving soldiers, and not yet plotting the helicopter if ( ( GetSelectedDestChar() == -1) && !fPlotForHelicopter && !fPlotForMilitia ) { // if we're on the surface level, and the click is over the helicopter icon // NOTE: The helicopter icon is NOT necessarily directly over the helicopter's current sector!!! if( ( iCurrentMapSectorZ == 0 ) && CheckForClickOverHelicopterIcon( sMapX, sMapY ) == TRUE ) { RequestGiveSkyriderNewDestination( ); return( MAP_SCREEN ); } } } // Flugente: militia movement else if ( fShowMilitia ) { // if not moving soldiers, and not yet plotting the helicopter if ( ( GetSelectedDestChar() == -1) && !fPlotForHelicopter && !fPlotForMilitia ) { if ( !iCurrentMapSectorZ && NumNonPlayerTeamMembersInSector( sMapX, sMapY , MILITIA_TEAM) > 0 ) { // move this later on... //MilitiaPlotInit(); if ( RequestGiveMilitiaNewDestination( ) ) return(MAP_SCREEN); } } } else // not in airspace mode { // sector must be already selected to initiate movement plotting! This is to allow selecting sectors with // mercs in them without necessarily initiating movement right away. if( fWasAlreadySelected ) { // if there are any movable characters here if ( AnyMovableCharsInOrBetweenThisSector( sMapX, sMapY, ( INT8 )iCurrentMapSectorZ ) ) { // if showing the surface level map if( iCurrentMapSectorZ == 0 ) { TurnOnShowTeamsMode( ); // NOTE: must allow move box to come up, since there may be movable characters between sectors which are // unaffected by combat / hostiles / air raid in the sector proper itself!! // This also allows all strategic movement error handling to be centralized in CanCharacterMoveInStrategic() // start the move box menu SetUpMovingListsForSector( sMapX, sMapY, ( INT16 )iCurrentMapSectorZ ); } else { // no strategic movement is possible from underground sectors DoMapMessageBox( MSG_BOX_BASIC_STYLE, pMapErrorString[ 1 ], MAP_SCREEN, MSG_BOX_FLAG_OK, MapScreenDefaultOkBoxCallback ); return( MAP_SCREEN ); } } } } } break; //Kris -- added hook so I can access AIView in non-release mode. #ifdef JA2BETAVERSION case MAP_EVENT_VIEWAI: SetPendingNewScreen( AIVIEWER_SCREEN ); CreateDestroyMapInvButton(); break; #endif } // if we pressed something that will cause a screen change if ( guiPendingScreen != NO_PENDING_SCREEN ) { uiNewScreen = guiPendingScreen; } return( uiNewScreen ); } // WANNE - BMP: This method is used only for multiplayer void InitializeWorldSize(INT16 sSectorX, INT16 sSectorY , INT8 bSectorZ) { CHAR8 datFilename[ 50 ]; CHAR8 mapFilename[ 50 ]; UINT32 uiFileSize; INT8 *pBuffer; INT8 *pBufferHead; UINT32 uiBytesRead; UINT8 ubMinorMapVersion; FLOAT dMajorMapVersion; HWFILE hfile; GetMapFileName( sSectorX, sSectorY, bSectorZ, datFilename, TRUE, TRUE ); //Load the placeholder map if the real map doesn't exist. if( !MapExists((UINT8 *) datFilename ) ) { AssertMsg( 0, "Failed to load map file." ); } sprintf( mapFilename, "MAPS\\%s", datFilename ); // Open file hfile = FileOpen( mapFilename, FILE_ACCESS_READ, FALSE ); if ( !hfile ) { // Initialize with default "normal" map size SetWorldSize(OLD_WORLD_ROWS, OLD_WORLD_COLS); } else { //Get the file size and alloc one huge buffer for it. //We will use this buffer to transfer all of the data from. uiFileSize = FileGetSize( hfile ); pBuffer = (INT8*)MemAlloc( uiFileSize ); pBufferHead = pBuffer; FileRead( hfile, pBuffer, uiFileSize, &uiBytesRead ); FileClose( hfile ); // Read JA2 Version ID LOADDATA( &dMajorMapVersion, pBuffer, sizeof( FLOAT ) ); LOADDATA( &ubMinorMapVersion, pBuffer, sizeof( UINT8 ) ); if(dMajorMapVersion < 7.00) // old map - always 160x160 SetWorldSize(OLD_WORLD_ROWS, OLD_WORLD_COLS); else { INT32 iRowSize = 0, iColSize = 0; LOADDATA( &iRowSize, pBuffer, sizeof( INT32 ) ); LOADDATA( &iColSize, pBuffer, sizeof( INT32 ) ); SetWorldSize(iRowSize, iColSize); } } } void GetMapKeyboardInput( UINT32 *puiNewEvent ) { InputAtom InputEvent; INT8 bSquadNumber; UINT8 ubGroupId = 0; BOOLEAN fCtrl, fAlt; INT16 sMapX, sMapY; INT32 iCounter2 = 0; fCtrl = _KeyDown( CTRL ); fAlt = _KeyDown( ALT ); while( DequeueEvent( &InputEvent ) ) { if( InputEvent.usEvent == KEY_DOWN ) { // if game is paused because of player, unpause with any key if ( gfPauseDueToPlayerGamePause ) { HandlePlayerPauseUnPauseOfGame( ); continue; } if( IsMapScreenHelpTextUp() ) { // stop mapscreen text StopMapScreenHelpText( ); continue; } // handle for fast help text for interface stuff if( IsTheInterfaceFastHelpTextActive() ) { ShutDownUserDefineHelpTextRegions( ); } switch( InputEvent.usParam ) { case ESC: gfDontStartTransitionFromLaptop = TRUE; if( gfPreBattleInterfaceActive && !gfPersistantPBI ) { //Non persistant PBI. Allow ESC to close it and return to mapscreen. KillPreBattleInterface(); gpBattleGroup = NULL; return; } if ( gfInChangeArrivalSectorMode ) { CancelChangeArrivalSectorMode( ); MapScreenMessage( FONT_MCOLOR_LTYELLOW, MSG_MAP_UI_POSITION_MIDDLE, pBullseyeStrings[ 3 ] ); } // ESC cancels MAP UI messages, unless we're in confirm map move mode else if( ( giUIMessageOverlay != -1 ) && !gfInConfirmMapMoveMode ) { CancelMapUIMessage( ); } else if( IsMapScreenHelpTextUp( ) ) { StopMapScreenHelpText( ); } else if ( gpCurrentTalkingFace != NULL && gpCurrentTalkingFace->fTalking ) { // ATE: We want to stop speech if somebody is talking... StopAnyCurrentlyTalkingSpeech( ); } else if( fShowUpdateBox ) { if( fShowUpdateBox ) { EndUpdateBox( FALSE ); // stop time compression } } else if(fShowDescriptionFlag) { DeleteItemDescriptionBox( ); } // plotting movement? else if ( ( GetSelectedDestChar() != -1) || fPlotForHelicopter || fPlotForMilitia ) { AbortMovementPlottingMode( ); } else if( fShowAssignmentMenu ) { // dirty region fTeamPanelDirty = TRUE; fMapPanelDirty = TRUE; fCharacterInfoPanelDirty = TRUE; fShowAttributeMenu = FALSE; fShowFacilityAssignmentMenu = FALSE; gAssignMenuState = ASMENU_NONE; fShowAssignmentMenu = FALSE; giAssignHighLine = -1; // restore background to glow region RestoreBackgroundForAssignmentGlowRegionList( ); } else if( fShowContractMenu == TRUE ) { fShowContractMenu = FALSE; // restore contract glow region RestoreBackgroundForContractGlowRegionList( ); fTeamPanelDirty = TRUE; fCharacterInfoPanelDirty = TRUE; giContractHighLine = -1; } // in militia popup? else if( ( sSelectedMilitiaTown != 0 ) && ( sGreensOnCursor == 0 ) && ( sRegularsOnCursor == 0 ) && ( sElitesOnCursor == 0 ) ) { sSelectedMilitiaTown = 0; fMapPanelDirty = TRUE; } else if( fShowTownInfo == TRUE ) { fShowTownInfo = FALSE; CreateDestroyScreenMaskForAssignmentAndContractMenus( ); } else if( fShowDescriptionFlag ) { if( gMPanelRegion.Cursor != EXTERN_CURSOR ) { DeleteItemDescriptionBox( ); } } else if( InKeyRingPopup( ) == TRUE ) { DeleteKeyRingPopup( ); fTeamPanelDirty = TRUE; } else if( fShowMapInventoryPool == TRUE ) { // no item on cursor & not in either stack popup if( gMPanelRegion.Cursor != EXTERN_CURSOR && !InSectorStackPopup() && !InItemStackPopup() ) { fShowMapInventoryPool = FALSE; CreateDestroyMapInventoryPoolButtons( FALSE ); } } else if( fShowInventoryFlag == TRUE ) { if ( gMPanelRegion.Cursor != EXTERN_CURSOR && !InItemStackPopup() ) { fEndShowInventoryFlag = TRUE; } } else if( MultipleCharacterListEntriesSelected( ) ) { ResetSelectedListForMapScreen( ); if( bSelectedInfoChar != -1 ) { SetEntryInSelectedCharacterList( bSelectedInfoChar ); } fTeamPanelDirty = TRUE; fCharacterInfoPanelDirty = TRUE; } else if (fShowMapScreenMovementList) { fShowMapScreenMovementList = FALSE; CreateDestroyMovementBox(0, 0, 0); } else { RequestTriggerExitFromMapscreen( MAP_EXIT_TO_TACTICAL ); } break; // end of ESC case PAUSE: // Pause game! HandlePlayerPauseUnPauseOfGame( ); break; case SPACE: if (fCtrl) { checkLBEArrayIntegrity(); } else if( fShowUpdateBox ) { EndUpdateBox( TRUE ); // restart time compression } else { // toggle time compression if ( CommonTimeCompressionChecks() == FALSE ) RequestToggleTimeCompression(); } break; case LEFTARROW: // previous character fResetMapCoords = TRUE; GoToPrevCharacterInList( ); break; case RIGHTARROW: // next character fResetMapCoords = TRUE; GoToNextCharacterInList( ); break; case UPARROW: // up a line MapScreenMsgScrollUp( 1 ); break; case DNARROW: // down a line MapScreenMsgScrollDown( 1 ); break; case PGUP: if (gfPreBattleInterfaceActive) { ScrollPreBattleInterface(TRUE); } else { // WANNE: Jump to first merc in list fResetMapCoords = TRUE; GoToFirstCharacterInList(); } break; case PGDN: if (gfPreBattleInterfaceActive) { ScrollPreBattleInterface(FALSE); } else { // WANNE: Jump to last merc in list fResetMapCoords = TRUE; GoToLastCharacterInList(); } break; case SHIFT_PGUP: // up a page MapScreenMsgScrollUp( MAX_MESSAGES_ON_MAP_BOTTOM ); break; case SHIFT_PGDN: // down a page MapScreenMsgScrollDown( MAX_MESSAGES_ON_MAP_BOTTOM ); break; case HOME: // jump to top of message list ChangeCurrentMapscreenMessageIndex( 0 ); break; case END: // jump to bottom of message list MoveToEndOfMapScreenMessageList(); break; case INSERT: // up one sublevel GoUpOneLevelInMap( ); break; case DEL: #ifdef INVFIX_Moa//dnl ch85 050214 // show the inventory pool? if( fShowMapInventoryPool && _KeyDown( CTRL ) ) { DeleteAllItemsInInventoryPool(); break; } #else if(fCtrl && fShowMapInventoryPool && !(gpItemPointer || InSectorStackPopup() || InItemStackPopup() || InItemDescriptionBox() || InKeyRingPopup())) { DoMessageBox(MSG_BOX_BASIC_STYLE, NewInvMessage[NIV_DELETE_ALL], guiCurrentScreen, (UINT8)MSG_BOX_FLAG_YESNO, BeginDeleteAllCallBack, NULL); break; } #endif // down one sublevel GoDownOneLevelInMap( ); break; case ENTER: RequestToggleMercInventoryPanel(); break; case BACKSPACE: StopAnyCurrentlyTalkingSpeech( ); break; case TAB: // go to next tab in enhanced description box if( fCtrl ) { if( InItemDescriptionBox( ) && gGameSettings.fOptions[ TOPTION_ENHANCED_DESC_BOX ] == TRUE ) { if ( (Item[ gpItemDescObject->usItem ].usItemClass & IC_WEAPON || Item[ gpItemDescObject->usItem ].usItemClass & IC_PUNCH) && gubDescGenPage == 0 && gubDescBoxPage == 1 ) { gubDescGenPage = 1; } else if ( gubDescBoxPage < 2 ) { gubDescGenPage = 0; gubDescBoxPage++; } else { gubDescBoxPage = 0; } HandleItemDescTabButton( ); } } break; case F1: case F2: case F3: case F4: case F5: case F6: ChangeCharacterListSortMethod( InputEvent.usParam - F1 ); break; case F7: #ifdef JA2TESTVERSION if( fAlt ) { if ( bSelectedInfoChar != -1 ) { SOLDIERTYPE *pSoldier = gCharactersList[ bSelectedInfoChar ].usSolID; if ( pSoldier->inv[ HANDPOS ].exists() == true ) { pSoldier->inv[ HANDPOS ][0]->data.objectStatus = 2; } } } if( fCtrl ) { if ( bSelectedInfoChar != -1 ) { SOLDIERTYPE *pSoldier = gCharactersList[ bSelectedInfoChar ].usSolID; if ( pSoldier->inv[ HANDPOS ].exists() == true ) { pSoldier->inv[ HANDPOS ].usItem = GUN_BARREL_EXTENDER; } } } #endif break; case F8: #ifdef JA2TESTVERSION if( fAlt ) { // reduce balance to $500 AddTransactionToPlayersBook( PAYMENT_TO_NPC, SKYRIDER, GetWorldTotalMin( ), - ( LaptopSaveInfo.iCurrentBalance - 500 ) ); } #endif break; case F9: #ifdef JA2TESTVERSION if( fAlt ) { UINT8 ubSamIndex; // ALT-F9: Reveal all SAM sites for( ubSamIndex = 0; ubSamIndex < NUMBER_OF_SAMS; ubSamIndex++ ) { SetSAMSiteAsFound( ubSamIndex ); } } #endif break; case F10: #ifdef JA2TESTVERSION if( fAlt ) { if ( bSelectedInfoChar != -1 ) { // ALT-F10: force selected character asleep (ignores breathmax) PutMercInAsleepState( gCharactersList[ bSelectedInfoChar ].usSolID ); } } #endif break; /* case F11: #ifdef JA2TESTVERSION if( fAlt ) { // ALT-F11: make all sectors player controlled ClearMapControlledFlags( ); fMapPanelDirty = TRUE; } #endif break; */ case F12: #ifdef JA2BETAVERSION *puiNewEvent = MAP_EVENT_VIEWAI; #endif break; case '+': case '=': if ( CommonTimeCompressionChecks() == FALSE ) RequestIncreaseInTimeCompression(); break; case '-': case '_': if ( CommonTimeCompressionChecks() == FALSE ) RequestDecreaseInTimeCompression(); break; case '`': if (fAlt) { } #ifdef JA2TESTVERSION else if( fCtrl ) { if( bSelectedInfoChar != -1 ) { TownMilitiaTrainingCompleted( gCharactersList[ bSelectedInfoChar ].usSolID, sSelMapX, sSelMapY ); } } #endif else RequestToggleMercInventoryPanel(); break; case '\\': #ifdef JA2TESTVERSION if (fAlt) { } else if( fCtrl ) { DumpItemsList(); } #endif break; case '>': #ifdef JA2TESTVERSION if( fCtrl ) { // free } #endif break; case '?': #ifdef JA2TESTVERSION if( fCtrl ) MapScreenMessage( 0, MSG_DEBUG, L"JA2Clock = %d", GetJA2Clock() ); else MapScreenMessage( 0, MSG_DEBUG, L"Mouse X,Y = %d,%d", MSYS_CurrentMX, MSYS_CurrentMY ); #endif break; case ',': if( fShowMapInventoryPool == TRUE ) { // if can go to previous page, go there if( iCurrentInventoryPoolPage > 0 ) { iCurrentInventoryPoolPage--; fMapPanelDirty = TRUE; } } break; case '.': if( fShowMapInventoryPool == TRUE ) { // if can go to next page, go there if( iCurrentInventoryPoolPage < ( iLastInventoryPoolPage ) ) { iCurrentInventoryPoolPage++; fMapPanelDirty = TRUE; } } break; case '/': #ifdef JA2TESTVERSION if( fAlt ) { if( bSelectedInfoChar != -1 ) { StatChange( gCharactersList[ bSelectedInfoChar ].usSolID, EXPERAMT, 1000, FROM_SUCCESS ); } } #endif break; // ROMAN:0 multiplayer: Maybe we need to change the keys, because they are bound to other functions // OJW - 20090210 - disabling the old method's for starting server and disconnecting // as they are no longer needed case '1': { /*if (is_networked) { // haydent start_server(); break; }*/ } case '2': { /*if (is_networked) { // haydent connect_client(); break; }*/ } case '3': { /*if (is_networked) { // haydent start_battle(); break; }*/ } case '4': { /*if (is_networked) { // haydent server_disconnect(); client_disconnect(); break; }*/ } case '5': case '6': case '7': case '8': case '9': if(gGameExternalOptions.fEnableInventoryPoolQ && fShowMapInventoryPool == TRUE)//dnl ch51 081009 { SwitchToInventoryPoolQ((UINT8)InputEvent.usParam); break; } // multi-selects all characters in that squad. SHIFT key and 1-0 for squads 11-20 bSquadNumber = ( INT8 ) ( InputEvent.usParam - '1' ); // internal squad #s start at 0 SelectAllCharactersInSquad( bSquadNumber ); break; case '0': if(gGameExternalOptions.fEnableInventoryPoolQ && fShowMapInventoryPool == TRUE)//dnl ch51 081009 { SwitchToInventoryPoolQ('0'); break; } SelectAllCharactersInSquad( 9 ); // internal squad #s start at 0 break; case '!': SelectAllCharactersInSquad( 10 ); // internal squad #s start at 0 break; case '@': SelectAllCharactersInSquad( 11 ); // internal squad #s start at 0 break; case '#': SelectAllCharactersInSquad( 12 ); // internal squad #s start at 0 break; case '$': SelectAllCharactersInSquad( 13 ); // internal squad #s start at 0 break; case '%': SelectAllCharactersInSquad( 14 ); // internal squad #s start at 0 break; case '^': SelectAllCharactersInSquad( 15 ); // internal squad #s start at 0 break; case '&': SelectAllCharactersInSquad( 16 ); // internal squad #s start at 0 break; case '*': SelectAllCharactersInSquad( 17 ); // internal squad #s start at 0 break; case '(': SelectAllCharactersInSquad( 18 ); // internal squad #s start at 0 break; case ')': SelectAllCharactersInSquad( 19 ); // internal squad #s start at 0 break; case '\''://dnl ch75 021113 #ifdef _DEBUG // temporary add soldiers to your list for equipment inspection and general testing for(UINT32 ubLoop=0; ubLoopbTeam == ENEMY_TEAM && MercSlots[ubLoop]->bActive) { for(int i=0; iubID) break; if(gCharactersList[i].usSolID == 0 && gCharactersList[i].fValid == FALSE) { gCharactersList[i].usSolID = MercSlots[ubLoop]->ubID; gCharactersList[i].fValid = TRUE; break; } } } } fTeamPanelDirty = TRUE; #endif break; case 'a': if( fAlt ) { if( giHighLine != -1 ) { if( gCharactersList[ giHighLine ].fValid == TRUE ) { bSelectedAssignChar = ( INT16 )giHighLine; RebuildAssignmentsBox( ); ChangeSelectedInfoChar( giHighLine, FALSE ); fShowAssignmentMenu = TRUE; } } else if( bSelectedInfoChar != -1 ) { if( gCharactersList[ bSelectedInfoChar ].fValid == TRUE ) { bSelectedAssignChar = bSelectedInfoChar; RebuildAssignmentsBox( ); fShowAssignmentMenu = TRUE; } } } else if( fCtrl ) { if( CHEATER_CHEAT_LEVEL( ) ) { if( gfAutoAmbush ^= 1 ) ScreenMsg( FONT_WHITE, MSG_TESTVERSION, L"Enemy ambush test mode enabled." ); else ScreenMsg( FONT_WHITE, MSG_TESTVERSION, L"Enemy ambush test mode disabled." ); } } else { if( gfPreBattleInterfaceActive ) { //activate autoresolve in prebattle interface. ActivatePreBattleAutoresolveAction(); } else { // only handle border button keyboard equivalents if the button is visible! if ( !fShowMapInventoryPool ) { ToggleAirspaceMode(); } } } break; case 'A': if (fCtrl && CHEATER_CHEAT_LEVEL())//reveal all sectors and show enemies { for (INT16 sSectorX = 0; sSectorX < MAP_WORLD_X; sSectorX++) { for (INT16 sSectorY = 0; sSectorY < MAP_WORLD_Y; sSectorY++) { SetSectorFlag(sSectorX, sSectorY, (UINT8)0, SF_ALREADY_VISITED); SetSectorFlag(sSectorX, sSectorY, (UINT8)0, SF_PLAYER_KNOWS_ENEMIES_ARE_HERE); } } fMapPanelDirty = TRUE; } break; case 'b': /* // CTRL-B: make player's perception of all sectors correct! if( ( fCtrl )&&( CHEATER_CHEAT_LEVEL( ) ) ) { for ( sMapX = 1; sMapX <= 16; sMapX++ ) { for ( sMapY = 1; sMapY <= 16; sMapY++ ) { MakePlayerPerceptionOfSectorControlCorrect( sMapX, sMapY, 0 ); } } } */ break; case 'c': if(gGameExternalOptions.fEnableInventoryPoolQ && fShowMapInventoryPool == TRUE)//dnl ch51 081009 { CopySectorInventoryToInventoryPoolQ(0); break; } //Ja25 UB //if ( fAlt ) //{ // MakeBadSectorListFromMapsOnHardDrive( TRUE ); //} //else //{ RequestContractMenu(); //} break; case 'd': #ifdef JA2TESTVERSION if( fAlt ) { // prints out a text file in C:\TEMP telling you how many stat change chances/successes each profile merc got TestDumpStatChanges(); } else #endif if ( !fShowMapInventoryPool ) { ToggleDiseaseFilter(); } break; case 'D': #ifdef INVFIX_Moa//dnl ch85 050214 if( fCtrl ) { if ( !InSectorStackPopup( ) && !InItemStackPopup( ) && !InItemDescriptionBox( ) && !InKeyRingPopup( ) ) { //CHRISL: Delete all items if(!fShowMapInventoryPool) { fShowMapInventoryPool = TRUE; CreateDestroyMapInventoryPoolButtons( TRUE ); } DoMessageBox( MSG_BOX_BASIC_STYLE, NewInvMessage[NIV_DELETE_ALL], guiCurrentScreen, ( UINT8 )MSG_BOX_FLAG_YESNO, BeginDeleteAllCallBack, NULL ); if(fShowMapInventoryPool) { fShowMapInventoryPool = FALSE; } } } #else if(fCtrl && fShowMapInventoryPool && !(gpItemPointer || InSectorStackPopup() || InItemStackPopup() || InItemDescriptionBox() || InKeyRingPopup())) { DoMessageBox(MSG_BOX_BASIC_STYLE, NewInvMessage[NIV_DELETE_ALL], guiCurrentScreen, (UINT8)MSG_BOX_FLAG_YESNO, BeginDeleteAllCallBack, NULL); break; } #endif break; case 'e': if( gfPreBattleInterfaceActive ) { //activate enter sector in prebattle interface. gfHotKeyEnterSector = TRUE; } break; case 'E': if(bSelectedInfoChar != -1) { SOLDIERTYPE *pSoldier = gCharactersList[ bSelectedInfoChar ].usSolID; pSoldier->bInSector = FALSE; //CHRISL: Try to update InSector value so we don't have to "activate" a sector if(pSoldier->sSectorX == sSelMapX && pSoldier->sSectorY == sSelMapY && pSoldier->bSectorZ == iCurrentMapSectorZ && !pSoldier->flags.fBetweenSectors) pSoldier->bInSector = TRUE; if(OK_CONTROL_MERC( pSoldier ) && pSoldier->bInSector == TRUE) { if(!fShowMapInventoryPool) { fShowMapInventoryPool = TRUE; CreateDestroyMapInventoryPoolButtons( TRUE ); } if(!fShowInventoryFlag) { fShowInventoryFlag = TRUE; } if( fCtrl ) { if ( UsingNewInventorySystem() && fShowInventoryFlag && fShowMapInventoryPool && !gTacticalStatus.fEnemyInSector) { //CHRISL: pickup all items to vehicle if ( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) { if (gGameExternalOptions.fVehicleInventory) { moveSectorInventoryToVehicle(pSoldier); } } // Flugente: also allow mercs to qickly pick up items this way (but not EPCs) else if ( !AM_AN_EPC(pSoldier) ) { for (unsigned int i = 0; i < pInventoryPoolList.size(); ++i) { if (pInventoryPoolList[i].fExists == TRUE && (pInventoryPoolList[i].usFlags & WORLD_ITEM_REACHABLE)) { INT8 invsize = (INT8)pSoldier->inv.size(); // remember inventorysize, so we don't call size() repeatedly for (INT8 bLoop = 0; bLoop < invsize; ++bLoop) { if ( CanItemFitInPosition( pSoldier, &pInventoryPoolList[i].object, bLoop, FALSE ) ) { // TODO: do not add LBE if we would then have to move existing items if (pSoldier->inv[bLoop].exists()) { if (pSoldier->inv[bLoop].usItem != pInventoryPoolList[i].object.usItem) continue; else pInventoryPoolList[i].object.AddObjectsToStack(pSoldier->inv[bLoop], -1, pSoldier, bLoop, 0, FALSE); } else pInventoryPoolList[i].object.MoveThisObjectTo(pSoldier->inv[bLoop], -1, pSoldier, bLoop); if (pInventoryPoolList[i].object.ubNumberOfObjects < 0) { //RemoveItemFromWorld(i); break; } } } } } fTeamPanelDirty = TRUE; fMapPanelDirty = TRUE; fInterfacePanelDirty = DIRTYLEVEL2; } } } else if ( fAlt ) { //CHRISL: drop all items in backpack if ( bSelectedInfoChar != -1 && fShowInventoryFlag && fShowMapInventoryPool && !(gTacticalStatus.fEnemyInSector) ) { for(int i = BIGPOCK4POS; i<=BIGPOCK7POS; i++) { if(pSoldier->inv[i].exists() == true) { AutoPlaceObjectInInventoryStash(&pSoldier->inv[i], pSoldier->sGridNo, pSoldier->pathing.bLevel); DeleteObj(&pSoldier->inv[i]); } } for(int i = SMALLPOCK23POS; iinv[i].exists() == true) { AutoPlaceObjectInInventoryStash(&pSoldier->inv[i], pSoldier->sGridNo, pSoldier->pathing.bLevel); DeleteObj(&pSoldier->inv[i]); } } fTeamPanelDirty = TRUE; fMapPanelDirty = TRUE; fInterfacePanelDirty = DIRTYLEVEL2; } } else { //CHRISL: drop all items if ( bSelectedInfoChar != -1 && fShowInventoryFlag && fShowMapInventoryPool && !(gTacticalStatus.fEnemyInSector) ) { for(int i = BODYPOSFINAL; iinv[i].exists() == true) { AutoPlaceObjectInInventoryStash(&pSoldier->inv[i], pSoldier->sGridNo, pSoldier->pathing.bLevel); DeleteObj(&pSoldier->inv[i]); } } fTeamPanelDirty = TRUE; fMapPanelDirty = TRUE; fInterfacePanelDirty = DIRTYLEVEL2; } } } } break; case 'f': #ifdef JA2TESTVERSION // CTRL-F: Refuel vehicle if( ( fCtrl ) && ( bSelectedInfoChar != -1 ) ) { SOLDIERTYPE *pSoldier = gCharactersList[ bSelectedInfoChar ].usSolID; if ( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) { pSoldier->sBreathRed = 10000; pSoldier->bBreath = 100; ScreenMsg( FONT_MCOLOR_RED, MSG_TESTVERSION, L"Vehicle refueled" ); fTeamPanelDirty = TRUE; fCharacterInfoPanelDirty = TRUE; } } #endif if( fAlt ) { if ( INFORMATION_CHEAT_LEVEL( ) ) { //Toggle Frame Rate Display gbFPSDisplay = !gbFPSDisplay; DisableFPSOverlay( (BOOLEAN)!gbFPSDisplay ); } } break; case 'G': if (fCtrl) { if (CHEATER_CHEAT_LEVEL()) { if (gTacticalStatus.uiFlags & GODMODE) { //ScreenMsg(FONT_MCOLOR_RED, MSG_INTERFACE, L"God mode deactivated."); gTacticalStatus.uiFlags &= (~GODMODE); } else { //ScreenMsg(FONT_MCOLOR_RED, MSG_INTERFACE, L"God mode activated."); gTacticalStatus.uiFlags |= GODMODE; } } } break; case 'g': break; case 'h': #ifdef JA2TESTVERSION if( fAlt ) { // set up the helicopter over Omerta (if it's not already set up) SetUpHelicopterForPlayer( 9,1 , SKYRIDER, HELICOPTER ); // raise Drassen loyalty to minimum that will allow Skyrider to fly if ( gTownLoyalty[ DRASSEN ].fStarted && ( gTownLoyalty[ DRASSEN ].ubRating < LOYALTY_LOW_THRESHOLD ) ) { SetTownLoyalty( DRASSEN, LOYALTY_LOW_THRESHOLD ); } TurnOnAirSpaceMode( ); } else #endif { // ARM: Feb01/98 - Cancel out of mapscreen movement plotting if Help subscreen is coming up if ( ( GetSelectedDestChar() != -1) || fPlotForHelicopter || fPlotForMilitia ) { AbortMovementPlottingMode( ); } ShouldTheHelpScreenComeUp( HELP_SCREEN_MAPSCREEN, TRUE ); } // fShowMapScreenHelpText = TRUE; break; case 'H': // swap primary & secondary hand if ( bSelectedInfoChar != -1 && fShowInventoryFlag && !AM_A_ROBOT( gCharactersList[ bSelectedInfoChar ].usSolID )) { SOLDIERTYPE *pSoldier = gCharactersList[ bSelectedInfoChar ].usSolID; UINT16 usOldHandItem = pSoldier->inv[HANDPOS].usItem; SwapHandItems( pSoldier ); fTeamPanelDirty = TRUE; fMapPanelDirty = TRUE; fInterfacePanelDirty = DIRTYLEVEL2; } break; case 'i': #ifdef JA2TESTVERSION /* if( fAlt ) { InitializeMines(); fMapPanelDirty = TRUE; } else */ if( fCtrl ) { fDisableJustForIan = ! fDisableJustForIan; } #endif // only handle border button keyboard equivalents if the button is visible! if ( !fShowMapInventoryPool ) { ToggleItemsFilter(); } break; case 'j': break; case 'K': //CHRISL: Swap gunsling if ( bSelectedInfoChar != -1 && fShowInventoryFlag && UsingNewInventorySystem() == true ) { SOLDIERTYPE *pSoldier = gCharactersList[bSelectedInfoChar].usSolID; if (fAlt) // switch to knife, or from knife to gun pSoldier->SwitchWeapons(TRUE); else if (fCtrl) // switch to sidearm, or from sidearm to non-sidearm gun pSoldier->SwitchWeapons(FALSE, TRUE); else // switch to and from gunsling pSoldier->SwitchWeapons(); fTeamPanelDirty = TRUE; fMapPanelDirty = TRUE; fInterfacePanelDirty = DIRTYLEVEL2; } break; // haydent case 'k': if(gGameExternalOptions.fEnableInventoryPoolQ && fShowMapInventoryPool == TRUE)//dnl ch51 081009 { CopySectorInventoryToInventoryPoolQs(0); //break; } break; case 'l': if( fAlt ) { // although we're not actually going anywhere, we must still be in a state where this is permitted if ( AllowedToExitFromMapscreenTo( MAP_EXIT_TO_LOAD ) ) { DoQuickLoad(); } } else if( fCtrl ) { // go to LOAD screen gfSaveGame = FALSE; RequestTriggerExitFromMapscreen( MAP_EXIT_TO_LOAD ); } else { // go to LAPTOP RequestTriggerExitFromMapscreen( MAP_EXIT_TO_LAPTOP ); } break; case 'm': //JA25 UB // only handle border button keyboard equivalents if the button is visible! /*if ( fAlt ) { INT16 sMapX, sMapY; // Get sector that is hilighted... if ( GetMouseMapXY(&sMapX, &sMapY) ) { AddCustomMap( sMapY, sMapX, TRUE, TRUE ); UpdateCustomMapMovementCosts(); } } else { if ( !fShowMapInventoryPool ) { // toggle show mines flag ToggleShowMinesMode(); } } */ // only handle border button keyboard equivalents if the button is visible! if ( !fShowMapInventoryPool ) { // toggle show mines flag ToggleShowMinesMode(); } break; case 'n': #ifdef JA2TESTVERSION if( fAlt ) { static UINT16 gQuoteNum = 0; // Get Soldier TacticalCharacterDialogue( gCharactersList[ bSelectedInfoChar ].usSolID, gQuoteNum ); gQuoteNum++; } else if( fCtrl ) { static UINT16 gQuoteNum = 0; // Get Soldier if ( giHighLine != -1 ) { TacticalCharacterDialogue( gCharactersList[ giHighLine ].usSolID, gQuoteNum ); gQuoteNum++; } } #endif break; case 'N': if ( bSelectedInfoChar != -1 && fShowInventoryFlag ) { SOLDIERTYPE *pSoldier = gCharactersList[ bSelectedInfoChar ].usSolID; SwapGoggles(pSoldier); } break; case 'o': if( fAlt ) { // toggle if Orta & Tixa have been found #ifdef JA2TESTVERSION fFoundOrta = !fFoundOrta; fFoundTixa = !fFoundTixa; for( iCounter2 = 1; iCounter2 < NUM_TOWNS; iCounter2++ ) { gfHiddenTown [ iCounter2 ] = TRUE; gfDrawHiddenTown[ iCounter2 ] = TRUE; } fMapPanelDirty = TRUE; #endif } else { // go to OPTIONS screen RequestTriggerExitFromMapscreen( MAP_EXIT_TO_OPTIONS ); } break; case 'p': #ifdef JA2TESTVERSION if( fCtrl ) { // CTRL-P: Display player's highest progress percentage DumpSectorDifficultyInfo(); } #endif #ifdef JA2TESTVERSION // ALT-P: Make the selected character a POW! if( ( fAlt ) && ( bSelectedInfoChar != -1 ) ) { SOLDIERTYPE *pSoldier = gCharactersList[ bSelectedInfoChar ].usSolID; EnemyCapturesPlayerSoldier( pSoldier ); if ( pSoldier->bInSector ) { RemoveSoldierFromTacticalSector( pSoldier, TRUE ); } fTeamPanelDirty = TRUE; fCharacterInfoPanelDirty = TRUE; fMapPanelDirty = TRUE; } #endif break; case 'q': #ifdef JA2TESTVERSION if( fAlt ) { // initialize miners if not already done so (fakes entering Drassen mine first) HandleQuestCodeOnSectorEntry( 13, 4, 0); // test miner quote system IssueHeadMinerQuote( (INT8) (1 + Random(MAX_NUMBER_OF_MINES - 1)), (UINT8) (1 + Random(2))); } else #endif if ( !fShowMapInventoryPool ) { ToggleIntelFilter(); } break; case 'Q'://dnl ch75 021113 #ifdef _DEBUG extern UINT8 gInventoryPoolIndex; if(fShowMapInventoryPool == TRUE && gInventoryPoolIndex == '0') { if(gGameExternalOptions.fEnableInventoryPoolQ) { gGameExternalOptions.fEnableInventoryPoolQ = FALSE; ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"InventoryPoolQ disabled."); } else { gGameExternalOptions.fEnableInventoryPoolQ = TRUE; ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"InventoryPoolQ enabled."); } } #endif break; case 'r': if( gfPreBattleInterfaceActive ) { //activate autoresolve in prebattle interface. ActivatePreBattleRetreatAction(); } else if ( !fShowMapInventoryPool ) { ToggleWeatherFilter(); } break; case 's': if( fAlt ) { // although we're not actually going anywhere, we must still be in a state where this is permitted if ( AllowedToExitFromMapscreenTo( MAP_EXIT_TO_SAVE ) ) { //if the game CAN be saved if( CanGameBeSaved() ) { SetOptionsPreviousScreen(guiCurrentScreen); DoQuickSave(); } else { //Display a message saying the player cant save now switch( gGameOptions.ubIronManMode ) { case 2: DoMapMessageBox( MSG_BOX_BASIC_STYLE, zNewTacticalMessages[ TCTL_MSG__SOFT_IRON_MAN_CANT_SAVE_NOW ], MAP_SCREEN, MSG_BOX_FLAG_OK, NULL ); break; case 3: CHAR16 zTemp[320]; swprintf( zTemp, zNewTacticalMessages[ TCTL_MSG__EXTREME_IRON_MAN_CANT_SAVE_NOW ], gGameExternalOptions.ubExtremeIronManSavingHour); DoMapMessageBox( MSG_BOX_BASIC_STYLE, zTemp, MAP_SCREEN, MSG_BOX_FLAG_OK, NULL ); break; default: DoMapMessageBox( MSG_BOX_BASIC_STYLE, zNewTacticalMessages[ TCTL_MSG__IRON_MAN_CANT_SAVE_NOW ], MAP_SCREEN, MSG_BOX_FLAG_OK, NULL ); break; } } } } else if( fCtrl ) { // go to SAVE screen gfSaveGame = TRUE; RequestTriggerExitFromMapscreen( MAP_EXIT_TO_SAVE ); } else if(gGameExternalOptions.fEnableInventoryPoolQ && fShowMapInventoryPool == TRUE)//dnl ch51 081009 { SortInventoryPoolQ(); //break; } break; case 'S': if( fCtrl ) { if ( !InSectorStackPopup( ) && !InItemStackPopup( ) && !InItemDescriptionBox( ) && !InKeyRingPopup( ) ) { //CHRISL: Sell all items if(gGameExternalOptions.fSellAll == TRUE) { if(!fShowMapInventoryPool) { fShowMapInventoryPool = TRUE; CreateDestroyMapInventoryPoolButtons( TRUE ); } DoMessageBox( MSG_BOX_BASIC_STYLE, NewInvMessage[NIV_SELL_ALL], guiCurrentScreen, ( UINT8 )MSG_BOX_FLAG_YESNO, BeginSellAllCallBack, NULL ); if(fShowMapInventoryPool) { fShowMapInventoryPool = FALSE; } } } } break; case 't': // Teleport: CTRL-T if( ( fCtrl )&&( CHEATER_CHEAT_LEVEL( ) ) ) { // check if selected dest char, if ( ( GetSelectedDestChar() != -1) && !fPlotForHelicopter && !fPlotForMilitia && (iCurrentMapSectorZ == 0) && (GetMouseMapXY( &sMapX, &sMapY )) ) { INT16 sDeltaX, sDeltaY; INT16 sPrevX = 0, sPrevY = 0; SOLDIERTYPE *pSoldier = gCharactersList[GetSelectedDestChar()].usSolID; // can't teleport to where we already are if ( ( sMapX == pSoldier->sSectorX ) && ( sMapY == pSoldier->sSectorY ) ) break; // figure out where they would've come from if (pTempCharacterPath) { pTempCharacterPath = MoveToEndOfPathList(pTempCharacterPath); UINT32 sSectorId = pTempCharacterPath->pPrev->uiSectorId; sPrevX = GET_X_FROM_STRATEGIC_INDEX(sSectorId); sPrevY = GET_Y_FROM_STRATEGIC_INDEX(sSectorId); } else if (pTempHelicopterPath) { pTempHelicopterPath = MoveToEndOfPathList(pTempHelicopterPath); UINT32 sSectorId = pTempHelicopterPath->pPrev->uiSectorId; sPrevX = GET_X_FROM_STRATEGIC_INDEX(sSectorId); sPrevY = GET_Y_FROM_STRATEGIC_INDEX(sSectorId); } // cancel movement plotting AbortMovementPlottingMode( ); // nuke the UI message generated by this CancelMapUIMessage( ); // clear their strategic movement (mercpaths and waypoints) ClearMvtForThisSoldierAndGang( pSoldier ); // select this sector ChangeSelectedMapSector( sMapX, sMapY, 0 ); // check to see if this person is moving, if not...then assign them to mvt group if( pSoldier->ubGroupID == 0 ) { ubGroupId = CreateNewPlayerGroupDepartingFromSector( ( INT8 ) ( pSoldier->sSectorX ) , ( INT8 ) ( pSoldier->sSectorY ) ); // assign to a group AddPlayerToGroup( ubGroupId, pSoldier ); } //shadooow: this should now only happen when teleporting into inaccessible sectors if (!sPrevX || !sPrevY) { // figure out where they would've come from sDeltaX = sMapX - pSoldier->sSectorX; sDeltaY = sMapY - pSoldier->sSectorY; if ( abs( sDeltaX ) >= abs( sDeltaY ) ) { // use East or West if( sDeltaX > 0 ) { // came in from the West sPrevX = sMapX - 1; } else { // came in from the East sPrevX = sMapX + 1; } sPrevY = sMapY; } else { // use North or South if( sDeltaY > 0 ) { // came in from the North sPrevY = sMapY - 1; } else { // came in from the South sPrevY = sMapY + 1; } sPrevX = sMapX; } } // set where they are, were/are going, then make them arrive there and check for battle PlaceGroupInSector( pSoldier->ubGroupID, sPrevX, sPrevY, sMapX, sMapY, 0, TRUE ); // unload the sector they teleported out of CheckAndHandleUnloadingOfCurrentWorld(); } } else { // only handle border button keyboard equivalents if the button is visible! if ( !fShowMapInventoryPool ) { // Toggle show teams flag ToggleShowTeamsMode(); } } break; case 'u': #ifdef JA2TESTVERSION { if( fAlt ) { UINT32 uiCnt; // initialize miners if not already done so (fakes entering Drassen mine first) HandleQuestCodeOnSectorEntry( 13, 4, 0); // test running out for (uiCnt = 0; uiCnt < 10; uiCnt++) { HandleIncomeFromMines(); } } } #endif // open selected sector inventory screen // if not already in sector inventory if ( !fShowMapInventoryPool ) { if ( ( GetSelectedDestChar() != -1) || fPlotForHelicopter || fPlotForMilitia ) { AbortMovementPlottingMode( ); } else if ( gfInChangeArrivalSectorMode ) { CancelChangeArrivalSectorMode( ); } // show sector inventory for selected sector ChangeSelectedMapSector( sSelMapX, sSelMapY, ( INT8 ) iCurrentMapSectorZ ); fShowMapInventoryPool = TRUE; CreateDestroyMapInventoryPoolButtons( TRUE ); } break; case 'v': if( fCtrl ) { #ifdef SGP_VIDEO_DEBUGGING ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"VObjects: %d", guiVObjectSize ); ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"VSurfaces: %d", guiVSurfaceSize ); ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"SGPVideoDump.txt updated..." ); PerformVideoInfoDumpIntoFile( "SGPVideoDump.txt", TRUE ); #endif } else { DisplayGameSettings( ); } break; case 'W': if( fAlt ) { if ( CHEATER_CHEAT_LEVEL( ) ) { if ( InItemDescriptionBox( ) ) { CycleItemDescriptionItem( MAP_ITEMDESC_START_X, MAP_ITEMDESC_START_Y ); } } } else { if(bSelectedInfoChar != -1) { SOLDIERTYPE *pSoldier = gCharactersList[ bSelectedInfoChar ].usSolID; //CHRISL: Try to update InSector value so we don't have to "activate" a sector if (pSoldier->sSectorX == sSelMapX && pSoldier->sSectorY == sSelMapY && pSoldier->bSectorZ == iCurrentMapSectorZ && !pSoldier->flags.fBetweenSectors) pSoldier->bInSector=TRUE; if (OK_CONTROL_MERC( pSoldier )) { if(!fShowMapInventoryPool) { fShowMapInventoryPool = TRUE; CreateDestroyMapInventoryPoolButtons( TRUE ); } if(!fShowInventoryFlag) { fShowInventoryFlag = TRUE; } //tais: borrowed the drop all items code from CHRISL to make it drop EVERYTHING! if ( bSelectedInfoChar != -1 && fShowInventoryFlag && fShowMapInventoryPool && !(gTacticalStatus.fEnemyInSector) ) { for ( int i = HELMETPOS; iinv[i].exists() == true) { // if we are Nails and are ordered to drop our vest, refuse and complain! if ( HandleNailsVestFetish( pSoldier, i, NOTHING ) ) continue; AutoPlaceObjectInInventoryStash(&pSoldier->inv[i], pSoldier->sGridNo, pSoldier->pathing.bLevel); DeleteObj(&pSoldier->inv[i]); } } fTeamPanelDirty = TRUE; fMapPanelDirty = TRUE; fInterfacePanelDirty = DIRTYLEVEL2; } } } } break; case 'w': if( fAlt ) { if ( CHEATER_CHEAT_LEVEL( ) ) { if ( InItemDescriptionBox( ) ) { CycleItemDescriptionItem( MAP_ITEMDESC_START_X, MAP_ITEMDESC_START_Y ); } } } else if( fCtrl ) { } else { // only handle border button keyboard equivalents if the button is visible! if ( !fShowMapInventoryPool ) { // toggle show towns filter ToggleShowTownsMode(); } } break; case 'x': if( fAlt ) { HandleShortCutExitState( ); } break; case 'y': // ALT-Y: toggles SAM sites disable if( fAlt ) { #ifdef JA2TESTVERSION fSAMSitesDisabledFromAttackingPlayer = !fSAMSitesDisabledFromAttackingPlayer; #endif } // OJW - 20090208 // Adding ingame chat else { if (is_networked && is_client) { OpenChatMsgBox(); } } break; case 'z': // only handle border button keyboard equivalents if the button is visible! if( fCtrl ) { if( CHEATER_CHEAT_LEVEL( ) ) { if( gfAutoAIAware ^= 1 ) ScreenMsg( FONT_WHITE, MSG_TESTVERSION, L"Strategic AI awareness maxed." ); else ScreenMsg( FONT_WHITE, MSG_TESTVERSION, L"Strategic AI awareness normal." ); } } else if ( !fShowMapInventoryPool ) { // Toggle Show Militia ON/OFF ToggleShowMilitiaMode(); } break; } } else if( InputEvent.usEvent == KEY_REPEAT ) { switch( InputEvent.usParam ) { case LEFTARROW: // previous character GoToPrevCharacterInList( ); break; case RIGHTARROW: // next character GoToNextCharacterInList( ); break; case UPARROW: // up a line MapScreenMsgScrollUp( 1 ); break; case DNARROW: // down a line MapScreenMsgScrollDown( 1 ); break; case SHIFT_PGUP: // up a page MapScreenMsgScrollUp( MAX_MESSAGES_ON_MAP_BOTTOM ); break; case SHIFT_PGDN: // down a page MapScreenMsgScrollDown( MAX_MESSAGES_ON_MAP_BOTTOM ); break; case ',': if( fShowMapInventoryPool == TRUE ) { // if can go to previous page, go there if( iCurrentInventoryPoolPage > 0 ) { iCurrentInventoryPoolPage--; fMapPanelDirty = TRUE; } } break; case '.': if( fShowMapInventoryPool == TRUE ) { // if can go to next page, go there if( iCurrentInventoryPoolPage < ( iLastInventoryPoolPage ) ) { iCurrentInventoryPoolPage++; fMapPanelDirty = TRUE; } } break; } } else { extern void HandleDefaultEvent(InputAtom *Event); HandleDefaultEvent(&InputEvent); } } // HEADROCK HAM 5: Alt alone shows sale prices on items in the sector inventory. if (fShowMapInventoryPool) { if (fAlt) { if ( _KeyDown( SHIFT ) ) { if (gubRenderedMapInventorySalePrices < 2) { gubRenderedMapInventorySalePrices = 2; fMapPanelDirty = TRUE; } } else { if (gubRenderedMapInventorySalePrices == 0 || gubRenderedMapInventorySalePrices == 2 ) { gubRenderedMapInventorySalePrices = 1; fMapPanelDirty = TRUE; } } } else { if (gubRenderedMapInventorySalePrices) { gubRenderedMapInventorySalePrices = 0; fMapPanelDirty = TRUE; } } } } void EndMapScreen( BOOLEAN fDuringFade ) { INT32 iCounter2 = 0; if ( fInMapMode == FALSE ) { // shouldn't be here return; } /* // exit is called due to message box, leave if( fMapExitDueToMessageBox ) { fMapExitDueToMessageBox = FALSE; return; } */ fLeavingMapScreen = FALSE; SetRenderFlags( RENDER_FLAG_FULL ); //MSYS_EnableRegion( &gViewportRegion ); //MSYS_EnableRegion( &gRadarRegion ); // ATE: Shutdown tactical interface panel // ShutdownCurrentPanel( ); if( IsMapScreenHelpTextUp() ) { // stop mapscreen text StopMapScreenHelpText( ); return; } // still plotting movement? if ( ( GetSelectedDestChar() != -1) || fPlotForHelicopter || fPlotForMilitia ) { AbortMovementPlottingMode( ); } DestroyMouseRegionsForTeamList( ); MSYS_RemoveRegion( &gMapViewRegion ); MSYS_RemoveRegion( &gCharInfoFaceRegion ); MSYS_RemoveRegion( &gCharInfoHandRegion ); MSYS_RemoveRegion( &gMPanelRegion ); MSYS_RemoveRegion( &gMapScreenMaskRegion ); MSYS_RemoveRegion( &gMapMercWeightRegion ); MSYS_RemoveRegion( &gMapMercCamoRegion ); fInMapMode = FALSE; // remove team panel sort button RemoveTeamPanelSortButtonsForMapScreen( ); // OJW - 20081204 if (is_networked) RemoveMPButtonsForMapScreen( ); // for th merc insurance help text CreateDestroyInsuranceMouseRegionForMercs( FALSE ); // gonna need to remove the screen mask regions CreateDestroyMouseRegionMasksForTimeCompressionButtons( ); UnloadButtonImage( giMapContractButtonImage ); RemoveButton( giMapContractButton ); HandleShutDownOfMapScreenWhileExternfaceIsTalking( ); fShowInventoryFlag = FALSE; if (isWidescreenUI()) { DestroyMapCharInvIOregions(); } else { CreateDestroyMapInvButton(); } // no longer can we show assignments menu fShowAssignmentMenu = FALSE; // clear out mouse regions for pop up boxes DetermineWhichAssignmentMenusCanBeShown( ); DetermineWhichMilitiaControlMenusCanBeShown( ); //lal sSelectedMilitiaTown = 0; CreateDestroyMilitiaPopUPRegions( ); CreateDestroyMilitiaSectorButtons( ); // stop showing contract menu fShowContractMenu = FALSE; // clear out contract menu DetermineIfContractMenuCanBeShown( ); // remove contract pop up box (always created upon mapscreen entry) RemoveBox(ghContractBox); ghContractBox = -1; // OJW if (is_networked) { DestroyMPCompassBox(); DestroyMPTeamBox(); } CreateDestroyAssignmentPopUpBoxes( ); CreateDestroyMilitiaControlPopUpBoxes( ); //lal // shutdown movement box if ( fShowMapScreenMovementList ) { fShowMapScreenMovementList = FALSE; CreateDestroyMovementBox( 0, 0, 0 ); } // the remove merc from team box RemoveBox( ghRemoveMercAssignBox ); ghRemoveMercAssignBox = -1; // clear screen mask if needed ClearScreenMaskForMapScreenExit( ); // get rid of pause clock area RemoveMouseRegionForPauseOfClock( ); // get rid of pop up for town info, if being shown fShowTownInfo = FALSE; CreateDestroyTownInfoBox( ); // build squad list RebuildCurrentSquad( ); DeleteMouseRegionsForLevelMarkers( ); if( fShowMapInventoryPool == FALSE ) { // delete buttons DeleteMapBorderButtons( ); } if(fShowDescriptionFlag) { DeleteItemDescriptionBox( ); } fShowInventoryFlag = FALSE; CreateDestroyTrashCanRegion( ); DeleteKeyRingPopup(); if ( !fDuringFade ) { MSYS_SetCurrentCursor(SCREEN_CURSOR); } if(fPreLoadedMapGraphics == FALSE ) { DeleteMapBottomGraphics( ); DeleteVideoObjectFromIndex(guiSubLevel1); DeleteVideoObjectFromIndex(guiSubLevel2); DeleteVideoObjectFromIndex(guiSubLevel3); DeleteVideoObjectFromIndex( guiSleepIcon ); DeleteVideoObjectFromIndex(guiMAPCURSORS); // HEADROCK HAM 5: New pathing arrows may replace the above eventually, but for now a separate variable will do. DeleteVideoObjectFromIndex(guiMapPathingArrows); //DeleteVideoObjectFromIndex(guiMAPBORDER); DeleteVideoObjectFromIndex(guiCHARLIST); //DeleteVideoObjectFromIndex(guiCORNERADDONS); //DeleteVideoObjectFromIndex(guiMAPCORNER); //DeleteVideoObjectFromIndex(guiPOPUPBORDERS); DeleteVideoObjectFromIndex(guiCHARINFO); DeleteVideoObjectFromIndex(guiCHARICONS); DeleteVideoObjectFromIndex( guiINTEL ); DeleteVideoObjectFromIndex(guiCROSS); DeleteVideoSurfaceFromIndex(guiBIGMAP); // DeleteVideoSurfaceFromIndex(guiPOPUPTEX); DeleteVideoObjectFromIndex(guiSAMICON); DeleteVideoObjectFromIndex(guiMAPINV); DeleteVideoObjectFromIndex(guiMapInvSecondHandBlockout); DeleteVideoObjectFromIndex(guiULICONS); DeleteVideoObjectFromIndex(guiORTAICON); DeleteVideoObjectFromIndex(guiTIXAICON); DeleteVideoObjectFromIndex( guiCHARBETWEENSECTORICONS ); // HEADROCK HAM 5.1: Enemies between sectors arrows DeleteVideoObjectFromIndex( guiENEMYBETWEENSECTORICONS ); DeleteVideoObjectFromIndex( guiLEVELMARKER ); DeleteVideoObjectFromIndex( guiMapBorderEtaPopUp ); DeleteVideoObjectFromIndex( guiSecItemHiddenVO ); DeleteVideoObjectFromIndex( guiSelectedCharArrow ); DeleteVideoObjectFromIndex( guiMapBorderHeliSectors ); DeleteVideoObjectFromIndex( guiMapBorderHeliSectorsAlternate ); DeleteVideoObjectFromIndex( guiHelicopterIcon ); DeleteVideoObjectFromIndex( guiEnemyHelicopterIcon ); DeleteVideoObjectFromIndex( guiMINEICON ); DeleteVideoObjectFromIndex( guiSectorLocatorGraphicID ); //----------- Legion 2 for( iCounter2 = 1; iCounter2 < NUM_TOWNS; iCounter2++ ) { //if ( gfDrawHiddenTown[iCounter2] == TRUE ) DeleteVideoObjectFromIndex(guiIcon2[iCounter2]); } //------- DeleteVideoObjectFromIndex( guiBULLSEYE ); // remove the militia pop up box RemoveMilitiaPopUpBox( ); // remove inventory pool graphic RemoveInventoryPoolGraphic( ); // get rid of border stuff DeleteMapBorderGraphics( ); //Kris: Remove the email icons. DeleteVideoObjectFromIndex( guiNewMailIcons ); } DeleteVideoObjectFromIndex( guiBrownBackgroundForTeamPanel ); RemoveMapStatusBarsRegion( ); fShowUpdateBox = FALSE; CreateDestroyTheUpdateBox( ); // get rid of mapscreen bottom DeleteMapScreenInterfaceBottom( ); // shutdown any mapscreen UI overlay message CancelMapUIMessage( ); CreateDestroyMapCharacterScrollButtons( ); // if time was ever compressed while we were in mapscreen if ( HasTimeCompressOccured( ) ) { // make sure everything tactical got cleared out ClearTacticalStuffDueToTimeCompression(); } CancelSectorInventoryDisplayIfOn( TRUE ); SetAllAutoFacesInactive( ); if(fLapTop) { StopAnyCurrentlyTalkingSpeech( ); guiCurrentScreen=LAPTOP_SCREEN; } else { guiCurrentScreen = GAME_SCREEN; // remove the progress bar RemoveProgressBar( 0 ); // enable scroll string video overlays EnableDisableScrollStringVideoOverlay( TRUE ); } // if going to tactical next if ( guiPendingScreen == GAME_SCREEN ) { // set compressed mode to Normal (X1) SetGameTimeCompressionLevel( TIME_COMPRESS_X1 ); } else // going to another screen (options, laptop, save/load) { StopTimeCompression(); } // update paused states, we are exiting...need to reset for any pathing or menus displayed UnLockPauseState( ); UpdatePausedStatesDueToTimeCompression( ); if( !gfDontStartTransitionFromLaptop ) { // WANNE: This code blocks never gets called, but this is fine, cause we don't need it. That seems to be an "old" unused code block! VOBJECT_DESC VObjectDesc; UINT32 uiLaptopOn; //Load a tiny graphic of the on screen and draw it to the buffer. PlayJA2SampleFromFile( "SOUNDS\\Initial Power Up (8-11).wav", RATE_11025, HIGHVOLUME, 1, MIDDLEPAN ); VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE; sprintf( VObjectDesc.ImageFile, "INTERFACE\\LaptopOn.sti" ); if( !AddVideoObject( &VObjectDesc, &uiLaptopOn ) ) AssertMsg( 0, "Failed to load data\\Interface\\LaptopOn.sti" ); BltVideoObjectFromIndex( FRAME_BUFFER, uiLaptopOn, 0, iScreenWidthOffset + 465, iScreenHeightOffset + 417, VO_BLT_SRCTRANSPARENCY, NULL ); InvalidateRegion( iScreenWidthOffset + 465, iScreenHeightOffset + 417, iScreenWidthOffset + 480, iScreenHeightOffset + 427 ); ExecuteBaseDirtyRectQueue( ); EndFrameBufferRender( ); DeleteVideoObjectFromIndex( uiLaptopOn ); RefreshScreen( NULL ); } //Kris: Removes the pre battle interface, but only if it exists. // It is internally considered. KillPreBattleInterface(); // cancel request if we somehow leave first gfRequestGiveSkyriderNewDestination = FALSE; } BOOLEAN GetMouseMapXY( INT16 *psMapWorldX, INT16 *psMapWorldY ) { POINT MousePos; if( IsMapScreenHelpTextUp( ) ) { // don't show highlight while global help text is up return( FALSE ); } GetCursorPos(&MousePos); ScreenToClient(ghWindow, &MousePos); // In window coords! return( GetMapXY( (INT16)MousePos.x, (INT16)MousePos.y, psMapWorldX, psMapWorldY ) ); } BOOLEAN GetMapXY( INT16 sX, INT16 sY, INT16 *psMapWorldX, INT16 *psMapWorldY ) { INT16 sMapX, sMapY; // Subtract start of map view sMapX = sX - UI_MAP.ViewRegion.x;//+2*UI_MAP.GridSize.iX; sMapY = sY - UI_MAP.ViewRegion.y; if ( sMapX < UI_MAP.GridSize.iX || sMapY < UI_MAP.GridSize.iY ) { return( FALSE ); } if ( sMapX < 1 || sMapY < 1 ) { return (FALSE); } if ( sMapX > UI_MAP.ViewRegion.width+UI_MAP.GridSize.iX-1 || sMapY > UI_MAP.ViewRegion.height+7/* +UI_MAP.ViewArea.height */ ) { return( FALSE ); } *psMapWorldX = ( sMapX / UI_MAP.GridSize.iX ); *psMapWorldY = ( sMapY / UI_MAP.GridSize.iY ); return( TRUE ); } void RenderMapHighlight( INT16 sMapX, INT16 sMapY, UINT16 usLineColor, BOOLEAN fStationary ) { INT16 sScreenX, sScreenY; UINT32 uiDestPitchBYTES; UINT8 *pDestBuf; Assert( ( sMapX >= 1 ) && ( sMapX <= 16 ) ); Assert( ( sMapY >= 1 ) && ( sMapY <= 16 ) ); // if we are not allowed to highlight, leave if( ( IsTheCursorAllowedToHighLightThisSector( sMapX, sMapY ) == FALSE ) ) { return; } GetScreenXYFromMapXY( sMapX, sMapY, &sScreenX, &sScreenY ); // blit in the highlighted sector pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES ); // clip to view region ClipBlitsToMapViewRegionForRectangleAndABit( uiDestPitchBYTES ); RectangleDraw( TRUE, sScreenX, sScreenY - 1, sScreenX + UI_MAP.GridSize.iX, sScreenY + UI_MAP.GridSize.iY - 1, usLineColor, pDestBuf ); InvalidateRegion( sScreenX, sScreenY - 2, sScreenX + UI_MAP.GridSize.iX + 1 + 1, sScreenY + UI_MAP.GridSize.iY + 1 - 1 ); RestoreClipRegionToFullScreenForRectangle( uiDestPitchBYTES ); UnLockVideoSurface( FRAME_BUFFER ); } void PollWheelInMapView(UINT32 *puiNewEvent) { gMapMessageRegion.WheelState = gMapMessageRegion.WheelState * (gGameSettings.fOptions[TOPTION_INVERT_WHEEL] ? -1 : 1); gMapMessageScrollBarRegion.WheelState = gMapMessageScrollBarRegion.WheelState * (gGameSettings.fOptions[TOPTION_INVERT_WHEEL] ? -1 : 1); if (gMapMessageRegion.uiFlags & MSYS_MOUSE_IN_AREA) { if (gMapMessageRegion.WheelState != 0) { if (gMapMessageRegion.WheelState > 0) { MapScreenMsgScrollUp(1); } else { MapScreenMsgScrollDown(1); } ResetWheelState(&gMapMessageRegion); } } if (gMapMessageScrollBarRegion.uiFlags & MSYS_MOUSE_IN_AREA) { if (gMapMessageScrollBarRegion.WheelState != 0) { if (gMapMessageScrollBarRegion.WheelState > 0) { MapScreenMsgScrollUp(1); } else { MapScreenMsgScrollDown(1); } ResetWheelState(&gMapMessageScrollBarRegion); } } // Scroll through mercenaries if the mouse is inside any of these three panels. Couldn't use MOUSE_REGION wheelstates because it would've been messy due to the panels having higher priority mouse regions on top of the larger areas. // This way there are only three cleanly defined areas to check for. SGPPoint MousePos; GetMousePos(&MousePos); const auto x = MousePos.iX; const auto y = MousePos.iY; if ( ( (UI_CHARINV.Region.x < x && x < (UI_CHARINV.Region.x + UI_CHARINV.Region.width)) && (UI_CHARINV.Region.y < y && y < (UI_CHARINV.Region.y + UI_CHARINV.Region.height)) ) || ((UI_CHARPANEL.Region.x < x && x < (UI_CHARPANEL.Region.x + UI_CHARPANEL.Region.width)) && (UI_CHARPANEL.Region.y < y && y < (UI_CHARPANEL.Region.y + UI_CHARPANEL.Region.height))) || ((UI_CHARLIST.Region.x < x && x < (UI_CHARLIST.Region.x + UI_CHARLIST.Region.width)) && (UI_CHARLIST.Region.y < y && y < (UI_CHARLIST.Region.y + UI_CHARLIST.Region.height))) ) { const auto Wheelstate = _WheelValue * (gGameSettings.fOptions[TOPTION_INVERT_WHEEL] ? -1 : 1); if (Wheelstate < 0) { fResetMapCoords = TRUE; GoToNextCharacterInList(); } else if (Wheelstate > 0) { fResetMapCoords = TRUE; GoToPrevCharacterInList(); } _WheelValue = 0; } } void PollLeftButtonInMapView( UINT32 *puiNewEvent ) { static BOOLEAN fLBBeenPressedInMapView = FALSE; INT16 sMapX, sMapY; // if the mouse is currently over the MAP area if ( gMapViewRegion.uiFlags & MSYS_MOUSE_IN_AREA ) { // if L-button is down at the moment if ( gMapViewRegion.ButtonState & MSYS_LEFT_BUTTON ) { if ( !fLBBeenPressedInMapView ) { fLBBeenPressedInMapView = TRUE; RESETCOUNTER( LMOUSECLICK_DELAY_COUNTER ); gfAllowSkyriderTooFarQuote = FALSE; } } else // L-button is NOT down at the moment { if ( fLBBeenPressedInMapView ) { fLBBeenPressedInMapView = FALSE; RESETCOUNTER( LMOUSECLICK_DELAY_COUNTER ); // if we are showing help text in mapscreen if( fShowMapScreenHelpText ) { fShowMapScreenHelpText = FALSE; fCharacterInfoPanelDirty = TRUE; fMapPanelDirty = TRUE; return; } // if in militia redistribution popup if ( sSelectedMilitiaTown != 0 ) { // ignore clicks outside the box return; } // left click cancels MAP UI messages, unless we're in confirm map move mode if( ( giUIMessageOverlay != -1 ) && !gfInConfirmMapMoveMode ) { CancelMapUIMessage( ); // return unless moving the bullseye if ( !gfInChangeArrivalSectorMode ) return; } // ignore left clicks in the map screen if: // game just started or we're in the prebattle interface or if we are about to hit pre-battle if (is_networked) { if ( /*( gTacticalStatus.fDidGameJustStart == TRUE ) || */ // commented out to allow heli drop off change @/b4 start ;) ( gfPreBattleInterfaceActive == TRUE ) || ( fDisableMapInterfaceDueToBattle == TRUE ) ) { return; } } else { if ( ( gTacticalStatus.fDidGameJustStart == TRUE ) || ( gfPreBattleInterfaceActive == TRUE ) || ( fDisableMapInterfaceDueToBattle == TRUE ) ) { return; } } // if in "plot route" mode if ( ( GetSelectedDestChar() != -1) || fPlotForHelicopter || fPlotForMilitia ) { fEndPlotting = FALSE; GetMouseMapXY(&sMapX, &sMapY); // if he clicked on the last sector in his current path if( CheckIfClickOnLastSectorInPath( sMapX, sMapY ) ) { DestinationPlottingCompleted(); } else // clicked on a new sector { if ( fPlotForHelicopter ) gfAllowSkyriderTooFarQuote = TRUE; // draw new map route *puiNewEvent = MAP_EVENT_PLOT_PATH; } } else // not plotting movement { // if not plotting a path if( ( fEndPlotting == FALSE ) && ( fJustFinishedPlotting == FALSE ) ) { // make this sector selected / trigger movement box / start helicopter plotting / changing arrival sector *puiNewEvent = MAP_EVENT_CLICK_SECTOR; } fEndPlotting = FALSE; } // reset town info flag fShowTownInfo = FALSE; } } } fJustFinishedPlotting = FALSE; } void PollRightButtonInMapView( UINT32 *puiNewEvent ) { static BOOLEAN fRBBeenPressedInMapView = FALSE; INT16 sMapX, sMapY; // if the mouse is currently over the MAP area if ( gMapViewRegion.uiFlags & MSYS_MOUSE_IN_AREA ) { // if R-button is down at the moment if ( gMapViewRegion.ButtonState & MSYS_RIGHT_BUTTON ) { if ( !fRBBeenPressedInMapView ) { fRBBeenPressedInMapView = TRUE; RESETCOUNTER( RMOUSECLICK_DELAY_COUNTER ); } } else // R-button is NOT down at the moment { if ( fRBBeenPressedInMapView ) { fRBBeenPressedInMapView = FALSE; RESETCOUNTER( RMOUSECLICK_DELAY_COUNTER ); // if we are showing help text in mapscreen if( fShowMapScreenHelpText ) { fShowMapScreenHelpText = FALSE; fCharacterInfoPanelDirty = TRUE; fMapPanelDirty = TRUE; return; } // if in militia redistribution popup if ( sSelectedMilitiaTown != 0 ) { // ignore clicks outside the box return; } if ( gfInChangeArrivalSectorMode ) { CancelChangeArrivalSectorMode( ); MapScreenMessage( FONT_MCOLOR_LTYELLOW, MSG_MAP_UI_POSITION_MIDDLE, pBullseyeStrings[ 3 ] ); return; } // right click cancels MAP UI messages, unless we're in confirm map move mode if( ( giUIMessageOverlay != -1 ) && !gfInConfirmMapMoveMode ) { CancelMapUIMessage( ); return; } // ignore right clicks in the map area if: // game just started or we're in the prebattle interface or if we are about to hit pre-battle if ( ( gTacticalStatus.fDidGameJustStart == TRUE ) || ( gfPreBattleInterfaceActive == TRUE ) || ( fDisableMapInterfaceDueToBattle == TRUE ) ) { return; } if ( ( GetSelectedDestChar() != -1) || fPlotForHelicopter || fPlotForMilitia ) { // cancel/shorten the path *puiNewEvent = MAP_EVENT_CANCEL_PATH; } else { if ( GetMouseMapXY( &sMapX, &sMapY ) ) { // don't change sectors if we've just done the militia restrictions thing. if( ( sSelMapX != sMapX ) || ( sSelMapY != sMapY ) ) { ChangeSelectedMapSector( sMapX, sMapY, ( INT8 )iCurrentMapSectorZ ); } } // sector must be selected to bring up militia or town info boxes for it if ( ( sMapX == sSelMapX ) && ( sSelMapY == sMapY ) ) { if ( fShowMilitia == TRUE ) { HandleMilitiaRedistributionClick(); } else // show militia is OFF { // if on the surface, or a real underground sector (we've visited it) if ( ( iCurrentMapSectorZ == 0 ) || ( GetSectorFlagStatus( sMapX, sMapY, ( UINT8 ) iCurrentMapSectorZ, SF_ALREADY_VISITED ) == TRUE ) ) { // toggle sector info for this sector fShowTownInfo = !fShowTownInfo; fMapPanelDirty = TRUE; } } // fMapScreenBottomDirty = TRUE; CreateDestroyScreenMaskForAssignmentAndContractMenus( ); if( fShowTownInfo == FALSE ) { // destroy town info box CreateDestroyTownInfoBox( ); } } } } } } } void PopupText( STR16 pFontString, ... ) { UINT8 *pDestBuf; UINT32 uiDestPitchBYTES; va_list argptr; INT16 sX, sY; CHAR16 PopupString[512]; va_start(argptr, pFontString); // Set up variable argument pointer vswprintf(PopupString, pFontString, argptr); // process gprintf string (get output str) va_end(argptr); FindFontCenterCoordinates( 0, 0, SCREEN_WIDTH, INTERFACE_START_Y, PopupString, LARGEFONT1, &sX, &sY ); BltVideoSurface( FRAME_BUFFER, guiINTEXT, 0, xResOffset + 85, yResOffset + 160, VS_BLT_FAST | VS_BLT_USECOLORKEY, NULL ); pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES); SetFont( LARGEFONT1 ); SetFontBackground( FONT_MCOLOR_BLACK ); SetFontForeground( FONT_MCOLOR_DKGRAY ); mprintf_buffer( pDestBuf, uiDestPitchBYTES, LARGEFONT1, sX, sY, PopupString ); UnLockVideoSurface( FRAME_BUFFER ); InvalidateScreen( ); } void CreateMapCharInvIOregions() { // CHRISL: Setup default coords // Have to initialize map UI Coordinates, because inventory panel layout location depends on them. initMapViewAndBorderCoordinates(); if ((UsingNewInventorySystem() == true)) InitializeInvPanelCoordsNew(); else InitializeInvPanelCoordsOld(); InitInvSlotInterface(gMapScreenInvPocketXY, &gSCamoXY, MAPInvMoveCallback, MAPInvClickCallback, MAPInvMoveCamoCallback, MAPInvClickCamoCallback, FALSE); MSYS_EnableRegion(&gMPanelRegion); MSYS_EnableRegion(&gMapMercWeightRegion); MSYS_EnableRegion(&gMapMercCamoRegion); // dirty character info panel ( Why? ARM ) fCharacterInfoPanelDirty = TRUE; fTeamPanelDirty = TRUE; fResetMapCoords = TRUE; // Create trashcan and keyring buttons fShowInventoryFlag = TRUE; CreateDestroyTrashCanRegion(); // Disable map inventory button, since widescreen res always has character inventory visible DisableButton(giMapInvDoneButton); fShowInventoryFlag = FALSE; } void DestroyMapCharInvIOregions() { ShutdownInvSlotInterface(); fTeamPanelDirty = TRUE; MSYS_DisableRegion(&gMPanelRegion); MSYS_DisableRegion(&gMapMercWeightRegion); MSYS_DisableRegion(&gMapMercCamoRegion); RemoveTeamPanelSortButtonsForMapScreen(); } void CreateDestroyMapInvButton() { static BOOLEAN fOldShowInventoryFlag=FALSE; if( fShowInventoryFlag && !fOldShowInventoryFlag ) { // create inventory button fOldShowInventoryFlag=TRUE; //giMapInvButtonImage= LoadButtonImage( "INTERFACE\\mapinv.sti" ,-1,1,-1,2,-1 ); //giMapInvButton= QuickCreateButton( giMapInvButtonImage, INV_BTN_X-1, INV_BTN_Y, // BUTTON_TOGGLE, MSYS_PRIORITY_HIGHEST - 1, // BUTTON_NO_CALLBACK, (GUI_CALLBACK)BtnINVCallback); // disable allmouse regions in this space fTeamPanelDirty=TRUE; // CHRISL: Setup default coords // Have to initialize map UI Coordinates, because inventory panel layout location depends on them. initMapViewAndBorderCoordinates(); if((UsingNewInventorySystem() == true)) InitializeInvPanelCoordsNew(); else InitializeInvPanelCoordsOld(); if (bSelectedInfoChar != -1 && gCharactersList[bSelectedInfoChar].fValid) { SOLDIERTYPE* pSoldier = gCharactersList[bSelectedInfoChar].usSolID; if (!(pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE) && !AM_A_ROBOT(pSoldier)) { InitInvSlotInterface(gMapScreenInvPocketXY, &gSCamoXY, MAPInvMoveCallback, MAPInvClickCallback, MAPInvMoveCamoCallback, MAPInvClickCamoCallback, FALSE); } } MSYS_EnableRegion(&gMPanelRegion); MSYS_EnableRegion(&gMapMercWeightRegion); MSYS_EnableRegion(&gMapMercCamoRegion); // switch hand region help text to "Exit Inventory" SetRegionFastHelpText( &gCharInfoHandRegion, pMiscMapScreenMouseRegionHelpText[ 2 ] ); // reset inventory item help text memset( gubMAP_HandInvDispText, 0, sizeof( gubMAP_HandInvDispText ) ); // dirty character info panel ( Why? ARM ) fCharacterInfoPanelDirty=TRUE; fResetMapCoords=TRUE; } else if( !fShowInventoryFlag && fOldShowInventoryFlag ) { // destroy inventory button ShutdownInvSlotInterface( ); fOldShowInventoryFlag=FALSE; //RemoveButton( giMapInvButton ); //UnloadButtonImage( giMapInvButtonImage ); fTeamPanelDirty=TRUE; MSYS_DisableRegion(&gMPanelRegion); MSYS_DisableRegion(&gMapMercWeightRegion); MSYS_DisableRegion(&gMapMercCamoRegion); // switch hand region help text to "Enter Inventory" SetRegionFastHelpText( &gCharInfoHandRegion, pMiscMapScreenMouseRegionHelpText[ 0 ] ); // force immediate reblit of item in HANDPOS now that it's not blitted while in inventory mode fCharacterInfoPanelDirty=TRUE; } } void BltEmptyCharInvPanel() { UINT32 uiDestPitchBYTES; UINT16* pDestBuf; HVOBJECT hCharListHandle; UINT8 stiIndex = 0; if (UsingNewInventorySystem()) { stiIndex = 1; } pDestBuf = (UINT16*)LockVideoSurface(guiSAVEBUFFER, &uiDestPitchBYTES); GetVideoObject(&hCharListHandle, guiMAPINV); Blt8BPPDataTo16BPPBufferTransparent(pDestBuf, uiDestPitchBYTES, hCharListHandle, UI_CHARINV.Region.x, UI_CHARINV.Region.y, stiIndex); UnLockVideoSurface(guiSAVEBUFFER); } void BltCharInvPanel() { UINT32 uiDestPitchBYTES; UINT16 *pDestBuf; HVOBJECT hCharListHandle; SOLDIERTYPE *pSoldier; CHAR16 sString[ 32 ]; INT16 usX, usY; UINT8 mapInvIndex = 0; // make sure we're here legally // In widescreen UI, draw an empty inv panel if no accessible inventory const BOOLEAN isAccessibleInventory = MapCharacterHasAccessibleInventory(bSelectedInfoChar); if (isWidescreenUI() && !isAccessibleInventory) { BltEmptyCharInvPanel(); return; } else { Assert(isAccessibleInventory); } GetSoldier( &pSoldier, gCharactersList[bSelectedInfoChar].usSolID ); Assert(pSoldier); // CHRISL: Changed last parameter so we can display graphic based on inventory system used if((UsingNewInventorySystem() == true) && gGameExternalOptions.fVehicleInventory && (pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE)) { if(fResetMapCoords) { InitializeInvPanelCoordsVehicle(); // This function sets the mouse regions for the vehicle inventory InitInventoryVehicle(gMapScreenInvPocketXY, MAPInvMoveCallback, MAPInvClickCallback, FALSE); fResetMapCoords=FALSE; } mapInvIndex = 2; } else if (UsingNewInventorySystem() && AM_A_ROBOT(pSoldier)) { if (fResetMapCoords) { InitializeInvPanelCoordsRobot(); InitInventoryRobot(gMapScreenInvPocketXY, MAPInvMoveCallback, MAPInvClickCallback, FALSE); fResetMapCoords = FALSE; } mapInvIndex = 3; } else if((UsingNewInventorySystem() == true)) { if(fResetMapCoords) { InitializeInvPanelCoordsNew(); // This function sets the mouse regions for the soldier inventory InitInventorySoldier(gMapScreenInvPocketXY, MAPInvMoveCallback, MAPInvClickCallback, FALSE, TRUE); fResetMapCoords=FALSE; } mapInvIndex = 1; } else { //InitializeInvPanelCoordsOld(); InitInventorySoldier(gMapScreenInvPocketXY, MAPInvMoveCallback, MAPInvClickCallback, FALSE, FALSE); } pDestBuf = (UINT16*)LockVideoSurface(guiSAVEBUFFER, &uiDestPitchBYTES); GetVideoObject(&hCharListHandle, guiMAPINV); Blt8BPPDataTo16BPPBufferTransparent( pDestBuf, uiDestPitchBYTES, hCharListHandle, UI_CHARINV.Region.x, UI_CHARINV.Region.y, mapInvIndex); UnLockVideoSurface( guiSAVEBUFFER ); // this soldier is a robot - the above initialisation set up the UI background, and this will draw the individual attachment slots if (UsingNewInventorySystem() && AM_A_ROBOT(pSoldier)) { // draw slot for robot's installed weapon BltVideoObjectFromIndex(guiSAVEBUFFER, guiMapScreenAttachmentSlot, 1, UI_CHARINV.Text.RobotWeaponLabel.iX, UI_CHARINV.Text.RobotWeaponLabel.iY + 10, VO_BLT_SRCTRANSPARENCY, NULL); // draw robot upgrade slots for (int a = 0; a <= NUM_INV_SLOTS; ++a) if (robotInv[a]) BltVideoObjectFromIndex(guiSAVEBUFFER, guiMapScreenAttachmentSlot, 1, gMapScreenInvPocketXY[a].sX - 6, gMapScreenInvPocketXY[a].sY, VO_BLT_SRCTRANSPARENCY, NULL); } if (!isWidescreenUI()) { CreateDestroyMapInvButton(); } if (gfCheckForMouseOverItem) { if (HandleCompatibleAmmoUI(pSoldier, (INT8)gbCheckForMouseOverItemPos, TRUE)) { // if showing sector inventory if (fShowMapInventoryPool) { fMapPanelDirty = TRUE; } fTeamPanelDirty = TRUE; } gfCheckForMouseOverItem = FALSE; } if( ( fShowMapInventoryPool ) ) { if( iCurrentlyHighLightedItem != -1 ) { HandleCompatibleAmmoUIForMapScreen( pSoldier, (INT32)( iCurrentlyHighLightedItem + ( iCurrentInventoryPoolPage * MAP_INVENTORY_POOL_SLOT_COUNT ) ) , TRUE, FALSE ); } } RenderInvBodyPanel(pSoldier, UI_CHARINV.BodyPanel.iX, UI_CHARINV.BodyPanel.iY); // reset font destination buffer to the save buffer SetFontDestBuffer( guiSAVEBUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, FALSE ); // render items in each of chars slots HandleRenderInvSlots( pSoldier, DIRTYLEVEL2 ); // reset font destination buffer SetFontDestBuffer( FRAME_BUFFER, 0,0, SCREEN_WIDTH, SCREEN_HEIGHT, FALSE ); SetFont( BLOCKFONT2 ); // Render Values for stats! // Set font drawing to saved buffer SetFontDestBuffer( guiSAVEBUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, FALSE ); SetFontBackground( FONT_MCOLOR_BLACK ); SetFontForeground( MAP_INV_STATS_TITLE_FONT_COLOR ); // CHRISL: Only display next three values if we're a merc if(!(pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE) && !AM_A_ROBOT(pSoldier)) { // print armor/weight/camo labels mprintf(UI_CHARINV.Text.ArmorLabel.iX, UI_CHARINV.Text.ArmorLabel.iY, pInvPanelTitleStrings[ 0 ] ); if( g_lang == i18n::Lang::zh ) { mprintf(UI_CHARINV.Text.ArmorPercent.iX, UI_CHARINV.Text.ArmorPercent.iY, ChineseSpecString1 ); } else { mprintf(UI_CHARINV.Text.ArmorPercent.iX, UI_CHARINV.Text.ArmorPercent.iY, L"%%" ); } mprintf(UI_CHARINV.Text.WeightLabel.iX, UI_CHARINV.Text.WeightLabel.iY, pInvPanelTitleStrings[ 1 ] ); if( g_lang == i18n::Lang::zh ) { mprintf(UI_CHARINV.Text.WeightPercent.iX, UI_CHARINV.Text.WeightPercent.iY, ChineseSpecString1 ); } else { mprintf(UI_CHARINV.Text.WeightPercent.iX, UI_CHARINV.Text.WeightPercent.iY, L"%%" ); } mprintf(UI_CHARINV.Text.CamoLabel.iX, UI_CHARINV.Text.CamoLabel.iY, pInvPanelTitleStrings[ 2 ] ); if( g_lang == i18n::Lang::zh ) { mprintf(UI_CHARINV.Text.CamoPercent.iX, UI_CHARINV.Text.CamoPercent.iY, ChineseSpecString1 ); } else { mprintf(UI_CHARINV.Text.CamoPercent.iX, UI_CHARINV.Text.CamoPercent.iY, L"%%" ); } const auto width = UI_CHARINV.Text.PercentWidth; const auto height = UI_CHARINV.Text.PercentHeight; // display armor value swprintf( sString, L"%3d", ArmourPercent( pSoldier ) ); FindFontRightCoordinates( UI_CHARINV.Text.Armor.iX, UI_CHARINV.Text.Armor.iY, width, height, sString, BLOCKFONT2, &usX, &usY ); mprintf( usX, usY, sString ); // Display weight value swprintf( sString, L"%3d", CalculateCarriedWeight( pSoldier ) ); FindFontRightCoordinates(UI_CHARINV.Text.Weight.iX, UI_CHARINV.Text.Weight.iY, width, height, sString, BLOCKFONT2, &usX, &usY); mprintf( usX, usY, sString ); ApplyEquipmentBonuses(pSoldier); // Display camo value swprintf( sString, L"%3d", max(0, min(max((pSoldier->bCamo + pSoldier->wornCamo), max((pSoldier->urbanCamo+pSoldier->wornUrbanCamo), max((pSoldier->desertCamo+pSoldier->wornDesertCamo), (pSoldier->snowCamo+pSoldier->wornSnowCamo)))),100)) ); FindFontRightCoordinates(UI_CHARINV.Text.Camo.iX, UI_CHARINV.Text.Camo.iY, width, height, sString, BLOCKFONT2, &usX, &usY); mprintf( usX, usY, sString ); if( fCharacterInfoPanelDirty ) { static CHAR16 pStr[ 200 ]; // detailed camo info popup CHAR16 pStrCamo[400]; swprintf( pStrCamo, L"" ); swprintf( pStr, L""); if ((pSoldier->bCamo + pSoldier->wornCamo) > 0 ) { swprintf( pStrCamo, L"\n%d/%d%s %s", pSoldier->bCamo, pSoldier->wornCamo, L"%", gzMiscItemStatsFasthelp[ 21 ]); wcscat( pStr, pStrCamo); swprintf( pStrCamo, L"" ); } if ((pSoldier->urbanCamo + pSoldier->wornUrbanCamo) > 0 ) { swprintf( pStrCamo, L"\n%d/%d%s %s", pSoldier->urbanCamo, pSoldier->wornUrbanCamo, L"%", gzMiscItemStatsFasthelp[ 22 ]); wcscat( pStr, pStrCamo); swprintf( pStrCamo, L"" ); } if ((pSoldier->desertCamo + pSoldier->wornDesertCamo) > 0 ) { swprintf( pStrCamo, L"\n%d/%d%s %s", pSoldier->desertCamo, pSoldier->wornDesertCamo, L"%", gzMiscItemStatsFasthelp[ 23 ]); wcscat( pStr, pStrCamo); swprintf( pStrCamo, L"" ); } if ((pSoldier->snowCamo + pSoldier->wornSnowCamo) > 0 ) { swprintf( pStrCamo, L"\n%d/%d%s %s", pSoldier->snowCamo, pSoldier->wornSnowCamo, L"%", gzMiscItemStatsFasthelp[ 24 ] ); wcscat( pStr, pStrCamo); swprintf( pStrCamo, L"" ); } // anv: display stealth together with camo INT16 wornstealth = GetWornStealth(pSoldier) - pSoldier->GetBackgroundValue(BG_PERC_STEALTH); INT16 bonusstealth = pSoldier->GetBackgroundValue(BG_PERC_STEALTH); if ( pSoldier->ubBodyType == BLOODCAT ) { bonusstealth += 50; } // SANDRO - new/old traits else if ( gGameOptions.fNewTraitSystem && HAS_SKILL_TRAIT( pSoldier, STEALTHY_NT )) { bonusstealth += gSkillTraitValues.ubSTBonusToMoveQuietly; } else if ( !gGameOptions.fNewTraitSystem && HAS_SKILL_TRAIT( pSoldier, STEALTHY_OT )) { bonusstealth += 25 * NUM_SKILL_TRAITS( pSoldier, STEALTHY_OT ); } if ( bonusstealth != 0 || wornstealth!= 0 ) { CHAR16 pStrBonusStealth[400]; CHAR16 pStrWornStealth[400]; if( bonusstealth < 0 ) swprintf( pStrBonusStealth, L"%d", bonusstealth ); else swprintf( pStrBonusStealth, L"+%d", bonusstealth ); if( wornstealth < 0 ) swprintf( pStrWornStealth, L"%d", wornstealth ); else swprintf( pStrWornStealth, L"+%d", wornstealth ); swprintf( pStrCamo, L"\n%s/%s %s", pStrBonusStealth, pStrWornStealth, gzMiscItemStatsFasthelp[ 25 ] ); wcscat( pStr, pStrCamo); swprintf( pStrCamo, L"" ); } SetRegionFastHelpText( &(gMapMercCamoRegion), pStr ); // Flugente: weight help text FLOAT totalweight = GetTotalWeight( pSoldier ); swprintf( pStr, gzMiscItemStatsFasthelp[35], totalweight / 10.0 ); SetRegionFastHelpText( &(gMapMercWeightRegion), pStr ); } } else if (AM_A_ROBOT(pSoldier)) { // draw robot upgrade text labels mprintf(UI_CHARINV.Text.RobotWeaponLabel.iX, UI_CHARINV.Text.RobotWeaponLabel.iY, szRobotText[ ROBOT_TEXT_INSTALLED_WEAPON ] ); mprintf(UI_CHARINV.Text.RobotAmmoLabel.iX, UI_CHARINV.Text.RobotAmmoLabel.iY, szRobotText[ ROBOT_TEXT_SLOT_AMMO ] ); mprintf(UI_CHARINV.Text.RobotTargetingLabel.iX, UI_CHARINV.Text.RobotTargetingLabel.iY, szRobotText[ ROBOT_TEXT_SLOT_TARGETING ] ); mprintf(UI_CHARINV.Text.RobotChassisLabel.iX, UI_CHARINV.Text.RobotChassisLabel.iY, szRobotText[ ROBOT_TEXT_SLOT_CHASSIS ] ); mprintf(UI_CHARINV.Text.RobotUtilityLabel.iX, UI_CHARINV.Text.RobotUtilityLabel.iY, szRobotText[ ROBOT_TEXT_SLOT_UTILITY ] ); mprintf(UI_CHARINV.Text.RobotInventoryLabel.iX, UI_CHARINV.Text.RobotInventoryLabel.iY, szRobotText[ ROBOT_TEXT_SLOT_INVENTORY ] ); // draw robot upgrade bonus text CHAR16 text[500]; UINT32 fontColour = FONT_MCOLOR_RED; // robot targeting bonus if (ItemProvidesRobotLaserBonus(pSoldier->inv[ROBOT_TARGETING_SLOT].usItem)) { swprintf(text, szRobotText[ROBOT_TEXT_LASER]); fontColour = FONT_MCOLOR_LTGREEN; } else if (ItemProvidesRobotNightvision(pSoldier->inv[ROBOT_TARGETING_SLOT].usItem)) { swprintf(text, szRobotText[ROBOT_TEXT_NIGHT_VISION]); fontColour = FONT_MCOLOR_LTGREEN; } else if (Item[pSoldier->inv[ROBOT_TARGETING_SLOT].usItem].bRobotTargetingSkillGrant > 0) { swprintf(text, szRobotText[ROBOT_TEXT_SKILL_GRANTED], gzMercSkillTextNew[Item[pSoldier->inv[ROBOT_TARGETING_SLOT].usItem].bRobotTargetingSkillGrant]); fontColour = FONT_MCOLOR_LTGREEN; } else { swprintf(text, szRobotText[ROBOT_TEXT_NO_BONUS]); fontColour = FONT_MCOLOR_RED; } DisplayWrappedString(UI_CHARINV.Text.RobotTargetingBonus.iX, UI_CHARINV.Text.RobotTargetingBonus.iY, 170, 2, FONT10ARIAL, fontColour, text, FONT_MCOLOR_BLACK, FALSE, 0); // robot chassis bonus if (Item[pSoldier->inv[ROBOT_CHASSIS_SLOT].usItem].bRobotStrBonus > 0 || Item[pSoldier->inv[ROBOT_CHASSIS_SLOT].usItem].bRobotAgiBonus > 0 || Item[pSoldier->inv[ROBOT_CHASSIS_SLOT].usItem].bRobotDexBonus > 0) { swprintf(text, szRobotText[ROBOT_TEXT_STAT_BONUSES]); fontColour = FONT_MCOLOR_LTGREEN; } else if (ItemProvidesRobotCamo(pSoldier->inv[ROBOT_CHASSIS_SLOT].usItem)) { swprintf(text, szRobotText[ROBOT_TEXT_CAMO]); fontColour = FONT_MCOLOR_LTGREEN; } else if (Item[pSoldier->inv[ROBOT_CHASSIS_SLOT].usItem].fRobotDamageReductionModifier > 0.0f && Item[pSoldier->inv[ROBOT_CHASSIS_SLOT].usItem].fRobotDamageReductionModifier < 1.0f) { swprintf(text, szRobotText[ROBOT_TEXT_PLATE]); fontColour = FONT_MCOLOR_LTGREEN; } else if (Item[pSoldier->inv[ROBOT_CHASSIS_SLOT].usItem].bRobotChassisSkillGrant > 0) { swprintf(text, szRobotText[ROBOT_TEXT_SKILL_GRANTED], gzMercSkillTextNew[Item[pSoldier->inv[ROBOT_CHASSIS_SLOT].usItem].bRobotChassisSkillGrant]); fontColour = FONT_MCOLOR_LTGREEN; } else { swprintf(text, szRobotText[ROBOT_TEXT_NO_BONUS]); fontColour = FONT_MCOLOR_RED; } DisplayWrappedString(UI_CHARINV.Text.RobotChassisBonus.iX, UI_CHARINV.Text.RobotChassisBonus.iY, 170, 2, FONT10ARIAL, fontColour, text, FONT_MCOLOR_BLACK, FALSE, 0); // robot utility bonus if ( HasItemFlag( pSoldier->inv[ROBOT_UTILITY_SLOT].usItem, CLEANING_KIT ) ) { swprintf(text, L"%s", szRobotText[ROBOT_TEXT_CLEANING_KIT]); fontColour = FONT_MCOLOR_LTGREEN; } else if ( HasItemFlag(pSoldier->inv[ROBOT_UTILITY_SLOT].usItem, RADIO_SET ) ) { swprintf(text, L"%s", szRobotText[ROBOT_TEXT_RADIO]); fontColour = FONT_MCOLOR_LTGREEN; } else if (ItemIsMetalDetector(pSoldier->inv[ROBOT_UTILITY_SLOT].usItem)) { swprintf(text, L"%s", szRobotText[ROBOT_TEXT_METAL_DETECTOR]); fontColour = FONT_MCOLOR_LTGREEN; } else if (ItemHasXRay(pSoldier->inv[ROBOT_UTILITY_SLOT].usItem)) { swprintf(text, L"%s", szRobotText[ROBOT_TEXT_XRAY]); fontColour = FONT_MCOLOR_LTGREEN; } else if (Item[pSoldier->inv[ROBOT_UTILITY_SLOT].usItem].bRobotUtilitySkillGrant > 0) { swprintf(text, szRobotText[ROBOT_TEXT_SKILL_GRANTED], gzMercSkillTextNew[Item[pSoldier->inv[ROBOT_UTILITY_SLOT].usItem].bRobotUtilitySkillGrant]); fontColour = FONT_MCOLOR_LTGREEN; } else { swprintf(text, L"%s", szRobotText[ROBOT_TEXT_NO_BONUS]); fontColour = FONT_MCOLOR_RED; } DisplayWrappedString(UI_CHARINV.Text.RobotUtilityBonus.iX, UI_CHARINV.Text.RobotUtilityBonus.iY, 170, 2, FONT10ARIAL, fontColour, text, FONT_MCOLOR_BLACK, FALSE, 0); } if(!(pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE) && !AM_A_ROBOT(pSoldier)) { MSYS_EnableRegion(&gMapMercCamoRegion); MSYS_EnableRegion(&gMapMercWeightRegion); } else { MSYS_DisableRegion(&gMapMercCamoRegion); MSYS_DisableRegion(&gMapMercWeightRegion); } if( InKeyRingPopup( ) ) { // shade the background const auto x = UI_CHARINV.Region.x; const auto y = UI_CHARINV.Region.y; const auto width = UI_CHARINV.Region.width; const auto height = UI_CHARINV.Region.height; ShadowVideoSurfaceRect( guiSAVEBUFFER , x, y, x + width, y + height); } else { // blit gold key on top of key ring if key ring is not empty } SetFontDestBuffer( FRAME_BUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, FALSE ); } // check for and highlight any ammo void HandleCursorOverRifleAmmo( ) { if( fShowInventoryFlag == FALSE ) { return; } if( gbCheckForMouseOverItemPos == -1 ) { return; } if ( gfCheckForMouseOverItem ) { if ( HandleCompatibleAmmoUI( gCharactersList[ bSelectedInfoChar ].usSolID, (INT8)gbCheckForMouseOverItemPos, TRUE ) ) { if ( ( GetJA2Clock( ) - guiMouseOverItemTime ) > 100 ) { fTeamPanelDirty = TRUE; } } } } void MAPInvClickCamoCallback( MOUSE_REGION *pRegion, INT32 iReason ) { if ( iReason & MSYS_CALLBACK_REASON_INIT ) { return; } if ( iReason & MSYS_CALLBACK_REASON_LBUTTON_DWN ) { // Apply camo ( if we have something in cursor... ) // If we do not have an item in hand, start moving it SOLDIERTYPE* pSoldier = NULL; if( (bSelectedInfoChar != -1) && (gCharactersList[bSelectedInfoChar].fValid == TRUE) ) { pSoldier = gCharactersList[bSelectedInfoChar].usSolID; } if ( gpItemPointer && pSoldier ) { // We are doing this ourselve, continue if ( pSoldier->stats.bLife >= CONSCIOUSNESS ) { BOOLEAN bApplyConsumable = ApplyConsumable(pSoldier, gpItemPointer, FALSE, TRUE); if (bApplyConsumable == TRUE) { UpdateMercBodyRegionHelpText( ); } else if(!bApplyConsumable) { // Send message //Heinz: 23.02.09 BUGFIX: Don't send message when SKI is on if ( !(guiTacticalInterfaceFlags & INTERFACE_SHOPKEEP_INTERFACE) ) ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, TacticalStr[CANNOT_DO_INV_STUFF_STR] ); } // Check if it's the same now! if ( !gpItemPointer->exists( ) ) { gbCompatibleApplyItem = FALSE; //EndItemPointer( ); MAPEndItemPointer( ); } } } } else if ( iReason & MSYS_CALLBACK_REASON_RBUTTON_DWN ) { } } void MAPInvMoveCamoCallback( MOUSE_REGION *pRegion, INT32 iReason ) { } // this is Map Screen's version of SMInvMoveCallback() void MAPInvMoveCallback( MOUSE_REGION *pRegion, INT32 iReason ) { SOLDIERTYPE *pSoldier; UINT32 uiHandPos; if (iReason & MSYS_CALLBACK_REASON_INIT) { return; } // make sure we're here legally const BOOLEAN isLegal = MapCharacterHasAccessibleInventory(bSelectedInfoChar); if (!isLegal && isWidescreenUI()) { return; } else { Assert(isLegal); } GetSoldier( &pSoldier, gCharactersList[ bSelectedInfoChar ].usSolID ); uiHandPos = MSYS_GetRegionUserData( pRegion, 0 ); if (pSoldier->inv[uiHandPos].exists() == false) return; if (iReason == MSYS_CALLBACK_REASON_MOVE) { } else if (iReason == MSYS_CALLBACK_REASON_GAIN_MOUSE ) { if (gpItemPointer == NULL) { gubMAP_HandInvDispText[uiHandPos] = 2; guiMouseOverItemTime = GetJA2Clock(); gfCheckForMouseOverItem = TRUE; gbCheckForMouseOverItemPos = (INT8)uiHandPos; fTeamPanelDirty = TRUE; } } if (iReason == MSYS_CALLBACK_REASON_LOST_MOUSE ) { if (gpItemPointer == NULL) { gubMAP_HandInvDispText[uiHandPos] = 1; HandleCompatibleAmmoUI(pSoldier, (INT8)uiHandPos, FALSE); gfCheckForMouseOverItem = FALSE; gbCheckForMouseOverItemPos = NO_SLOT; fTeamPanelDirty = TRUE; } } } // mapscreen wrapper to init the item description box BOOLEAN MAPInternalInitItemDescriptionBox( OBJECTTYPE *pObject, UINT8 ubStatusIndex, SOLDIERTYPE *pSoldier ) { BOOLEAN fRet; fRet = InternalInitItemDescriptionBox( pObject, MAP_ITEMDESC_START_X, MAP_ITEMDESC_START_Y, ubStatusIndex, pSoldier ); fShowDescriptionFlag=TRUE; fTeamPanelDirty=TRUE; fInterfacePanelDirty = DIRTYLEVEL2; return( fRet ); } //CHRISL: functons for LBENODE system extern BOOLEAN ChangeZipperStatus(SOLDIERTYPE *pSoldier, BOOLEAN newStatus); // this is Map Screen's version of SMInvClickCallback() void MAPInvClickCallback( MOUSE_REGION *pRegion, INT32 iReason ) { SOLDIERTYPE *pSoldier; UINT32 uiHandPos; UINT16 usOldItemIndex, usNewItemIndex, usCostToMoveItem = 0; static BOOLEAN fRightDown = FALSE; // OJW - 20090319 - fix merging bug on mapscreen // If you left click a merge item such as EBR stock, then left click it on the item to merge, such as M-14... // instead of right clicking (which is the correct action to merge) // it will open an ItemDescriptionPanel, but then after that call PlaceObject, which performs a swap // and overwites the gpItemDescObject pointer. Hence when the ItemDescriptionPanel is deleted // it no longer references the right object, and does not necessarily free up all resources // creating an error the next time it is called bool bJustOpenedItemDescPanel = false; if (iReason & MSYS_CALLBACK_REASON_INIT) { return; } // make sure we're here legally const BOOLEAN isLegal = MapCharacterHasAccessibleInventory(bSelectedInfoChar); if (!isLegal && isWidescreenUI()) { return; } else { Assert(isLegal); } GetSoldier( &pSoldier, gCharactersList[ bSelectedInfoChar ].usSolID ); uiHandPos = MSYS_GetRegionUserData( pRegion, 0 ); // CHRISL: Are we in combat, wearing a backpack with the zipper closed? Don't allow access to backpack items if((UsingNewInventorySystem() == true)) if(icLBE[uiHandPos] == BPACKPOCKPOS && (!(pSoldier->flags.ZipperFlag) || (pSoldier->flags.ZipperFlag && gAnimControl[pSoldier->usAnimState].ubEndHeight == ANIM_STAND)) && (gTacticalStatus.uiFlags & INCOMBAT) && (iReason & MSYS_CALLBACK_REASON_LBUTTON_UP )) iReason = MSYS_CALLBACK_REASON_NONE; if (iReason & MSYS_CALLBACK_REASON_LBUTTON_UP) { // If we do not have an item in hand, start moving it if ( gpItemPointer == NULL ) { if ( pSoldier->inv[ uiHandPos ].exists() == false ) { if ( gGameSettings.fOptions[TOPTION_ENABLE_INVENTORY_POPUPS] == TRUE && !IsVehicle( pSoldier ) && !AM_A_ROBOT(pSoldier)) // the_bob : enable popups for picking items from sector inv { if ( _KeyDown(CTRL) ) { PocketPopupFull( pSoldier, uiHandPos ); // if ctrl is pressed, display all options } else { PocketPopupDefault( pSoldier, uiHandPos ); // display pocket-specific options } } return; } //ATE: Put this here to handle Nails refusal.... if ( HandleNailsVestFetish( pSoldier, uiHandPos, NOTHING ) ) { return; } // rftr: robot can't unequip weapon if (AM_A_ROBOT(pSoldier) && uiHandPos == HANDPOS) { DoMessageBox(MSG_BOX_BASIC_STYLE, szRobotText[ROBOT_TEXT_CANNOT_CHANGE_INSTALLED_WEAPON], guiCurrentScreen, (UINT8)MSG_BOX_FLAG_OK, NULL, NULL); return; } /* CHRISL: For New Inventory system. Are we removing an existing LBE item? If so, we need to pull all items in the relevant IC Group pockets out of the soldiers inventory and put them into the LBE items inventory. But first, find out if we already have a LBE item inventory for this item and this merc. If we do, remove the items from it and place them into the sector the LBE inventory is located in.*/ if((UsingNewInventorySystem() == true) && !(pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE) && !AM_A_ROBOT(pSoldier)) { /*if we pick up a backpack without reactivating the drop pack button, and we have a dropkey, reactivate the button*/ if(uiHandPos == BPACKPOCKPOS) { // Deal with the zipper before we do anything if(pSoldier->flags.ZipperFlag) if(!ChangeZipperStatus(pSoldier, FALSE)) return; // Do we still have a linked backpack? If so, reset droppackflag for(unsigned int wi = 0; wi < guiNumWorldItems; wi++) { if(gWorldItems[wi].soldierID == pSoldier->ubID && gWorldItems[wi].object.exists() == true) { pSoldier->flags.DropPackFlag = TRUE; } } } } // remember what it was usOldItemIndex = pSoldier->inv[ uiHandPos ].usItem; iLastHandPos = uiHandPos; // pick it up MAPBeginItemPointer( pSoldier, (UINT8)uiHandPos ); // remember which gridno the object came from sObjectSourceGridNo = pSoldier->sGridNo; HandleTacticalEffectsOfEquipmentChange( pSoldier, uiHandPos, usOldItemIndex, NOTHING ); fInterfacePanelDirty = DIRTYLEVEL2; fCharacterInfoPanelDirty = TRUE; } else // item in cursor { // can we pass this part due to booby traps if( ContinuePastBoobyTrapInMapScreen( gpItemPointer, pSoldier ) == FALSE ) { return; } if (UsingInventoryCostsAPSystem() && (gTacticalStatus.uiFlags & INCOMBAT) && pSoldier->bInSector) { if (!CanItemFitInPosition(pSoldier, gpItemPointer, (INT8)uiHandPos, FALSE))//dnl ch66 070913 return; //Jenilee: determine the cost of moving this item around in our inventory usCostToMoveItem = GetInvMovementCost(gpItemPointer, iLastHandPos, uiHandPos); // Flugente: backgrounds usCostToMoveItem = (usCostToMoveItem * (100 + pSoldier->GetBackgroundValue(BG_INVENTORY))) / 100; //we dont have enough APs to move it to this slot, show a warning message if (usCostToMoveItem > 0 && pSoldier->bActionPoints < usCostToMoveItem && pSoldier->inv[iLastHandPos].usItem == NULL) { ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, TacticalStr[NOT_ENOUGH_APS_STR]); return; } } usOldItemIndex = pSoldier->inv[uiHandPos].usItem; usNewItemIndex = gpItemPointer->usItem; //ATE: Put this here to handle Nails refusal.... if ( HandleNailsVestFetish( pSoldier, uiHandPos, usNewItemIndex ) ) { return; } if ( _KeyDown(CTRL) ) { if ( pSoldier->inv[ uiHandPos ].exists() && gpItemPointer->exists() ) { if (pSoldier->inv[ uiHandPos ].usItem == gpItemPointer->usItem) CleanUpStack( &( pSoldier->inv[ uiHandPos ] ), gpItemPointer ); else //Madd: attach / merge object, merge only works on single objects for now { UINT8 cnt = pSoldier->inv[ uiHandPos ].ubNumberOfObjects; if ( gpItemPointer->ubNumberOfObjects < cnt ) cnt = gpItemPointer->ubNumberOfObjects; for (UINT8 i = 0; ibInSector) { // silversurfer: This didn't cost any AP. Why? CTRL + LeftClick should deduct the same AP as manual attachment in the EDB. usCostToMoveItem = AttachmentAPCost(gpItemPointer->usItem, pSoldier->inv[uiHandPos].usItem, pSoldier); // Flugente: backgrounds usCostToMoveItem = (usCostToMoveItem * (100 + pSoldier->GetBackgroundValue(BG_INVENTORY))) / 100; // do we have enough AP? if (!EnoughPoints(pSoldier, usCostToMoveItem, 0, TRUE)) return; pSoldier->bActionPoints -= usCostToMoveItem; //this will force redraw APs shown at merc portrait fCharacterInfoPanelDirty = TRUE; } if(pSoldier->inv[uiHandPos].AttachObject(pSoldier, gpItemPointer, TRUE, i)) fTeamPanelDirty = TRUE;//this will fix merged items not updating when we hold stack of items in hand } } } if ( gpItemPointer->exists() == false ) { MAPEndItemPointer( ); } return; } // hold ALT key to swap valid attachment item instead if ( _KeyDown(ALT) ) { // do nothing } else if ( ValidAttachment( usNewItemIndex, usOldItemIndex ) ) { // rftr: robot can't equip weapon attachments if (AM_A_ROBOT(pSoldier) && uiHandPos == HANDPOS) { DoMessageBox(MSG_BOX_BASIC_STYLE, szRobotText[ROBOT_TEXT_CANNOT_ADD_ATTACHMENTS], guiCurrentScreen, (UINT8)MSG_BOX_FLAG_OK, NULL, NULL); return; } // it's an attempt to attach; bring up the inventory panel if ( !InItemDescriptionBox( ) ) { // HEADROCK HAM 5: Sector Inventory Item Desc Box no longer accessible during combat. if( gTacticalStatus.uiFlags & INCOMBAT ) { DoScreenIndependantMessageBox( New113HAMMessage[ 23 ], MSG_BOX_FLAG_OK, NULL ); return; } else { MAPInternalInitItemDescriptionBox( &(pSoldier->inv[ uiHandPos ]), 0, pSoldier ); } } return; } // !!! MERGING ITEMS IN MAP SCREEN IS NOT SUPPORTED !!! if ( uiHandPos == HANDPOS || uiHandPos == SECONDHANDPOS || uiHandPos == HELMETPOS || uiHandPos == VESTPOS || uiHandPos == LEGPOS ) { if ( ValidMerge( usNewItemIndex, usOldItemIndex ) ) { // bring up merge requestor // TOO PAINFUL TO DO!! --CC if ( !InItemDescriptionBox( ) ) { // HEADROCK HAM 5: Sector Inventory Item Desc Box no longer accessible during combat. if( gTacticalStatus.uiFlags & INCOMBAT ) { DoScreenIndependantMessageBox( New113HAMMessage[ 24 ], MSG_BOX_FLAG_OK, NULL ); return; } else { bJustOpenedItemDescPanel = true; // OJW - 20090319 - fix merging on mapscreen - see top of function MAPInternalInitItemDescriptionBox( &(pSoldier->inv[ uiHandPos ]), 0, pSoldier ); } } /* gubHandPos = (UINT8) uiHandPos; gusOldItemIndex = usOldItemIndex; gusNewItemIndex = usNewItemIndex; gfDeductPoints = fDeductPoints; DoScreenIndependantMessageBox( Message[ STR_MERGE_ITEMS ], MSG_BOX_FLAG_YESNO, MergeMessageBoxCallBack ); return; */ } // else handle normally } if((UsingNewInventorySystem() == true) && !(pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE) && !AM_A_ROBOT(pSoldier)) { if((uiHandPos == VESTPOCKPOS || uiHandPos == LTHIGHPOCKPOS || uiHandPos == RTHIGHPOCKPOS || uiHandPos == CPACKPOCKPOS || uiHandPos == BPACKPOCKPOS) && CanItemFitInPosition(pSoldier, gpItemPointer, uiHandPos, FALSE)) { //If we put a new pack in the backpack pocket, turn off the droppack button if(uiHandPos == BPACKPOCKPOS) { // First, deal with the zipper if(pSoldier->flags.ZipperFlag) if(!ChangeZipperStatus(pSoldier, FALSE)) return; if(pSoldier->flags.DropPackFlag) pSoldier->flags.DropPackFlag = FALSE; } } } if (bJustOpenedItemDescPanel) // OJW - 20090319 - fix merging on mapscreen - see top of function return; // Else, try to place here if (PlaceObject(pSoldier, (UINT8)uiHandPos, gpItemPointer)) { iLastHandPos = uiHandPos; pSoldier->bActionPoints -= usCostToMoveItem; HandleTacticalEffectsOfEquipmentChange(pSoldier, uiHandPos, usOldItemIndex, usNewItemIndex); // Dirty fInterfacePanelDirty = DIRTYLEVEL2; fCharacterInfoPanelDirty = TRUE; fMapPanelDirty = TRUE; // Check if cursor is empty now if ( gpItemPointer->exists() == false ) { MAPEndItemPointer( ); } else // items swapped { // Update mouse cursor guiExternVo = GetInterfaceGraphicForItem( &(Item[ gpItemPointer->usItem ]) ); gusExternVoSubIndex = g_bUsePngItemImages ? 0 : Item[ gpItemPointer->usItem ].ubGraphicNum; MSYS_ChangeRegionCursor( &gMPanelRegion , EXTERN_CURSOR ); MSYS_SetCurrentCursor( EXTERN_CURSOR ); fMapInventoryItem=TRUE; fTeamPanelDirty=TRUE; //shadooow: this resets the current highlight item selection for swapped item HandleCompatibleAmmoUI(pSoldier, NO_SLOT, FALSE); gfCheckForMouseOverItem = TRUE; // remember which gridno the object came from sObjectSourceGridNo = pSoldier->sGridNo; // and who owned it last gpItemPointerSoldier = pSoldier; ReevaluateItemHatches( pSoldier, FALSE ); } // re-evaluate repairs gfReEvaluateEveryonesNothingToDo = TRUE; // if item came from another merc if ( gpItemPointerSoldier != pSoldier ) { ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, pMessageStrings[ MSG_ITEM_PASSED_TO_MERC ], ShortItemNames[ usNewItemIndex ], pSoldier->name ); } } } // Flugente: we have to recheck our flashlights, as we changed items pSoldier->HandleFlashLights(); // sevenfm: update morale, as we could add/remove walkman RefreshSoldierMorale(pSoldier); } else if (iReason & MSYS_CALLBACK_REASON_RBUTTON_DWN) { // if there is a map UI message being displayed if( giUIMessageOverlay != -1 ) { CancelMapUIMessage( ); return; } fRightDown = TRUE; } else if (iReason & MSYS_CALLBACK_REASON_RBUTTON_UP && fRightDown ) { fRightDown = FALSE; // Return if empty if (pSoldier->inv[ uiHandPos ].exists() == false ) { return; } // rftr: robot can't equip weapon attachments if (AM_A_ROBOT(pSoldier) && uiHandPos == HANDPOS) { DoMessageBox(MSG_BOX_BASIC_STYLE, szRobotText[ROBOT_TEXT_CANNOT_ADD_ATTACHMENTS], guiCurrentScreen, (UINT8)MSG_BOX_FLAG_OK, NULL, NULL); return; } // Some global stuff here - for esc, etc // Check for # of slots in item // CHRISL: Use new ItemSlotLimit function if we're using the new inventory system UINT8 isLimit = ItemSlotLimit(&pSoldier->inv[uiHandPos], uiHandPos, pSoldier); // access description box directly if CTRL is pressed for stack items if (!( ( pSoldier->inv[ uiHandPos ].ubNumberOfObjects > 1 ) && ( isLimit > 0 ) ) || _KeyDown( CTRL ) ) { if ( !InItemDescriptionBox( ) ) { if ( _KeyDown(SHIFT) && gpItemPointer == NULL && Item[pSoldier->inv[ uiHandPos ].usItem].usItemClass == IC_GUN && (pSoldier->inv[ uiHandPos ])[uiHandPos]->data.gun.ubGunShotsLeft > 0 && !ItemIsSingleShotRocketLauncher(pSoldier->inv[ uiHandPos ].usItem) ) { EmptyWeaponMagazine( &(pSoldier->inv[ uiHandPos ]), &gItemPointer, uiHandPos ); InternalMAPBeginItemPointer( pSoldier ); } else { //CHRISL: This could return a false in which case we don't want to activate the infobox. if(InitItemDescriptionBox( pSoldier, (UINT8)uiHandPos, MAP_ITEMDESC_START_X, MAP_ITEMDESC_START_Y, 0 )) { fShowDescriptionFlag=TRUE; fTeamPanelDirty=TRUE; fInterfacePanelDirty = DIRTYLEVEL2; } } } } else { if ( !InItemStackPopup( ) ) { // CHRISL: Changed final parameter so that we fill the inventory screen InitItemStackPopup( pSoldier, (UINT8)uiHandPos, xResOffset, INV_REGION_Y, 261, ( SCREEN_HEIGHT - PLAYER_INFO_Y ) ); fTeamPanelDirty=TRUE; fInterfacePanelDirty = DIRTYLEVEL2; } } } else if (iReason & MSYS_CALLBACK_REASON_LOST_MOUSE ) { fRightDown = FALSE; } } void InternalMAPBeginItemPointer( SOLDIERTYPE *pSoldier ) { // If not null return if ( gpItemPointer != NULL ) { return; } // Set global indicator gpItemPointer = &gItemPointer; gpItemPointerSoldier = pSoldier; // Set mouse guiExternVo = GetInterfaceGraphicForItem( &(Item[ gpItemPointer->usItem ]) ); gusExternVoSubIndex = g_bUsePngItemImages ? 0 : Item[ gpItemPointer->usItem ].ubGraphicNum; MSYS_ChangeRegionCursor( &gMPanelRegion , EXTERN_CURSOR ); MSYS_SetCurrentCursor( EXTERN_CURSOR ); fMapInventoryItem=TRUE; fTeamPanelDirty=TRUE; // hatch out incompatible inventory slots ReevaluateItemHatches( pSoldier, FALSE ); // re-evaluate repairs gfReEvaluateEveryonesNothingToDo = TRUE; } void MAPBeginItemPointer( SOLDIERTYPE *pSoldier, UINT8 ubHandPos ) { // If not null return if ( gpItemPointer != NULL ) { return; } int numToMove = 0; if (_KeyDown( SHIFT )) { // Remove all from soldier's slot numToMove = ALL_OBJECTS; } /* This needs work // WDS 08/17/2008 - Cntrl-Click drops all items else if (_KeyDown( CTRL )) { // Remove all from soldier's slot numToMove = ALL_OBJECTS; pSoldier->inv[ubHandPos].MoveThisObjectTo(gItemPointer, numToMove, pSoldier, ubHandPos); if ( gItemPointer.exists() == false ) { //oops, the move failed. It might have failed because the object was force placed //to a slot where the ItemSizeLimit is 0, try again //this method won't work with LBEs in LBE pockets pSoldier->inv[ubHandPos].MoveThisObjectTo(gItemPointer, numToMove); } if ( gItemPointer.exists() == true ) { SoldierHandleDropItem (pSoldier); // AddItemToPool( pSoldier->sGridNo, &gItemPointer, 1, pSoldier->pathing.bLevel, WORLD_ITEM_REACHABLE, -1 ); // InternalMAPBeginItemPointer( pSoldier ); } return; } */ else { numToMove = 1; } pSoldier->inv[ubHandPos].MoveThisObjectTo(gItemPointer, numToMove, pSoldier, ubHandPos); //Autoplace to map sector inventory if ( _KeyDown(CTRL) ) { // if in battle inform player they will have to do this in tactical if( !CanPlayerUseSectorInventory( gCharactersList[ bSelectedInfoChar ].usSolID ) ) { // return item to original slot PlaceObject( pSoldier, ubHandPos, &gItemPointer ); DoMapMessageBox( MSG_BOX_BASIC_STYLE, pMapInventoryErrorString[ 4 ], MAP_SCREEN, MSG_BOX_FLAG_OK, NULL ); } else if( AutoPlaceObjectToWorld(pSoldier, &gItemPointer) ) { //INVRenderINVPanelItem( pSoldier, uiHandPos, DIRTYLEVEL2); // redraw the empty slot fTeamPanelDirty = TRUE; RenderTeamRegionBackground(); } return; } if ( gItemPointer.exists() == false ) { //oops, the move failed. It might have failed because the object was force placed //to a slot where the ItemSizeLimit is 0, try again //this method won't work with LBEs in LBE pockets pSoldier->inv[ubHandPos].MoveThisObjectTo(gItemPointer, numToMove); } if ( gItemPointer.exists() == true ) { InternalMAPBeginItemPointer( pSoldier ); } } void MAPBeginKeyRingItemPointer( SOLDIERTYPE *pSoldier, UINT8 uiKeySlot ) { // If not null return if ( gpItemPointer != NULL ) { return; } // Set mouse guiExternVo = GetInterfaceGraphicForItem( &(Item[ gpItemPointer->usItem ]) ); gusExternVoSubIndex = g_bUsePngItemImages ? 0 : Item[ gpItemPointer->usItem ].ubGraphicNum; MSYS_ChangeRegionCursor( &gMPanelRegion , EXTERN_CURSOR ); MSYS_SetCurrentCursor( EXTERN_CURSOR ); fMapInventoryItem=TRUE; fTeamPanelDirty=TRUE; } void MAPEndItemPointer( ) { if ( gpItemPointer != NULL ) { gpItemPointer = NULL; MSYS_ChangeRegionCursor( &gMPanelRegion , CURSOR_NORMAL ); MSYS_SetCurrentCursor( CURSOR_NORMAL ); fMapInventoryItem=FALSE; fTeamPanelDirty=TRUE; if ( fShowMapInventoryPool ) { HandleButtonStatesWhileMapInventoryActive(); } if ( fShowInventoryFlag && bSelectedInfoChar >= 0 ) { ReevaluateItemHatches( gCharactersList[ bSelectedInfoChar ].usSolID, FALSE ); } } } void HandleMapInventoryCursor() { if(fMapInventoryItem) MSYS_SetCurrentCursor( EXTERN_CURSOR ); return; } // will place down the upper left hand corner attribute strings void RenderAttributeStringsForUpperLeftHandCorner( UINT32 uiBufferToRenderTo ) { INT32 iCounter = 0; SOLDIERTYPE *pSoldier = NULL; if ( ( bSelectedInfoChar != - 1) && ( gCharactersList[ bSelectedInfoChar ].fValid ) ) { pSoldier = gCharactersList[ bSelectedInfoChar ].usSolID; } SetFont( CHAR_FONT ); SetFontForeground( CHAR_TITLE_FONT_COLOR ); SetFontBackground( FONT_BLACK ); SetFontDestBuffer( uiBufferToRenderTo, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, FALSE ); // assignment strings DrawString( pUpperLeftMapScreenStrings[ 0 ], (UINT16)(UI_CHARPANEL.Text.Assignment.iX - StringPixLength( pUpperLeftMapScreenStrings[0], CHAR_FONT)/2), UI_CHARPANEL.Text.Assignment.iY, CHAR_FONT); // vehicles and robot don't have attributes, contracts, or morale if ( ( pSoldier == NULL ) || ( !( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) && !AM_A_ROBOT( pSoldier ) ) ) { // health DrawString(pUpperLeftMapScreenStrings[ 2 ], UI_CHARPANEL.Text.Health.iX, UI_CHARPANEL.Text.Health.iY, CHAR_FONT); for( iCounter = 0; iCounter < 5; iCounter++ ) { DrawString(pShortAttributeStrings[ iCounter ], UI_CHARPANEL.Text.Attributes.iX, ( INT16 )(UI_CHARPANEL.Text.Attributes.iY + iCounter * 10 ) ,CHAR_FONT ); DrawString(pShortAttributeStrings[ iCounter + 5 ] , UI_CHARPANEL.Text.Attributes2.iX, ( INT16 )(UI_CHARPANEL.Text.Attributes2.iY + iCounter * 10 ), CHAR_FONT ); } // contract //DrawString(pUpperLeftMapScreenStrings[ 1 ], 194, 52, CHAR_FONT); // morale DrawString(pUpperLeftMapScreenStrings[ 3 ], UI_CHARPANEL.Text.Morale.iX, UI_CHARPANEL.Text.Morale.iY, CHAR_FONT); } else { // condition DrawString(pUpperLeftMapScreenStrings[ 4 ], UI_CHARPANEL.Text.Condition.iX, UI_CHARPANEL.Text.Condition.iY, CHAR_FONT); } // restore buffer SetFontDestBuffer( FRAME_BUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, FALSE ); } void DisplayThePotentialPathForCurrentDestinationCharacterForMapScreenInterface(INT16 sMapX, INT16 sMapY ) { // simply check if we want to refresh the screen to display path static INT8 bOldDestChar = -1; static INT16 sPrevMapX, sPrevMapY; INT32 iDifference = 0; if( bOldDestChar != GetSelectedDestChar() ) { bOldDestChar = GetSelectedDestChar(); giPotCharPathBaseTime = GetJA2Clock( ); sPrevMapX = sMapX; sPrevMapY = sMapY; fTempPathAlreadyDrawn = FALSE; fDrawTempPath = FALSE; } if( ( sMapX != sPrevMapX) || ( sMapY != sPrevMapY ) ) { giPotCharPathBaseTime = GetJA2Clock( ); sPrevMapX = sMapX; sPrevMapY = sMapY; // path was plotted and we moved, re draw map..to clean up mess if( fTempPathAlreadyDrawn == TRUE ) { fMapPanelDirty = TRUE; } fTempPathAlreadyDrawn = FALSE; fDrawTempPath = FALSE; } if ( fTempPathAlreadyDrawn == TRUE ) { return; } iDifference = GetJA2Clock( ) - giPotCharPathBaseTime; if( iDifference > MIN_WAIT_TIME_FOR_TEMP_PATH ) { fDrawTempPath = TRUE; giPotCharPathBaseTime = GetJA2Clock( ); fTempPathAlreadyDrawn = TRUE; } } void SetUpCursorForStrategicMap( void ) { if ( !gfInChangeArrivalSectorMode ) { // check if character is in destination plotting mode if ( fPlotForHelicopter ) { // set cursor to chopper ChangeMapScreenMaskCursor( CURSOR_CHOPPER ); } else if ( fPlotForMilitia ) { // set cursor to chopper ChangeMapScreenMaskCursor( CURSOR_STRATEGIC_FOOT );//CURSOR_MILITIA ); } else { if( GetSelectedDestChar() == -1 ) { // no plot mode, reset cursor to normal ChangeMapScreenMaskCursor( CURSOR_NORMAL ); } else // yes - by character { // set cursor based on foot or vehicle SOLDIERTYPE* pSoldier = gCharactersList[GetSelectedDestChar()].usSolID; if( ( pSoldier->bAssignment != VEHICLE ) && !( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) ) { ChangeMapScreenMaskCursor( CURSOR_STRATEGIC_FOOT ); } else { ChangeMapScreenMaskCursor( CURSOR_STRATEGIC_VEHICLE ); } } } } else { // set cursor to bullseye ChangeMapScreenMaskCursor( CURSOR_STRATEGIC_BULLSEYE ); } } void HandleAnimatedCursorsForMapScreen( ) { if ( COUNTERDONE( CURSORCOUNTER ) ) { RESETCOUNTER( CURSORCOUNTER ); UpdateAnimatedCursorFrames( gMapScreenMaskRegion.Cursor ); SetCurrentCursorFromDatabase( gMapScreenMaskRegion.Cursor ); } } void AbortMovementPlottingMode( void ) { // invalid if we're not plotting movement Assert( ( GetSelectedDestChar() != -1) || fPlotForHelicopter || fPlotForMilitia ); // make everybody go back to where they were going before this plotting session started RestorePreviousPaths(); // don't need the previous paths any more ClearPreviousPaths(); // clear the character's temporary path (this is the route being constantly updated on the map) if( pTempCharacterPath ) { // make sure we're at the beginning pTempCharacterPath = MoveToBeginningOfPathList( pTempCharacterPath ); pTempCharacterPath = ClearStrategicPathList( pTempCharacterPath, 0 ); } // clear the helicopter's temporary path (this is the route being constantly updated on the map) if( pTempHelicopterPath ) { // make sure we're at the beginning pTempHelicopterPath = MoveToBeginningOfPathList( pTempHelicopterPath ); pTempHelicopterPath = ClearStrategicPathList( pTempHelicopterPath, 0 ); } if ( pTempMilitiaPath ) { // make sure we're at the beginning pTempMilitiaPath = MoveToBeginningOfPathList( pTempMilitiaPath ); pTempMilitiaPath = ClearStrategicPathList( pTempMilitiaPath, 0 ); } EndConfirmMapMoveMode( ); // cancel destination line highlight giDestHighLine = -1; // cancel movement mode SetSelectedDestChar( -1 ); fPlotForHelicopter = FALSE; if ( fPlotForMilitia ) { if ( gMilitiaPath[gMilitiaGroupId].sGroupid > -1 ) { DissolveMilitiaGroup( (UINT8)gMilitiaPath[gMilitiaGroupId].sGroupid ); } MilitiaplotFinish( ); fPlotForMilitia = FALSE; } gMilitiaPath[gMilitiaGroupId].path = NULL; // tell player the route was UNCHANGED MapScreenMessage( FONT_MCOLOR_LTYELLOW, MSG_MAP_UI_POSITION_MIDDLE, pMapPlotStrings[ 2 ] ); // reset cursors ChangeMapScreenMaskCursor( CURSOR_NORMAL ); SetUpCursorForStrategicMap( ); // restore glow region RestoreBackgroundForDestinationGlowRegionList( ); // we might be on the map, redraw to remove old path stuff fMapPanelDirty = TRUE; fTeamPanelDirty = TRUE; gfRenderPBInterface = TRUE; } void CheckToSeeIfMouseHasLeftMapRegionDuringPathPlotting( ) { static BOOLEAN fInArea = FALSE; if ( ( gMapViewRegion.uiFlags & MSYS_MOUSE_IN_AREA ) == 0 ) { if( fInArea ) { fInArea = FALSE; // plotting path, clean up if ( (( GetSelectedDestChar() != -1) || fPlotForHelicopter || fDrawTempHeliPath || fPlotForMilitia || fDrawTempMilitiaPath ) && fTempPathAlreadyDrawn ) { fDrawTempHeliPath = FALSE; fDrawTempMilitiaPath = FALSE; fMapPanelDirty = TRUE; gfRenderPBInterface = TRUE; // clear the temp path if( pTempCharacterPath ) { pTempCharacterPath = MoveToBeginningOfPathList( pTempCharacterPath); pTempCharacterPath = ClearStrategicPathList( pTempCharacterPath, 0 ); } else if ( pTempMilitiaPath ) { pTempMilitiaPath = MoveToBeginningOfPathList( pTempMilitiaPath ); pTempMilitiaPath = ClearStrategicPathList( pTempMilitiaPath, 0 ); } } // reset fact temp path has been drawn fTempPathAlreadyDrawn = FALSE; } } else { fInArea = TRUE; } } void BlitBackgroundToSaveBuffer( void ) { // render map RenderMapRegionBackground( ); // Headrock: Moved the following line here from the marker below, so that the Inventory Bottom panel // renders underneath the character info panel (and so doesn't truncate the large open inventory). We may // need to put TRUE here if there's any problem, but I doubt it. RenderMapScreenInterfaceBottom( TRUE ); if( fDisableDueToBattleRoster == FALSE ) { // render team RenderTeamRegionBackground( ); // render character info RenderCharacterInfoBackground( ); } else if( gfPreBattleInterfaceActive ) { ForceButtonUnDirty( giMapContractButton ); ForceButtonUnDirty( giCharInfoButton[ 0 ] ); ForceButtonUnDirty( giCharInfoButton[ 1 ] ); if (isWidescreenUI()) { ForceButtonUnDirty(giMapInvDoneButton); } RenderPreBattleInterface(); } // now render lower panel // HEADROCK - Moved the following line upwards, so it renders BEFORE the character info panel. // RenderMapScreenInterfaceBottom( ); } void CreateMouseRegionsForTeamList( void ) { // will create mouse regions for assignments, path plotting, character info selection // the info region...is the background for the list itself // OJW - MP int max_rows = maxNumberOfMercVisibleInStrategyList; if (is_networked) max_rows = 7; // check this value is correct / unhardcode it const auto xName = UI_CHARLIST.xName; const auto xEndName = xName + UI_CHARLIST.widthName; const auto xAssignment= UI_CHARLIST.xAssignment; const auto xEndAssignment = xAssignment + UI_CHARLIST.widthAssignment; const auto xLocation= UI_CHARLIST.xLocation; const auto xEndLocation= xLocation + UI_CHARLIST.widthLocation; const auto xETA= UI_CHARLIST.xETA; const auto xEndETA= xETA + UI_CHARLIST.widthETA; const auto xTime= UI_CHARLIST.xTimeRemaining; const auto xEndTime= xTime+ UI_CHARLIST.widthTimeRemaining; const auto xSleep= UI_CHARLIST.xSleep; const auto xEndSleep= xSleep+ UI_CHARLIST.widthSleep; const auto y = UI_CHARLIST.y; for(INT16 sCounter = 0; sCounter < max_rows; sCounter++ ) { const auto yStart = y + (sCounter) * (Y_SIZE + 2); const auto yEnd = y + (sCounter + 1) * (Y_SIZE + 2); // name region MSYS_DefineRegion( &gTeamListNameRegion[ sCounter ], xName, yStart, xEndName, yEnd, MSYS_PRIORITY_NORMAL, MSYS_NO_CURSOR, TeamListInfoRegionMvtCallBack, TeamListInfoRegionBtnCallBack ); // assignment region MSYS_DefineRegion( &gTeamListAssignmentRegion[ sCounter ], xAssignment, yStart, xEndAssignment, yEnd, MSYS_PRIORITY_NORMAL + 1, MSYS_NO_CURSOR, TeamListAssignmentRegionMvtCallBack, TeamListAssignmentRegionBtnCallBack ); // location region (same function as name regions, so uses the same callbacks) MSYS_DefineRegion( &gTeamListLocationRegion[ sCounter ], xLocation, yStart, xEndLocation, yEnd, MSYS_PRIORITY_NORMAL + 1, MSYS_NO_CURSOR, TeamListInfoRegionMvtCallBack, TeamListInfoRegionBtnCallBack ); // destination region MSYS_DefineRegion( &gTeamListDestinationRegion[ sCounter ], xETA, yStart, xEndETA, yEnd, MSYS_PRIORITY_NORMAL + 1, MSYS_NO_CURSOR, TeamListDestinationRegionMvtCallBack, TeamListDestinationRegionBtnCallBack ); // contract region MSYS_DefineRegion( &gTeamListContractRegion[ sCounter ], xTime, yStart, xEndTime, yEnd, MSYS_PRIORITY_NORMAL + 1, MSYS_NO_CURSOR, TeamListContractRegionMvtCallBack, TeamListContractRegionBtnCallBack ); // sleep region MSYS_DefineRegion( &gTeamListSleepRegion[ sCounter ], xSleep, yStart, xEndSleep, yEnd, MSYS_PRIORITY_NORMAL + 1, MSYS_NO_CURSOR, TeamListSleepRegionMvtCallBack, TeamListSleepRegionBtnCallBack ); MSYS_SetRegionUserData(&gTeamListNameRegion[sCounter],0,sCounter); MSYS_SetRegionUserData(&gTeamListAssignmentRegion[sCounter],0,sCounter); MSYS_SetRegionUserData(&gTeamListSleepRegion[sCounter],0,sCounter); MSYS_SetRegionUserData(&gTeamListLocationRegion[sCounter],0,sCounter); MSYS_SetRegionUserData(&gTeamListDestinationRegion[sCounter],0,sCounter); MSYS_SetRegionUserData(&gTeamListContractRegion[sCounter],0,sCounter); // set up help boxes SetRegionFastHelpText( &gTeamListNameRegion[sCounter], pMapScreenMouseRegionHelpText[ 0 ] ); SetRegionFastHelpText( &gTeamListAssignmentRegion[sCounter], pMapScreenMouseRegionHelpText[ 1 ] ); SetRegionFastHelpText( &gTeamListSleepRegion[sCounter], pMapScreenMouseRegionHelpText[ 5 ] ); SetRegionFastHelpText( &gTeamListLocationRegion[sCounter], pMapScreenMouseRegionHelpText[ 4 ] ); SetRegionFastHelpText( &gTeamListDestinationRegion[sCounter], pMapScreenMouseRegionHelpText[ 2 ] ); SetRegionFastHelpText( &gTeamListContractRegion[sCounter], pMapScreenMouseRegionHelpText[ 3 ] ); } return; } void DestroyMouseRegionsForTeamList( void ) { // will destroy mouse regions overlaying the team list area INT32 sCounter = 0; for( sCounter = 0; sCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; sCounter++ ) { MSYS_RemoveRegion( &gTeamListNameRegion[ sCounter ]); MSYS_RemoveRegion( &gTeamListAssignmentRegion[ sCounter ]); MSYS_RemoveRegion( &gTeamListSleepRegion[ sCounter ]); MSYS_RemoveRegion( &gTeamListDestinationRegion[ sCounter ]); MSYS_RemoveRegion( &gTeamListLocationRegion[ sCounter ]); MSYS_RemoveRegion( &gTeamListContractRegion[ sCounter ]); } } void MPReadyButtonCallback( GUI_BUTTON *btn, INT32 reason ) { int iIndex = MSYS_GetBtnUserData(btn,0); if (iIndex >= 1 || iIndex <= 4) { 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); if (iIndex == 3 || iIndex == 4) { // ready / start button was clicked if (is_networked) { start_battle(); } } else if (iIndex == 2) { // compass button clicked if (!is_compass_box_open) { if (can_edgechange()) { // open the box CreateDestroyMouseRegionsForCompassBox(); ShowBox(ghMPCompassBox); is_compass_box_open = true; } else if (allowlaptop) { // warn the user that cannot change once buying has commenced ScreenMsg( FONT_LTBLUE, MSG_MPSYSTEM, gszMPMapscreenText[3]); } } else { // close the box CreateDestroyMouseRegionsForCompassBox(); HideBox(ghMPCompassBox); is_compass_box_open = false; fTeamPanelDirty = true; } } else if (iIndex == 1) { // team button clicked if (!is_team_box_open) { if (can_teamchange()) { // open the box CreateDestroyMouseRegionsForTeamBox(); ShowBox(ghMPTeamBox); is_team_box_open = true; } else if (allowlaptop) { // warn the user that cannot change once buying has commenced ScreenMsg( FONT_LTBLUE, MSG_MPSYSTEM, gszMPMapscreenText[4]); } } else { // close the box CreateDestroyMouseRegionsForTeamBox(); HideBox(ghMPTeamBox); is_team_box_open = false; fTeamPanelDirty = true; } } } } } InvalidateRegion(btn->Area.RegionTopLeftX, btn->Area.RegionTopLeftY, btn->Area.RegionBottomRightX, btn->Area.RegionBottomRightY); } void MPCompassChangeCallback( MOUSE_REGION * pReason, INT32 iReason) { if (iReason & MSYS_CALLBACK_REASON_LBUTTON_UP) { if (!is_compass_box_open) { if (can_edgechange()) { // open the box CreateDestroyMouseRegionsForCompassBox(); ShowBox(ghMPCompassBox); is_compass_box_open = true; } else if (allowlaptop) { // warn the user that cannot change once buying has commenced ScreenMsg( FONT_LTBLUE, MSG_MPSYSTEM, gszMPMapscreenText[3]); } } else { // close the box CreateDestroyMouseRegionsForCompassBox(); HideBox(ghMPCompassBox); is_compass_box_open = false; fTeamPanelDirty = true; } } } void MPTeamChangeCallback( MOUSE_REGION * pReason, INT32 iReason) { if (iReason & MSYS_CALLBACK_REASON_LBUTTON_UP) { if (!is_team_box_open) { if (can_teamchange()) { // open the box CreateDestroyMouseRegionsForTeamBox(); ShowBox(ghMPTeamBox); is_team_box_open = true; } else if (allowlaptop) { // warn the user that cannot change once buying has commenced ScreenMsg( FONT_LTBLUE, MSG_MPSYSTEM, gszMPMapscreenText[4]); } else if (gRandomStartingEdge) { ScreenMsg( FONT_LTBLUE, MSG_MPSYSTEM, L"Cannot change edge, the game is set to random spawn"); } } else { // close the box CreateDestroyMouseRegionsForTeamBox(); HideBox(ghMPTeamBox); is_team_box_open = false; fTeamPanelDirty = true; } } } // OJW - End MP Mouse Regions and Callbacks // mask for mapscreen region void MapScreenMarkRegionBtnCallback(MOUSE_REGION *pRegion, INT32 iReason ) { if (iReason & MSYS_CALLBACK_REASON_LBUTTON_UP) { // reset selected characters ResetAllSelectedCharacterModes( ); } if (iReason & MSYS_CALLBACK_REASON_RBUTTON_UP) { // reset selected characters ResetAllSelectedCharacterModes( ); } } void ContractButtonCallback(GUI_BUTTON *btn,INT32 reason) { if( ( iDialogueBox != -1 ) ) { return; } if(reason & MSYS_CALLBACK_REASON_LBUTTON_DWN ) { if( IsMapScreenHelpTextUp() ) { // stop mapscreen text StopMapScreenHelpText( ); } /* if( ( bSelectedDestChar != -1 ) || fPlotForHelicopter || fPlotForMilitia ) { AbortMovementPlottingMode( ); return; } */ // redraw region if( btn->Area.uiFlags & MSYS_HAS_BACKRECT ) { fCharacterInfoPanelDirty = TRUE; } btn->uiFlags|=(BUTTON_CLICKED_ON); } else if(reason & MSYS_CALLBACK_REASON_LBUTTON_UP ) { if( IsMapScreenHelpTextUp() ) { // stop mapscreen text StopMapScreenHelpText( ); } if (btn->uiFlags & BUTTON_CLICKED_ON) { btn->uiFlags&= ~(BUTTON_CLICKED_ON); RequestContractMenu( ); } } else if(reason & MSYS_CALLBACK_REASON_RBUTTON_DWN ) { if( IsMapScreenHelpTextUp() ) { // stop mapscreen text StopMapScreenHelpText( ); } } } void TeamListInfoRegionBtnCallBack(MOUSE_REGION *pRegion, INT32 iReason ) { INT32 iValue = 0; SOLDIERTYPE *pSoldier = NULL; if( fLockOutMapScreenInterface || gfPreBattleInterfaceActive ) { return; } // marke strogg more mercs must add skipped mercs FIRSTmercTOdisplay iValue = MSYS_GetRegionUserData( pRegion, 0 ); if (iReason & MSYS_CALLBACK_REASON_LBUTTON_UP) { // set to new info character...make sure is valid if( IsMapScreenHelpTextUp() ) { // stop mapscreen text StopMapScreenHelpText( ); return; } if( gCharactersList[ iValue + FIRSTmercTOdisplay].fValid == TRUE && ValidSelectableCharForNextOrPrev(iValue + FIRSTmercTOdisplay)) { // HEADROCK HAM B2.8: Added argument for multi-select entire squads if ( HandleCtrlOrShiftInTeamPanel( iValue + FIRSTmercTOdisplay, FALSE )) { return; } ChangeSelectedInfoChar( iValue+ FIRSTmercTOdisplay, TRUE ); pSoldier = gCharactersList[ iValue + FIRSTmercTOdisplay].usSolID; // highlight giDestHighLine = -1; // reset character bSelectedAssignChar = -1; SetSelectedDestChar( -1 ); bSelectedContractChar = -1; fPlotForHelicopter = FALSE; fPlotForMilitia = FALSE; // if not dead or POW, select his sector if( ( pSoldier->stats.bLife > 0 ) && ( pSoldier->bAssignment != ASSIGNMENT_POW ) && ( pSoldier->bAssignment != ASSIGNMENT_MINIEVENT ) && ( pSoldier->bAssignment != ASSIGNMENT_REBELCOMMAND ) )//&& !SPY_LOCATION( pSoldier->bAssignment ) ) { ChangeSelectedMapSector( pSoldier->sSectorX, pSoldier->sSectorY, pSoldier->bSectorZ ); } // unhilight contract line giContractHighLine = -1; // can't assign highlight line giAssignHighLine = -1; // dirty team and map regions fTeamPanelDirty = TRUE; fMapPanelDirty = TRUE; //fMapScreenBottomDirty = TRUE; gfRenderPBInterface = TRUE; } else { // reset selected characters ResetAllSelectedCharacterModes( ); } } if (iReason & MSYS_CALLBACK_REASON_RBUTTON_UP) { if( IsMapScreenHelpTextUp() ) { // stop mapscreen text StopMapScreenHelpText( ); return; } if( gCharactersList[ iValue + FIRSTmercTOdisplay].fValid == TRUE ) { pSoldier = gCharactersList[ iValue + FIRSTmercTOdisplay].usSolID; // select this character ChangeSelectedInfoChar( iValue+ FIRSTmercTOdisplay, TRUE ); if (!isWidescreenUI()) { RequestToggleMercInventoryPanel(); } // highlight giDestHighLine = -1; // reset character bSelectedAssignChar = -1; SetSelectedDestChar( -1 ); bSelectedContractChar = -1; fPlotForHelicopter = FALSE; fPlotForMilitia = FALSE; // if not dead or POW, select his sector if( ( pSoldier->stats.bLife > 0 ) && ( pSoldier->bAssignment != ASSIGNMENT_POW ) && !SPY_LOCATION( pSoldier->bAssignment ) && ( pSoldier->bAssignment != ASSIGNMENT_MINIEVENT ) && ( pSoldier->bAssignment == ASSIGNMENT_REBELCOMMAND ) ) { ChangeSelectedMapSector( pSoldier->sSectorX, pSoldier->sSectorY, pSoldier->bSectorZ ); } // unhilight contract line giContractHighLine = -1; // can't assign highlight line giAssignHighLine = -1; // dirty team and map regions fTeamPanelDirty = TRUE; fMapPanelDirty = TRUE; // fMapScreenBottomDirty = TRUE; gfRenderPBInterface = TRUE; } } } void TeamListInfoRegionMvtCallBack(MOUSE_REGION *pRegion, INT32 iReason ) { INT32 iValue = 0; if( fLockOutMapScreenInterface || gfPreBattleInterfaceActive ) { return; } iValue = MSYS_GetRegionUserData( pRegion, 0 ); if (iReason & MSYS_CALLBACK_REASON_MOVE) { // marke strogg more mercs So, the ACTUAL merc is location + skipped FIRSTmercTOdisplay if( gCharactersList[ iValue + FIRSTmercTOdisplay ].fValid == TRUE ) { giHighLine = iValue; } else { giHighLine = -1; } } else if( iReason & MSYS_CALLBACK_REASON_LOST_MOUSE ) { giHighLine = -1; } } void TeamListAssignmentRegionBtnCallBack(MOUSE_REGION *pRegion, INT32 iReason ) { INT32 iValue = 0; SOLDIERTYPE *pSoldier = NULL; if( fLockOutMapScreenInterface || gfPreBattleInterfaceActive ) { return; } // marke strogg more mercs must add skipped mercs FIRSTmercTOdisplay iValue = MSYS_GetRegionUserData( pRegion, 0 ); if (iReason & MSYS_CALLBACK_REASON_LBUTTON_UP) { // set to new info character...make sure is valid if( IsMapScreenHelpTextUp() ) { // stop mapscreen text StopMapScreenHelpText( ); return; } if( gCharactersList[ iValue + FIRSTmercTOdisplay].fValid == TRUE && ValidSelectableCharForNextOrPrev(iValue + FIRSTmercTOdisplay)) { // HEADROCK HAM B2.8: Added argument for multi-select entire squads if ( HandleCtrlOrShiftInTeamPanel( iValue + FIRSTmercTOdisplay, FALSE )) { return; } // reset list if the clicked character isn't also selected ChangeSelectedInfoChar( iValue + FIRSTmercTOdisplay, ( BOOLEAN )( IsEntryInSelectedListSet( iValue + FIRSTmercTOdisplay) == FALSE ) ); pSoldier = gCharactersList[ iValue + FIRSTmercTOdisplay ].usSolID; // if alive (dead guys keep going, use remove menu instead), // and it's between sectors and it can be reassigned (non-vehicles) if ( ( pSoldier->bAssignment != ASSIGNMENT_DEAD ) && ( pSoldier->stats.bLife > 0 ) && ( pSoldier->flags.fBetweenSectors ) && !( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) ) { // can't reassign mercs while between sectors DoScreenIndependantMessageBox( pMapErrorString[ 41 ], MSG_BOX_FLAG_OK, NULL ); return; } bSelectedAssignChar = ( INT16 ) iValue + FIRSTmercTOdisplay; RebuildAssignmentsBox( ); // reset dest character SetSelectedDestChar( -1 ); fPlotForHelicopter = FALSE; fPlotForMilitia = FALSE; // reset contract char bSelectedContractChar = -1; giContractHighLine = -1; // can't highlight line, anymore..if we were giDestHighLine = -1; // dirty team and map regions fTeamPanelDirty = TRUE; fMapPanelDirty = TRUE; gfRenderPBInterface = TRUE; // if this thing can be re-assigned if( !( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) ) { giAssignHighLine = iValue + FIRSTmercTOdisplay; fShowAssignmentMenu = TRUE; if( ( pSoldier->stats.bLife == 0 ) || ( pSoldier->bAssignment == ASSIGNMENT_POW ) ) { fShowRemoveMenu = TRUE; } } else { // can't highlight line giAssignHighLine = -1; // we can't highlight this line // giHighLine = -1; } } else { // reset selected characters ResetAllSelectedCharacterModes( ); } } if (iReason & MSYS_CALLBACK_REASON_RBUTTON_UP) { // HEADROCK HAM B2.8: Added argument for multi-select entire squads if ( HandleCtrlOrShiftInTeamPanel( iValue + FIRSTmercTOdisplay, TRUE )) { return; } // reset selected characters ResetAllSelectedCharacterModes( ); // HEADROCK HAM B2.8: Right mouse button selects entire squad, if clicked on a squad-assigned character. // set to new info character...make sure is valid if( IsMapScreenHelpTextUp() ) { // stop mapscreen text StopMapScreenHelpText( ); return; } if( gCharactersList[ iValue + FIRSTmercTOdisplay].fValid == TRUE ) { ChangeSelectedInfoChar( iValue + FIRSTmercTOdisplay, TRUE ); pSoldier = gCharactersList[ iValue + FIRSTmercTOdisplay].usSolID; // highlight giDestHighLine = -1; // reset character bSelectedAssignChar = -1; SetSelectedDestChar( -1 ); bSelectedContractChar = -1; fPlotForHelicopter = FALSE; fPlotForMilitia = FALSE; fShowAssignmentMenu = FALSE; fShownAssignmentMenu = FALSE; // if not dead or POW, select his sector if( ( pSoldier->stats.bLife > 0 ) && ( pSoldier->bAssignment != ASSIGNMENT_POW ) && ( pSoldier->bAssignment != ASSIGNMENT_MINIEVENT ) && ( pSoldier->bAssignment == ASSIGNMENT_REBELCOMMAND ) ) { ChangeSelectedMapSector( pSoldier->sSectorX, pSoldier->sSectorY, pSoldier->bSectorZ ); } // Select all characters in squad INT16 iCounter; for( iCounter = 0; iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; ++iCounter ) { if( gCharactersList[ iCounter ].fValid == TRUE ) { // if not already selected if( fSelectedListOfMercsForMapScreen[ iCounter ] == FALSE ) { pSoldier = 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( iCounter ); } } } } } // unhilight contract line giContractHighLine = -1; // can't assign highlight line giAssignHighLine = -1; // dirty team and map regions fTeamPanelDirty = TRUE; fMapPanelDirty = TRUE; //fMapScreenBottomDirty = TRUE; gfRenderPBInterface = TRUE; } else { // reset selected characters ResetAllSelectedCharacterModes( ); } } } void TeamListAssignmentRegionMvtCallBack(MOUSE_REGION *pRegion, INT32 iReason ) { INT32 iValue = 0; if( fLockOutMapScreenInterface || gfPreBattleInterfaceActive ) { return; } iValue = MSYS_GetRegionUserData( pRegion, 0 ); if (iReason & MSYS_CALLBACK_REASON_MOVE) { // marke strogg more mercs So, the ACTUAL merc is location + FIRSTmercTOdisplay if( gCharactersList[ iValue + FIRSTmercTOdisplay ].fValid == TRUE ) { giHighLine = iValue; if( !( gCharactersList[ iValue + FIRSTmercTOdisplay ].usSolID->flags.uiStatusFlags & SOLDIER_VEHICLE ) ) { giAssignHighLine = iValue; } else { giAssignHighLine = -1; } } else { // can't highlight line giHighLine = -1; giAssignHighLine = -1; } } else if( iReason & MSYS_CALLBACK_REASON_LOST_MOUSE ) { giHighLine = -1; if( bSelectedAssignChar == -1 ) { giAssignHighLine = -1; } // restore background RestoreBackgroundForAssignmentGlowRegionList( ); } else if( iReason & MSYS_CALLBACK_REASON_GAIN_MOUSE ) { if( ( gCharactersList[ iValue + FIRSTmercTOdisplay ].fValid == TRUE ) && !( gCharactersList[ iValue + FIRSTmercTOdisplay].usSolID->flags.uiStatusFlags & SOLDIER_VEHICLE ) ) { // play click PlayGlowRegionSound( ); } } } void TeamListDestinationRegionBtnCallBack(MOUSE_REGION *pRegion, INT32 iReason ) { INT32 iValue = 0; if( fLockOutMapScreenInterface || gfPreBattleInterfaceActive || fShowMapInventoryPool ) { return; } // marke strogg more mercs must add skipped mercs FIRSTmercTOdisplay iValue = MSYS_GetRegionUserData( pRegion, 0 ); if (iReason & MSYS_CALLBACK_REASON_LBUTTON_UP) { if( IsMapScreenHelpTextUp() ) { // stop mapscreen text StopMapScreenHelpText( ); return; } if( gCharactersList[ iValue + FIRSTmercTOdisplay].fValid == TRUE && ValidSelectableCharForNextOrPrev(iValue + FIRSTmercTOdisplay)) { // HEADROCK HAM B2.8: Added argument for multi-select entire squads if ( HandleCtrlOrShiftInTeamPanel( iValue + FIRSTmercTOdisplay , FALSE )) { return; } // reset list if the clicked character isn't also selected ChangeSelectedInfoChar( iValue + FIRSTmercTOdisplay, ( BOOLEAN )( IsEntryInSelectedListSet( iValue + FIRSTmercTOdisplay ) == FALSE ) ); // deselect any characters/vehicles that can't accompany the clicked merc DeselectSelectedListMercsWhoCantMoveWithThisGuy( gCharactersList[ iValue + FIRSTmercTOdisplay ].usSolID ); // select all characters/vehicles that MUST accompany the clicked merc (same squad/vehicle) SelectUnselectedMercsWhoMustMoveWithThisGuy( ); // Find out if this guy and everyone travelling with him is allowed to move strategically // NOTE: errors are reported within... if ( CanChangeDestinationForCharSlot( ( INT16 ) iValue + FIRSTmercTOdisplay, TRUE ) ) { // turn off sector inventory, turn on show teams filter, etc. MakeMapModesSuitableForDestPlotting( ( INT8 ) iValue + FIRSTmercTOdisplay ); // check if person is in a vehicle if( gCharactersList[ iValue + FIRSTmercTOdisplay ].usSolID->bAssignment == VEHICLE ) { // if he's in the helicopter if( gCharactersList[ iValue + FIRSTmercTOdisplay ].usSolID->iVehicleId == iHelicopterVehicleId ) { TurnOnAirSpaceMode( ); if( RequestGiveSkyriderNewDestination( ) == FALSE ) { // not allowed to change destination of the helicopter return; } } } // select this character as the one plotting strategic movement SetSelectedDestChar( (INT16)iValue + FIRSTmercTOdisplay ); // remember the current paths for all selected characters so we can restore them if need be RememberPreviousPathForAllSelectedChars(); // check each person in this mvt group, if any bleeding, have them complain //CheckMembersOfMvtGroupAndComplainAboutBleeding( &( Menptr[ gCharactersList[ bSelectedDestChar ].usSolID ] ) ); // highlight giDestHighLine = iValue + FIRSTmercTOdisplay; // can't assign highlight line giAssignHighLine = -1; // reset assign character bSelectedAssignChar = -1; // reset contract char bSelectedContractChar = -1; giContractHighLine = -1; // dirty team and map regions fTeamPanelDirty = TRUE; fMapPanelDirty = TRUE; gfRenderPBInterface = TRUE; // set cursor SetUpCursorForStrategicMap( ); } else // problem - this guy can't move { // cancel destination highlight giDestHighLine = -1; } } else // empty char list slot { // reset selected characters ResetAllSelectedCharacterModes( ); } } if (iReason & MSYS_CALLBACK_REASON_RBUTTON_UP) { MakeMapModesSuitableForDestPlotting( ( INT8 ) iValue + FIRSTmercTOdisplay ); // reset list if the clicked character isn't also selected ChangeSelectedInfoChar( iValue + FIRSTmercTOdisplay, ( BOOLEAN )( IsEntryInSelectedListSet( iValue + FIRSTmercTOdisplay ) == FALSE ) ); CancelPathsOfAllSelectedCharacters(); if ( fPlotForMilitia && gMilitiaPath[gMilitiaGroupId].sGroupid > -1 ) CancelPathForMilitiaGroup( (UINT8)gMilitiaPath[gMilitiaGroupId].sGroupid ); // reset selected characters ResetAllSelectedCharacterModes( ); } } void TeamListDestinationRegionMvtCallBack(MOUSE_REGION *pRegion, INT32 iReason ) { INT32 iValue = -1; if( fLockOutMapScreenInterface || gfPreBattleInterfaceActive ) { return; } iValue = MSYS_GetRegionUserData( pRegion, 0 ); if (iReason & MSYS_CALLBACK_REASON_MOVE) { // marke strogg more mercs So, the ACTUAL merc is location + FIRSTmercTOdisplay if( gCharactersList[ iValue + FIRSTmercTOdisplay ].fValid == TRUE ) { giHighLine = iValue; giDestHighLine = iValue; } else { // can't highlight line giHighLine = -1; giDestHighLine = -1; } } else if( iReason & MSYS_CALLBACK_REASON_LOST_MOUSE ) { giHighLine = -1; if( GetSelectedDestChar() == -1 ) { giDestHighLine = -1; } // restore background RestoreBackgroundForDestinationGlowRegionList( ); } else if( iReason & MSYS_CALLBACK_REASON_GAIN_MOUSE ) { if( gCharactersList[ iValue + FIRSTmercTOdisplay ].fValid == TRUE ) { // play click PlayGlowRegionSound( ); } } } void TeamListSleepRegionBtnCallBack( MOUSE_REGION *pRegion, INT32 iReason ) { INT32 iValue = 0; SOLDIERTYPE *pSoldier = NULL; if( fLockOutMapScreenInterface || gfPreBattleInterfaceActive ) { return; } // marke strogg more mercs must add skipped mercs FIRSTmercTOdisplay iValue = MSYS_GetRegionUserData( pRegion, 0 ); if (iReason & MSYS_CALLBACK_REASON_LBUTTON_UP) { // set to new info character...make sure is valid.. not in transit and alive and concious if( IsMapScreenHelpTextUp() ) { // stop mapscreen text StopMapScreenHelpText( ); return; } if( ( gCharactersList[ iValue + FIRSTmercTOdisplay].fValid == TRUE ) ) { // HEADROCK HAM B2.8: Added argument for multi-select entire squads if ( HandleCtrlOrShiftInTeamPanel( iValue + FIRSTmercTOdisplay , FALSE )) { return; } // reset list if the clicked character isn't also selected ChangeSelectedInfoChar( iValue + FIRSTmercTOdisplay, ( BOOLEAN )( IsEntryInSelectedListSet( iValue + FIRSTmercTOdisplay ) == FALSE ) ); // if this slot's sleep status can be changed if ( CanChangeSleepStatusForCharSlot( (INT8) iValue + FIRSTmercTOdisplay ) ) { pSoldier = gCharactersList[ iValue + FIRSTmercTOdisplay ].usSolID; if( pSoldier->flags.fMercAsleep == TRUE ) { // try to wake him up if( SetMercAwake( pSoldier, gGameExternalOptions.fSleepDisplayFailNotification, FALSE ) ) { // HEADROCK HAM B2.8: New feature wakes all trainees/trainers automatically HandleTrainingWakeSynchronize( pSoldier ); // propagate HandleSelectedMercsBeingPutAsleep( TRUE, gGameExternalOptions.fSleepDisplayFailNotification); return; } else { HandleSelectedMercsBeingPutAsleep( TRUE, FALSE ); } } else // awake { // try to put him to sleep // Flugente: externalised option on whether messages on why merc cannot sleep appear if ( SetMercAsleep( pSoldier, gGameExternalOptions.fSleepDisplayFailNotification ) ) { // HEADROCK HAM B2.8: New feature sends all trainees/trainers to sleep automatically HandleTrainingSleepSynchronize( pSoldier ); // propagate HandleSelectedMercsBeingPutAsleep( FALSE, gGameExternalOptions.fSleepDisplayFailNotification); return; } else { HandleSelectedMercsBeingPutAsleep( FALSE, FALSE ); } } } } else { // reset selected characters ResetAllSelectedCharacterModes( ); } } if (iReason & MSYS_CALLBACK_REASON_RBUTTON_UP) { // reset selected characters ResetAllSelectedCharacterModes( ); } } void TeamListSleepRegionMvtCallBack( MOUSE_REGION *pRegion, INT32 iReason ) { INT32 iValue = -1; if( fLockOutMapScreenInterface || gfPreBattleInterfaceActive ) { return; } iValue = MSYS_GetRegionUserData( pRegion, 0 ); if (iReason & MSYS_CALLBACK_REASON_MOVE) { // marke strogg more mercs So, the ACTUAL merc is location + FIRSTmercTOdisplay if( gCharactersList[ iValue + FIRSTmercTOdisplay ].fValid == TRUE ) { giHighLine = iValue; if ( CanChangeSleepStatusForCharSlot( (INT8) iValue + FIRSTmercTOdisplay ) ) { giSleepHighLine = iValue; } else { giSleepHighLine = -1; } } else { // can't highlight line giHighLine = -1; giSleepHighLine = -1; } } else if( iReason & MSYS_CALLBACK_REASON_LOST_MOUSE ) { giHighLine = -1; giSleepHighLine = -1; // restore background RestoreBackgroundForSleepGlowRegionList( ); } else if( iReason & MSYS_CALLBACK_REASON_GAIN_MOUSE ) { if ( CanChangeSleepStatusForCharSlot( (INT8) iValue + FIRSTmercTOdisplay ) ) { // play click PlayGlowRegionSound( ); } } } static void HandleSelectedMercsContract() { INT32 iCounter = 0; UINT8 ubNumberOfSelectedSoldiers = 0; INT32 DailySalaries = 0; INT32 WeeklySalaries = 0; INT32 BiweeklySalaries = 0; SOLDIERTYPE* pSoldier = nullptr; gSelectedSoldiers.clear(); for (iCounter = 0; iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; ++iCounter) { pSoldier = nullptr; // if the current character in the list is valid...then grab soldier pointer for the character if (gCharactersList[iCounter].fValid) { // get the soldier pointer pSoldier = gCharactersList[iCounter].usSolID; if (pSoldier->bActive == FALSE) { continue; } if (IsEntryInSelectedListSet(iCounter) == FALSE) { continue; } if (CanExtendContractForCharSlot(iCounter)) { // up the total number of soldiers gSelectedSoldiers.push_back(pSoldier); ubNumberOfSelectedSoldiers++; DailySalaries += gMercProfiles[pSoldier->ubProfile].sSalary; WeeklySalaries += gMercProfiles[pSoldier->ubProfile].uiWeeklySalary; BiweeklySalaries += gMercProfiles[pSoldier->ubProfile].uiBiWeeklySalary; bSelectedContractChar = bSelectedInfoChar; giContractHighLine = bSelectedContractChar; } } } if (ubNumberOfSelectedSoldiers > 1) { for (size_t i = 0; i < ubNumberOfSelectedSoldiers; i++) { CheckIfSalaryIncreasedAndSayQuote(gSelectedSoldiers[i], false); } CreateContractBoxMultiSelect(DailySalaries, WeeklySalaries, BiweeklySalaries); } else if (ubNumberOfSelectedSoldiers == 1) { RequestContractMenu(); } } void TeamListContractRegionBtnCallBack(MOUSE_REGION *pRegion, INT32 iReason ) { INT32 iValue = 0; if( fLockOutMapScreenInterface || gfPreBattleInterfaceActive ) { return; } // marke strogg more mercs must add skipped mercs FIRSTmercTOdisplay iValue = MSYS_GetRegionUserData( pRegion, 0 ); #if 0 if( gCharactersList[ iValue ].fValid == TRUE && ValidSelectableCharForNextOrPrev(iValue + FIRSTmercTOdisplay)) { if (iReason & MSYS_CALLBACK_REASON_LBUTTON_UP) { // select ONLY this dude ChangeSelectedInfoChar( ( INT8 ) iValue + FIRSTmercTOdisplay, TRUE ); // reset character giDestHighLine = -1; bSelectedAssignChar = -1; SetSelectedDestChar( -1 ); bSelectedContractChar = -1; fPlotForHelicopter = FALSE; fPlotForMilitia = FALSE; fTeamPanelDirty = TRUE; } ContractRegionBtnCallback( pRegion, iReason ); } #else if (iReason & MSYS_CALLBACK_REASON_LBUTTON_UP) { if ((gCharactersList[iValue + FIRSTmercTOdisplay].fValid == TRUE)) { // HEADROCK HAM B2.8: Added argument for multi-select entire squads if (HandleCtrlOrShiftInTeamPanel(iValue + FIRSTmercTOdisplay, FALSE)) { return; } // reset list if the clicked character isn't also selected ChangeSelectedInfoChar(iValue + FIRSTmercTOdisplay, (BOOLEAN)(IsEntryInSelectedListSet(iValue + FIRSTmercTOdisplay) == FALSE)); HandleSelectedMercsContract(); } else { // reset selected characters ResetAllSelectedCharacterModes(); } } #endif if (iReason & MSYS_CALLBACK_REASON_RBUTTON_UP) { // reset selected characters ResetAllSelectedCharacterModes( ); } } void TeamListContractRegionMvtCallBack(MOUSE_REGION *pRegion, INT32 iReason ) { INT32 iValue = -1; if( fLockOutMapScreenInterface || gfPreBattleInterfaceActive ) { return; } iValue = MSYS_GetRegionUserData( pRegion, 0 ); if (iReason & MSYS_CALLBACK_REASON_MOVE) { // marke strogg more mercs So, the ACTUAL merc is location + FIRSTmercTOdisplay if( gCharactersList[ iValue + FIRSTmercTOdisplay ].fValid == TRUE ) { giHighLine = iValue; if( CanExtendContractForCharSlot( iValue + FIRSTmercTOdisplay ) ) { giContractHighLine = iValue; } else { giContractHighLine = -1; } } else { // can't highlight line giHighLine = -1; giContractHighLine = -1; } } else if( iReason & MSYS_CALLBACK_REASON_LOST_MOUSE ) { giHighLine = -1; // no longer valid char?...reset display of highlight boxes if( fShowContractMenu == FALSE ) { giContractHighLine = -1; } // restore background RestoreBackgroundForContractGlowRegionList( ); } else if( iReason & MSYS_CALLBACK_REASON_GAIN_MOUSE ) { if( CanExtendContractForCharSlot( iValue + FIRSTmercTOdisplay ) ) { // play click PlayGlowRegionSound( ); } } } INT32 GetIndexForthis( SOLDIERTYPE *pSoldier ) { INT32 iLastGuy; INT32 iIndex = 0; INT32 iCounter = 0; // get the index into the characters list for this soldier type iLastGuy = gTacticalStatus.Team[ OUR_TEAM ].bLastID; for( iCounter = 0; iCounter < iLastGuy; iCounter++ ) { if( gCharactersList[ iCounter ].fValid == TRUE ) { if( gCharactersList[ iCounter ].usSolID == pSoldier->ubID ) { iIndex = iCounter; iCounter = iLastGuy; } } } return( iIndex ); } BOOLEAN IsCursorWithInRegion(INT16 sLeft, INT16 sRight, INT16 sTop, INT16 sBottom ) { POINT MousePos; // get cursor position GetCursorPos(&MousePos); ScreenToClient(ghWindow, &MousePos); // In window coords! // is it within region? if( ( sLeft < MousePos.x ) && ( sRight > MousePos.x) && (sTop < MousePos.y ) && ( sBottom > MousePos.y ) ) { return ( TRUE ); } else { return ( FALSE ); } } void HandleHighLightingOfLinesInTeamPanel( void ) { if ( fShowInventoryFlag ) { return; } // will highlight or restore backgrounds to highlighted lines // restore backgrounds, if need be RestoreBackgroundForAssignmentGlowRegionList( ); RestoreBackgroundForDestinationGlowRegionList( ); RestoreBackgroundForContractGlowRegionList( ); RestoreBackgroundForSleepGlowRegionList( ); HighLightAssignLine( /*(UINT16)giAssignHighLine*/ ); // doesn't take parameters (jonathanl) HighLightDestLine( /*(UINT16)giDestHighLine */); // doesn't take parameters (jonathanl) HighLightSleepLine( /*(UINT16)giSleepHighLine */); // doesn't take parameters (jonathanl) // contracts? if( giContractHighLine != -1 ) { ContractListRegionBoxGlow( ( UINT16 ) giContractHighLine ); } } void PlotPermanentPaths( void ) { if( fPlotForHelicopter ) { DisplayHelicopterPath( ); } else if ( fPlotForMilitia ) { DisplayMilitiaPath(); } else if( GetSelectedDestChar() != -1 ) { DisplaySoldierPath( gCharactersList[GetSelectedDestChar()].usSolID ); } } void PlotTemporaryPaths( void ) { INT16 sMapX, sMapY; // check to see if we have in fact moved are are plotting a path? if ( GetMouseMapXY( &sMapX, &sMapY ) ) { if ( fPlotForHelicopter ) { Assert( gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE || gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE_COLOURED_SAMS ); // plot temp path PlotATemporaryPathForHelicopter( sMapX, sMapY); // check if potential path is allowed DisplayThePotentialPathForHelicopter( sMapX, sMapY ); if( fDrawTempHeliPath ) { // clip region ClipBlitsToMapViewRegion( ); // display heli temp path DisplayHelicopterTempPath( ); //restore RestoreClipRegionToFullScreen( ); } } else if ( fPlotForMilitia ) { Assert( fShowMilitia ); // plot temp path PlotATemporaryPathForMilitia( sMapX, sMapY ); // check if potential path is allowed DisplayThePotentialPathForMilitia( sMapX, sMapY ); if ( fDrawTempMilitiaPath ) { // clip region ClipBlitsToMapViewRegion( ); // display heli temp path DisplayMilitiaTempPath( ); //restore RestoreClipRegionToFullScreen( ); } } // dest char has been selected, else if( GetSelectedDestChar() != -1 ) { PlotATemporaryPathForCharacter( gCharactersList[GetSelectedDestChar()].usSolID, sMapX, sMapY ); // check to see if we are drawing path DisplayThePotentialPathForCurrentDestinationCharacterForMapScreenInterface( sMapX, sMapY ); // if we need to draw path, do it if( fDrawTempPath == TRUE ) { // clip region ClipBlitsToMapViewRegion( ); // blit DisplaySoldierTempPath( gCharactersList[GetSelectedDestChar()].usSolID ); // restore RestoreClipRegionToFullScreen( ); } } } } void RenderMapRegionBackground( void ) { // renders to save buffer when dirty flag set if( fMapPanelDirty == FALSE ) { gfMapPanelWasRedrawn = FALSE; // not dirty, leave return; } // don't bother if showing sector inventory instead of the map!!! if( !fShowMapInventoryPool ) { // draw map DrawMap( ); } // blit in border RenderMapBorder( ); if ( ghAttributeBox != - 1 ) { ForceUpDateOfBox( ghAttributeBox ); } // HEADROCK HAM 3.6: Force re-render due to Facility box if ( ghFacilityAssignmentBox != 1 ) { ForceUpDateOfBox( ghFacilityAssignmentBox ); } if ( ghTownMineBox != - 1 ) { // force update of town mine info boxes ForceUpDateOfBox( ghTownMineBox ); } MapscreenMarkButtonsDirty(); RestoreExternBackgroundRect( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT ); // don't bother if showing sector inventory instead of the map!!! if( !fShowMapInventoryPool ) { // if Skyrider can and wants to talk to us if( IsHelicopterPilotAvailable( ) ) { // see if Skyrider has anything new to tell us CheckAndHandleSkyriderMonologues( ); } } // reset dirty flag fMapPanelDirty = FALSE; gfMapPanelWasRedrawn = TRUE; } void RenderTeamRegionBackgroundWideScreen(void) { // renders to save buffer when dirty flag set if (fTeamPanelDirty == FALSE) { // not dirty, leave return; } // show inventory and the team list HVOBJECT hHandle; GetVideoObject(&hHandle, guiCHARLIST); BltVideoObject(guiSAVEBUFFER, hHandle, 0, UI_CHARLIST.Region, VO_BLT_SRCTRANSPARENCY, NULL); HandleHighLightingOfLinesInTeamPanel(); DisplayCharacterList(); fDrawCharacterList = FALSE; // display arrows by selected people HandleDisplayOfSelectedMercArrows(); DisplayIconsForMercsAsleep(); // reset dirty flag fTeamPanelDirty = FALSE; gfRenderPBInterface = TRUE; // mark all pop ups as dirty MarkAllBoxesAsAltered(); // restore background for area RestoreExternBackgroundRect(UI_CHARLIST.Region); MapscreenMarkButtonsDirty(); } void RenderCharacterInventoryWideScreen(void) { if (!gfItemDescTransformPopupVisible) { BltCharInvPanel(); MarkAllBoxesAsAltered(); if (!InItemDescriptionBox()) { RestoreExternBackgroundRect(UI_CHARINV.Region); } } } void RenderTeamRegionBackground( void ) { if (isWidescreenUI()) { RenderTeamRegionBackgroundWideScreen(); RenderCharacterInventoryWideScreen(); } else { // renders to save buffer when dirty flag set if (fTeamPanelDirty == FALSE) { // not dirty, leave return; } // show inventory or the team list? if (fShowInventoryFlag == FALSE) { HVOBJECT hHandle; GetVideoObject(&hHandle, guiCHARLIST); BltVideoObject(guiSAVEBUFFER, hHandle, 0, UI_CHARLIST.Region, VO_BLT_SRCTRANSPARENCY, NULL); HandleHighLightingOfLinesInTeamPanel(); DisplayCharacterList(); HandleDisplayOfSelectedMercArrows(); DisplayIconsForMercsAsleep(); RestoreExternBackgroundRect(UI_CHARLIST.Region); } else { BltCharInvPanel(); RestoreExternBackgroundRect(UI_CHARINV.Region); } fDrawCharacterList = FALSE; // reset dirty flag fTeamPanelDirty = FALSE; gfRenderPBInterface = TRUE; // mark all pop ups as dirty MarkAllBoxesAsAltered(); MapscreenMarkButtonsDirty(); } } void RenderCharacterInfoBackground( void ) { HVOBJECT hHandle; // will render the background for the character info panel if( fCharacterInfoPanelDirty == FALSE ) { // not dirty, leave return; } // the upleft hand corner character info panel GetVideoObject(&hHandle, guiCHARINFO); BltVideoObject(guiSAVEBUFFER, hHandle, 0, UI_CHARPANEL.Region.x, UI_CHARPANEL.Region.y, VO_BLT_SRCTRANSPARENCY, NULL); UpdateHelpTextForMapScreenMercIcons( ); if( ( bSelectedInfoChar != -1) && ( fDisableDueToBattleRoster == FALSE ) ) { // valid char to display DisplayCharacterInfo(); } if( ( fDisableDueToBattleRoster == FALSE ) ) { // draw attributes RenderAttributeStringsForUpperLeftHandCorner( guiSAVEBUFFER ); } // reset dirty flag fCharacterInfoPanelDirty = FALSE; // redraw face fReDrawFace = TRUE; MapscreenMarkButtonsDirty(); // mark all pop ups as dirty MarkAllBoxesAsAltered( ); // restore background for area RestoreExternBackgroundRect(UI_CHARPANEL.Region); } void DetermineIfContractMenuCanBeShown( void ) { if( fShowContractMenu == FALSE ) { // destroy menus for contract region CreateDestroyMouseRegionsForContractMenu( ); // hide all boxes HideBox( ghContractBox ); // make sure, absolutly sure we want to hide this box if( fShowAssignmentMenu == FALSE ) { HideBox( ghRemoveMercAssignBox ); } return; } // create mask, if needed CreateDestroyScreenMaskForAssignmentAndContractMenus( ); // create mouse regions for contract region CreateDestroyMouseRegionsForContractMenu( ); // determine which lines selectable HandleShadingOfLinesForContractMenu( ); if( gCharactersList[ bSelectedInfoChar ].usSolID->stats.bLife == 0 ) { // show basic assignment menu ShowBox( ghRemoveMercAssignBox ); } else { // show basic contract menu ShowBox( ghContractBox ); } } void CheckIfPlottingForCharacterWhileAirCraft( void ) { // if the plotting modes are inconsistent, stop plotting BOOLEAN fAbort = FALSE; if ( gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE || gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE_COLOURED_SAMS ) { if ( ( GetSelectedDestChar() != -1 || fPlotForMilitia) && !fPlotForHelicopter ) fAbort = TRUE; } else { if ( fPlotForHelicopter ) fAbort = TRUE; } if ( fShowMilitia ) { if ( ( GetSelectedDestChar() != -1 || fPlotForHelicopter) && !fPlotForMilitia ) fAbort = TRUE; } else { if ( fPlotForMilitia ) fAbort = TRUE; } if ( fAbort ) AbortMovementPlottingMode( ); } void ContractRegionBtnCallback( MOUSE_REGION *pRegion, INT32 iReason ) { SOLDIERTYPE *pSoldier = NULL; // btn callback handler for contract region if( ( iDialogueBox != -1 ) ) { return; } if (iReason & MSYS_CALLBACK_REASON_LBUTTON_UP) { if( IsMapScreenHelpTextUp() ) { // stop mapscreen text StopMapScreenHelpText( ); return; } if( CanExtendContractForCharSlot( bSelectedInfoChar ) ) { pSoldier = gCharactersList[ bSelectedInfoChar ].usSolID; // create RebuildContractBoxForMerc( pSoldier ); // reset selected characters ResetAllSelectedCharacterModes( ); bSelectedContractChar = bSelectedInfoChar; giContractHighLine = bSelectedContractChar; // if not triggered internally if ( CheckIfSalaryIncreasedAndSayQuote( pSoldier, TRUE ) == FALSE ) { // show contract box fShowContractMenu = TRUE; // stop any active dialogue StopAnyCurrentlyTalkingSpeech( ); } //fCharacterInfoPanelDirty = TRUE; } else { // reset selected characters ResetAllSelectedCharacterModes( ); } } if (iReason & MSYS_CALLBACK_REASON_RBUTTON_UP) { // reset selected characters ResetAllSelectedCharacterModes( ); } } void ContractRegionMvtCallback( MOUSE_REGION *pRegion, INT32 iReason ) { // mvt callback handler for contract region if( iReason & MSYS_CALLBACK_REASON_LOST_MOUSE ) { if( fGlowContractRegion == TRUE ) { // not showing box and lost mouse?..stop glowing if( fShowContractMenu == FALSE ) { fGlowContractRegion = FALSE; fCharacterInfoPanelDirty = TRUE; giContractHighLine = -1; // reset glow fResetContractGlow = TRUE; } } } else if( iReason & MSYS_CALLBACK_REASON_GAIN_MOUSE ) { if( bSelectedInfoChar != -1 ) { if( gCharactersList[ bSelectedInfoChar ].fValid == TRUE ) { if( fShowContractMenu == FALSE ) { // glow region fGlowContractRegion = TRUE; giContractHighLine = bSelectedInfoChar; PlayGlowRegionSound( ); } } } } } void HandleShadingOfLinesForContractMenu( void ) { SOLDIERTYPE *pSoldier; MERCPROFILESTRUCT *pProfile; if( ( fShowContractMenu == FALSE ) || ( ghContractBox == - 1 ) ) { return; } // error check, return if not a valid character if( bSelectedContractChar == -1 ) { return; } // check if this character is a valid character if( gCharactersList[ bSelectedContractChar ].fValid == FALSE ) { return; } Assert( CanExtendContractForCharSlot( bSelectedContractChar ) ); // grab the character pSoldier = gCharactersList[ bSelectedContractChar ].usSolID; // is guy in AIM? and well enough to talk and make such decisions? if( ( pSoldier->ubWhatKindOfMercAmI == MERC_TYPE__AIM_MERC ) && ( pSoldier->stats.bLife >= OKLIFE ) ) { pProfile = &( gMercProfiles[ pSoldier->ubProfile ] ); if (is_networked) { // WANNE - MP: Shade all contract renewals, because it is not needed in a MP game ShadeStringInBox( ghContractBox, CONTRACT_MENU_DAY ); ShadeStringInBox( ghContractBox, CONTRACT_MENU_WEEK ); ShadeStringInBox( ghContractBox, CONTRACT_MENU_TWO_WEEKS ); } else { // one day if( pProfile->sSalary > LaptopSaveInfo.iCurrentBalance ) { ShadeStringInBox( ghContractBox, CONTRACT_MENU_DAY ); } else { UnShadeStringInBox( ghContractBox, CONTRACT_MENU_DAY ); } // one week if( ( INT32 )( pProfile->uiWeeklySalary ) > LaptopSaveInfo.iCurrentBalance ) { ShadeStringInBox( ghContractBox, CONTRACT_MENU_WEEK ); } else { UnShadeStringInBox( ghContractBox, CONTRACT_MENU_WEEK ); } // two weeks if( ( INT32 )( pProfile->uiBiWeeklySalary ) > LaptopSaveInfo.iCurrentBalance ) { ShadeStringInBox( ghContractBox, CONTRACT_MENU_TWO_WEEKS ); } else { UnShadeStringInBox( ghContractBox, CONTRACT_MENU_TWO_WEEKS ); } } } else { // can't extend contract duration ShadeStringInBox( ghContractBox, CONTRACT_MENU_DAY ); ShadeStringInBox( ghContractBox, CONTRACT_MENU_WEEK ); ShadeStringInBox( ghContractBox, CONTRACT_MENU_TWO_WEEKS ); } // if THIS soldier is involved in a fight (dismissing in a hostile sector IS ok...) // Also if we have multiple mercs selected, disable terminating contracts if( gSelectedSoldiers.size() > 0 || (( gTacticalStatus.uiFlags & INCOMBAT ) && pSoldier->bInSector )) { ShadeStringInBox( ghContractBox, CONTRACT_MENU_TERMINATE ); } else { UnShadeStringInBox( ghContractBox, CONTRACT_MENU_TERMINATE ); } // WANNE - MP: Disable "Dismiss" button when Random merc was selected, because we cannot hire any new merc if (is_networked && gRandomMercs) { ShadeStringInBox( ghContractBox, CONTRACT_MENU_TERMINATE ); } } void ReBuildCharactersList( void ) { // rebuild character's list INT16 sCount = 0; // add in characters for ( sCount = 0; sCount < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; sCount++) { // clear this slot gCharactersList[ sCount ].fValid = FALSE; gCharactersList[ sCount ].usSolID = NOBODY; } // fills array with presence of player controlled characters for ( SoldierID soldier = gTacticalStatus.Team[ OUR_TEAM ].bFirstID; soldier <= gTacticalStatus.Team[ OUR_TEAM ].bLastID; ++soldier ) { if( soldier->bActive ) { AddCharacter( soldier ); } } // sort them according to current sorting method SortListOfMercsInTeamPanel( FALSE ); // if nobody is selected, or the selected merc has somehow become invalid if ( ( bSelectedInfoChar == -1 ) || ( !gCharactersList[ bSelectedInfoChar ].fValid ) ) { // is the first character in the list valid? if ( gCharactersList[ 0 ].fValid ) { // select him ChangeSelectedInfoChar( 0, TRUE ); } else { // select no one ChangeSelectedInfoChar( -1, TRUE ); } } // exit inventory mode fShowInventoryFlag = FALSE; // switch hand region help text to "Enter Inventory" SetRegionFastHelpText( &gCharInfoHandRegion, pMiscMapScreenMouseRegionHelpText[ 0 ] ); } void HandleChangeOfInfoChar( void ) { static INT16 bOldInfoChar = -1; if( bSelectedInfoChar != bOldInfoChar ) { // set auto faces inactive // valid character? if( bOldInfoChar != -1 ) { if( gCharactersList[ bOldInfoChar ].fValid == TRUE ) { // set face in active SetAutoFaceInActiveFromSoldier( gCharactersList[ bOldInfoChar ].usSolID ); } } // stop showing contract box //fShowContractMenu = FALSE; // update old info char value bOldInfoChar = bSelectedInfoChar; } } void RebuildContractBoxForMerc( SOLDIERTYPE *pCharacter ) { // rebuild contractbox for this merc RemoveBox( ghContractBox ); ghContractBox = -1; // recreate CreateContractBox( pCharacter ); return; } void TestMessageSystem( void ) { INT32 iCounter = 0; for( iCounter = 0; iCounter < 300; iCounter++ ) { MapScreenMessage( FONT_MCOLOR_DKRED, MSG_INTERFACE, L"%d", iCounter ); } MapScreenMessage( FONT_MCOLOR_DKRED, MSG_INTERFACE, L"%d", iCounter ); return; } void EnableDisableTeamListRegionsAndHelpText( void ) { // check if valid character here, if so, then do nothing..other wise set help text timer to a gazillion INT16 bCharNum; for( bCharNum = 0; bCharNum < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; bCharNum++ ) { // marke strogg more mercs limit regions to actual mercs + only do it for 18 slots if( gCharactersList[ bCharNum + FIRSTmercTOdisplay].fValid == FALSE || bCharNum >= maxNumberOfMercVisibleInStrategyList ) { // disable regions in all team list columns MSYS_DisableRegion( &gTeamListNameRegion[ bCharNum ] ); MSYS_DisableRegion( &gTeamListAssignmentRegion[ bCharNum ] ); MSYS_DisableRegion( &gTeamListLocationRegion[ bCharNum ] ); MSYS_DisableRegion( &gTeamListSleepRegion[ bCharNum ] ); MSYS_DisableRegion( &gTeamListDestinationRegion[ bCharNum ] ); MSYS_DisableRegion( &gTeamListContractRegion[ bCharNum ] ); } else { // always enable Name and Location regions MSYS_EnableRegion( &gTeamListNameRegion[ bCharNum ] ); MSYS_EnableRegion( &gTeamListLocationRegion[ bCharNum ] ); // valid character. If it's a vehicle, however if ( gCharactersList[ bCharNum + FIRSTmercTOdisplay].usSolID->flags.uiStatusFlags & SOLDIER_VEHICLE ) { // Can't change assignment for vehicles MSYS_DisableRegion( &gTeamListAssignmentRegion[ bCharNum ] ); } else { MSYS_EnableRegion( &gTeamListAssignmentRegion[ bCharNum ] ); // POW or dead ? if ( ( gCharactersList[ bCharNum + FIRSTmercTOdisplay].usSolID->bAssignment == ASSIGNMENT_POW ) || ( gCharactersList[ bCharNum + FIRSTmercTOdisplay].usSolID->stats.bLife == 0 ) ) { // "Remove Merc" SetRegionFastHelpText( &gTeamListAssignmentRegion[ bCharNum ], pRemoveMercStrings[ 0 ] ); SetRegionFastHelpText( &gTeamListDestinationRegion[ bCharNum ], L"" ); } else { // "Assign Merc" SetRegionFastHelpText( &gTeamListAssignmentRegion[ bCharNum ], pMapScreenMouseRegionHelpText[ 1 ] ); // "Plot Travel Route" SetRegionFastHelpText( &gTeamListDestinationRegion[ bCharNum ], pMapScreenMouseRegionHelpText[ 2 ] ); } } if ( CanExtendContractForCharSlot( bCharNum + FIRSTmercTOdisplay ) ) // marke strogg more mercs { MSYS_EnableRegion( &gTeamListContractRegion[ bCharNum ] ); } else { MSYS_DisableRegion( &gTeamListContractRegion[ bCharNum ] ); } if ( CanChangeSleepStatusForCharSlot( bCharNum + FIRSTmercTOdisplay ) ) { MSYS_EnableRegion( &gTeamListSleepRegion[ bCharNum ] ); } else { MSYS_DisableRegion( &gTeamListSleepRegion[ bCharNum ] ); } // destination region is always enabled for all valid character slots. // if the character can't move at this time, then the region handler must be able to tell the player why not MSYS_EnableRegion( &gTeamListDestinationRegion[ bCharNum ] ); } } } void ResetAllSelectedCharacterModes( void ) { if( IsMapScreenHelpTextUp() ) { // stop mapscreen text StopMapScreenHelpText( ); return; } // if in militia redistribution popup if ( sSelectedMilitiaTown != 0 ) { sSelectedMilitiaTown = 0; } // cancel destination line highlight giDestHighLine = -1; // cancel assign line highlight giAssignHighLine = -1; // unhilight contract line giContractHighLine = -1; // if we were plotting movement if ( ( GetSelectedDestChar() != -1) || fPlotForHelicopter || fPlotForMilitia ) { AbortMovementPlottingMode(); } // reset assign character bSelectedAssignChar = -1; // reset contract character bSelectedContractChar = -1; // reset map cursor to normal if ( !gfFadeOutDone && !gfFadeIn ) { SetUpCursorForStrategicMap( ); } } void UpdatePausedStatesDueToTimeCompression( void ) { // this executes every frame, so keep it optimized for speed! // if time is being compressed if( IsTimeBeingCompressed() ) { // but it shouldn't be if ( !AllowedToTimeCompress( ) ) { // pause game to (temporarily) stop time compression PauseGame( ); } } else // time is NOT being compressed { // but the player would like it to be compressing if ( IsTimeCompressionOn() && !gfPauseDueToPlayerGamePause ) { // so check if it's legal to start time compressing again if ( AllowedToTimeCompress( ) ) { // unpause game to restart time compresssion UnPauseGame( ); } } } return; } BOOLEAN ContinueDialogue(SoldierID id, BOOLEAN fDone ) { // continue this grunts dialogue, restore when done static INT16 bOldSelectedInfoChar = -1; static BOOLEAN fTalkingingGuy = FALSE; UINT16 bCounter = 0; if( fDone == TRUE ) { if( fTalkingingGuy == TRUE ) { /* // done, restore if( bOldSelectedInfoChar != -1 ) { ChangeSelectedInfoChar( bOldSelectedInfoChar, TRUE ); SetAutoFaceInActive( gCharactersList[ bSelectedInfoChar ].usSolID->iFaceIndex ); } */ fCharacterInfoPanelDirty = TRUE; fTalkingingGuy = FALSE; } return( TRUE ); } // check if valid character talking? if( id >= NOBODY ) { return FALSE; } // otherwise, find this character for( bCounter = 0; bCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; bCounter++ ) { if( gCharactersList[bCounter].fValid == TRUE ) { if( gCharactersList[bCounter].usSolID == id ) { if( bSelectedInfoChar != bCounter ) { bOldSelectedInfoChar = bSelectedInfoChar; ChangeSelectedInfoChar( bCounter, TRUE ); } fTalkingingGuy = TRUE; return ( FALSE ); } } } return ( FALSE ); } void HandleSpontanousTalking( ) { // simply polls if the talking guy is done, if so...send an end command to continue dialogue if( DialogueActive() == FALSE ) { if( ( bSelectedInfoChar != -1 ) && ( bSelectedInfoChar < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS ) ) { ContinueDialogue( gCharactersList[bSelectedInfoChar].usSolID, TRUE ); } } } BOOLEAN CheckIfClickOnLastSectorInPath( INT16 sX, INT16 sY ) { PathStPtr *ppMovePath = NULL; BOOLEAN fLastSectorInPath = FALSE; INT32 iVehicleId = -1; PathStPtr pPreviousMercPath = NULL; // see if we have clicked on the last sector in the characters path // check if helicopter if( fPlotForHelicopter ) { // helicopter route confirmed if ( CALCULATE_STRATEGIC_INDEX( sX, sY ) == GetLastSectorOfHelicoptersPath( ) ) { // WANNE: This check was added in revision 4724, to prevent the loophole for helicopter hovering forever // But is seems, it also causes the bug, that skyrider is stuck in the sector forever (bugzilla #562) // So hopefully, skyrider does not stuck anymore ... // if confirm moving to another sector //if( ( CheckForClickOverHelicopterIcon( sX, sY ) == FALSE ) ) { // take off TakeOffHelicopter( ); } // rebuild waypoints - helicopter ppMovePath = &( pVehicleList[ iHelicopterVehicleId ].pMercPath ); RebuildWayPointsForGroupPath( *ppMovePath, pVehicleList[ iHelicopterVehicleId ].ubMovementGroup ); // pointer to previous helicopter path pPreviousMercPath = gpHelicopterPreviousMercPath; fLastSectorInPath = TRUE; } } else if ( fPlotForMilitia ) { // helicopter route confirmed if ( gMilitiaPath[gMilitiaGroupId].sGroupid > -1 && CALCULATE_STRATEGIC_INDEX(sX, sY) == GetLastSectorOfMilitiaPath( ) ) { // rebuild waypoints ppMovePath = &( gMilitiaPath[gMilitiaGroupId].path ); // if our current sector is in our path, and we are not moving, we can obviously delete what came before it from the path // (this was added as there were occasions where the previous path was not properly cleared even though the group was no longer travelling) GROUP* pGroup = GetGroup( (UINT8)gMilitiaPath[gMilitiaGroupId].sGroupid ); if ( pGroup && pGroup->usGroupTeam == MILITIA_TEAM && !pGroup->fBetweenSectors ) { *ppMovePath = ClearStrategicPathListBeforeThisSector( *ppMovePath, pGroup->ubSectorX, pGroup->ubSectorY, gMilitiaPath[gMilitiaGroupId].sGroupid ); } RebuildWayPointsForGroupPath( *ppMovePath, (UINT8)gMilitiaPath[gMilitiaGroupId].sGroupid ); // pointer to previous path pPreviousMercPath = gpMilitiaPreviousMercPath; fLastSectorInPath = TRUE; } } else // not doing helicopter movement { // if not doing a soldier either, we shouldn't be here! if( GetSelectedDestChar() == -1 ) { return( FALSE ); } // invalid soldier? we shouldn't be here! if( gCharactersList[GetSelectedDestChar()].fValid == FALSE ) { SetSelectedDestChar( -1 ); return( FALSE ); } SOLDIERTYPE* pSoldier = gCharactersList[GetSelectedDestChar()].usSolID; if ( CALCULATE_STRATEGIC_INDEX( sX, sY ) == GetLastSectorIdInCharactersPath( pSoldier ) ) { // clicked on last sector, reset plotting mode // if he's IN a vehicle or IS a vehicle if( ( pSoldier->bAssignment == VEHICLE ) || ( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) ) { if( pSoldier->bAssignment == VEHICLE ) { // IN a vehicle iVehicleId = pSoldier->iVehicleId; } else { // IS a vehicle iVehicleId = pSoldier->bVehicleID; } // rebuild waypoints - vehicles ppMovePath = &( pVehicleList[ iVehicleId ].pMercPath ); } else { // rebuild waypoints - mercs on foot ppMovePath = &( pSoldier->pMercPath ); } RebuildWayPointsForAllSelectedCharsGroups( ); // pointer to previous character path pPreviousMercPath = gpCharacterPreviousMercPath[GetSelectedDestChar()]; fLastSectorInPath = TRUE; } } // if the click was over the last sector if ( fLastSectorInPath ) { // route has been confirmed EndConfirmMapMoveMode( ); // if we really did plot a path (this will skip message if left click on current sector with no path) if ( GetLengthOfPath( *ppMovePath ) > 0 ) { // then verbally confirm this destination! HandleNewDestConfirmation( sX, sY ); } else // NULL path confirmed { // if previously there was a path if ( pPreviousMercPath != NULL ) { // then this means we've CANCELED it MapScreenMessage( FONT_MCOLOR_LTYELLOW, MSG_MAP_UI_POSITION_MIDDLE, pMapPlotStrings[ 3 ] ); } else // no previous path { // then it means the route was UNCHANGED MapScreenMessage( FONT_MCOLOR_LTYELLOW, MSG_MAP_UI_POSITION_MIDDLE, pMapPlotStrings[ 2 ] ); } } } return( fLastSectorInPath ); } void RebuildWayPointsForAllSelectedCharsGroups( void ) { // rebuild the waypoints for everyone in the selected character list INT32 iCounter = 0; BOOLEAN fGroupIDRebuilt[ 256 ]; SOLDIERTYPE *pSoldier = NULL; INT32 iVehicleId; PathStPtr *ppMovePath = NULL; UINT8 ubGroupId; memset( fGroupIDRebuilt, FALSE, sizeof( fGroupIDRebuilt ) ); for( iCounter = 0; iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; iCounter++ ) { if( ( fSelectedListOfMercsForMapScreen[ iCounter ] == TRUE ) ) { pSoldier = gCharactersList[ iCounter ].usSolID; // if he's IN a vehicle or IS a vehicle if( ( pSoldier->bAssignment == VEHICLE ) || ( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) ) { if( pSoldier->bAssignment == VEHICLE ) { // IN a vehicle iVehicleId = pSoldier->iVehicleId; } else { // IS a vehicle iVehicleId = pSoldier->bVehicleID; } // vehicles ppMovePath = &( pVehicleList[ iVehicleId ].pMercPath ); ubGroupId = pVehicleList[ iVehicleId ].ubMovementGroup; } else { // mercs on foot /*CHRISL: I don't understand why we're using bSelectedDestChar to generate the ppMovePath but iCounter to generate ubGroupId. For vehicles, we use the iVhicleId to generate both. Shouldn't we be using the same system here? Meaning, shouldn't ppMovePath be generated with the soldier indicated with iCounter?*/ //ppMovePath = &( Menptr[gCharactersList[ bSelectedDestChar ].usSolID].pMercPath ); ppMovePath = &( pSoldier->pMercPath ); ubGroupId = pSoldier->ubGroupID; } // if we haven't already rebuilt this group if ( !fGroupIDRebuilt[ ubGroupId ] ) { // rebuild it now RebuildWayPointsForGroupPath( *ppMovePath, ubGroupId ); // mark it as rebuilt fGroupIDRebuilt[ ubGroupId ] = TRUE; } } } } void UpdateCursorIfInLastSector( void ) { INT16 sMapX = 0, sMapY = 0; // check to see if we are plotting a path, if so, see if we are highlighting the last sector int he path, if so, change the cursor if ( ( GetSelectedDestChar() != -1) || fPlotForHelicopter || fPlotForMilitia ) { GetMouseMapXY(&sMapX, &sMapY); if ( gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE || gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE_COLOURED_SAMS ) { // check for helicopter if ( fPlotForHelicopter ) { if ( CALCULATE_STRATEGIC_INDEX( sMapX, sMapY ) == GetLastSectorOfHelicoptersPath( ) ) { // set cursor to checkmark ChangeMapScreenMaskCursor( CURSOR_CHECKMARK ); } else if ( fCheckCursorWasSet ) { // reset to walking guy/vehicle SetUpCursorForStrategicMap( ); } } else { // reset to walking guy/vehicle SetUpCursorForStrategicMap( ); } } else if ( fShowMilitia ) { // check for militia if ( fPlotForMilitia ) { if ( CALCULATE_STRATEGIC_INDEX( sMapX, sMapY ) == GetLastSectorOfMilitiaPath( ) ) { // set cursor to checkmark ChangeMapScreenMaskCursor( CURSOR_CHECKMARK ); } else if ( fCheckCursorWasSet ) { // reset to walking guy/vehicle SetUpCursorForStrategicMap( ); } } else { // reset to walking guy/vehicle SetUpCursorForStrategicMap( ); } } else { if ( GetSelectedDestChar() != -1 ) { //c heck if we are in the last sector of the characters path? if ( CALCULATE_STRATEGIC_INDEX( sMapX, sMapY ) == GetLastSectorIdInCharactersPath( gCharactersList[GetSelectedDestChar()].usSolID ) ) { // set cursor to checkmark ChangeMapScreenMaskCursor( CURSOR_CHECKMARK ); } else if ( fCheckCursorWasSet ) { // reset to walking guy/vehicle SetUpCursorForStrategicMap( ); } } } } } void FaceRegionBtnCallback( MOUSE_REGION *pRegion, INT32 iReason ) { // error checking, make sure someone is there if( bSelectedInfoChar == -1 ) { return; } else if( gCharactersList[ bSelectedInfoChar ].fValid == FALSE ) { return; } if (iReason & MSYS_CALLBACK_REASON_LBUTTON_UP) { if( IsMapScreenHelpTextUp() ) { // stop mapscreen text StopMapScreenHelpText( ); return; } if( gfPreBattleInterfaceActive == TRUE ) { return; } // now stop any dialogue in progress StopAnyCurrentlyTalkingSpeech( ); } if (iReason & MSYS_CALLBACK_REASON_RBUTTON_UP) { RequestToggleMercInventoryPanel(); } } void FaceRegionMvtCallback( MOUSE_REGION *pRegion, INT32 iReason ) { if( bSelectedInfoChar == -1 ) { fShowFaceHightLight = FALSE; return; } else if( gCharactersList[ bSelectedInfoChar ].fValid == FALSE ) { fShowFaceHightLight = FALSE; return; } if( ( iReason & MSYS_CALLBACK_REASON_GAIN_MOUSE ) ) { fShowFaceHightLight = TRUE; } else if( iReason & MSYS_CALLBACK_REASON_LOST_MOUSE ) { fShowFaceHightLight = FALSE; } } void ItemRegionBtnCallback( MOUSE_REGION *pRegion, INT32 iReason ) { // left AND right button are handled the same way if (iReason & ( MSYS_CALLBACK_REASON_RBUTTON_UP | MSYS_CALLBACK_REASON_LBUTTON_UP ) ) { RequestToggleMercInventoryPanel(); } } void ItemRegionMvtCallback( MOUSE_REGION *pRegion, INT32 iReason ) { if ( !CanToggleSelectedCharInventory() ) { fShowItemHighLight = FALSE; return; } if( ( iReason & MSYS_CALLBACK_REASON_GAIN_MOUSE ) ) { fShowItemHighLight = TRUE; } else if( iReason & MSYS_CALLBACK_REASON_LOST_MOUSE ) { fShowItemHighLight = FALSE; } } void HandleChangeOfHighLightedLine( void ) { static INT32 iOldHighLine; if ( fShowInventoryFlag ) { return; } // check if change in highlight line if( giHighLine != iOldHighLine ) { iOldHighLine = giHighLine; if( giHighLine == -1 ) { giSleepHighLine = -1; giAssignHighLine = -1; giContractHighLine = -1; giSleepHighLine = -1; // don't do during plotting, allowing selected character to remain highlighted and their destination column to glow! if ( ( GetSelectedDestChar() == -1) && !fPlotForHelicopter && !fPlotForMilitia ) { giDestHighLine = -1; } } fDrawCharacterList = TRUE; } } void UpdateTownMinePopUpDisplay( void ) { if ( gMapViewRegion.uiFlags & MSYS_MOUSE_IN_AREA ) { ForceUpDateOfBox( ghTownMineBox ); MapscreenMarkButtonsDirty(); } } void HandleCharBarRender( void ) { // check if the panel is disbled, if so, do not render if( ( bSelectedInfoChar !=-1) && ( fDisableDueToBattleRoster == FALSE ) ) { // valid character?...render if( gCharactersList[ bSelectedInfoChar ].fValid == TRUE ) { //if( !( ( fShowContractMenu)||( fShowAssignmentMenu ) ) ) //{ // draw bars for them DrawCharBars( ); UpdateCharRegionHelpText( ); //} } } } // update the status of the contract box void UpDateStatusOfContractBox( void ) { if( fShowContractMenu == TRUE ) { ForceUpDateOfBox( ghContractBox ); if( ( gCharactersList[ bSelectedInfoChar ].usSolID->stats.bLife == 0 )||( gCharactersList[bSelectedInfoChar].usSolID->bAssignment == ASSIGNMENT_POW ) ) { ForceUpDateOfBox( ghRemoveMercAssignBox ); } } return; } void DestroyTheItemInCursor( ) { // actually destroy this item // End Item pickup MAPEndItemPointer( ); gpItemPointer = NULL; } void TrashItemMessageBoxCallBack( UINT8 bExitValue ) { if( bExitValue == MSG_BOX_RETURN_YES ) { // find the item and get rid of it DestroyTheItemInCursor( ); // reset cursor MSYS_ChangeRegionCursor( &gSMPanelRegion , CURSOR_NORMAL ); SetCurrentCursorFromDatabase( CURSOR_NORMAL ); HandleButtonStatesWhileMapInventoryActive( ); } } void TrashCanBtnCallback( MOUSE_REGION *pRegion, INT32 iReason) { if (iReason & MSYS_CALLBACK_REASON_LBUTTON_UP) { if( IsMapScreenHelpTextUp() ) { // stop mapscreen text StopMapScreenHelpText( ); return; } // check if an item is in the cursor, if so, warn player if( gpItemPointer != NULL ) { // set up for mapscreen Assert(! gpItemPointer->ubMission); //if( gpItemPointer->ubMission ) //{ DoMapMessageBox( MSG_BOX_BASIC_STYLE, pTrashItemText[ 1 ], MAP_SCREEN, MSG_BOX_FLAG_YESNO, TrashItemMessageBoxCallBack ); //} //else //{ // DoMapMessageBox( MSG_BOX_BASIC_STYLE, pTrashItemText[ 0 ], MAP_SCREEN, MSG_BOX_FLAG_YESNO, TrashItemMessageBoxCallBack ); //} } } } void TrashCanMoveCallback( MOUSE_REGION *pRegion, INT32 iReason) { if (iReason & MSYS_CALLBACK_REASON_GAIN_MOUSE ) { if( gMPanelRegion.Cursor == EXTERN_CURSOR ) { fShowTrashCanHighLight = TRUE; } } else if( iReason & MSYS_CALLBACK_REASON_LOST_MOUSE ) { fShowTrashCanHighLight = FALSE; } } void MapInvDoneButtonfastHelpCall( ) { SetPendingNewScreen( LAPTOP_SCREEN ); } void UpdateStatusOfMapSortButtons( void ) { INT32 iCounter = 0; static BOOLEAN fShownLastTime = FALSE; if( ( gfPreBattleInterfaceActive ) || fShowInventoryFlag ) { if ( fShownLastTime ) { for( iCounter = 0; iCounter < MAX_SORT_METHODS; iCounter++ ) { HideButton( giMapSortButton[ iCounter ] ); } // OJW - 20090210 - hide MP buttons here if (is_networked) { for( iCounter = 0; iCounter < MAX_MP_BUTTONS; iCounter++ ) { HideButton( giMapMPButton[ iCounter ] ); } } if ( gfPreBattleInterfaceActive ) { HideButton( giCharInfoButton[ 0 ] ); HideButton( giCharInfoButton[ 1 ] ); } fShownLastTime = FALSE; } } else { if ( !fShownLastTime ) { for( iCounter = 0; iCounter < MAX_SORT_METHODS; iCounter++ ) { ShowButton( giMapSortButton[ iCounter ] ); } // OJW - 20090210 - show MP buttons here if (is_networked) { for( iCounter = 0; iCounter < MAX_MP_BUTTONS; iCounter++ ) { ShowButton( giMapMPButton[ iCounter ] ); } } ShowButton( giCharInfoButton[ 0 ] ); ShowButton( giCharInfoButton[ 1 ] ); fShownLastTime = TRUE; } } } INT16 GetLastValidCharacterInTeamPanelList( void ) { INT16 iCounter = 0, iValue = 0; SOLDIERTYPE* pSoldier; SOLDIERTYPE* pSelectedSoldier = gCharactersList[bSelectedInfoChar].usSolID; // run through the list and find the last valid guy in the list for( iCounter = 0; iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; iCounter++ ) { if( gCharactersList[ iCounter ].fValid == TRUE ) { pSoldier = gCharactersList[iCounter].usSolID; if(pSoldier->stats.bLife >= OKLIFE ) { if( fShowMapInventoryPool ) { if( pSoldier->sSectorX == sSelMapX && pSoldier->sSectorY == sSelMapY && pSoldier->bSectorZ == ( INT8 )( iCurrentMapSectorZ ) ) { iValue = iCounter; } } else { if( fShowInventoryFlag && ( gMPanelRegion.Cursor == EXTERN_CURSOR ) ) { if( bSelectedInfoChar != -1 ) { if( gCharactersList[ bSelectedInfoChar ].fValid == TRUE ) { if( pSoldier->sSectorX == pSelectedSoldier->sSectorX && pSoldier->sSectorY == pSelectedSoldier->sSectorY && pSoldier->bSectorZ == pSelectedSoldier->bSectorZ ) { iValue = iCounter; } } } } else { iValue = iCounter; } } } } } // return the character return( iValue ); } /* // NB These functions weren't being called anywhere! Use GoToNextCharacterInList etc instead INT8 GetPrevValidCharacterInTeamPanelList( INT8 bCurrentIndex ) { INT8 iCounter = bCurrentIndex, iValue = 0; // run through the list and find the last valid guy in the list for( iCounter = bCurrentIndex; iCounter > 0; iCounter-- ) { if( gCharactersList[ iCounter ].fValid == TRUE ) { if( ( gCharactersList[ iCounter ].usSolID->bLife >= OKLIFE ) ) { if( fShowMapInventoryPool ) { if( gCharactersList[ iCounter ].usSolID->sSectorX == sSelMapX && gCharactersList[ iCounter ].usSolID->sSectorY == sSelMapY && gCharactersList[ iCounter ].usSolID->bSectorZ == ( INT8 )( iCurrentMapSectorZ ) ) { iValue = iCounter; } } else { if( fShowInventoryFlag && ( gMPanelRegion.Cursor == EXTERN_CURSOR ) ) { if( bSelectedInfoChar != -1 ) { if( gCharactersList[ bSelectedInfoChar ].fValid == TRUE ) { if( gCharactersList[ iCounter ].usSolID->sSectorX == gCharactersList[ bSelectedInfoChar ].usSolID->sSectorX && gCharactersList[ iCounter ].usSolID->sSectorY == gCharactersList[ bSelectedInfoChar ].usSolID->sSectorY && gCharactersList[ iCounter ].usSolID->bSectorZ ==gCharactersList[ bSelectedInfoChar ].usSolID->bSectorZ ) { iValue = iCounter; iCounter = 0; } } } } else { iValue = iCounter; } } } } } // return the character return( iValue ); } INT8 GetNextValidCharacterInTeamPanelList( INT8 bCurrentIndex ) { INT8 iCounter = bCurrentIndex, iValue = 0; // run through the list and find the last valid guy in the list for( iCounter = bCurrentIndex; iCounter < CODE_MAXIMUM_NUMBER_OF_PLAYER_SLOTS; iCounter++ ) { if( gCharactersList[ iCounter ].fValid == TRUE ) { if( ( gCharactersList[ iCounter ].usSolID->bLife >= OKLIFE ) ) { if( fShowMapInventoryPool ) { if( gCharactersList[ iCounter ].usSolID->sSectorX == sSelMapX && gCharactersList[ iCounter ].usSolID->sSectorY == sSelMapY && gCharactersList[ iCounter ].usSolID->bSectorZ == ( INT8 )( iCurrentMapSectorZ ) ) { iValue = iCounter; } } else { if( fShowInventoryFlag && ( gMPanelRegion.Cursor == EXTERN_CURSOR ) ) { if( bSelectedInfoChar != -1 ) { if( gCharactersList[ bSelectedInfoChar ].fValid == TRUE ) { if( gCharactersList[ iCounter ].usSolID->sSectorX == gCharactersList[ bSelectedInfoChar ].usSolID->sSectorX && gCharactersList[ iCounter ].usSolID->sSectorY == gCharactersList[ bSelectedInfoChar ].usSolID->sSectorY && gCharactersList[ iCounter ].usSolID->bSectorZ ==gCharactersList[ bSelectedInfoChar ].usSolID->bSectorZ ) { iValue = iCounter; } } } } else { iValue = iCounter; } } } } } // return the character return( iValue ); } */ void CreateDestroyTrashCanRegion( void ) { static BOOLEAN fCreated = FALSE; if( fShowInventoryFlag && ( fCreated == FALSE ) ) { fCreated = TRUE; // trash can MSYS_DefineRegion( &gTrashCanRegion, UI_CHARINV.Button.Trashcan.x, UI_CHARINV.Button.Trashcan.y, UI_CHARINV.Button.Trashcan.x + UI_CHARINV.Button.Trashcan.width, UI_CHARINV.Button.Trashcan.y + UI_CHARINV.Button.Trashcan.height, MSYS_PRIORITY_HIGHEST - 4 , MSYS_NO_CURSOR, TrashCanMoveCallback, TrashCanBtnCallback ); // region for detailed merc weight MSYS_DefineRegion(&gMapMercWeightRegion, UI_CHARINV.Text.Weight.iX + 2, UI_CHARINV.Text.Weight.iY, UI_CHARINV.Text.Weight.iX + 28, UI_CHARINV.Text.Weight.iY + 10, MSYS_PRIORITY_HIGH, MSYS_NO_CURSOR, MSYS_NO_CALLBACK, NULL ); // region for detailed merc camo MSYS_DefineRegion(&gMapMercCamoRegion, UI_CHARINV.Text.Camo.iX + 2, UI_CHARINV.Text.Camo.iY, UI_CHARINV.Text.Camo.iX + 28, UI_CHARINV.Text.Camo.iY + 10, MSYS_PRIORITY_HIGH, MSYS_NO_CURSOR, MSYS_NO_CALLBACK, MAPInvMoveCamoCallback ); // done inventory button define giMapInvButtonDoneImage = LoadButtonImage( "INTERFACE\\done_button2.sti" ,-1,0,-1,1,-1 ); giMapInvDoneButton = QuickCreateButton( giMapInvButtonDoneImage, UI_CHARINV.Button.Done.iX, UI_CHARINV.Button.Done.iY, BUTTON_TOGGLE, MSYS_PRIORITY_HIGHEST - 1, ( GUI_CALLBACK )BtnGenericMouseMoveButtonCallback, ( GUI_CALLBACK)DoneInventoryMapBtnCallback ); SetButtonFastHelpText( giMapInvDoneButton ,pMiscMapScreenMouseRegionHelpText[ 2 ] ); SetRegionFastHelpText( &gTrashCanRegion, pMiscMapScreenMouseRegionHelpText[ 1 ] ); InitMapKeyRingInterface( KeyRingItemPanelButtonCallback ); /* giMapInvNextImage= LoadButtonImage( "INTERFACE\\inventory_buttons.sti" ,-1,20,-1,22,-1 ); giMapInvNext= QuickCreateButton( giMapInvNextImage, ( 2 ), ( 79 ) , BUTTON_TOGGLE, MSYS_PRIORITY_HIGHEST - 1, ( GUI_CALLBACK )BtnGenericMouseMoveButtonCallback, ( GUI_CALLBACK)NextInventoryMapBtnCallback ); giMapInvPrevImage= LoadButtonImage( "INTERFACE\\inventory_buttons.sti" ,-1,21,-1,23,-1 ); giMapInvPrev= QuickCreateButton( giMapInvPrevImage, ( 30 ) , ( 79 ), BUTTON_TOGGLE, MSYS_PRIORITY_HIGHEST - 1, ( GUI_CALLBACK )BtnGenericMouseMoveButtonCallback, ( GUI_CALLBACK)PrevInventoryMapBtnCallback ); */ // reset the compatable item array at this point ResetCompatibleItemArray( ); } else if( ( fShowInventoryFlag == FALSE ) && ( fCreated == TRUE ) ) { // trash can region fCreated = FALSE; MSYS_RemoveRegion( &gTrashCanRegion ); MSYS_RemoveRegion(&gMapMercWeightRegion); MSYS_RemoveRegion(&gMapMercCamoRegion); // map inv done button RemoveButton( giMapInvDoneButton ); // get rid of button image UnloadButtonImage( giMapInvButtonDoneImage ); ShutdownKeyRingInterface( ); ShutdownInventoryInterface(); if( fShowDescriptionFlag == TRUE ) { // kill description DeleteItemDescriptionBox( ); } } } void InvmaskRegionBtnCallBack( MOUSE_REGION *pRegion, INT32 iReason ) { // CJC, December 15 1998: do NOTHING for clicks here } void DoneInventoryMapBtnCallback( GUI_BUTTON *btn, INT32 reason ) { // prevent inventory from being closed while stack popup up! 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); if ( gMPanelRegion.Cursor != EXTERN_CURSOR && !InItemStackPopup() ) { fEndShowInventoryFlag = TRUE; } } } } void StartConfirmMapMoveMode( INT16 sMapY ) { UINT8 ubPosition = ( sMapY < 8 ) ? MSG_MAP_UI_POSITION_LOWER : MSG_MAP_UI_POSITION_UPPER; // tell player what to do - to click again to confirm move MapScreenMessage( FONT_MCOLOR_LTYELLOW, ubPosition, pMapPlotStrings[ 0 ] ); gfInConfirmMapMoveMode = TRUE; } void EndConfirmMapMoveMode( void ) { CancelMapUIMessage( ); gfInConfirmMapMoveMode = FALSE; } void CancelMapUIMessage( void ) { // and kill the message overlay EndUIMessage( ); fMapPanelDirty = TRUE; } // automatically turns off mapscreen ui overlay messages when appropriate void MonitorMapUIMessage( void ) { // if there is a map UI message being displayed if( giUIMessageOverlay != -1 ) { // and if we're not in the middle of the "confirm move" sequence // if( !gfInConfirmMapMoveMode || bSelectedDestChar == -1 ) { // and we've now exceed its period of maximum persistance (without user input) if ( ( GetJA2Clock( ) - guiUIMessageTime ) > guiUIMessageTimeDelay ) { // then cancel the message now CancelMapUIMessage( ); } } } } void HandlePreBattleInterfaceWithInventoryPanelUp( void ) { if( ( gfPreBattleInterfaceActive == TRUE ) && ( fShowInventoryFlag == TRUE ) ) { if( fShowDescriptionFlag == TRUE ) { // kill description DeleteItemDescriptionBox( ); } // kill inventory panel fShowInventoryFlag = FALSE; if (isWidescreenUI()) { DestroyMapCharInvIOregions(); } else { CreateDestroyMapInvButton(); } } } // this puts anyone who is on NO_ASSIGNMENT onto a free squad void UpdateBadAssignments( void ) { UINT32 iCounter; for( iCounter = 0; iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; iCounter++ ) { if( gCharactersList[ iCounter ].fValid == TRUE ) { CheckIfSoldierUnassigned( gCharactersList[ iCounter ].usSolID ); } } return; } void InterruptTimeForMenus( void ) { if( ( fShowAssignmentMenu == TRUE )||( fShowContractMenu == TRUE ) ) { InterruptTime( ); PauseTimeForInterupt( ); } else if( fOneFrame ) { InterruptTime( ); PauseTimeForInterupt( ); } return; } void HandleContractTimeFlashForMercThatIsAboutLeave( void ) { INT32 iCurrentTime; // grab the current time iCurrentTime = GetJA2Clock(); // only bother checking once flash interval has elapsed if( ( iCurrentTime - giFlashContractBaseTime ) >= DELAY_PER_FLASH_FOR_DEPARTING_PERSONNEL ) { // update timer so that we only run check so often giFlashContractBaseTime = iCurrentTime; fFlashContractFlag = !fFlashContractFlag; // don't redraw unless we have to! if ( AnyMercsLeavingRealSoon() ) { // redraw character list fDrawCharacterList = TRUE; } } } BOOLEAN AnyMercsLeavingRealSoon() { UINT32 uiCounter = 0; UINT32 uiTimeInMin = GetWorldTotalMin(); BOOLEAN fFoundOne = FALSE; for( uiCounter = 0; uiCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; uiCounter++ ) { if( gCharactersList[ uiCounter ].fValid == TRUE ) { if( ( gCharactersList[uiCounter].usSolID->iEndofContractTime - uiTimeInMin ) <= MINS_TO_FLASH_CONTRACT_TIME ) { fFoundOne = TRUE; break; } } } return( fFoundOne ); } void HandleRemovalOfPreLoadedMapGraphics( void ) { if( fPreLoadedMapGraphics == TRUE ) { DeleteMapBottomGraphics( ); DeleteVideoObjectFromIndex( guiMAPCURSORS ); // HEADROCK HAM 5: New pathing arrows may replace the above eventually, but for now a separate variable will do. DeleteVideoObjectFromIndex(guiMapPathingArrows); DeleteVideoObjectFromIndex( guiSleepIcon ); //DeleteVideoObjectFromIndex(guiMAPBORDER); DeleteVideoObjectFromIndex(guiCHARLIST); //DeleteVideoObjectFromIndex(guiCORNERADDONS); //DeleteVideoObjectFromIndex(guiMAPCORNER); // DeleteVideoObjectFromIndex(guiPOPUPBORDERS); DeleteVideoObjectFromIndex(guiCHARINFO); DeleteVideoObjectFromIndex(guiCHARICONS); DeleteVideoObjectFromIndex( guiINTEL ); DeleteVideoObjectFromIndex(guiCROSS); DeleteVideoSurfaceFromIndex(guiBIGMAP); DeleteVideoObjectFromIndex(guiSubLevel1); DeleteVideoObjectFromIndex(guiSubLevel2); DeleteVideoObjectFromIndex(guiSubLevel3); // DeleteVideoSurfaceFromIndex(guiPOPUPTEX); DeleteVideoObjectFromIndex(guiSAMICON); DeleteVideoObjectFromIndex(guiMAPINV); DeleteVideoObjectFromIndex(guiMapInvSecondHandBlockout); DeleteVideoObjectFromIndex(guiULICONS); DeleteVideoObjectFromIndex(guiORTAICON); DeleteVideoObjectFromIndex(guiTIXAICON); DeleteVideoObjectFromIndex( guiCHARBETWEENSECTORICONS ); // HEADROCK HAM 5.1: Enemies between sectors arrows DeleteVideoObjectFromIndex( guiENEMYBETWEENSECTORICONS ); DeleteVideoObjectFromIndex( guiLEVELMARKER ); DeleteVideoObjectFromIndex( guiMapBorderEtaPopUp ); DeleteVideoObjectFromIndex( guiSecItemHiddenVO ); DeleteVideoObjectFromIndex( guiSelectedCharArrow ); DeleteVideoObjectFromIndex( guiMapBorderHeliSectors ); DeleteVideoObjectFromIndex( guiMapBorderHeliSectorsAlternate ); DeleteVideoObjectFromIndex( guiHelicopterIcon ); DeleteVideoObjectFromIndex( guiEnemyHelicopterIcon ); DeleteVideoObjectFromIndex( guiMINEICON ); DeleteVideoObjectFromIndex( guiSectorLocatorGraphicID ); //Kris: Remove the email icons. DeleteVideoObjectFromIndex( guiNewMailIcons ); DeleteVideoObjectFromIndex( guiBULLSEYE ); //----------- Legion 2 for ( INT32 iCounter2 = 1; iCounter2 < NUM_TOWNS; ++iCounter2 ) { //if ( gfDrawHiddenTown[iCounter2] == TRUE ) DeleteVideoObjectFromIndex(guiIcon2[iCounter2]); } //------- // remove the graphic for the militia pop up box RemoveMilitiaPopUpBox( ); // remove inventory pool graphic RemoveInventoryPoolGraphic( ); // get rid of border stuff DeleteMapBorderGraphics( ); } } BOOLEAN CharacterIsInLoadedSectorAndWantsToMoveInventoryButIsNotAllowed( INT16 bCharId ) { // invalid char id if( bCharId == -1 ) { return( FALSE ); } // valid char? if( gCharactersList[ bCharId ].fValid == FALSE ) { return( FALSE ); } // get the soldier id SoldierID usSoldierId = gCharactersList[ bCharId ].usSolID; // char is in loaded sector if( usSoldierId->sSectorX != gWorldSectorX || usSoldierId->sSectorY != gWorldSectorY || usSoldierId->bSectorZ != gbWorldSectorZ ) { return( FALSE ); } // not showing inventory? if( fShowInventoryFlag == FALSE ) { // nope return( FALSE ); } // picked something up? if( gMPanelRegion.Cursor != EXTERN_CURSOR ) { // nope return( FALSE ); } // only disallow when enemies in sector if ( !gTacticalStatus.fEnemyInSector ) { return( FALSE ); } return( TRUE ); } void UpdateTheStateOfTheNextPrevMapScreenCharacterButtons( void ) { if( gfPreBattleInterfaceActive ) { if( IsMapScreenHelpTextUp() ) { // stop mapscreen text StopMapScreenHelpText( ); } } else if( bSelectedInfoChar == -1 ) { DisableButton( giCharInfoButton[ 0 ] ); DisableButton( giCharInfoButton[ 1 ] ); DisableButton( giMapContractButton ); } /* ARM: Commented out at KM's request, it won't reenabled them when coming back from PBI, on Feb. 22, 99 else if ( fShowInventoryFlag == FALSE ) // make sure that we are in fact showing the mapscreen inventory { return; } */ else { // standard checks if ( ( GetNumberOfPeopleInCharacterList( ) < 2 ) || ( CharacterIsInLoadedSectorAndWantsToMoveInventoryButIsNotAllowed( bSelectedInfoChar ) ) || ( CharacterIsInTransitAndHasItemPickedUp( bSelectedInfoChar ) ) || ( fShowDescriptionFlag ) ) { DisableButton( giCharInfoButton[ 0 ] ); DisableButton( giCharInfoButton[ 1 ] ); } else { EnableButton( giCharInfoButton[ 0 ] ); EnableButton( giCharInfoButton[ 1 ] ); } } } void PrevInventoryMapBtnCallback( 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); fResetMapCoords = TRUE; GoToPrevCharacterInList( ); UpdateMercBodyRegionHelpText(); } } } void NextInventoryMapBtnCallback( 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); fResetMapCoords = TRUE; GoToNextCharacterInList( ); UpdateMercBodyRegionHelpText( ); } } } void CreateDestroyMapCharacterScrollButtons( void ) { static BOOLEAN fCreated = FALSE; if( ( fInMapMode == TRUE ) && ( fCreated == FALSE ) ) { // set the button image giCharInfoButtonImage[ 0 ]= LoadButtonImage( "INTERFACE\\map_screen_bottom_arrows.sti" ,11,4,-1,6,-1 ); // set the button value giCharInfoButton[ 0 ] = QuickCreateButton( giCharInfoButtonImage[ 0 ], UI_CHARPANEL.Button.Up.iX, UI_CHARPANEL.Button.Up.iY, BUTTON_TOGGLE, MSYS_PRIORITY_HIGHEST - 5, BtnGenericMouseMoveButtonCallback, (GUI_CALLBACK)PrevInventoryMapBtnCallback ); // set the button image giCharInfoButtonImage[ 1 ]= LoadButtonImage( "INTERFACE\\map_screen_bottom_arrows.sti" ,12,5,-1,7,-1 ); // set the button value giCharInfoButton[ 1 ] = QuickCreateButton( giCharInfoButtonImage[ 1 ], UI_CHARPANEL.Button.Down.iX, UI_CHARPANEL.Button.Down.iY, BUTTON_TOGGLE, MSYS_PRIORITY_HIGHEST - 5, BtnGenericMouseMoveButtonCallback, (GUI_CALLBACK)NextInventoryMapBtnCallback ); SetButtonFastHelpText( giCharInfoButton[ 0 ], pMapScreenPrevNextCharButtonHelpText[ 0 ] ); SetButtonFastHelpText( giCharInfoButton[ 1 ], pMapScreenPrevNextCharButtonHelpText[ 1 ] ); fCreated = TRUE; } else if( ( ( fInMapMode == FALSE ) ) && ( fCreated == TRUE ) ) { UnloadButtonImage( giCharInfoButtonImage[ 0 ] ); UnloadButtonImage( giCharInfoButtonImage[ 1 ] ); RemoveButton( giCharInfoButton[ 0 ]); RemoveButton( giCharInfoButton[ 1 ]); fCreated = FALSE; } } void TellPlayerWhyHeCantCompressTime( void ) { // if we're locked into paused time compression by some event that enforces that if ( PauseStateLocked() ) { #ifdef JA2BETAVERSION ScreenMsg( FONT_MCOLOR_RED, MSG_BETAVERSION, L"(BETA) Can't compress time, pause state locked (reason %d). OK unless permanent.", guiLockPauseStateLastReasonId ); ScreenMsg( FONT_MCOLOR_RED, MSG_BETAVERSION, L"(BETA) If permanent, take screenshot now, send with *previous* save & describe what happened since."); #endif } #ifdef JA2UB else if( DoesPlayerHaveNoMercsHiredAndJerryHasntSaidQuoteYet() ) { JerryMiloTalk( MILO_QUOTE__PLAYER_HAS_NO_MERCS ); DoMapMessageBox( MSG_BOX_BASIC_STYLE, pMapScreenJustStartedHelpText[ 0 ], MAP_SCREEN, MSG_BOX_FLAG_OK, MapScreenDefaultOkBoxCallback ); } #endif else if( gfAtLeastOneMercWasHired == FALSE ) { // no mercs hired, ever DoMapMessageBox( MSG_BOX_BASIC_STYLE, pMapScreenJustStartedHelpText[ 0 ], MAP_SCREEN, MSG_BOX_FLAG_OK, MapScreenDefaultOkBoxCallback ); } // WANNE - MP: It is forbidden to compress time in multiplayer else if (is_networked) { ScreenMsg( FONT_LTGREEN, MSG_MPSYSTEM, MPClientMessage[65]); } else if ( !AnyUsableRealMercenariesOnTeam() ) { // no usable mercs left on team DoMapMessageBox( MSG_BOX_BASIC_STYLE, pMapErrorString[ 39 ], MAP_SCREEN, MSG_BOX_FLAG_OK, MapScreenDefaultOkBoxCallback ); } else if ( ActiveTimedBombExists() ) { // can't time compress when a bomb is about to go off! DoMapMessageBox( MSG_BOX_BASIC_STYLE, gzLateLocalizedString[ 2 ], MAP_SCREEN, MSG_BOX_FLAG_OK, MapScreenDefaultOkBoxCallback ); } else if ( gfContractRenewalSquenceOn ) { #ifdef JA2BETAVERSION ScreenMsg( FONT_MCOLOR_RED, MSG_BETAVERSION, L"(BETA) Can't compress time while contract renewal sequence is on."); #endif } else if( fDisableMapInterfaceDueToBattle ) { #ifdef JA2BETAVERSION ScreenMsg( FONT_MCOLOR_RED, MSG_BETAVERSION, L"(BETA) Can't compress time while disabled due to battle."); #endif } else if( fDisableDueToBattleRoster ) { #ifdef JA2BETAVERSION ScreenMsg( FONT_MCOLOR_RED, MSG_BETAVERSION, L"(BETA) Can't compress time while in battle roster."); #endif } else if ( fMapInventoryItem ) { #ifdef JA2BETAVERSION ScreenMsg( FONT_MCOLOR_RED, MSG_BETAVERSION, L"(BETA) Can't compress time while still holding an inventory item."); #endif } else if( fShowMapInventoryPool ) { DoMapMessageBox( MSG_BOX_BASIC_STYLE, gzLateLocalizedString[ 55 ], MAP_SCREEN, MSG_BOX_FLAG_OK, MapScreenDefaultOkBoxCallback ); } #ifdef JA2UB //JA25 UB else if( !WillJerryMiloAllowThePlayerToCompressTimeAtBeginingOfGame() ) { // TODO.RW: JA2UB //Have jerry say why the player cant compress time HaveJerrySayWhyPlayerCantTimeCompressAtBeginningOfGame(); } #endif // ARM: THIS TEST SHOULD BE THE LAST ONE, BECAUSE IT ACTUALLY RESULTS IN SOMETHING HAPPENING NOW. // KM: Except if we are in a creature lair and haven't loaded the sector yet (no battle yet) else if( gTacticalStatus.uiFlags & INCOMBAT || gTacticalStatus.fEnemyInSector ) { if( OnlyHostileCivsInSector() ) { CHAR16 str[ 256 ]; CHAR16 pSectorString[ 128 ]; GetSectorIDString( gWorldSectorX, gWorldSectorY, gbWorldSectorZ, pSectorString, TRUE ); swprintf( str, gzLateLocalizedString[ 27 ], pSectorString ); DoMapMessageBox( MSG_BOX_BASIC_STYLE, str, MAP_SCREEN, MSG_BOX_FLAG_OK, MapScreenDefaultOkBoxCallback ); } else { //The NEW non-persistant PBI is used instead of a dialog box explaining why we can't compress time. InitPreBattleInterface( NULL, FALSE ); } } else if( PlayerGroupIsInACreatureInfestedMine() ) { DoMapMessageBox( MSG_BOX_BASIC_STYLE, gzLateLocalizedString[ 28 ], MAP_SCREEN, MSG_BOX_FLAG_OK, MapScreenDefaultOkBoxCallback ); } else if ( HostileCiviliansPresent() || HostileBloodcatsPresent() ) { DoMapMessageBox( MSG_BOX_BASIC_STYLE, gzLateLocalizedString[ 65 ], MAP_SCREEN, MSG_BOX_FLAG_OK, MapScreenDefaultOkBoxCallback ); } } void MapScreenDefaultOkBoxCallback( UINT8 bExitValue ) { // yes, load the game if( bExitValue == MSG_BOX_RETURN_OK ) { fMapPanelDirty = TRUE; fTeamPanelDirty = TRUE; fCharacterInfoPanelDirty = TRUE; } return; } void MapSortBtnCallback( GUI_BUTTON *btn, INT32 reason ) { INT32 iValue = 0; // grab the button index value for the sort buttons iValue = MSYS_GetBtnUserData( btn, 0 ); if(reason & MSYS_CALLBACK_REASON_LBUTTON_DWN ) { if( IsMapScreenHelpTextUp() ) { // stop mapscreen text StopMapScreenHelpText( ); return; } btn->uiFlags|=(BUTTON_CLICKED_ON); } else if(reason & MSYS_CALLBACK_REASON_LBUTTON_UP ) { if (btn->uiFlags & BUTTON_CLICKED_ON) { btn->uiFlags &= ~(BUTTON_CLICKED_ON); ChangeCharacterListSortMethod( iValue ); } } } void AddTeamPanelSortButtonsForMapScreen( void ) { INT32 iCounter = 0; SGPFILENAME filename; INT32 iImageIndex[ MAX_SORT_METHODS ] = { 0, 1, 5, 2, 3, 4 }; // sleep image is out or order (last) GetMLGFilename( filename, MLG_GOLDPIECEBUTTONS ); for( iCounter = 0; iCounter < MAX_SORT_METHODS; iCounter++ ) { giMapSortButtonImage[ iCounter ] = LoadButtonImage( filename, -1, iImageIndex[ iCounter ] , -1, iImageIndex[ iCounter ] + 6 , -1 ); giMapSortButton[ iCounter ]= QuickCreateButton( giMapSortButtonImage[ iCounter ], ( INT16 )(UI_CHARLIST.Title.iX + gMapSortButtons[ iCounter ].iX ), ( INT16 )(UI_CHARLIST.Title.iY + gMapSortButtons[ iCounter ].iY ), BUTTON_TOGGLE, MSYS_PRIORITY_HIGHEST - 5, (GUI_CALLBACK)BtnGenericMouseMoveButtonCallback, (GUI_CALLBACK)MapSortBtnCallback ); MSYS_SetBtnUserData(giMapSortButton[ iCounter ], 0, iCounter ); SetButtonFastHelpText( giMapSortButton[ iCounter ], wMapScreenSortButtonHelpText[ iCounter ] ); } return; } void AddMPButtonsForMapScreen( void ) { INT32 iCounter = 0; SGPFILENAME filename; INT32 iImageIndex[ MAX_MP_BUTTONS+1 ] = { 0, 1, 3, 5 , 7 }; // sleep image is out or order (last) INT32 iPressedIndex[ MAX_MP_BUTTONS+1 ] = { 0 , 2 , 4 , 6 , 8 }; GetMLGFilename( filename, MLG_MP_GOLDPIECEBUTTONS ); for( iCounter = 0; iCounter < MAX_MP_BUTTONS+1; iCounter++ ) { giMapMPButtonImage[ iCounter ] = LoadButtonImage( filename, -1, iImageIndex[ iCounter ] , -1, iPressedIndex[ iCounter ] , -1 ); if (iCounter < MAX_MP_BUTTONS) { UINT16 xButtonPos = gMapMPButtonsX[ iCounter ] + UI_CHARLIST.Region.x; // buttonmake giMapMPButton[ iCounter ]= QuickCreateButton( giMapMPButtonImage[ iCounter ], ( INT16 )( xButtonPos ), ( INT16 )( MP_BTN_Y ), BUTTON_TOGGLE, MSYS_PRIORITY_HIGHEST - 5, (GUI_CALLBACK)BtnGenericMouseMoveButtonCallback, (GUI_CALLBACK)MPReadyButtonCallback ); // so we can tell which button was clicked MSYS_SetBtnUserData(giMapMPButton[ iCounter ], 0, iCounter ); } //SetButtonFastHelpText( giMapSortButton[ iCounter ], wMapScreenSortButtonHelpText[ iCounter ] ); } if ((is_server || is_host) && !allowlaptop) { // Server has 'Start game' button showing first if the game hasnt started SpecifyButtonImage( giMapMPButton [3] , giMapMPButtonImage [4] ); } return; } void SortListOfMercsInTeamPanel( BOOLEAN fRetainSelectedMercs, BOOLEAN fReverse ) { INT32 iCounter = 0, iCounterA = 0; INT16 sEndSectorA, sEndSectorB; INT32 iExpiryTime, iExpiryTimeA; SoldierID uiID, uiIDA; SOLDIERTYPE *pSelectedSoldier[ CODE_MAXIMUM_NUMBER_OF_PLAYER_SLOTS ]; SOLDIERTYPE *pCurrentSoldier = NULL; SOLDIERTYPE *pPreviousSelectedInfoChar = NULL; if ( fRetainSelectedMercs ) { // if we have anyone valid selected if ( ( bSelectedInfoChar != -1 ) && ( gCharactersList[ bSelectedInfoChar ].fValid ) ) { pPreviousSelectedInfoChar = gCharactersList[ bSelectedInfoChar ].usSolID; } for( iCounter = 0; iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; iCounter++ ) { // set current entry to null pSelectedSoldier[ iCounter ] = NULL; // is this entry even valid if( gCharactersList[ iCounter ].fValid == FALSE ) { continue; } // get soldier assoc. with entry pCurrentSoldier = gCharactersList[ iCounter ].usSolID; // check if soldier is active if( pCurrentSoldier->bActive == FALSE ) { continue; } // are they selected?... if( fSelectedListOfMercsForMapScreen[ iCounter ] == TRUE ) { // yes, store pointer to them pSelectedSoldier[ iCounter ] = pCurrentSoldier; } } } // do the sort for( iCounter = 1; iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS ; iCounter++ ) { // have we gone too far if( gCharactersList[ iCounter ].fValid == FALSE ) { break; } switch( giSortStateForMapScreenList ) { case( 0 ): // by name for( iCounterA = 0; iCounterA < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; iCounterA++ ) { if( gCharactersList[ iCounterA ].fValid == FALSE ) { break; } //if( ( wcscmp( gCharactersList[ iCounterA ].usSolID->name, gCharactersList[ iCounter ].usSolID->name ) > 0 ) && ( iCounterA < iCounter ) ) if( iCounterA < iCounter ) { if((fReverse && ( wcscmp( gCharactersList[ iCounterA ].usSolID->name, gCharactersList[ iCounter ].usSolID->name ) < 0 )) || (!fReverse && ( wcscmp( gCharactersList[ iCounterA ].usSolID->name, gCharactersList[ iCounter ].usSolID->name ) > 0 ))) SwapCharactersInList( iCounter, iCounterA ); } } break; case( 1 ): // by assignment for( iCounterA = 0; iCounterA < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; iCounterA++ ) { if( gCharactersList[ iCounterA ].fValid == FALSE ) { break; } if( !fReverse && ( gCharactersList[ iCounterA ].usSolID->bAssignment > gCharactersList[ iCounter ].usSolID->bAssignment ) && ( iCounterA < iCounter ) ) { SwapCharactersInList( iCounter, iCounterA ); } else if( fReverse && ( gCharactersList[ iCounterA ].usSolID->bAssignment < gCharactersList[ iCounter ].usSolID->bAssignment ) && ( iCounterA < iCounter ) ) { SwapCharactersInList( iCounter, iCounterA ); } else if( ( gCharactersList[ iCounterA ].usSolID->bAssignment == gCharactersList[ iCounter ].usSolID->bAssignment ) && ( iCounterA < iCounter ) ) { // same assignment // if it's in a vehicle if( gCharactersList[ iCounterA ].usSolID->bAssignment == VEHICLE ) { // then also compare vehicle IDs if( ( gCharactersList[ iCounterA ].usSolID->iVehicleId > gCharactersList[ iCounter ].usSolID->iVehicleId ) && ( iCounterA < iCounter ) ) { SwapCharactersInList( iCounter, iCounterA ); } } } } break; case( 2 ): // by sleep status for( iCounterA = 0; iCounterA < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; iCounterA++ ) { if( gCharactersList[ iCounterA ].fValid == FALSE ) { break; } if( !fReverse && ( gCharactersList[ iCounterA ].usSolID->flags.fMercAsleep == TRUE ) && ( gCharactersList[ iCounter ].usSolID->flags.fMercAsleep == FALSE ) && ( iCounterA < iCounter ) ) { SwapCharactersInList( iCounter, iCounterA ); } else if( fReverse && ( gCharactersList[ iCounterA ].usSolID->flags.fMercAsleep == FALSE ) && ( gCharactersList[ iCounter ].usSolID->flags.fMercAsleep == TRUE ) && ( iCounterA < iCounter ) ) { SwapCharactersInList( iCounter, iCounterA ); } } break; case( 3 ): //by location sEndSectorA = CalcLocationValueForChar( iCounter ); for( iCounterA = 0; iCounterA < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; iCounterA++ ) { if( gCharactersList[ iCounterA ].fValid == FALSE ) { break; } sEndSectorB = CalcLocationValueForChar( iCounterA ); if( !fReverse && ( sEndSectorB > sEndSectorA ) && ( iCounterA < iCounter ) ) { SwapCharactersInList( iCounter, iCounterA ); } else if( fReverse && ( sEndSectorB < sEndSectorA ) && ( iCounterA < iCounter ) ) { SwapCharactersInList( iCounter, iCounterA ); } } break; case( 4 ): // by destination sector if( GetLengthOfMercPath( gCharactersList[ iCounter ].usSolID ) == 0 ) { sEndSectorA = 9999; } else { sEndSectorA = GetLastSectorIdInCharactersPath( gCharactersList[ iCounter ].usSolID ); } for( iCounterA = 0; iCounterA < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; iCounterA++ ) { if( gCharactersList[ iCounterA ].fValid == FALSE ) { break; } if( GetLengthOfMercPath( gCharactersList[ iCounterA ].usSolID ) == 0 ) { sEndSectorB = 9999; } else { sEndSectorB = GetLastSectorIdInCharactersPath( gCharactersList[ iCounterA ].usSolID ); } if( !fReverse && ( sEndSectorB > sEndSectorA ) && ( iCounterA < iCounter ) ) { SwapCharactersInList( iCounter, iCounterA ); } else if( fReverse && ( sEndSectorB < sEndSectorA ) && ( iCounterA < iCounter ) ) { SwapCharactersInList( iCounter, iCounterA ); } } break; case( 5 ): iExpiryTime = GetContractExpiryTime( gCharactersList[ iCounter ].usSolID ); //by contract expiry for( iCounterA = 0; iCounterA < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; iCounterA++ ) { if( gCharactersList[ iCounterA ].fValid == FALSE ) { break; } iExpiryTimeA = GetContractExpiryTime( gCharactersList[ iCounterA ].usSolID ); if( !fReverse && ( iExpiryTimeA > iExpiryTime ) && ( iCounterA < iCounter ) ) { SwapCharactersInList( iCounter, iCounterA ); } else if( fReverse && ( iExpiryTimeA < iExpiryTime ) && ( iCounterA < iCounter ) ) { SwapCharactersInList( iCounter, iCounterA ); } } break; case( 6 ): uiID = gCharactersList[ iCounter ].usSolID->ubID; //by ubID for( iCounterA = 0; iCounterA < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; iCounterA++ ) { if( gCharactersList[ iCounterA ].fValid == FALSE) { break; } uiIDA = gCharactersList[ iCounterA ].usSolID->ubID; if( !fReverse && ( uiIDA > uiID ) && ( iCounterA < iCounter ) ) { SwapCharactersInList( iCounter, iCounterA ); } else if( fReverse && ( uiIDA < uiID ) && ( iCounterA < iCounter ) ) { SwapCharactersInList( iCounter, iCounterA ); } } break; default: Assert(0); return; } } if ( fRetainSelectedMercs ) { // select nobody & reset the selected list ChangeSelectedInfoChar( -1, TRUE ); // now select all the soldiers that were selected before for( iCounter = 0; iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; iCounter++ ) { if( pSelectedSoldier[ iCounter ] ) { for( iCounterA = 0; iCounterA < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; iCounterA++ ) { // is this entry even valid if( gCharactersList[ iCounterA ].fValid == FALSE ) { continue; } // grab current soldier pCurrentSoldier = gCharactersList[ iCounterA ].usSolID; // check if soldier is active if( pCurrentSoldier->bActive == FALSE ) { continue; } // this guy is selected if( pSelectedSoldier[ iCounter ] == pCurrentSoldier ) { SetEntryInSelectedCharacterList( iCounterA ); } // update who the currently selected info guy is if( pPreviousSelectedInfoChar == pCurrentSoldier ) { ChangeSelectedInfoChar( iCounterA, FALSE ); } } } } } else { // keep currently selected merc, but reset the selected list (which isn't saved/restored, that's why) ResetSelectedListForMapScreen( ); } // reset blinking animations SetAllAutoFacesInactive( ); // dirty the screen parts affected fTeamPanelDirty = TRUE; fCharacterInfoPanelDirty = TRUE; } void SwapCharactersInList( INT32 iCharA, INT32 iCharB ) { // swap SoldierID usTempSoldID = gCharactersList[ iCharA ].usSolID; gCharactersList[ iCharA ].usSolID = gCharactersList[ iCharB ].usSolID; gCharactersList[ iCharB ].usSolID = usTempSoldID; } void RemoveTeamPanelSortButtonsForMapScreen( void ) { INT32 iCounter = 0; for( iCounter = 0; iCounter < MAX_SORT_METHODS; iCounter++ ) { if (giMapSortButtonImage[iCounter] != -1) { UnloadButtonImage(giMapSortButtonImage[iCounter]); RemoveButton(giMapSortButton[iCounter]); giMapSortButtonImage[iCounter] = -1; giMapSortButton[iCounter] = -1; } } return; } void RemoveMPButtonsForMapScreen( void ) { INT32 iCounter = 0; for( iCounter = 0; iCounter < MAX_MP_BUTTONS+1; iCounter++ ) { UnloadButtonImage( giMapMPButtonImage[ iCounter ] ); if(iCounter < MAX_MP_BUTTONS) { RemoveButton( giMapMPButton[ iCounter ] ); giMapMPButton[ iCounter ] = -1; } giMapMPButtonImage[ iCounter ] = -1; } return; } void HandleCommonGlowTimer( ) { INT32 iCurrentTime = 0; // grab the current time iCurrentTime = GetJA2Clock(); // only bother checking once flash interval has elapsed if( ( iCurrentTime - giCommonGlowBaseTime ) >= GLOW_DELAY ) { // update timer so that we only run check so often giCommonGlowBaseTime = iCurrentTime; // set flag to trigger glow higlight updates gfGlowTimerExpired = TRUE; } else { gfGlowTimerExpired = FALSE; } } void HandleAssignmentsDoneAndAwaitingFurtherOrders( void ) { // run through list of grunts and handle awating further orders INT32 iCounter = 0, iCurrentTime = 0; SOLDIERTYPE *pSoldier = NULL; // update "nothing to do" flags if necessary if ( gfReEvaluateEveryonesNothingToDo ) { ReEvaluateEveryonesNothingToDo(); } // grab the current time iCurrentTime = GetJA2Clock(); // only bother checking once flash interval has elapsed if( ( iCurrentTime - giFlashAssignBaseTime ) >= ASSIGNMENT_DONE_FLASH_TIME ) { // update timer so that we only run check so often giFlashAssignBaseTime = iCurrentTime; for( iCounter = 0; iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; iCounter++ ) { if( gCharactersList[ iCounter ].fValid == FALSE ) { break; } pSoldier = gCharactersList[ iCounter ].usSolID; // toggle and redraw if flash was left ON even though the flag is OFF if( pSoldier->flags.fDoneAssignmentAndNothingToDoFlag || fFlashAssignDone ) { fFlashAssignDone = !fFlashAssignDone; fDrawCharacterList = TRUE; // only need to find one break; } } } } void DisplayIconsForMercsAsleep( void ) { // run throught he list of grunts to see who is asleep and who isn't HVOBJECT hHandle; INT32 iCounter; SOLDIERTYPE *pSoldier; // if we are in inventory if( fShowInventoryFlag == TRUE ) { return; } GetVideoObject(&hHandle, guiSleepIcon ); // marke strogg more mercs set max display lines to 18 for( iCounter = 0; iCounter < maxNumberOfMercVisibleInStrategyList; iCounter++ ) { if( gCharactersList[ iCounter + FIRSTmercTOdisplay ].fValid == TRUE ) { pSoldier = gCharactersList[ iCounter + FIRSTmercTOdisplay ].usSolID; if( pSoldier->bActive && pSoldier->flags.fMercAsleep && CanChangeSleepStatusForSoldier( pSoldier ) ) { BltVideoObject( guiSAVEBUFFER , hHandle, 0, UI_CHARLIST.xSleep + 2, ( INT16 )(UI_CHARLIST.y + (iCounter * ( Y_SIZE + 2 ) ) ) , VO_BLT_SRCTRANSPARENCY,NULL ); } } } return; } //Kris: Added this function to blink the email icon on top of the laptop button whenever we are in // mapscreen and we have new email to read. void CheckForAndRenderNewMailOverlay() { const UINT16 xOffset = 7; const UINT16 yOffset = 6; const auto x = MAP_BOTTOM_LAPTOP_X + xOffset; const auto y = MAP_BOTTOM_LAPTOP_Y + yOffset; if( fNewMailFlag ) { if( GetJA2Clock() % 1000 < 667 ) { if( ButtonList[ guiMapBottomExitButtons[ MAP_EXIT_TO_LAPTOP ] ]->uiFlags & BUTTON_CLICKED_ON ) { BltVideoObjectFromIndex(FRAME_BUFFER, guiNewMailIcons, 1, x + 2, y + 2, VO_BLT_SRCTRANSPARENCY, NULL); InvalidateRegion(x, y, x + 25 - xOffset, y + 15 - yOffset); } else { //button is up, so draw the icon normally BltVideoObjectFromIndex( FRAME_BUFFER, guiNewMailIcons, 0, x + 1, y + 1, VO_BLT_SRCTRANSPARENCY, NULL ); if( !(ButtonList[ guiMapBottomExitButtons[ MAP_EXIT_TO_LAPTOP ] ]->uiFlags & BUTTON_ENABLED ) ) { UINT32 uiDestPitchBYTES; UINT8 *pDestBuf; SGPRect area = { x + 2, y + 1, x + 25 - xOffset, y + 15 - yOffset }; pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES ); Blt16BPPBufferHatchRect( (UINT16*)pDestBuf, uiDestPitchBYTES, &area ); UnLockVideoSurface( FRAME_BUFFER ); } InvalidateRegion(x, y, x + 25 - xOffset, y + 15 - yOffset); } } else { //The blink is now off, so mark the button dirty so that it'll render next frame. MarkAButtonDirty( guiMapBottomExitButtons[ MAP_EXIT_TO_LAPTOP ] ); } } } BOOLEAN CanToggleSelectedCharInventory( void ) { SOLDIERTYPE *pSoldier = NULL; if( gfPreBattleInterfaceActive == TRUE ) { return(FALSE); } // already in inventory and an item picked up? if( fShowInventoryFlag && ( gMPanelRegion.Cursor == EXTERN_CURSOR ) ) { return(FALSE); } // nobody selected? if( bSelectedInfoChar == -1 ) { return(FALSE); } // does the selected guy have inventory and can we get at it? if ( !MapCharacterHasAccessibleInventory( bSelectedInfoChar ) ) { return(FALSE); } pSoldier = gCharactersList[ bSelectedInfoChar ].usSolID; // if not in inventory, and holding an item from sector inventory if( !fShowInventoryFlag && ( ( gMPanelRegion.Cursor == EXTERN_CURSOR ) || gpItemPointer || fMapInventoryItem ) && ( gpItemPointerSoldier == NULL ) ) { // make sure he's in that sector if ( ( pSoldier->sSectorX != sSelMapX ) || ( pSoldier->sSectorY != sSelMapY ) || ( pSoldier->bSectorZ != iCurrentMapSectorZ ) || pSoldier->flags.fBetweenSectors ) { return(FALSE); } } // passed! return(TRUE); } BOOLEAN MapCharacterHasAccessibleInventory( INT16 bCharNumber ) { SOLDIERTYPE *pSoldier = NULL; //Assert( bCharNumber >= 0 ); //Assert( bCharNumber < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS ); if (bCharNumber < 0 || bCharNumber > giMAXIMUM_NUMBER_OF_PLAYER_SLOTS) { return(FALSE); } // invalid character slot selected? if( gCharactersList[ bCharNumber ].fValid == FALSE ) { return(FALSE); } pSoldier = gCharactersList[ bCharNumber ].usSolID; if( ( pSoldier->bAssignment == IN_TRANSIT ) || ( pSoldier->bAssignment == ASSIGNMENT_POW ) || ( pSoldier->bAssignment == ASSIGNMENT_MINIEVENT ) || ( pSoldier->bAssignment == ASSIGNMENT_REBELCOMMAND ) || // Kaiden: Vehicle Inventory change - Commented the following line // ( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) || // And added this instead: ( (!gGameExternalOptions.fVehicleInventory) && (pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE) ) || ( AM_A_ROBOT( pSoldier ) && !gGameExternalOptions.fRobotUpgradeable) || ( pSoldier->ubWhatKindOfMercAmI == MERC_TYPE__EPC && !AM_A_ROBOT( pSoldier ) ) || ( pSoldier->stats.bLife < OKLIFE ) ) { return(FALSE); } return( TRUE ); } void CheckForInventoryModeCancellation() { if ( fShowInventoryFlag || fShowDescriptionFlag ) { // can't bail while player has an item in hand... if( gMPanelRegion.Cursor == EXTERN_CURSOR ) { return; } if ( !CanToggleSelectedCharInventory( ) ) { // get out of inventory mode if it's on! (could have just bled below OKLIFE) if ( fShowInventoryFlag ) { fShowInventoryFlag = FALSE; SetRegionFastHelpText( &gCharInfoHandRegion, pMiscMapScreenMouseRegionHelpText[ 0 ] ); fTeamPanelDirty = TRUE; } // get out of inventory description if it's on! if ( fShowDescriptionFlag ) { DeleteItemDescriptionBox( ); } } } } void ChangeSelectedMapSector( INT16 sMapX, INT16 sMapY, INT8 bMapZ ) { // ignore while map inventory pool is showing, or else items can be replicated, since sector inventory always applies // only to the currently selected sector!!! if( fShowMapInventoryPool ) return; if ( gfPreBattleInterfaceActive ) return; if( !IsTheCursorAllowedToHighLightThisSector( sMapX, sMapY ) ) return; // disallow going underground while plotting (surface) movement if ( ( bMapZ != 0 ) && ( ( GetSelectedDestChar() != -1 ) || fPlotForHelicopter ) ) return; // make sure we don' try to display bad levels if ( bMapZ >= 10 ) bMapZ -= 10; sSelMapX = sMapX; sSelMapY = sMapY; iCurrentMapSectorZ = bMapZ; // if going underground while in airspace mode if ( (bMapZ > 0) && (gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE || gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE_COLOURED_SAMS) ) { // turn off airspace mode ToggleAirspaceMode( ); } fMapPanelDirty = TRUE; fMapScreenBottomDirty = TRUE; // also need this, to update the text coloring of mercs in this sector fTeamPanelDirty = TRUE; } BOOLEAN CanChangeDestinationForCharSlot( INT16 bCharNumber, BOOLEAN fShowErrorMessage ) { INT8 bErrorNumber = -1; if ( bCharNumber == -1 ) return( FALSE ); if ( gCharactersList[ bCharNumber ].fValid == FALSE ) return (FALSE); SOLDIERTYPE* pSoldier = gCharactersList[ bCharNumber ].usSolID; // valid soldier? Assert( pSoldier ); Assert( pSoldier->bActive ); if ( CanEntireMovementGroupMercIsInMove( 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 ); } } BOOLEAN CanExtendContractForCharSlot( INT16 bCharNumber ) { if ( bCharNumber == -1 ) return( FALSE ); if ( gCharactersList[ bCharNumber ].fValid == FALSE ) return (FALSE); SOLDIERTYPE* pSoldier = gCharactersList[ bCharNumber ].usSolID; // valid soldier? Assert( pSoldier ); Assert( pSoldier->bActive ); // if a vehicle, in transit, or a POW if( /*( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) ||*/ ( pSoldier->bAssignment == IN_TRANSIT ) || ( pSoldier->bAssignment == ASSIGNMENT_POW ) ) { // can't extend contracts at this time return (FALSE); } // if a vehicle has passengers if ( (pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE) && (DoesVehicleHaveAnyPassengers(pSoldier->bVehicleID) ) ) { // then restrict contract menu return (FALSE); } // mercs below OKLIFE, M.E.R.C. mercs, EPCs, and the Robot use the Contract menu so they can be DISMISSED/ABANDONED! // everything OK return( TRUE ); } BOOLEAN CanChangeSleepStatusForCharSlot( INT16 bCharNumber ) { if ( bCharNumber == -1 ) return( FALSE ); if ( gCharactersList[ bCharNumber ].fValid == FALSE ) return (FALSE); return( CanChangeSleepStatusForSoldier(gCharactersList[bCharNumber].usSolID) ); } BOOLEAN CanChangeSleepStatusForSoldier( SOLDIERTYPE *pSoldier ) { // valid soldier? Assert( pSoldier ); Assert( pSoldier->bActive ); // if a vehicle, robot, in transit, or a POW if( ( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) || AM_A_ROBOT( pSoldier ) || ( pSoldier->bAssignment == IN_TRANSIT ) || ( pSoldier->bAssignment == ASSIGNMENT_POW ) || ( pSoldier->bAssignment == ASSIGNMENT_MINIEVENT ) || ( pSoldier->bAssignment == ASSIGNMENT_REBELCOMMAND ) ) { // can't change the sleep status of such mercs return ( FALSE ); } // if dead if( ( pSoldier->stats.bLife <= 0 ) || ( pSoldier->bAssignment == ASSIGNMENT_DEAD ) ) { return ( FALSE ); } // this merc MAY be able to sleep/wake up - we'll allow player to click and find out return( TRUE ); } void ChangeMapScreenMaskCursor( UINT16 usCursor ) { MSYS_SetCurrentCursor( usCursor ); MSYS_ChangeRegionCursor( &gMapScreenMaskRegion, usCursor ); if ( usCursor == CURSOR_CHECKMARK ) fCheckCursorWasSet = TRUE; else fCheckCursorWasSet = FALSE; if ( usCursor == CURSOR_NORMAL ) { if ( !InItemStackPopup( ) ) { // cancel mouse restriction FreeMouseCursor( FALSE ); } } else { // restrict mouse cursor to the map area RestrictMouseCursor( &MapScreenRect ); } } void CancelOrShortenPlottedPath( void ) { INT16 sMapX, sMapY; UINT32 uiReturnValue; GetMouseMapXY(&sMapX, &sMapY); // check if we are in aircraft mode if ( gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE || gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE_COLOURED_SAMS ) { // check for helicopter path being plotted if( !fPlotForHelicopter ) return; // if player can't redirect it if ( CanHelicopterFly( ) == FALSE ) { // explain & ignore ExplainWhySkyriderCantFly(); return; } // try to delete portion of path AFTER the current sector for the helicopter uiReturnValue = ClearPathAfterThisSectorForHelicopter( sMapX, sMapY ); } else if ( fShowMilitia ) { // check for helicopter path being plotted if ( !fPlotForMilitia ) return; // if player can't redirect it /*if ( CanHelicopterFly( ) == FALSE ) { // explain & ignore ExplainWhySkyriderCantFly( ); return; }*/ // try to delete portion of path AFTER the current sector for the helicopter uiReturnValue = ClearPathAfterThisSectorForMilitia( sMapX, sMapY ); } else { // check for character path being plotted if( GetSelectedDestChar() == -1 ) return; // try to delete portion of path AFTER the current sector for the helicopter uiReturnValue = ClearPathAfterThisSectorForCharacter( gCharactersList[GetSelectedDestChar()].usSolID, sMapX, sMapY ); } switch ( uiReturnValue ) { case ABORT_PLOTTING: AbortMovementPlottingMode( ); break; case PATH_CLEARED: // movement was canceled // message was already issued when path was cleared DestinationPlottingCompleted(); break; case PATH_SHORTENED: // route was shortened but isn't completely gone // display "route shortened" message MapScreenMessage( FONT_MCOLOR_LTYELLOW, MSG_MAP_UI_POSITION_MIDDLE, pMapPlotStrings[ 4 ] ); break; default: Assert( FALSE ); break; } // this triggers the path node animation to reset itself back to the first node fDeletedNode = TRUE; fMapPanelDirty = TRUE; fTeamPanelDirty = TRUE; fCharacterInfoPanelDirty = TRUE; // to update ETAs if path reversed or shortened } BOOLEAN HandleCtrlOrShiftInTeamPanel( INT16 bCharNumber, BOOLEAN fFromRightClickAssignments ) { // HEADROCK HAM B2.8: New condition based on new argument. if (fFromRightClickAssignments) { if ( _KeyDown(CTRL) || _KeyDown(SHIFT) ) { if ( fSelectedListOfMercsForMapScreen[ bCharNumber ] == FALSE ) { SetEntryInSelectedCharacterList( bCharNumber ); INT16 iCounter; for( iCounter = 0; iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; iCounter++ ) { if( gCharactersList[ iCounter ].fValid == TRUE ) { // if not already selected if( fSelectedListOfMercsForMapScreen[ iCounter ] == FALSE ) { SOLDIERTYPE * pSelected = gCharactersList[ bCharNumber ].usSolID; SOLDIERTYPE * pSoldier = gCharactersList[ iCounter ].usSolID; // if on a squad, or in a vehicle, or IS a vehicle if ( pSoldier->bAssignment == VEHICLE ) { // and a member of that squad or vehicle is selected, or we are a vehicle if ( (pSelected->bAssignment == VEHICLE && pSoldier->iVehicleId == pSelected->iVehicleId) || (pSelected->flags.uiStatusFlags & SOLDIER_VEHICLE && pSoldier->iVehicleId == pSelected->bVehicleID ) || (pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE && pSelected->iVehicleId == pSoldier->bVehicleID ) ) { // then also select this guy SetEntryInSelectedCharacterList( iCounter ); } } else if ( pSoldier->bAssignment == pSelected->bAssignment && (pSoldier->bAssignment == TRAIN_TEAMMATE || pSoldier->bAssignment == TRAIN_BY_OTHER) && pSoldier->sSectorX == pSelected->sSectorX && pSoldier->sSectorY == pSelected->sSectorY && pSoldier->sZLevel == pSelected->sZLevel ) { // make sure only trainers/trainees of the same stat are selected together. if (pSoldier->bTrainStat == pSelected->bTrainStat) { SetEntryInSelectedCharacterList( iCounter ); } } else if ( pSoldier->bAssignment == pSelected->bAssignment && pSoldier->sSectorX == pSelected->sSectorX && pSoldier->sSectorY == pSelected->sSectorY && pSoldier->sZLevel == pSelected->sZLevel ) { SetEntryInSelectedCharacterList( iCounter ); } } } } } else { // Deselect entire group ResetEntryForSelectedList( bCharNumber ); INT16 iCounter; for( iCounter = 0; iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; iCounter++ ) { if( gCharactersList[ iCounter ].fValid == TRUE ) { // if not already selected if( fSelectedListOfMercsForMapScreen[ iCounter ] == TRUE ) { SOLDIERTYPE * pSelected = gCharactersList[ bCharNumber ].usSolID; SOLDIERTYPE * pSoldier = gCharactersList[ iCounter ].usSolID; // if on a squad, or in a vehicle, or IS a vehicle if ( pSoldier->bAssignment == VEHICLE ) { // and a member of that squad or vehicle is selected, or we are a vehicle if ( pSoldier->iVehicleId == pSelected->iVehicleId || (pSelected->flags.uiStatusFlags & SOLDIER_VEHICLE && pSoldier->iVehicleId == pSelected->bVehicleID ) || (pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE && pSelected->iVehicleId == pSoldier->bVehicleID ) ) { // then also select this guy ResetEntryForSelectedList( iCounter ); } } else if ( pSoldier->bAssignment == pSelected->bAssignment && (pSoldier->bAssignment == TRAIN_TEAMMATE || pSoldier->bAssignment == TRAIN_BY_OTHER) && pSoldier->sSectorX == pSelected->sSectorX && pSoldier->sSectorY == pSelected->sSectorY && pSoldier->sZLevel == pSelected->sZLevel ) { // make sure only trainers/trainees of the same stat are selected together. if (pSoldier->bTrainStat == pSelected->bTrainStat) { ResetEntryForSelectedList( iCounter ); } } else if ( pSoldier->bAssignment == pSelected->bAssignment && pSoldier->sSectorX == pSelected->sSectorX && pSoldier->sSectorY == pSelected->sSectorY && pSoldier->sZLevel == pSelected->sZLevel ) { ResetEntryForSelectedList( iCounter ); } } } } } fTeamPanelDirty = TRUE; fCharacterInfoPanelDirty = TRUE; return(TRUE); } return (FALSE); } else { // check if shift or ctrl held down, if so, set values in list if (_KeyDown(CTRL)) { ToggleEntryInSelectedList( bCharNumber ); fTeamPanelDirty = TRUE; fCharacterInfoPanelDirty = TRUE; return( TRUE); } else if( _KeyDown(SHIFT) ) { // build a list from the bSelectedInfoChar To here, reset everyone //empty the list ResetSelectedListForMapScreen( ); // rebuild the list BuildSelectedListFromAToB( bSelectedInfoChar, bCharNumber ); fTeamPanelDirty = TRUE; fCharacterInfoPanelDirty = TRUE; return( TRUE ); } return( FALSE ); } } INT32 GetContractExpiryTime( SOLDIERTYPE *pSoldier ) { #ifdef JA2UB /* JA25 UB */ #else if( ( pSoldier->ubWhatKindOfMercAmI == MERC_TYPE__AIM_MERC ) || ( pSoldier->ubProfile == SLAY ) ) { return ( pSoldier->iEndofContractTime ); } else #endif { // never - really high number return ( 999999 ); } } void ChangeSelectedInfoChar( INT16 bCharNumber, BOOLEAN fResetSelectedList ) { Assert( ( bCharNumber >= -1 ) && ( bCharNumber < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS ) ); if( ( bCharNumber != -1 ) && ( gCharactersList[ bCharNumber ].fValid == FALSE ) ) return; // CHRISL: The result of this block of code is that if we're holding an item, not only does the originally selected merc stay selected, // but the merc who happens to hold the originally selected mercs position in the new sort order will ALSO be selected. // if holding an item //if ( ( gMPanelRegion.Cursor == EXTERN_CURSOR ) || gpItemPointer || fMapInventoryItem ) //{ // make sure we can give it to this guy, otherwise don't allow the change // if ( !MapscreenCanPassItemToCharNum( bCharNumber ) ) // { // return; // } //} if ( fResetSelectedList ) { // reset selections of all listed characters. Do this even if this guy is already selected. // NOTE: this keeps the currently selected info char selected ResetSelectedListForMapScreen( ); } // if this is really a change if ( bSelectedInfoChar != bCharNumber ) { // if resetting, and another guy was selected if ( fResetSelectedList && ( bSelectedInfoChar != -1 ) ) { // deselect previously selected character ResetEntryForSelectedList( bSelectedInfoChar ); } bSelectedInfoChar = bCharNumber; if ( bCharNumber != -1 ) { // the selected guy must always be ON in the list of selected chars SetEntryInSelectedCharacterList( bCharNumber ); } // if we're in the inventory panel if ( fShowInventoryFlag ) { // and we're changing to nobody or a guy whose inventory can't be accessed if ( ( bCharNumber == -1 ) || !MapCharacterHasAccessibleInventory( bCharNumber ) ) { // then get out of inventory mode fShowInventoryFlag = FALSE; } //shadooow: this resets the current highlight item selection to be redrawn again HandleCompatibleAmmoUI(gCharactersList[bCharNumber].usSolID, NO_SLOT, FALSE); if (gpItemPointer != NULL) { gfCheckForMouseOverItem = TRUE; } } fCharacterInfoPanelDirty = TRUE; fResetMapCoords = TRUE; // if showing sector inventory if ( fShowMapInventoryPool ) { // redraw right side to update item hatches fMapPanelDirty = TRUE; } } // marke strogg more mercs // we have to adapt FIRSTmercTOdisplay bCharNumber is 0 to 90 any merc if ( bCharNumber >= 0 ) { if (bCharNumber < FIRSTmercTOdisplay) { FIRSTmercTOdisplay = bCharNumber; } else if (bCharNumber > FIRSTmercTOdisplay + (maxNumberOfMercVisibleInStrategyList - 1) ) { // WANNE: This check fixes the wrong offset when hiring the FIRST merc! if ((maxNumberOfMercVisibleInStrategyList - 1) >= 0) FIRSTmercTOdisplay = bCharNumber - (maxNumberOfMercVisibleInStrategyList - 1); else FIRSTmercTOdisplay = 0; } } // now this should do the trick // marke strogg end fTeamPanelDirty = TRUE; } void CopyPathToAllSelectedCharacters( PathStPtr pPath ) { INT32 iCounter = 0; SOLDIERTYPE *pSoldier = NULL; // run through list and copy paths for each selected character for( iCounter = 0; iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; iCounter++ ) { if( fSelectedListOfMercsForMapScreen[ iCounter ] == TRUE ) { pSoldier = gCharactersList[ iCounter ].usSolID; // skip itself! if ( GetSoldierMercPathPtr( pSoldier ) != pPath ) { if ( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) { pVehicleList[ pSoldier->bVehicleID ].pMercPath = CopyPaths( pPath, pVehicleList[ pSoldier->bVehicleID ].pMercPath ); } else if( pSoldier->bAssignment == VEHICLE ) { pVehicleList[ pSoldier->iVehicleId ].pMercPath = CopyPaths( pPath, pVehicleList[ pSoldier->iVehicleId ].pMercPath ); } else { pSoldier->pMercPath = CopyPaths( pPath, pSoldier->pMercPath ); } // don't use CopyPathToCharactersSquadIfInOne(), it will whack the original pPath by replacing that merc's path! } } } } void CancelPathsOfAllSelectedCharacters() { INT16 bCounter = 0; SOLDIERTYPE *pSoldier = NULL; BOOLEAN fSkyriderMsgShown = FALSE; // cancel destination for the clicked and ALL other valid & selected characters with a route set for( bCounter = 0; bCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; ++bCounter ) { // if we've clicked on a selected valid character if( ( gCharactersList[ bCounter ].fValid == TRUE ) && IsEntryInSelectedListSet( bCounter ) ) { pSoldier = gCharactersList[ bCounter ].usSolID; // and he has a route set if ( GetLengthOfMercPath( pSoldier ) > 0 ) { // if he's in the chopper, but player can't redirect it if ( ( pSoldier->bAssignment == VEHICLE ) && ( pSoldier->iVehicleId == iHelicopterVehicleId ) && ( CanHelicopterFly( ) == FALSE ) ) { if ( !fSkyriderMsgShown ) { // explain ExplainWhySkyriderCantFly(); fSkyriderMsgShown = TRUE; } // don't cancel, ignore continue; } // cancel the entire path (also clears vehicles for any passengers selected, and handles reversing directions) if( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) { CancelPathForVehicle( &( pVehicleList[ pSoldier->bVehicleID ] ), FALSE ); } else { CancelPathForCharacter( pSoldier ); } } } } } void ConvertMinTimeToDayHourMinString( UINT32 uiTimeInMin, STR16 sString ) { UINT32 uiDay, uiHour, uiMin; uiDay = (uiTimeInMin / NUM_MIN_IN_DAY); uiHour = (uiTimeInMin - (uiDay * NUM_MIN_IN_DAY)) / NUM_MIN_IN_HOUR; uiMin = uiTimeInMin - ((uiDay * NUM_MIN_IN_DAY) + (uiHour * NUM_MIN_IN_HOUR)); // there ain't enough room to show both the day and ETA: and without ETA it's confused as the current time // swprintf( sString, L"%s %s %d, %02d:%02d", pEtaString[ 0 ], pDayStrings[ 0 ], uiDay, uiHour, uiMin ); // swprintf( sString, L"%s %d, %02d:%02d", pDayStrings[ 0 ], uiDay, uiHour, uiMin ); swprintf( sString, L"%02d:%02d", uiHour, uiMin ); } void ConvertMinTimeToETADayHourMinString( UINT32 uiTimeInMin, STR16 sString ) { CHAR16 timestring[64]; ConvertMinTimeToDayHourMinString( uiTimeInMin, timestring ); swprintf( sString, L"%s %s", pEtaString[0], timestring ); } INT32 GetGroundTravelTimeOfCharacter( INT8 bCharNumber ) { INT32 iTravelTime = 0; if( bCharNumber == -1 ) return(0); if ( !gCharactersList[ bCharNumber ].fValid ) return(0); // get travel time for the last path segment (stored in pTempCharacterPath) iTravelTime = GetPathTravelTimeDuringPlotting( pTempCharacterPath ); // add travel time for any prior path segments (stored in the selected character's mercpath, but waypoints aren't built) iTravelTime += GetPathTravelTimeDuringPlotting( GetSoldierMercPathPtr( gCharactersList[ bCharNumber ].usSolID ) ); return( iTravelTime ); } INT32 GetGroundTravelTimeOfMilitia( ) { // get travel time for the last path segment (stored in pTempMilitiaPath) INT32 iTravelTime = GetPathTravelTimeDuringPlotting( pTempMilitiaPath ); // add travel time for any prior path segments (stored in the selected character's mercpath, but waypoints aren't built) iTravelTime += GetPathTravelTimeDuringPlotting( gMilitiaPath[gMilitiaGroupId].path ); return(iTravelTime); } INT16 CalcLocationValueForChar( INT32 iCounter ) { SOLDIERTYPE *pSoldier = NULL; INT16 sLocValue = 0; Assert( iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS ); if( gCharactersList[ iCounter ].fValid == FALSE ) return( sLocValue ); pSoldier = gCharactersList[ iCounter ].usSolID; // don't reveal location of POWs! if( pSoldier->bAssignment != ASSIGNMENT_POW && pSoldier->bAssignment != ASSIGNMENT_MINIEVENT && pSoldier->bAssignment != ASSIGNMENT_REBELCOMMAND ) { sLocValue = SECTOR( pSoldier->sSectorX, pSoldier->sSectorY ); // underground: add 1000 per sublevel sLocValue += 1000 * ( pSoldier->bSectorZ ); } return( sLocValue ); } void CancelChangeArrivalSectorMode( ) { // "put him in change arrival sector" mode gfInChangeArrivalSectorMode = FALSE; // change the cursor to that mode SetUpCursorForStrategicMap(); fMapPanelDirty = TRUE; } void MakeMapModesSuitableForDestPlotting( INT8 bCharNumber ) { SOLDIERTYPE *pSoldier = NULL; if( gCharactersList[ bCharNumber ].fValid == TRUE ) { pSoldier = gCharactersList[ bCharNumber ].usSolID; CancelSectorInventoryDisplayIfOn( FALSE ); TurnOnShowTeamsMode( ); if ( ( pSoldier->bAssignment == VEHICLE ) && ( pSoldier->iVehicleId == iHelicopterVehicleId ) ) { if ( gusMapDisplayColourMode != MAP_DISPLAY_AIRSPACE && gusMapDisplayColourMode != MAP_DISPLAY_AIRSPACE_COLOURED_SAMS ) { // turn on airspace mode automatically ToggleAirspaceMode(); } } else { if ( gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE || gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE_COLOURED_SAMS ) { // turn off airspace mode automatically ToggleAirspaceMode(); } } // if viewing a different sublevel if ( iCurrentMapSectorZ != pSoldier->bSectorZ ) { // switch to that merc's sublevel JumpToLevel( pSoldier->bSectorZ ); } } } BOOLEAN AnyMovableCharsInOrBetweenThisSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ ) { SOLDIERTYPE *pSoldier = NULL; // to speed it up a little? SoldierID id = gTacticalStatus.Team[ OUR_TEAM ].bFirstID; SoldierID iLastId = gTacticalStatus.Team[ OUR_TEAM ].bLastID; for( ; id <= iLastId; ++id) { // get the soldier pSoldier = id; // is the soldier active if( pSoldier->bActive == FALSE ) { continue; } // POWs, dead guys, guys in transit can't move if ( ( pSoldier->bAssignment == IN_TRANSIT ) || ( pSoldier->bAssignment == ASSIGNMENT_POW ) || SPY_LOCATION( pSoldier->bAssignment ) || ( pSoldier->bAssignment == ASSIGNMENT_DEAD ) || ( pSoldier->bAssignment == ASSIGNMENT_MINIEVENT ) || ( pSoldier->bAssignment == ASSIGNMENT_REBELCOMMAND ) || ( pSoldier->stats.bLife == 0 ) ) { continue; } // don't count mercs aboard Skyrider if ( ( pSoldier->bAssignment == VEHICLE ) && ( pSoldier->iVehicleId == iHelicopterVehicleId ) ) { continue; } // don't count vehicles - in order for them to move, somebody must be in the sector with them if ( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) { continue; } // is he here? if( ( pSoldier->sSectorX == sSectorX ) && ( pSoldier->sSectorY == sSectorY ) && ( pSoldier->bSectorZ == bSectorZ ) ) { // NOTE that we consider mercs between sectors, mercs < OKLIFE, and sleeping mercs to be "movable". // This lets CanCharacterMoveInStrategic() itself report the appropriate error message when character is clicked return( TRUE ); } } return( FALSE ); } BOOLEAN RequestGiveSkyriderNewDestination( void ) { // should we allow it? if( CanHelicopterFly( ) ) { // if not warned already, and chopper empty, but mercs are in this sector if ( !gfSkyriderEmptyHelpGiven && ( GetNumberOfPassengersInHelicopter() == 0 ) && ( PlayerMercsInHelicopterSector() > 0 ) ) { DoMapMessageBox( MSG_BOX_BASIC_STYLE, pSkyriderText[ 6 ], MAP_SCREEN, MSG_BOX_FLAG_OK, MapScreenDefaultOkBoxCallback ); gfSkyriderEmptyHelpGiven = TRUE; return( FALSE ); } // say Yo! if( !gGameSettings.fOptions[ TOPTION_SILENT_SKYRIDER ]) SkyRiderTalk( SKYRIDER_SAYS_HI ); // start plotting helicopter movement fPlotForHelicopter = TRUE; // change cursor to the helicopter SetUpCursorForStrategicMap(); // remember the helicopter's current path so we can restore it if need be gpHelicopterPreviousMercPath = CopyPaths( pVehicleList[ iHelicopterVehicleId ].pMercPath, gpHelicopterPreviousMercPath ); // affects Skyrider's dialogue SetFactTrue( FACT_SKYRIDER_USED_IN_MAPSCREEN ); return( TRUE ); } else // not allowed to reroute the chopper right now { // tell player why not ExplainWhySkyriderCantFly(); return( FALSE ); } } void ExplainWhySkyriderCantFly( void ) { // do we owe him money? if( gMercProfiles[ SKYRIDER ].iBalance < 0 ) { // overdue cash SkyRiderTalk( OWED_MONEY_TO_SKYRIDER ); return; } // is he returning to base? if( fHeliReturnStraightToBase ) { // returning to base SkyRiderTalk( RETURN_TO_BASE ); return; } // grounded by enemies in sector? if ( CanHelicopterTakeOff() == FALSE ) { SkyRiderTalk( CHOPPER_NOT_ACCESSIBLE ); // DoMapMessageBox( MSG_BOX_BASIC_STYLE, pSkyriderText[ 4 ], MAP_SCREEN, MSG_BOX_FLAG_OK, MapScreenDefaultOkBoxCallback ); return; } // Drassen too disloyal to wanna help player? if ( CheckFact( FACT_LOYALTY_LOW, SKYRIDER ) ) { SkyRiderTalk( DOESNT_WANT_TO_FLY ); return; } // repairs in progress if ( gubHelicopterHoursToRepair > 0 ) { DoMapMessageBox( MSG_BOX_BASIC_STYLE, pHelicopterRepairRefuelStrings[ STR_HELI_RR_REPAIR_IN_PROGRESS ], MAP_SCREEN, MSG_BOX_FLAG_OK, MapScreenDefaultOkBoxCallback ); return; } // anv - helicopter too damaged? if ( gGameExternalOptions.fSeriouslyDamagedSkyriderWontFly == TRUE && gubHelicopterHitsTaken > 1 ) { SkyRiderTalk( HELI_TOO_DAMAGED_TO_FLY ); return; } // travelled too far? if ( gGameExternalOptions.fAlternativeHelicopterFuelSystem ) { if ( iTotalHeliDistanceSinceRefuel > gHelicopterSettings.ubHelicopterDistanceWithoutRefuel ) { DoMapMessageBox( MSG_BOX_BASIC_STYLE, pHelicopterRepairRefuelStrings[STR_HELI_TOOFAR_ERROR], MAP_SCREEN, MSG_BOX_FLAG_OK, MapScreenDefaultOkBoxCallback ); return; } } // no explainable reason } UINT8 PlayerMercsInHelicopterSector( void ) { GROUP *pGroup = NULL; Assert( iHelicopterVehicleId != -1); pGroup = GetGroup( pVehicleList[ iHelicopterVehicleId ].ubMovementGroup ); AssertNotNIL(pGroup); if ( pGroup->fBetweenSectors ) { return( 0 ); } return( PlayerMercsInSector( pGroup->ubSectorX, pGroup->ubSectorY, 0 ) ); } void HandleNewDestConfirmation( INT16 sMapX, INT16 sMapY ) { UINT8 ubCurrentProgress; // if moving the chopper itself, or moving a character aboard the chopper if( fPlotForHelicopter ) { // if there are no enemies in destination sector, or we don't know if ( (NumNonPlayerTeamMembersInSector( sMapX, sMapY, ENEMY_TEAM ) == 0) || ( WhatPlayerKnowsAboutEnemiesInSector( sMapX, sMapY ) == KNOWS_NOTHING ) ) { // no problem // get current player progress ubCurrentProgress = CurrentPlayerProgressPercentage(); // if we're doing a lot better than last time he said anything if ( ( ubCurrentProgress > gubPlayerProgressSkyriderLastCommentedOn ) && ( ( ubCurrentProgress - gubPlayerProgressSkyriderLastCommentedOn ) >= MIN_PROGRESS_FOR_SKYRIDER_QUOTE_DOING_WELL ) ) { // kicking ass! SkyRiderTalk( THINGS_ARE_GOING_WELL ); gubPlayerProgressSkyriderLastCommentedOn = ubCurrentProgress; } // if we're doing noticably worse than last time he said anything else if ( ( ubCurrentProgress < gubPlayerProgressSkyriderLastCommentedOn ) && ( ( gubPlayerProgressSkyriderLastCommentedOn - ubCurrentProgress ) >= MIN_REGRESS_FOR_SKYRIDER_QUOTE_DOING_BADLY ) ) { // sucking rocks! SkyRiderTalk( THINGS_ARE_GOING_BADLY ); gubPlayerProgressSkyriderLastCommentedOn = ubCurrentProgress; } else { // ordinary confirmation quote if(gGameSettings.fOptions[ TOPTION_SILENT_SKYRIDER ] == FALSE) SkyRiderTalk( CONFIRM_DESTINATION ); } } //CHRISL: If we're allowing Skyrider to drop mercs into a hot LZ, we don't need Skyrider telling us he isn't going to drop the mercs off. else if(gGameExternalOptions.ubSkyriderHotLZ == 0) { // ok, but... you know there are enemies there... SkyRiderTalk( BELIEVED_ENEMY_SECTOR ); } } else if ( fPlotForMilitia ) { // we could play a generic militia confirmation sound here, if we had such a thing... } else { RandomAwakeSelectedMercConfirmsStrategicMove( ); // tell player the route was CONFIRMED // NOTE: We don't this this for the helicopter any more, since it clashes with Skyrider's own confirmation msg MapScreenMessage( FONT_MCOLOR_LTYELLOW, MSG_MAP_UI_POSITION_MIDDLE, pMapPlotStrings[ 1 ] ); // wake up anybody who needs to be awake to travel WakeUpAnySleepingSelectedMercsOnFootOrDriving(); } } void RandomAwakeSelectedMercConfirmsStrategicMove( void ) { SOLDIERTYPE *pSoldier = NULL; INT32 iCounter; // WDS - make number of mercenaries, etc. be configurable SoldierID ubSelectedMercID[ CODE_MAXIMUM_NUMBER_OF_PLAYER_SLOTS ]; UINT16 ubSelectedMercIndex[ CODE_MAXIMUM_NUMBER_OF_PLAYER_SLOTS ]; UINT16 ubNumMercs = 0; UINT16 ubChosenMerc; for( iCounter = 0; iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; iCounter++ ) { if( ( fSelectedListOfMercsForMapScreen[ iCounter ] == TRUE ) ) { pSoldier = gCharactersList[ iCounter ].usSolID; if ( pSoldier->stats.bLife >= OKLIFE && !( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) && !AM_A_ROBOT( pSoldier ) && !AM_AN_EPC( pSoldier ) && !pSoldier->flags.fMercAsleep ) { ubSelectedMercID[ ubNumMercs ] = pSoldier->ubID; ubSelectedMercIndex[ ubNumMercs ] = (UINT16)iCounter; ubNumMercs++; } } } if ( ubNumMercs > 0 ) { ubChosenMerc = (UINT16)Random( ubNumMercs ); // select that merc so that when he speaks we're showing his portrait and not someone else ChangeSelectedInfoChar( ubSelectedMercIndex[ ubChosenMerc ], FALSE ); ubSelectedMercID[ ubChosenMerc ]->DoMercBattleSound( BATTLE_SOUND_OK1 ); //TacticalCharacterDialogue( MercPtrs[ ubSelectedMercID[ ubChosenMerc ] ], ubQuoteNum ); } } void DestinationPlottingCompleted( void ) { // clear previous paths for selected characters and helicopter ClearPreviousPaths(); fPlotForHelicopter = FALSE; SetSelectedDestChar( -1 ); giDestHighLine = -1; // Flugente: add militia from the starting sector to the group if ( fPlotForMilitia ) { if ( gbWorldSectorZ <= 0 && gMilitiaPath[gMilitiaGroupId].sGroupid > -1 ) { GROUP* pGroup = GetGroup( (UINT8)gMilitiaPath[gMilitiaGroupId].sGroupid ); // If this group has size 0, we assume that we are starting a new path - so pick up militia. // If it already has members, do not do that if ( pGroup && pGroup->usGroupTeam == MILITIA_TEAM )//&& pGroup->ubGroupSize == 0 ) { /*SECTORINFO *pSector = &SectorInfo[SECTOR( pGroup->ubSectorX, pGroup->ubSectorY )]; pGroup->pEnemyGroup->ubNumAdmins = pSector->ubNumberOfCivsAtLevel[0]; pGroup->pEnemyGroup->ubNumTroops = pSector->ubNumberOfCivsAtLevel[1]; pGroup->pEnemyGroup->ubNumElites = pSector->ubNumberOfCivsAtLevel[2]; pSector->ubNumberOfCivsAtLevel[0] = 0; pSector->ubNumberOfCivsAtLevel[1] = 0; pSector->ubNumberOfCivsAtLevel[2] = 0;*/ pGroup->ubGroupSize = pGroup->pEnemyGroup->ubNumAdmins + pGroup->pEnemyGroup->ubNumTroops + pGroup->pEnemyGroup->ubNumElites; } } MilitiaplotFinish(); fPlotForMilitia = FALSE; } fMapPanelDirty = TRUE; // reset cursor SetUpCursorForStrategicMap( ); fJustFinishedPlotting = TRUE; fEndPlotting = TRUE; } void HandleMilitiaRedistributionClick( void ) { INT8 bTownId; //BOOLEAN fTownStillHidden; CHAR16 sString[ 128 ]; // if on the surface if ( iCurrentMapSectorZ == 0 ) { bTownId = GetTownIdForSector( sSelMapX, sSelMapY ); //fTownStillHidden = ( ( bTownId == TIXA ) && !fFoundTixa ) || ( ( bTownId == ORTA ) && !fFoundOrta ); // fTownStillHidden = ( ( bTownId == TIXA ) && !gfHiddenTown[ TIXA ] ) || ( ( bTownId == ORTA ) && !gfHiddenTown[ ORTA ] ); // WANNE: if gfHiddenTown[townID] == TRUE, then it is not HIDDEN!!! if( ( bTownId != BLANK_SECTOR ) && gfHiddenTown[ bTownId ] ) //&& !fTownStillHidden ) { if ( MilitiaTrainingAllowedInSector( sSelMapX, sSelMapY, ( INT8 )iCurrentMapSectorZ ) ) { if( fShowTownInfo == TRUE ) { fShowTownInfo = FALSE; } fMapPanelDirty = TRUE; // check if there's combat in any of the town's sectors if ( CanRedistributeMilitiaInSector( sSelMapX, sSelMapY, bTownId ) ) { // Nope, ok, set selected militia town sSelectedMilitiaTown = bTownId; } else { // can't redistribute militia during combat! DoScreenIndependantMessageBox( pMilitiaString[ 2 ], MSG_BOX_FLAG_OK, NULL ); } } else { // can't have militia in this town swprintf( sString, pMapErrorString[ 31 ], pTownNames [ bTownId ] ); DoScreenIndependantMessageBox( sString, MSG_BOX_FLAG_OK, NULL ); } } else if( IsThisSectorASAMSector( sSelMapX, sSelMapY, 0 ) && fSamSiteFound[ GetSAMIdFromSector( sSelMapX, sSelMapY, 0 ) ] ) { // can't move militia around sam sites DoScreenIndependantMessageBox( pMapErrorString[ 30 ], MSG_BOX_FLAG_OK, NULL ); } } } #ifdef JA2TESTVERSION void DumpSectorDifficultyInfo( void ) { // NOTE: This operates on the selected map sector! CHAR16 wSectorName[ 128 ]; ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_TESTVERSION, L"Playing Difficulty: %s", zDiffSetting[gGameOptions.ubDifficultyLevel].szDiffName ); ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_TESTVERSION, L"Highest Progress (0-100) = %d%%", HighestPlayerProgressPercentage() ); ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_TESTVERSION, L"Player Kills = %d", gStrategicStatus.usPlayerKills ); GetSectorIDString( sSelMapX, sSelMapY, ( INT8 ) iCurrentMapSectorZ, wSectorName, TRUE ); ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_TESTVERSION, L"SECTOR: %s", wSectorName ); ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_TESTVERSION, L"Pyth. Distance From Meduna (0-20) = %d", GetPythDistanceFromPalace( sSelMapX, sSelMapY ) ); if ( ( gWorldSectorX == sSelMapX ) && ( gWorldSectorY == sSelMapY ) && ( gbWorldSectorZ == iCurrentMapSectorZ ) ) { ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_TESTVERSION, L"Enemy Difficulty Factor (0 to 100) = %d%%", CalcDifficultyModifier( SOLDIER_CLASS_ARMY ) ); ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_TESTVERSION, L"Avg Regular Enemy Exp. Level (2-6) = %d", 2 + ( CalcDifficultyModifier( SOLDIER_CLASS_ARMY ) / 20 ) ); } else { ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_TESTVERSION, L"--Must load sector to calculate difficulty--" ); } } #endif void StartChangeSectorArrivalMode( void ) { // "put him in change arrival sector" mode gfInChangeArrivalSectorMode = TRUE; // redraw map with bullseye removed fMapPanelDirty = TRUE; // change the cursor to that mode SetUpCursorForStrategicMap(); // give instructions as overlay message MapScreenMessage( FONT_MCOLOR_LTYELLOW, MSG_MAP_UI_POSITION_MIDDLE, pBullseyeStrings[ 0 ] ); } BOOLEAN CanMoveBullseyeAndClickedOnIt( INT16 sMapX, INT16 sMapY ) { // if in airspace mode, and not plotting paths if ( (gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE || gusMapDisplayColourMode == MAP_DISPLAY_AIRSPACE_COLOURED_SAMS) && ( GetSelectedDestChar() == -1) && (fPlotForHelicopter == FALSE) ) { if (is_networked) { // haydent // OJW 080101 - allow map change before laptop unlock if ((!is_server && !is_client) || (is_server && !allowlaptop)) { // if he clicked on the bullseye, and we're on the surface level if ( ( sMapX == gsMercArriveSectorX ) && ( sMapY == gsMercArriveSectorY ) && ( iCurrentMapSectorZ == 0 ) ) { return( TRUE ); } } // haydent else if(is_server) { ScreenMsg( FONT_LTGREEN, MSG_MPSYSTEM, MPServerMessage[9] ); } else if(is_client) ScreenMsg( FONT_LTGREEN, MSG_MPSYSTEM, MPClientMessage[38] ); } else { // don't allow moving bullseye until after initial arrival if ( gTacticalStatus.fDidGameJustStart == FALSE ) { // if he clicked on the bullseye, and we're on the surface level if ( ( sMapX == gsMercArriveSectorX ) && ( sMapY == gsMercArriveSectorY ) && ( iCurrentMapSectorZ == 0 ) ) { return( TRUE ); } } } } return( FALSE ); } void CreateBullsEyeOrChopperSelectionPopup( void ) { wcscpy( gzUserDefinedButton1, pHelicopterEtaStrings[ STR_HELI_ETA_SKYRIDER ] ); wcscpy( gzUserDefinedButton2, pHelicopterEtaStrings[ STR_HELI_ETA_ARRIVALS ] ); // do a BULLSEYE/CHOPPER message box DoScreenIndependantMessageBox( pHelicopterEtaStrings[ STR_HELI_ETA_SELECT_SKYRIDER_OR_ARRIVALS ], MSG_BOX_FLAG_GENERIC_TWO_BUTTONS, BullsEyeOrChopperSelectionPopupCallback ); } void BullsEyeOrChopperSelectionPopupCallback( UINT8 ubExitValue ) { // button 1 pressed? if ( ubExitValue == MSG_BOX_RETURN_YES ) { // chose chopper // have to set a flag 'cause first call to RequestGiveSkyriderNewDestination() triggers another msg box & won't work gfRequestGiveSkyriderNewDestination = TRUE; } // button 2 pressed? else if( ubExitValue == MSG_BOX_RETURN_NO ) { // chose bullseye StartChangeSectorArrivalMode(); } } // wake up anybody who needs to be awake to travel void WakeUpAnySleepingSelectedMercsOnFootOrDriving( void ) { SOLDIERTYPE *pSoldier = NULL; INT32 iCounter; BOOLEAN fSuccess = FALSE; for( iCounter = 0; iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; iCounter++ ) { if( ( fSelectedListOfMercsForMapScreen[ iCounter ] == TRUE ) ) { pSoldier = gCharactersList[ iCounter ].usSolID; // if asleep if ( pSoldier->flags.fMercAsleep ) { // and on foot or driving if ( ( pSoldier->bAssignment < ON_DUTY ) || ( ( pSoldier->bAssignment == VEHICLE ) && SoldierMustDriveVehicle( pSoldier, pSoldier->iVehicleId, FALSE ) ) ) { // we should be guaranteed that he CAN wake up to get this far, so report errors, but don't force it fSuccess = SetMercAwake( pSoldier, TRUE, FALSE ); Assert( fSuccess ); } } } } } void HandlePostAutoresolveMessages() { //KM: Autoresolve sets up this global sector value whenever the enemy gains control of a sector. As soon as //we leave autoresolve and enter mapscreen, then this gets called and handles ownership change for the sector. //It also brings up a dialog stating to the player what happened, however, the internals of those functions //breaks autoresolve and the game crashes after autoresolve is finished. The value doesn't need to be saved. // //An additional case is when creatures kill all opposition in the sector. For each surviving monster, civilians //are "virtually" murdered and loyalty hits will be processed. if( gsCiviliansEatenByMonsters >= 1 ) { AdjustLoyaltyForCivsEatenByMonsters( (UINT8)SECTORX( gsEnemyGainedControlOfSectorID ), (UINT8)SECTORY( gsEnemyGainedControlOfSectorID ), (UINT8)gsCiviliansEatenByMonsters, ( guCreatureAttackType == CREATURE_ATTACK_TYPE_BANDIT ) ); gsCiviliansEatenByMonsters = -2; } else if( gsCiviliansEatenByMonsters == -2 ) { fMapPanelDirty = TRUE; gsCiviliansEatenByMonsters = -1; gsEnemyGainedControlOfSectorID = -1; } else if( gsEnemyGainedControlOfSectorID >= 0 ) { //bring up the dialog box SetThisSectorAsEnemyControlled( (UINT8)SECTORX( gsEnemyGainedControlOfSectorID ), (UINT8)SECTORY( gsEnemyGainedControlOfSectorID ), 0, TRUE ); gsEnemyGainedControlOfSectorID = -2; } else if( gsEnemyGainedControlOfSectorID == -2 ) { //dirty the mapscreen after the dialog box goes away. fMapPanelDirty = TRUE; gsEnemyGainedControlOfSectorID = -1; } else if( gbMilitiaPromotions ) { CHAR16 str[ 512 ]; BuildMilitiaPromotionsString( str ); DoScreenIndependantMessageBox( str, MSG_BOX_FLAG_OK, MapScreenDefaultOkBoxCallback ); } } void GetMapscreenMercAssignmentString( SOLDIERTYPE *pSoldier, CHAR16 sString[] ) { if ( pSoldier->bAssignment == VEHICLE ) { // wcscpy( sString, pShortVehicleStrings[ pVehicleList[ pSoldier->iVehicleId ].ubVehicleType ] ); wcscpy( sString, gNewVehicle[ pVehicleList[ pSoldier->iVehicleId ].ubVehicleType ].NewShortVehicleStrings); } else { if ( gGameExternalOptions.fUseXMLSquadNames && pSoldier->bAssignment < min(ON_DUTY, gSquadNameVector.size() ) ) swprintf( sString, L" %s", gSquadNameVector[pSoldier->bAssignment].c_str() ); else if(pSoldier->bVehicleID != 0 && pSoldier->bAssignment == ASSIGNMENT_DEAD) wcscpy(sString, L"Wrecked"); else wcscpy(sString, pAssignmentStrings[ pSoldier->bAssignment ] ); } // If soldier is working at a facility, add an asterisk. if (pSoldier->sFacilityTypeOperated != -1) { wcscat(sString, L"*"); } } void GetMapscreenMercLocationString( SOLDIERTYPE *pSoldier, CHAR16 sString[] ) { CHAR16 pTempString[32]; if( pSoldier->bAssignment == IN_TRANSIT ) { // show blank wcscpy( sString, L"--" ); } else { // Flugente: if we have intel on a POW, DO show their location if ( pSoldier->bAssignment == ASSIGNMENT_POW && !( pSoldier->usSoldierFlagMask2 & SOLDIER_MERC_POW_LOCATIONKNOWN )) { // POW - location unknown swprintf( sString, L"%s", pPOWStrings[ 1 ] ); } else if ( pSoldier->bAssignment == ASSIGNMENT_MINIEVENT ) { // mini event - unknown location, use the same string as POWs swprintf( sString, L"%s", pPOWStrings[ 1 ] ); } else if (pSoldier->bAssignment == ASSIGNMENT_REBELCOMMAND) { // on a rebel command mission swprintf( sString, L"%s%s*", pMapVertIndex[pSoldier->sSectorY], pMapHortIndex[pSoldier->sSectorX] ); } else if ( SPY_LOCATION( pSoldier->bAssignment ) ) { swprintf( pTempString, L"%s%s%s", pMapVertIndex[pSoldier->sSectorY], pMapHortIndex[pSoldier->sSectorX], pMapDepthIndex[max(0, pSoldier->bSectorZ - 10)] ); swprintf( sString, L"%s*", pTempString ); } else { swprintf( pTempString, L"%s%s%s", pMapVertIndex[ pSoldier->sSectorY ], pMapHortIndex[ pSoldier->sSectorX ], pMapDepthIndex[ pSoldier->bSectorZ ] ); if ( pSoldier->flags.fBetweenSectors ) { // put brackets around it when he's between sectors! swprintf( sString, L"(%s)", pTempString ); } else { wcscpy( sString, pTempString ); } } } } void GetMapscreenMercDestinationString( SOLDIERTYPE *pSoldier, CHAR16 sString[] ) { INT32 iSectorX, iSectorY; INT16 sSector=0; GROUP *pGroup = NULL; // by default, show nothing wcscpy( sString, L"" ); // if dead or POW - has no destination (no longer part of a group, for that matter) if( ( pSoldier->bAssignment == ASSIGNMENT_DEAD ) || ( pSoldier->bAssignment == ASSIGNMENT_POW ) || ( pSoldier->bAssignment == ASSIGNMENT_MINIEVENT ) || ( pSoldier->bAssignment == ASSIGNMENT_REBELCOMMAND ) || SPY_LOCATION( pSoldier->bAssignment ) || ( pSoldier->stats.bLife == 0 ) ) { return; } if( pSoldier->bAssignment == IN_TRANSIT ) { // show the sector he'll be arriving in iSectorX = gsMercArriveSectorX; iSectorY = gsMercArriveSectorY; } else { // if he's going somewhere if ( GetLengthOfMercPath( pSoldier ) > 0 ) { sSector = GetLastSectorIdInCharactersPath( pSoldier ); // convert iSectorX = sSector % MAP_WORLD_X; iSectorY = sSector / MAP_WORLD_Y; } else // no movement path is set... { if ( pSoldier->flags.fBetweenSectors ) { // he must be returning to his previous (reversed so as to be the next) sector, so show that as his destination // individual soldiers don't store previous/next sector coordinates, must go to his group for that pGroup = GetGroup( GetSoldierGroupId( pSoldier ) ); Assert( pGroup ); iSectorX = pGroup->ubNextX; iSectorY = pGroup->ubNextY; } else { // show nothing return; } } } swprintf( sString, L"%s%s", pMapVertIndex[ iSectorY ], pMapHortIndex[ iSectorX ] ); } void GetMapscreenMercDepartureString( SOLDIERTYPE *pSoldier, CHAR16 sString[], UINT8 *pubFontColor ) { INT32 iMinsRemaining = 0; INT32 iDaysRemaining = 0; INT32 iHoursRemaining = 0; #ifdef JA2UB //Ja25: Removed the aim merc check because aim mercs are hired for a 1 time fee if( ( pSoldier->ubProfile != SLAY ) || pSoldier->stats.bLife == 0 ) #else if( ( pSoldier->ubWhatKindOfMercAmI != MERC_TYPE__AIM_MERC && pSoldier->ubProfile != SLAY ) || pSoldier->stats.bLife == 0 ) #endif { swprintf( sString, L"%s", gpStrategicString[ STR_PB_NOTAPPLICABLE_ABBREVIATION ] ); } else { iMinsRemaining = pSoldier->iEndofContractTime - GetWorldTotalMin(); //if the merc is in transit if( pSoldier->bAssignment == IN_TRANSIT ) { //and if the time left on the cotract is greater then the contract time if( iMinsRemaining > (INT32)( pSoldier->iTotalContractLength * NUM_MIN_IN_DAY ) ) { iMinsRemaining = ( pSoldier->iTotalContractLength * NUM_MIN_IN_DAY ); } } // if 3 or more days remain if( iMinsRemaining >= MAP_TIME_UNDER_THIS_DISPLAY_AS_HOURS ) { iDaysRemaining = iMinsRemaining / (24*60); *pubFontColor = FONT_LTGREEN; swprintf(sString, L"%d%s", iDaysRemaining, gpStrategicString[ STR_PB_DAYS_ABBREVIATION ] ); } else // less than 3 days { if( iMinsRemaining > 5 ) { iHoursRemaining = ( iMinsRemaining + 59 ) / 60; } else { iHoursRemaining = 0; } // last 3 days is Red, last 4 hours start flashing red/white! if( ( iMinsRemaining <= MINS_TO_FLASH_CONTRACT_TIME ) && ( fFlashContractFlag == TRUE ) ) { *pubFontColor = FONT_WHITE; } else { *pubFontColor = FONT_RED; } swprintf(sString, L"%d%s", iHoursRemaining, gpStrategicString[ STR_PB_HOURS_ABBREVIATION ] ); } } } void InitPreviousPaths( void ) { INT32 iCounter = 0; // init character previous paths for( iCounter = 0; iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; ++iCounter ) { gpCharacterPreviousMercPath[ iCounter ] = NULL; } // init helicopter previous path gpHelicopterPreviousMercPath = NULL; //for ( iCounter = 0; iCounter < MILITIA_PATROLS_MAX; ++iCounter ) { gpMilitiaPreviousMercPath = NULL; } } void RememberPreviousPathForAllSelectedChars( void ) { INT32 iCounter = 0; SOLDIERTYPE *pSoldier = NULL; for( iCounter = 0; iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; iCounter++ ) { if( fSelectedListOfMercsForMapScreen[ iCounter ] == TRUE ) { pSoldier = gCharactersList[ iCounter ].usSolID; // remember his previous path by copying it to his slot in the array kept for that purpose gpCharacterPreviousMercPath[ iCounter ] = CopyPaths( GetSoldierMercPathPtr( gCharactersList[ iCounter ].usSolID ), gpCharacterPreviousMercPath[ iCounter ] ); } } } void RestorePreviousPaths( void ) { INT32 iCounter = 0; SOLDIERTYPE *pSoldier = NULL; PathStPtr *ppMovePath = NULL; UINT8 ubGroupId = 0; BOOLEAN fPathChanged = FALSE; // invalid if we're not plotting movement Assert( ( GetSelectedDestChar() != -1) || fPlotForHelicopter || fPlotForMilitia ); if ( fPlotForHelicopter ) { ppMovePath = &( pVehicleList[ iHelicopterVehicleId ].pMercPath ); ubGroupId = pVehicleList[ iHelicopterVehicleId ].ubMovementGroup; // if the helicopter had a previous path if( gpHelicopterPreviousMercPath != NULL ) { gpHelicopterPreviousMercPath = MoveToBeginningOfPathList( gpHelicopterPreviousMercPath ); // clear current path *ppMovePath = ClearStrategicPathList( *ppMovePath, ubGroupId ); // replace it with the previous one *ppMovePath = CopyPaths( gpHelicopterPreviousMercPath, *ppMovePath ); // will need to rebuild waypoints fPathChanged = TRUE; } else // no previous path { // if he currently has a path if( *ppMovePath ) { // wipe it out! *ppMovePath = MoveToBeginningOfPathList( *ppMovePath ); *ppMovePath = ClearStrategicPathList( *ppMovePath, ubGroupId ); // will need to rebuild waypoints fPathChanged = TRUE; } } if ( fPathChanged ) { // rebuild waypoints RebuildWayPointsForGroupPath( *ppMovePath, ubGroupId ); // copy his path to all selected characters CopyPathToAllSelectedCharacters( *ppMovePath ); } } else if ( fPlotForMilitia ) { //for ( iCounter = 0; iCounter < MILITIA_PATROLS_MAX; iCounter++ ) { // if selected //if ( fSelectedListOfMercsForMapScreen[iCounter] == TRUE ) if ( gMilitiaPath[gMilitiaGroupId].sGroupid > -1 ) { //pSoldier = MercPtrs[gCharactersList[iCounter].usSolID]; //if ( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) { ppMovePath = &gMilitiaPath[gMilitiaGroupId].path; ubGroupId = (UINT8)gMilitiaPath[gMilitiaGroupId].sGroupid; } fPathChanged = FALSE; // if we have the previous path stored for the dest char if ( gpMilitiaPreviousMercPath ) { gpMilitiaPreviousMercPath = MoveToBeginningOfPathList( gpMilitiaPreviousMercPath ); // clear current path *ppMovePath = ClearStrategicPathList( *ppMovePath, ubGroupId ); // replace it with the previous one *ppMovePath = CopyPaths( gpMilitiaPreviousMercPath, *ppMovePath ); // will need to rebuild waypoints fPathChanged = TRUE; } else // no previous path stored { // if he has one now, wipe it out if ( *ppMovePath ) { // wipe it out! *ppMovePath = MoveToBeginningOfPathList( *ppMovePath ); *ppMovePath = ClearStrategicPathList( *ppMovePath, ubGroupId ); // will need to rebuild waypoints fPathChanged = TRUE; } } if ( fPathChanged ) { // rebuild waypoints RebuildWayPointsForGroupPath( *ppMovePath, ubGroupId ); } } } } else // character(s) plotting { for( iCounter = 0; iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; ++iCounter ) { // if selected if( fSelectedListOfMercsForMapScreen[ iCounter ] == TRUE ) { pSoldier = gCharactersList[ iCounter ].usSolID; if( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) { ppMovePath = &( pVehicleList[ pSoldier->bVehicleID ].pMercPath ); ubGroupId = pVehicleList[ pSoldier->bVehicleID ].ubMovementGroup; } else if( pSoldier->bAssignment == VEHICLE ) { ppMovePath = &( pVehicleList[ pSoldier->iVehicleId ].pMercPath ); ubGroupId = pVehicleList[ pSoldier->iVehicleId ].ubMovementGroup; } else if( pSoldier->bAssignment < ON_DUTY ) { ppMovePath = &( pSoldier->pMercPath ); ubGroupId = pSoldier->ubGroupID; } else { // invalid pSoldier - that guy can't possibly be moving, he's on a non-vehicle assignment! Assert( 0 ); continue; } fPathChanged = FALSE; // if we have the previous path stored for the dest char if( gpCharacterPreviousMercPath[ iCounter ] ) { gpCharacterPreviousMercPath[ iCounter ] = MoveToBeginningOfPathList( gpCharacterPreviousMercPath[ iCounter ] ); // clear current path *ppMovePath = ClearStrategicPathList( *ppMovePath, ubGroupId ); // replace it with the previous one *ppMovePath = CopyPaths( gpCharacterPreviousMercPath[ iCounter ], *ppMovePath ); // will need to rebuild waypoints fPathChanged = TRUE; } else // no previous path stored { // if he has one now, wipe it out if( *ppMovePath ) { // wipe it out! *ppMovePath = MoveToBeginningOfPathList( *ppMovePath ); *ppMovePath = ClearStrategicPathList( *ppMovePath, ubGroupId ); // will need to rebuild waypoints fPathChanged = TRUE; } } if ( fPathChanged ) { // rebuild waypoints RebuildWayPointsForGroupPath( *ppMovePath, ubGroupId ); } } } } } void ClearPreviousPaths( void ) { INT32 iCounter = 0; for( iCounter = 0; iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; ++iCounter ) { if( fSelectedListOfMercsForMapScreen[ iCounter ] == TRUE ) { gpCharacterPreviousMercPath[ iCounter ] = ClearStrategicPathList( gpCharacterPreviousMercPath[ iCounter ], 0 ); } } gpHelicopterPreviousMercPath = ClearStrategicPathList( gpHelicopterPreviousMercPath, 0 ); gpMilitiaPreviousMercPath = ClearStrategicPathList( gpMilitiaPreviousMercPath, 0 ); } void SelectAllCharactersInSquad( INT8 bSquadNumber ) { INT16 bCounter; BOOLEAN fFirstOne = TRUE; SOLDIERTYPE *pSoldier; // ignore if that squad is empty if( SquadIsEmpty( bSquadNumber ) == TRUE ) { return; } // select nobody & reset the selected list ChangeSelectedInfoChar( -1, TRUE ); // now select all the soldiers that are in this squad for( bCounter = 0; bCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; bCounter++ ) { // is this entry is valid if( gCharactersList[ bCounter ].fValid == TRUE ) { pSoldier = gCharactersList[ bCounter ].usSolID; // if this guy is on that squad or in a vehicle which is assigned to that squad // NOTE: There's no way to select everyone aboard Skyrider with this function... if ( ( pSoldier->bAssignment == bSquadNumber ) || IsSoldierInThisVehicleSquad( pSoldier, bSquadNumber ) ) { if ( fFirstOne ) { // make the first guy in the list who is in this squad the selected info char ChangeSelectedInfoChar( bCounter, FALSE ); // select his sector ChangeSelectedMapSector( pSoldier->sSectorX, pSoldier->sSectorY, pSoldier->bSectorZ ); fFirstOne = FALSE; } SetEntryInSelectedCharacterList( bCounter ); } } } } BOOLEAN CanDrawSectorCursor( void ) { if( ( fShowTownInfo == FALSE ) && ( ghTownMineBox == -1 ) && ( fShowUpdateBox == FALSE ) && ( GetNumberOfMercsInUpdateList() == 0 ) && ( sSelectedMilitiaTown == 0 ) && ( gfMilitiaPopupCreated == FALSE ) && ( gfStartedFromMapScreen == FALSE ) && ( fShowMapScreenMovementList == FALSE ) && ( ghMoveBox == - 1 ) && ( fMapInventoryItem == FALSE ) ) { return( TRUE ); } return( FALSE ); } void RestoreMapSectorCursor( INT16 sMapX, INT16 sMapY ) { INT16 sScreenX, sScreenY; Assert( ( sMapX >= 1 ) && ( sMapX <= 16 ) ); Assert( ( sMapY >= 1 ) && ( sMapY <= 16 ) ); GetScreenXYFromMapXY( sMapX, sMapY, &sScreenX, &sScreenY ); sScreenY -= 1; RestoreExternBackgroundRect( sScreenX, sScreenY, UI_MAP.GridSize.iX + 1, UI_MAP.GridSize.iY + 1); } void RequestToggleMercInventoryPanel( void ) { if( IsMapScreenHelpTextUp() ) { // stop mapscreen text StopMapScreenHelpText( ); return; } if ( ( GetSelectedDestChar() != -1) || fPlotForHelicopter || fPlotForMilitia ) { AbortMovementPlottingMode( ); } if ( !CanToggleSelectedCharInventory() ) { return; } if( fShowDescriptionFlag == TRUE ) { // turn off item description DeleteItemDescriptionBox( ); } else { // toggle inventory mode fShowInventoryFlag = !fShowInventoryFlag; // set help text for item glow region if( fShowInventoryFlag ) { SetRegionFastHelpText( &gCharInfoHandRegion, pMiscMapScreenMouseRegionHelpText[ 2 ] ); } else { // Headrock. New line forces InvBottom rerender when the inventory is opened and closed. fEndShowInventoryFlag = TRUE; RenderMapScreenInterfaceBottom ( TRUE ); SetRegionFastHelpText( &gCharInfoHandRegion, pMiscMapScreenMouseRegionHelpText[ 0 ] ); } } fTeamPanelDirty = TRUE; } void RequestContractMenu( void ) { if( IsMapScreenHelpTextUp() ) { // stop mapscreen text StopMapScreenHelpText( ); return; } if( gfPreBattleInterfaceActive == TRUE ) { return; } if ( ( GetSelectedDestChar() != -1) || fPlotForHelicopter || fPlotForMilitia ) { AbortMovementPlottingMode( ); } // in case we have multiple guys selected, turn off everyone but the guy we're negotiating with ChangeSelectedInfoChar( bSelectedInfoChar, TRUE ); if ( CanExtendContractForCharSlot( bSelectedInfoChar ) ) { // create RebuildContractBoxForMerc( gCharactersList[ bSelectedInfoChar ].usSolID ); // reset selected characters ResetAllSelectedCharacterModes( ); bSelectedContractChar = bSelectedInfoChar; giContractHighLine = bSelectedContractChar; // if not triggered internally if ( CheckIfSalaryIncreasedAndSayQuote( gCharactersList[ bSelectedInfoChar ].usSolID, TRUE ) == FALSE ) { // show contract box fShowContractMenu = TRUE; // stop any dialogue by character StopAnyCurrentlyTalkingSpeech( ); } //fCharacterInfoPanelDirty = TRUE; } else { // reset selected characters ResetAllSelectedCharacterModes( ); } } void ChangeCharacterListSortMethod( INT32 iValue ) { Assert( iValue >= 0 ); Assert( iValue < MAX_SORT_METHODS ); if( IsMapScreenHelpTextUp() ) { // stop mapscreen text StopMapScreenHelpText( ); return; } if( gfPreBattleInterfaceActive == TRUE ) { return; } // not in popup or item in hand if( InItemStackPopup( ) || InSectorStackPopup( ) || InKeyRingPopup( ) || gpItemPointer != NULL ) { return; } if ( ( GetSelectedDestChar() != -1) || fPlotForHelicopter || fPlotForMilitia ) { AbortMovementPlottingMode( ); } if(iValue == 0 && _KeyDown( ALT ) ) iValue = 6; if(iValue == giSortStateForMapScreenList && giSortOrderAscending == TRUE) giSortOrderAscending = FALSE; else if(iValue == giSortStateForMapScreenList && giSortOrderAscending == FALSE) giSortOrderAscending = TRUE; giSortStateForMapScreenList = iValue; SortListOfMercsInTeamPanel( TRUE, giSortOrderAscending ); } void MapscreenMarkButtonsDirty() { // redraw buttons MarkButtonsDirty( ); // if border buttons are created if( !fShowMapInventoryPool ) { // if the attribute assignment menu is showing if ( fShowAttributeMenu ) { // don't redraw the town button, it would wipe out a chunk of the attribute menu UnMarkButtonDirty( giMapBorderButtons[ MAP_BORDER_TOWN_BTN ] ); } } } // HEADROCK HAM 3.6: Get a total of all merc salaries. Used for the new Daily Expenses display. INT32 GetTotalContractExpenses ( void ) { if (gGameExternalOptions.ubIncludeContractsInExpenses == 0) { // Contract costs are excluded. return (0); } UINT8 ubCounter = 0; SOLDIERTYPE *pSoldier; INT32 iTotalCost = 0; while(gCharactersList[ubCounter].fValid) { pSoldier = gCharactersList[ ubCounter ].usSolID; // salary if( pSoldier->ubWhatKindOfMercAmI == MERC_TYPE__AIM_MERC ) { if (gGameExternalOptions.ubIncludeContractsInExpenses == 2) { // daily rate if( pSoldier->bTypeOfLastContract == CONTRACT_EXTEND_2_WEEK ) { iTotalCost += ( gMercProfiles[ pSoldier->ubProfile ].uiBiWeeklySalary / 14 ); } else if( pSoldier->bTypeOfLastContract == CONTRACT_EXTEND_1_WEEK ) { iTotalCost += ( gMercProfiles[ pSoldier->ubProfile ].uiWeeklySalary / 7 ); } else { iTotalCost += gMercProfiles[ pSoldier->ubProfile ].sSalary; } } } else if(pSoldier->bAssignment != ASSIGNMENT_DEAD && pSoldier->bAssignment != ASSIGNMENT_POW) { iTotalCost += gMercProfiles[ pSoldier->ubProfile ].sSalary; } ubCounter++; } return (iTotalCost); } #ifdef JA2UB void HandleWhenPlayerHasNoMercsAndNoLaptop() { const UINT8 ubNumLoopsToDisplay=50; if( gJa25SaveStruct.ubDisplayPlayerLostMsgBox == 0 || gJa25SaveStruct.ubDisplayPlayerLostMsgBox >= ubNumLoopsToDisplay || guiCurrentScreen == MSG_BOX_SCREEN ) { return; } gJa25SaveStruct.ubDisplayPlayerLostMsgBox += 1; if( gJa25SaveStruct.ubDisplayPlayerLostMsgBox == ubNumLoopsToDisplay ) { DoMapMessageBox( MSG_BOX_BASIC_STYLE, zNewTacticalMessages[ TCTL_MSG__PLAYER_LOST_SHOULD_RESTART ], MAP_SCREEN, MSG_BOX_FLAG_OK, NULL ); } } #endif // Flugente: militia movement BOOLEAN RequestGiveMilitiaNewDestination( void ) { // are we even allowed to give militia orders in this sector? if ( !CanGiveStrategicMilitiaMoveOrder( sSelMapX, sSelMapY ) ) { ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, szMilitiaStrategicMovementText[0] ); return FALSE; } // if there are no more static militia in this sector, but a group is, select the last group BOOLEAN fGroupAlreadyExists = FALSE; if ( MilitiaInSectorOfRankStationary( sSelMapX, sSelMapY, GREEN_MILITIA ) + MilitiaInSectorOfRankStationary( sSelMapX, sSelMapY, REGULAR_MILITIA ) + MilitiaInSectorOfRankStationary( sSelMapX, sSelMapY, ELITE_MILITIA ) == 0 ) { UINT8 groupid = 0; if ( GetLastMilitiaGroupInSector( sSelMapX, sSelMapY, groupid ) ) { INT16 internalslot = GetMilitiaPathSlot( groupid ); if ( internalslot > -1 ) { fGroupAlreadyExists = TRUE; gMilitiaGroupId = internalslot; gNewMilitiaGroupId = gMilitiaPath[gMilitiaGroupId].sGroupid; // yes, we intentionally use a different sector number here gMilitiaPlotStartSector = CALCULATE_STRATEGIC_INDEX( sSelMapX, sSelMapY ); } } } // if we don't use a previously existing group and can't creae a new one, abort if ( !fGroupAlreadyExists && !MilitiaPlotStart( ) ) { return FALSE; } // start plotting fPlotForMilitia = TRUE; CreateMilitiaGroupBox(); // change cursor to the helicopter SetUpCursorForStrategicMap( ); // remember the helicopter's current path so we can restore it if need be gpMilitiaPreviousMercPath = CopyPaths( gMilitiaPath[gMilitiaGroupId].path, gpMilitiaPreviousMercPath ); return TRUE; } void SetUpMilitiaForMovement( ) { // nothing to do atm } // upon starting a game/loading from an old version, set up the data void MilitiaPlotInit() { static BOOLEAN fCleanOnStart = TRUE; if ( fCleanOnStart ) { // start new path list gpMilitiaPreviousMercPath = (PathStPtr)MemAlloc( sizeof(PathSt) ); memset( gpMilitiaPreviousMercPath, 0, sizeof(PathSt) ); gpMilitiaPreviousMercPath->fSpeed = NORMAL_MVT; gpMilitiaPreviousMercPath->uiSectorId = 0; gpMilitiaPreviousMercPath->uiEta = GetWorldTotalMin( ); gpMilitiaPreviousMercPath->pNext = NULL; gpMilitiaPreviousMercPath->pPrev = NULL; for ( int i = 0; i < MILITIA_PATROLS_MAX; ++i ) { gMilitiaPath[i].path = (PathStPtr)MemAlloc( sizeof(PathSt) ); memset( gMilitiaPath[i].path, 0, sizeof(PathSt) ); gMilitiaPath[i].path->fSpeed = NORMAL_MVT; gMilitiaPath[i].path->uiSectorId = 0; gMilitiaPath[i].path->uiEta = GetWorldTotalMin( ); gMilitiaPath[i].path->pNext = NULL; gMilitiaPath[i].path->pPrev = NULL; gMilitiaPath[i].sGroupid = -1; } fCleanOnStart = FALSE; SetUpMilitiaForMovement( ); } } // when starting to plot, set up things BOOLEAN MilitiaPlotStart( ) { // The number of militia groups is limited. Loop over all militia group, eliminate emtpy ones, and then use the first one. If none exists, we have to abort plotting for now BOOLEAN found = FALSE; for ( int groupid = 0; groupid < MILITIA_PATROLS_MAX; ++groupid ) { if ( gMilitiaPath[groupid].sGroupid > -1 ) { GROUP* pGroup = GetGroup( (UINT8)gMilitiaPath[groupid].sGroupid ); // if this group exists, is indeed militia but has no members, erase it and its path if ( pGroup && pGroup->usGroupTeam == MILITIA_TEAM && pGroup->ubGroupSize == 0 ) { gMilitiaPath[groupid].path = ClearStrategicPathList( gMilitiaPath[groupid].path, (UINT8)gMilitiaPath[groupid].sGroupid ); RemovePGroup( pGroup ); gMilitiaPath[groupid].sGroupid = -1; } else { // otherwise, if this isn't a valid group, set the id to -1 nevertheless if ( !pGroup ) { gMilitiaPath[groupid].sGroupid = -1; } } } if ( !found && gMilitiaPath[groupid].sGroupid < 0 ) { found = TRUE; gMilitiaGroupId = groupid; gMilitiaPath[groupid].path = (PathStPtr)MemAlloc( sizeof(PathSt) ); memset( gMilitiaPath[groupid].path, 0, sizeof(PathSt) ); gMilitiaPath[groupid].path->fSpeed = NORMAL_MVT; gMilitiaPath[groupid].path->uiSectorId = 0; gMilitiaPath[groupid].path->uiEta = GetWorldTotalMin( ); gMilitiaPath[groupid].path->pNext = NULL; gMilitiaPath[groupid].path->pPrev = NULL; } } // no free slot - abort if ( !found ) return FALSE; SECTORINFO *pSector = &SectorInfo[SECTOR( sSelMapX, sSelMapY )]; if ( !pSector ) return FALSE; // as group size will be cut to MAX_STRATEGIC_ENEMY_GROUP_SIZE, see how many troops are allowed and reduce sector count accordingly UINT16 greens = pSector->ubNumberOfCivsAtLevel[0]; UINT16 regulars = pSector->ubNumberOfCivsAtLevel[1]; UINT16 elites = pSector->ubNumberOfCivsAtLevel[2]; // when we start plotting, the group is still empty - we add militia later GROUP* pGroup = CreateNewMilitiaGroupDepartingFromSector( SECTOR( sSelMapX, sSelMapY ), greens, regulars, elites ); pSector->ubNumberOfCivsAtLevel[0] -= greens; pSector->ubNumberOfCivsAtLevel[1] -= regulars; pSector->ubNumberOfCivsAtLevel[2] -= elites; gMilitiaPath[gMilitiaGroupId].sGroupid = pGroup->ubGroupID; gNewMilitiaGroupId = pGroup->ubGroupID; // yes, we intentionally use a different sector number here gMilitiaPlotStartSector = CALCULATE_STRATEGIC_INDEX( sSelMapX, sSelMapY ); gMilitiaPath[gMilitiaGroupId].path->uiSectorId = gMilitiaPlotStartSector; return TRUE; } // when finished plotting, set up other things void MilitiaplotFinish() { gMilitiaPlotStartSector = 0; // destroy militia group if empty and not moving if ( gMilitiaPath[gMilitiaGroupId].sGroupid > -1 ) { GROUP* pGroup = GetGroup( (UINT8)gMilitiaPath[gMilitiaGroupId].sGroupid ); // if the group has no members, or if it is not given any movement orders, destroy it if ( pGroup && pGroup->usGroupTeam == MILITIA_TEAM && (!pGroup->ubGroupSize || (pGroup->ubNextX == pGroup->ubSectorX && pGroup->ubNextY == pGroup->ubSectorY) || (pGroup->ubNextX == 0 && pGroup->ubNextY == 0) ) ) { StrategicAddMilitiaToSector( pGroup->ubSectorX, pGroup->ubSectorY, GREEN_MILITIA, pGroup->pEnemyGroup->ubNumAdmins ); StrategicAddMilitiaToSector( pGroup->ubSectorX, pGroup->ubSectorY, REGULAR_MILITIA, pGroup->pEnemyGroup->ubNumTroops ); StrategicAddMilitiaToSector( pGroup->ubSectorX, pGroup->ubSectorY, ELITE_MILITIA, pGroup->pEnemyGroup->ubNumElites ); RemovePGroup( pGroup ); gMilitiaPath[gMilitiaGroupId].sGroupid = -1; gMilitiaGroupId = 0; gNewMilitiaGroupId = 0; } } } // if this group is a militia travel group, return its slot, othewise return -1 INT16 GetMilitiaPathSlot( UINT8 uGroupId ) { for ( INT32 iCounter = 0; iCounter < MILITIA_PATROLS_MAX; ++iCounter ) { if ( gMilitiaPath[iCounter].sGroupid == uGroupId ) return iCounter; } return -1; } void DeleteAllMilitiaPaths() { // empty out the vehicle list if ( gMilitiaPath ) { for ( INT32 iCounter = 0; iCounter < MILITIA_PATROLS_MAX; ++iCounter ) { if ( gMilitiaPath[iCounter].path ) { // toast the path gMilitiaPath[iCounter].path = ClearStrategicPathList( gMilitiaPath[iCounter].path, 0 ); MemFree( gMilitiaPath[iCounter].path ); } gMilitiaPath[iCounter].sGroupid = -1; } } } // return the last militia group in this sector, group id will be stored in arId. return FALSE if none found BOOLEAN GetLastMilitiaGroupInSector( INT16 sMapX, INT16 sMapY, UINT8& arId ) { BOOLEAN fFound = FALSE; GROUP *pGroup = gpGroupList; while ( pGroup ) { if ( pGroup->usGroupTeam == MILITIA_TEAM && pGroup->ubSectorX == sMapX && pGroup->ubSectorY == sMapY ) { arId = pGroup->ubGroupID; fFound = TRUE; } pGroup = pGroup->next; } if ( fFound ) return TRUE; return FALSE; } // are we allowed to give militia in this sector a strategic move order? BOOLEAN CanGiveStrategicMilitiaMoveOrder( INT16 sMapX, INT16 sMapY ) { // not allowed if setting says so if ( !gGameExternalOptions.fMilitiaStrategicCommand ) return FALSE; // if we posess and staff the militia HQ, we can command militia everywhere if ( MercStaffsMilitaryHQ( ) ) return TRUE; // town this sector is a part of UINT8 townid = GetTownIdForSector( sMapX, sMapY ); // we require mercs to 'give' the orders to militia. // For simplicity, we require the mercs simply to not be in a coma, asleep is okay (otherwsie we have to wake them up, give the order, set them asleep again - tedious!). // Mercs can give these orders if one of these is true // 1. they are in the same sector // 2. they are in the same town (otherwise we'd have to do tedious town-internal travel) // 3. they are a radio operator in an adjacent sector // 4. they are a radio operator in a sector adjacent to the militia's town // 5. they are a radio operator in a town adjacent to the militia's sector SoldierID id = gTacticalStatus.Team[OUR_TEAM].bFirstID; SoldierID lastid = gTacticalStatus.Team[OUR_TEAM].bLastID; for ( ; id <= lastid; ++id) { SOLDIERTYPE *pSoldier = id; if ( pSoldier && pSoldier->bActive && pSoldier->stats.bLife >= OKLIFE ) { BOOLEAN fRadioOperator = pSoldier->CanUseRadio( FALSE ); INT16 sectordist = abs( sMapX - pSoldier->sSectorX ) + abs( sMapY - pSoldier->sSectorY ); // 1. + 3. if ( fRadioOperator >= sectordist ) return TRUE; UINT8 soldiertownid = GetTownIdForSector( pSoldier->sSectorX, pSoldier->sSectorY ); // 2. if ( townid != BLANK_SECTOR && townid == soldiertownid ) return TRUE; // 4. if ( fRadioOperator && soldiertownid == BLANK_SECTOR && townid != BLANK_SECTOR ) { // check whether adjacent sectors belong to the town we search for if ( GetTownIdForSector( min( pSoldier->sSectorX + 1, MAP_WORLD_X - 2), pSoldier->sSectorY ) == townid ) return TRUE; if ( GetTownIdForSector( max( pSoldier->sSectorX - 1, 1 ), pSoldier->sSectorY ) == townid ) return TRUE; if ( GetTownIdForSector( pSoldier->sSectorX, min( pSoldier->sSectorY + 1, MAP_WORLD_Y - 2 ) ) == townid ) return TRUE; if ( GetTownIdForSector( pSoldier->sSectorX, max( pSoldier->sSectorY - 1, 1 ) ) == townid ) return TRUE; } // 5. if ( fRadioOperator && townid == BLANK_SECTOR && soldiertownid != BLANK_SECTOR ) { // check whether adjacent sectors belong to the town we search for if ( GetTownIdForSector( min( sMapX + 1, MAP_WORLD_X - 2 ), sMapY ) == soldiertownid ) return TRUE; if ( GetTownIdForSector( max( sMapX - 1, 1 ), sMapY ) == soldiertownid ) return TRUE; if ( GetTownIdForSector( sMapX, min( sMapY + 1, MAP_WORLD_Y - 2 ) ) == soldiertownid ) return TRUE; if ( GetTownIdForSector( sMapX, max( sMapY - 1, 1 ) ) == soldiertownid ) return TRUE; } } } return FALSE; } // Flugente: bandaging during retreat void RetreatBandageCallback( UINT8 ubResult ) { HandleRetreatBandaging( ); } // Bob: moved here to expand what CHRISL did // try to move all items in sector into the vehicle inventory. Try to use LBE items in sector to store as much stuff as possible void moveSectorInventoryToVehicle(SOLDIERTYPE *pSoldier) { fillCurrentSectorLBEItems(pSoldier); // puts LBE items in vehicle // ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"---------------------------------------------"); // ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Moving remaining sector items into the car..."); moveCurrentSectorItemsToVehicle(pSoldier); // puts remaining items in vehicle fTeamPanelDirty = TRUE; fMapPanelDirty = TRUE; fInterfacePanelDirty = DIRTYLEVEL2; } // fills all empty LBE items in currebt sector with other sector items then tries to place all LBE items in the vehicle (pSoldier) void fillCurrentSectorLBEItems(SOLDIERTYPE *pSoldier) { std::vector LBEObjects; // list of LBE objects found in sector // build a list of LBE objects in sector. Stacks are split into separate items. for (unsigned int i = 0; i < pInventoryPoolList.size(); i++) { WORLDITEM & stack = pInventoryPoolList[i]; OBJECTTYPE & stackContents = pInventoryPoolList[i].object; INVTYPE & stackContentType = Item[stackContents.usItem]; if ( stack.fExists == TRUE && stack.usFlags & WORLD_ITEM_REACHABLE && stackContentType.usItemClass == IC_LBEGEAR ) { for (int j = 0; j< stackContents.ubNumberOfObjects; j++) { OBJECTTYPE * LBEObject = new OBJECTTYPE(); stackContents.MoveThisObjectTo(*LBEObject, 1); LBEObjects.push_back(LBEObject); } } } // fill the LBE items in the list with items from current sector then try to put them in the vehicle for (std::vector::iterator LBEItemIter = LBEObjects.begin(); LBEItemIter != LBEObjects.end(); LBEItemIter++) { OBJECTTYPE* LBEItem = *LBEItemIter; INVTYPE LBEItemType = Item[LBEItem->usItem]; LBETYPE LBEType = LoadBearingEquipment[LBEItemType.ubClassIndex]; //ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"==================================="); //ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Filling: %s", LBEItemType.szItemName); if ( LBEItem->IsActiveLBE(0) == FALSE ) { // init LBE data CreateLBE(LBEItem, pSoldier->ubID, LBEType.lbePocketIndex.size()); // stuff it full of sector items fillLBEWithSectorItems(LBEItem); } // try to put the LBE item in the vehicle, if we fail then drop it. if (placeItemInVehicle(pSoldier, *LBEItem) == false) { // ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Dropped %s on the ground", LBEItemType.szItemName); AutoPlaceObjectToWorld(pSoldier, LBEItem); } else { // ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Moved %s into the car", LBEItemType.szItemName); } } } // fills LBEObject with items from currently loaded sector. Assumes that LBEObject contains only one item void fillLBEWithSectorItems(OBJECTTYPE * LBEObject) { LBENODE* pLBE = LBEObject->GetLBEPointer(0); INVTYPE LBEItemType = Item[LBEObject->usItem]; LBETYPE LBEType = LoadBearingEquipment[LBEItemType.ubClassIndex]; int movedItemsTotal = 0; for (int i = 0; i < LBEType.lbePocketIndex.size(); i++) { INT16 lbePocket = LBEType.lbePocketIndex[i]; if (lbePocket == 0) continue; POCKETTYPE lbePocketType = LBEPocketType[lbePocket]; for (auto itemIterator = pInventoryPoolList.begin(); itemIterator != pInventoryPoolList.end(); itemIterator++) { WORLDITEM * sectorItemStack = &(*itemIterator); OBJECTTYPE * sectorItemObject = &(itemIterator->object); INVTYPE sectorItemType = Item[sectorItemObject->usItem]; if (sectorItemStack->fExists && sectorItemStack->usFlags & WORLD_ITEM_REACHABLE && sectorItemType.usItemClass != IC_LBEGEAR && sectorItemObject->usItem > 0) { int pocketCapacity = lbePocketType.ItemCapacityPerSize[sectorItemType.ItemSize]; if (pocketCapacity > 0) { OBJECTTYPE * pocketItemObject = new OBJECTTYPE(); int movedItems = (sectorItemObject->ubNumberOfObjects > pocketCapacity) ? pocketCapacity : sectorItemObject->ubNumberOfObjects; int remainingItems = sectorItemObject->MoveThisObjectTo(*pocketItemObject, movedItems); //ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Moved %s * %i (%i remaining) into %s (%s)", sectorItemType.szItemName, movedItems, remainingItems, LBEItemType.szItemName, lbePocketType.pName); pLBE->inv[i] = (*pocketItemObject); movedItemsTotal += movedItems; break; } } } } if (movedItemsTotal == 0) { DestroyLBE(LBEObject); } } void moveCurrentSectorItemsToVehicle(SOLDIERTYPE *pSoldier) { for (unsigned int i = 0; i < pInventoryPoolList.size(); i++) { if (pInventoryPoolList[i].fExists == TRUE && (pInventoryPoolList[i].usFlags & WORLD_ITEM_REACHABLE)) { placeItemInVehicle(pSoldier, pInventoryPoolList[i]); } } } bool placeItemInVehicle(SOLDIERTYPE *pSoldier, WORLDITEM &worldItem) { return placeItemInVehicle(pSoldier, worldItem.object); } bool placeItemInVehicle(SOLDIERTYPE *pSoldier, OBJECTTYPE &item) { if (item.usItem < 1) return false; INVTYPE sectorItemType = Item[item.usItem]; for (int x = 0; x < NUM_INV_SLOTS && item.ubNumberOfObjects > 0; x++) { if (vehicleInv[x] == FALSE) continue; if (pSoldier->inv[x].exists() == true) { if (pSoldier->inv[x].usItem != item.usItem) { continue; } else { //ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Stacking %s * %i in car slot %i", sectorItemType.szItemName, item.ubNumberOfObjects, x); pSoldier->inv[x].AddObjectsToStack(item, -1, pSoldier, x); } } else { //ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Placing %s * %i in car slot %i", sectorItemType.szItemName, item.ubNumberOfObjects, x); int result = item.MoveThisObjectTo(pSoldier->inv[x], -1, pSoldier, x); } if (item.ubNumberOfObjects < 0) { break; } } return (item.ubNumberOfObjects == 0); } bool isWidescreenUI(void) { return (iResolution == _1280x720); } void initMapViewAndBorderCoordinates(void) { if (isWidescreenUI()) { MAP_FONT = FONT12ARIAL; ETA_FONT = BLOCKFONT2; UI_MAP.GridSize = { 43, 35 }; UI_MAP.BorderRegion = {SCREEN_WIDTH - 764, 0, 764, 605}; // mbs_1280x720.sti UI_MAP.ViewRegion = { UI_MAP.BorderRegion.x + 9, UI_MAP.BorderRegion.y + 10, UI_MAP.GridSize.iX * MAXIMUM_VALID_X_COORDINATE, UI_MAP.GridSize.iY * MAXIMUM_VALID_Y_COORDINATE + 27 }; // Strategic map numbers and letters. Numbers are on the horizontal line. UI_MAP.Numbers = { UI_MAP.BorderRegion.x + 53, UI_MAP.BorderRegion.y + 19, UI_MAP.GridSize.iX, GetFontHeight(MAP_FONT) }; UI_MAP.Alphabet = { UI_MAP.BorderRegion.x + 24, UI_MAP.BorderRegion.y + 44, GetFontHeight(MAP_FONT), UI_MAP.GridSize.iY }; UI_MAP.LevelString = { UI_MAP.ViewRegion.x + UI_MAP.ViewRegion.width / 2, UI_MAP.ViewRegion.y + UI_MAP.ViewRegion.height - 25 }; // standard ETA box UI_MAP.ETA.Clock_X = UI_MAP.ViewRegion.x + UI_MAP.ViewRegion.width / 2; UI_MAP.ETA.Start_Y = UI_MAP.ViewRegion.y + UI_MAP.ViewRegion.height - 15; UI_MAP.ETA.Hour_X = UI_MAP.ETA.Clock_X + 38; UI_MAP.ETA.Min_X = UI_MAP.ETA.Clock_X + 54; // Helicopter ETA box UI_MAP.HeliETA.PopupBox = { UI_MAP.ViewRegion.x + UI_MAP.ViewRegion.width / 2, UI_MAP.ViewRegion.y + UI_MAP.ViewRegion.height - 100, 120, 76 }; UI_MAP.HeliETA.Upper_Popup_Y = (50 + iScreenHeightOffset - 100); UI_MAP.HeliETA.Alternate_Height = 97; } else if (iResolution < _800x600) { MAP_FONT = BLOCKFONT2; ETA_FONT = BLOCKFONT2; UI_MAP.GridSize = { 21, 18 }; UI_MAP.BorderRegion = { SCREEN_WIDTH - xResOffset - 380, yResOffset, 380, 360 }; UI_MAP.ViewRegion = { UI_MAP.BorderRegion.x + 9, UI_MAP.BorderRegion.y + 10, UI_MAP.GridSize.iX * MAXIMUM_VALID_X_COORDINATE, UI_MAP.GridSize.iY * MAXIMUM_VALID_Y_COORDINATE + 10 }; // Strategic map numbers and letters. Numbers are on the horizontal line. UI_MAP.Numbers = { UI_MAP.BorderRegion.x + 31, UI_MAP.BorderRegion.y + 11, UI_MAP.GridSize.iX, GetFontHeight(MAP_FONT) }; UI_MAP.Alphabet = { UI_MAP.BorderRegion.x + 15, UI_MAP.BorderRegion.y + 29, GetFontHeight(MAP_FONT), UI_MAP.GridSize.iY }; UI_MAP.LevelString = { UI_MAP.ViewRegion.x + UI_MAP.ViewRegion.width / 2, (SCREEN_HEIGHT - 175) }; // standard ETA box UI_MAP.ETA.Clock_X = UI_MAP.ViewRegion.x + UI_MAP.ViewRegion.width / 2; UI_MAP.ETA.Start_Y = UI_MAP.ViewRegion.y + UI_MAP.ViewRegion.height - 15; UI_MAP.ETA.Hour_X = UI_MAP.ETA.Clock_X + 38; UI_MAP.ETA.Min_X = UI_MAP.ETA.Clock_X + 54; // Helicopter ETA box UI_MAP.HeliETA.PopupBox = { (400 + iScreenWidthOffset), (250 + iScreenHeightOffset), 120, 68 }; UI_MAP.HeliETA.Upper_Popup_Y = (50 + iScreenHeightOffset); UI_MAP.HeliETA.Alternate_Height = 74; } else if (iResolution < _1024x768) { MAP_FONT = BLOCKFONT2; ETA_FONT = BLOCKFONT2; UI_MAP.GridSize = { 30, 25 }; UI_MAP.BorderRegion = { SCREEN_WIDTH - xResOffset - 540, yResOffset, 540, 479 }; UI_MAP.ViewRegion = { UI_MAP.BorderRegion.x + 9, UI_MAP.BorderRegion.y + 10, UI_MAP.GridSize.iX * MAXIMUM_VALID_X_COORDINATE, UI_MAP.GridSize.iY * MAXIMUM_VALID_Y_COORDINATE + 17 }; // Strategic map numbers and letters. Numbers are on the horizontal line. UI_MAP.Numbers = { UI_MAP.BorderRegion.x + 38, UI_MAP.BorderRegion.y + 15, UI_MAP.GridSize.iX, GetFontHeight(MAP_FONT) }; UI_MAP.Alphabet = { UI_MAP.BorderRegion.x + 19, UI_MAP.BorderRegion.y + 36, GetFontHeight(MAP_FONT), UI_MAP.GridSize.iY }; UI_MAP.LevelString = { UI_MAP.ViewRegion.x + UI_MAP.ViewRegion.width / 2, UI_MAP.ViewRegion.y + (600 - 175) }; // standard ETA box UI_MAP.ETA.Clock_X = UI_MAP.ViewRegion.x + UI_MAP.ViewRegion.width / 2; UI_MAP.ETA.Start_Y = UI_MAP.ViewRegion.y + UI_MAP.ViewRegion.height - 15; UI_MAP.ETA.Hour_X = UI_MAP.ETA.Clock_X + 38; UI_MAP.ETA.Min_X = UI_MAP.ETA.Clock_X + 54; // Helicopter ETA box UI_MAP.HeliETA.PopupBox = { (400 + iScreenWidthOffset), (250 + iScreenHeightOffset + 58), 120, 68 }; UI_MAP.HeliETA.Upper_Popup_Y = (50 + iScreenHeightOffset - 40); UI_MAP.HeliETA.Alternate_Height = 74; } else { MAP_FONT = FONT12ARIAL; ETA_FONT = FONT12ARIAL; UI_MAP.GridSize = { 43, 35 }; UI_MAP.BorderRegion = { SCREEN_WIDTH - xResOffset - 764, yResOffset, 764, 647 }; UI_MAP.ViewRegion = { UI_MAP.BorderRegion.x + 9, UI_MAP.BorderRegion.y + 10, UI_MAP.GridSize.iX * MAXIMUM_VALID_X_COORDINATE, UI_MAP.GridSize.iY * MAXIMUM_VALID_Y_COORDINATE + 27 }; // Strategic map numbers and letters. Numbers are on the horizontal line. UI_MAP.Numbers = { UI_MAP.BorderRegion.x + 53, UI_MAP.BorderRegion.y + 19, UI_MAP.GridSize.iX, GetFontHeight(MAP_FONT) }; UI_MAP.Alphabet = { UI_MAP.BorderRegion.x + 24, UI_MAP.BorderRegion.y + 44, GetFontHeight(MAP_FONT), UI_MAP.GridSize.iY }; UI_MAP.LevelString = { UI_MAP.ViewRegion.x + UI_MAP.ViewRegion.width / 2, UI_MAP.ViewRegion.y + UI_MAP.ViewRegion.height - 25 }; // standard ETA box UI_MAP.ETA.Clock_X = UI_MAP.ViewRegion.x + UI_MAP.ViewRegion.width / 2; UI_MAP.ETA.Start_Y = UI_MAP.ViewRegion.y + UI_MAP.ViewRegion.height - 15; UI_MAP.ETA.Hour_X = UI_MAP.ETA.Clock_X + 38; UI_MAP.ETA.Min_X = UI_MAP.ETA.Clock_X + 54; // Helicopter ETA box UI_MAP.HeliETA.PopupBox = { (400 + iScreenWidthOffset), (250 + iScreenHeightOffset + 120), 120, 76 }; UI_MAP.HeliETA.Upper_Popup_Y = (50 + iScreenHeightOffset - 100); UI_MAP.HeliETA.Alternate_Height = 97; } }