Changeset View
Changeset View
Standalone View
Standalone View
binaries/data/mods/public/simulation/components/Capturable.js
function Capturable() {} | function Capturable() {} | ||||
Capturable.prototype.Schema = | Capturable.prototype.Schema = | ||||
"<element name='CapturePoints' a:help='Maximum capture points'>" + | "<element name='CapturePoints' a:help='Maximum capture points'>" + | ||||
"<ref name='positiveDecimal'/>" + | "<ref name='positiveDecimal'/>" + | ||||
"</element>" + | "</element>" + | ||||
"<element name='RegenRate' a:help='Number of capture are regenerated per second in favour of the owner'>" + | "<element name='RegenRate' a:help='Number of capture are regenerated per second in favour of the owner'>" + | ||||
"<ref name='nonNegativeDecimal'/>" + | "<ref name='nonNegativeDecimal'/>" + | ||||
"</element>" + | "</element>" + | ||||
"<element name='GarrisonRegenRate' a:help='Number of capture are regenerated per second and per garrisoned unit in favour of the owner'>" + | "<element name='GarrisonRegenRate' a:help='Number of capture are regenerated per second and per garrisoned unit in favour of the owner'>" + | ||||
"<ref name='nonNegativeDecimal'/>" + | "<ref name='nonNegativeDecimal'/>" + | ||||
"</element>"; | "</element>"; | ||||
Capturable.prototype.Init = function() | Capturable.prototype.Init = function() | ||||
{ | { | ||||
// Cache this value | // Values affected by modifications in onOwnershipChanged | ||||
this.maxCp = +this.template.CapturePoints; | this.maxCp = +this.template.CapturePoints; | ||||
this.garrisonRegenRate = +this.template.GarrisonRegenRate; | |||||
this.regenRate = +this.template.RegenRate; | |||||
this.cp = []; | this.cp = []; | ||||
}; | }; | ||||
//// Interface functions //// | //// Interface functions //// | ||||
/** | /** | ||||
* Returns the current capture points array | * Returns the current capture points array | ||||
*/ | */ | ||||
Capturable.prototype.GetCapturePoints = function() | Capturable.prototype.GetCapturePoints = function() | ||||
{ | { | ||||
return this.cp; | return this.cp; | ||||
}; | }; | ||||
Capturable.prototype.GetMaxCapturePoints = function() | Capturable.prototype.GetMaxCapturePoints = function() | ||||
{ | { | ||||
return this.maxCp; | return this.maxCp; | ||||
}; | }; | ||||
Capturable.prototype.GetGarrisonRegenRate = function() | Capturable.prototype.GetGarrisonRegenRate = function() | ||||
{ | { | ||||
return ApplyValueModificationsToEntity("Capturable/GarrisonRegenRate", +this.template.GarrisonRegenRate, this.entity); | return this.garrisonRegenRate; | ||||
}; | }; | ||||
/** | /** | ||||
* Set the new capture points, used for cloning entities | * Set the new capture points, used for cloning entities | ||||
* The caller should assure that the sum of capture points | * The caller should assure that the sum of capture points | ||||
* matches the max. | * matches the max. | ||||
*/ | */ | ||||
Capturable.prototype.SetCapturePoints = function(capturePointsArray) | Capturable.prototype.SetCapturePoints = function(capturePointsArray) | ||||
▲ Show 20 Lines • Show All 130 Lines • ▼ Show 20 Lines | Capturable.prototype.RegisterCapturePointsChanged = function() | ||||
let cmpCapturedPlayerStatisticsTracker = QueryOwnerInterface(this.entity, IID_StatisticsTracker); | let cmpCapturedPlayerStatisticsTracker = QueryOwnerInterface(this.entity, IID_StatisticsTracker); | ||||
if (cmpCapturedPlayerStatisticsTracker) | if (cmpCapturedPlayerStatisticsTracker) | ||||
cmpCapturedPlayerStatisticsTracker.CapturedEntity(this.entity); | cmpCapturedPlayerStatisticsTracker.CapturedEntity(this.entity); | ||||
}; | }; | ||||
Capturable.prototype.GetRegenRate = function() | Capturable.prototype.GetRegenRate = function() | ||||
{ | { | ||||
var regenRate = +this.template.RegenRate; | let cmpGarrisonHolder = Engine.QueryInterface(this.entity, IID_GarrisonHolder); | ||||
regenRate = ApplyValueModificationsToEntity("Capturable/RegenRate", regenRate, this.entity); | if (!cmpGarrisonHolder) | ||||
return this.regenRate; | |||||
var cmpGarrisonHolder = Engine.QueryInterface(this.entity, IID_GarrisonHolder); | let garrisonRegenRate = this.GetGarrisonRegenRate() * cmpGarrisonHolder.GetEntities().length; | ||||
if (cmpGarrisonHolder) | return this.regenRate + garrisonRegenRate; | ||||
var garrisonRegenRate = this.GetGarrisonRegenRate() * cmpGarrisonHolder.GetEntities().length; | |||||
else | |||||
var garrisonRegenRate = 0; | |||||
return regenRate + garrisonRegenRate; | |||||
}; | }; | ||||
Capturable.prototype.TimerTick = function() | Capturable.prototype.TimerTick = function() | ||||
{ | { | ||||
var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); | var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); | ||||
if (!cmpOwnership || cmpOwnership.GetOwner() == INVALID_PLAYER) | if (!cmpOwnership || cmpOwnership.GetOwner() == INVALID_PLAYER) | ||||
return; | return; | ||||
▲ Show 20 Lines • Show All 41 Lines • ▼ Show 20 Lines | |||||
* When nothing can be modified (f.e. because it is fully regenerated), the | * When nothing can be modified (f.e. because it is fully regenerated), the | ||||
* timer stops automatically after one execution. | * timer stops automatically after one execution. | ||||
*/ | */ | ||||
Capturable.prototype.CheckTimer = function() | Capturable.prototype.CheckTimer = function() | ||||
{ | { | ||||
if (this.timer) | if (this.timer) | ||||
return; | return; | ||||
var regenRate = this.GetRegenRate(); | let regenRate = this.GetRegenRate(); | ||||
var cmpDecay = Engine.QueryInterface(this.entity, IID_TerritoryDecay); | let cmpDecay = Engine.QueryInterface(this.entity, IID_TerritoryDecay); | ||||
var decay = cmpDecay && cmpDecay.IsDecaying() ? cmpDecay.GetDecayRate() : 0; | let decay = cmpDecay && cmpDecay.IsDecaying() ? cmpDecay.GetDecayRate() : 0; | ||||
if (regenRate == 0 && decay == 0) | if (regenRate == 0 && decay == 0) | ||||
return; | return; | ||||
var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); | let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); | ||||
this.timer = cmpTimer.SetInterval(this.entity, IID_Capturable, "TimerTick", 1000, 1000, null); | this.timer = cmpTimer.SetInterval(this.entity, IID_Capturable, "TimerTick", 1000, 1000, null); | ||||
Engine.PostMessage(this.entity, MT_CaptureRegenStateChanged, { "regenerating": true, "regenRate": regenRate, "territoryDecay": decay }); | Engine.PostMessage(this.entity, MT_CaptureRegenStateChanged, { "regenerating": true, "regenRate": regenRate, "territoryDecay": decay }); | ||||
}; | }; | ||||
//// Message Listeners //// | /** | ||||
* Update all chached values that could be affected by modifications. | |||||
*/ | |||||
Capturable.prototype.UpdateCachedValues = function() | |||||
{ | |||||
this.garrisonRegenRate = ApplyValueModificationsToEntity("Capturable/GarrisonRegenRate", +this.template.GarrisonRegenRate, this.entity); | |||||
this.regenRate = ApplyValueModificationsToEntity("Capturable/RegenRate", +this.template.RegenRate, this.entity); | |||||
this.maxCp = ApplyValueModificationsToEntity("Capturable/CapturePoints", +this.template.CapturePoints, this.entity); | |||||
} | |||||
Capturable.prototype.OnValueModification = function(msg) | /** | ||||
* Update all chached values that could be affected by modifications. | |||||
* Check timer and send changed messages when required. | |||||
* @param {boolean} dontSendCpChanged - when true, caller will take care of sending that message | |||||
*/ | |||||
Capturable.prototype.UpdateCachedValuesAndNotify = function(dontSendCpChanged = false) | |||||
{ | { | ||||
if (msg.component != "Capturable") | let oldMaxCp = this.maxCp; | ||||
return; | let oldGarrosionRegenRate = this.garrisonRegenRate; | ||||
let oldRegenRate = this.regenRate; | |||||
var oldMaxCp = this.GetMaxCapturePoints(); | this.UpdateCachedValues(); | ||||
this.maxCp = ApplyValueModificationsToEntity("Capturable/CapturePoints", +this.template.CapturePoints, this.entity); | |||||
if (oldMaxCp == this.maxCp) | |||||
return; | |||||
var scale = this.maxCp / oldMaxCp; | if (oldMaxCp != this.maxCp) | ||||
{ | |||||
let scale = this.maxCp / oldMaxCp; | |||||
for (let i in this.cp) | for (let i in this.cp) | ||||
this.cp[i] *= scale; | this.cp[i] *= scale; | ||||
if (!dontSendCpChanged) | |||||
Engine.PostMessage(this.entity, MT_CapturePointsChanged, { "capturePoints": this.cp }); | Engine.PostMessage(this.entity, MT_CapturePointsChanged, { "capturePoints": this.cp }); | ||||
} | |||||
if (oldGarrosionRegenRate != this.garrisonRegenRate || oldRegenRate != this.regenRate) | |||||
this.CheckTimer(); | this.CheckTimer(); | ||||
} | |||||
//// Message Listeners //// | |||||
Capturable.prototype.OnValueModification = function(msg) | |||||
{ | |||||
if (msg.component == "Capturable") | |||||
this.UpdateCachedValuesAndNotify(); | |||||
Freagarach: Why would we need to check the timer when only the max has changed? Perhaps because of the… | |||||
Done Inline Actionsbecause regen rate could change and seems like there is another bug about that if capture points where not affected but regen rate was Silier: because regen rate could change and seems like there is another bug about that if capture… | |||||
}; | }; | ||||
Capturable.prototype.OnGarrisonedUnitsChanged = function(msg) | Capturable.prototype.OnGarrisonedUnitsChanged = function(msg) | ||||
{ | { | ||||
this.CheckTimer(); | this.CheckTimer(); | ||||
}; | }; | ||||
Capturable.prototype.OnTerritoryDecayChanged = function(msg) | Capturable.prototype.OnTerritoryDecayChanged = function(msg) | ||||
{ | { | ||||
if (msg.to) | if (msg.to) | ||||
this.CheckTimer(); | this.CheckTimer(); | ||||
}; | }; | ||||
Capturable.prototype.OnDiplomacyChanged = function(msg) | Capturable.prototype.OnDiplomacyChanged = function(msg) | ||||
{ | { | ||||
this.CheckTimer(); | this.CheckTimer(); | ||||
}; | }; | ||||
Capturable.prototype.OnOwnershipChanged = function(msg) | Capturable.prototype.OnOwnershipChanged = function(msg) | ||||
{ | { | ||||
if (msg.to == INVALID_PLAYER) | if (msg.to == INVALID_PLAYER) | ||||
return; // we're dead | return; // we're dead | ||||
if (this.cp.length) | |||||
{ | |||||
if (!this.cp[msg.from]) | |||||
return; // nothing to change | |||||
// Was already initialised, this happens on defeat or wololo | |||||
// transfer the points of the old owner to the new one | |||||
this.cp[msg.to] += this.cp[msg.from]; | |||||
this.cp[msg.from] = 0; | |||||
this.RegisterCapturePointsChanged(); | |||||
} | |||||
else | |||||
{ | |||||
// Initialise the capture points when created. | // Initialise the capture points when created. | ||||
if (!this.cp.length) | |||||
{ | |||||
this.UpdateCachedValues(); | |||||
Not Done Inline ActionsNewline. Perhaps this block could be refactored, as there are two calls to recalculate values? Stan: Newline. Perhaps this block could be refactored, as there are two calls to recalculate values? | |||||
let numPlayers = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager).GetNumPlayers(); | let numPlayers = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager).GetNumPlayers(); | ||||
for (let i = 0; i < numPlayers; ++i) | for (let i = 0; i < numPlayers; ++i) | ||||
{ | |||||
if (i == msg.to) | if (i == msg.to) | ||||
this.cp[i] = this.maxCp; | this.cp[i] = this.maxCp; | ||||
else | else | ||||
this.cp[i] = 0; | this.cp[i] = 0; | ||||
} | } | ||||
this.CheckTimer(); | this.CheckTimer(); | ||||
return; | |||||
} | |||||
// Was already initialised, this happens on defeat or wololo | |||||
// transfer the points of the old owner to the new one | |||||
if (this.cp[msg.from]) | |||||
{ | |||||
this.cp[msg.to] += this.cp[msg.from]; | |||||
this.cp[msg.from] = 0; | |||||
this.UpdateCachedValuesAndNotify(true); | |||||
this.RegisterCapturePointsChanged(); | |||||
return; | |||||
} | |||||
this.UpdateCachedValuesAndNotify(); | |||||
}; | }; | ||||
/** | /** | ||||
* When a player is defeated, reassign the cp of non-owned entities to gaia. | * When a player is defeated, reassign the cp of non-owned entities to gaia. | ||||
* Those owned by the defeated player are dealt with onOwnershipChanged. | * Those owned by the defeated player are dealt with onOwnershipChanged. | ||||
*/ | */ | ||||
Capturable.prototype.OnGlobalPlayerDefeated = function(msg) | Capturable.prototype.OnGlobalPlayerDefeated = function(msg) | ||||
{ | { | ||||
Show All 12 Lines |
Wildfire Games · Phabricator
Why would we need to check the timer when only the max has changed? Perhaps because of the scaling, but that means one should also check RegisterCapturePointsChanged, which could in turn incorporate the timer check?
What I'm saying: Perhaps we can unify some functions ^^