ok-ef API 參考

返回:文件索引 / README

本文只記錄 ok-end-field 自己定義並由任務複用的介面ocrwait_ocrwait_featurewait_untilbacksleepsend_key 等框架介面來自 ok-script,其完整引數和返回型別應以當前安裝版本為準,不在此複製。

原始碼權威位置:

1. BaseEfTask 與 MRO

from src.core.BaseEfTask import BaseEfTask

BaseEfTask 的實際基類順序為:

BaseEfTask
├── WindowArrowDrawingMixin       src/core/base_mixin/window_arrow_drawing_mixin.py
├── AccountOverrideMixin         src/core/base_mixin/account_override_mixin.py
├── GameFlowMixin                src/core/base_mixin/game_flow_mixin.py
├── RuntimeMixin                 src/core/base_mixin/runtime_mixin.py
├── ok.BaseTask
└── ProcessManager               src/core/base_mixin/process_manager.py

任務層 Mixin 通常最終繼承 BaseEfTask

BattleMixin ────────────────> BaseEfTask
MapMixin ───────────────────> BaseEfTask
NavigationMixin ────────────> BaseEfTask
├── LiaisonMixin
└── ZipLineMixin
LoginMixin ─────────────────> BaseEfTask
└── AccountMixin

所有參與多重繼承的 __init__ 必須呼叫 super().__init__(*args, **kwargs)。任務配置應使用 self.default_config.update(...) 等增量方式,避免覆蓋前序 Mixin 已註冊的資料。

初始化後常用屬性:

屬性 含義
self.box ScreenPosition(self),提供常用螢幕區域
self.key_config 全域性 Game Hotkey Config 的持久化 Config
self.key_manager KeyConfigManager(self.key_config)
self.lang 按執行時 locale 載入 assets/lang/<module>.json 的訪問器
self.current_user / self.current_account_id 當前賬號上下文
self.once_sleep_time 全域性 Ensure Main Once Action Sleep.SingleActionWithDelay

1.1 座標

def box_of_screen(
    self, x=0, y=0, to_x=1.0, to_y=1.0,
    width=0.0, height=0.0, name=None,
    hcenter=False, vcenter=False, confidence=1.0,
)

def box_of_screen_scaled(
    self, original_screen_width, original_screen_height,
    x_original, y_original, to_x=0, to_y=0,
    width_original=0, height_original=0, name=None,
    hcenter=False, vcenter=False, confidence=1.0,
)

前者使用當前螢幕的比例座標;後者將參考解析度座標縮放到當前視窗。BaseEfTask 會將傳入的比例值統一保留三位小數後交給框架。

left_panel = self.box_of_screen(0.0, 0.1, 0.35, 0.9)
button = self.box_of_screen_scaled(1920, 1080, 1600, 900, 1800, 1020)

ScreenPosition 當前提供:top_lefttop_rightbottom_leftbottom_rightbottom_right_quarterleftrighttopbottomcenter,以及 nav_b/nav_c/nav_esc/nav_panelinteract_pick_fcombat_skill_1..4combat_ult_1..4combat_default_link_skillcombat_skill_barcombat_ult_bar

1.2 特徵匹配

定義於 src/core/base_mixin/runtime_mixin.py

def find_feature(
    self, feature_name=None, horizontal_variance=0, vertical_variance=0,
    threshold=0, use_gray_scale=False,
    x=-1, y=-1, to_x=-1, to_y=-1, width=-1, height=-1,
    box=None, canny_lower=0, canny_higher=0,
    frame_processor=None, template=None,
    match_method=cv2.TM_CCOEFF_NORMED, screenshot=False,
    mask_function=None, frame=None, limit=0, target_height=0,
    feature=None,
)

