From 1528314384f268a9df1e27bb2c3828a1a503711c Mon Sep 17 00:00:00 2001 From: sebbesiren <35768829+sebbesiren@users.noreply.github.com> Date: Thu, 22 Feb 2024 12:57:23 +0100 Subject: [PATCH 1/2] feat: boss loot event (#2293) Allows you to setup boss loot event similar to experience, spawnrate and loot. See updated examples in events.xml --------- Co-authored-by: Sebastian Nobbelin Co-authored-by: GitHub Actions --- data/XML/events.xml | 4 ++-- data/global.lua | 1 + data/libs/functions/monstertype.lua | 4 ++++ data/scripts/creaturescripts/player/login.lua | 4 ++++ data/scripts/globalevents/server_initialization.lua | 9 +++++++-- src/game/scheduling/events_scheduler.cpp | 9 +++++++++ src/game/scheduling/events_scheduler.hpp | 9 +++++++++ src/lua/functions/events/events_scheduler_functions.cpp | 6 ++++++ src/lua/functions/events/events_scheduler_functions.hpp | 2 ++ 9 files changed, 44 insertions(+), 4 deletions(-) diff --git a/data/XML/events.xml b/data/XML/events.xml index 982f21e3fcd..c4f483b21ef 100644 --- a/data/XML/events.xml +++ b/data/XML/events.xml @@ -1,13 +1,13 @@ - +
- +
diff --git a/data/global.lua b/data/global.lua index 1491987ffad..8e601fa422f 100644 --- a/data/global.lua +++ b/data/global.lua @@ -59,6 +59,7 @@ GLOBAL_CHARM_SCAVENGE = 125 -- 25% more chance to get creature products from ski -- Event Schedule SCHEDULE_LOOT_RATE = 100 SCHEDULE_EXP_RATE = 100 +SCHEDULE_BOSS_LOOT_RATE = 100 SCHEDULE_SKILL_RATE = 100 SCHEDULE_SPAWN_RATE = 100 diff --git a/data/libs/functions/monstertype.lua b/data/libs/functions/monstertype.lua index bd86b38a439..168cab13109 100644 --- a/data/libs/functions/monstertype.lua +++ b/data/libs/functions/monstertype.lua @@ -10,6 +10,10 @@ function MonsterType:generateLootRoll(config, resultTable) local factor = config.factor or 1.0 local uniqueItems = {} + if self:isRewardBoss() then + factor = factor * SCHEDULE_BOSS_LOOT_RATE / 100 + end + local result = resultTable or {} for _, item in ipairs(monsterLoot) do local iType = ItemType(item.itemId) diff --git a/data/scripts/creaturescripts/player/login.lua b/data/scripts/creaturescripts/player/login.lua index 1c008af20d1..4a7ac9379d6 100644 --- a/data/scripts/creaturescripts/player/login.lua +++ b/data/scripts/creaturescripts/player/login.lua @@ -69,6 +69,10 @@ function playerLoginGlobal.onLogin(player) sendBoostMessage(player, "Loot Rate", SCHEDULE_LOOT_RATE > 100) end + if SCHEDULE_BOSS_LOOT_RATE ~= 100 then + sendBoostMessage(player, "Boss Loot Rate", SCHEDULE_BOSS_LOOT_RATE > 100) + end + if SCHEDULE_SKILL_RATE ~= 100 then sendBoostMessage(player, "Skill Rate", SCHEDULE_SKILL_RATE > 100) end diff --git a/data/scripts/globalevents/server_initialization.lua b/data/scripts/globalevents/server_initialization.lua index 8b0ff53ceb8..97478582fc8 100644 --- a/data/scripts/globalevents/server_initialization.lua +++ b/data/scripts/globalevents/server_initialization.lua @@ -105,6 +105,11 @@ local function updateEventRates() SCHEDULE_LOOT_RATE = lootRate end + local bossLootRate = EventsScheduler.getEventSBossLoot() + if bossLootRate ~= 100 then + SCHEDULE_BOSS_LOOT_RATE = bossLootRate + end + local expRate = EventsScheduler.getEventSExp() if expRate ~= 100 then SCHEDULE_EXP_RATE = expRate @@ -121,8 +126,8 @@ local function updateEventRates() end -- Log information if any of the rates are not 100% - if expRate ~= 100 or lootRate ~= 100 or spawnRate ~= 100 or skillRate ~= 100 then - logger.info("[Events] Exp: {}%, loot: {}%, Spawn: {}%, Skill: {}%", expRate, lootRate, spawnRate, skillRate) + if expRate ~= 100 or lootRate ~= 100 or spawnRate ~= 100 or skillRate ~= 100 or bossLootRate ~= 100 then + logger.info("[Events] Exp: {}%, Loot: {}%, Spawn: {}%, Skill: {}%, Boss loot: {}%", expRate, lootRate, spawnRate, skillRate, bossLootRate) end end diff --git a/src/game/scheduling/events_scheduler.cpp b/src/game/scheduling/events_scheduler.cpp index 70f662f6176..c57f84b667c 100644 --- a/src/game/scheduling/events_scheduler.cpp +++ b/src/game/scheduling/events_scheduler.cpp @@ -74,6 +74,12 @@ bool EventsScheduler::loadScheduleEventFromXml() { g_eventsScheduler().setLootSchedule(lootrate); } + if (ingameNode.attribute("bosslootrate")) { + uint16_t bosslootrate = static_cast(ingameNode.attribute("bosslootrate").as_uint()); + currentEventRates.bosslootrate = bosslootrate; + g_eventsScheduler().setBossLootSchedule(bosslootrate); + } + if (ingameNode.attribute("spawnrate")) { uint16_t spawnrate = static_cast(ingameNode.attribute("spawnrate").as_uint()); currentEventRates.spawnrate = spawnrate; @@ -96,6 +102,9 @@ bool EventsScheduler::loadScheduleEventFromXml() { if (rates.lootrate != 100 && currentEventRates.lootrate != 100 && rates.lootrate == currentEventRates.lootrate) { modifiedRates.emplace_back("lootrate"); } + if (rates.bosslootrate != 100 && currentEventRates.bosslootrate != 100 && rates.bosslootrate == currentEventRates.bosslootrate) { + modifiedRates.emplace_back("bosslootrate"); + } if (rates.spawnrate != 100 && currentEventRates.spawnrate != 100 && rates.spawnrate == currentEventRates.spawnrate) { modifiedRates.emplace_back("spawnrate"); } diff --git a/src/game/scheduling/events_scheduler.hpp b/src/game/scheduling/events_scheduler.hpp index ae80afdda23..6c8233d8b0e 100644 --- a/src/game/scheduling/events_scheduler.hpp +++ b/src/game/scheduling/events_scheduler.hpp @@ -21,6 +21,7 @@ struct EventScheduler { struct EventRates { uint16_t exprate = 100; uint32_t lootrate = 100; + uint32_t bosslootrate = 100; uint32_t spawnrate = 100; uint16_t skillrate = 100; }; @@ -55,6 +56,13 @@ class EventsScheduler { lootSchedule = (lootSchedule * lootrate) / 100; } + uint32_t getBossLootSchedule() const { + return bossLootSchedule; + } + void setBossLootSchedule(uint32_t bosslootrate) { + bossLootSchedule = (bossLootSchedule * bosslootrate) / 100; + } + uint32_t getSpawnMonsterSchedule() const { return spawnMonsterSchedule; } @@ -73,6 +81,7 @@ class EventsScheduler { // Event schedule uint16_t expSchedule = 100; uint32_t lootSchedule = 100; + uint32_t bossLootSchedule = 100; uint16_t skillSchedule = 100; uint32_t spawnMonsterSchedule = 100; diff --git a/src/lua/functions/events/events_scheduler_functions.cpp b/src/lua/functions/events/events_scheduler_functions.cpp index 2dd8a8a7d85..e26794e218a 100644 --- a/src/lua/functions/events/events_scheduler_functions.cpp +++ b/src/lua/functions/events/events_scheduler_functions.cpp @@ -18,6 +18,12 @@ int EventsSchedulerFunctions::luaEventsSchedulergetEventSLoot(lua_State* L) { return 1; } +int EventsSchedulerFunctions::luaEventsSchedulergetEventSBossLoot(lua_State* L) { + // EventsScheduler.getEventSLoot + lua_pushnumber(L, g_eventsScheduler().getBossLootSchedule()); + return 1; +} + int EventsSchedulerFunctions::luaEventsSchedulergetEventSSkill(lua_State* L) { // EventsScheduler.getEventSSkill lua_pushnumber(L, g_eventsScheduler().getSkillSchedule()); diff --git a/src/lua/functions/events/events_scheduler_functions.hpp b/src/lua/functions/events/events_scheduler_functions.hpp index 2c57bd26717..bedbf16b4a1 100644 --- a/src/lua/functions/events/events_scheduler_functions.hpp +++ b/src/lua/functions/events/events_scheduler_functions.hpp @@ -17,6 +17,7 @@ class EventsSchedulerFunctions final : private LuaScriptInterface { registerTable(L, "EventsScheduler"); registerMethod(L, "EventsScheduler", "getEventSLoot", EventsSchedulerFunctions::luaEventsSchedulergetEventSLoot); + registerMethod(L, "EventsScheduler", "getEventSBossLoot", EventsSchedulerFunctions::luaEventsSchedulergetEventSBossLoot); registerMethod(L, "EventsScheduler", "getEventSSkill", EventsSchedulerFunctions::luaEventsSchedulergetEventSSkill); registerMethod(L, "EventsScheduler", "getEventSExp", EventsSchedulerFunctions::luaEventsSchedulergetEventSExp); registerMethod(L, "EventsScheduler", "getSpawnMonsterSchedule", EventsSchedulerFunctions::luaEventsSchedulergetSpawnMonsterSchedule); @@ -24,6 +25,7 @@ class EventsSchedulerFunctions final : private LuaScriptInterface { private: static int luaEventsSchedulergetEventSLoot(lua_State* L); + static int luaEventsSchedulergetEventSBossLoot(lua_State* L); static int luaEventsSchedulergetEventSSkill(lua_State* L); static int luaEventsSchedulergetEventSExp(lua_State* L); static int luaEventsSchedulergetSpawnMonsterSchedule(lua_State* L); From 4a86b3f3755ce75498537552f2755918898c7786 Mon Sep 17 00:00:00 2001 From: Marco Date: Thu, 22 Feb 2024 09:03:10 -0300 Subject: [PATCH 2/2] improvement: hireling foods and wall mirror (#2283) --- .../scripts/actions/other/hireling_food.lua | 87 ------------------- data/scripts/actions/items/hireling_foods.lua | 69 +++++++++++++++ data/scripts/actions/objects/wall_mirror.lua | 10 +-- 3 files changed, 74 insertions(+), 92 deletions(-) delete mode 100644 data-otservbr-global/scripts/actions/other/hireling_food.lua create mode 100644 data/scripts/actions/items/hireling_foods.lua diff --git a/data-otservbr-global/scripts/actions/other/hireling_food.lua b/data-otservbr-global/scripts/actions/other/hireling_food.lua deleted file mode 100644 index a7734b9d310..00000000000 --- a/data-otservbr-global/scripts/actions/other/hireling_food.lua +++ /dev/null @@ -1,87 +0,0 @@ -local config = { - storage = 19042, --use empty storage - exhaust = 600, --Exhaust is in seconds 600 equals 10min -} - -local chilliConCarniphila = Condition(CONDITION_HASTE) -chilliConCarniphila:setParameter(CONDITION_PARAM_TICKS, 60 * 60 * 1000) -chilliConCarniphila:setParameter(CONDITION_PARAM_SPEED, 80) - -local svargrondSalmonFilet = Condition(CONDITION_ATTRIBUTES) -svargrondSalmonFilet:setParameter(CONDITION_PARAM_TICKS, 60 * 60 * 1000) -svargrondSalmonFilet:setParameter(CONDITION_PARAM_SKILL_FISHING, 30) - -local tropicalMarinatedTiger = Condition(CONDITION_ATTRIBUTES) -tropicalMarinatedTiger:setParameter(CONDITION_PARAM_TICKS, 60 * 60 * 1000) -tropicalMarinatedTiger:setParameter(CONDITION_PARAM_STAT_MAGICPOINTS, 3) - -local delicatessenSalad = Condition(CONDITION_ATTRIBUTES) -delicatessenSalad:setParameter(CONDITION_PARAM_TICKS, 60 * 60 * 1000) -delicatessenSalad:setParameter(CONDITION_PARAM_SKILL_MELEE, 3) - -local roastedWyvernWings = Condition(CONDITION_ATTRIBUTES) -roastedWyvernWings:setParameter(CONDITION_PARAM_TICKS, 60 * 60 * 1000) -roastedWyvernWings:setParameter(CONDITION_PARAM_SKILL_SHIELD, 7) - -local carrotPie = Condition(CONDITION_ATTRIBUTES) -carrotPie:setParameter(CONDITION_PARAM_TICKS, 60 * 60 * 1000) -carrotPie:setParameter(CONDITION_PARAM_SKILL_DISTANCE, 7) - -local hirelingFood = Action() - -function hirelingFood.onUse(player, item, frompos, item2, topos) - local cid = player:getId() - if player:getStorageValue(config.storage) <= os.time() then - if item.itemid == 29408 then - player:say("Chomp.", TALKTYPE_MONSTER_SAY) - Creature(cid):addCondition(roastedWyvernWings) - item:remove(1) - player:setStorageValue(config.storage, os.time() + config.exhaust) - elseif item.itemid == 29409 then - player:say("Yummm.", TALKTYPE_MONSTER_SAY) - Creature(cid):addCondition(carrotPie) - item:remove(1) - player:setStorageValue(config.storage, os.time() + config.exhaust) - elseif item.itemid == 29410 then - player:say("Munch.", TALKTYPE_MONSTER_SAY) - Creature(cid):addCondition(tropicalMarinatedTiger) - item:remove(1) - player:setStorageValue(config.storage, os.time() + config.exhaust) - elseif item.itemid == 29411 then - player:say("Munch.", TALKTYPE_MONSTER_SAY) - Creature(cid):addCondition(delicatessenSalad) - item:remove(1) - player:setStorageValue(config.storage, os.time() + config.exhaust) - elseif item.itemid == 29412 then - player:say("Yummm.", TALKTYPE_MONSTER_SAY) - Creature(cid):addCondition(chilliConCarniphila) - item:remove(1) - player:setStorageValue(config.storage, os.time() + config.exhaust) - elseif item.itemid == 29413 then - player:say("Mmmmm.", TALKTYPE_MONSTER_SAY) - Creature(cid):addCondition(svargrondSalmonFilet) - item:remove(1) - player:setStorageValue(config.storage, os.time() + config.exhaust) - elseif item.itemid == 29414 then - Creature(cid):addHealth(getCreatureMaxHealth(cid) * 0.3) - player:say("Munch.", TALKTYPE_MONSTER_SAY) - item:remove(1) - player:setStorageValue(config.storage, os.time() + config.exhaust) - elseif item.itemid == 29415 then - Creature(cid):addMana(Creature(cid):getMaxMana() * 0.3) - player:say("Chomp.", TALKTYPE_MONSTER_SAY) - item:remove(1) - player:setStorageValue(config.storage, os.time() + config.exhaust) - elseif item.itemid == 29416 then - player:say("Blurg.", TALKTYPE_MONSTER_SAY) - item:remove(1) - player:setStorageValue(config.storage, os.time() + config.exhaust) - end - else - player:sendCancelMessage("You're still too full to eat any gourmet dishes for a while.") - end - return true -end - -hirelingFood:id(29408, 29409, 29410, 29411, 29412, 29413, 29414, 29415, 29416) -hirelingFood:register() diff --git a/data/scripts/actions/items/hireling_foods.lua b/data/scripts/actions/items/hireling_foods.lua new file mode 100644 index 00000000000..6b86c8d242a --- /dev/null +++ b/data/scripts/actions/items/hireling_foods.lua @@ -0,0 +1,69 @@ +local hasteCondition = Condition(CONDITION_HASTE) +hasteCondition:setParameter(CONDITION_PARAM_TICKS, 60 * 60 * 1000) +hasteCondition:setParameter(CONDITION_PARAM_SPEED, 80) + +local fishingCondition = Condition(CONDITION_ATTRIBUTES) +fishingCondition:setParameter(CONDITION_PARAM_TICKS, 60 * 60 * 1000) +fishingCondition:setParameter(CONDITION_PARAM_SKILL_FISHING, 30) + +local magicPointsCondition = Condition(CONDITION_ATTRIBUTES) +magicPointsCondition:setParameter(CONDITION_PARAM_TICKS, 60 * 60 * 1000) +magicPointsCondition:setParameter(CONDITION_PARAM_STAT_MAGICPOINTS, 3) + +local meleeCondition = Condition(CONDITION_ATTRIBUTES) +meleeCondition:setParameter(CONDITION_PARAM_TICKS, 60 * 60 * 1000) +meleeCondition:setParameter(CONDITION_PARAM_SKILL_MELEE, 3) + +local shieldCondition = Condition(CONDITION_ATTRIBUTES) +shieldCondition:setParameter(CONDITION_PARAM_TICKS, 60 * 60 * 1000) +shieldCondition:setParameter(CONDITION_PARAM_SKILL_SHIELD, 7) + +local distanceCondition = Condition(CONDITION_ATTRIBUTES) +distanceCondition:setParameter(CONDITION_PARAM_TICKS, 60 * 60 * 1000) +distanceCondition:setParameter(CONDITION_PARAM_SKILL_DISTANCE, 7) + +local gourmetDishes = { + [29408] = { condition = shieldCondition, message = "Chomp." }, + [29409] = { condition = distanceCondition, message = "Yummm." }, + [29410] = { condition = magicPointsCondition, message = "Munch." }, + [29411] = { condition = meleeCondition, message = "Munch." }, + [29412] = { condition = hasteCondition, message = "Yummm." }, + [29413] = { condition = fishingCondition, message = "Mmmmm." }, + [29414] = { healing = true, message = "Munch." }, + [29415] = { manaRestore = true, message = "Chomp." }, + [29416] = { message = "Blurg." }, +} + +local hirelingFoods = Action() + +function hirelingFoods.onUse(player, item, fromPosition, target, toPosition, isHotkey) + local dish = gourmetDishes[item.itemid] + if not dish then + return true + end + + if player:hasExhaustion("hireling-foods-cooldown") then + player:sendCancelMessage("You're still too full to eat any gourmet dishes for a while.") + return true + end + + if dish.condition then + player:addCondition(dish.condition) + elseif dish.healing then + player:addHealth(player:getMaxHealth() * 0.3) + elseif dish.manaRestore then + player:addMana(player:getMaxMana() * 0.3) + end + + player:say(dish.message, TALKTYPE_MONSTER_SAY) + player:setExhaustion("hireling-foods-cooldown", 10 * 60) + + item:remove(1) + return true +end + +for index, value in pairs(gourmetDishes) do + hirelingFoods:id(index) +end + +hirelingFoods:register() diff --git a/data/scripts/actions/objects/wall_mirror.lua b/data/scripts/actions/objects/wall_mirror.lua index 314753546a6..d76a39218a3 100644 --- a/data/scripts/actions/objects/wall_mirror.lua +++ b/data/scripts/actions/objects/wall_mirror.lua @@ -15,13 +15,13 @@ local setting = { local wallMirror = Action() function wallMirror.onUse(player, item, fromPosition, target, toPosition, isHotkey) - local hasExhaustion = player:kv():get("delay-wall-mirror") or 0 - if hasExhaustion > os.time() then + if player:hasExhaustion("delay-wall-mirror") then player:say("Don't be so vain about your appearance.", TALKTYPE_MONSTER_SAY) - else - player:kv():set("delay-wall-mirror", os.time() + 20 * 60 * 60) - player:say(setting[math.random(1, #setting)], TALKTYPE_MONSTER_SAY) + return true end + + player:say(setting[math.random(1, #setting)], TALKTYPE_MONSTER_SAY) + player:setExhaustion("delay-wall-mirror", 20 * 60 * 60) return true end