mirror of
https://github.com/1dot13/source.git
synced 2026-07-22 13:40:22 +02:00
Updates/Improvements (by Sevenfm) 1. Quick inventory items: Press [ALT] + [1..0] for quick access to predefined items in tactical (ja2_options.ini: QUICK_ITEM_0 to QUICK_ITEM_9) Press [ALT] + [`] (tilde key left to [1]) to put item back to inventory and switch hands. The item will be put in the same slot it was taken from (unless it was stacked or game was reloaded). 2. Also a few quick hotkeys: [ALT] + [q] - switch to sling (same as [SHIFT] + [k]) [CTRL] + [q] - switch hands [SHIFT] + [q] - drop item from main hand to the ground Additional info: -some hotkeys do not work in cheat mode -only NIV -only one-handed items supported -stacked items currently not supported -remembered item slot is lost when you reload game 3. A few small fixes for dynamic tooltips and other things git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@7130 3b4a5df2-a311-0410-b5c6-a8a6f20db521
6665 lines
212 KiB
C++
6665 lines
212 KiB
C++
#ifdef PRECOMPILEDHEADERS
|
|
#include "Tactical All.h"
|
|
#else
|
|
#include "builddefines.h"
|
|
#include <stdio.h>
|
|
#include <stdarg.h>
|
|
#include <time.h>
|
|
#include "sgp.h"
|
|
#include "gameloop.h"
|
|
#include "himage.h"
|
|
#include "vobject.h"
|
|
#include "sysutil.h"
|
|
#include "overhead.h"
|
|
#include "mousesystem.h"
|
|
#include "Button System.h"
|
|
#include "interface.h"
|
|
#include "vsurface.h"
|
|
#include "wcheck.h"
|
|
#include "input.h"
|
|
#include "Handle UI.h"
|
|
#include "Animation Control.h"
|
|
#include "Animation Data.h"
|
|
#include "renderworld.h"
|
|
#include "sys globals.h"
|
|
#include "cursors.h"
|
|
#include "radar screen.h"
|
|
#include "worldman.h"
|
|
#include "Font Control.h"
|
|
#include "render dirty.h"
|
|
#include "utilities.h"
|
|
#include "interface cursors.h"
|
|
#include "Sound Control.h"
|
|
#include "lighting.h"
|
|
#include "Interface Panels.h"
|
|
#include "pathai.h"
|
|
#include "vobject_blitters.h"
|
|
#include "faces.h"
|
|
#include "Handle UI Plan.h"
|
|
#include "interface control.h"
|
|
#include "interface items.h"
|
|
#include "soldier profile.h"
|
|
#include "MercTextBox.h"
|
|
#include "soldier functions.h"
|
|
#include "cursor control.h"
|
|
#include "handle doors.h"
|
|
#include "keys.h"
|
|
#include "text.h"
|
|
#include "points.h"
|
|
#include "soldier macros.h"
|
|
#include "game clock.h"
|
|
#include "physics.h"
|
|
#include "Map Screen Interface Map.h"
|
|
#include "line.h"
|
|
#include "Vehicles.h"
|
|
#include "messageboxscreen.h"
|
|
#include "gamesettings.h"
|
|
#include "Squads.h"
|
|
#include "message.h"
|
|
#include "strategicmap.h"
|
|
#include "Queen Command.h"
|
|
// HEADROCK HAM 4: Included for new CTH indicator
|
|
#include "weapons.h"
|
|
#include "Map Screen Interface.h" // added by Flugente for SquadNames
|
|
#include "environment.h"
|
|
// sevenfm: needed for _KeyDown(SHIFT)
|
|
#include "english.h"
|
|
|
|
#endif
|
|
|
|
#include "InterfaceItemImages.h"
|
|
#ifdef JA2UB
|
|
#include "Explosion Control.h"
|
|
#include "Ja25_Tactical.h"
|
|
#include "Ja25 Strategic Ai.h"
|
|
#include "MapScreen Quotes.h"
|
|
#include "email.h"
|
|
#include "interface Dialogue.h"
|
|
#include "mercs.h"
|
|
#include "ub_config.h"
|
|
#endif
|
|
|
|
#include "connect.h"
|
|
//const UINT32 INTERFACE_START_X = 0;
|
|
//const UINT32 INTERFACE_START_Y = ( SCREEN_HEIGHT - INTERFACE_HEIGHT );
|
|
//const UINT32 INV_INTERFACE_START_Y = ( SCREEN_HEIGHT - INV_INTERFACE_HEIGHT );
|
|
|
|
int INTERFACE_WIDTH;// = 640;
|
|
int INTERFACE_HEIGHT;// = 120;
|
|
int INV_INTERFACE_HEIGHT;// = 140;
|
|
|
|
int INTERFACE_START_X;// = 0;
|
|
int INTERFACE_START_Y;// = ( SCREEN_HEIGHT - INTERFACE_HEIGHT );
|
|
int INV_INTERFACE_START_Y;// = ( SCREEN_HEIGHT - INV_INTERFACE_HEIGHT );
|
|
|
|
#define ARROWS_X_OFFSET 10
|
|
#define ARROWS_HEIGHT 20
|
|
#define ARROWS_WIDTH 20
|
|
#define UPARROW_Y_OFFSET -30
|
|
#define DOWNARROW_Y_OFFSET -10
|
|
|
|
#define BUTTON_PANEL_WIDTH 78
|
|
#define BUTTON_PANEL_HEIGHT 76
|
|
|
|
HIDDEN_NAMES_VALUES zHiddenNames[500]; //legion2 Jazz
|
|
ENEMY_NAMES_VALUES zEnemyName[500];
|
|
ENEMY_RANK_VALUES zEnemyRank[20]; // Flugente: set this to 20, which should be way enough, as there are only 10 exp levels
|
|
CIV_NAMES_VALUES zCivGroupName[NUM_CIV_GROUPS];
|
|
|
|
// Flugente: soldier profiles
|
|
SOLDIER_PROFILE_VALUES zSoldierProfile[6][NUM_SOLDIER_PROFILES];
|
|
UINT16 num_found_soldier_profiles[6]; // the correct number is set on reading the xml
|
|
|
|
BACKGROUND_VALUES zBackground[NUM_BACKGROUND]; // Flugente: backgrounds
|
|
|
|
TAUNT_VALUES zTaunt[NUM_TAUNT]; // anv: externalised taunts
|
|
|
|
BOOLEAN gfInMovementMenu = FALSE;
|
|
INT32 giMenuAnchorX, giMenuAnchorY;
|
|
|
|
//*ddd
|
|
//#define PROG_BAR_START_Y 2
|
|
|
|
//**ddd{
|
|
//ïîñòàâèòü äåôàéí â 0 åñëè èñïîëüçîâàòü áîëüøîé ïðîãðåññ áàð
|
|
//#define fSmallSizeProgressbar 1
|
|
INT32 HEIGHT_PROGRESSBAR, PROG_BAR_START_Y;
|
|
//ddd}
|
|
|
|
|
|
BOOLEAN gfProgBarActive = FALSE;
|
|
UINT8 gubProgNumEnemies = 0;
|
|
UINT8 gubProgCurEnemy = 0;
|
|
|
|
|
|
UINT32 guiPORTRAITICONS;
|
|
UINT32 guiASSIGNMENTICONS; // Flugente: icons for assignments
|
|
|
|
//UINT32 guiPORTRAITICONS_NV; //legion
|
|
//UINT32 guiPORTRAITICONS_GAS_MASK; //legion
|
|
|
|
// WANNE: Additional face gear file for IMPs
|
|
//UINT32 guiPORTRAITICONS_NV_IMP;
|
|
//UINT32 guiPORTRAITICONS_GAS_MASK_IMP;
|
|
|
|
typedef struct
|
|
{
|
|
UINT32 uiSurface;
|
|
INT8 bCurrentMessage;
|
|
UINT32 uiTimeOfLastUpdate;
|
|
UINT32 uiTimeSinceLastBeep;
|
|
INT8 bAnimate;
|
|
INT8 bYPos;
|
|
BOOLEAN fCreated;
|
|
INT16 sWorldRenderX;
|
|
INT16 sWorldRenderY;
|
|
|
|
} TOP_MESSAGE;
|
|
|
|
|
|
TOP_MESSAGE gTopMessage;
|
|
BOOLEAN gfTopMessageDirty = FALSE;
|
|
|
|
void CreateTopMessage( UINT32 uiSurface, UINT8 ubType, STR16 psString );
|
|
|
|
extern UINT16 GetAnimStateForInteraction( SOLDIERTYPE *pSoldier, BOOLEAN fDoor, UINT16 usAnimState );
|
|
|
|
|
|
MOUSE_REGION gMenuOverlayRegion;
|
|
|
|
|
|
MOUSE_REGION gBottomPanalRegion;
|
|
|
|
UINT16 gusOldSelectedSoldier = NOBODY;
|
|
|
|
// OVerlay ID
|
|
INT32 giPopupSlideMessageOverlay = -1;
|
|
UINT16 gusOverlayPopupBoxWidth, gusOverlayPopupBoxHeight;
|
|
MercPopUpBox gpOverrideMercBox;
|
|
|
|
INT32 giUIMessageOverlay = -1;
|
|
UINT16 gusUIMessageWidth, gusUIMessageHeight;
|
|
MercPopUpBox gpUIMessageOverrideMercBox;
|
|
UINT32 guiUIMessageTime = 0;
|
|
INT32 iOverlayMessageBox = -1;
|
|
INT32 iUIMessageBox = -1;
|
|
UINT32 guiUIMessageTimeDelay = 0;
|
|
BOOLEAN gfUseSkullIconMessage = FALSE;
|
|
|
|
// Overlay callback
|
|
void BlitPopupText( VIDEO_OVERLAY *pBlitter );
|
|
|
|
BOOLEAN gfPanelAllocated = FALSE;
|
|
|
|
extern MOUSE_REGION gDisableRegion;
|
|
extern MOUSE_REGION gUserTurnRegion;
|
|
extern BOOLEAN gfUserTurnRegionActive;
|
|
extern UINT8 gubSelectSMPanelToMerc;
|
|
extern BOOLEAN gfIgnoreOnSelectedGuy;
|
|
|
|
typedef enum
|
|
{
|
|
WALK_IMAGES = 0,
|
|
SNEAK_IMAGES,
|
|
RUN_IMAGES,
|
|
CRAWL_IMAGES,
|
|
LOOK_IMAGES,
|
|
TALK_IMAGES,
|
|
HAND_IMAGES,
|
|
CANCEL_IMAGES,
|
|
|
|
TARGETACTIONC_IMAGES,
|
|
KNIFEACTIONC_IMAGES,
|
|
AIDACTIONC_IMAGES,
|
|
PUNCHACTIONC_IMAGES,
|
|
BOMBACTIONC_IMAGES,
|
|
|
|
OPEN_DOOR_IMAGES,
|
|
EXAMINE_DOOR_IMAGES,
|
|
LOCKPICK_DOOR_IMAGES,
|
|
BOOT_DOOR_IMAGES,
|
|
CROWBAR_DOOR_IMAGES,
|
|
USE_KEY_IMAGES,
|
|
USE_KEYRING_IMAGES,
|
|
EXPLOSIVE_DOOR_IMAGES,
|
|
|
|
TOOLKITACTIONC_IMAGES,
|
|
WIRECUTACTIONC_IMAGES,
|
|
|
|
NUM_ICON_IMAGES
|
|
};
|
|
|
|
INT32 iIconImages[ NUM_ICON_IMAGES ];
|
|
|
|
INT32 iActionIcons[ NUM_ICONS ];
|
|
|
|
// GLOBAL INTERFACE SURFACES
|
|
extern UINT32 guiRENDERBUFFER; // symbol already defined in sysutil.cpp (jonathanl)
|
|
UINT32 guiINTEXT;
|
|
UINT32 guiCLOSE;
|
|
UINT32 guiDEAD;
|
|
UINT32 guiHATCH;
|
|
|
|
UINT32 guiBUTTONBORDER;
|
|
UINT32 guiSILHOUETTE;
|
|
UINT32 guiRADIO;
|
|
UINT32 guiRADIO2;
|
|
UINT32 guiCOMPANEL;
|
|
UINT32 guiCOMPANELB;
|
|
UINT32 guiAIMCUBES;
|
|
UINT32 guiAIMBARS;
|
|
UINT32 guiVEHINV;
|
|
UINT32 guiBURSTACCUM;
|
|
UINT32 guiITEMPOINTERHATCHES;
|
|
|
|
UINT32 guiUNDERWATER; // added by Flugente
|
|
UINT32 guiENEMYROLES; // added by Flugente
|
|
|
|
// UI Globals
|
|
MOUSE_REGION gViewportRegion;
|
|
MOUSE_REGION gRadarRegion;
|
|
|
|
|
|
UINT16 gsUpArrowX;
|
|
UINT16 gsUpArrowY;
|
|
UINT16 gsDownArrowX;
|
|
UINT16 gsDownArrowY;
|
|
|
|
UINT32 giUpArrowRect;
|
|
UINT32 giDownArrowRect;
|
|
|
|
// HEADROCK HAM 4: Rectangles for the various CTH displays.
|
|
RECT MagRect;
|
|
RECT AimRect;
|
|
RECT ModeRect;
|
|
RECT APRect;
|
|
// sevenfm: additional rectangles
|
|
RECT RightRect;
|
|
RECT LeftRect;
|
|
RECT LeftRect2;
|
|
// HEADROCK HAM 4: Externed this value which tracks whether we've clicked out final aiming click yet.
|
|
extern BOOLEAN gfDisplayFullCountRing;
|
|
|
|
void DrawBarsInUIBox( SOLDIERTYPE *pSoldier , INT16 sXPos, INT16 sYPos, INT16 sWidth, INT16 sHeight, INT16 interval);
|
|
void PopupDoorOpenMenu( BOOLEAN fClosingDoor );
|
|
|
|
|
|
BOOLEAN fFirstTimeInGameScreen = TRUE;
|
|
BOOLEAN fInterfacePanelDirty = DIRTYLEVEL2;
|
|
INT16 gsInterfaceLevel = I_GROUND_LEVEL;
|
|
INT32 gsCurrentSoldierGridNo = 0;
|
|
INT16 gsCurInterfacePanel = TEAM_PANEL;
|
|
|
|
// LOCAL FUCTIONS
|
|
void BtnPositionCallback( GUI_BUTTON *btn, INT32 reason );
|
|
void BtnMovementCallback( GUI_BUTTON *btn, INT32 reason );
|
|
void BtnDoorMenuCallback( GUI_BUTTON *btn, INT32 reason );
|
|
void MovementMenuBackregionCallback( MOUSE_REGION * pRegion, INT32 iReason );
|
|
void DoorMenuBackregionCallback( MOUSE_REGION * pRegion, INT32 iReason );
|
|
|
|
UINT32 CalcUIMessageDuration( STR16 wString );
|
|
|
|
// sevenfm: this function is needed to show cover in health bar
|
|
extern void CalculateCoverForSoldier( SOLDIERTYPE* pForSoldier, const INT32& sTargetGridNo, const BOOLEAN& fRoof, INT8& bCover );
|
|
|
|
extern FLOAT Distance2D( FLOAT dDeltaX, FLOAT dDeltaY );
|
|
|
|
// Flugente: toggle display of enemy role indicators
|
|
BOOLEAN gDisplayEnemyRoles = TRUE;
|
|
|
|
BOOLEAN InitializeFaceGearGraphics()
|
|
{
|
|
VOBJECT_DESC VObjectDesc;
|
|
|
|
char fileName[500];
|
|
|
|
for(UINT32 iCounter2 = 1; iCounter2 < MAXITEMS; iCounter2++ )
|
|
{
|
|
VObjectDesc.fCreateFlags = VSURFACE_CREATE_FROMFILE;
|
|
|
|
#define SCSTI ".STI"
|
|
|
|
if ( zNewFaceGear[iCounter2].Type > 0 )
|
|
{
|
|
strcpy(fileName, zNewFaceGear[iCounter2].szFile);
|
|
strcat(fileName, SCSTI);
|
|
strcpy(VObjectDesc.ImageFile, fileName);
|
|
CHECKF(AddVideoObject(&VObjectDesc,&zNewFaceGear[iCounter2].uiIndex));
|
|
|
|
}
|
|
}
|
|
|
|
for(UINT32 iCounter2 = 1; iCounter2 < MAXITEMS; iCounter2++ )
|
|
{
|
|
VObjectDesc.fCreateFlags = VSURFACE_CREATE_FROMFILE;
|
|
|
|
#define SCSTI_IMP "_IMP.STI"
|
|
|
|
if ( zNewFaceGear[iCounter2].Type > 0 )
|
|
{
|
|
//IMP
|
|
strcpy(fileName, zNewFaceGear[iCounter2].szFile);
|
|
strcat(fileName, SCSTI_IMP);
|
|
strcpy(VObjectDesc.ImageFile, fileName);
|
|
CHECKF(AddVideoObject(&VObjectDesc,&zNewFaceGearIMP[iCounter2].uiIndex));
|
|
}
|
|
}
|
|
|
|
return ( TRUE );
|
|
}
|
|
|
|
BOOLEAN InitializeTacticalPortraits( )
|
|
{
|
|
VOBJECT_DESC VObjectDesc;
|
|
|
|
VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE;
|
|
|
|
//CHRISL: Moved from InitializeTacticalInterface so we can reinitialize portait graphics as we need to
|
|
//legion 2 jazz
|
|
if (gGameSettings.fOptions[ TOPTION_SHOW_TACTICAL_FACE_ICONS ] == TRUE)
|
|
{
|
|
//additional face icons (legion 2)
|
|
if (gGameExternalOptions.bTacticalFaceIconStyle == 0)
|
|
{
|
|
FilenameForBPP("INTERFACE\\portraiticons_a.sti", VObjectDesc.ImageFile);
|
|
|
|
if( !AddVideoObject( &VObjectDesc, &guiPORTRAITICONS ) )
|
|
AssertMsg(0, "Missing INTERFACE\\portraiticons_a.sti" );
|
|
}
|
|
else if (gGameExternalOptions.bTacticalFaceIconStyle == 1)
|
|
{
|
|
FilenameForBPP("INTERFACE\\portraiticons_b.sti", VObjectDesc.ImageFile);
|
|
|
|
if( !AddVideoObject( &VObjectDesc, &guiPORTRAITICONS ) )
|
|
AssertMsg(0, "Missing INTERFACE\\portraiticons_b.sti" );
|
|
}
|
|
else if (gGameExternalOptions.bTacticalFaceIconStyle == 2)
|
|
{
|
|
FilenameForBPP("INTERFACE\\portraiticons_c.sti", VObjectDesc.ImageFile);
|
|
|
|
if( !AddVideoObject( &VObjectDesc, &guiPORTRAITICONS ) )
|
|
AssertMsg(0, "Missing INTERFACE\\portraiticons_c.sti" );
|
|
}
|
|
else if (gGameExternalOptions.bTacticalFaceIconStyle == 3)
|
|
{
|
|
FilenameForBPP("INTERFACE\\portraiticons_d.sti", VObjectDesc.ImageFile);
|
|
|
|
if( !AddVideoObject( &VObjectDesc, &guiPORTRAITICONS ) )
|
|
AssertMsg(0, "Missing INTERFACE\\portraiticons_d.sti" );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// JA2 classic face icons
|
|
FilenameForBPP("INTERFACE\\portraiticons.sti", VObjectDesc.ImageFile);
|
|
|
|
if( !AddVideoObject( &VObjectDesc, &guiPORTRAITICONS ) )
|
|
AssertMsg(0, "Missing INTERFACE\\portraiticons.sti" );
|
|
}
|
|
|
|
// Flugente: icons for assignments
|
|
FilenameForBPP("INTERFACE\\AssignmentIcons.sti", VObjectDesc.ImageFile);
|
|
|
|
if( !AddVideoObject( &VObjectDesc, &guiASSIGNMENTICONS ) )
|
|
AssertMsg(0, "Missing INTERFACE\\AssignmentIcons.sti" );
|
|
|
|
return ( TRUE );
|
|
}
|
|
|
|
BOOLEAN InitializeTacticalInterface( )
|
|
{
|
|
VSURFACE_DESC vs_desc;
|
|
VOBJECT_DESC VObjectDesc;
|
|
|
|
//UINT32 iCounter2;
|
|
|
|
// CHRISL: Setup default interface coords based on inventory system in use
|
|
if((UsingNewInventorySystem() == true))
|
|
{
|
|
InitNewInventorySystem();
|
|
InitializeSMPanelCoordsNew();
|
|
}
|
|
else
|
|
{
|
|
InitOldInventorySystem();
|
|
InitializeSMPanelCoordsOld();
|
|
}
|
|
|
|
//*ddd{
|
|
if( gGameExternalOptions.fSmallSizeProgressbar )
|
|
{
|
|
HEIGHT_PROGRESSBAR = 7;
|
|
PROG_BAR_START_Y = 0;
|
|
}
|
|
else{
|
|
HEIGHT_PROGRESSBAR = 20;
|
|
PROG_BAR_START_Y = 2;
|
|
}
|
|
//*ddd}
|
|
|
|
/* OK i need to initialize coords here
|
|
* Isnt it cool
|
|
* any questions? joker
|
|
*/
|
|
InitializeViewPort( );
|
|
InitializeTEAMPanelCoords( );
|
|
|
|
// Load button Interfaces
|
|
iIconImages[ WALK_IMAGES ] = LoadButtonImage("INTERFACE\\newicons3.sti", -1,3,4,5,-1 );
|
|
iIconImages[ SNEAK_IMAGES ] = UseLoadedButtonImage(iIconImages[ WALK_IMAGES ], -1, 6, 7, 8, -1 );
|
|
iIconImages[ RUN_IMAGES ] = UseLoadedButtonImage(iIconImages[ WALK_IMAGES ], -1, 0, 1, 2, -1 );
|
|
iIconImages[ CRAWL_IMAGES ] = UseLoadedButtonImage(iIconImages[ WALK_IMAGES ], -1, 9, 10, 11, -1 );
|
|
iIconImages[ LOOK_IMAGES ] = UseLoadedButtonImage(iIconImages[ WALK_IMAGES ], -1, 12, 13, 14, -1 );
|
|
iIconImages[ TALK_IMAGES ] = UseLoadedButtonImage(iIconImages[ WALK_IMAGES ], -1, 21, 22, 23, -1 );
|
|
iIconImages[ HAND_IMAGES ] = UseLoadedButtonImage(iIconImages[ WALK_IMAGES ], -1, 18, 19, 20, -1 );
|
|
iIconImages[ CANCEL_IMAGES ] = UseLoadedButtonImage(iIconImages[ WALK_IMAGES ], -1, 15, 16, 17, -1 );
|
|
|
|
iIconImages[ TARGETACTIONC_IMAGES ] = UseLoadedButtonImage(iIconImages[ WALK_IMAGES ], -1, 24, 25, 26, -1 );
|
|
iIconImages[ KNIFEACTIONC_IMAGES ] = UseLoadedButtonImage(iIconImages[ WALK_IMAGES ], -1, 27, 28, 29, -1 );
|
|
iIconImages[ AIDACTIONC_IMAGES ] = UseLoadedButtonImage(iIconImages[ WALK_IMAGES ], -1, 30, 31, 32, -1 );
|
|
iIconImages[ PUNCHACTIONC_IMAGES ] = UseLoadedButtonImage(iIconImages[ WALK_IMAGES ], -1, 33, 34, 35, -1 );
|
|
iIconImages[ BOMBACTIONC_IMAGES ] = UseLoadedButtonImage(iIconImages[ WALK_IMAGES ], -1, 36, 37, 38, -1 );
|
|
iIconImages[ TOOLKITACTIONC_IMAGES ] = UseLoadedButtonImage(iIconImages[ WALK_IMAGES ], -1, 39, 40, 41, -1 );
|
|
iIconImages[ WIRECUTACTIONC_IMAGES ] = UseLoadedButtonImage(iIconImages[ WALK_IMAGES ], -1, 42, 43, 44, -1 );
|
|
|
|
iIconImages[ OPEN_DOOR_IMAGES ] = LoadButtonImage("INTERFACE\\door_op2.sti", -1,9,10,11,-1 );
|
|
iIconImages[ EXAMINE_DOOR_IMAGES ] = UseLoadedButtonImage(iIconImages[ OPEN_DOOR_IMAGES ], -1, 12, 13, 14, -1 );
|
|
iIconImages[ LOCKPICK_DOOR_IMAGES ] = UseLoadedButtonImage(iIconImages[ OPEN_DOOR_IMAGES ], -1, 21, 22, 23, -1 );
|
|
iIconImages[ BOOT_DOOR_IMAGES ] = UseLoadedButtonImage(iIconImages[ OPEN_DOOR_IMAGES ], -1, 25, 26, 27, -1 );
|
|
iIconImages[ CROWBAR_DOOR_IMAGES ] = UseLoadedButtonImage(iIconImages[ OPEN_DOOR_IMAGES ], -1, 0, 1, 2, -1 );
|
|
iIconImages[ USE_KEY_IMAGES ] = UseLoadedButtonImage(iIconImages[ OPEN_DOOR_IMAGES ], -1, 3, 4, 5, -1 );
|
|
iIconImages[ USE_KEYRING_IMAGES ] = UseLoadedButtonImage(iIconImages[ OPEN_DOOR_IMAGES ], -1, 6, 7, 8, -1 );
|
|
iIconImages[ EXPLOSIVE_DOOR_IMAGES ] = UseLoadedButtonImage(iIconImages[ OPEN_DOOR_IMAGES ], -1, 15, 16, 17, -1 );
|
|
|
|
// Load interface panels
|
|
vs_desc.fCreateFlags = VSURFACE_CREATE_FROMFILE | VSURFACE_SYSTEM_MEM_USAGE;
|
|
|
|
// failing the CHECKF after this will cause you to lose your mouse
|
|
|
|
if ( GETPIXELDEPTH() == 8 )
|
|
{
|
|
strcpy( vs_desc.ImageFile, "INTERFACE\\IN_TEXT_8.pcx" );
|
|
}
|
|
else if ( GETPIXELDEPTH() == 16 )
|
|
{
|
|
strcpy( vs_desc.ImageFile, "INTERFACE\\IN_TEXT.STI" );
|
|
}
|
|
|
|
if( !AddVideoSurface( &vs_desc, &guiINTEXT ) )
|
|
AssertMsg( 0, "Missing INTERFACE\\In_text.sti");
|
|
SetVideoSurfaceTransparency( guiINTEXT, FROMRGB( 255, 0, 0 ) );
|
|
|
|
|
|
// LOAD CLOSE ANIM
|
|
VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE;
|
|
FilenameForBPP("INTERFACE\\p_close.sti", VObjectDesc.ImageFile);
|
|
if( !AddVideoObject( &VObjectDesc, &guiCLOSE ) )
|
|
AssertMsg(0, "Missing INTERFACE\\p_close.sti" );
|
|
|
|
// LOAD DEAD ANIM
|
|
VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE;
|
|
FilenameForBPP("INTERFACE\\p_dead.sti", VObjectDesc.ImageFile);
|
|
if( !AddVideoObject( &VObjectDesc, &guiDEAD ) )
|
|
AssertMsg(0, "Missing INTERFACE\\p_dead.sti" );
|
|
|
|
// LOAD HATCH
|
|
VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE;
|
|
FilenameForBPP("INTERFACE\\hatch.sti", VObjectDesc.ImageFile);
|
|
if( !AddVideoObject( &VObjectDesc, &guiHATCH ) )
|
|
AssertMsg(0, "Missing INTERFACE\\hatch.sti" );
|
|
|
|
SGP_THROW_IFFALSE( RegisterItemImages(), L"Registering Item Images failed" );
|
|
|
|
// CHRISL:
|
|
// LOAD INTERFACE POCKET SILHOUETTES
|
|
VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE;
|
|
FilenameForBPP("INTERFACE\\Silhouettes.sti", VObjectDesc.ImageFile);
|
|
if( !AddVideoObject( &VObjectDesc, &guiSILHOUETTE ) )
|
|
AssertMsg(0, "Missing INTERFACE\\Silhouettes.sti" );
|
|
|
|
// LOAD INTERFACE BUTTON BORDER
|
|
VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE;
|
|
FilenameForBPP("INTERFACE\\button_frame.sti", VObjectDesc.ImageFile);
|
|
if( !AddVideoObject( &VObjectDesc, &guiBUTTONBORDER ) )
|
|
AssertMsg(0, "Missing INTERFACE\\button_frame.sti" );
|
|
|
|
// LOAD AIM CUBES
|
|
VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE;
|
|
FilenameForBPP("INTERFACE\\aimcubes.sti", VObjectDesc.ImageFile);
|
|
if( !AddVideoObject( &VObjectDesc, &guiAIMCUBES ) )
|
|
AssertMsg(0, "Missing INTERFACE\\aimcubes.sti" );
|
|
|
|
// LOAD AIM BARS
|
|
VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE;
|
|
FilenameForBPP("INTERFACE\\aimbars.sti", VObjectDesc.ImageFile);
|
|
if( !AddVideoObject( &VObjectDesc, &guiAIMBARS ) )
|
|
AssertMsg(0, "Missing INTERFACE\\aimbars.sti" );
|
|
|
|
|
|
VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE;
|
|
FilenameForBPP("INTERFACE\\inventor.sti", VObjectDesc.ImageFile);
|
|
if( !AddVideoObject( &VObjectDesc, &guiVEHINV ) )
|
|
AssertMsg(0, "Missing INTERFACE\\inventor.sti" );
|
|
|
|
|
|
VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE;
|
|
FilenameForBPP("INTERFACE\\burst1.sti", VObjectDesc.ImageFile);
|
|
if( !AddVideoObject( &VObjectDesc, &guiBURSTACCUM ) )
|
|
AssertMsg(0, "Missing INTERFACE\\burst1.sti" );
|
|
|
|
// Flugente: load fish symbol (signifies that a merc is diving until someone comes up with a proper animation)
|
|
VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE;
|
|
FilenameForBPP("INTERFACE\\fish.sti", VObjectDesc.ImageFile);
|
|
if( !AddVideoObject( &VObjectDesc, &guiUNDERWATER ) )
|
|
AssertMsg(0, "Missing INTERFACE\\fish.sti" );
|
|
|
|
// Flugente: enemy role symbols
|
|
VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE;
|
|
FilenameForBPP("INTERFACE\\RoleIcons.sti", VObjectDesc.ImageFile);
|
|
if( !AddVideoObject( &VObjectDesc, &guiENEMYROLES ) )
|
|
AssertMsg(0, "Missing INTERFACE\\RoleIcons.sti" );
|
|
|
|
//CHRISL: Moved to seperate function so we can call seperately
|
|
InitializeTacticalPortraits();
|
|
|
|
InitializeFaceGearGraphics();
|
|
|
|
/*
|
|
for( iCounter2 = 1; iCounter2 < MAXITEMS; iCounter2++ )
|
|
{
|
|
VObjectDesc.fCreateFlags = VSURFACE_CREATE_FROMFILE;
|
|
|
|
#define SCSTI ".STI"
|
|
|
|
if ( zNewFaceGear[iCounter2].Type > 0 )
|
|
{
|
|
strcpy(fileName, zNewFaceGear[iCounter2].szFile);
|
|
strcat(fileName, SCSTI);
|
|
strcpy(VObjectDesc.ImageFile, fileName);
|
|
CHECKF(AddVideoObject(&VObjectDesc,&zNewFaceGear[iCounter2].uiIndex));
|
|
|
|
}
|
|
}
|
|
|
|
for( iCounter2 = 1; iCounter2 < MAXITEMS; iCounter2++ )
|
|
{
|
|
VObjectDesc.fCreateFlags = VSURFACE_CREATE_FROMFILE;
|
|
|
|
#define SCSTI_IMP "_IMP.STI"
|
|
|
|
if ( zNewFaceGear[iCounter2].Type > 0 )
|
|
{
|
|
//IMP
|
|
strcpy(fileName, zNewFaceGear[iCounter2].szFile);
|
|
strcat(fileName, SCSTI_IMP);
|
|
strcpy(VObjectDesc.ImageFile, fileName);
|
|
CHECKF(AddVideoObject(&VObjectDesc,&zNewFaceGearIMP[iCounter2].uiIndex));
|
|
}
|
|
}
|
|
*/
|
|
|
|
// LOAD RADIO
|
|
VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE;
|
|
FilenameForBPP("INTERFACE\\radio.sti", VObjectDesc.ImageFile);
|
|
|
|
if( !AddVideoObject( &VObjectDesc, &guiRADIO ) )
|
|
AssertMsg(0, "Missing INTERFACE\\radio.sti" );
|
|
|
|
// LOAD RADIO2
|
|
VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE;
|
|
FilenameForBPP("INTERFACE\\radio2.sti", VObjectDesc.ImageFile);
|
|
if( !AddVideoObject( &VObjectDesc, &guiRADIO2 ) )
|
|
AssertMsg(0, "Missing INTERFACE\\radio2.sti" );
|
|
|
|
// LOAD com panel 2
|
|
VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE;
|
|
FilenameForBPP("INTERFACE\\communicationpopup.sti", VObjectDesc.ImageFile);
|
|
if( !AddVideoObject( &VObjectDesc, &guiCOMPANEL ) )
|
|
AssertMsg(0, "Missing INTERFACE\\communicationpopup.sti" );
|
|
|
|
// LOAD ITEM GRIDS....
|
|
VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE;
|
|
FilenameForBPP("INTERFACE\\itemgrid.sti", VObjectDesc.ImageFile);
|
|
if( !AddVideoObject( &VObjectDesc, &guiITEMPOINTERHATCHES ) )
|
|
AssertMsg(0, "Missing INTERFACE\\itemgrid.sti" );
|
|
|
|
|
|
VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE;
|
|
FilenameForBPP("INTERFACE\\communicationpopup_2.sti", VObjectDesc.ImageFile);
|
|
if( !AddVideoObject( &VObjectDesc, &guiCOMPANELB ) )
|
|
AssertMsg(0, "Missing INTERFACE\\communicationpopup_2.sti" );
|
|
|
|
|
|
// Alocate message surfaces
|
|
vs_desc.fCreateFlags = VSURFACE_CREATE_DEFAULT | VSURFACE_SYSTEM_MEM_USAGE;
|
|
vs_desc.usWidth = SCREEN_WIDTH;
|
|
vs_desc.usHeight = 20;
|
|
vs_desc.ubBitDepth = 16;
|
|
CHECKF( AddVideoSurface( &vs_desc, &(gTopMessage.uiSurface) ) );
|
|
|
|
|
|
InitItemInterface( );
|
|
|
|
InitRadarScreen( );
|
|
|
|
InitTEAMSlots( );
|
|
|
|
// Init popup box images
|
|
// CHECKF( LoadTextMercPopupImages( BASIC_MERC_POPUP_BACKGROUND, BASIC_MERC_POPUP_BORDER ) );
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
BOOLEAN ShutdownTacticalInterface( )
|
|
{
|
|
ShutdownCurrentPanel( );
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
BOOLEAN InitializeCurrentPanel( )
|
|
{
|
|
BOOLEAN fOK = FALSE;
|
|
|
|
MoveRadarScreen( );
|
|
|
|
switch( gsCurInterfacePanel )
|
|
{
|
|
case SM_PANEL:
|
|
// Set new viewport
|
|
gsVIEWPORT_WINDOW_END_Y = INV_INTERFACE_START_Y;
|
|
|
|
// Render full
|
|
SetRenderFlags(RENDER_FLAG_FULL);
|
|
fOK = InitializeSMPanel( );
|
|
break;
|
|
|
|
case TEAM_PANEL:
|
|
gsVIEWPORT_WINDOW_END_Y = INTERFACE_START_Y;
|
|
// Render full
|
|
SetRenderFlags(RENDER_FLAG_FULL);
|
|
fOK = InitializeTEAMPanel( );
|
|
break;
|
|
}
|
|
|
|
// RefreshMouseRegions( );
|
|
gfPanelAllocated = TRUE;
|
|
|
|
return( fOK );
|
|
}
|
|
|
|
void ShutdownCurrentPanel( )
|
|
{
|
|
if ( gfPanelAllocated )
|
|
{
|
|
|
|
switch( gsCurInterfacePanel )
|
|
{
|
|
case SM_PANEL:
|
|
ShutdownSMPanel( );
|
|
break;
|
|
|
|
case TEAM_PANEL:
|
|
ShutdownTEAMPanel( );
|
|
break;
|
|
}
|
|
|
|
gfPanelAllocated = FALSE;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void SetCurrentTacticalPanelCurrentMerc( UINT8 ubID )
|
|
{
|
|
SOLDIERTYPE *pSoldier;
|
|
|
|
// Disable faces
|
|
SetAllAutoFacesInactive( );
|
|
|
|
if ( gsCurInterfacePanel == SM_PANEL )
|
|
{
|
|
// If we are not of merc bodytype, or am an epc, and going into inv, goto another....
|
|
pSoldier = MercPtrs[ ubID ];
|
|
|
|
if ( !IS_MERC_BODY_TYPE( pSoldier ) || AM_AN_EPC( pSoldier ) )
|
|
{
|
|
SetCurrentInterfacePanel( TEAM_PANEL );
|
|
}
|
|
}
|
|
|
|
switch( gsCurInterfacePanel )
|
|
{
|
|
case SM_PANEL:
|
|
//SetSMPanelCurrentMerc( ubID );
|
|
gubSelectSMPanelToMerc = ubID;
|
|
break;
|
|
|
|
case TEAM_PANEL:
|
|
SetTEAMPanelCurrentMerc( (UINT8)gusSelectedSoldier );
|
|
break;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
void CreateCurrentTacticalPanelButtons( )
|
|
{
|
|
switch( gsCurInterfacePanel )
|
|
{
|
|
case SM_PANEL:
|
|
CreateSMPanelButtons( /*fInterfacePanelDirty*/ ); // doesn't take parameters (jonathanl)
|
|
break;
|
|
|
|
case TEAM_PANEL:
|
|
CreateTEAMPanelButtons( /*fInterfacePanelDirty*/ ); // doesn't take parameters (jonathanl)
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
void SetCurrentInterfacePanel( UINT8 ubNewPanel )
|
|
{
|
|
ShutdownCurrentPanel( );
|
|
|
|
// INit new panel
|
|
gsCurInterfacePanel = ubNewPanel;
|
|
|
|
InitializeCurrentPanel( );
|
|
|
|
|
|
}
|
|
|
|
|
|
void ToggleTacticalPanels( )
|
|
{
|
|
gfSwitchPanel = TRUE;
|
|
gubNewPanelParam = (UINT8)gusSelectedSoldier;
|
|
|
|
if ( gsCurInterfacePanel == SM_PANEL )
|
|
{
|
|
gbNewPanel = TEAM_PANEL;
|
|
}
|
|
else
|
|
{
|
|
gbNewPanel = SM_PANEL;
|
|
}
|
|
}
|
|
|
|
|
|
void RemoveCurrentTacticalPanelButtons( )
|
|
{
|
|
switch( gsCurInterfacePanel )
|
|
{
|
|
case SM_PANEL:
|
|
RemoveSMPanelButtons( /*fInterfacePanelDirty*/ ); // doesn't take parameters (jonathanl)
|
|
break;
|
|
|
|
case TEAM_PANEL:
|
|
RemoveTEAMPanelButtons( /*fInterfacePanelDirty*/ ); // doesn't take parameters (jonathanl)
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
BOOLEAN IsMercPortraitVisible( UINT8 ubSoldierID )
|
|
{
|
|
if ( gsCurInterfacePanel == TEAM_PANEL )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
|
|
if ( gsCurInterfacePanel == SM_PANEL )
|
|
{
|
|
if ( GetSMPanelCurrentMerc() == ubSoldierID )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
}
|
|
|
|
return( FALSE );
|
|
}
|
|
|
|
|
|
void HandleInterfaceBackgrounds( )
|
|
{
|
|
HandleUpDownArrowBackgrounds( );
|
|
}
|
|
|
|
|
|
void PopupPositionMenu( UI_EVENT *pUIEvent )
|
|
{
|
|
|
|
}
|
|
|
|
void PopDownPositionMenu( )
|
|
{
|
|
|
|
}
|
|
|
|
|
|
void BtnPositionCallback(GUI_BUTTON *btn,INT32 reason)
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void PopupMovementMenu( UI_EVENT *pUIEvent )
|
|
{
|
|
SOLDIERTYPE *pSoldier = NULL;
|
|
INT32 iMenuAnchorX, iMenuAnchorY;
|
|
UINT32 uiActionImages;
|
|
CHAR16 zActionString[ 50 ];
|
|
BOOLEAN fDisableAction = FALSE;
|
|
|
|
// Erase other menus....
|
|
EraseInterfaceMenus( TRUE );
|
|
|
|
giMenuAnchorX = gusMouseXPos - 18;
|
|
giMenuAnchorY = gusMouseYPos - 18;
|
|
|
|
// ATE: OK loser, let's check if we're going off the screen!
|
|
if ( giMenuAnchorX < 0 )
|
|
{
|
|
giMenuAnchorX = 0;
|
|
}
|
|
|
|
if ( giMenuAnchorY < 0 )
|
|
{
|
|
giMenuAnchorY = 0;
|
|
}
|
|
|
|
|
|
// Create mouse region over all area to facilitate clicking to end
|
|
MSYS_DefineRegion( &gMenuOverlayRegion, 0, 0 ,SCREEN_WIDTH, SCREEN_HEIGHT, MSYS_PRIORITY_HIGHEST-1,
|
|
CURSOR_NORMAL, MSYS_NO_CALLBACK, MovementMenuBackregionCallback );
|
|
// Add region
|
|
MSYS_AddRegion( &gMenuOverlayRegion);
|
|
|
|
|
|
// OK, CHECK FOR BOUNDARIES!
|
|
if ( ( giMenuAnchorX + BUTTON_PANEL_WIDTH ) > SCREEN_WIDTH )
|
|
{
|
|
giMenuAnchorX = ( SCREEN_WIDTH - BUTTON_PANEL_WIDTH );
|
|
}
|
|
if ( ( giMenuAnchorY + BUTTON_PANEL_HEIGHT ) > gsVIEWPORT_WINDOW_END_Y )
|
|
{
|
|
giMenuAnchorY = ( gsVIEWPORT_WINDOW_END_Y - BUTTON_PANEL_HEIGHT );
|
|
}
|
|
|
|
|
|
|
|
if ( gusSelectedSoldier != NOBODY )
|
|
{
|
|
pSoldier = MercPtrs[ gusSelectedSoldier ];
|
|
}
|
|
|
|
// Blit background!
|
|
//BltVideoObjectFromIndex( FRAME_BUFFER, guiBUTTONBORDER, 0, iMenuAnchorX, iMenuAnchorY, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
|
|
iMenuAnchorX = giMenuAnchorX + 9;
|
|
iMenuAnchorY = giMenuAnchorY + 8;
|
|
|
|
iActionIcons[ RUN_ICON ] = QuickCreateButton( iIconImages[ RUN_IMAGES ], (INT16)(iMenuAnchorX + 20 ), (INT16)(iMenuAnchorY ),
|
|
BUTTON_NO_TOGGLE, MSYS_PRIORITY_HIGHEST - 1,
|
|
DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)BtnMovementCallback );
|
|
if ( iActionIcons[ RUN_ICON ] == -1 )
|
|
{
|
|
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, "Cannot create Interface button" );
|
|
return;
|
|
}
|
|
SetButtonFastHelpText( iActionIcons[ RUN_ICON ], pTacticalPopupButtonStrings[ RUN_ICON ] );
|
|
//SetButtonSavedRect( iActionIcons[ RUN_ICON ] );
|
|
ButtonList[ iActionIcons[ RUN_ICON ] ]->UserData[0] = (UINT32)pUIEvent;
|
|
|
|
if ( pSoldier->MercInWater( ) || ( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) || ( pSoldier->flags.uiStatusFlags & SOLDIER_ROBOT ) )
|
|
{
|
|
DisableButton( iActionIcons[ RUN_ICON ] );
|
|
}
|
|
|
|
iActionIcons[ WALK_ICON ] = QuickCreateButton( iIconImages[ WALK_IMAGES ], (INT16)(iMenuAnchorX + 40 ), (INT16)(iMenuAnchorY ),
|
|
BUTTON_NO_TOGGLE, MSYS_PRIORITY_HIGHEST - 1,
|
|
DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)BtnMovementCallback );
|
|
if ( iActionIcons[ WALK_ICON ] == -1 )
|
|
{
|
|
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, "Cannot create Interface button" );
|
|
return;
|
|
}
|
|
//SetButtonSavedRect( iActionIcons[ WALK_ICON ] );
|
|
|
|
if ( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE )
|
|
{
|
|
SetButtonFastHelpText( iActionIcons[ WALK_ICON ], TacticalStr[ DRIVE_POPUPTEXT ] );
|
|
}
|
|
else
|
|
{
|
|
SetButtonFastHelpText( iActionIcons[ WALK_ICON ], pTacticalPopupButtonStrings[ WALK_ICON ] );
|
|
}
|
|
|
|
ButtonList[ iActionIcons[ WALK_ICON ] ]->UserData[0] = (UINT32)pUIEvent;
|
|
|
|
if ( pSoldier->flags.uiStatusFlags & SOLDIER_ROBOT )
|
|
{
|
|
if ( !pSoldier->CanRobotBeControlled( ) )
|
|
{
|
|
DisableButton( iActionIcons[ WALK_ICON ] );
|
|
}
|
|
}
|
|
|
|
|
|
iActionIcons[ SNEAK_ICON ] = QuickCreateButton( iIconImages[ SNEAK_IMAGES ], (INT16)(iMenuAnchorX + 40 ), (INT16)(iMenuAnchorY + 20 ),
|
|
BUTTON_NO_TOGGLE, MSYS_PRIORITY_HIGHEST - 1,
|
|
DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)BtnMovementCallback );
|
|
if ( iActionIcons[ SNEAK_ICON ] == -1 )
|
|
{
|
|
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, "Cannot create Interface button" );
|
|
return;
|
|
}
|
|
SetButtonFastHelpText( iActionIcons[ SNEAK_ICON ], pTacticalPopupButtonStrings[ SNEAK_ICON ] );
|
|
//SetButtonSavedRect( iActionIcons[ SNEAK_ICON ] );
|
|
ButtonList[ iActionIcons[ SNEAK_ICON ] ]->UserData[0] = (UINT32)pUIEvent;
|
|
|
|
// Check if this is a valid stance, diable if not!
|
|
if ( !IsValidStance( pSoldier, ANIM_CROUCH ) )
|
|
{
|
|
DisableButton( iActionIcons[ SNEAK_ICON ] );
|
|
}
|
|
|
|
iActionIcons[ CRAWL_ICON ] = QuickCreateButton( iIconImages[ CRAWL_IMAGES ], (INT16)(iMenuAnchorX + 40 ), (INT16)(iMenuAnchorY + 40 ),
|
|
BUTTON_NO_TOGGLE, MSYS_PRIORITY_HIGHEST - 1,
|
|
DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)BtnMovementCallback );
|
|
if ( iActionIcons[ CRAWL_ICON ] == -1 )
|
|
{
|
|
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, "Cannot create Interface button" );
|
|
return;
|
|
}
|
|
SetButtonFastHelpText( iActionIcons[ CRAWL_ICON ], pTacticalPopupButtonStrings[ CRAWL_ICON ] );
|
|
//SetButtonSavedRect( iActionIcons[ CRAWL_ICON ] );
|
|
ButtonList[ iActionIcons[ CRAWL_ICON ] ]->UserData[0] = (UINT32)pUIEvent;
|
|
|
|
// Check if this is a valid stance, diable if not!
|
|
if ( !IsValidStance( pSoldier, ANIM_PRONE ) )
|
|
{
|
|
DisableButton( iActionIcons[ CRAWL_ICON ] );
|
|
}
|
|
|
|
|
|
iActionIcons[ LOOK_ICON ] = QuickCreateButton( iIconImages[ LOOK_IMAGES ], (INT16)(iMenuAnchorX ), (INT16)(iMenuAnchorY ),
|
|
BUTTON_NO_TOGGLE, MSYS_PRIORITY_HIGHEST - 1,
|
|
DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)BtnMovementCallback );
|
|
if ( iActionIcons[ LOOK_ICON ] == -1 )
|
|
{
|
|
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, "Cannot create Interface button" );
|
|
return;
|
|
}
|
|
SetButtonFastHelpText( iActionIcons[ LOOK_ICON ], TacticalStr[ LOOK_CURSOR_POPUPTEXT ] );
|
|
//SetButtonSavedRect( iActionIcons[ LOOK_ICON ] );
|
|
ButtonList[ iActionIcons[ LOOK_ICON ] ]->UserData[0] = (UINT32)pUIEvent;
|
|
|
|
if ( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE )
|
|
{
|
|
DisableButton( iActionIcons[ LOOK_ICON ] );
|
|
}
|
|
|
|
if ( pSoldier->flags.uiStatusFlags & SOLDIER_ROBOT )
|
|
{
|
|
if ( !pSoldier->CanRobotBeControlled( ) )
|
|
{
|
|
DisableButton( iActionIcons[ LOOK_ICON ] );
|
|
}
|
|
}
|
|
|
|
if ( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE )
|
|
{
|
|
// Until we get mounted weapons...
|
|
uiActionImages = CANCEL_IMAGES;
|
|
swprintf( zActionString, TacticalStr[ NOT_APPLICABLE_POPUPTEXT ] );
|
|
fDisableAction = TRUE;
|
|
}
|
|
else
|
|
{
|
|
if ( Item[pSoldier->inv[ HANDPOS ].usItem].toolkit )
|
|
{
|
|
uiActionImages = TOOLKITACTIONC_IMAGES;
|
|
swprintf( zActionString, TacticalStr[ NOT_APPLICABLE_POPUPTEXT ] );
|
|
}
|
|
else if ( Item[pSoldier->inv[ HANDPOS ].usItem].wirecutters )
|
|
{
|
|
uiActionImages = WIRECUTACTIONC_IMAGES;
|
|
swprintf( zActionString, TacticalStr[ NOT_APPLICABLE_POPUPTEXT ] );
|
|
}
|
|
else
|
|
{
|
|
// Create button based on what is in our hands at the moment!
|
|
switch( Item[ pSoldier->inv[ HANDPOS ].usItem ].usItemClass )
|
|
{
|
|
case IC_PUNCH:
|
|
|
|
uiActionImages = PUNCHACTIONC_IMAGES;
|
|
swprintf( zActionString, TacticalStr[ USE_HANDTOHAND_POPUPTEXT ] );
|
|
break;
|
|
|
|
case IC_GUN:
|
|
|
|
uiActionImages = TARGETACTIONC_IMAGES;
|
|
swprintf( zActionString, TacticalStr[ USE_FIREARM_POPUPTEXT ] );
|
|
break;
|
|
|
|
case IC_BLADE:
|
|
|
|
uiActionImages = KNIFEACTIONC_IMAGES;
|
|
swprintf( zActionString, TacticalStr[ USE_BLADE_POPUPTEXT ] );
|
|
break;
|
|
|
|
case IC_GRENADE:
|
|
case IC_BOMB:
|
|
|
|
uiActionImages = BOMBACTIONC_IMAGES;
|
|
swprintf( zActionString, TacticalStr[ USE_EXPLOSIVE_POPUPTEXT ] );
|
|
break;
|
|
|
|
case IC_MEDKIT:
|
|
|
|
uiActionImages = AIDACTIONC_IMAGES;
|
|
swprintf( zActionString, TacticalStr[ USE_MEDKIT_POPUPTEXT ] );
|
|
break;
|
|
|
|
default:
|
|
|
|
uiActionImages = CANCEL_IMAGES;
|
|
swprintf( zActionString, TacticalStr[ NOT_APPLICABLE_POPUPTEXT ] );
|
|
fDisableAction = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( AM_AN_EPC( pSoldier ) )
|
|
{
|
|
fDisableAction = TRUE;
|
|
}
|
|
|
|
iActionIcons[ ACTIONC_ICON ] = QuickCreateButton( iIconImages[ uiActionImages ], (INT16)(iMenuAnchorX ), (INT16)(iMenuAnchorY + 20 ),
|
|
BUTTON_NO_TOGGLE, MSYS_PRIORITY_HIGHEST - 1,
|
|
DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)BtnMovementCallback );
|
|
if ( iActionIcons[ ACTIONC_ICON ] == -1 )
|
|
{
|
|
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, "Cannot create Interface button" );
|
|
return;
|
|
}
|
|
//SetButtonSavedRect( iActionIcons[ ACTIONC_ICON ] );
|
|
SetButtonFastHelpText( iActionIcons[ ACTIONC_ICON ], zActionString );
|
|
ButtonList[ iActionIcons[ ACTIONC_ICON ] ]->UserData[0] = (UINT32)pUIEvent;
|
|
|
|
if ( fDisableAction )
|
|
{
|
|
DisableButton( iActionIcons[ ACTIONC_ICON ] );
|
|
}
|
|
|
|
|
|
iActionIcons[ TALK_ICON ] = QuickCreateButton( iIconImages[ TALK_IMAGES ], (INT16)(iMenuAnchorX ), (INT16)(iMenuAnchorY + 40 ),
|
|
BUTTON_NO_TOGGLE, MSYS_PRIORITY_HIGHEST - 1,
|
|
DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)BtnMovementCallback );
|
|
if ( iActionIcons[ TALK_ICON ] == -1 )
|
|
{
|
|
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, "Cannot create Interface button" );
|
|
return;
|
|
}
|
|
//SetButtonSavedRect( iActionIcons[ TALK_ICON ] );
|
|
SetButtonFastHelpText( iActionIcons[ TALK_ICON ], pTacticalPopupButtonStrings[ TALK_ICON ] );
|
|
ButtonList[ iActionIcons[ TALK_ICON ] ]->UserData[0] = (UINT32)pUIEvent;
|
|
|
|
if ( AM_AN_EPC( pSoldier ) || ( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) )
|
|
{
|
|
DisableButton( iActionIcons[ TALK_ICON ] );
|
|
}
|
|
|
|
|
|
iActionIcons[ HAND_ICON ] = QuickCreateButton( iIconImages[ HAND_IMAGES ], (INT16)(iMenuAnchorX + 20 ), (INT16)(iMenuAnchorY + 40 ),
|
|
BUTTON_NO_TOGGLE, MSYS_PRIORITY_HIGHEST - 1,
|
|
DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)BtnMovementCallback );
|
|
if ( iActionIcons[ HAND_ICON ] == -1 )
|
|
{
|
|
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, "Cannot create Interface button" );
|
|
return;
|
|
}
|
|
//SetButtonSavedRect( iActionIcons[ HAND_ICON ] );
|
|
SetButtonFastHelpText( iActionIcons[ HAND_ICON ], pTacticalPopupButtonStrings[ HAND_ICON ] );
|
|
ButtonList[ iActionIcons[ HAND_ICON ] ]->UserData[0] = (UINT32)pUIEvent;
|
|
|
|
if ( AM_AN_EPC( pSoldier ) || ( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) )
|
|
{
|
|
DisableButton( iActionIcons[ HAND_ICON ] );
|
|
}
|
|
|
|
iActionIcons[ CANCEL_ICON ] = QuickCreateButton( iIconImages[ CANCEL_IMAGES ], (INT16)(iMenuAnchorX + 20 ), (INT16)(iMenuAnchorY + 20 ),
|
|
BUTTON_NO_TOGGLE, MSYS_PRIORITY_HIGHEST - 1,
|
|
DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)BtnMovementCallback );
|
|
if ( iActionIcons[ CANCEL_ICON ] == -1 )
|
|
{
|
|
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, "Cannot create Interface button" );
|
|
return;
|
|
}
|
|
//SetButtonSavedRect( iActionIcons[ CANCEL_ICON ] );
|
|
SetButtonFastHelpText( iActionIcons[ CANCEL_ICON ], pTacticalPopupButtonStrings[ CANCEL_ICON ] );
|
|
ButtonList[ iActionIcons[ CANCEL_ICON ] ]->UserData[0] = (UINT32)pUIEvent;
|
|
|
|
//LockTacticalInterface( );
|
|
|
|
gfInMovementMenu = TRUE;
|
|
|
|
// Ignore scrolling
|
|
gfIgnoreScrolling = TRUE;
|
|
|
|
}
|
|
|
|
void PopDownMovementMenu( )
|
|
{
|
|
if ( gfInMovementMenu )
|
|
{
|
|
RemoveButton( iActionIcons[ WALK_ICON ] );
|
|
RemoveButton( iActionIcons[ SNEAK_ICON ] );
|
|
RemoveButton( iActionIcons[ RUN_ICON ] );
|
|
RemoveButton( iActionIcons[ CRAWL_ICON ] );
|
|
RemoveButton( iActionIcons[ LOOK_ICON ] );
|
|
RemoveButton( iActionIcons[ ACTIONC_ICON ] );
|
|
RemoveButton( iActionIcons[ TALK_ICON ] );
|
|
RemoveButton( iActionIcons[ HAND_ICON ] );
|
|
RemoveButton( iActionIcons[ CANCEL_ICON ] );
|
|
|
|
// Turn off Ignore scrolling
|
|
gfIgnoreScrolling = FALSE;
|
|
|
|
// Rerender world
|
|
SetRenderFlags( RENDER_FLAG_FULL );
|
|
|
|
fInterfacePanelDirty = DIRTYLEVEL2;
|
|
|
|
//UnLockTacticalInterface( );
|
|
MSYS_RemoveRegion( &gMenuOverlayRegion );
|
|
|
|
}
|
|
|
|
gfInMovementMenu = FALSE;
|
|
|
|
}
|
|
|
|
void RenderMovementMenu( )
|
|
{
|
|
if ( gfInMovementMenu )
|
|
{
|
|
BltVideoObjectFromIndex( FRAME_BUFFER, guiBUTTONBORDER, 0, giMenuAnchorX, giMenuAnchorY, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
|
|
// Mark buttons dirty!
|
|
MarkAButtonDirty( iActionIcons[ WALK_ICON ] );
|
|
MarkAButtonDirty( iActionIcons[ SNEAK_ICON ] );
|
|
MarkAButtonDirty( iActionIcons[ RUN_ICON ] );
|
|
MarkAButtonDirty( iActionIcons[ CRAWL_ICON ] );
|
|
MarkAButtonDirty( iActionIcons[ LOOK_ICON ] );
|
|
MarkAButtonDirty( iActionIcons[ ACTIONC_ICON ] );
|
|
MarkAButtonDirty( iActionIcons[ TALK_ICON ] );
|
|
MarkAButtonDirty( iActionIcons[ HAND_ICON ] );
|
|
MarkAButtonDirty( iActionIcons[ CANCEL_ICON ] );
|
|
|
|
InvalidateRegion( giMenuAnchorX, giMenuAnchorY, giMenuAnchorX + BUTTON_PANEL_WIDTH, giMenuAnchorY + BUTTON_PANEL_HEIGHT );
|
|
|
|
}
|
|
}
|
|
|
|
void CancelMovementMenu( )
|
|
{
|
|
// Signal end of event
|
|
PopDownMovementMenu( );
|
|
guiPendingOverrideEvent = A_CHANGE_TO_MOVE;
|
|
}
|
|
|
|
void BtnMovementCallback(GUI_BUTTON *btn,INT32 reason)
|
|
{
|
|
INT32 uiBtnID;
|
|
UI_EVENT *pUIEvent;
|
|
|
|
if ( reason & MSYS_CALLBACK_REASON_LBUTTON_UP )
|
|
{
|
|
btn->uiFlags |= BUTTON_CLICKED_ON;
|
|
|
|
uiBtnID = btn->IDNum;
|
|
|
|
pUIEvent = (UI_EVENT*)( btn->UserData[0] );
|
|
|
|
if ( uiBtnID == iActionIcons[ WALK_ICON ] )
|
|
{
|
|
pUIEvent->uiParams[0] = MOVEMENT_MENU_WALK;
|
|
}
|
|
else if ( uiBtnID == iActionIcons[ RUN_ICON ] )
|
|
{
|
|
pUIEvent->uiParams[0] = MOVEMENT_MENU_RUN;
|
|
}
|
|
else if ( uiBtnID == iActionIcons[ SNEAK_ICON ] )
|
|
{
|
|
pUIEvent->uiParams[0] = MOVEMENT_MENU_SWAT;
|
|
}
|
|
else if ( uiBtnID == iActionIcons[ CRAWL_ICON ] )
|
|
{
|
|
pUIEvent->uiParams[0] = MOVEMENT_MENU_PRONE;
|
|
}
|
|
else if ( uiBtnID == iActionIcons[ LOOK_ICON ] )
|
|
{
|
|
pUIEvent->uiParams[2] = MOVEMENT_MENU_LOOK;
|
|
}
|
|
else if ( uiBtnID == iActionIcons[ ACTIONC_ICON ] )
|
|
{
|
|
pUIEvent->uiParams[2] = MOVEMENT_MENU_ACTIONC;
|
|
}
|
|
else if ( uiBtnID == iActionIcons[ TALK_ICON ] )
|
|
{
|
|
pUIEvent->uiParams[2] = MOVEMENT_MENU_TALK;
|
|
}
|
|
else if ( uiBtnID == iActionIcons[ HAND_ICON ] )
|
|
{
|
|
pUIEvent->uiParams[2] = MOVEMENT_MENU_HAND;
|
|
}
|
|
else if ( uiBtnID == iActionIcons[ CANCEL_ICON ] )
|
|
{
|
|
// Signal end of event
|
|
EndMenuEvent( U_MOVEMENT_MENU );
|
|
pUIEvent->uiParams[1] = FALSE;
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Signal end of event
|
|
EndMenuEvent( U_MOVEMENT_MENU );
|
|
pUIEvent->uiParams[1] = TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void HandleUpDownArrowBackgrounds( )
|
|
{
|
|
static UINT32 uiOldShowUpDownArrows = ARROWS_HIDE_UP | ARROWS_HIDE_DOWN;
|
|
|
|
// Check for change in mode
|
|
if ( guiShowUPDownArrows != uiOldShowUpDownArrows || gfUIRefreshArrows )
|
|
{
|
|
gfUIRefreshArrows = FALSE;
|
|
|
|
// Hide position of new ones
|
|
GetArrowsBackground( );
|
|
|
|
uiOldShowUpDownArrows = guiShowUPDownArrows;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void RenderArrows( )
|
|
{
|
|
TILE_ELEMENT TileElem;
|
|
|
|
if ( guiShowUPDownArrows & ARROWS_HIDE_UP && guiShowUPDownArrows & ARROWS_HIDE_DOWN )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ( guiShowUPDownArrows & ARROWS_SHOW_UP_BESIDE )
|
|
{
|
|
TileElem = gTileDatabase[ SECONDPOINTERS3 ];
|
|
BltVideoObject( FRAME_BUFFER, TileElem.hTileSurface, TileElem.usRegionIndex, gsUpArrowX, gsUpArrowY, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
}
|
|
|
|
if ( guiShowUPDownArrows & ARROWS_SHOW_UP_ABOVE_G )
|
|
{
|
|
TileElem = gTileDatabase[ SECONDPOINTERS1 ];
|
|
BltVideoObject( FRAME_BUFFER, TileElem.hTileSurface, TileElem.usRegionIndex, gsUpArrowX, gsUpArrowY, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
}
|
|
|
|
if ( guiShowUPDownArrows & ARROWS_SHOW_UP_ABOVE_Y )
|
|
{
|
|
TileElem = gTileDatabase[ SECONDPOINTERS3 ];
|
|
BltVideoObject( FRAME_BUFFER, TileElem.hTileSurface, TileElem.usRegionIndex, gsUpArrowX, gsUpArrowY, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
}
|
|
|
|
if ( guiShowUPDownArrows & ARROWS_SHOW_UP_ABOVE_YG )
|
|
{
|
|
TileElem = gTileDatabase[ SECONDPOINTERS3 ];
|
|
BltVideoObject( FRAME_BUFFER, TileElem.hTileSurface, TileElem.usRegionIndex, gsUpArrowX, gsUpArrowY, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
TileElem = gTileDatabase[ SECONDPOINTERS1 ];
|
|
BltVideoObject( FRAME_BUFFER, TileElem.hTileSurface, TileElem.usRegionIndex, gsUpArrowX, gsUpArrowY + 20, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
}
|
|
|
|
if ( guiShowUPDownArrows & ARROWS_SHOW_UP_ABOVE_GG )
|
|
{
|
|
TileElem = gTileDatabase[ SECONDPOINTERS1 ];
|
|
BltVideoObject( FRAME_BUFFER, TileElem.hTileSurface, TileElem.usRegionIndex, gsUpArrowX, gsUpArrowY, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
BltVideoObject( FRAME_BUFFER, TileElem.hTileSurface, TileElem.usRegionIndex, gsUpArrowX, gsUpArrowY + 20, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
}
|
|
|
|
if ( guiShowUPDownArrows & ARROWS_SHOW_UP_ABOVE_YY )
|
|
{
|
|
TileElem = gTileDatabase[ SECONDPOINTERS3 ];
|
|
BltVideoObject( FRAME_BUFFER, TileElem.hTileSurface, TileElem.usRegionIndex, gsUpArrowX, gsUpArrowY, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
BltVideoObject( FRAME_BUFFER, TileElem.hTileSurface, TileElem.usRegionIndex, gsUpArrowX, gsUpArrowY + 20, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
}
|
|
|
|
if ( guiShowUPDownArrows & ARROWS_SHOW_UP_ABOVE_CLIMB )
|
|
{
|
|
TileElem = gTileDatabase[ SECONDPOINTERS8 ];
|
|
BltVideoObject( FRAME_BUFFER, TileElem.hTileSurface, TileElem.usRegionIndex, gsUpArrowX, gsUpArrowY, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
}
|
|
|
|
if ( guiShowUPDownArrows & ARROWS_SHOW_UP_ABOVE_CLIMB2 )
|
|
{
|
|
TileElem = gTileDatabase[ SECONDPOINTERS3 ];
|
|
BltVideoObject( FRAME_BUFFER, TileElem.hTileSurface, TileElem.usRegionIndex, gsUpArrowX, gsUpArrowY + 20, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
TileElem = gTileDatabase[ SECONDPOINTERS8 ];
|
|
BltVideoObject( FRAME_BUFFER, TileElem.hTileSurface, TileElem.usRegionIndex, gsUpArrowX, gsUpArrowY, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
}
|
|
|
|
if ( guiShowUPDownArrows & ARROWS_SHOW_UP_ABOVE_CLIMB3 )
|
|
{
|
|
TileElem = gTileDatabase[ SECONDPOINTERS3 ];
|
|
BltVideoObject( FRAME_BUFFER, TileElem.hTileSurface, TileElem.usRegionIndex, gsUpArrowX, gsUpArrowY, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
TileElem = gTileDatabase[ SECONDPOINTERS8 ];
|
|
BltVideoObject( FRAME_BUFFER, TileElem.hTileSurface, TileElem.usRegionIndex, gsUpArrowX, gsUpArrowY + 20, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
BltVideoObject( FRAME_BUFFER, TileElem.hTileSurface, TileElem.usRegionIndex, gsUpArrowX, gsUpArrowY + 40, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
}
|
|
|
|
if ( guiShowUPDownArrows & ARROWS_SHOW_DOWN_BESIDE )
|
|
{
|
|
TileElem = gTileDatabase[ SECONDPOINTERS4 ];
|
|
BltVideoObject( FRAME_BUFFER, TileElem.hTileSurface, TileElem.usRegionIndex, gsDownArrowX, gsDownArrowY, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
}
|
|
|
|
if ( guiShowUPDownArrows & ARROWS_SHOW_DOWN_BELOW_G )
|
|
{
|
|
TileElem = gTileDatabase[ SECONDPOINTERS2 ];
|
|
BltVideoObject( FRAME_BUFFER, TileElem.hTileSurface, TileElem.usRegionIndex, gsDownArrowX, gsDownArrowY, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
}
|
|
|
|
if ( guiShowUPDownArrows & ARROWS_SHOW_DOWN_BELOW_Y )
|
|
{
|
|
TileElem = gTileDatabase[ SECONDPOINTERS4 ];
|
|
BltVideoObject( FRAME_BUFFER, TileElem.hTileSurface, TileElem.usRegionIndex, gsDownArrowX, gsDownArrowY, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
}
|
|
|
|
if ( guiShowUPDownArrows & ARROWS_SHOW_DOWN_CLIMB )
|
|
{
|
|
TileElem = gTileDatabase[ SECONDPOINTERS7 ];
|
|
BltVideoObject( FRAME_BUFFER, TileElem.hTileSurface, TileElem.usRegionIndex, gsDownArrowX, gsDownArrowY, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
}
|
|
|
|
if ( guiShowUPDownArrows & ARROWS_SHOW_DOWN_BELOW_YG )
|
|
{
|
|
TileElem = gTileDatabase[ SECONDPOINTERS2 ];
|
|
BltVideoObject( FRAME_BUFFER, TileElem.hTileSurface, TileElem.usRegionIndex, gsDownArrowX, gsDownArrowY, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
TileElem = gTileDatabase[ SECONDPOINTERS4 ];
|
|
BltVideoObject( FRAME_BUFFER, TileElem.hTileSurface, TileElem.usRegionIndex, gsDownArrowX, gsDownArrowY + 20, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
}
|
|
|
|
if ( guiShowUPDownArrows & ARROWS_SHOW_DOWN_BELOW_GG )
|
|
{
|
|
TileElem = gTileDatabase[ SECONDPOINTERS2 ];
|
|
BltVideoObject( FRAME_BUFFER, TileElem.hTileSurface, TileElem.usRegionIndex, gsDownArrowX, gsDownArrowY, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
BltVideoObject( FRAME_BUFFER, TileElem.hTileSurface, TileElem.usRegionIndex, gsDownArrowX, gsDownArrowY + 20, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
}
|
|
|
|
if ( guiShowUPDownArrows & ARROWS_SHOW_DOWN_BELOW_YY )
|
|
{
|
|
TileElem = gTileDatabase[ SECONDPOINTERS4 ];
|
|
BltVideoObject( FRAME_BUFFER, TileElem.hTileSurface, TileElem.usRegionIndex, gsDownArrowX, gsDownArrowY, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
BltVideoObject( FRAME_BUFFER, TileElem.hTileSurface, TileElem.usRegionIndex, gsDownArrowX, gsDownArrowY + 20, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
}
|
|
|
|
|
|
}
|
|
|
|
void EraseRenderArrows( )
|
|
{
|
|
if ( giUpArrowRect != 0 )
|
|
{
|
|
if ( giUpArrowRect != -1 )
|
|
{
|
|
FreeBackgroundRect( giUpArrowRect );
|
|
}
|
|
}
|
|
giUpArrowRect = 0;
|
|
|
|
if ( giDownArrowRect != 0 )
|
|
{
|
|
if ( giDownArrowRect != -1 )
|
|
{
|
|
FreeBackgroundRect( giDownArrowRect );
|
|
}
|
|
}
|
|
giDownArrowRect = 0;
|
|
}
|
|
|
|
void GetArrowsBackground( )
|
|
{
|
|
SOLDIERTYPE *pSoldier;
|
|
INT16 sMercScreenX, sMercScreenY;
|
|
UINT16 sArrowHeight = ARROWS_HEIGHT, sArrowWidth = ARROWS_WIDTH;
|
|
|
|
if ( guiShowUPDownArrows & ARROWS_HIDE_UP && guiShowUPDownArrows & ARROWS_HIDE_DOWN )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ( gusSelectedSoldier != NOBODY )
|
|
{
|
|
// Get selected soldier
|
|
GetSoldier( &pSoldier, gusSelectedSoldier );
|
|
|
|
// Get screen position of our guy
|
|
GetSoldierTRUEScreenPos( pSoldier, &sMercScreenX, &sMercScreenY );
|
|
|
|
if ( guiShowUPDownArrows & ARROWS_SHOW_UP_BESIDE )
|
|
{
|
|
// Setup blt rect
|
|
gsUpArrowX = sMercScreenX + ARROWS_X_OFFSET;
|
|
gsUpArrowY = sMercScreenY + UPARROW_Y_OFFSET;
|
|
}
|
|
|
|
if ( guiShowUPDownArrows & ARROWS_SHOW_UP_ABOVE_G || guiShowUPDownArrows & ARROWS_SHOW_UP_ABOVE_Y )
|
|
{
|
|
// Setup blt rect
|
|
gsUpArrowX = sMercScreenX - 10;
|
|
gsUpArrowY = sMercScreenY - 50;
|
|
}
|
|
|
|
if ( guiShowUPDownArrows & ARROWS_SHOW_UP_ABOVE_YG || guiShowUPDownArrows & ARROWS_SHOW_UP_ABOVE_GG || guiShowUPDownArrows & ARROWS_SHOW_UP_ABOVE_YY )
|
|
{
|
|
// Setup blt rect
|
|
gsUpArrowX = sMercScreenX - 10;
|
|
gsUpArrowY = sMercScreenY - 70;
|
|
sArrowHeight = 3 * ARROWS_HEIGHT;
|
|
}
|
|
|
|
if ( guiShowUPDownArrows & ARROWS_SHOW_UP_ABOVE_CLIMB )
|
|
{
|
|
// Setup blt rect
|
|
gsUpArrowX = sMercScreenX - 10;
|
|
gsUpArrowY = sMercScreenY - 70;
|
|
sArrowHeight = 2 * ARROWS_HEIGHT;
|
|
}
|
|
|
|
if ( guiShowUPDownArrows & ARROWS_SHOW_UP_ABOVE_CLIMB2 )
|
|
{
|
|
// Setup blt rect
|
|
gsUpArrowX = sMercScreenX - 10;
|
|
gsUpArrowY = sMercScreenY - 80;
|
|
sArrowHeight = 3 * ARROWS_HEIGHT;
|
|
}
|
|
|
|
if ( guiShowUPDownArrows & ARROWS_SHOW_UP_ABOVE_CLIMB3 )
|
|
{
|
|
// Setup blt rect
|
|
gsUpArrowX = sMercScreenX - 10;
|
|
gsUpArrowY = sMercScreenY - 900;
|
|
sArrowHeight = 5 * ARROWS_HEIGHT;
|
|
}
|
|
|
|
|
|
if ( guiShowUPDownArrows & ARROWS_SHOW_DOWN_BESIDE )
|
|
{
|
|
gsDownArrowX = sMercScreenX + ARROWS_X_OFFSET;
|
|
gsDownArrowY = sMercScreenY + DOWNARROW_Y_OFFSET;
|
|
}
|
|
|
|
if ( guiShowUPDownArrows & ARROWS_SHOW_DOWN_BELOW_Y || guiShowUPDownArrows & ARROWS_SHOW_DOWN_BELOW_G )
|
|
{
|
|
gsDownArrowX = sMercScreenX -10;
|
|
gsDownArrowY = sMercScreenY + 10;
|
|
}
|
|
|
|
if ( guiShowUPDownArrows & ARROWS_SHOW_DOWN_CLIMB )
|
|
{
|
|
gsDownArrowX = sMercScreenX - 10;
|
|
gsDownArrowY = sMercScreenY + 10;
|
|
sArrowHeight = 3 * ARROWS_HEIGHT;
|
|
}
|
|
|
|
if ( guiShowUPDownArrows & ARROWS_SHOW_DOWN_BELOW_YG || guiShowUPDownArrows & ARROWS_SHOW_DOWN_BELOW_GG || guiShowUPDownArrows & ARROWS_SHOW_DOWN_BELOW_YY )
|
|
{
|
|
gsDownArrowX = sMercScreenX -10;
|
|
gsDownArrowY = sMercScreenY + 10;
|
|
sArrowHeight = 3 * ARROWS_HEIGHT;
|
|
}
|
|
|
|
// Adjust arrows based on level
|
|
if ( gsInterfaceLevel == I_ROOF_LEVEL )
|
|
{
|
|
// gsDownArrowY -= ROOF_LEVEL_HEIGHT;
|
|
// gsUpArrowY -= ROOF_LEVEL_HEIGHT;
|
|
}
|
|
|
|
//Erase prevois ones...
|
|
EraseRenderArrows( );
|
|
|
|
// Register dirty rects
|
|
giDownArrowRect = RegisterBackgroundRect(BGND_FLAG_PERMANENT, NULL, gsDownArrowX, gsDownArrowY, (INT16)(gsDownArrowX + sArrowWidth), (INT16)(gsDownArrowY + sArrowHeight ) );
|
|
giUpArrowRect = RegisterBackgroundRect(BGND_FLAG_PERMANENT, NULL, gsUpArrowX, gsUpArrowY, (INT16)(gsUpArrowX + sArrowWidth), (INT16)(gsUpArrowY + sArrowHeight ) );
|
|
}
|
|
}
|
|
|
|
|
|
void GetSoldierAboveGuyPositions( SOLDIERTYPE *pSoldier, INT16 *psX, INT16 *psY, BOOLEAN fRadio )
|
|
{
|
|
INT16 sMercScreenX, sMercScreenY;
|
|
INT16 sOffsetX, sOffsetY;
|
|
UINT8 ubAnimUseHeight;
|
|
INT16 sStanceOffset = 0;
|
|
INT16 sTextBodyTypeYOffset = 62;
|
|
|
|
// Find XY, dims, offsets
|
|
GetSoldierScreenPos( pSoldier, &sMercScreenX, &sMercScreenY );
|
|
GetSoldierAnimOffsets( pSoldier, &sOffsetX, &sOffsetY );
|
|
|
|
// OK, first thing to do is subtract offsets ( because GetSoldierScreenPos adds them... )
|
|
sMercScreenX -= sOffsetX;
|
|
sMercScreenY -= sOffsetY;
|
|
|
|
// Adjust based on stance
|
|
if ( ( gAnimControl[ pSoldier->usAnimState ].uiFlags & ANIM_NOMOVE_MARKER) )
|
|
{
|
|
ubAnimUseHeight = gAnimControl[ pSoldier->usAnimState ].ubHeight;
|
|
}
|
|
else
|
|
{
|
|
ubAnimUseHeight = gAnimControl[ pSoldier->usAnimState ].ubEndHeight;
|
|
}
|
|
switch ( ubAnimUseHeight )
|
|
{
|
|
case ANIM_STAND:
|
|
break;
|
|
|
|
case ANIM_PRONE:
|
|
sStanceOffset = 25;
|
|
break;
|
|
|
|
case ANIM_CROUCH:
|
|
sStanceOffset = 10;
|
|
break;
|
|
}
|
|
|
|
// Adjust based on body type...
|
|
switch( pSoldier->ubBodyType )
|
|
{
|
|
case CROW:
|
|
|
|
sStanceOffset = 30;
|
|
break;
|
|
|
|
case ROBOTNOWEAPON:
|
|
|
|
sStanceOffset = 30;
|
|
break;
|
|
|
|
}
|
|
|
|
//sStanceOffset -= gpWorldLevelData[ pSoldier->sGridNo ].sHeight;
|
|
|
|
// Adjust based on level
|
|
if ( pSoldier->pathing.bLevel == 1 && gsInterfaceLevel == 0 )
|
|
{
|
|
//sStanceOffset -= ROOF_LEVEL_HEIGHT;
|
|
}
|
|
if ( pSoldier->pathing.bLevel == 0 && gsInterfaceLevel == 1 )
|
|
{
|
|
//sStanceOffset += ROOF_LEVEL_HEIGHT;
|
|
}
|
|
|
|
if ( pSoldier->ubProfile != NO_PROFILE )
|
|
{
|
|
if ( fRadio )
|
|
{
|
|
*psX = sMercScreenX - ( 80 / 2 ) - pSoldier->sLocatorOffX;
|
|
*psY = sMercScreenY - sTextBodyTypeYOffset + sStanceOffset;
|
|
}
|
|
else
|
|
{
|
|
*psX = sMercScreenX - ( 80 / 2 ) - pSoldier->sLocatorOffX;
|
|
*psY = sMercScreenY - sTextBodyTypeYOffset + sStanceOffset;
|
|
|
|
// OK, Check if we need to go below....
|
|
// Can do this 1) if displaying damge or 2 ) above screen
|
|
|
|
// If not a radio position, adjust if we are getting hit, to be lower!
|
|
// If we are getting hit, lower them!
|
|
if ( pSoldier->flags.fDisplayDamage || *psY < gsVIEWPORT_WINDOW_START_Y )
|
|
{
|
|
*psX = sMercScreenX - ( 80 / 2 ) - pSoldier->sLocatorOffX;
|
|
*psY = sMercScreenY;
|
|
}
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
//Display Text!
|
|
*psX = sMercScreenX - ( 80 / 2 ) - pSoldier->sLocatorOffX;
|
|
*psY = sMercScreenY - sTextBodyTypeYOffset + sStanceOffset;
|
|
}
|
|
}
|
|
|
|
void DrawCTHPixelToBuffer( UINT16 *pBuffer, UINT32 uiPitch, INT16 sLeft, INT16 sTop, INT16 sRight, INT16 sBottom, INT16 sPixelX, INT16 sPixelY, UINT16 usColor )
|
|
{
|
|
///////////////////////////////////////////////////////////
|
|
// HEADROCK HAM 4:
|
|
//
|
|
// This is a specialized drawing function that's used for the CTH indicator. It makes sure that the
|
|
// pixel is drawn only within the allowed region (the Tactical Viewport), and never drawn in regions
|
|
// reserved for other parts of the CTH indicator.
|
|
|
|
if (sPixelX < sLeft || sPixelX > sRight || sPixelY < sTop || sPixelY > (sBottom-1))
|
|
{
|
|
return;
|
|
}
|
|
// Do not draw in other CTH rects!
|
|
if ((sPixelX >= MagRect.left && sPixelX <= MagRect.right) && (sPixelY >= MagRect.top && sPixelY <= MagRect.bottom))
|
|
{
|
|
return;
|
|
}
|
|
if ((sPixelX >= AimRect.left && sPixelX <= AimRect.right) && (sPixelY >= AimRect.top && sPixelY <= AimRect.bottom))
|
|
{
|
|
return;
|
|
}
|
|
if ((sPixelX >= ModeRect.left && sPixelX <= ModeRect.right) && (sPixelY >= ModeRect.top && sPixelY <= ModeRect.bottom))
|
|
{
|
|
return;
|
|
}
|
|
if ((sPixelX >= APRect.left && sPixelX <= APRect.right) && (sPixelY >= APRect.top && sPixelY <= APRect.bottom))
|
|
{
|
|
return;
|
|
}
|
|
// sevenfm: added additional right, left rectangles
|
|
if ((sPixelX >= RightRect.left && sPixelX <= RightRect.right) && (sPixelY >= RightRect.top && sPixelY <= RightRect.bottom))
|
|
{
|
|
return;
|
|
}
|
|
if ((sPixelX >= LeftRect.left && sPixelX <= LeftRect.right) && (sPixelY >= LeftRect.top && sPixelY <= LeftRect.bottom))
|
|
{
|
|
return;
|
|
}
|
|
if ((sPixelX >= LeftRect2.left && sPixelX <= LeftRect2.right) && (sPixelY >= LeftRect2.top && sPixelY <= LeftRect2.bottom))
|
|
{
|
|
return;
|
|
}
|
|
|
|
pBuffer[sPixelX + uiPitch*sPixelY] = usColor;
|
|
}
|
|
|
|
//QUOTE_SYSTEM_STRUCT soldierTTInfo;
|
|
|
|
void DrawSelectedUIAboveGuy( UINT16 usSoldierID )
|
|
{
|
|
SOLDIERTYPE *pSoldier;
|
|
INT16 sXPos, sYPos;
|
|
INT16 sX, sY;
|
|
INT32 iBack;
|
|
TILE_ELEMENT TileElem;
|
|
CHAR16 *pStr;
|
|
CHAR16 NameStr[ MAX_ENEMY_NAMES_CHARS ];
|
|
UINT16 usGraphicToUse = THIRDPOINTERS1;
|
|
BOOLEAN fRaiseName = FALSE;
|
|
BOOLEAN fDoName = TRUE;
|
|
UINT16 iCounter2;
|
|
INT16 maxWidth = 40; // sevenfm: maximum string length (in pixels) is used to determine x coordinate for additional info
|
|
|
|
GetSoldier( &pSoldier, usSoldierID );
|
|
|
|
if ( !pSoldier || (pSoldier->bVisible == -1 && !(gTacticalStatus.uiFlags&SHOW_ALL_MERCS) ) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (TileIsOutOfBounds(pSoldier->sGridNo))
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ( pSoldier->flags.fFlashLocator )
|
|
{
|
|
if ( pSoldier->bVisible == -1 )
|
|
{
|
|
pSoldier->flags.fFlashLocator = FALSE;
|
|
}
|
|
else
|
|
{
|
|
if ( TIMECOUNTERDONE( pSoldier->timeCounters.BlinkSelCounter, 80 ) )
|
|
{
|
|
RESETTIMECOUNTER( pSoldier->timeCounters.BlinkSelCounter, 80 );
|
|
|
|
// pSoldier->flags.fShowLocator = !pSoldier->flags.fShowLocator;
|
|
|
|
pSoldier->flags.fShowLocator = TRUE;
|
|
|
|
// Update frame
|
|
pSoldier->sLocatorFrame++;
|
|
|
|
if ( pSoldier->sLocatorFrame == 5 )
|
|
{
|
|
// Update time we do this
|
|
pSoldier->flags.fFlashLocator++;
|
|
pSoldier->sLocatorFrame = 0;
|
|
}
|
|
}
|
|
|
|
//if ( TIMECOUNTERDONE( pSoldier->timeCounters.FlashSelCounter, 5000 ) )
|
|
//{
|
|
// RESETTIMECOUNTER( pSoldier->timeCounters.FlashSelCounter, 5000 );
|
|
|
|
// pSoldier->flags.fFlashLocator = FALSE;
|
|
// pSoldier->flags.fShowLocator = FALSE;
|
|
|
|
//}
|
|
if ( pSoldier->flags.fFlashLocator == pSoldier->ubNumLocateCycles )
|
|
{
|
|
pSoldier->flags.fFlashLocator = FALSE;
|
|
pSoldier->flags.fShowLocator = FALSE;
|
|
}
|
|
|
|
//if ( pSoldier->flags.fShowLocator )
|
|
{
|
|
// Render the beastie
|
|
GetSoldierAboveGuyPositions( pSoldier, &sXPos, &sYPos, TRUE );
|
|
|
|
// Adjust for bars!
|
|
sXPos += 25;
|
|
sYPos += 25;
|
|
|
|
//sXPos += 15;
|
|
//sYPos += 21;
|
|
|
|
|
|
// Add bars
|
|
//iBack = RegisterBackgroundRect( BGND_FLAG_SINGLE, NULL, sXPos, sYPos, (INT16)(sXPos + 55 ), (INT16)(sYPos + 80 ) );
|
|
iBack = RegisterBackgroundRect( BGND_FLAG_SINGLE, NULL, sXPos, sYPos, (INT16)(sXPos +40 ), (INT16)(sYPos + 40 ) );
|
|
|
|
if ( iBack != -1 )
|
|
{
|
|
SetBackgroundRectFilled( iBack );
|
|
}
|
|
|
|
if ( !pSoldier->aiData.bNeutral && ( pSoldier->bSide != gbPlayerNum ) )
|
|
{
|
|
BltVideoObjectFromIndex( FRAME_BUFFER, guiRADIO2, pSoldier->sLocatorFrame, sXPos, sYPos, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
}
|
|
else
|
|
{
|
|
BltVideoObjectFromIndex( FRAME_BUFFER, guiRADIO, pSoldier->sLocatorFrame, sXPos, sYPos, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
|
|
//BltVideoObjectFromIndex( FRAME_BUFFER, guiRADIO, 0, sXPos, sYPos, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// Flugente: show a small animation hat signifies that a merc is underwater (hopefully temporary until someone comes up with a proper animation)
|
|
else if ( pSoldier->UsesScubaGear() )
|
|
{
|
|
if ( TIMECOUNTERDONE( pSoldier->timeCounters.BlinkSelCounter, 320 ) )
|
|
{
|
|
RESETTIMECOUNTER( pSoldier->timeCounters.BlinkSelCounter, 320 );
|
|
|
|
// Update frame
|
|
pSoldier->sLocatorFrame++;
|
|
|
|
if ( pSoldier->sLocatorFrame == 5 )
|
|
{
|
|
// Update time we do this
|
|
pSoldier->sLocatorFrame = 0;
|
|
}
|
|
}
|
|
|
|
if ( pSoldier->flags.fFlashLocator == pSoldier->ubNumLocateCycles )
|
|
{
|
|
pSoldier->flags.fShowLocator = FALSE;
|
|
}
|
|
|
|
if ( gGameExternalOptions.ubShowHealthBarsOnHead )
|
|
{
|
|
// Render the beastie
|
|
GetSoldierAboveGuyPositions( pSoldier, &sXPos, &sYPos, TRUE );
|
|
|
|
// Adjust for bars!
|
|
sXPos += 25;
|
|
sYPos += 25;
|
|
|
|
// Add bars
|
|
iBack = RegisterBackgroundRect( BGND_FLAG_SINGLE, NULL, sXPos, sYPos, (INT16)(sXPos +40 ), (INT16)(sYPos + 40 ) );
|
|
|
|
if ( iBack != -1 )
|
|
{
|
|
SetBackgroundRectFilled( iBack );
|
|
}
|
|
|
|
BltVideoObjectFromIndex( FRAME_BUFFER, guiUNDERWATER, pSoldier->sLocatorFrame, sXPos, sYPos, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
}
|
|
}
|
|
|
|
if ( gDisplayEnemyRoles && pSoldier->bTeam == ENEMY_TEAM )
|
|
{
|
|
ShowSoldierRoleSymbol(pSoldier);
|
|
}
|
|
|
|
if ( !pSoldier->flags.fShowLocator )
|
|
{
|
|
// RETURN IF MERC IS NOT SELECTED
|
|
if ( gfUIHandleSelectionAboveGuy && pSoldier->ubID == gsSelectedGuy && pSoldier->ubID != gusSelectedSoldier && !gfIgnoreOnSelectedGuy )
|
|
{
|
|
|
|
}
|
|
else if ( pSoldier->ubID == gusSelectedSoldier && !gRubberBandActive )
|
|
{
|
|
usGraphicToUse = THIRDPOINTERS2;
|
|
}
|
|
// show all people's names if !
|
|
//else if ( pSoldier->ubID >= 20 && pSoldier->bVisible != -1 )
|
|
//{
|
|
|
|
//}
|
|
else if ( pSoldier->flags.uiStatusFlags & SOLDIER_MULTI_SELECTED )
|
|
{
|
|
|
|
}
|
|
else
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( pSoldier->ubID == gusSelectedSoldier && !gRubberBandActive )
|
|
{
|
|
usGraphicToUse = THIRDPOINTERS2;
|
|
}
|
|
}
|
|
|
|
// If he is in the middle of a certain animation, ignore!
|
|
if ( gAnimControl[ pSoldier->usAnimState ].uiFlags & ANIM_NOSHOW_MARKER )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Donot show if we are dead
|
|
if ( ( pSoldier->flags.uiStatusFlags & SOLDIER_DEAD ) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
GetSoldierAboveGuyPositions( pSoldier, &sXPos, &sYPos, FALSE );
|
|
|
|
// Display name
|
|
SetFont( TINYFONT1 );
|
|
SetFontBackground( FONT_MCOLOR_BLACK );
|
|
|
|
BOOLEAN bInCombat = gTacticalStatus.uiFlags & TURNBASED && gTacticalStatus.uiFlags & INCOMBAT;
|
|
BOOLEAN bStealth = pSoldier->bStealthMode || pSoldier->bSoldierFlagMask & ( SOLDIER_COVERT_CIV | SOLDIER_COVERT_SOLDIER );
|
|
// sevenfm: for mercs use name color as cover indicator
|
|
// only use color when there is enemy in sector
|
|
if( pSoldier->bTeam == OUR_TEAM &&
|
|
(NumEnemyInSector() != 0) &&
|
|
! ( pSoldier->flags.uiStatusFlags & ( SOLDIER_VEHICLE | SOLDIER_ROBOT) ) &&
|
|
( ( gGameExternalOptions.ubShowCoverIndicator == 1 && ( bInCombat || bStealth ) ) ||
|
|
( gGameExternalOptions.ubShowCoverIndicator == 2 && bStealth ) ) )
|
|
{
|
|
INT8 cover = 3; // MAX_COVER
|
|
BOOLEAN showCover;
|
|
INT32 usMapPos;
|
|
INT16 color8, color16;
|
|
|
|
if( GetMouseMapPos(&usMapPos) && _KeyDown(SHIFT) )
|
|
{
|
|
// target tile cover
|
|
CalculateCoverForSoldier( pSoldier, usMapPos, gsInterfaceLevel, cover );
|
|
showCover = CoverColorCode( cover, color8, color16 );
|
|
SetFontForeground( (UINT8)color8 );
|
|
}
|
|
else
|
|
{
|
|
// merc's cover
|
|
CalculateCoverForSoldier( pSoldier, pSoldier->sGridNo, pSoldier->pathing.bLevel, cover );
|
|
showCover = CoverColorCode( cover, color8, color16 );
|
|
SetFontForeground( (UINT8)color8 );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SetFontForeground( FONT_MCOLOR_WHITE );
|
|
}
|
|
|
|
if ( pSoldier->ubProfile != NO_PROFILE || ( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) )
|
|
{
|
|
if ( gfUIMouseOnValidCatcher == 1 && pSoldier->ubID == gubUIValidCatcherID )
|
|
{
|
|
swprintf( NameStr, TacticalStr[ CATCH_STR ] );
|
|
FindFontCenterCoordinates( sXPos, (INT16)(sYPos ), (INT16)(80 ), 1, NameStr, TINYFONT1, &sX, &sY );
|
|
gprintfdirty( sX, sY, NameStr );
|
|
mprintf( sX, sY, NameStr );
|
|
fRaiseName = TRUE;
|
|
}
|
|
else if ( gfUIMouseOnValidCatcher == 3 && pSoldier->ubID == gubUIValidCatcherID )
|
|
{
|
|
swprintf( NameStr, TacticalStr[ RELOAD_STR ] );
|
|
FindFontCenterCoordinates( sXPos, (INT16)(sYPos ), (INT16)(80 ), 1, NameStr, TINYFONT1, &sX, &sY );
|
|
gprintfdirty( sX, sY, NameStr );
|
|
mprintf( sX, sY, NameStr );
|
|
fRaiseName = TRUE;
|
|
}
|
|
else if ( gfUIMouseOnValidCatcher == 4 && pSoldier->ubID == gubUIValidCatcherID )
|
|
{
|
|
swprintf( NameStr, pMessageStrings[ MSG_PASS ] );
|
|
FindFontCenterCoordinates( sXPos, (INT16)(sYPos ), (INT16)(80 ), 1, NameStr, TINYFONT1, &sX, &sY );
|
|
gprintfdirty( sX, sY, NameStr );
|
|
mprintf( sX, sY, NameStr );
|
|
fRaiseName = TRUE;
|
|
}
|
|
else if ( pSoldier->bAssignment >= ON_DUTY )
|
|
{
|
|
SetFontForeground( FONT_YELLOW );
|
|
swprintf( NameStr, L"(%s)", pAssignmentStrings[ pSoldier->bAssignment ] );
|
|
FindFontCenterCoordinates( sXPos, (INT16)(sYPos ), (INT16)(80 ), 1, NameStr, TINYFONT1, &sX, &sY );
|
|
gprintfdirty( sX, sY, NameStr );
|
|
mprintf( sX, sY, NameStr );
|
|
fRaiseName = TRUE;
|
|
}
|
|
else if ( pSoldier->bTeam == gbPlayerNum && pSoldier->bAssignment < ON_DUTY && pSoldier->bAssignment != CurrentSquad() && !( pSoldier->flags.uiStatusFlags & SOLDIER_MULTI_SELECTED ) )
|
|
{
|
|
if ( gGameExternalOptions.fUseXMLSquadNames )
|
|
swprintf( NameStr, SquadNames[ pSoldier->bAssignment ].squadname );
|
|
else
|
|
swprintf( NameStr, gzLateLocalizedString[ 34 ], ( pSoldier->bAssignment + 1 ) );
|
|
|
|
FindFontCenterCoordinates( sXPos, (INT16)(sYPos ), (INT16)(80 ), 1, NameStr, TINYFONT1, &sX, &sY );
|
|
gprintfdirty( sX, sY, NameStr );
|
|
mprintf( sX, sY, NameStr );
|
|
fRaiseName = TRUE;
|
|
}
|
|
|
|
// If not in a squad....
|
|
if ( ( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) )
|
|
{
|
|
if ( GetNumberInVehicle( pSoldier->bVehicleID ) == 0 )
|
|
{
|
|
SetFontForeground( FONT_GRAY4 );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( pSoldier->bAssignment >= ON_DUTY )
|
|
{
|
|
SetFontForeground( FONT_YELLOW );
|
|
}
|
|
}
|
|
|
|
if ( fDoName )
|
|
{
|
|
if ( fRaiseName )
|
|
{
|
|
//legion2 jazz
|
|
if (pSoldier->ubBodyType == ROBOTNOWEAPON && pSoldier->bTeam == ENEMY_TEAM )
|
|
{
|
|
swprintf( NameStr, zGrod[0] );
|
|
}
|
|
else if (zHiddenNames[pSoldier->ubProfile].Hidden == TRUE)
|
|
{
|
|
swprintf( NameStr,L"???" );
|
|
}
|
|
else
|
|
{
|
|
swprintf( NameStr, L"%s", pSoldier->name );
|
|
}
|
|
|
|
//Legion
|
|
if (pSoldier->ubBodyType == TANK_NE || pSoldier->ubBodyType == TANK_NW)
|
|
{
|
|
swprintf( NameStr, gNewVehicle[164].NewVehicleStrings );
|
|
//swprintf( NameStr, pVehicleStrings[4] );
|
|
}
|
|
else if (zHiddenNames[pSoldier->ubProfile].Hidden == TRUE)
|
|
{
|
|
swprintf( NameStr,L"???" );
|
|
}
|
|
else
|
|
{
|
|
swprintf( NameStr, L"%s", pSoldier->name );
|
|
}
|
|
//-------
|
|
|
|
//swprintf( NameStr, L"%s", pSoldier->name );
|
|
FindFontCenterCoordinates( sXPos, (INT16)( sYPos - 10 ), (INT16)(80 ), 1, NameStr, TINYFONT1, &sX, &sY );
|
|
gprintfdirty( sX, sY, NameStr );
|
|
mprintf( sX, sY, NameStr );
|
|
}
|
|
else
|
|
{
|
|
//legion Jazz
|
|
if (pSoldier->ubBodyType == ROBOTNOWEAPON && pSoldier->bTeam == ENEMY_TEAM )
|
|
{
|
|
swprintf( NameStr, zGrod[0] );
|
|
}
|
|
else if (zHiddenNames[pSoldier->ubProfile].Hidden == TRUE)
|
|
{
|
|
swprintf( NameStr,L"???" );
|
|
}
|
|
else
|
|
{
|
|
swprintf( NameStr, L"%s", pSoldier->name );
|
|
}
|
|
|
|
//Legion
|
|
if (pSoldier->ubBodyType == TANK_NE || pSoldier->ubBodyType == TANK_NW)
|
|
{
|
|
//swprintf( NameStr, pVehicleStrings[4] );
|
|
swprintf( NameStr, gNewVehicle[164].NewVehicleStrings );
|
|
}
|
|
else if (zHiddenNames[pSoldier->ubProfile].Hidden == TRUE)
|
|
{
|
|
swprintf( NameStr,L"???" );
|
|
}
|
|
else
|
|
{
|
|
wprintf( NameStr, L"%s", pSoldier->name );
|
|
}
|
|
//---------------
|
|
|
|
//swprintf( NameStr, L"%s", pSoldier->name );
|
|
FindFontCenterCoordinates( sXPos, sYPos, (INT16)(80 ), 1, NameStr, TINYFONT1, &sX, &sY );
|
|
gprintfdirty( sX, sY, NameStr );
|
|
mprintf( sX, sY, NameStr );
|
|
}
|
|
}
|
|
|
|
// if ( pSoldier->ubProfile < FIRST_RPC || pSoldier->ubProfile >= GASTON || RPC_RECRUITED( pSoldier ) || AM_AN_EPC( pSoldier ) || ( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) )
|
|
//new profiles by Jazz
|
|
if ( gProfilesIMP[pSoldier->ubProfile].ProfilId == pSoldier->ubProfile || gProfilesAIM[pSoldier->ubProfile].ProfilId == pSoldier->ubProfile || gProfilesMERC[pSoldier->ubProfile].ProfilId == pSoldier->ubProfile || RPC_RECRUITED( pSoldier ) || AM_AN_EPC( pSoldier ) || ( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ))
|
|
{
|
|
if ( gGameExternalOptions.ubShowHealthBarsOnHead )
|
|
{
|
|
if( gGameExternalOptions.ubShowHealthBarsOnHead > 1 )
|
|
{
|
|
INT16 interval = gGameExternalOptions.ubShowHealthBarsOnHead;
|
|
//if( interval > 3 )
|
|
// interval -= 2;
|
|
sXPos += 28;
|
|
sYPos += 7;
|
|
iBack = RegisterBackgroundRect(BGND_FLAG_SINGLE, NULL, sXPos, sYPos-1, (INT16)(sXPos + 24 ), (INT16)(sYPos + 3 + interval*3 ) );
|
|
if ( iBack != -1 )
|
|
SetBackgroundRectFilled( iBack );
|
|
DrawBarsInUIBox( pSoldier, (INT16)(sXPos), (INT16)(sYPos), 20, 1, 2 );
|
|
|
|
// show AP only in turnbased combat, only during our turn
|
|
if( gGameExternalOptions.ubShowHealthBarsOnHead > 2 &&
|
|
(gTacticalStatus.uiFlags & TURNBASED ) && (gTacticalStatus.uiFlags & INCOMBAT) &&
|
|
gTacticalStatus.ubCurrentTeam == OUR_TEAM)
|
|
{
|
|
INT16 len;
|
|
swprintf( NameStr,L"%d", pSoldier->bActionPoints );
|
|
len = StringPixLength ( NameStr, TINYFONT1 );
|
|
SetFont( TINYFONT1 );
|
|
if(pSoldier->bActionPoints > APBPConstants[MIN_APS_TO_INTERRUPT])
|
|
SetFontForeground( FONT_MCOLOR_LTGRAY );
|
|
else if(pSoldier->bActionPoints > 10)
|
|
SetFontForeground( FONT_YELLOW );
|
|
else
|
|
SetFontForeground( FONT_MCOLOR_DKRED );
|
|
gprintfdirty( sXPos-2-len, sYPos-2, NameStr );
|
|
mprintf( sXPos-2-len, sYPos-2, NameStr );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Adjust for bars!
|
|
if ( pSoldier->ubID == gusSelectedSoldier )
|
|
{
|
|
sXPos += 28;
|
|
sYPos += 5;
|
|
}
|
|
else
|
|
{
|
|
sXPos += 30;
|
|
sYPos += 7;
|
|
}
|
|
|
|
// Add bars
|
|
iBack = RegisterBackgroundRect(BGND_FLAG_SINGLE, NULL, sXPos, sYPos, (INT16)(sXPos + 34 ), (INT16)(sYPos + 11 ) );
|
|
|
|
if ( iBack != -1 )
|
|
{
|
|
SetBackgroundRectFilled( iBack );
|
|
}
|
|
TileElem = gTileDatabase[ usGraphicToUse ];
|
|
BltVideoObject( FRAME_BUFFER, TileElem.hTileSurface, TileElem.usRegionIndex, sXPos, sYPos, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
|
|
// Draw life, breath
|
|
// Only do this when we are a vehicle but on our team
|
|
if ( pSoldier->ubID == gusSelectedSoldier )
|
|
{
|
|
DrawBarsInUIBox( pSoldier, (INT16)(sXPos +1), (INT16)(sYPos + 2), 16, 1, 3);
|
|
}
|
|
else
|
|
{
|
|
DrawBarsInUIBox( pSoldier, (INT16)(sXPos -1), (INT16)(sYPos ), 16, 1, 3 );
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
else // ( pSoldier->ubProfile < FIRST_RPC || pSoldier->ubProfile >= GASTON ||
|
|
{ // RPC_RECRUITED( pSoldier ) || AM_AN_EPC( pSoldier ) || ( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) )
|
|
if ( gfUIMouseOnValidCatcher == 2 && pSoldier->ubID == gubUIValidCatcherID )
|
|
{
|
|
SetFont( TINYFONT1 );
|
|
SetFontBackground( FONT_MCOLOR_BLACK );
|
|
SetFontForeground( FONT_MCOLOR_WHITE );
|
|
|
|
swprintf( NameStr, TacticalStr[ GIVE_STR ] );
|
|
FindFontCenterCoordinates( sXPos, (INT16)(sYPos + 10 ), (INT16)(80 ), 1, NameStr, TINYFONT1, &sX, &sY );
|
|
gprintfdirty( sX, sY, NameStr );
|
|
mprintf( sX, sY, NameStr );
|
|
}
|
|
else
|
|
{
|
|
SetFont( TINYFONT1 );
|
|
SetFontBackground( FONT_MCOLOR_BLACK );
|
|
SetFontForeground( FONT_MCOLOR_DKRED );
|
|
|
|
pStr = GetSoldierHealthString( pSoldier );
|
|
|
|
FindFontCenterCoordinates( sXPos, (INT16)( sYPos + 10 ), (INT16)(80 ), 1, pStr, TINYFONT1, &sX, &sY );
|
|
gprintfdirty( sX, sY, pStr );
|
|
mprintf( sX, sY, pStr );
|
|
|
|
//-----------------
|
|
if ( pSoldier->bInSector && pSoldier->ubProfile == NO_PROFILE )
|
|
{
|
|
if ( pSoldier->bTeam == ENEMY_TEAM )
|
|
{
|
|
// Flugente: soldier profiles
|
|
if ( gGameExternalOptions.fSoldierProfiles_Enemy && pSoldier->usSoldierProfile )
|
|
{
|
|
swprintf(NameStr, pSoldier->GetName());
|
|
|
|
SetFont( TINYFONT1 );
|
|
SetFontBackground( FONT_MCOLOR_BLACK );
|
|
SetFontForeground( FONT_YELLOW );
|
|
|
|
FindFontCenterCoordinates( sXPos, (INT16)( sYPos + 20 ), (INT16)(80 ), 1, NameStr, TINYFONT1, &sX, &sY );
|
|
gprintfdirty( sX, sY, NameStr );
|
|
mprintf( sX, sY, NameStr );
|
|
}
|
|
else if (gGameExternalOptions.fEnemyNames == TRUE && gGameExternalOptions.fEnemyRank == FALSE)
|
|
{
|
|
for( iCounter2 = 0; iCounter2 < 500; ++iCounter2 )
|
|
{
|
|
if (zEnemyName[iCounter2].Enabled == 1)
|
|
{
|
|
if ( pSoldier->sSectorX == zEnemyName[iCounter2].SectorX && pSoldier->sSectorY == zEnemyName[iCounter2].SectorY )
|
|
{
|
|
swprintf(NameStr, zEnemyName[iCounter2].szCurGroup);
|
|
|
|
SetFont( TINYFONT1 );
|
|
SetFontBackground( FONT_MCOLOR_BLACK );
|
|
SetFontForeground( FONT_YELLOW );
|
|
|
|
//legion2
|
|
FindFontCenterCoordinates( sXPos, (INT16)( sYPos + 20 ), (INT16)(80 ), 1, NameStr, TINYFONT1, &sX, &sY );
|
|
gprintfdirty( sX, sY, NameStr );
|
|
mprintf( sX, sY, NameStr );
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (gGameExternalOptions.fEnemyNames == FALSE && gGameExternalOptions.fEnemyRank == TRUE)
|
|
{
|
|
for( iCounter2 = 1; iCounter2 < 11; ++iCounter2 )
|
|
{
|
|
if (zEnemyRank[iCounter2].Enabled == 1)
|
|
{
|
|
if ( zEnemyRank[iCounter2].Stats == 0 && pSoldier->stats.bExpLevel == zEnemyRank[iCounter2].ExpLevel )
|
|
{
|
|
swprintf(NameStr, zEnemyRank[iCounter2].szCurRank);
|
|
|
|
SetFont( TINYFONT1 );
|
|
SetFontBackground( FONT_MCOLOR_BLACK );
|
|
SetFontForeground( FONT_YELLOW );
|
|
|
|
//legion2
|
|
FindFontCenterCoordinates( sXPos, (INT16)( sYPos + 20 ), (INT16)(80 ), 1, NameStr, TINYFONT1, &sX, &sY );
|
|
gprintfdirty( sX, sY, NameStr );
|
|
mprintf( sX, sY, NameStr );
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// Flugente: soldier profiles
|
|
else if ( pSoldier->bTeam == MILITIA_TEAM && gGameExternalOptions.fSoldierProfiles_Militia && pSoldier->usSoldierProfile )
|
|
{
|
|
// get a proper chaos name
|
|
swprintf(NameStr, pSoldier->GetName());
|
|
|
|
SetFont( TINYFONT1 );
|
|
SetFontBackground( FONT_MCOLOR_BLACK );
|
|
SetFontForeground( FONT_YELLOW );
|
|
|
|
FindFontCenterCoordinates( sXPos, (INT16)( sYPos + 20 ), (INT16)(80 ), 1, NameStr, TINYFONT1, &sX, &sY );
|
|
gprintfdirty( sX, sY, NameStr );
|
|
mprintf( sX, sY, NameStr );
|
|
}
|
|
else if (gGameExternalOptions.fCivGroupName == TRUE && pSoldier->ubCivilianGroup > 0 )
|
|
{
|
|
if (zCivGroupName[pSoldier->ubCivilianGroup].Enabled == 1)
|
|
{
|
|
swprintf(NameStr, zCivGroupName[pSoldier->ubCivilianGroup].szCurGroup);
|
|
|
|
SetFont( TINYFONT1 );
|
|
SetFontBackground( FONT_MCOLOR_BLACK );
|
|
SetFontForeground( FONT_YELLOW );
|
|
|
|
//legion2
|
|
FindFontCenterCoordinates( sXPos, (INT16)( sYPos + 20 ), (INT16)(80 ), 1, NameStr, TINYFONT1, &sX, &sY );
|
|
gprintfdirty( sX, sY, NameStr );
|
|
mprintf( sX, sY, NameStr );
|
|
}
|
|
}
|
|
}
|
|
//------------
|
|
}
|
|
}
|
|
}
|
|
else //pSoldier->ubProfile != NO_PROFILE || ( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE )
|
|
{
|
|
// show (roof) text
|
|
if ( pSoldier->pathing.bLevel != 0 )
|
|
{
|
|
// sevenfm: fix for overlapping with SHOW_ENEMY_WEAPON feature
|
|
if( !gGameExternalOptions.fShowEnemyWeapon || !gfUIFullTargetFound )
|
|
{
|
|
SetFont( TINYFONT1 );
|
|
SetFontBackground( FONT_MCOLOR_BLACK );
|
|
SetFontForeground( FONT_YELLOW );
|
|
|
|
swprintf( NameStr, gzLateLocalizedString[ 15 ] );
|
|
FindFontCenterCoordinates( sXPos, (INT16)(sYPos + 10), (INT16)(80 ), 1, NameStr, TINYFONT1, &sX, &sY );
|
|
gprintfdirty( sX, sY, NameStr );
|
|
mprintf( sX, sY, NameStr );
|
|
}
|
|
}
|
|
|
|
pStr = GetSoldierHealthString( pSoldier );
|
|
|
|
//jones
|
|
extern void SoldierTooltip(SOLDIERTYPE*);
|
|
//if ( gGameExternalOptions.gfAllowSoldierToolTips ) // changed by SANDRO
|
|
if ( gGameSettings.fOptions[TOPTION_ALLOW_SOLDIER_TOOLTIPS] )
|
|
SoldierTooltip(pSoldier);
|
|
|
|
SetFont( TINYFONT1 );
|
|
SetFontBackground( FONT_MCOLOR_BLACK );
|
|
SetFontForeground( FONT_MCOLOR_DKRED );
|
|
|
|
FindFontCenterCoordinates( sXPos, sYPos, (INT16)(80 ), 1, pStr, TINYFONT1, &sX, &sY );
|
|
gprintfdirty( sX, sY, pStr );
|
|
mprintf( sX, sY, pStr );
|
|
|
|
//-----------------
|
|
if ( pSoldier->bInSector && pSoldier->ubProfile == NO_PROFILE )
|
|
{
|
|
#ifdef ENABLE_ZOMBIES
|
|
if ( pSoldier->IsZombie() )
|
|
{
|
|
swprintf(NameStr, pSoldier->name);
|
|
|
|
// Display name
|
|
SetFont( TINYFONT1 );
|
|
SetFontBackground( FONT_MCOLOR_BLACK );
|
|
SetFontForeground( FONT_MCOLOR_WHITE );
|
|
|
|
//legion2
|
|
FindFontCenterCoordinates( sXPos, (INT16)( sYPos -10 ), (INT16)(80 ), 1, NameStr, TINYFONT1, &sX, &sY );
|
|
gprintfdirty( sX, sY, NameStr );
|
|
mprintf( sX, sY, NameStr );
|
|
}
|
|
else
|
|
#endif
|
|
if ( pSoldier->bTeam == ENEMY_TEAM )
|
|
{
|
|
// Flugente: soldier profiles
|
|
if ( gGameExternalOptions.fSoldierProfiles_Enemy && pSoldier->usSoldierProfile )
|
|
{
|
|
// get a proper chaos name
|
|
swprintf(NameStr, pSoldier->GetName());
|
|
|
|
SetFont( TINYFONT1 );
|
|
SetFontBackground( FONT_MCOLOR_BLACK );
|
|
SetFontForeground( FONT_YELLOW );
|
|
|
|
FindFontCenterCoordinates( sXPos, (INT16)( sYPos + 20 ), (INT16)(80 ), 1, NameStr, TINYFONT1, &sX, &sY );
|
|
gprintfdirty( sX, sY, NameStr );
|
|
mprintf( sX, sY, NameStr );
|
|
}
|
|
else if (gGameExternalOptions.fEnemyNames == TRUE)
|
|
{
|
|
for( iCounter2 = 0; iCounter2 < 500; ++iCounter2 )
|
|
{
|
|
if (zEnemyName[iCounter2].Enabled == 1 )
|
|
{
|
|
if ( pSoldier->sSectorX == zEnemyName[iCounter2].SectorX && pSoldier->sSectorY == zEnemyName[iCounter2].SectorY )
|
|
{
|
|
swprintf(NameStr, zEnemyName[iCounter2].szCurGroup);
|
|
|
|
SetFont( TINYFONT1 );
|
|
SetFontBackground( FONT_MCOLOR_BLACK );
|
|
SetFontForeground( FONT_YELLOW );
|
|
|
|
//legion2
|
|
FindFontCenterCoordinates( sXPos, (INT16)( sYPos + 20 ), (INT16)(80 ), 1, NameStr, TINYFONT1, &sX, &sY );
|
|
gprintfdirty( sX, sY, NameStr );
|
|
mprintf( sX, sY, NameStr );
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (gGameExternalOptions.fEnemyRank == TRUE)
|
|
{
|
|
for( iCounter2 = 1; iCounter2 < 11; ++iCounter2 )
|
|
{
|
|
if (zEnemyRank[iCounter2].Enabled == 1)
|
|
{
|
|
if ( zEnemyRank[iCounter2].Stats == 0 && pSoldier->stats.bExpLevel == zEnemyRank[iCounter2].ExpLevel )
|
|
{
|
|
swprintf(NameStr, zEnemyRank[iCounter2].szCurRank);
|
|
|
|
SetFont( TINYFONT1 );
|
|
SetFontBackground( FONT_MCOLOR_BLACK );
|
|
SetFontForeground( FONT_YELLOW );
|
|
|
|
// need to adjust sYPos because default position already occupied by the name
|
|
if ( gGameExternalOptions.fSoldierProfiles_Enemy && pSoldier->usSoldierProfile || gGameExternalOptions.fEnemyNames )
|
|
FindFontCenterCoordinates( sXPos, (INT16)( sYPos + 10 ), (INT16)(80 ), 1, NameStr, TINYFONT1, &sX, &sY );
|
|
|
|
// use default position for text
|
|
else
|
|
FindFontCenterCoordinates( sXPos, (INT16)( sYPos + 20 ), (INT16)(80 ), 1, NameStr, TINYFONT1, &sX, &sY );
|
|
|
|
//legion2
|
|
gprintfdirty( sX, sY, NameStr );
|
|
mprintf( sX, sY, NameStr );
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//FindFontCenterCoordinates( sXPos, (INT16)( sYPos ), (INT16)(80 ), 1, L"", TINYFONT1, &sX, &sY );
|
|
|
|
// sevenfm: show weapon name and additional info
|
|
ShowEnemyWeapon( sX, sY, pSoldier );
|
|
ShowEnemyHealthBar( sX, sY, pSoldier );
|
|
ShowAdditionalInfo( sX, sY, pSoldier );
|
|
ShowRankIcon( sXPos, sYPos, pSoldier );
|
|
}
|
|
// Flugente: soldier profiles
|
|
else if ( pSoldier->bTeam == MILITIA_TEAM && gGameExternalOptions.fSoldierProfiles_Militia && pSoldier->usSoldierProfile )
|
|
{
|
|
// get a proper chaos name
|
|
swprintf(NameStr, pSoldier->GetName());
|
|
|
|
SetFont( TINYFONT1 );
|
|
SetFontBackground( FONT_MCOLOR_BLACK );
|
|
SetFontForeground( FONT_YELLOW );
|
|
|
|
FindFontCenterCoordinates( sXPos, (INT16)( sYPos + 20 ), (INT16)(80 ), 1, NameStr, TINYFONT1, &sX, &sY );
|
|
gprintfdirty( sX, sY, NameStr );
|
|
mprintf( sX, sY, NameStr );
|
|
}
|
|
else if (gGameExternalOptions.fCivGroupName == TRUE && pSoldier->ubCivilianGroup > 0 )
|
|
{
|
|
if (zCivGroupName[pSoldier->ubCivilianGroup].Enabled == 1)
|
|
{
|
|
swprintf(NameStr, zCivGroupName[pSoldier->ubCivilianGroup].szCurGroup);
|
|
|
|
SetFont( TINYFONT1 );
|
|
SetFontBackground( FONT_MCOLOR_BLACK );
|
|
SetFontForeground( FONT_YELLOW );
|
|
|
|
//legion2
|
|
FindFontCenterCoordinates( sXPos, (INT16)( sYPos + 20 ), (INT16)(80 ), 1, NameStr, TINYFONT1, &sX, &sY );
|
|
gprintfdirty( sX, sY, NameStr );
|
|
mprintf( sX, sY, NameStr );
|
|
}
|
|
// sevenfm: show weapon name and additional info
|
|
FindFontCenterCoordinates( sXPos, (INT16)( sYPos ), (INT16)(80 ), 1, L"", TINYFONT1, &sX, &sY );
|
|
ShowEnemyWeapon( sX, sY, pSoldier );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
BOOLEAN DrawCTHIndicator()
|
|
{
|
|
////////////////////////////////////////////
|
|
// HEADROCK HAM 4: NCTH Indicator
|
|
//
|
|
// The NCTH shooting system is radically different from the old CTH, and as a result it requires a completely
|
|
// new indicator to show hit-probability. The "Hit Percentage" bar we've all gotten used to in JA2 1.13 is not
|
|
// doable in NCTH since the hit probability is unknown before the bullet reaches the target distance. Instead,
|
|
// we use a sort of "reticle" to show the margin of error for our current shot.
|
|
//
|
|
// The CTH indicator is made up of several parts:
|
|
// 1. Outer Circle: This circle shows the margin of error that we would have if Muzzle Accuracy was 0%. In other
|
|
// words, it indicates the "worst" possible shot with the gun we're holding, given the target's distance.
|
|
// This circle only gets larger or smaller if the shooter moves closer or further from the target (or
|
|
// changes weapons...).
|
|
// 2. Inner Circle+Crosshairs: This indicator shows the margin of error for the shot given all the bonuses from
|
|
// Base CTH and extra aiming clicks. It is a visual representation of where our bullet may end up once fired.
|
|
// The bullet can end up anywhere within this smaller circle. The circle gets larger or smaller as we change
|
|
// the number of applied aiming clicks, add magnification bonuses from a scope, change stance, etcetera.
|
|
// 3. Additional indicators: These are floating graphical and numerical indicators showing various important
|
|
// data, such as how many aiming clicks we've applied (and how many we can apply), how many bullets we're
|
|
// going to fire (in burst/auto mode), and how many APs it's going to cost us. These are generally just
|
|
// relocation and redesign of existing indicators on the OCTH cursor.
|
|
|
|
if (gCTHDisplay.MuzzleSwayPercentage < 0 || gCTHDisplay.MuzzleSwayPercentage > 99 || gCTHDisplay.FinalMagFactor < 1.0)
|
|
{
|
|
// Obviously Uninitialized.
|
|
return 0;
|
|
}
|
|
|
|
INT32 iBack;
|
|
|
|
// Find the shooter.
|
|
SOLDIERTYPE *pSoldier;
|
|
GetSoldier( &pSoldier, gusSelectedSoldier );
|
|
|
|
OBJECTTYPE* pWeapon = pSoldier->GetUsedWeapon( &pSoldier->inv[ pSoldier->ubAttackingHand ] );
|
|
|
|
// Create a Background Rect for us to draw our indicator on. With NCTH, the size and position of this rectangle
|
|
// is equal exactly to the size of the tactical screen viewport. Unlike the OCTH indicator, the NCTH one can grow
|
|
// so large as to fill the entire screen.
|
|
INT16 sLeft = gsVIEWPORT_START_X;
|
|
INT16 sTop = gsVIEWPORT_WINDOW_START_Y;
|
|
INT16 sRight = gsVIEWPORT_END_X;
|
|
INT16 sBottom = gsVIEWPORT_WINDOW_END_Y;
|
|
|
|
iBack = RegisterBackgroundRect(BGND_FLAG_SINGLE, NULL, sLeft, sTop, sRight, sBottom);
|
|
|
|
if ( iBack != -1 )
|
|
{
|
|
SetBackgroundRectFilled( iBack );
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
// HEADROCK HAM 4: New CTH, Aperture Size
|
|
//
|
|
// As explained above, the most important part of the new indicator is the Aperture circle/crosshairs.
|
|
// These indicate the size of the "margin of error" for our current shot. The more accurate we are,
|
|
// the smaller the circle will be.
|
|
//
|
|
// The player uses this to determine whether the shot has a good likelyhood to hit the target.
|
|
// If the circle is the same size or smaller than the target itself, then hit probability is 100%.
|
|
// The larger it gets, the less hit probability there will be. When adding extra aiming clicks,
|
|
// the circle gets proportionally smaller. The idea is to try to make it as small as the target
|
|
// (if possible) to ensure a hit.
|
|
//
|
|
// Shot aperture is calculated using the CTH formula (CalcChanceToHitGun). Scopes and lasers
|
|
// can help decrease the size of the aperture further.
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
/////////////////////////////////
|
|
// Define colors
|
|
UINT8 ColorsRed[10] = { 255, 255, 255, 255, 255, 255, 255, 255, 173, 0 };
|
|
UINT8 ColorsGreen[10] = { 0, 50, 81, 101, 133, 174, 211, 243, 255, 255 };
|
|
|
|
// Select the color of the indicator circles
|
|
UINT16 usCApertureBar;
|
|
|
|
// CHRISL: Instead of shigting the color based on MuzzleSwayPercent, let's move this line and base it on the final iAperture value
|
|
// Indicator changes color from red to yellow to green, based on how well the gun is aimed.
|
|
//usCApertureBar = Get16BPPColor( FROMRGB( ColorsRed[gCTHDisplay.MuzzleSwayPercentage/10], ColorsGreen[gCTHDisplay.MuzzleSwayPercentage/10], 0 ) ); // Crosshair color shifts from red (longshot) to green (Accurate shot)
|
|
|
|
UINT16 usCApertureBorder = Get16BPPColor( FROMRGB( 10, 10, 10 ) ); // Boundaries in dark color.
|
|
|
|
//////////////////////////////////
|
|
// Calculate Aperture
|
|
|
|
// Calculate the center point of the shooter, in world coordinates.
|
|
FLOAT dStartX = (FLOAT) CenterX( gCTHDisplay.iShooterGridNo );
|
|
FLOAT dStartY = (FLOAT) CenterY( gCTHDisplay.iShooterGridNo );
|
|
|
|
// Calculate the center point of the target, in world coordinates.
|
|
FLOAT dEndX = (FLOAT) CenterX( gCTHDisplay.iTargetGridNo );
|
|
FLOAT dEndY = (FLOAT) CenterY( gCTHDisplay.iTargetGridNo );
|
|
|
|
// Calculate a delta: the difference between the shooter and target.
|
|
FLOAT dDeltaX = dEndX - dStartX;
|
|
FLOAT dDeltaY = dEndY - dStartY;
|
|
|
|
// Calculate the distance of the shot, using Pythagorean Theorem
|
|
DOUBLE d2DDistance = Distance2D( dDeltaX, dDeltaY );
|
|
// Round it upwards.
|
|
INT32 iDistance = (INT32) d2DDistance;
|
|
if ( d2DDistance != iDistance )
|
|
{
|
|
iDistance += 1;
|
|
d2DDistance = (FLOAT) ( iDistance);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// Now we calculate the Aperture size. This is done using the same method as the shooting formula uses.
|
|
|
|
// Calculate the maximum angle of any shot.
|
|
DOUBLE ddMaxAngleRadians = (gGameCTHConstants.DEGREES_MAXIMUM_APERTURE * 6.283) / 360;
|
|
|
|
// Calculate the size of a "normal" aperture. This is how wide a shot can go at 1x Normal Distance.
|
|
FLOAT iBasicAperture = (FLOAT)((sin(ddMaxAngleRadians) * gGameCTHConstants.NORMAL_SHOOTING_DISTANCE) * 2); // The *2 compensates for the difference between CellXY and ScreenXY
|
|
|
|
// when using the reworked NCTH code we do additional calculations for iron sights and lasers
|
|
if (gGameExternalOptions.fUseNewCTHCalculation)
|
|
{
|
|
// iron sights can get a percentage bonus to make them overall better but only when not shooting from hip
|
|
if ( gCTHDisplay.ScopeMagFactor <= 1.0 && !pSoldier->IsValidAlternativeFireMode( pSoldier->aiData.bAimTime, gCTHDisplay.iTargetGridNo ) )
|
|
|
|
iBasicAperture = iBasicAperture * (FLOAT)( (100 - gGameCTHConstants.IRON_SIGHT_PERFORMANCE_BONUS) / 100);
|
|
|
|
// laser pointers can provide a percentage bonus to base aperture
|
|
if ( gCTHDisplay.iBestLaserRange > 0
|
|
&& ( gGameCTHConstants.LASER_PERFORMANCE_BONUS_HIP + gGameCTHConstants.LASER_PERFORMANCE_BONUS_IRON + gGameCTHConstants.LASER_PERFORMANCE_BONUS_SCOPE != 0) )
|
|
{
|
|
INT8 bLightLevel = LightTrueLevel(gCTHDisplay.iTargetGridNo, gsInterfaceLevel );
|
|
INT32 iMaxLaserRange = ( gCTHDisplay.iBestLaserRange*( 2*bLightLevel + 3*NORMAL_LIGHTLEVEL_NIGHT - 5*NORMAL_LIGHTLEVEL_DAY ) ) / ( 2 * ( NORMAL_LIGHTLEVEL_NIGHT - NORMAL_LIGHTLEVEL_DAY ) );
|
|
|
|
// laser only has effect when in range
|
|
if ( iMaxLaserRange > d2DDistance )
|
|
{
|
|
FLOAT fLaserBonus = 0;
|
|
// which bonus do we want to apply?
|
|
if ( pSoldier->IsValidAlternativeFireMode( pSoldier->aiData.bAimTime, gCTHDisplay.iTargetGridNo ) )
|
|
// shooting from hip
|
|
fLaserBonus = gGameCTHConstants.LASER_PERFORMANCE_BONUS_HIP;
|
|
else if ( gCTHDisplay.ScopeMagFactor <= 1.0 )
|
|
// using iron sights or other 1x sights
|
|
fLaserBonus = gGameCTHConstants.LASER_PERFORMANCE_BONUS_IRON;
|
|
else
|
|
// must be using a scope
|
|
fLaserBonus = gGameCTHConstants.LASER_PERFORMANCE_BONUS_SCOPE;
|
|
|
|
// light level influences how easy it is to spot the laser dot on the target
|
|
FLOAT fBrightnessModifier = (FLOAT)(bLightLevel) / (FLOAT)(NORMAL_LIGHTLEVEL_NIGHT);
|
|
|
|
// laser fully efficient
|
|
if ( gCTHDisplay.iBestLaserRange > d2DDistance )
|
|
// apply full bonus
|
|
iBasicAperture = iBasicAperture * (FLOAT)( (100 - (fLaserBonus * fBrightnessModifier)) / 100);
|
|
else
|
|
{
|
|
// beyond BestLaserRange laser bonus drops linearly to 0
|
|
FLOAT fEffectiveLaserRatio = (FLOAT)(iMaxLaserRange - d2DDistance) / (FLOAT)(iMaxLaserRange - gCTHDisplay.iBestLaserRange);
|
|
// apply partial bonus
|
|
iBasicAperture = iBasicAperture * (FLOAT)( (100 - (fLaserBonus * fBrightnessModifier * fEffectiveLaserRatio)) / 100);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Next, find out how large the aperture can be around the target, given range. The further the target is, the
|
|
// larger the aperture can be.
|
|
FLOAT iDistanceAperture = iBasicAperture * (d2DDistance / gGameCTHConstants.NORMAL_SHOOTING_DISTANCE);
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
// To make things easier for us, we now calculate the Magnification Factor for this shot. A Mag Factor
|
|
// is a divisor to the sway of the muzzle. It's about the same as multiplying CTH by a certain amount.
|
|
// Note that both optical magnification devices (like scopes) and dot-projection devices (like lasers and
|
|
// reflex sights) provide this sort of bonus.
|
|
FLOAT iMagFactor = CalcMagFactor( pSoldier, pWeapon, d2DDistance, gCTHDisplay.iTargetGridNo, (UINT8)pSoldier->aiData.bAimTime );
|
|
|
|
// Get effective mag factor for this shooter. This represents his ability to use scopes.
|
|
FLOAT fEffectiveMagFactor = CalcEffectiveMagFactor( pSoldier, iMagFactor );
|
|
|
|
// Next step is to apply scope/projection factor to decrease the size of the aperture. This gives us the "Max
|
|
// Aperture" value - the size of the shooting circle if the gun is as unstable as possible.
|
|
FLOAT iMaxAperture = iDistanceAperture / fEffectiveMagFactor;
|
|
|
|
// We now use the Muzzle Sway value, calculated by the CTH formula, to decrease the size of the shot aperture.
|
|
// It is used as a percentage: a 50% muzzle sway value gives a cone with half the maximum radius. A cone with
|
|
// 0% Muzzle Sway is a single line with no width (meaning all shots will fly right down the center, and all will
|
|
// hit the target), while a cone with 100% muzzle sway is as wide as possible.
|
|
FLOAT iAperture = ( iMaxAperture * (100.0f - (FLOAT)gCTHDisplay.MuzzleSwayPercentage) / 100.0f);
|
|
|
|
/////////////////////////////////////////////
|
|
// Factor in Weapon "Effective Range".
|
|
UINT16 sEffRange = Weapon[Item[pSoldier->inv[pSoldier->ubAttackingHand].usItem].ubClassIndex].usRange + GetRangeBonus(&(pSoldier->inv[ pSoldier->ubAttackingHand ]));
|
|
FLOAT iRangeRatio = __max(1.0f, (FLOAT)(d2DDistance / sEffRange));
|
|
FLOAT iDistanceRatio = (FLOAT)(d2DDistance / gGameCTHConstants.NORMAL_SHOOTING_DISTANCE);
|
|
|
|
/////////////////////////////////////////////
|
|
// Factor in Gun Accuracy.
|
|
|
|
INT16 sAccuracy = GetGunAccuracy( &(pSoldier->inv[ pSoldier->ubAttackingHand ]) );
|
|
|
|
sAccuracy = __max(0, sAccuracy);
|
|
sAccuracy = __min(100, sAccuracy);
|
|
|
|
FLOAT iBulletDev = (gGameCTHConstants.MAX_BULLET_DEV * (100-sAccuracy)) / 100;
|
|
if( gGameCTHConstants.RANGE_EFFECTS_DEV == TRUE )
|
|
iBulletDev *= iRangeRatio;
|
|
iBulletDev *= iDistanceRatio;
|
|
|
|
// Since bullet dev is only affected by distance, we add it last as a flat modifier.
|
|
iBasicAperture += iBulletDev;
|
|
iDistanceAperture += iBulletDev;
|
|
iAperture += iBulletDev;
|
|
|
|
// CHRISL: Moved here so we can base the cursor color on the iAperture value
|
|
UINT8 iColorCode = 0;
|
|
if(iAperture < 3.0)
|
|
iColorCode = 9;
|
|
else if(iAperture < 6.0)
|
|
iColorCode = 8;
|
|
else if(iAperture < 9.0)
|
|
iColorCode = 7;
|
|
else if(iAperture < 12.0)
|
|
iColorCode = 6;
|
|
else if(iAperture < 16.0)
|
|
iColorCode = 5;
|
|
else if(iAperture < 20.0)
|
|
iColorCode = 4;
|
|
else if(iAperture < 25.0)
|
|
iColorCode = 3;
|
|
else if(iAperture < 30.0)
|
|
iColorCode = 2;
|
|
else if(iAperture < 40.0)
|
|
iColorCode = 1;
|
|
usCApertureBar = Get16BPPColor( FROMRGB( ColorsRed[iColorCode], ColorsGreen[iColorCode], 0 ) ); // Crosshair color shifts from red (longshot) to green (Accurate shot)
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// HEADROCK HAM 4: Calculate Screen Positions
|
|
//
|
|
// Aperture Size has to be translated into on-screen size. We also want to track the position of the
|
|
// mouse so that our indicator moves with it like a cursor.
|
|
|
|
// Z Offset is used to move the indicator up or down. It's currently set to 0 since it's not required ATM.
|
|
FLOAT zOffset = 0;
|
|
|
|
// Calculate the position of the mouse cursor and store it.
|
|
INT16 sStartScreenX;
|
|
INT16 sStartScreenY;
|
|
|
|
POINT MousePos;
|
|
GetCursorPos(&MousePos);
|
|
ScreenToClient(ghWindow, &MousePos); // In window coords!
|
|
|
|
sStartScreenX = (INT16)MousePos.x;
|
|
sStartScreenY = (INT16)MousePos.y;
|
|
|
|
// Define regions for the various indicators. We need to do this now because the Aperture Circles will want to
|
|
// avoid being drawn within these regions, otherwise they might make them harder to see.
|
|
|
|
MagRect.left = sStartScreenX-50; MagRect.top = sStartScreenY-15; MagRect.right = sStartScreenX-20; MagRect.bottom = sStartScreenY-5;
|
|
APRect.left = sStartScreenX+22; APRect.top = sStartScreenY-15; APRect.right = sStartScreenX+52; APRect.bottom = sStartScreenY-5;
|
|
AimRect.left = sStartScreenX-35; AimRect.top = sStartScreenY+22; AimRect.right = sStartScreenX+35; AimRect.bottom = sStartScreenY+30;
|
|
ModeRect.left = sStartScreenX-28; ModeRect.top = sStartScreenY+31; ModeRect.right = sStartScreenX+28; ModeRect.bottom = sStartScreenY+41;
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////
|
|
// DRAW ADDITIONAL COMPONENTS:
|
|
//
|
|
// We now draw additional indicators on top of the circles. There are four indicators:
|
|
//
|
|
// 1. AP Cost: The current AP cost for the shot has been moved from the center of the
|
|
// targeting cursor to avoid obscuring the meeting point of the aperture crosshairs.
|
|
// It is now displayed in the top right, together with the word "AP".
|
|
// 2. MAG Factor: The current Magnification or Projection factor for the shot is displayed
|
|
// in the top-left, followed by an "x". Its color indicates whether we are using the
|
|
// full potential of our aiming device.
|
|
// 3. Aiming Pips: The circles on the old indicator shows how many aiming clicks we've
|
|
// placed into the shot. Now that the circles are used to indicate shot probability,
|
|
// the aiming clicks are displayed with a series of pips below the targeting cursor
|
|
// which fill up as we add levels.
|
|
// 4. Bullet Count: This indicator, now below the Aiming Pips indicator, shows the number
|
|
// of bullets queues up for a Burst/Autofire volley. For autofire, it starts out by
|
|
// displaying grey bullets showing how many we CAN add, then fills up with colored
|
|
// bullets as we add them to the volley. A "+" sign is added if space for bullets runs out.
|
|
|
|
CHAR16 pStr[10];
|
|
|
|
INT16 curX = 0;
|
|
INT16 curY = 0;
|
|
|
|
/////////////////////////////////////////
|
|
// Load image STI
|
|
UINT32 guiCTHImage;
|
|
VOBJECT_DESC VObjectDesc;
|
|
|
|
VObjectDesc.fCreateFlags=VOBJECT_CREATE_FROMFILE;
|
|
if(UsingNewCTHSystem() == true)
|
|
FilenameForBPP("CURSORS\\CUR_CTH_NCTH.sti", VObjectDesc.ImageFile);
|
|
else
|
|
FilenameForBPP("CURSORS\\CUR_CTH.sti", VObjectDesc.ImageFile);
|
|
CHECKF(AddVideoObject(&VObjectDesc, &guiCTHImage));
|
|
|
|
/////////////// AP COST FOR CURRENT SHOT
|
|
{
|
|
// Create a pointer to the Frame Buffer which we are going to draw directly into.
|
|
SetFont( TINYFONT1 );
|
|
SetFontBackground( FONT_MCOLOR_BLACK );
|
|
SetFontForeground( FONT_MCOLOR_WHITE );
|
|
|
|
// Find coordinates, using the full string ("XX AP")
|
|
swprintf( pStr, L"%d %s", gsCurrentActionPoints, gzNCTHlabels[ 1 ] );
|
|
FindFontCenterCoordinates( (INT16)APRect.left, (INT16)APRect.top, (INT16)APRect.right-(INT16)APRect.left, 10, pStr, TINYFONT1, &curX, &curY);
|
|
// Find width of this string.
|
|
UINT16 usTotalWidth = StringPixLength ( pStr, TINYFONT1 );
|
|
|
|
// Cut string to just the number of APs
|
|
swprintf( pStr, L"%d", gsCurrentActionPoints );
|
|
// Find out how wide this string is
|
|
UINT16 usWidth = StringPixLength( pStr, TINYFONT1 );
|
|
// Draw to screen
|
|
gprintfdirty( curX, curY, pStr );
|
|
mprintf( curX, curY, pStr);
|
|
|
|
// Draw the "AP" label 4 pixels forward.
|
|
SetFontForeground(FONT_MCOLOR_LTYELLOW);
|
|
swprintf( pStr, L"%s", gzNCTHlabels[ 1 ] );
|
|
curX += usWidth + 4;
|
|
gprintfdirty( curX, curY, pStr );
|
|
mprintf( curX, curY, pStr);
|
|
|
|
// Redefine area size based on total width plus a margin of 2 pixels.
|
|
usTotalWidth = usTotalWidth + 6;
|
|
INT16 sCenter = (INT16)((APRect.right + APRect.left) / 2);
|
|
APRect.left = sCenter - (usTotalWidth / 2);
|
|
APRect.right = sCenter + (usTotalWidth / 2);
|
|
}
|
|
|
|
// sevenfm: draw item pics
|
|
DrawNCTHCursorItemPics( sStartScreenX, sStartScreenY );
|
|
|
|
/////////////// MAG FACTOR
|
|
{
|
|
SetFont( TINYFONT1 );
|
|
|
|
// Find coordinates, using full string ("X.X x")
|
|
swprintf( pStr, L"%1.1f x", gCTHDisplay.FinalMagFactor );
|
|
FindFontCenterCoordinates( (INT16)MagRect.left, (INT16)MagRect.top, (INT16)MagRect.right-(INT16)MagRect.left, 10, pStr, TINYFONT1, &curX, &curY);
|
|
// Find width of this string.
|
|
UINT16 usTotalWidth = StringPixLength ( pStr, TINYFONT1 );
|
|
|
|
// Cut string to just the float
|
|
swprintf( pStr, L"%1.1f", gCTHDisplay.FinalMagFactor );
|
|
// Record the width of the float
|
|
UINT16 usWidth = StringPixLength( pStr, TINYFONT1 );
|
|
|
|
////////////////////////////
|
|
// We change the color of this indicator based on whether or not our optical devices are working
|
|
// at full potential. Remember that scopes below their best range give out penalties!
|
|
|
|
// If using a scope below its optimal range...
|
|
if (gCTHDisplay.ScopeMagFactor > 1.0 && gCTHDisplay.ScopeMagFactor > gCTHDisplay.FinalMagFactor)
|
|
{
|
|
// If within projection range...
|
|
if (gCTHDisplay.ProjectionFactor > 1.0 && gCTHDisplay.ProjectionFactor >= iDistanceRatio )
|
|
{
|
|
SetFontForeground( FONT_ORANGE );
|
|
}
|
|
// If only using a scope...
|
|
else
|
|
{
|
|
SetRGBFontForeground( 255, 150, 150 ); // Bright Pink
|
|
}
|
|
}
|
|
// If using a scope above its range, or a laser below its range
|
|
else if ((gCTHDisplay.ScopeMagFactor > 1.0 && gCTHDisplay.ScopeMagFactor <= iDistanceRatio) ||
|
|
(gCTHDisplay.ProjectionFactor > 1.0 && gCTHDisplay.ProjectionFactor >= iDistanceRatio) )
|
|
{
|
|
SetRGBFontForeground( 100,255,100 ); // True Light Green
|
|
}
|
|
// In all other circumstances...
|
|
else
|
|
{
|
|
SetFontForeground( FONT_MCOLOR_WHITE );
|
|
}
|
|
|
|
// Print the float
|
|
gprintfdirty( curX, curY, pStr );
|
|
mprintf( curX, curY, pStr);
|
|
|
|
// Add an "x" 4 pixels forward.
|
|
SetFontForeground( FONT_MCOLOR_LTYELLOW );
|
|
swprintf( pStr, L"x" );
|
|
curX += usWidth + 4;
|
|
gprintfdirty( curX, curY, pStr );
|
|
mprintf( curX, curY, pStr);
|
|
|
|
// Redefine area size based on total width plus a margin of 2 pixels.
|
|
usTotalWidth = usTotalWidth + 6;
|
|
INT16 sCenter = (INT16)((MagRect.right + MagRect.left) / 2);
|
|
MagRect.left = sCenter - (usTotalWidth / 2);
|
|
MagRect.right = sCenter + (usTotalWidth / 2);
|
|
}
|
|
|
|
#ifdef JA2BETAVERSION
|
|
/////////////// SHOT APERTURE SIZE
|
|
{
|
|
// Create a pointer to the Frame Buffer which we are going to draw directly into.
|
|
SetFont( TINYFONT1 );
|
|
SetFontBackground( FONT_MCOLOR_BLACK );
|
|
SetFontForeground( FONT_MCOLOR_WHITE );
|
|
|
|
// Find coordinates, using the full string ("XX AP")
|
|
swprintf( pStr, L"%3.2f", iAperture );
|
|
FindFontCenterCoordinates( (INT16)APRect.left, (INT16)APRect.top-5, (INT16)APRect.right-(INT16)APRect.left, 5, pStr, TINYFONT1, &curX, &curY);
|
|
// Find width of this string.
|
|
UINT16 usTotalWidth = StringPixLength ( pStr, TINYFONT1 );
|
|
|
|
// Draw to screen
|
|
gprintfdirty( curX, curY, pStr );
|
|
mprintf( curX, curY, pStr);
|
|
|
|
// Redefine area size based on total width plus a margin of 2 pixels.
|
|
usTotalWidth = usTotalWidth + 6;
|
|
INT16 sCenter = (INT16)((APRect.right + APRect.left) / 2);
|
|
APRect.left = sCenter - (usTotalWidth / 2);
|
|
APRect.right = sCenter + (usTotalWidth / 2);
|
|
}
|
|
|
|
/////////////// DISTANCE APERTURE SIZE
|
|
{
|
|
SetFont( TINYFONT1 );
|
|
|
|
// Find coordinates, using full string ("X.X x")
|
|
swprintf( pStr, L"%3.2f", iDistanceAperture );
|
|
FindFontCenterCoordinates( (INT16)MagRect.left, (INT16)MagRect.top-5, (INT16)MagRect.right-(INT16)MagRect.left, 5, pStr, TINYFONT1, &curX, &curY);
|
|
// Find width of this string.
|
|
UINT16 usTotalWidth = StringPixLength ( pStr, TINYFONT1 );
|
|
|
|
// Draw to screen
|
|
gprintfdirty( curX, curY, pStr );
|
|
mprintf( curX, curY, pStr);
|
|
|
|
// Redefine area size based on total width plus a margin of 2 pixels.
|
|
usTotalWidth = usTotalWidth + 6;
|
|
INT16 sCenter = (INT16)((MagRect.right + MagRect.left) / 2);
|
|
MagRect.left = sCenter - (usTotalWidth / 2);
|
|
MagRect.right = sCenter + (usTotalWidth / 2);
|
|
}
|
|
#endif
|
|
|
|
//////////////////// BURST/AUTO LABEL AND BULLETS
|
|
if (pSoldier->bDoBurst)
|
|
{
|
|
SetFont( TINYFONT1 );
|
|
SetFontBackground( FONT_MCOLOR_BLACK );
|
|
SetFontForeground( FONT_MCOLOR_WHITE );
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// We need to calculate how many bullets to display, and how much space they
|
|
// take, so that we can center them horizontally on the CTH indicator.
|
|
// This works slightly differently for Autofire and Burst.
|
|
|
|
UINT8 ubNumBullets = 0;
|
|
UINT8 ubBulletWidth = 4;
|
|
UINT8 ubTotalWidth = 0;
|
|
UINT32 uiMaxAutofire = 0;
|
|
UINT32 uiMaxBulletsToDisplay = 0;
|
|
UINT32 uiSpacesToDisplay = 0;
|
|
|
|
if (pSoldier->bDoAutofire)
|
|
{
|
|
// Number of COLORED bullets to display is the number of bullets we want to fire.
|
|
ubNumBullets = pSoldier->bDoAutofire;
|
|
|
|
// How many bullets are left in the gun?
|
|
UINT32 uiBulletsLeft = pSoldier->inv[ pSoldier->ubAttackingHand ][0]->data.gun.ubGunShotsLeft;
|
|
if (pSoldier->IsValidSecondHandBurst())
|
|
{
|
|
uiBulletsLeft = min( (pSoldier->inv[ SECONDHANDPOS ][0]->data.gun.ubGunShotsLeft), uiBulletsLeft );
|
|
}
|
|
|
|
UINT32 uiCurBullet = uiBulletsLeft;
|
|
while( uiCurBullet > 0 )
|
|
{
|
|
// We work backwards from the total number of bullets left, to find out the number of bullets
|
|
// that can be fired given the current number of APs left.
|
|
|
|
// Store Soldier Autofire variable into a temp. We do this to fool the AP Calculation formula.
|
|
UINT8 TempDoAutofire = pSoldier->bDoAutofire;
|
|
pSoldier->bDoAutofire = uiCurBullet;
|
|
|
|
//Get AP cost to fire this many bullets
|
|
INT16 sAPCosts = CalcTotalAPsToAttack( pSoldier, gCTHDisplay.iTargetGridNo, TRUE, pSoldier->aiData.bShownAimTime);
|
|
|
|
// Switch back.
|
|
pSoldier->bDoAutofire = TempDoAutofire;
|
|
|
|
// Have we reached a number of bullets that can be fired with the current APs?
|
|
if( !uiMaxAutofire && EnoughPoints( pSoldier, sAPCosts, 0, FALSE ) )
|
|
{
|
|
// Set it.
|
|
uiMaxAutofire = uiCurBullet;
|
|
}
|
|
|
|
//Decrement until zero.
|
|
uiCurBullet--;
|
|
}
|
|
|
|
// Display no more than X bullets on screen!
|
|
uiMaxBulletsToDisplay = __min(uiMaxAutofire, 15);
|
|
|
|
// Calculate how many spaces to display. Currently, a space is displayed after every 5 bullets.
|
|
uiSpacesToDisplay = (uiMaxBulletsToDisplay-1) / 5;
|
|
|
|
// Calculate the total width of this display in pixels. Spaces and bullets have the same width.
|
|
ubTotalWidth = ubBulletWidth * (uiMaxBulletsToDisplay + uiSpacesToDisplay);
|
|
}
|
|
else
|
|
{
|
|
// Number of COLORED bullets to display is the number of bullets we want to fire.
|
|
ubNumBullets = GetShotsPerBurst( &(pSoldier->inv[ pSoldier->ubAttackingHand ]) );
|
|
|
|
// Display no more than X bullets on screen!
|
|
uiMaxBulletsToDisplay = __min(ubNumBullets, 15);
|
|
|
|
// Calculate how many spaces to display. Currently, a space is displayed after every 5 bullets.
|
|
uiSpacesToDisplay = (uiMaxBulletsToDisplay-1) / 5;
|
|
|
|
// Calculate the total width of this display in pixels. Spaces and bullets have the same width.
|
|
ubTotalWidth = ubBulletWidth * (uiMaxBulletsToDisplay + uiSpacesToDisplay);
|
|
}
|
|
|
|
// Tracks the number of spaces we've drawn on screen so far.
|
|
UINT16 usNumSpacesShown = 0;
|
|
|
|
// AUTO FIRE
|
|
if (pSoldier->bDoAutofire)
|
|
{
|
|
// Draw greyed-out bullets, indicating how many bullets CAN be added to the volley given our
|
|
// current remaining APs.
|
|
for (UINT8 x = 0; x < (uiMaxBulletsToDisplay); x++)
|
|
{
|
|
// Find starting point for drawing
|
|
INT16 sLeft = (((INT16)ModeRect.left + (INT16)ModeRect.right)/2) - (ubTotalWidth/2);
|
|
INT16 sTop = (INT16)ModeRect.top;
|
|
|
|
// If we've drawn 5,10,15,etc. bullets, add a space.
|
|
if (x > 0 && x%5 == 0)
|
|
{
|
|
usNumSpacesShown++;
|
|
}
|
|
|
|
// Offset adds up the number of bullets and spaces we've already drawn.
|
|
INT16 sCurOffset = ubBulletWidth * (x+usNumSpacesShown);
|
|
|
|
// Draw a bullet here!
|
|
BltVideoObjectFromIndex( FRAME_BUFFER, guiCTHImage, 8, sLeft + sCurOffset, sTop, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
|
|
// If the number of bullets that can be fired is greater than the number of bullets we can display,
|
|
// and we've just now drawn the last displayable bullet, then...
|
|
if (x == uiMaxBulletsToDisplay-1 && uiMaxBulletsToDisplay < uiMaxAutofire)
|
|
{
|
|
// Draw a shaded plus sign at the end.
|
|
BltVideoObjectFromIndex( FRAME_BUFFER, guiCTHImage, 9, sLeft + sCurOffset + ubBulletWidth, sTop+2, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
}
|
|
}
|
|
|
|
// Draw colored bullets. These show how many bullets we've set to fire with the current volley.
|
|
usNumSpacesShown = 0;
|
|
for (UINT8 x = 0; x < ubNumBullets; x++)
|
|
{
|
|
// Set start point for drawing
|
|
INT16 sLeft = (((INT16)ModeRect.left + (INT16)ModeRect.right)/2) - (ubTotalWidth/2);
|
|
INT16 sTop = (INT16)ModeRect.top;
|
|
|
|
// Calculate offset based on the number of bullets and spaces already drawn.
|
|
INT16 sCurOffset = ubBulletWidth * (x+usNumSpacesShown);
|
|
|
|
// If we're drawing more bullets than can be displayed on-screen...
|
|
if (x == uiMaxBulletsToDisplay)
|
|
{
|
|
// Draw a colored plus sign at the end.
|
|
BltVideoObjectFromIndex( FRAME_BUFFER, guiCTHImage, 10, sLeft + sCurOffset, sTop+2, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
// Set x to NumBullets to end the loop
|
|
x = ubNumBullets;
|
|
}
|
|
else
|
|
{
|
|
// If we've drawn 5,10,15,etc. bullets, increase the number of spaces drawn.
|
|
if (x > 0 && x%5 == 0)
|
|
{
|
|
usNumSpacesShown++;
|
|
}
|
|
// Recalculate offset to take any new spaces into account.
|
|
INT16 sCurOffset = ubBulletWidth * (x+usNumSpacesShown);
|
|
// Draw a colored bullet here.
|
|
BltVideoObjectFromIndex( FRAME_BUFFER, guiCTHImage, 7, sLeft + sCurOffset, sTop, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
}
|
|
}
|
|
|
|
// Redefine area size based on total width plus a margin of 2 pixels.
|
|
ubTotalWidth = ubTotalWidth + 6;
|
|
INT16 sCenter = (INT16)((ModeRect.right + ModeRect.left) / 2);
|
|
ModeRect.left = sCenter - (ubTotalWidth / 2);
|
|
ModeRect.right = sCenter + (ubTotalWidth / 2);
|
|
|
|
}
|
|
// BURST FIRE
|
|
else
|
|
{
|
|
// Draw colored bullets. These show how many bullets we've set to fire with the current burst.
|
|
usNumSpacesShown = 0;
|
|
UINT16 usTotalWidth = 0;
|
|
UINT8 x;
|
|
for (x = 0; x < ubNumBullets; x++)
|
|
{
|
|
// Set start point for drawing
|
|
INT16 sLeft = (((INT16)ModeRect.left + (INT16)ModeRect.right)/2) - (ubTotalWidth/2);
|
|
INT16 sTop = (INT16)ModeRect.top;
|
|
|
|
// Calculate offset based on the number of bullets and spaces already drawn.
|
|
INT16 sCurOffset = ubBulletWidth * (x+usNumSpacesShown);
|
|
|
|
// If we're drawing more bullets than can be displayed on-screen...
|
|
if (x == uiMaxBulletsToDisplay)
|
|
{
|
|
// Draw a colored plus sign at the end.
|
|
BltVideoObjectFromIndex( FRAME_BUFFER, guiCTHImage, 10, sLeft + sCurOffset, sTop+2, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
// Set x to NumBullets to end the loop
|
|
x = ubNumBullets;
|
|
usTotalWidth += 5;
|
|
}
|
|
else
|
|
{
|
|
// If we've drawn 5,10,15,etc. bullets, increase the number of spaces drawn.
|
|
if (x > 0 && x%5 == 0)
|
|
{
|
|
usNumSpacesShown++;
|
|
}
|
|
// Recalculate offset to take any new spaces into account.
|
|
INT16 sCurOffset = ubBulletWidth * (x+usNumSpacesShown);
|
|
// Draw a colored bullet here.
|
|
BltVideoObjectFromIndex( FRAME_BUFFER, guiCTHImage, 7, sLeft + sCurOffset, sTop, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
}
|
|
}
|
|
usTotalWidth += ubBulletWidth * ((x+1)+usNumSpacesShown)+4;
|
|
INT16 sCenter = (INT16)((ModeRect.right + ModeRect.left) / 2);
|
|
ModeRect.left = sCenter - (ubTotalWidth / 2);
|
|
ModeRect.right = sCenter + (ubTotalWidth / 2);
|
|
}
|
|
}
|
|
|
|
/////////////// SINGLE-SHOT.
|
|
else
|
|
{
|
|
// Draw a label that says "SINGLE" instead of bullets.
|
|
SetFont( TINYFONT1 );
|
|
SetFontBackground( FONT_MCOLOR_BLACK );
|
|
SetFontForeground( FONT_MCOLOR_WHITE );
|
|
|
|
swprintf( pStr, gzNCTHlabels[ 0 ] );
|
|
FindFontCenterCoordinates( (INT16)ModeRect.left, (INT16)ModeRect.top, (INT16)ModeRect.right-(INT16)ModeRect.left, 10, pStr, TINYFONT1, &curX, &curY);
|
|
gprintfdirty( curX, curY, pStr );
|
|
mprintf( curX, curY, pStr);
|
|
|
|
UINT16 usTotalWidth = StringPixLength( pStr, TINYFONT1 ) + 6;
|
|
INT16 sCenter = (INT16)((ModeRect.right + ModeRect.left) / 2);
|
|
ModeRect.left = sCenter - (usTotalWidth / 2);
|
|
ModeRect.right = sCenter + (usTotalWidth / 2);
|
|
}
|
|
|
|
/////////////// AIM LEVELS
|
|
{
|
|
// Calculate number of allowed aiming levels on this gun.
|
|
INT8 ubAllowedLevels = AllowedAimingLevels( pSoldier, gCTHDisplay.iTargetGridNo );
|
|
|
|
// Number of ticks to display, and the number of spaces between them.
|
|
UINT8 ubNumTicks = ((ubAllowedLevels-1)*2)+1;
|
|
UINT8 ubNumSpaces = ubNumTicks-1;
|
|
|
|
// Width of the tick image plus (or minus) a mandatory margin.
|
|
UINT8 ubAimTickWidth = 5;
|
|
|
|
// Total width of the aiming display if using no extra spacing and MAXIMUM allowed aiming levels (currently 8)
|
|
UINT8 ubAimMaxTotalWidth = ubAimTickWidth * ((8 * 2)-1);
|
|
|
|
// Total width of the aiming display if using no extra spacing and as many levels as allowed by the gun.
|
|
UINT8 ubAimPlainWidth = ubAimTickWidth * ubNumTicks;
|
|
|
|
// Find the largest space width possible without exceeding the maximum width. We do this by
|
|
// finding the difference between MaxTotal width and Plain width, and dividing it by the number of spaces
|
|
// we've got.
|
|
UINT8 ubAimFinalOffset = 0;
|
|
UINT8 ubAimFinalWidth = 0;
|
|
if (ubNumSpaces > 0)
|
|
{
|
|
UINT8 ubAimBestOffset = (ubAimMaxTotalWidth - ubAimPlainWidth) / ubNumSpaces;
|
|
|
|
// Final offset is whichever is smallest - the largest width, or the width of a single tick.
|
|
ubAimFinalOffset = __min(ubAimBestOffset, ubAimTickWidth);
|
|
}
|
|
// else leave at 0
|
|
|
|
ubAimFinalOffset += ubAimTickWidth;
|
|
|
|
// Final width of the entire display, taking all ticks and spaces into account.
|
|
ubAimFinalWidth = ubAimTickWidth + (ubAimFinalOffset * ubNumSpaces);
|
|
|
|
// Find offset from center.
|
|
UINT8 ubAimLeftOffset = ubAimFinalWidth / 2;
|
|
|
|
// Find starting coordinates for this display
|
|
sTop = (INT16)AimRect.top;
|
|
sLeft = (INT16)((AimRect.left+AimRect.right)/2) - ubAimLeftOffset;
|
|
|
|
// Draw empty ticks.
|
|
for (UINT8 x = 0; x < (ubAllowedLevels*2)-1; x++)
|
|
{
|
|
INT16 sOffset = x * ubAimFinalOffset;
|
|
if (gfDisplayFullCountRing)
|
|
{
|
|
if (ubAllowedLevels - abs((ubAllowedLevels-(x+1))) >= pSoldier->aiData.bShownAimTime)
|
|
{
|
|
// Red empty tick - unusable aim level with current AP!
|
|
BltVideoObjectFromIndex( FRAME_BUFFER, guiCTHImage, 6, sLeft + sOffset, sTop, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
}
|
|
else
|
|
{
|
|
// Orange empty tick - Used aim tick.
|
|
BltVideoObjectFromIndex( FRAME_BUFFER, guiCTHImage, 4, sLeft + sOffset, sTop, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (pSoldier->IsValidAlternativeFireMode( pSoldier->aiData.bShownAimTime, gCTHDisplay.iTargetGridNo ) &&
|
|
ubAllowedLevels - abs((ubAllowedLevels-(x+1))) <= GetNumberAltFireAimLevels( pSoldier, gCTHDisplay.iTargetGridNo ) )
|
|
{
|
|
// yellow empty tick
|
|
BltVideoObjectFromIndex( FRAME_BUFFER, guiCTHImage, 2, sLeft + sOffset, sTop, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
}
|
|
else
|
|
{
|
|
// grey empty tick
|
|
BltVideoObjectFromIndex( FRAME_BUFFER, guiCTHImage, 0, sLeft + sOffset, sTop, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
}
|
|
}
|
|
}
|
|
|
|
// Draw Filled Ticks
|
|
if (pSoldier->aiData.bShownAimTime)
|
|
{
|
|
// Tick on the left
|
|
INT16 sNewLeft = sLeft + (ubAimFinalOffset * (pSoldier->aiData.bShownAimTime-1));
|
|
if (gfDisplayFullCountRing)
|
|
{
|
|
if ( pSoldier->IsValidAlternativeFireMode( pSoldier->aiData.bShownAimTime, gCTHDisplay.iTargetGridNo ) )
|
|
{
|
|
BltVideoObjectFromIndex( FRAME_BUFFER, guiCTHImage, 3, sNewLeft, sTop, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
}
|
|
else
|
|
{
|
|
BltVideoObjectFromIndex( FRAME_BUFFER, guiCTHImage, 5, sNewLeft, sTop, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( pSoldier->IsValidAlternativeFireMode( pSoldier->aiData.bShownAimTime, gCTHDisplay.iTargetGridNo ) )
|
|
{
|
|
BltVideoObjectFromIndex( FRAME_BUFFER, guiCTHImage, 3, sNewLeft, sTop, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
}
|
|
else
|
|
{
|
|
BltVideoObjectFromIndex( FRAME_BUFFER, guiCTHImage, 1, sNewLeft, sTop, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
}
|
|
}
|
|
|
|
// Tick on the right
|
|
sNewLeft = sLeft + (ubAimFinalOffset * (ubNumSpaces-(pSoldier->aiData.bShownAimTime-1)));
|
|
if (gfDisplayFullCountRing)
|
|
{
|
|
if ( pSoldier->IsValidAlternativeFireMode( pSoldier->aiData.bShownAimTime, gCTHDisplay.iTargetGridNo ) )
|
|
{
|
|
BltVideoObjectFromIndex( FRAME_BUFFER, guiCTHImage, 3, sNewLeft, sTop, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
}
|
|
else
|
|
{
|
|
BltVideoObjectFromIndex( FRAME_BUFFER, guiCTHImage, 5, sNewLeft, sTop, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( pSoldier->IsValidAlternativeFireMode( pSoldier->aiData.bShownAimTime, gCTHDisplay.iTargetGridNo ) )
|
|
{
|
|
BltVideoObjectFromIndex( FRAME_BUFFER, guiCTHImage, 3, sNewLeft, sTop, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
}
|
|
else
|
|
{
|
|
BltVideoObjectFromIndex( FRAME_BUFFER, guiCTHImage, 1, sNewLeft, sTop, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
}
|
|
}
|
|
}
|
|
|
|
ubAimFinalWidth += 6;
|
|
INT16 sCenter = (INT16)((AimRect.right + AimRect.left) / 2);
|
|
AimRect.left = sCenter - (ubAimFinalWidth / 2);
|
|
AimRect.right = sCenter + (ubAimFinalWidth / 2);
|
|
|
|
}
|
|
|
|
// Delete CTH indicator STIs from memory.
|
|
DeleteVideoObjectFromIndex( guiCTHImage );
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////
|
|
// HEADROCK HAM 4: Drawing the CTH indicator to the Frame Buffer
|
|
//
|
|
// Early on I ran into issues concerning drawing this indicator on the screen. At first I naturally
|
|
// wanted to draw it on the Cursor Buffer, the same way as the old indicator. Unfortunately,
|
|
// the size of the Cursor Buffer is quite limited (~35x35 pixels) and is governed by the size of the STIs used
|
|
// for the mouse cursor itself. After much trial and error, it became obvious that it was impossible to draw
|
|
// a large indicator (as required by the NCTH system) directly onto the mouse buffer.
|
|
//
|
|
// Fortunately, I found out that it was possible to draw into the Frame Buffer instead, without leaving
|
|
// graphical glitches behind. I could also dynamically define the area to draw into as I pleased. Furthermore,
|
|
// I managed to make this drawing behave the same as a mouse cursor would, by having it follow the mouse
|
|
// position.
|
|
//
|
|
// The end result is a bit of an ugly workaround: We're drawing what is essentially a mouse cursor without referring
|
|
// to ANY part of the mouse cursor system (except the location of the mouse). This is the only way I could make it
|
|
// work, and so far it works flawlessly.
|
|
|
|
// Create a pointer to the Frame Buffer which we are going to draw directly into.
|
|
UINT32 uiPitch;
|
|
UINT16 *ptrBuf = (UINT16*)LockVideoSurface( FRAME_BUFFER, &uiPitch );
|
|
uiPitch >>= 1;
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// Begin drawing
|
|
|
|
sLeft = gsVIEWPORT_START_X;
|
|
sTop = gsVIEWPORT_WINDOW_START_Y;
|
|
sRight = gsVIEWPORT_END_X;
|
|
sBottom = gsVIEWPORT_WINDOW_END_Y;
|
|
|
|
// INT16 lastY = 0;
|
|
// INT16 diffY = 0;
|
|
// UINT32 uiAperture = __max(2,(UINT32)iAperture);
|
|
// UINT32 uiMaxAperture = __max(2,(UINT32)iDistanceAperture);
|
|
UINT32 uiApertureBarLength = 10;
|
|
|
|
INT32 cnt = 0;
|
|
|
|
// Vertical bias makes the circle "flatter" and "wider" in prone and crouched stance.
|
|
FLOAT dVerticalBias = gGameCTHConstants.VERTICAL_BIAS;
|
|
switch (gAnimControl[ pSoldier->usAnimState ].ubEndHeight)
|
|
{
|
|
case ANIM_STAND:
|
|
dVerticalBias = 1.0;
|
|
break;
|
|
case ANIM_PRONE:
|
|
// no change
|
|
break;
|
|
case ANIM_CROUCH:
|
|
dVerticalBias = 1.0f + ((dVerticalBias - 1.0f) * 0.66f);
|
|
break;
|
|
}
|
|
|
|
// Circumference tells us how many pixels to draw, hopefully.
|
|
FLOAT RADIANS_IN_CIRCLE = (FLOAT)(PI * 2);
|
|
INT32 Circ = 0;
|
|
|
|
Circ = (INT32)((iDistanceAperture * RADIANS_IN_CIRCLE) * dVerticalBias);
|
|
if(gGameSettings.fOptions[ TOPTION_CTH_CURSOR ])
|
|
{
|
|
// Draw outer circle
|
|
for (INT32 iCurPoint = 0; iCurPoint < Circ; iCurPoint++)
|
|
{
|
|
curX = (INT16)(iDistanceAperture * cos((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
|
|
curY = (INT16)((iDistanceAperture * dVerticalBias) * sin((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
|
|
INT16 firstX = curX;
|
|
INT16 firstY = curY;
|
|
|
|
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+curX, sStartScreenY+curY+(INT16)zOffset, usCApertureBar );
|
|
|
|
// Draw a border circle which is 1 point wider
|
|
// curX = (INT16)((iDistanceAperture+1) * cos((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
|
|
// curY = (INT16)(((iDistanceAperture * dVerticalBias)+1) * sin((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
|
|
|
|
// if (curX != firstX || curY != firstY)
|
|
// DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+curX, sStartScreenY+curY+(INT16)zOffset, usCApertureBorder );
|
|
|
|
// Draw a border circle which is 1 point narrower
|
|
// curX = (INT16)((iDistanceAperture-1) * cos((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
|
|
// curY = (INT16)(((iDistanceAperture * dVerticalBias)-1) * sin((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
|
|
|
|
// if (curX != firstX || curY != firstY)
|
|
// DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+curX, sStartScreenY+curY+(INT16)zOffset, usCApertureBorder );
|
|
}
|
|
|
|
Circ = (INT32)((iAperture * RADIANS_IN_CIRCLE) * dVerticalBias);
|
|
// Draw inner circle
|
|
for (INT32 iCurPoint = 0; iCurPoint < Circ; iCurPoint++)
|
|
{
|
|
curX = (INT16)(iAperture * cos((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
|
|
curY = (INT16)((iAperture * dVerticalBias) * sin((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
|
|
INT16 firstX = curX;
|
|
INT16 firstY = curY;
|
|
|
|
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+curX, sStartScreenY+curY+(INT16)zOffset, usCApertureBar );
|
|
|
|
// Draw a border circle which is 1 point wider
|
|
// curX = (INT16)((iAperture+1) * cos((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
|
|
// curY = (INT16)(((iAperture * dVerticalBias)+1) * sin((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
|
|
|
|
// if (curX != firstX || curY != firstY)
|
|
// DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+curX, sStartScreenY+curY+(INT16)zOffset, usCApertureBorder );
|
|
|
|
// Draw a border circle which is 1 point narrower
|
|
// curX = (INT16)((iAperture-1) * cos((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
|
|
// curY = (INT16)(((iAperture * dVerticalBias)-1) * sin((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
|
|
|
|
// if (curX != firstX || curY != firstY)
|
|
// DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+curX, sStartScreenY+curY+(INT16)zOffset, usCApertureBorder );
|
|
}
|
|
|
|
// Aperture Crosshairs
|
|
for (INT16 cnt = (INT16)(iAperture); cnt <= (INT16)(iAperture + uiApertureBarLength); cnt++)
|
|
{
|
|
// Horizontal Aperture Crosshairs
|
|
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+cnt, sStartScreenY+(INT16)zOffset, usCApertureBar );
|
|
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX-cnt, sStartScreenY+(INT16)zOffset, usCApertureBar );
|
|
|
|
// DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+cnt, (sStartScreenY+1)+(INT16)zOffset, usCApertureBar );
|
|
// DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX-cnt, (sStartScreenY+1)+(INT16)zOffset, usCApertureBar );
|
|
|
|
// DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+cnt, (sStartScreenY-1)+(INT16)zOffset, usCApertureBar );
|
|
// DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX-cnt, (sStartScreenY-1)+(INT16)zOffset, usCApertureBar );
|
|
|
|
// Darker borders
|
|
// DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+cnt, (sStartScreenY+2)+(INT16)zOffset, usCApertureBorder );
|
|
// DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX-cnt, (sStartScreenY+2)+(INT16)zOffset, usCApertureBorder );
|
|
|
|
// DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+cnt, (sStartScreenY-2)+(INT16)zOffset, usCApertureBorder );
|
|
// DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX-cnt, (sStartScreenY-2)+(INT16)zOffset, usCApertureBorder );
|
|
|
|
// Darker borders
|
|
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+cnt, (sStartScreenY+1)+(INT16)zOffset, usCApertureBorder );
|
|
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX-cnt, (sStartScreenY+1)+(INT16)zOffset, usCApertureBorder );
|
|
|
|
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+cnt, (sStartScreenY-1)+(INT16)zOffset, usCApertureBorder );
|
|
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX-cnt, (sStartScreenY-1)+(INT16)zOffset, usCApertureBorder );
|
|
|
|
}
|
|
for (INT16 cnt = (INT16)(iAperture * dVerticalBias); cnt <= (INT16)((iAperture * dVerticalBias) + uiApertureBarLength); cnt++)
|
|
{
|
|
// Vertical Aperture Crosshairs
|
|
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX, (sStartScreenY+cnt)+(INT16)zOffset, usCApertureBar );
|
|
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX, (sStartScreenY-cnt)+(INT16)zOffset, usCApertureBar );
|
|
|
|
// DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+1, (sStartScreenY+cnt)+(INT16)zOffset, usCApertureBar );
|
|
// DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+1, (sStartScreenY-cnt)+(INT16)zOffset, usCApertureBar );
|
|
|
|
// DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX-1, (sStartScreenY+cnt)+(INT16)zOffset, usCApertureBar );
|
|
// DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX-1, (sStartScreenY-cnt)+(INT16)zOffset, usCApertureBar );
|
|
|
|
// Darker borders
|
|
// DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+2, (sStartScreenY+cnt)+(INT16)zOffset, usCApertureBorder );
|
|
// DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+2, (sStartScreenY-cnt)+(INT16)zOffset, usCApertureBorder );
|
|
|
|
// DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX-2, (sStartScreenY+cnt)+(INT16)zOffset, usCApertureBorder );
|
|
// DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX-2, (sStartScreenY-cnt)+(INT16)zOffset, usCApertureBorder );
|
|
|
|
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+1, (sStartScreenY+cnt)+(INT16)zOffset, usCApertureBorder );
|
|
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+1, (sStartScreenY-cnt)+(INT16)zOffset, usCApertureBorder );
|
|
|
|
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX-1, (sStartScreenY+cnt)+(INT16)zOffset, usCApertureBorder );
|
|
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX-1, (sStartScreenY-cnt)+(INT16)zOffset, usCApertureBorder );
|
|
|
|
}
|
|
}
|
|
|
|
// Unlock the Frame Buffer.
|
|
UnLockVideoSurface( FRAME_BUFFER );
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
void RenderOverlayMessage( VIDEO_OVERLAY *pBlitter )
|
|
{
|
|
// Override it!
|
|
OverrideMercPopupBox( &gpOverrideMercBox );
|
|
|
|
RenderMercPopupBox( pBlitter->sX, pBlitter->sY, pBlitter->uiDestBuff );
|
|
|
|
// Set it back!
|
|
ResetOverrideMercPopupBox( );
|
|
|
|
InvalidateRegion( pBlitter->sX, pBlitter->sY, pBlitter->sX + gusOverlayPopupBoxWidth, pBlitter->sY + gusOverlayPopupBoxHeight );
|
|
}
|
|
|
|
|
|
void BeginOverlayMessage( UINT32 uiFont, STR16 pFontString, ... )
|
|
{
|
|
va_list argptr;
|
|
VIDEO_OVERLAY_DESC VideoOverlayDesc;
|
|
CHAR16 SlideString[512];
|
|
|
|
|
|
va_start(argptr, pFontString); // Set up variable argument pointer
|
|
vswprintf(SlideString, pFontString, argptr); // process gprintf string (get output str)
|
|
va_end(argptr);
|
|
|
|
// Override it!
|
|
OverrideMercPopupBox( &gpOverrideMercBox );
|
|
|
|
SetPrepareMercPopupFlags( MERC_POPUP_PREPARE_FLAGS_TRANS_BACK | MERC_POPUP_PREPARE_FLAGS_MARGINS );
|
|
|
|
// Prepare text box
|
|
iOverlayMessageBox = PrepareMercPopupBox( iOverlayMessageBox, BASIC_MERC_POPUP_BACKGROUND, RED_MERC_POPUP_BORDER, SlideString, 200, 50, 0, 0, &gusOverlayPopupBoxWidth, &gusOverlayPopupBoxHeight );
|
|
|
|
// Set it back!
|
|
ResetOverrideMercPopupBox( );
|
|
|
|
if ( giPopupSlideMessageOverlay == -1 )
|
|
{
|
|
// WDS - bug fix: VideoOverlayDesc must be initialized! - 07/16/2007
|
|
memset( &VideoOverlayDesc, 0, sizeof( VIDEO_OVERLAY_DESC ) );
|
|
|
|
// Set Overlay
|
|
VideoOverlayDesc.sLeft = ( SCREEN_WIDTH - gusOverlayPopupBoxWidth ) / 2;
|
|
VideoOverlayDesc.sTop = 100;
|
|
VideoOverlayDesc.sRight = VideoOverlayDesc.sLeft + gusOverlayPopupBoxWidth;
|
|
VideoOverlayDesc.sBottom = VideoOverlayDesc.sTop + gusOverlayPopupBoxHeight;
|
|
VideoOverlayDesc.sX = VideoOverlayDesc.sLeft;
|
|
VideoOverlayDesc.sY = VideoOverlayDesc.sTop;
|
|
VideoOverlayDesc.BltCallback = RenderOverlayMessage;
|
|
|
|
giPopupSlideMessageOverlay = RegisterVideoOverlay( 0, &VideoOverlayDesc );
|
|
}
|
|
|
|
}
|
|
|
|
void EndOverlayMessage( )
|
|
{
|
|
if ( giPopupSlideMessageOverlay != -1 )
|
|
{
|
|
|
|
// DebugMsg( TOPIC_JA2, DBG_LEVEL_0, String( "Removing Overlay message") );
|
|
|
|
RemoveVideoOverlay( giPopupSlideMessageOverlay );
|
|
|
|
giPopupSlideMessageOverlay = -1;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
void DrawBarsInUIBox( SOLDIERTYPE *pSoldier , INT16 sXPos, INT16 sYPos, INT16 sWidth, INT16 sHeight, INT16 interval )
|
|
{
|
|
FLOAT dWidth, dPercentage;
|
|
UINT32 uiDestPitchBYTES;
|
|
UINT8 *pDestBuf;
|
|
INT8 bBandage;
|
|
INT8 bPoisonBandage;
|
|
INT16 color8;
|
|
INT16 color16;
|
|
|
|
// Draw new size
|
|
pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES );
|
|
|
|
// region rysowania barow nad najemnikiem
|
|
SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, gsVIEWPORT_WINDOW_START_Y, SCREEN_WIDTH, ( gsVIEWPORT_WINDOW_END_Y - gsVIEWPORT_WINDOW_START_Y ) );
|
|
|
|
// sevenfm: draw background for alt bar
|
|
if( gGameExternalOptions.ubShowHealthBarsOnHead > 1 )
|
|
{
|
|
DrawBar( sXPos+2, sYPos, sWidth + 2, 1 + interval*3, COLOR_BLACK, Get16BPPColor( FROMRGB( 0, 0, 0 ) ), pDestBuf );
|
|
// draw border: light brown for stealth mode, grey for regular
|
|
if(pSoldier->bStealthMode)
|
|
{
|
|
color8 = COLOR_BROWN;
|
|
color16 = Get16BPPColor( FROMRGB( 180, 140, 20 ) );
|
|
}
|
|
else{
|
|
color8 = COLOR_DKGREY;
|
|
color16 = Get16BPPColor( FROMRGB( 120, 120, 120 ) );
|
|
}
|
|
if ( pSoldier->ubID == gusSelectedSoldier )
|
|
{
|
|
if(gbPixelDepth==16)
|
|
RectangleDraw( TRUE, sXPos+1, sYPos-1, sXPos+sWidth+3, sYPos+1+interval*3, color16, pDestBuf);
|
|
else
|
|
RectangleDraw8( TRUE, sXPos+1, sYPos-1, sXPos+sWidth+3, sYPos+1+interval*3, color8, pDestBuf);
|
|
}
|
|
}
|
|
|
|
// get amt bandaged
|
|
bBandage = pSoldier->stats.bLifeMax - pSoldier->stats.bLife - pSoldier->bBleeding;
|
|
|
|
// get amount of poisoned bandage
|
|
bPoisonBandage = pSoldier->bPoisonSum - pSoldier->bPoisonBleeding - pSoldier->bPoisonLife;
|
|
|
|
// NOW DO BLEEDING
|
|
if ( pSoldier->bBleeding )
|
|
{
|
|
dPercentage = (FLOAT)( pSoldier->bBleeding + pSoldier->stats.bLife + bBandage )/ (FLOAT)100;
|
|
dWidth = dPercentage * sWidth;
|
|
DrawBar( sXPos + 3, sYPos + 1, (INT32)dWidth, sHeight, COLOR_RED, Get16BPPColor( FROMRGB( 240, 240, 20 ) ), pDestBuf );
|
|
}
|
|
|
|
// poisoned bleeding
|
|
if ( pSoldier->bPoisonBleeding )
|
|
{
|
|
dPercentage = (FLOAT)( pSoldier->stats.bLifeMax - pSoldier->bBleeding + pSoldier->bPoisonBleeding )/ (FLOAT)100;
|
|
dWidth = dPercentage * sWidth;
|
|
DrawBar( sXPos + 3, sYPos + 1, (INT32)dWidth, sHeight, COLOR_GREEN, Get16BPPColor( FROMRGB( 240, 20, 240 ) ), pDestBuf );
|
|
}
|
|
|
|
if( bBandage )
|
|
{
|
|
dPercentage = (FLOAT)( pSoldier->stats.bLife + bBandage ) / (FLOAT)100;
|
|
dWidth = dPercentage * sWidth;
|
|
DrawBar( sXPos + 3, sYPos + 1, (INT32)dWidth, sHeight, COLOR_RED, Get16BPPColor( FROMRGB( 222, 132, 132 ) ), pDestBuf );
|
|
}
|
|
|
|
// poisoned bandage
|
|
if ( bPoisonBandage )
|
|
{
|
|
dPercentage = (FLOAT)( pSoldier->stats.bLife + bPoisonBandage )/ (FLOAT)100;
|
|
dWidth = dPercentage * sWidth;
|
|
DrawBar( sXPos + 3, sYPos + 1, (INT32)dWidth, sHeight, COLOR_GREEN, Get16BPPColor( FROMRGB( 132, 222, 132 ) ), pDestBuf );
|
|
}
|
|
|
|
dPercentage = (FLOAT)pSoldier->stats.bLife / (FLOAT)100;
|
|
dWidth = dPercentage * sWidth;
|
|
DrawBar( sXPos + 3, sYPos + 1, (INT32)dWidth, sHeight, COLOR_RED, Get16BPPColor( FROMRGB( 200, 0, 0 ) ), pDestBuf );
|
|
|
|
// poisoned life
|
|
if ( pSoldier->bPoisonLife )
|
|
{
|
|
dPercentage = (FLOAT)( pSoldier->bPoisonLife )/ (FLOAT)100;
|
|
dWidth = dPercentage * sWidth;
|
|
DrawBar( sXPos + 3, sYPos + 1, (INT32)dWidth, sHeight, COLOR_GREEN, Get16BPPColor( FROMRGB( 0, 200, 0 ) ), pDestBuf );
|
|
}
|
|
|
|
dPercentage = (FLOAT)( pSoldier->bBreathMax ) / (FLOAT)100;
|
|
dWidth = dPercentage * sWidth;
|
|
DrawBar( sXPos + 3, sYPos + 1 + interval, (INT32)dWidth, sHeight, COLOR_BLUE, Get16BPPColor( FROMRGB( 20, 20, 150 ) ), pDestBuf );
|
|
|
|
dPercentage = (FLOAT)( pSoldier->bBreath ) / (FLOAT)100;
|
|
dWidth = dPercentage * sWidth;
|
|
DrawBar( sXPos + 3, sYPos + 1 + interval, (INT32)dWidth, sHeight, COLOR_BLUE, Get16BPPColor( FROMRGB( 100, 100, 220 ) ), pDestBuf );
|
|
|
|
/*
|
|
// morale
|
|
dPercentage = (FLOAT)pSoldier->aiData.bMorale / (FLOAT)100;
|
|
dWidth = dPercentage * sWidth;
|
|
if(gbPixelDepth==16)
|
|
{
|
|
usLineColor = Get16BPPColor( FROMRGB( 0, 250, 0 ) );
|
|
RectangleDraw( TRUE, sXPos + 1, sYPos + 7, (INT32)( sXPos + dWidth + 1 ), sYPos + 7, usLineColor, pDestBuf );
|
|
}
|
|
else if(gbPixelDepth==8)
|
|
{
|
|
// DB Need to change this to a color from the 8-bit standard palette
|
|
usLineColor = COLOR_GREEN;
|
|
RectangleDraw8( TRUE, sXPos + 1, sYPos + 7, (INT32)( sXPos + dWidth + 1 ), sYPos + 7, usLineColor, pDestBuf );
|
|
}
|
|
|
|
*/
|
|
|
|
// draw suppression shock bar
|
|
if( gGameExternalOptions.ubShowHealthBarsOnHead > 1 )
|
|
{
|
|
dPercentage = (FLOAT)( __min(100, ( (FLOAT)100 * CalcEffectiveShockLevel( pSoldier ) ) / CalcSuppressionTolerance( pSoldier ) ) ) / (FLOAT)100;
|
|
dWidth = dPercentage * sWidth;
|
|
DrawBar( sXPos+3, sYPos+1+2*interval, (INT32)dWidth, sHeight, COLOR_ORANGE, Get16BPPColor( FROMRGB( 220, 140, 0 ) ), pDestBuf );
|
|
}
|
|
|
|
/*
|
|
BOOLEAN bDisguised = pSoldier->bSoldierFlagMask & (SOLDIER_COVERT_CIV | SOLDIER_COVERT_SOLDIER);
|
|
BOOLEAN bStealth = pSoldier->bStealthMode;
|
|
// draw cover indicators
|
|
if( ( gGameExternalOptions.ubShowHealthBarsOnHead > 1 ) &&
|
|
( (gTacticalStatus.uiFlags & TURNBASED ) && (gTacticalStatus.uiFlags & INCOMBAT) || bStealth || bDisguised ) )
|
|
{
|
|
INT8 cover = 3; // MAX_COVER
|
|
BOOLEAN showCover;
|
|
INT32 usMapPos;
|
|
|
|
if( gGameExternalOptions.ubShowCoverIndicator ==1 ||
|
|
( gGameExternalOptions.ubShowCoverIndicator ==3 && (bStealth || bDisguised) ) )
|
|
{
|
|
if( GetMouseMapPos(&usMapPos) && _KeyDown(SHIFT) )
|
|
{
|
|
// draw target tile cover indicator
|
|
CalculateCoverForSoldier( pSoldier, usMapPos, gsInterfaceLevel, cover );
|
|
showCover = CoverColorCode( cover, color8, color16 );
|
|
}
|
|
else
|
|
{
|
|
// draw cover indicator
|
|
CalculateCoverForSoldier( pSoldier, pSoldier->sGridNo, pSoldier->pathing.bLevel, cover );
|
|
showCover = CoverColorCode( cover, color8, color16 );
|
|
if ( color8 == COLOR_GREEN)
|
|
showCover = FALSE;
|
|
}
|
|
|
|
if(showCover)
|
|
DrawBar( sXPos+33, sYPos+1, 1+sHeight , (interval==3 ? 2 : 3 )*interval-1, color8, color16, pDestBuf );
|
|
}
|
|
}
|
|
*/
|
|
|
|
UnLockVideoSurface( FRAME_BUFFER );
|
|
|
|
}
|
|
|
|
void EndDeadlockMsg( )
|
|
{
|
|
// Reset gridlock
|
|
gfUIInDeadlock = FALSE;
|
|
}
|
|
|
|
|
|
void ClearInterface( )
|
|
{
|
|
if ( (guiTacticalInterfaceFlags & INTERFACE_MAPSCREEN ) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Stop any UI menus!
|
|
if ( gCurrentUIMode == MENU_MODE )
|
|
{
|
|
EndMenuEvent( guiCurrentEvent );
|
|
}
|
|
|
|
if ( gfUIHandleShowMoveGrid )
|
|
{
|
|
RemoveTopmost( gsUIHandleShowMoveGridLocation, FIRSTPOINTERS4 );
|
|
RemoveTopmost( gsUIHandleShowMoveGridLocation, FIRSTPOINTERS2 );
|
|
RemoveTopmost( gsUIHandleShowMoveGridLocation, FIRSTPOINTERS13 );
|
|
RemoveTopmost( gsUIHandleShowMoveGridLocation, FIRSTPOINTERS15 );
|
|
}
|
|
|
|
// Remove any popup menus
|
|
if ( gCurrentUIMode == GETTINGITEM_MODE )
|
|
{
|
|
RemoveItemPickupMenu( );
|
|
}
|
|
|
|
// Remove any popup menus
|
|
if ( gCurrentUIMode == OPENDOOR_MENU_MODE )
|
|
{
|
|
PopDownOpenDoorMenu( );
|
|
}
|
|
|
|
// Remove UP/DOWN arrows...
|
|
//EraseRenderArrows( );
|
|
// Don't render arrows this frame!
|
|
guiShowUPDownArrows = ARROWS_HIDE_UP | ARROWS_HIDE_DOWN;
|
|
gTintBulletCounts = FALSE;
|
|
gfUIAutofireBulletCount = FALSE;
|
|
|
|
ResetPhysicsTrajectoryUI( );
|
|
|
|
// Remove any paths, cursors
|
|
ErasePath( FALSE );
|
|
|
|
//gfPlotNewMovement = TRUE;
|
|
|
|
// Erase Interface cursors
|
|
HideUICursor( );
|
|
|
|
MSYS_ChangeRegionCursor( &gViewportRegion , VIDEO_NO_CURSOR );
|
|
|
|
// Hide lock UI cursors...
|
|
MSYS_ChangeRegionCursor( &gDisableRegion , VIDEO_NO_CURSOR );
|
|
MSYS_ChangeRegionCursor( &gUserTurnRegion , VIDEO_NO_CURSOR );
|
|
|
|
// Remove special thing for south arrow...
|
|
if ( gsGlobalCursorYOffset == ( SCREEN_HEIGHT - gsVIEWPORT_WINDOW_END_Y ) )
|
|
{
|
|
SetCurrentCursorFromDatabase( VIDEO_NO_CURSOR );
|
|
}
|
|
|
|
}
|
|
|
|
void RestoreInterface( )
|
|
{
|
|
// Once we are done, plot path again!
|
|
gfPlotNewMovement = TRUE;
|
|
|
|
// OK, reset arrows too...
|
|
gfUIRefreshArrows = TRUE;
|
|
|
|
// SHow lock UI cursors...
|
|
MSYS_ChangeRegionCursor( &gDisableRegion , CURSOR_WAIT );
|
|
MSYS_ChangeRegionCursor( &gUserTurnRegion , CURSOR_WAIT );
|
|
|
|
}
|
|
|
|
|
|
void BlitPopupText( VIDEO_OVERLAY *pBlitter )
|
|
{
|
|
UINT8 *pDestBuf;
|
|
UINT32 uiDestPitchBYTES;
|
|
|
|
BltVideoSurface( pBlitter->uiDestBuff, guiINTEXT, 0, pBlitter->pBackground->sLeft, pBlitter->pBackground->sTop, VS_BLT_FAST | VS_BLT_USECOLORKEY, NULL );
|
|
|
|
|
|
pDestBuf = LockVideoSurface( pBlitter->uiDestBuff, &uiDestPitchBYTES);
|
|
|
|
SetFont( pBlitter->uiFontID );
|
|
SetFontBackground( pBlitter->ubFontBack );
|
|
SetFontForeground( pBlitter->ubFontFore );
|
|
|
|
mprintf_buffer( pDestBuf, uiDestPitchBYTES, pBlitter->uiFontID, pBlitter->sX, pBlitter->sY, pBlitter->zText );
|
|
|
|
UnLockVideoSurface( pBlitter->uiDestBuff );
|
|
|
|
}
|
|
|
|
void DirtyMercPanelInterface( SOLDIERTYPE *pSoldier, UINT8 ubDirtyLevel )
|
|
{
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("DirtyMercPanelInterface"));
|
|
if ( pSoldier->bTeam == gbPlayerNum )
|
|
{
|
|
// ONly set to a higher level!
|
|
if ( fInterfacePanelDirty < ubDirtyLevel )
|
|
{
|
|
fInterfacePanelDirty = ubDirtyLevel;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
typedef struct
|
|
{
|
|
SOLDIERTYPE *pSoldier;
|
|
STRUCTURE *pStructure;
|
|
UINT8 ubDirection;
|
|
INT16 sX;
|
|
INT16 sY;
|
|
BOOLEAN fMenuHandled;
|
|
BOOLEAN fClosingDoor;
|
|
|
|
} OPENDOOR_MENU;
|
|
|
|
OPENDOOR_MENU gOpenDoorMenu;
|
|
BOOLEAN gfInOpenDoorMenu = FALSE;
|
|
|
|
BOOLEAN InitDoorOpenMenu( SOLDIERTYPE *pSoldier, STRUCTURE *pStructure, UINT8 ubDirection, BOOLEAN fClosingDoor )
|
|
{
|
|
INT16 sHeight, sWidth;
|
|
INT16 sScreenX, sScreenY;
|
|
|
|
// Can't bring up this menu if in autobandage mode
|
|
if (gTacticalStatus.fAutoBandageMode)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
// Erase other menus....
|
|
EraseInterfaceMenus( TRUE );
|
|
|
|
InterruptTime();
|
|
PauseGame();
|
|
LockPauseState( 19 );
|
|
// Pause timers as well....
|
|
PauseTime( TRUE );
|
|
|
|
|
|
gOpenDoorMenu.pSoldier = pSoldier;
|
|
gOpenDoorMenu.pStructure = pStructure;
|
|
gOpenDoorMenu.ubDirection = ubDirection;
|
|
gOpenDoorMenu.fClosingDoor = fClosingDoor;
|
|
|
|
// OK, Determine position...
|
|
// Center on guy
|
|
// Locate to guy first.....
|
|
LocateSoldier( pSoldier->ubID, FALSE );
|
|
GetSoldierAnimDims( pSoldier, &sHeight, &sWidth );
|
|
GetSoldierScreenPos( pSoldier, &sScreenX, &sScreenY );
|
|
gOpenDoorMenu.sX = sScreenX - ( ( BUTTON_PANEL_WIDTH - sWidth ) / 2 );
|
|
gOpenDoorMenu.sY = sScreenY - ( ( BUTTON_PANEL_HEIGHT - sHeight ) / 2 );
|
|
|
|
// Alrighty, cancel lock UI if we havn't done so already
|
|
UnSetUIBusy( pSoldier->ubID );
|
|
|
|
|
|
// OK, CHECK FOR BOUNDARIES!
|
|
if ( ( gOpenDoorMenu.sX + BUTTON_PANEL_WIDTH ) > SCREEN_WIDTH )
|
|
{
|
|
gOpenDoorMenu.sX = ( SCREEN_WIDTH - BUTTON_PANEL_WIDTH );
|
|
}
|
|
if ( ( gOpenDoorMenu.sY + BUTTON_PANEL_HEIGHT ) > gsVIEWPORT_WINDOW_END_Y )
|
|
{
|
|
gOpenDoorMenu.sY = ( gsVIEWPORT_WINDOW_END_Y - BUTTON_PANEL_HEIGHT );
|
|
}
|
|
if ( gOpenDoorMenu.sX < 0 )
|
|
{
|
|
gOpenDoorMenu.sX = 0;
|
|
}
|
|
if ( gOpenDoorMenu.sY < 0 )
|
|
{
|
|
gOpenDoorMenu.sY = 0;
|
|
}
|
|
|
|
|
|
gOpenDoorMenu.fMenuHandled = FALSE;
|
|
|
|
guiPendingOverrideEvent = OP_OPENDOORMENU;
|
|
HandleTacticalUI( );
|
|
|
|
PopupDoorOpenMenu( fClosingDoor );
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
void PopupDoorOpenMenu( BOOLEAN fClosingDoor )
|
|
{
|
|
INT32 iMenuAnchorX, iMenuAnchorY;
|
|
CHAR16 zDisp[ 100 ];
|
|
|
|
//iMenuAnchorX = gOpenDoorMenu.sX;
|
|
//iMenuAnchorY = gOpenDoorMenu.sY;
|
|
|
|
// Blit background!
|
|
//BltVideoObjectFromIndex( FRAME_BUFFER, guiBUTTONBORDER, 0, iMenuAnchorX, iMenuAnchorY, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
iMenuAnchorX = gOpenDoorMenu.sX + 9;
|
|
iMenuAnchorY = gOpenDoorMenu.sY + 8;
|
|
|
|
|
|
// Create mouse region over all area to facilitate clicking to end
|
|
MSYS_DefineRegion( &gMenuOverlayRegion, 0, 0 ,SCREEN_WIDTH, SCREEN_HEIGHT, MSYS_PRIORITY_HIGHEST-1,
|
|
CURSOR_NORMAL, MSYS_NO_CALLBACK, DoorMenuBackregionCallback );
|
|
// Add region
|
|
MSYS_AddRegion( &gMenuOverlayRegion);
|
|
|
|
|
|
iActionIcons[ USE_KEYRING_ICON ] = QuickCreateButton( iIconImages[ USE_KEYRING_IMAGES ], (INT16)(iMenuAnchorX + 20 ), (INT16)(iMenuAnchorY ),
|
|
BUTTON_NO_TOGGLE, MSYS_PRIORITY_HIGHEST - 1,
|
|
DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)BtnDoorMenuCallback );
|
|
if ( iActionIcons[ USE_KEYRING_ICON ] == -1 )
|
|
{
|
|
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, "Cannot create Interface button" );
|
|
return;
|
|
}
|
|
|
|
if (!(gTacticalStatus.uiFlags & TURNBASED) || !(gTacticalStatus.uiFlags & INCOMBAT ) )
|
|
{
|
|
swprintf( zDisp, pTacticalPopupButtonStrings[ USE_KEYRING_ICON ] );
|
|
}
|
|
else
|
|
{
|
|
swprintf( zDisp, L"%s ( %d )", pTacticalPopupButtonStrings[ USE_KEYRING_ICON ], APBPConstants[AP_UNLOCK_DOOR] );
|
|
}
|
|
SetButtonFastHelpText( iActionIcons[ USE_KEYRING_ICON ], zDisp );
|
|
|
|
if ( !EnoughPoints( gOpenDoorMenu.pSoldier, APBPConstants[AP_UNLOCK_DOOR], APBPConstants[BP_UNLOCK_DOOR], FALSE ) || fClosingDoor || AM_AN_EPC( gOpenDoorMenu.pSoldier ) )
|
|
{
|
|
DisableButton( iActionIcons[ USE_KEYRING_ICON ] );
|
|
}
|
|
|
|
// Greyout if no keys found...
|
|
if ( !SoldierHasKey( gOpenDoorMenu.pSoldier, ANYKEY ) )
|
|
{
|
|
DisableButton( iActionIcons[ USE_KEYRING_ICON ] );
|
|
}
|
|
|
|
|
|
iActionIcons[ USE_CROWBAR_ICON ] = QuickCreateButton( iIconImages[ CROWBAR_DOOR_IMAGES ], (INT16)(iMenuAnchorX + 40 ), (INT16)(iMenuAnchorY ),
|
|
BUTTON_NO_TOGGLE, MSYS_PRIORITY_HIGHEST - 1,
|
|
DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)BtnDoorMenuCallback );
|
|
if ( iActionIcons[ USE_CROWBAR_ICON ] == -1 )
|
|
{
|
|
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, "Cannot create Interface button" );
|
|
return;
|
|
}
|
|
|
|
if (!(gTacticalStatus.uiFlags & TURNBASED) || !(gTacticalStatus.uiFlags & INCOMBAT ) )
|
|
{
|
|
swprintf( zDisp, pTacticalPopupButtonStrings[ USE_CROWBAR_ICON ] );
|
|
}
|
|
else
|
|
{
|
|
swprintf( zDisp, L"%s ( %d )", pTacticalPopupButtonStrings[ USE_CROWBAR_ICON ], APBPConstants[AP_USE_CROWBAR] );
|
|
}
|
|
SetButtonFastHelpText( iActionIcons[ USE_CROWBAR_ICON ], zDisp );
|
|
|
|
// Greyout if no crowbar found...
|
|
if ( FindUsableCrowbar ( gOpenDoorMenu.pSoldier ) == NO_SLOT || fClosingDoor )
|
|
{
|
|
DisableButton( iActionIcons[ USE_CROWBAR_ICON ] );
|
|
}
|
|
|
|
if ( !EnoughPoints( gOpenDoorMenu.pSoldier, APBPConstants[AP_USE_CROWBAR], APBPConstants[BP_USE_CROWBAR], FALSE ) )
|
|
{
|
|
DisableButton( iActionIcons[ USE_CROWBAR_ICON ] );
|
|
}
|
|
|
|
iActionIcons[ LOCKPICK_DOOR_ICON ] = QuickCreateButton( iIconImages[ LOCKPICK_DOOR_IMAGES ], (INT16)(iMenuAnchorX + 40 ), (INT16)(iMenuAnchorY + 20 ),
|
|
BUTTON_NO_TOGGLE, MSYS_PRIORITY_HIGHEST - 1,
|
|
DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)BtnDoorMenuCallback );
|
|
if ( iActionIcons[ LOCKPICK_DOOR_ICON ] == -1 )
|
|
{
|
|
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, "Cannot create Interface button" );
|
|
return;
|
|
}
|
|
|
|
if (!(gTacticalStatus.uiFlags & TURNBASED) || !(gTacticalStatus.uiFlags & INCOMBAT ) )
|
|
{
|
|
swprintf( zDisp, pTacticalPopupButtonStrings[ LOCKPICK_DOOR_ICON ] );
|
|
}
|
|
else
|
|
{
|
|
swprintf( zDisp, L"%s ( %d )", pTacticalPopupButtonStrings[ LOCKPICK_DOOR_ICON ], GetAPsToPicklock( gOpenDoorMenu.pSoldier ) ); // SANDRO
|
|
}
|
|
SetButtonFastHelpText( iActionIcons[ LOCKPICK_DOOR_ICON ], zDisp );
|
|
|
|
if ( !EnoughPoints( gOpenDoorMenu.pSoldier, GetAPsToPicklock( gOpenDoorMenu.pSoldier ), APBPConstants[BP_PICKLOCK], FALSE ) || fClosingDoor || AM_AN_EPC( gOpenDoorMenu.pSoldier ) ) // SANDRO
|
|
{
|
|
DisableButton( iActionIcons[ LOCKPICK_DOOR_ICON ] );
|
|
}
|
|
|
|
|
|
// Grayout if no lockpick found....
|
|
if ( FindLocksmithKit( gOpenDoorMenu.pSoldier ) == NO_SLOT )
|
|
{
|
|
DisableButton( iActionIcons[ LOCKPICK_DOOR_ICON ] );
|
|
}
|
|
|
|
|
|
iActionIcons[ EXPLOSIVE_DOOR_ICON ] = QuickCreateButton( iIconImages[ EXPLOSIVE_DOOR_IMAGES ], (INT16)(iMenuAnchorX + 40 ), (INT16)(iMenuAnchorY + 40 ),
|
|
BUTTON_NO_TOGGLE, MSYS_PRIORITY_HIGHEST - 1,
|
|
DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)BtnDoorMenuCallback );
|
|
if ( iActionIcons[ EXPLOSIVE_DOOR_ICON ] == -1 )
|
|
{
|
|
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, "Cannot create Interface button" );
|
|
return;
|
|
}
|
|
|
|
if (!(gTacticalStatus.uiFlags & TURNBASED) || !(gTacticalStatus.uiFlags & INCOMBAT ) )
|
|
{
|
|
swprintf( zDisp, pTacticalPopupButtonStrings[ EXPLOSIVE_DOOR_ICON ] );
|
|
}
|
|
else
|
|
{
|
|
swprintf( zDisp, L"%s ( %d )", pTacticalPopupButtonStrings[ EXPLOSIVE_DOOR_ICON ], GetAPsToBombDoor( gOpenDoorMenu.pSoldier ) ); // SANDRO
|
|
}
|
|
SetButtonFastHelpText( iActionIcons[ EXPLOSIVE_DOOR_ICON ], zDisp );
|
|
|
|
if ( !EnoughPoints( gOpenDoorMenu.pSoldier, GetAPsToBombDoor( gOpenDoorMenu.pSoldier ), APBPConstants[BP_EXPLODE_DOOR], FALSE ) || fClosingDoor || AM_AN_EPC( gOpenDoorMenu.pSoldier ) ) // SANDRO
|
|
{
|
|
DisableButton( iActionIcons[ EXPLOSIVE_DOOR_ICON ] );
|
|
}
|
|
|
|
// Grayout if no lock explosive found....
|
|
// For no use bomb1 until we get a special item for this
|
|
if ( FindLockBomb ( gOpenDoorMenu.pSoldier ) == NO_SLOT )
|
|
{
|
|
DisableButton( iActionIcons[ EXPLOSIVE_DOOR_ICON ] );
|
|
}
|
|
|
|
|
|
iActionIcons[ OPEN_DOOR_ICON ] = QuickCreateButton( iIconImages[ OPEN_DOOR_IMAGES ], (INT16)(iMenuAnchorX ), (INT16)(iMenuAnchorY ),
|
|
BUTTON_NO_TOGGLE, MSYS_PRIORITY_HIGHEST - 1,
|
|
DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)BtnDoorMenuCallback );
|
|
if ( iActionIcons[ OPEN_DOOR_ICON ] == -1 )
|
|
{
|
|
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, "Cannot create Interface button" );
|
|
return;
|
|
}
|
|
|
|
if ( fClosingDoor )
|
|
{
|
|
if (!(gTacticalStatus.uiFlags & TURNBASED) || !(gTacticalStatus.uiFlags & INCOMBAT ) )
|
|
{
|
|
swprintf( zDisp, pTacticalPopupButtonStrings[ CANCEL_ICON + 1 ] );
|
|
}
|
|
else
|
|
{
|
|
swprintf( zDisp, L"%s ( %d )", pTacticalPopupButtonStrings[ CANCEL_ICON + 1 ], GetAPsToOpenDoor( gOpenDoorMenu.pSoldier ) ); // SANDRO
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!(gTacticalStatus.uiFlags & TURNBASED) || !(gTacticalStatus.uiFlags & INCOMBAT ) )
|
|
{
|
|
swprintf( zDisp, pTacticalPopupButtonStrings[ OPEN_DOOR_ICON ] );
|
|
}
|
|
else
|
|
{
|
|
swprintf( zDisp, L"%s ( %d )", pTacticalPopupButtonStrings[ OPEN_DOOR_ICON ], GetAPsToOpenDoor( gOpenDoorMenu.pSoldier ) ); // SANDRO
|
|
}
|
|
}
|
|
SetButtonFastHelpText( iActionIcons[ OPEN_DOOR_ICON ], zDisp );
|
|
|
|
if ( !EnoughPoints( gOpenDoorMenu.pSoldier, GetAPsToOpenDoor( gOpenDoorMenu.pSoldier ), APBPConstants[BP_OPEN_DOOR], FALSE ) ) // SANDRO
|
|
{
|
|
DisableButton( iActionIcons[ OPEN_DOOR_ICON ] );
|
|
}
|
|
|
|
|
|
// Create button based on what is in our hands at the moment!
|
|
iActionIcons[ EXAMINE_DOOR_ICON ] = QuickCreateButton( iIconImages[ EXAMINE_DOOR_IMAGES ], (INT16)(iMenuAnchorX ), (INT16)(iMenuAnchorY + 20 ),
|
|
BUTTON_NO_TOGGLE, MSYS_PRIORITY_HIGHEST - 1,
|
|
DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)BtnDoorMenuCallback );
|
|
if ( iActionIcons[ EXAMINE_DOOR_ICON ] == -1 )
|
|
{
|
|
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, "Cannot create Interface button" );
|
|
return;
|
|
}
|
|
|
|
if (!(gTacticalStatus.uiFlags & TURNBASED) || !(gTacticalStatus.uiFlags & INCOMBAT ) )
|
|
{
|
|
swprintf( zDisp, pTacticalPopupButtonStrings[ EXAMINE_DOOR_ICON ] );
|
|
}
|
|
else
|
|
{
|
|
swprintf( zDisp, L"%s ( %d )", pTacticalPopupButtonStrings[ EXAMINE_DOOR_ICON ], APBPConstants[AP_EXAMINE_DOOR] );
|
|
}
|
|
SetButtonFastHelpText( iActionIcons[ EXAMINE_DOOR_ICON ], zDisp );
|
|
|
|
if ( !EnoughPoints( gOpenDoorMenu.pSoldier, APBPConstants[AP_EXAMINE_DOOR], APBPConstants[BP_EXAMINE_DOOR], FALSE ) || fClosingDoor || AM_AN_EPC( gOpenDoorMenu.pSoldier ) )
|
|
{
|
|
DisableButton( iActionIcons[ EXAMINE_DOOR_ICON ] );
|
|
}
|
|
|
|
iActionIcons[ BOOT_DOOR_ICON ] = QuickCreateButton( iIconImages[ BOOT_DOOR_IMAGES ], (INT16)(iMenuAnchorX ), (INT16)(iMenuAnchorY + 40 ),
|
|
BUTTON_NO_TOGGLE, MSYS_PRIORITY_HIGHEST - 1,
|
|
DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)BtnDoorMenuCallback );
|
|
if ( iActionIcons[ BOOT_DOOR_ICON ] == -1 )
|
|
{
|
|
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, "Cannot create Interface button" );
|
|
return;
|
|
}
|
|
|
|
if (!(gTacticalStatus.uiFlags & TURNBASED) || !(gTacticalStatus.uiFlags & INCOMBAT ) )
|
|
{
|
|
swprintf( zDisp, pTacticalPopupButtonStrings[ BOOT_DOOR_ICON ] );
|
|
}
|
|
else
|
|
{
|
|
swprintf( zDisp, L"%s ( %d )", pTacticalPopupButtonStrings[ BOOT_DOOR_ICON ], APBPConstants[AP_BOOT_DOOR] );
|
|
}
|
|
SetButtonFastHelpText( iActionIcons[ BOOT_DOOR_ICON ], zDisp );
|
|
|
|
if ( !EnoughPoints( gOpenDoorMenu.pSoldier, APBPConstants[AP_BOOT_DOOR], APBPConstants[BP_BOOT_DOOR], FALSE ) || fClosingDoor || AM_AN_EPC( gOpenDoorMenu.pSoldier ) )
|
|
{
|
|
DisableButton( iActionIcons[ BOOT_DOOR_ICON ] );
|
|
}
|
|
|
|
|
|
iActionIcons[ UNTRAP_DOOR_ICON ] = QuickCreateButton( iIconImages[ UNTRAP_DOOR_ICON ], (INT16)(iMenuAnchorX + 20 ), (INT16)(iMenuAnchorY + 40 ),
|
|
BUTTON_NO_TOGGLE, MSYS_PRIORITY_HIGHEST - 1,
|
|
DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)BtnDoorMenuCallback );
|
|
if ( iActionIcons[ UNTRAP_DOOR_ICON ] == -1 )
|
|
{
|
|
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, "Cannot create Interface button" );
|
|
return;
|
|
}
|
|
|
|
if (!(gTacticalStatus.uiFlags & TURNBASED) || !(gTacticalStatus.uiFlags & INCOMBAT ) )
|
|
{
|
|
swprintf( zDisp, pTacticalPopupButtonStrings[ UNTRAP_DOOR_ICON ] );
|
|
}
|
|
else
|
|
{
|
|
swprintf( zDisp, L"%s ( %d )", pTacticalPopupButtonStrings[ UNTRAP_DOOR_ICON ], GetAPsToUntrapDoor( gOpenDoorMenu.pSoldier ) ); // SANDRO
|
|
}
|
|
SetButtonFastHelpText( iActionIcons[ UNTRAP_DOOR_ICON ], zDisp );
|
|
|
|
if ( !EnoughPoints( gOpenDoorMenu.pSoldier, GetAPsToUntrapDoor( gOpenDoorMenu.pSoldier ), APBPConstants[BP_UNTRAP_DOOR], FALSE ) || fClosingDoor || AM_AN_EPC( gOpenDoorMenu.pSoldier ) ) // SANDRO
|
|
{
|
|
DisableButton( iActionIcons[ UNTRAP_DOOR_ICON ] );
|
|
}
|
|
|
|
iActionIcons[ CANCEL_ICON ] = QuickCreateButton( iIconImages[ CANCEL_IMAGES ], (INT16)(iMenuAnchorX + 20 ), (INT16)(iMenuAnchorY + 20 ),
|
|
BUTTON_NO_TOGGLE, MSYS_PRIORITY_HIGHEST - 1,
|
|
DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)BtnDoorMenuCallback );
|
|
if ( iActionIcons[ CANCEL_ICON ] == -1 )
|
|
{
|
|
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, "Cannot create Interface button" );
|
|
return;
|
|
}
|
|
SetButtonFastHelpText( iActionIcons[ CANCEL_ICON ], pTacticalPopupButtonStrings[ CANCEL_ICON ] );
|
|
|
|
//LockTacticalInterface( );
|
|
|
|
gfInOpenDoorMenu = TRUE;
|
|
|
|
// Ignore scrolling
|
|
gfIgnoreScrolling = TRUE;
|
|
}
|
|
|
|
|
|
void PopDownOpenDoorMenu( )
|
|
{
|
|
if ( gfInOpenDoorMenu )
|
|
{
|
|
UnLockPauseState();
|
|
UnPauseGame();
|
|
// UnPause timers as well....
|
|
PauseTime( FALSE );
|
|
|
|
RemoveButton( iActionIcons[ USE_KEYRING_ICON ] );
|
|
RemoveButton( iActionIcons[ USE_CROWBAR_ICON ] );
|
|
RemoveButton( iActionIcons[ LOCKPICK_DOOR_ICON ] );
|
|
RemoveButton( iActionIcons[ EXPLOSIVE_DOOR_ICON ] );
|
|
RemoveButton( iActionIcons[ OPEN_DOOR_ICON ] );
|
|
RemoveButton( iActionIcons[ EXAMINE_DOOR_ICON ] );
|
|
RemoveButton( iActionIcons[ BOOT_DOOR_ICON ] );
|
|
RemoveButton( iActionIcons[ UNTRAP_DOOR_ICON ] );
|
|
RemoveButton( iActionIcons[ CANCEL_ICON ] );
|
|
|
|
// Turn off Ignore scrolling
|
|
gfIgnoreScrolling = FALSE;
|
|
|
|
// Rerender world
|
|
SetRenderFlags( RENDER_FLAG_FULL );
|
|
|
|
fInterfacePanelDirty = DIRTYLEVEL2;
|
|
|
|
//UnLockTacticalInterface( );
|
|
MSYS_RemoveRegion( &gMenuOverlayRegion);
|
|
|
|
}
|
|
|
|
gfInOpenDoorMenu = FALSE;
|
|
|
|
}
|
|
|
|
void RenderOpenDoorMenu( )
|
|
{
|
|
if ( gfInOpenDoorMenu )
|
|
{
|
|
BltVideoObjectFromIndex( FRAME_BUFFER, guiBUTTONBORDER, 0, gOpenDoorMenu.sX, gOpenDoorMenu.sY, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
|
|
// Mark buttons dirty!
|
|
MarkAButtonDirty( iActionIcons[ USE_KEYRING_ICON ] );
|
|
MarkAButtonDirty( iActionIcons[ USE_CROWBAR_ICON ] );
|
|
MarkAButtonDirty( iActionIcons[ LOCKPICK_DOOR_ICON ] );
|
|
MarkAButtonDirty( iActionIcons[ EXPLOSIVE_DOOR_ICON ] );
|
|
MarkAButtonDirty( iActionIcons[ OPEN_DOOR_ICON ] );
|
|
MarkAButtonDirty( iActionIcons[ EXAMINE_DOOR_ICON ] );
|
|
MarkAButtonDirty( iActionIcons[ BOOT_DOOR_ICON ] );
|
|
MarkAButtonDirty( iActionIcons[ UNTRAP_DOOR_ICON ] );
|
|
MarkAButtonDirty( iActionIcons[ CANCEL_ICON ] );
|
|
|
|
RenderButtons( );
|
|
|
|
// if game is paused, then render paused game text
|
|
RenderPausedGameBox( );
|
|
|
|
InvalidateRegion( gOpenDoorMenu.sX, gOpenDoorMenu.sY, gOpenDoorMenu.sX + BUTTON_PANEL_WIDTH, gOpenDoorMenu.sY + BUTTON_PANEL_HEIGHT );
|
|
|
|
}
|
|
}
|
|
|
|
void CancelOpenDoorMenu( )
|
|
{
|
|
// Signal end of event
|
|
gOpenDoorMenu.fMenuHandled = 2;
|
|
}
|
|
|
|
void BtnDoorMenuCallback(GUI_BUTTON *btn,INT32 reason)
|
|
{
|
|
INT32 uiBtnID;
|
|
|
|
if ( reason & MSYS_CALLBACK_REASON_LBUTTON_UP )
|
|
{
|
|
btn->uiFlags |= BUTTON_CLICKED_ON;
|
|
|
|
uiBtnID = btn->IDNum;
|
|
|
|
// Popdown menu
|
|
gOpenDoorMenu.fMenuHandled = TRUE;
|
|
|
|
if ( uiBtnID == iActionIcons[ CANCEL_ICON ] )
|
|
{
|
|
// OK, set cancle code!
|
|
gOpenDoorMenu.fMenuHandled = 2;
|
|
#ifdef JA2UB
|
|
//Handle someone trying to open the door in the tunnel gate`
|
|
HandlePlayerSayingQuoteWhenFailingToOpenGateInTunnel( gOpenDoorMenu.pSoldier, FALSE ); //Ja25 UB
|
|
#endif
|
|
}
|
|
|
|
// Switch on command....
|
|
if ( uiBtnID == iActionIcons[ OPEN_DOOR_ICON ] )
|
|
{
|
|
#ifdef JA2UB
|
|
//Handle someone trying to open the door in the tunnel gate`
|
|
if( HandlePlayerSayingQuoteWhenFailingToOpenGateInTunnel( gOpenDoorMenu.pSoldier, TRUE ) ) //Ja25 UB
|
|
{
|
|
// OK, set cancle code!
|
|
gOpenDoorMenu.fMenuHandled = 2;
|
|
}
|
|
else
|
|
{
|
|
// Open door normally...
|
|
// Check APs
|
|
if ( EnoughPoints( gOpenDoorMenu.pSoldier, APBPConstants[AP_OPEN_DOOR], APBPConstants[BP_OPEN_DOOR], FALSE ) )
|
|
{
|
|
// Set UI
|
|
SetUIBusy( (UINT8)gOpenDoorMenu.pSoldier->ubID );
|
|
|
|
if ( gOpenDoorMenu.fClosingDoor )
|
|
{
|
|
gOpenDoorMenu.pSoldier->ChangeSoldierState( GetAnimStateForInteraction( gOpenDoorMenu.pSoldier, TRUE, CLOSE_DOOR ), 0 , FALSE );
|
|
}
|
|
else
|
|
{
|
|
InteractWithClosedDoor( gOpenDoorMenu.pSoldier, HANDLE_DOOR_OPEN );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// OK, set cancel code!
|
|
gOpenDoorMenu.fMenuHandled = 2;
|
|
}
|
|
}
|
|
#else
|
|
// Open door normally...
|
|
// Check APs
|
|
// SANDRO - changed APs for opening dorrs calc
|
|
if ( EnoughPoints( gOpenDoorMenu.pSoldier, GetAPsToOpenDoor( gOpenDoorMenu.pSoldier ), APBPConstants[BP_OPEN_DOOR], FALSE ) )
|
|
{
|
|
// Set UI
|
|
SetUIBusy( (UINT8)gOpenDoorMenu.pSoldier->ubID );
|
|
|
|
if ( gOpenDoorMenu.fClosingDoor )
|
|
{
|
|
gOpenDoorMenu.pSoldier->ChangeSoldierState( GetAnimStateForInteraction( gOpenDoorMenu.pSoldier, TRUE, CLOSE_DOOR ), 0 , FALSE );
|
|
}
|
|
else
|
|
{
|
|
InteractWithClosedDoor( gOpenDoorMenu.pSoldier, HANDLE_DOOR_OPEN );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// OK, set cancel code!
|
|
gOpenDoorMenu.fMenuHandled = 2;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
if ( uiBtnID == iActionIcons[ BOOT_DOOR_ICON ] )
|
|
{
|
|
// Boot door
|
|
if ( EnoughPoints( gOpenDoorMenu.pSoldier, APBPConstants[AP_BOOT_DOOR], APBPConstants[BP_BOOT_DOOR], FALSE ) )
|
|
{
|
|
// Set UI
|
|
SetUIBusy( (UINT8)gOpenDoorMenu.pSoldier->ubID );
|
|
|
|
InteractWithClosedDoor( gOpenDoorMenu.pSoldier, HANDLE_DOOR_FORCE );
|
|
}
|
|
else
|
|
{
|
|
// OK, set cancle code!
|
|
gOpenDoorMenu.fMenuHandled = 2;
|
|
}
|
|
}
|
|
|
|
if ( uiBtnID == iActionIcons[ USE_KEYRING_ICON ] )
|
|
{
|
|
// Unlock door
|
|
if ( EnoughPoints( gOpenDoorMenu.pSoldier, APBPConstants[AP_UNLOCK_DOOR], APBPConstants[BP_UNLOCK_DOOR], FALSE ) )
|
|
{
|
|
// Set UI
|
|
SetUIBusy( (UINT8)gOpenDoorMenu.pSoldier->ubID );
|
|
|
|
InteractWithClosedDoor( gOpenDoorMenu.pSoldier, HANDLE_DOOR_UNLOCK );
|
|
}
|
|
else
|
|
{
|
|
// OK, set cancle code!
|
|
gOpenDoorMenu.fMenuHandled = 2;
|
|
}
|
|
}
|
|
|
|
if ( uiBtnID == iActionIcons[ LOCKPICK_DOOR_ICON ] )
|
|
{
|
|
// Lockpick
|
|
if ( EnoughPoints( gOpenDoorMenu.pSoldier, GetAPsToPicklock( gOpenDoorMenu.pSoldier ), APBPConstants[BP_PICKLOCK], FALSE ) ) // SANDRO
|
|
{
|
|
// Set UI
|
|
SetUIBusy( (UINT8)gOpenDoorMenu.pSoldier->ubID );
|
|
|
|
InteractWithClosedDoor( gOpenDoorMenu.pSoldier, HANDLE_DOOR_LOCKPICK );
|
|
}
|
|
else
|
|
{
|
|
// OK, set cancle code!
|
|
gOpenDoorMenu.fMenuHandled = 2;
|
|
}
|
|
}
|
|
|
|
if ( uiBtnID == iActionIcons[ EXAMINE_DOOR_ICON ] )
|
|
{
|
|
// Lockpick
|
|
if ( EnoughPoints( gOpenDoorMenu.pSoldier, APBPConstants[AP_EXAMINE_DOOR], APBPConstants[BP_EXAMINE_DOOR], FALSE ) )
|
|
{
|
|
// Set UI
|
|
SetUIBusy( (UINT8)gOpenDoorMenu.pSoldier->ubID );
|
|
|
|
InteractWithClosedDoor( gOpenDoorMenu.pSoldier, HANDLE_DOOR_EXAMINE );
|
|
}
|
|
else
|
|
{
|
|
// OK, set cancle code!
|
|
gOpenDoorMenu.fMenuHandled = 2;
|
|
}
|
|
}
|
|
|
|
if ( uiBtnID == iActionIcons[ EXPLOSIVE_DOOR_ICON ] )
|
|
{
|
|
#ifdef JA2UB
|
|
//Handle someone trying to open the door in the tunnel gate`
|
|
if( HandlePlayerSayingQuoteWhenFailingToOpenGateInTunnel( gOpenDoorMenu.pSoldier, TRUE ) ) //Ja25 UB
|
|
{
|
|
// OK, set cancle code!
|
|
gOpenDoorMenu.fMenuHandled = 2;
|
|
}
|
|
else
|
|
{
|
|
// Explode
|
|
if ( EnoughPoints( gOpenDoorMenu.pSoldier, APBPConstants[AP_EXPLODE_DOOR], APBPConstants[BP_EXPLODE_DOOR], FALSE ) )
|
|
{
|
|
// Set UI
|
|
SetUIBusy( (UINT8)gOpenDoorMenu.pSoldier->ubID );
|
|
|
|
InteractWithClosedDoor( gOpenDoorMenu.pSoldier, HANDLE_DOOR_EXPLODE );
|
|
}
|
|
else
|
|
{
|
|
// OK, set cancle code!
|
|
gOpenDoorMenu.fMenuHandled = 2;
|
|
}
|
|
}
|
|
#else
|
|
// Explode
|
|
if ( EnoughPoints( gOpenDoorMenu.pSoldier, GetAPsToBombDoor( gOpenDoorMenu.pSoldier ), APBPConstants[BP_EXPLODE_DOOR], FALSE ) ) // SANDRO
|
|
{
|
|
// Set UI
|
|
SetUIBusy( (UINT8)gOpenDoorMenu.pSoldier->ubID );
|
|
|
|
InteractWithClosedDoor( gOpenDoorMenu.pSoldier, HANDLE_DOOR_EXPLODE );
|
|
}
|
|
else
|
|
{
|
|
// OK, set cancle code!
|
|
gOpenDoorMenu.fMenuHandled = 2;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
if ( uiBtnID == iActionIcons[ UNTRAP_DOOR_ICON ] )
|
|
{
|
|
// Explode
|
|
if ( EnoughPoints( gOpenDoorMenu.pSoldier, GetAPsToUntrapDoor( gOpenDoorMenu.pSoldier ), APBPConstants[BP_UNTRAP_DOOR], FALSE ) ) // SANDRO
|
|
{
|
|
// Set UI
|
|
SetUIBusy( (UINT8)gOpenDoorMenu.pSoldier->ubID );
|
|
|
|
InteractWithClosedDoor( gOpenDoorMenu.pSoldier, HANDLE_DOOR_UNTRAP );
|
|
}
|
|
else
|
|
{
|
|
// OK, set cancle code!
|
|
gOpenDoorMenu.fMenuHandled = 2;
|
|
}
|
|
}
|
|
|
|
if ( uiBtnID == iActionIcons[ USE_CROWBAR_ICON ] )
|
|
{
|
|
#ifdef JA2UB
|
|
//Handle someone trying to open the door in the tunnel gate`
|
|
if( HandlePlayerSayingQuoteWhenFailingToOpenGateInTunnel( gOpenDoorMenu.pSoldier, TRUE ) ) //JA25 UB
|
|
{
|
|
// OK, set cancle code!
|
|
gOpenDoorMenu.fMenuHandled = 2;
|
|
}
|
|
else
|
|
{
|
|
// Explode
|
|
if ( EnoughPoints( gOpenDoorMenu.pSoldier, APBPConstants[AP_USE_CROWBAR], APBPConstants[BP_USE_CROWBAR], FALSE ) )
|
|
{
|
|
// Set UI
|
|
SetUIBusy( (UINT8)gOpenDoorMenu.pSoldier->ubID );
|
|
|
|
InteractWithClosedDoor( gOpenDoorMenu.pSoldier, HANDLE_DOOR_CROWBAR );
|
|
}
|
|
else
|
|
{
|
|
// OK, set cancle code!
|
|
gOpenDoorMenu.fMenuHandled = 2;
|
|
}
|
|
}
|
|
#else
|
|
// Explode
|
|
if ( EnoughPoints( gOpenDoorMenu.pSoldier, APBPConstants[AP_USE_CROWBAR], APBPConstants[BP_USE_CROWBAR], FALSE ) )
|
|
{
|
|
// Set UI
|
|
SetUIBusy( (UINT8)gOpenDoorMenu.pSoldier->ubID );
|
|
|
|
InteractWithClosedDoor( gOpenDoorMenu.pSoldier, HANDLE_DOOR_CROWBAR );
|
|
}
|
|
else
|
|
{
|
|
// OK, set cancle code!
|
|
gOpenDoorMenu.fMenuHandled = 2;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
HandleOpenDoorMenu( );
|
|
|
|
}
|
|
}
|
|
|
|
|
|
BOOLEAN HandleOpenDoorMenu( )
|
|
{
|
|
if ( gOpenDoorMenu.fMenuHandled )
|
|
{
|
|
PopDownOpenDoorMenu( );
|
|
return( gOpenDoorMenu.fMenuHandled );
|
|
}
|
|
|
|
return( FALSE );
|
|
}
|
|
|
|
|
|
void RenderUIMessage( VIDEO_OVERLAY *pBlitter )
|
|
{
|
|
// Shade area first...
|
|
ShadowVideoSurfaceRect( pBlitter->uiDestBuff, pBlitter->sX, pBlitter->sY, pBlitter->sX + gusUIMessageWidth - 2, pBlitter->sY + gusUIMessageHeight - 2 );
|
|
|
|
RenderMercPopUpBoxFromIndex( iUIMessageBox, pBlitter->sX, pBlitter->sY, pBlitter->uiDestBuff );
|
|
|
|
InvalidateRegion( pBlitter->sX, pBlitter->sY, pBlitter->sX + gusUIMessageWidth, pBlitter->sY + gusUIMessageHeight );
|
|
}
|
|
|
|
|
|
void InternalBeginUIMessage( BOOLEAN fUseSkullIcon, STR16 pFontString, ... )
|
|
{
|
|
va_list argptr;
|
|
VIDEO_OVERLAY_DESC VideoOverlayDesc;
|
|
CHAR16 MsgString[512];
|
|
|
|
|
|
va_start(argptr, pFontString); // Set up variable argument pointer
|
|
vswprintf(MsgString, pFontString, argptr); // process gprintf string (get output str)
|
|
va_end(argptr);
|
|
|
|
guiUIMessageTime = GetJA2Clock( );
|
|
guiUIMessageTimeDelay = CalcUIMessageDuration(MsgString);
|
|
|
|
// Override it!
|
|
OverrideMercPopupBox( &gpUIMessageOverrideMercBox );
|
|
|
|
//SetPrepareMercPopupFlags( MERC_POPUP_PREPARE_FLAGS_TRANS_BACK | MERC_POPUP_PREPARE_FLAGS_MARGINS );
|
|
|
|
if ( fUseSkullIcon )
|
|
{
|
|
SetPrepareMercPopupFlags( MERC_POPUP_PREPARE_FLAGS_MARGINS | MERC_POPUP_PREPARE_FLAGS_SKULLICON );
|
|
}
|
|
else
|
|
{
|
|
SetPrepareMercPopupFlags( MERC_POPUP_PREPARE_FLAGS_MARGINS | MERC_POPUP_PREPARE_FLAGS_STOPICON );
|
|
}
|
|
|
|
// Prepare text box
|
|
iUIMessageBox = PrepareMercPopupBox( iUIMessageBox ,BASIC_MERC_POPUP_BACKGROUND, BASIC_MERC_POPUP_BORDER, MsgString, 200, 10, 0, 0, &gusUIMessageWidth, &gusUIMessageHeight );
|
|
|
|
// Set it back!
|
|
ResetOverrideMercPopupBox( );
|
|
|
|
if ( giUIMessageOverlay != -1 )
|
|
{
|
|
RemoveVideoOverlay( giUIMessageOverlay );
|
|
|
|
giUIMessageOverlay = -1;
|
|
}
|
|
|
|
if ( giUIMessageOverlay == -1 )
|
|
{
|
|
memset( &VideoOverlayDesc, 0, sizeof( VideoOverlayDesc ) );
|
|
|
|
// Set Overlay
|
|
VideoOverlayDesc.sLeft = ( SCREEN_WIDTH - gusUIMessageWidth ) / 2;
|
|
VideoOverlayDesc.sTop = 150;
|
|
VideoOverlayDesc.sRight = VideoOverlayDesc.sLeft + gusUIMessageWidth;
|
|
VideoOverlayDesc.sBottom = VideoOverlayDesc.sTop + gusUIMessageHeight;
|
|
VideoOverlayDesc.sX = VideoOverlayDesc.sLeft;
|
|
VideoOverlayDesc.sY = VideoOverlayDesc.sTop;
|
|
VideoOverlayDesc.BltCallback = RenderUIMessage;
|
|
|
|
giUIMessageOverlay = RegisterVideoOverlay( 0, &VideoOverlayDesc );
|
|
}
|
|
|
|
gfUseSkullIconMessage = fUseSkullIcon;
|
|
}
|
|
|
|
void BeginUIMessage( STR16 pFontString, ... )
|
|
{
|
|
va_list argptr;
|
|
CHAR16 MsgString[512];
|
|
|
|
va_start(argptr, pFontString); // Set up variable argument pointer
|
|
vswprintf(MsgString, pFontString, argptr); // process gprintf string (get output str)
|
|
va_end(argptr);
|
|
|
|
InternalBeginUIMessage( FALSE, MsgString );
|
|
}
|
|
|
|
|
|
void BeginMapUIMessage( UINT8 ubPosition, STR16 pFontString, ... )
|
|
{
|
|
va_list argptr;
|
|
VIDEO_OVERLAY_DESC VideoOverlayDesc;
|
|
CHAR16 MsgString[512];
|
|
|
|
memset( &VideoOverlayDesc, 0, sizeof( VideoOverlayDesc ) );
|
|
|
|
va_start(argptr, pFontString); // Set up variable argument pointer
|
|
vswprintf(MsgString, pFontString, argptr); // process gprintf string (get output str)
|
|
va_end(argptr);
|
|
|
|
guiUIMessageTime = GetJA2Clock( );
|
|
guiUIMessageTimeDelay = CalcUIMessageDuration(MsgString);
|
|
|
|
// Override it!
|
|
OverrideMercPopupBox( &gpUIMessageOverrideMercBox );
|
|
|
|
SetPrepareMercPopupFlags( MERC_POPUP_PREPARE_FLAGS_TRANS_BACK | MERC_POPUP_PREPARE_FLAGS_MARGINS );
|
|
|
|
// Prepare text box
|
|
iUIMessageBox = PrepareMercPopupBox( iUIMessageBox ,BASIC_MERC_POPUP_BACKGROUND, BASIC_MERC_POPUP_BORDER, MsgString, 200, 10, 0, 0, &gusUIMessageWidth, &gusUIMessageHeight );
|
|
|
|
// Set it back!
|
|
ResetOverrideMercPopupBox( );
|
|
|
|
if ( giUIMessageOverlay == -1 )
|
|
{
|
|
// WDS - bug fix: VideoOverlayDesc must be initialized! - 07/16/2007
|
|
memset( &VideoOverlayDesc, 0, sizeof( VIDEO_OVERLAY_DESC ) );
|
|
// Set Overlay
|
|
VideoOverlayDesc.sLeft = 20 + MAP_VIEW_START_X + ( MAP_VIEW_WIDTH - gusUIMessageWidth ) / 2;
|
|
|
|
VideoOverlayDesc.sTop = MAP_VIEW_START_Y + ( MAP_VIEW_HEIGHT - gusUIMessageHeight ) / 2;
|
|
|
|
if( ubPosition == MSG_MAP_UI_POSITION_UPPER )
|
|
{
|
|
VideoOverlayDesc.sTop -= 100;
|
|
}
|
|
else if ( ubPosition == MSG_MAP_UI_POSITION_LOWER )
|
|
{
|
|
VideoOverlayDesc.sTop += 100;
|
|
}
|
|
|
|
VideoOverlayDesc.sRight = VideoOverlayDesc.sLeft + gusUIMessageWidth;
|
|
VideoOverlayDesc.sBottom = VideoOverlayDesc.sTop + gusUIMessageHeight;
|
|
VideoOverlayDesc.sX = VideoOverlayDesc.sLeft;
|
|
VideoOverlayDesc.sY = VideoOverlayDesc.sTop;
|
|
VideoOverlayDesc.BltCallback = RenderUIMessage;
|
|
|
|
giUIMessageOverlay = RegisterVideoOverlay( 0, &VideoOverlayDesc );
|
|
}
|
|
|
|
}
|
|
|
|
void EndUIMessage( )
|
|
{
|
|
UINT32 uiClock = GetJA2Clock();
|
|
|
|
if ( giUIMessageOverlay != -1 )
|
|
{
|
|
if ( gfUseSkullIconMessage )
|
|
{
|
|
if ( ( uiClock - guiUIMessageTime ) < 300 )
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
// DebugMsg( TOPIC_JA2, DBG_LEVEL_0, String( "Removing Overlay message") );
|
|
|
|
RemoveVideoOverlay( giUIMessageOverlay );
|
|
|
|
// Remove popup as well....
|
|
if ( iUIMessageBox != -1 )
|
|
{
|
|
RemoveMercPopupBoxFromIndex( iUIMessageBox );
|
|
iUIMessageBox = -1;
|
|
}
|
|
|
|
giUIMessageOverlay = -1;
|
|
|
|
}
|
|
//iUIMessageBox = -1;
|
|
}
|
|
|
|
#define PLAYER_TEAM_TIMER_INTTERUPT_GRACE ( 15000 / PLAYER_TEAM_TIMER_SEC_PER_TICKS )
|
|
#define PLAYER_TEAM_TIMER_GRACE_PERIOD 1000
|
|
//#define PLAYER_TEAM_TIMER_SEC_PER_TICKS 100
|
|
int PLAYER_TEAM_TIMER_SEC_PER_TICKS = 100;//hayden
|
|
#define PLAYER_TEAM_TIMER_TICKS_PER_OK_MERC ( 15000 / PLAYER_TEAM_TIMER_SEC_PER_TICKS )
|
|
#define PLAYER_TEAM_TIMER_TICKS_PER_NOTOK_MERC ( 5000 / PLAYER_TEAM_TIMER_SEC_PER_TICKS )
|
|
#define PLAYER_TEAM_TIMER_TICKS_FROM_END_TO_START_BEEP ( (5000 / PLAYER_TEAM_TIMER_SEC_PER_TICKS)*1.15 )
|
|
#define PLAYER_TEAM_TIMER_TIME_BETWEEN_BEEPS ( 500 )
|
|
#define PLAYER_TEAM_TIMER_TICKS_PER_ENEMY ( 2000 / PLAYER_TEAM_TIMER_SEC_PER_TICKS )
|
|
|
|
|
|
BOOLEAN AddTopMessage( UINT8 ubType, STR16 pzString )
|
|
{
|
|
UINT32 cnt;
|
|
BOOLEAN fFound = FALSE;
|
|
|
|
// Set time of last update
|
|
gTopMessage.uiTimeOfLastUpdate = GetJA2Clock( );
|
|
|
|
// Set flag to animate down...
|
|
//gTopMessage.bAnimate = -1;
|
|
//gTopMessage.bYPos = 2;
|
|
|
|
gTopMessage.bAnimate = 0;
|
|
gTopMessage.bYPos = 20;
|
|
gTopMessage.fCreated = TRUE;
|
|
|
|
fFound = TRUE;
|
|
cnt = 0;
|
|
|
|
// WANNE: Disabled AI count on turnbar, because it shows different count on clients
|
|
/*
|
|
if(is_networked && gTacticalStatus.ubCurrentTeam == 1 && ubType == COMPUTER_TURN_MESSAGE){
|
|
//add ai count to turn bar - haydent
|
|
swprintf( pzString, MPClientMessage[80], NumEnemyInSector());
|
|
}
|
|
*/
|
|
|
|
if ( fFound )
|
|
{
|
|
gTopMessage.bCurrentMessage = (INT8)cnt;
|
|
|
|
gTacticalStatus.ubTopMessageType = ubType;
|
|
gTacticalStatus.fInTopMessage = TRUE;
|
|
|
|
// Copy string
|
|
wcsncpy( gTacticalStatus.zTopMessageString, pzString, 19 );
|
|
|
|
CreateTopMessage( gTopMessage.uiSurface, ubType, pzString );
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
return( FALSE );
|
|
}
|
|
|
|
void CreateTopMessage( UINT32 uiSurface, UINT8 ubType, STR16 psString )
|
|
{
|
|
UINT32 uiBAR, uiPLAYERBAR = 0, uiINTBAR = 0;
|
|
VOBJECT_DESC VObjectDesc;
|
|
INT16 sX, sY;
|
|
INT32 cnt2;
|
|
INT16 sBarX = 0;
|
|
UINT32 uiBarToUseInUpDate=0;
|
|
BOOLEAN fDoLimitBar = FALSE;
|
|
FLOAT dNumStepsPerEnemy, dLength, dCurSize;
|
|
INT16 iProgBarLength;
|
|
STR fn;
|
|
|
|
memset( &VObjectDesc, 0, sizeof( VObjectDesc ) );
|
|
VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE;
|
|
|
|
if (iResolution >= _640x480 && iResolution < _800x600)
|
|
{
|
|
iProgBarLength = 640 - 13;
|
|
if (gGameExternalOptions.fSmallSizeProgressbar)
|
|
fn = "INTERFACE\\rect_Thin.sti";
|
|
else
|
|
fn = "INTERFACE\\rect.sti";
|
|
}
|
|
else if (iResolution < _1024x768)
|
|
{
|
|
iProgBarLength = 800 - 13;
|
|
if (gGameExternalOptions.fSmallSizeProgressbar)
|
|
fn = "INTERFACE\\rect_800x600Thin.sti";
|
|
else
|
|
fn = "INTERFACE\\rect_800x600.sti";
|
|
}
|
|
else
|
|
{
|
|
iProgBarLength = 1024 - 13;
|
|
if (gGameExternalOptions.fSmallSizeProgressbar)
|
|
fn = "INTERFACE\\rect_1024x768Thin.sti";
|
|
else
|
|
fn = "INTERFACE\\rect_1024x768.sti";
|
|
}
|
|
|
|
FilenameForBPP(fn, VObjectDesc.ImageFile);
|
|
|
|
if( !AddVideoObject( &VObjectDesc, &uiBAR ) )
|
|
{
|
|
sprintf(fn, "Missing %s", fn);
|
|
AssertMsg(0, fn );
|
|
}
|
|
|
|
if (iResolution >= _640x480 && iResolution < _800x600)
|
|
{
|
|
if (gGameExternalOptions.fSmallSizeProgressbar)
|
|
fn = "INTERFACE\\timebargreen_Thin.sti";
|
|
else
|
|
fn = "INTERFACE\\timebargreen.sti";
|
|
}
|
|
else if (iResolution < _1024x768)
|
|
{
|
|
if (gGameExternalOptions.fSmallSizeProgressbar)
|
|
fn = "INTERFACE\\timebargreen_800x600Thin.sti";
|
|
else
|
|
fn = "INTERFACE\\timebargreen_800x600.sti";
|
|
}
|
|
else
|
|
{
|
|
if (gGameExternalOptions.fSmallSizeProgressbar)
|
|
fn = "INTERFACE\\timebargreen_1024x768Thin.sti";
|
|
else
|
|
fn = "INTERFACE\\timebargreen_1024x768.sti";
|
|
}
|
|
|
|
FilenameForBPP(fn, VObjectDesc.ImageFile);
|
|
if( !AddVideoObject( &VObjectDesc, &uiPLAYERBAR ) )
|
|
{
|
|
sprintf(fn, "Missing %s", fn);
|
|
AssertMsg(0, fn );
|
|
}
|
|
|
|
if (iResolution >= _640x480 && iResolution < _800x600)
|
|
{
|
|
if (gGameExternalOptions.fSmallSizeProgressbar)
|
|
fn = "INTERFACE\\timebaryellow_Thin.sti";
|
|
else
|
|
fn = "INTERFACE\\timebaryellow.sti";
|
|
}
|
|
else if (iResolution < _1024x768)
|
|
{
|
|
if (gGameExternalOptions.fSmallSizeProgressbar)
|
|
fn = "INTERFACE\\timebaryellow_800x600Thin.sti";
|
|
else
|
|
fn = "INTERFACE\\timebaryellow_800x600.sti";
|
|
}
|
|
else
|
|
{
|
|
if (gGameExternalOptions.fSmallSizeProgressbar)
|
|
fn = "INTERFACE\\timebaryellow_1024x768Thin.sti";
|
|
else
|
|
fn = "INTERFACE\\timebaryellow_1024x768.sti";
|
|
}
|
|
|
|
FilenameForBPP(fn, VObjectDesc.ImageFile);
|
|
|
|
if( !AddVideoObject( &VObjectDesc, &uiINTBAR ) )
|
|
{
|
|
sprintf(fn, "Missing %s", fn);
|
|
AssertMsg(0, fn );
|
|
}
|
|
|
|
SetFontDestBuffer( uiSurface , 0, 0, SCREEN_WIDTH , HEIGHT_PROGRESSBAR, FALSE );
|
|
SetFont( TINYFONT1 );
|
|
|
|
switch( ubType )
|
|
{
|
|
case COMPUTER_TURN_MESSAGE:
|
|
case COMPUTER_INTERRUPT_MESSAGE:
|
|
case MILITIA_INTERRUPT_MESSAGE:
|
|
case AIR_RAID_TURN_MESSAGE:
|
|
|
|
// Render rect into surface
|
|
BltVideoObjectFromIndex( uiSurface, uiBAR, 0, xResOffset, 0, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
|
|
SetFontBackground( FONT_MCOLOR_BLACK );
|
|
SetFontForeground( FONT_MCOLOR_WHITE );
|
|
uiBarToUseInUpDate = uiBAR;
|
|
fDoLimitBar = TRUE;
|
|
break;
|
|
|
|
case PLAYER_INTERRUPT_MESSAGE:
|
|
|
|
// Render rect into surface
|
|
BltVideoObjectFromIndex( uiSurface, uiINTBAR, 0, xResOffset, 0, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
|
|
SetFontBackground( FONT_MCOLOR_BLACK );
|
|
SetFontForeground( FONT_MCOLOR_WHITE );
|
|
SetFontShadow( NO_SHADOW );
|
|
uiBarToUseInUpDate = uiINTBAR;
|
|
break;
|
|
|
|
case PLAYER_TURN_MESSAGE:
|
|
|
|
// Render rect into surface
|
|
BltVideoObjectFromIndex( uiSurface, uiPLAYERBAR, 0, xResOffset, 0, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
|
|
SetFontBackground( FONT_MCOLOR_BLACK );
|
|
SetFontForeground( FONT_MCOLOR_WHITE );
|
|
SetFontShadow( NO_SHADOW );
|
|
uiBarToUseInUpDate = uiPLAYERBAR;
|
|
break;
|
|
}
|
|
|
|
if ( gGameOptions.fTurnTimeLimit )
|
|
{
|
|
if ( ubType == PLAYER_TURN_MESSAGE || ubType == PLAYER_INTERRUPT_MESSAGE )
|
|
{
|
|
fDoLimitBar = TRUE;
|
|
}
|
|
}
|
|
|
|
if ( fDoLimitBar )
|
|
{
|
|
dNumStepsPerEnemy = (FLOAT)( (FLOAT)iProgBarLength / (FLOAT)gTacticalStatus.usTactialTurnLimitMax );
|
|
|
|
// Render end peice
|
|
sBarX = (SCREEN_WIDTH - xResSize) / 2 + 5;
|
|
BltVideoObjectFromIndex( uiSurface, uiBarToUseInUpDate, 1, sBarX, PROG_BAR_START_Y, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
|
|
// Determine Length
|
|
dLength = ( gTacticalStatus.usTactialTurnLimitCounter ) * dNumStepsPerEnemy;
|
|
|
|
dCurSize = 0;
|
|
cnt2 = 0;
|
|
|
|
while( dCurSize < dLength )
|
|
{
|
|
sBarX++;
|
|
|
|
// Check sBarX, ( just as a precaution )
|
|
if ( sBarX > SCREEN_WIDTH - 1 )
|
|
{
|
|
break;
|
|
}
|
|
|
|
BltVideoObjectFromIndex( uiSurface, uiBarToUseInUpDate, (INT16)( 2 + cnt2 ), sBarX, PROG_BAR_START_Y, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
|
|
dCurSize++;
|
|
cnt2++;
|
|
|
|
if ( cnt2 == 10 )
|
|
{
|
|
cnt2 = 0;
|
|
}
|
|
}
|
|
|
|
// Do end...
|
|
if ( gTacticalStatus.usTactialTurnLimitCounter == gTacticalStatus.usTactialTurnLimitMax )
|
|
{
|
|
sBarX++;
|
|
BltVideoObjectFromIndex( uiSurface, uiBarToUseInUpDate, (INT16)( 2 + cnt2 ), sBarX, PROG_BAR_START_Y, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
sBarX++;
|
|
BltVideoObjectFromIndex( uiSurface, uiBarToUseInUpDate, (INT16)( 12 ), sBarX, PROG_BAR_START_Y, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
}
|
|
}
|
|
|
|
// Delete rect
|
|
DeleteVideoObjectFromIndex( uiBAR );
|
|
DeleteVideoObjectFromIndex( uiINTBAR );
|
|
DeleteVideoObjectFromIndex( uiPLAYERBAR );
|
|
|
|
// Draw text....
|
|
if(gGameExternalOptions.fSmallSizeProgressbar)
|
|
FindFontCenterCoordinates( SCREEN_WIDTH/2, 2, 1, 1, psString, TINYFONT1, &sX, &sY );
|
|
else
|
|
FindFontCenterCoordinates( SCREEN_WIDTH/2, 7, 1, 1, psString, TINYFONT1, &sX, &sY );
|
|
|
|
mprintf( sX, sY, psString );
|
|
|
|
// Change back...
|
|
SetFontDestBuffer( FRAME_BUFFER , 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, FALSE );
|
|
|
|
// Done!
|
|
SetFontShadow( DEFAULT_SHADOW );
|
|
|
|
gfTopMessageDirty = TRUE;
|
|
}
|
|
|
|
void TurnExpiredCallBack( UINT8 bExitValue )
|
|
{
|
|
// End turn...
|
|
UIHandleEndTurn( NULL );
|
|
}
|
|
|
|
void CheckForAndHandleEndPlayerTimeLimit( )
|
|
{
|
|
if ( gTacticalStatus.fInTopMessage )
|
|
{
|
|
if ( gGameOptions.fTurnTimeLimit )
|
|
{
|
|
if ( gTacticalStatus.ubTopMessageType == PLAYER_TURN_MESSAGE || gTacticalStatus.ubTopMessageType == PLAYER_INTERRUPT_MESSAGE )
|
|
{
|
|
if ( gTacticalStatus.usTactialTurnLimitCounter == ( gTacticalStatus.usTactialTurnLimitMax - 1 ) )
|
|
{
|
|
// ATE: increase this so that we don't go into here again...
|
|
gTacticalStatus.usTactialTurnLimitCounter++;
|
|
|
|
// OK, set message that time limit has expired....
|
|
//DoMessageBox( MSG_BOX_BASIC_STYLE, L"Turn has Expired!", GAME_SCREEN, ( UINT8 )MSG_BOX_FLAG_OK, TurnExpiredCallBack, NULL );
|
|
|
|
// End turn...
|
|
UIHandleEndTurn( NULL );
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void HandleTopMessages( )
|
|
{
|
|
//UINT32 uiTime;
|
|
blt_vs_fx BltFx;
|
|
|
|
// OK, is out current count > 0 ?
|
|
if ( gTacticalStatus.fInTopMessage )
|
|
{
|
|
//gfTopMessageDirty = TRUE;
|
|
|
|
|
|
// ATE: If we are told to go into top message, but we have not
|
|
// initialized it yet...
|
|
// This is mostly for loading saved games.....
|
|
if ( !gTopMessage.fCreated )
|
|
{
|
|
gfTopMessageDirty = TRUE;
|
|
AddTopMessage( gTacticalStatus.ubTopMessageType, gTacticalStatus.zTopMessageString );
|
|
}
|
|
|
|
if ( gTacticalStatus.ubTopMessageType == COMPUTER_TURN_MESSAGE ||
|
|
gTacticalStatus.ubTopMessageType == COMPUTER_INTERRUPT_MESSAGE ||
|
|
gTacticalStatus.ubTopMessageType == MILITIA_INTERRUPT_MESSAGE ||
|
|
gTacticalStatus.ubTopMessageType == AIR_RAID_TURN_MESSAGE )
|
|
{
|
|
// OK, update timer.....
|
|
if ( TIMECOUNTERDONE( giTimerTeamTurnUpdate, PLAYER_TEAM_TIMER_SEC_PER_TICKS ) )
|
|
{
|
|
RESETTIMECOUNTER( giTimerTeamTurnUpdate, PLAYER_TEAM_TIMER_SEC_PER_TICKS );
|
|
if(!is_networked)//hayden - stop clients from updating enemy progress bar... //could have another param in here when get coop going
|
|
{
|
|
// Update counter....
|
|
if ( gTacticalStatus.usTactialTurnLimitCounter < gTacticalStatus.usTactialTurnLimitMax )
|
|
{
|
|
gTacticalStatus.usTactialTurnLimitCounter++;
|
|
}
|
|
|
|
// Check if we have reach limit...
|
|
if ( gTacticalStatus.usTactialTurnLimitCounter >= ( ( gubProgCurEnemy ) * PLAYER_TEAM_TIMER_TICKS_PER_ENEMY ) )
|
|
{
|
|
gTacticalStatus.usTactialTurnLimitCounter = ( ( gubProgCurEnemy ) * PLAYER_TEAM_TIMER_TICKS_PER_ENEMY );
|
|
}
|
|
|
|
}
|
|
|
|
CreateTopMessage( gTopMessage.uiSurface, gTacticalStatus.ubTopMessageType, gTacticalStatus.zTopMessageString );
|
|
}
|
|
}
|
|
else if ( gGameOptions.fTurnTimeLimit )
|
|
{
|
|
if ( gTacticalStatus.ubTopMessageType == PLAYER_TURN_MESSAGE || gTacticalStatus.ubTopMessageType == PLAYER_INTERRUPT_MESSAGE )
|
|
{
|
|
if ( !gfUserTurnRegionActive && !AreWeInAUIMenu() )
|
|
{
|
|
// Check Grace period...
|
|
if ( ( GetJA2Clock( ) - gTacticalStatus.uiTactialTurnLimitClock ) > PLAYER_TEAM_TIMER_GRACE_PERIOD )
|
|
{
|
|
gTacticalStatus.uiTactialTurnLimitClock = 0;
|
|
|
|
if ( TIMECOUNTERDONE( giTimerTeamTurnUpdate, PLAYER_TEAM_TIMER_SEC_PER_TICKS ) )
|
|
{
|
|
RESETTIMECOUNTER( giTimerTeamTurnUpdate, PLAYER_TEAM_TIMER_SEC_PER_TICKS );
|
|
|
|
if ( gTacticalStatus.fTactialTurnLimitStartedBeep )
|
|
{
|
|
if ( ( GetJA2Clock( ) - gTopMessage.uiTimeSinceLastBeep ) > PLAYER_TEAM_TIMER_TIME_BETWEEN_BEEPS )
|
|
{
|
|
gTopMessage.uiTimeSinceLastBeep = GetJA2Clock( );
|
|
|
|
// Start sample....
|
|
PlayJA2SampleFromFile( "SOUNDS\\TURN_NEAR_END.WAV", RATE_11025, HIGHVOLUME, 1 , MIDDLEPAN );
|
|
}
|
|
}
|
|
|
|
// OK, have we gone past the time to
|
|
if ( !gTacticalStatus.fTactialTurnLimitStartedBeep && ( gTacticalStatus.usTactialTurnLimitMax - gTacticalStatus.usTactialTurnLimitCounter ) < PLAYER_TEAM_TIMER_TICKS_FROM_END_TO_START_BEEP )
|
|
{
|
|
gTacticalStatus.fTactialTurnLimitStartedBeep = TRUE;
|
|
|
|
gTopMessage.uiTimeSinceLastBeep = GetJA2Clock( );
|
|
|
|
}
|
|
|
|
// Update counter....
|
|
if ( gTacticalStatus.usTactialTurnLimitCounter < gTacticalStatus.usTactialTurnLimitMax )
|
|
{
|
|
gTacticalStatus.usTactialTurnLimitCounter++;
|
|
}
|
|
|
|
CreateTopMessage( gTopMessage.uiSurface, gTacticalStatus.ubTopMessageType, gTacticalStatus.zTopMessageString );
|
|
|
|
// Have we reached max?
|
|
if ( gTacticalStatus.usTactialTurnLimitCounter == ( gTacticalStatus.usTactialTurnLimitMax - 1) )
|
|
{
|
|
// IF we are not in lock ui mode....
|
|
CheckForAndHandleEndPlayerTimeLimit( );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Set redner viewport value
|
|
//* ddd gsVIEWPORT_WINDOW_START_Y = 20;
|
|
gsVIEWPORT_WINDOW_START_Y = HEIGHT_PROGRESSBAR;
|
|
|
|
// Check if we have scrolled...
|
|
if ( gTopMessage.sWorldRenderX != gsRenderCenterX || gTopMessage.sWorldRenderY != gsRenderCenterY )
|
|
{
|
|
gfTopMessageDirty = TRUE;
|
|
}
|
|
|
|
if ( gfTopMessageDirty )
|
|
{
|
|
gTopMessage.sWorldRenderX = gsRenderCenterX;
|
|
gTopMessage.sWorldRenderY = gsRenderCenterY;
|
|
|
|
// Redner!
|
|
BltFx.SrcRect.iLeft = 0;
|
|
//* ddd BltFx.SrcRect.iTop = 20 - gTopMessage.bYPos;
|
|
if(gGameExternalOptions.fSmallSizeProgressbar)
|
|
BltFx.SrcRect.iTop = 0;
|
|
else
|
|
BltFx.SrcRect.iTop = 20 - gTopMessage.bYPos;
|
|
|
|
BltFx.SrcRect.iRight = SCREEN_WIDTH ;
|
|
//*ddd BltFx.SrcRect.iBottom = 20;
|
|
BltFx.SrcRect.iBottom = HEIGHT_PROGRESSBAR;
|
|
|
|
BltVideoSurface( FRAME_BUFFER, gTopMessage.uiSurface, 0,
|
|
0, 0,
|
|
VS_BLT_SRCSUBRECT, &BltFx );
|
|
|
|
// Save to save buffer....
|
|
BltFx.SrcRect.iLeft = 0;
|
|
//* ddd BltFx.SrcRect.iTop = 0;
|
|
if(gGameExternalOptions.fSmallSizeProgressbar)
|
|
BltFx.SrcRect.iTop = 0;
|
|
else
|
|
BltFx.SrcRect.iTop = 20 - gTopMessage.bYPos;
|
|
|
|
BltFx.SrcRect.iRight = SCREEN_WIDTH;
|
|
//*ddd BltFx.SrcRect.iBottom = 20;
|
|
BltFx.SrcRect.iBottom = HEIGHT_PROGRESSBAR;
|
|
|
|
BltVideoSurface( guiSAVEBUFFER, FRAME_BUFFER, 0,
|
|
0, 0,
|
|
VS_BLT_SRCSUBRECT, &BltFx );
|
|
|
|
//*ddd InvalidateRegion( 0, 0, SCREEN_WIDTH, 20 );
|
|
InvalidateRegion( 0, 0, SCREEN_WIDTH, HEIGHT_PROGRESSBAR );
|
|
|
|
gfTopMessageDirty = FALSE;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
// Set redner viewport value
|
|
gsVIEWPORT_WINDOW_START_Y = 0;
|
|
}
|
|
}
|
|
|
|
|
|
void EndTopMessage( )
|
|
{
|
|
// blt_vs_fx BltFx;
|
|
|
|
|
|
// OK, end the topmost message!
|
|
if ( gTacticalStatus.fInTopMessage )
|
|
{
|
|
// Are we the last?
|
|
//if ( gTopMessage.bCurrentMessage == 1 )
|
|
{
|
|
// We are....
|
|
// Re-render our strip and then copy to the save buffer...
|
|
gsVIEWPORT_WINDOW_START_Y = 0;
|
|
gTacticalStatus.fInTopMessage = FALSE;
|
|
|
|
SetRenderFlags( RENDER_FLAG_FULL );
|
|
//RenderStaticWorldRect( 0, 0, 640, 20, TRUE );
|
|
//gsVIEWPORT_WINDOW_START_Y = 20;
|
|
|
|
// Copy into save buffer...
|
|
//BltFx.SrcRect.iLeft = 0;
|
|
//BltFx.SrcRect.iTop = 0;
|
|
//BltFx.SrcRect.iRight = 640;
|
|
//BltFx.SrcRect.iBottom = 20;
|
|
|
|
//BltVideoSurface( guiSAVEBUFFER, FRAME_BUFFER, 0,
|
|
// 0, 0,
|
|
// VS_BLT_SRCSUBRECT, &BltFx );
|
|
}
|
|
//else
|
|
//{
|
|
// Render to save buffer
|
|
// CreateTopMessage( guiSAVEBUFFER, gTopMessageTypes[ 0 ], gzTopMessageStrings[ 0 ] );
|
|
//}
|
|
|
|
// Animate up...
|
|
//gTopMessage.bAnimate = 1;
|
|
// Set time of last update
|
|
//gTopMessage.uiTimeOfLastUpdate = GetJA2Clock( ) + 150;
|
|
|
|
// Handle first frame now...
|
|
// HandleTopMessages( );
|
|
|
|
}
|
|
}
|
|
|
|
|
|
BOOLEAN InTopMessageBarAnimation( )
|
|
{
|
|
if ( gTacticalStatus.fInTopMessage )
|
|
{
|
|
if ( gTopMessage.bAnimate != 0 )
|
|
{
|
|
HandleTopMessages( );
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
}
|
|
|
|
return( FALSE );
|
|
}
|
|
|
|
|
|
void PauseRT( BOOLEAN fPause )
|
|
{
|
|
//StopMercAnimation( fPause );
|
|
|
|
if ( fPause )
|
|
{
|
|
// PauseGame( );
|
|
}
|
|
else
|
|
{
|
|
// UnPauseGame( );
|
|
}
|
|
}
|
|
|
|
|
|
void InitEnemyUIBar( UINT8 ubNumEnemies, UINT8 ubDoneEnemies )
|
|
{
|
|
// OK, set value
|
|
gubProgNumEnemies = ubNumEnemies + ubDoneEnemies;
|
|
gubProgCurEnemy = ubDoneEnemies;
|
|
gfProgBarActive = TRUE;
|
|
|
|
gTacticalStatus.usTactialTurnLimitCounter = ubDoneEnemies * PLAYER_TEAM_TIMER_TICKS_PER_ENEMY;
|
|
gTacticalStatus.usTactialTurnLimitMax = ( (ubNumEnemies + ubDoneEnemies) * PLAYER_TEAM_TIMER_TICKS_PER_ENEMY );
|
|
|
|
}
|
|
|
|
void UpdateEnemyUIBar( )
|
|
{
|
|
// Are we active?
|
|
if ( gfProgBarActive )
|
|
{
|
|
// OK, update team limit counter....
|
|
gTacticalStatus.usTactialTurnLimitCounter = ( gubProgCurEnemy * PLAYER_TEAM_TIMER_TICKS_PER_ENEMY );
|
|
|
|
gubProgCurEnemy++;
|
|
|
|
}
|
|
|
|
// Do we have an active enemy bar?
|
|
if ( gTacticalStatus.fInTopMessage )
|
|
{
|
|
if ( gTacticalStatus.ubTopMessageType == COMPUTER_TURN_MESSAGE )
|
|
{
|
|
// Update message!
|
|
CreateTopMessage( gTopMessage.uiSurface, COMPUTER_TURN_MESSAGE, gTacticalStatus.zTopMessageString );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void InitPlayerUIBar( BOOLEAN fInterrupt )
|
|
{
|
|
SOLDIERTYPE *pTeamSoldier;
|
|
INT32 cnt = 0;
|
|
INT8 bNumOK = 0, bNumNotOK = 0;
|
|
|
|
if ( !gGameOptions.fTurnTimeLimit )
|
|
{
|
|
if ( fInterrupt == TRUE )
|
|
{
|
|
AddTopMessage( PLAYER_INTERRUPT_MESSAGE, Message[STR_INTERRUPT] );
|
|
}
|
|
else
|
|
{
|
|
//EndTopMessage();
|
|
AddTopMessage( PLAYER_TURN_MESSAGE, TeamTurnString[0] );
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (is_networked)
|
|
gTacticalStatus.usTactialTurnLimitMax = 0;//hayden , cheap hack, always calc time...
|
|
|
|
// OK, calculate time....
|
|
if ( !fInterrupt || gTacticalStatus.usTactialTurnLimitMax == 0 )
|
|
{
|
|
gTacticalStatus.usTactialTurnLimitCounter = 0;
|
|
|
|
// IF IT'S THE SELECTED GUY, MAKE ANOTHER SELECTED!
|
|
cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
|
|
|
|
// look for all mercs on the same team,
|
|
for ( pTeamSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++,pTeamSoldier++)
|
|
{
|
|
// Are we active and in sector.....
|
|
if ( pTeamSoldier->bActive && pTeamSoldier->bInSector )
|
|
{
|
|
if ( pTeamSoldier->stats.bLife < OKLIFE )
|
|
{
|
|
bNumNotOK++;
|
|
}
|
|
else
|
|
{
|
|
bNumOK++;
|
|
}
|
|
}
|
|
}
|
|
|
|
gTacticalStatus.usTactialTurnLimitMax = ( bNumOK * PLAYER_TEAM_TIMER_TICKS_PER_OK_MERC ) + ( bNumNotOK * PLAYER_TEAM_TIMER_TICKS_PER_NOTOK_MERC );
|
|
}
|
|
else
|
|
{
|
|
if ( gTacticalStatus.usTactialTurnLimitCounter > PLAYER_TEAM_TIMER_INTTERUPT_GRACE )
|
|
{
|
|
gTacticalStatus.usTactialTurnLimitCounter -= PLAYER_TEAM_TIMER_INTTERUPT_GRACE;
|
|
}
|
|
}
|
|
|
|
gTacticalStatus.uiTactialTurnLimitClock = 0;
|
|
gTacticalStatus.fTactialTurnLimitStartedBeep = FALSE;
|
|
|
|
// RESET COIUNTER...
|
|
RESETTIMECOUNTER( giTimerTeamTurnUpdate, PLAYER_TEAM_TIMER_SEC_PER_TICKS );
|
|
|
|
|
|
// OK, set value
|
|
if ( fInterrupt != TRUE )
|
|
{
|
|
AddTopMessage( PLAYER_TURN_MESSAGE, TeamTurnString[0] );
|
|
}
|
|
else
|
|
{
|
|
AddTopMessage( PLAYER_INTERRUPT_MESSAGE, Message[STR_INTERRUPT] );
|
|
}
|
|
|
|
}
|
|
|
|
|
|
void MovementMenuBackregionCallback( MOUSE_REGION * pRegion, INT32 iReason )
|
|
{
|
|
if ( iReason & MSYS_CALLBACK_REASON_LBUTTON_UP )
|
|
{
|
|
CancelMovementMenu( );
|
|
}
|
|
}
|
|
|
|
void DoorMenuBackregionCallback( MOUSE_REGION * pRegion, INT32 iReason )
|
|
{
|
|
if ( iReason & MSYS_CALLBACK_REASON_LBUTTON_UP )
|
|
{
|
|
CancelOpenDoorMenu( );
|
|
}
|
|
}
|
|
|
|
STR16 GetSoldierHealthString( SOLDIERTYPE *pSoldier )
|
|
{
|
|
// sevenfm: show enemy health as text only when SHOW_ENEMY_HEALTH = 1
|
|
if ( ( gGameExternalOptions.ubShowEnemyHealth != 1 ) && (pSoldier->bTeam == ENEMY_TEAM || pSoldier->bTeam == CREATURE_TEAM))
|
|
{
|
|
return L"";
|
|
}
|
|
else
|
|
{
|
|
// Flugente: display if we are a prisoner of war
|
|
if ( pSoldier->bSoldierFlagMask & SOLDIER_POW )
|
|
return zHealthStr[ 7 ];
|
|
|
|
INT32 cnt, cntStart;
|
|
if( pSoldier->stats.bLife == pSoldier->stats.bLifeMax )
|
|
{
|
|
cntStart = 4;
|
|
}
|
|
else
|
|
{
|
|
cntStart = 0;
|
|
}
|
|
//Show health on others.........
|
|
for ( cnt = cntStart; cnt < 6; cnt ++ )
|
|
{
|
|
if ( pSoldier->stats.bLife < bHealthStrRanges[ cnt ] )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
return zHealthStr[ cnt ];
|
|
}
|
|
}
|
|
|
|
|
|
typedef struct
|
|
{
|
|
INT8 bHeight;
|
|
INT8 bPower;
|
|
INT32 sGridNo;
|
|
UINT8 ubLevel;
|
|
SOLDIERTYPE *pSoldier;
|
|
BOOLEAN fShowHeight;
|
|
BOOLEAN fShowPower;
|
|
BOOLEAN fActiveHeightBar;
|
|
BOOLEAN fActivePowerBar;
|
|
BOOLEAN fAtEndHeight;
|
|
INT32 sTargetGridNo;
|
|
FLOAT dInitialForce;
|
|
FLOAT dForce;
|
|
FLOAT dDegrees;
|
|
FLOAT dMaxForce;
|
|
UINT8 ubPowerIndex;
|
|
|
|
} AIMCUBE_UI_DATA;
|
|
|
|
static BOOLEAN gfInAimCubeUI = FALSE;
|
|
static AIMCUBE_UI_DATA gCubeUIData;
|
|
|
|
#define GET_CUBES_HEIGHT_FROM_UIHEIGHT( h ) ( 32 + ( h * 64 ) )
|
|
|
|
|
|
|
|
void CalculateAimCubeUIPhysics( )
|
|
{
|
|
UINT8 ubHeight;
|
|
|
|
ubHeight = GET_CUBES_HEIGHT_FROM_UIHEIGHT( gCubeUIData.bHeight );
|
|
|
|
if ( gCubeUIData.fActiveHeightBar )
|
|
{
|
|
|
|
// OK, determine which power to use.....
|
|
// TODO this: take force / max force * 10....
|
|
gCubeUIData.ubPowerIndex = (UINT8)( gCubeUIData.dForce / gCubeUIData.dMaxForce * 10 );
|
|
|
|
}
|
|
|
|
if ( gCubeUIData.fActivePowerBar )
|
|
{
|
|
gCubeUIData.dForce = ( gCubeUIData.dMaxForce * ( (FLOAT)gCubeUIData.ubPowerIndex / (FLOAT)10 ) );
|
|
|
|
// Limit to the max force...
|
|
if ( gCubeUIData.dForce > gCubeUIData.dMaxForce )
|
|
{
|
|
gCubeUIData.dForce = gCubeUIData.dMaxForce;
|
|
}
|
|
|
|
gCubeUIData.dDegrees = (FLOAT)CalculateLaunchItemAngle( gCubeUIData.pSoldier, gCubeUIData.sGridNo, ubHeight, gCubeUIData.dForce, &(gCubeUIData.pSoldier->inv[ HANDPOS ] ), &(gCubeUIData.sTargetGridNo ) );
|
|
}
|
|
|
|
}
|
|
|
|
|
|
INT32 GetInAimCubeUIGridNo( )
|
|
{
|
|
return( gCubeUIData.sGridNo );
|
|
}
|
|
|
|
BOOLEAN InAimCubeUI( )
|
|
{
|
|
return( gfInAimCubeUI );
|
|
}
|
|
|
|
BOOLEAN AimCubeUIClick( )
|
|
{
|
|
if ( !gfInAimCubeUI )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
// If we have clicked, and we are only on height, continue with power
|
|
if ( gCubeUIData.fActiveHeightBar && gCubeUIData.bHeight != 0 )
|
|
{
|
|
gCubeUIData.fShowPower = TRUE;
|
|
gCubeUIData.fActiveHeightBar = FALSE;
|
|
gCubeUIData.fActivePowerBar = TRUE;
|
|
|
|
return( FALSE );
|
|
}
|
|
else
|
|
{
|
|
return( TRUE );
|
|
}
|
|
}
|
|
|
|
void BeginAimCubeUI( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 ubLevel, UINT8 bStartPower, INT8 bStartHeight )
|
|
{
|
|
gfInAimCubeUI = TRUE;
|
|
|
|
gCubeUIData.sGridNo = sGridNo;
|
|
gCubeUIData.ubLevel = ubLevel;
|
|
gCubeUIData.pSoldier = pSoldier;
|
|
gCubeUIData.bPower = bStartPower;
|
|
gCubeUIData.bHeight = bStartHeight;
|
|
gCubeUIData.fShowHeight = TRUE;
|
|
gCubeUIData.fShowPower = FALSE;
|
|
gCubeUIData.fActivePowerBar = FALSE;
|
|
gCubeUIData.fActiveHeightBar = TRUE;
|
|
gCubeUIData.fAtEndHeight = FALSE;
|
|
gCubeUIData.dDegrees = (float)PI/4;
|
|
|
|
|
|
// Calculate Iniital force....
|
|
CalculateAimCubeUIPhysics( );
|
|
|
|
}
|
|
|
|
|
|
void EndAimCubeUI( )
|
|
{
|
|
gfInAimCubeUI = FALSE;
|
|
}
|
|
|
|
void IncrementAimCubeUI( )
|
|
{
|
|
if ( gCubeUIData.fActiveHeightBar )
|
|
{
|
|
// Cycle the last height yellow once
|
|
if ( gCubeUIData.bHeight == 3 )
|
|
{
|
|
if ( gCubeUIData.fAtEndHeight )
|
|
{
|
|
gCubeUIData.bHeight = 0;
|
|
gCubeUIData.fAtEndHeight = 0;
|
|
}
|
|
else
|
|
{
|
|
gCubeUIData.fAtEndHeight = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
gCubeUIData.bHeight++;
|
|
}
|
|
|
|
CalculateAimCubeUIPhysics( );
|
|
|
|
}
|
|
|
|
if ( gCubeUIData.fActivePowerBar )
|
|
{
|
|
if ( gCubeUIData.ubPowerIndex == 10 )
|
|
{
|
|
UINT8 ubHeight;
|
|
|
|
ubHeight = GET_CUBES_HEIGHT_FROM_UIHEIGHT( gCubeUIData.bHeight );
|
|
|
|
// Start back to basic7
|
|
gCubeUIData.dDegrees = (FLOAT)(PI/4);
|
|
gCubeUIData.dInitialForce = gCubeUIData.dForce;
|
|
|
|
// OK, determine which power to use.....
|
|
// TODO this: take force / max force * 10....
|
|
gCubeUIData.ubPowerIndex = (UINT8)( gCubeUIData.dForce / gCubeUIData.dMaxForce * 10 );
|
|
}
|
|
|
|
// Cycle the last height yellow once
|
|
gCubeUIData.ubPowerIndex++;
|
|
|
|
CalculateAimCubeUIPhysics( );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
void SetupAimCubeAI( )
|
|
{
|
|
if ( gfInAimCubeUI )
|
|
{
|
|
AddTopmostToHead( gCubeUIData.sTargetGridNo, FIRSTPOINTERS2 );
|
|
gpWorldLevelData[ gCubeUIData.sTargetGridNo ].pTopmostHead->ubShadeLevel=DEFAULT_SHADE_LEVEL;
|
|
gpWorldLevelData[ gCubeUIData.sTargetGridNo ].pTopmostHead->ubNaturalShadeLevel=DEFAULT_SHADE_LEVEL;
|
|
|
|
//AddTopmostToHead( gCubeUIData.sGridNo, FIRSTPOINTERS2 );
|
|
//gpWorldLevelData[ gCubeUIData.sGridNo ].pTopmostHead->ubShadeLevel=DEFAULT_SHADE_LEVEL;
|
|
//gpWorldLevelData[ gCubeUIData.sGridNo ].pTopmostHead->ubNaturalShadeLevel=DEFAULT_SHADE_LEVEL;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
void ResetAimCubeAI( )
|
|
{
|
|
if ( gfInAimCubeUI )
|
|
{
|
|
RemoveTopmost( gCubeUIData.sTargetGridNo, FIRSTPOINTERS2 );
|
|
//RemoveTopmost( gCubeUIData.sGridNo, FIRSTPOINTERS2 );
|
|
}
|
|
}
|
|
|
|
void RenderAimCubeUI( )
|
|
{
|
|
INT16 sScreenX = 0, sScreenY = 0;
|
|
INT32 cnt;
|
|
INT16 sBarHeight;
|
|
INT32 iBack;
|
|
INT8 bGraphicNum;
|
|
|
|
if ( gfInAimCubeUI )
|
|
{
|
|
|
|
// OK, given height
|
|
if ( gCubeUIData.fShowHeight )
|
|
{
|
|
// Determine screen location....
|
|
GetGridNoScreenPos( gCubeUIData.sGridNo, gCubeUIData.ubLevel, &sScreenX, &sScreenY );
|
|
|
|
// Save background
|
|
iBack = RegisterBackgroundRect( BGND_FLAG_SINGLE, NULL, sScreenX, (INT16)(sScreenY - 70 ), (INT16)(sScreenX + 40 ), (INT16)(sScreenY + 50 ) );
|
|
if ( iBack != -1 )
|
|
{
|
|
SetBackgroundRectFilled( iBack );
|
|
}
|
|
|
|
sBarHeight = 0;
|
|
bGraphicNum = 0;
|
|
|
|
if ( gCubeUIData.bHeight == 3 && gCubeUIData.fAtEndHeight )
|
|
{
|
|
bGraphicNum = 1;
|
|
}
|
|
|
|
// Do first level....
|
|
BltVideoObjectFromIndex( FRAME_BUFFER, guiAIMCUBES, bGraphicNum, sScreenX, ( sScreenY + sBarHeight ), VO_BLT_SRCTRANSPARENCY, NULL );
|
|
sBarHeight -= 3;
|
|
BltVideoObjectFromIndex( FRAME_BUFFER, guiAIMCUBES, bGraphicNum, sScreenX, ( sScreenY + sBarHeight ), VO_BLT_SRCTRANSPARENCY, NULL );
|
|
|
|
// Loop through height.....
|
|
for ( cnt = 1; cnt <= gCubeUIData.bHeight; cnt++ )
|
|
{
|
|
sBarHeight -= 3;
|
|
BltVideoObjectFromIndex( FRAME_BUFFER, guiAIMCUBES, bGraphicNum, sScreenX, ( sScreenY + sBarHeight ), VO_BLT_SRCTRANSPARENCY, NULL );
|
|
sBarHeight -= 3;
|
|
BltVideoObjectFromIndex( FRAME_BUFFER, guiAIMCUBES, bGraphicNum, sScreenX, ( sScreenY + sBarHeight ), VO_BLT_SRCTRANSPARENCY, NULL );
|
|
sBarHeight -= 3;
|
|
BltVideoObjectFromIndex( FRAME_BUFFER, guiAIMCUBES, bGraphicNum, sScreenX, ( sScreenY + sBarHeight ), VO_BLT_SRCTRANSPARENCY, NULL );
|
|
sBarHeight -= 3;
|
|
BltVideoObjectFromIndex( FRAME_BUFFER, guiAIMCUBES, bGraphicNum, sScreenX, ( sScreenY + sBarHeight ), VO_BLT_SRCTRANSPARENCY, NULL );
|
|
}
|
|
}
|
|
|
|
|
|
if ( gCubeUIData.fShowPower )
|
|
{
|
|
sBarHeight = -50;
|
|
|
|
BltVideoObjectFromIndex( FRAME_BUFFER, guiAIMBARS, gCubeUIData.ubPowerIndex, sScreenX, ( sScreenY + sBarHeight ), VO_BLT_SRCTRANSPARENCY, NULL );
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void GetLaunchItemParamsFromUI( )
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
static BOOLEAN gfDisplayPhysicsUI = FALSE;
|
|
static INT32 gsPhysicsImpactPointGridNo;
|
|
static INT8 gbPhysicsImpactPointLevel;
|
|
static BOOLEAN gfBadPhysicsCTGT = FALSE;
|
|
|
|
void BeginPhysicsTrajectoryUI( INT32 sGridNo, INT8 bLevel, BOOLEAN fBadCTGT )
|
|
{
|
|
gfDisplayPhysicsUI = TRUE;
|
|
gsPhysicsImpactPointGridNo = sGridNo;
|
|
gbPhysicsImpactPointLevel = bLevel;
|
|
gfBadPhysicsCTGT = fBadCTGT;
|
|
}
|
|
|
|
void EndPhysicsTrajectoryUI( )
|
|
{
|
|
gfDisplayPhysicsUI = FALSE;
|
|
|
|
}
|
|
|
|
void SetupPhysicsTrajectoryUI( )
|
|
{
|
|
if ( gfDisplayPhysicsUI && gfUIHandlePhysicsTrajectory )
|
|
{
|
|
if ( gbPhysicsImpactPointLevel == 0 )
|
|
{
|
|
if ( gfBadPhysicsCTGT )
|
|
{
|
|
AddTopmostToHead( gsPhysicsImpactPointGridNo, FIRSTPOINTERS12 );
|
|
}
|
|
else
|
|
{
|
|
AddTopmostToHead( gsPhysicsImpactPointGridNo, FIRSTPOINTERS8 );
|
|
}
|
|
gpWorldLevelData[ gsPhysicsImpactPointGridNo ].pTopmostHead->ubShadeLevel=DEFAULT_SHADE_LEVEL;
|
|
gpWorldLevelData[ gsPhysicsImpactPointGridNo ].pTopmostHead->ubNaturalShadeLevel=DEFAULT_SHADE_LEVEL;
|
|
}
|
|
else
|
|
{
|
|
if ( gfBadPhysicsCTGT )
|
|
{
|
|
AddOnRoofToHead( gsPhysicsImpactPointGridNo, FIRSTPOINTERS12 );
|
|
}
|
|
else
|
|
{
|
|
AddOnRoofToHead( gsPhysicsImpactPointGridNo, FIRSTPOINTERS8 );
|
|
}
|
|
gpWorldLevelData[ gsPhysicsImpactPointGridNo ].pOnRoofHead->ubShadeLevel=DEFAULT_SHADE_LEVEL;
|
|
gpWorldLevelData[ gsPhysicsImpactPointGridNo ].pOnRoofHead->ubNaturalShadeLevel=DEFAULT_SHADE_LEVEL;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void ResetPhysicsTrajectoryUI( )
|
|
{
|
|
if ( gfDisplayPhysicsUI )
|
|
{
|
|
RemoveTopmost( gsPhysicsImpactPointGridNo, FIRSTPOINTERS8 );
|
|
RemoveTopmost( gsPhysicsImpactPointGridNo, FIRSTPOINTERS12 );
|
|
RemoveOnRoof( gsPhysicsImpactPointGridNo, FIRSTPOINTERS8 );
|
|
RemoveOnRoof( gsPhysicsImpactPointGridNo, FIRSTPOINTERS12 );
|
|
}
|
|
|
|
}
|
|
|
|
void DirtyTopMessage( )
|
|
{
|
|
gTopMessage.fCreated = FALSE;
|
|
}
|
|
|
|
|
|
|
|
UINT32 CalcUIMessageDuration( STR16 wString )
|
|
{
|
|
// base + X per letter
|
|
return( 1000 + 50 * wcslen( wString ) );
|
|
}
|
|
|
|
|
|
BOOLEAN gfMultipurposeLocatorOn = FALSE;
|
|
UINT32 guiMultiPurposeLocatorLastUpdate;
|
|
INT8 gbMultiPurposeLocatorFrame;
|
|
INT32 gsMultiPurposeLocatorGridNo;
|
|
INT8 gbMultiPurposeLocatorLevel;
|
|
INT8 gbMultiPurposeLocatorCycles;
|
|
|
|
void BeginMultiPurposeLocator( INT32 sGridNo, INT8 bLevel, BOOLEAN fSlideTo )
|
|
{
|
|
guiMultiPurposeLocatorLastUpdate = 0;
|
|
gbMultiPurposeLocatorCycles = 0;
|
|
gbMultiPurposeLocatorFrame = 0;
|
|
gfMultipurposeLocatorOn = TRUE;
|
|
|
|
gsMultiPurposeLocatorGridNo = sGridNo;
|
|
gbMultiPurposeLocatorLevel = bLevel;
|
|
|
|
if ( fSlideTo )
|
|
{
|
|
// FIRST CHECK IF WE ARE ON SCREEN
|
|
if ( GridNoOnScreen( sGridNo ) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// sGridNo here for DG compatibility
|
|
gTacticalStatus.sSlideTarget = sGridNo;
|
|
gTacticalStatus.sSlideReason = NOBODY;
|
|
|
|
// Plot new path!
|
|
gfPlotNewMovement = TRUE;
|
|
}
|
|
}
|
|
|
|
|
|
void HandleMultiPurposeLocator( )
|
|
{
|
|
UINT32 uiClock;
|
|
|
|
if ( !gfMultipurposeLocatorOn )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Update radio locator
|
|
uiClock = GetJA2Clock( );
|
|
|
|
// Update frame values!
|
|
if ( ( uiClock - guiMultiPurposeLocatorLastUpdate ) > 80 )
|
|
{
|
|
guiMultiPurposeLocatorLastUpdate = uiClock;
|
|
|
|
// Update frame
|
|
gbMultiPurposeLocatorFrame++;
|
|
|
|
if ( gbMultiPurposeLocatorFrame == 5 )
|
|
{
|
|
gbMultiPurposeLocatorFrame = 0;
|
|
gbMultiPurposeLocatorCycles++;
|
|
}
|
|
|
|
if ( gbMultiPurposeLocatorCycles == 8 )
|
|
{
|
|
gfMultipurposeLocatorOn = FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void RenderTopmostMultiPurposeLocator( )
|
|
{
|
|
FLOAT dOffsetX, dOffsetY;
|
|
FLOAT dTempX_S, dTempY_S;
|
|
INT16 sX, sY, sXPos, sYPos;
|
|
INT32 iBack;
|
|
|
|
if ( !gfMultipurposeLocatorOn )
|
|
{
|
|
return;
|
|
}
|
|
|
|
ConvertGridNoToCenterCellXY( gsMultiPurposeLocatorGridNo, &sX, &sY );
|
|
|
|
dOffsetX = (FLOAT)( sX - gsRenderCenterX );
|
|
dOffsetY = (FLOAT)( sY - gsRenderCenterY );
|
|
|
|
// Calculate guy's position
|
|
FloatFromCellToScreenCoordinates( dOffsetX, dOffsetY, &dTempX_S, &dTempY_S );
|
|
|
|
sXPos = ( ( gsVIEWPORT_END_X - gsVIEWPORT_START_X ) /2 ) + (INT16)dTempX_S;
|
|
sYPos = ( ( gsVIEWPORT_END_Y - gsVIEWPORT_START_Y ) /2 ) + (INT16)dTempY_S - gpWorldLevelData[ gsMultiPurposeLocatorGridNo ].sHeight;
|
|
|
|
// Adjust for offset position on screen
|
|
sXPos -= gsRenderWorldOffsetX;
|
|
sYPos -= gsRenderWorldOffsetY;
|
|
|
|
// Adjust for render height
|
|
sYPos += gsRenderHeight;
|
|
|
|
// Adjust for level height
|
|
if ( gbMultiPurposeLocatorLevel )
|
|
{
|
|
sYPos -= ROOF_LEVEL_HEIGHT;
|
|
}
|
|
|
|
// Center circle!
|
|
sXPos -= 20;
|
|
sYPos -= 20;
|
|
|
|
iBack = RegisterBackgroundRect( BGND_FLAG_SINGLE, NULL, sXPos, sYPos, (INT16)(sXPos +40 ), (INT16)(sYPos + 40 ) );
|
|
if ( iBack != -1 )
|
|
{
|
|
SetBackgroundRectFilled( iBack );
|
|
}
|
|
|
|
BltVideoObjectFromIndex( FRAME_BUFFER, guiRADIO, gbMultiPurposeLocatorFrame, sXPos, sYPos, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
}
|
|
|
|
void DrawBar( INT32 x, INT32 y, INT32 width, INT32 height, UINT16 color8, UINT16 color16, UINT8 *pDestBuf )
|
|
{
|
|
if( width > 0 )
|
|
{
|
|
for( INT32 i=0; i < height; i++ )
|
|
{
|
|
if(gbPixelDepth==16)
|
|
LineDraw( TRUE, x, y+i, x+width-1, y+i, color16, pDestBuf );
|
|
else if(gbPixelDepth==8)
|
|
LineDraw8( TRUE, x, y+i, x+width-1, y+i, color8, pDestBuf );
|
|
}
|
|
}
|
|
}
|
|
|
|
BOOLEAN CoverColorCode( INT8 cover, INT16 &color8, INT16 &color16 ){
|
|
BOOLEAN showCover = TRUE;
|
|
switch(cover)
|
|
{
|
|
case 0:
|
|
//color8 = COLOR_RED;
|
|
color8 = FONT_MCOLOR_RED;
|
|
color16 = Get16BPPColor( FROMRGB( 220, 0, 0 ) );
|
|
break;
|
|
case 1:
|
|
color8 = COLOR_ORANGE;
|
|
color16 = Get16BPPColor( FROMRGB( 220, 140, 0 ) );
|
|
break;
|
|
case 2:
|
|
color8 = COLOR_YELLOW;
|
|
color16 = Get16BPPColor( FROMRGB( 220, 220, 0 ) );
|
|
break;
|
|
case 3:
|
|
color8 = COLOR_GREEN;
|
|
color16 = Get16BPPColor( FROMRGB( 0, 200, 0 ) );
|
|
break;
|
|
default:
|
|
showCover = FALSE;
|
|
}
|
|
return showCover;
|
|
}
|
|
|
|
void DrawRankIcon( INT8 rank, INT32 baseX, INT32 baseY )
|
|
{
|
|
UINT32 uiDestPitchBYTES;
|
|
UINT8 *pDestBuf;
|
|
INT16 color8;
|
|
INT16 color16;
|
|
|
|
pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES );
|
|
SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, gsVIEWPORT_WINDOW_START_Y, SCREEN_WIDTH, ( gsVIEWPORT_WINDOW_END_Y - gsVIEWPORT_WINDOW_START_Y ) );
|
|
|
|
if(rank<6)
|
|
{
|
|
color8 = FONT_DKGREEN;
|
|
color16 = Get16BPPColor( FROMRGB( 20, 60, 20 ) );
|
|
//color8 = FONT_ORANGE;
|
|
//color16 = Get16BPPColor( FROMRGB( 160, 80, 0 ) );
|
|
}
|
|
else
|
|
{
|
|
color8 = FONT_DKRED;
|
|
color16 = Get16BPPColor( FROMRGB( 60, 20, 20 ) );
|
|
}
|
|
|
|
DrawBar( baseX+2, baseY+2, 7, 8, color8, color16, pDestBuf );
|
|
DrawLine( baseX+3, baseY+10, baseX+7, baseY+10, color8, color16, pDestBuf );
|
|
DrawLine( baseX+4, baseY+11, baseX+6, baseY+11, color8, color16, pDestBuf );
|
|
|
|
if(rank<6)
|
|
{
|
|
color8 = COLOR_GREEN;
|
|
color16 = Get16BPPColor( FROMRGB( 20, 80, 20 ) );
|
|
//color8 = FONT_YELLOW;
|
|
//color16 = Get16BPPColor( FROMRGB( 200, 120, 00 ) );
|
|
}
|
|
else
|
|
{
|
|
color8 = COLOR_RED;
|
|
color16 = Get16BPPColor( FROMRGB( 120, 20, 20 ) );
|
|
}
|
|
|
|
DrawLine( baseX+2, baseY+1, baseX+8, baseY+1, color8, color16, pDestBuf );
|
|
DrawLine( baseX+1, baseY+2, baseX+1, baseY+9, color8, color16, pDestBuf );
|
|
DrawLine( baseX+9, baseY+2, baseX+9, baseY+9, color8, color16, pDestBuf );
|
|
|
|
DrawLine( baseX+1, baseY+9, baseX+4, baseY+12, color8, color16, pDestBuf );
|
|
DrawLine( baseX+4, baseY+12, baseX+6, baseY+12, color8, color16, pDestBuf );
|
|
DrawLine( baseX+6, baseY+12, baseX+9, baseY+9, color8, color16, pDestBuf );
|
|
|
|
if(rank<6)
|
|
{
|
|
//color8 = FONT_DKGREEN;
|
|
//color16 = Get16BPPColor( FROMRGB( 0, 40, 0 ) );
|
|
//color8 = COLOR_LTGREY;
|
|
//color16 = Get16BPPColor( FROMRGB( 120, 120, 120 ) );
|
|
color8 = COLOR_YELLOW;
|
|
color16 = Get16BPPColor( FROMRGB( 200, 200, 200 ) );
|
|
}
|
|
else
|
|
{
|
|
color8 = FONT_ORANGE;
|
|
color16 = Get16BPPColor( FROMRGB( 220, 140, 20 ) );
|
|
}
|
|
|
|
switch( rank )
|
|
{
|
|
case 1:
|
|
DrawLine( baseX+3, baseY+6, baseX+7, baseY+6, color8, color16, pDestBuf );
|
|
break;
|
|
case 2:
|
|
DrawLine( baseX+3, baseY+5, baseX+7, baseY+5, color8, color16, pDestBuf );
|
|
DrawLine( baseX+3, baseY+7, baseX+7, baseY+7, color8, color16, pDestBuf );
|
|
break;
|
|
case 3:
|
|
DrawLine( baseX+3, baseY+4, baseX+7, baseY+4, color8, color16, pDestBuf );
|
|
DrawLine( baseX+3, baseY+6, baseX+7, baseY+6, color8, color16, pDestBuf );
|
|
DrawLine( baseX+3, baseY+8, baseX+7, baseY+8, color8, color16, pDestBuf );
|
|
break;
|
|
case 4:
|
|
DrawLine( baseX+3, baseY+5, baseX+5, baseY+8, color8, color16, pDestBuf );
|
|
DrawLine( baseX+5, baseY+8, baseX+7, baseY+5, color8, color16, pDestBuf );
|
|
break;
|
|
case 5:
|
|
DrawLine( baseX+3, baseY+4, baseX+7, baseY+4, color8, color16, pDestBuf );
|
|
DrawLine( baseX+3, baseY+6, baseX+5, baseY+9, color8, color16, pDestBuf );
|
|
DrawLine( baseX+5, baseY+9, baseX+7, baseY+6, color8, color16, pDestBuf );
|
|
break;
|
|
case 6:
|
|
DrawLine( baseX+5, baseY+4, baseX+5, baseY+8, color8, color16, pDestBuf );
|
|
break;
|
|
case 7:
|
|
DrawLine( baseX+4, baseY+4, baseX+4, baseY+8, color8, color16, pDestBuf );
|
|
DrawLine( baseX+6, baseY+4, baseX+6, baseY+8, color8, color16, pDestBuf );
|
|
break;
|
|
case 8:
|
|
DrawLine( baseX+5, baseY+4, baseX+5, baseY+8, color8, color16, pDestBuf );
|
|
DrawLine( baseX+3, baseY+4, baseX+3, baseY+8, color8, color16, pDestBuf );
|
|
DrawLine( baseX+7, baseY+4, baseX+7, baseY+8, color8, color16, pDestBuf );
|
|
break;
|
|
case 9:
|
|
DrawLine( baseX+2, baseY+6, baseX+8, baseY+6, color8, color16, pDestBuf );
|
|
DrawLine( baseX+5, baseY+3, baseX+5, baseY+9, color8, color16, pDestBuf );
|
|
DrawLine( baseX+3, baseY+4, baseX+7, baseY+8, color8, color16, pDestBuf );
|
|
DrawLine( baseX+7, baseY+4, baseX+3, baseY+8, color8, color16, pDestBuf );
|
|
}
|
|
|
|
UnLockVideoSurface( FRAME_BUFFER );
|
|
}
|
|
|
|
void DrawItemPic(INVTYPE *pItem, INT16 sX, INT16 sY )
|
|
{
|
|
UINT16 usGraphicNum;
|
|
|
|
usGraphicNum = g_bUsePngItemImages ? 0 : pItem->ubGraphicNum;
|
|
|
|
HVOBJECT hVObject;
|
|
ETRLEObject *pTrav;
|
|
GetVideoObject( &hVObject, GetInterfaceGraphicForItem( pItem ) );
|
|
pTrav = &(hVObject->pETRLEObject[ usGraphicNum ] );
|
|
|
|
BltVideoObjectOutlineFromIndex( FRAME_BUFFER, GetInterfaceGraphicForItem( pItem ), usGraphicNum, sX - pTrav->sOffsetX, sY - pTrav->sOffsetY, Get16BPPColor( FROMRGB( 255, 255, 255 ) ), FALSE );
|
|
}
|
|
|
|
void GetItemDimensions( INVTYPE *pItem, INT16 &sWidth, INT16 &sHeight )
|
|
{
|
|
HVOBJECT hVObject;
|
|
ETRLEObject *pTrav;
|
|
UINT16 usGraphicNum;
|
|
|
|
usGraphicNum = g_bUsePngItemImages ? 0 : pItem->ubGraphicNum;
|
|
GetVideoObject( &hVObject, GetInterfaceGraphicForItem( pItem ) );
|
|
pTrav = &(hVObject->pETRLEObject[ usGraphicNum ] );
|
|
|
|
sWidth = (UINT32)(pTrav->usWidth);
|
|
sHeight = (UINT32)(pTrav->usHeight);
|
|
}
|
|
|
|
BOOLEAN ShowExactInfo( SOLDIERTYPE* pSoldier, SOLDIERTYPE* pTargetSoldier )
|
|
{
|
|
INT32 range;
|
|
INT32 maxExactWeaponDistance;
|
|
|
|
if( pTargetSoldier->bVisible == -1 )
|
|
return FALSE;
|
|
|
|
range = GetRangeInCellCoordsFromGridNoDiff( pSoldier->sGridNo, pTargetSoldier->sGridNo ) / 10;
|
|
|
|
// visible distance
|
|
maxExactWeaponDistance = (INT32)( pSoldier->GetMaxDistanceVisible( pTargetSoldier->sGridNo, 0, CALC_FROM_WANTED_DIR) ) / 2 ;
|
|
|
|
// apply experience level factor
|
|
maxExactWeaponDistance = (INT32)( maxExactWeaponDistance * ( 1 + FLOAT( EffectiveExpLevel( pSoldier ) ) / 10.0f ) );
|
|
|
|
if ( maxExactWeaponDistance >= range )
|
|
return TRUE;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
void DrawNCTHCursorItemPics( INT16 sStartScreenX, INT16 sStartScreenY )
|
|
{
|
|
// find target soldier
|
|
SOLDIERTYPE *pSoldier;
|
|
SOLDIERTYPE *pTargetSoldier;
|
|
INT32 usItemID = 0;
|
|
INT16 sX, sY, sWidth, sHeight;
|
|
INT16 sXOffset = 0;
|
|
|
|
GetSoldier( &pSoldier, gusSelectedSoldier );
|
|
GetSoldier( &pTargetSoldier, gusUIFullTargetID );
|
|
|
|
// zero rects
|
|
RightRect.left = 0; RightRect.top = 0; RightRect.right = 0; RightRect.bottom = 0;
|
|
LeftRect.left = 0; LeftRect.top = 0; LeftRect.right = 0; LeftRect.bottom = 0;
|
|
LeftRect2.left = 0; LeftRect2.top = 0; LeftRect2.right = 0; LeftRect2.bottom = 0;
|
|
|
|
if( gGameExternalOptions.ubAdditionalNCTHCursorInfo &&
|
|
gfUIBodyHitLocation &&
|
|
pSoldier->ubBodyType <= REGFEMALE &&
|
|
_KeyDown( ALT ) &&
|
|
ShowExactInfo( pSoldier, pTargetSoldier) )
|
|
{
|
|
// show armour
|
|
switch( pSoldier->bAimShotLocation )
|
|
{
|
|
case AIM_SHOT_HEAD:
|
|
if( pTargetSoldier->inv[HELMETPOS].exists() )
|
|
usItemID = pTargetSoldier->inv[HELMETPOS].usItem;
|
|
break;
|
|
case AIM_SHOT_TORSO:
|
|
if( pTargetSoldier->inv[VESTPOS].exists() )
|
|
usItemID = pTargetSoldier->inv[VESTPOS].usItem;
|
|
break;
|
|
case AIM_SHOT_LEGS:
|
|
if( pTargetSoldier->inv[LEGPOS].exists() )
|
|
usItemID = pTargetSoldier->inv[LEGPOS].usItem;
|
|
break;
|
|
}
|
|
if( usItemID )
|
|
{
|
|
sX = sStartScreenX+25;
|
|
sY = sStartScreenY-3;
|
|
DrawItemPic( &(Item[ usItemID ] ), sX, sY );
|
|
GetItemDimensions( &(Item[ usItemID ]), sWidth, sHeight );
|
|
RightRect.left = sX;
|
|
RightRect.top = sY;
|
|
RightRect.right = sX + sWidth;
|
|
RightRect.bottom = sY + sHeight;
|
|
}
|
|
|
|
if( gGameExternalOptions.ubAdditionalNCTHCursorInfo > 1 )
|
|
{
|
|
// show item in hands
|
|
if( pSoldier->bAimShotLocation == AIM_SHOT_TORSO )
|
|
{
|
|
if( pTargetSoldier->inv[HANDPOS].exists() )
|
|
{
|
|
usItemID = pTargetSoldier->inv[HANDPOS].usItem;
|
|
GetItemDimensions( &(Item[ usItemID ]), sWidth, sHeight );
|
|
if( sWidth > 30 )
|
|
sXOffset = 10;
|
|
sX = sStartScreenX - 25 - sWidth + sXOffset;
|
|
sY = sStartScreenY - 3;
|
|
DrawItemPic(&(Item[ usItemID ] ), sX, sY );
|
|
LeftRect.left = sX;
|
|
LeftRect.top = sY;
|
|
LeftRect.right = sX + sWidth;
|
|
LeftRect.bottom = sY + sHeight;
|
|
}
|
|
}
|
|
// show items in head slots
|
|
else if( pSoldier->bAimShotLocation == AIM_SHOT_HEAD )
|
|
{
|
|
if( pTargetSoldier->inv[HEAD2POS].exists() )
|
|
{
|
|
usItemID = pTargetSoldier->inv[HEAD2POS].usItem;
|
|
GetItemDimensions( &(Item[ usItemID ]), sWidth, sHeight );
|
|
sX = sStartScreenX - 25 - sWidth;
|
|
sY = sStartScreenY - 3;
|
|
DrawItemPic(&(Item[ usItemID ] ), sX, sY );
|
|
LeftRect.left = sX;
|
|
LeftRect.top = sY;
|
|
LeftRect.right = sX + sWidth;
|
|
LeftRect.bottom = sY + sHeight;
|
|
}
|
|
|
|
if( pTargetSoldier->inv[HEAD1POS].exists() )
|
|
{
|
|
usItemID = pTargetSoldier->inv[HEAD1POS].usItem;
|
|
GetItemDimensions( &(Item[ usItemID ]), sWidth, sHeight );
|
|
sX = sStartScreenX - 25 - sWidth;
|
|
sY = sStartScreenY - 3;
|
|
if( pTargetSoldier->inv[HEAD2POS].exists() )
|
|
sX -= LeftRect.right - LeftRect.left;
|
|
DrawItemPic(&(Item[ usItemID ] ), sX, sY );
|
|
LeftRect2.left = sX;
|
|
LeftRect2.top = sY;
|
|
LeftRect2.right = sX + sWidth;
|
|
LeftRect2.bottom = sY + sHeight;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void GetEnemyInfoString( SOLDIERTYPE* pSelectedSoldier, SOLDIERTYPE* pTargetSoldier, BOOLEAN showExactInfo, CHAR16 *NameStr )
|
|
{
|
|
UINT16 usItemID;
|
|
|
|
// if ALT pressed - show armour instead of weapon
|
|
if( gfUIBodyHitLocation &&
|
|
_KeyDown( ALT ) )
|
|
{
|
|
SetFontForeground( FONT_YELLOW );
|
|
// show armour
|
|
usItemID = 0;
|
|
switch( pSelectedSoldier->bAimShotLocation )
|
|
{
|
|
case AIM_SHOT_HEAD:
|
|
if( pTargetSoldier->inv[HELMETPOS].exists() )
|
|
usItemID = pTargetSoldier->inv[HELMETPOS].usItem;
|
|
break;
|
|
case AIM_SHOT_TORSO:
|
|
if( pTargetSoldier->inv[VESTPOS].exists() )
|
|
usItemID = pTargetSoldier->inv[VESTPOS].usItem;
|
|
break;
|
|
case AIM_SHOT_LEGS:
|
|
if( pTargetSoldier->inv[LEGPOS].exists() )
|
|
usItemID = pTargetSoldier->inv[LEGPOS].usItem;
|
|
break;
|
|
}
|
|
if( usItemID )
|
|
{
|
|
if( showExactInfo && gGameExternalOptions.fShowEnemyExtendedInfo )
|
|
{ // in range, show exact armour name
|
|
swprintf( NameStr, L"%s", ItemNames[ usItemID ] );
|
|
}
|
|
else
|
|
{ // show general armour type
|
|
switch( pSelectedSoldier->bAimShotLocation )
|
|
{
|
|
case AIM_SHOT_HEAD:
|
|
swprintf( NameStr, L"%s", gzTooltipStrings[STR_TT_HELMET] );
|
|
//swprintf( NameStr, L"%s", L"Helmet" );
|
|
break;
|
|
case AIM_SHOT_TORSO:
|
|
swprintf( NameStr, L"%s", gzTooltipStrings[STR_TT_VEST] );
|
|
//swprintf( NameStr, L"%s", L"Vest" );
|
|
break;
|
|
case AIM_SHOT_LEGS:
|
|
swprintf( NameStr, L"%s", gzTooltipStrings[STR_TT_LEGGINGS] );
|
|
//swprintf( NameStr, L"%s", L"Leggings" );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( gfUIBodyHitLocation &&
|
|
pSelectedSoldier->bAimShotLocation == AIM_SHOT_HEAD )
|
|
{
|
|
// show face items
|
|
SetFontForeground( FONT_ORANGE );
|
|
if( pTargetSoldier->inv[HEAD1POS].exists() )
|
|
{
|
|
if(gGameExternalOptions.fShowEnemyExtendedInfo)
|
|
{ // show exact name
|
|
wcscat( NameStr, ItemNames[ pTargetSoldier->inv[HEAD1POS].usItem ] );
|
|
}
|
|
else
|
|
{ // show general name
|
|
if( Item[pTargetSoldier->inv[HEAD1POS].usItem].gasmask )
|
|
wcscat( NameStr, TacticalStr[ GENERAL_INFO_MASK ] );
|
|
else if( Item[pTargetSoldier->inv[HEAD1POS].usItem].nightvisionrangebonus || Item[pTargetSoldier->inv[HEAD1POS].usItem].cavevisionrangebonus )
|
|
wcscat( NameStr, TacticalStr[ GENERAL_INFO_NVG ] );
|
|
}
|
|
}
|
|
if( pTargetSoldier->inv[HEAD2POS].exists() )
|
|
{
|
|
if( pTargetSoldier->inv[HEAD1POS].exists() )
|
|
wcscat( NameStr, L", " );
|
|
if(gGameExternalOptions.fShowEnemyExtendedInfo)
|
|
{ // show exact name
|
|
wcscat( NameStr, ItemNames[ pTargetSoldier->inv[HEAD2POS].usItem ] );
|
|
}
|
|
else
|
|
{ // show general name
|
|
if( Item[pTargetSoldier->inv[HEAD1POS].usItem].gasmask )
|
|
wcscat( NameStr, TacticalStr[ GENERAL_INFO_MASK ] );
|
|
else if( Item[pTargetSoldier->inv[HEAD1POS].usItem].nightvisionrangebonus || Item[pTargetSoldier->inv[HEAD1POS].usItem].cavevisionrangebonus )
|
|
wcscat( NameStr, TacticalStr[ GENERAL_INFO_NVG ] );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// show weapon
|
|
SetFontForeground( FONT_ORANGE );
|
|
if ( WeaponInHand( pTargetSoldier ) )
|
|
{
|
|
if ( showExactInfo )
|
|
{
|
|
swprintf( NameStr, L"%s", ShortItemNames[ pTargetSoldier->inv[ HANDPOS ].usItem ] );
|
|
}
|
|
else
|
|
{
|
|
// display general weapon class
|
|
switch( Weapon[pTargetSoldier->inv[ HANDPOS ].usItem].ubWeaponClass )
|
|
{
|
|
case HANDGUNCLASS:
|
|
swprintf( NameStr, L"%s", gzTooltipStrings[STR_TT_HANDGUN] );
|
|
break;
|
|
case SMGCLASS:
|
|
swprintf( NameStr, L"%s", gzTooltipStrings[STR_TT_SMG] );
|
|
break;
|
|
case RIFLECLASS:
|
|
swprintf( NameStr, L"%s", gzTooltipStrings[STR_TT_RIFLE] );
|
|
break;
|
|
case MGCLASS:
|
|
swprintf( NameStr, L"%s", gzTooltipStrings[STR_TT_MG] );
|
|
break;
|
|
case SHOTGUNCLASS:
|
|
swprintf( NameStr, L"%s", gzTooltipStrings[STR_TT_SHOTGUN] );
|
|
break;
|
|
case KNIFECLASS:
|
|
swprintf( NameStr, L"%s", gzTooltipStrings[STR_TT_KNIFE] );
|
|
break;
|
|
default:
|
|
swprintf( NameStr, L"%s", gzTooltipStrings[STR_TT_HEAVY_WEAPON] );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( showExactInfo )
|
|
{
|
|
if( pTargetSoldier->inv[ HANDPOS ].usItem )
|
|
swprintf( NameStr, L"%s", Item[ pTargetSoldier->inv[ HANDPOS ].usItem ].szItemName );
|
|
else
|
|
swprintf( NameStr, L"%s", gzTooltipStrings[STR_TT_NO_WEAPON] );
|
|
}
|
|
else
|
|
{
|
|
if( pTargetSoldier->inv[ HANDPOS ].usItem )
|
|
swprintf( NameStr, L"%s", TacticalStr[ GENERAL_INFO_ITEM ] );
|
|
else
|
|
swprintf( NameStr, L"%s", L"" );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void ShowEnemyWeapon( INT16 sX, INT16 sY, SOLDIERTYPE* pTargetSoldier )
|
|
{
|
|
SOLDIERTYPE *pSelectedSoldier;
|
|
BOOLEAN showExactInfo = FALSE;
|
|
CHAR16 NameStr[ MAX_ENEMY_NAMES_CHARS ];
|
|
UINT16 usTotalWidth;
|
|
INT32 iRange;
|
|
INT32 iVisibleDistance;
|
|
|
|
if ( gusSelectedSoldier != NOBODY )
|
|
pSelectedSoldier = MercPtrs[ gusSelectedSoldier ];
|
|
else
|
|
return;
|
|
|
|
if( gGameExternalOptions.fEnemyRank || gGameExternalOptions.fEnemyNames )
|
|
return;
|
|
|
|
iRange = GetRangeInCellCoordsFromGridNoDiff( pSelectedSoldier->sGridNo, pTargetSoldier->sGridNo ) / 10;
|
|
iVisibleDistance = (INT32)( pSelectedSoldier->GetMaxDistanceVisible( pTargetSoldier->sGridNo, 0, CALC_FROM_WANTED_DIR) ) ;
|
|
|
|
if( iRange > iVisibleDistance )
|
|
return;
|
|
|
|
if( !pTargetSoldier->bVisible )
|
|
return;
|
|
|
|
// calc max range for exact info
|
|
if ( gusSelectedSoldier != NOBODY )
|
|
showExactInfo = ShowExactInfo( pSelectedSoldier, pTargetSoldier );
|
|
|
|
// show weapon/armour/items info
|
|
if ( gGameExternalOptions.fShowEnemyWeapon && gTacticalStatus.ubCurrentTeam == OUR_TEAM && pTargetSoldier->ubBodyType <= REGFEMALE )
|
|
{
|
|
SetFont( TINYFONT1 );
|
|
SetFontBackground( FONT_MCOLOR_BLACK );
|
|
|
|
swprintf( NameStr, L"" );
|
|
GetEnemyInfoString( pSelectedSoldier, pTargetSoldier, showExactInfo, NameStr );
|
|
usTotalWidth = StringPixLength ( NameStr, TINYFONT1 );
|
|
sX -= usTotalWidth/2;
|
|
|
|
// print item name
|
|
gprintfdirty( sX, sY + 10, NameStr );
|
|
mprintf( sX, sY + 10, NameStr );
|
|
}
|
|
}
|
|
|
|
void ShowAdditionalInfo( INT16 sX, INT16 sY, SOLDIERTYPE* pTargetSoldier )
|
|
{
|
|
BOOLEAN showExactInfo;
|
|
CHAR16 NameStr[ MAX_ENEMY_NAMES_CHARS ];
|
|
SOLDIERTYPE *pSelectedSoldier;
|
|
|
|
if ( gusSelectedSoldier != NOBODY )
|
|
pSelectedSoldier = MercPtrs[ gusSelectedSoldier ];
|
|
else
|
|
return;
|
|
|
|
if( gGameExternalOptions.fEnemyRank || gGameExternalOptions.fEnemyNames )
|
|
return;
|
|
|
|
// calc max range for exact info
|
|
if ( gusSelectedSoldier != NOBODY )
|
|
showExactInfo = ShowExactInfo( pSelectedSoldier, pTargetSoldier );
|
|
|
|
sX -= StringPixLength ( L"*", TINYFONT1 );
|
|
if( gGameExternalOptions.fShowEnemyAwareness && gTacticalStatus.ubCurrentTeam == OUR_TEAM )
|
|
{
|
|
SetFont( TINYFONT1 );
|
|
SetFontBackground( FONT_MCOLOR_BLACK );
|
|
// show awareness sign only when in stealth mode or disguised
|
|
if( ( gusSelectedSoldier != NOBODY ) &&
|
|
( pTargetSoldier->bTeam == ENEMY_TEAM || pTargetSoldier->bTeam == CIV_TEAM && !pTargetSoldier->aiData.bNeutral ) &&
|
|
( MercPtrs[ gusSelectedSoldier ]->bStealthMode || MercPtrs[ gusSelectedSoldier ]->bSoldierFlagMask & ( SOLDIER_COVERT_CIV | SOLDIER_COVERT_SOLDIER ) ) )
|
|
{
|
|
if( pTargetSoldier->aiData.bOppList[ MercPtrs[ gusSelectedSoldier ]->ubID ] == SEEN_CURRENTLY )
|
|
swprintf( NameStr, L"%s", L"*" );
|
|
else
|
|
swprintf( NameStr, L"%s", L"-" );
|
|
|
|
SetFontForeground( FONT_GRAY1 );
|
|
switch ( pTargetSoldier->aiData.bAlertStatus )
|
|
{
|
|
case STATUS_GREEN: // everything's OK, no suspicion
|
|
SetFontForeground( FONT_GREEN );
|
|
break;
|
|
case STATUS_YELLOW: // he or his friend heard something
|
|
SetFontForeground( FONT_YELLOW );
|
|
break;
|
|
case STATUS_RED: // has definite evidence of opponent
|
|
SetFontForeground( FONT_ORANGE );
|
|
break;
|
|
case STATUS_BLACK: // currently sees an active opponent
|
|
SetFontForeground( FONT_DKRED );
|
|
break;
|
|
}
|
|
|
|
if ( showExactInfo )
|
|
{
|
|
// this feature is a part of 'show enemy health bar'
|
|
if( gGameExternalOptions.ubShowEnemyHealth > 1 )
|
|
{
|
|
gprintfdirty( sX - 15, sY, NameStr );
|
|
mprintf( sX - 15, sY, NameStr );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void ShowEnemyHealthBar( INT16 sX, INT16 sY, SOLDIERTYPE* pSoldier )
|
|
{
|
|
INT32 iBack;
|
|
UINT8 ubLines = gGameExternalOptions.ubShowEnemyHealth - 1;
|
|
INT32 iBarWidth = 24;
|
|
INT32 iBarHeight;
|
|
SOLDIERTYPE *pSelectedSoldier;
|
|
|
|
if ( gusSelectedSoldier != NOBODY )
|
|
pSelectedSoldier = MercPtrs[ gusSelectedSoldier ];
|
|
else
|
|
return;
|
|
|
|
if ( pSelectedSoldier->aiData.bOppList[pSoldier->ubID] != SEEN_CURRENTLY )
|
|
return;
|
|
|
|
// show enemy health bar
|
|
if( gGameExternalOptions.ubShowEnemyHealth > 1 && gTacticalStatus.ubCurrentTeam == OUR_TEAM )
|
|
{
|
|
iBarHeight = 2 + 3 * ubLines - 1;
|
|
sY += 10;
|
|
sY -= iBarHeight;
|
|
sX -= iBarWidth / 2;
|
|
|
|
iBack = RegisterBackgroundRect(BGND_FLAG_SINGLE, NULL, sX, sY, (INT16)(sX + iBarWidth), (INT16)(sY + iBarHeight ) );
|
|
if ( iBack != -1 )
|
|
SetBackgroundRectFilled( iBack );
|
|
|
|
DrawEnemyHealthBar( pSoldier, sX, sY, ubLines, iBarWidth - 2, iBarHeight );
|
|
}
|
|
}
|
|
|
|
void ShowRankIcon( INT16 sXPos, INT16 sYPos, SOLDIERTYPE* pSoldier )
|
|
{
|
|
INT32 iBack;
|
|
INT16 sX, sY;
|
|
SOLDIERTYPE *pSelectedSoldier;
|
|
|
|
if ( gusSelectedSoldier != NOBODY )
|
|
pSelectedSoldier = MercPtrs[ gusSelectedSoldier ];
|
|
else
|
|
return;
|
|
|
|
if ( pSelectedSoldier->aiData.bOppList[pSoldier->ubID] != SEEN_CURRENTLY )
|
|
return;
|
|
|
|
if( gGameExternalOptions.ubShowEnemyRankIcon && gTacticalStatus.ubCurrentTeam == OUR_TEAM )
|
|
//&& (!gGameExternalOptions.fEnemyNames) && (!gGameExternalOptions.fEnemyRank))
|
|
{
|
|
sX = sXPos + 50;
|
|
sY = sYPos + 17;
|
|
if(gGameExternalOptions.fEnemyNames)
|
|
sY+=10;
|
|
if(gGameExternalOptions.fEnemyRank)
|
|
sY+=10;
|
|
|
|
iBack = RegisterBackgroundRect(BGND_FLAG_SINGLE, NULL, sX, sY, (INT16)(sX + 11 ), (INT16)(sY + 14 ) );
|
|
if ( iBack != -1 )
|
|
SetBackgroundRectFilled( iBack );
|
|
|
|
DrawRankIcon( pSoldier->stats.bExpLevel, sX, sY );
|
|
}
|
|
}
|
|
|
|
void DrawLine( INT32 x1, INT32 y1, INT32 x2, INT32 y2, UINT16 color8, UINT16 color16, UINT8 *pDestBuf )
|
|
{
|
|
if(gbPixelDepth==16)
|
|
LineDraw( TRUE, x1, y1, x2, y2, color16, pDestBuf);
|
|
else
|
|
LineDraw8( TRUE, x1, y1, x2, y2, color8, pDestBuf);
|
|
}
|
|
|
|
void DrawEnemyHealthBar( SOLDIERTYPE* pSoldier, INT32 sX, INT32 sY, UINT8 ubLines, INT32 iBarWidth, INT32 iBarHeight )
|
|
{
|
|
FLOAT dWidth, dPercentage;
|
|
UINT32 uiDestPitchBYTES;
|
|
UINT8 *pDestBuf;
|
|
INT32 sHeight = 2;
|
|
|
|
pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES );
|
|
SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, gsVIEWPORT_WINDOW_START_Y, SCREEN_WIDTH, ( gsVIEWPORT_WINDOW_END_Y - gsVIEWPORT_WINDOW_START_Y ) );
|
|
|
|
// sevenfm: draw background
|
|
DrawBar( sX, sY, iBarWidth + 2, iBarHeight, COLOR_BLACK, Get16BPPColor( FROMRGB( 0, 0, 0 ) ), pDestBuf );
|
|
|
|
// draw health
|
|
if(ubLines > 0)
|
|
{
|
|
dPercentage = (FLOAT)pSoldier->stats.bLife / (FLOAT) pSoldier->stats.bLifeMax;
|
|
dWidth = dPercentage * iBarWidth;
|
|
dWidth = __min (dWidth, iBarWidth);
|
|
DrawBar( sX + 1, sY + 1, (INT32)dWidth, sHeight, COLOR_RED, Get16BPPColor( FROMRGB( 200, 0, 0 ) ), pDestBuf );
|
|
}
|
|
|
|
// draw ap
|
|
if(ubLines > 1)
|
|
{
|
|
if( pSoldier->bActionPoints >0 )
|
|
{
|
|
//dPercentage = (FLOAT)pSoldier->bActionPoints / (FLOAT) ( pSoldier->bActionPoints + pSoldier->ubAPsLostToSuppression + pSoldier->u);
|
|
dPercentage = (FLOAT)pSoldier->bActionPoints / (FLOAT) ( pSoldier->bInitialActionPoints);
|
|
dWidth = dPercentage * iBarWidth;
|
|
dWidth = __min (dWidth, iBarWidth);
|
|
//DrawBar( sX + 1, sY + 1 + (sHeight+1), (INT32)dWidth, sHeight, COLOR_BLUE, Get16BPPColor( FROMRGB( 20, 20, 220 ) ), pDestBuf );
|
|
DrawBar( sX + 1, sY + 1 + (sHeight+1), (INT32)dWidth, sHeight, COLOR_PURPLE, Get16BPPColor( FROMRGB( 110, 30, 210 ) ), pDestBuf );
|
|
}
|
|
else
|
|
{
|
|
dPercentage = (FLOAT)pSoldier->bActionPoints / (FLOAT) ( APBPConstants[AP_MIN_LIMIT] );
|
|
dWidth = dPercentage * iBarWidth;
|
|
dWidth = __min (dWidth, iBarWidth);
|
|
DrawBar( sX + 1, sY + 1 + (sHeight+1), (INT32)dWidth, sHeight, COLOR_LTGREY, Get16BPPColor( FROMRGB( 140, 140, 140 ) ), pDestBuf );
|
|
}
|
|
}
|
|
|
|
// draw suppression shock
|
|
if( ubLines > 2 )
|
|
{
|
|
dPercentage = (FLOAT)( __min(100, ( (FLOAT)100 * CalcEffectiveShockLevel( pSoldier ) ) / CalcSuppressionTolerance( pSoldier ) ) ) / (FLOAT)100;
|
|
dWidth = dPercentage * iBarWidth;
|
|
dWidth = __min (dWidth, iBarWidth);
|
|
DrawBar( sX+1, sY + 1 + 2*(sHeight+1), (INT32)dWidth, sHeight, COLOR_ORANGE, Get16BPPColor( FROMRGB( 200, 120, 0 ) ), pDestBuf );
|
|
}
|
|
|
|
// draw morale
|
|
if( ubLines > 3 )
|
|
{
|
|
dPercentage = (FLOAT)( pSoldier->aiData.bAIMorale ) / (FLOAT)( MORALE_FEARLESS );
|
|
//dPercentage = (FLOAT)( pSoldier->aiData.bMorale ) / (FLOAT)( 100 );
|
|
dWidth = dPercentage * iBarWidth;
|
|
dWidth = __min (dWidth, iBarWidth);
|
|
DrawBar( sX+1, sY + 1 + 3*(sHeight+1), (INT32)dWidth, sHeight, COLOR_GREEN, Get16BPPColor( FROMRGB( 0, 140, 0 ) ), pDestBuf );
|
|
}
|
|
|
|
// draw BP
|
|
if( ubLines > 4 )
|
|
{
|
|
dPercentage = (FLOAT)( pSoldier->bBreath ) / (FLOAT)( pSoldier->bBreathMax );
|
|
dWidth = dPercentage * iBarWidth;
|
|
dWidth = __min (dWidth, iBarWidth);
|
|
DrawBar( sX+1, sY + 1 + 4*(sHeight+1), (INT32)dWidth, sHeight, COLOR_BLUE, Get16BPPColor( FROMRGB( 0, 0, 200 ) ), pDestBuf );
|
|
}
|
|
|
|
UnLockVideoSurface( FRAME_BUFFER );
|
|
}
|
|
|
|
// Flugente: show enemy role
|
|
BOOLEAN ShowSoldierRoleSymbol(SOLDIERTYPE* pSoldier)
|
|
{
|
|
// this only works on enemy soldiers
|
|
if ( pSoldier->bTeam != ENEMY_TEAM )
|
|
return false;
|
|
|
|
if ( pSoldier->usSkillCounter[SOLDIER_COUNTER_ROLE_OBSERVED] < gGameExternalOptions.usTurnsToUncover )
|
|
return false;
|
|
|
|
INT16 sXPos = 0;
|
|
INT16 sYPos = 0;
|
|
INT32 iBack = 0;
|
|
|
|
GetSoldierAboveGuyPositions( pSoldier, &sXPos, &sYPos, TRUE );
|
|
|
|
// Adjust for bars!
|
|
sXPos += 50;
|
|
sYPos += 25;
|
|
|
|
// is this guy an officer?
|
|
if ( pSoldier->bSoldierFlagMask & SOLDIER_ENEMY_OFFICER )
|
|
{
|
|
// Add bars
|
|
iBack = RegisterBackgroundRect( BGND_FLAG_SINGLE, NULL, sXPos, sYPos, (INT16)(sXPos + 20 ), (INT16)(sYPos + 20 ) );
|
|
|
|
if ( iBack != -1 )
|
|
{
|
|
SetBackgroundRectFilled( iBack );
|
|
}
|
|
|
|
BltVideoObjectFromIndex( FRAME_BUFFER, guiENEMYROLES, 0, sXPos, sYPos, VO_BLT_TRANSSHADOW, NULL );
|
|
|
|
sYPos += 20;
|
|
}
|
|
|
|
// is this guy radio operator with a radio?
|
|
if ( pSoldier->CanUseRadio(false) )
|
|
{
|
|
// Add bars
|
|
iBack = RegisterBackgroundRect( BGND_FLAG_SINGLE, NULL, sXPos, sYPos, (INT16)(sXPos + 20 ), (INT16)(sYPos + 20 ) );
|
|
|
|
if ( iBack != -1 )
|
|
{
|
|
SetBackgroundRectFilled( iBack );
|
|
}
|
|
|
|
BltVideoObjectFromIndex( FRAME_BUFFER, guiENEMYROLES, 3, sXPos, sYPos, VO_BLT_TRANSSHADOW, NULL );
|
|
|
|
sYPos += 20;
|
|
}
|
|
|
|
// is this guy a doctor? we do not check for medical gear, as we would not have that information from a glance
|
|
if ( HAS_SKILL_TRAIT( pSoldier, DOCTOR_NT) )
|
|
{
|
|
// Add bars
|
|
iBack = RegisterBackgroundRect( BGND_FLAG_SINGLE, NULL, sXPos, sYPos, (INT16)(sXPos + 20 ), (INT16)(sYPos + 20 ) );
|
|
|
|
if ( iBack != -1 )
|
|
{
|
|
SetBackgroundRectFilled( iBack );
|
|
}
|
|
|
|
BltVideoObjectFromIndex( FRAME_BUFFER, guiENEMYROLES, 1, sXPos, sYPos, VO_BLT_TRANSSHADOW, NULL );
|
|
|
|
sYPos += 20;
|
|
}
|
|
|
|
// is this guy a sniper? Just check for the gun, trait is not necessary
|
|
if ( pSoldier->HasSniper() )
|
|
{
|
|
// Add bars
|
|
iBack = RegisterBackgroundRect( BGND_FLAG_SINGLE, NULL, sXPos, sYPos, (INT16)(sXPos + 20 ), (INT16)(sYPos + 20 ) );
|
|
|
|
if ( iBack != -1 )
|
|
{
|
|
SetBackgroundRectFilled( iBack );
|
|
}
|
|
|
|
BltVideoObjectFromIndex( FRAME_BUFFER, guiENEMYROLES, 2, sXPos, sYPos, VO_BLT_TRANSSHADOW, NULL );
|
|
|
|
sYPos += 20;
|
|
}
|
|
|
|
// is this guy a mortar guy? Just check for the gun, trait is not necessary
|
|
if ( pSoldier->HasMortar() )
|
|
{
|
|
// Add bars
|
|
iBack = RegisterBackgroundRect( BGND_FLAG_SINGLE, NULL, sXPos, sYPos, (INT16)(sXPos + 20 ), (INT16)(sYPos + 20 ) );
|
|
|
|
if ( iBack != -1 )
|
|
{
|
|
SetBackgroundRectFilled( iBack );
|
|
}
|
|
|
|
BltVideoObjectFromIndex( FRAME_BUFFER, guiENEMYROLES, 4, sXPos, sYPos, VO_BLT_TRANSSHADOW, NULL );
|
|
|
|
sYPos += 20;
|
|
}
|
|
|
|
return true;
|
|
}
|