109 lines
2.5 KiB
JavaScript
109 lines
2.5 KiB
JavaScript
import * as I from 'immutable';
|
|
|
|
import {Trait} from '@avocado/entity';
|
|
import {hasGraphics, TextNodeRenderer} from '@avocado/graphics';
|
|
|
|
import {DamageEmitter} from './emitter';
|
|
|
|
export class Vulnerable extends Trait {
|
|
|
|
static defaultState() {
|
|
return {
|
|
damageList: I.Map(),
|
|
};
|
|
}
|
|
|
|
initialize() {
|
|
this.damageList = {};
|
|
this.locks = new Map();
|
|
if (hasGraphics) {
|
|
this.emitter = new DamageEmitter();
|
|
this.setRenderer();
|
|
}
|
|
}
|
|
|
|
patchStateStep(key, step) {
|
|
if ('state' !== key) {
|
|
return;
|
|
}
|
|
const stateKey = step.path.substr(1);
|
|
const value = this.transformPatchValue(stateKey, step.value);
|
|
const stateKeyParts = stateKey.split('/');
|
|
switch (stateKeyParts[0]) {
|
|
case 'damageList':
|
|
for (let i = 0; i < value.length; ++i) {
|
|
const amount = value[i];
|
|
this.emitter.emit(this.entity.position, amount);
|
|
}
|
|
break;
|
|
default:
|
|
super.patchStateStep(key, step);
|
|
break;
|
|
}
|
|
}
|
|
|
|
setRenderer() {
|
|
if (this.entity.is('staged') && this.entity.stage) {
|
|
const renderer = new TextNodeRenderer('.damage', this.entity.stage);
|
|
this.emitter.addRenderer(renderer);
|
|
}
|
|
}
|
|
|
|
listeners() {
|
|
return {
|
|
|
|
stageChanged: () => {
|
|
this.setRenderer();
|
|
},
|
|
|
|
};
|
|
}
|
|
|
|
methods() {
|
|
return {
|
|
|
|
takeDamageFrom: (entity) => {
|
|
if (this.locks.has(entity)) {
|
|
return;
|
|
}
|
|
this.locks.set(entity, entity.lock);
|
|
const variance = Math.random() * entity.variance * 2 - entity.variance;
|
|
const difference = entity.power * variance;
|
|
const amount = (entity.power + difference) >> 0;
|
|
if (!this.damageList[entity.instanceUuid]) {
|
|
this.damageList[entity.instanceUuid] = [];
|
|
}
|
|
this.damageList[entity.instanceUuid].push(amount);
|
|
},
|
|
|
|
};
|
|
}
|
|
|
|
tick(elapsed) {
|
|
if (this.state.get('damageList').size > 0) {
|
|
this.state = this.state.set('damageList', I.Map());
|
|
}
|
|
if (Object.keys(this.damageList).length > 0) {
|
|
this.state = this.state.set('damageList', I.Map(this.damageList));
|
|
this.isDirty = true;
|
|
this.damageList = {};
|
|
}
|
|
if (hasGraphics) {
|
|
this.emitter.tick(elapsed);
|
|
}
|
|
const keys = Array.from(this.locks.keys());
|
|
for (let i = 0; i < keys.length; ++i) {
|
|
const key = keys[i];
|
|
const remaining = this.locks.get(key) - elapsed;
|
|
if (remaining <= 0) {
|
|
this.locks.delete(key);
|
|
}
|
|
else {
|
|
this.locks.set(key, remaining);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|