humus-old/common/combat/alive.trait.js
2019-05-03 02:23:43 -05:00

133 lines
2.7 KiB
JavaScript

import {
behaviorItemFromJSON,
buildCondition,
buildInvoke,
buildTraversal,
createContext,
} from '@avocado/behavior';
import {compose} from '@avocado/core';
import {StateProperty, Trait} from '@avocado/entity';
const decorate = compose(
StateProperty('life', {
track: true,
}),
StateProperty('maxLife', {
track: true,
}),
);
export class Alive extends decorate(Trait) {
static defaultParams() {
const playDeathSound = buildInvoke(['entity', 'playSound'], [
buildTraversal(['entity', 'deathSound']),
]);
const squeeze = buildInvoke(['entity', 'transition'], [
{
opacity: 0,
visibleScaleX: .3,
visibleScaleY: 3,
},
0.2,
]);
const isLifeGone = buildCondition('<=', [
buildTraversal(['entity', 'life']),
0,
]);
return {
deathActions: {
type: 'actions',
traversals: [
playDeathSound,
squeeze,
],
},
deathCondition: isLifeGone,
deathSound: 'deathSound',
};
}
static defaultState() {
return {
life: 100,
maxLife: 100,
};
}
initialize() {
this._context = createContext();
this._context.add('entity', this.entity);
const actionsJSON = this.params.get('deathActions').toJS();
this._deathActions = behaviorItemFromJSON(actionsJSON);
this._deathSound = this.params.get('deathSound');
const conditionJSON = this.params.get('deathCondition').toJS();
this._deathCondition = behaviorItemFromJSON(conditionJSON);
this._isDying = false;
}
destroy() {
this._context.clear();
}
get deathSound() {
return this._deathSound;
}
listeners() {
return {
tookDamage: (damage, source) => {
if (damage.damageSpec.power > 0) {
this.entity.life -= damage.amount;
}
else {
this.entity.life += damage.amount;
}
// Clamp health between 0 and max.
this.entity.life = Math.min(
Math.max(0, this.entity.life),
this.entity.maxLife
);
},
}
}
methods() {
return {
dieIfPossible: () => {
if (this._deathCondition.check(this._context)) {
this.entity.forceDeath();
}
},
forceDeath: () => {
if (this._isDying) {
return;
}
this._isDying = true;
this.entity.emit('dying');
this._deathActions.once('actionsFinished', () => {
if (this.entity.is('existent')) {
this.entity.destroy();
}
});
},
};
}
tick(elapsed) {
if (this._isDying) {
this._deathActions.tick(this._context, elapsed);
}
else {
this.entity.dieIfPossible();
}
}
}