diff --git a/bot_core.py b/bot_core.py index 0d1aaec..ab0a942 100644 --- a/bot_core.py +++ b/bot_core.py @@ -101,9 +101,16 @@ class DirtyLeagueBot: self.scaled_templates[name_without_ext] = img logging.info(f"Loaded {len(self.base_templates)} base template(s) from '{self.assets_dir}'") + def get_frame_scale(self, frame: np.ndarray) -> float: + """ + Calculates UI scaling factor relative to base design height. + Unity Canvas Scaler in DirtyLeague scales UI proportionally to screen height. + """ + return frame.shape[0] / float(self.BASE_DESIGN_HEIGHT) + def get_scaled_template(self, template_name: str, scale: float) -> Optional[np.ndarray]: """ - Retrieves template scaled for the given resolution scale factor (fw / BASE_DESIGN_WIDTH). + Retrieves template scaled for the given resolution scale factor (fh / BASE_DESIGN_HEIGHT). Caches scaled results so resizing only happens on window resolution changes. """ if template_name not in self.base_templates: @@ -137,7 +144,7 @@ class DirtyLeagueBot: Returns client center coordinates (center_x, center_y) if matched, else None. """ fh, fw = frame.shape[:2] - scale = fw / float(self.BASE_DESIGN_WIDTH) + scale = self.get_frame_scale(frame) tpl = self.get_scaled_template(template_name, scale) if tpl is None: return None @@ -177,7 +184,7 @@ class DirtyLeagueBot: x2 = max(0, min(fw, int(rx2 * fw))) y2 = max(0, min(fh, int(ry2 * fh))) - scale = fw / float(self.BASE_DESIGN_WIDTH) + scale = self.get_frame_scale(frame) tpl = self.get_scaled_template(template_name, scale) if tpl is None: return None @@ -284,7 +291,7 @@ class DirtyLeagueBot: return GameState.CHEST_OPEN_SCREEN if self.find_template(frame, "btn_fight") or self.find_template(frame, "btn_play"): return GameState.TOWER_LOBBY - if self.find_template(frame, "anchor_main_menu") or self.find_template(frame, "btn_mode_tower"): + if self.find_template(frame, "btn_mode_tower"): return GameState.MAIN_MENU return GameState.UNKNOWN @@ -301,7 +308,7 @@ class DirtyLeagueBot: rel_w = 0.0547 rel_h = 0.0341 - scale = fw / float(self.BASE_DESIGN_WIDTH) + scale = self.get_frame_scale(frame) tpl_open = self.get_scaled_template("status_open", scale) tpl_vacant = self.get_scaled_template("status_vacant", scale) @@ -327,6 +334,11 @@ class DirtyLeagueBot: if max_v_vacant >= 0.75: status = "VACANT" + if status != "OPEN" and status != "VACANT": + txt = ocr_reader.read_text(status_crop).lower() + if "vacan" in txt: + status = "VACANT" + click_cx = sx + sw // 2 click_cy = sy - int(0.035 * fh) results[slot_id] = { diff --git a/ocr_utils.py b/ocr_utils.py index 44b3037..4481b6c 100644 --- a/ocr_utils.py +++ b/ocr_utils.py @@ -96,7 +96,7 @@ class OcrReader: if fh < 300 or fw < 500: return None - scale = fw / 3840.0 + scale = fh / 2050.0 # Relative ROI for crown digit badge y1, y2 = int(fh * 0.6780), int(fh * 0.7146)