diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/CrateSystem.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/CrateSystem.h index 01c694803a5..f7e2a02bbd5 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/CrateSystem.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/CrateSystem.h @@ -73,6 +73,7 @@ class CrateTemplate : public Overridable ScienceType m_killerScience; ///< Must be killed by something posessing this science crateCreationEntryList m_possibleCrates; ///< CreationChance is for this CrateData to succeed, this list controls one-of-n crates created on success Bool m_isOwnedByMaker; ///< Design needs crates to be owned sometimes. + Bool m_allowWater; ///< Crate can spawn on water private: diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Die/CreateCrateDie.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Die/CreateCrateDie.cpp index de3a54c8c2d..941e673a6ac 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Die/CreateCrateDie.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Die/CreateCrateDie.cpp @@ -208,7 +208,14 @@ Object *CreateCrateDie::createCrate( CrateTemplate const *currentCrateData ) fpOptions.minRadius = 0.0f; fpOptions.maxRadius = 5.0f; fpOptions.relationshipObject = getObject(); - fpOptions.flags = FPF_IGNORE_ALLY_OR_NEUTRAL_UNITS; // So the dead guy won't block, nor will his dead hulk. + + if (currentCrateData->m_allowWater) { + fpOptions.flags = static_cast(FPF_IGNORE_ALLY_OR_NEUTRAL_UNITS | FPF_IGNORE_WATER); + } + else { + fpOptions.flags = FPF_IGNORE_ALLY_OR_NEUTRAL_UNITS; // So the dead guy won't block, nor will his dead hulk. + } + if (layer != LAYER_GROUND) { creationPoint = centerPoint; spotFound = true; @@ -223,7 +230,13 @@ Object *CreateCrateDie::createCrate( CrateTemplate const *currentCrateData ) fpOptions.minRadius = 0.0f; fpOptions.maxRadius = 125.0f; fpOptions.relationshipObject = NULL; - fpOptions.flags = FPF_NONE; + + if (currentCrateData->m_allowWater) { + fpOptions.flags = FPF_IGNORE_WATER; + } + else { + fpOptions.flags = FPF_NONE; + } if( ThePartitionManager->findPositionAround( ¢erPoint, &fpOptions, &creationPoint ) ) { spotFound = TRUE; @@ -232,6 +245,14 @@ Object *CreateCrateDie::createCrate( CrateTemplate const *currentCrateData ) if( spotFound ) { + //Move up to water surface if unterwater + if (currentCrateData->m_allowWater && getObject()->isOverWater()) { + Real waterZ{ 0 }; + if (TheTerrainLogic->isUnderwater(creationPoint.x, creationPoint.y, &waterZ)) { + creationPoint.z = std::max(creationPoint.z, waterZ); + } + } + Object *newCrate = TheThingFactory->newObject( crateType, NULL ); newCrate->setPosition( &creationPoint ); newCrate->setOrientation( GameLogicRandomValueReal( 0, 2*PI ) ); diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/System/CrateSystem.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/System/CrateSystem.cpp index 33eb9cef8e6..91a933fa4cc 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/System/CrateSystem.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/System/CrateSystem.cpp @@ -185,6 +185,7 @@ const FieldParse CrateTemplate::TheCrateTemplateFieldParseTable[] = { "CrateObject", CrateTemplate::parseCrateCreationEntry, NULL, NULL }, { "KillerScience", INI::parseScience, NULL, offsetof( CrateTemplate, m_killerScience) }, { "OwnedByMaker", INI::parseBool, NULL, offsetof( CrateTemplate, m_isOwnedByMaker) }, + { "AllowWater", INI::parseBool, NULL, offsetof( CrateTemplate, m_allowWater) }, { NULL, NULL, NULL, NULL }, }; @@ -196,6 +197,7 @@ CrateTemplate::CrateTemplate() m_killerScience = SCIENCE_INVALID; m_possibleCrates.clear(); m_isOwnedByMaker = FALSE; + m_allowWater = false; } CrateTemplate::~CrateTemplate()