mirror of
https://github.com/1dot13/source.git
synced 2026-07-22 13:40:22 +02:00
git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@2650 3b4a5df2-a311-0410-b5c6-a8a6f20db521
6473 lines
163 KiB
C++
6473 lines
163 KiB
C++
#include "connect.h"
|
|
#ifdef PRECOMPILEDHEADERS
|
|
#include "Tactical All.h"
|
|
#include "BuildDefines.h"
|
|
|
|
#else
|
|
#include "builddefines.h"
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include "wcheck.h"
|
|
#include "stdlib.h"
|
|
#include "debug.h"
|
|
#include "math.h"
|
|
#include "jascreens.h"
|
|
#include "pathai.h"
|
|
#include "Soldier Control.h"
|
|
#include "Animation Control.h"
|
|
#include "Animation Data.h"
|
|
#include "Event Pump.h"
|
|
#include "Timer Control.h"
|
|
#include "mousesystem.h"
|
|
#include "cursors.h"
|
|
#include "Handle UI.h"
|
|
#include "Isometric Utils.h"
|
|
#include "input.h"
|
|
#include "overhead.h"
|
|
#include "Sys Globals.h"
|
|
#include "screenids.h"
|
|
#include "interface.h"
|
|
#include "cursor control.h"
|
|
#include "points.h"
|
|
#include "Interactive Tiles.h"
|
|
#include "interface cursors.h"
|
|
#include "opplist.h"
|
|
#include "worldman.h"
|
|
#include "weapons.h"
|
|
#include "Sound Control.h"
|
|
#include "renderworld.h"
|
|
#include "structure.h"
|
|
#include "interface panels.h"
|
|
#include "weapons.h"
|
|
#include "Handle items.h"
|
|
#include "UI cursors.h"
|
|
#include "Handle UI plan.h"
|
|
#include "Message.h"
|
|
#include "Render fun.h"
|
|
#include "interface items.h"
|
|
#include "physics.h"
|
|
#include "Soldier Profile.h"
|
|
#include "strategicmap.h"
|
|
#include "soldier profile.h"
|
|
#include "soldier create.h"
|
|
#include "soldier add.h"
|
|
#include "interface dialogue.h"
|
|
#include "soldier macros.h"
|
|
#include "soldier functions.h"
|
|
#include "Assignments.h"
|
|
#include "squads.h"
|
|
#include "Strategic Pathing.h"
|
|
#include "strategic movement.h"
|
|
#include "strategic.h"
|
|
#include "exit grids.h"
|
|
#include "structure wrap.h"
|
|
#include "soldier add.h"
|
|
#include "Random.h"
|
|
#include "english.h"
|
|
#include "Random.h"
|
|
#include "english.h"
|
|
#include "vehicles.h"
|
|
#include "messageboxscreen.h"
|
|
#include "text.h"
|
|
#include "dialogue control.h"
|
|
#include "line.h"
|
|
#include "render dirty.h"
|
|
#include "GameSettings.h"
|
|
#include "los.h"
|
|
#include "Campaign Types.h"
|
|
#include "Queen Command.h"
|
|
#include "Options Screen.h"
|
|
#include "SaveLoadGame.h"
|
|
#include "Spread Burst.h"
|
|
#include "ai.h"
|
|
#include "Game Clock.h"
|
|
#include "civ quotes.h"
|
|
#include "Militia Control.h"
|
|
#include "qarray.h"
|
|
#include "environment.h"
|
|
#include "Map Information.h"
|
|
#include "Soldier Control.h"
|
|
#endif
|
|
|
|
#include "teamturns.h"
|
|
|
|
//extern BOOLEAN gfDisplayFullCountRingBurst;
|
|
extern UINT16 PickSoldierReadyAnimation( SOLDIERTYPE *pSoldier, BOOLEAN fEndReady );
|
|
|
|
//#define AP_TO_AIM_TILE_IF_GETTING_READY 1
|
|
#define AP_TO_AIM_TILE_IF_ALREADY_READY ( Weapon[ Item[pSoldier->inv[HANDPOS].usItem].ubClassIndex ].ubReadyTime ? 2 : 1 )
|
|
#define AP_TO_AIM_TILE_IF_GETTING_READY AP_TO_AIM_TILE_IF_ALREADY_READY
|
|
|
|
#define MAX_ON_DUTY_SOLDIERS 6
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
// UI SYSTEM DESCRIPTION
|
|
//
|
|
// The UI system here decouples event determination from event execution. IN other words,
|
|
// first any user input is gathered and analysed for an event to happen. Once the event is determined,
|
|
// it is then executed. For example, if the left mouse button is used to select a guy, it does not
|
|
// execute the code to selected the guy, rather it sets a flag to a particular event, in this case
|
|
// the I_SELECT_MERC event is set. The code then executes this event after all input is analysed. In
|
|
// this way, more than one input method from the user will cause the came event to occur and hence no
|
|
// duplication of code. Also, events have cetain charactoristics. The select merc event is executed just
|
|
// once and then returns to the previous event. Most events are set to run continuously until new
|
|
// input changes to another event. Other events have a 'SNAP-BACK' feature which snap the mouse back to
|
|
// it's position before the event was executed. Another issue is UI modes. In order to filter out input
|
|
// depending on other flags, for example we do not want to cancel the confirm when a user moves to another
|
|
// tile unless we are in the 'confirm' mode. This could be done by flags ( and in effect it is ) where
|
|
// if staements are used, but here at input collection time, we can switch on our current mode to handle
|
|
// input differently based on the mode. Doing it this way also allows us to group certain commands togther
|
|
// like menu commands which are initialized and deleted in the same manner.
|
|
//
|
|
// UI_EVENTS
|
|
/////////////
|
|
//
|
|
// UI_EVENTS have flags to itendtify themselves with special charactoristics, a UI_MODE catagory which
|
|
// signifies the UI mode this event will cause the system to move to. Also, a pointer to a handle function is
|
|
// used to actually handle the particular event. UI_EVENTS also have a couple of param variables and a number
|
|
// of boolean flags used during run-time to determine states of events.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// LOCAL DEFINES
|
|
#define GO_MOVE_ONE 40
|
|
#define GO_MOVE_TWO 80
|
|
#define GO_MOVE_THREE 100
|
|
|
|
|
|
// CALLBACKS FOR EVENTS
|
|
UINT32 UIHandleIDoNothing( UI_EVENT *pUIEvent );
|
|
UINT32 UIHandleExit( UI_EVENT *pUIEvent );
|
|
UINT32 UIHandleNewMerc( UI_EVENT *pUIEvent );
|
|
UINT32 UIHandleNewBadMerc( UI_EVENT *pUIEvent );
|
|
UINT32 UIHandleSelectMerc( UI_EVENT *pUIEvent );
|
|
UINT32 UIHandleEnterEditMode( UI_EVENT *pUIEvent );
|
|
UINT32 UIHandleEnterPalEditMode( UI_EVENT *pUIEvent );
|
|
UINT32 UIHandleEndTurn( UI_EVENT *pUIEvent );
|
|
UINT32 UIHandleTestHit( UI_EVENT *pUIEvent );
|
|
UINT32 UIHandleIOnTerrain( UI_EVENT *pUIEvent );
|
|
UINT32 UIHandleIChangeToIdle( UI_EVENT *pUIEvent );
|
|
UINT32 UIHandleILoadLevel( UI_EVENT *pUIEvent );
|
|
UINT32 UIHandleISoldierDebug( UI_EVENT *pUIEvent );
|
|
UINT32 UIHandleILOSDebug( UI_EVENT *pUIEvent );
|
|
UINT32 UIHandleILevelNodeDebug( UI_EVENT * pUIEvent );
|
|
UINT32 UIHandleIGotoDemoMode( UI_EVENT *pUIEvent );
|
|
|
|
|
|
|
|
UINT32 UIHandleILoadFirstLevel( UI_EVENT *pUIEvent );
|
|
UINT32 UIHandleILoadSecondLevel( UI_EVENT *pUIEvent );
|
|
UINT32 UIHandleILoadThirdLevel( UI_EVENT *pUIEvent );
|
|
UINT32 UIHandleILoadFourthLevel( UI_EVENT *pUIEvent );
|
|
UINT32 UIHandleILoadFifthLevel( UI_EVENT *pUIEvent );
|
|
|
|
UINT32 UIHandleIETOnTerrain( UI_EVENT *pUIEvent );
|
|
UINT32 UIHandleIETEndTurn( UI_EVENT *pUIEvent );
|
|
|
|
UINT32 UIHandleMOnTerrain( UI_EVENT *pUIEvent );
|
|
UINT32 UIHandleMChangeToAction( UI_EVENT *pUIEvent );
|
|
UINT32 UIHandleMCycleMovement( UI_EVENT *pUIEvent );
|
|
UINT32 UIHandleMCycleMoveAll( UI_EVENT *pUIEvent );
|
|
UINT32 UIHandleMAdjustStanceMode( UI_EVENT *pUIEvent );
|
|
UINT32 UIHandleMChangeToHandMode( UI_EVENT *pUIEvent );
|
|
|
|
UINT32 UIHandlePOPUPMSG( UI_EVENT *pUIEvent );
|
|
|
|
UINT32 UIHandleAOnTerrain( UI_EVENT *pUIEvent );
|
|
UINT32 UIHandleAChangeToMove( UI_EVENT *pUIEvent );
|
|
UINT32 UIHandleAChangeToConfirmAction( UI_EVENT *pUIEvent );
|
|
UINT32 UIHandleAEndAction( UI_EVENT *pUIEvent );
|
|
|
|
UINT32 UIHandleMovementMenu( UI_EVENT *pUIEvent );
|
|
UINT32 UIHandlePositionMenu( UI_EVENT *pUIEvent );
|
|
|
|
UINT32 UIHandleCWait( UI_EVENT *pUIEvent );
|
|
UINT32 UIHandleCMoveMerc( UI_EVENT *pUIEvent );
|
|
UINT32 UIHandleCOnTerrain( UI_EVENT *pUIEvent );
|
|
|
|
UINT32 UIHandlePADJAdjustStance( UI_EVENT *pUIEvent );
|
|
|
|
UINT32 UIHandleCAOnTerrain( UI_EVENT *pUIEvent );
|
|
UINT32 UIHandleCAMercShoot( UI_EVENT *pUIEvent );
|
|
UINT32 UIHandleCAEndConfirmAction( UI_EVENT *pUIEvent );
|
|
|
|
UINT32 UIHandleHCOnTerrain( UI_EVENT *pUIEvent );
|
|
UINT32 UIHandleHCGettingItem( UI_EVENT *pUIEvent );
|
|
|
|
|
|
UINT32 UIHandleLCOnTerrain( UI_EVENT *pUIEvent );
|
|
UINT32 UIHandleLCChangeToLook( UI_EVENT *pUIEvent );
|
|
UINT32 UIHandleLCLook( UI_EVENT *pUIEvent );
|
|
|
|
UINT32 UIHandleTATalkingMenu( UI_EVENT *pUIEvent );
|
|
|
|
UINT32 UIHandleTOnTerrain( UI_EVENT *pUIEvent );
|
|
UINT32 UIHandleTChangeToTalking( UI_EVENT *pUIEvent );
|
|
|
|
UINT32 UIHandleLUIOnTerrain( UI_EVENT *pUIEvent );
|
|
UINT32 UIHandleLUIBeginLock( UI_EVENT *pUIEvent );
|
|
UINT32 UIHandleLUIEndLock( UI_EVENT *pUIEvent );
|
|
|
|
UINT32 UIHandleLAOnTerrain( UI_EVENT *pUIEvent );
|
|
UINT32 UIHandleLABeginLockOurTurn( UI_EVENT *pUIEvent );
|
|
UINT32 UIHandleLAEndLockOurTurn( UI_EVENT *pUIEvent );
|
|
|
|
UINT32 UIHandleRubberBandOnTerrain( UI_EVENT *pUIEvent );
|
|
UINT32 UIHandleJumpOverOnTerrain( UI_EVENT *pUIEvent );
|
|
UINT32 UIHandleJumpOver( UI_EVENT *pUIEvent );
|
|
|
|
UINT32 UIHandleOpenDoorMenu( UI_EVENT *pUIEvent );
|
|
|
|
UINT32 UIHandleEXExitSectorMenu( UI_EVENT *pUIEvent );
|
|
|
|
BOOLEAN ValidQuickExchangePosition( );
|
|
|
|
|
|
extern void DebugLevelNodePage( void );
|
|
|
|
INT16 gsTreeRevealXPos;
|
|
INT16 gsTreeRevealYPos;
|
|
|
|
// taken out of header to remove multiple symbol definitions (jonathanl)
|
|
BOOLEAN gfUICtHBar;
|
|
// HEADROCK HAM B1/2: Created an array to hold CTH of different bullets for Burst/Auto CTH Bar.
|
|
UINT8 gbCtH[ 10 ];
|
|
UINT8 gbCtHBurstCount;
|
|
// HEADROCK HAM B2: This value tracks whether Autofire mode is selected. This value may be redundant... not sure.
|
|
BOOLEAN gbCtHAutoFire;
|
|
UINT16 gsTotalBulletCount;
|
|
UINT16 gsBulletCount;
|
|
BOOLEAN gTintBulletCounts;
|
|
BOOLEAN gfUIAutofireBulletCount;
|
|
BOOLEAN gfUIBodyHitLocation;
|
|
|
|
BOOLEAN HandleMultiSelectionMove( INT16 sDestGridNo );
|
|
void ResetMultiSelection( );
|
|
|
|
|
|
|
|
BOOLEAN SoldierCanAffordNewStance( SOLDIERTYPE *pSoldier, UINT8 ubDesiredStance );
|
|
void SetMovementModeCursor( SOLDIERTYPE *pSoldier );
|
|
void SetConfirmMovementModeCursor( SOLDIERTYPE *pSoldier, BOOLEAN fFromMove );
|
|
void SetUIbasedOnStance( SOLDIERTYPE *pSoldier, INT8 bNewStance );
|
|
INT8 DrawUIMovementPath( SOLDIERTYPE *pSoldier, INT16 sMapPos, UINT32 uiFlags );
|
|
INT8 UIHandleInteractiveTilesAndItemsOnTerrain( SOLDIERTYPE *pSoldier, INT16 sMapPos, BOOLEAN fUseOKCursor, BOOLEAN fItemsOnlyIfOnIntTiles );
|
|
|
|
extern BOOLEAN gfExitDebugScreen;
|
|
extern INT8 gCurDebugPage;
|
|
extern BOOLEAN gfGetNewPathThroughPeople;
|
|
extern BOOLEAN gfIgnoreOnSelectedGuy;
|
|
extern BOOLEAN gfInOpenDoorMenu;
|
|
|
|
BOOLEAN gfUIFullTargetFound;
|
|
UINT32 guiUIFullTargetFlags;
|
|
UINT16 gusUIFullTargetID;
|
|
BOOLEAN gfUISelectiveTargetFound;
|
|
UINT32 guiUISelectiveTargetFlags;
|
|
UINT16 gusUISelectiveTargetID;
|
|
|
|
SOLDIERTYPE *gpRequesterMerc = NULL;
|
|
SOLDIERTYPE *gpRequesterTargetMerc = NULL;
|
|
INT16 gsRequesterGridNo;
|
|
INT16 gsOverItemsGridNo = NOWHERE;
|
|
INT16 gsOverItemsLevel = 0;
|
|
BOOLEAN gfUIInterfaceSetBusy = FALSE;
|
|
UINT32 guiUIInterfaceBusyTime = 0;
|
|
|
|
UINT32 gfTacticalForceNoCursor = FALSE;
|
|
LEVELNODE *gpInvTileThatCausedMoveConfirm = NULL;
|
|
BOOLEAN gfResetUIMovementOptimization = FALSE;
|
|
BOOLEAN gfResetUIItemCursorOptimization = FALSE;
|
|
BOOLEAN gfBeginVehicleCursor = FALSE;
|
|
INT16 gsOutOfRangeGridNo = NOWHERE;
|
|
UINT8 gubOutOfRangeMerc = NOBODY;
|
|
BOOLEAN gfOKForExchangeCursor = FALSE;
|
|
UINT32 guiUIInterfaceSwapCursorsTime = 0;
|
|
INT16 gsJumpOverGridNo = 0;
|
|
|
|
|
|
UI_EVENT gEvents[ NUM_UI_EVENTS ] =
|
|
{
|
|
0, IDLE_MODE, UIHandleIDoNothing, FALSE, FALSE, 0, 0, 0, 0,
|
|
0, IDLE_MODE, UIHandleExit, FALSE, FALSE, 0, 0, 0, 0,
|
|
UIEVENT_SINGLEEVENT, DONT_CHANGEMODE, UIHandleNewMerc, FALSE, FALSE, 0, 0, 0, 0,
|
|
UIEVENT_SINGLEEVENT, DONT_CHANGEMODE, UIHandleNewBadMerc, FALSE, FALSE, 0, 0, 0, 0,
|
|
UIEVENT_SINGLEEVENT, MOVE_MODE, UIHandleSelectMerc, FALSE, FALSE, 0, 0, 0, 0,
|
|
UIEVENT_SINGLEEVENT, MOVE_MODE, UIHandleEnterEditMode, FALSE, FALSE, 0, 0, 0, 0,
|
|
UIEVENT_SINGLEEVENT, MOVE_MODE, UIHandleEnterPalEditMode, FALSE, FALSE, 0, 0, 0, 0,
|
|
UIEVENT_SINGLEEVENT, DONT_CHANGEMODE, UIHandleEndTurn, FALSE, FALSE, 0, 0, 0, 0,
|
|
UIEVENT_SINGLEEVENT, DONT_CHANGEMODE, UIHandleTestHit, FALSE, FALSE, 0, 0, 0, 0,
|
|
UIEVENT_SINGLEEVENT, MOVE_MODE, UIHandleChangeLevel, FALSE, FALSE, 0, 0, 0, 0,
|
|
UIEVENT_SINGLEEVENT, IDLE_MODE, UIHandleIOnTerrain, FALSE, FALSE, 0, 0, 0, 0,
|
|
UIEVENT_SINGLEEVENT, IDLE_MODE, UIHandleIChangeToIdle, FALSE, FALSE, 0, 0, 0, 0,
|
|
UIEVENT_SINGLEEVENT, IDLE_MODE, UIHandleILoadLevel, FALSE, FALSE, 0, 0, 0, 0,
|
|
UIEVENT_SINGLEEVENT, DONT_CHANGEMODE, UIHandleISoldierDebug, FALSE, FALSE, 0, 0, 0, 0,
|
|
UIEVENT_SINGLEEVENT, DONT_CHANGEMODE, UIHandleILOSDebug, FALSE, FALSE, 0, 0, 0, 0,
|
|
UIEVENT_SINGLEEVENT, DONT_CHANGEMODE, UIHandleILevelNodeDebug, FALSE, FALSE, 0, 0, 0, 0,
|
|
UIEVENT_SINGLEEVENT, DONT_CHANGEMODE, UIHandleIGotoDemoMode, FALSE, FALSE, 0, 0, 0, 0,
|
|
UIEVENT_SINGLEEVENT, DONT_CHANGEMODE, UIHandleILoadFirstLevel, FALSE, FALSE, 0, 0, 0, 0,
|
|
UIEVENT_SINGLEEVENT, DONT_CHANGEMODE, UIHandleILoadSecondLevel, FALSE, FALSE, 0, 0, 0, 0,
|
|
UIEVENT_SINGLEEVENT, DONT_CHANGEMODE, UIHandleILoadThirdLevel, FALSE, FALSE, 0, 0, 0, 0,
|
|
UIEVENT_SINGLEEVENT, DONT_CHANGEMODE, UIHandleILoadFourthLevel, FALSE, FALSE, 0, 0, 0, 0,
|
|
UIEVENT_SINGLEEVENT, DONT_CHANGEMODE, UIHandleILoadFifthLevel, FALSE, FALSE, 0, 0, 0, 0,
|
|
|
|
0, ENEMYS_TURN_MODE, UIHandleIETOnTerrain, FALSE, FALSE, 0, 0, 0, 0,
|
|
UIEVENT_SINGLEEVENT, MOVE_MODE, UIHandleIETEndTurn, FALSE, FALSE, 0, 0, 0, 0,
|
|
|
|
|
|
0, MOVE_MODE, UIHandleMOnTerrain, FALSE, FALSE, 0, 0, 0, 0,
|
|
UIEVENT_SINGLEEVENT, ACTION_MODE, UIHandleMChangeToAction, FALSE, FALSE, 0, 0, 0, 0,
|
|
UIEVENT_SINGLEEVENT, HANDCURSOR_MODE, UIHandleMChangeToHandMode, FALSE, FALSE, 0, 0, 0, 0,
|
|
UIEVENT_SINGLEEVENT, MOVE_MODE, UIHandleMCycleMovement, FALSE, FALSE, 0, 0, 0, 0,
|
|
UIEVENT_SINGLEEVENT, CONFIRM_MOVE_MODE, UIHandleMCycleMoveAll, FALSE, FALSE, 0, 0, 0, 0,
|
|
UIEVENT_SNAPMOUSE, ADJUST_STANCE_MODE, UIHandleMAdjustStanceMode, FALSE, FALSE, 0, 0, 0, 0,
|
|
0, POPUP_MODE, UIHandlePOPUPMSG, FALSE, FALSE, 0, 0, 0, 0,
|
|
0, ACTION_MODE, UIHandleAOnTerrain, FALSE, FALSE, 0, 0, 0, 0,
|
|
UIEVENT_SINGLEEVENT, MOVE_MODE, UIHandleAChangeToMove, FALSE, FALSE, 0, 0, 0, 0,
|
|
UIEVENT_SINGLEEVENT, CONFIRM_ACTION_MODE, UIHandleAChangeToConfirmAction, FALSE, FALSE, 0, 0, 0, 0,
|
|
UIEVENT_SINGLEEVENT, MOVE_MODE, UIHandleAEndAction, FALSE, FALSE, 0, 0, 0, 0,
|
|
UIEVENT_SNAPMOUSE, MENU_MODE, UIHandleMovementMenu, FALSE, FALSE, 0, 0, 0, 0,
|
|
UIEVENT_SNAPMOUSE, MENU_MODE, UIHandlePositionMenu, FALSE, FALSE, 0, 0, 0, 0,
|
|
0, CONFIRM_MOVE_MODE, UIHandleCWait, FALSE, FALSE, 0, 0, 0, 0,
|
|
UIEVENT_SINGLEEVENT, MOVE_MODE, UIHandleCMoveMerc, FALSE, FALSE, 0, 0, 0, 0,
|
|
0, CONFIRM_MOVE_MODE, UIHandleCOnTerrain, FALSE, FALSE, 0, 0, 0, 0,
|
|
0, MOVE_MODE, UIHandlePADJAdjustStance, FALSE, FALSE, 0, 0, 0, 0,
|
|
0, CONFIRM_ACTION_MODE, UIHandleCAOnTerrain, FALSE, FALSE, 0, 0, 0, 0,
|
|
UIEVENT_SINGLEEVENT, ACTION_MODE, UIHandleCAMercShoot, FALSE, FALSE, 0, 0, 0, 0,
|
|
UIEVENT_SINGLEEVENT, ACTION_MODE, UIHandleCAEndConfirmAction, FALSE, FALSE, 0, 0, 0, 0,
|
|
0, HANDCURSOR_MODE, UIHandleHCOnTerrain, FALSE, FALSE, 0, 0, 0, 0,
|
|
0, GETTINGITEM_MODE, UIHandleHCGettingItem, FALSE, FALSE, 0, 0, 0, 0,
|
|
0, LOOKCURSOR_MODE, UIHandleLCOnTerrain, FALSE, FALSE, 0, 0, 0, 0,
|
|
UIEVENT_SINGLEEVENT, LOOKCURSOR_MODE, UIHandleLCChangeToLook, FALSE, FALSE, 0, 0, 0, 0,
|
|
UIEVENT_SINGLEEVENT, MOVE_MODE, UIHandleLCLook, FALSE, FALSE, 0, 0, 0, 0,
|
|
0, TALKINGMENU_MODE, UIHandleTATalkingMenu, FALSE, FALSE, 0, 0, 0, 0,
|
|
0, TALKCURSOR_MODE, UIHandleTOnTerrain, FALSE, FALSE, 0, 0, 0, 0,
|
|
UIEVENT_SINGLEEVENT, TALKCURSOR_MODE, UIHandleTChangeToTalking, FALSE, FALSE, 0, 0, 0, 0,
|
|
0, LOCKUI_MODE, UIHandleLUIOnTerrain, FALSE, FALSE, 0, 0, 0, 0,
|
|
0, LOCKUI_MODE, UIHandleLUIBeginLock, FALSE, FALSE, 0, 0, 0, 0,
|
|
UIEVENT_SINGLEEVENT, MOVE_MODE, UIHandleLUIEndLock, FALSE, FALSE, 0, 0, 0, 0,
|
|
0, OPENDOOR_MENU_MODE, UIHandleOpenDoorMenu, FALSE, FALSE, 0, 0, 0, 0,
|
|
0, LOCKOURTURN_UI_MODE, UIHandleLAOnTerrain, FALSE, FALSE, 0, 0, 0, 0,
|
|
0, LOCKOURTURN_UI_MODE, UIHandleLABeginLockOurTurn, FALSE, FALSE, 0, 0, 0, 0,
|
|
UIEVENT_SINGLEEVENT, MOVE_MODE, UIHandleLAEndLockOurTurn, FALSE, FALSE, 0, 0, 0, 0,
|
|
0, EXITSECTORMENU_MODE, UIHandleEXExitSectorMenu, FALSE, FALSE, 0, 0, 0, 0,
|
|
0, RUBBERBAND_MODE, UIHandleRubberBandOnTerrain, FALSE, FALSE, 0, 0, 0, 0,
|
|
0, JUMPOVER_MODE, UIHandleJumpOverOnTerrain, FALSE, FALSE, 0, 0, 0, 0,
|
|
0, MOVE_MODE, UIHandleJumpOver, FALSE, FALSE, 0, 0, 0, 0,
|
|
|
|
};
|
|
|
|
UI_MODE gCurrentUIMode = IDLE_MODE;
|
|
UI_MODE gOldUIMode = IDLE_MODE;
|
|
UINT32 guiCurrentEvent = I_DO_NOTHING;
|
|
UINT32 guiOldEvent = I_DO_NOTHING;
|
|
UINT32 guiCurrentUICursor = NO_UICURSOR;
|
|
UINT32 guiNewUICursor = NORMAL_SNAPUICURSOR;
|
|
UINT32 guiPendingOverrideEvent = I_DO_NOTHING;
|
|
UINT16 gusSavedMouseX;
|
|
UINT16 gusSavedMouseY;
|
|
UIKEYBOARD_HOOK gUIKeyboardHook = NULL;
|
|
BOOLEAN gUIActionModeChangeDueToMouseOver = FALSE;
|
|
|
|
BOOLEAN gfDisplayTimerCursor = FALSE;
|
|
UINT32 guiTimerCursorID = 0;
|
|
UINT32 guiTimerLastUpdate = 0;
|
|
UINT32 guiTimerCursorDelay = 0;
|
|
|
|
|
|
CHAR16 gzLocation[ 20 ];
|
|
BOOLEAN gfLocation = FALSE;
|
|
|
|
CHAR16 gzIntTileLocation[ 20 ];
|
|
BOOLEAN gfUIIntTileLocation;
|
|
|
|
CHAR16 gzIntTileLocation2[ 20 ];
|
|
BOOLEAN gfUIIntTileLocation2;
|
|
|
|
MOUSE_REGION gDisableRegion;
|
|
BOOLEAN gfDisableRegionActive = FALSE;
|
|
|
|
MOUSE_REGION gUserTurnRegion;
|
|
BOOLEAN gfUserTurnRegionActive = FALSE;
|
|
|
|
|
|
// For use with mouse button query routines
|
|
BOOLEAN fRightButtonDown = FALSE;
|
|
BOOLEAN fLeftButtonDown = FALSE;
|
|
BOOLEAN fIgnoreLeftUp = FALSE;
|
|
|
|
BOOLEAN gUITargetReady = FALSE;
|
|
BOOLEAN gUITargetShotWaiting = FALSE;
|
|
INT16 gsUITargetShotGridNo = NOWHERE;
|
|
BOOLEAN gUIUseReverse = FALSE;
|
|
|
|
SGPRect gRubberBandRect = { 0, 0, 0, 0 };
|
|
BOOLEAN gRubberBandActive = FALSE;
|
|
BOOLEAN gfIgnoreOnSelectedGuy = FALSE;
|
|
BOOLEAN gfViewPortAdjustedForSouth = FALSE;
|
|
|
|
INT16 guiCreateGuyIndex = 0;
|
|
// Temp values for placing bad guys
|
|
INT16 guiCreateBadGuyIndex = 8;
|
|
|
|
// FLAGS
|
|
// These flags are set for a single frame execution and then are reset for the next iteration.
|
|
BOOLEAN gfUIDisplayActionPoints = FALSE;
|
|
BOOLEAN gfUIDisplayActionPointsInvalid = FALSE;
|
|
BOOLEAN gfUIDisplayActionPointsBlack = FALSE;
|
|
BOOLEAN gfUIDisplayActionPointsCenter = FALSE;
|
|
|
|
INT16 gUIDisplayActionPointsOffY = 0;
|
|
INT16 gUIDisplayActionPointsOffX = 0;
|
|
BOOLEAN gfUIDoNotHighlightSelMerc = FALSE;
|
|
BOOLEAN gfUIHandleSelection = FALSE;
|
|
BOOLEAN gfUIHandleSelectionAboveGuy = FALSE;
|
|
BOOLEAN gfUIInDeadlock = FALSE;
|
|
UINT8 gUIDeadlockedSoldier = NOBODY;
|
|
BOOLEAN gfUIHandleShowMoveGrid = FALSE;
|
|
UINT16 gsUIHandleShowMoveGridLocation = NOWHERE ;
|
|
BOOLEAN gfUIOverItemPool = FALSE;
|
|
INT16 gfUIOverItemPoolGridNo = 0;
|
|
INT16 gsCurrentActionPoints = 1;
|
|
BOOLEAN gfUIHandlePhysicsTrajectory = FALSE;
|
|
BOOLEAN gfUIMouseOnValidCatcher = FALSE;
|
|
UINT8 gubUIValidCatcherID = 0;
|
|
|
|
|
|
|
|
BOOLEAN gfUIConfirmExitArrows = FALSE;
|
|
|
|
BOOLEAN gfUIShowCurIntTile = FALSE;
|
|
|
|
BOOLEAN gfUIWaitingForUserSpeechAdvance = FALSE; // Waiting for key input/mouse click to advance speech
|
|
BOOLEAN gfUIKeyCheatModeOn = FALSE; // Sets cool cheat keys on
|
|
BOOLEAN gfUIAllMoveOn = FALSE; // Sets to all move
|
|
BOOLEAN gfUICanBeginAllMoveCycle = FALSE; // GEts set so we know that the next right-click is a move-call inc\stead of a movement cycle through
|
|
|
|
INT16 gsSelectedGridNo = 0;
|
|
INT16 gsSelectedLevel = I_GROUND_LEVEL;
|
|
INT16 gsSelectedGuy = NOBODY;
|
|
|
|
BOOLEAN gfUIDisplayDamage = FALSE;
|
|
INT8 gbDamage = 0;
|
|
INT16 gsDamageGridNo = 0;
|
|
|
|
BOOLEAN gfUIRefreshArrows = FALSE;
|
|
|
|
|
|
// Thse flags are not re-set after each frame
|
|
BOOLEAN gfPlotNewMovement = FALSE;
|
|
BOOLEAN gfPlotNewMovementNOCOST = FALSE;
|
|
UINT32 guiShowUPDownArrows = ARROWS_HIDE_UP | ARROWS_HIDE_DOWN;
|
|
INT8 gbAdjustStanceDiff = 0;
|
|
INT8 gbClimbID = 0;
|
|
|
|
BOOLEAN gfUIShowExitEast = FALSE;
|
|
BOOLEAN gfUIShowExitWest = FALSE;
|
|
BOOLEAN gfUIShowExitNorth = FALSE;
|
|
BOOLEAN gfUIShowExitSouth = FALSE;
|
|
BOOLEAN gfUIShowExitExitGrid = FALSE;
|
|
|
|
BOOLEAN gfUINewStateForIntTile = FALSE;
|
|
|
|
BOOLEAN gfUIForceReExamineCursorData = FALSE;
|
|
|
|
void SetUIMouseCursor( );
|
|
void ClearEvent( UI_EVENT *pUIEvent );
|
|
UINT8 GetAdjustedAnimHeight( UINT8 ubAnimHeight, INT8 bChange );
|
|
|
|
void PreventFromTheFreezingBug(SOLDIERTYPE* pSoldier)
|
|
{
|
|
gfUIInterfaceSetBusy = FALSE;
|
|
UnSetUIBusy( pSoldier->ubID );
|
|
// gTacticalStatus.ubAttackBusyCount = 0; // 0verhaul: I know commenting this may not be a good idea, but then neither is this kludgy routine.
|
|
guiPendingOverrideEvent = LU_ENDUILOCK;
|
|
UIHandleLUIEndLock( NULL );
|
|
}
|
|
|
|
// MAIN TACTICAL UI HANDLER
|
|
UINT32 HandleTacticalUI( void )
|
|
{
|
|
UINT32 ReturnVal = GAME_SCREEN;
|
|
UINT32 uiNewEvent;
|
|
INT16 sMapPos;
|
|
LEVELNODE *pIntTile;
|
|
static LEVELNODE *pOldIntTile = NULL;
|
|
|
|
|
|
// RESET FLAGS
|
|
gfUIDisplayActionPoints = FALSE;
|
|
gfUIDisplayActionPointsInvalid = FALSE;
|
|
gfUIDisplayActionPointsBlack = FALSE;
|
|
gfUIDisplayActionPointsCenter = FALSE;
|
|
gfUIDoNotHighlightSelMerc = FALSE;
|
|
gfUIHandleSelection = NO_GUY_SELECTION;
|
|
gfUIHandleSelectionAboveGuy = FALSE;
|
|
gfUIDisplayDamage = FALSE;
|
|
guiShowUPDownArrows = ARROWS_HIDE_UP | ARROWS_HIDE_DOWN;
|
|
gfUIBodyHitLocation = FALSE;
|
|
gfUIIntTileLocation = FALSE;
|
|
gfUIIntTileLocation2 = FALSE;
|
|
//gfUIForceReExamineCursorData = FALSE;
|
|
gfUINewStateForIntTile = FALSE;
|
|
gfUIShowExitExitGrid = FALSE;
|
|
gfUIOverItemPool = FALSE;
|
|
gfUIHandlePhysicsTrajectory = FALSE;
|
|
gfUIMouseOnValidCatcher = FALSE;
|
|
gfIgnoreOnSelectedGuy = FALSE;
|
|
gTintBulletCounts = FALSE;
|
|
gfUIAutofireBulletCount = FALSE;
|
|
gfUICtHBar = FALSE;
|
|
// HEADROCK HAM B2: tells the cursor-drawing function to draw two CTH bars (for autofire).
|
|
gbCtHAutoFire = FALSE;
|
|
|
|
// Set old event value
|
|
guiOldEvent = uiNewEvent = guiCurrentEvent;
|
|
|
|
if ( gfUIInterfaceSetBusy )
|
|
{
|
|
if ( ( GetJA2Clock( ) - guiUIInterfaceBusyTime ) > 25000 )
|
|
{
|
|
gfUIInterfaceSetBusy = FALSE;
|
|
|
|
//UNLOCK UI
|
|
UnSetUIBusy( (UINT8)gusSelectedSoldier );
|
|
|
|
// Decrease global busy counter...
|
|
gTacticalStatus.ubAttackBusyCount = 0;
|
|
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("Setting attack busy count to 0 due to ending AI lock" ) );
|
|
|
|
guiPendingOverrideEvent = LU_ENDUILOCK;
|
|
UIHandleLUIEndLock( NULL );
|
|
}
|
|
}
|
|
|
|
if ( ( GetJA2Clock( ) - guiUIInterfaceSwapCursorsTime ) > 1000 )
|
|
{
|
|
gfOKForExchangeCursor = !gfOKForExchangeCursor;
|
|
guiUIInterfaceSwapCursorsTime = GetJA2Clock( );
|
|
}
|
|
|
|
// OK, do a check for on an int tile...
|
|
pIntTile = GetCurInteractiveTile( );
|
|
|
|
if ( pIntTile != pOldIntTile )
|
|
{
|
|
gfUINewStateForIntTile = TRUE;
|
|
|
|
pOldIntTile = pIntTile;
|
|
}
|
|
|
|
if ( guiPendingOverrideEvent == I_DO_NOTHING )
|
|
{
|
|
// When we are here, guiCurrentEvent is set to the last event
|
|
// Within the input gathering phase, it may change
|
|
|
|
// GATHER INPUT
|
|
// Any new event will overwrite previous events. Therefore,
|
|
// PRIOTITIES GO LIKE THIS:
|
|
// Mouse Movement
|
|
// Keyboard Polling
|
|
// Mouse Buttons
|
|
// Keyboard Queued Events ( will override always )
|
|
|
|
// SWITCH ON INPUT GATHERING, DEPENDING ON MODE
|
|
// IF WE ARE NOT IN COMBAT OR IN REALTIME COMBAT
|
|
if ( ( gTacticalStatus.uiFlags & REALTIME ) || !( gTacticalStatus.uiFlags & INCOMBAT ) )
|
|
{
|
|
// FROM MOUSE POSITION
|
|
GetRTMousePositionInput( &uiNewEvent );
|
|
// FROM KEYBOARD POLLING
|
|
GetPolledKeyboardInput( &uiNewEvent );
|
|
// FROM MOUSE CLICKS
|
|
GetRTMouseButtonInput( &uiNewEvent );
|
|
// FROM KEYBOARD
|
|
GetKeyboardInput( &uiNewEvent );
|
|
|
|
}
|
|
else
|
|
{
|
|
// FROM MOUSE POSITION
|
|
GetTBMousePositionInput( &uiNewEvent );
|
|
// FROM KEYBOARD POLLING
|
|
GetPolledKeyboardInput( &uiNewEvent );
|
|
// FROM MOUSE CLICKS
|
|
GetTBMouseButtonInput( &uiNewEvent );
|
|
// FROM KEYBOARD
|
|
GetKeyboardInput( &uiNewEvent );
|
|
}
|
|
|
|
|
|
}
|
|
else
|
|
{
|
|
uiNewEvent = guiPendingOverrideEvent;
|
|
guiPendingOverrideEvent = I_DO_NOTHING;
|
|
}
|
|
|
|
if ( HandleItemPickupMenu( ) )
|
|
{
|
|
uiNewEvent = A_CHANGE_TO_MOVE;
|
|
}
|
|
|
|
// Set Current event to new one!
|
|
guiCurrentEvent = uiNewEvent;
|
|
|
|
//ATE: New! Get flags for over soldier or not...
|
|
gfUIFullTargetFound = FALSE;
|
|
gfUISelectiveTargetFound = FALSE;
|
|
|
|
if ( GetMouseMapPos( &sMapPos ) )
|
|
{
|
|
// Look for soldier full
|
|
if ( FindSoldier( sMapPos, &gusUIFullTargetID, &guiUIFullTargetFlags, ( FINDSOLDIERSAMELEVEL( gsInterfaceLevel ) ) ) )
|
|
{
|
|
gfUIFullTargetFound = TRUE;
|
|
}
|
|
|
|
// Look for soldier selective
|
|
if ( FindSoldier( sMapPos, &gusUISelectiveTargetID, &guiUISelectiveTargetFlags, FINDSOLDIERSELECTIVESAMELEVEL( gsInterfaceLevel ) ) )
|
|
{
|
|
gfUISelectiveTargetFound = TRUE;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
// Check if current event has changed and clear event if so, to prepare it for execution
|
|
// Clearing it does things like set first time flag, param variables, etc
|
|
if ( uiNewEvent != guiOldEvent )
|
|
{
|
|
// Snap mouse back if it's that type
|
|
if ( gEvents[ guiOldEvent ].uiFlags & UIEVENT_SNAPMOUSE )
|
|
{
|
|
SimulateMouseMovement( (UINT32)gusSavedMouseX, (UINT32)gusSavedMouseY );
|
|
}
|
|
|
|
ClearEvent( &gEvents[ uiNewEvent ] );
|
|
}
|
|
|
|
// Restore not scrolling from stance adjust....
|
|
if ( gOldUIMode == ADJUST_STANCE_MODE )
|
|
{
|
|
gfIgnoreScrolling = FALSE;
|
|
}
|
|
|
|
// IF this event is of type snap mouse, save position
|
|
if ( gEvents[ uiNewEvent ].uiFlags & UIEVENT_SNAPMOUSE && gEvents[ uiNewEvent ].fFirstTime )
|
|
{
|
|
// Save mouse position
|
|
gusSavedMouseX = gusMouseXPos;
|
|
gusSavedMouseY = gusMouseYPos;
|
|
}
|
|
|
|
// HANDLE UI EVENT
|
|
ReturnVal = gEvents[ uiNewEvent ].HandleEvent( &( gEvents[ uiNewEvent ] ) );
|
|
|
|
if ( gfInOpenDoorMenu )
|
|
{
|
|
return( ReturnVal );
|
|
}
|
|
|
|
// Set first time flag to false, now that it has been executed
|
|
gEvents[ uiNewEvent ].fFirstTime = FALSE;
|
|
|
|
// Check if UI mode has changed from previous event
|
|
if ( gEvents[ uiNewEvent ].ChangeToUIMode != gCurrentUIMode && ( gEvents[ uiNewEvent ].ChangeToUIMode != DONT_CHANGEMODE ) )
|
|
{
|
|
gEvents[ uiNewEvent ].uiMenuPreviousMode = gCurrentUIMode;
|
|
|
|
gOldUIMode = gCurrentUIMode;
|
|
|
|
gCurrentUIMode = gEvents[ uiNewEvent ].ChangeToUIMode;
|
|
|
|
// CHANGE MODE - DO SPECIAL THINGS IF WE ENTER THIS MODE
|
|
switch( gCurrentUIMode )
|
|
{
|
|
case ACTION_MODE:
|
|
ErasePath( TRUE );
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
// Check if menu event is done and if so set to privious mode
|
|
// This is needed to hook into the interface stuff which sets the fDoneMenu flag
|
|
if ( gEvents[ uiNewEvent ].fDoneMenu == TRUE )
|
|
{
|
|
if ( gCurrentUIMode == MENU_MODE || gCurrentUIMode == POPUP_MODE || gCurrentUIMode == LOOKCURSOR_MODE )
|
|
{
|
|
gCurrentUIMode = (UI_MODE) gEvents[ uiNewEvent ].uiMenuPreviousMode;
|
|
}
|
|
}
|
|
// Check to return to privious mode
|
|
// If the event is a single event, return to previous
|
|
if ( gEvents[ uiNewEvent ].uiFlags & UIEVENT_SINGLEEVENT )
|
|
{
|
|
// ATE: OK - don't revert to single event if our mouse is not
|
|
// in viewport - rather use m_on_t event
|
|
if ( ( gViewportRegion.uiFlags & MSYS_MOUSE_IN_AREA ) )
|
|
{
|
|
guiCurrentEvent = guiOldEvent;
|
|
}
|
|
else
|
|
{
|
|
// ATE: Check first that some modes are met....
|
|
if ( gCurrentUIMode != HANDCURSOR_MODE && gCurrentUIMode != LOOKCURSOR_MODE && gCurrentUIMode != TALKCURSOR_MODE )
|
|
{
|
|
guiCurrentEvent = M_ON_TERRAIN;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Donot display APs if not in combat
|
|
if ( !(gTacticalStatus.uiFlags & INCOMBAT ) || (gTacticalStatus.uiFlags & REALTIME ) )
|
|
{
|
|
gfUIDisplayActionPoints = FALSE;
|
|
}
|
|
|
|
|
|
// Will set the cursor but only if different
|
|
SetUIMouseCursor( );
|
|
|
|
// ATE: Check to reset selected guys....
|
|
if ( gTacticalStatus.fAtLeastOneGuyOnMultiSelect )
|
|
{
|
|
// If not in MOVE_MODE, CONFIRM_MOVE_MODE, RUBBERBAND_MODE, stop....
|
|
if ( gCurrentUIMode != MOVE_MODE && gCurrentUIMode != CONFIRM_MOVE_MODE && gCurrentUIMode != RUBBERBAND_MODE && gCurrentUIMode != ADJUST_STANCE_MODE && gCurrentUIMode != TALKCURSOR_MODE && gCurrentUIMode != LOOKCURSOR_MODE )
|
|
{
|
|
ResetMultiSelection( );
|
|
}
|
|
}
|
|
|
|
|
|
return( ReturnVal );
|
|
}
|
|
|
|
void SetUIMouseCursor( )
|
|
{
|
|
UINT32 uiCursorFlags;
|
|
UINT32 uiTraverseTimeInMinutes;
|
|
BOOLEAN fForceUpdateNewCursor = FALSE;
|
|
BOOLEAN fUpdateNewCursor = TRUE;
|
|
static INT16 sOldExitGridNo = NOWHERE;
|
|
static BOOLEAN fOkForExit = FALSE;
|
|
|
|
|
|
// Check if we moved from confirm mode on exit arrows
|
|
// If not in move mode, return!
|
|
if ( gCurrentUIMode == MOVE_MODE )
|
|
{
|
|
if ( gfUIConfirmExitArrows )
|
|
{
|
|
GetCursorMovementFlags( &uiCursorFlags );
|
|
|
|
if ( uiCursorFlags & MOUSE_MOVING )
|
|
{
|
|
gfUIConfirmExitArrows = FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
if ( gfUIShowExitEast )
|
|
{
|
|
gfUIDisplayActionPoints = FALSE;
|
|
ErasePath( TRUE );
|
|
|
|
if ( OKForSectorExit( EAST_STRATEGIC_MOVE, 0, &uiTraverseTimeInMinutes ) )
|
|
{
|
|
if ( gfUIConfirmExitArrows )
|
|
{
|
|
guiNewUICursor = CONFIRM_EXIT_EAST_UICURSOR;
|
|
}
|
|
else
|
|
{
|
|
guiNewUICursor = EXIT_EAST_UICURSOR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
guiNewUICursor = NOEXIT_EAST_UICURSOR;
|
|
}
|
|
|
|
if ( gusMouseXPos < SCREEN_WIDTH - 5 )
|
|
{
|
|
gfUIShowExitEast = FALSE;
|
|
}
|
|
}
|
|
|
|
if ( gfUIShowExitWest )
|
|
{
|
|
gfUIDisplayActionPoints = FALSE;
|
|
ErasePath( TRUE );
|
|
|
|
if ( OKForSectorExit( WEST_STRATEGIC_MOVE, 0, &uiTraverseTimeInMinutes ) )
|
|
{
|
|
if ( gfUIConfirmExitArrows )
|
|
{
|
|
guiNewUICursor = CONFIRM_EXIT_WEST_UICURSOR;
|
|
}
|
|
else
|
|
{
|
|
guiNewUICursor = EXIT_WEST_UICURSOR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
guiNewUICursor = NOEXIT_WEST_UICURSOR;
|
|
}
|
|
|
|
if ( gusMouseXPos > 5 )
|
|
{
|
|
gfUIShowExitWest = FALSE;
|
|
}
|
|
}
|
|
|
|
if ( gfUIShowExitNorth )
|
|
{
|
|
gfUIDisplayActionPoints = FALSE;
|
|
ErasePath( TRUE );
|
|
|
|
if ( OKForSectorExit( NORTH_STRATEGIC_MOVE, 0, &uiTraverseTimeInMinutes ) )
|
|
{
|
|
if ( gfUIConfirmExitArrows )
|
|
{
|
|
guiNewUICursor = CONFIRM_EXIT_NORTH_UICURSOR;
|
|
}
|
|
else
|
|
{
|
|
guiNewUICursor = EXIT_NORTH_UICURSOR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
guiNewUICursor = NOEXIT_NORTH_UICURSOR;
|
|
}
|
|
|
|
if ( gusMouseYPos > 5 )
|
|
{
|
|
gfUIShowExitNorth = FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
if ( gfUIShowExitSouth )
|
|
{
|
|
gfUIDisplayActionPoints = FALSE;
|
|
ErasePath( TRUE );
|
|
|
|
if ( OKForSectorExit( SOUTH_STRATEGIC_MOVE, 0, &uiTraverseTimeInMinutes ) )
|
|
{
|
|
if ( gfUIConfirmExitArrows )
|
|
{
|
|
guiNewUICursor = CONFIRM_EXIT_SOUTH_UICURSOR;
|
|
}
|
|
else
|
|
{
|
|
guiNewUICursor = EXIT_SOUTH_UICURSOR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
guiNewUICursor = NOEXIT_SOUTH_UICURSOR;
|
|
}
|
|
|
|
if ( gusMouseYPos < SCREEN_HEIGHT - 2 )
|
|
{
|
|
gfUIShowExitSouth = FALSE;
|
|
|
|
// Define region for viewport
|
|
MSYS_RemoveRegion( &gViewportRegion );
|
|
|
|
MSYS_DefineRegion( &gViewportRegion, 0, 0 ,gsVIEWPORT_END_X, gsVIEWPORT_WINDOW_END_Y, MSYS_PRIORITY_NORMAL,
|
|
VIDEO_NO_CURSOR, MSYS_NO_CALLBACK, MSYS_NO_CALLBACK );
|
|
|
|
|
|
// Adjust where we blit our cursor!
|
|
gsGlobalCursorYOffset = 0;
|
|
SetCurrentCursorFromDatabase( CURSOR_NORMAL );
|
|
}
|
|
else
|
|
{
|
|
if ( gfScrollPending || gfScrollInertia )
|
|
{
|
|
|
|
}
|
|
else
|
|
{
|
|
// Adjust viewport to edge of screen!
|
|
// Define region for viewport
|
|
MSYS_RemoveRegion( &gViewportRegion );
|
|
MSYS_DefineRegion( &gViewportRegion, 0, 0 ,gsVIEWPORT_END_X, SCREEN_HEIGHT, MSYS_PRIORITY_NORMAL,
|
|
VIDEO_NO_CURSOR, MSYS_NO_CALLBACK, MSYS_NO_CALLBACK );
|
|
|
|
gsGlobalCursorYOffset = ( SCREEN_HEIGHT - gsVIEWPORT_WINDOW_END_Y );
|
|
SetCurrentCursorFromDatabase( gUICursors[ guiNewUICursor ].usFreeCursorName );
|
|
|
|
gfViewPortAdjustedForSouth = TRUE;
|
|
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( gfViewPortAdjustedForSouth )
|
|
{
|
|
// Define region for viewport
|
|
MSYS_RemoveRegion( &gViewportRegion );
|
|
|
|
MSYS_DefineRegion( &gViewportRegion, 0, 0 ,gsVIEWPORT_END_X, gsVIEWPORT_WINDOW_END_Y, MSYS_PRIORITY_NORMAL,
|
|
VIDEO_NO_CURSOR, MSYS_NO_CALLBACK, MSYS_NO_CALLBACK );
|
|
|
|
|
|
// Adjust where we blit our cursor!
|
|
gsGlobalCursorYOffset = 0;
|
|
SetCurrentCursorFromDatabase( CURSOR_NORMAL );
|
|
|
|
gfViewPortAdjustedForSouth = FALSE;
|
|
}
|
|
}
|
|
|
|
if ( gfUIShowExitExitGrid )
|
|
{
|
|
INT16 sMapPos;
|
|
UINT8 ubRoomNum;
|
|
|
|
gfUIDisplayActionPoints = FALSE;
|
|
ErasePath( TRUE );
|
|
|
|
if( GetMouseMapPos( &sMapPos) )
|
|
{
|
|
if ( gusSelectedSoldier != NOBODY && MercPtrs[ gusSelectedSoldier ]->pathing.bLevel == 0 )
|
|
{
|
|
// ATE: Is this place revealed?
|
|
if ( !InARoom( sMapPos, &ubRoomNum ) || ( InARoom( sMapPos, &ubRoomNum ) && gpWorldLevelData[ sMapPos ].uiFlags & MAPELEMENT_REVEALED ) )
|
|
{
|
|
if ( sOldExitGridNo != sMapPos )
|
|
{
|
|
fOkForExit = OKForSectorExit( (INT8)-1, sMapPos, &uiTraverseTimeInMinutes );
|
|
sOldExitGridNo = sMapPos;
|
|
}
|
|
|
|
if ( fOkForExit )
|
|
{
|
|
if ( gfUIConfirmExitArrows )
|
|
{
|
|
guiNewUICursor = CONFIRM_EXIT_GRID_UICURSOR;
|
|
}
|
|
else
|
|
{
|
|
guiNewUICursor = EXIT_GRID_UICURSOR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
guiNewUICursor = NOEXIT_GRID_UICURSOR;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sOldExitGridNo = NOWHERE;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
gsGlobalCursorYOffset = 0;
|
|
}
|
|
|
|
if ( gfDisplayTimerCursor )
|
|
{
|
|
SetUICursor( guiTimerCursorID );
|
|
|
|
fUpdateNewCursor = FALSE;
|
|
|
|
if ( ( GetJA2Clock( ) - guiTimerLastUpdate ) > guiTimerCursorDelay )
|
|
{
|
|
gfDisplayTimerCursor = FALSE;
|
|
|
|
// OK, timer may be different, update...
|
|
fForceUpdateNewCursor = TRUE;
|
|
fUpdateNewCursor = TRUE;
|
|
}
|
|
}
|
|
|
|
if ( fUpdateNewCursor )
|
|
{
|
|
if ( !gfTacticalForceNoCursor )
|
|
{
|
|
if ( guiNewUICursor != guiCurrentUICursor || fForceUpdateNewCursor )
|
|
{
|
|
SetUICursor( guiNewUICursor );
|
|
|
|
guiCurrentUICursor = guiNewUICursor;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void SetUIKeyboardHook( UIKEYBOARD_HOOK KeyboardHookFnc )
|
|
{
|
|
gUIKeyboardHook = KeyboardHookFnc;
|
|
}
|
|
|
|
|
|
void ClearEvent( UI_EVENT *pUIEvent )
|
|
{
|
|
memset( pUIEvent->uiParams, 0, sizeof( pUIEvent->uiParams ) );
|
|
pUIEvent->fDoneMenu = FALSE;
|
|
pUIEvent->fFirstTime = TRUE;
|
|
pUIEvent->uiMenuPreviousMode = 0;
|
|
|
|
}
|
|
|
|
void EndMenuEvent( UINT32 uiEvent )
|
|
{
|
|
gEvents[ uiEvent ].fDoneMenu = TRUE;
|
|
|
|
}
|
|
|
|
// HANDLER FUCNTIONS
|
|
|
|
UINT32 UIHandleIDoNothing( UI_EVENT *pUIEvent )
|
|
{
|
|
guiNewUICursor = NORMAL_SNAPUICURSOR;
|
|
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
UINT32 UIHandleExit( UI_EVENT *pUIEvent )
|
|
{
|
|
gfProgramIsRunning = FALSE;
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
UINT32 UIHandleNewMerc( UI_EVENT *pUIEvent )
|
|
{
|
|
static UINT8 ubTemp = 3;
|
|
INT16 sMapPos;
|
|
static INT32 iSoldierCount=0;
|
|
MERC_HIRE_STRUCT HireMercStruct;
|
|
INT8 bReturnCode;
|
|
SOLDIERTYPE *pSoldier;
|
|
|
|
|
|
// Get Grid Corrdinates of mouse
|
|
if( GetMouseMapPos( &sMapPos) )
|
|
{
|
|
ubTemp+= 2;
|
|
|
|
memset( &HireMercStruct, 0, sizeof(MERC_HIRE_STRUCT));
|
|
|
|
HireMercStruct.ubProfileID = ubTemp;
|
|
|
|
//DEF: temp
|
|
HireMercStruct.sSectorX = gWorldSectorX;
|
|
HireMercStruct.sSectorY = gWorldSectorY;
|
|
HireMercStruct.bSectorZ = gbWorldSectorZ;
|
|
HireMercStruct.ubInsertionCode = INSERTION_CODE_GRIDNO;
|
|
HireMercStruct.usInsertionData = sMapPos;
|
|
HireMercStruct.fCopyProfileItemsOver = TRUE;
|
|
HireMercStruct.iTotalContractLength = 7;
|
|
|
|
//specify when the merc should arrive
|
|
HireMercStruct.uiTimeTillMercArrives = 0;
|
|
|
|
//if we succesfully hired the merc
|
|
bReturnCode = HireMerc( &HireMercStruct );
|
|
|
|
if( bReturnCode == MERC_HIRE_FAILED )
|
|
{
|
|
ScreenMsg( FONT_ORANGE, MSG_BETAVERSION, L"Merc hire failed: Either already hired or dislikes you." );
|
|
}
|
|
// WDS - make number of mercenaries, etc. be configurable
|
|
else if( bReturnCode == MERC_HIRE_OVER_PLAYER_LIMIT )
|
|
{
|
|
ScreenMsg( FONT_ORANGE, MSG_BETAVERSION, L"Can't hire that many mercs." );
|
|
}
|
|
else
|
|
{
|
|
// Get soldier from profile
|
|
pSoldier = FindSoldierByProfileID( ubTemp, FALSE );
|
|
|
|
MercArrivesCallback( pSoldier->ubID );
|
|
SelectSoldier( pSoldier->ubID, FALSE, TRUE );
|
|
}
|
|
|
|
}
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
UINT32 UIHandleNewBadMerc( UI_EVENT *pUIEvent )
|
|
{
|
|
SOLDIERTYPE *pSoldier;
|
|
INT16 sMapPos;
|
|
UINT16 usRandom;
|
|
|
|
//Get map postion and place the enemy there.
|
|
if( GetMouseMapPos( &sMapPos) )
|
|
{
|
|
// Are we an OK dest?
|
|
if ( !IsLocationSittable( sMapPos, 0 ) )
|
|
{
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
usRandom = (UINT16)Random( 10 );
|
|
if( usRandom < 4 )
|
|
pSoldier = TacticalCreateAdministrator();
|
|
else if( usRandom < 8 )
|
|
pSoldier = TacticalCreateArmyTroop();
|
|
else
|
|
pSoldier = TacticalCreateEliteEnemy();
|
|
|
|
//Add soldier strategic info, so it doesn't break the counters!
|
|
if( pSoldier )
|
|
{
|
|
if( !gbWorldSectorZ )
|
|
{
|
|
SECTORINFO *pSector = &SectorInfo[ SECTOR( gWorldSectorX, gWorldSectorY ) ];
|
|
switch( pSoldier->ubSoldierClass )
|
|
{
|
|
case SOLDIER_CLASS_ADMINISTRATOR: pSector->ubNumAdmins++; pSector->ubAdminsInBattle++; break;
|
|
case SOLDIER_CLASS_ARMY: pSector->ubNumTroops++; pSector->ubTroopsInBattle++; break;
|
|
case SOLDIER_CLASS_ELITE: pSector->ubNumElites++; pSector->ubElitesInBattle++; break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
UNDERGROUND_SECTORINFO *pSector = FindUnderGroundSector( gWorldSectorX, gWorldSectorY, gbWorldSectorZ );
|
|
if( pSector )
|
|
{
|
|
switch( pSoldier->ubSoldierClass )
|
|
{
|
|
case SOLDIER_CLASS_ADMINISTRATOR: pSector->ubNumAdmins++; pSector->ubAdminsInBattle++; break;
|
|
case SOLDIER_CLASS_ARMY: pSector->ubNumTroops++; pSector->ubTroopsInBattle++; break;
|
|
case SOLDIER_CLASS_ELITE: pSector->ubNumElites++; pSector->ubElitesInBattle++; break;
|
|
}
|
|
}
|
|
}
|
|
|
|
pSoldier->ubStrategicInsertionCode = INSERTION_CODE_GRIDNO;
|
|
pSoldier->usStrategicInsertionData = sMapPos;
|
|
UpdateMercInSector( pSoldier, gWorldSectorX, gWorldSectorY, gbWorldSectorZ );
|
|
AllTeamsLookForAll( NO_INTERRUPTS );
|
|
}
|
|
}
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
|
|
UINT32 UIHandleEnterEditMode( UI_EVENT *pUIEvent )
|
|
{
|
|
return( EDIT_SCREEN );
|
|
}
|
|
|
|
UINT32 UIHandleEnterPalEditMode( UI_EVENT *pUIEvent )
|
|
{
|
|
return( PALEDIT_SCREEN );
|
|
}
|
|
|
|
|
|
|
|
|
|
UINT32 UIHandleEndTurn( UI_EVENT *pUIEvent )
|
|
{
|
|
// CANCEL FROM PLANNING MODE!
|
|
if ( InUIPlanMode( ) )
|
|
{
|
|
EndUIPlan( );
|
|
}
|
|
|
|
// ATE: If we have an item pointer end it!
|
|
CancelItemPointer( );
|
|
|
|
//ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, TacticalStr[ ENDING_TURN ] );
|
|
|
|
if ( CheckForEndOfCombatMode( FALSE ) )
|
|
{
|
|
// do nothing...
|
|
}
|
|
else
|
|
{
|
|
// WANNE: Changed the auto save depending from AutoSave.pls
|
|
// to an option setting.
|
|
// So no more need to have a file AutoSave.pls in you ja2 root directory
|
|
//if( FileExists( "..\\AutoSave.pls" ) && CanGameBeSaved() )
|
|
if (gGameSettings.fOptions[TOPTION_USE_AUTO_SAVE] == TRUE && CanGameBeSaved() )
|
|
{
|
|
//Save the game
|
|
guiPreviousOptionScreen = guiCurrentScreen;
|
|
SaveGame( SAVE__END_TURN_NUM, L"End Turn Auto Save" );
|
|
}
|
|
|
|
// End our turn!
|
|
if (is_server || !is_client)
|
|
{
|
|
EndTurn( gbPlayerNum + 1 );
|
|
}
|
|
if(!is_server && is_client)
|
|
{
|
|
|
|
if (INTERRUPT_QUEUED)
|
|
{
|
|
EndTurn( gbPlayerNum + 1 );//is ending interrupt instead
|
|
}
|
|
else
|
|
{
|
|
send_EndTurn( netbTeam+1 );//for sending next netbteam rather than next local team
|
|
}
|
|
}
|
|
}
|
|
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
|
|
UINT32 UIHandleTestHit( UI_EVENT *pUIEvent )
|
|
{
|
|
SOLDIERTYPE *pSoldier;
|
|
INT8 bDamage;
|
|
|
|
// CHECK IF WE'RE ON A GUY ( EITHER SELECTED, OURS, OR THEIRS
|
|
if ( gfUIFullTargetFound )
|
|
{
|
|
// Get Soldier
|
|
GetSoldier( &pSoldier, gusUIFullTargetID );
|
|
|
|
if ( _KeyDown( SHIFT ) )
|
|
{
|
|
pSoldier->bBreath -= 30;
|
|
|
|
if ( pSoldier->bBreath < 0 )
|
|
pSoldier->bBreath = 0;
|
|
|
|
bDamage = 1;
|
|
}
|
|
else
|
|
{
|
|
if ( Random(2) )
|
|
{
|
|
bDamage = 20;
|
|
}
|
|
else
|
|
{
|
|
bDamage = 25;
|
|
}
|
|
}
|
|
|
|
// gTacticalStatus.ubAttackBusyCount++;
|
|
DebugAttackBusy( "Testing a hit.\n" );
|
|
pSoldier->EVENT_SoldierGotHit( 1, bDamage, 10, pSoldier->ubDirection, 320, NOBODY , FIRE_WEAPON_NO_SPECIAL, pSoldier->bAimShotLocation, 0, NOWHERE );
|
|
// callahan update end - put everything as it was
|
|
}
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
void ChangeInterfaceLevel( INT16 sLevel )
|
|
{
|
|
// Only if different!
|
|
if ( sLevel == gsInterfaceLevel )
|
|
{
|
|
return;
|
|
}
|
|
|
|
gsInterfaceLevel = sLevel;
|
|
|
|
if ( gsInterfaceLevel == 1 )
|
|
{
|
|
gsRenderHeight += ROOF_LEVEL_HEIGHT;
|
|
gTacticalStatus.uiFlags |= SHOW_ALL_ROOFS;
|
|
InvalidateWorldRedundency( );
|
|
}
|
|
else if ( gsInterfaceLevel == 0 )
|
|
{
|
|
gsRenderHeight -= ROOF_LEVEL_HEIGHT;
|
|
gTacticalStatus.uiFlags &= (~SHOW_ALL_ROOFS );
|
|
InvalidateWorldRedundency( );
|
|
}
|
|
|
|
SetRenderFlags(RENDER_FLAG_FULL);
|
|
// Remove any interactive tiles we could be over!
|
|
BeginCurInteractiveTileCheck( INTILE_CHECK_SELECTIVE );
|
|
gfPlotNewMovement = TRUE;
|
|
ErasePath(FALSE);
|
|
}
|
|
|
|
|
|
UINT32 UIHandleChangeLevel( UI_EVENT *pUIEvent )
|
|
{
|
|
if ( gsInterfaceLevel == 0 )
|
|
{
|
|
ChangeInterfaceLevel( 1 );
|
|
}
|
|
else if ( gsInterfaceLevel == 1 )
|
|
{
|
|
ChangeInterfaceLevel( 0 );
|
|
}
|
|
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
|
|
extern void InternalSelectSoldier( UINT16 usSoldierID, BOOLEAN fAcknowledge, BOOLEAN fForceReselect, BOOLEAN fFromUI );
|
|
|
|
UINT32 UIHandleSelectMerc( UI_EVENT *pUIEvent )
|
|
{
|
|
INT32 iCurrentSquad;
|
|
|
|
// Get merc index at mouse and set current selection
|
|
if ( gfUIFullTargetFound )
|
|
{
|
|
iCurrentSquad = CurrentSquad( );
|
|
|
|
InternalSelectSoldier( gusUIFullTargetID, TRUE, FALSE, TRUE );
|
|
|
|
// If different, display message
|
|
if ( CurrentSquad( ) != iCurrentSquad )
|
|
{
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, pMessageStrings[ MSG_SQUAD_ACTIVE ], ( CurrentSquad( ) + 1 ) );
|
|
}
|
|
}
|
|
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
|
|
|
|
UINT32 UIHandleMOnTerrain( UI_EVENT *pUIEvent )
|
|
{
|
|
SOLDIERTYPE *pSoldier;
|
|
INT16 sMapPos;
|
|
BOOLEAN fSetCursor = FALSE;
|
|
UINT32 uiCursorFlags;
|
|
LEVELNODE *pIntNode;
|
|
EXITGRID ExitGrid;
|
|
INT16 sIntTileGridNo;
|
|
ITEM_POOL *pItemPool;
|
|
|
|
static INT16 sGridNoForItemsOver;
|
|
static INT8 bLevelForItemsOver;
|
|
static UINT32 uiItemsOverTimer;
|
|
static BOOLEAN fOverItems;
|
|
|
|
if( !GetMouseMapPos( &sMapPos) )
|
|
{
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
gUIActionModeChangeDueToMouseOver = FALSE;
|
|
|
|
// If we are a vehicle..... just show an X
|
|
if ( GetSoldier( &pSoldier, gusSelectedSoldier ) )
|
|
{
|
|
if ( ( OK_ENTERABLE_VEHICLE( pSoldier ) ) )
|
|
{
|
|
if ( !UIHandleOnMerc( TRUE ) )
|
|
{
|
|
guiNewUICursor = FLOATING_X_UICURSOR;
|
|
return( GAME_SCREEN );
|
|
}
|
|
}
|
|
}
|
|
|
|
// CHECK IF WE'RE ON A GUY ( EITHER SELECTED, OURS, OR THEIRS
|
|
if ( !UIHandleOnMerc( TRUE ) )
|
|
{
|
|
// Are we over items...
|
|
if ( GetItemPool( sMapPos, &pItemPool, (UINT8)gsInterfaceLevel ) && ITEMPOOL_VISIBLE( pItemPool ) )
|
|
{
|
|
// Are we already in...
|
|
if ( fOverItems )
|
|
{
|
|
// Is this the same level & gridno...
|
|
if ( gsInterfaceLevel == (INT16)bLevelForItemsOver && sMapPos == sGridNoForItemsOver )
|
|
{
|
|
// Check timer...
|
|
if ( ( GetJA2Clock( ) - uiItemsOverTimer ) > 1500 )
|
|
{
|
|
// Change to hand curso mode
|
|
guiPendingOverrideEvent = M_CHANGE_TO_HANDMODE;
|
|
gsOverItemsGridNo = sMapPos;
|
|
gsOverItemsLevel = gsInterfaceLevel;
|
|
fOverItems = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
uiItemsOverTimer = GetJA2Clock( );
|
|
bLevelForItemsOver = (INT8)gsInterfaceLevel;
|
|
sGridNoForItemsOver = sMapPos;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
fOverItems = TRUE;
|
|
|
|
uiItemsOverTimer = GetJA2Clock( );
|
|
bLevelForItemsOver = (INT8)gsInterfaceLevel;
|
|
sGridNoForItemsOver = sMapPos;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
fOverItems = FALSE;
|
|
}
|
|
|
|
|
|
if ( GetSoldier( &pSoldier, gusSelectedSoldier ) )
|
|
{
|
|
if ( GetExitGrid( sMapPos, &ExitGrid ) && pSoldier->pathing.bLevel == 0 )
|
|
{
|
|
gfUIShowExitExitGrid = TRUE;
|
|
}
|
|
|
|
// ATE: Draw invalidc cursor if heights different
|
|
if ( gpWorldLevelData[ sMapPos ].sHeight != gpWorldLevelData[ pSoldier->sGridNo ].sHeight )
|
|
{
|
|
// ERASE PATH
|
|
ErasePath( TRUE );
|
|
|
|
guiNewUICursor = FLOATING_X_UICURSOR;
|
|
|
|
return( GAME_SCREEN );
|
|
}
|
|
}
|
|
|
|
// DO SOME CURSOR POSITION FLAGS SETTING
|
|
GetCursorMovementFlags( &uiCursorFlags );
|
|
|
|
if ( gusSelectedSoldier != NOBODY )
|
|
{
|
|
// Get Soldier Pointer
|
|
GetSoldier( &pSoldier, gusSelectedSoldier );
|
|
|
|
// Get interactvie tile node
|
|
pIntNode = GetCurInteractiveTileGridNo( &sIntTileGridNo );
|
|
|
|
// Check were we are
|
|
// CHECK IF WE CAN MOVE HERE
|
|
// THIS IS JUST A CRUDE TEST FOR NOW
|
|
if ( pSoldier->stats.bLife < OKLIFE )
|
|
{
|
|
UINT8 ubID;
|
|
// Show reg. cursor
|
|
// GO INTO IDLE MODE
|
|
// guiPendingOverrideEvent = I_CHANGE_TO_IDLE;
|
|
// gusSelectedSoldier = NOBODY;
|
|
ubID = FindNextActiveAndAliveMerc( pSoldier, FALSE, FALSE );
|
|
|
|
if ( ubID != NOBODY )
|
|
{
|
|
SelectSoldier( (INT16)ubID, FALSE, FALSE );
|
|
}
|
|
else
|
|
{
|
|
gusSelectedSoldier = NOBODY;
|
|
// Change UI mode to reflact that we are selected
|
|
guiPendingOverrideEvent = I_ON_TERRAIN;
|
|
}
|
|
}
|
|
else if ( ( UIOKMoveDestination( pSoldier, sMapPos ) != 1 ) && pIntNode == NULL )
|
|
{
|
|
// ERASE PATH
|
|
ErasePath( TRUE );
|
|
|
|
guiNewUICursor = CANNOT_MOVE_UICURSOR;
|
|
|
|
}
|
|
else
|
|
{
|
|
if ( !UIHandleInteractiveTilesAndItemsOnTerrain( pSoldier, sMapPos, FALSE, TRUE ) )
|
|
{
|
|
// Are we in combat?
|
|
if ( (gTacticalStatus.uiFlags & INCOMBAT ) && ( gTacticalStatus.uiFlags & TURNBASED ) )
|
|
{
|
|
// If so, draw path, etc
|
|
fSetCursor = HandleUIMovementCursor( pSoldier, uiCursorFlags, sMapPos, 0 );
|
|
}
|
|
else
|
|
{
|
|
// Donot draw path until confirm
|
|
fSetCursor = TRUE;
|
|
|
|
// If so, draw path, etc
|
|
fSetCursor = HandleUIMovementCursor( pSoldier, uiCursorFlags, sMapPos, 0 );
|
|
|
|
//ErasePath( TRUE );
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
fSetCursor = TRUE;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// IF GUSSELECTEDSOLDIER != NOSOLDIER
|
|
guiNewUICursor = NORMAL_SNAPUICURSOR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( ValidQuickExchangePosition( ) )
|
|
{
|
|
// Do new cursor!
|
|
guiNewUICursor = EXCHANGE_PLACES_UICURSOR;
|
|
}
|
|
}
|
|
|
|
|
|
{
|
|
|
|
//if ( fSetCursor && guiNewUICursor != ENTER_VEHICLE_UICURSOR )
|
|
if ( fSetCursor && !gfBeginVehicleCursor )
|
|
{
|
|
SetMovementModeCursor( pSoldier );
|
|
}
|
|
}
|
|
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
UINT32 UIHandleMovementMenu( UI_EVENT *pUIEvent )
|
|
{
|
|
SOLDIERTYPE *pSoldier;
|
|
|
|
|
|
// Get soldier
|
|
if ( !GetSoldier( &pSoldier, gusSelectedSoldier ) )
|
|
{
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
// Popup Menu
|
|
if ( pUIEvent->fFirstTime )
|
|
{
|
|
//Pop-up menu
|
|
PopupMovementMenu( pUIEvent );
|
|
|
|
// Change cusror to normal
|
|
guiNewUICursor = NORMAL_FREEUICURSOR;
|
|
|
|
}
|
|
|
|
// Check for done flag
|
|
if ( pUIEvent->fDoneMenu )
|
|
{
|
|
PopDownMovementMenu( );
|
|
|
|
// Excecute command, if user hit a button
|
|
if ( pUIEvent->uiParams[1] == TRUE )
|
|
{
|
|
if ( pUIEvent->uiParams[ 2 ] == MOVEMENT_MENU_LOOK )
|
|
{
|
|
guiPendingOverrideEvent = LC_CHANGE_TO_LOOK;
|
|
}
|
|
else if ( pUIEvent->uiParams[ 2 ] == MOVEMENT_MENU_HAND )
|
|
{
|
|
guiPendingOverrideEvent = HC_ON_TERRAIN;
|
|
}
|
|
else if ( pUIEvent->uiParams[ 2 ] == MOVEMENT_MENU_ACTIONC )
|
|
{
|
|
guiPendingOverrideEvent = M_CHANGE_TO_ACTION;
|
|
}
|
|
else if ( pUIEvent->uiParams[ 2 ] == MOVEMENT_MENU_TALK )
|
|
{
|
|
guiPendingOverrideEvent = T_CHANGE_TO_TALKING;
|
|
}
|
|
else
|
|
{
|
|
// Change stance based on params!
|
|
switch( pUIEvent->uiParams[ 0 ] )
|
|
{
|
|
case MOVEMENT_MENU_RUN:
|
|
|
|
if ( pSoldier->usUIMovementMode != WALKING && pSoldier->usUIMovementMode != RUNNING )
|
|
{
|
|
UIHandleSoldierStanceChange( pSoldier->ubID, ANIM_STAND );
|
|
pSoldier->flags.fUIMovementFast = 1;
|
|
}
|
|
else
|
|
{
|
|
pSoldier->flags.fUIMovementFast = 1;
|
|
pSoldier->usUIMovementMode = RUNNING;
|
|
gfPlotNewMovement = TRUE;
|
|
}
|
|
break;
|
|
|
|
case MOVEMENT_MENU_WALK:
|
|
|
|
UIHandleSoldierStanceChange( pSoldier->ubID, ANIM_STAND );
|
|
break;
|
|
|
|
case MOVEMENT_MENU_SWAT:
|
|
|
|
UIHandleSoldierStanceChange( pSoldier->ubID, ANIM_CROUCH );
|
|
break;
|
|
|
|
case MOVEMENT_MENU_PRONE:
|
|
|
|
UIHandleSoldierStanceChange( pSoldier->ubID, ANIM_PRONE );
|
|
break;
|
|
|
|
}
|
|
|
|
guiPendingOverrideEvent = A_CHANGE_TO_MOVE;
|
|
|
|
//pSoldier->usUIMovementMode = (INT8)pUIEvent->uiParams[ 0 ];
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
|
|
UINT32 UIHandlePositionMenu( UI_EVENT *pUIEvent )
|
|
{
|
|
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
|
|
UINT32 UIHandleAOnTerrain( UI_EVENT *pUIEvent )
|
|
{
|
|
UINT16 sMapPos;
|
|
SOLDIERTYPE *pSoldier;
|
|
// INT16 sTargetXPos, sTargetYPos;
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("UIHandleAOnTerrain"));
|
|
|
|
if( !GetMouseMapPos( (INT16*)&sMapPos) )
|
|
{
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
if ( gpItemPointer != NULL )
|
|
{
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
// Get soldier to determine range
|
|
if ( GetSoldier( &pSoldier, gusSelectedSoldier ) )
|
|
{
|
|
// ATE: Add stuff here to display a system message if we are targeting smeothing and
|
|
// are out of range.
|
|
// Are we using a gun?
|
|
if ( GetActionModeCursor( pSoldier ) == TARGETCURS )
|
|
{
|
|
SetActionModeDoorCursorText( );
|
|
|
|
// Yep, she's a gun.
|
|
// Are we in range?
|
|
if ( !InRange( pSoldier, sMapPos ) )
|
|
{
|
|
// Are we over a guy?
|
|
if ( gfUIFullTargetFound )
|
|
{
|
|
// No, ok display message IF this is the first time at this gridno
|
|
if ( gsOutOfRangeGridNo != MercPtrs[ gusUIFullTargetID ]->sGridNo || gubOutOfRangeMerc != gusSelectedSoldier )
|
|
{
|
|
// Display
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, TacticalStr[ OUT_OF_RANGE_STRING ] );
|
|
|
|
//PlayJA2Sample( TARGET_OUT_OF_RANGE, RATE_11025, MIDVOLUME, 1, MIDDLEPAN );
|
|
|
|
// Set
|
|
gsOutOfRangeGridNo = MercPtrs[ gusUIFullTargetID ]->sGridNo;
|
|
gubOutOfRangeMerc = (UINT8)gusSelectedSoldier;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
guiNewUICursor = GetProperItemCursor( (UINT8)gusSelectedSoldier, pSoldier->inv[ HANDPOS ].usItem, sMapPos, FALSE );
|
|
|
|
// Show UI ON GUY
|
|
UIHandleOnMerc( FALSE );
|
|
|
|
// If we are in realtime, and in a stationary animation, follow!
|
|
if ( ( gTacticalStatus.uiFlags & REALTIME ) || !( gTacticalStatus.uiFlags & INCOMBAT ) )
|
|
{
|
|
if ( gAnimControl[ pSoldier->usAnimState ].uiFlags & ANIM_STATIONARY && pSoldier->aiData.ubPendingAction == NO_PENDING_ACTION )
|
|
{
|
|
// Check if we have a shot waiting!
|
|
if ( gUITargetShotWaiting )
|
|
{
|
|
guiPendingOverrideEvent = CA_MERC_SHOOT;
|
|
}
|
|
|
|
if ( !gUITargetReady )
|
|
{
|
|
// Move to proper stance + direction!
|
|
// Convert our grid-not into an XY
|
|
// ConvertGridNoToXY( sMapPos, &sTargetXPos, &sTargetYPos );
|
|
|
|
// Ready weapon
|
|
// pSoldier->SoldierReadyWeapon(sTargetXPos, sTargetYPos, FALSE );
|
|
|
|
gUITargetReady = TRUE;
|
|
}
|
|
|
|
|
|
|
|
}
|
|
else
|
|
{
|
|
gUITargetReady = FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return( GAME_SCREEN );
|
|
|
|
}
|
|
|
|
UINT32 UIHandleMChangeToAction( UI_EVENT *pUIEvent )
|
|
{
|
|
gUITargetShotWaiting = FALSE;
|
|
|
|
EndPhysicsTrajectoryUI( );
|
|
|
|
//guiNewUICursor = CONFIRM_MOVE_UICURSOR;
|
|
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
UINT32 UIHandleMChangeToHandMode( UI_EVENT *pUIEvent )
|
|
{
|
|
ErasePath( FALSE );
|
|
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
UINT32 UIHandleAChangeToMove( UI_EVENT *pUIEvent )
|
|
{
|
|
// Set merc glow back to normal
|
|
// ( could have been set when in target cursor )
|
|
SetMercGlowNormal( );
|
|
|
|
// gsOutOfRangeGridNo = NOWHERE;
|
|
|
|
gfPlotNewMovement = TRUE;
|
|
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
UINT32 UIHandleCWait( UI_EVENT *pUIEvent )
|
|
{
|
|
INT16 sMapPos;
|
|
SOLDIERTYPE *pSoldier;
|
|
BOOLEAN fSetCursor;
|
|
UINT32 uiCursorFlags;
|
|
LEVELNODE *pInvTile;
|
|
|
|
if( !GetMouseMapPos( &sMapPos) )
|
|
{
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
if ( GetSoldier( &pSoldier, gusSelectedSoldier ) )
|
|
{
|
|
pInvTile = GetCurInteractiveTile( );
|
|
|
|
if ( pInvTile && gpInvTileThatCausedMoveConfirm != pInvTile )
|
|
{
|
|
// Get out og this mode...
|
|
guiPendingOverrideEvent = A_CHANGE_TO_MOVE;
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
GetCursorMovementFlags( &uiCursorFlags );
|
|
|
|
if ( pInvTile != NULL )
|
|
{
|
|
|
|
fSetCursor = HandleUIMovementCursor( pSoldier, uiCursorFlags, sMapPos, MOVEUI_TARGET_INTTILES );
|
|
|
|
//Set UI CURSOR
|
|
guiNewUICursor = GetInteractiveTileCursor( guiNewUICursor, TRUE );
|
|
|
|
// Make red tile under spot... if we've previously found one...
|
|
if ( gfUIHandleShowMoveGrid )
|
|
{
|
|
gfUIHandleShowMoveGrid = 2;
|
|
}
|
|
|
|
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
// Display action points
|
|
gfUIDisplayActionPoints = TRUE;
|
|
|
|
// Determine if we can afford!
|
|
if ( !EnoughPoints( pSoldier, gsCurrentActionPoints, 0, FALSE ) )
|
|
{
|
|
gfUIDisplayActionPointsInvalid = TRUE;
|
|
}
|
|
|
|
SetConfirmMovementModeCursor( pSoldier, FALSE );
|
|
|
|
// If we are not in combat, draw path here!
|
|
if ( (gTacticalStatus.uiFlags & REALTIME ) || !(gTacticalStatus.uiFlags & INCOMBAT ) )
|
|
{
|
|
//DrawUIMovementPath( pSoldier, sMapPos, 0 );
|
|
fSetCursor = HandleUIMovementCursor( pSoldier, uiCursorFlags, sMapPos, 0 );
|
|
}
|
|
|
|
}
|
|
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
|
|
// NOTE, ONCE AT THIS FUNCTION, WE HAVE ASSUMED TO HAVE CHECKED FOR ENOUGH APS THROUGH
|
|
// SelectedMercCanAffordMove
|
|
UINT32 UIHandleCMoveMerc( UI_EVENT *pUIEvent )
|
|
{
|
|
INT16 sMapPos;
|
|
SOLDIERTYPE *pSoldier;
|
|
INT16 sDestGridNo;
|
|
INT16 sActionGridNo;
|
|
STRUCTURE *pStructure;
|
|
UINT8 ubDirection = 0xff;
|
|
BOOLEAN fAllMove;
|
|
INT8 bLoop;
|
|
LEVELNODE *pIntTile;
|
|
INT16 sIntTileGridNo;
|
|
BOOLEAN fOldFastMove;
|
|
|
|
if ( gusSelectedSoldier != NOBODY )
|
|
{
|
|
fAllMove = gfUIAllMoveOn;
|
|
gfUIAllMoveOn = FALSE;
|
|
|
|
if( !GetMouseMapPos( &sMapPos) )
|
|
{
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
// ERASE PATH
|
|
ErasePath( TRUE );
|
|
|
|
if ( fAllMove )
|
|
{
|
|
gfGetNewPathThroughPeople = TRUE;
|
|
|
|
// Loop through all mercs and make go!
|
|
// TODO: Only our squad!
|
|
for (bLoop=gTacticalStatus.Team[gbPlayerNum].bFirstID, pSoldier=MercPtrs[bLoop]; bLoop <= gTacticalStatus.Team[gbPlayerNum].bLastID; bLoop++, pSoldier++)
|
|
{
|
|
if ( OK_CONTROLLABLE_MERC( pSoldier ) && pSoldier->bAssignment == CurrentSquad( ) && !pSoldier->flags.fMercAsleep )
|
|
{
|
|
// If we can't be controlled, returninvalid...
|
|
if ( pSoldier->flags.uiStatusFlags & SOLDIER_ROBOT )
|
|
{
|
|
if ( !pSoldier->CanRobotBeControlled( ) )
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
|
|
pSoldier->AdjustNoAPToFinishMove( FALSE );
|
|
|
|
fOldFastMove = pSoldier->flags.fUIMovementFast;
|
|
|
|
if ( fAllMove == 2 )
|
|
{
|
|
pSoldier->flags.fUIMovementFast = TRUE;
|
|
pSoldier->usUIMovementMode = RUNNING;
|
|
}
|
|
else
|
|
{
|
|
pSoldier->flags.fUIMovementFast = FALSE;
|
|
pSoldier->usUIMovementMode = pSoldier->GetMoveStateBasedOnStance( gAnimControl[ pSoldier->usAnimState ].ubEndHeight );
|
|
}
|
|
|
|
// Remove any previous actions
|
|
pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION;
|
|
|
|
|
|
//if ( !( gTacticalStatus.uiFlags & INCOMBAT ) && ( gAnimControl[ pSoldier->usAnimState ].uiFlags & ANIM_MOVING ) )
|
|
//{
|
|
// pSoldier->sRTPendingMovementGridNo = sMapPos;
|
|
// pSoldier->usRTPendingMovementAnim = pSoldier->usUIMovementMode;
|
|
//}
|
|
//else
|
|
if ( pSoldier->EVENT_InternalGetNewSoldierPath( sMapPos, pSoldier->usUIMovementMode, TRUE, FALSE ) )
|
|
{
|
|
pSoldier->InternalDoMercBattleSound( BATTLE_SOUND_OK1, BATTLE_SND_LOWER_VOLUME );
|
|
}
|
|
else
|
|
{
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, TacticalStr[ NO_PATH_FOR_MERC ], pSoldier->name );
|
|
}
|
|
|
|
pSoldier->flags.fUIMovementFast = fOldFastMove;
|
|
|
|
}
|
|
}
|
|
gfGetNewPathThroughPeople = FALSE;
|
|
|
|
// RESET MOVE FAST FLAG
|
|
SetConfirmMovementModeCursor( pSoldier, TRUE );
|
|
|
|
gfUIAllMoveOn = 0;
|
|
|
|
}
|
|
else
|
|
{
|
|
// Get soldier
|
|
if ( GetSoldier( &pSoldier, gusSelectedSoldier ) )
|
|
{
|
|
// CHRISL: This block should only run if we're running in the new inventory system
|
|
if((UsingNewInventorySystem() == true))
|
|
{
|
|
// CHRISL: If we're in combat and zipper is active, don't allow movement
|
|
if((gTacticalStatus.uiFlags & INCOMBAT) && pSoldier->flags.ZipperFlag)
|
|
{
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, NewInvMessage[NIV_ZIPPER_NO_MOVE] );
|
|
return( GAME_SCREEN );
|
|
}
|
|
// CHRISL: If we're not in combat but the zipper is active and we're moving, deactivate the zipper
|
|
if(!(gTacticalStatus.uiFlags & INCOMBAT) && pSoldier->flags.ZipperFlag)
|
|
{
|
|
pSoldier->flags.ZipperFlag=FALSE;
|
|
RenderBackpackButtons(0);
|
|
}
|
|
}
|
|
// FOR REALTIME - DO MOVEMENT BASED ON STANCE!
|
|
if ( ( gTacticalStatus.uiFlags & REALTIME ) || !( gTacticalStatus.uiFlags & INCOMBAT ) )
|
|
{
|
|
pSoldier->usUIMovementMode = pSoldier->GetMoveStateBasedOnStance( gAnimControl[ pSoldier->usAnimState ].ubEndHeight );
|
|
}
|
|
|
|
|
|
sDestGridNo = sMapPos;
|
|
|
|
|
|
// Get structure info for in tile!
|
|
pIntTile = GetCurInteractiveTileGridNoAndStructure( &sIntTileGridNo, &pStructure );
|
|
|
|
// We should not have null here if we are given this flag...
|
|
if ( pIntTile != NULL )
|
|
{
|
|
sActionGridNo = FindAdjacentGridEx( pSoldier, sIntTileGridNo, &ubDirection, NULL, FALSE, TRUE );
|
|
if ( sActionGridNo != -1 )
|
|
{
|
|
SetUIBusy( pSoldier->ubID );
|
|
|
|
// Set dest gridno
|
|
sDestGridNo = sActionGridNo;
|
|
|
|
// check if we are at this location
|
|
if ( pSoldier->sGridNo == sDestGridNo )
|
|
{
|
|
StartInteractiveObject( sIntTileGridNo, pStructure->usStructureID, pSoldier, ubDirection );
|
|
InteractWithInteractiveObject( pSoldier, pStructure, ubDirection );
|
|
return( GAME_SCREEN );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, TacticalStr[ NO_PATH ] );
|
|
return( GAME_SCREEN );
|
|
}
|
|
}
|
|
|
|
SetUIBusy( pSoldier->ubID );
|
|
|
|
if ( ( gTacticalStatus.uiFlags & REALTIME ) || !( gTacticalStatus.uiFlags & INCOMBAT ) )
|
|
{
|
|
// RESET MOVE FAST FLAG
|
|
SetConfirmMovementModeCursor( pSoldier, TRUE );
|
|
|
|
if ( !gTacticalStatus.fAtLeastOneGuyOnMultiSelect )
|
|
{
|
|
pSoldier->flags.fUIMovementFast = FALSE;
|
|
}
|
|
|
|
//StartLooseCursor( sMapPos, 0 );
|
|
}
|
|
|
|
if ( gTacticalStatus.fAtLeastOneGuyOnMultiSelect && pIntTile == NULL )
|
|
{
|
|
HandleMultiSelectionMove( sDestGridNo );
|
|
}
|
|
else
|
|
{
|
|
|
|
if ( gUIUseReverse )
|
|
{
|
|
pSoldier->bReverse = TRUE;
|
|
}
|
|
else
|
|
{
|
|
pSoldier->bReverse = FALSE;
|
|
}
|
|
|
|
// Remove any previous actions
|
|
pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION;
|
|
|
|
{
|
|
pSoldier->EVENT_InternalGetNewSoldierPath( sDestGridNo, pSoldier->usUIMovementMode , TRUE, pSoldier->flags.fNoAPToFinishMove );
|
|
}
|
|
|
|
if ( pSoldier->pathing.usPathDataSize > 5 )
|
|
{
|
|
pSoldier->DoMercBattleSound( BATTLE_SOUND_OK1 );
|
|
}
|
|
|
|
// HANDLE ANY INTERACTIVE OBJECTS HERE!
|
|
if ( pIntTile != NULL )
|
|
{
|
|
StartInteractiveObject( sIntTileGridNo, pStructure->usStructureID, pSoldier, ubDirection );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
UINT32 UIHandleMCycleMoveAll( UI_EVENT *pUIEvent )
|
|
{
|
|
SOLDIERTYPE *pSoldier;
|
|
|
|
if ( !GetSoldier( &pSoldier, gusSelectedSoldier ) )
|
|
{
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
if ( gfUICanBeginAllMoveCycle )
|
|
{
|
|
gfUIAllMoveOn = TRUE;
|
|
gfUICanBeginAllMoveCycle = FALSE;
|
|
}
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
|
|
UINT32 UIHandleMCycleMovement( UI_EVENT *pUIEvent )
|
|
{
|
|
SOLDIERTYPE *pSoldier;
|
|
BOOLEAN fGoodMode = FALSE;
|
|
|
|
if ( !GetSoldier( &pSoldier, gusSelectedSoldier ) )
|
|
{
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
gfUIAllMoveOn = FALSE;
|
|
|
|
if ( pSoldier->ubBodyType == ROBOTNOWEAPON )
|
|
{
|
|
pSoldier->usUIMovementMode = WALKING;
|
|
gfPlotNewMovement = TRUE;
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
do
|
|
{
|
|
// Cycle gmovement state
|
|
if ( pSoldier->usUIMovementMode == RUNNING )
|
|
{
|
|
pSoldier->usUIMovementMode = WALKING;
|
|
if ( IsValidMovementMode( pSoldier, WALKING ) )
|
|
{
|
|
fGoodMode = TRUE;
|
|
}
|
|
}
|
|
else if ( pSoldier->usUIMovementMode == WALKING )
|
|
{
|
|
pSoldier->usUIMovementMode = SWATTING;
|
|
if ( IsValidMovementMode( pSoldier, SWATTING ) )
|
|
{
|
|
fGoodMode = TRUE;
|
|
}
|
|
}
|
|
else if ( pSoldier->usUIMovementMode == SWATTING )
|
|
{
|
|
pSoldier->usUIMovementMode = CRAWLING;
|
|
if ( IsValidMovementMode( pSoldier, CRAWLING ) )
|
|
{
|
|
fGoodMode = TRUE;
|
|
}
|
|
}
|
|
else if ( pSoldier->usUIMovementMode == CRAWLING )
|
|
{
|
|
pSoldier->flags.fUIMovementFast = 1;
|
|
pSoldier->usUIMovementMode = RUNNING;
|
|
if ( IsValidMovementMode( pSoldier, RUNNING ) )
|
|
{
|
|
fGoodMode = TRUE;
|
|
}
|
|
}
|
|
|
|
} while( fGoodMode != TRUE );
|
|
|
|
gfPlotNewMovement = TRUE;
|
|
|
|
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
UINT32 UIHandleCOnTerrain( UI_EVENT *pUIEvent )
|
|
{
|
|
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
|
|
UINT32 UIHandleMAdjustStanceMode( UI_EVENT *pUIEvent )
|
|
{
|
|
SOLDIERTYPE *pSoldier;
|
|
INT32 iPosDiff;
|
|
static UINT16 gusAnchorMouseY;
|
|
static UINT16 usOldMouseY;
|
|
static BOOLEAN ubNearHeigherLevel;
|
|
static BOOLEAN ubNearLowerLevel;
|
|
static UINT8 ubUpHeight, ubDownDepth;
|
|
static UINT32 uiOldShowUPDownArrows;
|
|
INT8 bNewDirection;
|
|
|
|
// Change cusror to normal
|
|
guiNewUICursor = NO_UICURSOR;
|
|
|
|
|
|
if ( pUIEvent->fFirstTime )
|
|
{
|
|
gusAnchorMouseY = gusMouseYPos;
|
|
usOldMouseY = gusMouseYPos;
|
|
ubNearHeigherLevel = FALSE;
|
|
ubNearLowerLevel = FALSE;
|
|
|
|
guiShowUPDownArrows = ARROWS_SHOW_DOWN_BESIDE | ARROWS_SHOW_UP_BESIDE;
|
|
uiOldShowUPDownArrows = guiShowUPDownArrows;
|
|
|
|
gbAdjustStanceDiff = 0;
|
|
gbClimbID = 0;
|
|
|
|
gfIgnoreScrolling = TRUE;
|
|
|
|
// Get soldier current height of animation
|
|
if ( GetSoldier( &pSoldier, gusSelectedSoldier ) )
|
|
{
|
|
// IF we are on a basic level...(temp)
|
|
if ( pSoldier->pathing.bLevel == 0 )
|
|
{
|
|
if ( FindHeigherLevel( pSoldier, pSoldier->sGridNo, pSoldier->ubDirection, &bNewDirection ) )
|
|
{
|
|
ubNearHeigherLevel = TRUE;
|
|
}
|
|
}
|
|
|
|
// IF we are higher...
|
|
if ( pSoldier->pathing.bLevel > 0 )
|
|
{
|
|
if ( FindLowerLevel( pSoldier, pSoldier->sGridNo, pSoldier->ubDirection, &bNewDirection ) )
|
|
{
|
|
ubNearLowerLevel = TRUE;
|
|
}
|
|
}
|
|
|
|
switch( gAnimControl[ pSoldier->usAnimState ].ubEndHeight )
|
|
{
|
|
case ANIM_STAND:
|
|
if ( ubNearHeigherLevel )
|
|
{
|
|
ubUpHeight = 1;
|
|
ubDownDepth = 2;
|
|
}
|
|
else if ( ubNearLowerLevel )
|
|
{
|
|
ubUpHeight = 0;
|
|
ubDownDepth = 3;
|
|
}
|
|
else
|
|
{
|
|
ubUpHeight = 0;
|
|
ubDownDepth = 2;
|
|
}
|
|
break;
|
|
|
|
case ANIM_CROUCH:
|
|
if ( ubNearHeigherLevel )
|
|
{
|
|
ubUpHeight = 2;
|
|
ubDownDepth = 1;
|
|
}
|
|
else if ( ubNearLowerLevel )
|
|
{
|
|
ubUpHeight = 1;
|
|
ubDownDepth = 2;
|
|
}
|
|
else
|
|
{
|
|
ubUpHeight = 1;
|
|
ubDownDepth = 1;
|
|
}
|
|
break;
|
|
|
|
case ANIM_PRONE:
|
|
if ( ubNearHeigherLevel )
|
|
{
|
|
ubUpHeight = 3;
|
|
ubDownDepth = 0;
|
|
}
|
|
else if ( ubNearLowerLevel )
|
|
{
|
|
ubUpHeight = 2;
|
|
ubDownDepth = 1;
|
|
}
|
|
else
|
|
{
|
|
ubUpHeight = 2;
|
|
ubDownDepth = 0;
|
|
}
|
|
break;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Check if delta X has changed alot since last time
|
|
iPosDiff = abs( (INT32)( usOldMouseY - gusMouseYPos) );
|
|
|
|
//guiShowUPDownArrows = ARROWS_SHOW_DOWN_BESIDE | ARROWS_SHOW_UP_BESIDE;
|
|
guiShowUPDownArrows = uiOldShowUPDownArrows;
|
|
|
|
{
|
|
if ( gusAnchorMouseY > gusMouseYPos )
|
|
{
|
|
// Get soldier
|
|
if ( GetSoldier( &pSoldier, gusSelectedSoldier ) )
|
|
{
|
|
if ( iPosDiff < GO_MOVE_ONE && ubUpHeight >= 1 )
|
|
{
|
|
// Change arrows to move down arrow + show
|
|
//guiShowUPDownArrows = ARROWS_SHOW_UP_ABOVE_Y;
|
|
guiShowUPDownArrows = ARROWS_SHOW_DOWN_BESIDE | ARROWS_SHOW_UP_BESIDE;
|
|
gbAdjustStanceDiff = 0;
|
|
gbClimbID = 0;
|
|
}
|
|
else if ( iPosDiff > GO_MOVE_ONE && iPosDiff < GO_MOVE_TWO && ubUpHeight >= 1 )
|
|
{
|
|
//guiShowUPDownArrows = ARROWS_SHOW_UP_ABOVE_G;
|
|
if ( ubUpHeight == 1 && ubNearHeigherLevel )
|
|
{
|
|
guiShowUPDownArrows = ARROWS_SHOW_UP_ABOVE_CLIMB;
|
|
gbClimbID = 1;
|
|
}
|
|
else
|
|
{
|
|
guiShowUPDownArrows = ARROWS_SHOW_UP_ABOVE_Y;
|
|
gbClimbID = 0;
|
|
}
|
|
gbAdjustStanceDiff = 1;
|
|
}
|
|
else if ( iPosDiff >= GO_MOVE_TWO && iPosDiff < GO_MOVE_THREE && ubUpHeight >= 2 )
|
|
{
|
|
if ( ubUpHeight == 2 && ubNearHeigherLevel )
|
|
{
|
|
guiShowUPDownArrows = ARROWS_SHOW_UP_ABOVE_CLIMB;
|
|
gbClimbID = 1;
|
|
}
|
|
else
|
|
{
|
|
guiShowUPDownArrows = ARROWS_SHOW_UP_ABOVE_YY;
|
|
gbClimbID = 0;
|
|
}
|
|
gbAdjustStanceDiff = 2;
|
|
}
|
|
else if ( iPosDiff >= GO_MOVE_THREE && ubUpHeight >= 3 )
|
|
{
|
|
if ( ubUpHeight == 3 && ubNearHeigherLevel )
|
|
{
|
|
guiShowUPDownArrows = ARROWS_SHOW_UP_ABOVE_CLIMB;
|
|
gbClimbID = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
if ( gusAnchorMouseY < gusMouseYPos )
|
|
{
|
|
|
|
// Get soldier
|
|
if ( GetSoldier( &pSoldier, gusSelectedSoldier ) )
|
|
{
|
|
if ( iPosDiff < GO_MOVE_ONE && ubDownDepth >= 1 )
|
|
{
|
|
// Change arrows to move down arrow + show
|
|
//guiShowUPDownArrows = ARROWS_SHOW_DOWN_BELOW_Y;
|
|
guiShowUPDownArrows = ARROWS_SHOW_DOWN_BESIDE | ARROWS_SHOW_UP_BESIDE;
|
|
gbAdjustStanceDiff = 0;
|
|
gbClimbID = 0;
|
|
|
|
}
|
|
else if ( iPosDiff >= GO_MOVE_ONE && iPosDiff < GO_MOVE_TWO && ubDownDepth >= 1 )
|
|
{
|
|
// guiShowUPDownArrows = ARROWS_SHOW_DOWN_BELOW_G;
|
|
if ( ubDownDepth == 1 && ubNearLowerLevel )
|
|
{
|
|
guiShowUPDownArrows = ARROWS_SHOW_DOWN_CLIMB;
|
|
gbClimbID = -1;
|
|
}
|
|
else
|
|
{
|
|
guiShowUPDownArrows = ARROWS_SHOW_DOWN_BELOW_Y;
|
|
gbClimbID = 0;
|
|
}
|
|
gbAdjustStanceDiff = -1;
|
|
}
|
|
else if ( iPosDiff > GO_MOVE_TWO && iPosDiff < GO_MOVE_THREE && ubDownDepth >= 2 )
|
|
{
|
|
//guiShowUPDownArrows = ARROWS_SHOW_DOWN_BELOW_GG;
|
|
if ( ubDownDepth == 2 && ubNearLowerLevel )
|
|
{
|
|
guiShowUPDownArrows = ARROWS_SHOW_DOWN_CLIMB;
|
|
gbClimbID = -1;
|
|
}
|
|
else
|
|
{
|
|
guiShowUPDownArrows = ARROWS_SHOW_DOWN_BELOW_YY;
|
|
gbClimbID = 0;
|
|
}
|
|
gbAdjustStanceDiff = -2;
|
|
}
|
|
else if ( iPosDiff > GO_MOVE_THREE && ubDownDepth >= 3 )
|
|
{
|
|
//guiShowUPDownArrows = ARROWS_SHOW_DOWN_BELOW_GG;
|
|
if ( ubDownDepth == 3 && ubNearLowerLevel )
|
|
{
|
|
guiShowUPDownArrows = ARROWS_SHOW_DOWN_CLIMB;
|
|
gbClimbID = -1;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
uiOldShowUPDownArrows = guiShowUPDownArrows;
|
|
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
UINT32 UIHandleAChangeToConfirmAction( UI_EVENT *pUIEvent )
|
|
{
|
|
SOLDIERTYPE *pSoldier;
|
|
|
|
if ( GetSoldier( &pSoldier, gusSelectedSoldier ) )
|
|
{
|
|
HandleLeftClickCursor( pSoldier );
|
|
|
|
}
|
|
|
|
ResetBurstLocations( );
|
|
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
|
|
UINT32 UIHandleCAOnTerrain( UI_EVENT *pUIEvent )
|
|
{
|
|
SOLDIERTYPE *pSoldier;
|
|
INT16 sMapPos;
|
|
|
|
if( !GetMouseMapPos( &sMapPos) )
|
|
{
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
if ( GetSoldier( &pSoldier, gusSelectedSoldier ) )
|
|
{
|
|
guiNewUICursor = GetProperItemCursor( (UINT8)gusSelectedSoldier, pSoldier->inv[ HANDPOS ].usItem, sMapPos, TRUE );
|
|
|
|
UIHandleOnMerc( FALSE );
|
|
|
|
}
|
|
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
|
|
|
|
void UIHandleMercAttack( SOLDIERTYPE *pSoldier , SOLDIERTYPE *pTargetSoldier, INT16 sMapPos )
|
|
{
|
|
INT32 iHandleReturn;
|
|
INT16 sTargetGridNo;
|
|
INT8 bTargetLevel;
|
|
UINT16 usItem;
|
|
LEVELNODE *pIntNode;
|
|
STRUCTURE *pStructure;
|
|
INT16 sGridNo, sNewGridNo;
|
|
UINT8 ubItemCursor;
|
|
|
|
// get cursor
|
|
ubItemCursor = GetActionModeCursor( pSoldier );
|
|
|
|
if ( !(gTacticalStatus.uiFlags & INCOMBAT) && pTargetSoldier && Item[ pSoldier->inv[ HANDPOS ].usItem ].usItemClass & IC_WEAPON )
|
|
{
|
|
if ( NPCFirstDraw( pSoldier, pTargetSoldier ) )
|
|
{
|
|
// go into turnbased for that person
|
|
CancelAIAction( pTargetSoldier, TRUE );
|
|
AddToShouldBecomeHostileOrSayQuoteList( pTargetSoldier->ubID );
|
|
//MakeCivHostile( pTargetSoldier, 2 );
|
|
//TriggerNPCWithIHateYouQuote( pTargetSoldier->ubProfile );
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Set aim time to one in UI
|
|
pSoldier->aiData.bAimTime = (pSoldier->aiData.bShownAimTime );
|
|
usItem = pSoldier->inv[ HANDPOS ].usItem;
|
|
|
|
// ATE: Check if we are targeting an interactive tile, and adjust gridno accordingly...
|
|
pIntNode = GetCurInteractiveTileGridNoAndStructure( &sGridNo, &pStructure );
|
|
|
|
if ( pTargetSoldier != NULL )
|
|
{
|
|
sTargetGridNo = pTargetSoldier->sGridNo;
|
|
bTargetLevel = pTargetSoldier->pathing.bLevel;
|
|
}
|
|
else
|
|
{
|
|
sTargetGridNo = sMapPos;
|
|
bTargetLevel = (INT8)gsInterfaceLevel;
|
|
|
|
if ( pIntNode != NULL )
|
|
{
|
|
// Change gridno....
|
|
sTargetGridNo = sGridNo;
|
|
}
|
|
}
|
|
|
|
// here, change gridno if we're targeting ourselves....
|
|
if ( pIntNode != NULL )
|
|
{
|
|
// Are we in the same gridno?
|
|
if ( sGridNo == pSoldier->sGridNo && ubItemCursor != AIDCURS )
|
|
{
|
|
// Get orientation....
|
|
switch( pStructure->ubWallOrientation )
|
|
{
|
|
case OUTSIDE_TOP_LEFT:
|
|
case INSIDE_TOP_LEFT:
|
|
|
|
sNewGridNo = NewGridNo( sGridNo, DirectionInc( SOUTH ) );
|
|
break;
|
|
|
|
case OUTSIDE_TOP_RIGHT:
|
|
case INSIDE_TOP_RIGHT:
|
|
|
|
sNewGridNo = NewGridNo( sGridNo, DirectionInc( EAST ) );
|
|
break;
|
|
|
|
default:
|
|
sNewGridNo = sGridNo;
|
|
}
|
|
|
|
// Set target gridno to this one...
|
|
sTargetGridNo = sNewGridNo;
|
|
|
|
// now set target cube height
|
|
// CJC says to hardcode this value :)
|
|
pSoldier->bTargetCubeLevel = 2;
|
|
}
|
|
else
|
|
{
|
|
// ATE: Refine this a bit - if we have nobody as a target...
|
|
if ( pTargetSoldier == NULL )
|
|
{
|
|
sTargetGridNo = sGridNo;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// Cannot be fire if we are already in a fire animation....
|
|
// this is to stop the shooting trigger/happy duded from contiously pressing fire...
|
|
if ( !(gTacticalStatus.uiFlags & INCOMBAT) )
|
|
{
|
|
if ( gAnimControl[ pSoldier->usAnimState ].uiFlags & ANIM_FIRE )
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
// If in turn-based mode - return to movement
|
|
if ( ( gTacticalStatus.uiFlags & INCOMBAT ) )
|
|
{
|
|
// Reset some flags for cont move...
|
|
pSoldier->pathing.sFinalDestination = pSoldier->sGridNo;
|
|
pSoldier->bGoodContPath = FALSE;
|
|
// guiPendingOverrideEvent = A_CHANGE_TO_MOVE;
|
|
}
|
|
|
|
|
|
if (pSoldier->bWeaponMode == WM_ATTACHED_GL || pSoldier->bWeaponMode == WM_ATTACHED_GL_BURST || pSoldier->bWeaponMode == WM_ATTACHED_GL_AUTO )
|
|
{
|
|
iHandleReturn = HandleItem( pSoldier, sTargetGridNo, bTargetLevel, GetAttachedGrenadeLauncher(&pSoldier->inv[ HANDPOS ]), TRUE );
|
|
}
|
|
else
|
|
{
|
|
iHandleReturn = HandleItem( pSoldier, sTargetGridNo, bTargetLevel, pSoldier->inv[ HANDPOS ].usItem, TRUE );
|
|
}
|
|
|
|
if ( iHandleReturn < 0 )
|
|
{
|
|
if ( iHandleReturn == ITEM_HANDLE_RELOADING )
|
|
{
|
|
guiNewUICursor = ACTION_TARGET_RELOADING;
|
|
return;
|
|
}
|
|
|
|
if ( iHandleReturn == ITEM_HANDLE_NOROOM )
|
|
{
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, pMessageStrings[ MSG_CANT_FIRE_HERE ] );
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
if ( gTacticalStatus.uiFlags & TURNBASED && !( gTacticalStatus.uiFlags & INCOMBAT ) )
|
|
{
|
|
HandleUICursorRTFeedback( pSoldier );
|
|
}
|
|
|
|
gfUIForceReExamineCursorData = TRUE;
|
|
}
|
|
|
|
void AttackRequesterCallback( UINT8 bExitValue )
|
|
{
|
|
if( bExitValue == MSG_BOX_RETURN_YES )
|
|
{
|
|
gTacticalStatus.ubLastRequesterTargetID = gpRequesterTargetMerc->ubProfile;
|
|
|
|
UIHandleMercAttack( gpRequesterMerc , gpRequesterTargetMerc, gsRequesterGridNo );
|
|
}
|
|
}
|
|
|
|
|
|
UINT32 UIHandleCAMercShoot( UI_EVENT *pUIEvent )
|
|
{
|
|
INT16 sMapPos;
|
|
SOLDIERTYPE *pSoldier, *pTSoldier = NULL;
|
|
BOOLEAN fDidRequester = FALSE;
|
|
|
|
if ( gusSelectedSoldier != NOBODY )
|
|
{
|
|
|
|
if( !GetMouseMapPos( &sMapPos) )
|
|
{
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
// Get soldier
|
|
if ( GetSoldier( &pSoldier, gusSelectedSoldier ) )
|
|
{
|
|
// Get target guy...
|
|
if ( gfUIFullTargetFound )
|
|
{
|
|
// Get target soldier, if one exists
|
|
pTSoldier = MercPtrs[ gusUIFullTargetID ];
|
|
}
|
|
|
|
|
|
if ( pTSoldier != NULL )
|
|
{
|
|
// If this is one of our own guys.....pop up requiester...
|
|
if ( ( pTSoldier->bTeam == gbPlayerNum || pTSoldier->bTeam == MILITIA_TEAM ) && Item[ pSoldier->inv[ HANDPOS ].usItem ].usItemClass != IC_MEDKIT && !Item[pSoldier->inv[ HANDPOS ].usItem].gascan && gTacticalStatus.ubLastRequesterTargetID != pTSoldier->ubProfile && ( pTSoldier->ubID != pSoldier->ubID ) )
|
|
{
|
|
CHAR16 zStr[200];
|
|
|
|
gpRequesterMerc = pSoldier;
|
|
gpRequesterTargetMerc = pTSoldier;
|
|
gsRequesterGridNo = sMapPos;
|
|
|
|
fDidRequester = TRUE;
|
|
|
|
swprintf( zStr, TacticalStr[ ATTACK_OWN_GUY_PROMPT ], pTSoldier->name );
|
|
|
|
DoMessageBox( MSG_BOX_BASIC_STYLE, zStr, GAME_SCREEN, ( UINT8 )MSG_BOX_FLAG_YESNO, AttackRequesterCallback, NULL );
|
|
|
|
}
|
|
}
|
|
|
|
if ( !fDidRequester )
|
|
{
|
|
UIHandleMercAttack( pSoldier, pTSoldier, sMapPos );
|
|
}
|
|
}
|
|
}
|
|
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
|
|
UINT32 UIHandleAEndAction( UI_EVENT *pUIEvent )
|
|
{
|
|
SOLDIERTYPE *pSoldier;
|
|
INT16 sTargetXPos, sTargetYPos;
|
|
INT16 sMapPos;
|
|
|
|
// Get gridno at this location
|
|
if( !GetMouseMapPos( &sMapPos) )
|
|
{
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
|
|
if ( GetSoldier( &pSoldier, gusSelectedSoldier ) )
|
|
{
|
|
if ( ( gTacticalStatus.uiFlags & REALTIME ) || !( gTacticalStatus.uiFlags & INCOMBAT ) )
|
|
{
|
|
if ( gUITargetReady )
|
|
{
|
|
// Move to proper stance + direction!
|
|
// Convert our grid-not into an XY
|
|
ConvertGridNoToXY( sMapPos, &sTargetXPos, &sTargetYPos );
|
|
|
|
// UNReady weapon
|
|
pSoldier->SoldierReadyWeapon( sTargetXPos, sTargetYPos, TRUE );
|
|
|
|
gUITargetReady = FALSE;
|
|
}
|
|
|
|
}
|
|
}
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
|
|
UINT32 UIHandleCAEndConfirmAction( UI_EVENT *pUIEvent )
|
|
{
|
|
SOLDIERTYPE *pSoldier;
|
|
|
|
if ( GetSoldier( &pSoldier, gusSelectedSoldier ) )
|
|
{
|
|
HandleEndConfirmCursor( pSoldier );
|
|
}
|
|
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
|
|
UINT32 UIHandleIOnTerrain( UI_EVENT *pUIEvent )
|
|
{
|
|
INT16 sMapPos;
|
|
|
|
// Get gridno at this location
|
|
if( !GetMouseMapPos( &sMapPos) )
|
|
{
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
|
|
if ( !UIHandleOnMerc( TRUE ) )
|
|
{
|
|
// Check if dest is OK
|
|
//if ( !NewOKDestination( sMapPos, FALSE ) || IsRoofVisible( sMapPos ) )
|
|
////{
|
|
// guiNewUICursor = CANNOT_MOVE_UICURSOR;
|
|
//}
|
|
//else
|
|
{
|
|
guiNewUICursor = NORMAL_SNAPUICURSOR;
|
|
}
|
|
}
|
|
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
UINT32 UIHandleIChangeToIdle( UI_EVENT *pUIEvent )
|
|
{
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
UINT32 UIHandlePADJAdjustStance( UI_EVENT *pUIEvent )
|
|
{
|
|
SOLDIERTYPE *pSoldier;
|
|
UINT8 ubNewStance;
|
|
|
|
guiShowUPDownArrows = ARROWS_HIDE_UP | ARROWS_HIDE_DOWN;
|
|
|
|
|
|
gfIgnoreScrolling = FALSE;
|
|
|
|
if ( gusSelectedSoldier != NOBODY && gbAdjustStanceDiff != 0 )
|
|
{
|
|
// Get soldier
|
|
if ( GetSoldier( &pSoldier, gusSelectedSoldier ) )
|
|
{
|
|
ubNewStance = GetAdjustedAnimHeight( gAnimControl[ pSoldier->usAnimState ].ubEndHeight, gbAdjustStanceDiff );
|
|
|
|
if ( gbClimbID == 1 )
|
|
{
|
|
pSoldier->BeginSoldierClimbUpRoof( );
|
|
}
|
|
else if ( gbClimbID == -1 )
|
|
{
|
|
pSoldier->BeginSoldierClimbDownRoof( );
|
|
}
|
|
else
|
|
{
|
|
// Set state to result
|
|
UIHandleSoldierStanceChange( pSoldier->ubID, ubNewStance );
|
|
}
|
|
|
|
// Once we have APs, we can safely reset nomove flag!
|
|
// AdjustNoAPToFinishMove( pSoldier, FALSE );
|
|
|
|
}
|
|
|
|
}
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
|
|
UINT8 GetAdjustedAnimHeight( UINT8 ubAnimHeight, INT8 bChange )
|
|
{
|
|
UINT8 ubNewAnimHeight = ubAnimHeight;
|
|
|
|
if ( ubAnimHeight == ANIM_STAND )
|
|
{
|
|
if ( bChange == -1 )
|
|
{
|
|
ubNewAnimHeight = ANIM_CROUCH;
|
|
}
|
|
if ( bChange == -2 )
|
|
{
|
|
ubNewAnimHeight = ANIM_PRONE;
|
|
}
|
|
if ( bChange == 1 )
|
|
{
|
|
ubNewAnimHeight = 50;
|
|
}
|
|
}
|
|
else if ( ubAnimHeight == ANIM_CROUCH )
|
|
{
|
|
if ( bChange == 1 )
|
|
{
|
|
ubNewAnimHeight = ANIM_STAND;
|
|
}
|
|
if ( bChange == -1 )
|
|
{
|
|
ubNewAnimHeight = ANIM_PRONE;
|
|
}
|
|
if ( bChange == -2 )
|
|
{
|
|
ubNewAnimHeight = 55;
|
|
}
|
|
}
|
|
else if ( ubAnimHeight == ANIM_PRONE )
|
|
{
|
|
if ( bChange == -1 )
|
|
{
|
|
ubNewAnimHeight = 55;
|
|
}
|
|
if ( bChange == 1 )
|
|
{
|
|
ubNewAnimHeight = ANIM_CROUCH;
|
|
}
|
|
if ( bChange == 2 )
|
|
{
|
|
ubNewAnimHeight = ANIM_STAND;
|
|
}
|
|
}
|
|
|
|
return( ubNewAnimHeight );
|
|
}
|
|
|
|
void HandleObjectHighlighting( )
|
|
{
|
|
SOLDIERTYPE *pSoldier;
|
|
INT16 sMapPos;
|
|
|
|
if( !GetMouseMapPos( &sMapPos) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// CHECK IF WE'RE ON A GUY ( EITHER SELECTED, OURS, OR THEIRS
|
|
if ( gfUIFullTargetFound )
|
|
{
|
|
// Get Soldier
|
|
GetSoldier( &pSoldier, gusUIFullTargetID );
|
|
|
|
// If an enemy, and in a given mode, highlight
|
|
if ( guiUIFullTargetFlags & ENEMY_MERC )
|
|
{
|
|
switch( gCurrentUIMode )
|
|
{
|
|
|
|
case CONFIRM_MOVE_MODE:
|
|
case MENU_MODE:
|
|
|
|
break;
|
|
|
|
case MOVE_MODE:
|
|
case CONFIRM_ACTION_MODE:
|
|
//case ACTION_MODE:
|
|
case IDLE_MODE:
|
|
|
|
// Set as selected
|
|
//pSoldier->pCurrentShade = pSoldier->pShades[ 1 ];
|
|
break;
|
|
}
|
|
}
|
|
else if ( guiUIFullTargetFlags & OWNED_MERC )
|
|
{
|
|
// Check for selected
|
|
pSoldier->pCurrentShade = pSoldier->pShades[ 0 ];
|
|
gfUIDoNotHighlightSelMerc = TRUE;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void AdjustSoldierCreationStartValues( )
|
|
{
|
|
INT32 cnt;
|
|
SOLDIERTYPE *pSoldier;
|
|
|
|
|
|
cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
|
|
guiCreateGuyIndex = (INT16)cnt;
|
|
|
|
for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; pSoldier++, cnt++ )
|
|
{
|
|
if ( !pSoldier->bActive )
|
|
{
|
|
guiCreateGuyIndex = (INT16)cnt;
|
|
break;
|
|
}
|
|
}
|
|
|
|
cnt = gTacticalStatus.Team[ gbPlayerNum ].bLastID + 1;
|
|
guiCreateBadGuyIndex = (INT16)cnt;
|
|
|
|
for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ LAST_TEAM ].bLastID; pSoldier++, cnt++ )
|
|
{
|
|
if ( !pSoldier->bActive && cnt > gTacticalStatus.Team[ gbPlayerNum ].bLastID )
|
|
{
|
|
guiCreateBadGuyIndex = (INT16)cnt;
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
BOOLEAN SelectedMercCanAffordAttack( )
|
|
{
|
|
SOLDIERTYPE *pSoldier;
|
|
SOLDIERTYPE *pTargetSoldier;
|
|
INT16 sMapPos;
|
|
INT16 sTargetGridNo;
|
|
INT16 sAPCost;
|
|
UINT8 ubItemCursor;
|
|
UINT16 usInHand;
|
|
|
|
if ( gusSelectedSoldier != NOBODY )
|
|
{
|
|
|
|
if( !GetMouseMapPos( &sMapPos) )
|
|
{
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
// Get soldier
|
|
if ( GetSoldier( &pSoldier, gusSelectedSoldier ) )
|
|
{
|
|
// LOOK IN GUY'S HAND TO CHECK LOCATION
|
|
usInHand = pSoldier->inv[HANDPOS].usItem;
|
|
|
|
// Get cursor value
|
|
ubItemCursor = GetActionModeCursor( pSoldier );
|
|
|
|
if ( ubItemCursor == INVALIDCURS )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
if ( ubItemCursor == BOMBCURS )
|
|
{
|
|
// Check as...
|
|
if ( EnoughPoints( pSoldier, GetTotalAPsToDropBomb( pSoldier, sMapPos ), 0, TRUE ) )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
}
|
|
else if ( ubItemCursor == REMOTECURS )
|
|
{
|
|
// Check as...
|
|
if ( EnoughPoints( pSoldier, GetAPsToUseRemote( pSoldier ), 0, TRUE ) )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Look for a soldier at this position
|
|
if ( gfUIFullTargetFound )
|
|
{
|
|
// GetSoldier
|
|
GetSoldier( &pTargetSoldier, gusUIFullTargetID );
|
|
sTargetGridNo = pTargetSoldier->sGridNo;
|
|
}
|
|
else
|
|
{
|
|
sTargetGridNo = sMapPos;
|
|
}
|
|
|
|
sAPCost = CalcTotalAPsToAttack( pSoldier, sTargetGridNo, TRUE, (INT16)(pSoldier->aiData.bShownAimTime ) );
|
|
|
|
if ( EnoughPoints( pSoldier, sAPCost, 0, TRUE ) )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
else
|
|
{
|
|
// Play curse....
|
|
pSoldier->DoMercBattleSound( BATTLE_SOUND_CURSE1 );
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
return( FALSE );
|
|
}
|
|
|
|
|
|
BOOLEAN SelectedMercCanAffordMove( )
|
|
{
|
|
SOLDIERTYPE *pSoldier;
|
|
UINT16 sAPCost = 0;
|
|
INT16 sMapPos;
|
|
LEVELNODE *pIntTile;
|
|
|
|
// Get soldier
|
|
if ( GetSoldier( &pSoldier, gusSelectedSoldier ) )
|
|
{
|
|
if( !GetMouseMapPos( &sMapPos) )
|
|
{
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
|
|
// IF WE ARE OVER AN INTERACTIVE TILE, GIVE GRIDNO OF POSITION
|
|
pIntTile = GetCurInteractiveTile( );
|
|
|
|
if ( pIntTile != NULL )
|
|
{
|
|
// CHECK APS
|
|
if ( EnoughPoints( pSoldier, gsCurrentActionPoints, 0 , TRUE ) )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
else
|
|
{
|
|
return( FALSE );
|
|
}
|
|
}
|
|
|
|
// Take the first direction!
|
|
sAPCost = PtsToMoveDirection( pSoldier, (UINT8)guiPathingData[ 0 ] );
|
|
|
|
sAPCost += GetAPsToChangeStance( pSoldier, gAnimControl[ pSoldier->usUIMovementMode ].ubHeight );
|
|
|
|
if ( EnoughPoints( pSoldier, sAPCost, 0 , TRUE ) )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
else
|
|
{
|
|
// OK, remember where we were trying to get to.....
|
|
pSoldier->sContPathLocation = sMapPos;
|
|
pSoldier->bGoodContPath = TRUE;
|
|
}
|
|
}
|
|
|
|
return( FALSE );
|
|
}
|
|
|
|
void GetMercClimbDirection( UINT8 ubSoldierID, BOOLEAN *pfGoDown, BOOLEAN *pfGoUp )
|
|
{
|
|
INT8 bNewDirection;
|
|
SOLDIERTYPE *pSoldier;
|
|
|
|
*pfGoDown = FALSE;
|
|
*pfGoUp = FALSE;
|
|
|
|
if ( !GetSoldier( &pSoldier, ubSoldierID ) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Check if we are close / can climb
|
|
if ( pSoldier->pathing.bLevel == 0 )
|
|
{
|
|
// See if we are not in a building!
|
|
if ( FindHeigherLevel( pSoldier, pSoldier->sGridNo, pSoldier->ubDirection, &bNewDirection ) )
|
|
{
|
|
*pfGoUp = TRUE;
|
|
}
|
|
}
|
|
|
|
// IF we are higher...
|
|
if ( pSoldier->pathing.bLevel > 0 )
|
|
{
|
|
if ( FindLowerLevel( pSoldier, pSoldier->sGridNo, pSoldier->ubDirection, &bNewDirection ) )
|
|
{
|
|
*pfGoDown = TRUE;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
void RemoveTacticalCursor( )
|
|
{
|
|
guiNewUICursor = NO_UICURSOR;
|
|
ErasePath( TRUE );
|
|
}
|
|
|
|
UINT32 UIHandlePOPUPMSG( UI_EVENT *pUIEvent )
|
|
{
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
|
|
UINT32 UIHandleHCOnTerrain( UI_EVENT *pUIEvent )
|
|
{
|
|
INT16 sMapPos;
|
|
SOLDIERTYPE *pSoldier;
|
|
|
|
if( !GetMouseMapPos( &sMapPos) )
|
|
{
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
if ( !GetSoldier( &pSoldier, gusSelectedSoldier ) )
|
|
{
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
// If we are out of breath, no cursor...
|
|
if ( pSoldier->bBreath < OKBREATH && pSoldier->bCollapsed )
|
|
{
|
|
guiNewUICursor = INVALID_ACTION_UICURSOR;
|
|
}
|
|
else
|
|
{
|
|
if ( gsOverItemsGridNo != NOWHERE && ( sMapPos != gsOverItemsGridNo || gsInterfaceLevel != gsOverItemsLevel ) )
|
|
{
|
|
gsOverItemsGridNo = NOWHERE;
|
|
guiPendingOverrideEvent = A_CHANGE_TO_MOVE;
|
|
}
|
|
else
|
|
{
|
|
guiNewUICursor = NORMALHANDCURSOR_UICURSOR;
|
|
|
|
UIHandleInteractiveTilesAndItemsOnTerrain( pSoldier, sMapPos, TRUE, FALSE );
|
|
}
|
|
}
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
|
|
UINT32 UIHandleHCGettingItem( UI_EVENT *pUIEvent )
|
|
{
|
|
guiNewUICursor = NORMAL_FREEUICURSOR;
|
|
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
|
|
UINT32 UIHandleTATalkingMenu( UI_EVENT *pUIEvent )
|
|
{
|
|
guiNewUICursor = NORMAL_FREEUICURSOR;
|
|
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
|
|
UINT32 UIHandleEXExitSectorMenu( UI_EVENT *pUIEvent )
|
|
{
|
|
guiNewUICursor = NORMAL_FREEUICURSOR;
|
|
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
|
|
UINT32 UIHandleOpenDoorMenu( UI_EVENT *pUIEvent )
|
|
{
|
|
guiNewUICursor = NORMAL_FREEUICURSOR;
|
|
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
void ToggleHandCursorMode( UINT32 *puiNewEvent )
|
|
{
|
|
// Toggle modes
|
|
if ( gCurrentUIMode == HANDCURSOR_MODE )
|
|
{
|
|
*puiNewEvent = A_CHANGE_TO_MOVE;
|
|
}
|
|
else
|
|
{
|
|
|
|
*puiNewEvent = M_CHANGE_TO_HANDMODE;
|
|
}
|
|
}
|
|
|
|
void ToggleTalkCursorMode( UINT32 *puiNewEvent )
|
|
{
|
|
// Toggle modes
|
|
if ( gCurrentUIMode == TALKCURSOR_MODE )
|
|
{
|
|
*puiNewEvent = A_CHANGE_TO_MOVE;
|
|
}
|
|
else
|
|
{
|
|
*puiNewEvent = T_CHANGE_TO_TALKING;
|
|
}
|
|
}
|
|
|
|
void ToggleLookCursorMode( UINT32 *puiNewEvent )
|
|
{
|
|
// Toggle modes
|
|
if ( gCurrentUIMode == LOOKCURSOR_MODE )
|
|
{
|
|
guiPendingOverrideEvent = A_CHANGE_TO_MOVE;
|
|
HandleTacticalUI( );
|
|
}
|
|
else
|
|
{
|
|
guiPendingOverrideEvent = LC_CHANGE_TO_LOOK;
|
|
HandleTacticalUI( );
|
|
}
|
|
}
|
|
|
|
|
|
BOOLEAN UIHandleOnMerc( BOOLEAN fMovementMode )
|
|
{
|
|
SOLDIERTYPE *pSoldier;
|
|
UINT16 usSoldierIndex;
|
|
UINT32 uiMercFlags;
|
|
INT16 sMapPos;
|
|
BOOLEAN fFoundMerc = FALSE;
|
|
|
|
if( !GetMouseMapPos( &sMapPos) )
|
|
{
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
//if ( fMovementMode )
|
|
//{
|
|
// fFoundMerc = gfUISelectiveTargetFound;
|
|
// usSoldierIndex = gusUISelectiveTargetID;
|
|
// uiMercFlags = guiUISelectiveTargetFlags;
|
|
//}
|
|
//else
|
|
{
|
|
fFoundMerc = gfUIFullTargetFound;
|
|
usSoldierIndex = gusUIFullTargetID;
|
|
uiMercFlags = guiUIFullTargetFlags;
|
|
}
|
|
|
|
// CHECK IF WE'RE ON A GUY ( EITHER SELECTED, OURS, OR THEIRS
|
|
if ( fFoundMerc )
|
|
{
|
|
// Get Soldier
|
|
GetSoldier( &pSoldier, usSoldierIndex );
|
|
|
|
if ( uiMercFlags & OWNED_MERC )
|
|
{
|
|
// ATE: Check if this is an empty vehicle.....
|
|
//if ( OK_ENTERABLE_VEHICLE( pSoldier ) && GetNumberInVehicle( pSoldier->bVehicleID ) == 0 )
|
|
//{
|
|
// return( FALSE );
|
|
//}
|
|
|
|
// If not unconscious, select
|
|
if ( !( uiMercFlags & UNCONSCIOUS_MERC ) )
|
|
{
|
|
if ( fMovementMode )
|
|
{
|
|
// ERASE PATH
|
|
ErasePath( TRUE );
|
|
|
|
// Show cursor with highlight on selected merc
|
|
guiNewUICursor = NO_UICURSOR;
|
|
|
|
// IF selected, do selection one
|
|
if ( ( uiMercFlags & SELECTED_MERC ) )
|
|
{
|
|
// Add highlight to guy in interface.c
|
|
gfUIHandleSelection = SELECTED_GUY_SELECTION;
|
|
|
|
if ( gpItemPointer == NULL )
|
|
{
|
|
// Don't do this unless we want to
|
|
|
|
// Check if buddy is stationary!
|
|
if ( gAnimControl[ pSoldier->usAnimState ].uiFlags & ANIM_STATIONARY || pSoldier->flags.fNoAPToFinishMove )
|
|
{
|
|
guiShowUPDownArrows = ARROWS_SHOW_DOWN_BESIDE | ARROWS_SHOW_UP_BESIDE;
|
|
}
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
//if ( ( uiMercFlags & ONDUTY_MERC ) && !( uiMercFlags & NOINTERRUPT_MERC ) )
|
|
if ( !( uiMercFlags & NOINTERRUPT_MERC ) )
|
|
{
|
|
// Add highlight to guy in interface.c
|
|
gfUIHandleSelection = NONSELECTED_GUY_SELECTION;
|
|
}
|
|
else
|
|
{
|
|
gfUIHandleSelection = ENEMY_GUY_SELECTION;
|
|
gfUIHandleSelectionAboveGuy = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// If not dead, show above guy!
|
|
if ( !( uiMercFlags & DEAD_MERC ) )
|
|
{
|
|
if ( fMovementMode )
|
|
{
|
|
// ERASE PATH
|
|
ErasePath( TRUE );
|
|
|
|
// Show cursor with highlight on selected merc
|
|
guiNewUICursor = NO_UICURSOR;
|
|
|
|
gsSelectedGridNo = pSoldier->sGridNo;
|
|
gsSelectedLevel = pSoldier->pathing.bLevel;
|
|
}
|
|
|
|
gsSelectedGuy = usSoldierIndex;
|
|
gfUIHandleSelectionAboveGuy = TRUE;
|
|
}
|
|
|
|
}
|
|
else if ( ( ( uiMercFlags & ENEMY_MERC ) || ( uiMercFlags & NEUTRAL_MERC ) ) && ( uiMercFlags & VISIBLE_MERC ) )
|
|
{
|
|
// ATE: If we are a vehicle, let the mouse cursor be a wheel...
|
|
if ( ( OK_ENTERABLE_VEHICLE( pSoldier ) ) )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
else
|
|
{
|
|
if ( fMovementMode )
|
|
{
|
|
|
|
// Check if this guy is on the enemy team....
|
|
if ( !pSoldier->aiData.bNeutral && (pSoldier->bSide != gbPlayerNum ) )
|
|
{
|
|
gUIActionModeChangeDueToMouseOver = TRUE;
|
|
|
|
guiPendingOverrideEvent = M_CHANGE_TO_ACTION;
|
|
// Return FALSE
|
|
return( FALSE );
|
|
}
|
|
else
|
|
{
|
|
// ERASE PATH
|
|
ErasePath( TRUE );
|
|
|
|
// Show cursor with highlight on selected merc
|
|
guiNewUICursor = NO_UICURSOR;
|
|
// Show cursor with highlight
|
|
gfUIHandleSelection = ENEMY_GUY_SELECTION;
|
|
gsSelectedGridNo = pSoldier->sGridNo;
|
|
gsSelectedLevel = pSoldier->pathing.bLevel;
|
|
}
|
|
}
|
|
|
|
gfUIHandleSelectionAboveGuy = TRUE;
|
|
gsSelectedGuy = usSoldierIndex;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
gfIgnoreOnSelectedGuy = FALSE;
|
|
|
|
return( FALSE );
|
|
}
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
UINT32 UIHandleILoadLevel( UI_EVENT *pUIEvent )
|
|
{
|
|
return( INIT_SCREEN );
|
|
}
|
|
|
|
UINT32 UIHandleISoldierDebug( UI_EVENT *pUIEvent )
|
|
{
|
|
// Use soldier display pages
|
|
SetDebugRenderHook( (RENDER_HOOK)DebugSoldierPage1, 0 );
|
|
SetDebugRenderHook( (RENDER_HOOK)DebugSoldierPage2, 1 );
|
|
SetDebugRenderHook( (RENDER_HOOK)DebugSoldierPage3, 2 );
|
|
SetDebugRenderHook( (RENDER_HOOK)DebugSoldierPage4, 3 );
|
|
gCurDebugPage = 1;
|
|
|
|
return( DEBUG_SCREEN );
|
|
}
|
|
|
|
UINT32 UIHandleILOSDebug( UI_EVENT *pUIEvent )
|
|
{
|
|
SetDebugRenderHook( (RENDER_HOOK)DebugStructurePage1, 0 );
|
|
return( DEBUG_SCREEN );
|
|
}
|
|
|
|
UINT32 UIHandleILevelNodeDebug( UI_EVENT *pUIEvent )
|
|
{
|
|
SetDebugRenderHook( (RENDER_HOOK)DebugLevelNodePage, 0 );
|
|
return( DEBUG_SCREEN );
|
|
}
|
|
|
|
UINT32 UIHandleIETOnTerrain( UI_EVENT *pUIEvent )
|
|
{
|
|
//guiNewUICursor = CANNOT_MOVE_UICURSOR;
|
|
guiNewUICursor = NO_UICURSOR;
|
|
|
|
SetCurrentCursorFromDatabase( VIDEO_NO_CURSOR );
|
|
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
|
|
void UIHandleSoldierStanceChange( UINT8 ubSoldierID, INT8 bNewStance )
|
|
{
|
|
SOLDIERTYPE *pSoldier;
|
|
|
|
pSoldier = MercPtrs[ ubSoldierID ];
|
|
|
|
// Is this a valid stance for our position?
|
|
if ( !IsValidStance( pSoldier, bNewStance ) )
|
|
{
|
|
if ( pSoldier->bCollapsed && pSoldier->bBreath < OKBREATH )
|
|
{
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, gzLateLocalizedString[ 4 ], pSoldier->name );
|
|
}
|
|
else
|
|
{
|
|
if ( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE )
|
|
{
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, TacticalStr[ VEHICLES_NO_STANCE_CHANGE_STR ] );
|
|
}
|
|
else if ( pSoldier->flags.uiStatusFlags & SOLDIER_ROBOT )
|
|
{
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, TacticalStr[ ROBOT_NO_STANCE_CHANGE_STR ] );
|
|
}
|
|
else
|
|
{
|
|
if ( pSoldier->bCollapsed )
|
|
{
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, pMessageStrings[ MSG_CANT_CHANGE_STANCE ], pSoldier->name );
|
|
}
|
|
else
|
|
{
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, TacticalStr[ CANNOT_STANCE_CHANGE_STR ], pSoldier->name );
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
// IF turn-based - adjust stance now!
|
|
if ( gTacticalStatus.uiFlags & TURNBASED && ( gTacticalStatus.uiFlags & INCOMBAT ) )
|
|
{
|
|
pSoldier->flags.bTurningFromPronePosition = TURNING_FROM_PRONE_OFF;
|
|
|
|
// Check if we have enough APS
|
|
if ( SoldierCanAffordNewStance( pSoldier, bNewStance ) )
|
|
{
|
|
// Adjust stance
|
|
//pSoldier->ChangeSoldierStance( bNewStance );
|
|
SendChangeSoldierStanceEvent( pSoldier, bNewStance );
|
|
|
|
pSoldier->pathing.sFinalDestination = pSoldier->sGridNo;
|
|
pSoldier->bGoodContPath = FALSE;
|
|
|
|
}
|
|
else
|
|
return;
|
|
}
|
|
|
|
// If realtime- change walking animation!
|
|
if ( ( gTacticalStatus.uiFlags & REALTIME ) || !( gTacticalStatus.uiFlags & INCOMBAT ) )
|
|
{
|
|
|
|
// If we are stationary, do something else!
|
|
if ( gAnimControl[ pSoldier->usAnimState ].uiFlags & ANIM_STATIONARY )
|
|
{
|
|
// Change stance normally
|
|
SendChangeSoldierStanceEvent( pSoldier, bNewStance );
|
|
|
|
}
|
|
else
|
|
{
|
|
// Pick moving animation based on stance
|
|
|
|
// LOCK VARIBLE FOR NO UPDATE INDEX...
|
|
pSoldier->usUIMovementMode = pSoldier->GetMoveStateBasedOnStance( bNewStance );
|
|
pSoldier->ubDesiredHeight = NO_DESIRED_HEIGHT;
|
|
|
|
#if 0
|
|
if ( pSoldier->usUIMovementMode == CRAWLING && gAnimControl[ pSoldier->usAnimState ].ubEndHeight != ANIM_PRONE )
|
|
{
|
|
pSoldier->usDontUpdateNewGridNoOnMoveAnimChange = LOCKED_NO_NEWGRIDNO;
|
|
pSoldier->pathing.bPathStored = FALSE;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
pSoldier->usDontUpdateNewGridNoOnMoveAnimChange = 1;
|
|
}
|
|
|
|
|
|
pSoldier->ChangeSoldierState( pSoldier->usUIMovementMode, 0, FALSE );
|
|
|
|
}
|
|
}
|
|
|
|
// Set UI value for soldier
|
|
SetUIbasedOnStance( pSoldier, bNewStance );
|
|
|
|
gfUIStanceDifferent = TRUE;
|
|
|
|
// ATE: If we are being serviced...stop...
|
|
// pSoldier->InternalReceivingSoldierCancelServices(, FALSE );
|
|
pSoldier->InternalGivingSoldierCancelServices( FALSE );
|
|
//gfPlotNewMovement = TRUE;
|
|
|
|
}
|
|
|
|
UINT32 UIHandleIETEndTurn( UI_EVENT *pUIEvent )
|
|
{
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
|
|
UINT32 UIHandleIGotoDemoMode( UI_EVENT *pUIEvent )
|
|
{
|
|
return( EnterTacticalDemoMode() );
|
|
}
|
|
|
|
|
|
UINT32 UIHandleILoadFirstLevel( UI_EVENT *pUIEvent )
|
|
{
|
|
gubCurrentScene = 0;
|
|
return( INIT_SCREEN );
|
|
}
|
|
|
|
UINT32 UIHandleILoadSecondLevel( UI_EVENT *pUIEvent )
|
|
{
|
|
gubCurrentScene = 1;
|
|
return( INIT_SCREEN );
|
|
}
|
|
|
|
UINT32 UIHandleILoadThirdLevel( UI_EVENT *pUIEvent )
|
|
{
|
|
gubCurrentScene = 2;
|
|
return( INIT_SCREEN );
|
|
}
|
|
|
|
UINT32 UIHandleILoadFourthLevel( UI_EVENT *pUIEvent )
|
|
{
|
|
gubCurrentScene = 3;
|
|
return( INIT_SCREEN );
|
|
}
|
|
|
|
UINT32 UIHandleILoadFifthLevel( UI_EVENT *pUIEvent )
|
|
{
|
|
gubCurrentScene = 4;
|
|
return( INIT_SCREEN );
|
|
}
|
|
|
|
|
|
void GetCursorMovementFlags( UINT32 *puiCursorFlags )
|
|
{
|
|
INT16 sMapPos;
|
|
INT16 sXPos, sYPos;
|
|
|
|
static BOOLEAN fStationary = FALSE;
|
|
static UINT16 usOldMouseXPos = 32000;
|
|
static UINT16 usOldMouseYPos = 32000;
|
|
static UINT16 usOldMapPos = 32000;
|
|
|
|
static UINT32 uiSameFrameCursorFlags;
|
|
static UINT32 uiOldFrameNumber = 99999;
|
|
|
|
// Check if this is the same frame as before, return already calculated value if so!
|
|
if ( uiOldFrameNumber == guiGameCycleCounter )
|
|
{
|
|
( *puiCursorFlags ) = uiSameFrameCursorFlags;
|
|
return;
|
|
}
|
|
|
|
GetMouseMapPos( &sMapPos );
|
|
ConvertGridNoToXY( sMapPos, &sXPos, &sYPos );
|
|
|
|
*puiCursorFlags = 0;
|
|
|
|
if ( gusMouseXPos != usOldMouseXPos || gusMouseYPos != usOldMouseYPos )
|
|
{
|
|
(*puiCursorFlags ) |= MOUSE_MOVING;
|
|
|
|
// IF CURSOR WAS PREVIOUSLY STATIONARY, MAKE THE ADDITIONAL CHECK OF GRID POS CHANGE
|
|
if ( fStationary && usOldMapPos == sMapPos )
|
|
{
|
|
(*puiCursorFlags) |= MOUSE_MOVING_IN_TILE;
|
|
}
|
|
else
|
|
{
|
|
fStationary = FALSE;
|
|
(*puiCursorFlags) |= MOUSE_MOVING_NEW_TILE;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
(*puiCursorFlags) |= MOUSE_STATIONARY;
|
|
fStationary = TRUE;
|
|
}
|
|
|
|
usOldMapPos = sMapPos;
|
|
usOldMouseXPos = gusMouseXPos;
|
|
usOldMouseYPos = gusMouseYPos;
|
|
|
|
uiOldFrameNumber = guiGameCycleCounter;
|
|
uiSameFrameCursorFlags = (*puiCursorFlags);
|
|
}
|
|
|
|
BOOLEAN HandleUIMovementCursor( SOLDIERTYPE *pSoldier, UINT32 uiCursorFlags, INT16 sMapPos, UINT32 uiFlags )
|
|
{
|
|
BOOLEAN fSetCursor = FALSE;
|
|
static UINT16 usTargetID = NOBODY;
|
|
static BOOLEAN fTargetFound = FALSE;
|
|
BOOLEAN fTargetFoundAndLookingForOne = FALSE;
|
|
|
|
// Determine if we can afford!
|
|
if ( !EnoughPoints( pSoldier, gsCurrentActionPoints, 0, FALSE ) )
|
|
{
|
|
gfUIDisplayActionPointsInvalid = TRUE;
|
|
}
|
|
|
|
// Check if we're stationary
|
|
if ( ( ( gTacticalStatus.uiFlags & REALTIME ) || !( gTacticalStatus.uiFlags & INCOMBAT ) ) || ( ( gAnimControl[ pSoldier->usAnimState ].uiFlags & ANIM_STATIONARY ) || pSoldier->flags.fNoAPToFinishMove ) || pSoldier->ubID >= MAX_NUM_SOLDIERS )
|
|
{
|
|
// If we are targeting a merc for some reason, don't go thorugh normal channels if we are on someone now
|
|
if ( uiFlags == MOVEUI_TARGET_MERCS || uiFlags == MOVEUI_TARGET_MERCSFORAID )
|
|
{
|
|
if ( gfUIFullTargetFound != fTargetFound || usTargetID != gusUIFullTargetID || gfResetUIMovementOptimization )
|
|
{
|
|
gfResetUIMovementOptimization = FALSE;
|
|
|
|
// ERASE PATH
|
|
ErasePath( TRUE );
|
|
|
|
// Try and get a path right away
|
|
DrawUIMovementPath( pSoldier, sMapPos, uiFlags );
|
|
}
|
|
|
|
// Save for next time...
|
|
fTargetFound = gfUIFullTargetFound;
|
|
usTargetID = gusUIFullTargetID;
|
|
|
|
if ( fTargetFound )
|
|
{
|
|
fTargetFoundAndLookingForOne = TRUE;
|
|
}
|
|
}
|
|
|
|
if ( uiFlags == MOVEUI_TARGET_ITEMS )
|
|
{
|
|
gfUIOverItemPool = TRUE;
|
|
gfUIOverItemPoolGridNo = sMapPos;
|
|
}
|
|
else if ( uiFlags == MOVEUI_TARGET_MERCSFORAID )
|
|
{
|
|
// Set values for AP display...
|
|
gfUIDisplayActionPointsCenter = TRUE;
|
|
}
|
|
|
|
// IF CURSOR IS MOVING
|
|
if ( ( uiCursorFlags & MOUSE_MOVING ) || gfUINewStateForIntTile )
|
|
{
|
|
// SHOW CURSOR
|
|
fSetCursor = TRUE;
|
|
|
|
// IF CURSOR WAS PREVIOUSLY STATIONARY, MAKE THE ADDITIONAL CHECK OF GRID POS CHANGE
|
|
if ( ( ( uiCursorFlags & MOUSE_MOVING_NEW_TILE ) && !fTargetFoundAndLookingForOne ) || gfUINewStateForIntTile )
|
|
{
|
|
// ERASE PATH
|
|
ErasePath( TRUE );
|
|
|
|
// Reset counter
|
|
RESETCOUNTER( PATHFINDCOUNTER );
|
|
|
|
gfPlotNewMovement = TRUE;
|
|
|
|
}
|
|
|
|
if ( uiCursorFlags & MOUSE_MOVING_IN_TILE )
|
|
{
|
|
gfUIDisplayActionPoints = TRUE;
|
|
}
|
|
|
|
}
|
|
|
|
if ( uiCursorFlags & MOUSE_STATIONARY )
|
|
{
|
|
// CURSOR IS STATIONARY
|
|
if ( _KeyDown( SHIFT ) && !gfPlotNewMovementNOCOST )
|
|
{
|
|
gfPlotNewMovementNOCOST = TRUE;
|
|
gfPlotNewMovement = TRUE;
|
|
}
|
|
if ( !(_KeyDown( SHIFT ) ) && gfPlotNewMovementNOCOST )
|
|
{
|
|
gfPlotNewMovementNOCOST = FALSE;
|
|
gfPlotNewMovement = TRUE;
|
|
}
|
|
|
|
|
|
// ONLY DIPSLAY PATH AFTER A DELAY
|
|
if ( COUNTERDONE( PATHFINDCOUNTER ) )
|
|
{
|
|
// Reset counter
|
|
RESETCOUNTER( PATHFINDCOUNTER );
|
|
|
|
if ( gfPlotNewMovement )
|
|
{
|
|
DrawUIMovementPath( pSoldier, sMapPos, uiFlags );
|
|
|
|
gfPlotNewMovement = FALSE;
|
|
}
|
|
}
|
|
|
|
fSetCursor = TRUE;
|
|
|
|
// DISPLAY POINTS EVEN WITHOUT DELAY
|
|
// ONLY IF GFPLOT NEW MOVEMENT IS FALSE!
|
|
if ( !gfPlotNewMovement )
|
|
{
|
|
if ( gsCurrentActionPoints < 0 || ( (gTacticalStatus.uiFlags & REALTIME) || !(gTacticalStatus.uiFlags & INCOMBAT ) ) )
|
|
{
|
|
gfUIDisplayActionPoints = FALSE;
|
|
}
|
|
else
|
|
{
|
|
gfUIDisplayActionPoints = TRUE;
|
|
|
|
if ( uiFlags == MOVEUI_TARGET_INTTILES )
|
|
{
|
|
// Set values for AP display...
|
|
gUIDisplayActionPointsOffX = 22;
|
|
gUIDisplayActionPointsOffY = 15;
|
|
}
|
|
if ( uiFlags == MOVEUI_TARGET_BOMB )
|
|
{
|
|
// Set values for AP display...
|
|
gUIDisplayActionPointsOffX = 22;
|
|
gUIDisplayActionPointsOffY = 15;
|
|
}
|
|
else if ( uiFlags == MOVEUI_TARGET_ITEMS )
|
|
{
|
|
// Set values for AP display...
|
|
gUIDisplayActionPointsOffX = 22;
|
|
gUIDisplayActionPointsOffY = 15;
|
|
}
|
|
else
|
|
{
|
|
switch ( pSoldier->usUIMovementMode )
|
|
{
|
|
case WALKING:
|
|
|
|
gUIDisplayActionPointsOffY = 10;
|
|
gUIDisplayActionPointsOffX = 10;
|
|
break;
|
|
|
|
case RUNNING:
|
|
gUIDisplayActionPointsOffY = 15;
|
|
gUIDisplayActionPointsOffX = 21;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
// THE MERC IS MOVING
|
|
// We're moving, erase path, change cursor
|
|
ErasePath( TRUE );
|
|
|
|
fSetCursor = TRUE;
|
|
|
|
}
|
|
|
|
if(pSoldier->bDoAutofire) //reset the autofire bullet count
|
|
{
|
|
pSoldier->flags.autofireLastStep = FALSE;
|
|
pSoldier->bDoAutofire = 1;
|
|
}
|
|
|
|
return( fSetCursor );
|
|
}
|
|
|
|
|
|
|
|
INT8 DrawUIMovementPath( SOLDIERTYPE *pSoldier, INT16 sMapPos, UINT32 uiFlags )
|
|
{
|
|
INT16 sAPCost, sBPCost;
|
|
INT16 sActionGridNo;
|
|
STRUCTURE *pStructure;
|
|
UINT8 ubDirection;
|
|
// ITEM_POOL *pItemPool;
|
|
INT16 sAdjustedGridNo = -1;
|
|
INT16 sIntTileGridNo;
|
|
LEVELNODE *pIntTile;
|
|
INT8 bReturnCode = 0;
|
|
BOOLEAN fPlot;
|
|
UINT8 ubMercID;
|
|
|
|
if ( (gTacticalStatus.uiFlags & INCOMBAT ) && ( gTacticalStatus.uiFlags & TURNBASED ) || _KeyDown( SHIFT ) )
|
|
{
|
|
fPlot = PLOT;
|
|
}
|
|
else
|
|
{
|
|
fPlot = NO_PLOT;
|
|
}
|
|
|
|
sActionGridNo = sMapPos;
|
|
sAPCost = 0;
|
|
|
|
ErasePath( FALSE );
|
|
|
|
// IF WE ARE OVER AN INTERACTIVE TILE, GIVE GRIDNO OF POSITION
|
|
if ( uiFlags == MOVEUI_TARGET_INTTILES )
|
|
{
|
|
// Get structure info for in tile!
|
|
pIntTile = GetCurInteractiveTileGridNoAndStructure( &sIntTileGridNo, &pStructure );
|
|
|
|
// We should not have null here if we are given this flag...
|
|
if ( pIntTile != NULL )
|
|
{
|
|
sActionGridNo = FindAdjacentGridEx( pSoldier, sIntTileGridNo, &ubDirection, NULL, FALSE, TRUE );
|
|
if ( sActionGridNo == -1 )
|
|
{
|
|
sActionGridNo = sIntTileGridNo;
|
|
}
|
|
CalcInteractiveObjectAPs( sIntTileGridNo, pStructure, &sAPCost, &sBPCost );
|
|
//sAPCost += UIPlotPath( pSoldier, sActionGridNo, NO_COPYROUTE, PLOT, TEMPORARY, (UINT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints);
|
|
sAPCost += UIPlotPath( pSoldier, sActionGridNo, NO_COPYROUTE, fPlot, TEMPORARY, (UINT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints);
|
|
|
|
if ( sActionGridNo != pSoldier->sGridNo )
|
|
{
|
|
gfUIHandleShowMoveGrid = TRUE;
|
|
gsUIHandleShowMoveGridLocation = sActionGridNo;
|
|
}
|
|
|
|
// Add cost for stance change....
|
|
sAPCost += GetAPsToChangeStance( pSoldier, ANIM_STAND );
|
|
}
|
|
else
|
|
{
|
|
sAPCost += UIPlotPath( pSoldier, sActionGridNo, NO_COPYROUTE, fPlot, TEMPORARY, (UINT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints );
|
|
}
|
|
}
|
|
else if ( uiFlags == MOVEUI_TARGET_WIREFENCE )
|
|
{
|
|
sActionGridNo = FindAdjacentGridEx( pSoldier, sMapPos, &ubDirection, NULL, FALSE, TRUE );
|
|
if ( sActionGridNo == -1 )
|
|
{
|
|
sAPCost = 0;
|
|
}
|
|
else
|
|
{
|
|
sAPCost = GetAPsToCutFence( pSoldier );
|
|
|
|
sAPCost += UIPlotPath( pSoldier, sActionGridNo, NO_COPYROUTE, fPlot, TEMPORARY, (UINT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints);
|
|
|
|
if ( sActionGridNo != pSoldier->sGridNo )
|
|
{
|
|
gfUIHandleShowMoveGrid = TRUE;
|
|
gsUIHandleShowMoveGridLocation = sActionGridNo;
|
|
}
|
|
}
|
|
}
|
|
else if ( uiFlags == MOVEUI_TARGET_JAR )
|
|
{
|
|
sActionGridNo = FindAdjacentGridEx( pSoldier, sMapPos, &ubDirection, NULL, FALSE, TRUE );
|
|
if ( sActionGridNo == -1 )
|
|
{
|
|
sActionGridNo = sMapPos;
|
|
}
|
|
|
|
sAPCost = GetAPsToUseJar( pSoldier, sActionGridNo );
|
|
|
|
sAPCost += UIPlotPath( pSoldier, sActionGridNo, NO_COPYROUTE, fPlot, TEMPORARY, (UINT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints);
|
|
|
|
if ( sActionGridNo != pSoldier->sGridNo )
|
|
{
|
|
gfUIHandleShowMoveGrid = TRUE;
|
|
gsUIHandleShowMoveGridLocation = sActionGridNo;
|
|
}
|
|
}
|
|
else if ( uiFlags == MOVEUI_TARGET_CAN )
|
|
{
|
|
// Get structure info for in tile!
|
|
pIntTile = GetCurInteractiveTileGridNoAndStructure( &sIntTileGridNo, &pStructure );
|
|
|
|
// We should not have null here if we are given this flag...
|
|
if ( pIntTile != NULL )
|
|
{
|
|
sActionGridNo = FindAdjacentGridEx( pSoldier, sIntTileGridNo, &ubDirection, NULL, FALSE, TRUE );
|
|
if ( sActionGridNo != -1 )
|
|
{
|
|
sAPCost = APBPConstants[AP_ATTACH_CAN];
|
|
sAPCost += UIPlotPath( pSoldier, sActionGridNo, NO_COPYROUTE, fPlot, TEMPORARY, (UINT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints);
|
|
|
|
if ( sActionGridNo != pSoldier->sGridNo )
|
|
{
|
|
gfUIHandleShowMoveGrid = TRUE;
|
|
gsUIHandleShowMoveGridLocation = sActionGridNo;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sAPCost += UIPlotPath( pSoldier, sActionGridNo, NO_COPYROUTE, fPlot, TEMPORARY, (UINT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints );
|
|
}
|
|
|
|
}
|
|
else if ( uiFlags == MOVEUI_TARGET_REPAIR )
|
|
{
|
|
// For repair, check if we are over a vehicle, then get gridnot to edge of that vehicle!
|
|
if ( IsRepairableStructAtGridNo( sMapPos, &ubMercID ) == 2 )
|
|
{
|
|
INT16 sNewGridNo;
|
|
UINT8 ubDirection;
|
|
|
|
sNewGridNo = FindGridNoFromSweetSpotWithStructDataFromSoldier( pSoldier, pSoldier->usUIMovementMode, 5, &ubDirection, 0, MercPtrs[ ubMercID ] );
|
|
|
|
if ( sNewGridNo != NOWHERE )
|
|
{
|
|
sMapPos = sNewGridNo;
|
|
}
|
|
}
|
|
|
|
sActionGridNo = FindAdjacentGridEx( pSoldier, sMapPos, &ubDirection, NULL, FALSE, TRUE );
|
|
if ( sActionGridNo == -1 )
|
|
{
|
|
sActionGridNo = sMapPos;
|
|
}
|
|
|
|
sAPCost = GetAPsToBeginRepair( pSoldier );
|
|
|
|
sAPCost += UIPlotPath( pSoldier, sActionGridNo, NO_COPYROUTE, fPlot, TEMPORARY, (UINT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints);
|
|
|
|
if ( sActionGridNo != pSoldier->sGridNo )
|
|
{
|
|
gfUIHandleShowMoveGrid = TRUE;
|
|
gsUIHandleShowMoveGridLocation = sActionGridNo;
|
|
}
|
|
}
|
|
else if ( uiFlags == MOVEUI_TARGET_REFUEL )
|
|
{
|
|
// For repair, check if we are over a vehicle, then get gridnot to edge of that vehicle!
|
|
if ( IsRefuelableStructAtGridNo( sMapPos, &ubMercID ) == 2 )
|
|
{
|
|
INT16 sNewGridNo;
|
|
UINT8 ubDirection;
|
|
|
|
sNewGridNo = FindGridNoFromSweetSpotWithStructDataFromSoldier( pSoldier, pSoldier->usUIMovementMode, 5, &ubDirection, 0, MercPtrs[ ubMercID ] );
|
|
|
|
if ( sNewGridNo != NOWHERE )
|
|
{
|
|
sMapPos = sNewGridNo;
|
|
}
|
|
}
|
|
|
|
sActionGridNo = FindAdjacentGridEx( pSoldier, sMapPos, &ubDirection, NULL, FALSE, TRUE );
|
|
if ( sActionGridNo == -1 )
|
|
{
|
|
sActionGridNo = sMapPos;
|
|
}
|
|
|
|
sAPCost = GetAPsToRefuelVehicle( pSoldier );
|
|
|
|
sAPCost += UIPlotPath( pSoldier, sActionGridNo, NO_COPYROUTE, fPlot, TEMPORARY, (UINT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints);
|
|
|
|
if ( sActionGridNo != pSoldier->sGridNo )
|
|
{
|
|
gfUIHandleShowMoveGrid = TRUE;
|
|
gsUIHandleShowMoveGridLocation = sActionGridNo;
|
|
}
|
|
}
|
|
else if ( uiFlags == MOVEUI_TARGET_MERCS )
|
|
{
|
|
INT16 sGotLocation = NOWHERE;
|
|
BOOLEAN fGotAdjacent = FALSE;
|
|
|
|
// Check if we are on a target
|
|
if ( gfUIFullTargetFound )
|
|
{
|
|
INT32 cnt;
|
|
INT16 sSpot;
|
|
UINT8 ubGuyThere;
|
|
|
|
for ( cnt = 0; cnt < NUM_WORLD_DIRECTIONS; cnt++ )
|
|
{
|
|
sSpot = (INT16)NewGridNo( pSoldier->sGridNo, DirectionInc( (INT8)cnt ) );
|
|
|
|
// Make sure movement costs are OK....
|
|
if ( gubWorldMovementCosts[ sSpot ][ cnt ][ gsInterfaceLevel ] >= TRAVELCOST_BLOCKED )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
|
|
// Check for who is there...
|
|
ubGuyThere = WhoIsThere2( sSpot, pSoldier->pathing.bLevel );
|
|
|
|
if ( ubGuyThere == MercPtrs[ gusUIFullTargetID ]->ubID )
|
|
{
|
|
// We've got a guy here....
|
|
// Who is the one we want......
|
|
sGotLocation = sSpot;
|
|
sAdjustedGridNo = MercPtrs[ gusUIFullTargetID ]->sGridNo;
|
|
ubDirection = ( UINT8 )cnt;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( sGotLocation == NOWHERE )
|
|
{
|
|
sActionGridNo = FindAdjacentGridEx( pSoldier, MercPtrs[ gusUIFullTargetID ]->sGridNo, &ubDirection, &sAdjustedGridNo, TRUE, FALSE );
|
|
|
|
if ( sActionGridNo == -1 )
|
|
{
|
|
sGotLocation = NOWHERE;
|
|
}
|
|
else
|
|
{
|
|
sGotLocation = sActionGridNo;
|
|
}
|
|
fGotAdjacent = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sAdjustedGridNo = sMapPos;
|
|
sGotLocation = sActionGridNo;
|
|
fGotAdjacent = TRUE;
|
|
}
|
|
|
|
if ( sGotLocation != NOWHERE )
|
|
{
|
|
sAPCost += MinAPsToAttack( pSoldier, sAdjustedGridNo, TRUE );
|
|
|
|
// WANNE: Turn around APs were missing, I think ....
|
|
//sAPCost += APsToTurnAround(pSoldier, sAdjustedGridNo);
|
|
|
|
sAPCost += UIPlotPath( pSoldier, sGotLocation, NO_COPYROUTE, fPlot, TEMPORARY, (UINT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints);
|
|
|
|
if ( sGotLocation != pSoldier->sGridNo && fGotAdjacent )
|
|
{
|
|
gfUIHandleShowMoveGrid = TRUE;
|
|
gsUIHandleShowMoveGridLocation = sGotLocation;
|
|
}
|
|
}
|
|
}
|
|
else if ( uiFlags == MOVEUI_TARGET_STEAL )
|
|
{
|
|
// Check if we are on a target
|
|
if ( gfUIFullTargetFound )
|
|
{
|
|
sActionGridNo = FindAdjacentGridEx( pSoldier, MercPtrs[ gusUIFullTargetID ]->sGridNo, &ubDirection, &sAdjustedGridNo, TRUE, FALSE );
|
|
if ( sActionGridNo == -1 )
|
|
{
|
|
sActionGridNo = sAdjustedGridNo;
|
|
}
|
|
sAPCost += APBPConstants[AP_STEAL_ITEM];
|
|
// CJC August 13 2002: take into account stance in AP prediction
|
|
if (!(PTR_STANDING))
|
|
{
|
|
sAPCost += GetAPsToChangeStance( pSoldier, ANIM_STAND );
|
|
}
|
|
sAPCost += UIPlotPath( pSoldier, sActionGridNo, NO_COPYROUTE, fPlot, TEMPORARY, (UINT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints);
|
|
|
|
if ( sActionGridNo != pSoldier->sGridNo )
|
|
{
|
|
gfUIHandleShowMoveGrid = TRUE;
|
|
gsUIHandleShowMoveGridLocation = sActionGridNo;
|
|
}
|
|
}
|
|
}
|
|
else if ( uiFlags == MOVEUI_TARGET_BOMB )
|
|
{
|
|
if(Item[pSoldier->inv[HANDPOS].usItem].mine == 1)
|
|
sAPCost += GetAPsToPlantMine( pSoldier );
|
|
else
|
|
sAPCost += GetAPsToDropBomb( pSoldier );
|
|
sAPCost += UIPlotPath( pSoldier, sMapPos, NO_COPYROUTE, fPlot, TEMPORARY, (UINT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints );
|
|
|
|
gfUIHandleShowMoveGrid = TRUE;
|
|
gsUIHandleShowMoveGridLocation = sMapPos;
|
|
}
|
|
else if ( uiFlags == MOVEUI_TARGET_MERCSFORAID )
|
|
{
|
|
if ( gfUIFullTargetFound )
|
|
{
|
|
sActionGridNo = FindAdjacentGridEx( pSoldier, MercPtrs[ gusUIFullTargetID ]->sGridNo, &ubDirection, &sAdjustedGridNo, TRUE, FALSE );
|
|
|
|
// Try again at another gridno...
|
|
if ( sActionGridNo == -1 )
|
|
{
|
|
sActionGridNo = FindAdjacentGridEx( pSoldier, sMapPos, &ubDirection, &sAdjustedGridNo, TRUE, FALSE );
|
|
|
|
if ( sActionGridNo == -1 )
|
|
{
|
|
sActionGridNo = sAdjustedGridNo;
|
|
}
|
|
}
|
|
sAPCost += GetAPsToBeginFirstAid( pSoldier );
|
|
sAPCost += UIPlotPath( pSoldier, sActionGridNo, NO_COPYROUTE, fPlot, TEMPORARY, (UINT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints);
|
|
if ( sActionGridNo != pSoldier->sGridNo )
|
|
{
|
|
gfUIHandleShowMoveGrid = TRUE;
|
|
gsUIHandleShowMoveGridLocation = sActionGridNo;
|
|
}
|
|
}
|
|
}
|
|
else if ( uiFlags == MOVEUI_TARGET_ITEMS )
|
|
{
|
|
//if ( GetItemPool( sMapPos, &pItemPool, pSoldier->pathing.bLevel ) )
|
|
{
|
|
//if ( ITEMPOOL_VISIBLE( pItemPool ) )
|
|
{
|
|
sActionGridNo = AdjustGridNoForItemPlacement( pSoldier, sActionGridNo );
|
|
|
|
if ( pSoldier->sGridNo != sActionGridNo )
|
|
{
|
|
sAPCost += UIPlotPath( pSoldier, sActionGridNo, NO_COPYROUTE, fPlot, TEMPORARY, (UINT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints);
|
|
if ( sAPCost != 0 )
|
|
{
|
|
sAPCost += APBPConstants[AP_PICKUP_ITEM];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sAPCost += APBPConstants[AP_PICKUP_ITEM];
|
|
}
|
|
|
|
if ( sActionGridNo != pSoldier->sGridNo )
|
|
{
|
|
gfUIHandleShowMoveGrid = TRUE;
|
|
gsUIHandleShowMoveGridLocation = sActionGridNo;
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sAPCost += UIPlotPath( pSoldier, sActionGridNo, NO_COPYROUTE, fPlot, TEMPORARY, (UINT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints );
|
|
}
|
|
|
|
if ( gTacticalStatus.uiFlags & SHOW_AP_LEFT )
|
|
{
|
|
gsCurrentActionPoints = pSoldier->bActionPoints - sAPCost;
|
|
}
|
|
else
|
|
{
|
|
gsCurrentActionPoints = sAPCost;
|
|
}
|
|
|
|
return( bReturnCode );
|
|
}
|
|
|
|
// WANNE: Calculate the APs to turn around
|
|
INT16 APsToTurnAround(SOLDIERTYPE *pSoldier, INT16 sAdjustedGridNo)
|
|
{
|
|
INT16 sAPCost = 0;
|
|
BOOLEAN fInitalMove = FALSE;
|
|
|
|
// Get the new direction
|
|
UINT8 ubDirection = (UINT8)GetDirectionFromGridNo( sAdjustedGridNo, pSoldier );
|
|
|
|
// If new direction is not the same than the old direction
|
|
if ( pSoldier->pathing.bDesiredDirection != ubDirection)
|
|
{
|
|
if ( gAnimControl[ pSoldier->usAnimState ].uiFlags & ( ANIM_BREATH | ANIM_OK_CHARGE_AP_FOR_TURN | ANIM_FIREREADY ) && !fInitalMove && !pSoldier->flags.fDontChargeTurningAPs )
|
|
{
|
|
// Which position has the soldier?
|
|
switch( gAnimControl[ pSoldier->usAnimState ].ubEndHeight )
|
|
{
|
|
case ANIM_STAND:
|
|
sAPCost += APBPConstants[AP_LOOK_STANDING];
|
|
break;
|
|
case ANIM_CROUCH:
|
|
sAPCost += APBPConstants[AP_LOOK_CROUCHED];
|
|
break;
|
|
case ANIM_PRONE:
|
|
sAPCost += APBPConstants[AP_LOOK_PRONE];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return sAPCost;
|
|
}
|
|
|
|
|
|
BOOLEAN UIMouseOnValidAttackLocation( SOLDIERTYPE *pSoldier )
|
|
{
|
|
UINT16 usInHand;
|
|
BOOLEAN fGuyHere = FALSE;
|
|
SOLDIERTYPE *pTSoldier;
|
|
UINT8 ubItemCursor;
|
|
INT16 sMapPos;
|
|
|
|
if ( !GetMouseMapPos( &sMapPos ) )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
// LOOK IN GUY'S HAND TO CHECK LOCATION
|
|
usInHand = pSoldier->inv[HANDPOS].usItem;
|
|
|
|
// Get cursor value
|
|
ubItemCursor = GetActionModeCursor( pSoldier );
|
|
|
|
if ( ubItemCursor == INVALIDCURS )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
|
|
if ( ubItemCursor == WIRECUTCURS )
|
|
{
|
|
if ( IsCuttableWireFenceAtGridNo( sMapPos ) && pSoldier->pathing.bLevel == 0 )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
else
|
|
{
|
|
return( FALSE );
|
|
}
|
|
}
|
|
|
|
if ( ubItemCursor == REPAIRCURS )
|
|
{
|
|
if ( gfUIFullTargetFound )
|
|
{
|
|
sMapPos = MercPtrs[ gusUIFullTargetID ]->sGridNo;
|
|
}
|
|
|
|
if ( IsRepairableStructAtGridNo( sMapPos, NULL ) && pSoldier->pathing.bLevel == 0 )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
else
|
|
{
|
|
return( FALSE );
|
|
}
|
|
}
|
|
|
|
if ( ubItemCursor == REFUELCURS )
|
|
{
|
|
if ( gfUIFullTargetFound )
|
|
{
|
|
sMapPos = MercPtrs[ gusUIFullTargetID ]->sGridNo;
|
|
}
|
|
|
|
if ( IsRefuelableStructAtGridNo( sMapPos, NULL ) && pSoldier->pathing.bLevel == 0 )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
else
|
|
{
|
|
return( FALSE );
|
|
}
|
|
}
|
|
|
|
if ( ubItemCursor == BOMBCURS )
|
|
{
|
|
if ( sMapPos == pSoldier->sGridNo )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
|
|
if ( !NewOKDestination( pSoldier, sMapPos, TRUE, pSoldier->pathing.bLevel ) )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
}
|
|
|
|
// SEE IF THERE IS SOMEBODY HERE
|
|
if ( gfUIFullTargetFound && ubItemCursor != KNIFECURS )
|
|
{
|
|
fGuyHere = TRUE;
|
|
|
|
if ( guiUIFullTargetFlags & SELECTED_MERC && Item[ usInHand ].usItemClass != IC_MEDKIT )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
}
|
|
|
|
if ( !CanPlayerUseRocketRifle( pSoldier, TRUE ) )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
//if ( Item[ usInHand ].usItemClass == IC_BLADE && usInHand != THROWING_KNIFE )
|
|
//{
|
|
// if ( !fGuyHere )
|
|
// {
|
|
// return( FALSE );
|
|
// }
|
|
//}
|
|
|
|
if ( Item[ usInHand ].usItemClass == IC_PUNCH )
|
|
{
|
|
if ( !fGuyHere )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
}
|
|
|
|
//if ( Item[ usInHand ].usItemClass == IC_BLADE )
|
|
//{
|
|
// if ( !fGuyHere )
|
|
// {
|
|
// return( FALSE );
|
|
// }
|
|
//}
|
|
|
|
if ( Item[ usInHand ].usItemClass == IC_MEDKIT )
|
|
{
|
|
if ( !fGuyHere )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
// IF a guy's here, chack if they need medical help!
|
|
pTSoldier = MercPtrs[ gusUIFullTargetID ];
|
|
|
|
// If we are a vehicle...
|
|
if ( ( pTSoldier->flags.uiStatusFlags & ( SOLDIER_VEHICLE | SOLDIER_ROBOT ) ) )
|
|
{
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, TacticalStr[ CANNOT_DO_FIRST_AID_STR ], pTSoldier->name );
|
|
return( FALSE );
|
|
}
|
|
|
|
if ( pSoldier->stats.bMedical == 0 )
|
|
{
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, pMessageStrings[ MSG_MERC_HAS_NO_MEDSKILL ], pSoldier->name );
|
|
return( FALSE );
|
|
}
|
|
|
|
if ( pTSoldier->bBleeding == 0 && pTSoldier->stats.bLife != pTSoldier->stats.bLifeMax )
|
|
{
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, gzLateLocalizedString[ 19 ], pTSoldier->name );
|
|
return( FALSE );
|
|
}
|
|
|
|
if ( pTSoldier->bBleeding == 0 && pTSoldier->stats.bLife >= OKLIFE )
|
|
{
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, TacticalStr[ CANNOT_NO_NEED_FIRST_AID_STR ], pTSoldier->name );
|
|
return( FALSE );
|
|
}
|
|
|
|
}
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
BOOLEAN UIOkForItemPickup( SOLDIERTYPE *pSoldier, INT16 sGridNo )
|
|
{
|
|
INT16 sAPCost;
|
|
ITEM_POOL *pItemPool;
|
|
|
|
sAPCost = GetAPsToPickupItem( pSoldier, sGridNo );
|
|
|
|
if ( sAPCost == 0 )
|
|
{
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, TacticalStr[ NO_PATH ] );
|
|
}
|
|
else
|
|
{
|
|
if ( GetItemPool( sGridNo, &pItemPool, pSoldier->pathing.bLevel ) )
|
|
{
|
|
//if ( !ITEMPOOL_VISIBLE( pItemPool ) )
|
|
{
|
|
// return( FALSE );
|
|
}
|
|
}
|
|
|
|
if ( EnoughPoints( pSoldier, sAPCost, 0, TRUE ) )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
}
|
|
|
|
return( FALSE );
|
|
}
|
|
|
|
|
|
BOOLEAN SoldierCanAffordNewStance( SOLDIERTYPE *pSoldier, UINT8 ubDesiredStance )
|
|
{
|
|
INT8 bCurrentHeight;
|
|
UINT8 bAP = 0, bBP = 0;
|
|
|
|
bCurrentHeight = ( ubDesiredStance - gAnimControl[ pSoldier->usAnimState ].ubEndHeight );
|
|
|
|
// Now change to appropriate animation
|
|
|
|
// CHRISL: Modify function to include extra cost if wearing a backpack but only while running new inventory system
|
|
switch( bCurrentHeight )
|
|
{
|
|
case ANIM_STAND - ANIM_CROUCH:
|
|
if((UsingNewInventorySystem() == true))
|
|
if(pSoldier->inv[BPACKPOCKPOS].exists() == true && !pSoldier->flags.ZipperFlag)
|
|
bAP = bBP = 1;
|
|
bAP += APBPConstants[AP_CROUCH];
|
|
bBP += APBPConstants[BP_CROUCH];
|
|
break;
|
|
case ANIM_CROUCH - ANIM_STAND:
|
|
if((UsingNewInventorySystem() == true))
|
|
if(pSoldier->inv[BPACKPOCKPOS].exists() == true && !pSoldier->flags.ZipperFlag)
|
|
bAP = bBP = 2;
|
|
bAP += APBPConstants[AP_CROUCH];
|
|
bBP += APBPConstants[BP_CROUCH];
|
|
break;
|
|
case ANIM_STAND - ANIM_PRONE:
|
|
if((UsingNewInventorySystem() == true))
|
|
if(pSoldier->inv[BPACKPOCKPOS].exists() == true && !pSoldier->flags.ZipperFlag)
|
|
bAP = bBP = 2;
|
|
bAP += APBPConstants[AP_CROUCH] + APBPConstants[AP_PRONE];
|
|
bBP += APBPConstants[BP_CROUCH] + APBPConstants[BP_PRONE];
|
|
break;
|
|
case ANIM_PRONE - ANIM_STAND:
|
|
if((UsingNewInventorySystem() == true))
|
|
if(pSoldier->inv[BPACKPOCKPOS].exists() == true && !pSoldier->flags.ZipperFlag)
|
|
bAP = bBP = 4;
|
|
bAP += APBPConstants[AP_CROUCH] + APBPConstants[AP_PRONE];
|
|
bBP += APBPConstants[BP_CROUCH] + APBPConstants[BP_PRONE];
|
|
break;
|
|
case ANIM_CROUCH - ANIM_PRONE:
|
|
if((UsingNewInventorySystem() == true))
|
|
if(pSoldier->inv[BPACKPOCKPOS].exists() == true && !pSoldier->flags.ZipperFlag)
|
|
bAP = bBP = 1;
|
|
bAP += APBPConstants[AP_PRONE];
|
|
bBP += APBPConstants[BP_PRONE];
|
|
break;
|
|
case ANIM_PRONE - ANIM_CROUCH:
|
|
if((UsingNewInventorySystem() == true))
|
|
if(pSoldier->inv[BPACKPOCKPOS].exists() == true && !pSoldier->flags.ZipperFlag)
|
|
bAP = bBP = 2;
|
|
bAP += APBPConstants[AP_PRONE];
|
|
bBP += APBPConstants[BP_PRONE];
|
|
break;
|
|
|
|
}
|
|
|
|
return ( EnoughPoints( pSoldier, bAP, bBP , TRUE ) );
|
|
}
|
|
|
|
void SetUIbasedOnStance( SOLDIERTYPE *pSoldier, INT8 bNewStance )
|
|
{
|
|
// Set UI based on our stance!
|
|
switch ( bNewStance )
|
|
{
|
|
case ANIM_STAND:
|
|
pSoldier->usUIMovementMode = WALKING;
|
|
break;
|
|
|
|
case ANIM_CROUCH:
|
|
pSoldier->usUIMovementMode = SWATTING;
|
|
break;
|
|
|
|
case ANIM_PRONE:
|
|
pSoldier->usUIMovementMode = CRAWLING;
|
|
break;
|
|
}
|
|
|
|
// Set UI cursor!
|
|
|
|
}
|
|
|
|
|
|
void SetMovementModeCursor( SOLDIERTYPE *pSoldier )
|
|
{
|
|
if ( gTacticalStatus.uiFlags & TURNBASED && ( gTacticalStatus.uiFlags & INCOMBAT ) )
|
|
{
|
|
if ( ( OK_ENTERABLE_VEHICLE( pSoldier ) ) )
|
|
{
|
|
guiNewUICursor = MOVE_VEHICLE_UICURSOR;
|
|
}
|
|
else
|
|
{
|
|
// Change mouse cursor based on type of movement we want to do
|
|
switch ( pSoldier->usUIMovementMode )
|
|
{
|
|
case WALKING:
|
|
guiNewUICursor = MOVE_WALK_UICURSOR;
|
|
break;
|
|
|
|
case RUNNING:
|
|
guiNewUICursor = MOVE_RUN_UICURSOR;
|
|
break;
|
|
|
|
case SWATTING:
|
|
guiNewUICursor = MOVE_SWAT_UICURSOR;
|
|
break;
|
|
|
|
case CRAWLING:
|
|
guiNewUICursor = MOVE_PRONE_UICURSOR;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( ( gTacticalStatus.uiFlags & REALTIME ) || !( gTacticalStatus.uiFlags & INCOMBAT ) )
|
|
{
|
|
if ( gfUIAllMoveOn )
|
|
{
|
|
guiNewUICursor = ALL_MOVE_REALTIME_UICURSOR;
|
|
}
|
|
else
|
|
{
|
|
//if ( pSoldier->flags.fUIMovementFast )
|
|
//{
|
|
// BeginDisplayTimedCursor( MOVE_RUN_REALTIME_UICURSOR, 300 );
|
|
//}
|
|
|
|
guiNewUICursor = MOVE_REALTIME_UICURSOR;
|
|
}
|
|
}
|
|
|
|
guiNewUICursor = GetInteractiveTileCursor( guiNewUICursor, FALSE );
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetConfirmMovementModeCursor( SOLDIERTYPE *pSoldier, BOOLEAN fFromMove )
|
|
{
|
|
if ( gTacticalStatus.uiFlags & TURNBASED && ( gTacticalStatus.uiFlags & INCOMBAT ) )
|
|
{
|
|
if ( gfUIAllMoveOn )
|
|
{
|
|
if ( ( OK_ENTERABLE_VEHICLE( pSoldier ) ) )
|
|
{
|
|
guiNewUICursor = ALL_MOVE_VEHICLE_UICURSOR;
|
|
}
|
|
else
|
|
{
|
|
// Change mouse cursor based on type of movement we want to do
|
|
switch ( pSoldier->usUIMovementMode )
|
|
{
|
|
case WALKING:
|
|
guiNewUICursor = ALL_MOVE_WALK_UICURSOR;
|
|
break;
|
|
|
|
case RUNNING:
|
|
guiNewUICursor = ALL_MOVE_RUN_UICURSOR;
|
|
break;
|
|
|
|
case SWATTING:
|
|
guiNewUICursor = ALL_MOVE_SWAT_UICURSOR;
|
|
break;
|
|
|
|
case CRAWLING:
|
|
guiNewUICursor = ALL_MOVE_PRONE_UICURSOR;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE )
|
|
{
|
|
guiNewUICursor = CONFIRM_MOVE_VEHICLE_UICURSOR;
|
|
}
|
|
else
|
|
{
|
|
// Change mouse cursor based on type of movement we want to do
|
|
switch ( pSoldier->usUIMovementMode )
|
|
{
|
|
case WALKING:
|
|
guiNewUICursor = CONFIRM_MOVE_WALK_UICURSOR;
|
|
break;
|
|
|
|
case RUNNING:
|
|
guiNewUICursor = CONFIRM_MOVE_RUN_UICURSOR;
|
|
break;
|
|
|
|
case SWATTING:
|
|
guiNewUICursor = CONFIRM_MOVE_SWAT_UICURSOR;
|
|
break;
|
|
|
|
case CRAWLING:
|
|
guiNewUICursor = CONFIRM_MOVE_PRONE_UICURSOR;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( ( gTacticalStatus.uiFlags & REALTIME ) || !( gTacticalStatus.uiFlags & INCOMBAT ) )
|
|
{
|
|
if ( gfUIAllMoveOn )
|
|
{
|
|
if ( gfUIAllMoveOn == 2 )
|
|
{
|
|
BeginDisplayTimedCursor( MOVE_RUN_REALTIME_UICURSOR, 300 );
|
|
}
|
|
else
|
|
{
|
|
guiNewUICursor = ALL_MOVE_REALTIME_UICURSOR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( pSoldier->flags.fUIMovementFast && pSoldier->usAnimState == RUNNING && fFromMove )
|
|
{
|
|
BeginDisplayTimedCursor( MOVE_RUN_REALTIME_UICURSOR, 300 );
|
|
}
|
|
|
|
guiNewUICursor = CONFIRM_MOVE_REALTIME_UICURSOR;
|
|
}
|
|
}
|
|
|
|
guiNewUICursor = GetInteractiveTileCursor( guiNewUICursor, TRUE );
|
|
|
|
}
|
|
|
|
UINT8 gubShowActionPointsInRed = 0;
|
|
|
|
UINT32 UIHandleLCOnTerrain( UI_EVENT *pUIEvent )
|
|
{
|
|
SOLDIERTYPE *pSoldier;
|
|
INT16 sFacingDir, sXPos, sYPos;
|
|
UINT16 usAnimState;
|
|
|
|
guiNewUICursor = LOOK_UICURSOR;
|
|
|
|
// Get soldier
|
|
if ( !GetSoldier( &pSoldier, gusSelectedSoldier ) )
|
|
{
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
gfUIDisplayActionPoints = TRUE;
|
|
|
|
gUIDisplayActionPointsOffX = 14;
|
|
gUIDisplayActionPointsOffY = 7;
|
|
|
|
|
|
// Get soldier
|
|
if ( !GetSoldier( &pSoldier, gusSelectedSoldier ) )
|
|
{
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
GetMouseXY( &sXPos, &sYPos );
|
|
|
|
// Get direction from mouse pos
|
|
sFacingDir = GetDirectionFromXY( sXPos, sYPos, pSoldier );
|
|
|
|
// Set # of APs
|
|
if ( sFacingDir != pSoldier->ubDirection )
|
|
{
|
|
gsCurrentActionPoints = GetAPsToLook( pSoldier );
|
|
gfUIHandleShowMoveGrid = FALSE;
|
|
}
|
|
else
|
|
{
|
|
usAnimState = PickSoldierReadyAnimation( pSoldier, FALSE );
|
|
|
|
gsCurrentActionPoints = 0;
|
|
|
|
//CHRISL: Why are we doing this? If we ready a weapon, we spend the AP_CHANGE_TARGET APs, but then if we actually shoot
|
|
// at someone in our current firing arc, we'll again pay the AP_CHANGE_TARGET cost because it's considered a new tartget.
|
|
// Should be simply pay the ready weapon cost and only pay the AP_CHANGE_TARGET when we actually aim at a target?
|
|
// Lesh: raise weapon include APs to set weapon towards enemy and APs to aquire/change target
|
|
//if( pSoldier->sLastTarget != sXPos + (MAXCOL * sYPos ) )
|
|
// gsCurrentActionPoints = APBPConstants[AP_CHANGE_TARGET];
|
|
|
|
if( usAnimState != INVALID_ANIMATION )
|
|
{
|
|
gsCurrentActionPoints += GetAPsToReadyWeapon( pSoldier, usAnimState );// Madd: removed the next part since it was deducting 2 extra aps that would not be deducted when readying the old way //+ AP_TO_AIM_TILE_IF_GETTING_READY;
|
|
}
|
|
|
|
gfUIHandleShowMoveGrid = TRUE;
|
|
gsUIHandleShowMoveGridLocation = sXPos + (MAXCOL * sYPos );
|
|
|
|
gubShowActionPointsInRed = 5;
|
|
//gfDisplayFullCountRingBurst = FALSE;
|
|
}
|
|
|
|
// Determine if we can afford!
|
|
if ( !EnoughPoints( pSoldier, gsCurrentActionPoints, 0, FALSE ) )
|
|
{
|
|
gfUIDisplayActionPointsInvalid = TRUE;
|
|
}
|
|
|
|
//HandleSight( pSoldier, SIGHT_LOOK );
|
|
|
|
return( GAME_SCREEN );
|
|
|
|
}
|
|
|
|
|
|
UINT32 UIHandleLCChangeToLook( UI_EVENT *pUIEvent )
|
|
{
|
|
ErasePath( TRUE );
|
|
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
|
|
BOOLEAN MakeSoldierTurn( SOLDIERTYPE *pSoldier, INT16 sXPos, INT16 sYPos )
|
|
{
|
|
INT16 sFacingDir, sAPCost, sAPCostToReady;
|
|
UINT16 usAnimState;
|
|
|
|
// Make sure the merc is not collapsed!
|
|
if (!IsValidStance(pSoldier, ANIM_CROUCH) )
|
|
{
|
|
if ( pSoldier->bCollapsed && pSoldier->bBreath < OKBREATH )
|
|
{
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, gzLateLocalizedString[ 4 ], pSoldier->name );
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
// Get direction from mouse pos
|
|
sFacingDir = GetDirectionFromXY( sXPos, sYPos, pSoldier );
|
|
|
|
if ( sFacingDir != pSoldier->ubDirection )
|
|
{
|
|
sAPCost = GetAPsToLook( pSoldier );
|
|
|
|
// Check AP cost...
|
|
if ( !EnoughPoints( pSoldier, sAPCost, 0, TRUE ) )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
// ATE: make stationary if...
|
|
if ( pSoldier->flags.fNoAPToFinishMove )
|
|
{
|
|
// arynn : fix lower ready weapons
|
|
//previously "ready weapon" state was being dropped in a couple of cases
|
|
//the fix involves bypassing the reset animation state for the various "ready weapon" types
|
|
//since this is a reset animation function, we should be VERY specific about when and what we dont reset
|
|
|
|
UINT16 test;
|
|
test = pSoldier->usAnimState;
|
|
if (!( test == AIM_RIFLE_STAND || test == AIM_RIFLE_CROUCH ||
|
|
test == AIM_RIFLE_PRONE || test == AIM_DUAL_STAND ||
|
|
test == AIM_DUAL_CROUCH || test == AIM_DUAL_PRONE
|
|
))
|
|
{
|
|
pSoldier->SoldierGotoStationaryStance( );
|
|
}// arynn : fix lower ready weapon end_if
|
|
}
|
|
|
|
//DEF: made it an event
|
|
SendSoldierSetDesiredDirectionEvent( pSoldier, sFacingDir );
|
|
|
|
pSoldier->bTurningFromUI = TRUE;
|
|
|
|
// ATE: Hard-code here previous event to ui busy event...
|
|
guiOldEvent = LA_BEGINUIOURTURNLOCK;
|
|
|
|
return( TRUE );
|
|
}
|
|
else
|
|
{
|
|
usAnimState = PickSoldierReadyAnimation( pSoldier, FALSE );
|
|
|
|
sAPCostToReady = sAPCost = 0;
|
|
|
|
//CHRISL: We should only charge AP_CHANGE_TARGET if we're actually pointing at a new target. Don't charge just
|
|
// to ready a weapon since we'll charge AP_CHANGE_TARGET when we actually fire.
|
|
SOLDIERTYPE * pTarget = SimpleFindSoldier( sXPos + (MAXCOL * sYPos ), pSoldier->bTargetLevel );
|
|
|
|
// Lesh: raise weapon include APs to set weapon towards enemy and APs to aquire/change target
|
|
if( pSoldier->sLastTarget != sXPos + (MAXCOL * sYPos ) && pTarget != NULL )
|
|
sAPCost = APBPConstants[AP_CHANGE_TARGET];
|
|
|
|
if( usAnimState != INVALID_ANIMATION )
|
|
{
|
|
sAPCostToReady = GetAPsToReadyWeapon( pSoldier, usAnimState );
|
|
}
|
|
|
|
// Check AP cost...
|
|
if ( !EnoughPoints( pSoldier, sAPCost + sAPCostToReady, 0, TRUE ) )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
if( usAnimState != INVALID_ANIMATION )
|
|
pSoldier->SoldierReadyWeapon( sXPos, sYPos, FALSE );
|
|
|
|
pSoldier->bTurningFromUI = TRUE;
|
|
guiOldEvent = LA_BEGINUIOURTURNLOCK;
|
|
|
|
// Setting "Last Target"
|
|
|
|
pSoldier->sLastTarget = sXPos + (MAXCOL * sYPos);
|
|
DeductPoints( pSoldier, sAPCost, 0 );
|
|
|
|
return( TRUE );
|
|
}
|
|
}
|
|
|
|
|
|
UINT32 UIHandleLCLook( UI_EVENT *pUIEvent )
|
|
{
|
|
INT16 sXPos, sYPos;
|
|
SOLDIERTYPE *pSoldier;
|
|
INT32 cnt;
|
|
if ( !GetMouseXY( &sXPos, &sYPos ) )
|
|
{
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
if ( gTacticalStatus.fAtLeastOneGuyOnMultiSelect )
|
|
{
|
|
// OK, loop through all guys who are 'multi-selected' and
|
|
cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
|
|
for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++, pSoldier++ )
|
|
{
|
|
if ( pSoldier->bActive && pSoldier->bInSector )
|
|
{
|
|
if ( pSoldier->flags.uiStatusFlags & SOLDIER_MULTI_SELECTED )
|
|
{
|
|
MakeSoldierTurn( pSoldier, sXPos, sYPos );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Get soldier
|
|
if ( !GetSoldier( &pSoldier, gusSelectedSoldier ) )
|
|
{
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
if ( MakeSoldierTurn( pSoldier, sXPos, sYPos ) )
|
|
{
|
|
// 0verhaul: Why do we set UI busy for a single soldier but not for a group of selected soldiers?
|
|
//SetUIBusy( pSoldier->ubID );
|
|
}
|
|
}
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
|
|
|
|
UINT32 UIHandleTOnTerrain( UI_EVENT *pUIEvent )
|
|
{
|
|
SOLDIERTYPE *pSoldier;
|
|
UINT8 ubTargID;
|
|
UINT32 uiRange;
|
|
INT16 sMapPos;
|
|
BOOLEAN fValidTalkableGuy = FALSE;
|
|
INT16 sTargetGridNo;
|
|
|
|
// Get soldier
|
|
if ( !GetSoldier( &pSoldier, gusSelectedSoldier ) )
|
|
{
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
if (!GetMouseMapPos( &sMapPos ) )
|
|
{
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
if( ValidQuickExchangePosition( ) )
|
|
{
|
|
// Do new cursor!
|
|
guiPendingOverrideEvent = M_ON_TERRAIN;
|
|
return( UIHandleMOnTerrain( pUIEvent ) );
|
|
}
|
|
|
|
sTargetGridNo = sMapPos;
|
|
|
|
|
|
UIHandleOnMerc( FALSE );
|
|
|
|
|
|
//CHECK FOR VALID TALKABLE GUY HERE
|
|
fValidTalkableGuy = IsValidTalkableNPCFromMouse( &ubTargID, FALSE, TRUE , FALSE );
|
|
|
|
// USe cursor based on distance
|
|
// Get distance away
|
|
if ( fValidTalkableGuy )
|
|
{
|
|
sTargetGridNo = MercPtrs[ ubTargID ]->sGridNo;
|
|
}
|
|
|
|
uiRange = GetRangeFromGridNoDiff( pSoldier->sGridNo, sTargetGridNo );
|
|
|
|
|
|
if ( uiRange <= NPC_TALK_RADIUS )
|
|
{
|
|
if ( fValidTalkableGuy )
|
|
{
|
|
guiNewUICursor = TALK_A_UICURSOR;
|
|
}
|
|
else
|
|
{
|
|
guiNewUICursor = TALK_NA_UICURSOR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( fValidTalkableGuy )
|
|
{
|
|
//guiNewUICursor = TALK_OUT_RANGE_A_UICURSOR;
|
|
guiNewUICursor = TALK_A_UICURSOR;
|
|
}
|
|
else
|
|
{
|
|
guiNewUICursor = TALK_OUT_RANGE_NA_UICURSOR;
|
|
}
|
|
}
|
|
|
|
if ( fValidTalkableGuy )
|
|
{
|
|
if ( !SoldierTo3DLocationLineOfSightTest( pSoldier, sTargetGridNo, pSoldier->pathing.bLevel, 3, TRUE, CALC_FROM_ALL_DIRS ) )
|
|
{
|
|
//. ATE: Make range far, so we alternate cursors...
|
|
guiNewUICursor = TALK_OUT_RANGE_A_UICURSOR;
|
|
}
|
|
}
|
|
|
|
gfUIDisplayActionPoints = TRUE;
|
|
|
|
gUIDisplayActionPointsOffX = 8;
|
|
gUIDisplayActionPointsOffY = 3;
|
|
|
|
// Set # of APs
|
|
gsCurrentActionPoints = 6;
|
|
|
|
// Determine if we can afford!
|
|
if ( !EnoughPoints( pSoldier, gsCurrentActionPoints, 0, FALSE ) )
|
|
{
|
|
gfUIDisplayActionPointsInvalid = TRUE;
|
|
}
|
|
|
|
if ( !( gTacticalStatus.uiFlags & INCOMBAT ) )
|
|
{
|
|
if ( gfUIFullTargetFound )
|
|
{
|
|
PauseRT( TRUE );
|
|
}
|
|
else
|
|
{
|
|
PauseRT( FALSE );
|
|
}
|
|
}
|
|
|
|
return( GAME_SCREEN );
|
|
|
|
}
|
|
|
|
|
|
UINT32 UIHandleTChangeToTalking( UI_EVENT *pUIEvent )
|
|
{
|
|
ErasePath( TRUE );
|
|
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
|
|
UINT32 UIHandleLUIOnTerrain( UI_EVENT *pUIEvent )
|
|
{
|
|
//guiNewUICursor = NO_UICURSOR;
|
|
// SetCurrentCursorFromDatabase( VIDEO_NO_CURSOR );
|
|
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
|
|
UINT32 UIHandleLUIBeginLock( UI_EVENT *pUIEvent )
|
|
{
|
|
// Don't let both versions of the locks to happen at the same time!
|
|
// ( They are mutually exclusive )!
|
|
UIHandleLAEndLockOurTurn( NULL );
|
|
|
|
if ( !gfDisableRegionActive )
|
|
{
|
|
gfDisableRegionActive = TRUE;
|
|
|
|
RemoveTacticalCursor( );
|
|
//SetCurrentCursorFromDatabase( VIDEO_NO_CURSOR );
|
|
|
|
MSYS_DefineRegion( &gDisableRegion, 0, 0 ,SCREEN_WIDTH, SCREEN_HEIGHT, MSYS_PRIORITY_HIGHEST,
|
|
CURSOR_WAIT, MSYS_NO_CALLBACK, MSYS_NO_CALLBACK );
|
|
// Add region
|
|
MSYS_AddRegion( &gDisableRegion );
|
|
|
|
//guiPendingOverrideEvent = LOCKUI_MODE;
|
|
|
|
// UnPause time!
|
|
PauseGame();
|
|
LockPauseState( 16 );
|
|
|
|
}
|
|
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
UINT32 UIHandleLUIEndLock( UI_EVENT *pUIEvent )
|
|
{
|
|
if ( gfDisableRegionActive )
|
|
{
|
|
gfDisableRegionActive = FALSE;
|
|
|
|
// Add region
|
|
MSYS_RemoveRegion( &gDisableRegion );
|
|
RefreshMouseRegions( );
|
|
|
|
//SetCurrentCursorFromDatabase( guiCurrentUICursor );
|
|
|
|
guiForceRefreshMousePositionCalculation = TRUE;
|
|
UIHandleMOnTerrain( NULL );
|
|
|
|
if ( gViewportRegion.uiFlags & MSYS_MOUSE_IN_AREA )
|
|
{
|
|
SetCurrentCursorFromDatabase( gUICursors[ guiNewUICursor ].usFreeCursorName );
|
|
}
|
|
|
|
guiPendingOverrideEvent = M_ON_TERRAIN;
|
|
HandleTacticalUI( );
|
|
|
|
// ATE: Only if NOT in conversation!
|
|
if ( !( gTacticalStatus.uiFlags & ENGAGED_IN_CONV ) )
|
|
{
|
|
// UnPause time!
|
|
UnLockPauseState();
|
|
UnPauseGame();
|
|
}
|
|
}
|
|
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
|
|
void CheckForDisabledRegionRemove( )
|
|
{
|
|
if ( gfDisableRegionActive )
|
|
{
|
|
gfDisableRegionActive = FALSE;
|
|
|
|
// Remove region
|
|
MSYS_RemoveRegion( &gDisableRegion );
|
|
|
|
UnLockPauseState();
|
|
UnPauseGame();
|
|
|
|
}
|
|
|
|
if ( gfUserTurnRegionActive )
|
|
{
|
|
gfUserTurnRegionActive = FALSE;
|
|
|
|
gfUIInterfaceSetBusy = FALSE;
|
|
|
|
// Remove region
|
|
MSYS_RemoveRegion( &gUserTurnRegion );
|
|
|
|
UnLockPauseState();
|
|
UnPauseGame();
|
|
}
|
|
}
|
|
|
|
UINT32 UIHandleLAOnTerrain( UI_EVENT *pUIEvent )
|
|
{
|
|
//guiNewUICursor = NO_UICURSOR;
|
|
//SetCurrentCursorFromDatabase( VIDEO_NO_CURSOR );
|
|
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
|
|
void GetGridNoScreenXY( INT16 sGridNo, INT16 *pScreenX, INT16 *pScreenY )
|
|
{
|
|
INT16 sScreenX, sScreenY;
|
|
INT16 sOffsetX, sOffsetY;
|
|
INT16 sTempX_S, sTempY_S;
|
|
INT16 sXPos, sYPos;
|
|
|
|
ConvertGridNoToCellXY( sGridNo, &sXPos, &sYPos );
|
|
|
|
// Get 'TRUE' merc position
|
|
sOffsetX = sXPos - gsRenderCenterX;
|
|
sOffsetY = sYPos - gsRenderCenterY;
|
|
|
|
FromCellToScreenCoordinates( sOffsetX, sOffsetY, &sTempX_S, &sTempY_S );
|
|
|
|
sScreenX = ( ( gsVIEWPORT_END_X - gsVIEWPORT_START_X ) /2 ) + (INT16)sTempX_S;
|
|
sScreenY = ( ( gsVIEWPORT_END_Y - gsVIEWPORT_START_Y ) /2 ) + (INT16)sTempY_S;
|
|
|
|
// Adjust for offset position on screen
|
|
sScreenX -= gsRenderWorldOffsetX;
|
|
sScreenY -= gsRenderWorldOffsetY;
|
|
sScreenY -= gpWorldLevelData[ sGridNo ].sHeight;
|
|
|
|
// Adjust based on interface level
|
|
|
|
// Adjust for render height
|
|
sScreenY += gsRenderHeight;
|
|
|
|
// Adjust y offset!
|
|
sScreenY += ( WORLD_TILE_Y/2);
|
|
|
|
(*pScreenX) = sScreenX;
|
|
(*pScreenY) = sScreenY;
|
|
}
|
|
|
|
|
|
void EndMultiSoldierSelection( BOOLEAN fAcknowledge )
|
|
{
|
|
SOLDIERTYPE * pSoldier;
|
|
INT32 cnt;
|
|
SOLDIERTYPE *pFirstSoldier = NULL;
|
|
BOOLEAN fSelectedSoldierInBatch = FALSE;
|
|
|
|
|
|
gTacticalStatus.fAtLeastOneGuyOnMultiSelect = FALSE;
|
|
|
|
|
|
// OK, loop through all guys who are 'multi-selected' and
|
|
// check if our currently selected guy is amoung the
|
|
// lucky few.. if not, change to a guy who is...
|
|
cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
|
|
for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++, pSoldier++ )
|
|
{
|
|
if ( pSoldier->bActive && pSoldier->bInSector )
|
|
{
|
|
if ( pSoldier->flags.uiStatusFlags & SOLDIER_MULTI_SELECTED )
|
|
{
|
|
gTacticalStatus.fAtLeastOneGuyOnMultiSelect = TRUE;
|
|
|
|
if ( pSoldier->ubID != gusSelectedSoldier && pFirstSoldier == NULL )
|
|
{
|
|
pFirstSoldier = pSoldier;
|
|
}
|
|
|
|
if ( pSoldier->ubID == gusSelectedSoldier )
|
|
{
|
|
fSelectedSoldierInBatch = TRUE;
|
|
}
|
|
|
|
if( !gGameSettings.fOptions[ TOPTION_MUTE_CONFIRMATIONS ] && fAcknowledge )
|
|
pSoldier->InternalDoMercBattleSound( BATTLE_SOUND_ATTN1, BATTLE_SND_LOWER_VOLUME );
|
|
|
|
if ( pSoldier->flags.fMercAsleep )
|
|
{
|
|
PutMercInAwakeState( pSoldier );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// If here, select the first guy...
|
|
if ( pFirstSoldier != NULL && !fSelectedSoldierInBatch )
|
|
{
|
|
SelectSoldier( pFirstSoldier->ubID, TRUE, TRUE );
|
|
}
|
|
|
|
}
|
|
|
|
|
|
void StopRubberBandedMercFromMoving( )
|
|
{
|
|
if ( !gTacticalStatus.fAtLeastOneGuyOnMultiSelect )
|
|
{
|
|
return;
|
|
}
|
|
SOLDIERTYPE * pSoldier;
|
|
INT32 cnt;
|
|
|
|
// OK, loop through all guys who are 'multi-selected' and
|
|
// check if our currently selected guy is amoung the
|
|
// lucky few.. if not, change to a guy who is...
|
|
cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
|
|
for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++, pSoldier++ )
|
|
{
|
|
if ( pSoldier->bActive && pSoldier->bInSector )
|
|
{
|
|
if ( pSoldier->flags.uiStatusFlags & SOLDIER_MULTI_SELECTED )
|
|
{
|
|
pSoldier->flags.fDelayedMovement = FALSE;
|
|
pSoldier->pathing.sFinalDestination = pSoldier->sGridNo;
|
|
pSoldier->StopSoldier( );
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
void EndRubberBanding( )
|
|
{
|
|
if ( gRubberBandActive )
|
|
{
|
|
FreeMouseCursor( );
|
|
gfIgnoreScrolling = FALSE;
|
|
|
|
EndMultiSoldierSelection( TRUE );
|
|
|
|
gRubberBandActive = FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
BOOLEAN HandleMultiSelectionMove( INT16 sDestGridNo )
|
|
{
|
|
SOLDIERTYPE * pSoldier;
|
|
INT32 cnt;
|
|
BOOLEAN fAtLeastOneMultiSelect = FALSE;
|
|
BOOLEAN fMoveFast = FALSE;
|
|
|
|
// OK, loop through all guys who are 'multi-selected' and
|
|
// Make them move....
|
|
|
|
// Do a loop first to see if the selected guy is told to go fast...
|
|
gfGetNewPathThroughPeople = TRUE;
|
|
|
|
cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
|
|
for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++, pSoldier++ )
|
|
{
|
|
if ( pSoldier->bActive && pSoldier->bInSector )
|
|
{
|
|
if ( pSoldier->flags.uiStatusFlags & SOLDIER_MULTI_SELECTED )
|
|
{
|
|
if ( pSoldier->ubID == gusSelectedSoldier )
|
|
{
|
|
fMoveFast = pSoldier->flags.fUIMovementFast;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
|
|
for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++, pSoldier++ )
|
|
{
|
|
if ( pSoldier->bActive && pSoldier->bInSector )
|
|
{
|
|
if ( pSoldier->flags.uiStatusFlags & SOLDIER_MULTI_SELECTED )
|
|
{
|
|
// If we can't be controlled, returninvalid...
|
|
if ( pSoldier->flags.uiStatusFlags & SOLDIER_ROBOT )
|
|
{
|
|
if ( !pSoldier->CanRobotBeControlled( ) )
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
|
|
pSoldier->flags.fUIMovementFast = fMoveFast;
|
|
pSoldier->usUIMovementMode = pSoldier->GetMoveStateBasedOnStance( gAnimControl[ pSoldier->usAnimState ].ubEndHeight );
|
|
|
|
pSoldier->flags.fUIMovementFast = FALSE;
|
|
|
|
if ( gUIUseReverse )
|
|
{
|
|
pSoldier->bReverse = TRUE;
|
|
}
|
|
else
|
|
{
|
|
pSoldier->bReverse = FALSE;
|
|
}
|
|
|
|
// Remove any previous actions
|
|
pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION;
|
|
|
|
|
|
if ( pSoldier->EVENT_InternalGetNewSoldierPath( sDestGridNo, pSoldier->usUIMovementMode , TRUE, pSoldier->flags.fNoAPToFinishMove ) )
|
|
{
|
|
pSoldier->InternalDoMercBattleSound( BATTLE_SOUND_OK1, BATTLE_SND_LOWER_VOLUME );
|
|
}
|
|
else
|
|
{
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, TacticalStr[ NO_PATH_FOR_MERC ], pSoldier->name );
|
|
}
|
|
|
|
fAtLeastOneMultiSelect = TRUE;
|
|
}
|
|
}
|
|
}
|
|
gfGetNewPathThroughPeople = FALSE;
|
|
|
|
return( fAtLeastOneMultiSelect );
|
|
}
|
|
|
|
|
|
void ResetMultiSelection( )
|
|
{
|
|
SOLDIERTYPE * pSoldier;
|
|
INT32 cnt;
|
|
|
|
// OK, loop through all guys who are 'multi-selected' and
|
|
// Make them move....
|
|
|
|
cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
|
|
for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++, pSoldier++ )
|
|
{
|
|
if ( pSoldier->bActive && pSoldier->bInSector )
|
|
{
|
|
if ( pSoldier->flags.uiStatusFlags & SOLDIER_MULTI_SELECTED )
|
|
{
|
|
pSoldier->flags.uiStatusFlags &= (~SOLDIER_MULTI_SELECTED );
|
|
}
|
|
}
|
|
}
|
|
|
|
gTacticalStatus.fAtLeastOneGuyOnMultiSelect = FALSE;
|
|
}
|
|
|
|
|
|
|
|
UINT32 UIHandleRubberBandOnTerrain( UI_EVENT *pUIEvent )
|
|
{
|
|
SOLDIERTYPE * pSoldier;
|
|
INT32 cnt;
|
|
INT16 sScreenX, sScreenY;
|
|
INT32 iTemp;
|
|
SGPRect aRect;
|
|
BOOLEAN fAtLeastOne = FALSE;
|
|
|
|
guiNewUICursor = NO_UICURSOR;
|
|
//SetCurrentCursorFromDatabase( VIDEO_NO_CURSOR );
|
|
|
|
gRubberBandRect.iRight = gusMouseXPos;
|
|
gRubberBandRect.iBottom = gusMouseYPos;
|
|
|
|
// Copy into temp rect
|
|
memcpy( &aRect, &gRubberBandRect, sizeof( gRubberBandRect ) );
|
|
|
|
if ( aRect.iRight < aRect.iLeft )
|
|
{
|
|
iTemp = aRect.iLeft;
|
|
aRect.iLeft = aRect.iRight;
|
|
aRect.iRight = iTemp;
|
|
}
|
|
|
|
|
|
if ( aRect.iBottom < aRect.iTop )
|
|
{
|
|
iTemp = aRect.iTop;
|
|
aRect.iTop = aRect.iBottom;
|
|
aRect.iBottom = iTemp;
|
|
}
|
|
|
|
// ATE:Check at least for one guy that's in point!
|
|
cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
|
|
for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++, pSoldier++ )
|
|
{
|
|
// Check if this guy is OK to control....
|
|
if ( OK_CONTROLLABLE_MERC( pSoldier ) && !( pSoldier->flags.uiStatusFlags & ( SOLDIER_VEHICLE | SOLDIER_PASSENGER | SOLDIER_DRIVER ) ) )
|
|
{
|
|
// Get screen pos of gridno......
|
|
GetGridNoScreenXY( pSoldier->sGridNo, &sScreenX, &sScreenY );
|
|
|
|
// ATE: If we are in a hiehger interface level, subttrasct....
|
|
if ( gsInterfaceLevel == 1 )
|
|
{
|
|
sScreenY -= 50;
|
|
}
|
|
|
|
if ( IsPointInScreenRect( sScreenX, sScreenY, &aRect ) )
|
|
{
|
|
fAtLeastOne = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( !fAtLeastOne )
|
|
{
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
// ATE: Now loop through our guys and see if any fit!
|
|
cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
|
|
for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++, pSoldier++ )
|
|
{
|
|
|
|
// Check if this guy is OK to control....
|
|
if ( OK_CONTROLLABLE_MERC( pSoldier ) && !( pSoldier->flags.uiStatusFlags & ( SOLDIER_VEHICLE | SOLDIER_PASSENGER | SOLDIER_DRIVER ) ) )
|
|
{
|
|
if ( !_KeyDown( ALT ) )
|
|
{
|
|
pSoldier->flags.uiStatusFlags &= (~SOLDIER_MULTI_SELECTED );
|
|
}
|
|
|
|
// Get screen pos of gridno......
|
|
GetGridNoScreenXY( pSoldier->sGridNo, &sScreenX, &sScreenY );
|
|
|
|
// ATE: If we are in a hiehger interface level, subttrasct....
|
|
if ( gsInterfaceLevel == 1 )
|
|
{
|
|
sScreenY -= 50;
|
|
}
|
|
|
|
if ( IsPointInScreenRect( sScreenX, sScreenY, &aRect ) )
|
|
{
|
|
// Adjust this guy's flag...
|
|
pSoldier->flags.uiStatusFlags |= SOLDIER_MULTI_SELECTED;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
|
|
UINT32 UIHandleJumpOverOnTerrain( UI_EVENT *pUIEvent )
|
|
{
|
|
SOLDIERTYPE *pSoldier;
|
|
INT16 sMapPos;
|
|
|
|
// Here, first get map screen
|
|
if ( !GetSoldier( &pSoldier, gusSelectedSoldier ) )
|
|
{
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
if (!GetMouseMapPos( &sMapPos ) )
|
|
{
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
if ( !IsValidJumpLocation( pSoldier, sMapPos, FALSE ) )
|
|
{
|
|
guiPendingOverrideEvent = M_ON_TERRAIN;
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
// Display APs....
|
|
gsCurrentActionPoints = GetAPsToJumpOver( pSoldier );
|
|
|
|
gfUIDisplayActionPoints = TRUE;
|
|
gfUIDisplayActionPointsCenter = TRUE;
|
|
|
|
guiNewUICursor = JUMP_OVER_UICURSOR;
|
|
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
|
|
UINT32 UIHandleJumpOver( UI_EVENT *pUIEvent )
|
|
{
|
|
SOLDIERTYPE *pSoldier;
|
|
INT16 sMapPos;
|
|
UINT8 ubDirection;
|
|
|
|
// Here, first get map screen
|
|
if ( !GetSoldier( &pSoldier, gusSelectedSoldier ) )
|
|
{
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
if (!GetMouseMapPos( &sMapPos ) )
|
|
{
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
if ( !IsValidJumpLocation( pSoldier, sMapPos, FALSE ) )
|
|
{
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
SetUIBusy( pSoldier->ubID );
|
|
|
|
// OK, Start jumping!
|
|
// Remove any previous actions
|
|
pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION;
|
|
|
|
// Get direction to goto....
|
|
ubDirection = GetDirectionFromGridNo( sMapPos, pSoldier );
|
|
|
|
|
|
pSoldier->flags.fDontChargeTurningAPs = TRUE;
|
|
pSoldier->EVENT_SetSoldierDesiredDirection(ubDirection);
|
|
pSoldier->flags.fTurningUntilDone = TRUE;
|
|
// ATE: Reset flag to go back to prone...
|
|
//pSoldier->flags.fTurningFromPronePosition = TURNING_FROM_PRONE_OFF;
|
|
pSoldier->usPendingAnimation = JUMP_OVER_BLOCKING_PERSON;
|
|
|
|
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
UINT32 UIHandleLABeginLockOurTurn( UI_EVENT *pUIEvent )
|
|
{
|
|
// Don't let both versions of the locks to happen at the same time!
|
|
// ( They are mutually exclusive )!
|
|
UIHandleLUIEndLock( NULL );
|
|
|
|
if ( !gfUserTurnRegionActive )
|
|
{
|
|
gfUserTurnRegionActive = TRUE;
|
|
|
|
gfUIInterfaceSetBusy = TRUE;
|
|
guiUIInterfaceBusyTime = GetJA2Clock( );
|
|
|
|
//guiNewUICursor = NO_UICURSOR;
|
|
//SetCurrentCursorFromDatabase( VIDEO_NO_CURSOR );
|
|
|
|
MSYS_DefineRegion( &gUserTurnRegion, 0, 0 ,SCREEN_WIDTH, SCREEN_HEIGHT, MSYS_PRIORITY_HIGHEST,
|
|
CURSOR_WAIT, MSYS_NO_CALLBACK, MSYS_NO_CALLBACK );
|
|
// Add region
|
|
MSYS_AddRegion( &gUserTurnRegion );
|
|
|
|
//guiPendingOverrideEvent = LOCKOURTURN_UI_MODE;
|
|
|
|
ErasePath( TRUE );
|
|
|
|
// Pause time!
|
|
PauseGame();
|
|
LockPauseState( 17 );
|
|
}
|
|
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
UINT32 UIHandleLAEndLockOurTurn( UI_EVENT *pUIEvent )
|
|
{
|
|
if ( gfUserTurnRegionActive )
|
|
{
|
|
gfUserTurnRegionActive = FALSE;
|
|
|
|
gfUIInterfaceSetBusy = FALSE;
|
|
|
|
// Add region
|
|
MSYS_RemoveRegion( &gUserTurnRegion );
|
|
RefreshMouseRegions( );
|
|
//SetCurrentCursorFromDatabase( guiCurrentUICursor );
|
|
|
|
gfPlotNewMovement = TRUE;
|
|
|
|
guiForceRefreshMousePositionCalculation = TRUE;
|
|
UIHandleMOnTerrain( NULL );
|
|
|
|
if ( gViewportRegion.uiFlags & MSYS_MOUSE_IN_AREA )
|
|
{
|
|
SetCurrentCursorFromDatabase( gUICursors[ guiNewUICursor ].usFreeCursorName );
|
|
}
|
|
guiPendingOverrideEvent = M_ON_TERRAIN;
|
|
HandleTacticalUI( );
|
|
|
|
TurnOffTeamsMuzzleFlashes( gbPlayerNum );
|
|
|
|
// UnPause time!
|
|
UnLockPauseState();
|
|
UnPauseGame();
|
|
}
|
|
|
|
return( GAME_SCREEN );
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN IsValidTalkableNPCFromMouse( UINT8 *pubSoldierID , BOOLEAN fGive, BOOLEAN fAllowMercs, BOOLEAN fCheckCollapsed )
|
|
{
|
|
// Check if there is a guy here to talk to!
|
|
if ( gfUIFullTargetFound )
|
|
{
|
|
*pubSoldierID = (UINT8)gusUIFullTargetID;
|
|
return( IsValidTalkableNPC( (UINT8)gusUIFullTargetID, fGive, fAllowMercs, fCheckCollapsed ) );
|
|
}
|
|
|
|
return( FALSE );
|
|
}
|
|
|
|
|
|
BOOLEAN IsValidTalkableNPC( UINT8 ubSoldierID, BOOLEAN fGive , BOOLEAN fAllowMercs, BOOLEAN fCheckCollapsed )
|
|
{
|
|
SOLDIERTYPE *pSoldier = MercPtrs[ ubSoldierID ];
|
|
BOOLEAN fValidGuy = FALSE;
|
|
|
|
|
|
if ( gusSelectedSoldier != NOBODY )
|
|
{
|
|
if ( AM_A_ROBOT( MercPtrs[ gusSelectedSoldier ] ) )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
}
|
|
|
|
// CHECK IF ACTIVE!
|
|
if ( !pSoldier->bActive )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
// CHECK IF DEAD
|
|
if( pSoldier->stats.bLife == 0 )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
if ( pSoldier->bCollapsed && fCheckCollapsed )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
if ( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
|
|
// IF BAD GUY - CHECK VISIVILITY
|
|
if ( pSoldier->bTeam != gbPlayerNum )
|
|
{
|
|
if ( pSoldier->bVisible == -1 && !(gTacticalStatus.uiFlags&SHOW_ALL_MERCS) )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
}
|
|
|
|
if ( pSoldier->ubProfile != NO_PROFILE && pSoldier->ubProfile >= FIRST_RPC && pSoldier->ubProfile < GASTON && !RPC_RECRUITED( pSoldier ) && !AM_AN_EPC( pSoldier ) )
|
|
{
|
|
fValidGuy = TRUE;
|
|
}
|
|
|
|
// Check for EPC...
|
|
if ( pSoldier->ubProfile != NO_PROFILE && ( gCurrentUIMode == TALKCURSOR_MODE || fGive ) && AM_AN_EPC( pSoldier ) )
|
|
{
|
|
fValidGuy = TRUE;
|
|
}
|
|
|
|
// ATE: We can talk to our own teammates....
|
|
if ( pSoldier->bTeam == gbPlayerNum && fAllowMercs )
|
|
{
|
|
fValidGuy = TRUE;
|
|
}
|
|
|
|
if ( GetCivType( pSoldier ) != CIV_TYPE_NA && !fGive )
|
|
{
|
|
fValidGuy = TRUE;
|
|
}
|
|
|
|
// Alright, let's do something special here for robot...
|
|
if ( pSoldier->flags.uiStatusFlags & SOLDIER_ROBOT )
|
|
{
|
|
if ( fValidGuy == TRUE && !fGive )
|
|
{
|
|
// Can't talk to robots!
|
|
fValidGuy = FALSE;
|
|
}
|
|
}
|
|
|
|
// OK, check if they are stationary or not....
|
|
// Do some checks common to all..
|
|
if ( fValidGuy )
|
|
{
|
|
if ( ( gAnimControl[ pSoldier->usAnimState ].uiFlags & ANIM_MOVING ) && !(gTacticalStatus.uiFlags & INCOMBAT ) )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
return( FALSE );
|
|
}
|
|
|
|
|
|
BOOLEAN HandleTalkInit( )
|
|
{
|
|
INT16 sAPCost;
|
|
SOLDIERTYPE *pSoldier, *pTSoldier;
|
|
UINT32 uiRange;
|
|
INT16 sMapPos;
|
|
INT16 sGoodGridNo;
|
|
UINT8 ubNewDirection;
|
|
UINT8 ubQuoteNum;
|
|
UINT8 ubDiceRoll;
|
|
INT16 sActionGridNo;
|
|
UINT8 ubDirection;
|
|
UINT8 commandRange; //lal
|
|
|
|
// Get soldier
|
|
if ( !GetSoldier( &pSoldier, gusSelectedSoldier ) )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
if (!GetMouseMapPos( &sMapPos ) )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
// Check if there is a guy here to talk to!
|
|
if ( gfUIFullTargetFound )
|
|
{
|
|
// Is he a valid NPC?
|
|
if ( IsValidTalkableNPC( (UINT8)gusUIFullTargetID, FALSE, TRUE , FALSE ) )
|
|
{
|
|
GetSoldier( &pTSoldier, gusUIFullTargetID );
|
|
|
|
if ( pTSoldier->ubID != pSoldier->ubID )
|
|
{
|
|
if ( !(( pTSoldier->bTeam == MILITIA_TEAM ) && ( CheckIfRadioIsEquipped() )) ) //lal
|
|
{
|
|
// Check LOS!
|
|
if ( !SoldierTo3DLocationLineOfSightTest( pSoldier, pTSoldier->sGridNo, pTSoldier->pathing.bLevel, 3, TRUE, CALC_FROM_ALL_DIRS ) )
|
|
{
|
|
if ( pTSoldier->ubProfile != NO_PROFILE )
|
|
{
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, TacticalStr[ NO_LOS_TO_TALK_TARGET ], pSoldier->name, pTSoldier->name );
|
|
}
|
|
else
|
|
{
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, gzLateLocalizedString[ 45 ], pSoldier->name );
|
|
}
|
|
return( FALSE );
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( pTSoldier->bCollapsed )
|
|
{
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, gzLateLocalizedString[ 21 ], pTSoldier->name );
|
|
return( FALSE );
|
|
}
|
|
|
|
// If Q on, turn off.....
|
|
if ( guiCurrentScreen == DEBUG_SCREEN )
|
|
{
|
|
gfExitDebugScreen = TRUE;
|
|
}
|
|
|
|
// ATE: if our own guy...
|
|
if ( pTSoldier->bTeam == gbPlayerNum && !AM_AN_EPC( pTSoldier ) )
|
|
{
|
|
if ( pTSoldier->ubProfile == DIMITRI )
|
|
{
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, gzLateLocalizedString[ 32 ], pTSoldier->name );
|
|
return( FALSE );
|
|
}
|
|
|
|
// Randomize quote to use....
|
|
|
|
// If buddy had a social trait...
|
|
if ( gMercProfiles[ pTSoldier->ubProfile ].bAttitude != ATT_NORMAL )
|
|
{
|
|
ubDiceRoll = (UINT8)Random( 3 );
|
|
}
|
|
else
|
|
{
|
|
ubDiceRoll = (UINT8)Random( 2 );
|
|
}
|
|
|
|
// If we are a PC, only use 0
|
|
if ( pTSoldier->ubWhatKindOfMercAmI == MERC_TYPE__PLAYER_CHARACTER )
|
|
{
|
|
ubDiceRoll = 0;
|
|
}
|
|
|
|
switch( ubDiceRoll )
|
|
{
|
|
case 0:
|
|
|
|
ubQuoteNum = QUOTE_NEGATIVE_COMPANY;
|
|
break;
|
|
|
|
case 1:
|
|
|
|
if ( QuoteExp_PassingDislike[ pTSoldier->ubProfile ] )
|
|
{
|
|
ubQuoteNum = QUOTE_PASSING_DISLIKE;
|
|
}
|
|
else
|
|
{
|
|
ubQuoteNum = QUOTE_NEGATIVE_COMPANY;
|
|
}
|
|
break;
|
|
|
|
case 2:
|
|
|
|
ubQuoteNum = QUOTE_SOCIAL_TRAIT;
|
|
break;
|
|
|
|
default:
|
|
|
|
ubQuoteNum = QUOTE_NEGATIVE_COMPANY;
|
|
break;
|
|
}
|
|
|
|
if ( pTSoldier->ubProfile == IRA )
|
|
{
|
|
ubQuoteNum = QUOTE_PASSING_DISLIKE;
|
|
}
|
|
|
|
TacticalCharacterDialogue( pTSoldier, ubQuoteNum );
|
|
|
|
return( FALSE );
|
|
}
|
|
|
|
// Check distance
|
|
uiRange = GetRangeFromGridNoDiff( pSoldier->sGridNo, sMapPos );
|
|
|
|
// Double check path
|
|
if ( GetCivType( pTSoldier ) != CIV_TYPE_NA )
|
|
{
|
|
// ATE: If one is already active, just remove it!
|
|
if ( ShutDownQuoteBoxIfActive( ) )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
}
|
|
|
|
//lal
|
|
if ( pTSoldier->bTeam == MILITIA_TEAM )
|
|
{
|
|
commandRange = NPC_TALK_RADIUS*3;
|
|
}
|
|
else
|
|
{
|
|
commandRange = NPC_TALK_RADIUS;
|
|
}
|
|
|
|
|
|
if ( ( uiRange > commandRange ) && ( !CheckIfRadioIsEquipped() ) ) //lal
|
|
{
|
|
if( (gTacticalStatus.uiFlags & TURNBASED) && (gTacticalStatus.uiFlags & INCOMBAT) )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
else
|
|
{
|
|
// First get an adjacent gridno....
|
|
sActionGridNo = FindAdjacentGridEx( pSoldier, pTSoldier->sGridNo, &ubDirection, NULL, FALSE, TRUE );
|
|
|
|
if ( sActionGridNo == -1 )
|
|
{
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, TacticalStr[ NO_PATH ] );
|
|
return( FALSE );
|
|
}
|
|
|
|
if ( UIPlotPath( pSoldier, sActionGridNo, NO_COPYROUTE, FALSE, TEMPORARY, (UINT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints ) == 0 )
|
|
{
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, TacticalStr[ NO_PATH ] );
|
|
return( FALSE );
|
|
}
|
|
|
|
// Walk up and talk to buddy....
|
|
gfNPCCircularDistLimit = TRUE;
|
|
sGoodGridNo = FindGridNoFromSweetSpotWithStructData( pSoldier, pSoldier->usUIMovementMode, pTSoldier->sGridNo, (NPC_TALK_RADIUS-1), &ubNewDirection, TRUE );
|
|
gfNPCCircularDistLimit = FALSE;
|
|
|
|
// First calculate APs and validate...
|
|
sAPCost = APBPConstants[AP_TALK];
|
|
//sAPCost += UIPlotPath( pSoldier, sGoodGridNo, NO_COPYROUTE, FALSE, TEMPORARY, (UINT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints );
|
|
|
|
// Check AP cost...
|
|
if ( !EnoughPoints( pSoldier, sAPCost, 0, TRUE ) )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
// Now walkup to talk....
|
|
pSoldier->aiData.ubPendingAction = MERC_TALK;
|
|
pSoldier->aiData.uiPendingActionData1 = pTSoldier->ubID;
|
|
pSoldier->aiData.ubPendingActionAnimCount = 0;
|
|
|
|
// WALK UP TO DEST FIRST
|
|
pSoldier->EVENT_InternalGetNewSoldierPath( sGoodGridNo, pSoldier->usUIMovementMode , TRUE , pSoldier->flags.fNoAPToFinishMove );
|
|
|
|
return( FALSE );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sAPCost = APBPConstants[AP_TALK];
|
|
|
|
// Check AP cost...
|
|
if ( !EnoughPoints( pSoldier, sAPCost, 0, TRUE ) )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
// OK, startup!
|
|
pSoldier->PlayerSoldierStartTalking( pTSoldier->ubID, FALSE );
|
|
}
|
|
|
|
if ( GetCivType( pTSoldier ) != CIV_TYPE_NA )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
else
|
|
{
|
|
return( TRUE );
|
|
}
|
|
}
|
|
}
|
|
|
|
return( FALSE );
|
|
}
|
|
|
|
|
|
|
|
void SetUIBusy( UINT8 ubID )
|
|
{
|
|
if ( (gTacticalStatus.uiFlags & INCOMBAT ) && ( gTacticalStatus.uiFlags & TURNBASED ) && ( gTacticalStatus.ubCurrentTeam == gbPlayerNum ) )
|
|
{
|
|
if ( gusSelectedSoldier == ubID )
|
|
{
|
|
guiPendingOverrideEvent = LA_BEGINUIOURTURNLOCK;
|
|
HandleTacticalUI( );
|
|
}
|
|
}
|
|
}
|
|
|
|
void UnSetUIBusy( UINT8 ubID )
|
|
{
|
|
if ( gfUserTurnRegionActive && (gTacticalStatus.uiFlags & INCOMBAT ) && ( gTacticalStatus.uiFlags & TURNBASED ) && ( gTacticalStatus.ubCurrentTeam == gbPlayerNum ) )
|
|
{
|
|
{
|
|
if ( !gTacticalStatus.fUnLockUIAfterHiddenInterrupt )
|
|
{
|
|
if ( gusSelectedSoldier == ubID && (gTacticalStatus.ubCurrentTeam == OUR_TEAM || !is_networked))// now that mp
|
|
{
|
|
guiPendingOverrideEvent = LA_ENDUIOUTURNLOCK;
|
|
HandleTacticalUI( );
|
|
|
|
// Set grace period...
|
|
gTacticalStatus.uiTactialTurnLimitClock = GetJA2Clock( );
|
|
}
|
|
}
|
|
// player getting control back so reset all muzzle flashes
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void BeginDisplayTimedCursor( UINT32 uiCursorID, UINT32 uiDelay )
|
|
{
|
|
gfDisplayTimerCursor = TRUE;
|
|
guiTimerCursorID = uiCursorID;
|
|
guiTimerLastUpdate = GetJA2Clock( );
|
|
guiTimerCursorDelay = uiDelay;
|
|
}
|
|
|
|
|
|
|
|
INT8 UIHandleInteractiveTilesAndItemsOnTerrain( SOLDIERTYPE *pSoldier, INT16 sMapPos, BOOLEAN fUseOKCursor, BOOLEAN fItemsOnlyIfOnIntTiles )
|
|
{
|
|
ITEM_POOL *pItemPool;
|
|
BOOLEAN fSetCursor;
|
|
UINT32 uiCursorFlags;
|
|
LEVELNODE *pIntTile;
|
|
static BOOLEAN fOverPool = FALSE;
|
|
static BOOLEAN fOverEnemy = FALSE;
|
|
INT16 sActionGridNo;
|
|
INT16 sIntTileGridNo;
|
|
BOOLEAN fContinue = TRUE;
|
|
STRUCTURE *pStructure = NULL;
|
|
BOOLEAN fPoolContainsHiddenItems = FALSE;
|
|
SOLDIERTYPE *pTSoldier;
|
|
|
|
|
|
if ( gfResetUIItemCursorOptimization )
|
|
{
|
|
gfResetUIItemCursorOptimization = FALSE;
|
|
fOverPool = FALSE;
|
|
fOverEnemy = FALSE;
|
|
}
|
|
|
|
GetCursorMovementFlags( &uiCursorFlags );
|
|
|
|
// Default gridno to mouse pos
|
|
sActionGridNo = sMapPos;
|
|
|
|
// Look for being on a merc....
|
|
// Steal.....
|
|
UIHandleOnMerc( FALSE );
|
|
|
|
gfBeginVehicleCursor = FALSE;
|
|
|
|
if ( gfUIFullTargetFound )
|
|
{
|
|
pTSoldier = MercPtrs[ gusUIFullTargetID ];
|
|
|
|
if ( OK_ENTERABLE_VEHICLE( pTSoldier ) && pTSoldier->bVisible != -1 )
|
|
{
|
|
// grab number of occupants in vehicles
|
|
if ( fItemsOnlyIfOnIntTiles )
|
|
{
|
|
if ( !OKUseVehicle( pTSoldier->ubProfile ) )
|
|
{
|
|
// Set UI CURSOR....
|
|
guiNewUICursor = CANNOT_MOVE_UICURSOR;
|
|
|
|
gfBeginVehicleCursor = TRUE;
|
|
return( 1 );
|
|
}
|
|
else
|
|
{
|
|
if ( GetNumberInVehicle( pTSoldier->bVehicleID ) == 0 )
|
|
{
|
|
// Set UI CURSOR....
|
|
guiNewUICursor = ENTER_VEHICLE_UICURSOR;
|
|
|
|
gfBeginVehicleCursor = TRUE;
|
|
return( 1 );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Set UI CURSOR....
|
|
guiNewUICursor = ENTER_VEHICLE_UICURSOR;
|
|
return( 1 );
|
|
}
|
|
}
|
|
|
|
if ( !fItemsOnlyIfOnIntTiles )
|
|
{
|
|
if ( ( guiUIFullTargetFlags & ENEMY_MERC ) && !( guiUIFullTargetFlags & UNCONSCIOUS_MERC ) )
|
|
{
|
|
if ( !fOverEnemy )
|
|
{
|
|
fOverEnemy = TRUE;
|
|
gfPlotNewMovement = TRUE;
|
|
}
|
|
|
|
//Set UI CURSOR
|
|
if ( fUseOKCursor || ( ( gTacticalStatus.uiFlags & INCOMBAT ) && ( gTacticalStatus.uiFlags & TURNBASED ) ) )
|
|
{
|
|
guiNewUICursor = OKHANDCURSOR_UICURSOR;
|
|
}
|
|
else
|
|
{
|
|
guiNewUICursor = NORMALHANDCURSOR_UICURSOR;
|
|
}
|
|
|
|
fSetCursor = HandleUIMovementCursor( pSoldier, uiCursorFlags, sActionGridNo, MOVEUI_TARGET_STEAL );
|
|
|
|
// Display action points
|
|
gfUIDisplayActionPoints = TRUE;
|
|
|
|
// Determine if we can afford!
|
|
if ( !EnoughPoints( pSoldier, gsCurrentActionPoints, 0, FALSE ) )
|
|
{
|
|
gfUIDisplayActionPointsInvalid = TRUE;
|
|
}
|
|
|
|
return( 0 );
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( fOverEnemy )
|
|
{
|
|
ErasePath( TRUE );
|
|
fOverEnemy = FALSE;
|
|
gfPlotNewMovement = TRUE;
|
|
}
|
|
|
|
// If we are over an interactive struct, adjust gridno to this....
|
|
pIntTile = ConditionalGetCurInteractiveTileGridNoAndStructure( &sIntTileGridNo , &pStructure, FALSE );
|
|
gpInvTileThatCausedMoveConfirm = pIntTile;
|
|
|
|
if ( pIntTile != NULL )
|
|
{
|
|
sActionGridNo = sIntTileGridNo;
|
|
}
|
|
|
|
// Check if we are over an item pool
|
|
if ( GetItemPool( sActionGridNo, &pItemPool, pSoldier->pathing.bLevel ) )
|
|
{
|
|
// If we want only on int tiles, and we have no int tiles.. ignore items!
|
|
if ( fItemsOnlyIfOnIntTiles && pIntTile == NULL )
|
|
{
|
|
|
|
}
|
|
else if ( fItemsOnlyIfOnIntTiles && pIntTile != NULL && ( pStructure->fFlags & STRUCTURE_HASITEMONTOP ) )
|
|
{
|
|
// if in this mode, we don't want to automatically show hand cursor over items on strucutres
|
|
}
|
|
//else if ( pIntTile != NULL && ( pStructure->fFlags & ( STRUCTURE_SWITCH | STRUCTURE_ANYDOOR ) ) )
|
|
else if ( pIntTile != NULL && ( pStructure->fFlags & ( STRUCTURE_SWITCH ) ) )
|
|
{
|
|
// We don't want switches messing around with items ever!
|
|
}
|
|
else if ( ( pIntTile != NULL && ( pStructure->fFlags & ( STRUCTURE_ANYDOOR ) ) ) && ( sActionGridNo != sMapPos || fItemsOnlyIfOnIntTiles ) )
|
|
{
|
|
// Next we look for if we are over a door and if the mouse position is != base door position, ignore items!
|
|
}
|
|
else
|
|
{
|
|
fPoolContainsHiddenItems = DoesItemPoolContainAnyHiddenItems( pItemPool );
|
|
|
|
// Adjust this if we have not visited this gridno yet...
|
|
if ( fPoolContainsHiddenItems )
|
|
{
|
|
if ( !( gpWorldLevelData[ sActionGridNo ].uiFlags & MAPELEMENT_REVEALED ) )
|
|
{
|
|
fPoolContainsHiddenItems = FALSE;
|
|
}
|
|
}
|
|
|
|
if ( ITEMPOOL_VISIBLE( pItemPool ) || fPoolContainsHiddenItems )
|
|
{
|
|
|
|
if ( !fOverPool )
|
|
{
|
|
fOverPool = TRUE;
|
|
gfPlotNewMovement = TRUE;
|
|
}
|
|
|
|
//Set UI CURSOR
|
|
if ( fUseOKCursor || ( ( gTacticalStatus.uiFlags & INCOMBAT ) && ( gTacticalStatus.uiFlags & TURNBASED ) ) )
|
|
{
|
|
guiNewUICursor = OKHANDCURSOR_UICURSOR;
|
|
}
|
|
else
|
|
{
|
|
guiNewUICursor = NORMALHANDCURSOR_UICURSOR;
|
|
}
|
|
|
|
fSetCursor = HandleUIMovementCursor( pSoldier, uiCursorFlags, sActionGridNo, MOVEUI_TARGET_ITEMS );
|
|
|
|
// Display action points
|
|
gfUIDisplayActionPoints = TRUE;
|
|
|
|
if ( gsOverItemsGridNo == sActionGridNo )
|
|
{
|
|
gfPlotNewMovement = TRUE;
|
|
}
|
|
|
|
// Determine if we can afford!
|
|
if ( !EnoughPoints( pSoldier, gsCurrentActionPoints, 0, FALSE ) )
|
|
{
|
|
gfUIDisplayActionPointsInvalid = TRUE;
|
|
}
|
|
|
|
fContinue = FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( fContinue )
|
|
{
|
|
// Try interactive tiles now....
|
|
if ( pIntTile != NULL )
|
|
{
|
|
if ( fOverPool )
|
|
{
|
|
ErasePath( TRUE );
|
|
fOverPool = FALSE;
|
|
gfPlotNewMovement = TRUE;
|
|
}
|
|
|
|
HandleUIMovementCursor( pSoldier, uiCursorFlags, sMapPos, MOVEUI_TARGET_INTTILES );
|
|
|
|
//Set UI CURSOR
|
|
guiNewUICursor = GetInteractiveTileCursor( guiNewUICursor, fUseOKCursor );
|
|
}
|
|
else
|
|
{
|
|
if ( !fItemsOnlyIfOnIntTiles )
|
|
{
|
|
// Let's at least show where the merc will walk to if they go here...
|
|
if ( !fOverPool )
|
|
{
|
|
fOverPool = TRUE;
|
|
gfPlotNewMovement = TRUE;
|
|
}
|
|
|
|
fSetCursor = HandleUIMovementCursor( pSoldier, uiCursorFlags, sActionGridNo, MOVEUI_TARGET_ITEMS );
|
|
|
|
// Display action points
|
|
gfUIDisplayActionPoints = TRUE;
|
|
|
|
// Determine if we can afford!
|
|
if ( !EnoughPoints( pSoldier, gsCurrentActionPoints, 0, FALSE ) )
|
|
{
|
|
gfUIDisplayActionPointsInvalid = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
if ( pIntTile == NULL )
|
|
{
|
|
return( 0 );
|
|
}
|
|
else
|
|
{
|
|
return( 1 );
|
|
}
|
|
}
|
|
|
|
|
|
void HandleTacticalUILoseCursorFromOtherScreen( )
|
|
{
|
|
SetUICursor( 0 );
|
|
|
|
gfTacticalForceNoCursor = TRUE;
|
|
|
|
ErasePath( TRUE );
|
|
|
|
(*(GameScreens[GAME_SCREEN].HandleScreen))();
|
|
|
|
gfTacticalForceNoCursor = FALSE;
|
|
|
|
SetUICursor( guiCurrentUICursor );
|
|
}
|
|
|
|
|
|
BOOLEAN SelectedGuyInBusyAnimation( )
|
|
{
|
|
SOLDIERTYPE *pSoldier;
|
|
|
|
if ( gusSelectedSoldier != NOBODY )
|
|
{
|
|
pSoldier = MercPtrs[ gusSelectedSoldier ];
|
|
|
|
if ( pSoldier->usAnimState == LOB_ITEM ||
|
|
pSoldier->usAnimState == THROW_ITEM ||
|
|
//<SB> crouch throwing
|
|
pSoldier->usAnimState == THROW_ITEM_CROUCHED ||
|
|
//<SB> crouch throwing
|
|
pSoldier->usAnimState == PICKUP_ITEM ||
|
|
pSoldier->usAnimState == DROP_ITEM ||
|
|
pSoldier->usAnimState == OPEN_DOOR ||
|
|
pSoldier->usAnimState == OPEN_STRUCT ||
|
|
pSoldier->usAnimState == OPEN_STRUCT ||
|
|
pSoldier->usAnimState == END_OPEN_DOOR ||
|
|
pSoldier->usAnimState == END_OPEN_LOCKED_DOOR ||
|
|
pSoldier->usAnimState == ADJACENT_GET_ITEM ||
|
|
pSoldier->usAnimState == DROP_ADJACENT_OBJECT ||
|
|
|
|
pSoldier->usAnimState == OPEN_DOOR_CROUCHED ||
|
|
pSoldier->usAnimState == BEGIN_OPENSTRUCT_CROUCHED ||
|
|
pSoldier->usAnimState == CLOSE_DOOR_CROUCHED ||
|
|
pSoldier->usAnimState == OPEN_DOOR_CROUCHED ||
|
|
pSoldier->usAnimState == OPEN_STRUCT_CROUCHED ||
|
|
pSoldier->usAnimState == END_OPENSTRUCT_CROUCHED ||
|
|
pSoldier->usAnimState == END_OPEN_DOOR_CROUCHED ||
|
|
pSoldier->usAnimState == END_OPEN_LOCKED_DOOR_CROUCHED ||
|
|
pSoldier->usAnimState == END_OPENSTRUCT_LOCKED_CROUCHED ||
|
|
pSoldier->usAnimState == BEGIN_OPENSTRUCT )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
}
|
|
|
|
return( FALSE );
|
|
}
|
|
|
|
void GotoHeigherStance( SOLDIERTYPE *pSoldier )
|
|
{
|
|
BOOLEAN fNearHeigherLevel;
|
|
BOOLEAN fNearLowerLevel;
|
|
|
|
switch( gAnimControl[ pSoldier->usAnimState ].ubEndHeight )
|
|
{
|
|
case ANIM_STAND:
|
|
|
|
// Nowhere
|
|
// Try to climb
|
|
GetMercClimbDirection( pSoldier->ubID, &fNearLowerLevel, &fNearHeigherLevel );
|
|
|
|
if ( fNearHeigherLevel )
|
|
{
|
|
pSoldier->BeginSoldierClimbUpRoof( );
|
|
}
|
|
break;
|
|
|
|
case ANIM_CROUCH:
|
|
|
|
HandleStanceChangeFromUIKeys( ANIM_STAND );
|
|
break;
|
|
|
|
case ANIM_PRONE:
|
|
|
|
HandleStanceChangeFromUIKeys( ANIM_CROUCH );
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
void GotoLowerStance( SOLDIERTYPE *pSoldier )
|
|
{
|
|
BOOLEAN fNearHeigherLevel;
|
|
BOOLEAN fNearLowerLevel;
|
|
|
|
|
|
switch( gAnimControl[ pSoldier->usAnimState ].ubEndHeight )
|
|
{
|
|
case ANIM_STAND:
|
|
|
|
HandleStanceChangeFromUIKeys( ANIM_CROUCH );
|
|
break;
|
|
|
|
case ANIM_CROUCH:
|
|
|
|
HandleStanceChangeFromUIKeys( ANIM_PRONE );
|
|
break;
|
|
|
|
case ANIM_PRONE:
|
|
|
|
// Nowhere
|
|
// Try to climb
|
|
GetMercClimbDirection( pSoldier->ubID, &fNearLowerLevel, &fNearHeigherLevel );
|
|
|
|
if ( fNearLowerLevel )
|
|
{
|
|
pSoldier->BeginSoldierClimbDownRoof( );
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void SetInterfaceHeightLevel( )
|
|
{
|
|
INT16 sHeight;
|
|
static INT16 sOldHeight = 0;
|
|
INT16 sGridNo;
|
|
|
|
if( gfBasement || gfCaves )
|
|
{
|
|
gsRenderHeight = 0;
|
|
sOldHeight = 0;
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
// ATE: Use an entry point to determine what height to use....
|
|
if( gMapInformation.sNorthGridNo != -1 )
|
|
sGridNo = gMapInformation.sNorthGridNo;
|
|
else if( gMapInformation.sEastGridNo != -1 )
|
|
sGridNo = gMapInformation.sEastGridNo;
|
|
else if( gMapInformation.sSouthGridNo != -1 )
|
|
sGridNo = gMapInformation.sSouthGridNo;
|
|
else if( gMapInformation.sWestGridNo != -1 )
|
|
sGridNo = gMapInformation.sWestGridNo;
|
|
else
|
|
{
|
|
Assert(0);
|
|
return;
|
|
}
|
|
|
|
|
|
sHeight = gpWorldLevelData[ sGridNo ].sHeight;
|
|
|
|
if ( sHeight != sOldHeight )
|
|
{
|
|
gsRenderHeight = sHeight;
|
|
|
|
if ( gsInterfaceLevel > 0 )
|
|
{
|
|
gsRenderHeight += ROOF_LEVEL_HEIGHT;
|
|
}
|
|
|
|
SetRenderFlags(RENDER_FLAG_FULL);
|
|
ErasePath(FALSE);
|
|
|
|
sOldHeight = sHeight;
|
|
}
|
|
}
|
|
|
|
BOOLEAN ValidQuickExchangePosition( )
|
|
{
|
|
SOLDIERTYPE *pSoldier, *pOverSoldier;
|
|
BOOLEAN fOnValidGuy = FALSE;
|
|
static BOOLEAN fOldOnValidGuy = FALSE;
|
|
|
|
// Check if we over a civ
|
|
if ( gfUIFullTargetFound )
|
|
{
|
|
pOverSoldier = MercPtrs[ gusUIFullTargetID ];
|
|
|
|
//KM: Replaced this older if statement for the new one which allows exchanging with militia
|
|
//if ( ( pOverSoldier->bSide != gbPlayerNum ) && pOverSoldier->aiData.bNeutral )
|
|
if ( ( pOverSoldier->bTeam != gbPlayerNum && pOverSoldier->aiData.bNeutral ) || (pOverSoldier->bTeam == MILITIA_TEAM && pOverSoldier->bSide == 0 ) )
|
|
{
|
|
// hehe - don't allow animals to exchange places
|
|
if ( !( pOverSoldier->flags.uiStatusFlags & ( SOLDIER_ANIMAL ) ) )
|
|
{
|
|
// OK, we have a civ , now check if they are near selected guy.....
|
|
if ( GetSoldier( &pSoldier, gusSelectedSoldier ) )
|
|
{
|
|
if ( PythSpacesAway( pSoldier->sGridNo, pOverSoldier->sGridNo ) == 1 )
|
|
{
|
|
// Check if we have LOS to them....
|
|
if ( SoldierTo3DLocationLineOfSightTest( pSoldier, pOverSoldier->sGridNo, pOverSoldier->pathing.bLevel, 3, TRUE, CALC_FROM_ALL_DIRS ) )
|
|
{
|
|
// ATE:
|
|
// Check that the path is good!
|
|
if ( FindBestPath( pSoldier, pOverSoldier->sGridNo, pSoldier->pathing.bLevel, pSoldier->usUIMovementMode, NO_COPYROUTE, PATH_IGNORE_PERSON_AT_DEST ) == 1 )
|
|
{
|
|
fOnValidGuy = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( fOldOnValidGuy != fOnValidGuy )
|
|
{
|
|
// Update timer....
|
|
// ATE: Adjust clock for automatic swapping so that the 'feel' is there....
|
|
guiUIInterfaceSwapCursorsTime = GetJA2Clock( );
|
|
// Default it!
|
|
gfOKForExchangeCursor = TRUE;
|
|
}
|
|
|
|
// Update old value.....
|
|
fOldOnValidGuy = fOnValidGuy;
|
|
|
|
if ( !gfOKForExchangeCursor )
|
|
{
|
|
fOnValidGuy = FALSE;
|
|
}
|
|
|
|
return( fOnValidGuy );
|
|
}
|
|
|
|
|
|
// This function contains the logic for allowing the player
|
|
// to jump over people.
|
|
BOOLEAN IsValidJumpLocation( SOLDIERTYPE *pSoldier, INT16 sGridNo, BOOLEAN fCheckForPath )
|
|
{
|
|
INT16 sFourGrids[4], sSpot, sIntSpot;
|
|
static const UINT8 sDirs[4] = { NORTH, EAST, SOUTH, WEST };
|
|
//INT32 cnt;
|
|
UINT8 ubGuyThere;
|
|
UINT8 ubMovementCost;
|
|
INT32 iDoorGridNo;
|
|
|
|
// First check that action point cost is zero so far
|
|
// ie: NO PATH!
|
|
if ( gsCurrentActionPoints != 0 && fCheckForPath )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
// Loop through positions...
|
|
for (INT8 cnt = 0; cnt < 4; cnt++)
|
|
{
|
|
// MOVE OUT TWO DIRECTIONS
|
|
sIntSpot = NewGridNo( sGridNo, DirectionInc( sDirs[ cnt ] ) );
|
|
|
|
// ATE: Check our movement costs for going through walls!
|
|
ubMovementCost = gubWorldMovementCosts[ sIntSpot ][ sDirs[ cnt ] ][ pSoldier->pathing.bLevel ];
|
|
if ( IS_TRAVELCOST_DOOR( ubMovementCost ) )
|
|
{
|
|
ubMovementCost = DoorTravelCost( pSoldier, sIntSpot, ubMovementCost, (BOOLEAN) (pSoldier->bTeam == gbPlayerNum), &iDoorGridNo );
|
|
}
|
|
|
|
// If we have hit an obstacle, STOP HERE
|
|
if ( ubMovementCost >= TRAVELCOST_BLOCKED )
|
|
{
|
|
// no good, continue
|
|
continue;
|
|
}
|
|
|
|
|
|
// TWICE AS FAR!
|
|
sFourGrids[cnt] = sSpot = NewGridNo( sIntSpot, DirectionInc( sDirs[ cnt ] ) );
|
|
|
|
// Is the soldier we're looking at here?
|
|
ubGuyThere = WhoIsThere2( sSpot, pSoldier->pathing.bLevel );
|
|
|
|
// Alright folks, here we are!
|
|
if ( ubGuyThere == pSoldier->ubID )
|
|
{
|
|
// Double check OK destination......
|
|
if ( NewOKDestination( pSoldier, sGridNo, TRUE, (INT8)gsInterfaceLevel ) )
|
|
{
|
|
// If the soldier in the middle of doing stuff?
|
|
if ( !pSoldier->flags.fTurningUntilDone )
|
|
{
|
|
// OK, NOW check if there is a guy in between us
|
|
//
|
|
//
|
|
ubGuyThere = WhoIsThere2( sIntSpot, pSoldier->pathing.bLevel );
|
|
|
|
// Is there a guy and is he prone?
|
|
if ( ubGuyThere != NOBODY && ubGuyThere != pSoldier->ubID && gAnimControl[ MercPtrs[ ubGuyThere ]->usAnimState ].ubHeight == ANIM_PRONE )
|
|
{
|
|
// It's a GO!
|
|
return( TRUE );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return( FALSE );
|
|
}
|