znoteshop_globalevent.lua

main 105 lines · 3.9 KB Raw
Alex Alex Commit Initial commit 01/10/2026 09:20
1-- Znote Shop auto-delivery for Canary (opentibiabr) / otservbr-global.
2-- Every 30 seconds it hands pending item / outfit / mount / house orders to the
3-- buyer if they are online AND standing in a protection zone. Players can still
4-- force delivery with !shop (see znoteshop_talkaction.lua) - keep both.
5
6local znoteShopGlobal = GlobalEvent("ZnoteShopDelivery")
7
8function znoteShopGlobal.onThink(interval)
9 local orders = db.storeQuery([[
10 SELECT
11 MIN(`po`.`player_id`) AS `player_id`,
12 `shop`.`id`,
13 `shop`.`type`,
14 `shop`.`itemid`,
15 `shop`.`count`
16 FROM `players_online` AS `po`
17 INNER JOIN `players` AS `p` ON `po`.`player_id` = `p`.`id`
18 INNER JOIN `znote_shop_orders` AS `shop` ON `p`.`account_id` = `shop`.`account_id`
19 WHERE `shop`.`type` IN (1, 5, 6, 7)
20 GROUP BY `shop`.`id`
21 ]])
22 if orders == false then
23 return true
24 end
25
26 repeat
27 local playerId = result.getNumber(orders, "player_id")
28 local oId = result.getNumber(orders, "id")
29 local oType = result.getNumber(orders, "type")
30 local oItemId = result.getNumber(orders, "itemid")
31 local oCount = result.getNumber(orders, "count")
32
33 local player = Player(playerId)
34 if player then
35 local tile = Tile(player:getPosition())
36 if tile and tile:hasFlag(TILESTATE_PROTECTIONZONE) then
37
38 if oType == 1 then
39 local itemType = ItemType(oItemId)
40 local needSlots = itemType:isStackable() and (math.floor(oCount / 100) + 1) or oCount
41 if player:getFreeCapacity() < itemType:getWeight(oCount) then
42 player:sendTextMessage(MESSAGE_FAILURE, "You have a pending shop order but not enough capacity.")
43 elseif player:getFreeBackpackSlots() < needSlots then
44 player:sendTextMessage(MESSAGE_FAILURE, ("You have a pending shop order - free %d backpack slots."):format(needSlots))
45 else
46 db.query("DELETE FROM `znote_shop_orders` WHERE `id` = " .. oId .. ";")
47 player:addItem(oItemId, oCount)
48 player:sendTextMessage(MESSAGE_EVENT_ADVANCE, ("You received %dx %s."):format(oCount, itemType:getName()))
49 end
50
51 elseif oType == 5 then
52 local looks = {}
53 local packed = oItemId
54 if packed > 1000 then
55 local male = math.floor(packed / 1000)
56 table.insert(looks, male)
57 packed = packed - (male * 1000)
58 end
59 table.insert(looks, packed)
60 for _, lookType in ipairs(looks) do
61 if not player:hasOutfit(lookType, oCount) then
62 db.query("DELETE FROM `znote_shop_orders` WHERE `id` = " .. oId .. ";")
63 player:addOutfit(lookType)
64 player:addOutfitAddon(lookType, oCount)
65 player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You received a new outfit.")
66 else
67 player:sendTextMessage(MESSAGE_FAILURE, "You already own a purchased outfit and addon.")
68 end
69 end
70
71 elseif oType == 6 then
72 if not player:hasMount(oItemId) then
73 db.query("DELETE FROM `znote_shop_orders` WHERE `id` = " .. oId .. ";")
74 player:addMount(oItemId)
75 player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You received a new mount.")
76 else
77 player:sendTextMessage(MESSAGE_FAILURE, "You already own a purchased mount.")
78 end
79
80 elseif oType == 7 then
81 local house = House(oItemId)
82 local buyer = db.storeQuery("SELECT `name` FROM `players` WHERE `id` = " .. oCount .. " LIMIT 1;")
83 if buyer ~= false then
84 local buyerName = result.getString(buyer, "name")
85 result.free(buyer)
86 if house then
87 db.query("DELETE FROM `znote_shop_orders` WHERE `id` = " .. oId .. ";")
88 house:setHouseOwner(oCount, true)
89 player:sendTextMessage(MESSAGE_EVENT_ADVANCE, ("House %s now belongs to %s."):format(house:getName(), buyerName))
90 end
91 end
92 end
93
94 else
95 player:sendTextMessage(MESSAGE_STATUS, "You have a pending shop order - stand in a protection zone to receive it.")
96 end
97 end
98 until not result.next(orders)
99 result.free(orders)
100 return true
101end
102
103znoteShopGlobal:interval(30000)
104znoteShopGlobal:register()
105
Top