1
0
Fork 0

Remove system/component coupling

This commit is contained in:
Pabloader 2026-05-08 07:01:36 +00:00
parent a52762cc18
commit a14a602f23
3 changed files with 19 additions and 46 deletions

View File

@ -100,10 +100,6 @@ export class Effect extends BaseEffect {
if (this.state.permanent) {
this.entity.remove(this); // permanent effects are removed immediately
}
if (this.state.remaining || this.state.condition) {
this.ensureEffectSystem();
}
}
override onRemove(): void {
@ -118,7 +114,6 @@ export class Effect extends BaseEffect {
@action
reset(duration?: number): void {
this.ensureEffectSystem();
if (duration != null) {
this.state.duration = duration;
}
@ -129,33 +124,11 @@ export class Effect extends BaseEffect {
/** Mark as expired. EffectSystem will remove the component, which reverses the delta. */
@action
clear(): void {
this.ensureEffectSystem();
this.state.remaining = 0;
this.emit('expired');
}
update(dt: number): void {
if (this.state.remaining != null) {
if (this.state.remaining > 0) {
this.state.remaining -= dt;
if (this.state.remaining <= 0) {
this.clear();
}
if (this.state.gradual && this.state.duration) {
const delta = this.state.delta * dt / this.state.duration;
this.applyDelta(delta);
}
}
} else if (this.state.condition != null) {
if (!evaluateCondition(this.state.condition, this.entity)) {
this.clear();
}
}
// static effect (no duration, no condition): nothing to do
}
private applyDelta(delta: number) {
applyDelta(delta: number) {
const component = getComponentMeta(this.state.target);
if (component) {
const stat = this.entity.get(component.ctor, this.state.targetKey);
@ -165,14 +138,6 @@ export class Effect extends BaseEffect {
}
}
}
private async ensureEffectSystem() {
const { EffectSystem } = await import('@common/rpg/systems/effect');
if (!this.world.hasSystem(EffectSystem)) {
this.world.addSystem(new EffectSystem());
}
}
}
@component

View File

@ -19,15 +19,6 @@ export class Sprite extends Component<{
});
}
override async onAdd() {
if (Number.isFinite(this.state.animationDelay)) {
const { SpriteSystem } = await import('../systems/render/sprite'); // dynamic import to break cyclic dependency
if (!this.world.hasSystem(SpriteSystem)) {
this.world.addSystem(new SpriteSystem());
}
}
}
get image(): string {
return this.state.frames[this.state.currentFrame];
}

View File

@ -1,12 +1,29 @@
import { Effect } from "../components/effect";
import { Component, System, type Entity, type World } from "../core/world";
import { evaluateCondition } from "../utils/conditions";
export class EffectSystem extends System {
override update(world: World, dt: number) {
const expired: [Entity, Component<any>][] = [];
for (const [entity, , effect] of world.query(Effect)) {
effect.update(dt);
if (effect.state.remaining != null) {
if (effect.state.remaining > 0) {
effect.state.remaining -= dt;
if (effect.state.remaining <= 0) {
effect.clear();
}
if (effect.state.gradual && effect.state.duration) {
const delta = effect.state.delta * dt / effect.state.duration;
effect.applyDelta(delta);
}
}
} else if (effect.state.condition != null) {
if (!evaluateCondition(effect.state.condition, effect.entity)) {
effect.clear();
}
}
if (effect.state.remaining !== null && effect.state.remaining <= 0) {
expired.push([entity, effect]);
}