2013-01-21 00:36:08 +01:00
function BattleDetection ( ) { }
BattleDetection . prototype . Schema =
"<a:help>Detects the occurence of battles.</a:help>" +
"<a:example/>" +
2013-02-11 21:38:13 +01:00
"<element name='TimerInterval' a:help='Duration of one timer period. Interval over which damage should be recorded in milliseconds.'>" +
"<data type='positiveInteger'/>" +
"</element>" +
"<element name='RecordLength' a:help='Record length. Number of timer cycles over which damage rate should be calculated.'>" +
"<data type='positiveInteger'/>" +
"</element>" +
"<element name='DamageRateThreshold' a:help='Damage rate at which alertness is increased.'>" +
"<ref name='positiveDecimal'/>" +
"</element>" +
"<element name='AlertnessBattleThreshold' a:help='Alertness at which the player is considered in battle.'>" +
"<ref name='positiveDecimal'/>" +
"</element>" +
"<element name='AlertnessPeaceThreshold' a:help='Alertness at which the player is considered at peace.'>" +
"<ref name='nonNegativeDecimal'/>" +
"</element>" +
"<element name='AlertnessMax' a:help='Maximum alertness level.'>" +
"<ref name='positiveDecimal'/>" +
"</element>" ;
2013-01-21 00:36:08 +01:00
BattleDetection . prototype . Init = function ( )
{
2013-02-11 21:38:13 +01:00
// Load values from template.
2013-02-24 01:25:13 +01:00
this . interval = + this . template . TimerInterval ;
this . recordLength = + this . template . RecordLength ;
this . damageRateThreshold = + this . template . DamageRateThreshold ;
this . alertnessBattleThreshold = + this . template . AlertnessBattleThreshold ;
this . alertnessPeaceThreshold = + this . template . AlertnessPeaceThreshold ;
this . alertnessMax = + this . template . AlertnessMax ;
2013-02-11 21:38:13 +01:00
// 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.
2013-01-21 00:36:08 +01:00
this . alertness = 0 ; // Alertness level. Incremented if damage rate exceeds 'damageRateThreshold' over a given timer period and decremented if it does not.
} ;
BattleDetection . prototype . setState = function ( state )
{
if ( state != this . state ) {
var cmpPlayer = Engine . QueryInterface ( this . entity , IID _Player ) ;
this . state = state ;
Engine . PostMessage ( this . entity , MT _BattleStateChanged , { "player" : cmpPlayer . GetPlayerID ( ) , "to" : this . state } ) ;
}
} ;
BattleDetection . prototype . GetState = function ( )
{
return this . state ;
}
BattleDetection . prototype . TimerHandler = function ( data , lateness )
{
// Reset the timer
if ( data . timerRepeat === undefined )
{
this . timer = undefined ;
}
2013-02-11 21:38:13 +01:00
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'.
2013-01-21 00:36:08 +01:00
this . damage = 0 ; // Reset damage counter for the next timer period.
2013-02-11 21:38:13 +01:00
// 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 ;
2013-01-21 00:36:08 +01:00
} ;
/ * *
2013-02-11 21:38:13 +01:00
* 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
2013-01-21 00:36:08 +01:00
* will be sent each time the timer runs . Must not be called if a timer is already active .
* /
2013-02-11 21:38:13 +01:00
BattleDetection . prototype . startTimer = function ( offset , repeat )
2013-01-21 00:36:08 +01:00
{
if ( this . timer )
{
2013-02-11 21:38:13 +01:00
this . stopTimer ( ) ;
error ( "Called startTimer when there's already an active timer." ) ;
2013-01-21 00:36:08 +01:00
}
2013-02-11 21:38:13 +01:00
this . recordControl = 0 ;
this . damage = 0 ; // Reset damage counter for the first timer period.
2013-01-21 00:36:08 +01:00
2013-02-11 21:38:13 +01:00
var data = { "timerRepeat" : repeat } ;
2013-01-21 00:36:08 +01:00
var cmpTimer = Engine . QueryInterface ( SYSTEM _ENTITY , IID _Timer ) ;
if ( repeat === undefined )
this . timer = cmpTimer . SetTimeout ( this . entity , IID _BattleDetection , "TimerHandler" , offset , data ) ;
else
this . timer = cmpTimer . SetInterval ( this . entity , IID _BattleDetection , "TimerHandler" , offset , repeat , data ) ;
} ;
/ * *
2013-02-11 21:38:13 +01:00
* Stop the current damage rate timer .
2013-01-21 00:36:08 +01:00
* /
2013-02-11 21:38:13 +01:00
BattleDetection . prototype . stopTimer = function ( )
2013-01-21 00:36:08 +01:00
{
if ( ! this . timer )
return ;
var cmpTimer = Engine . QueryInterface ( SYSTEM _ENTITY , IID _Timer ) ;
cmpTimer . CancelTimer ( this . timer ) ;
this . timer = undefined ;
} ;
BattleDetection . prototype . OnGlobalAttacked = function ( msg )
{
var cmpPlayer = Engine . QueryInterface ( this . entity , IID _Player ) ;
// Only register attacks dealt by myself.
var cmpAttackerOwnership = Engine . QueryInterface ( msg . attacker , IID _Ownership ) ;
if ( ! cmpAttackerOwnership || cmpAttackerOwnership . GetOwner ( ) != cmpPlayer . GetPlayerID ( ) )
return ;
2013-02-11 21:38:13 +01:00
// Don't register attacks dealt against Gaia or invalid player or myself.
2013-01-21 00:36:08 +01:00
var cmpTargetOwnership = Engine . QueryInterface ( msg . target , IID _Ownership ) ;
2013-02-11 21:38:13 +01:00
if ( ! cmpTargetOwnership || cmpTargetOwnership . GetOwner ( ) <= 0 || cmpTargetOwnership . GetOwner ( ) == cmpPlayer . GetPlayerID ( ) )
2013-01-21 00:36:08 +01:00
return ;
2013-02-11 21:38:13 +01:00
// 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.
2013-01-21 00:36:08 +01:00
if ( msg . damage )
this . damage += msg . damage ;
} ;
Engine . RegisterComponentType ( IID _BattleDetection , "BattleDetection" , BattleDetection ) ;
2013-02-11 21:38:13 +01:00