Index: binaries/data/mods/public/simulation/components/GarrisonHolder.js
===================================================================
--- binaries/data/mods/public/simulation/components/GarrisonHolder.js
+++ binaries/data/mods/public/simulation/components/GarrisonHolder.js
@@ -31,6 +31,20 @@
"" +
"" +
"" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "own" +
+ "ally" +
+ "neutral" +
+ "enemy" +
+ "" +
+ "" +
+ "
" +
+ "" +
+ "" +
+ "" +
"" +
"" +
"" +
@@ -167,7 +181,7 @@
if (!this.IsGarrisoningAllowed())
return false;
- if (!IsOwnedByMutualAllyOfEntity(ent, this.entity))
+ if (!this.IsAllowedByDiplomacy(ent))
return false;
let cmpIdentity = Engine.QueryInterface(ent, IID_Identity);
@@ -190,6 +204,8 @@
if (!cmpPosition)
return false;
+ // Turn in when visibly garrisoned and the order is given. (D2367)
+
if (!this.PerformGarrison(entity))
return false;
@@ -505,7 +521,24 @@
GarrisonHolder.prototype.HasEnoughHealth = function()
{
let cmpHealth = Engine.QueryInterface(this.entity, IID_Health);
- return cmpHealth.GetHitpoints() > Math.floor(+this.template.EjectHealth * cmpHealth.GetMaxHitpoints());
+ if (cmpHealth)
+ return cmpHealth.GetHitpoints() > Math.floor(+this.template.EjectHealth * cmpHealth.GetMaxHitpoints());
+ return true;
+};
+
+GarrisonHolder.prototype.IsAllowedByDiplomacy = function(ent)
+{
+ if (!this.template.Owners)
+ return IsOwnedByMutualAllyOfEntity(ent, this.entity);
+
+ let owner = INVALID_PLAYER;
+ let cmpOwner = Engine.QueryInterface(this.entity, IID_Ownership);
+ if (cmpOwner)
+ owner = cmpOwner.GetOwner();
+ return this.template.Owners.indexOf("own") != -1 && IsOwnedByPlayer(owner, ent) ||
+ this.template.Owners.indexOf("ally") != -1 && IsOwnedByMutualAllyOfEntity(this.entity, ent) ||
+ this.template.Owners.indexOf("neutral") != -1 && IsOwnedByNeutralOfEntity(this.entity, ent) ||
+ this.template.Owners.indexOf("enemy") != -1 && IsOwnedByEnemyOfEntity(this.entity, ent);
};
/**
@@ -564,7 +597,7 @@
// The ownership change may be on the garrisonholder
if (this.entity == msg.entity)
{
- let entities = this.entities.filter(ent => msg.to == INVALID_PLAYER || !IsOwnedByMutualAllyOfEntity(this.entity, ent));
+ let entities = this.entities.filter(ent => msg.to == INVALID_PLAYER || !this.IsAllowedByDiplomacy(ent));
if (entities.length)
this.EjectOrKill(entities);
@@ -588,7 +621,7 @@
if (point.entity == msg.entity)
point.entity = null;
}
- else if (msg.to == INVALID_PLAYER || !IsOwnedByMutualAllyOfEntity(this.entity, msg.entity))
+ else if (msg.to == INVALID_PLAYER || !this.IsAllowedByDiplomacy(msg.entity))
this.EjectOrKill([msg.entity]);
}
};
@@ -636,7 +669,7 @@
*/
GarrisonHolder.prototype.OnDiplomacyChanged = function()
{
- this.EjectOrKill(this.entities.filter(ent => !IsOwnedByMutualAllyOfEntity(this.entity, ent)));
+ this.EjectOrKill(this.entities.filter(ent => !this.IsAllowedByDiplomacy(ent)));
};
/**
Index: binaries/data/mods/public/simulation/components/ResourceSupply.js
===================================================================
--- binaries/data/mods/public/simulation/components/ResourceSupply.js
+++ binaries/data/mods/public/simulation/components/ResourceSupply.js
@@ -25,6 +25,11 @@
"" +
"" +
"" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
"";
ResourceSupply.prototype.Init = function()
@@ -42,6 +47,15 @@
this.cachedType = { "generic": type, "specific": subtype };
};
+ResourceSupply.prototype.IsMine = function()
+{
+ let cmpGarrisonHolder = Engine.QueryInterface(this.entity, IID_GarrisonHolder);
+ if (!cmpGarrisonHolder)
+ return false;
+
+ return this.template.Mine && this.template.Mine == "true";
+};
+
ResourceSupply.prototype.IsInfinite = function()
{
return !isFinite(+this.template.Amount);
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
@@ -2216,6 +2216,17 @@
{
this.StopMoving();
this.SetDefaultAnimationVariant();
+
+ if (cmpSupply.IsMine())
+ {
+ let cmpGarrisonHolder = Engine.QueryInterface(this.gatheringTarget, IID_GarrisonHolder);
+ if (!cmpGarrisonHolder || !cmpGarrisonHolder.Garrison(this.entity))
+ {
+ this.FinishOrder();
+ return true;
+ }
+ this.isGarrisoned = true;
+ }
this.FaceTowardsTarget(this.order.data.target);
this.SelectAnimation("gather_" + this.order.data.type.specific);
}
@@ -2238,6 +2249,7 @@
},
"Timer": function(msg) {
+ let orderData = this.order.data;
let resourceTemplate = this.order.data.template;
let resourceType = this.order.data.type;
@@ -2259,7 +2271,7 @@
return;
}
- if (!this.CheckTargetRange(this.gatheringTarget, IID_ResourceGatherer))
+ if (!this.CheckTargetRange(this.gatheringTarget, IID_ResourceGatherer) && !cmpSupply.IsMine())
{
// Try to follow the target
if (this.MoveToTargetRange(this.gatheringTarget, IID_ResourceGatherer))
@@ -2299,6 +2311,12 @@
// return to the nearest dropsite
if (status.filled)
{
+ if (cmpSupply.IsMine())
+ {
+ let cmpGarrisonHolder = Engine.QueryInterface(this.gatheringTarget, IID_GarrisonHolder);
+ if (cmpGarrisonHolder && !cmpGarrisonHolder.Unload(this.entity))
+ return;
+ }
let nearby = this.FindNearestDropsite(resourceType.generic);
if (nearby)
{
@@ -2307,8 +2325,12 @@
// However mark our target as invalid if it's exhausted, so we don't waste time
// trying to gather from it.
if (status.exhausted)
- this.order.data.target = INVALID_ENTITY;
+ this.order ? this.order.data.target = INVALID_ENTITY : orderData.target = INVALID_ENTITY;
this.PushOrderFront("ReturnResource", { "target": nearby, "force": false });
+
+ // Needed because the ungarrison order clears the order queue.
+ if (cmpSupply.IsMine())
+ this.PushOrder("Gather", orderData);
return;
}
@@ -2319,7 +2341,17 @@
// Find a new target if the current one is exhausted
if (status.exhausted)
+ {
+ if (cmpSupply.IsMine())
+ {
+ let cmpGarrisonHolder = Engine.QueryInterface(this.gatheringTarget, IID_GarrisonHolder);
+ if (cmpGarrisonHolder && !cmpGarrisonHolder.Unload(this.entity))
+ return;
+ orderData.target = INVALID_ENTITY;
+ this.PushOrder("Gather", orderData);
+ }
this.SetNextState("FINDINGNEWTARGET");
+ }
},
},
@@ -2952,13 +2984,13 @@
delete this.pickup;
}
- if (this.IsTurret())
- {
- this.SetNextState("IDLE");
+ //if (this.IsTurret())
+ //{
+ this.FinishOrder();
return true;
- }
+ //}
- return false;
+ //return false;
}
}
else
@@ -5781,27 +5813,32 @@
UnitAI.prototype.CanGather = function(target)
{
- if (this.IsTurret())
- return false;
// The target must be a valid resource supply, or the mirage of one.
- var cmpResourceSupply = QueryMiragedInterface(target, IID_ResourceSupply);
+ let cmpResourceSupply = QueryMiragedInterface(target, IID_ResourceSupply);
if (!cmpResourceSupply)
return false;
- // Formation controllers should always respond to commands
+ // Formation controllers should always respond to commands.
// (then the individual units can make up their own minds)
if (this.IsFormationController())
return true;
- // Verify that we're able to respond to Gather commands
- var cmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer);
+ // Verify that we're able to respond to Gather commands.
+ let cmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer);
if (!cmpResourceGatherer)
return false;
- // Verify that we can gather from this target
+ // Verify that we can gather from this target.
if (!cmpResourceGatherer.GetTargetGatherRate(target))
return false;
+ // If we're a turret and can gather from our parent its okay.
+ if (this.IsTurret())
+ {
+ let cmpPosition = Engine.QueryInterface(this.entity, IID_Position);
+ return cmpPosition && cmpPosition.GetTurretParent() == target;
+ }
+
// No need to verify ownership as we should be able to gather from
// a target regardless of ownership.
// No need to call "cmpResourceSupply.IsAvailable()" either because that
Index: binaries/data/mods/public/simulation/helpers/Player.js
===================================================================
--- binaries/data/mods/public/simulation/helpers/Player.js
+++ binaries/data/mods/public/simulation/helpers/Player.js
@@ -277,6 +277,16 @@
return IsOwnedByEntityHelper(entity, target, "IsMutualAlly");
}
+function IsOwnedByNeutralOfEntity(entity, target)
+{
+ return IsOwnedByEntityHelper(entity, target, "IsNeutral");
+}
+
+function IsOwnedByEnemyOfEntity(entity, target)
+{
+ return IsOwnedByEntityHelper(entity, target, "IsEnemy");
+}
+
function IsOwnedByEntityHelper(entity, target, check)
{
// Figure out which player controls us
@@ -353,6 +363,8 @@
Engine.RegisterGlobal("QueryBuilderListInterface", QueryBuilderListInterface);
Engine.RegisterGlobal("IsOwnedByAllyOfEntity", IsOwnedByAllyOfEntity);
Engine.RegisterGlobal("IsOwnedByMutualAllyOfEntity", IsOwnedByMutualAllyOfEntity);
+Engine.RegisterGlobal("IsOwnedByNeutralOfEntity", IsOwnedByNeutralOfEntity);
+Engine.RegisterGlobal("IsOwnedByEnemyOfEntity", IsOwnedByEnemyOfEntity);
Engine.RegisterGlobal("IsOwnedByPlayer", IsOwnedByPlayer);
Engine.RegisterGlobal("IsOwnedByGaia", IsOwnedByGaia);
Engine.RegisterGlobal("IsOwnedByAllyOfPlayer", IsOwnedByAllyOfPlayer);
Index: binaries/data/mods/public/simulation/templates/template_gaia_geo_rock.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/template_gaia_geo_rock.xml
+++ binaries/data/mods/public/simulation/templates/template_gaia_geo_rock.xml
@@ -1,5 +1,19 @@
+
+ 12
+ 0
+ Unit
+ Worker
+ 0
+ own ally neutral enemy
+ 1
+
+
+ 011.50
+
+
+
Stone Quarry
Quarry rock for stone.
@@ -11,9 +25,10 @@
false
- 1000
+ 100
stone.rock
12
+ true
Index: binaries/data/mods/public/simulation/templates/template_gaia_geo_rock_slabs.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/template_gaia_geo_rock_slabs.xml
+++ binaries/data/mods/public/simulation/templates/template_gaia_geo_rock_slabs.xml
@@ -8,7 +8,7 @@
- 5000
+ 100
24