为了Lua模块化设计现开始设计通用函数,加了详细注释及使用范例,力求情怀站的Lua代码更简洁可读。

查询物品携带数量函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
-- 查询物品携带数量的函数,类似TinTin++的carryqty
-- 参数说明:
-- item_id: 物品ID,如"da huandan"
-- 返回值:物品数量,如果没有则返回0
function carryqty(item_id)
-- 如果参数为空,返回0
if not item_id or item_id == "" then
return 0
end

-- 如果物品表中没有该物品,返回0
if not item or not item[item_id] then
return 0
end

-- 返回物品数量
return item[item_id]
end

通用触发器管理函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
-- 通用触发器管理函数
-- trigger_prefix: 触发器名称前缀
-- start_index: 开始索引
-- end_index: 结束索引
function manage_triggers(trigger_prefix, start_index, end_index, action)
for i = start_index, end_index do
if action == "close" then
close_trigger(trigger_prefix .. "_" .. i)
elseif action == "open" then
open_trigger(trigger_prefix .. "_" .. i)
end
end
end

-- 关闭指定前缀和范围的触发器
function close_triggers(trigger_prefix, start_index, end_index)
manage_triggers(trigger_prefix, start_index, end_index, "close")
end

-- 打开指定前缀和范围的触发器
function open_triggers(trigger_prefix, start_index, end_index)
manage_triggers(trigger_prefix, start_index, end_index, "open")
end

--用法示例:
--[[
-- 关闭otherquest_task_1到otherquest_task_5的触发器
close_triggers("otherquest_task", 1, 5)

-- 打开fight_1到fight_10的触发器
open_triggers("fight", 1, 10)
--]]

通用A*寻路算法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
-- 通用A*寻路算法
-- start_room: 起始房间ID
-- end_room: 目标房间ID
-- options: 可选参数表,包含以下可选项:
-- - room_list: 可用房间列表,默认为nil(使用所有房间)
-- - heuristic_func: 启发式函数,默认为曼哈顿距离
-- - get_neighbors_func: 获取相邻房间函数,默认使用exits表
-- - cost_func: 计算移动成本函数,默认为1
-- - max_iterations: 最大迭代次数,默认为10000
-- - debug: 是否输出调试信息,默认为false
-- 添加通用A*寻路算法
function astar_search(start_room, end_room, options)
options = options or {}
local room_list = options.room_list
local max_iterations = options.max_iterations or 10000
local debug = options.debug or false
local max_radius = options.max_radius or 5 -- 最大搜索半径参数,默认5

-- 默认启发式函数:曼哈顿距离
local function default_heuristic(room_id, goal_id)
if not rooms[room_id] or not rooms[goal_id] then
return 999999 -- 如果房间不存在,返回一个很大的值
end

local x1, y1 = rooms[room_id].x or 0, rooms[room_id].y or 0
local x2, y2 = rooms[goal_id].x or 0, rooms[goal_id].y or 0

local distance = math.abs(x1 - x2) + math.abs(y1 - y2)

-- 如果距离超过最大半径,返回一个很大的值
if distance > max_radius then
return 999999
end

return distance
end

-- 默认获取相邻房间函数
local function default_get_neighbors(room_id)
local neighbors = {}
if not rooms[room_id] or not rooms[room_id].exits then
return neighbors
end

for dir, next_room in pairs(rooms[room_id].exits) do
-- 如果提供了房间列表,则只考虑列表中的房间
if not room_list or table.contains(room_list, next_room) then
table.insert(neighbors, { room = next_room, dir = dir, cost = 1 })
end
end

return neighbors
end

-- 检查表中是否包含某个值
local function table_contains(t, value)
for _, v in pairs(t) do
if v == value then
return true
end
end
return false
end

-- 使用自定义或默认函数
local heuristic = options.heuristic_func or default_heuristic
local get_neighbors = options.get_neighbors_func or default_get_neighbors

-- 优先队列实现
local open_set = {}
local closed_set = {}
local g_score = {} -- 从起点到当前点的实际代价
local f_score = {} -- 估计总代价
local came_from = {} -- 记录路径
local directions = {} -- 记录方向

-- 初始化起点
g_score[start_room] = 0
f_score[start_room] = heuristic(start_room, end_room)
table.insert(open_set, start_room)

local iterations = 0

while #open_set > 0 and iterations < max_iterations do
iterations = iterations + 1

-- 找到open_set中f_score最小的节点
local current_index = 1
for i = 2, #open_set do
if f_score[open_set[i]] < f_score[open_set[current_index]] then
current_index = i
end
end

local current = open_set[current_index]

-- 如果到达目标,构建路径并返回
if current == end_room then
local path = { current }
local path_dirs = {}