def find_one(
    self, feature_name=None, horizontal_variance=0, vertical_variance=0,
    threshold=0, use_gray_scale=False, box=None,
    canny_lower=0, canny_higher=0, frame_processor=None,
    template=None, mask_function=None, frame=None,
    match_method=cv2.TM_CCOEFF_NORMED, screenshot=False,
    limit=1, target_height=0, feature=None,
)
  • feature=feature_name= 的別名。
  • find_feature 接受單個特徵或 list/tuple;每個名稱都會先經過解析度適配。
  • 返回語義沿用框架:find_feature 返回結果列表,find_one 返回首個結果或空值。
  • 未顯式傳 box 時,框架可使用 assets/coco_annotations.json 的標註區域及 src/config.py 中的預設 variance/threshold。
from src.data.FeatureList import FeatureList as fL

results = self.find_feature([fL.monthly_card, fL.monthly_card2])
confirm = self.find_one(fL.skip_dialog_confirm, threshold=0.8)
if confirm:
    self.click(confirm)
def get_feature_by_resolution(self, base_name: str)

根據 self.widthFeatureList 中實際存在的列舉值選擇名稱:

視窗寬度 嘗試順序
>= 3800 _4k_2k、無後綴
>= 2500 _2k_4k、無後綴
其它 無後綴、_2k_4k

全部不存在時丟擲 AttributeError。傳入值必須能與字串拼接,通常使用 FeatureList(其成員是字串列舉)或字串。

def wait_click_feature(
    self, feature, horizontal_variance=0, vertical_variance=0,
    threshold=0, relative_x=0.5, relative_y=0.5,
    time_out=0, pre_action=None, post_action=None, box=None,
    raise_if_not_found=True, use_gray_scale=False,
    canny_lower=0, canny_higher=0, click_after_delay=0,
    settle_time=-1, after_sleep=0, target_height=0,
    alt: bool = False,
)

命中後點擊框內相對位置,成功返回 True,未命中且不拋異常時返回 Falsealt=Trueclick_with_alt

1.3 OCR 與登入截圖

普通 ocrwait_ocr 來自 ok-script。專案覆蓋了點選等待和登入截圖入口:

def wait_click_ocr(
    self, x=0, y=0, to_x=1, to_y=1, width=0, height=0,
    box=None, name=None, match=None, threshold=0, frame=None,
    target_height=0, time_out=0, raise_if_not_found=False,
    recheck_time=0, after_sleep=0, post_action=None, log=False,
    screenshot=False, settle_time=-1, lib="default", alt=False,
)

它呼叫 wait_ocr,命中後點擊並返回 OCR 結果;否則記錄日誌並返回 None。注意:recheck_time > 0 時會等待 recheck_time 秒後重新 OCR,以新座標再執行點選。

def login_screenshot(self, need_active=True)

def login_ocr(
    self, x=0, y=0, to_x=1, to_y=1, match=None,
    width=0, height=0, box=None, name=None, threshold=0,
    target_height=0, use_grayscale=False, log=False,
    frame_processor=None, lib="default", need_active=True,
)

def login_find_feature(
    self, feature=None, horizontal_variance=0, vertical_variance=0,
    threshold=0, use_gray_scale=False,
    x=-1, y=-1, to_x=-1, to_y=-1, width=-1, height=-1,
    box=None, canny_lower=0, canny_higher=0,
    frame_processor=None, template=None,
    match_method=cv2.TM_CCOEFF_NORMED, screenshot=False,
    mask_function=None, frame=None, limit=0, target_height=0,
    need_active=True,
)

這些入口使用 Win32 螢幕捕獲繞過登入介面無法由常規 WGC 幀可靠捕獲的問題。login_find_feature 總會獲取新的登入截圖,傳入的 frame 不會成為最終識別幀。

1.4 點選、按鍵和移動

def click(
    self, x=-1, y=-1, move_back=False, name=None, interval=-1,
    move=True, down_time=0.01, after_sleep=0,
    key="left", hcenter=False, vcenter=False,
)

click 在呼叫框架點選前先做危險狀態檢查;檢測到危險圖示會終止遊戲並拋異常。可將 Box 作為第一個位置引數傳入:

self.click(confirm_box, after_sleep=0.5)
self.click(0.5, 0.5)
def click_with_alt(
    self, x=-1, y=-1, move_back=False, name=None, interval=-1,
    move=True, down_time=0.01, after_sleep=0, key="left",
)

