Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2319,6 +2319,16 @@ void W3DView::screenToTerrain( const ICoord2D *screen, Coord3D *world )
intersection = bridgePt;
}

//Check for water height in this area, create a dummy plane around the point
if (TheGlobalData->m_heightAboveTerrainIncludesWater) {
Vector3 outPos{ 0,0,0 };
if (TheTerrainLogic->pickWaterPlane(rayStart, rayEnd, intersection, outPos)) {
if (outPos.Z > intersection.Z) {
intersection = outPos;
}
}
}

world->x = intersection.X;
world->y = intersection.Y;
world->z = intersection.Z;
Expand Down
3 changes: 3 additions & 0 deletions GeneralsMD/Code/GameEngine/Include/GameLogic/Damage.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,11 @@ enum DamageType CPP_11(: Int)
DAMAGE_SEISMIC,
DAMAGE_RAD_BEAM,
DAMAGE_TESLA,
DAMAGE_JET_TORPEDO,
DAMAGE_ANTI_SHIP,

// Specific damage types with special logic attached
DAMAGE_TORPEDO, ///< can only attack units over water
DAMAGE_CHRONO_GUN, ///< Disable target and remove them once health threshold is reached
DAMAGE_CHRONO_UNRESISTABLE, ///< Used for recovery from CHRONO_GUN
// DAMAGE_ZOMBIE_VIRUS, // TODO
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ class MissileAIUpdateModuleData : public AIUpdateModuleData

Bool m_applyLauncherBonus; ///< Apply the launcher's weapon bonus flags (for any non-detonate triggered weapon)

Bool m_isTorpedo; ///< die outside of water, strike objects from below.

MissileAIUpdateModuleData();

static void buildFieldParse(MultiIniFieldParse& p);
Expand Down
3 changes: 3 additions & 0 deletions GeneralsMD/Code/GameEngine/Include/GameLogic/TerrainLogic.h
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,9 @@ class TerrainLogic : public Snapshot,

virtual Drawable *pickBridge(const Vector3 &from, const Vector3 &to, Vector3 *pos);

// get water around a world point
virtual bool pickWaterPlane(const Vector3 &from, const Vector3 &to, const Vector3 &aroundPos, Vector3 &outPos);

virtual void addBridgeToLogic(BridgeInfo *pInfo, Dict *props, AsciiString bridgeTemplateName); ///< Adds a bridge's logical info.
virtual void addLandmarkBridgeToLogic(Object *bridgeObj); ///< Adds a bridge's logical info.
virtual void deleteBridge( Bridge *bridge ); ///< remove a bridge
Expand Down
8 changes: 8 additions & 0 deletions GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIGroup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,14 @@ void AIGroup::computeIndividualDestination( Coord3D *dest, const Coord3D *groupD
dest->x = groupDest->x + v.x;
dest->y = groupDest->y + v.y;
dest->z = TheTerrainLogic->getLayerHeight( dest->x, dest->y, layer );

if (TheGlobalData->m_heightAboveTerrainIncludesWater) {
// Put waypoints on water surface instead of ground
if (Real waterZ = 0; TheTerrainLogic->isUnderwater(dest->x, dest->y, &waterZ)) {
if (waterZ > dest->z) dest->z = waterZ;
}
}

AIUpdateInterface *ai = obj->getAIUpdateInterface();
if (ai && ai->isDoingGroundMovement()) {
if (isFormation) {
Expand Down
7 changes: 7 additions & 0 deletions GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIPathfind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8894,6 +8894,13 @@ void Pathfinder::adjustCoordToCell(Int cellX, Int cellY, Bool centerInCell, Coor
pos.y = ((Real)cellY+0.05) * PATHFIND_CELL_SIZE_F;
}
pos.z = TheTerrainLogic->getLayerHeight( pos.x, pos.y, layer );

if (TheGlobalData->m_heightAboveTerrainIncludesWater) {
//Adjust to water surface
if (Real waterZ = 0; TheTerrainLogic->isUnderwater(pos.x, pos.y, &waterZ)) {
if (waterZ > pos.z) pos.z = waterZ;
}
}
}


Expand Down
28 changes: 28 additions & 0 deletions GeneralsMD/Code/GameEngine/Source/GameLogic/Map/TerrainLogic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1975,6 +1975,34 @@ Drawable *TerrainLogic::pickBridge(const Vector3 &from, const Vector3 &to, Vecto
return(curDraw);
}

bool TerrainLogic::pickWaterPlane(const Vector3& from, const Vector3& to, const Vector3& aroundPos, Vector3 &outPos) {
Real waterZ{ 0 };
if (isUnderwater(aroundPos.X, aroundPos.Y, &waterZ)) {
Vector3 normal(0, 0, 1.0f);
Vector3 point(aroundPos.X, aroundPos.Y, waterZ);

PlaneClass plane(normal, point);

Real t;
plane.Compute_Intersection(from, to, &t);
Vector3 intersectPos;
intersectPos = from + (to - from) * t;

outPos.X = intersectPos.X;
outPos.Y = intersectPos.Y;
outPos.Z = intersectPos.Z;

return true;
}
else {
outPos.X = 0;
outPos.Y = 0;
outPos.Z = 0;
return false;
}
}


//-------------------------------------------------------------------------------------------------
/** Deletes the bridges list. */
//-------------------------------------------------------------------------------------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ void MissileAIUpdateModuleData::buildFieldParse(MultiIniFieldParse& p)
{ "KillSelfDelay", INI::parseDurationUnsignedInt, NULL, offsetof( MissileAIUpdateModuleData, m_killSelfDelay ) },
{ "ZCorrectionFactor", INI::parseReal, NULL, offsetof(MissileAIUpdateModuleData, m_zDirFactor) },
{ "ApplyLauncherBonus", INI::parseBool, NULL, offsetof(MissileAIUpdateModuleData, m_applyLauncherBonus) },
{ "IsTorpedo", INI::parseBool, NULL, offsetof(MissileAIUpdateModuleData, m_isTorpedo) },
{ 0, 0, 0, 0 }
};

Expand Down Expand Up @@ -633,7 +634,7 @@ void MissileAIUpdate::doAttackState(Bool turnOK, Bool randomPath)
}
}

