Skip to content

Combat

How fights happen — from a one-on-one dogfight to a team-scale fleet battle. Numbers below come from the implementation.

Scope and target classifications

Combat targets, in code: - Ship (PvP or vs hostile NPC) — combat_service.attack_player. - Sector dronescombat_service.attack_sector_drones. - Planetcombat_service.attack_planet. - Port / stationcombat_service.attack_port. - Fleet vs fleetfleet_service.py.

Initiating combat costs turns; defending is free. Defender-side cost is read from the defender ship type's ShipSpecification.attack_turn_cost — meaning it is intentionally expensive to attack tiny targets like an escape pod (which is set to a very high attack cost to discourage pod-killing).

Default turn costs (combat_service.py):

Action Turns
Attack player ship attack_turn_cost of defender's ship type, min 2
Attack sector drones 2
Attack planet 3
Attack port 3
Defend 0

Combat resolution model

The resolver is in services/gameserver/src/services/combat_service.py (~1940 lines; entry points _resolve_ship_combat, _resolve_drone_combat, _resolve_planet_combat, _resolve_port_combat).

Ship-vs-ship

Inputs: - Ship hull and shield values (per ship row). - Drone counts (Player.attack_drones, Player.defense_drones). - Ship type matchup multiplier (SHIP_COMBAT_MODIFIERS): - DEFENDER vs CARGO_HAULER = 1.5× - DEFENDER vs LIGHT_FREIGHTER = 1.3× - FAST_COURIER vs CARRIER = 0.7× - SCOUT vs CARRIER = 0.5× - CARRIER vs SCOUT = 1.8× - CARRIER vs FAST_COURIER = 1.5× - COLONY_SHIP vs DEFENDER = 0.5× - Default weapon by ship (SHIP_DEFAULT_WEAPONS): scout uses emp, defender plasma, carrier missile, warp jumper plasma, others laser. - Weapon profile (WEAPON_TYPES):

Weapon Base vs Shields vs Hull
laser 1.0 0.8 1.0
plasma 1.2 1.2 0.9
missile 1.5 0.6 1.5
emp 0.5 2.0 0.3

Damage stack:

shieldDamage = min(baseDamage, target.shields) × (1 - shieldResistance)
hullDamage   = (baseDamage - shieldDamage)      × (1 - armorRating)
critical     = critical ? hullDamage × 0.5 : 0

Round-by-round drone attrition is rolled stochastically; outcome is one of ATTACKER_VICTORY, DEFENDER_VICTORY, DRAW. Logged to CombatLog.

Sector drones

Defender drones get a +5% bonus over ship-deployed drones (SECTOR_DEFENSE). Drone-vs-drone exchanges resolve probabilistically until one side hits zero; survivor keeps remaining drones.

Planet assault

Assault is rejected if attacker is the owner, planet has no owner, or attacker is docked/landed. Resolution incorporates planet.defense_level, deployed drones, citadel-level defenses (turrets, shields, orbital platforms, rail guns — see planets/defense.md). On capture, ownership transfers atomically.

Port assault

Port defenses scale with port class — Class 1: 50 drones; Class 2: 100; Class 3: 200; Class 4: 300 + auto-turrets; Class 5: 500 + advanced grid. Successful raid temporarily disables the port (regen ~24h). 🚧 Partial — full takeover/sabotage flow is design-stage.

Escape mechanics

Players can attempt to flee. Success is a function of: - Ship type — Fast Courier and Scout get a flat boost (FAST_ESCAPE_SHIP_TYPES). - Remaining hull (lower hull = harder). - Distance to sector edge (closer = better). - Pursuer ship class (heavier ships pursue worse).

If a ship is destroyed: 1. Player is auto-ejected to escape pod. 2. Cargo lost. Credits retained. 3. If insured, payout based on InsuranceType (see ships.md). 4. Combat log records cause and salvage.

Post-combat hooks

