actions.display_message("Hello world!")
local hp = game.get_player_hp()
local fp = game.get_player_fp()
local sp = game.get_player_sp()
print("HP:", hp, "FP:", fp, "SP:", sp)
function select_target()
local pos = game.get_player_coord()
if pos then
actions.target_closest_character(
ActorGroup.Monsters,
pos.x, pos.y, pos.z, -- anchor
500.0, -- radius
{"Young Flem", "Digger Clan"}, -- filters
false -- checkRange
)
end
end
function auto_attack()
local target = game.get_player_target()
if target ~= 0 then
actions.click_on_target(target)
end
end
while true do
if not game.is_target_valid() then
select_target()
else
auto_attack()
end
sleep(200)
end
local pos = game.get_player_coord()
if pos then
local loot = game.get_closest_lootable_item(pos.x, pos.y, pos.z, 200.0)
if loot ~= 0 then actions.pick_up_item(loot) end
end
local pos = game.get_player_coord()
if not pos then return end
-- move 20 units on X and Z
local newX = pos.x + 20
local newY = pos.y
local newZ = pos.z + 20
actions.move_player(newX, newY, newZ)
Продать все предметы с подстрокой "sword" НПСу "CHARGER"
Код:
local npc = game.find_character_by_name(
ActorGroup.NPCs,
"CHARGER"
)
if npc == 0 then
return
end
actions.perform_npc_action(npc, 0)
sleep(1000)
actions.switch_tab_window(1)
sleep(400)
for bag = 0, 4 do
for cell = 0, 19 do
local ptr = game.get_bag_item(bag, cell)
if ptr ~= 0 then
local name = game.get_bag_item_name(ptr)
local isSword = string.find(string.lower(name), "sword", 1, true)
if name and isSword then
actions.put_item_into_sell_window(bag, cell)
sleep(200)
actions.confirm_sell_window()
sleep(200)
end
end
end
end
local inv = game.get_inventory()
for bagIdx, bag in ipairs(inv) do
for cellIdx, ptr in ipairs(bag) do
if ptr ~= 0 then
local name = game.get_bag_item_name(ptr)
print(("Bag %d Cell %d: %s"):format(bagIdx-1, cellIdx-1, name or "unknown"))
end
end
end
while true do
local debuffs = game.get_debuff_count()
if debuffs > 0 then
-- change bar/cell if needed
actions.use_bar_action(0, 0, true)
end
sleep(200)
end
Скрипт запускает основного бота. При появлении ГМ-а бот останавливается, и шлется пакет на прыжок.
Код:
bot.start()
-- jump
local pkt_type = string.char(0x0D, 0x16)
local pkt_body = string.char(0x46)
while true do
if game.get_is_gm_present()
or game.has_gm_appeared_recently(30000) then
bot.stop()
while true do
actions.send_packet(pkt_type, pkt_body, true)
sleep(300)
end
end
sleep(100)
end
Скрипт держится в радиусе ~75 от заданного персонажа и атакует указаную цель.
Код:
local group = ActorGroup.Monsters -- or ActorGroup.OtherPlayers / ActorGroup.NPCs
local fallback_name = "qweqwe" -- name to search when no party-assist target is present
while true do
local assist_ptr = game.find_party_assist_marked_character(ActorGroup.Monsters)
if assist_ptr ~= 0 then
-- Ensure we are targeting the assist-marked character
local current_target = game.get_player_target()
if current_target ~= assist_ptr then
actions.set_target(assist_ptr, true)
end
else
-- No party assist: try to find by name and move to that character
local found_ptr = game.find_character_by_name(ActorGroup.OtherPlayers, fallback_name)
if found_ptr ~= 0 then
local coord = game.get_character_coord(found_ptr)
if coord ~= nil and coord.x and coord.y and coord.z then
local player_coord = game.get_player_coord()
if player_coord ~= nil then
local dx = player_coord.x - coord.x
local dy = player_coord.y - coord.y
local dz = player_coord.z - coord.z
local distance = math.sqrt(dx * dx + dy * dy + dz * dz)
local radius = 75
if distance > radius then
-- pick a random offset inside a 50-unit radius
local angle = math.random() * math.pi * 2
local dist = math.random() * radius
local rx = coord.x + math.cos(angle) * dist
local ry = coord.y + math.sin(angle) * dist
local rz = coord.z
actions.move_player(rx, ry, rz)
end
end
end
end
end
-- If we have any target, auto-attack and use bar action (1,1)
local current_target = game.get_player_target()
if current_target ~= 0 then
actions.click_on_target(current_target)
sleep(100)
actions.use_bar_action(1, 1)
end
sleep(100) -- wait 100 ms before checking again
end
local function apply_buff(player_name, bar_index, cell_index)
local group = ActorGroup.OtherPlayers;
local characterPtr = game.find_character_by_name(group, player_name)
if characterPtr == 0 then return end
actions.use_bar_action(bar_index, cell_index, true)
sleep(500)
actions.click_on_target(characterPtr)
end
local function callback(sender, message)
print("[PRIVATE] " .. sender .. ": " .. message)
local lower = message:lower()
if lower:match("velo") or lower:match("вв") then
apply_buff(sender, 0, 0)
end
if lower:match("shield") or lower:match("щит") then
apply_buff(sender, 0, 1)
end
if lower:match("dodge") or lower:match("додж") then
apply_buff(sender, 0, 2)
end
end
actions.on_private_message(callback)
print("Listening for private messages ...")
while true do
sleep(250)
end
---@class ActorGroup
---@field Monsters integer
---@field OtherPlayers integer
---@field NPCs integer
ActorGroup = {}
---@class bot
---Bot control and inter-bot communication module
---Модуль управления ботом и межботовой коммуникации
bot = {
---Start the bot / Запустить бота
---@return nil
start = function() end,
---Stop the bot / Остановить бота
---@return nil
stop = function() end,
---Toggle bot state / Переключить состояние бота
---@return nil
toggle = function() end,
---Check if bot is running / Проверить, работает ли бот
---@return boolean
is_running = function() end,
---Get process PID / Получить PID процесса
---@return integer
pid = function() end,
---Send message to another bot by PID / Отправить сообщение другому боту по PID
---@param targetPid integer Target bot PID / PID целевого бота
---@param message string Message to send / Сообщение для отправки
---@return boolean Success / Успех
send_to_bot_by_pid = function(targetPid, message) end,
---Send message to another bot by player name / Отправить сообщение другому боту по имени игрока
---@param targetPlayerName string Target player name / Имя целевого игрока
---@param message string Message to send / Сообщение для отправки
---@return boolean Success / Успех
send_to_bot_by_name = function(targetPlayerName, message) end,
---Show notification popup / Показать всплывающее уведомление
---@param msg string Message text / Текст сообщения
---@return boolean Success (false if rate-limited) / Успех (false при ограничении частоты)
show_notification = function(msg) end,
}
---@class game
---Game state queries module / Модуль запросов состояния игры
game = {
---Check if player is dead / Проверить, мертв ли игрок
---@return boolean
is_player_dead = function() end,
---Check if player is in siege mode / Проверить, находится ли игрок в осадном режиме
---@return boolean
is_in_siege_mode = function() end,
---Get player GID / Получить GID игрока
---@return integer|nil
get_player_gid = function() end,
---Get player SID / Получить SID игрока
---@return integer|nil
get_player_sid = function() end,
---Get player name / Получить имя игрока
---@return string|nil
get_player_name = function() end,
---Get map name / Получить название карты
---@return string|nil
get_map_name = function() end,
---Get player HP / Получить HP игрока
---@return integer|nil
get_player_hp = function() end,
---Get player FP / Получить FP игрока
---@return integer|nil
get_player_fp = function() end,
---Get player SP / Получить SP игрока
---@return integer|nil
get_player_sp = function() end,
---Get player coordinates / Получить координаты игрока
---@return {x: number, y: number, z: number}|nil
get_player_coord = function() end,
---Get debuff count / Получить количество дебаффов
---@return integer
get_debuff_count = function() end,
---Get buff count / Получить количество баффов
---@return integer
get_buff_count = function() end,
---Check if animus is summoned / Проверить, призван ли анимус
---@return boolean
is_animus_summoned = function() end,
---Check if player is out of circle / Проверить, находится ли игрок вне круга
---@param cx number Center X / Центр X
---@param cy number Center Y / Центр Y
---@param cz number Center Z / Центр Z
---@param radius number Radius / Радиус
---@return boolean
is_player_out_of_circle = function(cx, cy, cz, radius) end,
---Check if target is valid / Проверить, валидна ли цель
---@return boolean
is_target_valid = function() end,
---Get current target address / Получить адрес текущей цели
---@return integer Address or 0 / Адрес или 0
get_player_target = function() end,
---Check if characters are nearby / Проверить, есть ли персонажи поблизости
---@param group integer ActorGroup / Группа
---@param radius number Radius / Радиус
---@return boolean
are_characters_nearby = function(group, radius) end,
---Check if characters with names are nearby / Проверить, есть ли персонажи с именами поблизости
---@param group integer ActorGroup / Группа
---@param radius number Radius / Радиус
---@param filters string[] Name filters (case-insensitive) / Фильтры имен (без учета регистра)
---@return boolean
are_characters_with_names_nearby = function(group, radius, filters) end,
---Get closest characters / Получить ближайших персонажей
---@param group integer ActorGroup / Группа
---@param ox number Origin X / Начало X
---@param oy number Origin Y / Начало Y
---@param oz number Origin Z / Начало Z
---@param radius number Radius / Радиус
---@param filters? string[] Optional name filters / Опциональные фильтры имен
---@return {ptr: integer, dist: number}[] Sorted by distance / Отсортировано по дистанции
get_closest_characters = function(group, ox, oy, oz, radius, filters) end,
---Find character by name / Найти персонажа по имени
---@param group integer ActorGroup / Группа
---@param name string Character name / Имя персонажа
---@return integer Address or 0 / Адрес или 0
find_character_by_name = function(group, name) end,
---Get character name / Получить имя персонажа
---@param ptr integer Character address / Адрес персонажа
---@return string|nil
get_character_name = function(ptr) end,
---Get character HP percent / Получить процент HP персонажа
---@param ptr integer Character address / Адрес персонажа
---@return number|nil 0..100
get_character_hp_percent = function(ptr) end,
---Get character coordinates / Получить координаты персонажа
---@param ptr integer Character address / Адрес персонажа
---@return {x: number, y: number, z: number}|nil
get_character_coord = function(ptr) end,
---Get character GID / Получить GID персонажа
---@param ptr integer Character address / Адрес персонажа
---@return integer|nil
get_character_gid = function(ptr) end,
---Get character SID / Получить SID персонажа
---@param ptr integer Character address / Адрес персонажа
---@return integer|nil
get_character_sid = function(ptr) end,
---Check if character is alive / Проверить, жив ли персонаж
---@param ptr integer Character address / Адрес персонажа
---@return boolean|nil
get_character_is_alive = function(ptr) end,
---Get character target / Получить цель персонажа
---@param ptr integer Character address / Адрес персонажа
---@return integer Address or 0 / Адрес или 0
get_character_target = function(ptr) end,
---Find party assist marked character / Найти персонажа с меткой помощи группы
---@param group integer ActorGroup / Группа
---@return integer Address or 0 / Адрес или 0
find_party_assist_marked_character = function(group) end,
---Get closest lootable item / Получить ближайший лутабельный предмет
---@param ox number Origin X / Начало X
---@param oy number Origin Y / Начало Y
---@param oz number Origin Z / Начало Z
---@param maxDist number Maximum distance / Максимальная дистанция
---@return integer Address or 0 / Адрес или 0
get_closest_lootable_item = function(ox, oy, oz, maxDist) end,
---Get loot item name / Получить имя предмета лута
---@param ptr integer Loot address / Адрес лута
---@return string|nil
get_loot_name = function(ptr) end,
---Get loot owner GID / Получить GID владельца лута
---@param ptr integer Loot address / Адрес лута
---@return integer|nil
get_loot_owner_gid = function(ptr) end,
---Get inventory / Получить инвентарь
---@return integer[][] Array of bags, each bag is array of item addresses / Массив сумок, каждая сумка - массив адресов предметов
get_inventory = function() end,
---Get bag item / Получить предмет из сумки
---@param bag integer Bag index (0-based) / Индекс сумки (с нуля)
---@param cell integer Cell index (0-based) / Индекс ячейки (с нуля)
---@return integer Address or 0 / Адрес или 0
get_bag_item = function(bag, cell) end,
---Get bag item name / Получить имя предмета из сумки
---@param ptr integer Item address / Адрес предмета
---@return string|nil
get_bag_item_name = function(ptr) end,
---Get weapon item / Получить предмет оружия
---@return integer Address or 0 / Адрес или 0
get_weapon_item = function() end,
---Check if weapon is equipped / Проверить, экипировано ли оружие
---@return boolean
is_weapon_equipped = function() end,
---Check if inventory is full / Проверить, полон ли инвентарь
---@return boolean
is_inventory_full = function() end,
}
---@class actions
---Game actions module / Модуль действий в игре
actions = {
---Display message in client / Показать сообщение в клиенте
---@param text string Message text / Текст сообщения
---@return nil
display_message = function(text) end,
---Send network packet / Отправить сетевой пакет
---@param type2 string Packet type (2 bytes) / Тип пакета (2 байта)
---@param content string Packet content / Содержимое пакета
---@param force? boolean
---@return nil
send_packet = function(type2, content, force) end,
---Send common chat message / Отправить сообщение в общий чат
---@param text string Message text / Текст сообщения
---@return nil
send_common_message = function(text) end,
---Send private message / Отправить личное сообщение
---@param name string Recipient name / Имя получателя
---@param text string Message text / Текст сообщения
---@return nil
send_private_message = function(name, text) end,
---Move player / Переместить игрока
---@param x number X coordinate / Координата X
---@param y number Y coordinate / Координата Y
---@param z number Z coordinate / Координата Z
---@return nil
move_player = function(x, y, z) end,
---Set target (better use click_on_target instead)
---Установить цель (рекомендуется использовать click_on_target вместо этого)
---@param ptr integer Target address / Адрес цели
---@param force? boolean
---@return nil
set_target = function(ptr, force) end,
---Click on target (can be used to select a target or auto-attack)
---Кликнуть по цели (может быть использовано для выбора цели или автоатаки)
---@param ptr integer Target address / Адрес цели
---@return nil
click_on_target = function(ptr) end,
---In-game tab target (4.15 only) / Внутриигровой таб цели (только 4.15)
---@return nil
in_game_tab_target = function() end,
---Target closest character / Выбрать ближайшего персонажа
---@param group integer ActorGroup / Группа
---@param ox number Origin X / Начало X
---@param oy number Origin Y / Начало Y
---@param oz number Origin Z / Начало Z
---@param radius number Radius / Радиус
---@param filters? string[] Optional name filters / Опциональные фильтры имен
---@param checkRange? boolean Check range / Проверить дальность
---@param force? boolean
---@return nil
target_closest_character = function(group, ox, oy, oz, radius, filters, checkRange, force) end,
---Perform NPC action / Выполнить действие NPC
---@param npcPtr integer NPC address / Адрес NPC
---@param index integer Action index / Индекс действия
---@param force? boolean
---@return nil
perform_npc_action = function(npcPtr, index, force) end,
---Request move to portal / Запросить перемещение к порталу
---@param index integer Portal index / Индекс портала
---@param force? boolean
---@return nil
request_move_to_portal = function(index, force) end,
---Pick up item / Поднять предмет
---@param ptr integer Item address / Адрес предмета
---@return nil
pick_up_item = function(ptr) end,
---Use bar action / Использовать действие с панели
---@param bar integer Bar index / Индекс панели
---@param cell integer Cell index / Индекс ячейки
---@param force? boolean
---@return nil
use_bar_action = function(bar, cell, force) end,
---Switch NPC tab window / Переключить вкладку окна NPC
---@param index integer Tab index / Индекс вкладки
---@return nil
switch_tab_window = function(index) end,
---Put item into sell window / Положить предмет в окно продажи
---@param bag integer Bag index (0-based) / Индекс сумки (с нуля)
---@param cell integer Cell index (0-based) / Индекс ячейки (с нуля)
---@return nil
put_item_into_sell_window = function(bag, cell) end,
---Confirm sell window / Подтвердить продажу
---@return nil
confirm_sell_window = function() end,
---Kill game process / Убить процесс игры
---@return nil
kill_game_process = function() end,
---Force disable auto attack (basic attack in game will stop
---working if auto-attack is disabled, may be useful if mage gives random basic attacks)
---Принудительно отключить автоатаку (тычки в игре перестанут
---работать при отключеной авто-атаке, может быть полезно, если маг дает случайные тычки)
---@return nil
force_disable_auto_attack = function() end,
---Restore auto attack / Восстановить автоатаку
---@return nil
restore_auto_attack = function() end,
}
---@class events
---Event subscriptions module / Модуль подписки на события
events = {
---Subscribe to common chat messages / Подписаться на сообщения общего чата
---@param callback fun(sender: string, message: string) Callback function / Функция обратного вызова
---@return nil
on_common_message = function(callback) end,
---Subscribe to private messages / Подписаться на личные сообщения
---@param callback fun(sender: string, message: string) Callback function / Функция обратного вызова
---@return nil
on_private_message = function(callback) end,
---Subscribe to bot messages / Подписаться на сообщения от других ботов
---@param callback fun(senderPid: integer, message: string) Callback function / Функция обратного вызова
---@return nil
on_bot_message = function(callback) end,
}
---Get current time in milliseconds / Получить текущее время в миллисекундах
---@return integer
function now_ms() end
---Sleep for specified milliseconds / Заснуть на указанное количество миллисекунд
---@param ms integer Milliseconds / Миллисекунды
---@return nil
function sleep(ms) end
Апишка будет дополняться
Добавлено через 3 минуты
Если отдельную тему нельзя, можете удалить. Сделаю просто сообщение в теме о продаже.
Последний раз редактировалось Diantro; 08.12.2025 в 17:53.
Причина: Добавлено сообщение
Скрипт держится в радиусе ~75 от заданного персонажа и атакует указаную цель.
Код:
local group = ActorGroup.Monsters -- or ActorGroup.OtherPlayers / ActorGroup.NPCs
local fallback_name = "qweqwe" -- name to search when no party-assist target is present
while true do
local assist_ptr = game.find_party_assist_marked_character(ActorGroup.Monsters)
if assist_ptr ~= 0 then
-- Ensure we are targeting the assist-marked character
local current_target = game.get_player_target()
if current_target ~= assist_ptr then
actions.set_target(assist_ptr, true)
end
else
-- No party assist: try to find by name and move to that character
local found_ptr = game.find_character_by_name(ActorGroup.OtherPlayers, fallback_name)
if found_ptr ~= 0 then
local coord = game.get_character_coord(found_ptr)
if coord ~= nil and coord.x and coord.y and coord.z then
local player_coord = game.get_player_coord()
if player_coord ~= nil then
local dx = player_coord.x - coord.x
local dy = player_coord.y - coord.y
local dz = player_coord.z - coord.z
local distance = math.sqrt(dx * dx + dy * dy + dz * dz)
local radius = 75
if distance > radius then
-- pick a random offset inside a 50-unit radius
local angle = math.random() * math.pi * 2
local dist = math.random() * radius
local rx = coord.x + math.cos(angle) * dist
local ry = coord.y + math.sin(angle) * dist
local rz = coord.z
actions.move_player(rx, ry, rz)
end
end
end
end
end
-- If we have any target, auto-attack and use bar action (1,1)
local current_target = game.get_player_target()
if current_target ~= 0 then
actions.click_on_target(current_target)
sleep(100)
actions.use_bar_action(1, 1)
end
sleep(100) -- wait 100 ms before checking again
end
local function apply_buff(player_name, bar_index, cell_index)
local group = ActorGroup.OtherPlayers;
local characterPtr = game.find_character_by_name(group, player_name)
if characterPtr == 0 then return end
actions.use_bar_action(bar_index, cell_index, true)
sleep(500)
actions.click_on_target(characterPtr)
end
local function callback(sender, message)
print("[PRIVATE] " .. sender .. ": " .. message)
local lower = message:lower()
if lower:match("velo") or lower:match("вв") then
apply_buff(sender, 0, 0)
end
if lower:match("shield") or lower:match("щит") then
apply_buff(sender, 0, 1)
end
if lower:match("dodge") or lower:match("додж") then
apply_buff(sender, 0, 2)
end
end
actions.on_private_message(callback)
print("Listening for private messages ...")
while true do
sleep(250)
end
Последний раз редактировалось Diantro; 15.10.2025 в 20:07.
Скрипт слушает сообщения от других ботов, получает GID монстра, после чего выбирает и атакует его. Если GID не поступает, скрипт пытается найти моба, на которого указывает стрелка. Если такого моба тоже нет — персонаж начинает следовать за заданным игроком.
Код:
local name_to_assist = "0ne" -- Имя персонажа для ассиста / Player name to assist
local targetGid = nil
local function findMonsterByGid(gid)
local player_coord = game.get_player_coord()
if not player_coord then
return 0
end
local monsters = game.get_closest_characters(
ActorGroup.Monsters,
player_coord.x,
player_coord.y,
player_coord.z,
1000
)
for i = 1, #monsters do
local ptr = monsters[i].ptr
local monsterGid = game.get_character_gid(ptr)
if monsterGid and monsterGid == gid then
return ptr
end
end
return 0
end
local function moveToCharacterIfNeeded(characterPtr, radius)
local coord = game.get_character_coord(characterPtr)
if not coord or not coord.x or not coord.y or not coord.z then
return
end
local player_coord = game.get_player_coord()
if not player_coord then
return
end
local dx = player_coord.x - coord.x
local dy = player_coord.y - coord.y
local dz = player_coord.z - coord.z
local distance = math.sqrt(dx * dx + dy * dy + dz * dz)
if distance > radius then
local angle = math.random() * math.pi * 2
local dist = math.random() * radius
local rx = coord.x + math.cos(angle) * dist
local ry = coord.y + math.sin(angle) * dist
local rz = coord.z
actions.move_player(rx, ry, rz)
end
end
local function findTarget()
-- First try to find by received GID
if targetGid then
local ptr = findMonsterByGid(targetGid)
if ptr ~= 0 then
return ptr
else
targetGid = nil -- Clear if not found
end
end
-- Fallback to party assist
local assist_ptr = game.find_party_assist_marked_character(ActorGroup.Monsters)
if assist_ptr ~= 0 then
return assist_ptr
end
-- Fallback to character by name
local found_ptr = game.find_character_by_name(ActorGroup.OtherPlayers, name_to_assist)
if found_ptr ~= 0 then
moveToCharacterIfNeeded(found_ptr, 75)
end
return 0
end
local function setTargetIfNeeded(targetPtr)
if targetPtr == 0 then
return
end
local current_target = game.get_player_target()
if current_target ~= targetPtr then
actions.set_target(targetPtr, true)
end
end
local function attackCurrentTarget()
local current_target = game.get_player_target()
if current_target ~= 0 then
actions.click_on_target(current_target)
sleep(100)
actions.use_bar_action(1, 1)
end
end
events.on_bot_message(function(senderPid, message)
local gid = tonumber(message)
if gid then
if gid == 0 then
targetGid = nil
print("Target cleared by bot " .. senderPid)
else
targetGid = gid
print("Received monster GID: " .. gid .. " from bot " .. senderPid)
end
end
end)
while true do
local targetPtr = findTarget()
setTargetIfNeeded(targetPtr)
attackCurrentTarget()
sleep(100)
end
Отравляет GID выделенного монстра боту с ником "Two".
Код:
local receiver_name = "Two"
local last_target = 0
while true do
local current_target = game.get_player_target()
if current_target ~= last_target then
if current_target ~= 0 then
local gid = game.get_character_gid(current_target)
if gid then
bot.send_to_bot_by_name(receiver_name, tostring(gid))
print("Sent GID " .. gid .. " to bot " .. receiver_name)
last_target = current_target
end
else
bot.send_to_bot_by_name(receiver_name, "0")
print("Target cleared - notified bot " .. receiver_name)
last_target = 0
end
end
sleep(100)
end
– Обновил документацию в шапке.
Можете вставить её, например, в VS Code, и IDE будет показывать подсказки.
Последний раз редактировалось Diantro; 27.11.2025 в 01:29.