humus-old/common/combat/harmful.trait.js
2019-12-12 19:27:19 -06:00

184 lines
3.9 KiB
JavaScript

import * as I from 'immutable';
import {compose, merge} from '@avocado/core';
import {StateProperty, Trait} from '@avocado/entity';
import {fromRad, normalizeAngleRange, Vector} from '@avocado/math';
import {AFFINITY_PHYSICAL} from './constants';
const decorate = compose(
StateProperty('isHarmful'),
);
export class Harmful extends decorate(Trait) {
static defaultParams() {
return {
harmfulSound: '',
harmSpecs: [],
};
}
static defaultState() {
return {
isHarmful: true,
};
}
static type() {
return 'harmful';
}
constructor(entity, params, state) {
super(entity, params, state);
this._doesNotHarm = [];
const harmSpecsJSON = this.params.harmSpecs;
this._harmSpecs = harmSpecsJSON.map((harmSpec) => {
return {
lock: 0.1,
power: 0,
variance: 0.2,
...harmSpec,
};
});
this._harmfulSound = this.params.harmfulSound;
}
doesNotHarmEntity(entity) {
if (!this.entity.isHarmful) {
return true;
}
return -1 !== this._doesNotHarm.indexOf(entity);
}
get harmSpecs() {
return this._harmSpecs;
}
get harmfulSound() {
return this._harmfulSound;
}
tryHarmfulEntity(entity) {
if (this.doesNotHarmEntity(entity)) {
return;
}
if (entity.is('vulnerable')) {
if (!entity.isInvulnerable) {
entity.takeHarmFrom(this.entity);
}
}
}
hooks() {
return {
particles: () => {
return {
harmful: {
traits: {
emitted: {
params: {
alpha: {
start: 1,
end: .2,
},
rotation: {
start: 0,
add: {
min: -0.5,
max: 0.5,
},
},
scale: {
start: 1,
end: 1.25,
},
ttl: .2,
},
},
existent: {},
layered: {},
listed: {},
positioned: {},
roomed: {},
visible: {},
},
},
};
},
};
}
listeners() {
const listeners = {};
if (AVOCADO_SERVER) {
listeners.collisionStart = (other) => {
this.tryHarmfulEntity(other);
};
}
return listeners;
}
methods() {
return {
emitHarmfulParticles: (other, json = {}) => {
const diff = Vector.sub(this.entity.position, other.position);
const velocityAngle = Vector.toAngle(Vector.normalize(diff));
const [fromAngle, toAngle] = normalizeAngleRange(
velocityAngle - Math.PI / 8,
velocityAngle + Math.PI / 8,
);
this.entity.emitParticle('harmful', merge(
{},
{
traits: {
emitted: {
params: {
position: other.position,
velocity: {
angle: {
min: 450 - fromRad(fromAngle),
max: 450 - fromRad(toAngle),
},
magnitude: 0.5,
},
},
},
},
},
json,
));
},
setDoesHarm: (entity) => {
const index = this._doesNotHarm.indexOf(entity);
if (-1 !== index) {
this._doesNotHarm.splice(index, 1);
}
},
setDoesNotHarm: (entity) => {
if (-1 === this._doesNotHarm.indexOf(entity)) {
this._doesNotHarm.push(entity);
}
},
};
}
tick(elapsed) {
if (AVOCADO_SERVER) {
if (this.entity.is('collider')) {
const isCollidingWith = this.entity.isCollidingWith;
for (let i = 0; i < isCollidingWith.length; i++) {
this.tryHarmfulEntity(isCollidingWith[i]);
}
}
}
}
}