From cd5e5882eee3ab8d72fb72a7557b00fbf4834fe4 Mon Sep 17 00:00:00 2001 From: quantumstate Date: Mon, 11 Feb 2013 20:38:13 +0000 Subject: [PATCH] Improvements to battle detection. Patch from zoot. Fixes #1425. This was SVN commit r13163. --- .../simulation/components/BattleDetection.js | 108 ++++++++++++------ .../simulation/templates/special/player.xml | 9 +- 2 files changed, 80 insertions(+), 37 deletions(-) diff --git a/binaries/data/mods/public/simulation/components/BattleDetection.js b/binaries/data/mods/public/simulation/components/BattleDetection.js index f8068b3749..adf9534d2f 100644 --- a/binaries/data/mods/public/simulation/components/BattleDetection.js +++ b/binaries/data/mods/public/simulation/components/BattleDetection.js @@ -3,22 +3,39 @@ function BattleDetection() {} BattleDetection.prototype.Schema = "Detects the occurence of battles." + "" + - "" + - ""; + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + ""; BattleDetection.prototype.Init = function() { - this.interval = 5 * 1000; // Duration of one timer period. Interval over which damage rate should be calculated in milliseconds. - this.damageRateThreshold = 0.04; // Damage rate at which alertness is increased. - this.alertnessBattleThreshold = 2; // Alertness at which the player is considered in battle. - this.alertnessPeaceThreshold = 0; // Alertness at which the player is considered at peace. - this.alertnessMax = 4; // Maximum alertness level. + // Load values from template. + this.interval = Number(this.template.TimerInterval); + this.recordLength = Number(this.template.RecordLength); + this.damageRateThreshold = Number(this.template.DamageRateThreshold); + this.alertnessBattleThreshold = Number(this.template.AlertnessBattleThreshold); + this.alertnessPeaceThreshold = Number(this.template.AlertnessPeaceThreshold); + this.alertnessMax = Number(this.template.AlertnessMax); - this.damage = 0; // Accumulative damage dealt over the current timer period. - this.damageRate = 0; // Damage rate. Total damage dealt over the previous timer period. + // Initialize variables. + this.damage = 0; // Damage counter. Accumulative damage done over the current timer period. + this.damageRecord = []; // Damage record. Array of elements representing total damage done in a given timer cycle. this.alertness = 0; // Alertness level. Incremented if damage rate exceeds 'damageRateThreshold' over a given timer period and decremented if it does not. - - this.StartTimer(0, this.interval); }; BattleDetection.prototype.setState = function(state) @@ -30,19 +47,6 @@ BattleDetection.prototype.setState = function(state) } }; -BattleDetection.prototype.updateAlertness = function() -{ - if (this.damageRate > this.damageRateThreshold) - this.alertness = Math.min(this.alertnessMax, this.alertness+1); // Increment alertness up to 'alertnessMax'. - else - this.alertness = Math.max(0, this.alertness-1); // Decrement alertness down to zero. - - if (this.alertness >= this.alertnessBattleThreshold) - this.setState("BATTLE"); - else if (this.alertness <= this.alertnessPeaceThreshold) - this.setState("PEACE"); -} - BattleDetection.prototype.GetState = function() { return this.state; @@ -56,26 +60,53 @@ BattleDetection.prototype.TimerHandler = function(data, lateness) this.timer = undefined; } - this.damageRate = this.damage / this.interval; // Define damage rate as total damage dealt per unit 'interval' (i.e. millisecond) over the previous timer period. + this.damageRecord.unshift(this.damage); + if (this.damageRecord.length > this.recordLength) + this.damageRecord.splice(this.recordLength, this.damageRecord.length-1); // Discard any elements beyond 'recordLength'. this.damage = 0; // Reset damage counter for the next timer period. - this.updateAlertness(); + + // Always update alertness if not already alert, or once per 'recordLength' otherwise. + if (!this.alertness || this.recordControl++ == this.recordLength-1) + { + var recordDamage = this.damageRecord.reduce(function(a, b) {return a + b;}, 0); // Sum up all values in the damage record. + var damageRate = recordDamage / (this.recordLength * this.interval); + + if (damageRate > this.damageRateThreshold) + this.alertness = Math.min(this.alertnessMax, this.alertness+1); // Increment alertness up to 'alertnessMax'. + else + this.alertness = Math.max(0, this.alertness-1); // Decrement alertness down to zero. + + // Stop the damage rate timer if we're no longer alert. + if (!this.alertness) + this.stopTimer(); + + if (this.alertness >= this.alertnessBattleThreshold) + this.setState("BATTLE"); + else if (this.alertness <= this.alertnessPeaceThreshold) + this.setState("PEACE"); + + } + if (this.recordControl > this.recordLength-1) + this.recordControl = 0; }; /** - * Set up the BattleDetection timer to run after 'offset' msecs, and then optionally - * every 'repeat' msecs until StopTimer is called, if 'repeat' is set. A "Timer" message + * Set up the damage rate timer to run after 'offset' msecs, and then optionally + * every 'repeat' msecs until stopTimer is called, if 'repeat' is set. A "Timer" message * will be sent each time the timer runs. Must not be called if a timer is already active. */ -BattleDetection.prototype.StartTimer = function(offset, repeat) +BattleDetection.prototype.startTimer = function(offset, repeat) { if (this.timer) { - this.StopTimer(); - error("Called StartTimer when there's already an active timer."); + this.stopTimer(); + error("Called startTimer when there's already an active timer."); } - var data = { "timerRepeat": repeat }; + this.recordControl = 0; + this.damage = 0; // Reset damage counter for the first timer period. + var data = { "timerRepeat": repeat }; var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); if (repeat === undefined) this.timer = cmpTimer.SetTimeout(this.entity, IID_BattleDetection, "TimerHandler", offset, data); @@ -84,9 +115,9 @@ BattleDetection.prototype.StartTimer = function(offset, repeat) }; /** - * Stop the current BattleDetection timer. + * Stop the current damage rate timer. */ -BattleDetection.prototype.StopTimer = function() +BattleDetection.prototype.stopTimer = function() { if (!this.timer) return; @@ -103,13 +134,18 @@ BattleDetection.prototype.OnGlobalAttacked = function(msg) var cmpAttackerOwnership = Engine.QueryInterface(msg.attacker, IID_Ownership); if (!cmpAttackerOwnership || cmpAttackerOwnership.GetOwner() != cmpPlayer.GetPlayerID()) return; - // Don't register attacks dealt against Gaia or invalid player. + // Don't register attacks dealt against Gaia or invalid player or myself. var cmpTargetOwnership = Engine.QueryInterface(msg.target, IID_Ownership); - if (!cmpTargetOwnership || cmpTargetOwnership.GetOwner() <= 0) + if (!cmpTargetOwnership || cmpTargetOwnership.GetOwner() <= 0 || cmpTargetOwnership.GetOwner() == cmpPlayer.GetPlayerID()) return; + // If the damage rate timer isn't already started, start it now. + if (!this.timer) + this.startTimer(0, this.interval); + // Add damage of this attack to the damage counter. if (msg.damage) this.damage += msg.damage; }; Engine.RegisterComponentType(IID_BattleDetection, "BattleDetection", BattleDetection); + diff --git a/binaries/data/mods/public/simulation/templates/special/player.xml b/binaries/data/mods/public/simulation/templates/special/player.xml index a2285a9abc..eaa28e6e2d 100644 --- a/binaries/data/mods/public/simulation/templates/special/player.xml +++ b/binaries/data/mods/public/simulation/templates/special/player.xml @@ -12,5 +12,12 @@ - + + 200 + 12 + 0.04 + 4 + 0 + 8 +