File size: 2,978 Bytes
565f6e7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
import { Pilot, WeaponType } from "../../types";
import { WEAPON_SPECS_MAP } from "../aircraftData";
import { destructible } from "../../types/components";
import { applyComponentDamage } from "../flightModel";
import { Vector3 } from "three";

export class DamageSystem {
  public registerKill(
    killerId: string, 
    victimId: string, 
    weapon: string,
    pilots: Map<string, Pilot>,
    statePlayers: any,
    addTeamScore: (team: number, points: number) => void,
    broadcast: (type: string, msg: any) => void,
    scheduleRespawn: (id: string) => void
  ) {
    const killer = pilots.get(killerId);
    const victim = pilots.get(victimId);
    if (!victim) return;

    victim.deaths++;
    const vState = statePlayers.get(victimId);
    if (vState) vState.deaths++;

    let killerName = "System";
    if (killer) {
      killer.kills++;
      killer.score += 300;
      
      const kState = statePlayers.get(killerId);
      if (kState) {
        kState.kills++;
        kState.score += 300;
      }
      killerName = killer.name;
      addTeamScore(killer.team, 100);
    }

    broadcast("kill_confirmed", {
      killerId,
      victimId,
      killerName,
      victimName: victim.name,
      weapon
    });

    scheduleRespawn(victimId);
  }

  public applyDamage(
    pilot: Pilot,
    amount: number,
    hitZone: string,
    weapon: string,
    ownerId: string,
    registerKillFn: (k: string, v: string, w: string) => void
  ) {
    const spec = WEAPON_SPECS_MAP[weapon as WeaponType];
    const baseDamage = spec?.damage ?? 10;
    const finalDamage = baseDamage * amount;

    applyComponentDamage(pilot, finalDamage, weapon, hitZone);

    if (destructible(pilot.entity).damageModel!.fuselage <= 0 && !destructible(pilot.entity).isDead) {
      destructible(pilot.entity).isDead = true;
      registerKillFn(ownerId, pilot.id, weapon);
    }
  }

  public triggerSplashDamage(
    pos: Vector3,
    ownerId: string,
    team: number,
    type: WeaponType,
    pilots: Map<string, Pilot>,
    registerKillFn: (k: string, v: string, w: string) => void
  ) {
    const spec = WEAPON_SPECS_MAP[type];
    if (!spec || !spec.splashRadius) return;
    const radius = spec.splashRadius;
    const baseSplash = spec.damage * 0.8; 

    for (const pilot of pilots.values()) {
      if (pilot.team === team) continue;
      if (destructible(pilot.entity).isDead) continue;
      if (pilot.invulnerableTimer && pilot.invulnerableTimer > 0) continue;

      const dist = pos.distanceTo(new Vector3(pilot.x, pilot.y, pilot.z));
      if (dist <= radius) {
        const falloff = 1.0 - (dist / radius);
        const relativeOffset = new Vector3(0, -0.5, 0); 
        applyComponentDamage(pilot, baseSplash * falloff, String(type), relativeOffset);

        if (destructible(pilot.entity).damageModel!.fuselage <= 0) {
          destructible(pilot.entity).isDead = true;
          registerKillFn(ownerId, pilot.id, String(type));
        }
      }
    }
  }
}