chore: sync codebase remediation, gameplay systems, and docs
Security & infrastructure: - Remove unused services/ (auth, spacetimedb) and auth.db - Add .env.example template, expand .gitignore for env/db files - Add GitHub Actions CI + commitlint config and workflows - Add manual vendor chunking and source maps to docs/site vite configs Shared UI & docs app: - Add ARIA props and focus-visible rings to Button/Panel - Add ButtonAsLink primitive; use shared Button in NotFound - Wire @void-nav/ui into docs app; refresh content pages - Replace Todo page with Kanban board Gameplay (Bevy): - Add ai module (behavior, faction, navigation, perception, spawning, states) - Add narrative module (events, history, synthesis, ui) - Refine galaxy contents and in-system flight/scene systems
This commit is contained in:
212
apps/game/src/gameplay/narrative/events.rs
Normal file
212
apps/game/src/gameplay/narrative/events.rs
Normal file
@@ -0,0 +1,212 @@
|
||||
//! Event logging system.
|
||||
//!
|
||||
//! Captures all player actions as structured events that become
|
||||
//! the foundation for narrative generation.
|
||||
|
||||
use bevy::prelude::*;
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::gameplay::narrative::CampaignHistory;
|
||||
|
||||
/// All possible game events that can occur in a campaign.
|
||||
#[derive(Event, Debug, Clone)]
|
||||
pub enum GameEvent {
|
||||
/// Player mined ore from an asteroid belt
|
||||
Mining(MiningEvent),
|
||||
/// Player bought or sold items at a station
|
||||
Trade(TradeEvent),
|
||||
/// Player engaged in combat
|
||||
Combat(CombatEvent),
|
||||
/// Player discovered a new system or POI
|
||||
Exploration(ExplorationEvent),
|
||||
/// Player docked at a station
|
||||
Docking(DockingEvent),
|
||||
/// Player accepted/abandoned/failed a mission
|
||||
Mission(MissionEvent),
|
||||
/// Custom event for extensible storytelling
|
||||
Custom(CustomEvent),
|
||||
}
|
||||
|
||||
/// Event from mining activities.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct MiningEvent {
|
||||
pub timestamp: f64,
|
||||
pub location: String,
|
||||
pub ore_type: String,
|
||||
pub quantity: u32,
|
||||
pub duration_seconds: f32,
|
||||
}
|
||||
|
||||
/// Event from trading activities.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct TradeEvent {
|
||||
pub timestamp: f64,
|
||||
pub station: String,
|
||||
pub faction: String,
|
||||
pub is_purchase: bool,
|
||||
pub item_name: String,
|
||||
pub quantity: u32,
|
||||
pub unit_price: f32,
|
||||
pub total_value: f32,
|
||||
}
|
||||
|
||||
/// Event from combat activities.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CombatEvent {
|
||||
pub timestamp: f64,
|
||||
pub location: String,
|
||||
pub opponent: String,
|
||||
pub opponent_faction: Option<String>,
|
||||
pub outcome: CombatOutcome,
|
||||
pub hull_remaining: f32,
|
||||
pub rewards_earned: Option<f32>,
|
||||
}
|
||||
|
||||
/// Outcome of a combat engagement.
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum CombatOutcome {
|
||||
Victory,
|
||||
Defeat,
|
||||
Retreat,
|
||||
Draw,
|
||||
}
|
||||
|
||||
/// Event from exploration activities.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ExplorationEvent {
|
||||
pub timestamp: f64,
|
||||
pub location: String,
|
||||
pub discovery_type: DiscoveryType,
|
||||
pub description: String,
|
||||
}
|
||||
|
||||
/// Types of discoveries.
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum DiscoveryType {
|
||||
NewSystem,
|
||||
NewStation,
|
||||
Anomaly,
|
||||
Derelict,
|
||||
ResourceDeposit,
|
||||
}
|
||||
|
||||
/// Event from docking activities.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct DockingEvent {
|
||||
pub timestamp: f64,
|
||||
pub station: String,
|
||||
pub system: String,
|
||||
pub faction: String,
|
||||
pub visit_duration_seconds: f32,
|
||||
}
|
||||
|
||||
/// Event from mission activities.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct MissionEvent {
|
||||
pub timestamp: f64,
|
||||
pub mission_id: String,
|
||||
pub mission_type: String,
|
||||
pub event_type: MissionEventType,
|
||||
pub outcome: Option<MissionOutcome>,
|
||||
}
|
||||
|
||||
/// Type of mission event.
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum MissionEventType {
|
||||
Accepted,
|
||||
Completed,
|
||||
Abandoned,
|
||||
Failed,
|
||||
}
|
||||
|
||||
/// Outcome of a completed mission.
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum MissionOutcome {
|
||||
Success,
|
||||
PartialSuccess,
|
||||
Failure,
|
||||
}
|
||||
|
||||
/// Custom event for extensible storytelling.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CustomEvent {
|
||||
pub timestamp: f64,
|
||||
pub event_type: String,
|
||||
pub title: String,
|
||||
pub description: String,
|
||||
pub metadata: HashMap<String, String>,
|
||||
}
|
||||
|
||||
impl GameEvent {
|
||||
/// Get the timestamp of this event.
|
||||
pub fn timestamp(&self) -> f64 {
|
||||
match self {
|
||||
GameEvent::Mining(e) => e.timestamp,
|
||||
GameEvent::Trade(e) => e.timestamp,
|
||||
GameEvent::Combat(e) => e.timestamp,
|
||||
GameEvent::Exploration(e) => e.timestamp,
|
||||
GameEvent::Docking(e) => e.timestamp,
|
||||
GameEvent::Mission(e) => e.timestamp,
|
||||
GameEvent::Custom(e) => e.timestamp,
|
||||
}
|
||||
}
|
||||
|
||||
/// Get a short title for this event.
|
||||
pub fn title(&self) -> String {
|
||||
match self {
|
||||
GameEvent::Mining(e) => format!("Mined {} {}", e.quantity, e.ore_type),
|
||||
GameEvent::Trade(e) => {
|
||||
if e.is_purchase {
|
||||
format!("Purchased {} {}", e.quantity, e.item_name)
|
||||
} else {
|
||||
format!("Sold {} {}", e.quantity, e.item_name)
|
||||
}
|
||||
}
|
||||
GameEvent::Combat(e) => match e.outcome {
|
||||
CombatOutcome::Victory => format!("Victory over {}", e.opponent),
|
||||
CombatOutcome::Defeat => format!("Defeated by {}", e.opponent),
|
||||
CombatOutcome::Retreat => format!("Retreated from {}", e.opponent),
|
||||
CombatOutcome::Draw => format!("Draw with {}", e.opponent),
|
||||
},
|
||||
GameEvent::Exploration(e) => match e.discovery_type {
|
||||
DiscoveryType::NewSystem => format!("Discovered system: {}", e.location),
|
||||
DiscoveryType::NewStation => format!("Discovered station: {}", e.location),
|
||||
DiscoveryType::Anomaly => format!("Found anomaly: {}", e.description),
|
||||
DiscoveryType::Derelict => format!("Found derelict: {}", e.description),
|
||||
DiscoveryType::ResourceDeposit => format!("Found resource: {}", e.description),
|
||||
},
|
||||
GameEvent::Docking(e) => format!("Docked at {}", e.station),
|
||||
GameEvent::Mission(e) => format!(
|
||||
"{:?} mission: {}",
|
||||
e.event_type, e.mission_id
|
||||
),
|
||||
GameEvent::Custom(e) => e.title.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the location where this event occurred.
|
||||
pub fn location(&self) -> String {
|
||||
match self {
|
||||
GameEvent::Mining(e) => e.location.clone(),
|
||||
GameEvent::Trade(e) => e.station.clone(),
|
||||
GameEvent::Combat(e) => e.location.clone(),
|
||||
GameEvent::Exploration(e) => e.location.clone(),
|
||||
GameEvent::Docking(e) => e.system.clone(),
|
||||
GameEvent::Mission(e) => "Unknown".to_string(),
|
||||
GameEvent::Custom(e) => e.metadata.get("location").cloned().unwrap_or_default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Log game events to campaign history.
|
||||
///
|
||||
/// This system listens for GameEvents and adds them to the CampaignHistory.
|
||||
pub fn log_game_events(
|
||||
mut events: EventReader<GameEvent>,
|
||||
mut history: ResMut<CampaignHistory>,
|
||||
) {
|
||||
for event in events.read() {
|
||||
bevy::log::debug!("Logging game event: {}", event.title());
|
||||
history.add_event(event.clone());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user