diff --git a/common/combat/damaging.trait.js b/common/combat/damaging.trait.js index c03b2fa..2bac75f 100644 --- a/common/combat/damaging.trait.js +++ b/common/combat/damaging.trait.js @@ -1,7 +1,8 @@ import * as I from 'immutable'; -import {compose} from '@avocado/core'; +import {compose, merge} from '@avocado/core'; import {StateProperty, Trait} from '@avocado/entity'; +import {fromRad, normalizeAngleRange, Vector} from '@avocado/math'; import {AFFINITY_PHYSICAL} from './constants'; @@ -70,6 +71,46 @@ export class Damaging extends decorate(Trait) { } } + hooks() { + return { + + particles: () => { + return { + damaging: { + 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) { @@ -83,6 +124,35 @@ export class Damaging extends decorate(Trait) { methods() { return { + emitDamagingParticles: (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('damaging', merge( + {}, + { + traits: { + emitted: { + params: { + position: other.position, + velocity: { + angle: { + min: 450 - fromRad(fromAngle), + max: 450 - fromRad(toAngle), + }, + magnitude: 0.5, + }, + }, + }, + }, + }, + json, + )); + }, + setDoesDamage: (entity) => { const index = this._doesNotDamage.indexOf(entity); if (-1 !== index) { diff --git a/common/combat/vulnerable.trait.js b/common/combat/vulnerable.trait.js index 0642fda..595826a 100644 --- a/common/combat/vulnerable.trait.js +++ b/common/combat/vulnerable.trait.js @@ -62,6 +62,9 @@ export class Vulnerable extends Trait { context.destroy(); }); this.damageTickingPromises.push(tickingPromise); + if (damage.from) { + damage.from.emitDamagingParticles(this.entity); + } } acceptPacket(packet) { @@ -134,10 +137,16 @@ export class Vulnerable extends Trait { end: 0, }, force: [0, 1], - velocity: [ - randomNumber(-0.5, 0.5), - randomNumber(-1.25, -0.75) - ], + velocity: { + angle: { + min: 337.5, + max: 382.5, + }, + magnitude: { + min: -1.25, + max: -0.75, + }, + }, rotation: { start: 0, add: { @@ -171,10 +180,16 @@ export class Vulnerable extends Trait { start: 1, end: 0.4, }, - force: [0, 4], + force: [0, 3], velocity: { - min: [-0.5, -1.25], - max: [0.5, -0.75], + angle: { + min: 316, + max: 405, + }, + magnitude: { + min: 0.7, + max: 0.9, + }, }, scale: { start: 1, diff --git a/common/traits/lootable.trait.js b/common/traits/lootable.trait.js index 7841966..0668481 100644 --- a/common/traits/lootable.trait.js +++ b/common/traits/lootable.trait.js @@ -56,10 +56,16 @@ export class Lootable extends decorate(Trait) { json.traits.emitted = { params: { force: [0, 8], - velocity: [ - randomNumber(-0.5, 0.5), - randomNumber(-1.25, -0.75) - ], + velocity: { + angle: { + min: 316, + max: 405, + }, + magnitude: { + min: 0.7, + max: 0.9, + }, + }, position, transient: false, ttl: 0.25, diff --git a/server/fixtures/rock-projectile.entity.js b/server/fixtures/rock-projectile.entity.js index 1b052f4..cba309d 100644 --- a/server/fixtures/rock-projectile.entity.js +++ b/server/fixtures/rock-projectile.entity.js @@ -65,7 +65,7 @@ export function rockProjectileJSON() { ['Math', 'Vector', 'sub'], [ buildTraversal(['entity', 'position']), - buildTraversal(['obstacle', 'position']), + buildTraversal(['other', 'position']), ], ), 0.2, @@ -136,7 +136,7 @@ export function rockProjectileJSON() { buildInvoke( ['entity', 'context', 'add'], [ - 'obstacle', + 'other', buildTraversal(['other']), ], ), @@ -167,6 +167,34 @@ export function rockProjectileJSON() { directionCount: 4, }, }, + emitter: { + params: { + particles: { + damaging: { + rate: 0.0125, + count: 5, + traits: { + primitive: { + params: { + primitives: [ + { + type: 'circle', + radius: 0.5, + line: { + rgba: [128, 128, 128], + }, + fill: { + rgba: [128, 128, 128], + }, + }, + ], + }, + }, + }, + }, + }, + }, + }, existent: { state: { name: 'Rock (projectile)',