refactor: harm

This commit is contained in:
cha0s 2024-10-18 07:49:15 -05:00
parent b2b52b5414
commit 6c815e7749
6 changed files with 102 additions and 4 deletions

View File

@ -0,0 +1,31 @@
import Component from '@/ecs/component.js';
export default class Harmful extends Component {
instanceFromSchema() {
const {ecs} = this;
return class HarmfulInstance extends super.instanceFromSchema() {
harm(other) {
const entity = ecs.get(this.entity);
const script = this.$$harm.clone();
script.locals.other = other;
script.locals.entity = entity;
entity.Ticking.add(script.ticker());
}
}
}
load(instance) {
// heavy handed...
if ('undefined' !== typeof window) {
return;
}
instance.$$harm = this.ecs.readScript(
instance.harmScript,
{
ecs: this.ecs,
},
);
}
static properties = {
harmScript: {type: 'string'},
};
}

View File

@ -1,4 +1,6 @@
import Component from '@/ecs/component.js'; import Component from '@/ecs/component.js';
import * as Math from '@/util/math.js';
import Ticker from '@/util/ticker.js';
export const DamageTypes = { export const DamageTypes = {
PAIN: 0, PAIN: 0,
@ -21,12 +23,20 @@ export default class Vulnerable extends Component {
const Component = this; const Component = this;
return class VulnerableInstance extends super.instanceFromSchema() { return class VulnerableInstance extends super.instanceFromSchema() {
id = 0; id = 0;
locked = new Set();
Types = DamageTypes; Types = DamageTypes;
damage(specification) { damage(fullSpecification) {
if (this.isInvulnerable) { if (this.isInvulnerable) {
return; return;
} }
const {Alive} = Component.ecs.get(this.entity); const {
lockout,
...specification
} = fullSpecification;
if (lockout && this.locked.has(lockout.subject)) {
return;
}
const {Alive, Forces, Position, Ticking} = Component.ecs.get(this.entity);
if (Alive) { if (Alive) {
switch (specification.type) { switch (specification.type) {
case DamageTypes.HEALING: case DamageTypes.HEALING:
@ -35,6 +45,28 @@ export default class Vulnerable extends Component {
} }
} }
} }
if (specification.knockback) {
const diff = Math.normalizeVector({
x: Position.x - specification.knockback.origin.x,
y: Position.y - specification.knockback.origin.y,
});
Forces.applyImpulse({
x: diff.x * specification.knockback.magnitude,
y: diff.y * specification.knockback.magnitude,
});
}
if (lockout) {
let {duration, subject} = lockout;
const self = this;
self.locked.add(subject);
Ticking.add(new Ticker(function*() {
while (duration > 0) {
const elapsed = yield;
duration -= elapsed;
}
self.locked.delete(subject);
}));
}
Component.markChange( Component.markChange(
this.entity, this.entity,
'damage', 'damage',

24
app/ecs/systems/harm.js Normal file
View File

@ -0,0 +1,24 @@
import {System} from '@/ecs/index.js';
export default class Harm extends System {
static queries() {
return {
default: ['Collider', 'Harmful'],
};
}
tick() {
for (const entity of this.select('default')) {
const intersecting = new Set();
for (const [other] of entity.Collider.$$intersections) {
intersecting.add(this.ecs.get(other.entity));
}
for (const other of intersecting) {
entity.Harmful.harm(other);
}
}
}
}

View File

@ -9,6 +9,7 @@ export default function createEcs(Ecs) {
'Attract', 'Attract',
'ResetForces', 'ResetForces',
'ApplyControlMovement', 'ApplyControlMovement',
'Harm',
'IntegratePhysics', 'IntegratePhysics',
'ClampPositions', 'ClampPositions',
'PlantGrowth', 'PlantGrowth',

View File

@ -3,12 +3,20 @@ import * as Math from '@/util/math.js';
export default function*({ecs, entity, other}) { export default function*({ecs, entity, other}) {
const playerEntity = ecs.lookupPlayerEntity(entity.Owned.owner); const playerEntity = ecs.lookupPlayerEntity(entity.Owned.owner);
if (playerEntity !== other && other.Vulnerable) { if (playerEntity !== other && other.Vulnerable) {
const magnitude = Math.floor(Math.random() * 2) const magnitude = Math.floor(Math.random() * 1);
other.Vulnerable.damage({ other.Vulnerable.damage({
amount: -Math.floor( amount: -Math.floor(
Math.pow(10, magnitude) Math.pow(10, magnitude)
+ Math.random() * (Math.pow(10, magnitude + 1) - Math.pow(10, magnitude)), + Math.random() * (Math.pow(10, magnitude + 1) - Math.pow(10, magnitude)),
), ),
knockback: {
magnitude: 150,
origin: entity.Position,
},
lockout: {
duration: 0.5,
subject: entity,
},
position: other.Position.toJSON(), position: other.Position.toJSON(),
type: other.Vulnerable.Types.PAIN, type: other.Vulnerable.Types.PAIN,
}) })

View File

@ -28,11 +28,13 @@ export default function*(locals) {
unstoppable: 1, unstoppable: 1,
}, },
], ],
collisionStartScript: '/resources/magic-swords/collision-start.js',
}, },
Controlled: {}, Controlled: {},
Direction: {direction: offset + Math.TAU * (i / N)}, Direction: {direction: offset + Math.TAU * (i / N)},
Forces: {}, Forces: {},
Harmful: {
harmScript: '/resources/magic-swords/harm.js',
},
Light: {brightness: 0}, Light: {brightness: 0},
Owned: {owner: Player ? Player.id : 0}, Owned: {owner: Player ? Player.id : 0},
Position: {x: Position.x, y: Position.y}, Position: {x: Position.x, y: Position.y},