Index: binaries/data/mods/public/art/actors/structures/gauls/ambush_camp.xml
===================================================================
--- binaries/data/mods/public/art/actors/structures/gauls/ambush_camp.xml
+++ binaries/data/mods/public/art/actors/structures/gauls/ambush_camp.xml
@@ -0,0 +1,143 @@
+
+
+
+
+
+ structural/field_propped_8x8.dae
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ basic_trans.xml
+
Index: binaries/data/mods/public/art/actors/structures/plot_ambush.xml
===================================================================
--- binaries/data/mods/public/art/actors/structures/plot_ambush.xml
+++ binaries/data/mods/public/art/actors/structures/plot_ambush.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+ structural/field_propped_8x8.dae
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ basic_trans.xml
+
Index: binaries/data/mods/public/gui/common/tooltips.js
===================================================================
--- binaries/data/mods/public/gui/common/tooltips.js
+++ binaries/data/mods/public/gui/common/tooltips.js
@@ -182,6 +182,18 @@
});
}
+function getPanelEntityGarrisonTooltip(entState, label)
+{
+ if (!entState.garrisonHolder)
+ return "";
+
+ return sprintf(translate("%(garrisonLabel)s %(garrisonSize)s / %(garrisonLimit)s"), {
+ "garrisonLabel": headerFont(label || translate("Current Garrison:")),
+ "garrisonSize": entState.garrisonHolder.occupiedSlots,
+ "garrisonLimit": entState.garrisonHolder.capacity
+ });
+}
+
/**
* Converts an resistance level into the actual reduction percentage.
*/
Index: binaries/data/mods/public/gui/session/PanelEntity.js
===================================================================
--- binaries/data/mods/public/gui/session/PanelEntity.js
+++ binaries/data/mods/public/gui/session/PanelEntity.js
@@ -142,5 +142,6 @@
getAttackTooltip,
getResistanceTooltip,
getEntityTooltip,
- getAurasTooltip
+ getAurasTooltip,
+ getPanelEntityGarrisonTooltip
];
Index: binaries/data/mods/public/simulation/ai/common-api/entity.js
===================================================================
--- binaries/data/mods/public/simulation/ai/common-api/entity.js
+++ binaries/data/mods/public/simulation/ai/common-api/entity.js
@@ -186,6 +186,8 @@
return false;
},
+ "isCamouflaged": function() { return "Camouflaged" in this._template; },
+
"isRepairable": function() { return this.get("Repairable") !== undefined; },
"getPopulationBonus": function() {
Index: binaries/data/mods/public/simulation/ai/petra/attackPlan.js
===================================================================
--- binaries/data/mods/public/simulation/ai/petra/attackPlan.js
+++ binaries/data/mods/public/simulation/ai/petra/attackPlan.js
@@ -977,10 +977,11 @@
PETRA.AttackPlan.prototype.isValidTarget = function(ent)
{
- if (!ent.position())
+ if (!ent.position() || ent.isCamouflaged())
return false;
if (this.sameLand && PETRA.getLandAccess(this.gameState, ent) != this.sameLand)
return false;
+
return !ent.decaying() || ent.getDefaultArrow() || ent.isGarrisonHolder() && ent.garrisoned().length;
};
Index: binaries/data/mods/public/simulation/components/BuildRestrictions.js
===================================================================
--- binaries/data/mods/public/simulation/components/BuildRestrictions.js
+++ binaries/data/mods/public/simulation/components/BuildRestrictions.js
@@ -18,6 +18,7 @@
"land" +
"shore" +
"land-shore"+
+ "land-ignore-obstruction"+
"" +
"" +
"" +
@@ -131,6 +132,10 @@
passClassName = "default-terrain-only";
break;
+ case "land-ignore-obstruction":
+ passClassName = "building-land-no-obstruction";
+ break;
+
case "land":
default:
passClassName = "building-land";
@@ -146,6 +151,15 @@
// for walls, only test the center point
var ret = cmpObstruction.CheckFoundation(passClassName, true);
}
+ else if (this.template.PlacementType == "land-ignore-obstruction")
+ {
+ // this is needed as the the none
+ // is not actually used when building
+ // it is rather assumed to be foundation
+ // by the c++ part. See palisades as another example who use
+ // land-shore but are still obstructed by foundations
+ var ret = "success";
+ }
else
{
var ret = cmpObstruction.CheckFoundation(passClassName, false);
Index: binaries/data/mods/public/simulation/components/BuildingAI.js
===================================================================
--- binaries/data/mods/public/simulation/components/BuildingAI.js
+++ binaries/data/mods/public/simulation/components/BuildingAI.js
@@ -185,9 +185,13 @@
// Add new targets.
for (let entity of msg.added)
+ {
+ if (Engine.QueryInterface(entity, IID_Camouflaged))
+ continue;
+
if (cmpAttack.CanAttack(entity))
this.targetUnits.push(entity);
-
+ }
// Remove targets outside of vision-range.
for (let entity of msg.removed)
{
Index: binaries/data/mods/public/simulation/components/Camouflaged.js
===================================================================
--- binaries/data/mods/public/simulation/components/Camouflaged.js
+++ binaries/data/mods/public/simulation/components/Camouflaged.js
@@ -0,0 +1,9 @@
+function Camouflaged() {}
+
+Camouflaged.prototype.Schema = "";
+
+Camouflaged.prototype.Init = function()
+{
+};
+
+Engine.RegisterComponentType(IID_Camouflaged, "Camouflaged", Camouflaged);
Index: binaries/data/mods/public/simulation/components/Player.js
===================================================================
--- binaries/data/mods/public/simulation/components/Player.js
+++ binaries/data/mods/public/simulation/components/Player.js
@@ -45,7 +45,7 @@
/**
* Which units will be shown with special icons at the top.
*/
-var panelEntityClasses = "Hero Relic";
+var panelEntityClasses = "Hero Relic AmbushCamp";
Player.prototype.Init = function()
{
Index: binaries/data/mods/public/simulation/components/UnitAI.js
===================================================================
--- binaries/data/mods/public/simulation/components/UnitAI.js
+++ binaries/data/mods/public/simulation/components/UnitAI.js
@@ -6413,6 +6413,9 @@
if (!cmpAttack.CanAttack(e))
return false;
+ if (Engine.QueryInterface(e, IID_Camouflaged))
+ return false;
+
let cmpOwnership = Engine.QueryInterface(e, IID_Ownership);
if (cmpOwnership && cmpOwnership.GetOwner() > 0)
return true;
Index: binaries/data/mods/public/simulation/components/interfaces/Camouflaged.js
===================================================================
--- binaries/data/mods/public/simulation/components/interfaces/Camouflaged.js
+++ binaries/data/mods/public/simulation/components/interfaces/Camouflaged.js
@@ -0,0 +1 @@
+Engine.RegisterInterface("Camouflaged");
Index: binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
===================================================================
--- binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
+++ binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
@@ -1,6 +1,7 @@
Engine.LoadHelperScript("Player.js");
Engine.LoadHelperScript("Position.js");
Engine.LoadHelperScript("Sound.js");
+Engine.LoadComponentScript("interfaces/Camouflaged.js");
Engine.LoadComponentScript("interfaces/Auras.js");
Engine.LoadComponentScript("interfaces/Builder.js");
Engine.LoadComponentScript("interfaces/BuildingAI.js");
Index: binaries/data/mods/public/simulation/data/pathfinder.xml
===================================================================
--- binaries/data/mods/public/simulation/data/pathfinder.xml
+++ binaries/data/mods/public/simulation/data/pathfinder.xml
@@ -63,6 +63,8 @@
from water and not on cliffs or mountains.
* Shore is used for docks, which must be near water and
land, yet shallow enough for builders to approach.
+ * Land-no-obstruction is used for buildings which should
+ be land only, but ignore all obstructions.
-->
foundation
@@ -75,6 +77,12 @@
8.0
1.25
+
+ none
+ 0
+ 4.0
+ 1.0
+