This commit is contained in:
Vasyl Kazakov
2026-05-29 18:01:05 +03:00
parent 2633be60a1
commit 6363396f84
20 changed files with 978 additions and 81 deletions
+96
View File
@@ -0,0 +1,96 @@
import { Object3D } from "three";
import { PhysicsBody } from "../PhysicsC";
import { PropType } from "./PropType";
import { PhysicsTriggerC } from "./PhysicsTriggerC";
import { PROP_DROPS } from "../Resources/PropDropTable";
import { createDropPlan, PropDropPlan } from "../Resources/PropDropPlanner";
import { ResourceSpawnC } from "../Resources/ResourceSpawnC";
export class PropRegistry {
private static props = new Map<Object3D, PropC>();
static register(prop: PropC) {
this.props.set(prop.object, prop);
}
static get(object: Object3D) {
return this.props.get(object);
}
}
export class PropC {
readonly object: Object3D;
readonly propType: PropType;
health: number;
readonly maxHealth: number;
isBroken = false;
private wallBodies: PhysicsBody[] = [];
private dropPlan: PropDropPlan | null = null;
constructor(object: Object3D, propType: PropType, maxHealth = 3) {
this.object = object;
this.propType = propType;
this.maxHealth = maxHealth;
this.health = maxHealth;
PropRegistry.register(this);
}
addWallBody(physicsBody: PhysicsBody) {
this.wallBodies.push(physicsBody);
}
takeDamage(amount: number): boolean {
if (this.isBroken) return false;
const hitIndex = this.maxHealth - this.health;
this.ensureDropPlan();
this.health -= amount;
this.spawnForHit(hitIndex);
if (this.health > 0) return false;
this.break();
return true;
}
break() {
if (this.isBroken) return;
this.isBroken = true;
this.object.visible = false;
this.wallBodies.forEach((body) => body.destroy());
this.wallBodies = [];
PhysicsTriggerC.unregister(this.object);
}
private ensureDropPlan() {
if (this.dropPlan) return;
const rules = PROP_DROPS[this.propType];
if (!rules.length) return;
this.dropPlan = createDropPlan(this.maxHealth, rules[0]);
}
private spawnForHit(hitIndex: number) {
if (!this.dropPlan) return;
let spawnCount = this.dropPlan.hitAmounts[hitIndex] ?? 0;
if (this.health <= 0) {
const remaining = this.dropPlan.totalDrop - this.dropPlan.spawnedDrop - spawnCount;
if (remaining > 0) {
spawnCount += remaining;
}
}
if (spawnCount <= 0) return;
ResourceSpawnC.spawnFromProp(this, this.dropPlan.resource, spawnCount);
this.dropPlan.spawnedDrop += spawnCount;
}
}