Vehicle Update: Roadkill with vehicles and ramming (by anv)

- new feature: ramming people - set with Tactical Gameplay Settings > ALLOW_CARS_DRIVING_OVER_PEOPLE and Tactical Gameplay Settings > ALLOW_TANKS_DRIVING_OVER_PEOPLE - when shift is pressed planned vehicle route will go through people. Those who will stay on its path will be hit, causing wounds and knock-outs.
- new feature: ramming structures - when shift is pressed planned vehicle route will go through obstacles. When vehicle hits the structure on its path it will be destroyed, causing small damage to vehicle too (with exception of tank). Tactical Gameplay Settings > CARS_RAMMING_MAX_STRUCTURE_ARMOUR and Tactical Gameplay Settings > TANKS_RAMMING_MAX_STRUCTURE_ARMOUR settings control how well armoured structure can be driven through and amount of potential damage for vehicle.
- see: http://www.ja-galaxy-forum.com/ubbthreads.php/topics/333829/Drivable_Vehicles#Post333829


git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@7284 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
Wanne
2014-06-21 10:07:11 +00:00
parent fc78fb6031
commit dbc852ea74
14 changed files with 331 additions and 19 deletions
+6
View File
@@ -1383,6 +1383,12 @@ void LoadGameExternalOptions()
gGameExternalOptions.fAllowDrivingVehiclesInTactical = iniReader.ReadBoolean("Tactical Gameplay Settings","ALLOW_DRIVING_VEHICLES_IN_TACTICAL", TRUE);
gGameExternalOptions.fAllowCarsDrivingOverPeople = iniReader.ReadBoolean("Tactical Gameplay Settings","ALLOW_CARS_DRIVING_OVER_PEOPLE", TRUE);
gGameExternalOptions.fAllowTanksDrivingOverPeople = iniReader.ReadBoolean("Tactical Gameplay Settings","ALLOW_TANKS_DRIVING_OVER_PEOPLE", TRUE);
gGameExternalOptions.ubCarsRammingMaxStructureArmour = iniReader.ReadInteger("Tactical Gameplay Settings","CARS_RAMMING_MAX_STRUCTURE_ARMOUR", 30, 0, 255);
gGameExternalOptions.ubTanksRammingMaxStructureArmour = iniReader.ReadInteger("Tactical Gameplay Settings","TANKS_RAMMING_MAX_STRUCTURE_ARMOUR", 70, 0, 255);
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);
+6
View File
@@ -1477,6 +1477,12 @@ typedef struct
BOOLEAN fAllowDrivingVehiclesInTactical;
BOOLEAN fAllowCarsDrivingOverPeople;
BOOLEAN fAllowTanksDrivingOverPeople;
UINT8 ubCarsRammingMaxStructureArmour;
UINT8 ubTanksRammingMaxStructureArmour;
UINT8 ubAPSharedAmongPassengersAndVehicleMode;
UINT8 ubAPSharedAmongPassengersAndVehicleScale;
+9
View File
@@ -2057,6 +2057,15 @@ UINT32 UIHandleCMoveMerc( UI_EVENT *pUIEvent )
if ( pSoldier->flags.uiStatusFlags & (SOLDIER_DRIVER ) )
{
pSoldier = GetSoldierStructureForVehicle( MercPtrs[ pSoldier->ubID ]->iVehicleId );
// anv: if shift is pressed, treat is as ram + move - flag has to be set for later add structure checks
if ( _KeyDown( SHIFT ) )
{
pSoldier->usSoldierFlagMask2 |= SOLDIER_RAM_THROUGH_OBSTACLES;
}
else
{
pSoldier->usSoldierFlagMask2 &= ~SOLDIER_RAM_THROUGH_OBSTACLES;
}
}
// CHRISL: This block should only run if we're running in the new inventory system
+1
View File
@@ -186,6 +186,7 @@ enum
#define FIRE_WEAPON_DEAFENED 10
#define FIRE_WEAPON_BLINDED_AND_DEAFENED 11
#define FIRE_WEAPON_BLINDED_SPECIAL 12 // Flugente: works like FIRE_WEAPON_BLINDED_BY_SPIT_SPECIAL but without the damage dependency
#define FIRE_WEAPON_VEHICLE_TRAUMA 13
#define NO_INTERRUPTS 0
+11 -3
View File
@@ -4765,7 +4765,7 @@ CHAR8 *GetSceneFilename( )
return( gzLevelFilenames[ gubCurrentScene ] );
}
extern BOOLEAN InternalOkayToAddStructureToWorld( INT32 sBaseGridNo, INT8 bLevel, DB_STRUCTURE_REF * pDBStructureRef, INT16 sExclusionID, BOOLEAN fIgnorePeople );
extern BOOLEAN InternalOkayToAddStructureToWorld( INT32 sBaseGridNo, INT8 bLevel, DB_STRUCTURE_REF * pDBStructureRef, INT16 sExclusionID, BOOLEAN fAddingForReal, INT16 sSoldierID );
// NB if making changes don't forget to update NewOKDestinationAndDirection
INT16 NewOKDestination( SOLDIERTYPE * pCurrSoldier, INT32 sGridNo, BOOLEAN fPeopleToo, INT8 bLevel )
@@ -4830,7 +4830,15 @@ INT16 NewOKDestination( SOLDIERTYPE * pCurrSoldier, INT32 sGridNo, BOOLEAN fPeop
usStructureID = INVALID_STRUCTURE_ID;
}
fOk = InternalOkayToAddStructureToWorld( sGridNo, bLevel, &(pStructureFileRef->pDBStructureRef[bLoop]), usStructureID, (BOOLEAN)!fPeopleToo );
// anv: allow ramming as a mean of getting to destination
if( _KeyDown( SHIFT ) && ( pCurrSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) && pCurrSoldier->bTeam == gbPlayerNum )
{
fOk = InternalOkayToAddStructureToWorld( sGridNo, bLevel, &(pStructureFileRef->pDBStructureRef[bLoop]), VEHICLE_IGNORE_OBSTACLES_STRUCTURE_ID, FALSE, pCurrSoldier->ubID );
}
else
{
fOk = InternalOkayToAddStructureToWorld( sGridNo, bLevel, &(pStructureFileRef->pDBStructureRef[bLoop]), usStructureID, FALSE, pCurrSoldier->ubID );
}
if (fOk)
{
return( TRUE );
@@ -4951,7 +4959,7 @@ INT16 NewOKDestinationAndDirection( SOLDIERTYPE * pCurrSoldier, INT32 sGridNo, I
usStructureID = pCurrSoldier->pLevelNode->pStructureData->usStructureID;
}
fOk = InternalOkayToAddStructureToWorld( sGridNo, pCurrSoldier->pathing.bLevel, &(pStructureFileRef->pDBStructureRef[ gOneCDirection[ bLoop ] ]), usStructureID, (BOOLEAN)!fPeopleToo );
fOk = InternalOkayToAddStructureToWorld( sGridNo, pCurrSoldier->pathing.bLevel, &(pStructureFileRef->pDBStructureRef[ gOneCDirection[ bLoop ] ]), usStructureID, FALSE, pCurrSoldier->ubID );
if (fOk)
{
return( TRUE );
+32 -3
View File
@@ -40,6 +40,7 @@
#include "gamesettings.h"
#include "Buildings.h"
#include "soldier profile.h" // added by SANDRO
#include "Soldier macros.h"
#endif
#include "connect.h"
@@ -2516,6 +2517,7 @@ b=GetJA2Clock();//return s->sGridNo+6;
STRUCTURE_FILE_REF * pStructureFileRef=NULL;
UINT16 usAnimSurface;
//INT32 iCnt2, iCnt3;
BOOLEAN fVehicleIgnoreObstacles = FALSE;
#endif
INT32 iLastDir = 0;
@@ -2628,6 +2630,25 @@ if(!GridNoOnVisibleWorldTile(iDestination))
}
}
fPathAroundPeople = ( (fFlags & PATH_THROUGH_PEOPLE) == 0 );
// anv: vehicles can drive through people and structures if shift is pressed
// (or rather route through can be planned, actual driving through is dependent on SOLDIER_RAM_THROUGH_OBSTACLES flag set in Handle UI)
if ( _KeyDown( SHIFT ) && fPathingForPlayer && ( s->flags.uiStatusFlags & SOLDIER_VEHICLE ) )
{
fVehicleIgnoreObstacles = TRUE;
}
// AI can't press shift, let's assume only tanks ram through (we wouldn't want AI cars to get destroyed kamikazing through walls, no matter how funny that would be)
else if( !fPathingForPlayer && TANK(s) )
{
fVehicleIgnoreObstacles = TRUE;
}
if( fVehicleIgnoreObstacles &&
( ( gGameExternalOptions.fAllowCarsDrivingOverPeople && !TANK(s) ) ||
( gGameExternalOptions.fAllowTanksDrivingOverPeople && TANK(s) ) ) )
{
fPathAroundPeople = FALSE;
}
fCloseGoodEnough = ( (fFlags & PATH_CLOSE_GOOD_ENOUGH) != 0);
if ( fCloseGoodEnough )
{
@@ -2758,6 +2779,10 @@ if(!GridNoOnVisibleWorldTile(iDestination))
{
usOKToAddStructID = INVALID_STRUCTURE_ID;
}
if( fVehicleIgnoreObstacles )
{
usOKToAddStructID = VEHICLE_IGNORE_OBSTACLES_STRUCTURE_ID;
}
}
else
@@ -3006,7 +3031,7 @@ if(!GridNoOnVisibleWorldTile(iDestination))
{
if ( iCnt != iLastDir )
{
if ( !OkayToAddStructureToWorld( curLoc, ubLevel, &(pStructureFileRef->pDBStructureRef[ iStructIndex ]), usOKToAddStructID ) )
if ( !OkayToAddStructureToWorld( curLoc, ubLevel, &(pStructureFileRef->pDBStructureRef[ iStructIndex ]), usOKToAddStructID, FALSE, s->ubID ) )
{
// we have to abort this loop and possibly reset the loop conditions to
// search in the other direction (if we haven't already done the other dir)
@@ -3126,7 +3151,7 @@ if(!GridNoOnVisibleWorldTile(iDestination))
}
//how much is admission to the next tile
if ( gfPathAroundObstacles )
if ( gfPathAroundObstacles && !fVehicleIgnoreObstacles )
{
nextCost = gubWorldMovementCosts[ newLoc ][ iCnt ][ ubLevel ];
@@ -3351,6 +3376,10 @@ if(!GridNoOnVisibleWorldTile(iDestination))
goto NEXTDIR;
}
else if( fVehicleIgnoreObstacles )
{
nextCost = TRAVELCOST_FLAT;
}
else
{
nextCost = TRAVELCOST_FLAT;
@@ -3394,7 +3423,7 @@ if(!GridNoOnVisibleWorldTile(iDestination))
// then 0 1 2 3 4 5 6), we must subtract 1 from the direction
// ATE: Send in our existing structure ID so it's ignored!
if (!OkayToAddStructureToWorld( newLoc, ubLevel, &(pStructureFileRef->pDBStructureRef[ iStructIndex ]), usOKToAddStructID ) )
if (!OkayToAddStructureToWorld( newLoc, ubLevel, &(pStructureFileRef->pDBStructureRef[ iStructIndex ]), usOKToAddStructID, FALSE, s->ubID ) )
{
goto NEXTDIR;
}
+2 -1
View File
@@ -3868,8 +3868,9 @@ BOOLEAN HandleSoldierDeath( SOLDIERTYPE *pSoldier , BOOLEAN *pfMadeCorpse )
//////////////////////////////////////////////////////////////
{
// anv: note that ubAttacker can be already different from pSoldier->ubAttackerID
// IF this guy has an attacker and he's a good guy, play sound
if ( ubAttacker != NOBODY )
if ( pSoldier->ubAttackerID != NOBODY )
{
if ( MercPtrs[ pSoldier->ubAttackerID ] != NULL && MercPtrs[ pSoldier->ubAttackerID ]->bTeam == gbPlayerNum && gTacticalStatus.ubAttackBusyCount > 0 )
{
+113 -1
View File
@@ -1699,6 +1699,7 @@ void SoldierGotHitGunFire( SOLDIERTYPE *pSoldier, UINT16 usWeaponIndex, INT16 sD
void SoldierGotHitBlade( SOLDIERTYPE *pSoldier, UINT16 usWeaponIndex, INT16 sDamage, UINT16 bDirection, UINT16 sRange, UINT8 ubAttackerID, UINT8 ubSpecial, UINT8 ubHitLocation );
void SoldierGotHitPunch( SOLDIERTYPE *pSoldier, UINT16 usWeaponIndex, INT16 sDamage, UINT16 bDirection, UINT16 sRange, UINT8 ubAttackerID, UINT8 ubSpecial, UINT8 ubHitLocation );
void SoldierGotHitExplosion( SOLDIERTYPE *pSoldier, UINT16 usWeaponIndex, INT16 sDamage, UINT16 bDirection, UINT16 sRange, UINT8 ubAttackerID, UINT8 ubSpecial, UINT8 ubHitLocation );
void SoldierGotHitVehicle( SOLDIERTYPE *pSoldier, UINT16 usWeaponIndex, INT16 sDamage, UINT16 bDirection, UINT16 sRange, UINT8 ubAttackerID, UINT8 ubSpecial, UINT8 ubHitLocation );
UINT8 CalcScreamVolume( SOLDIERTYPE * pSoldier, UINT8 ubCombinedLoss );
void PlaySoldierFootstepSound( SOLDIERTYPE *pSoldier );
void HandleSystemNewAISituation( SOLDIERTYPE *pSoldier, BOOLEAN fResetABC );
@@ -5721,6 +5722,10 @@ void SOLDIERTYPE::EVENT_SoldierGotHit( UINT16 usWeaponIndex, INT16 sDamage, INT1
{
ubReason = TAKE_DAMAGE_TENTACLES;
}
else if ( ubSpecial == FIRE_WEAPON_VEHICLE_TRAUMA )
{
ubReason = TAKE_DAMAGE_VEHICLE_TRAUMA;
}
// marke take out gunfire if ammotype is explosive
// callahan update start
@@ -6092,6 +6097,13 @@ void SOLDIERTYPE::EVENT_SoldierGotHit( UINT16 usWeaponIndex, INT16 sDamage, INT1
}
}
// anv: soldier got rammed by vehicle
if ( ubSpecial == FIRE_WEAPON_VEHICLE_TRAUMA )
{
SoldierGotHitVehicle( this, usWeaponIndex, sDamage, bDirection, sRange, ubAttackerID, ubSpecial, ubHitLocation );
return;
}
// CHECK FOR DOING HIT WHILE DOWN
if ( ( gAnimControl[ this->usAnimState ].uiFlags & ANIM_HITSTOP ) )
{
@@ -6811,6 +6823,70 @@ void SoldierGotHitPunch( SOLDIERTYPE *pSoldier, UINT16 usWeaponIndex, INT16 sDam
}
void SoldierGotHitVehicle( SOLDIERTYPE *pSoldier, UINT16 usWeaponIndex, INT16 sDamage, UINT16 bDirection, UINT16 sRange, UINT8 ubAttackerID, UINT8 ubSpecial, UINT8 ubHitLocation )
{
INT32 sNewGridNo = 0;
// IF HERE AND GUY IS DEAD, RETURN!
if ( pSoldier->flags.uiStatusFlags & SOLDIER_DEAD )
{
return;
}
if( pSoldier->flags.fTryingToFall )
{
return;
}
switch ( gAnimControl[ pSoldier->usAnimState ].ubEndHeight )
{
case ANIM_STAND:
sNewGridNo = NewGridNo( pSoldier->sGridNo, DirectionInc( bDirection ) );//DirectionInc( gOppositeDirection[ bDirection ] ) );
if( IS_MERC_BODY_TYPE( pSoldier ) && OKFallDirection( pSoldier, sNewGridNo, pSoldier->pathing.bLevel, bDirection, FLYBACK_HIT ) )
{
pSoldier->EVENT_SetSoldierDirection( (INT8)gOppositeDirection[ bDirection ] );
pSoldier->EVENT_SetSoldierDesiredDirection( pSoldier->ubDirection );
pSoldier->ChangeToFallbackAnimation( (UINT8)gOppositeDirection[ bDirection ] );
}
else if( IS_MERC_BODY_TYPE( pSoldier ) )
{
pSoldier->EVENT_SetSoldierDirection( bDirection );
pSoldier->EVENT_SetSoldierDesiredDirection( pSoldier->ubDirection );
pSoldier->BeginTyingToFall( );
pSoldier->EVENT_InitNewSoldierAnim( FALLFORWARD_FROMHIT_STAND, 0, FALSE );
}
else
{
SoldierCollapse( pSoldier );
}
break;
case ANIM_CROUCH:
pSoldier->EVENT_SetSoldierDirection( (INT8)gOppositeDirection[ bDirection ] );
pSoldier->EVENT_SetSoldierDesiredDirection( pSoldier->ubDirection );
// Check behind us!
sNewGridNo = NewGridNo( pSoldier->sGridNo, DirectionInc( bDirection ) );
if( IS_MERC_BODY_TYPE( pSoldier ) && OKFallDirection( pSoldier, sNewGridNo, pSoldier->pathing.bLevel, gOppositeDirection[ pSoldier->ubDirection ], FLYBACK_HIT ) )
{
pSoldier->ChangeToFallbackAnimation( (UINT8)gOppositeDirection[ bDirection ] );
}
else
{
SoldierCollapse( pSoldier );
}
break;
case ANIM_PRONE:
SoldierCollapse( pSoldier );
break;
}
}
BOOLEAN SOLDIERTYPE::EVENT_InternalGetNewSoldierPath( INT32 sDestGridNo, UINT16 usMovementAnim, BOOLEAN fFromUI, BOOLEAN fForceRestartAnim )
{
@@ -9464,7 +9540,40 @@ void SOLDIERTYPE::BeginSoldierGetup( void )
#endif
if ( this->bCollapsed )
{
if ( this->stats.bLife >= OKLIFE && this->bBreath >= OKBREATH && (this->bSleepDrugCounter == 0) )
// anv: only get up if we're not blocked by anything (like vehicle)
BOOLEAN fEnoughPlace = TRUE;
STRUCTURE_FILE_REF *pStructureFileRef;
if ( IS_MERC_BODY_TYPE( this ) )
{
switch( this->usAnimState )
{
case FALLOFF_FORWARD_STOP:
case PRONE_LAYFROMHIT_STOP:
case STAND_FALLFORWARD_STOP:
pStructureFileRef = GetAnimationStructureRef( this->ubID, DetermineSoldierAnimationSurface( this, ANIM_CROUCH ), ANIM_CROUCH );
break;
case FALLBACKHIT_STOP:
case FALLOFF_STOP:
case FLYBACKHIT_STOP:
case FALLBACK_HIT_STAND:
case FALLOFF:
case FLYBACK_HIT:
pStructureFileRef = GetAnimationStructureRef( this->ubID, DetermineSoldierAnimationSurface( this, ROLLOVER ), ROLLOVER );
break;
default:
pStructureFileRef = GetAnimationStructureRef( this->ubID, DetermineSoldierAnimationSurface( this, ANIM_CROUCH ), ANIM_CROUCH );
break;
}
fEnoughPlace = OkayToAddStructureToWorld( this->sGridNo, this->pathing.bLevel, &( pStructureFileRef->pDBStructureRef[ gOneCDirection[ this->ubDirection ] ] ), this->ubID, FALSE, NOBODY );
}
else
{
pStructureFileRef = GetAnimationStructureRef( this->ubID, DetermineSoldierAnimationSurface( this, END_COWER ), END_COWER );
fEnoughPlace = OkayToAddStructureToWorld( this->sGridNo, this->pathing.bLevel, &( pStructureFileRef->pDBStructureRef[ gOneCDirection[ this->ubDirection ] ] ), this->ubID, FALSE, NOBODY );
}
if ( this->stats.bLife >= OKLIFE && this->bBreath >= OKBREATH && (this->bSleepDrugCounter == 0) && fEnoughPlace )
{
// get up you hoser!
@@ -15747,6 +15856,9 @@ BOOLEAN SOLDIERTYPE::RecognizeAsCombatant(UINT8 ubTargetID)
if (!gGameOptions.fNewTraitSystem)
return TRUE;
if ( ubTargetID == NOBODY )
return TRUE;
SOLDIERTYPE* pSoldier = MercPtrs[ubTargetID];
if ( !pSoldier )
+2
View File
@@ -58,6 +58,7 @@ extern UINT16 CivLastNames[MAXCIVLASTNAMES][10];
#define TAKE_DAMAGE_TENTACLES 9
#define TAKE_DAMAGE_STRUCTURE_EXPLOSION 10
#define TAKE_DAMAGE_OBJECT 11
#define TAKE_DAMAGE_VEHICLE_TRAUMA 12
#define SOLDIER_UNBLIT_SIZE (75*75*2)
@@ -397,6 +398,7 @@ enum
// ------------------- more flags for soldiers --------------------
#define SOLDIER_SNITCHING_OFF 0x00000001 //1 // isn't allowed to snitch
#define SOLDIER_PREVENT_MISBEHAVIOUR_OFF 0x00000002 //2 // isn't allowed to prevent misbehaviour
#define SOLDIER_RAM_THROUGH_OBSTACLES 0x00000004 //4 // vehicle
// ----------------------------------------------------------------
// -------- added by Flugente: background property flags --------
+11
View File
@@ -48,6 +48,7 @@
#include "message.h"
#include "Text.h"
#include "NPC.h"
#include "Soldier macros.h"
#endif
extern INT8 gbNumMercsUntilWaitingOver;
@@ -222,6 +223,16 @@ INT8 TileIsClear( SOLDIERTYPE *pSoldier, INT8 bDirection, INT32 sGridNo, INT8 b
return( MOVE_TILE_CLEAR );
}
// anv: vehicles can ram people
if ( !TANK(pSoldier) && gGameExternalOptions.fAllowCarsDrivingOverPeople && pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE && pSoldier->usSoldierFlagMask2 & SOLDIER_RAM_THROUGH_OBSTACLES )
{
return( MOVE_TILE_CLEAR );
}
else if( TANK(pSoldier) && gGameExternalOptions.fAllowTanksDrivingOverPeople && pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE )
{
return( MOVE_TILE_CLEAR );
}
ubPerson = WhoIsThere2( sGridNo, bLevel );
+1 -1
View File
@@ -451,7 +451,7 @@ void ReevaluateBestSightingPosition( SOLDIERTYPE * pSoldier, INT8 bInterruptDuel
{
for ( ubLoop = 0; ubLoop < gubBestToMakeSightingSize; ubLoop++ )
{
if ( pSoldier->RecognizeAsCombatant(gubBestToMakeSighting[ ubLoop ]) && (gubBestToMakeSighting[ ubLoop ] == NOBODY) || (bInterruptDuelPts > MercPtrs[ gubBestToMakeSighting[ ubLoop ] ]->aiData.bInterruptDuelPts ) )
if ( pSoldier->RecognizeAsCombatant(gubBestToMakeSighting[ ubLoop ]) && (gubBestToMakeSighting[ ubLoop ] == NOBODY) || ( gubBestToMakeSighting[ ubLoop ] != NOBODY && bInterruptDuelPts > MercPtrs[ gubBestToMakeSighting[ ubLoop ] ]->aiData.bInterruptDuelPts ) )
{
if ( gubBestToMakeSighting[ gubBestToMakeSightingSize - 1 ] != NOBODY )
{
+128 -9
View File
@@ -41,6 +41,13 @@
#include "Tile Animation.h"
#include "Explosion Control.h" // added by Flugente
// anv: for ramming people with vehicles
#include "Soldier macros.h"
#include "Overhead.h"
#include "Soldier Functions.h"
#include "Animation Control.h"
#include "Soldier Ani.h"
#endif
#ifdef COUNT_PATHS
@@ -625,7 +632,7 @@ STRUCTURE * CreateStructureFromDB( DB_STRUCTURE_REF * pDBStructureRef, UINT8 ubT
return( pStructure );
}
BOOLEAN OkayToAddStructureToTile( INT32 sBaseGridNo, INT16 sCubeOffset, DB_STRUCTURE_REF * pDBStructureRef, UINT8 ubTileIndex, INT16 sExclusionID, BOOLEAN fIgnorePeople )
BOOLEAN OkayToAddStructureToTile( INT32 sBaseGridNo, INT16 sCubeOffset, DB_STRUCTURE_REF * pDBStructureRef, UINT8 ubTileIndex, INT16 sExclusionID, BOOLEAN fAddingForReal = FALSE, INT16 sSoldierID = NOBODY )
{
// Verifies whether a structure is blocked from being added to the map at a particular point
DB_STRUCTURE * pDBStructure;
@@ -636,6 +643,18 @@ BOOLEAN OkayToAddStructureToTile( INT32 sBaseGridNo, INT16 sCubeOffset, DB_STRUC
INT32 sGridNo;
INT32 sOtherGridNo;
BOOLEAN fIgnorePeople = (BOOLEAN)(sExclusionID == IGNORE_PEOPLE_STRUCTURE_ID);
BOOLEAN fVehicleIgnoreObstacles = (BOOLEAN)(sExclusionID == VEHICLE_IGNORE_OBSTACLES_STRUCTURE_ID);
if( gGameExternalOptions.ubCarsRammingMaxStructureArmour && sSoldierID != NOBODY && MercPtrs[ sSoldierID ]->usSoldierFlagMask2 & SOLDIER_RAM_THROUGH_OBSTACLES )
{
fVehicleIgnoreObstacles = TRUE;
}
else if( gGameExternalOptions.ubTanksRammingMaxStructureArmour && sSoldierID != NOBODY && TANK( MercPtrs[ sSoldierID ] ) )
{
fVehicleIgnoreObstacles = TRUE;
}
ppTile = pDBStructureRef->ppTile;
#if 0//dnl ch83 080114
sGridNo = sBaseGridNo + ppTile[ubTileIndex]->sPosRelToBase;
@@ -666,7 +685,7 @@ BOOLEAN OkayToAddStructureToTile( INT32 sBaseGridNo, INT16 sCubeOffset, DB_STRUC
while (pExistingStructure != NULL)
{
if (sCubeOffset == pExistingStructure->sCubeOffset)
if (pExistingStructure != NULL && sCubeOffset == pExistingStructure->sCubeOffset)
{
// CJC:
@@ -708,6 +727,70 @@ BOOLEAN OkayToAddStructureToTile( INT32 sBaseGridNo, INT16 sCubeOffset, DB_STRUC
}
}
if ( fVehicleIgnoreObstacles && !(pExistingStructure->fFlags & STRUCTURE_PASSABLE) && !(ppTile[ubTileIndex]->fFlags & TILE_PASSABLE) )
{
// anv: drive through people
if ( pExistingStructure->usStructureID < TOTAL_SOLDIERS )
{
SOLDIERTYPE *pSoldier = MercPtrs[ pExistingStructure->usStructureID ];
// but not monsters and such (they can't fall down due to lack of animations)
// also make sure AI won't flatten their allies
if( !( pSoldier->flags.uiStatusFlags & ( SOLDIER_VEHICLE | SOLDIER_ROBOT | SOLDIER_MONSTER ) ) &&
( ( !TANK(MercPtrs[ sSoldierID ]) && gGameExternalOptions.fAllowCarsDrivingOverPeople ) ||
( TANK(MercPtrs[ sSoldierID ]) && gGameExternalOptions.fAllowTanksDrivingOverPeople ) ) &&
( MercPtrs[ sSoldierID ]->bTeam == gbPlayerNum || MercPtrs[ sSoldierID ]->bTeam != pSoldier->bTeam ) )
{
pExistingStructure = pExistingStructure->pNext;
// damage people when driving on them
if( fAddingForReal && ( MercPtrs[ sSoldierID ]->flags.fPastXDest || MercPtrs[ sSoldierID ]->flags.fPastYDest ) )
{
if( TANK( MercPtrs[ sSoldierID ] ) )
{
pSoldier->EVENT_SoldierGotHit( 0, Random(10)+5, Random(200)+Random(200), MercPtrs[ sSoldierID ]->ubDirection, 0, sSoldierID, FIRE_WEAPON_VEHICLE_TRAUMA, 0, 0, pSoldier->sGridNo );
}
else if( gAnimControl[ pSoldier->usAnimState ].ubEndHeight == ANIM_PRONE && MercPtrs[ sSoldierID ]->flags.fUIMovementFast )
{
pSoldier->EVENT_SoldierGotHit( 0, Random(5), Random(100)+Random(100), MercPtrs[ sSoldierID ]->ubDirection, 0, sSoldierID, FIRE_WEAPON_VEHICLE_TRAUMA, 0, 0, pSoldier->sGridNo );
}
else
{
pSoldier->EVENT_SoldierGotHit( 0, Random(10)+5, Random(200)+Random(200), MercPtrs[ sSoldierID ]->ubDirection, 0, sSoldierID, FIRE_WEAPON_VEHICLE_TRAUMA, 0, 0, pSoldier->sGridNo );
}
}
continue;
}
// skip if it's part of the same vehicle
else if( pExistingStructure->usStructureID == sSoldierID )
{
pExistingStructure = pExistingStructure->pNext;
continue;
}
}
// anv: ram and destroy structures
else
{
// only if structure is weak enough
if( ( !TANK(MercPtrs[ sSoldierID ]) && gubMaterialArmour[ pExistingStructure->pDBStructureRef->pDBStructure->ubArmour ] < gGameExternalOptions.ubCarsRammingMaxStructureArmour ) ||
( TANK(MercPtrs[ sSoldierID ]) && gubMaterialArmour[ pExistingStructure->pDBStructureRef->pDBStructure->ubArmour ] < gGameExternalOptions.ubTanksRammingMaxStructureArmour ) )
{
// when not just plotting path, really destroy structure
if( fAddingForReal )
{
INT16 sXPos, sYPos = 0;
ConvertGridNoToXY(pExistingStructure->sGridNo, &sXPos, &sYPos);
DamageStructure( pExistingStructure, 255, STRUCTURE_DAMAGE_VEHICLE_TRAUMA, pExistingStructure->sGridNo, sXPos, sYPos, sSoldierID, 0 );
return( TRUE );
}
// else just skip
else
{
pExistingStructure = pExistingStructure->pNext;
continue;
}
}
}
}
// two obstacle structures aren't allowed in the same tile at the same height
// ATE: There is more sophisticated logic for mobiles, so postpone this check if mobile....
if ( ( pExistingStructure->fFlags & STRUCTURE_OBSTACLE ) && !( pDBStructure->fFlags & STRUCTURE_MOBILE ) )
@@ -830,6 +913,18 @@ BOOLEAN OkayToAddStructureToTile( INT32 sBaseGridNo, INT16 sCubeOffset, DB_STRUC
// ATE: Added check here - UNLESS the part we are trying to add is PASSABLE!
if ( pExistingStructure->fFlags & STRUCTURE_MOBILE && !(pExistingStructure->fFlags & STRUCTURE_PASSABLE) && !(ppTile[ubTileIndex]->fFlags & TILE_PASSABLE) )
{
// anv: check if we try to add soldier hit by a vehicle under vehicle
if( sSoldierID != NOBODY && pExistingStructure->usStructureID < TOTAL_SOLDIERS )
{
if( MercPtrs[ pExistingStructure->usStructureID ] != NULL && MercPtrs[ pExistingStructure->usStructureID ]->flags.uiStatusFlags & SOLDIER_VEHICLE )
{
if( MercPtrs[ sSoldierID ]->flags.fInNonintAnim == TRUE || gAnimControl[ MercPtrs[ sSoldierID ]->usAnimState ].ubEndHeight == ANIM_PRONE )
{
pExistingStructure = pExistingStructure->pNext;
continue;
}
}
}
// don't allow 2 people in the same tile
return( FALSE );
}
@@ -840,7 +935,7 @@ BOOLEAN OkayToAddStructureToTile( INT32 sBaseGridNo, INT16 sCubeOffset, DB_STRUC
// Skip!
pExistingStructure = pExistingStructure->pNext;
continue;
}
}
// ATE: Added here - UNLESS this part is PASSABLE....
// two obstacle structures aren't allowed in the same tile at the same height
@@ -868,7 +963,7 @@ BOOLEAN OkayToAddStructureToTile( INT32 sBaseGridNo, INT16 sCubeOffset, DB_STRUC
return( TRUE );
}
BOOLEAN InternalOkayToAddStructureToWorld( INT32 sBaseGridNo, INT8 bLevel, DB_STRUCTURE_REF * pDBStructureRef, INT16 sExclusionID, BOOLEAN fIgnorePeople )
BOOLEAN InternalOkayToAddStructureToWorld( INT32 sBaseGridNo, INT8 bLevel, DB_STRUCTURE_REF * pDBStructureRef, INT16 sExclusionID, BOOLEAN fAddingForReal, INT16 sSoldierID )
{
UINT8 ubLoop;
INT16 sCubeOffset;
@@ -903,7 +998,7 @@ BOOLEAN InternalOkayToAddStructureToWorld( INT32 sBaseGridNo, INT8 bLevel, DB_ST
{
sCubeOffset = bLevel * PROFILE_Z_SIZE;
}
if (!OkayToAddStructureToTile( sBaseGridNo, sCubeOffset, pDBStructureRef, ubLoop, sExclusionID, fIgnorePeople ))
if (!OkayToAddStructureToTile( sBaseGridNo, sCubeOffset, pDBStructureRef, ubLoop, sExclusionID, fAddingForReal, sSoldierID ))
{
return( FALSE );
}
@@ -911,9 +1006,9 @@ BOOLEAN InternalOkayToAddStructureToWorld( INT32 sBaseGridNo, INT8 bLevel, DB_ST
return( TRUE );
}
BOOLEAN OkayToAddStructureToWorld( INT32 sBaseGridNo, INT8 bLevel, DB_STRUCTURE_REF * pDBStructureRef, INT16 sExclusionID )
BOOLEAN OkayToAddStructureToWorld( INT32 sBaseGridNo, INT8 bLevel, DB_STRUCTURE_REF * pDBStructureRef, INT16 sExclusionID, BOOLEAN fAddingForReal, INT16 sSoldierID )
{
return( InternalOkayToAddStructureToWorld( sBaseGridNo, bLevel, pDBStructureRef, sExclusionID, (BOOLEAN)(sExclusionID == IGNORE_PEOPLE_STRUCTURE_ID) ) );
return( InternalOkayToAddStructureToWorld( sBaseGridNo, bLevel, pDBStructureRef, sExclusionID, fAddingForReal, sSoldierID ) );
}
BOOLEAN AddStructureToTile( MAP_ELEMENT * pMapElement, STRUCTURE * pStructure, UINT16 usStructureID )
@@ -968,7 +1063,14 @@ STRUCTURE * InternalAddStructureToWorld( INT32 sBaseGridNo, INT8 bLevel, DB_STRU
CHECKF( pDBStructure->ubNumberOfTiles > 0 );
// first check to see if the structure will be blocked
if (!OkayToAddStructureToWorld( sBaseGridNo, bLevel, pDBStructureRef, INVALID_STRUCTURE_ID ) )
if ( ( pLevelNode->uiFlags & LEVELNODE_SOLDIER ) && pLevelNode->pSoldier )
{
if ( !OkayToAddStructureToWorld( sBaseGridNo, bLevel, pDBStructureRef, INVALID_STRUCTURE_ID, TRUE, pLevelNode->pSoldier->ubID ) )
{
return( NULL );
}
}
else if ( !OkayToAddStructureToWorld( sBaseGridNo, bLevel, pDBStructureRef, INVALID_STRUCTURE_ID ) )
{
return( NULL );
}
@@ -1724,7 +1826,7 @@ BOOLEAN DamageStructure( STRUCTURE * pStructure, UINT8 ubDamage, UINT8 ubReason,
}
// OK, Let's check our reason
if ( ubReason == STRUCTURE_DAMAGE_GUNFIRE )
if ( ubReason == STRUCTURE_DAMAGE_GUNFIRE || ubReason == STRUCTURE_DAMAGE_VEHICLE_TRAUMA )
{
// If here, we have penetrated, check flags
// Are we an explodable structure?
@@ -1783,6 +1885,23 @@ BOOLEAN DamageStructure( STRUCTURE * pStructure, UINT8 ubDamage, UINT8 ubReason,
gpWorldLevelData[ sGridNo ].uiFlags |= MAPELEMENT_STRUCTURE_DAMAGED;
}
// anv: if we ram something with vehicle we have to destroy it, or else vehicle and structure will be drawn at the same tile
// max armour will be set by Player in .ini and checked before DamageStructure is called
if ( ubReason == STRUCTURE_DAMAGE_VEHICLE_TRAUMA )
{
BOOLEAN recompile = FALSE;
ExplosiveDamageGridNo( sGridNo, 255, 10, &recompile, FALSE, -1, FALSE, ubOwner, 0 );
//Since the structure is being damaged, set the map element that a structure is damaged
gpWorldLevelData[ sGridNo ].uiFlags |= MAPELEMENT_STRUCTURE_DAMAGED;
// handle structure revenge - damage to vehicle
if( ubOwner != NOBODY )
{
MercPtrs[ ubOwner ]->SoldierTakeDamage( 0, Random(max(0,(ubBaseArmour-10)/5))+max(0,(ubBaseArmour-10)/5), 0, 0, TAKE_DAMAGE_STRUCTURE_EXPLOSION, NOBODY, MercPtrs[ ubOwner ]->sGridNo, 0, TRUE );
}
}
// Don't update damage HPs....
return TRUE;
}
+3 -1
View File
@@ -21,9 +21,11 @@
// 100 == MAX_CORPSES
#define INVALID_STRUCTURE_ID ( TOTAL_SOLDIERS + 100 )
#define IGNORE_PEOPLE_STRUCTURE_ID (TOTAL_SOLDIERS+101)
#define VEHICLE_IGNORE_OBSTACLES_STRUCTURE_ID (TOTAL_SOLDIERS+102)
#define STRUCTURE_DAMAGE_EXPLOSION 1
#define STRUCTURE_DAMAGE_GUNFIRE 2
#define STRUCTURE_DAMAGE_VEHICLE_TRAUMA 3
// functions at the structure database level
@@ -35,7 +37,7 @@ BOOLEAN FreeStructureFile( STRUCTURE_FILE_REF * pStructureFile );
//
// functions at the structure instance level
//
BOOLEAN OkayToAddStructureToWorld( INT32 sBaseGridNo, INT8 bLevel, DB_STRUCTURE_REF * pDBStructureRef, INT16 sExclusionID );
BOOLEAN OkayToAddStructureToWorld( INT32 sBaseGridNo, INT8 bLevel, DB_STRUCTURE_REF * pDBStructureRef, INT16 sExclusionID, BOOLEAN fAddingForReal = FALSE, INT16 sSoldierID = NOBODY );
// for the PTR argument of AddStructureToWorld, pass in a LEVELNODE * please!
BOOLEAN AddStructureToWorld( INT32 sBaseGridNo, INT8 bLevel, DB_STRUCTURE_REF * pDBStructureRef, PTR pLevelN );
+6
View File
@@ -428,6 +428,9 @@ BOOLEAN RemoveAllObjectsOfTypeRange( INT32 iMapIndex, UINT32 fStartType, UINT32
UINT32 fTileType;
BOOLEAN fRetVal = FALSE;
if( iMapIndex < 0 )
return fRetVal;
pObject = gpWorldLevelData[ iMapIndex ].pObjectHead;
// Look through all objects and Search for type
@@ -2996,6 +2999,9 @@ BOOLEAN RemoveAllOnRoofsOfTypeRange( INT32 iMapIndex, UINT32 fStartType, UINT32
UINT32 fTileType;
BOOLEAN fRetVal = FALSE;
if( iMapIndex < 0 )
return fRetVal;
pOnRoof = gpWorldLevelData[ iMapIndex ].pOnRoofHead;
// Look through all OnRoofs and Search for type