diff --git a/binaries/data/mods/public/simulation/components/BuildRestrictions.js b/binaries/data/mods/public/simulation/components/BuildRestrictions.js
index 75c0c48..a998302 100644
a
|
b
|
BuildRestrictions.prototype.CheckPlacement = function()
|
133 | 133 | if (!cmpObstruction) |
134 | 134 | return result; // Fail |
135 | 135 | |
136 | | |
137 | | if (this.template.Category == "Wall") |
138 | | { |
139 | | // for walls, only test the center point |
140 | | var ret = cmpObstruction.CheckFoundation(passClassName, true); |
141 | | } |
142 | | else |
143 | | { |
144 | | var ret = cmpObstruction.CheckFoundation(passClassName, false); |
145 | | } |
| 136 | var ret = cmpObstruction.CheckFoundation(passClassName); |
146 | 137 | |
147 | 138 | if (ret != "success") |
148 | 139 | { |
diff --git a/binaries/data/mods/public/simulation/templates/other/bridge_hele.xml b/binaries/data/mods/public/simulation/templates/other/bridge_hele.xml
index dbe722f..f70f030 100644
a
|
b
|
|
20 | 20 | </Identity> |
21 | 21 | <Minimap disable=""/> |
22 | 22 | <Obstruction> |
| 23 | <Static disable=""/> |
23 | 24 | <Obstructions> |
24 | 25 | <Edge width="59" depth="4" x="0" z="5"/> |
25 | 26 | </Obstructions> |
diff --git a/binaries/data/mods/public/simulation/templates/other/bridge_wooden.xml b/binaries/data/mods/public/simulation/templates/other/bridge_wooden.xml
index 89b4e7e..6b1a5cd 100644
a
|
b
|
|
20 | 20 | </Identity> |
21 | 21 | <Minimap disable=""/> |
22 | 22 | <Obstruction> |
| 23 | <Static disable=""/> |
23 | 24 | <Obstructions> |
24 | 25 | <Edge width="59" depth="4" x="0" z="5"/> |
25 | 26 | </Obstructions> |
diff --git a/binaries/data/mods/public/simulation/templates/other/palisades_rocks_tower.xml b/binaries/data/mods/public/simulation/templates/other/palisades_rocks_tower.xml
index 2dc8899..d1a55cb 100644
a
|
b
|
|
30 | 30 | <RequiredTechnology>phase_village</RequiredTechnology> |
31 | 31 | </Identity> |
32 | 32 | <Obstruction> |
33 | | <Static width="4.0" depth="4.0"/> |
| 33 | <Static width="4.0" depth="4.0" clearance="-1"/> |
34 | 34 | <ControlPersist/> |
35 | 35 | </Obstruction> |
36 | 36 | <StatusBars> |
diff --git a/binaries/data/mods/public/simulation/templates/template_structure.xml b/binaries/data/mods/public/simulation/templates/template_structure.xml
index dd05092..728b825 100644
a
|
b
|
|
66 | 66 | <Type>structure</Type> |
67 | 67 | </Minimap> |
68 | 68 | <Obstruction> |
| 69 | <Static width="2" depth="2" clearance="4"/> |
69 | 70 | <Active>true</Active> |
70 | 71 | <BlockMovement>true</BlockMovement> |
71 | 72 | <BlockPathfinding>true</BlockPathfinding> |
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 36146e1..af51812 100644
a
|
b
|
|
31 | 31 | <stone>15</stone> |
32 | 32 | </Loot> |
33 | 33 | <Obstruction> |
34 | | <Static width="6.0" depth="6.0"/> |
| 34 | <Static width="6.0" depth="6.0" clearance="0"/> |
35 | 35 | </Obstruction> |
36 | 36 | <ProductionQueue disable=""/> |
37 | 37 | <RallyPoint disable=""/> |
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 12a9438..570b7aa 100644
a
|
b
|
|
58 | 58 | <stone>15</stone> |
59 | 59 | </Loot> |
60 | 60 | <Obstruction> |
61 | | <Static width="6.0" depth="6.0"/> |
| 61 | <Static width="6.0" depth="6.0" clearance="-1"/> |
62 | 62 | <ControlPersist/> |
63 | 63 | </Obstruction> |
64 | 64 | <ProductionQueue> |
diff --git a/source/simulation2/components/CCmpObstruction.cpp b/source/simulation2/components/CCmpObstruction.cpp
index a45b1e4..5c0cd23 100644
a
|
b
|
public:
|
122 | 122 | "<param name='minInclusive'>1.5</param>" |
123 | 123 | "</data>" |
124 | 124 | "</attribute>" |
| 125 | "<optional>" |
| 126 | "<attribute name='clearance' a:help='Extra clearance to be applied when placing the entity, ensures there is passable space around it (can be negative to allow for overlap, if the overlap is small enough to not cause problems).'>" |
| 127 | "<data type='decimal'/>" |
| 128 | "</attribute>" |
| 129 | "</optional>" |
125 | 130 | "</element>" |
126 | 131 | "<element name='Unit'>" |
127 | 132 | "<empty/>" |
… |
… |
public:
|
216 | 221 | m_Type = STATIC; |
217 | 222 | m_Size0 = paramNode.GetChild("Static").GetChild("@width").ToFixed(); |
218 | 223 | m_Size1 = paramNode.GetChild("Static").GetChild("@depth").ToFixed(); |
| 224 | m_Clearance = paramNode.GetChild("Static").GetChild("@clearance").ToFixed(); |
219 | 225 | ENSURE(m_Size0 > minObstruction); |
220 | 226 | ENSURE(m_Size1 > minObstruction); |
221 | 227 | } |
… |
… |
public:
|
244 | 250 | } |
245 | 251 | m_Size0 = fixed::FromInt(2).Multiply(MAX(max.X, -min.X)); |
246 | 252 | m_Size1 = fixed::FromInt(2).Multiply(MAX(max.Y, -min.Y)); |
| 253 | // TODO perhaps support clearance per obstruction |
| 254 | m_Clearance = entity_pos_t::Zero(); |
247 | 255 | } |
248 | 256 | |
249 | 257 | m_Active = paramNode.GetChild("Active").ToBool(); |
… |
… |
public:
|
525 | 533 | |
526 | 534 | virtual EFoundationCheck CheckFoundation(std::string className) |
527 | 535 | { |
528 | | return CheckFoundation(className, false); |
529 | | } |
530 | | |
531 | | virtual EFoundationCheck CheckFoundation(std::string className, bool onlyCenterPoint) |
532 | | { |
533 | 536 | CmpPtr<ICmpPosition> cmpPosition(GetEntityHandle()); |
534 | 537 | if (!cmpPosition) |
535 | 538 | return FOUNDATION_CHECK_FAIL_ERROR; // error |
… |
… |
public:
|
560 | 563 | ICmpObstructionManager::FLAG_BLOCK_FOUNDATION); |
561 | 564 | |
562 | 565 | if (m_Type == UNIT) |
563 | | return cmpPathfinder->CheckUnitPlacement(filter, pos.X, pos.Y, m_Clearance, passClass, onlyCenterPoint); |
| 566 | return cmpPathfinder->CheckUnitPlacement(filter, pos.X, pos.Y, m_Clearance, passClass); |
564 | 567 | else |
565 | | return cmpPathfinder->CheckBuildingPlacement(filter, pos.X, pos.Y, cmpPosition->GetRotation().Y, m_Size0, m_Size1, GetEntityId(), passClass, onlyCenterPoint); |
| 568 | return cmpPathfinder->CheckBuildingPlacement(filter, pos.X, pos.Y, cmpPosition->GetRotation().Y, m_Size0, m_Size1, GetEntityId(), passClass, m_Clearance * 2); |
566 | 569 | } |
567 | 570 | |
568 | 571 | virtual bool CheckDuplicateFoundation() |
diff --git a/source/simulation2/components/CCmpPathfinder.cpp b/source/simulation2/components/CCmpPathfinder.cpp
index e0e725f..ce13db4 100644
a
|
b
|
bool CCmpPathfinder::CheckMovement(const IObstructionTestFilter& filter,
|
810 | 810 | } |
811 | 811 | |
812 | 812 | ICmpObstruction::EFoundationCheck CCmpPathfinder::CheckUnitPlacement(const IObstructionTestFilter& filter, |
813 | | entity_pos_t x, entity_pos_t z, entity_pos_t r, pass_class_t passClass, bool UNUSED(onlyCenterPoint)) |
| 813 | entity_pos_t x, entity_pos_t z, entity_pos_t r, pass_class_t passClass) |
814 | 814 | { |
815 | 815 | // Check unit obstruction |
816 | 816 | CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSystemEntity()); |
… |
… |
ICmpObstruction::EFoundationCheck CCmpPathfinder::CheckBuildingPlacement(const I
|
838 | 838 | entity_pos_t x, entity_pos_t z, entity_pos_t a, entity_pos_t w, |
839 | 839 | entity_pos_t h, entity_id_t id, pass_class_t passClass) |
840 | 840 | { |
841 | | return CCmpPathfinder::CheckBuildingPlacement(filter, x, z, a, w, h, id, passClass, false); |
| 841 | return CCmpPathfinder::CheckBuildingPlacement(filter, x, z, a, w, h, id, passClass, entity_pos_t::Zero()); |
842 | 842 | } |
843 | 843 | |
844 | 844 | |
845 | 845 | ICmpObstruction::EFoundationCheck CCmpPathfinder::CheckBuildingPlacement(const IObstructionTestFilter& filter, |
846 | 846 | entity_pos_t x, entity_pos_t z, entity_pos_t a, entity_pos_t w, |
847 | | entity_pos_t h, entity_id_t id, pass_class_t passClass, bool UNUSED(onlyCenterPoint)) |
| 847 | entity_pos_t h, entity_id_t id, pass_class_t passClass, entity_pos_t clearance) |
848 | 848 | { |
849 | 849 | // Check unit obstruction |
850 | 850 | CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSystemEntity()); |
851 | 851 | if (!cmpObstructionManager) |
852 | 852 | return ICmpObstruction::FOUNDATION_CHECK_FAIL_ERROR; |
853 | 853 | |
854 | | if (cmpObstructionManager->TestStaticShape(filter, x, z, a, w, h, NULL)) |
| 854 | if (cmpObstructionManager->TestStaticShape(filter, x, z, a, w + clearance, h + clearance, NULL)) |
855 | 855 | return ICmpObstruction::FOUNDATION_CHECK_FAIL_OBSTRUCTS_FOUNDATION; |
856 | 856 | |
857 | 857 | // Test against terrain: |
diff --git a/source/simulation2/components/CCmpPathfinder_Common.h b/source/simulation2/components/CCmpPathfinder_Common.h
index 7fc9789..32de276 100644
a
|
b
|
public:
|
273 | 273 | |
274 | 274 | virtual bool CheckMovement(const IObstructionTestFilter& filter, entity_pos_t x0, entity_pos_t z0, entity_pos_t x1, entity_pos_t z1, entity_pos_t r, pass_class_t passClass); |
275 | 275 | |
276 | | 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); |
| 276 | virtual ICmpObstruction::EFoundationCheck CheckUnitPlacement(const IObstructionTestFilter& filter, entity_pos_t x, entity_pos_t z, entity_pos_t r, pass_class_t passClass); |
277 | 277 | |
278 | 278 | 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); |
279 | 279 | |
280 | | 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); |
| 280 | 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, entity_pos_t clearance); |
281 | 281 | |
282 | 282 | virtual void FinishAsyncRequests(); |
283 | 283 | |
diff --git a/source/simulation2/components/ICmpObstruction.cpp b/source/simulation2/components/ICmpObstruction.cpp
index 3216ae9..c6b967e 100644
a
|
b
|
|
23 | 23 | |
24 | 24 | #include "simulation2/system/SimContext.h" |
25 | 25 | |
26 | | std::string ICmpObstruction::CheckFoundation_wrapper(const std::string& className, bool onlyCenterPoint) |
| 26 | std::string ICmpObstruction::CheckFoundation_wrapper(const std::string& className) |
27 | 27 | { |
28 | | EFoundationCheck check = CheckFoundation(className, onlyCenterPoint); |
| 28 | EFoundationCheck check = CheckFoundation(className); |
29 | 29 | |
30 | 30 | switch (check) |
31 | 31 | { |
… |
… |
std::string ICmpObstruction::CheckFoundation_wrapper(const std::string& classNam
|
47 | 47 | |
48 | 48 | BEGIN_INTERFACE_WRAPPER(Obstruction) |
49 | 49 | DEFINE_INTERFACE_METHOD_0("GetUnitRadius", entity_pos_t, ICmpObstruction, GetUnitRadius) |
50 | | DEFINE_INTERFACE_METHOD_2("CheckFoundation", std::string, ICmpObstruction, CheckFoundation_wrapper, std::string, bool) |
| 50 | DEFINE_INTERFACE_METHOD_1("CheckFoundation", std::string, ICmpObstruction, CheckFoundation_wrapper, std::string) |
51 | 51 | DEFINE_INTERFACE_METHOD_0("CheckDuplicateFoundation", bool, ICmpObstruction, CheckDuplicateFoundation) |
52 | 52 | DEFINE_INTERFACE_METHOD_0("GetUnitCollisions", std::vector<entity_id_t>, ICmpObstruction, GetUnitCollisions) |
53 | 53 | DEFINE_INTERFACE_METHOD_1("SetActive", void, ICmpObstruction, SetActive, bool) |
diff --git a/source/simulation2/components/ICmpObstruction.h b/source/simulation2/components/ICmpObstruction.h
index a337502..eb5bfc3 100644
a
|
b
|
public:
|
68 | 68 | * value describing the type of failure. |
69 | 69 | */ |
70 | 70 | virtual EFoundationCheck CheckFoundation(std::string className) = 0; |
71 | | virtual EFoundationCheck CheckFoundation(std::string className, bool onlyCenterPoint) = 0; |
72 | 71 | |
73 | 72 | /** |
74 | 73 | * CheckFoundation wrapper for script calls, to return friendly strings instead of an EFoundationCheck. |
75 | 74 | * @return "success" if check passes, else a string describing the type of failure. |
76 | 75 | */ |
77 | | virtual std::string CheckFoundation_wrapper(const std::string& className, bool onlyCenterPoint); |
| 76 | virtual std::string CheckFoundation_wrapper(const std::string& className); |
78 | 77 | |
79 | 78 | /** |
80 | 79 | * 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 80b590b..35b55b8 100644
a
|
b
|
public:
|
134 | 134 | /** |
135 | 135 | * Check whether a unit placed here is valid and doesn't hit any obstructions |
136 | 136 | * or impassable terrain. |
137 | | * When onlyCenterPoint = true, only check the center tile of the unit |
138 | 137 | * @return ICmpObstruction::FOUNDATION_CHECK_SUCCESS if the placement is okay, else |
139 | 138 | * a value describing the type of failure. |
140 | 139 | */ |
141 | | 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 = false) = 0; |
| 140 | virtual ICmpObstruction::EFoundationCheck CheckUnitPlacement(const IObstructionTestFilter& filter, entity_pos_t x, entity_pos_t z, entity_pos_t r, pass_class_t passClass) = 0; |
142 | 141 | |
143 | 142 | /** |
144 | 143 | * Check whether a building placed here is valid and doesn't hit any obstructions |
… |
… |
public:
|
151 | 150 | /** |
152 | 151 | * Check whether a building placed here is valid and doesn't hit any obstructions |
153 | 152 | * or impassable terrain. |
154 | | * when onlyCenterPoint = true, only check the center tile of the building |
155 | 153 | * @return ICmpObstruction::FOUNDATION_CHECK_SUCCESS if the placement is okay, else |
156 | 154 | * a value describing the type of failure. |
157 | 155 | */ |
158 | | 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; |
| 156 | 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, entity_pos_t clearance) = 0; |
159 | 157 | |
160 | 158 | |
161 | 159 | /** |