Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
37f0883
Add batch update and reward chest improvements
dudantas Sep 29, 2025
6816cb9
Refactor NPC loot selling logic for efficiency
dudantas Oct 20, 2025
a3a6231
Add backpack and loot pouch access to Player Lua API
dudantas Oct 20, 2025
4ff4cac
Notify player on sale letter delivery failure
dudantas Oct 20, 2025
492f69d
Fix typo in variable name in internalCollectManagedItems
dudantas Oct 20, 2025
1f926fd
Merge branch 'main' into dudantas/implement-player-batch-updates
dudantas Oct 20, 2025
8024f6f
Refactor tests to use Google Test framework
dudantas Oct 21, 2025
d02388f
Code format - (CMake-format)
github-actions[bot] Oct 21, 2025
fe1d290
Code format - (Clang-format)
github-actions[bot] Oct 21, 2025
4dad28d
Apply suggestions from code review
dudantas Oct 21, 2025
db61b3a
Replace std::find with std::ranges::find in loot logic
dudantas Oct 21, 2025
3e006d8
Call updateState only when not batching in sendBatchUpdateContainer
dudantas Oct 21, 2025
d70797e
Merge branch 'main' into dudantas/implement-player-batch-updates
dudantas Jan 13, 2026
f5fdcd6
Refactor BatchUpdate to use shared_ptr and improve safety
dudantas Jan 13, 2026
e3c2304
Fix container cache updates and improve batch update tests
dudantas Jan 13, 2026
8320dcc
Remove redundant item weight update in addItemBack
dudantas Jan 13, 2026
06df817
Merge branch 'main' into dudantas/implement-player-batch-updates
dudantas Jan 13, 2026
8688375
Add tests for batch update deduplication and player storage
dudantas Jan 13, 2026
51fd09c
Merge branch 'main' into dudantas/implement-player-batch-updates
dudantas Jan 16, 2026
e2d70e5
Refactor batch update and NPC item selling logic
dudantas Jan 16, 2026
c22690c
Fix NPC sell logic and improve container safety checks
dudantas Jan 17, 2026
104c6a8
Refactor NPC sell logic and improve batch update handling
dudantas Jan 17, 2026
b306c44
Improve error handling for custom currency sales
dudantas Jan 17, 2026
34ea1e7
Merge branch 'main' into dudantas/implement-player-batch-updates
dudantas Jan 20, 2026
abc2cf7
fix: sonar changes
dudantas Jan 20, 2026
5fd9501
Update cmake-lint.yml
dudantas Jan 20, 2026
45cc00d
fix: compilation on linux
dudantas Jan 20, 2026
1f60e5d
fix: review
dudantas Jan 22, 2026
096c8c3
fix: review and build
dudantas Jan 22, 2026
52cb4bb
Merge branch 'main' into dudantas/implement-player-batch-updates
dudantas Jan 27, 2026
9f29a8f
improve: add missing tests and fix others
dudantas Jan 27, 2026
ae57cff
fix: add missing functions
dudantas Jan 27, 2026
92471a9
Code format - (Clang-format)
github-actions[bot] Jan 27, 2026
8ec23f2
Ensure container cache stays consistent
dudantas Jan 27, 2026
bc0e2fa
Collect items before removing all
dudantas Jan 27, 2026
824cae9
fix: sonar
dudantas Jan 27, 2026
68c6c19
Code format - (Clang-format)
github-actions[bot] Jan 27, 2026
86117ff
fix: sonar
dudantas Jan 27, 2026
e60cca4
Ensure equip hooks fire during batching
dudantas Jan 27, 2026
442c0cb
Ensure loot sale proceeds are atomic
dudantas Jan 27, 2026
07ec9a4
Fix loot sale context labels
dudantas Jan 27, 2026
12771bf
Update npc.cpp
dudantas Jan 27, 2026
b641d3a
Update src/creatures/npcs/npc.cpp
dudantas Jan 27, 2026
7c7d3c4
Code format - (Clang-format)
github-actions[bot] Jan 27, 2026
f43597a
Update src/creatures/npcs/npc.cpp
dudantas Jan 27, 2026
299cf0f
Code format - (Clang-format)
github-actions[bot] Jan 27, 2026
50f5e78
Merge branch 'main' into dudantas/implement-player-batch-updates
dudantas Jan 27, 2026
817ee12
Update src/creatures/npcs/npc.cpp
dudantas Jan 27, 2026
32c2b38
Update src/creatures/npcs/npc.cpp
dudantas Jan 27, 2026
6a3c443
Code format - (Clang-format)
github-actions[bot] Jan 27, 2026
fa64879
Fix type mismatches for cost calculations and cleanup guard
dudantas Jan 29, 2026
1a47fd7
Merge branch 'main' into dudantas/implement-player-batch-updates
dudantas Jan 30, 2026
436313e
Move balance_decrease metric to successful purchase
dudantas Jan 30, 2026
5d2f3d5
Merge branch 'main' into dudantas/implement-player-batch-updates
dudantas Mar 17, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions data-canary/npc/the_lootmonger.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
local internalNpcName = "The Lootmonger"
local npcType = Game.createNpcType(internalNpcName)
local npcConfig = {}

npcConfig.name = internalNpcName
npcConfig.description = internalNpcName

