From 5cd27cda9e6878848bce0dd5d15f52c75bb7f9c1 Mon Sep 17 00:00:00 2001 From: Luan Luciano Date: Sun, 4 Feb 2024 07:29:13 -0300 Subject: [PATCH] improve: boss mechanics Foreshock (#2125) Using BossLever system. More clean core. --------- Co-authored-by: Eduardo Dantas --- data-otservbr-global/lib/core/storages.lua | 4 + .../heart_of_destruction/quake_lever.lua | 169 ++++-------------- .../aftershock_transform.lua | 55 +++--- .../foreshock_transform.lua | 56 +++--- .../heart_of_destruction/shocks_death.lua | 39 ++-- 5 files changed, 128 insertions(+), 195 deletions(-) diff --git a/data-otservbr-global/lib/core/storages.lua b/data-otservbr-global/lib/core/storages.lua index 741c481d865..11cd653f0ae 100644 --- a/data-otservbr-global/lib/core/storages.lua +++ b/data-otservbr-global/lib/core/storages.lua @@ -3067,6 +3067,10 @@ GlobalStorage = { HeartOfDestruction = { -- Reserved storage from 60172 - 60190 ChargedAnomaly = 60172, + ForeshockHealth = 60173, + AftershockHealth = 60174, + ForeshockStage = 60175, + AftershockStage = 60176, RuptureResonanceStage = 60177, RuptureResonanceActive = 60178, EradicatorWeak = 60178, diff --git a/data-otservbr-global/scripts/actions/quests/heart_of_destruction/quake_lever.lua b/data-otservbr-global/scripts/actions/quests/heart_of_destruction/quake_lever.lua index 2bce5d64ebb..0bf9034d93b 100644 --- a/data-otservbr-global/scripts/actions/quests/heart_of_destruction/quake_lever.lua +++ b/data-otservbr-global/scripts/actions/quests/heart_of_destruction/quake_lever.lua @@ -1,133 +1,42 @@ --- FUNCTIONS -local function doCheckArea() - local upConer = { x = 32197, y = 31236, z = 14 } -- upLeftCorner - local downConer = { x = 32220, y = 31260, z = 14 } -- downRightCorner - - for i = upConer.x, downConer.x do - for j = upConer.y, downConer.y do - for k = upConer.z, downConer.z do - local room = { x = i, y = j, z = k } - local tile = Tile(room) - if tile then - local creatures = tile:getCreatures() - if creatures and #creatures > 0 then - for _, creature in pairs(creatures) do - local player = Player(creature) - if player then - return true - end - end - end - end - end - end - end - return false -end - -local function clearArea() - local upConer = { x = 32197, y = 31236, z = 14 } -- upLeftCorner - local downConer = { x = 32220, y = 31260, z = 14 } -- downRightCorner - - for i = upConer.x, downConer.x do - for j = upConer.y, downConer.y do - for k = upConer.z, downConer.z do - local room = { x = i, y = j, z = k } - local tile = Tile(room) - if tile then - local creatures = tile:getCreatures() - if creatures and #creatures > 0 then - for _, creatureUid in pairs(creatures) do - local creature = Creature(creatureUid) - if creature then - if creature:isPlayer() then - creature:teleportTo({ x = 32230, y = 31358, z = 11 }) - elseif creature:isMonster() then - creature:remove() - end - end - end - end - end - end - end - end - stopEvent(areaQuake1) -end --- FUNCTIONS END - -local heartDestructionQuake = Action() -function heartDestructionQuake.onUse(player, item, fromPosition, itemEx, toPosition) - local config = { - playerPositions = { - Position(32182, 31244, 14), - Position(32182, 31245, 14), - Position(32182, 31246, 14), - Position(32182, 31247, 14), - Position(32182, 31248, 14), - }, - - newPos = { x = 32208, y = 31256, z = 14 }, - } - - local pushPos = { x = 32182, y = 31244, z = 14 } - - if item.actionid == 14329 then - if item.itemid == 8911 then - if player:getPosition().x == pushPos.x and player:getPosition().y == pushPos.y and player:getPosition().z == pushPos.z then - local storePlayers = {} - for i = 1, #config.playerPositions do - local tile = Tile(Position(config.playerPositions[i])) - if tile then - local playerTile = tile:getTopCreature() - if playerTile and playerTile:isPlayer() then - storePlayers[#storePlayers + 1] = playerTile - end - end - end - - if doCheckArea() == false then - clearArea() - - local players - - for i = 1, #storePlayers do - players = storePlayers[i] - config.playerPositions[i]:sendMagicEffect(CONST_ME_POFF) - players:teleportTo(config.newPos) - players:setBossCooldown("Realityquake", os.time() + configManager.getNumber(configKeys.BOSS_DEFAULT_TIME_TO_FIGHT_AGAIN)) - end - Position(config.newPos):sendMagicEffect(11) - - areaQuake1 = addEvent(clearArea, 15 * 60000) - - Game.createMonster("Spark of Destruction", { x = 32203, y = 31246, z = 14 }, false, true) - Game.createMonster("Spark of Destruction", { x = 32205, y = 31251, z = 14 }, false, true) - Game.createMonster("Spark of Destruction", { x = 32210, y = 31251, z = 14 }, false, true) - Game.createMonster("Spark of Destruction", { x = 32212, y = 31246, z = 14 }, false, true) - Game.createMonster("Foreshock", { x = 32208, y = 31248, z = 14 }, false, true) - - foreshockHealth = 105000 - aftershockHealth = 105000 - foreshockStage = 0 - aftershockStage = 0 - - local vortex = Tile({ x = 32199, y = 31248, z = 14 }):getItemById(23482) - if vortex then - vortex:transform(23483) - vortex:setActionId(14345) - end - else - player:sendTextMessage(19, "Someone is in the area.") - end - else - return true +local config = { + boss = { + name = "Foreshock", + position = Position(32208, 31248, 14), + }, + playerPositions = { + { pos = Position(32182, 31244, 14), teleport = Position(32208, 31256, 14), effect = CONST_ME_TELEPORT }, + { pos = Position(32182, 31245, 14), teleport = Position(32208, 31256, 14), effect = CONST_ME_TELEPORT }, + { pos = Position(32182, 31246, 14), teleport = Position(32208, 31256, 14), effect = CONST_ME_TELEPORT }, + { pos = Position(32182, 31247, 14), teleport = Position(32208, 31256, 14), effect = CONST_ME_TELEPORT }, + { pos = Position(32182, 31248, 14), teleport = Position(32208, 31256, 14), effect = CONST_ME_TELEPORT }, + }, + specPos = { + from = Position(32197, 31236, 14), + to = Position(32220, 31260, 14), + }, + monsters = { + { name = "Spark of Destruction", pos = Position(32203, 31246, 14) }, + { name = "Spark of Destruction", pos = Position(32205, 31251, 14) }, + { name = "Spark of Destruction", pos = Position(32210, 31251, 14) }, + { name = "Spark of Destruction", pos = Position(32212, 31246, 14) }, + }, + onUseExtra = function() + Game.setStorageValue(GlobalStorage.HeartOfDestruction.ForeshockHealth, 105000) + Game.setStorageValue(GlobalStorage.HeartOfDestruction.AftershockHealth, 105000) + Game.setStorageValue(GlobalStorage.HeartOfDestruction.ForeshockStage, -1) + Game.setStorageValue(GlobalStorage.HeartOfDestruction.AftershockStage, -1) + local tile = Tile(Position(32199, 31248, 14)) + if tile then + local vortex = tile:getItemById(23482) + if vortex then + vortex:transform(23483) + vortex:setActionId(14345) end end - item:transform(item.itemid == 8911 and 8912 or 8911) - end - return true -end + end, + exit = Position(32230, 31358, 11), +} -heartDestructionQuake:aid(14329) -heartDestructionQuake:register() +local lever = BossLever(config) +lever:aid(14329) +lever:register() diff --git a/data-otservbr-global/scripts/creaturescripts/quests/heart_of_destruction/aftershock_transform.lua b/data-otservbr-global/scripts/creaturescripts/quests/heart_of_destruction/aftershock_transform.lua index abe45bbf7e2..abb374f5710 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/heart_of_destruction/aftershock_transform.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/heart_of_destruction/aftershock_transform.lua @@ -1,35 +1,42 @@ +local sparkOfDestructionPositions = { + Position(32203, 31246, 14), + Position(32205, 31251, 14), + Position(32210, 31251, 14), + Position(32212, 31246, 14), +} + +local monsterTable = { + [80] = { fromStage = 0, toStage = 1 }, + [60] = { fromStage = 1, toStage = 2 }, + [40] = { fromStage = 2, toStage = 3 }, + [20] = { fromStage = 3, toStage = 4 }, + [10] = { fromStage = 4, toStage = 5 }, +} + local aftershockTransform = CreatureEvent("AftershockTransform") + function aftershockTransform.onThink(creature) - if not creature:isMonster() then + if not creature or not creature:isMonster() then return true end - local sparkOfDestructionPositions = { - { x = 32203, y = 31246, z = 14 }, - { x = 32205, y = 31251, z = 14 }, - { x = 32210, y = 31251, z = 14 }, - { x = 32212, y = 31246, z = 14 }, - } - - local monsterTable = { - [80] = { fromStage = 0, toStage = 1 }, - [60] = { fromStage = 1, toStage = 2 }, - [40] = { fromStage = 2, toStage = 3 }, - [20] = { fromStage = 3, toStage = 4 }, - [10] = { fromStage = 4, toStage = 5 }, - } + local hpPercent = (creature:getHealth() / creature:getMaxHealth()) * 100 + Game.setStorageValue(GlobalStorage.HeartOfDestruction.AftershockHealth, creature:getHealth()) + local aftershockStage = Game.getStorageValue(GlobalStorage.HeartOfDestruction.AftershockStage) > 0 and Game.getStorageValue(GlobalStorage.HeartOfDestruction.AftershockStage) or 0 for index, value in pairs(monsterTable) do - local hp = (creature:getHealth() / creature:getMaxHealth()) * 100 - aftershockHealth = creature:getHealth() - if hp <= index and aftershockStage == value.fromStage then - creature:remove() - for i = 1, #sparkOfDestructionPositions do - Game.createMonster("spark of destruction", sparkOfDestructionPositions[i], false, true) + if hpPercent <= index and aftershockStage == value.fromStage then + local monster = Game.createMonster("Foreshock", Position(32208, 31248, 14), false, true) + if monster then + creature:remove() + for i = 1, #sparkOfDestructionPositions do + Game.createMonster("Spark of Destruction", sparkOfDestructionPositions[i], false, true) + end + local foreshockHealth = Game.getStorageValue(GlobalStorage.HeartOfDestruction.ForeshockHealth) > 0 and Game.getStorageValue(GlobalStorage.HeartOfDestruction.ForeshockHealth) or 0 + monster:addHealth(-monster:getHealth() + foreshockHealth, COMBAT_PHYSICALDAMAGE) + Game.setStorageValue(GlobalStorage.HeartOfDestruction.AftershockStage, value.toStage) + return true end - local monster = Game.createMonster("foreshock", { x = 32208, y = 31248, z = 14 }, false, true) - monster:addHealth(-monster:getHealth() + foreshockHealth, COMBAT_PHYSICALDAMAGE) - aftershockStage = value.toStage end end return true diff --git a/data-otservbr-global/scripts/creaturescripts/quests/heart_of_destruction/foreshock_transform.lua b/data-otservbr-global/scripts/creaturescripts/quests/heart_of_destruction/foreshock_transform.lua index 6e15d2596e6..d812a46dcb9 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/heart_of_destruction/foreshock_transform.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/heart_of_destruction/foreshock_transform.lua @@ -1,37 +1,45 @@ +local sparkOfDestructionPositions = { + Position(32203, 31246, 14), + Position(32205, 31251, 14), + Position(32210, 31251, 14), + Position(32212, 31246, 14), +} + +local monsterTable = { + [80] = { fromStage = 0, toStage = 1 }, + [60] = { fromStage = 1, toStage = 2 }, + [40] = { fromStage = 2, toStage = 3 }, + [20] = { fromStage = 3, toStage = 4 }, + [10] = { fromStage = 4, toStage = 5 }, +} + local foreshockTransform = CreatureEvent("ForeshockTransform") + function foreshockTransform.onThink(creature) - if not creature:isMonster() then + if not creature or not creature:isMonster() then return true end - local sparkOfDestructionPositions = { - { x = 32203, y = 31246, z = 14 }, - { x = 32205, y = 31251, z = 14 }, - { x = 32210, y = 31251, z = 14 }, - { x = 32212, y = 31246, z = 14 }, - } - - local monsterTable = { - [80] = { fromStage = 0, toStage = 1 }, - [60] = { fromStage = 1, toStage = 2 }, - [40] = { fromStage = 2, toStage = 3 }, - [20] = { fromStage = 3, toStage = 4 }, - [10] = { fromStage = 4, toStage = 5 }, - } + local hpPercent = (creature:getHealth() / creature:getMaxHealth()) * 100 + Game.setStorageValue(GlobalStorage.HeartOfDestruction.ForeshockHealth, creature:getHealth()) + local foreshockStage = Game.getStorageValue(GlobalStorage.HeartOfDestruction.ForeshockStage) > 0 and Game.getStorageValue(GlobalStorage.HeartOfDestruction.ForeshockStage) or 0 for index, value in pairs(monsterTable) do - local hp = (creature:getHealth() / creature:getMaxHealth()) * 100 - foreshockHealth = creature:getHealth() - if hp <= index and foreshockStage == value.fromStage then - creature:remove() - for i = 1, #sparkOfDestructionPositions do - Game.createMonster("spark of destruction", sparkOfDestructionPositions[i], false, true) + if hpPercent <= index and foreshockStage == value.fromStage then + local monster = Game.createMonster("Aftershock", Position(32208, 31248, 14), false, true) + if monster then + creature:remove() + for i = 1, #sparkOfDestructionPositions do + Game.createMonster("Spark of Destruction", sparkOfDestructionPositions[i], false, true) + end + local aftershockHealth = Game.getStorageValue(GlobalStorage.HeartOfDestruction.AftershockHealth) > 0 and Game.getStorageValue(GlobalStorage.HeartOfDestruction.AftershockHealth) or 0 + monster:addHealth(-monster:getHealth() + aftershockHealth, COMBAT_PHYSICALDAMAGE) + Game.setStorageValue(GlobalStorage.HeartOfDestruction.ForeshockStage, value.toStage) + return true end - local monster = Game.createMonster("aftershock", { x = 32208, y = 31248, z = 14 }, false, true) - monster:addHealth(-monster:getHealth() + aftershockHealth, COMBAT_PHYSICALDAMAGE) - foreshockStage = value.toStage end end return true end + foreshockTransform:register() diff --git a/data-otservbr-global/scripts/creaturescripts/quests/heart_of_destruction/shocks_death.lua b/data-otservbr-global/scripts/creaturescripts/quests/heart_of_destruction/shocks_death.lua index 400304c5912..7e60d7f3c85 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/heart_of_destruction/shocks_death.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/heart_of_destruction/shocks_death.lua @@ -1,27 +1,32 @@ +local function createSparksOfDestruction() + Game.createMonster("Spark Of Destruction", Position(32203, 31246, 14), false, true) + Game.createMonster("Spark Of Destruction", Position(32205, 31251, 14), false, true) + Game.createMonster("Spark Of Destruction", Position(32210, 31251, 14), false, true) + Game.createMonster("Spark Of Destruction", Position(32212, 31246, 14), false, true) +end + local shocksDeath = CreatureEvent("ShocksDeath") + function shocksDeath.onDeath(creature) if not creature or not creature:isMonster() then return true end - local name = creature:getName():lower() - if name == "foreshock" then - local monster = Game.createMonster("aftershock", { x = 32208, y = 31248, z = 14 }, false, true) - monster:addHealth(-monster:getHealth() + aftershockHealth, COMBAT_PHYSICALDAMAGE) - Game.createMonster("spark of destruction", { x = 32203, y = 31246, z = 14 }, false, true) - Game.createMonster("spark of destruction", { x = 32205, y = 31251, z = 14 }, false, true) - Game.createMonster("spark of destruction", { x = 32210, y = 31251, z = 14 }, false, true) - Game.createMonster("spark of destruction", { x = 32212, y = 31246, z = 14 }, false, true) - end - - if name == "aftershock" then - local pos = creature:getPosition() - local monster = Game.createMonster("realityquake", pos, false, true) - Game.createMonster("spark of destruction", { x = 32203, y = 31246, z = 14 }, false, true) - Game.createMonster("spark of destruction", { x = 32205, y = 31251, z = 14 }, false, true) - Game.createMonster("spark of destruction", { x = 32210, y = 31251, z = 14 }, false, true) - Game.createMonster("spark of destruction", { x = 32212, y = 31246, z = 14 }, false, true) + local creatureName = creature:getName():lower() + if creatureName == "foreshock" then + local monster = Game.createMonster("Aftershock", Position(32208, 31248, 14), false, true) + if monster then + local aftershockHealth = Game.getStorageValue(GlobalStorage.HeartOfDestruction.AftershockHealth) > 0 and Game.getStorageValue(GlobalStorage.HeartOfDestruction.AftershockHealth) or 0 + monster:addHealth(-monster:getHealth() + aftershockHealth, COMBAT_PHYSICALDAMAGE) + createSparksOfDestruction() + end + elseif creatureName == "aftershock" then + local monster = Game.createMonster("Realityquake", creature:getPosition(), false, true) + if monster then + createSparksOfDestruction() + end end return true end + shocksDeath:register()