From 8f06279c4f5eb0283d812a227d612ff407abac8c Mon Sep 17 00:00:00 2001 From: Skold <113406182+Skold177@users.noreply.github.com> Date: Sun, 12 Apr 2026 20:49:10 -0400 Subject: [PATCH] [lua] [sql] Storms of Fate & Bahamut Mobskills Refactors Storms of Fate and updates Bahamut mob skills --- scripts/enum/mob_skill.lua | 12 ++ .../zones/Riverne-Site_B01/mobs/Bahamut.lua | 189 +++++++++++------- sql/mob_pools.sql | 2 +- sql/mob_skills.sql | 20 +- 4 files changed, 140 insertions(+), 83 deletions(-) diff --git a/scripts/enum/mob_skill.lua b/scripts/enum/mob_skill.lua index 743f8590438..bbeccb6aa59 100644 --- a/scripts/enum/mob_skill.lua +++ b/scripts/enum/mob_skill.lua @@ -734,6 +734,18 @@ xi.mobSkill = CITADEL_BUSTER = 1540, + TRAMPLE_BAHAMUT = 1542, + TEMPEST_WING = 1543, + TOUCHDOWN_BAHAMUT = 1544, + SWEEPING_FLAIL = 1545, + PRODIGIOUS_SPIKE = 1546, + IMPULSION = 1547, + ABSOLUTE_TERROR_BAHAMUT = 1548, + HORRIBLE_ROAR_BAHAMUT = 1549, + + MEGAFLARE = 1551, + GIGAFLARE = 1552, + CAMISADO_2 = 1554, -- EES_? = 1557, diff --git a/scripts/zones/Riverne-Site_B01/mobs/Bahamut.lua b/scripts/zones/Riverne-Site_B01/mobs/Bahamut.lua index 729ddd91881..8a889e1b45f 100644 --- a/scripts/zones/Riverne-Site_B01/mobs/Bahamut.lua +++ b/scripts/zones/Riverne-Site_B01/mobs/Bahamut.lua @@ -8,7 +8,20 @@ local ID = zones[xi.zone.RIVERNE_SITE_B01] ---@type TMobEntity local entity = {} -entity.onMobSpawn = function(mob) +local flareTable = +{ + [1] = { 89, xi.mobSkill.MEGAFLARE }, + [2] = { 79, xi.mobSkill.MEGAFLARE }, + [3] = { 69, xi.mobSkill.MEGAFLARE }, + [4] = { 59, xi.mobSkill.MEGAFLARE }, + [5] = { 49, xi.mobSkill.MEGAFLARE }, + [6] = { 39, xi.mobSkill.MEGAFLARE }, + [7] = { 29, xi.mobSkill.MEGAFLARE }, + [8] = { 19, xi.mobSkill.MEGAFLARE }, + [9] = { 9, xi.mobSkill.GIGAFLARE }, +} + +entity.onMobInitialize = function(mob) mob:addImmunity(xi.immunity.GRAVITY) mob:addImmunity(xi.immunity.BIND) mob:addImmunity(xi.immunity.SILENCE) @@ -16,102 +29,134 @@ entity.onMobSpawn = function(mob) mob:addImmunity(xi.immunity.LIGHT_SLEEP) mob:addImmunity(xi.immunity.DARK_SLEEP) mob:addImmunity(xi.immunity.TERROR) +end + +entity.onMobSpawn = function(mob) mob:setMobMod(xi.mobMod.NO_STANDBACK, 1) mob:setMobMod(xi.mobMod.SIGHT_RANGE, 20) mob:setMobMod(xi.mobMod.SOUND_RANGE, 20) - -- should cast a spell every ~30 seconds mob:setMobMod(xi.mobMod.MAGIC_COOL, 50) - -- base damage scaled down from Bahamut v2 (wyrmking decends) value based on level difference - -- base damage of 136 = (lvl 83 + 2) + 51 mob:setMobMod(xi.mobMod.WEAPON_BONUS, 51) - -- Note baha has a job trait with fast cast of 15% so 75% total mob:setMod(xi.mod.UFASTCAST, 60) - -- ATT scaled down from Bahamut v2 (wyrmking decends) value based on level difference mob:setMod(xi.mod.ATT, 425) - -- should use mob skill every ~60 sec (without TP feed) mob:addMod(xi.mod.REGAIN, 50) mob:addMod(xi.mod.REGEN, 50) - -- MDEF bonus scaled down from Bahamut v2 (wyrmking decends) value based on level difference mob:setMod(xi.mod.MDEF, 55) mob:addStatusEffect(xi.effect.PHALANX, { power = 35, duration = 180, origin = mob }) mob:addStatusEffect(xi.effect.STONESKIN, { power = 350, duration = 300, origin = mob }) mob:addStatusEffect(xi.effect.PROTECT, { power = 175, duration = 1800, origin = mob }) mob:addStatusEffect(xi.effect.SHELL, { power = 24, duration = 1800, origin = mob }) - -- set these here to make sure no issues if previously killed during a flare mobskill + mob:setBehavior(xi.behavior.NO_TURN) mob:setMobAbilityEnabled(true) mob:setMagicCastingEnabled(true) mob:setAutoAttackEnabled(true) + mob:setLocalVar('phase', 1) end -local megaflareHPP = -{ - 90, 80, 70, 60, 50, 40, 30, 20, -} - entity.onMobFight = function(mob, target) - local megaFlareQueue = mob:getLocalVar('MegaFlareQueue') - local megaFlareTrigger = mob:getLocalVar('MegaFlareTrigger') - -- local megaFlareUses = mob:getLocalVar('MegaFlareUses') - local flareWait = mob:getLocalVar('FlareWait') - local gigaFlare = mob:getLocalVar('GigaFlare') - local tauntShown = mob:getLocalVar('tauntShown') - local mobHPP = mob:getHPP() - - -- if Megaflare hasn't been set to be used this many times, increase the queue of Megaflares. This will allow it to use multiple Megaflares in a row if the HP is decreased quickly enough. - for trigger, hpp in ipairs(megaflareHPP) do - if mobHPP < hpp and megaFlareTrigger < trigger then - mob:setLocalVar('MegaFlareTrigger', trigger) - mob:setLocalVar('MegaFlareQueue', megaFlareQueue + 1) - break - end + if xi.combat.behavior.isEntityBusy(mob) then + return end - if not xi.combat.behavior.isEntityBusy(mob) then -- the last check prevents multiple Mega/Gigaflares from being called at the same time. - if megaFlareQueue > 0 then - mob:setMobAbilityEnabled(false) -- disable all other actions until Megaflare is used successfully - mob:setMagicCastingEnabled(false) - mob:setAutoAttackEnabled(false) - - if flareWait == 0 and tauntShown == 0 then -- if there is a queued Megaflare and the last Megaflare has been used successfully or if the first one hasn't been used yet. - target:showText(mob, ID.text.BAHAMUT_TAUNT) - mob:setLocalVar('FlareWait', mob:getBattleTime() + 2) -- second taunt happens two seconds after the first. - mob:setLocalVar('tauntShown', 1) - elseif flareWait < mob:getBattleTime() and flareWait ~= 0 and tauntShown >= 0 then -- the wait time between the first and second taunt as passed. Checks for wait to be not 0 because it's set to 0 on successful use. - if tauntShown == 1 then - mob:setLocalVar('tauntShown', 2) -- if Megaflare gets stunned it won't show the text again, until successful use. - target:showText(mob, ID.text.BAHAMUT_TAUNT + 1) - end - - if mob:checkDistance(target) <= 15 then -- without this check if the target is out of range it will keep attemping and failing to use Megaflare. Both Megaflare and Gigaflare have range 15. - if bit.band(mob:getBehavior(), xi.behavior.NO_TURN) > 0 then -- default behavior - mob:setBehavior(bit.band(mob:getBehavior(), bit.bnot(xi.behavior.NO_TURN))) - end - - mob:useMobAbility(1551) - end - end - elseif - megaFlareQueue == 0 and - mobHPP < 10 and - gigaFlare < 1 and - mob:checkDistance(target) <= 15 - then - -- All of the scripted Megaflares are to happen before Gigaflare. - if tauntShown == 0 then - target:showText(mob, ID.text.BAHAMUT_TAUNT + 2) - mob:setLocalVar('tauntShown', 3) -- again, taunt won't show again until the move is successfully used. - end - - if bit.band(mob:getBehavior(), xi.behavior.NO_TURN) > 0 then -- default behavior - mob:setBehavior(bit.band(mob:getBehavior(), bit.bnot(xi.behavior.NO_TURN))) - end - - mob:useMobAbility(1552) - end + local hpPercent = mob:getHPP() + local phase = mob:getLocalVar('phase') + local messagePlayed = mob:getLocalVar('messagePlayed') + + local phaseData = flareTable[phase] + if not phaseData then + return + end + + local threshold = phaseData[1] + local flare = phaseData[2] + + -- If were above the HP threshold, and haven't played the message, do nothing.(We check messagePlayed as well because Bahamut has a very strong Regen) + if + hpPercent > threshold and + messagePlayed == 0 + then + return + end + + -- Play message Sequence, if it's phase 9 play the Gigaflare message instead. + if + messagePlayed == 0 and + phase < 9 + then + mob:messageText(mob, ID.text.BAHAMUT_TAUNT) + mob:setLocalVar('messagePlayed', 1) + mob:setMobAbilityEnabled(false) + mob:setMagicCastingEnabled(false) + mob:setAutoAttackEnabled(false) + + mob:timer(2000, function(mobArg) + mobArg:messageText(mobArg, ID.text.BAHAMUT_TAUNT + 1) + mobArg:setLocalVar('messagePlayed', 2) + end) + elseif + messagePlayed == 0 and + phase == 9 + then + mob:messageText(mob, ID.text.BAHAMUT_TAUNT + 2) + mob:setLocalVar('messagePlayed', 2) + mob:setMobAbilityEnabled(false) + mob:setMagicCastingEnabled(false) + mob:setAutoAttackEnabled(false) + return + end + + -- Use Megaflare / Gigaflare + if + messagePlayed == 2 and + mob:checkDistance(target) <= 8 + then + mob:useMobAbility(flare) + + mob:setLocalVar('phase', phase + 1) + mob:setLocalVar('messagePlayed', 0) + + mob:setMobAbilityEnabled(true) + mob:setMagicCastingEnabled(true) + mob:setAutoAttackEnabled(true) end end -entity.onMobDeath = function(mob, player, optParams) +entity.onMobMobskillChoose = function(mob, target, skillId) + local skills = + { + xi.mobSkill.TRAMPLE_BAHAMUT, + xi.mobSkill.TEMPEST_WING, + xi.mobSkill.TOUCHDOWN_BAHAMUT, + xi.mobSkill.SWEEPING_FLAIL, + xi.mobSkill.PRODIGIOUS_SPIKE, + xi.mobSkill.IMPULSION, + xi.mobSkill.ABSOLUTE_TERROR_BAHAMUT, + xi.mobSkill.HORRIBLE_ROAR_BAHAMUT + } + + return skills[math.random(1, #skills)] +end + +entity.onMobSpellChoose = function(mob, target, spellId) + local spellList = + { + [ 1] = { xi.magic.spell.FIRE_V, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100 }, + [ 2] = { xi.magic.spell.FIRAGA_IV, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100 }, + [ 3] = { xi.magic.spell.FLARE_II, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100 }, + [ 4] = { xi.magic.spell.CURE_V, mob, false, xi.action.type.HEALING_TARGET, 50, 0, 100 }, + [ 5] = { xi.magic.spell.SILENCEGA, target, false, xi.action.type.ENFEEBLING_TARGET, xi.effect.SILENCE, 0, 100 }, + [ 6] = { xi.magic.spell.GRAVIGA, target, false, xi.action.type.ENFEEBLING_TARGET, xi.effect.WEIGHT, 0, 100 }, + [ 7] = { xi.magic.spell.PROTECT_V, mob, false, xi.action.type.ENHANCING_FORCE_SELF, xi.effect.PROTECT, 0, 100 }, + [ 8] = { xi.magic.spell.SHELL_V, mob, false, xi.action.type.ENHANCING_FORCE_SELF, xi.effect.SHELL, 0, 100 }, + [ 9] = { xi.magic.spell.STONESKIN, mob, false, xi.action.type.ENHANCING_FORCE_SELF, xi.effect.STONESKIN, 0, 100 }, + [10] = { xi.magic.spell.PHALANX, mob, false, xi.action.type.ENHANCING_FORCE_SELF, xi.effect.PHALANX, 0, 100 }, + } + + if target:hasStatusEffectByFlag(xi.effectFlag.DISPELABLE) then + table.insert(spellList, #spellList + 1, { xi.magic.spell.DISPELGA, target, false, xi.action.type.NONE, nil, 0, 100 }) + end + + return xi.combat.behavior.chooseAction(mob, target, nil, spellList) end return entity diff --git a/sql/mob_pools.sql b/sql/mob_pools.sql index 312facae711..047aca23a80 100644 --- a/sql/mob_pools.sql +++ b/sql/mob_pools.sql @@ -380,7 +380,7 @@ INSERT INTO `mob_pools` VALUES (321,'Badlands_Crab','Badlands_Crab',77,0x0000640 INSERT INTO `mob_pools` VALUES (322,'Badshah','Badshah',242,0x0000340100000000000000000000000000000000,1,1,7,240,100,0,1,0,0,2,0,0,0,3,0,0,0,0,0,242,242,2,29); INSERT INTO `mob_pools` VALUES (323,'Baelfyr','Baelfyr',103,0x0000650800000000000000000000000000000000,5,3,11,240,100,0,1,0,0,0,0,0,0,131,0,0,3,0,0,0,103,1,17); INSERT INTO `mob_pools` VALUES (324,'Baetyl_Quadav_BS','Baetyl_Quadav_BS',202,0x00001F0400000000000000000000000000000000,3,3,3,265,100,0,1,0,1,0,0,0,1,131,0,0,20,0,0,202,202,1,15); -INSERT INTO `mob_pools` VALUES (325,'Bahamut','Bahamut',449,0x00001B0500000000000000000000000000000000,4,5,7,240,100,1024,1,1,0,16,0,32,100,157,0,0,144,0,0,726,449,2,54); +INSERT INTO `mob_pools` VALUES (325,'Bahamut','Bahamut',449,0x00001B0500000000000000000000000000000000,4,5,7,240,100,1024,1,1,0,16,0,32,100,157,0,0,1,0,0,726,449,2,54); INSERT INTO `mob_pools` VALUES (326,'Bakka','Bakka',165,0x0000BD0800000000000000000000000000000000,4,4,7,240,100,0,0,0,0,2,0,32,0,151,4,0,167,127,0,789,165,3,16); INSERT INTO `mob_pools` VALUES (327,'Bakru','Bakru',178,0x00002C0100000000000000000000000000000000,2,2,1,480,100,0,0,0,0,0,0,0,0,3,0,0,0,0,0,178,178,2,9); INSERT INTO `mob_pools` VALUES (328,'Balam-Agab','Balam-Agab',71,0x00006F0100000000000000000000000000000000,3,3,11,240,100,0,1,0,0,2,0,32,7611,157,0,0,20,0,0,71,71,2,18); diff --git a/sql/mob_skills.sql b/sql/mob_skills.sql index a252d6ab0b1..86df06132c7 100644 --- a/sql/mob_skills.sql +++ b/sql/mob_skills.sql @@ -1566,18 +1566,18 @@ INSERT INTO `mob_skills` VALUES (1538,1122,'ion_efflux',4,0.0,10.0,2000,1500,4,0 INSERT INTO `mob_skills` VALUES (1539,1123,'rear_lasers',0,0.0,7.0,2000,1500,4,0,0,0,0,0,0); INSERT INTO `mob_skills` VALUES (1540,1081,'citadel_buster',2,0.0,20.0,2000,1500,4,0,0,0,0,0,0); -- INSERT INTO `mob_skills` VALUES (1541,1285,'blighted_gloom',0,0.0,7.0,2000,1500,4,0,0,0,0,0,0); -INSERT INTO `mob_skills` VALUES (1542,1133,'trample',1,0.0,15.0,2000,1500,4,0,0,0,0,0,0); -INSERT INTO `mob_skills` VALUES (1543,1134,'tempest_wing',4,0.0,15.0,2000,1500,4,0,0,0,0,0,0); -INSERT INTO `mob_skills` VALUES (1544,1139,'touchdown_bahamut',1,0.0,15.0,2000,1500,4,@SKILLFLAG_ALWAYS_ANIMATE,0,0,0,0,0); -INSERT INTO `mob_skills` VALUES (1545,1135,'sweeping_flail',1,0.0,20.0,2000,1500,4,0,0,0,0,0,0); +INSERT INTO `mob_skills` VALUES (1542,1133,'trample',2,0.0,8.0,2000,800,4,0,0,2,0,0,0); +INSERT INTO `mob_skills` VALUES (1543,1134,'tempest_wing',4,0.0,10.0,2000,1200,4,0,0,4,0,0,0); +INSERT INTO `mob_skills` VALUES (1544,1139,'touchdown_bahamut',1,0.0,16.0,2000,1500,4,@SKILLFLAG_ALWAYS_ANIMATE,0,5,0,0,0); +INSERT INTO `mob_skills` VALUES (1545,1135,'sweeping_flail',1,0.0,20.0,2000,1500,4,0,0,6,0,0,0); INSERT INTO `mob_skills` VALUES (1546,1140,'prodigious_spike',0,0.0,15.0,2000,1500,4,0,0,0,0,0,0); -INSERT INTO `mob_skills` VALUES (1547,1141,'impulsion',0,0.0,15.0,2000,1500,4,0,0,0,0,0,0); -INSERT INTO `mob_skills` VALUES (1548,1143,'absolute_terror',1,0.0,15.0,2000,1500,4,0,0,0,0,0,0); -INSERT INTO `mob_skills` VALUES (1549,1142,'horrible_roar',0,0.0,15.0,2000,1500,4,0,0,0,0,0,0); +INSERT INTO `mob_skills` VALUES (1547,1141,'impulsion',2,0.0,8.0,2000,1600,4,0,0,0,0,0,0); +INSERT INTO `mob_skills` VALUES (1548,1143,'absolute_terror',2,0.0,14.0,2000,1200,4,0,0,0,0,0,0); +INSERT INTO `mob_skills` VALUES (1549,1142,'horrible_roar',2,0.0,25.0,2000,1200,4,0,0,0,0,0,0); -- INSERT INTO `mob_skills` VALUES (1550,1294,'.',0,0.0,7.0,2000,1500,4,0,0,0,0,0,0); -INSERT INTO `mob_skills` VALUES (1551,1136,'megaflare',4,0.0,15.0,6000,1500,4,0,0,0,0,0,0); -INSERT INTO `mob_skills` VALUES (1552,1137,'gigaflare',1,0.0,15.0,6000,1500,4,0,0,0,0,0,0); -INSERT INTO `mob_skills` VALUES (1553,1138,'teraflare',0,0.0,15.0,2000,1500,4,0,0,0,0,0,0); +INSERT INTO `mob_skills` VALUES (1551,1136,'megaflare',2,0.0,8.0,6000,2000,4,0,0,0,0,0,0); +INSERT INTO `mob_skills` VALUES (1552,1137,'gigaflare',2,0.0,25.0,6000,2500,4,0,0,0,0,0,0); +INSERT INTO `mob_skills` VALUES (1553,1138,'teraflare',2,0.0,20.0,2000,3000,4,0,0,0,0,0,0); INSERT INTO `mob_skills` VALUES (1554,915,'camisado',0,0.0,7.0,2000,1500,4,0,0,5,0,0,0); -- INSERT INTO `mob_skills` VALUES (1555,1299,'blessed_radiance',0,0.0,7.0,2000,1500,4,0,0,0,0,0,0); -- INSERT INTO `mob_skills` VALUES (1556,1300,'regeneration',0,0.0,7.0,2000,1500,4,0,0,0,0,0,0);