//! 成长领域模型。 //! //! 本文件只承载玩家等级、章节预算、自动定级和实体强度相关的稳定值对象; //! 任务、战斗、NPC 等奖励来源通过应用服务输入和领域事件接入。 use serde::{Deserialize, Serialize}; #[cfg(feature = "spacetime-types")] use spacetimedb::SpacetimeType; /// 玩家成长系统当前允许的最高等级。 pub const MAX_PLAYER_LEVEL: u32 = 20; /// 根据章节数推导终局叙事等级时的默认上限。 pub const DEFAULT_TERMINAL_STORY_LEVEL: u32 = 15; /// 根据章节数推导终局叙事等级时的最低上限。 pub const MIN_TERMINAL_STORY_LEVEL: u32 = 5; /// 章节 pseudo level 曲线指数,保持与既有 Node 侧节奏一致。 pub const PSEUDO_LEVEL_CURVE_EXPONENT: f64 = 0.92; #[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))] #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] pub enum PlayerProgressionGrantSource { Quest, HostileNpc, } impl PlayerProgressionGrantSource { pub fn as_str(&self) -> &'static str { match self { Self::Quest => "quest", Self::HostileNpc => "hostile_npc", } } } #[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))] #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] pub enum ChapterPaceBand { OpeningFast, Steady, Pressure, FinaleDense, } impl ChapterPaceBand { pub fn as_str(&self) -> &'static str { match self { Self::OpeningFast => "opening_fast", Self::Steady => "steady", Self::Pressure => "pressure", Self::FinaleDense => "finale_dense", } } } #[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))] #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] pub enum ProgressionRole { Guide, Ambient, Support, HostileStandard, HostileElite, HostileBoss, Rival, } impl ProgressionRole { pub fn as_str(&self) -> &'static str { match self { Self::Guide => "guide", Self::Ambient => "ambient", Self::Support => "support", Self::HostileStandard => "hostile_standard", Self::HostileElite => "hostile_elite", Self::HostileBoss => "hostile_boss", Self::Rival => "rival", } } } #[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))] #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] pub enum LevelProfileSource { ChapterAuto, PresetOverride, Manual, } impl LevelProfileSource { pub fn as_str(&self) -> &'static str { match self { Self::ChapterAuto => "chapter_auto", Self::PresetOverride => "preset_override", Self::Manual => "manual", } } } #[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))] #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct LevelBenchmark { pub level: u32, pub xp_to_next_level: u32, pub cumulative_xp_required: u32, pub reference_strength: u32, pub base_hp: u32, pub base_mana: u32, pub baseline_damage_scale: f32, } #[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))] #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct PlayerProgressionSnapshot { pub user_id: String, pub level: u32, pub current_level_xp: u32, pub total_xp: u32, pub xp_to_next_level: u32, pub pending_level_ups: u32, pub last_granted_source: Option, pub created_at_micros: i64, pub updated_at_micros: i64, } #[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))] #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct ChapterProgressionSnapshot { pub user_id: String, pub chapter_id: String, pub chapter_index: u32, pub total_chapters: u32, pub entry_pseudo_level_millis: u32, pub exit_pseudo_level_millis: u32, pub entry_level: u32, pub exit_level: u32, pub planned_total_xp: u32, pub planned_quest_xp: u32, pub planned_hostile_xp: u32, pub actual_quest_xp: u32, pub actual_hostile_xp: u32, pub expected_hostile_defeat_count: u32, pub actual_hostile_defeat_count: u32, pub level_at_entry: u32, pub level_at_exit: Option, pub pace_band: ChapterPaceBand, pub created_at_micros: i64, pub updated_at_micros: i64, } #[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))] #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct RuntimeEntityLevelProfile { pub level: u32, pub reference_strength: u32, pub chapter_id: Option, pub chapter_index: Option, pub progression_role: ProgressionRole, pub source: LevelProfileSource, }