From ae66f530fcdaa896ac6dade3d20835cd968908c6 Mon Sep 17 00:00:00 2001 From: Skold <113406182+Skold177@users.noreply.github.com> Date: Thu, 16 Apr 2026 10:18:11 -0400 Subject: [PATCH] [lua] [sql] The Wyrmking Descends Implements The Wyrmking Descends --- .../mobskills/call_of_the_wyrmking.lua | 18 ++ scripts/actions/mobskills/teraflare.lua | 4 +- scripts/actions/mobskills/touchdown.lua | 2 +- .../Riverne_Site_A01/ouryu_cometh.lua | 26 +- .../Riverne_Site_B01/wyrmking_descends.lua | 102 +++++++ scripts/enum/mob_skill.lua | 30 +- scripts/zones/Riverne-Site_A01/mobs/Ouryu.lua | 7 +- scripts/zones/Riverne-Site_B01/IDs.lua | 1 + scripts/zones/Riverne-Site_B01/mobs/Airi.lua | 45 +++ .../Riverne-Site_B01/mobs/Bahamut_bv2.lua | 256 ++++++++++++++++++ .../Riverne-Site_B01/mobs/Earth_Elemental.lua | 28 ++ scripts/zones/Riverne-Site_B01/mobs/Iruci.lua | 45 +++ .../Riverne-Site_B01/mobs/Jormungand_bv2.lua | 209 ++++++++++++++ .../zones/Riverne-Site_B01/mobs/Ouryu_bv2.lua | 222 +++++++++++++++ .../Riverne-Site_B01/mobs/Tiamat_bv2.lua | 206 ++++++++++++++ scripts/zones/Riverne-Site_B01/mobs/Vrtra.lua | 24 -- .../zones/Riverne-Site_B01/mobs/Vrtra_bv2.lua | 170 ++++++++++++ .../Riverne-Site_B01/mobs/Water_Elemental.lua | 28 ++ scripts/zones/Riverne-Site_B01/mobs/Ziryu.lua | 31 +++ sql/mob_droplist.sql | 16 +- sql/mob_groups.sql | 21 +- sql/mob_pools.sql | 5 + sql/mob_skills.sql | 12 +- sql/mob_spawn_points.sql | 34 +-- 24 files changed, 1465 insertions(+), 77 deletions(-) create mode 100644 scripts/actions/mobskills/call_of_the_wyrmking.lua create mode 100644 scripts/battlefields/Riverne_Site_B01/wyrmking_descends.lua create mode 100644 scripts/zones/Riverne-Site_B01/mobs/Airi.lua create mode 100644 scripts/zones/Riverne-Site_B01/mobs/Bahamut_bv2.lua create mode 100644 scripts/zones/Riverne-Site_B01/mobs/Earth_Elemental.lua create mode 100644 scripts/zones/Riverne-Site_B01/mobs/Iruci.lua create mode 100644 scripts/zones/Riverne-Site_B01/mobs/Jormungand_bv2.lua create mode 100644 scripts/zones/Riverne-Site_B01/mobs/Ouryu_bv2.lua create mode 100644 scripts/zones/Riverne-Site_B01/mobs/Tiamat_bv2.lua delete mode 100644 scripts/zones/Riverne-Site_B01/mobs/Vrtra.lua create mode 100644 scripts/zones/Riverne-Site_B01/mobs/Vrtra_bv2.lua create mode 100644 scripts/zones/Riverne-Site_B01/mobs/Water_Elemental.lua create mode 100644 scripts/zones/Riverne-Site_B01/mobs/Ziryu.lua diff --git a/scripts/actions/mobskills/call_of_the_wyrmking.lua b/scripts/actions/mobskills/call_of_the_wyrmking.lua new file mode 100644 index 00000000000..1b76c70d762 --- /dev/null +++ b/scripts/actions/mobskills/call_of_the_wyrmking.lua @@ -0,0 +1,18 @@ +----------------------------------- +-- Call of the Wyrmking +-- Description: Roars to the sky, calling forth Ouryu, Tiamat, Jormungand or Vrtra to join the battle. +----------------------------------- +---@type TMobSkill +local mobskillObject = {} + +mobskillObject.onMobSkillCheck = function(target, mob, skill) + return 0 +end + +mobskillObject.onMobWeaponSkill = function(mob, target, skill, action) + skill:setMsg(xi.msg.basic.NONE) + + return 0 +end + +return mobskillObject diff --git a/scripts/actions/mobskills/teraflare.lua b/scripts/actions/mobskills/teraflare.lua index 24dfef7b4c7..e5f167ca3cc 100644 --- a/scripts/actions/mobskills/teraflare.lua +++ b/scripts/actions/mobskills/teraflare.lua @@ -8,8 +8,7 @@ local mobskillObject = {} mobskillObject.onMobSkillCheck = function(target, mob, skill) - -- TODO: Mob mechanics where appropriate. - return 1 + return 0 end mobskillObject.onMobWeaponSkill = function(mob, target, skill, action) @@ -19,7 +18,6 @@ mobskillObject.onMobWeaponSkill = function(mob, target, skill, action) params.fTP = { 20, 20, 20 } params.element = xi.element.FIRE params.dStatMultiplier = 1.5 - -- TODO: Capture AoE type. params.attackType = xi.attackType.MAGICAL params.damageType = xi.damageType.FIRE params.shadowBehavior = xi.mobskills.shadowBehavior.WIPE_SHADOWS diff --git a/scripts/actions/mobskills/touchdown.lua b/scripts/actions/mobskills/touchdown.lua index 9db38f1b0b4..c22de64dc3b 100644 --- a/scripts/actions/mobskills/touchdown.lua +++ b/scripts/actions/mobskills/touchdown.lua @@ -32,7 +32,7 @@ end mobskillObject.onMobSkillFinalize = function(mob, skill) mob:delStatusEffect(xi.effect.ALL_MISS) mob:setMobSkillAttack(0) - skill:setFinalAnimationSub(2) + mob:setAnimationSub(2) end return mobskillObject diff --git a/scripts/battlefields/Riverne_Site_A01/ouryu_cometh.lua b/scripts/battlefields/Riverne_Site_A01/ouryu_cometh.lua index 649c28746b0..b96e9a44d6b 100644 --- a/scripts/battlefields/Riverne_Site_A01/ouryu_cometh.lua +++ b/scripts/battlefields/Riverne_Site_A01/ouryu_cometh.lua @@ -18,17 +18,21 @@ local content = Battlefield:new({ }) local function healCharacter(player) - if player:isAlive() then - player:setHP(player:getMaxHP()) - player:setMP(player:getMaxMP()) - player:setTP(0) - - if player:getPet() ~= nil then - local pet = player:getPet() - pet:setHP(pet:getMaxHP()) - pet:setMP(pet:getMaxMP()) - pet:setTP(0) - end + -- Handle player. + if not player:isAlive() then + return + end + + player:setHP(player:getMaxHP()) + player:setMP(player:getMaxMP()) + player:setTP(0) + + -- Handle player's pet. + local pet = player:getPet() + if pet then + pet:setHP(pet:getMaxHP()) + pet:setMP(pet:getMaxMP()) + pet:setTP(0) end end diff --git a/scripts/battlefields/Riverne_Site_B01/wyrmking_descends.lua b/scripts/battlefields/Riverne_Site_B01/wyrmking_descends.lua new file mode 100644 index 00000000000..84f8907ec97 --- /dev/null +++ b/scripts/battlefields/Riverne_Site_B01/wyrmking_descends.lua @@ -0,0 +1,102 @@ +-- Area: Riverne Site #B01 +-- Name: The Wyrmking Descends +-- !pos -612.800 1.750 693.190 29 +----------------------------------- +local content = Battlefield:new({ + zoneId = xi.zone.RIVERNE_SITE_B01, + battlefieldId = xi.battlefield.id.WYRMKING_DESCENDS, + maxPlayers = 18, + levelCap = 99, + timeLimit = utils.minutes(60), + index = 1, + area = 1, + entryNpc = 'Unstable_Displacement', + exitNpc = 'SD_BCNM_Exit', + requiredItems = { xi.item.MONARCHS_ORB } +}) + +local function healCharacter(player) + -- Handle player. + if not player:isAlive() then + return + end + + player:setHP(player:getMaxHP()) + player:setMP(player:getMaxMP()) + player:setTP(0) + + -- Handle player's pet. + local pet = player:getPet() + if pet then + pet:setHP(pet:getMaxHP()) + pet:setMP(pet:getMaxMP()) + pet:setTP(0) + end +end + +-- Players are healed when entering the battlefield +function content:battlefieldEntry(player, battlefield) + healCharacter(player) +end + +content.groups = +{ + { + mobs = { 'Bahamut_bv2' }, + + superlink = true, + allDeath = utils.bind(content.handleAllMonstersDefeated, content), + }, + { + mobs = { 'Ouryu_bv2' }, + superlink = true, + spawned = false, + }, + { + mobs = { 'Tiamat_bv2' }, + superlink = true, + spawned = false, + }, + { + mobs = { 'Jormungand_bv2' }, + superlink = true, + spawned = false, + }, + { + mobs = { 'Vrtra_bv2' }, + superlink = true, + spawned = false, + }, + { + mobs = { 'Ziryu' }, + superlink = false, + spawned = false, + }, + { + mobs = { 'Water_Elemental' }, + superlink = false, + spawned = false, + }, + { + mobs = { 'Earth_Elemental' }, + superlink = false, + spawned = false, + }, + { + mobs = { 'Pey' }, + superlink = true, + spawned = false, + }, + { + mobs = { 'Iruci' }, + superlink = true, + spawned = false, + }, + { + mobs = { 'Airi' }, + superlink = true, + spawned = false, + }, +} + +return content:register() diff --git a/scripts/enum/mob_skill.lua b/scripts/enum/mob_skill.lua index a614a78adf8..d35f8303066 100644 --- a/scripts/enum/mob_skill.lua +++ b/scripts/enum/mob_skill.lua @@ -622,6 +622,33 @@ xi.mobSkill = EMPTY_THRASH = 1275, PROMYVION_BRUME_2 = 1276, + INFERNO_BLAST_ATTACK = 1278, + TEBBAD_WING_1 = 1279, + SPIKE_FLAIL_3 = 1280, + FIERY_BREATH_1 = 1281, + TOUCHDOWN_3 = 1282, + INFERNO_BLAST = 1283, + TEBBAD_WING_2 = 1284, + ABSOLUTE_TERROR_3 = 1285, + HORRID_ROAR_3 = 1286, + + SLEET_BLAST_ATTACK = 1288, + GREGALE_WING_1 = 1289, + SPIKE_FLAIL_4 = 1290, + GLACIAL_BREATH_1 = 1291, + TOUCHDOWN_4 = 1292, + SLEET_BLAST = 1293, + GREGALE_WING_2 = 1294, + ABSOLUTE_TERROR_4 = 1295, + HORRID_ROAR_4 = 1296, + + CYCLONE_WING_1 = 1309, + SPIKE_FLAIL_6 = 1310, + SABLE_BREATH_1 = 1311, + + ABSOLUTE_TERROR_6 = 1315, + HORRID_ROAR_6 = 1316, + GERJIS_GRIP = 1322, -- EES_? = 1327, @@ -767,9 +794,10 @@ xi.mobSkill = IMPULSION = 1547, ABSOLUTE_TERROR_BAHAMUT = 1548, HORRIBLE_ROAR_BAHAMUT = 1549, - + CALL_OF_THE_WYRMKING = 1550, MEGAFLARE = 1551, GIGAFLARE = 1552, + TERAFLARE = 1553, CAMISADO_2 = 1554, diff --git a/scripts/zones/Riverne-Site_A01/mobs/Ouryu.lua b/scripts/zones/Riverne-Site_A01/mobs/Ouryu.lua index 7a0c44c34d3..f4f7c0f9bcd 100644 --- a/scripts/zones/Riverne-Site_A01/mobs/Ouryu.lua +++ b/scripts/zones/Riverne-Site_A01/mobs/Ouryu.lua @@ -55,7 +55,7 @@ local function executeMistmelt(mob) if mob:getAnimationSub() == 1 then local currentTime = GetSystemTime() mob:setLocalVar('phaseChangeTime', currentTime + 120) - mob:setLocalVar('phaseChangeHP', mob:getHP() - 6000) + mob:setLocalVar('phaseChangeHP', math.max(0, mob:getHP() - 6000)) mob:injectActionPacket(mob:getID(), 11, 974, 0, 0x18, 0, 0, 0) mob:setAnimationSub(2) mob:delStatusEffect(xi.effect.ALL_MISS) @@ -93,7 +93,7 @@ entity.onMobSpawn = function(mob) mob:setMobMod(xi.mobMod.ADD_EFFECT, 1) mob:setMobMod(xi.mobMod.NO_STANDBACK, 1) - mob:setLocalVar('phaseChangeHP', mob:getHP() - 6000) + mob:setLocalVar('phaseChangeHP', math.max(0, mob:getHP() - 6000)) ----------------------------------- -- May use Invincible every 10 minutes starting at 85% HP @@ -146,7 +146,7 @@ entity.onMobFight = function(mob, target) mob:getHP() <= mob:getLocalVar('phaseChangeHP') then mob:setLocalVar('phaseChangeTime', currentTime + 120) - mob:setLocalVar('phaseChangeHP', mob:getHP() - 6000) + mob:setLocalVar('phaseChangeHP', math.max(0, mob:getHP() - 6000)) if mob:getAnimationSub() == 1 then exitFlight(mob) else @@ -205,6 +205,7 @@ end entity.onMobDisengage = function(mob) if mob:getAnimationSub() == 1 then + mob:setMobSkillAttack(0) mob:injectActionPacket(mob:getID(), 11, 974, 0, 0x18, 0, 0, 0) mob:delStatusEffect(xi.effect.ALL_MISS) mob:setBehavior(bit.bor(mob:getBehavior(), xi.behavior.NO_TURN)) diff --git a/scripts/zones/Riverne-Site_B01/IDs.lua b/scripts/zones/Riverne-Site_B01/IDs.lua index d49b0cfdc9f..1befe163626 100644 --- a/scripts/zones/Riverne-Site_B01/IDs.lua +++ b/scripts/zones/Riverne-Site_B01/IDs.lua @@ -37,6 +37,7 @@ zones[xi.zone.RIVERNE_SITE_B01] = mob = { BAHAMUT = GetFirstID('Bahamut'), + BAHAMUT_V2 = GetFirstID('Bahamut_bv2'), IMDUGUD = GetFirstID('Imdugud'), SPELL_SPITTER_SPILUSPOK = GetFirstID('Spell_Spitter_Spilospok'), UNSTABLE_CLUSTER = GetFirstID('Unstable_Cluster'), diff --git a/scripts/zones/Riverne-Site_B01/mobs/Airi.lua b/scripts/zones/Riverne-Site_B01/mobs/Airi.lua new file mode 100644 index 00000000000..8410eca2211 --- /dev/null +++ b/scripts/zones/Riverne-Site_B01/mobs/Airi.lua @@ -0,0 +1,45 @@ +----------------------------------- +-- Area: Riverne - Site B01 +-- Mob: Airi +-- Notes: The Wyrmking Descends +-- TODO: Capture complete spell list. This one is usable placeholder based off other BLM enemies of similar level. +----------------------------------- +---@type TMobEntity +local entity = {} + +entity.onMobSpawn = function(mob) + mob:setMobMod(xi.mobMod.NO_STANDBACK, 1) +end + +entity.onMobSpellChoose = function(mob, target, spellId) + local spellList = + { + [ 1] = { xi.magic.spell.BLIZZARD_IV, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100 }, + [ 2] = { xi.magic.spell.THUNDER_IV, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100 }, + [ 3] = { xi.magic.spell.FIRE_IV, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100 }, + [ 4] = { xi.magic.spell.BLIZZAGA_III, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100 }, + [ 5] = { xi.magic.spell.THUNDAGA_III, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100 }, + [ 6] = { xi.magic.spell.FIRAGA_III, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100 }, + [ 7] = { xi.magic.spell.BURST, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100 }, + [ 8] = { xi.magic.spell.FLARE, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100 }, + [ 9] = { xi.magic.spell.FREEZE, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100 }, + [10] = { xi.magic.spell.DRAIN, target, false, xi.action.type.DRAIN_HP, nil, 0, 100 }, + [11] = { xi.magic.spell.ASPIR, target, false, xi.action.type.DRAIN_MP, nil, 0, 100 }, + [12] = { xi.magic.spell.STUN, target, false, xi.action.type.ENFEEBLING_TARGET, xi.effect.STUN, 0, 100 }, + [13] = { xi.magic.spell.DROWN, target, false, xi.action.type.ENFEEBLING_TARGET, xi.effect.DROWN, 0, 100 }, + [14] = { xi.magic.spell.FROST, target, false, xi.action.type.ENFEEBLING_TARGET, xi.effect.FROST, 0, 100 }, + [15] = { xi.magic.spell.RASP, target, false, xi.action.type.ENFEEBLING_TARGET, xi.effect.RASP, 0, 100 }, + [16] = { xi.magic.spell.BIO_II, target, false, xi.action.type.ENFEEBLING_TARGET, xi.effect.BIO, 4, 100 }, + [17] = { xi.magic.spell.POISONGA_II, target, false, xi.action.type.ENFEEBLING_TARGET, xi.effect.POISON, 0, 100 }, + [18] = { xi.magic.spell.BLIND, target, false, xi.action.type.ENFEEBLING_TARGET, xi.effect.BLINDNESS, 0, 100 }, + [19] = { xi.magic.spell.SLEEP, target, false, xi.action.type.ENFEEBLING_TARGET, xi.effect.SLEEP_I, 1, 25 }, + [20] = { xi.magic.spell.SLEEP_II, target, false, xi.action.type.ENFEEBLING_TARGET, xi.effect.SLEEP_I, 2, 25 }, + [21] = { xi.magic.spell.SLEEPGA, target, false, xi.action.type.ENFEEBLING_TARGET, xi.effect.SLEEP_I, 1, 25 }, + [22] = { xi.magic.spell.SLEEPGA_II, target, false, xi.action.type.ENFEEBLING_TARGET, xi.effect.SLEEP_I, 2, 25 }, + [23] = { xi.magic.spell.ICE_SPIKES, mob, false, xi.action.type.ENHANCING_FORCE_SELF, xi.effect.ICE_SPIKES, 0, 100 }, + } + + return xi.combat.behavior.chooseAction(mob, target, nil, spellList) +end + +return entity diff --git a/scripts/zones/Riverne-Site_B01/mobs/Bahamut_bv2.lua b/scripts/zones/Riverne-Site_B01/mobs/Bahamut_bv2.lua new file mode 100644 index 00000000000..64741ab2276 --- /dev/null +++ b/scripts/zones/Riverne-Site_B01/mobs/Bahamut_bv2.lua @@ -0,0 +1,256 @@ +----------------------------------- +-- Area: Riverne - Site B01 (BCNM) +-- NM: Bahamut V2 +-- !pos -612.800 1.750 693.190 29 +-- Uses a flare ability at 90%, 80%, 70%, 60%, 50%, 40%, 30%, 20%, 10%, and 0% HP. +-- Summons a Wyrm at 80%, 60%, 40%, and 20% HP. The Wyrms are Ouryu, Tiamat, Jormungand, and Vrtra, but they spawn in random order. +-- At 10% HP, Bahamut will stop using magic and only use auto-attacks and Teraflare. +-- Combat loop will always prioritze using the next Flare in the sequence over summoning a Wyrm due to early returns. This is retail accurate. +----------------------------------- +local ID = zones[xi.zone.RIVERNE_SITE_B01] +----------------------------------- +---@type TMobEntity +local entity = {} + +local flareTable = +{ + [ 1] = { 90, xi.mobSkill.MEGAFLARE }, + [ 2] = { 80, xi.mobSkill.MEGAFLARE }, + [ 3] = { 70, xi.mobSkill.MEGAFLARE }, + [ 4] = { 60, xi.mobSkill.GIGAFLARE }, + [ 5] = { 50, xi.mobSkill.GIGAFLARE }, + [ 6] = { 40, xi.mobSkill.GIGAFLARE }, + [ 7] = { 30, xi.mobSkill.GIGAFLARE }, + [ 8] = { 20, xi.mobSkill.GIGAFLARE }, + [ 9] = { 10, xi.mobSkill.TERAFLARE }, + [10] = { 0, xi.mobSkill.TERAFLARE }, +} + +local wyrms = +{ + ID.mob.BAHAMUT_V2 + 1, ID.mob.BAHAMUT_V2 + 2, ID.mob.BAHAMUT_V2 + 3, ID.mob.BAHAMUT_V2 + 4 -- Ouryu, Tiamat, Jormungand, Vrtra +} + +local wyrmTable = +{ + [1] = { 80, 1 }, + [2] = { 60, 2 }, + [3] = { 40, 3 }, + [4] = { 20, 4 }, +} + +entity.onMobInitialize = function(mob) + mob:addImmunity(xi.immunity.GRAVITY) + mob:addImmunity(xi.immunity.BIND) + mob:addImmunity(xi.immunity.SILENCE) + mob:addImmunity(xi.immunity.PARALYZE) + mob:addImmunity(xi.immunity.LIGHT_SLEEP) + mob:addImmunity(xi.immunity.DARK_SLEEP) + mob:addImmunity(xi.immunity.TERROR) + mob:addImmunity(xi.immunity.PETRIFY) +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) + mob:setMobMod(xi.mobMod.MAGIC_COOL, 45) + mob:setMobMod(xi.mobMod.WEAPON_BONUS, 156) + mob:setMod(xi.mod.UFASTCAST, 15) + mob:setMod(xi.mod.ATT, 376) + mob:setMod(xi.mod.INT, 21) + mob:setMod(xi.mod.MATT, 12) + mob:setMod(xi.mod.ATT, 425) + mob:addMod(xi.mod.REGAIN, 150) + mob:addMod(xi.mod.REGEN, 50) + mob:setMod(xi.mod.MDEF, 62) + 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 }) + mob:setBehavior(xi.behavior.NO_TURN) + mob:setMobAbilityEnabled(true) + mob:setMagicCastingEnabled(true) + mob:setAutoAttackEnabled(true) + local randomOrder = utils.shuffle(wyrms) + mob:setLocalVar('wyrm1', randomOrder[1]) + mob:setLocalVar('wyrm2', randomOrder[2]) + mob:setLocalVar('wyrm3', randomOrder[3]) + mob:setLocalVar('wyrm4', randomOrder[4]) + mob:setLocalVar('flarePhase', 1) + mob:setLocalVar('wyrmsCalled', 0) + mob:setLocalVar('isBusy', 0) +end + +entity.onMobFight = function(mob, target) + if xi.combat.behavior.isEntityBusy(mob) then + return + end + + local hpPercent = mob:getHPP() + local flarePhase = mob:getLocalVar('flarePhase') + local messagePlayed = mob:getLocalVar('messagePlayed') + + local phaseData = flareTable[flarePhase] + + if not phaseData then + return + end + + local flareThreshold = phaseData[1] + local flare = phaseData[2] + + -- Check to see if we need to use a flare. If so, start the sequence and route the messages based off phase. + if + hpPercent < flareThreshold and + messagePlayed == 0 + then + mob:setMobAbilityEnabled(false) + mob:setMagicCastingEnabled(false) + mob:setAutoAttackEnabled(false) + if flarePhase < 4 then + mob:messageText(mob, ID.text.BAHAMUT_TAUNT) + mob:setLocalVar('messagePlayed', 1) + mob:timer(2000, function(mobArg) + mobArg:messageText(mobArg, ID.text.BAHAMUT_TAUNT + 1) + mobArg:setLocalVar('messagePlayed', 2) + end) + + elseif flarePhase < 9 then + mob:messageText(mob, ID.text.BAHAMUT_TAUNT + 2) + mob:setLocalVar('messagePlayed', 2) + + elseif flarePhase == 9 then + mob:messageText(mob, ID.text.BAHAMUT_TAUNT + 3) + mob:setLocalVar('messagePlayed', 1) + mob:timer(2000, function(mobArg) + mobArg:messageText(mobArg, ID.text.BAHAMUT_TAUNT + 4) + end) + + mob:timer(4000, function(mobArg) + mobArg:messageText(mobArg, ID.text.BAHAMUT_TAUNT + 5) + mobArg:setLocalVar('messagePlayed', 2) + end) + end + return + end + + -- Use Megaflare / Gigaflare / Teraflare - Restore Magic/Attack/Abilities then advance the phase. If it's phase 10, turn off magic and switch to Teraflare only. + if + messagePlayed == 2 and + mob:checkDistance(target) <= 15 + then + mob:useMobAbility(flare) + mob:setLocalVar('messagePlayed', 0) + mob:setLocalVar('flarePhase', flarePhase + 1) + + if flarePhase < 10 then + mob:setMobAbilityEnabled(true) + mob:setAutoAttackEnabled(true) + mob:setMagicCastingEnabled(true) + else + mob:setAutoAttackEnabled(true) + mob:setMobAbilityEnabled(true) + mob:setMod(xi.mod.REGAIN, 50) + end + + return + end + + -- If we make it here, check to see if it's time to summon a Wyrm. If so, start that sequence and gate the loop with isBusy. + local wyrmsCalled = mob:getLocalVar('wyrmsCalled') + local wyrmPhase = wyrmTable[wyrmsCalled + 1] + + if + wyrmPhase and + hpPercent <= wyrmPhase[1] and + messagePlayed == 0 + then + mob:setLocalVar('isBusy', 1) + mob:messageText(mob, ID.text.BAHAMUT_TAUNT + 6) + mob:timer(2000, function(mobArg) + mobArg:messageText(mobArg, ID.text.BAHAMUT_TAUNT + 7) + end) + + mob:timer(4000, function(mobArg) + mobArg:messageText(mobArg, ID.text.BAHAMUT_TAUNT + 8) + mobArg:useMobAbility(xi.mobSkill.CALL_OF_THE_WYRMKING) + mobArg:setLocalVar('isBusy', 0) + end) + + mob:timer(5500, function(mobArg) + GetMobByID(mobArg:getLocalVar('wyrm' .. wyrmPhase[2])):spawn() + mobArg:setLocalVar('wyrmsCalled', wyrmsCalled + 1) + end) + end +end + +entity.onMobMobskillChoose = function(mob, target, skillId) + local skillList = + { + 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 + } + + if mob:getLocalVar('flarePhase') == 10 then + return xi.mobSkill.TERAFLARE + else + return skillList[math.random(1, #skillList)] + end +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 + +entity.onMobDeath = function(mob, player, optParams) + if player then + player:addTitle(xi.title.WYRM_ASTONISHER) + end + + if optParams.isKiller or optParams.noKiller then + mob:messageText(mob, ID.text.BAHAMUT_TAUNT + 9) + + mob:timer(2000, function(mobArg) + mobArg:messageText(mobArg, ID.text.BAHAMUT_TAUNT + 10) + end) + + mob:timer(4000, function(mobArg) + mobArg:messageText(mobArg, ID.text.BAHAMUT_TAUNT + 11) + end) + + for i = 1, 16 do + -- Defeat all additional enemies in the battlefield on death. + local bahamutSummons = GetMobByID(ID.mob.BAHAMUT_V2 + i) + if bahamutSummons and bahamutSummons:isAlive() then + bahamutSummons:setHP(0) + end + end + end +end + +return entity diff --git a/scripts/zones/Riverne-Site_B01/mobs/Earth_Elemental.lua b/scripts/zones/Riverne-Site_B01/mobs/Earth_Elemental.lua new file mode 100644 index 00000000000..d597f40af10 --- /dev/null +++ b/scripts/zones/Riverne-Site_B01/mobs/Earth_Elemental.lua @@ -0,0 +1,28 @@ +----------------------------------- +-- Area: Riverne - Site B01 +-- Mob: Earth Elemental +-- Notes: The Wyrmking Descends +----------------------------------- +---@type TMobEntity +local entity = {} + +entity.onMobSpawn = function(mob) + mob:setMobMod(xi.mobMod.ROAM_DISTANCE, 500) + mob:setMobMod(xi.mobMod.NO_DROPS, 1) +end + +entity.onMobSpellChoose = function(mob, target, spellId) + local spellList = + { + [1] = { xi.magic.spell.STONE_IV, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100 }, + [2] = { xi.magic.spell.STONEGA_III, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100 }, + [3] = { xi.magic.spell.QUAKE, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100 }, + [4] = { xi.magic.spell.RASP, target, false, xi.action.type.ENFEEBLING_TARGET, xi.effect.RASP, 0, 100 }, + [5] = { xi.magic.spell.SLOW, target, false, xi.action.type.ENFEEBLING_TARGET, xi.effect.SLOW, 3, 100 }, + [6] = { xi.magic.spell.STONESKIN, mob, false, xi.action.type.ENHANCING_FORCE_SELF, xi.effect.STONESKIN, 0, 100 }, + } + + return xi.combat.behavior.chooseAction(mob, target, nil, spellList) +end + +return entity diff --git a/scripts/zones/Riverne-Site_B01/mobs/Iruci.lua b/scripts/zones/Riverne-Site_B01/mobs/Iruci.lua new file mode 100644 index 00000000000..9c49ac0e9ad --- /dev/null +++ b/scripts/zones/Riverne-Site_B01/mobs/Iruci.lua @@ -0,0 +1,45 @@ +----------------------------------- +-- Area: Riverne - Site B01 +-- Mob: Iruci +-- Notes: The Wyrmking Descends +-- TODO: Capture complete spell list. This one is usable placeholder based off other BLM enemies of similar level. +----------------------------------- +---@type TMobEntity +local entity = {} + +entity.onMobSpawn = function(mob) + mob:setMobMod(xi.mobMod.NO_STANDBACK, 1) +end + +entity.onMobSpellChoose = function(mob, target, spellId) + local spellList = + { + [ 1] = { xi.magic.spell.BLIZZARD_IV, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100 }, + [ 2] = { xi.magic.spell.THUNDER_IV, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100 }, + [ 3] = { xi.magic.spell.FIRE_IV, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100 }, + [ 4] = { xi.magic.spell.BLIZZAGA_III, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100 }, + [ 5] = { xi.magic.spell.THUNDAGA_III, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100 }, + [ 6] = { xi.magic.spell.FIRAGA_III, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100 }, + [ 7] = { xi.magic.spell.BURST, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100 }, + [ 8] = { xi.magic.spell.FLARE, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100 }, + [ 9] = { xi.magic.spell.FREEZE, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100 }, + [10] = { xi.magic.spell.DRAIN, target, false, xi.action.type.DRAIN_HP, nil, 0, 100 }, + [11] = { xi.magic.spell.ASPIR, target, false, xi.action.type.DRAIN_MP, nil, 0, 100 }, + [12] = { xi.magic.spell.STUN, target, false, xi.action.type.ENFEEBLING_TARGET, xi.effect.STUN, 0, 100 }, + [13] = { xi.magic.spell.DROWN, target, false, xi.action.type.ENFEEBLING_TARGET, xi.effect.DROWN, 0, 100 }, + [14] = { xi.magic.spell.FROST, target, false, xi.action.type.ENFEEBLING_TARGET, xi.effect.FROST, 0, 100 }, + [15] = { xi.magic.spell.RASP, target, false, xi.action.type.ENFEEBLING_TARGET, xi.effect.RASP, 0, 100 }, + [16] = { xi.magic.spell.BIO_II, target, false, xi.action.type.ENFEEBLING_TARGET, xi.effect.BIO, 4, 100 }, + [17] = { xi.magic.spell.POISONGA_II, target, false, xi.action.type.ENFEEBLING_TARGET, xi.effect.POISON, 0, 100 }, + [18] = { xi.magic.spell.BLIND, target, false, xi.action.type.ENFEEBLING_TARGET, xi.effect.BLINDNESS, 0, 100 }, + [19] = { xi.magic.spell.SLEEP, target, false, xi.action.type.ENFEEBLING_TARGET, xi.effect.SLEEP_I, 1, 25 }, + [20] = { xi.magic.spell.SLEEP_II, target, false, xi.action.type.ENFEEBLING_TARGET, xi.effect.SLEEP_I, 2, 25 }, + [21] = { xi.magic.spell.SLEEPGA, target, false, xi.action.type.ENFEEBLING_TARGET, xi.effect.SLEEP_I, 1, 25 }, + [22] = { xi.magic.spell.SLEEPGA_II, target, false, xi.action.type.ENFEEBLING_TARGET, xi.effect.SLEEP_I, 2, 25 }, + [23] = { xi.magic.spell.ICE_SPIKES, mob, false, xi.action.type.ENHANCING_FORCE_SELF, xi.effect.ICE_SPIKES, 0, 100 }, + } + + return xi.combat.behavior.chooseAction(mob, target, nil, spellList) +end + +return entity diff --git a/scripts/zones/Riverne-Site_B01/mobs/Jormungand_bv2.lua b/scripts/zones/Riverne-Site_B01/mobs/Jormungand_bv2.lua new file mode 100644 index 00000000000..88bb93ee243 --- /dev/null +++ b/scripts/zones/Riverne-Site_B01/mobs/Jormungand_bv2.lua @@ -0,0 +1,209 @@ +-- Area : Riverne - Site B01 +-- Mob : Jormungand +-- Battlefield : The Wyrmking Descends +-- Uses Horrid Roar 3 times in a row when under 25% HP. Cannot change phases while Blood Weapon is active. Uses Blood Weapon every 2 1/2 minutes starting at 85% HP. Cannot be used while airborne. +----------------------------------- +---@type TMobEntity +local entity = {} + +local function enterFlight(mob) + mob:setMobSkillAttack(732) + mob:addStatusEffect(xi.effect.ALL_MISS, { power = 1, origin = mob, icon = 0 }) + mob:setBehavior(bit.band(mob:getBehavior(), bit.bnot(xi.behavior.NO_TURN))) + mob:setAnimationSub(1) +end + +local function exitFlight(mob) + mob:setMobSkillAttack(0) + mob:useMobAbility(xi.mobSkill.TOUCHDOWN_4) + mob:delStatusEffect(xi.effect.ALL_MISS) + mob:setBehavior(bit.bor(mob:getBehavior(), xi.behavior.NO_TURN)) + mob:setAnimationSub(2) +end + +entity.onMobInitialize = function(mob) + mob:addImmunity(xi.immunity.BIND) + mob:addImmunity(xi.immunity.GRAVITY) + mob:addImmunity(xi.immunity.PETRIFY) + mob:addImmunity(xi.immunity.SILENCE) + mob:addImmunity(xi.immunity.LIGHT_SLEEP) + mob:addImmunity(xi.immunity.DARK_SLEEP) + mob:addImmunity(xi.immunity.TERROR) + mob:addImmunity(xi.immunity.PLAGUE) +end + +entity.onMobSpawn = function(mob) + mob:setSpawnAnimation(1) + mob:setMobSkillAttack(0) + mob:setAnimationSub(0) + mob:setMod(xi.mod.ATT, 322) + mob:setMod(xi.mod.ACC, 358) + mob:setMod(xi.mod.CURSE_MEVA, 1000) + mob:setMod(xi.mod.DEF, 384) + mob:setMod(xi.mod.EVA, 379) + mob:setMod(xi.mod.MATT, 30) + mob:setMod(xi.mod.REFRESH, 200) + mob:setMod(xi.mod.REGEN, 22) + mob:setMod(xi.mod.UFASTCAST, 60) + mob:setMod(xi.mod.UDMGMAGIC, -4000) + mob:setMod(xi.mod.UDMGRANGE, -5000) + mob:setMod(xi.mod.UDMGBREATH, -5000) + mob:setMobMod(xi.mobMod.ADD_EFFECT, 1) + mob:setMobMod(xi.mobMod.MAGIC_COOL, 40) + mob:setMobMod(xi.mobMod.WEAPON_BONUS, 146) + mob:setBehavior(bit.bor(mob:getBehavior(), xi.behavior.NO_TURN)) + mob:setMobMod(xi.mobMod.DETECTION, bit.bor(xi.detects.SIGHT, xi.detects.HEARING)) + mob:setMobMod(xi.mobMod.SIGHT_RANGE, 20) + mob:setMobMod(xi.mobMod.SOUND_RANGE, 15) + + mob:setLocalVar('roarCount', 0) + mob:setLocalVar('bloodWeaponTime', 0) + + local battlefield = mob:getBattlefield() + + if not battlefield then + return + end + + local players = battlefield:getPlayers() + for _, player in pairs(players) do + if player:isAlive() then + mob:updateEnmity(player) + break + end + end +end + +entity.onMobEngage = function(mob) + local currentTime = GetSystemTime() + mob:setLocalVar('phaseChangeTime', currentTime + 60) + mob:setLocalVar('phaseChangeHP', math.max(0, mob:getHP() - 2500)) +end + +entity.onMobFight = function(mob, target) + if xi.combat.behavior.isEntityBusy(mob) then + return + end + + local currentTime = GetSystemTime() + local currentHP = mob:getHP() + local hpPercent = mob:getHPP() + + -- Can use Blood Weapon every 2 1/2 minutes starting at 85% HP. + -- Cannot be used while airborne. + if + hpPercent <= 85 and + currentTime >= mob:getLocalVar('bloodWeaponTime') and + mob:getAnimationSub() ~= 1 + then + mob:useMobAbility(xi.mobSkill.BLOOD_WEAPON_1) + mob:setLocalVar('bloodWeaponTime', currentTime + 150) + end + + if mob:hasStatusEffect(xi.effect.BLOOD_WEAPON) then + return + end + + -- Check if it's time to fly or land - Cannot change phases while Blood Weapon is active. + if + currentTime >= mob:getLocalVar('phaseChangeTime') or + currentHP <= mob:getLocalVar('phaseChangeHP') + then + if mob:getAnimationSub() == 1 then + exitFlight(mob) + mob:setLocalVar('phaseChangeTime', currentTime + 60) + else + enterFlight(mob) + mob:setLocalVar('phaseChangeTime', currentTime + 30) + end + + mob:setLocalVar('phaseChangeHP', math.max(0, currentHP - 2500)) + end +end + +entity.onMobMobskillChoose = function(mob, target, skillId) + if skillId == xi.mobSkill.SLEET_BLAST_ATTACK then + return 0 + end + + local skillList = {} + + -- Mid-flight. + if mob:getAnimationSub() == 1 then + table.insert(skillList, xi.mobSkill.SLEET_BLAST) + table.insert(skillList, xi.mobSkill.GREGALE_WING_2) + + -- Ground. + else + table.insert(skillList, xi.mobSkill.GREGALE_WING_1) + table.insert(skillList, xi.mobSkill.SPIKE_FLAIL_4) + table.insert(skillList, xi.mobSkill.GLACIAL_BREATH_1) + table.insert(skillList, xi.mobSkill.ABSOLUTE_TERROR_4) + table.insert(skillList, xi.mobSkill.HORRID_ROAR_4) + end + + return skillList[math.random(1, #skillList)] +end + +-- If under 25% HP, uses Horrid Roar 3 times in a row. +entity.onMobWeaponSkill = function(mob, target, skill, action) + if mob:getAnimationSub() == 1 then + return + end + + if target:isBehind(mob, 96) then + return + end + + local roarCount = mob:getLocalVar('roarCount') + + if + mob:getHPP() <= 25 and + skill:getID() == xi.mobSkill.HORRID_ROAR_4 + then + if roarCount < 2 then + mob:useMobAbility(xi.mobSkill.HORRID_ROAR_4) + mob:setLocalVar('roarCount', roarCount + 1) + else + mob:setLocalVar('roarCount', 0) + end + end +end + +entity.onMobSpellChoose = function(mob, target, spellId) + local spellList = + { + [1] = { xi.magic.spell.BLIZZAGA_III, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100 }, + [2] = { xi.magic.spell.PARALYGA, target, false, xi.action.type.ENFEEBLING_TARGET, xi.effect.PARALYSIS, 0, 100 }, + [3] = { xi.magic.spell.BINDGA, target, false, xi.action.type.ENFEEBLING_TARGET, xi.effect.BIND, 0, 100 }, + [4] = { xi.magic.spell.ICE_SPIKES, mob, false, xi.action.type.ENHANCING_FORCE_SELF, xi.effect.ICE_SPIKES, 0, 100 }, + } + + return xi.combat.behavior.chooseAction(mob, target, nil, spellList) +end + +entity.onAdditionalEffect = function(mob, target, damage) + local pTable = + { + chance = 20, + attackType = xi.attackType.MAGICAL, + magicalElement = xi.element.ICE, + basePower = math.floor(damage / 2), + actorStat = xi.mod.INT, + } + + return xi.combat.action.executeAddEffectDamage(mob, target, pTable) +end + +entity.onMobDisengage = function(mob) + if mob:getAnimationSub() == 1 then + mob:setMobSkillAttack(0) + mob:injectActionPacket(mob:getID(), 11, 974, 0, 0x18, 0, 0, 0) + mob:delStatusEffect(xi.effect.ALL_MISS) + mob:setBehavior(bit.bor(mob:getBehavior(), xi.behavior.NO_TURN)) + end + + mob:setAnimationSub(0) +end + +return entity diff --git a/scripts/zones/Riverne-Site_B01/mobs/Ouryu_bv2.lua b/scripts/zones/Riverne-Site_B01/mobs/Ouryu_bv2.lua new file mode 100644 index 00000000000..67ebf7dd75a --- /dev/null +++ b/scripts/zones/Riverne-Site_B01/mobs/Ouryu_bv2.lua @@ -0,0 +1,222 @@ +----------------------------------- +-- Area: Riverne - Site B01 +-- Mob: Ouryu +-- Notes: The Wyrmking Descends +-- !pos 184 0 344 30 +-- Summons adds in a random order, these adds are not pets, but may be aggrod through usual methods like magic/sound. +----------------------------------- +local ID = zones[xi.zone.RIVERNE_SITE_B01] +----------------------------------- +mixins = { require('scripts/mixins/job_special') } +----------------------------------- +---@type TMobEntity +local entity = {} + +----------------------------------- +-- Adds in the Wyrmking Descends are summoned in a random order. +----------------------------------- +local addTable = +{ + [1] = ID.mob.BAHAMUT_V2 + 5, -- Ziryu + [2] = ID.mob.BAHAMUT_V2 + 6, -- Ziryu + [3] = ID.mob.BAHAMUT_V2 + 7, -- Ziryu + [4] = ID.mob.BAHAMUT_V2 + 8, -- Ziryu + [5] = ID.mob.BAHAMUT_V2 + 9, -- Water Elemental + [6] = ID.mob.BAHAMUT_V2 + 10, -- Earth Elemental +} + +----------------------------------- +-- Enter/Exit Flight Functions +----------------------------------- +local function enterFlight(mob) + mob:setMobSkillAttack(425) + mob:addStatusEffect(xi.effect.ALL_MISS, { power = 1, origin = mob, icon = 0 }) + mob:setBehavior(bit.band(mob:getBehavior(), bit.bnot(xi.behavior.NO_TURN))) + mob:setAnimationSub(1) +end + +local function exitFlight(mob) + mob:setMobSkillAttack(0) + mob:useMobAbility(xi.mobSkill.TOUCHDOWN_1) + mob:delStatusEffect(xi.effect.ALL_MISS) + mob:setBehavior(bit.bor(mob:getBehavior(), xi.behavior.NO_TURN)) + mob:setAnimationSub(2) +end + +----------------------------------- +-- Mistmelt Function +----------------------------------- +local function executeMistmelt(mob) + if mob:getAnimationSub() == 1 then + local currentTime = GetSystemTime() + mob:setLocalVar('phaseChangeTime', currentTime + 120) + mob:setLocalVar('phaseChangeHP', math.max(0, mob:getHP() - 2500)) + mob:injectActionPacket(mob:getID(), 11, 974, 0, 0x18, 0, 0, 0) + mob:setBehavior(bit.bor(mob:getBehavior(), xi.behavior.NO_TURN)) + mob:setAnimationSub(2) + mob:delStatusEffect(xi.effect.ALL_MISS) + mob:setMobSkillAttack(0) + end + + mob:setLocalVar('mistmeltUsed', 0) +end + +entity.onMobInitialize = function(mob) + mob:addImmunity(xi.immunity.SLOW) + mob:addImmunity(xi.immunity.TERROR) + mob:addImmunity(xi.immunity.STUN) + mob:addImmunity(xi.immunity.PLAGUE) + mob:addImmunity(xi.immunity.ELEGY) + mob:addImmunity(xi.immunity.PETRIFY) + mob:addImmunity(xi.immunity.DARK_SLEEP) + mob:addImmunity(xi.immunity.LIGHT_SLEEP) +end + +entity.onMobSpawn = function(mob) + mob:setMobSkillAttack(0) + mob:setAnimationSub(0) + mob:setMod(xi.mod.UDMGRANGE, -5000) + mob:setMod(xi.mod.UDMGMAGIC, -5000) + mob:setMod(xi.mod.UDMGBREATH, -5000) + mob:setMod(xi.mod.UFASTCAST, 80) + mob:setMod(xi.mod.DOUBLE_ATTACK, 15) + mob:setMod(xi.mod.REFRESH, 200) + mob:setMobMod(xi.mobMod.WEAPON_BONUS, 52) + mob:setMobMod(xi.mobMod.DETECTION, bit.bor(xi.detects.SIGHT, xi.detects.HEARING)) + mob:setMobMod(xi.mobMod.SIGHT_RANGE, 20) + mob:setMobMod(xi.mobMod.SOUND_RANGE, 15) + mob:setMobMod(xi.mobMod.MAGIC_COOL, 60) + mob:setMobMod(xi.mobMod.ADD_EFFECT, 1) + mob:setMobMod(xi.mobMod.NO_STANDBACK, 1) + + mob:setLocalVar('phaseChangeHP', math.max(0, mob:getHP() - 2500)) + + local battlefield = mob:getBattlefield() + + if not battlefield then + return + end + + local players = battlefield:getPlayers() + for _, player in pairs(players) do + if player:isAlive() then + mob:updateEnmity(player) + break + end + end + + ----------------------------------- + -- May use Invincible every 10 minutes starting at 85% HP + ----------------------------------- + xi.mix.jobSpecial.config(mob, { + specials = + { + { id = xi.mobSkill.INVINCIBLE_1, hpp = 85, cooldown = 600 }, + }, + }) +end + +entity.onMobEngage = function(mob) + local currentTime = GetSystemTime() + mob:setLocalVar('phaseChangeTime', currentTime + 120) + mob:setLocalVar('addSpawnTime', currentTime + math.random(20, 30)) +end + +entity.onMobFight = function(mob, target) + if xi.combat.behavior.isEntityBusy(mob) then + return + end + + local currentTime = GetSystemTime() + + if mob:getLocalVar('mistmeltUsed') == 1 then + executeMistmelt(mob) + return + end + + if + currentTime >= mob:getLocalVar('phaseChangeTime') or + mob:getHP() <= mob:getLocalVar('phaseChangeHP') + then + mob:setLocalVar('phaseChangeTime', currentTime + 120) + mob:setLocalVar('phaseChangeHP', math.max(0, mob:getHP() - 2500)) + if mob:getAnimationSub() == 1 then + exitFlight(mob) + else + enterFlight(mob) + end + end + + if currentTime >= mob:getLocalVar('addSpawnTime') then + mob:setLocalVar('addSpawnTime', currentTime + math.random(60, 90)) + + for _, randomAdd in ipairs(utils.shuffle(addTable)) do + local addToSpawn = GetMobByID(randomAdd) + if addToSpawn and addToSpawn:isDead() then + addToSpawn:spawn() + break + end + end + end +end + +entity.onMobMobskillChoose = function(mob, target, skillId) + if skillId == xi.mobSkill.OCHER_BLAST_ATTACK_2 then + return 0 + end + + local skillList = {} + + -- Mid-flight. + if mob:getAnimationSub() == 1 then + table.insert(skillList, xi.mobSkill.OCHER_BLAST_2) + table.insert(skillList, xi.mobSkill.BAI_WING_2) + + -- Ground. + else + table.insert(skillList, xi.mobSkill.TYPHOON_WING_2) + table.insert(skillList, xi.mobSkill.SPIKE_FLAIL_7) + table.insert(skillList, xi.mobSkill.GEOTIC_BREATH_2) + table.insert(skillList, xi.mobSkill.ABSOLUTE_TERROR_7) + table.insert(skillList, xi.mobSkill.HORRID_ROAR_7) + end + + return skillList[math.random(1, #skillList)] +end + +entity.onMobSpellChoose = function(mob, target, spellId) + local spellList = + { + [1] = { xi.magic.spell.STONEGA_III, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100 }, + [2] = { xi.magic.spell.BREAK, target, false, xi.action.type.ENFEEBLING_TARGET, xi.effect.PETRIFICATION, 0, 100 }, + [3] = { xi.magic.spell.BREAKGA, target, false, xi.action.type.ENFEEBLING_TARGET, xi.effect.PETRIFICATION, 0, 100 }, + [4] = { xi.magic.spell.STONESKIN, mob, false, xi.action.type.ENHANCING_FORCE_SELF, xi.effect.STONESKIN, 0, 100 }, + } + + return xi.combat.behavior.chooseAction(mob, target, nil, spellList) +end + +entity.onAdditionalEffect = function(mob, target, damage) + local pTable = + { + attackType = xi.attackType.MAGICAL, + magicalElement = xi.element.EARTH, + basePower = math.floor(damage / 2), + actorStat = xi.mod.INT, + } + + return xi.combat.action.executeAddEffectDamage(mob, target, pTable) +end + +entity.onMobDisengage = function(mob) + if mob:getAnimationSub() == 1 then + mob:setMobSkillAttack(0) + mob:injectActionPacket(mob:getID(), 11, 974, 0, 0x18, 0, 0, 0) + mob:delStatusEffect(xi.effect.ALL_MISS) + mob:setBehavior(bit.bor(mob:getBehavior(), xi.behavior.NO_TURN)) + end + + mob:setAnimationSub(0) +end + +return entity diff --git a/scripts/zones/Riverne-Site_B01/mobs/Tiamat_bv2.lua b/scripts/zones/Riverne-Site_B01/mobs/Tiamat_bv2.lua new file mode 100644 index 00000000000..fe5f106b97e --- /dev/null +++ b/scripts/zones/Riverne-Site_B01/mobs/Tiamat_bv2.lua @@ -0,0 +1,206 @@ +-- Area : Riverne - Site B01 +-- Mob : Tiamat +-- Battlefield : The Wyrmking Descends +-- Gains a 75% attack boost at 25% HP, and a 25% delay reduction at 10% HP. +----------------------------------- +---@type TMobEntity +local entity = {} + +local function enterFlight(mob) + mob:setMobSkillAttack(730) + mob:addStatusEffect(xi.effect.ALL_MISS, { power = 1, origin = mob, icon = 0 }) + mob:setBehavior(bit.band(mob:getBehavior(), bit.bnot(xi.behavior.NO_TURN))) + mob:setAnimationSub(1) +end + +local function exitFlight(mob) + mob:setMobSkillAttack(0) + mob:useMobAbility(xi.mobSkill.TOUCHDOWN_1) + mob:delStatusEffect(xi.effect.ALL_MISS) + mob:setBehavior(bit.bor(mob:getBehavior(), xi.behavior.NO_TURN)) + mob:setAnimationSub(2) +end + +entity.onMobInitialize = function(mob) + mob:addImmunity(xi.immunity.BIND) + mob:addImmunity(xi.immunity.PETRIFY) + mob:addImmunity(xi.immunity.SILENCE) + mob:addImmunity(xi.immunity.LIGHT_SLEEP) + mob:addImmunity(xi.immunity.DARK_SLEEP) + mob:addImmunity(xi.immunity.TERROR) + mob:addImmunity(xi.immunity.PLAGUE) +end + +entity.onMobSpawn = function(mob) + mob:setSpawnAnimation(1) + mob:setMobSkillAttack(0) + mob:setAnimationSub(0) + mob:setMod(xi.mod.ACC, 361) + mob:setMod(xi.mod.ATT, 359) + mob:setMod(xi.mod.COUNTER, 10) + mob:setMod(xi.mod.DEF, 424) + mob:setMod(xi.mod.EVA, 367) + mob:setMod(xi.mod.MATT, 0) + mob:setMod(xi.mod.REFRESH, 200) + mob:setMod(xi.mod.REGEN, 22) + mob:setMod(xi.mod.UDMGMAGIC, -4000) + mob:setMod(xi.mod.UDMGRANGE, -5000) + mob:setMod(xi.mod.UDMGBREATH, -5000) + mob:setMod(xi.mod.UFASTCAST, 25) + mob:setMod(xi.mod.VIT, 12) + mob:setMobMod(xi.mobMod.ADD_EFFECT, 1) + mob:setMobMod(xi.mobMod.WEAPON_BONUS, 139) + mob:setBehavior(bit.bor(mob:getBehavior(), xi.behavior.NO_TURN)) + mob:setMobMod(xi.mobMod.DETECTION, bit.bor(xi.detects.SIGHT, xi.detects.HEARING)) + mob:setMobMod(xi.mobMod.SIGHT_RANGE, 20) + mob:setMobMod(xi.mobMod.SOUND_RANGE, 15) + mob:setMod(xi.mod.DOUBLE_ATTACK, 25) + mob:setMobMod(xi.mobMod.MAGIC_COOL, 45) + + mob:setLocalVar('mightyStrikesTime', 0) + mob:setLocalVar('delayReductionApplied', 0) + + local battlefield = mob:getBattlefield() + + if not battlefield then + return + end + + local players = battlefield:getPlayers() + for _, player in pairs(players) do + if player:isAlive() then + mob:updateEnmity(player) + break + end + end +end + +entity.onMobEngage = function(mob) + local currentTime = GetSystemTime() + mob:setLocalVar('phaseChangeTime', currentTime + 120) + mob:setLocalVar('phaseChangeHP', math.max(0, mob:getHP() - 2500)) +end + +entity.onMobFight = function(mob, target) + if xi.combat.behavior.isEntityBusy(mob) then + return + end + + local currentTime = GetSystemTime() + local currentHP = mob:getHP() + local hpPercent = mob:getHPP() + + -- Can use Mighty Strikes every 3 1/2 minutes starting at 85% HP. + -- Cannot be used while airborne. + if + hpPercent <= 85 and + currentTime >= mob:getLocalVar('mightyStrikesTime') and + mob:getAnimationSub() ~= 1 + then + mob:useMobAbility(xi.mobSkill.MIGHTY_STRIKES_1) + mob:setLocalVar('mightyStrikesTime', currentTime + 210) + end + + -- Gain a 75% attack boost at 25% HP, and a 25% delay reduction at 10% HP. + if + hpPercent <= 25 and + not mob:hasStatusEffect(xi.effect.ATTACK_BOOST) + then + mob:addStatusEffect(xi.effect.ATTACK_BOOST, { power = 75, origin = mob }) + mob:getStatusEffect(xi.effect.ATTACK_BOOST):addEffectFlag(xi.effectFlag.DEATH) + end + + if + hpPercent <= 10 and + mob:getLocalVar('delayReductionApplied') == 0 + then + mob:setMod(xi.mod.DELAYP, -25) + mob:setLocalVar('delayReductionApplied', 1) + end + + if mob:hasStatusEffect(xi.effect.MIGHTY_STRIKES) then + return + end + + -- Check if it's time to fly or land - Cannot change phases while Mighty Strikes is active. + if + currentTime >= mob:getLocalVar('phaseChangeTime') or + currentHP <= mob:getLocalVar('phaseChangeHP') + then + if mob:getAnimationSub() == 1 then + exitFlight(mob) + else + enterFlight(mob) + end + + mob:setLocalVar('phaseChangeTime', currentTime + 120) + mob:setLocalVar('phaseChangeHP', math.max(0, currentHP - 2500)) + end +end + +entity.onMobMobskillChoose = function(mob, target, skillId) + if skillId == xi.mobSkill.INFERNO_BLAST_ATTACK then + return 0 + end + + local skillList = {} + + -- Mid-flight. + if mob:getAnimationSub() == 1 then + table.insert(skillList, xi.mobSkill.INFERNO_BLAST) + table.insert(skillList, xi.mobSkill.TEBBAD_WING_2) + + -- Ground. + else + table.insert(skillList, xi.mobSkill.TEBBAD_WING_1) + table.insert(skillList, xi.mobSkill.SPIKE_FLAIL_3) + table.insert(skillList, xi.mobSkill.FIERY_BREATH_1) + table.insert(skillList, xi.mobSkill.ABSOLUTE_TERROR_3) + table.insert(skillList, xi.mobSkill.HORRID_ROAR_3) + end + + return skillList[math.random(1, #skillList)] +end + +entity.onMobSpellChoose = function(mob, target, spellId) + local spellList = + { + [1] = { xi.magic.spell.FIRAGA_III, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100 }, + [2] = { xi.magic.spell.BLAZE_SPIKES, mob, false, xi.action.type.ENHANCING_FORCE_SELF, xi.effect.BLAZE_SPIKES, 0, 100 }, + } + + return xi.combat.behavior.chooseAction(mob, target, nil, spellList) +end + +entity.onAdditionalEffect = function(mob, target, damage) + local pTable = + { + chance = 20, + attackType = xi.attackType.MAGICAL, + magicalElement = xi.element.FIRE, + basePower = math.floor(damage / 2), + actorStat = xi.mod.INT, + } + + return xi.combat.action.executeAddEffectDamage(mob, target, pTable) +end + +entity.onMobDisengage = function(mob) + if mob:getAnimationSub() == 1 then + mob:setMobSkillAttack(0) + mob:injectActionPacket(mob:getID(), 11, 974, 0, 0x18, 0, 0, 0) + mob:delStatusEffect(xi.effect.ALL_MISS) + mob:setBehavior(bit.bor(mob:getBehavior(), xi.behavior.NO_TURN)) + end + + if mob:hasStatusEffect(xi.effect.ATTACK_BOOST) then + mob:delStatusEffect(xi.effect.ATTACK_BOOST) + end + + mob:setMod(xi.mod.DELAYP, 0) + mob:setLocalVar('delayReductionApplied', 0) + + mob:setAnimationSub(0) +end + +return entity diff --git a/scripts/zones/Riverne-Site_B01/mobs/Vrtra.lua b/scripts/zones/Riverne-Site_B01/mobs/Vrtra.lua deleted file mode 100644 index 7bb173cd0e0..00000000000 --- a/scripts/zones/Riverne-Site_B01/mobs/Vrtra.lua +++ /dev/null @@ -1,24 +0,0 @@ ------------------------------------ --- The Wyrmking Descends --- Vrtra ------------------------------------ ----@type TMobEntity -local entity = {} - -entity.onMobInitialize = function(mob) - xi.pet.setMobPet(mob, 1, 'Ziryu') -end - -entity.onMobFight = function(mob, target) - local drawInTable = - { - conditions = - { - mob:checkDistance(target) >= 15, - }, - position = mob:getPos(), - } - utils.drawIn(target, drawInTable) -end - -return entity diff --git a/scripts/zones/Riverne-Site_B01/mobs/Vrtra_bv2.lua b/scripts/zones/Riverne-Site_B01/mobs/Vrtra_bv2.lua new file mode 100644 index 00000000000..de8ac9cdf80 --- /dev/null +++ b/scripts/zones/Riverne-Site_B01/mobs/Vrtra_bv2.lua @@ -0,0 +1,170 @@ +----------------------------------- +-- The Wyrmking Descends +-- Vrtra +-- !pos -612.800 1.750 693.190 29 +-- Charms 10 times starting at 85% HP (It is not time based, holding Vrtra at the same HP results in no charm being used. +-- Pushing their HP down quickly will result in multiple charms being used in quick succession. This is intended behavior. +-- Summons 6 pets, 2 each of type. Pey, Iruci, and Airi - once every minute, in a random order. +----------------------------------- +local ID = zones[xi.zone.RIVERNE_SITE_B01] +----------------------------------- +---@type TMobEntity +local entity = {} + +local charmThresholds = +{ + [ 1] = { 85 }, + [ 2] = { 77 }, + [ 3] = { 69 }, + [ 4] = { 61 }, + [ 5] = { 53 }, + [ 6] = { 45 }, + [ 7] = { 37 }, + [ 8] = { 29 }, + [ 9] = { 21 }, + [10] = { 13 }, +} + +local pets = +{ + ID.mob.BAHAMUT_V2 + 11, -- Pey + ID.mob.BAHAMUT_V2 + 12, -- Pey + ID.mob.BAHAMUT_V2 + 13, -- Iruci + ID.mob.BAHAMUT_V2 + 14, -- Iruci + ID.mob.BAHAMUT_V2 + 15, -- Airi + ID.mob.BAHAMUT_V2 + 16, -- Airi +} + +local callPetParams = +{ + inactiveTime = 3000, + maxSpawns = 1, + dieWithOwner = true, +} + +entity.onMobInitialize = function(mob) + mob:addImmunity(xi.immunity.BLIND) + mob:addImmunity(xi.immunity.DARK_SLEEP) + mob:addImmunity(xi.immunity.LIGHT_SLEEP) + mob:addImmunity(xi.immunity.PLAGUE) + mob:addImmunity(xi.immunity.PETRIFY) + mob:addImmunity(xi.immunity.TERROR) +end + +entity.onMobSpawn = function(mob) + mob:setSpawnAnimation(1) + mob:setMobSkillAttack(0) + mob:setAnimationSub(0) + mob:setMod(xi.mod.DEF, 436) + mob:setMod(xi.mod.ATT, 281) + mob:setMod(xi.mod.EVA, 371) + mob:setMod(xi.mod.ACC, 359) + mob:setMod(xi.mod.UFASTCAST, 40) + mob:setMod(xi.mod.DARK_MEVA, 100) + mob:setMod(xi.mod.REGEN, 22) + mob:setMod(xi.mod.REFRESH, 100) + mob:setMobMod(xi.mobMod.NO_STANDBACK, 1) + mob:setMod(xi.mod.UDMGRANGE, -5000) + mob:setMod(xi.mod.UDMGMAGIC, -4000) + mob:setMod(xi.mod.UDMGBREATH, -5000) + mob:setMobMod(xi.mobMod.ADD_EFFECT, 1) + mob:setMobMod(xi.mobMod.DETECTION, bit.bor(xi.detects.SIGHT, xi.detects.HEARING)) + mob:setMobMod(xi.mobMod.SIGHT_RANGE, 20) + mob:setMobMod(xi.mobMod.SOUND_RANGE, 15) + mob:setMobMod(xi.mobMod.WEAPON_BONUS, 137) + mob:setMobMod(xi.mobMod.MAGIC_COOL, 40) + mob:setMobMod(xi.mobMod.ADD_EFFECT, 1) + + mob:setLocalVar('charmsUsed', 0) + + local battlefield = mob:getBattlefield() + + if not battlefield then + return + end + + local players = battlefield:getPlayers() + for _, player in pairs(players) do + if player:isAlive() then + mob:updateEnmity(player) + break + end + end +end + +entity.onMobEngage = function(mob, target) + local currentTime = GetSystemTime() + mob:setLocalVar('addTime', currentTime + math.random(25, 30)) +end + +entity.onMobFight = function(mob, target) + if xi.combat.behavior.isEntityBusy(mob) then + return + end + + local currentTime = GetSystemTime() + local addTime = mob:getLocalVar('addTime') + + if currentTime > addTime then + mob:setLocalVar('addTime', currentTime + math.random(55, 60)) + xi.mob.callPets(mob, utils.shuffle(pets), callPetParams) + end + + local charmIndex = mob:getLocalVar('charmsUsed') + 1 + local charmData = charmThresholds[charmIndex] + + if not charmData then + return + end + + if + mob:getHPP() <= charmData[1] and + mob:checkDistance(target) <= 15 + then + mob:useMobAbility(xi.mobSkill.CHARM) + mob:setLocalVar('charmsUsed', charmIndex) + end +end + +entity.onMobMobskillChoose = function(mob, target, skillId) + local skillList = + { + xi.mobSkill.CYCLONE_WING_1, + xi.mobSkill.SPIKE_FLAIL_6, + xi.mobSkill.SABLE_BREATH_1, + xi.mobSkill.ABSOLUTE_TERROR_6, + xi.mobSkill.HORRID_ROAR_6, + } + + return skillList[math.random(1, #skillList)] +end + +entity.onMobSpellChoose = function(mob, target, spellId) + local spellList = + { + [1] = { xi.magic.spell.BIO_III, target, false, xi.action.type.ENFEEBLING_TARGET, xi.effect.BIO, 4, 100 }, + [2] = { xi.magic.spell.BLINDGA, target, false, xi.action.type.ENFEEBLING_TARGET, xi.effect.BLINDNESS, 0, 100 }, + [3] = { xi.magic.spell.SLEEPGA_II, target, false, xi.action.type.ENFEEBLING_TARGET, xi.effect.SLEEP_I, 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 + +entity.onAdditionalEffect = function(mob, target, damage) + local pTable = + { + chance = 25, + attackType = xi.attackType.MAGICAL, + magicalElement = xi.element.DARK, + basePower = math.floor(damage / 2), + actorStat = xi.mod.INT, + } + + return xi.combat.action.executeAddEffectDamage(mob, target, pTable) +end + +return entity diff --git a/scripts/zones/Riverne-Site_B01/mobs/Water_Elemental.lua b/scripts/zones/Riverne-Site_B01/mobs/Water_Elemental.lua new file mode 100644 index 00000000000..a0f8f5c8f60 --- /dev/null +++ b/scripts/zones/Riverne-Site_B01/mobs/Water_Elemental.lua @@ -0,0 +1,28 @@ +----------------------------------- +-- Area: Riverne - Site B01 +-- Mob: Water Elemental +-- Notes: The Wyrmking Descends +----------------------------------- +---@type TMobEntity +local entity = {} + +entity.onMobSpawn = function(mob) + mob:setMobMod(xi.mobMod.ROAM_DISTANCE, 500) + mob:setMobMod(xi.mobMod.NO_DROPS, 1) +end + +entity.onMobSpellChoose = function(mob, target, spellId) + local spellList = + { + [1] = { xi.magic.spell.WATER_IV, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100 }, + [2] = { xi.magic.spell.WATERGA_III, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100 }, + [3] = { xi.magic.spell.FLOOD, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100 }, + [4] = { xi.magic.spell.DROWN, target, false, xi.action.type.ENFEEBLING_TARGET, xi.effect.DROWN, 0, 100 }, + [5] = { xi.magic.spell.POISONGA_II, target, false, xi.action.type.ENFEEBLING_TARGET, xi.effect.POISON, 0, 100 }, + [6] = { xi.magic.spell.AQUAVEIL, mob, false, xi.action.type.ENHANCING_FORCE_SELF, xi.effect.AQUAVEIL, 0, 100 }, + } + + return xi.combat.behavior.chooseAction(mob, target, nil, spellList) +end + +return entity diff --git a/scripts/zones/Riverne-Site_B01/mobs/Ziryu.lua b/scripts/zones/Riverne-Site_B01/mobs/Ziryu.lua new file mode 100644 index 00000000000..c5bb476bae6 --- /dev/null +++ b/scripts/zones/Riverne-Site_B01/mobs/Ziryu.lua @@ -0,0 +1,31 @@ +----------------------------------- +-- Area: Riverne - Site B01 +-- Mob: Ziryu +-- Notes: The Wyrmking Descends +----------------------------------- +---@type TMobEntity +local entity = {} + +entity.onMobSpawn = function(mob) + mob:setMobMod(xi.mobMod.CHARMABLE, 1) + mob:setMobMod(xi.mobMod.SOUND_RANGE, 30) + mob:setMobMod(xi.mobMod.ROAM_DISTANCE, 500) + mob:setMobMod(xi.mobMod.ROAM_RATE, 10) + mob:setRoamFlags(xi.roamFlag.WORM) +end + +entity.onMobSpellChoose = function(mob, target, spellId) + local spellList = + { + [1] = { xi.magic.spell.STONE_IV, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100 }, + [2] = { xi.magic.spell.STONEGA_III, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100 }, + [3] = { xi.magic.spell.QUAKE, target, false, xi.action.type.DAMAGE_TARGET, nil, 0, 100 }, + [4] = { xi.magic.spell.RASP, target, false, xi.action.type.ENFEEBLING_TARGET, xi.effect.RASP, 0, 100 }, + [5] = { xi.magic.spell.BIND, target, false, xi.action.type.ENFEEBLING_TARGET, xi.effect.BIND, 0, 100 }, + [6] = { xi.magic.spell.STONESKIN, mob, false, xi.action.type.ENHANCING_FORCE_SELF, xi.effect.STONESKIN, 0, 100 }, + } + + return xi.combat.behavior.chooseAction(mob, target, nil, spellList) +end + +return entity diff --git a/sql/mob_droplist.sql b/sql/mob_droplist.sql index a0ee7c6d6e5..d2fc3ba3bdc 100644 --- a/sql/mob_droplist.sql +++ b/sql/mob_droplist.sql @@ -7004,7 +7004,21 @@ INSERT INTO `mob_droplist` VALUES (819,0,0,1000,2160,@RARE); -- Troll Pauldro INSERT INTO `mob_droplist` VALUES (820,0,0,1000,17306,@VCOMMON); -- Snoll Arm (Very Common, 24%) INSERT INTO `mob_droplist` VALUES (820,0,0,1000,15507,@COMMON); -- Purgatory Collar (Common, 15%) --- 821 Available +-- ZoneID: 29 - Bahamut +INSERT INTO `mob_droplist` VALUES (821,1,1,1000,17597,750); -- Dragon Staff (75%) +INSERT INTO `mob_droplist` VALUES (821,1,1,1000,17598,250); -- Bahamut's Staff (25%) +INSERT INTO `mob_droplist` VALUES (821,1,2,1000,15264,300); -- Bahamut's Mask (30%) +INSERT INTO `mob_droplist` VALUES (821,1,2,1000,18061,250); -- Bahamut's Zaghnal (25%) +INSERT INTO `mob_droplist` VALUES (821,1,2,1000,15599,450); -- Bahamut's Hose (45%) +INSERT INTO `mob_droplist` VALUES (821,0,0,1000,1704,@VCOMMON); -- Kunwu Iron (Very Common, 24%) +INSERT INTO `mob_droplist` VALUES (821,0,0,1000,1703,@VCOMMON); -- Kunwu Ore (Very Common, 24%) +INSERT INTO `mob_droplist` VALUES (821,0,0,1000,647,@VCOMMON); -- Molybdenum Ore (Very Common, 24%) +INSERT INTO `mob_droplist` VALUES (821,0,0,1000,647,@VCOMMON); -- Molybdenum Ore (Very Common, 24%) +INSERT INTO `mob_droplist` VALUES (821,0,0,1000,1714,@COMMON); -- Cashmere Cloth (Common, 15%) +INSERT INTO `mob_droplist` VALUES (821,0,0,1000,1713,@COMMON); -- Cashmere Thread (Common, 15%) +INSERT INTO `mob_droplist` VALUES (821,0,0,1000,1816,@VCOMMON); -- Wyrm Horn (Very Common, 24%) +INSERT INTO `mob_droplist` VALUES (821,1,3,1000,1313,@COMMON); -- Siren's Hair (Common, 15%) +INSERT INTO `mob_droplist` VALUES (821,1,3,1000,722,@RARE); -- Divine Log (Rare, 5%) -- ZoneID: 254 - Faunus Wyvern INSERT INTO `mob_droplist` VALUES (822,0,0,1000,3267,@UNCOMMON); -- Pursuers Wing (Uncommon, 10%) diff --git a/sql/mob_groups.sql b/sql/mob_groups.sql index bcd23183c74..6d96dc705a4 100644 --- a/sql/mob_groups.sql +++ b/sql/mob_groups.sql @@ -1168,16 +1168,17 @@ INSERT INTO `mob_groups` VALUES (14,708,29,'Chemical_Cook_Chemachiq',0,128,0,0,0 INSERT INTO `mob_groups` VALUES (15,503,29,'Book_Browser_Bokabraq',0,128,0,0,0,0,NULL); INSERT INTO `mob_groups` VALUES (16,4102,29,'Unstable_Cluster',0,128,2523,10000,0,0,NULL); INSERT INTO `mob_groups` VALUES (17,325,29,'Bahamut',0,128,0,26000,15000,0,NULL); -INSERT INTO `mob_groups` VALUES (18,3070,29,'Ouryu',0,128,0,0,0,0,NULL); -INSERT INTO `mob_groups` VALUES (19,3916,29,'Tiamat',0,128,0,0,0,0,NULL); -INSERT INTO `mob_groups` VALUES (20,2156,29,'Jormungand',0,128,0,0,0,0,NULL); -INSERT INTO `mob_groups` VALUES (21,4261,29,'Vrtra',0,128,0,0,0,0,NULL); -INSERT INTO `mob_groups` VALUES (22,4507,29,'Ziryu',0,128,0,0,0,0,NULL); -INSERT INTO `mob_groups` VALUES (23,4309,29,'Water_Elemental',0,128,2629,0,0,0,NULL); -INSERT INTO `mob_groups` VALUES (24,1160,29,'Earth_Elemental',0,128,733,0,0,0,NULL); -INSERT INTO `mob_groups` VALUES (25,3124,29,'Pey',0,128,0,0,0,0,NULL); -INSERT INTO `mob_groups` VALUES (26,2105,29,'Iruci',0,128,0,0,0,0,NULL); -INSERT INTO `mob_groups` VALUES (27,70,29,'Airi',0,128,0,0,0,0,NULL); +INSERT INTO `mob_groups` VALUES (18,7554,29,'Ouryu_bv2',0,128,0,6000,15000,0,NULL); +INSERT INTO `mob_groups` VALUES (19,7551,29,'Tiamat_bv2',0,128,0,6500,15000,0,NULL); +INSERT INTO `mob_groups` VALUES (20,7552,29,'Jormungand_bv2',0,128,0,6500,15000,0,NULL); +INSERT INTO `mob_groups` VALUES (21,7553,29,'Vrtra_bv2',0,128,0,5500,15000,0,NULL); +INSERT INTO `mob_groups` VALUES (22,4507,29,'Ziryu',0,128,0,2500,15000,0,NULL); +INSERT INTO `mob_groups` VALUES (23,4309,29,'Water_Elemental',0,128,2629,2500,15000,0,NULL); +INSERT INTO `mob_groups` VALUES (24,1160,29,'Earth_Elemental',0,128,733,2500,15000,0,NULL); +INSERT INTO `mob_groups` VALUES (25,3124,29,'Pey',0,128,0,1900,0,0,NULL); +INSERT INTO `mob_groups` VALUES (26,2105,29,'Iruci',0,128,0,1800,15000,0,NULL); +INSERT INTO `mob_groups` VALUES (27,70,29,'Airi',0,128,0,2000,15000,0,NULL); +INSERT INTO `mob_groups` VALUES (28,325,29,'Bahamut_bv2',0,128,821,34000,20000,0,NULL); -- ------------------------------------------------------------ -- Riverne-Site_A01 (Zone 30) diff --git a/sql/mob_pools.sql b/sql/mob_pools.sql index 41940853af1..0886337f52a 100644 --- a/sql/mob_pools.sql +++ b/sql/mob_pools.sql @@ -7484,6 +7484,11 @@ INSERT INTO `mob_pools` VALUES (7547,'Pet_Left-Handed_Yoko','Pet_Left-Handed_Yok INSERT INTO `mob_pools` VALUES (7548,'Pet_Brave_Hero_Glenn','Pet_Brave_Hero_Glenn',111,0x00006a0a00000000000000000000000000000000,1,1,5,150,100,0,0,0,0,8,0,32,0,0,0,0,0,0,0,0,196,0,6); INSERT INTO `mob_pools` VALUES (7549,'Pet_Yellow_Beetle_Familiar','Pet_Y._Beetle_Familiar',49,0x00009a0100000000000000000000000000000000,7,7,8,240,100,0,0,0,0,8,0,32,0,0,0,0,0,0,0,2097,49,0,12); INSERT INTO `mob_pools` VALUES (7550,'Pet_Energized_Sefina','Pet_Energized_Sefina',49,0x00009a0100000000000000000000000000000000,7,7,8,240,100,0,0,0,0,8,0,32,0,0,0,0,0,0,0,2097,49,0,12); +INSERT INTO `mob_pools` VALUES (7551,'Tiamat_bv2','Tiamat',393,0x0000600200000000000000000000000000000000,1,4,7,210,100,1040,1,1,0,2,0,32,157,157,0,0,78,0,0,393,393,0,42); +INSERT INTO `mob_pools` VALUES (7552,'Jormungand_bv2','Jormungand',392,0x0000610200000000000000000000000000000000,8,4,7,210,100,1048,1,1,0,2,0,32,606,157,0,0,111,0,0,392,392,0,42); +INSERT INTO `mob_pools` VALUES (7553,'Vrtra_bv2','Vrtra',391,0x0000630200000000000000000000000000000000,4,9,7,210,100,1048,1,1,1,2,0,32,732,157,4,0,57,0,0,391,391,0,42); +INSERT INTO `mob_pools` VALUES (7554,'Ouryu_bv2','Ouryu',259,0x0000620200000000000000000000000000000000,7,7,7,210,100,1040,1,1,0,18,0,32,297,1179,0,0,109,0,0,259,259,0,42); + -- ------------------------------------------------------------ -- Start of Ambuscade section -- NOTE: The mobs are changed every update in the DATs, so using out-of-date diff --git a/sql/mob_skills.sql b/sql/mob_skills.sql index d3c42260de8..7596c7583b6 100644 --- a/sql/mob_skills.sql +++ b/sql/mob_skills.sql @@ -1306,7 +1306,7 @@ INSERT INTO `mob_skills` VALUES (1278,652,'inferno_blast_alt',0,0.0,18.0,2000,0, INSERT INTO `mob_skills` VALUES (1279,653,'tebbad_wing',1,0.0,30.0,2000,1500,4,0,0,0,0,0,0); INSERT INTO `mob_skills` VALUES (1280,654,'spike_flail',1,0.0,23.0,2000,2000,4,0,0,0,0,0,0); INSERT INTO `mob_skills` VALUES (1281,655,'fiery_breath',4,0.0,18.0,2000,1500,4,0,0,0,0,0,0); -INSERT INTO `mob_skills` VALUES (1282,656,'touchdown',1,0.0,6.0,2000,0,4,@SKILLFLAG_ALWAYS_ANIMATE,0,0,0,0,0); +INSERT INTO `mob_skills` VALUES (1282,656,'touchdown',1,0.0,30.0,2000,0,4,@SKILLFLAG_ALWAYS_ANIMATE,0,0,0,0,0); INSERT INTO `mob_skills` VALUES (1283,657,'inferno_blast',1,0.0,23.0,2000,2000,4,0,0,0,0,0,0); INSERT INTO `mob_skills` VALUES (1284,658,'tebbad_wing_air',1,0.0,30.0,2000,1500,4,0,0,0,0,0,0); INSERT INTO `mob_skills` VALUES (1285,659,'absolute_terror',0,0.0,18.0,2000,1500,4,0,0,0,0,0,0); @@ -1316,7 +1316,7 @@ INSERT INTO `mob_skills` VALUES (1288,963,'sleet_blast_alt',0,0.0,18.0,2000,0,4, INSERT INTO `mob_skills` VALUES (1289,653,'gregale_wing',1,0.0,30.0,2000,1500,4,0,0,0,0,0,0); INSERT INTO `mob_skills` VALUES (1290,654,'spike_flail',1,0.0,23.0,2000,2000,4,0,0,0,0,0,0); INSERT INTO `mob_skills` VALUES (1291,962,'glacial_breath',4,0.0,18.0,2000,1500,4,0,0,0,0,0,0); -INSERT INTO `mob_skills` VALUES (1292,656,'touchdown',1,0.0,6.0,2000,0,4,@SKILLFLAG_ALWAYS_ANIMATE,0,0,0,0,0); +INSERT INTO `mob_skills` VALUES (1292,656,'touchdown',1,0.0,30.0,2000,0,4,@SKILLFLAG_ALWAYS_ANIMATE,0,0,0,0,0); INSERT INTO `mob_skills` VALUES (1293,964,'sleet_blast',1,0.0,23.0,2000,2000,4,0,0,0,0,0,0); INSERT INTO `mob_skills` VALUES (1294,658,'gregale_wing_air',1,0.0,30.0,2000,1500,4,0,0,0,0,0,0); INSERT INTO `mob_skills` VALUES (1295,659,'absolute_terror',0,0.0,18.0,4000,1500,4,0,0,0,0,0,0); @@ -1574,10 +1574,10 @@ INSERT INTO `mob_skills` VALUES (1546,1140,'prodigious_spike',0,0.0,15.0,2000,15 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',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 (1550,1144,'call_of_the_wyrmking',0,0.0,7.0,2000,0,1,0,0,0,0,0,0); +INSERT INTO `mob_skills` VALUES (1551,1136,'megaflare',2,8.0,20.0,6000,2000,4,0,0,0,0,0,0); +INSERT INTO `mob_skills` VALUES (1552,1137,'gigaflare',2,25.0,20.0,6000,2500,4,0,0,0,0,0,0); +INSERT INTO `mob_skills` VALUES (1553,1138,'teraflare',2,20.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); diff --git a/sql/mob_spawn_points.sql b/sql/mob_spawn_points.sql index fd8135712e2..f47d97a1854 100644 --- a/sql/mob_spawn_points.sql +++ b/sql/mob_spawn_points.sql @@ -6224,23 +6224,23 @@ INSERT INTO `mob_spawn_points` VALUES (16896155,0,'Unstable_Cluster','Unstable C INSERT INTO `mob_spawn_points` VALUES (16896156,0,'Bahamut','Bahamut',17,85,85,-706.661,0.405,820.898,3); -- The Wyrmking Descends -INSERT INTO `mob_spawn_points` VALUES (16896157,0,'Bahamut','Bahamut',17,85,85,-704.021,0.168,822.955,229); -INSERT INTO `mob_spawn_points` VALUES (16896158,0,'Ouryu','Ouryu',18,75,75,-694.789,0.099,825.472,255); -INSERT INTO `mob_spawn_points` VALUES (16896159,0,'Tiamat','Tiamat',19,75,75,-696.976,0.151,821.501,208); -INSERT INTO `mob_spawn_points` VALUES (16896160,0,'Jormungand','Jormungand',20,75,75,-704.433,0.464,798.733,150); -INSERT INTO `mob_spawn_points` VALUES (16896161,0,'Vrtra','Vrtra',21,75,75,-694.231,0.024,830.624,57); -INSERT INTO `mob_spawn_points` VALUES (16896162,0,'Ziryu','Ziryu',22,75,75,1.000,1.000,1.000,0); -INSERT INTO `mob_spawn_points` VALUES (16896163,0,'Ziryu','Ziryu',22,75,75,1.000,1.000,1.000,0); -INSERT INTO `mob_spawn_points` VALUES (16896164,0,'Ziryu','Ziryu',22,75,75,1.000,1.000,1.000,0); -INSERT INTO `mob_spawn_points` VALUES (16896165,0,'Ziryu','Ziryu',22,75,75,1.000,1.000,1.000,0); -INSERT INTO `mob_spawn_points` VALUES (16896166,0,'Water_Elemental','Water Elemental',23,75,75,1.000,1.000,1.000,0); -INSERT INTO `mob_spawn_points` VALUES (16896167,0,'Earth_Elemental','Earth Elemental',24,75,75,1.000,1.000,1.000,0); -INSERT INTO `mob_spawn_points` VALUES (16896168,0,'Pey','Pey',25,75,75,-688.086,-0.043,836.809,113); -INSERT INTO `mob_spawn_points` VALUES (16896169,0,'Pey','Pey',25,75,75,-684.670,0.217,824.265,181); -INSERT INTO `mob_spawn_points` VALUES (16896170,0,'Iruci','Iruci',26,75,75,-699.758,0.285,802.629,104); -INSERT INTO `mob_spawn_points` VALUES (16896171,0,'Iruci','Iruci',26,75,75,-686.287,0.157,828.709,165); -INSERT INTO `mob_spawn_points` VALUES (16896172,0,'Airi','Airi',27,15,17,-701.484,0.481,802.338,96); -INSERT INTO `mob_spawn_points` VALUES (16896173,0,'Airi','Airi',27,15,17,-709.580,0.302,827.196,94); +INSERT INTO `mob_spawn_points` VALUES (16896157,0,'Bahamut_bv2','Bahamut',28,92,92,-706.971,0.208,828.373,41); +INSERT INTO `mob_spawn_points` VALUES (16896158,0,'Ouryu_bv2','Ouryu',18,88,88,-700.194,0.49,841.407,67); +INSERT INTO `mob_spawn_points` VALUES (16896159,0,'Tiamat_bv2','Tiamat',19,88,88,-678.588,0.776,819.903,126); +INSERT INTO `mob_spawn_points` VALUES (16896160,0,'Jormungand_bv2','Jormungand',20,88,88,-701.959,0.869,797.652,156); +INSERT INTO `mob_spawn_points` VALUES (16896161,0,'Vrtra_bv2','Vrtra',21,88,88,-721.731,0.456,818.535,23); +INSERT INTO `mob_spawn_points` VALUES (16896162,0,'Ziryu','Ziryu',22,74,76,-687.889,0.321,791.656,0); +INSERT INTO `mob_spawn_points` VALUES (16896163,0,'Ziryu','Ziryu',22,74,76,-697.289,1.902,788.694,0); +INSERT INTO `mob_spawn_points` VALUES (16896164,0,'Ziryu','Ziryu',22,74,76,-716.0511,0.8159,813.272,0); +INSERT INTO `mob_spawn_points` VALUES (16896165,0,'Ziryu','Ziryu',22,74,76,-693.144,0.284,816.515,0); +INSERT INTO `mob_spawn_points` VALUES (16896166,0,'Water_Elemental','Water Elemental',23,74,76,-704.841,0.661,797.99,212); +INSERT INTO `mob_spawn_points` VALUES (16896167,0,'Earth_Elemental','Earth Elemental',24,74,76,-696.848,0.353,805.876,198); +INSERT INTO `mob_spawn_points` VALUES (16896168,0,'Pey','Pey',25,78,79,-688.086,-0.043,836.809,113); +INSERT INTO `mob_spawn_points` VALUES (16896169,0,'Pey','Pey',25,78,79,-684.670,0.217,824.265,181); +INSERT INTO `mob_spawn_points` VALUES (16896170,0,'Iruci','Iruci',26,78,79,-699.758,0.285,802.629,104); +INSERT INTO `mob_spawn_points` VALUES (16896171,0,'Iruci','Iruci',26,78,79,-686.287,0.157,828.709,165); +INSERT INTO `mob_spawn_points` VALUES (16896172,0,'Airi','Airi',27,78,79,-701.484,0.481,802.338,96); +INSERT INTO `mob_spawn_points` VALUES (16896173,0,'Airi','Airi',27,78,79,-709.580,0.302,827.196,94); -- ------------------------------------------------------------ -- Riverne - Site #A01 (Zone 30)