From e5eac88bb4ff8128e7598de8d8e6d5acd3f13d18 Mon Sep 17 00:00:00 2001 From: Sebastian Nobbelin Date: Wed, 16 Aug 2023 13:25:50 +0200 Subject: [PATCH 01/17] feat: added kill events for primal menace and magma bubble --- .../quests/primal_ordeal_quest/magma_bubble.lua | 4 ++++ .../primal_ordeal_quest/the_primal_menace.lua | 4 ++++ .../quests/the_primal_ordeal/magma_bubble_death.lua | 13 +++++++++++++ .../the_primal_ordeal/the_primal_menace_killed.lua | 13 +++++++++++++ 4 files changed, 34 insertions(+) create mode 100644 data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/magma_bubble_death.lua create mode 100644 data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/the_primal_menace_killed.lua diff --git a/data-otservbr-global/monster/quests/primal_ordeal_quest/magma_bubble.lua b/data-otservbr-global/monster/quests/primal_ordeal_quest/magma_bubble.lua index f8a7f5ce42d..7e163b43ea7 100644 --- a/data-otservbr-global/monster/quests/primal_ordeal_quest/magma_bubble.lua +++ b/data-otservbr-global/monster/quests/primal_ordeal_quest/magma_bubble.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0 } +monster.events = { + "MagmaBubbleDeath" +} + monster.health = 300000 monster.maxHealth = 300000 monster.race = "undead" diff --git a/data-otservbr-global/monster/quests/primal_ordeal_quest/the_primal_menace.lua b/data-otservbr-global/monster/quests/primal_ordeal_quest/the_primal_menace.lua index 2ec3f3daf0b..10fce4a62a8 100644 --- a/data-otservbr-global/monster/quests/primal_ordeal_quest/the_primal_menace.lua +++ b/data-otservbr-global/monster/quests/primal_ordeal_quest/the_primal_menace.lua @@ -13,6 +13,10 @@ monster.outfit = { lookMount = 0 } +monster.events = { + "ThePrimalMenaceDeath" +} + monster.health = 5000000 monster.maxHealth = 5000000 monster.race = "blood" diff --git a/data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/magma_bubble_death.lua b/data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/magma_bubble_death.lua new file mode 100644 index 00000000000..8f59293ede3 --- /dev/null +++ b/data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/magma_bubble_death.lua @@ -0,0 +1,13 @@ +local magmaBubbleDeath = CreatureEvent("MagmaBubbleDeath") +function magmaBubbleDeath.onDeath(creature, corpse, killer, mostDamage, unjustified, mostDamage_unjustified) + local damageMap = creature:getMonster():getDamageMap() + + for key, value in pairs(damageMap) do + local player = Player(key) + if player and player:getStorageValue(Storage.Quest.U12_90.PrimalOrdeal.MagmaBubbleKilled) < 1 then + player:setStorageValue(Storage.Quest.U12_90.PrimalOrdeal.MagmaBubbleKilled, 1) -- Access to The primal menace boss fight + end + end +end + +magmaBubbleDeath.register() diff --git a/data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/the_primal_menace_killed.lua b/data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/the_primal_menace_killed.lua new file mode 100644 index 00000000000..1db940ace8a --- /dev/null +++ b/data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/the_primal_menace_killed.lua @@ -0,0 +1,13 @@ +local thePrimalMenaceDeath = CreatureEvent("ThePrimalMenaceDeath") +function thePrimalMenaceDeath.onDeath(creature, corpse, killer, mostDamage, unjustified, mostDamage_unjustified) + local damageMap = creature:getMonster():getDamageMap() + + for key, value in pairs(damageMap) do + local player = Player(key) + if player and player:getStorageValue(Storage.Quest.U12_90.PrimalOrdeal.ThePrimalMenaceKilled) < 1 then + player:setStorageValue(Storage.Quest.U12_90.PrimalOrdeal.ThePrimalMenaceKilled, 1) + end + end +end + +thePrimalMenaceDeath.register() From 800ac4dca76c01ab4717535195b4d736126f15d8 Mon Sep 17 00:00:00 2001 From: Sebastian Nobbelin Date: Wed, 16 Aug 2023 13:30:44 +0200 Subject: [PATCH 02/17] fixed event registration --- .../quests/the_primal_ordeal/magma_bubble_death.lua | 2 +- .../quests/the_primal_ordeal/the_primal_menace_killed.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/magma_bubble_death.lua b/data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/magma_bubble_death.lua index 8f59293ede3..c870b82e260 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/magma_bubble_death.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/magma_bubble_death.lua @@ -10,4 +10,4 @@ function magmaBubbleDeath.onDeath(creature, corpse, killer, mostDamage, unjustif end end -magmaBubbleDeath.register() +magmaBubbleDeath:register() diff --git a/data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/the_primal_menace_killed.lua b/data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/the_primal_menace_killed.lua index 1db940ace8a..ccb530fb8df 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/the_primal_menace_killed.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/the_primal_menace_killed.lua @@ -10,4 +10,4 @@ function thePrimalMenaceDeath.onDeath(creature, corpse, killer, mostDamage, unju end end -thePrimalMenaceDeath.register() +thePrimalMenaceDeath:register() From 03a2deaf1fee33e3e1db357f9c15809d3f072951 Mon Sep 17 00:00:00 2001 From: Sebastian Nobbelin Date: Wed, 16 Aug 2023 13:33:35 +0200 Subject: [PATCH 03/17] fixed invalid storage path --- .../quests/the_primal_ordeal/magma_bubble_death.lua | 2 +- .../quests/the_primal_ordeal/the_primal_menace_killed.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/magma_bubble_death.lua b/data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/magma_bubble_death.lua index c870b82e260..5e3dd350eb4 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/magma_bubble_death.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/magma_bubble_death.lua @@ -5,7 +5,7 @@ function magmaBubbleDeath.onDeath(creature, corpse, killer, mostDamage, unjustif for key, value in pairs(damageMap) do local player = Player(key) if player and player:getStorageValue(Storage.Quest.U12_90.PrimalOrdeal.MagmaBubbleKilled) < 1 then - player:setStorageValue(Storage.Quest.U12_90.PrimalOrdeal.MagmaBubbleKilled, 1) -- Access to The primal menace boss fight + player:setStorageValue(Storage.Quest.U12_90.PrimalOrdeal.Bosses.MagmaBubbleKilled, 1) -- Access to The primal menace boss fight end end end diff --git a/data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/the_primal_menace_killed.lua b/data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/the_primal_menace_killed.lua index ccb530fb8df..18a006de140 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/the_primal_menace_killed.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/the_primal_menace_killed.lua @@ -5,7 +5,7 @@ function thePrimalMenaceDeath.onDeath(creature, corpse, killer, mostDamage, unju for key, value in pairs(damageMap) do local player = Player(key) if player and player:getStorageValue(Storage.Quest.U12_90.PrimalOrdeal.ThePrimalMenaceKilled) < 1 then - player:setStorageValue(Storage.Quest.U12_90.PrimalOrdeal.ThePrimalMenaceKilled, 1) + player:setStorageValue(Storage.Quest.U12_90.PrimalOrdeal.Bosses.ThePrimalMenaceKilled, 1) end end end From 0ca8e7bbd4b2333b1454155551f3a94faf1d7a01 Mon Sep 17 00:00:00 2001 From: Sebastian Nobbelin Date: Wed, 16 Aug 2023 13:35:45 +0200 Subject: [PATCH 04/17] fixed invalid storage lookup --- .../quests/the_primal_ordeal/magma_bubble_death.lua | 2 +- .../quests/the_primal_ordeal/the_primal_menace_killed.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/magma_bubble_death.lua b/data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/magma_bubble_death.lua index 5e3dd350eb4..f12fd3092b7 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/magma_bubble_death.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/magma_bubble_death.lua @@ -4,7 +4,7 @@ function magmaBubbleDeath.onDeath(creature, corpse, killer, mostDamage, unjustif for key, value in pairs(damageMap) do local player = Player(key) - if player and player:getStorageValue(Storage.Quest.U12_90.PrimalOrdeal.MagmaBubbleKilled) < 1 then + if player and player:getStorageValue(Storage.Quest.U12_90.PrimalOrdeal.Bosses.MagmaBubbleKilled) < 1 then player:setStorageValue(Storage.Quest.U12_90.PrimalOrdeal.Bosses.MagmaBubbleKilled, 1) -- Access to The primal menace boss fight end end diff --git a/data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/the_primal_menace_killed.lua b/data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/the_primal_menace_killed.lua index 18a006de140..79f73a73269 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/the_primal_menace_killed.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/the_primal_menace_killed.lua @@ -4,7 +4,7 @@ function thePrimalMenaceDeath.onDeath(creature, corpse, killer, mostDamage, unju for key, value in pairs(damageMap) do local player = Player(key) - if player and player:getStorageValue(Storage.Quest.U12_90.PrimalOrdeal.ThePrimalMenaceKilled) < 1 then + if player and player:getStorageValue(Storage.Quest.U12_90.PrimalOrdeal.Bosses.ThePrimalMenaceKilled) < 1 then player:setStorageValue(Storage.Quest.U12_90.PrimalOrdeal.Bosses.ThePrimalMenaceKilled, 1) end end From da87943ba7113c897b655d4072e613f30a23906a Mon Sep 17 00:00:00 2001 From: Sebastian Nobbelin Date: Thu, 17 Aug 2023 15:15:32 +0200 Subject: [PATCH 05/17] moved code from hazard.lua to primal menace kill. Also modified the primal menace hp and damage output. --- .../primal_ordeal_quest/the_primal_menace.lua | 31 ++++++++++++------- .../the_primal_menace_killed.lua | 10 ++++++ .../scripts/hazard/primal.lua | 28 +++-------------- data/libs/hazard_lib.lua | 17 ++++++++++ 4 files changed, 51 insertions(+), 35 deletions(-) diff --git a/data-otservbr-global/monster/quests/primal_ordeal_quest/the_primal_menace.lua b/data-otservbr-global/monster/quests/primal_ordeal_quest/the_primal_menace.lua index 10fce4a62a8..0cf13ba6697 100644 --- a/data-otservbr-global/monster/quests/primal_ordeal_quest/the_primal_menace.lua +++ b/data-otservbr-global/monster/quests/primal_ordeal_quest/the_primal_menace.lua @@ -17,8 +17,8 @@ monster.events = { "ThePrimalMenaceDeath" } -monster.health = 5000000 -monster.maxHealth = 5000000 +monster.health = 1000000 +monster.maxHealth = 1000000 monster.race = "blood" monster.corpse = 39530 monster.speed = 180 @@ -54,10 +54,19 @@ monster.light = { } monster.summon = { - maxSummons = 2, + maxSummons = 6, summons = { - {name = "Headpecker", chance = 20, interval = 2000}, - {name = "Sulphider", chance = 20, interval = 2000}, + {name = "Emerald Tortoise", chance = 2, interval = 2000, count = 6}, + {name = "Gore Horn", chance = 2, interval = 2000, count = 6}, + {name = "Gorerilla", chance = 2, interval = 2000, count = 6}, + {name = "Headpecker", chance = 2, interval = 2000, count = 6}, + {name = "Hulking Prehemoth", chance = 2, interval = 2000, count = 6}, + {name = "Mantosaurus", chance = 2, interval = 2000, count = 6}, + {name = "Nighthunter", chance = 2, interval = 2000, count = 6}, + {name = "Noxious Ripptor", chance = 2, interval = 2000, count = 6}, + {name = "Sabretooth", chance = 2, interval = 2000, count = 6}, + {name = "Stalking Stalk", chance = 2, interval = 2000, count = 6}, + {name = "Sulphider", chance = 2, interval = 2000, count = 6}, } } @@ -71,12 +80,12 @@ monster.loot = { } monster.attacks = { - {name ="melee", interval = 2000, chance = 85, minDamage = -2500, maxDamage = -3500}, - {name ="combat", interval = 4000, chance = 35, type = COMBAT_EARTHDAMAGE, minDamage = -3000, maxDamage = -4000, length = 10, spread = 3, effect = CONST_ME_CARNIPHILA, target = false}, - {name ="combat", interval = 2500, chance = 45, type = COMBAT_FIREDAMAGE, minDamage = -3000, maxDamage = -7000, length = 10, spread = 3, effect = CONST_ME_HITBYFIRE, target = false}, - {name ="big death wave", interval = 3500, chance = 35, minDamage = -4000, maxDamage = -7000, target = false}, - {name ="combat", interval = 5000, chance = 40, type = COMBAT_ENERGYDAMAGE, effect = CONST_ME_ENERGYHIT, minDamage = -3500, maxDamage = -4000, range = 4, target = false}, - {name ="combat", interval = 2700, chance = 45, type = COMBAT_EARTHDAMAGE, shootEffect = CONST_ANI_POISON, effect = CONST_ANI_EARTH, minDamage = -1500, maxDamage = -4000, range = 4, target = false}, + {name ="melee", interval = 2000, chance = 85, minDamage = -0, maxDamage = -763}, + {name ="combat", interval = 4000, chance = 35, type = COMBAT_EARTHDAMAGE, minDamage = -1500, maxDamage = -2200, length = 10, spread = 3, effect = CONST_ME_CARNIPHILA, target = false}, + {name ="combat", interval = 2500, chance = 45, type = COMBAT_FIREDAMAGE, minDamage = -700, maxDamage = -1000, length = 10, spread = 3, effect = CONST_ME_HITBYFIRE, target = false}, + {name ="big death wave", interval = 3500, chance = 35, minDamage = -250, maxDamage = -300, target = false}, + {name ="combat", interval = 5000, chance = 40, type = COMBAT_ENERGYDAMAGE, effect = CONST_ME_ENERGYHIT, minDamage = -1200, maxDamage = -1300, range = 4, target = false}, + {name ="combat", interval = 2700, chance = 45, type = COMBAT_EARTHDAMAGE, shootEffect = CONST_ANI_POISON, effect = CONST_ANI_EARTH, minDamage = -600, maxDamage = -1800, range = 4, target = false}, } monster.defenses = { diff --git a/data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/the_primal_menace_killed.lua b/data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/the_primal_menace_killed.lua index 79f73a73269..68a8c50a0e8 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/the_primal_menace_killed.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/the_primal_menace_killed.lua @@ -1,13 +1,23 @@ local thePrimalMenaceDeath = CreatureEvent("ThePrimalMenaceDeath") + function thePrimalMenaceDeath.onDeath(creature, corpse, killer, mostDamage, unjustified, mostDamage_unjustified) local damageMap = creature:getMonster():getDamageMap() + local gnompronaHazard = Hazard.getByName("Gnomprona Gardens") + local _, hazardPoints = gnompronaHazard:getHazardPlayerAndPoints(damageMap) for key, value in pairs(damageMap) do local player = Player(key) + if player and player:getStorageValue(Storage.Quest.U12_90.PrimalOrdeal.Bosses.ThePrimalMenaceKilled) < 1 then player:setStorageValue(Storage.Quest.U12_90.PrimalOrdeal.Bosses.ThePrimalMenaceKilled, 1) end + + if player:getHazardSystemPoints() == hazardPoints then + gnompronaHazard:levelUp(player) + end end + + end thePrimalMenaceDeath:register() diff --git a/data-otservbr-global/scripts/hazard/primal.lua b/data-otservbr-global/scripts/hazard/primal.lua index 26521bb1b72..49931e759f2 100644 --- a/data-otservbr-global/scripts/hazard/primal.lua +++ b/data-otservbr-global/scripts/hazard/primal.lua @@ -72,39 +72,18 @@ function primalKill.onKill(_player, creature) if not creature or not monster or not monster:hazard() or not monster:getPosition():isInArea(hazard) then return true end - - local player = nil - local points = -1 - - for key, value in pairs(monster:getDamageMap()) do - local killer = Player(key) - if killer then - local killerPoints = killer:getHazardSystemPoints() - if points > killerPoints or points == -1 then - player = killer - points = killerPoints - end - end - end - for key, value in pairs(monster:getDamageMap()) do - local killer = Player(key) - if killer then - local killerPoints = killer:getHazardSystemPoints() - if monster:getName():lower() == "the primal menace" and killerPoints == points then - hazard:levelUp(killer) - end - end - end - -- don't spawn pods or plunder if the monster is a reward boss if monster:getType():isRewardBoss() then return true end + + local player, points = hazard:getHazardPlayerAndPoints(monster:getDamageMap()) if points < 1 then return true end + -- Pod local chanceTo = math.random(1, 10000) if chanceTo <= (points * configManager.getNumber(configKeys.HAZARD_PODS_DROP_MULTIPLIER)) then local closesestPosition = player:getClosestFreePosition(monster:getPosition(), 4, true) @@ -117,6 +96,7 @@ function primalKill.onKill(_player, creature) return true end + -- Plunder patriarch chanceTo = math.random(1, 10000) if chanceTo <= (points * configManager.getNumber(configKeys.HAZARD_SPAWN_PLUNDER_MULTIPLIER)) then local closesestPosition = player:getClosestFreePosition(monster:getPosition(), 4, true) diff --git a/data/libs/hazard_lib.lua b/data/libs/hazard_lib.lua index 15aaf59a98b..77a31e0a7ee 100644 --- a/data/libs/hazard_lib.lua +++ b/data/libs/hazard_lib.lua @@ -27,6 +27,23 @@ function Hazard.createAreas() end end +function Hazard.getHazardPlayerAndPoints(self, damageMap) + -- Placed here to allow getHazardPoints from player based on which hazard + local hazardPlayer = nil + local hazardPoints = -1 + for key, value in pairs(damageMap) do + local player = Player(key) + local playerHazardPoints = player:getHazardSystemPoints() + + if playerHazardPoints < hazardPoints or hazardPoints == -1 then + hazardPlayer = player + hazardPoints = playerHazardPoints + end + end + + return hazardPlayer, hazardPoints +end + function Hazard.getPlayerCurrentLevel(self, player) return player:getStorageValue(self.storageCurrent) < 0 and 0 or player:getStorageValue(self.storageCurrent) end From 30cf8082afa745a71f93ac3e1b4c3e61c7e9c11c Mon Sep 17 00:00:00 2001 From: Sebastian Nobbelin Date: Thu, 17 Aug 2023 23:02:38 +0200 Subject: [PATCH 06/17] fix non player checks for hazard points --- .../the_primal_ordeal/the_primal_menace_killed.lua | 12 +++++++----- data/libs/hazard_lib.lua | 11 +++++++---- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/the_primal_menace_killed.lua b/data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/the_primal_menace_killed.lua index 68a8c50a0e8..d4a13568369 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/the_primal_menace_killed.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/the_primal_menace_killed.lua @@ -7,14 +7,16 @@ function thePrimalMenaceDeath.onDeath(creature, corpse, killer, mostDamage, unju for key, value in pairs(damageMap) do local player = Player(key) + if player then + if player:getStorageValue(Storage.Quest.U12_90.PrimalOrdeal.Bosses.ThePrimalMenaceKilled) < 1 then + player:setStorageValue(Storage.Quest.U12_90.PrimalOrdeal.Bosses.ThePrimalMenaceKilled, 1) + end - if player and player:getStorageValue(Storage.Quest.U12_90.PrimalOrdeal.Bosses.ThePrimalMenaceKilled) < 1 then - player:setStorageValue(Storage.Quest.U12_90.PrimalOrdeal.Bosses.ThePrimalMenaceKilled, 1) + if player:getHazardSystemPoints() == hazardPoints then + gnompronaHazard:levelUp(player) + end end - if player:getHazardSystemPoints() == hazardPoints then - gnompronaHazard:levelUp(player) - end end diff --git a/data/libs/hazard_lib.lua b/data/libs/hazard_lib.lua index 77a31e0a7ee..fbae493eab2 100644 --- a/data/libs/hazard_lib.lua +++ b/data/libs/hazard_lib.lua @@ -33,12 +33,15 @@ function Hazard.getHazardPlayerAndPoints(self, damageMap) local hazardPoints = -1 for key, value in pairs(damageMap) do local player = Player(key) - local playerHazardPoints = player:getHazardSystemPoints() + if player then + local playerHazardPoints = player:getHazardSystemPoints() - if playerHazardPoints < hazardPoints or hazardPoints == -1 then - hazardPlayer = player - hazardPoints = playerHazardPoints + if playerHazardPoints < hazardPoints or hazardPoints == -1 then + hazardPlayer = player + hazardPoints = playerHazardPoints + end end + end return hazardPlayer, hazardPoints From f62cf69641055eea880b0996ad7a00a57b5fe394 Mon Sep 17 00:00:00 2001 From: Sebastian Nobbelin Date: Fri, 18 Aug 2023 17:50:55 +0200 Subject: [PATCH 07/17] feat: primal menace boss fight mechanics --- .../primal_ordeal_quest/the_primal_menace.lua | 303 +++++++++++++++--- .../scripts/hazard/primal.lua | 23 +- data/libs/hazard_lib.lua | 5 +- 3 files changed, 281 insertions(+), 50 deletions(-) diff --git a/data-otservbr-global/monster/quests/primal_ordeal_quest/the_primal_menace.lua b/data-otservbr-global/monster/quests/primal_ordeal_quest/the_primal_menace.lua index 0cf13ba6697..2c093a0e943 100644 --- a/data-otservbr-global/monster/quests/primal_ordeal_quest/the_primal_menace.lua +++ b/data-otservbr-global/monster/quests/primal_ordeal_quest/the_primal_menace.lua @@ -1,6 +1,55 @@ local mType = Game.createMonsterType("The Primal Menace") local monster = {} +local thePrimalMenaceConfig = { + Storage = { + Initialized = 1, + SpawnPos = 2, + NextPodSpawn = 3, + NextMonsterSpawn = 4, + PrimalBeasts = 5, -- List of monsters and when they were created in order to turn them into fungosaurus {monster, created} + }, + + -- Spawn area + SpawnRadius = 5, + + -- Monster spawn time + MonsterConfig = { + IntervalBase = 30, + IntervalReductionPer10PercentHp = 0.97, + IntervalReductionPerHazard = 0.985, + + CountBase = 4, + CountVarianceRate = 0.5, + CountGrowthPerHazard = 1.05, + CountMax = 7, + MonsterPool = { + "Emerald Tortoise", + "Beast Gore Horn", + "Beast Gorerilla", + "Headpecker", + "Beast Hulking Prehemoth", + "Mantosaurus", + "Nighthunter", + "Noxious Ripptor", + "Beast Sabretooth", + "Stalking Stalk", + "Sulphider", + } + }, + + PodConfig = { + IntervalBase = 22.5, + IntervalReductionPer10PercentHp = 0.97, + IntervalReductionPerHazard = 0.99, + + CountBase = 2, + CountVarianceRate = 0.5, + CountGrowthPerHazard = 1.1, + CountMax = 4, + }, +} + monster.description = "The Primal Menace" monster.experience = 80000 monster.outfit = { @@ -17,8 +66,8 @@ monster.events = { "ThePrimalMenaceDeath" } -monster.health = 1000000 -monster.maxHealth = 1000000 +monster.health = 650000 +monster.maxHealth = 650000 monster.race = "blood" monster.corpse = 39530 monster.speed = 180 @@ -53,22 +102,7 @@ monster.light = { color = 0 } -monster.summon = { - maxSummons = 6, - summons = { - {name = "Emerald Tortoise", chance = 2, interval = 2000, count = 6}, - {name = "Gore Horn", chance = 2, interval = 2000, count = 6}, - {name = "Gorerilla", chance = 2, interval = 2000, count = 6}, - {name = "Headpecker", chance = 2, interval = 2000, count = 6}, - {name = "Hulking Prehemoth", chance = 2, interval = 2000, count = 6}, - {name = "Mantosaurus", chance = 2, interval = 2000, count = 6}, - {name = "Nighthunter", chance = 2, interval = 2000, count = 6}, - {name = "Noxious Ripptor", chance = 2, interval = 2000, count = 6}, - {name = "Sabretooth", chance = 2, interval = 2000, count = 6}, - {name = "Stalking Stalk", chance = 2, interval = 2000, count = 6}, - {name = "Sulphider", chance = 2, interval = 2000, count = 6}, - } -} +monster.summon = {} monster.voices = { interval = 5000, @@ -76,16 +110,16 @@ monster.voices = { } monster.loot = { - {name = "primal bag", chance = 50}, + { name = "primal bag", chance = 50 }, } monster.attacks = { - {name ="melee", interval = 2000, chance = 85, minDamage = -0, maxDamage = -763}, - {name ="combat", interval = 4000, chance = 35, type = COMBAT_EARTHDAMAGE, minDamage = -1500, maxDamage = -2200, length = 10, spread = 3, effect = CONST_ME_CARNIPHILA, target = false}, - {name ="combat", interval = 2500, chance = 45, type = COMBAT_FIREDAMAGE, minDamage = -700, maxDamage = -1000, length = 10, spread = 3, effect = CONST_ME_HITBYFIRE, target = false}, - {name ="big death wave", interval = 3500, chance = 35, minDamage = -250, maxDamage = -300, target = false}, - {name ="combat", interval = 5000, chance = 40, type = COMBAT_ENERGYDAMAGE, effect = CONST_ME_ENERGYHIT, minDamage = -1200, maxDamage = -1300, range = 4, target = false}, - {name ="combat", interval = 2700, chance = 45, type = COMBAT_EARTHDAMAGE, shootEffect = CONST_ANI_POISON, effect = CONST_ANI_EARTH, minDamage = -600, maxDamage = -1800, range = 4, target = false}, + { name = "melee", interval = 2000, chance = 85, minDamage = -0, maxDamage = -763 }, + { name = "combat", interval = 4000, chance = 35, type = COMBAT_EARTHDAMAGE, minDamage = -1500, maxDamage = -2200, length = 10, spread = 3, effect = CONST_ME_CARNIPHILA, target = false }, + { name = "combat", interval = 2500, chance = 45, type = COMBAT_FIREDAMAGE, minDamage = -700, maxDamage = -1000, length = 10, spread = 3, effect = CONST_ME_HITBYFIRE, target = false }, + { name = "big death wave", interval = 3500, chance = 35, minDamage = -250, maxDamage = -300, target = false }, + { name = "combat", interval = 5000, chance = 40, type = COMBAT_ENERGYDAMAGE, effect = CONST_ME_ENERGYHIT, minDamage = -1200, maxDamage = -1300, range = 4, target = false }, + { name = "combat", interval = 2700, chance = 45, type = COMBAT_EARTHDAMAGE, shootEffect = CONST_ANI_POISON, effect = CONST_ANI_EARTH, minDamage = -600, maxDamage = -1800, range = 4, target = false }, } monster.defenses = { @@ -94,24 +128,213 @@ monster.defenses = { } monster.elements = { - {type = COMBAT_PHYSICALDAMAGE, percent = 0}, - {type = COMBAT_ENERGYDAMAGE, percent = -5}, - {type = COMBAT_EARTHDAMAGE, percent = 100}, - {type = COMBAT_FIREDAMAGE, percent = 5}, - {type = COMBAT_LIFEDRAIN, percent = 0}, - {type = COMBAT_MANADRAIN, percent = 0}, - {type = COMBAT_DROWNDAMAGE, percent = 0}, - {type = COMBAT_ICEDAMAGE, percent = 50}, - {type = COMBAT_HOLYDAMAGE , percent = 40}, - {type = COMBAT_DEATHDAMAGE , percent = 0} + { type = COMBAT_PHYSICALDAMAGE, percent = 0 }, + { type = COMBAT_ENERGYDAMAGE, percent = -5 }, + { type = COMBAT_EARTHDAMAGE, percent = 100 }, + { type = COMBAT_FIREDAMAGE, percent = 5 }, + { type = COMBAT_LIFEDRAIN, percent = 0 }, + { type = COMBAT_MANADRAIN, percent = 0 }, + { type = COMBAT_DROWNDAMAGE, percent = 0 }, + { type = COMBAT_ICEDAMAGE, percent = 50 }, + { type = COMBAT_HOLYDAMAGE, percent = 40 }, + { type = COMBAT_DEATHDAMAGE, percent = 0 } } monster.immunities = { - {type = "paralyze", condition = true}, - {type = "outfit", condition = false}, - {type = "invisible", condition = true}, - {type = "drunk", condition = true}, - {type = "bleed", condition = false} + { type = "paralyze", condition = true }, + { type = "outfit", condition = false }, + { type = "invisible", condition = true }, + { type = "drunk", condition = true }, + { type = "bleed", condition = false } } +local function initialize(monster) + if (monster:getStorageValue(thePrimalMenaceConfig.Storage.Initialized) == true) then + return + end + + monster:setStorageValue(thePrimalMenaceConfig.Storage.SpawnPos, monster:getPosition()) + monster:setStorageValue(thePrimalMenaceConfig.Storage.NextPodSpawn, os.time() + 5) + monster:setStorageValue(thePrimalMenaceConfig.Storage.NextMonsterSpawn, os.time() + 10) + monster:setStorageValue(thePrimalMenaceConfig.Storage.PrimalBeasts, {}) + + monster:setStorageValue(thePrimalMenaceConfig.Storage.Initialized, true) +end + +-- Functions for the fight +mType.onAppear = function(monster, creature) + if monster:getId() == creature:getId() then + initialize(monster) + end + + if monster:getType():isRewardBoss() then + monster:setReward(true) + end +end + +local function getHazardPoints(monster) + local hazard = Hazard.getByName("Gnomprona Gardens") + + local _, hazardPoints = hazard:getHazardPlayerAndPoints(monster:getDamageMap()) + return hazardPoints +end + +local function setNextTimeToSpawn(monster, spawnStorageValue, spawnConfig, hazardPoints) + local intervalBase = spawnConfig.IntervalBase + local intervalReductionPer10PercentHp = spawnConfig.IntervalReductionPer10PercentHp + local intervalReductionPerHazard = spawnConfig.IntervalReductionPerHazard + + local maxHealth = monster:getMaxHealth() + local currentHealth = monster:getHealth() + local count10PercentHpMissing = math.floor((maxHealth - currentHealth) / maxHealth * 10) + + local interval = intervalBase * (intervalReductionPer10PercentHp ^ count10PercentHpMissing) * (intervalReductionPerHazard ^ hazardPoints) + + local nextTimeToSpawn = os.time() + interval + monster:setStorageValue(spawnStorageValue, nextTimeToSpawn) +end + +local function spawnCount(spawnConfig, hazardPoints) + local countBase = spawnConfig.CountBase + local countVarianceRate = spawnConfig.CountVarianceRate + local countGrowthPerHazard = spawnConfig.CountGrowthPerHazard + local countMax = spawnConfig.CountMax + + local directions = { -1, 1 } + local variance = math.random() * countVarianceRate * directions[math.random(#directions)] + local count = math.floor(countBase * (countGrowthPerHazard ^ hazardPoints) + variance) + + return math.min(count, countMax) +end + +local function getSpawnPosition(monster) + local attempts = 20 + local attempt = 0 + local spawnPosition = nil + local radius = thePrimalMenaceConfig.SpawnRadius + local centerPos = monster:getStorageValue(thePrimalMenaceConfig.Storage.SpawnPos) + + while (not spawnPosition or attempt < attempts) do + + local centerX = centerPos.x + local centerY = centerPos.y + + local directions = { -1, 1 } + local xCoord = centerX + math.ceil(math.random() * radius) * directions[math.random(#directions)] + local yCoord = centerY + math.ceil(math.random() * radius) * directions[math.random(#directions)] + + local positionAttempt = Position(xCoord, yCoord, centerPos.z) + local spawnTile = Tile(positionAttempt) + if (spawnTile and spawnTile:getCreatureCount() == 0 and not spawnTile:hasProperty(CONST_PROP_IMMOVABLEBLOCKSOLID)) then + spawnPosition = positionAttempt + end + attempt = attempt + 1 + end + + -- Fallback + if not spawnPosition then + spawnPosition = centerPos + end + + return spawnPosition +end + +local function spawnTimer(monster, spawnPosition, spawnCallback) + local time_to_spawn = 3 + for i = 1, time_to_spawn do + addEvent(function() + spawnPosition:sendMagicEffect(CONST_ME_TELEPORT) + end, i * 1000) + end + addEvent(function() + spawnCallback(monster, spawnPosition) + end, time_to_spawn * 1000) +end + +local function spawnPod(monster, position) + createPrimalPod(position) +end + +local function spawnPods(monster, hazardPoints) + local count = spawnCount(thePrimalMenaceConfig.PodConfig, hazardPoints) + for i = 1, count do + local spawnPosition = getSpawnPosition(monster) + spawnTimer(monster, spawnPosition, spawnPod) + end +end + +local function handlePodSpawn(monster, hazardPoints) + local nextSpawn = monster:getStorageValue(thePrimalMenaceConfig.Storage.NextPodSpawn) + if (nextSpawn - os.time() < 0) then + spawnPods(monster, hazardPoints) + + setNextTimeToSpawn(monster, thePrimalMenaceConfig.Storage.NextPodSpawn, thePrimalMenaceConfig.PodConfig, hazardPoints) + end +end + +local function spawnMonster(monster, spawnPosition) + local randomMonsterIndex = math.random(#thePrimalMenaceConfig.MonsterConfig.MonsterPool) + local primalBeastEntry = { + Monster = Game.createMonster(thePrimalMenaceConfig.MonsterConfig.MonsterPool[randomMonsterIndex], spawnPosition), + Created = os.time() + } + + local primalBeasts = monster:getStorageValue(thePrimalMenaceConfig.Storage.PrimalBeasts) + table.insert(primalBeasts, primalBeastEntry) + monster:setStorageValue(thePrimalMenaceConfig.Storage.PrimalBeasts, primalBeasts) +end + +local function spawnMonsters(monster, hazardPoints) + local count = spawnCount(thePrimalMenaceConfig.MonsterConfig, hazardPoints) + for i = 1, count do + local spawnPosition = getSpawnPosition(monster) + spawnTimer(monster, spawnPosition, spawnMonster) + end +end + +local function handleMonsterSpawn(monster, hazardPoints) + local nextSpawn = monster:getStorageValue(thePrimalMenaceConfig.Storage.NextMonsterSpawn) + if (nextSpawn - os.time() < 0) then + spawnMonsters(monster, hazardPoints) + + setNextTimeToSpawn(monster, thePrimalMenaceConfig.Storage.NextMonsterSpawn, thePrimalMenaceConfig.MonsterConfig, hazardPoints) + end +end + +local function handlePrimalBeasts(monster) + primalBeasts = monster:getStorageValue(thePrimalMenaceConfig.Storage.PrimalBeasts) + indexesToRemove = {} + + for index, beastData in pairs(primalBeasts) do + local monster = beastData.Monster + local created = beastData.Created + + if (os.time() - created > 20 and monster:getHealth() > 0) then + local position = monster:getPosition() + monster:remove() + table.insert(indexesToRemove, index) + Game.createMonster("Fungosaurus", position) + end + end + + for i = #indexesToRemove, 1, -1 do + table.remove(primalBeasts, i) + end + + monster:setStorageValue(thePrimalMenaceConfig.Storage.PrimalBeasts, primalBeasts) +end + +mType.onThink = function(monster, interval) + if (monster:getStorageValue(thePrimalMenaceConfig.Storage.Initialized) == -1) then + initialize(monster) + end + + local hazardPoints = getHazardPoints(monster) + + handleMonsterSpawn(monster, hazardPoints) + handlePodSpawn(monster, hazardPoints) + + handlePrimalBeasts(monster) +end + mType:register(monster) diff --git a/data-otservbr-global/scripts/hazard/primal.lua b/data-otservbr-global/scripts/hazard/primal.lua index 49931e759f2..7e0279118c1 100644 --- a/data-otservbr-global/scripts/hazard/primal.lua +++ b/data-otservbr-global/scripts/hazard/primal.lua @@ -62,6 +62,16 @@ local spawnFungosaurus = function(position) end end +-- Used by the primal menace +function createPrimalPod(position) + local primalPod = Game.createItem(ITEM_PRIMAL_POD, 1, position) + if primalPod then + primalPod:setCustomAttribute("HazardSystem_PodTimer", os.time() * 1000) + local podPos = primalPod:getPosition() + addEvent(spawnFungosaurus, configManager.getNumber(configKeys.HAZARD_PODS_TIME_TO_SPAWN), podPos) + end +end + local primalKill = CreatureEvent("PrimalHazardKill") function primalKill.onKill(_player, creature) if not configManager.getBoolean(configKeys.TOGGLE_HAZARDSYSTEM) then @@ -86,21 +96,16 @@ function primalKill.onKill(_player, creature) -- Pod local chanceTo = math.random(1, 10000) if chanceTo <= (points * configManager.getNumber(configKeys.HAZARD_PODS_DROP_MULTIPLIER)) then - local closesestPosition = player:getClosestFreePosition(monster:getPosition(), 4, true) - local primalPod = Game.createItem(ITEM_PRIMAL_POD, 1, closesestPosition.x == 0 and monster:getPosition() or closesestPosition) - if primalPod then - primalPod:setCustomAttribute("HazardSystem_PodTimer", os.time() * 1000) - local podPos = primalPod:getPosition() - addEvent(spawnFungosaurus, configManager.getNumber(configKeys.HAZARD_PODS_TIME_TO_SPAWN), podPos) - end + local closestFreePosition = player:getClosestFreePosition(monster:getPosition(), 4, true) + createPrimalPod(closestFreePosition) return true end -- Plunder patriarch chanceTo = math.random(1, 10000) if chanceTo <= (points * configManager.getNumber(configKeys.HAZARD_SPAWN_PLUNDER_MULTIPLIER)) then - local closesestPosition = player:getClosestFreePosition(monster:getPosition(), 4, true) - local monster = Game.createMonster("Plunder Patriarch", closesestPosition.x == 0 and monster:getPosition() or closesestPosition, false, true) + local closestFreePosition = player:getClosestFreePosition(monster:getPosition(), 4, true) + local monster = Game.createMonster("Plunder Patriarch", closestFreePosition.x == 0 and monster:getPosition() or closestFreePosition, false, true) if monster then monster:say("The Plunder Patriarch rises from the ashes.") end diff --git a/data/libs/hazard_lib.lua b/data/libs/hazard_lib.lua index fbae493eab2..3d461471c52 100644 --- a/data/libs/hazard_lib.lua +++ b/data/libs/hazard_lib.lua @@ -41,11 +41,14 @@ function Hazard.getHazardPlayerAndPoints(self, damageMap) hazardPoints = playerHazardPoints end end + end + if hazardPoints == -1 then + hazardPoints = 0 end return hazardPlayer, hazardPoints -end + end function Hazard.getPlayerCurrentLevel(self, player) return player:getStorageValue(self.storageCurrent) < 0 and 0 or player:getStorageValue(self.storageCurrent) From c4ddbc0d71d6bd118e7954ce9d97f3cfd54bc010 Mon Sep 17 00:00:00 2001 From: Sebastian Nobbelin Date: Fri, 18 Aug 2023 18:29:12 +0200 Subject: [PATCH 08/17] fix killing monsters causing conversion to fungusaurus to fail --- .../monster/quests/primal_ordeal_quest/the_primal_menace.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/data-otservbr-global/monster/quests/primal_ordeal_quest/the_primal_menace.lua b/data-otservbr-global/monster/quests/primal_ordeal_quest/the_primal_menace.lua index 2c093a0e943..4ff5c30b01f 100644 --- a/data-otservbr-global/monster/quests/primal_ordeal_quest/the_primal_menace.lua +++ b/data-otservbr-global/monster/quests/primal_ordeal_quest/the_primal_menace.lua @@ -308,8 +308,9 @@ local function handlePrimalBeasts(monster) for index, beastData in pairs(primalBeasts) do local monster = beastData.Monster local created = beastData.Created - - if (os.time() - created > 20 and monster:getHealth() > 0) then + if not monster:getHealth() then + table.insert(indexesToRemove, index) + elseif (os.time() - created > 20 and monster:getHealth() > 0) then local position = monster:getPosition() monster:remove() table.insert(indexesToRemove, index) From 6517acf98d786914fbf0924dcff5d9036790e711 Mon Sep 17 00:00:00 2001 From: Sebastian Nobbelin Date: Fri, 18 Aug 2023 23:05:57 +0200 Subject: [PATCH 09/17] added logs for live debugging --- .../primal_ordeal_quest/the_primal_menace.lua | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/data-otservbr-global/monster/quests/primal_ordeal_quest/the_primal_menace.lua b/data-otservbr-global/monster/quests/primal_ordeal_quest/the_primal_menace.lua index 4ff5c30b01f..98b94ca1084 100644 --- a/data-otservbr-global/monster/quests/primal_ordeal_quest/the_primal_menace.lua +++ b/data-otservbr-global/monster/quests/primal_ordeal_quest/the_primal_menace.lua @@ -208,13 +208,13 @@ local function spawnCount(spawnConfig, hazardPoints) end local function getSpawnPosition(monster) - local attempts = 20 + local attempts = 6 local attempt = 0 local spawnPosition = nil local radius = thePrimalMenaceConfig.SpawnRadius local centerPos = monster:getStorageValue(thePrimalMenaceConfig.Storage.SpawnPos) - while (not spawnPosition or attempt < attempts) do + while (not spawnPosition and attempt < attempts) do local centerX = centerPos.x local centerY = centerPos.y @@ -229,6 +229,7 @@ local function getSpawnPosition(monster) spawnPosition = positionAttempt end attempt = attempt + 1 + Spdlog.info("Attempts: " .. attempt) end -- Fallback @@ -309,6 +310,7 @@ local function handlePrimalBeasts(monster) local monster = beastData.Monster local created = beastData.Created if not monster:getHealth() then + Spdlog.info("Removing monster that has dissappeared") table.insert(indexesToRemove, index) elseif (os.time() - created > 20 and monster:getHealth() > 0) then local position = monster:getPosition() @@ -318,8 +320,11 @@ local function handlePrimalBeasts(monster) end end + Spdlog.info("Nbr of indexes to remove: " .. #indexesToRemove) for i = #indexesToRemove, 1, -1 do - table.remove(primalBeasts, i) + local indexToRemove = indexesToRemove[i] + table.remove(primalBeasts, indexToRemove) + Spdlog.info("Removed index: " .. indexesToRemove) end monster:setStorageValue(thePrimalMenaceConfig.Storage.PrimalBeasts, primalBeasts) @@ -330,11 +335,16 @@ mType.onThink = function(monster, interval) initialize(monster) end + Spdlog.info("hazardPoints: " .. hazardPoints) local hazardPoints = getHazardPoints(monster) + Spdlog.info("handleMonsterSpawn: " .. handleMonsterSpawn) handleMonsterSpawn(monster, hazardPoints) + + Spdlog.info("handlePodSpawn: " .. handlePodSpawn) handlePodSpawn(monster, hazardPoints) + Spdlog.info("handlePrimalBeasts: " .. handlePrimalBeasts) handlePrimalBeasts(monster) end From 9e4796258906eebe522b45cd315ad7cb27fd4711 Mon Sep 17 00:00:00 2001 From: Sebastian Nobbelin Date: Fri, 18 Aug 2023 23:11:24 +0200 Subject: [PATCH 10/17] fixed some logs --- .../quests/primal_ordeal_quest/the_primal_menace.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/data-otservbr-global/monster/quests/primal_ordeal_quest/the_primal_menace.lua b/data-otservbr-global/monster/quests/primal_ordeal_quest/the_primal_menace.lua index 98b94ca1084..099e52cc0ab 100644 --- a/data-otservbr-global/monster/quests/primal_ordeal_quest/the_primal_menace.lua +++ b/data-otservbr-global/monster/quests/primal_ordeal_quest/the_primal_menace.lua @@ -335,16 +335,16 @@ mType.onThink = function(monster, interval) initialize(monster) end - Spdlog.info("hazardPoints: " .. hazardPoints) local hazardPoints = getHazardPoints(monster) + Spdlog.info("hazardPoints: " .. hazardPoints) - Spdlog.info("handleMonsterSpawn: " .. handleMonsterSpawn) + Spdlog.info("handleMonsterSpawn") handleMonsterSpawn(monster, hazardPoints) - Spdlog.info("handlePodSpawn: " .. handlePodSpawn) + Spdlog.info("handlePodSpawn") handlePodSpawn(monster, hazardPoints) - Spdlog.info("handlePrimalBeasts: " .. handlePrimalBeasts) + Spdlog.info("handlePrimalBeasts") handlePrimalBeasts(monster) end From 84f79bef52f102f29a321527a1d4f5b6946ca599 Mon Sep 17 00:00:00 2001 From: Sebastian Nobbelin Date: Fri, 18 Aug 2023 23:39:19 +0200 Subject: [PATCH 11/17] fixed additional logging --- .../quests/primal_ordeal_quest/the_primal_menace.lua | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/data-otservbr-global/monster/quests/primal_ordeal_quest/the_primal_menace.lua b/data-otservbr-global/monster/quests/primal_ordeal_quest/the_primal_menace.lua index 099e52cc0ab..1a6269d54ad 100644 --- a/data-otservbr-global/monster/quests/primal_ordeal_quest/the_primal_menace.lua +++ b/data-otservbr-global/monster/quests/primal_ordeal_quest/the_primal_menace.lua @@ -229,7 +229,6 @@ local function getSpawnPosition(monster) spawnPosition = positionAttempt end attempt = attempt + 1 - Spdlog.info("Attempts: " .. attempt) end -- Fallback @@ -312,7 +311,11 @@ local function handlePrimalBeasts(monster) if not monster:getHealth() then Spdlog.info("Removing monster that has dissappeared") table.insert(indexesToRemove, index) + elseif monster:getHealth() == 0 then + Spdlog.info("Removing dead monster") + table.insert(indexesToRemove, index) elseif (os.time() - created > 20 and monster:getHealth() > 0) then + Spdlog.info("Converting mob to fungosaurus") local position = monster:getPosition() monster:remove() table.insert(indexesToRemove, index) @@ -320,11 +323,12 @@ local function handlePrimalBeasts(monster) end end - Spdlog.info("Nbr of indexes to remove: " .. #indexesToRemove) + Spdlog.info("Size of primal beasts: " .. #primalBeasts) + Spdlog.info("Nbr of indexes to remove: " .. #indexesToRemove) for i = #indexesToRemove, 1, -1 do local indexToRemove = indexesToRemove[i] table.remove(primalBeasts, indexToRemove) - Spdlog.info("Removed index: " .. indexesToRemove) + Spdlog.info("Removed index: " .. #indexesToRemove) end monster:setStorageValue(thePrimalMenaceConfig.Storage.PrimalBeasts, primalBeasts) From ea79a1d5eb3698da024085e2ada1c8a841657405 Mon Sep 17 00:00:00 2001 From: Sebastian Nobbelin Date: Sat, 19 Aug 2023 01:13:15 +0200 Subject: [PATCH 12/17] rebalanced and removed info --- .../primal_ordeal_quest/the_primal_menace.lua | 41 ++++++++----------- 1 file changed, 16 insertions(+), 25 deletions(-) diff --git a/data-otservbr-global/monster/quests/primal_ordeal_quest/the_primal_menace.lua b/data-otservbr-global/monster/quests/primal_ordeal_quest/the_primal_menace.lua index 1a6269d54ad..80775e014a3 100644 --- a/data-otservbr-global/monster/quests/primal_ordeal_quest/the_primal_menace.lua +++ b/data-otservbr-global/monster/quests/primal_ordeal_quest/the_primal_menace.lua @@ -16,13 +16,15 @@ local thePrimalMenaceConfig = { -- Monster spawn time MonsterConfig = { IntervalBase = 30, - IntervalReductionPer10PercentHp = 0.97, + IntervalReductionPer10PercentHp = 0.98, IntervalReductionPerHazard = 0.985, CountBase = 4, CountVarianceRate = 0.5, CountGrowthPerHazard = 1.05, - CountMax = 7, + CountMax = 6, + + HpRateOnSpawn = 0.7, MonsterPool = { "Emerald Tortoise", "Beast Gore Horn", @@ -39,9 +41,9 @@ local thePrimalMenaceConfig = { }, PodConfig = { - IntervalBase = 22.5, - IntervalReductionPer10PercentHp = 0.97, - IntervalReductionPerHazard = 0.99, + IntervalBase = 30, + IntervalReductionPer10PercentHp = 0.98, + IntervalReductionPerHazard = 0.985, CountBase = 2, CountVarianceRate = 0.5, @@ -66,8 +68,8 @@ monster.events = { "ThePrimalMenaceDeath" } -monster.health = 650000 -monster.maxHealth = 650000 +monster.health = 400000 +monster.maxHealth = 400000 monster.race = "blood" monster.corpse = 39530 monster.speed = 180 @@ -154,7 +156,7 @@ local function initialize(monster) end monster:setStorageValue(thePrimalMenaceConfig.Storage.SpawnPos, monster:getPosition()) - monster:setStorageValue(thePrimalMenaceConfig.Storage.NextPodSpawn, os.time() + 5) + monster:setStorageValue(thePrimalMenaceConfig.Storage.NextPodSpawn, os.time() + 20) monster:setStorageValue(thePrimalMenaceConfig.Storage.NextMonsterSpawn, os.time() + 10) monster:setStorageValue(thePrimalMenaceConfig.Storage.PrimalBeasts, {}) @@ -278,6 +280,8 @@ local function spawnMonster(monster, spawnPosition) Monster = Game.createMonster(thePrimalMenaceConfig.MonsterConfig.MonsterPool[randomMonsterIndex], spawnPosition), Created = os.time() } + local monsterMaxHealth = primalBeastEntry.Monster:getMaxHealth() + primalBeastEntry.Monster:setHealth(monsterMaxHealth * thePrimalMenaceConfig.MonsterConfig.HpRateOnSpawn) local primalBeasts = monster:getStorageValue(thePrimalMenaceConfig.Storage.PrimalBeasts) table.insert(primalBeasts, primalBeastEntry) @@ -308,27 +312,21 @@ local function handlePrimalBeasts(monster) for index, beastData in pairs(primalBeasts) do local monster = beastData.Monster local created = beastData.Created - if not monster:getHealth() then - Spdlog.info("Removing monster that has dissappeared") - table.insert(indexesToRemove, index) - elseif monster:getHealth() == 0 then - Spdlog.info("Removing dead monster") + if not monster:getHealth() or monster:getHealth() == 0 then table.insert(indexesToRemove, index) elseif (os.time() - created > 20 and monster:getHealth() > 0) then - Spdlog.info("Converting mob to fungosaurus") local position = monster:getPosition() monster:remove() table.insert(indexesToRemove, index) - Game.createMonster("Fungosaurus", position) + if position then + Game.createMonster("Fungosaurus", position) + end end end - Spdlog.info("Size of primal beasts: " .. #primalBeasts) - Spdlog.info("Nbr of indexes to remove: " .. #indexesToRemove) for i = #indexesToRemove, 1, -1 do local indexToRemove = indexesToRemove[i] table.remove(primalBeasts, indexToRemove) - Spdlog.info("Removed index: " .. #indexesToRemove) end monster:setStorageValue(thePrimalMenaceConfig.Storage.PrimalBeasts, primalBeasts) @@ -340,15 +338,8 @@ mType.onThink = function(monster, interval) end local hazardPoints = getHazardPoints(monster) - Spdlog.info("hazardPoints: " .. hazardPoints) - - Spdlog.info("handleMonsterSpawn") handleMonsterSpawn(monster, hazardPoints) - - Spdlog.info("handlePodSpawn") handlePodSpawn(monster, hazardPoints) - - Spdlog.info("handlePrimalBeasts") handlePrimalBeasts(monster) end From dcd8f9f587a905405adf80f72be312a407ab3ccd Mon Sep 17 00:00:00 2001 From: Sebastian Nobbelin Date: Wed, 23 Aug 2023 21:16:01 +0200 Subject: [PATCH 13/17] changes based on feedback --- .../primal_ordeal_quest/the_primal_menace.lua | 33 ++++++++++--------- .../the_primal_ordeal/magma_bubble_death.lua | 4 +++ .../the_primal_menace_killed.lua | 4 +++ 3 files changed, 26 insertions(+), 15 deletions(-) diff --git a/data-otservbr-global/monster/quests/primal_ordeal_quest/the_primal_menace.lua b/data-otservbr-global/monster/quests/primal_ordeal_quest/the_primal_menace.lua index 80775e014a3..af93fa00452 100644 --- a/data-otservbr-global/monster/quests/primal_ordeal_quest/the_primal_menace.lua +++ b/data-otservbr-global/monster/quests/primal_ordeal_quest/the_primal_menace.lua @@ -104,8 +104,6 @@ monster.light = { color = 0 } -monster.summon = {} - monster.voices = { interval = 5000, chance = 10, @@ -151,7 +149,7 @@ monster.immunities = { } local function initialize(monster) - if (monster:getStorageValue(thePrimalMenaceConfig.Storage.Initialized) == true) then + if monster:getStorageValue(thePrimalMenaceConfig.Storage.Initialized) == true then return end @@ -216,7 +214,7 @@ local function getSpawnPosition(monster) local radius = thePrimalMenaceConfig.SpawnRadius local centerPos = monster:getStorageValue(thePrimalMenaceConfig.Storage.SpawnPos) - while (not spawnPosition and attempt < attempts) do + while not spawnPosition and attempt < attempts do local centerX = centerPos.x local centerY = centerPos.y @@ -227,7 +225,7 @@ local function getSpawnPosition(monster) local positionAttempt = Position(xCoord, yCoord, centerPos.z) local spawnTile = Tile(positionAttempt) - if (spawnTile and spawnTile:getCreatureCount() == 0 and not spawnTile:hasProperty(CONST_PROP_IMMOVABLEBLOCKSOLID)) then + if spawnTile and spawnTile:getCreatureCount() == 0 and not spawnTile:hasProperty(CONST_PROP_IMMOVABLEBLOCKSOLID) then spawnPosition = positionAttempt end attempt = attempt + 1 @@ -241,7 +239,7 @@ local function getSpawnPosition(monster) return spawnPosition end -local function spawnTimer(monster, spawnPosition, spawnCallback) +local function spawnTimer(monsterId, spawnPosition, spawnCallback) local time_to_spawn = 3 for i = 1, time_to_spawn do addEvent(function() @@ -249,11 +247,11 @@ local function spawnTimer(monster, spawnPosition, spawnCallback) end, i * 1000) end addEvent(function() - spawnCallback(monster, spawnPosition) + spawnCallback(monsterId, spawnPosition) end, time_to_spawn * 1000) end -local function spawnPod(monster, position) +local function spawnPod(monsterId, position) createPrimalPod(position) end @@ -261,20 +259,25 @@ local function spawnPods(monster, hazardPoints) local count = spawnCount(thePrimalMenaceConfig.PodConfig, hazardPoints) for i = 1, count do local spawnPosition = getSpawnPosition(monster) - spawnTimer(monster, spawnPosition, spawnPod) + spawnTimer(monster:getId(), spawnPosition, spawnPod) end end local function handlePodSpawn(monster, hazardPoints) local nextSpawn = monster:getStorageValue(thePrimalMenaceConfig.Storage.NextPodSpawn) - if (nextSpawn - os.time() < 0) then + if nextSpawn - os.time() < 0 then spawnPods(monster, hazardPoints) setNextTimeToSpawn(monster, thePrimalMenaceConfig.Storage.NextPodSpawn, thePrimalMenaceConfig.PodConfig, hazardPoints) end end -local function spawnMonster(monster, spawnPosition) +local function spawnMonster(monsterId, spawnPosition) + local monster = Monster(monsterId) + if not monster then + return + end + local randomMonsterIndex = math.random(#thePrimalMenaceConfig.MonsterConfig.MonsterPool) local primalBeastEntry = { Monster = Game.createMonster(thePrimalMenaceConfig.MonsterConfig.MonsterPool[randomMonsterIndex], spawnPosition), @@ -292,13 +295,13 @@ local function spawnMonsters(monster, hazardPoints) local count = spawnCount(thePrimalMenaceConfig.MonsterConfig, hazardPoints) for i = 1, count do local spawnPosition = getSpawnPosition(monster) - spawnTimer(monster, spawnPosition, spawnMonster) + spawnTimer(monster:getId(), spawnPosition, spawnMonster) end end local function handleMonsterSpawn(monster, hazardPoints) local nextSpawn = monster:getStorageValue(thePrimalMenaceConfig.Storage.NextMonsterSpawn) - if (nextSpawn - os.time() < 0) then + if nextSpawn - os.time() < 0 then spawnMonsters(monster, hazardPoints) setNextTimeToSpawn(monster, thePrimalMenaceConfig.Storage.NextMonsterSpawn, thePrimalMenaceConfig.MonsterConfig, hazardPoints) @@ -314,7 +317,7 @@ local function handlePrimalBeasts(monster) local created = beastData.Created if not monster:getHealth() or monster:getHealth() == 0 then table.insert(indexesToRemove, index) - elseif (os.time() - created > 20 and monster:getHealth() > 0) then + elseif os.time() - created > 20 and monster:getHealth() > 0 then local position = monster:getPosition() monster:remove() table.insert(indexesToRemove, index) @@ -333,7 +336,7 @@ local function handlePrimalBeasts(monster) end mType.onThink = function(monster, interval) - if (monster:getStorageValue(thePrimalMenaceConfig.Storage.Initialized) == -1) then + if monster:getStorageValue(thePrimalMenaceConfig.Storage.Initialized) == -1 then initialize(monster) end diff --git a/data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/magma_bubble_death.lua b/data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/magma_bubble_death.lua index f12fd3092b7..953918d959e 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/magma_bubble_death.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/magma_bubble_death.lua @@ -1,5 +1,9 @@ local magmaBubbleDeath = CreatureEvent("MagmaBubbleDeath") function magmaBubbleDeath.onDeath(creature, corpse, killer, mostDamage, unjustified, mostDamage_unjustified) + if not creature then + return + end + local damageMap = creature:getMonster():getDamageMap() for key, value in pairs(damageMap) do diff --git a/data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/the_primal_menace_killed.lua b/data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/the_primal_menace_killed.lua index d4a13568369..75cb6a1e7d9 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/the_primal_menace_killed.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/the_primal_menace_killed.lua @@ -1,6 +1,10 @@ local thePrimalMenaceDeath = CreatureEvent("ThePrimalMenaceDeath") function thePrimalMenaceDeath.onDeath(creature, corpse, killer, mostDamage, unjustified, mostDamage_unjustified) + if not creature then + return + end + local damageMap = creature:getMonster():getDamageMap() local gnompronaHazard = Hazard.getByName("Gnomprona Gardens") local _, hazardPoints = gnompronaHazard:getHazardPlayerAndPoints(damageMap) From 518fe251102f0fb2e6476a7803943aaa278dca27 Mon Sep 17 00:00:00 2001 From: Sebastian Nobbelin Date: Wed, 23 Aug 2023 21:35:47 +0200 Subject: [PATCH 14/17] updates due to main branch changes --- .../monster/quests/primal_ordeal_quest/the_primal_menace.lua | 2 +- .../quests/the_primal_ordeal/the_primal_menace_killed.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/data-otservbr-global/monster/quests/primal_ordeal_quest/the_primal_menace.lua b/data-otservbr-global/monster/quests/primal_ordeal_quest/the_primal_menace.lua index af93fa00452..9dfd3728ae7 100644 --- a/data-otservbr-global/monster/quests/primal_ordeal_quest/the_primal_menace.lua +++ b/data-otservbr-global/monster/quests/primal_ordeal_quest/the_primal_menace.lua @@ -173,7 +173,7 @@ mType.onAppear = function(monster, creature) end local function getHazardPoints(monster) - local hazard = Hazard.getByName("Gnomprona Gardens") + local hazard = Hazard.getByName("hazard:gnomprona-gardens") local _, hazardPoints = hazard:getHazardPlayerAndPoints(monster:getDamageMap()) return hazardPoints diff --git a/data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/the_primal_menace_killed.lua b/data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/the_primal_menace_killed.lua index 75cb6a1e7d9..dfafa214a96 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/the_primal_menace_killed.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/the_primal_menace_killed.lua @@ -6,7 +6,7 @@ function thePrimalMenaceDeath.onDeath(creature, corpse, killer, mostDamage, unju end local damageMap = creature:getMonster():getDamageMap() - local gnompronaHazard = Hazard.getByName("Gnomprona Gardens") + local gnompronaHazard = Hazard.getByName("hazard:gnomprona-gardens") local _, hazardPoints = gnompronaHazard:getHazardPlayerAndPoints(damageMap) for key, value in pairs(damageMap) do From 3f32f6d1930d84e9cc6dbb9333b2ee61a7147efa Mon Sep 17 00:00:00 2001 From: Luan Santos Date: Sat, 26 Aug 2023 12:12:10 -0700 Subject: [PATCH 15/17] small fixes --- .../quests/primal_ordeal_quest/the_primal_menace.lua | 12 ++++++------ data-otservbr-global/npc/gnomadness.lua | 2 +- .../the_primal_ordeal/the_primal_menace_killed.lua | 12 +++++------- data-otservbr-global/scripts/hazard/primal.lua | 2 +- data/libs/hazard_lib.lua | 11 +++++------ 5 files changed, 18 insertions(+), 21 deletions(-) diff --git a/data-otservbr-global/monster/quests/primal_ordeal_quest/the_primal_menace.lua b/data-otservbr-global/monster/quests/primal_ordeal_quest/the_primal_menace.lua index 9dfd3728ae7..9f93a4d043a 100644 --- a/data-otservbr-global/monster/quests/primal_ordeal_quest/the_primal_menace.lua +++ b/data-otservbr-global/monster/quests/primal_ordeal_quest/the_primal_menace.lua @@ -124,8 +124,8 @@ monster.attacks = { monster.defenses = { defense = 80, - armor = 100 -} + armor = 100, + mitigation = 3.72, monster.elements = { { type = COMBAT_PHYSICALDAMAGE, percent = 0 }, @@ -173,7 +173,8 @@ mType.onAppear = function(monster, creature) end local function getHazardPoints(monster) - local hazard = Hazard.getByName("hazard:gnomprona-gardens") + local hazard = Hazard.getByName("hazard.gnomprona-gardens") + if not hazard then return 0 end local _, hazardPoints = hazard:getHazardPlayerAndPoints(monster:getDamageMap()) return hazardPoints @@ -215,7 +216,6 @@ local function getSpawnPosition(monster) local centerPos = monster:getStorageValue(thePrimalMenaceConfig.Storage.SpawnPos) while not spawnPosition and attempt < attempts do - local centerX = centerPos.x local centerY = centerPos.y @@ -309,8 +309,8 @@ local function handleMonsterSpawn(monster, hazardPoints) end local function handlePrimalBeasts(monster) - primalBeasts = monster:getStorageValue(thePrimalMenaceConfig.Storage.PrimalBeasts) - indexesToRemove = {} + local primalBeasts = monster:getStorageValue(thePrimalMenaceConfig.Storage.PrimalBeasts) + local indexesToRemove = {} for index, beastData in pairs(primalBeasts) do local monster = beastData.Monster diff --git a/data-otservbr-global/npc/gnomadness.lua b/data-otservbr-global/npc/gnomadness.lua index 7a011889fe1..deab21771a7 100644 --- a/data-otservbr-global/npc/gnomadness.lua +++ b/data-otservbr-global/npc/gnomadness.lua @@ -66,7 +66,7 @@ local function creatureSayCallback(npc, creature, type, message) return false end - local hazard = Hazard.getByName("hazard:gnomprona-gardens") + local hazard = Hazard.getByName("hazard.gnomprona-gardens") local current = hazard:getPlayerCurrentLevel(player) local maximum = hazard:getPlayerMaxLevel(player) diff --git a/data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/the_primal_menace_killed.lua b/data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/the_primal_menace_killed.lua index dfafa214a96..62abf7edc6c 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/the_primal_menace_killed.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/the_primal_ordeal/the_primal_menace_killed.lua @@ -6,8 +6,9 @@ function thePrimalMenaceDeath.onDeath(creature, corpse, killer, mostDamage, unju end local damageMap = creature:getMonster():getDamageMap() - local gnompronaHazard = Hazard.getByName("hazard:gnomprona-gardens") - local _, hazardPoints = gnompronaHazard:getHazardPlayerAndPoints(damageMap) + local hazard = Hazard.getByName("hazard.gnomprona-gardens") + if not hazard then return end + local _, hazardPoints = hazard:getHazardPlayerAndPoints(damageMap) for key, value in pairs(damageMap) do local player = Player(key) @@ -16,14 +17,11 @@ function thePrimalMenaceDeath.onDeath(creature, corpse, killer, mostDamage, unju player:setStorageValue(Storage.Quest.U12_90.PrimalOrdeal.Bosses.ThePrimalMenaceKilled, 1) end - if player:getHazardSystemPoints() == hazardPoints then - gnompronaHazard:levelUp(player) + if hazard:getPlayerMaxLevel(player) == hazardPoints then + hazard:levelUp(player) end end - end - - end thePrimalMenaceDeath:register() diff --git a/data-otservbr-global/scripts/hazard/primal.lua b/data-otservbr-global/scripts/hazard/primal.lua index 80946b3d340..ed45d26fd2e 100644 --- a/data-otservbr-global/scripts/hazard/primal.lua +++ b/data-otservbr-global/scripts/hazard/primal.lua @@ -1,5 +1,5 @@ local hazard = Hazard.new({ - name = "hazard:gnomprona-gardens", + name = "hazard.gnomprona-gardens", from = Position(33502, 32740,13), to = Position(33796, 32996, 15), maxLevel = 12, diff --git a/data/libs/hazard_lib.lua b/data/libs/hazard_lib.lua index ff8415d34be..24f2159ff0d 100644 --- a/data/libs/hazard_lib.lua +++ b/data/libs/hazard_lib.lua @@ -23,14 +23,13 @@ function Hazard.new(prototype) return instance end -function Hazard.getHazardPlayerAndPoints(damageMap) - -- Placed here to allow getHazardPoints from player based on which hazard +function Hazard:getHazardPlayerAndPoints(damageMap) local hazardPlayer = nil local hazardPoints = -1 - for key, value in pairs(damageMap) do + for key, _ in pairs(damageMap) do local player = Player(key) if player then - local playerHazardPoints = player:getHazardSystemPoints() + local playerHazardPoints = self:getPlayerCurrentLevel() if playerHazardPoints < hazardPoints or hazardPoints == -1 then hazardPlayer = player @@ -40,11 +39,11 @@ function Hazard.getHazardPlayerAndPoints(damageMap) end if hazardPoints == -1 then - hazardPoints = 0 + hazardPoints = 1 end return hazardPlayer, hazardPoints - end +end function Hazard:getPlayerCurrentLevel(player) return player:getStorageValue(self.storageCurrent) < 0 and 0 or player:getStorageValue(self.storageCurrent) From 42bc5b7d669e043e419ea48083d840f42fe968ba Mon Sep 17 00:00:00 2001 From: Eduardo Dantas Date: Sat, 26 Aug 2023 16:22:16 -0300 Subject: [PATCH 16/17] fix: typo --- .../monster/quests/primal_ordeal_quest/the_primal_menace.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/data-otservbr-global/monster/quests/primal_ordeal_quest/the_primal_menace.lua b/data-otservbr-global/monster/quests/primal_ordeal_quest/the_primal_menace.lua index 9f93a4d043a..9561b19e25d 100644 --- a/data-otservbr-global/monster/quests/primal_ordeal_quest/the_primal_menace.lua +++ b/data-otservbr-global/monster/quests/primal_ordeal_quest/the_primal_menace.lua @@ -126,6 +126,7 @@ monster.defenses = { defense = 80, armor = 100, mitigation = 3.72, +} monster.elements = { { type = COMBAT_PHYSICALDAMAGE, percent = 0 }, From 1e0224b961718207f15c6b9153339573da2ba4c0 Mon Sep 17 00:00:00 2001 From: Eduardo Dantas Date: Sat, 26 Aug 2023 16:25:07 -0300 Subject: [PATCH 17/17] fix typo --- data-otservbr-global/scripts/hazard/primal.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/data-otservbr-global/scripts/hazard/primal.lua b/data-otservbr-global/scripts/hazard/primal.lua index ed45d26fd2e..dd353031ac8 100644 --- a/data-otservbr-global/scripts/hazard/primal.lua +++ b/data-otservbr-global/scripts/hazard/primal.lua @@ -89,7 +89,6 @@ function primalKill.onKill(_player, creature) return true end - local player, points = hazard:getHazardPlayerAndPoints(monster:getDamageMap()) if points < 1 then return true