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

283 lines
8.6 KiB
Rust

//! 任务领域模型。
//!
//! 本文件承载任务状态、步骤、奖励、叙事绑定和进度信号等稳定值对象。
use serde::{Deserialize, Serialize};
#[cfg(feature = "spacetime-types")]
use spacetimedb::SpacetimeType;
pub const QUEST_LOG_ID_PREFIX: &str = "questlog_";
#[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum QuestStatus {
Active,
ReadyToTurnIn,
Completed,
TurnedIn,
Failed,
Expired,
}
#[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum QuestNarrativeType {
Bounty,
Escort,
Investigation,
Retrieval,
Relationship,
Trial,
}
#[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum QuestObjectiveKind {
DefeatHostileNpc,
InspectTreasure,
SparWithNpc,
TalkToNpc,
ReachScene,
DeliverItem,
}
#[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum QuestRewardItemRarity {
Common,
Uncommon,
Rare,
Epic,
Legendary,
}
#[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum QuestNarrativeOrigin {
AiCompiled,
FallbackBuilder,
}
#[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum QuestLogEventKind {
Accepted,
Progressed,
Completed,
CompletionAcknowledged,
TurnedIn,
}
#[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum QuestSignalKind {
HostileNpcDefeated,
TreasureInspected,
NpcSparCompleted,
NpcTalkCompleted,
SceneReached,
ItemDelivered,
}
#[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))]
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct QuestRewardItem {
pub item_id: String,
pub category: String,
pub name: String,
pub description: Option<String>,
pub quantity: u32,
pub rarity: QuestRewardItemRarity,
pub tags: Vec<String>,
pub stackable: bool,
pub stack_key: String,
pub equipment_slot_id: Option<QuestRewardEquipmentSlot>,
}
#[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum QuestRewardEquipmentSlot {
Weapon,
Armor,
Relic,
}
#[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))]
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct QuestRewardIntel {
pub rumor_text: String,
pub unlocked_scene_id: Option<String>,
}
#[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))]
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct QuestRewardSnapshot {
pub affinity_bonus: i32,
pub currency: i64,
pub experience: Option<u32>,
pub items: Vec<QuestRewardItem>,
pub intel: Option<QuestRewardIntel>,
pub story_hint: Option<String>,
}
#[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))]
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct QuestNarrativeBindingSnapshot {
pub origin: QuestNarrativeOrigin,
pub narrative_type: QuestNarrativeType,
pub dramatic_need: String,
pub issuer_goal: String,
pub player_hook: String,
pub world_reason: String,
pub followup_hooks: Vec<String>,
}
#[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))]
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct QuestObjectiveSnapshot {
pub kind: QuestObjectiveKind,
pub target_hostile_npc_id: Option<String>,
pub target_npc_id: Option<String>,
pub target_scene_id: Option<String>,
pub target_item_id: Option<String>,
pub required_count: u32,
}
#[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))]
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct QuestStepSnapshot {
pub step_id: String,
pub kind: QuestObjectiveKind,
pub target_hostile_npc_id: Option<String>,
pub target_npc_id: Option<String>,
pub target_scene_id: Option<String>,
pub target_item_id: Option<String>,
pub required_count: u32,
pub progress: u32,
pub title: String,
pub reveal_text: String,
pub complete_text: String,
}
#[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))]
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct QuestRecordSnapshot {
pub quest_id: String,
pub runtime_session_id: String,
pub story_session_id: Option<String>,
pub actor_user_id: String,
pub issuer_npc_id: String,
pub issuer_npc_name: String,
pub scene_id: Option<String>,
pub chapter_id: Option<String>,
pub act_id: Option<String>,
pub thread_id: Option<String>,
pub contract_id: Option<String>,
pub title: String,
pub description: String,
pub summary: String,
pub objective: QuestObjectiveSnapshot,
pub progress: u32,
pub status: QuestStatus,
pub completion_notified: bool,
pub reward: QuestRewardSnapshot,
pub reward_text: String,
pub narrative_binding: QuestNarrativeBindingSnapshot,
pub steps: Vec<QuestStepSnapshot>,
pub active_step_id: Option<String>,
pub visible_stage: u32,
pub hidden_flags: Vec<String>,
pub discovered_fact_ids: Vec<String>,
pub related_carrier_ids: Vec<String>,
pub consequence_ids: Vec<String>,
pub created_at_micros: i64,
pub updated_at_micros: i64,
pub completed_at_micros: Option<i64>,
pub turned_in_at_micros: Option<i64>,
}
#[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))]
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct QuestHostileNpcDefeatedSignal {
pub scene_id: Option<String>,
pub hostile_npc_id: String,
}
#[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))]
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct QuestTreasureInspectedSignal {
pub scene_id: Option<String>,
}
#[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))]
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct QuestNpcSparCompletedSignal {
pub npc_id: String,
}
#[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))]
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct QuestNpcTalkCompletedSignal {
pub npc_id: String,
}
#[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))]
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct QuestSceneReachedSignal {
pub scene_id: String,
}
#[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))]
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct QuestItemDeliveredSignal {
pub npc_id: String,
pub item_id: String,
pub quantity: u32,
}
#[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))]
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum QuestProgressSignal {
HostileNpcDefeated(QuestHostileNpcDefeatedSignal),
TreasureInspected(QuestTreasureInspectedSignal),
NpcSparCompleted(QuestNpcSparCompletedSignal),
NpcTalkCompleted(QuestNpcTalkCompletedSignal),
SceneReached(QuestSceneReachedSignal),
ItemDelivered(QuestItemDeliveredSignal),
}
impl QuestStatus {
pub fn is_terminal(self) -> bool {
matches!(self, Self::TurnedIn | Self::Failed | Self::Expired)
}
pub fn is_reward_ready(self) -> bool {
matches!(self, Self::ReadyToTurnIn | Self::Completed)
}
}
impl QuestLogEventKind {
pub fn as_str(self) -> &'static str {
match self {
Self::Accepted => "accepted",
Self::Progressed => "progressed",
Self::Completed => "completed",
Self::CompletionAcknowledged => "completion_ack",
Self::TurnedIn => "turned_in",
}
}
}
impl From<&QuestProgressSignal> for QuestSignalKind {
fn from(value: &QuestProgressSignal) -> Self {
match value {
QuestProgressSignal::HostileNpcDefeated(_) => Self::HostileNpcDefeated,
QuestProgressSignal::TreasureInspected(_) => Self::TreasureInspected,
QuestProgressSignal::NpcSparCompleted(_) => Self::NpcSparCompleted,
QuestProgressSignal::NpcTalkCompleted(_) => Self::NpcTalkCompleted,
QuestProgressSignal::SceneReached(_) => Self::SceneReached,
QuestProgressSignal::ItemDelivered(_) => Self::ItemDelivered,
}
}
}