diff --git a/LUA/TFS_10/creaturescript firstitems/firstitems.lua b/LUA/TFS_10/creaturescript firstitems/firstitems.lua deleted file mode 100644 index e4f7c3b..0000000 --- a/LUA/TFS_10/creaturescript firstitems/firstitems.lua +++ /dev/null @@ -1,70 +0,0 @@ --- With Rookgaard - ---[[ -local firstItems = {2050, 2382} -- torch and club - -function onLogin(player) - if player:getLastLoginSaved() <= 0 then - for i = 1, #firstItems do - player:addItem(firstItems[i], 1) - end - player:addItem(player:getSex() == 0 and 2651 or 2650, 1) -- coat - player:addItem(ITEM_BAG, 1) - player:addItem(2674, 1) -- red apple - end - return true -end -]]-- - --- Without Rookgaard -local config = { - [1] = { -- Sorcerer - -- equipment: spellbook, wand of vortex, magician's robe, mage hat, studded legs, leather boots, scarf - items = {{2175, 1}, {2190, 1}, {8819, 1}, {8820, 1}, {2468, 1}, {2643, 1}, {2661, 1}}, - -- container: rope, shovel, mana potion - container = {{2120, 1}, {2554, 1}, {7620, 1}} - }, - [2] = { -- Druid - -- equipment: spellbook, snakebite rod, magician's robe, mage hat, studded legs, leather boots, scarf - items = {{2175, 1}, {2182, 1}, {8819, 1}, {8820, 1}, {2468, 1}, {2643, 1}, {2661, 1}}, - -- container: rope, shovel, mana potion - container = {{2120, 1}, {2554, 1}, {7620, 1}} - }, - [3] = { -- Paladin - -- equipment: dwarven shield, 5 spear, ranger's cloak, ranger legs, scarf, legion helmet - items = {{2525, 1}, {2389, 5}, {2660, 1}, {8923, 1}, {2643, 1}, {2661, 1}, {2480, 1}}, - -- container: rope, shovel, health potion, bow, 50 arrow - container = {{2120, 1}, {2554, 1}, {7618, 1}, {2456, 1}, {2544, 50}} - }, - [4] = { -- Knight - -- equipment: dwarven shield, steel axe, brass armor, brass helmet, brass legs, scarf - items = {{2525, 1}, {8601, 1}, {2465, 1}, {2460, 1}, {2478, 1}, {2643, 1}, {2661, 1}}, - -- container jagged sword, daramanian mace, rope, shovel, health potion - container = {{8602, 1}, {2439, 1}, {2120, 1}, {2554, 1}, {7618, 1}} - } -} - -function onLogin(player) - local targetVocation = config[player:getVocation():getId()] - if not targetVocation then - return true - end - - if player:getLastLoginSaved() ~= 0 then - return true - end - - for i = 1, #targetVocation.items do - player:addItem(targetVocation.items[i][1], targetVocation.items[i][2]) - end - - local backpack = player:addItem(1988) - if not backpack then - return true - end - - for i = 1, #targetVocation.container do - backpack:addItem(targetVocation.container[i][1], targetVocation.container[i][2]) - end - return true -end diff --git a/LUA/TFS_10/creaturescript sync outfits/Installation Instructions.txt b/LUA/TFS_10/creaturescript sync outfits/Installation Instructions.txt deleted file mode 100644 index 7113085..0000000 --- a/LUA/TFS_10/creaturescript sync outfits/Installation Instructions.txt +++ /dev/null @@ -1,7 +0,0 @@ -1. Add below line to XML file: data/creaturescripts/creaturescripts.xml - - -2. Register event in login.lua: data/creaturescripts/scripts/login.lua -player:registerEvent("znote_syncoutfits") - -3. Place Lua file syncoutfit.lua in folder: data/creaturescripts/scripts/ diff --git a/LUA/TFS_10/creaturescript sync outfits/syncoutfit.lua b/LUA/TFS_10/creaturescript sync outfits/syncoutfit.lua deleted file mode 100644 index ada481d..0000000 --- a/LUA/TFS_10/creaturescript sync outfits/syncoutfit.lua +++ /dev/null @@ -1,39 +0,0 @@ --- Sync outfits that player own with Znote AAC --- So its possible to see which full sets player --- has in characterprofile.php - -znote_outfit_list = { - { -- Female (girl) outfits - 136,137,138,139,140,141,142,147,148, - 149,150,155,156,157,158,252,269,270, - 279,288,324,329,336,366,431,433,464, - 466,471,513,514,542,575,578,618,620, - 632,635,636,664,666,683,694,696,698, - 724,732,745,749,759,845,852,874,885, - 900 - }, - { -- Male (boy) outfits - 128,129,130,131,132,133,134,143,144, - 145,146,151,152,153,154,251,268,273, - 278,289,325,328,335,367,430,432,463, - 465,472,512,516,541,574,577,610,619, - 633,634,637,665,667,684,695,697,699, - 725,733,746,750,760,846,853,873,884, - 899 - } -} - -function onLogin(player) - -- storage_value + 1000 storages (highest outfit id) must not be used in other script. - -- Must be identical to Znote AAC config.php: $config['EQ_shower'] -> storage_value - local storage_value = 10000 - -- Loop through outfits - for _, outfit in pairs(znote_outfit_list[player:getSex()+1]) do - if player:hasOutfit(outfit,3) then - if player:getStorageValue(storage_value + outfit) ~= 3 then - player:setStorageValue(storage_value + outfit, 3) - end - end - end - return true -end diff --git a/LUA/TFS_02/creaturescript firstitems/Installation Instructions.txt b/Lua/TFS_02/creaturescript firstitems/Installation Instructions.txt similarity index 100% rename from LUA/TFS_02/creaturescript firstitems/Installation Instructions.txt rename to Lua/TFS_02/creaturescript firstitems/Installation Instructions.txt diff --git a/LUA/TFS_02/creaturescript firstitems/firstitems.lua b/Lua/TFS_02/creaturescript firstitems/firstitems.lua similarity index 100% rename from LUA/TFS_02/creaturescript firstitems/firstitems.lua rename to Lua/TFS_02/creaturescript firstitems/firstitems.lua diff --git a/LUA/TFS_02/talkaction shopsystem/talkaction XML.txt b/Lua/TFS_02/talkaction shopsystem/talkaction XML.txt similarity index 100% rename from LUA/TFS_02/talkaction shopsystem/talkaction XML.txt rename to Lua/TFS_02/talkaction shopsystem/talkaction XML.txt diff --git a/LUA/TFS_02/talkaction shopsystem/znoteshop.lua b/Lua/TFS_02/talkaction shopsystem/znoteshop.lua similarity index 100% rename from LUA/TFS_02/talkaction shopsystem/znoteshop.lua rename to Lua/TFS_02/talkaction shopsystem/znoteshop.lua diff --git a/LUA/TFS_03/creaturescript firstitems/Installation Instructions.txt b/Lua/TFS_03/creaturescript firstitems/Installation Instructions.txt similarity index 100% rename from LUA/TFS_03/creaturescript firstitems/Installation Instructions.txt rename to Lua/TFS_03/creaturescript firstitems/Installation Instructions.txt diff --git a/LUA/TFS_03/creaturescript firstitems/firstitems.lua b/Lua/TFS_03/creaturescript firstitems/firstitems.lua similarity index 100% rename from LUA/TFS_03/creaturescript firstitems/firstitems.lua rename to Lua/TFS_03/creaturescript firstitems/firstitems.lua diff --git a/LUA/TFS_03/creaturescript sync outfits/Installation Instructions.txt b/Lua/TFS_03/creaturescript sync outfits/Installation Instructions.txt similarity index 100% rename from LUA/TFS_03/creaturescript sync outfits/Installation Instructions.txt rename to Lua/TFS_03/creaturescript sync outfits/Installation Instructions.txt diff --git a/LUA/TFS_03/creaturescript sync outfits/syncoutfit.lua b/Lua/TFS_03/creaturescript sync outfits/syncoutfit.lua similarity index 100% rename from LUA/TFS_03/creaturescript sync outfits/syncoutfit.lua rename to Lua/TFS_03/creaturescript sync outfits/syncoutfit.lua diff --git a/LUA/TFS_03/talkaction shopsystem/Alternatives/znoteshop.lua b/Lua/TFS_03/talkaction shopsystem/Alternatives/znoteshop.lua similarity index 100% rename from LUA/TFS_03/talkaction shopsystem/Alternatives/znoteshop.lua rename to Lua/TFS_03/talkaction shopsystem/Alternatives/znoteshop.lua diff --git a/LUA/TFS_03/talkaction shopsystem/talkaction XML.txt b/Lua/TFS_03/talkaction shopsystem/talkaction XML.txt similarity index 100% rename from LUA/TFS_03/talkaction shopsystem/talkaction XML.txt rename to Lua/TFS_03/talkaction shopsystem/talkaction XML.txt diff --git a/LUA/TFS_03/talkaction shopsystem/znoteshop.lua b/Lua/TFS_03/talkaction shopsystem/znoteshop.lua similarity index 100% rename from LUA/TFS_03/talkaction shopsystem/znoteshop.lua rename to Lua/TFS_03/talkaction shopsystem/znoteshop.lua diff --git a/LUA/TFS_10/creaturescript firstitems/Installation Instructions.txt b/Lua/TFS_10/creaturescript firstitems/Installation Instructions.txt similarity index 100% rename from LUA/TFS_10/creaturescript firstitems/Installation Instructions.txt rename to Lua/TFS_10/creaturescript firstitems/Installation Instructions.txt diff --git a/Lua/TFS_10/creaturescript firstitems/firstitems.lua b/Lua/TFS_10/creaturescript firstitems/firstitems.lua new file mode 100644 index 0000000..6721392 --- /dev/null +++ b/Lua/TFS_10/creaturescript firstitems/firstitems.lua @@ -0,0 +1,114 @@ +-- With Rookgaard + +--[[ +local firstItems = {2050, 2382} -- torch and club + +function onLogin(player) + if player:getLastLoginSaved() <= 0 then + for i = 1, #firstItems do + player:addItem(firstItems[i], 1) + end + player:addItem(player:getSex() == 0 and 2651 or 2650, 1) -- coat + player:addItem(ITEM_BAG, 1) + player:addItem(2674, 1) -- red apple + end + return true +end +]]-- + +-- Without Rookgaard +local config = { + [1] = { -- Sorcerer + items = { + {2175, 1}, -- spellbook + {2190, 1}, -- wand of vortex + {8819, 1}, -- magician's robe + {8820, 1}, -- mage hat + {2468, 1}, -- studded legs + {2643, 1}, -- leather boots + {2661, 1} -- scarf + }, + container = { + {2120, 1}, -- rope + {2554, 1}, -- shovel + {7620, 1} -- mana potion + } + }, + [2] = { -- Druid + items = { + {2175, 1}, -- spellbook + {2182, 1}, -- snakebite rod + {8819, 1}, -- magician's robe + {8820, 1}, -- mage hat + {2468, 1}, -- studded legs + {2643, 1}, -- leather boots + {2661, 1} -- scarf + }, + container = { + {2120, 1}, -- rope + {2554, 1}, -- shovel + {7620, 1} -- mana potion + } + }, + [3] = { -- Paladin + items = { + {2525, 1}, -- dwarven shield + {2389, 5}, -- 5 spears + {2660, 1}, -- ranger's cloak + {8923, 1}, -- ranger legs + {2643, 1}, -- leather boots + {2661, 1}, -- scarf + {2480, 1} -- legion helmet + }, + container = { + {2120, 1}, -- rope + {2554, 1}, -- shovel + {7618, 1}, -- health potion + {2456, 1}, -- bow + {2544, 50} -- 50 arrows + } + }, + [4] = { -- Knight + items = { + {2525, 1}, -- dwarven shield + {8601, 1}, -- steel axe + {2465, 1}, -- brass armor + {2460, 1}, -- brass helmet + {2478, 1}, -- brass legs + {2643, 1}, -- leather boots + {2661, 1} -- scarf + }, + container = { + {8602, 1}, -- jagged sword + {2439, 1}, -- daramanian mace + {2120, 1}, -- rope + {2554, 1}, -- shovel + {7618, 1} -- health potion + } + } +} + +function onLogin(player) + local targetVocation = config[player:getVocation():getId()] + if not targetVocation then + return true + end + + if player:getLastLoginSaved() ~= 0 then + return true + end + + for i = 1, #targetVocation.items do + player:addItem(targetVocation.items[i][1], targetVocation.items[i][2]) + end + + local backpack = player:addItem(1988) + if not backpack then + return true + end + + for i = 1, #targetVocation.container do + backpack:addItem(targetVocation.container[i][1], targetVocation.container[i][2]) + end + return true +end diff --git a/Lua/TFS_10/creaturescript playerdeath/Installation Instructions.txt b/Lua/TFS_10/creaturescript playerdeath/Installation Instructions.txt new file mode 100644 index 0000000..c5ad6e9 --- /dev/null +++ b/Lua/TFS_10/creaturescript playerdeath/Installation Instructions.txt @@ -0,0 +1,3 @@ +Step 1: Replace the one that comes with tfs with this one + +Step 2: Restart OT server, and it should work. :) diff --git a/LUA/TFS_10/creaturescript playerdeath/playerdeath.lua b/Lua/TFS_10/creaturescript playerdeath/playerdeath.lua similarity index 98% rename from LUA/TFS_10/creaturescript playerdeath/playerdeath.lua rename to Lua/TFS_10/creaturescript playerdeath/playerdeath.lua index b61334f..2fd63fa 100644 --- a/LUA/TFS_10/creaturescript playerdeath/playerdeath.lua +++ b/Lua/TFS_10/creaturescript playerdeath/playerdeath.lua @@ -78,7 +78,7 @@ function onDeath(player, corpse, killer, mostDamageKiller, lastHitUnjustified, m end local playerGuid = player:getGuid() - db.query("INSERT INTO `player_deaths` (`player_id`, `time`, `level`, `killed_by`, `is_player`, `mostdamage_by`, `mostdamage_is_player`, `unjustified`, `mostdamage_unjustified`) VALUES (" .. playerGuid .. ", " .. os.time() .. ", " .. player:getLevel() .. ", " .. db.escapeString(killerName) .. ", " .. byPlayer .. ", " .. db.escapeString(mostDamageName) .. ", " .. byPlayerMostDamage .. ", " .. (unjustified and 1 or 0) .. ", " .. (mostDamage_unjustified and 1 or 0) .. ")") + db.query("INSERT INTO `player_deaths` (`player_id`, `time`, `level`, `killed_by`, `is_player`, `mostdamage_by`, `mostdamage_is_player`, `unjustified`, `mostdamage_unjustified`) VALUES (" .. playerGuid .. ", " .. os.time() .. ", " .. player:getLevel() .. ", " .. db.escapeString(killerName) .. ", " .. byPlayer .. ", " .. db.escapeString(mostDamageName) .. ", " .. byPlayerMostDamage .. ", " .. (lastHitUnjustified and 1 or 0) .. ", " .. (mostDamageUnjustified and 1 or 0) .. ")") local resultId = db.storeQuery("SELECT `player_id` FROM `player_deaths` WHERE `player_id` = " .. playerGuid) local deathRecords = 0 diff --git a/Lua/TFS_10/creaturescript sync outfits/Installation Instructions.txt b/Lua/TFS_10/creaturescript sync outfits/Installation Instructions.txt new file mode 100644 index 0000000..96f80a1 --- /dev/null +++ b/Lua/TFS_10/creaturescript sync outfits/Installation Instructions.txt @@ -0,0 +1,4 @@ +1. Add below line to XML file: data/creaturescripts/creaturescripts.xml + + +2. Place Lua file syncoutfit.lua in folder: data/creaturescripts/scripts/ diff --git a/Lua/TFS_10/creaturescript sync outfits/syncoutfit.lua b/Lua/TFS_10/creaturescript sync outfits/syncoutfit.lua new file mode 100644 index 0000000..5cdf71d --- /dev/null +++ b/Lua/TFS_10/creaturescript sync outfits/syncoutfit.lua @@ -0,0 +1,46 @@ +-- Sync outfits that player own with Znote AAC +-- So its possible to see which full sets player +-- has in characterprofile.php + +znote_outfit_list = { + { -- Female outfits + 136, 137, 138, 139, 140, 141, 142, 147, 148, + 149, 150, 155, 156, 157, 158, 252, 269, 270, + 279, 288, 324, 329, 336, 366, 431, 433, 464, + 466, 471, 513, 514, 542, 575, 578, 618, 620, + 632, 635, 636, 664, 666, 683, 694, 696, 698, + 724, 732, 745, 749, 759, 845, 852, 874, 885, + 900, 973, 975, 1020, 1024, 1043, 1050, 1057, + 1070, 1095, 1103, 1128, 1147, 1162, 1174, + 1187, 1203, 1205, 1207, 1211, 1246, 1244, + 1252, 1271, 1280, 1283, 1289, 1293, 1332 + }, + { -- Male outfits + 128, 129, 130, 131, 132, 133, 134, 143, 144, + 145, 146, 151, 152, 153, 154, 251, 268, 273, + 278, 289, 325, 328, 335, 367, 430, 432, 463, + 465, 472, 512, 516, 541, 574, 577, 610, 619, + 633, 634, 637, 665, 667, 684, 695, 697, 699, + 725, 733, 746, 750, 760, 846, 853, 873, 884, + 899, 908, 931, 955, 957, 962, 964, 966, 968, + 970, 972, 974, 1021, 1023, 1042, 1051, 1056, + 1069, 1094, 1102, 1127, 1146, 1161, 1173, + 1186, 1202, 1204, 1206, 1210, 1245, 1243, + 1251, 1270, 1279, 1282, 1288, 1292, 1331 + } +} + +function onLogin(player) + -- storage_value + 1000 storages (highest outfit id) must not be used in other script. + -- Must be identical to Znote AAC config.php: $config['EQ_shower'] -> storage_value + local storage_value = 10000 + -- Loop through outfits + for _, outfit in pairs(znote_outfit_list[player:getSex() + 1]) do + if player:hasOutfit(outfit,3) then + if player:getStorageValue(storage_value + outfit) ~= 3 then + player:setStorageValue(storage_value + outfit, 3) + end + end + end + return true +end diff --git a/LUA/TFS_10/globalevent powergamers/powergamers.lua b/Lua/TFS_10/globalevent powergamers/powergamers.lua similarity index 100% rename from LUA/TFS_10/globalevent powergamers/powergamers.lua rename to Lua/TFS_10/globalevent powergamers/powergamers.lua diff --git a/LUA/TFS_10/globalevent shopsystem/znoteshop.lua b/Lua/TFS_10/globalevent shopsystem/znoteshop.lua similarity index 97% rename from LUA/TFS_10/globalevent shopsystem/znoteshop.lua rename to Lua/TFS_10/globalevent shopsystem/znoteshop.lua index 0e75bb4..6d8659a 100644 --- a/LUA/TFS_10/globalevent shopsystem/znoteshop.lua +++ b/Lua/TFS_10/globalevent shopsystem/znoteshop.lua @@ -1,155 +1,155 @@ --- --- Znote Auto Shop v2.1 for Znote AAC on TFS 1.2+ -function onThink(interval, lastExecution) - local orderQuery = db.storeQuery([[ - SELECT - MIN(`po`.`player_id`) AS `player_id`, - `shop`.`id`, - `shop`.`type`, - `shop`.`itemid`, - `shop`.`count` - FROM `players_online` AS `po` - INNER JOIN `players` AS `p` - ON `po`.`player_id` = `p`.`id` - INNER JOIN `znote_shop_orders` AS `shop` - ON `p`.`account_id` = `shop`.`account_id` - WHERE `shop`.`type` IN(1,5,6,7) - GROUP BY `shop`.`id` - ]]) - -- Detect if we got any results - if orderQuery ~= false then - local type_desc = { - "itemids", - "pending premium (skip)", - "pending gender change (skip)", - "pending character name change (skip)", - "Outfit and addons", - "Mounts", - "Instant house purchase" - } - repeat - local player_id = result.getNumber(orderQuery, 'player_id') - local orderId = result.getNumber(orderQuery, 'id') - local orderType = result.getNumber(orderQuery, 'type') - local orderItemId = result.getNumber(orderQuery, 'itemid') - local orderCount = result.getNumber(orderQuery, 'count') - local served = false - - local player = Player(player_id) - if player ~= nil then - - local description = "Unknown or custom type" - if type_desc[orderType] ~= nil then - description = type_desc[orderType] - end - print("Processing type "..orderType..": ".. description) - print("Processing shop order for: [".. player:getName() .."] type "..orderType..": ".. description) - - local tile = Tile(player:getPosition()) - if tile ~= nil and tile:hasFlag(TILESTATE_PROTECTIONZONE) then - -- ORDER TYPE 1 (Regular item shop products) - if orderType == 1 then - served = true - local itemType = ItemType(orderItemId) - -- Get weight - if player:getFreeCapacity() >= itemType:getWeight(orderCount) then - local backpack = player:getSlotItem(CONST_SLOT_BACKPACK) - -- variable = (condition) and (return if true) or (return if false) - local needslots = itemType:isStackable() and math.floor(orderCount / 100) + 1 or orderCount - if backpack ~= nil and backpack:getEmptySlots(false) >= needslots then - db.query("DELETE FROM `znote_shop_orders` WHERE `id` = " .. orderId .. ";") - player:addItem(orderItemId, orderCount) - player:sendTextMessage(MESSAGE_INFO_DESCR, "Congratulations! You have received " .. orderCount .. "x " .. ItemType(orderItemId):getName() .. "!") - print("Process complete. [".. player:getName() .."] has received " .. orderCount .. "x " .. ItemType(orderItemId):getName() .. ".") - else -- not enough slots - player:sendTextMessage(MESSAGE_STATUS_WARNING, "Your main backpack is full. You need to free up "..needslots.." available slots to get " .. orderCount .. " " .. ItemType(orderItemId):getName() .. "!") - print("Process canceled. [".. player:getName() .."] need more space in his backpack to get " .. orderCount .. "x " .. ItemType(orderItemId):getName() .. ".") - end - else -- not enough cap - player:sendTextMessage(MESSAGE_STATUS_WARNING, "You need more CAP to carry this order!") - print("Process canceled. [".. player:getName() .."] need more cap to carry " .. orderCount .. "x " .. ItemType(orderItemId):getName() .. ".") - end - end - - -- ORDER TYPE 5 (Outfit and addon) - if orderType == 5 then - served = true - - local itemid = orderItemId - local outfits = {} - - if itemid > 1000 then - local first = math.floor(itemid/1000) - table.insert(outfits, first) - itemid = itemid - (first * 1000) - end - table.insert(outfits, itemid) - - for _, outfitId in pairs(outfits) do - -- Make sure player don't already have this outfit and addon - if not player:hasOutfit(outfitId, orderCount) then - db.query("DELETE FROM `znote_shop_orders` WHERE `id` = " .. orderId .. ";") - player:addOutfit(outfitId) - player:addOutfitAddon(outfitId, orderCount) - player:sendTextMessage(MESSAGE_INFO_DESCR, "Congratulations! You have received a new outfit!") - print("Process complete. [".. player:getName() .."] has received outfit: ["..outfitId.."] with addon: ["..orderCount.."]") - else -- Already has outfit - player:sendTextMessage(MESSAGE_STATUS_WARNING, "You already have this outfit and addon!") - print("Process canceled. [".. player:getName() .."] already have outfit: ["..outfitId.."] with addon: ["..orderCount.."].") - end - end - end - - -- ORDER TYPE 6 (Mounts) - if orderType == 6 then - served = true - -- Make sure player don't already have this outfit and addon - if not player:hasMount(orderItemId) then - db.query("DELETE FROM `znote_shop_orders` WHERE `id` = " .. orderId .. ";") - player:addMount(orderItemId) - player:sendTextMessage(MESSAGE_INFO_DESCR, "Congratulations! You have received a new mount!") - print("Process complete. [".. player:getName() .."] has received mount: ["..orderItemId.."]") - else -- Already has mount - player:sendTextMessage(MESSAGE_STATUS_WARNING, "You already have this mount!") - print("Process canceled. [".. player:getName() .."] already have mount: ["..orderItemId.."].") - end - end - - -- ORDER TYPE 7 (Direct house purchase) - if orderType == 7 then - served = true - local house = House(orderItemId) - -- Logged in player is not necessarily the player that bough the house. So we need to load player from db. - local buyerQuery = db.storeQuery("SELECT `name` FROM `players` WHERE `id` = "..orderCount.." LIMIT 1") - if buyerQuery ~= false then - local buyerName = result.getString(buyerQuery, "name") - result.free(buyerQuery) - if house then - db.query("DELETE FROM `znote_shop_orders` WHERE `id` = " .. orderId .. ";") - house:setOwnerGuid(orderCount) - player:sendTextMessage(MESSAGE_INFO_DESCR, "You have successfully bought the house "..house:getName().." on "..buyerName..", be sure to have the money for the rent in the bank.") - print("Process complete. [".. buyerName .."] has received house: ["..house:getName().."]") - else - print("Process canceled. Failed to load house with ID: "..orderItemId) - end - else - print("Process canceled. Failed to load player with ID: "..orderCount) - end - end - - if not served then -- If this order hasn't been processed yet (missing type handling?) - print("Znote shop: Type ["..orderType.."] not properly processed. Missing Lua code?") - end - else -- Not in protection zone - player:sendTextMessage(MESSAGE_INFO_DESCR, 'You have a pending shop order, please enter protection zone.') - print("Skipped one shop order. Reason: Player: [".. player:getName() .."] is not inside protection zone.") - end - else -- player not logged in - print("Skipped one shop order. Reason: Player with id [".. player_id .."] is not online.") - end - - until not result.next(orderQuery) - result.free(orderQuery) - end - return true -end +-- +-- Znote Auto Shop v2.1 for Znote AAC on TFS 1.2+ +function onThink(interval, lastExecution) + local orderQuery = db.storeQuery([[ + SELECT + MIN(`po`.`player_id`) AS `player_id`, + `shop`.`id`, + `shop`.`type`, + `shop`.`itemid`, + `shop`.`count` + FROM `players_online` AS `po` + INNER JOIN `players` AS `p` + ON `po`.`player_id` = `p`.`id` + INNER JOIN `znote_shop_orders` AS `shop` + ON `p`.`account_id` = `shop`.`account_id` + WHERE `shop`.`type` IN(1,5,6,7) + GROUP BY `shop`.`id` + ]]) + -- Detect if we got any results + if orderQuery ~= false then + local type_desc = { + "itemids", + "pending premium (skip)", + "pending gender change (skip)", + "pending character name change (skip)", + "Outfit and addons", + "Mounts", + "Instant house purchase" + } + repeat + local player_id = result.getNumber(orderQuery, 'player_id') + local orderId = result.getNumber(orderQuery, 'id') + local orderType = result.getNumber(orderQuery, 'type') + local orderItemId = result.getNumber(orderQuery, 'itemid') + local orderCount = result.getNumber(orderQuery, 'count') + local served = false + + local player = Player(player_id) + if player ~= nil then + + local description = "Unknown or custom type" + if type_desc[orderType] ~= nil then + description = type_desc[orderType] + end + print("Processing type "..orderType..": ".. description) + print("Processing shop order for: [".. player:getName() .."] type "..orderType..": ".. description) + + local tile = Tile(player:getPosition()) + if tile ~= nil and tile:hasFlag(TILESTATE_PROTECTIONZONE) then + -- ORDER TYPE 1 (Regular item shop products) + if orderType == 1 then + served = true + local itemType = ItemType(orderItemId) + -- Get weight + if player:getFreeCapacity() >= itemType:getWeight(orderCount) then + local backpack = player:getSlotItem(CONST_SLOT_BACKPACK) + -- variable = (condition) and (return if true) or (return if false) + local needslots = itemType:isStackable() and math.floor(orderCount / 100) + 1 or orderCount + if backpack ~= nil and backpack:getEmptySlots(false) >= needslots then + db.query("DELETE FROM `znote_shop_orders` WHERE `id` = " .. orderId .. ";") + player:addItem(orderItemId, orderCount) + player:sendTextMessage(MESSAGE_INFO_DESCR, "Congratulations! You have received " .. orderCount .. "x " .. ItemType(orderItemId):getName() .. "!") + print("Process complete. [".. player:getName() .."] has received " .. orderCount .. "x " .. ItemType(orderItemId):getName() .. ".") + else -- not enough slots + player:sendTextMessage(MESSAGE_STATUS_WARNING, "Your main backpack is full. You need to free up "..needslots.." available slots to get " .. orderCount .. " " .. ItemType(orderItemId):getName() .. "!") + print("Process canceled. [".. player:getName() .."] need more space in his backpack to get " .. orderCount .. "x " .. ItemType(orderItemId):getName() .. ".") + end + else -- not enough cap + player:sendTextMessage(MESSAGE_STATUS_WARNING, "You need more CAP to carry this order!") + print("Process canceled. [".. player:getName() .."] need more cap to carry " .. orderCount .. "x " .. ItemType(orderItemId):getName() .. ".") + end + end + + -- ORDER TYPE 5 (Outfit and addon) + if orderType == 5 then + served = true + + local itemid = orderItemId + local outfits = {} + + if itemid > 1000 then + local first = math.floor(itemid/1000) + table.insert(outfits, first) + itemid = itemid - (first * 1000) + end + table.insert(outfits, itemid) + + for _, outfitId in pairs(outfits) do + -- Make sure player don't already have this outfit and addon + if not player:hasOutfit(outfitId, orderCount) then + db.query("DELETE FROM `znote_shop_orders` WHERE `id` = " .. orderId .. ";") + player:addOutfit(outfitId) + player:addOutfitAddon(outfitId, orderCount) + player:sendTextMessage(MESSAGE_INFO_DESCR, "Congratulations! You have received a new outfit!") + print("Process complete. [".. player:getName() .."] has received outfit: ["..outfitId.."] with addon: ["..orderCount.."]") + else -- Already has outfit + player:sendTextMessage(MESSAGE_STATUS_WARNING, "You already have this outfit and addon!") + print("Process canceled. [".. player:getName() .."] already have outfit: ["..outfitId.."] with addon: ["..orderCount.."].") + end + end + end + + -- ORDER TYPE 6 (Mounts) + if orderType == 6 then + served = true + -- Make sure player don't already have this outfit and addon + if not player:hasMount(orderItemId) then + db.query("DELETE FROM `znote_shop_orders` WHERE `id` = " .. orderId .. ";") + player:addMount(orderItemId) + player:sendTextMessage(MESSAGE_INFO_DESCR, "Congratulations! You have received a new mount!") + print("Process complete. [".. player:getName() .."] has received mount: ["..orderItemId.."]") + else -- Already has mount + player:sendTextMessage(MESSAGE_STATUS_WARNING, "You already have this mount!") + print("Process canceled. [".. player:getName() .."] already have mount: ["..orderItemId.."].") + end + end + + -- ORDER TYPE 7 (Direct house purchase) + if orderType == 7 then + served = true + local house = House(orderItemId) + -- Logged in player is not necessarily the player that bough the house. So we need to load player from db. + local buyerQuery = db.storeQuery("SELECT `name` FROM `players` WHERE `id` = "..orderCount.." LIMIT 1") + if buyerQuery ~= false then + local buyerName = result.getString(buyerQuery, "name") + result.free(buyerQuery) + if house then + db.query("DELETE FROM `znote_shop_orders` WHERE `id` = " .. orderId .. ";") + house:setOwnerGuid(orderCount) + player:sendTextMessage(MESSAGE_INFO_DESCR, "You have successfully bought the house "..house:getName().." on "..buyerName..", be sure to have the money for the rent in the bank.") + print("Process complete. [".. buyerName .."] has received house: ["..house:getName().."]") + else + print("Process canceled. Failed to load house with ID: "..orderItemId) + end + else + print("Process canceled. Failed to load player with ID: "..orderCount) + end + end + + if not served then -- If this order hasn't been processed yet (missing type handling?) + print("Znote shop: Type ["..orderType.."] not properly processed. Missing Lua code?") + end + else -- Not in protection zone + player:sendTextMessage(MESSAGE_INFO_DESCR, 'You have a pending shop order, please enter protection zone.') + print("Skipped one shop order. Reason: Player: [".. player:getName() .."] is not inside protection zone.") + end + else -- player not logged in + print("Skipped one shop order. Reason: Player with id [".. player_id .."] is not online.") + end + + until not result.next(orderQuery) + result.free(orderQuery) + end + return true +end diff --git a/Lua/TFS_10/revscriptsys/Installation Instructions.txt b/Lua/TFS_10/revscriptsys/Installation Instructions.txt new file mode 100644 index 0000000..b847dae --- /dev/null +++ b/Lua/TFS_10/revscriptsys/Installation Instructions.txt @@ -0,0 +1,3 @@ +Step 1: Put script on data/script folder (edit content if necessary) + +Step 2: Restart OT server, and it should work. :) diff --git a/Lua/TFS_10/revscriptsys/first_items.lua b/Lua/TFS_10/revscriptsys/first_items.lua new file mode 100644 index 0000000..754224f --- /dev/null +++ b/Lua/TFS_10/revscriptsys/first_items.lua @@ -0,0 +1,99 @@ +local creatureevent = CreatureEvent("FirstItems") + +local config = { + [1] = { -- Sorcerer + items = { + {2175, 1}, -- spellbook + {2190, 1}, -- wand of vortex + {8819, 1}, -- magician's robe + {8820, 1}, -- mage hat + {2468, 1}, -- studded legs + {2643, 1}, -- leather boots + {2661, 1} -- scarf + }, + container = { + {2120, 1}, -- rope + {2554, 1}, -- shovel + {7620, 1} -- mana potion + } + }, + [2] = { -- Druid + items = { + {2175, 1}, -- spellbook + {2182, 1}, -- snakebite rod + {8819, 1}, -- magician's robe + {8820, 1}, -- mage hat + {2468, 1}, -- studded legs + {2643, 1}, -- leather boots + {2661, 1} -- scarf + }, + container = { + {2120, 1}, -- rope + {2554, 1}, -- shovel + {7620, 1} -- mana potion + } + }, + [3] = { -- Paladin + items = { + {2525, 1}, -- dwarven shield + {2389, 5}, -- 5 spears + {2660, 1}, -- ranger's cloak + {8923, 1}, -- ranger legs + {2643, 1}, -- leather boots + {2661, 1}, -- scarf + {2480, 1} -- legion helmet + }, + container = { + {2120, 1}, -- rope + {2554, 1}, -- shovel + {7618, 1}, -- health potion + {2456, 1}, -- bow + {2544, 50} -- 50 arrows + } + }, + [4] = { -- Knight + items = { + {2525, 1}, -- dwarven shield + {8601, 1}, -- steel axe + {2465, 1}, -- brass armor + {2460, 1}, -- brass helmet + {2478, 1}, -- brass legs + {2643, 1}, -- leather boots + {2661, 1} -- scarf + }, + container = { + {8602, 1}, -- jagged sword + {2439, 1}, -- daramanian mace + {2120, 1}, -- rope + {2554, 1}, -- shovel + {7618, 1} -- health potion + } + } +} + +function creatureevent.onLogin(player) + local targetVocation = config[player:getVocation():getId()] + if not targetVocation then + return true + end + + if player:getLastLoginSaved() ~= 0 then + return true + end + + for i = 1, #targetVocation.items do + player:addItem(targetVocation.items[i][1], targetVocation.items[i][2]) + end + + local backpack = player:addItem(1988) -- backpack + if not backpack then + return true + end + + for i = 1, #targetVocation.container do + backpack:addItem(targetVocation.container[i][1], targetVocation.container[i][2]) + end + return true +end + +creatureevent:register() diff --git a/Lua/TFS_10/revscriptsys/first_items_rook.lua b/Lua/TFS_10/revscriptsys/first_items_rook.lua new file mode 100644 index 0000000..54d5642 --- /dev/null +++ b/Lua/TFS_10/revscriptsys/first_items_rook.lua @@ -0,0 +1,17 @@ +local creatureevent = CreatureEvent("FirstItemsRook") + +local firstItems = {2050, 2382} -- torch and club + +function creatureevent.onLogin(player) + if player:getLastLoginSaved() <= 0 then + for i = 1, #firstItems do + player:addItem(firstItems[i], 1) + end + player:addItem(player:getSex() == 0 and 2651 or 2650, 1) -- coat + player:addItem(ITEM_BAG, 1) + player:addItem(2674, 1) -- red apple + end + return true +end + +creatureevent:register() diff --git a/Lua/TFS_10/revscriptsys/playerdeath.lua b/Lua/TFS_10/revscriptsys/playerdeath.lua new file mode 100644 index 0000000..0ec8bf4 --- /dev/null +++ b/Lua/TFS_10/revscriptsys/playerdeath.lua @@ -0,0 +1,135 @@ +local deathListEnabled = true +local maxDeathRecords = 5 + +local function sendWarStatus(guildId, enemyGuildId, warId, playerName, killerName) + local guild, enemyGuild = Guild(guildId), Guild(enemyGuildId) + if not guild or not enemyGuild then + return + end + + local resultId = db.storeQuery("SELECT `guild_wars`.`id`, (SELECT `limit` FROM `znote_guild_wars` WHERE `znote_guild_wars`.`id` = `guild_wars`.`id`) AS `limit`, (SELECT COUNT(1) FROM `guildwar_kills` WHERE `guildwar_kills`.`warid` = `guild_wars`.`id` AND `guildwar_kills`.`killerguild` = `guild_wars`.`guild1`) guild1_kills, (SELECT COUNT(1) FROM `guildwar_kills` WHERE `guildwar_kills`.`warid` = `guild_wars`.`id` AND `guildwar_kills`.`killerguild` = `guild_wars`.`guild2`) guild2_kills FROM `guild_wars` WHERE (`guild1` = " .. guildId .. " OR `guild2` = " .. guildId .. ") AND `status` = 1 AND `id` = " .. warId) + if resultId then + + local guild1_kills = result.getNumber(resultId, "guild1_kills") + local guild2_kills = result.getNumber(resultId, "guild2_kills") + local limit = result.getNumber(resultId, "limit") + result.free(resultId) + + local members = guild:getMembersOnline() + for i = 1, #members do + members[i]:sendChannelMessage("", string.format("%s was killed by %s. The new score is %d:%d frags (limit: %d)", playerName, killerName, guild1_kills, guild2_kills, limit), TALKTYPE_CHANNEL_R1, CHANNEL_GUILD) + end + + local enemyMembers = enemyGuild:getMembersOnline() + for i = 1, #enemyMembers do + enemyMembers[i]:sendChannelMessage("", string.format("%s was killed by %s. The new score is %d:%d frags (limit: %d)", playerName, killerName, guild1_kills, guild2_kills, limit), TALKTYPE_CHANNEL_R1, CHANNEL_GUILD) + end + + if guild1_kills >= limit or guild2_kills >= limit then + db.query("UPDATE `guild_wars` SET `status` = 4, `ended` = " .. os.time() .. " WHERE `status` = 1 AND `id` = " .. warId) + Game.broadcastMessage(string.format("%s has just won the war against %s.", guild:getName(), enemyGuild:getName()), MESSAGE_EVENT_ADVANCE) + end + end +end + +local creatureevent = CreatureEvent("PlayerDeath") + +function creatureevent.onDeath(creature, corpse, killer, mostDamageKiller, lastHitUnjustified, mostDamageUnjustified) + local playerId = player:getId() + if nextUseStaminaTime[playerId] then + nextUseStaminaTime[playerId] = nil + end + + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You are dead.") + if not deathListEnabled then + return + end + + local byPlayer = 0 + local killerName + if killer then + if killer:isPlayer() then + byPlayer = 1 + else + local master = killer:getMaster() + if master and master ~= killer and master:isPlayer() then + killer = master + byPlayer = 1 + end + end + killerName = killer:getName() + else + killerName = "field item" + end + + local byPlayerMostDamage = 0 + local mostDamageKillerName + if mostDamageKiller then + if mostDamageKiller:isPlayer() then + byPlayerMostDamage = 1 + else + local master = mostDamageKiller:getMaster() + if master and master ~= mostDamageKiller and master:isPlayer() then + mostDamageKiller = master + byPlayerMostDamage = 1 + end + end + mostDamageName = mostDamageKiller:getName() + else + mostDamageName = "field item" + end + + local playerGuid = player:getGuid() + db.query("INSERT INTO `player_deaths` (`player_id`, `time`, `level`, `killed_by`, `is_player`, `mostdamage_by`, `mostdamage_is_player`, `unjustified`, `mostdamage_unjustified`) VALUES (" .. playerGuid .. ", " .. os.time() .. ", " .. player:getLevel() .. ", " .. db.escapeString(killerName) .. ", " .. byPlayer .. ", " .. db.escapeString(mostDamageName) .. ", " .. byPlayerMostDamage .. ", " .. (lastHitUnjustified and 1 or 0) .. ", " .. (mostDamageUnjustified and 1 or 0) .. ")") + local resultId = db.storeQuery("SELECT `player_id` FROM `player_deaths` WHERE `player_id` = " .. playerGuid) + + local deathRecords = 0 + local tmpResultId = resultId + while tmpResultId ~= false do + tmpResultId = result.next(resultId) + deathRecords = deathRecords + 1 + end + + if resultId ~= false then + result.free(resultId) + end + + local limit = deathRecords - maxDeathRecords + if limit > 0 then + db.asyncQuery("DELETE FROM `player_deaths` WHERE `player_id` = " .. playerGuid .. " ORDER BY `time` LIMIT " .. limit) + end + + if byPlayer == 1 then + local targetGuild = player:getGuild() + targetGuild = targetGuild and targetGuild:getId() or 0 + if targetGuild ~= 0 then + local killerGuild = killer:getGuild() + killerGuild = killerGuild and killerGuild:getId() or 0 + if killerGuild ~= 0 and targetGuild ~= killerGuild and isInWar(playerId, killer:getId()) then + local warId = false + resultId = db.storeQuery("SELECT `id` FROM `guild_wars` WHERE `status` = 1 AND ((`guild1` = " .. killerGuild .. " AND `guild2` = " .. targetGuild .. ") OR (`guild1` = " .. targetGuild .. " AND `guild2` = " .. killerGuild .. "))") + if resultId ~= false then + warId = result.getNumber(resultId, "id") + result.free(resultId) + end + + if warId ~= false then + local playerName = player:getName() + db.asyncQuery("INSERT INTO `guildwar_kills` (`killer`, `target`, `killerguild`, `targetguild`, `time`, `warid`) VALUES (" .. db.escapeString(killerName) .. ", " .. db.escapeString(playerName) .. ", " .. killerGuild .. ", " .. targetGuild .. ", " .. os.time() .. ", " .. warId .. ")") + addEvent(sendWarStatus, 1000, killerGuild, targetGuild, warId, playerName, killerName) + end + end + end + end +end + +creatureevent:register() + +local creatureeventLogin = CreatureEvent("creatureeventLogin") + +function creatureeventLogin.onLogin(player) + player:registerEvent("PlayerDeath") + return true +end + +creatureeventLogin:register() diff --git a/Lua/TFS_10/revscriptsys/powergamers.lua b/Lua/TFS_10/revscriptsys/powergamers.lua new file mode 100644 index 0000000..c60fd8a --- /dev/null +++ b/Lua/TFS_10/revscriptsys/powergamers.lua @@ -0,0 +1,66 @@ + +-- getEternalStorage and setEternalStorage +-- can be added to data/global.lua if you want to use eternal storage for another purpose than this. +-- Regular TFS global storage values get reset every time server reboots. This does not. +local function getEternalStorage(key, parser) + local value = result.getString(db.storeQuery("SELECT `value` FROM `znote_global_storage` WHERE `key` = ".. key .. ";"), "value") + if not value then + if parser then + return false + else + return -1 + end + end + result.free(value) + return tonumber(value) or value +end + +local function setEternalStorage(key, value) + if getEternalStorage(key, true) then + db.query("UPDATE `znote_global_storage` SET `value` = '".. value .. "' WHERE `key` = ".. key .. ";") + else + db.query("INSERT INTO `znote_global_storage` (`key`, `value`) VALUES (".. key ..", ".. value ..");") + end + return true +end + +-- SQL Query to execute: -- +--[[ +ALTER TABLE `znote_players` ADD `exphist_lastexp` BIGINT(255) NOT NULL DEFAULT '0', +ADD `exphist1` BIGINT(255) NOT NULL DEFAULT '0', +ADD `exphist2` BIGINT(255) NOT NULL DEFAULT '0', +ADD `exphist3` BIGINT(255) NOT NULL DEFAULT '0', +ADD `exphist4` BIGINT(255) NOT NULL DEFAULT '0', +ADD `exphist5` BIGINT(255) NOT NULL DEFAULT '0', +ADD `exphist6` BIGINT(255) NOT NULL DEFAULT '0', +ADD `exphist7` BIGINT(255) NOT NULL DEFAULT '0', +ADD `onlinetimetoday` BIGINT(20) NOT NULL DEFAULT '0', +ADD `onlinetime1` BIGINT(20) NOT NULL DEFAULT '0', +ADD `onlinetime2` BIGINT(20) NOT NULL DEFAULT '0', +ADD `onlinetime3` BIGINT(20) NOT NULL DEFAULT '0', +ADD `onlinetime4` BIGINT(20) NOT NULL DEFAULT '0', +ADD `onlinetime5` BIGINT(20) NOT NULL DEFAULT '0', +ADD `onlinetime6` BIGINT(20) NOT NULL DEFAULT '0', +ADD `onlinetime7` BIGINT(20) NOT NULL DEFAULT '0', +ADD `onlinetimeall` BIGINT(20) NOT NULL DEFAULT '0'; +]]-- + +-- after that execute: -- +--[[ +UPDATE `znote_players` AS `z` INNER JOIN `players` AS `p` ON `p`.`id`=`z`.`player_id` SET `z`.`exphist_lastexp`=`p`.`experience`; +]]-- + +local globalevent = GlobalEvent("PowerGamers") + +function globalevent.onThink(...) + if tonumber(os.date("%d")) ~= getEternalStorage(23856) then + setEternalStorage(23856, (tonumber(os.date("%d")))) + db.query("UPDATE `znote_players` SET `onlinetime7`=`onlinetime6`, `onlinetime6`=`onlinetime5`, `onlinetime5`=`onlinetime4`, `onlinetime4`=`onlinetime3`, `onlinetime3`=`onlinetime2`, `onlinetime2`=`onlinetime1`, `onlinetime1`=`onlinetimetoday`, `onlinetimetoday`=0;") + db.query("UPDATE `znote_players` `z` INNER JOIN `players` `p` ON `p`.`id`=`z`.`player_id` SET `z`.`exphist7`=`z`.`exphist6`, `z`.`exphist6`=`z`.`exphist5`, `z`.`exphist5`=`z`.`exphist4`, `z`.`exphist4`=`z`.`exphist3`, `z`.`exphist3`=`z`.`exphist2`, `z`.`exphist2`=`z`.`exphist1`, `z`.`exphist1`=`p`.`experience`-`z`.`exphist_lastexp`, `z`.`exphist_lastexp`=`p`.`experience`;") + end + db.query("UPDATE `znote_players` SET `onlinetimetoday` = `onlinetimetoday` + 60, `onlinetimeall` = `onlinetimeall` + 60 WHERE `player_id` IN (SELECT `player_id` FROM `players_online` WHERE `players_online`.`player_id` = `znote_players`.`player_id`)") + return true +end + +globalevent:interval(60000) +globalevent:register() diff --git a/Lua/TFS_10/revscriptsys/report_talkaction.lua b/Lua/TFS_10/revscriptsys/report_talkaction.lua new file mode 100644 index 0000000..ddf2912 --- /dev/null +++ b/Lua/TFS_10/revscriptsys/report_talkaction.lua @@ -0,0 +1,21 @@ +local talkaction = TalkAction("!report") + +function talkaction.onSay(player) + local storage = 6708 -- You can change the storage if its already in use + local delaytime = 30 -- Exhaust In Seconds. + if param == '' then + player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "Command param required.") + return true + end + if player:getStorageValue(storage) <= os.time() then + player:sendTextMessage(MESSAGE_INFO_DESCR, "Your report has been received successfully!") + db.query("INSERT INTO `znote_player_reports` (`id` ,`name` ,`posx` ,`posy` ,`posz` ,`report_description` ,`date`)VALUES (NULL , " .. db.escapeString(player:getName()) .. ", '" .. player:getPosition().x .. "', '" .. player:getPosition().y .. "', '" .. player:getPosition().z .. "', " .. db.escapeString(param) .. ", '" .. os.time() .. "')") + player:setStorageValue(storage, os.time() + delaytime) + else + player:sendTextMessage(MESSAGE_STATUS_WARNING, "You have to wait " .. player:getStorageValue(storage) - os.time() .. " seconds to report again.") + end + return true +end + +talkaction:separator(" ") +talkaction:register() diff --git a/Lua/TFS_10/revscriptsys/shopsystem_globalevent.lua b/Lua/TFS_10/revscriptsys/shopsystem_globalevent.lua new file mode 100644 index 0000000..b2f0724 --- /dev/null +++ b/Lua/TFS_10/revscriptsys/shopsystem_globalevent.lua @@ -0,0 +1,158 @@ +local globalevent = GlobalEvent("ShopSystemGlobal") + +function globalevent.onThink(...) + local orderQuery = db.storeQuery([[ + SELECT + MIN(`po`.`player_id`) AS `player_id`, + `shop`.`id`, + `shop`.`type`, + `shop`.`itemid`, + `shop`.`count` + FROM `players_online` AS `po` + INNER JOIN `players` AS `p` + ON `po`.`player_id` = `p`.`id` + INNER JOIN `znote_shop_orders` AS `shop` + ON `p`.`account_id` = `shop`.`account_id` + WHERE `shop`.`type` IN(1,5,6,7) + GROUP BY `shop`.`id` + ]]) + -- Detect if we got any results + if orderQuery ~= false then + local type_desc = { + "itemids", + "pending premium (skip)", + "pending gender change (skip)", + "pending character name change (skip)", + "Outfit and addons", + "Mounts", + "Instant house purchase" + } + repeat + local player_id = result.getNumber(orderQuery, 'player_id') + local orderId = result.getNumber(orderQuery, 'id') + local orderType = result.getNumber(orderQuery, 'type') + local orderItemId = result.getNumber(orderQuery, 'itemid') + local orderCount = result.getNumber(orderQuery, 'count') + local served = false + + local player = Player(player_id) + if player ~= nil then + + local description = "Unknown or custom type" + if type_desc[orderType] ~= nil then + description = type_desc[orderType] + end + print("Processing type "..orderType..": ".. description) + print("Processing shop order for: [".. player:getName() .."] type "..orderType..": ".. description) + + local tile = Tile(player:getPosition()) + if tile ~= nil and tile:hasFlag(TILESTATE_PROTECTIONZONE) then + -- ORDER TYPE 1 (Regular item shop products) + if orderType == 1 then + served = true + local itemType = ItemType(orderItemId) + -- Get weight + if player:getFreeCapacity() >= itemType:getWeight(orderCount) then + local backpack = player:getSlotItem(CONST_SLOT_BACKPACK) + -- variable = (condition) and (return if true) or (return if false) + local needslots = itemType:isStackable() and math.floor(orderCount / 100) + 1 or orderCount + if backpack ~= nil and backpack:getEmptySlots(false) >= needslots then + db.query("DELETE FROM `znote_shop_orders` WHERE `id` = " .. orderId .. ";") + player:addItem(orderItemId, orderCount) + player:sendTextMessage(MESSAGE_INFO_DESCR, "Congratulations! You have received " .. orderCount .. "x " .. ItemType(orderItemId):getName() .. "!") + print("Process complete. [".. player:getName() .."] has received " .. orderCount .. "x " .. ItemType(orderItemId):getName() .. ".") + else -- not enough slots + player:sendTextMessage(MESSAGE_STATUS_WARNING, "Your main backpack is full. You need to free up "..needslots.." available slots to get " .. orderCount .. " " .. ItemType(orderItemId):getName() .. "!") + print("Process canceled. [".. player:getName() .."] need more space in his backpack to get " .. orderCount .. "x " .. ItemType(orderItemId):getName() .. ".") + end + else -- not enough cap + player:sendTextMessage(MESSAGE_STATUS_WARNING, "You need more CAP to carry this order!") + print("Process canceled. [".. player:getName() .."] need more cap to carry " .. orderCount .. "x " .. ItemType(orderItemId):getName() .. ".") + end + end + + -- ORDER TYPE 5 (Outfit and addon) + if orderType == 5 then + served = true + + local itemid = orderItemId + local outfits = {} + + if itemid > 1000 then + local first = math.floor(itemid/1000) + table.insert(outfits, first) + itemid = itemid - (first * 1000) + end + table.insert(outfits, itemid) + + for _, outfitId in pairs(outfits) do + -- Make sure player don't already have this outfit and addon + if not player:hasOutfit(outfitId, orderCount) then + db.query("DELETE FROM `znote_shop_orders` WHERE `id` = " .. orderId .. ";") + player:addOutfit(outfitId) + player:addOutfitAddon(outfitId, orderCount) + player:sendTextMessage(MESSAGE_INFO_DESCR, "Congratulations! You have received a new outfit!") + print("Process complete. [".. player:getName() .."] has received outfit: ["..outfitId.."] with addon: ["..orderCount.."]") + else -- Already has outfit + player:sendTextMessage(MESSAGE_STATUS_WARNING, "You already have this outfit and addon!") + print("Process canceled. [".. player:getName() .."] already have outfit: ["..outfitId.."] with addon: ["..orderCount.."].") + end + end + end + + -- ORDER TYPE 6 (Mounts) + if orderType == 6 then + served = true + -- Make sure player don't already have this outfit and addon + if not player:hasMount(orderItemId) then + db.query("DELETE FROM `znote_shop_orders` WHERE `id` = " .. orderId .. ";") + player:addMount(orderItemId) + player:sendTextMessage(MESSAGE_INFO_DESCR, "Congratulations! You have received a new mount!") + print("Process complete. [".. player:getName() .."] has received mount: ["..orderItemId.."]") + else -- Already has mount + player:sendTextMessage(MESSAGE_STATUS_WARNING, "You already have this mount!") + print("Process canceled. [".. player:getName() .."] already have mount: ["..orderItemId.."].") + end + end + + -- ORDER TYPE 7 (Direct house purchase) + if orderType == 7 then + served = true + local house = House(orderItemId) + -- Logged in player is not necessarily the player that bough the house. So we need to load player from db. + local buyerQuery = db.storeQuery("SELECT `name` FROM `players` WHERE `id` = "..orderCount.." LIMIT 1") + if buyerQuery ~= false then + local buyerName = result.getString(buyerQuery, "name") + result.free(buyerQuery) + if house then + db.query("DELETE FROM `znote_shop_orders` WHERE `id` = " .. orderId .. ";") + house:setOwnerGuid(orderCount) + player:sendTextMessage(MESSAGE_INFO_DESCR, "You have successfully bought the house "..house:getName().." on "..buyerName..", be sure to have the money for the rent in the bank.") + print("Process complete. [".. buyerName .."] has received house: ["..house:getName().."]") + else + print("Process canceled. Failed to load house with ID: "..orderItemId) + end + else + print("Process canceled. Failed to load player with ID: "..orderCount) + end + end + + if not served then -- If this order hasn't been processed yet (missing type handling?) + print("Znote shop: Type ["..orderType.."] not properly processed. Missing Lua code?") + end + else -- Not in protection zone + player:sendTextMessage(MESSAGE_INFO_DESCR, 'You have a pending shop order, please enter protection zone.') + print("Skipped one shop order. Reason: Player: [".. player:getName() .."] is not inside protection zone.") + end + else -- player not logged in + print("Skipped one shop order. Reason: Player with id [".. player_id .."] is not online.") + end + + until not result.next(orderQuery) + result.free(orderQuery) + end + return true +end + +globalevent:interval(30000) +globalevent:register() diff --git a/Lua/TFS_10/revscriptsys/shopsystem_talkaction.lua b/Lua/TFS_10/revscriptsys/shopsystem_talkaction.lua new file mode 100644 index 0000000..6c17ee7 --- /dev/null +++ b/Lua/TFS_10/revscriptsys/shopsystem_talkaction.lua @@ -0,0 +1,135 @@ +local talkaction = TalkAction("!shop") + +function talkaction.onSay(player) + local storage = 54073 -- Make sure to select non-used storage. This is used to prevent SQL load attacks. + local cooldown = 15 -- in seconds. + + if player:getStorageValue(storage) <= os.time() then + player:setStorageValue(storage, os.time() + cooldown) + + local type_desc = { + "itemids", + "pending premium (skip)", + "pending gender change (skip)", + "pending character name change (skip)", + "Outfit and addons", + "Mounts", + "Instant house purchase" + } + print("Player: " .. player:getName() .. " triggered !shop talkaction.") + -- Create the query + local orderQuery = db.storeQuery("SELECT `id`, `type`, `itemid`, `count` FROM `znote_shop_orders` WHERE `account_id` = " .. player:getAccountId() .. ";") + local served = false + + -- Detect if we got any results + if orderQuery ~= false then + repeat + -- Fetch order values + local q_id = result.getNumber(orderQuery, "id") + local q_type = result.getNumber(orderQuery, "type") + local q_itemid = result.getNumber(orderQuery, "itemid") + local q_count = result.getNumber(orderQuery, "count") + + local description = "Unknown or custom type" + if type_desc[q_type] ~= nil then + description = type_desc[q_type] + end + print("Processing type "..q_type..": ".. description) + + -- ORDER TYPE 1 (Regular item shop products) + if q_type == 1 then + served = true + -- Get weight + if player:getFreeCapacity() >= ItemType(q_itemid):getWeight(q_count) then + db.query("DELETE FROM `znote_shop_orders` WHERE `id` = " .. q_id .. ";") + player:addItem(q_itemid, q_count) + player:sendTextMessage(MESSAGE_INFO_DESCR, "Congratulations! You have received " .. q_count .. " x " .. ItemType(q_itemid):getName() .. "!") + else + player:sendTextMessage(MESSAGE_STATUS_WARNING, "Need more CAP!") + end + end + + -- ORDER TYPE 5 (Outfit and addon) + if q_type == 5 then + served = true + + local itemid = q_itemid + local outfits = {} + + if itemid > 1000 then + local first = math.floor(itemid/1000) + table.insert(outfits, first) + itemid = itemid - (first * 1000) + end + table.insert(outfits, itemid) + + for _, outfitId in pairs(outfits) do + -- Make sure player don't already have this outfit and addon + if not player:hasOutfit(outfitId, q_count) then + db.query("DELETE FROM `znote_shop_orders` WHERE `id` = " .. q_id .. ";") + player:addOutfit(outfitId) + player:addOutfitAddon(outfitId, q_count) + player:sendTextMessage(MESSAGE_INFO_DESCR, "Congratulations! You have received a new outfit!") + else + player:sendTextMessage(MESSAGE_STATUS_WARNING, "You already have this outfit and addon!") + end + end + end + + -- ORDER TYPE 6 (Mounts) + if q_type == 6 then + served = true + -- Make sure player don't already have this outfit and addon + if not player:hasMount(q_itemid) then + db.query("DELETE FROM `znote_shop_orders` WHERE `id` = " .. q_id .. ";") + player:addMount(q_itemid) + player:sendTextMessage(MESSAGE_INFO_DESCR, "Congratulations! You have received a new mount!") + else + player:sendTextMessage(MESSAGE_STATUS_WARNING, "You already have this mount!") + end + end + + -- ORDER TYPE 7 (Direct house purchase) + if orderType == 7 then + served = true + local house = House(orderItemId) + -- Logged in player is not necessarily the player that bough the house. So we need to load player from db. + local buyerQuery = db.storeQuery("SELECT `name` FROM `players` WHERE `id` = "..orderCount.." LIMIT 1") + if buyerQuery ~= false then + local buyerName = result.getString(buyerQuery, "name") + result.free(buyerQuery) + if house then + db.query("DELETE FROM `znote_shop_orders` WHERE `id` = " .. orderId .. ";") + house:setOwnerGuid(orderCount) + player:sendTextMessage(MESSAGE_INFO_DESCR, "You have successfully bought the house "..house:getName().." on "..buyerName..", be sure to have the money for the rent in the bank.") + print("Process complete. [".. buyerName .."] has received house: ["..house:getName().."]") + end + end + end + + -- Add custom order types here + -- Type 1 is for itemids (Already coded here) + -- Type 2 is for premium (Coded on web) + -- Type 3 is for gender change (Coded on web) + -- Type 4 is for character name change (Coded on web) + -- Type 5 is for character outfit and addon (Already coded here) + -- Type 6 is for mounts (Already coded here) + -- Type 7 is for Instant house purchase (Already coded here) + -- So use type 8+ for custom stuff, like etc packages. + -- if q_type == 8 then + -- end + until not result.next(orderQuery) + result.free(orderQuery) + if not served then + player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "You have no orders to process in-game.") + end + else + player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "You have no orders.") + end + else + player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Can only be executed once every " .. cooldown .. " seconds. Remaining cooldown: " .. player:getStorageValue(storage) - os.time()) + end + return false +end + +talkaction:register() diff --git a/Lua/TFS_10/revscriptsys/sync_outfit.lua b/Lua/TFS_10/revscriptsys/sync_outfit.lua new file mode 100644 index 0000000..8cc2d3a --- /dev/null +++ b/Lua/TFS_10/revscriptsys/sync_outfit.lua @@ -0,0 +1,50 @@ +local creatureevent = CreatureEvent("SincOutfit") + +-- Sync outfits that player own with Znote AAC +-- So its possible to see which full sets player +-- has in characterprofile.php + +znote_outfit_list = { + { -- Female outfits + 136, 137, 138, 139, 140, 141, 142, 147, 148, + 149, 150, 155, 156, 157, 158, 252, 269, 270, + 279, 288, 324, 329, 336, 366, 431, 433, 464, + 466, 471, 513, 514, 542, 575, 578, 618, 620, + 632, 635, 636, 664, 666, 683, 694, 696, 698, + 724, 732, 745, 749, 759, 845, 852, 874, 885, + 900, 973, 975, 1020, 1024, 1043, 1050, 1057, + 1070, 1095, 1103, 1128, 1147, 1162, 1174, + 1187, 1203, 1205, 1207, 1211, 1246, 1244, + 1252, 1271, 1280, 1283, 1289, 1293, 1332 + }, + { -- Male outfits + 128, 129, 130, 131, 132, 133, 134, 143, 144, + 145, 146, 151, 152, 153, 154, 251, 268, 273, + 278, 289, 325, 328, 335, 367, 430, 432, 463, + 465, 472, 512, 516, 541, 574, 577, 610, 619, + 633, 634, 637, 665, 667, 684, 695, 697, 699, + 725, 733, 746, 750, 760, 846, 853, 873, 884, + 899, 908, 931, 955, 957, 962, 964, 966, 968, + 970, 972, 974, 1021, 1023, 1042, 1051, 1056, + 1069, 1094, 1102, 1127, 1146, 1161, 1173, + 1186, 1202, 1204, 1206, 1210, 1245, 1243, + 1251, 1270, 1279, 1282, 1288, 1292, 1331 + } +} + +function creatureevent.onLogin(player) + -- storage_value + 1000 storages (highest outfit id) must not be used in other script. + -- Must be identical to Znote AAC config.php: $config['EQ_shower'] -> storage_value + local storage_value = 10000 + -- Loop through outfits + for _, outfit in pairs(znote_outfit_list[player:getSex() + 1]) do + if player:hasOutfit(outfit,3) then + if player:getStorageValue(storage_value + outfit) ~= 3 then + player:setStorageValue(storage_value + outfit, 3) + end + end + end + return true +end + +creatureevent:register() diff --git a/LUA/TFS_10/revscriptsys/znote_login.lua b/Lua/TFS_10/revscriptsys/znote_login.lua similarity index 100% rename from LUA/TFS_10/revscriptsys/znote_login.lua rename to Lua/TFS_10/revscriptsys/znote_login.lua diff --git a/LUA/TFS_10/talkaction report system/adminreport.lua b/Lua/TFS_10/talkaction report system/adminreport.lua similarity index 100% rename from LUA/TFS_10/talkaction report system/adminreport.lua rename to Lua/TFS_10/talkaction report system/adminreport.lua diff --git a/LUA/TFS_10/talkaction shopsystem/znoteshop.lua b/Lua/TFS_10/talkaction shopsystem/znoteshop.lua similarity index 100% rename from LUA/TFS_10/talkaction shopsystem/znoteshop.lua rename to Lua/TFS_10/talkaction shopsystem/znoteshop.lua diff --git a/config.php b/config.php index f71cccd..87edb99 100644 --- a/config.php +++ b/config.php @@ -256,7 +256,7 @@ // TFS 1.x powergamers and top online // Before enabling powergamers, make sure that you have added Lua files and added the SQL columns to your server db. - // files can be found at LUA folder. + // files can be found at Lua folder. $config['powergamers'] = array( 'enabled' => true, // Enable or disable page 'limit' => 20, // Number of players that it will show. @@ -607,7 +607,7 @@ 'outfits' => true, // Player storage (storage_value + outfitId) // used to see if player has outfit. - // see LUA scripts folder for otserv code + // see Lua scripts folder for otserv code 'storage_value' => 10000 ); @@ -936,7 +936,7 @@ //////////// /// SHOP /// //////////// - // If useDB is set to true, player can shop in-game as well using Znote LUA shop system plugin. + // If useDB is set to true, player can shop in-game as well using Znote Lua shop system plugin. $config['shop'] = array( 'enabled' => false, 'loginToView' => false, // Do user need to login to see the shop offers?