Files
source/Tactical/Handle UI.cpp
T
Overhaul dd0d6ea66d Fixed appearance of save game corruption when a game with different inventory set is loaded. Note that such games can still cause odd behavior and CTD's
Fixed old-style behavior when creating a soldier struct (caused memory corruption and leaks)
Fixed soldiers unable to fire if an error happened while firing the off-hand weapon
Fix animation system problems with soldiers interrupted while changing stance, such as twitching and not being able to navigate around obstacles
Prevent splitting money while an item is in the hand, which would result in losing the original item
Fix reverse of X,Y when checking visibility through a roof, which could make soldiers falsely visible/invisible
Prevent militia from simply waiting on the border when enemies are known to be in the sector
Fix stack overflow for soldier inventory debug display
Optimized A* pathing and cleaned up VS2K5 specific code
AI can now use all climb points for climbable buildings, not just a random few
Fix to not allow flat roof butted against slanted roof to be identified as a climb point
Prevent soldiers who cause an interrupt from a special action from continuing on their path after being interrupted
Prevent soldiers who enter or leave deep water from moving a space too far and turning back
Prevent soldiers from trying to crouch while in shallow water
Make soldier turn in the closest direction when he must get up from prone and turn then fall back to prone
Allow a soldier to swat for a tile before returning to prone if unable to return to prone immediately after a turn
Fix civilians that should show up in a sector, missing because of others that aren't
Fix a memset on a C++ class
Place Skyrider in a sector near his helecopter once available and the helicopter is present
Fix soldier corruption if too many shots burst-spread into too few tiles
Include both first and last tile in spread when some locations must be skipped
Fix to shoot at last location in burst
Fix to remove other previous spread locations when calculating a new spread
Fix to reload or rechamber off-hand when necessary, such as having a pistol shotgun in that hand


git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@1532 3b4a5df2-a311-0410-b5c6-a8a6f20db521
2007-10-20 08:09:03 +00:00

6392 lines
159 KiB
C++

