86 lines
3.2 KiB
TypeScript
86 lines
3.2 KiB
TypeScript
import { System } from '../core/System.ts';
|
|
import { SystemName, ComponentType } from '../core/Constants.ts';
|
|
import type { Entity } from '../core/Entity.ts';
|
|
import type { Stealth } from '../components/Stealth.ts';
|
|
import type { Velocity } from '../components/Velocity.ts';
|
|
import type { Combat } from '../components/Combat.ts';
|
|
import type { Evolution } from '../components/Evolution.ts';
|
|
import type { InputSystem } from './InputSystem.ts';
|
|
import type { PlayerControllerSystem } from './PlayerControllerSystem.ts';
|
|
|
|
/**
|
|
* System responsible for managing stealth mechanics, including visibility updates based on form, movement, and combat.
|
|
*/
|
|
export class StealthSystem extends System {
|
|
constructor() {
|
|
super(SystemName.STEALTH);
|
|
this.requiredComponents = [ComponentType.STEALTH];
|
|
this.priority = 12;
|
|
}
|
|
|
|
/**
|
|
* Update stealth state for entities, handling toggle input and form-specific visibility changes.
|
|
* @param deltaTime - Time elapsed since last frame in seconds
|
|
* @param entities - Entities matching active required components
|
|
*/
|
|
process(deltaTime: number, entities: Entity[]): void {
|
|
const inputSystem = this.engine.systems.find((s) => s.name === SystemName.INPUT) as
|
|
| InputSystem
|
|
| undefined;
|
|
const playerController = this.engine.systems.find(
|
|
(s) => s.name === SystemName.PLAYER_CONTROLLER
|
|
) as PlayerControllerSystem | undefined;
|
|
const player = playerController ? playerController.getPlayerEntity() : null;
|
|
|
|
entities.forEach((entity) => {
|
|
const stealth = entity.getComponent<Stealth>(ComponentType.STEALTH);
|
|
const velocity = entity.getComponent<Velocity>(ComponentType.VELOCITY);
|
|
const combat = entity.getComponent<Combat>(ComponentType.COMBAT);
|
|
const evolution = entity.getComponent<Evolution>(ComponentType.EVOLUTION);
|
|
|
|
if (!stealth) return;
|
|
|
|
if (evolution) {
|
|
const form = evolution.getDominantForm();
|
|
stealth.stealthType = form;
|
|
}
|
|
|
|
if (entity === player && inputSystem) {
|
|
const shiftPress = inputSystem.isKeyJustPressed('shift');
|
|
if (shiftPress) {
|
|
if (stealth.isStealthed) {
|
|
stealth.exitStealth();
|
|
} else {
|
|
stealth.enterStealth(stealth.stealthType);
|
|
}
|
|
}
|
|
}
|
|
|
|
const isMoving = velocity && (Math.abs(velocity.vx) > 1 || Math.abs(velocity.vy) > 1);
|
|
const isInCombat = combat && combat.isAttacking;
|
|
|
|
stealth.updateStealth(isMoving || false, isInCombat || false);
|
|
|
|
if (stealth.isStealthed) {
|
|
switch (stealth.stealthType) {
|
|
case 'slime':
|
|
if (!isMoving) {
|
|
stealth.visibility = Math.max(0.05, stealth.visibility - deltaTime * 0.2);
|
|
}
|
|
break;
|
|
case 'beast':
|
|
if (isMoving && velocity) {
|
|
const speed = Math.sqrt(velocity.vx * velocity.vx + velocity.vy * velocity.vy);
|
|
if (speed < 50) {
|
|
stealth.visibility = Math.max(0.1, stealth.visibility - deltaTime * 0.1);
|
|
}
|
|
}
|
|
break;
|
|
case 'human':
|
|
stealth.visibility = Math.max(0.2, stealth.visibility - deltaTime * 0.05);
|
|
break;
|
|
}
|
|
}
|
|
});
|
|
}
|
|
}
|