if(curLoco && curLoco->getPreferredHeight() > 0)
if(curLoco && (curLoco->getPreferredHeight() > 0 || curLoco->getPreferredHeight() < 0) )
{
// Am I close enough to the target to ignore my preferred height setting?
Real distanceToTargetSquared = ThePartitionManager->getDistanceSquared( getObject(), getGoalPosition(), FROM_CENTER_2D );
Expand Down Expand Up @@ -840,6 +841,13 @@ UpdateSleepTime MissileAIUpdate::update()
TheGameLogic->destroyObject(getObject());
return UPDATE_SLEEP_FOREVER;
}

// If treated as torpedo, explode when not over water
const MissileAIUpdateModuleData* d = getMissileAIUpdateModuleData();
if (d->m_isTorpedo && !getObject()->isOverWater()) {
detonate();
}

switch( m_state )
{
case PRELAUNCH:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,12 @@ void DefaultProductionExitUpdate::exitObjectViaDoor( Object *newObj, ExitDoorTyp
// make sure the point is on the terrain
loc.Z = TheTerrainLogic ? TheTerrainLogic->getLayerHeight( loc.X, loc.Y, creationObject->getLayer() ) : 0.0f;

// If underwater use water height, fixes shipyards spawning ships under water
if (Real waterZ = 0; TheTerrainLogic && TheTerrainLogic->isUnderwater(loc.X, loc.Y, &waterZ)) {
if (waterZ > loc.Z) loc.Z = waterZ;
}


// we need it in Coord3D form
createPoint.x = loc.X;
createPoint.y = loc.Y;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -838,6 +838,11 @@ CanAttackResult WeaponSet::getAbleToUseWeaponAgainstTarget( AbleToAttackType att
continue;
}

// Torpedoes cannot attack units not above water
if (weapon->getDamageType() == DAMAGE_TORPEDO && !victim->isOverWater()) {
continue;
}

return okResult;
}
}
Expand Down
3 changes: 3 additions & 0 deletions GeneralsMD/Code/GameEngine/Source/GameLogic/System/Damage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,10 @@ const char* const DamageTypeFlags::s_bitNameList[] =
"SEISMIC",
"RAD_BEAM",
"TESLA",
"JET_TORPEDO",
"ANTI_SHIP",
// Specific damage types with special logic attached
"TORPEDO",
"CHRONO_GUN",
"CHRONO_UNRESISTABLE",
//"ZOMBIE_VIRUS", // TODO
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,16 +148,24 @@ static void doSetRallyPoint( Object *obj, const Coord3D& pos )
// tells me how to get the locomotor sets based on a thing template (CBD)
//
NameKeyType key;
Coord3D rallyPointPos = pos;
if (obj->isKindOf(KINDOF_SHIPYARD)) {
key = NAMEKEY("BasicBoatLocomotor");

//Shift pos up to water height
Real waterZ;
if (TheTerrainLogic->isUnderwater(rallyPointPos.x, rallyPointPos.y, &waterZ)) {
rallyPointPos.z = waterZ;
}

}
else {
key = NAMEKEY("BasicHumanLocomotor");
}