npcConfig.health = 100
npcConfig.maxHealth = npcConfig.health
npcConfig.walkInterval = 2000
npcConfig.walkRadius = 2

npcConfig.outfit = {
lookType = 1575,
lookHead = 96,
lookBody = 101,
lookLegs = 120,
lookFeet = 120,
lookAddons = 2,
}

npcConfig.flags = {
floorchange = false,
}

local keywordHandler = KeywordHandler:new()
local npcHandler = NpcHandler:new(keywordHandler)

npcType.onThink = function(npc, interval)
npcHandler:onThink(npc, interval)
end

npcType.onAppear = function(npc, creature)
npcHandler:onAppear(npc, creature)
end

npcType.onDisappear = function(npc, creature)
npcHandler:onDisappear(npc, creature)
end

npcType.onMove = function(npc, creature, fromPosition, toPosition)
npcHandler:onMove(npc, creature, fromPosition, toPosition)
end

npcType.onSay = function(npc, creature, type, message)
npcHandler:onSay(npc, creature, type, message)
end

npcType.onCloseChannel = function(npc, creature)
npcHandler:onCloseChannel(npc, creature)
end

npcHandler:addModule(FocusModule:new(), npcConfig.name, true, true, true)

npcConfig.shop = LootShopConfig

local function creatureSayCallback(npc, player, type, message)
if not npcHandler:checkInteraction(npc, player) then
return false
end
local categoryTable = LootShopConfigTable[message:lower()]
if MsgContains(message, "shop options") then
npcHandler:say("I sell a selection of " .. GetFormattedShopCategoryNames(LootShopConfigTable), npc, player)
elseif categoryTable then
local remainingCategories = npc:getRemainingShopCategories(message:lower(), LootShopConfigTable)
npcHandler:say("Of course, just browse through my wares. You can also look at " .. remainingCategories .. ".", npc, player)
npc:openShopWindowTable(player, categoryTable)
end
return true
end

npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback)
npcHandler:setMessage(MESSAGE_GREET, "Ah, a customer! Be greeted, |PLAYERNAME|! I buy all kinds of loot, would you like a {trade}? I can also show you my {shop options}.")
npcHandler:setMessage(MESSAGE_SENDTRADE, "Ah, a customer! Be greeted, |PLAYERNAME|! I buy all kinds of loot, would you look at " .. GetFormattedShopCategoryNames(LootShopConfigTable) .. ".")

-- On buy npc shop message
npcType.onBuyItem = function(npc, player, itemId, subType, amount, ignore, inBackpacks, totalCost)
npc:sellItem(player, itemId, amount, subType, 0, ignore, inBackpacks)
end
-- On sell npc shop message
npcType.onSellItem = function(npc, player, itemId, subtype, amount, ignore, name, totalCost)
player:sendTextMessage(MESSAGE_TRADE, string.format("Sold %ix %s for %i gold.", amount, name, totalCost))
end
-- On check npc shop message (look item)
npcType.onCheckItem = function(npc, player, clientId, subType) end

npcType:register(npcConfig)
2 changes: 1 addition & 1 deletion data/scripts/eventcallbacks/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ Some event callbacks are expected to return a enum value, in this case, the enum
Here is an example of a ReturnValue event callback:

```lua
local callback = EventCallback()
local callback = EventCallback("CreatureOnAreaCombat")

function callback.creatureOnAreaCombat(creature, tile, isAggressive)
-- if the creature is not aggressive, stop the execution of the C++ function
Expand Down
56 changes: 56 additions & 0 deletions data/scripts/talkactions/god/add_item_to_rewardchest.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
local addReward = TalkAction("/addreward")

function addReward.onSay(player, words, param)
local args = param:split(",")
local itemInput = (args[1] or ""):trim()
local amount = tonumber(args[2]) or 1
local targetName = args[3] and args[3]:trim() or player:getName()

if itemInput == "" then
player:sendCancelMessage("Usage: /addreward item_name_or_id, amount[, target_player]")
return false
end

-- resolve target
local target = Player(targetName)
if not target then
player:sendCancelMessage("Target player not found.")
return false
end

-- resolve item
local it = ItemType(itemInput)
if it:getId() == 0 then
it = ItemType(tonumber(itemInput) or -1)
end
if it:getId() == 0 then
player:sendCancelMessage("Invalid item name or ID.")
return false
end

if amount < 1 then
player:sendCancelMessage("Invalid amount.")
return false
end

-- create/get the reward chest with a unique timestamp
local timestamp = systemTime()
local rewardBag = target:getReward(timestamp, true)

-- **this** will split your `amount` across as many
-- containers as necessary and return the total added
local added = target:addItemBatchToPaginedContainer(rewardBag, it:getId(), amount)
if added > 0 then
player:sendTextMessage(MESSAGE_EVENT_ADVANCE, string.format("Added %d x %s to %s's reward chest(s).", added, it:getName(), target:getName()))
target:sendTextMessage(MESSAGE_EVENT_ADVANCE, string.format("You received %d x %s in your reward chest(s).", added, it:getName()))
target:getPosition():sendMagicEffect(CONST_ME_MAGIC_GREEN)
else
player:sendCancelMessage("Could not add item to reward chest.")
end

return false
end

addReward:separator(" ")
addReward:groupType("god")
addReward:register()
Loading
Loading