def scroll(self, x: int, y: int, count: int) -> None
def scroll_relative(self, x: float, y: float, count: int) -> None

scroll 使用視窗內畫素位置;scroll_relative 使用 0..1 比例位置。正數向上、負數向下。需要控制遊戲視角滾輪的程式碼當前另有直接呼叫 pyautogui.scroll 的場景,不能假定 UI 滾動封裝適合所有視角操作。

def press_key(self, key: str, down_time=0.02, after_sleep=0, interval=-1)
def press_industry_key(self, key: str, down_time=0.02, after_sleep=0, interval=-1)
def press_combat_key(self, key: str, down_time=0.02, after_sleep=0, interval=-1)
def press_esc(self)
def move_keys(self, keys, duration, need_back=False)

前三個方法分別以 commonindustrycombat 型別呼叫 KeyConfigManager.resolve_key,引數傳預設按鍵值,例如 self.press_key("m")move_keys 用於 w/a/s/d 等持續移動;當前實現不使用 need_back 引數。

press_esc() 僅用於過劇情(對話時)觸發 ESC,底層使用 BaseEfTask 統一初始化的鍵盤控制器。其他返回主介面、關閉頁面等流程不得使用該函式。

def dodge_forward(self, pre_hold=0.004, dodge_down_time=0.003, after_sleep=0.005)
def dodge_backward(self, pre_hold=0.004, dodge_down_time=0.003, after_sleep=0.005)

def move_to_target_once(
    self, ocr_obj, max_step=100, min_step=20,
    slow_radius=200, deadzone=4,
)

步長、減速半徑和死區會按當前解析度縮放。

1.5 場景與 UI

def is_main(self, esc=False, need_active=True) -> bool
def ensure_main(self, esc=True, time_out=90, after_sleep=2, need_active=True)
def in_world(self)
def in_combat_world(self)
  • in_world 通過 esc 特徵判斷處於大世界,並設定 _logged_in=True
  • in_combat_world 通過 top_left_tab 特徵判斷戰鬥場景;它不是“非戰鬥大世界”判斷。
  • is_main 會依次嘗試大世界檢測、登入獎勵/月卡彈窗處理、已知確認彈窗和 OCR 規則;esc=True 時最後按返回。
  • ensure_main 反覆呼叫 is_main,預設超時為 90 秒,失敗拋異常。
def ensure_map(self, addtional_feature=None, time_out=30)

反覆傳送配置化地圖鍵 m,通過 in_maptransaction_iconmain_centre_icon 或附加特徵確認地圖。引數名原始碼中保留拼寫 addtional_feature

def wait_ui_stable(
    self, method="phash", threshold=5, stable_time=0.5,
    max_wait=5, refresh_interval=1, box=None,
)

支援 phashdhashpixelssimbox 可為 Box(x, y, width, height)。對於 ssimthreshold 是相似度,呼叫方通常應傳如 0.98 的浮點值,而不是預設整數 5

def safe_back(self, match=None, feature=None, box=None,
              time_out=30, once_time_out=2) -> bool

至少提供 matchfeature;目標未出現時持續返回,成功返回 True,總超時返回 False

1.6 YOLO

def yolo_detect(
    self, name: str | list[str], frame=None, box=None, conf=0.7,
    detections=None, model_key=None,
) -> list[Box]

def list_yolo_models(self) -> list[str]
def list_yolo_targets(self, model_key: str | None = None) -> list[str]
def set_yolo_model(self, model_key: str)
def release_yolo_detector(self)

模型註冊以 src/yolo/models.py 為準。未傳 model_key 時,根據第一個目標名稱路由模型;傳 detections 可跳過推理用於測試。ROI 檢測結果會映射回全屏座標,按置信度降序返回。空 nameValueError。開啟框架 use_overlay 後,原始結果畫黃色框、篩選結果畫紅色框。

2. 配置 API

2.1 任務配置

任務通過框架屬性增量註冊配置:

