Skip to content

Instantly share code, notes, and snippets.

@noih
Last active November 24, 2022 12:39
Show Gist options
  • Save noih/08b73b8d61b91efaeb518e239be0c379 to your computer and use it in GitHub Desktop.
Save noih/08b73b8d61b91efaeb518e239be0c379 to your computer and use it in GitHub Desktop.
; 客製化腳本
; 參考資源
; 按鍵列表 => https://wyagd001.github.io/zh-cn/docs/KeyList.htm
global HpPercent := 65 ; 補血 % (18 ~ 97)
global HpHotKey := "1" ; 腰帶水箱編號 (1 ~ 5)
; 起始指令 / 結束指令
global CommandsOnStart := ["/run", "/nowar", "/nomenu", "/shift on", "/trade off", "/effectoff", "/weather off"]
global CommandsOnEnd := ["/nowar off", "/nomenu off", "/shift off", "/trade on", "/weather on"]
; =======================================================
; 此區域通常不需要調整
#SingleInstance, Force
#NoEnv
SetBatchLines -1
ListLines Off
SendMode Input
SetDefaultMouseSpeed, 2
SetWorkingDir, %A_ScriptDir%
global Pos := []
global TimePool := {}
; Ctrl + r 重新載入
^r::Reload
; Pause 暫停 / 回復
Pause::Pause, Toggle
; Delete 離開程式
Delete::ExitApp
; =======================================================
; 使用範例
; Alt + 6
; 啟動後,滑鼠按 1 次右鍵,設定 Pos 1
; 第一次集氣後,每 30 秒按一次右鍵
; ex: 戰士掛泰班 + 撿東西
!6::
SetTimer, Emergency ; 定時檢查血量
center := GetRelativeCenter({ x: 400, y: 303 }) ; 中心點像素座標,可自行修改
SequenceSetPos(1, 1) ; 滑鼠按 1 次右鍵,設定 Pos 1
Speak(CommandsOnStart) ; 說 起始指令
SetBattle(1) ; 切換成戰鬥
Chant("F1", 2000) ; 按 F1 等 2000 豪秒
Loop { ; 無限迴圈
if (SetBattle(1)) { ; 如果成功切換了戰鬥
Chant("F1", 2000) ; 重新集氣 F1
}
UseRClick("F1", Pos[1], 30) ; 每 30 秒在 Pos1 按右鍵
Pick(center) ; 中心點範圍內撿東西
}
return
; Alt + 7
; 啟動後,滑鼠按 4 次右鍵,設定 Pos 1 ~ 4
; 技能用完在 Pos 1 點右鍵,循環連點左鍵 Pos2 ~ 4
; ex: 盜賊掛冰暴
!7::
SetTimer, Emergency ; 定時檢查血量
SequenceSetPos(1, 4) ; 滑鼠按 4 次右鍵,設定 Pos 1 ~ 4
Speak(CommandsOnStart) ; 說: 起始指令
SetBattle(1) ; 切換成戰鬥
Chant("F1", 2000) ; 按 F1 等 2000 豪秒
Loop { ; 無限迴圈
if (SetBattle(1)) { ; 如果成功切換了戰鬥
Chant("F1", 2000) ; 重新集氣 F1
}
if (IsSkillEmpty()) { ; 如果技能綠色條空的
UseRClick("F1", Pos[1], 1) ; 在 Pos 1 按右鍵
}
LClick(Pos[2]) ; 在 Pos 2 按左鍵
LClick(Pos[3]) ; 在 Pos 3 按左鍵
LClick(Pos[4]) ; 在 Pos 4 按左鍵
}
return
; Alt + 8
; 啟動後,滑鼠按 1 次右鍵,設定 Pos 1
; 循環放 F1 法術,定時放 F2, F3 法術
; ex: 祭司掛補、++、排
!8::
SetTimer, Emergency ; 定時檢查血量
SequenceSetPos(1, 1) ; 滑鼠按 1 次右鍵,設定 Pos 1
InitWindowsState() ; 關閉視窗、人物置中
Loop { ; 無限迴圈
SetBattle(TRUE) ; 切換成戰鬥
UseMagic("F1", Pos[1], 2600, 3700, 0) ; F1 集氣 2600 毫秒,施法 3700 毫秒,每 0 秒使用
UseMagic("F2", Pos[1], 2700, 3700, 180) ; F2 集氣 2700 毫秒,施法 3700 毫秒,每 180 秒使用
UseMagic("F1", Pos[1], 2600, 3700, 10) ; F1 集氣 2600 毫秒,施法 3700 毫秒,每 10 秒使用
UseMagic("F3", Pos[1], 2700, 3700, 80) ; F3 集氣 2700 毫秒,施法 3700 毫秒,每 80 秒使用
}
return
; Alt + 9
; 啟動後,滑鼠按 1 次右鍵,設定 Pos 1
; 循環放 F1 技能
; ex: 祭司掛看靈魂
!9::
SetTimer, Emergency ; 定時檢查血量
SequenceSetPos(1, 1) ; 滑鼠按 1 次右鍵,設定 Pos 1
InitWindowsState() ; 關閉視窗、人物置中
Loop { ; 無限迴圈
UseSkill("F1", Pos[1], 0, 4000, 10, "Left") ; F1 集氣 0 毫秒,放技能 4000 毫秒,每 10 秒使用,按滑鼠左鍵
}
return
; Alt + 0
; 啟動後,滑鼠按 1 次右鍵,設定 Pos 1
; F1 技能,連續右鍵施放
; ex: 祭司掛卡里斯
!0::
SetTimer, Emergency ; 定時檢查血量
SequenceSetPos(1, 1) ; 滑鼠按 1 次右鍵,設定 Pos 1
Loop { ; 無限迴圈
SetBattle(1) ; 切換成戰鬥
Chant("F1", 2100) ; F1 集氣 2100 毫秒
RClick(Pos[1], 42) ; 滑鼠右鍵 42 次
KeyPress("~", 2) ; 按 "~" 取消施法
Sleep, 3200 ; 等待 3200 毫秒
}
return
; Alt + y
; 啟動後,滑鼠按 2 次右鍵,設定 Pos 1 ~ 2
; 技能用完且 20 秒後在 Pos 1 點右鍵,連點左鍵 Pos2
; ex: 戰士掛雙重
!y::
SetTimer, Emergency ; 定時檢查血量
SequenceSetPos(1, 2) ; 滑鼠按 2 次右鍵,設定 Pos 1 ~ 2
Speak(CommandsOnStart) ; 說: 起始指令
SetBattle(1) ; 切換成戰鬥
Chant("F1", 2000) ; 按 F1 等 2000 豪秒
Loop { ; 無限迴圈
if (SetBattle(1)) { ; 如果成功切換了戰鬥
Chant("F1", 2000) ; 重新集氣 F1
}
if (IsTimeUp("F1", 20) AND IsSkillEmpty()) { ; 如果 F1 用了 20 秒,而且技能綠色條空的
RClick(Pos[1]) ; 在 Pos 1 按右鍵
UpdateLastTime("F1") ; 更新最後使用時間
}
LClick(Pos[2]) ; 在 Pos 2 按左鍵
}
return
; Alt + u
; 自動補血、連點左鍵
; ex: 連點掛紅龍
!u::
SetTimer, Emergency ; 定時檢查血量
Loop { ; 無限迴圈
SetBattle(1)
MouseClick, Left ; 點滑鼠左鍵 (當前滑鼠位置)
Sleep, 50 ; 等待 50 毫秒
}
return
; Alt + i
; 啟動後,滑鼠按 2 次右鍵,設定 Pos 1, 2
; 放魔增 (Pos1) 法術 (Pos2)、自動喝藍水 (1)
; ex. 法師掛法術
!i::
SetTimer, Emergency ; 定時檢查血量
SequenceSetPos(1, 2)
Loop { ; 無限迴圈
SetBattle(1)
if (isManaLow()) { ; 如果魔力太低
UseBelt("1", 300) ; 按 1 補藍
}
UseMagic("F4", Pos[1], 700, 4000, 151, 3) ; F4 集氣 700 毫秒,放法術 4000 毫秒,每 151 秒使用
UseMagic("F2", Pos[2], 700, 4000, 5, 3) ; F2 集氣 700 毫秒,放法術 4000 毫秒,每 5 秒使用
}
return
; Ctrl + t
; 說 結束指令
^t::
InitWindowsState() ; 關閉視窗、人物置中
Speak(CommandsOnEnd) ; 說 結束指令
return
; 緊急事項
Emergency:
CheckHp(HpHotKey, HpPercent) ; 檢查血量
return
; =======================================================
; 腳本提供的功能,此區域通常不需要調整
; Ctrl + Alt + 1 ~ 8
; 傳統方式設定 Pos 點
^!1::
^!2::
^!3::
^!4::
^!5::
^!6::
^!7::
^!8::
MouseGetPos, x, y
idx := SubStr(A_ThisHotkey, 3, 1)
Pos[idx] := { x: x, y: y }
return
; Ctrl + Y
; 1.5 秒後 (為了不被鼠標擋住),顯示觸發當下的滑鼠座標、顏色資訊
^y::
MouseGetPos, x, y
Sleep, 1500
PixelGetColor, color, %x%, %y%
rgb := hex2rgb(color)
MsgBox, % "pos: [" . x . ", " . y . "], color: " . color . " (" . rgb[1] . "," . rgb[2] . "," . rgb[3] . ")"
return
; 循環設定 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
}
}
; 16 進制顏色轉 RGB
hex2rgb(v) {
n := InStr(v, "0x") ? v : (InStr(v, "#") ? "0x" SubStr(v, 2) : "0x" v)
return [(n / 65536) & 255, (n / 256) & 255, n & 255]
}
; 技能綠條是否為空 ?
IsSkillEmpty() {
p := GetRelativeCenterBottom({ x: 761, y: 595 })
PixelGetColor, color, p.x, p.y
return color = 0x182429
}
; 點滑鼠左鍵, ex. LClick({ x: 0, y: 0 })
LClick(position = "", cnt = 1, preMs = 0) {
Loop, % cnt {
if (position) {
MouseMove, position.x, position.y, 0
Sleep, % preMs
}
MouseClick, Left
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
}
}
; 關掉視窗、人物置中、右鍵點兩下
InitWindowsState() {
KeyPress("Escape", 3) ; close window
AlignCenter()
RClick(GetRelativeCenterBottom({ 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")
}
}
; 血量少於百分比 ?
; percentage 18 ~ 97
IsHpLessThan(percentage) {
if (percentage >= 18 AND percentage <= 97) {
p := GetRelativeCenterBottom({ 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
}
; 檢查血量並補血
; key 1 ~ 5
; percentage 百分比
CheckHp(key, percentage) {
if (!IsDead() AND IsHpLessThan(percentage) AND RegExMatch(key, "^[1-5]$")) {
UseBelt(key, 300)
}
}
; 是否已死亡?
IsDead() {
p := GetRelativeCenterBottom({ x: 27, y: 596 })
PixelGetColor, color, p.x, p.y
return color != 0x292894
}
; 設定戰鬥模式
; index 1 = 戰鬥, 2 = 和平, 3 = PK
SetBattle(index) {
changed := FALSE
Loop, 10 {
p := GetRelativeCenterBottom({ x: 713, y: 555 })
PixelGetColor, color, p.x, p.y
if ((index = 1 AND (color = 0x293431 OR color = 0xD6D3D6)) OR (index = 0 AND (color = 0x526D6B OR color = 0xBDBABD OR color = 0x293842)) OR (index = 2 AND (color = 0xE7E3E7 OR color = 0x6B868C))) {
return changed
}
LClick(GetRelativeCenterBottom({ x: 708, y: 560 }), 1, 150)
Sleep, 100
changed := TRUE
}
}
; 用腰帶物品欄
; 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
}
}
; 快速鍵時間到了嗎?
IsTimeUp(key, duration) {
if (duration = "" OR duration <= 0 OR TimePool[key] = "") {
return TRUE
}
result := (GetUnixTimestamp() - TimePool[key]) >= duration
OutputDebug, % "? " . "s " . GetUnixTimestamp() . ", t " . TimePool[key] . ", d " . duration . ", ? " . result
return result
}
isManaLow() {
p := GetRelativeCenterBottom({ x: 783, y: 587 })
PixelGetColor, color, p.x, p.y
return color != 0x5A0818
}
; 更新快速鍵最後使用時間
; 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)
}
; 定時使用右鍵
; key 快速鍵
; position 位置
; duration 多久再次使用
; cnt 點擊次數
UseRClick(key, position, duration, cnt = 2) {
if (IsTimeUp(key, duration)) {
RClick(position, cnt)
UpdateLastTime(key)
}
}
; 定時使用技能
; key 快速鍵
; position 位置
; preMS 詠唱時間
; postMS 施放時間
; duration 多久再次使用
; mouseKey 滑鼠左鍵 (Left) / 右鍵 (Right)
; cnt 集氣、放技能時,點擊 (按鍵、滑鼠) 的次數
UseSkill(key, position, preMS, postMS, duration, mouseKey = "Right", cnt = 3) {
if (RegExMatch(key, "^F[1-8]$") AND IsTimeUp(key, duration)) {
px := ""
py := ""
MouseGetPos, px, py
Chant(key, preMs - (cnt * 160), cnt)
Loop, % cnt {
MouseClick, %mouseKey%, position.x, position.y, 1, 0, D,
Sleep, 80
MouseClick, %mouseKey%, position.x, position.y, 1, 0, U,
Sleep, 80
}
MouseMove, px, py
Sleep, Max(postMS - (cnt * 160), 0)
UpdateLastTime(key)
}
}
; 取得當前系統時間
GetUnixTimestamp() {
NowUTC := A_NowUTC
NowUTC -= 19700101000000, S
return NowUTC
}
; 從 base 中心點,上下左右範圍內撿東西
Pick(base, left = 65, right = 65, top = 55, bottom = 65) {
x := base.x + right
While (x >= (base.x - left)) {
y := base.y - top
While (y <= (base.y + bottom)) {
LClick({ x: x, y: y })
y := y + 15
}
x := x - 8
}
}
GetRelativeCenterBottom(position, width = 800, height = 600) {
return { x: Floor((A_ScreenWidth / 2) - (width / 2) + position.x), y: A_ScreenHeight - height + position.y }
}
GetRelativeCenter(position, width = 800, height = 600) {
return { x: Floor((A_ScreenWidth / 2) - (width / 2) + position.x), y: Floor((A_ScreenHeight / 2) - (height / 2) + position.y) }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment