Skip to content

Commit

Permalink
fix: soulpit fight
Browse files Browse the repository at this point in the history
  • Loading branch information
phacUFPE committed Dec 3, 2024
1 parent 44fdece commit 3647df2
Show file tree
Hide file tree
Showing 11 changed files with 219 additions and 184 deletions.
1 change: 1 addition & 0 deletions data-otservbr-global/lib/others/load.lua
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
dofile(DATA_DIRECTORY .. "/lib/others/dawnport.lua")
dofile(DATA_DIRECTORY .. "/lib/others/soulpit.lua")
73 changes: 73 additions & 0 deletions data-otservbr-global/lib/others/soulpit.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
SoulPit = {
encounter = nil,
soulCores = Game.getSoulCoreItems(),
requiredLevel = 8,
playerPositions = {
{ pos = Position(32371, 31155, 8), teleport = Position(32373, 31138, 8), effect = CONST_ME_TELEPORT },
{ pos = Position(32371, 31156, 8), teleport = Position(32373, 31138, 8), effect = CONST_ME_TELEPORT },
{ pos = Position(32371, 31157, 8), teleport = Position(32373, 31138, 8), effect = CONST_ME_TELEPORT },
{ pos = Position(32371, 31158, 8), teleport = Position(32373, 31138, 8), effect = CONST_ME_TELEPORT },
{ pos = Position(32371, 31159, 8), teleport = Position(32373, 31138, 8), effect = CONST_ME_TELEPORT },
},
waves = {
[1] = {
stacks = {
[1] = 6,
[40] = 1
},
},
[2] = {
stacks = {
[1] = 4,
[5] = 3,
},
},
[3] = {
stacks = {
[1] = 5,
[15] = 2,
},
},
[4] = {
stacks = {
[1] = 3,
[5] = 3,
[40] = 1,
},
},
},
effects = {
[1] = CONST_ME_TELEPORT,
[5] = CONST_ME_ORANGETELEPORT,
[15] = CONST_ME_REDTELEPORT,
[40] = CONST_ME_PURPLETELEPORT,
},
possibleAbilities = {
"overpowerSoulPit",
"enrageSoulPit",
"opressorSoulPit",
},
bossAbilities = {
["overpowerSoulPit"] = {
player = true,
monster = false,
},
["enrageSoulPit"] = {
player = false,
monster = true,
},
["opressorSoulPit"] = {
player = false,
monster = true,
},
},
timeToKick = 3 * 1000, -- 3 seconds
checkMonstersDelay = 4.5 * 1000, -- 4.5 seconds | The check delay should never be less than the timeToSpawnMonsters.
timeToSpawnMonsters = 4 * 1000, -- 4 seconds
totalMonsters = 7,
bossPosition = Position(32372, 31135, 8),
exit = Position(32371, 31164, 8),
zone = Zone("soulpit"),
}