self.default_config.update({"启用功能": True})
self.config_description.update({"启用功能": "控制是否执行该步骤。"})
self.config_type["模式"] = {
    "type": "drop_down",
    "options": ["快速", "稳定"],
}
self.default_config_group.update({"常用": ["启用功能", "模式"]})

執行時使用 self.config.get(key, default)BaseEfTask.load_config() 會按完整 MRO 收集各類的 config_key_migrations,先遷移 configs/<TaskClass>.json 的舊鍵,再呼叫框架載入。

def register_config_groups(self, groups: dict, dropdown_name="配置选择")

該方法建立帶 sub_configs 的下拉配置,併為分組內尚無預設值的鍵補 None。它會直接使用 self.config_description.update(...),呼叫前應確保任務已按框架慣例初始化配置字典。

2.2 全域性配置

from src.core.global_config_store import (
    KEY_CONFIG_NAME,
    get_global_config,
)

hotkeys = get_global_config(KEY_CONFIG_NAME)
map_key = hotkeys.get("Map Key", "m")

當前全域性配置項:

常量/名稱 內容
Game Hotkey Config 通用、工業、戰鬥鍵位
Battle Config DEFAULT_BATTLE_CONFIG 戰鬥引數
Ensure Main Once Action Sleep SingleActionWithDelay
Zip Line Config 送貨/淤積點滑索路線與滾動設定

get_global_config(name) 返回持久化 ok.util.config.Config。未知名稱只有在已載入配置中能找到對應鍵時才回退返回該配置,否則拋 RuntimeError。全域性配置頁由 get_all_visible_configs()GlobalConfigTab 構建。

2.3 按鍵配置

class KeyConfigManager:
    def __init__(self, key_config: dict = None): ...
    def update_config(self, key_config: dict): ...
    def resolve_key(self, key: str, key_type: str = "common") -> str: ...

不存在 resolve_common_keyresolve_industry_keyresolve_combat_keyresolve_key 在指定預設表中按預設值反查配置名稱,再讀取使用者值;找不到時原樣返回。

當前預設表比舊文件多出以下鍵:

  • 通用:Handbook Key=f8Recruitment Key=f9
  • 工業:Area Build Key=yBlueprint Key=f1Product Icon Toggle Key=f4

所有可改鍵操作應走 press_key/press_industry_key/press_combat_key。固定技能數字、方向鍵和系統修飾鍵等程式碼可按其明確語義使用底層傳送介面。

2.4 戰鬥配置與賬號覆蓋

def get_battle_config(self, key: str, default=None)

BattleMixin 的讀取順序:

  1. BattleConfigManager 從全域性 Battle Config 取值。
  2. 任務配置 战斗配置使用全局配置 時直接返回全域性值。
  3. 使用独立配置 時讀取當前任務配置,以全域性值兜底。
  4. AccountOverrideMixin 繫結後的 self.config.get 可再按當前穩定賬號 ID 應用賬號任務覆蓋;賬號覆蓋優先順序最高。

賬號上下文通過以下介面設定:

def set_current_account(self, username, account_id)

def iter_multi_account_context(
    self, repeat_times=1, empty_accounts_message=None,
    account_log_suffix="", allow_multi_account=True,
)

iter_multi_account_context 在多賬戶模式下解析賬號列表、繫結賬號覆蓋並呼叫 login_flow(username);單賬號模式清空賬號上下文。賬號列表每行只需要賬號,舊 账号, 密码 格式僅取逗號前賬號,密碼被忽略。

3. 業務 Mixin

3.1 BattleMixin

from src.tasks.mixin.battle_mixin import BattleMixin
def in_combat(self, required_yellow=0)
def in_team(self)
def is_combat_ended(self)
def wait_in_combat(self, time_out=3, click=False)
def get_skill_bar_count(self)
def ocr_lv(self)
def use_ult(self, ult_sequence: str = None)
def use_link_skill(self)
def approach_enemy(self)
def auto_battle(self, no_battle: bool = False)

