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); @@ -505,7 +519,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(this.entity, ent); + + 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 +595,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 +619,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 +667,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) { @@ -2309,6 +2327,8 @@ if (status.exhausted) this.order.data.target = INVALID_ENTITY; this.PushOrderFront("ReturnResource", { "target": nearby, "force": false }); + if (cmpSupply.IsMine()) + this.PushOrder("Gather", orderData); return; } @@ -2319,7 +2339,15 @@ // 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; + } this.SetNextState("FINDINGNEWTARGET"); + } }, }, @@ -5781,8 +5809,6 @@ 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); if (!cmpResourceSupply) 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. @@ -14,6 +28,7 @@ 1000 stone.rock 12 + true