From 06e18ef7e8f4866cf5c120a31bd096625a2eacfc Mon Sep 17 00:00:00 2001 From: Pedro Henrique Alves Cruz Date: Mon, 27 May 2024 15:59:31 -0300 Subject: [PATCH 01/20] feat: 20 Years a Cook quest --- data-otservbr-global/lib/core/quests.lua | 39 ++++++ data-otservbr-global/lib/core/storages.lua | 6 + .../lib/quests/20_years_a_cook_quest.lua | 1 + data-otservbr-global/lib/quests/quest.lua | 1 + .../the_rest_of_ratha.lua | 103 ++++++++++++++ data-otservbr-global/npc/cheaty.lua | 96 +++++++++++++ data-otservbr-global/npc/npctester.lua | 99 +++++++++++++ data-otservbr-global/npc/the_draccoon.lua | 131 ++++++++++++++++++ data/items/items.xml | 5 + data/scripts/lib/register_monster_type.lua | 3 + src/creatures/monsters/monster.cpp | 4 + src/creatures/monsters/monster.hpp | 3 + src/creatures/monsters/monsters.hpp | 1 + .../monster/monster_type_functions.cpp | 16 +++ .../monster/monster_type_functions.hpp | 2 + 15 files changed, 510 insertions(+) create mode 100644 data-otservbr-global/lib/quests/20_years_a_cook_quest.lua create mode 100644 data-otservbr-global/monster/quests/20_years_a_cook_quest/the_rest_of_ratha.lua create mode 100644 data-otservbr-global/npc/cheaty.lua create mode 100644 data-otservbr-global/npc/npctester.lua create mode 100644 data-otservbr-global/npc/the_draccoon.lua diff --git a/data-otservbr-global/lib/core/quests.lua b/data-otservbr-global/lib/core/quests.lua index a35dcb15dea..59de10ff9a7 100644 --- a/data-otservbr-global/lib/core/quests.lua +++ b/data-otservbr-global/lib/core/quests.lua @@ -6510,5 +6510,44 @@ if not Quests then }, }, }, + [49] = { + name = "20 Years a Cook", + startStorageId = Storage.Quest.U13_30.TwentyYearsACook.QuestLine, + startStorageValue = 1, + missions = { + [1] = { + name = "The lair of the Draccoon", + storageId = Storage.Quest.U13_30.TwentyYearsACook.QuestLine, + missionId = 10451, + startValue = 1, + endValue = 2, + description = "Find the Draccoon in his lair. The secret entrance is supposed to be found somewhere in the Venorean dumpster area.", + }, + [2] = { + name = "An old friend", + storageId = Storage.Quest.U13_30.TwentyYearsACook.QuestLine, + missionId = 10452, + startValue = 2, + endValue = 3, + description = "Look for an old friend of the Draccoon. The Draccoon assumes his friend still lives in an appartment in the upper levels of Kazordoon.", + }, + [3] = { + name = "Sad news", + storageId = Storage.Quest.U13_30.TwentyYearsACook.QuestLine, + missionId = 10453, + startValue = 3, + endValue = 4, + description = "Ratha, the Draccoon's old friend has met his ultimely demise. Travel to the Draccoon's lair to inform about Ratha's fate", + }, + [4] = { + name = "Ghost hunt", + storageId = Storage.Quest.U13_30.TwentyYearsACook.QuestLine, + missionId = 10454, + startValue = 4, + endValue = 5, + description = "Meet the ally of the Draccoon in Ratha's quarters in Kazordoon and extract Ratha's spirit.", + }, + }, + }, } end diff --git a/data-otservbr-global/lib/core/storages.lua b/data-otservbr-global/lib/core/storages.lua index fce8059f7d1..92bc4f9d945 100644 --- a/data-otservbr-global/lib/core/storages.lua +++ b/data-otservbr-global/lib/core/storages.lua @@ -2797,6 +2797,12 @@ Storage = { }, }, }, + U13_30 = { -- update 13.30 - Reserved Storages 47952 - 48002 + TwentyYearsACook = { + QuestLine = 47952, + DraccoonOutfits = {}, + }, + }, }, -- Reserved storage from 63951 - 63999 ThaisExhibition = { diff --git a/data-otservbr-global/lib/quests/20_years_a_cook_quest.lua b/data-otservbr-global/lib/quests/20_years_a_cook_quest.lua new file mode 100644 index 00000000000..d370f3c94bd --- /dev/null +++ b/data-otservbr-global/lib/quests/20_years_a_cook_quest.lua @@ -0,0 +1 @@ +TwentyYearsACookQuest = {} \ No newline at end of file diff --git a/data-otservbr-global/lib/quests/quest.lua b/data-otservbr-global/lib/quests/quest.lua index 21b1744fec6..7ba4c8e8796 100644 --- a/data-otservbr-global/lib/quests/quest.lua +++ b/data-otservbr-global/lib/quests/quest.lua @@ -1,3 +1,4 @@ +dofile(DATA_DIRECTORY .. "/lib/quests/20_years_a_cook_quest.lua") dofile(DATA_DIRECTORY .. "/lib/quests/bigfoot_burden.lua") dofile(DATA_DIRECTORY .. "/lib/quests/demon_oak.lua") dofile(DATA_DIRECTORY .. "/lib/quests/grimvale.lua") diff --git a/data-otservbr-global/monster/quests/20_years_a_cook_quest/the_rest_of_ratha.lua b/data-otservbr-global/monster/quests/20_years_a_cook_quest/the_rest_of_ratha.lua new file mode 100644 index 00000000000..da69c7f04c9 --- /dev/null +++ b/data-otservbr-global/monster/quests/20_years_a_cook_quest/the_rest_of_ratha.lua @@ -0,0 +1,103 @@ +local monsterName = "The Rest of Ratha" +local mType = Game.createMonsterType(monsterName) +local monster = {} + +monster.description = monsterName +monster.experience = 0 +monster.outfit = { + lookType = 1692, + lookHead = 0, + lookBody = 0, + lookLegs = 0, + lookFeet = 0, + lookAddons = 0, + lookMount = 0, +} + +monster.events = {} + +monster.health = 200 +monster.maxHealth = 200 +monster.race = "undead" +monster.corpse = 0 +monster.speed = 125 +monster.manaCost = 0 + +monster.changeTarget = { + interval = 0, + chance = 0, +} + +monster.strategiesTarget = { + nearest = 0, + random = 0, +} + +monster.flags = { + canTarget = false, + summonable = false, + attackable = false, + hostile = false, + convinceable = false, + pushable = false, + rewardBoss = false, + illusionable = false, + canPushItems = false, + canPushCreatures = false, + staticAttackChance = 0, + targetDistance = 0, + runHealth = 0, + healthHidden = false, + isBlockable = false, + canWalkOnEnergy = true, + canWalkOnFire = true, + canWalkOnPoison = true, +} + +monster.light = { + level = 0, + color = 0, +} + +monster.summon = {} + +monster.voices = {} + +monster.loot = {} + +monster.attacks = {} + +monster.defenses = {} + +monster.elements = { + { type = COMBAT_PHYSICALDAMAGE, percent = 0 }, + { type = COMBAT_ENERGYDAMAGE, percent = 0 }, + { type = COMBAT_EARTHDAMAGE, percent = 0 }, + { type = COMBAT_FIREDAMAGE, percent = 0 }, + { type = COMBAT_LIFEDRAIN, percent = 0 }, + { type = COMBAT_MANADRAIN, percent = 0 }, + { type = COMBAT_DROWNDAMAGE, percent = 0 }, + { type = COMBAT_ICEDAMAGE, percent = 0 }, + { type = COMBAT_HOLYDAMAGE, percent = 0 }, + { type = COMBAT_DEATHDAMAGE, percent = 0 }, +} + +monster.immunities = { + { type = "paralyze", condition = true }, + { type = "outfit", condition = false }, + { type = "invisible", condition = true }, + { type = "bleed", condition = false }, +} + +mType.onThink = function(monster, interval) + local monsterPosition = monster:getPosition() + if monster then + for i, player in pairs(Game.getSpectators(monsterPosition, false, true, 0, 1, 0, 1)) do + if player:getStorageValue(Storage.Quest.U13_30.TwentyYearsACook.QuestLine) == 2 then + player:setStorageValue(Storage.Quest.U13_30.TwentyYearsACook.QuestLine, 3) + end + end + end +end + +mType:register(monster) diff --git a/data-otservbr-global/npc/cheaty.lua b/data-otservbr-global/npc/cheaty.lua new file mode 100644 index 00000000000..71c7d7d0432 --- /dev/null +++ b/data-otservbr-global/npc/cheaty.lua @@ -0,0 +1,96 @@ +local internalNpcName = "Cheaty" +local npcType = Game.createNpcType(internalNpcName) +local npcConfig = {} + +npcConfig.name = internalNpcName +npcConfig.description = internalNpcName + +npcConfig.health = 100 +npcConfig.maxHealth = npcConfig.health +npcConfig.walkInterval = 2000 +npcConfig.walkRadius = 2 + +npcConfig.outfit = { + lookType = 1378, + lookHead = 78, + lookBody = 78, + lookLegs = 90, + lookFeet = 0, + lookAddons = 0, +} + +npcConfig.flags = { + floorchange = false, +} + +local keywordHandler = KeywordHandler:new() +local npcHandler = NpcHandler:new(keywordHandler) + +npcType.onThink = function(npc, interval) + npcHandler:onThink(npc, interval) +end + +npcType.onAppear = function(npc, creature) + npcHandler:onAppear(npc, creature) +end + +npcType.onDisappear = function(npc, creature) + npcHandler:onDisappear(npc, creature) +end + +npcType.onMove = function(npc, creature, fromPosition, toPosition) + npcHandler:onMove(npc, creature, fromPosition, toPosition) +end + +npcType.onSay = function(npc, creature, type, message) + npcHandler:onSay(npc, creature, type, message) +end + +npcType.onCloseChannel = function(npc, creature) + npcHandler:onCloseChannel(npc, creature) +end + +local function creatureSayCallback(npc, creature, type, message) + local player = Player(creature) + local playerId = player:getId() + local questline = player:getStorageValue(Storage.Quest.U13_30.TwentyYearsACook.QuestLine) + + if not npcHandler:checkInteraction(npc, creature) then + return false + end + if MsgContains(message, "name") or MsgContains(message, "cheaty") then + npcHandler:say("I am Cheaty Chief, just call me Cheaty, no need for formalities like calling me Miss. ", npc, creature) + elseif MsgContains(message, "draccoon") then + npcHandler:say("The Draccoon is a magnificent creature, somewhat like a rascoohan, somewhat like a dragon. ...", npc, creature) + npcHandler:say("He taught me my first few spells when I was a little cub.", npc, creature, 2000) + elseif MsgContains(message, "venore") then + npcHandler:say("Ah, good old Venore, the city of trash.", npc, creature) + elseif MsgContains(message, "talk") then + player:setStorageValue(Storage.Quest.U13_30.TwentyYearsACook.QuestLine, 0) + npcHandler:say("The Draccoon has just returned after a longer inconvenient absence. He could use the help of some talented individuals and has a mission for them. Are you interested, {yes} or {no}?", npc, creature) + npcHandler:setTopic(playerId, 1) + elseif MsgContains(message, "yes") then + if npcHandler:getTopic(playerId) == 1 and questline < 1 then + npcHandler:say("Search for the entrance to the secret lair of the {Draccoon} at the Venore dumpster!", npc, creature) + npcHandler:setTopic(playerId, 0) + player:setStorageValue(Storage.Quest.U13_30.TwentyYearsACook.QuestLine, 1) + end + elseif MsgContains(message, "no") then + if npcHandler:getTopic(playerId) == 1 then + npcHandler:say("Oh, well, if you change your mind, you know where to find me!", npc, creature) + npcHandler:setTopic(playerId, 0) + end + end + return true +end + +npcHandler:setMessage(MESSAGE_GREET, "Be greeted, |PLAYERNAME|! My friend, the Draccoon, wants to have a {talk} with you!") + +npcHandler:setMessage(MESSAGE_FAREWELL, "Bye, bye, |PLAYERNAME|.") + +npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback) + +npcHandler:addModule(FocusModule:new(), npcConfig.name, true, true, true) + +-- npcType registering the npcConfig table +npcType:register(npcConfig) diff --git a/data-otservbr-global/npc/npctester.lua b/data-otservbr-global/npc/npctester.lua new file mode 100644 index 00000000000..e3ad2fbc345 --- /dev/null +++ b/data-otservbr-global/npc/npctester.lua @@ -0,0 +1,99 @@ +local internalNpcName = "Just a Test NPC" +local npcType = Game.createNpcType(internalNpcName) +local npcConfig = {} + +npcConfig.name = internalNpcName +npcConfig.description = internalNpcName + +npcConfig.health = 150 +npcConfig.maxHealth = npcConfig.health +npcConfig.walkInterval = 2000 +npcConfig.walkRadius = 2 + +npcConfig.outfit = { + lookType = 146, + lookHead = 85, + lookBody = 7, + lookLegs = 12, + lookFeet = 19, + lookAddons = 2, +} + +npcConfig.flags = { + floorchange = false, +} + +local keywordHandler = KeywordHandler:new() +local npcHandler = NpcHandler:new(keywordHandler) + +npcType.onThink = function(npc, interval) + npcHandler:onThink(npc, interval) +end + +npcType.onAppear = function(npc, creature) + npcHandler:onAppear(npc, creature) +end + +npcType.onDisappear = function(npc, creature) + npcHandler:onDisappear(npc, creature) +end + +npcType.onMove = function(npc, creature, fromPosition, toPosition) + npcHandler:onMove(npc, creature, fromPosition, toPosition) +end + +npcType.onSay = function(npc, creature, type, message) + npcHandler:onSay(npc, creature, type, message) +end + +npcType.onCloseChannel = function(npc, creature) + npcHandler:onCloseChannel(npc, creature) +end + +npcConfig.shop = { + { itemName = "acorn", clientId = 10296, sell = 4000000000 }, + { itemName = "blank rune", clientId = 3147, buy = 4000000000 }, +} +-- On buy npc shop message +npcType.onBuyItem = function(npc, player, itemId, subType, amount, ignore, inBackpacks, totalCost) + npc:sellItem(player, itemId, amount, subType, 0, ignore, inBackpacks) +end +-- On sell npc shop message +npcType.onSellItem = function(npc, player, itemId, subtype, amount, ignore, name, totalCost) + player:sendTextMessage(MESSAGE_TRADE, string.format("Sold %ix %s for %i gold.", amount, name, totalCost)) +end +-- On check npc shop message (look item) +npcType.onCheckItem = function(npc, player, clientId, subType) end + +local function creatureSayCallback(npc, creature, type, message) + local player = Player(creature) + local playerId = player:getId() + + if not npcHandler:checkInteraction(npc, creature) then + return false + end + + if MsgContains(message, "name") then + return npcHandler:say("Me Yasir.", npc, creature) + elseif MsgContains(message, "job") then + return npcHandler:say("Tje hari ku ne finjala. {Ariki}?", npc, creature) + elseif MsgContains(message, "passage") then + return npcHandler:say("Soso yana. ", npc, creature) + elseif MsgContains(message, "ariki") then + npc:openShopWindow(creature) + creature:addAchievement("Si, Ariki!") + end + return true +end + +local function onTradeRequest(npc, creature, message) + creature:addAchievement("Si, Ariki!") + return true +end + +npcHandler:setMessage(MESSAGE_FAREWELL, "Si, jema ze harun. ") +npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback) +npcHandler:setCallback(CALLBACK_ON_TRADE_REQUEST, onTradeRequest) +npcHandler:addModule(FocusModule:new(), npcConfig.name, true, true, true) + +npcType:register(npcConfig) diff --git a/data-otservbr-global/npc/the_draccoon.lua b/data-otservbr-global/npc/the_draccoon.lua new file mode 100644 index 00000000000..ddb2a05bb5d --- /dev/null +++ b/data-otservbr-global/npc/the_draccoon.lua @@ -0,0 +1,131 @@ +local internalNpcName = "The Draccoon" +local npcType = Game.createNpcType(internalNpcName) +local npcConfig = {} + +npcConfig.name = internalNpcName +npcConfig.description = internalNpcName + +npcConfig.health = 100 +npcConfig.maxHealth = npcConfig.health +npcConfig.walkInterval = 2000 +npcConfig.walkRadius = 2 + +npcConfig.outfit = { + lookType = 1703, + lookHead = 0, + lookBody = 0, + lookLegs = 0, + lookFeet = 0, + lookAddons = 0, +} + +npcConfig.flags = { + floorchange = false, +} + +local keywordHandler = KeywordHandler:new() +local npcHandler = NpcHandler:new(keywordHandler) + +npcType.onThink = function(npc, interval) + npcHandler:onThink(npc, interval) +end + +npcType.onAppear = function(npc, creature) + npcHandler:onAppear(npc, creature) +end + +npcType.onDisappear = function(npc, creature) + npcHandler:onDisappear(npc, creature) +end + +npcType.onMove = function(npc, creature, fromPosition, toPosition) + npcHandler:onMove(npc, creature, fromPosition, toPosition) +end + +npcType.onSay = function(npc, creature, type, message) + npcHandler:onSay(npc, creature, type, message) +end + +npcType.onCloseChannel = function(npc, creature) + npcHandler:onCloseChannel(npc, creature) +end + +local function creatureSayCallback(npc, creature, type, message) + local player = Player(creature) + local playerId = player:getId() + local questline = player:getStorageValue(Storage.Quest.U13_30.TwentyYearsACook.QuestLine) + + if not npcHandler:checkInteraction(npc, creature) then + return false + end + if MsgContains(message, "name") or MsgContains(message, "draccoon") then + npcHandler:say("I'm just known as 'The Draccoon'! Like some famous artists, you know. I am one of a kind anyway!", npc, creature) + elseif MsgContains(message, "job") then + npcHandler:say("Besides being awesome? I make {plans}.", npc, creature) + elseif MsgContains(message, "venore") then + npcHandler:say("The city has changed so much, since I left! I hardly recognized it!", npc, creature) + elseif MsgContains(message, "plans") then + npcHandler:say("I love it, when a plan comes together.", npc, creature) + elseif MsgContains(message, "glad") then + npcHandler:say("I need your assistance in a {quest} of mine!?", npc, creature) + npcHandler:setTopic(playerId, 1) + elseif MsgContains(message, "quest") then + if npcHandler:getTopic(playerId) == 1 then + npcHandler:say("Due to treachery and malice the evil dragon Nimmersatt managed to catch me in a trap and held me {captive} for 20 years!", npc, creature) + npcHandler:setTopic(playerId, 2) + end + elseif MsgContains(message, "captive") then + if npcHandler:getTopic(playerId) == 2 then + npcHandler:say("As he is greedy and always hungry, he made me one of his cooks! I had to serve him the finest meals for 20 years, to his constant {complaints}!", npc, creature) + npcHandler:setTopic(playerId, 3) + end + elseif MsgContains(message, "complaints") then + if npcHandler:getTopic(playerId) == 3 then + npcHandler:say("He was never satisfied and always found something to criticise and his complaints never stopped! ...", npc, creature) + npcHandler:say("Gladly over the years, he let his guard down and I managed to {escape}!", npc, creature, 2000) + npcHandler:setTopic(playerId, 4) + end + elseif MsgContains(message, "escape") then + if npcHandler:getTopic(playerId) == 4 then + npcHandler:say("Now that I am free again, I am plotting my revenge... and this is where you enter the {picture}!", npc, creature) + npcHandler:setTopic(playerId, 5) + end + elseif MsgContains(message, "picture") then + if npcHandler:getTopic(playerId) == 5 then + npcHandler:say("Even in captivity, I heard about all your exploits and deeds and decided you are just the person I need to bring my plans to fruition! ...", npc, creature) + npcHandler:say("I hope you are ready for that {mission}!", npc, creature, 2000) + npcHandler:setTopic(playerId, 6) + end + elseif MsgContains(message, "mission") then + local mission = player:getStorageValue(Storage.Quest.U13_30.TwentyYearsACook.QuestLine) + if npcHandler:getTopic(playerId) <= 5 and mission == 1 then + npcHandler:say("Well, the dragon Nimmersatt managed to catch me off guard and entrapped me with the intention to devour me. ...", npc, creature) + npcHandler:say("Knowing his insatiable appetite, I managed to talk him into accepting me as one of his cooks! Indeed, my cooking skills aren't garbage, so to say, and I managed to prolong my life for one year after the other. ...", npc, creature, 2000) + npcHandler:say("Over the years, even Nimmersatt himself let his guard down, and I learned many of his secrets. After 20 years, I finally managed to trick myself out of his clutches and managed to {escape}! ...", npc, creature, 2000) + npcHandler:say("Now the time of the revenge of the {Draccoon} has come! Nimmersatt will pay dearly for what he did to me! But not only that! ...", npc, creature, 2000) + npcHandler:say("There are also old friends to be contacted, debts to be called in, and some other culprits to be punished for their role in my capture and imprisonment! ...", npc, creature, 2000) + npcHandler:say("I'd like you to assist me in that {mission}.", npc, creature, 2000) + npcHandler:setTopic(playerId, 6) + elseif mission == 1 then + npcHandler:say("My dearest human friend must yet be informed of my return. I am sure he will join us in our campaign! ...", npc, creature) + npcHandler:say("He lives in an apartment in Kazordoon, as I understand he had some trouble in most other cities. I'm pretty sure you'll still find him there. ...", npc, creature, 2000) + npcHandler:say("Just pay him a visit and tell him, his good old pal, the Draccoon is back!", npc, creature, 2000) + npcHandler:setTopic(playerId, 0) + player:setStorageValue(Storage.Quest.U13_30.TwentyYearsACook.QuestLine, 2) + elseif mission == 2 then + + end + end + return true +end + +npcHandler:setMessage(MESSAGE_GREET, "Hello, |PLAYERNAME|! I am {glad} to see you!") + +npcHandler:setMessage(MESSAGE_FAREWELL, "Good bye, my friend!") + +npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback) + +npcHandler:addModule(FocusModule:new(), npcConfig.name, true, true, true) + +-- npcType registering the npcConfig table +npcType:register(npcConfig) diff --git a/data/items/items.xml b/data/items/items.xml index e7e73d9753b..ea08a440e61 100644 --- a/data/items/items.xml +++ b/data/items/items.xml @@ -75748,6 +75748,11 @@ Granted by TibiaGoals.com"/> + + + + + diff --git a/data/scripts/lib/register_monster_type.lua b/data/scripts/lib/register_monster_type.lua index a9cfaee3354..fcd9f550ed9 100644 --- a/data/scripts/lib/register_monster_type.lua +++ b/data/scripts/lib/register_monster_type.lua @@ -165,6 +165,9 @@ registerMonsterType.flags = function(mtype, mask) if mask.flags.attackable ~= nil then mtype:isAttackable(mask.flags.attackable) end + if mask.flags.canTarget ~= nil then + mtype:canTarget(mask.flags.canTarget) + end if mask.flags.convinceable ~= nil then mtype:isConvinceable(mask.flags.convinceable) end diff --git a/src/creatures/monsters/monster.cpp b/src/creatures/monsters/monster.cpp index fccc19b05e5..d05b3060609 100644 --- a/src/creatures/monsters/monster.cpp +++ b/src/creatures/monsters/monster.cpp @@ -660,6 +660,10 @@ bool Monster::selectTarget(const std::shared_ptr &creature) { return false; } + if (!canTarget()) { + return false; + } + const auto &it = getTargetIterator(creature); if (it == targetList.end()) { // Target not found in our target list. diff --git a/src/creatures/monsters/monster.hpp b/src/creatures/monsters/monster.hpp index bf9a39e4133..87f01a0c88a 100644 --- a/src/creatures/monsters/monster.hpp +++ b/src/creatures/monsters/monster.hpp @@ -102,6 +102,9 @@ class Monster final : public Creature { bool isAttackable() const override { return mType->info.isAttackable; } + bool canTarget() const { + return mType->info.canTarget; + } bool canPushItems() const { return mType->info.canPushItems; } diff --git a/src/creatures/monsters/monsters.hpp b/src/creatures/monsters/monsters.hpp index 518befd8a70..ae48ceba6a5 100644 --- a/src/creatures/monsters/monsters.hpp +++ b/src/creatures/monsters/monsters.hpp @@ -139,6 +139,7 @@ class MonsterType { Faction_t faction = FACTION_DEFAULT; stdext::vector_set enemyFactions; + bool canTarget = true; bool canPushItems = false; bool canPushCreatures = false; bool pushable = true; diff --git a/src/lua/functions/creatures/monster/monster_type_functions.cpp b/src/lua/functions/creatures/monster/monster_type_functions.cpp index b937083fddb..96e4f469746 100644 --- a/src/lua/functions/creatures/monster/monster_type_functions.cpp +++ b/src/lua/functions/creatures/monster/monster_type_functions.cpp @@ -249,6 +249,22 @@ int MonsterTypeFunctions::luaMonsterTypeCanSpawn(lua_State* L) { return 1; } +int MonsterTypeFunctions::luaMonsterTypeCanTarget(lua_State* L) { + // get: monsterType:canTarget() set: monsterType:canTarget(bool) + const auto monsterType = getUserdataShared(L, 1); + if (monsterType) { + if (lua_gettop(L) == 1) { + pushBoolean(L, monsterType->info.canTarget); + } else { + monsterType->info.canTarget = getBoolean(L, 2); + pushBoolean(L, true); + } + } else { + lua_pushnil(L); + } + return 1; +} + int MonsterTypeFunctions::luaMonsterTypeCanPushItems(lua_State* L) { // get: monsterType:canPushItems() set: monsterType:canPushItems(bool) const auto monsterType = getUserdataShared(L, 1); diff --git a/src/lua/functions/creatures/monster/monster_type_functions.hpp b/src/lua/functions/creatures/monster/monster_type_functions.hpp index 9a72f53b145..3d1e0f82f09 100644 --- a/src/lua/functions/creatures/monster/monster_type_functions.hpp +++ b/src/lua/functions/creatures/monster/monster_type_functions.hpp @@ -32,6 +32,7 @@ class MonsterTypeFunctions final : LuaScriptInterface { registerMethod(L, "MonsterType", "canSpawn", MonsterTypeFunctions::luaMonsterTypeCanSpawn); + registerMethod(L, "MonsterType", "canTarget", MonsterTypeFunctions::luaMonsterTypeCanTarget); registerMethod(L, "MonsterType", "canPushItems", MonsterTypeFunctions::luaMonsterTypeCanPushItems); registerMethod(L, "MonsterType", "canPushCreatures", MonsterTypeFunctions::luaMonsterTypeCanPushCreatures); @@ -163,6 +164,7 @@ class MonsterTypeFunctions final : LuaScriptInterface { static int luaMonsterTypeRespawnType(lua_State* L); static int luaMonsterTypeCanSpawn(lua_State* L); + static int luaMonsterTypeCanTarget(lua_State* L); static int luaMonsterTypeCanPushItems(lua_State* L); static int luaMonsterTypeCanPushCreatures(lua_State* L); From 4aa16d4cdecf64aac17e27485e0d9b8c712c26a9 Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Mon, 27 May 2024 19:00:37 +0000 Subject: [PATCH 02/20] Lua code format - (Stylua) --- data-otservbr-global/lib/quests/20_years_a_cook_quest.lua | 2 +- data-otservbr-global/npc/the_draccoon.lua | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/data-otservbr-global/lib/quests/20_years_a_cook_quest.lua b/data-otservbr-global/lib/quests/20_years_a_cook_quest.lua index d370f3c94bd..43b7528e5e0 100644 --- a/data-otservbr-global/lib/quests/20_years_a_cook_quest.lua +++ b/data-otservbr-global/lib/quests/20_years_a_cook_quest.lua @@ -1 +1 @@ -TwentyYearsACookQuest = {} \ No newline at end of file +TwentyYearsACookQuest = {} diff --git a/data-otservbr-global/npc/the_draccoon.lua b/data-otservbr-global/npc/the_draccoon.lua index ddb2a05bb5d..be5d5806d02 100644 --- a/data-otservbr-global/npc/the_draccoon.lua +++ b/data-otservbr-global/npc/the_draccoon.lua @@ -113,7 +113,6 @@ local function creatureSayCallback(npc, creature, type, message) npcHandler:setTopic(playerId, 0) player:setStorageValue(Storage.Quest.U13_30.TwentyYearsACook.QuestLine, 2) elseif mission == 2 then - end end return true From 52606fe6305738ce54b9f8ddae3b677c8eb3eee9 Mon Sep 17 00:00:00 2001 From: Pedro Henrique Alves Cruz Date: Wed, 29 May 2024 23:10:52 -0300 Subject: [PATCH 03/20] feat: the rest of ratha mechanics --- data-otservbr-global/lib/core/quests.lua | 8 ++ data-otservbr-global/lib/core/storages.lua | 2 + .../lib/quests/20_years_a_cook_quest.lua | 20 +++- .../20_years_a_cook_quest/ghost_duster.lua | 93 +++++++++++++++++ .../spirit_container.lua | 88 +++++++++++++++++ .../the_rest_of_ratha.lua | 64 ++++++++---- data-otservbr-global/npc/npctester.lua | 99 ------------------- data-otservbr-global/npc/the_draccoon.lua | 6 +- .../ghost_duster_creaturescripts.lua | 60 +++++++++++ .../20_years_a_cook_quest/harp_action.lua | 34 +++++++ .../omnious_trash_moveevents.lua | 53 ++++++++++ .../spirit_flask_action.lua | 58 +++++++++++ .../the_rest_of_ratha_fight.lua | 26 +++++ .../the_rest_of_ratha_lever.lua | 27 +++++ .../startup/tables/door_quest.lua | 5 + data/scripts/lib/register_monster_type.lua | 3 + src/creatures/monsters/monster.cpp | 2 +- src/creatures/monsters/monster.hpp | 3 + src/creatures/monsters/monsters.hpp | 1 + .../monster/monster_type_functions.cpp | 16 +++ .../monster/monster_type_functions.hpp | 2 + 21 files changed, 550 insertions(+), 120 deletions(-) create mode 100644 data-otservbr-global/monster/quests/20_years_a_cook_quest/ghost_duster.lua create mode 100644 data-otservbr-global/monster/quests/20_years_a_cook_quest/spirit_container.lua delete mode 100644 data-otservbr-global/npc/npctester.lua create mode 100644 data-otservbr-global/scripts/quests/20_years_a_cook_quest/ghost_duster_creaturescripts.lua create mode 100644 data-otservbr-global/scripts/quests/20_years_a_cook_quest/harp_action.lua create mode 100644 data-otservbr-global/scripts/quests/20_years_a_cook_quest/omnious_trash_moveevents.lua create mode 100644 data-otservbr-global/scripts/quests/20_years_a_cook_quest/spirit_flask_action.lua create mode 100644 data-otservbr-global/scripts/quests/20_years_a_cook_quest/the_rest_of_ratha_fight.lua create mode 100644 data-otservbr-global/scripts/quests/20_years_a_cook_quest/the_rest_of_ratha_lever.lua diff --git a/data-otservbr-global/lib/core/quests.lua b/data-otservbr-global/lib/core/quests.lua index 59de10ff9a7..aa5b4b52f3d 100644 --- a/data-otservbr-global/lib/core/quests.lua +++ b/data-otservbr-global/lib/core/quests.lua @@ -6547,6 +6547,14 @@ if not Quests then endValue = 5, description = "Meet the ally of the Draccoon in Ratha's quarters in Kazordoon and extract Ratha's spirit.", }, + [5] = { + name = "Ghost hunt", + storageId = Storage.Quest.U13_30.TwentyYearsACook.QuestLine, + missionId = 10455, + startValue = 5, + endValue = 6, + description = "Travel to the Draccoon's lair to learn how to proceed.", + } }, }, } diff --git a/data-otservbr-global/lib/core/storages.lua b/data-otservbr-global/lib/core/storages.lua index 92bc4f9d945..3cd41a89c4b 100644 --- a/data-otservbr-global/lib/core/storages.lua +++ b/data-otservbr-global/lib/core/storages.lua @@ -2800,6 +2800,8 @@ Storage = { U13_30 = { -- update 13.30 - Reserved Storages 47952 - 48002 TwentyYearsACook = { QuestLine = 47952, + TheRestOfRathaDoor = 47953, + FlaskBox = 47954, DraccoonOutfits = {}, }, }, diff --git a/data-otservbr-global/lib/quests/20_years_a_cook_quest.lua b/data-otservbr-global/lib/quests/20_years_a_cook_quest.lua index 43b7528e5e0..6386125f1ba 100644 --- a/data-otservbr-global/lib/quests/20_years_a_cook_quest.lua +++ b/data-otservbr-global/lib/quests/20_years_a_cook_quest.lua @@ -1 +1,19 @@ -TwentyYearsACookQuest = {} +TwentyYearsACookQuest = { + TheRestOfRatha = { + MissionZone = Zone("mission.the-rest-of-ratha"), + BossZone = Zone("boss.the-rest-of-ratha"), + Items = { + GhostItem = 44598, + EmptySpiritFlask = 44527, + FullSpiritFlask = 44528, + Harp = 44599, + HarpCooldown = 44600, + }, + FlaskBoxUID = 62134, + SpiritContainerPoints = 0, + }, +} + +-- Initializing zones +TwentyYearsACookQuest.TheRestOfRatha.MissionZone:addArea({ x = 33303, y = 31425, z = 15 }, { x = 33327, y = 31445, z = 15 }) +TwentyYearsACookQuest.TheRestOfRatha.BossZone:addArea({ x = 33303, y = 31388, z = 15 }, { x = 33327, y = 31408, z = 15 }) diff --git a/data-otservbr-global/monster/quests/20_years_a_cook_quest/ghost_duster.lua b/data-otservbr-global/monster/quests/20_years_a_cook_quest/ghost_duster.lua new file mode 100644 index 00000000000..048854106df --- /dev/null +++ b/data-otservbr-global/monster/quests/20_years_a_cook_quest/ghost_duster.lua @@ -0,0 +1,93 @@ +local monsterName = "Ghost Duster" +local mType = Game.createMonsterType(monsterName) +local monster = {} + +monster.description = monsterName +monster.experience = 0 +monster.outfit = { + lookTypeEx = 40574, +} + +monster.events = { + "GhostDusterAttack" +} + +monster.health = 100000000 +monster.maxHealth = 100000000 +monster.race = "energy" +monster.corpse = 0 +monster.speed = 20 +monster.manaCost = 0 + +monster.changeTarget = { + interval = 0, + chance = 0, +} + +monster.strategiesTarget = { + nearest = 0, + random = 0, +} + +monster.flags = { + canWalk = false, + canTarget = false, + summonable = false, + attackable = true, + hostile = false, + convinceable = false, + pushable = true, + rewardBoss = false, + illusionable = false, + canPushItems = false, + canPushCreatures = false, + staticAttackChance = 0, + targetDistance = 0, + runHealth = 0, + healthHidden = false, + isBlockable = false, + canWalkOnEnergy = false, + canWalkOnFire = false, + canWalkOnPoison = false, +} + +monster.light = { + level = 0, + color = 0, +} + +monster.summon = {} + +monster.voices = {} + +monster.loot = {} + +monster.attacks = {} + +monster.defenses = { + { name = "combat", type = COMBAT_HEALING, chance = 100, interval = 2000, minDamage = 100000000, maxDamage = 100000000, effect = CONST_ME_NONE }, +} + +monster.elements = { + { type = COMBAT_PHYSICALDAMAGE, percent = 0 }, + { type = COMBAT_ENERGYDAMAGE, percent = 0 }, + { type = COMBAT_EARTHDAMAGE, percent = 0 }, + { type = COMBAT_FIREDAMAGE, percent = 0 }, + { type = COMBAT_LIFEDRAIN, percent = 0 }, + { type = COMBAT_MANADRAIN, percent = 0 }, + { type = COMBAT_DROWNDAMAGE, percent = 0 }, + { type = COMBAT_ICEDAMAGE, percent = 0 }, + { type = COMBAT_HOLYDAMAGE, percent = 0 }, + { type = COMBAT_DEATHDAMAGE, percent = 0 }, +} + +monster.immunities = { + { type = "paralyze", condition = true }, + { type = "outfit", condition = true }, + { type = "invisible", condition = true }, + { type = "bleed", condition = true }, +} + +mType.onThink = function(monster, interval) end + +mType:register(monster) diff --git a/data-otservbr-global/monster/quests/20_years_a_cook_quest/spirit_container.lua b/data-otservbr-global/monster/quests/20_years_a_cook_quest/spirit_container.lua new file mode 100644 index 00000000000..aff8f2ee840 --- /dev/null +++ b/data-otservbr-global/monster/quests/20_years_a_cook_quest/spirit_container.lua @@ -0,0 +1,88 @@ +local monsterName = "Spirit Container" +local mType = Game.createMonsterType(monsterName) +local monster = {} + +monster.description = monsterName +monster.experience = 0 +monster.outfit = { + lookTypeEx = 40495, +} + +monster.events = {} + +monster.health = 200 +monster.maxHealth = 200 +monster.race = "undead" +monster.corpse = 0 +monster.speed = 0 +monster.manaCost = 0 + +monster.changeTarget = { + interval = 0, + chance = 0, +} + +monster.strategiesTarget = { + nearest = 0, + random = 0, +} + +monster.flags = { + canTarget = false, + summonable = false, + attackable = false, + hostile = false, + convinceable = false, + pushable = false, + rewardBoss = false, + illusionable = false, + canPushItems = false, + canPushCreatures = false, + staticAttackChance = 0, + targetDistance = 0, + runHealth = 0, + healthHidden = false, + isBlockable = false, + canWalkOnEnergy = false, + canWalkOnFire = false, + canWalkOnPoison = false, +} + +monster.light = { + level = 0, + color = 0, +} + +monster.summon = {} + +monster.voices = {} + +monster.loot = {} + +monster.attacks = {} + +monster.defenses = {} + +monster.elements = { + { type = COMBAT_PHYSICALDAMAGE, percent = 0 }, + { type = COMBAT_ENERGYDAMAGE, percent = 0 }, + { type = COMBAT_EARTHDAMAGE, percent = 0 }, + { type = COMBAT_FIREDAMAGE, percent = 0 }, + { type = COMBAT_LIFEDRAIN, percent = 0 }, + { type = COMBAT_MANADRAIN, percent = 0 }, + { type = COMBAT_DROWNDAMAGE, percent = 0 }, + { type = COMBAT_ICEDAMAGE, percent = 0 }, + { type = COMBAT_HOLYDAMAGE, percent = 0 }, + { type = COMBAT_DEATHDAMAGE, percent = 0 }, +} + +monster.immunities = { + { type = "paralyze", condition = true }, + { type = "outfit", condition = true }, + { type = "invisible", condition = true }, + { type = "bleed", condition = true }, +} + +mType.onThink = function(monster, interval) end + +mType:register(monster) diff --git a/data-otservbr-global/monster/quests/20_years_a_cook_quest/the_rest_of_ratha.lua b/data-otservbr-global/monster/quests/20_years_a_cook_quest/the_rest_of_ratha.lua index da69c7f04c9..011a14ef9f1 100644 --- a/data-otservbr-global/monster/quests/20_years_a_cook_quest/the_rest_of_ratha.lua +++ b/data-otservbr-global/monster/quests/20_years_a_cook_quest/the_rest_of_ratha.lua @@ -16,8 +16,8 @@ monster.outfit = { monster.events = {} -monster.health = 200 -monster.maxHealth = 200 +monster.health = 10000 +monster.maxHealth = 10000 monster.race = "undead" monster.corpse = 0 monster.speed = 125 @@ -36,7 +36,7 @@ monster.strategiesTarget = { monster.flags = { canTarget = false, summonable = false, - attackable = false, + attackable = true, hostile = false, convinceable = false, pushable = false, @@ -67,36 +67,64 @@ monster.loot = {} monster.attacks = {} -monster.defenses = {} +monster.defenses = { + { name = "combat", type = COMBAT_HEALING, chance = 100, interval = 2000, minDamage = 10000, maxDamage = 10000, effect = CONST_ME_NONE }, +} monster.elements = { - { type = COMBAT_PHYSICALDAMAGE, percent = 0 }, - { type = COMBAT_ENERGYDAMAGE, percent = 0 }, - { type = COMBAT_EARTHDAMAGE, percent = 0 }, - { type = COMBAT_FIREDAMAGE, percent = 0 }, - { type = COMBAT_LIFEDRAIN, percent = 0 }, - { type = COMBAT_MANADRAIN, percent = 0 }, - { type = COMBAT_DROWNDAMAGE, percent = 0 }, - { type = COMBAT_ICEDAMAGE, percent = 0 }, - { type = COMBAT_HOLYDAMAGE, percent = 0 }, - { type = COMBAT_DEATHDAMAGE, percent = 0 }, + { type = COMBAT_PHYSICALDAMAGE, percent = 100 }, + { type = COMBAT_ENERGYDAMAGE, percent = 100 }, + { type = COMBAT_EARTHDAMAGE, percent = 100 }, + { type = COMBAT_FIREDAMAGE, percent = 100 }, + { type = COMBAT_LIFEDRAIN, percent = 100 }, + { type = COMBAT_MANADRAIN, percent = 100 }, + { type = COMBAT_DROWNDAMAGE, percent = 100 }, + { type = COMBAT_ICEDAMAGE, percent = 100 }, + { type = COMBAT_HOLYDAMAGE, percent = 100 }, + { type = COMBAT_DEATHDAMAGE, percent = 100 }, } monster.immunities = { { type = "paralyze", condition = true }, - { type = "outfit", condition = false }, + { type = "outfit", condition = true }, { type = "invisible", condition = true }, - { type = "bleed", condition = false }, + { type = "bleed", condition = true }, } +local effectSent = true + mType.onThink = function(monster, interval) - local monsterPosition = monster:getPosition() - if monster then + local monsterPosition = monster and monster:getPosition() or nil + if monsterPosition and TwentyYearsACookQuest.TheRestOfRatha.MissionZone:isInZone(monsterPosition) then for i, player in pairs(Game.getSpectators(monsterPosition, false, true, 0, 1, 0, 1)) do if player:getStorageValue(Storage.Quest.U13_30.TwentyYearsACook.QuestLine) == 2 then + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have found the friend of the Draccoon or what's left of him, You should tell the Draccoon about it!") player:setStorageValue(Storage.Quest.U13_30.TwentyYearsACook.QuestLine, 3) end end + elseif monsterPosition and TwentyYearsACookQuest.TheRestOfRatha.BossZone:isInZone(monsterPosition) then + local appliedCondition = monster:getCondition(CONDITION_PARALYZE) + local conditionsTicks = appliedCondition and appliedCondition:getTicks() or 0 + if conditionsTicks > 0 then + local tile = Tile(monsterPosition) + if conditionsTicks % 2000 == 0 then + monsterPosition:sendMagicEffect(CONST_ME_BLACK_BLOOD) + end + if tile and not tile:getItemById(TwentyYearsACookQuest.TheRestOfRatha.Items.GhostItem) then + effectSent = false + local item = Game.createItem(TwentyYearsACookQuest.TheRestOfRatha.Items.GhostItem, 1, monsterPosition) + addEvent(function(position) + local tile = Tile(position) + local ghostItem = tile:getItemById(TwentyYearsACookQuest.TheRestOfRatha.Items.GhostItem) + if ghostItem then + ghostItem:remove() + end + end, 6000, monsterPosition) + end + elseif not effectSent then + effectSent = true + monsterPosition:sendMagicEffect(CONST_ME_MORTAREA) + end end end diff --git a/data-otservbr-global/npc/npctester.lua b/data-otservbr-global/npc/npctester.lua deleted file mode 100644 index e3ad2fbc345..00000000000 --- a/data-otservbr-global/npc/npctester.lua +++ /dev/null @@ -1,99 +0,0 @@ -local internalNpcName = "Just a Test NPC" -local npcType = Game.createNpcType(internalNpcName) -local npcConfig = {} - -npcConfig.name = internalNpcName -npcConfig.description = internalNpcName - -npcConfig.health = 150 -npcConfig.maxHealth = npcConfig.health -npcConfig.walkInterval = 2000 -npcConfig.walkRadius = 2 - -npcConfig.outfit = { - lookType = 146, - lookHead = 85, - lookBody = 7, - lookLegs = 12, - lookFeet = 19, - lookAddons = 2, -} - -npcConfig.flags = { - floorchange = false, -} - -local keywordHandler = KeywordHandler:new() -local npcHandler = NpcHandler:new(keywordHandler) - -npcType.onThink = function(npc, interval) - npcHandler:onThink(npc, interval) -end - -npcType.onAppear = function(npc, creature) - npcHandler:onAppear(npc, creature) -end - -npcType.onDisappear = function(npc, creature) - npcHandler:onDisappear(npc, creature) -end - -npcType.onMove = function(npc, creature, fromPosition, toPosition) - npcHandler:onMove(npc, creature, fromPosition, toPosition) -end - -npcType.onSay = function(npc, creature, type, message) - npcHandler:onSay(npc, creature, type, message) -end - -npcType.onCloseChannel = function(npc, creature) - npcHandler:onCloseChannel(npc, creature) -end - -npcConfig.shop = { - { itemName = "acorn", clientId = 10296, sell = 4000000000 }, - { itemName = "blank rune", clientId = 3147, buy = 4000000000 }, -} --- On buy npc shop message -npcType.onBuyItem = function(npc, player, itemId, subType, amount, ignore, inBackpacks, totalCost) - npc:sellItem(player, itemId, amount, subType, 0, ignore, inBackpacks) -end --- On sell npc shop message -npcType.onSellItem = function(npc, player, itemId, subtype, amount, ignore, name, totalCost) - player:sendTextMessage(MESSAGE_TRADE, string.format("Sold %ix %s for %i gold.", amount, name, totalCost)) -end --- On check npc shop message (look item) -npcType.onCheckItem = function(npc, player, clientId, subType) end - -local function creatureSayCallback(npc, creature, type, message) - local player = Player(creature) - local playerId = player:getId() - - if not npcHandler:checkInteraction(npc, creature) then - return false - end - - if MsgContains(message, "name") then - return npcHandler:say("Me Yasir.", npc, creature) - elseif MsgContains(message, "job") then - return npcHandler:say("Tje hari ku ne finjala. {Ariki}?", npc, creature) - elseif MsgContains(message, "passage") then - return npcHandler:say("Soso yana. ", npc, creature) - elseif MsgContains(message, "ariki") then - npc:openShopWindow(creature) - creature:addAchievement("Si, Ariki!") - end - return true -end - -local function onTradeRequest(npc, creature, message) - creature:addAchievement("Si, Ariki!") - return true -end - -npcHandler:setMessage(MESSAGE_FAREWELL, "Si, jema ze harun. ") -npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback) -npcHandler:setCallback(CALLBACK_ON_TRADE_REQUEST, onTradeRequest) -npcHandler:addModule(FocusModule:new(), npcConfig.name, true, true, true) - -npcType:register(npcConfig) diff --git a/data-otservbr-global/npc/the_draccoon.lua b/data-otservbr-global/npc/the_draccoon.lua index be5d5806d02..c9cf3d38f39 100644 --- a/data-otservbr-global/npc/the_draccoon.lua +++ b/data-otservbr-global/npc/the_draccoon.lua @@ -112,7 +112,11 @@ local function creatureSayCallback(npc, creature, type, message) npcHandler:say("Just pay him a visit and tell him, his good old pal, the Draccoon is back!", npc, creature, 2000) npcHandler:setTopic(playerId, 0) player:setStorageValue(Storage.Quest.U13_30.TwentyYearsACook.QuestLine, 2) - elseif mission == 2 then + player:setStorageValue(Storage.Quest.U13_30.TwentyYearsACook.TheRestOfRathaDoor, 1) + elseif mission == 3 then + npcHandler:say(" Ratha's demise is most unfortunate, indeed! ...", npc, creature) + npcHandler:say("But well, as he is still around... to some capacity at least, I am sure we are able to communicate with him. Just travel to his apartment again, I'll send one of my buddies to your assistance. ...", npc, creature, 2000) + player:setStorageValue(Storage.Quest.U13_30.TwentyYearsACook.QuestLine, 4) end end return true diff --git a/data-otservbr-global/scripts/quests/20_years_a_cook_quest/ghost_duster_creaturescripts.lua b/data-otservbr-global/scripts/quests/20_years_a_cook_quest/ghost_duster_creaturescripts.lua new file mode 100644 index 00000000000..ef41fcde9e5 --- /dev/null +++ b/data-otservbr-global/scripts/quests/20_years_a_cook_quest/ghost_duster_creaturescripts.lua @@ -0,0 +1,60 @@ +local ghostDusterAttack = CreatureEvent("GhostDusterAttack") + +local combat = Combat() +combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_BLUE_ENERGY_SPARK) +combat:setArea(createCombatArea( + { + { 0, 0, 2, 0, 0 }, + { 0, 0, 1, 0, 0 }, + { 0, 0, 1, 0, 0 }, + { 0, 0, 1, 0, 0 }, + { 0, 0, 1, 0, 0 }, + { 0, 0, 1, 0, 0 }, + { 0, 0, 1, 0, 0 }, + { 0, 0, 1, 0, 0 }, + } +)) + +local condition = Condition(CONDITION_PARALYZE) +condition:setParameter(CONDITION_PARAM_TICKS, 8000) +condition:setFormula(-0.70, 0, -0.85, 0) + +function onTargetTile(cid, pos) + local tile = Tile(pos) + if tile then + local target = tile:getTopCreature() + if target and target ~= cid then + if target:getName():lower() == "the rest of ratha" then + target:addHealth(-100, COMBAT_AGONYDAMAGE) + local appliedCondition = target:getCondition(CONDITION_PARALYZE) + if not appliedCondition then + target:addCondition(condition) + end + end + end + end + return true +end + +combat:setCallback(CALLBACK_PARAM_TARGETTILE, "onTargetTile") + +local accumulatedDamage = 0 + +function ghostDusterAttack.onHealthChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin) + if creature and creature:isMonster() then + if primaryType == COMBAT_HEALING then + return primaryDamage, primaryType, secondaryDamage, secondaryType + end + + if accumulatedDamage >= 5 then + accumulatedDamage = 0 + local var = { type = 1, number = creature:getId() } + combat:execute(creature, var) + else + accumulatedDamage = accumulatedDamage + math.abs(primaryDamage + secondaryDamage) + end + end + return primaryDamage, primaryType, secondaryDamage, secondaryType +end + +ghostDusterAttack:register() diff --git a/data-otservbr-global/scripts/quests/20_years_a_cook_quest/harp_action.lua b/data-otservbr-global/scripts/quests/20_years_a_cook_quest/harp_action.lua new file mode 100644 index 00000000000..ef7b745580d --- /dev/null +++ b/data-otservbr-global/scripts/quests/20_years_a_cook_quest/harp_action.lua @@ -0,0 +1,34 @@ +local harp = Action() + +function harp.onUse(player, item, fromPosition, target, toPosition, isHotkey) + local icon = player:getIcon("the-rest-of-ratha") + if icon.count <= 0 then + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You are out of inspiration to play.") + return true + end + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You used your musical inspiration to play a luring tunel!") + item:transform(TwentyYearsACookQuest.TheRestOfRatha.Items.HarpCooldown) + fromPosition:sendMagicEffect(CONST_ME_SOUND_GREEN) + player:setIcon("the-rest-of-ratha", CreatureIconCategory_Quests, CreatureIconQuests_Dove, icon.count - 1) + addEvent(function(position) + local tile = Tile(position) + local harpCooldown = tile and tile:getItemById(TwentyYearsACookQuest.TheRestOfRatha.Items.HarpCooldown) or nil + if harpCooldown then + harpCooldown:transform(TwentyYearsACookQuest.TheRestOfRatha.Items.Harp) + end + end, 15 * 1000, fromPosition) + return true +end + +harp:id(TwentyYearsACookQuest.TheRestOfRatha.Items.Harp) +harp:register() + +local harpCooldown = Action() + +function harpCooldown.onUse(player, item, fromPosition, target, toPosition, isHotkey) + fromPosition:sendMagicEffect(CONST_ME_SOUND_RED) + return true +end + +harpCooldown:id(TwentyYearsACookQuest.TheRestOfRatha.Items.HarpCooldown) +harpCooldown:register() \ No newline at end of file diff --git a/data-otservbr-global/scripts/quests/20_years_a_cook_quest/omnious_trash_moveevents.lua b/data-otservbr-global/scripts/quests/20_years_a_cook_quest/omnious_trash_moveevents.lua new file mode 100644 index 00000000000..c4db2ce84f3 --- /dev/null +++ b/data-otservbr-global/scripts/quests/20_years_a_cook_quest/omnious_trash_moveevents.lua @@ -0,0 +1,53 @@ +local positions = { + [Position(32591, 31936, 5)] = { + toPosition = Position(32587, 31937, 5), + storageValue = 4 + }, + [Position(32591, 31936, 5)] = { + toPosition = Position(33319, 31443, 15), + storageValue = 2 + }, + [Position(32974, 32110, 7)] = { + toPosition = Position(32973, 32087, 8), + storageValue = 1 + }, + [Position(32973, 32089, 8)] = { + toPosition = Position(32975, 32112, 7), + storageValue = 1 + }, +} + +local omniousTrashCan = MoveEvent() + +function omniousTrashCan.onStepIn(creature, item, position, fromPosition) + local player = creature:getPlayer() + if not player then + return + end + + playerStorage = player:getStorageValue(Storage.Quest.U13_30.TwentyYearsACook.QuestLine) or -1 + + for position, data in pairs(positions) do + if position == player:getPosition() and playerStorage >= data.storageValue and player:getLevel() >= 250 then + fromPosition:sendMagicEffect(CONST_ME_POFF) + player:teleportTo(data.toPosition) + player:getPosition():sendMagicEffect(CONST_ME_POFF) + return + end + end + + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You are not ready for this yet") + player:teleportTo(fromPosition, true) +end + +local addedPositions = {} + +for key, _ in pairs(positions) do + if not table.contains(addedPositions, key) then + omniousTrashCan:position(key) + end + table.insert(addedPositions, key) +end + +omniousTrashCan:type("stepin") +omniousTrashCan:register() \ No newline at end of file diff --git a/data-otservbr-global/scripts/quests/20_years_a_cook_quest/spirit_flask_action.lua b/data-otservbr-global/scripts/quests/20_years_a_cook_quest/spirit_flask_action.lua new file mode 100644 index 00000000000..a8d3935fe71 --- /dev/null +++ b/data-otservbr-global/scripts/quests/20_years_a_cook_quest/spirit_flask_action.lua @@ -0,0 +1,58 @@ +local flaskBox = Action() + +function flaskBox.onUse(player, item, fromPosition, target, toPosition, isHotkey) + if player:getStorageValue(Storage.Quest.U13_30.FlaskBox) < 1 then + player:setStorageValue(Storage.Quest.U13_30.FlaskBox, 1) + player:addItem(TwentyYearsACookQuest.TheRestOfRatha.Items.EmptySpiritFlask, 1) + end +end + +flaskBox:uid(TwentyYearsACookQuest.TheRestOfRatha.FlaskBoxUID) +flaskBox:register() + +local emptySpiritFlask = Action() + +function emptySpiritFlask.onUse(player, item, fromPosition, target, toPosition, isHotkey) + if not target and not target:isItem() then + return true + end + + if target:getId() == TwentyYearsACookQuest.TheRestOfRatha.Items.GhostItem then + target:getPosition():sendMagicEffect(CONST_ME_PIXIE_EXPLOSION) + target:remove() + item:transform(TwentyYearsACookQuest.TheRestOfRatha.Items.FullSpiritFlask) + end +end + +emptySpiritFlask:id(TwentyYearsACookQuest.TheRestOfRatha.Items.EmptySpiritFlask) +emptySpiritFlask:register() + +local fullSpiritFlask = Action() + +function fullSpiritFlask.onUse(player, item, fromPosition, target, toPosition, isHotkey) + if target and not target:isMonster() then + return true + end + + local monster = target:getMonster() + + if not monster then + return true + end + + if monster:getName():lower() == "spirit container" then + local icon = monster:getIcon("spirit-container") + monster:setIcon("spirit-container", CreatureIconCategory_Quests, CreatureIconQuests_WhiteCross, icon and icon.count + 1 or 1) + monster:getPosition():sendMagicEffect(CONST_ME_PIXIE_EXPLOSION) + item:transform(TwentyYearsACookQuest.TheRestOfRatha.Items.EmptySpiritFlask) + if TwentyYearsACookQuest.TheRestOfRatha.SpiritContainerPoints > 50 then + local players = TwentyYearsACookQuest.TheRestOfRatha.BossZone:getPlayers() + for i, player in ipairs(players) do + player:setStorageValue(Storage.Quest.U13_30.TwentyYearsACook.QuestLine, 5) + end + end + end +end + +fullSpiritFlask:id(TwentyYearsACookQuest.TheRestOfRatha.Items.FullSpiritFlask) +fullSpiritFlask:register() \ No newline at end of file diff --git a/data-otservbr-global/scripts/quests/20_years_a_cook_quest/the_rest_of_ratha_fight.lua b/data-otservbr-global/scripts/quests/20_years_a_cook_quest/the_rest_of_ratha_fight.lua new file mode 100644 index 00000000000..3d52fb09795 --- /dev/null +++ b/data-otservbr-global/scripts/quests/20_years_a_cook_quest/the_rest_of_ratha_fight.lua @@ -0,0 +1,26 @@ +local theRestOfRathaZoneEvent = ZoneEvent(TwentyYearsACookQuest.TheRestOfRatha.BossZone) +function theRestOfRathaZoneEvent.afterEnter(_zone, creature) + local player = creature:getPlayer() + if not player then + return false + end + + player:setIcon("the-rest-of-ratha", CreatureIconCategory_Quests, CreatureIconQuests_Dove, 3) + return true +end + +function theRestOfRathaZoneEvent.afterLeave(zone, creature) + local player = creature:getPlayer() + if not player then + return false + end + + if not zone:getPlayers() then + TwentyYearsACookQuest.TheRestOfRatha.SpiritContainerPoints = 0 + end + + player:removeIcon("the-rest-of-ratha") + return true +end + +theRestOfRathaZoneEvent:register() \ No newline at end of file diff --git a/data-otservbr-global/scripts/quests/20_years_a_cook_quest/the_rest_of_ratha_lever.lua b/data-otservbr-global/scripts/quests/20_years_a_cook_quest/the_rest_of_ratha_lever.lua new file mode 100644 index 00000000000..45fe563f39d --- /dev/null +++ b/data-otservbr-global/scripts/quests/20_years_a_cook_quest/the_rest_of_ratha_lever.lua @@ -0,0 +1,27 @@ +local config = { + boss = { + name = "The Rest of Ratha", + position = Position(33309, 31391, 15), + }, + requiredLevel = 250, + playerPositions = { + { pos = Position(32585, 31939, 5), teleport = Position(33319, 31406, 15), effect = CONST_ME_TELEPORT }, + { pos = Position(32586, 31939, 5), teleport = Position(33319, 31406, 15), effect = CONST_ME_TELEPORT }, + { pos = Position(32587, 31939, 5), teleport = Position(33319, 31406, 15), effect = CONST_ME_TELEPORT }, + { pos = Position(32588, 31939, 5), teleport = Position(33319, 31406, 15), effect = CONST_ME_TELEPORT }, + { pos = Position(32584, 31939, 5), teleport = Position(33319, 31406, 15), effect = CONST_ME_TELEPORT }, + }, + specPos = { + from = Position(33303, 31388, 15), + to = Position(33327, 31408, 15), + }, + monsters = { + { name = "Spirit Container", pos = Position(33325, 31407, 15) }, + { name = "Ghost Duster", pos = Position(33323, 31407, 15) }, + }, + exit = Position(32586, 31937, 5), +} + +local lever = BossLever(config) +lever:uid(62133) +lever:register() diff --git a/data-otservbr-global/startup/tables/door_quest.lua b/data-otservbr-global/startup/tables/door_quest.lua index 366a6d052bb..23dbbd0840f 100644 --- a/data-otservbr-global/startup/tables/door_quest.lua +++ b/data-otservbr-global/startup/tables/door_quest.lua @@ -519,6 +519,7 @@ QuestDoorAction = { { x = 33271, y = 31657, z = 8 }, { x = 33284, y = 31791, z = 13 }, { x = 33307, y = 32291, z = 7 }, + { x = 32964, y = 32084, z = 8}, }, }, -- The thieves guild door @@ -914,6 +915,10 @@ QuestDoorAction = { { x = 33782, y = 32576, z = 12 }, }, }, + [Storage.Quest.U13_30.TwentyYearsACook.TheRestOfRathaDoor] = { + itemId = false, + itemPos = { { x = 32595, y = 31938, z = 5 } }, + }, } QuestDoorUnique = { diff --git a/data/scripts/lib/register_monster_type.lua b/data/scripts/lib/register_monster_type.lua index fcd9f550ed9..c0101203c51 100644 --- a/data/scripts/lib/register_monster_type.lua +++ b/data/scripts/lib/register_monster_type.lua @@ -168,6 +168,9 @@ registerMonsterType.flags = function(mtype, mask) if mask.flags.canTarget ~= nil then mtype:canTarget(mask.flags.canTarget) end + if mask.flags.canWalk ~= nil then + mtype:canWalk(mask.flags.canWalk) + end if mask.flags.convinceable ~= nil then mtype:isConvinceable(mask.flags.convinceable) end diff --git a/src/creatures/monsters/monster.cpp b/src/creatures/monsters/monster.cpp index d05b3060609..25855d379ca 100644 --- a/src/creatures/monsters/monster.cpp +++ b/src/creatures/monsters/monster.cpp @@ -1174,7 +1174,7 @@ void Monster::pushCreatures(std::shared_ptr tile) { } bool Monster::getNextStep(Direction &nextDirection, uint32_t &flags) { - if (isIdle || getHealth() <= 0) { + if (isIdle || getHealth() <= 0 || !canWalk()) { // we dont have anyone watching might aswell stop walking eventWalk = 0; return false; diff --git a/src/creatures/monsters/monster.hpp b/src/creatures/monsters/monster.hpp index 87f01a0c88a..f0a4d9e03ab 100644 --- a/src/creatures/monsters/monster.hpp +++ b/src/creatures/monsters/monster.hpp @@ -102,6 +102,9 @@ class Monster final : public Creature { bool isAttackable() const override { return mType->info.isAttackable; } + bool canWalk() const { + return mType->info.canWalk; + } bool canTarget() const { return mType->info.canTarget; } diff --git a/src/creatures/monsters/monsters.hpp b/src/creatures/monsters/monsters.hpp index ae48ceba6a5..171e30c4f1b 100644 --- a/src/creatures/monsters/monsters.hpp +++ b/src/creatures/monsters/monsters.hpp @@ -139,6 +139,7 @@ class MonsterType { Faction_t faction = FACTION_DEFAULT; stdext::vector_set enemyFactions; + bool canWalk = true; bool canTarget = true; bool canPushItems = false; bool canPushCreatures = false; diff --git a/src/lua/functions/creatures/monster/monster_type_functions.cpp b/src/lua/functions/creatures/monster/monster_type_functions.cpp index 96e4f469746..595f01fd235 100644 --- a/src/lua/functions/creatures/monster/monster_type_functions.cpp +++ b/src/lua/functions/creatures/monster/monster_type_functions.cpp @@ -249,6 +249,22 @@ int MonsterTypeFunctions::luaMonsterTypeCanSpawn(lua_State* L) { return 1; } +int MonsterTypeFunctions::luaMonsterTypeCanWalk(lua_State* L) { + // get: monsterType:canWalk() set: monsterType:canWalk(bool) + const auto monsterType = getUserdataShared(L, 1); + if (monsterType) { + if (lua_gettop(L) == 1) { + pushBoolean(L, monsterType->info.canWalk); + } else { + monsterType->info.canWalk = getBoolean(L, 2); + pushBoolean(L, true); + } + } else { + lua_pushnil(L); + } + return 1; +} + int MonsterTypeFunctions::luaMonsterTypeCanTarget(lua_State* L) { // get: monsterType:canTarget() set: monsterType:canTarget(bool) const auto monsterType = getUserdataShared(L, 1); diff --git a/src/lua/functions/creatures/monster/monster_type_functions.hpp b/src/lua/functions/creatures/monster/monster_type_functions.hpp index 3d1e0f82f09..cda0c8cc0fc 100644 --- a/src/lua/functions/creatures/monster/monster_type_functions.hpp +++ b/src/lua/functions/creatures/monster/monster_type_functions.hpp @@ -32,6 +32,7 @@ class MonsterTypeFunctions final : LuaScriptInterface { registerMethod(L, "MonsterType", "canSpawn", MonsterTypeFunctions::luaMonsterTypeCanSpawn); + registerMethod(L, "MonsterType", "canWalk", MonsterTypeFunctions::luaMonsterTypeCanWalk); registerMethod(L, "MonsterType", "canTarget", MonsterTypeFunctions::luaMonsterTypeCanTarget); registerMethod(L, "MonsterType", "canPushItems", MonsterTypeFunctions::luaMonsterTypeCanPushItems); registerMethod(L, "MonsterType", "canPushCreatures", MonsterTypeFunctions::luaMonsterTypeCanPushCreatures); @@ -164,6 +165,7 @@ class MonsterTypeFunctions final : LuaScriptInterface { static int luaMonsterTypeRespawnType(lua_State* L); static int luaMonsterTypeCanSpawn(lua_State* L); + static int luaMonsterTypeCanWalk(lua_State* L); static int luaMonsterTypeCanTarget(lua_State* L); static int luaMonsterTypeCanPushItems(lua_State* L); static int luaMonsterTypeCanPushCreatures(lua_State* L); From c708ddcf010ece5201688641c98b21d1bf769588 Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Thu, 30 May 2024 02:11:41 +0000 Subject: [PATCH 04/20] Lua code format - (Stylua) --- data-otservbr-global/lib/core/quests.lua | 2 +- .../lib/quests/20_years_a_cook_quest.lua | 26 +++---- .../20_years_a_cook_quest/ghost_duster.lua | 2 +- .../ghost_duster_creaturescripts.lua | 52 +++++++------- .../20_years_a_cook_quest/harp_action.lua | 40 +++++------ .../omnious_trash_moveevents.lua | 32 ++++----- .../spirit_flask_action.lua | 72 +++++++++---------- .../the_rest_of_ratha_fight.lua | 2 +- .../startup/tables/door_quest.lua | 2 +- 9 files changed, 114 insertions(+), 116 deletions(-) diff --git a/data-otservbr-global/lib/core/quests.lua b/data-otservbr-global/lib/core/quests.lua index aa5b4b52f3d..0033e79f5c5 100644 --- a/data-otservbr-global/lib/core/quests.lua +++ b/data-otservbr-global/lib/core/quests.lua @@ -6554,7 +6554,7 @@ if not Quests then startValue = 5, endValue = 6, description = "Travel to the Draccoon's lair to learn how to proceed.", - } + }, }, }, } diff --git a/data-otservbr-global/lib/quests/20_years_a_cook_quest.lua b/data-otservbr-global/lib/quests/20_years_a_cook_quest.lua index 6386125f1ba..f2d67a86d2a 100644 --- a/data-otservbr-global/lib/quests/20_years_a_cook_quest.lua +++ b/data-otservbr-global/lib/quests/20_years_a_cook_quest.lua @@ -1,17 +1,17 @@ TwentyYearsACookQuest = { - TheRestOfRatha = { - MissionZone = Zone("mission.the-rest-of-ratha"), - BossZone = Zone("boss.the-rest-of-ratha"), - Items = { - GhostItem = 44598, - EmptySpiritFlask = 44527, - FullSpiritFlask = 44528, - Harp = 44599, - HarpCooldown = 44600, - }, - FlaskBoxUID = 62134, - SpiritContainerPoints = 0, - }, + TheRestOfRatha = { + MissionZone = Zone("mission.the-rest-of-ratha"), + BossZone = Zone("boss.the-rest-of-ratha"), + Items = { + GhostItem = 44598, + EmptySpiritFlask = 44527, + FullSpiritFlask = 44528, + Harp = 44599, + HarpCooldown = 44600, + }, + FlaskBoxUID = 62134, + SpiritContainerPoints = 0, + }, } -- Initializing zones diff --git a/data-otservbr-global/monster/quests/20_years_a_cook_quest/ghost_duster.lua b/data-otservbr-global/monster/quests/20_years_a_cook_quest/ghost_duster.lua index 048854106df..fbab50636b9 100644 --- a/data-otservbr-global/monster/quests/20_years_a_cook_quest/ghost_duster.lua +++ b/data-otservbr-global/monster/quests/20_years_a_cook_quest/ghost_duster.lua @@ -9,7 +9,7 @@ monster.outfit = { } monster.events = { - "GhostDusterAttack" + "GhostDusterAttack", } monster.health = 100000000 diff --git a/data-otservbr-global/scripts/quests/20_years_a_cook_quest/ghost_duster_creaturescripts.lua b/data-otservbr-global/scripts/quests/20_years_a_cook_quest/ghost_duster_creaturescripts.lua index ef41fcde9e5..0aa738ea1c0 100644 --- a/data-otservbr-global/scripts/quests/20_years_a_cook_quest/ghost_duster_creaturescripts.lua +++ b/data-otservbr-global/scripts/quests/20_years_a_cook_quest/ghost_duster_creaturescripts.lua @@ -2,18 +2,16 @@ local ghostDusterAttack = CreatureEvent("GhostDusterAttack") local combat = Combat() combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_BLUE_ENERGY_SPARK) -combat:setArea(createCombatArea( - { - { 0, 0, 2, 0, 0 }, - { 0, 0, 1, 0, 0 }, - { 0, 0, 1, 0, 0 }, - { 0, 0, 1, 0, 0 }, - { 0, 0, 1, 0, 0 }, - { 0, 0, 1, 0, 0 }, - { 0, 0, 1, 0, 0 }, - { 0, 0, 1, 0, 0 }, - } -)) +combat:setArea(createCombatArea({ + { 0, 0, 2, 0, 0 }, + { 0, 0, 1, 0, 0 }, + { 0, 0, 1, 0, 0 }, + { 0, 0, 1, 0, 0 }, + { 0, 0, 1, 0, 0 }, + { 0, 0, 1, 0, 0 }, + { 0, 0, 1, 0, 0 }, + { 0, 0, 1, 0, 0 }, +})) local condition = Condition(CONDITION_PARALYZE) condition:setParameter(CONDITION_PARAM_TICKS, 8000) @@ -26,10 +24,10 @@ function onTargetTile(cid, pos) if target and target ~= cid then if target:getName():lower() == "the rest of ratha" then target:addHealth(-100, COMBAT_AGONYDAMAGE) - local appliedCondition = target:getCondition(CONDITION_PARALYZE) - if not appliedCondition then - target:addCondition(condition) - end + local appliedCondition = target:getCondition(CONDITION_PARALYZE) + if not appliedCondition then + target:addCondition(condition) + end end end end @@ -42,17 +40,17 @@ local accumulatedDamage = 0 function ghostDusterAttack.onHealthChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin) if creature and creature:isMonster() then - if primaryType == COMBAT_HEALING then - return primaryDamage, primaryType, secondaryDamage, secondaryType - end - - if accumulatedDamage >= 5 then - accumulatedDamage = 0 - local var = { type = 1, number = creature:getId() } - combat:execute(creature, var) - else - accumulatedDamage = accumulatedDamage + math.abs(primaryDamage + secondaryDamage) - end + if primaryType == COMBAT_HEALING then + return primaryDamage, primaryType, secondaryDamage, secondaryType + end + + if accumulatedDamage >= 5 then + accumulatedDamage = 0 + local var = { type = 1, number = creature:getId() } + combat:execute(creature, var) + else + accumulatedDamage = accumulatedDamage + math.abs(primaryDamage + secondaryDamage) + end end return primaryDamage, primaryType, secondaryDamage, secondaryType end diff --git a/data-otservbr-global/scripts/quests/20_years_a_cook_quest/harp_action.lua b/data-otservbr-global/scripts/quests/20_years_a_cook_quest/harp_action.lua index ef7b745580d..251734aff38 100644 --- a/data-otservbr-global/scripts/quests/20_years_a_cook_quest/harp_action.lua +++ b/data-otservbr-global/scripts/quests/20_years_a_cook_quest/harp_action.lua @@ -1,23 +1,23 @@ local harp = Action() function harp.onUse(player, item, fromPosition, target, toPosition, isHotkey) - local icon = player:getIcon("the-rest-of-ratha") - if icon.count <= 0 then - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You are out of inspiration to play.") - return true - end - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You used your musical inspiration to play a luring tunel!") - item:transform(TwentyYearsACookQuest.TheRestOfRatha.Items.HarpCooldown) - fromPosition:sendMagicEffect(CONST_ME_SOUND_GREEN) - player:setIcon("the-rest-of-ratha", CreatureIconCategory_Quests, CreatureIconQuests_Dove, icon.count - 1) - addEvent(function(position) - local tile = Tile(position) - local harpCooldown = tile and tile:getItemById(TwentyYearsACookQuest.TheRestOfRatha.Items.HarpCooldown) or nil - if harpCooldown then - harpCooldown:transform(TwentyYearsACookQuest.TheRestOfRatha.Items.Harp) - end - end, 15 * 1000, fromPosition) - return true + local icon = player:getIcon("the-rest-of-ratha") + if icon.count <= 0 then + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You are out of inspiration to play.") + return true + end + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You used your musical inspiration to play a luring tunel!") + item:transform(TwentyYearsACookQuest.TheRestOfRatha.Items.HarpCooldown) + fromPosition:sendMagicEffect(CONST_ME_SOUND_GREEN) + player:setIcon("the-rest-of-ratha", CreatureIconCategory_Quests, CreatureIconQuests_Dove, icon.count - 1) + addEvent(function(position) + local tile = Tile(position) + local harpCooldown = tile and tile:getItemById(TwentyYearsACookQuest.TheRestOfRatha.Items.HarpCooldown) or nil + if harpCooldown then + harpCooldown:transform(TwentyYearsACookQuest.TheRestOfRatha.Items.Harp) + end + end, 15 * 1000, fromPosition) + return true end harp:id(TwentyYearsACookQuest.TheRestOfRatha.Items.Harp) @@ -26,9 +26,9 @@ harp:register() local harpCooldown = Action() function harpCooldown.onUse(player, item, fromPosition, target, toPosition, isHotkey) - fromPosition:sendMagicEffect(CONST_ME_SOUND_RED) - return true + fromPosition:sendMagicEffect(CONST_ME_SOUND_RED) + return true end harpCooldown:id(TwentyYearsACookQuest.TheRestOfRatha.Items.HarpCooldown) -harpCooldown:register() \ No newline at end of file +harpCooldown:register() diff --git a/data-otservbr-global/scripts/quests/20_years_a_cook_quest/omnious_trash_moveevents.lua b/data-otservbr-global/scripts/quests/20_years_a_cook_quest/omnious_trash_moveevents.lua index c4db2ce84f3..ea765a04851 100644 --- a/data-otservbr-global/scripts/quests/20_years_a_cook_quest/omnious_trash_moveevents.lua +++ b/data-otservbr-global/scripts/quests/20_years_a_cook_quest/omnious_trash_moveevents.lua @@ -1,20 +1,20 @@ local positions = { [Position(32591, 31936, 5)] = { - toPosition = Position(32587, 31937, 5), - storageValue = 4 - }, + toPosition = Position(32587, 31937, 5), + storageValue = 4, + }, [Position(32591, 31936, 5)] = { - toPosition = Position(33319, 31443, 15), - storageValue = 2 - }, + toPosition = Position(33319, 31443, 15), + storageValue = 2, + }, [Position(32974, 32110, 7)] = { - toPosition = Position(32973, 32087, 8), - storageValue = 1 - }, - [Position(32973, 32089, 8)] = { - toPosition = Position(32975, 32112, 7), - storageValue = 1 - }, + toPosition = Position(32973, 32087, 8), + storageValue = 1, + }, + [Position(32973, 32089, 8)] = { + toPosition = Position(32975, 32112, 7), + storageValue = 1, + }, } local omniousTrashCan = MoveEvent() @@ -25,9 +25,9 @@ function omniousTrashCan.onStepIn(creature, item, position, fromPosition) return end - playerStorage = player:getStorageValue(Storage.Quest.U13_30.TwentyYearsACook.QuestLine) or -1 + playerStorage = player:getStorageValue(Storage.Quest.U13_30.TwentyYearsACook.QuestLine) or -1 - for position, data in pairs(positions) do + for position, data in pairs(positions) do if position == player:getPosition() and playerStorage >= data.storageValue and player:getLevel() >= 250 then fromPosition:sendMagicEffect(CONST_ME_POFF) player:teleportTo(data.toPosition) @@ -50,4 +50,4 @@ for key, _ in pairs(positions) do end omniousTrashCan:type("stepin") -omniousTrashCan:register() \ No newline at end of file +omniousTrashCan:register() diff --git a/data-otservbr-global/scripts/quests/20_years_a_cook_quest/spirit_flask_action.lua b/data-otservbr-global/scripts/quests/20_years_a_cook_quest/spirit_flask_action.lua index a8d3935fe71..2a8738f6ee7 100644 --- a/data-otservbr-global/scripts/quests/20_years_a_cook_quest/spirit_flask_action.lua +++ b/data-otservbr-global/scripts/quests/20_years_a_cook_quest/spirit_flask_action.lua @@ -1,10 +1,10 @@ local flaskBox = Action() function flaskBox.onUse(player, item, fromPosition, target, toPosition, isHotkey) - if player:getStorageValue(Storage.Quest.U13_30.FlaskBox) < 1 then - player:setStorageValue(Storage.Quest.U13_30.FlaskBox, 1) - player:addItem(TwentyYearsACookQuest.TheRestOfRatha.Items.EmptySpiritFlask, 1) - end + if player:getStorageValue(Storage.Quest.U13_30.FlaskBox) < 1 then + player:setStorageValue(Storage.Quest.U13_30.FlaskBox, 1) + player:addItem(TwentyYearsACookQuest.TheRestOfRatha.Items.EmptySpiritFlask, 1) + end end flaskBox:uid(TwentyYearsACookQuest.TheRestOfRatha.FlaskBoxUID) @@ -13,15 +13,15 @@ flaskBox:register() local emptySpiritFlask = Action() function emptySpiritFlask.onUse(player, item, fromPosition, target, toPosition, isHotkey) - if not target and not target:isItem() then - return true - end - - if target:getId() == TwentyYearsACookQuest.TheRestOfRatha.Items.GhostItem then - target:getPosition():sendMagicEffect(CONST_ME_PIXIE_EXPLOSION) - target:remove() - item:transform(TwentyYearsACookQuest.TheRestOfRatha.Items.FullSpiritFlask) - end + if not target and not target:isItem() then + return true + end + + if target:getId() == TwentyYearsACookQuest.TheRestOfRatha.Items.GhostItem then + target:getPosition():sendMagicEffect(CONST_ME_PIXIE_EXPLOSION) + target:remove() + item:transform(TwentyYearsACookQuest.TheRestOfRatha.Items.FullSpiritFlask) + end end emptySpiritFlask:id(TwentyYearsACookQuest.TheRestOfRatha.Items.EmptySpiritFlask) @@ -30,29 +30,29 @@ emptySpiritFlask:register() local fullSpiritFlask = Action() function fullSpiritFlask.onUse(player, item, fromPosition, target, toPosition, isHotkey) - if target and not target:isMonster() then - return true - end - - local monster = target:getMonster() - - if not monster then - return true - end - - if monster:getName():lower() == "spirit container" then - local icon = monster:getIcon("spirit-container") - monster:setIcon("spirit-container", CreatureIconCategory_Quests, CreatureIconQuests_WhiteCross, icon and icon.count + 1 or 1) - monster:getPosition():sendMagicEffect(CONST_ME_PIXIE_EXPLOSION) - item:transform(TwentyYearsACookQuest.TheRestOfRatha.Items.EmptySpiritFlask) - if TwentyYearsACookQuest.TheRestOfRatha.SpiritContainerPoints > 50 then - local players = TwentyYearsACookQuest.TheRestOfRatha.BossZone:getPlayers() - for i, player in ipairs(players) do - player:setStorageValue(Storage.Quest.U13_30.TwentyYearsACook.QuestLine, 5) - end - end - end + if target and not target:isMonster() then + return true + end + + local monster = target:getMonster() + + if not monster then + return true + end + + if monster:getName():lower() == "spirit container" then + local icon = monster:getIcon("spirit-container") + monster:setIcon("spirit-container", CreatureIconCategory_Quests, CreatureIconQuests_WhiteCross, icon and icon.count + 1 or 1) + monster:getPosition():sendMagicEffect(CONST_ME_PIXIE_EXPLOSION) + item:transform(TwentyYearsACookQuest.TheRestOfRatha.Items.EmptySpiritFlask) + if TwentyYearsACookQuest.TheRestOfRatha.SpiritContainerPoints > 50 then + local players = TwentyYearsACookQuest.TheRestOfRatha.BossZone:getPlayers() + for i, player in ipairs(players) do + player:setStorageValue(Storage.Quest.U13_30.TwentyYearsACook.QuestLine, 5) + end + end + end end fullSpiritFlask:id(TwentyYearsACookQuest.TheRestOfRatha.Items.FullSpiritFlask) -fullSpiritFlask:register() \ No newline at end of file +fullSpiritFlask:register() diff --git a/data-otservbr-global/scripts/quests/20_years_a_cook_quest/the_rest_of_ratha_fight.lua b/data-otservbr-global/scripts/quests/20_years_a_cook_quest/the_rest_of_ratha_fight.lua index 3d52fb09795..31741d309a3 100644 --- a/data-otservbr-global/scripts/quests/20_years_a_cook_quest/the_rest_of_ratha_fight.lua +++ b/data-otservbr-global/scripts/quests/20_years_a_cook_quest/the_rest_of_ratha_fight.lua @@ -23,4 +23,4 @@ function theRestOfRathaZoneEvent.afterLeave(zone, creature) return true end -theRestOfRathaZoneEvent:register() \ No newline at end of file +theRestOfRathaZoneEvent:register() diff --git a/data-otservbr-global/startup/tables/door_quest.lua b/data-otservbr-global/startup/tables/door_quest.lua index 23dbbd0840f..be285e23e07 100644 --- a/data-otservbr-global/startup/tables/door_quest.lua +++ b/data-otservbr-global/startup/tables/door_quest.lua @@ -519,7 +519,7 @@ QuestDoorAction = { { x = 33271, y = 31657, z = 8 }, { x = 33284, y = 31791, z = 13 }, { x = 33307, y = 32291, z = 7 }, - { x = 32964, y = 32084, z = 8}, + { x = 32964, y = 32084, z = 8 }, }, }, -- The thieves guild door From 28485bd91cfc319647ffd21f7cfccc94f8bd4142 Mon Sep 17 00:00:00 2001 From: Pedro Henrique Alves Cruz Date: Thu, 30 May 2024 18:27:51 -0300 Subject: [PATCH 05/20] feat: complete the rest of ratha mechanics --- data-otservbr-global/lib/quests/quest.lua | 2 +- ...uest.lua => twenty_years_a_cook_quest.lua} | 0 .../ghost_duster_creaturescripts.lua | 12 +++++---- .../harp_action.lua | 9 +++++++ .../omnious_trash_moveevents.lua | 0 .../spirit_flask_action.lua | 10 ++++--- .../the_rest_of_ratha_fight.lua | 0 .../the_rest_of_ratha_lever.lua | 0 src/creatures/monsters/monster.cpp | 27 +++++++++++++++++++ src/creatures/monsters/monster.hpp | 3 +++ .../creatures/monster/monster_functions.cpp | 14 ++++++++++ .../creatures/monster/monster_functions.hpp | 4 +++ 12 files changed, 72 insertions(+), 9 deletions(-) rename data-otservbr-global/lib/quests/{20_years_a_cook_quest.lua => twenty_years_a_cook_quest.lua} (100%) rename data-otservbr-global/scripts/quests/{20_years_a_cook_quest => twenty_years_a_cook_quest}/ghost_duster_creaturescripts.lua (87%) rename data-otservbr-global/scripts/quests/{20_years_a_cook_quest => twenty_years_a_cook_quest}/harp_action.lua (80%) rename data-otservbr-global/scripts/quests/{20_years_a_cook_quest => twenty_years_a_cook_quest}/omnious_trash_moveevents.lua (100%) rename data-otservbr-global/scripts/quests/{20_years_a_cook_quest => twenty_years_a_cook_quest}/spirit_flask_action.lua (84%) rename data-otservbr-global/scripts/quests/{20_years_a_cook_quest => twenty_years_a_cook_quest}/the_rest_of_ratha_fight.lua (100%) rename data-otservbr-global/scripts/quests/{20_years_a_cook_quest => twenty_years_a_cook_quest}/the_rest_of_ratha_lever.lua (100%) diff --git a/data-otservbr-global/lib/quests/quest.lua b/data-otservbr-global/lib/quests/quest.lua index 7ba4c8e8796..313096cfb2d 100644 --- a/data-otservbr-global/lib/quests/quest.lua +++ b/data-otservbr-global/lib/quests/quest.lua @@ -1,4 +1,3 @@ -dofile(DATA_DIRECTORY .. "/lib/quests/20_years_a_cook_quest.lua") dofile(DATA_DIRECTORY .. "/lib/quests/bigfoot_burden.lua") dofile(DATA_DIRECTORY .. "/lib/quests/demon_oak.lua") dofile(DATA_DIRECTORY .. "/lib/quests/grimvale.lua") @@ -8,3 +7,4 @@ dofile(DATA_DIRECTORY .. "/lib/quests/the_cursed_crystal.lua") dofile(DATA_DIRECTORY .. "/lib/quests/the_queen_of_the_banshees.lua") dofile(DATA_DIRECTORY .. "/lib/quests/their_masters_voice.lua") dofile(DATA_DIRECTORY .. "/lib/quests/the_primal_ordeal.lua") +dofile(DATA_DIRECTORY .. "/lib/quests/twenty_years_a_cook_quest.lua") diff --git a/data-otservbr-global/lib/quests/20_years_a_cook_quest.lua b/data-otservbr-global/lib/quests/twenty_years_a_cook_quest.lua similarity index 100% rename from data-otservbr-global/lib/quests/20_years_a_cook_quest.lua rename to data-otservbr-global/lib/quests/twenty_years_a_cook_quest.lua diff --git a/data-otservbr-global/scripts/quests/20_years_a_cook_quest/ghost_duster_creaturescripts.lua b/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/ghost_duster_creaturescripts.lua similarity index 87% rename from data-otservbr-global/scripts/quests/20_years_a_cook_quest/ghost_duster_creaturescripts.lua rename to data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/ghost_duster_creaturescripts.lua index ef41fcde9e5..177622a83b2 100644 --- a/data-otservbr-global/scripts/quests/20_years_a_cook_quest/ghost_duster_creaturescripts.lua +++ b/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/ghost_duster_creaturescripts.lua @@ -38,21 +38,23 @@ end combat:setCallback(CALLBACK_PARAM_TARGETTILE, "onTargetTile") -local accumulatedDamage = 0 - function ghostDusterAttack.onHealthChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin) if creature and creature:isMonster() then if primaryType == COMBAT_HEALING then return primaryDamage, primaryType, secondaryDamage, secondaryType end - if accumulatedDamage >= 5 then + local accumulatedDamage = creature:getStorageValue(1) + + accumulatedDamage = accumulatedDamage + math.abs(primaryDamage + secondaryDamage) + + if accumulatedDamage >= 300 then accumulatedDamage = 0 local var = { type = 1, number = creature:getId() } combat:execute(creature, var) - else - accumulatedDamage = accumulatedDamage + math.abs(primaryDamage + secondaryDamage) end + + creature:setStorageValue(1, accumulatedDamage) end return primaryDamage, primaryType, secondaryDamage, secondaryType end diff --git a/data-otservbr-global/scripts/quests/20_years_a_cook_quest/harp_action.lua b/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/harp_action.lua similarity index 80% rename from data-otservbr-global/scripts/quests/20_years_a_cook_quest/harp_action.lua rename to data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/harp_action.lua index ef7b745580d..fe430b197f1 100644 --- a/data-otservbr-global/scripts/quests/20_years_a_cook_quest/harp_action.lua +++ b/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/harp_action.lua @@ -10,6 +10,15 @@ function harp.onUse(player, item, fromPosition, target, toPosition, isHotkey) item:transform(TwentyYearsACookQuest.TheRestOfRatha.Items.HarpCooldown) fromPosition:sendMagicEffect(CONST_ME_SOUND_GREEN) player:setIcon("the-rest-of-ratha", CreatureIconCategory_Quests, CreatureIconQuests_Dove, icon.count - 1) + + local monsters = TwentyYearsACookQuest.TheRestOfRatha.BossZone:getMonsters() + for i, monster in pairs(monsters) do + if monster:getName():lower() == "the rest of ratha" then + -- local position = + monster:walkTo(player:getPosition()) + -- monster:setFollowCreature(player) + end + end addEvent(function(position) local tile = Tile(position) local harpCooldown = tile and tile:getItemById(TwentyYearsACookQuest.TheRestOfRatha.Items.HarpCooldown) or nil diff --git a/data-otservbr-global/scripts/quests/20_years_a_cook_quest/omnious_trash_moveevents.lua b/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/omnious_trash_moveevents.lua similarity index 100% rename from data-otservbr-global/scripts/quests/20_years_a_cook_quest/omnious_trash_moveevents.lua rename to data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/omnious_trash_moveevents.lua diff --git a/data-otservbr-global/scripts/quests/20_years_a_cook_quest/spirit_flask_action.lua b/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/spirit_flask_action.lua similarity index 84% rename from data-otservbr-global/scripts/quests/20_years_a_cook_quest/spirit_flask_action.lua rename to data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/spirit_flask_action.lua index a8d3935fe71..52d4444fb83 100644 --- a/data-otservbr-global/scripts/quests/20_years_a_cook_quest/spirit_flask_action.lua +++ b/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/spirit_flask_action.lua @@ -1,10 +1,14 @@ local flaskBox = Action() function flaskBox.onUse(player, item, fromPosition, target, toPosition, isHotkey) - if player:getStorageValue(Storage.Quest.U13_30.FlaskBox) < 1 then - player:setStorageValue(Storage.Quest.U13_30.FlaskBox, 1) - player:addItem(TwentyYearsACookQuest.TheRestOfRatha.Items.EmptySpiritFlask, 1) + if player:getStorageValue(Storage.Quest.U13_30.TwentyYearsACook.FlaskBox) >= 1 then + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You already got the flask.") + return true end + + player:setStorageValue(Storage.Quest.U13_30.TwentyYearsACook.FlaskBox, 1) + player:addItem(TwentyYearsACookQuest.TheRestOfRatha.Items.EmptySpiritFlask, 1) + return true end flaskBox:uid(TwentyYearsACookQuest.TheRestOfRatha.FlaskBoxUID) diff --git a/data-otservbr-global/scripts/quests/20_years_a_cook_quest/the_rest_of_ratha_fight.lua b/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/the_rest_of_ratha_fight.lua similarity index 100% rename from data-otservbr-global/scripts/quests/20_years_a_cook_quest/the_rest_of_ratha_fight.lua rename to data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/the_rest_of_ratha_fight.lua diff --git a/data-otservbr-global/scripts/quests/20_years_a_cook_quest/the_rest_of_ratha_lever.lua b/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/the_rest_of_ratha_lever.lua similarity index 100% rename from data-otservbr-global/scripts/quests/20_years_a_cook_quest/the_rest_of_ratha_lever.lua rename to data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/the_rest_of_ratha_lever.lua diff --git a/src/creatures/monsters/monster.cpp b/src/creatures/monsters/monster.cpp index 25855d379ca..2940c6705a9 100644 --- a/src/creatures/monsters/monster.cpp +++ b/src/creatures/monsters/monster.cpp @@ -1186,6 +1186,8 @@ bool Monster::getNextStep(Direction &nextDirection, uint32_t &flags) { doFollowCreature(flags, nextDirection, result); } else if (isWalkingBack) { doWalkBack(flags, nextDirection, result); + } else if (isWalkingTo && !randomStepping) { + doWalkTo(flags, nextDirection, result); } else { doRandomStep(nextDirection, result); } @@ -1214,6 +1216,16 @@ void Monster::doRandomStep(Direction &nextDirection, bool &result) { } } +void Monster::walkTo(const Position& walkToPosition) { + randomStepping = false; + isWalkingTo = true; + stdext::arraylist listDir(128); + if (!getPathTo(walkToPosition, listDir, 1, 1, true, true, 25)) { + return; + } + startAutoWalk(listDir.data(), true); +} + void Monster::doWalkBack(uint32_t &flags, Direction &nextDirection, bool &result) { result = Creature::getNextStep(nextDirection, flags); if (result) { @@ -1239,6 +1251,21 @@ void Monster::doWalkBack(uint32_t &flags, Direction &nextDirection, bool &result } } +void Monster::doWalkTo(uint32_t &flags, Direction &nextDirection, bool &result) { + result = Creature::getNextStep(nextDirection, flags); + if (result) { + flags |= FLAG_PATHFINDING; + } else { + if (ignoreFieldDamage) { + ignoreFieldDamage = false; + updateMapCache(); + } + + randomStepping = true; + isWalkingTo = false; + } +} + void Monster::doFollowCreature(uint32_t &flags, Direction &nextDirection, bool &result) { randomStepping = false; result = Creature::getNextStep(nextDirection, flags); diff --git a/src/creatures/monsters/monster.hpp b/src/creatures/monsters/monster.hpp index f0a4d9e03ab..82b7ad91cf6 100644 --- a/src/creatures/monsters/monster.hpp +++ b/src/creatures/monsters/monster.hpp @@ -395,6 +395,7 @@ class Monster final : public Creature { Position masterPos; bool isWalkingBack = false; + bool isWalkingTo = false; bool isIdle = true; bool extraMeleeAttack = false; bool randomStepping = false; @@ -467,7 +468,9 @@ class Monster final : public Creature { static std::vector> getPushItemLocationOptions(const Direction &direction); + void walkTo(const Position &walkToPosition); void doWalkBack(uint32_t &flags, Direction &nextDirection, bool &result); + void doWalkTo(uint32_t &flags, Direction &nextDirection, bool &result); void doFollowCreature(uint32_t &flags, Direction &nextDirection, bool &result); void doRandomStep(Direction &nextDirection, bool &result); diff --git a/src/lua/functions/creatures/monster/monster_functions.cpp b/src/lua/functions/creatures/monster/monster_functions.cpp index 1591053c391..5038dce09c1 100644 --- a/src/lua/functions/creatures/monster/monster_functions.cpp +++ b/src/lua/functions/creatures/monster/monster_functions.cpp @@ -613,3 +613,17 @@ int MonsterFunctions::luaMonsterHazardDefenseBoost(lua_State* L) { } return 1; } + +int MonsterFunctions::luaMonsterWalkTo(lua_State* L) { + // monster:walkTo(position) + std::shared_ptr monster = getUserdataShared(L, 1); + Position position = getPosition(L, 2); + if (!monster) { + reportErrorFunc(getErrorDesc(LUA_ERROR_MONSTER_NOT_FOUND)); + pushBoolean(L, false); + return 0; + } + + monster->walkTo(position); + return 1; +} diff --git a/src/lua/functions/creatures/monster/monster_functions.hpp b/src/lua/functions/creatures/monster/monster_functions.hpp index bf2785ae430..9926a3b5821 100644 --- a/src/lua/functions/creatures/monster/monster_functions.hpp +++ b/src/lua/functions/creatures/monster/monster_functions.hpp @@ -63,6 +63,8 @@ class MonsterFunctions final : LuaScriptInterface { registerMethod(L, "Monster", "hazardDamageBoost", MonsterFunctions::luaMonsterHazardDamageBoost); registerMethod(L, "Monster", "hazardDefenseBoost", MonsterFunctions::luaMonsterHazardDefenseBoost); + registerMethod(L, "Monster", "walkTo", MonsterFunctions::luaMonsterWalkTo); + CharmFunctions::init(L); LootFunctions::init(L); MonsterSpellFunctions::init(L); @@ -123,5 +125,7 @@ class MonsterFunctions final : LuaScriptInterface { static int luaMonsterHazardDamageBoost(lua_State* L); static int luaMonsterHazardDefenseBoost(lua_State* L); + static int luaMonsterWalkTo(lua_State* L); + friend class CreatureFunctions; }; From c872caf81effed530cb707019db98c4db7bab1d2 Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Thu, 30 May 2024 21:30:31 +0000 Subject: [PATCH 06/20] Lua code format - (Stylua) --- .../ghost_duster_creaturescripts.lua | 16 +++---- .../twenty_years_a_cook_quest/harp_action.lua | 48 +++++++++---------- .../spirit_flask_action.lua | 16 +++---- 3 files changed, 40 insertions(+), 40 deletions(-) diff --git a/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/ghost_duster_creaturescripts.lua b/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/ghost_duster_creaturescripts.lua index 8b31873afa6..61edcc303c7 100644 --- a/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/ghost_duster_creaturescripts.lua +++ b/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/ghost_duster_creaturescripts.lua @@ -42,17 +42,17 @@ function ghostDusterAttack.onHealthChange(creature, attacker, primaryDamage, pri return primaryDamage, primaryType, secondaryDamage, secondaryType end - local accumulatedDamage = creature:getStorageValue(1) + local accumulatedDamage = creature:getStorageValue(1) - accumulatedDamage = accumulatedDamage + math.abs(primaryDamage + secondaryDamage) + accumulatedDamage = accumulatedDamage + math.abs(primaryDamage + secondaryDamage) - if accumulatedDamage >= 300 then - accumulatedDamage = 0 - local var = { type = 1, number = creature:getId() } - combat:execute(creature, var) - end + if accumulatedDamage >= 300 then + accumulatedDamage = 0 + local var = { type = 1, number = creature:getId() } + combat:execute(creature, var) + end - creature:setStorageValue(1, accumulatedDamage) + creature:setStorageValue(1, accumulatedDamage) end return primaryDamage, primaryType, secondaryDamage, secondaryType end diff --git a/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/harp_action.lua b/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/harp_action.lua index ba581c0ebe8..22cc131674e 100644 --- a/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/harp_action.lua +++ b/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/harp_action.lua @@ -1,31 +1,31 @@ local harp = Action() function harp.onUse(player, item, fromPosition, target, toPosition, isHotkey) - local icon = player:getIcon("the-rest-of-ratha") - if icon.count <= 0 then - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You are out of inspiration to play.") - return true - end - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You used your musical inspiration to play a luring tunel!") - item:transform(TwentyYearsACookQuest.TheRestOfRatha.Items.HarpCooldown) - fromPosition:sendMagicEffect(CONST_ME_SOUND_GREEN) - player:setIcon("the-rest-of-ratha", CreatureIconCategory_Quests, CreatureIconQuests_Dove, icon.count - 1) + local icon = player:getIcon("the-rest-of-ratha") + if icon.count <= 0 then + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You are out of inspiration to play.") + return true + end + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You used your musical inspiration to play a luring tunel!") + item:transform(TwentyYearsACookQuest.TheRestOfRatha.Items.HarpCooldown) + fromPosition:sendMagicEffect(CONST_ME_SOUND_GREEN) + player:setIcon("the-rest-of-ratha", CreatureIconCategory_Quests, CreatureIconQuests_Dove, icon.count - 1) - local monsters = TwentyYearsACookQuest.TheRestOfRatha.BossZone:getMonsters() - for i, monster in pairs(monsters) do - if monster:getName():lower() == "the rest of ratha" then - local position = player:getPosition() - monster:walkTo(position) - end - end - addEvent(function(position) - local tile = Tile(position) - local harpCooldown = tile and tile:getItemById(TwentyYearsACookQuest.TheRestOfRatha.Items.HarpCooldown) or nil - if harpCooldown then - harpCooldown:transform(TwentyYearsACookQuest.TheRestOfRatha.Items.Harp) - end - end, 15 * 1000, fromPosition) - return true + local monsters = TwentyYearsACookQuest.TheRestOfRatha.BossZone:getMonsters() + for i, monster in pairs(monsters) do + if monster:getName():lower() == "the rest of ratha" then + local position = player:getPosition() + monster:walkTo(position) + end + end + addEvent(function(position) + local tile = Tile(position) + local harpCooldown = tile and tile:getItemById(TwentyYearsACookQuest.TheRestOfRatha.Items.HarpCooldown) or nil + if harpCooldown then + harpCooldown:transform(TwentyYearsACookQuest.TheRestOfRatha.Items.Harp) + end + end, 15 * 1000, fromPosition) + return true end harp:id(TwentyYearsACookQuest.TheRestOfRatha.Items.Harp) diff --git a/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/spirit_flask_action.lua b/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/spirit_flask_action.lua index 951d908295b..21105ba9352 100644 --- a/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/spirit_flask_action.lua +++ b/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/spirit_flask_action.lua @@ -1,14 +1,14 @@ local flaskBox = Action() function flaskBox.onUse(player, item, fromPosition, target, toPosition, isHotkey) - if player:getStorageValue(Storage.Quest.U13_30.TwentyYearsACook.FlaskBox) >= 1 then - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You already got the flask.") - return true - end - - player:setStorageValue(Storage.Quest.U13_30.TwentyYearsACook.FlaskBox, 1) - player:addItem(TwentyYearsACookQuest.TheRestOfRatha.Items.EmptySpiritFlask, 1) - return true + if player:getStorageValue(Storage.Quest.U13_30.TwentyYearsACook.FlaskBox) >= 1 then + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You already got the flask.") + return true + end + + player:setStorageValue(Storage.Quest.U13_30.TwentyYearsACook.FlaskBox, 1) + player:addItem(TwentyYearsACookQuest.TheRestOfRatha.Items.EmptySpiritFlask, 1) + return true end flaskBox:uid(TwentyYearsACookQuest.TheRestOfRatha.FlaskBoxUID) From ecc40a132fe5365ebf03c4dffa6401b34ce4c425 Mon Sep 17 00:00:00 2001 From: Pedro Henrique Alves Cruz Date: Fri, 31 May 2024 20:15:17 -0300 Subject: [PATCH 07/20] feat: draccoon herald outfits --- data/XML/outfits.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/data/XML/outfits.xml b/data/XML/outfits.xml index e18d48e865b..8ad0e140959 100644 --- a/data/XML/outfits.xml +++ b/data/XML/outfits.xml @@ -116,6 +116,7 @@ + @@ -233,4 +234,5 @@ + From 91b99d64e8bd024fe691c201860541f414625c25 Mon Sep 17 00:00:00 2001 From: Pedro Henrique Alves Cruz Date: Fri, 31 May 2024 20:15:45 -0300 Subject: [PATCH 08/20] feat: outfit items and valuables --- data/items/items.xml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/data/items/items.xml b/data/items/items.xml index ea08a440e61..f19807966c0 100644 --- a/data/items/items.xml +++ b/data/items/items.xml @@ -75825,5 +75825,23 @@ Granted by TibiaGoals.com"/> + + + + + + + + + + + + + + + + + + From d1f4e0240ce4974941ececf6a14616c34c734399 Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Fri, 31 May 2024 23:16:51 +0000 Subject: [PATCH 09/20] Code format - (Clang-format) --- src/creatures/monsters/monster.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/creatures/monsters/monster.cpp b/src/creatures/monsters/monster.cpp index 2940c6705a9..e4345532976 100644 --- a/src/creatures/monsters/monster.cpp +++ b/src/creatures/monsters/monster.cpp @@ -1216,7 +1216,7 @@ void Monster::doRandomStep(Direction &nextDirection, bool &result) { } } -void Monster::walkTo(const Position& walkToPosition) { +void Monster::walkTo(const Position &walkToPosition) { randomStepping = false; isWalkingTo = true; stdext::arraylist listDir(128); From 80f4d4d04994d2ac54e8d56f335d3495dabbfb7a Mon Sep 17 00:00:00 2001 From: Pedro Henrique Alves Cruz Date: Fri, 31 May 2024 21:36:10 -0300 Subject: [PATCH 10/20] feat: add missing effects --- src/lua/functions/core/game/lua_enums.cpp | 8 +++++++- src/utils/utils_definitions.hpp | 9 ++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/lua/functions/core/game/lua_enums.cpp b/src/lua/functions/core/game/lua_enums.cpp index 2e3813e0769..84e57cf395e 100644 --- a/src/lua/functions/core/game/lua_enums.cpp +++ b/src/lua/functions/core/game/lua_enums.cpp @@ -620,7 +620,13 @@ void LuaEnums::initConstMeEnums(lua_State* L) { registerEnum(L, CONST_ME_DIVINE_GRENADE); registerEnum(L, CONST_ME_DIVINE_EMPOWERMENT); registerEnum(L, CONST_ME_WATER_FLOATING_THRASH); - registerEnum(L, CONST_ME_AGONY); + registerEnum(L, CONST_ME_LOOT_HIGHLIGHT); + registerEnum(L, CONST_ME_STRANGE_SYMBOLS_1); + registerEnum(L, CONST_ME_STRANGE_SYMBOLS_2); + registerEnum(L, CONST_ME_STRANGE_SYMBOLS_3); + registerEnum(L, CONST_ME_BLUE_LINES); + registerEnum(L, CONST_ME_GHOST_CLAW); + registerEnum(L, CONST_ME_FOG); } void LuaEnums::initConstAniEnums(lua_State* L) { diff --git a/src/utils/utils_definitions.hpp b/src/utils/utils_definitions.hpp index af2c40ba533..117b7f7bbed 100644 --- a/src/utils/utils_definitions.hpp +++ b/src/utils/utils_definitions.hpp @@ -235,8 +235,15 @@ enum MagicEffectClasses : uint16_t { CONST_ME_WATER_FLOATING_THRASH = 247, CONST_ME_AGONY = 249, - + // 250-251 are empty CONST_ME_LOOT_HIGHLIGHT = 252, + CONST_ME_STRANGE_SYMBOLS_1 = 253, + CONST_ME_STRANGE_SYMBOLS_2 = 254, + CONST_ME_STRANGE_SYMBOLS_3 = 255, + // 256-259 are empty + CONST_ME_BLUE_LINES = 260, + CONST_ME_GHOST_CLAW = 261, + CONST_ME_FOG = 262, CONST_ME_LAST }; From 3f6e7b3a3f00c4f15c1fff84bfea57a12f243c7c Mon Sep 17 00:00:00 2001 From: Pedro Henrique Alves Cruz Date: Fri, 31 May 2024 21:37:33 -0300 Subject: [PATCH 11/20] refactor: the rest of ratha --- data-otservbr-global/lib/core/storages.lua | 8 +- .../lib/quests/twenty_years_a_cook_quest.lua | 7 ++ .../the_rest_of_ratha.lua | 73 +++++++++++++------ .../ghost_duster_creaturescripts.lua | 6 +- 4 files changed, 68 insertions(+), 26 deletions(-) diff --git a/data-otservbr-global/lib/core/storages.lua b/data-otservbr-global/lib/core/storages.lua index 3cd41a89c4b..4b3e9feca5b 100644 --- a/data-otservbr-global/lib/core/storages.lua +++ b/data-otservbr-global/lib/core/storages.lua @@ -2802,7 +2802,13 @@ Storage = { QuestLine = 47952, TheRestOfRathaDoor = 47953, FlaskBox = 47954, - DraccoonOutfits = {}, + GhostDusterDamage = 47955, + RathaConditionsApplied = 47956, + DraccoonOutfits = { + Outfit = 47997, + Outfit = 47998, + Outfit = 47999, + }, }, }, }, diff --git a/data-otservbr-global/lib/quests/twenty_years_a_cook_quest.lua b/data-otservbr-global/lib/quests/twenty_years_a_cook_quest.lua index f2d67a86d2a..e1a1d083a4e 100644 --- a/data-otservbr-global/lib/quests/twenty_years_a_cook_quest.lua +++ b/data-otservbr-global/lib/quests/twenty_years_a_cook_quest.lua @@ -2,6 +2,13 @@ TwentyYearsACookQuest = { TheRestOfRatha = { MissionZone = Zone("mission.the-rest-of-ratha"), BossZone = Zone("boss.the-rest-of-ratha"), + PositionsToTeleport = { + Position(33309, 31393, 15), + Position(33324, 31396, 15), + Position(33323, 31405, 15), + Position(33312, 31402, 15), + Position(33317, 31393, 15), + }, Items = { GhostItem = 44598, EmptySpiritFlask = 44527, diff --git a/data-otservbr-global/monster/quests/20_years_a_cook_quest/the_rest_of_ratha.lua b/data-otservbr-global/monster/quests/20_years_a_cook_quest/the_rest_of_ratha.lua index 011a14ef9f1..44892f7fc96 100644 --- a/data-otservbr-global/monster/quests/20_years_a_cook_quest/the_rest_of_ratha.lua +++ b/data-otservbr-global/monster/quests/20_years_a_cook_quest/the_rest_of_ratha.lua @@ -93,37 +93,64 @@ monster.immunities = { local effectSent = true +local function removeGhostItem(position) + local tile = Tile(position) + local ghostItem = tile:getItemById(TwentyYearsACookQuest.TheRestOfRatha.Items.GhostItem) + if ghostItem then + ghostItem:remove() + end +end + +local function createGhostItem(rathaPosition) + local tile = Tile(rathaPosition) + if tile and not tile:getItemById(TwentyYearsACookQuest.TheRestOfRatha.Items.GhostItem) then + effectSent = false + local item = Game.createItem(TwentyYearsACookQuest.TheRestOfRatha.Items.GhostItem, 1, rathaPosition) + addEvent(removeGhostItem, 6 * 1000, rathaPosition) + end +end + +local function onConditionClear(ratha) + effectSent = true + + local rathaPosition = ratha:getPosition() + if ratha:getStorageValue(Storage.Quest.U13_30.TwentyYearsACook.RathaConditionsApplied) >= 2 then + local positionIndex = math.random(1, #TwentyYearsACookQuest.TheRestOfRatha.PositionsToTeleport) + rathaPosition:sendMagicEffect(CONST_ME_GHOST_CLAW) + ratha:teleportTo(TwentyYearsACookQuest.TheRestOfRatha.PositionsToTeleport[positionIndex]) + else + rathaPosition:sendMagicEffect(CONST_ME_MORTAREA) + end +end + +local function onConditionApplied(ratha, conditionsTicks) + local rathaPosition = ratha:getPosition() + if conditionsTicks % 2000 == 0 then + rathaPosition:sendMagicEffect(CONST_ME_BLACK_BLOOD) + end + createGhostItem(rathaPosition) +end + +local function updateQuestLogOnRathaFound(rathaPosition) + for i, player in pairs(Game.getSpectators(rathaPosition, false, true, 0, 1, 0, 1)) do + if player:getStorageValue(Storage.Quest.U13_30.TwentyYearsACook.QuestLine) == 2 then + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have found the friend of the Draccoon or what's left of him, You should tell the Draccoon about it!") + player:setStorageValue(Storage.Quest.U13_30.TwentyYearsACook.QuestLine, 3) + end + end +end + mType.onThink = function(monster, interval) local monsterPosition = monster and monster:getPosition() or nil if monsterPosition and TwentyYearsACookQuest.TheRestOfRatha.MissionZone:isInZone(monsterPosition) then - for i, player in pairs(Game.getSpectators(monsterPosition, false, true, 0, 1, 0, 1)) do - if player:getStorageValue(Storage.Quest.U13_30.TwentyYearsACook.QuestLine) == 2 then - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have found the friend of the Draccoon or what's left of him, You should tell the Draccoon about it!") - player:setStorageValue(Storage.Quest.U13_30.TwentyYearsACook.QuestLine, 3) - end - end + updateQuestLogOnRathaFound(monsterPosition) elseif monsterPosition and TwentyYearsACookQuest.TheRestOfRatha.BossZone:isInZone(monsterPosition) then local appliedCondition = monster:getCondition(CONDITION_PARALYZE) local conditionsTicks = appliedCondition and appliedCondition:getTicks() or 0 if conditionsTicks > 0 then - local tile = Tile(monsterPosition) - if conditionsTicks % 2000 == 0 then - monsterPosition:sendMagicEffect(CONST_ME_BLACK_BLOOD) - end - if tile and not tile:getItemById(TwentyYearsACookQuest.TheRestOfRatha.Items.GhostItem) then - effectSent = false - local item = Game.createItem(TwentyYearsACookQuest.TheRestOfRatha.Items.GhostItem, 1, monsterPosition) - addEvent(function(position) - local tile = Tile(position) - local ghostItem = tile:getItemById(TwentyYearsACookQuest.TheRestOfRatha.Items.GhostItem) - if ghostItem then - ghostItem:remove() - end - end, 6000, monsterPosition) - end + onConditionApplied(monster, conditionsTicks) elseif not effectSent then - effectSent = true - monsterPosition:sendMagicEffect(CONST_ME_MORTAREA) + onConditionClear(monster) end end end diff --git a/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/ghost_duster_creaturescripts.lua b/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/ghost_duster_creaturescripts.lua index 61edcc303c7..5c8a41f2134 100644 --- a/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/ghost_duster_creaturescripts.lua +++ b/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/ghost_duster_creaturescripts.lua @@ -26,6 +26,8 @@ function onTargetTile(cid, pos) target:addHealth(-100, COMBAT_AGONYDAMAGE) local appliedCondition = target:getCondition(CONDITION_PARALYZE) if not appliedCondition then + local amountConditionsApplied = target:getStorageValue(Storage.Quest.U13_30.TwentyYearsACook.RathaConditionsApplied) + target:setStorageValue(Storage.Quest.U13_30.TwentyYearsACook.RathaConditionsApplied, amountConditionsApplied > 2 and 1 or amountConditionsApplied + 1) target:addCondition(condition) end end @@ -42,7 +44,7 @@ function ghostDusterAttack.onHealthChange(creature, attacker, primaryDamage, pri return primaryDamage, primaryType, secondaryDamage, secondaryType end - local accumulatedDamage = creature:getStorageValue(1) + local accumulatedDamage = creature:getStorageValue(Storage.Quest.U13_30.TwentyYearsACook.GhostDusterDamage) accumulatedDamage = accumulatedDamage + math.abs(primaryDamage + secondaryDamage) @@ -52,7 +54,7 @@ function ghostDusterAttack.onHealthChange(creature, attacker, primaryDamage, pri combat:execute(creature, var) end - creature:setStorageValue(1, accumulatedDamage) + creature:setStorageValue(Storage.Quest.U13_30.TwentyYearsACook.GhostDusterDamage, accumulatedDamage) end return primaryDamage, primaryType, secondaryDamage, secondaryType end From 84192ec88896ab4c04126e0eae1ec373cfe1a3ad Mon Sep 17 00:00:00 2001 From: Pedro Henrique Alves Cruz Date: Fri, 31 May 2024 21:40:48 -0300 Subject: [PATCH 12/20] fix: updated the rest of ratha time to defeat to 10 minutes --- .../quests/twenty_years_a_cook_quest/the_rest_of_ratha_lever.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/the_rest_of_ratha_lever.lua b/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/the_rest_of_ratha_lever.lua index 45fe563f39d..c6f24bb5ce2 100644 --- a/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/the_rest_of_ratha_lever.lua +++ b/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/the_rest_of_ratha_lever.lua @@ -3,6 +3,7 @@ local config = { name = "The Rest of Ratha", position = Position(33309, 31391, 15), }, + timeToDefeat = 10 * 60, -- 10 minutes requiredLevel = 250, playerPositions = { { pos = Position(32585, 31939, 5), teleport = Position(33319, 31406, 15), effect = CONST_ME_TELEPORT }, From 64968b53d58bc51f8e2b84dbc17b530b3a280716 Mon Sep 17 00:00:00 2001 From: Pedro Henrique Alves Cruz Date: Sun, 2 Jun 2024 18:27:03 -0300 Subject: [PATCH 13/20] refactor/feat: refactor the rest of ratha and added fryclosp mechanics --- data-otservbr-global/lib/core/quests.lua | 40 ++++++++ data-otservbr-global/lib/core/storages.lua | 7 +- .../lib/quests/twenty_years_a_cook_quest.lua | 48 +++++++++- .../twenty_years_a_cook_quest/fryclops.lua | 96 +++++++++++++++++++ .../ghost_duster.lua | 0 .../twenty_years_a_cook_quest/locked_door.lua | 90 +++++++++++++++++ .../spirit_container.lua | 0 .../the_rest_of_ratha.lua | 2 +- data-otservbr-global/npc/the_draccoon.lua | 4 + .../fryclops/axe_action.lua | 67 +++++++++++++ .../fryclops/fryclops_fight.lua | 32 +++++++ .../fryclops/fryclops_lever.lua | 27 ++++++ .../omnious_trash_moveevents.lua | 12 +++ .../ghost_duster_creaturescripts.lua | 0 .../{ => the_rest_of_ratha}/harp_action.lua | 0 .../the_rest_of_ratha/potion_rack_action.lua | 14 +++ .../spirit_flask_action.lua | 10 +- .../the_rest_of_ratha_fight.lua | 9 +- .../the_rest_of_ratha_lever.lua | 4 +- .../scripts/spells/monster/fryclops_beam.lua | 60 ++++++++++++ .../scripts/spells/monster/fryclops_melee.lua | 36 +++++++ data/items/items.xml | 3 + 22 files changed, 546 insertions(+), 15 deletions(-) create mode 100644 data-otservbr-global/monster/quests/twenty_years_a_cook_quest/fryclops.lua rename data-otservbr-global/monster/quests/{20_years_a_cook_quest => twenty_years_a_cook_quest}/ghost_duster.lua (100%) create mode 100644 data-otservbr-global/monster/quests/twenty_years_a_cook_quest/locked_door.lua rename data-otservbr-global/monster/quests/{20_years_a_cook_quest => twenty_years_a_cook_quest}/spirit_container.lua (100%) rename data-otservbr-global/monster/quests/{20_years_a_cook_quest => twenty_years_a_cook_quest}/the_rest_of_ratha.lua (98%) create mode 100644 data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/fryclops/axe_action.lua create mode 100644 data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/fryclops/fryclops_fight.lua create mode 100644 data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/fryclops/fryclops_lever.lua rename data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/{ => the_rest_of_ratha}/ghost_duster_creaturescripts.lua (100%) rename data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/{ => the_rest_of_ratha}/harp_action.lua (100%) create mode 100644 data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/the_rest_of_ratha/potion_rack_action.lua rename data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/{ => the_rest_of_ratha}/spirit_flask_action.lua (84%) rename data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/{ => the_rest_of_ratha}/the_rest_of_ratha_fight.lua (55%) rename data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/{ => the_rest_of_ratha}/the_rest_of_ratha_lever.lua (88%) create mode 100644 data-otservbr-global/scripts/spells/monster/fryclops_beam.lua create mode 100644 data-otservbr-global/scripts/spells/monster/fryclops_melee.lua diff --git a/data-otservbr-global/lib/core/quests.lua b/data-otservbr-global/lib/core/quests.lua index 0033e79f5c5..63127372400 100644 --- a/data-otservbr-global/lib/core/quests.lua +++ b/data-otservbr-global/lib/core/quests.lua @@ -6555,6 +6555,46 @@ if not Quests then endValue = 6, description = "Travel to the Draccoon's lair to learn how to proceed.", }, + [6] = { + name = "The potion", + storageId = Storage.Quest.U13_30.TwentyYearsACook.QuestLine, + missionId = 10456, + startValue = 6, + endValue = 7, + description = "Drink a 'potion of spirit of talking' in the Draccoon's lair.", + }, + [7] = { + name = "The potion", + storageId = Storage.Quest.U13_30.TwentyYearsACook.QuestLine, + missionId = 10457, + startValue = 7, + endValue = 8, + description = "You accidentally drunk Ratha. Better talk to the Draccoon about it.", + }, + [8] = { + name = "Revenge best served fried!", + storageId = Storage.Quest.U13_30.TwentyYearsACook.QuestLine, + missionId = 10458, + startValue = 8, + endValue = 9, + description = "Travel to the house of the Fryclops and find a way to remove him from the picture. The Draccoon's allies will provide a secret access from somewhere in the south of the Ghostlands.", + }, + [9] = { + name = "An eye for an eye", + storageId = Storage.Quest.U13_30.TwentyYearsACook.QuestLine, + missionId = 10459, + startValue = 9, + endValue = 10, + description = "You triumphed over the Fryclops.\nTalk to the Draccoon about your success.", + }, + [10] = { + name = "In charge", + storageId = Storage.Quest.U13_30.TwentyYearsACook.QuestLine, + missionId = 10460, + startValue = 10, + endValue = 11, + description = "Travel to Edron to find the Draccoon's ally. Steal charged crystals from some demons to power up the Fryclop's machine.", + }, }, }, } diff --git a/data-otservbr-global/lib/core/storages.lua b/data-otservbr-global/lib/core/storages.lua index 4b3e9feca5b..d34469c2e06 100644 --- a/data-otservbr-global/lib/core/storages.lua +++ b/data-otservbr-global/lib/core/storages.lua @@ -2802,12 +2802,13 @@ Storage = { QuestLine = 47952, TheRestOfRathaDoor = 47953, FlaskBox = 47954, - GhostDusterDamage = 47955, - RathaConditionsApplied = 47956, + AxeBox = 47955, + GhostDusterDamage = 47956, + RathaConditionsApplied = 47957, DraccoonOutfits = { - Outfit = 47997, Outfit = 47998, Outfit = 47999, + Outfit = 48000, }, }, }, diff --git a/data-otservbr-global/lib/quests/twenty_years_a_cook_quest.lua b/data-otservbr-global/lib/quests/twenty_years_a_cook_quest.lua index e1a1d083a4e..1fd1e19fa37 100644 --- a/data-otservbr-global/lib/quests/twenty_years_a_cook_quest.lua +++ b/data-otservbr-global/lib/quests/twenty_years_a_cook_quest.lua @@ -10,17 +10,61 @@ TwentyYearsACookQuest = { Position(33317, 31393, 15), }, Items = { - GhostItem = 44598, EmptySpiritFlask = 44527, FullSpiritFlask = 44528, + PotionRack = 44597, + GhostItem = 44598, Harp = 44599, HarpCooldown = 44600, }, + LeverUID = 62133, FlaskBoxUID = 62134, - SpiritContainerPoints = 0, + TimeToDefeat = 10 * 60, -- 10 minutes + }, + Fryclops = { + BossZone = Zone("boss.fryclops"), + Items = { + AxeBox = 44562, + Axe = 44525, + CatapultRope = 44410, + }, + LeverUID = 62135, + TimeToDefeat = 10 * 60, -- 10 minutes + MeleePoints = 5, + BeamPoints = 10, + Exit = Position(32299, 31698, 8), + Catapult = { + FryclopsPosition = Position(32349, 31595, 6), + RopePosition = Position(32348, 31595, 6), + CatapultUpdateMap = { + [Position(32349, 31595, 6)] = { on = 0, off = 44411 }, + [Position(32348, 31595, 6)] = { on = 44419, off = 44410 }, + [Position(32350, 31595, 6)] = { on = 44420, off = 44412 }, + [Position(32351, 31595, 5)] = { on = 44426, off = 0 }, + [Position(32351, 31595, 6)] = { on = 44421, off = 44413 }, + }, + UpdateCatapultItems = function(on) + for position, status in pairs(TwentyYearsACookQuest.Fryclops.Catapult.CatapultUpdateMap) do + local tile = Tile(position) + local updated = false + if tile then + local item = tile:getItemById(on and status.off or status.on) + if item then + item:remove() + end + else + Game.createTile(position) + end + if (on and status.on ~= 0) or (not on and status.off ~= 0) then + Game.createItem(on and status.on or status.off, 1, position) + end + end + end + }, }, } -- Initializing zones TwentyYearsACookQuest.TheRestOfRatha.MissionZone:addArea({ x = 33303, y = 31425, z = 15 }, { x = 33327, y = 31445, z = 15 }) TwentyYearsACookQuest.TheRestOfRatha.BossZone:addArea({ x = 33303, y = 31388, z = 15 }, { x = 33327, y = 31408, z = 15 }) +TwentyYearsACookQuest.Fryclops.BossZone:addArea({ x = 32342, y = 31589, z = 6 }, { x = 32368, y = 31611, z = 6 }) \ No newline at end of file diff --git a/data-otservbr-global/monster/quests/twenty_years_a_cook_quest/fryclops.lua b/data-otservbr-global/monster/quests/twenty_years_a_cook_quest/fryclops.lua new file mode 100644 index 00000000000..4bc3f25ef3f --- /dev/null +++ b/data-otservbr-global/monster/quests/twenty_years_a_cook_quest/fryclops.lua @@ -0,0 +1,96 @@ +local monsterName = "Fryclops" +local mType = Game.createMonsterType(monsterName) +local monster = {} + +monster.description = monsterName +monster.experience = 0 +monster.outfit = { + lookType = 1700, + lookHead = 0, + lookBody = 0, + lookLegs = 0, + lookFeet = 0, + lookAddons = 0, + lookMount = 0, +} + +monster.events = {} + +monster.health = 100 +monster.maxHealth = 100 +monster.race = "blood" +monster.corpse = 0 +monster.speed = 95 +monster.manaCost = 0 + +monster.changeTarget = { + interval = 4000, + chance = 10, +} + +monster.strategiesTarget = { + random = 100, +} + +monster.flags = { + summonable = false, + attackable = false, + hostile = true, + convinceable = false, + pushable = false, + rewardBoss = false, + illusionable = false, + canPushItems = false, + canPushCreatures = false, + staticAttackChance = 90, + targetDistance = 1, + runHealth = 0, + healthHidden = false, + isBlockable = false, + canWalkOnEnergy = true, + canWalkOnFire = true, + canWalkOnPoison = true, +} + +monster.light = { + level = 0, + color = 0, +} + +monster.summon = {} + +monster.voices = {} + +monster.loot = {} + +monster.attacks = { + { name = "fryclops melee", interval = 2000, chance = 100, minDamage = 0, maxDamage = 0, effect = CONST_ME_EXPLOSIONAREA, range = 1 }, + { name = "fryclops beam", interval = 2000, chance = 100, minDamage = 0, maxDamage = 0 }, +} + +monster.defenses = {} + +monster.elements = { + { type = COMBAT_PHYSICALDAMAGE, percent = 100 }, + { type = COMBAT_ENERGYDAMAGE, percent = 100 }, + { type = COMBAT_EARTHDAMAGE, percent = 100 }, + { type = COMBAT_FIREDAMAGE, percent = 100 }, + { type = COMBAT_LIFEDRAIN, percent = 100 }, + { type = COMBAT_MANADRAIN, percent = 100 }, + { type = COMBAT_DROWNDAMAGE, percent = 100 }, + { type = COMBAT_ICEDAMAGE, percent = 100 }, + { type = COMBAT_HOLYDAMAGE, percent = 100 }, + { type = COMBAT_DEATHDAMAGE, percent = 100 }, +} + +monster.immunities = { + { type = "paralyze", condition = true }, + { type = "outfit", condition = true }, + { type = "invisible", condition = true }, + { type = "bleed", condition = true }, +} + +mType.onThink = function(monster, interval) +end + +mType:register(monster) diff --git a/data-otservbr-global/monster/quests/20_years_a_cook_quest/ghost_duster.lua b/data-otservbr-global/monster/quests/twenty_years_a_cook_quest/ghost_duster.lua similarity index 100% rename from data-otservbr-global/monster/quests/20_years_a_cook_quest/ghost_duster.lua rename to data-otservbr-global/monster/quests/twenty_years_a_cook_quest/ghost_duster.lua diff --git a/data-otservbr-global/monster/quests/twenty_years_a_cook_quest/locked_door.lua b/data-otservbr-global/monster/quests/twenty_years_a_cook_quest/locked_door.lua new file mode 100644 index 00000000000..4314362d7f4 --- /dev/null +++ b/data-otservbr-global/monster/quests/twenty_years_a_cook_quest/locked_door.lua @@ -0,0 +1,90 @@ +local monsterName = "Locked Door" +local mType = Game.createMonsterType(monsterName) +local monster = {} + +monster.description = monsterName +monster.experience = 0 +monster.outfit = { + lookTypeEx = 44568, +} + +monster.events = {} + +monster.health = 1000 +monster.maxHealth = 1000 +monster.race = "undead" +monster.corpse = 0 +monster.speed = 0 +monster.manaCost = 0 + +monster.changeTarget = { + interval = 0, + chance = 0, +} + +monster.strategiesTarget = { + nearest = 0, + random = 0, +} + +monster.flags = { + canWalk = false, + canTarget = false, + summonable = false, + attackable = true, + hostile = false, + convinceable = false, + pushable = false, + rewardBoss = false, + illusionable = false, + canPushItems = false, + canPushCreatures = false, + staticAttackChance = 0, + targetDistance = 0, + runHealth = 0, + healthHidden = false, + isBlockable = false, + canWalkOnEnergy = false, + canWalkOnFire = false, + canWalkOnPoison = false, +} + +monster.light = { + level = 0, + color = 0, +} + +monster.summon = {} + +monster.voices = {} + +monster.loot = {} + +monster.attacks = {} + +monster.defenses = {} + +monster.elements = { + { type = COMBAT_PHYSICALDAMAGE, percent = 100 }, + { type = COMBAT_ENERGYDAMAGE, percent = 100 }, + { type = COMBAT_EARTHDAMAGE, percent = 100 }, + { type = COMBAT_FIREDAMAGE, percent = 100 }, + { type = COMBAT_LIFEDRAIN, percent = 100 }, + { type = COMBAT_MANADRAIN, percent = 100 }, + { type = COMBAT_DROWNDAMAGE, percent = 100 }, + { type = COMBAT_ICEDAMAGE, percent = 100 }, + { type = COMBAT_HOLYDAMAGE, percent = 100 }, + { type = COMBAT_DEATHDAMAGE, percent = 100 }, +} + +monster.immunities = { + { type = "paralyze", condition = true }, + { type = "outfit", condition = true }, + { type = "invisible", condition = true }, + { type = "bleed", condition = true }, +} + +mType.onThink = function(monster, interval) +end + +mType:register(monster) diff --git a/data-otservbr-global/monster/quests/20_years_a_cook_quest/spirit_container.lua b/data-otservbr-global/monster/quests/twenty_years_a_cook_quest/spirit_container.lua similarity index 100% rename from data-otservbr-global/monster/quests/20_years_a_cook_quest/spirit_container.lua rename to data-otservbr-global/monster/quests/twenty_years_a_cook_quest/spirit_container.lua diff --git a/data-otservbr-global/monster/quests/20_years_a_cook_quest/the_rest_of_ratha.lua b/data-otservbr-global/monster/quests/twenty_years_a_cook_quest/the_rest_of_ratha.lua similarity index 98% rename from data-otservbr-global/monster/quests/20_years_a_cook_quest/the_rest_of_ratha.lua rename to data-otservbr-global/monster/quests/twenty_years_a_cook_quest/the_rest_of_ratha.lua index 44892f7fc96..209cd8e265e 100644 --- a/data-otservbr-global/monster/quests/20_years_a_cook_quest/the_rest_of_ratha.lua +++ b/data-otservbr-global/monster/quests/twenty_years_a_cook_quest/the_rest_of_ratha.lua @@ -116,7 +116,7 @@ local function onConditionClear(ratha) local rathaPosition = ratha:getPosition() if ratha:getStorageValue(Storage.Quest.U13_30.TwentyYearsACook.RathaConditionsApplied) >= 2 then local positionIndex = math.random(1, #TwentyYearsACookQuest.TheRestOfRatha.PositionsToTeleport) - rathaPosition:sendMagicEffect(CONST_ME_GHOST_CLAW) + rathaPosition:sendMagicEffect(CONST_ME_GHOST_SMOKE) ratha:teleportTo(TwentyYearsACookQuest.TheRestOfRatha.PositionsToTeleport[positionIndex]) else rathaPosition:sendMagicEffect(CONST_ME_MORTAREA) diff --git a/data-otservbr-global/npc/the_draccoon.lua b/data-otservbr-global/npc/the_draccoon.lua index c9cf3d38f39..ee148871fba 100644 --- a/data-otservbr-global/npc/the_draccoon.lua +++ b/data-otservbr-global/npc/the_draccoon.lua @@ -117,6 +117,10 @@ local function creatureSayCallback(npc, creature, type, message) npcHandler:say(" Ratha's demise is most unfortunate, indeed! ...", npc, creature) npcHandler:say("But well, as he is still around... to some capacity at least, I am sure we are able to communicate with him. Just travel to his apartment again, I'll send one of my buddies to your assistance. ...", npc, creature, 2000) player:setStorageValue(Storage.Quest.U13_30.TwentyYearsACook.QuestLine, 4) + elseif mission == 5 then + + elseif mission == 7 then + end end return true diff --git a/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/fryclops/axe_action.lua b/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/fryclops/axe_action.lua new file mode 100644 index 00000000000..11106d9d5a3 --- /dev/null +++ b/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/fryclops/axe_action.lua @@ -0,0 +1,67 @@ +local axeBox = Action() + +function axeBox.onUse(player, item, fromPosition, target, toPosition, isHotkey) + if not TwentyYearsACookQuest.Fryclops.BossZone:isInZone(player:getPosition()) then + return true + end + + if player:getStorageValue(Storage.Quest.U13_30.TwentyYearsACook.AxeBox) > os.time() then + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You already got the flask.") + return true + end + + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You got an axe, unwieldy but sharp!") + player:setStorageValue(Storage.Quest.U13_30.TwentyYearsACook.AxeBox, os.time() + (TwentyYearsACookQuest.Fryclops.TimeToDefeat * 1000)) + player:addItem(TwentyYearsACookQuest.Fryclops.Items.Axe, 1) + return true +end + +axeBox:id(TwentyYearsACookQuest.Fryclops.Items.AxeBox) +axeBox:register() + +local fryclopsAxe = Action() + +local function sendMagicEffectAroundFryclops() + for i = 1, -1, -1 do + for j = -1, 1, 1 do + local yPosition = Position(TwentyYearsACookQuest.Fryclops.Catapult.FryclopsPosition.x + j, TwentyYearsACookQuest.Fryclops.Catapult.FryclopsPosition.y + i, TwentyYearsACookQuest.Fryclops.Catapult.FryclopsPosition.z) + yPosition:sendMagicEffect(CONST_ME_POFF) + end + end +end + +function fryclopsAxe.onUse(player, item, fromPosition, target, toPosition, isHotkey) + if target and not target:isItem() then + return true + end + + if target:getId() ~= TwentyYearsACookQuest.Fryclops.Items.CatapultRope then + return true + end + + if toPosition ~= TwentyYearsACookQuest.Fryclops.Catapult.RopePosition then + return true + end + + local tile = Tile(TwentyYearsACookQuest.Fryclops.Catapult.FryclopsPosition) + if not tile then + return true + end + + local creature = tile:getTopCreature() + + sendMagicEffectAroundFryclops() + TwentyYearsACookQuest.Fryclops.Catapult.UpdateCatapultItems(true) + + if creature and creature:getName():lower() == "fryclops" then + creature:say("WAAAAAaaaaaaaaa...a...a...a...a...a............!", TALKTYPE_MONSTER_SAY) + creature:remove() + local players = TwentyYearsACookQuest.Fryclops.BossZone:getPlayers() + for i, playerInZone in pairs(players) do + player:setStorageValue(Storage.Quest.U13_30.TwentyYearsACook.QuestLine, 9) + end + end +end + +fryclopsAxe:id(TwentyYearsACookQuest.Fryclops.Items.Axe) +fryclopsAxe:register() diff --git a/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/fryclops/fryclops_fight.lua b/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/fryclops/fryclops_fight.lua new file mode 100644 index 00000000000..fa1b65449aa --- /dev/null +++ b/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/fryclops/fryclops_fight.lua @@ -0,0 +1,32 @@ +local fryclopsZoneEvent = ZoneEvent(TwentyYearsACookQuest.Fryclops.BossZone) +function fryclopsZoneEvent.afterEnter(_zone, creature) + local player = creature:getPlayer() + if not player then + return false + end + + player:setIcon("fryclops", CreatureIconCategory_Quests, CreatureIconQuests_GreenBall, 200) + return true +end + +function fryclopsZoneEvent.afterLeave(zone, creature) + local player = creature:getPlayer() + if not player then + return false + end + + local axeCount = player:getItemCount(TwentyYearsACookQuest.Fryclops.Items.Axe) + if axeCount and axeCount > 0 then + player:removeItem(TwentyYearsACookQuest.Fryclops.Items.Axe, axeCount) + end + + player:removeIcon("fryclops") + + if #zone:getPlayers() == 0 then + TwentyYearsACookQuest.Fryclops.Catapult.UpdateCatapultItems(false) + end + + return true +end + +fryclopsZoneEvent:register() diff --git a/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/fryclops/fryclops_lever.lua b/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/fryclops/fryclops_lever.lua new file mode 100644 index 00000000000..d30ec3c8050 --- /dev/null +++ b/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/fryclops/fryclops_lever.lua @@ -0,0 +1,27 @@ +local config = { + boss = { + name = "Fryclops", + position = Position(32353, 31604, 6), + }, + timeToDefeat = TwentyYearsACookQuest.Fryclops.TimeToDefeat, + requiredLevel = 250, + playerPositions = { + { pos = Position(32365, 31602, 7), teleport = Position(32362, 31602, 6), effect = CONST_ME_TELEPORT }, + { pos = Position(32366, 31602, 7), teleport = Position(32362, 31602, 6), effect = CONST_ME_TELEPORT }, + { pos = Position(32367, 31602, 7), teleport = Position(32362, 31602, 6), effect = CONST_ME_TELEPORT }, + { pos = Position(32368, 31602, 7), teleport = Position(32362, 31602, 6), effect = CONST_ME_TELEPORT }, + { pos = Position(32369, 31602, 7), teleport = Position(32362, 31602, 6), effect = CONST_ME_TELEPORT }, + }, + specPos = { + from = Position(32341, 31589, 6), + to = Position(32368, 21611, 6), + }, + monsters = { + { name = "Locked Door", pos = Position(32357, 31600, 6) }, + }, + exit = TwentyYearsACookQuest.Fryclops.Exit, +} + +local lever = BossLever(config) +lever:uid(TwentyYearsACookQuest.Fryclops.LeverUID) +lever:register() diff --git a/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/omnious_trash_moveevents.lua b/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/omnious_trash_moveevents.lua index ea765a04851..e43155865a0 100644 --- a/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/omnious_trash_moveevents.lua +++ b/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/omnious_trash_moveevents.lua @@ -1,4 +1,16 @@ local positions = { + [Position(32367, 31596, 7)] = { + toPosition = Position(32301, 31697, 8), + storageValue = 8, + }, + [Position(32301, 31697, 8)] = { + toPosition = Position(32368, 31598, 7), + storageValue = 8, + }, + [Position(32246, 31832, 7)] = { + toPosition = Position(32298, 31704, 8), + storageValue = 8, + }, [Position(32591, 31936, 5)] = { toPosition = Position(32587, 31937, 5), storageValue = 4, diff --git a/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/ghost_duster_creaturescripts.lua b/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/the_rest_of_ratha/ghost_duster_creaturescripts.lua similarity index 100% rename from data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/ghost_duster_creaturescripts.lua rename to data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/the_rest_of_ratha/ghost_duster_creaturescripts.lua diff --git a/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/harp_action.lua b/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/the_rest_of_ratha/harp_action.lua similarity index 100% rename from data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/harp_action.lua rename to data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/the_rest_of_ratha/harp_action.lua diff --git a/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/the_rest_of_ratha/potion_rack_action.lua b/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/the_rest_of_ratha/potion_rack_action.lua new file mode 100644 index 00000000000..d2a82f71551 --- /dev/null +++ b/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/the_rest_of_ratha/potion_rack_action.lua @@ -0,0 +1,14 @@ +local potionRack = Action() + +function potionRack.onUse(player, item, fromPosition, target, toPosition, isHotkey) + if player:getStorageValue(Storage.Quest.U13_30.TwentyYearsACook.QuestLine) == 6 then + item:getPosition():sendMagicEffect(CONST_ME_POFF) + player:getPosition():sendMagicEffect(CONST_ME_STUN) + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Oops, that was the wrong potion! It seems you have accidently drunken Ratha!") + player:say("GULP!", TALKTYPE_MONSTER_SAY) + player:setStorageValue(Storage.Quest.U13_30.TwentyYearsACook.QuestLine, 7) + end +end + +potionRack:id(TwentyYearsACookQuest.TheRestOfRatha.Items.PotionRack) +potionRack:register() diff --git a/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/spirit_flask_action.lua b/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/the_rest_of_ratha/spirit_flask_action.lua similarity index 84% rename from data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/spirit_flask_action.lua rename to data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/the_rest_of_ratha/spirit_flask_action.lua index 21105ba9352..0942cacf047 100644 --- a/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/spirit_flask_action.lua +++ b/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/the_rest_of_ratha/spirit_flask_action.lua @@ -1,12 +1,12 @@ local flaskBox = Action() function flaskBox.onUse(player, item, fromPosition, target, toPosition, isHotkey) - if player:getStorageValue(Storage.Quest.U13_30.TwentyYearsACook.FlaskBox) >= 1 then + if player:getStorageValue(Storage.Quest.U13_30.TwentyYearsACook.FlaskBox) > os.time() then player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You already got the flask.") return true end - player:setStorageValue(Storage.Quest.U13_30.TwentyYearsACook.FlaskBox, 1) + player:setStorageValue(Storage.Quest.U13_30.TwentyYearsACook.FlaskBox, os.time() + (TwentyYearsACookQuest.TheRestOfRatha.TimeToDefeat * 1000)) player:addItem(TwentyYearsACookQuest.TheRestOfRatha.Items.EmptySpiritFlask, 1) return true end @@ -45,11 +45,11 @@ function fullSpiritFlask.onUse(player, item, fromPosition, target, toPosition, i end if monster:getName():lower() == "spirit container" then - local icon = monster:getIcon("spirit-container") - monster:setIcon("spirit-container", CreatureIconCategory_Quests, CreatureIconQuests_WhiteCross, icon and icon.count + 1 or 1) + local addIconCount = monster:getIcon("spirit-container") and icon.count + 1 or 1 + monster:setIcon("spirit-container", CreatureIconCategory_Quests, CreatureIconQuests_WhiteCross, addIconCount) monster:getPosition():sendMagicEffect(CONST_ME_PIXIE_EXPLOSION) item:transform(TwentyYearsACookQuest.TheRestOfRatha.Items.EmptySpiritFlask) - if TwentyYearsACookQuest.TheRestOfRatha.SpiritContainerPoints > 50 then + if addIconCount >= 50 and player:getStorageValue(Storage.Quest.U13_30.TwentyYearsACook.QuestLine) < 5 then local players = TwentyYearsACookQuest.TheRestOfRatha.BossZone:getPlayers() for i, player in ipairs(players) do player:setStorageValue(Storage.Quest.U13_30.TwentyYearsACook.QuestLine, 5) diff --git a/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/the_rest_of_ratha_fight.lua b/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/the_rest_of_ratha/the_rest_of_ratha_fight.lua similarity index 55% rename from data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/the_rest_of_ratha_fight.lua rename to data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/the_rest_of_ratha/the_rest_of_ratha_fight.lua index 31741d309a3..e8ff69ecd68 100644 --- a/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/the_rest_of_ratha_fight.lua +++ b/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/the_rest_of_ratha/the_rest_of_ratha_fight.lua @@ -15,8 +15,13 @@ function theRestOfRathaZoneEvent.afterLeave(zone, creature) return false end - if not zone:getPlayers() then - TwentyYearsACookQuest.TheRestOfRatha.SpiritContainerPoints = 0 + local emptyCount = player:getItemCount(TwentyYearsACookQuest.TheRestOfRatha.Items.EmptySpiritFlask) + local fullCount = player:getItemCount(TwentyYearsACookQuest.TheRestOfRatha.Items.FullSpiritFlask) + if emptyCount and emptyCount > 0 then + player:removeItem(TwentyYearsACookQuest.TheRestOfRatha.Items.EmptySpiritFlask, emptyCount) + end + if fullCount and fullCount > 0 then + player:removeItem(TwentyYearsACookQuest.TheRestOfRatha.Items.FullSpiritFlask, 1) end player:removeIcon("the-rest-of-ratha") diff --git a/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/the_rest_of_ratha_lever.lua b/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/the_rest_of_ratha/the_rest_of_ratha_lever.lua similarity index 88% rename from data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/the_rest_of_ratha_lever.lua rename to data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/the_rest_of_ratha/the_rest_of_ratha_lever.lua index c6f24bb5ce2..1e7c9c52c7a 100644 --- a/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/the_rest_of_ratha_lever.lua +++ b/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/the_rest_of_ratha/the_rest_of_ratha_lever.lua @@ -3,7 +3,7 @@ local config = { name = "The Rest of Ratha", position = Position(33309, 31391, 15), }, - timeToDefeat = 10 * 60, -- 10 minutes + timeToDefeat = TwentyYearsACookQuest.TheRestOfRatha.TimeToDefeat, requiredLevel = 250, playerPositions = { { pos = Position(32585, 31939, 5), teleport = Position(33319, 31406, 15), effect = CONST_ME_TELEPORT }, @@ -24,5 +24,5 @@ local config = { } local lever = BossLever(config) -lever:uid(62133) +lever:uid(TwentyYearsACookQuest.TheRestOfRatha.LeverUID) lever:register() diff --git a/data-otservbr-global/scripts/spells/monster/fryclops_beam.lua b/data-otservbr-global/scripts/spells/monster/fryclops_beam.lua new file mode 100644 index 00000000000..98abe0acfa4 --- /dev/null +++ b/data-otservbr-global/scripts/spells/monster/fryclops_beam.lua @@ -0,0 +1,60 @@ +local combat = Combat() + +arr = { + { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0 }, +} + +local area = createCombatArea(arr) +combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_GROUNDSHAKER) +combat:setArea(area) + +function onTargetTile(creature, pos) + local tile = Tile(pos) + + if not tile then + return true + end + + local target = tile:getTopCreature() + + if not target then + return true + end + + if target:isMonster() and target:getName():lower() == "locked door" then + target:addHealth(-250, COMBAT_AGONYDAMAGE) + elseif target:isPlayer() then + local icon = target:getIcon("fryclops") + if icon and icon.count > 0 then + local newCount = icon.count - TwentyYearsACookQuest.Fryclops.BeamPoints + if newCount > 0 then + target:setIcon("fryclops", CreatureIconCategory_Quests, CreatureIconQuests_GreenBall, newCount) + else + target:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You ran out of points!") + target:teleportTo(TwentyYearsACookQuest.Fryclops.Exit) + end + end + end + return true +end + +combat:setCallback(CALLBACK_PARAM_TARGETTILE, "onTargetTile") + +local spell = Spell("instant") + +function spell.onCastSpell(creature, var) + return combat:execute(creature, var) +end + +spell:name("fryclops beam") +spell:words("###545") +spell:isAggressive(true) +spell:blockWalls(true) +spell:needLearn(true) +spell:needDirection(true) +spell:register() diff --git a/data-otservbr-global/scripts/spells/monster/fryclops_melee.lua b/data-otservbr-global/scripts/spells/monster/fryclops_melee.lua new file mode 100644 index 00000000000..6fabd3a08f5 --- /dev/null +++ b/data-otservbr-global/scripts/spells/monster/fryclops_melee.lua @@ -0,0 +1,36 @@ +local spell = Spell("instant") + +local combat = Combat() +combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_EXPLOSIONAREA) + +function onTargetCreature(creature, target) + if not target:isPlayer() then + return true + end + + local icon = target:getIcon("fryclops") + if icon and icon.count > 0 then + local newCount = icon.count - TwentyYearsACookQuest.Fryclops.MeleePoints + if newCount > 0 then + target:setIcon("fryclops", CreatureIconCategory_Quests, CreatureIconQuests_GreenBall, newCount) + else + target:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You ran out of points!") + target:teleportTo(TwentyYearsACookQuest.Fryclops.Exit) + end + end + return true +end + +combat:setCallback(CALLBACK_PARAM_TARGETCREATURE, "onTargetCreature") + +function spell.onCastSpell(creature, var) + return combat:execute(creature, var) +end + +spell:name("fryclops melee") +spell:words("###544") +spell:isAggressive(true) +spell:blockWalls(true) +spell:needLearn(true) +spell:needTarget(true) +spell:register() diff --git a/data/items/items.xml b/data/items/items.xml index f19807966c0..e20636da5d1 100644 --- a/data/items/items.xml +++ b/data/items/items.xml @@ -75748,6 +75748,9 @@ Granted by TibiaGoals.com"/> + + + From 486307741bf36af287ff0ab40142fa31df513882 Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Sun, 2 Jun 2024 21:28:28 +0000 Subject: [PATCH 14/20] Lua code format - (Stylua) --- .../lib/quests/twenty_years_a_cook_quest.lua | 4 ++-- .../quests/twenty_years_a_cook_quest/fryclops.lua | 3 +-- .../twenty_years_a_cook_quest/locked_door.lua | 3 +-- data-otservbr-global/npc/the_draccoon.lua | 2 -- .../fryclops/axe_action.lua | 2 +- .../the_rest_of_ratha/potion_rack_action.lua | 14 +++++++------- 6 files changed, 12 insertions(+), 16 deletions(-) diff --git a/data-otservbr-global/lib/quests/twenty_years_a_cook_quest.lua b/data-otservbr-global/lib/quests/twenty_years_a_cook_quest.lua index 1fd1e19fa37..1cb233de7e2 100644 --- a/data-otservbr-global/lib/quests/twenty_years_a_cook_quest.lua +++ b/data-otservbr-global/lib/quests/twenty_years_a_cook_quest.lua @@ -59,7 +59,7 @@ TwentyYearsACookQuest = { Game.createItem(on and status.on or status.off, 1, position) end end - end + end, }, }, } @@ -67,4 +67,4 @@ TwentyYearsACookQuest = { -- Initializing zones TwentyYearsACookQuest.TheRestOfRatha.MissionZone:addArea({ x = 33303, y = 31425, z = 15 }, { x = 33327, y = 31445, z = 15 }) TwentyYearsACookQuest.TheRestOfRatha.BossZone:addArea({ x = 33303, y = 31388, z = 15 }, { x = 33327, y = 31408, z = 15 }) -TwentyYearsACookQuest.Fryclops.BossZone:addArea({ x = 32342, y = 31589, z = 6 }, { x = 32368, y = 31611, z = 6 }) \ No newline at end of file +TwentyYearsACookQuest.Fryclops.BossZone:addArea({ x = 32342, y = 31589, z = 6 }, { x = 32368, y = 31611, z = 6 }) diff --git a/data-otservbr-global/monster/quests/twenty_years_a_cook_quest/fryclops.lua b/data-otservbr-global/monster/quests/twenty_years_a_cook_quest/fryclops.lua index 4bc3f25ef3f..7ea639d481b 100644 --- a/data-otservbr-global/monster/quests/twenty_years_a_cook_quest/fryclops.lua +++ b/data-otservbr-global/monster/quests/twenty_years_a_cook_quest/fryclops.lua @@ -90,7 +90,6 @@ monster.immunities = { { type = "bleed", condition = true }, } -mType.onThink = function(monster, interval) -end +mType.onThink = function(monster, interval) end mType:register(monster) diff --git a/data-otservbr-global/monster/quests/twenty_years_a_cook_quest/locked_door.lua b/data-otservbr-global/monster/quests/twenty_years_a_cook_quest/locked_door.lua index 4314362d7f4..af39c600752 100644 --- a/data-otservbr-global/monster/quests/twenty_years_a_cook_quest/locked_door.lua +++ b/data-otservbr-global/monster/quests/twenty_years_a_cook_quest/locked_door.lua @@ -84,7 +84,6 @@ monster.immunities = { { type = "bleed", condition = true }, } -mType.onThink = function(monster, interval) -end +mType.onThink = function(monster, interval) end mType:register(monster) diff --git a/data-otservbr-global/npc/the_draccoon.lua b/data-otservbr-global/npc/the_draccoon.lua index ee148871fba..fa01df11ba4 100644 --- a/data-otservbr-global/npc/the_draccoon.lua +++ b/data-otservbr-global/npc/the_draccoon.lua @@ -118,9 +118,7 @@ local function creatureSayCallback(npc, creature, type, message) npcHandler:say("But well, as he is still around... to some capacity at least, I am sure we are able to communicate with him. Just travel to his apartment again, I'll send one of my buddies to your assistance. ...", npc, creature, 2000) player:setStorageValue(Storage.Quest.U13_30.TwentyYearsACook.QuestLine, 4) elseif mission == 5 then - elseif mission == 7 then - end end return true diff --git a/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/fryclops/axe_action.lua b/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/fryclops/axe_action.lua index 11106d9d5a3..47de6ecbf54 100644 --- a/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/fryclops/axe_action.lua +++ b/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/fryclops/axe_action.lua @@ -44,7 +44,7 @@ function fryclopsAxe.onUse(player, item, fromPosition, target, toPosition, isHot end local tile = Tile(TwentyYearsACookQuest.Fryclops.Catapult.FryclopsPosition) - if not tile then + if not tile then return true end diff --git a/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/the_rest_of_ratha/potion_rack_action.lua b/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/the_rest_of_ratha/potion_rack_action.lua index d2a82f71551..a261cf21805 100644 --- a/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/the_rest_of_ratha/potion_rack_action.lua +++ b/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/the_rest_of_ratha/potion_rack_action.lua @@ -1,13 +1,13 @@ local potionRack = Action() function potionRack.onUse(player, item, fromPosition, target, toPosition, isHotkey) - if player:getStorageValue(Storage.Quest.U13_30.TwentyYearsACook.QuestLine) == 6 then - item:getPosition():sendMagicEffect(CONST_ME_POFF) - player:getPosition():sendMagicEffect(CONST_ME_STUN) - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Oops, that was the wrong potion! It seems you have accidently drunken Ratha!") - player:say("GULP!", TALKTYPE_MONSTER_SAY) - player:setStorageValue(Storage.Quest.U13_30.TwentyYearsACook.QuestLine, 7) - end + if player:getStorageValue(Storage.Quest.U13_30.TwentyYearsACook.QuestLine) == 6 then + item:getPosition():sendMagicEffect(CONST_ME_POFF) + player:getPosition():sendMagicEffect(CONST_ME_STUN) + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Oops, that was the wrong potion! It seems you have accidently drunken Ratha!") + player:say("GULP!", TALKTYPE_MONSTER_SAY) + player:setStorageValue(Storage.Quest.U13_30.TwentyYearsACook.QuestLine, 7) + end end potionRack:id(TwentyYearsACookQuest.TheRestOfRatha.Items.PotionRack) From e8b43024c2253705f92133f5a69ad8daa01015fd Mon Sep 17 00:00:00 2001 From: Pedro Henrique Alves Cruz Date: Sun, 2 Jun 2024 18:29:51 -0300 Subject: [PATCH 15/20] refactor: renamed catapult update method --- data-otservbr-global/lib/quests/twenty_years_a_cook_quest.lua | 2 +- .../quests/twenty_years_a_cook_quest/fryclops/axe_action.lua | 2 +- .../twenty_years_a_cook_quest/fryclops/fryclops_fight.lua | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/data-otservbr-global/lib/quests/twenty_years_a_cook_quest.lua b/data-otservbr-global/lib/quests/twenty_years_a_cook_quest.lua index 1cb233de7e2..9cee6c433ec 100644 --- a/data-otservbr-global/lib/quests/twenty_years_a_cook_quest.lua +++ b/data-otservbr-global/lib/quests/twenty_years_a_cook_quest.lua @@ -43,7 +43,7 @@ TwentyYearsACookQuest = { [Position(32351, 31595, 5)] = { on = 44426, off = 0 }, [Position(32351, 31595, 6)] = { on = 44421, off = 44413 }, }, - UpdateCatapultItems = function(on) + UpdateCatapult = function(on) for position, status in pairs(TwentyYearsACookQuest.Fryclops.Catapult.CatapultUpdateMap) do local tile = Tile(position) local updated = false diff --git a/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/fryclops/axe_action.lua b/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/fryclops/axe_action.lua index 47de6ecbf54..39a07018f31 100644 --- a/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/fryclops/axe_action.lua +++ b/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/fryclops/axe_action.lua @@ -51,7 +51,7 @@ function fryclopsAxe.onUse(player, item, fromPosition, target, toPosition, isHot local creature = tile:getTopCreature() sendMagicEffectAroundFryclops() - TwentyYearsACookQuest.Fryclops.Catapult.UpdateCatapultItems(true) + TwentyYearsACookQuest.Fryclops.Catapult.UpdateCatapult(true) if creature and creature:getName():lower() == "fryclops" then creature:say("WAAAAAaaaaaaaaa...a...a...a...a...a............!", TALKTYPE_MONSTER_SAY) diff --git a/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/fryclops/fryclops_fight.lua b/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/fryclops/fryclops_fight.lua index fa1b65449aa..ee9d12a28a5 100644 --- a/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/fryclops/fryclops_fight.lua +++ b/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/fryclops/fryclops_fight.lua @@ -23,7 +23,7 @@ function fryclopsZoneEvent.afterLeave(zone, creature) player:removeIcon("fryclops") if #zone:getPlayers() == 0 then - TwentyYearsACookQuest.Fryclops.Catapult.UpdateCatapultItems(false) + TwentyYearsACookQuest.Fryclops.Catapult.UpdateCatapult(false) end return true From 52757194c8c904837021530d4182710c6ba33015 Mon Sep 17 00:00:00 2001 From: Pedro Henrique Alves Cruz Date: Wed, 5 Jun 2024 22:30:58 -0300 Subject: [PATCH 16/20] fix: quest bugs --- .../lib/quests/twenty_years_a_cook_quest.lua | 2 +- .../the_rest_of_ratha.lua | 5 ++- .../fryclops/fryclops_lever.lua | 4 +- .../omnious_trash_moveevents.lua | 37 ++++++++++++++----- .../the_rest_of_ratha/harp_action.lua | 5 +++ 5 files changed, 39 insertions(+), 14 deletions(-) diff --git a/data-otservbr-global/lib/quests/twenty_years_a_cook_quest.lua b/data-otservbr-global/lib/quests/twenty_years_a_cook_quest.lua index 9cee6c433ec..91d22df7d26 100644 --- a/data-otservbr-global/lib/quests/twenty_years_a_cook_quest.lua +++ b/data-otservbr-global/lib/quests/twenty_years_a_cook_quest.lua @@ -67,4 +67,4 @@ TwentyYearsACookQuest = { -- Initializing zones TwentyYearsACookQuest.TheRestOfRatha.MissionZone:addArea({ x = 33303, y = 31425, z = 15 }, { x = 33327, y = 31445, z = 15 }) TwentyYearsACookQuest.TheRestOfRatha.BossZone:addArea({ x = 33303, y = 31388, z = 15 }, { x = 33327, y = 31408, z = 15 }) -TwentyYearsACookQuest.Fryclops.BossZone:addArea({ x = 32342, y = 31589, z = 6 }, { x = 32368, y = 31611, z = 6 }) +TwentyYearsACookQuest.Fryclops.BossZone:addArea({ x = 32340, y = 31587, z = 6 }, { x = 32368, y = 31611, z = 6 }) \ No newline at end of file diff --git a/data-otservbr-global/monster/quests/twenty_years_a_cook_quest/the_rest_of_ratha.lua b/data-otservbr-global/monster/quests/twenty_years_a_cook_quest/the_rest_of_ratha.lua index 209cd8e265e..077c429229e 100644 --- a/data-otservbr-global/monster/quests/twenty_years_a_cook_quest/the_rest_of_ratha.lua +++ b/data-otservbr-global/monster/quests/twenty_years_a_cook_quest/the_rest_of_ratha.lua @@ -132,8 +132,9 @@ local function onConditionApplied(ratha, conditionsTicks) end local function updateQuestLogOnRathaFound(rathaPosition) - for i, player in pairs(Game.getSpectators(rathaPosition, false, true, 0, 1, 0, 1)) do - if player:getStorageValue(Storage.Quest.U13_30.TwentyYearsACook.QuestLine) == 2 then + for i, player in pairs(Game.getSpectators(rathaPosition, false, true, 1, 1, 1, 1)) do + local playerStorage = player:getStorageValue(Storage.Quest.U13_30.TwentyYearsACook.QuestLine) + if playerStorage == 2 then player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have found the friend of the Draccoon or what's left of him, You should tell the Draccoon about it!") player:setStorageValue(Storage.Quest.U13_30.TwentyYearsACook.QuestLine, 3) end diff --git a/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/fryclops/fryclops_lever.lua b/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/fryclops/fryclops_lever.lua index d30ec3c8050..5181d369085 100644 --- a/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/fryclops/fryclops_lever.lua +++ b/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/fryclops/fryclops_lever.lua @@ -13,8 +13,8 @@ local config = { { pos = Position(32369, 31602, 7), teleport = Position(32362, 31602, 6), effect = CONST_ME_TELEPORT }, }, specPos = { - from = Position(32341, 31589, 6), - to = Position(32368, 21611, 6), + from = Position(32340, 31587, 7), + to = Position(32368, 31611, 6), }, monsters = { { name = "Locked Door", pos = Position(32357, 31600, 6) }, diff --git a/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/omnious_trash_moveevents.lua b/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/omnious_trash_moveevents.lua index e43155865a0..5ee8737e6ec 100644 --- a/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/omnious_trash_moveevents.lua +++ b/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/omnious_trash_moveevents.lua @@ -1,24 +1,34 @@ local positions = { + [Position(33117, 31672, 7)] = { + toPosition = Position(33327, 31481, 15), + storageValue = 10, + }, [Position(32367, 31596, 7)] = { - toPosition = Position(32301, 31697, 8), + toPosition = Position(32299, 31698, 8), storageValue = 8, }, [Position(32301, 31697, 8)] = { toPosition = Position(32368, 31598, 7), storageValue = 8, + boss = "Fryclops" + }, + [Position(32297, 31706, 8)] = { + toPosition = Position(32246, 31834, 7), + storageValue = 8, }, [Position(32246, 31832, 7)] = { toPosition = Position(32298, 31704, 8), storageValue = 8, }, - [Position(32591, 31936, 5)] = { - toPosition = Position(32587, 31937, 5), - storageValue = 4, - }, [Position(32591, 31936, 5)] = { toPosition = Position(33319, 31443, 15), storageValue = 2, }, + [Position(32591, 31936, 5)] = { + toPosition = Position(32587, 31937, 5), + storageValue = 4, + boss = "The Rest of Ratha" + }, [Position(32974, 32110, 7)] = { toPosition = Position(32973, 32087, 8), storageValue = 1, @@ -34,22 +44,31 @@ local omniousTrashCan = MoveEvent() function omniousTrashCan.onStepIn(creature, item, position, fromPosition) local player = creature:getPlayer() if not player then - return + return false end playerStorage = player:getStorageValue(Storage.Quest.U13_30.TwentyYearsACook.QuestLine) or -1 + hasBossCooldown = false for position, data in pairs(positions) do - if position == player:getPosition() and playerStorage >= data.storageValue and player:getLevel() >= 250 then + logger.warn(data.storageValue) + if position == player:getPosition() and playerStorage >= data.storageValue then + if data.boss and creature:getBossCooldown(data.boss) > os.time() then + hasBossCooldown = true + break + end fromPosition:sendMagicEffect(CONST_ME_POFF) player:teleportTo(data.toPosition) player:getPosition():sendMagicEffect(CONST_ME_POFF) - return + return true end end - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You are not ready for this yet") + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, hasBossCooldown and "You need to wait to challenge again." or "You are not ready for this yet") + player:teleportTo(fromPosition, true) + + return true end local addedPositions = {} diff --git a/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/the_rest_of_ratha/harp_action.lua b/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/the_rest_of_ratha/harp_action.lua index 22cc131674e..f178b3c0ecc 100644 --- a/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/the_rest_of_ratha/harp_action.lua +++ b/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/the_rest_of_ratha/harp_action.lua @@ -1,6 +1,11 @@ local harp = Action() function harp.onUse(player, item, fromPosition, target, toPosition, isHotkey) + + if not TwentyYearsACookQuest.TheRestOfRatha.BossZone:isInZone(fromPosition) then + return true + end + local icon = player:getIcon("the-rest-of-ratha") if icon.count <= 0 then player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You are out of inspiration to play.") From 791e1133c54f35c62be0804e4fde058b7b688726 Mon Sep 17 00:00:00 2001 From: Pedro Henrique Alves Cruz Date: Wed, 5 Jun 2024 22:31:20 -0300 Subject: [PATCH 17/20] feat: The Draccon transcripts --- data-otservbr-global/npc/the_draccoon.lua | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/data-otservbr-global/npc/the_draccoon.lua b/data-otservbr-global/npc/the_draccoon.lua index fa01df11ba4..1354651fa0f 100644 --- a/data-otservbr-global/npc/the_draccoon.lua +++ b/data-otservbr-global/npc/the_draccoon.lua @@ -118,7 +118,29 @@ local function creatureSayCallback(npc, creature, type, message) npcHandler:say("But well, as he is still around... to some capacity at least, I am sure we are able to communicate with him. Just travel to his apartment again, I'll send one of my buddies to your assistance. ...", npc, creature, 2000) player:setStorageValue(Storage.Quest.U13_30.TwentyYearsACook.QuestLine, 4) elseif mission == 5 then + npcHandler:say("Execellent, the vial with Ratha's essence arrived just minutes ago via our friends from the postman guild...", npc, creature) + npcHandler:say("Even better, I managed to get my paws on a potion of spirit talking, it's just over there in the potion rack. Sadly it only allows humans to talk with human spirits...", npc, creature, 2000) + npcHandler:say("But luckily for us, you ARE a human after all! So grab that potion and just drink it! Then we will start to have a conversation with Ratha!", npc, creature, 2000) + player:setStorageValue(Storage.Quest.U13_30.TwentyYearsACook.QuestLine, 6) elseif mission == 7 then + npcHandler:say("Well I hope you and Ratha get along well. Fret net! I will find a way to extract Ratha From you... sooner or later that is! ...", npc, creature) + npcHandler:say("Now we have other things to care for, though! The master cook of Nimmersatt and cruel taskmaster for all to us cooks in Nimmersatt's service was a cyclops of immense power and immensely bad taste. ...", npc, creature, 2000) + npcHandler:say("His answer to anything cooking related was 'fry it!'. So he became known only as ...", npc, creature, 2000) + npcHandler:say("THE FRYCLOPS! ...", npc, creature, 2000) + npcHandler:say("His skin became nearly impenetrable by constantly being burnt by frying oil. I learned he got a special reward for his service to Nimmersatt. ...", npc, creature, 2000) + npcHandler:say("A strange machine that is able to retrieve items from places anywhere in the world! We will conquer this item and also punish the evil fryclops! ...", npc, creature, 2000) + npcHandler:say("According to my pal and guild mate in the fools guild, Bozo, the despicable Fryclops now resides on a small island north of Carlin where he tries to sink ships at his leisure. ...", npc, creature, 2000) + npcHandler:say("I arranged for you a secret passage to his isle from the Ghostlands! Look there for an innocent looking trash can . A friend of mine will be waiting there with further directions.", npc, creature, 2000) + player:setStorageValue(Storage.Quest.U13_30.TwentyYearsACook.QuestLine, 8) + elseif mission == 9 then + npcHandler:say("We got hand on the machine in his cellar. ...", npc, creature) + npcHandler:say("My mates are stil trying to figure it out, yet one thing is clear, the stupid Fryclops used up all available charges and we need to refuel that thing! ...", npc, creature, 2000) + npcHandler:say("And I happen to know how to refuel this machine with ease! All we need is some infernal power crystals! ...", npc, creature, 2000) + npcHandler:say("I'm sure its just a name, don't worry! My informants told me where to find some of those! ...", npc, creature, 2000) + npcHandler:say("All we have to do is to steal them from some unsuspecting demons, a piece of cake for you, I am sure! ...", npc, creature, 2000) + npcHandler:say("To make things even easier Cheaty will assist you with her magic and provid you with a disguise! So absolutely nothing could possibly go wrong! ...", npc, creature, 2000) + npcHandler:say("You will find the entrance at an abandoned tower in Edron, it's close to a stone circle.", npc, creature, 2000) + player:setStorageValue(Storage.Quest.U13_30.TwentyYearsACook.QuestLine, 10) end end return true From a9157f89521314a7dac366e1fc996dcfcd6a50e2 Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Thu, 6 Jun 2024 01:32:10 +0000 Subject: [PATCH 18/20] Lua code format - (Stylua) --- data-otservbr-global/lib/quests/twenty_years_a_cook_quest.lua | 2 +- .../twenty_years_a_cook_quest/omnious_trash_moveevents.lua | 4 ++-- .../the_rest_of_ratha/harp_action.lua | 1 - 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/data-otservbr-global/lib/quests/twenty_years_a_cook_quest.lua b/data-otservbr-global/lib/quests/twenty_years_a_cook_quest.lua index 91d22df7d26..320f64ac424 100644 --- a/data-otservbr-global/lib/quests/twenty_years_a_cook_quest.lua +++ b/data-otservbr-global/lib/quests/twenty_years_a_cook_quest.lua @@ -67,4 +67,4 @@ TwentyYearsACookQuest = { -- Initializing zones TwentyYearsACookQuest.TheRestOfRatha.MissionZone:addArea({ x = 33303, y = 31425, z = 15 }, { x = 33327, y = 31445, z = 15 }) TwentyYearsACookQuest.TheRestOfRatha.BossZone:addArea({ x = 33303, y = 31388, z = 15 }, { x = 33327, y = 31408, z = 15 }) -TwentyYearsACookQuest.Fryclops.BossZone:addArea({ x = 32340, y = 31587, z = 6 }, { x = 32368, y = 31611, z = 6 }) \ No newline at end of file +TwentyYearsACookQuest.Fryclops.BossZone:addArea({ x = 32340, y = 31587, z = 6 }, { x = 32368, y = 31611, z = 6 }) diff --git a/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/omnious_trash_moveevents.lua b/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/omnious_trash_moveevents.lua index 5ee8737e6ec..c56787aaedc 100644 --- a/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/omnious_trash_moveevents.lua +++ b/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/omnious_trash_moveevents.lua @@ -10,7 +10,7 @@ local positions = { [Position(32301, 31697, 8)] = { toPosition = Position(32368, 31598, 7), storageValue = 8, - boss = "Fryclops" + boss = "Fryclops", }, [Position(32297, 31706, 8)] = { toPosition = Position(32246, 31834, 7), @@ -27,7 +27,7 @@ local positions = { [Position(32591, 31936, 5)] = { toPosition = Position(32587, 31937, 5), storageValue = 4, - boss = "The Rest of Ratha" + boss = "The Rest of Ratha", }, [Position(32974, 32110, 7)] = { toPosition = Position(32973, 32087, 8), diff --git a/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/the_rest_of_ratha/harp_action.lua b/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/the_rest_of_ratha/harp_action.lua index f178b3c0ecc..22495ce2d3a 100644 --- a/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/the_rest_of_ratha/harp_action.lua +++ b/data-otservbr-global/scripts/quests/twenty_years_a_cook_quest/the_rest_of_ratha/harp_action.lua @@ -1,7 +1,6 @@ local harp = Action() function harp.onUse(player, item, fromPosition, target, toPosition, isHotkey) - if not TwentyYearsACookQuest.TheRestOfRatha.BossZone:isInZone(fromPosition) then return true end From b6f08e20e95e4f6e3494a84d9ab90d7a0309bb8f Mon Sep 17 00:00:00 2001 From: Pedro Henrique Alves Cruz Date: Tue, 17 Sep 2024 22:23:48 -0300 Subject: [PATCH 19/20] fix: update monster walkto to new listdir structure --- src/creatures/monsters/monster.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/creatures/monsters/monster.cpp b/src/creatures/monsters/monster.cpp index c310f5527a7..85a60ff28fc 100644 --- a/src/creatures/monsters/monster.cpp +++ b/src/creatures/monsters/monster.cpp @@ -1339,11 +1339,11 @@ void Monster::doRandomStep(Direction &nextDirection, bool &result) { void Monster::walkTo(const Position &walkToPosition) { randomStepping = false; isWalkingTo = true; - stdext::arraylist listDir(128); + std::vector listDir; if (!getPathTo(walkToPosition, listDir, 1, 1, true, true, 25)) { return; } - startAutoWalk(listDir.data(), true); + startAutoWalk(listDir, true); } void Monster::doWalkBack(uint32_t &flags, Direction &nextDirection, bool &result) { From d858d2237476caff52d0b5917cc91f4f34284581 Mon Sep 17 00:00:00 2001 From: Pedro Henrique Alves Cruz Date: Tue, 17 Sep 2024 22:36:18 -0300 Subject: [PATCH 20/20] feat: add quest npc and monster spawns --- data-otservbr-global/world/otservbr-monster.xml | 3 +++ data-otservbr-global/world/otservbr-npc.xml | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/data-otservbr-global/world/otservbr-monster.xml b/data-otservbr-global/world/otservbr-monster.xml index 80c5f5d4ff3..023992df9c9 100644 --- a/data-otservbr-global/world/otservbr-monster.xml +++ b/data-otservbr-global/world/otservbr-monster.xml @@ -180944,4 +180944,7 @@ + + + diff --git a/data-otservbr-global/world/otservbr-npc.xml b/data-otservbr-global/world/otservbr-npc.xml index 2b3f88a00d7..fba51eea399 100644 --- a/data-otservbr-global/world/otservbr-npc.xml +++ b/data-otservbr-global/world/otservbr-npc.xml @@ -2995,4 +2995,10 @@ + + + + + +