Ticket #996: capture.diff
File capture.diff, 35.8 KB (added by , 9 years ago) |
---|
-
binaries/data/mods/public/gui/common/tooltips.js
140 140 if (type === "Charge") return translate("Charge Attack:"); 141 141 if (type === "Melee") return translate("Melee Attack:"); 142 142 if (type === "Ranged") return translate("Ranged Attack:"); 143 if (type === "Capture") return translate("Capture Attack:"); 143 144 144 145 warn(sprintf("Internationalization: Unexpected attack type found with code ‘%(attackType)s’. This attack type must be internationalized.", { attackType: type })); 145 146 return translate("Attack:"); … … 169 170 }); 170 171 171 172 var attackLabel = txtFormats.header[0] + getAttackTypeLabel(type) + txtFormats.header[1]; 173 if (type == "Capture") 174 { 175 attacks.push(sprintf(translate("%(attackLabel)s %(details)s, %(rate)s"), { 176 attackLabel: attackLabel, 177 details: template.attack[type].value, 178 rate: rate 179 })); 180 continue; 181 } 172 182 if (type != "Ranged") 173 183 { 174 184 attacks.push(sprintf(translate("%(attackLabel)s %(details)s, %(rate)s"), { -
binaries/data/mods/public/gui/session/selection_details.js
86 86 Engine.GetGUIObjectByName("healthSection").hidden = true; 87 87 } 88 88 89 // TODO: Stamina 90 var player = Engine.GetPlayerID(); 91 if (entState.stamina && (entState.player == player || g_DevSettings.controlAll)) 92 Engine.GetGUIObjectByName("staminaSection").hidden = false; 89 // CapturePoints 90 if (entState.capturePoints) 91 { 92 var size = 0; 93 for (let i in entState.capturePoints) 94 { 95 var unitCaptureBar = Engine.GetGUIObjectByName("captureBar"+i); 96 var sizeObj = unitCaptureBar.size; 97 sizeObj.rleft = size; 98 99 size += 100*Math.max(0, Math.min(1, entState.capturePoints[i] / entState.maxCapturePoints)); 100 sizeObj.rright = size; 101 unitCaptureBar.size = sizeObj; 102 let c = g_Players[i].color; 103 104 unitCaptureBar.sprite = "color: " + c.r + " " + c.g + " " + c.b + " 128"; 105 } 106 107 // TODO determinte stats format 108 Engine.GetGUIObjectByName("captureStats").caption = translate("Capture points"); 109 Engine.GetGUIObjectByName("captureSection").hidden = false; 110 } 93 111 else 94 Engine.GetGUIObjectByName("staminaSection").hidden = true; 112 { 113 Engine.GetGUIObjectByName("captureSection").hidden = true; 114 } 95 115 116 // TODO: Stamina 117 96 118 // Experience 97 119 if (entState.promotion) 98 120 { … … 136 158 Engine.GetGUIObjectByName("resourceStats").caption = resources; 137 159 138 160 if (entState.hitpoints) 139 Engine.GetGUIObjectByName("resourceSection").size = Engine.GetGUIObjectByName(" staminaSection").size;161 Engine.GetGUIObjectByName("resourceSection").size = Engine.GetGUIObjectByName("captureSection").size; 140 162 else 141 163 Engine.GetGUIObjectByName("resourceSection").size = Engine.GetGUIObjectByName("healthSection").size; 142 164 -
binaries/data/mods/public/gui/session/selection_panels_middle/single_details_area.xml
20 20 </object> 21 21 </object> 22 22 23 <!-- Staminabar -->24 <object size="88 28 100% 52" name=" staminaSection">25 <object size="0 0 100% 16" name=" staminaLabel" type="text" style="StatsTextLeft" ghost="true">26 <translatableAttribute id="tooltip"> Stamina:</translatableAttribute>23 <!-- Capture bar --> 24 <object size="88 28 100% 52" name="captureSection"> 25 <object size="0 0 100% 16" name="captureLabel" type="text" style="StatsTextLeft" ghost="true"> 26 <translatableAttribute id="tooltip">Capture points:</translatableAttribute> 27 27 </object> 28 <object size="0 0 100% 16" name=" staminaStats" type="text" style="StatsTextRight" ghost="true"/>29 <object size="1 16 100% 23" name=" stamina" type="image">28 <object size="0 0 100% 16" name="captureStats" type="text" style="StatsTextRight" ghost="true"/> 29 <object size="1 16 100% 23" name="capture" type="image"> 30 30 <object type="image" sprite="barBorder" ghost="true" size="-1 -1 100%+1 100%+1"/> 31 <object type="image" sprite="staminaBackground" ghost="true"/> 32 <object type="image" sprite="staminaForeground" ghost="true" name="staminaBar"/> 31 <!-- TODO use repeat --> 32 <object type="image" sprite="playerColorBackground" ghost="true" name="captureBar0"/> 33 <object type="image" sprite="playerColorBackground" ghost="true" name="captureBar1"/> 34 <object type="image" sprite="playerColorBackground" ghost="true" name="captureBar2"/> 35 <object type="image" sprite="playerColorBackground" ghost="true" name="captureBar3"/> 36 <object type="image" sprite="playerColorBackground" ghost="true" name="captureBar4"/> 37 <object type="image" sprite="playerColorBackground" ghost="true" name="captureBar5"/> 38 <object type="image" sprite="playerColorBackground" ghost="true" name="captureBar6"/> 39 <object type="image" sprite="playerColorBackground" ghost="true" name="captureBar7"/> 40 <object type="image" sprite="playerColorBackground" ghost="true" name="captureBar8"/> 33 41 <object type="image" sprite="statsBarShaderHorizontal" ghost="true"/> 34 42 </object> 35 43 </object> -
binaries/data/mods/public/gui/session/unit_actions.js
99 99 { 100 100 if (!entState.attack || !targetState.hitpoints) 101 101 return false; 102 if (playerCheck(entState, targetState, ["Neutral", "Enemy"])) 103 return {"possible": Engine.GuiInterfaceCall("CanAttack", {"entity": entState.id, "target": targetState.id})}; 104 return false; 102 return {"possible": Engine.GuiInterfaceCall("CanAttack", {"entity": entState.id, "target": targetState.id})}; 105 103 }, 106 104 "hotkeyActionCheck": function(target) 107 105 { … … 672 670 "icon": "kill_small.png" 673 671 }; 674 672 673 if (entState.capturePoints && entState.capturePoints[entState.player] < entState.maxCapturePoints / 2) 674 return { 675 "tooltip": translate("You cannot destroy this entity you own less than half the capture points"), 676 "icon": "kill_small.png" 677 }; 678 679 675 680 return { 676 681 "tooltip": translate("Delete"), 677 682 "icon": "kill_small.png" -
binaries/data/mods/public/simulation/components/Attack.js
159 159 "</element>" + 160 160 "</optional>" + 161 161 "<optional>" + 162 "<element name='Capture'>" + 163 "<interleave>" + 164 "<element name='Value' a:help='Capture points value'><ref name='nonNegativeDecimal'/></element>" + 165 "<element name='MaxRange' a:help='Maximum attack range (in metres)'><ref name='nonNegativeDecimal'/></element>" + 166 "<element name='RepeatTime' a:help='Time between attacks (in milliseconds). The attack animation will be stretched to match this time'>" + // TODO: it shouldn't be stretched 167 "<data type='positiveInteger'/>" + 168 "</element>" + 169 Attack.prototype.bonusesSchema + 170 Attack.prototype.preferredClassesSchema + 171 Attack.prototype.restrictedClassesSchema + 172 "</interleave>" + 173 "</element>" + 174 "</optional>" + 175 "<optional>" + 162 176 "<element name='Charge'>" + 163 177 "<interleave>" + 164 178 "<element name='Hack' a:help='Hack damage strength'><ref name='nonNegativeDecimal'/></element>" + … … 198 212 if (this.template.Charge) ret.push("Charge"); 199 213 if (this.template.Melee) ret.push("Melee"); 200 214 if (this.template.Ranged) ret.push("Ranged"); 215 if (this.template.Capture) ret.push("Capture"); 201 216 return ret; 202 217 }; 203 218 … … 309 324 if (cmpFormation) 310 325 return this.GetBestAttack(); 311 326 312 constcmpIdentity = Engine.QueryInterface(target, IID_Identity);327 var cmpIdentity = Engine.QueryInterface(target, IID_Identity); 313 328 if (!cmpIdentity) 314 329 return undefined; 315 330 316 const targetClasses = cmpIdentity.GetClassesList();317 const isTargetClass = function (value, i, a) { return targetClasses.indexOf(value) != -1; };318 const types = this.GetAttackTypes();319 const attack = this;320 const isAllowed = function (value, i, a) { return !attack.GetRestrictedClasses(value).some(isTargetClass); }321 const isPreferred = function (value, i, a) { return attack.GetPreferredClasses(value).some(isTargetClass); }322 const byPreference = function (a, b) { return (types.indexOf(a) + (isPreferred(a) ? types.length : 0) ) - (types.indexOf(b) + (isPreferred(b) ? types.length : 0) ); }323 331 332 var targetClasses = cmpIdentity.GetClassesList(); 333 var isTargetClass = function (className) { return targetClasses.indexOf(className) != -1; }; 334 324 335 // Always slaughter domestic animals instead of using a normal attack 325 336 if (isTargetClass("Domestic") && this.template.Slaughter) 326 337 return "Slaughter"; 327 338 328 return types.filter(isAllowed).sort(byPreference).pop(); 339 var attack = this; 340 var isAllowed = function (type) { return !attack.GetRestrictedClasses(type).some(isTargetClass); } 341 342 var types = this.GetAttackTypes().filter(isAllowed); 343 344 // check if the target is capturable 345 var captureIndex = types.indexOf("Capture") 346 if (captureIndex != -1) 347 { 348 var cmpCapturable = Engine.QueryInterface(target, IID_Capturable); 349 var cmpPlayer = QueryOwnerInterface(this.entity, IID_Player); 350 if (cmpPlayer && cmpCapturable && cmpCapturable.CanCapture(cmpPlayer.GetPlayerID())) 351 return "Capture"; 352 // not captureable, so remove this attack 353 types.splice(captureIndex, 1); 354 } 355 356 var isPreferred = function (className) { return attack.GetPreferredClasses(className).some(isTargetClass); } 357 var byPreference = function (a, b) { return (types.indexOf(a) + (isPreferred(a) ? types.length : 0) ) - (types.indexOf(b) + (isPreferred(b) ? types.length : 0) ); } 358 359 360 return types.sort(byPreference).pop(); 329 361 }; 330 362 331 363 Attack.prototype.CompareEntitiesByPreference = function(a, b) … … 367 399 { 368 400 return ApplyValueModificationsToEntity("Attack/" + type + splash + "/" + damageType, +(template[damageType] || 0), self.entity); 369 401 }; 370 402 403 if (type == "Capture") 404 return {value: applyMods("Value")}; 405 371 406 return { 372 407 hack: applyMods("Hack"), 373 408 pierce: applyMods("Pierce"), … … 517 552 var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); 518 553 cmpTimer.SetTimeout(this.entity, IID_Attack, "MissileHit", timeToTarget*1000, {"type": type, "target": target, "position": realTargetPosition, "direction": missileDirection, "projectileId": id, "playerId":playerId}); 519 554 } 555 else if (type == "Capture") 556 { 557 var multiplier = this.GetAttackBonus(type, target); 558 var cmpHealth = Engine.QueryInterface(target, IID_Health); 559 if (!cmpHealth || cmpHealth.GetHitpoints() == 0) 560 return; 561 multiplier *= cmpHealth.GetMaxHitpoints() / cmpHealth.GetHitpoints(); 562 563 var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); 564 if (!cmpOwnership || cmpOwnership.GetOwner() == -1) 565 return; 566 var owner = cmpOwnership.GetOwner(); 567 var cmpCapturable = Engine.QueryInterface(target, IID_Capturable); 568 if (!cmpCapturable || !cmpCapturable.CanCapture(owner)) 569 return; 570 571 var strength = this.GetAttackStrengths("Capture").value; 572 cmpCapturable.Reduce(strength * multiplier, owner); 573 } 520 574 else 521 575 { 522 576 // Melee attack - hurt the target immediately -
binaries/data/mods/public/simulation/components/Builder.js
26 26 27 27 Builder.prototype.GetEntitiesList = function() 28 28 { 29 var entities = [];30 29 var string = this.template.Entities._string; 31 if ( string)32 {33 // Replace the "{civ}" codes with this entity's civ ID 34 35 if (cmpIdentity)36 string = string.replace(/\{civ\}/g, cmpIdentity.GetCiv());37 entities = string.split(/\s+/);38 39 // Remove disabled entities40 var cmpPlayer = QueryOwnerInterface(this.entity, IID_Player)41 var disabledEntities = cmpPlayer.GetDisabledTemplates();42 43 for (var i = entities.length - 1; i >= 0; --i)44 if (disabledEntities[entities[i]])45 entities.splice(i, 1);46 }47 return entities ;30 if (!string) 31 return []; 32 33 var cmpIdentity = Engine.QueryInterface(this.entity, IID_Identity); 34 var cmpPlayer = QueryOwnerInterface(this.entity, IID_Player) 35 if (!cmpIdentity || !cmpPlayer) 36 return []; 37 38 // disable building of structures from other civs 39 if (cmpIdentity.GetCiv() != cmpPlayer.GetCiv()) 40 return []; 41 42 // Replace the "{civ}" codes with this entity's civ ID 43 var entities = string.replace(/\{civ\}/g, cmpIdentity.GetCiv()).split(/\s+/); 44 // Remove disabled entities 45 var disabledEntities = cmpPlayer.GetDisabledTemplates(); 46 return entities.filter(function(e) { return !disabledEntities[e]; }); 48 47 }; 49 48 50 49 Builder.prototype.GetRange = function() -
binaries/data/mods/public/simulation/components/Capturable.js
1 function Capturable() {} 2 3 Capturable.prototype.Schema = 4 "<element name='CapturePoints' a:help='Maximum capture points'>" + 5 "<ref name='nonNegativeDecimal'/>" + 6 "</element>"; 7 8 Capturable.prototype.Init = function() 9 { 10 // Cache this value 11 this.maxCp = +this.template.CapturePoints; 12 }; 13 14 //// Interface functions //// 15 16 /** 17 * Returns the current capture points array 18 */ 19 Capturable.prototype.GetCapturePoints = function() 20 { 21 return this.cp; 22 }; 23 24 Capturable.prototype.GetMaxCapturePoints = function() 25 { 26 return this.maxCp; 27 }; 28 29 /** 30 * Reset all capture points by assigning them to the current owner 31 */ 32 Capturable.prototype.ResetCapturePoints = function() 33 { 34 this.cp = []; 35 var cmpPlayerManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager); 36 var playerId = QueryOwnerInterface(this.entity, IID_Player).GetPlayerID(); 37 38 // FIXME: check if this works with observers, defeated players, stuff like that 39 for (let i = 0; i < cmpPlayerManager.GetNumPlayers(); i++) 40 if (i == playerId) 41 this.cp[i] = this.maxCp; 42 else 43 this.cp[i] = 0; 44 }; 45 46 /** 47 * Reduces the amount of capture points of an entity, 48 * in the favour of the player of the source 49 * Returns true when captured 50 */ 51 Capturable.prototype.Reduce = function(amount, player) 52 { 53 // Before changing the value, activate Fogging if necessary to hide changes 54 let cmpFogging = Engine.QueryInterface(this.entity, IID_Fogging); 55 if (cmpFogging) 56 cmpFogging.Activate(); 57 58 var cmpPlayerSource = QueryPlayerIDInterface(player, IID_Player); 59 60 if (!cmpPlayerSource) 61 warn(source + " has no player component defined on its owner "); 62 63 var sourceEnemyCp = 0; 64 var sourceAllyCp = 0; 65 for (let i in this.cp) 66 { 67 let cp = this.cp[i]; 68 if (cmpPlayerSource.IsAlly(i)) 69 sourceAllyCp += cp; 70 else 71 sourceEnemyCp += cp; 72 } 73 74 var newCp = []; 75 for (let i in this.cp) 76 { 77 if (i == cmpPlayerSource.GetPlayerID()) 78 newCp[i] = this.cp[i] + amount; 79 else if (cmpPlayerSource.IsAlly(i)) 80 newCp[i] = this.cp[i]; 81 else // subtract proportional amount 82 newCp[i] = this.cp[i] - amount * this.cp[i] / sourceEnemyCp; 83 } 84 this.cp = newCp; 85 86 if (sourceEnemyCp > amount) 87 return false; 88 89 // We proceed to the capture part 90 91 var bestPlayer = 0; 92 for (let i in this.cp) 93 { 94 if (this.cp[i] >= this.cp[bestPlayer]) 95 bestPlayer = i; 96 } 97 98 var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); 99 cmpOwnership.SetOwner(bestPlayer); 100 101 return true; 102 }; 103 104 /** 105 * Check if the source can (re)capture points from this building 106 */ 107 Capturable.prototype.CanCapture = function(playerID) 108 { 109 var cmpPlayerSource = QueryPlayerIDInterface(playerID, IID_Player); 110 111 if (!cmpPlayerSource) 112 warn(source + " has no player component defined on its owner "); 113 var cp = this.GetCapturePoints() 114 var sourceEnemyCp = 0; 115 for (let i in this.GetCapturePoints()) 116 if (!cmpPlayerSource.IsAlly(i)) 117 sourceEnemyCp += cp[i]; 118 return sourceEnemyCp > 0; 119 }; 120 121 //// Private functions //// 122 123 Capturable.prototype.OnValueModification = function(msg) 124 { 125 if (msg.component != "Capturable") 126 return; 127 128 var oldMaxCp = this.GetMaxCapturePoints(); 129 this.maxCp = Math.round(ApplyValueModificationsToEntity("Capturable/Max", +this.template.Max, this.entity)); 130 if (oldMaxCp != this.maxCp) 131 { 132 var scale = this.maxCp / oldMaxCp; 133 for (let i in this.cp) 134 this.cp[i] *= scale; 135 } 136 }; 137 138 Capturable.prototype.OnOwnershipChanged = function(msg) 139 { 140 this.ResetCapturePoints(); 141 }; 142 143 Engine.RegisterComponentType(IID_Capturable, "Capturable", Capturable); -
binaries/data/mods/public/simulation/components/GarrisonHolder.js
75 75 this.visibleGarrisonPoints.push({"offset":o, "entity": null}); 76 76 } 77 77 } 78 this.captureTimers = {}; 78 79 }; 79 80 80 81 /** … … 269 270 if (this.GetGarrisonedEntitiesCount() + extraCount >= this.GetCapacity()) 270 271 return false; 271 272 273 var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); 272 274 if (!this.timer && this.GetHealRate() > 0) 273 {274 var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);275 275 this.timer = cmpTimer.SetTimeout(this.entity, IID_GarrisonHolder, "HealTimeout", 1000, {}); 276 }277 276 278 277 // Actual garrisoning happens here 279 278 this.entities.push(entity); … … 291 290 var cmpUnitAI = Engine.QueryInterface(entity, IID_UnitAI); 292 291 if (cmpUnitAI && cmpUnitAI.IsUnderAlert()) 293 292 Engine.PostMessage(cmpUnitAI.GetAlertRaiser(), MT_UnitGarrisonedAfterAlert, {"holder": this.entity, "unit": entity}); 293 294 var cmpAttack = Engine.QueryInterface(entity, IID_Attack); 295 if (cmpAttack && cmpAttack.GetAttackTypes().indexOf("Capture") != -1) 296 { 297 var repeatTime = cmpAttack.GetTimers("Capture").repeat; 298 var timer = cmpTimer.SetInterval(this.entity, IID_GarrisonHolder, "Recapture", repeatTime, repeatTime, {"entity": entity}); 299 this.captureTimers[entity] = timer; 300 } 294 301 295 302 return true; 296 303 }; … … 420 427 this.OrderWalkToRallyPoint(ejectedEntities); 421 428 this.UpdateGarrisonFlag(); 422 429 430 if (forced || success) 431 { 432 var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); 433 for (let ent of entities) 434 { 435 var timerId = this.captureTimers[ent]; 436 if (timerId) 437 { 438 cmpTimer.CancelTimer(timerId); 439 this.captureTimers[ent] = 0; 440 } 441 } 442 } 443 423 444 return success; 424 445 }; 425 446 … … 723 744 return false; 724 745 }; 725 746 747 GarrisonHolder.prototype.Recapture = function(data) 748 { 749 var cmpAttack = Engine.QueryInterface(data.entity, IID_Attack); 750 if (!cmpAttack) 751 return; // error 752 if (cmpAttack.GetAttackTypes().indexOf("Capture") == -1) 753 return; // error 754 cmpAttack.PerformAttack("Capture", this.entity); 755 }; 756 726 757 /** 727 758 * Initialise the garrisoned units 728 759 */ -
binaries/data/mods/public/simulation/components/GuiInterface.js
267 267 ret.needsRepair = cmpMirage.NeedsRepair(); 268 268 } 269 269 270 var cmpCapturable = Engine.QueryInterface(ent, IID_Capturable); 271 if (cmpCapturable) 272 { 273 ret.capturePoints = cmpCapturable.GetCapturePoints(); 274 ret.maxCapturePoints = cmpCapturable.GetMaxCapturePoints(); 275 } 276 // TODO mirage support 277 270 278 var cmpBuilder = Engine.QueryInterface(ent, IID_Builder); 271 279 if (cmpBuilder) 272 280 ret.builder = true; … … 1701 1709 var cmpAttack = Engine.QueryInterface(data.entity, IID_Attack); 1702 1710 if (!cmpAttack) 1703 1711 return false; 1712 var cmpEntityPlayer = QueryOwnerInterface(data.entity, IID_Player); 1713 var cmpTargetPlayer = QueryOwnerInterface(data.target, IID_Player); 1714 if (!cmpEntityPlayer || !cmpTargetPlayer) 1715 return false; 1704 1716 1705 return cmpAttack.CanAttack(data.target); 1717 1718 // if the owner is an enemy, it's up to the attack component to decide 1719 if (!cmpEntityPlayer.IsAlly(cmpTargetPlayer.GetPlayerID())) 1720 return cmpAttack.CanAttack(data.target); 1721 1722 // if the owner is an ally, we could still want to capture some capture points back 1723 var cmpCapturable = Engine.QueryInterface(data.target, IID_Capturable); 1724 if (cmpCapturable && cmpCapturable.CanCapture(cmpEntityPlayer.GetPlayerID())) 1725 return cmpAttack.CanAttack(data.target); 1726 1727 return false; 1706 1728 }; 1707 1729 1708 1730 /* -
binaries/data/mods/public/simulation/components/ProductionQueue.js
154 154 if (!cmpTechnologyManager) 155 155 return []; 156 156 157 var cmpPlayer = QueryOwnerInterface(this.entity, IID_Player); 158 var cmpIdentity = Engine.QueryInterface(this.entity, IID_Identity); 159 if (!cmpPlayer || !cmpIdentity) 160 return []; 161 162 // don't allow researching techs of other civs 163 if (cmpIdentity.GetCiv() != cmpPlayer.GetCiv()) 164 return []; 165 157 166 var techs = string.split(/\s+/); 158 167 var techList = []; 159 168 var superseded = {}; // Stores the tech which supersedes the key 160 169 161 var cmpPlayer = QueryOwnerInterface(this.entity, IID_Player); 162 if (cmpPlayer) 163 var disabledTechnologies = cmpPlayer.GetDisabledTechnologies(); 170 var disabledTechnologies = cmpPlayer.GetDisabledTechnologies(); 164 171 165 172 // Add any top level technologies to an array which corresponds to the displayed icons 166 173 // Also store what a technology is superceded by in the superceded object {"tech1":"techWhichSupercedesTech1", ...} -
binaries/data/mods/public/simulation/components/TerritoryDecay.js
1 1 function TerritoryDecay() {} 2 2 3 3 TerritoryDecay.prototype.Schema = 4 "<element name=' HealthDecayRate' a:help='Decay rate in hitpoints per second'>" +4 "<element name='DecayRate' a:help='Decay rate in hitpoints per second'>" + 5 5 "<data type='positiveInteger'/>" + 6 6 "</element>"; 7 7 … … 9 9 { 10 10 this.timer = undefined; 11 11 this.decaying = false; 12 this.convertTo = 0; // by default, convert to gaia 12 13 }; 13 14 14 15 TerritoryDecay.prototype.IsConnected = function() 15 16 { 17 this.convertTo = 0; 16 18 var cmpPosition = Engine.QueryInterface(this.entity, IID_Position); 17 19 if (!cmpPosition || !cmpPosition.IsInWorld()) 18 20 return false; … … 22 24 return false; 23 25 24 26 // Prevent special gaia buildings from decaying (e.g. fences, ruins) 25 if (cmpOwnership.GetOwner() == 0)26 return true;27 // if (cmpOwnership.GetOwner() == 0) 28 // return true; 27 29 28 30 var cmpTerritoryManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TerritoryManager); 29 31 if (!cmpTerritoryManager) … … 32 34 var pos = cmpPosition.GetPosition2D(); 33 35 var tileOwner = cmpTerritoryManager.GetOwner(pos.x, pos.y); 34 36 if (tileOwner != cmpOwnership.GetOwner()) 37 { 38 this.convertTo = tileOwner; 35 39 return false; 36 // TODO: this should probably use the same territory restriction 37 // logic as BuildRestrictions, to handle allies etc 40 } 38 41 39 42 return cmpTerritoryManager.IsConnected(pos.x, pos.y); 40 43 }; … … 64 67 if (connected) 65 68 var decaying = false; 66 69 else 67 var decaying = (Math.round(ApplyValueModificationsToEntity("TerritoryDecay/ HealthDecayRate", +this.template.HealthDecayRate, this.entity)) > 0);70 var decaying = (Math.round(ApplyValueModificationsToEntity("TerritoryDecay/DecayRate", +this.template.DecayRate, this.entity)) > 0); 68 71 if (decaying === this.decaying) 69 72 return; 70 73 this.decaying = decaying; … … 88 91 89 92 TerritoryDecay.prototype.Decay = function() 90 93 { 91 var cmp Health = Engine.QueryInterface(this.entity, IID_Health);92 if (!cmp Health)94 var cmpCapturable = Engine.QueryInterface(this.entity, IID_Capturable); 95 if (!cmpCapturable) 93 96 return; // error 94 97 95 var decayRate = ApplyValueModificationsToEntity("TerritoryDecay/ HealthDecayRate", +this.template.HealthDecayRate, this.entity);98 var decayRate = ApplyValueModificationsToEntity("TerritoryDecay/DecayRate", +this.template.DecayRate, this.entity); 96 99 97 cmp Health.Reduce(Math.round(decayRate));100 cmpCapturable.Reduce(decayRate, this.convertTo); 98 101 }; 99 102 100 103 Engine.RegisterComponentType(IID_TerritoryDecay, "TerritoryDecay", TerritoryDecay); -
binaries/data/mods/public/simulation/components/interfaces/Capturable.js
1 Engine.RegisterInterface("Capturable"); 2 3 -
binaries/data/mods/public/simulation/data/technologies/decay_outpost.json
7 7 "icon": "blocks_three.png", 8 8 "researchTime": 40, 9 9 "tooltip": "Territory decay -50% for Outposts.", 10 "modifications": [{"value": "TerritoryDecay/ HealthDecayRate", "multiply": 0.5}],10 "modifications": [{"value": "TerritoryDecay/DecayRate", "multiply": 0.5}], 11 11 "affects": ["Outpost"], 12 12 "soundComplete": "interface/alarm/alarm_upgradearmory.xml" 13 13 } -
binaries/data/mods/public/simulation/data/technologies/romans/decay_logistics.json
7 7 "icon": "handcart_empty.png", 8 8 "researchTime": 40, 9 9 "tooltip": "Entrenched Camps and Siege Walls decay 50% slower.", 10 "modifications": [{"value": "TerritoryDecay/ HealthDecayRate", "multiply": 0.5}],10 "modifications": [{"value": "TerritoryDecay/DecayRate", "multiply": 0.5}], 11 11 "affects": ["ArmyCamp", "SiegeWall"], 12 12 "soundComplete": "interface/alarm/alarm_upgradearmory.xml" 13 13 } -
binaries/data/mods/public/simulation/helpers/Commands.js
349 349 350 350 "delete-entities": function(player, cmd, data) 351 351 { 352 for each (var ent indata.entities)352 for (let ent of data.entities) 353 353 { 354 // don't allow to delete entities who are half-captured 355 var cmpCapturable = Engine.QueryInterface(ent, IID_Capturable); 356 if (cmpCapturable) 357 { 358 var capturePoints = cmpCapturable.GetCapturePoints(); 359 var maxCapturePoints = cmpCapturable.GetMaxCapturePoints(); 360 if (capturePoints[player] < maxCapturePoints / 2) 361 return; 362 } 363 // either kill or delete the entity 354 364 var cmpHealth = Engine.QueryInterface(ent, IID_Health); 355 365 if (cmpHealth) 356 366 { -
binaries/data/mods/public/simulation/templates/structures/merc_camp_egyptian.xml
60 60 </SoundGroups> 61 61 </Sound> 62 62 <TerritoryDecay> 63 < HealthDecayRate>1</HealthDecayRate>63 <DecayRate>1</DecayRate> 64 64 </TerritoryDecay> 65 65 <TerritoryInfluence disable=""/> 66 66 <VisualActor> -
binaries/data/mods/public/simulation/templates/structures/ptol_mercenary_camp.xml
62 62 </SoundGroups> 63 63 </Sound> 64 64 <TerritoryDecay> 65 < HealthDecayRate>1</HealthDecayRate>65 <DecayRate>1</DecayRate> 66 66 </TerritoryDecay> 67 67 <TerritoryInfluence disable=""/> 68 68 <VisualActor> -
binaries/data/mods/public/simulation/templates/structures/ptol_military_colony.xml
76 76 </SoundGroups> 77 77 </Sound> 78 78 <TerritoryDecay> 79 < HealthDecayRate>1</HealthDecayRate>79 <DecayRate>1</DecayRate> 80 80 </TerritoryDecay> 81 81 <TerritoryInfluence> 82 82 <Radius>80</Radius> -
binaries/data/mods/public/simulation/templates/structures/rome_army_camp.xml
76 76 </SoundGroups> 77 77 </Sound> 78 78 <TerritoryDecay> 79 < HealthDecayRate>10</HealthDecayRate>79 <DecayRate>10</DecayRate> 80 80 </TerritoryDecay> 81 81 <TerritoryInfluence disable=""/> 82 82 <ProductionQueue> -
binaries/data/mods/public/simulation/templates/structures/rome_siege_wall_gate.xml
44 44 </Obstructions> 45 45 </Obstruction> 46 46 <TerritoryDecay> 47 < HealthDecayRate>1</HealthDecayRate>47 <DecayRate>1</DecayRate> 48 48 </TerritoryDecay> 49 49 <TerritoryInfluence disable=""/> 50 50 <VisualActor> -
binaries/data/mods/public/simulation/templates/structures/rome_siege_wall_long.xml
62 62 <Static width="37.0" depth="5.0"/> 63 63 </Obstruction> 64 64 <TerritoryDecay> 65 < HealthDecayRate>1</HealthDecayRate>65 <DecayRate>1</DecayRate> 66 66 </TerritoryDecay> 67 67 <TerritoryInfluence disable=""/> 68 68 <VisualActor> -
binaries/data/mods/public/simulation/templates/structures/rome_siege_wall_medium.xml
55 55 <Static width="25.0" depth="5.0"/> 56 56 </Obstruction> 57 57 <TerritoryDecay> 58 < HealthDecayRate>1</HealthDecayRate>58 <DecayRate>1</DecayRate> 59 59 </TerritoryDecay> 60 60 <TerritoryInfluence disable=""/> 61 61 <VisualActor> -
binaries/data/mods/public/simulation/templates/structures/rome_siege_wall_short.xml
42 42 <Static width="13.0" depth="5.0"/> 43 43 </Obstruction> 44 44 <TerritoryDecay> 45 < HealthDecayRate>1</HealthDecayRate>45 <DecayRate>1</DecayRate> 46 46 </TerritoryDecay> 47 47 <TerritoryInfluence disable=""/> 48 48 <VisualActor> -
binaries/data/mods/public/simulation/templates/structures/rome_siege_wall_tower.xml
36 36 <Static width="7.0" depth="7.0"/> 37 37 </Obstruction> 38 38 <TerritoryDecay> 39 < HealthDecayRate>1</HealthDecayRate>39 <DecayRate>1</DecayRate> 40 40 </TerritoryDecay> 41 41 <TerritoryInfluence disable=""/> 42 42 <VisualActor> -
binaries/data/mods/public/simulation/templates/structures/rome_tent.xml
50 50 </SoundGroups> 51 51 </Sound> 52 52 <TerritoryDecay> 53 < HealthDecayRate>1</HealthDecayRate>53 <DecayRate>1</DecayRate> 54 54 </TerritoryDecay> 55 55 <TerritoryInfluence disable=""/> 56 56 <VisualActor> -
binaries/data/mods/public/simulation/templates/structures/sele_military_colony.xml
75 75 </SoundGroups> 76 76 </Sound> 77 77 <TerritoryDecay> 78 < HealthDecayRate>1</HealthDecayRate>78 <DecayRate>1</DecayRate> 79 79 </TerritoryDecay> 80 80 <TerritoryInfluence> 81 81 <Radius>80</Radius> -
binaries/data/mods/public/simulation/templates/template_structure.xml
20 20 <PlacementType>land</PlacementType> 21 21 <Territory>own</Territory> 22 22 </BuildRestrictions> 23 <Capturable> 24 <CapturePoints>1000</CapturePoints> 25 </Capturable> 23 26 <Cost> 24 27 <Population>0</Population> 25 28 <PopulationBonus>0</PopulationBonus> … … 100 103 <HeightOffset>12.0</HeightOffset> 101 104 </StatusBars> 102 105 <TerritoryDecay> 103 < HealthDecayRate>5</HealthDecayRate>106 <DecayRate>5</DecayRate> 104 107 </TerritoryDecay> 105 108 <Visibility> 106 109 <RetainInFog>true</RetainInFog> -
binaries/data/mods/public/simulation/templates/template_structure_defense_outpost.xml
90 90 <HeightOffset>18.0</HeightOffset> 91 91 </StatusBars> 92 92 <TerritoryDecay> 93 < HealthDecayRate>2</HealthDecayRate>93 <DecayRate>2</DecayRate> 94 94 </TerritoryDecay> 95 95 <Vision> 96 96 <Range>80</Range> -
binaries/data/mods/public/simulation/templates/template_unit_infantry.xml
6 6 <Crush>15</Crush> 7 7 </Armour> 8 8 <Attack> 9 <Capture> 10 <Value>10</Value> 11 <MaxRange>4</MaxRange> 12 <RepeatTime>1000</RepeatTime> 13 </Capture> 9 14 <Slaughter> 10 15 <Hack>50.0</Hack> 11 16 <Pierce>0.0</Pierce>