// The auto hunt window (PORT; 40250 has no counterpart), run by PythonBoot::RunMainScript as module // mt_autohunt. It hooks game.GameWindow.Open/Close so the window lives exactly as long as the game phase, // whichever way the host reached it. The logic is CPythonPlayer's (UserInterface/PythonPlayerAutoHunt.cpp); // this is only the player.AutoHunt* front end. Strings are UTF-8 here and go through // player.AutoHuntLocalize into the locale's code page, as the packed locale strings are. static const char c_szAutoHuntScript[] = R"PY(# -*- coding: utf-8 -*- import app import chat import game import player import ui import wndMgr L = player.AutoHuntLocalize STATE_OFF, STATE_SEARCH, STATE_ENGAGE, STATE_LOOT, STATE_RETURN, STATE_PAUSED = range(6) STOP_NONE, STOP_USER, STOP_DEAD, STOP_MAP, STOP_INVENTORY_FULL = range(5) SKILL_SLOT_NUM = 8 STATE_TEXT = { STATE_SEARCH: "寻找目标", STATE_ENGAGE: "战斗中", STATE_LOOT: "拾取中", STATE_RETURN: "返回挂机点", STATE_PAUSED: "手动操作,3秒后继续", } STOP_TEXT = { STOP_USER: "自动狩猎已停止", STOP_DEAD: "角色死亡,自动狩猎已停止", STOP_MAP: "切换地图,自动狩猎已停止", STOP_INVENTORY_FULL: "背包已满,自动狩猎已停止", } RANGE_VALUES = (1000, 2000, 3500) RANGE_TEXTS = ("近", "中", "远") HP_VALUES = (0, 30, 50, 70) SP_VALUES = (0, 20, 40, 60) PICKUP_TEXTS = ("不拾取", "全部", "金币装备") GATHER_VALUES = (0, 3, 5, 8) GATHER_TEXTS = ("关", "3只", "5只", "8只") SMALL_BUTTON = "d:/ymir work/ui/public/small_button_%02d.sub" MIDDLE_BUTTON = "d:/ymir work/ui/public/middle_button_%02d.sub" XSMALL_BUTTON = "d:/ymir work/ui/public/xsmall_button_%02d.sub" COLOR_ON = 0xff7fff7f COLOR_OFF = 0xffffcf7f COLOR_SELECTED = 0xffffd24a COLOR_UNSELECTED = 0xffc8c8c8 def _MarkButton(button, isSelected): "Down and gold text while selected: the down visual alone is hard to tell apart on a phone." if isSelected: button.Down() else: button.SetUp() if button.ButtonText: button.ButtonText.SetPackedFontColor(isSelected and COLOR_SELECTED or COLOR_UNSELECTED) def _Nearest(values, value): best = 0 for i in xrange(len(values)): if abs(values[i] - value) < abs(values[best] - value): best = i return best class ChoiceRow: "One setting: a label and a row of buttons of which exactly one stays down." def __init__(self, parent, y, label, texts, image, step, event): self.label = ui.TextLine() self.label.SetParent(parent) self.label.SetPosition(18, y + 4) self.label.SetText(L(label)) self.label.Show() self.buttons = [] self.event = event self.index = -1 x = 70 for i in xrange(len(texts)): button = ui.RadioButton() button.SetParent(parent) button.SetUpVisual(image % 1) button.SetOverVisual(image % 2) button.SetDownVisual(image % 3) button.SetPosition(x, y) button.SetText(L(texts[i])) button.SetEvent(lambda i=i: self.Select(i, True)) button.Show() self.buttons.append(button) x += step def Select(self, index, notify): self.index = index for i in xrange(len(self.buttons)): _MarkButton(self.buttons[i], i == index) if notify and self.event: self.event() def Destroy(self): self.event = None self.buttons = [] self.label = None class FlagButton(ui.ToggleButton): "A button that stays down while its flag is on." def __init__(self, parent, x, y, image, text, event): ui.ToggleButton.__init__(self) self.SetParent(parent) self.SetUpVisual(image % 1) self.SetOverVisual(image % 2) self.SetDownVisual(image % 3) self.SetPosition(x, y) self.SetText(L(text)) self.flag = False self.flagEvent = event self.SetToggleDownEvent(lambda: self.__OnToggle(True)) self.SetToggleUpEvent(lambda: self.__OnToggle(False)) self.Show() def __OnToggle(self, flag): self.SetFlag(flag) if self.flagEvent: self.flagEvent() def SetFlag(self, flag): self.flag = flag _MarkButton(self, flag) def Destroy(self): self.flagEvent = None self.eventUp = None self.eventDown = None class SettingDialog(ui.BoardWithTitleBar): WIDTH = 330 HEIGHT = 300 def __init__(self): ui.BoardWithTitleBar.__init__(self) self.AddFlag("movable") self.AddFlag("float") self.SetSize(self.WIDTH, self.HEIGHT) self.SetTitleName(L("自动狩猎")) self.SetCloseEvent(self.Close) y = 36 self.rangeRow = ChoiceRow(self, y, "范围", RANGE_TEXTS, SMALL_BUTTON, 48, self.__Save) y += 28 self.hpRow = ChoiceRow(self, y, "红药", ["关"] + ["%d%%" % v for v in HP_VALUES[1:]], SMALL_BUTTON, 48, self.__Save) y += 28 self.spRow = ChoiceRow(self, y, "蓝药", ["关"] + ["%d%%" % v for v in SP_VALUES[1:]], SMALL_BUTTON, 48, self.__Save) y += 28 self.pickupRow = ChoiceRow(self, y, "拾取", PICKUP_TEXTS, MIDDLE_BUTTON, 66, self.__Save) y += 28 self.gatherRow = ChoiceRow(self, y, "聚怪", GATHER_TEXTS, SMALL_BUTTON, 48, self.__Save) y += 28 self.skillLabel = ui.TextLine() self.skillLabel.SetParent(self) self.skillLabel.SetPosition(18, y + 4) self.skillLabel.SetText(L("技能栏")) self.skillLabel.Show() self.skillButtons = [] for i in xrange(SKILL_SLOT_NUM): self.skillButtons.append(FlagButton(self, 70 + i * 31, y, XSMALL_BUTTON, str(i + 1), self.__Save)) y += 28 self.targetLabel = ui.TextLine() self.targetLabel.SetParent(self) self.targetLabel.SetPosition(18, y + 4) self.targetLabel.SetText(L("攻击")) self.targetLabel.Show() self.stoneButton = FlagButton(self, 70, y, MIDDLE_BUTTON, "石头", self.__Save) self.bossButton = FlagButton(self, 136, y, MIDDLE_BUTTON, "首领", self.__Save) y += 30 self.hintLine = ui.TextLine() self.hintLine.SetParent(self) self.hintLine.SetPosition(0, y + 2) self.hintLine.SetWindowHorizontalAlignCenter() self.hintLine.SetHorizontalAlignCenter() self.hintLine.SetPackedFontColor(0xffa0a0a0) self.hintLine.SetText(L("手动操作时暂停,3秒后继续")) self.hintLine.Show() y += 26 self.startButton = ui.Button() self.startButton.SetParent(self) self.startButton.SetUpVisual("d:/ymir work/ui/public/large_button_01.sub") self.startButton.SetOverVisual("d:/ymir work/ui/public/large_button_02.sub") self.startButton.SetDownVisual("d:/ymir work/ui/public/large_button_03.sub") self.startButton.SetPosition(0, y) self.startButton.SetWindowHorizontalAlignCenter() self.startButton.SetEvent(self.__OnClickStart) self.startButton.Show() self.SetSize(self.WIDTH, y + 36) self.SetCenterPosition() self.isStarted = None def Destroy(self): for row in (self.rangeRow, self.hpRow, self.spRow, self.pickupRow, self.gatherRow): row.Destroy() for button in self.skillButtons + [self.stoneButton, self.bossButton]: button.Destroy() self.skillButtons = [] self.startButton = None self.Hide() def Open(self): (range_, hp, sp, pickup, stone, boss, mask, gather) = player.AutoHuntGetConfig() self.rangeRow.Select(_Nearest(RANGE_VALUES, range_), False) self.hpRow.Select(_Nearest(HP_VALUES, hp), False) self.spRow.Select(_Nearest(SP_VALUES, sp), False) self.pickupRow.Select(pickup, False) self.gatherRow.Select(_Nearest(GATHER_VALUES, gather), False) for i in xrange(SKILL_SLOT_NUM): self.skillButtons[i].SetFlag(bool(mask & (1 << i))) self.stoneButton.SetFlag(bool(stone)) self.bossButton.SetFlag(bool(boss)) self.isStarted = None self.Show() self.SetTop() def Close(self): self.Hide() def OnPressEscapeKey(self): self.Close() return True def OnUpdate(self): isStarted = bool(player.AutoHuntIsEnabled()) if isStarted != self.isStarted: self.isStarted = isStarted self.startButton.SetText(L(isStarted and "停止狩猎" or "开始狩猎")) def __Save(self): mask = 0 for i in xrange(SKILL_SLOT_NUM): if self.skillButtons[i].flag: mask |= 1 << i player.AutoHuntSetConfig(RANGE_VALUES[self.rangeRow.index], HP_VALUES[self.hpRow.index], SP_VALUES[self.spRow.index], self.pickupRow.index, int(self.stoneButton.flag), int(self.bossButton.flag), mask, GATHER_VALUES[self.gatherRow.index]) def __OnClickStart(self): Toggle() if player.AutoHuntIsEnabled(): self.Close() class StatusBoard(ui.ThinBoard): def __init__(self): ui.ThinBoard.__init__(self) self.AddFlag("not_pick") self.SetSize(260, 28) self.SetWindowHorizontalAlignCenter() self.SetPosition(0, 64) self.textLine = ui.TextLine() self.textLine.SetParent(self) self.textLine.SetPosition(0, 7) self.textLine.SetWindowHorizontalAlignCenter() self.textLine.SetHorizontalAlignCenter() self.textLine.Show() def SetStatus(self, text, color): self.textLine.SetText(text) self.textLine.SetPackedFontColor(color) self.Show() class Ticker(ui.Window): "Always shown and empty: polls the hunt state for the status board, which is hidden while off." def __init__(self, status): ui.Window.__init__(self) self.AddFlag("not_pick") self.status = status self.last = None self.stopShowTime = 0.0 def OnUpdate(self): state = player.AutoHuntGetState() if state != self.last: (stateIndex, reason, noHP, noSP, gathering, gathered) = state wasOn = self.last and self.last[0] != STATE_OFF self.last = state if stateIndex != STATE_OFF: text = L("自动狩猎 · ") + L(STATE_TEXT.get(stateIndex, "")) if gathering: text = L("自动狩猎 · 聚怪中 %d/%d" % (gathered, player.AutoHuntGetConfig()[7])) if noHP: text += L(" · 无红药") if noSP: text += L(" · 无蓝药") self.status.SetStatus(text, COLOR_ON) elif wasOn and reason in STOP_TEXT: self.status.SetStatus(L(STOP_TEXT[reason]), COLOR_OFF) self.stopShowTime = app.GetTime() + 5.0 if reason != STOP_USER: chat.AppendChat(chat.CHAT_TYPE_INFO, L(STOP_TEXT[reason])) else: self.status.Hide() elif state[0] == STATE_OFF and self.stopShowTime and app.GetTime() > self.stopShowTime: self.stopShowTime = 0.0 self.status.Hide() g_status = None g_ticker = None g_dialog = None def Toggle(): if player.AutoHuntIsEnabled(): player.AutoHuntSetEnabled(0) return player.AutoHuntSetEnabled(1) if player.AutoHuntIsEnabled(): chat.AppendChat(chat.CHAT_TYPE_INFO, L("自动狩猎已开启(再次点击AUTO或F9停止)")) def OpenSettings(): if g_dialog: if g_dialog.IsShow(): g_dialog.Close() else: g_dialog.Open() def IsSettingsOpen(): return g_dialog and g_dialog.IsShow() def Attach(gameWindow): global g_status, g_ticker, g_dialog Detach() g_status = StatusBoard() g_ticker = Ticker(g_status) g_ticker.Show() g_dialog = SettingDialog() if gameWindow.onPressKeyDict is not None: gameWindow.onPressKeyDict[app.DIK_F9] = Toggle gameWindow.onPressKeyDict[app.DIK_F8] = OpenSettings def Detach(): global g_status, g_ticker, g_dialog player.AutoHuntSetEnabled(0) if g_dialog: g_dialog.Destroy() if g_ticker: g_ticker.Hide() g_ticker.status = None if g_status: g_status.Hide() g_status = g_ticker = g_dialog = None def __Install(): openGame = game.GameWindow.Open closeGame = game.GameWindow.Close def Open(self): openGame(self) Attach(self) def Close(self): Detach() closeGame(self) game.GameWindow.Open = Open game.GameWindow.Close = Close __Install() )PY";