SOULGATE/server/game_state.py
2026-05-04 03:42:47 +02:00

185 lines
4.5 KiB
Python

# game_state.py : structures de donnees broadcastees au client a chaque tick
from dataclasses import dataclass, field
@dataclass
class ProjectileState:
id: str
owner_id: str
x: float
y: float
vx: float
vy: float
damage: int
radius: float
ttl: float
def to_dict(self):
# vx/vy/damage/ttl : info serveur, pas envoyes au client
return {
"id": self.id,
"owner": self.owner_id,
"x": self.x,
"y": self.y,
"radius": self.radius,
}
@dataclass
class EnemyState:
id: str
type: str
x: float
y: float
hp: int
max_hp: int
attack_cooldown: float = 0.0
is_boss: bool = False
frozen_timer: float = 0.0 # gel du sort divin Seris
data: dict = field(default_factory=dict) # interne au boss (phases, charge), pas broadcast
def to_dict(self):
return {
"id": self.id,
"type": self.type,
"x": self.x,
"y": self.y,
"hp": self.hp,
"max_hp": self.max_hp,
"is_boss": self.is_boss,
"frozen": self.frozen_timer > 0,
"is_charging": self.data.get("is_charging", False) if self.is_boss else False,
}
@dataclass
class PlayerState:
id: str
class_name: str
username: str
x: float
y: float
hp: int
max_hp: int
alive: bool
revive_progress: float = 0.0
cooldowns: dict = field(default_factory=lambda: {
"attack": 0,
"ability_1": 0,
"ability_2": 0,
"displacement": 0,
})
# buffs actifs : {"type": "...", "timer": float, ...}
# types : invulnerable, intangible, flying, casting, damage_mult, speed_mult, combat_buff, divine_freeze_dps
buffs: list = field(default_factory=list)
souls: int = 0
enemies_killed: int = 0
# upgrade_id -> nb stacks (damage_up, cooldown_down, hp_up, speed_up)
upgrades: dict = field(default_factory=dict)
def to_dict(self):
return {
"id": self.id,
"class": self.class_name,
"username": self.username,
"x": self.x,
"y": self.y,
"hp": self.hp,
"max_hp": self.max_hp,
"alive": self.alive,
"revive_progress": self.revive_progress,
"cooldowns": self.cooldowns,
"buffs": self.buffs,
"souls": self.souls,
"enemies_killed": self.enemies_killed,
"upgrades": self.upgrades,
}
@dataclass
class AoeZone:
id: str
owner_id: str
zone_type: str
x: float
y: float
radius: float
damage_per_tick: int
ticks_remaining: int
max_ticks: int
def to_dict(self):
return {
"id": self.id,
"type": self.zone_type,
"x": self.x,
"y": self.y,
"radius": self.radius,
"ticks": self.ticks_remaining,
"max_ticks": self.max_ticks,
}
@dataclass
class SoulgateState:
hp: int
max_hp: int
def to_dict(self):
return {"hp": self.hp, "max_hp": self.max_hp}
@dataclass
class WaveState:
number: int
phase: int
enemies_remaining: int
state: str # combat | preparation | boss | victory
prep_timer: float = 0.0
boss_hp: int = 0
boss_max_hp: int = 0
boss_name: str = ""
def to_dict(self):
return {
"number": self.number,
"phase": self.phase,
"enemies_remaining": self.enemies_remaining,
"state": self.state,
"prep_timer": self.prep_timer,
"boss_hp": self.boss_hp,
"boss_max_hp": self.boss_max_hp,
"boss_name": self.boss_name,
}
@dataclass
class GameState:
tick: int
players: list
enemies: list
projectiles: list
soulgate: SoulgateState
wave: WaveState
effects: list
aoe_zones: list = field(default_factory=list)
def to_dict(self):
return {
"type": "game_state",
"tick": self.tick,
"players": [p.to_dict() for p in self.players],
"enemies": [e.to_dict() for e in self.enemies],
"projectiles": [p.to_dict() for p in self.projectiles],
"aoe_zones": [z.to_dict() for z in self.aoe_zones],
"soulgate": self.soulgate.to_dict(),
"wave": self.wave.to_dict(),
"effects": self.effects,
}