Index: binaries/data/mods/public/globalscripts/Templates.js
===================================================================
--- binaries/data/mods/public/globalscripts/Templates.js
+++ binaries/data/mods/public/globalscripts/Templates.js
@@ -452,6 +452,8 @@
"maxTowerOverlap": +template.WallSet.MaxTowerOverlap,
"minTowerOverlap": +template.WallSet.MinTowerOverlap
};
+ if (template.WallSet.TowerSlot)
+ ret.wallSet.towerSlot = template.WallSet.TowerSlot;
if (template.WallSet.Templates.WallEnd)
ret.wallSet.templates.end = template.WallSet.Templates.WallEnd;
if (template.WallSet.Templates.WallCurves)
Index: binaries/data/mods/public/gui/session/input.js
===================================================================
--- binaries/data/mods/public/gui/session/input.js
+++ binaries/data/mods/public/gui/session/input.js
@@ -191,12 +191,16 @@
true, // require exact template match
true // include foundations
);
-
+ placementSupport.wallSlots = null;
+ if (placementSupport.wallSet.towerSlot) {
+ placementSupport.wallSlots = Engine.GuiInterfaceCall("getSlots", {"player": g_ViewedPlayer});
+ }
return Engine.GuiInterfaceCall("SetWallPlacementPreview", {
"wallSet": placementSupport.wallSet,
"start": placementSupport.position,
"end": placementSupport.wallEndPosition,
"snapEntities": placementSupport.wallSnapEntities, // snapping entities (towers) for starting a wall segment
+ "snapSlots": placementSupport.wallSlots
});
}
}
@@ -294,7 +298,7 @@
return false;
}
- var selection = g_Selection.toList();
+ let selection = g_Selection.toList();
Engine.PostNetworkCommand({
"type": "construct",
@@ -326,7 +330,7 @@
return false;
}
- var wallPlacementInfo = updateBuildingPlacementPreview(); // entities making up the wall (wall segments, towers, ...)
+ let wallPlacementInfo = updateBuildingPlacementPreview(); // entities making up the wall (wall segments, towers, ...)
if (!(wallPlacementInfo === false || typeof(wallPlacementInfo) === "object"))
{
error("Invalid updateBuildingPlacementPreview return value: " + uneval(wallPlacementInfo));
@@ -336,8 +340,8 @@
if (!wallPlacementInfo)
return false;
- var selection = g_Selection.toList();
- var cmd = {
+ let selection = g_Selection.toList();
+ let cmd = {
"type": "construct-wall",
"autorepair": true,
"autocontinue": true,
@@ -347,12 +351,13 @@
"pieces": wallPlacementInfo.pieces,
"startSnappedEntity": wallPlacementInfo.startSnappedEnt,
"endSnappedEntity": wallPlacementInfo.endSnappedEnt,
+ "rebuildStartTower": wallPlacementInfo.rebuildStartTower
};
// make sure that there's at least one non-tower entity getting built, to prevent silly edge cases where the start and end
// point are too close together for the algorithm to place a wall segment inbetween, and only the towers are being previewed
// (this is somewhat non-ideal and hardcode-ish)
- var hasWallSegment = false;
+ let hasWallSegment = false;
for (let piece of cmd.pieces)
{
if (piece.template != cmd.wallSet.templates.tower) // TODO: hardcode-ish :(
@@ -362,7 +367,7 @@
}
}
- if (hasWallSegment)
+ if (hasWallSegment || cmd.rebuildStartTower)
{
Engine.PostNetworkCommand(cmd);
Engine.GuiInterfaceCall("PlaySound", { "name": "order_repair", "entity": selection[0] });
@@ -683,6 +688,7 @@
{
placementSupport.Reset();
inputState = INPUT_NORMAL;
+ Engine.GuiInterfaceCall("SetSlotVisibility", {"player": g_ViewedPlayer, "active": false});
}
}
else
@@ -693,6 +699,8 @@
}
else if (ev.button == SDL_BUTTON_RIGHT)
{
+
+ Engine.GuiInterfaceCall("SetSlotVisibility", {"player": g_ViewedPlayer, "active": false});
// reset to normal input mode
placementSupport.Reset();
updateBuildingPlacementPreview();
@@ -1096,6 +1104,7 @@
else if (ev.button == SDL_BUTTON_RIGHT)
{
// Cancel building
+ Engine.GuiInterfaceCall("SetSlotVisibility", {"player": g_ViewedPlayer, "active": false});
placementSupport.Reset();
inputState = INPUT_NORMAL;
return true;
@@ -1303,12 +1312,13 @@
placementSupport.Reset();
// find out if we're building a wall, and change the entity appropriately if so
- var templateData = GetTemplateData(buildTemplate);
+ let templateData = GetTemplateData(buildTemplate);
if (templateData.wallSet)
{
placementSupport.mode = "wall";
placementSupport.wallSet = templateData.wallSet;
inputState = INPUT_BUILDING_PLACEMENT;
+ Engine.GuiInterfaceCall("SetSlotVisibility", {"player": g_ViewedPlayer, "active": true});
}
else
{
Index: binaries/data/mods/public/simulation/components/Foundation.js
===================================================================
--- binaries/data/mods/public/simulation/components/Foundation.js
+++ binaries/data/mods/public/simulation/components/Foundation.js
@@ -39,6 +39,10 @@
this.maxProgress = 0;
this.initialised = true;
+
+ let cmpObstruction = Engine.QueryInterface(this.entity, IID_Obstruction);
+ for (let ent of cmpObstruction.GetEntitiesDeletedUponConstruction())
+ Engine.DestroyEntity(ent);
};
/**
Index: binaries/data/mods/public/simulation/components/GuiInterface.js
===================================================================
--- binaries/data/mods/public/simulation/components/GuiInterface.js
+++ binaries/data/mods/public/simulation/components/GuiInterface.js
@@ -1133,6 +1133,7 @@
"angle": 0,
"snapped": false, // did the start position snap to anything?
"snappedEnt": INVALID_ENTITY, // if we snapped, was it to an entity? if yes, holds that entity's ID
+ "snappedSlot": false,
};
let end = {
@@ -1140,6 +1141,7 @@
"angle": 0,
"snapped": false, // did the start position snap to anything?
"snappedEnt": INVALID_ENTITY, // if we snapped, was it to an entity? if yes, holds that entity's ID
+ "snappedSlot": false,
};
// --------------------------------------------------------------------------------
@@ -1205,6 +1207,32 @@
if (end.pos && (start.pos.x === end.pos.x && start.pos.z === end.pos.z))
end.pos = undefined;
+ let startSlotGroup = null;
+ // Try to snap existing slots
+ if (cmd.snapSlots)
+ {
+ let snapRadius = this.placementWallEntities[wallSet.templates.tower].templateData.wallPiece.length * 0.5; // determined through trial and error
+ let startSnapData = this.GetFoundationSnapData(player, {
+ "x": start.pos.x,
+ "z": start.pos.z,
+ "template": wallSet.templates.tower,
+ "snapEntities": cmd.snapSlots,
+ "snapRadius": snapRadius,
+ });
+
+ if (startSnapData)
+ {
+ start.pos.x = startSnapData.x;
+ start.pos.z = startSnapData.z;
+ start.angle = startSnapData.angle;
+ start.snapped = true;
+ start.snappedSlot = true;
+
+ if (startSnapData.ent)
+ start.snappedEnt = startSnapData.ent;
+ }
+ }
+
// See if we need to snap the start and/or end coordinates to any of our list of snap entities. Note that, despite the list
// of snapping candidate entities, it might still snap to e.g. terrain features. Use the "ent" key in the returned snapping
// data to determine whether it snapped to an entity (if any), and to which one (see GetFoundationSnapData).
@@ -1252,6 +1280,7 @@
}
}
}
+
// clear the single-building preview entity (we'll be rolling our own)
this.SetBuildingPlacementPreview(player, { "template": "" });
@@ -1287,8 +1316,18 @@
// Additionally, in the situation that we're snapping to merely a foundation of a tower instead of a fully
// constructed one, we'll need an extra preview entity for the starting tower, which also must not be obstructed
// by the foundation it snaps to.
-
- if (start.snappedEnt && start.snappedEnt != INVALID_ENTITY)
+ if (start.snappedSlot)
+ {
+ let slotEntityObstruction = Engine.QueryInterface(start.snappedEnt, IID_Obstruction);
+ previewEntities.unshift({
+ "template": wallSet.templates.tower,
+ "pos": start.pos,
+ "angle": start.angle,
+ "controlGroups": [slotEntityObstruction.GetControlGroup()],
+ "slot": true
+ });
+ }
+ else if (start.snappedEnt && start.snappedEnt != INVALID_ENTITY)
{
let startEntObstruction = Engine.QueryInterface(start.snappedEnt, IID_Obstruction);
if (previewEntities.length > 0 && startEntObstruction)
@@ -1394,8 +1433,12 @@
let allPiecesValid = true;
let numRequiredPieces = 0; // number of entities that are required to build the entire wall, regardless of validity
-
- for (let i = 0; i < previewEntities.length; ++i)
+
+ let lengt = previewEntities.length;
+ if (previewEntities.length && previewEntities[0].slot)
+ lengt = 1;
+
+ for (let i = 0; i < lengt; ++i)
{
let entInfo = previewEntities[i];
@@ -1504,14 +1547,16 @@
// TODO: Handle results of CheckPlacement
validPlacement = cmpBuildRestrictions && cmpBuildRestrictions.CheckPlacement().success;
-
+
// If a wall piece has two control groups, it's likely a segment that spans
// between two existing towers. To avoid placing a duplicate wall segment,
// check for collisions with entities that share both control groups.
if (validPlacement && entInfo.controlGroups && entInfo.controlGroups.length > 1)
validPlacement = cmpObstruction.CheckDuplicateFoundation();
+
+ if (entInfo.slot)
+ validPlacement = true;
}
-
allPiecesValid = allPiecesValid && validPlacement;
// The requirement below that all pieces so far have to have valid positions, rather than only this single one,
@@ -1568,6 +1613,7 @@
if (start.snappedEnt && start.snappedEnt != INVALID_ENTITY)
result.startSnappedEnt = start.snappedEnt;
+ result.rebuildStartTower = start.snappedSlot;
// We should only return that we snapped to an entity if all pieces up until that entity can be validly constructed,
// i.e. are included in result.pieces (see docs for the result object).
if (end.pos && end.snappedEnt && end.snappedEnt != INVALID_ENTITY && allPiecesValid)
@@ -1850,6 +1896,38 @@
Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager).SetDebugOverlay(enabled);
};
+GuiInterface.prototype.getSlots = function(player)
+{
+ let cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
+ let entities = cmpRangeManager.GetEntitiesByPlayer(player);
+ let res = [];
+ for (let ent of entities) {
+ let cmpIdentity = Engine.QueryInterface(ent, IID_Identity);
+ if (!cmpIdentity || !cmpIdentity.HasClass("Slot"))
+ continue;
+ res.push(ent);
+
+ }
+ return res;
+}
+
+GuiInterface.prototype.SetSlotVisibility = function(player, data)
+{
+ let cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
+ let entities = cmpRangeManager.GetEntitiesByPlayer(player);
+ let res = [];
+ for (let ent of entities) {
+ let cmpIdentity = Engine.QueryInterface(ent, IID_Identity);
+ if (!cmpIdentity || !cmpIdentity.HasClass("Slot"))
+ continue;
+ let cmpVisibility = Engine.QueryInterface(ent, IID_Visibility);
+ if (cmpVisibility.IsHidden() != !data.active) {
+ cmpVisibility.SetHidden(!data.active);
+ cmpRangeManager.RequestVisibilityUpdate(ent);
+ }
+ }
+}
+
GuiInterface.prototype.GetTraderNumber = function(player)
{
let cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
@@ -1961,7 +2039,10 @@
"GetTraderNumber": 1,
"GetTradingGoods": 1,
"IsTemplateModified": 1,
- "ResetTemplateModified": 1
+ "ResetTemplateModified": 1,
+
+ "getSlots": 1,
+ "SetSlotVisibility": 1,
};
GuiInterface.prototype.ScriptCall = function(player, name, args)
Index: binaries/data/mods/public/simulation/components/Health.js
===================================================================
--- binaries/data/mods/public/simulation/components/Health.js
+++ binaries/data/mods/public/simulation/components/Health.js
@@ -47,6 +47,11 @@
"" +
"" +
"" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
"" +
"" +
"";
@@ -208,6 +213,8 @@
if (this.template.SpawnEntityOnDeath)
this.CreateDeathSpawnedEntity();
+ if (this.template.SpawnSlotOnDeath)
+ this.CreateSlotOnDeath();
switch (this.template.DeathType)
{
@@ -314,6 +321,55 @@
return corpse;
};
+Health.prototype.CreateSlotOnDeath = function()
+{
+ // If the unit died while not in the world, don't spawn a death entity for it
+ // since there's nowhere for it to be placed
+ let cmpPosition = Engine.QueryInterface(this.entity, IID_Position);
+ if (!cmpPosition.IsInWorld())
+ return INVALID_ENTITY;
+
+ // Create SpawnEntityOnDeath entity
+ let spawnedEntity = Engine.AddEntity(this.template.SpawnSlotOnDeath);
+
+ // Move to same position
+ let cmpSpawnedPosition = Engine.QueryInterface(spawnedEntity, IID_Position);
+ if (cmpSpawnedPosition) {
+ let pos = cmpPosition.GetPosition();
+ let rot = cmpPosition.GetRotation();
+ cmpSpawnedPosition.JumpTo(pos.x, pos.z);
+ cmpSpawnedPosition.SetYRotation(rot.y);
+ cmpSpawnedPosition.SetXZRotation(rot.x, rot.z);
+ } else {
+ error("entity " + this.template.SpawnSlotOnDeath + " has not position");
+ }
+
+ let cmpVisual = Engine.QueryInterface(spawnedEntity, IID_Visual);
+ if (cmpVisual) {
+ cmpVisual.SetShadingColor(0, 1, 0, 1);
+ }
+
+ let cmpVisibility = Engine.QueryInterface(spawnedEntity, IID_Visibility);
+ if (cmpVisibility) {
+ cmpVisibility.SetActivated(true);
+ cmpVisibility.SetHidden(true);
+ }
+
+ let cmpObstruction = Engine.QueryInterface(this.entity, IID_Obstruction);
+ let cmpSpawnedObstruction = Engine.QueryInterface(spawnedEntity, IID_Obstruction);
+ if (cmpObstruction && cmpSpawnedObstruction) {
+ cmpSpawnedObstruction.SetControlGroup(cmpObstruction.GetControlGroup());
+ }
+
+ let cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership);
+ let cmpSpawnedOwnership = Engine.QueryInterface(spawnedEntity, IID_Ownership);
+ if (cmpOwnership && cmpSpawnedOwnership) {
+ cmpSpawnedOwnership.SetOwner(cmpOwnership.GetOwner());
+ }
+
+ return spawnedEntity;
+}
+
Health.prototype.CreateDeathSpawnedEntity = function()
{
// If the unit died while not in the world, don't spawn a death entity for it
@@ -337,7 +393,6 @@
let cmpSpawnedOwnership = Engine.QueryInterface(spawnedEntity, IID_Ownership);
if (cmpOwnership && cmpSpawnedOwnership)
cmpSpawnedOwnership.SetOwner(cmpOwnership.GetOwner());
-
return spawnedEntity;
};
Index: binaries/data/mods/public/simulation/components/Visibility.js
===================================================================
--- binaries/data/mods/public/simulation/components/Visibility.js
+++ binaries/data/mods/public/simulation/components/Visibility.js
@@ -16,7 +16,8 @@
"" +
"" +
"" +
- "";
+ ""
+ ;
Visibility.prototype.Init = function()
{
@@ -26,6 +27,7 @@
this.preview = this.template.Preview == "true";
this.activated = false;
+ this.hidden = false;
if (this.preview || this.corpse)
this.SetActivated(true);
@@ -60,6 +62,9 @@
*/
Visibility.prototype.GetVisibility = function(player, isVisible, isExplored)
{
+ if (this.hidden)
+ return VIS_HIDDEN;
+
if (this.preview)
{
// For the owner only, mock the "RetainInFog" behavior
@@ -80,10 +85,20 @@
// For others, regular displaying
return isVisible ? VIS_VISIBLE : VIS_HIDDEN;
}
-
+
return VIS_VISIBLE;
};
+Visibility.prototype.SetHidden = function(hidden)
+{
+ this.hidden = hidden;
+}
+
+Visibility.prototype.IsHidden = function()
+{
+ return this.hidden;
+}
+
Visibility.prototype.GetRetainInFog = function()
{
return this.retainInFog;
Index: binaries/data/mods/public/simulation/components/WallSet.js
===================================================================
--- binaries/data/mods/public/simulation/components/WallSet.js
+++ binaries/data/mods/public/simulation/components/WallSet.js
@@ -4,6 +4,11 @@
"" +
"" +
"" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
"" +
"" +
"" +
Index: binaries/data/mods/public/simulation/helpers/Commands.js
===================================================================
--- binaries/data/mods/public/simulation/helpers/Commands.js
+++ binaries/data/mods/public/simulation/helpers/Commands.js
@@ -1196,13 +1196,14 @@
if (cmd.pieces.length <= 0)
return;
- if (cmd.startSnappedEntity && cmd.pieces[0].template == cmd.wallSet.templates.tower)
+ if (!cmd.rebuildStartTower && cmd.startSnappedEntity && cmd.pieces[0].template == cmd.wallSet.templates.tower)
{
+ error(cmd.startSnappedEntity);
error("[TryConstructWall] Starting wall piece cannot be a tower (" + cmd.wallSet.templates.tower + ") when snapping at the starting side");
return;
}
- if (cmd.endSnappedEntity && cmd.pieces[cmd.pieces.length - 1].template == cmd.wallSet.templates.tower)
+ if (!cmd.rebuildEndTower && cmd.endSnappedEntity && cmd.pieces[cmd.pieces.length - 1].template == cmd.wallSet.templates.tower)
{
error("[TryConstructWall] Ending wall piece cannot be a tower (" + cmd.wallSet.templates.tower + ") when snapping at the ending side");
return;
@@ -1238,14 +1239,14 @@
// first pass; L -> R
- var lastTowerIndex = -1; // index of the last tower we've encountered in cmd.pieces
- var lastTowerControlGroup = null; // control group of the last tower we've encountered, to assign to non-tower pieces
+ let lastTowerIndex = -1; // index of the last tower we've encountered in cmd.pieces
+ let lastTowerControlGroup = null; // control group of the last tower we've encountered, to assign to non-tower pieces
// If we're snapping to an existing entity at the starting end, set lastTowerControlGroup to its control group ID so that
// the first wall piece can be built while overlapping it.
if (cmd.startSnappedEntity)
{
- var cmpSnappedStartObstruction = Engine.QueryInterface(cmd.startSnappedEntity, IID_Obstruction);
+ let cmpSnappedStartObstruction = Engine.QueryInterface(cmd.startSnappedEntity, IID_Obstruction);
if (!cmpSnappedStartObstruction)
{
error("[TryConstructWall] Snapped entity on starting side does not have an obstruction component");
@@ -1253,15 +1254,19 @@
}
lastTowerControlGroup = cmpSnappedStartObstruction.GetControlGroup();
- //warn("setting lastTowerControlGroup to control group of start snapped entity " + cmd.startSnappedEntity + ": " + lastTowerControlGroup);
+ // set different control group to delete upon construction
+ if (cmd.rebuildStartTower) {
+ cmpSnappedStartObstruction.SetControlGroup(0);
+ }
+ // warn("setting lastTowerControlGroup to control group of start snapped entity " + cmd.startSnappedEntity + ": " + lastTowerControlGroup);
}
- var i = 0;
- var queued = cmd.queued;
- var pieces = clone(cmd.pieces);
+ let i = 0;
+ let queued = cmd.queued;
+ let pieces = clone(cmd.pieces);
for (; i < pieces.length; ++i)
{
- var piece = pieces[i];
+ let piece = pieces[i];
// All wall pieces after the first must be queued.
if (i > 0 && !queued)
@@ -1278,7 +1283,7 @@
}
}
- var constructPieceCmd = {
+ let constructPieceCmd = {
"type": "construct",
"entities": cmd.entities,
"template": piece.template,
@@ -1298,12 +1303,12 @@
// while overlapping the snapped entity.
if (i == pieces.length - 1 && cmd.endSnappedEntity)
{
- var cmpEndSnappedObstruction = Engine.QueryInterface(cmd.endSnappedEntity, IID_Obstruction);
+ let cmpEndSnappedObstruction = Engine.QueryInterface(cmd.endSnappedEntity, IID_Obstruction);
if (cmpEndSnappedObstruction)
constructPieceCmd.obstructionControlGroup2 = cmpEndSnappedObstruction.GetControlGroup();
}
- var pieceEntityId = TryConstructBuilding(player, cmpPlayer, controlAllUnits, constructPieceCmd);
+ let pieceEntityId = TryConstructBuilding(player, cmpPlayer, controlAllUnits, constructPieceCmd);
if (pieceEntityId)
{
// wall piece foundation successfully built, save the entity ID in the piece info object so we can reference it later
@@ -1312,21 +1317,22 @@
// if we built a tower, do the control group dance (see outline above) and update lastTowerControlGroup and lastTowerIndex
if (piece.template == cmd.wallSet.templates.tower)
{
- var cmpTowerObstruction = Engine.QueryInterface(pieceEntityId, IID_Obstruction);
- var newTowerControlGroup = pieceEntityId;
+ let cmpTowerObstruction = Engine.QueryInterface(pieceEntityId, IID_Obstruction);
+ let newTowerControlGroup = pieceEntityId;
if (i > 0)
{
- //warn(" updating previous wall piece's secondary control group to " + newTowerControlGroup);
- var cmpPreviousObstruction = Engine.QueryInterface(pieces[i-1].ent, IID_Obstruction);
- // TODO: ensure that cmpPreviousObstruction exists
+ // warn(" updating previous wall piece's secondary control group to " + newTowerControlGroup);
+ let cmpPreviousObstruction = Engine.QueryInterface(pieces[i-1].ent, IID_Obstruction);
+ if(cmpPreviousObstruction)
// TODO: ensure that the previous obstruction does not yet have a secondary control group set
- cmpPreviousObstruction.SetControlGroup2(newTowerControlGroup);
+ cmpPreviousObstruction.SetControlGroup2(newTowerControlGroup);
}
- // TODO: ensure that cmpTowerObstruction exists
- cmpTowerObstruction.SetControlGroup(newTowerControlGroup); // give the tower its own unique control group
-
+ // give the tower its unique control group if not rebuildings
+ if (!cmd.rebuildStartTower && cmpTowerObstruction) {
+ cmpTowerObstruction.SetControlGroup(newTowerControlGroup);
+ }
lastTowerIndex = i;
lastTowerControlGroup = newTowerControlGroup;
}
@@ -1335,8 +1341,8 @@
break;
}
- var lastBuiltPieceIndex = i - 1;
- var wallComplete = (lastBuiltPieceIndex == pieces.length - 1);
+ let lastBuiltPieceIndex = i - 1;
+ let wallComplete = (lastBuiltPieceIndex == pieces.length - 1);
// At this point, 'i' is the index of the last wall piece that was successfully constructed (which may or may not be a tower).
// Now do the second pass going right-to-left, registering the control groups of the towers to the right of each piece (if any)
@@ -1347,7 +1353,7 @@
// only start off with the ending side's snapped tower's control group if we were able to build the entire wall
if (cmd.endSnappedEntity && wallComplete)
{
- var cmpSnappedEndObstruction = Engine.QueryInterface(cmd.endSnappedEntity, IID_Obstruction);
+ let cmpSnappedEndObstruction = Engine.QueryInterface(cmd.endSnappedEntity, IID_Obstruction);
if (!cmpSnappedEndObstruction)
{
error("[TryConstructWall] Snapped entity on ending side does not have an obstruction component");
@@ -1357,9 +1363,9 @@
lastTowerControlGroup = cmpSnappedEndObstruction.GetControlGroup();
}
- for (var j = lastBuiltPieceIndex; j >= 0; --j)
+ for (let j = lastBuiltPieceIndex; j >= 0; --j)
{
- var piece = pieces[j];
+ let piece = pieces[j];
if (!piece.ent)
{
@@ -1367,7 +1373,7 @@
continue;
}
- var cmpPieceObstruction = Engine.QueryInterface(piece.ent, IID_Obstruction);
+ let cmpPieceObstruction = Engine.QueryInterface(piece.ent, IID_Obstruction);
if (!cmpPieceObstruction)
{
error("[TryConstructWall] Wall piece of template '" + piece.template + "' has no Obstruction component");
@@ -1385,7 +1391,7 @@
// Note that the wall piece may already have its secondary control group set to the tower's entity ID from a control group
// dance during the first pass, in which case we should validate it against 'lastTowerControlGroup'.
- var existingSecondaryControlGroup = cmpPieceObstruction.GetControlGroup2();
+ let existingSecondaryControlGroup = cmpPieceObstruction.GetControlGroup2();
if (existingSecondaryControlGroup == INVALID_ENTITY)
{
if (lastTowerControlGroup != null && lastTowerControlGroup != INVALID_ENTITY)
Index: binaries/data/mods/public/simulation/templates/other/palisades_rocks_tower.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/other/palisades_rocks_tower.xml
+++ binaries/data/mods/public/simulation/templates/other/palisades_rocks_tower.xml
@@ -18,6 +18,7 @@
0.25
+ slots/slot_palisade_tower
other/wallset_palisade
Index: binaries/data/mods/public/simulation/templates/other/wallset_palisade.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/other/wallset_palisade.xml
+++ binaries/data/mods/public/simulation/templates/other/wallset_palisade.xml
@@ -8,6 +8,7 @@
phase_village
+ slots/slot_palisade_tower
other/palisades_rocks_tower
other/palisades_rocks_gate
Index: binaries/data/mods/public/simulation/templates/slots/slot_palisade_tower.xml
===================================================================
--- /dev/null
+++ binaries/data/mods/public/simulation/templates/slots/slot_palisade_tower.xml
@@ -0,0 +1,6 @@
+
+
+
+ props/special/palisade_rocks_tower.xml
+
+
Index: binaries/data/mods/public/simulation/templates/slots/slot_wall_tower.xml
===================================================================
--- /dev/null
+++ binaries/data/mods/public/simulation/templates/slots/slot_wall_tower.xml
@@ -0,0 +1,6 @@
+
+
+
+ structures/hellenes/wall_tower.xml
+
+
Index: binaries/data/mods/public/simulation/templates/template_building_slot.xml
===================================================================
--- /dev/null
+++ binaries/data/mods/public/simulation/templates/template_building_slot.xml
@@ -0,0 +1,58 @@
+
+
+
+ false
+ false
+ 0.0
+ 0.0
+ 0
+
+
+ 0
+ upright
+ false
+ 0.0
+ 6.0
+
+
+ 1
+ 0
+ 0
+
+
+ false
+ false
+ false
+ true
+
+
+ 0
+
+
+ structures/destruct_stone_3x3.xml
+ false
+ false
+ false
+
+
+
+ Slot
+ Slot
+ true
+
+
+
+
+ true
+ false
+ false
+ false
+ false
+ false
+ false
+ true
+
+
+ 1
+
+
Index: binaries/data/mods/public/simulation/templates/template_structure_defensive_wall_tower.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/template_structure_defensive_wall_tower.xml
+++ binaries/data/mods/public/simulation/templates/template_structure_defensive_wall_tower.xml
@@ -54,6 +54,7 @@
4000
decay|rubble/rubble_stone_wall_tower
+ slots/slot_wall_tower
Wall Turret
Index: binaries/data/mods/public/simulation/templates/template_wallset.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/template_wallset.xml
+++ binaries/data/mods/public/simulation/templates/template_wallset.xml
@@ -14,6 +14,7 @@
true
+ slots/slot_wall_tower
0.85
0.05
Index: source/simulation2/components/CCmpRangeManager.cpp
===================================================================
--- source/simulation2/components/CCmpRangeManager.cpp
+++ source/simulation2/components/CCmpRangeManager.cpp
@@ -1601,15 +1601,6 @@
int i = (pos.X / (int)TERRAIN_TILE_SIZE).ToInt_RoundToNearest();
int j = (pos.Y / (int)TERRAIN_TILE_SIZE).ToInt_RoundToNearest();
- // Reveal flag makes all positioned entities visible and all mirages useless
- if (GetLosRevealAll(player))
- {
- if (LosIsOffWorld(i, j) || cmpMirage)
- return VIS_HIDDEN;
- else
- return VIS_VISIBLE;
- }
-
// Get visible regions
CLosQuerier los(GetSharedLosMask(player), m_LosState, m_TerrainVerticesPerSide);
@@ -1630,6 +1621,15 @@
// Else, default behavior
+ // Reveal flag makes all positioned entities visible and all mirages useless
+ if (GetLosRevealAll(player))
+ {
+ if (LosIsOffWorld(i, j) || cmpMirage)
+ return VIS_HIDDEN;
+ else
+ return VIS_VISIBLE;
+ }
+
if (los.IsVisible(i, j))
{
if (cmpMirage)