while came_from[current] do
current = came_from[current]
table.insert(path, 1, current)
if directions[current] then
table.insert(path_dirs, 1, directions[current])
end
end

if debug then
echo("\nA*搜索完成,迭代次数: " .. iterations)
echo("\n路径: " .. table.concat(path, " -> "))
echo("\n方向: " .. table.concat(path_dirs, ", "))
end

return path, path_dirs
end

-- 从open_set中移除当前节点
table.remove(open_set, current_index)
-- 添加到closed_set
table.insert(closed_set, current)

-- 检查所有邻居
for _, neighbor_info in ipairs(get_neighbors(current)) do
local neighbor = neighbor_info.room
local dir = neighbor_info.dir
local move_cost = neighbor_info.cost or 1

-- 如果邻居已经在closed_set中,跳过
if not table_contains(closed_set, neighbor) then
-- 计算从起点经过当前节点到邻居的代价
local tentative_g_score = (g_score[current] or 0) + move_cost

-- 如果邻居不在open_set中,或者找到了更好的路径
if not table_contains(open_set, neighbor) or tentative_g_score < (g_score[neighbor] or math.huge) then
-- 更新路径信息
came_from[neighbor] = current
directions[neighbor] = dir
g_score[neighbor] = tentative_g_score
f_score[neighbor] = tentative_g_score + heuristic(neighbor, end_room)

-- 如果邻居不在open_set中,添加它
if not table_contains(open_set, neighbor) then
table.insert(open_set, neighbor)
end
end
end
end
end

if debug then
echo("\nA*搜索失败,迭代次数: " .. iterations)
end

-- 没有找到路径
return nil, nil
end

-- 使用A*寻路和job.lua中的get_job_rooms函数寻找最佳任务路径
-- start_room: 起始房间ID
-- job_zone: 任务区域
-- flag_job: 任务标志
-- options: 可选参数表,与astar_search相同
function find_best_job_path(start_room, job_zone, flag_job, options)
options = options or {}

-- 获取任务房间列表
local room_list_check = {}
for _, room_id in ipairs(get_job_rooms(job_zone, flag_job) or {}) do
room_list_check[room_id] = true
end

-- 重置搜索列表
local search_list = reset_search_list(room_list_check, get_job_rooms(job_zone, flag_job), job_zone, flag_job, 1)

if #search_list == 0 then
if options.debug then
echo("\n没有找到可用的任务房间")
end
return nil, nil, nil
end

-- 找到最近的任务房间
local best_path = nil
local best_dirs = nil
local best_target = nil
local best_distance = math.huge

for _, target_room in ipairs(search_list) do
local path, dirs = astar_search(start_room, target_room, options)

if path and #path < best_distance then
best_path = path
best_dirs = dirs
best_target = target_room
best_distance = #path
end
end