#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
//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;
UINT8 gbCtH;
UINT8 gsTotalBulletCount;
UINT8 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, UINT16 usMapPos, UINT32 uiFlags );
INT8 UIHandleInteractiveTilesAndItemsOnTerrain( SOLDIERTYPE *pSoldier, INT16 usMapPos, 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;
UINT16 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;
UINT16 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;
UINT16 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;
UINT16 usMapPos;
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;
// 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( &usMapPos ) )
{
// Look for soldier full
if ( FindSoldier( usMapPos, &gusUIFullTargetID, &guiUIFullTargetFlags, ( FINDSOLDIERSAMELEVEL( gsInterfaceLevel ) ) ) )
{
gfUIFullTargetFound = TRUE;
}
// Look for soldier selective
if ( FindSoldier( usMapPos, &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 )
{
UINT16 usMapPos;
UINT8 ubRoomNum;
gfUIDisplayActionPoints = FALSE;
ErasePath( TRUE );
if( GetMouseMapPos( &usMapPos) )
{
if ( gusSelectedSoldier != NOBODY && MercPtrs[ gusSelectedSoldier ]->bLevel == 0 )
{
// ATE: Is this place revealed?
if ( !InARoom( usMapPos, &ubRoomNum ) || ( InARoom( usMapPos, &ubRoomNum ) && gpWorldLevelData[ usMapPos ].uiFlags & MAPELEMENT_REVEALED ) )
{
if ( sOldExitGridNo != usMapPos )
{
fOkForExit = OKForSectorExit( (INT8)-1, usMapPos, &uiTraverseTimeInMinutes );
sOldExitGridNo = usMapPos;
}
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;
UINT16 usMapPos;
static INT32 iSoldierCount=0;
MERC_HIRE_STRUCT HireMercStruct;
INT8 bReturnCode;
SOLDIERTYPE *pSoldier;
// Get Grid Corrdinates of mouse
if( GetMouseMapPos( &usMapPos) )
{
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 = usMapPos;
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." );
}
else if( bReturnCode == MERC_HIRE_OVER_18_MERCS_HIRED )
{
ScreenMsg( FONT_ORANGE, MSG_BETAVERSION, L"Can't hire more than 18 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;
UINT16 usMapPos;
UINT16 usRandom;
//Get map postion and place the enemy there.
if( GetMouseMapPos( &usMapPos) )
{
// Are we an OK dest?
if ( !IsLocationSittable( usMapPos, 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 = usMapPos;
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!
EndTurn( gbPlayerNum + 1 );
}
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" );
EVENT_SoldierGotHit( pSoldier, 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;
UINT16 usMapPos;
BOOLEAN fSetCursor = FALSE;
UINT32 uiCursorFlags;
LEVELNODE *pIntNode;
EXITGRID ExitGrid;
INT16 sIntTileGridNo;
BOOLEAN fContinue = TRUE;
ITEM_POOL *pItemPool;
static INT16 sGridNoForItemsOver;
static INT8 bLevelForItemsOver;
static UINT32 uiItemsOverTimer;
static BOOLEAN fOverItems;
if( !GetMouseMapPos( &usMapPos) )
{
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( usMapPos, &pItemPool, (UINT8)gsInterfaceLevel ) && ITEMPOOL_VISIBLE( pItemPool ) )
{
// Are we already in...
if ( fOverItems )
{
// Is this the same level & gridno...
if ( gsInterfaceLevel == (INT16)bLevelForItemsOver && usMapPos == sGridNoForItemsOver )
{
// Check timer...
if ( ( GetJA2Clock( ) - uiItemsOverTimer ) > 1500 )
{
// Change to hand curso mode
guiPendingOverrideEvent = M_CHANGE_TO_HANDMODE;
gsOverItemsGridNo = usMapPos;
gsOverItemsLevel = gsInterfaceLevel;
fOverItems = FALSE;
}
}
else
{
uiItemsOverTimer = GetJA2Clock( );
bLevelForItemsOver = (INT8)gsInterfaceLevel;
sGridNoForItemsOver = usMapPos;
}
}
else
{
fOverItems = TRUE;
uiItemsOverTimer = GetJA2Clock( );
bLevelForItemsOver = (INT8)gsInterfaceLevel;
sGridNoForItemsOver = usMapPos;
}
}
else
{
fOverItems = FALSE;
}
if ( GetSoldier( &pSoldier, gusSelectedSoldier ) )
{
if ( pSoldier->sGridNo == NOWHERE )
{
int i = 0;
}
if ( GetExitGrid( usMapPos, &ExitGrid ) && pSoldier->bLevel == 0 )
{
gfUIShowExitExitGrid = TRUE;
}
// ATE: Draw invalidc cursor if heights different
if ( gpWorldLevelData[ usMapPos ].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->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, usMapPos ) != 1 ) && pIntNode == NULL )
{
// ERASE PATH
ErasePath( TRUE );
guiNewUICursor = CANNOT_MOVE_UICURSOR;
}
else
{
if ( !UIHandleInteractiveTilesAndItemsOnTerrain( pSoldier, usMapPos, FALSE, TRUE ) )
{
// Are we in combat?
if ( (gTacticalStatus.uiFlags & INCOMBAT ) && ( gTacticalStatus.uiFlags & TURNBASED ) )
{
// If so, draw path, etc
fSetCursor = HandleUIMovementCursor( pSoldier, uiCursorFlags, usMapPos, 0 );
}
else
{
// Donot draw path until confirm
fSetCursor = TRUE;
// If so, draw path, etc
fSetCursor = HandleUIMovementCursor( pSoldier, uiCursorFlags, usMapPos, 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->fUIMovementFast = 1;
}
else
{
pSoldier->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 usMapPos;
SOLDIERTYPE *pSoldier;
// INT16 sTargetXPos, sTargetYPos;
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("UIHandleAOnTerrain"));
if( !GetMouseMapPos( &usMapPos) )
{
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, usMapPos ) )
{
// 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, usMapPos, 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->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( usMapPos, &sTargetXPos, &sTargetYPos );
// Ready weapon
// SoldierReadyWeapon( pSoldier, 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 )
{
UINT16 usMapPos;
SOLDIERTYPE *pSoldier;
BOOLEAN fSetCursor;
UINT32 uiCursorFlags;
LEVELNODE *pInvTile;
if( !GetMouseMapPos( &usMapPos) )
{
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, usMapPos, 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, usMapPos, 0 );
fSetCursor = HandleUIMovementCursor( pSoldier, uiCursorFlags, usMapPos, 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 )
{
UINT16 usMapPos;
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( &usMapPos) )
{
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->fMercAsleep )
{
// If we can't be controlled, returninvalid...
if ( pSoldier->uiStatusFlags & SOLDIER_ROBOT )
{
if ( !CanRobotBeControlled( pSoldier ) )
{
continue;
}
}
AdjustNoAPToFinishMove( pSoldier, FALSE );
fOldFastMove = pSoldier->fUIMovementFast;
if ( fAllMove == 2 )
{
pSoldier->fUIMovementFast = TRUE;
pSoldier->usUIMovementMode = RUNNING;
}
else
{
pSoldier->fUIMovementFast = FALSE;
pSoldier->usUIMovementMode = GetMoveStateBasedOnStance( pSoldier, gAnimControl[ pSoldier->usAnimState ].ubEndHeight );
}
// Remove any previous actions
pSoldier->ubPendingAction = NO_PENDING_ACTION;
//if ( !( gTacticalStatus.uiFlags & INCOMBAT ) && ( gAnimControl[ pSoldier->usAnimState ].uiFlags & ANIM_MOVING ) )
//{
// pSoldier->sRTPendingMovementGridNo = usMapPos;
// pSoldier->usRTPendingMovementAnim = pSoldier->usUIMovementMode;
//}
//else
if ( EVENT_InternalGetNewSoldierPath( pSoldier, usMapPos, pSoldier->usUIMovementMode, TRUE, FALSE ) )
{
InternalDoMercBattleSound( pSoldier, BATTLE_SOUND_OK1, BATTLE_SND_LOWER_VOLUME );
}
else
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, TacticalStr[ NO_PATH_FOR_MERC ], pSoldier->name );
}
pSoldier->fUIMovementFast = fOldFastMove;
}
}
gfGetNewPathThroughPeople = FALSE;
// RESET MOVE FAST FLAG
SetConfirmMovementModeCursor( pSoldier, TRUE );
gfUIAllMoveOn = 0;
}
else
{
// Get soldier
if ( GetSoldier( &pSoldier, gusSelectedSoldier ) )
{
// FOR REALTIME - DO MOVEMENT BASED ON STANCE!
if ( ( gTacticalStatus.uiFlags & REALTIME ) || !( gTacticalStatus.uiFlags & INCOMBAT ) )
{
pSoldier->usUIMovementMode = GetMoveStateBasedOnStance( pSoldier, gAnimControl[ pSoldier->usAnimState ].ubEndHeight );
}
sDestGridNo = usMapPos;
// 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->fUIMovementFast = FALSE;
}
//StartLooseCursor( usMapPos, 0 );
}
if ( gTacticalStatus.fAtLeastOneGuyOnMultiSelect && pIntTile == NULL )
{
HandleMultiSelectionMove( sDestGridNo );
}
else
{
if ( gUIUseReverse )
{
pSoldier->bReverse = TRUE;
}
else
{
pSoldier->bReverse = FALSE;
}
// Remove any previous actions
pSoldier->ubPendingAction = NO_PENDING_ACTION;
{
EVENT_InternalGetNewSoldierPath( pSoldier, sDestGridNo, pSoldier->usUIMovementMode , TRUE, pSoldier->fNoAPToFinishMove );
}
if ( pSoldier->usPathDataSize > 5 )
{
DoMercBattleSound( pSoldier, 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->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;
BOOLEAN fCheck = FALSE;
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->bLevel == 0 )
{
if ( FindHeigherLevel( pSoldier, pSoldier->sGridNo, pSoldier->ubDirection, &bNewDirection ) )
{
ubNearHeigherLevel = TRUE;
}
}
// IF we are higher...
if ( pSoldier->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;
UINT16 usMapPos;
if( !GetMouseMapPos( &usMapPos) )
{
return( GAME_SCREEN );
}
if ( GetSoldier( &pSoldier, gusSelectedSoldier ) )
{
guiNewUICursor = GetProperItemCursor( (UINT8)gusSelectedSoldier, pSoldier->inv[ HANDPOS ].usItem, usMapPos, TRUE );
UIHandleOnMerc( FALSE );
}
return( GAME_SCREEN );
}
void UIHandleMercAttack( SOLDIERTYPE *pSoldier , SOLDIERTYPE *pTargetSoldier, UINT16 usMapPos )
{
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->bAimTime = (pSoldier->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->bLevel;
}
else
{
sTargetGridNo = usMapPos;
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->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 )
{
UINT16 usMapPos;
SOLDIERTYPE *pSoldier, *pTSoldier = NULL;
BOOLEAN fDidRequester = FALSE;
if ( gusSelectedSoldier != NOBODY )
{
if( !GetMouseMapPos( &usMapPos) )
{
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 = usMapPos;
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, usMapPos );
}
}
}
return( GAME_SCREEN );
}
UINT32 UIHandleAEndAction( UI_EVENT *pUIEvent )
{
SOLDIERTYPE *pSoldier;
INT16 sTargetXPos, sTargetYPos;
UINT16 usMapPos;
// Get gridno at this location
if( !GetMouseMapPos( &usMapPos) )
{
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( usMapPos, &sTargetXPos, &sTargetYPos );
// UNReady weapon
SoldierReadyWeapon( pSoldier, 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 )
{
UINT16 usMapPos;
// Get gridno at this location
if( !GetMouseMapPos( &usMapPos) )
{
return( GAME_SCREEN );
}
if ( !UIHandleOnMerc( TRUE ) )
{
// Check if dest is OK
//if ( !NewOKDestination( usMapPos, FALSE ) || IsRoofVisible( usMapPos ) )
////{
// 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;
BOOLEAN fChangeStance = FALSE;
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 )
{
BeginSoldierClimbUpRoof( pSoldier );
}
else if ( gbClimbID == -1 )
{
BeginSoldierClimbDownRoof( pSoldier );
}
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;
UINT16 usMapPos;
if( !GetMouseMapPos( &usMapPos) )
{
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;
UINT16 usMapPos;
INT16 sTargetGridNo;
BOOLEAN fEnoughPoints = TRUE;
INT16 sAPCost;
UINT8 ubItemCursor;
UINT16 usInHand;
if ( gusSelectedSoldier != NOBODY )
{
if( !GetMouseMapPos( &usMapPos) )
{
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, usMapPos ), 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 = usMapPos;
}
sAPCost = CalcTotalAPsToAttack( pSoldier, sTargetGridNo, TRUE, (INT8)(pSoldier->bShownAimTime ) );
if ( EnoughPoints( pSoldier, sAPCost, 0, TRUE ) )
{
return( TRUE );
}
else
{
// Play curse....
DoMercBattleSound( pSoldier, BATTLE_SOUND_CURSE1 );
}
}
}
}
return( FALSE );
}
BOOLEAN SelectedMercCanAffordMove( )
{
SOLDIERTYPE *pSoldier;
UINT16 sAPCost = 0;
INT16 sBPCost = 0;
UINT16 usMapPos;
LEVELNODE *pIntTile;
// Get soldier
if ( GetSoldier( &pSoldier, gusSelectedSoldier ) )
{
if( !GetMouseMapPos( &usMapPos) )
{
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 = usMapPos;
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->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->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 )
{
UINT16 usMapPos;
SOLDIERTYPE *pSoldier;
if( !GetMouseMapPos( &usMapPos) )
{
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 && ( usMapPos != gsOverItemsGridNo || gsInterfaceLevel != gsOverItemsLevel ) )
{
gsOverItemsGridNo = NOWHERE;
guiPendingOverrideEvent = A_CHANGE_TO_MOVE;
}
else
{
guiNewUICursor = NORMALHANDCURSOR_UICURSOR;
UIHandleInteractiveTilesAndItemsOnTerrain( pSoldier, usMapPos, 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;
UINT16 usMapPos;
BOOLEAN fFoundMerc = FALSE;
if( !GetMouseMapPos( &usMapPos) )
{
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->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->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->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->bLevel;
}
}
gfUIHandleSelectionAboveGuy = TRUE;
gsSelectedGuy = usSoldierIndex;
}
}
else
{
if ( pSoldier->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->uiStatusFlags & SOLDIER_VEHICLE )
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, TacticalStr[ VEHICLES_NO_STANCE_CHANGE_STR ] );
}
else if ( pSoldier->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->bTurningFromPronePosition = TURNING_FROM_PRONE_OFF;
// Check if we have enough APS
if ( SoldierCanAffordNewStance( pSoldier, bNewStance ) )
{
// Adjust stance
//ChangeSoldierStance( pSoldier, bNewStance );
SendChangeSoldierStanceEvent( pSoldier, bNewStance );
pSoldier->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 = GetMoveStateBasedOnStance( pSoldier, bNewStance );
pSoldier->ubDesiredHeight = NO_DESIRED_HEIGHT;
#if 0
if ( pSoldier->usUIMovementMode == CRAWLING && gAnimControl[ pSoldier->usAnimState ].ubEndHeight != ANIM_PRONE )
{
pSoldier->usDontUpdateNewGridNoOnMoveAnimChange = LOCKED_NO_NEWGRIDNO;
pSoldier->bPathStored = FALSE;
}
else
#endif
{
pSoldier->usDontUpdateNewGridNoOnMoveAnimChange = 1;
}
ChangeSoldierState( pSoldier, pSoldier->usUIMovementMode, 0, FALSE );
}
}
// Set UI value for soldier
SetUIbasedOnStance( pSoldier, bNewStance );
gfUIStanceDifferent = TRUE;
// ATE: If we are being serviced...stop...
// InternalReceivingSoldierCancelServices( pSoldier, FALSE );
InternalGivingSoldierCancelServices( pSoldier, 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 )
{
UINT16 usMapPos;
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( &usMapPos );
ConvertGridNoToXY( usMapPos, &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 == usMapPos )
{
(*puiCursorFlags) |= MOUSE_MOVING_IN_TILE;
}
else
{
fStationary = FALSE;
(*puiCursorFlags) |= MOUSE_MOVING_NEW_TILE;
}
}
else
{
(*puiCursorFlags) |= MOUSE_STATIONARY;
fStationary = TRUE;
}
usOldMapPos = usMapPos;
usOldMouseXPos = gusMouseXPos;
usOldMouseYPos = gusMouseYPos;
uiOldFrameNumber = guiGameCycleCounter;
uiSameFrameCursorFlags = (*puiCursorFlags);
}
BOOLEAN HandleUIMovementCursor( SOLDIERTYPE *pSoldier, UINT32 uiCursorFlags, UINT16 usMapPos, UINT32 uiFlags )
{
BOOLEAN fSetCursor = FALSE;
BOOLEAN fCalculated = FALSE;
static UINT16 usTargetID = NOBODY;
static BOOLEAN fTargetFound = FALSE;
BOOLEAN fTargetFoundAndLookingForOne = FALSE;
BOOLEAN fIntTileFoundAndLookingForOne = 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->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, usMapPos, uiFlags );
}
// Save for next time...
fTargetFound = gfUIFullTargetFound;
usTargetID = gusUIFullTargetID;
if ( fTargetFound )
{
fTargetFoundAndLookingForOne = TRUE;
}
}
if ( uiFlags == MOVEUI_TARGET_ITEMS )
{
gfUIOverItemPool = TRUE;
gfUIOverItemPoolGridNo = usMapPos;
}
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, usMapPos, 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->autofireLastStep = FALSE;
pSoldier->bDoAutofire = 1;
}
return( fSetCursor );
}
INT8 DrawUIMovementPath( SOLDIERTYPE *pSoldier, UINT16 usMapPos, UINT32 uiFlags )
{
INT16 sAPCost, sBPCost;
INT16 sActionGridNo;
STRUCTURE *pStructure;
BOOLEAN fOnInterTile = FALSE;
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 = usMapPos;
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, usMapPos, &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, usMapPos, &ubDirection, NULL, FALSE, TRUE );
if ( sActionGridNo == -1 )
{
sActionGridNo = usMapPos;
}
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 = 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( usMapPos, &ubMercID ) == 2 )
{
INT16 sNewGridNo;
UINT8 ubDirection;
sNewGridNo = FindGridNoFromSweetSpotWithStructDataFromSoldier( pSoldier, pSoldier->usUIMovementMode, 5, &ubDirection, 0, MercPtrs[ ubMercID ] );
if ( sNewGridNo != NOWHERE )
{
usMapPos = sNewGridNo;
}
}
sActionGridNo = FindAdjacentGridEx( pSoldier, usMapPos, &ubDirection, NULL, FALSE, TRUE );
if ( sActionGridNo == -1 )
{
sActionGridNo = usMapPos;
}
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( usMapPos, &ubMercID ) == 2 )
{
INT16 sNewGridNo;
UINT8 ubDirection;
sNewGridNo = FindGridNoFromSweetSpotWithStructDataFromSoldier( pSoldier, pSoldier->usUIMovementMode, 5, &ubDirection, 0, MercPtrs[ ubMercID ] );
if ( sNewGridNo != NOWHERE )
{
usMapPos = sNewGridNo;
}
}
sActionGridNo = FindAdjacentGridEx( pSoldier, usMapPos, &ubDirection, NULL, FALSE, TRUE );
if ( sActionGridNo == -1 )
{
sActionGridNo = usMapPos;
}
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->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 = usMapPos;
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 += 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 )
{
sAPCost += GetAPsToDropBomb( pSoldier );
sAPCost += UIPlotPath( pSoldier, usMapPos, NO_COPYROUTE, fPlot, TEMPORARY, (UINT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints );
gfUIHandleShowMoveGrid = TRUE;
gsUIHandleShowMoveGridLocation = usMapPos;
}
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, usMapPos, &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( usMapPos, &pItemPool, pSoldier->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 += AP_PICKUP_ITEM;
}
}
else
{
sAPCost += 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->bDesiredDirection != ubDirection)
{
if ( gAnimControl[ pSoldier->usAnimState ].uiFlags & ( ANIM_BREATH | ANIM_OK_CHARGE_AP_FOR_TURN | ANIM_FIREREADY ) && !fInitalMove && !pSoldier->fDontChargeTurningAPs )
{
// Which position has the soldier?
switch( gAnimControl[ pSoldier->usAnimState ].ubEndHeight )
{
case ANIM_STAND:
sAPCost += AP_LOOK_STANDING;
break;
case ANIM_CROUCH:
sAPCost += AP_LOOK_CROUCHED;
break;
case ANIM_PRONE:
sAPCost += AP_LOOK_PRONE;
break;
}
}
}
return sAPCost;
}
BOOLEAN UIMouseOnValidAttackLocation( SOLDIERTYPE *pSoldier )
{
UINT16 usInHand;
BOOLEAN fGuyHere = FALSE;
SOLDIERTYPE *pTSoldier;
UINT8 ubItemCursor;
UINT16 usMapPos;
if ( !GetMouseMapPos( &usMapPos ) )
{
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( usMapPos ) && pSoldier->bLevel == 0 )
{
return( TRUE );
}
else
{
return( FALSE );
}
}
if ( ubItemCursor == REPAIRCURS )
{
if ( gfUIFullTargetFound )
{
usMapPos = MercPtrs[ gusUIFullTargetID ]->sGridNo;
}
if ( IsRepairableStructAtGridNo( usMapPos, NULL ) && pSoldier->bLevel == 0 )
{
return( TRUE );
}
else
{
return( FALSE );
}
}
if ( ubItemCursor == REFUELCURS )
{
if ( gfUIFullTargetFound )
{
usMapPos = MercPtrs[ gusUIFullTargetID ]->sGridNo;
}
if ( IsRefuelableStructAtGridNo( usMapPos, NULL ) && pSoldier->bLevel == 0 )
{
return( TRUE );
}
else
{
return( FALSE );
}
}
if ( ubItemCursor == BOMBCURS )
{
if ( usMapPos == pSoldier->sGridNo )
{
return( TRUE );
}
if ( !NewOKDestination( pSoldier, usMapPos, TRUE, pSoldier->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->uiStatusFlags & ( SOLDIER_VEHICLE | SOLDIER_ROBOT ) ) )
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, TacticalStr[ CANNOT_DO_FIRST_AID_STR ], pTSoldier->name );
return( FALSE );
}
if ( pSoldier->bMedical == 0 )
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, pMessageStrings[ MSG_MERC_HAS_NO_MEDSKILL ], pSoldier->name );
return( FALSE );
}
if ( pTSoldier->bBleeding == 0 && pTSoldier->bLife != pTSoldier->bLifeMax )
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, gzLateLocalizedString[ 19 ], pTSoldier->name );
return( FALSE );
}
if ( pTSoldier->bBleeding == 0 && pTSoldier->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->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
switch( bCurrentHeight )
{
case ANIM_STAND - ANIM_CROUCH:
case ANIM_CROUCH - ANIM_STAND:
bAP = AP_CROUCH;
bBP = BP_CROUCH;
break;
case ANIM_STAND - ANIM_PRONE:
case ANIM_PRONE - ANIM_STAND:
bAP = AP_CROUCH + AP_PRONE;
bBP = BP_CROUCH + BP_PRONE;
break;
case ANIM_CROUCH - ANIM_PRONE:
case ANIM_PRONE - ANIM_CROUCH:
bAP = AP_PRONE;
bBP = 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->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->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->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;
// Lesh: raise weapon include APs to set weapon towards enemy and APs to aquire/change target
if( pSoldier->sLastTarget != sXPos + (MAXCOL * sYPos ) )
gsCurrentActionPoints = 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;
// 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->fNoAPToFinishMove )
{
SoldierGotoStationaryStance( pSoldier );
}
//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;
// Lesh: raise weapon include APs to set weapon towards enemy and APs to aquire/change target
if( pSoldier->sLastTarget != sXPos + (MAXCOL * sYPos ) )
sAPCost = 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 )
SoldierReadyWeapon( pSoldier, 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;
SOLDIERTYPE *pFirstSoldier = NULL;
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->uiStatusFlags & SOLDIER_MULTI_SELECTED )
{
MakeSoldierTurn( pSoldier, sXPos, sYPos );
}
}
}
}
else
{
// Get soldier
if ( !GetSoldier( &pSoldier, gusSelectedSoldier ) )
{
return( GAME_SCREEN );
}
if ( MakeSoldierTurn( pSoldier, sXPos, sYPos ) )
{
SetUIBusy( pSoldier->ubID );
}
}
return( GAME_SCREEN );
}
UINT32 UIHandleTOnTerrain( UI_EVENT *pUIEvent )
{
SOLDIERTYPE *pSoldier;
UINT8 ubTargID;
UINT32 uiRange;
UINT16 usMapPos;
BOOLEAN fValidTalkableGuy = FALSE;
INT16 sTargetGridNo;
// Get soldier
if ( !GetSoldier( &pSoldier, gusSelectedSoldier ) )
{
return( GAME_SCREEN );
}
if (!GetMouseMapPos( &usMapPos ) )
{
return( GAME_SCREEN );
}
if( ValidQuickExchangePosition( ) )
{
// Do new cursor!
guiPendingOverrideEvent = M_ON_TERRAIN;
return( UIHandleMOnTerrain( pUIEvent ) );
}
sTargetGridNo = usMapPos;
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->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->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 )
InternalDoMercBattleSound( pSoldier, BATTLE_SOUND_ATTN1, BATTLE_SND_LOWER_VOLUME );
if ( pSoldier->fMercAsleep )
{
PutMercInAwakeState( pSoldier );
}
}
}
}
// If here, select the first guy...
if ( pFirstSoldier != NULL && !fSelectedSoldierInBatch )
{
SelectSoldier( pFirstSoldier->ubID, TRUE, TRUE );
}
}
void StopRubberBandedMercFromMoving( )
{
SOLDIERTYPE * pSoldier;
INT32 cnt;
SOLDIERTYPE *pFirstSoldier = NULL;
if ( !gTacticalStatus.fAtLeastOneGuyOnMultiSelect )
{
return;
}
// 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->uiStatusFlags & SOLDIER_MULTI_SELECTED )
{
pSoldier->fDelayedMovement = FALSE;
pSoldier->sFinalDestination = pSoldier->sGridNo;
StopSoldier( pSoldier );
}
}
}
}
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->uiStatusFlags & SOLDIER_MULTI_SELECTED )
{
if ( pSoldier->ubID == gusSelectedSoldier )
{
fMoveFast = pSoldier->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->uiStatusFlags & SOLDIER_MULTI_SELECTED )
{
// If we can't be controlled, returninvalid...
if ( pSoldier->uiStatusFlags & SOLDIER_ROBOT )
{
if ( !CanRobotBeControlled( pSoldier ) )
{
continue;
}
}
pSoldier->fUIMovementFast = fMoveFast;
pSoldier->usUIMovementMode = GetMoveStateBasedOnStance( pSoldier, gAnimControl[ pSoldier->usAnimState ].ubEndHeight );
pSoldier->fUIMovementFast = FALSE;
if ( gUIUseReverse )
{
pSoldier->bReverse = TRUE;
}
else
{
pSoldier->bReverse = FALSE;
}
// Remove any previous actions
pSoldier->ubPendingAction = NO_PENDING_ACTION;
if ( EVENT_InternalGetNewSoldierPath( pSoldier, sDestGridNo, pSoldier->usUIMovementMode , TRUE, pSoldier->fNoAPToFinishMove ) )
{
InternalDoMercBattleSound( pSoldier, 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->uiStatusFlags & SOLDIER_MULTI_SELECTED )
{
pSoldier->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->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->uiStatusFlags & ( SOLDIER_VEHICLE | SOLDIER_PASSENGER | SOLDIER_DRIVER ) ) )
{
if ( !_KeyDown( ALT ) )
{
pSoldier->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->uiStatusFlags |= SOLDIER_MULTI_SELECTED;
}
}
}
return( GAME_SCREEN );
}
UINT32 UIHandleJumpOverOnTerrain( UI_EVENT *pUIEvent )
{
SOLDIERTYPE *pSoldier;
UINT16 usMapPos;
// Here, first get map screen
if ( !GetSoldier( &pSoldier, gusSelectedSoldier ) )
{
return( GAME_SCREEN );
}
if (!GetMouseMapPos( &usMapPos ) )
{
return( GAME_SCREEN );
}
if ( !IsValidJumpLocation( pSoldier, usMapPos, 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;
UINT16 usMapPos;
UINT8 ubDirection;
// Here, first get map screen
if ( !GetSoldier( &pSoldier, gusSelectedSoldier ) )
{
return( GAME_SCREEN );
}
if (!GetMouseMapPos( &usMapPos ) )
{
return( GAME_SCREEN );
}
if ( !IsValidJumpLocation( pSoldier, usMapPos, FALSE ) )
{
return( GAME_SCREEN );
}
SetUIBusy( pSoldier->ubID );
// OK, Start jumping!
// Remove any previous actions
pSoldier->ubPendingAction = NO_PENDING_ACTION;
// Get direction to goto....
ubDirection = GetDirectionFromGridNo( usMapPos, pSoldier );
pSoldier->fDontChargeTurningAPs = TRUE;
EVENT_SetSoldierDesiredDirection( pSoldier, ubDirection);
pSoldier->fTurningUntilDone = TRUE;
// ATE: Reset flag to go back to prone...
//pSoldier->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->bLife == 0 )
{
return( FALSE );
}
if ( pSoldier->bCollapsed && fCheckCollapsed )
{
return( FALSE );
}
if ( pSoldier->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->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;
UINT16 usMapPos;
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( &usMapPos ) )
{
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->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, usMapPos );
// 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 = 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->ubPendingAction = MERC_TALK;
pSoldier->uiPendingActionData1 = pTSoldier->ubID;
pSoldier->ubPendingActionAnimCount = 0;
// WALK UP TO DEST FIRST
EVENT_InternalGetNewSoldierPath( pSoldier, sGoodGridNo, pSoldier->usUIMovementMode , TRUE , pSoldier->fNoAPToFinishMove );
return( FALSE );
}
}
else
{
sAPCost = AP_TALK;
// Check AP cost...
if ( !EnoughPoints( pSoldier, sAPCost, 0, TRUE ) )
{
return( FALSE );
}
// OK, startup!
PlayerSoldierStartTalking( pSoldier, 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 )
{
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 usMapPos, 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 = usMapPos;
// 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->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 != usMapPos || 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, usMapPos, 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 )
{
BeginSoldierClimbUpRoof( pSoldier );
}
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 )
{
BeginSoldierClimbDownRoof( pSoldier );
}
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;
INT16 sDistVisible = FALSE;
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->bNeutral )
if ( ( pOverSoldier->bTeam != gbPlayerNum && pOverSoldier->bNeutral ) || (pOverSoldier->bTeam == MILITIA_TEAM && pOverSoldier->bSide == 0 ) )
{
// hehe - don't allow animals to exchange places
if ( !( pOverSoldier->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 )
{
if ( SoldierTo3DLocationLineOfSightTest( pSoldier, pOverSoldier->sGridNo, pOverSoldier->bLevel, 3, TRUE, CALC_FROM_ALL_DIRS ) )
{
// ATE:
// Check that the path is good!
if ( FindBestPath( pSoldier, pOverSoldier->sGridNo, pSoldier->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], sDistance=0, 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->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->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->fTurningUntilDone )
{
// OK, NOW check if there is a guy in between us
//
//
ubGuyThere = WhoIsThere2( sIntSpot, pSoldier->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 );
}