Index: ps/trunk/binaries/data/mods/public/simulation/components/TerritoryDecay.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/TerritoryDecay.js (revision 25457) +++ ps/trunk/binaries/data/mods/public/simulation/components/TerritoryDecay.js (revision 25458) @@ -1,156 +1,171 @@ function TerritoryDecay() {} -TerritoryDecay.prototype.Schema = - "" + - "Infinity" + - ""; +TerritoryDecay.prototype.Schema = ` + + Infinity + + + + + + neutral + enemy + + + + + `; TerritoryDecay.prototype.Init = function() { this.decaying = false; this.connectedNeighbours = new Array(Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager).GetNumPlayers()).fill(0); this.territoryOwnership = !isFinite(+this.template.DecayRate); }; TerritoryDecay.prototype.IsConnected = function() { this.connectedNeighbours.fill(0); var cmpPosition = Engine.QueryInterface(this.entity, IID_Position); if (!cmpPosition || !cmpPosition.IsInWorld()) return false; var cmpPlayer = QueryOwnerInterface(this.entity); if (!cmpPlayer) return true;// something without ownership can't decay + const decayTerritory = ApplyValueModificationsToEntity("TerritoryDecay/Territory", this.template.Territory, this.entity); + var cmpTerritoryManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TerritoryManager); var pos = cmpPosition.GetPosition2D(); var tileOwner = cmpTerritoryManager.GetOwner(pos.x, pos.y); if (tileOwner == 0) { this.connectedNeighbours[0] = 1; - return cmpPlayer.GetPlayerID() == 0; // Gaia building on gaia ground -> don't decay + return cmpPlayer.GetPlayerID() == 0 || decayTerritory.indexOf("neutral") === -1; } var tileConnected = cmpTerritoryManager.IsConnected(pos.x, pos.y); if (tileConnected && !cmpPlayer.IsMutualAlly(tileOwner)) { this.connectedNeighbours[tileOwner] = 1; - return false; + return decayTerritory.indexOf("enemy") === -1; } if (tileConnected) return true; + // Special-case: if the tile is unconnected, non-own territory, decay towards gaia. + // TODO: this is not great, see #4749 if (cmpPlayer.GetPlayerID() != tileOwner) { this.connectedNeighbours[0] = 1; return false; } this.connectedNeighbours = cmpTerritoryManager.GetNeighbours(pos.x, pos.y, true); let numPlayers = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager).GetNumPlayers(); for (var i = 1; i < numPlayers; ++i) if (this.connectedNeighbours[i] > 0 && cmpPlayer.IsMutualAlly(i)) { // don't decay if connected to a connected ally; disable blinking cmpTerritoryManager.SetTerritoryBlinking(pos.x, pos.y, false); return true; } cmpTerritoryManager.SetTerritoryBlinking(pos.x, pos.y, true); return false; }; TerritoryDecay.prototype.IsDecaying = function() { return this.decaying; }; TerritoryDecay.prototype.GetDecayRate = function() { return ApplyValueModificationsToEntity( "TerritoryDecay/DecayRate", +this.template.DecayRate, this.entity); }; /** * Get the number of connected bordering tiles to this region * Only valid when this.IsDecaying() */ TerritoryDecay.prototype.GetConnectedNeighbours = function() { return this.connectedNeighbours; }; TerritoryDecay.prototype.UpdateDecayState = function() { let decaying = !this.IsConnected() && this.GetDecayRate() > 0; if (decaying === this.decaying) return; this.decaying = decaying; Engine.PostMessage(this.entity, MT_TerritoryDecayChanged, { "entity": this.entity, "to": decaying, "rate": this.GetDecayRate() }); }; TerritoryDecay.prototype.UpdateOwner = function() { let cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); let cmpPosition = Engine.QueryInterface(this.entity, IID_Position); if (!cmpOwnership || !cmpPosition || !cmpPosition.IsInWorld()) return; let cmpTerritoryManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TerritoryManager); let pos = cmpPosition.GetPosition2D(); let tileOwner = cmpTerritoryManager.GetOwner(pos.x, pos.y); if (tileOwner != cmpOwnership.GetOwner()) cmpOwnership.SetOwner(tileOwner); }; TerritoryDecay.prototype.OnTerritoriesChanged = function(msg) { if (this.territoryOwnership) this.UpdateOwner(); else this.UpdateDecayState(); }; TerritoryDecay.prototype.OnTerritoryPositionChanged = function(msg) { if (this.territoryOwnership) this.UpdateOwner(); else this.UpdateDecayState(); }; TerritoryDecay.prototype.OnDiplomacyChanged = function(msg) { // Can change the connectedness of certain areas if (!this.territoryOwnership) this.UpdateDecayState(); }; TerritoryDecay.prototype.OnOwnershipChanged = function(msg) { // Update the list of TerritoryDecay components in the manager if (msg.from == INVALID_PLAYER || msg.to == INVALID_PLAYER) { let cmpTerritoryDecayManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TerritoryDecayManager); if (msg.from == INVALID_PLAYER) cmpTerritoryDecayManager.Add(this.entity); else cmpTerritoryDecayManager.Remove(this.entity); } // if it influences the territory, wait until we get a TerritoriesChanged message if (!this.territoryOwnership && !Engine.QueryInterface(this.entity, IID_TerritoryInfluence)) this.UpdateDecayState(); }; TerritoryDecay.prototype.HasTerritoryOwnership = function() { return this.territoryOwnership; }; Engine.RegisterComponentType(IID_TerritoryDecay, "TerritoryDecay", TerritoryDecay); Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_structure.xml =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/templates/template_structure.xml (revision 25457) +++ ps/trunk/binaries/data/mods/public/simulation/templates/template_structure.xml (revision 25458) @@ -1,181 +1,182 @@ land own Structure 500 0.5 5.0 0 10 0 0 0 0 false false 0.0 3.0 9.8 0.85 0.65 0.35 corpse 0 0 true gaia Structure Structure false 0 0 0 0 0 structure true true true true false false false false 0 upright false 0 6 1.0 1.0 1.0 1.0 1.0 special/rallypoint art/textures/misc/rallypoint_line.png art/textures/misc/rallypoint_line_mask.png 0.25 square round default 2.0 0.0 1 1 10 1 0.0 1 1 10 1 outline_border.png outline_border_mask.png 0.4 interface/complete/building/complete_universal.xml attack/destruction/building_collapse_large.xml interface/alarm/alarm_attackplayer.xml interface/alarm/alarm_attacked_gaia.xml interface/alarm/alarm_attackplayer.xml interface/alarm/alarm_attacked_gaia.xml 6.0 0.6 12.0 20 + neutral enemy true false false false 4 false false true false Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_territory_pull.xml =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/templates/template_territory_pull.xml (revision 25457) +++ ps/trunk/binaries/data/mods/public/simulation/templates/template_territory_pull.xml (revision 25458) @@ -1,40 +1,41 @@ 5 0 0 0 upright false 0 6 128x128/octagram.png 128x128/octagram_mask.png 5 + neutral enemy false false false false false true props/special/common/waypoint_flag.xml true