combat_service.attack_player fires the following on resolution (best-effort; failures are logged but don't roll back the fight):

  • Ranking — winner gets rank points via RankingService.calculate_combat_points (see ranking.md).
  • ARIA consciousnesswinner.aria_total_interactions += 1. Thresholds: 50 → L2 (1.1× turn regen), 150 → L3 (1.2×), 400 → L4 (1.35×), 1000 → L5 (1.5×).
  • MedalsMedalService.check_combat_medals(winner_id, victory_count) (Bronze Star at 100 wins, Silver at 1k, Quantum Cross at 10k).
  • Personal reputation (PersonalReputationService):
  • Killed a defender with active bounties → +100, "defeat_bounty_target".
  • Killed an innocent (no bounty) → −100, "attack_innocent".
  • Killed a defender in an escape pod → additional −500, "kill_escape_pod".
  • Successfully defended → +50, "defend_against_attacker".
  • BountyBountyService.collect_bounty if the defender had bounties placed (see bounties.md).

Drones

Drone type Cost (cr) Notes
Attack 1,000 Offensive primary
Defense 1,200 Damage reduction

Every 10 attack drones = +5% combat effectiveness; every 10 defense drones = −5% incoming damage. Drones prefer engaging enemy drones first.

Code: services/drone_service.py, model models/drone.py.

Weapons

combat_service.py:WEAPON_TYPES covers laser/plasma/missile/emp. 🚧 Planned — fuller weapon catalog (autocannon, particle, torpedo, tractor, mining); the resolver currently consumes only the four primary types listed above.

Fleet battles

services/fleet_service.py (~908 lines) handles team fleets: - Roles: Attacker, Defender, Scout, Support, Commander. - Formations: Standard, Wedge (+20% off / −10% def), Defensive (+30% def / −20% off), Offensive (+30% off / −30% def), Scatter (+30% evasion / −40% coordination). - Stats aggregated from member ships' combat JSONB via _recalculate_fleet_stats. - Status machine: forming → ready → deployed → in_combat → disbanded.

Battle records are persisted as FleetBattle + FleetBattleCasualty rows.

Status: 🐛 Bug — GET /api/v1/fleets/{fleet_id} in services/gameserver/src/api/routes/fleets.py raises a NameError at runtime because of an undefined symbol in the response builder. Other fleet routes function; this single endpoint must be fixed before fleet detail loads.

🚧 Planned: large-scale (100v100+) tier with tiered subscriptions, dedicated combat-engine cluster, distributed processing, broadcasting. Current fleet system handles team-vs-team coordinated combat at moderate scale.

Sector control & deployable assets

  • Deployed drones can be left in a sector to defend it (one player per sector). Deployed drones get +5% effectiveness vs ship-based.
  • Mines (2,000 cr each, design) damage hostile entrants.
  • Rented NPC defenders — design only, not implemented in code.

See galaxy/sectors.md.

Player-facing affordances

  • Combat HUD shows hull/shield/cargo, weapon list, target, action buttons (Attack / Defend / Evade / Flee).
  • Turn cost preview before initiating.
  • Combat log (models/combat_log.py) is queryable per player and shows full history.

Source map

Topic Path
Player-vs-player resolver services/gameserver/src/services/combat_service.py
Drone combat helpers services/gameserver/src/services/combat_service.py:_resolve_drone_combat
Player combat orchestration services/gameserver/src/services/player_combat_service.py
Fleet battles services/gameserver/src/services/fleet_service.py
Combat models services/gameserver/src/models/combat.py, combat_log.py
Drones services/gameserver/src/models/drone.py, services/drone_service.py
Combat REST routes services/gameserver/src/api/routes/combat.py, player_combat.py
Admin combat tools services/gameserver/src/api/routes/admin_combat.py
Ranking hook services/gameserver/src/services/ranking_service.py
Reputation hook services/gameserver/src/services/personal_reputation_service.py
Bounty hook services/gameserver/src/services/bounty_service.py
Medal hook services/gameserver/src/services/medal_service.py