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 +