overlord_event_system/logic/
auto_chest.rs1use crate::{
2 event::OverlordEvent, game_config_helpers::GameConfigLookup, logic::handler::OverlordLogic,
3 state::OverlordState,
4};
5
6use essences::autochest::{AutoChestFilter, AutoChestFilterId};
7use event_system::{event::EventPluginized, system::EventHandleResult};
8
9impl OverlordLogic {
10 pub fn handle_enable_auto_chest(
11 &self,
12 mut state: OverlordState,
13 ) -> EventHandleResult<OverlordEvent, OverlordState> {
14 let game_config = self.game_config.get();
15
16 let level_gate = game_config
20 .gatings
21 .autochest
22 .autochest_button_unlock_character_level;
23 if state.character_state.character.character_level < level_gate {
24 tracing::warn!(
25 "EnableAutoChest rejected: character_level {} < gate {}",
26 state.character_state.character.character_level,
27 level_gate
28 );
29 return EventHandleResult::fail(state);
30 }
31
32 let events = if !state.character_state.character.auto_chest_enabled {
33 state.character_state.character.auto_chest_enabled = true;
34
35 vec![EventPluginized::delayed(
36 OverlordEvent::AutoChestOpenItemCase {
37 batch_size: state.auto_chest.batch_size,
38 },
39 game_config.game_settings.auto_chest_pause_duration_ticks,
40 )]
41 } else {
42 vec![]
43 };
44
45 EventHandleResult::ok_events(state, events)
46 }
47
48 pub fn handle_disable_auto_chest(
49 &self,
50 mut state: OverlordState,
51 ) -> EventHandleResult<OverlordEvent, OverlordState> {
52 state.character_state.character.auto_chest_enabled = false;
53
54 EventHandleResult::ok(state)
55 }
56
57 pub fn handle_enable_auto_chest_filter(
58 &self,
59 filter_id: AutoChestFilterId,
60 mut state: OverlordState,
61 ) -> EventHandleResult<OverlordEvent, OverlordState> {
62 let Some(filter) = state.auto_chest.filters.iter().find(|f| f.id == filter_id) else {
63 tracing::error!(
64 "Tried enabling auto_chest filter with id = {}, but didnt find it in state",
65 filter_id
66 );
67 return EventHandleResult::fail(state);
68 };
69
70 state.character_state.character.last_filter_used_id = Some(filter.id);
71
72 state.auto_chest.active_filter = Some(filter.clone());
73
74 EventHandleResult::ok(state)
75 }
76
77 pub fn handle_disable_auto_chest_filter(
78 &self,
79 mut state: OverlordState,
80 ) -> EventHandleResult<OverlordEvent, OverlordState> {
81 state.auto_chest.active_filter = None;
82
83 EventHandleResult::ok(state)
84 }
85
86 pub fn handle_enable_auto_chest_power_compare(
87 &self,
88 mut state: OverlordState,
89 ) -> EventHandleResult<OverlordEvent, OverlordState> {
90 state.auto_chest.power_compare_enabled = true;
91
92 EventHandleResult::ok(state)
93 }
94
95 pub fn handle_disable_auto_chest_power_compare(
96 &self,
97 mut state: OverlordState,
98 ) -> EventHandleResult<OverlordEvent, OverlordState> {
99 state.auto_chest.power_compare_enabled = false;
100
101 EventHandleResult::ok(state)
102 }
103
104 pub fn handle_update_auto_chest_batch_size(
105 &self,
106 batch_size: i64,
107 mut state: OverlordState,
108 ) -> EventHandleResult<OverlordEvent, OverlordState> {
109 let game_config = self.game_config.get();
110 let Some(item_case_settings) = game_config
111 .item_case_settings_by_level(state.character_state.character.item_case_level)
112 else {
113 tracing::error!(
114 "No item case settings for level = {}",
115 state.character_state.character.item_case_level
116 );
117 return EventHandleResult::fail(state);
118 };
119
120 if batch_size
121 > item_case_settings
122 .auto_chest_settings
123 .auto_only_max_batch_size
124 {
125 tracing::error!(
126 "Batch size = {}, is bigger than auto max = {}",
127 batch_size,
128 item_case_settings
129 .auto_chest_settings
130 .auto_only_max_batch_size,
131 );
132 return EventHandleResult::fail(state);
133 }
134 state.auto_chest.batch_size = batch_size;
135
136 EventHandleResult::ok(state)
137 }
138
139 pub fn handle_new_auto_chest_filter(
140 &self,
141 filter: AutoChestFilter,
142 mut state: OverlordState,
143 ) -> EventHandleResult<OverlordEvent, OverlordState> {
144 let game_config = self.game_config.get();
145
146 if let Err(e) = filter.validate(
147 state.character_state.character.current_chapter_level,
148 state.character_state.character.character_level,
149 &game_config.attributes,
150 &game_config.gatings.autochest,
151 ) {
152 tracing::error!("Filter {:?},\n Didn't pass validation: {:?}", filter, e);
153 return EventHandleResult::fail(state);
154 }
155
156 if let Some(existing) = state
160 .auto_chest
161 .filters
162 .iter_mut()
163 .find(|f| f.id == filter.id)
164 {
165 *existing = filter.clone();
166 } else {
167 state.auto_chest.filters.push(filter.clone());
168 }
169
170 Self::refresh_active_filter(&mut state, &filter);
171
172 EventHandleResult::ok(state)
173 }
174
175 fn refresh_active_filter(state: &mut OverlordState, updated: &AutoChestFilter) {
179 if let Some(active) = &mut state.auto_chest.active_filter
180 && active.id == updated.id
181 {
182 *active = updated.clone();
183 }
184 }
185
186 pub fn handle_update_auto_chest_filter(
187 &self,
188 updated_filter: AutoChestFilter,
189 mut state: OverlordState,
190 ) -> EventHandleResult<OverlordEvent, OverlordState> {
191 let game_config = self.game_config.get();
192
193 let Some(old_filter) = state
194 .auto_chest
195 .filters
196 .iter_mut()
197 .find(|f| f.id == updated_filter.id)
198 else {
199 tracing::error!(
200 "Tried updating auto_chest filter with id = {}, but didn't find it in state",
201 updated_filter.id
202 );
203 return EventHandleResult::fail(state);
204 };
205
206 if let Err(e) = updated_filter.validate(
207 state.character_state.character.current_chapter_level,
208 state.character_state.character.character_level,
209 &game_config.attributes,
210 &game_config.gatings.autochest,
211 ) {
212 tracing::error!(
213 "Filter {:?}, didn't pass validation = {:?}",
214 updated_filter,
215 e
216 );
217 return EventHandleResult::fail(state);
218 }
219
220 *old_filter = updated_filter.clone();
221
222 Self::refresh_active_filter(&mut state, &updated_filter);
223
224 EventHandleResult::ok(state)
225 }
226
227 pub fn handle_remove_auto_chest_filter(
228 &self,
229 filter_id: AutoChestFilterId,
230 mut state: OverlordState,
231 ) -> EventHandleResult<OverlordEvent, OverlordState> {
232 let Some(filter_position) = state
233 .auto_chest
234 .filters
235 .iter()
236 .position(|filter| filter.id == filter_id)
237 else {
238 tracing::error!(
239 "Tried removing filter with id = {}, but didn't find it in state",
240 filter_id
241 );
242 return EventHandleResult::fail(state);
243 };
244
245 if state.character_state.character.last_filter_used_id == Some(filter_id) {
246 state.character_state.character.last_filter_used_id = None;
247 }
248
249 if state
252 .auto_chest
253 .active_filter
254 .as_ref()
255 .is_some_and(|f| f.id == filter_id)
256 {
257 state.auto_chest.active_filter = None;
258 }
259
260 state.auto_chest.filters.remove(filter_position);
261
262 EventHandleResult::ok(state)
263 }
264}