關鍵語義:

  • in_team 從首個框開始匹配 skill_1,隨後再命中一個連續技能即確認隊伍狀態(至少 2 個特徵;skill_1 位於最後一個框時為單人隊伍,1 個即可)。
  • in_combat 要求技能條數量達到閾值、處於隊伍且沒有等級 UI。
  • is_combat_ended 要求內部退出條件連續命中兩次;該條件是“出現等級 UI 或不在隊伍”。
  • use_ult(None)1..4 尋找可用終極技;傳值時只嘗試該角色。返回是否釋放成功。
  • use_link_skill 僅在識別到連攜技特徵後傳送配置化戰鬥鍵 e
  • auto_battle 每輪委託 AutoCombatLogic.run,全域性保護超時 420 秒;no_battle=True 傳給戰鬥邏輯,使其等待而不主動戰鬥。成功/失敗返回布林值。
  • 戰鬥結束並非通過 YOLO 單一判斷;當前迴圈還結合戰鬥時間和 battle_space_left/b 特徵。

3.2 MapMixin

from src.tasks.mixin.map_mixin import MapMixin

def task_to_transfer_point(self, need_location_list=None)
def clear_icon_in_map(self, need_reserve_icon_name=None, ocr=False)
def to_near_transfer_point(self, after_track, need_location_list=None)

task_to_transfer_point 從任務介面定位地圖,地圖穩定後再呼叫 to_near_transfer_pointto_near_transfer_point 傳送至附近傳送點。

3.3 NavigationMixin

from src.tasks.mixin.navigation_mixin import NavigationMixin

def navigate_until_target(
    self, target, nav=None,
    target_is_ocr=True, nav_is_ocr=False,
    time_out=60, pre_loop_callback=None,
    found_special_callback=None,
    target_is_yolo=False, nav_is_yolo=False,
    box=None, target_vertical_variance=0.0,
    need_v=False, max_run_time=-1,
    allow_rotate_search=True,
)

持續按 W 前進,目標和導航標識分別可用 OCR、YOLO 或 Feature。nav=None 表示純直線搜尋;found_special_callback 返回非 None 時該值直接作為函式結果。目標需持續穩定 2 秒(OCR)或 1 秒(其它方式)才返回 True。超時返回 Falsemax_run_time 只限制 ctrl 切換的奔跑累計時間,不限制按住 W-1 不限制,0 全程步行,正數達到上限後切步行。allow_rotate_search 預設 True,導航連續丟失時旋轉視角整圈搜尋;送禮等不應轉動視角的場景傳 False 跳過旋轉直接按中鍵並後退搜尋。

def start_tracking_and_align_target(
    self, target_feature_in_map, target_feature_out_map,
)

在地圖點選目標並啟動追蹤,關閉地圖,等待地圖外圖示並做水平對齊;返回布林值。

def align_ocr_or_find_target_to_center(
    self, ocr_match_or_feature_name_list,
    only_x=False, only_y=False, box=None, threshold=0.8,
    max_time=50, ocr=True, use_yolo=False, back_prev=False,
    raise_if_fail=True, is_num=False, need_scroll=False,
    max_step=120, min_step=20, slow_radius=350, deadzone=8,
    once_time=0.05, tolerance=50,
    ocr_frame_processor_list=None, allow_random_move=True,
)

在 OCR、Feature 或 YOLO 模式下將目標對齊螢幕中心。max_time 是演算法嘗試尺度,內部最多迴圈 max_time * 2,不是秒數。失敗時預設拋異常;raise_if_fail=False 返回 Falseback_prev 引數當前未被方法體使用。

3.4 LiaisonMixin

from src.tasks.mixin.liaison_mixin import LiaisonMixin