if options.debug and best_path then
echo("\n找到最佳任务路径,目标房间: " .. best_target)
echo("\n路径长度: " .. #best_path)
end

return best_path, best_dirs, best_target
end

通用日志输出函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
-- 添加通用日志输出函数
-- 参数说明:
-- message: 日志消息内容
-- color: 颜色代码,默认为C.x
-- prefix: 日志前缀,默认为"<解密>"
function log_message(message, color, prefix)
local id = var["char_id"] or "none"
local os_date = os.date("%m/%d %H:%M:%S")
color = color or C.x
prefix = prefix or "<解密>"
echo("\n" .. C.c .. prefix .. ":" .. os_date .. color .. "【玩家:" .. id .. "】:" .. message)
end

--[[
-- 用法示例:
log_message("这是一条日志消息", C.y, "<解密>")
--]]

通用大还丹购买函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
-- 购买大还丹的通用函数
-- 参数说明:
-- target_count: 目标数量,希望携带的大还丹总数
-- callback: 购买完成后执行的回调函数,可选
function buy_da_huandan(target_count, callback)
-- 使用i命令检查物品
exec("i")
wait(0.5, function()
-- 检查当前携带的大还丹数量
local current_count = carryqty("da huandan")

-- 计算需要购买的数量
local need_count = target_count - current_count

-- 如果已经有足够的大还丹,不需要购买
if need_count <= 0 then
log_message("已有足够的大还丹,当前数量: " .. current_count, C.g)
-- 如果有回调函数,直接执行
if callback then
callback()
end
return true
end

-- 输出购买信息
log_message("当前大还丹数量: " .. current_count .. ",目标数量: " .. target_count .. ",需要购买: " .. need_count, C.y)

-- 前往扬州当铺(92)
g(92, function()
-- 执行购买逻辑
buy_huandan_recursive(need_count, target_count, callback)
end)
end)

return true
end

-- 递归购买大还丹的辅助函数
-- 由于每次只能买一个,需要递归调用
function buy_huandan_recursive(remaining, target_count, callback)
-- 如果已经购买完所需数量,结束递归
if remaining <= 0 then
-- 使用i命令检查物品
exec("i")
wait(0.5, function()
local final_count = carryqty("da huandan")
log_message("大还丹购买完成,当前数量: " .. final_count, C.g)

-- 如果有回调函数,执行它
if callback then
callback()
end
end)
return
end

-- 使用check_busy2检查是否繁忙
check_busy2(function()
-- 执行购买命令(每次只能买一个)
exec("duihuan da huandan")

-- 延迟一段时间后检查是否购买成功并继续递归
wait(1, function()
-- 使用i命令检查物品
exec("i")
wait(0.5, function()
local current_count = carryqty("da huandan")
local previous_count = target_count - remaining

-- 检查是否购买成功(当前数量比之前多)
if current_count > previous_count then
-- 购买成功,继续购买下一个
buy_huandan_recursive(target_count - current_count, target_count, callback)
else
-- 购买失败,但继续尝试购买
log_message("购买未成功,继续尝试...", C.y)
-- 继续尝试购买,不减少remaining
buy_huandan_recursive(remaining, target_count, callback)
end
end)
end)
end)
end

--[[
-- 用法示例:
-- 确保携带10个大还丹,不足则前往扬州当铺购买,完成后执行回调函数
buy_da_huandan(10, function()
log_message("购买完成后执行的操作", C.g)
-- 这里可以添加其他命令
-- exec("其他命令")
end)
--]]

通用物品购买函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
-- 通用物品购买函数
-- 参数说明:
-- item_id: 物品ID,如"da huandan"
-- target_count: 目标数量,希望携带的物品总数
-- shop_room_id: 购买物品的商店房间ID
-- buy_command: 购买物品的命令,如"duihuan da huandan"
-- callback: 购买完成后执行的回调函数,可选
-- options: 可选参数表,包含以下可选项:
-- - delay: 购买间隔延迟,默认为1秒
-- - check_delay: 检查物品延迟,默认为0.5秒
-- - prefix: 日志前缀,默认为"<解密>"
function buy_item(item_id, target_count, shop_room_id, buy_command, callback, options)
options = options or {}
local delay = options.delay or 1
local check_delay = options.check_delay or 0.5
local prefix = options.prefix or "<解密>"

-- 使用i命令检查物品
exec("i")
wait(check_delay, function()
-- 检查当前携带的物品数量
local current_count = carryqty(item_id)

-- 计算需要购买的数量
local need_count = target_count - current_count

-- 如果已经有足够的物品,不需要购买
if need_count <= 0 then
log_message("已有足够的" .. item_id .. ",当前数量: " .. current_count, C.g, prefix)
-- 如果有回调函数,直接执行
if callback then
callback()
end
return true
end

-- 输出购买信息
log_message("当前" .. item_id .. "数量: " .. current_count .. ",目标数量: " .. target_count .. ",需要购买: " .. need_count, C.y, prefix)

-- 前往指定商店
g(shop_room_id, function()
-- 执行购买逻辑
buy_item_recursive(item_id, need_count, target_count, buy_command, callback, delay, check_delay, prefix)
end)
end)

return true
end

-- 递归购买物品的辅助函数
function buy_item_recursive(item_id, remaining, target_count, buy_command, callback, delay, check_delay, prefix)
-- 如果已经购买完所需数量,结束递归
if remaining <= 0 then
-- 使用i命令检查物品
exec("i")
wait(check_delay, function()
local final_count = carryqty(item_id)
log_message(item_id .. "购买完成,当前数量: " .. final_count, C.g, prefix)

-- 如果有回调函数,执行它
if callback then
callback()
end
end)
return
end

-- 使用check_busy2检查是否繁忙
check_busy2(function()
-- 执行购买命令
exec(buy_command)

-- 延迟一段时间后检查是否购买成功并继续递归
wait(delay, function()
-- 使用i命令检查物品
exec("i")
wait(check_delay, function()
local current_count = carryqty(item_id)
local previous_count = target_count - remaining

-- 检查是否购买成功(当前数量比之前多)
if current_count > previous_count then
-- 购买成功,继续购买下一个
buy_item_recursive(item_id, target_count - current_count, target_count, buy_command, callback, delay, check_delay, prefix)
else
-- 购买失败,但继续尝试购买
log_message("购买未成功,继续尝试...", C.y, prefix)
-- 继续尝试购买,不减少remaining
buy_item_recursive(item_id, remaining, target_count, buy_command, callback, delay, check_delay, prefix)
end
end)
end)
end)
end

--[[
-- 用法示例:
-- 确保携带10个大还丹,不足则前往扬州当铺购买,完成后执行回调函数
buy_item("da huandan", 10, 92, "duihuan da huandan", function()
log_message("购买完成后执行的操作", C.g)
-- 这里可以添加其他命令
-- exec("其他命令")
end)

-- 确保携带5个金创药,不足则前往药店购买
buy_item("jin chuang yao", 5, 93, "buy jin chuang yao", nil, {prefix = "<解密>"})
--]]

通用HP检测函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
-- 通用HP检测函数
-- 参数说明:
-- trigger_name: 触发器名称,如"otherquest_tongtianta_1"
-- options: 可选参数表,包含以下可选项:
-- - qi_threshold: 气血百分比阈值,低于此值时执行恢复命令,默认为80
-- - neili_threshold: 内力阈值,低于此值时执行恢复命令,默认为5000
-- - recovery_command: 恢复命令,默认为"fu dan"
-- - callback: 自定义回调函数,可以根据HP信息执行自定义操作
function setup_hp_monitor(trigger_name, options)
options = options or {}
local qi_threshold = options.qi_threshold or 80
local neili_threshold = options.neili_threshold or 5000
local recovery_command = options.recovery_command or "fu dan"
local callback = options.callback

-- 关闭已存在的同名触发器(如果有)
close_trigger(trigger_name)

-- 添加新的HP监控触发器
add_trigger(trigger_name, "\^\\s*HP\:(.+)", function(params)
local jing, maxjing, hurtjing, jingli, maxjingli, qi, maxqi, hurtqi, neili, maxneili, jiali, shen, food, pot, maxpot, water, myexp = string.match(params[1],
"(.%d*)/(%d-)/(%d-)%%/(.%d*)/(%d-)/%d-/(.%d*)/(%d-)/(%d-)%%/(.%d*)/(%d-)/%+(%d-)/(.%d-)/%d-/%d-/(%d-)%.%d%d%%/(%d-)/(%d-)/(%d-)%.%d%d%%/(%d-)/%d")

-- 转换为数字并存入变量
var["jing"], var["maxjing"], var["hurtjing"] = tonumber(jing), tonumber(maxjing), tonumber(hurtjing)
var["jingli"], var["maxjingli"] = tonumber(jingli), tonumber(maxjingli)
var["qi"], var["maxqi"], var["hurtqi"] = tonumber(qi), tonumber(maxqi), tonumber(hurtqi)
var["neili"], var["maxneili"], var["jiali"] = tonumber(neili), tonumber(maxneili), tonumber(jiali)
var["shen"] = tonumber(shen)
var["food"], var["pot"], var["maxpot"] = tonumber(food), tonumber(pot), tonumber(maxpot)
var["water"], var["exp"] = tonumber(water), tonumber(myexp)

-- 检查是否需要恢复
if var["hurtqi"] < qi_threshold or var["neili"] < neili_threshold then
exec(recovery_command)
end

-- 如果有自定义回调函数,执行它
if callback then
callback({
jing = var["jing"], maxjing = var["maxjing"], hurtjing = var["hurtjing"],
jingli = var["jingli"], maxjingli = var["maxjingli"],
qi = var["qi"], maxqi = var["maxqi"], hurtqi = var["hurtqi"],
neili = var["neili"], maxneili = var["maxneili"], jiali = var["jiali"],
shen = var["shen"],
food = var["food"], pot = var["pot"], maxpot = var["maxpot"],
water = var["water"], exp = var["exp"]
})
end

-- 清理临时变量
jing, maxjing, hurtjing, jingli, maxjingli = nil, nil, nil, nil, nil
qi, maxqi, hurtqi, neili, maxneili = nil, nil, nil, nil, nil
jiali, shen, food, pot, maxpot = nil, nil, nil, nil, nil
water, myexp = nil, nil
end)

return trigger_name
end

-- 移除HP监控触发器
function remove_hp_monitor(trigger_name)
close_trigger(trigger_name)
end

--[[
-- 用法示例:
-- 基本用法(使用默认参数)
setup_hp_monitor("my_hp_monitor")

-- 自定义阈值和恢复命令
setup_hp_monitor("combat_hp_monitor", {
qi_threshold = 70,
neili_threshold = 3000,
recovery_command = "yun recover;yun regenerate"
})

-- 使用自定义回调函数
setup_hp_monitor("advanced_hp_monitor", {
callback = function(hp_data)
-- 根据HP数据执行自定义逻辑
if hp_data.hurtjing < 50 then
exec("yun refresh")
end

if hp_data.food < 100 then
exec("eat liang")
end

if hp_data.water < 100 then
exec("drink jiudai")
end
end
})

-- 移除监控
remove_hp_monitor("my_hp_monitor")
--]]

--简易HP检测(保留原有功能,使用新函数实现)
--setup_hp_monitor("otherquest_tongtianta_1")