Driveable vehicle Update: Externalized vehicle seats (by anv)

- externalised vehicle seats (TableData\Vehicles.xml) influence position of passenger, field of view, ability to shoot and being hidden,
- seat can chosen by using ctrl+RMB on vehicle (ctrl + LMB just takes the first visible seat)
- seats can be changed or swapped while inside vehicle,
- remade JSD files for cars,
- vehicles aren't transparent anymore,
- vehicles are louder than people, depending how fast they move.
see: http://www.bears-pit.com/board/ubbthreads.php/topics/332790/5.html


git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@7212 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
Wanne
2014-05-18 15:26:15 +00:00
parent cf1b9982ba
commit bbff053fc5
35 changed files with 1209 additions and 144 deletions
+6 -1
View File
@@ -16750,7 +16750,12 @@ SOLDIERTYPE *GetSelectedAssignSoldier( BOOLEAN fNullOK )
{
// better be an active person, not a vehicle
Assert( pSoldier->bActive );
Assert( !( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) );
// anv: don't assert, handle...
//Assert( !( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) );
if( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE )
{
pSoldier = GetDriver( pSoldier->iVehicleId );
}
}
return( pSoldier );
+15 -15
View File
@@ -777,27 +777,27 @@ AnimationStructureType gAnimStructureDatabase[ TOTALBODYTYPES ][ NUM_STRUCT_IDS
"ANIMS\\STRUCTDATA\\M_CROUCH.JSD", NULL, // default
//ELDORADO
"ANIMS\\STRUCTDATA\\HMMV.JSD", NULL,
"ANIMS\\STRUCTDATA\\HMMV.JSD", NULL,
"ANIMS\\STRUCTDATA\\HMMV.JSD", NULL,
"ANIMS\\STRUCTDATA\\HMMV.JSD", NULL,
"ANIMS\\STRUCTDATA\\HMMV.JSD", NULL,
"ANIMS\\STRUCTDATA\\ELDRDO.JSD", NULL,
"ANIMS\\STRUCTDATA\\ELDRDO.JSD", NULL,
"ANIMS\\STRUCTDATA\\ELDRDO.JSD", NULL,
"ANIMS\\STRUCTDATA\\ELDRDO.JSD", NULL,
"ANIMS\\STRUCTDATA\\ELDRDO.JSD", NULL,
"ANIMS\\STRUCTDATA\\M_CROUCH.JSD",NULL, // default
//ICECREAMTRUCK
"ANIMS\\STRUCTDATA\\HMMV.JSD", NULL,
"ANIMS\\STRUCTDATA\\HMMV.JSD", NULL,
"ANIMS\\STRUCTDATA\\HMMV.JSD", NULL,
"ANIMS\\STRUCTDATA\\HMMV.JSD", NULL,
"ANIMS\\STRUCTDATA\\HMMV.JSD", NULL,
"ANIMS\\STRUCTDATA\\ICECREAM.JSD", NULL,
"ANIMS\\STRUCTDATA\\ICECREAM.JSD", NULL,
"ANIMS\\STRUCTDATA\\ICECREAM.JSD", NULL,
"ANIMS\\STRUCTDATA\\ICECREAM.JSD", NULL,
"ANIMS\\STRUCTDATA\\ICECREAM.JSD", NULL,
"ANIMS\\STRUCTDATA\\M_CROUCH.JSD",NULL, // default
//JEEP
"ANIMS\\STRUCTDATA\\HMMV.JSD", NULL,
"ANIMS\\STRUCTDATA\\HMMV.JSD", NULL,
"ANIMS\\STRUCTDATA\\HMMV.JSD", NULL,
"ANIMS\\STRUCTDATA\\HMMV.JSD", NULL,
"ANIMS\\STRUCTDATA\\HMMV.JSD", NULL,
"ANIMS\\STRUCTDATA\\JEEP.JSD", NULL,
"ANIMS\\STRUCTDATA\\JEEP.JSD", NULL,
"ANIMS\\STRUCTDATA\\JEEP.JSD", NULL,
"ANIMS\\STRUCTDATA\\JEEP.JSD", NULL,
"ANIMS\\STRUCTDATA\\JEEP.JSD", NULL,
"ANIMS\\STRUCTDATA\\M_CROUCH.JSD",NULL, // default
};
+37 -14
View File
@@ -1491,14 +1491,14 @@ UINT32 UIHandleMOnTerrain( UI_EVENT *pUIEvent )
}
}
// If we are a passenger or driver just show an X
// If we are a passenger or driver just show ?
if ( GetSoldier( &pSoldier, gusSelectedSoldier ) )
{
if ( ( pSoldier->flags.uiStatusFlags & ( SOLDIER_PASSENGER )) )
{
if ( !UIHandleOnMerc( TRUE ) )
{
guiNewUICursor = FLOATING_X_UICURSOR;
guiNewUICursor = INVALID_ACTION_UICURSOR;
return( GAME_SCREEN );
}
}
@@ -3219,16 +3219,6 @@ 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 )
{
@@ -3445,6 +3435,20 @@ BOOLEAN UIHandleOnMerc( BOOLEAN fMovementMode )
// Check if this guy is on the enemy team....
if ( !pSoldier->aiData.bNeutral && (pSoldier->bSide != gbPlayerNum ) )
{
// anv: don't switch if passengers are blocked from attacking
if( gusSelectedSoldier != NOBODY )
{
SOLDIERTYPE *pSelectedSoldier = MercPtrs[gusSelectedSoldier];
if( pSelectedSoldier->flags.uiStatusFlags & ( SOLDIER_DRIVER | SOLDIER_PASSENGER ) )
{
SOLDIERTYPE *pVehicle = GetSoldierStructureForVehicle( pSelectedSoldier->iVehicleId );
INT8 bSeatIndex = GetSeatIndexFromSoldier( pSelectedSoldier );
if( gNewVehicle[ pVehicleList[ pSelectedSoldier->iVehicleId ].ubVehicleType ].VehicleSeats[bSeatIndex].fBlockedShots == TRUE )
{
return( FALSE );
}
}
}
gUIActionModeChangeDueToMouseOver = TRUE;
guiPendingOverrideEvent = M_CHANGE_TO_ACTION;
@@ -3531,7 +3535,7 @@ void UIHandleSoldierStanceChange( UINT8 ubSoldierID, INT8 bNewStance )
{
SOLDIERTYPE *pSoldier = MercPtrs[ ubSoldierID ];
if( pSoldier->flags.uiStatusFlags & SOLDIER_DRIVER )
if( pSoldier->flags.uiStatusFlags & ( SOLDIER_DRIVER | SOLDIER_PASSENGER ) )
{
pSoldier = GetSoldierStructureForVehicle( pSoldier->iVehicleId );
}
@@ -6371,11 +6375,30 @@ INT8 UIHandleInteractiveTilesAndItemsOnTerrain( SOLDIERTYPE *pSoldier, INT32 usM
gfBeginVehicleCursor = FALSE;
// If we are a passenger or driver just show an ?
if ( ( pSoldier->flags.uiStatusFlags & ( SOLDIER_VEHICLE | SOLDIER_DRIVER | SOLDIER_PASSENGER )) )
{
// unless we are over our own vehicle, then we can call vehicle menu
if( gfUIFullTargetFound )
{
pTSoldier = MercPtrs[ gusUIFullTargetID ];
if( pSoldier->iVehicleId == pTSoldier->bVehicleID )
{
guiNewUICursor = ENTER_VEHICLE_UICURSOR;
return( 1 );
}
}
guiNewUICursor = INVALID_ACTION_UICURSOR;
return( 0 );
}
if ( gfUIFullTargetFound )
{
pTSoldier = MercPtrs[ gusUIFullTargetID ];
if ( OK_ENTERABLE_VEHICLE( pTSoldier ) && pTSoldier->bVisible != -1 )
// anv: added condition - make sure we won't put vehicle in another vehicle
if ( OK_ENTERABLE_VEHICLE( pTSoldier ) && pTSoldier->bVisible != -1 && !( pSoldier->flags.uiStatusFlags & ( SOLDIER_DRIVER | SOLDIER_PASSENGER | SOLDIER_VEHICLE ) ) )
//if ( OK_ENTERABLE_VEHICLE( pTSoldier ) && pTSoldier->bVisible != -1 )
{
// grab number of occupants in vehicles
if ( fItemsOnlyIfOnIntTiles )
+1
View File
@@ -343,6 +343,7 @@ UINT32 UIHandleLUIEndLock( UI_EVENT *pUIEvent );
void BeginDisplayTimedCursor( UINT32 uiCursorID, UINT32 uiDelay );
void HandleHandCursorClick( INT32 usMapPos, UINT32 *puiNewEvent );
void HandleHandCursorRightClick( INT32 usMapPos, UINT32 *puiNewEvent );
INT8 HandleMoveModeInteractiveClick( INT32 usMapPos, UINT32 *puiNewEvent );
BOOLEAN HandleUIReloading( SOLDIERTYPE *pSoldier );
+40 -32
View File
@@ -5693,6 +5693,13 @@ void RenderTEAMPanel( BOOLEAN fDirty )
// clear pStr value
swprintf( pStr, L"");
INT8 bSeatIndex = GetSeatIndexFromSoldier( pSoldier );
if( bSeatIndex != (-1) )
{
swprintf( sTemp, L"%s\n", gNewVehicle[ pVehicleList[ pSoldier->iVehicleId ].ubVehicleType ].VehicleSeats[ bSeatIndex ].zSeatName );
wcscat( pStr, sTemp );
}
if (gGameOptions.fNewTraitSystem) // SANDRO - old/new traits check
{
UINT8 ubTempSkillArray[30];
@@ -5716,7 +5723,8 @@ void RenderTEAMPanel( BOOLEAN fDirty )
if ( bNumSkillTraits == 0 )
{
swprintf( pStr, L"%s", pPersonnelScreenStrings[ PRSNL_TXT_NOSKILLS ] );
swprintf( sTemp, L"%s", pPersonnelScreenStrings[ PRSNL_TXT_NOSKILLS ] );
wcscat( pStr, sTemp );
}
else
{
@@ -6974,8 +6982,8 @@ void AddPlayerToInterfaceTeamSlot( UINT8 ubID )
return;
}
//if ( !( MercPtrs[ ubID ]->flags.uiStatusFlags & ( SOLDIER_DRIVER | SOLDIER_PASSENGER ) ) )
//{
if ( !( MercPtrs[ ubID ]->flags.uiStatusFlags & ( SOLDIER_DRIVER | SOLDIER_PASSENGER ) ) )
{
if ( !PlayerExistsInSlot( ubID ) )
{
// Find a free slot
@@ -6999,38 +7007,38 @@ void AddPlayerToInterfaceTeamSlot( UINT8 ubID )
}
}
}
//}
//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;
}
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 );
MSYS_SetRegionUserData( &gTEAM_FirstHandInv[ iCounter ], 0, iCounter );
MSYS_SetRegionUserData( &gTEAM_FaceRegions[ iCounter ], 0, iCounter );
// // DIRTY INTERFACE
// fInterfacePanelDirty = DIRTYLEVEL2;
// DIRTY INTERFACE
fInterfacePanelDirty = DIRTYLEVEL2;
// // Set ID to do open anim
// MercPtrs[ ubID ]->flags.fUInewMerc = TRUE;
//
// return;
// }
// }
// }
// }
//}
// Set ID to do open anim
MercPtrs[ ubID ]->flags.fUInewMerc = TRUE;
return;
}
}
}
}
}
}
BOOLEAN InitTEAMSlots( )
+41 -3
View File
@@ -1083,6 +1083,17 @@ void PopupMovementMenu( UI_EVENT *pUIEvent )
fDisableAction = TRUE;
}
// anv: don't switch if passengers are blocked from attacking
if( pSoldier->flags.uiStatusFlags & ( SOLDIER_DRIVER | SOLDIER_PASSENGER ) )
{
SOLDIERTYPE *pVehicle = GetSoldierStructureForVehicle( pSoldier->iVehicleId );
INT8 bSeatIndex = GetSeatIndexFromSoldier( pSoldier );
if( gNewVehicle[ pVehicleList[ pSoldier->iVehicleId ].ubVehicleType ].VehicleSeats[bSeatIndex].fBlockedShots == TRUE )
{
fDisableAction = TRUE;
}
}
iActionIcons[ ACTIONC_ICON ] = QuickCreateButton( iIconImages[ uiActionImages ], (INT16)(iMenuAnchorX ), (INT16)(iMenuAnchorY + 20 ),
BUTTON_NO_TOGGLE, MSYS_PRIORITY_HIGHEST - 1,
DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)BtnMovementCallback );
@@ -1776,7 +1787,16 @@ void DrawSelectedUIAboveGuy( UINT16 usSoldierID )
//if ( pSoldier->flags.fShowLocator )
{
// Render the beastie
GetSoldierAboveGuyPositions( pSoldier, &sXPos, &sYPos, TRUE );
// anv: if soldier is in vehicle, draw above middle of the vehicle
if( !(pSoldier->flags.uiStatusFlags & ( SOLDIER_DRIVER | SOLDIER_PASSENGER ) ) )
{
GetSoldierAboveGuyPositions( pSoldier, &sXPos, &sYPos, TRUE );
}
else
{
SOLDIERTYPE *pVehicle = GetSoldierStructureForVehicle( pSoldier->iVehicleId );
GetSoldierAboveGuyPositions( pVehicle, &sXPos, &sYPos, TRUE );
}
// Adjust for bars!
sXPos += 25;
@@ -1833,7 +1853,16 @@ void DrawSelectedUIAboveGuy( UINT16 usSoldierID )
if ( gGameExternalOptions.ubShowHealthBarsOnHead )
{
// Render the beastie
GetSoldierAboveGuyPositions( pSoldier, &sXPos, &sYPos, TRUE );
// anv: if soldier is in vehicle, draw above middle of the vehicle
if( !(pSoldier->flags.uiStatusFlags & ( SOLDIER_DRIVER | SOLDIER_PASSENGER ) ) )
{
GetSoldierAboveGuyPositions( pSoldier, &sXPos, &sYPos, TRUE );
}
else
{
SOLDIERTYPE *pVehicle = GetSoldierStructureForVehicle( pSoldier->iVehicleId );
GetSoldierAboveGuyPositions( pVehicle, &sXPos, &sYPos, TRUE );
}
// Adjust for bars!
sXPos += 25;
@@ -1901,7 +1930,16 @@ void DrawSelectedUIAboveGuy( UINT16 usSoldierID )
return;
}
GetSoldierAboveGuyPositions( pSoldier, &sXPos, &sYPos, FALSE );
// anv: if soldier is in vehicle, draw above middle of the vehicle
if( !(pSoldier->flags.uiStatusFlags & ( SOLDIER_DRIVER | SOLDIER_PASSENGER ) ) )
{
GetSoldierAboveGuyPositions( pSoldier, &sXPos, &sYPos, FALSE );
}
else
{
SOLDIERTYPE *pVehicle = GetSoldierStructureForVehicle( pSoldier->iVehicleId );
GetSoldierAboveGuyPositions( pVehicle, &sXPos, &sYPos, FALSE );
}
// Display name
SetFont( TINYFONT1 );
+37
View File
@@ -43,6 +43,7 @@
#include "Quests.h"
#include "items.h"
#include "Item Types.h"
#include "Vehicles.h"
#endif
#include "fresh_header.h"
#include "WorldDat.h"
@@ -902,6 +903,16 @@ INT16 GetSightAdjustment( SOLDIERTYPE* pSoldier, INT32 sGridNo, INT16 bLevel, IN
iSightAdjustment += GetSightAdjustmentCamouflageOnTerrain( pSoldier, bStance, ubTerrainType );
}
// anv: some places in vehicle completely obscure passenger from outside
INT8 bSeatIndex = GetSeatIndexFromSoldier( pSoldier );
if( bSeatIndex != (-1) )
{
if( gNewVehicle[ pVehicleList[ pSoldier->iVehicleId ].ubVehicleType ].VehicleSeats[ bSeatIndex ].fHidden )
{
iSightAdjustment = (-100);
}
}
return MINMAX100N(iSightAdjustment);
}
@@ -2316,6 +2327,32 @@ INT32 SoldierToSoldierLineOfSightTest( SOLDIERTYPE * pStartSoldier, SOLDIERTYPE
iTileSightLimit += iTileSightLimit * GetSightAdjustment(pEndSoldier) / 100;
}
// anv: special check for vehicles - since they're no longer transparent, we need to check for visibility
// of all substructures, also vehicle will be noticed even if just part of it is sticking around the corner
if( pEndSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE && !TANK( pEndSoldier ) )
{
STRUCTURE *pBase = pEndSoldier->pLevelNode->pStructureData;
if( pBase == NULL )
{
return( FALSE );
}
DB_STRUCTURE_TILE ** ppTile = pBase->pDBStructureRef->ppTile;
UINT8 ubNumberOfTiles = pBase->pDBStructureRef->pDBStructure->ubNumberOfTiles;
INT32 sStructGridNo;
// loop through all tiles
for (UINT8 ubLoop = BASE_TILE; ubLoop < ubNumberOfTiles; ubLoop++)
{
sStructGridNo = AddPosRelToBase(pBase->sGridNo, ppTile[ubLoop]);
if( LineOfSightTest( (FLOAT) CenterX( pStartSoldier->sGridNo ), (FLOAT) CenterY( pStartSoldier->sGridNo ), dStartZPos, (FLOAT) CenterX( sStructGridNo ), (FLOAT) CenterY( sStructGridNo ), dEndZPos, iTileSightLimit, bAware, fSmell, NULL, adjustForSight, cthCalc ) )
{
return( TRUE );
}
}
return( FALSE );
}
return( LineOfSightTest( (FLOAT) CenterX( pStartSoldier->sGridNo ), (FLOAT) CenterY( pStartSoldier->sGridNo ), dStartZPos, (FLOAT) CenterX( pEndSoldier->sGridNo ), (FLOAT) CenterY( pEndSoldier->sGridNo ), dEndZPos, iTileSightLimit, bAware, fSmell, NULL, adjustForSight, cthCalc ) );
}
+10 -3
View File
@@ -1512,7 +1512,7 @@ BOOLEAN ExecuteOverhead( )
}
else if ( pSoldier->aiData.ubPendingAction == MERC_ENTER_VEHICLE )
{
pSoldier->EVENT_SoldierEnterVehicle( pSoldier->aiData.sPendingActionData2, pSoldier->aiData.bPendingActionData3 );
pSoldier->EVENT_SoldierEnterVehicle( pSoldier->aiData.sPendingActionData2, pSoldier->aiData.bPendingActionData3, pSoldier->aiData.uiPendingActionData4 );
pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION;
continue;
}
@@ -3104,8 +3104,15 @@ void InternalSelectSoldier( UINT16 usSoldierID, BOOLEAN fAcknowledge, BOOLEAN fF
if( ( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) )
{
pSoldier = GetDriver( pSoldier->iVehicleId );
usSoldierID = pSoldier->ubID;
pSoldier = GetDriver( pSoldier->bVehicleID );
if( pSoldier == NULL )
{
return;
}
else
{
usSoldierID = pSoldier->ubID;
}
}
// If we are dead, ignore
+23 -1
View File
@@ -62,6 +62,7 @@
#include "SkillMenu.h" // sevenfm: need this for TraitsMenu
#include "Vehicles.h" // anv: for switching from soldier to vehicle
#include "VehicleMenu.h"
#endif
@@ -1249,6 +1250,16 @@ void QueryRTRightButton( UINT32 *puiNewEvent )
break;
}
}
// anv: CTRL+RMB - VehicleMenu
else if(_KeyDown(CTRL))
{
switch( gCurrentUIMode )
{
case HANDCURSOR_MODE:
HandleHandCursorRightClick( usMapPos, puiNewEvent );
break;
}
}
else
{
// Switch on UI mode
@@ -1261,7 +1272,18 @@ void QueryRTRightButton( UINT32 *puiNewEvent )
case CONFIRM_MOVE_MODE:
case MOVE_MODE:
case TALKCURSOR_MODE:
// anv: don't switch if passengers are blocked from attacking
pSoldier = MercPtrs[ gusSelectedSoldier ];
if( pSoldier->flags.uiStatusFlags & ( SOLDIER_DRIVER | SOLDIER_PASSENGER ) )
{
SOLDIERTYPE *pVehicle = GetSoldierStructureForVehicle( pSoldier->iVehicleId );
INT8 bSeatIndex = GetSeatIndexFromSoldier( pSoldier );
if( gNewVehicle[ pVehicleList[ pSoldier->iVehicleId ].ubVehicleType ].VehicleSeats[bSeatIndex].fBlockedShots == TRUE )
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, pVehicleSeatsStrings[0] );
break;
}
}
// We have here a change to action mode
*puiNewEvent = M_CHANGE_TO_ACTION;
fClickIntercepted = TRUE;
+8 -2
View File
@@ -1097,6 +1097,7 @@ void SOLDIERTYPE::initialize()
memset( this, 0, SIZEOF_SOLDIERTYPE_POD);
inv.clear();
ai_masterplan_ = 0;
this->iVehicleId = (-1);
memset( &aiData, 0, sizeof(STRUCT_AIData) );
memset( &flags, 0, sizeof(STRUCT_Flags) );
@@ -8210,6 +8211,7 @@ void SOLDIERTYPE::TurnSoldier( void )
pVehicleList[ iId ].pPassengers[ iCounter ]->EVENT_SetSoldierDesiredDirection( ( pVehicleList[ iId ].pPassengers[ iCounter ]->pathing.bDesiredDirection + bDirectionChange + NUM_WORLD_DIRECTIONS ) % NUM_WORLD_DIRECTIONS );
}
}
UpdateAllVehiclePassengersGridNo( this );
}
// If the soldier is not crawling or multi-tiled, he should be allowed to turn in place. Even if there is some
@@ -12643,7 +12645,7 @@ void SOLDIERTYPE::EVENT_SoldierBeginFirstAid( INT32 sGridNo, UINT8 ubDirection )
}
void SOLDIERTYPE::EVENT_SoldierEnterVehicle( INT32 sGridNo, UINT8 ubDirection )
void SOLDIERTYPE::EVENT_SoldierEnterVehicle( INT32 sGridNo, UINT8 ubDirection, UINT8 ubSeatIndex )
{
SOLDIERTYPE *pTSoldier;
UINT32 uiMercFlags;
@@ -12654,7 +12656,7 @@ void SOLDIERTYPE::EVENT_SoldierEnterVehicle( INT32 sGridNo, UINT8 ubDirection )
pTSoldier = MercPtrs[ usSoldierIndex ];
// Enter vehicle...
EnterVehicle( pTSoldier, this );
EnterVehicle( pTSoldier, this, ubSeatIndex );
}
UnSetUIBusy( this->ubID );
@@ -20497,6 +20499,10 @@ void InternalPlaySoldierFootstepSound( SOLDIERTYPE * pSoldier )
{
// anv: vehicle sounds
//PlaySoldierJA2Sample( pSoldier->ubID, S_VECH1_MOVE, RATE_11025, SoundVolume( bVolume, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ), TRUE );
if ( pSoldier->usAnimState == RUNNING )
{
bVolume = HIGHVOLUME;
}
PlaySoldierJA2Sample( pSoldier->ubID, pVehicleList[ pSoldier->bVehicleID ].iMoveSound, RATE_11025, SoundVolume( bVolume, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ), TRUE );
}
}
+1 -1
View File
@@ -1546,7 +1546,7 @@ public:
void EVENT_SoldierBeginUseDetonator( void );
void EVENT_SoldierBeginDropBomb( );
void EVENT_SoldierDefuseTripwire( INT32 sGridNo, INT32 sItem );
void EVENT_SoldierEnterVehicle( INT32 sGridNo, UINT8 ubDirection );
void EVENT_SoldierEnterVehicle( INT32 sGridNo, UINT8 ubDirection, UINT8 ubSeatIndex = 0 );
void EVENT_SoldierBeginGiveItem( void );
void EVENT_SetSoldierPositionAndMaybeFinalDest( FLOAT dNewXPos, FLOAT dNewYPos, BOOLEAN fUpdateFinalDest );
void EVENT_SetSoldierPositionForceDelete( FLOAT dNewXPos, FLOAT dNewYPos );
+8
View File
@@ -666,6 +666,10 @@
RelativePath=".\Vehicles.h"
>
</File>
<File
RelativePath=".\VehicleMenu.h"
>
</File>
<File
RelativePath=".\Weapons.h"
>
@@ -992,6 +996,10 @@
RelativePath=".\Vehicles.cpp"
>
</File>
<File
RelativePath=".\VehicleMenu.cpp"
>
</File>
<File
RelativePath=".\Weapons.cpp"
>
+8
View File
@@ -670,6 +670,10 @@
RelativePath="Vehicles.h"
>
</File>
<File
RelativePath="VehicleMenu.h"
>
</File>
<File
RelativePath="Weapons.h"
>
@@ -994,6 +998,10 @@
RelativePath="Vehicles.cpp"
>
</File>
<File
RelativePath="VehicleMenu.cpp"
>
</File>
<File
RelativePath="Weapons.cpp"
>
+1
View File
@@ -186,6 +186,7 @@
<ClCompile Include="TeamTurns.cpp" />
<ClCompile Include="Turn Based Input.cpp" />
<ClCompile Include="UI Cursors.cpp" />
<ClCompile Include="VehicleMenu.cpp" />
<ClCompile Include="Vehicles.cpp" />
<ClCompile Include="Weapons.cpp" />
<ClCompile Include="World Items.cpp" />
+3
View File
@@ -668,5 +668,8 @@
<ClCompile Include="XML_Keys.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="VehicleMenu.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>
+2
View File
@@ -105,6 +105,7 @@
<ClInclude Include="TeamTurns.h" />
<ClInclude Include="UI Cursors.h" />
<ClInclude Include="Vehicles.h" />
<ClInclude Include="VehicleMenu.h" />
<ClInclude Include="Weapons.h" />
<ClInclude Include="World Items.h" />
<ClInclude Include="XML.h" />
@@ -187,6 +188,7 @@
<ClCompile Include="Turn Based Input.cpp" />
<ClCompile Include="UI Cursors.cpp" />
<ClCompile Include="Vehicles.cpp" />
<ClCompile Include="VehicleMenu.cpp" />
<ClCompile Include="Weapons.cpp" />
<ClCompile Include="World Items.cpp" />
<ClCompile Include="XML_AmmoStrings.cpp" />
+6
View File
@@ -245,6 +245,9 @@
</ClInclude>
<ClInclude Include="Vehicles.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="VehicleMenu.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Weapons.h">
<Filter>Header Files</Filter>
@@ -484,6 +487,9 @@
</ClCompile>
<ClCompile Include="Vehicles.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="VehicleMenu.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Weapons.cpp">
<Filter>Source Files</Filter>
+84 -13
View File
@@ -107,6 +107,7 @@
#include "Militia Control.h"
#include "Ambient Control.h"
#include "Strategic AI.h"
#include "VehicleMenu.h"
#endif
#include "Quest Debug System.h"
@@ -1012,6 +1013,16 @@ void QueryTBRightButton( UINT32 *puiNewEvent )
break;
}
}
// anv: CTRL+RMB - VehicleMenu
else if(_KeyDown(CTRL))
{
switch( gCurrentUIMode )
{
case HANDCURSOR_MODE:
HandleHandCursorRightClick( usMapPos, puiNewEvent );
break;
}
}
else
{
// Switch on UI mode
@@ -1022,7 +1033,18 @@ void QueryTBRightButton( UINT32 *puiNewEvent )
break;
case MOVE_MODE:
// anv: don't switch if passengers are blocked from attacking
pSoldier = MercPtrs[ gusSelectedSoldier ];
if( pSoldier->flags.uiStatusFlags & ( SOLDIER_DRIVER | SOLDIER_PASSENGER ) )
{
SOLDIERTYPE *pVehicle = GetSoldierStructureForVehicle( pSoldier->iVehicleId );
INT8 bSeatIndex = GetSeatIndexFromSoldier( pSoldier );
if( gNewVehicle[ pVehicleList[ pSoldier->iVehicleId ].ubVehicleType ].VehicleSeats[bSeatIndex].fBlockedShots == TRUE )
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, pVehicleSeatsStrings[0] );
break;
}
}
// We have here a change to action mode
*puiNewEvent = M_CHANGE_TO_ACTION;
fClickIntercepted = TRUE;
@@ -5308,7 +5330,7 @@ void CreatePlayerControlledMonster()
}
INT8 CheckForAndHandleHandleVehicleInteractiveClick( SOLDIERTYPE *pSoldier, UINT16 usMapPos, BOOLEAN fMovementMode )
INT8 CheckForAndHandleHandleVehicleInteractiveClick( SOLDIERTYPE *pSoldier, UINT16 usMapPos, BOOLEAN fMovementMode, UINT8 ubSeatIndex )
{
// Look for an item pool
INT32 sActionGridNo;
@@ -5320,7 +5342,9 @@ INT8 CheckForAndHandleHandleVehicleInteractiveClick( SOLDIERTYPE *pSoldier, UINT
{
pTSoldier = MercPtrs[ gusUIFullTargetID ];
if ( OK_ENTERABLE_VEHICLE( pTSoldier ) && pTSoldier->bVisible != -1 && OKUseVehicle( pTSoldier->ubProfile ) )
// anv: added condition - make sure we won't put vehicle in another vehicle
if ( OK_ENTERABLE_VEHICLE( pTSoldier ) && pTSoldier->bVisible != -1 && OKUseVehicle( pTSoldier->ubProfile ) && !( pSoldier->flags.uiStatusFlags & ( SOLDIER_DRIVER | SOLDIER_PASSENGER | SOLDIER_VEHICLE ) ) )
//if ( OK_ENTERABLE_VEHICLE( pTSoldier ) && pTSoldier->bVisible != -1 && OKUseVehicle( pTSoldier->ubProfile ) )
{
if ( ( GetNumberInVehicle( pTSoldier->bVehicleID ) == 0 ) || !fMovementMode )
{
@@ -5344,6 +5368,7 @@ INT8 CheckForAndHandleHandleVehicleInteractiveClick( SOLDIERTYPE *pSoldier, UINT
pSoldier->aiData.ubPendingAction = MERC_ENTER_VEHICLE;
pSoldier->aiData.sPendingActionData2 = pTSoldier->sGridNo;
pSoldier->aiData.bPendingActionData3 = ubDirection;
pSoldier->aiData.uiPendingActionData4 = ubSeatIndex;
pSoldier->aiData.ubPendingActionAnimCount = 0;
// WALK UP TO DEST FIRST
@@ -5351,7 +5376,7 @@ INT8 CheckForAndHandleHandleVehicleInteractiveClick( SOLDIERTYPE *pSoldier, UINT
}
else
{
pSoldier->EVENT_SoldierEnterVehicle( pTSoldier->sGridNo, ubDirection );
pSoldier->EVENT_SoldierEnterVehicle( pTSoldier->sGridNo, ubDirection, ubSeatIndex );
}
// OK, set UI
@@ -5390,7 +5415,7 @@ void HandleHandCursorClick( INT32 usMapPos, UINT32 *puiNewEvent )
return;
}
if ( CheckForAndHandleHandleVehicleInteractiveClick( pSoldier, usMapPos, FALSE ) == -1 )
if ( CheckForAndHandleHandleVehicleInteractiveClick( pSoldier, usMapPos, FALSE, 0 ) == -1 )
{
return;
}
@@ -5531,6 +5556,41 @@ void HandleHandCursorClick( INT32 usMapPos, UINT32 *puiNewEvent )
}
}
void HandleHandCursorRightClick( INT32 usMapPos, UINT32 *puiNewEvent )
{
SOLDIERTYPE *pSoldier;
SOLDIERTYPE *pTSoldier;
if( GetSoldier( &pSoldier, gusSelectedSoldier ) )
{
// If we are out of breath, no cursor...
if( pSoldier->bBreath < OKBREATH && pSoldier->bCollapsed )
{
return;
}
if( gfUIFullTargetFound )
{
pTSoldier = MercPtrs[ gusUIFullTargetID ];
if( OK_ENTERABLE_VEHICLE( pTSoldier ) && pTSoldier->bVisible != -1 && OKUseVehicle( pTSoldier->ubProfile ) )
{
// anv: if we are passengers, only show menu when clicking on vehicle we're in
if( pSoldier->flags.uiStatusFlags & ( SOLDIER_DRIVER | SOLDIER_PASSENGER ) )
{
if( pSoldier->iVehicleId == pTSoldier->bVehicleID )
{
VehicleMenu(usMapPos, pSoldier, pTSoldier);
}
}
else
{
VehicleMenu(usMapPos, pSoldier, pTSoldier);
}
return;
}
}
}
}
extern BOOLEAN AnyItemsVisibleOnLevel( ITEM_POOL *pItemPool, INT8 bZLevel );
@@ -5596,7 +5656,7 @@ INT8 HandleMoveModeInteractiveClick( INT32 usMapPos, UINT32 *puiNewEvent )
}
// See if we are over a vehicle, and walk up to it and enter....
if ( CheckForAndHandleHandleVehicleInteractiveClick( pSoldier, usMapPos, TRUE ) == -1 )
if ( CheckForAndHandleHandleVehicleInteractiveClick( pSoldier, usMapPos, TRUE, 0 ) == -1 )
{
return( -1 );
}
@@ -6744,6 +6804,24 @@ void SwapMercPortraits ( SOLDIERTYPE *pSoldier, INT8 bDirection )
INT8 bNewPosition = bOldPosition + bDirection;
SOLDIERTYPE TempMercPtr = *MercPtrs[ ubSourceMerc ];
// anv: vehicle passengers are swapped differently
if( pSoldier->flags.uiStatusFlags & ( SOLDIER_DRIVER | SOLDIER_PASSENGER ) )
{
SOLDIERTYPE *pVehicle = GetSoldierStructureForVehicle( pSoldier->iVehicleId );
if( pVehicle != NULL && bNewPosition < gNewVehicle[pVehicle->bVehicleID].iNewSeatingCapacities )
{
if( SwapVehicleSeat( pVehicle, pSoldier, bNewPosition ) )
{
RebuildCurrentSquad( );
// refresh interface
fCharacterInfoPanelDirty = TRUE;
fTeamPanelDirty = TRUE;
fInterfacePanelDirty = DIRTYLEVEL2;
}
}
return;
}
// check if new position is occupied by another merc? we won't replace an empty slot
if ( gTeamPanel[ bNewPosition ].fOccupied && gTeamPanel[ bNewPosition ].ubID != NOBODY )
{
@@ -6786,13 +6864,6 @@ 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;
+222
View File
@@ -0,0 +1,222 @@
// anv: totally not a copy of SkillMenu.cpp
#include "VehicleMenu.h"
#include "Soldier Profile Type.h"
#include "Overhead.h"
#include "Text.h"
#include "Isometric Utils.h"
#include "DisplayCover.h"
#include "worldman.h"
#include "Vehicles.h"
#include "soldier macros.h"
#include "Soldier Add.h"
#include "PATHAI.h"
#include "Points.h"
#include "Handle UI.h"
#include "Squads.h"
#include "Font Control.h"
// sevenfm: need this for correct calculation of vehicle menu position
extern INT16 gsInterfaceLevel;
UINT16 usVehicleMenuPosX = 0;
UINT16 usVehicleMenuPosY = 0;
INT32 sVehicleMenuTargetGridNo = NOWHERE;
SOLDIERTYPE *pCurrentSoldier = NULL;
SOLDIERTYPE *pCurrentVehicle = NULL;
void HideVehicleMenu( void )
{
// Dirty!
fMapPanelDirty = TRUE;
}
// Turns an option off by always returning FALSE
BOOLEAN Popup_VehicleMenuOptionOff( void ) { return FALSE; }
void
VehicleMenuItem::SetupPopup(CHAR* name)
{
// create a popup
gPopup = new POPUP(name);
// add a callback that lets the keyboard handler know we're done (and ready to pop up again)
gPopup->setCallback(POPUP_CALLBACK_HIDE, new popupCallbackFunction<void, void>( &HideVehicleMenu ) );
}
// Different VehicleItem classes. We need wrappers for each one, as we cannot pass a pointer to a member function (we need a concrete object)
/////////////////////////////// Vehicle Selection ////////////////////////////////////////////
VehicleSelection gVehicleSelection;
void Wrapper_Function_VehicleSelection( UINT32 aVal ) { gVehicleSelection.Functions(aVal); }
void Wrapper_Setup_VehicleSelection( UINT32 aVal ) { gVehicleSelection.Setup(aVal); }
void Wrapper_Cancel_VehicleSelection( UINT32 aVal ) { gVehicleSelection.Cancel(); }
/////////////////////////////// Vehicle Selection ////////////////////////////////////////////
/////////////////////////////// Vehicle Selection ////////////////////////////////////////////
void
VehicleSelection::Setup( UINT32 aVal )
{
Destroy();
if ( pCurrentSoldier == NULL )
return;
if ( pCurrentVehicle == NULL )
return;
SetupPopup("VehicleSelection");
POPUP_OPTION *pOption;
CHAR16 pStr[300];
// create entries for each vehicle seat
INT8 bVehicleID = pCurrentVehicle->bVehicleID;
INT8 bSeatIndex = GetSeatIndexFromSoldier( pCurrentSoldier );
INT32 iSeatingCapacity = gNewVehicle[ pVehicleList[ bVehicleID ].ubVehicleType ].iNewSeatingCapacities;
for ( int i = 0; i < iSeatingCapacity; ++i)
{
swprintf( pStr, gNewVehicle[ pVehicleList[ bVehicleID ].ubVehicleType ].VehicleSeats[i].zSeatName );
pOption = new POPUP_OPTION(&std::wstring( pStr ), new popupCallbackFunction<void,UINT32>( &Wrapper_Function_VehicleSelection, i ));
// if seat is already taken, grey it out
if ( pVehicleList[ bVehicleID ].pPassengers[ i ] != NULL )
{
if( pCurrentSoldier->flags.uiStatusFlags & ( SOLDIER_DRIVER | SOLDIER_PASSENGER ) )
{
if( pVehicleList[ bVehicleID ].pPassengers[ i ] == pCurrentSoldier )
{
// Set this option off.
pOption->setAvail(new popupCallbackFunction<bool,void*>( &Popup_VehicleMenuOptionOff, NULL ));
}
else
{
// keep, but colour in yellow
pOption->color_foreground = FONT_YELLOW;
}
}
else
{
// Set this option off.
pOption->setAvail(new popupCallbackFunction<bool,void*>( &Popup_VehicleMenuOptionOff, NULL ));
}
}
// block swapping between different compartments
if( gTacticalStatus.uiFlags & INCOMBAT )
{
if( bSeatIndex != (-1) )
{
if( gNewVehicle[pVehicleList[ pCurrentVehicle->bVehicleID ].ubVehicleType].VehicleSeats[bSeatIndex].ubCompartment !=
gNewVehicle[pVehicleList[ pCurrentVehicle->bVehicleID ].ubVehicleType].VehicleSeats[i].ubCompartment )
{
// Set this option off.
pOption->setAvail(new popupCallbackFunction<bool,void*>( &Popup_VehicleMenuOptionOff, NULL ));
}
}
}
GetPopup()->addOption( *pOption );
}
// cancel option
swprintf( pStr, pSkillMenuStrings[SKILLMENU_CANCEL] );
pOption = new POPUP_OPTION(&std::wstring( pStr ), new popupCallbackFunction<void,UINT32>( &Wrapper_Cancel_VehicleSelection, 0 ) );
GetPopup()->addOption( *pOption );
// grab soldier's x,y screen position
INT16 sX, sY;
GetGridNoScreenPos( sVehicleMenuTargetGridNo, gsInterfaceLevel, &sX, &sY );
if( sX < 0 ) sX = 0;
if( sY < 0 ) sY = 0;
usVehicleMenuPosX = sX + 30;
usVehicleMenuPosY = sY;
if ( ( usVehicleMenuPosX + 200 ) > SCREEN_WIDTH )
usVehicleMenuPosX = SCREEN_WIDTH - 200;
if ( ( usVehicleMenuPosY + 130 ) > SCREEN_HEIGHT )
usVehicleMenuPosY = SCREEN_HEIGHT - 190;
SetPos(usVehicleMenuPosX, usVehicleMenuPosY);
}
void
VehicleSelection::Functions( UINT32 aVal )
{
INT32 sActionGridNo;
UINT8 ubDirection;
INT16 sAPCost = 0;
INT32 sTempSelectedSoldier;
Cancel();
if( pCurrentSoldier->flags.uiStatusFlags & ( SOLDIER_DRIVER | SOLDIER_PASSENGER ) && pCurrentSoldier->iVehicleId == pCurrentVehicle->bVehicleID )
{
if( SwapVehicleSeat( pCurrentVehicle, pCurrentSoldier, aVal ) )
{
sTempSelectedSoldier = gusSelectedSoldier;
SetCurrentSquad( CurrentSquad(), TRUE );
gusSelectedSoldier = sTempSelectedSoldier;
}
}
else if ( OK_ENTERABLE_VEHICLE( pCurrentVehicle ) && pCurrentVehicle->bVisible != -1 && OKUseVehicle( pCurrentVehicle->ubProfile ) )
{
// Find a gridno closest to sweetspot...
sActionGridNo = FindGridNoFromSweetSpotWithStructDataFromSoldier( pCurrentSoldier, pCurrentSoldier->usUIMovementMode, 5, &ubDirection, 0, pCurrentVehicle, TRUE );
if (!TileIsOutOfBounds(sActionGridNo))
{
// Calculate AP costs...
//sAPCost = GetAPsToBeginFirstAid( pSoldier );
sAPCost += PlotPath( pCurrentSoldier, sActionGridNo, NO_COPYROUTE, FALSE, TEMPORARY, (UINT16)pCurrentSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pCurrentSoldier->bActionPoints);
if ( EnoughPoints( pCurrentSoldier, sAPCost, 0, TRUE ) )
{
pCurrentSoldier->DoMercBattleSound( BATTLE_SOUND_OK1 );
// CHECK IF WE ARE AT THIS GRIDNO NOW
if ( pCurrentSoldier->sGridNo != sActionGridNo )
{
// SEND PENDING ACTION
pCurrentSoldier->aiData.ubPendingAction = MERC_ENTER_VEHICLE;
pCurrentSoldier->aiData.sPendingActionData2 = pCurrentVehicle->sGridNo;
pCurrentSoldier->aiData.bPendingActionData3 = ubDirection;
pCurrentSoldier->aiData.uiPendingActionData4 = aVal;
pCurrentSoldier->aiData.ubPendingActionAnimCount = 0;
// WALK UP TO DEST FIRST
pCurrentSoldier->EVENT_InternalGetNewSoldierPath( sActionGridNo, pCurrentSoldier->usUIMovementMode, 3 , pCurrentSoldier->flags.fNoAPToFinishMove );
}
else
{
pCurrentSoldier->EVENT_SoldierEnterVehicle( pCurrentVehicle->sGridNo, ubDirection, aVal );
}
// OK, set UI
SetUIBusy( pCurrentSoldier->ubID );
//guiPendingOverrideEvent = A_CHANGE_TO_MOVE;
}
}
}
Cancel();
gVehicleSelection.Cancel();
}
/////////////////////////////// Vehicle Selection ////////////////////////////////////////////
void VehicleMenu( INT32 usMapPos, SOLDIERTYPE *pSoldier, SOLDIERTYPE *pVehicle )
{
sVehicleMenuTargetGridNo = usMapPos;
pCurrentSoldier = pSoldier;
pCurrentVehicle = pVehicle;
gVehicleSelection.Setup(0);
}
+85
View File
@@ -0,0 +1,85 @@
#ifndef _VEHICLE_MENU_
#define _VEHICLE_MENU_
#include "popup_class.h"
#include "Soldier Profile.h"
class VehicleMenuItem
{
public:
VehicleMenuItem() :
fInitialized(FALSE), usPosX(0), gPopup(NULL)
{
}
virtual void Cancel()
{
// Hide the Filter Menu pop-up.
if (gPopup != NULL && fInitialized )
{
gPopup->hide();
}
}
virtual void Destroy()
{
// If we already have a popup, destroy it first. This ensures we get a fresh menu each time.
if ( fInitialized )
{
delete(gPopup);
gPopup = NULL;
fInitialized = FALSE;
}
}
UINT16 GetMaxPosX()
{
if ( gPopup )
return (usPosX + gPopup->getBoxDimensions().iRight);
return usPosX;
}
virtual void SetPos(UINT16 usX, UINT16 usY)
{
// same y, different x
usPosX = usX;
gPopup->setPosition( usPosX, usY );
fInitialized = TRUE;
gPopup->show();
}
void SetupPopup(CHAR* name);
POPUP* GetPopup()
{
return gPopup;
}
virtual void Setup( UINT32 aVal ) {}
virtual void Functions( UINT32 aVal ) {}
private:
BOOLEAN fInitialized;
UINT16 usPosX;
POPUP* gPopup;
};
// select a vehicle seat (and possibly other options)
class VehicleSelection : public VehicleMenuItem
{
public:
VehicleSelection() : usSector(0) {}
void Setup( UINT32 aVal );
void Functions( UINT32 aVal );
private:
UINT32 usSector;
};
void VehicleMenu( INT32 usMapPos, SOLDIERTYPE *pSoldier, SOLDIERTYPE *pVehicle );
#endif
+358 -37
View File
@@ -475,10 +475,12 @@ BOOLEAN IsThisVehicleAccessibleToSoldier( SOLDIERTYPE *pSoldier, INT32 iId )
}
BOOLEAN AddSoldierToVehicle( SOLDIERTYPE *pSoldier, INT32 iId, BOOLEAN fSpecificSeat, UINT8 ubSeatIndex )
BOOLEAN AddSoldierToVehicle( SOLDIERTYPE *pSoldier, INT32 iId, UINT8 ubSeatIndex )
{
INT32 iCounter = 0;
UINT32 vCount = 0;
UINT8 ubFinalSeatIndex = 0;
BOOLEAN fFoundPlace = FALSE;
SOLDIERTYPE *pVehicleSoldier = NULL;
@@ -571,13 +573,35 @@ BOOLEAN AddSoldierToVehicle( SOLDIERTYPE *pSoldier, INT32 iId, BOOLEAN fSpecific
PlayJA2Sample( pVehicleList[ pVehicleSoldier->bVehicleID ].iOutOfSound, RATE_11025, SoundVolume( HIGHVOLUME, pVehicleSoldier->sGridNo ), 1, SoundDir( pVehicleSoldier->sGridNo ) );
}
for( iCounter = 0; iCounter < gNewVehicle[ pVehicleList[ iId ].ubVehicleType ].iNewSeatingCapacities; iCounter++ )
if( pVehicleList[ iId ].pPassengers[ ubSeatIndex ] == NULL )
{
ubFinalSeatIndex = ubSeatIndex;
fFoundPlace = TRUE;
}
else
{
for( iCounter = 0; !fFoundPlace && iCounter < gNewVehicle[ pVehicleList[ iId ].ubVehicleType ].iNewSeatingCapacities; iCounter++ )
{
if( pVehicleList[ iId ].pPassengers[ iCounter ] == NULL )
{
ubFinalSeatIndex = iCounter;
fFoundPlace = TRUE;
}
}
}
if( fFoundPlace )
{
// check if slot free
if( pVehicleList[ iId ].pPassengers[ iCounter ] == NULL )
if( pVehicleList[ iId ].pPassengers[ ubFinalSeatIndex ] == NULL )
{
// anv: since now they can shoot it's important to set passenger to proper stance
SendChangeSoldierStanceEvent( pSoldier, ANIM_CROUCH );
// add person in
pVehicleList[ iId ].pPassengers[ iCounter ] = pSoldier;
pVehicleList[ iId ].pPassengers[ ubFinalSeatIndex ] = pSoldier;
if( pSoldier->bAssignment == VEHICLE )
{
@@ -624,17 +648,27 @@ BOOLEAN AddSoldierToVehicle( SOLDIERTYPE *pSoldier, INT32 iId, BOOLEAN fSpecific
}
// Are we the first?
if ( GetNumberInVehicle( iId ) == 1 )
//if ( GetNumberInVehicle( iId ) == 1 )
//{
// // Set as driver...
// pSoldier->flags.uiStatusFlags |= SOLDIER_DRIVER;
// SetDriver( iId , pSoldier->ubID );
//}
//else
//{
// // Set as driver...
// pSoldier->flags.uiStatusFlags |= SOLDIER_PASSENGER;
//}
// anv: are we taking driver's seat
if( gNewVehicle[ pVehicleList[ iId ].ubVehicleType ].VehicleSeats[ubFinalSeatIndex].fDriver )
{
// Set as driver...
pSoldier->flags.uiStatusFlags |= SOLDIER_DRIVER;
SetDriver( iId , pSoldier->ubID );
}
else
{
// Set as driver...
pSoldier->flags.uiStatusFlags |= SOLDIER_PASSENGER;
}
@@ -643,8 +677,16 @@ BOOLEAN AddSoldierToVehicle( SOLDIERTYPE *pSoldier, INT32 iId, BOOLEAN fSpecific
if ( pVehicleSoldier )
{
// bInitialActionPoints - point in time where soldier and vehicle start sharing timeline
pSoldier->bInitialActionPoints = pSoldier->bActionPoints;
// set proper initial rotation
UINT8 ubRotation = gNewVehicle[ pVehicleList[ pVehicleSoldier->bVehicleID ].ubVehicleType ].VehicleSeats[ ubSeatIndex ].ubRotation;
pSoldier->flags.fDontChargeTurningAPs = TRUE;
pSoldier->EVENT_SetSoldierDesiredDirection( ( pVehicleSoldier->pathing.bDesiredDirection + ubRotation ) % NUM_WORLD_DIRECTIONS );
// Set gridno for vehicle.....
pSoldier->EVENT_SetSoldierPosition( pVehicleSoldier->dXPos, pVehicleSoldier->dYPos );
//pSoldier->EVENT_SetSoldierPosition( pVehicleSoldier->dXPos, pVehicleSoldier->dYPos );
UpdateAllVehiclePassengersGridNo( pVehicleSoldier );
// Stop from any movement.....
pSoldier->EVENT_StopMerc( pSoldier->sGridNo, pSoldier->ubDirection );
@@ -754,6 +796,7 @@ BOOLEAN RemoveSoldierFromVehicle( SOLDIERTYPE *pSoldier, INT32 iId )
if( pSoldier->flags.uiStatusFlags & SOLDIER_DRIVER )
{
fNewDriverNeeded = TRUE;
pVehicleList[ iId ].ubDriver = NOBODY;
}
pSoldier->flags.uiStatusFlags &= ( ~( SOLDIER_DRIVER | SOLDIER_PASSENGER ) );
@@ -765,14 +808,14 @@ BOOLEAN RemoveSoldierFromVehicle( SOLDIERTYPE *pSoldier, INT32 iId )
if( pVehicleList[ iId ].pPassengers[ iCounter ] != NULL )
{
fSoldierLeft = TRUE;
if( fNewDriverNeeded )
{
SOLDIERTYPE* pNewDriver = pVehicleList[ iId ].pPassengers[ iCounter ];
pNewDriver->flags.uiStatusFlags |= SOLDIER_DRIVER;
pNewDriver->flags.uiStatusFlags &= ~(SOLDIER_PASSENGER);
SetDriver( iId, pNewDriver->ubID );
fNewDriverNeeded = FALSE;
}
//if( fNewDriverNeeded )
//{
// SOLDIERTYPE* pNewDriver = pVehicleList[ iId ].pPassengers[ iCounter ];
// pNewDriver->flags.uiStatusFlags |= SOLDIER_DRIVER;
// pNewDriver->flags.uiStatusFlags &= ~(SOLDIER_PASSENGER);
// SetDriver( iId, pNewDriver->ubID );
// fNewDriverNeeded = FALSE;
//}
}
}
@@ -1526,12 +1569,46 @@ BOOLEAN AnyAccessibleVehiclesInSoldiersSector( SOLDIERTYPE *pSoldier )
SOLDIERTYPE *GetDriver( INT32 iID )
{
return( MercPtrs[ pVehicleList[ iID ].ubDriver ] );
INT32 iCounter;
if( pVehicleList[ iID ].ubDriver != NOBODY )
{
return( MercPtrs[ pVehicleList[ iID ].ubDriver ] );
}
else
{
// anv: if vehicle has no driver, return any passenger
for( iCounter = 0; iCounter < gNewVehicle[ pVehicleList[ iID ].ubVehicleType ].iNewSeatingCapacities; iCounter++ )
{
if( pVehicleList[ iID ].pPassengers[ iCounter ] != NULL )
{
return( pVehicleList[ iID ].pPassengers[ iCounter ] );
}
}
}
return( NULL );
}
void SetDriver( INT32 iID, UINT8 ubID )
{
// anv: first make sure previous driver won't be driver anymore
if( pVehicleList[ iID ].ubDriver != NOBODY )
{
if( MercPtrs[ pVehicleList[ iID ].ubDriver ] )
{
MercPtrs[ pVehicleList[ iID ].ubDriver ]->flags.uiStatusFlags &= ~(SOLDIER_DRIVER);
if( GetSeatIndexFromSoldier( MercPtrs[ pVehicleList[ iID ].ubDriver ] ) != (-1) )
{
MercPtrs[ pVehicleList[ iID ].ubDriver ]->flags.uiStatusFlags |= SOLDIER_PASSENGER;
}
}
}
// set proper flags
if( ubID != NOBODY )
{
MercPtrs[ ubID ]->flags.uiStatusFlags |= SOLDIER_DRIVER;
MercPtrs[ ubID ]->flags.uiStatusFlags &= ~(SOLDIER_PASSENGER);
}
pVehicleList[ iID ].ubDriver = ubID;
}
@@ -1611,7 +1688,7 @@ BOOLEAN TakeSoldierOutOfVehicle( SOLDIERTYPE *pSoldier )
BOOLEAN EnterVehicle( SOLDIERTYPE *pVehicle, SOLDIERTYPE *pSoldier, BOOLEAN fSpecificSeat, UINT8 ubSeatIndex )
BOOLEAN EnterVehicle( SOLDIERTYPE *pVehicle, SOLDIERTYPE *pSoldier, UINT8 ubSeatIndex )
{
// TEST IF IT'S VALID...
@@ -1621,13 +1698,9 @@ BOOLEAN EnterVehicle( SOLDIERTYPE *pVehicle, SOLDIERTYPE *pSoldier, BOOLEAN fSpe
if ( IsEnoughSpaceInVehicle( pVehicle->bVehicleID ) )
{
// anv: check if preferred seat is already taken, if so automatically choose another
if( fSpecificSeat )
if ( pVehicleList[ pVehicle->bVehicleID ].pPassengers[ubSeatIndex] != NULL )
{
if ( pVehicleList[ pVehicle->bVehicleID ].pPassengers[ubSeatIndex] != NULL )
{
fSpecificSeat = FALSE;
ubSeatIndex = 0;
}
ubSeatIndex = 0;
}
INT16 sAPCost = APBPConstants[AP_ENTER_VEHICLE];
@@ -1640,16 +1713,8 @@ BOOLEAN EnterVehicle( SOLDIERTYPE *pVehicle, SOLDIERTYPE *pSoldier, BOOLEAN fSpe
return( FALSE );
}
// anv: since now they can shoot it's important to set passenger to proper stance
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 );
AddSoldierToVehicle( pSoldier, pVehicle->bVehicleID, ubSeatIndex );
if ( !(guiTacticalInterfaceFlags & INTERFACE_MAPSCREEN ) )
{
@@ -1742,6 +1807,7 @@ BOOLEAN ExitVehicle( SOLDIERTYPE *pSoldier )
// anv: since now they can shoot it's important to set passenger to proper stance
// namely, back to standing, because we set them to crouching when entering
SendChangeSoldierStanceEvent( pSoldier, ANIM_STAND );
pSoldier->EVENT_SetSoldierDesiredDirection( pSoldier->ubDirection );
// Update visiblity.....
HandleSight(pSoldier,SIGHT_LOOK | SIGHT_RADIO );
@@ -1783,6 +1849,138 @@ BOOLEAN ExitVehicle( SOLDIERTYPE *pSoldier )
return( FALSE );
}
BOOLEAN ChangeVehicleSeat( SOLDIERTYPE *pVehicle, SOLDIERTYPE *pSoldier, UINT8 ubSeatIndex )
{
// TEST IF IT'S VALID...
if ( pVehicle->flags.uiStatusFlags & SOLDIER_VEHICLE )
{
// anv: check if preferred seat is available
if ( pVehicleList[ pVehicle->bVehicleID ].pPassengers[ubSeatIndex] == NULL )
{
INT8 bCurrentSeatIndex = GetSeatIndexFromSoldier( pSoldier );
if( bCurrentSeatIndex == (-1) )
{
return( FALSE );
}
INT16 sAPCost = APBPConstants[AP_CHANGE_SEAT_VEHICLE];
//Are we currently in combat?
if(gTacticalStatus.uiFlags & INCOMBAT)
{
if( gNewVehicle[pVehicleList[ pVehicle->bVehicleID ].ubVehicleType].VehicleSeats[bCurrentSeatIndex].ubCompartment !=
gNewVehicle[pVehicleList[ pVehicle->bVehicleID ].ubVehicleType].VehicleSeats[ubSeatIndex].ubCompartment )
{
// different compartment!
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, pVehicleSeatsStrings[1] );
return( FALSE );
}
if(EnoughPoints(pSoldier, sAPCost, 0, TRUE))
DeductPoints(pSoldier, sAPCost, 0);
else
return( FALSE );
}
pVehicleList[ pVehicle->bVehicleID ].pPassengers[ubSeatIndex] = pSoldier;
pVehicleList[ pVehicle->bVehicleID ].pPassengers[bCurrentSeatIndex] = NULL;
if( gNewVehicle[pVehicleList[ pVehicle->bVehicleID ].ubVehicleType].VehicleSeats[bCurrentSeatIndex].fDriver )
{
SetDriver( pVehicle->bVehicleID, NOBODY );
}
if( gNewVehicle[pVehicleList[ pVehicle->bVehicleID ].ubVehicleType].VehicleSeats[ubSeatIndex].fDriver )
{
SetDriver( pVehicle->bVehicleID, pSoldier->ubID );
}
// set proper initial rotation
UINT8 ubRotation = gNewVehicle[ pVehicleList[ pVehicle->bVehicleID ].ubVehicleType ].VehicleSeats[ ubSeatIndex ].ubRotation;
pSoldier->flags.fDontChargeTurningAPs = TRUE;
pSoldier->EVENT_SetSoldierDesiredDirection( ( pVehicle->pathing.bDesiredDirection + ubRotation ) % NUM_WORLD_DIRECTIONS );
UpdateAllVehiclePassengersGridNo( pVehicle );
return( TRUE );
}
}
return( FALSE );
}
BOOLEAN SwapVehicleSeat( SOLDIERTYPE *pVehicle, SOLDIERTYPE *pSoldier, UINT8 ubSeatIndex )
{
// TEST IF IT'S VALID...
if ( pVehicle->flags.uiStatusFlags & SOLDIER_VEHICLE )
{
SOLDIERTYPE *pSoldier2 = pVehicleList[ pVehicle->bVehicleID ].pPassengers[ubSeatIndex];
if ( pSoldier2 != NULL )
{
INT8 bCurrentSeatIndex = GetSeatIndexFromSoldier( pSoldier );
if( bCurrentSeatIndex == (-1) )
{
return( FALSE );
}
INT16 sAPCost = APBPConstants[AP_CHANGE_SEAT_VEHICLE];
//Are we currently in combat?
if(gTacticalStatus.uiFlags & INCOMBAT)
{
if( gNewVehicle[pVehicleList[ pVehicle->bVehicleID ].ubVehicleType].VehicleSeats[bCurrentSeatIndex].ubCompartment !=
gNewVehicle[pVehicleList[ pVehicle->bVehicleID ].ubVehicleType].VehicleSeats[ubSeatIndex].ubCompartment )
{
// different compartment!
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, pVehicleSeatsStrings[1] );
return( FALSE );
}
if( EnoughPoints(pSoldier, sAPCost, 0, TRUE) && EnoughPoints(pSoldier2, sAPCost, 0, TRUE) )
{
DeductPoints(pSoldier, sAPCost, 0);
DeductPoints(pSoldier2, sAPCost, 0);
}
else
return( FALSE );
}
pVehicleList[ pVehicle->bVehicleID ].pPassengers[ubSeatIndex] = pSoldier;
pVehicleList[ pVehicle->bVehicleID ].pPassengers[bCurrentSeatIndex] = pSoldier2;
if( gNewVehicle[pVehicleList[ pVehicle->bVehicleID ].ubVehicleType].VehicleSeats[bCurrentSeatIndex].fDriver )
{
SetDriver( pVehicle->bVehicleID, pSoldier2->ubID );
}
if( gNewVehicle[pVehicleList[ pVehicle->bVehicleID ].ubVehicleType].VehicleSeats[ubSeatIndex].fDriver )
{
SetDriver( pVehicle->bVehicleID, pSoldier->ubID );
}
// set proper initial rotations
UINT8 ubRotation = gNewVehicle[ pVehicleList[ pVehicle->bVehicleID ].ubVehicleType ].VehicleSeats[ ubSeatIndex ].ubRotation;
pSoldier->flags.fDontChargeTurningAPs = TRUE;
pSoldier->EVENT_SetSoldierDesiredDirection( ( pVehicle->pathing.bDesiredDirection + ubRotation ) % NUM_WORLD_DIRECTIONS );
ubRotation = gNewVehicle[ pVehicleList[ pVehicle->bVehicleID ].ubVehicleType ].VehicleSeats[ bCurrentSeatIndex ].ubRotation;
pSoldier2->flags.fDontChargeTurningAPs = TRUE;
pSoldier2->EVENT_SetSoldierDesiredDirection( ( pVehicle->pathing.bDesiredDirection + ubRotation ) % NUM_WORLD_DIRECTIONS );
UpdateAllVehiclePassengersGridNo( pVehicle );
return( TRUE );
}
else
{
return( ChangeVehicleSeat( pVehicle, pSoldier, ubSeatIndex ) );
}
}
return( FALSE );
}
void AddPassangersToTeamPanel( INT32 iId )
{
@@ -2009,6 +2207,11 @@ INT16 GetOrigInternalArmorValueForVehicleInLocation( UINT8 ubID, UINT8 ubLocatio
SOLDIERTYPE * GetSoldierStructureForVehicle( INT32 iId )
{
if( iId == (-1) )
{
return( 0 );
}
for( INT32 iCounter = 0; iCounter < TOTAL_SOLDIERS; iCounter++ )
{
SOLDIERTYPE *pSoldier = &Menptr[ iCounter ];
@@ -2357,8 +2560,88 @@ void UpdateAllVehiclePassengersGridNo( SOLDIERTYPE *pSoldier )
{
pPassenger = pVehicleList[ iId ].pPassengers[ iCounter ];
INT8 bOffsetX = gNewVehicle[ pVehicleList[ iId ].ubVehicleType ].VehicleSeats[ iCounter ].bOffsetX;
INT8 bOffsetY = gNewVehicle[ pVehicleList[ iId ].ubVehicleType ].VehicleSeats[ iCounter ].bOffsetY;
FLOAT dXOffset = 0;
FLOAT dYOffset = 0;
INT8 dX, dY;
INT8 bDiagonalX = 0;
INT8 bDiagonalY = 0;
switch( pSoldier->ubBodyType )
{
case ELDORADO:
case HUMVEE:
case JEEP:
bDiagonalY = -1;
}
switch( pSoldier->ubDirection )
{
case 0:
dYOffset = -10 * ( bOffsetY + bDiagonalY );
dXOffset = 10 * bOffsetX;
break;
case 1:
if( bOffsetX < 0 )
{
dXOffset = - 10 + 10 * bOffsetY;
dYOffset = - 10 * bOffsetY;
}
else
{
dYOffset = 10 + - 10 * bOffsetY;
dXOffset = 10 * bOffsetY;
}
break;
case 2:
dXOffset = 10 * ( bOffsetY + bDiagonalY);
dYOffset = 10 * bOffsetX;
break;
case 3:
dX = bOffsetY;
dY = bOffsetY;
if( bOffsetX > 0 )
dX -= 1;
else if( bOffsetX < 0 )
dY -= 1;
dXOffset = 10 * dX;
dYOffset = 10 * dY;
break;
case 4:
dYOffset = 10 * ( bOffsetY + bDiagonalY );
dXOffset = -10 * bOffsetX;
break;
case 5:
if( bOffsetX < 0 )
{
dXOffset = 10 + - 10 * bOffsetY;
dYOffset = 10 * bOffsetY;
}
else
{
dYOffset = - 10 + 10 * bOffsetY;
dXOffset = - 10 * bOffsetY;
}
break;
case 6:
dXOffset = -10 * ( bOffsetY + bDiagonalY );
dYOffset = -10 * bOffsetX;
break;
case 7:
dX = bOffsetY;
dY = bOffsetY;
if( bOffsetX > 0 )
dX -= 1;
else if( bOffsetX < 0 )
dY -= 1;
dXOffset = - 10 * dX;
dYOffset = - 10 * dY;
break;
}
// Set gridno.....
pPassenger->EVENT_SetSoldierPosition( pSoldier->dXPos, pSoldier->dYPos );
pPassenger->EVENT_SetSoldierPosition( pSoldier->dXPos + dXOffset, pSoldier->dYPos + dYOffset);
}
}
}
@@ -2595,6 +2878,12 @@ BOOLEAN CanSoldierDriveVehicle( SOLDIERTYPE *pSoldier, INT32 iVehicleId, BOOLEAN
return (FALSE);
}
// anv: only driver on driver's seat can drive
INT8 bSeatIndex = GetSeatIndexFromSoldier( pSoldier );
if( bSeatIndex == (-1) || gNewVehicle[ pVehicleList[ iVehicleId ].ubVehicleType ].VehicleSeats[bSeatIndex].fDriver == FALSE )
{
return (FALSE);
}
// yup, he could drive this vehicle
return( TRUE );
@@ -2708,6 +2997,38 @@ BOOLEAN IsSoldierInThisVehicleSquad( SOLDIERTYPE *pSoldier, INT8 bSquadNumber )
}
INT8 GetSeatIndexFromSoldier( SOLDIERTYPE *pSoldier )
{
INT32 iVehicleId;
SOLDIERTYPE *pVehicleSoldier;
INT32 iCounter;
iVehicleId = pSoldier->iVehicleId;
if( iVehicleId == (-1) )
{
return( -1 );
}
pVehicleSoldier = GetSoldierStructureForVehicle( iVehicleId );
if( pVehicleSoldier == NULL )
{
return( -1 );
}
// Loop through passengers
for( iCounter = 0; iCounter < gNewVehicle[ pVehicleList[ iVehicleId ].ubVehicleType ].iNewSeatingCapacities; iCounter++ )
{
if( pVehicleList[ iVehicleId ].pPassengers[ iCounter ] == pSoldier )
{
return( iCounter );
}
}
return( -1 );
}
SOLDIERTYPE* PickRandomPassengerFromVehicle( SOLDIERTYPE *pSoldier )
{
// WDS - make number of mercenaries, etc. be configurable
+27 -20
View File
@@ -11,6 +11,25 @@
extern std::vector<INT8> gubVehicleMovementGroups;
#define MAX_MAIN_VEHICLE_CHARS 500
typedef struct
{
UINT8 ubSeatIndex; // index inside a vehicle (corresponding to .pPassengers[counter])
CHAR16 zSeatName[20]; // name (to display on entering menu and on team panel)
BOOLEAN fDriver; // seat has to be taken to steer the vehicle
BOOLEAN fBlockedView; // can't look out of vehicle
BOOLEAN fBlockedShots; // can't shoot from this seat
BOOLEAN fSeatBelt; // for collisions
BOOLEAN fHidden; // merc on this seat is invisible from outside - spy as a driver smuggling in others?
UINT8 ubRotation; // initial rotation in relation to vehicle
INT8 bOffsetX; // X offset of seat grid, relative to vehicle middle
INT8 bOffsetY; // Y offset of seat grid, relative to vehicle middle
UINT8 ubCoverage; // influence probability vehicle will be hit instead of passenger
UINT8 ubCompartment; // passenger can switch to another seat in the same compartment without exiting vehicle
UINT8 ubStructureLink; // link to physical part of structure (for hit calculations)
UINT32 usMountedGun; // passenger on this seat will use this gun instead of his own, link to Items.xml
} VEHICLE_SEAT;
typedef struct
{
UINT8 uiIndex;
@@ -30,27 +49,10 @@ typedef struct
CHAR16 NewShortVehicleStrings[128];
INT32 NewCarPortraits;
BOOLEAN NewUsed;
VEHICLE_SEAT VehicleSeats[10];
} NEW_CAR;
typedef struct
{
UINT8 ubSeatIndex; // index inside a vehicle (corresponding to .pPassengers[counter])
CHAR16 zSeatName[16]; // name (to display on entering menu and on team panel)
BOOLEAN fDriver; // seat has to be taken to steer the vehicle
BOOLEAN fView; // can look out of vehicle
BOOLEAN fDriveBy; // can shoot from this seat
BOOLEAN fSeatBelt; // for collisions
BOOLEAN fHidden; // merc on this seat is invisible from outside - spy as a driver smuggling in others?
UINT8 ubRotation; // rotation in relation to vehicle
UINT8 ubTunnelVision; // tunnel vision (small windows, etc.)
UINT8 ubProtection; // influence probability vehicle will be hit instead of passenger
UINT8 ubCompartment; // passenger can switch to another seat in the same compartment without exiting vehicle
UINT8 ubStructureLink; // link to physical part of structure (for hit calculations)
UINT32 usMountedGun; // passenger on this seat will use this gun instead of his own, link to Items.xml
} VEHICLE_SEAT;
extern NEW_CAR gNewVehicle[NUM_PROFILES];
extern BOOLEAN LoadNewVehiclesToSaveGameFile( HWFILE hFile );
@@ -331,7 +333,7 @@ BOOLEAN AnyAccessibleVehiclesInSoldiersSector( SOLDIERTYPE *pSoldier );
BOOLEAN IsThisVehicleAccessibleToSoldier( SOLDIERTYPE *pSoldier, INT32 iId );
// add soldier to Vehicle
BOOLEAN AddSoldierToVehicle( SOLDIERTYPE *pSoldier, INT32 iId, BOOLEAN fSpecificSeat = FALSE, UINT8 ubSeatIndex = 0 );
BOOLEAN AddSoldierToVehicle( SOLDIERTYPE *pSoldier, INT32 iId, UINT8 ubSeatIndex = 0 );
// remove soldier from vehicle
BOOLEAN RemoveSoldierFromVehicle( SOLDIERTYPE *pSoldier, INT32 iId );
@@ -387,7 +389,7 @@ INT32 GetNumberInVehicle( INT32 iId );
// grab # in vehicle skipping EPCs (who aren't allowed to drive :-)
INT32 GetNumberOfNonEPCsInVehicle( INT32 iId );
BOOLEAN EnterVehicle( SOLDIERTYPE *pVehicle, SOLDIERTYPE *pSoldier, BOOLEAN fSpecificSeat = FALSE, UINT8 ubSeatIndex = 0 );
BOOLEAN EnterVehicle( SOLDIERTYPE *pVehicle, SOLDIERTYPE *pSoldier, UINT8 ubSeatIndex = 0 );
SOLDIERTYPE *GetDriver( INT32 iID );
@@ -395,6 +397,9 @@ void SetVehicleName( SOLDIERTYPE *pVehicle );
BOOLEAN ExitVehicle( SOLDIERTYPE *pSoldier );
BOOLEAN ChangeVehicleSeat( SOLDIERTYPE *pVehicle, SOLDIERTYPE *pSoldier, UINT8 ubSeatIndex );
BOOLEAN SwapVehicleSeat( SOLDIERTYPE *pVehicle, SOLDIERTYPE *pSoldier, UINT8 ubSeatIndex );
void AddPassangersToTeamPanel( INT32 iId );
@@ -456,6 +461,8 @@ BOOLEAN IsEnoughSpaceInVehicle( INT32 iID );
BOOLEAN IsSoldierInThisVehicleSquad( SOLDIERTYPE *pSoldier, INT8 bSquadNumber );
INT8 GetSeatIndexFromSoldier( SOLDIERTYPE *pSoldier );
SOLDIERTYPE* PickRandomPassengerFromVehicle( SOLDIERTYPE *pSoldier );
BOOLEAN DoesVehicleHaveAnyPassengers( INT32 iVehicleID );
+104 -2
View File
@@ -19,6 +19,7 @@ struct
UINT32 maxArraySize;
UINT32 curIndex;
UINT32 curSeatIndex;
UINT32 currentDepth;
UINT32 maxReadDepth;
}
@@ -65,6 +66,28 @@ newCarStartElementHandle(void *userData, const XML_Char *name, const XML_Char **
pData->curElement = ELEMENT_PROPERTY;
pData->maxReadDepth++;
}
else if(strcmp(name, "SEAT") == 0 && pData->curElement == ELEMENT)
{
pData->curElement = ELEMENT_SUBLIST;
pData->maxReadDepth++;
}
else if(pData->curElement == ELEMENT_SUBLIST &&
(strcmp(name, "SeatIndex") == 0 ||
strcmp(name, "SeatName") == 0 ||
strcmp(name, "Driver") == 0 ||
strcmp(name, "Hidden") == 0 ||
strcmp(name, "BlockedView") == 0 ||
strcmp(name, "BlockedShots") == 0 ||
strcmp(name, "Rotation") == 0 ||
strcmp(name, "OffsetX") == 0 ||
strcmp(name, "OffsetY") == 0 ||
strcmp(name, "Coverage") == 0 ||
strcmp(name, "Compartment") == 0 ||
strcmp(name, "MountedGun") == 0 ))
{
pData->curElement = ELEMENT_SUBLIST_PROPERTY;
pData->maxReadDepth++; //we are not skipping this element
}
pData->szCharData[0] = '\0';
}
@@ -121,13 +144,16 @@ newCarEndElementHandle(void *userData, const XML_Char *name)
wcscpy(gNewVehicle[pData->curNewCar.uiIndex].NewVehicleName, pData->curNewCar.NewVehicleName);
wcscpy(gNewVehicle[pData->curNewCar.uiIndex].NewShortVehicleStrings, pData->curNewCar.NewShortVehicleStrings);
gNewVehicle[ pData->curNewCar.uiIndex ].NewUsed = FALSE;
memcpy( gNewVehicle[ pData->curNewCar.uiIndex ].VehicleSeats, pData->curNewCar.VehicleSeats, sizeof(pData->curNewCar.VehicleSeats) );
}
else
{
wcscpy(gNewVehicle[pData->curNewCar.uiIndex].NewVehicleStrings, pData->curNewCar.NewVehicleStrings);
wcscpy(gNewVehicle[pData->curNewCar.uiIndex].NewVehicleName, pData->curNewCar.NewVehicleName);
wcscpy(gNewVehicle[pData->curNewCar.uiIndex].NewShortVehicleStrings, pData->curNewCar.NewShortVehicleStrings);
}
wcscpy(gNewVehicle[pData->curNewCar.uiIndex].NewShortVehicleStrings, pData->curNewCar.NewShortVehicleStrings);
}
memset( pData->curNewCar.VehicleSeats, 0, sizeof(pData->curNewCar.VehicleSeats) );
}
else if(strcmp(name, "uiIndex") == 0)
{
@@ -213,6 +239,81 @@ newCarEndElementHandle(void *userData, const XML_Char *name)
pData->curNewCar.szIconFace[i] = temp;
}
}
else if(strcmp(name, "SEAT") == 0 )
{
pData->curElement = ELEMENT;
if (!NewCar_TextOnly)
{
memcpy( gNewVehicle[pData->curNewCar.uiIndex].VehicleSeats, pData->curNewCar.VehicleSeats, sizeof(pData->curNewCar.VehicleSeats) );
}
else
{
wcscpy( gNewVehicle[pData->curNewCar.uiIndex].VehicleSeats[pData->curSeatIndex].zSeatName, pData->curNewCar.VehicleSeats[pData->curSeatIndex].zSeatName );
}
}
else if(strcmp(name, "SeatIndex") == 0)
{
pData->curElement = ELEMENT_SUBLIST;
pData->curSeatIndex = (int) atol(pData->szCharData);
pData->curNewCar.VehicleSeats[pData->curSeatIndex].ubSeatIndex = pData->curSeatIndex;
}
else if(strcmp(name, "SeatName") == 0)
{
pData->curElement = ELEMENT_SUBLIST;
MultiByteToWideChar( CP_UTF8, 0, pData->szCharData, -1, pData->curNewCar.VehicleSeats[pData->curSeatIndex].zSeatName, sizeof(pData->curNewCar.VehicleSeats[pData->curSeatIndex].zSeatName)/sizeof( pData->curNewCar.VehicleSeats[pData->curSeatIndex].zSeatName[0]) );
pData->curNewCar.VehicleSeats[pData->curSeatIndex].zSeatName[sizeof(pData->curNewCar.VehicleSeats[pData->curSeatIndex].zSeatName)/sizeof(pData->curNewCar.VehicleSeats[pData->curSeatIndex].zSeatName[0]) - 1] = '\0';
}
else if(strcmp(name, "Driver") == 0)
{
pData->curElement = ELEMENT_SUBLIST;
pData->curNewCar.VehicleSeats[pData->curSeatIndex].fDriver = (BOOLEAN) atol(pData->szCharData);
}
else if(strcmp(name, "Hidden") == 0)
{
pData->curElement = ELEMENT_SUBLIST;
pData->curNewCar.VehicleSeats[pData->curSeatIndex].fHidden = (BOOLEAN) atol(pData->szCharData);
}
else if(strcmp(name, "BlockedView") == 0)
{
pData->curElement = ELEMENT_SUBLIST;
pData->curNewCar.VehicleSeats[pData->curSeatIndex].fBlockedView = (BOOLEAN) atol(pData->szCharData);
}
else if(strcmp(name, "BlockedShots") == 0)
{
pData->curElement = ELEMENT_SUBLIST;
pData->curNewCar.VehicleSeats[pData->curSeatIndex].fBlockedShots = (BOOLEAN) atol(pData->szCharData);
}
else if(strcmp(name, "Rotation") == 0)
{
pData->curElement = ELEMENT_SUBLIST;
pData->curNewCar.VehicleSeats[pData->curSeatIndex].ubRotation = (UINT8) atol(pData->szCharData);
}
else if(strcmp(name, "OffsetX") == 0)
{
pData->curElement = ELEMENT_SUBLIST;
pData->curNewCar.VehicleSeats[pData->curSeatIndex].bOffsetX = (INT8) atol(pData->szCharData);
}
else if(strcmp(name, "OffsetY") == 0)
{
pData->curElement = ELEMENT_SUBLIST;
pData->curNewCar.VehicleSeats[pData->curSeatIndex].bOffsetY = (INT8) atol(pData->szCharData);
}
else if(strcmp(name, "Coverage") == 0)
{
pData->curElement = ELEMENT_SUBLIST;
pData->curNewCar.VehicleSeats[pData->curSeatIndex].ubCoverage = (UINT8) atol(pData->szCharData);
}
else if(strcmp(name, "Compartment") == 0)
{
pData->curElement = ELEMENT_SUBLIST;
pData->curNewCar.VehicleSeats[pData->curSeatIndex].ubCompartment = (UINT8) atol(pData->szCharData);
}
else if(strcmp(name, "MountedGun") == 0)
{
pData->curElement = ELEMENT_SUBLIST;
pData->curNewCar.VehicleSeats[pData->curSeatIndex].usMountedGun = (UINT32) atol(pData->szCharData);
}
pData->maxReadDepth--;
@@ -301,6 +402,7 @@ void InitNewVehicles ()
gNewVehicle[ iCount ].NewVehicleName[127] = '\0';
gNewVehicle[ iCount ].NewShortVehicleStrings[127] = '\0';
gNewVehicle[ iCount ].NewUsed = FALSE;
memset( &gNewVehicle[ iCount ].VehicleSeats, 0, sizeof(gNewVehicle[ iCount ].VehicleSeats) );
}
}
+34
View File
@@ -48,6 +48,7 @@
#include "drugs and alcohol.h"
#include "Interface.h"
#include "Explosion Control.h"//dnl ch40 200909
#include "Vehicles.h"
#endif
#ifdef JA2UB
@@ -1217,6 +1218,18 @@ INT16 DistanceVisible( SOLDIERTYPE *pSoldier, INT8 bFacingDir, INT8 bSubjectDir,
return( 0 );
}
// anv: some places in vehicle don't give passenger any view outside
INT8 bSeatIndex = GetSeatIndexFromSoldier( pSoldier );
if( bSeatIndex != (-1) )
{
SOLDIERTYPE *pVehicle = GetSoldierStructureForVehicle( pSoldier ->iVehicleId );
// need to check this even if bSubjectDir is DIRECTION_IRRELEVANT
if( gNewVehicle[ pVehicleList[ pSoldier->iVehicleId ].ubVehicleType ].VehicleSeats[ bSeatIndex ].fBlockedView )
{
return( 0 );
}
}
if ( bFacingDir == DIRECTION_IRRELEVANT && TANK( pSoldier ) )
{
// always calculate direction for tanks so we have something to work with
@@ -5296,6 +5309,8 @@ void DebugSoldierPage4( )
//
#define MAX_MOVEMENT_NOISE 9
#define VEHICLE_FAST_MOVEMENT_NOISE 25
#define VEHICLE_NORMAL_MOVEMENT_NOISE 15
UINT8 MovementNoise( SOLDIERTYPE *pSoldier )
{
@@ -5303,6 +5318,25 @@ UINT8 MovementNoise( SOLDIERTYPE *pSoldier )
UINT8 ubMaxVolume, ubVolume, ubBandaged, ubEffLife;
INT8 bInWater = FALSE;
// anv: vehicle and passengers
if( pSoldier->flags.uiStatusFlags & ( SOLDIER_DRIVER | SOLDIER_PASSENGER ) )
{
return( 0 );
}
else if( pSoldier->flags.uiStatusFlags & ( SOLDIER_VEHICLE ) )
{
if( pSoldier->usAnimState == RUNNING )
{
// driving fast makes engine work louder
return( VEHICLE_FAST_MOVEMENT_NOISE );
}
else
{
return( VEHICLE_NORMAL_MOVEMENT_NOISE );
}
}
// anv: additional tile properties
// modify amount of noise and stealth difficulty depending on surface type
+1
View File
@@ -177,6 +177,7 @@ bool Loc::ExportStrings()
ExportSection(props, L"Vehicle", Loc::pVehicleStrings, 0, 6);
ExportSection(props, L"ShortVehicle", Loc::pShortVehicleStrings, 0, 6);
ExportSection(props, L"VehicleName", Loc::zVehicleName, 0, 6);
ExportSection(props, L"VehicleSeatsStrings", Loc::pVehicleSeatsStrings, 0, 2);
ExportSection(props, L"Tactical", Loc::TacticalStr, 0, TEXT_NUM_TACTICAL_STR);
ExportSection(props, L"ExitingSectorHelp", Loc::pExitingSectorHelpText, 0, TEXT_NUM_EXIT_GUI);
+1
View File
@@ -740,6 +740,7 @@ extern STR16 sKeyDescriptionStrings[2];
extern CHAR16 zHealthStr[][13];
extern STR16 gzHiddenHitCountStr[1];
extern STR16 zVehicleName[ 6 ];
extern STR16 pVehicleSeatsStrings[ 2 ] ;
// Flugente: externalised texts for some features
enum
+5
View File
@@ -3072,6 +3072,11 @@ STR16 zVehicleName[] =
L"直升飞机", //an abbreviation for Helicopter
};
STR16 pVehicleSeatsStrings[] =
{
L"You cannot shoot from this seat.", // TODO.Translate
L"You cannot swap those two seats in combat without exiting vehicle first.", // TODO.Translate
};
//These are messages Used in the Tactical Screen
+5
View File
@@ -3070,6 +3070,11 @@ STR16 zVehicleName[] =
L"Heli", //an abbreviation for Helicopter
};
STR16 pVehicleSeatsStrings[] =
{
L"You cannot shoot from this seat.", // TODO.Translate
L"You cannot swap those two seats in combat without exiting vehicle first.", // TODO.Translate
};
//These are messages Used in the Tactical Screen
+5
View File
@@ -3072,6 +3072,11 @@ STR16 zVehicleName[] =
L"Heli", //an abbreviation for Helicopter
};
STR16 pVehicleSeatsStrings[] =
{
L"You cannot shoot from this seat.",
L"You cannot swap those two seats in combat without exiting vehicle first.",
};
//These are messages Used in the Tactical Screen
+5
View File
@@ -3074,6 +3074,11 @@ STR16 zVehicleName[] =
L"Hélico", //an abbreviation for Helicopter
};
STR16 pVehicleSeatsStrings[] =
{
L"You cannot shoot from this seat.", // TODO.Translate
L"You cannot swap those two seats in combat without exiting vehicle first.", // TODO.Translate
};
//These are messages Used in the Tactical Screen
+6
View File
@@ -3075,6 +3075,12 @@ STR16 zVehicleName[] =
L"Heli", //an abbreviation for Helicopter
};
STR16 pVehicleSeatsStrings[] =
{
L"You cannot shoot from this seat.", // TODO.Translate
L"You cannot swap those two seats in combat without exiting vehicle first.", // TODO.Translate
};
//These are messages Used in the Tactical Screen
CHAR16 TacticalStr[][ MED_STRING_LENGTH ] =
{
+5
View File
@@ -3066,6 +3066,11 @@ STR16 zVehicleName[] =
L"Eli", //an abbreviation for Helicopter
};
STR16 pVehicleSeatsStrings[] =
{
L"You cannot shoot from this seat.", // TODO.Translate
L"You cannot swap those two seats in combat without exiting vehicle first.", // TODO.Translate
};
//These are messages Used in the Tactical Screen
+5
View File
@@ -3079,6 +3079,11 @@ STR16 zVehicleName[] =
L"Heli.", //an abbreviation for Helicopter
};
STR16 pVehicleSeatsStrings[] =
{
L"Nie jesteś w stanie strzelać z tego miejsca.",
L"Nie możesz sie przesiąść między tymi dwoma miejscami bez opuszczania pojazdu.",
};
//These are messages Used in the Tactical Screen
+5
View File
@@ -3072,6 +3072,11 @@ STR16 zVehicleName[] =
L"Вертолёт", //an abbreviation for Helicopter
};
STR16 pVehicleSeatsStrings[] =
{
L"You cannot shoot from this seat.", // TODO.Translate
L"You cannot swap those two seats in combat without exiting vehicle first.", // TODO.Translate
};
//These are messages Used in the Tactical Screen
+5
View File
@@ -3075,6 +3075,11 @@ STR16 zVehicleName[] =
L"Heli", //an abbreviation for Helicopter
};
STR16 pVehicleSeatsStrings[] =
{
L"You cannot shoot from this seat.", // TODO.Translate
L"You cannot swap those two seats in combat without exiting vehicle first.", // TODO.Translate
};
//These are messages Used in the Tactical Screen