From 3e1c720123ea2968812308978131422bc014a4ba Mon Sep 17 00:00:00 2001 From: Critical <48370698+CriticalXI@users.noreply.github.com> Date: Sun, 18 Jan 2026 21:12:25 -0700 Subject: [PATCH] [lua, sql, c++] CoP Monster Base Damage Audit --- scripts/actions/mobskills/ochre_blast_alt.lua | 4 +- scripts/enum/mob_skill.lua | 2 +- scripts/specs/core/CBaseEntity.lua | 3 +- scripts/zones/Attohwa_Chasm/mobs/Lioumere.lua | 1 + .../Bearclaw_Pinnacle/mobs/Snoll_Tzar.lua | 2 + .../Boneyard_Gully/mobs/Shikaree_X_HW.lua | 10 +- .../Boneyard_Gully/mobs/Shikaree_Y_HW.lua | 8 +- .../Boneyard_Gully/mobs/Shikaree_Z_HW.lua | 8 +- .../Carpenters_Landing/mobs/Overgrown_Ivy.lua | 4 + .../mobs/Disaster_Idol.lua | 201 +++++++++++++++++- scripts/zones/Mine_Shaft_2716/mobs/Bugbby.lua | 4 + .../Monarch_Linn/mobs/Mammet-19_Epsilon.lua | 1 + .../Phomiuna_Aqueducts/mobs/Minotaur.lua | 6 +- scripts/zones/Sacrarium/globals.lua | 10 - scripts/zones/Sacrarium/mobs/Azren_Kuba.lua | 1 + .../zones/Spire_of_Dem/mobs/Progenerator.lua | 2 +- scripts/zones/Spire_of_Holla/mobs/Wreaker.lua | 2 +- scripts/zones/Spire_of_Mea/mobs/Delver.lua | 2 +- .../zones/Spire_of_Vahzl/mobs/Agonizer.lua | 2 +- .../zones/Spire_of_Vahzl/mobs/Cumulator.lua | 2 +- .../zones/Spire_of_Vahzl/mobs/Procreator.lua | 2 +- .../The_Shrouded_Maw/mobs/Diabolos_DN.lua | 1 + sql/mob_groups.sql | 2 +- sql/mob_pools.sql | 2 +- src/map/lua/lua_baseentity.cpp | 8 +- src/map/lua/lua_baseentity.h | 2 +- src/map/utils/mobutils.cpp | 19 +- 27 files changed, 247 insertions(+), 64 deletions(-) diff --git a/scripts/actions/mobskills/ochre_blast_alt.lua b/scripts/actions/mobskills/ochre_blast_alt.lua index abedb6134c5..bac76cab906 100644 --- a/scripts/actions/mobskills/ochre_blast_alt.lua +++ b/scripts/actions/mobskills/ochre_blast_alt.lua @@ -14,9 +14,7 @@ mobskillObject.onMobSkillCheck = function(target, mob, skill) end mobskillObject.onMobWeaponSkill = function(target, mob, skill) - local damage = mob:getWeaponDmg() * 3 - - damage = xi.mobskills.mobMagicalMove(mob, target, skill, damage, xi.element.EARTH, 1, xi.mobskills.magicalTpBonus.NO_EFFECT) + local damage = xi.mobskills.mobMagicalMove(mob, target, skill, mob:getMainLvl() + 2, xi.element.EARTH, 5, xi.mobskills.magicalTpBonus.NO_EFFECT) damage = xi.mobskills.mobFinalAdjustments(damage, mob, skill, target, xi.attackType.MAGICAL, xi.damageType.EARTH, xi.mobskills.shadowBehavior.IGNORE_SHADOWS) target:takeDamage(damage, mob, xi.attackType.MAGICAL, xi.damageType.EARTH) diff --git a/scripts/enum/mob_skill.lua b/scripts/enum/mob_skill.lua index 49a36d75396..5bf719393be 100644 --- a/scripts/enum/mob_skill.lua +++ b/scripts/enum/mob_skill.lua @@ -173,7 +173,7 @@ xi.mobSkill = BLITZSTRAHL = 535, PANZERFAUST = 536, BERSERK_DOLL = 537, - + PANZERSCHRECK = 538, TYPHOON = 539, TREMOROUS_TREAD = 540, -- Mammet-800 diff --git a/scripts/specs/core/CBaseEntity.lua b/scripts/specs/core/CBaseEntity.lua index 176a306fd76..ae7764bc4b9 100644 --- a/scripts/specs/core/CBaseEntity.lua +++ b/scripts/specs/core/CBaseEntity.lua @@ -3663,8 +3663,9 @@ function CBaseEntity:removeAllRunes() end ---@param level integer +---@param recover boolean? ---@return nil -function CBaseEntity:setMobLevel(level) +function CBaseEntity:setMobLevel(level, recover) end ---@nodiscard diff --git a/scripts/zones/Attohwa_Chasm/mobs/Lioumere.lua b/scripts/zones/Attohwa_Chasm/mobs/Lioumere.lua index 19446778b1b..671eb4ba60c 100644 --- a/scripts/zones/Attohwa_Chasm/mobs/Lioumere.lua +++ b/scripts/zones/Attohwa_Chasm/mobs/Lioumere.lua @@ -53,6 +53,7 @@ end entity.onMobSpawn = function(mob) mob:setMobMod(xi.mobMod.ALWAYS_AGGRO, 1) + mob:setMobMod(xi.mobMod.BASE_DAMAGE_MULTIPLIER, 150) end entity.onMobRoam = function(mob) diff --git a/scripts/zones/Bearclaw_Pinnacle/mobs/Snoll_Tzar.lua b/scripts/zones/Bearclaw_Pinnacle/mobs/Snoll_Tzar.lua index 76cec4cdeec..c78464d4067 100644 --- a/scripts/zones/Bearclaw_Pinnacle/mobs/Snoll_Tzar.lua +++ b/scripts/zones/Bearclaw_Pinnacle/mobs/Snoll_Tzar.lua @@ -12,6 +12,8 @@ entity.onMobInitialize = function(mob) end entity.onMobSpawn = function(mob) + mob:setMobMod(xi.mobMod.BASE_DAMAGE_MULTIPLIER, 200) + mob:addListener('WEAPONSKILL_STATE_EXIT', 'SNOLL_EXPLOSION', function(snoll, skillID) if skillID == xi.mobSkill.HYPOTHERMAL_COMBUSTION_2 then snoll:getBattlefield():lose() diff --git a/scripts/zones/Boneyard_Gully/mobs/Shikaree_X_HW.lua b/scripts/zones/Boneyard_Gully/mobs/Shikaree_X_HW.lua index ba156422463..31bf4cbd9cd 100644 --- a/scripts/zones/Boneyard_Gully/mobs/Shikaree_X_HW.lua +++ b/scripts/zones/Boneyard_Gully/mobs/Shikaree_X_HW.lua @@ -9,17 +9,13 @@ local ID = zones[xi.zone.BONEYARD_GULLY] ---@type TMobEntity local entity = {} -entity.onMobInitialize = function(mob) +entity.onMobSpawn = function(mob) mob:setMobMod(xi.mobMod.DUAL_WIELD, 1) + mob:setMobMod(xi.mobMod.SPECIAL_SKILL, 0) + mob:setMobMod(xi.mobMod.BASE_DAMAGE_MULTIPLIER, 150) mob:setMod(xi.mod.DARK_SLEEP_RES_RANK, 8) mob:setMod(xi.mod.LIGHT_SLEEP_RES_RANK, 8) mob:setMod(xi.mod.BIND_RES_RANK, 8) - -- TODO: Needs gravity res rank -end - -entity.onMobSpawn = function(mob) - mob:setMobMod(xi.mobMod.SPECIAL_SKILL, 0) - mob:setMobMod(xi.mobMod.WEAPON_BONUS, 30) mob:setMod(xi.mod.REGAIN, 55) mob:setMobAbilityEnabled(false) xi.mob.callPets(mob, mob:getID() + 2, { inactiveTime = 3000 }) diff --git a/scripts/zones/Boneyard_Gully/mobs/Shikaree_Y_HW.lua b/scripts/zones/Boneyard_Gully/mobs/Shikaree_Y_HW.lua index 9ff6ac19cf9..0d0131c8259 100644 --- a/scripts/zones/Boneyard_Gully/mobs/Shikaree_Y_HW.lua +++ b/scripts/zones/Boneyard_Gully/mobs/Shikaree_Y_HW.lua @@ -9,16 +9,12 @@ local ID = zones[xi.zone.BONEYARD_GULLY] ---@type TMobEntity local entity = {} -entity.onMobInitialize = function(mob) +entity.onMobSpawn = function(mob) mob:setMod(xi.mod.DARK_SLEEP_RES_RANK, 8) mob:setMod(xi.mod.LIGHT_SLEEP_RES_RANK, 8) mob:setMod(xi.mod.BIND_RES_RANK, 8) - -- TODO: Needs gravity res rank -end - -entity.onMobSpawn = function(mob) mob:setMod(xi.mod.REGAIN, 55) - mob:setMobMod(xi.mobMod.WEAPON_BONUS, 30) + mob:setMobMod(xi.mobMod.BASE_DAMAGE_MULTIPLIER, 150) mob:setMobAbilityEnabled(false) end diff --git a/scripts/zones/Boneyard_Gully/mobs/Shikaree_Z_HW.lua b/scripts/zones/Boneyard_Gully/mobs/Shikaree_Z_HW.lua index 218bcc0df1b..8d80a00e68d 100644 --- a/scripts/zones/Boneyard_Gully/mobs/Shikaree_Z_HW.lua +++ b/scripts/zones/Boneyard_Gully/mobs/Shikaree_Z_HW.lua @@ -8,17 +8,13 @@ local ID = zones[xi.zone.BONEYARD_GULLY] ---@type TMobEntity local entity = {} -entity.onMobInitialize = function(mob) +entity.onMobSpawn = function(mob) mob:setMod(xi.mod.DARK_SLEEP_RES_RANK, 8) mob:setMod(xi.mod.LIGHT_SLEEP_RES_RANK, 8) mob:setMod(xi.mod.BIND_RES_RANK, 8) - -- TODO: Needs gravity res rank -end - -entity.onMobSpawn = function(mob) mob:setMod(xi.mod.REGAIN, 55) mob:setMod(xi.mobMod.MAGIC_DELAY, 35) - mob:setMobMod(xi.mobMod.WEAPON_BONUS, 30) + mob:addMobMod(xi.mobMod.BASE_DAMAGE_MULTIPLIER, 150) mob:setMobAbilityEnabled(false) mob:addListener('WEAPONSKILL_USE', 'SHIKAREE_Z_WS', function(mobArg, targetArg, skillid, spentTP, action) diff --git a/scripts/zones/Carpenters_Landing/mobs/Overgrown_Ivy.lua b/scripts/zones/Carpenters_Landing/mobs/Overgrown_Ivy.lua index 2da694944d1..a4fb438dd57 100644 --- a/scripts/zones/Carpenters_Landing/mobs/Overgrown_Ivy.lua +++ b/scripts/zones/Carpenters_Landing/mobs/Overgrown_Ivy.lua @@ -9,6 +9,10 @@ entity.onMobInitialize = function(mob) mob:setMobMod(xi.mobMod.IDLE_DESPAWN, 180) end +entity.onMobSpawn = function(mob) + mob:setMobMod(xi.mobMod.BASE_DAMAGE_MULTIPLIER, 150) +end + entity.onMobFight = function(mob, target) -- retail capture shows mob using 5x bad breath when it falls below 20% -- then resumes normal attacks and moves diff --git a/scripts/zones/Lower_Delkfutts_Tower/mobs/Disaster_Idol.lua b/scripts/zones/Lower_Delkfutts_Tower/mobs/Disaster_Idol.lua index bac54890948..de20d8f3714 100644 --- a/scripts/zones/Lower_Delkfutts_Tower/mobs/Disaster_Idol.lua +++ b/scripts/zones/Lower_Delkfutts_Tower/mobs/Disaster_Idol.lua @@ -6,29 +6,208 @@ local entity = {} entity.onMobInitialize = function(mob) + mob:addImmunity(xi.immunity.SLOW) + mob:addImmunity(xi.immunity.ELEGY) + mob:addImmunity(xi.immunity.BLIND) -- TODO: Should only be dark immune, can be flashed + mob:addImmunity(xi.immunity.DARK_SLEEP) + mob:addImmunity(xi.immunity.LIGHT_SLEEP) + mob:addImmunity(xi.immunity.SILENCE) + mob:addImmunity(xi.immunity.PARALYZE) mob:setMobMod(xi.mobMod.IDLE_DESPAWN, 180) end -entity.onMobEngage = function(mob, target) - local DayOfTheWeek = VanadielDayOfTheWeek() +entity.onMobSpawn = function(mob) + mob:setMobMod(xi.mobMod.BASE_DAMAGE_MULTIPLIER, 150) + mob:setMod(xi.mod.BIND_RES_RANK, 11) + mob:setMod(xi.mod.POISON_RES_RANK, 11) + mob:setMod(xi.mod.DARK_RES_RANK, 11) + mob:setMod(xi.mod.MATT, 68) + mob:setMod(xi.mod.REGEN, 5) +end + +entity.onMobMobskillChoose = function(mob, target) + local skillList = + { + xi.mobSkill.KARTSTRAHL, + xi.mobSkill.BLITZSTRAHL, + xi.mobSkill.PANZERFAUST, + xi.mobSkill.BERSERK_DOLL, + xi.mobSkill.PANZERSCHRECK, + xi.mobSkill.TYPHOON, + xi.mobSkill.GRAVITY_FIELD, + } - mob:setSpellList(118 + DayOfTheWeek) - mob:setLocalVar('DayOfTheWeek', DayOfTheWeek + 1) + return skillList[math.random(1, #skillList)] end +-- Disaster Idol dynamically adjusts his level based on his current target's level entity.onMobFight = function(mob, target) - -- TODO: Has level mimic of person who spawned it. Minimum level 65. HP should scale accordingly. + if not target then + return + end + + local targetLevel = target:getMainLvl() + local currentStatLevel = mob:getLocalVar('currentStatLevel') - local DayOfTheWeek = VanadielDayOfTheWeek() - local mobday = mob:getLocalVar('DayOfTheWeek') + if targetLevel ~= currentStatLevel then - if DayOfTheWeek + 1 ~= mobday then - mob:setSpellList(118 + DayOfTheWeek) - mob:setLocalVar('DayOfTheWeek', DayOfTheWeek + 1) + mob:setMobLevel(utils.clamp(targetLevel, 55, 85), false) + mob:setLocalVar('currentStatLevel', targetLevel) end end -entity.onMobDeath = function(mob, player, optParams) +-- Casts spells based on the current in game day +-- Changes what spells cast based on the current target's level +entity.onMobSpellChoose = function(mob, target, spellId) + local targetLevel = target:getMainLvl() + local dayElement = VanadielDayElement() + local spellLists = + { + -- Firesday + [xi.element.FIRE] = + { + [1] = { xi.magic.spell.FIRE_II, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100, 1, 61 }, + [2] = { xi.magic.spell.FIRE_III, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100, 62, 72 }, + [3] = { xi.magic.spell.FIRE_IV, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100, 73, 99 }, + [4] = { xi.magic.spell.FLARE, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100, 60, 99 }, + [5] = { xi.magic.spell.FIRAGA_II, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100, 1, 68 }, + [6] = { xi.magic.spell.FIRAGA_III, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100, 69, 99 }, + [7] = { xi.magic.spell.BURN, target, false, xi.action.type.ENFEEBLING_TARGET, xi.effect.BURN, 0, 100, 1, 99 }, + [8] = { xi.magic.spell.ENFIRE, mob, false, xi.action.type.ENHANCING_TARGET, xi.effect.ENFIRE, 0, 100, 1, 99 }, + }, + + -- Earthsday + [xi.element.EARTH] = + { + [1] = { xi.magic.spell.STONE_III, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100, 1, 67 }, + [2] = { xi.magic.spell.STONE_IV, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100, 68, 76 }, + [3] = { xi.magic.spell.STONE_V, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100, 77, 99 }, + [4] = { xi.magic.spell.QUAKE, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100, 1, 99 }, + [5] = { xi.magic.spell.STONEGA_II, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100, 1, 62 }, + [6] = { xi.magic.spell.STONEGA_III, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100, 63, 99 }, + [7] = { xi.magic.spell.RASP, target, false, xi.action.type.ENFEEBLING_TARGET, xi.effect.RASP, 0, 100, 1, 99 }, + [8] = { xi.magic.spell.STONESKIN, mob, false, xi.action.type.ENHANCING_TARGET, xi.effect.STONESKIN, 0, 100, 1, 99 }, + [9] = { xi.magic.spell.ENSTONE, mob, false, xi.action.type.ENHANCING_TARGET, xi.effect.ENSTONE, 0, 100, 1, 99 }, + }, + + -- Watersday + [xi.element.WATER] = + { + [ 1] = { xi.magic.spell.WATER_II, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100, 1, 54 }, + [ 2] = { xi.magic.spell.WATER_III, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100, 55, 69 }, + [ 3] = { xi.magic.spell.WATER_IV, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100, 70, 79 }, + [ 4] = { xi.magic.spell.WATER_V, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100, 80, 99 }, + [ 5] = { xi.magic.spell.FLOOD, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100, 58, 99 }, + [ 6] = { xi.magic.spell.WATERGA_II, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100, 1, 64 }, + [ 7] = { xi.magic.spell.WATERGA_III, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100, 65, 99 }, + [ 8] = { xi.magic.spell.DROWN, target, false, xi.action.type.ENFEEBLING_TARGET, xi.effect.DROWN, 0, 100, 1, 99 }, + [ 9] = { xi.magic.spell.POISONGA_II, target, false, xi.action.type.ENFEEBLING_TARGET, xi.effect.POISON, 0, 100, 1, 99 }, + [10] = { xi.magic.spell.AQUAVEIL, mob, false, xi.action.type.ENHANCING_TARGET, xi.effect.AQUAVEIL, 0, 100, 1, 99 }, + [11] = { xi.magic.spell.ENWATER, mob, false, xi.action.type.ENHANCING_TARGET, xi.effect.ENWATER, 0, 100, 1, 99 }, + }, + + -- Windsday + [xi.element.WIND] = + { + [ 1] = { xi.magic.spell.AERO_II, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100, 1, 58 }, + [ 2] = { xi.magic.spell.AERO_III, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100, 59, 71 }, + [ 3] = { xi.magic.spell.AERO_IV, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100, 72, 82 }, + [ 4] = { xi.magic.spell.AERO_V, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100, 83, 99 }, + [ 5] = { xi.magic.spell.TORNADO, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100, 1, 99 }, + [ 6] = { xi.magic.spell.AEROGA_II, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100, 1, 66 }, + [ 7] = { xi.magic.spell.AEROGA_III, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100, 67, 99 }, + [ 8] = { xi.magic.spell.CHOKE, target, false, xi.action.type.ENFEEBLING_TARGET, xi.effect.CHOKE, 0, 100, 1, 99 }, + [ 9] = { xi.magic.spell.SILENCE, target, false, xi.action.type.ENFEEBLING_TARGET, xi.effect.SILENCE, 0, 100, 1, 99 }, + [10] = { xi.magic.spell.BLINK, mob, false, xi.action.type.ENHANCING_TARGET, xi.effect.BLINK, 0, 100, 1, 99 }, + [11] = { xi.magic.spell.ENAERO, mob, false, xi.action.type.ENHANCING_TARGET, xi.effect.ENAERO, 0, 100, 1, 99 }, + }, + + -- Iceday + [xi.element.ICE] = + { + [ 1] = { xi.magic.spell.BLIZZARD_II, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100, 1, 63 }, + [ 2] = { xi.magic.spell.BLIZZARD_III, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100, 64, 73 }, + [ 3] = { xi.magic.spell.BLIZZARD_IV, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100, 74, 99 }, + [ 4] = { xi.magic.spell.FREEZE, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100, 1, 99 }, + [ 5] = { xi.magic.spell.BLIZZAGA_II, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100, 57, 70 }, + [ 6] = { xi.magic.spell.BLIZZAGA_III, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100, 71, 99 }, + [ 7] = { xi.magic.spell.FROST, target, false, xi.action.type.ENFEEBLING_TARGET, xi.effect.FROST, 0, 100, 1, 99 }, + [ 8] = { xi.magic.spell.PARALYZE, target, false, xi.action.type.ENFEEBLING_TARGET, xi.effect.PARALYSIS, 0, 100, 1, 99 }, + [ 9] = { xi.magic.spell.BIND, target, false, xi.action.type.ENFEEBLING_TARGET, xi.effect.BIND, 0, 100, 1, 99 }, + [10] = { xi.magic.spell.ICE_SPIKES, mob, false, xi.action.type.ENHANCING_TARGET, xi.effect.ICE_SPIKES, 0, 100, 1, 99 }, + [11] = { xi.magic.spell.ENBLIZZARD, mob, false, xi.action.type.ENHANCING_TARGET, xi.effect.ENBLIZZARD, 0, 100, 1, 99 }, + }, + + -- Lightningsday + [xi.element.THUNDER] = + { + [ 1] = { xi.magic.spell.THUNDER_II, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100, 1, 65 }, + [ 2] = { xi.magic.spell.THUNDER_III, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100, 66, 74 }, + [ 3] = { xi.magic.spell.THUNDER_IV, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100, 75, 99 }, + [ 4] = { xi.magic.spell.BURST, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100, 56, 99 }, + [ 5] = { xi.magic.spell.THUNDAGA_II, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100, 61, 72 }, + [ 6] = { xi.magic.spell.THUNDAGA_III, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100, 73, 99 }, + [ 7] = { xi.magic.spell.SHOCK, target, false, xi.action.type.ENFEEBLING_TARGET, xi.effect.SHOCK, 0, 100, 1, 99 }, + [ 8] = { xi.magic.spell.STUN, target, false, xi.action.type.ENFEEBLING_TARGET, xi.effect.STUN, 0, 100, 1, 99 }, + [ 9] = { xi.magic.spell.SHOCK_SPIKES, mob, false, xi.action.type.ENHANCING_TARGET, xi.effect.SHOCK_SPIKES, 0, 100, 1, 99 }, + [10] = { xi.magic.spell.ENTHUNDER, mob, false, xi.action.type.ENHANCING_TARGET, xi.effect.ENTHUNDER, 0, 100, 1, 99 }, + }, + + -- Lightsday + [xi.element.LIGHT] = + { + [ 1] = { xi.magic.spell.BANISH_II, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100, 1, 64 }, + [ 2] = { xi.magic.spell.BANISH_III, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100, 65, 75 }, + [ 3] = { xi.magic.spell.BANISH_IV, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100, 76, 99 }, + [ 4] = { xi.magic.spell.HOLY, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100, 1, 99 }, + [ 5] = { xi.magic.spell.BANISHGA_III, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100, 1, 99 }, + [ 6] = { xi.magic.spell.DIA_II, target, false, xi.action.type.ENFEEBLING_TARGET, xi.effect.DIA, 3, 100, 1, 99 }, + [ 7] = { xi.magic.spell.DIAGA_II, target, false, xi.action.type.ENFEEBLING_TARGET, xi.effect.DIA, 3, 100, 1, 99 }, + [ 8] = { xi.magic.spell.FLASH, target, false, xi.action.type.ENFEEBLING_TARGET, xi.effect.FLASH, 0, 100, 1, 99 }, + [ 9] = { xi.magic.spell.DISPELGA, target, false, xi.action.type.ENFEEBLING_TARGET, nil, 0, 100, 1, 99 }, + [10] = { xi.magic.spell.BLINK, mob, false, xi.action.type.ENHANCING_TARGET, xi.effect.BLINK, 0, 100, 1, 99 }, + [11] = { xi.magic.spell.STONESKIN, mob, false, xi.action.type.ENHANCING_TARGET, xi.effect.STONESKIN, 0, 100, 1, 99 }, + [12] = { xi.magic.spell.HASTE, mob, false, xi.action.type.ENHANCING_TARGET, xi.effect.HASTE, 0, 100, 1, 99 }, + [13] = { xi.magic.spell.SHELL_IV, mob, false, xi.action.type.ENHANCING_TARGET, xi.effect.SHELL, 0, 100, 1, 99 }, + [14] = { xi.magic.spell.REGEN, mob, false, xi.action.type.ENHANCING_TARGET, xi.effect.REGEN, 0, 100, 1, 99 }, + }, + + -- Darksday + [xi.element.DARK] = + { + [ 1] = { xi.magic.spell.DRAIN, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100, 1, 99 }, + [ 2] = { xi.magic.spell.ASPIR, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100, 1, 99 }, + [ 3] = { xi.magic.spell.BIO_III, target, false, xi.action.type.ENFEEBLING_TARGET, xi.effect.BIO, 0, 100, 1, 99 }, + [ 4] = { xi.magic.spell.BLIND, target, false, xi.action.type.ENFEEBLING_TARGET, xi.effect.BLINDNESS, 0, 100, 1, 99 }, + [ 5] = { xi.magic.spell.SLEEPGA, target, false, xi.action.type.ENFEEBLING_TARGET, xi.effect.SLEEP_I, 0, 100, 1, 55 }, + [ 6] = { xi.magic.spell.SLEEPGA_II, target, false, xi.action.type.ENFEEBLING_TARGET, xi.effect.SLEEP_II, 0, 100, 56, 99 }, + [ 7] = { xi.magic.spell.DISPEL, target, false, xi.action.type.ENFEEBLING_TARGET, nil, 0, 100, 1, 99 }, + [ 8] = { xi.magic.spell.ABSORB_STR, target, false, xi.action.type.ENFEEBLING_TARGET, nil, 0, 100, 1, 99 }, + [ 9] = { xi.magic.spell.ABSORB_DEX, target, false, xi.action.type.ENFEEBLING_TARGET, nil, 0, 100, 1, 99 }, + [10] = { xi.magic.spell.ABSORB_VIT, target, false, xi.action.type.ENFEEBLING_TARGET, nil, 0, 100, 1, 99 }, + [11] = { xi.magic.spell.ABSORB_AGI, target, false, xi.action.type.ENFEEBLING_TARGET, nil, 0, 100, 1, 99 }, + [12] = { xi.magic.spell.ABSORB_INT, target, false, xi.action.type.ENFEEBLING_TARGET, nil, 0, 100, 1, 99 }, + [13] = { xi.magic.spell.ABSORB_MND, target, false, xi.action.type.ENFEEBLING_TARGET, nil, 0, 100, 1, 99 }, + [14] = { xi.magic.spell.ABSORB_CHR, target, false, xi.action.type.ENFEEBLING_TARGET, nil, 0, 100, 1, 99 }, + }, + } + + -- Filter spells based on target level + local validSpells = {} + local daySpells = spellLists[dayElement] + + if daySpells then + for _, spellData in pairs(daySpells) do + local minLevel = spellData[8] or 1 + local maxLevel = spellData[9] or 99 + + if targetLevel >= minLevel and targetLevel <= maxLevel then + table.insert(validSpells, spellData) + end + end + end + + return xi.combat.behavior.chooseAction(mob, target, nil, validSpells) end return entity diff --git a/scripts/zones/Mine_Shaft_2716/mobs/Bugbby.lua b/scripts/zones/Mine_Shaft_2716/mobs/Bugbby.lua index 89cbaede32c..85479292636 100644 --- a/scripts/zones/Mine_Shaft_2716/mobs/Bugbby.lua +++ b/scripts/zones/Mine_Shaft_2716/mobs/Bugbby.lua @@ -14,6 +14,10 @@ entity.onMobInitialize = function(mob) mob:addImmunity(xi.immunity.BIND) end +entity.onMobSpawn = function(mob) + mob:setMobMod(xi.mobMod.BASE_DAMAGE_MULTIPLIER, 150) +end + entity.onMobDeath = function(mob, player, optParams) if optParams.isKiller or optParams.noKiller then local battlefield = mob:getBattlefield() diff --git a/scripts/zones/Monarch_Linn/mobs/Mammet-19_Epsilon.lua b/scripts/zones/Monarch_Linn/mobs/Mammet-19_Epsilon.lua index 9665b320412..7392e051cc9 100644 --- a/scripts/zones/Monarch_Linn/mobs/Mammet-19_Epsilon.lua +++ b/scripts/zones/Monarch_Linn/mobs/Mammet-19_Epsilon.lua @@ -36,6 +36,7 @@ local tpMoves = entity.onMobInitialize = function(mob) mob:addImmunity(xi.immunity.DARK_SLEEP) mob:addImmunity(xi.immunity.LIGHT_SLEEP) + mob:setMobMod(xi.mobMod.SIGHT_RANGE, 20) end entity.onMobSpawn = function(mob) diff --git a/scripts/zones/Phomiuna_Aqueducts/mobs/Minotaur.lua b/scripts/zones/Phomiuna_Aqueducts/mobs/Minotaur.lua index 516d487cd28..fb83efbe21c 100644 --- a/scripts/zones/Phomiuna_Aqueducts/mobs/Minotaur.lua +++ b/scripts/zones/Phomiuna_Aqueducts/mobs/Minotaur.lua @@ -7,9 +7,13 @@ mixins = { require('scripts/mixins/fomor_hate') } ---@type TMobEntity local entity = {} +entity.onMobInitialize = function(mob) + mob:setMobMod(xi.mobMod.SIGHT_RANGE, 45) +end + entity.onMobSpawn = function(mob) mob:setLocalVar('fomorHateAdj', 2) - mob:setMobMod(xi.mobMod.SIGHT_RANGE, 25) + mob:setMobMod(xi.mobMod.BASE_DAMAGE_MULTIPLIER, 200) end entity.onMobFight = function(mob, target) diff --git a/scripts/zones/Sacrarium/globals.lua b/scripts/zones/Sacrarium/globals.lua index 23ee45753f6..186e2fc8bf5 100644 --- a/scripts/zones/Sacrarium/globals.lua +++ b/scripts/zones/Sacrarium/globals.lua @@ -86,14 +86,4 @@ professorTables.locations = } } -professorTables.returnPoint = -{ - [0] = { 102.669, -3.111, 127.279 }, - [1] = { 62.6680, -3.111, 127.288 }, - [2] = { 22.6690, -3.111, 127.279 }, - [3] = { 102.670, -3.111, -127.318 }, - [4] = { 62.6680, -3.111, -127.318 }, - [5] = { 22.6690, -3.111, -127.318 }, -} - return professorTables diff --git a/scripts/zones/Sacrarium/mobs/Azren_Kuba.lua b/scripts/zones/Sacrarium/mobs/Azren_Kuba.lua index b77c77a4b12..6e332d101a7 100644 --- a/scripts/zones/Sacrarium/mobs/Azren_Kuba.lua +++ b/scripts/zones/Sacrarium/mobs/Azren_Kuba.lua @@ -7,6 +7,7 @@ local entity = {} entity.onMobInitialize = function(mob) mob:addImmunity(xi.immunity.DARK_SLEEP) + mob:setMobMod(xi.mobMod.NO_STANDBACK, 1) end return entity diff --git a/scripts/zones/Spire_of_Dem/mobs/Progenerator.lua b/scripts/zones/Spire_of_Dem/mobs/Progenerator.lua index e94bdff7568..b8a4f321f39 100644 --- a/scripts/zones/Spire_of_Dem/mobs/Progenerator.lua +++ b/scripts/zones/Spire_of_Dem/mobs/Progenerator.lua @@ -17,10 +17,10 @@ entity.onMobInitialize = function(mob) end entity.onMobSpawn = function(mob) + mob:setMobMod(xi.mobMod.BASE_DAMAGE_MULTIPLIER, 150) mob:setMod(xi.mod.DEFP, 35) mob:setMod(xi.mod.TRIPLE_ATTACK, 10) mob:setMod(xi.mod.STORETP, 62) - mob:setMobMod(xi.mobMod.WEAPON_BONUS, 15) end entity.onMobMobskillChoose = function(mob, target) diff --git a/scripts/zones/Spire_of_Holla/mobs/Wreaker.lua b/scripts/zones/Spire_of_Holla/mobs/Wreaker.lua index b4387a98c7f..ce3ab658545 100644 --- a/scripts/zones/Spire_of_Holla/mobs/Wreaker.lua +++ b/scripts/zones/Spire_of_Holla/mobs/Wreaker.lua @@ -13,10 +13,10 @@ entity.onMobInitialize = function(mob) end entity.onMobSpawn = function(mob) + mob:setMobMod(xi.mobMod.BASE_DAMAGE_MULTIPLIER, 150) mob:setMod(xi.mod.DOUBLE_ATTACK, 20) mob:setMod(xi.mod.DEFP, 35) mob:setMod(xi.mod.STORETP, 155) - mob:setMobMod(xi.mobMod.WEAPON_BONUS, 15) end entity.onMobMobskillChoose = function(mob, target) diff --git a/scripts/zones/Spire_of_Mea/mobs/Delver.lua b/scripts/zones/Spire_of_Mea/mobs/Delver.lua index 170a0da036f..9cdf6c3ddf1 100644 --- a/scripts/zones/Spire_of_Mea/mobs/Delver.lua +++ b/scripts/zones/Spire_of_Mea/mobs/Delver.lua @@ -13,10 +13,10 @@ entity.onMobInitialize = function(mob) end entity.onMobSpawn = function(mob) + mob:setMobMod(xi.mobMod.BASE_DAMAGE_MULTIPLIER, 150) mob:setMod(xi.mod.DOUBLE_ATTACK, 20) mob:setMod(xi.mod.DEFP, 35) mob:setMod(xi.mod.STORETP, 62) - mob:setMobMod(xi.mobMod.WEAPON_BONUS, 15) end entity.onMobMobskillChoose = function(mob, target) diff --git a/scripts/zones/Spire_of_Vahzl/mobs/Agonizer.lua b/scripts/zones/Spire_of_Vahzl/mobs/Agonizer.lua index 8862881dc40..dfe0498e741 100644 --- a/scripts/zones/Spire_of_Vahzl/mobs/Agonizer.lua +++ b/scripts/zones/Spire_of_Vahzl/mobs/Agonizer.lua @@ -16,7 +16,7 @@ entity.onMobSpawn = function(mob) mob:setMod(xi.mod.DOUBLE_ATTACK, 20) mob:setMod(xi.mod.STORETP, 62) mob:setMobMod(xi.mobMod.NO_LINK, 1) - mob:setMobMod(xi.mobMod.WEAPON_BONUS, 25) + mob:setMobMod(xi.mobMod.BASE_DAMAGE_MULTIPLIER, 150) end entity.onMobMobskillChoose = function(mob, target) diff --git a/scripts/zones/Spire_of_Vahzl/mobs/Cumulator.lua b/scripts/zones/Spire_of_Vahzl/mobs/Cumulator.lua index 03661db5bbf..55e5cc05225 100644 --- a/scripts/zones/Spire_of_Vahzl/mobs/Cumulator.lua +++ b/scripts/zones/Spire_of_Vahzl/mobs/Cumulator.lua @@ -16,7 +16,7 @@ entity.onMobSpawn = function(mob) mob:setMod(xi.mod.DOUBLE_ATTACK, 20) mob:setMod(xi.mod.STORETP, 62) mob:setMobMod(xi.mobMod.NO_LINK, 1) - mob:setMobMod(xi.mobMod.WEAPON_BONUS, 25) + mob:setMobMod(xi.mobMod.BASE_DAMAGE_MULTIPLIER, 150) end entity.onMobMobskillChoose = function(mob, target) diff --git a/scripts/zones/Spire_of_Vahzl/mobs/Procreator.lua b/scripts/zones/Spire_of_Vahzl/mobs/Procreator.lua index c5e7b3824cf..694e876652b 100644 --- a/scripts/zones/Spire_of_Vahzl/mobs/Procreator.lua +++ b/scripts/zones/Spire_of_Vahzl/mobs/Procreator.lua @@ -18,7 +18,7 @@ entity.onMobSpawn = function(mob) mob:setMod(xi.mod.TRIPLE_ATTACK, 10) mob:setMod(xi.mod.STORETP, 62) mob:setMobMod(xi.mobMod.NO_LINK, 1) - mob:setMobMod(xi.mobMod.WEAPON_BONUS, 25) + mob:setMobMod(xi.mobMod.BASE_DAMAGE_MULTIPLIER, 150) end entity.onMobMobskillChoose = function(mob, target) diff --git a/scripts/zones/The_Shrouded_Maw/mobs/Diabolos_DN.lua b/scripts/zones/The_Shrouded_Maw/mobs/Diabolos_DN.lua index fb0d4479755..09bacfcc449 100644 --- a/scripts/zones/The_Shrouded_Maw/mobs/Diabolos_DN.lua +++ b/scripts/zones/The_Shrouded_Maw/mobs/Diabolos_DN.lua @@ -72,6 +72,7 @@ entity.onMobSpawn = function(mob) mob:setLocalVar('instance', inst) mob:setLocalVar('nightmarePercent', math.random(25, 75)) mob:setMagicCastingEnabled(false) + mob:setMobMod(xi.mobMod.BASE_DAMAGE_MULTIPLIER, 150) mob:addListener('WEAPONSKILL_STATE_EXIT', 'DIABOLOS_NIGHTMARE_WS', function(mobArg, skillID) if diff --git a/sql/mob_groups.sql b/sql/mob_groups.sql index 282376f0296..a77979cdd48 100644 --- a/sql/mob_groups.sql +++ b/sql/mob_groups.sql @@ -12701,7 +12701,7 @@ INSERT INTO `mob_groups` VALUES (22,2483,184,'Magic_Urn',300,0,1571,0,0,34,35,0) INSERT INTO `mob_groups` VALUES (23,1961,184,'Hippolytos',0,32,787,0,0,28,32,0); INSERT INTO `mob_groups` VALUES (24,2480,184,'Magic_Pot',300,0,606,0,0,28,29,0); INSERT INTO `mob_groups` VALUES (25,1261,184,'Eurymedon',0,32,787,0,0,30,34,0); -INSERT INTO `mob_groups` VALUES (26,1049,184,'Disaster_Idol',0,128,0,4300,0,55,55,0); +INSERT INTO `mob_groups` VALUES (26,1049,184,'Disaster_Idol',0,128,0,4300,10000,55,55,0); INSERT INTO `mob_groups` VALUES (27,3055,184,'Orna',0,128,0,0,0,40,40,0); INSERT INTO `mob_groups` VALUES (28,1379,184,'Fomorian_Spear',0,128,0,0,0,32,32,0); INSERT INTO `mob_groups` VALUES (29,2058,184,'Illusory_Pot',0,128,0,0,0,45,50,0); diff --git a/sql/mob_pools.sql b/sql/mob_pools.sql index ffd91f76eb3..d08c2f36c72 100644 --- a/sql/mob_pools.sql +++ b/sql/mob_pools.sql @@ -614,7 +614,7 @@ INSERT INTO `mob_pools` VALUES (555,'Bugaboo','Bugaboo',121,0x000070010000000000 INSERT INTO `mob_pools` VALUES (556,'Bugallug','Bugallug',59,0x00004B0500000000000000000000000000000000,2,2,1,480,100,0,1,0,1,2,0,32,0,157,0,0,0,0,0,59,59,2,13); INSERT INTO `mob_pools` VALUES (557,'Bugard','Bugard',58,0x0000470500000000000000000000000000000000,1,1,3,300,100,0,1,0,0,0,0,0,1379,131,0,0,0,0,0,58,58,1,12); INSERT INTO `mob_pools` VALUES (558,'Bugard-X','Bugard-X',58,0x0000470500000000000000000000000000000000,1,1,5,300,100,0,1,1,1,2,0,0,0,3,0,0,0,0,0,58,58,1,12); -INSERT INTO `mob_pools` VALUES (559,'Bugbby','Bugbby',59,0x00004B0500000000000000000000000000000000,1,1,5,240,100,0,1,0,1,18,6144,32,4045,155,0,0,0,0,0,0,59,1,12); +INSERT INTO `mob_pools` VALUES (559,'Bugbby','Bugbby',59,0x00004B0500000000000000000000000000000000,2,1,1,480,100,0,1,0,1,18,6144,32,4045,155,0,0,0,0,0,0,59,1,12); INSERT INTO `mob_pools` VALUES (560,'Bugbear_Bondman','Bugbear_Bondman',59,0x00004B0500000000000000000000000000000000,2,2,1,480,100,0,1,0,1,0,0,0,6,131,0,0,0,0,0,59,59,1,12); INSERT INTO `mob_pools` VALUES (561,'Bugbear_Deathsman','Bugbear_Deathsman',59,0x00004B0500000000000000000000000000000000,2,2,1,480,100,0,1,0,1,0,0,0,79,133,0,0,0,0,0,59,59,2,13); INSERT INTO `mob_pools` VALUES (562,'Bugbear_Matman','Bugbear_Matman',59,0x00004B0500000000000000000000000000000000,2,2,1,480,100,0,1,0,1,2,6272,0,1259,135,0,0,0,0,0,59,59,NULL,NULL); diff --git a/src/map/lua/lua_baseentity.cpp b/src/map/lua/lua_baseentity.cpp index c09748dd46d..503caa192f1 100644 --- a/src/map/lua/lua_baseentity.cpp +++ b/src/map/lua/lua_baseentity.cpp @@ -16867,11 +16867,11 @@ void CLuaBaseEntity::removeAllRunes() /************************************************************************ * Function: setMobLevel() * Purpose : Updates the monsters level and recalculates stats - * Example : mob:setMobLevel(125) - * Notes : CalculateStats will refill mobs hp/mp as well + * Example : mob:setMobLevel(125) or mob:setMobLevel(125, false) to not reset HP/MP + * Notes : By default, CalculateStats will refill mobs hp/mp unless recover is false ************************************************************************/ -void CLuaBaseEntity::setMobLevel(uint8 level) +void CLuaBaseEntity::setMobLevel(uint8 level, sol::optional recover) { if (m_PBaseEntity->objtype != TYPE_MOB) { @@ -16887,7 +16887,7 @@ void CLuaBaseEntity::setMobLevel(uint8 level) // Remove traits, because they were calculated in the previous CalculateMobStats and are NOT saved, so they must be recalculated. PMob->TraitList.clear(); - mobutils::CalculateMobStats(PMob); + mobutils::CalculateMobStats(PMob, recover.value_or(true)); mobutils::GetAvailableSpells(PMob); } } diff --git a/src/map/lua/lua_baseentity.h b/src/map/lua/lua_baseentity.h index 775ea529150..55ec6e6caa7 100644 --- a/src/map/lua/lua_baseentity.h +++ b/src/map/lua/lua_baseentity.h @@ -831,7 +831,7 @@ class CLuaBaseEntity void removeAllRunes(); // Mob Entity-Specific - void setMobLevel(uint8 level); + void setMobLevel(uint8 level, sol::optional recover); uint8 getEcosystem(); uint16 getSuperFamily(); uint16 getFamily(); diff --git a/src/map/utils/mobutils.cpp b/src/map/utils/mobutils.cpp index b0505ae2453..81f763ef51e 100644 --- a/src/map/utils/mobutils.cpp +++ b/src/map/utils/mobutils.cpp @@ -592,11 +592,16 @@ bool CheckSubJobZone(CMobEntity* PMob) void CalculateMobStats(CMobEntity* PMob, bool recover) { - // remove all to keep mods in sync - PMob->StatusEffectContainer->KillAllStatusEffect(); + // Reset modifiers to base values to prevent stacking PMob->restoreModifiers(); PMob->restoreMobModifiers(); + if (recover) + { + // Clear status effects only when fully recovering + PMob->StatusEffectContainer->KillAllStatusEffect(); + } + bool isNM = PMob->m_Type & MOBTYPE_NOTORIOUS; JOBTYPE mJob = PMob->GetMJob(); JOBTYPE sJob = PMob->GetSJob(); @@ -950,9 +955,13 @@ void CalculateMobStats(CMobEntity* PMob, bool recover) // Max [HP/MP] Boost traits PMob->UpdateHealth(); - PMob->health.tp = 0; - PMob->health.hp = PMob->GetMaxHP(); - PMob->health.mp = PMob->GetMaxMP(); + + if (recover) + { + PMob->health.tp = 0; + PMob->health.hp = PMob->GetMaxHP(); + PMob->health.mp = PMob->GetMaxMP(); + } SetupJob(PMob); SetupRoaming(PMob);