File: gameplay\health\System.js
/**
This system is reponsible for dealing damage, healing and checking if entities are dead. If an entity dies, the system will trigger
an 'entityDied' event with the entity as an argument.
@class HealthSystem
@constructor
@param entitySystemManager {Manager} The entity system manager whose entities this system will be working on.
@extends EventHandler
*/
function HealthSystem(entitySystemManager){
//Inherit from the event handling object.
EventHandler.call(this);
var thisHealthSystem = this,
//Color strings.
cyan = 'c',
magenta = 'm',
yellow = 'y',
white = 'w',
//Triggered animations.
//Event strings.
entityDied = 'entityDied';
/**
Damages an entity if it has the health component. Additionally, if a spell effect component is present, all shield and resistance
effects will be taken into account. When damaging an entity, first the damage is modified by resistance values, then damage
is dealt to shield effects if present, then if there's any damage left to be dealt, it's dealt to health.
@method damageEntity
@param entity {Entity} Entity that will be damaged.
@param damageAmount {Number}
@param damageType {String} The type of damage dealt. This type can be 'c' for cyan, 'm' for magenta, 'y' for yellow and 'w' for white.
*/
this.damageEntity = function(entity, damageAmount, damageType){
var health = entity.get(Health),
spellEffects = entity.get(SpellEffects);
if(health){
var resistance;
//The type of resistance used depends on the damage type.
switch(damageType){
case cyan : resistance = health._baseCyanResistance;
break;
case magenta : resistance = health._baseMagentaResistance;
break;
case yellow : resistance = health._baseYellowResistance;
break;
case white : resistance = health._baseWhiteResistance;
break;
}
//Add resistance from spell effects, if present.
if(spellEffects){
for(var node=spellEffects.getResistanceSpellEffects().getFirst(); node; node=node.next){
if(damageType === node.value.getResistanceType()){
resistance += node.value.getResistanceAmount();
}
}
}
//Clamp the resistance value.
resistance = Math.min(resistance, 1);
//Modify the damage amount by the level of resistance.
damageAmount *= (1 - resistance);
var damageToBeDealt = damageAmount;
//If the entity has a shield, deal damage to the shield first.
//If the shield can't absorb all the damage, deal the rest to health.
if(spellEffects){
for(var node=spellEffects.getShieldSpellEffects().getFirst(); node; node=node.next){
//Check if this shield can absorb all the remaining damage.
if(node.value.getAbsorbtionAmountRemaining() >= damageToBeDealt){
node.value._absorbtionAmountRemaining -= damageToBeDealt;
damageToBeDealt = 0;
//This shield has absorbed all the damage, quit.
break;
}else{
//This shield can't absorb all the damage, have it absorb all it can.
damageToBeDealt -= node.value.getAbsorbtionAmountRemaining();
node.value._absorbtionAmountRemaining = 0;
}
}
//If the remaining damage after the shield handling code is smaller than initial damage amount,
//then a shield has absorbed some damage.
if(damageToBeDealt < damageAmount){
var shieldDamageTaken = damageAmount - damageToBeDealt;
//do stuff related to taking shield damage.
}
}
//If there's still damage to be dealt, deal it to health.
if(damageToBeDealt > 0){
health._currentHealth -= damageToBeDealt;
//do stuff related to taking damage to health.
}
}
};
/**
Heals the specified entity by the given value. Doesn't heal past maximum health.
@method healEntity
@param entity {Entity} Entity that will be healed.
@param healAmount {Number}
*/
this.healEntity = function(entity, healAmount){
var health = entity.get(Health);
if(health){
health._currentHealth += healAmount;
//Clamp the current health so that it can't be higher than maximum health.
health._currentHealth = Math.min(health._currentHealth, health._maximumHealth);
//do stuff related to healing
}
};
var healthEntities = entitySystemManager.createAspect([Health]);
/**
@method update
*/
this.update = (function(){
function checkHealth(entity){
var health = entity.get(Health);
if(health._currentHealth <= 0){
//Remove any over-kill damage.
health._currentHealth = 0;
//do stuff related to dying
thisHealthSystem.trigger(entityDied, entity);
}
}
return function(){
healthEntities.iterate(checkHealth);
};
})();
/**
@method destroy
*/
this.destroy = function(){
healthEntities.destroy();
};
}
//Inherit from the event handling object.
HealthSystem.prototype = Object.create(EventHandler.prototype);
HealthSystem.prototype.constructor = HealthSystem;