def transfer_to_home_point(self, box=None, should_check_out_boat=False)
def navigate_to_main_hall(self) -> bool
def navigate_to_operator_liaison_station(self)
def perform_operator_liaison(self)
def collect_gifts(self, time_out=30)
def give_gifts(self, time_out=30, gift_entry_clicked=False)
def collect_and_give_gifts(self)
  • transfer_to_home_point 預設在地圖左半屏找傳送點;呼叫方傳 box=self.box.right 才是右側點。should_check_out_boat=True 的實際語義是:若點選不到帝江號入口,則認為已經在帝江號區域並直接返回主介面,不會執行“退出好友船”。
  • navigate_to_main_hall 最多向前移動兩次並 OCR 區域名;即使未識別到也記錄日誌後返回 True,是寬鬆檢查。
  • navigate_to_operator_liaison_station 使用地圖追蹤和 navigate_until_target;途中發現聊天圖示可返回 LiaisonResult.FIND_CHAT_ICON,因此返回值不只布林值。
  • perform_operator_liaison 選擇配置的優先物件,找不到時回退任一可聯絡物件,完成聯絡介面、目標對齊和聊天互動;它不包含收禮/送禮步驟。
  • collect_and_give_gifts 處理當前交流介面中的收禮或送禮入口;收禮成功後繼續嘗試送禮。

3.5 ZipLineMixin

from src.tasks.mixin.zip_line_mixin import ZipLineMixin

def on_zip_line_start(
    self, delivery_to, need_scroll=None, target=None, need_v=True,
)

def zip_line_list_go(
    self, zip_line_list, need_scroll=None, target=None, need_v=False,
)

def ensure_click_on_zip_line(self, max_attempts=5)

on_zip_line_start 先等待滑索 UI,隨後從 self.config[delivery_to] 讀取整數序列並呼叫 zip_line_list_go;它不是接收距離列表的入口。每段距離通過金色/白色 HSV 預處理 OCR 並居中,點選進入滑索後持續傳送固定鍵 e,直到滑索 UI 再次出現。單段等待上限 240 秒;初始滑索 UI 等待上限 60 秒,超時拋異常。

target(目标, "ocr" | "yolo" | 其它),用於最後一段後的目標對齊;其它型別按 Feature 處理。流程末尾確保回到主介面。

3.6 LoginMixin

from src.tasks.mixin.login_mixin import LoginMixin

def login_flow(self, username: str, password: str | None = None)
def click_text(
    self, match: str, box=None,
    need_wait_disappear=True, success_match=None,
)

login_flow 不是使用者名稱密碼輸入流程。它用於切換到登入介面的“最近賬號”:

  1. 判斷當前是否已登入,必要時回到主介面並退出當前賬號。
  2. 等待登入介面的 logout 特徵並確認登出。
  3. 點選“最近”,再用 username 後四位 OCR 點選最近賬號。
  4. 點選“登入”,通過重新出現 logout 特徵確認成功。

password 僅為舊呼叫相容引數,當前不儲存、不輸入、也不參與賬號判定。失敗路徑可能返回 False 或拋 RuntimeError;成功無顯式返回值。後四位匹配要求最近賬號列表中後四位唯一。

4. 語言資源 API

from src.data.lang import (
    ACTIVE_LOCALES_CONFIG,
    SUPPORTED_LOCALES,
    get_lang_accessor,
    get_lang_module_value,
)

每個模組對應單個 assets/lang/<module>.json

{
  "k_confirm": {
    "zh_CN": {"string": "确认"},
    "zh_TW": {"string": "確認"}
  },
  "k_amount": {
    "zh_CN": {"pattern": "^\\d+$"},
    "zh_TW": {"pattern": "^\\d+$"}
  }
}

訪問 self.lang.<module>.<key> 時,string 返回字串、pattern 返回編譯後的正則、terms 返回列表。直接屬性解析的優先順序是 stringpatterntermsLangNode.as_matcher()/build_matcher() 的優先順序是 patternstringterms。正常資源節點應只設置其中一種,避免依賴該差異。

當前活動 OCR locale 只有 zh_CNzh_TW;其它四種 locale 雖可存在於 JSON 和 gettext 目錄,但在 ACTIVE_LOCALES_CONFIG 中關閉,不會進入 SUPPORTED_LOCALES。完整維護流程見 i18n 與 OCR 配置流程

在 GitHub 查看來源 ↗ · 頁面產生時間: 2026年8月10日