184 lines
3.9 KiB
JavaScript
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]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|