Fix template and OCR dynamic scaling to use Unity Canvas Scaler height and refine MAIN_MENU detection
This commit is contained in:
22
bot_core.py
22
bot_core.py
@ -101,9 +101,16 @@ class DirtyLeagueBot:
|
|||||||
self.scaled_templates[name_without_ext] = img
|
self.scaled_templates[name_without_ext] = img
|
||||||
logging.info(f"Loaded {len(self.base_templates)} base template(s) from '{self.assets_dir}'")
|
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]:
|
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.
|
Caches scaled results so resizing only happens on window resolution changes.
|
||||||
"""
|
"""
|
||||||
if template_name not in self.base_templates:
|
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.
|
Returns client center coordinates (center_x, center_y) if matched, else None.
|
||||||
"""
|
"""
|
||||||
fh, fw = frame.shape[:2]
|
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)
|
tpl = self.get_scaled_template(template_name, scale)
|
||||||
if tpl is None:
|
if tpl is None:
|
||||||
return None
|
return None
|
||||||
@ -177,7 +184,7 @@ class DirtyLeagueBot:
|
|||||||
x2 = max(0, min(fw, int(rx2 * fw)))
|
x2 = max(0, min(fw, int(rx2 * fw)))
|
||||||
y2 = max(0, min(fh, int(ry2 * fh)))
|
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)
|
tpl = self.get_scaled_template(template_name, scale)
|
||||||
if tpl is None:
|
if tpl is None:
|
||||||
return None
|
return None
|
||||||
@ -284,7 +291,7 @@ class DirtyLeagueBot:
|
|||||||
return GameState.CHEST_OPEN_SCREEN
|
return GameState.CHEST_OPEN_SCREEN
|
||||||
if self.find_template(frame, "btn_fight") or self.find_template(frame, "btn_play"):
|
if self.find_template(frame, "btn_fight") or self.find_template(frame, "btn_play"):
|
||||||
return GameState.TOWER_LOBBY
|
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.MAIN_MENU
|
||||||
|
|
||||||
return GameState.UNKNOWN
|
return GameState.UNKNOWN
|
||||||
@ -301,7 +308,7 @@ class DirtyLeagueBot:
|
|||||||
rel_w = 0.0547
|
rel_w = 0.0547
|
||||||
rel_h = 0.0341
|
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_open = self.get_scaled_template("status_open", scale)
|
||||||
tpl_vacant = self.get_scaled_template("status_vacant", scale)
|
tpl_vacant = self.get_scaled_template("status_vacant", scale)
|
||||||
|
|
||||||
@ -327,6 +334,11 @@ class DirtyLeagueBot:
|
|||||||
if max_v_vacant >= 0.75:
|
if max_v_vacant >= 0.75:
|
||||||
status = "VACANT"
|
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_cx = sx + sw // 2
|
||||||
click_cy = sy - int(0.035 * fh)
|
click_cy = sy - int(0.035 * fh)
|
||||||
results[slot_id] = {
|
results[slot_id] = {
|
||||||
|
|||||||
@ -96,7 +96,7 @@ class OcrReader:
|
|||||||
if fh < 300 or fw < 500:
|
if fh < 300 or fw < 500:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
scale = fw / 3840.0
|
scale = fh / 2050.0
|
||||||
|
|
||||||
# Relative ROI for crown digit badge
|
# Relative ROI for crown digit badge
|
||||||
y1, y2 = int(fh * 0.6780), int(fh * 0.7146)
|
y1, y2 = int(fh * 0.6780), int(fh * 0.7146)
|
||||||
|
|||||||
Reference in New Issue
Block a user