Index: binaries/data/mods/public/gui/session/selection_details.js
===================================================================
--- binaries/data/mods/public/gui/session/selection_details.js (révision 13775)
+++ binaries/data/mods/public/gui/session/selection_details.js (copie de travail)
@@ -166,6 +166,15 @@
getGUIObjectByName("resourceCarryingText").caption = entState.resourceSupply.gatherers.length + " / " + entState.resourceSupply.maxGatherers + " ";
getGUIObjectByName("resourceCarryingIcon").tooltip = "Current/max gatherers";
}
+ // And for number of corraled animals
+ else if (entState.corral)
+ {
+ getGUIObjectByName("resourceCarryingIcon").hidden = false;
+ getGUIObjectByName("resourceCarryingText").hidden = false;
+ getGUIObjectByName("resourceCarryingIcon").sprite = "stretched:session/portraits/structures/corral.png";
+ getGUIObjectByName("resourceCarryingText").caption = entState.corral.entities.length + " / " + entState.corral.capacity + " ";
+ getGUIObjectByName("resourceCarryingIcon").tooltip = "Current/max corraled animals";
+ }
else
{
getGUIObjectByName("resourceCarryingIcon").hidden = true;
Index: binaries/data/mods/public/gui/session/input.js
===================================================================
--- binaries/data/mods/public/gui/session/input.js (révision 13775)
+++ binaries/data/mods/public/gui/session/input.js (copie de travail)
@@ -248,6 +248,16 @@
if (targetState.garrisonHolder.entities.length >= targetState.garrisonHolder.capacity)
tooltip = "[color=\"orange\"]" + tooltip + "[/color]";
}
+ else if (targetState.corral)
+ {
+ data.command = "corral";
+ data.target = target;
+ cursor = "action-gather-milk";
+ tooltip = "Current corraled: " + targetState.corral.entities.length
+ + "/" + targetState.corral.capacity;
+ if (targetState.corral.entities.length >= targetState.corral.capacity)
+ tooltip = "[color=\"orange\"]" + tooltip + "[/color]";
+ }
else if (targetState.resourceSupply)
{
var resourceType = targetState.resourceSupply.type;
@@ -349,6 +359,16 @@
}
}
break;
+ case "corral":
+ if (hasClass(entState, "Unit") && targetState.corral)
+ {
+ var tooltip = "Current corraled: " + targetState.corral.entities.length
+ + "/" + targetState.corral.capacity;
+ if (targetState.corral.entities.length >= targetState.corral.capacity)
+ tooltip = "[color=\"orange\"]" + tooltip + "[/color]";
+ return {"possible": Engine.GuiInterfaceCall("CanBeCorraled", {"entity": entState.id, "corral": target}), "tooltip": tooltip};
+ }
+ break;
case "setup-trade-route":
// If ground or sea trade possible
if (!targetState.foundation && ((entState.trader && hasClass(entState, "Organic") && (playerOwned || allyOwned) && hasClass(targetState, "Market")) ||
@@ -515,6 +535,10 @@
{
return {"type": "garrison", "cursor": "action-garrison", "tooltip": actionInfo.tooltip, "target": target};
}
+ else if (Engine.HotkeyIsPressed("session.corral") && (actionInfo = getActionInfo("corral", target)).possible)
+ {
+ return {"type": "corral", "cursor": "action-gather-milk", "tooltip": actionInfo.tooltip, "target": target};
+ }
else if (Engine.HotkeyIsPressed("session.attackmove") && getActionInfo("attack-move", target).possible)
{
return {"type": "attack-move", "cursor": "action-attack-move"};
@@ -1397,6 +1421,11 @@
Engine.GuiInterfaceCall("PlaySound", { "name": "order_garrison", "entity": selection[0] });
return true;
+ case "corral":
+ Engine.PostNetworkCommand({"type": "corral", "entities": selection, "target": action.target, "queued": queued});
+ Engine.GuiInterfaceCall("PlaySound", { "name": "order_corral", "entity": selection[0] });
+ return true;
+
case "set-rallypoint":
var pos = undefined;
// if there is a position set in the action then use this so that when setting a
Index: binaries/data/mods/public/gui/session/session.xml
===================================================================
--- binaries/data/mods/public/gui/session/session.xml (révision 13775)
+++ binaries/data/mods/public/gui/session/session.xml (copie de travail)
@@ -997,7 +997,7 @@
-
+
Index: binaries/data/mods/public/simulation/templates/template_structure_resource_corral.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/template_structure_resource_corral.xml (révision 13775)
+++ binaries/data/mods/public/simulation/templates/template_structure_resource_corral.xml (copie de travail)
@@ -10,14 +10,10 @@
5.0
-
- 10
- 0.1
- true
- Animal
- 1
- 2
-
+
+ 10
+ 6
+
500
rubble/rubble_2x4
Index: binaries/data/mods/public/simulation/templates/gaia/fauna_sheep.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/gaia/fauna_sheep.xml (révision 13775)
+++ binaries/data/mods/public/simulation/templates/gaia/fauna_sheep.xml (copie de travail)
@@ -12,6 +12,10 @@
Domestic
gaia/fauna_sheep.png
+
+ food
+ 0.4
+
pitch
Index: binaries/data/mods/public/simulation/templates/gaia/fauna_pig.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/gaia/fauna_pig.xml (révision 13775)
+++ binaries/data/mods/public/simulation/templates/gaia/fauna_pig.xml (copie de travail)
@@ -5,6 +5,10 @@
Pig
gaia/fauna_pig.png
+
+ food
+ 0.4
+
pitch
Index: binaries/data/mods/public/simulation/helpers/Commands.js
===================================================================
--- binaries/data/mods/public/simulation/helpers/Commands.js (révision 13775)
+++ binaries/data/mods/public/simulation/helpers/Commands.js (copie de travail)
@@ -319,6 +319,12 @@
}
break;
+ case "corral":
+ GetFormationUnitAIs(entities, player).forEach(function(cmpUnitAI) {
+ cmpUnitAI.SetCorraled(cmd.target, cmd.queued);
+ });
+ break;
+
case "stop":
GetFormationUnitAIs(entities, player).forEach(function(cmpUnitAI) {
cmpUnitAI.Stop(cmd.queued);
Index: binaries/data/mods/public/simulation/helpers/RallyPointCommands.js
===================================================================
--- binaries/data/mods/public/simulation/helpers/RallyPointCommands.js (révision 13775)
+++ binaries/data/mods/public/simulation/helpers/RallyPointCommands.js (copie de travail)
@@ -60,6 +60,14 @@
"queued": true
});
break;
+ case "corral":
+ ret.push( {
+ "type": "corral",
+ "entities": spawnedEnts,
+ "target": data[i].target,
+ "queued": true
+ });
+ break;
case "trade":
ret.push( {
"type": "setup-trade-route",
Index: binaries/data/mods/public/simulation/components/GuiInterface.js
===================================================================
--- binaries/data/mods/public/simulation/components/GuiInterface.js (révision 13775)
+++ binaries/data/mods/public/simulation/components/GuiInterface.js (copie de travail)
@@ -291,18 +291,27 @@
}
var cmpResourceSupply = Engine.QueryInterface(ent, IID_ResourceSupply);
- if (cmpResourceSupply)
+ if (cmpResourceSupply)
+ {
+ ret.resourceSupply = {
+ "isInfinite": cmpResourceSupply.IsInfinite(),
+ "max": cmpResourceSupply.GetMaxAmount(),
+ "amount": cmpResourceSupply.GetCurrentAmount(),
+ "type": cmpResourceSupply.GetType(),
+ "killBeforeGather": cmpResourceSupply.GetKillBeforeGather(),
+ "maxGatherers": cmpResourceSupply.GetMaxGatherers(),
+ "gatherers": cmpResourceSupply.GetGatherers()
+ };
+ }
+
+ var cmpCorral = Engine.QueryInterface(ent, IID_Corral);
+ if (cmpCorral)
{
- ret.resourceSupply = {
- "isInfinite": cmpResourceSupply.IsInfinite(),
- "max": cmpResourceSupply.GetMaxAmount(),
- "amount": cmpResourceSupply.GetCurrentAmount(),
- "type": cmpResourceSupply.GetType(),
- "killBeforeGather": cmpResourceSupply.GetKillBeforeGather(),
- "maxGatherers": cmpResourceSupply.GetMaxGatherers(),
- "gatherers": cmpResourceSupply.GetGatherers()
- };
- }
+ ret.corral = {
+ "entities": cmpCorral.GetEntities(),
+ "capacity": cmpCorral.GetCapacity()
+ };
+ }
var cmpResourceGatherer = Engine.QueryInterface(ent, IID_ResourceGatherer);
if (cmpResourceGatherer)
@@ -1716,6 +1725,15 @@
return cmpAttack.CanAttack(data.target);
};
+GuiInterface.prototype.CanBeCorraled = function(player, data)
+{
+ var cmpCorral = Engine.QueryInterface(data.corral, IID_Corral);
+ if (!cmpCorral)
+ return false;
+
+ return cmpCorral.CanBeCorraled(data.entity);
+};
+
/*
* Returns batch build time.
*/
@@ -1801,6 +1819,7 @@
"GetTradingRouteGain": 1,
"GetTradingDetails": 1,
"CanAttack": 1,
+ "CanBeCorraled": 1,
"GetBatchTime": 1,
"SetPathfinderDebugOverlay": 1,
Index: binaries/data/mods/public/simulation/components/interfaces/Corral.js
===================================================================
--- binaries/data/mods/public/simulation/components/interfaces/Corral.js (révision 0)
+++ binaries/data/mods/public/simulation/components/interfaces/Corral.js (copie de travail)
@@ -0,0 +1,5 @@
+Engine.RegisterInterface("Corral");
+
+// Message of the form { },
+// sent to the current entity whenever the corraled units change.
+Engine.RegisterMessageType("CorraledUnitsChanged");
Index: binaries/data/mods/public/simulation/components/Corral.js
===================================================================
--- binaries/data/mods/public/simulation/components/Corral.js (révision 0)
+++ binaries/data/mods/public/simulation/components/Corral.js (copie de travail)
@@ -0,0 +1,162 @@
+function Corral() {}
+
+Corral.prototype.Schema =
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "";
+
+Corral.prototype.Init = function()
+{
+ this.entities = [];
+ this.increment = 1;
+ this.timer = undefined;
+};
+
+Corral.prototype.GetCapacity = function()
+{
+ return +this.template.MaxCapacity;
+};
+
+Corral.prototype.GetEntities = function()
+{
+ return this.entities;
+};
+
+Corral.prototype.GetRange = function()
+{
+ return +this.template.Range;
+};
+
+/**
+ * Returns true if the entity ent can be corraled inside,
+ */
+Corral.prototype.CanBeCorraled = function(ent)
+{
+ var cmpUnitAI = Engine.QueryInterface(ent, IID_UnitAI);
+ if (!cmpUnitAI)
+ return false;
+ // Formation controllers should always respond to commands
+ if (cmpUnitAI.IsFormationController())
+ return true;
+
+ // The entity must have a corral type not null
+ var entType = cmpUnitAI.GetCorralType();
+ if (entType == null)
+ return false;
+ // And if there is already a corraled unit, it must have the same type
+ var type = this.GetType();
+ if (type != null && type != entType)
+ return false;
+ return true;
+};
+
+Corral.prototype.AddCorraled = function(ent)
+{
+ if (this.entities.indexOf(ent) != -1 || this.entities.length >= this.GetCapacity())
+ return false;
+ this.entities.push(ent);
+ Engine.PostMessage(this.entity, MT_CorraledUnitsChanged, {});
+ return true;
+};
+
+Corral.prototype.RemoveCorraled = function(ent)
+{
+ if (this.entities.indexOf(ent) == -1)
+ return;
+ this.entities.splice(this.entities.indexOf(ent), 1);
+ Engine.PostMessage(this.entity, MT_CorraledUnitsChanged, {});
+};
+
+Corral.prototype.GetRate = function()
+{
+ var rate = 0;
+ for each (var ent in this.entities)
+ {
+ var cmpUnitAI = Engine.QueryInterface(ent, IID_UnitAI);
+ rate += cmpUnitAI.GetCorralRate();
+ }
+ rate = ApplyTechModificationsToEntity("Corral/Rate", rate, this.entity);
+ return rate;
+}
+
+Corral.prototype.GetType = function()
+{
+ var type = null;
+ if (this.entities.length > 0)
+ {
+ var cmpUnitAI = Engine.QueryInterface(this.entities[0], IID_UnitAI);
+ type= cmpUnitAI.GetCorralType();
+ }
+ return type;
+}
+
+/**
+ * Called every second. Produce food (in corrals)
+ */
+Corral.prototype.Timeout = function(data)
+{
+ var type = this.GetType();
+ var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
+ if (type != null)
+ {
+ var cmpPlayer = QueryOwnerInterface(this.entity, IID_Player);
+ cmpPlayer.AddResource(type, this.increment);
+ var cmpStatisticsTracker = QueryOwnerInterface(this.entity, IID_StatisticsTracker);
+ if (cmpStatisticsTracker)
+ cmpStatisticsTracker.IncreaseResourceGatheredCounter(type, this.increment);
+
+ var rate = this.GetRate();
+ this.increment = this.entities.length;
+ this.timer = cmpTimer.SetTimeout(this.entity, IID_Corral, "Timeout", this.increment*1000/rate, {});
+ }
+ else
+ {
+ cmpTimer.CancelTimer(this.timer);
+ this.timer = undefined;
+ }
+};
+
+
+Corral.prototype.OnCorraledUnitsChanged = function(msg)
+{
+ // first clear the cache for technology modifications (the total rate has changed)
+ var cmpTechMan = QueryOwnerInterface(this.entity, IID_TechnologyManager);
+ if (cmpTechMan)
+ cmpTechMan.clearModificationCache(this.entity);
+
+ if (this.entities.length > 0 && !this.timer)
+ {
+ var rate = this.GetRate();
+ this.increment = this.entities.length;
+ var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
+ this.timer = cmpTimer.SetTimeout(this.entity, IID_Corral, "Timeout", this.increment*1000/rate, {});
+ }
+ else if (this.entities.length == 0 && this.timer)
+ {
+ var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
+ cmpTimer.CancelTimer(this.timer);
+ this.timer = undefined;
+ }
+};
+
+Corral.prototype.OnDestroy = function()
+{
+ if (this.timer)
+ {
+ var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
+ cmpTimer.CancelTimer(this.timer);
+ }
+
+ for (var i = this.entities.length; i > 0; --i)
+ {
+ var cmpUnitAI = Engine.QueryInterface(this.entities[i-1], IID_UnitAI);
+ if (cmpUnitAI)
+ cmpUnitAI.UnsetCorraled();
+ }
+};
+
+
+Engine.RegisterComponentType(IID_Corral, "Corral", Corral);
Index: binaries/data/mods/public/simulation/components/UnitAI.js
===================================================================
--- binaries/data/mods/public/simulation/components/UnitAI.js (révision 13775)
+++ binaries/data/mods/public/simulation/components/UnitAI.js (copie de travail)
@@ -46,6 +46,19 @@
"" +
""+
"" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "food" +
+ "metal" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
"";
// Unit stances.
@@ -620,6 +633,26 @@
}
},
+ "Order.Corral": function(msg) {
+ var cmpCorral = Engine.QueryInterface(msg.data.target, IID_Corral);
+ if (!cmpCorral)
+ {
+ this.FinishOrder();
+ return;
+ }
+
+ var range = cmpCorral.GetRange();
+ if (this.MoveToTargetRangeExplicit(this.order.data.target, 0, range))
+ {
+ this.SetNextState("ANIMAL.CORRAL.APPROACHING");
+ }
+ else
+ {
+ this.StopMoving();
+ this.SetNextState("ANIMAL.CORRAL.CORRALED");
+ }
+ },
+
"Order.Cheering": function(msg) {
this.SetNextState("INDIVIDUAL.CHEERING");
},
@@ -905,6 +938,14 @@
this.SetNextStateAlwaysEntering("MEMBER");
},
+ "Order.Corral": function(msg) {
+ var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation);
+ cmpFormation.SetRearrange(false);
+ cmpFormation.CallMemberFunction("SetCorraled", [msg.data.target, false]);
+
+ this.SetNextStateAlwaysEntering("MEMBER");
+ },
+
"IDLE": {
},
@@ -2382,6 +2423,27 @@
this.SetNextState("FLEEING");
},
+
+ "Order.Corral": function(msg) {
+ var cmpCorral = Engine.QueryInterface(msg.data.target, IID_Corral);
+ if (!cmpCorral)
+ {
+ this.FinishOrder();
+ return;
+ }
+
+ var range = cmpCorral.GetRange();
+ if (this.MoveToTargetRangeExplicit(this.order.data.target, 0, range))
+ {
+ this.SetNextState("ANIMAL.CORRAL.APPROACHING");
+ }
+ else
+ {
+ this.StopMoving();
+ this.SetNextState("ANIMAL.CORRAL.CORRALED");
+ }
+ },
+
"IDLE": {
// (We need an IDLE state so that FinishOrder works)
@@ -2392,6 +2454,53 @@
},
},
+ 'CORRAL': {
+ 'APPROACHING': {
+ "MoveCompleted": function() {
+ var cmpCorral = Engine.QueryInterface(this.order.data.target, IID_Corral);
+ if (cmpCorral)
+ {
+ var range = cmpCorral.GetRange();
+ var cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion);
+ if (cmpUnitMotion.IsInTargetRange(this.order.data.target, 0, range))
+ {
+ this.SetNextState("ANIMAL.CORRAL.CORRALED");
+ return;
+ }
+ }
+ this.FinishOrder();
+ },
+ },
+
+ 'CORRALED': {
+ "enter": function() {
+ this.corral = this.order.data.target;
+ var cmpCorral = Engine.QueryInterface(this.corral, IID_Corral);
+ if (!cmpCorral || !cmpCorral.AddCorraled(this.entity))
+ {
+ this.SetNextState("ROAMING");
+ return true;
+ }
+ this.SelectAnimation("feeding");
+ return false;
+ },
+
+ "Order.UnsetCorraled": function() {
+ this.FinishOrder();
+ },
+
+ "leave": function() {
+ if (this.corral)
+ {
+ var cmpCorral = Engine.QueryInterface(this.corral, IID_Corral);
+ if (cmpCorral)
+ cmpCorral.RemoveCorraled(this.entity);
+ delete this.corral;
+ }
+ },
+ },
+ },
+
"ROAMING": {
"enter": function() {
// Walk in a random direction
@@ -3781,6 +3890,7 @@
case "ReturnResource":
case "Repair":
case "Garrison":
+ case "Corral":
// Find the target unit's position
var cmpTargetPosition = Engine.QueryInterface(order.data.target, IID_Position);
if (!cmpTargetPosition || !cmpTargetPosition.IsInWorld())
@@ -4521,6 +4631,39 @@
//// Animal specific functions ////
+/**
+ * Adds setcorraled order to the queue, forced by the player.
+ */
+UnitAI.prototype.SetCorraled = function(target, queued)
+{
+ var cmpCorral = Engine.QueryInterface(target, IID_Corral);
+ if (!cmpCorral || !cmpCorral.CanBeCorraled(this.entity))
+ {
+ this.WalkToTarget(target, queued);
+ return;
+ }
+ this.AddOrder("Corral", { "target": target, "force": true }, queued);
+};
+
+/**
+ * Adds unsetcorraled order to the queue.
+ */
+UnitAI.prototype.UnsetCorraled = function()
+{
+ if (this.corral)
+ this.AddOrder("UnsetCorraled", null, false);
+};
+
+UnitAI.prototype.GetCorralRate = function()
+{
+ return +(this.template.CorralRate || 0);
+};
+
+UnitAI.prototype.GetCorralType = function()
+{
+ return (this.template.CorralType || null);
+};
+
UnitAI.prototype.MoveRandomly = function(distance)
{
// We want to walk in a random direction, but avoid getting stuck
Index: binaries/data/config/default.cfg
===================================================================
--- binaries/data/config/default.cfg (révision 13775)
+++ binaries/data/config/default.cfg (copie de travail)
@@ -270,6 +270,7 @@
hotkey.session.attack = "Ctrl+Alt" ; Modifier to force attack instead of another action
hotkey.session.garrison = Ctrl ; Modifier to garrison when clicking on building
hotkey.session.attackmove = Ctrl ; Modifier to attackmove when clicking on a point
+hotkey.session.corral = Ctrl ; Modifier to corral an animal
hotkey.session.queue = Shift ; Modifier to queue unit orders instead of replacing
hotkey.session.batchtrain = Shift ; Modifier to train units in batches
hotkey.session.massbarter = Shift ; Modifier to barter bunch of resources