Index: binaries/data/mods/public/globalscripts/Templates.js
===================================================================
--- binaries/data/mods/public/globalscripts/Templates.js
+++ binaries/data/mods/public/globalscripts/Templates.js
@@ -464,6 +464,8 @@
"maxTowerOverlap": +template.WallSet.MaxTowerOverlap,
"minTowerOverlap": +template.WallSet.MinTowerOverlap
};
+ if (template.WallSet.Templates.TowerSlot)
+ ret.wallSet.templates.towerSlot = template.WallSet.Templates.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,11 +191,15 @@
true // include foundations
);
+ if (placementSupport.wallSet.templates.towerSlot)
+ placementSupport.wallSlots = Engine.GuiInterfaceCall("GetSlots", undefined);
+
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
});
}
}
@@ -356,6 +360,7 @@
"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
@@ -371,7 +376,7 @@
}
}
- if (hasWallSegment)
+ if (hasWallSegment || cmd.rebuildStartTower)
{
Engine.PostNetworkCommand(cmd);
Engine.GuiInterfaceCall("PlaySound", { "name": "order_build", "entity": selection[0] });
@@ -692,6 +697,7 @@
{
placementSupport.Reset();
inputState = INPUT_NORMAL;
+ Engine.GuiInterfaceCall("SetSlotVisibility", { "hidden": true });
}
}
else
@@ -702,6 +708,7 @@
}
else if (ev.button == SDL_BUTTON_RIGHT)
{
+ Engine.GuiInterfaceCall("SetSlotVisibility", { "hidden": true });
// reset to normal input mode
placementSupport.Reset();
updateBuildingPlacementPreview();
@@ -1111,6 +1118,7 @@
else if (ev.button == SDL_BUTTON_RIGHT)
{
// Cancel building
+ Engine.GuiInterfaceCall("SetSlotVisibility", { "hidden": true });
placementSupport.Reset();
inputState = INPUT_NORMAL;
return true;
@@ -1305,6 +1313,7 @@
placementSupport.mode = "wall";
placementSupport.wallSet = templateData.wallSet;
inputState = INPUT_BUILDING_PLACEMENT;
+ Engine.GuiInterfaceCall("SetSlotVisibility", { "hidden": false });
}
else
{
Index: binaries/data/mods/public/gui/session/placement.js
===================================================================
--- binaries/data/mods/public/gui/session/placement.js
+++ binaries/data/mods/public/gui/session/placement.js
@@ -19,7 +19,7 @@
this.wallSnapEntities = null; // list of candidate entities to snap the starting and (!) ending positions to when building walls
this.wallEndPosition = null;
this.wallSnapEntitiesIncludeOffscreen = false; // should the next update of the snap candidate list include offscreen towers?
-
+ this.wallSlots = null;
this.SetDefaultAngle();
this.RandomizeActorSeed();
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,13 @@
this.maxProgress = 0;
this.initialised = true;
+
+ let cmpObstruction = Engine.QueryInterface(this.entity, IID_Obstruction);
+ if (!cmpObstruction)
+ return;
+
+ 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
@@ -1168,6 +1168,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 = {
@@ -1175,6 +1176,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
};
// --------------------------------------------------------------------------------
@@ -1240,6 +1242,24 @@
if (end.pos && (start.pos.x === end.pos.x && start.pos.z === end.pos.z))
end.pos = undefined;
+ // Try to snap to existing slots.
+ if (cmd.snapSlots)
+ {
+ // Determined through trial and error.
+ let snapRadiusMultiplier = 0.5;
+ let snapRadius = this.placementWallEntities[wallSet.templates.tower].templateData.wallPiece.length * snapRadiusMultiplier ;
+ let startSnapData = this.GetFoundationSnapData(player, {
+ "x": start.pos.x,
+ "z": start.pos.z,
+ "template": wallSet.templates.tower,
+ "snapEntities": cmd.snapSlots,
+ "snapRadius": snapRadius
+ });
+
+ if (startSnapData)
+ this.SetSnapData(startSnapData, start, true);
+ }
+
// 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).
@@ -1255,15 +1275,7 @@
});
if (startSnapData)
- {
- start.pos.x = startSnapData.x;
- start.pos.z = startSnapData.z;
- start.angle = startSnapData.angle;
- start.snapped = true;
-
- if (startSnapData.ent)
- start.snappedEnt = startSnapData.ent;
- }
+ this.SetSnapData(startSnapData, start, false);
if (end.pos)
{
@@ -1276,15 +1288,7 @@
});
if (endSnapData)
- {
- end.pos.x = endSnapData.x;
- end.pos.z = endSnapData.z;
- end.angle = endSnapData.angle;
- end.snapped = true;
-
- if (endSnapData.ent)
- end.snappedEnt = endSnapData.ent;
- }
+ this.SetSnapData(startSnapData, end, false);
}
}
@@ -1323,7 +1327,19 @@
// 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);
+ if(slotEntityObstruction)
+ 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)
@@ -1430,7 +1446,10 @@
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)
+ // If the first element is a tower slot, only build that preview.
+ const length = previewEntities.length && previewEntities[0].slot ? 1 : previewEntities.length;
+
+ for (let i = 0; i < length; ++i)
{
let entInfo = previewEntities[i];
@@ -1528,7 +1547,11 @@
// Check whether it's in a visible or fogged region
// TODO: should definitely reuse SetBuildingPlacementPreview, this is just straight up copy/pasta
let visible = cmpRangeManager.GetLosVisibility(ent, player) != "hidden";
- if (visible)
+ if (visible && entInfo.slot)
+ {
+ validPlacement = true;
+ }
+ else if(visible)
{
let cmpBuildRestrictions = Engine.QueryInterface(ent, IID_BuildRestrictions);
if (!cmpBuildRestrictions)
@@ -1603,6 +1626,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)
@@ -1892,6 +1916,34 @@
Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager).SetDebugOverlay(enabled);
};
+GuiInterface.prototype.GetSlots = function(player, data)
+{
+ let cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
+ let entities = cmpRangeManager.GetEntitiesByPlayer(player);
+ return entities.filter((ent) => {
+ let cmpIdentity = Engine.QueryInterface(ent, IID_Identity);
+ return cmpIdentity && cmpIdentity.HasClass("Slot");
+ });
+};
+
+GuiInterface.prototype.SetSlotVisibility = function(player, data)
+{
+ let slots = this.GetSlots(player, undefined);
+ if (!slots || !slots.length)
+ return;
+
+ let cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
+ for (let ent of slots)
+ {
+ let cmpVisibility = Engine.QueryInterface(ent, IID_Visibility);
+ if (!cmpVisibility || cmpVisibility.IsHidden() == data.hidden)
+ continue;
+
+ cmpVisibility.SetHidden(data.hidden);
+ cmpRangeManager.RequestVisibilityUpdate(ent);
+ }
+};
+
GuiInterface.prototype.GetTraderNumber = function(player)
{
let cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
@@ -1941,6 +1993,23 @@
this.renamedEntities.push(msg);
};
+/**
+ * @param {Object} snapData - The snapped object's data.
+ * @param {Object} target - The snapped object's target object.
+ * @param {boolean} isSnappedSlot - Whether the object is a slot.
+ */
+GuiInterface.prototype.SetSnapData = function(snapData, target, isSnappedSlot)
+{
+ target.pos.x = snapData.x;
+ target.pos.z = snapData.z;
+ target.angle = snapData.angle;
+ target.snapped = true;
+ target.snappedSlot = isSnappedSlot;
+
+ if (snapData.ent)
+ target.snappedEnt = snapData.ent;
+};
+
// List the GuiInterface functions that can be safely called by GUI scripts.
// (GUI scripts are non-deterministic and untrusted, so these functions must be
// appropriately careful. They are called with a first argument "player", which is
@@ -2005,7 +2074,9 @@
"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 @@
"" +
"" +
"" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
"" +
"" +
"";
@@ -254,7 +259,10 @@
PlaySound("death", this.entity);
if (this.template.SpawnEntityOnDeath)
- this.CreateDeathSpawnedEntity();
+ this.CreateDeathSpawnedEntity(this.template.SpawnEntityOnDeath);
+
+ if (this.template.SpawnSlotOnDeath)
+ this.CreateDeathSpawnedSlot(this.template.SpawnSlotOnDeath);
switch (this.template.DeathType)
{
@@ -312,34 +320,13 @@
Health.prototype.CreateCorpse = function(leaveResources)
{
- // If the unit died while not in the world, don't create any corpse for it
- // since there's nowhere for the corpse to be placed
- let cmpPosition = Engine.QueryInterface(this.entity, IID_Position);
- if (!cmpPosition.IsInWorld())
- return INVALID_ENTITY;
-
// Either creates a static local version of the current entity, or a
// persistent corpse retaining the ResourceSupply element of the parent.
let cmpTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager);
let templateName = cmpTemplateManager.GetCurrentTemplateName(this.entity);
- let corpse;
- if (leaveResources)
- corpse = Engine.AddEntity("resource|" + templateName);
- else
- corpse = Engine.AddLocalEntity("corpse|" + templateName);
-
- // Copy various parameters so it looks just like us
-
- let cmpCorpsePosition = Engine.QueryInterface(corpse, IID_Position);
- let pos = cmpPosition.GetPosition();
- cmpCorpsePosition.JumpTo(pos.x, pos.z);
- let rot = cmpPosition.GetRotation();
- cmpCorpsePosition.SetYRotation(rot.y);
- cmpCorpsePosition.SetXZRotation(rot.x, rot.z);
-
- let cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership);
- let cmpCorpseOwnership = Engine.QueryInterface(corpse, IID_Ownership);
- cmpCorpseOwnership.SetOwner(cmpOwnership.GetOwner());
+ let corpse = this.CreateDeathSpawnedEntity((leaveResources ? "resource|" : "corpse|") + templateName, !leaveResources);
+ if (corpse == INVALID_ENTITY)
+ return INVALID_ENTITY;
let cmpVisual = Engine.QueryInterface(this.entity, IID_Visual);
let cmpCorpseVisual = Engine.QueryInterface(corpse, IID_Visual);
@@ -351,7 +338,32 @@
return corpse;
};
-Health.prototype.CreateDeathSpawnedEntity = function()
+Health.prototype.CreateDeathSpawnedSlot = function(entityTemplate)
+{
+ let spawnedEntity = this.CreateDeathSpawnedEntity(entityTemplate, false);
+ if (spawnedEntity == INVALID_ENTITY)
+ return INVALID_ENTITY;
+
+ 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());
+
+ return spawnedEntity;
+};
+
+Health.prototype.CreateDeathSpawnedEntity = function(entityTemplate, isLocal = true)
{
// 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
@@ -360,15 +372,20 @@
return INVALID_ENTITY;
// Create SpawnEntityOnDeath entity
- let spawnedEntity = Engine.AddLocalEntity(this.template.SpawnEntityOnDeath);
+ let spawnedEntity = isLocal ? Engine.AddLocalEntity(entityTemplate) : Engine.AddEntity(entityTemplate);
// Move to same position
let cmpSpawnedPosition = Engine.QueryInterface(spawnedEntity, IID_Position);
- let pos = cmpPosition.GetPosition();
- cmpSpawnedPosition.JumpTo(pos.x, pos.z);
- let rot = cmpPosition.GetRotation();
- cmpSpawnedPosition.SetYRotation(rot.y);
- cmpSpawnedPosition.SetXZRotation(rot.x, rot.z);
+ 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 cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership);
let cmpSpawnedOwnership = Engine.QueryInterface(spawnedEntity, IID_Ownership);
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
@@ -26,6 +26,7 @@
this.preview = this.template.Preview == "true";
this.activated = false;
+ this.hidden = false;
if (this.preview || this.corpse)
this.SetActivated(true);
@@ -60,6 +61,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
@@ -94,4 +98,14 @@
return this.alwaysVisible;
};
+Visibility.prototype.SetHidden = function(hidden)
+{
+ this.hidden = hidden;
+};
+
+Visibility.prototype.IsHidden = function()
+{
+ return this.hidden;
+};
+
Engine.RegisterComponentType(IID_Visibility, "Visibility", Visibility);
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
@@ -36,6 +36,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
@@ -1193,13 +1193,13 @@
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("[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;
@@ -1250,7 +1250,9 @@
}
lastTowerControlGroup = cmpSnappedStartObstruction.GetControlGroup();
- //warn("setting lastTowerControlGroup to control group of start snapped entity " + cmd.startSnappedEntity + ": " + lastTowerControlGroup);
+ // Set different control groups to delete upon construction.
+ if (cmd.rebuildStartTower)
+ cmpSnappedStartObstruction.SetControlGroup(0);
}
var i = 0;
@@ -1314,15 +1316,15 @@
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
- // TODO: ensure that the previous obstruction does not yet have a secondary control group set
- cmpPreviousObstruction.SetControlGroup2(newTowerControlGroup);
+ let cmpPreviousObstruction = Engine.QueryInterface(pieces[i - 1].ent, IID_Obstruction);
+ let previousGroup2 = cmpPreviousObstruction.GetControlGroup2();
+ if(previousGroup2 == INVALID_ENTITY && cmpPreviousObstruction)
+ cmpPreviousObstruction.SetControlGroup2(newTowerControlGroup);
}
- // TODO: ensure that cmpTowerObstruction exists
- cmpTowerObstruction.SetControlGroup(newTowerControlGroup); // give the tower its own unique control group
+ // If we are not rebuilding it, give the tower its unique control group.
+ if (!cmd.rebuildStartTower && cmpTowerObstruction)
+ cmpTowerObstruction.SetControlGroup(newTowerControlGroup);
lastTowerIndex = i;
lastTowerControlGroup = newTowerControlGroup;
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/structures/palisades_tower.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/palisades_tower.xml
+++ binaries/data/mods/public/simulation/templates/structures/palisades_tower.xml
@@ -12,6 +12,7 @@
0.75
+ slots/slot_palisade_tower
structures/wallset_palisade
Index: binaries/data/mods/public/simulation/templates/structures/wallset_palisade.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/wallset_palisade.xml
+++ binaries/data/mods/public/simulation/templates/structures/wallset_palisade.xml
@@ -17,6 +17,7 @@
structures/palisades_short
structures/palisades_curve
structures/palisades_end
+ slots/slot_palisade_tower
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,61 @@
+
+
+
+ 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
+
+
+ 0
+
+
Index: binaries/data/mods/public/simulation/templates/template_structure_defensive_palisade.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/template_structure_defensive_palisade.xml
+++ binaries/data/mods/public/simulation/templates/template_structure_defensive_palisade.xml
@@ -15,6 +15,7 @@
1000
decay|rubble/rubble_stone_2x2
+ true
Palisade
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
@@ -49,6 +49,8 @@
4000
decay|rubble/rubble_stone_wall_tower
+ slots/slot_wall_tower
+ true
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
@@ -20,6 +20,9 @@
false
+
+ slots/slot_wall_tower
+
0.85
0.05
Index: source/simulation2/components/CCmpRangeManager.cpp
===================================================================
--- source/simulation2/components/CCmpRangeManager.cpp
+++ source/simulation2/components/CCmpRangeManager.cpp
@@ -1600,15 +1600,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);
@@ -1627,7 +1618,10 @@
return cmpVisibility->GetVisibility(player, los.IsVisible(i, j), los.IsExplored(i, j));
}
- // Else, default behavior
+ // Else, default behavior.
+ // Reveal flag makes all positioned entities visible and all mirages useless.
+ if (GetLosRevealAll(player))
+ return LosIsOffWorld(i, j) || cmpMirage ? VIS_HIDDEN : VIS_VISIBLE;
if (los.IsVisible(i, j))
{