Files
Genarrative/server-rs/crates/module-combat/src/domain.rs

119 lines
3.7 KiB
Rust

//! 战斗领域模型。
//!
//! 本文件只承载战斗聚合内部状态和值对象;背包奖励、成长记账和任务联动由
//! SpacetimeDB 事务 adapter 编排,不在战斗领域内直连其他上下文。
use module_runtime_item::RuntimeItemRewardItemSnapshot;
use serde::{Deserialize, Serialize};
#[cfg(feature = "spacetime-types")]
use spacetimedb::SpacetimeType;
/// 战斗状态 ID 的稳定前缀,由领域层统一持有,避免应用层重复拼接规则。
pub const BATTLE_STATE_ID_PREFIX: &str = "battle_";
/// 新建战斗状态的初始版本号,用于乐观更新和快照投影。
pub const INITIAL_BATTLE_VERSION: u32 = 1;
/// 普通战斗中敌方反击伤害占玩家输出的比例。
pub const BASIC_FIGHT_COUNTER_RATIO: f32 = 0.14;
/// 普通战斗中敌方反击的最低伤害,保证战斗有稳定消耗。
pub const MIN_FIGHT_COUNTER_DAMAGE: i32 = 4;
/// 切磋模式保底生命值,避免非生死战把玩家扣到 0。
pub const SPAR_MIN_HP: i32 = 1;
/// 旧版战斗动作 function id 白名单,仍由结算规则用于识别攻击类动作。
pub(crate) const LEGACY_ATTACK_FUNCTION_IDS: [&str; 5] = [
"battle_all_in_crush",
"battle_guard_break",
"battle_probe_pressure",
"battle_feint_step",
"battle_finisher_window",
];
/// 战斗模式,决定结算时是否允许击败玩家。
#[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum BattleMode {
Fight,
Spar,
}
impl BattleMode {
pub fn as_str(&self) -> &'static str {
match self {
Self::Fight => "fight",
Self::Spar => "spar",
}
}
}
/// 战斗状态,用于标记战斗是否仍可继续接收行动。
#[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum BattleStatus {
Ongoing,
Resolved,
Aborted,
}
impl BattleStatus {
pub fn as_str(&self) -> &'static str {
match self {
Self::Ongoing => "ongoing",
Self::Resolved => "resolved",
Self::Aborted => "aborted",
}
}
}
/// 单次战斗行动结算后的领域结果。
#[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum CombatOutcome {
Ongoing,
Victory,
SparComplete,
Escaped,
}
impl CombatOutcome {
pub fn as_str(&self) -> &'static str {
match self {
Self::Ongoing => "ongoing",
Self::Victory => "victory",
Self::SparComplete => "spar_complete",
Self::Escaped => "escaped",
}
}
}
#[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))]
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct BattleStateSnapshot {
pub battle_state_id: String,
pub story_session_id: String,
pub runtime_session_id: String,
pub actor_user_id: String,
pub chapter_id: Option<String>,
pub target_npc_id: String,
pub target_name: String,
pub battle_mode: BattleMode,
pub status: BattleStatus,
pub player_hp: i32,
pub player_max_hp: i32,
pub player_mana: i32,
pub player_max_mana: i32,
pub target_hp: i32,
pub target_max_hp: i32,
pub experience_reward: u32,
pub reward_items: Vec<RuntimeItemRewardItemSnapshot>,
pub turn_index: u32,
pub last_action_function_id: Option<String>,
pub last_action_text: Option<String>,
pub last_result_text: Option<String>,
pub last_damage_dealt: i32,
pub last_damage_taken: i32,
pub last_outcome: CombatOutcome,
pub version: u32,
pub created_at_micros: i64,
pub updated_at_micros: i64,
}