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.
*/