SoulPit.zone:addArea(Position(32365, 31134, 8), Position(32382, 31152, 8))
3 changes: 3 additions & 0 deletions data-otservbr-global/monster/humanoids/orc_warlord.lua
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,9 @@ monster.loot = {
monster.attacks = {
{ name = "melee", interval = 2000, chance = 100, minDamage = 0, maxDamage = -250 },
{ name = "combat", interval = 2000, chance = 20, type = COMBAT_PHYSICALDAMAGE, minDamage = 0, maxDamage = -200, range = 7, shootEffect = CONST_ANI_THROWINGSTAR, target = false },
{ name = "soulpit opressor", interval = 2000, chance = 25, minDamage = 0, maxDamage = 0 },
{ name = "soulpit powerless", interval = 2000, chance = 30, minDamage = 0, maxDamage = 0 },
{ name = "soulpit intensehex", interval = 2000, chance = 15, minDamage = 0, maxDamage = 0 },
}

monster.defenses = {
Expand Down
220 changes: 63 additions & 157 deletions data-otservbr-global/scripts/actions/soulpit/soulpit_fight.lua
Original file line number Diff line number Diff line change
@@ -1,114 +1,24 @@
local config = {
soulCores = Game.getSoulCoreItems(),
requiredLevel = 8,
playerPositions = {
{ pos = Position(32371, 31155, 8), teleport = Position(32373, 31138, 8), effect = CONST_ME_TELEPORT },
{ pos = Position(32371, 31156, 8), teleport = Position(32373, 31138, 8), effect = CONST_ME_TELEPORT },
{ pos = Position(32371, 31157, 8), teleport = Position(32373, 31138, 8), effect = CONST_ME_TELEPORT },
{ pos = Position(32371, 31158, 8), teleport = Position(32373, 31138, 8), effect = CONST_ME_TELEPORT },
{ pos = Position(32371, 31159, 8), teleport = Position(32373, 31138, 8), effect = CONST_ME_TELEPORT },
},
waves = {
[1] = {
stacks = {
[1] = 7,
},
},
[2] = {
stacks = {
[1] = 4,
[5] = 3,
},
},
[3] = {
stacks = {
[1] = 5,
[15] = 2,
},
},
[4] = {
stacks = {
[1] = 3,
[5] = 3,
[40] = 1,
},
},
},
effects = {
[1] = CONST_ME_TELEPORT,
[5] = CONST_ME_ORANGETELEPORT,
[15] = CONST_ME_REDTELEPORT,
[40] = CONST_ME_PURPLETELEPORT,
},
bossAbilitiesIndexes = {},
bossAbilities = {
["enrage"] = {
monsterEvents = {
"enrageSoulPit",
},
},
["opressor"] = {
spells = {
{ name = "soulpit opressor", interval = 2000, chance = 25, minDamage = 0, maxDamage = 0 },
{ name = "soulpit powerless", interval = 2000, chance = 30, minDamage = 0, maxDamage = 0 },
{ name = "soulpit hexer", interval = 2000, chance = 15, minDamage = 0, maxDamage = 0 },
},
},
["overpower"] = {
playerEvents = {
"overpowerSoulPit"
},
},
},
checkMonstersDelay = 4.5 * 1000, -- 4.5 seconds | The check delay should never be less than the timeToSpawnMonsters.
timeToSpawnMonsters = 4 * 1000, -- 4 seconds
totalMonsters = 7,
bossPosition = Position(32372, 31135, 8),
exit = Position(32371, 31164, 8),
zone = Zone("soulpit"),
}

for name, _ in pairs(config.bossAbilities) do
table.insert(config.bossAbilitiesIndexes, name)
logger.warn(name)
end

config.zone:addArea(Position(32365, 31134, 8), Position(32382, 31152, 8))

local enrage = CreatureEvent("enrageSoulPit")
function enrage.onHealthChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType)
if not creature or not creature:isMonster() then
return true
local zoneEvent = ZoneEvent(SoulPit.zone)
function zoneEvent.afterLeave(zone, creature)
local player = creature:getPlayer()
if not player then
return false
end

local healthPercentage = creature:getHealth() / creature:getMaxHealth()

if healthPercentage >= 0.5 and healthPercentage <= 0.7 then
primaryDamage = primaryDamage * 0.9 -- 10% damage reduction
secondaryDamage = secondaryDamage * 0.9 -- 10% damage reduction
elseif healthPercentage >= 0.3 and healthPercentage < 0.5 then
primaryDamage = primaryDamage * 0.75 -- 25% damage reduction
secondaryDamage = secondaryDamage * 0.75 -- 25% damage reduction
elseif healthPercentage > 0 and healthPercentage < 0.3 then
primaryDamage = primaryDamage * 0.6 -- 40% damage reduction
secondaryDamage = secondaryDamage * 0.6 -- 40% damage reduction
if table.empty(zone:getPlayers()) then
if SoulPit.encounter then
SoulPit.encounter:reset()
SoulPit.encounter = nil
end
end

return primaryDamage, primaryType, secondaryDamage, secondaryType
end
enrage:register()

local overpower = CreatureEvent("overpowerSoulPit")
function overpower.onHealthChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType)
if attacker:getForgeStack() == 40 then
primaryDamage = primaryDamage * 1.1
secondaryDamage = secondaryDamage * 1.1
creature:getPosition():sendMagicEffect(CONST_ME_CRITICAL_DAMAGE)
for abilityName, abilityInfo in pairs(SoulPit.bossAbilities) do
if abilityInfo.player then
player:unregisterEvent(abilityName)
end
end

return primaryDamage, primaryType, secondaryDamage, secondaryType
end
overpower:register()
zoneEvent:register()

