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 drones — combat_service.attack_sector_drones.
- Planet — combat_service.attack_planet.
- Port / station — combat_service.attack_port.
- Fleet vs fleet — fleet_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 consciousness —
winner.aria_total_interactions += 1. Thresholds: 50 → L2 (1.1× turn regen), 150 → L3 (1.2×), 400 → L4 (1.35×), 1000 → L5 (1.5×). - Medals —
MedalService.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".
- Bounty —
BountyService.collect_bountyif 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}inservices/gameserver/src/api/routes/fleets.pyraises aNameErrorat 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 |