Skip to content

Combat

Two layers: ship-vs-ship/port/planet combat (CombatLog, CombatStats) and the fleet/drone subsystem (Fleet*, Drone*). CombatLog lives in combat_log.py.


CombatLog

Source: services/gameserver/src/models/combat_log.py

Purpose: Immutable per-engagement record (ship-vs-ship, port attack, planet defense). Captures forces, damage, loot, and admin moderation state.

Fields:

name type constraints notes
id UUID PK
attacker_id, defender_id UUID FK players.id nullable, SET NULL nullable so logs survive player deletes
attacker_ship_id, defender_ship_id UUID FK ships.id nullable, SET NULL
attacker_ship_name, defender_ship_name String(100) nullable denormalized snapshot
attacker_ship_type, defender_ship_type String(50) nullable denormalized
sector_id Integer nullable human-readable
sector_uuid UUID FK sectors.id nullable, SET NULL
port_id UUID FK stations.id nullable, SET NULL FK targets stations
planet_id UUID FK planets.id nullable, SET NULL
combat_type String(50) default ship_to_ship ship_to_ship/port_attack/planet_defense
outcome String(20) not null attacker_win/defender_win/draw/escaped (matches CombatOutcome)
attacker_drones, defender_drones Integer default 0 totals at start
attacker_attack_drones, attacker_defense_drones, defender_attack_drones, defender_defense_drones Integer default 0 by class
attacker_damage_dealt, defender_damage_dealt Integer default 0
attacker_drones_lost, defender_drones_lost Integer default 0
credits_looted Integer default 0
cargo_looted JSONB nullable commodity → quantity
experience_gained Integer default 0
combat_duration Float default 0.0 seconds
rounds Integer default 1
combat_log Text nullable textual play-by-play
timestamp DateTime server default now primary sort
started_at, ended_at DateTime mixed
admin_notes Text nullable
admin_resolved Boolean default false
admin_resolved_at DateTime nullable
disputed Boolean default false
resolved Boolean default true
admin_reviewed Boolean default false

Relationships: attacker, defender, attacker_ship, defender_ship, sector, station (via port_id), planet.


CombatStats

Source: services/gameserver/src/models/combat_log.py

Purpose: Daily aggregated combat statistics for admin dashboards.

Key fields: date (unique), counts (total_combats, ship_combats, port_attacks, planet_defenses), outcomes (attacker_wins, defender_wins, draws, escapes), economy (total_credits_looted, total_cargo_looted_value, average_loot_per_combat), efficiency (total_drones_lost, average_combat_duration, most_effective_ship_type), most_active_attacker_id / most_active_defender_id FK players, unique_combatants, calculated_at.


Drone

Source: services/gameserver/src/models/drone.py

Purpose: Individual deployable combat/scout/mining/repair unit. Drones live in sectors, fight, and accumulate stats.

Fields:

name type constraints notes
id UUID PK
player_id UUID FK players.id not null, CASCADE, indexed
team_id UUID FK teams.id nullable, SET NULL, indexed
drone_type String(50) not null attack/defense/scout/mining/repair (DroneType enum)
name String(100) nullable optional custom name
level Integer default 1
health, max_health Integer default 100
attack_power, defense_power Integer default 10
speed Float default 1.0
status String(50) default deployed deployed/combat/returning/destroyed/damaged
sector_id UUID FK sectors.id nullable, SET NULL, indexed
deployed_at, last_action DateTime nullable
kills, damage_dealt, damage_taken, battles_fought Integer default 0 lifetime stats
abilities String(255) nullable comma-separated ability IDs
destroyed_at DateTime nullable

Relationships: player, team, sector (back-pop deployed_drones); deploymentsDroneDeployment (1:many cascade).

DroneDeployment

Per-deployment record. Columns: drone_id FK CASCADE, player_id FK CASCADE, sector_id UUID FK sectors.id CASCADE, deployed_at, recalled_at, is_active, deployment_type (defense/patrol/mining/…), target_id (optional UUID, no FK), enemies_destroyed, resources_collected, damage_prevented.

DroneCombat

Per-engagement record between two drones. Columns: attacker_drone_id / defender_drone_id FK SET NULL, sector_id UUID FK SET NULL, started_at, ended_at, rounds, winner_drone_id, attacker_damage_dealt, defender_damage_dealt, combat_log String(2000) (JSON-encoded).


Fleet

Source: services/gameserver/src/models/fleet.py

Purpose: Group of ships organized for large-scale battle, scoped to a team.

Fields:

name type constraints notes
id UUID PK
team_id UUID FK teams.id not null, CASCADE, indexed
commander_id UUID FK players.id nullable, SET NULL
name String(100) not null
status String(50) default forming forming/ready/in_battle/retreating/disbanded (FleetStatus)
formation String(50) default standard
sector_id UUID FK sectors.id nullable, SET NULL, indexed
total_ships, total_firepower, total_shields, total_hull Integer default 0 aggregated from members
average_speed Float default 0.0
morale Integer default 100 0-100
supply_level Integer default 100 0-100
disbanded_at, last_battle DateTime nullable

Relationships: team, commander, sector, membersFleetMember (1:many cascade).

FleetMember

Columns: fleet_id FK CASCADE, ship_id FK CASCADE, player_id FK CASCADE, role (flagship/attacker/defender/support/scout), position, joined_at, ready_status.

FleetBattle

Inter-fleet engagement record. Key columns: attacker_fleet_id, defender_fleet_id, sector_id (all SET NULL on delete), phase (preparation/engagement/main_battle/pursuit/aftermath), started_at, ended_at, attacker_ships_initial, defender_ships_initial, winner (attacker/defender/draw), attacker_ships_destroyed, defender_ships_destroyed, attacker_ships_retreated, defender_ships_retreated, total_damage_dealt, attacker_damage_dealt, defender_damage_dealt, battle_log JSON, credits_looted, resources_looted JSON.

Relationships: attacker_fleet, defender_fleet, sector, ship_casualtiesFleetBattleCasualty (1:many cascade).

FleetBattleCasualty

Per-ship casualty entry. Columns: battle_id FK CASCADE, ship_id (SET NULL), player_id (SET NULL), fleet_id (SET NULL), ship_name and ship_type (denormalized in case of delete), was_attacker, destroyed, retreated, damage_taken, damage_dealt, kills, casualty_time, battle_phase.


Notes

  • CombatLog.combat_type is a free-form string mirroring the canonical values ship_to_ship, port_attack, planet_defense, sector_defense, ship_vs_drones, planet_defense, port_defense. CombatLog.outcome uses the CombatOutcome string enum from combat_log.py (ongoing/attacker_win/defender_win/draw/escaped).
  • CombatLog.port_id is named port_id but the FK targets stations.