Skip to content

Commit a423b0e

Browse files
committed
ship stuff
1 parent 6ba2e60 commit a423b0e

5 files changed

Lines changed: 45 additions & 20 deletions

File tree

GeneralsMD/Code/GameEngine/Include/Common/GlobalData.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -587,7 +587,7 @@ class GlobalData : public SubsystemInterface
587587
//AudioEventRTS m_chronoDisableSoundLoop;
588588

589589
DeathTypeFlags m_defaultExcludedDeathTypes;
590-
590+
Bool m_heightAboveTerrainIncludesWater;
591591

592592
// the trailing '\' is included!
593593
const AsciiString &getPath_UserData() const { return m_userDataDir; }

GeneralsMD/Code/GameEngine/Include/GameLogic/Weapon.h

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -401,21 +401,21 @@ class WeaponTemplate : public MemoryPoolObject
401401
{
402402
friend class WeaponStore;
403403

404-
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( WeaponTemplate, "WeaponTemplate" )
404+
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(WeaponTemplate, "WeaponTemplate")
405405

406406
public:
407407

408408
WeaponTemplate();
409409
// virtual destructor declared by memory pool
410410

411-
void reset( void );
411+
void reset(void);
412412

413-
void friend_setNextTemplate(WeaponTemplate *nextTemplate) { m_nextTemplate = nextTemplate; }
414-
WeaponTemplate *friend_clearNextTemplate( void ) { WeaponTemplate *ret = m_nextTemplate; m_nextTemplate = NULL; return ret; }
415-
Bool isOverride( void ) { return m_nextTemplate != NULL; }
413+
void friend_setNextTemplate(WeaponTemplate* nextTemplate) { m_nextTemplate = nextTemplate; }
414+
WeaponTemplate* friend_clearNextTemplate(void) { WeaponTemplate* ret = m_nextTemplate; m_nextTemplate = NULL; return ret; }
415+
Bool isOverride(void) { return m_nextTemplate != NULL; }
416416

417417
/// field table for loading the values from an INI
418-
const FieldParse *getFieldParse() const { return TheWeaponTemplateFieldParseTable; }
418+
const FieldParse* getFieldParse() const { return TheWeaponTemplateFieldParseTable; }
419419

420420
/**
421421
fire the weapon. return the logic-frame in which the damage will be dealt.
@@ -427,15 +427,15 @@ class WeaponTemplate : public MemoryPoolObject
427427
*/
428428
UnsignedInt fireWeaponTemplate
429429
(
430-
const Object *sourceObj,
430+
const Object* sourceObj,
431431
WeaponSlotType wslot,
432432
Int specificBarrelToUse,
433-
Object *victimObj,
433+
Object* victimObj,
434434
const Coord3D* victimPos,
435435
const WeaponBonus& bonus,
436436
Bool isProjectileDetonation,
437437
Bool ignoreRanges,
438-
Weapon *firingWeapon,
438+
Weapon* firingWeapon,
439439
ObjectID* projectileID,
440440
Bool inflictDamage
441441
) const;
@@ -447,8 +447,8 @@ class WeaponTemplate : public MemoryPoolObject
447447
take weapon range into account -- it ASSUMES that the victim is within range!
448448
*/
449449
Real estimateWeaponTemplateDamage(
450-
const Object *sourceObj,
451-
const Object *victimObj,
450+
const Object* sourceObj,
451+
const Object* victimObj,
452452
const Coord3D* victimPos,
453453
const WeaponBonus& bonus
454454
) const;
@@ -469,7 +469,7 @@ class WeaponTemplate : public MemoryPoolObject
469469
Real getShockWaveRadius() const { return m_shockWaveRadius; }
470470
Real getShockWaveTaperOff() const { return m_shockWaveTaperOff; }
471471

472-
Real getRequestAssistRange() const {return m_requestAssistRange;}
472+
Real getRequestAssistRange() const { return m_requestAssistRange; }
473473
AsciiString getName() const { return m_name; }
474474
AsciiString getProjectileStreamName() const { return m_projectileStreamName; }
475475
AsciiString getLaserName() const { return m_laserName; }
@@ -501,7 +501,7 @@ class WeaponTemplate : public MemoryPoolObject
501501
Int getContinuousFireOneShotsNeeded() const { return m_continuousFireOneShotsNeeded; }
502502
Int getContinuousFireTwoShotsNeeded() const { return m_continuousFireTwoShotsNeeded; }
503503
UnsignedInt getContinuousFireCoastFrames() const { return m_continuousFireCoastFrames; }
504-
UnsignedInt getAutoReloadWhenIdleFrames() const { return m_autoReloadWhenIdleFrames; }
504+
UnsignedInt getAutoReloadWhenIdleFrames() const { return m_autoReloadWhenIdleFrames; }
505505
UnsignedInt getSuspendFXDelay() const { return m_suspendFXDelay; }
506506

507507
const FXList* getFireFX(VeterancyLevel v) const { return m_fireFXs[v]; }
@@ -532,8 +532,9 @@ class WeaponTemplate : public MemoryPoolObject
532532
Bool isScatterTargetAligned() const { return m_scatterTargetAligned; }
533533
Bool isScatterTargetRandom() const { return m_scatterTargetRandom; }
534534
Bool isScatterTargetRandomAngle() const { return m_scatterTargetRandomAngle; }
535-
Real getScatterTargetMinScalar () const { return m_scatterTargetMinScalar; }
535+
Real getScatterTargetMinScalar() const { return m_scatterTargetMinScalar; }
536536
Bool isScatterTargetCenteredAtShooter() const { return m_scatterTargetCenteredAtShooter; }
537+
Bool isScatterOnWaterSurface() const { return m_scatterOnWaterSurface; }
537538

538539
Bool shouldProjectileCollideWith(
539540
const Object* projectileLauncher,
@@ -661,6 +662,8 @@ class WeaponTemplate : public MemoryPoolObject
661662
UnsignedInt m_scatterTargetResetTime; ///< if this much time between shots has passed, we reset the scatter targets
662663
Bool m_scatterTargetResetRecenter; ///< when resetting scatter targets, use indices in the "middle" of the list, to keep the target centered for Line based attacks
663664

665+
Bool m_scatterOnWaterSurface; ///< Scatter radius and targets include the water surface instead of just the terrain height
666+
664667
mutable HistoricWeaponDamageList m_historicDamage;
665668
mutable UnsignedInt m_historicDamageTriggerId;
666669
};

GeneralsMD/Code/GameEngine/Source/Common/GlobalData.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -573,7 +573,7 @@ GlobalData* GlobalData::m_theOriginal = NULL;
573573
{"ChronoDamageParticleSystemSmall", INI::parseAsciiString, NULL, offsetof(GlobalData, m_chronoDisableParticleSystemSmall) },
574574

575575
{"DefaultExcludedDeathTypes", INI::parseDeathTypeFlagsList, NULL, offsetof(GlobalData, m_defaultExcludedDeathTypes) },
576-
576+
{"HeightAboveTerrainIncludesWater", INI::parseBool, NULL, offsetof(GlobalData, m_heightAboveTerrainIncludesWater) },
577577
{ NULL, NULL, NULL, 0 } // keep this last
578578

579579
};
@@ -1160,6 +1160,8 @@ GlobalData::GlobalData()
11601160
m_chronoDisableParticleSystemSmall.clear();
11611161
// m_chronoTintStatusType = TINT_STATUS_INVALID;
11621162

