1use crate::actor::{Action, ActorRules};
4use crate::battle::{Battle, BattleRules};
5use crate::entity::EntityId;
6use crate::error::{WeaselError, WeaselResult};
7use crate::event::{Event, EventKind, EventProcessor, EventQueue, EventRights, EventTrigger};
8use crate::util::Id;
9#[cfg(feature = "serialization")]
10use serde::{Deserialize, Serialize};
11use std::any::Any;
12
13pub type Ability<R> = <<R as BattleRules>::AR as ActorRules<R>>::Ability;
18
19pub type AbilityId<R> = <Ability<R> as Id>::Id;
21
22pub type AbilitiesSeed<R> = <<R as BattleRules>::AR as ActorRules<R>>::AbilitiesSeed;
24
25pub type Activation<R> = <<R as BattleRules>::AR as ActorRules<R>>::Activation;
30
31pub type AbilitiesAlteration<R> = <<R as BattleRules>::AR as ActorRules<R>>::AbilitiesAlteration;
33
34#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
68pub struct ActivateAbility<R: BattleRules> {
69 #[cfg_attr(
70 feature = "serialization",
71 serde(bound(
72 serialize = "EntityId<R>: Serialize",
73 deserialize = "EntityId<R>: Deserialize<'de>"
74 ))
75 )]
76 entity_id: EntityId<R>,
77
78 #[cfg_attr(
79 feature = "serialization",
80 serde(bound(
81 serialize = "AbilityId<R>: Serialize",
82 deserialize = "AbilityId<R>: Deserialize<'de>"
83 ))
84 )]
85 ability_id: AbilityId<R>,
86
87 #[cfg_attr(
88 feature = "serialization",
89 serde(bound(
90 serialize = "Option<Activation<R>>: Serialize",
91 deserialize = "Option<Activation<R>>: Deserialize<'de>"
92 ))
93 )]
94 activation: Option<Activation<R>>,
95}
96
97impl<R: BattleRules> ActivateAbility<R> {
98 pub fn trigger<P: EventProcessor<R>>(
100 processor: &mut P,
101 entity_id: EntityId<R>,
102 ability_id: AbilityId<R>,
103 ) -> ActivateAbilityTrigger<R, P> {
104 ActivateAbilityTrigger {
105 processor,
106 entity_id,
107 ability_id,
108 activation: None,
109 }
110 }
111
112 pub fn entity_id(&self) -> &EntityId<R> {
114 &self.entity_id
115 }
116
117 pub fn ability_id(&self) -> &AbilityId<R> {
119 &self.ability_id
120 }
121
122 pub fn activation(&self) -> &Option<Activation<R>> {
124 &self.activation
125 }
126}
127
128impl<R: BattleRules> std::fmt::Debug for ActivateAbility<R> {
129 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
130 write!(
131 f,
132 "ActivateAbility {{ entity_id: {:?}, ability_id: {:?}, activation: {:?} }}",
133 self.entity_id, self.ability_id, self.activation
134 )
135 }
136}
137
138impl<R: BattleRules> Clone for ActivateAbility<R> {
139 fn clone(&self) -> Self {
140 ActivateAbility {
141 entity_id: self.entity_id.clone(),
142 ability_id: self.ability_id.clone(),
143 activation: self.activation.clone(),
144 }
145 }
146}
147
148impl<R: BattleRules + 'static> Event<R> for ActivateAbility<R> {
149 fn verify(&self, battle: &Battle<R>) -> WeaselResult<(), R> {
150 if !self.entity_id.is_actor() {
152 return Err(WeaselError::NotAnActor(self.entity_id.clone()));
153 }
154 if let Some(actor) = battle.entities().actor(&self.entity_id) {
156 if !battle.state.rounds.is_acting(&self.entity_id) {
158 return Err(WeaselError::ActorNotReady(self.entity_id.clone()));
159 }
160 if let Some(ability) = actor.ability(&self.ability_id) {
162 battle
164 .rules
165 .actor_rules()
166 .activable(&battle.state, Action::new(actor, ability, &self.activation))
167 .map_err(|err| {
168 WeaselError::AbilityNotActivable(
169 self.entity_id.clone(),
170 self.ability_id.clone(),
171 Box::new(err),
172 )
173 })
174 } else {
175 Err(WeaselError::AbilityNotKnown(
176 self.entity_id.clone(),
177 self.ability_id.clone(),
178 ))
179 }
180 } else {
181 Err(WeaselError::EntityNotFound(self.entity_id.clone()))
182 }
183 }
184
185 fn apply(&self, battle: &mut Battle<R>, event_queue: &mut Option<EventQueue<R>>) {
186 let actor = battle
187 .state
188 .entities
189 .actor(&self.entity_id)
190 .unwrap_or_else(|| {
191 panic!("constraint violated: entity {:?} not found", self.entity_id)
192 });
193 let ability = actor.ability(&self.ability_id).unwrap_or_else(|| {
194 panic!(
195 "constraint violated: ability {:?} not found in actor {:?}",
196 self.ability_id, self.entity_id
197 )
198 });
199 battle.rules.actor_rules().activate(
200 &battle.state,
201 Action::new(actor, ability, &self.activation),
202 event_queue,
203 &mut battle.entropy,
204 &mut battle.metrics.write_handle(),
205 );
206 }
207
208 fn kind(&self) -> EventKind {
209 EventKind::ActivateAbility
210 }
211
212 fn box_clone(&self) -> Box<dyn Event<R> + Send> {
213 Box::new(self.clone())
214 }
215
216 fn as_any(&self) -> &dyn Any {
217 self
218 }
219
220 fn rights<'a>(&'a self, battle: &'a Battle<R>) -> EventRights<'a, R> {
221 let actor = battle
222 .state
223 .entities
224 .actor(&self.entity_id)
225 .unwrap_or_else(|| {
226 panic!("constraint violated: entity {:?} not found", self.entity_id)
227 });
228 EventRights::Team(actor.team_id())
229 }
230}
231
232pub struct ActivateAbilityTrigger<'a, R, P>
234where
235 R: BattleRules,
236 P: EventProcessor<R>,
237{
238 processor: &'a mut P,
239 entity_id: EntityId<R>,
240 ability_id: AbilityId<R>,
241 activation: Option<Activation<R>>,
242}
243
244impl<'a, R, P> ActivateAbilityTrigger<'a, R, P>
245where
246 R: BattleRules + 'static,
247 P: EventProcessor<R>,
248{
249 pub fn activation(&'a mut self, activation: Activation<R>) -> &'a mut Self {
251 self.activation = Some(activation);
252 self
253 }
254}
255
256impl<'a, R, P> EventTrigger<'a, R, P> for ActivateAbilityTrigger<'a, R, P>
257where
258 R: BattleRules + 'static,
259 P: EventProcessor<R>,
260{
261 fn processor(&'a mut self) -> &'a mut P {
262 self.processor
263 }
264
265 fn event(&self) -> Box<dyn Event<R> + Send> {
267 Box::new(ActivateAbility {
268 entity_id: self.entity_id.clone(),
269 ability_id: self.ability_id.clone(),
270 activation: self.activation.clone(),
271 })
272 }
273}