edda_types/combat/
cost.rs1use uuid::Uuid;
7
8use super::{CombatCommand, CombatEvent, SpellSlot};
9use crate::CharacterAction;
10
11#[derive(Debug, Clone, PartialEq, Eq)]
14pub enum SheetCost {
15 Slot(SpellSlot),
16 Feature { name: String, amount: u16 },
17}
18
19impl SheetCost {
20 pub fn spend(&self) -> CharacterAction {
22 match self {
23 SheetCost::Slot(SpellSlot::Level(level)) => {
24 CharacterAction::ExpendSpellSlot { level: *level }
25 }
26 SheetCost::Slot(SpellSlot::Pact(_)) => CharacterAction::ExpendPactSlot,
27 SheetCost::Feature { name, amount } => CharacterAction::UseResource {
28 name: name.clone(),
29 amount: *amount,
30 },
31 }
32 }
33
34 pub fn give_back(&self) -> CharacterAction {
36 match self {
37 SheetCost::Slot(SpellSlot::Level(level)) => {
38 CharacterAction::RestoreSpellSlot { level: *level }
39 }
40 SheetCost::Slot(SpellSlot::Pact(_)) => CharacterAction::RestorePactSlot,
41 SheetCost::Feature { name, amount } => CharacterAction::RestoreResource {
42 name: name.clone(),
43 amount: *amount,
44 },
45 }
46 }
47}
48
49impl CombatCommand {
50 pub fn sheet_cost(&self) -> Option<(Uuid, SheetCost)> {
52 match self {
53 CombatCommand::CastSpell {
54 caster,
55 slot: Some(slot),
56 ..
57 } => Some((*caster, SheetCost::Slot(*slot))),
58 CombatCommand::UseFeature {
59 combatant,
60 feature,
61 amount,
62 } => Some((
63 *combatant,
64 SheetCost::Feature {
65 name: feature.clone(),
66 amount: *amount,
67 },
68 )),
69 _ => None,
70 }
71 }
72}
73
74impl CombatEvent {
75 pub fn sheet_cost(&self) -> Option<(Uuid, SheetCost)> {
78 match self {
79 CombatEvent::SpellCast {
80 caster,
81 slot: Some(slot),
82 ..
83 } => Some((*caster, SheetCost::Slot(*slot))),
84 CombatEvent::FeatureUsed {
85 combatant,
86 feature,
87 amount,
88 } => Some((
89 *combatant,
90 SheetCost::Feature {
91 name: feature.clone(),
92 amount: *amount,
93 },
94 )),
95 _ => None,
96 }
97 }
98}
99
100#[cfg(test)]
101mod tests {
102 use super::*;
103
104 #[test]
105 fn casts_and_feature_uses_cost_what_they_say_and_give_it_back() {
106 let caster = Uuid::new_v4();
107 let bless = CombatCommand::CastSpell {
108 caster,
109 spell: "Bless".into(),
110 slot: Some(SpellSlot::Level(2)),
111 targets: vec![],
112 concentration: None,
113 };
114 let (who, cost) = bless.sheet_cost().unwrap();
115 assert_eq!(who, caster);
116 assert_eq!(cost.spend(), CharacterAction::ExpendSpellSlot { level: 2 });
117 assert_eq!(
118 cost.give_back(),
119 CharacterAction::RestoreSpellSlot { level: 2 }
120 );
121
122 let pact = SheetCost::Slot(SpellSlot::Pact(3));
123 assert_eq!(pact.spend(), CharacterAction::ExpendPactSlot);
124 assert_eq!(pact.give_back(), CharacterAction::RestorePactSlot);
125
126 let cantrip = CombatCommand::CastSpell {
127 caster,
128 spell: "Fire Bolt".into(),
129 slot: None,
130 targets: vec![],
131 concentration: None,
132 };
133 assert_eq!(cantrip.sheet_cost(), None, "cantrips are free");
134
135 let used = CombatEvent::FeatureUsed {
136 combatant: caster,
137 feature: "Rage".into(),
138 amount: 1,
139 };
140 assert_eq!(
141 used.sheet_cost().unwrap().1.give_back(),
142 CharacterAction::RestoreResource {
143 name: "Rage".into(),
144 amount: 1
145 }
146 );
147 }
148}