Files
source/Tactical/Handle UI.cpp
T
Kriplo d83f23ce2b Brief: //dnl ch73
- Fixing bad APs deduction when using blade or blunt weapons and punching in general from different stances when need turn to your target.
Details:
- Fix wrong APs deduction and animation change when go to attack with knife or punch from prone.
- Fix no APs cost for martial artist when perform turning.
- When target was prone there was several problems in defining turnover and stance cost as range to them could vary depending of obstacles between, and as punch or stub in general use same logic put all stubbing and punching under one function MinAPsToPunch which should solve current problems with APs calculations.
- Still there are no turning cost when going to stub or punch from moving, but this problem is not related with MinAPsToAttack but with UIPlotPath which don't add turning cost, hope someone in the future will add this feature which never exist.


git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@6465 3b4a5df2-a311-0410-b5c6-a8a6f20db521
2013-10-03 20:22:35 +00:00

7128 lines
190 KiB
C++

#include "connect.h"
#ifdef PRECOMPILEDHEADERS
#include "Tactical All.h"
#include "BuildDefines.h"
#else
#include "builddefines.h"
#include <stdio.h>
#include <string.h>
#include "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 "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 "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"
#include "DisplayCover.h"
//ddd îïòèìèçàöèÿ äëÿ õîäà äðàíèêîâ
#include "aiinternals.h"
//#include "los.h"
//#include "structure wrap.h"
//#include "DisplayCover.h"
//ddd îïòèìèçàöèÿ äëÿ õîäà äðàíèêîâ
#endif
#include "teamturns.h"
#include "Options Screen.h"
#include "SaveLoadScreen.h"
//////////////////////////////////////////////////////////////////////////////
// SANDRO - In this file, all APBPConstants[AP_CROUCH] and APBPConstants[AP_PRONE] were changed to GetAPsCrouch() and GetAPsProne()
// On the bottom here, there are these functions made
//////////////////////////////////////////////////////////////////////
//extern BOOLEAN gfDisplayFullCountRingBurst;
extern UINT16 PickSoldierReadyAnimation( SOLDIERTYPE *pSoldier, BOOLEAN fEndReady, BOOLEAN fHipStance );
//#define AP_TO_AIM_TILE_IF_GETTING_READY 1
#define AP_TO_AIM_TILE_IF_ALREADY_READY ( Weapon[ Item[pSoldier->inv[HANDPOS].usItem].ubClassIndex ].ubReadyTime ? 2 : 1 )
#define AP_TO_AIM_TILE_IF_GETTING_READY AP_TO_AIM_TILE_IF_ALREADY_READY
#define MAX_ON_DUTY_SOLDIERS 6
/////////////////////////////////////////////////////////////////////////////////////
// UI SYSTEM DESCRIPTION
//
// The UI system here decouples event determination from event execution. IN other words,
// first any user input is gathered and analysed for an event to happen. Once the event is determined,
// it is then executed. For example, if the left mouse button is used to select a guy, it does not
// execute the code to selected the guy, rather it sets a flag to a particular event, in this case
// the I_SELECT_MERC event is set. The code then executes this event after all input is analysed. In
// this way, more than one input method from the user will cause the came event to occur and hence no
// duplication of code. Also, events have cetain charactoristics. The select merc event is executed just
// once and then returns to the previous event. Most events are set to run continuously until new
// input changes to another event. Other events have a 'SNAP-BACK' feature which snap the mouse back to
// it's position before the event was executed. Another issue is UI modes. In order to filter out input
// depending on other flags, for example we do not want to cancel the confirm when a user moves to another
// tile unless we are in the 'confirm' mode. This could be done by flags ( and in effect it is ) where
// if staements are used, but here at input collection time, we can switch on our current mode to handle
// input differently based on the mode. Doing it this way also allows us to group certain commands togther
// like menu commands which are initialized and deleted in the same manner.
//
// UI_EVENTS
/////////////
//
// UI_EVENTS have flags to itendtify themselves with special charactoristics, a UI_MODE catagory which
// signifies the UI mode this event will cause the system to move to. Also, a pointer to a handle function is
// used to actually handle the particular event. UI_EVENTS also have a couple of param variables and a number
// of boolean flags used during run-time to determine states of events.
//
////////////////////////////////////////////////////////////////////////////////////////////////
// LOCAL DEFINES
#define GO_MOVE_ONE 40
#define GO_MOVE_TWO 80
#define GO_MOVE_THREE 100
// CALLBACKS FOR EVENTS
UINT32 UIHandleIDoNothing( UI_EVENT *pUIEvent );
UINT32 UIHandleExit( UI_EVENT *pUIEvent );
UINT32 UIHandleNewMerc( UI_EVENT *pUIEvent );
UINT32 UIHandleNewBadMerc( UI_EVENT *pUIEvent );
UINT32 UIHandleSelectMerc( UI_EVENT *pUIEvent );
UINT32 UIHandleEnterEditMode( UI_EVENT *pUIEvent );
UINT32 UIHandleEnterPalEditMode( UI_EVENT *pUIEvent );
UINT32 UIHandleEndTurn( UI_EVENT *pUIEvent );
UINT32 UIHandleTestHit( UI_EVENT *pUIEvent );
UINT32 UIHandleIOnTerrain( UI_EVENT *pUIEvent );
UINT32 UIHandleIChangeToIdle( UI_EVENT *pUIEvent );
UINT32 UIHandleILoadLevel( UI_EVENT *pUIEvent );
UINT32 UIHandleISoldierDebug( UI_EVENT *pUIEvent );
UINT32 UIHandleILOSDebug( UI_EVENT *pUIEvent );
UINT32 UIHandleILevelNodeDebug( UI_EVENT * pUIEvent );
UINT32 UIHandleIGotoDemoMode( UI_EVENT *pUIEvent );
UINT32 UIHandleILoadFirstLevel( UI_EVENT *pUIEvent );
UINT32 UIHandleILoadSecondLevel( UI_EVENT *pUIEvent );
UINT32 UIHandleILoadThirdLevel( UI_EVENT *pUIEvent );
UINT32 UIHandleILoadFourthLevel( UI_EVENT *pUIEvent );
UINT32 UIHandleILoadFifthLevel( UI_EVENT *pUIEvent );
UINT32 UIHandleIETOnTerrain( UI_EVENT *pUIEvent );
UINT32 UIHandleIETEndTurn( UI_EVENT *pUIEvent );
UINT32 UIHandleMOnTerrain( UI_EVENT *pUIEvent );
UINT32 UIHandleMChangeToAction( UI_EVENT *pUIEvent );
UINT32 UIHandleMCycleMovement( UI_EVENT *pUIEvent );
UINT32 UIHandleMCycleMoveAll( UI_EVENT *pUIEvent );
UINT32 UIHandleMAdjustStanceMode( UI_EVENT *pUIEvent );
UINT32 UIHandleMChangeToHandMode( UI_EVENT *pUIEvent );
UINT32 UIHandlePOPUPMSG( UI_EVENT *pUIEvent );
UINT32 UIHandleAOnTerrain( UI_EVENT *pUIEvent );
UINT32 UIHandleAChangeToMove( UI_EVENT *pUIEvent );
UINT32 UIHandleAChangeToConfirmAction( UI_EVENT *pUIEvent );
UINT32 UIHandleAEndAction( UI_EVENT *pUIEvent );
UINT32 UIHandleMovementMenu( UI_EVENT *pUIEvent );
UINT32 UIHandlePositionMenu( UI_EVENT *pUIEvent );
UINT32 UIHandleCWait( UI_EVENT *pUIEvent );
UINT32 UIHandleCMoveMerc( UI_EVENT *pUIEvent );
UINT32 UIHandleCOnTerrain( UI_EVENT *pUIEvent );
UINT32 UIHandlePADJAdjustStance( UI_EVENT *pUIEvent );
UINT32 UIHandleCAOnTerrain( UI_EVENT *pUIEvent );
UINT32 UIHandleCAMercShoot( UI_EVENT *pUIEvent );
UINT32 UIHandleCAEndConfirmAction( UI_EVENT *pUIEvent );
UINT32 UIHandleHCOnTerrain( UI_EVENT *pUIEvent );
UINT32 UIHandleHCGettingItem( UI_EVENT *pUIEvent );
UINT32 UIHandleLCOnTerrain( UI_EVENT *pUIEvent );
UINT32 UIHandleLCChangeToLook( UI_EVENT *pUIEvent );
UINT32 UIHandleLCLook( UI_EVENT *pUIEvent );
UINT32 UIHandleTATalkingMenu( UI_EVENT *pUIEvent );
UINT32 UIHandleTOnTerrain( UI_EVENT *pUIEvent );
UINT32 UIHandleTChangeToTalking( UI_EVENT *pUIEvent );
UINT32 UIHandleLUIOnTerrain( UI_EVENT *pUIEvent );
UINT32 UIHandleLUIBeginLock( UI_EVENT *pUIEvent );
UINT32 UIHandleLUIEndLock( UI_EVENT *pUIEvent );
UINT32 UIHandleLAOnTerrain( UI_EVENT *pUIEvent );
UINT32 UIHandleLABeginLockOurTurn( UI_EVENT *pUIEvent );
UINT32 UIHandleLAEndLockOurTurn( UI_EVENT *pUIEvent );
UINT32 UIHandleRubberBandOnTerrain( UI_EVENT *pUIEvent );
UINT32 UIHandleJumpOverOnTerrain( UI_EVENT *pUIEvent );
UINT32 UIHandleJumpOver( UI_EVENT *pUIEvent );
UINT32 UIHandleOpenDoorMenu( UI_EVENT *pUIEvent );
UINT32 UIHandleEXExitSectorMenu( UI_EVENT *pUIEvent );
BOOLEAN ValidQuickExchangePosition( );
extern void DebugLevelNodePage( void );
INT16 gsTreeRevealXPos;
INT16 gsTreeRevealYPos;
// taken out of header to remove multiple symbol definitions (jonathanl)
BOOLEAN gfUICtHBar;
// HEADROCK HAM 4: A new Struct to contain all CTH display data
CTHDISPLAY gCTHDisplay;
// HEADROCK HAM B1/2: Created an array to hold CTH of different bullets for Burst/Auto CTH Bar.
UINT8 gbCtH[ 10 ];
UINT8 gbCtHBurstCount;
// HEADROCK HAM B2: This value tracks whether Autofire mode is selected. This value may be redundant... not sure.
BOOLEAN gbCtHAutoFire;
UINT16 gsTotalBulletCount;
UINT16 gsBulletCount;
BOOLEAN gTintBulletCounts;
BOOLEAN gfUIAutofireBulletCount;
BOOLEAN gfUIBodyHitLocation;
BOOLEAN HandleMultiSelectionMove( INT32 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, INT32 usMapPos, UINT32 uiFlags );
INT8 UIHandleInteractiveTilesAndItemsOnTerrain( SOLDIERTYPE *pSoldier, INT32 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;
INT32 gsRequesterGridNo;
INT32 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;
INT32 gsOutOfRangeGridNo = NOWHERE;
UINT8 gubOutOfRangeMerc = NOBODY;
BOOLEAN gfOKForExchangeCursor = FALSE;
UINT32 guiUIInterfaceSwapCursorsTime = 0;
INT32 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;
///*** dddd
BOOLEAN fMiddleButtonDown = FALSE;
BOOLEAN fX1ButtonDown = FALSE;
BOOLEAN fX2ButtonDown = FALSE;
BOOLEAN gUITargetReady = FALSE;
BOOLEAN gUITargetShotWaiting = FALSE;
INT32 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;
INT32 gsUIHandleShowMoveGridLocation = NOWHERE ;
BOOLEAN gfUIOverItemPool = FALSE;
INT32 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
INT32 gsSelectedGridNo = 0;
INT16 gsSelectedLevel = I_GROUND_LEVEL;
INT16 gsSelectedGuy = NOBODY;
BOOLEAN gfUIDisplayDamage = FALSE;
INT8 gbDamage = 0;
INT32 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 );
//-------------------------Legion 2 okno-----------------------------------------------------------
void GetMercOknoDirection( UINT8 ubSoldierID, BOOLEAN *pfGoDown, BOOLEAN *pfGoUp )
{
INT8 bNewDirection;
SOLDIERTYPE *pSoldier;
*pfGoDown = FALSE;
*pfGoUp = FALSE;
if ( !GetSoldier( &pSoldier, ubSoldierID ) )
{
return;
}
if ( pSoldier->pathing.bLevel == 0 && ( pSoldier->ubDirection == NORTH || pSoldier->ubDirection == EAST || pSoldier->ubDirection == SOUTH || pSoldier->ubDirection == WEST ))
{
if ( FindHeigherLevelOkno( pSoldier, pSoldier->sGridNo, pSoldier->ubDirection, &bNewDirection ) )
{
*pfGoUp = TRUE;
}
}
}
//----------------------------------------------------------------------------------
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;
INT32 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;
// HEADROCK HAM B2: tells the cursor-drawing function to draw two CTH bars (for autofire).
gbCtHAutoFire = FALSE;
// Set old event value
guiOldEvent = uiNewEvent = guiCurrentEvent;
if ( gfUIInterfaceSetBusy )
{
if ( ( GetJA2Clock( ) - guiUIInterfaceBusyTime ) > 25000 )
{
gfUIInterfaceSetBusy = FALSE;
//UNLOCK UI
UnSetUIBusy( (UINT8)gusSelectedSoldier );
// Decrease global busy counter...
gTacticalStatus.ubAttackBusyCount = 0;
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("Setting attack busy count to 0 due to ending AI lock" ) );
guiPendingOverrideEvent = LU_ENDUILOCK;
UIHandleLUIEndLock( NULL );
}
}
if ( !gGameSettings.fOptions[TOPTION_DISABLE_CURSOR_SWAP] )
{
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;
}
DisplayCover();
DisplayMines(); // added by Flugente
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 INT32 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 )
{
INT32 usMapPos;
//DBrot: More Rooms
//UINT8 ubRoomNum;
UINT16 usRoomNum;
gfUIDisplayActionPoints = FALSE;
ErasePath( TRUE );
if( GetMouseMapPos( &usMapPos) )
{
if ( gusSelectedSoldier != NOBODY && MercPtrs[ gusSelectedSoldier ]->pathing.bLevel == 0 )
{
// ATE: Is this place revealed?
if ( !InARoom( usMapPos, &usRoomNum ) || ( InARoom( usMapPos, &usRoomNum ) && gpWorldLevelData[ usMapPos ].uiFlags & MAPELEMENT_REVEALED ) )
{
if ( sOldExitGridNo != usMapPos )
{
fOkForExit = OKForSectorExit( (INT8)-1, usMapPos, &uiTraverseTimeInMinutes );
sOldExitGridNo = usMapPos;
}
if ( fOkForExit )
{
if ( gGameExternalOptions.fGridExitInTurnBased || ( gTacticalStatus.uiFlags & REALTIME ) || !( gTacticalStatus.uiFlags & INCOMBAT ) )
{
if ( gfUIConfirmExitArrows )
{
guiNewUICursor = CONFIRM_EXIT_GRID_UICURSOR;
}
else
{
guiNewUICursor = EXIT_GRID_UICURSOR;
}
}
else
{
guiNewUICursor = NOEXIT_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;
INT32 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." );
}
// WDS - make number of mercenaries, etc. be configurable
else if( bReturnCode == MERC_HIRE_OVER_PLAYER_LIMIT )
{
ScreenMsg( FONT_ORANGE, MSG_BETAVERSION, L"Can't hire that many mercs." );
}
else
{
// Get soldier from profile
pSoldier = FindSoldierByProfileID( ubTemp, FALSE );
MercArrivesCallback( pSoldier->ubID );
SelectSoldier( pSoldier->ubID, FALSE, TRUE );
}
}
return( GAME_SCREEN );
}
UINT32 UIHandleNewBadMerc( UI_EVENT *pUIEvent )
{
SOLDIERTYPE *pSoldier;
INT32 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 )
{
CHAR16 zString[128];
// CANCEL FROM PLANNING MODE!
if ( InUIPlanMode( ) )
{
EndUIPlan( );
}
// ATE: If we have an item pointer end it!
CancelItemPointer( );
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() )
{
guiPreviousOptionScreen = guiCurrentScreen;
//increment end turn number
guiLastSaveGameNum++;
if( guiLastSaveGameNum == 2 )
guiLastSaveGameNum = 0;
swprintf( zString, L"%s%d",pMessageStrings[ MSG_SAVE_END_TURN_SAVE_TEXT ], guiLastSaveGameNum + 1);
SaveGame(SAVE__END_TURN_NUM, zString );
}
////ddd îïòèìèçàöèÿ äëÿ õîäà äðàíèêîâ
if ( (gTacticalStatus.uiFlags & TURNBASED) && (gTacticalStatus.uiFlags & INCOMBAT ) )
{
memset( gubWorldTileInLight, FALSE, sizeof( gubWorldTileInLight ) );
memset( gubIsCorpseThere, FALSE, sizeof( gubIsCorpseThere ) );
memset( gubMerkCanSeeThisTile, FALSE, sizeof( gubMerkCanSeeThisTile ) );
//ðàçâåðòêà öèêëà. ïðè èçìåíåíèè WORLD_MAX íà äð.çíà÷. íåîáõîäèìî áóäåò ïîä÷èùàòü õâîñòû! èáî îïàñíûé êîä!!! ;)
// WANNE: We had a custom user map (Tixa, J9), where the following loop caused an unhandled exception.
// The crash occurd at ~index 16000 when calling the method IsCorpseAtGridNo() ...
// I don't know what causes it ...
// Just try/catch (ugly, but works).
__try
{
for(UINT32 i=0; i<(UINT32)WORLD_MAX ;i+=4)
{
gubWorldTileInLight[i] = InLightAtNight(i, gpWorldLevelData[ i ].sHeight);
gubIsCorpseThere[i] = IsCorpseAtGridNo( i, gpWorldLevelData[ i ].sHeight );
gubWorldTileInLight[i+1] = InLightAtNight(i+1, gpWorldLevelData[ i+1 ].sHeight);
gubIsCorpseThere[i+1] = IsCorpseAtGridNo( i+1, gpWorldLevelData[ i+1 ].sHeight );
gubWorldTileInLight[i+2] = InLightAtNight(i+2, gpWorldLevelData[ i+2 ].sHeight);
gubIsCorpseThere[i+2] = IsCorpseAtGridNo( i+2, gpWorldLevelData[ i+2 ].sHeight );
gubWorldTileInLight[i+3] = InLightAtNight(i+3, gpWorldLevelData[ i+3 ].sHeight);
gubIsCorpseThere[i+3] = IsCorpseAtGridNo( i+3, gpWorldLevelData[ i+3 ].sHeight );
}
}
__except( EXCEPTION_EXECUTE_HANDLER )
{
// WANNE: Ignore, so the game can continue ...
}
INT32 tcnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
SOLDIERTYPE *tS;
INT16 sXOffset, sYOffset;
INT32 sGridNo;UINT16 usSightLimit=0;
for ( tS = MercPtrs[ tcnt ]; tcnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; tcnt++,tS++ )
if ( tS->stats.bLife >= OKLIFE && tS->sGridNo != NOWHERE && tS->bInSector )
{
//loop through all the gridnos that we are interested in
for (sYOffset = -30; sYOffset <= 30; sYOffset++)
for (sXOffset = -30; sXOffset <= 30; sXOffset++)
{
sGridNo = tS->sGridNo + sXOffset + (MAXCOL * sYOffset);
if ( sGridNo <= 0 || sGridNo >= WORLD_MAX )
continue;
//usSightLimit = tS->GetMaxDistanceVisible(sGridNo, FALSE, CALC_FROM_WANTED_DIR);
if(gubMerkCanSeeThisTile[sGridNo]==0)
gubMerkCanSeeThisTile[sGridNo]=//SoldierToVirtualSoldierLineOfSightTest( tS, sGridNo, FALSE, ANIM_STAND, TRUE, usSightLimit );
SoldierToVirtualSoldierLineOfSightTest( tS, sGridNo, tS->pathing.bLevel,
ANIM_STAND, TRUE, CALC_FROM_WANTED_DIR);
}//fo
}//if
}
//ddd îïòèìèçàöèÿ äëÿ õîäà äðàíèêîâ**
// End our turn!
if (is_server || !is_client)
{
EndTurn( gbPlayerNum + 1 );
}
if(!is_server && is_client)
{
if (INTERRUPT_QUEUED)
{
EndTurn( gbPlayerNum + 1 );//is ending interrupt instead
}
else
{
send_EndTurn( netbTeam+1 );//for sending next netbteam rather than next local team
}
}
}
return( GAME_SCREEN );
}
UINT32 UIHandleTestHit( UI_EVENT *pUIEvent )
{
SOLDIERTYPE *pSoldier;
INT8 bDamage;
// CHECK IF WE'RE ON A GUY ( EITHER SELECTED, OURS, OR THEIRS
if ( gfUIFullTargetFound )
{
// Get Soldier
GetSoldier( &pSoldier, gusUIFullTargetID );
if ( _KeyDown( SHIFT ) )
{
pSoldier->bBreath -= 30;
if ( pSoldier->bBreath < 0 )
pSoldier->bBreath = 0;
bDamage = 1;
}
else
{
if ( Random(2) )
{
bDamage = 20;
}
else
{
bDamage = 25;
}
}
// gTacticalStatus.ubAttackBusyCount++;
DebugAttackBusy( "Testing a hit.\n" );
pSoldier->EVENT_SoldierGotHit( 1, bDamage, 10, pSoldier->ubDirection, 320, NOBODY , FIRE_WEAPON_NO_SPECIAL, pSoldier->bAimShotLocation, 0, NOWHERE );
// callahan update end - put everything as it was
}
return( GAME_SCREEN );
}
void ChangeInterfaceLevel( INT16 sLevel )
{
// Only if different!
if ( sLevel == gsInterfaceLevel )
{
return;
}
gsInterfaceLevel = sLevel;
if ( gsInterfaceLevel == 1 )
{
gsRenderHeight += ROOF_LEVEL_HEIGHT;
gTacticalStatus.uiFlags |= SHOW_ALL_ROOFS;
InvalidateWorldRedundency( );
}
else if ( gsInterfaceLevel == 0 )
{
gsRenderHeight -= ROOF_LEVEL_HEIGHT;
gTacticalStatus.uiFlags &= (~SHOW_ALL_ROOFS );
InvalidateWorldRedundency( );
}
SetRenderFlags(RENDER_FLAG_FULL);
// Remove any interactive tiles we could be over!
BeginCurInteractiveTileCheck( INTILE_CHECK_SELECTIVE );
gfPlotNewMovement = TRUE;
ErasePath(FALSE);
}
UINT32 UIHandleChangeLevel( UI_EVENT *pUIEvent )
{
if ( gsInterfaceLevel == 0 )
{
ChangeInterfaceLevel( 1 );
}
else if ( gsInterfaceLevel == 1 )
{
ChangeInterfaceLevel( 0 );
}
return( GAME_SCREEN );
}
extern void InternalSelectSoldier( UINT16 usSoldierID, BOOLEAN fAcknowledge, BOOLEAN fForceReselect, BOOLEAN fFromUI );
UINT32 UIHandleSelectMerc( UI_EVENT *pUIEvent )
{
INT32 iCurrentSquad;
// Get merc index at mouse and set current selection
if ( gfUIFullTargetFound )
{
iCurrentSquad = CurrentSquad( );
InternalSelectSoldier( gusUIFullTargetID, TRUE, FALSE, TRUE );
// If different, display message
if ( CurrentSquad( ) != iCurrentSquad )
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, pMessageStrings[ MSG_SQUAD_ACTIVE ], ( CurrentSquad( ) + 1 ) );
}
}
return( GAME_SCREEN );
}
UINT32 UIHandleMOnTerrain( UI_EVENT *pUIEvent )
{
SOLDIERTYPE *pSoldier;
INT32 usMapPos;
BOOLEAN fSetCursor = FALSE;
UINT32 uiCursorFlags;
LEVELNODE *pIntNode;
EXITGRID ExitGrid;
INT32 sIntTileGridNo;
ITEM_POOL *pItemPool;
static INT32 sGridNoForItemsOver;
static INT8 bLevelForItemsOver;
static UINT32 uiItemsOverTimer;
static BOOLEAN fOverItems;
if(!GetMouseMapPos(&usMapPos))//dnl ch53 151009
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 ( GetExitGrid( usMapPos, &ExitGrid ) && pSoldier->pathing.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->stats.bLife < OKLIFE )
{
UINT8 ubID;
// Show reg. cursor
// GO INTO IDLE MODE
// guiPendingOverrideEvent = I_CHANGE_TO_IDLE;
// gusSelectedSoldier = NOBODY;
ubID = FindNextActiveAndAliveMerc( pSoldier, FALSE, FALSE );
if ( ubID != NOBODY )
{
SelectSoldier( (INT16)ubID, FALSE, FALSE );
}
else
{
gusSelectedSoldier = NOBODY;
// Change UI mode to reflact that we are selected
guiPendingOverrideEvent = I_ON_TERRAIN;
}
}
else if ( ( UIOKMoveDestination( pSoldier, usMapPos ) != 1 ) && pIntNode == NULL )
{
// ERASE PATH
ErasePath( TRUE );
guiNewUICursor = CANNOT_MOVE_UICURSOR;
}
else
{
if ( !UIHandleInteractiveTilesAndItemsOnTerrain( pSoldier, usMapPos, FALSE, TRUE ) )
{
fSetCursor = HandleUIMovementCursor( pSoldier, uiCursorFlags, usMapPos, 0 );
}
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 && pSoldier->usUIMovementMode != WALKING_WEAPON_RDY && pSoldier->usUIMovementMode != WALKING_DUAL_RDY && pSoldier->usUIMovementMode != WALKING_ALTERNATIVE_RDY )
{
UIHandleSoldierStanceChange( pSoldier->ubID, ANIM_STAND );
pSoldier->flags.fUIMovementFast = 1;
}
else
{
pSoldier->flags.fUIMovementFast = 1;
pSoldier->usUIMovementMode = RUNNING;
gfPlotNewMovement = TRUE;
}
break;
case MOVEMENT_MENU_WALK:
UIHandleSoldierStanceChange( pSoldier->ubID, ANIM_STAND );
break;
case MOVEMENT_MENU_SWAT:
UIHandleSoldierStanceChange( pSoldier->ubID, ANIM_CROUCH );
break;
case MOVEMENT_MENU_PRONE:
UIHandleSoldierStanceChange( pSoldier->ubID, ANIM_PRONE );
break;
}
guiPendingOverrideEvent = A_CHANGE_TO_MOVE;
//pSoldier->usUIMovementMode = (INT8)pUIEvent->uiParams[ 0 ];
}
}
}
return( GAME_SCREEN );
}
UINT32 UIHandlePositionMenu( UI_EVENT *pUIEvent )
{
return( GAME_SCREEN );
}
UINT32 UIHandleAOnTerrain( UI_EVENT *pUIEvent )
{
INT32 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->aiData.ubPendingAction == NO_PENDING_ACTION )
{
// Check if we have a shot waiting!
if ( gUITargetShotWaiting )
{
guiPendingOverrideEvent = CA_MERC_SHOOT;
}
if ( !gUITargetReady )
{
// Move to proper stance + direction!
// Convert our grid-not into an XY
// ConvertGridNoToXY( sMapPos, &sTargetXPos, &sTargetYPos );
// Ready weapon
// pSoldier->SoldierReadyWeapon(sTargetXPos, sTargetYPos, FALSE );
gUITargetReady = TRUE;
}
}
else
{
gUITargetReady = FALSE;
}
}
}
return( GAME_SCREEN );
}
UINT32 UIHandleMChangeToAction( UI_EVENT *pUIEvent )
{
gUITargetShotWaiting = FALSE;
EndPhysicsTrajectoryUI( );
//guiNewUICursor = CONFIRM_MOVE_UICURSOR;
return( GAME_SCREEN );
}
UINT32 UIHandleMChangeToHandMode( UI_EVENT *pUIEvent )
{
ErasePath( FALSE );
return( GAME_SCREEN );
}
UINT32 UIHandleAChangeToMove( UI_EVENT *pUIEvent )
{
// Set merc glow back to normal
// ( could have been set when in target cursor )
SetMercGlowNormal( );
// gsOutOfRangeGridNo = NOWHERE;
gfPlotNewMovement = TRUE;
return( GAME_SCREEN );
}
UINT32 UIHandleCWait( UI_EVENT *pUIEvent )
{
INT32 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, sMapPos, 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 )
{
INT32 usMapPos;
SOLDIERTYPE *pSoldier;
INT32 sDestGridNo;
INT32 sActionGridNo;
STRUCTURE *pStructure;
UINT8 ubDirection = 0xff;
BOOLEAN fAllMove;
INT8 bLoop;
LEVELNODE *pIntTile;
INT32 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->flags.fMercAsleep )
{
// If we can't be controlled, returninvalid...
if ( pSoldier->flags.uiStatusFlags & SOLDIER_ROBOT )
{
if ( !pSoldier->CanRobotBeControlled( ) )
{
continue;
}
}
pSoldier->AdjustNoAPToFinishMove( FALSE );
fOldFastMove = pSoldier->flags.fUIMovementFast;
if ( fAllMove == 2 )
{
pSoldier->flags.fUIMovementFast = TRUE;
pSoldier->usUIMovementMode = RUNNING;
}
else
{
pSoldier->flags.fUIMovementFast = FALSE;
pSoldier->usUIMovementMode = pSoldier->GetMoveStateBasedOnStance( gAnimControl[ pSoldier->usAnimState ].ubEndHeight );
}
// Remove any previous actions
pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION;
//if ( !( gTacticalStatus.uiFlags & INCOMBAT ) && ( gAnimControl[ pSoldier->usAnimState ].uiFlags & ANIM_MOVING ) )
//{
// pSoldier->sRTPendingMovementGridNo = sMapPos;
// pSoldier->usRTPendingMovementAnim = pSoldier->usUIMovementMode;
//}
//else
if ( pSoldier->EVENT_InternalGetNewSoldierPath( usMapPos, pSoldier->usUIMovementMode, TRUE, FALSE ) )
{
pSoldier->InternalDoMercBattleSound( BATTLE_SOUND_OK1, BATTLE_SND_LOWER_VOLUME );
}
else
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, TacticalStr[ NO_PATH_FOR_MERC ], pSoldier->GetName() );
}
pSoldier->flags.fUIMovementFast = fOldFastMove;
}
}
gfGetNewPathThroughPeople = FALSE;
// RESET MOVE FAST FLAG
SetConfirmMovementModeCursor( pSoldier, TRUE );
gfUIAllMoveOn = 0;
}
else
{
// Get soldier
if ( GetSoldier( &pSoldier, gusSelectedSoldier ) )
{
// CHRISL: This block should only run if we're running in the new inventory system
if((UsingNewInventorySystem() == true))
{
// CHRISL: If we're in combat and zipper is active, don't allow movement
if((gTacticalStatus.uiFlags & INCOMBAT) && pSoldier->flags.ZipperFlag)
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, NewInvMessage[NIV_ZIPPER_NO_MOVE] );
return( GAME_SCREEN );
}
// CHRISL: If we're not in combat but the zipper is active and we're moving, deactivate the zipper
if(!(gTacticalStatus.uiFlags & INCOMBAT) && pSoldier->flags.ZipperFlag)
{
pSoldier->flags.ZipperFlag=FALSE;
RenderBackpackButtons(ACTIVATE_BUTTON);
}
}
// FOR REALTIME - DO MOVEMENT BASED ON STANCE!
if ( ( gTacticalStatus.uiFlags & REALTIME ) || !( gTacticalStatus.uiFlags & INCOMBAT ) )
{
pSoldier->usUIMovementMode = pSoldier->GetMoveStateBasedOnStance( 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->flags.fUIMovementFast = FALSE;
}
//StartLooseCursor( sMapPos, 0 );
}
if ( gTacticalStatus.fAtLeastOneGuyOnMultiSelect && pIntTile == NULL )
{
HandleMultiSelectionMove( sDestGridNo );
}
else
{
if ( gUIUseReverse )
{
pSoldier->bReverse = TRUE;
}
else
{
pSoldier->bReverse = FALSE;
}
// Remove any previous actions
pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION;
{
pSoldier->EVENT_InternalGetNewSoldierPath( sDestGridNo, pSoldier->usUIMovementMode , TRUE, pSoldier->flags.fNoAPToFinishMove );
}
if ( pSoldier->pathing.usPathDataSize > 5 )
{
pSoldier->DoMercBattleSound( BATTLE_SOUND_OK1 );
}
// HANDLE ANY INTERACTIVE OBJECTS HERE!
if ( pIntTile != NULL )
{
StartInteractiveObject( sIntTileGridNo, pStructure->usStructureID, pSoldier, ubDirection );
}
}
}
}
}
return( GAME_SCREEN );
}
UINT32 UIHandleMCycleMoveAll( UI_EVENT *pUIEvent )
{
SOLDIERTYPE *pSoldier;
if ( !GetSoldier( &pSoldier, gusSelectedSoldier ) )
{
return( GAME_SCREEN );
}
if ( gfUICanBeginAllMoveCycle )
{
gfUIAllMoveOn = TRUE;
gfUICanBeginAllMoveCycle = FALSE;
}
return( GAME_SCREEN );
}
UINT32 UIHandleMCycleMovement( UI_EVENT *pUIEvent )
{
SOLDIERTYPE *pSoldier;
BOOLEAN fGoodMode = FALSE;
if ( !GetSoldier( &pSoldier, gusSelectedSoldier ) )
{
return( GAME_SCREEN );
}
gfUIAllMoveOn = FALSE;
if ( pSoldier->ubBodyType == ROBOTNOWEAPON )
{
pSoldier->usUIMovementMode = WALKING;
gfPlotNewMovement = TRUE;
return( GAME_SCREEN );
}
do
{
// Cycle gmovement state
if ( pSoldier->usUIMovementMode == RUNNING )
{
pSoldier->usUIMovementMode = WALKING;
if ( IsValidMovementMode( pSoldier, WALKING ) )
{
fGoodMode = TRUE;
}
}
else if ( pSoldier->usUIMovementMode == WALKING )
{
pSoldier->usUIMovementMode = SWATTING;
if ( IsValidMovementMode( pSoldier, SWATTING ) )
{
fGoodMode = TRUE;
}
}
else if ( pSoldier->usUIMovementMode == SWATTING )
{
pSoldier->usUIMovementMode = CRAWLING;
if ( IsValidMovementMode( pSoldier, CRAWLING ) && IsValidStance(pSoldier, ANIM_PRONE) )
{
fGoodMode = TRUE;
}
}
else if ( pSoldier->usUIMovementMode == CRAWLING )
{
pSoldier->flags.fUIMovementFast = 1;
pSoldier->usUIMovementMode = RUNNING;
if ( IsValidMovementMode( pSoldier, RUNNING ) )
{
fGoodMode = TRUE;
}
}
} while( fGoodMode != TRUE );
gfPlotNewMovement = TRUE;
return( GAME_SCREEN );
}
UINT32 UIHandleCOnTerrain( UI_EVENT *pUIEvent )
{
return( GAME_SCREEN );
}
UINT32 UIHandleMAdjustStanceMode( UI_EVENT *pUIEvent )
{
SOLDIERTYPE *pSoldier;
INT32 iPosDiff;
static UINT16 gusAnchorMouseY;
static UINT16 usOldMouseY;
static BOOLEAN ubNearHeigherLevel;
static BOOLEAN ubNearLowerLevel;
static UINT8 ubUpHeight, ubDownDepth;
static UINT32 uiOldShowUPDownArrows;
INT8 bNewDirection;
// Change cusror to normal
guiNewUICursor = NO_UICURSOR;
if ( pUIEvent->fFirstTime )
{
gusAnchorMouseY = gusMouseYPos;
usOldMouseY = gusMouseYPos;
ubNearHeigherLevel = FALSE;
ubNearLowerLevel = FALSE;
guiShowUPDownArrows = ARROWS_SHOW_DOWN_BESIDE | ARROWS_SHOW_UP_BESIDE;
uiOldShowUPDownArrows = guiShowUPDownArrows;
gbAdjustStanceDiff = 0;
gbClimbID = 0;
gfIgnoreScrolling = TRUE;
// Get soldier current height of animation
if ( GetSoldier( &pSoldier, gusSelectedSoldier ) )
{
// IF we are on a basic level...(temp)
if ( pSoldier->pathing.bLevel == 0 )
{
if ( FindHeigherLevel( pSoldier, pSoldier->sGridNo, pSoldier->ubDirection, &bNewDirection ) )
{
ubNearHeigherLevel = TRUE;
}
}
// IF we are higher...
if ( pSoldier->pathing.bLevel > 0 )
{
if ( FindLowerLevel( pSoldier, pSoldier->sGridNo, pSoldier->ubDirection, &bNewDirection ) )
{
ubNearLowerLevel = TRUE;
}
}
switch( gAnimControl[ pSoldier->usAnimState ].ubEndHeight )
{
case ANIM_STAND:
if ( ubNearHeigherLevel )
{
ubUpHeight = 1;
ubDownDepth = 2;
}
else if ( ubNearLowerLevel )
{
ubUpHeight = 0;
ubDownDepth = 3;
}
else
{
ubUpHeight = 0;
ubDownDepth = 2;
}
break;
case ANIM_CROUCH:
if ( ubNearHeigherLevel )
{
ubUpHeight = 2;
ubDownDepth = 1;
}
else if ( ubNearLowerLevel )
{
ubUpHeight = 1;
ubDownDepth = 2;
}
else
{
ubUpHeight = 1;
ubDownDepth = 1;
}
break;
case ANIM_PRONE:
if ( ubNearHeigherLevel )
{
ubUpHeight = 3;
ubDownDepth = 0;
}
else if ( ubNearLowerLevel )
{
ubUpHeight = 2;
ubDownDepth = 1;
}
else
{
ubUpHeight = 2;
ubDownDepth = 0;
}
break;
}
}
}
// Check if delta X has changed alot since last time
iPosDiff = abs( (INT32)( usOldMouseY - gusMouseYPos) );
//guiShowUPDownArrows = ARROWS_SHOW_DOWN_BESIDE | ARROWS_SHOW_UP_BESIDE;
guiShowUPDownArrows = uiOldShowUPDownArrows;
{
if ( gusAnchorMouseY > gusMouseYPos )
{
// Get soldier
if ( GetSoldier( &pSoldier, gusSelectedSoldier ) )
{
if ( iPosDiff < GO_MOVE_ONE && ubUpHeight >= 1 )
{
// Change arrows to move down arrow + show
//guiShowUPDownArrows = ARROWS_SHOW_UP_ABOVE_Y;
guiShowUPDownArrows = ARROWS_SHOW_DOWN_BESIDE | ARROWS_SHOW_UP_BESIDE;
gbAdjustStanceDiff = 0;
gbClimbID = 0;
}
else if ( iPosDiff > GO_MOVE_ONE && iPosDiff < GO_MOVE_TWO && ubUpHeight >= 1 )
{
//guiShowUPDownArrows = ARROWS_SHOW_UP_ABOVE_G;
if ( ubUpHeight == 1 && ubNearHeigherLevel )
{
guiShowUPDownArrows = ARROWS_SHOW_UP_ABOVE_CLIMB;
gbClimbID = 1;
}
else
{
guiShowUPDownArrows = ARROWS_SHOW_UP_ABOVE_Y;
gbClimbID = 0;
}
gbAdjustStanceDiff = 1;
}
else if ( iPosDiff >= GO_MOVE_TWO && iPosDiff < GO_MOVE_THREE && ubUpHeight >= 2 )
{
if ( ubUpHeight == 2 && ubNearHeigherLevel )
{
guiShowUPDownArrows = ARROWS_SHOW_UP_ABOVE_CLIMB;
gbClimbID = 1;
}
else
{
guiShowUPDownArrows = ARROWS_SHOW_UP_ABOVE_YY;
gbClimbID = 0;
}
gbAdjustStanceDiff = 2;
}
else if ( iPosDiff >= GO_MOVE_THREE && ubUpHeight >= 3 )
{
if ( ubUpHeight == 3 && ubNearHeigherLevel )
{
guiShowUPDownArrows = ARROWS_SHOW_UP_ABOVE_CLIMB;
gbClimbID = 1;
}
}
}
}
if ( gusAnchorMouseY < gusMouseYPos )
{
// Get soldier
if ( GetSoldier( &pSoldier, gusSelectedSoldier ) )
{
if ( iPosDiff < GO_MOVE_ONE && ubDownDepth >= 1 )
{
// Change arrows to move down arrow + show
//guiShowUPDownArrows = ARROWS_SHOW_DOWN_BELOW_Y;
guiShowUPDownArrows = ARROWS_SHOW_DOWN_BESIDE | ARROWS_SHOW_UP_BESIDE;
gbAdjustStanceDiff = 0;
gbClimbID = 0;
}
else if ( iPosDiff >= GO_MOVE_ONE && iPosDiff < GO_MOVE_TWO && ubDownDepth >= 1 )
{
// guiShowUPDownArrows = ARROWS_SHOW_DOWN_BELOW_G;
if ( ubDownDepth == 1 && ubNearLowerLevel )
{
guiShowUPDownArrows = ARROWS_SHOW_DOWN_CLIMB;
gbClimbID = -1;
}
else
{
guiShowUPDownArrows = ARROWS_SHOW_DOWN_BELOW_Y;
gbClimbID = 0;
}
gbAdjustStanceDiff = -1;
}
else if ( iPosDiff > GO_MOVE_TWO && iPosDiff < GO_MOVE_THREE && ubDownDepth >= 2 )
{
//guiShowUPDownArrows = ARROWS_SHOW_DOWN_BELOW_GG;
if ( ubDownDepth == 2 && ubNearLowerLevel )
{
guiShowUPDownArrows = ARROWS_SHOW_DOWN_CLIMB;
gbClimbID = -1;
}
else
{
guiShowUPDownArrows = ARROWS_SHOW_DOWN_BELOW_YY;
gbClimbID = 0;
}
gbAdjustStanceDiff = -2;
}
else if ( iPosDiff > GO_MOVE_THREE && ubDownDepth >= 3 )
{
//guiShowUPDownArrows = ARROWS_SHOW_DOWN_BELOW_GG;
if ( ubDownDepth == 3 && ubNearLowerLevel )
{
guiShowUPDownArrows = ARROWS_SHOW_DOWN_CLIMB;
gbClimbID = -1;
}
}
}
}
}
uiOldShowUPDownArrows = guiShowUPDownArrows;
return( GAME_SCREEN );
}
UINT32 UIHandleAChangeToConfirmAction( UI_EVENT *pUIEvent )
{
SOLDIERTYPE *pSoldier;
if ( GetSoldier( &pSoldier, gusSelectedSoldier ) )
{
HandleLeftClickCursor( pSoldier );
}
ResetBurstLocations( );
return( GAME_SCREEN );
}
UINT32 UIHandleCAOnTerrain( UI_EVENT *pUIEvent )
{
SOLDIERTYPE *pSoldier;
INT32 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, INT32 usMapPos )
{
INT32 iHandleReturn;
INT32 sTargetGridNo;
INT8 bTargetLevel;
UINT16 usItem;
LEVELNODE* pIntNode;
STRUCTURE* pStructure;
INT32 sGridNo, sNewGridNo;
UINT8 ubItemCursor;
// get cursor
ubItemCursor = GetActionModeCursor( pSoldier );
OBJECTTYPE* pObj = pSoldier->GetUsedWeapon(&pSoldier->inv[HANDPOS]);
usItem = pSoldier->GetUsedWeaponNumber(&pSoldier->inv[HANDPOS]);
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;
}
}
// ATE: Check if we are targeting an interactive tile, and adjust gridno accordingly...
pIntNode = GetCurInteractiveTileGridNoAndStructure( &sGridNo, &pStructure );
if ( pTargetSoldier != NULL )
{
sTargetGridNo = pTargetSoldier->sGridNo;
bTargetLevel = pTargetSoldier->pathing.bLevel;
}
else
{
sTargetGridNo = usMapPos;
bTargetLevel = (INT8)gsInterfaceLevel;
if ( pIntNode != NULL )
{
// Change gridno....
sTargetGridNo = sGridNo;
}
}
// In realtime mode we cannot aim. Assume that max allowed aiming levels will be used.
if ( gTacticalStatus.uiFlags & REALTIME || !( gTacticalStatus.uiFlags & INCOMBAT ) )
pSoldier->aiData.bAimTime = AllowedAimingLevels(pSoldier, sGridNo);
else
// Set aim time to one in UI
pSoldier->aiData.bAimTime = (pSoldier->aiData.bShownAimTime );
// here, change gridno if we're targeting ourselves....
if ( pIntNode != NULL )
{
// Are we in the same gridno?
if ( sGridNo == pSoldier->sGridNo && ubItemCursor != AIDCURS )
{
// Get orientation....
switch( pStructure->ubWallOrientation )
{
case OUTSIDE_TOP_LEFT:
case INSIDE_TOP_LEFT:
sNewGridNo = NewGridNo( sGridNo, DirectionInc( SOUTH ) );
break;
case OUTSIDE_TOP_RIGHT:
case INSIDE_TOP_RIGHT:
sNewGridNo = NewGridNo( sGridNo, DirectionInc( EAST ) );
break;
default:
sNewGridNo = sGridNo;
}
// Set target gridno to this one...
sTargetGridNo = sNewGridNo;
// now set target cube height
// CJC says to hardcode this value :)
pSoldier->bTargetCubeLevel = 2;
}
else
{
// ATE: Refine this a bit - if we have nobody as a target...
if ( pTargetSoldier == NULL )
{
sTargetGridNo = sGridNo;
}
}
}
// Cannot be fire if we are already in a fire animation....
// this is to stop the shooting trigger/happy duded from contiously pressing fire...
if ( !(gTacticalStatus.uiFlags & INCOMBAT) )
{
if ( gAnimControl[ pSoldier->usAnimState ].uiFlags & ANIM_FIRE )
{
return;
}
}
// If in turn-based mode - return to movement
if ( ( gTacticalStatus.uiFlags & INCOMBAT ) )
{
// Reset some flags for cont move...
pSoldier->pathing.sFinalDestination = pSoldier->sGridNo;
pSoldier->bGoodContPath = FALSE;
// guiPendingOverrideEvent = A_CHANGE_TO_MOVE;
}
if (pSoldier->bWeaponMode == WM_ATTACHED_GL || pSoldier->bWeaponMode == WM_ATTACHED_GL_BURST || pSoldier->bWeaponMode == WM_ATTACHED_GL_AUTO )
{
iHandleReturn = HandleItem( pSoldier, sTargetGridNo, bTargetLevel, GetAttachedGrenadeLauncher(pObj), TRUE );
}
else
{
iHandleReturn = HandleItem( pSoldier, sTargetGridNo, bTargetLevel, 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 );
}
}
// SANDRO - added function
void SurgeryRequesterCallback( UINT8 bExitValue )
{
if( bExitValue == MSG_BOX_RETURN_YES )
{
//gpRequesterMerc->ubSurgeryApprovalMerc = gpRequesterTargetMerc->ubID;
gTacticalStatus.ubLastRequesterSurgeryTargetID = gpRequesterTargetMerc->ubID;
UIHandleMercAttack( gpRequesterMerc , gpRequesterTargetMerc, gsRequesterGridNo );
}
else if( bExitValue == MSG_BOX_RETURN_NO )
{
gTacticalStatus.ubLastRequesterSurgeryTargetID = NOBODY;
if (!gpRequesterTargetMerc->bBleeding && gpRequesterTargetMerc->stats.bLife >= OKLIFE)
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, TacticalStr[ CANNOT_NO_NEED_FIRST_AID_STR ], gpRequesterTargetMerc->GetName() );
}
else
{
UIHandleMercAttack( gpRequesterMerc , gpRequesterTargetMerc, gsRequesterGridNo );
}
}
}
UINT32 UIHandleCAMercShoot( UI_EVENT *pUIEvent )
{
INT32 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
&& !ItemCanBeAppliedToOthers( pSoldier->inv[ HANDPOS ].usItem )
&& 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->GetName() );
DoMessageBox( MSG_BOX_BASIC_STYLE, zStr, GAME_SCREEN, ( UINT8 )MSG_BOX_FLAG_YESNO, AttackRequesterCallback, NULL );
}
////////////////////////////////////////////////////////////////////////////////////////////////
// SANDRO - Should we ask if we really want to do the surgery?
else if (Item[ pSoldier->inv[ HANDPOS ].usItem ].medicalkit && (NUM_SKILL_TRAITS( pSoldier, DOCTOR_NT ) >= gSkillTraitValues.ubDONumberTraitsNeededForSurgery)
&& (pTSoldier->bTeam == OUR_TEAM || pTSoldier->bTeam == MILITIA_TEAM)
&& (IS_MERC_BODY_TYPE( pTSoldier ) || IS_CIV_BODY_TYPE( pTSoldier ))
&& gGameOptions.fNewTraitSystem && pTSoldier->iHealableInjury >= 100
&& pTSoldier->ubID != pSoldier->ubID && gTacticalStatus.ubLastRequesterSurgeryTargetID != pTSoldier->ubID )
{
CHAR16 zStr[200];
gpRequesterMerc = pSoldier;
gpRequesterTargetMerc = pTSoldier;
gsRequesterGridNo = usMapPos;
fDidRequester = TRUE;
if (pTSoldier->bBleeding)
swprintf( zStr, New113Message[ MSG113_DO_WE_WANT_SURGERY_FIRST ], pTSoldier->GetName(), (pTSoldier->iHealableInjury * (gSkillTraitValues.ubDOSurgeryHealPercentBase + gSkillTraitValues.ubDOSurgeryHealPercentOnTop * NUM_SKILL_TRAITS( pSoldier, DOCTOR_NT )) / 10000) );
else
swprintf( zStr, New113Message[ MSG113_DO_WE_WANT_SURGERY ], pTSoldier->GetName(), (pTSoldier->iHealableInjury * (gSkillTraitValues.ubDOSurgeryHealPercentBase + gSkillTraitValues.ubDOSurgeryHealPercentOnTop * NUM_SKILL_TRAITS( pSoldier, DOCTOR_NT )) / 10000) );
DoMessageBox( MSG_BOX_BASIC_STYLE, zStr, GAME_SCREEN, ( UINT8 )MSG_BOX_FLAG_YESNO, SurgeryRequesterCallback, NULL );
}
////////////////////////////////////////////////////////////////////////////////////////////////
}
if ( !fDidRequester )
{
UIHandleMercAttack( pSoldier, pTSoldier, usMapPos );
}
}
}
return( GAME_SCREEN );
}
UINT32 UIHandleAEndAction( UI_EVENT *pUIEvent )
{
SOLDIERTYPE *pSoldier;
INT16 sTargetXPos, sTargetYPos;
INT32 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
pSoldier->SoldierReadyWeapon( sTargetXPos, sTargetYPos, TRUE, FALSE );
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 )
{
INT32 usMapPos;
// Get gridno at this location
if( !GetMouseMapPos( &usMapPos) )
{
return( GAME_SCREEN );
}
if ( !UIHandleOnMerc( TRUE ) )
{
// Check if dest is OK
//if ( !NewOKDestination( sMapPos, FALSE ) || IsRoofVisible( sMapPos ) )
////{
// guiNewUICursor = CANNOT_MOVE_UICURSOR;
//}
//else
{
guiNewUICursor = NORMAL_SNAPUICURSOR;
}
}
return( GAME_SCREEN );
}
UINT32 UIHandleIChangeToIdle( UI_EVENT *pUIEvent )
{
return( GAME_SCREEN );
}
UINT32 UIHandlePADJAdjustStance( UI_EVENT *pUIEvent )
{
SOLDIERTYPE *pSoldier;
UINT8 ubNewStance;
guiShowUPDownArrows = ARROWS_HIDE_UP | ARROWS_HIDE_DOWN;
gfIgnoreScrolling = FALSE;
if ( gusSelectedSoldier != NOBODY && gbAdjustStanceDiff != 0 )
{
// Get soldier
if ( GetSoldier( &pSoldier, gusSelectedSoldier ) )
{
ubNewStance = GetAdjustedAnimHeight( gAnimControl[ pSoldier->usAnimState ].ubEndHeight, gbAdjustStanceDiff );
if ( gbClimbID == 1 )
{
pSoldier->BeginSoldierClimbUpRoof( );
}
else if ( gbClimbID == -1 )
{
pSoldier->BeginSoldierClimbDownRoof( );
}
else
{
// Set state to result
UIHandleSoldierStanceChange( pSoldier->ubID, ubNewStance );
}
// Once we have APs, we can safely reset nomove flag!
// AdjustNoAPToFinishMove( pSoldier, FALSE );
}
}
return( GAME_SCREEN );
}
UINT8 GetAdjustedAnimHeight( UINT8 ubAnimHeight, INT8 bChange )
{
UINT8 ubNewAnimHeight = ubAnimHeight;
if ( ubAnimHeight == ANIM_STAND )
{
if ( bChange == -1 )
{
ubNewAnimHeight = ANIM_CROUCH;
}
if ( bChange == -2 )
{
ubNewAnimHeight = ANIM_PRONE;
}
if ( bChange == 1 )
{
ubNewAnimHeight = 50;
}
}
else if ( ubAnimHeight == ANIM_CROUCH )
{
if ( bChange == 1 )
{
ubNewAnimHeight = ANIM_STAND;
}
if ( bChange == -1 )
{
ubNewAnimHeight = ANIM_PRONE;
}
if ( bChange == -2 )
{
ubNewAnimHeight = 55;
}
}
else if ( ubAnimHeight == ANIM_PRONE )
{
if ( bChange == -1 )
{
ubNewAnimHeight = 55;
}
if ( bChange == 1 )
{
ubNewAnimHeight = ANIM_CROUCH;
}
if ( bChange == 2 )
{
ubNewAnimHeight = ANIM_STAND;
}
}
return( ubNewAnimHeight );
}
void HandleObjectHighlighting( )
{
SOLDIERTYPE *pSoldier;
INT32 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;
INT32 usMapPos;
INT32 sTargetGridNo;
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, (INT16)(pSoldier->aiData.bShownAimTime ) );
if ( EnoughPoints( pSoldier, sAPCost, 0, TRUE ) )
{
return( TRUE );
}
else
{
// Play curse....
pSoldier->DoMercBattleSound( BATTLE_SOUND_CURSE1 );
}
}
}
}
return( FALSE );
}
BOOLEAN SelectedMercCanAffordMove( )
{
SOLDIERTYPE *pSoldier;
UINT16 sAPCost = 0;
INT32 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->pathing.bLevel == 0 )
{
// See if we are not in a building!
if ( FindHeigherLevel( pSoldier, pSoldier->sGridNo, pSoldier->ubDirection, &bNewDirection ) )
{
*pfGoUp = TRUE;
}
}
// IF we are higher...
if ( pSoldier->pathing.bLevel > 0 )
{
if ( FindLowerLevel( pSoldier, pSoldier->sGridNo, pSoldier->ubDirection, &bNewDirection ) )
{
*pfGoDown = TRUE;
}
}
}
void RemoveTacticalCursor( )
{
guiNewUICursor = NO_UICURSOR;
ErasePath( TRUE );
}
UINT32 UIHandlePOPUPMSG( UI_EVENT *pUIEvent )
{
return( GAME_SCREEN );
}
UINT32 UIHandleHCOnTerrain( UI_EVENT *pUIEvent )
{
INT32 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 (!TileIsOutOfBounds(gsOverItemsGridNo) && ( 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;
INT32 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->flags.fNoAPToFinishMove )
{
guiShowUPDownArrows = ARROWS_SHOW_DOWN_BESIDE | ARROWS_SHOW_UP_BESIDE;
}
}
}
else
{
//if ( ( uiMercFlags & ONDUTY_MERC ) && !( uiMercFlags & NOINTERRUPT_MERC ) )
if ( !( uiMercFlags & NOINTERRUPT_MERC ) )
{
// Add highlight to guy in interface.c
gfUIHandleSelection = NONSELECTED_GUY_SELECTION;
}
else
{
gfUIHandleSelection = ENEMY_GUY_SELECTION;
gfUIHandleSelectionAboveGuy = TRUE;
}
}
}
}
// If not dead, show above guy!
if ( !( uiMercFlags & DEAD_MERC ) )
{
if ( fMovementMode )
{
// ERASE PATH
ErasePath( TRUE );
// Show cursor with highlight on selected merc
guiNewUICursor = NO_UICURSOR;
gsSelectedGridNo = pSoldier->sGridNo;
gsSelectedLevel = pSoldier->pathing.bLevel;
}
gsSelectedGuy = usSoldierIndex;
gfUIHandleSelectionAboveGuy = TRUE;
}
}
else if ( ( ( uiMercFlags & ENEMY_MERC ) || ( uiMercFlags & NEUTRAL_MERC ) ) && ( uiMercFlags & VISIBLE_MERC ) )
{
// ATE: If we are a vehicle, let the mouse cursor be a wheel...
if ( ( OK_ENTERABLE_VEHICLE( pSoldier ) ) )
{
return( FALSE );
}
else
{
if ( fMovementMode )
{
// Check if this guy is on the enemy team....
if ( !pSoldier->aiData.bNeutral && (pSoldier->bSide != gbPlayerNum ) )
{
gUIActionModeChangeDueToMouseOver = TRUE;
guiPendingOverrideEvent = M_CHANGE_TO_ACTION;
// Return FALSE
return( FALSE );
}
else
{
// ERASE PATH
ErasePath( TRUE );
// Show cursor with highlight on selected merc
guiNewUICursor = NO_UICURSOR;
// Show cursor with highlight
gfUIHandleSelection = ENEMY_GUY_SELECTION;
gsSelectedGridNo = pSoldier->sGridNo;
gsSelectedLevel = pSoldier->pathing.bLevel;
}
}
gfUIHandleSelectionAboveGuy = TRUE;
gsSelectedGuy = usSoldierIndex;
}
}
else
{
if ( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE )
{
return( FALSE );
}
}
}
else
{
gfIgnoreOnSelectedGuy = FALSE;
return( FALSE );
}
return( TRUE );
}
UINT32 UIHandleILoadLevel( UI_EVENT *pUIEvent )
{
return( INIT_SCREEN );
}
UINT32 UIHandleISoldierDebug( UI_EVENT *pUIEvent )
{
// Use soldier display pages
SetDebugRenderHook( (RENDER_HOOK)DebugSoldierPage1, 0 );
SetDebugRenderHook( (RENDER_HOOK)DebugSoldierPage2, 1 );
SetDebugRenderHook( (RENDER_HOOK)DebugSoldierPage3, 2 );
SetDebugRenderHook( (RENDER_HOOK)DebugSoldierPage4, 3 );
gCurDebugPage = 1;
return( DEBUG_SCREEN );
}
UINT32 UIHandleILOSDebug( UI_EVENT *pUIEvent )
{
SetDebugRenderHook( (RENDER_HOOK)DebugStructurePage1, 0 );
return( DEBUG_SCREEN );
}
UINT32 UIHandleILevelNodeDebug( UI_EVENT *pUIEvent )
{
SetDebugRenderHook( (RENDER_HOOK)DebugLevelNodePage, 0 );
return( DEBUG_SCREEN );
}
UINT32 UIHandleIETOnTerrain( UI_EVENT *pUIEvent )
{
//guiNewUICursor = CANNOT_MOVE_UICURSOR;
guiNewUICursor = NO_UICURSOR;
SetCurrentCursorFromDatabase( VIDEO_NO_CURSOR );
return( GAME_SCREEN );
}
void UIHandleSoldierStanceChange( UINT8 ubSoldierID, INT8 bNewStance )
{
SOLDIERTYPE *pSoldier;
pSoldier = MercPtrs[ ubSoldierID ];
// Is this a valid stance for our position?
if ( !IsValidStance( pSoldier, bNewStance ) )
{
if ( pSoldier->bCollapsed && pSoldier->bBreath < OKBREATH )
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, gzLateLocalizedString[ 4 ], pSoldier->GetName() );
}
else
{
if ( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE )
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, TacticalStr[ VEHICLES_NO_STANCE_CHANGE_STR ] );
}
else if ( pSoldier->flags.uiStatusFlags & SOLDIER_ROBOT )
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, TacticalStr[ ROBOT_NO_STANCE_CHANGE_STR ] );
}
else
{
if ( pSoldier->bCollapsed )
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, pMessageStrings[ MSG_CANT_CHANGE_STANCE ], pSoldier->GetName() );
}
else
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, TacticalStr[ CANNOT_STANCE_CHANGE_STR ], pSoldier->GetName() );
}
}
}
return;
}
// IF turn-based - adjust stance now!
if ( gTacticalStatus.uiFlags & TURNBASED && ( gTacticalStatus.uiFlags & INCOMBAT ) )
{
pSoldier->flags.bTurningFromPronePosition = TURNING_FROM_PRONE_OFF;
// Check if we have enough APS
if ( SoldierCanAffordNewStance( pSoldier, bNewStance ) )
{
// Adjust stance
//pSoldier->ChangeSoldierStance( bNewStance );
SendChangeSoldierStanceEvent( pSoldier, bNewStance );
pSoldier->pathing.sFinalDestination = pSoldier->sGridNo;
pSoldier->bGoodContPath = FALSE;
//dnl ch71 180913 when we go to crouch or prone for now there is no alternative fire mode option
if(pSoldier->bScopeMode == USE_ALT_WEAPON_HOLD && bNewStance != ANIM_STAND)
{
ChangeScopeMode(pSoldier, 0);
ManLooksForOtherTeams(pSoldier);
}
}
else
return;
}
// If realtime- change walking animation!
if ( ( gTacticalStatus.uiFlags & REALTIME ) || !( gTacticalStatus.uiFlags & INCOMBAT ) )
{
// If we are stationary, do something else!
if ( gAnimControl[ pSoldier->usAnimState ].uiFlags & ANIM_STATIONARY )
{
// Change stance normally
SendChangeSoldierStanceEvent( pSoldier, bNewStance );
}
else
{
// Pick moving animation based on stance
// LOCK VARIBLE FOR NO UPDATE INDEX...
pSoldier->usUIMovementMode = pSoldier->GetMoveStateBasedOnStance( bNewStance );
pSoldier->ubDesiredHeight = NO_DESIRED_HEIGHT;
#if 0
if ( pSoldier->usUIMovementMode == CRAWLING && gAnimControl[ pSoldier->usAnimState ].ubEndHeight != ANIM_PRONE )
{
pSoldier->usDontUpdateNewGridNoOnMoveAnimChange = LOCKED_NO_NEWGRIDNO;
pSoldier->pathing.bPathStored = FALSE;
}
else
#endif
{
pSoldier->usDontUpdateNewGridNoOnMoveAnimChange = 1;
}
pSoldier->ChangeSoldierState( pSoldier->usUIMovementMode, 0, FALSE );
}
}
// Set UI value for soldier
SetUIbasedOnStance( pSoldier, bNewStance );
gfUIStanceDifferent = TRUE;
// ATE: If we are being serviced...stop...
// pSoldier->InternalReceivingSoldierCancelServices(, FALSE );
pSoldier->InternalGivingSoldierCancelServices( FALSE );
//gfPlotNewMovement = TRUE;
}
UINT32 UIHandleIETEndTurn( UI_EVENT *pUIEvent )
{
return( GAME_SCREEN );
}
UINT32 UIHandleIGotoDemoMode( UI_EVENT *pUIEvent )
{
return( EnterTacticalDemoMode() );
}
UINT32 UIHandleILoadFirstLevel( UI_EVENT *pUIEvent )
{
gubCurrentScene = 0;
return( INIT_SCREEN );
}
UINT32 UIHandleILoadSecondLevel( UI_EVENT *pUIEvent )
{
gubCurrentScene = 1;
return( INIT_SCREEN );
}
UINT32 UIHandleILoadThirdLevel( UI_EVENT *pUIEvent )
{
gubCurrentScene = 2;
return( INIT_SCREEN );
}
UINT32 UIHandleILoadFourthLevel( UI_EVENT *pUIEvent )
{
gubCurrentScene = 3;
return( INIT_SCREEN );
}
UINT32 UIHandleILoadFifthLevel( UI_EVENT *pUIEvent )
{
gubCurrentScene = 4;
return( INIT_SCREEN );
}
void GetCursorMovementFlags( UINT32 *puiCursorFlags )
{
INT32 usMapPos;
INT16 sXPos, sYPos;
static BOOLEAN fStationary = FALSE;
static UINT16 usOldMouseXPos = 32000;
static UINT16 usOldMouseYPos = 32000;
static INT32 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, INT32 usMapPos, UINT32 uiFlags )
{
BOOLEAN fSetCursor = FALSE;
static UINT16 usTargetID = NOBODY;
static BOOLEAN fTargetFound = FALSE;
BOOLEAN fTargetFoundAndLookingForOne = FALSE;
// Determine if we can afford!
if ( !EnoughPoints( pSoldier, gsCurrentActionPoints, 0, FALSE ) )
{
gfUIDisplayActionPointsInvalid = TRUE;
}
// Check if we're stationary
if ( ( ( gTacticalStatus.uiFlags & REALTIME ) || !( gTacticalStatus.uiFlags & INCOMBAT ) ) || ( ( gAnimControl[ pSoldier->usAnimState ].uiFlags & ANIM_STATIONARY ) || pSoldier->flags.fNoAPToFinishMove ) || pSoldier->ubID >= MAX_NUM_SOLDIERS )
{
// If we are targeting a merc for some reason, don't go thorugh normal channels if we are on someone now
if ( uiFlags == MOVEUI_TARGET_MERCS || uiFlags == MOVEUI_TARGET_MERCSFORAID )
{
if ( gfUIFullTargetFound != fTargetFound || usTargetID != gusUIFullTargetID || gfResetUIMovementOptimization )
{
gfResetUIMovementOptimization = FALSE;
// ERASE PATH
ErasePath( TRUE );
// Try and get a path right away
DrawUIMovementPath( pSoldier, 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:
case WALKING_WEAPON_RDY:
case WALKING_DUAL_RDY:
case WALKING_ALTERNATIVE_RDY:
gUIDisplayActionPointsOffY = 10;
gUIDisplayActionPointsOffX = 10;
break;
case RUNNING:
gUIDisplayActionPointsOffY = 15;
gUIDisplayActionPointsOffX = 21;
break;
}
}
}
}
}
}
else
{
// THE MERC IS MOVING
// We're moving, erase path, change cursor
ErasePath( TRUE );
fSetCursor = TRUE;
}
if(pSoldier->bDoAutofire) //reset the autofire bullet count
{
pSoldier->flags.autofireLastStep = FALSE;
pSoldier->bDoAutofire = 1;
}
return( fSetCursor );
}
INT8 DrawUIMovementPath( SOLDIERTYPE *pSoldier, INT32 usMapPos, UINT32 uiFlags )
{
INT16 sAPCost, sBPCost;
INT32 sActionGridNo;
STRUCTURE *pStructure;
UINT8 ubDirection;
// ITEM_POOL *pItemPool;
INT32 sAdjustedGridNo = -1;
INT32 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( pSoldier, sIntTileGridNo, pStructure, &sAPCost, &sBPCost ); // SANDRO - added argument
//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 = APBPConstants[AP_ATTACH_CAN];
sAPCost += UIPlotPath( pSoldier, sActionGridNo, NO_COPYROUTE, fPlot, TEMPORARY, (UINT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints);
if ( sActionGridNo != pSoldier->sGridNo )
{
gfUIHandleShowMoveGrid = TRUE;
gsUIHandleShowMoveGridLocation = sActionGridNo;
}
}
}
else
{
sAPCost += UIPlotPath( pSoldier, sActionGridNo, NO_COPYROUTE, fPlot, TEMPORARY, (UINT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints );
}
}
else if ( uiFlags == MOVEUI_TARGET_REPAIR )
{
// For repair, check if we are over a vehicle, then get gridnot to edge of that vehicle!
if ( IsRepairableStructAtGridNo( usMapPos, &ubMercID ) == 2 )
{
INT32 sNewGridNo;
UINT8 ubDirection;
sNewGridNo = FindGridNoFromSweetSpotWithStructDataFromSoldier( pSoldier, pSoldier->usUIMovementMode, 5, &ubDirection, 0, MercPtrs[ ubMercID ] );
if (!TileIsOutOfBounds(sNewGridNo))
{
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 )
{
INT32 sNewGridNo;
UINT8 ubDirection;
sNewGridNo = FindGridNoFromSweetSpotWithStructDataFromSoldier( pSoldier, pSoldier->usUIMovementMode, 5, &ubDirection, 0, MercPtrs[ ubMercID ] );
if (!TileIsOutOfBounds(sNewGridNo))
{
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_FORTIFICATION )
{
sActionGridNo = FindAdjacentGridEx( pSoldier, usMapPos, &ubDirection, NULL, FALSE, TRUE );
if ( sActionGridNo == -1 )
{
sActionGridNo = usMapPos;
}
sAPCost = GetAPsForMultiTurnAction( pSoldier, MTA_FORTIFY );
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_HANDCUFF )
{
sActionGridNo = FindAdjacentGridEx( pSoldier, usMapPos, &ubDirection, NULL, FALSE, TRUE );
if ( sActionGridNo == -1 )
{
sActionGridNo = usMapPos;
}
sAPCost = GetAPsToHandcuff( 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_APPLYITEM )
{
sActionGridNo = FindAdjacentGridEx( pSoldier, usMapPos, &ubDirection, NULL, FALSE, TRUE );
if ( sActionGridNo == -1 )
{
sActionGridNo = usMapPos;
}
sAPCost = GetAPsToApplyItem( 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_MERCS )
{
INT32 sGotLocation = NOWHERE;
BOOLEAN fGotAdjacent = FALSE;
// Check if we are on a target
if ( gfUIFullTargetFound )
{
INT32 cnt;
INT32 sSpot;
UINT8 ubGuyThere;
for ( cnt = 0; cnt < NUM_WORLD_DIRECTIONS; cnt++ )
{
sSpot = NewGridNo( pSoldier->sGridNo, DirectionInc( (INT8)cnt ) );
// Make sure movement costs are OK....
if ( gubWorldMovementCosts[ sSpot ][ cnt ][ gsInterfaceLevel ] >= TRAVELCOST_BLOCKED )
{
continue;
}
// Check for who is there...
ubGuyThere = WhoIsThere2( sSpot, pSoldier->pathing.bLevel );
if ( ubGuyThere == MercPtrs[ gusUIFullTargetID ]->ubID )
{
// We've got a guy here....
// Who is the one we want......
sGotLocation = sSpot;
sAdjustedGridNo = MercPtrs[ gusUIFullTargetID ]->sGridNo;
ubDirection = ( UINT8 )cnt;
break;
}
}
if (TileIsOutOfBounds(sGotLocation))
{
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 (!TileIsOutOfBounds(sGotLocation))
{
#if 0//dnl ch73 021013 don't add turnover cost if we are moving, in the future this should be calculated by UIPlotPath
sAPCost += MinAPsToAttack( pSoldier, sAdjustedGridNo, TRUE, pSoldier->aiData.bShownAimTime, 0 );
// 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);
#else
sAPCost = UIPlotPath(pSoldier, sGotLocation, NO_COPYROUTE, fPlot, TEMPORARY, (UINT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints);
sAPCost += MinAPsToAttack(pSoldier, sAdjustedGridNo, sAPCost>0?FALSE:TRUE, pSoldier->aiData.bShownAimTime, 0);
#endif
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;
}
/////////////////////////////////////////////////////////////////////////////////////////
// CHANGED BY SANDRO - REDUCE AP COST TO STEAL FOR MARTIAL ARTS AND HAND TO HAND NEW TRAITS
if (MercPtrs[ gusUIFullTargetID ]->bCollapsed && gGameExternalOptions.fEnhancedCloseCombatSystem)
{
sAPCost += (GetBasicAPsToPickupItem( pSoldier )); // stealing from collapsed soldiers is treated differently
}
else if ((HAS_SKILL_TRAIT( pSoldier, MARTIAL_ARTS_NT )) && ( gGameOptions.fNewTraitSystem ))
{
sAPCost += max( 1, (INT16)((APBPConstants[AP_STEAL_ITEM] * (100 - gSkillTraitValues.ubMAReducedAPsToSteal * NUM_SKILL_TRAITS( pSoldier, MARTIAL_ARTS_NT ))/ 100) + 0.5));
}
else
{
sAPCost += APBPConstants[AP_STEAL_ITEM];
}
/////////////////////////////////////////////////////////////////////////////////////////
// CJC August 13 2002: take into account stance in AP prediction
if (!(PTR_STANDING))
{
sAPCost += GetAPsToChangeStance( pSoldier, ANIM_STAND );
}
sAPCost += UIPlotPath( pSoldier, sActionGridNo, NO_COPYROUTE, fPlot, TEMPORARY, (UINT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints);
if ( sActionGridNo != pSoldier->sGridNo )
{
gfUIHandleShowMoveGrid = TRUE;
gsUIHandleShowMoveGridLocation = sActionGridNo;
}
}
}
else if ( uiFlags == MOVEUI_TARGET_BOMB )
{
if(Item[pSoldier->inv[HANDPOS].usItem].mine == 1)
sAPCost += GetAPsToPlantMine( pSoldier );
else
sAPCost += GetAPsToDropBomb( pSoldier );
sAPCost += UIPlotPath( pSoldier, 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( sMapPos, &pItemPool, pSoldier->pathing.bLevel ) )
{
//if ( ITEMPOOL_VISIBLE( pItemPool ) )
{
sActionGridNo = AdjustGridNoForItemPlacement( pSoldier, sActionGridNo );
if ( pSoldier->sGridNo != sActionGridNo )
{
sAPCost += UIPlotPath( pSoldier, sActionGridNo, NO_COPYROUTE, fPlot, TEMPORARY, (UINT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints);
if ( sAPCost != 0 )
{
sAPCost += GetBasicAPsToPickupItem( pSoldier ); // SANDRO
}
}
else
{
sAPCost += GetBasicAPsToPickupItem( pSoldier ); // SANDRO
}
if ( sActionGridNo != pSoldier->sGridNo )
{
gfUIHandleShowMoveGrid = TRUE;
gsUIHandleShowMoveGridLocation = sActionGridNo;
}
}
}
}
else
{
sAPCost += UIPlotPath( pSoldier, sActionGridNo, NO_COPYROUTE, fPlot, TEMPORARY, (UINT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints );
}
if ( gTacticalStatus.uiFlags & SHOW_AP_LEFT )
{
gsCurrentActionPoints = pSoldier->bActionPoints - sAPCost;
}
else
{
gsCurrentActionPoints = sAPCost;
}
return( bReturnCode );
}
// WANNE: Calculate the APs to turn around
INT16 APsToTurnAround(SOLDIERTYPE *pSoldier, INT16 sAdjustedGridNo)
{
INT16 sAPCost = 0;
BOOLEAN fInitalMove = FALSE;
// Get the new direction
UINT8 ubDirection = (UINT8)GetDirectionFromGridNo( sAdjustedGridNo, pSoldier );
// If new direction is not the same than the old direction
if ( pSoldier->pathing.bDesiredDirection != ubDirection)
{
if ( gAnimControl[ pSoldier->usAnimState ].uiFlags & ( ANIM_BREATH | ANIM_OK_CHARGE_AP_FOR_TURN | ANIM_FIREREADY ) && !fInitalMove && !pSoldier->flags.fDontChargeTurningAPs )
{
// SANDRO - hey, we have a function for this, why not to use it, huh?
sAPCost += GetAPsToLook( pSoldier );
//// Which position has the soldier?
//switch( gAnimControl[ pSoldier->usAnimState ].ubEndHeight )
//{
//case ANIM_STAND:
// sAPCost += APBPConstants[AP_LOOK_STANDING];
// break;
//case ANIM_CROUCH:
// sAPCost += APBPConstants[AP_LOOK_CROUCHED];
// break;
//case ANIM_PRONE:
// sAPCost += APBPConstants[AP_LOOK_PRONE];
// break;
//}
}
}
return sAPCost;
}
BOOLEAN UIMouseOnValidAttackLocation( SOLDIERTYPE *pSoldier )
{
UINT16 usInHand;
BOOLEAN fGuyHere = FALSE;
SOLDIERTYPE *pTSoldier;
UINT8 ubItemCursor;
INT32 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->pathing.bLevel == 0 )
{
return( TRUE );
}
// Flugente: if there is tripwire here that we know of, allow handling
else if ( FindWorldItemForTripwireInGridNo( usMapPos, pSoldier->pathing.bLevel, TRUE ) != -1 )
{
return( TRUE );
}
else
{
return( FALSE );
}
}
if ( ubItemCursor == REPAIRCURS )
{
if ( gfUIFullTargetFound )
{
usMapPos = MercPtrs[ gusUIFullTargetID ]->sGridNo;
}
if ( IsRepairableStructAtGridNo( usMapPos, NULL ) && pSoldier->pathing.bLevel == 0 )
{
return( TRUE );
}
else
{
return( FALSE );
}
}
if ( ubItemCursor == REFUELCURS )
{
if ( gfUIFullTargetFound )
{
usMapPos = MercPtrs[ gusUIFullTargetID ]->sGridNo;
}
if ( IsRefuelableStructAtGridNo( usMapPos, NULL ) && pSoldier->pathing.bLevel == 0 )
{
return( TRUE );
}
else
{
return( FALSE );
}
}
if ( ubItemCursor == FORTICURS )
{
if ( gfUIFullTargetFound )
{
usMapPos = MercPtrs[ gusUIFullTargetID ]->sGridNo;
}
if ( pSoldier->pathing.bLevel == 0 )
{
if ( HasItemFlag( (&(pSoldier->inv[HANDPOS]))->usItem, (EMPTY_SANDBAG)) )
{
// check if we have a shovel in our second hand
OBJECTTYPE* pShovelObj = &(pSoldier->inv[SECONDHANDPOS]);
if ( pShovelObj && (pShovelObj->exists()) && HasItemFlag(pSoldier->inv[ SECONDHANDPOS ].usItem, (SHOVEL)) )
{
INT8 bOverTerrainType = GetTerrainType( usMapPos );
if( bOverTerrainType == FLAT_GROUND || bOverTerrainType == DIRT_ROAD || bOverTerrainType == LOW_GRASS )
{
return( TRUE );
}
}
}
else if ( HasItemFlag( (&(pSoldier->inv[HANDPOS]))->usItem, (SHOVEL)) )
{
STRUCTURE* pStruct = FindStructure(usMapPos, STRUCTURE_GENERIC);
if ( pStruct )
{
return( TRUE );
}
}
else if ( IsFortificationPossibleAtGridNo( usMapPos ) )
{
return( TRUE );
}
}
return( FALSE );
}
if ( ubItemCursor == HANDCUFFCURS )
{
if ( HasItemFlag( (&(pSoldier->inv[HANDPOS]))->usItem, HANDCUFFS ) )
{
if ( gfUIFullTargetFound )
{
usMapPos = MercPtrs[ gusUIFullTargetID ]->sGridNo;
return( TRUE );
}
}
return( FALSE );
}
if ( ubItemCursor == APPLYITEMCURS )
{
if ( ItemCanBeAppliedToOthers( (&(pSoldier->inv[HANDPOS]))->usItem ) )
{
if ( gfUIFullTargetFound )
{
usMapPos = MercPtrs[ gusUIFullTargetID ]->sGridNo;
return( TRUE );
}
}
return( FALSE );
}
if ( ubItemCursor == BOMBCURS )
{
if ( usMapPos == pSoldier->sGridNo )
{
return( TRUE );
}
if ( !NewOKDestination( pSoldier, usMapPos, TRUE, pSoldier->pathing.bLevel ) )
{
return( FALSE );
}
}
// SEE IF THERE IS SOMEBODY HERE
if ( gfUIFullTargetFound && ubItemCursor != KNIFECURS )
{
fGuyHere = TRUE;
if ( guiUIFullTargetFlags & SELECTED_MERC && Item[ usInHand ].usItemClass != IC_MEDKIT )
{
return( FALSE );
}
}
if ( !CanPlayerUseRocketRifle( pSoldier, TRUE ) )
{
return( FALSE );
}
//if ( Item[ usInHand ].usItemClass == IC_BLADE && usInHand != THROWING_KNIFE )
//{
// if ( !fGuyHere )
// {
// return( FALSE );
// }
//}
if ( Item[ usInHand ].usItemClass == IC_PUNCH )
{
if ( !fGuyHere )
{
return( FALSE );
}
}
//if ( Item[ usInHand ].usItemClass == IC_BLADE )
//{
// if ( !fGuyHere )
// {
// return( FALSE );
// }
//}
if ( Item[ usInHand ].usItemClass == IC_MEDKIT )
{
if ( !fGuyHere )
{
return( FALSE );
}
// IF a guy's here, chack if they need medical help!
pTSoldier = MercPtrs[ gusUIFullTargetID ];
// If we are a vehicle...
if ( ( pTSoldier->flags.uiStatusFlags & ( SOLDIER_VEHICLE | SOLDIER_ROBOT ) ) )
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, TacticalStr[ CANNOT_DO_FIRST_AID_STR ], pTSoldier->GetName() );
return( FALSE );
}
if ( pSoldier->stats.bMedical == 0 )
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, pMessageStrings[ MSG_MERC_HAS_NO_MEDSKILL ], pSoldier->GetName() );
return( FALSE );
}
// SANDRO - doctor with medical bag trying to do the surgery
if ((NUM_SKILL_TRAITS( pSoldier, DOCTOR_NT ) >= gSkillTraitValues.ubDONumberTraitsNeededForSurgery) && Item[pSoldier->inv[ HANDPOS ].usItem].medicalkit && gGameOptions.fNewTraitSystem
&& (pTSoldier->stats.bLife != pTSoldier->stats.bLifeMax) && (pTSoldier->iHealableInjury >= 100))
{
// should come a question first if you really want to do the surgery
return( TRUE );
}
else
{
if ( pTSoldier->bBleeding == 0 && pTSoldier->stats.bLife != pTSoldier->stats.bLifeMax )
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, gzLateLocalizedString[ 19 ], pTSoldier->GetName() );
return( FALSE );
}
if ( pTSoldier->bBleeding == 0 && pTSoldier->stats.bLife >= OKLIFE )
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, TacticalStr[ CANNOT_NO_NEED_FIRST_AID_STR ], pTSoldier->GetName() );
return( FALSE );
}
}
}
return( TRUE );
}
BOOLEAN UIOkForItemPickup( SOLDIERTYPE *pSoldier, INT32 sGridNo )
{
INT16 sAPCost;
ITEM_POOL *pItemPool;
sAPCost = GetAPsToPickupItem( pSoldier, sGridNo );
if ( sAPCost == 0 )
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, TacticalStr[ NO_PATH ] );
}
else
{
if ( GetItemPool( sGridNo, &pItemPool, pSoldier->pathing.bLevel ) )
{
//if ( !ITEMPOOL_VISIBLE( pItemPool ) )
{
// return( FALSE );
}
}
if ( EnoughPoints( pSoldier, sAPCost, 0, TRUE ) )
{
return( TRUE );
}
}
return( FALSE );
}
BOOLEAN SoldierCanAffordNewStance( SOLDIERTYPE *pSoldier, UINT8 ubDesiredStance )
{
INT8 bCurrentHeight;
UINT8 bAP = 0, bBP = 0;
bCurrentHeight = ( ubDesiredStance - gAnimControl[ pSoldier->usAnimState ].ubEndHeight );
// Now change to appropriate animation
// CHRISL: Modify function to include extra cost if wearing a backpack but only while running new inventory system
switch( bCurrentHeight )
{
case ANIM_STAND - ANIM_CROUCH:
if((UsingNewInventorySystem() == true))
if(pSoldier->inv[BPACKPOCKPOS].exists() == true && !pSoldier->flags.ZipperFlag)
bAP = bBP = 1;
bAP += GetAPsCrouch(pSoldier, FALSE);
bBP += APBPConstants[BP_CROUCH];
break;
case ANIM_CROUCH - ANIM_STAND:
if((UsingNewInventorySystem() == true))
if(pSoldier->inv[BPACKPOCKPOS].exists() == true && !pSoldier->flags.ZipperFlag)
bAP = bBP = 2;
bAP += GetAPsCrouch(pSoldier, FALSE);
bBP += APBPConstants[BP_CROUCH];
break;
case ANIM_STAND - ANIM_PRONE:
if((UsingNewInventorySystem() == true))
if(pSoldier->inv[BPACKPOCKPOS].exists() == true && !pSoldier->flags.ZipperFlag)
bAP = bBP = 2;
bAP += GetAPsCrouch(pSoldier, FALSE) + GetAPsProne(pSoldier, FALSE);
bBP += APBPConstants[BP_CROUCH] + APBPConstants[BP_PRONE];
break;
case ANIM_PRONE - ANIM_STAND:
if((UsingNewInventorySystem() == true))
if(pSoldier->inv[BPACKPOCKPOS].exists() == true && !pSoldier->flags.ZipperFlag)
bAP = bBP = 4;
bAP += GetAPsCrouch(pSoldier, FALSE) + GetAPsProne(pSoldier, FALSE);
bBP += APBPConstants[BP_CROUCH] + APBPConstants[BP_PRONE];
break;
case ANIM_CROUCH - ANIM_PRONE:
if((UsingNewInventorySystem() == true))
if(pSoldier->inv[BPACKPOCKPOS].exists() == true && !pSoldier->flags.ZipperFlag)
bAP = bBP = 1;
bAP += GetAPsProne(pSoldier, FALSE);
bBP += APBPConstants[BP_PRONE];
break;
case ANIM_PRONE - ANIM_CROUCH:
if((UsingNewInventorySystem() == true))
if(pSoldier->inv[BPACKPOCKPOS].exists() == true && !pSoldier->flags.ZipperFlag)
bAP = bBP = 2;
bAP += GetAPsProne(pSoldier, FALSE);
bBP += APBPConstants[BP_PRONE];
break;
}
return ( EnoughPoints( pSoldier, bAP, bBP , TRUE ) );
}
void SetUIbasedOnStance( SOLDIERTYPE *pSoldier, INT8 bNewStance )
{
// Set UI based on our stance!
switch ( bNewStance )
{
case ANIM_STAND:
pSoldier->usUIMovementMode = WALKING;
break;
case ANIM_CROUCH:
pSoldier->usUIMovementMode = SWATTING;
break;
case ANIM_PRONE:
pSoldier->usUIMovementMode = CRAWLING;
break;
}
// Set UI cursor!
}
void SetMovementModeCursor( SOLDIERTYPE *pSoldier )
{
if ( gTacticalStatus.uiFlags & TURNBASED && ( gTacticalStatus.uiFlags & INCOMBAT ) )
{
if ( ( OK_ENTERABLE_VEHICLE( pSoldier ) ) )
{
guiNewUICursor = MOVE_VEHICLE_UICURSOR;
}
else
{
// Change mouse cursor based on type of movement we want to do
switch ( pSoldier->usUIMovementMode )
{
case WALKING:
case WALKING_WEAPON_RDY:
case WALKING_DUAL_RDY:
case WALKING_ALTERNATIVE_RDY:
guiNewUICursor = MOVE_WALK_UICURSOR;
break;
case RUNNING:
guiNewUICursor = MOVE_RUN_UICURSOR;
break;
case SWATTING:
///ddd quick fix for losed cursor {
case SWATTING_WK:
///ddd quick fix for losed cursor }
guiNewUICursor = MOVE_SWAT_UICURSOR;
break;
case CRAWLING:
guiNewUICursor = MOVE_PRONE_UICURSOR;
break;
}
}
}
if ( ( gTacticalStatus.uiFlags & REALTIME ) || !( gTacticalStatus.uiFlags & INCOMBAT ) )
{
if ( gfUIAllMoveOn )
{
guiNewUICursor = ALL_MOVE_REALTIME_UICURSOR;
}
else
{
//if ( pSoldier->flags.fUIMovementFast )
//{
// BeginDisplayTimedCursor( MOVE_RUN_REALTIME_UICURSOR, 300 );
//}
guiNewUICursor = MOVE_REALTIME_UICURSOR;
}
}
guiNewUICursor = GetInteractiveTileCursor( guiNewUICursor, FALSE );
}
void SetConfirmMovementModeCursor( SOLDIERTYPE *pSoldier, BOOLEAN fFromMove )
{
if ( gTacticalStatus.uiFlags & TURNBASED && ( gTacticalStatus.uiFlags & INCOMBAT ) )
{
if ( gfUIAllMoveOn )
{
if ( ( OK_ENTERABLE_VEHICLE( pSoldier ) ) )
{
guiNewUICursor = ALL_MOVE_VEHICLE_UICURSOR;
}
else
{
// Change mouse cursor based on type of movement we want to do
switch ( pSoldier->usUIMovementMode )
{
case WALKING:
case WALKING_WEAPON_RDY:
case WALKING_DUAL_RDY:
case WALKING_ALTERNATIVE_RDY:
guiNewUICursor = ALL_MOVE_WALK_UICURSOR;
break;
case RUNNING:
guiNewUICursor = ALL_MOVE_RUN_UICURSOR;
break;
case SWATTING:
guiNewUICursor = ALL_MOVE_SWAT_UICURSOR;
break;
case CRAWLING:
guiNewUICursor = ALL_MOVE_PRONE_UICURSOR;
break;
}
}
}
else
{
if ( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE )
{
guiNewUICursor = CONFIRM_MOVE_VEHICLE_UICURSOR;
}
else
{
// Change mouse cursor based on type of movement we want to do
switch ( pSoldier->usUIMovementMode )
{
case WALKING:
case WALKING_WEAPON_RDY:
case WALKING_DUAL_RDY:
case WALKING_ALTERNATIVE_RDY:
guiNewUICursor = CONFIRM_MOVE_WALK_UICURSOR;
break;
case RUNNING:
guiNewUICursor = CONFIRM_MOVE_RUN_UICURSOR;
break;
case SWATTING:
guiNewUICursor = CONFIRM_MOVE_SWAT_UICURSOR;
break;
case CRAWLING:
guiNewUICursor = CONFIRM_MOVE_PRONE_UICURSOR;
break;
}
}
}
}
if ( ( gTacticalStatus.uiFlags & REALTIME ) || !( gTacticalStatus.uiFlags & INCOMBAT ) )
{
if ( gfUIAllMoveOn )
{
if ( gfUIAllMoveOn == 2 )
{
BeginDisplayTimedCursor( MOVE_RUN_REALTIME_UICURSOR, 300 );
}
else
{
guiNewUICursor = ALL_MOVE_REALTIME_UICURSOR;
}
}
else
{
if ( pSoldier->flags.fUIMovementFast && pSoldier->usAnimState == RUNNING && fFromMove )
{
BeginDisplayTimedCursor( MOVE_RUN_REALTIME_UICURSOR, 300 );
}
guiNewUICursor = CONFIRM_MOVE_REALTIME_UICURSOR;
}
}
guiNewUICursor = GetInteractiveTileCursor( guiNewUICursor, TRUE );
}
UINT8 gubShowActionPointsInRed = 0;
UINT32 UIHandleLCOnTerrain( UI_EVENT *pUIEvent )
{
SOLDIERTYPE *pSoldier;
INT16 sFacingDir, sXPos, sYPos;
UINT16 usAnimState;
guiNewUICursor = LOOK_UICURSOR;
// Get soldier
if ( !GetSoldier( &pSoldier, gusSelectedSoldier ) )
{
return( GAME_SCREEN );
}
gfUIDisplayActionPoints = TRUE;
gUIDisplayActionPointsOffX = 14;
gUIDisplayActionPointsOffY = 7;
// Get soldier
if ( !GetSoldier( &pSoldier, gusSelectedSoldier ) )
{
return( GAME_SCREEN );
}
GetMouseXY( &sXPos, &sYPos );
// Get direction from mouse pos
sFacingDir = GetDirectionFromXY( sXPos, sYPos, pSoldier );
// Set # of APs
if ( sFacingDir != pSoldier->ubDirection )
{
gsCurrentActionPoints = GetAPsToLook( pSoldier );
gfUIHandleShowMoveGrid = FALSE;
}
else
{
if ( pSoldier->bScopeMode == USE_ALT_WEAPON_HOLD && gGameExternalOptions.ubAllowAlternativeWeaponHolding == 3 )
usAnimState = PickSoldierReadyAnimation( pSoldier, FALSE, TRUE );
else
usAnimState = PickSoldierReadyAnimation( pSoldier, FALSE, FALSE );
gsCurrentActionPoints = 0;
//CHRISL: Why are we doing this? If we ready a weapon, we spend the AP_CHANGE_TARGET APs, but then if we actually shoot
// at someone in our current firing arc, we'll again pay the AP_CHANGE_TARGET cost because it's considered a new tartget.
// Should be simply pay the ready weapon cost and only pay the AP_CHANGE_TARGET when we actually aim at a target?
// Lesh: raise weapon include APs to set weapon towards enemy and APs to aquire/change target
//if( pSoldier->sLastTarget != sXPos + (MAXCOL * sYPos ) )
// gsCurrentActionPoints = APBPConstants[AP_CHANGE_TARGET];
if( usAnimState != INVALID_ANIMATION )
{
gsCurrentActionPoints += GetAPsToReadyWeapon( pSoldier, usAnimState );// Madd: removed the next part since it was deducting 2 extra aps that would not be deducted when readying the old way //+ AP_TO_AIM_TILE_IF_GETTING_READY;
}
gfUIHandleShowMoveGrid = TRUE;
gsUIHandleShowMoveGridLocation = sXPos + (MAXCOL * sYPos );
gubShowActionPointsInRed = 5;
//gfDisplayFullCountRingBurst = FALSE;
}
// Determine if we can afford!
if ( !EnoughPoints( pSoldier, gsCurrentActionPoints, 0, FALSE ) )
{
gfUIDisplayActionPointsInvalid = TRUE;
}
//HandleSight( pSoldier, SIGHT_LOOK );
return( GAME_SCREEN );
}
UINT32 UIHandleLCChangeToLook( UI_EVENT *pUIEvent )
{
ErasePath( TRUE );
return( GAME_SCREEN );
}
BOOLEAN MakeSoldierTurn( SOLDIERTYPE *pSoldier, INT16 sXPos, INT16 sYPos )
{
INT16 sFacingDir, sAPCost, sAPCostToReady;
UINT16 usAnimState;
INT32 iBPCpst = 0;
// Make sure the merc is not collapsed!
if (!IsValidStance(pSoldier, ANIM_CROUCH) )
{
if ( pSoldier->bCollapsed && pSoldier->bBreath < OKBREATH )
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, gzLateLocalizedString[ 4 ], pSoldier->GetName() );
}
return FALSE;
}
// Get direction from mouse pos
sFacingDir = GetDirectionFromXY( sXPos, sYPos, pSoldier );
if ( sFacingDir != pSoldier->ubDirection )
{
sAPCost = GetAPsToLook( pSoldier );
// Check AP cost...
if ( !EnoughPoints( pSoldier, sAPCost, 0, TRUE ) )
{
return( FALSE );
}
// ATE: make stationary if...
if ( pSoldier->flags.fNoAPToFinishMove )
{
// arynn : fix lower ready weapons
//previously "ready weapon" state was being dropped in a couple of cases
//the fix involves bypassing the reset animation state for the various "ready weapon" types
//since this is a reset animation function, we should be VERY specific about when and what we dont reset
UINT16 test;
test = pSoldier->usAnimState;
if (!( test == AIM_RIFLE_STAND || test == AIM_RIFLE_CROUCH ||
test == AIM_RIFLE_PRONE || test == AIM_DUAL_STAND ||
test == AIM_DUAL_CROUCH || test == AIM_DUAL_PRONE
))
{
pSoldier->SoldierGotoStationaryStance( );
}// arynn : fix lower ready weapon end_if
}
//DEF: made it an event
SendSoldierSetDesiredDirectionEvent( pSoldier, sFacingDir );
pSoldier->bTurningFromUI = TRUE;
// ATE: Hard-code here previous event to ui busy event...
guiOldEvent = LA_BEGINUIOURTURNLOCK;
return( TRUE );
}
else
{
if ( pSoldier->bScopeMode == USE_ALT_WEAPON_HOLD && gGameExternalOptions.ubAllowAlternativeWeaponHolding == 3 )
usAnimState = PickSoldierReadyAnimation( pSoldier, FALSE, TRUE );
else
usAnimState = PickSoldierReadyAnimation( pSoldier, FALSE, FALSE );
sAPCostToReady = sAPCost = 0;
//CHRISL: We should only charge AP_CHANGE_TARGET if we're actually pointing at a new target. Don't charge just
// to ready a weapon since we'll charge AP_CHANGE_TARGET when we actually fire.
SOLDIERTYPE * pTarget = SimpleFindSoldier( sXPos + (MAXCOL * sYPos ), pSoldier->bTargetLevel );
// Lesh: raise weapon include APs to set weapon towards enemy and APs to aquire/change target
if( pSoldier->sLastTarget != sXPos + (MAXCOL * sYPos ) && pTarget != NULL )
sAPCost = APBPConstants[AP_CHANGE_TARGET];
if ( pSoldier->bScopeMode == USE_ALT_WEAPON_HOLD && gGameExternalOptions.ubAllowAlternativeWeaponHolding == 3 )
sAPCost /= 2;
if( usAnimState != INVALID_ANIMATION )
{
sAPCostToReady = GetAPsToReadyWeapon( pSoldier, usAnimState );
}
// Check AP cost...
if ( !EnoughPoints( pSoldier, sAPCost + sAPCostToReady, 0, TRUE ) )
{
return( FALSE );
}
if( usAnimState != INVALID_ANIMATION )
{
if ( pSoldier->bScopeMode == USE_ALT_WEAPON_HOLD && gGameExternalOptions.ubAllowAlternativeWeaponHolding == 3 )
pSoldier->SoldierReadyWeapon( sXPos, sYPos, FALSE, TRUE );
else
pSoldier->SoldierReadyWeapon( sXPos, sYPos, FALSE, FALSE );
}
pSoldier->bTurningFromUI = TRUE;
guiOldEvent = LA_BEGINUIOURTURNLOCK;
// Setting "Last Target"
//pSoldier->sLastTarget = sXPos + (MAXCOL * sYPos);//dnl ch70 160913 when you turn you will lost target, it was always been like that!
// SANDRO - get BP cost for weapon manipulating
if ( gGameExternalOptions.ubEnergyCostForWeaponWeight)
iBPCpst = sAPCost * GetBPCostPer10APsForGunHolding( pSoldier ) / 10;
else
iBPCpst = 0;
DeductPoints( pSoldier, sAPCost, iBPCpst, AFTERACTION_INTERRUPT );
return( TRUE );
}
}
UINT32 UIHandleLCLook( UI_EVENT *pUIEvent )
{
INT16 sXPos, sYPos;
SOLDIERTYPE *pSoldier;
INT32 cnt;
if ( !GetMouseXY( &sXPos, &sYPos ) )
{
return( GAME_SCREEN );
}
if ( gTacticalStatus.fAtLeastOneGuyOnMultiSelect )
{
// OK, loop through all guys who are 'multi-selected' and
cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++, pSoldier++ )
{
if ( pSoldier->bActive && pSoldier->bInSector )
{
if ( pSoldier->flags.uiStatusFlags & SOLDIER_MULTI_SELECTED )
{
MakeSoldierTurn( pSoldier, sXPos, sYPos );
}
}
}
}
else
{
// Get soldier
if ( !GetSoldier( &pSoldier, gusSelectedSoldier ) )
{
return( GAME_SCREEN );
}
if ( MakeSoldierTurn( pSoldier, sXPos, sYPos ) )
{
// 0verhaul: Why do we set UI busy for a single soldier but not for a group of selected soldiers?
//SetUIBusy( pSoldier->ubID );
}
}
return( GAME_SCREEN );
}
UINT32 UIHandleTOnTerrain( UI_EVENT *pUIEvent )
{
SOLDIERTYPE *pSoldier;
UINT8 ubTargID;
UINT32 uiRange;
INT32 usMapPos;
BOOLEAN fValidTalkableGuy = FALSE;
INT32 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->pathing.bLevel, 3, TRUE, CALC_FROM_ALL_DIRS ) )
{
//. ATE: Make range far, so we alternate cursors...
guiNewUICursor = TALK_OUT_RANGE_A_UICURSOR;
}
}
gfUIDisplayActionPoints = TRUE;
gUIDisplayActionPointsOffX = 8;
gUIDisplayActionPointsOffY = 3;
// Set # of APs
gsCurrentActionPoints = APBPConstants[AP_TALK];
// 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( INT32 sGridNo, INT16 *pScreenX, INT16 *pScreenY )
{
INT16 sScreenX, sScreenY;
INT16 sOffsetX, sOffsetY;
INT16 sTempX_S, sTempY_S;
INT16 sXPos, sYPos;
ConvertGridNoToCellXY( sGridNo, &sXPos, &sYPos );
// Get 'TRUE' merc position
sOffsetX = sXPos - gsRenderCenterX;
sOffsetY = sYPos - gsRenderCenterY;
FromCellToScreenCoordinates( sOffsetX, sOffsetY, &sTempX_S, &sTempY_S );
sScreenX = ( ( gsVIEWPORT_END_X - gsVIEWPORT_START_X ) /2 ) + (INT16)sTempX_S;
sScreenY = ( ( gsVIEWPORT_END_Y - gsVIEWPORT_START_Y ) /2 ) + (INT16)sTempY_S;
// Adjust for offset position on screen
sScreenX -= gsRenderWorldOffsetX;
sScreenY -= gsRenderWorldOffsetY;
sScreenY -= gpWorldLevelData[ sGridNo ].sHeight;
// Adjust based on interface level
// Adjust for render height
sScreenY += gsRenderHeight;
// Adjust y offset!
sScreenY += ( WORLD_TILE_Y/2);
(*pScreenX) = sScreenX;
(*pScreenY) = sScreenY;
}
void EndMultiSoldierSelection( BOOLEAN fAcknowledge )
{
SOLDIERTYPE * pSoldier;
INT32 cnt;
SOLDIERTYPE *pFirstSoldier = NULL;
BOOLEAN fSelectedSoldierInBatch = FALSE;
gTacticalStatus.fAtLeastOneGuyOnMultiSelect = FALSE;
// OK, loop through all guys who are 'multi-selected' and
// check if our currently selected guy is amoung the
// lucky few.. if not, change to a guy who is...
cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++, pSoldier++ )
{
if ( pSoldier->bActive && pSoldier->bInSector )
{
if ( pSoldier->flags.uiStatusFlags & SOLDIER_MULTI_SELECTED )
{
gTacticalStatus.fAtLeastOneGuyOnMultiSelect = TRUE;
if ( pSoldier->ubID != gusSelectedSoldier && pFirstSoldier == NULL )
{
pFirstSoldier = pSoldier;
}
if ( pSoldier->ubID == gusSelectedSoldier )
{
fSelectedSoldierInBatch = TRUE;
}
if( !gGameSettings.fOptions[ TOPTION_MUTE_CONFIRMATIONS ] && fAcknowledge )
pSoldier->InternalDoMercBattleSound( BATTLE_SOUND_ATTN1, BATTLE_SND_LOWER_VOLUME );
if ( pSoldier->flags.fMercAsleep )
{
PutMercInAwakeState( pSoldier );
}
}
}
}
// If here, select the first guy...
if ( pFirstSoldier != NULL && !fSelectedSoldierInBatch )
{
SelectSoldier( pFirstSoldier->ubID, TRUE, TRUE );
}
}
void StopRubberBandedMercFromMoving( )
{
if ( !gTacticalStatus.fAtLeastOneGuyOnMultiSelect )
{
return;
}
SOLDIERTYPE * pSoldier;
INT32 cnt;
// OK, loop through all guys who are 'multi-selected' and
// check if our currently selected guy is amoung the
// lucky few.. if not, change to a guy who is...
cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++, pSoldier++ )
{
if ( pSoldier->bActive && pSoldier->bInSector )
{
if ( pSoldier->flags.uiStatusFlags & SOLDIER_MULTI_SELECTED )
{
pSoldier->flags.fDelayedMovement = FALSE;
pSoldier->pathing.sFinalDestination = pSoldier->sGridNo;
pSoldier->StopSoldier( );
}
}
}
}
void EndRubberBanding( )
{
if ( gRubberBandActive )
{
FreeMouseCursor( TRUE );
gfIgnoreScrolling = FALSE;
EndMultiSoldierSelection( TRUE );
gRubberBandActive = FALSE;
}
}
BOOLEAN HandleMultiSelectionMove( INT32 sDestGridNo )
{
SOLDIERTYPE * pSoldier;
INT32 cnt;
BOOLEAN fAtLeastOneMultiSelect = FALSE;
BOOLEAN fMoveFast = FALSE;
// OK, loop through all guys who are 'multi-selected' and
// Make them move....
// Do a loop first to see if the selected guy is told to go fast...
gfGetNewPathThroughPeople = TRUE;
cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++, pSoldier++ )
{
if ( pSoldier->bActive && pSoldier->bInSector )
{
if ( pSoldier->flags.uiStatusFlags & SOLDIER_MULTI_SELECTED )
{
if ( pSoldier->ubID == gusSelectedSoldier )
{
fMoveFast = pSoldier->flags.fUIMovementFast;
break;
}
}
}
}
// Flugente: we want to ove mercs in formation. In order to achieve this, we need to find their centre gridno.
// We can then determine their range to this centre, an set as their new gridno the sDestGridNo + this difference
INT32 lowestX = 999999;
INT32 highestX = 0;
INT32 lowestY = 999999;
INT32 highestY = 0;
cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++, pSoldier++ )
{
if ( pSoldier->bActive && pSoldier->bInSector )
{
if ( pSoldier->flags.uiStatusFlags & SOLDIER_MULTI_SELECTED )
{
// update lowest and highest x and y values
lowestX = min(lowestX, pSoldier->sGridNo % MAXCOL );
highestX = max(highestX, pSoldier->sGridNo % MAXCOL );
lowestY = min(lowestY, pSoldier->sGridNo / MAXCOL );
highestY = max(highestY, pSoldier->sGridNo / MAXCOL );
}
}
}
// determine center gridno
INT32 centerX = (highestX + lowestX)/2;
INT32 centerY = (highestY + lowestY)/2;
cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++, pSoldier++ )
{
if ( pSoldier->bActive && pSoldier->bInSector )
{
if ( pSoldier->flags.uiStatusFlags & SOLDIER_MULTI_SELECTED )
{
// If we can't be controlled, returninvalid...
if ( pSoldier->flags.uiStatusFlags & SOLDIER_ROBOT )
{
if ( !pSoldier->CanRobotBeControlled( ) )
{
continue;
}
}
pSoldier->flags.fUIMovementFast = fMoveFast;
pSoldier->usUIMovementMode = pSoldier->GetMoveStateBasedOnStance( gAnimControl[ pSoldier->usAnimState ].ubEndHeight );
pSoldier->flags.fUIMovementFast = FALSE;
if ( gUIUseReverse )
{
pSoldier->bReverse = TRUE;
}
else
{
pSoldier->bReverse = FALSE;
}
// Remove any previous actions
pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION;
INT32 sIndividualDestGridNo = sDestGridNo;
// Flugente: determine offset to current center gridno
if ( gGameSettings.fOptions[TOPTION_MERCENARY_FORMATIONS] )
{
INT32 currentX = pSoldier->sGridNo % MAXCOL;
INT32 currentY = pSoldier->sGridNo / MAXCOL;
INT32 diffX = currentX - centerX;
INT32 diffY = currentY - centerY;
sIndividualDestGridNo = sDestGridNo + diffX + MAXCOL * diffY;
// if we cannot walk to this gridno, move to one nearby
if ( !IsLocationSittableExcludingPeople( sIndividualDestGridNo, pSoldier->pathing.bLevel ) )
{
// try to find a fitting gridno nearby, otherwise go to target location
BOOLEAN found = FALSE;
for (UINT8 i = 0; i < 10; ++i)
{
INT32 rdX = Random(5) - 2; // -2 : 2
INT32 rdY = Random(5) - 2; // -2 : 2
if ( IsLocationSittableExcludingPeople( sIndividualDestGridNo + rdX + MAXCOL * rdY, pSoldier->pathing.bLevel ) )
{
found = TRUE;
sIndividualDestGridNo = sIndividualDestGridNo + rdX + MAXCOL * rdY;
break;
}
}
if ( !found )
sIndividualDestGridNo = sDestGridNo;
}
}
if ( pSoldier->EVENT_InternalGetNewSoldierPath( sIndividualDestGridNo, pSoldier->usUIMovementMode , TRUE, pSoldier->flags.fNoAPToFinishMove ) )
{
pSoldier->InternalDoMercBattleSound( BATTLE_SOUND_OK1, BATTLE_SND_LOWER_VOLUME );
}
else
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, TacticalStr[ NO_PATH_FOR_MERC ], pSoldier->GetName() );
}
fAtLeastOneMultiSelect = TRUE;
}
}
}
gfGetNewPathThroughPeople = FALSE;
return( fAtLeastOneMultiSelect );
}
void ResetMultiSelection( )
{
SOLDIERTYPE * pSoldier;
INT32 cnt;
// OK, loop through all guys who are 'multi-selected' and
// Make them move....
cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++, pSoldier++ )
{
if ( pSoldier->bActive && pSoldier->bInSector )
{
if ( pSoldier->flags.uiStatusFlags & SOLDIER_MULTI_SELECTED )
{
pSoldier->flags.uiStatusFlags &= (~SOLDIER_MULTI_SELECTED );
}
}
}
gTacticalStatus.fAtLeastOneGuyOnMultiSelect = FALSE;
}
UINT32 UIHandleRubberBandOnTerrain( UI_EVENT *pUIEvent )
{
SOLDIERTYPE * pSoldier;
INT32 cnt;
INT16 sScreenX, sScreenY;
INT32 iTemp;
SGPRect aRect;
BOOLEAN fAtLeastOne = FALSE;
guiNewUICursor = NO_UICURSOR;
//SetCurrentCursorFromDatabase( VIDEO_NO_CURSOR );
gRubberBandRect.iRight = gusMouseXPos;
gRubberBandRect.iBottom = gusMouseYPos;
// Copy into temp rect
memcpy( &aRect, &gRubberBandRect, sizeof( gRubberBandRect ) );
if ( aRect.iRight < aRect.iLeft )
{
iTemp = aRect.iLeft;
aRect.iLeft = aRect.iRight;
aRect.iRight = iTemp;
}
if ( aRect.iBottom < aRect.iTop )
{
iTemp = aRect.iTop;
aRect.iTop = aRect.iBottom;
aRect.iBottom = iTemp;
}
// ATE:Check at least for one guy that's in point!
cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++, pSoldier++ )
{
// Check if this guy is OK to control....
if ( OK_CONTROLLABLE_MERC( pSoldier ) && !( pSoldier->flags.uiStatusFlags & ( SOLDIER_VEHICLE | SOLDIER_PASSENGER | SOLDIER_DRIVER ) ) )
{
// Get screen pos of gridno......
GetGridNoScreenXY( pSoldier->sGridNo, &sScreenX, &sScreenY );
// ATE: If we are in a hiehger interface level, subttrasct....
if ( gsInterfaceLevel == 1 )
{
sScreenY -= 50;
}
if ( IsPointInScreenRect( sScreenX, sScreenY, &aRect ) )
{
fAtLeastOne = TRUE;
}
}
}
if ( !fAtLeastOne )
{
return( GAME_SCREEN );
}
// ATE: Now loop through our guys and see if any fit!
cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++, pSoldier++ )
{
// Check if this guy is OK to control....
if ( OK_CONTROLLABLE_MERC( pSoldier ) && !( pSoldier->flags.uiStatusFlags & ( SOLDIER_VEHICLE | SOLDIER_PASSENGER | SOLDIER_DRIVER ) ) )
{
if ( !_KeyDown( ALT ) )
{
pSoldier->flags.uiStatusFlags &= (~SOLDIER_MULTI_SELECTED );
}
// Get screen pos of gridno......
GetGridNoScreenXY( pSoldier->sGridNo, &sScreenX, &sScreenY );
// ATE: If we are in a hiehger interface level, subttrasct....
if ( gsInterfaceLevel == 1 )
{
sScreenY -= 50;
}
if ( IsPointInScreenRect( sScreenX, sScreenY, &aRect ) )
{
// Adjust this guy's flag...
pSoldier->flags.uiStatusFlags |= SOLDIER_MULTI_SELECTED;
}
}
}
return( GAME_SCREEN );
}
UINT32 UIHandleJumpOverOnTerrain( UI_EVENT *pUIEvent )
{
SOLDIERTYPE *pSoldier;
INT32 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;
INT32 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->aiData.ubPendingAction = NO_PENDING_ACTION;
// Get direction to goto....
ubDirection = GetDirectionFromGridNo( usMapPos, pSoldier );
pSoldier->flags.fDontChargeTurningAPs = TRUE;
pSoldier->EVENT_SetSoldierDesiredDirection(ubDirection);
pSoldier->flags.fTurningUntilDone = TRUE;
// ATE: Reset flag to go back to prone...
//pSoldier->flags.fTurningFromPronePosition = TURNING_FROM_PRONE_OFF;
if (SpacesAway(pSoldier->sGridNo, usMapPos) == 3 )
pSoldier->usPendingAnimation = LONG_JUMP;
else
pSoldier->usPendingAnimation = JUMP_OVER_BLOCKING_PERSON;
return( GAME_SCREEN );
}
UINT32 UIHandleLABeginLockOurTurn( UI_EVENT *pUIEvent )
{
// Don't let both versions of the locks to happen at the same time!
// ( They are mutually exclusive )!
UIHandleLUIEndLock( NULL );
if ( !gfUserTurnRegionActive )
{
gfUserTurnRegionActive = TRUE;
gfUIInterfaceSetBusy = TRUE;
guiUIInterfaceBusyTime = GetJA2Clock( );
//guiNewUICursor = NO_UICURSOR;
//SetCurrentCursorFromDatabase( VIDEO_NO_CURSOR );
MSYS_DefineRegion( &gUserTurnRegion, 0, 0 ,SCREEN_WIDTH, SCREEN_HEIGHT, MSYS_PRIORITY_HIGHEST,
CURSOR_WAIT, MSYS_NO_CALLBACK, MSYS_NO_CALLBACK );
// Add region
MSYS_AddRegion( &gUserTurnRegion );
//guiPendingOverrideEvent = LOCKOURTURN_UI_MODE;
ErasePath( TRUE );
// Pause time!
PauseGame();
LockPauseState( 17 );
}
return( GAME_SCREEN );
}
UINT32 UIHandleLAEndLockOurTurn( UI_EVENT *pUIEvent )
{
if ( gfUserTurnRegionActive )
{
gfUserTurnRegionActive = FALSE;
gfUIInterfaceSetBusy = FALSE;
// Add region
MSYS_RemoveRegion( &gUserTurnRegion );
RefreshMouseRegions( );
//SetCurrentCursorFromDatabase( guiCurrentUICursor );
gfPlotNewMovement = TRUE;
guiForceRefreshMousePositionCalculation = TRUE;
UIHandleMOnTerrain( NULL );
if ( gViewportRegion.uiFlags & MSYS_MOUSE_IN_AREA )
{
SetCurrentCursorFromDatabase( gUICursors[ guiNewUICursor ].usFreeCursorName );
}
guiPendingOverrideEvent = M_ON_TERRAIN;
HandleTacticalUI( );
TurnOffTeamsMuzzleFlashes( gbPlayerNum );
// UnPause time!
UnLockPauseState();
UnPauseGame();
}
return( GAME_SCREEN );
}
BOOLEAN IsValidTalkableNPCFromMouse( UINT8 *pubSoldierID , BOOLEAN fGive, BOOLEAN fAllowMercs, BOOLEAN fCheckCollapsed )
{
// Check if there is a guy here to talk to!
if ( gfUIFullTargetFound )
{
*pubSoldierID = (UINT8)gusUIFullTargetID;
return( IsValidTalkableNPC( (UINT8)gusUIFullTargetID, fGive, fAllowMercs, fCheckCollapsed ) );
}
return( FALSE );
}
BOOLEAN IsValidTalkableNPC( UINT8 ubSoldierID, BOOLEAN fGive , BOOLEAN fAllowMercs, BOOLEAN fCheckCollapsed )
{
SOLDIERTYPE *pSoldier = MercPtrs[ ubSoldierID ];
BOOLEAN fValidGuy = FALSE;
if ( gusSelectedSoldier != NOBODY )
{
if ( AM_A_ROBOT( MercPtrs[ gusSelectedSoldier ] ) )
{
return( FALSE );
}
}
// CHECK IF ACTIVE!
if ( !pSoldier->bActive )
{
return( FALSE );
}
// CHECK IF DEAD
if( pSoldier->stats.bLife == 0 )
{
return( FALSE );
}
if ( pSoldier->bCollapsed && fCheckCollapsed )
{
return( FALSE );
}
if ( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE )
{
return( FALSE );
}
// IF BAD GUY - CHECK VISIVILITY
if ( pSoldier->bTeam != gbPlayerNum )
{
if ( pSoldier->bVisible == -1 && !(gTacticalStatus.uiFlags&SHOW_ALL_MERCS) )
{
return( FALSE );
}
}
// if ( pSoldier->ubProfile != NO_PROFILE && pSoldier->ubProfile >= FIRST_RPC && pSoldier->ubProfile < GASTON && !RPC_RECRUITED( pSoldier ) && !AM_AN_EPC( pSoldier ) )
//new profiles by Jazz
if ( pSoldier->ubProfile != NO_PROFILE && ( gProfilesRPC[pSoldier->ubProfile].ProfilId == pSoldier->ubProfile || gProfilesNPC[pSoldier->ubProfile].ProfilId == pSoldier->ubProfile ) && !RPC_RECRUITED( pSoldier ) && !AM_AN_EPC( pSoldier ) )
{
fValidGuy = TRUE;
}
// Check for EPC...
if ( pSoldier->ubProfile != NO_PROFILE && ( gCurrentUIMode == TALKCURSOR_MODE || fGive ) && AM_AN_EPC( pSoldier ) )
{
fValidGuy = TRUE;
}
// ATE: We can talk to our own teammates....
if ( pSoldier->bTeam == gbPlayerNum && fAllowMercs )
{
fValidGuy = TRUE;
}
if ( GetCivType( pSoldier ) != CIV_TYPE_NA && !fGive )
{
fValidGuy = TRUE;
}
// Alright, let's do something special here for robot...
if ( pSoldier->flags.uiStatusFlags & SOLDIER_ROBOT )
{
if ( fValidGuy == TRUE && !fGive )
{
// Can't talk to robots!
fValidGuy = FALSE;
}
}
// OK, check if they are stationary or not....
// Do some checks common to all..
if ( fValidGuy )
{
if ( ( gAnimControl[ pSoldier->usAnimState ].uiFlags & ANIM_MOVING ) && !(gTacticalStatus.uiFlags & INCOMBAT ) )
{
return( FALSE );
}
return( TRUE );
}
return( FALSE );
}
BOOLEAN HandleTalkInit( )
{
INT16 sAPCost;
SOLDIERTYPE *pSoldier, *pTSoldier;
UINT32 uiRange;
INT32 usMapPos;
INT32 sGoodGridNo;
UINT8 ubNewDirection;
UINT8 ubQuoteNum;
UINT8 ubDiceRoll;
INT32 sActionGridNo;
UINT8 ubDirection;
UINT32 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->pathing.bLevel, 3, TRUE, CALC_FROM_ALL_DIRS ) )
{
if ( pTSoldier->ubProfile != NO_PROFILE )
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, TacticalStr[ NO_LOS_TO_TALK_TARGET ], pSoldier->GetName(), pTSoldier->GetName() );
}
else
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, gzLateLocalizedString[ 45 ], pSoldier->GetName() );
}
return( FALSE );
}
}
}
if ( pTSoldier->bCollapsed )
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, gzLateLocalizedString[ 21 ], pTSoldier->GetName() );
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->GetName() );
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[ pTSoldier->ubProfile ].QuoteExpPassingDislike )
{
ubQuoteNum = QUOTE_PASSING_DISLIKE;
}
else
{
ubQuoteNum = QUOTE_NEGATIVE_COMPANY;
}
break;
case 2:
ubQuoteNum = QUOTE_SOCIAL_TRAIT;
break;
default:
ubQuoteNum = QUOTE_NEGATIVE_COMPANY;
break;
}
#ifdef JA2UB
// ja25 UB
#else
if ( pTSoldier->ubProfile == IRA )
{
ubQuoteNum = QUOTE_PASSING_DISLIKE;
}
#endif
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 = APBPConstants[AP_TALK];
//sAPCost += UIPlotPath( pSoldier, sGoodGridNo, NO_COPYROUTE, FALSE, TEMPORARY, (UINT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints );
// Check AP cost...
if ( !EnoughPoints( pSoldier, sAPCost, 0, TRUE ) )
{
return( FALSE );
}
// Now walkup to talk....
pSoldier->aiData.ubPendingAction = MERC_TALK;
pSoldier->aiData.uiPendingActionData1 = pTSoldier->ubID;
pSoldier->aiData.ubPendingActionAnimCount = 0;
// WALK UP TO DEST FIRST
pSoldier->EVENT_InternalGetNewSoldierPath( sGoodGridNo, pSoldier->usUIMovementMode , TRUE , pSoldier->flags.fNoAPToFinishMove );
return( FALSE );
}
}
else
{
sAPCost = APBPConstants[AP_TALK];
// Check AP cost...
if ( !EnoughPoints( pSoldier, sAPCost, 0, TRUE ) )
{
return( FALSE );
}
// OK, startup!
pSoldier->PlayerSoldierStartTalking( pTSoldier->ubID, FALSE );
}
if ( GetCivType( pTSoldier ) != CIV_TYPE_NA )
{
return( FALSE );
}
else
{
return( TRUE );
}
}
}
return( FALSE );
}
void SetUIBusy( UINT8 ubID )
{
if ( (gTacticalStatus.uiFlags & INCOMBAT ) && ( gTacticalStatus.uiFlags & TURNBASED ) && ( gTacticalStatus.ubCurrentTeam == gbPlayerNum ) )
{
if ( gusSelectedSoldier == ubID )
{
guiPendingOverrideEvent = LA_BEGINUIOURTURNLOCK;
HandleTacticalUI( );
}
}
}
void UnSetUIBusy( UINT8 ubID )
{
if ( gfUserTurnRegionActive && (gTacticalStatus.uiFlags & INCOMBAT ) && ( gTacticalStatus.uiFlags & TURNBASED ) && ( gTacticalStatus.ubCurrentTeam == gbPlayerNum ) )
{
{
if ( !gTacticalStatus.fUnLockUIAfterHiddenInterrupt )
{
if ( gusSelectedSoldier == ubID && (gTacticalStatus.ubCurrentTeam == OUR_TEAM || !is_networked))// now that mp
{
guiPendingOverrideEvent = LA_ENDUIOUTURNLOCK;
HandleTacticalUI( );
// Set grace period...
gTacticalStatus.uiTactialTurnLimitClock = GetJA2Clock( );
}
}
// player getting control back so reset all muzzle flashes
}
}
}
void BeginDisplayTimedCursor( UINT32 uiCursorID, UINT32 uiDelay )
{
gfDisplayTimerCursor = TRUE;
guiTimerCursorID = uiCursorID;
guiTimerLastUpdate = GetJA2Clock( );
guiTimerCursorDelay = uiDelay;
}
INT8 UIHandleInteractiveTilesAndItemsOnTerrain( SOLDIERTYPE *pSoldier, INT32 usMapPos, BOOLEAN fUseOKCursor, BOOLEAN fItemsOnlyIfOnIntTiles )
{
ITEM_POOL *pItemPool;
BOOLEAN fSetCursor;
UINT32 uiCursorFlags;
LEVELNODE *pIntTile;
static BOOLEAN fOverPool = FALSE;
static BOOLEAN fOverEnemy = FALSE;
INT32 sActionGridNo;
INT32 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->pathing.bLevel ) )
{
// If we want only on int tiles, and we have no int tiles.. ignore items!
if ( fItemsOnlyIfOnIntTiles && pIntTile == NULL )
{
}
else if ( fItemsOnlyIfOnIntTiles && pIntTile != NULL && ( pStructure->fFlags & STRUCTURE_HASITEMONTOP ) )
{
// if in this mode, we don't want to automatically show hand cursor over items on strucutres
}
//else if ( pIntTile != NULL && ( pStructure->fFlags & ( STRUCTURE_SWITCH | STRUCTURE_ANYDOOR ) ) )
else if ( pIntTile != NULL && ( pStructure->fFlags & ( STRUCTURE_SWITCH ) ) )
{
// We don't want switches messing around with items ever!
}
else if ( ( pIntTile != NULL && ( pStructure->fFlags & ( STRUCTURE_ANYDOOR ) ) ) && ( sActionGridNo != 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 == ADJACENT_GET_ITEM_CROUCHED ||
pSoldier->usAnimState == DROP_ADJACENT_OBJECT ||
pSoldier->usAnimState == OPEN_DOOR_CROUCHED ||
pSoldier->usAnimState == BEGIN_OPENSTRUCT_CROUCHED ||
pSoldier->usAnimState == CLOSE_DOOR_CROUCHED ||
pSoldier->usAnimState == OPEN_DOOR_CROUCHED ||
pSoldier->usAnimState == OPEN_STRUCT_CROUCHED ||
pSoldier->usAnimState == END_OPENSTRUCT_CROUCHED ||
pSoldier->usAnimState == END_OPEN_DOOR_CROUCHED ||
pSoldier->usAnimState == END_OPEN_LOCKED_DOOR_CROUCHED ||
pSoldier->usAnimState == END_OPENSTRUCT_LOCKED_CROUCHED ||
pSoldier->usAnimState == BEGIN_OPENSTRUCT )
{
return( TRUE );
}
}
return( FALSE );
}
void GotoHeigherStance( SOLDIERTYPE *pSoldier )
{
BOOLEAN fNearHeigherLevel;
BOOLEAN fNearLowerLevel;
switch( gAnimControl[ pSoldier->usAnimState ].ubEndHeight )
{
case ANIM_STAND:
// Nowhere
// Try to climb
GetMercClimbDirection( pSoldier->ubID, &fNearLowerLevel, &fNearHeigherLevel );
if ( fNearHeigherLevel )
{
pSoldier->BeginSoldierClimbUpRoof( );
}
break;
case ANIM_CROUCH:
HandleStanceChangeFromUIKeys( ANIM_STAND );
break;
case ANIM_PRONE:
HandleStanceChangeFromUIKeys( ANIM_CROUCH );
break;
}
}
void GotoLowerStance( SOLDIERTYPE *pSoldier )
{
BOOLEAN fNearHeigherLevel;
BOOLEAN fNearLowerLevel;
switch( gAnimControl[ pSoldier->usAnimState ].ubEndHeight )
{
case ANIM_STAND:
HandleStanceChangeFromUIKeys( ANIM_CROUCH );
break;
case ANIM_CROUCH:
HandleStanceChangeFromUIKeys( ANIM_PRONE );
break;
case ANIM_PRONE:
// Nowhere
// Try to climb
GetMercClimbDirection( pSoldier->ubID, &fNearLowerLevel, &fNearHeigherLevel );
if ( fNearLowerLevel )
{
pSoldier->BeginSoldierClimbDownRoof( );
}
break;
}
}
void SetInterfaceHeightLevel( )
{
INT16 sHeight;
static INT16 sOldHeight = 0;
INT32 sGridNo;
if( gfBasement || gfCaves )
{
gsRenderHeight = 0;
sOldHeight = 0;
return;
}
// ATE: Use an entry point to determine what height to use....
if( gMapInformation.sNorthGridNo != -1 )
sGridNo = gMapInformation.sNorthGridNo;
else if( gMapInformation.sEastGridNo != -1 )
sGridNo = gMapInformation.sEastGridNo;
else if( gMapInformation.sSouthGridNo != -1 )
sGridNo = gMapInformation.sSouthGridNo;
else if( gMapInformation.sWestGridNo != -1 )
sGridNo = gMapInformation.sWestGridNo;
else
{
Assert(0);
return;
}
sHeight = gpWorldLevelData[ sGridNo ].sHeight;
if ( sHeight != sOldHeight )
{
gsRenderHeight = sHeight;
if ( gsInterfaceLevel > 0 )
{
gsRenderHeight += ROOF_LEVEL_HEIGHT;
}
SetRenderFlags(RENDER_FLAG_FULL);
ErasePath(FALSE);
sOldHeight = sHeight;
}
}
BOOLEAN ValidQuickExchangePosition( )
{
SOLDIERTYPE *pSoldier, *pOverSoldier;
BOOLEAN fOnValidGuy = FALSE;
static BOOLEAN fOldOnValidGuy = FALSE;
// Check if we over a civ
if ( gfUIFullTargetFound )
{
pOverSoldier = MercPtrs[ gusUIFullTargetID ];
//KM: Replaced this older if statement for the new one which allows exchanging with militia
//if ( ( pOverSoldier->bSide != gbPlayerNum ) && pOverSoldier->aiData.bNeutral )
if ( ( pOverSoldier->bTeam != gbPlayerNum && pOverSoldier->aiData.bNeutral ) || (pOverSoldier->bTeam == MILITIA_TEAM && pOverSoldier->bSide == 0 ) )
{
// hehe - don't allow animals to exchange places
if ( !( pOverSoldier->flags.uiStatusFlags & ( SOLDIER_ANIMAL ) ) )
{
// OK, we have a civ , now check if they are near selected guy.....
if ( GetSoldier( &pSoldier, gusSelectedSoldier ) )
{
if ( PythSpacesAway( pSoldier->sGridNo, pOverSoldier->sGridNo ) == 1 )
{
// Check if we have LOS to them....
if ( SoldierTo3DLocationLineOfSightTest( pSoldier, pOverSoldier->sGridNo, pOverSoldier->pathing.bLevel, 3, TRUE, CALC_FROM_ALL_DIRS ) )
{
// ATE:
// Check that the path is good!
if ( FindBestPath( pSoldier, pOverSoldier->sGridNo, pSoldier->pathing.bLevel, pSoldier->usUIMovementMode, NO_COPYROUTE, PATH_IGNORE_PERSON_AT_DEST ) == 1 )
{
fOnValidGuy = TRUE;
}
}
}
}
}
}
}
if ( gGameSettings.fOptions[TOPTION_DISABLE_CURSOR_SWAP] )
{
gfOKForExchangeCursor = FALSE;
fOnValidGuy = FALSE;
}
else
{
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, INT32 sGridNo, BOOLEAN fCheckForPath )
{
// SANDRO: been here, did mess
INT32 sFourGrids[4], sDistance=0, sSpot, sInBetween, sInBetween2, iDoorGridNo;
static const UINT8 sDirs[4] = { NORTH, EAST, SOUTH, WEST };
//INT32 cnt;
UINT8 ubGuyThere, ubMovementCost, ubDirection;
INT8 bTileHeight = 0;
// SANDRO: commented out to allow jumping even in cases we could get to the destination normally
// 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
sInBetween = NewGridNo( sGridNo, DirectionInc( sDirs[ cnt ] ) );
// SANDRO: moved this someplace else and made it more fluid
// ATE: Check our movement costs for going through walls!
/*ubMovementCost = gubWorldMovementCosts[ sIntSpot ][ sDirs[ cnt ] ][ pSoldier->pathing.bLevel ];
if ( IS_TRAVELCOST_DOOR( ubMovementCost ) )
{
ubMovementCost = DoorTravelCost( pSoldier, sIntSpot, ubMovementCost, (BOOLEAN) (pSoldier->bTeam == gbPlayerNum), &iDoorGridNo );
}*/
// If we have hit an obstacle, STOP HERE
//if ( ubMovementCost >= TRAVELCOST_BLOCKED )
//{
// // no good, continue
// continue;
//}
// TWICE AS FAR!
sFourGrids[cnt] = sSpot = NewGridNo( sInBetween, DirectionInc( sDirs[ cnt ] ) );
// Is the soldier we're looking at here?
ubGuyThere = WhoIsThere2( sSpot, pSoldier->pathing.bLevel );
// Alright folks, here we are!
if ( ubGuyThere == pSoldier->ubID )
{
// Double check OK destination......
if ( NewOKDestination( pSoldier, sGridNo, TRUE, (INT8)gsInterfaceLevel ) && IsLocationSittable( sGridNo, pSoldier->pathing.bLevel ) )
{
// If the soldier in the middle of doing stuff?
if ( !pSoldier->flags.fTurningUntilDone )
{
// OK, NOW check if there is a guy in between us
//
// SANDRO: made this a bit different - if we hold down the shift key, and pointing at a spot 2 tiles away, we check if jumping
// there is possible for all cases, and if it is, then we juuuuumpppp!
// So we don't care if there is a guy on the ground there, and the cursor wont appear atutomatically anymore
//
//ubGuyThere = WhoIsThere2( sIntSpot, pSoldier->pathing.bLevel );
// Is there a guy and is he prone?
//if ( ubGuyThere != NOBODY && ubGuyThere != pSoldier->ubID && gAnimControl[ MercPtrs[ ubGuyThere ]->usAnimState ].ubHeight == ANIM_PRONE )
//{
// // It's a GO!
// return( TRUE );
//}
//else
// Can't jump from a water tile (but we can jumpt TO a water tile)
if ( pSoldier->MercInWater() )
{
return( FALSE );
}
// check for cliffs and similar oddities
if ( gpWorldLevelData[ sGridNo ].sHeight != gpWorldLevelData[ sSpot ].sHeight )
{
return( FALSE );
}
// If there's a guy here, and he's not prone, we can't jump over him (maybe the way we hop over fence when he's crouched? lol)
ubGuyThere = WhoIsThere2( sInBetween, pSoldier->pathing.bLevel );
if ( ubGuyThere != NOBODY && ubGuyThere != pSoldier->ubID )
{
if ( gAnimControl[ MercPtrs[ ubGuyThere ]->usAnimState ].ubHeight != ANIM_PRONE )
{
return( FALSE );
}
else if ( gsCurrentActionPoints == 0 || !fCheckForPath )
{
return( TRUE );
}
}
// Get the height of stuff on the tile, we can only jump over low obstacles like this
bTileHeight = GetTallestStructureHeight( sInBetween, pSoldier->pathing.bLevel );
if ( bTileHeight > 0 && !IsLocationSittableExcludingPeople( sInBetween, pSoldier->pathing.bLevel ) && !( pSoldier->pathing.bLevel && FlatRoofAboveGridNo( sInBetween ) ))
{
return( FALSE );
}
// Check again for these structures as they may have odd height preset
if (( FindStructure( sInBetween, STRUCTURE_TREE ) != NULL || FindStructure( sInBetween, STRUCTURE_FENCE ) != NULL ||
FindStructure( sInBetween, STRUCTURE_WIREFENCE ) != NULL || FindStructure( sInBetween, STRUCTURE_VEHICLE ) != NULL ||
FindStructure( sInBetween, STRUCTURE_CAVEWALL ) != NULL ) && !IsLocationSittableExcludingPeople( sInBetween, pSoldier->pathing.bLevel ))
{
return( FALSE );
}
// Now check for walls between the tiles
// Between our tile and the middle tile...
ubDirection = GetDirectionToGridNoFromGridNo( sInBetween, pSoldier->sGridNo );
ubMovementCost = gubWorldMovementCosts[ pSoldier->sGridNo ][ ubDirection ][ pSoldier->pathing.bLevel ];
if ( IS_TRAVELCOST_DOOR( ubMovementCost ) )
{
ubMovementCost = DoorTravelCost( pSoldier, pSoldier->sGridNo, ubMovementCost, (BOOLEAN) (pSoldier->bTeam == gbPlayerNum), &iDoorGridNo );
}
if ( ubMovementCost >= TRAVELCOST_BLOCKED )
{
return( FALSE );
}
// Between destination tile and the middle tile...
ubDirection = GetDirectionToGridNoFromGridNo( sInBetween, sGridNo );
ubMovementCost = gubWorldMovementCosts[ sGridNo ][ ubDirection ][ pSoldier->pathing.bLevel ];
if ( IS_TRAVELCOST_DOOR( ubMovementCost ) )
{
ubMovementCost = DoorTravelCost( pSoldier, sGridNo, ubMovementCost, (BOOLEAN) (pSoldier->bTeam == gbPlayerNum), &iDoorGridNo );
}
if ( ubMovementCost >= TRAVELCOST_BLOCKED )
{
return( FALSE );
}
if( !(_KeyDown( SHIFT ) && _KeyDown( ALT )) )
{
return( FALSE );
}
// If we got here, we are good to go
return ( TRUE );
}
}
}
// Attempt to long jump
else
{
// 3 TILES FAR!
sInBetween2 = sSpot;
sSpot = NewGridNo( sInBetween2, DirectionInc( sDirs[ cnt ] ) );
// Is the soldier we're looking at here?
ubGuyThere = WhoIsThere2( sSpot, pSoldier->pathing.bLevel );
// Alright folks, here we are!
if ( ubGuyThere == pSoldier->ubID )
{
// Double check OK destination......
if ( NewOKDestination( pSoldier, sGridNo, TRUE, (INT8)gsInterfaceLevel ) && IsLocationSittable( sGridNo, pSoldier->pathing.bLevel ) )
{
// If the soldier in the middle of doing stuff?
if ( !pSoldier->flags.fTurningUntilDone )
{
// Can't jump from a water tile (but we can jumpt TO a water tile)
if ( pSoldier->MercInWater() )
{
return( FALSE );
}
// This ain't gonna happen with backpack
if((UsingNewInventorySystem() == true) && FindBackpackOnSoldier( pSoldier ) != ITEM_NOT_FOUND )
{
return( FALSE );
}
// check for cliffs and similar oddities
if ( gpWorldLevelData[ sGridNo ].sHeight != gpWorldLevelData[ sSpot ].sHeight )
{
return( FALSE );
}
// If there's a guy on any of the two middle tiles, and he's not prone, we can't jump over him
ubGuyThere = WhoIsThere2( sInBetween, pSoldier->pathing.bLevel );
if ( ubGuyThere != NOBODY && ubGuyThere != pSoldier->ubID && gAnimControl[ MercPtrs[ ubGuyThere ]->usAnimState ].ubHeight != ANIM_PRONE )
{
return( FALSE );
}
ubGuyThere = WhoIsThere2( sInBetween2, pSoldier->pathing.bLevel );
if ( ubGuyThere != NOBODY && ubGuyThere != pSoldier->ubID && gAnimControl[ MercPtrs[ ubGuyThere ]->usAnimState ].ubHeight != ANIM_PRONE )
{
return( FALSE );
}
// Get the height of stuff on both middle tiles, we can only jump over low obstacles
bTileHeight = GetTallestStructureHeight( sInBetween, pSoldier->pathing.bLevel );
if ( bTileHeight > 0 && !IsLocationSittableExcludingPeople( sInBetween, pSoldier->pathing.bLevel ) && !( pSoldier->pathing.bLevel && FlatRoofAboveGridNo( sInBetween ) ))
{
return( FALSE );
}
bTileHeight = GetTallestStructureHeight( sInBetween2, pSoldier->pathing.bLevel );
if ( bTileHeight > 0 && !IsLocationSittableExcludingPeople( sInBetween2, pSoldier->pathing.bLevel ) && !( pSoldier->pathing.bLevel && FlatRoofAboveGridNo( sInBetween2 ) ))
{
return( FALSE );
}
// Check again for these structures as they may have odd height preset
if (( FindStructure( sInBetween, STRUCTURE_TREE ) != NULL || FindStructure( sInBetween, STRUCTURE_FENCE ) != NULL ||
FindStructure( sInBetween, STRUCTURE_WIREFENCE ) != NULL || FindStructure( sInBetween, STRUCTURE_VEHICLE ) != NULL ||
FindStructure( sInBetween, STRUCTURE_CAVEWALL ) != NULL ) && !IsLocationSittableExcludingPeople( sInBetween, pSoldier->pathing.bLevel ))
{
return( FALSE );
}
if (( FindStructure( sInBetween2, STRUCTURE_TREE ) != NULL || FindStructure( sInBetween2, STRUCTURE_FENCE ) != NULL ||
FindStructure( sInBetween2, STRUCTURE_WIREFENCE ) != NULL || FindStructure( sInBetween2, STRUCTURE_VEHICLE ) != NULL ||
FindStructure( sInBetween2, STRUCTURE_CAVEWALL ) != NULL ) && !IsLocationSittableExcludingPeople( sInBetween2, pSoldier->pathing.bLevel ))
{
return( FALSE );
}
// Now check for walls between the tiles
// Between our tile and the middle tile next to us...
ubDirection = GetDirectionToGridNoFromGridNo( sInBetween2, pSoldier->sGridNo );
ubMovementCost = gubWorldMovementCosts[ pSoldier->sGridNo ][ ubDirection ][ pSoldier->pathing.bLevel ];
if ( IS_TRAVELCOST_DOOR( ubMovementCost ) )
{
ubMovementCost = DoorTravelCost( pSoldier, pSoldier->sGridNo, ubMovementCost, (BOOLEAN) (pSoldier->bTeam == gbPlayerNum), &iDoorGridNo );
}
if ( ubMovementCost >= TRAVELCOST_BLOCKED )
{
return( FALSE );
}
// Between destination tile and the middle tile next to it...
ubDirection = GetDirectionToGridNoFromGridNo( sInBetween, sGridNo );
ubMovementCost = gubWorldMovementCosts[ sGridNo ][ ubDirection ][ pSoldier->pathing.bLevel ];
if ( IS_TRAVELCOST_DOOR( ubMovementCost ) )
{
ubMovementCost = DoorTravelCost( pSoldier, sGridNo, ubMovementCost, (BOOLEAN) (pSoldier->bTeam == gbPlayerNum), &iDoorGridNo );
}
if ( ubMovementCost >= TRAVELCOST_BLOCKED )
{
return( FALSE );
}
// Now we need to check if there is not a wall between the two middle tiles
ubDirection = GetDirectionToGridNoFromGridNo( sInBetween2, sInBetween );
switch (ubDirection)
{
case NORTH:
if ( WallOrClosedDoorExistsOfTopLeftOrientation( sInBetween ) )
return( FALSE );
break;
case EAST:
if ( WallOrClosedDoorExistsOfTopRightOrientation( sInBetween2 ) )
return( FALSE );
break;
case SOUTH:
if ( WallOrClosedDoorExistsOfTopLeftOrientation( sInBetween2 ) )
return( FALSE );
break;
case WEST:
if ( WallOrClosedDoorExistsOfTopRightOrientation( sInBetween ) )
return( FALSE );
break;
default:
return( FALSE );
break;
}
if( !(_KeyDown( SHIFT ) && _KeyDown( ALT )) )
{
return( FALSE );
}
// If we got here, we are good to go
return ( TRUE );
}
}
}
}
}
return( FALSE );
}