Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

improve: boss mechanics Foreshock #2125

Merged
merged 10 commits into from
Feb 4, 2024
4 changes: 4 additions & 0 deletions data-otservbr-global/lib/core/storages.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
@@ -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()
Original file line number Diff line number Diff line change
@@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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()
Original file line number Diff line number Diff line change
@@ -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()
Loading