1163+
m_heightAboveTerrainIncludesWater = false;
1164+
11631165
} // end GlobalData
11641166

11651167

GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2355,8 +2355,10 @@ UpdateSleepTime AIUpdateInterface::doLocomotor( void )
23552355
}
23562356

23572357
// After our movement for the frame, update our AirborneTarget flag.
2358-
if(getObject()->getHeightAboveTerrain() > m_curLocomotor->getAirborneTargetingHeight() )
2358+
if(TheGlobalData->m_heightAboveTerrainIncludesWater && getObject()->getHeightAboveTerrainOrWater() > m_curLocomotor->getAirborneTargetingHeight() )
23592359
getObject()->setStatus( MAKE_OBJECT_STATUS_MASK( OBJECT_STATUS_AIRBORNE_TARGET ) );
2360+
else if (!TheGlobalData->m_heightAboveTerrainIncludesWater && getObject()->getHeightAboveTerrain() > m_curLocomotor->getAirborneTargetingHeight())
2361+
getObject()->setStatus(MAKE_OBJECT_STATUS_MASK(OBJECT_STATUS_AIRBORNE_TARGET));
23602362
else
23612363
getObject()->clearStatus( MAKE_OBJECT_STATUS_MASK( OBJECT_STATUS_AIRBORNE_TARGET ) );
23622364

GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,7 @@ const FieldParse WeaponTemplate::TheWeaponTemplateFieldParseTable[] =
252252
{ "ContinuousLaserLoopTime", INI::parseDurationUnsignedInt, NULL, offsetof(WeaponTemplate, m_continuousLaserLoopTime) },
253253
{ "LaserGroundTargetHeight", INI::parseReal, NULL, offsetof(WeaponTemplate, m_laserGroundTargetHeight) },
254254
{ "LaserGroundUnitTargetHeight", INI::parseReal, NULL, offsetof(WeaponTemplate, m_laserGroundUnitTargetHeight) },
255+
{ "ScatterOnWaterSurface", INI::parseBool, NULL, offsetof(WeaponTemplate, m_scatterOnWaterSurface) },
255256
{ NULL, NULL, NULL, 0 } // keep this last
256257

257258
};
@@ -345,7 +346,7 @@ WeaponTemplate::WeaponTemplate() : m_nextTemplate(NULL)
345346
m_scatterTargetResetTime = 0;
346347
m_preAttackFXDelay = 6; // Non-Zero default! 6 frames = 200ms. This should be a good base value to avoid spamming
347348
m_laserGroundUnitTargetHeight = 10; // Default Height offset
348-
349+
m_scatterOnWaterSurface = false;
349350
m_historicDamageTriggerId = 0;
350351
}
351352

@@ -1025,7 +1026,16 @@ UnsignedInt WeaponTemplate::fireWeaponTemplate
10251026
//If we aim for the center point of our target and miss, the shot will go much farther than
10261027
//we expect!
10271028
// srj sez: we should actually fire at the layer the victim is on, if possible, in case it is on a bridge...
1028-
projectileDestination.z = TheTerrainLogic->getLayerHeight( projectileDestination.x, projectileDestination.y, targetLayer );
1029+
1030+
if (targetLayer == LAYER_GROUND && firingWeapon->getTemplate()->isScatterOnWaterSurface()) {
1031+
Real waterZ;
1032+
Real terrainZ;
1033+
TheTerrainLogic->isUnderwater(projectileDestination.x, projectileDestination.y, &waterZ, &terrainZ);
1034+
projectileDestination.z = std::max(waterZ, terrainZ);
1035+
}
1036+
else {
1037+
projectileDestination.z = TheTerrainLogic->getLayerHeight(projectileDestination.x, projectileDestination.y, targetLayer);
1038+
}
10291039
}
10301040

10311041
if (getProjectileTemplate() == NULL || isProjectileDetonation)
@@ -2979,7 +2989,15 @@ Bool Weapon::privateFireWeapon(
29792989
targetPos.x += scatterOffset.x;
29802990
targetPos.y += scatterOffset.y;
29812991

2982-
targetPos.z = TheTerrainLogic->getGroundHeight(targetPos.x, targetPos.y);
2992+
if (m_template->isScatterOnWaterSurface()) {
2993+
Real waterZ;
2994+
Real terrainZ;
2995+
TheTerrainLogic->isUnderwater(targetPos.x, targetPos.y, &waterZ, &terrainZ);
2996+
targetPos.z = std::max(waterZ, terrainZ);
2997+
}
2998+
else {
2999+
targetPos.z = TheTerrainLogic->getGroundHeight(targetPos.x, targetPos.y);
3000+
}
29833001

29843002
// Note AW: We have to ignore Ranges when using ScatterTargets, or else the weapon can fail in the next stage
29853003
ignoreRanges = TRUE;

0 commit comments

Comments
 (0)