diff --git a/config.lua.dist b/config.lua.dist
index d667bb48952..a5bb3d73ca5 100644
--- a/config.lua.dist
+++ b/config.lua.dist
@@ -238,6 +238,7 @@ onlyPremiumAccount = false
-- NOTE: randomMonsterSpawn = true, will enable monsters from the same spawn to be randomized between them, thus making a variable hunt
-- NOTE: enablePlayerPutItemInAmmoSlot = true, will enable players to put any items on ammo slot, more used in custom shopping system
-- NOTE: startStreakLevel will make a reward streak level for new players who never logged in
+-- NOTE: if showLootsInBestiary is true, will cause all loots to be shown in the bestiary even if the player has not reached the required number of kills
stashMoving = false
depotChest = 4
autoLoot = false
@@ -255,6 +256,7 @@ lootPouchMaxLimit = 2000
storeInboxMaxLimit = 2000
enablePlayerPutItemInAmmoSlot = false
startStreakLevel = 0
+showLootsInBestiary = false
-- Teleport summon
-- Set to true will never remove the summon
@@ -427,6 +429,9 @@ maxDamageReflection = 200
toggleChainSystem = true
combatChainDelay = 50
combatChainTargets = 5
+combatChainSkillFormulaAxe = 0.9
+combatChainSkillFormulaClub = 0.7
+combatChainSkillFormulaSword = 1.1
-- Global server Save
-- NOTE: globalServerSaveNotifyDuration in minutes
diff --git a/data-canary/scripts/actions/other/carpets.lua b/data-canary/scripts/actions/other/carpets.lua
deleted file mode 100644
index aaa90026a22..00000000000
--- a/data-canary/scripts/actions/other/carpets.lua
+++ /dev/null
@@ -1,88 +0,0 @@
-local carpetItems = {
- [22737] = 22736,
- [22736] = 22737, -- Rift carpet
- [23537] = 23536,
- [23536] = 23537, -- Void carpet
- [23431] = 23453,
- [23453] = 23431, -- Yalaharian carpet
- [23432] = 23454,
- [23454] = 23432, -- White fur carpet
- [23433] = 23455,
- [23455] = 23433, -- Bamboo mat carpet
- [23715] = 23707,
- [23707] = 23715, -- Crimson carpet
- [23710] = 23716,
- [23716] = 23710, -- Azure carpet
- [23711] = 23717,
- [23717] = 23711, -- Emerald carpet
- [23712] = 23718,
- [23718] = 23712, -- Light parquet carpet
- [23713] = 23719,
- [23719] = 23713, -- Dark parquet carpet
- [23714] = 23720,
- [23720] = 23714, -- Marble floor
- [24416] = 24424,
- [24424] = 24416, -- Flowery carpet
- [24417] = 24425,
- [24425] = 24417, -- Colourful Carpet
- [24418] = 24426,
- [24426] = 24418, -- Striped carpet
- [24419] = 24427,
- [24427] = 24419, -- Fur carpet
- [24420] = 24428,
- [24428] = 24420, -- Diamond carpet
- [24421] = 24429,
- [24429] = 24421, -- Patterned carpet
- [24422] = 24430,
- [24430] = 24422, -- Night sky carpet
- [24423] = 24431,
- [24431] = 24423, -- Star carpet
- [26114] = 26115,
- [26115] = 26114, -- Verdant carpet
- [26116] = 26117,
- [26117] = 26116, -- Shaggy carpet
- [26118] = 26119,
- [26119] = 26118, -- Mystic carpet
- [26120] = 26121,
- [26121] = 26120, -- Stone tile
- [26123] = 26122,
- [26122] = 26123, -- Wooden plank
- [26151] = 26150,
- [26150] = 26151, -- Wheat carpet
- [26152] = 26153,
- [26153] = 26152, -- Crested carpet
- [26154] = 26155,
- [26155] = 26154, -- Decorated carpet
-}
-
-local carpets = Action()
-
-function carpets.onUse(player, item, fromPosition, target, toPosition, isHotkey)
- local carpet = carpetItems[item.itemid]
- if not carpet then
- return false
- end
- local tile = Tile(item:getPosition())
- local carpetStack = 0
- for _, carpetId in pairs(carpetItems) do
- carpetStack = carpetStack + tile:getItemCountById(carpetId)
- end
- if fromPosition.x == CONTAINER_POSITION then
- player:sendTextMessage(MESSAGE_FAILURE, "Put the item on the floor first.")
- return true
- elseif not tile or not tile:getHouse() then
- player:sendTextMessage(MESSAGE_FAILURE, "You may use this only inside a house.")
- return true
- elseif carpetStack > 1 then
- player:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE)
- return true
- end
- item:transform(carpet)
- return true
-end
-
-for index, value in pairs(carpetItems) do
- carpets:id(index)
-end
-
-carpets:register()
diff --git a/data-canary/scripts/actions/other/die.lua b/data-canary/scripts/actions/other/die.lua
deleted file mode 100644
index e7bc7316e9a..00000000000
--- a/data-canary/scripts/actions/other/die.lua
+++ /dev/null
@@ -1,23 +0,0 @@
-local die = Action()
-
-function die.onUse(player, item, fromPosition, target, toPosition, isHotkey)
- local position = item:getPosition()
- local value = math.random(1, 6)
- local isInGhostMode = player:isInGhostMode()
-
- position:sendMagicEffect(CONST_ME_CRAPS, isInGhostMode and player)
-
- local spectators = Game.getSpectators(position, false, true, 3, 3)
- for _, spectator in ipairs(spectators) do
- player:say(player:getName() .. " rolled a " .. value .. ".", TALKTYPE_MONSTER_SAY, isInGhostMode, spectator, position)
- end
-
- item:transform(5791 + value)
- return true
-end
-
-for items = 5792, 5797 do
- die:id(items)
-end
-
-die:register()
diff --git a/data-canary/scripts/actions/other/food.lua b/data-canary/scripts/actions/other/food.lua
deleted file mode 100644
index fcf05eefd52..00000000000
--- a/data-canary/scripts/actions/other/food.lua
+++ /dev/null
@@ -1,132 +0,0 @@
-local setting = {
- --[itemid] = {foodvalue, saytext}
- [169] = { 9, "Urgh." }, -- scarab cheese
- [836] = { 4, "Crunch." }, -- walnut
- [841] = { 4, "Crunch." }, -- peanut
- [901] = { 60, "Munch." }, -- marlin
- [3250] = { 5, "Crunch." }, -- carrot
- [3577] = { 15, "Munch." }, -- meat
- [3578] = { 12, "Munch." }, -- fish
- [3579] = { 10, "Mmmm." }, -- salmon
- [3580] = { 17, "Munch." }, -- northern pike
- [3581] = { 4, "Gulp." }, -- shrimp
- [3582] = { 30, "Chomp." }, -- ham
- [3583] = { 60, "Chomp." }, -- dragon ham
- [3584] = { 5, "Yum." }, -- pear
- [3585] = { 6, "Yum." }, -- red apple
- [3586] = { 13, "Yum." }, -- orange
- [3587] = { 8, "Yum." }, -- banana
- [3588] = { 1, "Yum." }, -- blueberry
- [3589] = { 18, "Slurp." }, -- coconut
- [3590] = { 1, "Yum." }, -- cherry
- [3591] = { 2, "Yum." }, -- strawberry
- [3592] = { 9, "Yum." }, -- grapes
- [3593] = { 20, "Yum." }, -- melon
- [3594] = { 17, "Munch." }, -- pumpkin
- [3595] = { 5, "Crunch." }, -- carrot
- [3596] = { 6, "Munch." }, -- tomato
- [3597] = { 9, "Crunch." }, -- corncob
- [3598] = { 2, "Crunch." }, -- cookie
- [3599] = { 2, "Munch." }, -- candy cane
- [3600] = { 10, "Crunch." }, -- bread
- [3601] = { 3, "Crunch." }, -- roll
- [3602] = { 8, "Crunch." }, -- brown bread
- [3606] = { 6, "Gulp." }, -- egg
- [3607] = { 9, "Smack." }, -- cheese
- [3723] = { 9, "Munch." }, -- white mushroom
- [3724] = { 4, "Munch." }, -- red mushroom
- [3725] = { 22, "Munch." }, -- brown mushroom
- [3726] = { 30, "Munch." }, -- orange mushroom
- [3727] = { 9, "Munch." }, -- wood mushroom
- [3728] = { 6, "Munch." }, -- dark mushroom
- [3729] = { 12, "Munch." }, -- some mushrooms
- [3730] = { 3, "Munch." }, -- some mushrooms
- [3731] = { 36, "Munch." }, -- fire mushroom
- [3732] = { 5, "Munch." }, -- green mushroom
- [5096] = { 4, "Yum." }, -- mango
- [6125] = { 8, "Gulp." }, -- tortoise egg
- [6277] = { 10, "Mmmm." }, -- cake
- [6278] = { 15, "Mmmm." }, -- decorated cake
- [6392] = { 12, "Mmmm." }, -- valentine's cake
- [6393] = { 15, "Mmmm." }, -- cream cake
- [6500] = { 20, "Mmmm." }, -- gingerbread man
- [6541] = { 6, "Gulp." }, -- coloured egg (yellow)
- [6542] = { 6, "Gulp." }, -- coloured egg (red)
- [6543] = { 6, "Gulp." }, -- coloured egg (blue)
- [6544] = { 6, "Gulp." }, -- coloured egg (green)
- [6545] = { 6, "Gulp." }, -- coloured egg (purple)
- [6569] = { 1, "Mmmm." }, -- candy
- [6574] = { 5, "Mmmm." }, -- bar of chocolate
- [7158] = { 15, "Munch." }, -- rainbow trout
- [7159] = { 13, "Munch." }, -- green perch
- [7372] = { 2, "Yum." }, -- ice cream cone (crispy chocolate chips)
- [7373] = { 2, "Yum." }, -- ice cream cone (velvet vanilla)
- [7374] = { 2, "Yum." }, -- ice cream cone (sweet strawberry)
- [7375] = { 2, "Yum." }, -- ice cream cone (chilly cherry)
- [7376] = { 2, "Yum." }, -- ice cream cone (mellow melon)
- [7377] = { 2, "Yum." }, -- ice cream cone (blue-barian)
- [8010] = { 10, "Gulp." }, -- potato
- [8011] = { 5, "Yum." }, -- plum
- [8012] = { 1, "Yum." }, -- raspberry
- [8013] = { 1, "Urgh." }, -- lemon
- [8014] = { 7, "Munch." }, -- cucumber
- [8015] = { 5, "Crunch." }, -- onion
- [8016] = { 1, "Gulp." }, -- jalapeƱo pepper
- [8017] = { 5, "Munch." }, -- beetroot
- [8018] = { 11, "Yum." }, -- chocolate cake
- [8019] = { 7, "Slurp." }, -- yummy gummy worm
- [8197] = { 5, "Crunch." }, -- bulb of garlic
- [9083] = { 0, "Slurp." }, -- banana chocolate shake
- [9537] = { 0, "Your head begins to feel better." }, -- headache pill
- [10329] = { 15, "Yum." }, -- rice ball
- [10453] = { 3, "Urgh." }, -- terramite eggs
- [10219] = { 10, "Mmmm." }, -- crocodile steak
- [11459] = { 20, "Yum." }, -- pineapple
- [11460] = { 10, "Munch." }, -- aubergine
- [11461] = { 8, "Crunch." }, -- broccoli
- [11462] = { 9, "Crunch." }, -- cauliflower
- [11681] = { 55, "Gulp." }, -- ectoplasmic sushi
- [11682] = { 18, "Yum." }, -- dragonfruit
- [11683] = { 2, "Munch." }, -- peas
- [12310] = { 20, "Crunch." }, -- haunch of boar
- [13992] = { 55, "Munch." }, -- sandfish
- [14084] = { 14, "Urgh." }, -- larvae
- [14085] = { 15, "Munch." }, -- deepling filet
- [14681] = { 60, "Mmmm." }, -- anniversary cake
- [16103] = { 33, "Munch." }, -- mushroom pie
- [17457] = { 10, "Urgh." }, -- insectoid eggs
- [17820] = { 15, "Smack." }, -- soft cheese
- [17821] = { 12, "Smack." }, -- rat cheese
- [22185] = { 12, "Yum." }, -- prickly pear
- [22187] = { 60, "Chomp." }, -- roasted meat
- [23535] = { 30, "Mmmm." }, -- energy bar
- [23545] = { 18, "Mmmm." }, -- energy drink
-}
-
-local food = Action()
-
-function food.onUse(player, item, fromPosition, target, toPosition, isHotkey)
- local itemFood = setting[item.itemid]
- if not itemFood then
- return false
- end
-
- local condition = player:getCondition(CONDITION_REGENERATION, CONDITIONID_DEFAULT)
- if condition and math.floor(condition:getTicks() / 1000 + (itemFood[1] * 12)) >= 1200 then
- player:sendTextMessage(MESSAGE_FAILURE, "You are full.")
- return true
- end
-
- player:feed(itemFood[1] * 12)
- player:say(itemFood[2], TALKTYPE_MONSTER_SAY)
- item:remove(1)
- player:updateSupplyTracker(item)
- player:getPosition():sendSingleSoundEffect(SOUND_EFFECT_TYPE_ACTION_EAT, player:isInGhostMode() and nil or player)
- return true
-end
-
-for index, value in pairs(setting) do
- food:id(index)
-end
-
-food:register()
diff --git a/data-canary/scripts/creaturescripts/advance_save.lua b/data-canary/scripts/creaturescripts/advance_save.lua
deleted file mode 100644
index 8bd6fd2fd06..00000000000
--- a/data-canary/scripts/creaturescripts/advance_save.lua
+++ /dev/null
@@ -1,32 +0,0 @@
-local config = {
- heal = true,
- save = true,
- effect = false,
-}
-
-local advanceSave = CreatureEvent("AdvanceSave")
-
-function advanceSave.onAdvance(player, skill, oldLevel, newLevel)
- if skill ~= SKILL_LEVEL or newLevel <= oldLevel then
- return true
- end
-
- if config.effect then
- player:getPosition():sendMagicEffect(math.random(CONST_ME_FIREWORK_YELLOW, CONST_ME_FIREWORK_BLUE))
- player:say("LEVEL UP!", TALKTYPE_MONSTER_SAY)
- end
-
- if config.heal then
- player:addHealth(player:getMaxHealth())
- end
-
- if config.save then
- player:save()
- end
-
- player:getFinalLowLevelBonus()
-
- return true
-end
-
-advanceSave:register()
diff --git a/data-canary/scripts/creaturescripts/logout.lua b/data-canary/scripts/creaturescripts/logout.lua
deleted file mode 100644
index 598a55878d2..00000000000
--- a/data-canary/scripts/creaturescripts/logout.lua
+++ /dev/null
@@ -1,17 +0,0 @@
-local logout = CreatureEvent("PlayerLogout")
-
-function logout.onLogout(player)
- local playerId = player:getId()
- if _G.NextUseStaminaTime[playerId] then
- _G.NextUseStaminaTime[playerId] = nil
- end
-
- if _G.OnExerciseTraining[playerId] then
- stopEvent(_G.OnExerciseTraining[playerId].event)
- _G.OnExerciseTraining[playerId] = nil
- player:setTraining(false)
- end
- return true
-end
-
-logout:register()
diff --git a/data-canary/scripts/creaturescripts/regenerate_stamina.lua b/data-canary/scripts/creaturescripts/regenerate_stamina.lua
deleted file mode 100644
index cc112ce6958..00000000000
--- a/data-canary/scripts/creaturescripts/regenerate_stamina.lua
+++ /dev/null
@@ -1,31 +0,0 @@
-local regenerateStamina = CreatureEvent("Regenerate Stamina")
-
-function regenerateStamina.onLogin(player)
- if not configManager.getBoolean(configKeys.STAMINA_SYSTEM) then
- return true
- end
-
- local lastLogout = player:getLastLogout()
- local offlineTime = lastLogout ~= 0 and math.min(os.time() - lastLogout, 86400 * 21) or 0
- offlineTime = offlineTime - 600
-
- if offlineTime < 180 then
- return true
- end
-
- local staminaMinutes = player:getStamina()
- local maxNormalStaminaRegen = 2400 - math.min(2400, staminaMinutes)
-
- local regainStaminaMinutes = offlineTime / 180
- if regainStaminaMinutes > maxNormalStaminaRegen then
- local happyHourStaminaRegen = (offlineTime - (maxNormalStaminaRegen * 180)) / 600
- staminaMinutes = math.min(2520, math.max(2400, staminaMinutes) + happyHourStaminaRegen)
- else
- staminaMinutes = staminaMinutes + regainStaminaMinutes
- end
-
- player:setStamina(staminaMinutes)
- return true
-end
-
-regenerateStamina:register()
diff --git a/data-otservbr-global/lib/core/storages.lua b/data-otservbr-global/lib/core/storages.lua
index 8dd5ff45a61..69f1d7f7948 100644
--- a/data-otservbr-global/lib/core/storages.lua
+++ b/data-otservbr-global/lib/core/storages.lua
@@ -103,7 +103,7 @@ Storage = {
Factions = 30024,
-- unused TrainerRoom = 30027,
-- unused NpcSpawn = 30028,
- ExerciseDummyExhaust = 30029,
+ -- unused ExerciseDummyExhaust = 30029,
SamsOldBackpack = 30030,
SamsOldBackpackDoor = 30031,
StrawberryCupcake = 30032,
@@ -2113,7 +2113,7 @@ Storage = {
BloodBrothers = {
QuestLine = 41901,
Mission01 = 41902,
- GarlicBread = 41903,
+ -- unused GarlicBread = 41903,
Mission02 = 41904,
Cookies = {
Serafin = 41905,
diff --git a/data-otservbr-global/lib/others/vip_system.lua b/data-otservbr-global/lib/others/vip_system.lua
index 6ca6de7d204..5a393157c8c 100644
--- a/data-otservbr-global/lib/others/vip_system.lua
+++ b/data-otservbr-global/lib/others/vip_system.lua
@@ -3,7 +3,7 @@ local config = {
activationMessageType = MESSAGE_EVENT_ADVANCE,
expirationMessage = "Your VIP days ran out.",
- expirationMessageType = MESSAGE_ADMINISTRADOR,
+ expirationMessageType = MESSAGE_ADMINISTRATOR,
outfits = {},
mounts = {},
diff --git a/data-otservbr-global/migrations/41.lua b/data-otservbr-global/migrations/41.lua
index 179ac18b574..15eb1d88e99 100644
--- a/data-otservbr-global/migrations/41.lua
+++ b/data-otservbr-global/migrations/41.lua
@@ -3,8 +3,8 @@ function onUpdateDatabase()
db.query([[
ALTER TABLE `players`
- MODIFY `xpboost_stamina` smallint(5) UNSIGNED DEFAULT NULL,
- MODIFY `xpboost_value` tinyint(4) UNSIGNED DEFAULT NULL
+ MODIFY `xpboost_stamina` smallint(5) UNSIGNED DEFAULT NULL,
+ MODIFY `xpboost_value` tinyint(4) UNSIGNED DEFAULT NULL
]])
return true
diff --git a/data-otservbr-global/migrations/43.lua b/data-otservbr-global/migrations/43.lua
index 86a6d8ffec1..1464703c96e 100644
--- a/data-otservbr-global/migrations/43.lua
+++ b/data-otservbr-global/migrations/43.lua
@@ -1,3 +1,12 @@
function onUpdateDatabase()
- return false -- true = There are others migrations file | false = this is the last migration file
+ logger.info("Updating database to version 43 (feat frags_limit, payment and duration_days in guild wars)")
+
+ db.query([[
+ ALTER TABLE `guild_wars`
+ ADD `frags_limit` smallint(4) UNSIGNED NOT NULL DEFAULT '0',
+ ADD `payment` bigint(13) UNSIGNED NOT NULL DEFAULT '0',
+ ADD `duration_days` tinyint(3) UNSIGNED NOT NULL DEFAULT '0'
+ ]])
+
+ return true
end
diff --git a/data-otservbr-global/migrations/44.lua b/data-otservbr-global/migrations/44.lua
new file mode 100644
index 00000000000..86a6d8ffec1
--- /dev/null
+++ b/data-otservbr-global/migrations/44.lua
@@ -0,0 +1,3 @@
+function onUpdateDatabase()
+ return false -- true = There are others migrations file | false = this is the last migration file
+end
diff --git a/data-otservbr-global/monster/quests/the_secret_library/bosses/grand_master_oberon_functions.lua b/data-otservbr-global/monster/quests/the_secret_library/bosses/grand_master_oberon_functions.lua
index 86714879320..af9c6f0218a 100644
--- a/data-otservbr-global/monster/quests/the_secret_library/bosses/grand_master_oberon_functions.lua
+++ b/data-otservbr-global/monster/quests/the_secret_library/bosses/grand_master_oberon_functions.lua
@@ -24,7 +24,7 @@ GrandMasterOberonResponses = {
[6] = { msg = "Excuse me but I still do not get the message!", msg2 = oberonOthersMessages[2] },
[7] = { msg = "Dare strike up a Minnesang and you will receive your last accolade!", msg2 = oberonOthersMessages[1] },
[8] = { msg = "Then why are we fighting alone right now?", msg2 = oberonOthersMessages[2] },
- [9] = { msg = "SEHWO ASIMO, TOLIDO ESD", msg2 = oberonOthersMessages[2] },
+ [9] = { msg = "SEHWO ASIMO, TOLIDO ESD!", msg2 = oberonOthersMessages[2] },
}
GrandMasterOberonConfig = {
diff --git a/data-otservbr-global/npc/julius.lua b/data-otservbr-global/npc/julius.lua
index ac3c660a29b..47e8e123760 100644
--- a/data-otservbr-global/npc/julius.lua
+++ b/data-otservbr-global/npc/julius.lua
@@ -83,7 +83,6 @@ local function creatureSayCallback(npc, creature, type, message)
end
elseif player:getStorageValue(BloodBrothers.Mission01) == 3 then
npcHandler:say("Let me check - yes indeed, there's garlic in it. Now eat one, in front of my eyes. Right now! Say '{aaah}' when you've chewed it all down so that I can see you're not hiding it!", npc, creature)
- player:setStorageValue(BloodBrothers.GarlicBread, 0)
npcHandler:setTopic(playerId, 4)
elseif player:getStorageValue(BloodBrothers.Mission01) == 4 and player:getStorageValue(BloodBrothers.Mission02) < 0 then
npcHandler:say("So, are you ready for your first real task?", npc, creature)
@@ -164,7 +163,7 @@ local function creatureSayCallback(npc, creature, type, message)
end
end
elseif MsgContains(message, "aaah") then
- if npcHandler:getTopic(playerId) == 4 and player:getStorageValue(BloodBrothers.GarlicBread) == 1 then
+ if npcHandler:getTopic(playerId) == 4 and player:removeItem(8194, 1) then
npcHandler:say("Very well. I think I can trust you now. Sorry that I had to put you through this embarassing procedure, but I'm sure you understand. So, are you ready for your first real task?", npc, creature)
player:setStorageValue(BloodBrothers.Mission01, 4)
npcHandler:setTopic(playerId, 5)
diff --git a/data-otservbr-global/scripts/actions/other/dice.lua b/data-otservbr-global/scripts/actions/other/dice.lua
deleted file mode 100644
index bd0c6c8f31a..00000000000
--- a/data-otservbr-global/scripts/actions/other/dice.lua
+++ /dev/null
@@ -1,18 +0,0 @@
-local dice = Action()
-
-function dice.onUse(player, item, fromPosition, target, toPosition, isHotkey)
- local dicePosition = item:getPosition()
- local value = math.random(6)
- local isInGhostMode = player:isInGhostMode()
-
- dicePosition:sendMagicEffect(CONST_ME_CRAPS, isInGhostMode and player)
- local spectators = Game.getSpectators(dicePosition, false, true, 3, 3)
- for i = 1, #spectators do
- player:say(player:getName() .. " rolled a " .. value .. ".", TALKTYPE_MONSTER_SAY, isInGhostMode, spectators[i], dicePosition)
- end
- item:transform(5791 + value)
- return true
-end
-
-dice:id(5792, 5793, 5794, 5795, 5796, 5797)
-dice:register()
diff --git a/data-otservbr-global/scripts/actions/other/voodoo_doll.lua b/data-otservbr-global/scripts/actions/other/voodoo_doll.lua
deleted file mode 100644
index 1b77081ee1c..00000000000
--- a/data-otservbr-global/scripts/actions/other/voodoo_doll.lua
+++ /dev/null
@@ -1,21 +0,0 @@
-local voodooDoll = Action()
-
-function voodooDoll.onUse(player, item, fromPosition, target, toPosition, isHotkey)
- if target.itemid ~= 1 or target.type ~= THING_TYPE_PLAYER then
- return false
- end
-
- local text = ""
- if math.random(100) <= 5 then
- text = "You concentrate on your victim and hit the needle in the doll."
- player:addAchievement("Dark Voodoo Priest")
- toPosition:sendMagicEffect(CONST_ME_DRAWBLOOD, player)
- else
- text = "You concentrate on your victim, hit the needle in the doll.......but nothing happens."
- end
- player:say(text, TALKTYPE_MONSTER_SAY, false, player)
- return true
-end
-
-voodooDoll:id(3002)
-voodooDoll:register()
diff --git a/data-otservbr-global/scripts/actions/rookgaard/rapier_quest.lua b/data-otservbr-global/scripts/actions/rookgaard/rapier_quest.lua
new file mode 100644
index 00000000000..20e6697d2f7
--- /dev/null
+++ b/data-otservbr-global/scripts/actions/rookgaard/rapier_quest.lua
@@ -0,0 +1,15 @@
+local rapierQuest = Action()
+
+function rapierQuest.onUse(player, item, fromPosition, target, toPosition, isHotkey)
+ local rewardId = 3272
+ if not player:canGetReward(rewardId, "rapier") then
+ return true
+ end
+ player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have found a rapier.")
+ player:addItem(rewardId, 1)
+ player:questKV("rapier"):set("completed", true)
+ return true
+end
+
+rapierQuest:uid(14042)
+rapierQuest:register()
diff --git a/data-otservbr-global/scripts/creaturescripts/others/advance_save.lua b/data-otservbr-global/scripts/creaturescripts/others/advance_save.lua
deleted file mode 100644
index 8bd6fd2fd06..00000000000
--- a/data-otservbr-global/scripts/creaturescripts/others/advance_save.lua
+++ /dev/null
@@ -1,32 +0,0 @@
-local config = {
- heal = true,
- save = true,
- effect = false,
-}
-
-local advanceSave = CreatureEvent("AdvanceSave")
-
-function advanceSave.onAdvance(player, skill, oldLevel, newLevel)
- if skill ~= SKILL_LEVEL or newLevel <= oldLevel then
- return true
- end
-
- if config.effect then
- player:getPosition():sendMagicEffect(math.random(CONST_ME_FIREWORK_YELLOW, CONST_ME_FIREWORK_BLUE))
- player:say("LEVEL UP!", TALKTYPE_MONSTER_SAY)
- end
-
- if config.heal then
- player:addHealth(player:getMaxHealth())
- end
-
- if config.save then
- player:save()
- end
-
- player:getFinalLowLevelBonus()
-
- return true
-end
-
-advanceSave:register()
diff --git a/data-otservbr-global/scripts/creaturescripts/others/modal_window_helper.lua b/data-otservbr-global/scripts/creaturescripts/others/modal_window_helper.lua
deleted file mode 100644
index d2651af1e69..00000000000
--- a/data-otservbr-global/scripts/creaturescripts/others/modal_window_helper.lua
+++ /dev/null
@@ -1,35 +0,0 @@
-local creatureEvent = CreatureEvent("modalWindowHelper")
-
-function creatureEvent.onModalWindow(player, modalWindowId, buttonId, choiceId)
- local playerId = player:getId()
- local modalWindows = ModalWindows[playerId]
- if not modalWindows then
- return true
- end
-
- local modalWindow = modalWindows[modalWindowId]
- if not modalWindow then
- return true
- end
-
- local button = modalWindow.buttons[buttonId] or {}
- local choice = modalWindow.choices[choiceId] or {}
- if button.callback then
- button.callback(player, button, choice)
- elseif choice.callback then
- choice.callback(player, button, choice)
- elseif modalWindow.defaultCallback then
- modalWindow.defaultCallback(player, button, choice)
- end
-
- modalWindow.using = modalWindow.using - 1
- if modalWindow.using == 0 then
- modalWindows[modalWindowId] = nil
- if not next(modalWindows) then
- ModalWindows[playerId] = nil
- end
- end
- return true
-end
-
-creatureEvent:register()
diff --git a/data-otservbr-global/scripts/creaturescripts/others/player_death.lua b/data-otservbr-global/scripts/creaturescripts/others/player_death.lua
index 9e8bfbeca34..b848235ebae 100644
--- a/data-otservbr-global/scripts/creaturescripts/others/player_death.lua
+++ b/data-otservbr-global/scripts/creaturescripts/others/player_death.lua
@@ -84,24 +84,52 @@ function playerDeath.onDeath(player, corpse, killer, mostDamageKiller, unjustifi
if byPlayer == 1 then
local targetGuild = player:getGuild()
- targetGuild = targetGuild and targetGuild:getId() or 0
- if targetGuild ~= 0 then
+ local targetGuildId = targetGuild and targetGuild:getId() or 0
+ if targetGuildId ~= 0 then
local killerGuild = killer:getGuild()
- killerGuild = killerGuild and killerGuild:getId() or 0
- if killerGuild ~= 0 and targetGuild ~= killerGuild and isInWar(player:getId(), killer.uid) then
+ local killerGuildId = killerGuild and killerGuild:getId() or 0
+ if killerGuildId ~= 0 and targetGuildId ~= killerGuildId and isInWar(player:getId(), killer:getId()) then
local warId = false
resultId = db.storeQuery("SELECT `id` FROM `guild_wars` WHERE `status` = 1 AND \z
- ((`guild1` = " .. killerGuild .. " AND `guild2` = " .. targetGuild .. ") OR \z
- (`guild1` = " .. targetGuild .. " AND `guild2` = " .. killerGuild .. "))")
- if resultId ~= false then
+ ((`guild1` = " .. killerGuildId .. " AND `guild2` = " .. targetGuildId .. ") OR \z
+ (`guild1` = " .. targetGuildId .. " AND `guild2` = " .. killerGuildId .. "))")
+ if resultId then
warId = Result.getNumber(resultId, "id")
Result.free(resultId)
end
- if warId ~= false then
+ if warId then
+ local playerName = player:getName()
db.asyncQuery("INSERT INTO `guildwar_kills` (`killer`, `target`, `killerguild`, `targetguild`, `time`, `warid`) \z
- VALUES (" .. db.escapeString(killerName) .. ", " .. db.escapeString(player:getName()) .. ", " .. killerGuild .. ", \z
- " .. targetGuild .. ", " .. os.time() .. ", " .. warId .. ")")
+ VALUES (" .. db.escapeString(killerName) .. ", " .. db.escapeString(playerName) .. ", " .. killerGuildId .. ", \z
+ " .. targetGuildId .. ", " .. os.time() .. ", " .. warId .. ")")
+
+ resultId = db.storeQuery("SELECT `guild_wars`.`id`, `guild_wars`.`frags_limit`, (SELECT COUNT(1) FROM `guildwar_kills` \z
+ WHERE `guildwar_kills`.`warid` = `guild_wars`.`id` AND `guildwar_kills`.`killerguild` = `guild_wars`.`guild1`) AS guild1_kills, \z
+ (SELECT COUNT(1) FROM `guildwar_kills` WHERE `guildwar_kills`.`warid` = `guild_wars`.`id` AND `guildwar_kills`.`killerguild` = `guild_wars`.`guild2`) AS guild2_kills \z
+ FROM `guild_wars` WHERE (`guild1` = " .. killerGuildId .. " OR `guild2` = " .. killerGuildId .. ") 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 frags_limit = Result.getNumber(resultId, "frags_limit")
+ Result.free(resultId)
+
+ local members = killerGuild:getMembersOnline()
+ for i = 1, #members do
+ members[i]:sendChannelMessage(members[i], string.format("%s was killed by %s. The new score is: %s %d:%d %s (frags limit: %d)", playerName, killerName, targetGuild:getName(), guild1_kills, guild2_kills, killerGuild:getName(), frags_limit), TALKTYPE_CHANNEL_R1, CHANNEL_GUILD)
+ end
+
+ local enemyMembers = targetGuild:getMembersOnline()
+ for i = 1, #enemyMembers do
+ enemyMembers[i]:sendChannelMessage(enemyMembers[i], string.format("%s was killed by %s. The new score is: %s %d:%d %s (frags limit: %d)", playerName, killerName, targetGuild:getName(), guild1_kills, guild2_kills, killerGuild:getName(), frags_limit), TALKTYPE_CHANNEL_R1, CHANNEL_GUILD)
+ end
+
+ if guild1_kills >= frags_limit or guild2_kills >= frags_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.", killerGuild:getName(), targetGuild:getName()))
+ end
+ end
end
end
end
diff --git a/data-otservbr-global/scripts/globalevents/others/guild_war.lua b/data-otservbr-global/scripts/globalevents/others/guild_war.lua
index f34828b1fa7..41238755494 100644
--- a/data-otservbr-global/scripts/globalevents/others/guild_war.lua
+++ b/data-otservbr-global/scripts/globalevents/others/guild_war.lua
@@ -1,9 +1,10 @@
local guildWar = GlobalEvent("guildwar")
+
function guildWar.onThink(interval)
local time = os.time()
- db.query("UPDATE `guild_wars` SET `status` = 4, `ended` = " .. time .. " WHERE `status` = 1 AND (`started` + 5 * 60 * 60) < " .. time)
+ db.query("UPDATE `guild_wars` SET `status` = 4, `ended` = " .. time .. " WHERE `status` = 1 AND `ended` != 0 AND `ended` < " .. time)
return true
end
-guildWar:interval(100000)
+guildWar:interval(60000)
guildWar:register()
diff --git a/data-otservbr-global/scripts/globalevents/others/online_record.lua b/data-otservbr-global/scripts/globalevents/others/online_record.lua
deleted file mode 100644
index 9d7bb82e284..00000000000
--- a/data-otservbr-global/scripts/globalevents/others/online_record.lua
+++ /dev/null
@@ -1,7 +0,0 @@
-local playerrecord = GlobalEvent("playerrecord")
-function playerrecord.onRecord(current, old)
- addEvent(Game.broadcastMessage, 150, "New record: " .. current .. " players online.", MESSAGE_EVENT_ADVANCE)
- return true
-end
-
-playerrecord:register()
diff --git a/data-otservbr-global/scripts/movements/others/tiles.lua b/data-otservbr-global/scripts/movements/others/tiles.lua
deleted file mode 100644
index b797f0380a3..00000000000
--- a/data-otservbr-global/scripts/movements/others/tiles.lua
+++ /dev/null
@@ -1,87 +0,0 @@
-local increasing = { [419] = 420, [431] = 430, [452] = 453, [563] = 564, [549] = 562, [10145] = 10146 }
-local decreasing = { [420] = 419, [430] = 431, [453] = 452, [564] = 563, [562] = 549, [10146] = 10145 }
-
--- onStepIn
-local tiles = MoveEvent()
-
-function tiles.onStepIn(creature, item, position, fromPosition)
- if not increasing[item.itemid] then
- return true
- end
-
- local player = creature:getPlayer()
- if not player or player:isInGhostMode() then
- return true
- end
-
- item:transform(increasing[item.itemid])
-
- if item.actionid >= 1000 then
- if player:getLevel() < item.actionid - 1000 then
- player:teleportTo(fromPosition, false)
- position:sendMagicEffect(CONST_ME_MAGIC_BLUE)
- player:sendTextMessage(MESSAGE_FAILURE, "The tile seems to be protected against unwanted intruders.")
- end
- return true
- end
-
- if position:getTile():hasFlag(TILESTATE_PROTECTIONZONE) then
- for _, direction in ipairs(DIRECTIONS_TABLE) do
- local playerPosition = player:getPosition()
- playerPosition:getNextPosition(direction)
- local depotItem = playerPosition:getTile():getItemByType(ITEM_TYPE_DEPOT)
-
- if depotItem ~= nil then
- local depotItems = 0
- for id = 1, configManager.getNumber(configKeys.DEPOT_BOXES) do
- depotItems = depotItems + player:getDepotChest(id, true):getItemHoldingCount()
- end
-
- player:sendTextMessage(MESSAGE_FAILURE, "Your depot contains " .. depotItems .. " item" .. (depotItems > 1 and "s." or ".") .. "\
- Your supply stash contains " .. player:getStashCount() .. " item" .. (player:getStashCount() > 1 and "s." or "."))
- player:setSpecialContainersAvailable(true, true, true)
- return true
- end
- end
- end
-
- if item.actionid ~= 0 and player:getStorageValue(item.actionid) <= 0 then
- player:teleportTo(fromPosition, false)
- position:sendMagicEffect(CONST_ME_MAGIC_BLUE)
- player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "The tile seems to be protected against unwanted intruders.")
- return true
- end
-end
-
-tiles:type("stepin")
-
-for index, value in pairs(increasing) do
- tiles:id(index)
-end
-
-tiles:register()
-
-tiles = MoveEvent()
-
-function tiles.onStepOut(creature, item, position, fromPosition)
- if not decreasing[item.itemid] then
- return false
- end
-
- local player = creature:getPlayer()
- if not player or player:isInGhostMode() then
- return true
- end
-
- item:transform(decreasing[item.itemid])
- player:setSpecialContainersAvailable(false, false, false)
- return true
-end
-
-tiles:type("stepout")
-
-for index, value in pairs(decreasing) do
- tiles:id(index)
-end
-
-tiles:register()
diff --git a/data-otservbr-global/startup/tables/chest.lua b/data-otservbr-global/startup/tables/chest.lua
index f5049f93f61..228e9ba2976 100644
--- a/data-otservbr-global/startup/tables/chest.lua
+++ b/data-otservbr-global/startup/tables/chest.lua
@@ -1186,4 +1186,8 @@ ChestUnique = {
itemId = 11810,
itemPos = { x = 33195, y = 31765, z = 1 },
},
+ [14042] = {
+ itemId = 2473,
+ itemPos = { x = 32099, y = 32198, z = 9 },
+ },
}
diff --git a/data/items/items.xml b/data/items/items.xml
index faa2edfce01..097081b8dd3 100644
--- a/data/items/items.xml
+++ b/data/items/items.xml
@@ -1252,7 +1252,7 @@
-
+
-
@@ -1327,7 +1327,7 @@
-
+
-
@@ -1386,7 +1386,7 @@
-
+
-
@@ -1401,7 +1401,7 @@
-
+
-
@@ -1490,7 +1490,7 @@
-
+
-
@@ -1565,7 +1565,7 @@
-
+
-
@@ -1624,7 +1624,7 @@
-
+
-
@@ -1639,7 +1639,7 @@
-
+
-
@@ -2267,7 +2267,7 @@
-
+
-
@@ -2342,7 +2342,7 @@
-
+
-
@@ -2401,7 +2401,7 @@
-
+
-
@@ -2416,7 +2416,7 @@
-
+
-
@@ -2488,7 +2488,7 @@
-
+
-
@@ -2567,7 +2567,7 @@
-
+
-
@@ -2626,7 +2626,7 @@
-
+
-
@@ -2641,7 +2641,7 @@
-
+
-
@@ -3113,7 +3113,6 @@
-
-
-
@@ -8267,7 +8266,7 @@
-
+
-
@@ -8281,7 +8280,7 @@
-
+
-
@@ -8317,7 +8316,7 @@
-
+
-
@@ -8398,7 +8397,7 @@
-
+
-
@@ -8439,7 +8438,7 @@
-
+
-
@@ -8461,7 +8460,7 @@
-
+
-
@@ -8500,7 +8499,7 @@
-
+
-
@@ -8608,7 +8607,7 @@
-
+
-
@@ -8701,7 +8700,7 @@
-
+
-
@@ -8772,7 +8771,7 @@
-
+
-
@@ -8794,7 +8793,7 @@
-
+
-
@@ -8817,7 +8816,7 @@
-
+
-
@@ -8964,7 +8963,7 @@
-
+
-
@@ -8978,7 +8977,7 @@
-
+
-
@@ -8999,7 +8998,7 @@
-
+
-
@@ -9074,7 +9073,7 @@
-
+
-
@@ -9218,7 +9217,7 @@
-
+
-
@@ -9260,7 +9259,7 @@
-
+
-
@@ -9282,7 +9281,7 @@
-
+
-
@@ -9339,7 +9338,7 @@
-
+
-
@@ -9417,7 +9416,7 @@
-
+
-
@@ -9461,7 +9460,7 @@
-
+
-
@@ -9521,7 +9520,7 @@
-
+
-
@@ -9568,7 +9567,7 @@
-
+
-
@@ -9580,7 +9579,7 @@
-
+
-
@@ -10827,7 +10826,7 @@
-
+
-
@@ -15647,7 +15646,7 @@
-
+
-
@@ -17989,7 +17988,7 @@
-
+
-
@@ -18117,7 +18116,7 @@
-
+
-
@@ -19369,7 +19368,7 @@
-
+
-
@@ -19392,7 +19391,7 @@
-
+
-
@@ -19428,7 +19427,7 @@
-
+
-
@@ -19508,7 +19507,7 @@
-
+
-
@@ -19594,7 +19593,7 @@
-
+
-
@@ -19616,7 +19615,7 @@
-
+
-
@@ -19674,7 +19673,7 @@
-
+
-
@@ -19696,7 +19695,7 @@
-
+
-
@@ -19739,7 +19738,7 @@
-
+
-
@@ -19762,7 +19761,7 @@
-
+
-
@@ -19784,7 +19783,7 @@
-
+
-
@@ -19887,7 +19886,7 @@
-
+
-
@@ -19910,7 +19909,7 @@
-
+
-
@@ -20085,7 +20084,7 @@
-
+
-
@@ -20106,7 +20105,7 @@
-
+
-
@@ -20120,7 +20119,7 @@
-
+
-
@@ -20141,7 +20140,7 @@
-
+
-
@@ -20156,7 +20155,7 @@
-
+
-
@@ -20172,7 +20171,7 @@
-
+
-
@@ -20322,7 +20321,7 @@
-
+
-
@@ -20364,7 +20363,7 @@
-
+
-
@@ -20421,7 +20420,7 @@
-
+
-
@@ -20435,7 +20434,7 @@
-
+
-
@@ -20477,7 +20476,7 @@
-
+
-
@@ -20499,7 +20498,7 @@
-
+
-
@@ -20514,7 +20513,7 @@
-
+
-
@@ -21456,7 +21455,7 @@
-
+
-
@@ -21479,7 +21478,7 @@
-
+
-
@@ -21503,7 +21502,7 @@
-
+
-
@@ -21526,7 +21525,7 @@
-
+
-
@@ -21548,7 +21547,7 @@
-
+
-
@@ -21572,7 +21571,7 @@
-
+
-
@@ -21596,7 +21595,7 @@
-
+
-
@@ -21611,7 +21610,7 @@
-
+
-
@@ -21634,7 +21633,7 @@
-
+
-
@@ -21649,7 +21648,7 @@
-
+
-
@@ -22373,7 +22372,7 @@
-
+
-
@@ -22429,7 +22428,7 @@
-
+
-
@@ -22484,7 +22483,7 @@
-
+
-
@@ -25285,7 +25284,7 @@
-
+
-
@@ -25373,7 +25372,7 @@
-
+
-
@@ -25396,7 +25395,7 @@
-
+
-
@@ -27223,7 +27222,7 @@
-
+
-
@@ -27238,7 +27237,7 @@
-
+
-
@@ -27274,7 +27273,7 @@
-
+
-
@@ -27296,7 +27295,7 @@
-
+
-
@@ -27376,7 +27375,7 @@
-
+
-
@@ -28881,7 +28880,7 @@
-
+
-
@@ -30741,7 +30740,7 @@
-
+
-
@@ -30884,7 +30883,7 @@
-
+
-
@@ -31910,7 +31909,7 @@
-
+
-
@@ -32300,7 +32299,7 @@
-
+
-
@@ -32657,7 +32656,7 @@
-
+
-
@@ -32674,7 +32673,7 @@
-
+
-
@@ -32936,7 +32935,7 @@
-
+
-
@@ -34608,7 +34607,7 @@
-
+
-
@@ -34632,7 +34631,7 @@
-
+
-
@@ -36066,7 +36065,7 @@
-
+
-
@@ -39422,7 +39421,7 @@
-
+
-
@@ -39487,7 +39486,7 @@
-
+
-
@@ -39625,6 +39624,12 @@
+
+
+
+
+
+
-
@@ -39953,7 +39958,7 @@
-
+
-
@@ -39975,7 +39980,7 @@
-
+
-
@@ -39998,7 +40003,7 @@
-
+
-
@@ -40073,7 +40078,7 @@
-
+
-
@@ -40095,7 +40100,7 @@
-
+
-
@@ -40118,7 +40123,7 @@
-
+
-
@@ -40193,7 +40198,7 @@
-
+
-
@@ -40215,7 +40220,7 @@
-
+
-
@@ -40238,7 +40243,7 @@
-
+
-
@@ -40255,7 +40260,7 @@
-
+
-
@@ -40279,7 +40284,7 @@
-
+
-
@@ -40304,7 +40309,7 @@
-
+
-
@@ -40321,7 +40326,7 @@
-
+
-
@@ -40345,7 +40350,7 @@
-
+
-
@@ -40370,7 +40375,7 @@
-
+
-
@@ -41953,7 +41958,7 @@
-
+
-
@@ -41989,7 +41994,7 @@
-
+
-
@@ -42021,7 +42026,7 @@
-
+
-
@@ -42039,7 +42044,7 @@
-
+
-
@@ -42057,7 +42062,7 @@
-
+
@@ -42211,7 +42216,7 @@
-
+ ogre klubb
@@ -44335,7 +44340,7 @@ Awarded by TibiaMisterios.com.br"/>
-
+
-
@@ -44349,7 +44354,7 @@ Awarded by TibiaMisterios.com.br"/>
-
+
@@ -45194,7 +45199,7 @@ Awarded by TibiaMisterios.com.br"/>
-
+
-
@@ -45688,7 +45693,7 @@ Awarded by TibiaMisterios.com.br"/>
-
+
-
@@ -45712,7 +45717,7 @@ Awarded by TibiaMisterios.com.br"/>
-
+
-
@@ -48684,8 +48689,7 @@ hands of its owner. Granted by TibiaRoyal.com"/>
-
-
+
-
@@ -51745,7 +51749,7 @@ TibiaTome.com"/>
-
+
-
@@ -51786,7 +51790,7 @@ TibiaTome.com"/>
-
+
-
@@ -51827,7 +51831,7 @@ TibiaTome.com"/>
-
+
-
@@ -51850,7 +51854,7 @@ TibiaTome.com"/>
-
+
-
@@ -51873,7 +51877,7 @@ TibiaTome.com"/>
-
+
-
@@ -54202,7 +54206,7 @@ TibiaTome.com"/>
-
+
-
@@ -54307,7 +54311,7 @@ TibiaTome.com"/>
-
+
-
@@ -54331,7 +54335,7 @@ TibiaTome.com"/>
-
+
-
@@ -55251,7 +55255,7 @@ TibiaTome.com"/>
-
+
-
@@ -55469,7 +55473,7 @@ TibiaTome.com"/>
-
+
-
@@ -55513,7 +55517,7 @@ TibiaTome.com"/>
-
+
-
@@ -57316,7 +57320,7 @@ TibiaTome.com"/>
-
+
-
@@ -59168,7 +59172,7 @@ TibiaTome.com"/>
-
+
-
@@ -59309,7 +59313,7 @@ TibiaTome.com"/>
-
+
-
@@ -61756,7 +61760,7 @@ TibiaTome.com"/>
-
+
-
@@ -64022,7 +64026,7 @@ TibiaTome.com"/>
-
+
-
@@ -64074,7 +64078,7 @@ TibiaTome.com"/>
-
+
-
@@ -64126,7 +64130,7 @@ TibiaTome.com"/>
-
+
-
@@ -64154,7 +64158,7 @@ TibiaTome.com"/>
-
+
-
@@ -64182,7 +64186,7 @@ TibiaTome.com"/>
-
+
-
@@ -64599,7 +64603,7 @@ TibiaTome.com"/>
-
+
-
@@ -65924,7 +65928,7 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/>
-
+
-
@@ -65996,7 +66000,7 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/>
-
+
-
@@ -67394,7 +67398,7 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/>
-
+
-
@@ -67419,7 +67423,7 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/>
-
+
-
@@ -67443,7 +67447,7 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/>
-
+
-
@@ -67492,7 +67496,7 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/>
-
+
-
@@ -67517,7 +67521,7 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/>
-
+
-
@@ -67563,7 +67567,7 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/>
-
+
-
@@ -67590,7 +67594,7 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/>
-
+
-
@@ -71641,7 +71645,7 @@ Granted by TibiaGoals.com"/>
-
+
-
@@ -75310,7 +75314,7 @@ Granted by TibiaGoals.com"/>
-
+
-
@@ -75335,7 +75339,7 @@ Granted by TibiaGoals.com"/>
-
+
-
@@ -75360,7 +75364,7 @@ Granted by TibiaGoals.com"/>
-
+
-
@@ -75385,7 +75389,7 @@ Granted by TibiaGoals.com"/>
-
+
-
@@ -75410,7 +75414,7 @@ Granted by TibiaGoals.com"/>
-
+
-
@@ -75435,7 +75439,7 @@ Granted by TibiaGoals.com"/>
-
+
-
@@ -75478,7 +75482,7 @@ Granted by TibiaGoals.com"/>
-
+
-
@@ -75506,7 +75510,7 @@ Granted by TibiaGoals.com"/>
-
+
-
@@ -75534,7 +75538,7 @@ Granted by TibiaGoals.com"/>
-
+
-
@@ -75562,7 +75566,7 @@ Granted by TibiaGoals.com"/>
-
+
-
diff --git a/data/libs/functions/modal_window_helper.lua b/data/libs/functions/modal_window_helper.lua
index 9de5e394cc5..ed169805b06 100644
--- a/data/libs/functions/modal_window_helper.lua
+++ b/data/libs/functions/modal_window_helper.lua
@@ -209,7 +209,7 @@ function ModalWindow:sendToPlayer(player)
local playerId = player:getId()
ModalWindows[playerId] = ModalWindows[playerId] or {}
ModalWindows[playerId][self.modalWindowId] = self
- player:registerEvent("modalWindowHelper")
+ player:registerEvent("ModalWindowHelper")
self.using = self.using + 1
return modalWindow:sendToPlayer(player)
end
diff --git a/data/libs/functions/player.lua b/data/libs/functions/player.lua
index 2662db60d11..03e88d7ccca 100644
--- a/data/libs/functions/player.lua
+++ b/data/libs/functions/player.lua
@@ -966,3 +966,37 @@ do
return true
end
end
+
+function Player:questKV(questName)
+ return self:kv():scoped("quests"):scoped(questName)
+end
+
+function Player:canGetReward(rewardId, questName)
+ if self:questKV(questName):get("completed") then
+ self:sendTextMessage(MESSAGE_EVENT_ADVANCE, "The box is empty.")
+ return false
+ end
+
+ local rewardItem = ItemType(rewardId)
+ if not rewardItem then
+ self:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Reward item is wrong, please contact an administrator.")
+ return false
+ end
+
+ local itemWeight = rewardItem:getWeight() / 100
+ local baseMessage = "You have found a " .. rewardItem:getName()
+ local backpack = self:getSlotItem(CONST_SLOT_BACKPACK)
+ if not backpack or backpack:getEmptySlots(true) < 1 then
+ baseMessage = baseMessage .. ", but you have no room to take it."
+ self:sendTextMessage(MESSAGE_EVENT_ADVANCE, baseMessage)
+ return false
+ end
+
+ if (self:getFreeCapacity() / 100) < itemWeight then
+ baseMessage = baseMessage .. ". Weighing " .. itemWeight .. " oz, it is too heavy for you to carry."
+ self:sendTextMessage(MESSAGE_EVENT_ADVANCE, baseMessage)
+ return false
+ end
+
+ return true
+end
diff --git a/data/libs/functions/revscriptsys.lua b/data/libs/functions/revscriptsys.lua
index 5a31ec086f3..84b8275e3ce 100644
--- a/data/libs/functions/revscriptsys.lua
+++ b/data/libs/functions/revscriptsys.lua
@@ -108,7 +108,7 @@ do
local function EventCallbackNewIndex(self, key, value)
local func = eventCallbacks[key]
if func and type(func) == "function" then
- logger.debug("[Registering EventCallback: {}", key)
+ logger.trace("[Registering EventCallback: {}", key)
func(self, value)
self:type(key)
else
diff --git a/data-otservbr-global/scripts/actions/other/anniversary_reward_boxes.lua b/data/scripts/actions/items/anniversary_reward_boxes.lua
similarity index 92%
rename from data-otservbr-global/scripts/actions/other/anniversary_reward_boxes.lua
rename to data/scripts/actions/items/anniversary_reward_boxes.lua
index 8327222a570..d5d36bb7455 100644
--- a/data-otservbr-global/scripts/actions/other/anniversary_reward_boxes.lua
+++ b/data/scripts/actions/items/anniversary_reward_boxes.lua
@@ -55,22 +55,24 @@ local config = {
}
local rewardBox = Action()
+
function rewardBox.onUse(player, item, fromPosition, itemEx, toPosition)
local box = config[item:getId()]
- if not box or not player then
+ if not box then
return false
end
- for i = 1, #box do
- if box[i] then
- player:addItem(box[i].id, box[i].count)
- player:getPosition():sendMagicEffect(CONST_ME_PRISMATIC_SPARK)
- end
+
+ for _, reward in ipairs(box) do
+ player:addItem(reward.id, reward.count)
+ player:getPosition():sendMagicEffect(CONST_ME_PRISMATIC_SPARK)
end
+
item:remove()
return true
end
-for index, value in pairs(config) do
+for index, _ in pairs(config) do
rewardBox:id(index)
end
+
rewardBox:register()
diff --git a/data/scripts/actions/items/die.lua b/data/scripts/actions/items/die.lua
new file mode 100644
index 00000000000..661926e79ea
--- /dev/null
+++ b/data/scripts/actions/items/die.lua
@@ -0,0 +1,36 @@
+local die = Action()
+
+function die.onUse(player, item, fromPosition, target, toPosition, isHotkey)
+ local position = item:getPosition()
+ local value = math.random(1, 6)
+ local isInGhostMode = player:isInGhostMode()
+
+ if not isInGhostMode then
+ position:sendMagicEffect(CONST_ME_CRAPS)
+
+ local spectators = Game.getSpectators(position, false, true, 3, 3)
+ for _, spectator in ipairs(spectators) do
+ player:say(player:getName() .. " rolled a " .. value .. ".", TALKTYPE_MONSTER_SAY, isInGhostMode, spectator, position)
+ end
+ end
+
+ if value == 6 then
+ local rolledSixCount = player:kv():get("die-rolled-six") or 0
+ player:kv():set("die-rolled-six", rolledSixCount + 1)
+
+ if rolledSixCount == 2 then
+ player:addAchievement("Number of the Beast")
+ end
+ else
+ player:kv():remove("die-rolled-six")
+ end
+
+ item:transform(5791 + value)
+ return true
+end
+
+for items = 5792, 5797 do
+ die:id(items)
+end
+
+die:register()
diff --git a/data-canary/scripts/actions/other/explosive_present.lua b/data/scripts/actions/items/explosive_present.lua
similarity index 81%
rename from data-canary/scripts/actions/other/explosive_present.lua
rename to data/scripts/actions/items/explosive_present.lua
index 33878ffda93..2ca4730decd 100644
--- a/data-canary/scripts/actions/other/explosive_present.lua
+++ b/data/scripts/actions/items/explosive_present.lua
@@ -3,9 +3,10 @@ local explosivePresent = Action()
function explosivePresent.onUse(player, item, fromPosition, target, toPosition, isHotkey)
player:say("KABOOOOOOOOOOM!", TALKTYPE_MONSTER_SAY)
player:getPosition():sendMagicEffect(CONST_ME_FIREAREA)
+ player:addAchievement("Joke's on You")
item:remove()
return true
end
-explosivePresent:id(3218)
+explosivePresent:id(906)
explosivePresent:register()
diff --git a/data-otservbr-global/scripts/actions/other/food.lua b/data/scripts/actions/items/foods.lua
similarity index 94%
rename from data-otservbr-global/scripts/actions/other/food.lua
rename to data/scripts/actions/items/foods.lua
index 3c6b5290fed..4a8072d163e 100644
--- a/data-otservbr-global/scripts/actions/other/food.lua
+++ b/data/scripts/actions/items/foods.lua
@@ -82,7 +82,6 @@ local foods = {
[8017] = { 5, "Munch." }, -- beetroot
[8019] = { 11, "Yum." }, -- chocolate cake
[8177] = { 7, "Slurp." }, -- yummy gummy worm
- [8194] = { 0, "Urgh.", CONST_ME_MAGIC_BLUE }, -- garlic bread
[8197] = { 5, "Crunch." }, -- bulb of garlic
[9537] = { 0, "Your head begins to feel better." }, -- headache pill
[10329] = { 15, "Yum." }, -- rice ball
@@ -124,29 +123,24 @@ local foods = {
}
local food = Action()
+
function food.onUse(player, item, fromPosition, target, toPosition, isHotkey)
- local bloodBrothersStorage = Storage.Quest.U8_4.BloodBrothers
local itemFood = foods[item.itemid]
- local effect = itemFood[3]
if not itemFood then
return false
end
+
local condition = player:getCondition(CONDITION_REGENERATION, CONDITIONID_DEFAULT)
if condition and math.floor(condition:getTicks() / 1000 + (itemFood[1] * 12)) >= 1200 then
player:sendTextMessage(MESSAGE_FAILURE, "You are full.")
return true
end
- if item.itemid == 8194 and player:getStorageValue(bloodBrothersStorage.GarlicBread) == 0 then
- player:setStorageValue(bloodBrothersStorage.GarlicBread, 1)
- end
+
player:feed(itemFood[1] * 12)
player:say(itemFood[2], TALKTYPE_MONSTER_SAY)
- item:remove(1)
player:updateSupplyTracker(item)
player:getPosition():sendSingleSoundEffect(SOUND_EFFECT_TYPE_ACTION_EAT, player:isInGhostMode() and nil or player)
- if effect then
- player:getPosition():sendMagicEffect(effect)
- end
+ item:remove(1)
return true
end
diff --git a/data/scripts/actions/items/garlic_bread.lua b/data/scripts/actions/items/garlic_bread.lua
new file mode 100644
index 00000000000..315dbbadd5c
--- /dev/null
+++ b/data/scripts/actions/items/garlic_bread.lua
@@ -0,0 +1,9 @@
+local garlicBread = Action()
+
+function garlicBread.onUse(player, item, fromPosition, target, toPosition, isHotkey)
+ player:say("After taking a small bite you decide that you don't want to eat that.", TALKTYPE_MONSTER_SAY)
+ return true
+end
+
+garlicBread:id(8194)
+garlicBread:register()
diff --git a/data/scripts/actions/items/scroll_of_ascension.lua b/data/scripts/actions/items/scroll_of_ascension.lua
index b763460c09b..1b32d0d994a 100644
--- a/data/scripts/actions/items/scroll_of_ascension.lua
+++ b/data/scripts/actions/items/scroll_of_ascension.lua
@@ -11,15 +11,10 @@ function scrollOfAscension.onUse(player, item, fromPosition, target, toPosition,
return true
end
- if math.random(10) > 1 then
- player:setMonsterOutfit("Demon", 30 * 10 * 1000)
- else
- player:setMonsterOutfit("Ferumbras", 30 * 10 * 1000)
- end
-
- player:setExhaustion("scroll-of-ascension", 60 * 60)
+ player:setMonsterOutfit(math.random(10) > 1 and "Demon" or "Ferumbras", 5 * 60 * 1000)
player:say("Magical sparks whirl around the scroll as you read it and then your appearance is changing.", TALKTYPE_MONSTER_SAY)
- player:getPosition():sendMagicEffect(CONST_ME_MAGIC_RED)
+ player:getPosition():sendMagicEffect(CONST_ME_HITBYFIRE)
+ player:setExhaustion("scroll-of-ascension", 60 * 60)
return true
end
diff --git a/data-canary/scripts/actions/other/voodoo_doll.lua b/data/scripts/actions/items/voodoo_doll.lua
similarity index 92%
rename from data-canary/scripts/actions/other/voodoo_doll.lua
rename to data/scripts/actions/items/voodoo_doll.lua
index 07940e32864..6e906e9b996 100644
--- a/data-canary/scripts/actions/other/voodoo_doll.lua
+++ b/data/scripts/actions/items/voodoo_doll.lua
@@ -8,6 +8,7 @@ function voodooDoll.onUse(player, item, fromPosition, target, toPosition, isHotk
local text = ""
if math.random(100) <= 5 then
text = "You concentrate on your victim and hit the needle in the doll."
+ player:addAchievement("Dark Voodoo Priest")
toPosition:sendMagicEffect(CONST_ME_DRAWBLOOD, player)
else
text = "You concentrate on your victim, hit the needle in the doll.......but nothing happens."
diff --git a/data-otservbr-global/scripts/actions/other/carpets.lua b/data/scripts/actions/objects/carpets.lua
similarity index 93%
rename from data-otservbr-global/scripts/actions/other/carpets.lua
rename to data/scripts/actions/objects/carpets.lua
index ccd69a7e446..6232eb2f1a1 100644
--- a/data-otservbr-global/scripts/actions/other/carpets.lua
+++ b/data/scripts/actions/objects/carpets.lua
@@ -170,23 +170,35 @@ function carpets.onUse(player, item, fp, target, toPosition, isHotkey)
end
local fromPosition = item:getPosition()
- local tile = Tile(fromPosition)
- if not fromPosition:getTile():getHouse() then
+ local tile = fromPosition:getTile()
+ if not tile then
player:sendTextMessage(MESSAGE_FAILURE, "You may use this only inside a house.")
- elseif tile:getItemCountById(item.itemid) == 1 then
+ return true
+ end
+
+ local house = tile:getHouse()
+ if not house then
+ player:sendTextMessage(MESSAGE_FAILURE, "You may use this only inside a house.")
+ return true
+ end
+
+ local itemCount = tile:getItemCountById(item.itemid)
+ if itemCount == 1 then
local topItem = tile:getTopTopItem()
if topItem and topItem:canReceiveAutoCarpet() then
item:remove()
return true
end
+
for k, v in pairs(carpetItems) do
- if tile:getItemCountById(k) > 0 and k ~= item.itemid then
+ if k ~= item.itemid and tile:getItemCountById(k) > 0 then
player:sendCancelMessage(Game.getReturnMessage(RETURNVALUE_NOTPOSSIBLE))
return true
end
end
- item:transform(carpet)
end
+
+ item:transform(carpet)
return true
end
diff --git a/data-otservbr-global/scripts/creaturescripts/monster/white_deer.lua b/data/scripts/creaturescripts/monster/white_deer_death.lua
similarity index 90%
rename from data-otservbr-global/scripts/creaturescripts/monster/white_deer.lua
rename to data/scripts/creaturescripts/monster/white_deer_death.lua
index 5fff12eaad4..cc9c9377a6e 100644
--- a/data-otservbr-global/scripts/creaturescripts/monster/white_deer.lua
+++ b/data/scripts/creaturescripts/monster/white_deer_death.lua
@@ -1,11 +1,11 @@
local config = {
- -- ordered by chance, the last chance being 100
{ chance = 30, monster = "Enraged White Deer", message = "The white deer summons all his strength and turns to fight!" },
{ chance = 100, monster = "Desperate White Deer", message = "The white deer desperately tries to escape!" },
}
local whiteDeerDeath = CreatureEvent("WhiteDeerDeath")
-function whiteDeerDeath.onDeath(creature, corpse, killer, mostDamageKiller, unjustified, mostDamageUnjustified)
+
+function whiteDeerDeath.onDeath(creature, corpse, killer, mostDamageKiller, lastHitUnjustified, mostDamageUnjustified)
local targetMonster = creature:getMonster()
if not targetMonster or targetMonster:getMaster() then
return true
diff --git a/data-otservbr-global/scripts/creaturescripts/monster/white_deer_scout.lua b/data/scripts/creaturescripts/monster/white_deer_scouts.lua
similarity index 81%
rename from data-otservbr-global/scripts/creaturescripts/monster/white_deer_scout.lua
rename to data/scripts/creaturescripts/monster/white_deer_scouts.lua
index 8466df46af7..214c0ad5269 100644
--- a/data-otservbr-global/scripts/creaturescripts/monster/white_deer_scout.lua
+++ b/data/scripts/creaturescripts/monster/white_deer_scouts.lua
@@ -1,5 +1,6 @@
local whiteDeerScoutsDeath = CreatureEvent("WhiteDeerScoutsDeath")
-function whiteDeerScoutsDeath.onDeath(creature, corpse, lasthitkiller, mostdamagekiller, lasthitunjustified, mostdamageunjustified)
+
+function whiteDeerScoutsDeath.onDeath(creature, corpse, killer, mostDamageKiller, lastHitUnjustified, mostDamageUnjustified)
local targetMonster = creature:getMonster()
if not targetMonster or targetMonster:getMaster() then
return true
@@ -16,6 +17,7 @@ function whiteDeerScoutsDeath.onDeath(creature, corpse, lasthitkiller, mostdamag
targetMonster:say("The elves came too late to save the deer, however they might avenge it.", TALKTYPE_MONSTER_SAY)
end
+ return true
end
whiteDeerScoutsDeath:register()
diff --git a/data-canary/scripts/creaturescripts/modal_window_helper.lua b/data/scripts/creaturescripts/others/modal_window_helper.lua
similarity index 93%
rename from data-canary/scripts/creaturescripts/modal_window_helper.lua
rename to data/scripts/creaturescripts/others/modal_window_helper.lua
index d2651af1e69..a3a33b3d274 100644
--- a/data-canary/scripts/creaturescripts/modal_window_helper.lua
+++ b/data/scripts/creaturescripts/others/modal_window_helper.lua
@@ -1,4 +1,4 @@
-local creatureEvent = CreatureEvent("modalWindowHelper")
+local creatureEvent = CreatureEvent("ModalWindowHelper")
function creatureEvent.onModalWindow(player, modalWindowId, buttonId, choiceId)
local playerId = player:getId()
diff --git a/data-otservbr-global/scripts/creaturescripts/others/logout.lua b/data/scripts/creaturescripts/player/logout.lua
similarity index 73%
rename from data-otservbr-global/scripts/creaturescripts/others/logout.lua
rename to data/scripts/creaturescripts/player/logout.lua
index 07e0d5dfce5..cab57c5ad68 100644
--- a/data-otservbr-global/scripts/creaturescripts/others/logout.lua
+++ b/data/scripts/creaturescripts/player/logout.lua
@@ -1,22 +1,21 @@
local playerLogout = CreatureEvent("PlayerLogout")
+
function playerLogout.onLogout(player)
local playerId = player:getId()
- if _G.NextUseStaminaTime[playerId] ~= nil then
+ if _G.NextUseStaminaTime[playerId] then
_G.NextUseStaminaTime[playerId] = nil
end
- player:setStorageValue(Storage.ExerciseDummyExhaust, 0)
-
local stats = player:inBossFight()
if stats then
local boss = Monster(stats.bossId)
- -- Player logged out (or died) in the middle of a boss fight, store his damageOut and stamina
if boss then
local dmgOut = boss:getDamageMap()[playerId]
if dmgOut then
stats.damageOut = (stats.damageOut or 0) + dmgOut.total
end
+
stats.stamina = player:getStamina()
end
end
@@ -26,8 +25,6 @@ function playerLogout.onLogout(player)
_G.OnExerciseTraining[playerId] = nil
player:setTraining(false)
end
-
- player:setStorageValue(17101, 0)
return true
end
diff --git a/data/scripts/creaturescripts/player/name_lock.lua b/data/scripts/creaturescripts/player/name_lock.lua
index 322e8d135b8..cb2af81de3f 100644
--- a/data/scripts/creaturescripts/player/name_lock.lua
+++ b/data/scripts/creaturescripts/player/name_lock.lua
@@ -6,7 +6,7 @@ function CheckNamelock(player)
player:setMoveLocked(true)
player:teleportTo(player:getTown():getTemplePosition())
- player:sendTextMessage(MESSAGE_ADMINISTRADOR, "Your name has been locked for the following reason: " .. namelockReason .. ".")
+ player:sendTextMessage(MESSAGE_ADMINISTRATOR, "Your name has been locked for the following reason: " .. namelockReason .. ".")
player:openStore("extras")
addPlayerEvent(sendRequestPurchaseData, 50, player, 65002, GameStore.ClientOfferTypes.CLIENT_STORE_OFFER_NAMECHANGE)
addPlayerEvent(CheckNamelock, 30000, player)
diff --git a/data/scripts/creaturescripts/others/offline_training.lua b/data/scripts/creaturescripts/player/offline_training.lua
similarity index 100%
rename from data/scripts/creaturescripts/others/offline_training.lua
rename to data/scripts/creaturescripts/player/offline_training.lua
diff --git a/data-otservbr-global/scripts/creaturescripts/others/regenerate_stamina.lua b/data/scripts/creaturescripts/player/regenerate_stamina.lua
similarity index 99%
rename from data-otservbr-global/scripts/creaturescripts/others/regenerate_stamina.lua
rename to data/scripts/creaturescripts/player/regenerate_stamina.lua
index 4c70f7eb080..52c78e93f39 100644
--- a/data-otservbr-global/scripts/creaturescripts/others/regenerate_stamina.lua
+++ b/data/scripts/creaturescripts/player/regenerate_stamina.lua
@@ -1,4 +1,5 @@
local regenerateStamina = CreatureEvent("RegenerateStamina")
+
function regenerateStamina.onLogin(player)
if not configManager.getBoolean(configKeys.STAMINA_SYSTEM) then
return true
@@ -6,6 +7,7 @@ function regenerateStamina.onLogin(player)
local lastLogout = player:getLastLogout()
local offlineTime = lastLogout ~= 0 and math.min(os.time() - lastLogout, 86400 * 21) or 0
+
offlineTime = offlineTime - 600
if offlineTime < 180 then
@@ -15,12 +17,14 @@ function regenerateStamina.onLogin(player)
local staminaMinutes = player:getStamina()
local maxNormalStaminaRegen = 2340 - math.min(2340, staminaMinutes)
local regainStaminaMinutes = offlineTime / 180
+
if regainStaminaMinutes > maxNormalStaminaRegen then
local happyHourStaminaRegen = (offlineTime - (maxNormalStaminaRegen * 180)) / 360
staminaMinutes = math.min(2520, math.max(2340, staminaMinutes) + happyHourStaminaRegen)
else
staminaMinutes = staminaMinutes + regainStaminaMinutes
end
+
player:setStamina(staminaMinutes)
return true
end
diff --git a/data/scripts/creaturescripts/player/update_player_on_advanced_level.lua b/data/scripts/creaturescripts/player/update_player_on_advanced_level.lua
new file mode 100644
index 00000000000..aa22976740c
--- /dev/null
+++ b/data/scripts/creaturescripts/player/update_player_on_advanced_level.lua
@@ -0,0 +1,15 @@
+local updatePlayerOnAdvancedLevel = CreatureEvent("UpdatePlayerOnAdvancedLevel")
+
+function updatePlayerOnAdvancedLevel.onAdvance(player, skill, oldLevel, newLevel)
+ if skill ~= SKILL_LEVEL or newLevel <= oldLevel then
+ return true
+ end
+
+ player:addHealth(player:getMaxHealth())
+ player:addMana(player:getMaxMana())
+ player:getFinalLowLevelBonus()
+ player:save()
+ return true
+end
+
+updatePlayerOnAdvancedLevel:register()
diff --git a/data-canary/scripts/globalevents/record.lua b/data/scripts/globalevents/online_record.lua
similarity index 52%
rename from data-canary/scripts/globalevents/record.lua
rename to data/scripts/globalevents/online_record.lua
index 981b2db003c..506fd328ac1 100644
--- a/data-canary/scripts/globalevents/record.lua
+++ b/data/scripts/globalevents/online_record.lua
@@ -1,8 +1,8 @@
-local globalevent = GlobalEvent("Player Record")
+local onlineRecord = GlobalEvent("OnlineRecord")
-function globalevent.onRecord(current, old)
+function onlineRecord.onRecord(current, old)
addEvent(Game.broadcastMessage, 150, "New record: " .. current .. " players are logged in.", MESSAGE_LOGIN)
return true
end
-globalevent:register()
+onlineRecord:register()
diff --git a/data/scripts/lib/register_achievements.lua b/data/scripts/lib/register_achievements.lua
index b906afd287a..11d238d8bcf 100644
--- a/data/scripts/lib/register_achievements.lua
+++ b/data/scripts/lib/register_achievements.lua
@@ -551,7 +551,7 @@ Functions:
ACHIEVEMENT_FIRST = 1
ACHIEVEMENT_LAST = #ACHIEVEMENTS
-for id, achievTable in ipairs(ACHIEVEMENTS) do
+for id, achievTable in pairs(ACHIEVEMENTS) do
if achievTable.name == nil then
logger.error(string.format("[Achievements registration] - Invalid achievement with no name, id: '%s'", id))
goto continue -- Skips to the next iteration using the 'continue' label
@@ -567,7 +567,7 @@ for id, achievTable in ipairs(ACHIEVEMENTS) do
local grade = achievTable.grade or 0
local points = achievTable.points or 0
- logger.debug("[Achievements registration] - Registering achievement '{}' with id '{}'", achievTable.name, id)
+ logger.trace("[Achievements registration] - Registering achievement '{}' with id '{}'", achievTable.name, id)
Game.registerAchievement(id, achievTable.name, achievTable.description, secret, grade, points)
::continue:: -- Label used by 'goto' to continue the loop
diff --git a/data-canary/scripts/movements/tiles.lua b/data/scripts/movements/special_tiles.lua
similarity index 86%
rename from data-canary/scripts/movements/tiles.lua
rename to data/scripts/movements/special_tiles.lua
index 5f0f74e2c80..a1ec92dbbad 100644
--- a/data-canary/scripts/movements/tiles.lua
+++ b/data/scripts/movements/special_tiles.lua
@@ -1,17 +1,15 @@
local increasing = { [419] = 420, [431] = 430, [452] = 453, [563] = 564, [549] = 562, [10145] = 10146 }
local decreasing = { [420] = 419, [430] = 431, [453] = 452, [564] = 563, [562] = 549, [10146] = 10145 }
--- onStepIn
local tile = MoveEvent()
-tile:type("stepin")
function tile.onStepIn(creature, item, position, fromPosition)
- if not increasing[item.itemid] then
+ local player = creature:getPlayer()
+ if not player or player:isInGhostMode() then
return true
end
- local player = creature:getPlayer()
- if not player or player:isInGhostMode() then
+ if not increasing[item.itemid] then
return true
end
@@ -30,14 +28,19 @@ function tile.onStepIn(creature, item, position, fromPosition)
for _, direction in ipairs(DIRECTIONS_TABLE) do
local playerPosition = player:getPosition()
playerPosition:getNextPosition(direction)
+
local depotItem = playerPosition:getTile():getItemByType(ITEM_TYPE_DEPOT)
- if depotItem ~= nil then
+ if depotItem then
local depotItems = 0
+
for id = 1, configManager.getNumber(configKeys.DEPOT_BOXES) do
depotItems = depotItems + player:getDepotChest(id, true):getItemHoldingCount()
end
- player:sendTextMessage(MESSAGE_FAILURE, "Your depot contains " .. depotItems .. " item" .. (depotItems > 1 and "s." or ".") .. "\
- Your supply stash contains " .. player:getStashCount() .. " item" .. (player:getStashCount() > 1 and "s." or "."))
+
+ local depotMessage = "Your depot contains " .. depotItems .. " item" .. (depotItems ~= 1 and "s." or ".")
+ local stashMessage = "Your supply stash contains " .. player:getStashCount() .. " item" .. (player:getStashCount() ~= 1 and "s." or ".")
+
+ player:sendTextMessage(MESSAGE_FAILURE, depotMessage .. "\n" .. stashMessage)
player:setSpecialContainersAvailable(true, true, true)
return true
end
@@ -57,18 +60,18 @@ for index, value in pairs(increasing) do
tile:id(index)
end
+tile:type("stepin")
tile:register()
tile = MoveEvent()
-tile:type("stepout")
function tile.onStepOut(creature, item, position, fromPosition)
- if not decreasing[item.itemid] then
+ local player = creature:getPlayer()
+ if not player or player:isInGhostMode() then
return true
end
- local player = creature:getPlayer()
- if not player or player:isInGhostMode() then
+ if not decreasing[item.itemid] then
return true
end
@@ -81,4 +84,5 @@ for index, value in pairs(decreasing) do
tile:id(index)
end
+tile:type("stepout")
tile:register()
diff --git a/data-canary/scripts/movements/yellow_pillow.lua b/data/scripts/movements/yellow_pillow.lua
similarity index 66%
rename from data-canary/scripts/movements/yellow_pillow.lua
rename to data/scripts/movements/yellow_pillow.lua
index 6d981448ca5..f0a433f2fb7 100644
--- a/data-canary/scripts/movements/yellow_pillow.lua
+++ b/data/scripts/movements/yellow_pillow.lua
@@ -1,14 +1,16 @@
local yellowPillow = MoveEvent()
-yellowPillow:type("stepin")
-function yellowPillow.onStepIn(player, item, position, fromPosition)
+function yellowPillow.onStepIn(creature, item, position, fromPosition)
+ local player = creature:getPlayer()
if not player or player:isInGhostMode() then
return true
end
+
player:say("Faaart!", TALKTYPE_MONSTER_SAY)
item:getPosition():sendMagicEffect(CONST_ME_POFF)
return true
end
-yellowPillow:id(8072)
+yellowPillow:id(2397)
+yellowPillow:type("stepin")
yellowPillow:register()
diff --git a/data/scripts/talkactions/gm/ban.lua b/data/scripts/talkactions/gm/ban.lua
index 8b46394a3e2..0ab07040333 100644
--- a/data/scripts/talkactions/gm/ban.lua
+++ b/data/scripts/talkactions/gm/ban.lua
@@ -37,11 +37,11 @@ function ban.onSay(player, words, param)
local target = Player(name)
if target then
local text = target:getName() .. " has been banned"
- player:sendTextMessage(MESSAGE_ADMINISTRADOR, text)
+ player:sendTextMessage(MESSAGE_ADMINISTRATOR, text)
Webhook.sendMessage("Player Banned", text .. " reason: " .. reason .. ". (by: " .. player:getName() .. ")", WEBHOOK_COLOR_YELLOW, announcementChannels["serverAnnouncements"])
target:remove()
else
- player:sendTextMessage(MESSAGE_ADMINISTRADOR, name .. " has been banned.")
+ player:sendTextMessage(MESSAGE_ADMINISTRATOR, name .. " has been banned.")
end
end
diff --git a/data/scripts/talkactions/gm/broadcast.lua b/data/scripts/talkactions/gm/broadcast.lua
index 021f218ebe3..dffbe1bb0e9 100644
--- a/data/scripts/talkactions/gm/broadcast.lua
+++ b/data/scripts/talkactions/gm/broadcast.lua
@@ -5,7 +5,7 @@ function Broadcast(text, filter)
if filter and not filter(targetPlayer) then
goto continue
end
- targetPlayer:sendTextMessage(MESSAGE_ADMINISTRADOR, text)
+ targetPlayer:sendTextMessage(MESSAGE_ADMINISTRATOR, text)
::continue::
end
end
diff --git a/data/scripts/talkactions/gm/clean.lua b/data/scripts/talkactions/gm/clean.lua
index 6fe5f3cddfa..18ab149e216 100644
--- a/data/scripts/talkactions/gm/clean.lua
+++ b/data/scripts/talkactions/gm/clean.lua
@@ -6,7 +6,7 @@ function clean.onSay(player, words, param)
local itemCount = cleanMap()
if itemCount ~= 0 then
- player:sendTextMessage(MESSAGE_ADMINISTRADOR, "Cleaned " .. itemCount .. " item" .. (itemCount > 1 and "s" or "") .. " from the map.")
+ player:sendTextMessage(MESSAGE_ADMINISTRATOR, "Cleaned " .. itemCount .. " item" .. (itemCount > 1 and "s" or "") .. " from the map.")
end
return true
end
diff --git a/data/scripts/talkactions/gm/mc_check.lua b/data/scripts/talkactions/gm/mc_check.lua
index c93661053e4..1815b7fdc9d 100644
--- a/data/scripts/talkactions/gm/mc_check.lua
+++ b/data/scripts/talkactions/gm/mc_check.lua
@@ -4,7 +4,7 @@ function mcCheck.onSay(player, words, param)
-- create log
logCommand(player, words, param)
- player:sendTextMessage(MESSAGE_ADMINISTRADOR, "Multiclient Check List:")
+ player:sendTextMessage(MESSAGE_ADMINISTRATOR, "Multiclient Check List:")
local ipList = {}
local players = Game.getPlayers()
for i = 1, #players do
@@ -29,7 +29,7 @@ function mcCheck.onSay(player, words, param)
tmpPlayer = list[i]
message = ("%s, %s [%d]"):format(message, tmpPlayer:getName(), tmpPlayer:getLevel())
end
- player:sendTextMessage(MESSAGE_ADMINISTRADOR, message .. ".")
+ player:sendTextMessage(MESSAGE_ADMINISTRATOR, message .. ".")
end
end
return true
diff --git a/data/scripts/talkactions/gm/namelock.lua b/data/scripts/talkactions/gm/namelock.lua
index 1b204759e02..27e41710096 100644
--- a/data/scripts/talkactions/gm/namelock.lua
+++ b/data/scripts/talkactions/gm/namelock.lua
@@ -33,7 +33,7 @@ function namelock.onSay(player, words, param)
target:kv():set("namelock", reason)
local text = target:getName() .. " has been namelocked"
logger.info(text .. ", reason: " .. reason)
- player:sendTextMessage(MESSAGE_ADMINISTRADOR, text)
+ player:sendTextMessage(MESSAGE_ADMINISTRATOR, text)
Webhook.sendMessage("Player Namelocked", text .. " reason: " .. reason .. ".", WEBHOOK_COLOR_YELLOW, announcementChannels["serverAnnouncements"])
if online then
CheckNamelock(target)
diff --git a/data/scripts/talkactions/gm/unban.lua b/data/scripts/talkactions/gm/unban.lua
index 264335eeec7..3d1caba8b77 100644
--- a/data/scripts/talkactions/gm/unban.lua
+++ b/data/scripts/talkactions/gm/unban.lua
@@ -18,7 +18,7 @@ function unban.onSay(player, words, param)
db.asyncQuery("DELETE FROM `ip_bans` WHERE `ip` = " .. Result.getNumber(resultId, "lastip"))
Result.free(resultId)
local text = param .. " has been unbanned."
- player:sendTextMessage(MESSAGE_ADMINISTRADOR, text)
+ player:sendTextMessage(MESSAGE_ADMINISTRATOR, text)
Webhook.sendMessage("Player Unbanned", text .. " (by: " .. player:getName() .. ")", WEBHOOK_COLOR_YELLOW, announcementChannels["serverAnnouncements"])
return true
end
diff --git a/data/scripts/talkactions/god/add_bosstiary_kills.lua b/data/scripts/talkactions/god/add_bosstiary_kills.lua
index 4e5aecdfbd4..a6463c26162 100644
--- a/data/scripts/talkactions/god/add_bosstiary_kills.lua
+++ b/data/scripts/talkactions/god/add_bosstiary_kills.lua
@@ -24,9 +24,9 @@ function talkaction.onSay(player, words, param)
local message = "Added received kills: " .. kills .. ", for boss: " .. monsterName
if target == player then
- player:sendTextMessage(MESSAGE_ADMINISTRADOR, message .. " to yourself.")
+ player:sendTextMessage(MESSAGE_ADMINISTRATOR, message .. " to yourself.")
else
- player:sendTextMessage(MESSAGE_ADMINISTRADOR, message .. " to player: " .. targetName)
+ player:sendTextMessage(MESSAGE_ADMINISTRATOR, message .. " to player: " .. targetName)
target:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You received kills: " .. kills .. ", to boss: " .. monsterName)
end
target:addBosstiaryKill(monsterName, kills)
diff --git a/data/scripts/talkactions/god/add_mount.lua b/data/scripts/talkactions/god/add_mount.lua
index 813f46f38a9..b8b2f00dda1 100644
--- a/data/scripts/talkactions/god/add_mount.lua
+++ b/data/scripts/talkactions/god/add_mount.lua
@@ -22,8 +22,8 @@ function addOutfit.onSay(player, words, param)
if target then
local mount = tonumber(split[2])
target:addMount(mount)
- target:sendTextMessage(MESSAGE_ADMINISTRADOR, "" .. player:getName() .. " has been added a new mount for you.")
- player:sendTextMessage(MESSAGE_ADMINISTRADOR, "You have sucessfull added mount " .. mount .. " to the player " .. target:getName() .. ".")
+ target:sendTextMessage(MESSAGE_ADMINISTRATOR, "" .. player:getName() .. " has been added a new mount for you.")
+ player:sendTextMessage(MESSAGE_ADMINISTRATOR, "You have sucessfull added mount " .. mount .. " to the player " .. target:getName() .. ".")
if printConsole then
logger.info("[addOutfit.onSay] - Player: {} has been added mount: {} to the player: {}", player:getName(), lookType, target:getName())
end
diff --git a/data/scripts/talkactions/god/add_outfit.lua b/data/scripts/talkactions/god/add_outfit.lua
index 825aaf84c7e..a27fb4f8a18 100644
--- a/data/scripts/talkactions/god/add_outfit.lua
+++ b/data/scripts/talkactions/god/add_outfit.lua
@@ -24,8 +24,8 @@ function addOutfit.onSay(player, words, param)
if target then
local lookType = tonumber(split[2])
target:addOutfit(lookType)
- target:sendTextMessage(MESSAGE_ADMINISTRADOR, "" .. player:getName() .. " has been added a new outfit for you.")
- player:sendTextMessage(MESSAGE_ADMINISTRADOR, "You have sucessfull added looktype " .. lookType .. " to the player " .. target:getName() .. ".")
+ target:sendTextMessage(MESSAGE_ADMINISTRATOR, "" .. player:getName() .. " has been added a new outfit for you.")
+ player:sendTextMessage(MESSAGE_ADMINISTRATOR, "You have sucessfull added looktype " .. lookType .. " to the player " .. target:getName() .. ".")
if printConsole then
logger.info("[addOutfit.onSay] - Player: {} has been added looktype: {} to the player: {}", player:getName(), lookType, target:getName())
end
diff --git a/data/scripts/talkactions/god/close_server.lua b/data/scripts/talkactions/god/close_server.lua
index 930cde5be79..ad8cfadef2c 100644
--- a/data/scripts/talkactions/god/close_server.lua
+++ b/data/scripts/talkactions/god/close_server.lua
@@ -19,10 +19,10 @@ function closeServer.onSay(player, words, param)
end
elseif param == "maintainance" then
Game.setGameState(GAME_STATE_MAINTAIN)
- player:sendTextMessage(MESSAGE_ADMINISTRADOR, "Server is set to maintenance mode.")
+ player:sendTextMessage(MESSAGE_ADMINISTRATOR, "Server is set to maintenance mode.")
else
Game.setGameState(GAME_STATE_CLOSED)
- player:sendTextMessage(MESSAGE_ADMINISTRADOR, "Server is now closed.")
+ player:sendTextMessage(MESSAGE_ADMINISTRATOR, "Server is now closed.")
Webhook.sendMessage(":yellow_square: Server was closed by: **" .. player:getName() .. "**", announcementChannels["serverAnnouncements"])
end
return true
diff --git a/data/scripts/talkactions/god/ip_ban.lua b/data/scripts/talkactions/god/ip_ban.lua
index 9826d726c87..09269de446f 100644
--- a/data/scripts/talkactions/god/ip_ban.lua
+++ b/data/scripts/talkactions/god/ip_ban.lua
@@ -32,14 +32,14 @@ function ipBan.onSay(player, words, param)
resultId = db.storeQuery("SELECT 1 FROM `ip_bans` WHERE `ip` = " .. targetIp)
if resultId ~= false then
- player:sendTextMessage(MESSAGE_ADMINISTRADOR, targetName .. " is already IP banned.")
+ player:sendTextMessage(MESSAGE_ADMINISTRATOR, targetName .. " is already IP banned.")
Result.free(resultId)
return true
end
local timeNow = os.time()
db.query("INSERT INTO `ip_bans` (`ip`, `reason`, `banned_at`, `expires_at`, `banned_by`) VALUES (" .. targetIp .. ", '', " .. timeNow .. ", " .. timeNow + (ipBanDays * 86400) .. ", " .. player:getGuid() .. ")")
- player:sendTextMessage(MESSAGE_ADMINISTRADOR, targetName .. " has been IP banned.")
+ player:sendTextMessage(MESSAGE_ADMINISTRATOR, targetName .. " has been IP banned.")
return true
end
diff --git a/data/scripts/talkactions/god/open_server.lua b/data/scripts/talkactions/god/open_server.lua
index 84f0b4afe49..83ac47878a1 100644
--- a/data/scripts/talkactions/god/open_server.lua
+++ b/data/scripts/talkactions/god/open_server.lua
@@ -5,7 +5,7 @@ function openServer.onSay(player, words, param)
logCommand(player, words, param)
Game.setGameState(GAME_STATE_NORMAL)
- player:sendTextMessage(MESSAGE_ADMINISTRADOR, "Server is now open.")
+ player:sendTextMessage(MESSAGE_ADMINISTRATOR, "Server is now open.")
Webhook.sendMessage(":green_circle: Server was opened by: **" .. player:getName() .. "**", announcementChannels["serverAnnouncements"])
return true
end
diff --git a/data/scripts/talkactions/god/raids.lua b/data/scripts/talkactions/god/raids.lua
index 15f21801293..b9b4b909668 100644
--- a/data/scripts/talkactions/god/raids.lua
+++ b/data/scripts/talkactions/god/raids.lua
@@ -12,18 +12,18 @@ function startRaid.onSay(player, words, param)
if Raid.registry[param] then
local raid = Raid.registry[param]
if raid:tryStart(true) then
- player:sendTextMessage(MESSAGE_ADMINISTRADOR, "Raid " .. param .. " started.")
+ player:sendTextMessage(MESSAGE_ADMINISTRATOR, "Raid " .. param .. " started.")
else
- player:sendTextMessage(MESSAGE_ADMINISTRADOR, "Raid " .. param .. " could not be started.")
+ player:sendTextMessage(MESSAGE_ADMINISTRATOR, "Raid " .. param .. " could not be started.")
end
return true
end
local returnValue = Game.startRaid(param)
if returnValue ~= RETURNVALUE_NOERROR then
- player:sendTextMessage(MESSAGE_ADMINISTRADOR, Game.getReturnMessage(returnValue))
+ player:sendTextMessage(MESSAGE_ADMINISTRATOR, Game.getReturnMessage(returnValue))
else
- player:sendTextMessage(MESSAGE_ADMINISTRADOR, "Raid started.")
+ player:sendTextMessage(MESSAGE_ADMINISTRATOR, "Raid started.")
end
return true
end
diff --git a/data/scripts/talkactions/god/reload.lua b/data/scripts/talkactions/god/reload.lua
index 5b294305cf3..5bf72868320 100644
--- a/data/scripts/talkactions/god/reload.lua
+++ b/data/scripts/talkactions/god/reload.lua
@@ -49,19 +49,17 @@ function reload.onSay(player, words, param)
logCommand(player, "/reload", param)
local reloadType = reloadTypes[param:lower()]
- if reloadType then
- saveServer()
- SaveHirelings()
-
- Game.reload(reloadType)
- logger.info("Reloaded {}", param:lower())
-
- player:sendTextMessage(MESSAGE_LOOK, string.format("Reloaded %s.", param:lower()))
- player:sendTextMessage(MESSAGE_ADMINISTRADOR, "Server is saved. Now will reload configs!")
- elseif not reloadType then
+ if not reloadType then
player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Reload type not found.")
- logger.warn("[reload.onSay] - Reload type '{}' not found", param)
+ return true
end
+
+ saveServer()
+ SaveHirelings()
+
+ Game.reload(reloadType)
+
+ player:sendTextMessage(MESSAGE_ADMINISTRATOR, string.format("The server has been reloaded, %s and configurations are now being reloaded.", param:lower()))
return true
end
diff --git a/data/scripts/talkactions/god/save.lua b/data/scripts/talkactions/god/save.lua
index 444f6ea20d2..845df50d9b4 100644
--- a/data/scripts/talkactions/god/save.lua
+++ b/data/scripts/talkactions/god/save.lua
@@ -16,7 +16,7 @@ function save.onSay(player, words, param)
else
saveServer()
SaveHirelings()
- player:sendTextMessage(MESSAGE_ADMINISTRADOR, "Server has been saved.")
+ player:sendTextMessage(MESSAGE_ADMINISTRATOR, "Server has been saved.")
end
return true
end
diff --git a/data/scripts/talkactions/god/start_raid.lua b/data/scripts/talkactions/god/start_raid.lua
index b43e77c061a..cbd3fe24a79 100644
--- a/data/scripts/talkactions/god/start_raid.lua
+++ b/data/scripts/talkactions/god/start_raid.lua
@@ -11,9 +11,9 @@ function startRaid.onSay(player, words, param)
local returnValue = Game.startRaid(param)
if returnValue ~= RETURNVALUE_NOERROR then
- player:sendTextMessage(MESSAGE_ADMINISTRADOR, Game.getReturnMessage(returnValue))
+ player:sendTextMessage(MESSAGE_ADMINISTRATOR, Game.getReturnMessage(returnValue))
else
- player:sendTextMessage(MESSAGE_ADMINISTRADOR, "Raid started.")
+ player:sendTextMessage(MESSAGE_ADMINISTRATOR, "Raid started.")
end
return true
end
diff --git a/schema.sql b/schema.sql
index 1eeb78fcd14..58e6ea216ce 100644
--- a/schema.sql
+++ b/schema.sql
@@ -7,7 +7,7 @@ CREATE TABLE IF NOT EXISTS `server_config` (
CONSTRAINT `server_config_pk` PRIMARY KEY (`config`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-INSERT INTO `server_config` (`config`, `value`) VALUES ('db_version', '43'), ('motd_hash', ''), ('motd_num', '0'), ('players_record', '0');
+INSERT INTO `server_config` (`config`, `value`) VALUES ('db_version', '44'), ('motd_hash', ''), ('motd_num', '0'), ('players_record', '0');
-- Table structure `accounts`
CREATE TABLE IF NOT EXISTS `accounts` (
@@ -312,9 +312,12 @@ CREATE TABLE IF NOT EXISTS `guild_wars` (
`guild2` int(11) NOT NULL DEFAULT '0',
`name1` varchar(255) NOT NULL,
`name2` varchar(255) NOT NULL,
- `status` tinyint(2) NOT NULL DEFAULT '0',
+ `status` tinyint(2) UNSIGNED NOT NULL DEFAULT '0',
`started` bigint(15) NOT NULL DEFAULT '0',
`ended` bigint(15) NOT NULL DEFAULT '0',
+ `frags_limit` smallint(4) UNSIGNED NOT NULL DEFAULT '0',
+ `payment` bigint(13) UNSIGNED NOT NULL DEFAULT '0',
+ `duration_days` tinyint(3) UNSIGNED NOT NULL DEFAULT '0',
INDEX `guild1` (`guild1`),
INDEX `guild2` (`guild2`),
CONSTRAINT `guild_wars_pk` PRIMARY KEY (`id`)
diff --git a/src/config/config_enums.hpp b/src/config/config_enums.hpp
index ee8b531ddcc..b9b857f435c 100644
--- a/src/config/config_enums.hpp
+++ b/src/config/config_enums.hpp
@@ -37,6 +37,9 @@ enum ConfigKey_t : uint16_t {
CLEAN_PROTECTION_ZONES,
COMBAT_CHAIN_DELAY,
COMBAT_CHAIN_TARGETS,
+ COMBAT_CHAIN_SKILL_FORMULA_AXE,
+ COMBAT_CHAIN_SKILL_FORMULA_CLUB,
+ COMBAT_CHAIN_SKILL_FORMULA_SWORD,
COMPRESSION_LEVEL,
CONVERT_UNSAFE_SCRIPTS,
CORE_DIRECTORY,
@@ -240,6 +243,7 @@ enum ConfigKey_t : uint16_t {
SCRIPTS_CONSOLE_LOGS,
SERVER_MOTD,
SERVER_NAME,
+ SHOW_LOOTS_IN_BESTIARY,
SKULLED_DEATH_LOSE_STORE_ITEM,
SORT_LOOT_BY_CHANCE,
SQL_PORT,
diff --git a/src/config/configmanager.cpp b/src/config/configmanager.cpp
index 7069ca10fb2..c1702672e71 100644
--- a/src/config/configmanager.cpp
+++ b/src/config/configmanager.cpp
@@ -128,6 +128,7 @@ bool ConfigManager::load() {
loadBoolConfig(L, REPLACE_KICK_ON_LOGIN, "replaceKickOnLogin", true);
loadBoolConfig(L, REWARD_CHEST_COLLECT_ENABLED, "rewardChestCollectEnabled", true);
loadBoolConfig(L, SCRIPTS_CONSOLE_LOGS, "showScriptsLogInConsole", true);
+ loadBoolConfig(L, SHOW_LOOTS_IN_BESTIARY, "showLootsInBestiary", false);
loadBoolConfig(L, SKULLED_DEATH_LOSE_STORE_ITEM, "skulledDeathLoseStoreItem", false);
loadBoolConfig(L, SORT_LOOT_BY_CHANCE, "sortLootByChance", false);
loadBoolConfig(L, STAMINA_PZ, "staminaPz", false);
@@ -217,6 +218,9 @@ bool ConfigManager::load() {
loadIntConfig(L, CHECK_EXPIRED_MARKET_OFFERS_EACH_MINUTES, "checkExpiredMarketOffersEachMinutes", 60);
loadIntConfig(L, COMBAT_CHAIN_DELAY, "combatChainDelay", 50);
loadIntConfig(L, COMBAT_CHAIN_TARGETS, "combatChainTargets", 5);
+ loadFloatConfig(L, COMBAT_CHAIN_SKILL_FORMULA_AXE, "combatChainSkillFormulaAxe", 0.9);
+ loadFloatConfig(L, COMBAT_CHAIN_SKILL_FORMULA_CLUB, "combatChainSkillFormulaClub", 0.7);
+ loadFloatConfig(L, COMBAT_CHAIN_SKILL_FORMULA_SWORD, "combatChainSkillFormulaSword", 1.1);
loadIntConfig(L, COMPRESSION_LEVEL, "packetCompressionLevel", 6);
loadIntConfig(L, CRITICALCHANCE, "criticalChance", 10);
loadIntConfig(L, DAY_KILLS_TO_RED, "dayKillsToRedSkull", 3);
diff --git a/src/creatures/combat/combat.cpp b/src/creatures/combat/combat.cpp
index 7456f572938..532f4d48bb1 100644
--- a/src/creatures/combat/combat.cpp
+++ b/src/creatures/combat/combat.cpp
@@ -524,7 +524,7 @@ bool Combat::setCallback(CallBackParam_t key) {
void Combat::setChainCallback(uint8_t chainTargets, uint8_t chainDistance, bool backtracking) {
params.chainCallback = std::make_unique(chainTargets, chainDistance, backtracking);
- g_logger().debug("ChainCallback created: {}, with targets: {}, distance: {}, backtracking: {}", params.chainCallback != nullptr, chainTargets, chainDistance, backtracking);
+ g_logger().trace("ChainCallback created: {}, with targets: {}, distance: {}, backtracking: {}", params.chainCallback != nullptr, chainTargets, chainDistance, backtracking);
}
CallBack* Combat::getCallback(CallBackParam_t key) {
@@ -941,6 +941,15 @@ void Combat::setupChain(const std::shared_ptr &weapon) {
return;
}
+ if (weapon->isChainDisabled()) {
+ return;
+ }
+
+ const auto &weaponType = weapon->getWeaponType();
+ if (weaponType == WEAPON_NONE || weaponType == WEAPON_SHIELD || weaponType == WEAPON_AMMO || weaponType == WEAPON_DISTANCE) {
+ return;
+ }
+
// clang-format off
static std::list areaList = {
0, 0, 0, 1, 0, 0, 0,
@@ -957,7 +966,6 @@ void Combat::setupChain(const std::shared_ptr &weapon) {
setArea(area);
g_logger().trace("Weapon: {}, element type: {}", Item::items[weapon->getID()].name, weapon->params.combatType);
setParam(COMBAT_PARAM_TYPE, weapon->params.combatType);
- const auto &weaponType = weapon->getWeaponType();
if (weaponType != WEAPON_WAND) {
setParam(COMBAT_PARAM_BLOCKARMOR, true);
}
@@ -976,15 +984,13 @@ void Combat::setupChain(const std::shared_ptr &weapon) {
switch (weaponType) {
case WEAPON_SWORD:
- setCommonValues(1.1, MELEE_ATK_SWORD, CONST_ME_SLASH);
+ setCommonValues(g_configManager().getFloat(COMBAT_CHAIN_SKILL_FORMULA_SWORD, __FUNCTION__), MELEE_ATK_SWORD, CONST_ME_SLASH);
break;
-
case WEAPON_CLUB:
- setCommonValues(0.7, MELEE_ATK_CLUB, CONST_ME_BLACK_BLOOD);
+ setCommonValues(g_configManager().getFloat(COMBAT_CHAIN_SKILL_FORMULA_CLUB, __FUNCTION__), MELEE_ATK_CLUB, CONST_ME_BLACK_BLOOD);
break;
-
case WEAPON_AXE:
- setCommonValues(0.9, MELEE_ATK_AXE, CONST_ANI_WHIRLWINDAXE);
+ setCommonValues(g_configManager().getFloat(COMBAT_CHAIN_SKILL_FORMULA_AXE, __FUNCTION__), MELEE_ATK_AXE, CONST_ANI_WHIRLWINDAXE);
break;
}
diff --git a/src/creatures/players/player.cpp b/src/creatures/players/player.cpp
index 7cf6b6bcaf3..6dd304e90ba 100644
--- a/src/creatures/players/player.cpp
+++ b/src/creatures/players/player.cpp
@@ -2190,7 +2190,7 @@ void Player::onThink(uint32_t interval) {
} else if (client && idleTime == 60000 * kickAfterMinutes) {
std::ostringstream ss;
ss << "There was no variation in your behaviour for " << kickAfterMinutes << " minutes. You will be disconnected in one minute if there is no change in your actions until then.";
- client->sendTextMessage(TextMessage(MESSAGE_ADMINISTRADOR, ss.str()));
+ client->sendTextMessage(TextMessage(MESSAGE_ADMINISTRATOR, ss.str()));
}
}
@@ -8074,3 +8074,13 @@ void Player::checkAndShowBlessingMessage() {
sendTextMessage(MESSAGE_EVENT_ADVANCE, blessOutput.str());
}
}
+
+bool Player::canSpeakWithHireling(uint8_t speechbubble) {
+ const auto &playerTile = getTile();
+ const auto &house = playerTile ? playerTile->getHouse() : nullptr;
+ if (speechbubble == SPEECHBUBBLE_HIRELING && (!house || house->getHouseAccessLevel(static_self_cast()) == HOUSE_NOT_INVITED)) {
+ return false;
+ }
+
+ return true;
+}
diff --git a/src/creatures/players/player.hpp b/src/creatures/players/player.hpp
index d37214911f3..592db179071 100644
--- a/src/creatures/players/player.hpp
+++ b/src/creatures/players/player.hpp
@@ -2595,6 +2595,8 @@ class Player final : public Creature, public Cylinder, public Bankable {
std::shared_ptr getStoreInbox() const;
+ bool canSpeakWithHireling(uint8_t speechbubble);
+
private:
friend class PlayerLock;
std::mutex mutex;
diff --git a/src/game/game.cpp b/src/game/game.cpp
index c17f16b1a17..ab39f632457 100644
--- a/src/game/game.cpp
+++ b/src/game/game.cpp
@@ -5691,7 +5691,7 @@ void Game::playerChangeOutfit(uint32_t playerId, Outfit_t outfit, uint8_t isMoun
return;
}
- if (playerTile->hasFlag(TILESTATE_PROTECTIONZONE)) {
+ if (!g_configManager().getBoolean(TOGGLE_MOUNT_IN_PZ, __FUNCTION__) && playerTile->hasFlag(TILESTATE_PROTECTIONZONE)) {
outfit.lookMount = 0;
}
@@ -5908,6 +5908,10 @@ void Game::playerSpeakToNpc(std::shared_ptr player, const std::string &t
}
for (const auto &spectator : Spectators().find(player->getPosition()).filter()) {
+ if (!player->canSpeakWithHireling(spectator->getNpc()->getSpeechBubble())) {
+ continue;
+ }
+
spectator->getNpc()->onCreatureSay(player, TALKTYPE_PRIVATE_PN, text);
}
@@ -8452,6 +8456,16 @@ void Game::playerNpcGreet(uint32_t playerId, uint32_t npcId) {
return;
}
+ // Check npc say exhausted
+ if (player->isUIExhausted()) {
+ player->sendCancelMessage(RETURNVALUE_YOUAREEXHAUSTED);
+ return;
+ }
+
+ if (!player->canSpeakWithHireling(npc->getSpeechBubble())) {
+ return;
+ }
+
auto spectators = Spectators().find(player->getPosition(), true);
spectators.insert(npc);
internalCreatureSay(player, TALKTYPE_SAY, "hi", false, &spectators);
@@ -8463,6 +8477,8 @@ void Game::playerNpcGreet(uint32_t playerId, uint32_t npcId) {
} else {
internalCreatureSay(player, TALKTYPE_PRIVATE_PN, "sail", false, &npcsSpectators);
}
+
+ player->updateUIExhausted();
}
void Game::playerLeaveMarket(uint32_t playerId) {
diff --git a/src/io/ioguild.cpp b/src/io/ioguild.cpp
index 115d688c89a..99e1e750676 100644
--- a/src/io/ioguild.cpp
+++ b/src/io/ioguild.cpp
@@ -60,7 +60,7 @@ uint32_t IOGuild::getGuildIdByName(const std::string &name) {
void IOGuild::getWarList(uint32_t guildId, GuildWarVector &guildWarVector) {
std::ostringstream query;
- query << "SELECT `guild1`, `guild2` FROM `guild_wars` WHERE (`guild1` = " << guildId << " OR `guild2` = " << guildId << ") AND `ended` = 0 AND `status` = 1";
+ query << "SELECT `guild1`, `guild2` FROM `guild_wars` WHERE (`guild1` = " << guildId << " OR `guild2` = " << guildId << ") AND `status` = 1";
DBResult_ptr result = Database::getInstance().storeQuery(query.str());
if (!result) {
diff --git a/src/items/functions/item/item_parse.cpp b/src/items/functions/item/item_parse.cpp
index 365cda202ce..a6255983f67 100644
--- a/src/items/functions/item/item_parse.cpp
+++ b/src/items/functions/item/item_parse.cpp
@@ -1165,9 +1165,14 @@ void ItemParse::createAndRegisterScript(ItemType &itemType, pugi::xml_node attri
g_logger().warn("[{}] - wandtype '{}' does not exist", __FUNCTION__, elementName);
}
} else if (stringKey == "chain" && weapon) {
- auto value = subValueAttribute.as_double();
- weapon->setChainSkillValue(value);
- g_logger().trace("Found chain skill value '{}' for weapon: {}", value, itemType.name);
+ if (auto value = subValueAttribute.as_double()) {
+ weapon->setChainSkillValue(value);
+ g_logger().trace("Found chain skill value '{}' for weapon: {}", value, itemType.name);
+ }
+ if (subValueAttribute.as_bool() == false) {
+ weapon->setDisabledChain();
+ g_logger().warn("Chain disabled for weapon: {}", itemType.name);
+ }
}
}
diff --git a/src/items/weapons/weapons.cpp b/src/items/weapons/weapons.cpp
index 25287ca9f92..aa90fda6c2d 100644
--- a/src/items/weapons/weapons.cpp
+++ b/src/items/weapons/weapons.cpp
@@ -221,9 +221,10 @@ void Weapon::internalUseWeapon(std::shared_ptr player, std::shared_ptr player, std::shared_ptrdoCombatChain(player, target, params.aggressive);
} else {
Combat::doCombatHealth(player, target, damage, params);
}
+
g_logger().debug("Weapon::internalUseWeapon - cpp callback executed.");
}
diff --git a/src/items/weapons/weapons.hpp b/src/items/weapons/weapons.hpp
index 2cf97568aef..5b2b260e2ee 100644
--- a/src/items/weapons/weapons.hpp
+++ b/src/items/weapons/weapons.hpp
@@ -192,6 +192,14 @@ class Weapon : public Script {
return m_chainSkillValue;
}
+ void setDisabledChain() {
+ m_isDisabledChain = true;
+ }
+
+ bool isChainDisabled() const {
+ return m_isDisabledChain;
+ }
+
const WeaponType_t getWeaponType() const {
return weaponType;
}
@@ -243,6 +251,7 @@ class Weapon : public Script {
bool enabled = true;
bool premium = false;
bool wieldUnproperly = false;
+ bool m_isDisabledChain = false;
std::string vocationString = "";
void onUsedWeapon(std::shared_ptr player, std::shared_ptr
- item, std::shared_ptr destTile) const;
diff --git a/src/lua/functions/core/game/lua_enums.cpp b/src/lua/functions/core/game/lua_enums.cpp
index 66b7cf1feec..2e3813e0769 100644
--- a/src/lua/functions/core/game/lua_enums.cpp
+++ b/src/lua/functions/core/game/lua_enums.cpp
@@ -742,7 +742,7 @@ void LuaEnums::initGameStateEnums(lua_State* L) {
void LuaEnums::initMessageEnums(lua_State* L) {
registerEnum(L, MESSAGE_GAMEMASTER_CONSOLE);
registerEnum(L, MESSAGE_LOGIN);
- registerEnum(L, MESSAGE_ADMINISTRADOR);
+ registerEnum(L, MESSAGE_ADMINISTRATOR);
registerEnum(L, MESSAGE_EVENT_ADVANCE);
registerEnum(L, MESSAGE_GAME_HIGHLIGHT);
registerEnum(L, MESSAGE_FAILURE);
diff --git a/src/lua/functions/core/libs/logger_functions.cpp b/src/lua/functions/core/libs/logger_functions.cpp
index dc039a9ed0d..1b2605f6421 100644
--- a/src/lua/functions/core/libs/logger_functions.cpp
+++ b/src/lua/functions/core/libs/logger_functions.cpp
@@ -24,6 +24,7 @@ void LoggerFunctions::init(lua_State* L) {
registerMethod(L, "logger", "warn", LoggerFunctions::luaLoggerWarn);
registerMethod(L, "logger", "error", LoggerFunctions::luaLoggerError);
registerMethod(L, "logger", "debug", LoggerFunctions::luaLoggerDebug);
+ registerMethod(L, "logger", "trace", LoggerFunctions::luaLoggerTrace);
}
int LoggerFunctions::luaSpdlogInfo(lua_State* L) {
@@ -107,3 +108,13 @@ int LoggerFunctions::luaLoggerDebug(lua_State* L) {
}
return 1;
}
+
+int LoggerFunctions::luaLoggerTrace(lua_State* L) {
+ // logger.trace(text)
+ if (isString(L, 1)) {
+ g_logger().trace(getFormatedLoggerMessage(L));
+ } else {
+ reportErrorFunc("First parameter needs to be a string");
+ }
+ return 1;
+}
diff --git a/src/lua/functions/core/libs/logger_functions.hpp b/src/lua/functions/core/libs/logger_functions.hpp
index 5e83f1461c9..2c4dba46cc1 100644
--- a/src/lua/functions/core/libs/logger_functions.hpp
+++ b/src/lua/functions/core/libs/logger_functions.hpp
@@ -25,4 +25,5 @@ class LoggerFunctions final : public LuaScriptInterface {
static int luaLoggerError(lua_State* L);
static int luaLoggerInfo(lua_State* L);
static int luaLoggerWarn(lua_State* L);
+ static int luaLoggerTrace(lua_State* L);
};
diff --git a/src/server/network/protocol/protocolgame.cpp b/src/server/network/protocol/protocolgame.cpp
index 566f39c7e71..43fa9046cbb 100644
--- a/src/server/network/protocol/protocolgame.cpp
+++ b/src/server/network/protocol/protocolgame.cpp
@@ -2334,10 +2334,10 @@ void ProtocolGame::parseBestiarysendMonsterData(NetworkMessage &msg) {
break;
}
- newmsg.add(shouldAddItem == true ? loot.id : 0);
+ newmsg.add(g_configManager().getBoolean(SHOW_LOOTS_IN_BESTIARY, __FUNCTION__) || shouldAddItem == true ? loot.id : 0);
newmsg.addByte(difficult);
newmsg.addByte(0); // 1 if special event - 0 if regular loot (?)
- if (shouldAddItem == true) {
+ if (g_configManager().getBoolean(SHOW_LOOTS_IN_BESTIARY, __FUNCTION__) || shouldAddItem == true) {
newmsg.addString(loot.name, "ProtocolGame::parseBestiarysendMonsterData - loot.name");
newmsg.addByte(loot.countmax > 0 ? 0x1 : 0x0);
}
@@ -4062,7 +4062,7 @@ void ProtocolGame::sendPremiumTrigger() {
void ProtocolGame::sendTextMessage(const TextMessage &message) {
if (message.type == MESSAGE_NONE) {
g_logger().error("[ProtocolGame::sendTextMessage] - Message type is wrong, missing or invalid for player with name {}, on position {}", player->getName(), player->getPosition().toString());
- player->sendTextMessage(MESSAGE_ADMINISTRADOR, "There was a problem requesting your message, please contact the administrator");
+ player->sendTextMessage(MESSAGE_ADMINISTRATOR, "There was a problem requesting your message, please contact the administrator");
return;
}
diff --git a/src/utils/utils_definitions.hpp b/src/utils/utils_definitions.hpp
index 59f0049ad9c..af2c40ba533 100644
--- a/src/utils/utils_definitions.hpp
+++ b/src/utils/utils_definitions.hpp
@@ -340,7 +340,7 @@ enum MessageClasses : uint8_t {
/* Red message in the console*/ /* TALKTYPE_BROADCAST */
MESSAGE_LOGIN = 17, /* White message at the bottom of the game window and in the console*/
- MESSAGE_ADMINISTRADOR = 18, /* Red message in game window and in the console*/
+ MESSAGE_ADMINISTRATOR = 18, /* Red message in game window and in the console*/
MESSAGE_EVENT_ADVANCE = 19, /* White message in game window and in the console*/
MESSAGE_GAME_HIGHLIGHT = 20, /* Red message in game window and in the console*/
MESSAGE_FAILURE = 21, /* White message at the bottom of the game window"*/