LocomotorSet locomotorSet;
locomotorSet.addLocomotor( TheLocomotorStore->findLocomotorTemplate( key ) );
if( TheAI->pathfinder()->clientSafeQuickDoesPathExist( locomotorSet, obj->getPosition(), &pos ) == FALSE )
if( TheAI->pathfinder()->clientSafeQuickDoesPathExist( locomotorSet, obj->getPosition(), &rallyPointPos) == FALSE )
{

// user feedback
Expand All @@ -169,7 +177,7 @@ static void doSetRallyPoint( Object *obj, const Coord3D& pos )

// play the no can do sound
static AudioEventRTS rallyNotSet("UnableToSetRallyPoint");
rallyNotSet.setPosition(&pos);
rallyNotSet.setPosition(&rallyPointPos);
rallyNotSet.setPlayerIndex(obj->getControllingPlayer()->getPlayerIndex());
TheAudio->addAudioEvent(&rallyNotSet);

Expand All @@ -191,7 +199,7 @@ static void doSetRallyPoint( Object *obj, const Coord3D& pos )

// play a sound for setting the rally point
static AudioEventRTS rallyPointSet("RallyPointSet");
rallyPointSet.setPosition(&pos);
rallyPointSet.setPosition(&rallyPointPos);
rallyPointSet.setPlayerIndex(obj->getControllingPlayer()->getPlayerIndex());
TheAudio->addAudioEvent(&rallyPointSet);

Expand All @@ -207,7 +215,7 @@ static void doSetRallyPoint( Object *obj, const Coord3D& pos )
if( exitInterface )
{
// set the rally point
exitInterface->setRallyPoint( &pos );
exitInterface->setRallyPoint( &rallyPointPos);

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1039,6 +1039,13 @@ void W3DProjectedShadowManager::queueDecal(W3DProjectedShadow *shadow)
{
hmapVertex.X=(float)(i-borderSize)*MAP_XY_FACTOR;
hmapVertex.Z=__max((float)hmap->getHeight(i,j)*MAP_HEIGHT_SCALE,layerHeight);

if (TheGlobalData->m_heightAboveTerrainIncludesWater) {
if (Real waterZ = 0; TheTerrainLogic->isUnderwater(hmapVertex.X, hmapVertex.Y, &waterZ)) {
if (waterZ > hmapVertex.Z) hmapVertex.Z = waterZ;
}
}

pvVertices->x=hmapVertex.X;
pvVertices->y=hmapVertex.Y;
pvVertices->z=hmapVertex.Z;
Expand All @@ -1058,6 +1065,13 @@ void W3DProjectedShadowManager::queueDecal(W3DProjectedShadow *shadow)
{
hmapVertex.X=(float)(i-borderSize)*MAP_XY_FACTOR;
hmapVertex.Z=(float)hmap->getHeight(i,j)*MAP_HEIGHT_SCALE+0.01f * MAP_XY_FACTOR;

if (TheGlobalData->m_heightAboveTerrainIncludesWater) {
if (Real waterZ = 0; TheTerrainLogic->isUnderwater(hmapVertex.X, hmapVertex.Y, &waterZ)) {
if (waterZ > hmapVertex.Z) hmapVertex.Z = waterZ;
}
}

pvVertices->x=hmapVertex.X;
pvVertices->y=hmapVertex.Y;
pvVertices->z=hmapVertex.Z;
Expand Down