wowlab_engine_domain/rotation/lower/action/
terminators.rs1use wowlab_types::{constants::WAIT_UNTIL_POLL_SECS, game::GearSlot, sim::Condition};
2
3use super::{
4 super::{
5 super::{backend::RotationBackend, condition::spell_usable_condition},
6 condition::lower_condition,
7 },
8 LowerCtx, LoweredGuard, failing_condition, lower_optional_guard, record_guarded,
9 record_skipped, skip_in_run,
10};
11
12pub(super) fn lower_cast<B>(
13 ctx: &mut LowerCtx<'_, '_, '_, B>,
14 spell: &str,
15 empower_rank: Option<u8>,
16 condition: Option<&Condition>,
17) where
18 B: RotationBackend,
19{
20 let Ok(spell_id) = ctx.lo.resolver.resolve_spell(spell) else {
21 record_skipped(ctx, failing_condition(condition));
22
23 return;
24 };
25
26 if skip_in_run(ctx, condition) {
27 return;
28 }
29
30 let usable = spell_usable_condition(spell);
31 let cast_condition = condition.map_or(usable.clone(), |condition| Condition::And {
32 operands: vec![usable, condition.clone()],
33 });
34 let guard = LoweredGuard {
35 bool_val: lower_condition(ctx.lo, ctx.b, &cast_condition).into_bool(ctx.b),
36 is_unconditional: false,
37 };
38
39 ctx.b
40 .return_cast_if(guard.bool_val, spell_id.0, empower_rank.unwrap_or(0));
41 record_guarded(ctx, &guard, Some(&cast_condition));
42}
43
44pub(super) fn lower_wait<B>(
45 ctx: &mut LowerCtx<'_, '_, '_, B>,
46 seconds: f64,
47 condition: Option<&Condition>,
48) where
49 B: RotationBackend,
50{
51 if skip_in_run(ctx, condition) {
52 return;
53 }
54
55 let secs = crate::numeric::rotation_payload_f32(seconds);
56 let guard = lower_optional_guard(ctx.lo, ctx.b, condition);
57
58 ctx.b.return_wait_if(guard.bool_val, secs);
59 record_guarded(ctx, &guard, condition);
60}
61
62pub(super) fn lower_wait_until<B>(ctx: &mut LowerCtx<'_, '_, '_, B>, condition: &Condition)
63where
64 B: RotationBackend,
65{
66 if ctx.lo.run_depth > 0 {
67 record_skipped(ctx, condition);
68
69 return;
70 }
71
72 let satisfied = lower_condition(ctx.lo, ctx.b, condition).into_bool(ctx.b);
73 let unsatisfied = ctx.b.not_b(satisfied);
74
75 ctx.b.return_wait_if(unsatisfied, WAIT_UNTIL_POLL_SECS);
76 ctx.b.record_action_guarded(
77 ctx.action.list_id,
78 ctx.action.action_index,
79 ctx.action.action,
80 ctx.action.is_term,
81 unsatisfied,
82 condition,
83 );
84}
85
86pub(super) fn lower_pool<B>(
87 ctx: &mut LowerCtx<'_, '_, '_, B>,
88 extra: Option<f64>,
89 condition: Option<&Condition>,
90) where
91 B: RotationBackend,
92{
93 if skip_in_run(ctx, condition) {
94 return;
95 }
96
97 let target = crate::numeric::rotation_payload_f32(extra.unwrap_or(0.0));
98 let guard = lower_optional_guard(ctx.lo, ctx.b, condition);
99
100 ctx.b.return_pool_if(guard.bool_val, target);
101 record_guarded(ctx, &guard, condition);
102}
103
104pub(super) fn lower_use_trinket<B>(
105 ctx: &mut LowerCtx<'_, '_, '_, B>,
106 slot: u8,
107 empower_rank: Option<u8>,
108 condition: Option<&Condition>,
109) where
110 B: RotationBackend,
111{
112 if skip_in_run(ctx, condition) {
113 return;
114 }
115
116 let Some(gear_slot) = GearSlot::trinket_from_index(slot) else {
117 tracing::warn!(
118 slot,
119 "use_trinket references an invalid trinket index, skipping"
120 );
121 record_skipped(ctx, failing_condition(condition));
122
123 return;
124 };
125
126 emit_use_item(ctx, gear_slot, empower_rank, condition);
127}
128
129pub(super) fn lower_use_item<B>(
130 ctx: &mut LowerCtx<'_, '_, '_, B>,
131 name: &str,
132 empower_rank: Option<u8>,
133 condition: Option<&Condition>,
134) where
135 B: RotationBackend,
136{
137 if skip_in_run(ctx, condition) {
138 return;
139 }
140
141 let Some(gear_slot) = GearSlot::from_slug(name) else {
142 tracing::warn!(
143 item = name,
144 "use_item references an unknown gear slot name, skipping"
145 );
146 record_skipped(ctx, failing_condition(condition));
147
148 return;
149 };
150
151 emit_use_item(ctx, gear_slot, empower_rank, condition);
152}
153
154fn emit_use_item<B>(
155 ctx: &mut LowerCtx<'_, '_, '_, B>,
156 gear_slot: GearSlot,
157 empower_rank: Option<u8>,
158 condition: Option<&Condition>,
159) where
160 B: RotationBackend,
161{
162 let gear_slot = gear_slot as u8;
164 let guard = lower_optional_guard(ctx.lo, ctx.b, condition);
165
166 ctx.b
167 .return_use_item_if(guard.bool_val, gear_slot, empower_rank.unwrap_or(0));
168 record_guarded(ctx, &guard, condition);
169}