mirror of
https://github.com/opentibiabr/canary
synced 2026-08-16 06:26:09 -04:00
This commit standardizes NPC configuration across multiple Lua files by adding explicit profession and speechBubble properties to each affected NPC config. The goal is to make each NPC role clear in the script itself and keep speech bubble behavior consistent between the server NPC configuration and the client presentation layer. NPCs now explicitly declare whether they are normal NPCs or trader NPCs, instead of relying on implicit or inconsistent defaults. The profession value was added under npcConfig flags for all affected NPCs. Each NPC now uses either normal or trader depending on its expected role. This makes the NPC intent easier to read and helps avoid ambiguity when future scripts or client side behavior depend on the configured profession. The speechBubble value was also added to each NPC config. Normal NPCs use SPEECHBUBBLE_NORMAL and trader NPCs use SPEECHBUBBLE_TRADE. This keeps the in game dialogue bubble aligned with the NPC role and improves consistency in how NPCs are displayed to players. Main changes included in this commit • Adds explicit profession configuration to affected NPC Lua files • Uses normal for regular NPCs • Uses trader for shop and trade related NPCs • Adds explicit speechBubble configuration to affected NPC Lua files • Uses SPEECHBUBBLE_NORMAL for normal NPC dialogue presentation • Uses SPEECHBUBBLE_TRADE for trader NPC dialogue presentation • Keeps NPC role information visible directly in each NPC config • Reduces reliance on implicit default behavior • Improves consistency between NPC server configuration and client side speech bubble rendering • Aligns server NPC configs with the related client support added in tibia client PR 18 • Preserves existing NPC behavior while making the configuration more explicit This is a configuration standardization change. It does not rework NPC logic or change the data access flow. The intended behavior remains the same, but the role and speech bubble metadata are now declared consistently so both server and client can interpret NPC presentation more reliably.
186 lines
3.6 KiB
Lua
186 lines
3.6 KiB
Lua
NpcDialog = NpcDialog or {}
|
|
NpcDialog._stateByPlayerId = NpcDialog._stateByPlayerId or {}
|
|
NpcDialog.ValidProfessions = NpcDialog.ValidProfessions or {
|
|
normal = true,
|
|
sailor = true,
|
|
banker = true,
|
|
king = true,
|
|
queen = true,
|
|
trader = true,
|
|
hireling = true,
|
|
}
|
|
|
|
local BUTTON = {
|
|
Trade = 0,
|
|
TradePotion = 1,
|
|
TradeEquipment = 2,
|
|
Sail = 3,
|
|
DepositAll = 4,
|
|
Withdraw = 5,
|
|
Balance = 6,
|
|
Yes = 7,
|
|
No = 8,
|
|
Bye = 9,
|
|
}
|
|
|
|
local function addAction(actions, buttonId, keyword)
|
|
actions[#actions + 1] = {
|
|
buttonId = buttonId,
|
|
keyword = keyword,
|
|
}
|
|
end
|
|
|
|
local function hasNpcId(list, npcId)
|
|
for _, id in ipairs(list) do
|
|
if id == npcId then
|
|
return true
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
|
|
function NpcDialog._getList(player)
|
|
local playerId = player and player:getId()
|
|
if not playerId then
|
|
return nil
|
|
end
|
|
|
|
local list = NpcDialog._stateByPlayerId[playerId]
|
|
if not list then
|
|
list = {}
|
|
NpcDialog._stateByPlayerId[playerId] = list
|
|
end
|
|
|
|
return list
|
|
end
|
|
|
|
function NpcDialog.add(player, npcId)
|
|
if not player or not npcId or npcId == 0 then
|
|
return
|
|
end
|
|
|
|
local list = NpcDialog._getList(player)
|
|
if not list or hasNpcId(list, npcId) then
|
|
return
|
|
end
|
|
|
|
list[#list + 1] = npcId
|
|
end
|
|
|
|
function NpcDialog.remove(player, npcId)
|
|
if not player or not npcId or npcId == 0 then
|
|
return
|
|
end
|
|
|
|
local list = NpcDialog._getList(player)
|
|
if not list or #list == 0 then
|
|
return
|
|
end
|
|
|
|
for i = #list, 1, -1 do
|
|
if list[i] == npcId then
|
|
table.remove(list, i)
|
|
end
|
|
end
|
|
end
|
|
|
|
function NpcDialog.clear(player)
|
|
if not player then
|
|
return
|
|
end
|
|
|
|
local playerId = player:getId()
|
|
if not playerId then
|
|
return
|
|
end
|
|
|
|
NpcDialog._stateByPlayerId[playerId] = {}
|
|
end
|
|
|
|
function NpcDialog.buildActions(player, npc)
|
|
local actions = {}
|
|
if not player or not npc then
|
|
return actions
|
|
end
|
|
|
|
addAction(actions, BUTTON.Yes, "yes")
|
|
addAction(actions, BUTTON.No, "no")
|
|
addAction(actions, BUTTON.Bye, "bye")
|
|
|
|
if npc:isMerchant() then
|
|
addAction(actions, BUTTON.Trade, "trade")
|
|
end
|
|
|
|
local profession = "normal"
|
|
if NpcDialogProfessionByName then
|
|
profession = NpcDialogProfessionByName[npc:getName():lower()] or profession
|
|
end
|
|
|
|
if profession == "sailor" then
|
|
addAction(actions, BUTTON.Sail, "sail")
|
|
end
|
|
|
|
if profession == "banker" then
|
|
addAction(actions, BUTTON.DepositAll, "deposit all")
|
|
addAction(actions, BUTTON.Withdraw, "withdraw")
|
|
addAction(actions, BUTTON.Balance, "balance")
|
|
end
|
|
|
|
if profession == "hireling" or npc:getSpeechBubble() == SPEECHBUBBLE_HIRELING then
|
|
local skills = player:kv():scoped("hireling-skills")
|
|
if skills:get("banker") then
|
|
addAction(actions, BUTTON.DepositAll, "deposit all")
|
|
addAction(actions, BUTTON.Withdraw, "withdraw")
|
|
addAction(actions, BUTTON.Balance, "balance")
|
|
end
|
|
if skills:get("trader") then
|
|
addAction(actions, BUTTON.TradePotion, "potions")
|
|
addAction(actions, BUTTON.TradeEquipment, "equipment")
|
|
end
|
|
end
|
|
|
|
return actions
|
|
end
|
|
|
|
function NpcDialog.sendWindow(player)
|
|
if not player then
|
|
return
|
|
end
|
|
|
|
local npcIds = NpcDialog._getList(player) or {}
|
|
|
|
local msg = NetworkMessage()
|
|
msg:addByte(0x1C)
|
|
msg:addByte(#npcIds > 0 and 0x00 or 0x01)
|
|
|
|
if #npcIds <= 0 then
|
|
msg:sendToPlayer(player)
|
|
return
|
|
end
|
|
|
|
msg:addByte(#npcIds)
|
|
for _, npcId in ipairs(npcIds) do
|
|
msg:addU32(npcId)
|
|
end
|
|
|
|
local actions = {}
|
|
local lastNpc = Npc(npcIds[#npcIds])
|
|
if not lastNpc then
|
|
NpcDialog.clear(player)
|
|
msg = NetworkMessage()
|
|
msg:addByte(0x1C)
|
|
msg:addByte(0x01)
|
|
msg:sendToPlayer(player)
|
|
return
|
|
end
|
|
|
|
actions = NpcDialog.buildActions(player, lastNpc)
|
|
|
|
msg:addByte(#actions)
|
|
for _, action in ipairs(actions) do
|
|
msg:addByte(action.buttonId)
|
|
msg:addString(action.keyword)
|
|
end
|
|
|
|
msg:sendToPlayer(player)
|
|
end
|