local soulPitAction = Action()
function soulPitAction.onUse(player, item, fromPosition, target, toPosition, isHotkey)
Expand All @@ -117,7 +27,7 @@ function soulPitAction.onUse(player, item, fromPosition, target, toPosition, isH
end

local isParticipant = false
for _, v in ipairs(config.playerPositions) do
for _, v in ipairs(SoulPit.playerPositions) do
if Position(v.pos) == player:getPosition() then
isParticipant = true
end
Expand All @@ -128,17 +38,22 @@ function soulPitAction.onUse(player, item, fromPosition, target, toPosition, isH
end

local lever = Lever()
lever:setPositions(config.playerPositions)
lever:setPositions(SoulPit.playerPositions)
lever:setCondition(function(creature)
if not creature or not creature:isPlayer() then
return true
end

if not table.empty(SoulPit.zone:getPlayers()) then
local message = "Someone is fighting in the arena!"
creature:sendTextMessage(MESSAGE_EVENT_ADVANCE, message)
return false
end

local isAccountNormal = creature:getAccountType() < ACCOUNT_TYPE_GAMEMASTER
if isAccountNormal and creature:getLevel() < config.requiredLevel then
local message = "All players need to be level " .. config.requiredLevel .. " or higher."
if isAccountNormal and creature:getLevel() < SoulPit.requiredLevel then
local message = string.format("All players need to be level %s or higher.", SoulPit.requiredLevel)
creature:sendTextMessage(MESSAGE_EVENT_ADVANCE, message)
player:sendTextMessage(MESSAGE_EVENT_ADVANCE, message)
return false
end

Expand All @@ -154,83 +69,74 @@ function soulPitAction.onUse(player, item, fromPosition, target, toPosition, isH

logger.warn("monster name: " .. monsterName)

config.zone:removeMonsters()
SoulPit.zone:removeMonsters()

if SoulPit.encounter ~= nil then
SoulPit.encounter:reset()
end

local encounter = Encounter("Soulpit", {
zone = config.zone,
zone = SoulPit.zone,
})

SoulPit.encounter = encounter

local function waveStart()
for stack, amount in pairs(config.waves[encounter.currentStage].stacks) do
for stack, amount in pairs(SoulPit.waves[encounter.currentStage].stacks) do
logger.warn("stack: " .. stack)
logger.warn("amount: " .. amount)
for i = 1, amount do
local position = stack ~= 40 and config.zone:randomPosition() or config.bossPosition
for i = 1, config.timeToSpawnMonsters / 1000 do
local position = stack ~= 40 and SoulPit.zone:randomPosition() or SoulPit.bossPosition
for i = 1, SoulPit.timeToSpawnMonsters / 1000 do
encounter:addEvent(function(position)
position:sendMagicEffect(config.effects[stack])
position:sendMagicEffect(SoulPit.effects[stack])
end, i * 1000, position)
end

encounter:addEvent(function(name, stack, position)
local monster = Game.createMonster(name, position)
local randomAbility = SoulPit.possibleAbilities[math.random(1, #SoulPit.possibleAbilities)]
local chosenBossAbility = SoulPit.bossAbilities[randomAbility]

encounter:addEvent(function(name, stack, position, bossAbilityName, bossAbility)
local monster = Game.createSoulPitMonster(name, position, stack)
if not monster then
return false
end
monster:setForgeStack(stack)
local icon = stack <= 15 and CreatureIconModifications_ReducedHealth or CreatureIconModifications_ReducedHealthExclamation
monster:removeIcon("forge")
monster:setIcon("soulpit", CreatureIconCategory_Modifications, icon, stack <= 15 and stack or 0)
monster:setDropLoot(false)
if stack == 40 then
local monsterType = monster:getType()
local randomAbility = bossAbilitiesIndexes[math.random(#bossAbilitiesIndexes)]
logger.warn("the random ability chosen was: " .. randomAbility)
for _, ability in pairs(config.bossAbilities[randomAbility]) do
if ability.spells then
for _, spell in pairs(ability.spells) do
monsterType:addAttack(readSpell(spell, monsterType))
end
end
if ability.monsterEvents then
for _, name in pairs(ability.monsterEvents) do
monster:registerEvent(name)
end
end
if ability.playerEvents then
for _, name in pairs(ability.playerEvents) do
for _, players in pairs(config.zone:getPlayers()) do
player:registerEvent(name)
end
end
end
logger.warn("ability name: {}", bossAbilityName)
if bossAbility.monster then
monster:registerEvent(bossAbilityName)
end
if bossAbility.player then
player:registerEvent(bossAbilityName)
end
end
end, config.timeToSpawnMonsters, monsterName, stack, position)
end, SoulPit.timeToSpawnMonsters, monsterName, stack, position, randomAbility, chosenBossAbility)
end
end
end

for i = 1, #config.waves do
for i = 1, #SoulPit.waves do
encounter
:addStage({
start = waveStart,
})
:autoAdvance({ delay = config.checkMonstersDelay, monstersKilled = true })
:autoAdvance({ delay = SoulPit.checkMonstersDelay, monstersKilled = true })
end

function encounter:onReset(position)
for _, player in pairs(config.zone:getPlayers()) do
SoulPit.zone:removeMonsters()

for _, player in pairs(SoulPit.zone:getPlayers()) do
player:sendTextMessage(MESSAGE_EVENT_ADVANCE, string.format("You have defeated the core of the %s soul and unlocked its animus mastery!", monsterName))
player:teleportTo(config.exit)
for abilityName, abilities in pairs(config.bossAbilities) do
if abilities.playerEvents then
for _, eventName in pairs(abilities.playerEvents) do
player:registerEvent(eventName)
end
end
end
-- Add the monster animus mastery for the player.
end

addEvent(function()
SoulPit.encounter = nil
for _, player in pairs(SoulPit.zone:getPlayers()) do
player:teleportTo(SoulPit.exit)
end
end, SoulPit.timeToKick)
end

encounter:start()
Expand All @@ -239,7 +145,7 @@ function soulPitAction.onUse(player, item, fromPosition, target, toPosition, isH
return true
end

for _, itemType in pairs(config.soulCores) do
for _, itemType in pairs(SoulPit.soulCores) do
soulPitAction:id(itemType:getId())
end
soulPitAction:register()
Loading

0 comments on commit 3647df2

Please sign in to comment.