Skip to content

Instantly share code, notes, and snippets.

@noih
Last active September 25, 2022 04:40
Show Gist options
  • Save noih/71a1bbd74eafca7588d63da21bbdff88 to your computer and use it in GitHub Desktop.
Save noih/71a1bbd74eafca7588d63da21bbdff88 to your computer and use it in GitHub Desktop.
global HpPercent := 65 ; 補血 % (18 ~ 97)
global HpHotKey := "1" ; 腰帶水箱編號 (1 ~ 5)
global LightHotKey := "" ; 開燈 法術 "F1" ~ "F8", 腰帶蠟燭 "1" ~ "5", "" = 不開燈
global LightTime := 366 ; 多久開燈一次
global MoveTime := 3500 ; 移動等待時間 (毫秒),根據腳色移動速度調整
global DelayPerRound := 100 ; 多久偵測一次 (毫秒),如果 lag 可嘗試加大
; 起始指令 / 結束指令
global CommandsOnStart := ["/run", "/nowar", "/nomenu", "/trade off", "/effectoff all", "/weather off"]
global CommandsOnEnd := ["/nowar off", "/nomenu off", "/shift off", "/trade on", "/effecton", "/weather on"]
; =======================================================
; 此區域通常不需要調整
#SingleInstance, Force
#NoEnv
SetBatchLines -1
ListLines Off
SendMode Input
SetDefaultMouseSpeed, 2
SetWorkingDir, %A_ScriptDir%
global FolderName := "detect" ; 圖檔資料夾名稱
global Pos := []
global TimePool := {}
global n := 5
; Ctrl + r 重新載入
^r::Reload
; Pause 暫停 / 回復
Pause::Pause, Toggle
; Delete 離開程式
Delete::ExitApp
; =======================================================
; Alt + 6
; 啟動後,滑鼠按 1 次右鍵,設定 Pos 1 (角色腳的位置)
; 偵測物品跑去撿並走回原位,若有設定可開燈
!6::
SetTimer, Emergency ; 定時檢查血量
base := GetRelativePos(800, 600, { x: 400, y: 525 })
current := Pos[1] ; 當前位置
images := GetImages(FolderName) ; 取得圖檔
SequenceSetPos(1, 1) ; 滑鼠按 1 次右鍵,設定 Pos 1
Speak(CommandsOnStart) ; 說 起始指令
Loop, {
UseLight(LightHotKey, Pos[1], LightTime) ; 定時開燈
MouseMove, base.x, base.y, 0 ; 滑鼠移到 base,避免擋住畫面
item := FoundItem(images) ; 搜尋物品
if (item != "") { ; 如果有找到
SetBattle(FALSE) ; 和平
RoleGoTo(item, TRUE) ; 往物品附近移動
if (current.x = item.x AND current.y = item.y) { ; 如果物品座標相同
Sleep, 1500 ; 只等待 1500 毫秒
} else {
Sleep, % MoveTime ; 等待移動時間
}
Send, {Shift Down} ; 按下 shift (防止走到邊緣導致畫面位移)
Sleep, 80
Loop, 2 { ; 撿物品
MouseMove, item.x, item.y, 0
Sleep, 80
MouseClick, Left, item.x, item.y, 1, 0, D
Sleep, 110
MouseClick, Left, item.x, item.y, 1, 0, U
Sleep, 80
}
Send, {Shift Up} ; 放開 shift
current := item ; 記錄當前位置
} else if (current.x != Pos[1].x OR current.y != Pos[1].y) { ; 如果腳色離開原位
RoleGoTo(Pos[1], FALSE) ; 腳色回原位
Sleep, % MoveTime ; 等待移動時間
current := Pos[1] ; 記錄當前位置
}
Sleep, % DelayPerRound
}
return
; Ctrl + t
; 說 結束指令
^t::
InitWindowsState() ; 關閉視窗、人物置中
Speak(CommandsOnEnd) ; 說 結束指令
return
Emergency:
CheckHp(HpHotKey, HpPercent) ; 檢查血量
return
; =======================================================
; 腳本提供的功能,此區域通常不需要調整
; 關掉視窗、人物置中、右鍵點兩下
InitWindowsState() {
KeyPress("Escape", 3) ; close window
AlignCenter()
RClick(GetRelativePos(800, 600, { x: 401, y: 273 }), 2) ; release skill
}
; 人物置中
AlignCenter() {
KeyPress("Space", 2)
Sleep, 750
}
; 說話
; contents ["文字1", "文字2"]
; shouldESC 最後是否按 esc
Speak(contents, shouldESC = TRUE) {
KeyPress("Enter")
for k, v in contents {
Send, {Text}%v%
KeyPress("Enter")
}
if (shouldESC) {
KeyPress("Escape")
}
}
; 檢查血量並補血
; key 1 ~ 5
; percentage 百分比
CheckHp(key, percentage) {
if (!IsDead() AND IsHpLessThan(percentage) AND RegExMatch(key, "^[1-5]$")) {
UseBelt(key, 300)
}
}
; 血量少於百分比 ?
; percentage 18 ~ 97
IsHpLessThan(percentage) {
if (percentage >= 18 AND percentage <= 97) {
p := GetRelativePos(800, 600, { x: 54, y: 596 })
y1 := p.y - Ceil(84 * percentage / 100)
y2 := y1 - 1
PixelGetColor, color1, p.x, %y1%
PixelGetColor, color2, p.x, %y2%
r1 := Format( "{1:u}", "0x" . SubStr(color1, 3, 2))
r2 := Format( "{1:u}", "0x" . SubStr(color2, 3, 2))
return ((r1 + r2) / 2) >= 41
}
return FALSE
}
; 是否已死亡?
IsDead() {
p := GetRelativePos(800, 600, { x: 27, y: 596 })
PixelGetColor, color, p.x, p.y
return color != 0x292894
}
; 設定戰鬥模式
; isBattle True = 戰鬥, False = 和平
SetBattle(isBattle) {
changed := FALSE
Loop, 10 {
p := GetRelativePos(800, 600, { x: 691, y: 567 })
PixelGetColor, color, p.x, p.y
if ((isBattle AND color = 0x000000) OR (!isBattle AND (color = 0x213039 OR color = 0x293845 OR color = 0x293842))) {
return changed
}
LClick(GetRelativePos(800, 600, { x: 708, y: 560 }))
Sleep, 150
changed := TRUE
}
}
; 點滑鼠左鍵, ex. LClick({ x: 0, y: 0 })
LClick(position = "", cnt = 1) {
Loop, % cnt {
MouseClick, Left, position.x, position.y, 1, 0
Sleep, 80
}
}
; 點滑鼠右鍵, ex. RClick({ x: 0, y: 0 })
RClick(position = "", cnt = 1) {
Loop, % cnt {
MouseMove, position.x, position.y, 0
Sleep, 80
MouseClick, Right, position.x, position.y, 1, 0, D,
Sleep, 80
MouseClick, Right, position.x, position.y, 1, 0, U,
Sleep, 80
}
}
; 按鍵盤按鍵 ex: KeyPress("Enter")
; 按鍵列表 https://wyagd001.github.io/zh-cn/docs/KeyList.htm
KeyPress(key, cnt = 1) {
Loop, % cnt {
Send, {%key% Down}
Sleep, 80
Send, {%key% Up}
Sleep, 80
}
}
; 用腰帶物品欄
; index 1 ~ 5
; postMs 使用後的延遲時間 (毫秒) (太短可能導致使用多次)
UseBelt(index, postMS) {
if (RegExMatch(index, "^[1-5]$")) {
Send, {Alt Down}
Send, {%index% Down}
Sleep, 80
Send, {%index% Up}
Send, {Alt Up}
Sleep, postMS
}
}
; 更新快速鍵最後使用時間
; key 快速鍵
UpdateLastTime(key) {
TimePool[key] := GetUnixTimestamp()
}
; 定時使用法術
; key 快速鍵
; position 位置
; preMS 詠唱時間
; postMS 施放時間
; duration 多久再次使用
; cnt 集氣、施法時,點擊 (按鍵、滑鼠) 的次數
UseMagic(key, position, preMS, postMS, duration, cnt = 3) {
if (RegExMatch(key, "^F[1-8]$") AND IsTimeUp(key, duration)) {
px := ""
py := ""
MouseGetPos, px, py
Chant(key, preMs - (cnt * 160), cnt)
RClick(position, cnt)
MouseMove, px, py
Sleep, Max(postMS - (cnt * 240), 0)
KeyPress("~", 2) ; prevent failed
UpdateLastTime(key)
}
}
; 詠唱法術、技能
; key 快速鍵
; ms 等待時間
; cnt 按鍵次數
Chant(key, ms, cnt = 2) {
KeyPress(key, cnt)
Sleep, Max(ms, 0)
}
; 快速鍵時間到了嗎?
IsTimeUp(key, duration) {
if (duration = "" OR duration <= 0 OR TimePool[key] = "") {
return TRUE
}
return (GetUnixTimestamp() - TimePool[key]) >= duration
}
GetImages(path) {
images := []
Loop Files, %path%\*.bmp, R
{
images.Push(A_LoopFileFullPath)
; OutputDebug, image:, %A_LoopFileFullPath%
}
return images
}
FoundItem(paths) {
for k, v in paths {
ImageSearch, x, y, 30, 30, A_ScreenWidth - 30, A_ScreenHeight - 30, *%n% %v%
; OutputDebug, detect:, %v%, err: %ErrorLevel%
if (x > 0 AND y > 0) {
return { x: x, y: y }
}
}
return ""
}
RoleMove(p, cnt = 3) {
LClick({ x: Min(Max(p.x, 110), A_ScreenWidth - 110), y: Min(Max(p.y, 110), A_ScreenHeight - 110) }, cnt)
}
RoleGoTo(to, isRandom) {
if (to = "") {
return
}
if (!isRandom) {
RoleMove(to, 3)
} else {
Random, v, 35, 65
Random, p, 0, 1
x := (p = 1) ? v : v * -1
Random, v, 35, 60
Random, p, 0, 1
y := (p = 1) ? v : v * -1
RoleMove({ x: to.x + 17 + x, y: to.y + 17 + y }, 3)
}
}
UseLight(key, position, duration) {
if (key != "" AND duration != "" AND IsTimeUp(key, duration)) {
if (RegExMatch(key, "^F[1-8]$")) {
SetBattle(TRUE)
UseMagic(key, position, 1000, 4000, duration, 3)
} else if (RegExMatch(key, "^[1-5]$")) {
UseBelt(key, 300)
}
}
}
; 循環設定 Pos
; start => 起始編號, number => 設定幾個點
SequenceSetPos(start, number) {
idx := start
Loop, % number {
KeyWait, RButton, D
KeyWait, RButton, U
MouseGetPos, x, y
Pos[idx] := { x: x, y: y }
idx := idx + 1
}
}
; 取得當前系統時間
GetUnixTimestamp() {
NowUTC := A_NowUTC
NowUTC -= 19700101000000, S
return NowUTC
}
; 計算 來源 width x height <-> 目前解析度的相對座標
GetRelativePos(width, height, position) {
return { x: Floor((A_ScreenWidth / 2) - (width / 2) + position.x), y: A_ScreenHeight - height + position.y }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment