From 1fe56555ebf8a22a21ef1656055534df9ad3dda2 Mon Sep 17 00:00:00 2001 From: Flugente Date: Tue, 13 May 2014 20:50:16 +0000 Subject: [PATCH] Drivable Cars update (by anv): - Streamlined vehicle controls - no more selecting driver and vehicle separately, switching displayed APs and other esoteric activities. To move vehicle just select its driver and you're good to go. If you click on vehicle in tactical, also its driver will be selected automatically. Besides driving car, driver can perform other actions normally. - Vehicle's APs, health and fuel are displayed on the steering wheel - thanks to Buggler for idea. Vehicle APs are treated as a resource (so if car changes driver mid-turn, it won't go any further than it would). - Added option Tactical Interface Settings > ADD_PASSENGER_TO_ANY_SQUAD. If you order passenger to exit vehicle by clicking on the seat belt, he'll be added to new squad, so if you ordered six passengers to exit one by one, you'd end up with six new squads. With ADD_PASSENGER_TO_ANY_SQUAD = TRUE, passenger will be added to any existing squad with empty slot if possible. - Added option Tactical Interface Settings > PASSENGER_LEAVING_SWITCH_TO_NEW_SQUAD. If you order passenger to exit vehicle by clicking on the seat belt, by default you get switched to his new squad. With PASSENGER_LEAVING_SWITCH_TO_NEW_SQUAD = FALSE you'll switch only if exiting passenger is the selected one. - Cosmetic fix: changed display above vehicle from "*Merc's name* (VEHICLE)" to "*Merc's name* (*Vehicle's name*)" and colour from yellow to white (since mercs in vehicle are controllable and yellow is reserved for mercs on assignments). - Fixed passengers rotation. Again. - Fixed vehicles getting "tired" - lowered APs due to fuel below max. They can move the same as long as they have any fuel. - Fixed unrelated bug: clicking on any empty slot in team panel would select merc with id 0. - Fixed unrelated bug: switching to squad with less mercs would cause team panel to still show skill tooltips for mercs from previous squad on empty slots. git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@7204 3b4a5df2-a311-0410-b5c6-a8a6f20db521 --- GameSettings.cpp | 7 ++ GameSettings.h | 6 ++ Tactical/Animation Control.cpp | 2 + Tactical/Handle Items.cpp | 6 ++ Tactical/Handle UI.cpp | 70 ++++++++++++---- Tactical/Interface Items.cpp | 55 +++++++++++++ Tactical/Interface Items.h | 1 + Tactical/Interface Panels.cpp | 141 ++++++++++++++++++--------------- Tactical/Interface.cpp | 17 +++- Tactical/Overhead.cpp | 14 +++- Tactical/Real Time Input.cpp | 29 ++++--- Tactical/Soldier Add.cpp | 5 +- Tactical/Soldier Add.h | 2 +- Tactical/Soldier Control.cpp | 51 ++++++------ Tactical/Soldier macros.h | 3 +- Tactical/Turn Based Input.cpp | 55 +++++++++---- Tactical/Vehicles.cpp | 60 +++++++++----- 17 files changed, 368 insertions(+), 156 deletions(-) diff --git a/GameSettings.cpp b/GameSettings.cpp index d62ed292..7ab67de6 100644 --- a/GameSettings.cpp +++ b/GameSettings.cpp @@ -1381,6 +1381,8 @@ void LoadGameExternalOptions() else gGameExternalOptions.fSoldierProfiles_Militia = FALSE; + gGameExternalOptions.fAllowDrivingVehiclesInTactical = iniReader.ReadBoolean("Tactical Gameplay Settings","ALLOW_DRIVING_VEHICLES_IN_TACTICAL", TRUE); + gGameExternalOptions.ubAPSharedAmongPassengersAndVehicleMode = iniReader.ReadInteger("Tactical Gameplay Settings","AP_SHARED_AMONG_PASSENGERS_AND_VEHICLE_MODE", 3, 0, 3); gGameExternalOptions.ubAPSharedAmongPassengersAndVehicleScale = iniReader.ReadInteger("Tactical Gameplay Settings","AP_SHARED_AMONG_PASSENGERS_AND_VEHICLE_SCALE", 100, 0, 200); @@ -1465,6 +1467,11 @@ void LoadGameExternalOptions() // anv: automatically return to team panel on turn end (better situation overview during enemy turn) gGameExternalOptions.fAutoCollapseInventoryOnTurnEnd = iniReader.ReadBoolean("Tactical Interface Settings","AUTO_COLLAPSE_INVENTORY_ON_TURN_END", TRUE); + + // anv: vehicle interface options + gGameExternalOptions.fAddPassengerToAnySquad = iniReader.ReadBoolean("Tactical Interface Settings","ADD_PASSENGER_TO_ANY_SQUAD", TRUE); + gGameExternalOptions.fPassengerLeavingSwitchToNewSquad = iniReader.ReadBoolean("Tactical Interface Settings","PASSENGER_LEAVING_SWITCH_TO_NEW_SQUAD", FALSE); + // *** ddd - END // SANDRO - Improved camo applying and camo can be removed diff --git a/GameSettings.h b/GameSettings.h index 78246df5..4f3ec9cf 100644 --- a/GameSettings.h +++ b/GameSettings.h @@ -833,6 +833,10 @@ typedef struct // anv: automatically return to team panel on turn end (better situation overview during enemy turn) BOOLEAN fAutoCollapseInventoryOnTurnEnd; + // anv: vehicle interface options + BOOLEAN fAddPassengerToAnySquad; + BOOLEAN fPassengerLeavingSwitchToNewSquad; + // WANNE: Always use "prof.dat". BOOLEAN fUseDifficultyBasedProfDat; @@ -1451,6 +1455,8 @@ typedef struct UINT8 ubExtremeIronManSavingTimeNotification; UINT8 ubExtremeIronManSavingHour; + BOOLEAN fAllowDrivingVehiclesInTactical; + UINT8 ubAPSharedAmongPassengersAndVehicleMode; UINT8 ubAPSharedAmongPassengersAndVehicleScale; diff --git a/Tactical/Animation Control.cpp b/Tactical/Animation Control.cpp index 18f6b35d..7abd3161 100644 --- a/Tactical/Animation Control.cpp +++ b/Tactical/Animation Control.cpp @@ -3504,6 +3504,7 @@ void InitAnimationSurfacesPerBodytype( ) // TANK gubAnimSurfaceIndex[ TANK_NW ][ STANDING ] = TANKNW_READY; gubAnimSurfaceIndex[ TANK_NW ][ WALKING ] = TANKNW_READY; + gubAnimSurfaceIndex[ TANK_NW ][ RUNNING ] = TANKNW_READY; gubAnimSurfaceIndex[ TANK_NW ][ WALK_BACKWARDS ] = TANKNW_READY; gubAnimSurfaceIndex[ TANK_NW ][ TANK_SHOOT ] = TANKNW_SHOOT; gubAnimSurfaceIndex[ TANK_NW ][ TANK_BURST ] = TANKNW_SHOOT; @@ -3513,6 +3514,7 @@ void InitAnimationSurfacesPerBodytype( ) // TANK gubAnimSurfaceIndex[ TANK_NE ][ STANDING ] = TANKNE_READY; gubAnimSurfaceIndex[ TANK_NE ][ WALKING ] = TANKNE_READY; + gubAnimSurfaceIndex[ TANK_NE ][ RUNNING ] = TANKNE_READY; gubAnimSurfaceIndex[ TANK_NE ][ WALK_BACKWARDS ] = TANKNE_READY; gubAnimSurfaceIndex[ TANK_NE ][ TANK_SHOOT ] = TANKNE_SHOOT; gubAnimSurfaceIndex[ TANK_NE ][ TANK_BURST ] = TANKNE_SHOOT; diff --git a/Tactical/Handle Items.cpp b/Tactical/Handle Items.cpp index d1c3c525..acd3ee7c 100644 --- a/Tactical/Handle Items.cpp +++ b/Tactical/Handle Items.cpp @@ -5825,6 +5825,12 @@ BOOLEAN NearbyGroundSeemsWrong( SOLDIERTYPE * pSoldier, INT32 sGridNo, BOOLEAN f fCheckFlag = MAPELEMENT_ENEMY_MINE_PRESENT; } + // anv: vehicles and passengers can't detect mines + if ( pSoldier->flags.uiStatusFlags & ( SOLDIER_VEHICLE | SOLDIER_DRIVER | SOLDIER_PASSENGER )) + { + return (FALSE); + } + // check every tile around gridno for the presence of "nasty stuff" for (ubDirection = 0; ubDirection < NUM_WORLD_DIRECTIONS; ++ubDirection) { diff --git a/Tactical/Handle UI.cpp b/Tactical/Handle UI.cpp index 4851bc62..7fa53aa8 100644 --- a/Tactical/Handle UI.cpp +++ b/Tactical/Handle UI.cpp @@ -1459,6 +1459,7 @@ UINT32 UIHandleSelectMerc( UI_EVENT *pUIEvent ) UINT32 UIHandleMOnTerrain( UI_EVENT *pUIEvent ) { SOLDIERTYPE *pSoldier; + SOLDIERTYPE *pVehicle; INT32 usMapPos; BOOLEAN fSetCursor = FALSE; UINT32 uiCursorFlags; @@ -1466,6 +1467,7 @@ UINT32 UIHandleMOnTerrain( UI_EVENT *pUIEvent ) EXITGRID ExitGrid; INT32 sIntTileGridNo; ITEM_POOL *pItemPool; + BOOLEAN fVehicleDriver = FALSE; static INT32 sGridNoForItemsOver; static INT8 bLevelForItemsOver; @@ -1477,22 +1479,9 @@ UINT32 UIHandleMOnTerrain( UI_EVENT *pUIEvent ) 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 ); - // } - // } - //} - - // If we are a passenger or driver just show an X - if ( GetSoldier( &pSoldier, gusSelectedSoldier ) ) + if ( !gGameExternalOptions.fAllowDrivingVehiclesInTactical && GetSoldier( &pSoldier, gusSelectedSoldier ) ) { - if ( ( pSoldier->flags.uiStatusFlags & ( SOLDIER_DRIVER | SOLDIER_PASSENGER )) ) + if ( ( OK_ENTERABLE_VEHICLE( pSoldier ) ) ) { if ( !UIHandleOnMerc( TRUE ) ) { @@ -1502,6 +1491,24 @@ UINT32 UIHandleMOnTerrain( UI_EVENT *pUIEvent ) } } + // If we are a passenger or driver just show an X + if ( GetSoldier( &pSoldier, gusSelectedSoldier ) ) + { + if ( ( pSoldier->flags.uiStatusFlags & ( SOLDIER_PASSENGER )) ) + { + if ( !UIHandleOnMerc( TRUE ) ) + { + guiNewUICursor = FLOATING_X_UICURSOR; + return( GAME_SCREEN ); + } + } + else if ( pSoldier->flags.uiStatusFlags & (SOLDIER_DRIVER ) ) + { + pVehicle = GetSoldierStructureForVehicle( pSoldier->iVehicleId ); + fVehicleDriver = TRUE; + } + } + // CHECK IF WE'RE ON A GUY ( EITHER SELECTED, OURS, OR THEIRS if ( !UIHandleOnMerc( TRUE ) ) { @@ -1572,6 +1579,11 @@ UINT32 UIHandleMOnTerrain( UI_EVENT *pUIEvent ) // Get Soldier Pointer GetSoldier( &pSoldier, gusSelectedSoldier ); + if( fVehicleDriver ) + { + pSoldier = pVehicle; + } + // Get interactvie tile node pIntNode = GetCurInteractiveTileGridNo( &sIntTileGridNo ); @@ -1879,6 +1891,11 @@ UINT32 UIHandleCWait( UI_EVENT *pUIEvent ) if ( GetSoldier( &pSoldier, gusSelectedSoldier ) ) { + if( pSoldier->flags.uiStatusFlags & SOLDIER_DRIVER ) + { + pSoldier = GetSoldierStructureForVehicle( MercPtrs[ gusSelectedSoldier ]->iVehicleId ); + } + pInvTile = GetCurInteractiveTile( ); if ( pInvTile && gpInvTileThatCausedMoveConfirm != pInvTile ) @@ -2026,6 +2043,12 @@ UINT32 UIHandleCMoveMerc( UI_EVENT *pUIEvent ) // Get soldier if ( GetSoldier( &pSoldier, gusSelectedSoldier ) ) { + // anv: if we selected vehicle driver, move his vehicle + if ( pSoldier->flags.uiStatusFlags & (SOLDIER_DRIVER ) ) + { + pSoldier = GetSoldierStructureForVehicle( MercPtrs[ pSoldier->ubID ]->iVehicleId ); + } + // CHRISL: This block should only run if we're running in the new inventory system if((UsingNewInventorySystem() == true)) { @@ -3196,6 +3219,16 @@ UINT32 UIHandleHCOnTerrain( UI_EVENT *pUIEvent ) return( GAME_SCREEN ); } + // If we are a passenger or driver just show an ? + if ( GetSoldier( &pSoldier, gusSelectedSoldier ) ) + { + if ( ( pSoldier->flags.uiStatusFlags & ( SOLDIER_VEHICLE | SOLDIER_DRIVER | SOLDIER_PASSENGER )) ) + { + guiNewUICursor = INVALID_ACTION_UICURSOR; + return( GAME_SCREEN ); + } + } + // If we are out of breath, no cursor... if ( pSoldier->bBreath < OKBREATH && pSoldier->bCollapsed ) { @@ -3498,6 +3531,11 @@ void UIHandleSoldierStanceChange( UINT8 ubSoldierID, INT8 bNewStance ) { SOLDIERTYPE *pSoldier = MercPtrs[ ubSoldierID ]; + if( pSoldier->flags.uiStatusFlags & SOLDIER_DRIVER ) + { + pSoldier = GetSoldierStructureForVehicle( pSoldier->iVehicleId ); + } + // Is this a valid stance for our position? if ( !IsValidStance( pSoldier, bNewStance ) ) { @@ -4979,7 +5017,7 @@ BOOLEAN MakeSoldierTurn( SOLDIERTYPE *pSoldier, INT16 sXPos, INT16 sYPos ) INT32 iBPCpst = 0; // Make sure the merc is not collapsed! - if (!IsValidStance(pSoldier, ANIM_CROUCH) ) + if (!IsValidStance(pSoldier, ANIM_CROUCH) && !( pSoldier->flags.uiStatusFlags & ( SOLDIER_DRIVER | SOLDIER_PASSENGER ) && !IsValidStance(pSoldier, ANIM_STAND) ) ) { if ( pSoldier->bCollapsed && pSoldier->bBreath < OKBREATH ) { diff --git a/Tactical/Interface Items.cpp b/Tactical/Interface Items.cpp index b65ef319..d1109bf2 100644 --- a/Tactical/Interface Items.cpp +++ b/Tactical/Interface Items.cpp @@ -4372,6 +4372,61 @@ void INVRenderItem( UINT32 uiBuffer, SOLDIERTYPE * pSoldier, OBJECTTYPE *pObjec } } +void INVRenderSteeringWheel( UINT32 uiBuffer, UINT32 uiSteeringWheelIndex, SOLDIERTYPE *pSoldier, INT16 sX, INT16 sY, INT16 sWidth, INT16 sHeight, UINT8 fDirtyLevel ) +{ + SOLDIERTYPE *pVehicle = NULL; + UINT32 usHeight, usWidth; + INT16 sNewY, sNewX; + + static CHAR16 pStr[ 100 ], pStr2[ 100 ]; + + if ( pSoldier == NULL ) + { + return; + } + + pVehicle = GetSoldierStructureForVehicle ( MercPtrs[ pSoldier->ubID ]->iVehicleId ); + + if ( pVehicle == NULL ) + { + return; + } + + SetFont( ITEM_FONT ); + + if ( fDirtyLevel != DIRTYLEVEL0 ) + { + BltVideoObjectFromIndex( guiSAVEBUFFER, uiSteeringWheelIndex, 0, sX, sY, VO_BLT_SRCTRANSPARENCY, NULL ); + RestoreExternBackgroundRect( sX, sY, (INT16)( sWidth ), (INT16)( sHeight ) ); + + if( !gGameExternalOptions.fAllowDrivingVehiclesInTactical ) + { + return; + } + + sNewY = sY + sHeight - 10; + sNewX = sX + 1; + + if ( uiBuffer == guiSAVEBUFFER ) + { + RestoreExternBackgroundRect( sNewX, sNewY, 20, 15 ); + } + + if( ( gTacticalStatus.uiFlags & TURNBASED ) && ( gTacticalStatus.uiFlags & INCOMBAT ) ) + { + SetFontBackground( FONT_MCOLOR_BLACK ); + SetFontForeground( FONT_MCOLOR_DKGRAY ); + + swprintf( pStr, L"%d", pVehicle->bActionPoints ); + mprintf( sNewX, sNewY, pStr ); + gprintfinvalidate( sNewX, sNewY, pStr ); + } + } + + DrawLifeUIBarEx( pVehicle, sX + sWidth - 10, sY + sHeight - 1, ITEMDESC_ITEM_STATUS_WIDTH, sHeight - 3, TRUE, FRAME_BUFFER ); + DrawBreathUIBarEx( pVehicle, sX + sWidth - 7, sY + sHeight - 1, ITEMDESC_ITEM_STATUS_WIDTH, sHeight - 3, TRUE, FRAME_BUFFER ); +} + // HEADROCK HAM 5.1: Render item in a BigItem sector inventory slot. // This function works largely like the one above it, with several exceptions. For one, the BigItemPic is used, // which allows us to add lots of data. Since this is only used in the sector inventory, we can forgo things diff --git a/Tactical/Interface Items.h b/Tactical/Interface Items.h index c1e5755a..1ebd241f 100644 --- a/Tactical/Interface Items.h +++ b/Tactical/Interface Items.h @@ -226,6 +226,7 @@ BOOLEAN HandleCompatibleAmmoUI( SOLDIERTYPE *pSoldier, INT8 bInvPos, BOOLEAN fOn void RenderBulletIcon(OBJECTTYPE *pObject, UINT32 ubStatusIndex = 0); void INVRenderItem( UINT32 uiBuffer, SOLDIERTYPE * pSoldier, OBJECTTYPE *pObject, INT16 sX, INT16 sY, INT16 sWidth, INT16 sHeight, UINT8 fDirtyLevel, UINT8 *pubHighlightCounter, UINT8 ubStatusIndex, BOOLEAN fOutline, INT16 sOutlineColor, UINT8 iter = 0 ); +void INVRenderSteeringWheel( UINT32 uiBuffer, UINT32 uiSteeringWheelIndex, SOLDIERTYPE *pSoldier, INT16 sX, INT16 sY, INT16 sWidth, INT16 sHeight, UINT8 fDirtyLevel ); // HEADROCK HAM 5: Drawing a large item pic with extra data. void MAPINVRenderItem( UINT32 uiBuffer, SOLDIERTYPE * pSoldier, OBJECTTYPE *pObject, UINT32 uiItemGraphicNum, INT16 sX, INT16 sY, INT16 sWidth, INT16 sHeight, BOOLEAN fOutline, INT16 sOutlineColor ); // CHRISL: Add a new function that will be used to render a pocket silhouette diff --git a/Tactical/Interface Panels.cpp b/Tactical/Interface Panels.cpp index 4de0183e..0d87ae66 100644 --- a/Tactical/Interface Panels.cpp +++ b/Tactical/Interface Panels.cpp @@ -581,25 +581,9 @@ extern BOOLEAN gfMouseLockedOnBorder; // Wraps up check for AP-s get from a different soldier for in a vehicle... INT16 GetUIApsToDisplay( SOLDIERTYPE *pSoldier ) { - SOLDIERTYPE *pVehicle; - if ( pSoldier->flags.uiStatusFlags & SOLDIER_DRIVER ) - { - pVehicle = GetSoldierStructureForVehicle( pSoldier->iVehicleId ); + return ( pSoldier->bActionPoints ); - if ( pVehicle != NULL ) - { - return( pVehicle->bActionPoints ); - } - else - { - return( 0 ); - } - } - else - { - return ( pSoldier->bActionPoints ); - } } void CheckForDisabledForGiveItem( ) @@ -684,6 +668,11 @@ void CheckForDisabledForGiveItem( ) gfSMDisableForItems = FALSE; } } + // anv: passengers in the same vehicle can pass items freely + else if ( MercPtrs[ ubSrcSoldier ]->iVehicleId != -1 && MercPtrs[ ubSrcSoldier ]->iVehicleId == MercPtrs[ gusSMCurrentMerc ]->iVehicleId ) + { + gfSMDisableForItems = FALSE; + } } else { @@ -4515,7 +4504,6 @@ void SelectedMercButtonMoveCallback( MOUSE_REGION * pRegion, INT32 iReason ) void SelectedMercButtonCallback( MOUSE_REGION * pRegion, INT32 iReason ) { - SOLDIERTYPE *pVehicle; if ( gpSMCurrentMerc == NULL ) { @@ -4535,24 +4523,15 @@ void SelectedMercButtonCallback( MOUSE_REGION * pRegion, INT32 iReason ) // ATE: Don't if this guy can't.... if ( !gfSMDisableForItems ) { - if ( gpSMCurrentMerc->flags.uiStatusFlags & ( SOLDIER_DRIVER | SOLDIER_PASSENGER ) ) + if ( CheckForMercContMove( gpSMCurrentMerc ) ) { - pVehicle = GetSoldierStructureForVehicle( gpSMCurrentMerc->iVehicleId ); - - HandleLocateSelectMerc( pVehicle->ubID, 0 ); + // Continue + ContinueMercMovement( gpSMCurrentMerc ); + ErasePath( TRUE ); } else { - if ( CheckForMercContMove( gpSMCurrentMerc ) ) - { - // Continue - ContinueMercMovement( gpSMCurrentMerc ); - ErasePath( TRUE ); - } - else - { - HandleLocateSelectMerc( gpSMCurrentMerc->ubID, 0 ); - } + HandleLocateSelectMerc( gpSMCurrentMerc->ubID, 0 ); } } } @@ -4599,10 +4578,10 @@ void SelectedMercEnemyIndicatorCallback( MOUSE_REGION * pRegion, INT32 iReason ) // ATE: Don't if this guy can't.... if ( !gfSMDisableForItems ) { - if ( gpSMCurrentMerc->flags.uiStatusFlags & ( SOLDIER_DRIVER | SOLDIER_PASSENGER ) ) - { - } - else + //if ( gpSMCurrentMerc->flags.uiStatusFlags & ( SOLDIER_DRIVER | SOLDIER_PASSENGER ) ) + //{ + //} + //else { if ( gpSMCurrentMerc->aiData.bOppCnt > 0 ) { @@ -6224,10 +6203,10 @@ void EnemyIndicatorClickCallback( MOUSE_REGION * pRegion, INT32 iReason ) if (iReason & MSYS_CALLBACK_REASON_LBUTTON_DWN) { - if ( MercPtrs[ ubSoldierID ]->flags.uiStatusFlags & ( SOLDIER_DRIVER | SOLDIER_PASSENGER ) ) - { - } - else + //if ( MercPtrs[ ubSoldierID ]->flags.uiStatusFlags & ( SOLDIER_DRIVER | SOLDIER_PASSENGER ) ) + //{ + //} + //else { SOLDIERTYPE *pSoldier; @@ -6249,7 +6228,6 @@ void EnemyIndicatorClickCallback( MOUSE_REGION * pRegion, INT32 iReason ) void MercFacePanelCallback( MOUSE_REGION * pRegion, INT32 iReason ) { UINT8 ubID, ubSoldierID; - SOLDIERTYPE *pVehicle; ubID = (UINT8) MSYS_GetRegionUserData( pRegion, 0 ); @@ -6765,9 +6743,8 @@ void RenderSoldierTeamInv( SOLDIERTYPE *pSoldier, INT16 sX, INT16 sY, UINT8 ubPa if ( pSoldier->bActive && !(pSoldier->flags.uiStatusFlags & SOLDIER_DEAD ) ) { if ( pSoldier->flags.uiStatusFlags & SOLDIER_DRIVER ) - { - BltVideoObjectFromIndex( guiSAVEBUFFER, guiVEHINV, 0, sX, sY, VO_BLT_SRCTRANSPARENCY, NULL ); - RestoreExternBackgroundRect( sX, sY, (INT16)( TM_INV_WIDTH ) , (INT16)( TM_INV_HEIGHT ) ); + { + INVRenderSteeringWheel( guiSAVEBUFFER, guiVEHINV, pSoldier, sX, sY, TM_INV_WIDTH, TM_INV_HEIGHT, fDirty ); } else { @@ -6860,12 +6837,12 @@ void TMClickFirstHandInvCallback( MOUSE_REGION * pRegion, INT32 iReason ) if (iReason == MSYS_CALLBACK_REASON_LBUTTON_UP ) { // anv: select vehicle by clicking on the steering wheel - if ( MercPtrs[ ubSoldierID ]->flags.uiStatusFlags & SOLDIER_DRIVER ) - { - SOLDIERTYPE *pVehicle = GetSoldierStructureForVehicle( MercPtrs[ ubSoldierID ]->iVehicleId ); - HandleLocateSelectMerc( pVehicle->ubID, 0 ); - } - else + //if ( MercPtrs[ ubSoldierID ]->flags.uiStatusFlags & SOLDIER_DRIVER ) + //{ + // SOLDIERTYPE *pVehicle = GetSoldierStructureForVehicle( MercPtrs[ ubSoldierID ]->iVehicleId ); + // HandleLocateSelectMerc( pVehicle->ubID, 0 ); + //} + //else { // Change to use cursor mode... guiPendingOverrideEvent = A_ON_TERRAIN; @@ -6997,29 +6974,63 @@ void AddPlayerToInterfaceTeamSlot( UINT8 ubID ) return; } - if ( !PlayerExistsInSlot( ubID ) ) - { - // Find a free slot - for ( cnt = 0; cnt < gGameOptions.ubSquadSize; cnt++ ) + //if ( !( MercPtrs[ ubID ]->flags.uiStatusFlags & ( SOLDIER_DRIVER | SOLDIER_PASSENGER ) ) ) + //{ + if ( !PlayerExistsInSlot( ubID ) ) { - if ( !gTeamPanel[ cnt ].fOccupied ) + // Find a free slot + for ( cnt = 0; cnt < gGameOptions.ubSquadSize; cnt++ ) { - gTeamPanel[ cnt ].fOccupied = TRUE; - gTeamPanel[ cnt ].ubID = ubID; + if ( !gTeamPanel[ cnt ].fOccupied ) + { + gTeamPanel[ cnt ].fOccupied = TRUE; + gTeamPanel[ cnt ].ubID = ubID; - MSYS_SetRegionUserData( &gTEAM_FirstHandInv[ cnt ], 0, cnt ); - MSYS_SetRegionUserData( &gTEAM_FaceRegions[ cnt ], 0, cnt ); + MSYS_SetRegionUserData( &gTEAM_FirstHandInv[ cnt ], 0, cnt ); + MSYS_SetRegionUserData( &gTEAM_FaceRegions[ cnt ], 0, cnt ); - // DIRTY INTERFACE - fInterfacePanelDirty = DIRTYLEVEL2; + // DIRTY INTERFACE + fInterfacePanelDirty = DIRTYLEVEL2; - // Set ID to do open anim - MercPtrs[ ubID ]->flags.fUInewMerc = TRUE; + // Set ID to do open anim + MercPtrs[ ubID ]->flags.fUInewMerc = TRUE; - break; + break; + } } } - } + //} + //else + //{ + // // anv: for passengers, position on team panel will be linked with seat in vehicle + // if ( MercPtrs[ ubID ]->flags.uiStatusFlags & ( SOLDIER_DRIVER | SOLDIER_PASSENGER ) ) + // { + // SOLDIERTYPE *pVehicle = GetSoldierStructureForVehicle( MercPtrs[ ubID ]->iVehicleId ); + // if( pVehicle != NULL ) + // { + // for( UINT8 iCounter = 0; iCounter < gNewVehicle[ pVehicleList[ MercPtrs[ ubID ]->iVehicleId ].ubVehicleType ].iNewSeatingCapacities; iCounter++ ) + // { + // SOLDIERTYPE *pPassenger = pVehicleList[ MercPtrs[ ubID ]->iVehicleId ].pPassengers[ iCounter ]; + // if( pPassenger != NULL && pPassenger->ubID == ubID ) + // { + // gTeamPanel[ iCounter ].fOccupied = TRUE; + // gTeamPanel[ iCounter ].ubID = ubID; + + // MSYS_SetRegionUserData( &gTEAM_FirstHandInv[ iCounter ], 0, iCounter ); + // MSYS_SetRegionUserData( &gTEAM_FaceRegions[ iCounter ], 0, iCounter ); + + // // DIRTY INTERFACE + // fInterfacePanelDirty = DIRTYLEVEL2; + + // // Set ID to do open anim + // MercPtrs[ ubID ]->flags.fUInewMerc = TRUE; + // + // return; + // } + // } + // } + // } + //} } BOOLEAN InitTEAMSlots( ) diff --git a/Tactical/Interface.cpp b/Tactical/Interface.cpp index 9962831a..072c4ad6 100644 --- a/Tactical/Interface.cpp +++ b/Tactical/Interface.cpp @@ -1605,6 +1605,12 @@ void GetSoldierAboveGuyPositions( SOLDIERTYPE *pSoldier, INT16 *psX, INT16 *psY, } + // anv: passengers sit, but we want to display their names above vehicle + if( pSoldier->flags.uiStatusFlags & ( SOLDIER_DRIVER | SOLDIER_PASSENGER ) ) + { + sStanceOffset = 0; + } + //sStanceOffset -= gpWorldLevelData[ pSoldier->sGridNo ].sHeight; // Adjust based on level @@ -1962,6 +1968,15 @@ void DrawSelectedUIAboveGuy( UINT16 usSoldierID ) mprintf( sX, sY, NameStr ); fRaiseName = TRUE; } + // anv: if soldier is in vehicle, write its name instead of "vehicle" + else if ( pSoldier->bAssignment == VEHICLE ) + { + swprintf( NameStr, L"(%s)", GetSoldierStructureForVehicle( pSoldier->iVehicleId )->GetName() ); + FindFontCenterCoordinates( sXPos, (INT16)(sYPos ), (INT16)(80 ), 1, NameStr, TINYFONT1, &sX, &sY ); + gprintfdirty( sX, sY, NameStr ); + mprintf( sX, sY, NameStr ); + fRaiseName = TRUE; + } else if ( pSoldier->bAssignment >= ON_DUTY ) { SetFontForeground( FONT_YELLOW ); @@ -1994,7 +2009,7 @@ void DrawSelectedUIAboveGuy( UINT16 usSoldierID ) } else { - if ( pSoldier->bAssignment >= ON_DUTY ) + if ( pSoldier->bAssignment >= ON_DUTY && pSoldier->bAssignment != VEHICLE ) { SetFontForeground( FONT_YELLOW ); } diff --git a/Tactical/Overhead.cpp b/Tactical/Overhead.cpp index 2db7a2da..09c66902 100644 --- a/Tactical/Overhead.cpp +++ b/Tactical/Overhead.cpp @@ -3102,6 +3102,11 @@ void InternalSelectSoldier( UINT16 usSoldierID, BOOLEAN fAcknowledge, BOOLEAN fF // Get guy pSoldier = MercPtrs[ usSoldierID ]; + if( ( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) ) + { + pSoldier = GetDriver( pSoldier->iVehicleId ); + usSoldierID = pSoldier->ubID; + } // If we are dead, ignore if ( !OK_CONTROLLABLE_MERC( pSoldier) ) @@ -3163,7 +3168,14 @@ void InternalSelectSoldier( UINT16 usSoldierID, BOOLEAN fAcknowledge, BOOLEAN fF gusSelectedSoldier = (UINT16)usSoldierID; // find which squad this guy is, then set selected squad to this guy - SetCurrentSquad( pSoldier -> bAssignment, FALSE ); + if( pSoldier->bAssignment == VEHICLE ) + { + SetCurrentSquad( GetSoldierStructureForVehicle(pSoldier->iVehicleId)->bAssignment, FALSE ); + } + else + { + SetCurrentSquad( pSoldier->bAssignment, FALSE ); + } if ( pSoldier->pathing.bLevel == 0 ) { diff --git a/Tactical/Real Time Input.cpp b/Tactical/Real Time Input.cpp index 7f4fac52..fe35385d 100644 --- a/Tactical/Real Time Input.cpp +++ b/Tactical/Real Time Input.cpp @@ -61,6 +61,7 @@ #include "SkillMenu.h" // sevenfm: need this for TraitsMenu +#include "Vehicles.h" // anv: for switching from soldier to vehicle #endif @@ -177,6 +178,7 @@ void QueryRTLeftButton( UINT32 *puiNewEvent ) { UINT16 usSoldierIndex; SOLDIERTYPE *pSoldier; + SOLDIERTYPE *pVehicle; UINT32 uiMercFlags; static UINT32 uiSingleClickTime; INT32 usMapPos; @@ -184,7 +186,7 @@ void QueryRTLeftButton( UINT32 *puiNewEvent ) static BOOLEAN fValidDoubleClickPossible = FALSE; static BOOLEAN fCanCheckForSpeechAdvance = FALSE; static INT32 sMoveClickGridNo = 0; - + UINT16 usSubjectSoldier = gusSelectedSoldier; // LEFT MOUSE BUTTON if ( gViewportRegion.uiFlags & MSYS_MOUSE_IN_AREA ) @@ -200,6 +202,11 @@ void QueryRTLeftButton( UINT32 *puiNewEvent ) { return; } + if ( MercPtrs[ gusSelectedSoldier ]->flags.uiStatusFlags & SOLDIER_DRIVER ) + { + pVehicle = GetSoldierStructureForVehicle( MercPtrs[ usSubjectSoldier ]->iVehicleId ); + usSubjectSoldier = pVehicle->ubID; + } } if ( gViewportRegion.ButtonState & MSYS_LEFT_BUTTON ) @@ -299,9 +306,9 @@ void QueryRTLeftButton( UINT32 *puiNewEvent ) { BOOLEAN fResult; - if ( gusSelectedSoldier != NOBODY ) + if ( usSubjectSoldier != NOBODY ) { - if ( ( fResult = UIOKMoveDestination( MercPtrs[ gusSelectedSoldier ], usMapPos ) ) == 1 ) + if ( ( fResult = UIOKMoveDestination( MercPtrs[ usSubjectSoldier ], usMapPos ) ) == 1 ) { if ( gsCurrentActionPoints != 0 ) { @@ -432,14 +439,14 @@ void QueryRTLeftButton( UINT32 *puiNewEvent ) fDoubleClickIntercepted = TRUE; // First check if we clicked on a guy, if so, make selected if it's ours - if( gusSelectedSoldier != NOBODY ) + if( usSubjectSoldier != NOBODY ) { // Set movement mode // OK, only change this if we are stationary! //if ( gAnimControl[ MercPtrs[ gusSelectedSoldier ]->usAnimState ].uiFlags & ANIM_STATIONARY ) //if ( MercPtrs[ gusSelectedSoldier ]->usAnimState == WALKING ) { - MercPtrs[ gusSelectedSoldier ]->flags.fUIMovementFast = TRUE; + MercPtrs[ usSubjectSoldier ]->flags.fUIMovementFast = TRUE; *puiNewEvent = C_MOVE_MERC; } } @@ -578,15 +585,15 @@ void QueryRTLeftButton( UINT32 *puiNewEvent ) case CONFIRM_MOVE_MODE: - if ( gusSelectedSoldier != NOBODY ) + if ( usSubjectSoldier != NOBODY ) { - if ( MercPtrs[ gusSelectedSoldier ]->usAnimState != RUNNING ) + if ( MercPtrs[ usSubjectSoldier ]->usAnimState != RUNNING ) { *puiNewEvent = C_MOVE_MERC; } else { - MercPtrs[ gusSelectedSoldier ]->flags.fUIMovementFast = 2; + MercPtrs[ usSubjectSoldier ]->flags.fUIMovementFast = 2; *puiNewEvent = C_MOVE_MERC; } } @@ -749,7 +756,7 @@ void QueryRTLeftButton( UINT32 *puiNewEvent ) } else if ( bReturnCode == 0 ) { - if( GetSoldier( &pSoldier, gusSelectedSoldier ) ) + if( GetSoldier( &pSoldier, usSubjectSoldier ) ) { // First check if we clicked on a guy, if so, make selected if it's ours if( FindSoldierFromMouse( &usSoldierIndex, &uiMercFlags ) && ( uiMercFlags & OWNED_MERC ) ) @@ -770,9 +777,9 @@ void QueryRTLeftButton( UINT32 *puiNewEvent ) { BOOLEAN fResult; - if ( gusSelectedSoldier != NOBODY ) + if ( usSubjectSoldier != NOBODY ) { - if ( ( fResult = UIOKMoveDestination( MercPtrs[ gusSelectedSoldier ], usMapPos ) ) == 1 ) + if ( ( fResult = UIOKMoveDestination( MercPtrs[ usSubjectSoldier ], usMapPos ) ) == 1 ) { if ( gfUIAllMoveOn ) { diff --git a/Tactical/Soldier Add.cpp b/Tactical/Soldier Add.cpp index 558cfff5..c53f13b2 100644 --- a/Tactical/Soldier Add.cpp +++ b/Tactical/Soldier Add.cpp @@ -606,7 +606,7 @@ INT32 FindGridNoFromSweetSpotWithStructDataUsingGivenDirectionFirst( SOLDIERTYPE } -INT32 FindGridNoFromSweetSpotWithStructDataFromSoldier( SOLDIERTYPE *pSoldier, UINT16 usAnimState, INT8 ubRadius, UINT8 *pubDirection, BOOLEAN fClosestToMerc, SOLDIERTYPE *pSrcSoldier ) +INT32 FindGridNoFromSweetSpotWithStructDataFromSoldier( SOLDIERTYPE *pSoldier, UINT16 usAnimState, INT8 ubRadius, UINT8 *pubDirection, BOOLEAN fClosestToMerc, SOLDIERTYPE *pSrcSoldier, BOOLEAN fAllowSoldierCurrentGrid ) { INT16 sTop, sBottom; INT16 sLeft, sRight; @@ -676,7 +676,8 @@ INT32 FindGridNoFromSweetSpotWithStructDataFromSoldier( SOLDIERTYPE *pSoldier, U && gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REACHABLE ) { // Go on sweet stop - if ( NewOKDestination( pSoldier, sGridNo, TRUE, pSoldier->pathing.bLevel ) ) + // anv: sometimes it's possible soldier already is on the best grid, NewOKDestination alone would skip it + if ( NewOKDestination( pSoldier, sGridNo, TRUE, pSoldier->pathing.bLevel ) || ( fAllowSoldierCurrentGrid && pSoldier->sGridNo == sGridNo ) ) { BOOLEAN fDirectionFound = FALSE; UINT16 usOKToAddStructID; diff --git a/Tactical/Soldier Add.h b/Tactical/Soldier Add.h index 14148047..51bbfd39 100644 --- a/Tactical/Soldier Add.h +++ b/Tactical/Soldier Add.h @@ -51,7 +51,7 @@ INT32 FindGridNoFromSweetSpotWithStructData( SOLDIERTYPE *pSoldier, UINT16 usAni void SoldierInSectorSleep( SOLDIERTYPE *pSoldier, INT16 sGridNo ); */ -INT32 FindGridNoFromSweetSpotWithStructDataFromSoldier( SOLDIERTYPE *pSoldier, UINT16 usAnimState, INT8 ubRadius, UINT8 *pubDirection, BOOLEAN fClosestToMerc, SOLDIERTYPE *pSrcSoldier ); +INT32 FindGridNoFromSweetSpotWithStructDataFromSoldier( SOLDIERTYPE *pSoldier, UINT16 usAnimState, INT8 ubRadius, UINT8 *pubDirection, BOOLEAN fClosestToMerc, SOLDIERTYPE *pSrcSoldier, BOOLEAN fAllowSoldierCurrentGrid = FALSE ); void SoldierInSectorPatient( SOLDIERTYPE *pSoldier, INT32 sGridNo ); void SoldierInSectorDoctor( SOLDIERTYPE *pSoldier, INT32 sGridNo ); diff --git a/Tactical/Soldier Control.cpp b/Tactical/Soldier Control.cpp index 088d891e..7cf2070b 100644 --- a/Tactical/Soldier Control.cpp +++ b/Tactical/Soldier Control.cpp @@ -1957,7 +1957,7 @@ INT16 SOLDIERTYPE::CalcActionPoints( void ) } // If tired, reduce action points accordingly (by up to 1/2) - if (this->bBreath < 100) + if (this->bBreath < 100 && !( this->flags.uiStatusFlags & SOLDIER_VEHICLE ) ) ubPoints -= (ubPoints * (100 - this->bBreath)) / 200; if (this->sWeightCarriedAtTurnStart > 100) @@ -7879,27 +7879,13 @@ void SOLDIERTYPE::TurnSoldier( void ) // If we are a vehicle... DON'T TURN! // anv: YES PLIZ DO - if ( this->flags.uiStatusFlags & SOLDIER_VEHICLE ) - { - //if ( this->ubBodyType != TANK_NW && this->ubBodyType != TANK_NE ) - //{ - // return; - //} - - // need to turn around passengers inside - INT32 iId = this->bVehicleID; - - // Loop through passengers and update each guy's rotation - for( INT32 iCounter = 0; iCounter < gNewVehicle[ pVehicleList[ iId ].ubVehicleType ].iNewSeatingCapacities; iCounter++ ) - { - if( pVehicleList[ iId ].pPassengers[ iCounter ] != NULL ) - { - pVehicleList[ iId ].pPassengers[ iCounter ]->flags.fDontChargeTurningAPs = TRUE; - pVehicleList[ iId ].pPassengers[ iCounter ]->EVENT_SetSoldierDesiredDirection( this->pathing.bDesiredDirection ); - //pVehicleList[ iId ].pPassengers[ iCounter ]->pathing.bDesiredDirection = this->pathing.bDesiredDirection; - } - } - } + //if ( this->flags.uiStatusFlags & SOLDIER_VEHICLE ) + //{ + // if ( this->ubBodyType != TANK_NW && this->ubBodyType != TANK_NE ) + // { + // return; + // } + //} //else // Lesh: patch for "Bug: Enemy turns around in turn based mode!" { // in case of errors in turning tasks @@ -8207,6 +8193,25 @@ void SOLDIERTYPE::TurnSoldier( void ) // This is needed for prone animations as well as any multi-tiled structs if ( fDoDirectionChange ) { + if ( this->flags.uiStatusFlags & SOLDIER_VEHICLE ) + { + // need to turn around passengers inside + INT32 iId = this->bVehicleID; + + // check which side vehicle turned + INT16 bDirectionChange = QuickestDirection( this->ubDirection, this->pathing.bDesiredDirection ); + + // Loop through passengers and update each guy's rotation + for( INT32 iCounter = 0; iCounter < gNewVehicle[ pVehicleList[ iId ].ubVehicleType ].iNewSeatingCapacities; iCounter++ ) + { + if( pVehicleList[ iId ].pPassengers[ iCounter ] != NULL ) + { + pVehicleList[ iId ].pPassengers[ iCounter ]->flags.fDontChargeTurningAPs = TRUE; + pVehicleList[ iId ].pPassengers[ iCounter ]->EVENT_SetSoldierDesiredDirection( ( pVehicleList[ iId ].pPassengers[ iCounter ]->pathing.bDesiredDirection + bDirectionChange + NUM_WORLD_DIRECTIONS ) % NUM_WORLD_DIRECTIONS ); + } + } + } + // If the soldier is not crawling or multi-tiled, he should be allowed to turn in place. Even if there is some // obstacle he shouldn't be standing on. if ( OKToAddMercToWorld( this, (INT8)sDirection ) ) @@ -8228,7 +8233,7 @@ void SOLDIERTYPE::TurnSoldier( void ) this->EVENT_SetSoldierDirection( sDirection ); - if ( this->ubBodyType != LARVAE_MONSTER && !this->MercInWater( ) && this->bOverTerrainType != DIRT_ROAD && this->bOverTerrainType != PAVED_ROAD ) + if ( this->ubBodyType != LARVAE_MONSTER && !this->MercInWater( ) && this->bOverTerrainType != DIRT_ROAD && this->bOverTerrainType != PAVED_ROAD && !( this->flags.uiStatusFlags & ( SOLDIER_DRIVER | SOLDIER_PASSENGER ) )) { PlaySoldierFootstepSound( this ); } diff --git a/Tactical/Soldier macros.h b/Tactical/Soldier macros.h index e6acaeb3..3b3bddfd 100644 --- a/Tactical/Soldier macros.h +++ b/Tactical/Soldier macros.h @@ -34,6 +34,7 @@ #define TANK( p ) (p->ubBodyType == TANK_NE || p->ubBodyType == TANK_NW ) -#define OK_ENTERABLE_VEHICLE( p ) ( ( p->flags.uiStatusFlags & SOLDIER_VEHICLE ) && !TANK( p ) && p->stats.bLife >= OKLIFE ) +//#define OK_ENTERABLE_VEHICLE( p ) ( ( p->flags.uiStatusFlags & SOLDIER_VEHICLE ) && !TANK( p ) && p->stats.bLife >= OKLIFE ) +#define OK_ENTERABLE_VEHICLE( p ) ( ( p->flags.uiStatusFlags & SOLDIER_VEHICLE ) && (!TANK( p ) || !(p->flags.uiStatusFlags & SOLDIER_ENEMY) ) && p->stats.bLife >= OKLIFE ) #endif \ No newline at end of file diff --git a/Tactical/Turn Based Input.cpp b/Tactical/Turn Based Input.cpp index 17a7df47..394977f0 100644 --- a/Tactical/Turn Based Input.cpp +++ b/Tactical/Turn Based Input.cpp @@ -5325,7 +5325,7 @@ INT8 CheckForAndHandleHandleVehicleInteractiveClick( SOLDIERTYPE *pSoldier, UINT if ( ( GetNumberInVehicle( pTSoldier->bVehicleID ) == 0 ) || !fMovementMode ) { // Find a gridno closest to sweetspot... - sActionGridNo = FindGridNoFromSweetSpotWithStructDataFromSoldier( pSoldier, pSoldier->usUIMovementMode, 5, &ubDirection, 0, pTSoldier ); + sActionGridNo = FindGridNoFromSweetSpotWithStructDataFromSoldier( pSoldier, pSoldier->usUIMovementMode, 5, &ubDirection, 0, pTSoldier, TRUE ); if (!TileIsOutOfBounds(sActionGridNo)) { @@ -5395,6 +5395,10 @@ void HandleHandCursorClick( INT32 usMapPos, UINT32 *puiNewEvent ) return; } + if ( pSoldier->flags.uiStatusFlags & ( SOLDIER_VEHICLE | SOLDIER_DRIVER | SOLDIER_PASSENGER ) ) + { + return; + } // Check if we are on a merc... if so.. steal! if ( gfUIFullTargetFound ) @@ -5563,20 +5567,27 @@ INT8 HandleMoveModeInteractiveClick( INT32 usMapPos, UINT32 *puiNewEvent ) //} // ATE: If we are a vehicle, no moving! - if ( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) + if ( !gGameExternalOptions.fAllowDrivingVehiclesInTactical && pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) { - // anv: yes moving - //ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, TacticalStr[ VEHICLE_CANT_MOVE_IN_TACTICAL ] ); - //return( -3 ); + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, TacticalStr[ VEHICLE_CANT_MOVE_IN_TACTICAL ] ); + return( -3 ); } - if ( pSoldier->flags.uiStatusFlags & ( SOLDIER_DRIVER | SOLDIER_PASSENGER ) ) + //if ( pSoldier->flags.uiStatusFlags & ( SOLDIER_DRIVER | SOLDIER_PASSENGER ) ) + if ( pSoldier->flags.uiStatusFlags & ( SOLDIER_PASSENGER ) ) { // anv: there's some weird bug with moving invisible passengers after loading game, that should solve it //ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, TacticalStr[ VEHICLE_CANT_MOVE_IN_TACTICAL ] ); + // actually, you know what, let's switch to vehicle using the occasion + HandleLocateSelectMerc( GetDriver(MercPtrs[ pSoldier->ubID ]->iVehicleId)->ubID, 0 ); return( -3 ); } + if ( pSoldier->flags.uiStatusFlags & ( SOLDIER_DRIVER ) ) + { + pSoldier = GetSoldierStructureForVehicle( MercPtrs[ pSoldier->ubID ]->iVehicleId ); + } + // OK, check for height differences..... if ( gpWorldLevelData[ usMapPos ].sHeight != gpWorldLevelData[ pSoldier->sGridNo ].sHeight ) { @@ -6775,6 +6786,13 @@ void SwapMercPortraits ( SOLDIERTYPE *pSoldier, INT8 bDirection ) // don't forget to renew selection of merc gusSelectedSoldier = ubTargetMerc; + // anv: if swapped guy was a driver, make sure vehicle driver ubID gets updates + if( MercPtrs[ ubTargetMerc ]->flags.uiStatusFlags & SOLDIER_DRIVER ) + { + pVehicleList[ pSoldier->iVehicleId ].ubDriver = MercPtrs[ ubTargetMerc ]->ubID; + } + + // refresh interface fCharacterInfoPanelDirty = TRUE; fTeamPanelDirty = TRUE; @@ -7763,22 +7781,27 @@ void HandleTBPickUpBackpacks( void ) } void HandleTBSoldierRun( void ) { - if ( !MercPtrs[ gusSelectedSoldier ]->MercInWater( ) && !(MercPtrs[ gusSelectedSoldier ]->flags.uiStatusFlags & SOLDIER_ROBOT ) ) + SOLDIERTYPE *pSoldier = MercPtrs[ gusSelectedSoldier ]; + if ( pSoldier->flags.uiStatusFlags & ( SOLDIER_DRIVER ) ) + { + pSoldier = GetSoldierStructureForVehicle( pSoldier->iVehicleId ); + } + if ( !pSoldier->MercInWater() && !(pSoldier->flags.uiStatusFlags & SOLDIER_ROBOT ) ) { //change selected merc to run - if ( MercPtrs[ gusSelectedSoldier ]->usUIMovementMode != WALKING - && MercPtrs[ gusSelectedSoldier ]->usUIMovementMode != RUNNING - && MercPtrs[ gusSelectedSoldier ]->usUIMovementMode != WALKING_WEAPON_RDY - && MercPtrs[ gusSelectedSoldier ]->usUIMovementMode != WALKING_DUAL_RDY - && MercPtrs[ gusSelectedSoldier ]->usUIMovementMode != WALKING_ALTERNATIVE_RDY ) + if ( pSoldier->usUIMovementMode != WALKING + && pSoldier->usUIMovementMode != RUNNING + && pSoldier->usUIMovementMode != WALKING_WEAPON_RDY + && pSoldier->usUIMovementMode != WALKING_DUAL_RDY + && pSoldier->usUIMovementMode != WALKING_ALTERNATIVE_RDY ) { - UIHandleSoldierStanceChange( (UINT8)gusSelectedSoldier, ANIM_STAND ); - MercPtrs[ gusSelectedSoldier ]->flags.fUIMovementFast = 1; + UIHandleSoldierStanceChange( (UINT8)pSoldier->ubID, ANIM_STAND ); + pSoldier->flags.fUIMovementFast = 1; } else { - MercPtrs[ gusSelectedSoldier ]->flags.fUIMovementFast = 1; - MercPtrs[ gusSelectedSoldier ]->usUIMovementMode = RUNNING; + pSoldier->flags.fUIMovementFast = 1; + pSoldier->usUIMovementMode = RUNNING; gfPlotNewMovement = TRUE; } } diff --git a/Tactical/Vehicles.cpp b/Tactical/Vehicles.cpp index 9d7dee94..bffd894a 100644 --- a/Tactical/Vehicles.cpp +++ b/Tactical/Vehicles.cpp @@ -770,7 +770,7 @@ BOOLEAN RemoveSoldierFromVehicle( SOLDIERTYPE *pSoldier, INT32 iId ) SOLDIERTYPE* pNewDriver = pVehicleList[ iId ].pPassengers[ iCounter ]; pNewDriver->flags.uiStatusFlags |= SOLDIER_DRIVER; pNewDriver->flags.uiStatusFlags &= ~(SOLDIER_PASSENGER); - pVehicleList[ iId ].ubDriver = pNewDriver->ubID; + SetDriver( iId, pNewDriver->ubID ); fNewDriverNeeded = FALSE; } } @@ -831,13 +831,13 @@ BOOLEAN RemoveSoldierFromVehicle( SOLDIERTYPE *pSoldier, INT32 iId ) TeleportVehicleToItsClosestSector( iId, pVehicleSoldier->ubGroupID ); } - // Remove vehicle from squad..... - RemoveCharacterFromSquads( pVehicleSoldier ); - // ATE: Add him back to vehicle group! - if ( !DoesPlayerExistInPGroup( pVehicleList[ iId ].ubMovementGroup, pVehicleSoldier ) ) - { - AddPlayerToGroup( pVehicleList[ iId ].ubMovementGroup, pVehicleSoldier ); - } + // Remove vehicle from squad..... + RemoveCharacterFromSquads( pVehicleSoldier ); + // ATE: Add him back to vehicle group! + if ( !DoesPlayerExistInPGroup( pVehicleList[ iId ].ubMovementGroup, pVehicleSoldier ) ) + { + AddPlayerToGroup( pVehicleList[ iId ].ubMovementGroup, pVehicleSoldier ); + } ChangeSoldiersAssignment( pVehicleSoldier, ASSIGNMENT_EMPTY ); @@ -1644,6 +1644,9 @@ BOOLEAN EnterVehicle( SOLDIERTYPE *pVehicle, SOLDIERTYPE *pSoldier, BOOLEAN fSpe SendChangeSoldierStanceEvent( pSoldier, ANIM_CROUCH ); // bInitialActionPoints - point in time where soldier and vehicle start sharing timeline pSoldier->bInitialActionPoints = pSoldier->bActionPoints; + // set proper rotation + pSoldier->flags.fDontChargeTurningAPs = TRUE; + pSoldier->EVENT_SetSoldierDesiredDirection( pVehicle->pathing.bDesiredDirection ); // OK, add.... AddSoldierToVehicle( pSoldier, pVehicle->bVehicleID, fSpecificSeat, ubSeatIndex ); @@ -1742,20 +1745,39 @@ BOOLEAN ExitVehicle( SOLDIERTYPE *pSoldier ) // Update visiblity..... HandleSight(pSoldier,SIGHT_LOOK | SIGHT_RADIO ); - - // Add to unique squad.... - AddCharacterToUniqueSquad( pSoldier ); - - // can't call SetCurrentSquad OR SelectSoldier in mapscreen, that will initialize interface panels!!! - if ( guiCurrentScreen == GAME_SCREEN ) + + if( !gGameExternalOptions.fAddPassengerToAnySquad ) { - SetCurrentSquad( pSoldier->bAssignment, TRUE ); - - SelectSoldier( pSoldier->ubID, FALSE, TRUE ); + // Add to unique squad.... + AddCharacterToUniqueSquad( pSoldier ); + } + else + { + // anv: optionally add to any squad + AddCharacterToAnySquad( pSoldier ); } - PlayJA2Sample( pVehicleList[ pVehicle->bVehicleID ].iOutOfSound, RATE_11025, SoundVolume( HIGHVOLUME, pVehicle->sGridNo ), 1, SoundDir( pVehicle->sGridNo ) ); - return( TRUE ); + // can't call SetCurrentSquad OR SelectSoldier in mapscreen, that will initialize interface panels!!! + if ( guiCurrentScreen == GAME_SCREEN ) + { + if( gGameExternalOptions.fPassengerLeavingSwitchToNewSquad ) + { + SetCurrentSquad( pSoldier->bAssignment, TRUE ); + + SelectSoldier( pSoldier->ubID, FALSE, TRUE ); + } + else + { + UINT16 usTempSelectedSoldier = gusSelectedSoldier; + + SetCurrentSquad( CurrentSquad(), TRUE ); + + SelectSoldier( usTempSelectedSoldier, FALSE, FALSE ); + } + + } + + PlayJA2Sample( pVehicleList[ pVehicle->bVehicleID ].iOutOfSound, RATE_11025, SoundVolume( HIGHVOLUME, pVehicle->sGridNo ), 1, SoundDir( pVehicle->sGridNo ) ); return( TRUE ); } return( FALSE );