From 041855e547a26b5ddeadcfefbb932bdd2c592019 Mon Sep 17 00:00:00 2001 From: alpha123 Date: Sun, 7 Jul 2013 22:44:47 +0000 Subject: [PATCH] Allow building walls along the shore. Patch by sanderd17. Fix #1610. This was SVN commit r13542. --- .../components/BuildRestrictions.js | 21 +++++++++-- .../template_structure_defense_wall.xml | 1 + .../template_structure_defense_wall_tower.xml | 13 +++---- .../components/CCmpObstruction.cpp | 13 ++++--- .../simulation2/components/CCmpPathfinder.cpp | 36 +++++++++++++++++++ .../components/CCmpPathfinder_Common.h | 4 +++ .../components/ICmpObstruction.cpp | 6 ++-- .../simulation2/components/ICmpObstruction.h | 3 +- .../simulation2/components/ICmpPathfinder.h | 19 ++++++++++ 9 files changed, 100 insertions(+), 16 deletions(-) diff --git a/binaries/data/mods/public/simulation/components/BuildRestrictions.js b/binaries/data/mods/public/simulation/components/BuildRestrictions.js index f87282a3fb..148fa0e4f5 100644 --- a/binaries/data/mods/public/simulation/components/BuildRestrictions.js +++ b/binaries/data/mods/public/simulation/components/BuildRestrictions.js @@ -17,6 +17,7 @@ BuildRestrictions.prototype.Schema = "" + "land" + "shore" + + "land-shore"+ "" + "" + "" + @@ -130,7 +131,13 @@ BuildRestrictions.prototype.CheckPlacement = function() case "shore": passClassName = "building-shore"; break; - + + case "land-shore": + // 'default' is everywhere a normal unit can go + // So on passable land, and not too deep in the water + passClassName = "default"; + break; + case "land": default: passClassName = "building-land"; @@ -139,8 +146,18 @@ BuildRestrictions.prototype.CheckPlacement = function() var cmpObstruction = Engine.QueryInterface(this.entity, IID_Obstruction); if (!cmpObstruction) return result; // Fail + + + if (this.template.Category == "Wall") + { + // for walls, only test the center point + var ret = cmpObstruction.CheckFoundation(passClassName, true); + } + else + { + var ret = cmpObstruction.CheckFoundation(passClassName, false); + } - var ret = cmpObstruction.CheckFoundation(passClassName); if (ret != "success") { switch (ret) diff --git a/binaries/data/mods/public/simulation/templates/template_structure_defense_wall.xml b/binaries/data/mods/public/simulation/templates/template_structure_defense_wall.xml index fc5ad6484a..62b3c64357 100644 --- a/binaries/data/mods/public/simulation/templates/template_structure_defense_wall.xml +++ b/binaries/data/mods/public/simulation/templates/template_structure_defense_wall.xml @@ -1,6 +1,7 @@ + land-shore Wall diff --git a/binaries/data/mods/public/simulation/templates/template_structure_defense_wall_tower.xml b/binaries/data/mods/public/simulation/templates/template_structure_defense_wall_tower.xml index a1b6746a32..cc10471848 100644 --- a/binaries/data/mods/public/simulation/templates/template_structure_defense_wall_tower.xml +++ b/binaries/data/mods/public/simulation/templates/template_structure_defense_wall_tower.xml @@ -15,12 +15,13 @@ 1 - 1 - - - Wall - - + 1 + + + land-shore + Wall + + 20 100 diff --git a/source/simulation2/components/CCmpObstruction.cpp b/source/simulation2/components/CCmpObstruction.cpp index 9fdccd60d8..a0ab6a72d7 100644 --- a/source/simulation2/components/CCmpObstruction.cpp +++ b/source/simulation2/components/CCmpObstruction.cpp @@ -477,8 +477,13 @@ public: { return m_ControlPersist; } - + virtual EFoundationCheck CheckFoundation(std::string className) + { + return CheckFoundation(className, false); + } + + virtual EFoundationCheck CheckFoundation(std::string className, bool onlyCenterPoint) { CmpPtr cmpPosition(GetSimContext(), GetEntityId()); if (!cmpPosition) @@ -510,9 +515,9 @@ public: ICmpObstructionManager::FLAG_BLOCK_FOUNDATION); if (m_Type == UNIT) - return cmpPathfinder->CheckUnitPlacement(filter, pos.X, pos.Y, m_Size0, passClass); + return cmpPathfinder->CheckUnitPlacement(filter, pos.X, pos.Y, m_Size0, passClass, onlyCenterPoint); else - return cmpPathfinder->CheckBuildingPlacement(filter, pos.X, pos.Y, cmpPosition->GetRotation().Y, m_Size0, m_Size1, GetEntityId(), passClass); + return cmpPathfinder->CheckBuildingPlacement(filter, pos.X, pos.Y, cmpPosition->GetRotation().Y, m_Size0, m_Size1, GetEntityId(), passClass, onlyCenterPoint); } virtual bool CheckDuplicateFoundation() @@ -544,7 +549,7 @@ public: if (m_Type == UNIT) return !cmpObstructionManager->TestUnitShape(filter, pos.X, pos.Y, m_Size0, NULL); else - return !cmpObstructionManager->TestStaticShape(filter, pos.X, pos.Y, cmpPosition->GetRotation().Y, m_Size0, m_Size1, NULL); + return !cmpObstructionManager->TestStaticShape(filter, pos.X, pos.Y, cmpPosition->GetRotation().Y, m_Size0, m_Size1, NULL ); } virtual std::vector GetEntityCollisions(bool checkStructures, bool checkUnits) diff --git a/source/simulation2/components/CCmpPathfinder.cpp b/source/simulation2/components/CCmpPathfinder.cpp index 0df667cde4..d7e1091442 100644 --- a/source/simulation2/components/CCmpPathfinder.cpp +++ b/source/simulation2/components/CCmpPathfinder.cpp @@ -658,6 +658,12 @@ void CCmpPathfinder::ProcessSameTurnMoves() ICmpObstruction::EFoundationCheck CCmpPathfinder::CheckUnitPlacement(const IObstructionTestFilter& filter, entity_pos_t x, entity_pos_t z, entity_pos_t r, pass_class_t passClass) +{ + return CCmpPathfinder::CheckUnitPlacement(filter, x, z, r, passClass, false); +} + +ICmpObstruction::EFoundationCheck CCmpPathfinder::CheckUnitPlacement(const IObstructionTestFilter& filter, + entity_pos_t x, entity_pos_t z, entity_pos_t r, pass_class_t passClass, bool onlyCenterPoint) { // Check unit obstruction CmpPtr cmpObstructionManager(GetSimContext(), SYSTEM_ENTITY); @@ -670,6 +676,17 @@ ICmpObstruction::EFoundationCheck CCmpPathfinder::CheckUnitPlacement(const IObst // Test against terrain: UpdateGrid(); + + if (onlyCenterPoint) + { + u16 i, j; + NearestTile(x , z, i, j); + + if (IS_TERRAIN_PASSABLE(m_Grid->get(i,j), passClass)) + return ICmpObstruction::FOUNDATION_CHECK_SUCCESS; + + return ICmpObstruction::FOUNDATION_CHECK_FAIL_TERRAIN_CLASS; + } u16 i0, j0, i1, j1; NearestTile(x - r, z - r, i0, j0); @@ -690,6 +707,14 @@ ICmpObstruction::EFoundationCheck CCmpPathfinder::CheckUnitPlacement(const IObst ICmpObstruction::EFoundationCheck CCmpPathfinder::CheckBuildingPlacement(const IObstructionTestFilter& filter, entity_pos_t x, entity_pos_t z, entity_pos_t a, entity_pos_t w, entity_pos_t h, entity_id_t id, pass_class_t passClass) +{ + return CCmpPathfinder::CheckBuildingPlacement(filter, x, z, a, w, h, id, passClass, false); +} + + +ICmpObstruction::EFoundationCheck CCmpPathfinder::CheckBuildingPlacement(const IObstructionTestFilter& filter, + entity_pos_t x, entity_pos_t z, entity_pos_t a, entity_pos_t w, + entity_pos_t h, entity_id_t id, pass_class_t passClass, bool onlyCenterPoint) { // Check unit obstruction CmpPtr cmpObstructionManager(GetSimContext(), SYSTEM_ENTITY); @@ -708,6 +733,17 @@ ICmpObstruction::EFoundationCheck CCmpPathfinder::CheckBuildingPlacement(const I if (!cmpObstruction || !cmpObstruction->GetObstructionSquare(square)) return ICmpObstruction::FOUNDATION_CHECK_FAIL_NO_OBSTRUCTION; + if (onlyCenterPoint) + { + u16 i, j; + NearestTile(x, z, i, j); + + if (IS_TERRAIN_PASSABLE(m_Grid->get(i,j), passClass)) + return ICmpObstruction::FOUNDATION_CHECK_SUCCESS; + + return ICmpObstruction::FOUNDATION_CHECK_FAIL_TERRAIN_CLASS; + } + // Expand bounds by 1/sqrt(2) tile (multiply by TERRAIN_TILE_SIZE since we want world coordinates) entity_pos_t expand = entity_pos_t::FromInt(2).Sqrt().Multiply(entity_pos_t::FromInt(TERRAIN_TILE_SIZE / 2)); CFixedVector2D halfSize(square.hw + expand, square.hh + expand); diff --git a/source/simulation2/components/CCmpPathfinder_Common.h b/source/simulation2/components/CCmpPathfinder_Common.h index a5e4a74dd4..bcbbcab262 100644 --- a/source/simulation2/components/CCmpPathfinder_Common.h +++ b/source/simulation2/components/CCmpPathfinder_Common.h @@ -262,8 +262,12 @@ public: virtual ICmpObstruction::EFoundationCheck CheckUnitPlacement(const IObstructionTestFilter& filter, entity_pos_t x, entity_pos_t z, entity_pos_t r, pass_class_t passClass); +virtual ICmpObstruction::EFoundationCheck CheckUnitPlacement(const IObstructionTestFilter& filter, entity_pos_t x, entity_pos_t z, entity_pos_t r, pass_class_t passClass, bool onlyCenterPoint); + virtual ICmpObstruction::EFoundationCheck CheckBuildingPlacement(const IObstructionTestFilter& filter, entity_pos_t x, entity_pos_t z, entity_pos_t a, entity_pos_t w, entity_pos_t h, entity_id_t id, pass_class_t passClass); + virtual ICmpObstruction::EFoundationCheck CheckBuildingPlacement(const IObstructionTestFilter& filter, entity_pos_t x, entity_pos_t z, entity_pos_t a, entity_pos_t w, entity_pos_t h, entity_id_t id, pass_class_t passClass, bool onlyCenterPoint); + virtual void FinishAsyncRequests(); void ProcessLongRequests(const std::vector& longRequests); diff --git a/source/simulation2/components/ICmpObstruction.cpp b/source/simulation2/components/ICmpObstruction.cpp index fb5ce9d62d..33373f96c1 100644 --- a/source/simulation2/components/ICmpObstruction.cpp +++ b/source/simulation2/components/ICmpObstruction.cpp @@ -23,9 +23,9 @@ #include "simulation2/system/SimContext.h" -std::string ICmpObstruction::CheckFoundation_wrapper(std::string className) +std::string ICmpObstruction::CheckFoundation_wrapper(std::string className, bool onlyCenterPoint) { - EFoundationCheck check = CheckFoundation(className); + EFoundationCheck check = CheckFoundation(className, onlyCenterPoint); switch (check) { @@ -47,7 +47,7 @@ std::string ICmpObstruction::CheckFoundation_wrapper(std::string className) BEGIN_INTERFACE_WRAPPER(Obstruction) DEFINE_INTERFACE_METHOD_0("GetUnitRadius", entity_pos_t, ICmpObstruction, GetUnitRadius) -DEFINE_INTERFACE_METHOD_1("CheckFoundation", std::string, ICmpObstruction, CheckFoundation_wrapper, std::string) +DEFINE_INTERFACE_METHOD_2("CheckFoundation", std::string, ICmpObstruction, CheckFoundation_wrapper, std::string, bool) DEFINE_INTERFACE_METHOD_0("CheckDuplicateFoundation", bool, ICmpObstruction, CheckDuplicateFoundation) DEFINE_INTERFACE_METHOD_2("GetEntityCollisions", std::vector, ICmpObstruction, GetEntityCollisions, bool, bool) DEFINE_INTERFACE_METHOD_1("SetActive", void, ICmpObstruction, SetActive, bool) diff --git a/source/simulation2/components/ICmpObstruction.h b/source/simulation2/components/ICmpObstruction.h index 666680d891..6060c4dbf3 100644 --- a/source/simulation2/components/ICmpObstruction.h +++ b/source/simulation2/components/ICmpObstruction.h @@ -59,12 +59,13 @@ public: * value describing the type of failure. */ virtual EFoundationCheck CheckFoundation(std::string className) = 0; + virtual EFoundationCheck CheckFoundation(std::string className, bool onlyCenterPoint) = 0; /** * CheckFoundation wrapper for script calls, to return friendly strings instead of an EFoundationCheck. * @return "success" if check passes, else a string describing the type of failure. */ - virtual std::string CheckFoundation_wrapper(std::string className); + virtual std::string CheckFoundation_wrapper(std::string className, bool onlyCenterPoint); /** * Test whether this entity is colliding with any obstructions that share its diff --git a/source/simulation2/components/ICmpPathfinder.h b/source/simulation2/components/ICmpPathfinder.h index e75713addf..a1256c2a0e 100644 --- a/source/simulation2/components/ICmpPathfinder.h +++ b/source/simulation2/components/ICmpPathfinder.h @@ -158,6 +158,15 @@ public: */ virtual ICmpObstruction::EFoundationCheck CheckUnitPlacement(const IObstructionTestFilter& filter, entity_pos_t x, entity_pos_t z, entity_pos_t r, pass_class_t passClass) = 0; + /** + * Check whether a unit placed here is valid and doesn't hit any obstructions + * or impassable terrain. + * When onlyCenterPoint = true, only check the center tile of the unit + * @return ICmpObstruction::FOUNDATION_CHECK_SUCCESS if the placement is okay, else + * a value describing the type of failure. + */ + virtual ICmpObstruction::EFoundationCheck CheckUnitPlacement(const IObstructionTestFilter& filter, entity_pos_t x, entity_pos_t z, entity_pos_t r, pass_class_t passClass, bool onlyCenterPoint) = 0; + /** * Check whether a building placed here is valid and doesn't hit any obstructions * or impassable terrain. @@ -166,6 +175,16 @@ public: */ virtual ICmpObstruction::EFoundationCheck CheckBuildingPlacement(const IObstructionTestFilter& filter, entity_pos_t x, entity_pos_t z, entity_pos_t a, entity_pos_t w, entity_pos_t h, entity_id_t id, pass_class_t passClass) = 0; + /** + * Check whether a building placed here is valid and doesn't hit any obstructions + * or impassable terrain. + * when onlyCenterPoint = true, only check the center tile of the building + * @return ICmpObstruction::FOUNDATION_CHECK_SUCCESS if the placement is okay, else + * a value describing the type of failure. + */ + virtual ICmpObstruction::EFoundationCheck CheckBuildingPlacement(const IObstructionTestFilter& filter, entity_pos_t x, entity_pos_t z, entity_pos_t a, entity_pos_t w, entity_pos_t h, entity_id_t id, pass_class_t passClass, bool onlyCenterPoint) = 0; + + /** * Toggle the storage and rendering of debug info. */