Lua для TFS: пишем первый скрипт на обработку событий (на примере системы квестов)
Разберём создание простой системы квестов для TFS (The Forgotten Server) на Lua — от базовой структуры до обработки событий.
Шаг 1. Структура данных квеста
Создадим таблицу с описанием квеста:
lua
quests = {
[1] = {
name = "Охота на гоблинов",
description = "Убейте 5 гоблинов и доложите старосте.",
target_mob = "goblin",
target_count = 5,
reward_exp = 1000,
reward_items = {{id = 2148, count = 10}}, -- 10 золотых монет
started = false,
progress = 0
}
}
Шаг 2. Регистрация обработчиков событий
В TFS события регистрируются через registerCreatureEvent(). Добавим обработчики:
lua
-- Регистрация событий для игрока
Player:registerEvent("QuestStart")
Player:registerEvent("QuestKill")
Player:registerEvent("QuestComplete")
Шаг 3. Скрипт квеста (quests.lua)
Поместим скрипт в папку data/scripts/.
1. Функция начала квеста:
lua
function onQuestStart(player, item, fromPosition, target, toPosition, isHotkey)
local questId = 1 -- ID квеста
local quest = quests[questId]
if not quest.started then
quest.started = true
player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Квест начат: " .. quest.name)
player:setStorageValue(questId, 1) -- сохраняем прогресс
else
player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Вы уже выполняете этот квест!")
end
return true
end
2. Обработчик убийства моба:
lua
function onKill(creature, target)
if not creature:isPlayer() then return true end
local player = creature
local targetName = target:getName():lower()
local questId = 1
local quest = quests[questId]
-- Проверяем, что игрок выполняет квест и убил нужного моба
if quest.started and quest.target_mob == targetName then
quest.progress = quest.progress + 1
player:sendTextMessage(MESSAGE_EVENT_ADVANCE,
"Прогресс квеста: " .. quest.progress .. "/" .. quest.target_count)
-- Сохраняем прогресс в хранилище игрока
player:setStorageValue(questId + 1000, quest.progress)
-- Проверяем завершение квеста
if quest.progress >= quest.target_count then
player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Квест завершён! Заберите награду у старосты.")
end
end
return true
end
3. Функция получения награды:
lua
function onQuestComplete(player, item, fromPosition, target, toPosition, isHotkey)
local questId = 1
local quest = quests[questId]
if quest.progress >= quest.target_count and quest.started then
-- Выдаём награду
player:addExperience(quest.reward_exp)
for _, reward in ipairs(quest.reward_items) do
player:addItem(reward.id, reward.count)
end
-- Сбрасываем прогресс
quest.started = false
quest.progress = 0
player:setStorageValue(questId, -1)
player:setStorageValue(questId + 1000, 0)
player:sendTextMessage(MESSAGE_EVENT_ADVANCE,
"Награда получена: " .. quest.reward_exp .. " опыта и предметы!")
else
player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Вы ещё не выполнили условия квеста!")
end
return true
end
Шаг 4. Конфигурация событий (creatureevents.xml)
Добавьте в data/creatureevents/creatureevents.xml:
xml
<event type="login" name="QuestStart" script="quests.lua"/>
<event type="kill" name="QuestKill" script="quests.lua"/>
<event type="usecontainer" name="QuestComplete" script="quests.lua"/>
Шаг 5. Интеграция с NPC
Чтобы игрок мог начать квест у NPC, отредактируйте скрипт NPC:
lua
local keywordHandler = KeywordHandler:new()
local npcHandler = NpcHandler:new(keywordHandler)
NpcSystem.parseParameters(npcHandler)
function creatureSayCallback(cid, type, msg)
if not npcHandler:isFocused(cid) then return false end
local player = Player(cid)
if msgcontains(msg, "quest") then
npcHandler:say("Хотите взять квест 'Охота на гоблинов'?", cid)
npcHandler.topic[cid] = 1
elseif npcHandler.topic[cid] == 1 then
if msgcontains(msg, "yes") then
-- Вызываем функцию начала квеста
onQuestStart(player)
npcHandler:say("Удачи в выполнении!", cid)
else
npcHandler:say("Приходите, когда будете готовы.", cid)
end
npcHandler.topic[cid] = 0
end
return true
end
npcHandler.setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback)
npcHandler.addModule(FocusModule:new())
Шаг 6. Тестирование
- Запустите сервер.
- Поговорите с NPC и возьмите квест.
- Убейте 5 гоблинов.
- Вернитесь к NPC и получите награду.
- Проверьте логи на ошибки: tail -f logs/game.log.
Дополнительные возможности
Расширение системы:
- Несколько квестов: добавьте больше записей в таблицу quests.
- Условия старта: проверяйте уровень игрока (player:getLevel()) или другие квесты.
- Промежуточные цели: сохраняйте прогресс для каждого этапа квеста.
- Таймеры: используйте addEvent() для ограниченных по времени квестов.
- Визуальные эффекты: добавляйте анимации при получении награды (player:sendMagicEffect(CONST_EFFECT_EXPLOSION)).
Отладка:
- Используйте print() для вывода отладочной информации в консоль сервера.
- Проверяйте значения storage через player:getStorageValue().
- Логируйте ошибки в файл: io.write("Ошибка квеста: " .. err .. "\n").
Чек‑лист проверки
- Квест запускается через NPC.
- Прогресс убийства мобов сохраняется.
- Награда выдаётся при выполнении условий.
- Данные квеста сохраняются между перезагрузками сервера.
- Ошибки не выводятся в логах.
Устранение распространённых проблем
- «Квест не начинается»: проверьте регистрацию события в creatureevents.xml.
- «Прогресс не сохраняется»: убедитесь, что setStorageValue() вызывается с уникальными ID.
- «Награда не выдаётся»: проверьте условие if quest.progress >= quest.target_count.
- «Ошибки в скрипте»: проверьте синтаксис Lua и соответствие имён функций в XML.
Теперь у вас есть основа для создания сложных квестовых систем в TFS. Если хотите, могу помочь расширить функционал или разобрать другой тип событий!