From bd3596a68232dc77f91d9d12b36afa82d70acea4 Mon Sep 17 00:00:00 2001
From: Eduardo Dantas <eduardo.dantas@hotmail.com.br>
Date: Wed, 10 Apr 2024 17:18:04 -0300
Subject: [PATCH 01/60] feat: full soul war quest

---
 .../quests/soul_war/aspect_of_power.lua       |   25 +-
 ...nia.lua => goshnar's_megalomania_blue.lua} |   80 +-
 .../soul_war/goshnar's_megalomania_green.lua  |  160 ++
 .../soul_war/goshnar's_megalomania_purple.lua |  132 ++
 .../quests/soul_war/goshnars_cruelty.lua      |   19 +-
 .../quests/soul_war/goshnars_greed.lua        |   40 +-
 .../quests/soul_war/goshnars_hatred.lua       |   17 +-
 .../quests/soul_war/goshnars_malice.lua       |   17 +-
 .../quests/soul_war/goshnars_spite.lua        |    7 +-
 .../monster/quests/soul_war/greedbeast.lua    |   98 ++
 .../monster/quests/soul_war/mirror_image.lua  |   40 +
 .../normal_monsters}/bony_sea_devil.lua       |    8 +
 .../normal_monsters}/brachiodemon.lua         |    8 +
 .../normal_monsters}/branchy_crawler.lua      |    8 +
 .../ashes_of_burning_hatred.lua               |   89 ++
 .../blaze_of_burning_hatred.lua               |   89 ++
 .../flame_of_burning_hatred.lua               |   89 ++
 .../spark_of_burning_hatred.lua               |   89 ++
 .../burning_hatred/symbol_of_hatred.lua       |   84 ++
 .../normal_monsters}/capricious_phantom.lua   |    4 +
 .../normal_monsters}/distorted_phantom.lua    |    4 +
 .../normal_monsters}/druid's_apparition.lua   |    4 +
 .../furious_crater/a_greedy_eye.lua           |   93 ++
 .../furious_crater}/cloak_of_terror.lua       |    9 +
 .../furious_crater}/courage_leech.lua         |    4 +
 .../furious_crater/poor_soul.lua              |  119 ++
 .../furious_crater}/vibrant_phantom.lua       |    4 +
 .../{ => normal_monsters}/hateful_soul.lua    |    2 +-
 .../normal_monsters}/infernal_demon.lua       |    4 +
 .../normal_monsters}/infernal_phantom.lua     |    4 +
 .../normal_monsters}/knight's_apparition.lua  |    4 +
 .../soul_war/normal_monsters}/many_faces.lua  |    8 +
 .../greater_splinter_of_madness.lua           |  107 ++
 .../lesser_splinter_of_madness.lua            |  107 ++
 .../mighty_splinter_of_madness.lua            |  113 ++
 .../megalomania_room/necromantic_focus.lua    |   82 +
 .../normal_monsters}/mould_phantom.lua        |    4 +
 .../normal_monsters}/paladin's_apparition.lua |    4 +
 .../normal_monsters}/rotten_golem.lua         |    4 +
 .../sorcerer's_apparition.lua                 |    4 +
 .../normal_monsters}/turbulent_elemental.lua  |    4 +
 .../monster/quests/soul_war/powerful_soul.lua |  115 ++
 .../monster/quests/soul_war/soul_cage.lua     |   71 +
 .../monster/quests/soul_war/soul_sphere.lua   |  109 ++
 .../monster/quests/soul_war/soulsnatcher.lua  |  115 ++
 .../quests/soul_war/spiteful_spitter.lua      |    4 +
 .../monster/quests/soul_war/strong_soul.lua   |  106 ++
 .../monster/quests/soul_war/weak_soul.lua     |  106 ++
 .../monster/quests/soul_war/weeping_soul.lua  |   91 ++
 .../monster/undeads/hazardous_phantom.lua     |    4 +
 data-otservbr-global/npc/flickering_soul.lua  |  195 +++
 .../actions/bosses_levers/goshnar_cruelty.lua |   23 -
 .../actions/bosses_levers/goshnar_greed.lua   |   23 -
 .../actions/bosses_levers/goshnar_hatred.lua  |   23 -
 .../actions/bosses_levers/goshnar_malice.lua  |   23 -
 .../bosses_levers/goshnar_megalomania.lua     |   23 -
 .../actions/bosses_levers/goshnar_spite.lua   |   23 -
 .../actions/quests/soul_war/bosses_killed.lua |   24 -
 .../quests/soul_war/portal_megalomania.lua    |   38 -
 .../quests/soul_war/reward_soul_war.lua       |   89 --
 .../quests/soul_war/soulwar_entrances.lua     |   63 -
 .../scripts/lib/quests/soul-war.lua           | 1343 +++++++++++++++++
 .../soul_war/action-reward_soul_war.lua       |   60 +
 .../eventcallback_on_combat_taint.lua         |  127 ++
 ...ntcallback_on_drop_loot_bag_you_desire.lua |   16 +
 .../globalevent-ebb_and_flow_change_maps.lua  |  132 ++
 .../soul_war/moveevent-soul_war_entrances.lua |  151 ++
 .../moveevent-teleport_entrance_reward.lua}   |    7 +-
 .../quests/soul_war/soul_war_mechanics.lua    | 1081 +++++++++++++
 .../quests/soul_war/spell-eye_beam.lua        |   38 +
 .../soul_war/spell-fire_beam_cruelty.lua      |   61 +
 .../soul_war/spell-fire_beam_megalomania.lua  |   54 +
 .../soul_war/spell-megalomania_blue.lua       |   58 +
 .../quests/soul_war/spell-soulsnatcher.lua    |   58 +
 .../iron_servant_transformation.lua           |    2 +-
 .../world/otservbr-monster.xml                |  965 ++++++------
 data-otservbr-global/world/otservbr-npc.xml   |    3 +
 .../ebb_and_flow/ebb-flow-empty-zones.xml     |    2 +
 .../soul_war/ebb_and_flow/ebb-flow-empty.otbm |  Bin 0 -> 129535 bytes
 .../ebb_and_flow/ebb-flow-inundate-zones.xml  |    2 +
 .../{inundate.otbm => ebb-flow-inundate.otbm} |  Bin 325937 -> 323339 bytes
 .../quest/soul_war/ebb_and_flow/empty.otbm    |  Bin 13957 -> 0 bytes
 data/items/items.xml                          |   52 +-
 data/libs/functions/bosslever.lua             |    7 +-
 data/libs/functions/creature.lua              |    2 +-
 data/libs/functions/revscriptsys.lua          |    8 +
 data/libs/systems/zones.lua                   |   10 +-
 data/scripts/actions/items/cobra_flask.lua    |    2 +-
 data/scripts/eventcallbacks/README.md         |   17 +-
 .../creature/on_area_combat.lua               |    2 +-
 .../eventcallbacks/creature/on_hear.lua       |    2 +-
 .../eventcallbacks/monster/on_spawn.lua       |    2 +-
 .../monster/ondroploot__base.lua              |    4 +-
 .../monster/ondroploot_boosted.lua            |    2 +-
 .../monster/ondroploot_gem_atelier.lua        |    2 +-
 .../monster/ondroploot_hazard.lua             |    2 +-
 .../monster/ondroploot_prey.lua               |    2 +-
 .../monster/ondroploot_wealth_duplex.lua      |    2 +-
 .../monster/postdroploot_analyzer.lua         |    2 +-
 .../eventcallbacks/party/on_disband.lua       |    2 +-
 .../eventcallbacks/player/on_browse_field.lua |    2 +-
 .../scripts/eventcallbacks/player/on_look.lua |    2 +-
 .../eventcallbacks/player/on_look_in_shop.lua |    2 +-
 .../player/on_look_in_trade.lua               |    2 +-
 .../eventcallbacks/player/on_remove_count.lua |    2 +-
 .../player/on_request_quest_line.lua          |    2 +-
 .../player/on_request_quest_log.lua           |    2 +-
 .../eventcallbacks/player/on_rotate_item.lua  |    2 +-
 .../player/on_storage_update.lua              |    2 +-
 .../eventcallbacks/player/on_trade_accept.lua |    2 +-
 data/scripts/lib/register_lever_tables.lua    |    4 +-
 data/scripts/lib/register_monster_type.lua    |    4 +-
 data/scripts/lib/register_spells.lua          |    6 +
 data/scripts/spells/healing/heal_malice.lua   |   29 +
 .../talkactions/gm/distance_effect.lua        |   37 +
 src/creatures/appearance/outfit/outfit.hpp    |   10 +
 src/creatures/combat/combat.cpp               |   10 +
 src/creatures/creature.cpp                    |    2 +-
 src/creatures/creature.hpp                    |   10 +-
 src/creatures/creatures_definitions.hpp       |   14 +-
 src/creatures/monsters/monster.cpp            |  103 +-
 src/creatures/monsters/monster.hpp            |   35 +-
 src/creatures/monsters/monsters.cpp           |   37 +-
 src/creatures/monsters/monsters.hpp           |    2 +
 .../monsters/spawns/spawn_monster.cpp         |    1 +
 src/creatures/players/grouping/party.cpp      |    2 +-
 src/creatures/players/player.cpp              |   16 +-
 src/creatures/players/player.hpp              |   10 +-
 src/game/bank/bank.cpp                        |    4 +
 src/game/game.cpp                             |    8 +-
 src/game/zones/zone.cpp                       |    5 +
 src/io/functions/iologindata_load_player.cpp  |    7 +-
 src/io/io_bosstiary.cpp                       |    1 +
 src/io/iomap.cpp                              |    2 +-
 src/lua/callbacks/callbacks_definitions.hpp   |    3 +
 src/lua/callbacks/event_callback.cpp          |  105 +-
 src/lua/callbacks/event_callback.hpp          |   22 +-
 src/lua/callbacks/events_callbacks.cpp        |   28 +-
 src/lua/callbacks/events_callbacks.hpp        |   23 +-
 src/lua/creature/creatureevent.cpp            |    6 +-
 src/lua/creature/creatureevent.hpp            |    2 +-
 src/lua/creature/events.cpp                   |    2 +-
 .../functions/core/game/bank_functions.cpp    |    1 +
 .../functions/core/game/game_functions.cpp    |    1 +
 src/lua/functions/core/game/lua_enums.cpp     |    8 +-
 .../functions/core/game/zone_functions.cpp    |    2 +-
 .../creatures/creature_functions.cpp          |    2 +-
 .../creatures/monster/monster_functions.cpp   |   86 +-
 .../creatures/monster/monster_functions.hpp   |   13 +
 .../monster/monster_type_functions.cpp        |    4 +-
 .../monster/monster_type_functions.hpp        |    2 +
 .../creatures/player/player_functions.cpp     |   30 +-
 .../creatures/player/player_functions.hpp     |    4 +
 .../events/event_callback_functions.cpp       |   14 +-
 src/map/map.cpp                               |    9 +-
 src/map/mapcache.cpp                          |   16 +-
 156 files changed, 7053 insertions(+), 1050 deletions(-)
 rename data-otservbr-global/monster/quests/soul_war/{goshnars_megalomania.lua => goshnar's_megalomania_blue.lua} (63%)
 create mode 100644 data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_green.lua
 create mode 100644 data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_purple.lua
 create mode 100644 data-otservbr-global/monster/quests/soul_war/greedbeast.lua
 rename data-otservbr-global/monster/{undeads => quests/soul_war/normal_monsters}/bony_sea_devil.lua (96%)
 rename data-otservbr-global/monster/{demons => quests/soul_war/normal_monsters}/brachiodemon.lua (96%)
 rename data-otservbr-global/monster/{plants => quests/soul_war/normal_monsters}/branchy_crawler.lua (95%)
 create mode 100644 data-otservbr-global/monster/quests/soul_war/normal_monsters/burning_hatred/ashes_of_burning_hatred.lua
 create mode 100644 data-otservbr-global/monster/quests/soul_war/normal_monsters/burning_hatred/blaze_of_burning_hatred.lua
 create mode 100644 data-otservbr-global/monster/quests/soul_war/normal_monsters/burning_hatred/flame_of_burning_hatred.lua
 create mode 100644 data-otservbr-global/monster/quests/soul_war/normal_monsters/burning_hatred/spark_of_burning_hatred.lua
 create mode 100644 data-otservbr-global/monster/quests/soul_war/normal_monsters/burning_hatred/symbol_of_hatred.lua
 rename data-otservbr-global/monster/{undeads => quests/soul_war/normal_monsters}/capricious_phantom.lua (98%)
 rename data-otservbr-global/monster/{undeads => quests/soul_war/normal_monsters}/distorted_phantom.lua (98%)
 rename data-otservbr-global/monster/{undeads => quests/soul_war/normal_monsters}/druid's_apparition.lua (98%)
 create mode 100644 data-otservbr-global/monster/quests/soul_war/normal_monsters/furious_crater/a_greedy_eye.lua
 rename data-otservbr-global/monster/{plants => quests/soul_war/normal_monsters/furious_crater}/cloak_of_terror.lua (95%)
 rename data-otservbr-global/monster/{extra_dimensional => quests/soul_war/normal_monsters/furious_crater}/courage_leech.lua (98%)
 create mode 100644 data-otservbr-global/monster/quests/soul_war/normal_monsters/furious_crater/poor_soul.lua
 rename data-otservbr-global/monster/{undeads => quests/soul_war/normal_monsters/furious_crater}/vibrant_phantom.lua (98%)
 rename data-otservbr-global/monster/quests/soul_war/{ => normal_monsters}/hateful_soul.lua (99%)
 rename data-otservbr-global/monster/{demons => quests/soul_war/normal_monsters}/infernal_demon.lua (98%)
 rename data-otservbr-global/monster/{undeads => quests/soul_war/normal_monsters}/infernal_phantom.lua (98%)
 rename data-otservbr-global/monster/{undeads => quests/soul_war/normal_monsters}/knight's_apparition.lua (98%)
 rename data-otservbr-global/monster/{demons => quests/soul_war/normal_monsters}/many_faces.lua (96%)
 create mode 100644 data-otservbr-global/monster/quests/soul_war/normal_monsters/megalomania_room/greater_splinter_of_madness.lua
 create mode 100644 data-otservbr-global/monster/quests/soul_war/normal_monsters/megalomania_room/lesser_splinter_of_madness.lua
 create mode 100644 data-otservbr-global/monster/quests/soul_war/normal_monsters/megalomania_room/mighty_splinter_of_madness.lua
 create mode 100644 data-otservbr-global/monster/quests/soul_war/normal_monsters/megalomania_room/necromantic_focus.lua
 rename data-otservbr-global/monster/{undeads => quests/soul_war/normal_monsters}/mould_phantom.lua (98%)
 rename data-otservbr-global/monster/{undeads => quests/soul_war/normal_monsters}/paladin's_apparition.lua (98%)
 rename data-otservbr-global/monster/{constructs => quests/soul_war/normal_monsters}/rotten_golem.lua (98%)
 rename data-otservbr-global/monster/{undeads => quests/soul_war/normal_monsters}/sorcerer's_apparition.lua (98%)
 rename data-otservbr-global/monster/{elementals => quests/soul_war/normal_monsters}/turbulent_elemental.lua (98%)
 create mode 100644 data-otservbr-global/monster/quests/soul_war/powerful_soul.lua
 create mode 100644 data-otservbr-global/monster/quests/soul_war/soul_cage.lua
 create mode 100644 data-otservbr-global/monster/quests/soul_war/soul_sphere.lua
 create mode 100644 data-otservbr-global/monster/quests/soul_war/soulsnatcher.lua
 create mode 100644 data-otservbr-global/monster/quests/soul_war/strong_soul.lua
 create mode 100644 data-otservbr-global/monster/quests/soul_war/weak_soul.lua
 create mode 100644 data-otservbr-global/monster/quests/soul_war/weeping_soul.lua
 create mode 100644 data-otservbr-global/npc/flickering_soul.lua
 delete mode 100644 data-otservbr-global/scripts/actions/bosses_levers/goshnar_cruelty.lua
 delete mode 100644 data-otservbr-global/scripts/actions/bosses_levers/goshnar_greed.lua
 delete mode 100644 data-otservbr-global/scripts/actions/bosses_levers/goshnar_hatred.lua
 delete mode 100644 data-otservbr-global/scripts/actions/bosses_levers/goshnar_malice.lua
 delete mode 100644 data-otservbr-global/scripts/actions/bosses_levers/goshnar_megalomania.lua
 delete mode 100644 data-otservbr-global/scripts/actions/bosses_levers/goshnar_spite.lua
 delete mode 100644 data-otservbr-global/scripts/actions/quests/soul_war/bosses_killed.lua
 delete mode 100644 data-otservbr-global/scripts/actions/quests/soul_war/portal_megalomania.lua
 delete mode 100644 data-otservbr-global/scripts/actions/quests/soul_war/reward_soul_war.lua
 delete mode 100644 data-otservbr-global/scripts/actions/quests/soul_war/soulwar_entrances.lua
 create mode 100644 data-otservbr-global/scripts/lib/quests/soul-war.lua
 create mode 100644 data-otservbr-global/scripts/quests/soul_war/action-reward_soul_war.lua
 create mode 100644 data-otservbr-global/scripts/quests/soul_war/eventcallback_on_combat_taint.lua
 create mode 100644 data-otservbr-global/scripts/quests/soul_war/eventcallback_on_drop_loot_bag_you_desire.lua
 create mode 100644 data-otservbr-global/scripts/quests/soul_war/globalevent-ebb_and_flow_change_maps.lua
 create mode 100644 data-otservbr-global/scripts/quests/soul_war/moveevent-soul_war_entrances.lua
 rename data-otservbr-global/scripts/{actions/quests/soul_war/portal_reward_soulwar.lua => quests/soul_war/moveevent-teleport_entrance_reward.lua} (78%)
 create mode 100644 data-otservbr-global/scripts/quests/soul_war/soul_war_mechanics.lua
 create mode 100644 data-otservbr-global/scripts/quests/soul_war/spell-eye_beam.lua
 create mode 100644 data-otservbr-global/scripts/quests/soul_war/spell-fire_beam_cruelty.lua
 create mode 100644 data-otservbr-global/scripts/quests/soul_war/spell-fire_beam_megalomania.lua
 create mode 100644 data-otservbr-global/scripts/quests/soul_war/spell-megalomania_blue.lua
 create mode 100644 data-otservbr-global/scripts/quests/soul_war/spell-soulsnatcher.lua
 create mode 100644 data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-empty-zones.xml
 create mode 100644 data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-empty.otbm
 create mode 100644 data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-inundate-zones.xml
 rename data-otservbr-global/world/quest/soul_war/ebb_and_flow/{inundate.otbm => ebb-flow-inundate.otbm} (83%)
 delete mode 100644 data-otservbr-global/world/quest/soul_war/ebb_and_flow/empty.otbm
 create mode 100644 data/scripts/spells/healing/heal_malice.lua
 create mode 100644 data/scripts/talkactions/gm/distance_effect.lua

diff --git a/data-otservbr-global/monster/quests/soul_war/aspect_of_power.lua b/data-otservbr-global/monster/quests/soul_war/aspect_of_power.lua
index 8ff012c96ef..896cb520722 100644
--- a/data-otservbr-global/monster/quests/soul_war/aspect_of_power.lua
+++ b/data-otservbr-global/monster/quests/soul_war/aspect_of_power.lua
@@ -4,20 +4,20 @@ local monster = {}
 monster.description = "an aspect of power"
 monster.experience = 0
 monster.outfit = {
-	lookType = 1303,
+	lookType = 1306,
 	lookHead = 0,
 	lookBody = 0,
 	lookLegs = 0,
 	lookFeet = 0,
-	lookAddons = 1,
+	lookAddons = 0,
 	lookMount = 0,
 }
 
 monster.health = 25000
 monster.maxHealth = 25000
 monster.race = "undead"
-monster.corpse = 0
-monster.speed = 125
+monster.corpse = 33949
+monster.speed = 175
 monster.manaCost = 0
 
 monster.changeTarget = {
@@ -25,8 +25,14 @@ monster.changeTarget = {
 	chance = 8,
 }
 
+monster.events = {
+	"SoulWarAspectOfPowerDeath",
+}
+
 monster.strategiesTarget = {
 	nearest = 100,
+	health = 20,
+	damage = 30,
 }
 
 monster.flags = {
@@ -64,16 +70,15 @@ monster.attacks = {
 	{ name = "combat", interval = 1700, chance = 15, type = COMBAT_EARTHDAMAGE, minDamage = -400, maxDamage = -950, radius = 3, shootEffect = CONST_ANI_ENVENOMEDARROW, effect = CONST_ME_HITBYPOISON, target = true },
 	{ name = "combat", interval = 1700, chance = 25, type = COMBAT_ENERGYDAMAGE, minDamage = -300, maxDamage = -850, length = 4, spread = 0, effect = CONST_ME_ENERGYHIT, target = false },
 	{ name = "combat", interval = 1700, chance = 35, type = COMBAT_DEATHDAMAGE, minDamage = -700, maxDamage = -1550, radius = 3, effect = CONST_ME_MORTAREA, target = false },
-	{ name = "outfit", interval = 1000, chance = 5, radius = 8, effect = CONST_ME_LOSEENERGY, target = false, duration = 5000, outfitMonster = "goshnar's hatred" },
-	{ name = "outfit", interval = 1000, chance = 5, radius = 8, effect = CONST_ME_LOSEENERGY, target = false, duration = 5000, outfitMonster = "goshnar's greed" },
-	{ name = "outfit", interval = 1000, chance = 5, radius = 8, effect = CONST_ME_LOSEENERGY, target = false, duration = 5000, outfitMonster = "goshnar's malice" },
-	{ name = "outfit", interval = 1000, chance = 5, radius = 8, effect = CONST_ME_LOSEENERGY, target = false, duration = 5000, outfitMonster = "goshnar's spite" },
 }
 
 monster.defenses = {
 	defense = 40,
-	armor = 0,
-	--	mitigation = ???,
+	armor = 40,
+	{ name = "outfit", interval = 4000, chance = 30, target = false, duration = 4000, outfitMonster = "Goshnar's Malice" },
+	{ name = "outfit", interval = 4000, chance = 30, target = false, duration = 4000, outfitMonster = "Goshnar's Cruelty" },
+	{ name = "outfit", interval = 4000, chance = 30, target = false, duration = 4000, outfitMonster = "Goshnar's Hatred" },
+	{ name = "outfit", interval = 4000, chance = 30, target = false, duration = 4000, outfitMonster = "Goshnar's Spite" },
 }
 
 monster.elements = {
diff --git a/data-otservbr-global/monster/quests/soul_war/goshnars_megalomania.lua b/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_blue.lua
similarity index 63%
rename from data-otservbr-global/monster/quests/soul_war/goshnars_megalomania.lua
rename to data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_blue.lua
index 7346e628cfc..69bd51a6923 100644
--- a/data-otservbr-global/monster/quests/soul_war/goshnars_megalomania.lua
+++ b/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_blue.lua
@@ -1,44 +1,40 @@
-local mType = Game.createMonsterType("Goshnar's Megalomania")
+local mType = Game.createMonsterType("Goshnar's Megalomania Blue")
 local monster = {}
 
+monster.name = "Goshnar's Megalomania"
 monster.description = "Goshnar's Megalomania"
-monster.experience = 200000
+monster.experience = 3000000
 monster.outfit = {
-	lookType = 1308,
-	lookHead = 0,
-	lookBody = 0,
-	lookLegs = 0,
-	lookFeet = 0,
-	lookAddons = 0,
-	lookMount = 0,
+	lookType = 1337,
 }
 
-monster.events = {
-	"SoulwarsBossDeath",
-}
-
-monster.health = 500000
-monster.maxHealth = 500000
+monster.health = 620000
+monster.maxHealth = 620000
 monster.race = "undead"
 monster.corpse = 33889
-monster.speed = 165
+monster.speed = 0
 monster.manaCost = 0
-
-monster.changeTarget = {
-	interval = 2000,
-	chance = 10,
-}
+monster.maxSummons = 4
 
 monster.bosstiary = {
 	bossRaceId = 1969,
 	bossRace = RARITY_NEMESIS,
 }
 
+monster.changeTarget = {
+	interval = 4000,
+	chance = 10,
+}
+
 monster.strategiesTarget = {
-	nearest = 70,
+	nearest = 80,
 	health = 10,
 	damage = 10,
-	random = 10,
+}
+
+monster.events = {
+	"GoshnarsHatredBuff",
+	"MegalomaniaDeath",
 }
 
 monster.flags = {
@@ -51,7 +47,7 @@ monster.flags = {
 	illusionable = false,
 	canPushItems = true,
 	canPushCreatures = true,
-	staticAttackChance = 95,
+	staticAttackChance = 80,
 	targetDistance = 1,
 	runHealth = 0,
 	healthHidden = false,
@@ -67,14 +63,6 @@ monster.light = {
 	color = 0,
 }
 
-monster.summon = {
-	maxSummons = 4,
-	summons = {
-		{ name = "dreadful harvester", chance = 40, interval = 1000, count = 2 },
-		{ name = "aspect of power", chance = 50, interval = 1000, count = 2 },
-	},
-}
-
 monster.voices = {
 	interval = 5000,
 	chance = 10,
@@ -110,19 +98,14 @@ monster.loot = {
 }
 
 monster.attacks = {
-	{ name = "melee", interval = 2000, chance = 100, minDamage = 0, maxDamage = -8000 },
-	{ name = "combat", interval = 2000, chance = 30, type = COMBAT_PHYSICALDAMAGE, minDamage = -2950, maxDamage = -4400, range = 7, radius = 3, shootEffect = CONST_ANI_DEATH, effect = CONST_ME_MORTAREA, target = true },
-	{ name = "combat", interval = 2000, chance = 10, type = COMBAT_DEATHDAMAGE, minDamage = -3000, maxDamage = -5500, length = 8, spread = 0, effect = CONST_ME_INSECTS, target = false },
-	{ name = "singlecloudchain", interval = 6000, chance = 40, minDamage = -3300, maxDamage = -5500, range = 6, effect = CONST_ME_ENERGYHIT, target = true },
-	{ name = "combat", interval = 2000, chance = 10, type = COMBAT_DEATHDAMAGE, minDamage = -3300, maxDamage = -5200, length = 10, spread = 0, effect = CONST_ME_BLUE_GHOST, target = false },
+	{ name = "melee", interval = 2000, chance = 100, minDamage = -400, maxDamage = -2225 },
+	{ name = "megalomania blue", interval = 6000, chance = 100, target = true },
+	{ name = "combat", interval = 30000, chance = 100, type = COMBAT_LIFEDRAIN, minDamage = -1000, maxDamage = -1500, length = 8, radius = 5, spread = 0, effect = CONST_ME_PINK_ENERGY_SPARK, target = true },
 }
 
 monster.defenses = {
-	defense = 160,
-	armor = 160,
-	mitigation = 8.40,
-	{ name = "speed", interval = 1000, chance = 20, speedChange = 500, effect = CONST_ME_MAGIC_RED, target = false, duration = 10000 },
-	{ name = "combat", interval = 2000, chance = 25, type = COMBAT_HEALING, minDamage = 2250, maxDamage = 4250, effect = CONST_ME_MAGIC_BLUE, target = false },
+	defense = 55,
+	armor = 55,
 }
 
 monster.elements = {
@@ -145,18 +128,21 @@ monster.immunities = {
 	{ type = "bleed", condition = false },
 }
 
-mType.onThink = function(monster, interval) end
-
 mType.onAppear = function(monster, creature)
 	if monster:getType():isRewardBoss() then
 		monster:setReward(true)
 	end
 end
 
-mType.onDisappear = function(monster, creature) end
+local intervalBetweenExecutions = 10000
 
-mType.onMove = function(monster, creature, fromPosition, toPosition) end
+local zone = Zone.getByName("boss.goshnar's-megalomania-purple")
+local zonePositions = zone:getPositions()
 
-mType.onSay = function(monster, creature, type, message) end
+mType.onThink = function(monsterCallback, interval)
+	monsterCallback:onThinkGoshnarTormentCounter(interval, 36, intervalBetweenExecutions, SoulWarQuest.levers.goshnarsMegalomania.boss.position)
+	monsterCallback:onThinkMegalomaniaWhiteTiles(interval, zonePositions, 8000)
+	monsterCallback:goshnarsDefenseIncrease("cleansed-sanity-action")
+end
 
 mType:register(monster)
diff --git a/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_green.lua b/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_green.lua
new file mode 100644
index 00000000000..5c6170d3f92
--- /dev/null
+++ b/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_green.lua
@@ -0,0 +1,160 @@
+local mType = Game.createMonsterType("Goshnar's Megalomania Green")
+local monster = {}
+
+monster.name = "Goshnar's Megalomania"
+monster.description = "Goshnar's Megalomania"
+monster.experience = 3000000
+monster.outfit = {
+	lookType = 99,
+	lookHead = 95,
+	lookBody = 116,
+	lookLegs = 119,
+	lookFeet = 115,
+	lookAddons = 0,
+	lookMount = 0,
+}
+
+monster.bosstiary = {
+	bossRaceId = 1969,
+	bossRace = RARITY_NEMESIS,
+}
+
+monster.health = 620000
+monster.maxHealth = 620000
+monster.race = "undead"
+monster.corpse = 33889
+monster.speed = 250
+monster.manaCost = 0
+monster.maxSummons = 4
+
+monster.changeTarget = {
+	interval = 4000,
+	chance = 10,
+}
+
+monster.events = {
+	"GoshnarsHatredBuff",
+	"MegalomaniaDeath",
+}
+
+monster.strategiesTarget = {
+	nearest = 80,
+	health = 10,
+	damage = 10,
+}
+
+monster.flags = {
+	summonable = false,
+	attackable = true,
+	hostile = true,
+	convinceable = false,
+	pushable = false,
+	rewardBoss = true,
+	illusionable = false,
+	canPushItems = true,
+	canPushCreatures = true,
+	staticAttackChance = 80,
+	targetDistance = 1,
+	runHealth = 0,
+	healthHidden = false,
+	isBlockable = false,
+	canWalkOnEnergy = true,
+	canWalkOnFire = true,
+	canWalkOnPoison = true,
+	pet = false,
+}
+
+monster.light = {
+	level = 0,
+	color = 0,
+}
+
+monster.voices = {
+	interval = 5000,
+	chance = 10,
+}
+
+monster.loot = {
+	{ name = "crystal coin", chance = 55000, minCount = 70, maxCount = 75 },
+	{ id = 281, chance = 1150 }, -- giant shimmering pearl (green)
+	{ name = "giant sapphire", chance = 10000, maxCount = 1 },
+	{ name = "giant topaz", chance = 10000, maxCount = 1 },
+	{ name = "violet gem", chance = 6000, maxCount = 1 },
+	{ name = "blue gem", chance = 10000, maxCount = 3 },
+	{ id = 3039, chance = 10000, maxCount = 3 }, -- red gem
+	{ name = "green gem", chance = 10000, maxCount = 3 },
+	{ name = "yellow gem", chance = 10000, maxCount = 3 },
+	{ name = "white gem", chance = 6000, maxCount = 3 },
+	{ name = "dragon figurine", chance = 10000, maxCount = 1 },
+	{ name = "bullseye potion", chance = 15000, minCount = 10, maxCount = 25 },
+	{ name = "mastermind potion", chance = 15000, minCount = 10, maxCount = 25 },
+	{ name = "berserk potion", chance = 15000, minCount = 10, maxCount = 25 },
+	{ name = "ultimate mana potion", chance = 18000, minCount = 50, maxCount = 100 },
+	{ name = "supreme health potion", chance = 18000, minCount = 50, maxCount = 100 },
+	{ name = "ultimate spirit potion", chance = 18000, minCount = 50, maxCount = 100 },
+	{ name = "figurine of malice", chance = 400 },
+	{ name = "figurine of cruelty", chance = 400 },
+	{ name = "figurine of hatred", chance = 400 },
+	{ name = "figurine of greed", chance = 400 },
+	{ name = "figurine of spite", chance = 400 },
+	{ name = "figurine of megalomania", chance = 400 },
+	{ name = "megalomania's skull", chance = 400 },
+	{ name = "megalomania's essence", chance = 400 },
+	{ name = "bag you desire", chance = 100 },
+}
+
+monster.attacks = {
+	{ name = "melee", interval = 2000, chance = 100, minDamage = -800, maxDamage = -2500 },
+	{ name = "combat", interval = 2000, chance = 30, type = COMBAT_DEATHDAMAGE, minDamage = -1550, maxDamage = -2620, length = 8, spread = 0, effect = CONST_ME_MORTAREA, target = false },
+	{ name = "combat", interval = 2000, chance = 30, type = COMBAT_DEATHDAMAGE, minDamage = -1550, maxDamage = -2620, length = 8, spread = 0, effect = CONST_ME_BLACK_BLOOD, target = false },
+	{ name = "combat", interval = 2000, chance = 30, type = COMBAT_DEATHDAMAGE, minDamage = -1050, maxDamage = -2020, length = 8, spread = 3, effect = CONST_ME_GHOST_SMOKE, target = false },
+	{ name = "combat", interval = 2000, chance = 30, type = COMBAT_DEATHDAMAGE, minDamage = -1050, maxDamage = -2020, length = 8, spread = 3, effect = CONST_ME_SMALLCLOUDS, target = false },
+	{ name = "combat", interval = 2000, chance = 30, type = COMBAT_DEATHDAMAGE, minDamage = -950, maxDamage = -1400, radius = 3, effect = CONST_ME_MORTAREA, target = true },
+	{ name = "soulwars fear", interval = 35000, chance = 100, target = true },
+	{ name = "megalomania transform elemental", interval = SoulWarQuest.goshnarsCrueltyWaveInterval * 1000, chance = 50 },
+	{ name = "combat", interval = 30000, chance = 100, type = COMBAT_LIFEDRAIN, minDamage = -1000, maxDamage = -1500, length = 8, radius = 5, spread = 0, effect = CONST_ME_PINK_ENERGY_SPARK, target = true },
+}
+
+monster.defenses = {
+	defense = 55,
+	armor = 55,
+}
+
+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.onAppear = function(monster, creature)
+	if monster:getType():isRewardBoss() then
+		monster:setReward(true)
+	end
+end
+
+local intervalBetweenExecutions = 10000
+
+local zone = Zone.getByName("boss.goshnar's-megalomania-purple")
+local zonePositions = zone:getPositions()
+
+mType.onThink = function(monsterCallback, interval)
+	monsterCallback:onThinkGoshnarTormentCounter(interval, 36, intervalBetweenExecutions, SoulWarQuest.levers.goshnarsMegalomania.boss.position)
+	monsterCallback:onThinkMegalomaniaWhiteTiles(interval, zonePositions, 8000)
+	monsterCallback:goshnarsDefenseIncrease("cleansed-sanity-action")
+end
+
+mType:register(monster)
diff --git a/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_purple.lua b/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_purple.lua
new file mode 100644
index 00000000000..6b7b12968e5
--- /dev/null
+++ b/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_purple.lua
@@ -0,0 +1,132 @@
+local mType = Game.createMonsterType("Goshnar's Megalomania Purple")
+local monster = {}
+
+monster.name = "Goshnar's Megalomania"
+monster.description = "Goshnar's Megalomania"
+monster.experience = 0
+monster.outfit = {
+	lookType = 1308,
+}
+
+monster.health = 620000
+monster.maxHealth = 620000
+monster.race = "undead"
+monster.corpse = 6028
+monster.speed = 250
+monster.manaCost = 0
+monster.maxSummons = 4
+
+monster.changeTarget = {
+	interval = 4000,
+	chance = 10,
+}
+
+monster.strategiesTarget = {
+	nearest = 80,
+	health = 10,
+	damage = 10,
+}
+
+monster.events = {
+	"GoshnarsHatredBuff",
+}
+
+monster.flags = {
+	summonable = false,
+	attackable = true,
+	hostile = true,
+	convinceable = false,
+	pushable = false,
+	rewardBoss = true,
+	illusionable = false,
+	canPushItems = true,
+	canPushCreatures = true,
+	staticAttackChance = 80,
+	targetDistance = 1,
+	runHealth = 0,
+	healthHidden = false,
+	isBlockable = false,
+	canWalkOnEnergy = true,
+	canWalkOnFire = true,
+	canWalkOnPoison = true,
+	pet = false,
+}
+
+monster.light = {
+	level = 0,
+	color = 0,
+}
+
+monster.voices = {
+	interval = 5000,
+	chance = 10,
+}
+
+monster.attacks = {
+	{ name = "melee", interval = 2000, chance = 100, minDamage = -800, maxDamage = -2500 },
+	{ name = "combat", interval = 2000, chance = 30, type = COMBAT_DEATHDAMAGE, minDamage = -1550, maxDamage = -2620, length = 8, spread = 0, effect = CONST_ME_MORTAREA, target = false },
+	{ name = "combat", interval = 2000, chance = 30, type = COMBAT_DEATHDAMAGE, minDamage = -1550, maxDamage = -2620, length = 8, spread = 0, effect = CONST_ME_BLACK_BLOOD, target = false },
+	{ name = "combat", interval = 2000, chance = 30, type = COMBAT_DEATHDAMAGE, minDamage = -1050, maxDamage = -2020, length = 8, spread = 3, effect = CONST_ME_GHOST_SMOKE, target = false },
+	{ name = "combat", interval = 2000, chance = 30, type = COMBAT_DEATHDAMAGE, minDamage = -1050, maxDamage = -2020, length = 8, spread = 3, effect = CONST_ME_SMALLCLOUDS, target = false },
+	{ name = "combat", interval = 2000, chance = 30, type = COMBAT_DEATHDAMAGE, minDamage = -950, maxDamage = -1400, radius = 3, effect = CONST_ME_MORTAREA, target = true },
+	{ name = "soulwars fear", interval = 35000, chance = 100, target = true },
+	{ name = "megalomania transform elemental", interval = SoulWarQuest.goshnarsCrueltyWaveInterval * 1000, chance = 50 },
+	{ name = "combat", interval = 30000, chance = 100, type = COMBAT_LIFEDRAIN, minDamage = -1000, maxDamage = -1500, length = 8, radius = 5, spread = 0, effect = CONST_ME_PINK_ENERGY_SPARK, target = true },
+}
+
+monster.defenses = {
+	defense = 25,
+	armor = 25,
+}
+
+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 = false },
+	{ type = "invisible", condition = true },
+	{ type = "bleed", condition = false },
+}
+
+mType.onSpawn = function(monster)
+	if monster:getType():isRewardBoss() then
+		monster:setReward(true)
+	end
+
+	if SoulWarQuest.changeBlueEvent then
+		stopEvent(SoulWarQuest.changeBlueEvent)
+	end
+	if SoulWarQuest.changePurpleEvent then
+		stopEvent(SoulWarQuest.changePurpleEvent)
+	end
+
+	SoulWarQuest.changeBlueEvent = addEvent(SoulWarQuest.changeMegalomaniaBlue, 6 * 60 * 1000)
+
+	local bossKV = monster:getSoulWarKV()
+	bossKV:set("aspect-of-power-death-count", 0)
+	monster:resetHatredDamageMultiplier()
+end
+
+local intervalBetweenExecutions = 10000
+
+local zone = Zone.getByName("boss.goshnar's-megalomania-purple")
+local zonePositions = zone:getPositions()
+
+mType.onThink = function(monsterCallback, interval)
+	monsterCallback:onThinkGoshnarTormentCounter(interval, 36, intervalBetweenExecutions, SoulWarQuest.levers.goshnarsMegalomania.boss.position)
+	monsterCallback:onThinkMegalomaniaWhiteTiles(interval, zonePositions, 8000)
+	monsterCallback:goshnarsDefenseIncrease("cleansed-sanity-action")
+end
+
+mType:register(monster)
diff --git a/data-otservbr-global/monster/quests/soul_war/goshnars_cruelty.lua b/data-otservbr-global/monster/quests/soul_war/goshnars_cruelty.lua
index 40957e0bde4..90a0235225b 100644
--- a/data-otservbr-global/monster/quests/soul_war/goshnars_cruelty.lua
+++ b/data-otservbr-global/monster/quests/soul_war/goshnars_cruelty.lua
@@ -14,7 +14,7 @@ monster.outfit = {
 }
 
 monster.events = {
-	"SoulwarsBossDeath",
+	"SoulWarBossesDeath",
 }
 
 monster.health = 300000
@@ -67,14 +67,6 @@ monster.light = {
 	color = 0,
 }
 
-monster.summon = {
-	maxSummons = 4,
-	summons = {
-		{ name = "dreadful harvester", chance = 40, interval = 1000, count = 2 },
-		{ name = "mean maw", chance = 30, interval = 1000, count = 2 },
-	},
-}
-
 monster.voices = {
 	interval = 5000,
 	chance = 10,
@@ -112,6 +104,7 @@ monster.attacks = {
 	{ name = "singlecloudchain", interval = 6000, chance = 40, minDamage = -1700, maxDamage = -2500, range = 6, effect = CONST_ME_ENERGYHIT, target = true },
 	{ name = "combat", interval = 2000, chance = 30, type = COMBAT_PHYSICALDAMAGE, minDamage = -1000, maxDamage = -2500, range = 7, radius = 4, shootEffect = CONST_ANI_EXPLOSION, effect = CONST_ME_DRAWBLOOD, target = true },
 	{ name = "combat", interval = 2000, chance = 15, type = COMBAT_DEATHDAMAGE, minDamage = -1500, maxDamage = -3000, radius = 3, effect = CONST_ME_GROUNDSHAKER, target = false },
+	{ name = "cruelty transform elemental", interval = SoulWarQuest.goshnarsCrueltyWaveInterval * 1000, chance = 50 },
 }
 
 monster.defenses = {
@@ -142,9 +135,13 @@ monster.immunities = {
 	{ type = "bleed", condition = false },
 }
 
-mType.onThink = function(monster, interval) end
+mType.onThink = function(monster)
+	monster:goshnarsDefenseIncrease("greedy-maw-action")
+end
+
+mType.onAppear = function(monster, creature) end
 
-mType.onAppear = function(monster, creature)
+mType.onSpawn = function(monster)
 	if monster:getType():isRewardBoss() then
 		monster:setReward(true)
 	end
diff --git a/data-otservbr-global/monster/quests/soul_war/goshnars_greed.lua b/data-otservbr-global/monster/quests/soul_war/goshnars_greed.lua
index 171f963f5ff..bd0e064a6b4 100644
--- a/data-otservbr-global/monster/quests/soul_war/goshnars_greed.lua
+++ b/data-otservbr-global/monster/quests/soul_war/goshnars_greed.lua
@@ -14,7 +14,7 @@ monster.outfit = {
 }
 
 monster.events = {
-	"SoulwarsBossDeath",
+	"SoulWarBossesDeath",
 }
 
 monster.health = 300000
@@ -68,10 +68,9 @@ monster.light = {
 }
 
 monster.summon = {
-	maxSummons = 4,
+	maxSummons = 1,
 	summons = {
-		{ name = "dreadful harvester", chance = 10, interval = 1000, count = 2 },
-		{ name = "hateful soul", chance = 10, interval = 1000, count = 2 },
+		{ name = "dreadful harvester", chance = 10, interval = 1000, count = 1 },
 	},
 }
 
@@ -139,12 +138,41 @@ monster.immunities = {
 	{ type = "bleed", condition = false },
 }
 
-mType.onThink = function(monster, interval) end
+local immuneTimeCount = 0
+local isImmune = nil
+local createdSoulSphere = nil
+mType.onThink = function(monsterCallback, interval)
+	if GreedbeastKills == 5 and isImmune == nil then
+		isImmune = monsterCallback:immune(false)
+		monsterCallback:teleportTo(Position(33741, 31659, 14))
+		monsterCallback:setSpeed(0)
+		createdSoulSphere = Game.createMonster("Soul Sphere", Position(33752, 31659, 14), true, true)
+	end
+	if isImmune ~= nil then
+		immuneTimeCount = immuneTimeCount + interval
+		logger.info("Immune time count {}", immuneTimeCount)
+		if immuneTimeCount >= 45000 then
+			monsterCallback:immune(true)
+			monsterCallback:setSpeed(monster.speed)
+			monsterCallback:teleportTo(Position(33746, 31666, 14))
+			immuneTimeCount = 0
+			GreedbeastKills = 0
+			isImmune = nil
+			if createdSoulSphere then
+				createdSoulSphere:remove()
+			end
+		end
+	end
+end
 
-mType.onAppear = function(monster, creature)
+mType.onSpawn = function(monster)
 	if monster:getType():isRewardBoss() then
 		monster:setReward(true)
 	end
+
+	monster:immune(true)
+	immuneTimeCount = 0
+	GreedbeastKills = 0
 end
 
 mType.onDisappear = function(monster, creature) end
diff --git a/data-otservbr-global/monster/quests/soul_war/goshnars_hatred.lua b/data-otservbr-global/monster/quests/soul_war/goshnars_hatred.lua
index fa5ccf36984..09970df24fe 100644
--- a/data-otservbr-global/monster/quests/soul_war/goshnars_hatred.lua
+++ b/data-otservbr-global/monster/quests/soul_war/goshnars_hatred.lua
@@ -14,7 +14,8 @@ monster.outfit = {
 }
 
 monster.events = {
-	"SoulwarsBossDeath",
+	"GoshnarsHatredBuff",
+	"SoulWarBossesDeath",
 }
 
 monster.health = 300000
@@ -67,14 +68,6 @@ monster.light = {
 	color = 0,
 }
 
-monster.summon = {
-	maxSummons = 4,
-	summons = {
-		{ name = "dreadful harvester", chance = 10, interval = 1000, count = 2 },
-		{ name = "hateful soul", chance = 10, interval = 1000, count = 2 },
-	},
-}
-
 monster.voices = {
 	interval = 5000,
 	chance = 10,
@@ -143,10 +136,14 @@ monster.immunities = {
 
 mType.onThink = function(monster, interval) end
 
-mType.onAppear = function(monster, creature)
+mType.onAppear = function(monster, creature) end
+
+mType.onSpawn = function(monster)
 	if monster:getType():isRewardBoss() then
 		monster:setReward(true)
 	end
+
+	monster:resetHatredDamageMultiplier()
 end
 
 mType.onDisappear = function(monster, creature) end
diff --git a/data-otservbr-global/monster/quests/soul_war/goshnars_malice.lua b/data-otservbr-global/monster/quests/soul_war/goshnars_malice.lua
index 5e79dcccbdd..2d71ff568b2 100644
--- a/data-otservbr-global/monster/quests/soul_war/goshnars_malice.lua
+++ b/data-otservbr-global/monster/quests/soul_war/goshnars_malice.lua
@@ -14,7 +14,8 @@ monster.outfit = {
 }
 
 monster.events = {
-	"SoulwarsBossDeath",
+	"SoulWarBossesDeath",
+	"Goshnar's-Malice",
 }
 
 monster.health = 300000
@@ -141,7 +142,19 @@ monster.immunities = {
 	{ type = "bleed", condition = false },
 }
 
-mType.onThink = function(monster, interval) end
+local zone = Zone.getByName("boss.goshnar's-malice")
+local zonePositions = zone:getPositions()
+
+local accumulatedTime = 0
+local desiredInterval = 40000
+mType.onThink = function(monster, interval)
+	accumulatedTime = accumulatedTime + interval
+	-- Execute only after 40 seconds
+	if accumulatedTime >= desiredInterval then
+		monster:createSoulWarWhiteTiles(SoulWarQuest.levers.goshnarsMalice.boss.position, zonePositions)
+		accumulatedTime = 0
+	end
+end
 
 mType.onAppear = function(monster, creature)
 	if monster:getType():isRewardBoss() then
diff --git a/data-otservbr-global/monster/quests/soul_war/goshnars_spite.lua b/data-otservbr-global/monster/quests/soul_war/goshnars_spite.lua
index 19d35cd1af7..0e41373cc8e 100644
--- a/data-otservbr-global/monster/quests/soul_war/goshnars_spite.lua
+++ b/data-otservbr-global/monster/quests/soul_war/goshnars_spite.lua
@@ -14,7 +14,7 @@ monster.outfit = {
 }
 
 monster.events = {
-	"SoulwarsBossDeath",
+	"SoulWarBossesDeath",
 }
 
 monster.health = 300000
@@ -70,8 +70,8 @@ monster.light = {
 monster.summon = {
 	maxSummons = 4,
 	summons = {
-		{ name = "dreadful harvester", chance = 40, interval = 1000, count = 2 },
-		{ name = "spiteful spitter", chance = 30, interval = 1000, count = 2 },
+		{ name = "dreadful harvester", chance = 50, interval = 1000, count = 2 },
+		{ name = "spiteful spitter", chance = 50, interval = 1000, count = 2 },
 	},
 }
 
@@ -111,6 +111,7 @@ monster.attacks = {
 	{ name = "singlecloudchain", interval = 6000, chance = 40, minDamage = -1700, maxDamage = -1900, range = 6, effect = CONST_ME_ENERGYHIT, target = true },
 	{ name = "combat", interval = 2000, chance = 30, type = COMBAT_EARTHDAMAGE, minDamage = -1200, maxDamage = -3500, range = 7, radius = 4, shootEffect = CONST_ANI_POISON, effect = CONST_ME_GREEN_RINGS, target = true },
 	{ name = "combat", interval = 2000, chance = 10, type = COMBAT_EARTHDAMAGE, minDamage = -1400, maxDamage = -2200, length = 8, spread = 0, effect = CONST_ME_GREEN_RINGS, target = false },
+	{ name = "soulwars fear", interval = 2000, chance = 10, target = true },
 }
 
 monster.defenses = {
diff --git a/data-otservbr-global/monster/quests/soul_war/greedbeast.lua b/data-otservbr-global/monster/quests/soul_war/greedbeast.lua
new file mode 100644
index 00000000000..db7076d5710
--- /dev/null
+++ b/data-otservbr-global/monster/quests/soul_war/greedbeast.lua
@@ -0,0 +1,98 @@
+local mType = Game.createMonsterType("Greedbeast")
+local monster = {}
+
+monster.description = "a greedbeast"
+monster.experience = 0
+monster.outfit = {
+	lookType = 101,
+	lookHead = 0,
+	lookBody = 0,
+	lookLegs = 0,
+	lookFeet = 0,
+	lookAddons = 0,
+	lookMount = 0,
+}
+
+monster.health = 10000
+monster.maxHealth = 10000
+monster.race = "undead"
+monster.corpse = 0
+monster.speed = 200
+
+monster.events = {
+	"GreedMonsterDeath",
+}
+
+monster.changeTarget = {
+	interval = 4000,
+	chance = 10,
+}
+
+monster.strategiesTarget = {
+	nearest = 100,
+}
+
+monster.flags = {
+	summonable = false,
+	attackable = true,
+	hostile = true,
+	convinceable = false,
+	pushable = false,
+	rewardBoss = false,
+	illusionable = false,
+	canPushItems = true,
+	canPushCreatures = true,
+	staticAttackChance = 90,
+	targetDistance = 1,
+	runHealth = 0,
+	healthHidden = false,
+	isBlockable = false,
+	canWalkOnEnergy = false,
+	canWalkOnFire = false,
+	canWalkOnPoison = true,
+}
+
+monster.light = {
+	level = 0,
+	color = 0,
+}
+
+monster.attacks = {
+	{ name = "melee", interval = 2000, chance = 100, minDamage = 0, maxDamage = -500, condition = { type = CONDITION_POISON, totalDamage = 100, interval = 4000 } },
+	{ name = "combat", interval = 2000, chance = 15, type = COMBAT_EARTHDAMAGE, minDamage = -50, maxDamage = -90, range = 7, shootEffect = CONST_ANI_POISON, effect = CONST_ME_POISONAREA, target = false },
+	{ name = "combat", interval = 2000, chance = 10, type = COMBAT_LIFEDRAIN, minDamage = -25, maxDamage = -47, radius = 3, effect = CONST_ME_MAGIC_RED, target = false },
+	-- poison
+	{ name = "condition", type = CONDITION_POISON, interval = 2000, chance = 10, minDamage = -200, maxDamage = -400, radius = 3, effect = CONST_ME_POISONAREA, target = false },
+	-- poison
+	{ name = "condition", type = CONDITION_POISON, interval = 2000, chance = 10, minDamage = -200, maxDamage = -400, length = 6, spread = 0, effect = CONST_ME_POISONAREA, target = false },
+	{ name = "speed", interval = 2000, chance = 15, speedChange = -600, target = true, duration = 13000 },
+}
+
+monster.defenses = {
+	defense = 70,
+	armor = 80,
+	mitigation = 1.15,
+	{ name = "combat", interval = 2000, chance = 15, type = COMBAT_HEALING, minDamage = 50, maxDamage = 60, effect = CONST_ME_HITBYPOISON, target = false },
+}
+
+monster.elements = {
+	{ type = COMBAT_PHYSICALDAMAGE, percent = 0 },
+	{ type = COMBAT_ENERGYDAMAGE, percent = 0 },
+	{ type = COMBAT_EARTHDAMAGE, percent = 100 },
+	{ type = COMBAT_FIREDAMAGE, percent = -10 },
+	{ type = COMBAT_LIFEDRAIN, percent = 100 },
+	{ type = COMBAT_MANADRAIN, percent = 0 },
+	{ type = COMBAT_DROWNDAMAGE, percent = 100 },
+	{ type = COMBAT_ICEDAMAGE, percent = 0 },
+	{ type = COMBAT_HOLYDAMAGE, percent = -25 },
+	{ type = COMBAT_DEATHDAMAGE, percent = 100 },
+}
+
+monster.immunities = {
+	{ type = "paralyze", condition = true },
+	{ type = "outfit", condition = false },
+	{ type = "invisible", condition = true },
+	{ type = "bleed", condition = false },
+}
+
+mType:register(monster)
diff --git a/data-otservbr-global/monster/quests/soul_war/mirror_image.lua b/data-otservbr-global/monster/quests/soul_war/mirror_image.lua
index 8813ba2e93f..ceacde54c26 100644
--- a/data-otservbr-global/monster/quests/soul_war/mirror_image.lua
+++ b/data-otservbr-global/monster/quests/soul_war/mirror_image.lua
@@ -13,6 +13,10 @@ monster.outfit = {
 	lookMount = 0,
 }
 
+monster.events = {
+	"FourthTaintBossesPrepareDeath",
+}
+
 monster.health = 35000
 monster.maxHealth = 35000
 monster.race = "blood"
@@ -106,4 +110,40 @@ monster.events = {
 	"MirrorImageTransform",
 }
 
+mType.onPlayerAttack = function(monster, attackerPlayer)
+	logger.info("Player {}, attacking monster {}", attackerPlayer:getName(), monster:getName())
+
+	local apparitionType = ""
+	local apparitionTypes = {
+		"Druid's Apparition",
+		"Knight's Apparition",
+		"Paladin's Apparition",
+		"Sorcerer's Apparition",
+	}
+
+	local sameVocationProbability = 70 -- 70% chance for create monster of first player attack vocation
+	if attackerPlayer:isDruid() then
+		apparitionType = "Druid's Apparition"
+	elseif attackerPlayer:isKnight() then
+		apparitionType = "Knight's Apparition"
+	elseif attackerPlayer:isPaladin() then
+		apparitionType = "Paladin's Apparition"
+	elseif attackerPlayer:isSorcerer() then
+		apparitionType = "Sorcerer's Apparition"
+	end
+
+	if math.random(100) > sameVocationProbability then
+		repeat
+			local randomIndex = math.random(#apparitionTypes)
+			if apparitionTypes[randomIndex] ~= apparitionType then
+				apparitionType = apparitionTypes[randomIndex]
+				break
+			end
+		until false
+	end
+
+	Game.createMonster(apparitionType, monster:getPosition(), true, true)
+	monster:remove()
+end
+
 mType:register(monster)
diff --git a/data-otservbr-global/monster/undeads/bony_sea_devil.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/bony_sea_devil.lua
similarity index 96%
rename from data-otservbr-global/monster/undeads/bony_sea_devil.lua
rename to data-otservbr-global/monster/quests/soul_war/normal_monsters/bony_sea_devil.lua
index 1199240df4b..2737bd3a098 100644
--- a/data-otservbr-global/monster/undeads/bony_sea_devil.lua
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/bony_sea_devil.lua
@@ -26,6 +26,10 @@ monster.Bestiary = {
 	Locations = "Ebb and Flow.",
 }
 
+monster.events = {
+	"FourthTaintBossesPrepareDeath",
+}
+
 monster.health = 24000
 monster.maxHealth = 24000
 monster.race = "undead"
@@ -136,4 +140,8 @@ monster.immunities = {
 	{ type = "bleed", condition = false },
 }
 
+mType.onThink = function(monster, interval)
+	monster:tryTeleportToPlayer("Get out the way!")
+end
+
 mType:register(monster)
diff --git a/data-otservbr-global/monster/demons/brachiodemon.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/brachiodemon.lua
similarity index 96%
rename from data-otservbr-global/monster/demons/brachiodemon.lua
rename to data-otservbr-global/monster/quests/soul_war/normal_monsters/brachiodemon.lua
index 930ecfe469f..378a15814c6 100644
--- a/data-otservbr-global/monster/demons/brachiodemon.lua
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/brachiodemon.lua
@@ -26,6 +26,10 @@ monster.Bestiary = {
 	Locations = "Claustrophobic Inferno.",
 }
 
+monster.events = {
+	"FourthTaintBossesPrepareDeath",
+}
+
 monster.health = 25000
 monster.maxHealth = 25000
 monster.race = "blood"
@@ -137,4 +141,8 @@ monster.immunities = {
 	{ type = "bleed", condition = false },
 }
 
+mType.onThink = function(monster, interval)
+	monster:tryTeleportToPlayer("Burn in hell!")
+end
+
 mType:register(monster)
diff --git a/data-otservbr-global/monster/plants/branchy_crawler.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/branchy_crawler.lua
similarity index 95%
rename from data-otservbr-global/monster/plants/branchy_crawler.lua
rename to data-otservbr-global/monster/quests/soul_war/normal_monsters/branchy_crawler.lua
index d319fcde5e5..0798c9f482f 100644
--- a/data-otservbr-global/monster/plants/branchy_crawler.lua
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/branchy_crawler.lua
@@ -26,6 +26,10 @@ monster.Bestiary = {
 	Locations = "Rotten Wasteland.",
 }
 
+monster.events = {
+	"FourthTaintBossesPrepareDeath",
+}
+
 monster.health = 27000
 monster.maxHealth = 27000
 monster.race = "blood"
@@ -132,4 +136,8 @@ monster.immunities = {
 	{ type = "bleed", condition = false },
 }
 
+mType.onThink = function(monster, interval)
+	monster:tryTeleportToPlayer("My growth is your death!")
+end
+
 mType:register(monster)
diff --git a/data-otservbr-global/monster/quests/soul_war/normal_monsters/burning_hatred/ashes_of_burning_hatred.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/burning_hatred/ashes_of_burning_hatred.lua
new file mode 100644
index 00000000000..72c4082ee0e
--- /dev/null
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/burning_hatred/ashes_of_burning_hatred.lua
@@ -0,0 +1,89 @@
+local mType = Game.createMonsterType("Ashes of Burning Hatred")
+local monster = {}
+
+monster.description = "a ashes of burning hatred"
+monster.experience = 0
+monster.outfit = {
+	lookTypeEx = 34009,
+}
+
+monster.health = 15000
+monster.maxHealth = 15000
+monster.race = "undead"
+monster.corpse = 5993
+monster.speed = 0
+monster.manaCost = 100
+monster.maxSummons = 0
+
+monster.changeTarget = {
+	interval = 2000,
+	chance = 40,
+}
+
+monster.strategiesTarget = {
+	nearest = 0,
+	health = 0,
+	damage = 0,
+	random = 100,
+}
+
+monster.events = {
+	"BurningChangeForm",
+}
+
+monster.flags = {
+	summonable = false,
+	attackable = true,
+	hostile = true,
+	convinceable = false,
+	pushable = false,
+	rewardBoss = false,
+	illusionable = false,
+	canPushItems = true,
+	canPushCreatures = true,
+	staticAttackChance = 90,
+	targetDistance = 1,
+	runHealth = 0,
+	healthHidden = false,
+	isBlockable = false,
+	canWalkOnEnergy = true,
+	canWalkOnFire = true,
+	canWalkOnPoison = true,
+	pet = false,
+}
+
+monster.light = {
+	level = 0,
+	color = 0,
+}
+
+monster.attacks = {
+	{ name = "combat", interval = 2000, chance = 25, type = COMBAT_FIREDAMAGE, minDamage = -555, maxDamage = -703, range = 9, shootEffect = CONST_ANI_FIRE, target = true },
+}
+
+monster.defenses = {
+	defense = 5,
+	armor = 10,
+}
+
+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 = false },
+	{ type = "invisible", condition = false },
+	{ type = "bleed", condition = false },
+}
+
+mType:register(monster)
diff --git a/data-otservbr-global/monster/quests/soul_war/normal_monsters/burning_hatred/blaze_of_burning_hatred.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/burning_hatred/blaze_of_burning_hatred.lua
new file mode 100644
index 00000000000..c0b76ce98df
--- /dev/null
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/burning_hatred/blaze_of_burning_hatred.lua
@@ -0,0 +1,89 @@
+local mType = Game.createMonsterType("Blaze of Burning Hatred")
+local monster = {}
+
+monster.description = "a blaze of burning hatred"
+monster.experience = 0
+monster.outfit = {
+	lookTypeEx = 34013,
+}
+
+monster.health = 15000
+monster.maxHealth = 15000
+monster.race = "undead"
+monster.corpse = 5993
+monster.speed = 0
+monster.manaCost = 100
+monster.maxSummons = 0
+
+monster.changeTarget = {
+	interval = 2000,
+	chance = 40,
+}
+
+monster.strategiesTarget = {
+	nearest = 0,
+	health = 0,
+	damage = 0,
+	random = 100,
+}
+
+monster.events = {
+	"BurningChangeForm",
+}
+
+monster.flags = {
+	summonable = false,
+	attackable = true,
+	hostile = true,
+	convinceable = false,
+	pushable = false,
+	rewardBoss = false,
+	illusionable = false,
+	canPushItems = true,
+	canPushCreatures = true,
+	staticAttackChance = 90,
+	targetDistance = 1,
+	runHealth = 0,
+	healthHidden = false,
+	isBlockable = false,
+	canWalkOnEnergy = true,
+	canWalkOnFire = true,
+	canWalkOnPoison = true,
+	pet = false,
+}
+
+monster.light = {
+	level = 0,
+	color = 0,
+}
+
+monster.attacks = {
+	{ name = "combat", interval = 2000, chance = 25, type = COMBAT_FIREDAMAGE, minDamage = -555, maxDamage = -703, range = 9, shootEffect = CONST_ANI_FIRE, target = true },
+}
+
+monster.defenses = {
+	defense = 5,
+	armor = 10,
+}
+
+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 = false },
+	{ type = "invisible", condition = false },
+	{ type = "bleed", condition = false },
+}
+
+mType:register(monster)
diff --git a/data-otservbr-global/monster/quests/soul_war/normal_monsters/burning_hatred/flame_of_burning_hatred.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/burning_hatred/flame_of_burning_hatred.lua
new file mode 100644
index 00000000000..483c5156fb1
--- /dev/null
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/burning_hatred/flame_of_burning_hatred.lua
@@ -0,0 +1,89 @@
+local mType = Game.createMonsterType("Flame of Burning Hatred")
+local monster = {}
+
+monster.description = "a flame of burning hatred"
+monster.experience = 0
+monster.outfit = {
+	lookTypeEx = 34011,
+}
+
+monster.health = 15000
+monster.maxHealth = 15000
+monster.race = "undead"
+monster.corpse = 5993
+monster.speed = 0
+monster.manaCost = 100
+monster.maxSummons = 0
+
+monster.changeTarget = {
+	interval = 2000,
+	chance = 40,
+}
+
+monster.strategiesTarget = {
+	nearest = 0,
+	health = 0,
+	damage = 0,
+	random = 100,
+}
+
+monster.events = {
+	"BurningChangeForm",
+}
+
+monster.flags = {
+	summonable = false,
+	attackable = true,
+	hostile = true,
+	convinceable = false,
+	pushable = false,
+	rewardBoss = false,
+	illusionable = false,
+	canPushItems = true,
+	canPushCreatures = true,
+	staticAttackChance = 90,
+	targetDistance = 1,
+	runHealth = 0,
+	healthHidden = false,
+	isBlockable = false,
+	canWalkOnEnergy = true,
+	canWalkOnFire = true,
+	canWalkOnPoison = true,
+	pet = false,
+}
+
+monster.light = {
+	level = 0,
+	color = 0,
+}
+
+monster.attacks = {
+	{ name = "combat", interval = 2000, chance = 25, type = COMBAT_FIREDAMAGE, minDamage = -555, maxDamage = -703, range = 9, shootEffect = CONST_ANI_FIRE, target = true },
+}
+
+monster.defenses = {
+	defense = 5,
+	armor = 10,
+}
+
+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 = false },
+	{ type = "invisible", condition = false },
+	{ type = "bleed", condition = false },
+}
+
+mType:register(monster)
diff --git a/data-otservbr-global/monster/quests/soul_war/normal_monsters/burning_hatred/spark_of_burning_hatred.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/burning_hatred/spark_of_burning_hatred.lua
new file mode 100644
index 00000000000..dc9ff25f05e
--- /dev/null
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/burning_hatred/spark_of_burning_hatred.lua
@@ -0,0 +1,89 @@
+local mType = Game.createMonsterType("Spark of Burning Hatred")
+local monster = {}
+
+monster.description = "a spark of burning hatred"
+monster.experience = 0
+monster.outfit = {
+	lookTypeEx = 34010,
+}
+
+monster.health = 15000
+monster.maxHealth = 15000
+monster.race = "undead"
+monster.corpse = 5993
+monster.speed = 0
+monster.manaCost = 100
+monster.maxSummons = 0
+
+monster.changeTarget = {
+	interval = 2000,
+	chance = 40,
+}
+
+monster.strategiesTarget = {
+	nearest = 0,
+	health = 0,
+	damage = 0,
+	random = 100,
+}
+
+monster.events = {
+	"BurningChangeForm",
+}
+
+monster.flags = {
+	summonable = false,
+	attackable = true,
+	hostile = true,
+	convinceable = false,
+	pushable = false,
+	rewardBoss = false,
+	illusionable = false,
+	canPushItems = true,
+	canPushCreatures = true,
+	staticAttackChance = 90,
+	targetDistance = 1,
+	runHealth = 0,
+	healthHidden = false,
+	isBlockable = false,
+	canWalkOnEnergy = true,
+	canWalkOnFire = true,
+	canWalkOnPoison = true,
+	pet = false,
+}
+
+monster.light = {
+	level = 0,
+	color = 0,
+}
+
+monster.attacks = {
+	{ name = "combat", interval = 2000, chance = 25, type = COMBAT_FIREDAMAGE, minDamage = -555, maxDamage = -703, range = 9, shootEffect = CONST_ANI_FIRE, target = true },
+}
+
+monster.defenses = {
+	defense = 5,
+	armor = 10,
+}
+
+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 = false },
+	{ type = "invisible", condition = false },
+	{ type = "bleed", condition = false },
+}
+
+mType:register(monster)
diff --git a/data-otservbr-global/monster/quests/soul_war/normal_monsters/burning_hatred/symbol_of_hatred.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/burning_hatred/symbol_of_hatred.lua
new file mode 100644
index 00000000000..9df86b773a9
--- /dev/null
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/burning_hatred/symbol_of_hatred.lua
@@ -0,0 +1,84 @@
+local mType = Game.createMonsterType("Symbol of Hatred")
+local monster = {}
+
+monster.description = "a symbol of hatred"
+monster.experience = 0
+monster.outfit = {
+	lookTypeEx = 11427,
+}
+
+monster.health = 14000
+monster.maxHealth = 14000
+monster.race = "undead"
+monster.corpse = 33792
+monster.speed = 0
+monster.manaCost = 100
+monster.maxSummons = 0
+
+monster.changeTarget = {
+	interval = 4000,
+	chance = 0,
+}
+
+monster.strategiesTarget = {
+	nearest = 100,
+}
+
+monster.flags = {
+	summonable = false,
+	attackable = true,
+	hostile = true,
+	convinceable = false,
+	pushable = false,
+	rewardBoss = false,
+	illusionable = false,
+	canPushItems = true,
+	canPushCreatures = true,
+	staticAttackChance = 90,
+	targetDistance = 1,
+	runHealth = 0,
+	healthHidden = false,
+	isBlockable = false,
+	canWalkOnEnergy = false,
+	canWalkOnFire = false,
+	canWalkOnPoison = true,
+	pet = false,
+}
+
+monster.light = {
+	level = 0,
+	color = 0,
+}
+
+monster.defenses = {
+	defense = 55,
+	armor = 55,
+}
+
+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 = false },
+	{ type = "bleed", condition = false },
+}
+
+local intervalBetweenExecutions = 3000
+
+mType.onThink = function(monsterCallback, interval)
+	monsterCallback:onThinkGoshnarTormentCounter(interval, 30, intervalBetweenExecutions, SoulWarQuest.levers.goshnarsHatred.boss.position)
+end
+
+mType:register(monster)
diff --git a/data-otservbr-global/monster/undeads/capricious_phantom.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/capricious_phantom.lua
similarity index 98%
rename from data-otservbr-global/monster/undeads/capricious_phantom.lua
rename to data-otservbr-global/monster/quests/soul_war/normal_monsters/capricious_phantom.lua
index cd402486853..6a3b5ea0bbc 100644
--- a/data-otservbr-global/monster/undeads/capricious_phantom.lua
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/capricious_phantom.lua
@@ -26,6 +26,10 @@ monster.Bestiary = {
 	Locations = "Ebb and Flow.",
 }
 
+monster.events = {
+	"FourthTaintBossesPrepareDeath",
+}
+
 monster.health = 30000
 monster.maxHealth = 30000
 monster.race = "undead"
diff --git a/data-otservbr-global/monster/undeads/distorted_phantom.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/distorted_phantom.lua
similarity index 98%
rename from data-otservbr-global/monster/undeads/distorted_phantom.lua
rename to data-otservbr-global/monster/quests/soul_war/normal_monsters/distorted_phantom.lua
index c1fdc41461b..a27ae569343 100644
--- a/data-otservbr-global/monster/undeads/distorted_phantom.lua
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/distorted_phantom.lua
@@ -26,6 +26,10 @@ monster.Bestiary = {
 	Locations = "Mirrored Nightmare.",
 }
 
+monster.events = {
+	"FourthTaintBossesPrepareDeath",
+}
+
 monster.health = 26000
 monster.maxHealth = 26000
 monster.race = "undead"
diff --git a/data-otservbr-global/monster/undeads/druid's_apparition.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/druid's_apparition.lua
similarity index 98%
rename from data-otservbr-global/monster/undeads/druid's_apparition.lua
rename to data-otservbr-global/monster/quests/soul_war/normal_monsters/druid's_apparition.lua
index 414de6155bf..6948a58fb53 100644
--- a/data-otservbr-global/monster/undeads/druid's_apparition.lua
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/druid's_apparition.lua
@@ -32,6 +32,10 @@ monster.corpse = 6081
 monster.speed = 235
 monster.manaCost = 0
 
+monster.events = {
+	"MirroredNightmareBossAccess",
+}
+
 monster.changeTarget = {
 	interval = 4000,
 	chance = 0,
diff --git a/data-otservbr-global/monster/quests/soul_war/normal_monsters/furious_crater/a_greedy_eye.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/furious_crater/a_greedy_eye.lua
new file mode 100644
index 00000000000..aed9dcfc829
--- /dev/null
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/furious_crater/a_greedy_eye.lua
@@ -0,0 +1,93 @@
+local mType = Game.createMonsterType("A Greedy Eye")
+local monster = {}
+
+monster.description = "a greedy eye"
+monster.experience = 0
+monster.outfit = {
+	lookType = 925,
+	lookHead = 0,
+	lookBody = 0,
+	lookLegs = 0,
+	lookFeet = 0,
+	lookAddons = 0,
+	lookMount = 0,
+}
+
+monster.health = 30000
+monster.maxHealth = 30000
+monster.race = "blood"
+monster.corpse = 5995
+monster.speed = 0
+monster.manaCost = 0
+monster.maxSummons = 0
+
+monster.changeTarget = {
+	interval = 4000,
+	chance = 20,
+}
+
+monster.strategiesTarget = {
+	nearest = 100,
+}
+
+monster.flags = {
+	summonable = false,
+	attackable = true,
+	hostile = true,
+	convinceable = false,
+	pushable = false,
+	rewardBoss = false,
+	illusionable = false,
+	canPushItems = true,
+	canPushCreatures = true,
+	staticAttackChance = 70,
+	targetDistance = 1,
+	runHealth = 0,
+	healthHidden = false,
+	isBlockable = false,
+	canWalkOnEnergy = true,
+	canWalkOnFire = true,
+	canWalkOnPoison = true,
+	pet = false,
+}
+
+monster.light = {
+	level = 0,
+	color = 0,
+}
+
+monster.voices = {
+	interval = 5000,
+	chance = 10,
+}
+
+monster.attacks = {
+	{ name = "greedy eye beam", interval = 2000, chance = 100, minDamage = -1000, maxDamage = -1000 },
+}
+
+monster.defenses = {
+	defense = 55,
+	armor = 55,
+}
+
+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 = false },
+	{ type = "invisible", condition = true },
+	{ type = "bleed", condition = false },
+}
+
+mType:register(monster)
diff --git a/data-otservbr-global/monster/plants/cloak_of_terror.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/furious_crater/cloak_of_terror.lua
similarity index 95%
rename from data-otservbr-global/monster/plants/cloak_of_terror.lua
rename to data-otservbr-global/monster/quests/soul_war/normal_monsters/furious_crater/cloak_of_terror.lua
index 184ba93fab2..4048e0fd69e 100644
--- a/data-otservbr-global/monster/plants/cloak_of_terror.lua
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/furious_crater/cloak_of_terror.lua
@@ -26,6 +26,11 @@ monster.Bestiary = {
 	Locations = "Furious Crater.",
 }
 
+monster.events = {
+	"FourthTaintBossesPrepareDeath",
+	"CloakOfTerrorHealthLoss",
+}
+
 monster.health = 28000
 monster.maxHealth = 28000
 monster.race = "undead"
@@ -131,4 +136,8 @@ monster.immunities = {
 	{ type = "bleed", condition = false },
 }
 
+mType.onThink = function(monster, interval)
+	monster:tryTeleportToPlayer("I am your terror!")
+end
+
 mType:register(monster)
diff --git a/data-otservbr-global/monster/extra_dimensional/courage_leech.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/furious_crater/courage_leech.lua
similarity index 98%
rename from data-otservbr-global/monster/extra_dimensional/courage_leech.lua
rename to data-otservbr-global/monster/quests/soul_war/normal_monsters/furious_crater/courage_leech.lua
index d8ad3147a8e..8e4a61b6ef0 100644
--- a/data-otservbr-global/monster/extra_dimensional/courage_leech.lua
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/furious_crater/courage_leech.lua
@@ -26,6 +26,10 @@ monster.Bestiary = {
 	Locations = "Furious Crater",
 }
 
+monster.events = {
+	"FourthTaintBossesPrepareDeath",
+}
+
 monster.health = 27000
 monster.maxHealth = 27000
 monster.race = "undead"
diff --git a/data-otservbr-global/monster/quests/soul_war/normal_monsters/furious_crater/poor_soul.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/furious_crater/poor_soul.lua
new file mode 100644
index 00000000000..55f5ccb623f
--- /dev/null
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/furious_crater/poor_soul.lua
@@ -0,0 +1,119 @@
+local mType = Game.createMonsterType("Poor Soul")
+local monster = {}
+
+monster.description = "a poor soul"
+monster.experience = 0
+monster.outfit = {
+	lookType = 1296,
+	lookHead = 0,
+	lookBody = 0,
+	lookLegs = 0,
+	lookFeet = 0,
+	lookAddons = 0,
+	lookMount = 0,
+}
+
+monster.health = 500
+monster.maxHealth = 500
+monster.race = "undead"
+monster.corpse = 33891
+monster.speed = 140
+monster.manaCost = 0
+monster.maxSummons = 0
+
+monster.changeTarget = {
+	interval = 4000,
+	chance = 5,
+}
+
+monster.strategiesTarget = {
+	nearest = 60,
+	health = 10,
+	damage = 10,
+	random = 20,
+}
+
+monster.flags = {
+	summonable = false,
+	attackable = true,
+	hostile = true,
+	convinceable = false,
+	pushable = false,
+	rewardBoss = false,
+	illusionable = false,
+	canPushItems = true,
+	canPushCreatures = true,
+	staticAttackChance = 90,
+	targetDistance = 1,
+	runHealth = 0,
+	healthHidden = false,
+	isBlockable = false,
+	canWalkOnEnergy = true,
+	canWalkOnFire = true,
+	canWalkOnPoison = true,
+	pet = false,
+}
+
+monster.light = {
+	level = 0,
+	color = 0,
+}
+
+monster.voices = {
+	interval = 5000,
+	chance = 10,
+	{ text = "I have a head start.", yell = false },
+	{ text = "Look into my eyes! No, the other ones!", yell = false },
+	{ text = "The mirrors can't contain the night!", yell = false },
+}
+
+monster.loot = {
+	{ name = "crystal coin", chance = 70540 },
+	{ name = "ultimate health potion", chance = 12220, maxCount = 7 },
+	{ name = "violet gem", chance = 4560 },
+	{ name = "green gem", chance = 5760 },
+	{ name = "blue gem", chance = 4960 },
+	{ name = "northwind rod", chance = 5920 },
+	{ name = "sacred tree amulet", chance = 5520 },
+	{ id = 33933, chance = 7920 }, -- apron
+	{ id = 3067, chance = 7220 }, -- hailstorm rod
+	{ name = "glacier shoes", chance = 2520 },
+	{ name = "glacier robe", chance = 2220 },
+	{ name = "stone skin amulet", chance = 5920 },
+	{ id = 23533, chance = 4892 }, -- ring of red plasma
+	{ id = 33932, chance = 3520 }, -- head
+	{ name = "glacial rod", chance = 620 },
+	{ id = 34024, chance = 650 }, -- gruesome fan
+	{ id = 34109, chance = 1 }, -- bag you desire
+}
+
+monster.attacks = {
+	{ name = "melee", interval = 2000, chance = 100, minDamage = -250, maxDamage = -450 },
+}
+
+monster.defenses = {
+	defense = 90,
+	armor = 105,
+}
+
+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 = -300 },
+	{ 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 = false },
+}
+
+mType:register(monster)
diff --git a/data-otservbr-global/monster/undeads/vibrant_phantom.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/furious_crater/vibrant_phantom.lua
similarity index 98%
rename from data-otservbr-global/monster/undeads/vibrant_phantom.lua
rename to data-otservbr-global/monster/quests/soul_war/normal_monsters/furious_crater/vibrant_phantom.lua
index 9f17bee76ee..b6d4b89f024 100644
--- a/data-otservbr-global/monster/undeads/vibrant_phantom.lua
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/furious_crater/vibrant_phantom.lua
@@ -26,6 +26,10 @@ monster.Bestiary = {
 	Locations = "Furious Crater.",
 }
 
+monster.events = {
+	"FourthTaintBossesPrepareDeath",
+}
+
 monster.health = 27000
 monster.maxHealth = 27000
 monster.race = "undead"
diff --git a/data-otservbr-global/monster/quests/soul_war/hateful_soul.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/hateful_soul.lua
similarity index 99%
rename from data-otservbr-global/monster/quests/soul_war/hateful_soul.lua
rename to data-otservbr-global/monster/quests/soul_war/normal_monsters/hateful_soul.lua
index 4aad05f3f33..69c413aa242 100644
--- a/data-otservbr-global/monster/quests/soul_war/hateful_soul.lua
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/hateful_soul.lua
@@ -16,7 +16,7 @@ monster.outfit = {
 monster.health = 25000
 monster.maxHealth = 25000
 monster.race = "undead"
-monster.corpse = 0
+monster.corpse = 33793
 monster.speed = 125
 monster.manaCost = 0
 
diff --git a/data-otservbr-global/monster/demons/infernal_demon.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/infernal_demon.lua
similarity index 98%
rename from data-otservbr-global/monster/demons/infernal_demon.lua
rename to data-otservbr-global/monster/quests/soul_war/normal_monsters/infernal_demon.lua
index 7c4a1d80302..8760d3b1757 100644
--- a/data-otservbr-global/monster/demons/infernal_demon.lua
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/infernal_demon.lua
@@ -26,6 +26,10 @@ monster.Bestiary = {
 	Locations = "Claustrophobic Inferno.",
 }
 
+monster.events = {
+	"FourthTaintBossesPrepareDeath",
+}
+
 monster.health = 32000
 monster.maxHealth = 32000
 monster.race = "blood"
diff --git a/data-otservbr-global/monster/undeads/infernal_phantom.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/infernal_phantom.lua
similarity index 98%
rename from data-otservbr-global/monster/undeads/infernal_phantom.lua
rename to data-otservbr-global/monster/quests/soul_war/normal_monsters/infernal_phantom.lua
index 0b61e291291..e8ef7b231f1 100644
--- a/data-otservbr-global/monster/undeads/infernal_phantom.lua
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/infernal_phantom.lua
@@ -26,6 +26,10 @@ monster.Bestiary = {
 	Locations = "Claustrophobic Inferno.",
 }
 
+monster.events = {
+	"FourthTaintBossesPrepareDeath",
+}
+
 monster.health = 26000
 monster.maxHealth = 26000
 monster.race = "undead"
diff --git a/data-otservbr-global/monster/undeads/knight's_apparition.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/knight's_apparition.lua
similarity index 98%
rename from data-otservbr-global/monster/undeads/knight's_apparition.lua
rename to data-otservbr-global/monster/quests/soul_war/normal_monsters/knight's_apparition.lua
index 0a4415aa2fd..86893bfa01c 100644
--- a/data-otservbr-global/monster/undeads/knight's_apparition.lua
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/knight's_apparition.lua
@@ -33,6 +33,10 @@ monster.corpse = 111
 monster.speed = 235
 monster.manaCost = 0
 
+monster.events = {
+	"MirroredNightmareBossAccess",
+}
+
 monster.changeTarget = {
 	interval = 4000,
 	chance = 0,
diff --git a/data-otservbr-global/monster/demons/many_faces.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/many_faces.lua
similarity index 96%
rename from data-otservbr-global/monster/demons/many_faces.lua
rename to data-otservbr-global/monster/quests/soul_war/normal_monsters/many_faces.lua
index 8b9724a6252..627f1dc8052 100644
--- a/data-otservbr-global/monster/demons/many_faces.lua
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/many_faces.lua
@@ -26,6 +26,10 @@ monster.Bestiary = {
 	Locations = "Mirrored Nightmare.",
 }
 
+monster.events = {
+	"FourthTaintBossesPrepareDeath",
+}
+
 monster.health = 30000
 monster.maxHealth = 30000
 monster.race = "undead"
@@ -133,4 +137,8 @@ monster.immunities = {
 	{ type = "bleed", condition = false },
 }
 
+mType.onThink = function(monster, interval)
+	monster:tryTeleportToPlayer("Hands off my comrades!")
+end
+
 mType:register(monster)
diff --git a/data-otservbr-global/monster/quests/soul_war/normal_monsters/megalomania_room/greater_splinter_of_madness.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/megalomania_room/greater_splinter_of_madness.lua
new file mode 100644
index 00000000000..2193aac5447
--- /dev/null
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/megalomania_room/greater_splinter_of_madness.lua
@@ -0,0 +1,107 @@
+local mType = Game.createMonsterType("Greater Splinter of Madness")
+local monster = {}
+
+monster.description = "a greater splinter of madness"
+monster.experience = 0
+monster.outfit = {
+	lookType = 1268,
+	lookHead = 0,
+	lookBody = 82,
+	lookLegs = 0,
+	lookFeet = 0,
+	lookAddons = 1,
+	lookMount = 0,
+}
+
+monster.health = 4000
+monster.maxHealth = 4000
+monster.race = "undead"
+monster.corpse = 32610
+monster.speed = 175
+monster.manaCost = 0
+monster.maxSummons = 0
+
+monster.changeTarget = {
+	interval = 5000,
+	chance = 10,
+}
+
+monster.strategiesTarget = {
+	nearest = 60,
+	health = 10,
+	damage = 10,
+	random = 20,
+}
+
+monster.flags = {
+	summonable = false,
+	attackable = true,
+	hostile = true,
+	convinceable = false,
+	pushable = false,
+	rewardBoss = false,
+	illusionable = false,
+	canPushItems = true,
+	canPushCreatures = true,
+	staticAttackChance = 90,
+	targetDistance = 1,
+	runHealth = 0,
+	healthHidden = false,
+	isBlockable = false,
+	canWalkOnEnergy = true,
+	canWalkOnFire = true,
+	canWalkOnPoison = true,
+	pet = false,
+}
+
+monster.light = {
+	level = 0,
+	color = 0,
+}
+
+monster.voices = {
+	interval = 5000,
+	chance = 10,
+}
+
+monster.attacks = {
+	{ name = "melee", interval = 2000, chance = 100, minDamage = -100, maxDamage = -450 },
+	{ name = "combat", interval = 2000, chance = 30, type = COMBAT_DEATHDAMAGE, minDamage = -350, maxDamage = -800, range = 4, shootEffect = CONST_ANI_SUDDENDEATH, target = false },
+	{ name = "combat", interval = 2000, chance = 30, type = COMBAT_ENERGYDAMAGE, minDamage = -300, maxDamage = -750, range = 4, shootEffect = CONST_ANI_ENERGY, target = true },
+}
+
+monster.defenses = {
+	defense = 40,
+	armor = 79,
+}
+
+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 = false },
+	{ type = "invisible", condition = true },
+	{ type = "bleed", condition = false },
+}
+
+mType.onSpawn = function(monsterCallback)
+	addEvent(function(monsterId)
+		local eventMonster = Monster(monsterId)
+		if eventMonster then
+			eventMonster:setType("Mighty Splinter of Madness", true)
+		end
+	end, 120000, monsterCallback:getId())
+end
+
+mType:register(monster)
diff --git a/data-otservbr-global/monster/quests/soul_war/normal_monsters/megalomania_room/lesser_splinter_of_madness.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/megalomania_room/lesser_splinter_of_madness.lua
new file mode 100644
index 00000000000..7927ac18a26
--- /dev/null
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/megalomania_room/lesser_splinter_of_madness.lua
@@ -0,0 +1,107 @@
+local mType = Game.createMonsterType("Lesser Splinter of Madness")
+local monster = {}
+
+monster.description = "a lesser splinter of madness"
+monster.experience = 0
+monster.outfit = {
+	lookType = 1268,
+	lookHead = 0,
+	lookBody = 57,
+	lookLegs = 0,
+	lookFeet = 0,
+	lookAddons = 1,
+	lookMount = 0,
+}
+
+monster.health = 4000
+monster.maxHealth = 4000
+monster.race = "undead"
+monster.corpse = 32610
+monster.speed = 175
+monster.manaCost = 0
+monster.maxSummons = 0
+
+monster.changeTarget = {
+	interval = 5000,
+	chance = 10,
+}
+
+monster.strategiesTarget = {
+	nearest = 60,
+	health = 10,
+	damage = 10,
+	random = 20,
+}
+
+monster.flags = {
+	summonable = false,
+	attackable = true,
+	hostile = true,
+	convinceable = false,
+	pushable = false,
+	rewardBoss = false,
+	illusionable = false,
+	canPushItems = true,
+	canPushCreatures = true,
+	staticAttackChance = 90,
+	targetDistance = 1,
+	runHealth = 0,
+	healthHidden = false,
+	isBlockable = false,
+	canWalkOnEnergy = true,
+	canWalkOnFire = true,
+	canWalkOnPoison = true,
+	pet = false,
+}
+
+monster.light = {
+	level = 0,
+	color = 0,
+}
+
+monster.voices = {
+	interval = 5000,
+	chance = 10,
+}
+
+monster.attacks = {
+	{ name = "melee", interval = 2000, chance = 100, minDamage = -100, maxDamage = -350 },
+	{ name = "combat", interval = 2000, chance = 30, type = COMBAT_DEATHDAMAGE, minDamage = -300, maxDamage = -550, range = 4, shootEffect = CONST_ANI_SUDDENDEATH, target = false },
+	{ name = "combat", interval = 2000, chance = 30, type = COMBAT_ENERGYDAMAGE, minDamage = -300, maxDamage = -550, range = 4, shootEffect = CONST_ANI_ENERGY, target = true },
+}
+
+monster.defenses = {
+	defense = 40,
+	armor = 79,
+}
+
+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 = false },
+	{ type = "invisible", condition = true },
+	{ type = "bleed", condition = false },
+}
+
+mType.onSpawn = function(monsterCallback)
+	addEvent(function(monsterId)
+		local eventMonster = Monster(monsterId)
+		if eventMonster then
+			eventMonster:setType("Greater Splinter of Madness", true)
+		end
+	end, 120000, monsterCallback:getId())
+end
+
+mType:register(monster)
diff --git a/data-otservbr-global/monster/quests/soul_war/normal_monsters/megalomania_room/mighty_splinter_of_madness.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/megalomania_room/mighty_splinter_of_madness.lua
new file mode 100644
index 00000000000..18dd5825b89
--- /dev/null
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/megalomania_room/mighty_splinter_of_madness.lua
@@ -0,0 +1,113 @@
+local mType = Game.createMonsterType("Mighty Splinter of Madness")
+local monster = {}
+
+monster.description = "a mighty splinter of madness"
+monster.experience = 0
+monster.outfit = {
+	lookType = 1268,
+	lookHead = 0,
+	lookBody = 93,
+	lookLegs = 0,
+	lookFeet = 0,
+	lookAddons = 1,
+	lookMount = 0,
+}
+
+monster.health = 4000
+monster.maxHealth = 4000
+monster.race = "undead"
+monster.corpse = 32610
+monster.speed = 175
+monster.manaCost = 0
+monster.maxSummons = 0
+
+monster.changeTarget = {
+	interval = 5000,
+	chance = 10,
+}
+
+monster.strategiesTarget = {
+	nearest = 60,
+	health = 10,
+	damage = 10,
+	random = 20,
+}
+
+monster.flags = {
+	summonable = false,
+	attackable = true,
+	hostile = true,
+	convinceable = false,
+	pushable = false,
+	rewardBoss = false,
+	illusionable = false,
+	canPushItems = true,
+	canPushCreatures = true,
+	staticAttackChance = 90,
+	targetDistance = 1,
+	runHealth = 0,
+	healthHidden = false,
+	isBlockable = false,
+	canWalkOnEnergy = true,
+	canWalkOnFire = true,
+	canWalkOnPoison = true,
+	pet = false,
+}
+
+monster.light = {
+	level = 0,
+	color = 0,
+}
+
+monster.voices = {
+	interval = 5000,
+	chance = 10,
+}
+
+monster.attacks = {
+	{ name = "melee", interval = 2000, chance = 100, minDamage = -100, maxDamage = -750 },
+	{ name = "combat", interval = 2000, chance = 30, type = COMBAT_DEATHDAMAGE, minDamage = -450, maxDamage = -800, range = 4, shootEffect = CONST_ANI_SUDDENDEATH, target = false },
+	{ name = "combat", interval = 2000, chance = 30, type = COMBAT_ENERGYDAMAGE, minDamage = -400, maxDamage = -800, range = 4, shootEffect = CONST_ANI_ENERGY, target = true },
+}
+
+monster.defenses = {
+	defense = 40,
+	armor = 79,
+}
+
+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 = false },
+	{ type = "invisible", condition = true },
+	{ type = "bleed", condition = false },
+}
+
+mType.onSpawn = function(monsterCallback)
+	addEvent(function(monsterId)
+		local eventMonster = Monster(monsterId)
+		if eventMonster then
+			creature:say("Goshnar's Megalomania feeds on its own madness and becomes stronger!", TALKTYPE_MONSTER_SAY, 0, 0, Position(34091, 31026, 9))
+			creature:remove()
+			local boss = Creature("Goshnar's Megalomania")
+			if boss then
+				boss:increaseHatredDamageMultiplier(5)
+				logger.debug("Goshnar's Megalomania has increased its damage multiplier to 5.")
+			end
+		end
+	end, 120000, monsterCallback:getId())
+end
+
+mType:register(monster)
diff --git a/data-otservbr-global/monster/quests/soul_war/normal_monsters/megalomania_room/necromantic_focus.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/megalomania_room/necromantic_focus.lua
new file mode 100644
index 00000000000..53c607ace7f
--- /dev/null
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/megalomania_room/necromantic_focus.lua
@@ -0,0 +1,82 @@
+local mType = Game.createMonsterType("Necromantic Focus")
+local monster = {}
+
+monster.description = "a necromantic focus"
+monster.experience = 0
+monster.outfit = {
+	lookTypeEx = 7059,
+}
+
+monster.health = 12000
+monster.maxHealth = 12000
+monster.race = "undead"
+monster.corpse = 33984
+monster.speed = 0
+monster.manaCost = 100
+monster.maxSummons = 0
+
+monster.events = {
+	"NecromanticFocusDeath",
+}
+
+monster.changeTarget = {
+	interval = 4000,
+	chance = 0,
+}
+
+monster.strategiesTarget = {
+	nearest = 100,
+}
+
+monster.flags = {
+	summonable = false,
+	attackable = true,
+	hostile = true,
+	convinceable = false,
+	pushable = false,
+	rewardBoss = false,
+	illusionable = false,
+	canPushItems = true,
+	canPushCreatures = true,
+	staticAttackChance = 90,
+	targetDistance = 1,
+	runHealth = 0,
+	healthHidden = false,
+	isBlockable = false,
+	canWalkOnEnergy = false,
+	canWalkOnFire = false,
+	canWalkOnPoison = true,
+	pet = false,
+}
+
+monster.light = {
+	level = 0,
+	color = 0,
+}
+
+monster.defenses = {
+	defense = 55,
+	armor = 55,
+}
+
+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 = false },
+	{ type = "bleed", condition = false },
+}
+
+mType:register(monster)
diff --git a/data-otservbr-global/monster/undeads/mould_phantom.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/mould_phantom.lua
similarity index 98%
rename from data-otservbr-global/monster/undeads/mould_phantom.lua
rename to data-otservbr-global/monster/quests/soul_war/normal_monsters/mould_phantom.lua
index c3d7ea8ea86..54f3794360b 100644
--- a/data-otservbr-global/monster/undeads/mould_phantom.lua
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/mould_phantom.lua
@@ -26,6 +26,10 @@ monster.Bestiary = {
 	Locations = "Rotten Wasteland.",
 }
 
+monster.events = {
+	"FourthTaintBossesPrepareDeath",
+}
+
 monster.health = 28000
 monster.maxHealth = 28000
 monster.race = "undead"
diff --git a/data-otservbr-global/monster/undeads/paladin's_apparition.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/paladin's_apparition.lua
similarity index 98%
rename from data-otservbr-global/monster/undeads/paladin's_apparition.lua
rename to data-otservbr-global/monster/quests/soul_war/normal_monsters/paladin's_apparition.lua
index 066266e70e3..5162f5d1808 100644
--- a/data-otservbr-global/monster/undeads/paladin's_apparition.lua
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/paladin's_apparition.lua
@@ -33,6 +33,10 @@ monster.corpse = 111
 monster.speed = 235
 monster.manaCost = 0
 
+monster.events = {
+	"MirroredNightmareBossAccess",
+}
+
 monster.changeTarget = {
 	interval = 4000,
 	chance = 0,
diff --git a/data-otservbr-global/monster/constructs/rotten_golem.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/rotten_golem.lua
similarity index 98%
rename from data-otservbr-global/monster/constructs/rotten_golem.lua
rename to data-otservbr-global/monster/quests/soul_war/normal_monsters/rotten_golem.lua
index edc6f909a70..bf9ea5b7555 100644
--- a/data-otservbr-global/monster/constructs/rotten_golem.lua
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/rotten_golem.lua
@@ -26,6 +26,10 @@ monster.Bestiary = {
 	Locations = "Rotten Wasteland.",
 }
 
+monster.events = {
+	"FourthTaintBossesPrepareDeath",
+}
+
 monster.health = 28000
 monster.maxHealth = 28000
 monster.race = "venom"
diff --git a/data-otservbr-global/monster/undeads/sorcerer's_apparition.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/sorcerer's_apparition.lua
similarity index 98%
rename from data-otservbr-global/monster/undeads/sorcerer's_apparition.lua
rename to data-otservbr-global/monster/quests/soul_war/normal_monsters/sorcerer's_apparition.lua
index 8cf059be62c..c054a0d584f 100644
--- a/data-otservbr-global/monster/undeads/sorcerer's_apparition.lua
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/sorcerer's_apparition.lua
@@ -33,6 +33,10 @@ monster.corpse = 6081
 monster.speed = 235
 monster.manaCost = 0
 
+monster.events = {
+	"MirroredNightmareBossAccess",
+}
+
 monster.changeTarget = {
 	interval = 4000,
 	chance = 0,
diff --git a/data-otservbr-global/monster/elementals/turbulent_elemental.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/turbulent_elemental.lua
similarity index 98%
rename from data-otservbr-global/monster/elementals/turbulent_elemental.lua
rename to data-otservbr-global/monster/quests/soul_war/normal_monsters/turbulent_elemental.lua
index 3bef5da44e3..feaf706ae97 100644
--- a/data-otservbr-global/monster/elementals/turbulent_elemental.lua
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/turbulent_elemental.lua
@@ -26,6 +26,10 @@ monster.Bestiary = {
 	Locations = "Ebb and Flow.",
 }
 
+monster.events = {
+	"FourthTaintBossesPrepareDeath",
+}
+
 monster.health = 28000
 monster.maxHealth = 28000
 monster.race = "blood"
diff --git a/data-otservbr-global/monster/quests/soul_war/powerful_soul.lua b/data-otservbr-global/monster/quests/soul_war/powerful_soul.lua
new file mode 100644
index 00000000000..cee228f7185
--- /dev/null
+++ b/data-otservbr-global/monster/quests/soul_war/powerful_soul.lua
@@ -0,0 +1,115 @@
+local mType = Game.createMonsterType("Powerful Soul")
+local monster = {}
+
+monster.description = "a powerful soul"
+monster.experience = 0
+monster.outfit = {
+	lookType = 48,
+	lookHead = 0,
+	lookBody = 0,
+	lookLegs = 0,
+	lookFeet = 0,
+	lookAddons = 0,
+	lookMount = 0,
+}
+
+monster.health = 30000
+monster.maxHealth = 30000
+monster.race = "undead"
+monster.corpse = 0
+monster.speed = 80
+monster.manaCost = 0
+
+monster.events = {
+	"GreedMonsterDeath",
+}
+
+monster.changeTarget = {
+	interval = 1000,
+	chance = 0,
+}
+
+monster.strategiesTarget = {
+	nearest = 100,
+}
+
+monster.flags = {
+	summonable = false,
+	attackable = true,
+	hostile = true,
+	convinceable = false,
+	pushable = false,
+	rewardBoss = false,
+	illusionable = false,
+	canPushItems = true,
+	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.attacks = {
+	{ name = "melee", interval = 2000, chance = 100, minDamage = -2000, maxDamage = -3000 },
+	{ name = "combat", interval = 2000, chance = 15, type = COMBAT_LIFEDRAIN, minDamage = -2000, maxDamage = -3000, range = 1, effect = CONST_ME_MAGIC_RED, target = false },
+}
+
+monster.defenses = {
+	defense = 80,
+	armor = 90,
+	mitigation = 2,
+}
+
+monster.elements = {
+	{ type = COMBAT_PHYSICALDAMAGE, percent = 100 },
+	{ type = COMBAT_ENERGYDAMAGE, percent = 0 },
+	{ type = COMBAT_EARTHDAMAGE, percent = 100 },
+	{ type = COMBAT_FIREDAMAGE, percent = 0 },
+	{ type = COMBAT_LIFEDRAIN, percent = 100 },
+	{ type = COMBAT_MANADRAIN, percent = 0 },
+	{ type = COMBAT_DROWNDAMAGE, percent = 100 },
+	{ type = COMBAT_ICEDAMAGE, percent = 0 },
+	{ type = COMBAT_HOLYDAMAGE, percent = 0 },
+	{ type = COMBAT_DEATHDAMAGE, percent = 100 },
+}
+
+monster.immunities = {
+	{ type = "paralyze", condition = true },
+	{ type = "outfit", condition = false },
+	{ type = "invisible", condition = false },
+	{ type = "bleed", condition = false },
+}
+
+local transformTimeCount = 0
+mType.onThink = function(monster, interval)
+	transformTimeCount = transformTimeCount + interval
+	if transformTimeCount == 8000 then
+		CreateGoshnarsGreedMonster("Weak Soul", GreedMonsters[monster:getName()])
+		monster:remove()
+		local boss = Creature("Goshnar's Greed")
+		if boss then
+			for elementType, reflectPercent in pairs(SoulWarReflectDamageMap) do
+				boss:addReflectElement(elementType, reflectPercent)
+			end
+			boss:addDefense(10)
+			boss:setMaxHealth(boss:getHealth() + 10000)
+			boss:addHealth(10000)
+		end
+		transformTimeCount = 0
+	end
+end
+
+mType.onSpawn = function(monster)
+	transformTimeCount = 0
+end
+
+mType:register(monster)
diff --git a/data-otservbr-global/monster/quests/soul_war/soul_cage.lua b/data-otservbr-global/monster/quests/soul_war/soul_cage.lua
new file mode 100644
index 00000000000..c6c65b32547
--- /dev/null
+++ b/data-otservbr-global/monster/quests/soul_war/soul_cage.lua
@@ -0,0 +1,71 @@
+local mType = Game.createMonsterType("Soul Cage")
+local monster = {}
+
+monster.description = "a soul cage"
+monster.experience = 100000
+monster.outfit = {
+	lookType = 863,
+	lookHead = 0,
+	lookBody = 0,
+	lookLegs = 0,
+	lookFeet = 0,
+	lookAddons = 0,
+	lookMount = 0,
+}
+
+monster.health = 100000
+monster.maxHealth = 100000
+monster.race = "undead"
+monster.corpse = 0
+monster.speed = 0
+monster.manaCost = 0
+
+monster.flags = {
+	summonable = false,
+	attackable = true,
+	hostile = true,
+	convinceable = false,
+	pushable = false,
+	rewardBoss = false,
+	illusionable = false,
+	staticAttackChance = 90,
+	targetDistance = 1,
+	runHealth = 0,
+	healthHidden = false,
+	isBlockable = false,
+}
+
+monster.events = {
+	"SoulCageDeath",
+	"SoulCageHealthChange",
+}
+
+monster.light = {
+	level = 0,
+	color = 0,
+}
+
+monster.defenses = {
+	defense = 80,
+	armor = 100,
+	{ name = "Heal Malice", interval = 2000, chance = 90, target = false },
+}
+
+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 = "invisible", condition = true },
+}
+
+mType:register(monster)
diff --git a/data-otservbr-global/monster/quests/soul_war/soul_sphere.lua b/data-otservbr-global/monster/quests/soul_war/soul_sphere.lua
new file mode 100644
index 00000000000..c0142e3e611
--- /dev/null
+++ b/data-otservbr-global/monster/quests/soul_war/soul_sphere.lua
@@ -0,0 +1,109 @@
+local mType = Game.createMonsterType("Soul Sphere")
+local monster = {}
+
+monster.description = "a soul sphere"
+monster.experience = 0
+monster.outfit = {
+	lookType = 979,
+	lookHead = 0,
+	lookBody = 0,
+	lookLegs = 0,
+	lookFeet = 0,
+	lookAddons = 0,
+	lookMount = 0,
+}
+
+monster.health = 10000
+monster.maxHealth = 10000
+monster.corpse = 0
+monster.speed = 0
+monster.manaCost = 0
+
+monster.changeTarget = {
+	interval = 4000,
+	chance = 0,
+}
+
+monster.strategiesTarget = {
+	nearest = 100,
+}
+
+monster.flags = {
+	summonable = false,
+	attackable = true,
+	hostile = true,
+	convinceable = false,
+	pushable = false,
+	rewardBoss = false,
+	illusionable = false,
+	canPushItems = true,
+	canPushCreatures = true,
+	staticAttackChance = 90,
+	targetDistance = 1,
+	runHealth = 0,
+	healthHidden = false,
+	isBlockable = false,
+	canWalkOnEnergy = true,
+	canWalkOnFire = true,
+	canWalkOnPoison = true,
+}
+
+monster.light = {
+	level = 0,
+	color = 0,
+}
+
+monster.attacks = {
+	{ name = "melee", interval = 2000, chance = 100, minDamage = -500, maxDamage = -1000 },
+}
+
+monster.defenses = {
+	defense = 80,
+	armor = 90,
+	mitigation = 0.51,
+}
+
+monster.elements = {
+	{ type = COMBAT_PHYSICALDAMAGE, percent = 0 },
+	{ type = COMBAT_ENERGYDAMAGE, percent = 100 },
+	{ type = COMBAT_EARTHDAMAGE, percent = 0 },
+	{ type = COMBAT_FIREDAMAGE, percent = 0 },
+	{ type = COMBAT_LIFEDRAIN, percent = 100 },
+	{ type = COMBAT_MANADRAIN, percent = 0 },
+	{ type = COMBAT_DROWNDAMAGE, percent = 100 },
+	{ type = COMBAT_ICEDAMAGE, percent = 0 },
+	{ type = COMBAT_HOLYDAMAGE, percent = 0 },
+	{ type = COMBAT_DEATHDAMAGE, percent = 100 },
+}
+
+monster.immunities = {
+	{ type = "paralyze", condition = true },
+	{ type = "outfit", condition = false },
+	{ type = "invisible", condition = false },
+	{ type = "bleed", condition = false },
+}
+
+local moveTimeCount = 0
+mType.onThink = function(monster, interval)
+	moveTimeCount = moveTimeCount + interval
+	if moveTimeCount == 3000 then
+		monster:move(DIRECTION_WEST)
+		moveTimeCount = 0
+		local monsterPos = monster:getPosition()
+		local nextPos = Position(monsterPos.x - 1, monsterPos.y, monsterPos.z)
+		local tile = Tile(nextPos)
+		if not tile then
+			return
+		end
+
+		for _, creatureId in pairs(tile:getCreatures()) do
+			local monster = Monster(creatureId)
+			if monster and monster:getName() == "Goshnar's Greed" then
+				monster:setHealth(monster:getMaxHealth())
+				break
+			end
+		end
+	end
+end
+
+mType:register(monster)
diff --git a/data-otservbr-global/monster/quests/soul_war/soulsnatcher.lua b/data-otservbr-global/monster/quests/soul_war/soulsnatcher.lua
new file mode 100644
index 00000000000..faa819dec6e
--- /dev/null
+++ b/data-otservbr-global/monster/quests/soul_war/soulsnatcher.lua
@@ -0,0 +1,115 @@
+local mType = Game.createMonsterType("Soulsnatcher")
+local monster = {}
+
+monster.description = "a soulsnatcher"
+monster.experience = 0
+monster.outfit = {
+	lookType = 1268,
+	lookHead = 0,
+	lookBody = 94,
+	lookLegs = 0,
+	lookFeet = 0,
+	lookAddons = 0,
+	lookMount = 0,
+}
+
+monster.health = 10000
+monster.maxHealth = 10000
+monster.race = "undead"
+monster.corpse = 0
+monster.speed = 80
+monster.manaCost = 0
+
+monster.events = {
+	"GreedMonsterDeath",
+}
+
+monster.changeTarget = {
+	interval = 4000,
+	chance = 0,
+}
+
+monster.strategiesTarget = {
+	nearest = 100,
+}
+
+monster.flags = {
+	summonable = false,
+	attackable = true,
+	hostile = true,
+	convinceable = false,
+	pushable = false,
+	rewardBoss = false,
+	illusionable = true,
+	canPushItems = true,
+	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.attacks = {
+	{ name = "melee", interval = 2000, chance = 100, minDamage = -1000, maxDamage = -1500 },
+	{ name = "soulsnatcher-lifedrain-beam", interval = 2000, chance = 20, minDamage = -1000, maxDamage = -1500, target = false },
+	{ name = "soulsnatcher-lifedrain-missile", interval = 2000, chance = 25, minDamage = -1000, maxDamage = -1500, target = true },
+	{ name = "soulsnatcher-manadrain-ball", interval = 2000, chance = 30, minDamage = -500, maxDamage = -1000 },
+}
+
+monster.defenses = {
+	defense = 80,
+	armor = 90,
+	mitigation = 0.51,
+}
+
+monster.elements = {
+	{ type = COMBAT_PHYSICALDAMAGE, percent = 0 },
+	{ type = COMBAT_ENERGYDAMAGE, percent = 0 },
+	{ type = COMBAT_EARTHDAMAGE, percent = 100 },
+	{ type = COMBAT_FIREDAMAGE, percent = 0 },
+	{ type = COMBAT_LIFEDRAIN, percent = 100 },
+	{ type = COMBAT_MANADRAIN, percent = 0 },
+	{ type = COMBAT_DROWNDAMAGE, percent = 100 },
+	{ type = COMBAT_ICEDAMAGE, percent = 0 },
+	{ type = COMBAT_HOLYDAMAGE, percent = 0 },
+	{ type = COMBAT_DEATHDAMAGE, percent = 100 },
+}
+
+monster.immunities = {
+	{ type = "paralyze", condition = true },
+	{ type = "outfit", condition = false },
+	{ type = "invisible", condition = false },
+	{ type = "bleed", condition = false },
+}
+
+local transformTimeCount = 0
+mType.onThink = function(monster, interval)
+	transformTimeCount = transformTimeCount + interval
+	if transformTimeCount == 8000 then
+		transformTimeCount = 0
+		local zone = Zone("boss.goshnar's-greed")
+		if zone then
+			local players = zone:getPlayers()
+			for _, player in ipairs(players) do
+				player:addHealth(-math.random(500, 1000))
+			end
+		end
+		CreateGoshnarsGreedMonster(monster:getName(), GreedMonsters[monster:getName()])
+		monster:remove()
+	end
+end
+
+mType.onSpawn = function(monster)
+	transformTimeCount = 0
+end
+
+mType:register(monster)
diff --git a/data-otservbr-global/monster/quests/soul_war/spiteful_spitter.lua b/data-otservbr-global/monster/quests/soul_war/spiteful_spitter.lua
index 8b8cec55ccf..d51b52e2e84 100644
--- a/data-otservbr-global/monster/quests/soul_war/spiteful_spitter.lua
+++ b/data-otservbr-global/monster/quests/soul_war/spiteful_spitter.lua
@@ -99,4 +99,8 @@ monster.immunities = {
 	{ type = "bleed", condition = false },
 }
 
+mType.onThink = function(monster, interval)
+	monster:tryTeleportToPlayer("You have been chosen for a harvest!")
+end
+
 mType:register(monster)
diff --git a/data-otservbr-global/monster/quests/soul_war/strong_soul.lua b/data-otservbr-global/monster/quests/soul_war/strong_soul.lua
new file mode 100644
index 00000000000..3fb844d1f97
--- /dev/null
+++ b/data-otservbr-global/monster/quests/soul_war/strong_soul.lua
@@ -0,0 +1,106 @@
+local mType = Game.createMonsterType("Strong Soul")
+local monster = {}
+
+monster.description = "a strong soul"
+monster.experience = 0
+monster.outfit = {
+	lookType = 48,
+	lookHead = 0,
+	lookBody = 0,
+	lookLegs = 0,
+	lookFeet = 0,
+	lookAddons = 0,
+	lookMount = 0,
+}
+
+monster.health = 20000
+monster.maxHealth = 20000
+monster.race = "undead"
+monster.corpse = 0
+monster.speed = 80
+monster.manaCost = 0
+
+monster.events = {
+	"GreedMonsterDeath",
+}
+
+monster.changeTarget = {
+	interval = 1000,
+	chance = 0,
+}
+
+monster.strategiesTarget = {
+	nearest = 100,
+}
+
+monster.flags = {
+	summonable = false,
+	attackable = true,
+	hostile = true,
+	convinceable = false,
+	pushable = false,
+	rewardBoss = false,
+	illusionable = false,
+	canPushItems = true,
+	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.attacks = {
+	{ name = "melee", interval = 2000, chance = 100, minDamage = -1000, maxDamage = -2000 },
+	{ name = "combat", interval = 2000, chance = 15, type = COMBAT_LIFEDRAIN, minDamage = -1000, maxDamage = -2000, range = 1, effect = CONST_ME_MAGIC_RED, target = false },
+}
+
+monster.defenses = {
+	defense = 80,
+	armor = 90,
+	mitigation = 2,
+}
+
+monster.elements = {
+	{ type = COMBAT_PHYSICALDAMAGE, percent = 100 },
+	{ type = COMBAT_ENERGYDAMAGE, percent = 0 },
+	{ type = COMBAT_EARTHDAMAGE, percent = 100 },
+	{ type = COMBAT_FIREDAMAGE, percent = 0 },
+	{ type = COMBAT_LIFEDRAIN, percent = 100 },
+	{ type = COMBAT_MANADRAIN, percent = 0 },
+	{ type = COMBAT_DROWNDAMAGE, percent = 100 },
+	{ type = COMBAT_ICEDAMAGE, percent = 0 },
+	{ type = COMBAT_HOLYDAMAGE, percent = 0 },
+	{ type = COMBAT_DEATHDAMAGE, percent = 100 },
+}
+
+monster.immunities = {
+	{ type = "paralyze", condition = true },
+	{ type = "outfit", condition = false },
+	{ type = "invisible", condition = false },
+	{ type = "bleed", condition = false },
+}
+
+local transformTimeCount = 0
+mType.onThink = function(monster, interval)
+	transformTimeCount = transformTimeCount + interval
+	if transformTimeCount == 8000 then
+		Game.createMonster("Powerful Soul", GreedMonsters[monster:getName()], true, false)
+		monster:remove()
+		transformTimeCount = 0
+	end
+end
+
+mType.onSpawn = function(monster)
+	transformTimeCount = 0
+end
+
+mType:register(monster)
diff --git a/data-otservbr-global/monster/quests/soul_war/weak_soul.lua b/data-otservbr-global/monster/quests/soul_war/weak_soul.lua
new file mode 100644
index 00000000000..b7150efa00f
--- /dev/null
+++ b/data-otservbr-global/monster/quests/soul_war/weak_soul.lua
@@ -0,0 +1,106 @@
+local mType = Game.createMonsterType("Weak Soul")
+local monster = {}
+
+monster.description = "a weak soul"
+monster.experience = 0
+monster.outfit = {
+	lookType = 48,
+	lookHead = 0,
+	lookBody = 0,
+	lookLegs = 0,
+	lookFeet = 0,
+	lookAddons = 0,
+	lookMount = 0,
+}
+
+monster.health = 10000
+monster.maxHealth = 10000
+monster.race = "undead"
+monster.corpse = 0
+monster.speed = 80
+monster.manaCost = 0
+
+monster.events = {
+	"GreedMonsterDeath",
+}
+
+monster.changeTarget = {
+	interval = 4000,
+	chance = 0,
+}
+
+monster.strategiesTarget = {
+	nearest = 100,
+}
+
+monster.flags = {
+	summonable = false,
+	attackable = true,
+	hostile = true,
+	convinceable = false,
+	pushable = false,
+	rewardBoss = false,
+	illusionable = false,
+	canPushItems = true,
+	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.attacks = {
+	{ name = "melee", interval = 2000, chance = 100, minDamage = 0, maxDamage = -1000 },
+	{ name = "combat", interval = 2000, chance = 15, type = COMBAT_LIFEDRAIN, minDamage = -500, maxDamage = -1000, range = 1, effect = CONST_ME_MAGIC_RED, target = false },
+}
+
+monster.defenses = {
+	defense = 80,
+	armor = 90,
+	mitigation = 0.51,
+}
+
+monster.elements = {
+	{ type = COMBAT_PHYSICALDAMAGE, percent = 100 },
+	{ type = COMBAT_ENERGYDAMAGE, percent = 0 },
+	{ type = COMBAT_EARTHDAMAGE, percent = 100 },
+	{ type = COMBAT_FIREDAMAGE, percent = 0 },
+	{ type = COMBAT_LIFEDRAIN, percent = 100 },
+	{ type = COMBAT_MANADRAIN, percent = 0 },
+	{ type = COMBAT_DROWNDAMAGE, percent = 100 },
+	{ type = COMBAT_ICEDAMAGE, percent = 0 },
+	{ type = COMBAT_HOLYDAMAGE, percent = 0 },
+	{ type = COMBAT_DEATHDAMAGE, percent = 100 },
+}
+
+monster.immunities = {
+	{ type = "paralyze", condition = true },
+	{ type = "outfit", condition = false },
+	{ type = "invisible", condition = false },
+	{ type = "bleed", condition = false },
+}
+
+local transformTimeCount = 0
+mType.onThink = function(monster, interval)
+	transformTimeCount = transformTimeCount + interval
+	if transformTimeCount == 8000 then
+		Game.createMonster("Strong Soul", GreedMonsters[monster:getName()], true, false)
+		monster:remove()
+		transformTimeCount = 0
+	end
+end
+
+mType.onSpawn = function(monster)
+	transformTimeCount = 0
+end
+
+mType:register(monster)
diff --git a/data-otservbr-global/monster/quests/soul_war/weeping_soul.lua b/data-otservbr-global/monster/quests/soul_war/weeping_soul.lua
new file mode 100644
index 00000000000..3631fa3cb8e
--- /dev/null
+++ b/data-otservbr-global/monster/quests/soul_war/weeping_soul.lua
@@ -0,0 +1,91 @@
+local mType = Game.createMonsterType("Weeping Soul")
+local monster = {}
+
+monster.description = "a weeping soul"
+monster.experience = 0
+monster.outfit = {
+	lookType = 48,
+	lookHead = 0,
+	lookBody = 0,
+	lookLegs = 0,
+	lookFeet = 0,
+	lookAddons = 0,
+	lookMount = 0,
+}
+
+monster.health = 7000
+monster.maxHealth = 7000
+monster.race = "undead"
+monster.corpse = 33876
+monster.speed = 150
+monster.manaCost = 100
+monster.maxSummons = 0
+
+monster.changeTarget = {
+	interval = 4000,
+	chance = 15,
+}
+
+monster.strategiesTarget = {
+	nearest = 60,
+	health = 10,
+	damage = 10,
+	random = 20,
+}
+
+monster.flags = {
+	summonable = false,
+	attackable = true,
+	hostile = true,
+	convinceable = false,
+	pushable = false,
+	rewardBoss = false,
+	illusionable = false,
+	canPushItems = true,
+	canPushCreatures = true,
+	staticAttackChance = 90,
+	targetDistance = 1,
+	runHealth = 0,
+	healthHidden = false,
+	isBlockable = false,
+	canWalkOnEnergy = true,
+	canWalkOnFire = true,
+	canWalkOnPoison = true,
+	pet = false,
+}
+
+monster.light = {
+	level = 0,
+	color = 0,
+}
+
+monster.attacks = {
+	{ name = "melee", interval = 2000, chance = 100, minDamage = -220, maxDamage = -650 },
+}
+
+monster.defenses = {
+	defense = 55,
+	armor = 55,
+}
+
+monster.elements = {
+	{ type = COMBAT_PHYSICALDAMAGE, percent = 40 },
+	{ 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 = false },
+	{ type = "bleed", condition = false },
+}
+
+mType:register(monster)
diff --git a/data-otservbr-global/monster/undeads/hazardous_phantom.lua b/data-otservbr-global/monster/undeads/hazardous_phantom.lua
index 29384eafe55..4d3eb338b19 100644
--- a/data-otservbr-global/monster/undeads/hazardous_phantom.lua
+++ b/data-otservbr-global/monster/undeads/hazardous_phantom.lua
@@ -20,6 +20,10 @@ monster.corpse = 34125
 monster.speed = 100
 monster.manaCost = 0
 
+monster.events = {
+	"HazardousPhantomDeath",
+}
+
 monster.changeTarget = {
 	interval = 4000,
 	chance = 0,
diff --git a/data-otservbr-global/npc/flickering_soul.lua b/data-otservbr-global/npc/flickering_soul.lua
new file mode 100644
index 00000000000..a6e11c311c6
--- /dev/null
+++ b/data-otservbr-global/npc/flickering_soul.lua
@@ -0,0 +1,195 @@
+local internalNpcName = "Flickering Soul"
+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 = 1219,
+	lookHead = 6,
+	lookBody = 26,
+	lookLegs = 26,
+	lookFeet = 6,
+	lookAddons = 0,
+	lookMount = 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, player)
+	npcHandler:onAppear(npc, player)
+end
+
+npcType.onDisappear = function(npc, player)
+	npcHandler:onDisappear(npc, player)
+end
+
+npcType.onMove = function(npc, player, fromPosition, toPosition)
+	npcHandler:onMove(npc, player, fromPosition, toPosition)
+end
+
+npcType.onSay = function(npc, player, type, message)
+	npcHandler:onSay(npc, player, type, message)
+end
+
+npcType.onCloseChannel = function(npc, player)
+	npcHandler:onCloseChannel(npc, player)
+end
+
+local function playerSayCallback(npc, player, type, message)
+	if not npcHandler:checkInteraction(npc, player) then
+		return false
+	end
+
+	local soulWarQuest = player:soulWarQuestKV()
+
+	local playerId = player:getId()
+	if MsgContains(message, "living") then
+		npcHandler:say("It has been a while since I roamed the world of the living in a mortal shell.", npc, player)
+	elseif MsgContains(message, "mortal") then
+		npcHandler:say("I had many names in my live. The one that would be the most recognizable is probably the name Goshnar. Even that was an assumed name that I took when I left my mundane past behind.", npc, player)
+	elseif MsgContains(message, "Goshnar") then
+		npcHandler:say({
+			"I was once known as the necromant king. ...",
+			"For some it was meant as a curse, others used the name with reverence. To me it was just another stepping stone, in a life that burned with ambition.",
+		}, npc, player, 4000)
+	elseif MsgContains(message, "ambition") then
+		npcHandler:say({
+			"My ambitions were high and knew no limits. Mastery over life and death was but a milestone that I wanted to accomplish. In the end I aspired probably somewhat like godhood. ...",
+			"Though in hindsight even that wouldn't have been enough. There was a hunger in me that nothing could put to rest.",
+		}, npc, player, 4000)
+	elseif MsgContains(message, "milestone") then
+		npcHandler:say("Everything in my life was just a tool to further my goals. The brotherhood of bones was just a tool for me. As was everyone or everything. In the path I had chosen nothing mattered but me and my ambitions.", npc, player)
+	elseif MsgContains(message, "everything") then
+		npcHandler:say("Necromancy was a passion at first, another tool while I amassed power and a crutch when my ambitions surpassed that what it could accomplish.", npc, player)
+	elseif MsgContains(message, "accomplish") then
+		npcHandler:say({
+			"I was so convinced about my brilliance, my greatness, my destiny. And this hunger for more, it let me not have peace at any point in my life. I was always driven. There was no time to rest. ...",
+			"And there was no looking back. I never cared to remember my humble beginnings, what I had sacrificed to get where I was. All that I had left behind and that I had lost forever. ...",
+			"Now I see the bitter irony. I could bring back the dead, but I couldn't create second chances. I couldn't restore the truly important things that I had lost.",
+		}, npc, player, 4000)
+	elseif MsgContains(message, "dead") then
+		npcHandler:say("My demise did not meet me unprepared. As a powerful necromancer I had fettered my soul in the living world and the realms beyond. I had prepared for my return and was confident in my power.", npc, player)
+	elseif MsgContains(message, "confident") then
+		npcHandler:say("My soul wandered the plains of Zarganash, waiting for my wards to power up. Waiting for my soul to be slowly pulled back and manifest in the world of the living once again. What I had not taken into consideration was peace.", npc, player)
+	elseif MsgContains(message, "peace") then
+		npcHandler:say({
+			"Zarganash was not a place without its dangers, but for a soul as powerful as mine, there was little threat at all. For the first time in my existence I had to stop running forward. I had to wait for things to fit into their places. ...",
+			"And me, who had seen things that horrible, they would have obliterated a lesser man's mind, finally took the time to look back. And what I saw was frightening in its own right. ...",
+			"A great tiredness overcame me. With the flames of my ambitions calming down for the first time since I could remember, all my aspirations and plans seemed to petty and futile. ...",
+			"Everything I had worked for and my plans for the things to come seemed pointless, and the things I had lost and never allowed myself to experience weighed heavily on my soul.",
+		}, npc, player, 4000)
+	elseif MsgContains(message, "soul") then
+		npcHandler:say({
+			"I talked to other souls, lost in Zarganash, and most of them seemed like mirrors to myself. Their faults, their shortcomings, the things that were important to them and the things they had lost. ...",
+			"It was all like miniature copies of my own grand plans and losses. It made me think. And the great tiredness weighed even more heavy on me. A weariness of the world, of the hunger that drove me.",
+		}, npc, player, 4000)
+	elseif MsgContains(message, "weariness") then
+		npcHandler:say({
+			"Then I met a wise soul. A teacher that did not lecture. I never was impressed by anything but my own accomplishments. But the inner balance and peace of this soul, it did impress me. A lot. ...",
+			"I, who fancied myself to have been the epitome of knowledge, learned things that were entirely new to me. But this knowledge wasn't about power. It was about me.",
+		}, npc, player, 4000)
+	elseif MsgContains(message, "knowledge") then
+		npcHandler:say("I recognized the extent of my folly and failure. I decided not to return to the world of the living.", npc, player)
+	elseif MsgContains(message, "return") then
+		npcHandler:say({
+			"I decided to stay here, even pass on into the great beyond at some point. Yet I still feel the pull of my fetters. I can faintly hear those who think they are my followers, calling to me.",
+			"And I feel others, many others who crave my powers and try to bring me back for their own gain.",
+		}, npc, player, 4000)
+	elseif MsgContains(message, "fetters") then
+		npcHandler:say({
+			"Over my time in Zarganash I split away the parts of me that my worldly fetters were bound to. Yet I had to recognize that they are still a part of me and I'm bound to them. ...",
+			"The fetters and the efforts to call me back are empowering them. I feel them growing in strength and gaining awareness on their own. ...",
+			"They are beginning to feed not only on the fetters and incarnations but also on me. As I grow weaker, they grow more powerful over time.",
+		}, npc, player, 4000)
+	elseif MsgContains(message, "powerful") then
+		npcHandler:say("The only way I can get rid of them is to disperse them, to 'kill' them so to say. But they are tainted parts of myself and even going near them might endanger my sanity and stability. So all I can do is to ask you to do this daunting task.", npc, player)
+	elseif MsgContains(message, "task") then
+		local soulWarQuest = player:soulWarQuestKV()
+		-- Checks if the boss has already been defeated
+		if soulWarQuest:get("goshnar's-megalomania-killed") then
+			npcHandler:say({
+				"You did it! For the first time I can feel free from the pull of my past. Now I'm free at last. ...",
+				"I might stay a while and teach other souls about the inner peace, but will eventually pass on. Thank you so much, my hero. My eternal gratitude and blessings will be with you!",
+			}, npc, player, 2000)
+			npcHandler:setTopic(playerId, 2)
+			player:addOutfit("Revenant")
+		else
+			npcHandler:say("I'm aware I have no right to ask and I have little to offer as a payment, but I ask you nonetheless. Will you face my fettered vices and destroy them for me?", npc, player)
+			npcHandler:setTopic(playerId, 1)
+		end
+	elseif MsgContains(message, "yes") and npcHandler:getTopic(playerId) == 1 then
+		npcHandler:say("Thank you for accepting this burden.", npc, player)
+		soulWarQuest:set("teleport-access", true)
+	elseif MsgContains(message, "burden") then
+		npcHandler:say({
+			"You will have to reach each of the negative parts of my personality that I split away. They are hidden deep in the depths of Zarganash and will have corrupted and twisted their surroundings into dangerous nightmares. ...",
+			"Even worse, you'll likely encounter minions of those who want to claim my soul as their prize for their own depraved reasons. You will have to destroy my shards to set me free.",
+		}, npc, player, 5000)
+	elseif MsgContains(message, "shards") then
+		npcHandler:say("You haven't killed Malice yet. You haven't killed Hatred yet. You haven't killed Spite yet. You haven't killed Cruelty yet. You haven't killed Greed yet.", npc, player)
+	elseif MsgContains(message, "hate") then
+		npcHandler:say({
+			"I hated the world for its flaws and the reluctance of people to comply with my will. I was convinced I was destined for greatness and to change everything. Ordinary beings were far beneath me and my consideration. ...",
+			"All this opposition, all the wars were a nuisance on my way to greatness. I would have sacrificed the whole world to reach my goals.",
+		}, npc, player, 4000)
+	elseif MsgContains(message, "fermuba") then
+		npcHandler:say("My daughter was as ambitious as me, yet she lacked my intellect and my raw talent. She still was great and talented yet I sadly let her feel my disdain. One of the many errors that my way of hubris made me do.", npc, player)
+	elseif MsgContains(message, "ferumbras") then
+		npcHandler:say({
+			"Even in the lands of the dead, this one caused a stir. The dead were whispering his name. It made me feel jealous and angry at first, but at some point, after much self-reflection, I could recognize my own faults in the stories about him.",
+			"It was almost like looking into a mirror for the first time. However, he lived way later than me, and I never met his soul here, so I can't tell more about him.",
+		}, npc, player, 4000)
+	elseif MsgContains(message, "grandson") then
+		npcHandler:say(" I'm not aware of the fate of my linage. Neither I'm able to relate to the mortal world in that way. Each of us is an individual, not bound by ties of blood or herritage.", npc, player)
+	elseif MsgContains(message, "pale worm") then
+		npcHandler:say("His avatar might be destroyed for now and it'd grip on Zarganash considerably weakened. Yet he burrowed to deep into the essence of this realm to be annihilated this easy.", npc, player)
+	elseif MsgContains(message, "necromant king") then
+		npcHandler:say({
+			"They called me the necromant king, in an act of reverence, but to me it was always more of a slander. To limit my greatness to this insignificant aspect was an insult to my ego. But I let it slip for the greater good. ...",
+			"I felt it was beneath me to correct them and I went along.",
+		}, npc, player, 4000)
+	elseif MsgContains(message, "minions") or MsgContains(message, "followers") then
+		npcHandler:say("I despised my followers for their petty agendas and for their limited vision of my own goals and personality.", npc, player)
+	elseif MsgContains(message, "shards") then
+		local bossesYetToDefeat = {}
+		for bossName, _ in pairs(SoulWarBosses) do
+			if not soulWarQuest:get(bossName) then
+				table.insert(bossesYetToDefeat, bossName)
+			end
+		end
+
+		local message
+		if #bossesYetToDefeat > 0 then
+			message = "You haven't killed " .. table.concat(bossesYetToDefeat, ", ") .. " yet."
+		else
+			message = "You have defeated all the Goshnar's Bosses. Your soul shines brighter with each victory."
+		end
+		npcHandler:say(message, npc, player)
+	end
+	return true
+end
+
+npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, playerSayCallback)
+
+npcHandler:setMessage(MESSAGE_GREET, "Be greeted, living soul!")
+
+npcHandler:addModule(FocusModule:new(), npcConfig.name, true, true, true)
+
+-- npcType registering the npcConfig table
+npcType:register(npcConfig)
diff --git a/data-otservbr-global/scripts/actions/bosses_levers/goshnar_cruelty.lua b/data-otservbr-global/scripts/actions/bosses_levers/goshnar_cruelty.lua
deleted file mode 100644
index 2e01880589d..00000000000
--- a/data-otservbr-global/scripts/actions/bosses_levers/goshnar_cruelty.lua
+++ /dev/null
@@ -1,23 +0,0 @@
-local config = {
-	boss = {
-		name = "Goshnar's Cruelty",
-		position = Position(33856, 31866, 7),
-	},
-	requiredLevel = 250,
-	playerPositions = {
-		{ pos = Position(33854, 31854, 6), teleport = Position(33856, 31872, 7), effect = CONST_ME_TELEPORT },
-		{ pos = Position(33855, 31854, 6), teleport = Position(33856, 31872, 7), effect = CONST_ME_TELEPORT },
-		{ pos = Position(33856, 31854, 6), teleport = Position(33856, 31872, 7), effect = CONST_ME_TELEPORT },
-		{ pos = Position(33857, 31854, 6), teleport = Position(33856, 31872, 7), effect = CONST_ME_TELEPORT },
-		{ pos = Position(33858, 31854, 6), teleport = Position(33856, 31872, 7), effect = CONST_ME_TELEPORT },
-	},
-	specPos = {
-		from = Position(33847, 31858, 7),
-		to = Position(33864, 31874, 7),
-	},
-	exit = Position(33621, 31427, 10),
-}
-
-local lever = BossLever(config)
-lever:position({ x = 33853, y = 31854, z = 6 })
-lever:register()
diff --git a/data-otservbr-global/scripts/actions/bosses_levers/goshnar_greed.lua b/data-otservbr-global/scripts/actions/bosses_levers/goshnar_greed.lua
deleted file mode 100644
index 522cde76845..00000000000
--- a/data-otservbr-global/scripts/actions/bosses_levers/goshnar_greed.lua
+++ /dev/null
@@ -1,23 +0,0 @@
-local config = {
-	boss = {
-		name = "Goshnar's Greed",
-		position = Position(33746, 31666, 14),
-	},
-	requiredLevel = 250,
-	playerPositions = {
-		{ pos = Position(33776, 31665, 14), teleport = Position(33747, 31671, 14), effect = CONST_ME_TELEPORT },
-		{ pos = Position(33777, 31665, 14), teleport = Position(33747, 31671, 14), effect = CONST_ME_TELEPORT },
-		{ pos = Position(33778, 31665, 14), teleport = Position(33747, 31671, 14), effect = CONST_ME_TELEPORT },
-		{ pos = Position(33779, 31665, 14), teleport = Position(33747, 31671, 14), effect = CONST_ME_TELEPORT },
-		{ pos = Position(33780, 31665, 14), teleport = Position(33747, 31671, 14), effect = CONST_ME_TELEPORT },
-	},
-	specPos = {
-		from = Position(33737, 31658, 14),
-		to = Position(33755, 31673, 14),
-	},
-	exit = Position(33621, 31427, 10),
-}
-
-local lever = BossLever(config)
-lever:position({ x = 33775, y = 31665, z = 14 })
-lever:register()
diff --git a/data-otservbr-global/scripts/actions/bosses_levers/goshnar_hatred.lua b/data-otservbr-global/scripts/actions/bosses_levers/goshnar_hatred.lua
deleted file mode 100644
index 963404c8d85..00000000000
--- a/data-otservbr-global/scripts/actions/bosses_levers/goshnar_hatred.lua
+++ /dev/null
@@ -1,23 +0,0 @@
-local config = {
-	boss = {
-		name = "Goshnar's Hatred",
-		position = Position(33744, 31599, 14),
-	},
-	requiredLevel = 250,
-	playerPositions = {
-		{ pos = Position(33773, 31601, 14), teleport = Position(33743, 31604, 14), effect = CONST_ME_TELEPORT },
-		{ pos = Position(33774, 31601, 14), teleport = Position(33743, 31604, 14), effect = CONST_ME_TELEPORT },
-		{ pos = Position(33775, 31601, 14), teleport = Position(33743, 31604, 14), effect = CONST_ME_TELEPORT },
-		{ pos = Position(33776, 31601, 14), teleport = Position(33743, 31604, 14), effect = CONST_ME_TELEPORT },
-		{ pos = Position(33777, 31601, 14), teleport = Position(33743, 31604, 14), effect = CONST_ME_TELEPORT },
-	},
-	specPos = {
-		from = Position(33735, 31592, 14),
-		to = Position(33751, 31606, 14),
-	},
-	exit = Position(33621, 31427, 10),
-}
-
-local lever = BossLever(config)
-lever:position({ x = 33772, y = 31601, z = 14 })
-lever:register()
diff --git a/data-otservbr-global/scripts/actions/bosses_levers/goshnar_malice.lua b/data-otservbr-global/scripts/actions/bosses_levers/goshnar_malice.lua
deleted file mode 100644
index 44d102ad598..00000000000
--- a/data-otservbr-global/scripts/actions/bosses_levers/goshnar_malice.lua
+++ /dev/null
@@ -1,23 +0,0 @@
-local config = {
-	boss = {
-		name = "Goshnar's Malice",
-		position = Position(33710, 31599, 14),
-	},
-	requiredLevel = 250,
-	playerPositions = {
-		{ pos = Position(33679, 31599, 14), teleport = Position(33710, 31605, 14), effect = CONST_ME_TELEPORT },
-		{ pos = Position(33680, 31599, 14), teleport = Position(33710, 31605, 14), effect = CONST_ME_TELEPORT },
-		{ pos = Position(33681, 31599, 14), teleport = Position(33710, 31605, 14), effect = CONST_ME_TELEPORT },
-		{ pos = Position(33682, 31599, 14), teleport = Position(33710, 31605, 14), effect = CONST_ME_TELEPORT },
-		{ pos = Position(33683, 31599, 14), teleport = Position(33710, 31605, 14), effect = CONST_ME_TELEPORT },
-	},
-	specPos = {
-		from = Position(33699, 31590, 14),
-		to = Position(33718, 31607, 14),
-	},
-	exit = Position(33621, 31427, 10),
-}
-
-local lever = BossLever(config)
-lever:position({ x = 33678, y = 31599, z = 14 })
-lever:register()
diff --git a/data-otservbr-global/scripts/actions/bosses_levers/goshnar_megalomania.lua b/data-otservbr-global/scripts/actions/bosses_levers/goshnar_megalomania.lua
deleted file mode 100644
index 5896faa74c4..00000000000
--- a/data-otservbr-global/scripts/actions/bosses_levers/goshnar_megalomania.lua
+++ /dev/null
@@ -1,23 +0,0 @@
-local config = {
-	boss = {
-		name = "Goshnar's Megalomania",
-		position = Position(33710, 31634, 14),
-	},
-	requiredLevel = 250,
-	playerPositions = {
-		{ pos = Position(33676, 31634, 14), teleport = Position(33710, 31639, 14), effect = CONST_ME_TELEPORT },
-		{ pos = Position(33677, 31634, 14), teleport = Position(33710, 31639, 14), effect = CONST_ME_TELEPORT },
-		{ pos = Position(33678, 31634, 14), teleport = Position(33710, 31639, 14), effect = CONST_ME_TELEPORT },
-		{ pos = Position(33679, 31634, 14), teleport = Position(33710, 31639, 14), effect = CONST_ME_TELEPORT },
-		{ pos = Position(33680, 31634, 14), teleport = Position(33710, 31639, 14), effect = CONST_ME_TELEPORT },
-	},
-	specPos = {
-		from = Position(33701, 31626, 14),
-		to = Position(33719, 31642, 14),
-	},
-	exit = Position(33621, 31427, 10),
-}
-
-local lever = BossLever(config)
-lever:position({ x = 33675, y = 31634, z = 14 })
-lever:register()
diff --git a/data-otservbr-global/scripts/actions/bosses_levers/goshnar_spite.lua b/data-otservbr-global/scripts/actions/bosses_levers/goshnar_spite.lua
deleted file mode 100644
index 0fd2396ae03..00000000000
--- a/data-otservbr-global/scripts/actions/bosses_levers/goshnar_spite.lua
+++ /dev/null
@@ -1,23 +0,0 @@
-local config = {
-	boss = {
-		name = "Goshnar's Spite",
-		position = Position(33743, 31632, 14),
-	},
-	requiredLevel = 250,
-	playerPositions = {
-		{ pos = Position(33774, 31634, 14), teleport = Position(33742, 31639, 14), effect = CONST_ME_TELEPORT },
-		{ pos = Position(33775, 31634, 14), teleport = Position(33742, 31639, 14), effect = CONST_ME_TELEPORT },
-		{ pos = Position(33776, 31634, 14), teleport = Position(33742, 31639, 14), effect = CONST_ME_TELEPORT },
-		{ pos = Position(33777, 31634, 14), teleport = Position(33742, 31639, 14), effect = CONST_ME_TELEPORT },
-		{ pos = Position(33778, 31634, 14), teleport = Position(33742, 31639, 14), effect = CONST_ME_TELEPORT },
-	},
-	specPos = {
-		from = Position(33734, 31624, 14),
-		to = Position(33751, 31640, 14),
-	},
-	exit = Position(33621, 31427, 10),
-}
-
-local lever = BossLever(config)
-lever:position({ x = 33773, y = 31634, z = 14 })
-lever:register()
diff --git a/data-otservbr-global/scripts/actions/quests/soul_war/bosses_killed.lua b/data-otservbr-global/scripts/actions/quests/soul_war/bosses_killed.lua
deleted file mode 100644
index de4b8ae182f..00000000000
--- a/data-otservbr-global/scripts/actions/quests/soul_war/bosses_killed.lua
+++ /dev/null
@@ -1,24 +0,0 @@
-local bosses = {
-	["goshnar's malice"] = { storage = Storage.Quest.U12_40.SoulWar.GoshnarMaliceKilled },
-	["goshnar's hatred"] = { storage = Storage.Quest.U12_40.SoulWar.GoshnarHatredKilled },
-	["goshnar's spite"] = { storage = Storage.Quest.U12_40.SoulWar.GoshnarSpiteKilled },
-	["goshnar's cruelty"] = { storage = Storage.Quest.U12_40.SoulWar.GoshnarCrueltyKilled },
-	["goshnar's greed"] = { storage = Storage.Quest.U12_40.SoulWar.GoshnarGreedKilled },
-	["goshnar's megalomania"] = { storage = Storage.Quest.U12_40.SoulWar.GoshnarMegalomaniaKilled },
-}
-
-local bossesSoulWar = CreatureEvent("SoulwarsBossDeath")
-function bossesSoulWar.onDeath(creature)
-	local bossConfig = bosses[creature:getName():lower()]
-	if not bossConfig then
-		return true
-	end
-	onDeathForDamagingPlayers(creature, function(creature, player)
-		if bossConfig.storage then
-			player:setStorageValue(bossConfig.storage, 1)
-		end
-	end)
-	return true
-end
-
-bossesSoulWar:register()
diff --git a/data-otservbr-global/scripts/actions/quests/soul_war/portal_megalomania.lua b/data-otservbr-global/scripts/actions/quests/soul_war/portal_megalomania.lua
deleted file mode 100644
index 41d3763c1c7..00000000000
--- a/data-otservbr-global/scripts/actions/quests/soul_war/portal_megalomania.lua
+++ /dev/null
@@ -1,38 +0,0 @@
-local storagesTable = {
-	{ storage = Storage.Quest.U12_40.SoulWar.GoshnarMaliceKilled, bossName = "Goshnar's Malice" },
-	{ storage = Storage.Quest.U12_40.SoulWar.GoshnarHatredKilled, bossName = "Goshnar's Hatred" },
-	{ storage = Storage.Quest.U12_40.SoulWar.GoshnarSpiteKilled, bossName = "Goshnar's Spite" },
-	{ storage = Storage.Quest.U12_40.SoulWar.GoshnarCrueltyKilled, bossName = "Goshnar's Cruelty" },
-	{ storage = Storage.Quest.U12_40.SoulWar.GoshnarGreedKilled, bossName = "Goshnar's Greed" },
-}
-
-local portalMegalomania = MoveEvent()
-function portalMegalomania.onStepIn(creature, item, position, fromPosition)
-	local player = creature:getPlayer()
-	if not player then
-		return false
-	end
-	if player:getLevel() < 250 then
-		player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You need at least level 250 to enter.")
-		player:teleportTo(fromPosition, true)
-		player:getPosition():sendMagicEffect(CONST_ME_TELEPORT)
-		return false
-	end
-	local text = ""
-	for value in pairs(storagesTable) do
-		if player:getStorageValue(storagesTable[value].storage) < 0 then
-			text = text .. "\n" .. storagesTable[value].bossName
-		end
-	end
-	if text == "" then
-		return true
-	else
-		player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You still need to defeat:" .. text)
-		player:teleportTo(fromPosition, true)
-		return false
-	end
-end
-
-portalMegalomania:type("stepin")
-portalMegalomania:position({ x = 33611, y = 31430, z = 10 })
-portalMegalomania:register()
diff --git a/data-otservbr-global/scripts/actions/quests/soul_war/reward_soul_war.lua b/data-otservbr-global/scripts/actions/quests/soul_war/reward_soul_war.lua
deleted file mode 100644
index 1e3c9c773e0..00000000000
--- a/data-otservbr-global/scripts/actions/quests/soul_war/reward_soul_war.lua
+++ /dev/null
@@ -1,89 +0,0 @@
-local rewards = {
-	{ id = 34082, name = "Soulcutter" },
-	{ id = 34083, name = "Soulshredder" },
-	{ id = 34084, name = "Soulbiter" },
-	{ id = 34085, name = "Souleater" },
-	{ id = 34086, name = "Soulcrusher" },
-	{ id = 34087, name = "Soulmaimer" },
-	{ id = 34088, name = "Soulbleeder" },
-	{ id = 34089, name = "Soulpiercer" },
-	{ id = 34090, name = "Soultainter" },
-	{ id = 34091, name = "Soulhexer" },
-	{ id = 34092, name = "Soulshanks" },
-	{ id = 34093, name = "Soulstrider" },
-	{ id = 34094, name = "Soulshell" },
-	{ id = 34095, name = "Soulmantel" },
-	{ id = 34096, name = "Soulshroud" },
-	{ id = 34097, name = "Pair of Soulwalkers" },
-	{ id = 34098, name = "Pair of Soulstalkers" },
-	{ id = 34099, name = "Soulbastion" },
-}
-local outfits = { 1322, 1323 }
-
-local function addOutfits(player)
-	if player:getStorageValue(Storage.Quest.U12_40.SoulWar.OutfitReward) < 0 then
-		player:addOutfit(outfits[1], 0)
-		player:addOutfit(outfits[2], 0)
-		player:setStorageValue(Storage.Quest.U12_40.SoulWar.OutfitReward, 1)
-		player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Congratulations you received the Revenant Outfit.")
-	end
-end
-
-local rewardSoulWar = Action()
-function rewardSoulWar.onUse(creature, item, fromPosition, target, toPosition, isHotkey)
-	local randId = math.random(1, #rewards)
-	local rewardItem = rewards[randId]
-	local player = creature:getPlayer()
-	if not player then
-		return false
-	end
-	if player:getStorageValue(Storage.Quest.U12_40.SoulWar.QuestReward) < 0 then
-		player:addItem(rewardItem.id, 1)
-		player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have found a " .. rewardItem.name .. ".")
-		player:setStorageValue(Storage.Quest.U12_40.SoulWar.QuestReward, 1)
-		addOutfits(player)
-		return true
-	else
-		addOutfits(player)
-		player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have already collected your reward")
-		return false
-	end
-end
-
-rewardSoulWar:position({ x = 33620, y = 31400, z = 10 })
-rewardSoulWar:register()
-
------------------------------
--- Phantasmal Jade Mount function
-
-local phantasmalJadeMount = Action()
-function phantasmalJadeMount.onUse(player, item, fromPosition, target, toPosition, isHotkey)
-	local storage = Storage.Quest.U12_40.SoulWar.MountReward
-	if player:getStorageValue(storage) == 1 then
-		player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You already have Phantasmal Jade mount!")
-		return false
-	end
-
-	if table.contains({ 34072, 34073, 34074 }, item.itemid) then
-		-- check items
-		if player:getItemCount(34072) >= 4 and player:getItemCount(34073) == 1 and player:getItemCount(34074) == 1 then
-			player:removeItem(34072, 4)
-			player:removeItem(34073, 1)
-			player:removeItem(34074, 1)
-			player:addMount(167)
-			player:setStorageValue(storage, 1)
-			player:addAchievement("You got Horse Power")
-			player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Congratulations! You won Phantasmal Jade mount.")
-			player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Congratulations! You won You got Horse Power achievement.")
-			player:getPosition():sendMagicEffect(CONST_ME_HOLYDAMAGE)
-			return true
-		else
-			player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You don't have the necessary items!")
-			player:getPosition():sendMagicEffect(CONST_ME_POFF)
-			return false
-		end
-	end
-end
-
-phantasmalJadeMount:id(34072, 34073, 34074)
-phantasmalJadeMount:register()
diff --git a/data-otservbr-global/scripts/actions/quests/soul_war/soulwar_entrances.lua b/data-otservbr-global/scripts/actions/quests/soul_war/soulwar_entrances.lua
deleted file mode 100644
index 51f8281a04d..00000000000
--- a/data-otservbr-global/scripts/actions/quests/soul_war/soulwar_entrances.lua
+++ /dev/null
@@ -1,63 +0,0 @@
-local config = {
-	{ position = { x = 33615, y = 31422, z = 10 }, destination = { x = 34009, y = 31014, z = 9 } }, -- hunt infernal demon
-	{ position = { x = 33618, y = 31422, z = 10 }, destination = { x = 33972, y = 31041, z = 11 } }, -- hunt rotten
-	{ position = { x = 33621, y = 31422, z = 10 }, destination = { x = 33894, y = 31019, z = 8 } }, -- hunt bony sea devil
-	{ position = { x = 33624, y = 31422, z = 10 }, destination = { x = 33858, y = 31831, z = 3 } }, -- hunt cloak
-	{ position = { x = 33627, y = 31422, z = 10 }, destination = { x = 33887, y = 31188, z = 10 } }, -- hunt many faces
-	{ position = { x = 33950, y = 31109, z = 8 }, destination = { x = 33780, y = 31634, z = 14 } }, -- goshnar's spite entrance
-	{ position = { x = 33937, y = 31217, z = 11 }, destination = { x = 33782, y = 31665, z = 14 } }, -- goshnar's greed entrance
-	{ position = { x = 34022, y = 31091, z = 11 }, destination = { x = 33685, y = 31599, z = 14 } }, -- goshnar's malice entrance
-	{ position = { x = 33856, y = 31884, z = 5 }, destination = { x = 33857, y = 31865, z = 6 } }, -- goshnar's cruelty entrance
-	{ position = { x = 33889, y = 31873, z = 3 }, destination = { x = 33830, y = 31881, z = 4 } }, -- 1st to 2nd floor cloak
-	{ position = { x = 33829, y = 31880, z = 4 }, destination = { x = 33856, y = 31889, z = 5 } }, -- 2nd to 3rd floor cloak
-}
-
-local portal = { position = { x = 33914, y = 31032, z = 12 }, destination = { x = 33780, y = 31601, z = 14 } } -- goshnar's hatred entrance
-
-local soulWarEntrances = MoveEvent()
-function soulWarEntrances.onStepIn(creature, item, position, fromPosition)
-	local player = creature:getPlayer()
-	if not player then
-		return false
-	end
-	if player:getLevel() < 250 then
-		player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You need at least level 250 to enter.")
-		player:teleportTo(fromPosition, true)
-		player:getPosition():sendMagicEffect(CONST_ME_TELEPORT)
-		return false
-	end
-	for value in pairs(config) do
-		if Position(config[value].position) == player:getPosition() then
-			player:teleportTo(Position(config[value].destination))
-			player:getPosition():sendMagicEffect(CONST_ME_TELEPORT)
-			return true
-		end
-	end
-end
-
-soulWarEntrances:type("stepin")
-for value in pairs(config) do
-	soulWarEntrances:position(config[value].position)
-end
-soulWarEntrances:register()
-
-local portalHatred = Action()
-function portalHatred.onUse(creature, item, position, fromPosition)
-	local player = creature:getPlayer()
-	if not player then
-		return false
-	end
-	if player:getLevel() < 250 then
-		player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You need at least level 250 to enter.")
-		player:teleportTo(fromPosition, true)
-		player:getPosition():sendMagicEffect(CONST_ME_TELEPORT)
-		return false
-	end
-	doSendMagicEffect(item:getPosition(), CONST_ME_TELEPORT)
-	player:teleportTo(Position(portal.destination))
-	player:getPosition():sendMagicEffect(CONST_ME_TELEPORT)
-	return true
-end
-
-portalHatred:position(portal.position)
-portalHatred:register()
diff --git a/data-otservbr-global/scripts/lib/quests/soul-war.lua b/data-otservbr-global/scripts/lib/quests/soul-war.lua
new file mode 100644
index 00000000000..ba44d49943f
--- /dev/null
+++ b/data-otservbr-global/scripts/lib/quests/soul-war.lua
@@ -0,0 +1,1343 @@
+SoulWarQuest = {
+	-- Item ids
+	-- Goshnar's Hatred
+	bagYouDesireItemId = 34109,
+	goshnarsHatredSorrowId = 33793,
+	condensedRemorseId = 33792,
+	-- Goshnar's Spite
+	weepingSoulCorpseId = 33876,
+	searingFireId = 33877,
+	-- Goshnar's Cruelty
+	pulsatingEnergyId = 34005,
+	greedyMawId = 33890,
+	someMortalEssenceId = 33891,
+	theBloodOfCloakTerrorIds = { 33854, 34006, 34007 },
+	-- Goshnar's Megalomania
+	deadAspectOfPowerCorpseId = 33949,
+	cleansedSanityItemId = 33950,
+	necromanticRemainsItemId = 33984,
+
+	poolDamagePercentages = {
+		[33854] = 0.20, -- 20% of maximum health for the largest pool
+		[34006] = 0.15, -- 15% for a medium-sized pool
+		[34007] = 0.10, -- 10% for the smallest pool
+	},
+
+	timeToIncreaseCrueltyDefense = 15, -- In seconds, it will increase every 15 seconds if don't use mortal essence in greedy maw
+	useGreedMawCooldown = 30, -- In seconds
+	goshnarsCrueltyDefenseChange = 2, -- Defense change, the amount that will decrease or increase defense, the defense cannot decrease more than the monster's original defense amount
+	goshnarsCrueltyWaveInterval = 7, -- In seconds
+
+	timeToReturnImmuneMegalomania = 70, -- In seconds
+
+	baseBagYouDesireChance = 1, -- 1% base chance
+	bagYouDesireChancePerTaint = 1, -- Increases 1% per taint
+	bagYouDesireMonsters = {
+		"Bony Sea Devil",
+		"Brachiodemon",
+		"Branchy Crawler",
+		"Capricious Phantom",
+		"Cloak Of Terror",
+		"Courage Leech",
+		"Distorted Phantom",
+		"Druid's Apparition",
+		"Infernal Demon",
+		"Infernal Phantom",
+		"Knight's Apparition",
+		"Many Faces",
+		"Mould Phantom",
+		"Paladin's Apparition",
+		"Rotten Golem",
+		"Sorcerer's Apparition",
+		"Turbulent Elemental",
+		"Vibrant Phantom.",
+	},
+	bagYouDesireBosses = {
+		"Goshnar's Cruelty",
+		"Goshnar's Spite",
+		"Goshnar's Malice",
+		"Goshnar's Hatred",
+		"Goshnar's Greed",
+	},
+
+	-- Goshnar's Cruelty pulsating energy monsters
+	pulsatingEnergyMonsters = {
+		"Vibrant Phantom",
+		"Cloak of Terror",
+		"Courage Leech",
+	},
+
+	finalRewards = {
+		{ id = 34082, name = "soulcutter" },
+		{ id = 34083, name = "soulshredder" },
+		{ id = 34084, name = "soulbiter" },
+		{ id = 34085, name = "souleater" },
+		{ id = 34086, name = "soulcrusher" },
+		{ id = 34087, name = "soulmaimer" },
+		{ id = 34088, name = "soulbleeder" },
+		{ id = 34089, name = "soulpiercer" },
+		{ id = 34090, name = "soultainter" },
+		{ id = 34091, name = "soulhexer" },
+		{ id = 34092, name = "soulshanks" },
+		{ id = 34093, name = "soulstrider" },
+		{ id = 34094, name = "soulshell" },
+		{ id = 34095, name = "soulmantel" },
+		{ id = 34096, name = "soulshroud" },
+		{ id = 34097, name = "pair of soulwalkers" },
+		{ id = 34098, name = "pair of soulstalkers" },
+		{ id = 34099, name = "soulbastion" },
+	},
+
+	kvSoulWar = KV.scoped("quest"):scoped("soul-war"),
+	-- Global KV for storage burning change form time
+	kvBurning = KV.scoped("quest"):scoped("soul-war"):scoped("burning-change-form"),
+
+	rottenWastelandShrines = {
+		[33019] = { x = 33926, y = 31091, z = 13 },
+		[33021] = { x = 33963, y = 31078, z = 13 },
+		[33022] = { x = 33970, y = 30988, z = 13 },
+		[33024] = { x = 33970, y = 31012, z = 13 },
+	},
+
+	-- Lever room and teleports positions
+	goshnarsGreedAccessPosition = { from = { x = 33937, y = 31217, z = 11 }, to = { x = 33782, y = 31665, z = 14 } },
+	goshnarsHatredAccessPosition = { from = { x = 33914, y = 31032, z = 12 }, to = { x = 33774, y = 31604, z = 14 } },
+	-- Teleports from 1st/2nd/3rd floors
+	goshnarsCrueltyTeleportRoomPositions = {
+		{ from = Position(33889, 31873, 3), to = Position(33830, 31881, 4), access = "first-floor-access", count = 40 },
+		{ from = Position(33829, 31880, 4), to = Position(33856, 31889, 5), access = "second-floor-access", count = 55 },
+		{ from = Position(33856, 31884, 5), to = Position(33857, 31865, 6), access = "third-floor-access", count = 70 },
+	},
+
+	-- Levers configuration
+	levers = {
+		goshnarsMalicePosition = { x = 33678, y = 31599, z = 14 },
+		goshnarsSpitePosition = { x = 33773, y = 31634, z = 14 },
+		goshnarsGreedPosition = { x = 33775, y = 31665, z = 14 },
+		goshnarsHatredPosition = { x = 33772, y = 31601, z = 14 },
+		goshnarsCrueltyPosition = { x = 33853, y = 31854, z = 6 },
+		goshnarsMegalomaniaPosition = { x = 33675, y = 31634, z = 14 },
+
+		-- Levers system
+		goshnarsSpite = {
+			boss = {
+				name = "Goshnar's Spite",
+				position = Position(33743, 31632, 14),
+			},
+			requiredLevel = 250,
+			playerPositions = {
+				{ pos = Position(33774, 31634, 14), teleport = Position(33742, 31639, 14), effect = CONST_ME_TELEPORT },
+				{ pos = Position(33775, 31634, 14), teleport = Position(33742, 31639, 14), effect = CONST_ME_TELEPORT },
+				{ pos = Position(33776, 31634, 14), teleport = Position(33742, 31639, 14), effect = CONST_ME_TELEPORT },
+				{ pos = Position(33777, 31634, 14), teleport = Position(33742, 31639, 14), effect = CONST_ME_TELEPORT },
+				{ pos = Position(33778, 31634, 14), teleport = Position(33742, 31639, 14), effect = CONST_ME_TELEPORT },
+			},
+			specPos = {
+				from = Position(33734, 31624, 14),
+				to = Position(33751, 31640, 14),
+			},
+			exit = Position(33621, 31427, 10),
+			timeToFightAgain = 20 * 60 * 60, -- 20 hours
+		},
+		goshnarsMalice = {
+			boss = {
+				name = "Goshnar's Malice",
+				position = Position(33709, 31599, 14),
+			},
+			requiredLevel = 250,
+			playerPositions = {
+				{ pos = Position(33679, 31599, 14), teleport = Position(33710, 31605, 14), effect = CONST_ME_TELEPORT },
+				{ pos = Position(33680, 31599, 14), teleport = Position(33710, 31605, 14), effect = CONST_ME_TELEPORT },
+				{ pos = Position(33681, 31599, 14), teleport = Position(33710, 31605, 14), effect = CONST_ME_TELEPORT },
+				{ pos = Position(33682, 31599, 14), teleport = Position(33710, 31605, 14), effect = CONST_ME_TELEPORT },
+				{ pos = Position(33683, 31599, 14), teleport = Position(33710, 31605, 14), effect = CONST_ME_TELEPORT },
+			},
+			specPos = {
+				from = Position(33699, 31590, 14),
+				to = Position(33718, 31607, 14),
+			},
+			onUseExtra = function(player)
+				addEvent(SpawnSoulCage, 23000)
+			end,
+			exit = Position(33621, 31427, 10),
+			timeToFightAgain = 20 * 60 * 60, -- 20 hours
+		},
+		goshnarsGreed = {
+			boss = {
+				name = "Goshnar's Greed",
+				position = Position(33746, 31666, 14),
+			},
+			requiredLevel = 250,
+			playerPositions = {
+				{ pos = Position(33776, 31665, 14), teleport = Position(33747, 31671, 14), effect = CONST_ME_TELEPORT },
+				{ pos = Position(33777, 31665, 14), teleport = Position(33747, 31671, 14), effect = CONST_ME_TELEPORT },
+				{ pos = Position(33778, 31665, 14), teleport = Position(33747, 31671, 14), effect = CONST_ME_TELEPORT },
+				{ pos = Position(33779, 31665, 14), teleport = Position(33747, 31671, 14), effect = CONST_ME_TELEPORT },
+				{ pos = Position(33780, 31665, 14), teleport = Position(33747, 31671, 14), effect = CONST_ME_TELEPORT },
+			},
+			specPos = {
+				from = Position(33737, 31658, 14),
+				to = Position(33755, 31673, 14),
+			},
+			timeToFightAgain = 0, -- TODO: Remove later
+			onUseExtra = function()
+				CreateGoshnarsGreedMonster("Greedbeast", Position(33744, 31666, 14))
+				CreateGoshnarsGreedMonster("Soulsnatcher", Position(33747, 31668, 14))
+				CreateGoshnarsGreedMonster("Weak Soul", Position(33750, 31666, 14))
+			end,
+			exit = Position(33621, 31427, 10),
+			timeToFightAgain = 20 * 60 * 60, -- 20 hours
+		},
+		goshnarsHatred = {
+			boss = {
+				name = "Goshnar's Hatred",
+				position = Position(33744, 31599, 14),
+			},
+			monsters = {
+				{ name = "Ashes of Burning Hatred", pos = { x = 33743, y = 31599, z = 14 } },
+			},
+			requiredLevel = 250,
+			playerPositions = {
+				{ pos = Position(33773, 31601, 14), teleport = Position(33743, 31604, 14), effect = CONST_ME_TELEPORT },
+				{ pos = Position(33774, 31601, 14), teleport = Position(33743, 31604, 14), effect = CONST_ME_TELEPORT },
+				{ pos = Position(33775, 31601, 14), teleport = Position(33743, 31604, 14), effect = CONST_ME_TELEPORT },
+				{ pos = Position(33776, 31601, 14), teleport = Position(33743, 31604, 14), effect = CONST_ME_TELEPORT },
+				{ pos = Position(33777, 31601, 14), teleport = Position(33743, 31604, 14), effect = CONST_ME_TELEPORT },
+			},
+			specPos = {
+				from = Position(33735, 31592, 14),
+				to = Position(33751, 31606, 14),
+			},
+			exit = Position(33621, 31427, 10),
+			timeToFightAgain = 20 * 60 * 60, -- 20 hours
+			onUseExtra = function(player)
+				SoulWarQuest.kvBurning:set("time", 180)
+				logger.debug("Goshnar's Hatred burning change form time set to: {}", 180)
+				player:resetGoshnarSymbolTormentCounter()
+			end,
+		},
+		goshnarsCruelty = {
+			boss = {
+				name = "Goshnar's Cruelty",
+				position = Position(33856, 31866, 7),
+			},
+			monsters = {
+				{ name = "A Greedy Eye", pos = { x = 33856, y = 31858, z = 7 } },
+			},
+			requiredLevel = 250,
+			playerPositions = {
+				{ pos = Position(33854, 31854, 6), teleport = Position(33856, 31872, 7), effect = CONST_ME_TELEPORT },
+				{ pos = Position(33855, 31854, 6), teleport = Position(33856, 31872, 7), effect = CONST_ME_TELEPORT },
+				{ pos = Position(33856, 31854, 6), teleport = Position(33856, 31872, 7), effect = CONST_ME_TELEPORT },
+				{ pos = Position(33857, 31854, 6), teleport = Position(33856, 31872, 7), effect = CONST_ME_TELEPORT },
+				{ pos = Position(33858, 31854, 6), teleport = Position(33856, 31872, 7), effect = CONST_ME_TELEPORT },
+			},
+			specPos = {
+				from = Position(33847, 31858, 7),
+				to = Position(33864, 31874, 7),
+			},
+			exit = Position(33621, 31427, 10),
+			timeToFightAgain = 20 * 60 * 60, -- 20 hours
+			onUseExtra = function(player)
+				SoulWarQuest.kvSoulWar:remove("greedy-maw-action")
+				player:soulWarQuestKV():scoped("furious-crater"):remove("greedy-maw-action")
+			end,
+		},
+		goshnarsMegalomania = {
+			boss = {
+				name = "Goshnar's Megalomania Purple",
+				position = Position(33710, 31634, 14),
+			},
+			monsters = {
+				{ name = "Aspect of Power", pos = { x = 33710, y = 31635, z = 14 } },
+			},
+			requiredLevel = 250,
+			playerPositions = {
+				{ pos = Position(33676, 31634, 14), teleport = Position(33710, 31639, 14), effect = CONST_ME_TELEPORT },
+				{ pos = Position(33677, 31634, 14), teleport = Position(33710, 31639, 14), effect = CONST_ME_TELEPORT },
+				{ pos = Position(33678, 31634, 14), teleport = Position(33710, 31639, 14), effect = CONST_ME_TELEPORT },
+				{ pos = Position(33679, 31634, 14), teleport = Position(33710, 31639, 14), effect = CONST_ME_TELEPORT },
+				{ pos = Position(33680, 31634, 14), teleport = Position(33710, 31639, 14), effect = CONST_ME_TELEPORT },
+			},
+			specPos = {
+				from = Position(33701, 31626, 14),
+				to = Position(33719, 31642, 14),
+			},
+			exit = Position(33621, 31427, 10),
+			timeToFightAgain = 72 * 60 * 60, -- 72 hours
+			onUseExtra = function(player)
+				player:resetGoshnarSymbolTormentCounter()
+				SoulWarQuest.kvSoulWar:remove("cleansed-sanity-action")
+				player:soulWarQuestKV():scoped("furious-crater"):remove("cleansed-sanity-action")
+			end,
+		},
+	},
+
+	-- Goshnar's Greed
+	apparitionNames = {
+		"Druid's Apparition",
+		"Knight's Apparition",
+		"Paladin's Apparition",
+		"Sorcerer's Apparition",
+	},
+
+	burningTransformations = {
+		{ 180, "Ashes of Burning Hatred" },
+		{ 135, "Spark of Burning Hatred" },
+		{ 90, "Flame of Burning Hatred" },
+		{ 45, "Blaze of Burning Hatred" },
+	},
+
+	requiredCountPerApparition = 25,
+
+	-- Ebb and flow
+	ebbAndFlow = {
+		zone = Zone("ebb-and-flow-zone"),
+		-- Positions to teleport into rooms when innundate map is loaded
+		centerRoomPositions = {
+			{ conor = { x = 33929, y = 31020, z = 9 }, teleportPosition = { x = 33939, y = 31021, z = 8 } },
+			{ conor = { x = 33929, y = 31047, z = 9 }, teleportPosition = { x = 33938, y = 31047, z = 8 } },
+			{ conor = { x = 33918, y = 31047, z = 9 }, teleportPosition = { x = 33903, y = 31049, z = 8 } },
+			{ conor = { x = 33898, y = 31054, z = 9 }, teleportPosition = { x = 33903, y = 31049, z = 8 } },
+			{ conor = { x = 33929, y = 31047, z = 9 }, teleportPosition = { x = 33938, y = 31047, z = 8 } },
+			{ conor = { x = 33940, y = 31054, z = 9 }, teleportPosition = { x = 33938, y = 31047, z = 8 } },
+			{ conor = { x = 33940, y = 31064, z = 9 }, teleportPosition = { x = 33937, y = 31074, z = 8 } },
+			{ conor = { x = 33937, y = 31086, z = 9 }, teleportPosition = { x = 33937, y = 31074, z = 8 } },
+			{ conor = { x = 33937, y = 31098, z = 9 }, teleportPosition = { x = 33929, y = 31109, z = 8 } },
+			{ conor = { x = 33933, y = 31109, z = 9 }, teleportPosition = { x = 33929, y = 31109, z = 8 } },
+			{ conor = { x = 33921, y = 31113, z = 9 }, teleportPosition = { x = 33929, y = 31109, z = 8 } },
+			{ conor = { x = 33912, y = 31113, z = 9 }, teleportPosition = { x = 33904, y = 31117, z = 8 } },
+			{ conor = { x = 33901, y = 31108, z = 9 }, teleportPosition = { x = 33904, y = 31117, z = 8 } },
+			{ conor = { x = 33901, y = 31098, z = 9 }, teleportPosition = { x = 33904, y = 31082, z = 8 } },
+			{ conor = { x = 33899, y = 31064, z = 9 }, teleportPosition = { x = 33904, y = 31082, z = 8 } },
+		},
+		mapsPath = {
+			empty = "data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-empty.otbm",
+			inundate = "data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-inundate.otbm",
+		},
+
+		-- In Minutes
+		intervalChangeMap = 2,
+		waitPosition = Position(33893, 31020, 8),
+
+		getZone = function()
+			return SoulWarQuest.ebbAndFlow.zone
+		end,
+
+		reloadZone = function()
+			SoulWarQuest.ebbAndFlow.zone:addArea({ x = 33869, y = 30991, z = 8 }, { x = 33964, y = 31147, z = 9 })
+		end,
+
+		kv = KV.scoped("quest"):scoped("soul-war"):scoped("ebb-and-flow-maps"),
+		isActive = function()
+			return SoulWarQuest.ebbAndFlow.kv:get("is-active")
+		end,
+		isLoadedEmptyMap = function()
+			return SoulWarQuest.ebbAndFlow.kv:get("is-loaded-empty-map")
+		end,
+		setActive = function(value)
+			SoulWarQuest.ebbAndFlow.kv:set("is-active", value)
+		end,
+		setLoadedEmptyMap = function(value)
+			SoulWarQuest.ebbAndFlow.kv:set("is-loaded-empty-map", value)
+		end,
+
+		updateZonePlayers = function()
+			if SoulWarQuest.ebbAndFlow.zone and SoulWarQuest.ebbAndFlow.getZone():countPlayers() > 0 then
+				SoulWarQuest.ebbAndFlow.reloadZone()
+				local players = SoulWarQuest.ebbAndFlow.getZone():getPlayers()
+				for _, player in ipairs(players) do
+					logger.debug("Updating player: {}", player:getName())
+					player:sendCreatureAppear()
+				end
+			end
+		end,
+
+		-- Add here more positions of the pools that must transform before innundate map is loaded
+		poolPositions = {
+			{ x = 33906, y = 31026, z = 9 },
+			{ x = 33901, y = 31026, z = 9 },
+			{ x = 33932, y = 31011, z = 9 },
+			{ x = 33941, y = 31033, z = 9 },
+			{ x = 33946, y = 31037, z = 9 },
+			{ x = 33939, y = 31056, z = 9 },
+		},
+
+		boatId = 7272,
+		doorId = 33767,
+		smallPoolId = 33772,
+		MediumPoolId = 33773,
+	},
+
+	changeBlueEvent = nil,
+	changePurpleEvent = nil,
+
+	changeMegalomaniaBlue = function()
+		local boss = Creature("Goshnar's Megalomania")
+		if boss then
+			boss:teleportTo(SoulWarQuest.levers.goshnarsMegalomania.boss.position)
+			boss:say("ENOUGH! I WILL MAKE YOU SUFFER FOR YOUR INSOLENCE! NOW - I - WILL - ANIHILATE - YOU!")
+			boss:setType("Goshnar's Megalomania Blue")
+			local function changeBack()
+				boss:setType("Goshnar's Megalomania Purple")
+			end
+
+			changePurpleEvent = addEvent(changeBack, 7000)
+		end
+	end,
+
+	-- Chance to heal the life of the monster by stepping on the corpse of "weeping soul"
+	goshnarsSpiteHealChance = 10,
+	-- Percentage that will heal by stepping and the chance is successful
+	goshnarsSpiteHealPercentage = 10,
+
+	goshnarSpiteEntrancePosition = { fromPos = Position(33950, 31109, 8), toPos = Position(33780, 31634, 14) },
+
+	waterElementalOutfit = {
+		lookType = 286,
+		lookHead = 0,
+		lookBody = 0,
+		lookLegs = 0,
+		lookFeet = 0,
+		lookAddons = 0,
+		lookMount = 0,
+	},
+
+	goshnarsSpiteFirePositions = {
+		-- North
+		{ x = 33743, y = 31628, z = 14 },
+		-- East
+		{ x = 33736, y = 31632, z = 14 },
+		-- West
+		{ x = 33750, y = 31632, z = 14 },
+		-- South
+		{ x = 33742, y = 31637, z = 14 },
+	},
+
+	-- Increased defense if the searing fire disappears
+	goshnarsSpiteIncreaseDefense = 10,
+	-- Count of monsters to kill for enter in the boss room
+	hardozousPanthomDeathCount = 20,
+	-- Time to fire created again
+	timeToCreateSearingFire = 14, -- In seconds
+	-- Time to remove the searing fire if player don't step on it
+	timeToRemoveSearingFire = 5, -- In seconds
+	cooldownToStepOnSearingFire = 56, -- In seconds (14 seconds x 4)
+
+	-- Positions to teleport into rooms when innundate map is loaded
+	ebbAndFlowBoatTeleportPositions = {
+		-- First boat
+		-- Enter on boat
+		{ register = { x = 33919, y = 31019, z = 8 }, teleportTo = { x = 33923, y = 31019, z = 8 } },
+		{ register = { x = 33919, y = 31020, z = 8 }, teleportTo = { x = 33923, y = 31020, z = 8 } },
+		{ register = { x = 33919, y = 31021, z = 8 }, teleportTo = { x = 33923, y = 31021, z = 8 } },
+		{ register = { x = 33919, y = 31022, z = 8 }, teleportTo = { x = 33923, y = 31022, z = 8 } },
+		-- Back to innitial room
+		{ register = { x = 33922, y = 31019, z = 8 }, teleportTo = { x = 33918, y = 31019, z = 8 } },
+		{ register = { x = 33922, y = 31020, z = 8 }, teleportTo = { x = 33918, y = 31020, z = 8 } },
+		{ register = { x = 33922, y = 31021, z = 8 }, teleportTo = { x = 33918, y = 31021, z = 8 } },
+		{ register = { x = 33922, y = 31022, z = 8 }, teleportTo = { x = 33918, y = 31022, z = 8 } },
+		-- From boat to room
+		{ register = { x = 33926, y = 31019, z = 8 }, teleportTo = { x = 33930, y = 31019, z = 8 } },
+		{ register = { x = 33926, y = 31020, z = 8 }, teleportTo = { x = 33930, y = 31020, z = 8 } },
+		{ register = { x = 33926, y = 31021, z = 8 }, teleportTo = { x = 33930, y = 31021, z = 8 } },
+		{ register = { x = 33926, y = 31022, z = 8 }, teleportTo = { x = 33930, y = 31022, z = 8 } },
+		-- From room to boat
+		{ register = { x = 33929, y = 31019, z = 8 }, teleportTo = { x = 33925, y = 31019, z = 8 } },
+		{ register = { x = 33929, y = 31020, z = 8 }, teleportTo = { x = 33925, y = 31020, z = 8 } },
+		{ register = { x = 33929, y = 31021, z = 8 }, teleportTo = { x = 33925, y = 31021, z = 8 } },
+		{ register = { x = 33929, y = 31022, z = 8 }, teleportTo = { x = 33925, y = 31022, z = 8 } },
+
+		-- Boat
+		-- Enter on boat
+		{ register = { x = 33929, y = 31045, z = 8 }, teleportTo = { x = 33925, y = 31045, z = 8 } },
+		{ register = { x = 33929, y = 31046, z = 8 }, teleportTo = { x = 33925, y = 31046, z = 8 } },
+		{ register = { x = 33929, y = 31047, z = 8 }, teleportTo = { x = 33925, y = 31047, z = 8 } },
+		{ register = { x = 33929, y = 31048, z = 8 }, teleportTo = { x = 33925, y = 31048, z = 8 } },
+		-- Back to room
+		{ register = { x = 33926, y = 31045, z = 8 }, teleportTo = { x = 33930, y = 31045, z = 8 } },
+		{ register = { x = 33926, y = 31046, z = 8 }, teleportTo = { x = 33930, y = 31046, z = 8 } },
+		{ register = { x = 33926, y = 31047, z = 8 }, teleportTo = { x = 33930, y = 31047, z = 8 } },
+		{ register = { x = 33926, y = 31048, z = 8 }, teleportTo = { x = 33930, y = 31048, z = 8 } },
+		-- From boat to room
+		{ register = { x = 33922, y = 31045, z = 8 }, teleportTo = { x = 33918, y = 31045, z = 8 } },
+		{ register = { x = 33922, y = 31046, z = 8 }, teleportTo = { x = 33918, y = 31046, z = 8 } },
+		{ register = { x = 33922, y = 31047, z = 8 }, teleportTo = { x = 33918, y = 31047, z = 8 } },
+		{ register = { x = 33922, y = 31048, z = 8 }, teleportTo = { x = 33918, y = 31048, z = 8 } },
+		-- From room to boat
+		{ register = { x = 33919, y = 31045, z = 8 }, teleportTo = { x = 33923, y = 31045, z = 8 } },
+		{ register = { x = 33919, y = 31046, z = 8 }, teleportTo = { x = 33923, y = 31046, z = 8 } },
+		{ register = { x = 33919, y = 31047, z = 8 }, teleportTo = { x = 33923, y = 31047, z = 8 } },
+		{ register = { x = 33919, y = 31048, z = 8 }, teleportTo = { x = 33923, y = 31048, z = 8 } },
+
+		-- Boat
+		-- Enter on boat
+		{ register = { x = 33896, y = 31055, z = 8 }, teleportTo = { x = 33896, y = 31059, z = 8 } },
+		{ register = { x = 33897, y = 31055, z = 8 }, teleportTo = { x = 33897, y = 31059, z = 8 } },
+		{ register = { x = 33898, y = 31055, z = 8 }, teleportTo = { x = 33898, y = 31059, z = 8 } },
+		{ register = { x = 33899, y = 31055, z = 8 }, teleportTo = { x = 33899, y = 31059, z = 8 } },
+		{ register = { x = 33900, y = 31055, z = 8 }, teleportTo = { x = 33900, y = 31059, z = 8 } },
+		{ register = { x = 33901, y = 31055, z = 8 }, teleportTo = { x = 33901, y = 31059, z = 8 } },
+		-- Back to room
+		{ register = { x = 33896, y = 31058, z = 8 }, teleportTo = { x = 33896, y = 31054, z = 8 } },
+		{ register = { x = 33897, y = 31058, z = 8 }, teleportTo = { x = 33897, y = 31054, z = 8 } },
+		{ register = { x = 33898, y = 31058, z = 8 }, teleportTo = { x = 33898, y = 31054, z = 8 } },
+		{ register = { x = 33899, y = 31058, z = 8 }, teleportTo = { x = 33899, y = 31054, z = 8 } },
+		{ register = { x = 33900, y = 31058, z = 8 }, teleportTo = { x = 33900, y = 31054, z = 8 } },
+		{ register = { x = 33901, y = 31058, z = 8 }, teleportTo = { x = 33901, y = 31054, z = 8 } },
+		-- From boat to room
+		{ register = { x = 33896, y = 31061, z = 8 }, teleportTo = { x = 33896, y = 31065, z = 8 } },
+		{ register = { x = 33897, y = 31061, z = 8 }, teleportTo = { x = 33897, y = 31065, z = 8 } },
+		{ register = { x = 33898, y = 31061, z = 8 }, teleportTo = { x = 33898, y = 31065, z = 8 } },
+		{ register = { x = 33899, y = 31061, z = 8 }, teleportTo = { x = 33899, y = 31065, z = 8 } },
+		{ register = { x = 33900, y = 31061, z = 8 }, teleportTo = { x = 33900, y = 31065, z = 8 } },
+		{ register = { x = 33901, y = 31061, z = 8 }, teleportTo = { x = 33901, y = 31065, z = 8 } },
+		-- From room to boat
+		{ register = { x = 33896, y = 31064, z = 8 }, teleportTo = { x = 33896, y = 31060, z = 8 } },
+		{ register = { x = 33897, y = 31064, z = 8 }, teleportTo = { x = 33897, y = 31060, z = 8 } },
+		{ register = { x = 33898, y = 31064, z = 8 }, teleportTo = { x = 33898, y = 31060, z = 8 } },
+		{ register = { x = 33899, y = 31064, z = 8 }, teleportTo = { x = 33899, y = 31060, z = 8 } },
+		{ register = { x = 33900, y = 31064, z = 8 }, teleportTo = { x = 33900, y = 31060, z = 8 } },
+		{ register = { x = 33901, y = 31064, z = 8 }, teleportTo = { x = 33901, y = 31060, z = 8 } },
+
+		-- Boat
+		-- Enter on boat
+		{ register = { x = 33899, y = 31099, z = 8 }, teleportTo = { x = 33899, y = 31103, z = 8 } },
+		{ register = { x = 33900, y = 31099, z = 8 }, teleportTo = { x = 33900, y = 31103, z = 8 } },
+		{ register = { x = 33901, y = 31099, z = 8 }, teleportTo = { x = 33901, y = 31103, z = 8 } },
+		{ register = { x = 33902, y = 31099, z = 8 }, teleportTo = { x = 33902, y = 31103, z = 8 } },
+		{ register = { x = 33903, y = 31099, z = 8 }, teleportTo = { x = 33903, y = 31103, z = 8 } },
+		{ register = { x = 33904, y = 31099, z = 8 }, teleportTo = { x = 33904, y = 31103, z = 8 } },
+		{ register = { x = 33905, y = 31099, z = 8 }, teleportTo = { x = 33905, y = 31103, z = 8 } },
+		-- Back from boat to room
+		{ register = { x = 33899, y = 31102, z = 8 }, teleportTo = { x = 33899, y = 31098, z = 8 } },
+		{ register = { x = 33900, y = 31102, z = 8 }, teleportTo = { x = 33900, y = 31098, z = 8 } },
+		{ register = { x = 33901, y = 31102, z = 8 }, teleportTo = { x = 33901, y = 31098, z = 8 } },
+		{ register = { x = 33902, y = 31102, z = 8 }, teleportTo = { x = 33902, y = 31098, z = 8 } },
+		{ register = { x = 33903, y = 31102, z = 8 }, teleportTo = { x = 33903, y = 31098, z = 8 } },
+		{ register = { x = 33904, y = 31102, z = 8 }, teleportTo = { x = 33904, y = 31098, z = 8 } },
+		{ register = { x = 33905, y = 31102, z = 8 }, teleportTo = { x = 33905, y = 31098, z = 8 } },
+		-- From boat to room
+		{ register = { x = 33899, y = 31105, z = 8 }, teleportTo = { x = 33899, y = 31109, z = 8 } },
+		{ register = { x = 33900, y = 31105, z = 8 }, teleportTo = { x = 33900, y = 31109, z = 8 } },
+		{ register = { x = 33901, y = 31105, z = 8 }, teleportTo = { x = 33901, y = 31109, z = 8 } },
+		{ register = { x = 33902, y = 31105, z = 8 }, teleportTo = { x = 33902, y = 31109, z = 8 } },
+		{ register = { x = 33903, y = 31105, z = 8 }, teleportTo = { x = 33903, y = 31109, z = 8 } },
+		{ register = { x = 33904, y = 31105, z = 8 }, teleportTo = { x = 33904, y = 31109, z = 8 } },
+		{ register = { x = 33905, y = 31105, z = 8 }, teleportTo = { x = 33905, y = 31109, z = 8 } },
+		-- From room to boat
+		{ register = { x = 33899, y = 31108, z = 8 }, teleportTo = { x = 33899, y = 31104, z = 8 } },
+		{ register = { x = 33900, y = 31108, z = 8 }, teleportTo = { x = 33900, y = 31104, z = 8 } },
+		{ register = { x = 33901, y = 31108, z = 8 }, teleportTo = { x = 33901, y = 31104, z = 8 } },
+		{ register = { x = 33902, y = 31108, z = 8 }, teleportTo = { x = 33902, y = 31104, z = 8 } },
+		{ register = { x = 33903, y = 31108, z = 8 }, teleportTo = { x = 33903, y = 31104, z = 8 } },
+		{ register = { x = 33904, y = 31108, z = 8 }, teleportTo = { x = 33904, y = 31104, z = 8 } },
+		{ register = { x = 33905, y = 31108, z = 8 }, teleportTo = { x = 33905, y = 31104, z = 8 } },
+
+		-- Boat
+		-- Enter on boat
+		{ register = { x = 33913, y = 31112, z = 8 }, teleportTo = { x = 33917, y = 31112, z = 8 } },
+		{ register = { x = 33913, y = 31113, z = 8 }, teleportTo = { x = 33917, y = 31113, z = 8 } },
+		{ register = { x = 33913, y = 31114, z = 8 }, teleportTo = { x = 33917, y = 31114, z = 8 } },
+		{ register = { x = 33913, y = 31115, z = 8 }, teleportTo = { x = 33917, y = 31115, z = 8 } },
+		{ register = { x = 33913, y = 31116, z = 8 }, teleportTo = { x = 33917, y = 31116, z = 8 } },
+		-- Back to room
+		{ register = { x = 33916, y = 31112, z = 8 }, teleportTo = { x = 33912, y = 31112, z = 8 } },
+		{ register = { x = 33916, y = 31113, z = 8 }, teleportTo = { x = 33912, y = 31113, z = 8 } },
+		{ register = { x = 33916, y = 31114, z = 8 }, teleportTo = { x = 33912, y = 31114, z = 8 } },
+		{ register = { x = 33916, y = 31115, z = 8 }, teleportTo = { x = 33912, y = 31115, z = 8 } },
+		{ register = { x = 33916, y = 31116, z = 8 }, teleportTo = { x = 33912, y = 31116, z = 8 } },
+		-- From boat to room
+		{ register = { x = 33918, y = 31112, z = 8 }, teleportTo = { x = 33922, y = 31112, z = 8 } },
+		{ register = { x = 33918, y = 31113, z = 8 }, teleportTo = { x = 33922, y = 31113, z = 8 } },
+		{ register = { x = 33918, y = 31114, z = 8 }, teleportTo = { x = 33922, y = 31114, z = 8 } },
+		{ register = { x = 33918, y = 31115, z = 8 }, teleportTo = { x = 33922, y = 31115, z = 8 } },
+		{ register = { x = 33918, y = 31116, z = 8 }, teleportTo = { x = 33922, y = 31116, z = 8 } },
+		-- From room to boat
+		{ register = { x = 33921, y = 31112, z = 8 }, teleportTo = { x = 33917, y = 31112, z = 8 } },
+		{ register = { x = 33921, y = 31113, z = 8 }, teleportTo = { x = 33917, y = 31113, z = 8 } },
+		{ register = { x = 33921, y = 31114, z = 8 }, teleportTo = { x = 33917, y = 31114, z = 8 } },
+		{ register = { x = 33921, y = 31115, z = 8 }, teleportTo = { x = 33917, y = 31115, z = 8 } },
+		{ register = { x = 33921, y = 31116, z = 8 }, teleportTo = { x = 33917, y = 31116, z = 8 } },
+
+		-- Boat
+		-- Enter on boat
+		{ register = { x = 33936, y = 31087, z = 8 }, teleportTo = { x = 33936, y = 31091, z = 8 } },
+		{ register = { x = 33937, y = 31087, z = 8 }, teleportTo = { x = 33937, y = 31091, z = 8 } },
+		{ register = { x = 33938, y = 31087, z = 8 }, teleportTo = { x = 33938, y = 31091, z = 8 } },
+		{ register = { x = 33939, y = 31087, z = 8 }, teleportTo = { x = 33939, y = 31091, z = 8 } },
+		{ register = { x = 33940, y = 31087, z = 8 }, teleportTo = { x = 33940, y = 31091, z = 8 } },
+		{ register = { x = 33941, y = 31087, z = 8 }, teleportTo = { x = 33941, y = 31091, z = 8 } },
+		-- Back to room
+		{ register = { x = 33936, y = 31090, z = 8 }, teleportTo = { x = 33936, y = 31086, z = 8 } },
+		{ register = { x = 33937, y = 31090, z = 8 }, teleportTo = { x = 33937, y = 31086, z = 8 } },
+		{ register = { x = 33938, y = 31090, z = 8 }, teleportTo = { x = 33938, y = 31086, z = 8 } },
+		{ register = { x = 33939, y = 31090, z = 8 }, teleportTo = { x = 33939, y = 31086, z = 8 } },
+		{ register = { x = 33940, y = 31090, z = 8 }, teleportTo = { x = 33940, y = 31086, z = 8 } },
+		{ register = { x = 33941, y = 31090, z = 8 }, teleportTo = { x = 33941, y = 31086, z = 8 } },
+		-- From boat to room
+		{ register = { x = 33936, y = 31095, z = 8 }, teleportTo = { x = 33934, y = 31099, z = 8 } },
+		{ register = { x = 33937, y = 31095, z = 8 }, teleportTo = { x = 33935, y = 31099, z = 8 } },
+		{ register = { x = 33938, y = 31095, z = 8 }, teleportTo = { x = 33936, y = 31099, z = 8 } },
+		{ register = { x = 33939, y = 31095, z = 8 }, teleportTo = { x = 33937, y = 31099, z = 8 } },
+		{ register = { x = 33940, y = 31095, z = 8 }, teleportTo = { x = 33938, y = 31099, z = 8 } },
+		{ register = { x = 33941, y = 31095, z = 8 }, teleportTo = { x = 33939, y = 31099, z = 8 } },
+		-- From room to boat
+		{ register = { x = 33934, y = 31098, z = 8 }, teleportTo = { x = 33936, y = 31094, z = 8 } },
+		{ register = { x = 33935, y = 31098, z = 8 }, teleportTo = { x = 33937, y = 31094, z = 8 } },
+		{ register = { x = 33936, y = 31098, z = 8 }, teleportTo = { x = 33938, y = 31094, z = 8 } },
+		{ register = { x = 33937, y = 31098, z = 8 }, teleportTo = { x = 33939, y = 31094, z = 8 } },
+		{ register = { x = 33938, y = 31098, z = 8 }, teleportTo = { x = 33940, y = 31094, z = 8 } },
+		{ register = { x = 33939, y = 31098, z = 8 }, teleportTo = { x = 33941, y = 31094, z = 8 } },
+		{ register = { x = 33940, y = 31098, z = 8 }, teleportTo = { x = 33942, y = 31094, z = 8 } },
+
+		-- Boat
+		-- Enter on boat
+		{ register = { x = 33939, y = 31064, z = 8 }, teleportTo = { x = 33939, y = 31060, z = 8 } },
+		{ register = { x = 33940, y = 31064, z = 8 }, teleportTo = { x = 33940, y = 31060, z = 8 } },
+		{ register = { x = 33941, y = 31064, z = 8 }, teleportTo = { x = 33941, y = 31060, z = 8 } },
+		{ register = { x = 33942, y = 31064, z = 8 }, teleportTo = { x = 33942, y = 31060, z = 8 } },
+		{ register = { x = 33943, y = 31064, z = 8 }, teleportTo = { x = 33943, y = 31060, z = 8 } },
+		{ register = { x = 33944, y = 31064, z = 8 }, teleportTo = { x = 33944, y = 31060, z = 8 } },
+		-- Back to room
+		{ register = { x = 33939, y = 31061, z = 8 }, teleportTo = { x = 33939, y = 31065, z = 8 } },
+		{ register = { x = 33940, y = 31061, z = 8 }, teleportTo = { x = 33940, y = 31065, z = 8 } },
+		{ register = { x = 33941, y = 31061, z = 8 }, teleportTo = { x = 33941, y = 31065, z = 8 } },
+		{ register = { x = 33942, y = 31061, z = 8 }, teleportTo = { x = 33942, y = 31065, z = 8 } },
+		{ register = { x = 33943, y = 31061, z = 8 }, teleportTo = { x = 33943, y = 31065, z = 8 } },
+		{ register = { x = 33944, y = 31061, z = 8 }, teleportTo = { x = 33944, y = 31065, z = 8 } },
+		-- From boat to room
+		{ register = { x = 33939, y = 31058, z = 8 }, teleportTo = { x = 33939, y = 31054, z = 8 } },
+		{ register = { x = 33940, y = 31058, z = 8 }, teleportTo = { x = 33940, y = 31054, z = 8 } },
+		{ register = { x = 33941, y = 31058, z = 8 }, teleportTo = { x = 33941, y = 31054, z = 8 } },
+		{ register = { x = 33942, y = 31058, z = 8 }, teleportTo = { x = 33942, y = 31054, z = 8 } },
+		{ register = { x = 33943, y = 31058, z = 8 }, teleportTo = { x = 33943, y = 31054, z = 8 } },
+		{ register = { x = 33944, y = 31058, z = 8 }, teleportTo = { x = 33944, y = 31054, z = 8 } },
+		-- From room to boat
+		{ register = { x = 33939, y = 31055, z = 8 }, teleportTo = { x = 33939, y = 31059, z = 8 } },
+		{ register = { x = 33940, y = 31055, z = 8 }, teleportTo = { x = 33940, y = 31059, z = 8 } },
+		{ register = { x = 33941, y = 31055, z = 8 }, teleportTo = { x = 33941, y = 31059, z = 8 } },
+		{ register = { x = 33942, y = 31055, z = 8 }, teleportTo = { x = 33942, y = 31059, z = 8 } },
+		{ register = { x = 33943, y = 31055, z = 8 }, teleportTo = { x = 33943, y = 31059, z = 8 } },
+		{ register = { x = 33944, y = 31055, z = 8 }, teleportTo = { x = 33944, y = 31059, z = 8 } },
+
+		-- Boat
+		-- Enter on boat
+		{ register = { x = 33934, y = 31108, z = 8 }, teleportTo = { x = 33938, y = 31108, z = 8 } },
+		{ register = { x = 33934, y = 31109, z = 8 }, teleportTo = { x = 33938, y = 31109, z = 8 } },
+		{ register = { x = 33934, y = 31110, z = 8 }, teleportTo = { x = 33938, y = 31110, z = 8 } },
+		{ register = { x = 33934, y = 31111, z = 8 }, teleportTo = { x = 33938, y = 31111, z = 8 } },
+		{ register = { x = 33934, y = 31112, z = 8 }, teleportTo = { x = 33938, y = 31112, z = 8 } },
+		-- Back to room
+		{ register = { x = 33937, y = 31108, z = 8 }, teleportTo = { x = 33933, y = 31108, z = 8 } },
+		{ register = { x = 33937, y = 31109, z = 8 }, teleportTo = { x = 33933, y = 31109, z = 8 } },
+		{ register = { x = 33937, y = 31110, z = 8 }, teleportTo = { x = 33933, y = 31110, z = 8 } },
+		{ register = { x = 33937, y = 31111, z = 8 }, teleportTo = { x = 33933, y = 31111, z = 8 } },
+		{ register = { x = 33937, y = 31112, z = 8 }, teleportTo = { x = 33933, y = 31112, z = 8 } },
+		-- From boat to room
+		{ register = { x = 33942, y = 31108, z = 8 }, teleportTo = { x = 33946, y = 31108, z = 8 } },
+		{ register = { x = 33942, y = 31109, z = 8 }, teleportTo = { x = 33946, y = 31109, z = 8 } },
+		{ register = { x = 33942, y = 31110, z = 8 }, teleportTo = { x = 33946, y = 31110, z = 8 } },
+		{ register = { x = 33942, y = 31111, z = 8 }, teleportTo = { x = 33946, y = 31111, z = 8 } },
+		{ register = { x = 33942, y = 31112, z = 8 }, teleportTo = { x = 33946, y = 31112, z = 8 } },
+		-- From room to boat
+		{ register = { x = 33945, y = 31108, z = 8 }, teleportTo = { x = 33941, y = 31108, z = 8 } },
+		{ register = { x = 33945, y = 31109, z = 8 }, teleportTo = { x = 33941, y = 31109, z = 8 } },
+		{ register = { x = 33945, y = 31110, z = 8 }, teleportTo = { x = 33941, y = 31110, z = 8 } },
+		{ register = { x = 33945, y = 31111, z = 8 }, teleportTo = { x = 33941, y = 31111, z = 8 } },
+		{ register = { x = 33945, y = 31112, z = 8 }, teleportTo = { x = 33941, y = 31112, z = 8 } },
+	},
+}
+
+-- Initialize ebb and flow zone area
+SoulWarQuest.ebbAndFlow.zone:addArea({ x = 33869, y = 30991, z = 8 }, { x = 33964, y = 31147, z = 9 })
+
+SoulCagePosition = Position(33709, 31596, 14)
+TaintDurationSeconds = 14 * 24 * 60 * 60 -- 14 days
+GreedbeastKills = 0
+
+SoulWarReflectDamageMap = {
+	[COMBAT_PHYSICALDAMAGE] = 10,
+	[COMBAT_FIREDAMAGE] = 10,
+	[COMBAT_EARTHDAMAGE] = 10,
+	[COMBAT_ENERGYDAMAGE] = 10,
+	[COMBAT_ICEDAMAGE] = 10,
+	[COMBAT_HOLYDAMAGE] = 10,
+	[COMBAT_DEATHDAMAGE] = 10,
+}
+
+local soulWarTaints = {
+	"taints-teleport", -- Taint 1
+	"taints-spawn", -- Taint 2
+	"taints-damage", -- Taint 3
+	"taints-heal", -- Taint 4
+	"taints-loss", -- Taint 5
+}
+
+SoulWarBosses = {
+	["Goshnar's Malice"] = true,
+	["Goshnar's Hatred"] = true,
+	["Goshnar's Spite"] = true,
+	["Goshnar's Cruelty"] = true,
+	["Goshnar's Greed"] = true,
+}
+
+GreedMonsters = {
+	["Greedbeast"] = Position(33744, 31666, 14),
+	["Soulsnatcher"] = Position(33747, 31668, 14),
+	["Weak Soul"] = Position(33750, 31666, 14),
+	["Strong Soul"] = Position(33750, 31666, 14),
+	["Powerful Soul"] = Position(33750, 31666, 14),
+}
+
+function CreateGoshnarsGreedMonster(name, position)
+	local function sendEffect()
+		position:sendMagicEffect(CONST_ME_TELEPORT)
+	end
+
+	local function spawnMonster()
+		Game.createMonster(name, position, true, false)
+		logger.debug("Spawning {} in position {}", name, position:toString())
+	end
+
+	for i = 7, 9 do
+		addEvent(sendEffect, i * 1000)
+	end
+
+	addEvent(spawnMonster, 10000)
+end
+
+local soulWarSpawnMonsters = {
+	["soulwars.claustrophobic-inferno"] = "Brachiodemon",
+	["soulwars.mirrored-nightmare"] = "Many Faces",
+	["soulwars.ebb-and-flow"] = "Bony Sea Devil",
+	["soulwars.furious-crater"] = "Cloak of Terror",
+	["soulwars.rotten-wasteland"] = "Branchy Crawler",
+	["boss-rooms"] = "Dreadful Harvester",
+}
+
+function RemoveSoulCageAndBuffMalice()
+	local tile = Tile(SoulCagePosition)
+	local creatures = tile:getCreatures() or {}
+	local soulCage
+	for i, creature in ipairs(creatures) do
+		if creature:getName() == "Soul Cage" then
+			soulCage = creature
+			logger.debug("Removing Soul Cage, the players not be able to kill him")
+			break
+		end
+	end
+
+	local rangeX = 20
+	local rangeY = 20
+	local spectators = Game.getSpectators(Position(33709, 31599, 14), false, false, rangeX, rangeX, rangeY, rangeY)
+	if soulCage then
+		local malice
+		for i = 1, #spectators do
+			logger.debug("Specs found {}", i)
+			if spectators[i]:isMonster() then
+				logger.debug("Malice Spectators {}", spectators[i]:getName())
+				if spectators[i]:getName() == "Goshnar's Malice" then
+					logger.debug("Found malice")
+					malice = Monster(spectators[i])
+					break
+				end
+			end
+		end
+
+		soulCage:remove()
+		addEvent(SpawnSoulCage, 23000)
+
+		if malice then
+			logger.debug("Found malice, try adding reflect and defense")
+			for elementType, reflectPercent in pairs(SoulWarReflectDamageMap) do
+				malice:addReflectElement(elementType, reflectPercent)
+			end
+			malice:addDefense(10)
+		end
+	end
+end
+
+function SpawnSoulCage()
+	local tile = Tile(SoulCagePosition)
+	local creatures = tile:getCreatures() or {}
+	local soulCage
+	for i, creature in ipairs(creatures) do
+		if creature:getName() == "Soul Cage" then
+			soulCage = true
+			break
+		end
+	end
+
+	if not soulCage then
+		Game.createMonster("Soul Cage", SoulCagePosition, true, true)
+		logger.debug("Spawning Soul Cage in position {}", SoulCagePosition:toString())
+		addEvent(RemoveSoulCageAndBuffMalice, 40000)
+	end
+end
+
+local function shuffle(list)
+	for i = #list, 2, -1 do
+		local j = math.random(i)
+		list[i], list[j] = list[j], list[i]
+	end
+end
+
+local function createConnectedGroup(startPos, groupPositions, groupSize)
+	local group = { startPos }
+	local lastPos = startPos
+	local directions = {
+		{ x = 1, y = 0 },
+		{ x = -1, y = 0 }, -- Right and left
+		{ x = 0, y = 1 },
+		{ x = 0, y = -1 }, -- Up and down
+		{ x = 1, y = 1 },
+		{ x = -1, y = -1 }, -- Diagonals
+		{ x = -1, y = 1 },
+		{ x = 1, y = -1 },
+	}
+
+	for i = 2, groupSize do
+		shuffle(directions)
+		local nextPos = nil
+		for _, dir in ipairs(directions) do
+			local potentialNextPos = Position(lastPos.x + dir.x, lastPos.y + dir.y, lastPos.z)
+			if table.contains(groupPositions, potentialNextPos) then
+				nextPos = potentialNextPos
+				break
+			end
+		end
+
+		if nextPos then
+			table.insert(group, nextPos)
+			table.remove(groupPositions, table.find(groupPositions, nextPos))
+			lastPos = nextPos
+		else
+			break
+		end
+	end
+
+	return group
+end
+
+local function generatePositionsInRange(center, range)
+	local positions = {}
+	for x = center.x - range, center.x + range do
+		for y = center.y - range, center.y + range do
+			table.insert(positions, Position(x, y, center.z))
+		end
+	end
+	return positions
+end
+
+local toRevertPositions = {}
+
+local function revertTilesAndApplyDamage(zonePositions)
+	for _, pos in ipairs(zonePositions) do
+		local tile = Tile(pos)
+		if tile and tile:getGround() and tile:getGround():getId() ~= 409 then
+			local creature = tile:getTopCreature()
+			if creature then
+				local player = creature:getPlayer()
+				if player then
+					pos:sendMagicEffect(CONST_ME_REDSMOKE)
+					player:addHealth(-8000, COMBAT_DEATHDAMAGE)
+				end
+			end
+		end
+	end
+
+	for posString, itemId in pairs(toRevertPositions) do
+		local pos = posString:toPosition()
+		local tile = Tile(pos)
+		if tile and tile:getGround() and tile:getGround():getId() == 409 then
+			tile:getGround():transform(itemId)
+			toRevertPositions[pos:toString()] = nil
+		end
+	end
+end
+
+function Monster:createSoulWarWhiteTiles(centerRoomPosition, zonePositions, executeInterval)
+	local groupPositions = generatePositionsInRange(centerRoomPosition, 7)
+	local totalTiles = 11
+	local groupSize = 3
+	local groupsCreated = 0
+
+	-- Run only for megalomania boss
+	if executeInterval then
+		-- Remove remains
+		for _, pos in ipairs(zonePositions) do
+			local tile = Tile(pos)
+			if tile and tile:getGround() then
+				local remains = tile:getItemById(33984)
+				if remains then
+					remains:remove()
+				end
+			end
+		end
+	end
+
+	while #groupPositions > 0 and groupsCreated * groupSize < totalTiles do
+		local randomIndex = math.random(#groupPositions)
+		local startPos = groupPositions[randomIndex]
+		table.remove(groupPositions, randomIndex)
+
+		local group = createConnectedGroup(startPos, groupPositions, groupSize)
+		for _, pos in ipairs(group) do
+			local tile = Tile(pos)
+			if tile then
+				toRevertPositions[pos:toString()] = tile:getGround():getId()
+				tile:getGround():transform(409)
+			end
+		end
+
+		groupsCreated = groupsCreated + 1
+	end
+
+	addEvent(revertTilesAndApplyDamage, executeInterval or 3000, zonePositions)
+end
+
+function Monster:generateBagYouDesireLoot(player)
+	local playerTaintLevel = player:getTaintLevel()
+	if not playerTaintLevel then
+		return {}
+	end
+
+	local monsterName = self:getName()
+	local isMonsterValid = false
+	for _, monster in ipairs(SoulWarQuest.bagYouDesireMonsters) do
+		if monsterName == monster then
+			isMonsterValid = true
+			break
+		end
+	end
+
+	if not isMonsterValid then
+		return {}
+	end
+
+	-- Calculates the chances based on the number of taints
+	local totalChance = SoulWarQuest.baseBagYouDesireChance + (playerTaintLevel * SoulWarQuest.bagYouDesireChancePerTaint)
+	logger.debug("Player {} killed {} and has {} taints, loot chance {}", player:getName(), monsterName, playerTaintLevel, totalChance)
+	-- Generate loot
+	local loot = {}
+	if math.random(1, 100) <= totalChance then
+		local itemType = ItemType(SoulWarQuest.bagYouDesireItemId)
+		if itemType then
+			loot[itemType:getId()] = { count = 1 }
+			logger.debug("Player {} killed {} and got a bag you desire with drop chance {}", player:getName(), monsterName, totalChance)
+		end
+	end
+
+	return loot
+end
+
+local intervalBetweenExecutions = 10000
+
+local accumulatedTime = 0
+local desiredInterval = 40000
+local bossSayInterval = 38000
+
+function Monster:onThinkMegalomaniaWhiteTiles(interval, zonePositions, revertTime)
+	self:onThinkGoshnarTormentCounter(interval, 36, intervalBetweenExecutions, SoulWarQuest.levers.goshnarsMegalomania.boss.position)
+
+	accumulatedTime = accumulatedTime + interval
+
+	if accumulatedTime == bossSayInterval then
+		self:say("FEEL THE POWER OF MY WRATH!!")
+	end
+	-- Execute only after 40 seconds
+	if accumulatedTime >= desiredInterval then
+		self:createSoulWarWhiteTiles(SoulWarQuest.levers.goshnarsMegalomania.boss.position, zonePositions, revertTime)
+		accumulatedTime = 0
+	end
+end
+
+TaintTeleportCooldown = {}
+
+function Player:getTaintNameByNumber(taintNumber)
+	local haveTaintName = nil
+	local soulWarQuest = self:soulWarQuestKV()
+	local taintName = soulWarTaints[taintNumber]
+	if taintName and soulWarQuest:get(taintName) then
+		haveTaintName = taintName
+	end
+
+	return haveTaintName
+end
+
+function Player:addNextTaint()
+	local soulWarQuest = self:soulWarQuestKV()
+	for _, taint in ipairs(soulWarTaints) do
+		if not soulWarQuest:get(taint) then
+			soulWarQuest:set(taint, true)
+			self:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have gained the " .. taint .. ".")
+			break
+		end
+	end
+end
+
+function Player:getTaintLevel()
+	local taintLevel = nil
+	local soulWarQuest = self:soulWarQuestKV()
+	for i, taint in ipairs(soulWarTaints) do
+		if soulWarQuest:get(taint) then
+			taintLevel = i
+		end
+	end
+
+	return taintLevel
+end
+
+function Player:resetTaints()
+	local soulWarQuest = self:soulWarQuestKV()
+	local firstTaintTime = soulWarQuest:get("firstTaintTime")
+	if firstTaintTime and os.time() >= (firstTaintTime + TaintDurationSeconds) then
+		-- Reset all taints
+		for _, taint in ipairs(soulWarTaints) do
+			if soulWarQuest:get(taint) then
+				soulWarQuest:remove(taint)
+			end
+		end
+
+		soulWarQuest:remove("firstTaintTime")
+		self:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Your goshnar's taints have been reset. You didn't finish the quest in 14 days")
+	end
+end
+
+function Monster:tryTeleportToPlayer(sayMessage)
+	local range = 30
+	local spectators = Game.getSpectators(self:getPosition(), false, false, range, range, range, range)
+	local maxDistance = 0
+	local farthestPlayer = nil
+	logger.debug("Checking teleport monster for monster {}", self:getName())
+	for i, spectator in ipairs(spectators) do
+		if spectator:isPlayer() then
+			local player = spectator:getPlayer()
+			if player:getTaintNameByNumber(1) ~= nil then
+				local distance = self:getPosition():getDistance(player:getPosition())
+				if distance > maxDistance then
+					maxDistance = distance
+					farthestPlayer = player
+					logger.debug("Found player {} to teleport", player:getName())
+				end
+			end
+		end
+	end
+
+	if farthestPlayer and math.random(100) <= 10 then
+		local playerPosition = farthestPlayer:getPosition()
+		if TaintTeleportCooldown[farthestPlayer:getId()] then
+			logger.debug("Cooldown is active to player {}", farthestPlayer:getName())
+			return
+		end
+
+		if not TaintTeleportCooldown[farthestPlayer:getId()] then
+			TaintTeleportCooldown[farthestPlayer:getId()] = true
+
+			logger.debug("Scheduling player {} to teleport", farthestPlayer:getName())
+			self:getPosition():sendMagicEffect(CONST_ME_MORTAREA)
+			farthestPlayer:getPosition():sendMagicEffect(CONST_ME_MORTAREA)
+			addEvent(function(playerId, monsterId)
+				local monsterEvent = Monster(monsterId)
+				local playerEvent = Player(playerId)
+				if monsterEvent and playerEvent then
+					local destinationTile = Tile(playerPosition)
+					if destinationTile and not (destinationTile:hasProperty(CONST_PROP_BLOCKPROJECTILE) or destinationTile:hasProperty(CONST_PROP_MOVEABLE)) then
+						monsterEvent:say(sayMessage)
+						monsterEvent:getPosition():sendMagicEffect(CONST_ME_TELEPORT)
+						monsterEvent:teleportTo(playerPosition, true)
+						monsterEvent:getPosition():sendMagicEffect(CONST_ME_TELEPORT)
+					end
+				end
+			end, 2000, farthestPlayer:getId(), self:getId())
+
+			addEvent(function(playerId)
+				local playerEvent = Player(playerId)
+				if not playerEvent then
+					return
+				end
+
+				logger.debug("Cleaning player cooldown")
+				TaintTeleportCooldown[playerEvent:getId()] = nil
+			end, 10000, farthestPlayer:getId())
+		end
+	end
+end
+
+function Monster:getSoulWarKV()
+	return SoulWarQuest.kvSoulWar:scoped("monster"):scoped(self:getName())
+end
+
+function Monster:getHatredDamageMultiplier()
+	return self:getSoulWarKV():get("burning-hatred-empowered") or 0
+end
+
+function Monster:increaseHatredDamageMultiplier(multiplierCount)
+	local attackMultiplier = self:getHatredDamageMultiplier()
+	self:getSoulWarKV():set("burning-hatred-empowered", attackMultiplier + multiplierCount or 10)
+end
+
+function Monster:resetHatredDamageMultiplier()
+	self:getSoulWarKV():remove("burning-hatred-empowered")
+end
+
+function Position:increaseNecromaticMegalomaniaStrength()
+	local tile = Tile(self)
+	if tile then
+		local item = tile:getItemById(SoulWarQuest.necromanticRemainsId)
+		if item then
+			local boss = Creature("Goshnar's Megalomania")
+			if boss then
+				boss:increaseHatredDamageMultiplier(5)
+				item:remove()
+				logger.debug("Necromantic remains strength increased")
+			end
+		end
+	end
+end
+
+local lastExecutionTime = 0
+
+-- Damage 24 to 36 have a special damage
+local damageTable = {
+	1400,
+	1600,
+	1800,
+	2200,
+	2400,
+	2600,
+	3000,
+	3400,
+	3800,
+	4200,
+	4800,
+	5200,
+	5600,
+}
+
+function Monster:onThinkGoshnarTormentCounter(interval, maxLimit, intervalBetweenExecutions, bossPosition)
+	local interval = os.time() * 1000
+	if interval - lastExecutionTime < intervalBetweenExecutions then
+		return
+	end
+
+	lastExecutionTime = interval
+	logger.debug("Icon time count {}", interval)
+	local spectators = Game.getSpectators(bossPosition, false, true, 15, 15, 15, 15)
+	for i = 1, #spectators do
+		local player = spectators[i]
+		local tormentCounter = player:getGoshnarSymbolTormentCounter()
+		if tormentCounter <= maxLimit then
+			player:increaseGoshnarSymbolTormentCounter(maxLimit)
+			logger.debug("Player {} has {} damage counter", player:getName(), tormentCounter)
+
+			if tormentCounter > 0 then
+				local damage = tormentCounter * 35
+				if tormentCounter >= 24 then
+					damage = damageTable[tormentCounter - 23]
+				end
+
+				logger.debug("Final damage {}", damage)
+				player:addHealth(-damage, COMBAT_DEATHDAMAGE)
+				player:getPosition():sendMagicEffect(CONST_ME_PINK_ENERGY_SPARK)
+			end
+		end
+
+		if tormentCounter == 5 then
+			player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "The dread starts to torment you! Don't let dread level reach critical value!")
+		elseif tormentCounter == 15 then
+			player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "The dread's torment becomes unbearable!")
+		elseif tormentCounter == 24 then
+			player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "The Dread's torment begins to tear you apart!")
+		elseif tormentCounter == 30 then
+			player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "The dread's torment is killing you!")
+		elseif tormentCounter == 36 then
+			player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "The dread's torment is now lethal!")
+		end
+	end
+end
+
+function Monster:increaseAspectOfPowerDeathCount()
+	local bossKV = self:getSoulWarKV()
+	local aspectDeathCount = bossKV:get("aspect-of-power-death-count") or 0
+	local newCount = aspectDeathCount + 1
+	logger.debug("Aspect of Power death count {}", newCount)
+	bossKV:set("aspect-of-power-death-count", newCount)
+	if newCount == 4 then
+		self:setType("Goshnar's Megalomania Green")
+		self:say("THE DEATH OF ASPECTS DIMINISHES GOSHNAR'S POWER AND HE TURNS VULNERABLE!")
+		bossKV:set("aspect-of-power-death-count", 0)
+		logger.debug("Aspect of Power defeated all and Megalomania is now vulnerable, reseting death count.")
+		SoulWarQuest.changePurpleEvent = addEvent(function()
+			local boss = Creature("Goshnar's Megalomania")
+			if boss and boss:getTypeName() == "Goshnar's Megalomania Green" then
+				boss:setType("Goshnar's Megalomania Purple")
+				boss:say("GOSHNAR REGAINED ENOUGH POWER TO TURN INVULNERABLE AGAIN!")
+				logger.debug("Megalomania is now immune again")
+			end
+		end, SoulWarQuest.timeToReturnImmuneMegalomania * 1000)
+	end
+end
+
+function Monster:goshnarsDefenseIncrease(kvName)
+	local currentTime = os.time()
+	-- Gets the time when the "Greedy Maw" item was last used.
+	local lastItemUseTime = SoulWarQuest.kvSoulWar:get(kvName) or 0
+	-- Checks if more than config time have passed since the item was last used.
+	if currentTime >= lastItemUseTime + SoulWarQuest.timeToIncreaseCrueltyDefense then
+		logger.debug("{} old defense {}", self:getName(), self:getDefense())
+		self:addDefense(SoulWarQuest.goshnarsCrueltyDefenseChange)
+		logger.debug("{} new defense {}", self:getName(), self:getDefense())
+
+		--- Updates the KV to reflect the timing of the increase to maintain control.
+		SoulWarQuest.kvSoulWar:set(kvName, currentTime)
+	else
+		-- If config time have not passed, logs the increase has been skipped.
+		logger.debug("{} skips increase cooldown due to recent item use.", self:getName())
+	end
+end
+
+function Player:getSoulWarZoneMonster()
+	local zoneMonsterName = nil
+	for zoneName, monsterName in pairs(soulWarSpawnMonsters) do
+		local zone = Zone.getByName(zoneName)
+		if zone and zone:isInZone(self:getPosition()) then
+			zoneMonsterName = monsterName
+			break
+		end
+	end
+
+	return zoneMonsterName
+end
+
+function Player:isInBoatSpot()
+	-- Get ebb and flow zone and check if player is in zone
+	local zone = SoulWarQuest.ebbAndFlow.getZone()
+	local tile = Tile(self:getPosition())
+	local groundId
+	if tile and tile:getGround() then
+		groundId = tile:getGround():getId()
+	end
+	if zone and zone:isInZone(self:getPosition()) and tile and groundId == SoulWarQuest.ebbAndFlow.boatId then
+		logger.debug("Player {} is in boat spot", self:getName())
+		return true
+	end
+
+	logger.debug("Player {} is not in boat spot", self:getName())
+	return false
+end
+
+function Player:soulWarQuestKV()
+	return self:kv():scoped("quest"):scoped("soul-war")
+end
+
+function Player:getGoshnarSymbolTormentCounter()
+	local soulWarKV = self:soulWarQuestKV()
+	return soulWarKV:get("goshnars-hatred-torment-count") or 0
+end
+
+function Player:increaseGoshnarSymbolTormentCounter(maxLimit)
+	local soulWarKV = self:soulWarQuestKV()
+	local tormentCount = self:getGoshnarSymbolTormentCounter()
+	if tormentCount == maxLimit then
+		self:setIcon("goshnars-hatred-damage", CreatureIconCategory_Quests, CreatureIconQuests_RedCross, tormentCount)
+		return
+	end
+
+	self:setIcon("goshnars-hatred-damage", CreatureIconCategory_Quests, CreatureIconQuests_RedCross, tormentCount + 1)
+	soulWarKV:set("goshnars-hatred-torment-count", tormentCount + 1)
+end
+
+function Player:removeGoshnarSymbolTormentCounter(count)
+	local soulWarKV = self:soulWarQuestKV()
+	local tormentCount = self:getGoshnarSymbolTormentCounter()
+	if tormentCount > count then
+		self:setIcon("goshnars-hatred-damage", CreatureIconCategory_Quests, CreatureIconQuests_RedCross, tormentCount - count)
+		soulWarKV:set("goshnars-hatred-torment-count", tormentCount - count)
+	else
+		self:resetGoshnarSymbolTormentCounter()
+	end
+end
+
+function Player:resetGoshnarSymbolTormentCounter()
+	local soulWarKV = self:soulWarQuestKV()
+	soulWarKV:remove("goshnars-hatred-torment-count")
+	self:removeIcon("goshnars-hatred-damage")
+end
+
+function Player:furiousCraterKV()
+	return self:soulWarQuestKV():scoped("furius-crater")
+end
+
+function Player:pulsatingEnergyKV()
+	return self:furiousCraterKV():scoped("pulsating-energy")
+end
+
+function Zone:getRandomPlayer()
+	local players = self:getPlayers()
+	if #players == 0 then
+		return nil
+	end
+
+	local randomIndex = math.random(#players)
+	return players[randomIndex]
+end
+
+local function delayedCastSpell(cid, var, combat, targetId)
+	local creature = Creature(cid)
+	if not creature then
+		return
+	end
+
+	local target = Player(targetId)
+	if target then
+		combat:execute(creature, positionToVariant(target:getPosition()))
+	end
+end
+
+function Creature:applyZoneEffect(var, combat, zoneName)
+	local outfitConfig = {
+		outfit = { lookType = 242, lookHead = 0, lookBody = 0, lookLegs = 0, lookFeet = 0, lookAddons = 0 },
+		time = 7000,
+	}
+
+	local zone = Zone.getByName(zoneName)
+	if not zone then
+		logger.error("Could not find zone '" .. zoneName .. "', you need use the 'BossLever' system")
+		return false
+	end
+
+	local target = zone:getRandomPlayer()
+	if not target then
+		return true
+	end
+
+	local condition = Condition(CONDITION_OUTFIT)
+	condition:setTicks(outfitConfig.time)
+	condition:setOutfit(outfitConfig.outfit)
+	target:addCondition(condition)
+	target:getPosition():sendMagicEffect(CONST_ME_MAGIC_BLUE)
+
+	addEvent(delayedCastSpell, SoulWarQuest.goshnarsCrueltyWaveInterval * 1000, self:getId(), var, combat, target:getId())
+
+	return true
+end
+
+function string.toPosition(str)
+	local patterns = {
+		-- table format
+		"{%s*x%s*=%s*(%d+)%s*,%s*y%s*=%s*(%d+)%s*,%s*z%s*=%s*(%d+)%s*}",
+		-- Position format
+		"Position%s*%((%d+)%s*,%s*(%d+)%s*,%s*(%d+)%s*%)",
+		-- x, y, z format
+		"(%d+)%s*,%s*(%d+)%s*,%s*(%d+)",
+	}
+
+	for _, pattern in ipairs(patterns) do
+		local x, y, z = string.match(str, pattern)
+		if x and y and z then
+			return Position(tonumber(x), tonumber(y), tonumber(z))
+		end
+	end
+end
diff --git a/data-otservbr-global/scripts/quests/soul_war/action-reward_soul_war.lua b/data-otservbr-global/scripts/quests/soul_war/action-reward_soul_war.lua
new file mode 100644
index 00000000000..fae3fc59794
--- /dev/null
+++ b/data-otservbr-global/scripts/quests/soul_war/action-reward_soul_war.lua
@@ -0,0 +1,60 @@
+local rewardSoulWar = Action()
+
+function rewardSoulWar.onUse(creature, item, fromPosition, target, toPosition, isHotkey)
+	local rewardItem = SoulWarQuest.finalRewards[math.random(1, #SoulWarQuest.finalRewards)]
+	local player = creature:getPlayer()
+	if not player then
+		return false
+	end
+
+	local soulWarQuest = player:soulWarQuestKV()
+	if soulWarQuest:get("final-reward") then
+		player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have already received your reward.")
+		return true
+	end
+
+	if not soulWarQuest:get("goshnar's-megalomania-killed") then
+		player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You need to defeat Goshnar's Megalomania to receive your reward.")
+		return true
+	end
+
+	player:addItem(rewardItem.id, 1)
+	player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have found a " .. rewardItem.name .. ".")
+	soulWarQuest:set("final-reward", true)
+	return true
+end
+
+rewardSoulWar:position({ x = 33620, y = 31400, z = 10 })
+rewardSoulWar:register()
+
+local phantasmalJadeMount = Action()
+
+function phantasmalJadeMount.onUse(player, item, fromPosition, target, toPosition, isHotkey)
+	local soulWarQuest = player:soulWarQuestKV()
+	if soulWarQuest:get("panthasmal-jade-mount") then
+		player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You already have Phantasmal Jade mount!")
+		return true
+	end
+
+	if table.contains({ 34072, 34073, 34074 }, item.itemid) then
+		if player:getItemCount(34072) >= 4 and player:getItemCount(34073) == 1 and player:getItemCount(34074) == 1 then
+			player:removeItem(34072, 4)
+			player:removeItem(34073, 1)
+			player:removeItem(34074, 1)
+			player:addMount(167)
+			player:addAchievement("You got Horse Power")
+			player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Congratulations! You won Phantasmal Jade mount.")
+			player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Congratulations! You won You got Horse Power achievement.")
+			player:getPosition():sendMagicEffect(CONST_ME_HOLYDAMAGE)
+			soulWarQuest:set("panthasmal-jade-mount", true)
+		else
+			player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You don't have the necessary items!")
+			player:getPosition():sendMagicEffect(CONST_ME_POFF)
+		end
+	end
+
+	return true
+end
+
+phantasmalJadeMount:id(34072, 34073, 34074)
+phantasmalJadeMount:register()
diff --git a/data-otservbr-global/scripts/quests/soul_war/eventcallback_on_combat_taint.lua b/data-otservbr-global/scripts/quests/soul_war/eventcallback_on_combat_taint.lua
new file mode 100644
index 00000000000..01637f1aff8
--- /dev/null
+++ b/data-otservbr-global/scripts/quests/soul_war/eventcallback_on_combat_taint.lua
@@ -0,0 +1,127 @@
+local taintCooldown = {}
+
+local function createTeleportEffect(position)
+	position:sendMagicEffect(CONST_ME_TELEPORT)
+end
+
+local function scheduleMonsterCreation(player, monster, monsterName, spawnPosition)
+	addEvent(createTeleportEffect, 1000, spawnPosition)
+	addEvent(createTeleportEffect, 2000, spawnPosition)
+	addEvent(createTeleportEffect, 3000, spawnPosition)
+
+	addEvent(function(playerId, monsterId)
+		local eventPlayer = Player(playerId)
+		if not eventPlayer then
+			return
+		end
+
+		local eventMonster = Monster(monsterId)
+		if not eventMonster or eventMonster:isDead() then
+			return
+		end
+
+		-- Only create if the player not have cooldown
+		if not taintCooldown[playerId] or os.time() > taintCooldown[playerId] then
+			taintCooldown[playerId] = os.time() + 30
+			local monster = Game.createMonster(monsterName, spawnPosition, true, true)
+			if monster then
+				spawnPosition:sendMagicEffect(CONST_ME_TELEPORT)
+				logger.debug("Spamming monster with name {} to player {}", monsterName, eventPlayer:getName())
+			end
+		end
+	end, 4000, player:getId(), monster:getId())
+end
+
+local function onPlayerAttackMonster(player, target)
+	local monster = target:getMonster()
+	if not monster then
+		return
+	end
+
+	-- It will only execute if the player has the second taint
+	if player:getTaintNameByNumber(2) ~= nil then
+		local chance = math.random(1, 200)
+		local spawnPosition = player:getPosition()
+		if chance == 1 then -- 0.5% chance
+			local foundMonsterName = player:getSoulWarZoneMonster()
+			if foundMonsterName ~= nil then
+				scheduleMonsterCreation(player, monster, foundMonsterName, spawnPosition)
+			end
+		end
+	end
+end
+
+local function onMonsterAttackPlayer(target, primaryValue, secondaryValue)
+	local targetPlayer = target:getPlayer()
+	if not targetPlayer then
+		return primaryValue, secondaryValue
+	end
+
+	if targetPlayer:getTaintNameByNumber(3) ~= nil then
+		local monsterZone = targetPlayer:getSoulWarZoneMonster()
+		if monsterZone ~= nil then
+			logger.debug("Player {} have third taint, primary value {}, secondary {}", targetPlayer:getName(), primaryValue, secondaryValue)
+			primaryValue = primaryValue + math.ceil(primaryValue * 0.15)
+			secondaryValue = secondaryValue + math.ceil(secondaryValue * 0.15)
+			logger.debug("Primary value after {}, secondary {}", primaryValue, secondaryValue)
+		end
+	end
+
+	return primaryValue, secondaryValue
+end
+
+local callback = EventCallback("CreatureOnCombatTaint")
+
+function callback.creatureOnCombat(caster, target, primaryValue, primaryType, secondaryValue, secondaryType, origin)
+	if not caster or not target then
+		return primaryValue, primaryType, secondaryValue, secondaryType
+	end
+
+	-- Second taint
+	local attackerPlayer = caster:getPlayer()
+	if attackerPlayer and target:isMonster() then
+		onPlayerAttackMonster(attackerPlayer, target)
+	end
+
+	-- Third taint
+	if caster:getMonster() then
+		primaryValue, secondaryValue = onMonsterAttackPlayer(target, primaryValue, secondaryValue)
+	end
+
+	return primaryValue, primaryType, secondaryValue, secondaryType
+end
+
+callback:register()
+
+callback = EventCallback("PlayerOnThinkTaint")
+
+local accumulatedTime = {}
+
+function callback.playerOnThink(player, interval)
+	if not player then
+		return
+	end
+
+	local playerId = player:getId()
+	if not accumulatedTime[playerId] then
+		accumulatedTime[playerId] = 0
+	end
+
+	accumulatedTime[playerId] = accumulatedTime[playerId] + interval
+
+	if accumulatedTime[playerId] >= 10000 then
+		logger.debug("Checking soul war fifth taint, interval {}", interval)
+		local soulWarQuest = player:soulWarQuestKV()
+		if player:getSoulWarZoneMonster() ~= nil and player:getTaintNameByNumber(5) ~= nil then
+			local hpLoss = math.ceil(player:getHealth() * 0.1)
+			local manaLoss = math.ceil(player:getMana() * 0.1)
+			player:addHealth(-hpLoss)
+			player:addMana(-manaLoss)
+			logger.debug("Removing '{}' mana and '{}' health from player {}", manaLoss, hpLoss, player:getName())
+		end
+
+		accumulatedTime[playerId] = 0
+	end
+end
+
+callback:register()
diff --git a/data-otservbr-global/scripts/quests/soul_war/eventcallback_on_drop_loot_bag_you_desire.lua b/data-otservbr-global/scripts/quests/soul_war/eventcallback_on_drop_loot_bag_you_desire.lua
new file mode 100644
index 00000000000..04fe2035956
--- /dev/null
+++ b/data-otservbr-global/scripts/quests/soul_war/eventcallback_on_drop_loot_bag_you_desire.lua
@@ -0,0 +1,16 @@
+local callback = EventCallback("MonsterOnDropBagYouDesire")
+
+function callback.monsterOnDropLoot(monster, corpse)
+	if not monster or not corpse then
+		return
+	end
+
+	local player = Player(corpse:getCorpseOwner())
+	if not player or not player:canReceiveLoot() then
+		return
+	end
+
+	corpse:addLoot(monster:generateBagYouDesireLoot(player))
+end
+
+callback:register()
diff --git a/data-otservbr-global/scripts/quests/soul_war/globalevent-ebb_and_flow_change_maps.lua b/data-otservbr-global/scripts/quests/soul_war/globalevent-ebb_and_flow_change_maps.lua
new file mode 100644
index 00000000000..7bc644448b3
--- /dev/null
+++ b/data-otservbr-global/scripts/quests/soul_war/globalevent-ebb_and_flow_change_maps.lua
@@ -0,0 +1,132 @@
+local function updateWaterPoolsSize()
+	for _, pos in ipairs(SoulWarQuest.ebbAndFlow.poolPositions) do
+		local tile = Tile(pos)
+		if tile then
+			local item = tile:getItemById(SoulWarQuest.ebbAndFlow.smallPoolId)
+			if item then
+				item:transform(SoulWarQuest.ebbAndFlow.MediumPoolId)
+				-- Starts another timer for filling after an additional 40 seconds
+				addEvent(function()
+					local item = tile:getItemById(SoulWarQuest.ebbAndFlow.MediumPoolId)
+					if item then
+						item:transform(SoulWarQuest.ebbAndFlow.smallPoolId)
+					end
+				end, 40000) -- 40 seconds
+			end
+		end
+	end
+end
+
+local function loadMapEmpty()
+	if SoulWarQuest.ebbAndFlow.getZone():countPlayers() > 0 then
+		local players = SoulWarQuest.ebbAndFlow.getZone():getPlayers()
+		for _, player in ipairs(players) do
+			if player:getPosition().z == 8 then
+				if player:isInBoatSpot() then
+					local teleportPosition = player:getPosition()
+					teleportPosition.z = 9
+					player:teleportTo(teleportPosition)
+					logger.debug("Teleporting player to down.")
+				end
+				player:sendCreatureAppear()
+			end
+		end
+	end
+
+	Game.loadMap(SoulWarQuest.ebbAndFlow.mapsPath.empty)
+	SoulWarQuest.ebbAndFlow.setLoadedEmptyMap(true)
+	SoulWarQuest.ebbAndFlow.setActive(false)
+
+	local updatePlayers = EventCallback("UpdatePlayersEmptyEbbFlowMap")
+	function updatePlayers.mapOnLoad(mapPath)
+		if mapPath ~= SoulWarQuest.ebbAndFlow.mapsPath.empty then
+			return
+		end
+
+		SoulWarQuest.ebbAndFlow.updateZonePlayers()
+	end
+
+	updatePlayers:register()
+
+	addEvent(function()
+		-- Change the appearance of puddles to indicate the next filling
+		updateWaterPoolsSize()
+	end, 80000) -- 80 seconds
+end
+
+local function getDistance(pos1, pos2)
+	return math.sqrt((pos1.x - pos2.x) ^ 2 + (pos1.y - pos2.y) ^ 2 + (pos1.z - pos2.z) ^ 2)
+end
+
+local function findNearestRoomPosition(playerPosition)
+	local nearestPosition = nil
+	local smallestDistance = nil
+	for _, room in ipairs(SoulWarQuest.ebbAndFlow.centerRoomPositions) do
+		local distance = getDistance(playerPosition, room.conor)
+		if not smallestDistance or distance < smallestDistance then
+			smallestDistance = distance
+			nearestPosition = room.teleportPosition
+		end
+	end
+	return nearestPosition
+end
+
+local function loadMapInundate()
+	if SoulWarQuest.ebbAndFlow.getZone():countPlayers() > 0 then
+		local players = SoulWarQuest.ebbAndFlow.getZone():getPlayers()
+		for _, player in ipairs(players) do
+			local playerPosition = player:getPosition()
+			if playerPosition.z == 9 then
+				if player:isInBoatSpot() then
+					local nearestCenterPosition = findNearestRoomPosition(playerPosition)
+					player:teleportTo(nearestCenterPosition)
+					logger.debug("Teleporting player to the near center position room and updating tile.")
+				else
+					player:teleportTo(SoulWarQuest.ebbAndFlow.waitPosition)
+					logger.debug("Teleporting player to wait position and updating tile.")
+				end
+				playerPosition:sendMagicEffect(CONST_ME_TELEPORT)
+			end
+			player:sendCreatureAppear()
+		end
+	end
+
+	Game.loadMap(SoulWarQuest.ebbAndFlow.mapsPath.inundate)
+	SoulWarQuest.ebbAndFlow.setLoadedEmptyMap(false)
+	SoulWarQuest.ebbAndFlow.setActive(true)
+
+	local updatePlayers = EventCallback("UpdatePlayersInundateEbbFlowMap")
+	function updatePlayers.mapOnLoad(mapPath)
+		if mapPath ~= SoulWarQuest.ebbAndFlow.mapsPath.inundate then
+			return
+		end
+
+		SoulWarQuest.ebbAndFlow.updateZonePlayers()
+	end
+
+	updatePlayers:register()
+end
+
+local loadEmptyMap = GlobalEvent("SoulWarQuest.ebbAndFlow")
+function loadEmptyMap.onStartup()
+	loadMapEmpty()
+	SoulWarQuest.ebbAndFlow.updateZonePlayers()
+end
+
+loadEmptyMap:register()
+
+local eddAndFlowInundate = GlobalEvent("eddAndFlowInundate")
+function eddAndFlowInundate.onThink(interval, lastExecution)
+	if SoulWarQuest.ebbAndFlow.isLoadedEmptyMap() then
+		logger.debug("Map change to empty in {} minutes.", SoulWarQuest.ebbAndFlow.intervalChangeMap)
+		loadMapInundate()
+	elseif SoulWarQuest.ebbAndFlow.isActive() then
+		logger.debug("Map change to inundate in {} minutes.", SoulWarQuest.ebbAndFlow.intervalChangeMap)
+		loadMapEmpty()
+	end
+
+	return true
+end
+
+eddAndFlowInundate:interval(SoulWarQuest.ebbAndFlow.intervalChangeMap * 60 * 1000)
+eddAndFlowInundate:register()
diff --git a/data-otservbr-global/scripts/quests/soul_war/moveevent-soul_war_entrances.lua b/data-otservbr-global/scripts/quests/soul_war/moveevent-soul_war_entrances.lua
new file mode 100644
index 00000000000..e1728e3a66d
--- /dev/null
+++ b/data-otservbr-global/scripts/quests/soul_war/moveevent-soul_war_entrances.lua
@@ -0,0 +1,151 @@
+local positionsTable = {
+	-- Hunts
+	[Position(33615, 31422, 10)] = Position(34009, 31014, 9), -- hunt infernal demon
+	[Position(33618, 31422, 10)] = Position(33972, 31041, 11), -- hunt rotten
+	[Position(33621, 31422, 10)] = Position(33894, 31019, 8), -- hunt bony sea devil
+	[Position(33624, 31422, 10)] = Position(33858, 31831, 3), -- hunt cloak
+	[Position(33627, 31422, 10)] = Position(33887, 31188, 10), -- hunt many faces
+
+	[Position(34022, 31091, 11)] = Position(33685, 31599, 14), -- goshnar's malice entrance
+}
+
+local soul_war_entrances = MoveEvent()
+
+function soul_war_entrances.onStepIn(creature, item, position, fromPosition)
+	local player = creature:getPlayer()
+	if not player then
+		return
+	end
+
+	if player:getLevel() < 250 then
+		player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You need level 250 to enter here.")
+		player:teleportTo(fromPosition, true)
+		player:getPosition():sendMagicEffect(CONST_ME_TELEPORT)
+		return
+	end
+
+	-- Check if player has access to teleport from Flickering Soul npc: "hi/task/yes"
+	local soulWarQuest = player:soulWarQuestKV()
+	if not soulWarQuest:get("teleport-access") then
+		player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Your soul does not yet resonate with the frequency required to enter here.")
+		player:teleportTo(fromPosition, true)
+		player:getPosition():sendMagicEffect(CONST_ME_TELEPORT)
+		return
+	end
+
+	for position, destination in pairs(positionsTable) do
+		if position == player:getPosition() then
+			fromPosition:sendMagicEffect(CONST_ME_TELEPORT)
+			player:teleportTo(destination)
+			player:getPosition():sendMagicEffect(CONST_ME_TELEPORT)
+			break
+		end
+	end
+
+	return true
+end
+
+for key, value in pairs(positionsTable) do
+	soul_war_entrances:position(key)
+end
+
+soul_war_entrances:register()
+
+local soul_war_megalomania_entrance = MoveEvent()
+
+function soul_war_megalomania_entrance.onStepIn(creature, item, position, fromPosition)
+	local player = creature:getPlayer()
+	if not player then
+		return false
+	end
+
+	local soulWarQuest = player:soulWarQuestKV()
+	if player:getLevel() < 250 then
+		player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You are not allowed to enter here.")
+		player:teleportTo(fromPosition, true)
+		player:getPosition():sendMagicEffect(CONST_ME_TELEPORT)
+		return false
+	end
+
+	local text = ""
+	local soulWarCount = 0
+	for bossName, completed in pairs(SoulWarBosses) do
+		if soulWarQuest:get(bossName) == completed then
+			soulWarCount = soulWarCount + 1
+		else
+			text = text .. "\n" .. bossName
+		end
+	end
+
+	if soulWarCount < 5 then
+		player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You still need to defeat:" .. text)
+		player:teleportTo(fromPosition, true)
+		return false
+	end
+
+	return true
+end
+
+soul_war_megalomania_entrance:position({ x = 33611, y = 31430, z = 10 })
+soul_war_megalomania_entrance:register()
+
+local areasConfig = {
+	[Position(34013, 31049, 9)] = Position(34014, 31058, 9),
+	[Position(34010, 31073, 10)] = Position(34012, 31063, 10),
+	[Position(34009, 31038, 11)] = Position(34012, 31047, 11),
+}
+
+local soul_war_areas_timer = MoveEvent()
+
+function soul_war_areas_timer.onStepIn(creature, item, position, fromPosition)
+	local player = creature:getPlayer()
+	if not player then
+		return false
+	end
+
+	local soulWarQuest = player:soulWarQuestKV()
+	for tablePosition, toPosition in pairs(areasConfig) do
+		if tablePosition == position then
+			player:teleportTo(toPosition)
+			toPosition:sendMagicEffect(CONST_ME_TELEPORT)
+			break
+		end
+	end
+
+	return true
+end
+
+for key, value in pairs(areasConfig) do
+	soul_war_areas_timer:position(key)
+end
+
+soul_war_areas_timer:register()
+
+local goshnarSpiteEntrance = MoveEvent()
+
+function goshnarSpiteEntrance.onStepIn(creature, item, position, fromPosition)
+	local player = creature:getPlayer()
+	if not player then
+		return false
+	end
+
+	local soulWarQuest = player:soulWarQuestKV()
+	local killCount = soulWarQuest:get("hazardous-phantom-death") or 0
+	if killCount < 20 then
+		player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have killed " .. killCount .. " and need to kill 20 Hazardous Phantoms")
+		player:teleportTo(fromPosition, true)
+		player:getPosition():sendMagicEffect(CONST_ME_TELEPORT)
+		return false
+	end
+
+	if position == SoulWarQuest.goshnarSpiteEntrancePosition.fromPos then
+		player:teleportTo(SoulWarQuest.goshnarSpiteEntrancePosition.toPos)
+		player:getPosition():sendMagicEffect(CONST_ME_TELEPORT)
+		return true
+	end
+
+	return false
+end
+
+goshnarSpiteEntrance:position(SoulWarQuest.goshnarSpiteEntrancePosition.fromPos)
+goshnarSpiteEntrance:register()
diff --git a/data-otservbr-global/scripts/actions/quests/soul_war/portal_reward_soulwar.lua b/data-otservbr-global/scripts/quests/soul_war/moveevent-teleport_entrance_reward.lua
similarity index 78%
rename from data-otservbr-global/scripts/actions/quests/soul_war/portal_reward_soulwar.lua
rename to data-otservbr-global/scripts/quests/soul_war/moveevent-teleport_entrance_reward.lua
index cf999f89c7b..7aaff112056 100644
--- a/data-otservbr-global/scripts/actions/quests/soul_war/portal_reward_soulwar.lua
+++ b/data-otservbr-global/scripts/quests/soul_war/moveevent-teleport_entrance_reward.lua
@@ -1,10 +1,14 @@
 local portalReward = MoveEvent()
+
 function portalReward.onStepIn(creature, item, position, fromPosition)
 	local player = creature:getPlayer()
 	if not player then
 		return false
 	end
-	if player:getStorageValue(Storage.Quest.U12_40.SoulWar.GoshnarMegalomaniaKilled) < 1 then
+
+	local soulWarQuest = player:soulWarQuestKV()
+	-- Checks if the boss has already been defeated
+	if not soulWarQuest:get("goshnar's-megalomania-killed") then
 		player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Only warriors who defeated Goshnar's Megalomania can access this area.")
 		player:teleportTo(fromPosition, true)
 		return false
@@ -15,6 +19,5 @@ function portalReward.onStepIn(creature, item, position, fromPosition)
 	return true
 end
 
-portalReward:type("stepin")
 portalReward:position({ x = 33621, y = 31416, z = 10 })
 portalReward:register()
diff --git a/data-otservbr-global/scripts/quests/soul_war/soul_war_mechanics.lua b/data-otservbr-global/scripts/quests/soul_war/soul_war_mechanics.lua
new file mode 100644
index 00000000000..8daa70f3060
--- /dev/null
+++ b/data-otservbr-global/scripts/quests/soul_war/soul_war_mechanics.lua
@@ -0,0 +1,1081 @@
+-- Register levers
+local goshnarsMaliceLever = BossLever(SoulWarQuest.levers.goshnarsMalice)
+goshnarsMaliceLever:position(SoulWarQuest.levers.goshnarsMalicePosition)
+goshnarsMaliceLever:register()
+logger.debug("Registering soul war boss lever zone: {}", goshnarsMaliceLever:getZone():getName())
+
+local goshnarsSpiteLever = BossLever(SoulWarQuest.levers.goshnarsSpite)
+goshnarsSpiteLever:position(SoulWarQuest.levers.goshnarsSpitePosition)
+goshnarsSpiteLever:register()
+logger.debug("Registering soul war boss lever zone: {}", goshnarsSpiteLever:getZone():getName())
+
+local goshnarsGreedLever = BossLever(SoulWarQuest.levers.goshnarsGreed)
+goshnarsGreedLever:position(SoulWarQuest.levers.goshnarsGreedPosition)
+goshnarsGreedLever:register()
+logger.debug("Registering soul war boss lever zone: {}", goshnarsGreedLever:getZone():getName())
+
+local goshnarsHatredLever = BossLever(SoulWarQuest.levers.goshnarsHatred)
+goshnarsHatredLever:position(SoulWarQuest.levers.goshnarsHatredPosition)
+goshnarsHatredLever:register()
+logger.debug("Registering soul war boss lever zone: {}", goshnarsHatredLever:getZone():getName())
+
+local goshnarsCrueltyLever = BossLever(SoulWarQuest.levers.goshnarsCruelty)
+goshnarsCrueltyLever:position(SoulWarQuest.levers.goshnarsCrueltyPosition)
+goshnarsCrueltyLever:register()
+logger.debug("Registering soul war boss lever zone: {}", goshnarsCrueltyLever:getZone():getName())
+
+local goshnarsMegalomaniaLever = BossLever(SoulWarQuest.levers.goshnarsMegalomania)
+goshnarsMegalomaniaLever:position(SoulWarQuest.levers.goshnarsMegalomaniaPosition)
+goshnarsMegalomaniaLever:register()
+logger.debug("Registering soul war boss lever zone: {}", goshnarsMegalomaniaLever:getZone():getName())
+
+local login = CreatureEvent("SoulWarLogin")
+
+function login.onLogin(player)
+	player:registerEvent("GoshnarsHatredBuff")
+	player:resetTaints()
+	player:resetGoshnarSymbolTormentCounter()
+	return true
+end
+
+login:register()
+
+-- Goshnar's Malice reflection (100%) of physical and death damage
+local goshnarsMaliceReflection = CreatureEvent("Goshnar's-Malice")
+
+function goshnarsMaliceReflection.onHealthChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin)
+	local player = attacker:getPlayer()
+	if player then
+		if primaryDamage > 0 and (primaryType == COMBAT_PHYSICALDAMAGE or primaryType == COMBAT_DEATHDAMAGE) then
+			player:addHealth(-primaryDamage)
+		end
+		if secondaryDamage > 0 and (secondaryType == COMBAT_PHYSICALDAMAGE or secondaryType == COMBAT_DEATHDAMAGE) then
+			player:addHealth(-secondaryDamage)
+		end
+	end
+
+	return primaryDamage, primaryType, secondaryDamage, secondaryType
+end
+
+goshnarsMaliceReflection:register()
+
+local soulCageReflection = CreatureEvent("SoulCageHealthChange")
+
+function soulCageReflection.onHealthChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin)
+	local player = attacker:getPlayer()
+	if player then
+		if primaryDamage > 0 then
+			player:addHealth(-primaryDamage * 0.1)
+		end
+		if secondaryDamage > 0 then
+			player:addHealth(-secondaryDamage * 0.1)
+		end
+	end
+
+	return primaryDamage, primaryType, secondaryDamage, secondaryType
+end
+
+soulCageReflection:register()
+
+local soulCageDeath = CreatureEvent("SoulCageDeath")
+
+function soulCageDeath.onDeath(creature, corpse, killer, mostDamageKiller, lastHitUnjustified, mostDamageUnjustified)
+	if not creature or creature:isPlayer() or creature:getMaster() then
+		return true
+	end
+
+	addEvent(SpawnSoulCage, 23000)
+end
+
+soulCageDeath:register()
+
+local fourthTaintBossesDeath = CreatureEvent("FourthTaintBossesPrepareDeath")
+
+function fourthTaintBossesDeath.onPrepareDeath(creature, killer, realDamage)
+	if not creature or not killer:getPlayer() then
+		return true
+	end
+
+	if creature:getHealth() - realDamage < 1 then
+		if killer:getTaintNameByNumber(4) then
+			local isInZone = killer:getSoulWarZoneMonster()
+			if isInZone ~= nil then
+				-- 10% of chance to heal
+				if math.random(1, 10) == 1 then
+					creature:say("Health restored by the mystic powers of Zarganash!")
+					creature:addHealth(creature:getMaxHealth())
+				end
+			end
+		end
+	end
+	return true
+end
+
+fourthTaintBossesDeath:register()
+
+local bossesDeath = CreatureEvent("SoulWarBossesDeath")
+
+function bossesDeath.onDeath(creature, corpse, killer, mostDamageKiller, lastHitUnjustified, mostDamageUnjustified)
+	local bossName = creature:getName()
+	if SoulWarBosses[bossName] then
+		local killers = creature:getKillers(true)
+		for i, killerPlayer in ipairs(killers) do
+			local soulWarQuest = killerPlayer:soulWarQuestKV()
+			-- Checks if the boss has already been defeated
+			if not soulWarQuest:get(bossName) then
+				local firstTaintTime = soulWarQuest:get("firstTaintTime")
+				if not firstTaintTime then
+					local currentTime = os.time()
+					soulWarQuest:set("firstTaintTime", currentTime)
+				end
+
+				soulWarQuest:set(bossName, true) -- Mark the boss as defeated
+				-- Adds the next taint in the sequence that the player does not already have
+				killerPlayer:addNextTaint()
+			end
+		end
+	end
+end
+
+bossesDeath:register()
+
+fourthTaintBossesDeath:register()
+
+local mirroredNightmareApparitionDeath = CreatureEvent("MirroredNightmareBossAccess")
+
+function mirroredNightmareApparitionDeath.onDeath(creature, corpse, killer, mostDamageKiller, lastHitUnjustified, mostDamageUnjustified)
+	local creatureName = creature:getName()
+	if table.contains(SoulWarQuest.apparitionNames, creatureName) then
+		local damageMap = creature:getMonster():getDamageMap()
+		for key, _ in pairs(damageMap) do
+			local player = Player(key)
+			if player then
+				local soulWarQuest = player:soulWarQuestKV()
+				local currentCount = soulWarQuest:get(creatureName) or 0
+				soulWarQuest:set(creatureName, currentCount + 1)
+			end
+		end
+	end
+end
+
+mirroredNightmareApparitionDeath:register()
+
+-- Check mirrored nightmare boss access
+local goshnarGreedEntrance = MoveEvent()
+
+function goshnarGreedEntrance.onStepIn(creature, item, position, fromPosition)
+	local player = creature:getPlayer()
+	if not player then
+		return false
+	end
+
+	local soulWarQuest = player:soulWarQuestKV()
+	local hasAccess = true
+	local message = "Progress towards Mirrored Nightmare boss access:\n"
+
+	for _, apparitionName in pairs(SoulWarQuest.apparitionNames) do
+		local count = soulWarQuest:get(apparitionName) or 0
+		if count < SoulWarQuest.requiredCountPerApparition then
+			hasAccess = false
+			message = message .. apparitionName .. ": " .. count .. "/" .. SoulWarQuest.requiredCountPerApparition .. " kills\n"
+		else
+			message = message .. apparitionName .. ": Access achieved!\n"
+		end
+	end
+
+	if not hasAccess then
+		player:sendTextMessage(MESSAGE_EVENT_ADVANCE, message)
+		player:teleportTo(fromPosition)
+		return false
+	end
+
+	player:teleportTo(SoulWarQuest.goshnarsGreedAccessPosition.to)
+	player:getPosition():sendMagicEffect(CONST_ME_TELEPORT)
+	return true
+end
+
+goshnarGreedEntrance:position(SoulWarQuest.goshnarsGreedAccessPosition.from)
+goshnarGreedEntrance:register()
+
+local greedMonsterDeath = CreatureEvent("GreedMonsterDeath")
+
+function greedMonsterDeath.onDeath(creature, corpse, killer, mostDamageKiller, lastHitUnjustified, mostDamageUnjustified)
+	local createMonsterPosition = GreedMonsters[creature:getName()]
+	if creature:getName() == "Greedbeast" then
+		GreedbeastKills = GreedbeastKills + 1
+	end
+
+	CreateGoshnarsGreedMonster(creature:getName(), createMonsterPosition)
+end
+
+greedMonsterDeath:register()
+
+local checkTaint = TalkAction("!checktaint")
+
+function checkTaint.onSay(player, words, param)
+	local taintLevel = player:getTaintLevel()
+	local taintName = player:getTaintNameByNumber(taintLevel)
+	if taintLevel ~= nil and taintName ~= nil then
+		player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Your current taint level is: " .. taintLevel .. " name: " .. taintName)
+	else
+		player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You currently have no taint.")
+	end
+
+	return true
+end
+
+checkTaint:groupType("normal")
+checkTaint:register()
+
+local setTaint = TalkAction("/settaint")
+
+function setTaint.onSay(player, words, param)
+	local split = param:split(",")
+	local target = Player(split[1])
+	if not target then
+		player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Player is offline")
+		return false
+	end
+
+	local taintLevel = split[2]:trim():lower()
+	local taintName = player:getTaintNameByNumber(tonumber(taintLevel))
+	if taintName ~= nil then
+		target:soulWarQuestKV():set(taintName, true)
+		target:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You new taint level is: " .. taintLevel .. ", name: " .. taintName)
+		player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Added taint level: " .. taintLevel .. ", name: " .. taintName .. " to player: " .. target:getName())
+	end
+end
+
+setTaint:separator(" ")
+setTaint:groupType("god")
+setTaint:register()
+
+local goshnarGreedTeleport = MoveEvent()
+
+function goshnarGreedTeleport.onStepIn(creature, item, position, fromPosition)
+	local creatureName = creature:getName()
+	if creatureName == "Greedbeast" then
+		return
+	end
+
+	local foundCreaturePosition = GreedMonsters[creatureName]
+	if not foundCreaturePosition then
+		return false
+	end
+
+	if item:getId() == 33791 then
+		creature:remove()
+		item:transform(33790)
+		position:sendMagicEffect(CONST_ME_MORTAREA)
+		CreateGoshnarsGreedMonster(creatureName, foundCreaturePosition)
+	end
+
+	return true
+end
+
+goshnarGreedTeleport:id(33790, 33791)
+goshnarGreedTeleport:register()
+
+local setTaint = TalkAction("/removetaint")
+
+function setTaint.onSay(player, words, param)
+	local split = param:split(",")
+	local target = Player(split[1])
+	if not target then
+		player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Player is offline")
+		return false
+	end
+
+	local taintLevel = split[2]:trim():lower()
+	local taintName = player:getTaintNameByNumber(tonumber(taintLevel))
+	if taintName ~= nil then
+		target:soulWarQuestKV():remove(taintName)
+		target:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You lose taint level: " .. taintLevel .. ", name: " .. taintName)
+		player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Removed taint level: " .. taintLevel .. ", name: " .. taintName .. " from player: " .. target:getName())
+	end
+end
+
+setTaint:separator(" ")
+setTaint:groupType("god")
+setTaint:register()
+
+local setTaint = TalkAction("/changeflowmap")
+
+function setTaint.onSay(player, words, param)
+	if param == "empty" then
+		Game.loadMap("data-otservbr-global/world/quest/soul_war/ebb_and_flow/empty.otbm")
+	elseif param == "inundate" then
+		Game.loadMap("data-otservbr-global/world/quest/soul_war/ebb_and_flow/inundate.otbm")
+	elseif param == "ebb" then
+		Game.loadMap("data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb_and_flow.otbm")
+	end
+end
+
+setTaint:separator(" ")
+setTaint:groupType("god")
+setTaint:register()
+
+local hazardousPhantomDeath = CreatureEvent("HazardousPhantomDeath")
+
+function hazardousPhantomDeath.onDeath(creature, corpse, killer, mostDamageKiller, lastHitUnjustified, mostDamageUnjustified)
+	local killers = creature:getKillers(true)
+	for i, killerPlayer in ipairs(killers) do
+		-- Checks if the killer is a player
+		if killerPlayer:isPlayer() then
+			local soulWarQuest = killerPlayer:soulWarQuestKV()
+			local deathCount = soulWarQuest:get("hazardous-phantom-death") or 0
+			-- Checks that the death count has not yet reached the limit
+			if deathCount < SoulWarQuest.hardozousPanthomDeathCount then
+				-- Increases death count
+				soulWarQuest:set("hazardous-phantom-death", deathCount + 1)
+				-- Send the count for the player
+				killerPlayer:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You killed " .. (deathCount + 1) .. " of " .. SoulWarQuest.hardozousPanthomDeathCount .. " Hazardous Panthom.")
+			end
+
+			if deathCount + 1 == SoulWarQuest.hardozousPanthomDeathCount then
+				killerPlayer:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You can now access the boss room.")
+			end
+		end
+	end
+end
+
+hazardousPhantomDeath:register()
+
+local weepingSoulCorpse = MoveEvent()
+
+local condition = Condition(CONDITION_OUTFIT)
+condition:setOutfit(SoulWarQuest.waterElementalOutfit)
+condition:setTicks(14000)
+
+function weepingSoulCorpse.onStepIn(creature, item, position, fromPosition)
+	local player = creature:getPlayer()
+	if not player then
+		return
+	end
+
+	if player:hasCondition(CONDITION_OUTFIT) then
+		return
+	end
+
+	local zone = Zone.getByName("boss.goshnar's-spite")
+	if not zone then
+		logger.error("Goshnar's Spite zone not found. Check the lever boss register.")
+		return
+	end
+
+	local monsters = zone:getMonsters()
+	for _, monster in ipairs(monsters) do
+		if monster:getName() == "Goshnar's Spite" then
+			local chance = math.random(100)
+			if chance <= SoulWarQuest.goshnarsSpiteHealChance then
+				local healAmount = math.floor(monster:getMaxHealth() * (SoulWarQuest.goshnarsSpiteHealPercentage / 100))
+				-- Heal percentage of the maximum health
+				monster:addHealth(healAmount)
+				logger.debug("Goshnar's Spite was healed to 10% of its maximum health.")
+			end
+			break
+		end
+	end
+
+	item:remove()
+	player:addCondition(condition)
+	player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You are soaked by tears of the weeping soul!")
+	return true
+end
+
+weepingSoulCorpse:id(SoulWarQuest.weepingSoulCorpseId)
+weepingSoulCorpse:register()
+
+local function removeSearingFire(position)
+	local tile = Tile(position)
+	if tile then
+		local fire = tile:getItemById(SoulWarQuest.searingFireId)
+		if fire then
+			local zone = Zone.getByName("boss.goshnar's-spite")
+			if not zone then
+				logger.error("Goshnar's Spite zone not found. Check the lever boss register.")
+				return
+			end
+
+			local monsters = zone:getMonsters()
+			for _, monster in ipairs(monsters) do
+				if monster:getName() == "Goshnar's Spite" then
+					monster:addDefense(SoulWarQuest.goshnarsSpiteIncreaseDefense)
+					logger.debug("Found Goshnar's Spite on boss zone, adding defense.")
+					break
+				end
+			end
+			fire:remove()
+		end
+	end
+end
+
+local goshnarSpiteFire = GlobalEvent("CreateGoshnarSpiteFire")
+
+function goshnarSpiteFire.onThink(interval)
+	local randomIndex = math.random(#SoulWarQuest.goshnarsSpiteFirePositions) -- Choose a random index
+	local firePosition = SoulWarQuest.goshnarsSpiteFirePositions[randomIndex] -- Get the corresponding position
+	local tile = Tile(firePosition)
+	if tile then
+		local fire = Game.createItem(SoulWarQuest.searingFireId, 1, firePosition)
+		if fire then
+			addEvent(removeSearingFire, SoulWarQuest.timeToRemoveSearingFire * 1000, firePosition)
+		end
+	end
+
+	return true
+end
+
+goshnarSpiteFire:interval(SoulWarQuest.timeToCreateSearingFire * 1000)
+goshnarSpiteFire:register()
+
+local goshnarSpiteSoulFire = MoveEvent()
+
+function goshnarSpiteSoulFire.onStepIn(creature, item, position, fromPosition)
+	local player = creature:getPlayer()
+	if not player then
+		return
+	end
+
+	local tile = Tile(position)
+	if not tile then
+		return
+	end
+
+	local searingFire = tile:getItemById(SoulWarQuest.searingFireId)
+	if not searingFire then
+		return
+	end
+
+	local soulWarQuest = player:soulWarQuestKV()
+	local lastSteppedTime = soulWarQuest:get("goshnar-spite-fire") or 0
+	local currentTime = os.time()
+
+	if lastSteppedTime + SoulWarQuest.cooldownToStepOnSearingFire > currentTime then
+		local remainingTime = lastSteppedTime + SoulWarQuest.cooldownToStepOnSearingFire - currentTime
+		player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "His soul won't need to recover again! You need wait " .. remainingTime .. " seconds.")
+		return true
+	end
+
+	addEvent(function(playerId)
+		local eventPlayer = Player(playerId)
+		if eventPlayer then
+			eventPlayer:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Your soul has recovered!")
+		end
+	end, SoulWarQuest.cooldownToStepOnSearingFire * 1000, player:getId())
+
+	soulWarQuest:set("goshnar-spite-fire", currentTime)
+	searingFire:remove()
+	player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "The soul fire was stomped out in time! Your soul will now have to recover before you can do this again.")
+
+	return true
+end
+
+for _, pos in pairs(SoulWarQuest.goshnarsSpiteFirePositions) do
+	goshnarSpiteSoulFire:position(pos)
+end
+
+goshnarSpiteSoulFire:register()
+
+local ebbAndFlowBoatTeleports = MoveEvent()
+
+function ebbAndFlowBoatTeleports.onStepIn(creature, item, position, fromPosition)
+	local player = creature:getPlayer()
+	if not player or not SoulWarQuest.ebbAndFlow.isActive() then
+		return
+	end
+
+	for _, pos in pairs(SoulWarQuest.ebbAndFlowBoatTeleportPositions) do
+		if Position(pos.register) == position then
+			player:teleportTo(pos.teleportTo)
+			player:getPosition():sendMagicEffect(CONST_ME_TELEPORT)
+			return true
+		end
+	end
+end
+
+for _, pos in pairs(SoulWarQuest.ebbAndFlowBoatTeleportPositions) do
+	ebbAndFlowBoatTeleports:position(pos.register)
+end
+ebbAndFlowBoatTeleports:register()
+
+local ebbAndFlowDoor = Action()
+
+function ebbAndFlowDoor.onUse(player, item, fromPosition, target, toPosition, isHotkey)
+	if SoulWarQuest.ebbAndFlow.isActive() then
+		return false
+	end
+
+	-- Determines whether the player is north or south of the door
+	local playerPosition = player:getPosition()
+	local destination = Position(toPosition.x, toPosition.y, toPosition.z)
+	if playerPosition.y < toPosition.y then
+		-- Player is north, move south
+		destination.y = toPosition.y + 1
+	else
+		-- Player is south (or at the same y position), moves north
+		destination.y = toPosition.y - 1
+	end
+
+	player:teleportTo(destination)
+	destination:sendMagicEffect(CONST_ME_TELEPORT)
+	return true
+end
+
+ebbAndFlowDoor:id(SoulWarQuest.ebbAndFlow.doorId)
+ebbAndFlowDoor:register()
+
+local rottenWastelandShrines = Action()
+
+function rottenWastelandShrines.onUse(player, item, fromPosition, target, toPosition, isHotkey)
+	local soulWarQuest = player:soulWarQuestKV()
+	local shrineUsed = soulWarQuest:get("rotten-wasterland-activated-shrine-id") or 0
+	if shrineUsed == item:getId() then
+		player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have already activated this shrine.")
+		return true
+	end
+
+	local activatedShrinesCount = soulWarQuest:get("rotten-wasterland-activated-shrine-count") or 0
+	if activatedShrinesCount >= 4 then
+		player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have already activated all the shrines.")
+		return true
+	end
+
+	soulWarQuest:set("rotten-wasterland-activated-shrine-id", item:getId())
+
+	soulWarQuest:set("rotten-wasterland-activated-shrine-count", activatedShrinesCount + 1)
+	player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have activated this shrine.")
+	return true
+end
+
+for itemId, position in pairs(SoulWarQuest.rottenWastelandShrines) do
+	rottenWastelandShrines:id(itemId)
+end
+
+rottenWastelandShrines:register()
+
+local goshnarsHatredAccess = Action()
+
+function goshnarsHatredAccess.onUse(player, item, fromPosition, target, toPosition, isHotkey)
+	local soulWarQuest = player:soulWarQuestKV()
+	local activatedShrineCount = soulWarQuest:get("rotten-wasterland-activated-shrine-count") or 0
+	if activatedShrineCount < 4 then
+		player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You still need to activate all the shrines.")
+		return true
+	end
+
+	player:teleportTo(SoulWarQuest.goshnarsHatredAccessPosition.to)
+	player:getPosition():sendMagicEffect(CONST_ME_TELEPORT)
+	return true
+end
+
+goshnarsHatredAccess:position(SoulWarQuest.goshnarsHatredAccessPosition.from)
+goshnarsHatredAccess:register()
+
+local burningHatredMonsters = {
+	"Ashes of Burning Hatred",
+	"Spark of Burning Hatred",
+	"Flame of Burning Hatred",
+	"Blaze of Burning Hatred",
+}
+
+local goshnarsHatredSorrow = Action()
+
+function goshnarsHatredSorrow.onUse(player, item, fromPosition, target, toPosition, isHotkey)
+	logger.debug("Player {} used the item {} on target {}.", player:getName(), item:getId(), target:getName())
+	if not target then
+		return
+	end
+
+	if not table.contains(burningHatredMonsters, target:getName()) then
+		logger.error("Player {} tried to use the item on a non-burning hatred monster.", player:getName())
+		return
+	end
+
+	item:remove()
+	local actualTime = SoulWarQuest.kvBurning:get("time") or 0
+	SoulWarQuest.kvBurning:set("time", actualTime + 10)
+	logger.debug("Player {} used the item on the monster {}, oldTime {}, newTime {}.", player:getName(), target:getName(), actualTime, actualTime + 10)
+	player:say("The flame of hatred is doused!", TALKTYPE_MONSTER_SAY, 0, 0, target:getPosition())
+	return true
+end
+
+goshnarsHatredSorrow:id(SoulWarQuest.goshnarsHatredSorrowId)
+goshnarsHatredSorrow:register()
+
+local burningChangeForm = CreatureEvent("BurningChangeForm")
+
+function burningChangeForm.onThink(creature)
+	if not creature or not creature:getMonster() then
+		return true
+	end
+
+	local monster = creature:getMonster()
+	local currentTime = SoulWarQuest.kvBurning:get("time") or 0
+	if currentTime == 0 then
+		SoulWarQuest.kvBurning:set("time", 180)
+		return true
+	end
+
+	SoulWarQuest.kvBurning:set("time", currentTime - 1)
+
+	logger.debug("Burning transformation decreased to time : {}", currentTime)
+	for _, transformation in ipairs(SoulWarQuest.burningTransformations) do
+		local timeTransformation, newType = unpack(transformation)
+		if currentTime == timeTransformation and monster:getName() ~= newType then
+			monster:setType(newType, true)
+			logger.debug("Changing monster to {} on currentTime {}.", newType, currentTime)
+
+			if newType == "Ashes of Burning Hatred" then
+				monster:say("The fire of hatred fuels and empowers Goshnar's Hate!", TALKTYPE_MONSTER_SAY, 0, 0, monster:getPosition())
+				local boss = Creature("Goshnar's Hatred")
+				if boss then
+					logger.debug("Increasing hatred damage multiplier.")
+					boss:increaseHatredDamageMultiplier()
+				end
+				logger.debug("Beginning of the burning transformation cycle.")
+			end
+			break
+		end
+	end
+
+	return true
+end
+
+burningChangeForm:register()
+
+local goshnarsHatredBuff = CreatureEvent("GoshnarsHatredBuff")
+
+function goshnarsHatredBuff.onHealthChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin)
+	-- Ensure both attacker and creature are valid and the creature is "Goshnar's Hatred"
+	if creature then
+		-- Check if the attacker is a player and the creature is being hit
+		if attacker and creature:isMonster() and attacker:isPlayer() and (creature:getName() == "Goshnar's Hatred" or creature:getName() == "Goshnar's Megalomania") then
+			local defenseMultiplier = creature:getHatredDamageMultiplier()
+			if defenseMultiplier > 0 then
+				-- Apply the defense multiplier
+				creature:addDefense(defenseMultiplier)
+				logger.debug("Adding defense to {}.", creature:getName())
+			end
+		-- Check if the attacker is a monster and the player is being hit
+		elseif attacker and creature:isPlayer() and attacker:isMonster() and (attacker:getName() == "Goshnar's Hatred" or creature:getName() == "Goshnar's Megalomania") then
+			local damageMultiplier = attacker:getHatredDamageMultiplier()
+			if damageMultiplier > 0 then
+				local multip = 1 + (damageMultiplier / 100)
+				logger.debug("Adding damage: {} to {}.", multip, attacker:getName())
+				-- Return modified damage values
+				return primaryDamage * multip, primaryType, secondaryDamage, secondaryType
+			end
+		end
+	end
+
+	-- Return original damage values if no conditions are met
+	return primaryDamage, primaryType, secondaryDamage, secondaryType
+end
+
+goshnarsHatredBuff:register()
+
+local condensedRemorse = MoveEvent()
+
+function condensedRemorse.onStepIn(creature, item, position, fromPosition)
+	local player = creature:getPlayer()
+	if not player then
+		return false
+	end
+
+	local soulWarKV = player:soulWarQuestKV()
+	local remorseCount = soulWarKV:get("condensed-remorse") or 0
+	soulWarKV:set("condensed-remorse", remorseCount + 1)
+	if remorseCount + 1 == 2 then
+		player:resetGoshnarSymbolTormentCounter()
+		player:say("The remorse calms your dread!", TALKTYPE_MONSTER_SAY, 0, 0, item:getPosition())
+		player:getPosition():sendMagicEffect(CONST_ME_HOLYAREA)
+		soulWarKV:remove("condensed-remorse")
+	end
+
+	item:remove()
+	return true
+end
+
+condensedRemorse:id(SoulWarQuest.condensedRemorseId)
+condensedRemorse:register()
+
+local furiousCraterAccess = EventCallback("FuriousCraterAccessDropLoot")
+
+function furiousCraterAccess.monsterOnDropLoot(monster, corpse)
+	if not monster or not corpse then
+		return
+	end
+
+	local player = Player(corpse:getCorpseOwner())
+	if not player or not player:canReceiveLoot() then
+		return
+	end
+
+	local mType = monster:getType()
+	if not mType then
+		return
+	end
+
+	if not table.contains(SoulWarQuest.pulsatingEnergyMonsters, mType:getName()) then
+		return
+	end
+
+	Game.createItem(SoulWarQuest.pulsatingEnergyId, 1, monster:getPosition())
+end
+
+furiousCraterAccess:register()
+
+local pulsatingEnergy = MoveEvent()
+
+function pulsatingEnergy.onStepIn(creature, item, position, fromPosition)
+	local player = creature:getPlayer()
+	if not player then
+		return false
+	end
+
+	local kv = player:pulsatingEnergyKV()
+	local energyCount = kv:get("access-counter") or 0
+	energyCount = energyCount + 1
+	kv:set("access-counter", energyCount)
+
+	logger.debug("Player {} stepped on a pulsating energy, current count: {}", player:getName(), energyCount)
+
+	local firstFloorAccess = kv:get("first-floor-access") or false
+	local secondFloorAccess = kv:get("second-floor-access") or false
+	local thirdFloorAccess = kv:get("third-floor-access") or false
+	if thirdFloorAccess then
+		player:sendTextMessage(MESSAGE_INFO_DESCR, "You've already gained access to fight with the Goshnar's Cruelty.")
+		return true
+	end
+
+	if energyCount >= 40 and not firstFloorAccess then
+		kv:set("access-counter", 0)
+		kv:set("first-floor-access", true)
+		player:sendTextMessage(MESSAGE_INFO_DESCR, "You've gained access to the first floor. Continue collecting Pulsating Energies to gain further access.")
+	end
+
+	if energyCount >= 55 and not secondFloorAccess then
+		kv:set("access-counter", 0)
+		kv:set("second-floor-access", true)
+		player:sendTextMessage(MESSAGE_INFO_DESCR, "You've gained access to the second floor. Continue collecting Pulsating Energies to gain further access.")
+	end
+
+	if energyCount >= 70 and not thirdFloorAccess then
+		kv:set("access-counter", 0)
+		kv:set("third-floor-access", true)
+		player:sendTextMessage(MESSAGE_INFO_DESCR, "You've gained access to the third floor. You can now fight with the Goshnar's Cruelty.")
+	end
+
+	item:remove()
+	return true
+end
+
+pulsatingEnergy:id(SoulWarQuest.pulsatingEnergyId)
+pulsatingEnergy:register()
+
+local pulsatingEnergyTeleportAccess = MoveEvent()
+
+function pulsatingEnergyTeleportAccess.onStepIn(creature, item, position, fromPosition)
+	local player = creature:getPlayer()
+	if not player then
+		return false
+	end
+
+	for _, posData in pairs(SoulWarQuest.goshnarsCrueltyTeleportRoomPositions) do
+		if posData.from == position then
+			local kv = player:pulsatingEnergyKV()
+			local hasAccess = kv:get(posData.access) or false
+			local energyCount = kv:get("access-counter") or 0
+			local energiesNeeded = posData.count - energyCount
+			if not hasAccess then
+				player:sendTextMessage(MESSAGE_INFO_DESCR, "You don't have access to this floor yet. You have collected " .. energyCount .. "/" .. posData.count .. ", and need " .. energiesNeeded .. " more pulsating energies to gain access.")
+				player:teleportTo(fromPosition, true)
+				fromPosition:sendMagicEffect(CONST_ME_TELEPORT)
+			else
+				player:teleportTo(posData.to)
+				posData.to:sendMagicEffect(CONST_ME_TELEPORT)
+			end
+
+			break
+		end
+	end
+
+	return true
+end
+
+for _, positions in pairs(SoulWarQuest.goshnarsCrueltyTeleportRoomPositions) do
+	pulsatingEnergyTeleportAccess:position(positions.from)
+end
+
+pulsatingEnergyTeleportAccess:register()
+
+local cloakOfTerrorHealthLoss = CreatureEvent("CloakOfTerrorHealthLoss")
+
+function cloakOfTerrorHealthLoss.onHealthChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin)
+	if not creature or not attacker then
+		return primaryDamage, primaryType, secondaryDamage, secondaryType
+	end
+
+	if attacker:getPlayer() and primaryDamage > 0 or secondaryDamage > 0 then
+		Game.createItem(SoulWarQuest.theBloodOfCloakTerrorIds[1], 1, creature:getPosition())
+	end
+
+	return primaryDamage, primaryType, secondaryDamage, secondaryType
+end
+
+cloakOfTerrorHealthLoss:register()
+
+local theBloodOfCloakStep = MoveEvent()
+
+function theBloodOfCloakStep.onStepIn(creature, item, position, fromPosition)
+	local player = creature:getPlayer()
+	-- If a player steps in blood, it takes damage
+	if player then
+		local damagePercentage = SoulWarQuest.poolDamagePercentages[item:getId()] or 0
+		local maxHealth = player:getMaxHealth()
+		local damage = maxHealth * damagePercentage
+
+		player:addHealth(-damage, COMBAT_ENERGYDAMAGE)
+	end
+
+	-- If a "Cloak of Terror" monster steps in blood, it heals itself
+	local monster = creature:getMonster()
+	if monster and monster:getName() == "Cloak of Terror" then
+		local healAmount = math.random(1500, 2000)
+		monster:addHealth(healAmount)
+	end
+
+	return true
+end
+
+for _, itemId in pairs(SoulWarQuest.theBloodOfCloakTerrorIds) do
+	theBloodOfCloakStep:id(itemId)
+end
+
+theBloodOfCloakStep:register()
+
+local greedyMaw = Action()
+
+function greedyMaw.onUse(player, item, fromPosition, target, toPosition, isHotkey)
+	if not item or not target then
+		logger.error("Greedy Maw action failed, item or target is nil.")
+		return false
+	end
+
+	if target:getId() == SoulWarQuest.greedyMawId then
+		local kv = player:soulWarQuestKV():scoped("furious-crater")
+		local cooldown = kv:get("greedy-maw-action") or 0
+		local currentTime = os.time()
+		if cooldown + SoulWarQuest.useGreedMawCooldown > currentTime then
+			local timeLeft = cooldown + SoulWarQuest.useGreedMawCooldown - currentTime
+			player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You need to wait " .. timeLeft .. " more seconds before using the greedy maw again.")
+			return true
+		end
+
+		kv:set("greedy-maw-action", currentTime)
+		local timeToIncreaseDefense = SoulWarQuest.timeToIncreaseCrueltyDefense
+		SoulWarQuest.kvSoulWar:set("greedy-maw-action", currentTime + timeToIncreaseDefense)
+		target:getPosition():sendMagicEffect(CONST_ME_DRAWBLOOD)
+		item:remove()
+		player:sendTextMessage(MESSAGE_INFO_DESCR, "Use the item again within " .. timeToIncreaseDefense .. " seconds, or the monster's defense will increase by 2 every " .. timeToIncreaseDefense .. " seconds.")
+		local goshnarsCruelty = Creature("Goshnar's Cruelty")
+		if goshnarsCruelty then
+			local mtype = goshnarsCruelty:getType()
+			if not mtype then
+				logger.error("Greedy Maw action failed, Goshnar's Cruelty has no type.")
+				return false
+			end
+
+			-- If the defense of Goshnar's Cruelty is higher than the default defense, decrease it by 2
+			if goshnarsCruelty:getDefense() > mtype:defense() then
+				logger.debug("Greedy Maw used on Goshnar's Cruelty, old defense {}", goshnarsCruelty:getDefense())
+				goshnarsCruelty:addDefense(-SoulWarQuest.goshnarsCrueltyDefenseChange)
+				logger.debug("Greedy Maw used on Goshnar's Cruelty, new defense {}", goshnarsCruelty:getDefense())
+			end
+		end
+		return true
+	end
+
+	return false
+end
+
+greedyMaw:id(SoulWarQuest.someMortalEssenceId)
+greedyMaw:register()
+
+local soulWarAspectOfPowerDeath = CreatureEvent("SoulWarAspectOfPowerDeath")
+
+function soulWarAspectOfPowerDeath.onDeath(creature)
+	local targetMonster = creature:getMonster()
+	if not targetMonster or targetMonster:getMaster() then
+		return
+	end
+
+	logger.debug("Aspect of Power died, checking if all are dead.")
+	local boss = Creature("Goshnar's Megalomania")
+	if boss and boss:getTypeName() == "Goshnar's Megalomania Purple" then
+		boss:increaseAspectOfPowerDeathCount()
+	end
+
+	local position = boss and boss:getPosition() or creature:getPosition()
+	addEvent(function(position)
+		local aspectMonster = Game.createMonster("Aspect of Power", position)
+		if aspectMonster then
+			local outfit = aspectMonster:getOutfit()
+			outfit.lookType = math.random(1303, 1307)
+			aspectMonster:setOutfit(outfit)
+		end
+	end, 5000, position)
+
+	return true
+end
+
+soulWarAspectOfPowerDeath:register()
+
+local madnessReduce = MoveEvent()
+
+function madnessReduce.onStepIn(creature, item, position, fromPosition)
+	local player = creature:getPlayer()
+	item:getPosition():sendMagicEffect(CONST_ME_HOLYAREA)
+
+	if player and player:getGoshnarSymbolTormentCounter() > 0 then
+		player:resetGoshnarSymbolTormentCounter()
+		player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "The ooze calms your dread but leaves you vulnerable to phantasmal attacks!")
+		item:remove()
+		return true
+	end
+
+	local creatureName = creature:getName()
+	if creatureName == "Lesser Splinter of Madness" or creatureName == "Greater Splinter of Madness" or creatureName == "Mighty Splinter of Madness" then
+		creature:remove()
+		item:transform(SoulWarQuest.cleansedSanityItemId)
+	end
+
+	return true
+end
+
+madnessReduce:id(SoulWarQuest.deadAspectOfPowerCorpseId)
+madnessReduce:register()
+
+local cleansedSanity = Action()
+
+function cleansedSanity.onUse(player, item, fromPosition, target, toPosition, isHotkey)
+	if not item or not target then
+		logger.error("Cleansed action failed, item or target is nil.")
+		return false
+	end
+
+	local kv = player:soulWarQuestKV():scoped("furious-crater")
+	local cooldown = kv:get("cleansed-sanity-action") or 0
+	local currentTime = os.time()
+	if cooldown + SoulWarQuest.useGreedMawCooldown > currentTime then
+		local timeLeft = cooldown + SoulWarQuest.useGreedMawCooldown - currentTime
+		player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You need to wait " .. timeLeft .. " more seconds before using the cleansed again.")
+		return true
+	end
+
+	kv:set("cleansed-sanity-action", currentTime)
+	if target:getId() == SoulWarQuest.greedyMawId then
+		local timeToIncreaseDefense = SoulWarQuest.timeToIncreaseCrueltyDefense
+		SoulWarQuest.kvSoulWar:set("cleansed-sanity-action", currentTime + timeToIncreaseDefense)
+		target:getPosition():sendMagicEffect(CONST_ME_DRAWBLOOD)
+		item:remove()
+		player:sendTextMessage(MESSAGE_INFO_DESCR, "Use the item again within " .. timeToIncreaseDefense .. " seconds, or the monster's defense will increase by 2 every " .. timeToIncreaseDefense .. " seconds.")
+		local boss = Creature("Goshnar's Megalomania")
+		if boss then
+			local mtype = boss:getType()
+			if not mtype then
+				logger.error("Cleansed action failed, Goshnar's Megalomania has no type.")
+				return false
+			end
+
+			-- If the defense of Goshnar's Megalomania is higher than the default defense, decrease it by 2
+			if boss:getDefense() > mtype:defense() then
+				logger.debug("Cleansed used on Goshnar's Megalomania, old defense {}", boss:getDefense())
+				boss:addDefense(-SoulWarQuest.goshnarsCrueltyDefenseChange)
+				logger.debug("Cleansed used on Goshnar's Megalomania, new defense {}", boss:getDefense())
+			end
+		end
+		return true
+	end
+
+	return false
+end
+
+cleansedSanity:id(SoulWarQuest.cleansedSanityItemId)
+cleansedSanity:register()
+
+local necromanticRemainsReduce = MoveEvent()
+
+function necromanticRemainsReduce.onStepIn(creature, item, position, fromPosition)
+	local player = creature:getPlayer()
+	if not player then
+		return
+	end
+
+	player:removeGoshnarSymbolTormentCounter(5)
+	item:remove()
+	position:sendMagicEffect(CONST_ME_HOLYAREA)
+	return true
+end
+
+necromanticRemainsReduce:id(SoulWarQuest.necromanticRemainsItemId)
+necromanticRemainsReduce:register()
+
+local necromanticFocusDeath = CreatureEvent("NecromanticFocusDeath")
+
+function necromanticFocusDeath.onDeath(creature)
+	local targetMonster = creature:getMonster()
+	if not targetMonster or targetMonster:getMaster() then
+		return
+	end
+
+	local position = targetMonster:getPosition()
+	addEvent(function()
+		position:increaseNecromaticMegalomaniaStrength()
+	end, 5 * 60 * 1000)
+
+	return true
+end
+
+necromanticFocusDeath:register()
+
+local megalomaniaDeath = CreatureEvent("MegalomaniaDeath")
+
+function megalomaniaDeath.onDeath(creature, corpse, killer, mostDamageKiller, lastHitUnjustified, mostDamageUnjustified)
+	local killers = creature:getKillers(true)
+	for i, killerPlayer in ipairs(killers) do
+		local soulWarQuest = killerPlayer:soulWarQuestKV()
+		-- Checks if the boss has already been defeated
+		if not soulWarQuest:get("goshnar's-megalomania-killed") then
+			soulWarQuest:set("goshnar's-megalomania-killed", true)
+			killerPlayer:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have defeated Goshnar's Megalomania. Report the 'task' to Flickering Soul and earn your outfit.")
+		end
+	end
+	return true
+end
+
+megalomaniaDeath:register()
+
+local teleportStepRemoveIcon = MoveEvent()
+
+function teleportStepRemoveIcon.onStepIn(creature, item, position, fromPosition)
+	local player = creature:getPlayer()
+	if not player then
+		return
+	end
+
+	player:resetGoshnarSymbolTormentCounter()
+	return true
+end
+
+local teleportPositions = {
+	Position(33713, 31642, 14),
+	Position(33743, 31606, 14),
+}
+
+for _, pos in pairs(teleportPositions) do
+	teleportStepRemoveIcon:position(pos)
+end
+
+teleportStepRemoveIcon:register()
diff --git a/data-otservbr-global/scripts/quests/soul_war/spell-eye_beam.lua b/data-otservbr-global/scripts/quests/soul_war/spell-eye_beam.lua
new file mode 100644
index 00000000000..7a73979930a
--- /dev/null
+++ b/data-otservbr-global/scripts/quests/soul_war/spell-eye_beam.lua
@@ -0,0 +1,38 @@
+local combat = Combat()
+combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_DROWNDAMAGE)
+combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_SMALLCLOUDS)
+
+combat:setArea(createCombatArea({
+	{ 1 },
+	{ 1 },
+	{ 3 },
+}))
+
+function onTargetTile(cid, pos)
+	local tile = Tile(pos)
+	local target = tile:getTopCreature()
+	if tile then
+		if target then
+			if target:isMonster() and target:getName() == "Poor Soul" then
+				target:addHealth(-1000)
+			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("greedy eye beam")
+spell:words("greedy eye beam")
+spell:isAggressive(true)
+spell:blockWalls(true)
+spell:needLearn(true)
+spell:needDirection(true)
+spell:register()
diff --git a/data-otservbr-global/scripts/quests/soul_war/spell-fire_beam_cruelty.lua b/data-otservbr-global/scripts/quests/soul_war/spell-fire_beam_cruelty.lua
new file mode 100644
index 00000000000..2bc321f24e0
--- /dev/null
+++ b/data-otservbr-global/scripts/quests/soul_war/spell-fire_beam_cruelty.lua
@@ -0,0 +1,61 @@
+local areaSpell = {
+	{ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
+	{ 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0 },
+	{ 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 },
+	{ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
+	{ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
+	{ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
+	{ 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1 },
+	{ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
+	{ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
+	{ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
+	{ 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 },
+	{ 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0 },
+	{ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
+}
+
+local area = createCombatArea(areaSpell)
+
+local combat = Combat()
+combat:setArea(area)
+combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_FIREDAMAGE)
+combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_FIREAREA)
+
+function onTargetTile(cid, pos)
+	local tile = Tile(pos)
+	if tile then
+		local target = tile:getTopCreature()
+		if target and target:isPlayer() then
+			target:addHealth(math.random(2300, 3000))
+		end
+	end
+	return true
+end
+
+combat:setCallback(CALLBACK_PARAM_TARGETTILE, "onTargetTile")
+
+local function delayedCastSpell(cid, var, targetId)
+	local creature = Creature(cid)
+	if not creature then
+		return
+	end
+
+	local target = Player(targetId)
+	if target then
+		combat:execute(creature, positionToVariant(target:getPosition()))
+	end
+end
+
+local spell = Spell("instant")
+
+function spell.onCastSpell(creature, var, isHotkey)
+	return creature:applyZoneEffect(var, combat, "boss.goshnar's-cruelty")
+end
+
+spell:name("cruelty transform elemental")
+spell:words("cruelty transform elemental")
+spell:isAggressive(true)
+spell:blockWalls(true)
+spell:needLearn(true)
+spell:needDirection(true)
+spell:register()
diff --git a/data-otservbr-global/scripts/quests/soul_war/spell-fire_beam_megalomania.lua b/data-otservbr-global/scripts/quests/soul_war/spell-fire_beam_megalomania.lua
new file mode 100644
index 00000000000..2906f213d74
--- /dev/null
+++ b/data-otservbr-global/scripts/quests/soul_war/spell-fire_beam_megalomania.lua
@@ -0,0 +1,54 @@
+local areaSpell = {
+	{ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
+	{ 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0 },
+	{ 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 },
+	{ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
+	{ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
+	{ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
+	{ 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1 },
+	{ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
+	{ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
+	{ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
+	{ 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 },
+	{ 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0 },
+	{ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
+}
+
+local area = createCombatArea(areaSpell)
+
+local combat = Combat()
+combat:setArea(area)
+combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_FIREDAMAGE)
+combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_FIREAREA)
+
+function onTargetTile(cid, pos)
+	local tile = Tile(pos)
+	if tile then
+		local target = tile:getTopCreature()
+		if target and target:isPlayer() then
+			target:addHealth(math.random(2300, 3000))
+		end
+	end
+	return true
+end
+
+combat:setCallback(CALLBACK_PARAM_TARGETTILE, "onTargetTile")
+
+local config = {
+	outfit = { lookType = 242, lookHead = 0, lookBody = 0, lookLegs = 0, lookFeet = 0, lookAddons = 0 },
+	time = 7000,
+}
+
+local spell = Spell("instant")
+
+function spell.onCastSpell(creature, var, isHotkey)
+	return creature:applyZoneEffect(var, combat, "boss.goshnar's-megalomania-purple")
+end
+
+spell:name("megalomania transform elemental")
+spell:words("megalomania transform elemental")
+spell:isAggressive(true)
+spell:blockWalls(true)
+spell:needLearn(true)
+spell:needDirection(true)
+spell:register()
diff --git a/data-otservbr-global/scripts/quests/soul_war/spell-megalomania_blue.lua b/data-otservbr-global/scripts/quests/soul_war/spell-megalomania_blue.lua
new file mode 100644
index 00000000000..d8a9c8e9875
--- /dev/null
+++ b/data-otservbr-global/scripts/quests/soul_war/spell-megalomania_blue.lua
@@ -0,0 +1,58 @@
+local area = {
+	{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
+	{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
+	{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
+	{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
+	{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
+	{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
+	{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
+	{ 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1 },
+	{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
+	{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
+	{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
+	{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
+	{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
+	{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
+	{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
+}
+
+local createArea = createCombatArea(area)
+
+local combat = Combat()
+combat:setArea(createArea)
+
+local zone = Zone.getByName("boss.goshnar's-megalomania-purple")
+local zonePositions = zone:getPositions()
+
+function onTargetTile(creature, pos)
+	for _, pos in ipairs(zonePositions) do
+		local tile = Tile(pos)
+		if tile and tile:getGround() and tile:getGround():getId() ~= 409 then
+			local creature = tile:getTopCreature()
+			if creature then
+				local player = creature:getPlayer()
+				if player then
+					player:addHealth(-6000, COMBAT_DEATHDAMAGE)
+				end
+			end
+		end
+	end
+
+	pos:sendMagicEffect(CONST_ME_BLACKSMOKE)
+	return true
+end
+
+combat:setCallback(CALLBACK_PARAM_TARGETTILE, "onTargetTile")
+
+local spell = Spell("instant")
+
+function spell.onCastSpell(creature, var)
+	return combat:execute(creature, positionToVariant(creature:getPosition()))
+end
+
+spell:name("megalomania blue")
+spell:words("megalomania blue")
+spell:isAggressive(true)
+spell:blockWalls(false)
+spell:needLearn(true)
+spell:register()
diff --git a/data-otservbr-global/scripts/quests/soul_war/spell-soulsnatcher.lua b/data-otservbr-global/scripts/quests/soul_war/spell-soulsnatcher.lua
new file mode 100644
index 00000000000..9292f10530f
--- /dev/null
+++ b/data-otservbr-global/scripts/quests/soul_war/spell-soulsnatcher.lua
@@ -0,0 +1,58 @@
+local combat = Combat()
+combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_PHYSICALDAMAGE)
+combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_HOLYDAMAGE)
+
+combat:setArea(createCombatArea(CrossBeamArea3X2))
+
+local spell = Spell("instant")
+
+function spell.onCastSpell(creature, var)
+	return combat:execute(creature, var)
+end
+
+spell:name("soulsnatcher-lifedrain-beam")
+spell:words("soulsnatcher-lifedrain-beam")
+spell:isAggressive(true)
+spell:blockWalls(true)
+spell:needLearn(true)
+spell:needDirection(true)
+spell:register()
+
+local combat = Combat()
+combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_PHYSICALDAMAGE)
+combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_HOLYAREA)
+combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_HOLY)
+
+spell = Spell("instant")
+
+function spell.onCastSpell(creature, var)
+	return combat:execute(creature, var)
+end
+
+spell:name("soulsnatcher-lifedrain-missile")
+spell:words("soulsnatcher-lifedrain-missile")
+spell:isAggressive(true)
+spell:blockWalls(true)
+spell:needLearn(true)
+spell:needTarget(true)
+spell:register()
+
+-- Mana drain ball
+local combat = Combat()
+combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_PHYSICALDAMAGE)
+combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_ENERGYAREA)
+
+combat:setArea(createCombatArea(AREA_CIRCLE3X3))
+
+spell = Spell("instant")
+
+function spell.onCastSpell(creature, var)
+	return combat:execute(creature, var)
+end
+
+spell:name("soulsnatcher-manadrain-ball")
+spell:words("soulsnatcher-manadrain-ball")
+spell:isAggressive(true)
+spell:blockWalls(true)
+spell:needLearn(true)
+spell:register()
diff --git a/data-otservbr-global/scripts/world_changes/iron_servant_transformation.lua b/data-otservbr-global/scripts/world_changes/iron_servant_transformation.lua
index 65e6af5a3b2..7da5f5d1b99 100644
--- a/data-otservbr-global/scripts/world_changes/iron_servant_transformation.lua
+++ b/data-otservbr-global/scripts/world_changes/iron_servant_transformation.lua
@@ -1,4 +1,4 @@
-local ironServantTransformation = EventCallback()
+local ironServantTransformation = EventCallback("IronServantTransformationOnSpawn")
 
 ironServantTransformation.monsterOnSpawn = function(monster, position)
 	if monster:getName():lower() ~= "iron servant replica" then
diff --git a/data-otservbr-global/world/otservbr-monster.xml b/data-otservbr-global/world/otservbr-monster.xml
index d3bbc69e858..84419e700e7 100644
--- a/data-otservbr-global/world/otservbr-monster.xml
+++ b/data-otservbr-global/world/otservbr-monster.xml
@@ -34109,6 +34109,12 @@
 	<monster centerx="32073" centery="31861" centerz="7" radius="1">
 		<monster name="Dawnfly" x="0" y="0" z="7" spawntime="90" />
 	</monster>
+	<monster centerx="33853" centery="31861" centerz="7" radius="1">
+		<monster name="Dreadful Harvester" x="0" y="0" z="7" spawntime="14" />
+	</monster>
+	<monster centerx="33857" centery="31861" centerz="7" radius="1">
+		<monster name="Dreadful Harvester" x="0" y="0" z="7" spawntime="14" />
+	</monster>
 	<monster centerx="32058" centery="31862" centerz="7" radius="1">
 		<monster name="Dawnfly" x="0" y="0" z="7" spawntime="90" />
 	</monster>
@@ -34219,6 +34225,9 @@
 		<monster name="Poison Spider" x="4" y="3" z="7" spawntime="90" />
 		<monster name="Poison Spider" x="-4" y="4" z="7" spawntime="90" />
 	</monster>
+	<monster centerx="33856" centery="31868" centerz="7" radius="1">
+		<monster name="Mean Maw" x="0" y="0" z="7" spawntime="14" />
+	</monster>
 	<monster centerx="32508" centery="31869" centerz="7" radius="1">
 		<monster name="Deer" x="0" y="1" z="7" spawntime="90" />
 	</monster>
@@ -34244,6 +34253,9 @@
 	<monster centerx="32665" centery="31871" centerz="7" radius="2">
 		<monster name="Deer" x="2" y="1" z="7" spawntime="90" />
 	</monster>
+	<monster centerx="33852" centery="31871" centerz="7" radius="1">
+		<monster name="Poor Soul" x="0" y="0" z="7" spawntime="14" direction="2" />
+	</monster>
 	<monster centerx="32106" centery="31872" centerz="7" radius="1">
 		<monster name="Dawnfly" x="0" y="0" z="7" spawntime="90" />
 	</monster>
@@ -48967,11 +48979,20 @@
 	<monster centerx="33159" centery="31014" centerz="8" radius="5">
 		<monster name="Ghastly Dragon" x="-1" y="1" z="8" spawntime="90" />
 	</monster>
+	<monster centerx="33934" centery="31014" centerz="8" radius="1">
+		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33939" centery="31014" centerz="8" radius="1">
+		<monster name="Capricious Phantom" x="1" y="1" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33944" centery="31014" centerz="8" radius="1">
+		<monster name="Turbulent Elemental" x="1" y="1" z="8" spawntime="60" />
+	</monster>
 	<monster centerx="32726" centery="31015" centerz="8" radius="2">
 		<monster name="Mutated Bat" x="0" y="0" z="8" spawntime="90" />
 	</monster>
-	<monster centerx="33943" centery="31015" centerz="8" radius="1">
-		<monster name="Capricious Phantom" x="1" y="0" z="8" spawntime="60" />
+	<monster centerx="33930" centery="31015" centerz="8" radius="1">
+		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
 	</monster>
 	<monster centerx="31910" centery="31017" centerz="8" radius="2">
 		<monster name="Blood Crab" x="1" y="1" z="8" spawntime="90" />
@@ -48979,18 +49000,12 @@
 	<monster centerx="32764" centery="31017" centerz="8" radius="2">
 		<monster name="Bonebeast" x="1" y="-2" z="8" spawntime="90" />
 	</monster>
-	<monster centerx="33930" centery="31017" centerz="8" radius="1">
-		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33938" centery="31017" centerz="8" radius="1">
-		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33948" centery="31017" centerz="8" radius="1">
-		<monster name="Turbulent Elemental" x="1" y="1" z="8" spawntime="60" />
-	</monster>
 	<monster centerx="33534" centery="31018" centerz="8" radius="1">
 		<monster name="Memory Of A Manticore" x="0" y="0" z="8" spawntime="60" />
 	</monster>
+	<monster centerx="33940" centery="31018" centerz="8" radius="1">
+		<monster name="Hazardous Phantom" x="1" y="0" z="8" spawntime="60" />
+	</monster>
 	<monster centerx="33141" centery="31019" centerz="8" radius="3">
 		<monster name="Ghastly Dragon" x="-1" y="0" z="8" spawntime="90" />
 	</monster>
@@ -49000,6 +49015,9 @@
 	<monster centerx="33512" centery="31019" centerz="8" radius="1">
 		<monster name="Memory Of A Werelion" x="0" y="0" z="8" spawntime="60" />
 	</monster>
+	<monster centerx="33931" centery="31019" centerz="8" radius="1">
+		<monster name="Hazardous Phantom" x="0" y="0" z="8" spawntime="60" />
+	</monster>
 	<monster centerx="32231" centery="31020" centerz="8" radius="3">
 		<monster name="Mammoth" x="0" y="1" z="8" spawntime="90" />
 	</monster>
@@ -49018,15 +49036,12 @@
 		<monster name="Old Bug" x="-1" y="2" z="8" spawntime="60" />
 		<monster name="Old Bug" x="2" y="2" z="8" spawntime="60" />
 	</monster>
+	<monster centerx="33934" centery="31020" centerz="8" radius="1">
+		<monster name="Turbulent Elemental" x="0" y="1" z="8" spawntime="60" />
+	</monster>
 	<monster centerx="33480" centery="31021" centerz="8" radius="1">
 		<monster name="Memory Of A Carnisylvan" x="0" y="0" z="8" spawntime="60" />
 	</monster>
-	<monster centerx="33944" centery="31021" centerz="8" radius="1">
-		<monster name="Hazardous Phantom" x="1" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33935" centery="31022" centerz="8" radius="1">
-		<monster name="Hazardous Phantom" x="0" y="0" z="8" spawntime="60" />
-	</monster>
 	<monster centerx="31913" centery="31023" centerz="8" radius="2">
 		<monster name="Blood Crab" x="-1" y="-1" z="8" spawntime="90" />
 	</monster>
@@ -49034,9 +49049,6 @@
 		<monster name="Banshee" x="3" y="-3" z="8" spawntime="90" />
 		<monster name="Braindeath" x="-3" y="2" z="8" spawntime="90" />
 	</monster>
-	<monster centerx="33938" centery="31023" centerz="8" radius="1">
-		<monster name="Turbulent Elemental" x="0" y="1" z="8" spawntime="60" />
-	</monster>
 	<monster centerx="31919" centery="31024" centerz="8" radius="2">
 		<monster name="Blood Crab" x="-1" y="0" z="8" spawntime="90" />
 	</monster>
@@ -49056,6 +49068,9 @@
 	<monster centerx="33530" centery="31025" centerz="8" radius="1">
 		<monster name="Memory Of A Manticore" x="0" y="0" z="8" spawntime="60" />
 	</monster>
+	<monster centerx="33941" centery="31025" centerz="8" radius="1">
+		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
+	</monster>
 	<monster centerx="31943" centery="31026" centerz="8" radius="2">
 		<monster name="Blood Crab" x="1" y="0" z="8" spawntime="90" />
 	</monster>
@@ -49112,9 +49127,6 @@
 	<monster centerx="33548" centery="31028" centerz="8" radius="1">
 		<monster name="Memory Of A Manticore" x="0" y="0" z="8" spawntime="60" />
 	</monster>
-	<monster centerx="33945" centery="31028" centerz="8" radius="1">
-		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
-	</monster>
 	<monster centerx="31927" centery="31029" centerz="8" radius="2">
 		<monster name="Blood Crab" x="0" y="0" z="8" spawntime="90" />
 	</monster>
@@ -49209,10 +49221,19 @@
 	<monster centerx="33566" centery="31037" centerz="8" radius="1">
 		<monster name="Memory Of A Manticore" x="0" y="0" z="8" spawntime="60" />
 	</monster>
+	<monster centerx="33911" centery="31037" centerz="8" radius="1">
+		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
+	</monster>
 	<monster centerx="32892" centery="31038" centerz="8" radius="3">
 		<monster name="Hellspawn" x="-1" y="2" z="8" spawntime="90" />
 		<monster name="Plaguesmith" x="2" y="2" z="8" spawntime="90" />
 	</monster>
+	<monster centerx="33891" centery="31038" centerz="8" radius="1">
+		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33913" centery="31038" centerz="8" radius="1">
+		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
+	</monster>
 	<monster centerx="31914" centery="31039" centerz="8" radius="2">
 		<monster name="Blood Crab" x="0" y="1" z="8" spawntime="90" />
 	</monster>
@@ -49225,8 +49246,8 @@
 	<monster centerx="32874" centery="31040" centerz="8" radius="1">
 		<monster name="Plaguesmith" x="0" y="0" z="8" spawntime="90" />
 	</monster>
-	<monster centerx="33915" centery="31040" centerz="8" radius="1">
-		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
+	<monster centerx="33891" centery="31040" centerz="8" radius="1">
+		<monster name="Hazardous Phantom" x="-1" y="0" z="8" spawntime="60" />
 	</monster>
 	<monster centerx="31992" centery="31041" centerz="8" radius="3">
 		<monster name="Chakoya Toolshaper" x="0" y="-2" z="8" spawntime="90" />
@@ -49277,11 +49298,14 @@
 		<monster name="Old Bug" x="-2" y="-1" z="8" spawntime="60" />
 		<monster name="Old Bug" x="-2" y="0" z="8" spawntime="60" />
 	</monster>
-	<monster centerx="33917" centery="31041" centerz="8" radius="1">
+	<monster centerx="33931" centery="31041" centerz="8" radius="1">
 		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
 	</monster>
-	<monster centerx="33933" centery="31041" centerz="8" radius="1">
-		<monster name="Capricious Phantom" x="0" y="0" z="8" spawntime="60" />
+	<monster centerx="33934" centery="31041" centerz="8" radius="1">
+		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33940" centery="31041" centerz="8" radius="1">
+		<monster name="Capricious Phantom" x="1" y="0" z="8" spawntime="60" />
 	</monster>
 	<monster centerx="31932" centery="31042" centerz="8" radius="2">
 		<monster name="Blood Crab" x="-1" y="-2" z="8" spawntime="90" />
@@ -49305,11 +49329,8 @@
 	<monster centerx="33645" centery="31042" centerz="8" radius="3">
 		<monster name="Old Bug" x="2" y="2" z="8" spawntime="60" />
 	</monster>
-	<monster centerx="33891" centery="31042" centerz="8" radius="1">
-		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33938" centery="31042" centerz="8" radius="1">
-		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
+	<monster centerx="33911" centery="31042" centerz="8" radius="1">
+		<monster name="Capricious Phantom" x="0" y="0" z="8" spawntime="60" />
 	</monster>
 	<monster centerx="32809" centery="31043" centerz="8" radius="3">
 		<monster name="Grim Reaper" x="1" y="0" z="8" spawntime="90" />
@@ -49317,6 +49338,12 @@
 	<monster centerx="32867" centery="31043" centerz="8" radius="2">
 		<monster name="Plaguesmith" x="1" y="0" z="8" spawntime="90" />
 	</monster>
+	<monster centerx="33891" centery="31043" centerz="8" radius="1">
+		<monster name="Capricious Phantom" x="1" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33938" centery="31043" centerz="8" radius="1">
+		<monster name="Hazardous Phantom" x="0" y="0" z="8" spawntime="60" />
+	</monster>
 	<monster centerx="33507" centery="31044" centerz="8" radius="1">
 		<monster name="Memory Of A Werelion" x="0" y="0" z="8" spawntime="60" />
 	</monster>
@@ -49326,11 +49353,14 @@
 	<monster centerx="33525" centery="31044" centerz="8" radius="1">
 		<monster name="Memory Of A Manticore" x="0" y="0" z="8" spawntime="60" />
 	</monster>
-	<monster centerx="33891" centery="31044" centerz="8" radius="1">
+	<monster centerx="33908" centery="31044" centerz="8" radius="1">
 		<monster name="Hazardous Phantom" x="0" y="0" z="8" spawntime="60" />
 	</monster>
-	<monster centerx="33935" centery="31044" centerz="8" radius="1">
-		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
+	<monster centerx="33930" centery="31044" centerz="8" radius="1">
+		<monster name="Hazardous Phantom" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33934" centery="31044" centerz="8" radius="1">
+		<monster name="Bony Sea Devil" x="0" y="1" z="8" spawntime="60" />
 	</monster>
 	<monster centerx="32855" centery="31045" centerz="8" radius="2">
 		<monster name="Hellspawn" x="-1" y="0" z="8" spawntime="90" />
@@ -49341,14 +49371,8 @@
 	<monster centerx="32903" centery="31045" centerz="8" radius="3">
 		<monster name="Plaguesmith" x="-2" y="0" z="8" spawntime="90" />
 	</monster>
-	<monster centerx="33893" centery="31045" centerz="8" radius="1">
-		<monster name="Capricious Phantom" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33915" centery="31045" centerz="8" radius="1">
-		<monster name="Capricious Phantom" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33931" centery="31045" centerz="8" radius="1">
-		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
+	<monster centerx="33901" centery="31045" centerz="8" radius="1">
+		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
 	</monster>
 	<monster centerx="32751" centery="31046" centerz="8" radius="2">
 		<monster name="Braindeath" x="0" y="1" z="8" spawntime="90" />
@@ -49356,17 +49380,11 @@
 	<monster centerx="32763" centery="31046" centerz="8" radius="2">
 		<monster name="Mutated Bat" x="-1" y="0" z="8" spawntime="90" />
 	</monster>
-	<monster centerx="33942" centery="31046" centerz="8" radius="1">
-		<monster name="Hazardous Phantom" x="0" y="0" z="8" spawntime="60" />
-	</monster>
 	<monster centerx="31940" centery="31047" centerz="8" radius="2">
 		<monster name="Blood Crab" x="2" y="1" z="8" spawntime="90" />
 	</monster>
-	<monster centerx="33912" centery="31047" centerz="8" radius="1">
-		<monster name="Hazardous Phantom" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33934" centery="31047" centerz="8" radius="1">
-		<monster name="Hazardous Phantom" x="0" y="0" z="8" spawntime="60" />
+	<monster centerx="33936" centery="31047" centerz="8" radius="1">
+		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
 	</monster>
 	<monster centerx="31915" centery="31048" centerz="8" radius="2">
 		<monster name="Blood Crab" x="1" y="0" z="8" spawntime="90" />
@@ -49392,9 +49410,6 @@
 	<monster centerx="33798" centery="31048" centerz="8" radius="3">
 		<monster name="Schiach" x="3" y="-1" z="8" spawntime="60" />
 	</monster>
-	<monster centerx="33905" centery="31048" centerz="8" radius="1">
-		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
-	</monster>
 	<monster centerx="31991" centery="31049" centerz="8" radius="3">
 		<monster name="Polar Bear" x="3" y="-2" z="8" spawntime="90" />
 		<monster name="Chakoya Tribewarden" x="-2" y="-1" z="8" spawntime="90" />
@@ -49406,25 +49421,37 @@
 	<monster centerx="33645" centery="31049" centerz="8" radius="3">
 		<monster name="Old Bug" x="0" y="-3" z="8" spawntime="60" />
 	</monster>
-	<monster centerx="33931" centery="31050" centerz="8" radius="1">
-		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
+	<monster centerx="33898" centery="31049" centerz="8" radius="1">
+		<monster name="Capricious Phantom" x="0" y="0" z="8" spawntime="60" />
 	</monster>
-	<monster centerx="33940" centery="31050" centerz="8" radius="1">
+	<monster centerx="33902" centery="31049" centerz="8" radius="1">
 		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
 	</monster>
-	<monster centerx="32733" centery="31051" centerz="8" radius="2">
-		<monster name="Banshee" x="-1" y="0" z="8" spawntime="90" />
+	<monster centerx="33908" centery="31049" centerz="8" radius="1">
+		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
 	</monster>
-	<monster centerx="33902" centery="31052" centerz="8" radius="1">
-		<monster name="Capricious Phantom" x="0" y="0" z="8" spawntime="60" />
+	<monster centerx="33912" centery="31049" centerz="8" radius="1">
+		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
 	</monster>
-	<monster centerx="33906" centery="31052" centerz="8" radius="1">
-		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
+	<monster centerx="33892" centery="31050" centerz="8" radius="1">
+		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
 	</monster>
-	<monster centerx="33912" centery="31052" centerz="8" radius="1">
+	<monster centerx="33896" centery="31050" centerz="8" radius="1">
+		<monster name="Hazardous Phantom" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33933" centery="31050" centerz="8" radius="1">
 		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
 	</monster>
-	<monster centerx="33916" centery="31052" centerz="8" radius="1">
+	<monster centerx="33937" centery="31050" centerz="8" radius="1">
+		<monster name="Capricious Phantom" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33940" centery="31050" centerz="8" radius="1">
+		<monster name="Turbulent Elemental" x="-1" y="1" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="32733" centery="31051" centerz="8" radius="2">
+		<monster name="Banshee" x="-1" y="0" z="8" spawntime="90" />
+	</monster>
+	<monster centerx="33930" centery="31051" centerz="8" radius="1">
 		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
 	</monster>
 	<monster centerx="31930" centery="31053" centerz="8" radius="2">
@@ -49441,21 +49468,6 @@
 		<monster name="Hellspawn" x="-1" y="2" z="8" spawntime="90" />
 		<monster name="Hellspawn" x="2" y="4" z="8" spawntime="90" />
 	</monster>
-	<monster centerx="33896" centery="31053" centerz="8" radius="1">
-		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33900" centery="31053" centerz="8" radius="1">
-		<monster name="Hazardous Phantom" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33937" centery="31053" centerz="8" radius="1">
-		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33941" centery="31053" centerz="8" radius="1">
-		<monster name="Capricious Phantom" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33944" centery="31053" centerz="8" radius="1">
-		<monster name="Turbulent Elemental" x="-1" y="1" z="8" spawntime="60" />
-	</monster>
 	<monster centerx="31906" centery="31054" centerz="8" radius="2">
 		<monster name="Blood Crab" x="-1" y="0" z="8" spawntime="90" />
 	</monster>
@@ -49571,6 +49583,12 @@
 		<monster name="Plaguesmith" x="-1" y="-3" z="8" spawntime="90" />
 		<monster name="Hellspawn" x="1" y="0" z="8" spawntime="90" />
 	</monster>
+	<monster centerx="33930" centery="31064" centerz="8" radius="1">
+		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33941" centery="31064" centerz="8" radius="1">
+		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
+	</monster>
 	<monster centerx="31944" centery="31065" centerz="8" radius="2">
 		<monster name="Blood Crab" x="0" y="2" z="8" spawntime="90" />
 	</monster>
@@ -49597,14 +49615,8 @@
 	<monster centerx="32832" centery="31067" centerz="8" radius="1">
 		<monster name="Hellspawn" x="0" y="0" z="8" spawntime="90" />
 	</monster>
-	<monster centerx="33931" centery="31067" centerz="8" radius="1">
-		<monster name="Capricious Phantom" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33934" centery="31067" centerz="8" radius="1">
-		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33945" centery="31067" centerz="8" radius="1">
-		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
+	<monster centerx="33937" centery="31067" centerz="8" radius="1">
+		<monster name="Hazardous Phantom" x="0" y="0" z="8" spawntime="60" />
 	</monster>
 	<monster centerx="32720" centery="31068" centerz="8" radius="5">
 		<monster name="Braindeath" x="-1" y="-3" z="8" spawntime="90" />
@@ -49613,8 +49625,11 @@
 	<monster centerx="32874" centery="31068" centerz="8" radius="2">
 		<monster name="Hellspawn" x="0" y="0" z="8" spawntime="90" />
 	</monster>
-	<monster centerx="33896" centery="31068" centerz="8" radius="1">
-		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
+	<monster centerx="33897" centery="31068" centerz="8" radius="1">
+		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33931" centery="31068" centerz="8" radius="1">
+		<monster name="Capricious Phantom" x="-1" y="0" z="8" spawntime="60" />
 	</monster>
 	<monster centerx="31979" centery="31069" centerz="8" radius="3">
 		<monster name="Chakoya Tribewarden" x="-1" y="0" z="8" spawntime="90" />
@@ -49649,24 +49664,30 @@
 	<monster centerx="33840" centery="31069" centerz="8" radius="3">
 		<monster name="Percht" x="-2" y="-2" z="8" spawntime="60" />
 	</monster>
-	<monster centerx="33941" centery="31070" centerz="8" radius="1">
+	<monster centerx="33895" centery="31069" centerz="8" radius="1">
 		<monster name="Hazardous Phantom" x="0" y="0" z="8" spawntime="60" />
 	</monster>
+	<monster centerx="33903" centery="31069" centerz="8" radius="1">
+		<monster name="Turbulent Elemental" x="1" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33941" centery="31069" centerz="8" radius="1">
+		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
+	</monster>
 	<monster centerx="32654" centery="31071" centerz="8" radius="1">
 		<monster name="Mutated Tiger" x="0" y="0" z="8" spawntime="90" />
 	</monster>
-	<monster centerx="33901" centery="31071" centerz="8" radius="1">
+	<monster centerx="33928" centery="31071" centerz="8" radius="1">
 		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
 	</monster>
 	<monster centerx="32859" centery="31072" centerz="8" radius="4">
 		<monster name="Plaguesmith" x="1" y="-2" z="8" spawntime="90" />
 		<monster name="Hellspawn" x="-2" y="4" z="8" spawntime="90" />
 	</monster>
-	<monster centerx="33899" centery="31072" centerz="8" radius="1">
-		<monster name="Hazardous Phantom" x="0" y="0" z="8" spawntime="60" />
+	<monster centerx="33923" centery="31072" centerz="8" radius="1">
+		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
 	</monster>
-	<monster centerx="33945" centery="31072" centerz="8" radius="1">
-		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
+	<monster centerx="33933" centery="31072" centerz="8" radius="1">
+		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
 	</monster>
 	<monster centerx="32757" centery="31073" centerz="8" radius="2">
 		<monster name="Mutated Bat" x="0" y="1" z="8" spawntime="90" />
@@ -49677,24 +49698,21 @@
 	<monster centerx="32833" centery="31073" centerz="8" radius="3">
 		<monster name="Hellspawn" x="1" y="0" z="8" spawntime="90" />
 	</monster>
+	<monster centerx="33897" centery="31073" centerz="8" radius="1">
+		<monster name="Capricious Phantom" x="1" y="0" z="8" spawntime="60" />
+	</monster>
 	<monster centerx="31951" centery="31074" centerz="8" radius="2">
 		<monster name="Blood Crab" x="1" y="1" z="8" spawntime="90" />
 	</monster>
 	<monster centerx="32848" centery="31074" centerz="8" radius="2">
 		<monster name="Hellspawn" x="1" y="0" z="8" spawntime="90" />
 	</monster>
-	<monster centerx="33932" centery="31074" centerz="8" radius="1">
-		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
-	</monster>
 	<monster centerx="31988" centery="31075" centerz="8" radius="3">
 		<monster name="Chakoya Toolshaper" x="2" y="0" z="8" spawntime="90" />
 		<monster name="Chakoya Tribewarden" x="-1" y="1" z="8" spawntime="90" />
 	</monster>
-	<monster centerx="33927" centery="31075" centerz="8" radius="1">
-		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33937" centery="31075" centerz="8" radius="1">
-		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
+	<monster centerx="33928" centery="31075" centerz="8" radius="1">
+		<monster name="Hazardous Phantom" x="0" y="0" z="8" spawntime="60" />
 	</monster>
 	<monster centerx="32035" centery="31076" centerz="8" radius="3">
 		<monster name="Chakoya Windcaller" x="-1" y="-3" z="8" spawntime="90" />
@@ -49724,8 +49742,8 @@
 	<monster centerx="33826" centery="31076" centerz="8" radius="3">
 		<monster name="Percht" x="2" y="-3" z="8" spawntime="60" />
 	</monster>
-	<monster centerx="33897" centery="31076" centerz="8" radius="1">
-		<monster name="Capricious Phantom" x="0" y="0" z="8" spawntime="60" />
+	<monster centerx="33906" centery="31076" centerz="8" radius="1">
+		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
 	</monster>
 	<monster centerx="32733" centery="31077" centerz="8" radius="3">
 		<monster name="Banshee" x="1" y="0" z="8" spawntime="90" />
@@ -49733,6 +49751,12 @@
 	<monster centerx="33053" centery="31077" centerz="8" radius="1">
 		<monster name="Death Blob" x="0" y="1" z="8" spawntime="90" />
 	</monster>
+	<monster centerx="33897" centery="31077" centerz="8" radius="1">
+		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33939" centery="31077" centerz="8" radius="1">
+		<monster name="Capricious Phantom" x="0" y="0" z="8" spawntime="60" />
+	</monster>
 	<monster centerx="33056" centery="31078" centerz="8" radius="1">
 		<monster name="Draken Warmaster" x="0" y="0" z="8" spawntime="90" />
 	</monster>
@@ -49745,12 +49769,6 @@
 	<monster centerx="33084" centery="31078" centerz="8" radius="1">
 		<monster name="Draken Elite" x="0" y="0" z="8" spawntime="90" />
 	</monster>
-	<monster centerx="33910" centery="31078" centerz="8" radius="1">
-		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33932" centery="31078" centerz="8" radius="1">
-		<monster name="Hazardous Phantom" x="0" y="0" z="8" spawntime="60" />
-	</monster>
 	<monster centerx="33081" centery="31079" centerz="8" radius="1">
 		<monster name="Draken Warmaster" x="0" y="0" z="8" spawntime="90" />
 	</monster>
@@ -49760,17 +49778,17 @@
 	<monster centerx="33100" centery="31079" centerz="8" radius="1">
 		<monster name="Draken Abomination" x="0" y="0" z="8" spawntime="90" />
 	</monster>
+	<monster centerx="33905" centery="31079" centerz="8" radius="1">
+		<monster name="Hazardous Phantom" x="0" y="0" z="8" spawntime="60" />
+	</monster>
 	<monster centerx="31907" centery="31080" centerz="8" radius="2">
 		<monster name="Blood Crab" x="1" y="0" z="8" spawntime="90" />
 	</monster>
 	<monster centerx="33110" centery="31080" centerz="8" radius="1">
 		<monster name="Draken Elite" x="0" y="0" z="8" spawntime="90" />
 	</monster>
-	<monster centerx="33901" centery="31080" centerz="8" radius="1">
-		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33943" centery="31080" centerz="8" radius="1">
-		<monster name="Capricious Phantom" x="0" y="0" z="8" spawntime="60" />
+	<monster centerx="33935" centery="31080" centerz="8" radius="1">
+		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
 	</monster>
 	<monster centerx="31932" centery="31081" centerz="8" radius="3">
 		<monster name="Blood Crab" x="-2" y="-2" z="8" spawntime="90" />
@@ -49791,6 +49809,9 @@
 	<monster centerx="32745" centery="31081" centerz="8" radius="2">
 		<monster name="Braindeath" x="0" y="-1" z="8" spawntime="90" />
 	</monster>
+	<monster centerx="33938" centery="31081" centerz="8" radius="1">
+		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
+	</monster>
 	<monster centerx="32785" centery="31082" centerz="8" radius="2">
 		<monster name="Banshee" x="2" y="2" z="8" spawntime="90" />
 	</monster>
@@ -49812,8 +49833,8 @@
 	<monster centerx="33104" centery="31082" centerz="8" radius="1">
 		<monster name="Draken Warmaster" x="0" y="0" z="8" spawntime="90" />
 	</monster>
-	<monster centerx="33909" centery="31082" centerz="8" radius="1">
-		<monster name="Hazardous Phantom" x="0" y="0" z="8" spawntime="60" />
+	<monster centerx="33903" centery="31082" centerz="8" radius="1">
+		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
 	</monster>
 	<monster centerx="31919" centery="31083" centerz="8" radius="2">
 		<monster name="Blood Crab" x="-1" y="0" z="8" spawntime="90" />
@@ -49854,8 +49875,8 @@
 	<monster centerx="33847" centery="31083" centerz="8" radius="3">
 		<monster name="Percht" x="-3" y="3" z="8" spawntime="60" />
 	</monster>
-	<monster centerx="33939" centery="31083" centerz="8" radius="1">
-		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
+	<monster centerx="33933" centery="31083" centerz="8" radius="1">
+		<monster name="Bony Sea Devil" x="0" y="1" z="8" spawntime="60" />
 	</monster>
 	<monster centerx="32804" centery="31084" centerz="8" radius="3">
 		<monster name="Adept Of The Cult" x="-1" y="-3" z="8" spawntime="90" />
@@ -49867,19 +49888,13 @@
 	<monster centerx="33051" centery="31084" centerz="8" radius="1">
 		<monster name="Draken Warmaster" x="0" y="0" z="8" spawntime="90" />
 	</monster>
-	<monster centerx="33942" centery="31084" centerz="8" radius="1">
-		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
-	</monster>
 	<monster centerx="32416" centery="31085" centerz="8" radius="1">
 		<monster name="Chakoya Tribewarden" x="-1" y="0" z="8" spawntime="90" />
 	</monster>
 	<monster centerx="33104" centery="31085" centerz="8" radius="1">
 		<monster name="Draken Spellweaver" x="0" y="0" z="8" spawntime="90" />
 	</monster>
-	<monster centerx="33907" centery="31085" centerz="8" radius="1">
-		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33934" centery="31085" centerz="8" radius="1">
+	<monster centerx="33909" centery="31085" centerz="8" radius="1">
 		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
 	</monster>
 	<monster centerx="32421" centery="31086" centerz="8" radius="1">
@@ -49916,8 +49931,8 @@
 	<monster centerx="33109" centery="31088" centerz="8" radius="1">
 		<monster name="Draken Warmaster" x="0" y="0" z="8" spawntime="90" />
 	</monster>
-	<monster centerx="33913" centery="31088" centerz="8" radius="1">
-		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
+	<monster centerx="33900" centery="31088" centerz="8" radius="1">
+		<monster name="Capricious Phantom" x="0" y="0" z="8" spawntime="60" />
 	</monster>
 	<monster centerx="33056" centery="31089" centerz="8" radius="1">
 		<monster name="Draken Elite" x="0" y="0" z="8" spawntime="90" />
@@ -49962,7 +49977,7 @@
 		<monster name="Schiach" x="1" y="0" z="8" spawntime="60" />
 		<monster name="Percht" x="1" y="3" z="8" spawntime="60" />
 	</monster>
-	<monster centerx="33896" centery="31090" centerz="8" radius="1">
+	<monster centerx="33895" centery="31090" centerz="8" radius="1">
 		<monster name="Hazardous Phantom" x="0" y="0" z="8" spawntime="60" />
 	</monster>
 	<monster centerx="31909" centery="31091" centerz="8" radius="2">
@@ -49974,9 +49989,6 @@
 	<monster centerx="33102" centery="31091" centerz="8" radius="1">
 		<monster name="Draken Warmaster" x="0" y="0" z="8" spawntime="90" />
 	</monster>
-	<monster centerx="33904" centery="31091" centerz="8" radius="1">
-		<monster name="Capricious Phantom" x="0" y="0" z="8" spawntime="60" />
-	</monster>
 	<monster centerx="32421" centery="31092" centerz="8" radius="1">
 		<monster name="Chakoya Tribewarden" x="-1" y="-1" z="8" spawntime="90" />
 	</monster>
@@ -49995,6 +50007,9 @@
 	<monster centerx="33459" centery="31092" centerz="8" radius="1">
 		<monster name="Mutated Bat" x="0" y="0" z="8" spawntime="60" />
 	</monster>
+	<monster centerx="33900" centery="31092" centerz="8" radius="1">
+		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
+	</monster>
 	<monster centerx="31920" centery="31093" centerz="8" radius="2">
 		<monster name="Blood Crab" x="-1" y="-1" z="8" spawntime="90" />
 	</monster>
@@ -50028,10 +50043,7 @@
 	<monster centerx="33499" centery="31094" centerz="8" radius="1">
 		<monster name="Mutated Bat" x="0" y="0" z="8" spawntime="60" />
 	</monster>
-	<monster centerx="33895" centery="31095" centerz="8" radius="1">
-		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33904" centery="31095" centerz="8" radius="1">
+	<monster centerx="33894" centery="31095" centerz="8" radius="1">
 		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
 	</monster>
 	<monster centerx="31952" centery="31096" centerz="8" radius="2">
@@ -50127,6 +50139,9 @@
 	<monster centerx="33505" centery="31098" centerz="8" radius="1">
 		<monster name="Mutated Bat" x="0" y="0" z="8" spawntime="60" />
 	</monster>
+	<monster centerx="33932" centery="31098" centerz="8" radius="1">
+		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
+	</monster>
 	<monster centerx="33079" centery="31099" centerz="8" radius="1">
 		<monster name="Death Blob" x="-1" y="0" z="8" spawntime="90" />
 	</monster>
@@ -50136,6 +50151,9 @@
 	<monster centerx="33457" centery="31099" centerz="8" radius="1">
 		<monster name="Mutated Bat" x="0" y="0" z="8" spawntime="60" />
 	</monster>
+	<monster centerx="33923" centery="31099" centerz="8" radius="1">
+		<monster name="Hazardous Phantom" x="0" y="0" z="8" spawntime="60" />
+	</monster>
 	<monster centerx="33100" centery="31100" centerz="8" radius="1">
 		<monster name="Draken Warmaster" x="0" y="0" z="8" spawntime="90" />
 	</monster>
@@ -50151,8 +50169,8 @@
 	<monster centerx="33446" centery="31100" centerz="8" radius="1">
 		<monster name="Mutated Bat" x="0" y="0" z="8" spawntime="60" />
 	</monster>
-	<monster centerx="33936" centery="31100" centerz="8" radius="1">
-		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
+	<monster centerx="33933" centery="31100" centerz="8" radius="1">
+		<monster name="Capricious Phantom" x="0" y="0" z="8" spawntime="60" />
 	</monster>
 	<monster centerx="32751" centery="31101" centerz="8" radius="2">
 		<monster name="Braindeath" x="-1" y="1" z="8" spawntime="90" />
@@ -50172,6 +50190,12 @@
 	<monster centerx="33467" centery="31101" centerz="8" radius="1">
 		<monster name="Mutated Bat" x="0" y="0" z="8" spawntime="60" />
 	</monster>
+	<monster centerx="33926" centery="31101" centerz="8" radius="1">
+		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33929" centery="31101" centerz="8" radius="1">
+		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
+	</monster>
 	<monster centerx="32785" centery="31102" centerz="8" radius="2">
 		<monster name="Mutated Bat" x="-1" y="0" z="8" spawntime="90" />
 	</monster>
@@ -50181,12 +50205,6 @@
 	<monster centerx="33110" centery="31102" centerz="8" radius="1">
 		<monster name="Draken Warmaster" x="0" y="0" z="8" spawntime="90" />
 	</monster>
-	<monster centerx="33923" centery="31102" centerz="8" radius="1">
-		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33927" centery="31102" centerz="8" radius="1">
-		<monster name="Hazardous Phantom" x="0" y="0" z="8" spawntime="60" />
-	</monster>
 	<monster centerx="31928" centery="31103" centerz="8" radius="2">
 		<monster name="Blood Crab" x="2" y="0" z="8" spawntime="90" />
 	</monster>
@@ -50202,9 +50220,6 @@
 	<monster centerx="33541" centery="31103" centerz="8" radius="1">
 		<monster name="Mutated Tiger" x="0" y="0" z="8" spawntime="60" />
 	</monster>
-	<monster centerx="33937" centery="31103" centerz="8" radius="1">
-		<monster name="Capricious Phantom" x="0" y="0" z="8" spawntime="60" />
-	</monster>
 	<monster centerx="31965" centery="31104" centerz="8" radius="3">
 		<monster name="Pirate Skeleton" x="3" y="-1" z="8" spawntime="90" />
 		<monster name="Pirate Skeleton" x="1" y="2" z="8" spawntime="90" />
@@ -50242,8 +50257,8 @@
 	<monster centerx="33519" centery="31104" centerz="8" radius="1">
 		<monster name="Mutated Bat" x="0" y="0" z="8" spawntime="60" />
 	</monster>
-	<monster centerx="33933" centery="31104" centerz="8" radius="1">
-		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
+	<monster centerx="33924" centery="31104" centerz="8" radius="1">
+		<monster name="Capricious Phantom" x="0" y="0" z="8" spawntime="60" />
 	</monster>
 	<monster centerx="33082" centery="31105" centerz="8" radius="1">
 		<monster name="Draken Abomination" x="0" y="0" z="8" spawntime="90" />
@@ -50257,6 +50272,9 @@
 	<monster centerx="33059" centery="31106" centerz="8" radius="1">
 		<monster name="Draken Warmaster" x="0" y="0" z="8" spawntime="90" />
 	</monster>
+	<monster centerx="33928" centery="31106" centerz="8" radius="1">
+		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
+	</monster>
 	<monster centerx="33094" centery="31107" centerz="8" radius="1">
 		<monster name="Draken Warmaster" x="0" y="0" z="8" spawntime="90" />
 	</monster>
@@ -50275,6 +50293,9 @@
 	<monster centerx="33544" centery="31107" centerz="8" radius="1">
 		<monster name="Mutated Bat" x="0" y="0" z="8" spawntime="60" />
 	</monster>
+	<monster centerx="33921" centery="31107" centerz="8" radius="1">
+		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
+	</monster>
 	<monster centerx="31936" centery="31108" centerz="8" radius="2">
 		<monster name="Blood Crab" x="2" y="1" z="8" spawntime="90" />
 	</monster>
@@ -50284,6 +50305,9 @@
 	<monster centerx="33065" centery="31108" centerz="8" radius="1">
 		<monster name="Death Blob" x="1" y="0" z="8" spawntime="90" />
 	</monster>
+	<monster centerx="33906" centery="31108" centerz="8" radius="1">
+		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
+	</monster>
 	<monster centerx="32434" centery="31109" centerz="8" radius="1">
 		<monster name="Chakoya Tribewarden" x="-1" y="-1" z="8" spawntime="90" />
 		<monster name="Chakoya Windcaller" x="1" y="-1" z="8" spawntime="90" />
@@ -50298,9 +50322,6 @@
 	<monster centerx="33490" centery="31109" centerz="8" radius="1">
 		<monster name="Mutated Bat" x="0" y="0" z="8" spawntime="60" />
 	</monster>
-	<monster centerx="33932" centery="31109" centerz="8" radius="1">
-		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
-	</monster>
 	<monster centerx="32470" centery="31110" centerz="8" radius="1">
 		<monster name="Chakoya Tribewarden" x="-1" y="-1" z="8" spawntime="90" />
 	</monster>
@@ -50310,15 +50331,12 @@
 	<monster centerx="33286" centery="31110" centerz="8" radius="1">
 		<monster name="Brimstone Bug" x="0" y="0" z="8" spawntime="90" />
 	</monster>
-	<monster centerx="33898" centery="31110" centerz="8" radius="1">
+	<monster centerx="33901" centery="31110" centerz="8" radius="1">
 		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
 	</monster>
-	<monster centerx="33922" centery="31110" centerz="8" radius="1">
+	<monster centerx="33905" centery="31110" centerz="8" radius="1">
 		<monster name="Capricious Phantom" x="0" y="0" z="8" spawntime="60" />
 	</monster>
-	<monster centerx="33925" centery="31110" centerz="8" radius="1">
-		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
-	</monster>
 	<monster centerx="32084" centery="31111" centerz="8" radius="3">
 		<monster name="Quara Constrictor Scout" x="-1" y="1" z="8" spawntime="90" />
 		<monster name="Quara Constrictor Scout" x="-1" y="2" z="8" spawntime="90" />
@@ -50329,8 +50347,11 @@
 	<monster centerx="33074" centery="31111" centerz="8" radius="1">
 		<monster name="Draken Warmaster" x="0" y="0" z="8" spawntime="90" />
 	</monster>
-	<monster centerx="33910" centery="31111" centerz="8" radius="1">
-		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
+	<monster centerx="33897" centery="31111" centerz="8" radius="1">
+		<monster name="Hazardous Phantom" x="1" y="1" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33921" centery="31111" centerz="8" radius="1">
+		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
 	</monster>
 	<monster centerx="31927" centery="31112" centerz="8" radius="2">
 		<monster name="Blood Crab" x="-1" y="-1" z="8" spawntime="90" />
@@ -50346,12 +50367,6 @@
 	<monster centerx="33110" centery="31113" centerz="8" radius="1">
 		<monster name="Draken Warmaster" x="0" y="0" z="8" spawntime="90" />
 	</monster>
-	<monster centerx="33898" centery="31113" centerz="8" radius="1">
-		<monster name="Hazardous Phantom" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33909" centery="31113" centerz="8" radius="1">
-		<monster name="Capricious Phantom" x="0" y="0" z="8" spawntime="60" />
-	</monster>
 	<monster centerx="32432" centery="31114" centerz="8" radius="1">
 		<monster name="Chakoya Tribewarden" x="1" y="-1" z="8" spawntime="90" />
 		<monster name="Chakoya Toolshaper" x="-1" y="1" z="8" spawntime="90" />
@@ -50359,9 +50374,12 @@
 	<monster centerx="33098" centery="31114" centerz="8" radius="1">
 		<monster name="Draken Warmaster" x="0" y="0" z="8" spawntime="90" />
 	</monster>
-	<monster centerx="33925" centery="31114" centerz="8" radius="1">
+	<monster centerx="33900" centery="31114" centerz="8" radius="1">
 		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
 	</monster>
+	<monster centerx="33925" centery="31114" centerz="8" radius="1">
+		<monster name="Hazardous Phantom" x="0" y="0" z="8" spawntime="60" />
+	</monster>
 	<monster centerx="33058" centery="31115" centerz="8" radius="1">
 		<monster name="Draken Elite" x="0" y="0" z="8" spawntime="90" />
 	</monster>
@@ -50377,6 +50395,12 @@
 	<monster centerx="33545" centery="31115" centerz="8" radius="1">
 		<monster name="Mutated Bat" x="0" y="0" z="8" spawntime="60" />
 	</monster>
+	<monster centerx="33905" centery="31115" centerz="8" radius="1">
+		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33921" centery="31115" centerz="8" radius="1">
+		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
+	</monster>
 	<monster centerx="32713" centery="31116" centerz="8" radius="2">
 		<monster name="Mutated Human" x="1" y="0" z="8" spawntime="90" />
 		<monster name="Spit Nettle" x="1" y="1" z="8" spawntime="90" />
@@ -50393,6 +50417,9 @@
 	<monster centerx="33437" centery="31116" centerz="8" radius="1">
 		<monster name="Lizard Legionnaire" x="0" y="0" z="8" spawntime="60" />
 	</monster>
+	<monster centerx="33929" centery="31116" centerz="8" radius="1">
+		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
+	</monster>
 	<monster centerx="32721" centery="31117" centerz="8" radius="2">
 		<monster name="Mutated Human" x="1" y="0" z="8" spawntime="90" />
 	</monster>
@@ -50411,12 +50438,6 @@
 	<monster centerx="33539" centery="31117" centerz="8" radius="1">
 		<monster name="Mutated Bat" x="0" y="0" z="8" spawntime="60" />
 	</monster>
-	<monster centerx="33904" centery="31117" centerz="8" radius="1">
-		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33929" centery="31117" centerz="8" radius="1">
-		<monster name="Hazardous Phantom" x="0" y="0" z="8" spawntime="60" />
-	</monster>
 	<monster centerx="31933" centery="31118" centerz="8" radius="2">
 		<monster name="Blood Crab" x="1" y="0" z="8" spawntime="90" />
 	</monster>
@@ -50433,12 +50454,9 @@
 	<monster centerx="33284" centery="31118" centerz="8" radius="1">
 		<monster name="Brimstone Bug" x="0" y="1" z="8" spawntime="90" />
 	</monster>
-	<monster centerx="33909" centery="31118" centerz="8" radius="1">
+	<monster centerx="33898" centery="31118" centerz="8" radius="1">
 		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
 	</monster>
-	<monster centerx="33925" centery="31118" centerz="8" radius="1">
-		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
-	</monster>
 	<monster centerx="33110" centery="31119" centerz="8" radius="1">
 		<monster name="Death Blob" x="0" y="1" z="8" spawntime="90" />
 	</monster>
@@ -50451,8 +50469,8 @@
 	<monster centerx="33542" centery="31119" centerz="8" radius="1">
 		<monster name="Mutated Tiger" x="0" y="0" z="8" spawntime="60" />
 	</monster>
-	<monster centerx="33933" centery="31119" centerz="8" radius="1">
-		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
+	<monster centerx="33905" centery="31119" centerz="8" radius="1">
+		<monster name="Hazardous Phantom" x="0" y="0" z="8" spawntime="60" />
 	</monster>
 	<monster centerx="33102" centery="31120" centerz="8" radius="1">
 		<monster name="Draken Spellweaver" x="0" y="0" z="8" spawntime="90" />
@@ -50460,9 +50478,6 @@
 	<monster centerx="33089" centery="31121" centerz="8" radius="1">
 		<monster name="Draken Elite" x="0" y="0" z="8" spawntime="90" />
 	</monster>
-	<monster centerx="33902" centery="31121" centerz="8" radius="1">
-		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
-	</monster>
 	<monster centerx="32712" centery="31122" centerz="8" radius="2">
 		<monster name="Mutated Human" x="1" y="0" z="8" spawntime="90" />
 	</monster>
@@ -50487,8 +50502,8 @@
 	<monster centerx="33899" centery="31122" centerz="8" radius="1">
 		<monster name="Capricious Phantom" x="0" y="0" z="8" spawntime="60" />
 	</monster>
-	<monster centerx="33909" centery="31122" centerz="8" radius="1">
-		<monster name="Hazardous Phantom" x="0" y="0" z="8" spawntime="60" />
+	<monster centerx="33906" centery="31122" centerz="8" radius="1">
+		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
 	</monster>
 	<monster centerx="33314" centery="31123" centerz="8" radius="1">
 		<monster name="Lizard Legionnaire" x="0" y="0" z="8" spawntime="90" />
@@ -50537,9 +50552,6 @@
 	<monster centerx="33324" centery="31125" centerz="8" radius="1">
 		<monster name="Lizard High Guard" x="0" y="0" z="8" spawntime="90" />
 	</monster>
-	<monster centerx="33910" centery="31125" centerz="8" radius="1">
-		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
-	</monster>
 	<monster centerx="32763" centery="31126" centerz="8" radius="2">
 		<monster name="Skeleton" x="2" y="-1" z="8" spawntime="90" />
 		<monster name="Skeleton" x="-1" y="0" z="8" spawntime="90" />
@@ -73808,20 +73820,34 @@
 	<monster centerx="32810" centery="31009" centerz="9" radius="1">
 		<monster name="Grim Reaper" x="0" y="0" z="9" spawntime="90" />
 	</monster>
+	<monster centerx="33889" centery="31009" centerz="9" radius="5">
+		<monster name="Bony Sea Devil" x="2" y="1" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="5" y="1" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="-1" y="2" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="1" y="3" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="3" y="3" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="5" y="4" z="9" spawntime="60" />
+	</monster>
+	<monster centerx="33908" centery="31009" centerz="9" radius="5">
+		<monster name="Bony Sea Devil" x="3" y="-1" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="-2" y="1" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="1" y="1" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="-4" y="2" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="-2" y="3" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="0" y="3" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="3" y="3" z="9" spawntime="60" />
+	</monster>
+	<monster centerx="33941" centery="31009" centerz="9" radius="1">
+		<monster name="Bony Sea Devil" x="1" y="1" z="9" spawntime="60" />
+	</monster>
 	<monster centerx="32772" centery="31010" centerz="9" radius="1">
 		<monster name="Grim Reaper" x="0" y="0" z="9" spawntime="90" />
 	</monster>
 	<monster centerx="33466" centery="31010" centerz="9" radius="1">
 		<monster name="Memory Of An Ogre" x="0" y="0" z="9" spawntime="60" />
 	</monster>
-	<monster centerx="33933" centery="31010" centerz="9" radius="1">
-		<monster name="Bony Sea Devil" x="0" y="0" z="9" spawntime="60" />
-	</monster>
 	<monster centerx="33944" centery="31010" centerz="9" radius="1">
-		<monster name="Bony Sea Devil" x="0" y="0" z="9" spawntime="60" />
-	</monster>
-	<monster centerx="33948" centery="31010" centerz="9" radius="1">
-		<monster name="Capricious Phantom" x="0" y="0" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="1" y="0" z="9" spawntime="60" />
 	</monster>
 	<monster centerx="32166" centery="31011" centerz="9" radius="5">
 		<monster name="Lancer Beetle" x="0" y="-2" z="9" spawntime="90" />
@@ -73833,22 +73859,8 @@
 	<monster centerx="33475" centery="31012" centerz="9" radius="1">
 		<monster name="Memory Of An Ogre" x="0" y="0" z="9" spawntime="60" />
 	</monster>
-	<monster centerx="33893" centery="31012" centerz="9" radius="5">
-		<monster name="Capricious Phantom" x="-1" y="-2" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="2" y="-1" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="4" y="0" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="-1" y="2" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="1" y="3" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="3" y="3" z="9" spawntime="60" />
-	</monster>
-	<monster centerx="33912" centery="31012" centerz="9" radius="5">
-		<monster name="Turbulent Elemental" x="1" y="-2" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="-2" y="-1" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="3" y="-1" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="-2" y="0" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="-2" y="3" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="0" y="3" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="3" y="3" z="9" spawntime="60" />
+	<monster centerx="33923" centery="31012" centerz="9" radius="1">
+		<monster name="Bony Sea Devil" x="-1" y="1" z="9" spawntime="60" />
 	</monster>
 	<monster centerx="32007" centery="31013" centerz="9" radius="3">
 		<monster name="Demon" x="0" y="2" z="9" spawntime="90" />
@@ -73863,6 +73875,15 @@
 	<monster centerx="33485" centery="31015" centerz="9" radius="1">
 		<monster name="Memory Of An Ogre" x="0" y="0" z="9" spawntime="60" />
 	</monster>
+	<monster centerx="33930" centery="31015" centerz="9" radius="5">
+		<monster name="Turbulent Elemental" x="-3" y="-3" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="0" y="-3" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="3" y="-2" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="-3" y="0" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="3" y="2" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="-4" y="3" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="-1" y="3" z="9" spawntime="60" />
+	</monster>
 	<monster centerx="34028" centery="31015" centerz="9" radius="2">
 		<monster name="Infernal Phantom" x="0" y="-1" z="9" spawntime="60" />
 		<monster name="Brachiodemon" x="-1" y="2" z="9" spawntime="60" />
@@ -73914,15 +73935,6 @@
 	<monster centerx="33542" centery="31018" centerz="9" radius="1">
 		<monster name="Memory Of A Book" x="0" y="0" z="9" spawntime="60" />
 	</monster>
-	<monster centerx="33934" centery="31018" centerz="9" radius="5">
-		<monster name="Turbulent Elemental" x="-3" y="-3" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="0" y="-3" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="3" y="-2" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="-3" y="0" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="3" y="2" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="-4" y="3" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="-1" y="3" z="9" spawntime="60" />
-	</monster>
 	<monster centerx="32767" centery="31019" centerz="9" radius="1">
 		<monster name="Grim Reaper" x="0" y="0" z="9" spawntime="90" />
 	</monster>
@@ -73970,6 +73982,14 @@
 		<monster name="Old Beholder" x="-3" y="1" z="9" spawntime="60" />
 		<monster name="Skeleton" x="-1" y="1" z="9" spawntime="60" />
 	</monster>
+	<monster centerx="33939" centery="31020" centerz="9" radius="5">
+		<monster name="Capricious Phantom" x="1" y="-3" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="4" y="-2" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="-3" y="1" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="3" y="1" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="-2" y="3" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="2" y="4" z="9" spawntime="60" />
+	</monster>
 	<monster centerx="34022" centery="31020" centerz="9" radius="1">
 		<monster name="Brachiodemon" x="0" y="0" z="9" spawntime="60" />
 	</monster>
@@ -73988,14 +74008,6 @@
 		<monster name="Infernal Phantom" x="-1" y="1" z="9" spawntime="60" />
 		<monster name="Infernal Demon" x="2" y="1" z="9" spawntime="60" />
 	</monster>
-	<monster centerx="33943" centery="31023" centerz="9" radius="5">
-		<monster name="Capricious Phantom" x="1" y="-3" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="4" y="-2" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="-3" y="1" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="3" y="1" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="-2" y="3" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="2" y="4" z="9" spawntime="60" />
-	</monster>
 	<monster centerx="34006" centery="31023" centerz="9" radius="1">
 		<monster name="Infernal Demon" x="0" y="0" z="9" spawntime="60" />
 	</monster>
@@ -74060,8 +74072,23 @@
 	<monster centerx="33652" centery="31027" centerz="9" radius="3">
 		<monster name="Old Beholder" x="0" y="-2" z="9" spawntime="60" />
 	</monster>
-	<monster centerx="33891" centery="31027" centerz="9" radius="1">
-		<monster name="Bony Sea Devil" x="0" y="0" z="9" spawntime="60" />
+	<monster centerx="33896" centery="31027" centerz="9" radius="5">
+		<monster name="Bony Sea Devil" x="1" y="-2" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="4" y="-2" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="-4" y="-1" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="-1" y="1" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="3" y="2" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="1" y="4" z="9" spawntime="60" />
+	</monster>
+	<monster centerx="33919" centery="31027" centerz="9" radius="5">
+		<monster name="Turbulent Elemental" x="0" y="-4" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="2" y="-4" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="-2" y="-2" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="3" y="-1" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="-2" y="1" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="2" y="2" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="-3" y="3" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="0" y="4" z="9" spawntime="60" />
 	</monster>
 	<monster centerx="33988" centery="31027" centerz="9" radius="2">
 		<monster name="Infernal Demon" x="-1" y="-1" z="9" spawntime="60" />
@@ -74091,6 +74118,9 @@
 	<monster centerx="32808" centery="31028" centerz="9" radius="3">
 		<monster name="Grim Reaper" x="3" y="-3" z="9" spawntime="90" />
 	</monster>
+	<monster centerx="33891" centery="31028" centerz="9" radius="1">
+		<monster name="Bony Sea Devil" x="-1" y="1" z="9" spawntime="60" />
+	</monster>
 	<monster centerx="32081" centery="31029" centerz="9" radius="3">
 		<monster name="Frost Troll" x="-1" y="-1" z="9" spawntime="90" />
 		<monster name="Frost Troll" x="2" y="2" z="9" spawntime="90" />
@@ -74146,24 +74176,6 @@
 	<monster centerx="33501" centery="31030" centerz="9" radius="1">
 		<monster name="Memory Of A Shaper" x="0" y="0" z="9" spawntime="60" />
 	</monster>
-	<monster centerx="33900" centery="31030" centerz="9" radius="5">
-		<monster name="Bony Sea Devil" x="1" y="-2" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="4" y="-2" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="-4" y="-1" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="-1" y="1" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="3" y="2" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="1" y="4" z="9" spawntime="60" />
-	</monster>
-	<monster centerx="33923" centery="31030" centerz="9" radius="5">
-		<monster name="Turbulent Elemental" x="0" y="-4" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="2" y="-4" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="-2" y="-2" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="3" y="-1" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="-2" y="1" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="2" y="2" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="-3" y="3" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="0" y="4" z="9" spawntime="60" />
-	</monster>
 	<monster centerx="33980" centery="31030" centerz="9" radius="2">
 		<monster name="Brachiodemon" x="2" y="-2" z="9" spawntime="60" />
 		<monster name="Infernal Demon" x="-1" y="-1" z="9" spawntime="60" />
@@ -74182,6 +74194,15 @@
 		<monster name="Memory Of An Ogre" x="-1" y="0" z="9" spawntime="60" />
 		<monster name="Memory Of An Ogre" x="0" y="0" z="9" spawntime="60" />
 	</monster>
+	<monster centerx="33940" centery="31031" centerz="9" radius="5">
+		<monster name="Capricious Phantom" x="3" y="-3" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="-3" y="-1" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="-1" y="-1" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="3" y="0" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="-1" y="2" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="3" y="2" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="-4" y="3" z="9" spawntime="60" />
+	</monster>
 	<monster centerx="31937" centery="31032" centerz="9" radius="3">
 		<monster name="Sea Serpent" x="-3" y="0" z="9" spawntime="90" />
 		<monster name="Sea Serpent" x="0" y="3" z="9" spawntime="90" />
@@ -74234,15 +74255,6 @@
 	<monster centerx="33617" centery="31034" centerz="9" radius="3">
 		<monster name="Skeleton" x="-1" y="-3" z="9" spawntime="60" />
 	</monster>
-	<monster centerx="33944" centery="31034" centerz="9" radius="5">
-		<monster name="Capricious Phantom" x="3" y="-2" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="-3" y="-1" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="-1" y="-1" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="3" y="0" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="-1" y="2" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="3" y="2" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="-4" y="3" z="9" spawntime="60" />
-	</monster>
 	<monster centerx="32335" centery="31036" centerz="9" radius="1">
 		<monster name="Crystal Spider" x="0" y="0" z="9" spawntime="90" />
 	</monster>
@@ -74255,6 +74267,12 @@
 	<monster centerx="33537" centery="31038" centerz="9" radius="1">
 		<monster name="Memory Of A Faun" x="0" y="0" z="9" spawntime="60" />
 	</monster>
+	<monster centerx="33891" centery="31038" centerz="9" radius="1">
+		<monster name="Turbulent Elemental" x="0" y="1" z="9" spawntime="60" />
+	</monster>
+	<monster centerx="33911" centery="31038" centerz="9" radius="1">
+		<monster name="Turbulent Elemental" x="0" y="0" z="9" spawntime="60" />
+	</monster>
 	<monster centerx="34025" centery="31038" centerz="9" radius="2">
 		<monster name="Brachiodemon" x="-2" y="-2" z="9" spawntime="60" />
 		<monster name="Infernal Phantom" x="0" y="-1" z="9" spawntime="60" />
@@ -74283,12 +74301,6 @@
 		<monster name="Chakoya Toolshaper" x="1" y="-1" z="9" spawntime="90" />
 		<monster name="Chakoya Toolshaper" x="0" y="1" z="9" spawntime="90" />
 	</monster>
-	<monster centerx="33892" centery="31040" centerz="9" radius="1">
-		<monster name="Turbulent Elemental" x="0" y="0" z="9" spawntime="60" />
-	</monster>
-	<monster centerx="33914" centery="31040" centerz="9" radius="1">
-		<monster name="Turbulent Elemental" x="0" y="0" z="9" spawntime="60" />
-	</monster>
 	<monster centerx="33998" centery="31040" centerz="9" radius="2">
 		<monster name="Infernal Demon" x="-1" y="-1" z="9" spawntime="60" />
 		<monster name="Infernal Phantom" x="-1" y="0" z="9" spawntime="60" />
@@ -74350,6 +74362,18 @@
 	<monster centerx="33488" centery="31044" centerz="9" radius="1">
 		<monster name="Memory Of A Shaper" x="0" y="0" z="9" spawntime="60" />
 	</monster>
+	<monster centerx="33933" centery="31044" centerz="9" radius="5">
+		<monster name="Turbulent Elemental" x="0" y="-3" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="2" y="-3" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="-3" y="-2" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="1" y="1" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="-2" y="2" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="-4" y="3" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="3" y="3" z="9" spawntime="60" />
+	</monster>
+	<monster centerx="33945" centery="31044" centerz="9" radius="1">
+		<monster name="Bony Sea Devil" x="0" y="0" z="9" spawntime="60" />
+	</monster>
 	<monster centerx="33461" centery="31045" centerz="9" radius="1">
 		<monster name="Memory Of An Ogre" x="0" y="0" z="9" spawntime="60" />
 	</monster>
@@ -74359,6 +74383,23 @@
 	<monster centerx="33538" centery="31045" centerz="9" radius="1">
 		<monster name="Memory Of A Faun" x="0" y="0" z="9" spawntime="60" />
 	</monster>
+	<monster centerx="33891" centery="31045" centerz="9" radius="5">
+		<monster name="Capricious Phantom" x="0" y="-3" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="-1" y="-1" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="1" y="0" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="-1" y="2" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="1" y="2" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="-3" y="4" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="1" y="4" z="9" spawntime="60" />
+	</monster>
+	<monster centerx="33910" centery="31045" centerz="9" radius="5">
+		<monster name="Bony Sea Devil" x="-3" y="-3" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="0" y="-2" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="3" y="-2" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="-2" y="0" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="1" y="3" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="-1" y="5" z="9" spawntime="60" />
+	</monster>
 	<monster centerx="33983" centery="31045" centerz="9" radius="2">
 		<monster name="Infernal Phantom" x="0" y="-1" z="9" spawntime="60" />
 		<monster name="Infernal Demon" x="0" y="0" z="9" spawntime="60" />
@@ -74386,16 +74427,7 @@
 	<monster centerx="33464" centery="31047" centerz="9" radius="1">
 		<monster name="Memory Of An Ogre" x="0" y="0" z="9" spawntime="60" />
 	</monster>
-	<monster centerx="33937" centery="31047" centerz="9" radius="5">
-		<monster name="Turbulent Elemental" x="0" y="-3" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="2" y="-3" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="-3" y="-2" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="1" y="1" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="-2" y="2" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="-4" y="3" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="3" y="3" z="9" spawntime="60" />
-	</monster>
-	<monster centerx="33949" centery="31047" centerz="9" radius="1">
+	<monster centerx="33919" centery="31047" centerz="9" radius="1">
 		<monster name="Bony Sea Devil" x="0" y="0" z="9" spawntime="60" />
 	</monster>
 	<monster centerx="34034" centery="31047" centerz="9" radius="1">
@@ -74438,14 +74470,6 @@
 		<monster name="Skeleton" x="-2" y="-1" z="9" spawntime="60" />
 		<monster name="Old Beholder" x="2" y="-1" z="9" spawntime="60" />
 	</monster>
-	<monster centerx="33914" centery="31048" centerz="9" radius="5">
-		<monster name="Bony Sea Devil" x="-3" y="-3" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="0" y="-2" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="3" y="-2" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="-2" y="-1" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="1" y="3" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="-1" y="5" z="9" spawntime="60" />
-	</monster>
 	<monster centerx="34029" centery="31048" centerz="9" radius="1">
 		<monster name="Infernal Demon" x="0" y="0" z="9" spawntime="60" />
 	</monster>
@@ -74464,15 +74488,6 @@
 	<monster centerx="33645" centery="31049" centerz="9" radius="3">
 		<monster name="Old Beholder" x="3" y="0" z="9" spawntime="60" />
 	</monster>
-	<monster centerx="33892" centery="31049" centerz="9" radius="5">
-		<monster name="Bony Sea Devil" x="-3" y="-4" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="2" y="-2" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="-3" y="-1" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="2" y="1" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="4" y="1" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="-2" y="2" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="0" y="3" z="9" spawntime="60" />
-	</monster>
 	<monster centerx="33994" centery="31049" centerz="9" radius="2">
 		<monster name="Brachiodemon" x="-2" y="-1" z="9" spawntime="60" />
 		<monster name="Infernal Phantom" x="-1" y="-1" z="9" spawntime="60" />
@@ -74494,9 +74509,6 @@
 	<monster centerx="33539" centery="31050" centerz="9" radius="1">
 		<monster name="Memory Of A Faun" x="0" y="0" z="9" spawntime="60" />
 	</monster>
-	<monster centerx="33923" centery="31050" centerz="9" radius="1">
-		<monster name="Bony Sea Devil" x="0" y="0" z="9" spawntime="60" />
-	</monster>
 	<monster centerx="32376" centery="31051" centerz="9" radius="5">
 		<monster name="Crystal Spider" x="-5" y="-3" z="9" spawntime="90" />
 		<monster name="Ice Golem" x="-3" y="-2" z="9" spawntime="90" />
@@ -74607,6 +74619,15 @@
 	<monster centerx="33538" centery="31057" centerz="9" radius="1">
 		<monster name="Memory Of A Faun" x="0" y="0" z="9" spawntime="60" />
 	</monster>
+	<monster centerx="33930" centery="31057" centerz="9" radius="5">
+		<monster name="Capricious Phantom" x="-1" y="-4" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="2" y="-3" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="4" y="-3" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="-3" y="-1" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="5" y="-1" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="3" y="1" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="-1" y="2" z="9" spawntime="60" />
+	</monster>
 	<monster centerx="32454" centery="31058" centerz="9" radius="1">
 		<monster name="Chakoya Toolshaper" x="0" y="-1" z="9" spawntime="90" />
 	</monster>
@@ -74640,15 +74661,6 @@
 		<monster name="Grim Reaper" x="2" y="0" z="9" spawntime="90" />
 		<monster name="Grim Reaper" x="1" y="3" z="9" spawntime="90" />
 	</monster>
-	<monster centerx="33934" centery="31060" centerz="9" radius="5">
-		<monster name="Capricious Phantom" x="-2" y="-3" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="2" y="-3" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="4" y="-3" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="-3" y="-1" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="5" y="-1" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="3" y="1" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="-1" y="2" z="9" spawntime="60" />
-	</monster>
 	<monster centerx="33997" centery="31060" centerz="9" radius="2">
 		<monster name="Infernal Demon" x="-1" y="-2" z="9" spawntime="60" />
 		<monster name="Brachiodemon" x="2" y="-2" z="9" spawntime="60" />
@@ -74727,6 +74739,14 @@
 	<monster centerx="32146" centery="31064" centerz="9" radius="3">
 		<monster name="Mammoth" x="1" y="1" z="9" spawntime="90" />
 	</monster>
+	<monster centerx="33910" centery="31064" centerz="9" radius="5">
+		<monster name="Bony Sea Devil" x="-2" y="-3" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="3" y="-3" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="-2" y="1" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="4" y="1" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="0" y="3" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="-3" y="4" z="9" spawntime="60" />
+	</monster>
 	<monster centerx="33495" centery="31065" centerz="9" radius="1">
 		<monster name="Memory Of A Shaper" x="0" y="0" z="9" spawntime="60" />
 	</monster>
@@ -74746,6 +74766,17 @@
 	<monster centerx="32801" centery="31066" centerz="9" radius="1">
 		<monster name="Grim Reaper" x="0" y="0" z="9" spawntime="90" />
 	</monster>
+	<monster centerx="33889" centery="31066" centerz="9" radius="1">
+		<monster name="Bony Sea Devil" x="1" y="1" z="9" spawntime="60" />
+	</monster>
+	<monster centerx="33930" centery="31066" centerz="9" radius="5">
+		<monster name="Bony Sea Devil" x="0" y="-3" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="-3" y="-1" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="2" y="-1" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="3" y="1" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="-3" y="2" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="-1" y="4" z="9" spawntime="60" />
+	</monster>
 	<monster centerx="33989" centery="31066" centerz="9" radius="2">
 		<monster name="Brachiodemon" x="2" y="-2" z="9" spawntime="60" />
 		<monster name="Infernal Demon" x="-2" y="-1" z="9" spawntime="60" />
@@ -74769,13 +74800,14 @@
 	<monster centerx="33551" centery="31067" centerz="9" radius="1">
 		<monster name="Memory Of A Faun" x="0" y="0" z="9" spawntime="60" />
 	</monster>
-	<monster centerx="33914" centery="31067" centerz="9" radius="5">
-		<monster name="Bony Sea Devil" x="-2" y="-3" z="9" spawntime="60" />
+	<monster centerx="33895" centery="31067" centerz="9" radius="5">
+		<monster name="Turbulent Elemental" x="-1" y="-3" z="9" spawntime="60" />
 		<monster name="Bony Sea Devil" x="3" y="-3" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="-2" y="1" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="4" y="1" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="0" y="3" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="-3" y="4" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="-2" y="-2" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="2" y="0" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="-2" y="3" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="1" y="3" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="3" y="3" z="9" spawntime="60" />
 	</monster>
 	<monster centerx="34003" centery="31067" centerz="9" radius="2">
 		<monster name="Infernal Phantom" x="0" y="0" z="9" spawntime="60" />
@@ -74818,17 +74850,6 @@
 	<monster centerx="33861" centery="31069" centerz="9" radius="3">
 		<monster name="Schiach" x="1" y="1" z="9" spawntime="60" />
 	</monster>
-	<monster centerx="33890" centery="31069" centerz="9" radius="1">
-		<monster name="Bony Sea Devil" x="0" y="0" z="9" spawntime="60" />
-	</monster>
-	<monster centerx="33934" centery="31069" centerz="9" radius="5">
-		<monster name="Bony Sea Devil" x="0" y="-3" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="-3" y="-1" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="2" y="-1" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="3" y="1" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="-3" y="2" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="-1" y="4" z="9" spawntime="60" />
-	</monster>
 	<monster centerx="32733" centery="31070" centerz="9" radius="4">
 		<monster name="Crypt Shambler" x="-1" y="-4" z="9" spawntime="90" />
 		<monster name="Ghoul" x="2" y="-4" z="9" spawntime="90" />
@@ -74843,15 +74864,6 @@
 	<monster centerx="32801" centery="31070" centerz="9" radius="3">
 		<monster name="Grim Reaper" x="0" y="-2" z="9" spawntime="90" />
 	</monster>
-	<monster centerx="33899" centery="31070" centerz="9" radius="5">
-		<monster name="Turbulent Elemental" x="-1" y="-3" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="3" y="-3" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="-2" y="-2" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="2" y="0" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="-2" y="3" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="1" y="3" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="3" y="3" z="9" spawntime="60" />
-	</monster>
 	<monster centerx="32337" centery="31071" centerz="9" radius="1">
 		<monster name="Crystal Spider" x="0" y="0" z="9" spawntime="90" />
 	</monster>
@@ -74872,6 +74884,9 @@
 	<monster centerx="32778" centery="31071" centerz="9" radius="1">
 		<monster name="Grim Reaper" x="0" y="0" z="9" spawntime="90" />
 	</monster>
+	<monster centerx="33889" centery="31071" centerz="9" radius="1">
+		<monster name="Turbulent Elemental" x="0" y="0" z="9" spawntime="60" />
+	</monster>
 	<monster centerx="32146" centery="31072" centerz="9" radius="3">
 		<monster name="Novice Of The Cult" x="-1" y="-1" z="9" spawntime="90" />
 		<monster name="Novice Of The Cult" x="2" y="2" z="9" spawntime="90" />
@@ -74896,6 +74911,9 @@
 		<monster name="Crystal Spider" x="-1" y="2" z="9" spawntime="90" />
 		<monster name="Crystal Spider" x="3" y="3" z="9" spawntime="90" />
 	</monster>
+	<monster centerx="33945" centery="31073" centerz="9" radius="1">
+		<monster name="Bony Sea Devil" x="1" y="-1" z="9" spawntime="60" />
+	</monster>
 	<monster centerx="33997" centery="31073" centerz="9" radius="2">
 		<monster name="Infernal Demon" x="-2" y="-2" z="9" spawntime="60" />
 		<monster name="Brachiodemon" x="2" y="-2" z="9" spawntime="60" />
@@ -74918,9 +74936,6 @@
 		<monster name="Chakoya Windcaller" x="-1" y="2" z="9" spawntime="90" />
 		<monster name="Chakoya Tribewarden" x="2" y="2" z="9" spawntime="90" />
 	</monster>
-	<monster centerx="33891" centery="31074" centerz="9" radius="1">
-		<monster name="Turbulent Elemental" x="0" y="0" z="9" spawntime="60" />
-	</monster>
 	<monster centerx="31913" centery="31075" centerz="9" radius="3">
 		<monster name="Sea Serpent" x="0" y="-2" z="9" spawntime="90" />
 		<monster name="Sea Serpent" x="1" y="0" z="9" spawntime="90" />
@@ -74977,9 +74992,6 @@
 	<monster centerx="33100" centery="31076" centerz="9" radius="1">
 		<monster name="Death Blob" x="0" y="0" z="9" spawntime="90" />
 	</monster>
-	<monster centerx="33949" centery="31076" centerz="9" radius="1">
-		<monster name="Bony Sea Devil" x="1" y="-1" z="9" spawntime="60" />
-	</monster>
 	<monster centerx="32021" centery="31077" centerz="9" radius="3">
 		<monster name="Novice Of The Cult" x="-3" y="-1" z="9" spawntime="90" />
 		<monster name="Novice Of The Cult" x="3" y="0" z="9" spawntime="90" />
@@ -75028,35 +75040,22 @@
 		<monster name="Schiach" x="1" y="1" z="9" spawntime="60" />
 		<monster name="Schiach" x="-1" y="2" z="9" spawntime="60" />
 	</monster>
-	<monster centerx="33057" centery="31078" centerz="9" radius="1">
-		<monster name="Death Blob" x="0" y="0" z="9" spawntime="90" />
-	</monster>
-	<monster centerx="32416" centery="31079" centerz="9" radius="1">
-		<monster name="Chakoya Tribewarden" x="1" y="-1" z="9" spawntime="90" />
-		<monster name="Chakoya Windcaller" x="-1" y="1" z="9" spawntime="90" />
-	</monster>
-	<monster centerx="32736" centery="31079" centerz="9" radius="2">
-		<monster name="Ghoul" x="1" y="-1" z="9" spawntime="90" />
-	</monster>
-	<monster centerx="32145" centery="31080" centerz="9" radius="3">
-		<monster name="Gargoyle" x="2" y="1" z="9" spawntime="90" />
-	</monster>
-	<monster centerx="33910" centery="31080" centerz="9" radius="5">
+	<monster centerx="33906" centery="31077" centerz="9" radius="5">
 		<monster name="Bony Sea Devil" x="2" y="-3" z="9" spawntime="60" />
 		<monster name="Turbulent Elemental" x="-1" y="-2" z="9" spawntime="60" />
 		<monster name="Turbulent Elemental" x="-4" y="0" z="9" spawntime="60" />
 		<monster name="Capricious Phantom" x="-1" y="1" z="9" spawntime="60" />
 		<monster name="Capricious Phantom" x="3" y="3" z="9" spawntime="60" />
 	</monster>
-	<monster centerx="33065" centery="31081" centerz="9" radius="1">
-		<monster name="Draken Spellweaver" x="0" y="0" z="9" spawntime="90" />
+	<monster centerx="33057" centery="31078" centerz="9" radius="1">
+		<monster name="Death Blob" x="0" y="0" z="9" spawntime="90" />
 	</monster>
-	<monster centerx="33899" centery="31081" centerz="9" radius="5">
+	<monster centerx="33895" centery="31078" centerz="9" radius="5">
 		<monster name="Capricious Phantom" x="-2" y="-2" z="9" spawntime="60" />
 		<monster name="Bony Sea Devil" x="2" y="-2" z="9" spawntime="60" />
 		<monster name="Turbulent Elemental" x="3" y="1" z="9" spawntime="60" />
 	</monster>
-	<monster centerx="33941" centery="31081" centerz="9" radius="5">
+	<monster centerx="33937" centery="31078" centerz="9" radius="5">
 		<monster name="Turbulent Elemental" x="-3" y="-3" z="9" spawntime="60" />
 		<monster name="Bony Sea Devil" x="-1" y="-3" z="9" spawntime="60" />
 		<monster name="Capricious Phantom" x="3" y="-3" z="9" spawntime="60" />
@@ -75065,6 +75064,19 @@
 		<monster name="Bony Sea Devil" x="3" y="3" z="9" spawntime="60" />
 		<monster name="Turbulent Elemental" x="-3" y="4" z="9" spawntime="60" />
 	</monster>
+	<monster centerx="32416" centery="31079" centerz="9" radius="1">
+		<monster name="Chakoya Tribewarden" x="1" y="-1" z="9" spawntime="90" />
+		<monster name="Chakoya Windcaller" x="-1" y="1" z="9" spawntime="90" />
+	</monster>
+	<monster centerx="32736" centery="31079" centerz="9" radius="2">
+		<monster name="Ghoul" x="1" y="-1" z="9" spawntime="90" />
+	</monster>
+	<monster centerx="32145" centery="31080" centerz="9" radius="3">
+		<monster name="Gargoyle" x="2" y="1" z="9" spawntime="90" />
+	</monster>
+	<monster centerx="33065" centery="31081" centerz="9" radius="1">
+		<monster name="Draken Spellweaver" x="0" y="0" z="9" spawntime="90" />
+	</monster>
 	<monster centerx="33076" centery="31082" centerz="9" radius="1">
 		<monster name="Death Blob" x="0" y="0" z="9" spawntime="90" />
 	</monster>
@@ -75095,6 +75107,15 @@
 	<monster centerx="33082" centery="31083" centerz="9" radius="1">
 		<monster name="Draken Spellweaver" x="0" y="0" z="9" spawntime="90" />
 	</monster>
+	<monster centerx="33921" centery="31083" centerz="9" radius="5">
+		<monster name="Turbulent Elemental" x="-1" y="-4" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="-3" y="-3" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="2" y="-2" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="4" y="0" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="-3" y="1" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="2" y="2" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="0" y="4" z="9" spawntime="60" />
+	</monster>
 	<monster centerx="32359" centery="31084" centerz="9" radius="5">
 		<monster name="Crystal Spider" x="3" y="2" z="9" spawntime="90" />
 	</monster>
@@ -75106,6 +75127,9 @@
 	<monster centerx="33105" centery="31084" centerz="9" radius="1">
 		<monster name="Death Blob" x="0" y="0" z="9" spawntime="90" />
 	</monster>
+	<monster centerx="33889" centery="31084" centerz="9" radius="1">
+		<monster name="Capricious Phantom" x="0" y="1" z="9" spawntime="60" />
+	</monster>
 	<monster centerx="34001" centery="31084" centerz="9" radius="1">
 		<monster name="Infernal Demon" x="0" y="0" z="9" spawntime="60" />
 		<monster name="Brachiodemon" x="1" y="1" z="9" spawntime="60" />
@@ -75141,15 +75165,6 @@
 	<monster centerx="33107" centery="31086" centerz="9" radius="1">
 		<monster name="Draken Abomination" x="0" y="0" z="9" spawntime="90" />
 	</monster>
-	<monster centerx="33925" centery="31086" centerz="9" radius="5">
-		<monster name="Turbulent Elemental" x="-1" y="-4" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="-3" y="-3" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="2" y="-2" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="4" y="0" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="-3" y="1" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="2" y="2" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="0" y="4" z="9" spawntime="60" />
-	</monster>
 	<monster centerx="34033" centery="31086" centerz="9" radius="1">
 		<monster name="Brachiodemon" x="0" y="0" z="9" spawntime="60" />
 	</monster>
@@ -75180,9 +75195,6 @@
 	<monster centerx="33220" centery="31087" centerz="9" radius="1">
 		<monster name="Lancer Beetle" x="0" y="0" z="9" spawntime="90" />
 	</monster>
-	<monster centerx="33890" centery="31087" centerz="9" radius="1">
-		<monster name="Capricious Phantom" x="0" y="0" z="9" spawntime="60" />
-	</monster>
 	<monster centerx="33993" centery="31087" centerz="9" radius="1">
 		<monster name="Brachiodemon" x="0" y="0" z="9" spawntime="60" />
 	</monster>
@@ -75208,6 +75220,15 @@
 		<monster name="Crypt Shambler" x="2" y="-1" z="9" spawntime="90" />
 		<monster name="Ghoul" x="-3" y="4" z="9" spawntime="90" />
 	</monster>
+	<monster centerx="33895" centery="31089" centerz="9" radius="5">
+		<monster name="Turbulent Elemental" x="3" y="-4" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="0" y="-3" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="-3" y="-2" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="2" y="-2" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="-4" y="1" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="2" y="2" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="-1" y="3" z="9" spawntime="60" />
+	</monster>
 	<monster centerx="31954" centery="31090" centerz="9" radius="3">
 		<monster name="Sea Serpent" x="-1" y="0" z="9" spawntime="90" />
 	</monster>
@@ -75285,15 +75306,6 @@
 	<monster centerx="33273" centery="31092" centerz="9" radius="1">
 		<monster name="Ghastly Dragon" x="0" y="0" z="9" spawntime="90" />
 	</monster>
-	<monster centerx="33899" centery="31092" centerz="9" radius="5">
-		<monster name="Turbulent Elemental" x="3" y="-4" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="0" y="-3" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="-3" y="-2" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="2" y="-2" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="-4" y="1" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="2" y="2" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="-1" y="3" z="9" spawntime="60" />
-	</monster>
 	<monster centerx="32441" centery="31093" centerz="9" radius="1">
 		<monster name="Chakoya Tribewarden" x="-1" y="0" z="9" spawntime="90" />
 	</monster>
@@ -75317,6 +75329,15 @@
 	<monster centerx="33085" centery="31093" centerz="9" radius="1">
 		<monster name="Draken Abomination" x="0" y="0" z="9" spawntime="90" />
 	</monster>
+	<monster centerx="33941" centery="31093" centerz="9" radius="5">
+		<monster name="Turbulent Elemental" x="4" y="-4" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="-3" y="-3" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="0" y="-2" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="2" y="-2" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="-2" y="0" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="3" y="3" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="-2" y="4" z="9" spawntime="60" />
+	</monster>
 	<monster centerx="31943" centery="31094" centerz="9" radius="3">
 		<monster name="Sea Serpent" x="0" y="1" z="9" spawntime="90" />
 	</monster>
@@ -75329,6 +75350,14 @@
 	<monster centerx="33054" centery="31095" centerz="9" radius="1">
 		<monster name="Draken Warmaster" x="0" y="0" z="9" spawntime="90" />
 	</monster>
+	<monster centerx="33908" centery="31095" centerz="9" radius="5">
+		<monster name="Turbulent Elemental" x="4" y="-4" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="1" y="-3" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="-3" y="-2" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="-1" y="1" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="4" y="1" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="-1" y="4" z="9" spawntime="60" />
+	</monster>
 	<monster centerx="34003" centery="31095" centerz="9" radius="2">
 		<monster name="Brachiodemon" x="2" y="-2" z="9" spawntime="60" />
 		<monster name="Infernal Phantom" x="0" y="0" z="9" spawntime="60" />
@@ -75349,15 +75378,6 @@
 	<monster centerx="33230" centery="31096" centerz="9" radius="1">
 		<monster name="Wailing Widow" x="0" y="0" z="9" spawntime="90" />
 	</monster>
-	<monster centerx="33945" centery="31096" centerz="9" radius="5">
-		<monster name="Turbulent Elemental" x="4" y="-4" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="-3" y="-3" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="0" y="-2" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="2" y="-2" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="-2" y="0" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="3" y="3" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="-2" y="4" z="9" spawntime="60" />
-	</monster>
 	<monster centerx="34000" centery="31096" centerz="9" radius="1">
 		<monster name="Infernal Demon" x="0" y="0" z="9" spawntime="60" />
 	</monster>
@@ -75407,13 +75427,8 @@
 		<monster name="Chakoya Tribewarden" x="1" y="0" z="9" spawntime="90" />
 		<monster name="Chakoya Toolshaper" x="-1" y="2" z="9" spawntime="90" />
 	</monster>
-	<monster centerx="33912" centery="31098" centerz="9" radius="5">
-		<monster name="Turbulent Elemental" x="4" y="-4" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="1" y="-3" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="-3" y="-2" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="-1" y="1" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="4" y="1" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="-1" y="4" z="9" spawntime="60" />
+	<monster centerx="33890" centery="31098" centerz="9" radius="1">
+		<monster name="Bony Sea Devil" x="0" y="1" z="9" spawntime="60" />
 	</monster>
 	<monster centerx="31901" centery="31099" centerz="9" radius="5">
 		<monster name="Sea Serpent" x="1" y="-4" z="9" spawntime="90" />
@@ -75442,6 +75457,16 @@
 	<monster centerx="33070" centery="31100" centerz="9" radius="1">
 		<monster name="Draken Elite" x="0" y="0" z="9" spawntime="90" />
 	</monster>
+	<monster centerx="33922" centery="31100" centerz="9" radius="5">
+		<monster name="Capricious Phantom" x="-2" y="-3" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="2" y="-3" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="-4" y="-2" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="3" y="0" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="-2" y="2" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="3" y="3" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="-1" y="4" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="1" y="4" z="9" spawntime="60" />
+	</monster>
 	<monster centerx="32107" centery="31101" centerz="9" radius="3">
 		<monster name="Frost Troll" x="-3" y="-2" z="9" spawntime="90" />
 		<monster name="Frost Troll" x="3" y="-2" z="9" spawntime="90" />
@@ -75479,25 +75504,12 @@
 	<monster centerx="33263" centery="31102" centerz="9" radius="1">
 		<monster name="Ghastly Dragon" x="0" y="0" z="9" spawntime="90" />
 	</monster>
-	<monster centerx="33893" centery="31102" centerz="9" radius="1">
-		<monster name="Bony Sea Devil" x="0" y="-1" z="9" spawntime="60" />
-	</monster>
 	<monster centerx="31957" centery="31103" centerz="9" radius="3">
 		<monster name="Sea Serpent" x="-1" y="-1" z="9" spawntime="90" />
 	</monster>
 	<monster centerx="33103" centery="31103" centerz="9" radius="1">
 		<monster name="Draken Abomination" x="0" y="0" z="9" spawntime="90" />
 	</monster>
-	<monster centerx="33926" centery="31103" centerz="9" radius="5">
-		<monster name="Capricious Phantom" x="-2" y="-3" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="2" y="-3" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="-4" y="-2" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="3" y="0" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="-2" y="2" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="3" y="3" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="-1" y="4" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="1" y="4" z="9" spawntime="60" />
-	</monster>
 	<monster centerx="31947" centery="31104" centerz="9" radius="3">
 		<monster name="Sea Serpent" x="-2" y="1" z="9" spawntime="90" />
 	</monster>
@@ -75584,6 +75596,15 @@
 	<monster centerx="33102" centery="31109" centerz="9" radius="1">
 		<monster name="Draken Abomination" x="0" y="0" z="9" spawntime="90" />
 	</monster>
+	<monster centerx="33897" centery="31109" centerz="9" radius="5">
+		<monster name="Bony Sea Devil" x="-4" y="-3" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="0" y="-3" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="4" y="-3" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="2" y="0" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="-3" y="4" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="-1" y="4" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="3" y="5" z="9" spawntime="60" />
+	</monster>
 	<monster centerx="32503" centery="31110" centerz="9" radius="1">
 		<monster name="Chakoya Toolshaper" x="-1" y="1" z="9" spawntime="90" />
 	</monster>
@@ -75621,15 +75642,6 @@
 		<monster name="Chakoya Toolshaper" x="1" y="0" z="9" spawntime="90" />
 		<monster name="Chakoya Windcaller" x="-1" y="2" z="9" spawntime="90" />
 	</monster>
-	<monster centerx="33901" centery="31112" centerz="9" radius="5">
-		<monster name="Bony Sea Devil" x="-4" y="-3" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="0" y="-3" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="4" y="-3" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="2" y="0" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="-3" y="4" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="-1" y="4" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="3" y="5" z="9" spawntime="60" />
-	</monster>
 	<monster centerx="33054" centery="31113" centerz="9" radius="1">
 		<monster name="Draken Warmaster" x="0" y="0" z="9" spawntime="90" />
 	</monster>
@@ -75654,6 +75666,16 @@
 	<monster centerx="33408" centery="31114" centerz="9" radius="1">
 		<monster name="Lizard High Guard" x="0" y="0" z="9" spawntime="60" />
 	</monster>
+	<monster centerx="33926" centery="31114" centerz="9" radius="5">
+		<monster name="Turbulent Elemental" x="0" y="-4" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="-3" y="-2" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="1" y="-2" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="3" y="-2" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="-2" y="0" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="4" y="2" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="-2" y="3" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="1" y="3" z="9" spawntime="60" />
+	</monster>
 	<monster centerx="31932" centery="31115" centerz="9" radius="3">
 		<monster name="Sea Serpent" x="-2" y="0" z="9" spawntime="90" />
 	</monster>
@@ -75706,15 +75728,13 @@
 	<monster centerx="33395" centery="31117" centerz="9" radius="1">
 		<monster name="Lizard Chosen" x="0" y="0" z="9" spawntime="60" />
 	</monster>
-	<monster centerx="33930" centery="31117" centerz="9" radius="5">
-		<monster name="Turbulent Elemental" x="0" y="-4" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="-3" y="-2" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="1" y="-2" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="3" y="-2" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="-2" y="0" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="4" y="2" z="9" spawntime="60" />
+	<monster centerx="33893" centery="31117" centerz="9" radius="5">
+		<monster name="Turbulent Elemental" x="-4" y="-3" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="-4" y="0" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="1" y="1" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="-4" y="2" z="9" spawntime="60" />
 		<monster name="Turbulent Elemental" x="-2" y="3" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="1" y="3" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="-4" y="4" z="9" spawntime="60" />
 	</monster>
 	<monster centerx="31979" centery="31118" centerz="9" radius="3">
 		<monster name="Hellspawn" x="0" y="1" z="9" spawntime="90" />
@@ -75769,13 +75789,13 @@
 	<monster centerx="33272" centery="31120" centerz="9" radius="1">
 		<monster name="Lizard Chosen" x="0" y="0" z="9" spawntime="90" />
 	</monster>
-	<monster centerx="33891" centery="31120" centerz="9" radius="5">
-		<monster name="Turbulent Elemental" x="2" y="-3" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="2" y="0" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="0" y="2" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="2" y="2" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="-1" y="4" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="2" y="4" z="9" spawntime="60" />
+	<monster centerx="33904" centery="31120" centerz="9" radius="5">
+		<monster name="Capricious Phantom" x="-1" y="-4" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="3" y="-4" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="0" y="-1" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="2" y="-1" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="-3" y="1" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="0" y="3" z="9" spawntime="60" />
 	</monster>
 	<monster centerx="32049" centery="31121" centerz="9" radius="3">
 		<monster name="Novice Of The Cult" x="2" y="-2" z="9" spawntime="90" />
@@ -75852,13 +75872,15 @@
 	<monster centerx="33381" centery="31122" centerz="9" radius="1">
 		<monster name="Lizard Legionnaire" x="0" y="0" z="9" spawntime="60" />
 	</monster>
-	<monster centerx="33908" centery="31123" centerz="9" radius="5">
-		<monster name="Capricious Phantom" x="-1" y="-4" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="3" y="-4" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="0" y="-1" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="2" y="-1" z="9" spawntime="60" />
+	<monster centerx="33941" centery="31123" centerz="9" radius="5">
+		<monster name="Capricious Phantom" x="0" y="-3" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="2" y="-3" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="-3" y="-2" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="3" y="-1" z="9" spawntime="60" />
 		<monster name="Turbulent Elemental" x="-3" y="1" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="0" y="3" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="3" y="1" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="0" y="4" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="3" y="4" z="9" spawntime="60" />
 	</monster>
 	<monster centerx="31939" centery="31124" centerz="9" radius="3">
 		<monster name="Sea Serpent" x="2" y="-1" z="9" spawntime="90" />
@@ -75902,6 +75924,16 @@
 	<monster centerx="33277" centery="31125" centerz="9" radius="1">
 		<monster name="Lizard Chosen" x="0" y="0" z="9" spawntime="90" />
 	</monster>
+	<monster centerx="33916" centery="31125" centerz="9" radius="5">
+		<monster name="Turbulent Elemental" x="-4" y="-3" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="0" y="-3" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="1" y="-2" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="5" y="0" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="-1" y="1" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="3" y="3" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="-4" y="4" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="1" y="4" z="9" spawntime="60" />
+	</monster>
 	<monster centerx="33285" centery="31126" centerz="9" radius="1">
 		<monster name="Lizard Chosen" x="0" y="0" z="9" spawntime="90" />
 	</monster>
@@ -75911,16 +75943,6 @@
 	<monster centerx="33365" centery="31126" centerz="9" radius="1">
 		<monster name="Mutated Tiger" x="0" y="0" z="9" spawntime="60" />
 	</monster>
-	<monster centerx="33945" centery="31126" centerz="9" radius="5">
-		<monster name="Capricious Phantom" x="0" y="-3" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="2" y="-3" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="-3" y="-2" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="3" y="-1" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="-3" y="0" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="3" y="1" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="0" y="4" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="3" y="4" z="9" spawntime="60" />
-	</monster>
 	<monster centerx="31912" centery="31127" centerz="9" radius="3">
 		<monster name="Sea Serpent" x="0" y="1" z="9" spawntime="90" />
 	</monster>
@@ -75951,15 +75973,13 @@
 	<monster centerx="33298" centery="31128" centerz="9" radius="1">
 		<monster name="Lizard Chosen" x="0" y="0" z="9" spawntime="90" />
 	</monster>
-	<monster centerx="33920" centery="31128" centerz="9" radius="5">
-		<monster name="Turbulent Elemental" x="-3" y="-3" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="0" y="-3" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="1" y="-2" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="-3" y="0" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="5" y="0" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="3" y="3" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="-4" y="4" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="1" y="4" z="9" spawntime="60" />
+	<monster centerx="33896" centery="31128" centerz="9" radius="5">
+		<monster name="Turbulent Elemental" x="-4" y="-2" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="-2" y="-1" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="-1" y="-1" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="-1" y="1" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="4" y="1" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="-4" y="2" z="9" spawntime="60" />
 	</monster>
 	<monster centerx="32477" centery="31129" centerz="9" radius="1">
 		<monster name="Chakoya Toolshaper" x="1" y="-1" z="9" spawntime="90" />
@@ -75996,14 +76016,6 @@
 	<monster centerx="33361" centery="31130" centerz="9" radius="1">
 		<monster name="Mutated Bat" x="0" y="0" z="9" spawntime="60" />
 	</monster>
-	<monster centerx="33900" centery="31131" centerz="9" radius="5">
-		<monster name="Turbulent Elemental" x="-4" y="-2" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="-2" y="-1" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="-1" y="-1" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="-1" y="1" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="4" y="1" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="-4" y="2" z="9" spawntime="60" />
-	</monster>
 	<monster centerx="31921" centery="31132" centerz="9" radius="3">
 		<monster name="Sea Serpent" x="3" y="1" z="9" spawntime="90" />
 	</monster>
@@ -162037,6 +162049,9 @@
 	<monster centerx="32505" centery="31594" centerz="14" radius="3">
 		<monster name="Warlock" x="0" y="-1" z="14" spawntime="90" />
 	</monster>
+	<monster centerx="33744" centery="31595" centerz="14" radius="1">
+		<monster name="Dreadful Harvester" x="0" y="0" z="14" spawntime="14" />
+	</monster>
 	<monster centerx="33349" centery="31596" centerz="14" radius="7">
 		<monster name="Dark Torturer" x="0" y="-7" z="14" spawntime="90" />
 		<monster name="Betrayed Wraith" x="5" y="-5" z="14" spawntime="90" />
@@ -162063,6 +162078,9 @@
 		<monster name="Dark Torturer" x="4" y="5" z="14" spawntime="90" />
 		<monster name="Lost Soul" x="0" y="6" z="14" spawntime="90" />
 	</monster>
+	<monster centerx="33743" centery="31597" centerz="14" radius="1">
+		<monster name="Hateful Soul" x="0" y="0" z="14" spawntime="14" />
+	</monster>
 	<monster centerx="32805" centery="31598" centerz="14" radius="1">
 		<monster name="Skeleton" x="1" y="0" z="14" spawntime="90" />
 	</monster>
@@ -162072,6 +162090,12 @@
 	<monster centerx="33161" centery="31598" centerz="14" radius="1">
 		<monster name="Dark Magician" x="0" y="1" z="14" spawntime="90" />
 	</monster>
+	<monster centerx="33738" centery="31599" centerz="14" radius="1">
+		<monster name="Symbol of Hatred" x="0" y="0" z="14" spawntime="14" />
+	</monster>
+	<monster centerx="33748" centery="31599" centerz="14" radius="1">
+		<monster name="Symbol of Hatred" x="0" y="0" z="14" spawntime="14" />
+	</monster>
 	<monster centerx="32808" centery="31600" centerz="14" radius="1">
 		<monster name="Ghoul" x="1" y="0" z="14" spawntime="90" />
 	</monster>
@@ -162119,6 +162143,9 @@
 		<monster name="Fire Elemental" x="0" y="4" z="14" spawntime="90" />
 		<monster name="Fire Elemental" x="4" y="4" z="14" spawntime="90" />
 	</monster>
+	<monster centerx="33743" centery="31603" centerz="14" radius="1">
+		<monster name="Hateful Soul" x="0" y="0" z="14" spawntime="14" />
+	</monster>
 	<monster centerx="33137" centery="31604" centerz="14" radius="1">
 		<monster name="Monk" x="0" y="-1" z="14" spawntime="90" />
 	</monster>
@@ -162201,6 +162228,9 @@
 	<monster centerx="33138" centery="31630" centerz="14" radius="1">
 		<monster name="Monk" x="-1" y="0" z="14" spawntime="90" />
 	</monster>
+	<monster centerx="33710" centery="31630" centerz="14" radius="1">
+		<monster name="Dreadful Harvester" x="0" y="0" z="14" spawntime="20" />
+	</monster>
 	<monster centerx="32795" centery="31631" centerz="14" radius="1">
 		<monster name="Ghoul" x="1" y="0" z="14" spawntime="90" />
 	</monster>
@@ -162214,6 +162244,12 @@
 		<monster name="Skeleton" x="1" y="0" z="14" spawntime="90" />
 		<monster name="Skeleton" x="1" y="1" z="14" spawntime="90" />
 	</monster>
+	<monster centerx="33738" centery="31633" centerz="14" radius="1">
+		<monster name="Weeping Soul" x="0" y="0" z="14" spawntime="60" />
+	</monster>
+	<monster centerx="33747" centery="31633" centerz="14" radius="1">
+		<monster name="Weeping Soul" x="0" y="0" z="14" spawntime="60" />
+	</monster>
 	<monster centerx="32781" centery="31634" centerz="14" radius="1">
 		<monster name="Ghoul" x="1" y="0" z="14" spawntime="90" />
 	</monster>
@@ -162221,6 +162257,15 @@
 		<monster name="Demon Skeleton" x="-1" y="1" z="14" spawntime="90" />
 		<monster name="Skeleton" x="1" y="1" z="14" spawntime="90" />
 	</monster>
+	<monster centerx="33703" centery="31634" centerz="14" radius="1">
+		<monster name="Necromantic Focus" x="0" y="0" z="14" spawntime="20" />
+	</monster>
+	<monster centerx="33710" centery="31634" centerz="14" radius="1">
+		<monster name="Lesser Splinter of Madness" x="0" y="0" z="14" spawntime="20" />
+	</monster>
+	<monster centerx="33717" centery="31634" centerz="14" radius="1">
+		<monster name="Necromantic Focus" x="0" y="0" z="14" spawntime="20" />
+	</monster>
 	<monster centerx="32792" centery="31635" centerz="14" radius="1">
 		<monster name="Ghoul" x="1" y="0" z="14" spawntime="90" />
 	</monster>
diff --git a/data-otservbr-global/world/otservbr-npc.xml b/data-otservbr-global/world/otservbr-npc.xml
index 10772902341..8a2e5ebb3e9 100644
--- a/data-otservbr-global/world/otservbr-npc.xml
+++ b/data-otservbr-global/world/otservbr-npc.xml
@@ -2451,6 +2451,9 @@
 	<npc centerx="33239" centery="31224" centerz="10" radius="1">
 		<npc name="A Sleeping Dragon" x="0" y="0" z="10" spawntime="60" />
 	</npc>
+	<npc centerx="33621" centery="31419" centerz="10" radius="2">
+		<npc name="Flickering Soul" x="0" y="0" z="10" spawntime="60" />
+	</npc>
 	<npc centerx="32533" centery="31437" centerz="10" radius="1">
 		<npc name="Bolfona" x="0" y="0" z="10" spawntime="60" />
 	</npc>
diff --git a/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-empty-zones.xml b/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-empty-zones.xml
new file mode 100644
index 00000000000..a9224bd3c2d
--- /dev/null
+++ b/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-empty-zones.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0"?>
+<zones />
diff --git a/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-empty.otbm b/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-empty.otbm
new file mode 100644
index 0000000000000000000000000000000000000000..7892efac0906d82faaa89ea3905180de70e1abcc
GIT binary patch
literal 129535
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

literal 0
HcmV?d00001

diff --git a/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-inundate-zones.xml b/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-inundate-zones.xml
new file mode 100644
index 00000000000..a9224bd3c2d
--- /dev/null
+++ b/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-inundate-zones.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0"?>
+<zones />
diff --git a/data-otservbr-global/world/quest/soul_war/ebb_and_flow/inundate.otbm b/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-inundate.otbm
similarity index 83%
rename from data-otservbr-global/world/quest/soul_war/ebb_and_flow/inundate.otbm
rename to data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-inundate.otbm
index 1790545b34b30062748ce1249d4e00616b248c67..98992c326dd4532fb48d78bcc3c2c083cff1266e 100644
GIT binary patch
delta 4311
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
TF3bw`aBG&nJ6`)8jLQE3nPRaX

delta 7138
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
bJN?_+>RHcCyNZbpu*TTzul~@yYCQ3O<%8Ru

diff --git a/data-otservbr-global/world/quest/soul_war/ebb_and_flow/empty.otbm b/data-otservbr-global/world/quest/soul_war/ebb_and_flow/empty.otbm
deleted file mode 100644
index 70036d063b14a9694c6166b1bd317cf887aeb285..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 13957
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
HU=#R%=4!6#

diff --git a/data/items/items.xml b/data/items/items.xml
index 765c6e9db51..c4ba2b3a93b 100644
--- a/data/items/items.xml
+++ b/data/items/items.xml
@@ -62027,9 +62027,7 @@ hands of its owner. Granted by TibiaRoyal.com"/>
 	<item id="32767" article="a" name="unknown">
 		<attribute key="weight" value="500"/>
 	</item>
-	<item id="32768" article="a" name="unknown">
-		<attribute key="weight" value="500"/>
-	</item>
+	<item id="32768" article="a" name="sandtimer"/>
 	<item id="32769" article="a" name="white gem">
 		<attribute key="primarytype" value="valuables"/>
 		<attribute key="showCount" value="1"/>
@@ -62471,6 +62469,7 @@ hands of its owner. Granted by TibiaRoyal.com"/>
 		<attribute key="type" value="teleport"/>
 		<attribute key="effect" value="teleport"/>
 	</item>
+	<item fromid="33018" toid="33025" name="shrine" editorsuffix="(soul war quest)"/>
 	<item fromid="33026" toid="33027" name="heart lamp">
 		<attribute key="primarytype" value="light sources"/>
 		<attribute key="wrapableto" value="23398"/>
@@ -62893,21 +62892,15 @@ hands of its owner. Granted by TibiaRoyal.com"/>
 	</item>
 	<item id="33785" article="a" name="broken mirror"/>
 	<item fromid="33788" toid="33789" article="a" name="wall"/>
-	<item id="33790" article="a" name="large crystal teleporter">
-		<attribute key="primarytype" value="teleporters"/>
-		<attribute key="type" value="teleport"/>
-		<attribute key="effect" value="teleport"/>
-	</item>
-	<item id="33791" article="a" name="water vortex">
-		<attribute key="primarytype" value="teleporters"/>
-	</item>
-	<item id="33792" article="a" name="sulphur puddle">
-		<attribute key="primarytype" value="fields"/>
-		<attribute key="weight" value="60"/>
+	<item id="33790" article="a" name="inactive vortex">
+		<attribute key="duration" value="10"/>
+		<attribute key="decayTo" value="33791"/>
 	</item>
+	<item id="33791" article="a" name="active spirit vortex"/>
+	<item id="33792" article="a" name="condensed remorse"/>
 	<item id="33793" article="a" name="sorrow">
 		<attribute key="primarytype" value="quest items"/>
-		<attribute key="weight" value="60"/>
+		<attribute key="weight" value="50"/>
 	</item>
 	<item id="33794" article="a" name="dead bony sea devil">
 		<attribute key="duration" value="600"/>
@@ -63061,6 +63054,10 @@ hands of its owner. Granted by TibiaRoyal.com"/>
 		<attribute key="decayTo" value="33824"/>
 		<attribute key="containersize" value="48"/>
 	</item>
+	<item id="33854" article="the" name="blood of cloak of Terror">
+		<attribute key="duration" value="600"/>
+		<attribute key="decayTo" value="34006"/>
+	</item>
 	<item id="33856" article="a" name="dead goshnar's cruelty">
 		<attribute key="duration" value="600"/>
 		<attribute key="decayTo" value="0"/>
@@ -63156,6 +63153,11 @@ hands of its owner. Granted by TibiaRoyal.com"/>
 		<attribute key="decayTo" value="33874"/>
 		<attribute key="containersize" value="48"/>
 	</item>
+	<item id="33876" article="a" name="dead weeping soul">
+		<attribute key="duration" value="300"/>
+		<attribute key="decayTo" value="0"/>
+	</item>
+	<item id="33877" article="a" name="searing fire"/>
 	<item id="33886" article="a" name="dead goshnars megalomania">
 		<attribute key="duration" value="600"/>
 		<attribute key="decayTo" value="0"/>
@@ -63175,6 +63177,7 @@ hands of its owner. Granted by TibiaRoyal.com"/>
 		<attribute key="decayTo" value="33888"/>
 		<attribute key="containersize" value="48"/>
 	</item>
+	<item id="33890" article="a" name="greedy maw"/>
 	<item id="33891" article="a" name="some mortal essence"/>
 	<item id="33892" name="love elixir">
 		<attribute key="primarytype" value="fansite items"/>
@@ -63374,6 +63377,10 @@ hands of its owner. Granted by TibiaRoyal.com"/>
 		<attribute key="description" value="A goblin zombie is stuffed into it"/>
 		<attribute key="weight" value="5500"/>
 	</item>
+	<item id="33949" name="dead aspect of power">
+		<attribute key="duration" value="300"/>
+		<attribute key="decayTo" value="0"/>
+	</item>
 	<item id="33950" name="cleansed sanity">
 		<attribute key="description" value="Can be used to douse Goshnar's madness"/>
 		<attribute key="weight" value="101"/>
@@ -63520,6 +63527,19 @@ hands of its owner. Granted by TibiaRoyal.com"/>
 	<item id="33982" name="crawler's essence" plural="crawler's essences">
 		<attribute key="weight" value="45"/>
 	</item>
+	<item id="33984" article="a" name="necromantic remains">
+		<attribute key="duration" value="300"/>
+		<attribute key="decayTo" value="0"/>
+	</item>
+	<item id="34005" name="pulsating energy"/>
+	<item id="34006" article="the" name="blood of cloak of Terror">
+		<attribute key="duration" value="300"/>
+		<attribute key="decayTo" value="34007"/>
+	</item>
+	<item id="34007" article="the" name="blood of cloak of Terror">
+		<attribute key="duration" value="300"/>
+		<attribute key="decayTo" value="0"/>
+	</item>
 	<item id="34008" name="white silk flower">
 		<attribute key="primarytype" value="plants and herbs"/>
 		<attribute key="description" value="The petals are made of silk, the buds and pistil of white pearls. The werelions of the Darama Desert often use such flowers as love pledges"/>
@@ -64257,7 +64277,7 @@ hands of its owner. Granted by TibiaRoyal.com"/>
 	<item id="34109" article="a" name="bag you desire">
 		<attribute key="primarytype" value="valuables"/>
 		<attribute key="description" value="It contains the most powerful artifacts from the depths of Zarganash's darkest realms"/>
-		<attribute key="weight" value="30"/>
+		<attribute key="weight" value="1500"/>
 	</item>
 	<item id="34110" article="a" name="sandstone statue">
 		<attribute key="primarytype" value="statues"/>
diff --git a/data/libs/functions/bosslever.lua b/data/libs/functions/bosslever.lua
index 3792cdf629d..5834b4a9a5e 100644
--- a/data/libs/functions/bosslever.lua
+++ b/data/libs/functions/bosslever.lua
@@ -144,6 +144,7 @@ end
 ---@param player Player
 ---@return boolean
 function BossLever:onUse(player)
+	local monsterName = MonsterType(self.name):getName()
 	local isParticipant = false
 	for _, v in ipairs(self.playerPositions) do
 		if Position(v.pos) == player:getPosition() then
@@ -161,7 +162,7 @@ function BossLever:onUse(player)
 
 	local zone = self:getZone()
 	if zone:countPlayers(IgnoredByMonsters) > 0 then
-		player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "There's already someone fighting with " .. self.name .. ".")
+		player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "There's already someone fighting with " .. monsterName .. ".")
 		return true
 	end
 
@@ -178,13 +179,13 @@ function BossLever:onUse(player)
 			return false
 		end
 
-		if self:lastEncounterTime(creature) > os.time() then
+		if creature:getGroup():getId() < GROUP_TYPE_GOD and self:lastEncounterTime(creature) > os.time() then
 			local info = lever:getInfoPositions()
 			for _, v in pairs(info) do
 				local newPlayer = v.creature
 				if newPlayer then
 					local timeLeft = self:lastEncounterTime(newPlayer) - os.time()
-					newPlayer:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You or a member in your team have to wait " .. getTimeInWords(timeLeft) .. " to face " .. self.name .. " again!")
+					newPlayer:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You or a member in your team have to wait " .. getTimeInWords(timeLeft) .. " to face " .. monsterName .. " again!")
 					if self:lastEncounterTime(newPlayer) > os.time() then
 						newPlayer:getPosition():sendMagicEffect(CONST_ME_POFF)
 					end
diff --git a/data/libs/functions/creature.lua b/data/libs/functions/creature.lua
index be95a45144c..376f828c5b0 100644
--- a/data/libs/functions/creature.lua
+++ b/data/libs/functions/creature.lua
@@ -208,7 +208,7 @@ end
 function Creature.getKillers(self, onlyPlayers)
 	local killers = {}
 	local inFightTicks = configManager.getNumber(configKeys.PZ_LOCKED)
-	local timeNow = os.mtime()
+	local timeNow = systemTime()
 	local getCreature = onlyPlayers and Player or Creature
 	for cid, cb in pairs(self:getDamageMap()) do
 		local creature = getCreature(cid)
diff --git a/data/libs/functions/revscriptsys.lua b/data/libs/functions/revscriptsys.lua
index 84b8275e3ce..b7f41b55298 100644
--- a/data/libs/functions/revscriptsys.lua
+++ b/data/libs/functions/revscriptsys.lua
@@ -286,6 +286,14 @@ do
 			self:eventType(MONSTERS_EVENT_SAY)
 			self:onSay(value)
 			return
+		elseif key == "onPlayerAttack" then
+			self:eventType(MONSTERS_EVENT_ATTACKED_BY_PLAYER)
+			self:onPlayerAttack(value)
+			return
+		elseif key == "onSpawn" then
+			self:eventType(MONSTERS_EVENT_ON_SPAWN)
+			self:onSpawn(value)
+			return
 		end
 		rawset(self, key, value)
 	end
diff --git a/data/libs/systems/zones.lua b/data/libs/systems/zones.lua
index ff37af5b16a..1406242517a 100644
--- a/data/libs/systems/zones.lua
+++ b/data/libs/systems/zones.lua
@@ -100,7 +100,7 @@ setmetatable(ZoneEvent, {
 
 function ZoneEvent:register()
 	if self.beforeEnter then
-		local beforeEnter = EventCallback()
+		local beforeEnter = EventCallback("ZoneEventBeforeEnter", true)
 		function beforeEnter.zoneBeforeCreatureEnter(zone, creature)
 			if zone ~= self.zone then
 				return true
@@ -112,7 +112,7 @@ function ZoneEvent:register()
 	end
 
 	if self.beforeLeave then
-		local beforeLeave = EventCallback()
+		local beforeLeave = EventCallback("ZoneEventBeforeLeave", true)
 		function beforeLeave.zoneBeforeCreatureLeave(zone, creature)
 			if zone ~= self.zone then
 				return true
@@ -124,7 +124,7 @@ function ZoneEvent:register()
 	end
 
 	if self.afterEnter then
-		local afterEnter = EventCallback()
+		local afterEnter = EventCallback("ZoneEventAfterEnter", true)
 		function afterEnter.zoneAfterCreatureEnter(zone, creature)
 			if zone ~= self.zone then
 				return true
@@ -136,7 +136,7 @@ function ZoneEvent:register()
 	end
 
 	if self.afterLeave then
-		local afterLeave = EventCallback()
+		local afterLeave = EventCallback("ZoneEventAfterLeave", true)
 		function afterLeave.zoneAfterCreatureLeave(zone, creature)
 			if zone ~= self.zone then
 				return true
@@ -148,7 +148,7 @@ function ZoneEvent:register()
 	end
 
 	if self.onSpawn then
-		local afterEnter = EventCallback()
+		local afterEnter = EventCallback("ZoneEventAfterEnter", true)
 		function afterEnter.zoneAfterCreatureEnter(zone, creature)
 			if zone ~= self.zone then
 				return true
diff --git a/data/scripts/actions/items/cobra_flask.lua b/data/scripts/actions/items/cobra_flask.lua
index ddeecf8ec4f..410e4f1af43 100644
--- a/data/scripts/actions/items/cobra_flask.lua
+++ b/data/scripts/actions/items/cobra_flask.lua
@@ -1,4 +1,4 @@
-local applyCobraFlaskEffectOnMonsterSpawn = EventCallback()
+local applyCobraFlaskEffectOnMonsterSpawn = EventCallback("CobraFlaskEffectOnMonsterSpawn")
 
 applyCobraFlaskEffectOnMonsterSpawn.monsterOnSpawn = function(monster, position)
 	if table.contains({ "cobra scout", "cobra vizier", "cobra assassin" }, monster:getName():lower()) then
diff --git a/data/scripts/eventcallbacks/README.md b/data/scripts/eventcallbacks/README.md
index bdafcb41b33..4b0ea40bc31 100644
--- a/data/scripts/eventcallbacks/README.md
+++ b/data/scripts/eventcallbacks/README.md
@@ -18,6 +18,7 @@ Event callbacks are available for several categories of game entities, such as `
 - `(bool)` `creatureOnTargetCombat`
 - `(void)` `creatureOnHear`
 - `(void)` `creatureOnDrainHealth`
+- `(void)` `creatureOnCombat`
 - `(bool)` `partyOnJoin`
 - `(bool)` `partyOnLeave`
 - `(bool)` `partyOnDisband`
@@ -61,7 +62,7 @@ Below are examples for each category of game entities:
 ### Creature Callback
 
 ```lua
-local callback = EventCallback()
+local callback = EventCallback("UniqueCallbackName")
 
 function callback.creatureOnAreaCombat(creature, tile, isAggressive)
 	-- custom behavior when a creature enters combat area
@@ -74,7 +75,7 @@ callback:register()
 ### Player Callback
 
 ```lua
-local callback = EventCallback()
+local callback = EventCallback("UniqueCallbackName")
 
 function callback.playerOnLook(player, position, thing, stackpos, lookDistance)
 	-- custom behavior when a player looks at something
@@ -86,7 +87,7 @@ callback:register()
 ### Party Callback
 
 ```lua
-local callback = EventCallback()
+local callback = EventCallback("UniqueCallbackName")
 
 function callback.partyOnJoin(party, player)
 	-- custom behavior when a player joins a party
@@ -98,7 +99,7 @@ callback:register()
 ### Monster Callback
 
 ```lua
-local callback = EventCallback()
+local callback = EventCallback("UniqueCallbackName")
 
 function callback.monsterOnSpawn(monster, position)
 	-- custom behavior when a monster spawns
@@ -110,7 +111,7 @@ callback:register()
 ### Npc Callback
 
 ```lua
-local callback = EventCallback()
+local callback = EventCallback("UniqueCallbackName")
 
 function callback.npcOnSpawn(npc, position)
 	-- custom behavior when a npc spawns
@@ -128,7 +129,7 @@ If the callback returns `false`, the execution of the associated function on the
 Here is an example of a boolean event callback:
 
 ```lua
-local callback = EventCallback()
+local callback = EventCallback("UniqueCallbackName")
 
 function callback.creatureOnAreaCombat(creature, tile, isAggressive)
 	-- if the creature is not aggressive, stop the execution of the C++ function
@@ -156,7 +157,7 @@ Here is an example of defining multiple callbacks for the creatureOnAreaCombat e
 #### Example 1
 
 ```lua
-local example1 = EventCallback()
+local example1 = EventCallback("UniqueCallbackName")
 
 function example1.creatureOnAreaCombat(creature, tile, isAggressive)
 	-- custom behavior 1 when a creature enters combat area
@@ -168,7 +169,7 @@ example1:register()
 #### Example 2
 
 ```lua
-local example2 = EventCallback()
+local example2 = EventCallback("UniqueCallbackName")
 
 function example2.creatureOnAreaCombat(creature, tile, isAggressive)
 	-- custom behavior 2 when a creature enters combat area
diff --git a/data/scripts/eventcallbacks/creature/on_area_combat.lua b/data/scripts/eventcallbacks/creature/on_area_combat.lua
index a6295074df3..7653dc1b095 100644
--- a/data/scripts/eventcallbacks/creature/on_area_combat.lua
+++ b/data/scripts/eventcallbacks/creature/on_area_combat.lua
@@ -1,4 +1,4 @@
-local callback = EventCallback()
+local callback = EventCallback("CreatureOnAreaCombatBaseEvent")
 
 function callback.creatureOnAreaCombat(creature, tile, isAggressive)
 	return true
diff --git a/data/scripts/eventcallbacks/creature/on_hear.lua b/data/scripts/eventcallbacks/creature/on_hear.lua
index 871f6456c9a..2954c81c8fb 100644
--- a/data/scripts/eventcallbacks/creature/on_hear.lua
+++ b/data/scripts/eventcallbacks/creature/on_hear.lua
@@ -1,4 +1,4 @@
-local callback = EventCallback()
+local callback = EventCallback("CreatureOnHearBaseEvent")
 
 function callback.creatureOnHear(creature, speaker, words, type) end
 
diff --git a/data/scripts/eventcallbacks/monster/on_spawn.lua b/data/scripts/eventcallbacks/monster/on_spawn.lua
index e40778aafce..5a490a8edac 100644
--- a/data/scripts/eventcallbacks/monster/on_spawn.lua
+++ b/data/scripts/eventcallbacks/monster/on_spawn.lua
@@ -1,4 +1,4 @@
-local callback = EventCallback()
+local callback = EventCallback("MonsterOnSpawnBase")
 
 function callback.monsterOnSpawn(monster, position)
 	if not monster then
diff --git a/data/scripts/eventcallbacks/monster/ondroploot__base.lua b/data/scripts/eventcallbacks/monster/ondroploot__base.lua
index cb7bc4207e8..900259d4fef 100644
--- a/data/scripts/eventcallbacks/monster/ondroploot__base.lua
+++ b/data/scripts/eventcallbacks/monster/ondroploot__base.lua
@@ -1,4 +1,4 @@
-local callback = EventCallback()
+local callback = EventCallback("MonsterOnDropLootBaseEvent")
 
 function Player:canReceiveLoot()
 	return self:getStamina() > 840
@@ -15,7 +15,7 @@ function callback.monsterOnDropLoot(monster, corpse)
 	end
 	local mType = monster:getType()
 	if not mType then
-		logger.warning("monsterOnDropLoot: monster has no type")
+		logger.warn("monsterOnDropLoot: monster '{}' has no type", monster:getName())
 		return
 	end
 
diff --git a/data/scripts/eventcallbacks/monster/ondroploot_boosted.lua b/data/scripts/eventcallbacks/monster/ondroploot_boosted.lua
index 1d94033a572..507df354ab7 100644
--- a/data/scripts/eventcallbacks/monster/ondroploot_boosted.lua
+++ b/data/scripts/eventcallbacks/monster/ondroploot_boosted.lua
@@ -1,4 +1,4 @@
-local callback = EventCallback()
+local callback = EventCallback("MonsterOnDropLootBoosted")
 
 function callback.monsterOnDropLoot(monster, corpse)
 	if not monster or not corpse then
diff --git a/data/scripts/eventcallbacks/monster/ondroploot_gem_atelier.lua b/data/scripts/eventcallbacks/monster/ondroploot_gem_atelier.lua
index d1fb6ad38b1..4305e60e086 100644
--- a/data/scripts/eventcallbacks/monster/ondroploot_gem_atelier.lua
+++ b/data/scripts/eventcallbacks/monster/ondroploot_gem_atelier.lua
@@ -1,4 +1,4 @@
-local callback = EventCallback()
+local callback = EventCallback("MonsterOnDropLootGemAtelier")
 
 function callback.monsterOnDropLoot(monster, corpse)
 	if not monster or not corpse then
diff --git a/data/scripts/eventcallbacks/monster/ondroploot_hazard.lua b/data/scripts/eventcallbacks/monster/ondroploot_hazard.lua
index ddcaeaee782..92ae22482fd 100644
--- a/data/scripts/eventcallbacks/monster/ondroploot_hazard.lua
+++ b/data/scripts/eventcallbacks/monster/ondroploot_hazard.lua
@@ -1,4 +1,4 @@
-local callback = EventCallback()
+local callback = EventCallback("MonsterOnDropLootHazard")
 
 function callback.monsterOnDropLoot(monster, corpse)
 	if not monster:hazard() then
diff --git a/data/scripts/eventcallbacks/monster/ondroploot_prey.lua b/data/scripts/eventcallbacks/monster/ondroploot_prey.lua
index 1f732f173d2..a0fce3d4457 100644
--- a/data/scripts/eventcallbacks/monster/ondroploot_prey.lua
+++ b/data/scripts/eventcallbacks/monster/ondroploot_prey.lua
@@ -1,4 +1,4 @@
-local callback = EventCallback()
+local callback = EventCallback("MonsterOnDropLootPrey")
 
 function callback.monsterOnDropLoot(monster, corpse)
 	local player = Player(corpse:getCorpseOwner())
diff --git a/data/scripts/eventcallbacks/monster/ondroploot_wealth_duplex.lua b/data/scripts/eventcallbacks/monster/ondroploot_wealth_duplex.lua
index 20202c0b5cc..ffba226956a 100644
--- a/data/scripts/eventcallbacks/monster/ondroploot_wealth_duplex.lua
+++ b/data/scripts/eventcallbacks/monster/ondroploot_wealth_duplex.lua
@@ -1,4 +1,4 @@
-local callback = EventCallback()
+local callback = EventCallback("MonsterOnDropLootWealthDuplex")
 
 function callback.monsterOnDropLoot(monster, corpse)
 	local player = Player(corpse:getCorpseOwner())
diff --git a/data/scripts/eventcallbacks/monster/postdroploot_analyzer.lua b/data/scripts/eventcallbacks/monster/postdroploot_analyzer.lua
index 8214ac98ea1..4c1e53e6f77 100644
--- a/data/scripts/eventcallbacks/monster/postdroploot_analyzer.lua
+++ b/data/scripts/eventcallbacks/monster/postdroploot_analyzer.lua
@@ -1,4 +1,4 @@
-local callback = EventCallback()
+local callback = EventCallback("MonsterPostDropLootAnalyzer")
 
 function callback.monsterPostDropLoot(monster, corpse)
 	local player = Player(corpse:getCorpseOwner())
diff --git a/data/scripts/eventcallbacks/party/on_disband.lua b/data/scripts/eventcallbacks/party/on_disband.lua
index 60838962395..93bb1578fd1 100644
--- a/data/scripts/eventcallbacks/party/on_disband.lua
+++ b/data/scripts/eventcallbacks/party/on_disband.lua
@@ -1,4 +1,4 @@
-local callback = EventCallback()
+local callback = EventCallback("PartyOnDisbandEventBaseEvent")
 
 function callback.partyOnDisband(party)
 	local members = party:getMembers()
diff --git a/data/scripts/eventcallbacks/player/on_browse_field.lua b/data/scripts/eventcallbacks/player/on_browse_field.lua
index a4f00341202..3b674a608a7 100644
--- a/data/scripts/eventcallbacks/player/on_browse_field.lua
+++ b/data/scripts/eventcallbacks/player/on_browse_field.lua
@@ -1,4 +1,4 @@
-local callback = EventCallback()
+local callback = EventCallback("PlayerOnBrowseFieldBaseEvent")
 
 function callback.playerOnBrowseField(player, position)
 	return true
diff --git a/data/scripts/eventcallbacks/player/on_look.lua b/data/scripts/eventcallbacks/player/on_look.lua
index 90d3089052d..c4743052cfa 100644
--- a/data/scripts/eventcallbacks/player/on_look.lua
+++ b/data/scripts/eventcallbacks/player/on_look.lua
@@ -1,4 +1,4 @@
-local callback = EventCallback()
+local callback = EventCallback("PlayerOnLookBaseEvent")
 
 function callback.playerOnLook(player, thing, position, distance)
 	local description = "You see "
diff --git a/data/scripts/eventcallbacks/player/on_look_in_shop.lua b/data/scripts/eventcallbacks/player/on_look_in_shop.lua
index bd96296624d..0e724009b5e 100644
--- a/data/scripts/eventcallbacks/player/on_look_in_shop.lua
+++ b/data/scripts/eventcallbacks/player/on_look_in_shop.lua
@@ -1,4 +1,4 @@
-local callback = EventCallback()
+local callback = EventCallback("PlayerOnLookInShopBaseEvent")
 
 function callback.playerOnLookInShop(player, itemType, count)
 	return true
diff --git a/data/scripts/eventcallbacks/player/on_look_in_trade.lua b/data/scripts/eventcallbacks/player/on_look_in_trade.lua
index 77711c5b95d..c82dd9905f0 100644
--- a/data/scripts/eventcallbacks/player/on_look_in_trade.lua
+++ b/data/scripts/eventcallbacks/player/on_look_in_trade.lua
@@ -1,4 +1,4 @@
-local callback = EventCallback()
+local callback = EventCallback("PlayerOnLookInTradeBaseEvent")
 
 function callback.playerOnLookInTrade(player, partner, item, distance)
 	player:sendTextMessage(MESSAGE_LOOK, "You see " .. item:getDescription(distance))
diff --git a/data/scripts/eventcallbacks/player/on_remove_count.lua b/data/scripts/eventcallbacks/player/on_remove_count.lua
index 4629d0a1b12..f39438c24ba 100644
--- a/data/scripts/eventcallbacks/player/on_remove_count.lua
+++ b/data/scripts/eventcallbacks/player/on_remove_count.lua
@@ -1,4 +1,4 @@
-local callback = EventCallback()
+local callback = EventCallback("PlayerOnRemoveCountBaseEvent")
 
 function callback.playerOnRemoveCount(player, item)
 	player:sendWaste(item:getId())
diff --git a/data/scripts/eventcallbacks/player/on_request_quest_line.lua b/data/scripts/eventcallbacks/player/on_request_quest_line.lua
index c233279cfb8..ad5737d3246 100644
--- a/data/scripts/eventcallbacks/player/on_request_quest_line.lua
+++ b/data/scripts/eventcallbacks/player/on_request_quest_line.lua
@@ -1,4 +1,4 @@
-local callback = EventCallback()
+local callback = EventCallback("PlayerOnRequestQuestLineBaseEvent")
 
 function callback.playerOnRequestQuestLine(player, questId)
 	player:sendQuestLine(questId)
diff --git a/data/scripts/eventcallbacks/player/on_request_quest_log.lua b/data/scripts/eventcallbacks/player/on_request_quest_log.lua
index b6bcbbc3a64..15cfbd34719 100644
--- a/data/scripts/eventcallbacks/player/on_request_quest_log.lua
+++ b/data/scripts/eventcallbacks/player/on_request_quest_log.lua
@@ -1,4 +1,4 @@
-local callback = EventCallback()
+local callback = EventCallback("PlayerOnRequestQuestLogBaseEvent")
 
 function callback.playerOnRequestQuestLog(player)
 	player:sendQuestLog()
diff --git a/data/scripts/eventcallbacks/player/on_rotate_item.lua b/data/scripts/eventcallbacks/player/on_rotate_item.lua
index 3692fcdc655..61bb2a99b2a 100644
--- a/data/scripts/eventcallbacks/player/on_rotate_item.lua
+++ b/data/scripts/eventcallbacks/player/on_rotate_item.lua
@@ -1,4 +1,4 @@
-local callback = EventCallback()
+local callback = EventCallback("PlayerOnRotateItemBaseEvent")
 
 function callback.playerOnRotateItem(player, item, position)
 	if item:getActionId() == IMMOVABLE_ACTION_ID then
diff --git a/data/scripts/eventcallbacks/player/on_storage_update.lua b/data/scripts/eventcallbacks/player/on_storage_update.lua
index 8b3006b1d54..0f4233e51d2 100644
--- a/data/scripts/eventcallbacks/player/on_storage_update.lua
+++ b/data/scripts/eventcallbacks/player/on_storage_update.lua
@@ -1,4 +1,4 @@
-local callback = EventCallback()
+local callback = EventCallback("PlayerOnStorageUpdateBaseEvent")
 
 function callback.playerOnStorageUpdate(player, key, value, oldValue, currentFrameTime)
 	player:updateStorage(key, value, oldValue, currentFrameTime)
diff --git a/data/scripts/eventcallbacks/player/on_trade_accept.lua b/data/scripts/eventcallbacks/player/on_trade_accept.lua
index 3d1eba7171b..8425bdc10b3 100644
--- a/data/scripts/eventcallbacks/player/on_trade_accept.lua
+++ b/data/scripts/eventcallbacks/player/on_trade_accept.lua
@@ -1,4 +1,4 @@
-local callback = EventCallback()
+local callback = EventCallback("PlayerOnTradeAcceptBaseEvent")
 
 function callback.playerOnTradeAccept(player, target, item, targetItem)
 	player:closeForge()
diff --git a/data/scripts/lib/register_lever_tables.lua b/data/scripts/lib/register_lever_tables.lua
index 66a78f42a11..de3cba6649e 100644
--- a/data/scripts/lib/register_lever_tables.lua
+++ b/data/scripts/lib/register_lever_tables.lua
@@ -7,8 +7,8 @@ AscendingFerumbrasConfig = {
 	centerRoom = Position(33392, 31473, 14), -- Center Room
 	exitPosition = Position(33266, 31479, 14), -- Exit Position
 	newPos = Position(33392, 31479, 14), -- Player Position on room
-	days = 3,
+	days = 5,
 	range = 20,
 	time = 60, -- time in minutes to remove the player
-	vortex = 23726,
+	vortex = 20121,
 }
diff --git a/data/scripts/lib/register_monster_type.lua b/data/scripts/lib/register_monster_type.lua
index a9cfaee3354..cb101f0126f 100644
--- a/data/scripts/lib/register_monster_type.lua
+++ b/data/scripts/lib/register_monster_type.lua
@@ -934,8 +934,8 @@ function readSpell(incomingLua, mtype)
 			if incomingLua.effect then
 				spell:setCombatEffect(incomingLua.effect)
 			end
-			if incomingLua.shootEffect then
-				spell:setCombatShootEffect(incomingLua.shootEffect)
+			if incomingLua.shootEffect or incomingLua.shooteffect then
+				spell:setCombatShootEffect(incomingLua.shootEffect or incomingLua.shooteffect)
 			end
 		end
 
diff --git a/data/scripts/lib/register_spells.lua b/data/scripts/lib/register_spells.lua
index 49a5d7aec2f..8c549859640 100644
--- a/data/scripts/lib/register_spells.lua
+++ b/data/scripts/lib/register_spells.lua
@@ -393,6 +393,12 @@ AREA_RING1_BURST3 = {
 	{ 0, 0, 0, 1, 1, 1, 0, 0, 0 },
 }
 
+CrossBeamArea3X2 = {
+	{ 1, 1, 1 },
+	{ 0, 1, 0 },
+	{ 0, 3, 0 },
+}
+
 -- The numbered-keys represents the damage values, and their table
 -- contains the minimum and maximum number of rounds of those damage values.
 RANGE = {
diff --git a/data/scripts/spells/healing/heal_malice.lua b/data/scripts/spells/healing/heal_malice.lua
new file mode 100644
index 00000000000..67211a58341
--- /dev/null
+++ b/data/scripts/spells/healing/heal_malice.lua
@@ -0,0 +1,29 @@
+function onTargetCreature(creature, target)
+	if target:getName() == "Goshnar's Malice" then
+		logger.debug("Monster {} Healing {}", creature:getName(), target:getName())
+		local min = 15000
+		local max = 30000
+		doTargetCombatHealth(target, target, COMBAT_HEALING, min, max)
+	end
+	return true
+end
+
+local combat = Combat()
+combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_RED)
+combat:setParameter(COMBAT_PARAM_AGGRESSIVE, 0)
+combat:setParameter(COMBAT_PARAM_DISPEL, CONDITION_PARALYZE)
+combat:setArea(createCombatArea(AREA_CIRCLE3X3))
+combat:setCallback(CALLBACK_PARAM_TARGETCREATURE, "onTargetCreature")
+
+local spell = Spell("instant")
+
+function spell.onCastSpell(creature, var)
+	return combat:execute(creature, var)
+end
+
+spell:name("Heal Malice")
+spell:words("#####462")
+spell:blockWalls(true)
+spell:needLearn(true)
+spell:needDirection(true)
+spell:register()
diff --git a/data/scripts/talkactions/gm/distance_effect.lua b/data/scripts/talkactions/gm/distance_effect.lua
new file mode 100644
index 00000000000..4c637972cb7
--- /dev/null
+++ b/data/scripts/talkactions/gm/distance_effect.lua
@@ -0,0 +1,37 @@
+local magicEffect = TalkAction("/distanceeffect")
+
+function magicEffect.onSay(player, words, param)
+	-- create log
+	logCommand(player, words, param)
+
+	if param == "" then
+		player:sendCancelMessage("Command param required.")
+		return true
+	end
+
+	local effect = tonumber(param)
+	if effect ~= nil and effect > 0 then
+		local playerPos = player:getPosition()
+		local direction = player:getDirection()
+		local targetPos = Position(playerPos.x, playerPos.y, playerPos.z)
+
+		local distance = 7
+		if direction == DIRECTION_NORTH then
+			targetPos.y = targetPos.y - distance
+		elseif direction == DIRECTION_EAST then
+			targetPos.x = targetPos.x + distance
+		elseif direction == DIRECTION_SOUTH then
+			targetPos.y = targetPos.y + distance
+		elseif direction == DIRECTION_WEST then
+			targetPos.x = targetPos.x - distance
+		end
+
+		player:getPosition():sendDistanceEffect(targetPos, effect)
+	end
+
+	return true
+end
+
+magicEffect:separator(" ")
+magicEffect:groupType("gamemaster")
+magicEffect:register()
diff --git a/src/creatures/appearance/outfit/outfit.hpp b/src/creatures/appearance/outfit/outfit.hpp
index e1a5143c673..d8df003ad0f 100644
--- a/src/creatures/appearance/outfit/outfit.hpp
+++ b/src/creatures/appearance/outfit/outfit.hpp
@@ -47,6 +47,16 @@ class Outfits {
 		return outfits[sex];
 	}
 
+	std::shared_ptr<Outfit> getOutfitByName(PlayerSex_t sex, const std::string &name) const {
+		for (const auto &outfit : outfits[sex]) {
+			if (outfit->name == name) {
+				return outfit;
+			}
+		}
+
+		return nullptr;
+	}
+
 private:
 	std::vector<std::shared_ptr<Outfit>> outfits[PLAYERSEX_LAST + 1];
 };
diff --git a/src/creatures/combat/combat.cpp b/src/creatures/combat/combat.cpp
index cf98fcb6a7b..7d6971c0038 100644
--- a/src/creatures/combat/combat.cpp
+++ b/src/creatures/combat/combat.cpp
@@ -12,6 +12,8 @@
 #include "declarations.hpp"
 #include "creatures/combat/combat.hpp"
 #include "lua/creature/events.hpp"
+#include "lua/callbacks/event_callback.hpp"
+#include "lua/callbacks/events_callbacks.hpp"
 #include "creatures/players/wheel/player_wheel.hpp"
 #include "game/game.hpp"
 #include "game/scheduling/dispatcher.hpp"
@@ -582,10 +584,15 @@ void Combat::CombatHealthFunc(std::shared_ptr<Creature> caster, std::shared_ptr<
 		targetPlayer = target->getPlayer();
 	}
 
+	g_logger().debug("[{}] (old) eventcallback: 'creatureOnCombat', damage primary: '{}', secondary: '{}'", __FUNCTION__, damage.primary.value, damage.secondary.value);
+	g_callbacks().executeCallback(EventCallback_t::creatureOnCombat, &EventCallback::creatureOnCombat, caster, target, std::ref(damage));
+	g_logger().debug("[{}] (new) eventcallback: 'creatureOnCombat', damage primary: '{}', secondary: '{}'", __FUNCTION__, damage.primary.value, damage.secondary.value);
+
 	if (attackerPlayer) {
 		std::shared_ptr<Item> item = attackerPlayer->getWeapon();
 		damage = applyImbuementElementalDamage(attackerPlayer, item, damage);
 		g_events().eventPlayerOnCombat(attackerPlayer, target, item, damage);
+		g_callbacks().executeCallback(EventCallback_t::playerOnCombat, &EventCallback::playerOnCombat, attackerPlayer, target, item, std::ref(damage));
 
 		if (targetPlayer && targetPlayer->getSkull() != SKULL_BLACK) {
 			if (damage.primary.type != COMBAT_HEALING) {
@@ -611,6 +618,9 @@ void Combat::CombatHealthFunc(std::shared_ptr<Creature> caster, std::shared_ptr<
 			damage.primary.value += static_cast<int32_t>(std::ceil((damage.primary.value * slot->bonusPercentage) / 100));
 			damage.secondary.value += static_cast<int32_t>(std::ceil((damage.secondary.value * slot->bonusPercentage) / 100));
 		}
+
+		// Monster type onPlayerAttack event
+		targetMonster->onAttackedByPlayer(attackerPlayer);
 	}
 
 	// Monster attacking player
diff --git a/src/creatures/creature.cpp b/src/creatures/creature.cpp
index 6101ff0473d..ef4b1e5bbc9 100644
--- a/src/creatures/creature.cpp
+++ b/src/creatures/creature.cpp
@@ -1793,7 +1793,7 @@ void Creature::handleLostSummon(bool teleportSummons) {
 	g_game().addMagicEffect(getPosition(), CONST_ME_POFF);
 }
 
-int32_t Creature::getReflectPercent(CombatType_t combatType, bool useCharges /*= false*/) const {
+double_t Creature::getReflectPercent(CombatType_t combatType, bool useCharges /*= false*/) const {
 	try {
 		return reflectPercent.at(combatTypeToIndex(combatType));
 	} catch (const std::out_of_range &e) {
diff --git a/src/creatures/creature.hpp b/src/creatures/creature.hpp
index 4acbacb570a..8ee86323648 100644
--- a/src/creatures/creature.hpp
+++ b/src/creatures/creature.hpp
@@ -255,6 +255,10 @@ class Creature : virtual public Thing, public SharedObject {
 		return creatureIcons.at(key);
 	}
 
+	bool hasIcon(const std::string &key) const {
+		return creatureIcons.contains(key);
+	}
+
 	void setIcon(const std::string &key, CreatureIcon icon) {
 		creatureIcons[key] = icon;
 		iconChanged();
@@ -605,7 +609,7 @@ class Creature : virtual public Thing, public SharedObject {
 	 * @param useCharges Indicates whether charges should be considered.
 	 * @return The reflection percentage for the specified combat type.
 	 */
-	virtual int32_t getReflectPercent(CombatType_t combatType, bool useCharges = false) const;
+	virtual double_t getReflectPercent(CombatType_t combatType, bool useCharges = false) const;
 
 	/**
 	 * @brief Retrieves the flat reflection value for a given combat type.
@@ -703,6 +707,10 @@ class Creature : virtual public Thing, public SharedObject {
 		return false;
 	}
 
+	virtual bool isDead() const {
+		return false;
+	}
+
 	static constexpr int32_t mapWalkWidth = MAP_MAX_VIEW_PORT_X * 2 + 1;
 	static constexpr int32_t mapWalkHeight = MAP_MAX_VIEW_PORT_Y * 2 + 1;
 	static constexpr int32_t maxWalkCacheWidth = (mapWalkWidth - 1) / 2;
diff --git a/src/creatures/creatures_definitions.hpp b/src/creatures/creatures_definitions.hpp
index 46fb5fe5979..f1929a633c1 100644
--- a/src/creatures/creatures_definitions.hpp
+++ b/src/creatures/creatures_definitions.hpp
@@ -494,12 +494,14 @@ enum BestiaryType_t : uint8_t {
 };
 
 enum MonstersEvent_t : uint8_t {
-	MONSTERS_EVENT_NONE = 0,
-	MONSTERS_EVENT_THINK = 1,
-	MONSTERS_EVENT_APPEAR = 2,
-	MONSTERS_EVENT_DISAPPEAR = 3,
-	MONSTERS_EVENT_MOVE = 4,
-	MONSTERS_EVENT_SAY = 5,
+	MONSTERS_EVENT_NONE,
+	MONSTERS_EVENT_THINK,
+	MONSTERS_EVENT_APPEAR,
+	MONSTERS_EVENT_DISAPPEAR,
+	MONSTERS_EVENT_MOVE,
+	MONSTERS_EVENT_SAY,
+	MONSTERS_EVENT_ATTACKED_BY_PLAYER,
+	MONSTERS_EVENT_ON_SPAWN,
 };
 
 enum NpcsEvent_t : uint8_t {
diff --git a/src/creatures/monsters/monster.cpp b/src/creatures/monsters/monster.cpp
index f15616d6af5..9d24b9cc4f3 100644
--- a/src/creatures/monsters/monster.cpp
+++ b/src/creatures/monsters/monster.cpp
@@ -77,15 +77,57 @@ bool Monster::canWalkOnFieldType(CombatType_t combatType) const {
 	}
 }
 
-int32_t Monster::getReflectPercent(CombatType_t reflectType, bool useCharges) const {
-	int32_t result = Creature::getReflectPercent(reflectType, useCharges);
+double_t Monster::getReflectPercent(CombatType_t reflectType, bool useCharges) const {
+	// Monster type reflect
+	auto result = Creature::getReflectPercent(reflectType, useCharges);
+	if (result != 0) {
+		g_logger().debug("[{}] before mtype reflect element {}, percent {}", __FUNCTION__, fmt::underlying(reflectType), result);
+	}
 	auto it = mType->info.reflectMap.find(reflectType);
 	if (it != mType->info.reflectMap.end()) {
 		result += it->second;
 	}
+
+	if (result != 0) {
+		g_logger().debug("[{}] after mtype reflect element {}, percent {}", __FUNCTION__, fmt::underlying(reflectType), result);
+	}
+
+	// Monster reflect
+	auto monsterReflectIt = m_reflectElementMap.find(reflectType);
+	if (monsterReflectIt != m_reflectElementMap.end()) {
+		result += monsterReflectIt->second;
+	}
+
+	if (result != 0) {
+		g_logger().debug("[{}] (final) after monster reflect element {}, percent {}", __FUNCTION__, fmt::underlying(reflectType), result);
+	}
+
 	return result;
 }
 
+void Monster::addReflectElement(CombatType_t combatType, int32_t percent) {
+	g_logger().debug("[{}] added reflect element {}, percent {}", __FUNCTION__, fmt::underlying(combatType), percent);
+	m_reflectElementMap[combatType] += percent;
+}
+
+int32_t Monster::getDefense() const {
+	auto mtypeDefense = mType->info.defense;
+	if (mtypeDefense != 0) {
+		g_logger().debug("[{}] old defense {}", __FUNCTION__, mtypeDefense);
+	}
+	mtypeDefense += m_defense;
+	if (mtypeDefense != 0) {
+		g_logger().debug("[{}] new defense {}", __FUNCTION__, mtypeDefense);
+	}
+	return mtypeDefense * getDefenseMultiplier();
+}
+
+void Monster::addDefense(int32_t defense) {
+	g_logger().debug("[{}] adding defense {}", __FUNCTION__, defense);
+	m_defense += defense;
+	g_logger().debug("[{}] new defense {}", __FUNCTION__, m_defense);
+}
+
 uint32_t Monster::getHealingCombatValue(CombatType_t healingType) const {
 	auto it = mType->info.healingMap.find(healingType);
 	if (it != mType->info.healingMap.end()) {
@@ -284,6 +326,57 @@ void Monster::onCreatureSay(std::shared_ptr<Creature> creature, SpeakClasses typ
 	}
 }
 
+void Monster::onAttackedByPlayer(std::shared_ptr<Player> attackerPlayer) {
+	if (mType->info.monsterAttackedByPlayerEvent != -1) {
+		// onPlayerAttack(self, attackerPlayer)
+		LuaScriptInterface* scriptInterface = mType->info.scriptInterface;
+		if (!scriptInterface->reserveScriptEnv()) {
+			g_logger().error("Monster {} creature {}] Call stack overflow. Too many lua "
+							 "script calls being nested.",
+							 getName(), this->getName());
+			return;
+		}
+
+		ScriptEnvironment* env = scriptInterface->getScriptEnv();
+		env->setScriptId(mType->info.monsterAttackedByPlayerEvent, scriptInterface);
+
+		lua_State* L = scriptInterface->getLuaState();
+		scriptInterface->pushFunction(mType->info.monsterAttackedByPlayerEvent);
+
+		LuaScriptInterface::pushUserdata<Monster>(L, getMonster());
+		LuaScriptInterface::setMetatable(L, -1, "Monster");
+
+		LuaScriptInterface::pushUserdata<Player>(L, attackerPlayer);
+		LuaScriptInterface::setMetatable(L, -1, "Player");
+
+		scriptInterface->callVoidFunction(2);
+	}
+}
+
+void Monster::onSpawn() {
+	if (mType->info.spawnEvent != -1) {
+		// onSpawn(self)
+		LuaScriptInterface* scriptInterface = mType->info.scriptInterface;
+		if (!scriptInterface->reserveScriptEnv()) {
+			g_logger().error("Monster {} creature {}] Call stack overflow. Too many lua "
+							 "script calls being nested.",
+							 getName(), this->getName());
+			return;
+		}
+
+		ScriptEnvironment* env = scriptInterface->getScriptEnv();
+		env->setScriptId(mType->info.spawnEvent, scriptInterface);
+
+		lua_State* L = scriptInterface->getLuaState();
+		scriptInterface->pushFunction(mType->info.spawnEvent);
+
+		LuaScriptInterface::pushUserdata<Monster>(L, getMonster());
+		LuaScriptInterface::setMetatable(L, -1, "Monster");
+
+		scriptInterface->callVoidFunction(1);
+	}
+}
+
 void Monster::addFriend(const std::shared_ptr<Creature> &creature) {
 	if (creature == getMonster()) {
 		g_logger().error("[{}]: adding creature is same of monster", __FUNCTION__);
@@ -1894,6 +1987,8 @@ void Monster::death(std::shared_ptr<Creature>) {
 	if (mType) {
 		g_game().sendSingleSoundEffect(static_self_cast<Monster>()->getPosition(), mType->info.deathSound, getMonster());
 	}
+
+	setDead(true);
 }
 
 std::shared_ptr<Item> Monster::getCorpse(std::shared_ptr<Creature> lastHitCreature, std::shared_ptr<Creature> mostDamageCreature) {
@@ -2095,11 +2190,11 @@ bool Monster::changeTargetDistance(int32_t distance, uint32_t duration /* = 1200
 }
 
 bool Monster::isImmune(ConditionType_t conditionType) const {
-	return mType->info.m_conditionImmunities[static_cast<size_t>(conditionType)];
+	return m_isImmune || mType->info.m_conditionImmunities[static_cast<size_t>(conditionType)];
 }
 
 bool Monster::isImmune(CombatType_t combatType) const {
-	return mType->info.m_damageImmunities[combatTypeToIndex(combatType)];
+	return m_isImmune || mType->info.m_damageImmunities[combatTypeToIndex(combatType)];
 }
 
 void Monster::getPathSearchParams(const std::shared_ptr<Creature> &creature, FindPathParams &fpp) {
diff --git a/src/creatures/monsters/monster.hpp b/src/creatures/monsters/monster.hpp
index edf3874161d..6ba6c583cd6 100644
--- a/src/creatures/monsters/monster.hpp
+++ b/src/creatures/monsters/monster.hpp
@@ -77,9 +77,9 @@ class Monster final : public Creature {
 	int32_t getArmor() const override {
 		return mType->info.armor * getDefenseMultiplier();
 	}
-	int32_t getDefense() const override {
-		return mType->info.defense * getDefenseMultiplier();
-	}
+	int32_t getDefense() const override;
+
+	void addDefense(int32_t defense);
 
 	Faction_t getFaction() const override {
 		auto master = getMaster();
@@ -134,9 +134,11 @@ class Monster final : public Creature {
 		this->spawnMonster = newSpawnMonster;
 	}
 
-	int32_t getReflectPercent(CombatType_t combatType, bool useCharges = false) const override;
+	double_t getReflectPercent(CombatType_t combatType, bool useCharges = false) const override;
 	uint32_t getHealingCombatValue(CombatType_t healingType) const;
 
+	void addReflectElement(CombatType_t combatType, int32_t percent);
+
 	bool canWalkOnFieldType(CombatType_t combatType) const;
 	void onAttackedCreatureDisappear(bool isLogout) override;
 
@@ -144,6 +146,8 @@ class Monster final : public Creature {
 	void onRemoveCreature(std::shared_ptr<Creature> creature, bool isLogout) override;
 	void onCreatureMove(const std::shared_ptr<Creature> &creature, const std::shared_ptr<Tile> &newTile, const Position &newPos, const std::shared_ptr<Tile> &oldTile, const Position &oldPos, bool teleport) override;
 	void onCreatureSay(std::shared_ptr<Creature> creature, SpeakClasses type, const std::string &text) override;
+	void onAttackedByPlayer(std::shared_ptr<Player> attackerPlayer);
+	void onSpawn();
 
 	void drainHealth(std::shared_ptr<Creature> attacker, int32_t damage) override;
 	void changeHealth(int32_t healthChange, bool sendHealthChange = true) override;
@@ -333,6 +337,12 @@ class Monster final : public Creature {
 
 	bool isImmune(ConditionType_t conditionType) const override;
 	bool isImmune(CombatType_t combatType) const override;
+	void setImmune(bool immune) {
+		m_isImmune = immune;
+	}
+	bool isImmune() const {
+		return m_isImmune;
+	}
 
 	float getAttackMultiplier() const {
 		float multiplier = mType->getAttackMultiplier();
@@ -347,6 +357,14 @@ class Monster final : public Creature {
 		return multiplier * std::pow(1.02f, getForgeStack());
 	}
 
+	bool isDead() const override {
+		return m_isDead;
+	}
+
+	void setDead(bool isDead) {
+		m_isDead = isDead;
+	}
+
 private:
 	auto getTargetIterator(const std::shared_ptr<Creature> &creature) {
 		return std::ranges::find_if(targetList.begin(), targetList.end(), [id = creature->getID()](const std::weak_ptr<Creature> &ref) {
@@ -371,6 +389,8 @@ class Monster final : public Creature {
 
 	int64_t lastMeleeAttack = 0;
 
+	uint16_t totalPlayersOnScreen = 0;
+
 	uint32_t attackTicks = 0;
 	uint32_t targetChangeTicks = 0;
 	uint32_t defenseTicks = 0;
@@ -384,8 +404,10 @@ class Monster final : public Creature {
 	int32_t stepDuration = 0;
 	int32_t targetDistance = 1;
 	int32_t challengeMeleeDuration = 0;
-	uint16_t totalPlayersOnScreen = 0;
 	int32_t runAwayHealth = 0;
+	int32_t m_defense = 0;
+
+	std::unordered_map<CombatType_t, int32_t> m_reflectElementMap;
 
 	Position masterPos;
 
@@ -401,6 +423,9 @@ class Monster final : public Creature {
 	bool hazardDamageBoost = false;
 	bool hazardDefenseBoost = false;
 
+	bool m_isDead = false;
+	bool m_isImmune = false;
+
 	void onCreatureEnter(std::shared_ptr<Creature> creature);
 	void onCreatureLeave(std::shared_ptr<Creature> creature);
 	void onCreatureFound(std::shared_ptr<Creature> creature, bool pushFront = false);
diff --git a/src/creatures/monsters/monsters.cpp b/src/creatures/monsters/monsters.cpp
index 190c14c76e5..a6d16abdfe0 100644
--- a/src/creatures/monsters/monsters.cpp
+++ b/src/creatures/monsters/monsters.cpp
@@ -278,17 +278,34 @@ bool MonsterType::loadCallback(LuaScriptInterface* scriptInterface) {
 	}
 
 	info.scriptInterface = scriptInterface;
-	if (info.eventType == MONSTERS_EVENT_THINK) {
-		info.thinkEvent = id;
-	} else if (info.eventType == MONSTERS_EVENT_APPEAR) {
-		info.creatureAppearEvent = id;
-	} else if (info.eventType == MONSTERS_EVENT_DISAPPEAR) {
-		info.creatureDisappearEvent = id;
-	} else if (info.eventType == MONSTERS_EVENT_MOVE) {
-		info.creatureMoveEvent = id;
-	} else if (info.eventType == MONSTERS_EVENT_SAY) {
-		info.creatureSayEvent = id;
+
+	switch (info.eventType) {
+		case MONSTERS_EVENT_THINK:
+			info.thinkEvent = id;
+			break;
+		case MONSTERS_EVENT_APPEAR:
+			info.creatureAppearEvent = id;
+			break;
+		case MONSTERS_EVENT_DISAPPEAR:
+			info.creatureDisappearEvent = id;
+			break;
+		case MONSTERS_EVENT_MOVE:
+			info.creatureMoveEvent = id;
+			break;
+		case MONSTERS_EVENT_SAY:
+			info.creatureSayEvent = id;
+			break;
+		case MONSTERS_EVENT_ATTACKED_BY_PLAYER:
+			info.monsterAttackedByPlayerEvent = id;
+			break;
+		case MONSTERS_EVENT_ON_SPAWN:
+			info.spawnEvent = id;
+			break;
+		default:
+			g_logger().error("[MonsterType::loadCallback] - Unknown event type");
+			return false;
 	}
+
 	return true;
 }
 
diff --git a/src/creatures/monsters/monsters.hpp b/src/creatures/monsters/monsters.hpp
index 0fa2a3d88db..d7ba5da0774 100644
--- a/src/creatures/monsters/monsters.hpp
+++ b/src/creatures/monsters/monsters.hpp
@@ -120,7 +120,9 @@ class MonsterType {
 		int32_t creatureDisappearEvent = -1;
 		int32_t creatureMoveEvent = -1;
 		int32_t creatureSayEvent = -1;
+		int32_t monsterAttackedByPlayerEvent = -1;
 		int32_t thinkEvent = -1;
+		int32_t spawnEvent = -1;
 		int32_t targetDistance = 1;
 		int32_t runAwayHealth = 0;
 		int32_t health = 100;
diff --git a/src/creatures/monsters/spawns/spawn_monster.cpp b/src/creatures/monsters/spawns/spawn_monster.cpp
index 21eab1a7c0b..39fb08327ba 100644
--- a/src/creatures/monsters/spawns/spawn_monster.cpp
+++ b/src/creatures/monsters/spawns/spawn_monster.cpp
@@ -193,6 +193,7 @@ bool SpawnMonster::spawnMonster(uint32_t spawnMonsterId, spawnBlock_t &sb, const
 	spawnedMonsterMap[spawnMonsterId] = monster;
 	sb.lastSpawn = OTSYS_TIME();
 	g_events().eventMonsterOnSpawn(monster, sb.pos);
+	monster->onSpawn();
 	g_callbacks().executeCallback(EventCallback_t::monsterOnSpawn, &EventCallback::monsterOnSpawn, monster, sb.pos);
 	return true;
 }
diff --git a/src/creatures/players/grouping/party.cpp b/src/creatures/players/grouping/party.cpp
index 880fc77594f..d3f89f45431 100644
--- a/src/creatures/players/grouping/party.cpp
+++ b/src/creatures/players/grouping/party.cpp
@@ -452,7 +452,7 @@ void Party::shareExperience(uint64_t experience, std::shared_ptr<Creature> targe
 
 	uint64_t shareExperience = experience;
 	g_events().eventPartyOnShareExperience(getParty(), shareExperience);
-	g_callbacks().executeCallback(EventCallback_t::partyOnShareExperience, &EventCallback::partyOnShareExperience, getParty(), shareExperience);
+	g_callbacks().executeCallback(EventCallback_t::partyOnShareExperience, &EventCallback::partyOnShareExperience, getParty(), std::ref(shareExperience));
 
 	for (auto member : getMembers()) {
 		member->onGainSharedExperience(shareExperience, target);
diff --git a/src/creatures/players/player.cpp b/src/creatures/players/player.cpp
index 75e5b5ef2af..04aa4b7787f 100644
--- a/src/creatures/players/player.cpp
+++ b/src/creatures/players/player.cpp
@@ -674,7 +674,7 @@ void Player::addSkillAdvance(skills_t skill, uint64_t count) {
 	}
 
 	g_events().eventPlayerOnGainSkillTries(static_self_cast<Player>(), skill, count);
-	g_callbacks().executeCallback(EventCallback_t::playerOnGainSkillTries, &EventCallback::playerOnGainSkillTries, getPlayer(), skill, count);
+	g_callbacks().executeCallback(EventCallback_t::playerOnGainSkillTries, &EventCallback::playerOnGainSkillTries, getPlayer(), std::ref(skill), std::ref(count));
 	if (count == 0) {
 		return;
 	}
@@ -2205,6 +2205,8 @@ void Player::onThink(uint32_t interval) {
 
 	// Wheel of destiny major spells
 	wheel()->onThink();
+
+	g_callbacks().executeCallback(EventCallback_t::playerOnThink, &EventCallback::playerOnThink, getPlayer(), interval);
 }
 
 uint32_t Player::isMuted() const {
@@ -2336,7 +2338,7 @@ void Player::addExperience(std::shared_ptr<Creature> target, uint64_t exp, bool
 		return;
 	}
 
-	g_callbacks().executeCallback(EventCallback_t::playerOnGainExperience, &EventCallback::playerOnGainExperience, getPlayer(), target, exp, rawExp);
+	g_callbacks().executeCallback(EventCallback_t::playerOnGainExperience, &EventCallback::playerOnGainExperience, getPlayer(), target, std::ref(exp), std::ref(rawExp));
 
 	g_events().eventPlayerOnGainExperience(static_self_cast<Player>(), target, exp, rawExp);
 	if (exp == 0) {
@@ -2451,7 +2453,7 @@ void Player::removeExperience(uint64_t exp, bool sendText /* = false*/) {
 	}
 
 	g_events().eventPlayerOnLoseExperience(static_self_cast<Player>(), exp);
-	g_callbacks().executeCallback(EventCallback_t::playerOnLoseExperience, &EventCallback::playerOnLoseExperience, getPlayer(), exp);
+	g_callbacks().executeCallback(EventCallback_t::playerOnLoseExperience, &EventCallback::playerOnLoseExperience, getPlayer(), std::ref(exp));
 	if (exp == 0) {
 		return;
 	}
@@ -5525,15 +5527,15 @@ int32_t Player::getMagicShieldCapacityPercent(bool useCharges) const {
 	return result;
 }
 
-int32_t Player::getReflectPercent(CombatType_t combat, bool useCharges) const {
-	int32_t result = reflectPercent[combatTypeToIndex(combat)];
+double_t Player::getReflectPercent(CombatType_t combat, bool useCharges) const {
+	double_t result = reflectPercent[combatTypeToIndex(combat)];
 	for (const auto item : getEquippedItems()) {
 		const ItemType &itemType = Item::items[item->getID()];
 		if (!itemType.abilities) {
 			continue;
 		}
 
-		int32_t reflectPercent = itemType.abilities->reflectPercent[combatTypeToIndex(combat)];
+		double_t reflectPercent = itemType.abilities->reflectPercent[combatTypeToIndex(combat)];
 		if (reflectPercent != 0) {
 			result += reflectPercent;
 			uint16_t charges = item->getCharges();
@@ -5948,7 +5950,7 @@ bool Player::addOfflineTrainingTries(skills_t skill, uint64_t tries) {
 		oldPercentToNextLevel = static_cast<long double>(manaSpent * 100) / nextReqMana;
 
 		g_events().eventPlayerOnGainSkillTries(static_self_cast<Player>(), SKILL_MAGLEVEL, tries);
-		g_callbacks().executeCallback(EventCallback_t::playerOnGainSkillTries, &EventCallback::playerOnGainSkillTries, getPlayer(), SKILL_MAGLEVEL, tries);
+		g_callbacks().executeCallback(EventCallback_t::playerOnGainSkillTries, &EventCallback::playerOnGainSkillTries, getPlayer(), SKILL_MAGLEVEL, std::ref(tries));
 
 		uint32_t currMagLevel = magLevel;
 		while ((manaSpent + tries) >= nextReqMana) {
diff --git a/src/creatures/players/player.hpp b/src/creatures/players/player.hpp
index 592db179071..3fd4ce856c4 100644
--- a/src/creatures/players/player.hpp
+++ b/src/creatures/players/player.hpp
@@ -405,7 +405,7 @@ class Player final : public Creature, public Cylinder, public Bankable {
 		magicShieldCapacityPercent += value;
 	}
 
-	int32_t getReflectPercent(CombatType_t combat, bool useCharges = false) const override;
+	double_t getReflectPercent(CombatType_t combat, bool useCharges = false) const override;
 
 	int32_t getReflectFlat(CombatType_t combat, bool useCharges = false) const override;
 
@@ -2886,7 +2886,7 @@ class Player final : public Creature, public Cylinder, public Bankable {
 	bool marketMenu = false; // Menu option 'show in market'
 	bool exerciseTraining = false;
 	bool moved = false;
-	bool dead = false;
+	bool m_isDead = false;
 	bool imbuementTrackerWindowOpen = false;
 
 	// Hazard system
@@ -2954,10 +2954,10 @@ class Player final : public Creature, public Cylinder, public Bankable {
 	void getPathSearchParams(const std::shared_ptr<Creature> &creature, FindPathParams &fpp) override;
 
 	void setDead(bool isDead) {
-		dead = isDead;
+		m_isDead = isDead;
 	}
-	bool isDead() const {
-		return dead;
+	bool isDead() const override {
+		return m_isDead;
 	}
 
 	void triggerMomentum();
diff --git a/src/game/bank/bank.cpp b/src/game/bank/bank.cpp
index 30345e0495b..bb8a98c6481 100644
--- a/src/game/bank/bank.cpp
+++ b/src/game/bank/bank.cpp
@@ -128,6 +128,10 @@ bool Bank::transferTo(const std::shared_ptr<Bank> destination, uint64_t amount)
 }
 
 bool Bank::withdraw(std::shared_ptr<Player> player, uint64_t amount) {
+	if (!player) {
+		return false;
+	}
+
 	if (!debit(amount)) {
 		return false;
 	}
diff --git a/src/game/game.cpp b/src/game/game.cpp
index cac0b596ebf..3d713847d07 100644
--- a/src/game/game.cpp
+++ b/src/game/game.cpp
@@ -1318,6 +1318,10 @@ ReturnValue Game::internalMoveCreature(std::shared_ptr<Creature> creature, Direc
 		return RETURNVALUE_NOTPOSSIBLE;
 	}
 
+	if (creature->getBaseSpeed() == 0 && flags != FLAG_IGNORENOTMOVABLE) {
+		return RETURNVALUE_NOTMOVABLE;
+	}
+
 	creature->setLastPosition(creature->getPosition());
 	const Position &currentPos = creature->getPosition();
 	Position destPos = getNextPosition(direction, currentPos);
@@ -6921,7 +6925,7 @@ bool Game::combatChangeHealth(std::shared_ptr<Creature> attacker, std::shared_pt
 
 		if (!isEvent) {
 			g_events().eventCreatureOnDrainHealth(target, attacker, damage.primary.type, damage.primary.value, damage.secondary.type, damage.secondary.value, message.primary.color, message.secondary.color);
-			g_callbacks().executeCallback(EventCallback_t::creatureOnDrainHealth, &EventCallback::creatureOnDrainHealth, target, attacker, damage.primary.type, damage.primary.value, damage.secondary.type, damage.secondary.value, message.primary.color, message.secondary.color);
+			g_callbacks().executeCallback(EventCallback_t::creatureOnDrainHealth, &EventCallback::creatureOnDrainHealth, target, attacker, std::ref(damage.primary.type), std::ref(damage.primary.value), std::ref(damage.secondary.type), std::ref(damage.secondary.value), std::ref(message.primary.color), std::ref(message.secondary.color));
 		}
 		if (damage.origin != ORIGIN_NONE && attacker && damage.primary.type != COMBAT_HEALING) {
 			damage.primary.value *= attacker->getBuff(BUFF_DAMAGEDEALT) / 100.;
@@ -7116,7 +7120,7 @@ bool Game::combatChangeHealth(std::shared_ptr<Creature> attacker, std::shared_pt
 			return true;
 		} else if (realDamage >= targetHealth) {
 			for (const auto creatureEvent : target->getCreatureEvents(CREATURE_EVENT_PREPAREDEATH)) {
-				if (!creatureEvent->executeOnPrepareDeath(target, attacker)) {
+				if (!creatureEvent->executeOnPrepareDeath(target, attacker, std::ref(realDamage))) {
 					return false;
 				}
 			}
diff --git a/src/game/zones/zone.cpp b/src/game/zones/zone.cpp
index b6c1191aa78..7ffa4b594f4 100644
--- a/src/game/zones/zone.cpp
+++ b/src/game/zones/zone.cpp
@@ -15,6 +15,7 @@
 #include "creatures/npcs/npc.hpp"
 #include "creatures/players/player.hpp"
 #include "utils/pugicast.hpp"
+#include "kv/kv.hpp"
 
 phmap::parallel_flat_hash_map<std::string, std::shared_ptr<Zone>> Zone::zones = {};
 phmap::parallel_flat_hash_map<uint32_t, std::shared_ptr<Zone>> Zone::zonesByID = {};
@@ -122,6 +123,10 @@ std::vector<std::shared_ptr<Item>> Zone::getItems() {
 void Zone::removePlayers() {
 	for (const auto &player : getPlayers()) {
 		g_game().internalTeleport(player, getRemoveDestination(player));
+		// Remove icon from player (soul war quest)
+		if (player->hasIcon("goshnars-hatred-damage")) {
+			player->removeIcon("goshnars-hatred-damage");
+		}
 	}
 }
 
diff --git a/src/io/functions/iologindata_load_player.cpp b/src/io/functions/iologindata_load_player.cpp
index d4a4f33774d..bb10a8d19ff 100644
--- a/src/io/functions/iologindata_load_player.cpp
+++ b/src/io/functions/iologindata_load_player.cpp
@@ -807,7 +807,12 @@ void IOLoginDataLoad::loadPlayerForgeHistory(std::shared_ptr<Player> player, DBR
 }
 
 void IOLoginDataLoad::loadPlayerBosstiary(std::shared_ptr<Player> player, DBResult_ptr result) {
-	if (!result || !player) {
+	if (!result) {
+		g_logger().warn("[IOLoginData::loadPlayer] - Result nullptr: {}", __FUNCTION__);
+		return;
+	}
+
+	if (!player) {
 		g_logger().warn("[IOLoginData::loadPlayer] - Player or Result nullptr: {}", __FUNCTION__);
 		return;
 	}
diff --git a/src/io/io_bosstiary.cpp b/src/io/io_bosstiary.cpp
index 0090c0b3ebb..4381c5c8a31 100644
--- a/src/io/io_bosstiary.cpp
+++ b/src/io/io_bosstiary.cpp
@@ -249,6 +249,7 @@ std::vector<uint16_t> IOBosstiary::getBosstiaryFinished(const std::shared_ptr<Pl
 
 		const auto mType = g_monsters().getMonsterType(bossName);
 		if (!mType) {
+			g_logger().error("[{}] Boss with id {} and name {} not found in boss map", __FUNCTION__, bossId, bossName);
 			continue;
 		}
 
diff --git a/src/io/iomap.cpp b/src/io/iomap.cpp
index 4edfefa66d1..c6b494937d6 100644
--- a/src/io/iomap.cpp
+++ b/src/io/iomap.cpp
@@ -77,7 +77,7 @@ void IOMap::loadMap(Map* map, const Position &pos) {
 
 	map->flush();
 
-	g_logger().info("Map Loaded {} ({}x{}) in {} milliseconds", map->path.filename().string(), map->width, map->height, bm_mapLoad.duration());
+	g_logger().debug("Map Loaded {} ({}x{}) in {} milliseconds", map->path.filename().string(), map->width, map->height, bm_mapLoad.duration());
 }
 
 void IOMap::parseMapDataAttributes(FileStream &stream, Map* map) {
diff --git a/src/lua/callbacks/callbacks_definitions.hpp b/src/lua/callbacks/callbacks_definitions.hpp
index 521a2c4cda7..12a36736e20 100644
--- a/src/lua/callbacks/callbacks_definitions.hpp
+++ b/src/lua/callbacks/callbacks_definitions.hpp
@@ -25,6 +25,7 @@ enum class EventCallback_t : uint16_t {
 	creatureOnTargetCombat,
 	creatureOnHear,
 	creatureOnDrainHealth,
+	creatureOnCombat,
 	// Party
 	partyOnJoin,
 	partyOnLeave,
@@ -56,6 +57,7 @@ enum class EventCallback_t : uint16_t {
 	playerOnCombat,
 	playerOnInventoryUpdate,
 	playerOnRotateItem,
+	playerOnThink,
 	// Monster
 	monsterOnDropLoot,
 	monsterPostDropLoot,
@@ -67,4 +69,5 @@ enum class EventCallback_t : uint16_t {
 	zoneBeforeCreatureLeave,
 	zoneAfterCreatureEnter,
 	zoneAfterCreatureLeave,
+	mapOnLoad,
 };
diff --git a/src/lua/callbacks/event_callback.cpp b/src/lua/callbacks/event_callback.cpp
index 51c03131fa9..96d824a14d6 100644
--- a/src/lua/callbacks/event_callback.cpp
+++ b/src/lua/callbacks/event_callback.cpp
@@ -25,8 +25,16 @@
  *
  * @see Script
  */
-EventCallback::EventCallback(LuaScriptInterface* scriptInterface) :
-	Script(scriptInterface) {
+EventCallback::EventCallback(LuaScriptInterface* scriptInterface, const std::string &callbackName, bool skipDuplicationCheck) :
+	Script(scriptInterface), m_callbackName(callbackName), m_skipDuplicationCheck(skipDuplicationCheck) {
+}
+
+std::string EventCallback::getName() const {
+	return m_callbackName;
+}
+
+bool EventCallback::skipDuplicationCheck() const {
+	return m_skipDuplicationCheck;
 }
 
 std::string EventCallback::getScriptTypeName() const {
@@ -225,6 +233,58 @@ void EventCallback::creatureOnDrainHealth(std::shared_ptr<Creature> creature, st
 	getScriptInterface()->resetScriptEnv();
 }
 
+void EventCallback::creatureOnCombat(std::shared_ptr<Creature> attacker, std::shared_ptr<Creature> target, CombatDamage &damage) const {
+	if (!getScriptInterface()->reserveScriptEnv()) {
+		g_logger().error("[{} - "
+						 "Creature {} target {}] "
+						 "Call stack overflow. Too many lua script calls being nested.",
+						 __FUNCTION__, attacker->getName(), target->getName());
+		return;
+	}
+
+	ScriptEnvironment* scriptEnvironment = getScriptInterface()->getScriptEnv();
+	scriptEnvironment->setScriptId(getScriptId(), getScriptInterface());
+
+	lua_State* L = getScriptInterface()->getLuaState();
+	getScriptInterface()->pushFunction(getScriptId());
+
+	LuaScriptInterface::pushUserdata<Creature>(L, attacker);
+	LuaScriptInterface::setCreatureMetatable(L, -1, attacker);
+
+	LuaScriptInterface::pushUserdata<Creature>(L, target);
+	LuaScriptInterface::setCreatureMetatable(L, -1, target);
+
+	LuaScriptInterface::pushCombatDamage(L, damage);
+
+	if (getScriptInterface()->protectedCall(L, 7, 4) != 0) {
+		LuaScriptInterface::reportError(nullptr, LuaScriptInterface::popString(L));
+	} else {
+		damage.primary.value = std::abs(LuaScriptInterface::getNumber<int32_t>(L, -4));
+		damage.primary.type = LuaScriptInterface::getNumber<CombatType_t>(L, -3);
+		damage.secondary.value = std::abs(LuaScriptInterface::getNumber<int32_t>(L, -2));
+		damage.secondary.type = LuaScriptInterface::getNumber<CombatType_t>(L, -1);
+
+		lua_pop(L, 4);
+		if (damage.primary.type != COMBAT_HEALING) {
+			damage.primary.value = -damage.primary.value;
+			damage.secondary.value = -damage.secondary.value;
+		}
+		/*
+			Only EK with dealing physical damage will get elemental damage on skill
+		*/
+		if (damage.origin == ORIGIN_SPELL && attacker) {
+			const auto &player = attacker->getPlayer();
+			if (player && player->getVocationId() != 4 && player->getVocationId() != 8) {
+				damage.primary.value = damage.primary.value + damage.secondary.value;
+				damage.secondary.type = COMBAT_NONE;
+				damage.secondary.value = 0;
+			}
+		}
+	}
+
+	getScriptInterface()->resetScriptEnv();
+}
+
 // Party
 bool EventCallback::partyOnJoin(std::shared_ptr<Party> party, std::shared_ptr<Player> player) const {
 	if (!getScriptInterface()->reserveScriptEnv()) {
@@ -852,7 +912,7 @@ void EventCallback::playerOnCombat(std::shared_ptr<Player> player, std::shared_p
 
 	if (target) {
 		LuaScriptInterface::pushUserdata<Creature>(L, target);
-		LuaScriptInterface::setMetatable(L, -1, "Creature");
+		LuaScriptInterface::setCreatureMetatable(L, -1, target);
 	} else {
 		lua_pushnil(L);
 	}
@@ -1011,6 +1071,26 @@ void EventCallback::playerOnStorageUpdate(std::shared_ptr<Player> player, const
 	getScriptInterface()->callVoidFunction(5);
 }
 
+void EventCallback::playerOnThink(std::shared_ptr<Player> player, uint32_t interval) const {
+	if (!getScriptInterface()->reserveScriptEnv()) {
+		g_logger().error("[{}] player {}. Call stack overflow. Too many lua script calls being nested.", __FUNCTION__, player->getName());
+		return;
+	}
+
+	ScriptEnvironment* scriptEnvironment = getScriptInterface()->getScriptEnv();
+	scriptEnvironment->setScriptId(getScriptId(), getScriptInterface());
+
+	lua_State* L = getScriptInterface()->getLuaState();
+	getScriptInterface()->pushFunction(getScriptId());
+
+	LuaScriptInterface::pushUserdata<Player>(L, player);
+	LuaScriptInterface::setMetatable(L, -1, "Player");
+
+	lua_pushnumber(L, interval);
+
+	getScriptInterface()->callVoidFunction(2);
+}
+
 // Monster
 void EventCallback::monsterOnDropLoot(std::shared_ptr<Monster> monster, std::shared_ptr<Container> corpse) const {
 	if (!getScriptInterface()->reserveScriptEnv()) {
@@ -1212,3 +1292,22 @@ void EventCallback::zoneAfterCreatureLeave(std::shared_ptr<Zone> zone, std::shar
 
 	getScriptInterface()->callVoidFunction(2);
 }
+
+void EventCallback::mapOnLoad(const std::string &mapFullPath) const {
+	if (!getScriptInterface()->reserveScriptEnv()) {
+		g_logger().error("[{} - "
+						 "Call stack overflow. Too many lua script calls being nested.",
+						 __FUNCTION__);
+		return;
+	}
+
+	ScriptEnvironment* scriptEnvironment = getScriptInterface()->getScriptEnv();
+	scriptEnvironment->setScriptId(getScriptId(), getScriptInterface());
+
+	lua_State* L = getScriptInterface()->getLuaState();
+	getScriptInterface()->pushFunction(getScriptId());
+
+	LuaScriptInterface::pushString(L, mapFullPath);
+
+	getScriptInterface()->callVoidFunction(1);
+}
diff --git a/src/lua/callbacks/event_callback.hpp b/src/lua/callbacks/event_callback.hpp
index d9dc4a9b110..e5c560ce232 100644
--- a/src/lua/callbacks/event_callback.hpp
+++ b/src/lua/callbacks/event_callback.hpp
@@ -35,13 +35,27 @@ class EventCallback : public Script {
 private:
 	EventCallback_t m_callbackType = EventCallback_t::none; ///< The type of the event callback.
 	std::string m_scriptTypeName; ///< The name associated with the script type.
+	std::string m_callbackName; ///< The name of the callback.
+	bool m_skipDuplicationCheck = false; ///< Whether the callback is silent error for already registered log error.
 
 public:
 	/**
 	 * @brief Constructor that initializes the EventCallback with a given script interface.
 	 * @param scriptInterface Pointer to the LuaScriptInterface object.
 	 */
-	explicit EventCallback(LuaScriptInterface* scriptInterface);
+	explicit EventCallback(LuaScriptInterface* scriptInterface, const std::string &callbackName, bool silentAlreadyRegistered);
+
+	/**
+	 * @brief Retrieves the callback name.
+	 * @return The callback name as a string.
+	 */
+	std::string getName() const;
+
+	/**
+	 * @brief Retrieves the skip registration status of the callback.
+	 * @return True if the callback is true for skip duplication check and register again the event, false otherwise.
+	 */
+	bool skipDuplicationCheck() const;
 
 	/**
 	 * @brief Retrieves the script type name.
@@ -84,6 +98,7 @@ class EventCallback : public Script {
 	ReturnValue creatureOnTargetCombat(std::shared_ptr<Creature> creature, std::shared_ptr<Creature> target) const;
 	void creatureOnHear(std::shared_ptr<Creature> creature, std::shared_ptr<Creature> speaker, const std::string &words, SpeakClasses type) const;
 	void creatureOnDrainHealth(std::shared_ptr<Creature> creature, std::shared_ptr<Creature> attacker, CombatType_t &typePrimary, int32_t &damagePrimary, CombatType_t &typeSecondary, int32_t &damageSecondary, TextColor_t &colorPrimary, TextColor_t &colorSecondary) const;
+	void creatureOnCombat(std::shared_ptr<Creature> attacker, std::shared_ptr<Creature> target, CombatDamage &damage) const;
 
 	// Party
 	bool partyOnJoin(std::shared_ptr<Party> party, std::shared_ptr<Player> player) const;
@@ -116,6 +131,7 @@ class EventCallback : public Script {
 	void playerOnCombat(std::shared_ptr<Player> player, std::shared_ptr<Creature> target, std::shared_ptr<Item> item, CombatDamage &damage) const;
 	void playerOnInventoryUpdate(std::shared_ptr<Player> player, std::shared_ptr<Item> item, Slots_t slot, bool equip) const;
 	bool playerOnRotateItem(std::shared_ptr<Player> player, std::shared_ptr<Item> item, const Position &position) const;
+	void playerOnThink(std::shared_ptr<Player> player, uint32_t interval) const;
 
 	// Monster
 	void monsterOnDropLoot(std::shared_ptr<Monster> monster, std::shared_ptr<Container> corpse) const;
@@ -131,7 +147,5 @@ class EventCallback : public Script {
 	void zoneAfterCreatureEnter(std::shared_ptr<Zone> zone, std::shared_ptr<Creature> creature) const;
 	void zoneAfterCreatureLeave(std::shared_ptr<Zone> zone, std::shared_ptr<Creature> creature) const;
 
-	/**
-	 * @note here end the lua binder functions }
-	 */
+	void mapOnLoad(const std::string &mapFullPath) const;
 };
diff --git a/src/lua/callbacks/events_callbacks.cpp b/src/lua/callbacks/events_callbacks.cpp
index 4a1830f80fb..1ab64957497 100644
--- a/src/lua/callbacks/events_callbacks.cpp
+++ b/src/lua/callbacks/events_callbacks.cpp
@@ -12,6 +12,8 @@
 #include "lua/callbacks/events_callbacks.hpp"
 
 #include "lua/callbacks/event_callback.hpp"
+#include "game/game.hpp"
+#include "lib/di/container.hpp"
 
 /**
  * @class EventsCallbacks
@@ -28,22 +30,34 @@ EventsCallbacks &EventsCallbacks::getInstance() {
 	return inject<EventsCallbacks>();
 }
 
-void EventsCallbacks::addCallback(const std::shared_ptr<EventCallback> callback) {
-	m_callbacks.push_back(callback);
+bool EventsCallbacks::isCallbackRegistered(const std::shared_ptr<EventCallback> &callback) {
+	if (g_game().getGameState() == GAME_STATE_STARTUP && !callback->skipDuplicationCheck() && m_callbacks.find(callback->getName()) != m_callbacks.end()) {
+		return true;
+	}
+
+	return false;
+}
+
+void EventsCallbacks::addCallback(const std::shared_ptr<EventCallback> &callback) {
+	if (m_callbacks.find(callback->getName()) != m_callbacks.end()) {
+		return;
+	}
+
+	m_callbacks[callback->getName()] = callback;
 }
 
-std::vector<std::shared_ptr<EventCallback>> EventsCallbacks::getCallbacks() const {
+std::unordered_map<std::string, std::shared_ptr<EventCallback>> EventsCallbacks::getCallbacks() const {
 	return m_callbacks;
 }
 
-std::vector<std::shared_ptr<EventCallback>> EventsCallbacks::getCallbacksByType(EventCallback_t type) const {
-	std::vector<std::shared_ptr<EventCallback>> eventCallbacks;
-	for (auto callback : getCallbacks()) {
+std::unordered_map<std::string, std::shared_ptr<EventCallback>> EventsCallbacks::getCallbacksByType(EventCallback_t type) const {
+	std::unordered_map<std::string, std::shared_ptr<EventCallback>> eventCallbacks;
+	for (auto [name, callback] : getCallbacks()) {
 		if (callback->getType() != type) {
 			continue;
 		}
 
-		eventCallbacks.push_back(callback);
+		eventCallbacks[name] = callback;
 	}
 
 	return eventCallbacks;
diff --git a/src/lua/callbacks/events_callbacks.hpp b/src/lua/callbacks/events_callbacks.hpp
index 53b119f6445..7ca4679ab4f 100644
--- a/src/lua/callbacks/events_callbacks.hpp
+++ b/src/lua/callbacks/events_callbacks.hpp
@@ -45,24 +45,35 @@ class EventsCallbacks {
 	 */
 	static EventsCallbacks &getInstance();
 
+	/**
+	 * @brief Checks if an event callback is already registered.
+	 *
+	 * @details Determines if the game state is at startup and if a callback with the same name already exists.
+	 * @details If both conditions are met, logs an error and indicates the callback is already registered.
+	 *
+	 * @param callback Shared pointer to the event callback being checked.
+	 * @return True if the callback already exists during the game startup state, otherwise false.
+	 */
+	bool isCallbackRegistered(const std::shared_ptr<EventCallback> &callback);
+
 	/**
 	 * @brief Adds a new event callback to the list.
 	 * @param callback Pointer to the EventCallback object to add.
 	 */
-	void addCallback(const std::shared_ptr<EventCallback> callback);
+	void addCallback(const std::shared_ptr<EventCallback> &callback);
 
 	/**
 	 * @brief Gets all registered event callbacks.
 	 * @return Vector of pointers to EventCallback objects.
 	 */
-	std::vector<std::shared_ptr<EventCallback>> getCallbacks() const;
+	std::unordered_map<std::string, std::shared_ptr<EventCallback>> getCallbacks() const;
 
 	/**
 	 * @brief Gets event callbacks by their type.
 	 * @param type The type of callbacks to retrieve.
 	 * @return Vector of pointers to EventCallback objects of the specified type.
 	 */
-	std::vector<std::shared_ptr<EventCallback>> getCallbacksByType(EventCallback_t type) const;
+	std::unordered_map<std::string, std::shared_ptr<EventCallback>> getCallbacksByType(EventCallback_t type) const;
 
 	/**
 	 * @brief Clears all registered event callbacks.
@@ -77,7 +88,7 @@ class EventsCallbacks {
 	 */
 	template <typename CallbackFunc, typename... Args>
 	void executeCallback(EventCallback_t eventType, CallbackFunc callbackFunc, Args &&... args) {
-		for (const auto &callback : getCallbacksByType(eventType)) {
+		for (const auto &[name, callback] : getCallbacksByType(eventType)) {
 			auto argsCopy = std::make_tuple(args...);
 			if (callback && callback->isLoadedCallback()) {
 				std::apply(
@@ -101,7 +112,7 @@ class EventsCallbacks {
 	bool checkCallback(EventCallback_t eventType, CallbackFunc callbackFunc, Args &&... args) {
 		bool allCallbacksSucceeded = true;
 
-		for (const auto &callback : getCallbacksByType(eventType)) {
+		for (const auto &[name, callback] : getCallbacksByType(eventType)) {
 			auto argsCopy = std::make_tuple(args...);
 			if (callback && callback->isLoadedCallback()) {
 				bool callbackResult = std::apply(
@@ -118,7 +129,7 @@ class EventsCallbacks {
 
 private:
 	// Container for storing registered event callbacks.
-	std::vector<std::shared_ptr<EventCallback>> m_callbacks;
+	std::unordered_map<std::string, std::shared_ptr<EventCallback>> m_callbacks;
 };
 
 constexpr auto g_callbacks = EventsCallbacks::getInstance;
diff --git a/src/lua/creature/creatureevent.cpp b/src/lua/creature/creatureevent.cpp
index e3ac954908f..63b77254cc0 100644
--- a/src/lua/creature/creatureevent.cpp
+++ b/src/lua/creature/creatureevent.cpp
@@ -233,7 +233,7 @@ bool CreatureEvent::executeOnThink(std::shared_ptr<Creature> creature, uint32_t
 	return getScriptInterface()->callFunction(2);
 }
 
-bool CreatureEvent::executeOnPrepareDeath(std::shared_ptr<Creature> creature, std::shared_ptr<Creature> killer) const {
+bool CreatureEvent::executeOnPrepareDeath(std::shared_ptr<Creature> creature, std::shared_ptr<Creature> killer, int realDamage) const {
 	// onPrepareDeath(creature, killer)
 	if (!getScriptInterface()->reserveScriptEnv()) {
 		g_logger().error("[CreatureEvent::executeOnPrepareDeath - Creature {} killer {}"
@@ -259,7 +259,9 @@ bool CreatureEvent::executeOnPrepareDeath(std::shared_ptr<Creature> creature, st
 		lua_pushnil(L);
 	}
 
-	return getScriptInterface()->callFunction(2);
+	lua_pushnumber(L, realDamage);
+
+	return getScriptInterface()->callFunction(3);
 }
 
 bool CreatureEvent::executeOnDeath(std::shared_ptr<Creature> creature, std::shared_ptr<Item> corpse, std::shared_ptr<Creature> killer, std::shared_ptr<Creature> mostDamageKiller, bool lastHitUnjustified, bool mostDamageUnjustified) const {
diff --git a/src/lua/creature/creatureevent.hpp b/src/lua/creature/creatureevent.hpp
index 8a208343e11..e34bd8eb75e 100644
--- a/src/lua/creature/creatureevent.hpp
+++ b/src/lua/creature/creatureevent.hpp
@@ -46,7 +46,7 @@ class CreatureEvent final : public Script {
 	bool executeOnLogin(std::shared_ptr<Player> player) const;
 	bool executeOnLogout(std::shared_ptr<Player> player) const;
 	bool executeOnThink(std::shared_ptr<Creature> creature, uint32_t interval) const;
-	bool executeOnPrepareDeath(std::shared_ptr<Creature> creature, std::shared_ptr<Creature> killer) const;
+	bool executeOnPrepareDeath(std::shared_ptr<Creature> creature, std::shared_ptr<Creature> killer, int realDamage) const;
 	bool executeOnDeath(std::shared_ptr<Creature> creature, std::shared_ptr<Item> corpse, std::shared_ptr<Creature> killer, std::shared_ptr<Creature> mostDamageKiller, bool lastHitUnjustified, bool mostDamageUnjustified) const;
 	void executeOnKill(std::shared_ptr<Creature> creature, std::shared_ptr<Creature> target, bool lastHit) const;
 	bool executeAdvance(std::shared_ptr<Player> player, skills_t, uint32_t, uint32_t) const;
diff --git a/src/lua/creature/events.cpp b/src/lua/creature/events.cpp
index 2917d128b8a..19c5da2fc5b 100644
--- a/src/lua/creature/events.cpp
+++ b/src/lua/creature/events.cpp
@@ -1159,7 +1159,7 @@ void Events::eventPlayerOnCombat(std::shared_ptr<Player> player, std::shared_ptr
 
 	if (target) {
 		LuaScriptInterface::pushUserdata<Creature>(L, target);
-		LuaScriptInterface::setMetatable(L, -1, "Creature");
+		LuaScriptInterface::setCreatureMetatable(L, -1, target);
 	} else {
 		lua_pushnil(L);
 	}
diff --git a/src/lua/functions/core/game/bank_functions.cpp b/src/lua/functions/core/game/bank_functions.cpp
index f6732b8bf70..cc76bf4c091 100644
--- a/src/lua/functions/core/game/bank_functions.cpp
+++ b/src/lua/functions/core/game/bank_functions.cpp
@@ -81,6 +81,7 @@ int BankFunctions::luaBankTransferToGuild(lua_State* L) {
 		reportErrorFunc("Source is nullptr");
 		return 1;
 	}
+
 	std::shared_ptr<Bank> destination = getBank(L, 2, true /* isGuild */);
 	if (destination == nullptr) {
 		reportErrorFunc("Destination is nullptr");
diff --git a/src/lua/functions/core/game/game_functions.cpp b/src/lua/functions/core/game/game_functions.cpp
index ea418dede66..4b031cdd3fe 100644
--- a/src/lua/functions/core/game/game_functions.cpp
+++ b/src/lua/functions/core/game/game_functions.cpp
@@ -435,6 +435,7 @@ int GameFunctions::luaGameCreateMonster(lua_State* L) {
 	if (g_game().placeCreature(monster, position, extended, force)) {
 		g_events().eventMonsterOnSpawn(monster, position);
 		g_callbacks().executeCallback(EventCallback_t::monsterOnSpawn, &EventCallback::monsterOnSpawn, monster, position);
+		monster->onSpawn();
 		const auto &mtype = monster->getMonsterType();
 		if (mtype && mtype->info.raceid > 0 && mtype->info.bosstiaryRace == BosstiaryRarity_t::RARITY_ARCHFOE) {
 			for (const auto &spectator : Spectators().find<Player>(monster->getPosition(), true)) {
diff --git a/src/lua/functions/core/game/lua_enums.cpp b/src/lua/functions/core/game/lua_enums.cpp
index 2e3813e0769..19e7b9219ec 100644
--- a/src/lua/functions/core/game/lua_enums.cpp
+++ b/src/lua/functions/core/game/lua_enums.cpp
@@ -1219,11 +1219,9 @@ void LuaEnums::initReloadTypeEnums(lua_State* L) {
 
 void LuaEnums::initCreaturesEventEnums(lua_State* L) {
 	// Monsters
-	registerEnum(L, MONSTERS_EVENT_THINK);
-	registerEnum(L, MONSTERS_EVENT_APPEAR);
-	registerEnum(L, MONSTERS_EVENT_DISAPPEAR);
-	registerEnum(L, MONSTERS_EVENT_MOVE);
-	registerEnum(L, MONSTERS_EVENT_SAY);
+	for (auto value : magic_enum::enum_values<MonstersEvent_t>()) {
+		registerMagicEnum(L, value);
+	}
 
 	// Npcs
 	registerEnum(L, NPCS_EVENT_THINK);
diff --git a/src/lua/functions/core/game/zone_functions.cpp b/src/lua/functions/core/game/zone_functions.cpp
index 5471d01895a..0f19c94f789 100644
--- a/src/lua/functions/core/game/zone_functions.cpp
+++ b/src/lua/functions/core/game/zone_functions.cpp
@@ -136,7 +136,7 @@ int ZoneFunctions::luaZoneGetCreatures(lua_State* L) {
 	for (auto creature : creatures) {
 		index++;
 		pushUserdata<Creature>(L, creature);
-		setMetatable(L, -1, "Creature");
+		setCreatureMetatable(L, -1, creature);
 		lua_rawseti(L, -2, index);
 	}
 	return 1;
diff --git a/src/lua/functions/creatures/creature_functions.cpp b/src/lua/functions/creatures/creature_functions.cpp
index a633afe9749..29f72078619 100644
--- a/src/lua/functions/creatures/creature_functions.cpp
+++ b/src/lua/functions/creatures/creature_functions.cpp
@@ -968,7 +968,7 @@ int CreatureFunctions::luaCreatureMove(lua_State* L) {
 			lua_pushnil(L);
 			return 1;
 		}
-		lua_pushnumber(L, g_game().internalMoveCreature(creature, direction, FLAG_NOLIMIT));
+		lua_pushnumber(L, g_game().internalMoveCreature(creature, direction, FLAG_IGNORENOTMOVABLE));
 	} else {
 		std::shared_ptr<Tile> tile = getUserdataShared<Tile>(L, 2);
 		if (!tile) {
diff --git a/src/lua/functions/creatures/monster/monster_functions.cpp b/src/lua/functions/creatures/monster/monster_functions.cpp
index 1591053c391..39836e68999 100644
--- a/src/lua/functions/creatures/monster/monster_functions.cpp
+++ b/src/lua/functions/creatures/monster/monster_functions.cpp
@@ -60,7 +60,8 @@ int MonsterFunctions::luaMonsterGetType(lua_State* L) {
 }
 
 int MonsterFunctions::luaMonsterSetType(lua_State* L) {
-	// monster:setType(name or raceid)
+	// monster:setType(name or raceid, restoreHealth = false)
+	bool restoreHealth = getBoolean(L, 3, false);
 	std::shared_ptr<Monster> monster = getUserdataShared<Monster>(L, 1);
 	if (monster) {
 		std::shared_ptr<MonsterType> mType = nullptr;
@@ -81,8 +82,14 @@ int MonsterFunctions::luaMonsterSetType(lua_State* L) {
 		monster->defaultOutfit = mType->info.outfit;
 		monster->currentOutfit = mType->info.outfit;
 		monster->skull = mType->info.skull;
-		monster->health = mType->info.health * mType->getHealthMultiplier();
-		monster->healthMax = mType->info.healthMax * mType->getHealthMultiplier();
+		if (restoreHealth) {
+			auto multiplier = mType->getHealthMultiplier();
+			monster->health = mType->info.health * multiplier;
+			monster->healthMax = mType->info.healthMax * multiplier;
+		} else {
+			monster->health = monster->getHealth();
+			monster->healthMax = monster->getMaxHealth();
+		}
 		monster->baseSpeed = mType->getBaseSpeed();
 		monster->internalLight = mType->info.light;
 		monster->hiddenHealth = mType->info.hiddenHealth;
@@ -613,3 +620,76 @@ int MonsterFunctions::luaMonsterHazardDefenseBoost(lua_State* L) {
 	}
 	return 1;
 }
+
+int MonsterFunctions::luaMonsterAddReflectElement(lua_State* L) {
+	// monster:addReflectElement(type, percent)
+	const auto &monster = getUserdataShared<Monster>(L, 1);
+	if (!monster) {
+		reportErrorFunc(getErrorDesc(LUA_ERROR_MONSTER_NOT_FOUND));
+		pushBoolean(L, false);
+		return 0;
+	}
+
+	CombatType_t element = getNumber<CombatType_t>(L, 2);
+	monster->addReflectElement(element, getNumber<int32_t>(L, 3));
+	pushBoolean(L, true);
+	return 1;
+}
+
+int MonsterFunctions::luaMonsterAddDefense(lua_State* L) {
+	// monster:addDefense(defense)
+	const auto &monster = getUserdataShared<Monster>(L, 1);
+	if (!monster) {
+		reportErrorFunc(getErrorDesc(LUA_ERROR_MONSTER_NOT_FOUND));
+		pushBoolean(L, false);
+		return 0;
+	}
+
+	monster->addDefense(getNumber<int32_t>(L, 2));
+	pushBoolean(L, true);
+	return 1;
+}
+
+int MonsterFunctions::luaMonsterGetDefense(lua_State* L) {
+	// monster:getDefense(defense)
+	const auto &monster = getUserdataShared<Monster>(L, 1);
+	if (!monster) {
+		reportErrorFunc(getErrorDesc(LUA_ERROR_MONSTER_NOT_FOUND));
+		pushBoolean(L, false);
+		return 0;
+	}
+
+	lua_pushnumber(L, monster->getDefense());
+	return 1;
+}
+
+int MonsterFunctions::luaMonsterIsDead(lua_State* L) {
+	// monster:isDead()
+	const auto &monster = getUserdataShared<Monster>(L, 1);
+	if (!monster) {
+		reportErrorFunc(getErrorDesc(LUA_ERROR_MONSTER_NOT_FOUND));
+		pushBoolean(L, false);
+		return 0;
+	}
+
+	pushBoolean(L, monster->isDead());
+	return 1;
+}
+
+int MonsterFunctions::luaMonsterImmune(lua_State* L) {
+	// to get: isImmune = monster:immune()
+	// to set and get: newImmuneBool = monster:immune(newImmuneBool)
+	const auto &monster = getUserdataShared<Monster>(L, 1);
+	if (!monster) {
+		reportErrorFunc(getErrorDesc(LUA_ERROR_MONSTER_NOT_FOUND));
+		pushBoolean(L, false);
+		return 0;
+	}
+
+	if (lua_gettop(L) > 1) {
+		monster->setImmune(getBoolean(L, 2));
+	}
+
+	pushBoolean(L, monster->isImmune());
+	return 1;
+}
diff --git a/src/lua/functions/creatures/monster/monster_functions.hpp b/src/lua/functions/creatures/monster/monster_functions.hpp
index bf2785ae430..11ce05cb79c 100644
--- a/src/lua/functions/creatures/monster/monster_functions.hpp
+++ b/src/lua/functions/creatures/monster/monster_functions.hpp
@@ -63,6 +63,13 @@ class MonsterFunctions final : LuaScriptInterface {
 		registerMethod(L, "Monster", "hazardDamageBoost", MonsterFunctions::luaMonsterHazardDamageBoost);
 		registerMethod(L, "Monster", "hazardDefenseBoost", MonsterFunctions::luaMonsterHazardDefenseBoost);
 
+		registerMethod(L, "Monster", "addReflectElement", MonsterFunctions::luaMonsterAddReflectElement);
+		registerMethod(L, "Monster", "addDefense", MonsterFunctions::luaMonsterAddDefense);
+		registerMethod(L, "Monster", "getDefense", MonsterFunctions::luaMonsterGetDefense);
+
+		registerMethod(L, "Monster", "isDead", MonsterFunctions::luaMonsterIsDead);
+		registerMethod(L, "Monster", "immune", MonsterFunctions::luaMonsterImmune);
+
 		CharmFunctions::init(L);
 		LootFunctions::init(L);
 		MonsterSpellFunctions::init(L);
@@ -122,6 +129,12 @@ class MonsterFunctions final : LuaScriptInterface {
 	static int luaMonsterHazardDodge(lua_State* L);
 	static int luaMonsterHazardDamageBoost(lua_State* L);
 	static int luaMonsterHazardDefenseBoost(lua_State* L);
+	static int luaMonsterAddReflectElement(lua_State* L);
+	static int luaMonsterAddDefense(lua_State* L);
+	static int luaMonsterGetDefense(lua_State* L);
+
+	static int luaMonsterIsDead(lua_State* L);
+	static int luaMonsterImmune(lua_State* L);
 
 	friend class CreatureFunctions;
 };
diff --git a/src/lua/functions/creatures/monster/monster_type_functions.cpp b/src/lua/functions/creatures/monster/monster_type_functions.cpp
index b937083fddb..96d7850f35c 100644
--- a/src/lua/functions/creatures/monster/monster_type_functions.cpp
+++ b/src/lua/functions/creatures/monster/monster_type_functions.cpp
@@ -1023,6 +1023,8 @@ int MonsterTypeFunctions::luaMonsterTypeEventOnCallback(lua_State* L) {
 	// monsterType:onDisappear(callback)
 	// monsterType:onMove(callback)
 	// monsterType:onSay(callback)
+	// monsterType:onPlayerAttack(callback)
+	// monsterType:onSpawn(callback)
 	const auto monsterType = getUserdataShared<MonsterType>(L, 1);
 	if (monsterType) {
 		if (monsterType->loadCallback(&g_scripts().getScriptInterface())) {
@@ -1570,7 +1572,7 @@ int MonsterTypeFunctions::luaMonsterTypeBossRaceId(lua_State* L) {
 	} else {
 		auto raceId = getNumber<uint16_t>(L, 2, 0);
 		monsterType->info.raceid = raceId;
-		g_ioBosstiary().addBosstiaryMonster(raceId, monsterType->name);
+		g_ioBosstiary().addBosstiaryMonster(raceId, monsterType->typeName);
 		pushBoolean(L, true);
 	}
 
diff --git a/src/lua/functions/creatures/monster/monster_type_functions.hpp b/src/lua/functions/creatures/monster/monster_type_functions.hpp
index 9a72f53b145..e4bf82053b5 100644
--- a/src/lua/functions/creatures/monster/monster_type_functions.hpp
+++ b/src/lua/functions/creatures/monster/monster_type_functions.hpp
@@ -96,6 +96,8 @@ class MonsterTypeFunctions final : LuaScriptInterface {
 		registerMethod(L, "MonsterType", "onDisappear", MonsterTypeFunctions::luaMonsterTypeEventOnCallback);
 		registerMethod(L, "MonsterType", "onMove", MonsterTypeFunctions::luaMonsterTypeEventOnCallback);
 		registerMethod(L, "MonsterType", "onSay", MonsterTypeFunctions::luaMonsterTypeEventOnCallback);
+		registerMethod(L, "MonsterType", "onPlayerAttack", MonsterTypeFunctions::luaMonsterTypeEventOnCallback);
+		registerMethod(L, "MonsterType", "onSpawn", MonsterTypeFunctions::luaMonsterTypeEventOnCallback);
 
 		registerMethod(L, "MonsterType", "getSummonList", MonsterTypeFunctions::luaMonsterTypeGetSummonList);
 		registerMethod(L, "MonsterType", "addSummon", MonsterTypeFunctions::luaMonsterTypeAddSummon);
diff --git a/src/lua/functions/creatures/player/player_functions.cpp b/src/lua/functions/creatures/player/player_functions.cpp
index 3ba2c43841d..a6204283fbb 100644
--- a/src/lua/functions/creatures/player/player_functions.cpp
+++ b/src/lua/functions/creatures/player/player_functions.cpp
@@ -2261,10 +2261,23 @@ int PlayerFunctions::luaPlayerGetParty(lua_State* L) {
 }
 
 int PlayerFunctions::luaPlayerAddOutfit(lua_State* L) {
-	// player:addOutfit(lookType)
+	// player:addOutfit(lookType or name, addon = 0)
 	std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1);
 	if (player) {
-		player->addOutfit(getNumber<uint16_t>(L, 2), 0);
+		auto addon = getNumber<uint8_t>(L, 3, 0);
+		if (lua_isnumber(L, 2)) {
+			player->addOutfit(getNumber<uint16_t>(L, 2), addon);
+		} else if (lua_isstring(L, 2)) {
+			const std::string &outfitName = getString(L, 2);
+			const auto &outfit = Outfits::getInstance().getOutfitByName(player->getSex(), outfitName);
+			if (!outfit) {
+				reportErrorFunc("Outfit not found");
+				return 1;
+			}
+
+			player->addOutfit(outfit->lookType, addon);
+		}
+
 		pushBoolean(L, true);
 	} else {
 		lua_pushnil(L);
@@ -4279,3 +4292,16 @@ int PlayerFunctions::luaPlayerRemoveAchievementPoints(lua_State* L) {
 	pushBoolean(L, true);
 	return 1;
 }
+
+int PlayerFunctions::luaPlayerSendCreatureAppear(lua_State* L) {
+	auto player = getUserdataShared<Player>(L, 1);
+	if (!player) {
+		reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND));
+		return 1;
+	}
+
+	bool isLogin = getBoolean(L, 2, false);
+	player->sendCreatureAppear(player, player->getPosition(), isLogin);
+	pushBoolean(L, true);
+	return 1;
+}
diff --git a/src/lua/functions/creatures/player/player_functions.hpp b/src/lua/functions/creatures/player/player_functions.hpp
index fafc99ff955..996bfd76794 100644
--- a/src/lua/functions/creatures/player/player_functions.hpp
+++ b/src/lua/functions/creatures/player/player_functions.hpp
@@ -364,6 +364,8 @@ class PlayerFunctions final : LuaScriptInterface {
 		registerMethod(L, "Player", "addAchievementPoints", PlayerFunctions::luaPlayerAddAchievementPoints);
 		registerMethod(L, "Player", "removeAchievementPoints", PlayerFunctions::luaPlayerRemoveAchievementPoints);
 
+		registerMethod(L, "Player", "sendCreatureAppear", PlayerFunctions::luaPlayerSendCreatureAppear);
+
 		GroupFunctions::init(L);
 		GuildFunctions::init(L);
 		MountFunctions::init(L);
@@ -718,5 +720,7 @@ class PlayerFunctions final : LuaScriptInterface {
 	static int luaPlayerAddAchievementPoints(lua_State* L);
 	static int luaPlayerRemoveAchievementPoints(lua_State* L);
 
+	static int luaPlayerSendCreatureAppear(lua_State* L);
+
 	friend class CreatureFunctions;
 };
diff --git a/src/lua/functions/events/event_callback_functions.cpp b/src/lua/functions/events/event_callback_functions.cpp
index 54457f4367a..ef1c348c113 100644
--- a/src/lua/functions/events/event_callback_functions.cpp
+++ b/src/lua/functions/events/event_callback_functions.cpp
@@ -34,7 +34,14 @@ void EventCallbackFunctions::init(lua_State* luaState) {
 }
 
 int EventCallbackFunctions::luaEventCallbackCreate(lua_State* luaState) {
-	const auto eventCallback = std::make_shared<EventCallback>(getScriptEnv()->getScriptInterface());
+	const auto &callbackName = getString(luaState, 2);
+	if (callbackName.empty()) {
+		reportErrorFunc("Invalid callback name");
+		return 1;
+	}
+
+	bool skipDuplicationCheck = getBoolean(luaState, 3, false);
+	const auto eventCallback = std::make_shared<EventCallback>(getScriptEnv()->getScriptInterface(), callbackName, skipDuplicationCheck);
 	pushUserdata<EventCallback>(luaState, eventCallback);
 	setMetatable(luaState, -1, "EventCallback");
 	return 1;
@@ -82,6 +89,11 @@ int EventCallbackFunctions::luaEventCallbackRegister(lua_State* luaState) {
 		return 0;
 	}
 
+	if (g_callbacks().isCallbackRegistered(callback)) {
+		reportErrorFunc(fmt::format("EventCallback is duplicated for event with name: {}", callback->getName()));
+		return 0;
+	}
+
 	g_callbacks().addCallback(callback);
 	pushBoolean(luaState, true);
 	return 1;
diff --git a/src/map/map.cpp b/src/map/map.cpp
index 395e6d7d2be..55bb0fc6548 100644
--- a/src/map/map.cpp
+++ b/src/map/map.cpp
@@ -12,6 +12,8 @@
 #include "map.hpp"
 #include "utils/astarnodes.hpp"
 
+#include "lua/callbacks/event_callback.hpp"
+#include "lua/callbacks/events_callbacks.hpp"
 #include "creatures/monsters/monster.hpp"
 #include "game/game.hpp"
 #include "game/zones/zone.hpp"
@@ -97,6 +99,10 @@ void Map::loadMap(const std::string &identifier, bool mainMap /*= false*/, bool
 		housefile.clear();
 		npcfile.clear();
 	}
+
+	if (!mainMap) {
+		g_callbacks().executeCallback(EventCallback_t::mapOnLoad, &EventCallback::mapOnLoad, path.string());
+	}
 }
 
 void Map::loadMapCustom(const std::string &mapName, bool loadHouses, bool loadMonsters, bool loadNpcs, bool loadZones, int customMapIndex) {
@@ -192,8 +198,7 @@ std::shared_ptr<Tile> Map::getTile(uint16_t x, uint16_t y, uint8_t z) {
 		return nullptr;
 	}
 
-	const auto tile = floor->getTile(x, y);
-	return tile ? tile : getOrCreateTileFromCache(floor, x, y);
+	return getOrCreateTileFromCache(floor, x, y);
 }
 
 void Map::refreshZones(uint16_t x, uint16_t y, uint8_t z) {
diff --git a/src/map/mapcache.cpp b/src/map/mapcache.cpp
index ede4d3fd862..32cc153318c 100644
--- a/src/map/mapcache.cpp
+++ b/src/map/mapcache.cpp
@@ -103,8 +103,9 @@ std::shared_ptr<Item> MapCache::createItem(const std::shared_ptr<BasicItem> &Bas
 
 std::shared_ptr<Tile> MapCache::getOrCreateTileFromCache(const std::unique_ptr<Floor> &floor, uint16_t x, uint16_t y) {
 	const auto cachedTile = floor->getTileCache(x, y);
+	const auto oldTile = floor->getTile(x, y);
 	if (!cachedTile) {
-		return floor->getTile(x, y);
+		return oldTile;
 	}
 
 	std::unique_lock l(floor->getMutex());
@@ -113,6 +114,15 @@ std::shared_ptr<Tile> MapCache::getOrCreateTileFromCache(const std::unique_ptr<F
 
 	auto map = static_cast<Map*>(this);
 
+	std::vector<std::shared_ptr<Creature>> oldCreatureList;
+	if (oldTile) {
+		if (CreatureVector* creatures = oldTile->getCreatures()) {
+			for (const auto &creature : *creatures) {
+				oldCreatureList.emplace_back(creature);
+			}
+		}
+	}
+
 	std::shared_ptr<Tile> tile = nullptr;
 	if (cachedTile->isHouse()) {
 		const auto house = map->houses.getHouse(cachedTile->houseId);
@@ -126,6 +136,10 @@ std::shared_ptr<Tile> MapCache::getOrCreateTileFromCache(const std::unique_ptr<F
 
 	auto pos = Position(x, y, z);
 
+	for (const auto &creature : oldCreatureList) {
+		tile->internalAddThing(creature);
+	}
+
 	if (cachedTile->ground != nullptr) {
 		tile->internalAddThing(createItem(cachedTile->ground, pos));
 	}

From 1a07c704f9989cf7682bd3eb8a303866cb077905 Mon Sep 17 00:00:00 2001
From: Eduardo Dantas <eduardo.dantas@hotmail.com.br>
Date: Wed, 10 Apr 2024 20:47:19 -0300
Subject: [PATCH 02/60] fix: goshnar's malice damage white tiles and add zones

---
 .../quests/soul_war/goshnars_malice.lua       |  8 --
 .../scripts/lib/quests/soul-war.lua           | 98 ++++++++++++++-----
 .../eventcallback_on_combat_taint.lua         |  3 +-
 .../soul_war/moveevent-soul_war_entrances.lua | 17 ++--
 .../quests/soul_war/soul_war_mechanics.lua    |  3 +-
 .../world/otservbr-monster.xml                | 12 +++
 src/creatures/combat/combat.cpp               |  4 +-
 src/creatures/monsters/monster.cpp            |  8 +-
 8 files changed, 101 insertions(+), 52 deletions(-)

diff --git a/data-otservbr-global/monster/quests/soul_war/goshnars_malice.lua b/data-otservbr-global/monster/quests/soul_war/goshnars_malice.lua
index 2d71ff568b2..e0b054dc10d 100644
--- a/data-otservbr-global/monster/quests/soul_war/goshnars_malice.lua
+++ b/data-otservbr-global/monster/quests/soul_war/goshnars_malice.lua
@@ -68,14 +68,6 @@ monster.light = {
 	color = 0,
 }
 
-monster.summon = {
-	maxSummons = 4,
-	summons = {
-		{ name = "dreadful harvester", chance = 40, interval = 1000, count = 2 },
-		{ name = "malicious soul", chance = 30, interval = 1000, count = 2 },
-	},
-}
-
 monster.voices = {
 	interval = 5000,
 	chance = 10,
diff --git a/data-otservbr-global/scripts/lib/quests/soul-war.lua b/data-otservbr-global/scripts/lib/quests/soul-war.lua
index ba44d49943f..e4fcfe4d4bb 100644
--- a/data-otservbr-global/scripts/lib/quests/soul-war.lua
+++ b/data-otservbr-global/scripts/lib/quests/soul-war.lua
@@ -67,6 +67,14 @@ SoulWarQuest = {
 		"Courage Leech",
 	},
 
+	miniBosses = {
+		["Goshnar's Malice"] = true,
+		["Goshnar's Hatred"] = true,
+		["Goshnar's Spite"] = true,
+		["Goshnar's Cruelty"] = true,
+		["Goshnar's Greed"] = true,
+	},
+
 	finalRewards = {
 		{ id = 34082, name = "soulcutter" },
 		{ id = 34083, name = "soulshredder" },
@@ -109,6 +117,28 @@ SoulWarQuest = {
 		{ from = Position(33856, 31884, 5), to = Position(33857, 31865, 6), access = "third-floor-access", count = 70 },
 	},
 
+	areaZones = {
+		monsters = {
+			["zone.claustrophobic-inferno"] = "Brachiodemon",
+			["zone.mirrored-nightmare"] = "Many Faces",
+			["zone.ebb-and-flow"] = "Bony Sea Devil",
+			["zone.furious-crater"] = "Cloak of Terror",
+			["zone.rotten-wasteland"] = "Branchy Crawler",
+			["boss.goshnar's-malice"] = "Dreadful Harvester",
+			["boss.goshnar's-spite"] = "Dreadful Harvester",
+			["boss.goshnar's-greed"] = "Dreadful Harvester",
+			["boss.goshnar's-hatred"] = "Dreadful Harvester",
+			["boss.goshnar's-cruelty"] = "Dreadful Harvester",
+			["boss.goshnar's-megalomania-purple"] = "Dreadful Harvester",
+		},
+
+		caustrophobicInferno = Zone("zone.claustrophobic-inferno"),
+		mirroredNightmare = Zone("zone.mirrored-nightmare"),
+		ebbAndFlow = Zone("zone.ebb-and-flow"),
+		furiousCrater = Zone("zone.furious-crater"),
+		rottenWasteland = Zone("zone.rotten-wasteland"),
+	},
+
 	-- Levers configuration
 	levers = {
 		goshnarsMalicePosition = { x = 33678, y = 31599, z = 14 },
@@ -652,6 +682,17 @@ SoulWarQuest = {
 -- Initialize ebb and flow zone area
 SoulWarQuest.ebbAndFlow.zone:addArea({ x = 33869, y = 30991, z = 8 }, { x = 33964, y = 31147, z = 9 })
 
+-- Initialize bosses access for taint check
+SoulWarQuest.areaZones.caustrophobicInferno:addArea({ x = 33982, y = 30981, z = 9 }, { x = 34051, y = 31110, z = 11 })
+
+SoulWarQuest.areaZones.ebbAndFlow:addArea({ x = 33873, y = 30994, z = 8 }, { x = 33968, y = 31150, z = 9 })
+
+SoulWarQuest.areaZones.furiousCrater:addArea({ x = 33814, y = 31819, z = 3 }, { x = 33907, y = 31920, z = 7 })
+
+SoulWarQuest.areaZones.rottenWasteland:addArea({ x = 33980, y = 30986, z = 11 }, { x = 33901, y = 31105, z = 12 })
+
+SoulWarQuest.areaZones.mirroredNightmare:addArea({ x = 33877, y = 31164, z = 9 }, { x = 33991, y = 31241, z = 13 })
+
 SoulCagePosition = Position(33709, 31596, 14)
 TaintDurationSeconds = 14 * 24 * 60 * 60 -- 14 days
 GreedbeastKills = 0
@@ -674,14 +715,6 @@ local soulWarTaints = {
 	"taints-loss", -- Taint 5
 }
 
-SoulWarBosses = {
-	["Goshnar's Malice"] = true,
-	["Goshnar's Hatred"] = true,
-	["Goshnar's Spite"] = true,
-	["Goshnar's Cruelty"] = true,
-	["Goshnar's Greed"] = true,
-}
-
 GreedMonsters = {
 	["Greedbeast"] = Position(33744, 31666, 14),
 	["Soulsnatcher"] = Position(33747, 31668, 14),
@@ -707,15 +740,6 @@ function CreateGoshnarsGreedMonster(name, position)
 	addEvent(spawnMonster, 10000)
 end
 
-local soulWarSpawnMonsters = {
-	["soulwars.claustrophobic-inferno"] = "Brachiodemon",
-	["soulwars.mirrored-nightmare"] = "Many Faces",
-	["soulwars.ebb-and-flow"] = "Bony Sea Devil",
-	["soulwars.furious-crater"] = "Cloak of Terror",
-	["soulwars.rotten-wasteland"] = "Branchy Crawler",
-	["boss-rooms"] = "Dreadful Harvester",
-}
-
 function RemoveSoulCageAndBuffMalice()
 	local tile = Tile(SoulCagePosition)
 	local creatures = tile:getCreatures() or {}
@@ -832,18 +856,41 @@ end
 
 local toRevertPositions = {}
 
+local tileItemIds = {
+	32906,
+	33066,
+	33067,
+	33068,
+	33069,
+	33070,
+}
+
 local function revertTilesAndApplyDamage(zonePositions)
 	for _, pos in ipairs(zonePositions) do
 		local tile = Tile(pos)
-		if tile and tile:getGround() and tile:getGround():getId() ~= 409 then
-			local creature = tile:getTopCreature()
-			if creature then
-				local player = creature:getPlayer()
-				if player then
-					pos:sendMagicEffect(CONST_ME_REDSMOKE)
-					player:addHealth(-8000, COMBAT_DEATHDAMAGE)
+		if tile and tile:getGround() then
+			if tile:getGround():getId() ~= 409 then
+				local creature = tile:getTopCreature()
+				if creature then
+					local player = creature:getPlayer()
+					if player then
+						player:addHealth(-8000, COMBAT_DEATHDAMAGE)
+					end
 				end
 			end
+
+			local itemFound = false
+			for i = 1, #tileItemIds do
+				local item = tile:getItemById(tileItemIds[i])
+				if item then
+					itemFound = true
+					break
+				end
+			end
+
+			if tile:getGround():getId() == 410 and not itemFound and not tile:getItemByTopOrder(1) and not tile:getItemByTopOrder(3) then
+				pos:sendMagicEffect(CONST_ME_REDSMOKE)
+			end
 		end
 	end
 
@@ -1010,7 +1057,6 @@ function Monster:tryTeleportToPlayer(sayMessage)
 	local spectators = Game.getSpectators(self:getPosition(), false, false, range, range, range, range)
 	local maxDistance = 0
 	local farthestPlayer = nil
-	logger.debug("Checking teleport monster for monster {}", self:getName())
 	for i, spectator in ipairs(spectators) do
 		if spectator:isPlayer() then
 			local player = spectator:getPlayer()
@@ -1200,7 +1246,7 @@ end
 
 function Player:getSoulWarZoneMonster()
 	local zoneMonsterName = nil
-	for zoneName, monsterName in pairs(soulWarSpawnMonsters) do
+	for zoneName, monsterName in pairs(SoulWarQuest.areaZones.monsters) do
 		local zone = Zone.getByName(zoneName)
 		if zone and zone:isInZone(self:getPosition()) then
 			zoneMonsterName = monsterName
diff --git a/data-otservbr-global/scripts/quests/soul_war/eventcallback_on_combat_taint.lua b/data-otservbr-global/scripts/quests/soul_war/eventcallback_on_combat_taint.lua
index 01637f1aff8..3e5ec34f930 100644
--- a/data-otservbr-global/scripts/quests/soul_war/eventcallback_on_combat_taint.lua
+++ b/data-otservbr-global/scripts/quests/soul_war/eventcallback_on_combat_taint.lua
@@ -110,14 +110,13 @@ function callback.playerOnThink(player, interval)
 	accumulatedTime[playerId] = accumulatedTime[playerId] + interval
 
 	if accumulatedTime[playerId] >= 10000 then
-		logger.debug("Checking soul war fifth taint, interval {}", interval)
 		local soulWarQuest = player:soulWarQuestKV()
 		if player:getSoulWarZoneMonster() ~= nil and player:getTaintNameByNumber(5) ~= nil then
 			local hpLoss = math.ceil(player:getHealth() * 0.1)
 			local manaLoss = math.ceil(player:getMana() * 0.1)
 			player:addHealth(-hpLoss)
 			player:addMana(-manaLoss)
-			logger.debug("Removing '{}' mana and '{}' health from player {}", manaLoss, hpLoss, player:getName())
+			logger.debug("Fifth taint removing '{}' mana and '{}' health from player {}", manaLoss, hpLoss, player:getName())
 		end
 
 		accumulatedTime[playerId] = 0
diff --git a/data-otservbr-global/scripts/quests/soul_war/moveevent-soul_war_entrances.lua b/data-otservbr-global/scripts/quests/soul_war/moveevent-soul_war_entrances.lua
index e1728e3a66d..ccf56ea6a3b 100644
--- a/data-otservbr-global/scripts/quests/soul_war/moveevent-soul_war_entrances.lua
+++ b/data-otservbr-global/scripts/quests/soul_war/moveevent-soul_war_entrances.lua
@@ -5,8 +5,6 @@ local positionsTable = {
 	[Position(33621, 31422, 10)] = Position(33894, 31019, 8), -- hunt bony sea devil
 	[Position(33624, 31422, 10)] = Position(33858, 31831, 3), -- hunt cloak
 	[Position(33627, 31422, 10)] = Position(33887, 31188, 10), -- hunt many faces
-
-	[Position(34022, 31091, 11)] = Position(33685, 31599, 14), -- goshnar's malice entrance
 }
 
 local soul_war_entrances = MoveEvent()
@@ -89,22 +87,23 @@ end
 soul_war_megalomania_entrance:position({ x = 33611, y = 31430, z = 10 })
 soul_war_megalomania_entrance:register()
 
-local areasConfig = {
+local claustrophobicInfernoTeleportPositions = {
 	[Position(34013, 31049, 9)] = Position(34014, 31058, 9),
 	[Position(34010, 31073, 10)] = Position(34012, 31063, 10),
 	[Position(34009, 31038, 11)] = Position(34012, 31047, 11),
+	[Position(34022, 31091, 11)] = Position(33685, 31599, 14),
 }
 
-local soul_war_areas_timer = MoveEvent()
+local claustrophobicInfernoTeleports = MoveEvent()
 
-function soul_war_areas_timer.onStepIn(creature, item, position, fromPosition)
+function claustrophobicInfernoTeleports.onStepIn(creature, item, position, fromPosition)
 	local player = creature:getPlayer()
 	if not player then
 		return false
 	end
 
 	local soulWarQuest = player:soulWarQuestKV()
-	for tablePosition, toPosition in pairs(areasConfig) do
+	for tablePosition, toPosition in pairs(claustrophobicInfernoTeleportPositions) do
 		if tablePosition == position then
 			player:teleportTo(toPosition)
 			toPosition:sendMagicEffect(CONST_ME_TELEPORT)
@@ -115,11 +114,11 @@ function soul_war_areas_timer.onStepIn(creature, item, position, fromPosition)
 	return true
 end
 
-for key, value in pairs(areasConfig) do
-	soul_war_areas_timer:position(key)
+for key, value in pairs(claustrophobicInfernoTeleportPositions) do
+	claustrophobicInfernoTeleports:position(key)
 end
 
-soul_war_areas_timer:register()
+claustrophobicInfernoTeleports:register()
 
 local goshnarSpiteEntrance = MoveEvent()
 
diff --git a/data-otservbr-global/scripts/quests/soul_war/soul_war_mechanics.lua b/data-otservbr-global/scripts/quests/soul_war/soul_war_mechanics.lua
index 8daa70f3060..2bbb37b0a6a 100644
--- a/data-otservbr-global/scripts/quests/soul_war/soul_war_mechanics.lua
+++ b/data-otservbr-global/scripts/quests/soul_war/soul_war_mechanics.lua
@@ -117,9 +117,10 @@ local bossesDeath = CreatureEvent("SoulWarBossesDeath")
 
 function bossesDeath.onDeath(creature, corpse, killer, mostDamageKiller, lastHitUnjustified, mostDamageUnjustified)
 	local bossName = creature:getName()
-	if SoulWarBosses[bossName] then
+	if SoulWarQuest.miniBosses[bossName] then
 		local killers = creature:getKillers(true)
 		for i, killerPlayer in ipairs(killers) do
+			logger.debug("Player {} killed the boss.", killerPlayer:getName())
 			local soulWarQuest = killerPlayer:soulWarQuestKV()
 			-- Checks if the boss has already been defeated
 			if not soulWarQuest:get(bossName) then
diff --git a/data-otservbr-global/world/otservbr-monster.xml b/data-otservbr-global/world/otservbr-monster.xml
index 84419e700e7..0a876191095 100644
--- a/data-otservbr-global/world/otservbr-monster.xml
+++ b/data-otservbr-global/world/otservbr-monster.xml
@@ -162049,6 +162049,9 @@
 	<monster centerx="32505" centery="31594" centerz="14" radius="3">
 		<monster name="Warlock" x="0" y="-1" z="14" spawntime="90" />
 	</monster>
+	<monster centerx="33709" centery="31594" centerz="14" radius="1">
+		<monster name="Dreadful Harvester" x="0" y="0" z="14" spawntime="10" />
+	</monster>
 	<monster centerx="33744" centery="31595" centerz="14" radius="1">
 		<monster name="Dreadful Harvester" x="0" y="0" z="14" spawntime="14" />
 	</monster>
@@ -162078,6 +162081,12 @@
 		<monster name="Dark Torturer" x="4" y="5" z="14" spawntime="90" />
 		<monster name="Lost Soul" x="0" y="6" z="14" spawntime="90" />
 	</monster>
+	<monster centerx="33709" centery="31596" centerz="14" radius="1">
+		<monster name="Dreadful Harvester" x="0" y="0" z="14" spawntime="10" />
+	</monster>
+	<monster centerx="33712" centery="31597" centerz="14" radius="1">
+		<monster name="Malicious Soul" x="0" y="0" z="14" spawntime="10" />
+	</monster>
 	<monster centerx="33743" centery="31597" centerz="14" radius="1">
 		<monster name="Hateful Soul" x="0" y="0" z="14" spawntime="14" />
 	</monster>
@@ -162143,6 +162152,9 @@
 		<monster name="Fire Elemental" x="0" y="4" z="14" spawntime="90" />
 		<monster name="Fire Elemental" x="4" y="4" z="14" spawntime="90" />
 	</monster>
+	<monster centerx="33709" centery="31603" centerz="14" radius="1">
+		<monster name="Malicious Soul" x="0" y="0" z="14" spawntime="10" />
+	</monster>
 	<monster centerx="33743" centery="31603" centerz="14" radius="1">
 		<monster name="Hateful Soul" x="0" y="0" z="14" spawntime="14" />
 	</monster>
diff --git a/src/creatures/combat/combat.cpp b/src/creatures/combat/combat.cpp
index 7d6971c0038..244128435f8 100644
--- a/src/creatures/combat/combat.cpp
+++ b/src/creatures/combat/combat.cpp
@@ -584,9 +584,9 @@ void Combat::CombatHealthFunc(std::shared_ptr<Creature> caster, std::shared_ptr<
 		targetPlayer = target->getPlayer();
 	}
 
-	g_logger().debug("[{}] (old) eventcallback: 'creatureOnCombat', damage primary: '{}', secondary: '{}'", __FUNCTION__, damage.primary.value, damage.secondary.value);
+	g_logger().trace("[{}] (old) eventcallback: 'creatureOnCombat', damage primary: '{}', secondary: '{}'", __FUNCTION__, damage.primary.value, damage.secondary.value);
 	g_callbacks().executeCallback(EventCallback_t::creatureOnCombat, &EventCallback::creatureOnCombat, caster, target, std::ref(damage));
-	g_logger().debug("[{}] (new) eventcallback: 'creatureOnCombat', damage primary: '{}', secondary: '{}'", __FUNCTION__, damage.primary.value, damage.secondary.value);
+	g_logger().trace("[{}] (new) eventcallback: 'creatureOnCombat', damage primary: '{}', secondary: '{}'", __FUNCTION__, damage.primary.value, damage.secondary.value);
 
 	if (attackerPlayer) {
 		std::shared_ptr<Item> item = attackerPlayer->getWeapon();
diff --git a/src/creatures/monsters/monster.cpp b/src/creatures/monsters/monster.cpp
index 9d24b9cc4f3..2bf7edd75ac 100644
--- a/src/creatures/monsters/monster.cpp
+++ b/src/creatures/monsters/monster.cpp
@@ -113,19 +113,19 @@ void Monster::addReflectElement(CombatType_t combatType, int32_t percent) {
 int32_t Monster::getDefense() const {
 	auto mtypeDefense = mType->info.defense;
 	if (mtypeDefense != 0) {
-		g_logger().debug("[{}] old defense {}", __FUNCTION__, mtypeDefense);
+		g_logger().trace("[{}] old defense {}", __FUNCTION__, mtypeDefense);
 	}
 	mtypeDefense += m_defense;
 	if (mtypeDefense != 0) {
-		g_logger().debug("[{}] new defense {}", __FUNCTION__, mtypeDefense);
+		g_logger().trace("[{}] new defense {}", __FUNCTION__, mtypeDefense);
 	}
 	return mtypeDefense * getDefenseMultiplier();
 }
 
 void Monster::addDefense(int32_t defense) {
-	g_logger().debug("[{}] adding defense {}", __FUNCTION__, defense);
+	g_logger().trace("[{}] adding defense {}", __FUNCTION__, defense);
 	m_defense += defense;
-	g_logger().debug("[{}] new defense {}", __FUNCTION__, m_defense);
+	g_logger().trace("[{}] new defense {}", __FUNCTION__, m_defense);
 }
 
 uint32_t Monster::getHealingCombatValue(CombatType_t healingType) const {

From 715f127488dd74732617d37f10e9ba09d62f7310 Mon Sep 17 00:00:00 2001
From: Eduardo Dantas <eduardo.dantas@hotmail.com.br>
Date: Wed, 10 Apr 2024 22:27:31 -0300
Subject: [PATCH 03/60] fix: ebb and flow fixed map

---
 .../scripts/lib/quests/soul-war.lua           |   5 +-
 .../globalevent-ebb_and_flow_change_maps.lua  |   3 +
 .../soul_war/ebb_and_flow/ebb-flow-house.xml  |   2 +
 .../ebb_and_flow/ebb-flow-monster.xml         | 541 ++++++++++++++++++
 .../soul_war/ebb_and_flow/ebb-flow-npc.xml    |   2 +
 .../soul_war/ebb_and_flow/ebb-flow-zones.xml  |   2 +
 .../quest/soul_war/ebb_and_flow/ebb-flow.otbm | Bin 0 -> 181554 bytes
 7 files changed, 553 insertions(+), 2 deletions(-)
 create mode 100644 data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-house.xml
 create mode 100644 data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-monster.xml
 create mode 100644 data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-npc.xml
 create mode 100644 data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-zones.xml
 create mode 100644 data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow.otbm

diff --git a/data-otservbr-global/scripts/lib/quests/soul-war.lua b/data-otservbr-global/scripts/lib/quests/soul-war.lua
index e4fcfe4d4bb..167d33eddc8 100644
--- a/data-otservbr-global/scripts/lib/quests/soul-war.lua
+++ b/data-otservbr-global/scripts/lib/quests/soul-war.lua
@@ -344,6 +344,7 @@ SoulWarQuest = {
 		mapsPath = {
 			empty = "data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-empty.otbm",
 			inundate = "data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-inundate.otbm",
+			ebbFlow = "data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow.otbm",
 		},
 
 		-- In Minutes
@@ -1060,12 +1061,12 @@ function Monster:tryTeleportToPlayer(sayMessage)
 	for i, spectator in ipairs(spectators) do
 		if spectator:isPlayer() then
 			local player = spectator:getPlayer()
-			if player:getTaintNameByNumber(1) ~= nil then
+			if player:getTaintNameByNumber(1) then
 				local distance = self:getPosition():getDistance(player:getPosition())
 				if distance > maxDistance then
 					maxDistance = distance
 					farthestPlayer = player
-					logger.debug("Found player {} to teleport", player:getName())
+					logger.trace("Found player {} to teleport", player:getName())
 				end
 			end
 		end
diff --git a/data-otservbr-global/scripts/quests/soul_war/globalevent-ebb_and_flow_change_maps.lua b/data-otservbr-global/scripts/quests/soul_war/globalevent-ebb_and_flow_change_maps.lua
index 7bc644448b3..7d2a64ef19c 100644
--- a/data-otservbr-global/scripts/quests/soul_war/globalevent-ebb_and_flow_change_maps.lua
+++ b/data-otservbr-global/scripts/quests/soul_war/globalevent-ebb_and_flow_change_maps.lua
@@ -108,7 +108,9 @@ local function loadMapInundate()
 end
 
 local loadEmptyMap = GlobalEvent("SoulWarQuest.ebbAndFlow")
+
 function loadEmptyMap.onStartup()
+	Game.loadMap(SoulWarQuest.ebbAndFlow.mapsPath.ebbFlow)
 	loadMapEmpty()
 	SoulWarQuest.ebbAndFlow.updateZonePlayers()
 end
@@ -116,6 +118,7 @@ end
 loadEmptyMap:register()
 
 local eddAndFlowInundate = GlobalEvent("eddAndFlowInundate")
+
 function eddAndFlowInundate.onThink(interval, lastExecution)
 	if SoulWarQuest.ebbAndFlow.isLoadedEmptyMap() then
 		logger.debug("Map change to empty in {} minutes.", SoulWarQuest.ebbAndFlow.intervalChangeMap)
diff --git a/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-house.xml b/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-house.xml
new file mode 100644
index 00000000000..e5a6b86118e
--- /dev/null
+++ b/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-house.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0"?>
+<houses />
diff --git a/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-monster.xml b/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-monster.xml
new file mode 100644
index 00000000000..a476474dd74
--- /dev/null
+++ b/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-monster.xml
@@ -0,0 +1,541 @@
+<?xml version="1.0"?>
+<monsters>
+	<monster centerx="33934" centery="31014" centerz="8" radius="1">
+		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33939" centery="31014" centerz="8" radius="1">
+		<monster name="Capricious Phantom" x="1" y="1" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33944" centery="31014" centerz="8" radius="1">
+		<monster name="Turbulent Elemental" x="1" y="1" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33930" centery="31015" centerz="8" radius="1">
+		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33940" centery="31018" centerz="8" radius="1">
+		<monster name="Hazardous Phantom" x="1" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33931" centery="31019" centerz="8" radius="1">
+		<monster name="Hazardous Phantom" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33934" centery="31020" centerz="8" radius="1">
+		<monster name="Turbulent Elemental" x="0" y="1" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33941" centery="31025" centerz="8" radius="1">
+		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33931" centery="31027" centerz="8" radius="1">
+		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33911" centery="31037" centerz="8" radius="1">
+		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33891" centery="31038" centerz="8" radius="1">
+		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33913" centery="31038" centerz="8" radius="1">
+		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33891" centery="31040" centerz="8" radius="1">
+		<monster name="Hazardous Phantom" x="-1" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33931" centery="31041" centerz="8" radius="1">
+		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33934" centery="31041" centerz="8" radius="1">
+		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33940" centery="31041" centerz="8" radius="1">
+		<monster name="Capricious Phantom" x="1" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33911" centery="31042" centerz="8" radius="1">
+		<monster name="Capricious Phantom" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33891" centery="31043" centerz="8" radius="1">
+		<monster name="Capricious Phantom" x="1" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33938" centery="31043" centerz="8" radius="1">
+		<monster name="Hazardous Phantom" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33908" centery="31044" centerz="8" radius="1">
+		<monster name="Hazardous Phantom" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33930" centery="31044" centerz="8" radius="1">
+		<monster name="Hazardous Phantom" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33934" centery="31044" centerz="8" radius="1">
+		<monster name="Bony Sea Devil" x="0" y="1" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33901" centery="31045" centerz="8" radius="1">
+		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33936" centery="31047" centerz="8" radius="1">
+		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33898" centery="31049" centerz="8" radius="1">
+		<monster name="Capricious Phantom" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33902" centery="31049" centerz="8" radius="1">
+		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33908" centery="31049" centerz="8" radius="1">
+		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33912" centery="31049" centerz="8" radius="1">
+		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33892" centery="31050" centerz="8" radius="1">
+		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33896" centery="31050" centerz="8" radius="1">
+		<monster name="Hazardous Phantom" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33933" centery="31050" centerz="8" radius="1">
+		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33937" centery="31050" centerz="8" radius="1">
+		<monster name="Capricious Phantom" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33940" centery="31050" centerz="8" radius="1">
+		<monster name="Turbulent Elemental" x="-1" y="1" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33930" centery="31051" centerz="8" radius="1">
+		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33930" centery="31064" centerz="8" radius="1">
+		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33941" centery="31064" centerz="8" radius="1">
+		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33937" centery="31067" centerz="8" radius="1">
+		<monster name="Hazardous Phantom" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33897" centery="31068" centerz="8" radius="1">
+		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33931" centery="31068" centerz="8" radius="1">
+		<monster name="Capricious Phantom" x="-1" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33895" centery="31069" centerz="8" radius="1">
+		<monster name="Hazardous Phantom" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33903" centery="31069" centerz="8" radius="1">
+		<monster name="Turbulent Elemental" x="1" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33941" centery="31069" centerz="8" radius="1">
+		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33928" centery="31071" centerz="8" radius="1">
+		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33923" centery="31072" centerz="8" radius="1">
+		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33933" centery="31072" centerz="8" radius="1">
+		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33897" centery="31073" centerz="8" radius="1">
+		<monster name="Capricious Phantom" x="1" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33928" centery="31075" centerz="8" radius="1">
+		<monster name="Hazardous Phantom" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33906" centery="31076" centerz="8" radius="1">
+		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33897" centery="31077" centerz="8" radius="1">
+		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33939" centery="31077" centerz="8" radius="1">
+		<monster name="Capricious Phantom" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33905" centery="31079" centerz="8" radius="1">
+		<monster name="Hazardous Phantom" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33935" centery="31080" centerz="8" radius="1">
+		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33938" centery="31081" centerz="8" radius="1">
+		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33903" centery="31082" centerz="8" radius="1">
+		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33933" centery="31083" centerz="8" radius="1">
+		<monster name="Bony Sea Devil" x="0" y="1" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33909" centery="31085" centerz="8" radius="1">
+		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33900" centery="31088" centerz="8" radius="1">
+		<monster name="Capricious Phantom" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33895" centery="31090" centerz="8" radius="1">
+		<monster name="Hazardous Phantom" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33900" centery="31092" centerz="8" radius="1">
+		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33894" centery="31095" centerz="8" radius="1">
+		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33932" centery="31098" centerz="8" radius="1">
+		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33923" centery="31099" centerz="8" radius="1">
+		<monster name="Hazardous Phantom" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33933" centery="31100" centerz="8" radius="1">
+		<monster name="Capricious Phantom" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33926" centery="31101" centerz="8" radius="1">
+		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33929" centery="31101" centerz="8" radius="1">
+		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33924" centery="31104" centerz="8" radius="1">
+		<monster name="Capricious Phantom" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33928" centery="31106" centerz="8" radius="1">
+		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33921" centery="31107" centerz="8" radius="1">
+		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33906" centery="31108" centerz="8" radius="1">
+		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33901" centery="31110" centerz="8" radius="1">
+		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33905" centery="31110" centerz="8" radius="1">
+		<monster name="Capricious Phantom" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33897" centery="31111" centerz="8" radius="1">
+		<monster name="Hazardous Phantom" x="1" y="1" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33921" centery="31111" centerz="8" radius="1">
+		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33900" centery="31114" centerz="8" radius="1">
+		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33925" centery="31114" centerz="8" radius="1">
+		<monster name="Hazardous Phantom" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33905" centery="31115" centerz="8" radius="1">
+		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33921" centery="31115" centerz="8" radius="1">
+		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33929" centery="31116" centerz="8" radius="1">
+		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33898" centery="31118" centerz="8" radius="1">
+		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33905" centery="31119" centerz="8" radius="1">
+		<monster name="Hazardous Phantom" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33899" centery="31122" centerz="8" radius="1">
+		<monster name="Capricious Phantom" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33906" centery="31122" centerz="8" radius="1">
+		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33898" centery="31124" centerz="8" radius="1">
+		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
+	</monster>
+	<monster centerx="33889" centery="31009" centerz="9" radius="5">
+		<monster name="Bony Sea Devil" x="2" y="1" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="5" y="1" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="1" y="3" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="3" y="3" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="0" y="4" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="5" y="4" z="9" spawntime="60" />
+	</monster>
+	<monster centerx="33908" centery="31009" centerz="9" radius="5">
+		<monster name="Bony Sea Devil" x="3" y="-1" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="-2" y="1" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="1" y="1" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="-4" y="2" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="-2" y="3" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="0" y="3" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="3" y="3" z="9" spawntime="60" />
+	</monster>
+	<monster centerx="33941" centery="31009" centerz="9" radius="1">
+		<monster name="Bony Sea Devil" x="1" y="1" z="9" spawntime="60" />
+	</monster>
+	<monster centerx="33944" centery="31010" centerz="9" radius="1">
+		<monster name="Capricious Phantom" x="1" y="0" z="9" spawntime="60" />
+	</monster>
+	<monster centerx="33923" centery="31012" centerz="9" radius="1">
+		<monster name="Bony Sea Devil" x="-1" y="1" z="9" spawntime="60" />
+	</monster>
+	<monster centerx="33930" centery="31015" centerz="9" radius="5">
+		<monster name="Turbulent Elemental" x="-3" y="-3" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="0" y="-3" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="3" y="-2" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="-3" y="0" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="3" y="2" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="-4" y="3" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="-1" y="3" z="9" spawntime="60" />
+	</monster>
+	<monster centerx="33939" centery="31020" centerz="9" radius="5">
+		<monster name="Capricious Phantom" x="1" y="-3" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="4" y="-2" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="-3" y="1" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="3" y="1" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="-2" y="3" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="2" y="4" z="9" spawntime="60" />
+	</monster>
+	<monster centerx="33896" centery="31027" centerz="9" radius="5">
+		<monster name="Bony Sea Devil" x="1" y="-2" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="4" y="-2" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="-4" y="-1" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="-1" y="1" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="3" y="2" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="1" y="4" z="9" spawntime="60" />
+	</monster>
+	<monster centerx="33919" centery="31027" centerz="9" radius="5">
+		<monster name="Turbulent Elemental" x="0" y="-4" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="2" y="-4" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="-2" y="-2" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="3" y="-1" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="-2" y="1" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="2" y="2" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="-3" y="3" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="0" y="4" z="9" spawntime="60" />
+	</monster>
+	<monster centerx="33891" centery="31028" centerz="9" radius="1">
+		<monster name="Bony Sea Devil" x="-1" y="1" z="9" spawntime="60" />
+	</monster>
+	<monster centerx="33940" centery="31031" centerz="9" radius="5">
+		<monster name="Capricious Phantom" x="3" y="-3" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="-3" y="-1" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="-1" y="-1" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="3" y="0" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="-1" y="2" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="3" y="2" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="-4" y="3" z="9" spawntime="60" />
+	</monster>
+	<monster centerx="33891" centery="31038" centerz="9" radius="1">
+		<monster name="Turbulent Elemental" x="0" y="1" z="9" spawntime="60" />
+	</monster>
+	<monster centerx="33911" centery="31038" centerz="9" radius="1">
+		<monster name="Turbulent Elemental" x="0" y="0" z="9" spawntime="60" />
+	</monster>
+	<monster centerx="33933" centery="31044" centerz="9" radius="5">
+		<monster name="Turbulent Elemental" x="0" y="-3" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="2" y="-3" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="-3" y="-2" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="1" y="1" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="-2" y="2" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="-4" y="3" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="3" y="3" z="9" spawntime="60" />
+	</monster>
+	<monster centerx="33945" centery="31044" centerz="9" radius="1">
+		<monster name="Bony Sea Devil" x="0" y="0" z="9" spawntime="60" />
+	</monster>
+	<monster centerx="33891" centery="31045" centerz="9" radius="5">
+		<monster name="Capricious Phantom" x="0" y="-3" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="-1" y="-1" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="1" y="0" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="-1" y="2" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="1" y="2" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="-3" y="4" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="1" y="4" z="9" spawntime="60" />
+	</monster>
+	<monster centerx="33910" centery="31045" centerz="9" radius="5">
+		<monster name="Bony Sea Devil" x="-3" y="-3" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="0" y="-2" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="3" y="-2" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="-2" y="0" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="1" y="3" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="-1" y="5" z="9" spawntime="60" />
+	</monster>
+	<monster centerx="33919" centery="31047" centerz="9" radius="1">
+		<monster name="Bony Sea Devil" x="0" y="0" z="9" spawntime="60" />
+	</monster>
+	<monster centerx="33930" centery="31057" centerz="9" radius="5">
+		<monster name="Capricious Phantom" x="-1" y="-4" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="2" y="-3" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="4" y="-3" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="-3" y="-1" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="5" y="-1" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="3" y="1" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="-1" y="2" z="9" spawntime="60" />
+	</monster>
+	<monster centerx="33910" centery="31064" centerz="9" radius="5">
+		<monster name="Bony Sea Devil" x="-2" y="-3" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="3" y="-3" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="-2" y="1" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="4" y="1" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="0" y="3" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="-3" y="4" z="9" spawntime="60" />
+	</monster>
+	<monster centerx="33889" centery="31066" centerz="9" radius="1">
+		<monster name="Bony Sea Devil" x="1" y="1" z="9" spawntime="60" />
+	</monster>
+	<monster centerx="33930" centery="31066" centerz="9" radius="5">
+		<monster name="Bony Sea Devil" x="0" y="-3" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="-3" y="-1" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="2" y="-1" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="3" y="1" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="-3" y="2" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="-1" y="4" z="9" spawntime="60" />
+	</monster>
+	<monster centerx="33895" centery="31067" centerz="9" radius="5">
+		<monster name="Turbulent Elemental" x="-1" y="-3" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="3" y="-3" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="-2" y="-2" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="2" y="0" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="-2" y="3" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="1" y="3" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="3" y="3" z="9" spawntime="60" />
+	</monster>
+	<monster centerx="33889" centery="31071" centerz="9" radius="1">
+		<monster name="Turbulent Elemental" x="0" y="0" z="9" spawntime="60" />
+	</monster>
+	<monster centerx="33945" centery="31073" centerz="9" radius="1">
+		<monster name="Bony Sea Devil" x="1" y="-1" z="9" spawntime="60" />
+	</monster>
+	<monster centerx="33906" centery="31077" centerz="9" radius="5">
+		<monster name="Bony Sea Devil" x="2" y="-3" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="-1" y="-2" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="-4" y="0" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="-1" y="1" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="3" y="3" z="9" spawntime="60" />
+	</monster>
+	<monster centerx="33895" centery="31078" centerz="9" radius="5">
+		<monster name="Capricious Phantom" x="-2" y="-2" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="2" y="-2" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="3" y="1" z="9" spawntime="60" />
+	</monster>
+	<monster centerx="33937" centery="31078" centerz="9" radius="5">
+		<monster name="Turbulent Elemental" x="-3" y="-3" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="-1" y="-3" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="3" y="-3" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="-3" y="0" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="3" y="0" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="3" y="3" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="-3" y="4" z="9" spawntime="60" />
+	</monster>
+	<monster centerx="33921" centery="31083" centerz="9" radius="5">
+		<monster name="Turbulent Elemental" x="-1" y="-4" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="-3" y="-3" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="2" y="-2" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="4" y="0" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="-3" y="1" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="2" y="2" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="0" y="4" z="9" spawntime="60" />
+	</monster>
+	<monster centerx="33889" centery="31084" centerz="9" radius="1">
+		<monster name="Capricious Phantom" x="0" y="1" z="9" spawntime="60" />
+	</monster>
+	<monster centerx="33895" centery="31089" centerz="9" radius="5">
+		<monster name="Turbulent Elemental" x="3" y="-4" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="0" y="-3" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="-3" y="-2" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="2" y="-2" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="-4" y="1" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="2" y="2" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="-1" y="3" z="9" spawntime="60" />
+	</monster>
+	<monster centerx="33941" centery="31093" centerz="9" radius="5">
+		<monster name="Turbulent Elemental" x="4" y="-4" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="-3" y="-3" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="0" y="-2" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="2" y="-2" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="-2" y="0" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="3" y="3" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="-2" y="4" z="9" spawntime="60" />
+	</monster>
+	<monster centerx="33908" centery="31095" centerz="9" radius="5">
+		<monster name="Turbulent Elemental" x="4" y="-4" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="1" y="-3" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="-3" y="-2" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="-1" y="1" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="4" y="1" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="-1" y="4" z="9" spawntime="60" />
+	</monster>
+	<monster centerx="33890" centery="31098" centerz="9" radius="1">
+		<monster name="Bony Sea Devil" x="0" y="1" z="9" spawntime="60" />
+	</monster>
+	<monster centerx="33922" centery="31100" centerz="9" radius="5">
+		<monster name="Capricious Phantom" x="-2" y="-3" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="2" y="-3" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="-4" y="-2" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="3" y="0" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="-2" y="2" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="3" y="3" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="-1" y="4" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="1" y="4" z="9" spawntime="60" />
+	</monster>
+	<monster centerx="33897" centery="31109" centerz="9" radius="5">
+		<monster name="Bony Sea Devil" x="-4" y="-3" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="0" y="-3" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="4" y="-3" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="2" y="0" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="-3" y="4" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="-1" y="4" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="3" y="5" z="9" spawntime="60" />
+	</monster>
+	<monster centerx="33926" centery="31114" centerz="9" radius="5">
+		<monster name="Turbulent Elemental" x="0" y="-4" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="-3" y="-2" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="1" y="-2" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="3" y="-2" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="-2" y="0" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="4" y="2" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="-2" y="3" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="1" y="3" z="9" spawntime="60" />
+	</monster>
+	<monster centerx="33893" centery="31117" centerz="9" radius="5">
+		<monster name="Turbulent Elemental" x="-4" y="-3" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="-4" y="0" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="1" y="1" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="-4" y="2" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="-2" y="3" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="-4" y="4" z="9" spawntime="60" />
+	</monster>
+	<monster centerx="33904" centery="31120" centerz="9" radius="5">
+		<monster name="Capricious Phantom" x="-1" y="-4" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="3" y="-4" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="0" y="-1" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="2" y="-1" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="-3" y="1" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="0" y="3" z="9" spawntime="60" />
+	</monster>
+	<monster centerx="33941" centery="31123" centerz="9" radius="5">
+		<monster name="Capricious Phantom" x="0" y="-3" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="2" y="-3" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="-3" y="-2" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="3" y="-1" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="-3" y="1" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="3" y="1" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="0" y="4" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="3" y="4" z="9" spawntime="60" />
+	</monster>
+	<monster centerx="33916" centery="31125" centerz="9" radius="5">
+		<monster name="Turbulent Elemental" x="-4" y="-3" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="0" y="-3" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="1" y="-2" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="5" y="0" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="-1" y="1" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="3" y="3" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="-4" y="4" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="1" y="4" z="9" spawntime="60" />
+	</monster>
+	<monster centerx="33896" centery="31128" centerz="9" radius="5">
+		<monster name="Turbulent Elemental" x="-4" y="-2" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="-2" y="-1" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="-1" y="-1" z="9" spawntime="60" />
+		<monster name="Capricious Phantom" x="-1" y="1" z="9" spawntime="60" />
+		<monster name="Bony Sea Devil" x="4" y="1" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="-4" y="2" z="9" spawntime="60" />
+	</monster>
+</monsters>
diff --git a/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-npc.xml b/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-npc.xml
new file mode 100644
index 00000000000..af7984e2faf
--- /dev/null
+++ b/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-npc.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0"?>
+<npcs />
diff --git a/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-zones.xml b/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-zones.xml
new file mode 100644
index 00000000000..a9224bd3c2d
--- /dev/null
+++ b/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-zones.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0"?>
+<zones />
diff --git a/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow.otbm b/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow.otbm
new file mode 100644
index 0000000000000000000000000000000000000000..7fbac6bb391d7259a4e6c818564a58b83570a320
GIT binary patch
literal 181554
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

literal 0
HcmV?d00001


From 535503bb419741d624c56b79ae3236ad50d32db6 Mon Sep 17 00:00:00 2001
From: Eduardo Dantas <eduardo.dantas@hotmail.com.br>
Date: Wed, 10 Apr 2024 22:48:04 -0300
Subject: [PATCH 04/60] fix: simplify some functions, logs to trace and map
 fixes

---
 .../scripts/lib/quests/soul-war.lua           |  81 ++++++------------
 .../quests/soul_war/soul_war_mechanics.lua    |  43 +++-------
 .../ebb_and_flow/ebb-flow-empty-house.xml     |   2 +
 .../ebb_and_flow/ebb-flow-empty-monster.xml   |   2 +
 .../ebb_and_flow/ebb-flow-empty-npc.xml       |   2 +
 .../soul_war/ebb_and_flow/ebb-flow-empty.otbm | Bin 129535 -> 129560 bytes
 .../ebb_and_flow/ebb-flow-inundate-house.xml  |   2 +
 .../ebb-flow-inundate-monster.xml             |   2 +
 .../ebb_and_flow/ebb-flow-inundate-npc.xml    |   2 +
 .../ebb_and_flow/ebb-flow-inundate.otbm       | Bin 323339 -> 322942 bytes
 .../quest/soul_war/ebb_and_flow/ebb-flow.otbm | Bin 181554 -> 181546 bytes
 .../monsters/spawns/spawn_monster.cpp         |   2 +-
 12 files changed, 49 insertions(+), 89 deletions(-)
 create mode 100644 data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-empty-house.xml
 create mode 100644 data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-empty-monster.xml
 create mode 100644 data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-empty-npc.xml
 create mode 100644 data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-inundate-house.xml
 create mode 100644 data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-inundate-monster.xml
 create mode 100644 data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-inundate-npc.xml

diff --git a/data-otservbr-global/scripts/lib/quests/soul-war.lua b/data-otservbr-global/scripts/lib/quests/soul-war.lua
index 167d33eddc8..4a8a47ee131 100644
--- a/data-otservbr-global/scripts/lib/quests/soul-war.lua
+++ b/data-otservbr-global/scripts/lib/quests/soul-war.lua
@@ -242,7 +242,7 @@ SoulWarQuest = {
 			timeToFightAgain = 20 * 60 * 60, -- 20 hours
 			onUseExtra = function(player)
 				SoulWarQuest.kvBurning:set("time", 180)
-				logger.debug("Goshnar's Hatred burning change form time set to: {}", 180)
+				logger.trace("Goshnar's Hatred burning change form time set to: {}", 180)
 				player:resetGoshnarSymbolTormentCounter()
 			end,
 		},
@@ -378,7 +378,7 @@ SoulWarQuest = {
 				SoulWarQuest.ebbAndFlow.reloadZone()
 				local players = SoulWarQuest.ebbAndFlow.getZone():getPlayers()
 				for _, player in ipairs(players) do
-					logger.debug("Updating player: {}", player:getName())
+					logger.trace("Updating player: {}", player:getName())
 					player:sendCreatureAppear()
 				end
 			end
@@ -731,7 +731,7 @@ function CreateGoshnarsGreedMonster(name, position)
 
 	local function spawnMonster()
 		Game.createMonster(name, position, true, false)
-		logger.debug("Spawning {} in position {}", name, position:toString())
+		logger.trace("Spawning {} in position {}", name, position:toString())
 	end
 
 	for i = 7, 9 do
@@ -742,39 +742,13 @@ function CreateGoshnarsGreedMonster(name, position)
 end
 
 function RemoveSoulCageAndBuffMalice()
-	local tile = Tile(SoulCagePosition)
-	local creatures = tile:getCreatures() or {}
-	local soulCage
-	for i, creature in ipairs(creatures) do
-		if creature:getName() == "Soul Cage" then
-			soulCage = creature
-			logger.debug("Removing Soul Cage, the players not be able to kill him")
-			break
-		end
-	end
-
-	local rangeX = 20
-	local rangeY = 20
-	local spectators = Game.getSpectators(Position(33709, 31599, 14), false, false, rangeX, rangeX, rangeY, rangeY)
+	local soulCage = Creature("Soul Cage")
 	if soulCage then
-		local malice
-		for i = 1, #spectators do
-			logger.debug("Specs found {}", i)
-			if spectators[i]:isMonster() then
-				logger.debug("Malice Spectators {}", spectators[i]:getName())
-				if spectators[i]:getName() == "Goshnar's Malice" then
-					logger.debug("Found malice")
-					malice = Monster(spectators[i])
-					break
-				end
-			end
-		end
-
 		soulCage:remove()
 		addEvent(SpawnSoulCage, 23000)
-
+		local malice = Creature("Goshnar's Malice")
 		if malice then
-			logger.debug("Found malice, try adding reflect and defense")
+			logger.trace("Found malice, try adding reflect and defense")
 			for elementType, reflectPercent in pairs(SoulWarReflectDamageMap) do
 				malice:addReflectElement(elementType, reflectPercent)
 			end
@@ -786,17 +760,10 @@ end
 function SpawnSoulCage()
 	local tile = Tile(SoulCagePosition)
 	local creatures = tile:getCreatures() or {}
-	local soulCage
-	for i, creature in ipairs(creatures) do
-		if creature:getName() == "Soul Cage" then
-			soulCage = true
-			break
-		end
-	end
-
+	local soulCage = Creature("Soul Cage")
 	if not soulCage then
 		Game.createMonster("Soul Cage", SoulCagePosition, true, true)
-		logger.debug("Spawning Soul Cage in position {}", SoulCagePosition:toString())
+		logger.trace("Spawning Soul Cage in position {}", SoulCagePosition:toString())
 		addEvent(RemoveSoulCageAndBuffMalice, 40000)
 	end
 end
@@ -966,7 +933,7 @@ function Monster:generateBagYouDesireLoot(player)
 
 	-- Calculates the chances based on the number of taints
 	local totalChance = SoulWarQuest.baseBagYouDesireChance + (playerTaintLevel * SoulWarQuest.bagYouDesireChancePerTaint)
-	logger.debug("Player {} killed {} and has {} taints, loot chance {}", player:getName(), monsterName, playerTaintLevel, totalChance)
+	logger.trace("Player {} killed {} and has {} taints, loot chance {}", player:getName(), monsterName, playerTaintLevel, totalChance)
 	-- Generate loot
 	local loot = {}
 	if math.random(1, 100) <= totalChance then
@@ -1075,14 +1042,14 @@ function Monster:tryTeleportToPlayer(sayMessage)
 	if farthestPlayer and math.random(100) <= 10 then
 		local playerPosition = farthestPlayer:getPosition()
 		if TaintTeleportCooldown[farthestPlayer:getId()] then
-			logger.debug("Cooldown is active to player {}", farthestPlayer:getName())
+			logger.trace("Cooldown is active to player {}", farthestPlayer:getName())
 			return
 		end
 
 		if not TaintTeleportCooldown[farthestPlayer:getId()] then
 			TaintTeleportCooldown[farthestPlayer:getId()] = true
 
-			logger.debug("Scheduling player {} to teleport", farthestPlayer:getName())
+			logger.trace("Scheduling player {} to teleport", farthestPlayer:getName())
 			self:getPosition():sendMagicEffect(CONST_ME_MORTAREA)
 			farthestPlayer:getPosition():sendMagicEffect(CONST_ME_MORTAREA)
 			addEvent(function(playerId, monsterId)
@@ -1105,7 +1072,7 @@ function Monster:tryTeleportToPlayer(sayMessage)
 					return
 				end
 
-				logger.debug("Cleaning player cooldown")
+				logger.trace("Cleaning player cooldown")
 				TaintTeleportCooldown[playerEvent:getId()] = nil
 			end, 10000, farthestPlayer:getId())
 		end
@@ -1138,7 +1105,7 @@ function Position:increaseNecromaticMegalomaniaStrength()
 			if boss then
 				boss:increaseHatredDamageMultiplier(5)
 				item:remove()
-				logger.debug("Necromantic remains strength increased")
+				logger.trace("Necromantic remains strength increased")
 			end
 		end
 	end
@@ -1170,14 +1137,14 @@ function Monster:onThinkGoshnarTormentCounter(interval, maxLimit, intervalBetwee
 	end
 
 	lastExecutionTime = interval
-	logger.debug("Icon time count {}", interval)
+	logger.trace("Icon time count {}", interval)
 	local spectators = Game.getSpectators(bossPosition, false, true, 15, 15, 15, 15)
 	for i = 1, #spectators do
 		local player = spectators[i]
 		local tormentCounter = player:getGoshnarSymbolTormentCounter()
 		if tormentCounter <= maxLimit then
 			player:increaseGoshnarSymbolTormentCounter(maxLimit)
-			logger.debug("Player {} has {} damage counter", player:getName(), tormentCounter)
+			logger.trace("Player {} has {} damage counter", player:getName(), tormentCounter)
 
 			if tormentCounter > 0 then
 				local damage = tormentCounter * 35
@@ -1185,7 +1152,7 @@ function Monster:onThinkGoshnarTormentCounter(interval, maxLimit, intervalBetwee
 					damage = damageTable[tormentCounter - 23]
 				end
 
-				logger.debug("Final damage {}", damage)
+				logger.trace("Final damage {}", damage)
 				player:addHealth(-damage, COMBAT_DEATHDAMAGE)
 				player:getPosition():sendMagicEffect(CONST_ME_PINK_ENERGY_SPARK)
 			end
@@ -1209,19 +1176,19 @@ function Monster:increaseAspectOfPowerDeathCount()
 	local bossKV = self:getSoulWarKV()
 	local aspectDeathCount = bossKV:get("aspect-of-power-death-count") or 0
 	local newCount = aspectDeathCount + 1
-	logger.debug("Aspect of Power death count {}", newCount)
+	logger.trace("Aspect of Power death count {}", newCount)
 	bossKV:set("aspect-of-power-death-count", newCount)
 	if newCount == 4 then
 		self:setType("Goshnar's Megalomania Green")
 		self:say("THE DEATH OF ASPECTS DIMINISHES GOSHNAR'S POWER AND HE TURNS VULNERABLE!")
 		bossKV:set("aspect-of-power-death-count", 0)
-		logger.debug("Aspect of Power defeated all and Megalomania is now vulnerable, reseting death count.")
+		logger.trace("Aspect of Power defeated all and Megalomania is now vulnerable, reseting death count.")
 		SoulWarQuest.changePurpleEvent = addEvent(function()
 			local boss = Creature("Goshnar's Megalomania")
 			if boss and boss:getTypeName() == "Goshnar's Megalomania Green" then
 				boss:setType("Goshnar's Megalomania Purple")
 				boss:say("GOSHNAR REGAINED ENOUGH POWER TO TURN INVULNERABLE AGAIN!")
-				logger.debug("Megalomania is now immune again")
+				logger.trace("Megalomania is now immune again")
 			end
 		end, SoulWarQuest.timeToReturnImmuneMegalomania * 1000)
 	end
@@ -1233,15 +1200,15 @@ function Monster:goshnarsDefenseIncrease(kvName)
 	local lastItemUseTime = SoulWarQuest.kvSoulWar:get(kvName) or 0
 	-- Checks if more than config time have passed since the item was last used.
 	if currentTime >= lastItemUseTime + SoulWarQuest.timeToIncreaseCrueltyDefense then
-		logger.debug("{} old defense {}", self:getName(), self:getDefense())
+		logger.trace("{} old defense {}", self:getName(), self:getDefense())
 		self:addDefense(SoulWarQuest.goshnarsCrueltyDefenseChange)
-		logger.debug("{} new defense {}", self:getName(), self:getDefense())
+		logger.trace("{} new defense {}", self:getName(), self:getDefense())
 
 		--- Updates the KV to reflect the timing of the increase to maintain control.
 		SoulWarQuest.kvSoulWar:set(kvName, currentTime)
 	else
 		-- If config time have not passed, logs the increase has been skipped.
-		logger.debug("{} skips increase cooldown due to recent item use.", self:getName())
+		logger.trace("{} skips increase cooldown due to recent item use.", self:getName())
 	end
 end
 
@@ -1267,11 +1234,11 @@ function Player:isInBoatSpot()
 		groundId = tile:getGround():getId()
 	end
 	if zone and zone:isInZone(self:getPosition()) and tile and groundId == SoulWarQuest.ebbAndFlow.boatId then
-		logger.debug("Player {} is in boat spot", self:getName())
+		logger.trace("Player {} is in boat spot", self:getName())
 		return true
 	end
 
-	logger.debug("Player {} is not in boat spot", self:getName())
+	logger.trace("Player {} is not in boat spot", self:getName())
 	return false
 end
 
diff --git a/data-otservbr-global/scripts/quests/soul_war/soul_war_mechanics.lua b/data-otservbr-global/scripts/quests/soul_war/soul_war_mechanics.lua
index 2bbb37b0a6a..8c0c802aa33 100644
--- a/data-otservbr-global/scripts/quests/soul_war/soul_war_mechanics.lua
+++ b/data-otservbr-global/scripts/quests/soul_war/soul_war_mechanics.lua
@@ -358,23 +358,14 @@ function weepingSoulCorpse.onStepIn(creature, item, position, fromPosition)
 		return
 	end
 
-	local zone = Zone.getByName("boss.goshnar's-spite")
-	if not zone then
-		logger.error("Goshnar's Spite zone not found. Check the lever boss register.")
-		return
-	end
-
-	local monsters = zone:getMonsters()
-	for _, monster in ipairs(monsters) do
-		if monster:getName() == "Goshnar's Spite" then
-			local chance = math.random(100)
-			if chance <= SoulWarQuest.goshnarsSpiteHealChance then
-				local healAmount = math.floor(monster:getMaxHealth() * (SoulWarQuest.goshnarsSpiteHealPercentage / 100))
-				-- Heal percentage of the maximum health
-				monster:addHealth(healAmount)
-				logger.debug("Goshnar's Spite was healed to 10% of its maximum health.")
-			end
-			break
+	local monster = Creature("Goshnar's Spite")
+	if monster then
+		local chance = math.random(100)
+		if chance <= SoulWarQuest.goshnarsSpiteHealChance then
+			local healAmount = math.floor(monster:getMaxHealth() * (SoulWarQuest.goshnarsSpiteHealPercentage / 100))
+			-- Heal percentage of the maximum health
+			monster:addHealth(healAmount)
+			logger.debug("Goshnar's Spite was healed to 10% of its maximum health.")
 		end
 	end
 
@@ -392,19 +383,10 @@ local function removeSearingFire(position)
 	if tile then
 		local fire = tile:getItemById(SoulWarQuest.searingFireId)
 		if fire then
-			local zone = Zone.getByName("boss.goshnar's-spite")
-			if not zone then
-				logger.error("Goshnar's Spite zone not found. Check the lever boss register.")
-				return
-			end
-
-			local monsters = zone:getMonsters()
-			for _, monster in ipairs(monsters) do
-				if monster:getName() == "Goshnar's Spite" then
-					monster:addDefense(SoulWarQuest.goshnarsSpiteIncreaseDefense)
-					logger.debug("Found Goshnar's Spite on boss zone, adding defense.")
-					break
-				end
+			local monster = Creature("Goshnar's Spite")
+			if monster then
+				monster:addDefense(SoulWarQuest.goshnarsSpiteIncreaseDefense)
+				logger.debug("Found Goshnar's Spite on boss zone, adding defense.")
 			end
 			fire:remove()
 		end
@@ -583,7 +565,6 @@ local burningHatredMonsters = {
 local goshnarsHatredSorrow = Action()
 
 function goshnarsHatredSorrow.onUse(player, item, fromPosition, target, toPosition, isHotkey)
-	logger.debug("Player {} used the item {} on target {}.", player:getName(), item:getId(), target:getName())
 	if not target then
 		return
 	end
diff --git a/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-empty-house.xml b/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-empty-house.xml
new file mode 100644
index 00000000000..e5a6b86118e
--- /dev/null
+++ b/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-empty-house.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0"?>
+<houses />
diff --git a/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-empty-monster.xml b/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-empty-monster.xml
new file mode 100644
index 00000000000..8704e6da3b2
--- /dev/null
+++ b/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-empty-monster.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0"?>
+<monsters />
diff --git a/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-empty-npc.xml b/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-empty-npc.xml
new file mode 100644
index 00000000000..af7984e2faf
--- /dev/null
+++ b/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-empty-npc.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0"?>
+<npcs />
diff --git a/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-empty.otbm b/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-empty.otbm
index 7892efac0906d82faaa89ea3905180de70e1abcc..6d37ae4fb880709f5c9facf23687f08eb776fb95 100644
GIT binary patch
delta 38
wcmV+>0NMZl^9Pvp2awJdL;ynv{sp7`{{9A?2MC0OEqMt4|Nnu@waWoC`EryKjQ{`u

delta 15
XcmbR7h5i3$_6g@2pKpE6X!sKVN=XSC

diff --git a/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-inundate-house.xml b/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-inundate-house.xml
new file mode 100644
index 00000000000..e5a6b86118e
--- /dev/null
+++ b/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-inundate-house.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0"?>
+<houses />
diff --git a/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-inundate-monster.xml b/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-inundate-monster.xml
new file mode 100644
index 00000000000..8704e6da3b2
--- /dev/null
+++ b/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-inundate-monster.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0"?>
+<monsters />
diff --git a/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-inundate-npc.xml b/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-inundate-npc.xml
new file mode 100644
index 00000000000..af7984e2faf
--- /dev/null
+++ b/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-inundate-npc.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0"?>
+<npcs />
diff --git a/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-inundate.otbm b/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-inundate.otbm
index 98992c326dd4532fb48d78bcc3c2c083cff1266e..01f462c2f7a821fca0e31dab752b4087eb2b84e3 100644
GIT binary patch
delta 907
zcmYk4O(;ZB6vu~mFj9t$qQ=*T5{g0+7KRzDl%1v0SWLpgD80n<CKQduybbYYlm$vd
zu8g8A$O`!=^0BbAk(Grv=G}V^Z}&Ur{qFhSdwL5mdB$Vjl#-&P?n^V@PPeT+!$^z#
z7)JVPhFwvrC+rC(e@pe{Ql`(P#Y-T>p|2ETMafRWNSm&f>^7SXiyA7lx-wWpMYSsG
zpTd61pg|07_CggOJWLQJcp%8?5)NzYf<OwlPrC8g7ePf2cKQjH5ZGA{+`ITO-G|a0
zLFN#4S`gUC5VQfe5B=gB`|!h}RGcv1+{vG5q$f9EmY%;-(??*Po-Hh~8C5vu7X71e
zpp}oovN@iej)5nK2RRhHL_5K_0=4|pE_L1!Sivj=#S%7EJoZH32+|;eaRjy%girw=
z>0U=EK(I~lM&Q(i!@N4^BJDGRSE`I63=pgk+##^+4LHx{Y0oiC%iTlhAeca4JA2@h
zxLw3Bx0gYaR4Fz%IY<9ia^;ir)?$GQ?cxYp(U+~hZ1v@T-yH{;M_$IkV*)EY28R<z
rgl1`QGBTuEiy#%+;1#^0AGZ2os~`UNXRcwMN9NxE<B_*F(CGRF><0mr

delta 1308
zcmZXTJ1j$C7=~NtBVAmAL8J)=mq-Z)mjRoigGj_mB9cmKa7zr$iD-L-hNOo63sINN
zAe!=rh}A}2V(37`V31fOq)ST&=YKzEeBOTF^S|dmr<qh)_^E6uXb<Kkv_M*JrL~qi
zN2b8*q|M2!xT&IuqKRsXyZ(O5X7ZPtG>6S*!=#xdqOFE@aKo@{7<@y1)KEJVsP8A2
zDlp0@#3;e&6-ky3(4t*w)(25~!RVb)r3WVmkmRC=9-T@$?8VU~Mn{aEkYwQ$^^(#I
zO@l`2)3l-0=Uzqby8GDW<`Oq1qH%^|?6xfn23yFAw;4Lse)VE|mNv~2vTcssB_;}g
z06K|7MyUX`s>z}tPIe<nUyxSdC47Z&wAMfxVH98#N0KiFMJm+!3p=PeV06zYFNTw?
zNOC+zyU>*O@DV#1`546*Js?TPK3x^5rgz79zCDiA!e|UhZp6u}DNXtW7G=XJb!k2D
zfAp{72a@}U{A-pZ%n}hkqaJkV7Kd(e=>Hs_XQZo=^XKF?NnV~)aXB6k39$mdB_oC<
jSz(FzzNTk%L@kb}#S!I>Xp+{<R$@I#(j@7=r4Hv0x=--x

diff --git a/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow.otbm b/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow.otbm
index 7fbac6bb391d7259a4e6c818564a58b83570a320..b8ba1414d09e6bdea0cf36d80dfe9f1b39ab8e17 100644
GIT binary patch
delta 100
zcmV-q0Gt1^iVLcW3y`)JL;ynv{sp7`{{9A?2MC0OEqMt4|NpVG&4jaqg%>aa=YzAK
zwc97NechV{vm4`jO1GFT0sSSnm{S3SFt;Cs0dO9-lA-})8@Kqq0b47#R_OuQFSjun
G0s*XBbuFy`

delta 120
zcmZ40#l5MEd&0Jj=TEgTvrJ6gJhN5YfHhkJ#N4#?wmMj>_wH;~Fhk>Ul^2MyeUUEX
wUsW(`elTN;0hp!S!dM^&W=&qim@ExuecQ_ztqo=czGS?i4`yjfGBK_J0A%DXV*mgE

diff --git a/src/creatures/monsters/spawns/spawn_monster.cpp b/src/creatures/monsters/spawns/spawn_monster.cpp
index 39fb08327ba..d95d24d9a54 100644
--- a/src/creatures/monsters/spawns/spawn_monster.cpp
+++ b/src/creatures/monsters/spawns/spawn_monster.cpp
@@ -180,7 +180,7 @@ bool SpawnMonster::spawnMonster(uint32_t spawnMonsterId, spawnBlock_t &sb, const
 			return false;
 		}
 	} else {
-		g_logger().debug("[SpawnMonster] Spawning {} at {}", monsterType->name, sb.pos.toString());
+		g_logger().trace("[SpawnMonster] Spawning {} at {}", monsterType->name, sb.pos.toString());
 		if (!g_game().placeCreature(monster, sb.pos, false, true)) {
 			return false;
 		}

From 446718becbbc9d2b4e5b510ff9ee466884950d63 Mon Sep 17 00:00:00 2001
From: Eduardo Dantas <eduardo.dantas@hotmail.com.br>
Date: Wed, 10 Apr 2024 22:49:49 -0300
Subject: [PATCH 05/60] fix: more logs to debug

---
 .../soul_war/globalevent-ebb_and_flow_change_maps.lua  | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/data-otservbr-global/scripts/quests/soul_war/globalevent-ebb_and_flow_change_maps.lua b/data-otservbr-global/scripts/quests/soul_war/globalevent-ebb_and_flow_change_maps.lua
index 7d2a64ef19c..d13b5cf2cd6 100644
--- a/data-otservbr-global/scripts/quests/soul_war/globalevent-ebb_and_flow_change_maps.lua
+++ b/data-otservbr-global/scripts/quests/soul_war/globalevent-ebb_and_flow_change_maps.lua
@@ -26,7 +26,7 @@ local function loadMapEmpty()
 					local teleportPosition = player:getPosition()
 					teleportPosition.z = 9
 					player:teleportTo(teleportPosition)
-					logger.debug("Teleporting player to down.")
+					logger.trace("Teleporting player to down.")
 				end
 				player:sendCreatureAppear()
 			end
@@ -80,10 +80,10 @@ local function loadMapInundate()
 				if player:isInBoatSpot() then
 					local nearestCenterPosition = findNearestRoomPosition(playerPosition)
 					player:teleportTo(nearestCenterPosition)
-					logger.debug("Teleporting player to the near center position room and updating tile.")
+					logger.trace("Teleporting player to the near center position room and updating tile.")
 				else
 					player:teleportTo(SoulWarQuest.ebbAndFlow.waitPosition)
-					logger.debug("Teleporting player to wait position and updating tile.")
+					logger.trace("Teleporting player to wait position and updating tile.")
 				end
 				playerPosition:sendMagicEffect(CONST_ME_TELEPORT)
 			end
@@ -121,10 +121,10 @@ local eddAndFlowInundate = GlobalEvent("eddAndFlowInundate")
 
 function eddAndFlowInundate.onThink(interval, lastExecution)
 	if SoulWarQuest.ebbAndFlow.isLoadedEmptyMap() then
-		logger.debug("Map change to empty in {} minutes.", SoulWarQuest.ebbAndFlow.intervalChangeMap)
+		logger.trace("Map change to empty in {} minutes.", SoulWarQuest.ebbAndFlow.intervalChangeMap)
 		loadMapInundate()
 	elseif SoulWarQuest.ebbAndFlow.isActive() then
-		logger.debug("Map change to inundate in {} minutes.", SoulWarQuest.ebbAndFlow.intervalChangeMap)
+		logger.trace("Map change to inundate in {} minutes.", SoulWarQuest.ebbAndFlow.intervalChangeMap)
 		loadMapEmpty()
 	end
 

From be209b301524a82360fc91f2d0df10d42f570beb Mon Sep 17 00:00:00 2001
From: Eduardo Dantas <eduardo.dantas@hotmail.com.br>
Date: Wed, 10 Apr 2024 22:58:35 -0300
Subject: [PATCH 06/60] improve: "/pos" talkaction better handling

---
 data/scripts/talkactions/gm/position.lua | 43 ++++++++----------------
 1 file changed, 14 insertions(+), 29 deletions(-)

diff --git a/data/scripts/talkactions/gm/position.lua b/data/scripts/talkactions/gm/position.lua
index 1869b109c5f..dc95552d5c2 100644
--- a/data/scripts/talkactions/gm/position.lua
+++ b/data/scripts/talkactions/gm/position.lua
@@ -1,23 +1,5 @@
 local position = TalkAction("/pos", "!pos")
 
-local function extractCoordinates(input)
-	local patterns = {
-		-- table format
-		"{%s*x%s*=%s*(%d+)%s*,%s*y%s*=%s*(%d+)%s*,%s*z%s*=%s*(%d+)%s*}",
-		-- Position format
-		"Position%s*%((%d+)%s*,%s*(%d+)%s*,%s*(%d+)%s*%)",
-		-- x, y, z format
-		"(%d+)%s*,%s*(%d+)%s*,%s*(%d+)",
-	}
-
-	for _, pattern in ipairs(patterns) do
-		local x, y, z = string.match(input, pattern)
-		if x and y and z then
-			return tonumber(x), tonumber(y), tonumber(z)
-		end
-	end
-end
-
 function position.onSay(player, words, param)
 	-- create log
 	logCommand(player, words, param)
@@ -28,18 +10,21 @@ function position.onSay(player, words, param)
 		return
 	end
 
-	local x, y, z = extractCoordinates(param)
-	if x and y and z then
-		local teleportPosition = Position(x, y, z)
-		local tile = Tile(teleportPosition)
-		if not tile then
-			player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Invalid tile or position. Send a valid position.")
-			return
-		end
-
-		player:teleportTo(teleportPosition)
-	else
+	local teleportPosition = param:toPosition()
+	if not teleportPosition then
 		player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Invalid position format. Use one of the following formats: \n/pos {x = ..., y = ..., z = ...}\n/pos Position(..., ..., ...)\n/pos x, y, z.")
+		return
+	end
+
+	local tile = Tile(teleportPosition)
+	if not tile then
+		player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Invalid tile or position. Send a valid position.")
+		return
+	end
+
+	player:teleportTo(teleportPosition)
+	if not player:isInGhostMode() then
+		teleportPosition:sendMagicEffect(CONST_ME_TELEPORT)
 	end
 end
 

From 55edd29bae8df7ab8de7f009b8bb26083cfe6a14 Mon Sep 17 00:00:00 2001
From: Eduardo Dantas <eduardo.dantas@hotmail.com.br>
Date: Thu, 11 Apr 2024 14:42:18 -0300
Subject: [PATCH 07/60] fix: miniBosses table

---
 data-otservbr-global/npc/flickering_soul.lua                    | 2 +-
 .../scripts/quests/soul_war/moveevent-soul_war_entrances.lua    | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/data-otservbr-global/npc/flickering_soul.lua b/data-otservbr-global/npc/flickering_soul.lua
index a6e11c311c6..92828d77396 100644
--- a/data-otservbr-global/npc/flickering_soul.lua
+++ b/data-otservbr-global/npc/flickering_soul.lua
@@ -168,7 +168,7 @@ local function playerSayCallback(npc, player, type, message)
 		npcHandler:say("I despised my followers for their petty agendas and for their limited vision of my own goals and personality.", npc, player)
 	elseif MsgContains(message, "shards") then
 		local bossesYetToDefeat = {}
-		for bossName, _ in pairs(SoulWarBosses) do
+		for bossName, _ in pairs(SoulWarQuest.miniBosses) do
 			if not soulWarQuest:get(bossName) then
 				table.insert(bossesYetToDefeat, bossName)
 			end
diff --git a/data-otservbr-global/scripts/quests/soul_war/moveevent-soul_war_entrances.lua b/data-otservbr-global/scripts/quests/soul_war/moveevent-soul_war_entrances.lua
index ccf56ea6a3b..a6792315882 100644
--- a/data-otservbr-global/scripts/quests/soul_war/moveevent-soul_war_entrances.lua
+++ b/data-otservbr-global/scripts/quests/soul_war/moveevent-soul_war_entrances.lua
@@ -67,7 +67,7 @@ function soul_war_megalomania_entrance.onStepIn(creature, item, position, fromPo
 
 	local text = ""
 	local soulWarCount = 0
-	for bossName, completed in pairs(SoulWarBosses) do
+	for bossName, completed in pairs(SoulWarQuest.miniBosses) do
 		if soulWarQuest:get(bossName) == completed then
 			soulWarCount = soulWarCount + 1
 		else

From f9e664e3be98eadfcd89f3ddd992ee6f358956b5 Mon Sep 17 00:00:00 2001
From: Eduardo Dantas <eduardo.dantas@hotmail.com.br>
Date: Thu, 11 Apr 2024 16:35:29 -0300
Subject: [PATCH 08/60] fix: some bugs

---
 .../soul_war/goshnar's_megalomania_green.lua  |  1 -
 .../soul_war/goshnar's_megalomania_purple.lua |  1 -
 .../quests/soul_war/goshnars_spite.lua        |  8 -----
 .../quests/soul_war/soul_war_mechanics.lua    | 14 ++++----
 .../world/otservbr-monster.xml                | 34 +++++++++++++------
 5 files changed, 30 insertions(+), 28 deletions(-)

diff --git a/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_green.lua b/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_green.lua
index 5c6170d3f92..8a8d3d0d43f 100644
--- a/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_green.lua
+++ b/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_green.lua
@@ -25,7 +25,6 @@ monster.race = "undead"
 monster.corpse = 33889
 monster.speed = 250
 monster.manaCost = 0
-monster.maxSummons = 4
 
 monster.changeTarget = {
 	interval = 4000,
diff --git a/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_purple.lua b/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_purple.lua
index 6b7b12968e5..c2530a43087 100644
--- a/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_purple.lua
+++ b/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_purple.lua
@@ -14,7 +14,6 @@ monster.race = "undead"
 monster.corpse = 6028
 monster.speed = 250
 monster.manaCost = 0
-monster.maxSummons = 4
 
 monster.changeTarget = {
 	interval = 4000,
diff --git a/data-otservbr-global/monster/quests/soul_war/goshnars_spite.lua b/data-otservbr-global/monster/quests/soul_war/goshnars_spite.lua
index 0e41373cc8e..40817c335b0 100644
--- a/data-otservbr-global/monster/quests/soul_war/goshnars_spite.lua
+++ b/data-otservbr-global/monster/quests/soul_war/goshnars_spite.lua
@@ -67,14 +67,6 @@ monster.light = {
 	color = 0,
 }
 
-monster.summon = {
-	maxSummons = 4,
-	summons = {
-		{ name = "dreadful harvester", chance = 50, interval = 1000, count = 2 },
-		{ name = "spiteful spitter", chance = 50, interval = 1000, count = 2 },
-	},
-}
-
 monster.voices = {
 	interval = 5000,
 	chance = 10,
diff --git a/data-otservbr-global/scripts/quests/soul_war/soul_war_mechanics.lua b/data-otservbr-global/scripts/quests/soul_war/soul_war_mechanics.lua
index 8c0c802aa33..49a67775a96 100644
--- a/data-otservbr-global/scripts/quests/soul_war/soul_war_mechanics.lua
+++ b/data-otservbr-global/scripts/quests/soul_war/soul_war_mechanics.lua
@@ -727,26 +727,26 @@ function pulsatingEnergy.onStepIn(creature, item, position, fromPosition)
 	local secondFloorAccess = kv:get("second-floor-access") or false
 	local thirdFloorAccess = kv:get("third-floor-access") or false
 	if thirdFloorAccess then
-		player:sendTextMessage(MESSAGE_INFO_DESCR, "You've already gained access to fight with the Goshnar's Cruelty.")
+		player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You've already gained access to fight with the Goshnar's Cruelty.")
 		return true
 	end
 
 	if energyCount >= 40 and not firstFloorAccess then
 		kv:set("access-counter", 0)
 		kv:set("first-floor-access", true)
-		player:sendTextMessage(MESSAGE_INFO_DESCR, "You've gained access to the first floor. Continue collecting Pulsating Energies to gain further access.")
+		player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You've gained access to the first floor. Continue collecting Pulsating Energies to gain further access.")
 	end
 
 	if energyCount >= 55 and not secondFloorAccess then
 		kv:set("access-counter", 0)
 		kv:set("second-floor-access", true)
-		player:sendTextMessage(MESSAGE_INFO_DESCR, "You've gained access to the second floor. Continue collecting Pulsating Energies to gain further access.")
+		player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You've gained access to the second floor. Continue collecting Pulsating Energies to gain further access.")
 	end
 
 	if energyCount >= 70 and not thirdFloorAccess then
 		kv:set("access-counter", 0)
 		kv:set("third-floor-access", true)
-		player:sendTextMessage(MESSAGE_INFO_DESCR, "You've gained access to the third floor. You can now fight with the Goshnar's Cruelty.")
+		player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You've gained access to the third floor. You can now fight with the Goshnar's Cruelty.")
 	end
 
 	item:remove()
@@ -771,7 +771,7 @@ function pulsatingEnergyTeleportAccess.onStepIn(creature, item, position, fromPo
 			local energyCount = kv:get("access-counter") or 0
 			local energiesNeeded = posData.count - energyCount
 			if not hasAccess then
-				player:sendTextMessage(MESSAGE_INFO_DESCR, "You don't have access to this floor yet. You have collected " .. energyCount .. "/" .. posData.count .. ", and need " .. energiesNeeded .. " more pulsating energies to gain access.")
+				player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You don't have access to this floor yet. You have collected " .. energyCount .. "/" .. posData.count .. ", and need " .. energiesNeeded .. " more pulsating energies to gain access.")
 				player:teleportTo(fromPosition, true)
 				fromPosition:sendMagicEffect(CONST_ME_TELEPORT)
 			else
@@ -860,7 +860,7 @@ function greedyMaw.onUse(player, item, fromPosition, target, toPosition, isHotke
 		SoulWarQuest.kvSoulWar:set("greedy-maw-action", currentTime + timeToIncreaseDefense)
 		target:getPosition():sendMagicEffect(CONST_ME_DRAWBLOOD)
 		item:remove()
-		player:sendTextMessage(MESSAGE_INFO_DESCR, "Use the item again within " .. timeToIncreaseDefense .. " seconds, or the monster's defense will increase by 2 every " .. timeToIncreaseDefense .. " seconds.")
+		player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Use the item again within " .. timeToIncreaseDefense .. " seconds, or the monster's defense will increase by 2 every " .. timeToIncreaseDefense .. " seconds.")
 		local goshnarsCruelty = Creature("Goshnar's Cruelty")
 		if goshnarsCruelty then
 			local mtype = goshnarsCruelty:getType()
@@ -962,7 +962,7 @@ function cleansedSanity.onUse(player, item, fromPosition, target, toPosition, is
 		SoulWarQuest.kvSoulWar:set("cleansed-sanity-action", currentTime + timeToIncreaseDefense)
 		target:getPosition():sendMagicEffect(CONST_ME_DRAWBLOOD)
 		item:remove()
-		player:sendTextMessage(MESSAGE_INFO_DESCR, "Use the item again within " .. timeToIncreaseDefense .. " seconds, or the monster's defense will increase by 2 every " .. timeToIncreaseDefense .. " seconds.")
+		player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Use the item again within " .. timeToIncreaseDefense .. " seconds, or the monster's defense will increase by 2 every " .. timeToIncreaseDefense .. " seconds.")
 		local boss = Creature("Goshnar's Megalomania")
 		if boss then
 			local mtype = boss:getType()
diff --git a/data-otservbr-global/world/otservbr-monster.xml b/data-otservbr-global/world/otservbr-monster.xml
index 0a876191095..40eb0ee4534 100644
--- a/data-otservbr-global/world/otservbr-monster.xml
+++ b/data-otservbr-global/world/otservbr-monster.xml
@@ -96137,15 +96137,15 @@
 	<monster centerx="33234" centery="32794" centerz="9" radius="2">
 		<monster name="Larva" x="0" y="-2" z="9" spawntime="90" />
 	</monster>
+	<monster centerx="32006" centery="32795" centerz="9" radius="2">
+		<monster name="Ghoul" x="-1" y="-1" z="9" spawntime="90" />
+	</monster>
 	<monster centerx="32296" centery="32795" centerz="9" radius="1">
 		<monster name="Corym Skirmisher" x="0" y="0" z="9" spawntime="60" />
 	</monster>
 	<monster centerx="32300" centery="32795" centerz="9" radius="1">
 		<monster name="Corym Charlatan" x="0" y="0" z="9" spawntime="60" />
 	</monster>
-	<monster centerx="32006" centery="32795" centerz="9" radius="2">
-		<monster name="Ghoul" x="-1" y="-1" z="9" spawntime="90" />
-	</monster>
 	<monster centerx="33071" centery="32795" centerz="9" radius="2">
 		<monster name="Scarab" x="1" y="-1" z="9" spawntime="90" />
 	</monster>
@@ -96730,6 +96730,9 @@
 	<monster centerx="32245" centery="32835" centerz="9" radius="1">
 		<monster name="Rotworm" x="1" y="-1" z="9" spawntime="90" />
 	</monster>
+	<monster centerx="32274" centery="32835" centerz="9" radius="1">
+		<monster name="Corym Skirmisher" x="0" y="0" z="9" spawntime="60" />
+	</monster>
 	<monster centerx="32015" centery="32836" centerz="9" radius="3">
 		<monster name="Ghoul" x="1" y="-3" z="9" spawntime="90" />
 		<monster name="Ghoul" x="-2" y="0" z="9" spawntime="90" />
@@ -96737,9 +96740,6 @@
 	<monster centerx="32024" centery="32836" centerz="9" radius="3">
 		<monster name="Pirate Skeleton" x="2" y="-1" z="9" spawntime="90" />
 	</monster>
-	<monster centerx="32274" centery="32835" centerz="9" radius="1">
-		<monster name="Corym Skirmisher" x="0" y="0" z="9" spawntime="60" />
-	</monster>
 	<monster centerx="32566" centery="32836" centerz="9" radius="2">
 		<monster name="Water Elemental" x="0" y="0" z="9" spawntime="90" />
 	</monster>
@@ -118901,12 +118901,12 @@
 		<monster name="Rotworm" x="-3" y="3" z="10" spawntime="90" />
 		<monster name="Carrion Worm" x="1" y="3" z="10" spawntime="90" />
 	</monster>
-	<monster centerx="32026" centery="32830" centerz="10" radius="2">
-		<monster name="Pirate Skeleton" x="0" y="-1" z="10" spawntime="90" />
-	</monster>
 	<monster centerx="32276" centery="32829" centerz="10" radius="1">
 		<monster name="Corym Skirmisher" x="0" y="0" z="10" spawntime="60" />
 	</monster>
+	<monster centerx="32026" centery="32830" centerz="10" radius="2">
+		<monster name="Pirate Skeleton" x="0" y="-1" z="10" spawntime="90" />
+	</monster>
 	<monster centerx="32224" centery="32831" centerz="10" radius="4">
 		<monster name="Rotworm" x="-3" y="-1" z="10" spawntime="90" />
 		<monster name="Carrion Worm" x="2" y="1" z="10" spawntime="90" />
@@ -162231,6 +162231,9 @@
 		<monster name="Blood Crab" x="0" y="-3" z="14" spawntime="60" />
 		<monster name="Sea Serpent" x="0" y="-1" z="14" spawntime="60" />
 	</monster>
+	<monster centerx="33742" centery="31629" centerz="14" radius="1">
+		<monster name="Dreadful Harvester" x="0" y="0" z="14" spawntime="20" />
+	</monster>
 	<monster centerx="32798" centery="31630" centerz="14" radius="1">
 		<monster name="Ghoul" x="1" y="0" z="14" spawntime="90" />
 	</monster>
@@ -162243,9 +162246,15 @@
 	<monster centerx="33710" centery="31630" centerz="14" radius="1">
 		<monster name="Dreadful Harvester" x="0" y="0" z="14" spawntime="20" />
 	</monster>
+	<monster centerx="33746" centery="31630" centerz="14" radius="1">
+		<monster name="Dreadful Harvester" x="0" y="0" z="14" spawntime="20" />
+	</monster>
 	<monster centerx="32795" centery="31631" centerz="14" radius="1">
 		<monster name="Ghoul" x="1" y="0" z="14" spawntime="90" />
 	</monster>
+	<monster centerx="33738" centery="31631" centerz="14" radius="1">
+		<monster name="Spiteful Spitter" x="0" y="0" z="14" spawntime="20" />
+	</monster>
 	<monster centerx="32782" centery="31632" centerz="14" radius="1">
 		<monster name="Ghoul" x="1" y="0" z="14" spawntime="90" />
 	</monster>
@@ -162257,10 +162266,10 @@
 		<monster name="Skeleton" x="1" y="1" z="14" spawntime="90" />
 	</monster>
 	<monster centerx="33738" centery="31633" centerz="14" radius="1">
-		<monster name="Weeping Soul" x="0" y="0" z="14" spawntime="60" />
+		<monster name="Weeping Soul" x="0" y="0" z="14" spawntime="20" />
 	</monster>
 	<monster centerx="33747" centery="31633" centerz="14" radius="1">
-		<monster name="Weeping Soul" x="0" y="0" z="14" spawntime="60" />
+		<monster name="Weeping Soul" x="0" y="0" z="14" spawntime="20" />
 	</monster>
 	<monster centerx="32781" centery="31634" centerz="14" radius="1">
 		<monster name="Ghoul" x="1" y="0" z="14" spawntime="90" />
@@ -162294,6 +162303,9 @@
 	<monster centerx="33505" centery="31636" centerz="14" radius="3">
 		<monster name="Blood Crab" x="-1" y="2" z="14" spawntime="60" />
 	</monster>
+	<monster centerx="33742" centery="31636" centerz="14" radius="1">
+		<monster name="Spiteful Spitter" x="0" y="0" z="14" spawntime="20" />
+	</monster>
 	<monster centerx="33298" centery="31640" centerz="14" radius="1">
 		<monster name="Behemoth" x="-1" y="0" z="14" spawntime="90" />
 	</monster>

From 89f1744f78183f5fb9e1ab530e41537f31f8d65e Mon Sep 17 00:00:00 2001
From: Eduardo Dantas <eduardo.dantas@hotmail.com.br>
Date: Thu, 11 Apr 2024 16:48:57 -0300
Subject: [PATCH 09/60] feat: add mirror item to summon mirror image

---
 .../quests/soul_war/soul_war_mechanics.lua    | 22 +++++++++++++++++++
 data/items/items.xml                          |  5 ++++-
 2 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/data-otservbr-global/scripts/quests/soul_war/soul_war_mechanics.lua b/data-otservbr-global/scripts/quests/soul_war/soul_war_mechanics.lua
index 49a67775a96..ebf390e6c7b 100644
--- a/data-otservbr-global/scripts/quests/soul_war/soul_war_mechanics.lua
+++ b/data-otservbr-global/scripts/quests/soul_war/soul_war_mechanics.lua
@@ -142,6 +142,28 @@ bossesDeath:register()
 
 fourthTaintBossesDeath:register()
 
+local lastUse = 0
+local cooldown = 30
+
+local mirrorImageCreation = Action()
+function mirrorImageCreation.onUse(player, item, fromPosition, target, toPosition, isHotkey)
+	local currentTime = os.time()
+	local timePassed = currentTime - lastUse
+	if timePassed >= cooldown or lastUse == 0 then
+		Game.createMonster("Mirror Image", player:getPosition())
+		lastUse = currentTime
+		item:transform(33783)
+	else
+		local timeLeft = cooldown - timePassed
+		player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You need to wait " .. timeLeft .. " second(s) to use this item again.")
+	end
+
+	return true
+end
+
+mirrorImageCreation:id(33782)
+mirrorImageCreation:register()
+
 local mirroredNightmareApparitionDeath = CreatureEvent("MirroredNightmareBossAccess")
 
 function mirroredNightmareApparitionDeath.onDeath(creature, corpse, killer, mostDamageKiller, lastHitUnjustified, mostDamageUnjustified)
diff --git a/data/items/items.xml b/data/items/items.xml
index c4ba2b3a93b..822caa3a9d2 100644
--- a/data/items/items.xml
+++ b/data/items/items.xml
@@ -62885,7 +62885,10 @@ hands of its owner. Granted by TibiaRoyal.com"/>
 		<attribute key="primarytype" value="tools"/>
 		<attribute key="weight" value="950"/>
 	</item>
-	<item id="33783" article="a" name="broken mirror"/>
+	<item id="33783" article="a" name="broken mirror">
+		<attribute key="duration" value="30"/>
+		<attribute key="decayTo" value="33782"/>
+	</item>
 	<item id="33784" article="a" name="mirror">
 		<attribute key="primarytype" value="tools"/>
 		<attribute key="weight" value="950"/>

From 8319f29ad4c62d70587eb7f9c1d073e4d55219c0 Mon Sep 17 00:00:00 2001
From: Eduardo Dantas <eduardo.dantas@hotmail.com.br>
Date: Thu, 11 Apr 2024 19:20:56 -0300
Subject: [PATCH 10/60] fix: map paths

---
 .../quests/soul_war/soul_war_mechanics.lua       | 16 ++++++++--------
 src/map/map.cpp                                  |  6 +-----
 2 files changed, 9 insertions(+), 13 deletions(-)

diff --git a/data-otservbr-global/scripts/quests/soul_war/soul_war_mechanics.lua b/data-otservbr-global/scripts/quests/soul_war/soul_war_mechanics.lua
index ebf390e6c7b..488183fa94e 100644
--- a/data-otservbr-global/scripts/quests/soul_war/soul_war_mechanics.lua
+++ b/data-otservbr-global/scripts/quests/soul_war/soul_war_mechanics.lua
@@ -322,21 +322,21 @@ setTaint:separator(" ")
 setTaint:groupType("god")
 setTaint:register()
 
-local setTaint = TalkAction("/changeflowmap")
+local changeMap = TalkAction("/changeflowmap")
 
-function setTaint.onSay(player, words, param)
+function changeMap.onSay(player, words, param)
 	if param == "empty" then
-		Game.loadMap("data-otservbr-global/world/quest/soul_war/ebb_and_flow/empty.otbm")
+		Game.loadMap(SoulWarQuest.mapsPath.empty)
 	elseif param == "inundate" then
-		Game.loadMap("data-otservbr-global/world/quest/soul_war/ebb_and_flow/inundate.otbm")
+		Game.loadMap(SoulWarQuest.mapsPath.inundate)
 	elseif param == "ebb" then
-		Game.loadMap("data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb_and_flow.otbm")
+		Game.loadMap(SoulWarQuest.mapsPath.ebbFlow)
 	end
 end
 
-setTaint:separator(" ")
-setTaint:groupType("god")
-setTaint:register()
+changeMap:separator(" ")
+changeMap:groupType("god")
+changeMap:register()
 
 local hazardousPhantomDeath = CreatureEvent("HazardousPhantomDeath")
 
diff --git a/src/map/map.cpp b/src/map/map.cpp
index 55bb0fc6548..d5a510c33a7 100644
--- a/src/map/map.cpp
+++ b/src/map/map.cpp
@@ -27,11 +27,7 @@ void Map::load(const std::string &identifier, const Position &pos) {
 		path = identifier;
 		IOMap::loadMap(this, pos);
 	} catch (const std::exception &e) {
-		throw IOMapException(fmt::format(
-			"\n[Map::load] - The map in folder {} is missing or corrupted"
-			"\n            - {}",
-			identifier, e.what()
-		));
+		g_logger().warn("[Map::load] - The map in folder {} is missing or corrupted", identifier);
 	}
 }
 

From b1fb702eccb1368853bf77d13832a175d5ab521d Mon Sep 17 00:00:00 2001
From: Eduardo Dantas <eduardo.dantas@hotmail.com.br>
Date: Mon, 15 Apr 2024 18:45:29 -0300
Subject: [PATCH 11/60] fix: add condition for taint icon

---
 .../scripts/lib/quests/soul-war.lua           | 42 ++++++++++++-------
 .../quests/soul_war/soul_war_mechanics.lua    |  8 +++-
 .../scripts/talkactions/god/add_condition.lua | 10 +++++
 src/creatures/combat/condition.cpp            | 23 +++++++++-
 src/creatures/creatures_definitions.hpp       |  6 +--
 src/lua/functions/core/game/lua_enums.cpp     | 34 ++-------------
 src/utils/utils_definitions.hpp               | 10 ++---
 7 files changed, 76 insertions(+), 57 deletions(-)
 create mode 100644 data/scripts/talkactions/god/add_condition.lua

diff --git a/data-otservbr-global/scripts/lib/quests/soul-war.lua b/data-otservbr-global/scripts/lib/quests/soul-war.lua
index 4a8a47ee131..7ebe42b0441 100644
--- a/data-otservbr-global/scripts/lib/quests/soul-war.lua
+++ b/data-otservbr-global/scripts/lib/quests/soul-war.lua
@@ -970,11 +970,11 @@ end
 
 TaintTeleportCooldown = {}
 
-function Player:getTaintNameByNumber(taintNumber)
+function Player:getTaintNameByNumber(taintNumber, skipKvCheck)
 	local haveTaintName = nil
 	local soulWarQuest = self:soulWarQuestKV()
 	local taintName = soulWarTaints[taintNumber]
-	if taintName and soulWarQuest:get(taintName) then
+	if skipKvCheck or taintName and soulWarQuest:get(taintName) then
 		haveTaintName = taintName
 	end
 
@@ -983,15 +983,29 @@ end
 
 function Player:addNextTaint()
 	local soulWarQuest = self:soulWarQuestKV()
-	for _, taint in ipairs(soulWarTaints) do
-		if not soulWarQuest:get(taint) then
-			soulWarQuest:set(taint, true)
-			self:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have gained the " .. taint .. ".")
+	for _, taintName in ipairs(soulWarTaints) do
+		if not soulWarQuest:get(taintName) then
+			soulWarQuest:set(taintName, true)
+			self:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have gained the " .. taintName .. ".")
+			self:setTaintIcon()
 			break
 		end
 	end
 end
 
+function Player:setTaintIcon(taintId)
+	self:resetTaintConditions()
+	local condition = Condition(CONDITION_GOSHNARTAINT, CONDITIONID_DEFAULT, taintId or self:getTaintLevel())
+	condition:setTicks(14 * 24 * 60 * 60 * 1000)
+	self:addCondition(condition)
+end
+
+function Player:resetTaintConditions()
+	for i = 1, 5 do
+		self:removeCondition(CONDITION_GOSHNARTAINT, CONDITIONID_DEFAULT, i)
+	end
+end
+
 function Player:getTaintLevel()
 	local taintLevel = nil
 	local soulWarQuest = self:soulWarQuestKV()
@@ -1004,17 +1018,17 @@ function Player:getTaintLevel()
 	return taintLevel
 end
 
-function Player:resetTaints()
+function Player:resetTaints(skipCheckTime)
 	local soulWarQuest = self:soulWarQuestKV()
 	local firstTaintTime = soulWarQuest:get("firstTaintTime")
-	if firstTaintTime and os.time() >= (firstTaintTime + TaintDurationSeconds) then
-		-- Reset all taints
-		for _, taint in ipairs(soulWarTaints) do
-			if soulWarQuest:get(taint) then
-				soulWarQuest:remove(taint)
+	if skipCheckTime or firstTaintTime and os.time() >= (firstTaintTime + TaintDurationSeconds) then
+		-- Reset all taints and remove condition
+		for _, taintName in ipairs(soulWarTaints) do
+			if soulWarQuest:get(taintName) then
+				soulWarQuest:remove(taintName)
 			end
 		end
-
+		self:resetTaintConditions()
 		soulWarQuest:remove("firstTaintTime")
 		self:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Your goshnar's taints have been reset. You didn't finish the quest in 14 days")
 	end
@@ -1028,7 +1042,7 @@ function Monster:tryTeleportToPlayer(sayMessage)
 	for i, spectator in ipairs(spectators) do
 		if spectator:isPlayer() then
 			local player = spectator:getPlayer()
-			if player:getTaintNameByNumber(1) then
+			if player:getTaintNameByNumber(1, true) then
 				local distance = self:getPosition():getDistance(player:getPosition())
 				if distance > maxDistance then
 					maxDistance = distance
diff --git a/data-otservbr-global/scripts/quests/soul_war/soul_war_mechanics.lua b/data-otservbr-global/scripts/quests/soul_war/soul_war_mechanics.lua
index 488183fa94e..7a7103fa08f 100644
--- a/data-otservbr-global/scripts/quests/soul_war/soul_war_mechanics.lua
+++ b/data-otservbr-global/scripts/quests/soul_war/soul_war_mechanics.lua
@@ -44,6 +44,10 @@ login:register()
 local goshnarsMaliceReflection = CreatureEvent("Goshnar's-Malice")
 
 function goshnarsMaliceReflection.onHealthChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin)
+	if not attacker then
+		return primaryDamage, primaryType, secondaryDamage, secondaryType
+	end
+
 	local player = attacker:getPlayer()
 	if player then
 		if primaryDamage > 0 and (primaryType == COMBAT_PHYSICALDAMAGE or primaryType == COMBAT_DEATHDAMAGE) then
@@ -261,11 +265,13 @@ function setTaint.onSay(player, words, param)
 	end
 
 	local taintLevel = split[2]:trim():lower()
-	local taintName = player:getTaintNameByNumber(tonumber(taintLevel))
+	local taintName = player:getTaintNameByNumber(tonumber(taintLevel), true)
 	if taintName ~= nil then
+		target:resetTaints(true)
 		target:soulWarQuestKV():set(taintName, true)
 		target:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You new taint level is: " .. taintLevel .. ", name: " .. taintName)
 		player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Added taint level: " .. taintLevel .. ", name: " .. taintName .. " to player: " .. target:getName())
+		target:setTaintIcon()
 	end
 end
 
diff --git a/data/scripts/talkactions/god/add_condition.lua b/data/scripts/talkactions/god/add_condition.lua
new file mode 100644
index 00000000000..7d92cbc0a09
--- /dev/null
+++ b/data/scripts/talkactions/god/add_condition.lua
@@ -0,0 +1,10 @@
+local talkaction = TalkAction("/testtaintconditions")
+
+function talkaction.onSay(player, words, param)
+	player:setTaintIcon()
+	return false
+end
+
+talkaction:separator(" ")
+talkaction:groupType("god")
+talkaction:register()
diff --git a/src/creatures/combat/condition.cpp b/src/creatures/combat/condition.cpp
index 9d0f6962884..74eded14e1f 100644
--- a/src/creatures/combat/condition.cpp
+++ b/src/creatures/combat/condition.cpp
@@ -242,6 +242,8 @@ std::shared_ptr<Condition> Condition::createCondition(ConditionId_t id, Conditio
 		case CONDITION_YELLTICKS:
 		case CONDITION_PACIFIED:
 			return std::make_shared<ConditionGeneric>(id, type, ticks, buff, subId);
+		case CONDITION_GOSHNARTAINT:
+			return std::make_shared<ConditionGeneric>(id, type, ticks, buff, subId);
 
 		default:
 			return nullptr;
@@ -390,7 +392,26 @@ uint32_t ConditionGeneric::getIcons() const {
 		case CONDITION_ROOTED:
 			icons |= ICON_ROOTED;
 			break;
-
+		case CONDITION_GOSHNARTAINT:
+			switch (subId) {
+				case 1:
+					icons = ICON_GOSHNARTAINT_1;
+					break;
+				case 2:
+					icons = ICON_GOSHNARTAINT_2;
+					break;
+				case 3:
+					icons = ICON_GOSHNARTAINT_3;
+					break;
+				case 4:
+					icons = ICON_GOSHNARTAINT_4;
+					break;
+				case 5:
+					icons = ICON_GOSHNARTAINT_5;
+					break;
+				default:
+					break;
+			}
 		default:
 			break;
 	}
diff --git a/src/creatures/creatures_definitions.hpp b/src/creatures/creatures_definitions.hpp
index f1929a633c1..b66293c594a 100644
--- a/src/creatures/creatures_definitions.hpp
+++ b/src/creatures/creatures_definitions.hpp
@@ -112,11 +112,7 @@ enum ConditionType_t : uint8_t {
 	CONDITION_LESSERHEX = 31,
 	CONDITION_INTENSEHEX = 32,
 	CONDITION_GREATERHEX = 33,
-	CONDITION_GOSHNAR1 = 34,
-	CONDITION_GOSHNAR2 = 35,
-	CONDITION_GOSHNAR3 = 36,
-	CONDITION_GOSHNAR4 = 37,
-	CONDITION_GOSHNAR5 = 38,
+	CONDITION_GOSHNARTAINT = 34,
 
 	// Need the last ever
 	CONDITION_COUNT = 39
diff --git a/src/lua/functions/core/game/lua_enums.cpp b/src/lua/functions/core/game/lua_enums.cpp
index 19e7b9219ec..46335d2fde7 100644
--- a/src/lua/functions/core/game/lua_enums.cpp
+++ b/src/lua/functions/core/game/lua_enums.cpp
@@ -316,37 +316,9 @@ void LuaEnums::initFactionEnums(lua_State* L) {
 }
 
 void LuaEnums::initConditionEnums(lua_State* L) {
-	registerEnum(L, CONDITION_NONE);
-	registerEnum(L, CONDITION_POISON);
-	registerEnum(L, CONDITION_FIRE);
-	registerEnum(L, CONDITION_ENERGY);
-	registerEnum(L, CONDITION_BLEEDING);
-	registerEnum(L, CONDITION_HASTE);
-	registerEnum(L, CONDITION_PARALYZE);
-	registerEnum(L, CONDITION_OUTFIT);
-	registerEnum(L, CONDITION_INVISIBLE);
-	registerEnum(L, CONDITION_LIGHT);
-	registerEnum(L, CONDITION_MANASHIELD);
-	registerEnum(L, CONDITION_INFIGHT);
-	registerEnum(L, CONDITION_DRUNK);
-	registerEnum(L, CONDITION_EXHAUST);
-	registerEnum(L, CONDITION_REGENERATION);
-	registerEnum(L, CONDITION_SOUL);
-	registerEnum(L, CONDITION_DROWN);
-	registerEnum(L, CONDITION_MUTED);
-	registerEnum(L, CONDITION_CHANNELMUTEDTICKS);
-	registerEnum(L, CONDITION_YELLTICKS);
-	registerEnum(L, CONDITION_ATTRIBUTES);
-	registerEnum(L, CONDITION_FREEZING);
-	registerEnum(L, CONDITION_DAZZLED);
-	registerEnum(L, CONDITION_CURSED);
-	registerEnum(L, CONDITION_EXHAUST_COMBAT);
-	registerEnum(L, CONDITION_EXHAUST_HEAL);
-	registerEnum(L, CONDITION_PACIFIED);
-	registerEnum(L, CONDITION_SPELLCOOLDOWN);
-	registerEnum(L, CONDITION_SPELLGROUPCOOLDOWN);
-	registerEnum(L, CONDITION_ROOTED);
-	registerEnum(L, CONDITION_FEARED);
+	for (auto value : magic_enum::enum_values<ConditionType_t>()) {
+		registerMagicEnum(L, value);
+	}
 }
 
 void LuaEnums::initConditionIdEnums(lua_State* L) {
diff --git a/src/utils/utils_definitions.hpp b/src/utils/utils_definitions.hpp
index af2c40ba533..e2992379f0c 100644
--- a/src/utils/utils_definitions.hpp
+++ b/src/utils/utils_definitions.hpp
@@ -32,11 +32,11 @@ enum Icons_t {
 	ICON_GREATERHEX = 1 << 18,
 	ICON_ROOTED = 1 << 19,
 	ICON_FEARED = 1 << 20,
-	ICON_GOSHNAR1 = 1 << 21,
-	ICON_GOSHNAR2 = 1 << 22,
-	ICON_GOSHNAR3 = 1 << 23,
-	ICON_GOSHNAR4 = 1 << 24,
-	ICON_GOSHNAR5 = 1 << 25,
+	ICON_GOSHNARTAINT_1 = 1 << 21,
+	ICON_GOSHNARTAINT_2 = 1 << 22,
+	ICON_GOSHNARTAINT_3 = 1 << 23,
+	ICON_GOSHNARTAINT_4 = 1 << 24,
+	ICON_GOSHNARTAINT_5 = 1 << 25,
 	ICON_NEWMANASHIELD = 1 << 26,
 };
 

From f01418a4844b1553a92fd4ff4d1225d1ac1c00bc Mon Sep 17 00:00:00 2001
From: Eduardo Dantas <eduardo.dantas@hotmail.com.br>
Date: Mon, 15 Apr 2024 19:21:42 -0300
Subject: [PATCH 12/60] fix: cloak of terror mechanic

---
 .../scripts/quests/soul_war/soul_war_mechanics.lua     | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/data-otservbr-global/scripts/quests/soul_war/soul_war_mechanics.lua b/data-otservbr-global/scripts/quests/soul_war/soul_war_mechanics.lua
index 7a7103fa08f..9f8c5c4f031 100644
--- a/data-otservbr-global/scripts/quests/soul_war/soul_war_mechanics.lua
+++ b/data-otservbr-global/scripts/quests/soul_war/soul_war_mechanics.lua
@@ -828,7 +828,13 @@ function cloakOfTerrorHealthLoss.onHealthChange(creature, attacker, primaryDamag
 	end
 
 	if attacker:getPlayer() and primaryDamage > 0 or secondaryDamage > 0 then
-		Game.createItem(SoulWarQuest.theBloodOfCloakTerrorIds[1], 1, creature:getPosition())
+		local position = creature:getPosition()
+		local tile = Tile(position)
+		if tile then
+			if not tile:getItemById(SoulWarQuest.theBloodOfCloakTerrorIds[1]) then
+				Game.createItem(SoulWarQuest.theBloodOfCloakTerrorIds[1], 1, position)
+			end
+		end
 	end
 
 	return primaryDamage, primaryType, secondaryDamage, secondaryType
@@ -856,6 +862,8 @@ function theBloodOfCloakStep.onStepIn(creature, item, position, fromPosition)
 		monster:addHealth(healAmount)
 	end
 
+	item:remove()
+
 	return true
 end
 

From 316b668ebf8384777c27abd58816a6e6c92453c9 Mon Sep 17 00:00:00 2001
From: Eduardo Dantas <eduardo.dantas@hotmail.com.br>
Date: Tue, 16 Apr 2024 10:10:18 -0300
Subject: [PATCH 13/60] fix: change soul war table to lib folder

---
 data-otservbr-global/lib/quests/quest.lua                        | 1 +
 .../{scripts/lib/quests/soul-war.lua => lib/quests/soul_war.lua} | 0
 2 files changed, 1 insertion(+)
 rename data-otservbr-global/{scripts/lib/quests/soul-war.lua => lib/quests/soul_war.lua} (100%)

diff --git a/data-otservbr-global/lib/quests/quest.lua b/data-otservbr-global/lib/quests/quest.lua
index 21b1744fec6..392367c9d94 100644
--- a/data-otservbr-global/lib/quests/quest.lua
+++ b/data-otservbr-global/lib/quests/quest.lua
@@ -5,5 +5,6 @@ dofile(DATA_DIRECTORY .. "/lib/quests/killing_in_the_name_of.lua")
 dofile(DATA_DIRECTORY .. "/lib/quests/svargrond_arena.lua")
 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/soul_war.lua")
 dofile(DATA_DIRECTORY .. "/lib/quests/their_masters_voice.lua")
 dofile(DATA_DIRECTORY .. "/lib/quests/the_primal_ordeal.lua")
diff --git a/data-otservbr-global/scripts/lib/quests/soul-war.lua b/data-otservbr-global/lib/quests/soul_war.lua
similarity index 100%
rename from data-otservbr-global/scripts/lib/quests/soul-war.lua
rename to data-otservbr-global/lib/quests/soul_war.lua

From c3bbf05b1561e004e0fcde45f8c27f4e60081fd3 Mon Sep 17 00:00:00 2001
From: Eduardo Dantas <eduardo.dantas@hotmail.com.br>
Date: Tue, 16 Apr 2024 10:21:48 -0300
Subject: [PATCH 14/60] fix: no removable conditions on death

---
 src/creatures/combat/condition.cpp | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/src/creatures/combat/condition.cpp b/src/creatures/combat/condition.cpp
index 74eded14e1f..cb39c9c79d2 100644
--- a/src/creatures/combat/condition.cpp
+++ b/src/creatures/combat/condition.cpp
@@ -324,7 +324,14 @@ bool Condition::isRemovableOnDeath() const {
 		return false;
 	}
 
-	if (conditionType == CONDITION_SPELLCOOLDOWN || conditionType == CONDITION_SPELLGROUPCOOLDOWN || conditionType == CONDITION_MUTED) {
+	static const std::unordered_set<ConditionType_t> nonRemovableConditions = {
+		CONDITION_SPELLCOOLDOWN,
+		CONDITION_SPELLGROUPCOOLDOWN,
+		CONDITION_MUTED,
+		CONDITION_GOSHNARTAINT
+	};
+
+	if (nonRemovableConditions.find(conditionType) != nonRemovableConditions.end()) {
 		return false;
 	}
 

From cd7a82c894fc5543db733c4672bce5bb6f862c57 Mon Sep 17 00:00:00 2001
From: Eduardo Dantas <eduardo.dantas@hotmail.com.br>
Date: Tue, 16 Apr 2024 11:22:39 -0300
Subject: [PATCH 15/60] fix: nil value with boss levers

---
 data-otservbr-global/lib/quests/soul_war.lua  | 33 +++++++++++++++++++
 .../quests/soul_war/soul_war_mechanics.lua    | 31 -----------------
 data/scripts/lib/quests.lua                   |  2 ++
 3 files changed, 35 insertions(+), 31 deletions(-)
 create mode 100644 data/scripts/lib/quests.lua

diff --git a/data-otservbr-global/lib/quests/soul_war.lua b/data-otservbr-global/lib/quests/soul_war.lua
index 7ebe42b0441..aa71fc36d95 100644
--- a/data-otservbr-global/lib/quests/soul_war.lua
+++ b/data-otservbr-global/lib/quests/soul_war.lua
@@ -680,6 +680,39 @@ SoulWarQuest = {
 	},
 }
 
+function RegisterSoulWarBossesLevers()
+	-- Register levers
+	local goshnarsMaliceLever = BossLever(SoulWarQuest.levers.goshnarsMalice)
+	goshnarsMaliceLever:position(SoulWarQuest.levers.goshnarsMalicePosition)
+	goshnarsMaliceLever:register()
+	logger.debug("Registering soul war boss lever zone: {}", goshnarsMaliceLever:getZone():getName())
+
+	local goshnarsSpiteLever = BossLever(SoulWarQuest.levers.goshnarsSpite)
+	goshnarsSpiteLever:position(SoulWarQuest.levers.goshnarsSpitePosition)
+	goshnarsSpiteLever:register()
+	logger.debug("Registering soul war boss lever zone: {}", goshnarsSpiteLever:getZone():getName())
+
+	local goshnarsGreedLever = BossLever(SoulWarQuest.levers.goshnarsGreed)
+	goshnarsGreedLever:position(SoulWarQuest.levers.goshnarsGreedPosition)
+	goshnarsGreedLever:register()
+	logger.debug("Registering soul war boss lever zone: {}", goshnarsGreedLever:getZone():getName())
+
+	local goshnarsHatredLever = BossLever(SoulWarQuest.levers.goshnarsHatred)
+	goshnarsHatredLever:position(SoulWarQuest.levers.goshnarsHatredPosition)
+	goshnarsHatredLever:register()
+	logger.debug("Registering soul war boss lever zone: {}", goshnarsHatredLever:getZone():getName())
+
+	local goshnarsCrueltyLever = BossLever(SoulWarQuest.levers.goshnarsCruelty)
+	goshnarsCrueltyLever:position(SoulWarQuest.levers.goshnarsCrueltyPosition)
+	goshnarsCrueltyLever:register()
+	logger.debug("Registering soul war boss lever zone: {}", goshnarsCrueltyLever:getZone():getName())
+
+	local goshnarsMegalomaniaLever = BossLever(SoulWarQuest.levers.goshnarsMegalomania)
+	goshnarsMegalomaniaLever:position(SoulWarQuest.levers.goshnarsMegalomaniaPosition)
+	goshnarsMegalomaniaLever:register()
+	logger.debug("Registering soul war boss lever zone: {}", goshnarsMegalomaniaLever:getZone():getName())
+end
+
 -- Initialize ebb and flow zone area
 SoulWarQuest.ebbAndFlow.zone:addArea({ x = 33869, y = 30991, z = 8 }, { x = 33964, y = 31147, z = 9 })
 
diff --git a/data-otservbr-global/scripts/quests/soul_war/soul_war_mechanics.lua b/data-otservbr-global/scripts/quests/soul_war/soul_war_mechanics.lua
index 9f8c5c4f031..bc6d6a7e920 100644
--- a/data-otservbr-global/scripts/quests/soul_war/soul_war_mechanics.lua
+++ b/data-otservbr-global/scripts/quests/soul_war/soul_war_mechanics.lua
@@ -1,34 +1,3 @@
--- Register levers
-local goshnarsMaliceLever = BossLever(SoulWarQuest.levers.goshnarsMalice)
-goshnarsMaliceLever:position(SoulWarQuest.levers.goshnarsMalicePosition)
-goshnarsMaliceLever:register()
-logger.debug("Registering soul war boss lever zone: {}", goshnarsMaliceLever:getZone():getName())
-
-local goshnarsSpiteLever = BossLever(SoulWarQuest.levers.goshnarsSpite)
-goshnarsSpiteLever:position(SoulWarQuest.levers.goshnarsSpitePosition)
-goshnarsSpiteLever:register()
-logger.debug("Registering soul war boss lever zone: {}", goshnarsSpiteLever:getZone():getName())
-
-local goshnarsGreedLever = BossLever(SoulWarQuest.levers.goshnarsGreed)
-goshnarsGreedLever:position(SoulWarQuest.levers.goshnarsGreedPosition)
-goshnarsGreedLever:register()
-logger.debug("Registering soul war boss lever zone: {}", goshnarsGreedLever:getZone():getName())
-
-local goshnarsHatredLever = BossLever(SoulWarQuest.levers.goshnarsHatred)
-goshnarsHatredLever:position(SoulWarQuest.levers.goshnarsHatredPosition)
-goshnarsHatredLever:register()
-logger.debug("Registering soul war boss lever zone: {}", goshnarsHatredLever:getZone():getName())
-
-local goshnarsCrueltyLever = BossLever(SoulWarQuest.levers.goshnarsCruelty)
-goshnarsCrueltyLever:position(SoulWarQuest.levers.goshnarsCrueltyPosition)
-goshnarsCrueltyLever:register()
-logger.debug("Registering soul war boss lever zone: {}", goshnarsCrueltyLever:getZone():getName())
-
-local goshnarsMegalomaniaLever = BossLever(SoulWarQuest.levers.goshnarsMegalomania)
-goshnarsMegalomaniaLever:position(SoulWarQuest.levers.goshnarsMegalomaniaPosition)
-goshnarsMegalomaniaLever:register()
-logger.debug("Registering soul war boss lever zone: {}", goshnarsMegalomaniaLever:getZone():getName())
-
 local login = CreatureEvent("SoulWarLogin")
 
 function login.onLogin(player)
diff --git a/data/scripts/lib/quests.lua b/data/scripts/lib/quests.lua
new file mode 100644
index 00000000000..08005e34ae2
--- /dev/null
+++ b/data/scripts/lib/quests.lua
@@ -0,0 +1,2 @@
+-- We need to register the variables beforehand to avoid accessing null values.
+RegisterSoulWarBossesLevers()

From ce7c611dc2eb2ca4b27e157a2e538f58866853f9 Mon Sep 17 00:00:00 2001
From: GitHub Actions <github-actions[bot]@users.noreply.github.com>
Date: Mon, 29 Apr 2024 17:38:18 +0000
Subject: [PATCH 16/60] Code format - (Clang-format)

---
 src/lua/callbacks/callbacks_definitions.hpp | 2 +-
 src/lua/callbacks/event_callback.hpp        | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/lua/callbacks/callbacks_definitions.hpp b/src/lua/callbacks/callbacks_definitions.hpp
index ff8c05e7fab..6c19cc809c9 100644
--- a/src/lua/callbacks/callbacks_definitions.hpp
+++ b/src/lua/callbacks/callbacks_definitions.hpp
@@ -58,7 +58,7 @@ enum class EventCallback_t : uint16_t {
 	playerOnInventoryUpdate,
 	playerOnRotateItem,
 	playerOnWalk,
-  playerOnThink,
+	playerOnThink,
 	// Monster
 	monsterOnDropLoot,
 	monsterPostDropLoot,
diff --git a/src/lua/callbacks/event_callback.hpp b/src/lua/callbacks/event_callback.hpp
index f95bbce0b12..9e65480c246 100644
--- a/src/lua/callbacks/event_callback.hpp
+++ b/src/lua/callbacks/event_callback.hpp
@@ -131,7 +131,7 @@ class EventCallback : public Script {
 	void playerOnCombat(std::shared_ptr<Player> player, std::shared_ptr<Creature> target, std::shared_ptr<Item> item, CombatDamage &damage) const;
 	void playerOnInventoryUpdate(std::shared_ptr<Player> player, std::shared_ptr<Item> item, Slots_t slot, bool equip) const;
 	bool playerOnRotateItem(std::shared_ptr<Player> player, std::shared_ptr<Item> item, const Position &position) const;
-  void playerOnWalk(std::shared_ptr<Player> player, Direction &dir) const;
+	void playerOnWalk(std::shared_ptr<Player> player, Direction &dir) const;
 	void playerOnThink(std::shared_ptr<Player> player, uint32_t interval) const;
 
 	// Monster

From 164e093b22df25c90b19e3a57e2302183eb6a25d Mon Sep 17 00:00:00 2001
From: Pedro Henrique Alves Cruz <phac@cin.ufpe.br>
Date: Sun, 12 May 2024 02:36:22 -0300
Subject: [PATCH 17/60] fix: mechanics and npc flickering soul changes: - Added
 taints removal with words "taints" and "penalties" to npc flickering soul -
 Fixed soul war mechanics that should not be applied when in safe places
 (before hunt teleport) - Removed bag you desire as loot of soul war monsters

---
 data-otservbr-global/lib/quests/soul_war.lua  | 35 +++++++++++++++++--
 .../normal_monsters/bony_sea_devil.lua        |  1 -
 .../soul_war/normal_monsters/brachiodemon.lua |  1 -
 .../normal_monsters/branchy_crawler.lua       |  1 -
 .../normal_monsters/capricious_phantom.lua    |  1 -
 .../normal_monsters/distorted_phantom.lua     |  1 -
 .../normal_monsters/druid's_apparition.lua    |  1 -
 .../furious_crater/cloak_of_terror.lua        |  1 -
 .../furious_crater/courage_leech.lua          |  1 -
 .../furious_crater/vibrant_phantom.lua        |  1 -
 .../normal_monsters/infernal_demon.lua        |  1 -
 .../normal_monsters/infernal_phantom.lua      |  1 -
 .../normal_monsters/knight's_apparition.lua   |  1 -
 .../soul_war/normal_monsters/many_faces.lua   |  1 -
 .../normal_monsters/mould_phantom.lua         |  1 -
 .../normal_monsters/paladin's_apparition.lua  |  1 -
 .../soul_war/normal_monsters/rotten_golem.lua |  1 -
 .../normal_monsters/sorcerer's_apparition.lua |  1 -
 .../normal_monsters/turbulent_elemental.lua   |  1 -
 .../monster/undeads/hazardous_phantom.lua     |  1 -
 data-otservbr-global/npc/flickering_soul.lua  |  4 +++
 .../eventcallback_on_combat_taint.lua         |  2 +-
 .../quests/soul_war/soul_war_mechanics.lua    |  6 ++--
 23 files changed, 40 insertions(+), 26 deletions(-)

diff --git a/data-otservbr-global/lib/quests/soul_war.lua b/data-otservbr-global/lib/quests/soul_war.lua
index aa71fc36d95..987d65d5816 100644
--- a/data-otservbr-global/lib/quests/soul_war.lua
+++ b/data-otservbr-global/lib/quests/soul_war.lua
@@ -132,7 +132,15 @@ SoulWarQuest = {
 			["boss.goshnar's-megalomania-purple"] = "Dreadful Harvester",
 		},
 
-		caustrophobicInferno = Zone("zone.claustrophobic-inferno"),
+		safe = {
+			claustrophobicInferno = Zone("safezone.claustrophobic-inferno"),
+			mirroredNightmare = Zone("safezone.mirrored-nightmare"),
+			ebbAndFlow = Zone("safezone.ebb-and-flow"),
+			furiousCrater = Zone("safezone.furious-crater"),
+			rottenWasteland = Zone("safezone.rotten-wasteland"),
+		},
+
+		claustrophobicInferno = Zone("zone.claustrophobic-inferno"),
 		mirroredNightmare = Zone("zone.mirrored-nightmare"),
 		ebbAndFlow = Zone("zone.ebb-and-flow"),
 		furiousCrater = Zone("zone.furious-crater"),
@@ -716,8 +724,19 @@ end
 -- Initialize ebb and flow zone area
 SoulWarQuest.ebbAndFlow.zone:addArea({ x = 33869, y = 30991, z = 8 }, { x = 33964, y = 31147, z = 9 })
 
+-- Initialize safe areas (should not spawn monster, teleport, take damage from taint, etc)
+SoulWarQuest.areaZones.safe.ebbAndFlow:addArea({ x = 33887, y = 31015, z = 8 }, { x = 33920, y = 31024, z = 8 })
+
+SoulWarQuest.areaZones.safe.claustrophobicInferno:addArea({ x = 34002, y = 31008, z = 9 }, { x = 34019, y = 31019, z = 9 })
+
+SoulWarQuest.areaZones.safe.furiousCrater:addArea({ x = 33854, y = 31828, z = 3 }, { x = 33869, y = 31834, z = 3 })
+
+SoulWarQuest.areaZones.safe.rottenWasteland:addArea({ x = 33967, y = 31037, z = 11 }, { x = 33977, y = 31051, z = 11 })
+
+SoulWarQuest.areaZones.safe.mirroredNightmare:addArea({ x = 33884, y = 31181, z = 10 }, { x = 33892, y = 31198, z = 10 })
+
 -- Initialize bosses access for taint check
-SoulWarQuest.areaZones.caustrophobicInferno:addArea({ x = 33982, y = 30981, z = 9 }, { x = 34051, y = 31110, z = 11 })
+SoulWarQuest.areaZones.claustrophobicInferno:addArea({ x = 33982, y = 30981, z = 9 }, { x = 34051, y = 31110, z = 11 })
 
 SoulWarQuest.areaZones.ebbAndFlow:addArea({ x = 33873, y = 30994, z = 8 }, { x = 33968, y = 31150, z = 9 })
 
@@ -1075,7 +1094,7 @@ function Monster:tryTeleportToPlayer(sayMessage)
 	for i, spectator in ipairs(spectators) do
 		if spectator:isPlayer() then
 			local player = spectator:getPlayer()
-			if player:getTaintNameByNumber(1, true) then
+			if player:getTaintNameByNumber(1, true) and not player:isInSafeZone() then
 				local distance = self:getPosition():getDistance(player:getPosition())
 				if distance > maxDistance then
 					maxDistance = distance
@@ -1259,6 +1278,16 @@ function Monster:goshnarsDefenseIncrease(kvName)
 	end
 end
 
+function Player:isInSafeZone()
+	for zoneName, zone in pairs(SoulWarQuest.areaZones.safe) do
+		if zone and zone:isInZone(self:getPosition()) then
+			return true
+		end
+	end
+
+	return false
+end
+
 function Player:getSoulWarZoneMonster()
 	local zoneMonsterName = nil
 	for zoneName, monsterName in pairs(SoulWarQuest.areaZones.monsters) do
diff --git a/data-otservbr-global/monster/quests/soul_war/normal_monsters/bony_sea_devil.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/bony_sea_devil.lua
index 2737bd3a098..95120bfb0d2 100644
--- a/data-otservbr-global/monster/quests/soul_war/normal_monsters/bony_sea_devil.lua
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/bony_sea_devil.lua
@@ -100,7 +100,6 @@ monster.loot = {
 	{ name = "goblet of gloom", chance = 880 },
 	{ name = "glacier kilt", chance = 880 },
 	{ name = "glacial rod", chance = 1210 },
-	{ id = 34109, chance = 20 }, -- bag you desire
 }
 
 monster.attacks = {
diff --git a/data-otservbr-global/monster/quests/soul_war/normal_monsters/brachiodemon.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/brachiodemon.lua
index 378a15814c6..dfb94760041 100644
--- a/data-otservbr-global/monster/quests/soul_war/normal_monsters/brachiodemon.lua
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/brachiodemon.lua
@@ -103,7 +103,6 @@ monster.loot = {
 	{ name = "mastermind shield", chance = 420 },
 	{ name = "assassin dagger", chance = 340 },
 	{ name = "alloy legs", chance = 170 },
-	{ id = 34109, chance = 20 }, -- bag you desire
 }
 
 monster.attacks = {
diff --git a/data-otservbr-global/monster/quests/soul_war/normal_monsters/branchy_crawler.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/branchy_crawler.lua
index 0798c9f482f..87a491a29d9 100644
--- a/data-otservbr-global/monster/quests/soul_war/normal_monsters/branchy_crawler.lua
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/branchy_crawler.lua
@@ -98,7 +98,6 @@ monster.loot = {
 	{ name = "twiceslicer", chance = 420 },
 	{ name = "crystalline sword", chance = 390 },
 	{ name = "ruthless axe", chance = 330 },
-	{ id = 34109, chance = 20 }, -- bag you desire
 }
 
 monster.attacks = {
diff --git a/data-otservbr-global/monster/quests/soul_war/normal_monsters/capricious_phantom.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/capricious_phantom.lua
index 6a3b5ea0bbc..15221cdaf0a 100644
--- a/data-otservbr-global/monster/quests/soul_war/normal_monsters/capricious_phantom.lua
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/capricious_phantom.lua
@@ -97,7 +97,6 @@ monster.loot = {
 	{ id = 23542, chance = 1180 }, -- collar of blue plasma
 	{ name = "glacial rod", chance = 940 },
 	{ name = "ornate crossbow", chance = 940 },
-	{ id = 34109, chance = 20 }, -- bag you desire
 }
 
 monster.attacks = {
diff --git a/data-otservbr-global/monster/quests/soul_war/normal_monsters/distorted_phantom.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/distorted_phantom.lua
index a27ae569343..12d78f77654 100644
--- a/data-otservbr-global/monster/quests/soul_war/normal_monsters/distorted_phantom.lua
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/distorted_phantom.lua
@@ -96,7 +96,6 @@ monster.loot = {
 	{ name = "spellbook of warding", chance = 2890 },
 	{ id = 23531, chance = 1930 }, -- ring of green plasma
 	{ name = "glacial rod", chance = 1290 },
-	{ id = 34109, chance = 20 }, -- bag you desire
 }
 
 monster.attacks = {
diff --git a/data-otservbr-global/monster/quests/soul_war/normal_monsters/druid's_apparition.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/druid's_apparition.lua
index 6948a58fb53..c0436e734a3 100644
--- a/data-otservbr-global/monster/quests/soul_war/normal_monsters/druid's_apparition.lua
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/druid's_apparition.lua
@@ -94,7 +94,6 @@ monster.loot = {
 	{ name = "platinum amulet", chance = 1750 },
 	{ name = "glacier robe", chance = 880 },
 	{ id = 23544, chance = 440 }, -- collar of red plasma
-	{ id = 34109, chance = 20 }, -- bag you desire
 }
 
 monster.attacks = {
diff --git a/data-otservbr-global/monster/quests/soul_war/normal_monsters/furious_crater/cloak_of_terror.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/furious_crater/cloak_of_terror.lua
index 4048e0fd69e..c5e440ef02e 100644
--- a/data-otservbr-global/monster/quests/soul_war/normal_monsters/furious_crater/cloak_of_terror.lua
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/furious_crater/cloak_of_terror.lua
@@ -98,7 +98,6 @@ monster.loot = {
 	{ name = "blue gem", chance = 1490 },
 	{ name = "brooch of embracement", chance = 1490 },
 	{ name = "wand of defiance", chance = 990 },
-	{ id = 34109, chance = 20 }, -- bag you desire
 }
 
 monster.attacks = {
diff --git a/data-otservbr-global/monster/quests/soul_war/normal_monsters/furious_crater/courage_leech.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/furious_crater/courage_leech.lua
index 8e4a61b6ef0..4df38a95cc7 100644
--- a/data-otservbr-global/monster/quests/soul_war/normal_monsters/furious_crater/courage_leech.lua
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/furious_crater/courage_leech.lua
@@ -96,7 +96,6 @@ monster.loot = {
 	{ name = "stone skin amulet", chance = 910 },
 	{ name = "nightmare blade", chance = 1190 },
 	{ name = "demonrage sword", chance = 600 },
-	{ id = 34109, chance = 20 }, -- bag you desire
 }
 
 monster.attacks = {
diff --git a/data-otservbr-global/monster/quests/soul_war/normal_monsters/furious_crater/vibrant_phantom.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/furious_crater/vibrant_phantom.lua
index b6d4b89f024..f4ab16a5307 100644
--- a/data-otservbr-global/monster/quests/soul_war/normal_monsters/furious_crater/vibrant_phantom.lua
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/furious_crater/vibrant_phantom.lua
@@ -98,7 +98,6 @@ monster.loot = {
 	{ name = "violet crystal shard", chance = 1080 },
 	{ id = 23529, chance = 1080 }, -- ring of blue plasma
 	{ name = "green gem", chance = 1080 },
-	{ id = 34109, chance = 20 }, -- bag you desire
 }
 
 monster.attacks = {
diff --git a/data-otservbr-global/monster/quests/soul_war/normal_monsters/infernal_demon.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/infernal_demon.lua
index 8760d3b1757..9fa157fa7a0 100644
--- a/data-otservbr-global/monster/quests/soul_war/normal_monsters/infernal_demon.lua
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/infernal_demon.lua
@@ -98,7 +98,6 @@ monster.loot = {
 	{ name = "giant sword", chance = 2860 },
 	{ name = "magma boots", chance = 2290 },
 	{ name = "stone skin amulet", chance = 570 },
-	{ id = 34109, chance = 20 }, -- bag you desire
 }
 
 monster.attacks = {
diff --git a/data-otservbr-global/monster/quests/soul_war/normal_monsters/infernal_phantom.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/infernal_phantom.lua
index e8ef7b231f1..1704c7338e0 100644
--- a/data-otservbr-global/monster/quests/soul_war/normal_monsters/infernal_phantom.lua
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/infernal_phantom.lua
@@ -99,7 +99,6 @@ monster.loot = {
 	{ name = "crystal mace", chance = 1610 },
 	{ name = "war axe", chance = 1410 },
 	{ name = "warrior's axe", chance = 1410 },
-	{ id = 34109, chance = 20 }, -- bag you desire
 }
 
 monster.attacks = {
diff --git a/data-otservbr-global/monster/quests/soul_war/normal_monsters/knight's_apparition.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/knight's_apparition.lua
index 86893bfa01c..b9be9209d0e 100644
--- a/data-otservbr-global/monster/quests/soul_war/normal_monsters/knight's_apparition.lua
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/knight's_apparition.lua
@@ -92,7 +92,6 @@ monster.loot = {
 	{ name = "giant sword", chance = 1720 },
 	{ name = "stone skin amulet", chance = 1500 },
 	{ name = "crown shield", chance = 640 },
-	{ id = 34109, chance = 20 }, -- bag you desire
 }
 
 monster.attacks = {
diff --git a/data-otservbr-global/monster/quests/soul_war/normal_monsters/many_faces.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/many_faces.lua
index 627f1dc8052..ad924df93ff 100644
--- a/data-otservbr-global/monster/quests/soul_war/normal_monsters/many_faces.lua
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/many_faces.lua
@@ -99,7 +99,6 @@ monster.loot = {
 	{ name = "glacier robe", chance = 2130 },
 	{ name = "gruesome fan", chance = 610 },
 	{ name = "glacial rod", chance = 610 },
-	{ id = 34109, chance = 20 }, -- bag you desire
 }
 
 monster.attacks = {
diff --git a/data-otservbr-global/monster/quests/soul_war/normal_monsters/mould_phantom.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/mould_phantom.lua
index 54f3794360b..a2b38a76b90 100644
--- a/data-otservbr-global/monster/quests/soul_war/normal_monsters/mould_phantom.lua
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/mould_phantom.lua
@@ -97,7 +97,6 @@ monster.loot = {
 	{ id = 23529, chance = 1040 }, -- ring of blue plasma
 	{ name = "ornate crossbow", chance = 840 },
 	{ name = "crystal crossbow", chance = 620 },
-	{ id = 34109, chance = 20 }, -- bag you desire
 }
 
 monster.attacks = {
diff --git a/data-otservbr-global/monster/quests/soul_war/normal_monsters/paladin's_apparition.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/paladin's_apparition.lua
index 5162f5d1808..ab9db4fe484 100644
--- a/data-otservbr-global/monster/quests/soul_war/normal_monsters/paladin's_apparition.lua
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/paladin's_apparition.lua
@@ -95,7 +95,6 @@ monster.loot = {
 	{ name = "stone skin amulet", chance = 1560 },
 	{ id = 23542, chance = 1250 }, -- collar of blue plasma
 	{ id = 23529, chance = 1250 }, -- ring of blue plasma
-	{ id = 34109, chance = 20 }, -- bag you desire
 }
 
 monster.attacks = {
diff --git a/data-otservbr-global/monster/quests/soul_war/normal_monsters/rotten_golem.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/rotten_golem.lua
index bf9ea5b7555..f49c96d8b7d 100644
--- a/data-otservbr-global/monster/quests/soul_war/normal_monsters/rotten_golem.lua
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/rotten_golem.lua
@@ -95,7 +95,6 @@ monster.loot = {
 	{ name = "stone skin amulet", chance = 740 },
 	{ name = "terra mantle", chance = 510 },
 	{ name = "rubber cap", chance = 430 },
-	{ id = 34109, chance = 20 }, -- bag you desire
 }
 
 monster.attacks = {
diff --git a/data-otservbr-global/monster/quests/soul_war/normal_monsters/sorcerer's_apparition.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/sorcerer's_apparition.lua
index c054a0d584f..63faa04b271 100644
--- a/data-otservbr-global/monster/quests/soul_war/normal_monsters/sorcerer's_apparition.lua
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/sorcerer's_apparition.lua
@@ -96,7 +96,6 @@ monster.loot = {
 	{ name = "wand of starstorm", chance = 1310 },
 	{ name = "stone skin amulet", chance = 1310 },
 	{ name = "alloy legs", chance = 440 },
-	{ id = 34109, chance = 20 }, -- bag you desire
 }
 
 monster.attacks = {
diff --git a/data-otservbr-global/monster/quests/soul_war/normal_monsters/turbulent_elemental.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/turbulent_elemental.lua
index feaf706ae97..57cacb3ee76 100644
--- a/data-otservbr-global/monster/quests/soul_war/normal_monsters/turbulent_elemental.lua
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/turbulent_elemental.lua
@@ -95,7 +95,6 @@ monster.loot = {
 	{ name = "crystalline armor", chance = 710 },
 	{ name = "rubber cap", chance = 710 },
 	{ name = "stone skin amulet", chance = 470 },
-	{ id = 34109, chance = 20 }, -- bag you desire
 }
 
 monster.attacks = {
diff --git a/data-otservbr-global/monster/undeads/hazardous_phantom.lua b/data-otservbr-global/monster/undeads/hazardous_phantom.lua
index 4d3eb338b19..f1ba2b8c335 100644
--- a/data-otservbr-global/monster/undeads/hazardous_phantom.lua
+++ b/data-otservbr-global/monster/undeads/hazardous_phantom.lua
@@ -82,7 +82,6 @@ monster.loot = {
 	{ id = 282, chance = 1570 }, -- giant shimmering pearl
 	{ name = "wand of everblazing", chance = 790 },
 	{ id = 23542, chance = 790 }, -- collar of blue plasma
-	{ id = 34109, chance = 20 }, -- bag you desire
 }
 
 monster.attacks = {
diff --git a/data-otservbr-global/npc/flickering_soul.lua b/data-otservbr-global/npc/flickering_soul.lua
index 92828d77396..a00df70e338 100644
--- a/data-otservbr-global/npc/flickering_soul.lua
+++ b/data-otservbr-global/npc/flickering_soul.lua
@@ -181,6 +181,10 @@ local function playerSayCallback(npc, player, type, message)
 			message = "You have defeated all the Goshnar's Bosses. Your soul shines brighter with each victory."
 		end
 		npcHandler:say(message, npc, player)
+	elseif MsgContains(message, "taints") or MsgContains(message, "penalties") then
+		if player:getTaintLevel() == nil then
+			player:resetTaints()
+		end
 	end
 	return true
 end
diff --git a/data-otservbr-global/scripts/quests/soul_war/eventcallback_on_combat_taint.lua b/data-otservbr-global/scripts/quests/soul_war/eventcallback_on_combat_taint.lua
index 3e5ec34f930..936ab8502aa 100644
--- a/data-otservbr-global/scripts/quests/soul_war/eventcallback_on_combat_taint.lua
+++ b/data-otservbr-global/scripts/quests/soul_war/eventcallback_on_combat_taint.lua
@@ -111,7 +111,7 @@ function callback.playerOnThink(player, interval)
 
 	if accumulatedTime[playerId] >= 10000 then
 		local soulWarQuest = player:soulWarQuestKV()
-		if player:getSoulWarZoneMonster() ~= nil and player:getTaintNameByNumber(5) ~= nil then
+		if player:getSoulWarZoneMonster() ~= nil and not player:isInSafeZone() and player:getTaintNameByNumber(5) ~= nil then
 			local hpLoss = math.ceil(player:getHealth() * 0.1)
 			local manaLoss = math.ceil(player:getMana() * 0.1)
 			player:addHealth(-hpLoss)
diff --git a/data-otservbr-global/scripts/quests/soul_war/soul_war_mechanics.lua b/data-otservbr-global/scripts/quests/soul_war/soul_war_mechanics.lua
index bc6d6a7e920..dc7197176fa 100644
--- a/data-otservbr-global/scripts/quests/soul_war/soul_war_mechanics.lua
+++ b/data-otservbr-global/scripts/quests/soul_war/soul_war_mechanics.lua
@@ -301,11 +301,11 @@ local changeMap = TalkAction("/changeflowmap")
 
 function changeMap.onSay(player, words, param)
 	if param == "empty" then
-		Game.loadMap(SoulWarQuest.mapsPath.empty)
+		Game.loadMap(SoulWarQuest.ebbAndFlow.mapsPath.empty)
 	elseif param == "inundate" then
-		Game.loadMap(SoulWarQuest.mapsPath.inundate)
+		Game.loadMap(SoulWarQuest.ebbAndFlow.mapsPath.inundate)
 	elseif param == "ebb" then
-		Game.loadMap(SoulWarQuest.mapsPath.ebbFlow)
+		Game.loadMap(SoulWarQuest.ebbAndFlowmapsPath.ebbFlow)
 	end
 end
 

From b9ce9ff22660014a8c60233c1f3f089a7ac4b742 Mon Sep 17 00:00:00 2001
From: GitHub Actions <github-actions[bot]@users.noreply.github.com>
Date: Sun, 12 May 2024 12:46:47 +0000
Subject: [PATCH 18/60] Code format - (Clang-format)

---
 src/lua/functions/creatures/player/player_functions.cpp | 6 +++---
 src/lua/functions/creatures/player/player_functions.hpp | 8 ++++----
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/src/lua/functions/creatures/player/player_functions.cpp b/src/lua/functions/creatures/player/player_functions.cpp
index 6027dad7615..d4eb3eec79a 100644
--- a/src/lua/functions/creatures/player/player_functions.cpp
+++ b/src/lua/functions/creatures/player/player_functions.cpp
@@ -4302,8 +4302,8 @@ int PlayerFunctions::luaPlayerAddBadge(lua_State* L) {
 		reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND));
 		return 1;
 	}
-  
-  player->badge()->add(getNumber<uint8_t>(L, 2, 0));
+
+	player->badge()->add(getNumber<uint8_t>(L, 2, 0));
 	pushBoolean(L, true);
 	return 1;
 }
@@ -4373,4 +4373,4 @@ int PlayerFunctions::luaPlayerSendCreatureAppear(lua_State* L) {
 	player->sendCreatureAppear(player, player->getPosition(), isLogin);
 	pushBoolean(L, true);
 	return 1;
-}
\ No newline at end of file
+}
diff --git a/src/lua/functions/creatures/player/player_functions.hpp b/src/lua/functions/creatures/player/player_functions.hpp
index f483b9f9b6f..e9114a708e7 100644
--- a/src/lua/functions/creatures/player/player_functions.hpp
+++ b/src/lua/functions/creatures/player/player_functions.hpp
@@ -371,8 +371,8 @@ class PlayerFunctions final : LuaScriptInterface {
 		registerMethod(L, "Player", "addTitle", PlayerFunctions::luaPlayerAddTitle);
 		registerMethod(L, "Player", "getTitles", PlayerFunctions::luaPlayerGetTitles);
 		registerMethod(L, "Player", "setCurrentTitle", PlayerFunctions::luaPlayerSetCurrentTitle);
-  
-    registerMethod(L, "Player", "sendCreatureAppear", PlayerFunctions::luaPlayerSendCreatureAppear);
+
+		registerMethod(L, "Player", "sendCreatureAppear", PlayerFunctions::luaPlayerSendCreatureAppear);
 
 		GroupFunctions::init(L);
 		GuildFunctions::init(L);
@@ -734,7 +734,7 @@ class PlayerFunctions final : LuaScriptInterface {
 	static int luaPlayerGetTitles(lua_State* L);
 	static int luaPlayerSetCurrentTitle(lua_State* L);
 
-  static int luaPlayerSendCreatureAppear(lua_State* L);
-  
+	static int luaPlayerSendCreatureAppear(lua_State* L);
+
 	friend class CreatureFunctions;
 };

From beb3dba61d382ca865dd746686eea867cbe7997d Mon Sep 17 00:00:00 2001
From: Pedro Henrique Alves Cruz <phac@cin.ufpe.br>
Date: Sun, 12 May 2024 10:48:42 -0300
Subject: [PATCH 19/60] feat: claustrophobic inferno boss access mechanics
 changes: - Added raid system to access boss on claustrophobic inferno

---
 data-otservbr-global/lib/quests/soul_war.lua  | 118 +++++++++++++++---
 .../moveevent-claustrophobic-inferno-raid.lua |  85 +++++++++++++
 2 files changed, 189 insertions(+), 14 deletions(-)
 create mode 100644 data-otservbr-global/scripts/quests/soul_war/moveevent-claustrophobic-inferno-raid.lua

diff --git a/data-otservbr-global/lib/quests/soul_war.lua b/data-otservbr-global/lib/quests/soul_war.lua
index 987d65d5816..06ecc85fe04 100644
--- a/data-otservbr-global/lib/quests/soul_war.lua
+++ b/data-otservbr-global/lib/quests/soul_war.lua
@@ -117,6 +117,98 @@ SoulWarQuest = {
 		{ from = Position(33856, 31884, 5), to = Position(33857, 31865, 6), access = "third-floor-access", count = 70 },
 	},
 
+	safeZones = {
+		claustrophobicInferno = Zone("safe.claustrophobic-inferno"),
+		mirroredNightmare = Zone("safe.mirrored-nightmare"),
+		ebbAndFlow = Zone("safe.ebb-and-flow"),
+		furiousCrater = Zone("safe.furious-crater"),
+		rottenWasteland = Zone("safe.rotten-wasteland"),
+	},
+
+	raids = {
+		[1] = {
+			timerStarted = false,
+			sandTimerPositions = {
+				{ x = 34012, y = 31049, z = 9 },
+				{ x = 34013, y = 31049, z = 9 },
+				{ x = 34014, y = 31049, z = 9 },
+				{ x = 34015, y = 31049, z = 9 },
+			},
+			zone = Zone("raid.first-claustrophobic-inferno"),
+			spawns = {
+				Position(33991, 31064, 9), Position(34034, 31060, 9), Position(34028, 31067, 9), Position(34020, 31067, 9),
+				Position(34008, 31067, 9), Position(34001, 31059, 9), Position(33992, 31069, 9), Position(34002, 31072, 9), 
+				Position(34013, 31074, 9), Position(33998, 31060, 9), Position(34039, 31065, 9), Position(34032, 31072, 9), 
+			},
+			exitPosition = Position(34009, 31083, 9),
+			endEvent = nil,
+			kickEvent = nil,
+			spawnEvent = nil,
+			getZone = function()
+				return SoulWarQuest.raids[1].zone
+			end,
+			toggleTimer = function()
+				SoulWarQuest.raids[1].timerStarted = not SoulWarQuest.raids[1].timerStarted
+			end,
+		},
+		[2] = {
+			timerStarted = false,
+			sandTimerPositions = {
+				{ x = 34012, y = 31075, z = 10 },
+				{ x = 34011, y = 31075, z = 10 },
+				{ x = 34010, y = 31075, z = 10 },
+			},
+			zone = Zone("raid.second-claustrophobic-inferno"),
+			spawns = {
+				Position(33999, 31046, 10), Position(34011, 31047, 10), Position(34005, 31052, 10), Position(34015, 31052, 10),
+				Position(34021, 31044, 10), Position(34029, 31054, 10), Position(34037, 31052, 10), Position(34037, 31060, 10),
+				Position(34023, 31062, 10), Position(34012, 31061, 10), Position(33998, 31061, 10), Position(34005, 31052, 10),
+			},
+			exitPosition = Position(34011, 31028, 10),
+			endEvent = nil,
+			kickEvent = nil,
+			spawnEvent = nil,
+			getZone = function()
+				return SoulWarQuest.raids[2].zone
+			end,
+			toggleTimer = function()
+				SoulWarQuest.raids[2].timerStarted = not SoulWarQuest.raids[2].timerStarted
+			end,
+		},
+		[3] = {
+			timerStarted = false,
+			sandTimerPositions = {
+				{ x = 34009, y = 31036, z = 11 },
+				{ x = 34010, y = 31036, z = 11 },
+				{ x = 34011, y = 31036, z = 11 },
+				{ x = 34012, y = 31036, z = 11 },
+				{ x = 34013, y = 31036, z = 11 },
+				{ x = 34014, y = 31036, z = 11 },
+			},
+			zone = Zone("raid.third-claustrophobic-inferno"),
+			spawns = {
+				Position(34005, 31049, 11), Position(33999, 31051, 11), Position(33995, 31055, 11), Position(33995, 31055, 11),
+				Position(34001, 31069, 11), Position(33999, 31068, 11), Position(34016, 31068, 11), Position(34029, 31071, 11),
+				Position(34030, 31070, 11), Position(34038, 31066, 11), Position(34038, 31051, 11), Position(34033, 31051, 11),
+				Position(34025, 31048, 11), Position(34025, 31049, 11), Position(34013, 31058, 11), Position(34021, 31059, 11),
+				Position(34027, 31063, 11), Position(34007, 31063, 11), Position(34004, 31059, 11),
+			},
+			exitPosition = Position(34014, 31085, 11),
+			endEvent = nil,
+			kickEvent = nil,
+			spawnEvent = nil,
+			getZone = function()
+				return SoulWarQuest.raids[3].zone
+			end,
+			toggleTimer = function()
+				SoulWarQuest.raids[3].timerStarted = not SoulWarQuest.raids[3].timerStarted
+			end,
+		},
+		spawnTime = 10, -- seconds
+		suriviveTime = 2 * 60, -- 2 minutes
+		timeToKick = 5, -- seconds
+	},
+
 	areaZones = {
 		monsters = {
 			["zone.claustrophobic-inferno"] = "Brachiodemon",
@@ -132,14 +224,6 @@ SoulWarQuest = {
 			["boss.goshnar's-megalomania-purple"] = "Dreadful Harvester",
 		},
 
-		safe = {
-			claustrophobicInferno = Zone("safezone.claustrophobic-inferno"),
-			mirroredNightmare = Zone("safezone.mirrored-nightmare"),
-			ebbAndFlow = Zone("safezone.ebb-and-flow"),
-			furiousCrater = Zone("safezone.furious-crater"),
-			rottenWasteland = Zone("safezone.rotten-wasteland"),
-		},
-
 		claustrophobicInferno = Zone("zone.claustrophobic-inferno"),
 		mirroredNightmare = Zone("zone.mirrored-nightmare"),
 		ebbAndFlow = Zone("zone.ebb-and-flow"),
@@ -724,16 +808,22 @@ end
 -- Initialize ebb and flow zone area
 SoulWarQuest.ebbAndFlow.zone:addArea({ x = 33869, y = 30991, z = 8 }, { x = 33964, y = 31147, z = 9 })
 
+-- Initialize claustrophobic inferno raid zones
+
+SoulWarQuest.raids[1].zone:addArea({ x = 33985, y = 31053, z = 9}, { x = 34045, y = 31077, z = 9})
+SoulWarQuest.raids[2].zone:addArea({ x = 33988, y = 31042, z = 10}, { x = 34043, y = 31068, z = 10})
+SoulWarQuest.raids[3].zone:addArea({ x = 33987, y = 31043, z = 11}, { x = 34044, y = 31076, z = 11})
+
 -- Initialize safe areas (should not spawn monster, teleport, take damage from taint, etc)
-SoulWarQuest.areaZones.safe.ebbAndFlow:addArea({ x = 33887, y = 31015, z = 8 }, { x = 33920, y = 31024, z = 8 })
+SoulWarQuest.safeZones.ebbAndFlow:addArea({ x = 33887, y = 31015, z = 8 }, { x = 33920, y = 31024, z = 8 })
 
-SoulWarQuest.areaZones.safe.claustrophobicInferno:addArea({ x = 34002, y = 31008, z = 9 }, { x = 34019, y = 31019, z = 9 })
+SoulWarQuest.safeZones.claustrophobicInferno:addArea({ x = 34002, y = 31008, z = 9 }, { x = 34019, y = 31019, z = 9 })
 
-SoulWarQuest.areaZones.safe.furiousCrater:addArea({ x = 33854, y = 31828, z = 3 }, { x = 33869, y = 31834, z = 3 })
+SoulWarQuest.safeZones.furiousCrater:addArea({ x = 33854, y = 31828, z = 3 }, { x = 33869, y = 31834, z = 3 })
 
-SoulWarQuest.areaZones.safe.rottenWasteland:addArea({ x = 33967, y = 31037, z = 11 }, { x = 33977, y = 31051, z = 11 })
+SoulWarQuest.safeZones.rottenWasteland:addArea({ x = 33967, y = 31037, z = 11 }, { x = 33977, y = 31051, z = 11 })
 
-SoulWarQuest.areaZones.safe.mirroredNightmare:addArea({ x = 33884, y = 31181, z = 10 }, { x = 33892, y = 31198, z = 10 })
+SoulWarQuest.safeZones.mirroredNightmare:addArea({ x = 33884, y = 31181, z = 10 }, { x = 33892, y = 31198, z = 10 })
 
 -- Initialize bosses access for taint check
 SoulWarQuest.areaZones.claustrophobicInferno:addArea({ x = 33982, y = 30981, z = 9 }, { x = 34051, y = 31110, z = 11 })
@@ -1279,7 +1369,7 @@ function Monster:goshnarsDefenseIncrease(kvName)
 end
 
 function Player:isInSafeZone()
-	for zoneName, zone in pairs(SoulWarQuest.areaZones.safe) do
+	for zoneName, zone in pairs(SoulWarQuest.safeZones) do
 		if zone and zone:isInZone(self:getPosition()) then
 			return true
 		end
diff --git a/data-otservbr-global/scripts/quests/soul_war/moveevent-claustrophobic-inferno-raid.lua b/data-otservbr-global/scripts/quests/soul_war/moveevent-claustrophobic-inferno-raid.lua
new file mode 100644
index 00000000000..ea1d004b99a
--- /dev/null
+++ b/data-otservbr-global/scripts/quests/soul_war/moveevent-claustrophobic-inferno-raid.lua
@@ -0,0 +1,85 @@
+local firstRaid = MoveEvent()
+local secondRaid = MoveEvent()
+local thirdRaid = MoveEvent()
+
+local spawnMonsterName = "Brachiodemon"
+
+local firstRaidNumber = 1
+local secondRaidNumber = 2
+local thirdRaidNumber = 3
+
+local function createTeleportEffect(position)
+	position:sendMagicEffect(CONST_ME_TELEPORT)
+end
+
+local function spawnMonsters(raidNumber)
+	if not SoulWarQuest.raids[raidNumber].timerStarted then return end
+	for _, spawnPosition in pairs(SoulWarQuest.raids[raidNumber].spawns) do
+		addEvent(createTeleportEffect, 1000, spawnPosition)
+		addEvent(createTeleportEffect, 2000, spawnPosition)
+		addEvent(createTeleportEffect, 3000, spawnPosition)
+		addEvent(Game.createMonster, 4000, spawnMonsterName, spawnPosition, true, true)
+	end
+	SoulWarQuest.raids[raidNumber].spawnEvent = addEvent(spawnMonsters, SoulWarQuest.raids.spawnTime * 1000, raidNumber)
+end
+
+local function kickPlayers(zone, raidNumber)
+	SoulWarQuest.raids[raidNumber].toggleTimer()
+	for _, player in pairs(zone:getPlayers()) do
+		player:teleportTo(SoulWarQuest.raids[raidNumber].exitPosition)
+	end
+end
+
+local function endRaid(zone, raidNumber)
+	if SoulWarQuest.raids[raidNumber].spawnEvent then stopEvent(SoulWarQuest.raids[raidNumber].spawnEvent) end
+	for _, monster in pairs(zone:getMonsters()) do
+		if not monster:getMaster() then
+			monster:getPosition():sendMagicEffect(CONST_ME_POFF)
+			monster:remove()
+		end
+	end
+	SoulWarQuest.raids[raidNumber].kickEvent = addEvent(kickPlayers, SoulWarQuest.raids.timeToKick * 1000, zone, raidNumber)
+	logger.debug("Claustrophobic Inferno Raid #{} ended", raidNumber)
+end
+
+local function raid(zone, raidNumber)
+	if SoulWarQuest.raids[raidNumber].timerStarted then return end
+	logger.debug("Claustrophobic Inferno Raid #{} started", raidNumber)
+	SoulWarQuest.raids[raidNumber].toggleTimer()
+	SoulWarQuest.raids[raidNumber].spawnEvent = addEvent(spawnMonsters, SoulWarQuest.raids.spawnTime * 1000, raidNumber)
+	SoulWarQuest.raids[raidNumber].endEvent = addEvent(endRaid, SoulWarQuest.raids.suriviveTime * 1000, zone, raidNumber)
+end
+
+function firstRaid.onStepIn(creature, item, position, fromPosition)
+	if not creature:getPlayer() then return true end
+	raid(SoulWarQuest.raids[firstRaidNumber].getZone(), firstRaidNumber)
+	return true
+end
+
+function secondRaid.onStepIn(creature, item, position, fromPosition)
+	if not creature:getPlayer() then return true end
+	raid(SoulWarQuest.raids[secondRaidNumber].getZone(), secondRaidNumber)
+	return true
+end
+
+function thirdRaid.onStepIn(creature, item, position, fromPosition)
+	if not creature:getPlayer() then return true end
+	raid(SoulWarQuest.raids[thirdRaidNumber].getZone(), thirdRaidNumber)
+	return true
+end
+
+for _, pos in pairs(SoulWarQuest.raids[firstRaidNumber].sandTimerPositions) do
+	firstRaid:position(pos)
+end
+
+for _, pos in pairs(SoulWarQuest.raids[secondRaidNumber].sandTimerPositions) do
+	secondRaid:position(pos)
+end
+
+for _, position in pairs(SoulWarQuest.raids[thirdRaidNumber].sandTimerPositions) do
+	thirdRaid:position(position)
+end
+
+firstRaid:register()
+secondRaid:register()
+thirdRaid:register()

From 19346e2b601ed8322ba59524e871d4981880e0b9 Mon Sep 17 00:00:00 2001
From: GitHub Actions <github-actions[bot]@users.noreply.github.com>
Date: Sun, 12 May 2024 13:51:00 +0000
Subject: [PATCH 20/60] Lua code format - (Stylua)

---
 data-otservbr-global/lib/quests/soul_war.lua  | 60 ++++++++++++++-----
 .../moveevent-claustrophobic-inferno-raid.lua | 24 ++++++--
 2 files changed, 64 insertions(+), 20 deletions(-)

diff --git a/data-otservbr-global/lib/quests/soul_war.lua b/data-otservbr-global/lib/quests/soul_war.lua
index 06ecc85fe04..942609d61bb 100644
--- a/data-otservbr-global/lib/quests/soul_war.lua
+++ b/data-otservbr-global/lib/quests/soul_war.lua
@@ -136,9 +136,18 @@ SoulWarQuest = {
 			},
 			zone = Zone("raid.first-claustrophobic-inferno"),
 			spawns = {
-				Position(33991, 31064, 9), Position(34034, 31060, 9), Position(34028, 31067, 9), Position(34020, 31067, 9),
-				Position(34008, 31067, 9), Position(34001, 31059, 9), Position(33992, 31069, 9), Position(34002, 31072, 9), 
-				Position(34013, 31074, 9), Position(33998, 31060, 9), Position(34039, 31065, 9), Position(34032, 31072, 9), 
+				Position(33991, 31064, 9),
+				Position(34034, 31060, 9),
+				Position(34028, 31067, 9),
+				Position(34020, 31067, 9),
+				Position(34008, 31067, 9),
+				Position(34001, 31059, 9),
+				Position(33992, 31069, 9),
+				Position(34002, 31072, 9),
+				Position(34013, 31074, 9),
+				Position(33998, 31060, 9),
+				Position(34039, 31065, 9),
+				Position(34032, 31072, 9),
 			},
 			exitPosition = Position(34009, 31083, 9),
 			endEvent = nil,
@@ -160,9 +169,18 @@ SoulWarQuest = {
 			},
 			zone = Zone("raid.second-claustrophobic-inferno"),
 			spawns = {
-				Position(33999, 31046, 10), Position(34011, 31047, 10), Position(34005, 31052, 10), Position(34015, 31052, 10),
-				Position(34021, 31044, 10), Position(34029, 31054, 10), Position(34037, 31052, 10), Position(34037, 31060, 10),
-				Position(34023, 31062, 10), Position(34012, 31061, 10), Position(33998, 31061, 10), Position(34005, 31052, 10),
+				Position(33999, 31046, 10),
+				Position(34011, 31047, 10),
+				Position(34005, 31052, 10),
+				Position(34015, 31052, 10),
+				Position(34021, 31044, 10),
+				Position(34029, 31054, 10),
+				Position(34037, 31052, 10),
+				Position(34037, 31060, 10),
+				Position(34023, 31062, 10),
+				Position(34012, 31061, 10),
+				Position(33998, 31061, 10),
+				Position(34005, 31052, 10),
 			},
 			exitPosition = Position(34011, 31028, 10),
 			endEvent = nil,
@@ -187,11 +205,25 @@ SoulWarQuest = {
 			},
 			zone = Zone("raid.third-claustrophobic-inferno"),
 			spawns = {
-				Position(34005, 31049, 11), Position(33999, 31051, 11), Position(33995, 31055, 11), Position(33995, 31055, 11),
-				Position(34001, 31069, 11), Position(33999, 31068, 11), Position(34016, 31068, 11), Position(34029, 31071, 11),
-				Position(34030, 31070, 11), Position(34038, 31066, 11), Position(34038, 31051, 11), Position(34033, 31051, 11),
-				Position(34025, 31048, 11), Position(34025, 31049, 11), Position(34013, 31058, 11), Position(34021, 31059, 11),
-				Position(34027, 31063, 11), Position(34007, 31063, 11), Position(34004, 31059, 11),
+				Position(34005, 31049, 11),
+				Position(33999, 31051, 11),
+				Position(33995, 31055, 11),
+				Position(33995, 31055, 11),
+				Position(34001, 31069, 11),
+				Position(33999, 31068, 11),
+				Position(34016, 31068, 11),
+				Position(34029, 31071, 11),
+				Position(34030, 31070, 11),
+				Position(34038, 31066, 11),
+				Position(34038, 31051, 11),
+				Position(34033, 31051, 11),
+				Position(34025, 31048, 11),
+				Position(34025, 31049, 11),
+				Position(34013, 31058, 11),
+				Position(34021, 31059, 11),
+				Position(34027, 31063, 11),
+				Position(34007, 31063, 11),
+				Position(34004, 31059, 11),
 			},
 			exitPosition = Position(34014, 31085, 11),
 			endEvent = nil,
@@ -810,9 +842,9 @@ SoulWarQuest.ebbAndFlow.zone:addArea({ x = 33869, y = 30991, z = 8 }, { x = 3396
 
 -- Initialize claustrophobic inferno raid zones
 
-SoulWarQuest.raids[1].zone:addArea({ x = 33985, y = 31053, z = 9}, { x = 34045, y = 31077, z = 9})
-SoulWarQuest.raids[2].zone:addArea({ x = 33988, y = 31042, z = 10}, { x = 34043, y = 31068, z = 10})
-SoulWarQuest.raids[3].zone:addArea({ x = 33987, y = 31043, z = 11}, { x = 34044, y = 31076, z = 11})
+SoulWarQuest.raids[1].zone:addArea({ x = 33985, y = 31053, z = 9 }, { x = 34045, y = 31077, z = 9 })
+SoulWarQuest.raids[2].zone:addArea({ x = 33988, y = 31042, z = 10 }, { x = 34043, y = 31068, z = 10 })
+SoulWarQuest.raids[3].zone:addArea({ x = 33987, y = 31043, z = 11 }, { x = 34044, y = 31076, z = 11 })
 
 -- Initialize safe areas (should not spawn monster, teleport, take damage from taint, etc)
 SoulWarQuest.safeZones.ebbAndFlow:addArea({ x = 33887, y = 31015, z = 8 }, { x = 33920, y = 31024, z = 8 })
diff --git a/data-otservbr-global/scripts/quests/soul_war/moveevent-claustrophobic-inferno-raid.lua b/data-otservbr-global/scripts/quests/soul_war/moveevent-claustrophobic-inferno-raid.lua
index ea1d004b99a..944bd0dbda8 100644
--- a/data-otservbr-global/scripts/quests/soul_war/moveevent-claustrophobic-inferno-raid.lua
+++ b/data-otservbr-global/scripts/quests/soul_war/moveevent-claustrophobic-inferno-raid.lua
@@ -13,7 +13,9 @@ local function createTeleportEffect(position)
 end
 
 local function spawnMonsters(raidNumber)
-	if not SoulWarQuest.raids[raidNumber].timerStarted then return end
+	if not SoulWarQuest.raids[raidNumber].timerStarted then
+		return
+	end
 	for _, spawnPosition in pairs(SoulWarQuest.raids[raidNumber].spawns) do
 		addEvent(createTeleportEffect, 1000, spawnPosition)
 		addEvent(createTeleportEffect, 2000, spawnPosition)
@@ -31,7 +33,9 @@ local function kickPlayers(zone, raidNumber)
 end
 
 local function endRaid(zone, raidNumber)
-	if SoulWarQuest.raids[raidNumber].spawnEvent then stopEvent(SoulWarQuest.raids[raidNumber].spawnEvent) end
+	if SoulWarQuest.raids[raidNumber].spawnEvent then
+		stopEvent(SoulWarQuest.raids[raidNumber].spawnEvent)
+	end
 	for _, monster in pairs(zone:getMonsters()) do
 		if not monster:getMaster() then
 			monster:getPosition():sendMagicEffect(CONST_ME_POFF)
@@ -43,7 +47,9 @@ local function endRaid(zone, raidNumber)
 end
 
 local function raid(zone, raidNumber)
-	if SoulWarQuest.raids[raidNumber].timerStarted then return end
+	if SoulWarQuest.raids[raidNumber].timerStarted then
+		return
+	end
 	logger.debug("Claustrophobic Inferno Raid #{} started", raidNumber)
 	SoulWarQuest.raids[raidNumber].toggleTimer()
 	SoulWarQuest.raids[raidNumber].spawnEvent = addEvent(spawnMonsters, SoulWarQuest.raids.spawnTime * 1000, raidNumber)
@@ -51,19 +57,25 @@ local function raid(zone, raidNumber)
 end
 
 function firstRaid.onStepIn(creature, item, position, fromPosition)
-	if not creature:getPlayer() then return true end
+	if not creature:getPlayer() then
+		return true
+	end
 	raid(SoulWarQuest.raids[firstRaidNumber].getZone(), firstRaidNumber)
 	return true
 end
 
 function secondRaid.onStepIn(creature, item, position, fromPosition)
-	if not creature:getPlayer() then return true end
+	if not creature:getPlayer() then
+		return true
+	end
 	raid(SoulWarQuest.raids[secondRaidNumber].getZone(), secondRaidNumber)
 	return true
 end
 
 function thirdRaid.onStepIn(creature, item, position, fromPosition)
-	if not creature:getPlayer() then return true end
+	if not creature:getPlayer() then
+		return true
+	end
 	raid(SoulWarQuest.raids[thirdRaidNumber].getZone(), thirdRaidNumber)
 	return true
 end

From 5c7f1214fcb055a9dd82b419d8f5fa27e4253ed5 Mon Sep 17 00:00:00 2001
From: Pedro Henrique Alves Cruz <phac@cin.ufpe.br>
Date: Mon, 13 May 2024 05:42:05 -0300
Subject: [PATCH 21/60] fix: dont start raid when player exits the raid zones
 changes: - Added checkage to not start raid when player pass on sandtimer
 from raid zones

---
 .../moveevent-claustrophobic-inferno-raid.lua       | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/data-otservbr-global/scripts/quests/soul_war/moveevent-claustrophobic-inferno-raid.lua b/data-otservbr-global/scripts/quests/soul_war/moveevent-claustrophobic-inferno-raid.lua
index 944bd0dbda8..53684b1052e 100644
--- a/data-otservbr-global/scripts/quests/soul_war/moveevent-claustrophobic-inferno-raid.lua
+++ b/data-otservbr-global/scripts/quests/soul_war/moveevent-claustrophobic-inferno-raid.lua
@@ -46,11 +46,14 @@ local function endRaid(zone, raidNumber)
 	logger.debug("Claustrophobic Inferno Raid #{} ended", raidNumber)
 end
 
-local function raid(zone, raidNumber)
+local function raid(zone, raidNumber, position, fromPosition)
+	if fromPosition.y == position.y - (raidNumber % 2 ~= 0 and -1 or 1) then -- if player comes from the raid zone don't start the raid
+		return
+	end
 	if SoulWarQuest.raids[raidNumber].timerStarted then
 		return
 	end
-	logger.debug("Claustrophobic Inferno Raid #{} started", raidNumber)
+	logger.warn("Claustrophobic Inferno Raid #{} started", raidNumber)
 	SoulWarQuest.raids[raidNumber].toggleTimer()
 	SoulWarQuest.raids[raidNumber].spawnEvent = addEvent(spawnMonsters, SoulWarQuest.raids.spawnTime * 1000, raidNumber)
 	SoulWarQuest.raids[raidNumber].endEvent = addEvent(endRaid, SoulWarQuest.raids.suriviveTime * 1000, zone, raidNumber)
@@ -60,7 +63,7 @@ function firstRaid.onStepIn(creature, item, position, fromPosition)
 	if not creature:getPlayer() then
 		return true
 	end
-	raid(SoulWarQuest.raids[firstRaidNumber].getZone(), firstRaidNumber)
+	raid(SoulWarQuest.raids[firstRaidNumber].getZone(), firstRaidNumber, position, fromPosition)
 	return true
 end
 
@@ -68,7 +71,7 @@ function secondRaid.onStepIn(creature, item, position, fromPosition)
 	if not creature:getPlayer() then
 		return true
 	end
-	raid(SoulWarQuest.raids[secondRaidNumber].getZone(), secondRaidNumber)
+	raid(SoulWarQuest.raids[secondRaidNumber].getZone(), secondRaidNumber, position, fromPosition)
 	return true
 end
 
@@ -76,7 +79,7 @@ function thirdRaid.onStepIn(creature, item, position, fromPosition)
 	if not creature:getPlayer() then
 		return true
 	end
-	raid(SoulWarQuest.raids[thirdRaidNumber].getZone(), thirdRaidNumber)
+	raid(SoulWarQuest.raids[thirdRaidNumber].getZone(), thirdRaidNumber, position, fromPosition)
 	return true
 end
 

From 4c7402db7217887a7d0a2ea630eddb679db063c9 Mon Sep 17 00:00:00 2001
From: Pedro Henrique Alves Cruz <phac@cin.ufpe.br>
Date: Sun, 26 May 2024 17:10:01 -0300
Subject: [PATCH 22/60] improvement: claustrophobic inferno raids and safe
 zones

---
 data-otservbr-global/lib/quests/soul_war.lua  |  79 ++++-------
 .../eventcallback_on_combat_taint.lua         |   2 +-
 .../moveevent-claustrophobic-inferno-raid.lua | 133 ++++++------------
 .../soul_war/moveevent-soul_war_entrances.lua |   3 -
 src/game/game.cpp                             |   1 +
 5 files changed, 77 insertions(+), 141 deletions(-)

diff --git a/data-otservbr-global/lib/quests/soul_war.lua b/data-otservbr-global/lib/quests/soul_war.lua
index 942609d61bb..b70f42aa85e 100644
--- a/data-otservbr-global/lib/quests/soul_war.lua
+++ b/data-otservbr-global/lib/quests/soul_war.lua
@@ -117,15 +117,7 @@ SoulWarQuest = {
 		{ from = Position(33856, 31884, 5), to = Position(33857, 31865, 6), access = "third-floor-access", count = 70 },
 	},
 
-	safeZones = {
-		claustrophobicInferno = Zone("safe.claustrophobic-inferno"),
-		mirroredNightmare = Zone("safe.mirrored-nightmare"),
-		ebbAndFlow = Zone("safe.ebb-and-flow"),
-		furiousCrater = Zone("safe.furious-crater"),
-		rottenWasteland = Zone("safe.rotten-wasteland"),
-	},
-
-	raids = {
+	claustrophobicInfernoRaids = {
 		[1] = {
 			timerStarted = false,
 			sandTimerPositions = {
@@ -149,15 +141,12 @@ SoulWarQuest = {
 				Position(34039, 31065, 9),
 				Position(34032, 31072, 9),
 			},
-			exitPosition = Position(34009, 31083, 9),
-			endEvent = nil,
-			kickEvent = nil,
-			spawnEvent = nil,
+			exitPosition = { x = 34009, y = 31083, z = 9 },
 			getZone = function()
-				return SoulWarQuest.raids[1].zone
+				return SoulWarQuest.claustrophobicInfernoRaids[1].zone
 			end,
 			toggleTimer = function()
-				SoulWarQuest.raids[1].timerStarted = not SoulWarQuest.raids[1].timerStarted
+				SoulWarQuest.claustrophobicInfernoRaids[1].timerStarted = not SoulWarQuest.claustrophobicInfernoRaids[1].timerStarted
 			end,
 		},
 		[2] = {
@@ -182,15 +171,12 @@ SoulWarQuest = {
 				Position(33998, 31061, 10),
 				Position(34005, 31052, 10),
 			},
-			exitPosition = Position(34011, 31028, 10),
-			endEvent = nil,
-			kickEvent = nil,
-			spawnEvent = nil,
+			exitPosition = { x = 34011, y = 31028, z = 10 },
 			getZone = function()
-				return SoulWarQuest.raids[2].zone
+				return SoulWarQuest.claustrophobicInfernoRaids[2].zone
 			end,
 			toggleTimer = function()
-				SoulWarQuest.raids[2].timerStarted = not SoulWarQuest.raids[2].timerStarted
+				SoulWarQuest.claustrophobicInfernoRaids[2].timerStarted = not SoulWarQuest.claustrophobicInfernoRaids[2].timerStarted
 			end,
 		},
 		[3] = {
@@ -225,15 +211,12 @@ SoulWarQuest = {
 				Position(34007, 31063, 11),
 				Position(34004, 31059, 11),
 			},
-			exitPosition = Position(34014, 31085, 11),
-			endEvent = nil,
-			kickEvent = nil,
-			spawnEvent = nil,
+			exitPosition = { x = 34014, y = 31085, z = 11 },
 			getZone = function()
-				return SoulWarQuest.raids[3].zone
+				return SoulWarQuest.claustrophobicInfernoRaids[3].zone
 			end,
 			toggleTimer = function()
-				SoulWarQuest.raids[3].timerStarted = not SoulWarQuest.raids[3].timerStarted
+				SoulWarQuest.claustrophobicInfernoRaids[3].timerStarted = not SoulWarQuest.claustrophobicInfernoRaids[3].timerStarted
 			end,
 		},
 		spawnTime = 10, -- seconds
@@ -842,20 +825,15 @@ SoulWarQuest.ebbAndFlow.zone:addArea({ x = 33869, y = 30991, z = 8 }, { x = 3396
 
 -- Initialize claustrophobic inferno raid zones
 
-SoulWarQuest.raids[1].zone:addArea({ x = 33985, y = 31053, z = 9 }, { x = 34045, y = 31077, z = 9 })
-SoulWarQuest.raids[2].zone:addArea({ x = 33988, y = 31042, z = 10 }, { x = 34043, y = 31068, z = 10 })
-SoulWarQuest.raids[3].zone:addArea({ x = 33987, y = 31043, z = 11 }, { x = 34044, y = 31076, z = 11 })
-
--- Initialize safe areas (should not spawn monster, teleport, take damage from taint, etc)
-SoulWarQuest.safeZones.ebbAndFlow:addArea({ x = 33887, y = 31015, z = 8 }, { x = 33920, y = 31024, z = 8 })
-
-SoulWarQuest.safeZones.claustrophobicInferno:addArea({ x = 34002, y = 31008, z = 9 }, { x = 34019, y = 31019, z = 9 })
+SoulWarQuest.claustrophobicInfernoRaids[1].zone:addArea({ x = 33985, y = 31053, z = 9 }, { x = 34045, y = 31077, z = 9 })
+SoulWarQuest.claustrophobicInfernoRaids[2].zone:addArea({ x = 33988, y = 31042, z = 10 }, { x = 34043, y = 31068, z = 10 })
+SoulWarQuest.claustrophobicInfernoRaids[3].zone:addArea({ x = 33987, y = 31043, z = 11 }, { x = 34044, y = 31076, z = 11 })
 
-SoulWarQuest.safeZones.furiousCrater:addArea({ x = 33854, y = 31828, z = 3 }, { x = 33869, y = 31834, z = 3 })
+-- Add remove destination
 
-SoulWarQuest.safeZones.rottenWasteland:addArea({ x = 33967, y = 31037, z = 11 }, { x = 33977, y = 31051, z = 11 })
-
-SoulWarQuest.safeZones.mirroredNightmare:addArea({ x = 33884, y = 31181, z = 10 }, { x = 33892, y = 31198, z = 10 })
+SoulWarQuest.claustrophobicInfernoRaids[1].zone:setRemoveDestination(SoulWarQuest.claustrophobicInfernoRaids[1].exitPosition)
+SoulWarQuest.claustrophobicInfernoRaids[2].zone:setRemoveDestination(SoulWarQuest.claustrophobicInfernoRaids[2].exitPosition)
+SoulWarQuest.claustrophobicInfernoRaids[3].zone:setRemoveDestination(SoulWarQuest.claustrophobicInfernoRaids[3].exitPosition)
 
 -- Initialize bosses access for taint check
 SoulWarQuest.areaZones.claustrophobicInferno:addArea({ x = 33982, y = 30981, z = 9 }, { x = 34051, y = 31110, z = 11 })
@@ -868,6 +846,17 @@ SoulWarQuest.areaZones.rottenWasteland:addArea({ x = 33980, y = 30986, z = 11 },
 
 SoulWarQuest.areaZones.mirroredNightmare:addArea({ x = 33877, y = 31164, z = 9 }, { x = 33991, y = 31241, z = 13 })
 
+-- Initialize safe areas (should not spawn monster, teleport, take damage from taint, etc)
+SoulWarQuest.areaZones.claustrophobicInferno:subtractArea({ x = 34002, y = 31008, z = 9 }, { x = 34019, y = 31019, z = 9 })
+
+SoulWarQuest.areaZones.ebbAndFlow:subtractArea({ x = 33887, y = 31015, z = 8 }, { x = 33920, y = 31024, z = 8 })
+
+SoulWarQuest.areaZones.furiousCrater:subtractArea({ x = 33854, y = 31828, z = 3 }, { x = 33869, y = 31834, z = 3 })
+
+SoulWarQuest.areaZones.rottenWasteland:subtractArea({ x = 33967, y = 31037, z = 11 }, { x = 33977, y = 31051, z = 11 })
+
+SoulWarQuest.areaZones.mirroredNightmare:subtractArea({ x = 33884, y = 31181, z = 10 }, { x = 33892, y = 31198, z = 10 })
+
 SoulCagePosition = Position(33709, 31596, 14)
 TaintDurationSeconds = 14 * 24 * 60 * 60 -- 14 days
 GreedbeastKills = 0
@@ -1216,7 +1205,7 @@ function Monster:tryTeleportToPlayer(sayMessage)
 	for i, spectator in ipairs(spectators) do
 		if spectator:isPlayer() then
 			local player = spectator:getPlayer()
-			if player:getTaintNameByNumber(1, true) and not player:isInSafeZone() then
+			if player:getTaintNameByNumber(1, true) and player:getSoulWarZoneMonster() ~= nil then
 				local distance = self:getPosition():getDistance(player:getPosition())
 				if distance > maxDistance then
 					maxDistance = distance
@@ -1400,16 +1389,6 @@ function Monster:goshnarsDefenseIncrease(kvName)
 	end
 end
 
-function Player:isInSafeZone()
-	for zoneName, zone in pairs(SoulWarQuest.safeZones) do
-		if zone and zone:isInZone(self:getPosition()) then
-			return true
-		end
-	end
-
-	return false
-end
-
 function Player:getSoulWarZoneMonster()
 	local zoneMonsterName = nil
 	for zoneName, monsterName in pairs(SoulWarQuest.areaZones.monsters) do
diff --git a/data-otservbr-global/scripts/quests/soul_war/eventcallback_on_combat_taint.lua b/data-otservbr-global/scripts/quests/soul_war/eventcallback_on_combat_taint.lua
index 936ab8502aa..3e5ec34f930 100644
--- a/data-otservbr-global/scripts/quests/soul_war/eventcallback_on_combat_taint.lua
+++ b/data-otservbr-global/scripts/quests/soul_war/eventcallback_on_combat_taint.lua
@@ -111,7 +111,7 @@ function callback.playerOnThink(player, interval)
 
 	if accumulatedTime[playerId] >= 10000 then
 		local soulWarQuest = player:soulWarQuestKV()
-		if player:getSoulWarZoneMonster() ~= nil and not player:isInSafeZone() and player:getTaintNameByNumber(5) ~= nil then
+		if player:getSoulWarZoneMonster() ~= nil and player:getTaintNameByNumber(5) ~= nil then
 			local hpLoss = math.ceil(player:getHealth() * 0.1)
 			local manaLoss = math.ceil(player:getMana() * 0.1)
 			player:addHealth(-hpLoss)
diff --git a/data-otservbr-global/scripts/quests/soul_war/moveevent-claustrophobic-inferno-raid.lua b/data-otservbr-global/scripts/quests/soul_war/moveevent-claustrophobic-inferno-raid.lua
index 53684b1052e..4f0cac5a3f0 100644
--- a/data-otservbr-global/scripts/quests/soul_war/moveevent-claustrophobic-inferno-raid.lua
+++ b/data-otservbr-global/scripts/quests/soul_war/moveevent-claustrophobic-inferno-raid.lua
@@ -4,97 +4,56 @@ local thirdRaid = MoveEvent()
 
 local spawnMonsterName = "Brachiodemon"
 
-local firstRaidNumber = 1
-local secondRaidNumber = 2
-local thirdRaidNumber = 3
-
-local function createTeleportEffect(position)
-	position:sendMagicEffect(CONST_ME_TELEPORT)
-end
-
-local function spawnMonsters(raidNumber)
-	if not SoulWarQuest.raids[raidNumber].timerStarted then
-		return
-	end
-	for _, spawnPosition in pairs(SoulWarQuest.raids[raidNumber].spawns) do
-		addEvent(createTeleportEffect, 1000, spawnPosition)
-		addEvent(createTeleportEffect, 2000, spawnPosition)
-		addEvent(createTeleportEffect, 3000, spawnPosition)
-		addEvent(Game.createMonster, 4000, spawnMonsterName, spawnPosition, true, true)
-	end
-	SoulWarQuest.raids[raidNumber].spawnEvent = addEvent(spawnMonsters, SoulWarQuest.raids.spawnTime * 1000, raidNumber)
-end
-
-local function kickPlayers(zone, raidNumber)
-	SoulWarQuest.raids[raidNumber].toggleTimer()
-	for _, player in pairs(zone:getPlayers()) do
-		player:teleportTo(SoulWarQuest.raids[raidNumber].exitPosition)
-	end
-end
-
-local function endRaid(zone, raidNumber)
-	if SoulWarQuest.raids[raidNumber].spawnEvent then
-		stopEvent(SoulWarQuest.raids[raidNumber].spawnEvent)
-	end
-	for _, monster in pairs(zone:getMonsters()) do
-		if not monster:getMaster() then
-			monster:getPosition():sendMagicEffect(CONST_ME_POFF)
-			monster:remove()
+-- Registering encounters, stages and move events
+for raidNumber, raid in ipairs(SoulWarQuest.claustrophobicInfernoRaids) do
+	-- Registering encounter
+	local raidName = string.format("Claustrophobic Inferno Raid %d", raidNumber)
+	local encounter = Encounter(raidName, {
+		zone = raid.getZone(),
+		timeToSpawnMonsters = "3s"
+	})
+
+	local spawnTimes = (SoulWarQuest.claustrophobicInfernoRaids.suriviveTime) / SoulWarQuest.claustrophobicInfernoRaids.spawnTime
+
+	-- Registering encounter stages
+	for i = 1, spawnTimes do
+		encounter:addSpawnMonsters({
+			{
+				name = spawnMonsterName,
+				positions = raid.spawns
+			},
+		}):autoAdvance(SoulWarQuest.claustrophobicInfernoRaids.spawnTime * 1000)
+	end
+
+	function encounter:onReset(position)
+		encounter:removeMonsters()
+		addEvent(function(zone)
+			zone:refresh()
+			zone:removePlayers()
+		end, SoulWarQuest.claustrophobicInfernoRaids.timeToKick * 1000, raid.getZone())
+		logger.debug("{} has ended", raidName)
+	end
+
+	encounter:register()
+
+	-- Registering move event
+	local raidMoveEvent = MoveEvent()
+
+	function raidMoveEvent.onStepIn(creature, item, position, fromPosition)
+		if not creature:getPlayer() then
+			return true
 		end
-	end
-	SoulWarQuest.raids[raidNumber].kickEvent = addEvent(kickPlayers, SoulWarQuest.raids.timeToKick * 1000, zone, raidNumber)
-	logger.debug("Claustrophobic Inferno Raid #{} ended", raidNumber)
-end
-
-local function raid(zone, raidNumber, position, fromPosition)
-	if fromPosition.y == position.y - (raidNumber % 2 ~= 0 and -1 or 1) then -- if player comes from the raid zone don't start the raid
-		return
-	end
-	if SoulWarQuest.raids[raidNumber].timerStarted then
-		return
-	end
-	logger.warn("Claustrophobic Inferno Raid #{} started", raidNumber)
-	SoulWarQuest.raids[raidNumber].toggleTimer()
-	SoulWarQuest.raids[raidNumber].spawnEvent = addEvent(spawnMonsters, SoulWarQuest.raids.spawnTime * 1000, raidNumber)
-	SoulWarQuest.raids[raidNumber].endEvent = addEvent(endRaid, SoulWarQuest.raids.suriviveTime * 1000, zone, raidNumber)
-end
-
-function firstRaid.onStepIn(creature, item, position, fromPosition)
-	if not creature:getPlayer() then
+		if fromPosition.y == position.y - (raidNumber % 2 ~= 0 and -1 or 1) then -- if player comes from the raid zone don't start the raid
+			return
+		end
+		logger.debug("{} has started", raidName)
+		encounter:start()
 		return true
 	end
-	raid(SoulWarQuest.raids[firstRaidNumber].getZone(), firstRaidNumber, position, fromPosition)
-	return true
-end
 
-function secondRaid.onStepIn(creature, item, position, fromPosition)
-	if not creature:getPlayer() then
-		return true
+	for _, pos in pairs(raid.sandTimerPositions) do
+		raidMoveEvent:position(pos)
 	end
-	raid(SoulWarQuest.raids[secondRaidNumber].getZone(), secondRaidNumber, position, fromPosition)
-	return true
-end
 
-function thirdRaid.onStepIn(creature, item, position, fromPosition)
-	if not creature:getPlayer() then
-		return true
-	end
-	raid(SoulWarQuest.raids[thirdRaidNumber].getZone(), thirdRaidNumber, position, fromPosition)
-	return true
+	raidMoveEvent:register()
 end
-
-for _, pos in pairs(SoulWarQuest.raids[firstRaidNumber].sandTimerPositions) do
-	firstRaid:position(pos)
-end
-
-for _, pos in pairs(SoulWarQuest.raids[secondRaidNumber].sandTimerPositions) do
-	secondRaid:position(pos)
-end
-
-for _, position in pairs(SoulWarQuest.raids[thirdRaidNumber].sandTimerPositions) do
-	thirdRaid:position(position)
-end
-
-firstRaid:register()
-secondRaid:register()
-thirdRaid:register()
diff --git a/data-otservbr-global/scripts/quests/soul_war/moveevent-soul_war_entrances.lua b/data-otservbr-global/scripts/quests/soul_war/moveevent-soul_war_entrances.lua
index a6792315882..0d2bd4fffec 100644
--- a/data-otservbr-global/scripts/quests/soul_war/moveevent-soul_war_entrances.lua
+++ b/data-otservbr-global/scripts/quests/soul_war/moveevent-soul_war_entrances.lua
@@ -88,9 +88,6 @@ soul_war_megalomania_entrance:position({ x = 33611, y = 31430, z = 10 })
 soul_war_megalomania_entrance:register()
 
 local claustrophobicInfernoTeleportPositions = {
-	[Position(34013, 31049, 9)] = Position(34014, 31058, 9),
-	[Position(34010, 31073, 10)] = Position(34012, 31063, 10),
-	[Position(34009, 31038, 11)] = Position(34012, 31047, 11),
 	[Position(34022, 31091, 11)] = Position(33685, 31599, 14),
 }
 
diff --git a/src/game/game.cpp b/src/game/game.cpp
index 11c3e2bf966..2dbcafe69b1 100644
--- a/src/game/game.cpp
+++ b/src/game/game.cpp
@@ -1128,6 +1128,7 @@ bool Game::removeCreature(std::shared_ptr<Creature> creature, bool isLogout /* =
 		size_t i = 0;
 		for (const auto &spectator : playersSpectators) {
 			if (const auto &player = spectator->getPlayer()) {
+				player->sendMagicEffect(tilePosition, CONST_ME_POFF);
 				player->sendRemoveTileThing(tilePosition, oldStackPosVector[i++]);
 			}
 		}

From f84006e869cb18768ac8168043d5cc8bf50529f6 Mon Sep 17 00:00:00 2001
From: GitHub Actions <github-actions[bot]@users.noreply.github.com>
Date: Sun, 26 May 2024 20:11:27 +0000
Subject: [PATCH 23/60] Lua code format - (Stylua)

---
 .../moveevent-claustrophobic-inferno-raid.lua  | 18 ++++++++++--------
 1 file changed, 10 insertions(+), 8 deletions(-)

diff --git a/data-otservbr-global/scripts/quests/soul_war/moveevent-claustrophobic-inferno-raid.lua b/data-otservbr-global/scripts/quests/soul_war/moveevent-claustrophobic-inferno-raid.lua
index 4f0cac5a3f0..0502d53e365 100644
--- a/data-otservbr-global/scripts/quests/soul_war/moveevent-claustrophobic-inferno-raid.lua
+++ b/data-otservbr-global/scripts/quests/soul_war/moveevent-claustrophobic-inferno-raid.lua
@@ -10,19 +10,21 @@ for raidNumber, raid in ipairs(SoulWarQuest.claustrophobicInfernoRaids) do
 	local raidName = string.format("Claustrophobic Inferno Raid %d", raidNumber)
 	local encounter = Encounter(raidName, {
 		zone = raid.getZone(),
-		timeToSpawnMonsters = "3s"
+		timeToSpawnMonsters = "3s",
 	})
 
-	local spawnTimes = (SoulWarQuest.claustrophobicInfernoRaids.suriviveTime) / SoulWarQuest.claustrophobicInfernoRaids.spawnTime
+	local spawnTimes = SoulWarQuest.claustrophobicInfernoRaids.suriviveTime / SoulWarQuest.claustrophobicInfernoRaids.spawnTime
 
 	-- Registering encounter stages
 	for i = 1, spawnTimes do
-		encounter:addSpawnMonsters({
-			{
-				name = spawnMonsterName,
-				positions = raid.spawns
-			},
-		}):autoAdvance(SoulWarQuest.claustrophobicInfernoRaids.spawnTime * 1000)
+		encounter
+			:addSpawnMonsters({
+				{
+					name = spawnMonsterName,
+					positions = raid.spawns,
+				},
+			})
+			:autoAdvance(SoulWarQuest.claustrophobicInfernoRaids.spawnTime * 1000)
 	end
 
 	function encounter:onReset(position)

From b4152a537d273230251aa50b60e8f9e15cff5618 Mon Sep 17 00:00:00 2001
From: Pedro Henrique Alves Cruz <phac@cin.ufpe.br>
Date: Sun, 26 May 2024 22:21:50 -0300
Subject: [PATCH 24/60] fix: removed duplicated spawns and some improvements

---
 data-otservbr-global/lib/quests/soul_war.lua | 45 ++++++++------------
 1 file changed, 18 insertions(+), 27 deletions(-)

diff --git a/data-otservbr-global/lib/quests/soul_war.lua b/data-otservbr-global/lib/quests/soul_war.lua
index b70f42aa85e..899038c3fe3 100644
--- a/data-otservbr-global/lib/quests/soul_war.lua
+++ b/data-otservbr-global/lib/quests/soul_war.lua
@@ -119,7 +119,10 @@ SoulWarQuest = {
 
 	claustrophobicInfernoRaids = {
 		[1] = {
-			timerStarted = false,
+			zoneArea = {
+				{ x = 33985, y = 31053, z = 9 },
+				{ x = 34045, y = 31077, z = 9 },
+			},
 			sandTimerPositions = {
 				{ x = 34012, y = 31049, z = 9 },
 				{ x = 34013, y = 31049, z = 9 },
@@ -145,12 +148,12 @@ SoulWarQuest = {
 			getZone = function()
 				return SoulWarQuest.claustrophobicInfernoRaids[1].zone
 			end,
-			toggleTimer = function()
-				SoulWarQuest.claustrophobicInfernoRaids[1].timerStarted = not SoulWarQuest.claustrophobicInfernoRaids[1].timerStarted
-			end,
 		},
 		[2] = {
-			timerStarted = false,
+			zoneArea = {
+				{ x = 33988, y = 31042, z = 10 },
+				{ x = 34043, y = 31068, z = 10 },
+			},
 			sandTimerPositions = {
 				{ x = 34012, y = 31075, z = 10 },
 				{ x = 34011, y = 31075, z = 10 },
@@ -160,7 +163,6 @@ SoulWarQuest = {
 			spawns = {
 				Position(33999, 31046, 10),
 				Position(34011, 31047, 10),
-				Position(34005, 31052, 10),
 				Position(34015, 31052, 10),
 				Position(34021, 31044, 10),
 				Position(34029, 31054, 10),
@@ -175,12 +177,12 @@ SoulWarQuest = {
 			getZone = function()
 				return SoulWarQuest.claustrophobicInfernoRaids[2].zone
 			end,
-			toggleTimer = function()
-				SoulWarQuest.claustrophobicInfernoRaids[2].timerStarted = not SoulWarQuest.claustrophobicInfernoRaids[2].timerStarted
-			end,
 		},
 		[3] = {
-			timerStarted = false,
+			zoneArea = {
+				{ x = 33987, y = 31043, z = 11 },
+				{ x = 34044, y = 31076, z = 11 },
+			},
 			sandTimerPositions = {
 				{ x = 34009, y = 31036, z = 11 },
 				{ x = 34010, y = 31036, z = 11 },
@@ -194,16 +196,12 @@ SoulWarQuest = {
 				Position(34005, 31049, 11),
 				Position(33999, 31051, 11),
 				Position(33995, 31055, 11),
-				Position(33995, 31055, 11),
-				Position(34001, 31069, 11),
 				Position(33999, 31068, 11),
 				Position(34016, 31068, 11),
-				Position(34029, 31071, 11),
 				Position(34030, 31070, 11),
 				Position(34038, 31066, 11),
 				Position(34038, 31051, 11),
 				Position(34033, 31051, 11),
-				Position(34025, 31048, 11),
 				Position(34025, 31049, 11),
 				Position(34013, 31058, 11),
 				Position(34021, 31059, 11),
@@ -215,9 +213,6 @@ SoulWarQuest = {
 			getZone = function()
 				return SoulWarQuest.claustrophobicInfernoRaids[3].zone
 			end,
-			toggleTimer = function()
-				SoulWarQuest.claustrophobicInfernoRaids[3].timerStarted = not SoulWarQuest.claustrophobicInfernoRaids[3].timerStarted
-			end,
 		},
 		spawnTime = 10, -- seconds
 		suriviveTime = 2 * 60, -- 2 minutes
@@ -823,17 +818,13 @@ end
 -- Initialize ebb and flow zone area
 SoulWarQuest.ebbAndFlow.zone:addArea({ x = 33869, y = 30991, z = 8 }, { x = 33964, y = 31147, z = 9 })
 
--- Initialize claustrophobic inferno raid zones
-
-SoulWarQuest.claustrophobicInfernoRaids[1].zone:addArea({ x = 33985, y = 31053, z = 9 }, { x = 34045, y = 31077, z = 9 })
-SoulWarQuest.claustrophobicInfernoRaids[2].zone:addArea({ x = 33988, y = 31042, z = 10 }, { x = 34043, y = 31068, z = 10 })
-SoulWarQuest.claustrophobicInfernoRaids[3].zone:addArea({ x = 33987, y = 31043, z = 11 }, { x = 34044, y = 31076, z = 11 })
+-- Initialize claustrophobic inferno raid zones and add remove destination
 
--- Add remove destination
-
-SoulWarQuest.claustrophobicInfernoRaids[1].zone:setRemoveDestination(SoulWarQuest.claustrophobicInfernoRaids[1].exitPosition)
-SoulWarQuest.claustrophobicInfernoRaids[2].zone:setRemoveDestination(SoulWarQuest.claustrophobicInfernoRaids[2].exitPosition)
-SoulWarQuest.claustrophobicInfernoRaids[3].zone:setRemoveDestination(SoulWarQuest.claustrophobicInfernoRaids[3].exitPosition)
+for _, raid in ipairs(SoulWarQuest.claustrophobicInfernoRaids) do
+	local zone = raid.getZone()
+	zone:addArea(raid.zoneArea[1], raid.zoneArea[2])
+	zone:setRemoveDestination(raid.exitPosition)
+end
 
 -- Initialize bosses access for taint check
 SoulWarQuest.areaZones.claustrophobicInferno:addArea({ x = 33982, y = 30981, z = 9 }, { x = 34051, y = 31110, z = 11 })

From d37fdff1482d2e510c07dc9a25771c99ff4de3e1 Mon Sep 17 00:00:00 2001
From: Eduardo Dantas <eduardo.dantas@hotmail.com.br>
Date: Fri, 14 Jun 2024 22:36:39 -0300
Subject: [PATCH 25/60] fix: eventcallback and flickering soul

---
 data-otservbr-global/npc/flickering_soul.lua | 8 ++++++--
 data/scripts/talkactions/gm/afk.lua          | 2 +-
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/data-otservbr-global/npc/flickering_soul.lua b/data-otservbr-global/npc/flickering_soul.lua
index a00df70e338..2010198da6e 100644
--- a/data-otservbr-global/npc/flickering_soul.lua
+++ b/data-otservbr-global/npc/flickering_soul.lua
@@ -182,9 +182,13 @@ local function playerSayCallback(npc, player, type, message)
 		end
 		npcHandler:say(message, npc, player)
 	elseif MsgContains(message, "taints") or MsgContains(message, "penalties") then
-		if player:getTaintLevel() == nil then
-			player:resetTaints()
+		if player:getTaintLevel() ~= nil then
+			player:resetTaints(true)
+			npcHandler:say("I have cleansed you from the taints that you carried with you. You are now free from the burden that you should not have to bear.", npc, player)
+			return
 		end
+
+		npcHandler:say("You are not tainted by the darkness of the world. You are pure and free from the burdens that others carry.", npc, player)
 	end
 	return true
 end
diff --git a/data/scripts/talkactions/gm/afk.lua b/data/scripts/talkactions/gm/afk.lua
index 6167a2b6068..f5342362113 100644
--- a/data/scripts/talkactions/gm/afk.lua
+++ b/data/scripts/talkactions/gm/afk.lua
@@ -69,7 +69,7 @@ afkEffect:interval(5000)
 afkEffect:register()
 
 ------------------ Stop AFK Message when moves ------------------
-local callback = EventCallback()
+local callback = EventCallback("PlayerOnWalk")
 function callback.playerOnWalk(player, creature, creaturePos, toPos)
 	local isAfk = checkIsAFK(player:getId())
 	if isAfk.afk then

From 9fc0f114987de36712acee93550ce96c8730c312 Mon Sep 17 00:00:00 2001
From: Eduardo Dantas <eduardo.dantas@hotmail.com.br>
Date: Sat, 15 Jun 2024 00:01:56 -0300
Subject: [PATCH 26/60] fix: megalomania drop for bag you desire

---
 data-otservbr-global/lib/quests/soul_war.lua  | 41 ++++++++++++-------
 .../soul_war/goshnar's_megalomania_blue.lua   |  1 -
 .../soul_war/goshnar's_megalomania_green.lua  |  1 -
 .../quests/soul_war/goshnars_cruelty.lua      |  1 -
 .../quests/soul_war/goshnars_greed.lua        |  1 -
 .../quests/soul_war/goshnars_hatred.lua       |  1 -
 .../quests/soul_war/goshnars_malice.lua       |  1 -
 .../quests/soul_war/goshnars_spite.lua        |  1 -
 8 files changed, 26 insertions(+), 22 deletions(-)

diff --git a/data-otservbr-global/lib/quests/soul_war.lua b/data-otservbr-global/lib/quests/soul_war.lua
index 899038c3fe3..319d731faf7 100644
--- a/data-otservbr-global/lib/quests/soul_war.lua
+++ b/data-otservbr-global/lib/quests/soul_war.lua
@@ -51,13 +51,12 @@ SoulWarQuest = {
 		"Sorcerer's Apparition",
 		"Turbulent Elemental",
 		"Vibrant Phantom.",
-	},
-	bagYouDesireBosses = {
 		"Goshnar's Cruelty",
 		"Goshnar's Spite",
 		"Goshnar's Malice",
 		"Goshnar's Hatred",
 		"Goshnar's Greed",
+		"Goshnar's Megalomania",
 	},
 
 	-- Goshnar's Cruelty pulsating energy monsters
@@ -1068,33 +1067,45 @@ end
 
 function Monster:generateBagYouDesireLoot(player)
 	local playerTaintLevel = player:getTaintLevel()
-	if not playerTaintLevel then
+	if not playerTaintLevel or playerTaintLevel == 0 then
 		return {}
 	end
 
 	local monsterName = self:getName()
-	local isMonsterValid = false
-	for _, monster in ipairs(SoulWarQuest.bagYouDesireMonsters) do
-		if monsterName == monster then
-			isMonsterValid = true
-			break
-		end
-	end
-
+	local isMonsterValid = table.contains(SoulWarQuest.bagYouDesireMonsters, monsterName)
 	if not isMonsterValid then
 		return {}
 	end
 
-	-- Calculates the chances based on the number of taints
-	local totalChance = SoulWarQuest.baseBagYouDesireChance + (playerTaintLevel * SoulWarQuest.bagYouDesireChancePerTaint)
-	logger.trace("Player {} killed {} and has {} taints, loot chance {}", player:getName(), monsterName, playerTaintLevel, totalChance)
-	-- Generate loot
 	local loot = {}
+	local totalChance = SoulWarQuest.baseBagYouDesireChance
+	local soulWarQuest = player:soulWarQuestKV()
+	local megalomaniaKills = soulWarQuest:scoped("megalomania-kills"):get("count") or 0
+
+	if monsterName == "Goshnar's Megalomania" then
+		-- Special handling for Goshnar's Megalomania
+		totalChance = totalChance + megalomaniaKills * SoulWarQuest.bagYouDesireChancePerTaint
+	else
+		-- General handling for other monsters (bosses and non-bosses)
+		totalChance = totalChance + (playerTaintLevel * SoulWarQuest.bagYouDesireChancePerTaint)
+	end
+
+	logger.trace("Player {} killed {} with {} taints, loot chance {}", player:getName(), monsterName, playerTaintLevel, totalChance)
+
 	if math.random(1, 100) <= totalChance then
 		local itemType = ItemType(SoulWarQuest.bagYouDesireItemId)
 		if itemType then
 			loot[itemType:getId()] = { count = 1 }
 			logger.debug("Player {} killed {} and got a bag you desire with drop chance {}", player:getName(), monsterName, totalChance)
+			if monsterName == "Goshnar's Megalomania" then
+				-- Reset kill count on successful drop
+				soulWarQuest:scoped("megalomania-kills"):set("count", 0)
+			end
+		end
+	else
+		if monsterName == "Goshnar's Megalomania" then
+			-- Increment kill count for unsuccessful attempts
+			soulWarQuest:scoped("megalomania-kills"):set("count", megalomaniaKills + 1)
 		end
 	end
 
diff --git a/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_blue.lua b/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_blue.lua
index 69bd51a6923..232018a285e 100644
--- a/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_blue.lua
+++ b/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_blue.lua
@@ -94,7 +94,6 @@ monster.loot = {
 	{ name = "figurine of megalomania", chance = 400 },
 	{ name = "megalomania's skull", chance = 400 },
 	{ name = "megalomania's essence", chance = 400 },
-	{ name = "bag you desire", chance = 100 },
 }
 
 monster.attacks = {
diff --git a/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_green.lua b/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_green.lua
index 8a8d3d0d43f..08fed30648c 100644
--- a/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_green.lua
+++ b/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_green.lua
@@ -99,7 +99,6 @@ monster.loot = {
 	{ name = "figurine of megalomania", chance = 400 },
 	{ name = "megalomania's skull", chance = 400 },
 	{ name = "megalomania's essence", chance = 400 },
-	{ name = "bag you desire", chance = 100 },
 }
 
 monster.attacks = {
diff --git a/data-otservbr-global/monster/quests/soul_war/goshnars_cruelty.lua b/data-otservbr-global/monster/quests/soul_war/goshnars_cruelty.lua
index 90a0235225b..2142f4527ec 100644
--- a/data-otservbr-global/monster/quests/soul_war/goshnars_cruelty.lua
+++ b/data-otservbr-global/monster/quests/soul_war/goshnars_cruelty.lua
@@ -95,7 +95,6 @@ monster.loot = {
 	{ name = "figurine of cruelty", chance = 400 },
 	{ name = "spectral saddle", chance = 400 },
 	{ name = "spectral horse tack", chance = 400 },
-	{ name = "bag you desire", chance = 100 },
 }
 
 monster.attacks = {
diff --git a/data-otservbr-global/monster/quests/soul_war/goshnars_greed.lua b/data-otservbr-global/monster/quests/soul_war/goshnars_greed.lua
index bd0e064a6b4..2c68f56770d 100644
--- a/data-otservbr-global/monster/quests/soul_war/goshnars_greed.lua
+++ b/data-otservbr-global/monster/quests/soul_war/goshnars_greed.lua
@@ -100,7 +100,6 @@ monster.loot = {
 	{ name = "greed's arm", chance = 25000, maxCount = 1 },
 	{ name = "figurine of greed", chance = 400 },
 	{ name = "the skull of a beast", chance = 400 },
-	{ name = "bag you desire", chance = 100 },
 }
 
 monster.attacks = {
diff --git a/data-otservbr-global/monster/quests/soul_war/goshnars_hatred.lua b/data-otservbr-global/monster/quests/soul_war/goshnars_hatred.lua
index 09970df24fe..023dadbd2d4 100644
--- a/data-otservbr-global/monster/quests/soul_war/goshnars_hatred.lua
+++ b/data-otservbr-global/monster/quests/soul_war/goshnars_hatred.lua
@@ -96,7 +96,6 @@ monster.loot = {
 	{ name = "spectral horseshoe", chance = 400 },
 	{ name = "spectral horse tack", chance = 400 },
 	{ name = "bracelet of strengthening", chance = 400 },
-	{ name = "bag you desire", chance = 100 },
 }
 
 monster.attacks = {
diff --git a/data-otservbr-global/monster/quests/soul_war/goshnars_malice.lua b/data-otservbr-global/monster/quests/soul_war/goshnars_malice.lua
index e0b054dc10d..6931add8bd5 100644
--- a/data-otservbr-global/monster/quests/soul_war/goshnars_malice.lua
+++ b/data-otservbr-global/monster/quests/soul_war/goshnars_malice.lua
@@ -97,7 +97,6 @@ monster.loot = {
 	{ name = "spectral horseshoe", chance = 400 },
 	{ name = "the skull of a beast", chance = 400 },
 	{ name = "figurine of malice", chance = 400 },
-	{ name = "bag you desire", chance = 100 },
 }
 
 monster.attacks = {
diff --git a/data-otservbr-global/monster/quests/soul_war/goshnars_spite.lua b/data-otservbr-global/monster/quests/soul_war/goshnars_spite.lua
index 40817c335b0..9e04448fa19 100644
--- a/data-otservbr-global/monster/quests/soul_war/goshnars_spite.lua
+++ b/data-otservbr-global/monster/quests/soul_war/goshnars_spite.lua
@@ -93,7 +93,6 @@ monster.loot = {
 	{ name = "the skull of a beast", chance = 400 },
 	{ name = "figurine of spite", chance = 400 },
 	{ name = "spite's spirit", chance = 400 },
-	{ name = "bag you desire", chance = 100 },
 }
 
 monster.attacks = {

From 43afc714758260cf940e6169eb7d1e3b8058ab29 Mon Sep 17 00:00:00 2001
From: GitHub Actions <github-actions[bot]@users.noreply.github.com>
Date: Wed, 26 Jun 2024 17:42:46 +0000
Subject: [PATCH 27/60] Code format - (Clang-format)

---
 src/creatures/monsters/monster.cpp   |  8 ++++----
 src/lua/callbacks/event_callback.cpp | 12 ++++++------
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/src/creatures/monsters/monster.cpp b/src/creatures/monsters/monster.cpp
index 8e43f752bf9..0ffe2309caf 100644
--- a/src/creatures/monsters/monster.cpp
+++ b/src/creatures/monsters/monster.cpp
@@ -363,8 +363,8 @@ void Monster::onAttackedByPlayer(std::shared_ptr<Player> attackerPlayer) {
 		LuaScriptInterface* scriptInterface = mType->info.scriptInterface;
 		if (!scriptInterface->reserveScriptEnv()) {
 			g_logger().error("Monster {} creature {}] Call stack overflow. Too many lua "
-							 "script calls being nested.",
-							 getName(), this->getName());
+			                 "script calls being nested.",
+			                 getName(), this->getName());
 			return;
 		}
 
@@ -390,8 +390,8 @@ void Monster::onSpawn() {
 		LuaScriptInterface* scriptInterface = mType->info.scriptInterface;
 		if (!scriptInterface->reserveScriptEnv()) {
 			g_logger().error("Monster {} creature {}] Call stack overflow. Too many lua "
-							 "script calls being nested.",
-							 getName(), this->getName());
+			                 "script calls being nested.",
+			                 getName(), this->getName());
 			return;
 		}
 
diff --git a/src/lua/callbacks/event_callback.cpp b/src/lua/callbacks/event_callback.cpp
index 10796abd8e0..8280bad6d2b 100644
--- a/src/lua/callbacks/event_callback.cpp
+++ b/src/lua/callbacks/event_callback.cpp
@@ -236,9 +236,9 @@ void EventCallback::creatureOnDrainHealth(std::shared_ptr<Creature> creature, st
 void EventCallback::creatureOnCombat(std::shared_ptr<Creature> attacker, std::shared_ptr<Creature> target, CombatDamage &damage) const {
 	if (!getScriptInterface()->reserveScriptEnv()) {
 		g_logger().error("[{} - "
-						 "Creature {} target {}] "
-						 "Call stack overflow. Too many lua script calls being nested.",
-						 __FUNCTION__, attacker->getName(), target->getName());
+		                 "Creature {} target {}] "
+		                 "Call stack overflow. Too many lua script calls being nested.",
+		                 __FUNCTION__, attacker->getName(), target->getName());
 		return;
 	}
 
@@ -270,7 +270,7 @@ void EventCallback::creatureOnCombat(std::shared_ptr<Creature> attacker, std::sh
 			damage.secondary.value = -damage.secondary.value;
 		}
 		/*
-			Only EK with dealing physical damage will get elemental damage on skill
+		    Only EK with dealing physical damage will get elemental damage on skill
 		*/
 		if (damage.origin == ORIGIN_SPELL && attacker) {
 			const auto &player = attacker->getPlayer();
@@ -1319,8 +1319,8 @@ void EventCallback::zoneAfterCreatureLeave(std::shared_ptr<Zone> zone, std::shar
 void EventCallback::mapOnLoad(const std::string &mapFullPath) const {
 	if (!getScriptInterface()->reserveScriptEnv()) {
 		g_logger().error("[{} - "
-						 "Call stack overflow. Too many lua script calls being nested.",
-						 __FUNCTION__);
+		                 "Call stack overflow. Too many lua script calls being nested.",
+		                 __FUNCTION__);
 		return;
 	}
 

From 4e2e53709b7f2bc9febe4c743b90961359f4c2c7 Mon Sep 17 00:00:00 2001
From: Elson Costa <elsongabriel@hotmail.com>
Date: Tue, 2 Jul 2024 15:43:21 -0300
Subject: [PATCH 28/60] fix build error.

---
 src/lua/callbacks/events_callbacks.hpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/lua/callbacks/events_callbacks.hpp b/src/lua/callbacks/events_callbacks.hpp
index c479398fdcc..4d3758405a6 100644
--- a/src/lua/callbacks/events_callbacks.hpp
+++ b/src/lua/callbacks/events_callbacks.hpp
@@ -110,7 +110,7 @@ class EventsCallbacks {
 	template <typename CallbackFunc, typename... Args>
 	ReturnValue checkCallbackWithReturnValue(EventCallback_t eventType, CallbackFunc callbackFunc, Args &&... args) {
 		ReturnValue res = RETURNVALUE_NOERROR;
-		for (const auto &callback : getCallbacksByType(eventType)) {
+		for (const auto &[name, callback] : getCallbacksByType(eventType)) {
 			auto argsCopy = std::make_tuple(args...);
 			if (callback && callback->isLoadedCallback()) {
 				ReturnValue callbackResult = std::apply(

From d364e3279116fb1c8955427bd5f24a55ae3cb018 Mon Sep 17 00:00:00 2001
From: GitHub Actions <github-actions[bot]@users.noreply.github.com>
Date: Thu, 18 Jul 2024 12:05:24 +0000
Subject: [PATCH 29/60] Code format - (Clang-format)

---
 .../functions/creatures/player/player_functions.cpp  |  2 +-
 .../functions/creatures/player/player_functions.hpp  | 12 ++++++------
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/src/lua/functions/creatures/player/player_functions.cpp b/src/lua/functions/creatures/player/player_functions.cpp
index 9a830134737..702676ddd76 100644
--- a/src/lua/functions/creatures/player/player_functions.cpp
+++ b/src/lua/functions/creatures/player/player_functions.cpp
@@ -4418,4 +4418,4 @@ int PlayerFunctions::luaPlayerSendCreatureAppear(lua_State* L) {
 	player->sendCreatureAppear(player, player->getPosition(), isLogin);
 	pushBoolean(L, true);
 	return 1;
-}
\ No newline at end of file
+}
diff --git a/src/lua/functions/creatures/player/player_functions.hpp b/src/lua/functions/creatures/player/player_functions.hpp
index f59f92fe1c4..550ecd76539 100644
--- a/src/lua/functions/creatures/player/player_functions.hpp
+++ b/src/lua/functions/creatures/player/player_functions.hpp
@@ -371,12 +371,12 @@ class PlayerFunctions final : LuaScriptInterface {
 		registerMethod(L, "Player", "addTitle", PlayerFunctions::luaPlayerAddTitle);
 		registerMethod(L, "Player", "getTitles", PlayerFunctions::luaPlayerGetTitles);
 		registerMethod(L, "Player", "setCurrentTitle", PlayerFunctions::luaPlayerSetCurrentTitle);
-    
-    registerMethod(L, "Player", "createTransactionSummary", PlayerFunctions::luaPlayerCreateTransactionSummary);
+
+		registerMethod(L, "Player", "createTransactionSummary", PlayerFunctions::luaPlayerCreateTransactionSummary);
 
 		registerMethod(L, "Player", "takeScreenshot", PlayerFunctions::luaPlayerTakeScreenshot);
-    
-    registerMethod(L, "Player", "sendCreatureAppear", PlayerFunctions::luaPlayerSendCreatureAppear);
+
+		registerMethod(L, "Player", "sendCreatureAppear", PlayerFunctions::luaPlayerSendCreatureAppear);
 
 		GroupFunctions::init(L);
 		GuildFunctions::init(L);
@@ -741,8 +741,8 @@ class PlayerFunctions final : LuaScriptInterface {
 	static int luaPlayerCreateTransactionSummary(lua_State* L);
 
 	static int luaPlayerTakeScreenshot(lua_State* L);
-  
-  static int luaPlayerSendCreatureAppear(lua_State* L);
+
+	static int luaPlayerSendCreatureAppear(lua_State* L);
 
 	friend class CreatureFunctions;
 };

From 95f1c17622b91ecbdd1d214ce9c390457a0f14b9 Mon Sep 17 00:00:00 2001
From: Eduardo Dantas <eduardo.dantas@hotmail.com.br>
Date: Thu, 1 Aug 2024 19:05:30 -0300
Subject: [PATCH 30/60] fix: crash related to lua callback

---
 src/creatures/combat/combat.cpp | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/creatures/combat/combat.cpp b/src/creatures/combat/combat.cpp
index 7a19a292728..a0c5fb81ec6 100644
--- a/src/creatures/combat/combat.cpp
+++ b/src/creatures/combat/combat.cpp
@@ -1222,7 +1222,9 @@ void Combat::CombatFunc(std::shared_ptr<Creature> caster, const Position &origin
 
 		if (CreatureVector* creatures = tile->getCreatures()) {
 			const std::shared_ptr<Creature> topCreature = tile->getTopCreature();
-			for (auto &creature : *creatures) {
+			// A copy of the tile's creature list is made because modifications to this vector, such as adding or removing creatures through a Lua callback, may occur during the iteration within the for loop.
+			CreatureVector creaturesCopy = *creatures;
+			for (auto &creature : creaturesCopy) {
 				if (params.targetCasterOrTopMost) {
 					if (caster && caster->getTile() == tile) {
 						if (creature != caster) {

From be1179e9561899d55f55bc3e0d02dc87981b9b6b Mon Sep 17 00:00:00 2001
From: Eduardo Dantas <eduardo.dantas@hotmail.com.br>
Date: Fri, 2 Aug 2024 18:36:29 -0300
Subject: [PATCH 31/60] fix: addCallback check

---
 src/lua/callbacks/events_callbacks.cpp | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/src/lua/callbacks/events_callbacks.cpp b/src/lua/callbacks/events_callbacks.cpp
index 1ab64957497..4b147d4dd6f 100644
--- a/src/lua/callbacks/events_callbacks.cpp
+++ b/src/lua/callbacks/events_callbacks.cpp
@@ -39,10 +39,13 @@ bool EventsCallbacks::isCallbackRegistered(const std::shared_ptr<EventCallback>
 }
 
 void EventsCallbacks::addCallback(const std::shared_ptr<EventCallback> &callback) {
-	if (m_callbacks.find(callback->getName()) != m_callbacks.end()) {
+	if (m_callbacks.find(callback->getName()) != m_callbacks.end() && !callback->skipDuplicationCheck()) {
+		g_logger().error("Event callback already registered: {}", callback->getName());
 		return;
 	}
 
+	g_logger().trace("Registering event callback: {}", callback->getName());
+
 	m_callbacks[callback->getName()] = callback;
 }
 

From 2e89beb6be82939e8098ff276c200080b98b506a Mon Sep 17 00:00:00 2001
From: Eduardo Dantas <eduardo.dantas@hotmail.com.br>
Date: Wed, 7 Aug 2024 19:52:04 -0300
Subject: [PATCH 32/60] fix: ZoneEvent callback

---
 data/libs/functions/boss_lever.lua     |  5 +--
 data/libs/systems/zones.lua            |  2 +-
 data/scripts/talkactions/god/test.lua  | 44 ++++++++++++++++++++++++++
 src/lua/callbacks/events_callbacks.hpp |  1 +
 4 files changed, 49 insertions(+), 3 deletions(-)

diff --git a/data/libs/functions/boss_lever.lua b/data/libs/functions/boss_lever.lua
index cbecfc26f8c..9cd577ee911 100644
--- a/data/libs/functions/boss_lever.lua
+++ b/data/libs/functions/boss_lever.lua
@@ -174,14 +174,15 @@ function BossLever:onUse(player)
 			return true
 		end
 
-		if creature:getLevel() < self.requiredLevel then
+		local isAccountNormal = creature:getAccountType() == ACCOUNT_TYPE_NORMAL
+		if isAccountNormal and creature:getLevel() < self.requiredLevel then
 			local message = "All players need to be level " .. self.requiredLevel .. " or higher."
 			creature:sendTextMessage(MESSAGE_EVENT_ADVANCE, message)
 			player:sendTextMessage(MESSAGE_EVENT_ADVANCE, message)
 			return false
 		end
 
-		if creature:getGroup():getId() < GROUP_TYPE_GOD and self:lastEncounterTime(creature) > os.time() then
+		if creature:getGroup():getId() < GROUP_TYPE_GOD and isAccountNormal and self:lastEncounterTime(creature) > os.time() then
 			local infoPositions = lever:getInfoPositions()
 			for _, posInfo in pairs(infoPositions) do
 				local currentPlayer = posInfo.creature
diff --git a/data/libs/systems/zones.lua b/data/libs/systems/zones.lua
index 1406242517a..698a464fe87 100644
--- a/data/libs/systems/zones.lua
+++ b/data/libs/systems/zones.lua
@@ -148,7 +148,7 @@ function ZoneEvent:register()
 	end
 
 	if self.onSpawn then
-		local afterEnter = EventCallback("ZoneEventAfterEnter", true)
+		local afterEnter = EventCallback("ZoneEventAfterEnterOnSpawn", true)
 		function afterEnter.zoneAfterCreatureEnter(zone, creature)
 			if zone ~= self.zone then
 				return true
diff --git a/data/scripts/talkactions/god/test.lua b/data/scripts/talkactions/god/test.lua
index 25b2fd49da2..f22f86ff921 100644
--- a/data/scripts/talkactions/god/test.lua
+++ b/data/scripts/talkactions/god/test.lua
@@ -36,3 +36,47 @@ end
 testLog:separator(" ")
 testLog:groupType("god")
 testLog:register()
+
+local testIcons = TalkAction("/testicons")
+
+local function convertIconsToBitValue(iconList)
+	local bitObj = NewBit(0)
+	for icon in string.gmatch(iconList, "%d+") do
+		icon = tonumber(icon)
+		if icon then
+			local flag = bit.lshift(1, icon - 1)
+			bitObj:updateFlag(flag) 
+		end
+	end
+	return bitObj:getNumber()
+end
+
+--[[Usage:
+/testicons 1
+/testicons 2
+/testicons 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
+]]
+function testIcons.onSay(player, words, param)
+	if param == "" then
+		player:sendCancelMessage("Icon required.")
+		logger.error("[testIcons.onSay] - Icon required")
+		return true
+	end
+
+	function Player:sendIconsTest()
+		local msg = NetworkMessage()
+		msg:addByte(0xA2)
+		local icons = convertIconsToBitValue(param)
+		msg:addU32(icons)
+		msg:addByte(0)
+		msg:sendToPlayer(self)
+	end
+
+	player:sendIconsTest()
+	return true
+end
+
+testIcons:separator(" ")
+testIcons:setDescription("[Usage]: /seticons {icon1}, {icon2}, {icon3}, ...")
+testIcons:groupType("god")
+testIcons:register()
diff --git a/src/lua/callbacks/events_callbacks.hpp b/src/lua/callbacks/events_callbacks.hpp
index 4d3758405a6..dff5cec30c5 100644
--- a/src/lua/callbacks/events_callbacks.hpp
+++ b/src/lua/callbacks/events_callbacks.hpp
@@ -97,6 +97,7 @@ class EventsCallbacks {
 					},
 					argsCopy
 				);
+				g_logger().trace("Executed callback: {}", name);
 			}
 		}
 	}

From fb9a4a15517f6d5510a8a3a13a46dc3ef23b6404 Mon Sep 17 00:00:00 2001
From: GitHub Actions <github-actions[bot]@users.noreply.github.com>
Date: Wed, 7 Aug 2024 22:52:47 +0000
Subject: [PATCH 33/60] Lua code format - (Stylua)

---
 data/scripts/talkactions/god/test.lua | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/data/scripts/talkactions/god/test.lua b/data/scripts/talkactions/god/test.lua
index f22f86ff921..cd5e7e1aec9 100644
--- a/data/scripts/talkactions/god/test.lua
+++ b/data/scripts/talkactions/god/test.lua
@@ -45,7 +45,7 @@ local function convertIconsToBitValue(iconList)
 		icon = tonumber(icon)
 		if icon then
 			local flag = bit.lshift(1, icon - 1)
-			bitObj:updateFlag(flag) 
+			bitObj:updateFlag(flag)
 		end
 	end
 	return bitObj:getNumber()

From 7b2444ddac97396286c39c4c01fce4293cc6b351 Mon Sep 17 00:00:00 2001
From: Eduardo Dantas <eduardo.dantas@hotmail.com.br>
Date: Wed, 7 Aug 2024 21:12:39 -0300
Subject: [PATCH 34/60] fix: maps bugs

---
 .../soul_war/ebb_and_flow/ebb-flow-empty.otbm | Bin 129560 -> 129452 bytes
 .../ebb_and_flow/ebb-flow-monster.xml         |   3 +--
 .../quest/soul_war/ebb_and_flow/ebb-flow.otbm | Bin 181546 -> 181627 bytes
 3 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-empty.otbm b/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-empty.otbm
index 6d37ae4fb880709f5c9facf23687f08eb776fb95..9d3fa897425709c4d254f1ac0b598f26e2cbe0bd 100644
GIT binary patch
delta 100
zcmbR7g?-Iu_6@A(H_M;Ti{HLnk8zXM^x{ZH_385?8AG@KjAVQuuJy|I|39{Fj{pDv
ou~tv`$MzYCJMkaeTVJrmBoJ#lZxQ1SPLR6kAnx`bMT`pV0Po;4jQ{`u

delta 211
zcmZ4UnSI6=_6@A(rT+h8VQ68f<ow5)SN)IedGr7OP!W#JtmpIMk>vX-QRTN6>oIQ9
zLQ+uDjH+O|Y9ymN%Rjbmj_KZ!jA3Bb_63oQ55-NoIe^x%R!#iJ_SzT3s-6H+24(@p
e-unKBb0@*M(^nTV-VlaMOovNs?<rzbXa@l3ZDoxB

diff --git a/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-monster.xml b/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-monster.xml
index a476474dd74..af4787bae03 100644
--- a/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-monster.xml
+++ b/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-monster.xml
@@ -522,8 +522,7 @@
 	</monster>
 	<monster centerx="33916" centery="31125" centerz="9" radius="5">
 		<monster name="Turbulent Elemental" x="-4" y="-3" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="0" y="-3" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="1" y="-2" z="9" spawntime="60" />
+		<monster name="Turbulent Elemental" x="3" y="-2" z="9" spawntime="60" />
 		<monster name="Capricious Phantom" x="5" y="0" z="9" spawntime="60" />
 		<monster name="Capricious Phantom" x="-1" y="1" z="9" spawntime="60" />
 		<monster name="Turbulent Elemental" x="3" y="3" z="9" spawntime="60" />
diff --git a/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow.otbm b/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow.otbm
index b8ba1414d09e6bdea0cf36d80dfe9f1b39ab8e17..5a8d5d16fefe7f43e2bd163cb1f86eac75068fc0 100644
GIT binary patch
delta 435
zcmZ40#r?aByI~9C<Y2CUY@dDqgNf~vgBf?eb~P9L$L7oO|NlSM%88toKu#cpGl^4I
z5F|L6(+oscP2|)EN``_Zt0r+8!nIXR=G2{DV$bC44pKgeGo1mV4NO-};LO$h$JX2k
zw9}CtWDC$BkVt1Em@^5PGa15}&f&nM$F2*~qSH9t!huPbsi|Rlx&xCo>pwQ_#{b(V
zIWUPcdw^`2%Bc-@<TRjrK>X=INB?8<gE(>urxC)DAeAtWR!!s7L2#y@ab~ishnNO&
z`!uK@rUPlP+d<Brg6z_%$ed}&oatarAJ})*5ItHD4n&V0gagt8G_@L}97xx2LX?KE
M|KHy0!Zf!50G3C^nE(I)

delta 332
zcmey}#l5PFyI~9C<lyadgBf?e*02!#$L7oO|NlSM%88t22+kx<T?A(`r`hz`_Ds%!
z|JXVk!D=UQrZd1flaV-86F74<|FJo;gOpWG1ad(1B(UH-u->Z4V2)1X|9@<{(^Vaq
z^q86&rbjt2=`v|IPVaPJ(%!z)fk~WM8Sb#DoZ1MtOye{}aHdPRFxh3p9WoWkA(hjR
zIn%+MK8ORRfE}O(;Y<Z{^dOvRKn}>g(;;*<L}durGu0rK(+|2ZNo>F8!Zf!50BG=*
Al>h($


From 60e6102b9e486b76e6a36424d954eb46f4f57f4a Mon Sep 17 00:00:00 2001
From: Eduardo Dantas <eduardo.dantas@hotmail.com.br>
Date: Thu, 8 Aug 2024 00:19:55 -0300
Subject: [PATCH 35/60] fix: some things

---
 data-otservbr-global/world/otservbr-house.xml |  3 +-
 .../world/otservbr-monster.xml                |  6 --
 data-otservbr-global/world/otservbr-npc.xml   | 60 +++++++++----------
 data-otservbr-global/world/otservbr-zones.xml |  2 +-
 src/creatures/combat/combat.cpp               |  4 +-
 src/lua/callbacks/events_callbacks.cpp        |  2 +-
 6 files changed, 37 insertions(+), 40 deletions(-)

diff --git a/data-otservbr-global/world/otservbr-house.xml b/data-otservbr-global/world/otservbr-house.xml
index f7e5cd52370..6acaadf5bd9 100644
--- a/data-otservbr-global/world/otservbr-house.xml
+++ b/data-otservbr-global/world/otservbr-house.xml
@@ -284,7 +284,7 @@
 	<house name="Mill Avenue 4" houseid="2953" entryx="32413" entryy="32189" entryz="6" rent="100000" townid="8" size="33" clientid="0" beds="2" />
 	<house name="Mill Avenue 5" houseid="2954" entryx="32422" entryy="32178" entryz="7" rent="300000" townid="8" size="69" clientid="0" beds="4" />
 	<house name="Open-Air Theatre" houseid="2955" entryx="32262" entryy="32238" entryz="7" rent="150000" townid="8" size="81" clientid="0" beds="1" />
-	<house name="Smuggler's Den" houseid="2956" entryx="32419" entryy="32262" entryz="9" rent="400000" townid="8" size="227" clientid="0" beds="7" />
+	<house name="Smuggler's Den" houseid="2956" entryx="32419" entryy="32262" entryz="9" rent="400000" townid="8" size="226" clientid="0" beds="7" />
 	<house name="Sorcerer's Avenue 1a" houseid="2957" entryx="32300" entryy="32254" entryz="7" rent="100000" townid="8" size="24" clientid="0" beds="2" />
 	<house name="Sorcerer's Avenue 5 (Shop)" houseid="2958" entryx="32284" entryy="32256" entryz="7" rent="150000" townid="8" size="54" clientid="0" beds="1" />
 	<house name="Sorcerer's Avenue 1b" houseid="2959" entryx="32300" entryy="32251" entryz="6" rent="80000" townid="8" size="19" clientid="0" beds="2" />
@@ -984,4 +984,5 @@
 	<house name="Pilchard Bin 9" houseid="3684" entryx="32281" entryy="31152" entryz="6" rent="50000" townid="16" size="11" clientid="0" beds="1" />
 	<house name="Pilchard Bin 10" houseid="3685" entryx="32281" entryy="31148" entryz="6" rent="0" townid="16" size="11" clientid="0" beds="1" />
 	<house name="Mammoth House" houseid="3686" entryx="32234" entryy="31227" entryz="7" rent="300000" townid="16" size="280" clientid="0" beds="6" />
+	<house name="" houseid="3687" entryx="0" entryy="0" entryz="0" rent="0" townid="0" size="398" clientid="0" beds="0" />
 </houses>
diff --git a/data-otservbr-global/world/otservbr-monster.xml b/data-otservbr-global/world/otservbr-monster.xml
index 8441ed918a1..bde660e0c60 100644
--- a/data-otservbr-global/world/otservbr-monster.xml
+++ b/data-otservbr-global/world/otservbr-monster.xml
@@ -96181,7 +96181,6 @@
 	</monster>
 	<monster centerx="32833" centery="32798" centerz="9" radius="3">
 		<monster name="True Midnight Asura" x="3" y="-2" z="9" spawntime="60" />
-		<monster name="Midnight Asura" x="2" y="0" z="9" spawntime="60" />
 	</monster>
 	<monster centerx="32840" centery="32798" centerz="9" radius="3">
 		<monster name="Midnight Asura" x="-2" y="-3" z="9" spawntime="60" />
@@ -118064,11 +118063,6 @@
 		<monster name="True Midnight Asura" x="-1" y="2" z="10" spawntime="60" />
 		<monster name="Hellspawn" x="2" y="2" z="10" spawntime="60" />
 	</monster>
-	<monster centerx="32840" centery="32763" centerz="10" radius="3">
-		<monster name="True Midnight Asura" x="3" y="-3" z="10" spawntime="60" />
-		<monster name="True Frost Flower Asura" x="-3" y="1" z="10" spawntime="60" />
-		<monster name="Hellspawn" x="3" y="3" z="10" spawntime="60" />
-	</monster>
 	<monster centerx="32847" centery="32763" centerz="10" radius="3">
 		<monster name="True Midnight Asura" x="3" y="-3" z="10" spawntime="60" />
 	</monster>
diff --git a/data-otservbr-global/world/otservbr-npc.xml b/data-otservbr-global/world/otservbr-npc.xml
index 271d28c46ab..8bc05fa7f15 100644
--- a/data-otservbr-global/world/otservbr-npc.xml
+++ b/data-otservbr-global/world/otservbr-npc.xml
@@ -840,6 +840,9 @@
 	<npc centerx="32826" centery="32574" centerz="6" radius="1">
 		<npc name="Hairycles" x="0" y="0" z="6" spawntime="60" />
 	</npc>
+	<npc centerx="33710" centery="32602" centerz="6" radius="1">
+		<npc name="Hawkhurst Ingol" x="0" y="0" z="6" spawntime="60" />
+	</npc>
 	<npc centerx="33047" centery="32622" centerz="6" radius="1">
 		<npc name="Ubaid" x="0" y="0" z="6" spawntime="60" />
 	</npc>
@@ -1551,6 +1554,9 @@
 	<npc centerx="33189" centery="31982" centerz="7" radius="1">
 		<npc name="Scrutinon" x="0" y="0" z="7" spawntime="60" />
 	</npc>
+	<npc centerx="33356" centery="31982" centerz="7" radius="1">
+		<npc name="Hawkhurst" x="0" y="0" z="7" spawntime="60" />
+	</npc>
 	<npc centerx="33479" centery="31986" centerz="7" radius="1">
 		<npc name="Captain Gulliver" x="0" y="0" z="7" spawntime="60" />
 	</npc>
@@ -1932,6 +1938,9 @@
 	<npc centerx="33238" centery="32482" centerz="7" radius="1">
 		<npc name="Miraia" x="0" y="0" z="7" spawntime="60" />
 	</npc>
+	<npc centerx="32398" centery="32509" centerz="7" radius="1">
+		<npc name="An Idol" x="0" y="0" z="7" spawntime="60" />
+	</npc>
 	<npc centerx="32329" centery="32528" centerz="7" radius="1">
 		<npc name="Marina" x="0" y="0" z="7" spawntime="60" />
 	</npc>
@@ -2106,6 +2115,9 @@
 	<npc centerx="32259" centery="32881" centerz="7" radius="1">
 		<npc name="Evan" x="0" y="0" z="7" spawntime="60" />
 	</npc>
+	<npc centerx="33181" centery="32883" centerz="7" radius="1">
+		<npc name="Tonar" x="0" y="0" z="7" spawntime="60" />
+	</npc>
 	<npc centerx="33066" centery="32886" centerz="7" radius="1">
 		<npc name="Feizuhl" x="0" y="0" z="7" spawntime="60" />
 	</npc>
@@ -2115,6 +2127,9 @@
 	<npc centerx="32131" centery="32914" centerz="7" radius="1">
 		<npc name="Captain Waverider (Island)" x="0" y="0" z="7" spawntime="60" />
 	</npc>
+	<npc centerx="33068" centery="32917" centerz="7" radius="1">
+		<npc name="Tonar Oskayaat" x="0" y="0" z="7" spawntime="60" />
+	</npc>
 	<npc centerx="32043" centery="32931" centerz="7" radius="1">
 		<npc name="Captain Waverider" x="0" y="0" z="7" spawntime="60" />
 	</npc>
@@ -2331,6 +2346,18 @@
 	<npc centerx="33419" centery="31125" centerz="9" radius="1">
 		<npc name="A Strange Chalice" x="0" y="0" z="9" spawntime="60" />
 	</npc>
+	<npc centerx="33361" centery="31316" centerz="9" radius="1">
+		<npc name="Oberon'S Bile" x="0" y="0" z="9" spawntime="60" />
+	</npc>
+	<npc centerx="33367" centery="31316" centerz="9" radius="1">
+		<npc name="Oberon'S Hate" x="0" y="0" z="9" spawntime="60" />
+	</npc>
+	<npc centerx="33361" centery="31320" centerz="9" radius="1">
+		<npc name="Oberon'S Spite" x="0" y="0" z="9" spawntime="60" />
+	</npc>
+	<npc centerx="33367" centery="31320" centerz="9" radius="1">
+		<npc name="Oberon'S Ire" x="0" y="0" z="9" spawntime="60" />
+	</npc>
 	<npc centerx="33444" centery="31321" centerz="9" radius="1">
 		<npc name="Rock With A Soft Spot" x="0" y="0" z="9" spawntime="60" />
 	</npc>
@@ -2379,18 +2406,6 @@
 	<npc centerx="33007" centery="31891" centerz="9" radius="1">
 		<npc name="Gnomission" x="0" y="0" z="9" spawntime="60" />
 	</npc>
-	<npc centerx="33361" centery="31316" centerz="9" radius="1">
-		<npc name="Oberon's Bile" x="0" y="0" z="9" spawntime="60" />
-	</npc>
-	<npc centerx="33367" centery="31316" centerz="9" radius="1">
-		<npc name="Oberon's Hate" x="0" y="0" z="9" spawntime="60" />
-	</npc>
-	<npc centerx="33361" centery="31320" centerz="9" radius="1">
-		<npc name="Oberon's Spite" x="0" y="0" z="9" spawntime="60" />
-	</npc>
-	<npc centerx="33367" centery="31320" centerz="9" radius="1">
-		<npc name="Oberon's Ire" x="0" y="0" z="9" spawntime="60" />
-	</npc>
 	<npc centerx="32664" centery="31894" centerz="9" radius="1">
 		<npc name="Uzgod" x="0" y="0" z="9" spawntime="60" />
 	</npc>
@@ -2848,6 +2863,9 @@
 	<npc centerx="32700" centery="31992" centerz="14" radius="1">
 		<npc name="Rapanaio (Boat)" x="0" y="0" z="14" spawntime="60" />
 	</npc>
+	<npc centerx="34070" centery="32009" centerz="14" radius="1">
+		<npc name="Altar" x="0" y="0" z="14" spawntime="60" />
+	</npc>
 	<npc centerx="32527" centery="32029" centerz="14" radius="1">
 		<npc name="Lunch" x="0" y="0" z="14" spawntime="60" />
 	</npc>
@@ -2983,22 +3001,4 @@
 	<npc centerx="33587" centery="32966" centerz="15" radius="1">
 		<npc name="Gnomish Operative (Raiders)" x="0" y="0" z="15" spawntime="60" />
 	</npc>
-	<npc centerx="33356" centery="31982" centerz="7" radius="1">
-		<npc name="Hawkhurst" x="0" y="0" z="15" spawntime="60" />
-	</npc>
-	<npc centerx="33710" centery="32602" centerz="6" radius="1">
-		<npc name="Hawkhurst Ingol" x="0" y="0" z="15" spawntime="60" />
-	</npc>
-	<npc centerx="34070" centery="32009" centerz="14" radius="1">
-		<npc name="Altar" x="0" y="0" z="15" spawntime="60" />
-	</npc>
-  <npc centerx="33181" centery="32883" centerz="7" radius="1">
-		<npc name="Tonar" x="0" y="0" z="7" spawntime="60" />
-	</npc>
-	<npc centerx="33068" centery="32917" centerz="7" radius="1">
-		<npc name="Tonar Oskayaat" x="0" y="0" z="7" spawntime="60" />
-	</npc>
-	<npc centerx="32398" centery="32509" centerz="7" radius="1">
-		<npc name="An Idol" x="0" y="0" z="15" spawntime="60" />
-	</npc>
 </npcs>
diff --git a/data-otservbr-global/world/otservbr-zones.xml b/data-otservbr-global/world/otservbr-zones.xml
index 4740d50385c..44cff897a42 100644
--- a/data-otservbr-global/world/otservbr-zones.xml
+++ b/data-otservbr-global/world/otservbr-zones.xml
@@ -1,4 +1,4 @@
 <?xml version="1.0"?>
 <zones>
-	<zone name="boss.brain-head" zoneid="1"/>
+	<zone name="boss.brain-head" zoneid="1" />
 </zones>
diff --git a/src/creatures/combat/combat.cpp b/src/creatures/combat/combat.cpp
index a0c5fb81ec6..d65d10e4e6f 100644
--- a/src/creatures/combat/combat.cpp
+++ b/src/creatures/combat/combat.cpp
@@ -1167,7 +1167,9 @@ void Combat::CombatFunc(std::shared_ptr<Creature> caster, const Position &origin
 
 		if (CreatureVector* creatures = tile->getCreatures()) {
 			const std::shared_ptr<Creature> topCreature = tile->getTopCreature();
-			for (auto &creature : *creatures) {
+			// A copy of the tile's creature list is made because modifications to this vector, such as adding or removing creatures through a Lua callback, may occur during the iteration within the for loop.
+			CreatureVector creaturesCopy = *creatures;
+			for (auto &creature : creaturesCopy) {
 				if (params.targetCasterOrTopMost) {
 					if (caster && caster->getTile() == tile) {
 						if (creature != caster) {
diff --git a/src/lua/callbacks/events_callbacks.cpp b/src/lua/callbacks/events_callbacks.cpp
index 4b147d4dd6f..13a42baa15a 100644
--- a/src/lua/callbacks/events_callbacks.cpp
+++ b/src/lua/callbacks/events_callbacks.cpp
@@ -40,7 +40,7 @@ bool EventsCallbacks::isCallbackRegistered(const std::shared_ptr<EventCallback>
 
 void EventsCallbacks::addCallback(const std::shared_ptr<EventCallback> &callback) {
 	if (m_callbacks.find(callback->getName()) != m_callbacks.end() && !callback->skipDuplicationCheck()) {
-		g_logger().error("Event callback already registered: {}", callback->getName());
+		g_logger().trace("Event callback already registered: {}", callback->getName());
 		return;
 	}
 

From 16c20870bdf25ba0c4cb36f385cff52123374559 Mon Sep 17 00:00:00 2001
From: Eduardo Dantas <eduardo.dantas@hotmail.com.br>
Date: Thu, 8 Aug 2024 00:29:53 -0300
Subject: [PATCH 36/60] fix: remove house

---
 data-otservbr-global/world/otservbr-house.xml | 1 -
 1 file changed, 1 deletion(-)

diff --git a/data-otservbr-global/world/otservbr-house.xml b/data-otservbr-global/world/otservbr-house.xml
index 6acaadf5bd9..7eff23b4606 100644
--- a/data-otservbr-global/world/otservbr-house.xml
+++ b/data-otservbr-global/world/otservbr-house.xml
@@ -984,5 +984,4 @@
 	<house name="Pilchard Bin 9" houseid="3684" entryx="32281" entryy="31152" entryz="6" rent="50000" townid="16" size="11" clientid="0" beds="1" />
 	<house name="Pilchard Bin 10" houseid="3685" entryx="32281" entryy="31148" entryz="6" rent="0" townid="16" size="11" clientid="0" beds="1" />
 	<house name="Mammoth House" houseid="3686" entryx="32234" entryy="31227" entryz="7" rent="300000" townid="16" size="280" clientid="0" beds="6" />
-	<house name="" houseid="3687" entryx="0" entryy="0" entryz="0" rent="0" townid="0" size="398" clientid="0" beds="0" />
 </houses>

From 5c5470a02144cb42304927d774885902625a8fa9 Mon Sep 17 00:00:00 2001
From: Eduardo Dantas <eduardo.dantas@hotmail.com.br>
Date: Thu, 8 Aug 2024 01:42:18 -0300
Subject: [PATCH 37/60] fix: change bag you desire chance

---
 data-otservbr-global/lib/quests/soul_war.lua | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/data-otservbr-global/lib/quests/soul_war.lua b/data-otservbr-global/lib/quests/soul_war.lua
index 319d731faf7..100788d9acb 100644
--- a/data-otservbr-global/lib/quests/soul_war.lua
+++ b/data-otservbr-global/lib/quests/soul_war.lua
@@ -30,7 +30,7 @@ SoulWarQuest = {
 
 	timeToReturnImmuneMegalomania = 70, -- In seconds
 
-	baseBagYouDesireChance = 1, -- 1% base chance
+	baseBagYouDesireChance = 500, -- 1000 = 1% chance, 500 = 0.5% chance
 	bagYouDesireChancePerTaint = 1, -- Increases 1% per taint
 	bagYouDesireMonsters = {
 		"Bony Sea Devil",
@@ -1092,7 +1092,7 @@ function Monster:generateBagYouDesireLoot(player)
 
 	logger.trace("Player {} killed {} with {} taints, loot chance {}", player:getName(), monsterName, playerTaintLevel, totalChance)
 
-	if math.random(1, 100) <= totalChance then
+	if math.random(1, 100000) <= totalChance then
 		local itemType = ItemType(SoulWarQuest.bagYouDesireItemId)
 		if itemType then
 			loot[itemType:getId()] = { count = 1 }

From 784f6719f3a5b31dc33aa840a110c63484d4540c Mon Sep 17 00:00:00 2001
From: Eduardo Dantas <eduardo.dantas@hotmail.com.br>
Date: Thu, 8 Aug 2024 09:18:53 -0300
Subject: [PATCH 38/60] feat: add new icon

---
 data/scripts/talkactions/god/test.lua | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/data/scripts/talkactions/god/test.lua b/data/scripts/talkactions/god/test.lua
index cd5e7e1aec9..ac6ca921483 100644
--- a/data/scripts/talkactions/god/test.lua
+++ b/data/scripts/talkactions/god/test.lua
@@ -68,7 +68,7 @@ function testIcons.onSay(player, words, param)
 		msg:addByte(0xA2)
 		local icons = convertIconsToBitValue(param)
 		msg:addU32(icons)
-		msg:addByte(0)
+		msg:addByte(tonumber(param))
 		msg:sendToPlayer(self)
 	end
 

From e337caeed3f1df7170d3599f43d098ffa15d9491 Mon Sep 17 00:00:00 2001
From: Eduardo Dantas <eduardo.dantas@hotmail.com.br>
Date: Fri, 9 Aug 2024 02:07:50 -0300
Subject: [PATCH 39/60] fix: goshnar's greed bugs

---
 data-otservbr-global/lib/quests/soul_war.lua  |  2 +-
 .../quests/soul_war/goshnars_greed.lua        |  5 +--
 .../monster/quests/soul_war/powerful_soul.lua |  2 +-
 .../monster/quests/soul_war/soul_sphere.lua   | 41 ++++++++++++-------
 src/game/game.cpp                             |  2 +-
 .../creatures/creature_functions.cpp          |  2 +-
 6 files changed, 32 insertions(+), 22 deletions(-)

diff --git a/data-otservbr-global/lib/quests/soul_war.lua b/data-otservbr-global/lib/quests/soul_war.lua
index 100788d9acb..5df73dc6115 100644
--- a/data-otservbr-global/lib/quests/soul_war.lua
+++ b/data-otservbr-global/lib/quests/soul_war.lua
@@ -37,7 +37,7 @@ SoulWarQuest = {
 		"Brachiodemon",
 		"Branchy Crawler",
 		"Capricious Phantom",
-		"Cloak Of Terror",
+		"Cloak of Terror",
 		"Courage Leech",
 		"Distorted Phantom",
 		"Druid's Apparition",
diff --git a/data-otservbr-global/monster/quests/soul_war/goshnars_greed.lua b/data-otservbr-global/monster/quests/soul_war/goshnars_greed.lua
index 2c68f56770d..4f197ad9541 100644
--- a/data-otservbr-global/monster/quests/soul_war/goshnars_greed.lua
+++ b/data-otservbr-global/monster/quests/soul_war/goshnars_greed.lua
@@ -68,10 +68,7 @@ monster.light = {
 }
 
 monster.summon = {
-	maxSummons = 1,
-	summons = {
-		{ name = "dreadful harvester", chance = 10, interval = 1000, count = 1 },
-	},
+	maxSummons = 1
 }
 
 monster.voices = {
diff --git a/data-otservbr-global/monster/quests/soul_war/powerful_soul.lua b/data-otservbr-global/monster/quests/soul_war/powerful_soul.lua
index cee228f7185..4174abd5413 100644
--- a/data-otservbr-global/monster/quests/soul_war/powerful_soul.lua
+++ b/data-otservbr-global/monster/quests/soul_war/powerful_soul.lua
@@ -101,7 +101,7 @@ mType.onThink = function(monster, interval)
 				boss:addReflectElement(elementType, reflectPercent)
 			end
 			boss:addDefense(10)
-			boss:setMaxHealth(boss:getHealth() + 10000)
+			boss:setMaxHealth(boss:getMaxHealth() + 10000)
 			boss:addHealth(10000)
 		end
 		transformTimeCount = 0
diff --git a/data-otservbr-global/monster/quests/soul_war/soul_sphere.lua b/data-otservbr-global/monster/quests/soul_war/soul_sphere.lua
index c0142e3e611..5cf6560132f 100644
--- a/data-otservbr-global/monster/quests/soul_war/soul_sphere.lua
+++ b/data-otservbr-global/monster/quests/soul_war/soul_sphere.lua
@@ -84,26 +84,39 @@ monster.immunities = {
 }
 
 local moveTimeCount = 0
+local stop = false
 mType.onThink = function(monster, interval)
+	if stop then
+		return
+	end
+
 	moveTimeCount = moveTimeCount + interval
-	if moveTimeCount == 3000 then
-		monster:move(DIRECTION_WEST)
-		moveTimeCount = 0
-		local monsterPos = monster:getPosition()
-		local nextPos = Position(monsterPos.x - 1, monsterPos.y, monsterPos.z)
-		local tile = Tile(nextPos)
-		if not tile then
-			return
-		end
+	if moveTimeCount >= 3000 then
+		local currentPos = monster:getPosition()
+		local newPos = Position(currentPos.x - 1, currentPos.y, currentPos.z)
 
-		for _, creatureId in pairs(tile:getCreatures()) do
-			local monster = Monster(creatureId)
-			if monster and monster:getName() == "Goshnar's Greed" then
-				monster:setHealth(monster:getMaxHealth())
-				break
+		local nextTile = Tile(newPos)
+		if nextTile then
+			for _, creatureId in pairs(nextTile:getCreatures()) do
+				local greedMonster = Monster(creatureId)
+				if greedMonster and greedMonster:getName() == "Goshnar's Greed" then
+					greedMonster:setHealth(greedMonster:getMaxHealth())
+					stop = true
+					return
+				end
 			end
 		end
+
+		if not stop then
+			monster:teleportTo(newPos, true)
+			moveTimeCount = 0
+		end
 	end
 end
 
+mType.onSpawn = function(monster)
+	moveTimeCount = 0
+	stop = false
+end
+
 mType:register(monster)
diff --git a/src/game/game.cpp b/src/game/game.cpp
index f3415b0cb7e..ee49b9cc7cc 100644
--- a/src/game/game.cpp
+++ b/src/game/game.cpp
@@ -1487,7 +1487,7 @@ ReturnValue Game::internalMoveCreature(std::shared_ptr<Creature> creature, Direc
 		return RETURNVALUE_NOTPOSSIBLE;
 	}
 
-	if (creature->getBaseSpeed() == 0 && flags != FLAG_IGNORENOTMOVABLE) {
+	if (creature->getBaseSpeed() == 0) {
 		return RETURNVALUE_NOTMOVABLE;
 	}
 
diff --git a/src/lua/functions/creatures/creature_functions.cpp b/src/lua/functions/creatures/creature_functions.cpp
index da935d05fdc..6b09945971a 100644
--- a/src/lua/functions/creatures/creature_functions.cpp
+++ b/src/lua/functions/creatures/creature_functions.cpp
@@ -968,7 +968,7 @@ int CreatureFunctions::luaCreatureMove(lua_State* L) {
 			lua_pushnil(L);
 			return 1;
 		}
-		lua_pushnumber(L, g_game().internalMoveCreature(creature, direction, FLAG_IGNORENOTMOVABLE));
+		lua_pushnumber(L, g_game().internalMoveCreature(creature, direction, FLAG_NOLIMIT));
 	} else {
 		std::shared_ptr<Tile> tile = getUserdataShared<Tile>(L, 2);
 		if (!tile) {

From bfbcf19504603b0bf43b57e981102ccac7060a3f Mon Sep 17 00:00:00 2001
From: GitHub Actions <github-actions[bot]@users.noreply.github.com>
Date: Fri, 9 Aug 2024 05:08:29 +0000
Subject: [PATCH 40/60] Lua code format - (Stylua)

---
 data-otservbr-global/monster/quests/soul_war/goshnars_greed.lua | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/data-otservbr-global/monster/quests/soul_war/goshnars_greed.lua b/data-otservbr-global/monster/quests/soul_war/goshnars_greed.lua
index 4f197ad9541..2ec3a528eb5 100644
--- a/data-otservbr-global/monster/quests/soul_war/goshnars_greed.lua
+++ b/data-otservbr-global/monster/quests/soul_war/goshnars_greed.lua
@@ -68,7 +68,7 @@ monster.light = {
 }
 
 monster.summon = {
-	maxSummons = 1
+	maxSummons = 1,
 }
 
 monster.voices = {

From 46da501195b92d62188550fdd5eb254d91cd1320 Mon Sep 17 00:00:00 2001
From: Eduardo Dantas <eduardo.dantas@hotmail.com.br>
Date: Fri, 9 Aug 2024 10:46:32 -0300
Subject: [PATCH 41/60] fix: soul ghosts looktype

---
 data-otservbr-global/monster/quests/soul_war/powerful_soul.lua | 2 +-
 data-otservbr-global/monster/quests/soul_war/strong_soul.lua   | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/data-otservbr-global/monster/quests/soul_war/powerful_soul.lua b/data-otservbr-global/monster/quests/soul_war/powerful_soul.lua
index 4174abd5413..0ece602eab5 100644
--- a/data-otservbr-global/monster/quests/soul_war/powerful_soul.lua
+++ b/data-otservbr-global/monster/quests/soul_war/powerful_soul.lua
@@ -4,7 +4,7 @@ local monster = {}
 monster.description = "a powerful soul"
 monster.experience = 0
 monster.outfit = {
-	lookType = 48,
+	lookType = 568,
 	lookHead = 0,
 	lookBody = 0,
 	lookLegs = 0,
diff --git a/data-otservbr-global/monster/quests/soul_war/strong_soul.lua b/data-otservbr-global/monster/quests/soul_war/strong_soul.lua
index 3fb844d1f97..ae3615b6eb4 100644
--- a/data-otservbr-global/monster/quests/soul_war/strong_soul.lua
+++ b/data-otservbr-global/monster/quests/soul_war/strong_soul.lua
@@ -4,7 +4,7 @@ local monster = {}
 monster.description = "a strong soul"
 monster.experience = 0
 monster.outfit = {
-	lookType = 48,
+	lookType = 566,
 	lookHead = 0,
 	lookBody = 0,
 	lookLegs = 0,

From a55a2b5381151727b4e837fc45adfcbb4e965ccc Mon Sep 17 00:00:00 2001
From: Eduardo Dantas <eduardo.dantas@hotmail.com.br>
Date: Fri, 9 Aug 2024 14:17:45 -0300
Subject: [PATCH 42/60] fix: final conflicts

---
 data/scripts/talkactions/god/test.lua | 44 ---------------------------
 src/enums/player_icons.hpp            | 10 +++---
 2 files changed, 5 insertions(+), 49 deletions(-)

diff --git a/data/scripts/talkactions/god/test.lua b/data/scripts/talkactions/god/test.lua
index ac6ca921483..25b2fd49da2 100644
--- a/data/scripts/talkactions/god/test.lua
+++ b/data/scripts/talkactions/god/test.lua
@@ -36,47 +36,3 @@ end
 testLog:separator(" ")
 testLog:groupType("god")
 testLog:register()
-
-local testIcons = TalkAction("/testicons")
-
-local function convertIconsToBitValue(iconList)
-	local bitObj = NewBit(0)
-	for icon in string.gmatch(iconList, "%d+") do
-		icon = tonumber(icon)
-		if icon then
-			local flag = bit.lshift(1, icon - 1)
-			bitObj:updateFlag(flag)
-		end
-	end
-	return bitObj:getNumber()
-end
-
---[[Usage:
-/testicons 1
-/testicons 2
-/testicons 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
-]]
-function testIcons.onSay(player, words, param)
-	if param == "" then
-		player:sendCancelMessage("Icon required.")
-		logger.error("[testIcons.onSay] - Icon required")
-		return true
-	end
-
-	function Player:sendIconsTest()
-		local msg = NetworkMessage()
-		msg:addByte(0xA2)
-		local icons = convertIconsToBitValue(param)
-		msg:addU32(icons)
-		msg:addByte(tonumber(param))
-		msg:sendToPlayer(self)
-	end
-
-	player:sendIconsTest()
-	return true
-end
-
-testIcons:separator(" ")
-testIcons:setDescription("[Usage]: /seticons {icon1}, {icon2}, {icon3}, ...")
-testIcons:groupType("god")
-testIcons:register()
diff --git a/src/enums/player_icons.hpp b/src/enums/player_icons.hpp
index c289144bd7b..7878d9e5037 100644
--- a/src/enums/player_icons.hpp
+++ b/src/enums/player_icons.hpp
@@ -35,11 +35,11 @@ enum class PlayerIcon : uint8_t {
 	GreaterHex = 18,
 	Rooted = 19,
 	Feared = 20,
-	Goshnar1 = 21,
-	Goshnar2 = 22,
-	Goshnar3 = 23,
-	Goshnar4 = 24,
-	Goshnar5 = 25,
+	GoshnarTaint1 = 21,
+	GoshnarTaint2 = 22,
+	GoshnarTaint3 = 23,
+	GoshnarTaint4 = 24,
+	GoshnarTaint5 = 25,
 	NewManaShield = 26,
 	Agony = 27,
 

From f4a8e547fc28cf20d6bc56ee48c91b35465da664 Mon Sep 17 00:00:00 2001
From: Eduardo Dantas <eduardo.dantas@hotmail.com.br>
Date: Fri, 9 Aug 2024 14:55:35 -0300
Subject: [PATCH 43/60] fix: register missing stairs

---
 data/items/items.xml | 44 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 44 insertions(+)

diff --git a/data/items/items.xml b/data/items/items.xml
index c898c235f8d..a4750514e26 100644
--- a/data/items/items.xml
+++ b/data/items/items.xml
@@ -74771,12 +74771,31 @@ Granted by TibiaGoals.com"/>
 		<attribute key="transformOnUse" value="42367"/>
 		<attribute key="wrapableto" value="23398"/>
 	</item>
+	<item id="42390" name="stairs"/>
+	<item id="42391" name="stairs">
+		<attribute key="floorchange" value="north"/>
+	</item>
+	<item id="42392" name="stairs"/>
+	<item id="42393" name="stairs">
+		<attribute key="floorchange" value="west"/>
+	</item>
+	<item id="42394" name="stairs"/>
+	<item id="42395" name="stairs">
+		<attribute key="floorchange" value="east"/>
+	</item>
+	<item id="42396" name="stairs"/>
+	<item id="42397" name="stairs">
+		<attribute key="floorchange" value="south"/>
+	</item>
+	<item id="42618" name="stairs"/>
 	<item id="42619" name="stairs">
 		<attribute key="floorchange" value="north"/>
 	</item>
+	<item id="42620" name="stairs"/>
 	<item id="42621" name="stairs">
 		<attribute key="floorchange" value="west"/>
 	</item>
+	<item id="42622" name="stairs"/>
 	<item id="42623" name="stairs">
 		<attribute key="floorchange" value="south"/>
 	</item>
@@ -74811,6 +74830,22 @@ Granted by TibiaGoals.com"/>
 	<item id="42632" name="stairs">
 		<attribute key="floorchange" value="east"/>
 	</item>
+	<item id="42964" name="stairs"/>
+	<item id="42965" name="stairs">
+		<attribute key="floorchange" value="north"/>
+	</item>
+	<item id="42966" name="stairs"/>
+	<item id="42967" name="stairs">
+		<attribute key="floorchange" value="west"/>
+	</item>
+	<item id="42968" name="stairs"/>
+	<item id="42969" name="stairs">
+		<attribute key="floorchange" value="east"/>
+	</item>
+	<item id="42970" name="stairs"/>
+	<item id="42971" name="stairs">
+		<attribute key="floorchange" value="south"/>
+	</item>
 	<item id="43952" article="a" name="closed door">
 		<attribute key="type" value="door"/>
 		<attribute key="blockProjectile" value="1"/>
@@ -74829,6 +74864,15 @@ Granted by TibiaGoals.com"/>
 		<attribute key="type" value="door"/>
 		<attribute key="transformOnUse" value="43953"/>
 	</item>
+	<item id="43129" name="stairs"/>
+	<item id="43130" name="stairs">
+		<attribute key="floorchange" value="north"/>
+	</item>
+	<item id="43131" name="stairs"/>
+	<item id="43132" name="stairs">
+		<attribute key="floorchange" value="west"/>
+	</item>
+	<item id="43133" name="stairs"/>
 	<item id="43134" name="stairs">
 		<attribute key="floorchange" value="south"/>
 	</item>

From a9b5c9529beaee5264146766189bab05c24b73b8 Mon Sep 17 00:00:00 2001
From: Eduardo Dantas <eduardo.dantas@hotmail.com.br>
Date: Tue, 10 Sep 2024 00:07:14 -0300
Subject: [PATCH 44/60] fix: goshnar's cruelty and greed mechanic

---
 data-otservbr-global/lib/quests/soul_war.lua  |  6 ++++--
 .../quests/soul_war/goshnars_cruelty.lua      | 18 +++++++++++-----
 .../quests/soul_war/goshnars_greed.lua        | 16 ++++++++++++--
 .../monster/quests/soul_war/soul_sphere.lua   |  6 +++---
 .../quests/soul_war/soul_war_mechanics.lua    | 21 +++++++++++++++++++
 src/config/configmanager.cpp                  |  2 +-
 6 files changed, 56 insertions(+), 13 deletions(-)

diff --git a/data-otservbr-global/lib/quests/soul_war.lua b/data-otservbr-global/lib/quests/soul_war.lua
index 5df73dc6115..009fe7f31ba 100644
--- a/data-otservbr-global/lib/quests/soul_war.lua
+++ b/data-otservbr-global/lib/quests/soul_war.lua
@@ -371,6 +371,7 @@ SoulWarQuest = {
 			timeToFightAgain = 20 * 60 * 60, -- 20 hours
 			onUseExtra = function(player)
 				SoulWarQuest.kvSoulWar:remove("greedy-maw-action")
+				SoulWarQuest.kvSoulWar:remove("goshnars-cruelty-defense-drain")
 				player:soulWarQuestKV():scoped("furious-crater"):remove("greedy-maw-action")
 			end,
 		},
@@ -1379,9 +1380,10 @@ function Monster:goshnarsDefenseIncrease(kvName)
 	local lastItemUseTime = SoulWarQuest.kvSoulWar:get(kvName) or 0
 	-- Checks if more than config time have passed since the item was last used.
 	if currentTime >= lastItemUseTime + SoulWarQuest.timeToIncreaseCrueltyDefense then
-		logger.trace("{} old defense {}", self:getName(), self:getDefense())
 		self:addDefense(SoulWarQuest.goshnarsCrueltyDefenseChange)
-		logger.trace("{} new defense {}", self:getName(), self:getDefense())
+		-- Register the drain callback to modify the damage for goshnar's cruelty
+		local newValue = SoulWarQuest.kvSoulWar:get("goshnars-cruelty-defense-drain") or SoulWarQuest.goshnarsCrueltyDefenseChange
+		SoulWarQuest.kvSoulWar:set("goshnars-cruelty-defense-drain", newValue + 1) -- Increment the value to track usage or modifications
 
 		--- Updates the KV to reflect the timing of the increase to maintain control.
 		SoulWarQuest.kvSoulWar:set(kvName, currentTime)
diff --git a/data-otservbr-global/monster/quests/soul_war/goshnars_cruelty.lua b/data-otservbr-global/monster/quests/soul_war/goshnars_cruelty.lua
index 2142f4527ec..300a47184e3 100644
--- a/data-otservbr-global/monster/quests/soul_war/goshnars_cruelty.lua
+++ b/data-otservbr-global/monster/quests/soul_war/goshnars_cruelty.lua
@@ -15,6 +15,7 @@ monster.outfit = {
 
 monster.events = {
 	"SoulWarBossesDeath",
+	"GoshnarsCrueltyBuff",
 }
 
 monster.health = 300000
@@ -134,16 +135,23 @@ monster.immunities = {
 	{ type = "bleed", condition = false },
 }
 
-mType.onThink = function(monster)
-	monster:goshnarsDefenseIncrease("greedy-maw-action")
+local firstTime = 0
+mType.onThink = function(monster, interval)
+	firstTime = firstTime + interval
+	-- Run only 15 seconds before creation
+	if firstTime >= 15000 then
+		monster:goshnarsDefenseIncrease("greedy-maw-action")
+	end
 end
 
 mType.onAppear = function(monster, creature) end
 
-mType.onSpawn = function(monster)
-	if monster:getType():isRewardBoss() then
-		monster:setReward(true)
+mType.onSpawn = function(monsterCallback)
+	if monsterCallback:getType():isRewardBoss() then
+		monsterCallback:setReward(true)
 	end
+
+	firstTime = 0
 end
 
 mType.onDisappear = function(monster, creature) end
diff --git a/data-otservbr-global/monster/quests/soul_war/goshnars_greed.lua b/data-otservbr-global/monster/quests/soul_war/goshnars_greed.lua
index 2ec3a528eb5..7c6110f4592 100644
--- a/data-otservbr-global/monster/quests/soul_war/goshnars_greed.lua
+++ b/data-otservbr-global/monster/quests/soul_war/goshnars_greed.lua
@@ -138,7 +138,7 @@ local immuneTimeCount = 0
 local isImmune = nil
 local createdSoulSphere = nil
 mType.onThink = function(monsterCallback, interval)
-	if GreedbeastKills == 5 and isImmune == nil then
+	if GreedbeastKills >= 5 and isImmune == nil then
 		isImmune = monsterCallback:immune(false)
 		monsterCallback:teleportTo(Position(33741, 31659, 14))
 		monsterCallback:setSpeed(0)
@@ -166,12 +166,24 @@ mType.onSpawn = function(monster)
 		monster:setReward(true)
 	end
 
+	isImmune = nil
 	monster:immune(true)
 	immuneTimeCount = 0
 	GreedbeastKills = 0
 end
 
-mType.onDisappear = function(monster, creature) end
+mType.onDisappear = function(monster, creature)
+	if creature:getName() == "Greedbeast" then
+		logger.debug("GreedbeastKills {}", GreedbeastKills)
+	end
+	if creature:getName() == "Goshnar's Greed" then
+		logger.debug("Killed goshnar's greed")
+		if createdSoulSphere then
+			logger.debug("Found soul sphere, remove it")
+			createdSoulSphere:remove()
+		end
+	end
+end
 
 mType.onMove = function(monster, creature, fromPosition, toPosition) end
 
diff --git a/data-otservbr-global/monster/quests/soul_war/soul_sphere.lua b/data-otservbr-global/monster/quests/soul_war/soul_sphere.lua
index 5cf6560132f..160879ba9db 100644
--- a/data-otservbr-global/monster/quests/soul_war/soul_sphere.lua
+++ b/data-otservbr-global/monster/quests/soul_war/soul_sphere.lua
@@ -98,9 +98,9 @@ mType.onThink = function(monster, interval)
 		local nextTile = Tile(newPos)
 		if nextTile then
 			for _, creatureId in pairs(nextTile:getCreatures()) do
-				local greedMonster = Monster(creatureId)
-				if greedMonster and greedMonster:getName() == "Goshnar's Greed" then
-					greedMonster:setHealth(greedMonster:getMaxHealth())
+				local tileMonster = Monster(creatureId)
+				if tileMonster and tileMonster:getName() == "Goshnar's Greed" then
+					tileMonster:setHealth(tileMonster:getMaxHealth())
 					stop = true
 					return
 				end
diff --git a/data-otservbr-global/scripts/quests/soul_war/soul_war_mechanics.lua b/data-otservbr-global/scripts/quests/soul_war/soul_war_mechanics.lua
index dc7197176fa..f326455fdd9 100644
--- a/data-otservbr-global/scripts/quests/soul_war/soul_war_mechanics.lua
+++ b/data-otservbr-global/scripts/quests/soul_war/soul_war_mechanics.lua
@@ -880,6 +880,11 @@ function greedyMaw.onUse(player, item, fromPosition, target, toPosition, isHotke
 				goshnarsCruelty:addDefense(-SoulWarQuest.goshnarsCrueltyDefenseChange)
 				logger.debug("Greedy Maw used on Goshnar's Cruelty, new defense {}", goshnarsCruelty:getDefense())
 			end
+
+			local defenseDrainValue = SoulWarQuest.kvSoulWar:get("goshnars-cruelty-defense-drain") or 0
+			if defenseDrainValue > 0 then
+				SoulWarQuest.kvSoulWar:set("goshnars-cruelty-defense-drain", defenseDrainValue - 1)
+			end
 		end
 		return true
 	end
@@ -1066,3 +1071,19 @@ for _, pos in pairs(teleportPositions) do
 end
 
 teleportStepRemoveIcon:register()
+
+local goshnarsCrueltyBuff = CreatureEvent("GoshnarsCrueltyBuff")
+
+function goshnarsCrueltyBuff.onHealthChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin)
+	if creature and creature:isMonster() and attacker:isPlayer() and creature:getName() == "Goshnar's Cruelty" then
+		local newValue = SoulWarQuest.kvSoulWar:get("goshnars-cruelty-defense-drain") or SoulWarQuest.goshnarsCrueltyDefenseChange
+		if newValue ~= 0 then
+			local multiplier = math.max(0, 1 - (newValue / 100))
+			return primaryDamage * multiplier, primaryType, secondaryDamage * multiplier, secondaryType
+		end
+	end
+
+	return primaryDamage, primaryType, secondaryDamage, secondaryType
+end
+
+goshnarsCrueltyBuff:register()
diff --git a/src/config/configmanager.cpp b/src/config/configmanager.cpp
index 6390d0699b3..80126ddac93 100644
--- a/src/config/configmanager.cpp
+++ b/src/config/configmanager.cpp
@@ -379,7 +379,7 @@ bool ConfigManager::reload() {
 }
 
 void ConfigManager::missingConfigWarning(const char* identifier) {
-	g_logger().warn("[{}]: Missing configuration for identifier: {}", __FUNCTION__, identifier);
+	g_logger().debug("[{}]: Missing configuration for identifier: {}", __FUNCTION__, identifier);
 }
 
 std::string ConfigManager::loadStringConfig(lua_State* L, const ConfigKey_t &key, const char* identifier, const std::string &defaultValue) {

From 7622cfdfe4bf7df76ca555fb3dcdf45dc66f97c0 Mon Sep 17 00:00:00 2001
From: Eduardo Dantas <eduardo.dantas@hotmail.com.br>
Date: Tue, 10 Sep 2024 00:07:29 -0300
Subject: [PATCH 45/60] fix: reset taint correctly

---
 data-otservbr-global/lib/quests/soul_war.lua | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/data-otservbr-global/lib/quests/soul_war.lua b/data-otservbr-global/lib/quests/soul_war.lua
index 009fe7f31ba..0c92ddc0c7d 100644
--- a/data-otservbr-global/lib/quests/soul_war.lua
+++ b/data-otservbr-global/lib/quests/soul_war.lua
@@ -1196,7 +1196,15 @@ function Player:resetTaints(skipCheckTime)
 		end
 		self:resetTaintConditions()
 		soulWarQuest:remove("firstTaintTime")
-		self:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Your goshnar's taints have been reset. You didn't finish the quest in 14 days")
+		local resetMessage = "Your Goshnar's taints have been reset."
+		if not skipCheckTime then
+			resetMessage = resetMessage .. " You didn't finish the quest in 14 days."
+		end
+		self:sendTextMessage(MESSAGE_EVENT_ADVANCE, resetMessage)
+
+		for bossName, _ in pairs(SoulWarQuest.miniBosses) do
+			soulWarQuest:remove(bossName)
+		end
 	end
 end
 

From 3a836e9be6be076c0845c0545517dfb8caa1382d Mon Sep 17 00:00:00 2001
From: Eduardo Dantas <eduardo.dantas@hotmail.com.br>
Date: Tue, 10 Sep 2024 00:21:06 -0300
Subject: [PATCH 46/60] fix: remove duplicated script

---
 .../actions_portal_reward_soulwar.lua         | 23 -------------------
 1 file changed, 23 deletions(-)
 delete mode 100644 data-otservbr-global/scripts/quests/soul_war/actions_portal_reward_soulwar.lua

diff --git a/data-otservbr-global/scripts/quests/soul_war/actions_portal_reward_soulwar.lua b/data-otservbr-global/scripts/quests/soul_war/actions_portal_reward_soulwar.lua
deleted file mode 100644
index 7aaff112056..00000000000
--- a/data-otservbr-global/scripts/quests/soul_war/actions_portal_reward_soulwar.lua
+++ /dev/null
@@ -1,23 +0,0 @@
-local portalReward = MoveEvent()
-
-function portalReward.onStepIn(creature, item, position, fromPosition)
-	local player = creature:getPlayer()
-	if not player then
-		return false
-	end
-
-	local soulWarQuest = player:soulWarQuestKV()
-	-- Checks if the boss has already been defeated
-	if not soulWarQuest:get("goshnar's-megalomania-killed") then
-		player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Only warriors who defeated Goshnar's Megalomania can access this area.")
-		player:teleportTo(fromPosition, true)
-		return false
-	end
-
-	player:teleportTo(Position(33621, 31411, 10))
-	player:getPosition():sendMagicEffect(CONST_ME_TELEPORT)
-	return true
-end
-
-portalReward:position({ x = 33621, y = 31416, z = 10 })
-portalReward:register()

From 3aab8a31794986ed2b3f1d015b495b72a31a81cf Mon Sep 17 00:00:00 2001
From: Eduardo Dantas <eduardo.dantas@hotmail.com.br>
Date: Tue, 10 Sep 2024 00:30:47 -0300
Subject: [PATCH 47/60] fix: revert conflict

---
 data-otservbr-global/startup/tables/item.lua | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/data-otservbr-global/startup/tables/item.lua b/data-otservbr-global/startup/tables/item.lua
index 790090f417b..e2f94a88d18 100644
--- a/data-otservbr-global/startup/tables/item.lua
+++ b/data-otservbr-global/startup/tables/item.lua
@@ -1811,7 +1811,7 @@ ItemUnique = {
 	-- Path: data\scripts\actions\quests\the_rookie_guard\mission06_run_like_wolf.lua
 	-- Poacher corpse
 	[40044] = {
-		itemId = 3204,
+		itemId = 111,
 		itemPos = { x = 32135, y = 32133, z = 8 },
 	},
 	-- War wolf corpse

From 631c6c31e7e23379c23340b2412f385b5bb02a6d Mon Sep 17 00:00:00 2001
From: GitHub Actions <github-actions[bot]@users.noreply.github.com>
Date: Tue, 10 Sep 2024 03:35:01 +0000
Subject: [PATCH 48/60] fix: indent

---
 src/lua/functions/creatures/player/player_functions.cpp | 1 +
 src/lua/functions/creatures/player/player_functions.hpp | 3 ++-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/lua/functions/creatures/player/player_functions.cpp b/src/lua/functions/creatures/player/player_functions.cpp
index 111f2a12c99..421ceefcb0d 100644
--- a/src/lua/functions/creatures/player/player_functions.cpp
+++ b/src/lua/functions/creatures/player/player_functions.cpp
@@ -4411,6 +4411,7 @@ int PlayerFunctions::luaPlayerTakeScreenshot(lua_State* L) {
 	pushBoolean(L, true);
 	return 1;
 }
+
 int PlayerFunctions::luaPlayerSendIconBakragore(lua_State* L) {
 	// player:sendIconBakragore()
 	const auto &player = getUserdataShared<Player>(L, 1);
diff --git a/src/lua/functions/creatures/player/player_functions.hpp b/src/lua/functions/creatures/player/player_functions.hpp
index d75cc8aa29f..aa4db5857f7 100644
--- a/src/lua/functions/creatures/player/player_functions.hpp
+++ b/src/lua/functions/creatures/player/player_functions.hpp
@@ -372,11 +372,12 @@ class PlayerFunctions final : LuaScriptInterface {
 		registerMethod(L, "Player", "getTitles", PlayerFunctions::luaPlayerGetTitles);
 		registerMethod(L, "Player", "setCurrentTitle", PlayerFunctions::luaPlayerSetCurrentTitle);
 
+		// Store Summary
 		registerMethod(L, "Player", "createTransactionSummary", PlayerFunctions::luaPlayerCreateTransactionSummary);
 
 		registerMethod(L, "Player", "takeScreenshot", PlayerFunctions::luaPlayerTakeScreenshot);
 		registerMethod(L, "Player", "sendIconBakragore", PlayerFunctions::luaPlayerSendIconBakragore);
-    registerMethod(L, "Player", "removeIconBakragore", PlayerFunctions::luaPlayerRemoveIconBakragore);
+		registerMethod(L, "Player", "removeIconBakragore", PlayerFunctions::luaPlayerRemoveIconBakragore);
 		registerMethod(L, "Player", "sendCreatureAppear", PlayerFunctions::luaPlayerSendCreatureAppear);
 
 		GroupFunctions::init(L);

From 4b9816c73809dba5cd0483b1dd8d928c8f27ddc6 Mon Sep 17 00:00:00 2001
From: Eduardo Dantas <eduardo.dantas@hotmail.com.br>
Date: Tue, 10 Sep 2024 09:30:02 -0300
Subject: [PATCH 49/60] fix: mirror image change to table and remove xml files

---
 .../monster/quests/soul_war/mirror_image.lua  |  12 +-
 .../world/otservbr-monster.xml                |  15 +
 .../ebb_and_flow/ebb-flow-empty-house.xml     |   2 -
 .../ebb_and_flow/ebb-flow-empty-monster.xml   |   2 -
 .../ebb_and_flow/ebb-flow-empty-npc.xml       |   2 -
 .../ebb_and_flow/ebb-flow-empty-zones.xml     |   2 -
 .../soul_war/ebb_and_flow/ebb-flow-house.xml  |   2 -
 .../ebb_and_flow/ebb-flow-inundate-house.xml  |   2 -
 .../ebb-flow-inundate-monster.xml             |   2 -
 .../ebb_and_flow/ebb-flow-inundate-npc.xml    |   2 -
 .../ebb_and_flow/ebb-flow-inundate-zones.xml  |   2 -
 .../ebb_and_flow/ebb-flow-monster.xml         | 540 ------------------
 .../soul_war/ebb_and_flow/ebb-flow-npc.xml    |   2 -
 .../soul_war/ebb_and_flow/ebb-flow-zones.xml  |   2 -
 14 files changed, 18 insertions(+), 571 deletions(-)
 delete mode 100644 data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-empty-house.xml
 delete mode 100644 data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-empty-monster.xml
 delete mode 100644 data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-empty-npc.xml
 delete mode 100644 data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-empty-zones.xml
 delete mode 100644 data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-house.xml
 delete mode 100644 data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-inundate-house.xml
 delete mode 100644 data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-inundate-monster.xml
 delete mode 100644 data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-inundate-npc.xml
 delete mode 100644 data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-inundate-zones.xml
 delete mode 100644 data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-monster.xml
 delete mode 100644 data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-npc.xml
 delete mode 100644 data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-zones.xml

diff --git a/data-otservbr-global/monster/quests/soul_war/mirror_image.lua b/data-otservbr-global/monster/quests/soul_war/mirror_image.lua
index ceacde54c26..600550d3d78 100644
--- a/data-otservbr-global/monster/quests/soul_war/mirror_image.lua
+++ b/data-otservbr-global/monster/quests/soul_war/mirror_image.lua
@@ -114,12 +114,6 @@ mType.onPlayerAttack = function(monster, attackerPlayer)
 	logger.info("Player {}, attacking monster {}", attackerPlayer:getName(), monster:getName())
 
 	local apparitionType = ""
-	local apparitionTypes = {
-		"Druid's Apparition",
-		"Knight's Apparition",
-		"Paladin's Apparition",
-		"Sorcerer's Apparition",
-	}
 
 	local sameVocationProbability = 70 -- 70% chance for create monster of first player attack vocation
 	if attackerPlayer:isDruid() then
@@ -134,9 +128,9 @@ mType.onPlayerAttack = function(monster, attackerPlayer)
 
 	if math.random(100) > sameVocationProbability then
 		repeat
-			local randomIndex = math.random(#apparitionTypes)
-			if apparitionTypes[randomIndex] ~= apparitionType then
-				apparitionType = apparitionTypes[randomIndex]
+			local randomIndex = math.random(#SoulWarQuest.apparitionNames)
+			if SoulWarQuest.apparitionNames[randomIndex] ~= apparitionType then
+				apparitionType = SoulWarQuest.apparitionNames[randomIndex]
 				break
 			end
 		until false
diff --git a/data-otservbr-global/world/otservbr-monster.xml b/data-otservbr-global/world/otservbr-monster.xml
index ef003deee1a..308d9631af9 100644
--- a/data-otservbr-global/world/otservbr-monster.xml
+++ b/data-otservbr-global/world/otservbr-monster.xml
@@ -162156,6 +162156,9 @@
 		<monster name="Blood Crab" x="0" y="-3" z="14" spawntime="60" />
 		<monster name="Sea Serpent" x="0" y="-1" z="14" spawntime="60" />
 	</monster>
+	<monster centerx="33747" centery="31629" centerz="14" radius="1">
+		<monster name="Dreadful Harvester" x="0" y="0" z="14" spawntime="10" />
+	</monster>
 	<monster centerx="32798" centery="31630" centerz="14" radius="1">
 		<monster name="Ghoul" x="1" y="0" z="14" spawntime="90" />
 	</monster>
@@ -162168,12 +162171,18 @@
 	<monster centerx="32795" centery="31631" centerz="14" radius="1">
 		<monster name="Ghoul" x="1" y="0" z="14" spawntime="90" />
 	</monster>
+	<monster centerx="33744" centery="31631" centerz="14" radius="1">
+		<monster name="Dreadful Harvester" x="0" y="0" z="14" spawntime="10" />
+	</monster>
 	<monster centerx="32782" centery="31632" centerz="14" radius="1">
 		<monster name="Ghoul" x="1" y="0" z="14" spawntime="90" />
 	</monster>
 	<monster centerx="32799" centery="31632" centerz="14" radius="1">
 		<monster name="Bonelord" x="1" y="0" z="14" spawntime="90" />
 	</monster>
+	<monster centerx="33738" centery="31632" centerz="14" radius="1">
+		<monster name="Weeping Soul" x="0" y="0" z="14" spawntime="10" />
+	</monster>
 	<monster centerx="32795" centery="31633" centerz="14" radius="1">
 		<monster name="Skeleton" x="1" y="0" z="14" spawntime="90" />
 		<monster name="Skeleton" x="1" y="1" z="14" spawntime="90" />
@@ -162185,6 +162194,9 @@
 		<monster name="Demon Skeleton" x="-1" y="1" z="14" spawntime="90" />
 		<monster name="Skeleton" x="1" y="1" z="14" spawntime="90" />
 	</monster>
+	<monster centerx="33748" centery="31634" centerz="14" radius="1">
+		<monster name="Weeping Soul" x="0" y="0" z="14" spawntime="10" />
+	</monster>
 	<monster centerx="32792" centery="31635" centerz="14" radius="1">
 		<monster name="Ghoul" x="1" y="0" z="14" spawntime="90" />
 	</monster>
@@ -162201,6 +162213,9 @@
 	<monster centerx="33505" centery="31636" centerz="14" radius="3">
 		<monster name="Blood Crab" x="-1" y="2" z="14" spawntime="60" />
 	</monster>
+	<monster centerx="33744" centery="31636" centerz="14" radius="1">
+		<monster name="Spiteful Spitter" x="0" y="0" z="14" spawntime="10" />
+	</monster>
 	<monster centerx="33298" centery="31640" centerz="14" radius="1">
 		<monster name="Behemoth" x="-1" y="0" z="14" spawntime="90" />
 	</monster>
diff --git a/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-empty-house.xml b/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-empty-house.xml
deleted file mode 100644
index e5a6b86118e..00000000000
--- a/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-empty-house.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0"?>
-<houses />
diff --git a/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-empty-monster.xml b/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-empty-monster.xml
deleted file mode 100644
index 8704e6da3b2..00000000000
--- a/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-empty-monster.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0"?>
-<monsters />
diff --git a/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-empty-npc.xml b/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-empty-npc.xml
deleted file mode 100644
index af7984e2faf..00000000000
--- a/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-empty-npc.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0"?>
-<npcs />
diff --git a/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-empty-zones.xml b/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-empty-zones.xml
deleted file mode 100644
index a9224bd3c2d..00000000000
--- a/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-empty-zones.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0"?>
-<zones />
diff --git a/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-house.xml b/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-house.xml
deleted file mode 100644
index e5a6b86118e..00000000000
--- a/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-house.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0"?>
-<houses />
diff --git a/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-inundate-house.xml b/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-inundate-house.xml
deleted file mode 100644
index e5a6b86118e..00000000000
--- a/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-inundate-house.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0"?>
-<houses />
diff --git a/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-inundate-monster.xml b/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-inundate-monster.xml
deleted file mode 100644
index 8704e6da3b2..00000000000
--- a/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-inundate-monster.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0"?>
-<monsters />
diff --git a/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-inundate-npc.xml b/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-inundate-npc.xml
deleted file mode 100644
index af7984e2faf..00000000000
--- a/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-inundate-npc.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0"?>
-<npcs />
diff --git a/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-inundate-zones.xml b/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-inundate-zones.xml
deleted file mode 100644
index a9224bd3c2d..00000000000
--- a/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-inundate-zones.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0"?>
-<zones />
diff --git a/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-monster.xml b/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-monster.xml
deleted file mode 100644
index af4787bae03..00000000000
--- a/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-monster.xml
+++ /dev/null
@@ -1,540 +0,0 @@
-<?xml version="1.0"?>
-<monsters>
-	<monster centerx="33934" centery="31014" centerz="8" radius="1">
-		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33939" centery="31014" centerz="8" radius="1">
-		<monster name="Capricious Phantom" x="1" y="1" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33944" centery="31014" centerz="8" radius="1">
-		<monster name="Turbulent Elemental" x="1" y="1" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33930" centery="31015" centerz="8" radius="1">
-		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33940" centery="31018" centerz="8" radius="1">
-		<monster name="Hazardous Phantom" x="1" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33931" centery="31019" centerz="8" radius="1">
-		<monster name="Hazardous Phantom" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33934" centery="31020" centerz="8" radius="1">
-		<monster name="Turbulent Elemental" x="0" y="1" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33941" centery="31025" centerz="8" radius="1">
-		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33931" centery="31027" centerz="8" radius="1">
-		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33911" centery="31037" centerz="8" radius="1">
-		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33891" centery="31038" centerz="8" radius="1">
-		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33913" centery="31038" centerz="8" radius="1">
-		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33891" centery="31040" centerz="8" radius="1">
-		<monster name="Hazardous Phantom" x="-1" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33931" centery="31041" centerz="8" radius="1">
-		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33934" centery="31041" centerz="8" radius="1">
-		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33940" centery="31041" centerz="8" radius="1">
-		<monster name="Capricious Phantom" x="1" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33911" centery="31042" centerz="8" radius="1">
-		<monster name="Capricious Phantom" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33891" centery="31043" centerz="8" radius="1">
-		<monster name="Capricious Phantom" x="1" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33938" centery="31043" centerz="8" radius="1">
-		<monster name="Hazardous Phantom" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33908" centery="31044" centerz="8" radius="1">
-		<monster name="Hazardous Phantom" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33930" centery="31044" centerz="8" radius="1">
-		<monster name="Hazardous Phantom" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33934" centery="31044" centerz="8" radius="1">
-		<monster name="Bony Sea Devil" x="0" y="1" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33901" centery="31045" centerz="8" radius="1">
-		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33936" centery="31047" centerz="8" radius="1">
-		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33898" centery="31049" centerz="8" radius="1">
-		<monster name="Capricious Phantom" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33902" centery="31049" centerz="8" radius="1">
-		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33908" centery="31049" centerz="8" radius="1">
-		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33912" centery="31049" centerz="8" radius="1">
-		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33892" centery="31050" centerz="8" radius="1">
-		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33896" centery="31050" centerz="8" radius="1">
-		<monster name="Hazardous Phantom" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33933" centery="31050" centerz="8" radius="1">
-		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33937" centery="31050" centerz="8" radius="1">
-		<monster name="Capricious Phantom" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33940" centery="31050" centerz="8" radius="1">
-		<monster name="Turbulent Elemental" x="-1" y="1" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33930" centery="31051" centerz="8" radius="1">
-		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33930" centery="31064" centerz="8" radius="1">
-		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33941" centery="31064" centerz="8" radius="1">
-		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33937" centery="31067" centerz="8" radius="1">
-		<monster name="Hazardous Phantom" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33897" centery="31068" centerz="8" radius="1">
-		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33931" centery="31068" centerz="8" radius="1">
-		<monster name="Capricious Phantom" x="-1" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33895" centery="31069" centerz="8" radius="1">
-		<monster name="Hazardous Phantom" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33903" centery="31069" centerz="8" radius="1">
-		<monster name="Turbulent Elemental" x="1" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33941" centery="31069" centerz="8" radius="1">
-		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33928" centery="31071" centerz="8" radius="1">
-		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33923" centery="31072" centerz="8" radius="1">
-		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33933" centery="31072" centerz="8" radius="1">
-		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33897" centery="31073" centerz="8" radius="1">
-		<monster name="Capricious Phantom" x="1" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33928" centery="31075" centerz="8" radius="1">
-		<monster name="Hazardous Phantom" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33906" centery="31076" centerz="8" radius="1">
-		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33897" centery="31077" centerz="8" radius="1">
-		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33939" centery="31077" centerz="8" radius="1">
-		<monster name="Capricious Phantom" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33905" centery="31079" centerz="8" radius="1">
-		<monster name="Hazardous Phantom" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33935" centery="31080" centerz="8" radius="1">
-		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33938" centery="31081" centerz="8" radius="1">
-		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33903" centery="31082" centerz="8" radius="1">
-		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33933" centery="31083" centerz="8" radius="1">
-		<monster name="Bony Sea Devil" x="0" y="1" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33909" centery="31085" centerz="8" radius="1">
-		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33900" centery="31088" centerz="8" radius="1">
-		<monster name="Capricious Phantom" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33895" centery="31090" centerz="8" radius="1">
-		<monster name="Hazardous Phantom" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33900" centery="31092" centerz="8" radius="1">
-		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33894" centery="31095" centerz="8" radius="1">
-		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33932" centery="31098" centerz="8" radius="1">
-		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33923" centery="31099" centerz="8" radius="1">
-		<monster name="Hazardous Phantom" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33933" centery="31100" centerz="8" radius="1">
-		<monster name="Capricious Phantom" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33926" centery="31101" centerz="8" radius="1">
-		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33929" centery="31101" centerz="8" radius="1">
-		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33924" centery="31104" centerz="8" radius="1">
-		<monster name="Capricious Phantom" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33928" centery="31106" centerz="8" radius="1">
-		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33921" centery="31107" centerz="8" radius="1">
-		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33906" centery="31108" centerz="8" radius="1">
-		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33901" centery="31110" centerz="8" radius="1">
-		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33905" centery="31110" centerz="8" radius="1">
-		<monster name="Capricious Phantom" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33897" centery="31111" centerz="8" radius="1">
-		<monster name="Hazardous Phantom" x="1" y="1" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33921" centery="31111" centerz="8" radius="1">
-		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33900" centery="31114" centerz="8" radius="1">
-		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33925" centery="31114" centerz="8" radius="1">
-		<monster name="Hazardous Phantom" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33905" centery="31115" centerz="8" radius="1">
-		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33921" centery="31115" centerz="8" radius="1">
-		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33929" centery="31116" centerz="8" radius="1">
-		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33898" centery="31118" centerz="8" radius="1">
-		<monster name="Bony Sea Devil" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33905" centery="31119" centerz="8" radius="1">
-		<monster name="Hazardous Phantom" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33899" centery="31122" centerz="8" radius="1">
-		<monster name="Capricious Phantom" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33906" centery="31122" centerz="8" radius="1">
-		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33898" centery="31124" centerz="8" radius="1">
-		<monster name="Turbulent Elemental" x="0" y="0" z="8" spawntime="60" />
-	</monster>
-	<monster centerx="33889" centery="31009" centerz="9" radius="5">
-		<monster name="Bony Sea Devil" x="2" y="1" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="5" y="1" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="1" y="3" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="3" y="3" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="0" y="4" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="5" y="4" z="9" spawntime="60" />
-	</monster>
-	<monster centerx="33908" centery="31009" centerz="9" radius="5">
-		<monster name="Bony Sea Devil" x="3" y="-1" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="-2" y="1" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="1" y="1" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="-4" y="2" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="-2" y="3" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="0" y="3" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="3" y="3" z="9" spawntime="60" />
-	</monster>
-	<monster centerx="33941" centery="31009" centerz="9" radius="1">
-		<monster name="Bony Sea Devil" x="1" y="1" z="9" spawntime="60" />
-	</monster>
-	<monster centerx="33944" centery="31010" centerz="9" radius="1">
-		<monster name="Capricious Phantom" x="1" y="0" z="9" spawntime="60" />
-	</monster>
-	<monster centerx="33923" centery="31012" centerz="9" radius="1">
-		<monster name="Bony Sea Devil" x="-1" y="1" z="9" spawntime="60" />
-	</monster>
-	<monster centerx="33930" centery="31015" centerz="9" radius="5">
-		<monster name="Turbulent Elemental" x="-3" y="-3" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="0" y="-3" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="3" y="-2" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="-3" y="0" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="3" y="2" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="-4" y="3" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="-1" y="3" z="9" spawntime="60" />
-	</monster>
-	<monster centerx="33939" centery="31020" centerz="9" radius="5">
-		<monster name="Capricious Phantom" x="1" y="-3" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="4" y="-2" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="-3" y="1" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="3" y="1" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="-2" y="3" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="2" y="4" z="9" spawntime="60" />
-	</monster>
-	<monster centerx="33896" centery="31027" centerz="9" radius="5">
-		<monster name="Bony Sea Devil" x="1" y="-2" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="4" y="-2" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="-4" y="-1" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="-1" y="1" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="3" y="2" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="1" y="4" z="9" spawntime="60" />
-	</monster>
-	<monster centerx="33919" centery="31027" centerz="9" radius="5">
-		<monster name="Turbulent Elemental" x="0" y="-4" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="2" y="-4" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="-2" y="-2" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="3" y="-1" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="-2" y="1" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="2" y="2" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="-3" y="3" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="0" y="4" z="9" spawntime="60" />
-	</monster>
-	<monster centerx="33891" centery="31028" centerz="9" radius="1">
-		<monster name="Bony Sea Devil" x="-1" y="1" z="9" spawntime="60" />
-	</monster>
-	<monster centerx="33940" centery="31031" centerz="9" radius="5">
-		<monster name="Capricious Phantom" x="3" y="-3" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="-3" y="-1" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="-1" y="-1" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="3" y="0" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="-1" y="2" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="3" y="2" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="-4" y="3" z="9" spawntime="60" />
-	</monster>
-	<monster centerx="33891" centery="31038" centerz="9" radius="1">
-		<monster name="Turbulent Elemental" x="0" y="1" z="9" spawntime="60" />
-	</monster>
-	<monster centerx="33911" centery="31038" centerz="9" radius="1">
-		<monster name="Turbulent Elemental" x="0" y="0" z="9" spawntime="60" />
-	</monster>
-	<monster centerx="33933" centery="31044" centerz="9" radius="5">
-		<monster name="Turbulent Elemental" x="0" y="-3" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="2" y="-3" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="-3" y="-2" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="1" y="1" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="-2" y="2" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="-4" y="3" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="3" y="3" z="9" spawntime="60" />
-	</monster>
-	<monster centerx="33945" centery="31044" centerz="9" radius="1">
-		<monster name="Bony Sea Devil" x="0" y="0" z="9" spawntime="60" />
-	</monster>
-	<monster centerx="33891" centery="31045" centerz="9" radius="5">
-		<monster name="Capricious Phantom" x="0" y="-3" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="-1" y="-1" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="1" y="0" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="-1" y="2" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="1" y="2" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="-3" y="4" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="1" y="4" z="9" spawntime="60" />
-	</monster>
-	<monster centerx="33910" centery="31045" centerz="9" radius="5">
-		<monster name="Bony Sea Devil" x="-3" y="-3" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="0" y="-2" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="3" y="-2" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="-2" y="0" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="1" y="3" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="-1" y="5" z="9" spawntime="60" />
-	</monster>
-	<monster centerx="33919" centery="31047" centerz="9" radius="1">
-		<monster name="Bony Sea Devil" x="0" y="0" z="9" spawntime="60" />
-	</monster>
-	<monster centerx="33930" centery="31057" centerz="9" radius="5">
-		<monster name="Capricious Phantom" x="-1" y="-4" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="2" y="-3" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="4" y="-3" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="-3" y="-1" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="5" y="-1" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="3" y="1" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="-1" y="2" z="9" spawntime="60" />
-	</monster>
-	<monster centerx="33910" centery="31064" centerz="9" radius="5">
-		<monster name="Bony Sea Devil" x="-2" y="-3" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="3" y="-3" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="-2" y="1" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="4" y="1" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="0" y="3" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="-3" y="4" z="9" spawntime="60" />
-	</monster>
-	<monster centerx="33889" centery="31066" centerz="9" radius="1">
-		<monster name="Bony Sea Devil" x="1" y="1" z="9" spawntime="60" />
-	</monster>
-	<monster centerx="33930" centery="31066" centerz="9" radius="5">
-		<monster name="Bony Sea Devil" x="0" y="-3" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="-3" y="-1" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="2" y="-1" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="3" y="1" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="-3" y="2" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="-1" y="4" z="9" spawntime="60" />
-	</monster>
-	<monster centerx="33895" centery="31067" centerz="9" radius="5">
-		<monster name="Turbulent Elemental" x="-1" y="-3" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="3" y="-3" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="-2" y="-2" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="2" y="0" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="-2" y="3" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="1" y="3" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="3" y="3" z="9" spawntime="60" />
-	</monster>
-	<monster centerx="33889" centery="31071" centerz="9" radius="1">
-		<monster name="Turbulent Elemental" x="0" y="0" z="9" spawntime="60" />
-	</monster>
-	<monster centerx="33945" centery="31073" centerz="9" radius="1">
-		<monster name="Bony Sea Devil" x="1" y="-1" z="9" spawntime="60" />
-	</monster>
-	<monster centerx="33906" centery="31077" centerz="9" radius="5">
-		<monster name="Bony Sea Devil" x="2" y="-3" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="-1" y="-2" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="-4" y="0" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="-1" y="1" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="3" y="3" z="9" spawntime="60" />
-	</monster>
-	<monster centerx="33895" centery="31078" centerz="9" radius="5">
-		<monster name="Capricious Phantom" x="-2" y="-2" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="2" y="-2" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="3" y="1" z="9" spawntime="60" />
-	</monster>
-	<monster centerx="33937" centery="31078" centerz="9" radius="5">
-		<monster name="Turbulent Elemental" x="-3" y="-3" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="-1" y="-3" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="3" y="-3" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="-3" y="0" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="3" y="0" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="3" y="3" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="-3" y="4" z="9" spawntime="60" />
-	</monster>
-	<monster centerx="33921" centery="31083" centerz="9" radius="5">
-		<monster name="Turbulent Elemental" x="-1" y="-4" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="-3" y="-3" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="2" y="-2" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="4" y="0" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="-3" y="1" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="2" y="2" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="0" y="4" z="9" spawntime="60" />
-	</monster>
-	<monster centerx="33889" centery="31084" centerz="9" radius="1">
-		<monster name="Capricious Phantom" x="0" y="1" z="9" spawntime="60" />
-	</monster>
-	<monster centerx="33895" centery="31089" centerz="9" radius="5">
-		<monster name="Turbulent Elemental" x="3" y="-4" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="0" y="-3" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="-3" y="-2" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="2" y="-2" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="-4" y="1" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="2" y="2" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="-1" y="3" z="9" spawntime="60" />
-	</monster>
-	<monster centerx="33941" centery="31093" centerz="9" radius="5">
-		<monster name="Turbulent Elemental" x="4" y="-4" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="-3" y="-3" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="0" y="-2" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="2" y="-2" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="-2" y="0" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="3" y="3" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="-2" y="4" z="9" spawntime="60" />
-	</monster>
-	<monster centerx="33908" centery="31095" centerz="9" radius="5">
-		<monster name="Turbulent Elemental" x="4" y="-4" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="1" y="-3" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="-3" y="-2" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="-1" y="1" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="4" y="1" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="-1" y="4" z="9" spawntime="60" />
-	</monster>
-	<monster centerx="33890" centery="31098" centerz="9" radius="1">
-		<monster name="Bony Sea Devil" x="0" y="1" z="9" spawntime="60" />
-	</monster>
-	<monster centerx="33922" centery="31100" centerz="9" radius="5">
-		<monster name="Capricious Phantom" x="-2" y="-3" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="2" y="-3" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="-4" y="-2" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="3" y="0" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="-2" y="2" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="3" y="3" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="-1" y="4" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="1" y="4" z="9" spawntime="60" />
-	</monster>
-	<monster centerx="33897" centery="31109" centerz="9" radius="5">
-		<monster name="Bony Sea Devil" x="-4" y="-3" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="0" y="-3" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="4" y="-3" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="2" y="0" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="-3" y="4" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="-1" y="4" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="3" y="5" z="9" spawntime="60" />
-	</monster>
-	<monster centerx="33926" centery="31114" centerz="9" radius="5">
-		<monster name="Turbulent Elemental" x="0" y="-4" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="-3" y="-2" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="1" y="-2" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="3" y="-2" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="-2" y="0" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="4" y="2" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="-2" y="3" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="1" y="3" z="9" spawntime="60" />
-	</monster>
-	<monster centerx="33893" centery="31117" centerz="9" radius="5">
-		<monster name="Turbulent Elemental" x="-4" y="-3" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="-4" y="0" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="1" y="1" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="-4" y="2" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="-2" y="3" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="-4" y="4" z="9" spawntime="60" />
-	</monster>
-	<monster centerx="33904" centery="31120" centerz="9" radius="5">
-		<monster name="Capricious Phantom" x="-1" y="-4" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="3" y="-4" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="0" y="-1" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="2" y="-1" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="-3" y="1" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="0" y="3" z="9" spawntime="60" />
-	</monster>
-	<monster centerx="33941" centery="31123" centerz="9" radius="5">
-		<monster name="Capricious Phantom" x="0" y="-3" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="2" y="-3" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="-3" y="-2" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="3" y="-1" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="-3" y="1" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="3" y="1" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="0" y="4" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="3" y="4" z="9" spawntime="60" />
-	</monster>
-	<monster centerx="33916" centery="31125" centerz="9" radius="5">
-		<monster name="Turbulent Elemental" x="-4" y="-3" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="3" y="-2" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="5" y="0" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="-1" y="1" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="3" y="3" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="-4" y="4" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="1" y="4" z="9" spawntime="60" />
-	</monster>
-	<monster centerx="33896" centery="31128" centerz="9" radius="5">
-		<monster name="Turbulent Elemental" x="-4" y="-2" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="-2" y="-1" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="-1" y="-1" z="9" spawntime="60" />
-		<monster name="Capricious Phantom" x="-1" y="1" z="9" spawntime="60" />
-		<monster name="Bony Sea Devil" x="4" y="1" z="9" spawntime="60" />
-		<monster name="Turbulent Elemental" x="-4" y="2" z="9" spawntime="60" />
-	</monster>
-</monsters>
diff --git a/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-npc.xml b/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-npc.xml
deleted file mode 100644
index af7984e2faf..00000000000
--- a/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-npc.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0"?>
-<npcs />
diff --git a/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-zones.xml b/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-zones.xml
deleted file mode 100644
index a9224bd3c2d..00000000000
--- a/data-otservbr-global/world/quest/soul_war/ebb_and_flow/ebb-flow-zones.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0"?>
-<zones />

From 5a0f4a7e356f62738830ebf801b2cdae3bae382b Mon Sep 17 00:00:00 2001
From: Eduardo Dantas <eduardo.dantas@hotmail.com.br>
Date: Tue, 10 Sep 2024 09:30:28 -0300
Subject: [PATCH 50/60] fix: remove weeping soul corpses on boss spawn

---
 data-otservbr-global/lib/quests/soul_war.lua | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/data-otservbr-global/lib/quests/soul_war.lua b/data-otservbr-global/lib/quests/soul_war.lua
index 0c92ddc0c7d..c739d181764 100644
--- a/data-otservbr-global/lib/quests/soul_war.lua
+++ b/data-otservbr-global/lib/quests/soul_war.lua
@@ -267,6 +267,22 @@ SoulWarQuest = {
 				from = Position(33734, 31624, 14),
 				to = Position(33751, 31640, 14),
 			},
+			onUseExtra = function(player)
+				local zone = Zone("boss.goshnar's-spite")
+				if zone then
+					local positions = zone:getPositions()
+					for _, pos in ipairs(positions) do
+						local tile = Tile(pos)
+						if tile then
+							local item = tile:getItemById(SoulWarQuest.weepingSoulCorpseId)
+							if item then
+								logger.debug("Weeping Soul Corpse removed from position: {}", pos)
+								item:remove()
+							end
+						end
+					end
+				end
+			end,
 			exit = Position(33621, 31427, 10),
 			timeToFightAgain = 20 * 60 * 60, -- 20 hours
 		},

From 419579832f063cdf4d7213dae019f53886bae982 Mon Sep 17 00:00:00 2001
From: Eduardo Dantas <eduardo.dantas@hotmail.com.br>
Date: Tue, 10 Sep 2024 09:58:36 -0300
Subject: [PATCH 51/60] fix: remove outfit massive fire elemental

---
 data-otservbr-global/lib/quests/soul_war.lua | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/data-otservbr-global/lib/quests/soul_war.lua b/data-otservbr-global/lib/quests/soul_war.lua
index c739d181764..25c6981df6b 100644
--- a/data-otservbr-global/lib/quests/soul_war.lua
+++ b/data-otservbr-global/lib/quests/soul_war.lua
@@ -1503,6 +1503,8 @@ function Zone:getRandomPlayer()
 	return players[randomIndex]
 end
 
+local conditionOutfit = Condition(CONDITION_OUTFIT)
+
 local function delayedCastSpell(cid, var, combat, targetId)
 	local creature = Creature(cid)
 	if not creature then
@@ -1512,6 +1514,7 @@ local function delayedCastSpell(cid, var, combat, targetId)
 	local target = Player(targetId)
 	if target then
 		combat:execute(creature, positionToVariant(target:getPosition()))
+		target:removeCondition(conditionOutfit)
 	end
 end
 
@@ -1532,10 +1535,10 @@ function Creature:applyZoneEffect(var, combat, zoneName)
 		return true
 	end
 
-	local condition = Condition(CONDITION_OUTFIT)
-	condition:setTicks(outfitConfig.time)
-	condition:setOutfit(outfitConfig.outfit)
-	target:addCondition(condition)
+	
+	conditionOutfit:setTicks(outfitConfig.time)
+	conditionOutfit:setOutfit(outfitConfig.outfit)
+	target:addCondition(conditionOutfit)
 	target:getPosition():sendMagicEffect(CONST_ME_MAGIC_BLUE)
 
 	addEvent(delayedCastSpell, SoulWarQuest.goshnarsCrueltyWaveInterval * 1000, self:getId(), var, combat, target:getId())

From a231525e940027b87abed11ab18455aaad65c972 Mon Sep 17 00:00:00 2001
From: Eduardo Dantas <eduardo.dantas@hotmail.com.br>
Date: Tue, 10 Sep 2024 09:58:44 -0300
Subject: [PATCH 52/60] fix spawns

---
 .../scripts/quests/soul_war/soul_war_mechanics.lua       | 2 +-
 data-otservbr-global/world/otservbr-monster.xml          | 9 +++++++++
 2 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/data-otservbr-global/scripts/quests/soul_war/soul_war_mechanics.lua b/data-otservbr-global/scripts/quests/soul_war/soul_war_mechanics.lua
index f326455fdd9..8f91f72c0d2 100644
--- a/data-otservbr-global/scripts/quests/soul_war/soul_war_mechanics.lua
+++ b/data-otservbr-global/scripts/quests/soul_war/soul_war_mechanics.lua
@@ -972,7 +972,7 @@ function cleansedSanity.onUse(player, item, fromPosition, target, toPosition, is
 		SoulWarQuest.kvSoulWar:set("cleansed-sanity-action", currentTime + timeToIncreaseDefense)
 		target:getPosition():sendMagicEffect(CONST_ME_DRAWBLOOD)
 		item:remove()
-		player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Use the item again within " .. timeToIncreaseDefense .. " seconds, or the monster's defense will increase by 2 every " .. timeToIncreaseDefense .. " seconds.")
+		player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Use the item again within " .. timeToIncreaseDefense .. " seconds, or the monster's defense will increase every " .. timeToIncreaseDefense .. " seconds.")
 		local boss = Creature("Goshnar's Megalomania")
 		if boss then
 			local mtype = boss:getType()
diff --git a/data-otservbr-global/world/otservbr-monster.xml b/data-otservbr-global/world/otservbr-monster.xml
index 308d9631af9..529c6b470ac 100644
--- a/data-otservbr-global/world/otservbr-monster.xml
+++ b/data-otservbr-global/world/otservbr-monster.xml
@@ -34097,6 +34097,9 @@
 	<monster centerx="32552" centery="31862" centerz="7" radius="1">
 		<monster name="Deer" x="-1" y="0" z="7" spawntime="90" />
 	</monster>
+	<monster centerx="33855" centery="31862" centerz="7" radius="1">
+		<monster name="Dreadful Harvester" x="0" y="0" z="7" spawntime="60" />
+	</monster>
 	<monster centerx="32641" centery="31863" centerz="7" radius="2">
 		<monster name="Deer" x="0" y="2" z="7" spawntime="90" />
 	</monster>
@@ -34129,6 +34132,9 @@
 	<monster centerx="32575" centery="31866" centerz="7" radius="1">
 		<monster name="Deer" x="1" y="-1" z="7" spawntime="90" />
 	</monster>
+	<monster centerx="33855" centery="31866" centerz="7" radius="1">
+		<monster name="Mean Maw" x="0" y="0" z="7" spawntime="10" />
+	</monster>
 	<monster centerx="32042" centery="31867" centerz="7" radius="3">
 		<monster name="Dawnfly" x="1" y="2" z="7" spawntime="90" />
 		<monster name="Troll-Trained Salamander" x="3" y="2" z="7" spawntime="90" />
@@ -34214,6 +34220,9 @@
 		<monster name="Deer" x="1" y="-2" z="7" spawntime="90" />
 		<monster name="Deer" x="0" y="2" z="7" spawntime="90" />
 	</monster>
+	<monster centerx="33851" centery="31870" centerz="7" radius="1">
+		<monster name="Poor Soul" x="0" y="0" z="7" spawntime="10" />
+	</monster>
 	<monster centerx="32088" centery="31871" centerz="7" radius="1">
 		<monster name="Deer" x="0" y="0" z="7" spawntime="90" />
 	</monster>

From 5d9e835937119373e13ae656cb0847d4647f81c9 Mon Sep 17 00:00:00 2001
From: GitHub Actions <github-actions[bot]@users.noreply.github.com>
Date: Tue, 10 Sep 2024 12:59:31 +0000
Subject: [PATCH 53/60] fix: stop mechanics on bosses death

---
 data-otservbr-global/lib/quests/soul_war.lua  | 18 ++++++++++++++--
 .../quests/soul_war/goshnars_cruelty.lua      |  9 +++++++-
 .../quests/soul_war/goshnars_hatred.lua       | 11 +++++++++-
 .../quests/soul_war/soul_war_mechanics.lua    | 11 ++--------
 .../world/otservbr-monster.xml                | 21 +++++++++++++++++++
 5 files changed, 57 insertions(+), 13 deletions(-)

diff --git a/data-otservbr-global/lib/quests/soul_war.lua b/data-otservbr-global/lib/quests/soul_war.lua
index 25c6981df6b..c6cc517d48a 100644
--- a/data-otservbr-global/lib/quests/soul_war.lua
+++ b/data-otservbr-global/lib/quests/soul_war.lua
@@ -436,6 +436,13 @@ SoulWarQuest = {
 		{ 45, "Blaze of Burning Hatred" },
 	},
 
+	burningHatredMonsters = {
+		"Ashes of Burning Hatred",
+		"Spark of Burning Hatred",
+		"Flame of Burning Hatred",
+		"Blaze of Burning Hatred",
+	},
+
 	requiredCountPerApparition = 25,
 
 	-- Ebb and flow
@@ -1293,7 +1300,7 @@ end
 
 function Monster:increaseHatredDamageMultiplier(multiplierCount)
 	local attackMultiplier = self:getHatredDamageMultiplier()
-	self:getSoulWarKV():set("burning-hatred-empowered", attackMultiplier + multiplierCount or 10)
+	self:getSoulWarKV():set("burning-hatred-empowered", attackMultiplier + multiplierCount)
 end
 
 function Monster:resetHatredDamageMultiplier()
@@ -1346,6 +1353,12 @@ function Monster:onThinkGoshnarTormentCounter(interval, maxLimit, intervalBetwee
 	for i = 1, #spectators do
 		local player = spectators[i]
 		local tormentCounter = player:getGoshnarSymbolTormentCounter()
+		local goshnarsHatred = Creature("Goshnar's Hatred")
+		if not goshnarsHatred then
+			player:resetGoshnarSymbolTormentCounter()
+			goto continue
+		end
+
 		if tormentCounter <= maxLimit then
 			player:increaseGoshnarSymbolTormentCounter(maxLimit)
 			logger.trace("Player {} has {} damage counter", player:getName(), tormentCounter)
@@ -1373,6 +1386,8 @@ function Monster:onThinkGoshnarTormentCounter(interval, maxLimit, intervalBetwee
 		elseif tormentCounter == 36 then
 			player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "The dread's torment is now lethal!")
 		end
+
+		::continue::
 	end
 end
 
@@ -1535,7 +1550,6 @@ function Creature:applyZoneEffect(var, combat, zoneName)
 		return true
 	end
 
-	
 	conditionOutfit:setTicks(outfitConfig.time)
 	conditionOutfit:setOutfit(outfitConfig.outfit)
 	target:addCondition(conditionOutfit)
diff --git a/data-otservbr-global/monster/quests/soul_war/goshnars_cruelty.lua b/data-otservbr-global/monster/quests/soul_war/goshnars_cruelty.lua
index 300a47184e3..f42d09e89dd 100644
--- a/data-otservbr-global/monster/quests/soul_war/goshnars_cruelty.lua
+++ b/data-otservbr-global/monster/quests/soul_war/goshnars_cruelty.lua
@@ -154,7 +154,14 @@ mType.onSpawn = function(monsterCallback)
 	firstTime = 0
 end
 
-mType.onDisappear = function(monster, creature) end
+mType.onDisappear = function(monster, creature)
+	if creature:getName() == "Goshnar's Cruelty" then
+		local eyeCreature = Creature("A Greedy Eye")
+		if eyeCreature then
+			eyeCreature:remove()
+		end
+	end
+end
 
 mType.onMove = function(monster, creature, fromPosition, toPosition) end
 
diff --git a/data-otservbr-global/monster/quests/soul_war/goshnars_hatred.lua b/data-otservbr-global/monster/quests/soul_war/goshnars_hatred.lua
index 023dadbd2d4..89f00c899eb 100644
--- a/data-otservbr-global/monster/quests/soul_war/goshnars_hatred.lua
+++ b/data-otservbr-global/monster/quests/soul_war/goshnars_hatred.lua
@@ -145,7 +145,16 @@ mType.onSpawn = function(monster)
 	monster:resetHatredDamageMultiplier()
 end
 
-mType.onDisappear = function(monster, creature) end
+mType.onDisappear = function(monster, creature)
+	if creature:getName() == "Goshnar's Hatred" then
+		for _, monsterName in pairs(SoulWarQuest.burningHatredMonsters) do
+			local ashesCreature = Creature(monsterName)
+			if ashesCreature then
+				ashesCreature:remove()
+			end
+		end
+	end
+end
 
 mType.onMove = function(monster, creature, fromPosition, toPosition) end
 
diff --git a/data-otservbr-global/scripts/quests/soul_war/soul_war_mechanics.lua b/data-otservbr-global/scripts/quests/soul_war/soul_war_mechanics.lua
index 8f91f72c0d2..5f8fd9276fe 100644
--- a/data-otservbr-global/scripts/quests/soul_war/soul_war_mechanics.lua
+++ b/data-otservbr-global/scripts/quests/soul_war/soul_war_mechanics.lua
@@ -552,13 +552,6 @@ end
 goshnarsHatredAccess:position(SoulWarQuest.goshnarsHatredAccessPosition.from)
 goshnarsHatredAccess:register()
 
-local burningHatredMonsters = {
-	"Ashes of Burning Hatred",
-	"Spark of Burning Hatred",
-	"Flame of Burning Hatred",
-	"Blaze of Burning Hatred",
-}
-
 local goshnarsHatredSorrow = Action()
 
 function goshnarsHatredSorrow.onUse(player, item, fromPosition, target, toPosition, isHotkey)
@@ -566,7 +559,7 @@ function goshnarsHatredSorrow.onUse(player, item, fromPosition, target, toPositi
 		return
 	end
 
-	if not table.contains(burningHatredMonsters, target:getName()) then
+	if not table.contains(SoulWarQuest.burningHatredMonsters, target:getName()) then
 		logger.error("Player {} tried to use the item on a non-burning hatred monster.", player:getName())
 		return
 	end
@@ -610,7 +603,7 @@ function burningChangeForm.onThink(creature)
 				local boss = Creature("Goshnar's Hatred")
 				if boss then
 					logger.debug("Increasing hatred damage multiplier.")
-					boss:increaseHatredDamageMultiplier()
+					boss:increaseHatredDamageMultiplier(10)
 				end
 				logger.debug("Beginning of the burning transformation cycle.")
 			end
diff --git a/data-otservbr-global/world/otservbr-monster.xml b/data-otservbr-global/world/otservbr-monster.xml
index 529c6b470ac..60450b7142b 100644
--- a/data-otservbr-global/world/otservbr-monster.xml
+++ b/data-otservbr-global/world/otservbr-monster.xml
@@ -162010,6 +162010,9 @@
 	<monster centerx="32505" centery="31594" centerz="14" radius="3">
 		<monster name="Warlock" x="0" y="-1" z="14" spawntime="90" />
 	</monster>
+	<monster centerx="33739" centery="31595" centerz="14" radius="1">
+		<monster name="Dreadful Harvester" x="0" y="0" z="14" spawntime="10" />
+	</monster>
 	<monster centerx="33349" centery="31596" centerz="14" radius="7">
 		<monster name="Dark Torturer" x="0" y="-7" z="14" spawntime="90" />
 		<monster name="Betrayed Wraith" x="5" y="-5" z="14" spawntime="90" />
@@ -162036,6 +162039,9 @@
 		<monster name="Dark Torturer" x="4" y="5" z="14" spawntime="90" />
 		<monster name="Lost Soul" x="0" y="6" z="14" spawntime="90" />
 	</monster>
+	<monster centerx="33748" centery="31596" centerz="14" radius="1">
+		<monster name="Dreadful Harvester" x="0" y="0" z="14" spawntime="10" />
+	</monster>
 	<monster centerx="32805" centery="31598" centerz="14" radius="1">
 		<monster name="Skeleton" x="1" y="0" z="14" spawntime="90" />
 	</monster>
@@ -162045,6 +162051,12 @@
 	<monster centerx="33161" centery="31598" centerz="14" radius="1">
 		<monster name="Dark Magician" x="0" y="1" z="14" spawntime="90" />
 	</monster>
+	<monster centerx="33738" centery="31599" centerz="14" radius="1">
+		<monster name="Symbol of Hatred" x="0" y="0" z="14" spawntime="10" />
+	</monster>
+	<monster centerx="33748" centery="31599" centerz="14" radius="1">
+		<monster name="Symbol of Hatred" x="0" y="0" z="14" spawntime="10" />
+	</monster>
 	<monster centerx="32808" centery="31600" centerz="14" radius="1">
 		<monster name="Ghoul" x="1" y="0" z="14" spawntime="90" />
 	</monster>
@@ -162059,6 +162071,9 @@
 	<monster centerx="33140" centery="31601" centerz="14" radius="1">
 		<monster name="Monk" x="1" y="-1" z="14" spawntime="90" />
 	</monster>
+	<monster centerx="33745" centery="31601" centerz="14" radius="1">
+		<monster name="Hateful Soul" x="1" y="0" z="14" spawntime="10" />
+	</monster>
 	<monster centerx="32423" centery="31602" centerz="14" radius="3">
 		<monster name="Warlock" x="-1" y="-3" z="14" spawntime="90" />
 		<monster name="Elf Arcanist" x="1" y="1" z="14" spawntime="90" />
@@ -162071,6 +162086,9 @@
 		<monster name="Demon Skeleton" x="1" y="0" z="14" spawntime="90" />
 		<monster name="Demon Skeleton" x="1" y="1" z="14" spawntime="90" />
 	</monster>
+	<monster centerx="33748" centery="31602" centerz="14" radius="1">
+		<monster name="Dreadful Harvester" x="0" y="0" z="14" spawntime="10" />
+	</monster>
 	<monster centerx="33156" centery="31603" centerz="14" radius="1">
 		<monster name="Stone Golem" x="1" y="-1" z="14" spawntime="90" />
 	</monster>
@@ -162092,6 +162110,9 @@
 		<monster name="Fire Elemental" x="0" y="4" z="14" spawntime="90" />
 		<monster name="Fire Elemental" x="4" y="4" z="14" spawntime="90" />
 	</monster>
+	<monster centerx="33743" centery="31603" centerz="14" radius="1">
+		<monster name="Hateful Soul" x="0" y="0" z="14" spawntime="10" />
+	</monster>
 	<monster centerx="33137" centery="31604" centerz="14" radius="1">
 		<monster name="Monk" x="0" y="-1" z="14" spawntime="90" />
 	</monster>

From 84e76484b144950f616c64c76965e370f156e638 Mon Sep 17 00:00:00 2001
From: Eduardo Dantas <eduardo.dantas@hotmail.com.br>
Date: Tue, 10 Sep 2024 11:39:31 -0300
Subject: [PATCH 54/60] fix: some goshnar's megalomania mechanics

---
 data-otservbr-global/lib/quests/soul_war.lua  | 19 ++++++++++++++++++-
 .../soul_war/goshnar's_megalomania_blue.lua   |  4 ++++
 .../soul_war/goshnar's_megalomania_green.lua  |  4 ++++
 .../burning_hatred/symbol_of_hatred.lua       |  2 +-
 .../quests/soul_war/soul_war_mechanics.lua    |  3 +--
 .../world/otservbr-monster.xml                | 13 +++++++++++++
 6 files changed, 41 insertions(+), 4 deletions(-)

diff --git a/data-otservbr-global/lib/quests/soul_war.lua b/data-otservbr-global/lib/quests/soul_war.lua
index c6cc517d48a..e21c23900cc 100644
--- a/data-otservbr-global/lib/quests/soul_war.lua
+++ b/data-otservbr-global/lib/quests/soul_war.lua
@@ -1353,7 +1353,7 @@ function Monster:onThinkGoshnarTormentCounter(interval, maxLimit, intervalBetwee
 	for i = 1, #spectators do
 		local player = spectators[i]
 		local tormentCounter = player:getGoshnarSymbolTormentCounter()
-		local goshnarsHatred = Creature("Goshnar's Hatred")
+		local goshnarsHatred = Creature(bossName or "Goshnar's Megalomania")
 		if not goshnarsHatred then
 			player:resetGoshnarSymbolTormentCounter()
 			goto continue
@@ -1432,6 +1432,23 @@ function Monster:goshnarsDefenseIncrease(kvName)
 	end
 end
 
+function Monster:removeGoshnarsMegalomaniaMonsters(monsterName)
+	if self:getName() ~= "Goshnar's Megalomania" then
+		return
+	end
+
+	local zone = Zone.getByName("boss.goshnar's-megalomania-purple")
+	if zone then
+		logger.info("Removing all monsters from Goshnar's Megalomania zone")
+		local creatures = zone:getCreatures()
+		for _, creature in ipairs(creatures) do
+			if creature:getMonster() then
+				creature:remove()
+			end
+		end
+	end
+end
+
 function Player:getSoulWarZoneMonster()
 	local zoneMonsterName = nil
 	for zoneName, monsterName in pairs(SoulWarQuest.areaZones.monsters) do
diff --git a/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_blue.lua b/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_blue.lua
index 232018a285e..2cd7f55239c 100644
--- a/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_blue.lua
+++ b/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_blue.lua
@@ -144,4 +144,8 @@ mType.onThink = function(monsterCallback, interval)
 	monsterCallback:goshnarsDefenseIncrease("cleansed-sanity-action")
 end
 
+mType.onDisappear = function(monster, creature)
+	creature:removeGoshnarsMegalomaniaMonsters()
+end
+
 mType:register(monster)
diff --git a/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_green.lua b/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_green.lua
index 08fed30648c..02067499b27 100644
--- a/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_green.lua
+++ b/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_green.lua
@@ -155,4 +155,8 @@ mType.onThink = function(monsterCallback, interval)
 	monsterCallback:goshnarsDefenseIncrease("cleansed-sanity-action")
 end
 
+mType.onDisappear = function(monster, creature)
+	creature:removeGoshnarsMegalomaniaMonsters()
+end
+
 mType:register(monster)
diff --git a/data-otservbr-global/monster/quests/soul_war/normal_monsters/burning_hatred/symbol_of_hatred.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/burning_hatred/symbol_of_hatred.lua
index 9df86b773a9..76d403fab1a 100644
--- a/data-otservbr-global/monster/quests/soul_war/normal_monsters/burning_hatred/symbol_of_hatred.lua
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/burning_hatred/symbol_of_hatred.lua
@@ -78,7 +78,7 @@ monster.immunities = {
 local intervalBetweenExecutions = 3000
 
 mType.onThink = function(monsterCallback, interval)
-	monsterCallback:onThinkGoshnarTormentCounter(interval, 30, intervalBetweenExecutions, SoulWarQuest.levers.goshnarsHatred.boss.position)
+	monsterCallback:onThinkGoshnarTormentCounter(interval, 30, intervalBetweenExecutions, SoulWarQuest.levers.goshnarsHatred.boss.position, "Goshnar's Hatred")
 end
 
 mType:register(monster)
diff --git a/data-otservbr-global/scripts/quests/soul_war/soul_war_mechanics.lua b/data-otservbr-global/scripts/quests/soul_war/soul_war_mechanics.lua
index 5f8fd9276fe..6a60195277a 100644
--- a/data-otservbr-global/scripts/quests/soul_war/soul_war_mechanics.lua
+++ b/data-otservbr-global/scripts/quests/soul_war/soul_war_mechanics.lua
@@ -922,11 +922,10 @@ local madnessReduce = MoveEvent()
 function madnessReduce.onStepIn(creature, item, position, fromPosition)
 	local player = creature:getPlayer()
 	item:getPosition():sendMagicEffect(CONST_ME_HOLYAREA)
-
+	item:remove()
 	if player and player:getGoshnarSymbolTormentCounter() > 0 then
 		player:resetGoshnarSymbolTormentCounter()
 		player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "The ooze calms your dread but leaves you vulnerable to phantasmal attacks!")
-		item:remove()
 		return true
 	end
 
diff --git a/data-otservbr-global/world/otservbr-monster.xml b/data-otservbr-global/world/otservbr-monster.xml
index 60450b7142b..41bb280696e 100644
--- a/data-otservbr-global/world/otservbr-monster.xml
+++ b/data-otservbr-global/world/otservbr-monster.xml
@@ -162201,6 +162201,10 @@
 	<monster centerx="32795" centery="31631" centerz="14" radius="1">
 		<monster name="Ghoul" x="1" y="0" z="14" spawntime="90" />
 	</monster>
+	<monster centerx="33710" centery="31631" centerz="14" radius="1">
+		<monster name="Dreadful Harvester" x="-1" y="-1" z="14" spawntime="10" />
+		<monster name="Dreadful Harvester" x="0" y="0" z="14" spawntime="10" />
+	</monster>
 	<monster centerx="33744" centery="31631" centerz="14" radius="1">
 		<monster name="Dreadful Harvester" x="0" y="0" z="14" spawntime="10" />
 	</monster>
@@ -162224,6 +162228,12 @@
 		<monster name="Demon Skeleton" x="-1" y="1" z="14" spawntime="90" />
 		<monster name="Skeleton" x="1" y="1" z="14" spawntime="90" />
 	</monster>
+	<monster centerx="33704" centery="31634" centerz="14" radius="1">
+		<monster name="Necromantic Focus" x="0" y="0" z="14" spawntime="10" />
+	</monster>
+	<monster centerx="33716" centery="31634" centerz="14" radius="1">
+		<monster name="Necromantic Focus" x="0" y="0" z="14" spawntime="10" />
+	</monster>
 	<monster centerx="33748" centery="31634" centerz="14" radius="1">
 		<monster name="Weeping Soul" x="0" y="0" z="14" spawntime="10" />
 	</monster>
@@ -162236,6 +162246,9 @@
 	<monster centerx="32799" centery="31635" centerz="14" radius="1">
 		<monster name="Ghoul" x="1" y="0" z="14" spawntime="90" />
 	</monster>
+	<monster centerx="33711" centery="31635" centerz="14" radius="1">
+		<monster name="Lesser Splinter of Madness" x="1" y="0" z="14" spawntime="10" />
+	</monster>
 	<monster centerx="33498" centery="31636" centerz="14" radius="3">
 		<monster name="Shark" x="0" y="-3" z="14" spawntime="60" />
 		<monster name="Sea Serpent" x="1" y="-3" z="14" spawntime="60" />

From 5b403e221aa1534bd7b4c56a5154eb1a39481c46 Mon Sep 17 00:00:00 2001
From: Eduardo Dantas <eduardo.dantas@hotmail.com.br>
Date: Tue, 10 Sep 2024 11:44:05 -0300
Subject: [PATCH 55/60] fix: zone param

---
 data-otservbr-global/lib/quests/soul_war.lua                  | 4 +---
 .../monster/quests/soul_war/goshnar's_megalomania_blue.lua    | 2 +-
 .../monster/quests/soul_war/goshnar's_megalomania_green.lua   | 2 +-
 3 files changed, 3 insertions(+), 5 deletions(-)

diff --git a/data-otservbr-global/lib/quests/soul_war.lua b/data-otservbr-global/lib/quests/soul_war.lua
index e21c23900cc..1cacf4de08f 100644
--- a/data-otservbr-global/lib/quests/soul_war.lua
+++ b/data-otservbr-global/lib/quests/soul_war.lua
@@ -1432,14 +1432,12 @@ function Monster:goshnarsDefenseIncrease(kvName)
 	end
 end
 
-function Monster:removeGoshnarsMegalomaniaMonsters(monsterName)
+function Monster:removeGoshnarsMegalomaniaMonsters(zone)
 	if self:getName() ~= "Goshnar's Megalomania" then
 		return
 	end
 
-	local zone = Zone.getByName("boss.goshnar's-megalomania-purple")
 	if zone then
-		logger.info("Removing all monsters from Goshnar's Megalomania zone")
 		local creatures = zone:getCreatures()
 		for _, creature in ipairs(creatures) do
 			if creature:getMonster() then
diff --git a/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_blue.lua b/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_blue.lua
index 2cd7f55239c..93ecb6c4230 100644
--- a/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_blue.lua
+++ b/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_blue.lua
@@ -145,7 +145,7 @@ mType.onThink = function(monsterCallback, interval)
 end
 
 mType.onDisappear = function(monster, creature)
-	creature:removeGoshnarsMegalomaniaMonsters()
+	creature:removeGoshnarsMegalomaniaMonsters(zone)
 end
 
 mType:register(monster)
diff --git a/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_green.lua b/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_green.lua
index 02067499b27..6c7b16bd707 100644
--- a/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_green.lua
+++ b/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_green.lua
@@ -156,7 +156,7 @@ mType.onThink = function(monsterCallback, interval)
 end
 
 mType.onDisappear = function(monster, creature)
-	creature:removeGoshnarsMegalomaniaMonsters()
+	creature:removeGoshnarsMegalomaniaMonsters(zone)
 end
 
 mType:register(monster)

From 89f2ad84f5cb9b666b60034d28313f743348c139 Mon Sep 17 00:00:00 2001
From: Eduardo Dantas <eduardo.dantas@hotmail.com.br>
Date: Tue, 10 Sep 2024 11:57:57 -0300
Subject: [PATCH 56/60] fix: move event location

---
 data-otservbr-global/lib/quests/soul_war.lua                    | 1 +
 .../monster/quests/soul_war/goshnar's_megalomania_purple.lua    | 2 --
 2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/data-otservbr-global/lib/quests/soul_war.lua b/data-otservbr-global/lib/quests/soul_war.lua
index 1cacf4de08f..fa96ebd774a 100644
--- a/data-otservbr-global/lib/quests/soul_war.lua
+++ b/data-otservbr-global/lib/quests/soul_war.lua
@@ -1401,6 +1401,7 @@ function Monster:increaseAspectOfPowerDeathCount()
 		self:setType("Goshnar's Megalomania Green")
 		self:say("THE DEATH OF ASPECTS DIMINISHES GOSHNAR'S POWER AND HE TURNS VULNERABLE!")
 		bossKV:set("aspect-of-power-death-count", 0)
+		SoulWarQuest.changeBlueEvent = addEvent(SoulWarQuest.changeMegalomaniaBlue, 1 * 60 * 1000)
 		logger.trace("Aspect of Power defeated all and Megalomania is now vulnerable, reseting death count.")
 		SoulWarQuest.changePurpleEvent = addEvent(function()
 			local boss = Creature("Goshnar's Megalomania")
diff --git a/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_purple.lua b/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_purple.lua
index c2530a43087..79914af4935 100644
--- a/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_purple.lua
+++ b/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_purple.lua
@@ -110,8 +110,6 @@ mType.onSpawn = function(monster)
 		stopEvent(SoulWarQuest.changePurpleEvent)
 	end
 
-	SoulWarQuest.changeBlueEvent = addEvent(SoulWarQuest.changeMegalomaniaBlue, 6 * 60 * 1000)
-
 	local bossKV = monster:getSoulWarKV()
 	bossKV:set("aspect-of-power-death-count", 0)
 	monster:resetHatredDamageMultiplier()

From 2df6acee7ccbd7a779a51c134cc8b7c87dfecdd4 Mon Sep 17 00:00:00 2001
From: Eduardo Dantas <eduardo.dantas@hotmail.com.br>
Date: Tue, 10 Sep 2024 12:57:28 -0300
Subject: [PATCH 57/60] fix: add missing spawns

---
 data-otservbr-global/world/otservbr-monster.xml | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/data-otservbr-global/world/otservbr-monster.xml b/data-otservbr-global/world/otservbr-monster.xml
index 41bb280696e..80c5f5d4ff3 100644
--- a/data-otservbr-global/world/otservbr-monster.xml
+++ b/data-otservbr-global/world/otservbr-monster.xml
@@ -162007,6 +162007,9 @@
 	<monster centerx="32513" centery="31593" centerz="14" radius="3">
 		<monster name="Warlock" x="1" y="1" z="14" spawntime="90" />
 	</monster>
+	<monster centerx="33708" centery="31593" centerz="14" radius="1">
+		<monster name="Dreadful Harvester" x="0" y="0" z="14" spawntime="10" />
+	</monster>
 	<monster centerx="32505" centery="31594" centerz="14" radius="3">
 		<monster name="Warlock" x="0" y="-1" z="14" spawntime="90" />
 	</monster>
@@ -162039,6 +162042,12 @@
 		<monster name="Dark Torturer" x="4" y="5" z="14" spawntime="90" />
 		<monster name="Lost Soul" x="0" y="6" z="14" spawntime="90" />
 	</monster>
+	<monster centerx="33706" centery="31596" centerz="14" radius="1">
+		<monster name="Malicious Soul" x="0" y="0" z="14" spawntime="10" />
+	</monster>
+	<monster centerx="33712" centery="31596" centerz="14" radius="1">
+		<monster name="Dreadful Harvester" x="0" y="0" z="14" spawntime="10" />
+	</monster>
 	<monster centerx="33748" centery="31596" centerz="14" radius="1">
 		<monster name="Dreadful Harvester" x="0" y="0" z="14" spawntime="10" />
 	</monster>
@@ -162110,6 +162119,9 @@
 		<monster name="Fire Elemental" x="0" y="4" z="14" spawntime="90" />
 		<monster name="Fire Elemental" x="4" y="4" z="14" spawntime="90" />
 	</monster>
+	<monster centerx="33706" centery="31603" centerz="14" radius="1">
+		<monster name="Malicious Soul" x="0" y="0" z="14" spawntime="10" />
+	</monster>
 	<monster centerx="33743" centery="31603" centerz="14" radius="1">
 		<monster name="Hateful Soul" x="0" y="0" z="14" spawntime="10" />
 	</monster>

From b5a9e79e948c6e00ff713ffdbafbec737d6e7bef Mon Sep 17 00:00:00 2001
From: Eduardo Dantas <eduardo.dantas@hotmail.com.br>
Date: Tue, 10 Sep 2024 14:37:15 -0300
Subject: [PATCH 58/60] fix: bag you desire drop

---
 data-otservbr-global/lib/quests/soul_war.lua  | 26 +++++++------------
 .../soul_war/goshnar's_megalomania_blue.lua   |  1 +
 .../soul_war/goshnar's_megalomania_green.lua  |  1 +
 .../quests/soul_war/goshnars_cruelty.lua      |  1 +
 .../quests/soul_war/goshnars_greed.lua        |  1 +
 .../quests/soul_war/goshnars_hatred.lua       |  1 +
 .../quests/soul_war/goshnars_malice.lua       |  1 +
 .../quests/soul_war/goshnars_spite.lua        |  1 +
 .../normal_monsters/bony_sea_devil.lua        |  1 +
 .../soul_war/normal_monsters/brachiodemon.lua |  1 +
 .../normal_monsters/branchy_crawler.lua       |  1 +
 .../normal_monsters/capricious_phantom.lua    |  1 +
 .../normal_monsters/distorted_phantom.lua     |  1 +
 .../normal_monsters/druid's_apparition.lua    |  1 +
 .../furious_crater/cloak_of_terror.lua        |  1 +
 .../furious_crater/courage_leech.lua          |  1 +
 .../furious_crater/poor_soul.lua              |  1 -
 .../furious_crater/vibrant_phantom.lua        |  1 +
 .../normal_monsters/infernal_demon.lua        |  1 +
 .../normal_monsters/infernal_phantom.lua      |  1 +
 .../normal_monsters/knight's_apparition.lua   |  1 +
 .../soul_war/normal_monsters/many_faces.lua   |  1 +
 .../normal_monsters/mould_phantom.lua         |  1 +
 .../normal_monsters/paladin's_apparition.lua  |  1 +
 .../soul_war/normal_monsters/rotten_golem.lua |  1 +
 .../normal_monsters/sorcerer's_apparition.lua |  1 +
 .../normal_monsters/turbulent_elemental.lua   |  1 +
 .../monster/undeads/hazardous_phantom.lua     |  1 +
 ...ntcallback_on_drop_loot_bag_you_desire.lua | 16 ------------
 data/libs/functions/monster.lua               |  4 +--
 data/libs/functions/monstertype.lua           |  7 ++++-
 .../monster/ondroploot__base.lua              |  2 +-
 .../monster/ondroploot_boosted.lua            |  2 +-
 .../monster/ondroploot_hazard.lua             |  2 +-
 .../monster/ondroploot_prey.lua               |  2 +-
 .../monster/ondroploot_wealth_duplex.lua      |  2 +-
 data/scripts/systems/reward_chest.lua         |  4 +--
 37 files changed, 51 insertions(+), 43 deletions(-)
 delete mode 100644 data-otservbr-global/scripts/quests/soul_war/eventcallback_on_drop_loot_bag_you_desire.lua

diff --git a/data-otservbr-global/lib/quests/soul_war.lua b/data-otservbr-global/lib/quests/soul_war.lua
index fa96ebd774a..1072ee519ab 100644
--- a/data-otservbr-global/lib/quests/soul_war.lua
+++ b/data-otservbr-global/lib/quests/soul_war.lua
@@ -30,8 +30,7 @@ SoulWarQuest = {
 
 	timeToReturnImmuneMegalomania = 70, -- In seconds
 
-	baseBagYouDesireChance = 500, -- 1000 = 1% chance, 500 = 0.5% chance
-	bagYouDesireChancePerTaint = 1, -- Increases 1% per taint
+	bagYouDesireChancePerTaint = 10, -- Increases % per taint
 	bagYouDesireMonsters = {
 		"Bony Sea Devil",
 		"Brachiodemon",
@@ -1089,7 +1088,7 @@ function Monster:createSoulWarWhiteTiles(centerRoomPosition, zonePositions, exec
 	addEvent(revertTilesAndApplyDamage, executeInterval or 3000, zonePositions)
 end
 
-function Monster:generateBagYouDesireLoot(player)
+function MonsterType:calculateBagYouDesireChance(player, itemChance)
 	local playerTaintLevel = player:getTaintLevel()
 	if not playerTaintLevel or playerTaintLevel == 0 then
 		return {}
@@ -1102,29 +1101,24 @@ function Monster:generateBagYouDesireLoot(player)
 	end
 
 	local loot = {}
-	local totalChance = SoulWarQuest.baseBagYouDesireChance
 	local soulWarQuest = player:soulWarQuestKV()
 	local megalomaniaKills = soulWarQuest:scoped("megalomania-kills"):get("count") or 0
 
 	if monsterName == "Goshnar's Megalomania" then
 		-- Special handling for Goshnar's Megalomania
-		totalChance = totalChance + megalomaniaKills * SoulWarQuest.bagYouDesireChancePerTaint
+		itemChance = itemChance + megalomaniaKills * SoulWarQuest.bagYouDesireChancePerTaint
 	else
 		-- General handling for other monsters (bosses and non-bosses)
-		totalChance = totalChance + (playerTaintLevel * SoulWarQuest.bagYouDesireChancePerTaint)
+		itemChance = itemChance + (playerTaintLevel * SoulWarQuest.bagYouDesireChancePerTaint)
 	end
 
-	logger.trace("Player {} killed {} with {} taints, loot chance {}", player:getName(), monsterName, playerTaintLevel, totalChance)
+	logger.info("Player {} killed {} with {} taints, loot chance {}", player:getName(), monsterName, playerTaintLevel, itemChance)
 
 	if math.random(1, 100000) <= totalChance then
-		local itemType = ItemType(SoulWarQuest.bagYouDesireItemId)
-		if itemType then
-			loot[itemType:getId()] = { count = 1 }
-			logger.debug("Player {} killed {} and got a bag you desire with drop chance {}", player:getName(), monsterName, totalChance)
-			if monsterName == "Goshnar's Megalomania" then
-				-- Reset kill count on successful drop
-				soulWarQuest:scoped("megalomania-kills"):set("count", 0)
-			end
+		logger.debug("Player {} killed {} and got a bag you desire with drop chance {}", player:getName(), monsterName, itemChance)
+		if monsterName == "Goshnar's Megalomania" then
+			-- Reset kill count on successful drop
+			soulWarQuest:scoped("megalomania-kills"):set("count", 0)
 		end
 	else
 		if monsterName == "Goshnar's Megalomania" then
@@ -1133,7 +1127,7 @@ function Monster:generateBagYouDesireLoot(player)
 		end
 	end
 
-	return loot
+	return itemChance
 end
 
 local intervalBetweenExecutions = 10000
diff --git a/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_blue.lua b/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_blue.lua
index 93ecb6c4230..1433d2ed7d4 100644
--- a/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_blue.lua
+++ b/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_blue.lua
@@ -94,6 +94,7 @@ monster.loot = {
 	{ name = "figurine of megalomania", chance = 400 },
 	{ name = "megalomania's skull", chance = 400 },
 	{ name = "megalomania's essence", chance = 400 },
+	{ name = "bag you desire", chance = 100 },
 }
 
 monster.attacks = {
diff --git a/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_green.lua b/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_green.lua
index 6c7b16bd707..f6d60b0b747 100644
--- a/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_green.lua
+++ b/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_green.lua
@@ -99,6 +99,7 @@ monster.loot = {
 	{ name = "figurine of megalomania", chance = 400 },
 	{ name = "megalomania's skull", chance = 400 },
 	{ name = "megalomania's essence", chance = 400 },
+	{ name = "bag you desire", chance = 100 },
 }
 
 monster.attacks = {
diff --git a/data-otservbr-global/monster/quests/soul_war/goshnars_cruelty.lua b/data-otservbr-global/monster/quests/soul_war/goshnars_cruelty.lua
index f42d09e89dd..44f87cca574 100644
--- a/data-otservbr-global/monster/quests/soul_war/goshnars_cruelty.lua
+++ b/data-otservbr-global/monster/quests/soul_war/goshnars_cruelty.lua
@@ -96,6 +96,7 @@ monster.loot = {
 	{ name = "figurine of cruelty", chance = 400 },
 	{ name = "spectral saddle", chance = 400 },
 	{ name = "spectral horse tack", chance = 400 },
+	{ name = "bag you desire", chance = 100 },
 }
 
 monster.attacks = {
diff --git a/data-otservbr-global/monster/quests/soul_war/goshnars_greed.lua b/data-otservbr-global/monster/quests/soul_war/goshnars_greed.lua
index 7c6110f4592..f1f5284398e 100644
--- a/data-otservbr-global/monster/quests/soul_war/goshnars_greed.lua
+++ b/data-otservbr-global/monster/quests/soul_war/goshnars_greed.lua
@@ -97,6 +97,7 @@ monster.loot = {
 	{ name = "greed's arm", chance = 25000, maxCount = 1 },
 	{ name = "figurine of greed", chance = 400 },
 	{ name = "the skull of a beast", chance = 400 },
+	{ name = "bag you desire", chance = 100 },
 }
 
 monster.attacks = {
diff --git a/data-otservbr-global/monster/quests/soul_war/goshnars_hatred.lua b/data-otservbr-global/monster/quests/soul_war/goshnars_hatred.lua
index 89f00c899eb..47fedea4e7c 100644
--- a/data-otservbr-global/monster/quests/soul_war/goshnars_hatred.lua
+++ b/data-otservbr-global/monster/quests/soul_war/goshnars_hatred.lua
@@ -96,6 +96,7 @@ monster.loot = {
 	{ name = "spectral horseshoe", chance = 400 },
 	{ name = "spectral horse tack", chance = 400 },
 	{ name = "bracelet of strengthening", chance = 400 },
+	{ name = "bag you desire", chance = 100 },
 }
 
 monster.attacks = {
diff --git a/data-otservbr-global/monster/quests/soul_war/goshnars_malice.lua b/data-otservbr-global/monster/quests/soul_war/goshnars_malice.lua
index 6931add8bd5..e0b054dc10d 100644
--- a/data-otservbr-global/monster/quests/soul_war/goshnars_malice.lua
+++ b/data-otservbr-global/monster/quests/soul_war/goshnars_malice.lua
@@ -97,6 +97,7 @@ monster.loot = {
 	{ name = "spectral horseshoe", chance = 400 },
 	{ name = "the skull of a beast", chance = 400 },
 	{ name = "figurine of malice", chance = 400 },
+	{ name = "bag you desire", chance = 100 },
 }
 
 monster.attacks = {
diff --git a/data-otservbr-global/monster/quests/soul_war/goshnars_spite.lua b/data-otservbr-global/monster/quests/soul_war/goshnars_spite.lua
index 9e04448fa19..40817c335b0 100644
--- a/data-otservbr-global/monster/quests/soul_war/goshnars_spite.lua
+++ b/data-otservbr-global/monster/quests/soul_war/goshnars_spite.lua
@@ -93,6 +93,7 @@ monster.loot = {
 	{ name = "the skull of a beast", chance = 400 },
 	{ name = "figurine of spite", chance = 400 },
 	{ name = "spite's spirit", chance = 400 },
+	{ name = "bag you desire", chance = 100 },
 }
 
 monster.attacks = {
diff --git a/data-otservbr-global/monster/quests/soul_war/normal_monsters/bony_sea_devil.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/bony_sea_devil.lua
index 95120bfb0d2..d6e4bcfcafe 100644
--- a/data-otservbr-global/monster/quests/soul_war/normal_monsters/bony_sea_devil.lua
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/bony_sea_devil.lua
@@ -100,6 +100,7 @@ monster.loot = {
 	{ name = "goblet of gloom", chance = 880 },
 	{ name = "glacier kilt", chance = 880 },
 	{ name = "glacial rod", chance = 1210 },
+	{ name = "bag you desire", chance = 15 },
 }
 
 monster.attacks = {
diff --git a/data-otservbr-global/monster/quests/soul_war/normal_monsters/brachiodemon.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/brachiodemon.lua
index dfb94760041..a76c9f40ee9 100644
--- a/data-otservbr-global/monster/quests/soul_war/normal_monsters/brachiodemon.lua
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/brachiodemon.lua
@@ -103,6 +103,7 @@ monster.loot = {
 	{ name = "mastermind shield", chance = 420 },
 	{ name = "assassin dagger", chance = 340 },
 	{ name = "alloy legs", chance = 170 },
+	{ name = "bag you desire", chance = 15 },
 }
 
 monster.attacks = {
diff --git a/data-otservbr-global/monster/quests/soul_war/normal_monsters/branchy_crawler.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/branchy_crawler.lua
index 87a491a29d9..f5dccd47eb5 100644
--- a/data-otservbr-global/monster/quests/soul_war/normal_monsters/branchy_crawler.lua
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/branchy_crawler.lua
@@ -98,6 +98,7 @@ monster.loot = {
 	{ name = "twiceslicer", chance = 420 },
 	{ name = "crystalline sword", chance = 390 },
 	{ name = "ruthless axe", chance = 330 },
+	{ name = "bag you desire", chance = 15 },
 }
 
 monster.attacks = {
diff --git a/data-otservbr-global/monster/quests/soul_war/normal_monsters/capricious_phantom.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/capricious_phantom.lua
index 15221cdaf0a..0b3bf5b8572 100644
--- a/data-otservbr-global/monster/quests/soul_war/normal_monsters/capricious_phantom.lua
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/capricious_phantom.lua
@@ -97,6 +97,7 @@ monster.loot = {
 	{ id = 23542, chance = 1180 }, -- collar of blue plasma
 	{ name = "glacial rod", chance = 940 },
 	{ name = "ornate crossbow", chance = 940 },
+	{ name = "bag you desire", chance = 15 },
 }
 
 monster.attacks = {
diff --git a/data-otservbr-global/monster/quests/soul_war/normal_monsters/distorted_phantom.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/distorted_phantom.lua
index 12d78f77654..3f28aac16b9 100644
--- a/data-otservbr-global/monster/quests/soul_war/normal_monsters/distorted_phantom.lua
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/distorted_phantom.lua
@@ -96,6 +96,7 @@ monster.loot = {
 	{ name = "spellbook of warding", chance = 2890 },
 	{ id = 23531, chance = 1930 }, -- ring of green plasma
 	{ name = "glacial rod", chance = 1290 },
+	{ name = "bag you desire", chance = 15 },
 }
 
 monster.attacks = {
diff --git a/data-otservbr-global/monster/quests/soul_war/normal_monsters/druid's_apparition.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/druid's_apparition.lua
index c0436e734a3..957307c40eb 100644
--- a/data-otservbr-global/monster/quests/soul_war/normal_monsters/druid's_apparition.lua
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/druid's_apparition.lua
@@ -94,6 +94,7 @@ monster.loot = {
 	{ name = "platinum amulet", chance = 1750 },
 	{ name = "glacier robe", chance = 880 },
 	{ id = 23544, chance = 440 }, -- collar of red plasma
+	{ name = "bag you desire", chance = 15 },
 }
 
 monster.attacks = {
diff --git a/data-otservbr-global/monster/quests/soul_war/normal_monsters/furious_crater/cloak_of_terror.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/furious_crater/cloak_of_terror.lua
index c5e440ef02e..ff25ab1f058 100644
--- a/data-otservbr-global/monster/quests/soul_war/normal_monsters/furious_crater/cloak_of_terror.lua
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/furious_crater/cloak_of_terror.lua
@@ -98,6 +98,7 @@ monster.loot = {
 	{ name = "blue gem", chance = 1490 },
 	{ name = "brooch of embracement", chance = 1490 },
 	{ name = "wand of defiance", chance = 990 },
+	{ name = "bag you desire", chance = 15 },
 }
 
 monster.attacks = {
diff --git a/data-otservbr-global/monster/quests/soul_war/normal_monsters/furious_crater/courage_leech.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/furious_crater/courage_leech.lua
index 4df38a95cc7..615e4637841 100644
--- a/data-otservbr-global/monster/quests/soul_war/normal_monsters/furious_crater/courage_leech.lua
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/furious_crater/courage_leech.lua
@@ -96,6 +96,7 @@ monster.loot = {
 	{ name = "stone skin amulet", chance = 910 },
 	{ name = "nightmare blade", chance = 1190 },
 	{ name = "demonrage sword", chance = 600 },
+	{ name = "bag you desire", chance = 15 },
 }
 
 monster.attacks = {
diff --git a/data-otservbr-global/monster/quests/soul_war/normal_monsters/furious_crater/poor_soul.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/furious_crater/poor_soul.lua
index 55f5ccb623f..316959ddcd8 100644
--- a/data-otservbr-global/monster/quests/soul_war/normal_monsters/furious_crater/poor_soul.lua
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/furious_crater/poor_soul.lua
@@ -84,7 +84,6 @@ monster.loot = {
 	{ id = 33932, chance = 3520 }, -- head
 	{ name = "glacial rod", chance = 620 },
 	{ id = 34024, chance = 650 }, -- gruesome fan
-	{ id = 34109, chance = 1 }, -- bag you desire
 }
 
 monster.attacks = {
diff --git a/data-otservbr-global/monster/quests/soul_war/normal_monsters/furious_crater/vibrant_phantom.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/furious_crater/vibrant_phantom.lua
index f4ab16a5307..ae4c60df095 100644
--- a/data-otservbr-global/monster/quests/soul_war/normal_monsters/furious_crater/vibrant_phantom.lua
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/furious_crater/vibrant_phantom.lua
@@ -98,6 +98,7 @@ monster.loot = {
 	{ name = "violet crystal shard", chance = 1080 },
 	{ id = 23529, chance = 1080 }, -- ring of blue plasma
 	{ name = "green gem", chance = 1080 },
+	{ name = "bag you desire", chance = 15 },
 }
 
 monster.attacks = {
diff --git a/data-otservbr-global/monster/quests/soul_war/normal_monsters/infernal_demon.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/infernal_demon.lua
index 9fa157fa7a0..0ec107c192f 100644
--- a/data-otservbr-global/monster/quests/soul_war/normal_monsters/infernal_demon.lua
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/infernal_demon.lua
@@ -98,6 +98,7 @@ monster.loot = {
 	{ name = "giant sword", chance = 2860 },
 	{ name = "magma boots", chance = 2290 },
 	{ name = "stone skin amulet", chance = 570 },
+	{ name = "bag you desire", chance = 15 },
 }
 
 monster.attacks = {
diff --git a/data-otservbr-global/monster/quests/soul_war/normal_monsters/infernal_phantom.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/infernal_phantom.lua
index 1704c7338e0..82b7fd2090a 100644
--- a/data-otservbr-global/monster/quests/soul_war/normal_monsters/infernal_phantom.lua
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/infernal_phantom.lua
@@ -99,6 +99,7 @@ monster.loot = {
 	{ name = "crystal mace", chance = 1610 },
 	{ name = "war axe", chance = 1410 },
 	{ name = "warrior's axe", chance = 1410 },
+	{ name = "bag you desire", chance = 15 },
 }
 
 monster.attacks = {
diff --git a/data-otservbr-global/monster/quests/soul_war/normal_monsters/knight's_apparition.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/knight's_apparition.lua
index b9be9209d0e..f763e9b4dfe 100644
--- a/data-otservbr-global/monster/quests/soul_war/normal_monsters/knight's_apparition.lua
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/knight's_apparition.lua
@@ -92,6 +92,7 @@ monster.loot = {
 	{ name = "giant sword", chance = 1720 },
 	{ name = "stone skin amulet", chance = 1500 },
 	{ name = "crown shield", chance = 640 },
+	{ name = "bag you desire", chance = 15 },
 }
 
 monster.attacks = {
diff --git a/data-otservbr-global/monster/quests/soul_war/normal_monsters/many_faces.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/many_faces.lua
index ad924df93ff..f60b999dbce 100644
--- a/data-otservbr-global/monster/quests/soul_war/normal_monsters/many_faces.lua
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/many_faces.lua
@@ -99,6 +99,7 @@ monster.loot = {
 	{ name = "glacier robe", chance = 2130 },
 	{ name = "gruesome fan", chance = 610 },
 	{ name = "glacial rod", chance = 610 },
+	{ name = "bag you desire", chance = 15 },
 }
 
 monster.attacks = {
diff --git a/data-otservbr-global/monster/quests/soul_war/normal_monsters/mould_phantom.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/mould_phantom.lua
index a2b38a76b90..1af17c877fa 100644
--- a/data-otservbr-global/monster/quests/soul_war/normal_monsters/mould_phantom.lua
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/mould_phantom.lua
@@ -97,6 +97,7 @@ monster.loot = {
 	{ id = 23529, chance = 1040 }, -- ring of blue plasma
 	{ name = "ornate crossbow", chance = 840 },
 	{ name = "crystal crossbow", chance = 620 },
+	{ name = "bag you desire", chance = 15 },
 }
 
 monster.attacks = {
diff --git a/data-otservbr-global/monster/quests/soul_war/normal_monsters/paladin's_apparition.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/paladin's_apparition.lua
index ab9db4fe484..2dc7a49555c 100644
--- a/data-otservbr-global/monster/quests/soul_war/normal_monsters/paladin's_apparition.lua
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/paladin's_apparition.lua
@@ -95,6 +95,7 @@ monster.loot = {
 	{ name = "stone skin amulet", chance = 1560 },
 	{ id = 23542, chance = 1250 }, -- collar of blue plasma
 	{ id = 23529, chance = 1250 }, -- ring of blue plasma
+	{ name = "bag you desire", chance = 15 },
 }
 
 monster.attacks = {
diff --git a/data-otservbr-global/monster/quests/soul_war/normal_monsters/rotten_golem.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/rotten_golem.lua
index f49c96d8b7d..f5d5808b05c 100644
--- a/data-otservbr-global/monster/quests/soul_war/normal_monsters/rotten_golem.lua
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/rotten_golem.lua
@@ -95,6 +95,7 @@ monster.loot = {
 	{ name = "stone skin amulet", chance = 740 },
 	{ name = "terra mantle", chance = 510 },
 	{ name = "rubber cap", chance = 430 },
+	{ name = "bag you desire", chance = 15 },
 }
 
 monster.attacks = {
diff --git a/data-otservbr-global/monster/quests/soul_war/normal_monsters/sorcerer's_apparition.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/sorcerer's_apparition.lua
index 63faa04b271..e554c27dfd9 100644
--- a/data-otservbr-global/monster/quests/soul_war/normal_monsters/sorcerer's_apparition.lua
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/sorcerer's_apparition.lua
@@ -96,6 +96,7 @@ monster.loot = {
 	{ name = "wand of starstorm", chance = 1310 },
 	{ name = "stone skin amulet", chance = 1310 },
 	{ name = "alloy legs", chance = 440 },
+	{ name = "bag you desire", chance = 15 },
 }
 
 monster.attacks = {
diff --git a/data-otservbr-global/monster/quests/soul_war/normal_monsters/turbulent_elemental.lua b/data-otservbr-global/monster/quests/soul_war/normal_monsters/turbulent_elemental.lua
index 57cacb3ee76..6d7804f2207 100644
--- a/data-otservbr-global/monster/quests/soul_war/normal_monsters/turbulent_elemental.lua
+++ b/data-otservbr-global/monster/quests/soul_war/normal_monsters/turbulent_elemental.lua
@@ -95,6 +95,7 @@ monster.loot = {
 	{ name = "crystalline armor", chance = 710 },
 	{ name = "rubber cap", chance = 710 },
 	{ name = "stone skin amulet", chance = 470 },
+	{ name = "bag you desire", chance = 15 },
 }
 
 monster.attacks = {
diff --git a/data-otservbr-global/monster/undeads/hazardous_phantom.lua b/data-otservbr-global/monster/undeads/hazardous_phantom.lua
index f1ba2b8c335..1cd1eb7d38c 100644
--- a/data-otservbr-global/monster/undeads/hazardous_phantom.lua
+++ b/data-otservbr-global/monster/undeads/hazardous_phantom.lua
@@ -82,6 +82,7 @@ monster.loot = {
 	{ id = 282, chance = 1570 }, -- giant shimmering pearl
 	{ name = "wand of everblazing", chance = 790 },
 	{ id = 23542, chance = 790 }, -- collar of blue plasma
+	{ name = "bag you desire", chance = 15 },
 }
 
 monster.attacks = {
diff --git a/data-otservbr-global/scripts/quests/soul_war/eventcallback_on_drop_loot_bag_you_desire.lua b/data-otservbr-global/scripts/quests/soul_war/eventcallback_on_drop_loot_bag_you_desire.lua
deleted file mode 100644
index 04fe2035956..00000000000
--- a/data-otservbr-global/scripts/quests/soul_war/eventcallback_on_drop_loot_bag_you_desire.lua
+++ /dev/null
@@ -1,16 +0,0 @@
-local callback = EventCallback("MonsterOnDropBagYouDesire")
-
-function callback.monsterOnDropLoot(monster, corpse)
-	if not monster or not corpse then
-		return
-	end
-
-	local player = Player(corpse:getCorpseOwner())
-	if not player or not player:canReceiveLoot() then
-		return
-	end
-
-	corpse:addLoot(monster:generateBagYouDesireLoot(player))
-end
-
-callback:register()
diff --git a/data/libs/functions/monster.lua b/data/libs/functions/monster.lua
index f26f2a5b9b4..0327daab3b3 100644
--- a/data/libs/functions/monster.lua
+++ b/data/libs/functions/monster.lua
@@ -204,7 +204,7 @@ do
 		return table.contains(equipmentTypes, t)
 	end
 
-	function MonsterType.getBossReward(self, lootFactor, topScore, equipmentOnly, lootTable)
+	function MonsterType.getBossReward(self, lootFactor, topScore, equipmentOnly, lootTable, player)
 		if configManager.getNumber(configKeys.RATE_LOOT) <= 0 then
 			return lootTable or {}
 		end
@@ -221,6 +221,6 @@ do
 				end
 				return true
 			end,
-		}, lootTable)
+		}, lootTable, player)
 	end
 end
diff --git a/data/libs/functions/monstertype.lua b/data/libs/functions/monstertype.lua
index 168cab13109..a9f6fff59f7 100644
--- a/data/libs/functions/monstertype.lua
+++ b/data/libs/functions/monstertype.lua
@@ -1,7 +1,7 @@
 -- return a dictionary of itemId => { count, gut }
 ---@param config { factor: number, gut: boolean, filter?: fun(itemType: ItemType, unique: boolean): boolean }
 ---@return LootItems
-function MonsterType:generateLootRoll(config, resultTable)
+function MonsterType:generateLootRoll(config, resultTable, player)
 	if configManager.getNumber(configKeys.RATE_LOOT) <= 0 then
 		return resultTable or {}
 	end
@@ -28,6 +28,11 @@ function MonsterType:generateLootRoll(config, resultTable)
 		end
 
 		local chance = item.chance
+		if iType:getId() == SoulWarQuest.bagYouDesireItemId then
+			result[item.itemId].chance = self:calculateBagYouDesireChance(player, chance)
+			logger.debug("Final chance for bag you desire: {}, original chance: {}", result[item.itemId].chance, chance)
+		end
+
 		if config.gut and iType:getType() == ITEM_TYPE_CREATUREPRODUCT then
 			chance = math.ceil((chance * GLOBAL_CHARM_GUT) / 100)
 		end
diff --git a/data/scripts/eventcallbacks/monster/ondroploot__base.lua b/data/scripts/eventcallbacks/monster/ondroploot__base.lua
index 900259d4fef..0f724be9f67 100644
--- a/data/scripts/eventcallbacks/monster/ondroploot__base.lua
+++ b/data/scripts/eventcallbacks/monster/ondroploot__base.lua
@@ -22,7 +22,7 @@ function callback.monsterOnDropLoot(monster, corpse)
 	local charm = player and player:getCharmMonsterType(CHARM_GUT)
 	local gut = charm and charm:raceId() == mType:raceId()
 
-	local lootTable = mType:generateLootRoll({ factor = factor, gut = gut }, {})
+	local lootTable = mType:generateLootRoll({ factor = factor, gut = gut }, {}, player)
 	corpse:addLoot(lootTable)
 	for _, item in ipairs(lootTable) do
 		if item.gut then
diff --git a/data/scripts/eventcallbacks/monster/ondroploot_boosted.lua b/data/scripts/eventcallbacks/monster/ondroploot_boosted.lua
index 507df354ab7..3bb43256772 100644
--- a/data/scripts/eventcallbacks/monster/ondroploot_boosted.lua
+++ b/data/scripts/eventcallbacks/monster/ondroploot_boosted.lua
@@ -22,7 +22,7 @@ function callback.monsterOnDropLoot(monster, corpse)
 
 	local factor = 1.0
 	local msgSuffix = " (boosted loot)"
-	corpse:addLoot(mType:generateLootRoll({ factor = factor, gut = false }, {}))
+	corpse:addLoot(mType:generateLootRoll({ factor = factor, gut = false }, {}, player))
 
 	local existingSuffix = corpse:getAttribute(ITEM_ATTRIBUTE_LOOTMESSAGE_SUFFIX) or ""
 	corpse:setAttribute(ITEM_ATTRIBUTE_LOOTMESSAGE_SUFFIX, existingSuffix .. msgSuffix)
diff --git a/data/scripts/eventcallbacks/monster/ondroploot_hazard.lua b/data/scripts/eventcallbacks/monster/ondroploot_hazard.lua
index 92ae22482fd..78851d186e6 100644
--- a/data/scripts/eventcallbacks/monster/ondroploot_hazard.lua
+++ b/data/scripts/eventcallbacks/monster/ondroploot_hazard.lua
@@ -31,7 +31,7 @@ function callback.monsterOnDropLoot(monster, corpse)
 
 	local lootTable = {}
 	for _ = 1, rolls do
-		lootTable = mType:generateLootRoll({ factor = factor, gut = false }, lootTable)
+		lootTable = mType:generateLootRoll({ factor = factor, gut = false }, lootTable, player)
 	end
 	corpse:addLoot(lootTable)
 
diff --git a/data/scripts/eventcallbacks/monster/ondroploot_prey.lua b/data/scripts/eventcallbacks/monster/ondroploot_prey.lua
index a0fce3d4457..eb4657ccc4f 100644
--- a/data/scripts/eventcallbacks/monster/ondroploot_prey.lua
+++ b/data/scripts/eventcallbacks/monster/ondroploot_prey.lua
@@ -42,7 +42,7 @@ function callback.monsterOnDropLoot(monster, corpse)
 		msgSuffix = msgSuffix .. " (active prey bonus)"
 	end
 
-	corpse:addLoot(mType:generateLootRoll({ factor = factor, gut = false }, {}))
+	corpse:addLoot(mType:generateLootRoll({ factor = factor, gut = false }, {}, player))
 	local existingSuffix = corpse:getAttribute(ITEM_ATTRIBUTE_LOOTMESSAGE_SUFFIX) or ""
 	corpse:setAttribute(ITEM_ATTRIBUTE_LOOTMESSAGE_SUFFIX, existingSuffix .. msgSuffix)
 end
diff --git a/data/scripts/eventcallbacks/monster/ondroploot_wealth_duplex.lua b/data/scripts/eventcallbacks/monster/ondroploot_wealth_duplex.lua
index ffba226956a..a4f3c67fe9c 100644
--- a/data/scripts/eventcallbacks/monster/ondroploot_wealth_duplex.lua
+++ b/data/scripts/eventcallbacks/monster/ondroploot_wealth_duplex.lua
@@ -59,7 +59,7 @@ function callback.monsterOnDropLoot(monster, corpse)
 
 	local lootTable = {}
 	for _ = 1, rolls do
-		lootTable = mType:generateLootRoll({ factor = factor, gut = false }, lootTable)
+		lootTable = mType:generateLootRoll({ factor = factor, gut = false }, lootTable, player)
 	end
 	corpse:addLoot(lootTable)
 
diff --git a/data/scripts/systems/reward_chest.lua b/data/scripts/systems/reward_chest.lua
index 384115af0b0..07ec9b512a9 100644
--- a/data/scripts/systems/reward_chest.lua
+++ b/data/scripts/systems/reward_chest.lua
@@ -103,9 +103,9 @@ function bossDeath.onDeath(creature, corpse, killer, mostDamageKiller, lastHitUn
 				end
 
 				local playerLoot = creature:generateGemAtelierLoot()
-				playerLoot = monsterType:getBossReward(lootFactor, _ == 1, false, playerLoot)
+				playerLoot = monsterType:getBossReward(lootFactor, _ == 1, false, playerLoot, player)
 				for _ = 2, rolls do
-					playerLoot = monsterType:getBossReward(lootFactor, false, true, playerLoot)
+					playerLoot = monsterType:getBossReward(lootFactor, false, true, playerLoot, player)
 				end
 
 				-- Add droped items to reward container

From e763b835dab7a41df16d794e8abfbd9a4685297c Mon Sep 17 00:00:00 2001
From: Eduardo Dantas <eduardo.dantas@hotmail.com.br>
Date: Tue, 10 Sep 2024 14:42:29 -0300
Subject: [PATCH 59/60] fix: missing monster and remove "."

---
 data-otservbr-global/lib/quests/soul_war.lua | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/data-otservbr-global/lib/quests/soul_war.lua b/data-otservbr-global/lib/quests/soul_war.lua
index 1072ee519ab..4b48d3be9d8 100644
--- a/data-otservbr-global/lib/quests/soul_war.lua
+++ b/data-otservbr-global/lib/quests/soul_war.lua
@@ -49,7 +49,8 @@ SoulWarQuest = {
 		"Rotten Golem",
 		"Sorcerer's Apparition",
 		"Turbulent Elemental",
-		"Vibrant Phantom.",
+		"Vibrant Phantom",
+		"Hazardous Phantom",
 		"Goshnar's Cruelty",
 		"Goshnar's Spite",
 		"Goshnar's Malice",

From 376e38783293c2d82ecc00bfd279d8f6ee1287ac Mon Sep 17 00:00:00 2001
From: Eduardo Dantas <eduardo.dantas@hotmail.com.br>
Date: Tue, 10 Sep 2024 14:44:23 -0300
Subject: [PATCH 60/60] fix: calculate desire chance function

---
 data-otservbr-global/lib/quests/soul_war.lua | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/data-otservbr-global/lib/quests/soul_war.lua b/data-otservbr-global/lib/quests/soul_war.lua
index 4b48d3be9d8..a9e9d920e91 100644
--- a/data-otservbr-global/lib/quests/soul_war.lua
+++ b/data-otservbr-global/lib/quests/soul_war.lua
@@ -1092,16 +1092,15 @@ end
 function MonsterType:calculateBagYouDesireChance(player, itemChance)
 	local playerTaintLevel = player:getTaintLevel()
 	if not playerTaintLevel or playerTaintLevel == 0 then
-		return {}
+		return itemChance
 	end
 
 	local monsterName = self:getName()
 	local isMonsterValid = table.contains(SoulWarQuest.bagYouDesireMonsters, monsterName)
 	if not isMonsterValid then
-		return {}
+		return itemChance
 	end
 
-	local loot = {}
 	local soulWarQuest = player:soulWarQuestKV()
 	local megalomaniaKills = soulWarQuest:scoped("megalomania-kills"):get("count") or 0