From fd97085fdbe70f4388b6837740ab63afd88f67fe Mon Sep 17 00:00:00 2001 From: Critical <48370698+CriticalXI@users.noreply.github.com> Date: Thu, 18 Dec 2025 22:15:52 -0700 Subject: [PATCH] [lua, sql] CoP 7-5 Warrior's Path audit Co-authored-by: Xaver-DaRed --- .../actions/mobskills/amatsu_hanaikusa.lua | 9 +- scripts/actions/mobskills/amatsu_kazakiri.lua | 9 +- scripts/actions/mobskills/amatsu_torimai.lua | 9 +- .../actions/mobskills/amatsu_tsukikage.lua | 6 +- .../actions/mobskills/amatsu_tsukioboro.lua | 9 +- .../actions/mobskills/amatsu_yukiarashi.lua | 9 +- .../actions/mobskills/cosmic_elucidation.lua | 5 +- scripts/actions/mobskills/oisoya.lua | 9 +- scripts/actions/mobskills/riceball.lua | 1 + .../Sealions_Den/warriors_path.lua | 6 + scripts/enum/mob_skill.lua | 5 +- scripts/zones/Sealions_Den/IDs.lua | 4 + scripts/zones/Sealions_Den/mobs/Cherukiki.lua | 7 + .../Sealions_Den/mobs/Kukki-Chebukki.lua | 7 + .../Sealions_Den/mobs/Makki-Chebukki.lua | 6 + scripts/zones/Sealions_Den/mobs/Tenzen.lua | 374 +++++++++++++----- sql/mob_groups.sql | 2 +- sql/mob_pools.sql | 2 +- sql/mob_skills.sql | 4 +- 19 files changed, 318 insertions(+), 165 deletions(-) diff --git a/scripts/actions/mobskills/amatsu_hanaikusa.lua b/scripts/actions/mobskills/amatsu_hanaikusa.lua index 9ac96f10803..da2fde40751 100644 --- a/scripts/actions/mobskills/amatsu_hanaikusa.lua +++ b/scripts/actions/mobskills/amatsu_hanaikusa.lua @@ -6,14 +6,7 @@ local mobskillObject = {} mobskillObject.onMobSkillCheck = function(target, mob, skill) - if - mob:getObjType() == xi.objType.TRUST or - mob:getAnimationSub() == 0 - then - return 0 - else - return 1 - end + return 0 end mobskillObject.onMobWeaponSkill = function(target, mob, skill) diff --git a/scripts/actions/mobskills/amatsu_kazakiri.lua b/scripts/actions/mobskills/amatsu_kazakiri.lua index 84b21197923..c28d4e9cffe 100644 --- a/scripts/actions/mobskills/amatsu_kazakiri.lua +++ b/scripts/actions/mobskills/amatsu_kazakiri.lua @@ -6,14 +6,7 @@ local mobskillObject = {} mobskillObject.onMobSkillCheck = function(target, mob, skill) - if - mob:getObjType() == xi.objType.TRUST or - mob:getAnimationSub() == 0 - then - return 0 - else - return 1 - end + return 0 end mobskillObject.onMobWeaponSkill = function(target, mob, skill) diff --git a/scripts/actions/mobskills/amatsu_torimai.lua b/scripts/actions/mobskills/amatsu_torimai.lua index 38a646e77bf..ea96aea4268 100644 --- a/scripts/actions/mobskills/amatsu_torimai.lua +++ b/scripts/actions/mobskills/amatsu_torimai.lua @@ -6,14 +6,7 @@ local mobskillObject = {} mobskillObject.onMobSkillCheck = function(target, mob, skill) - if - mob:getObjType() == xi.objType.TRUST or - mob:getAnimationSub() == 0 - then - return 0 - else - return 1 - end + return 0 end mobskillObject.onMobWeaponSkill = function(target, mob, skill) diff --git a/scripts/actions/mobskills/amatsu_tsukikage.lua b/scripts/actions/mobskills/amatsu_tsukikage.lua index 3ecef382ac3..06962e8177a 100644 --- a/scripts/actions/mobskills/amatsu_tsukikage.lua +++ b/scripts/actions/mobskills/amatsu_tsukikage.lua @@ -6,11 +6,7 @@ local mobskillObject = {} mobskillObject.onMobSkillCheck = function(target, mob, skill) - if mob:getObjType() == xi.objType.TRUST then - return 0 - else - return 1 --if BCNM version dont use this - end + return 0 end mobskillObject.onMobWeaponSkill = function(target, mob, skill) diff --git a/scripts/actions/mobskills/amatsu_tsukioboro.lua b/scripts/actions/mobskills/amatsu_tsukioboro.lua index 0e5550f671a..29117676764 100644 --- a/scripts/actions/mobskills/amatsu_tsukioboro.lua +++ b/scripts/actions/mobskills/amatsu_tsukioboro.lua @@ -6,14 +6,7 @@ local mobskillObject = {} mobskillObject.onMobSkillCheck = function(target, mob, skill) - if - mob:getObjType() == xi.objType.TRUST or - mob:getAnimationSub() == 0 - then - return 0 - else - return 1 - end + return 0 end mobskillObject.onMobWeaponSkill = function(target, mob, skill) diff --git a/scripts/actions/mobskills/amatsu_yukiarashi.lua b/scripts/actions/mobskills/amatsu_yukiarashi.lua index d0c4579dda6..ebaeb7c70dc 100644 --- a/scripts/actions/mobskills/amatsu_yukiarashi.lua +++ b/scripts/actions/mobskills/amatsu_yukiarashi.lua @@ -6,14 +6,7 @@ local mobskillObject = {} mobskillObject.onMobSkillCheck = function(target, mob, skill) - if - mob:getObjType() == xi.objType.TRUST or - mob:getAnimationSub() == 0 - then - return 0 - else - return 1 - end + return 0 end mobskillObject.onMobWeaponSkill = function(target, mob, skill) diff --git a/scripts/actions/mobskills/cosmic_elucidation.lua b/scripts/actions/mobskills/cosmic_elucidation.lua index c3fc5437a7a..66835265777 100644 --- a/scripts/actions/mobskills/cosmic_elucidation.lua +++ b/scripts/actions/mobskills/cosmic_elucidation.lua @@ -14,11 +14,8 @@ mobskillObject.onMobSkillCheck = function(target, mob, skill) end mobskillObject.onMobWeaponSkill = function(target, mob, skill) - local damage = mob:getWeaponDmg() * 21 - - damage = xi.mobskills.mobMagicalMove(mob, target, skill, damage, xi.element.LIGHT, 2, xi.mobskills.magicalTpBonus.DMG_BONUS, 1) + local damage = xi.mobskills.mobMagicalMove(mob, target, skill, mob:getMainLvl() + 2, xi.element.LIGHT, 14, xi.mobskills.magicalTpBonus.NO_EFFECT, 1) damage = xi.mobskills.mobFinalAdjustments(damage, mob, skill, target, xi.attackType.MAGICAL, xi.damageType.LIGHT, 0) - damage = math.min(0, damage) -- Cosmic Elucidation does not have an absorb message target:takeDamage(damage, mob, xi.attackType.SPECIAL, xi.damageType.ELEMENTAL) skill:setMsg(xi.msg.basic.SKILLCHAIN_COSMIC_ELUCIDATION) diff --git a/scripts/actions/mobskills/oisoya.lua b/scripts/actions/mobskills/oisoya.lua index c0fcf5e6524..e2bcbcd1d36 100644 --- a/scripts/actions/mobskills/oisoya.lua +++ b/scripts/actions/mobskills/oisoya.lua @@ -11,8 +11,9 @@ local mobskillObject = {} mobskillObject.onMobSkillCheck = function(target, mob, skill) if - mob:getAnimationSub() == 5 or - mob:getAnimationSub() == 6 + (mob:getAnimationSub() == 5 or + mob:getAnimationSub() == 6) and + mob:getLocalVar('[Tenzen]ShouldOisoya') == 1 then -- if tenzen is in bow mode return 0 end @@ -22,10 +23,10 @@ end mobskillObject.onMobWeaponSkill = function(target, mob, skill) local numhits = 1 - local accmod = 1 + local accmod = 0.8 local ftp = 5.5 - local info = xi.mobskills.mobPhysicalMove(mob, target, skill, numhits, accmod, ftp, 2, 2.75, 2.75, 2.75) + local info = xi.mobskills.mobRangedMove(mob, target, skill, numhits, accmod, ftp, xi.mobskills.physicalTpBonus.ATK_VARIES, 2.75, 2.75, 2.75) local dmg = xi.mobskills.mobFinalAdjustments(info.dmg, mob, skill, target, xi.attackType.RANGED, xi.damageType.PIERCING, info.hitslanded) target:takeDamage(dmg, mob, xi.attackType.RANGED, xi.damageType.PIERCING) diff --git a/scripts/actions/mobskills/riceball.lua b/scripts/actions/mobskills/riceball.lua index c9d9e0b1674..e3c119c2fca 100644 --- a/scripts/actions/mobskills/riceball.lua +++ b/scripts/actions/mobskills/riceball.lua @@ -15,6 +15,7 @@ mobskillObject.onMobWeaponSkill = function(target, mob, skill) mob:addMod(xi.mod.VIT, 4) mob:addMod(xi.mod.CHR, 4) mob:setMod(xi.mod.DOUBLE_ATTACK, 5) + mob:setMod(xi.mod.DMGMAGIC, -2500) skill:setMsg(xi.msg.basic.NONE) diff --git a/scripts/battlefields/Sealions_Den/warriors_path.lua b/scripts/battlefields/Sealions_Den/warriors_path.lua index b313f507ad5..9f75a355d24 100644 --- a/scripts/battlefields/Sealions_Den/warriors_path.lua +++ b/scripts/battlefields/Sealions_Den/warriors_path.lua @@ -25,6 +25,12 @@ local content = BattlefieldMission:new({ title = xi.title.THE_CHEBUKKIS_WORST_NIGHTMARE, }) +function content:onBattlefieldLoss(player, battlefield) + player:messageSpecial(sealionsDenID.text.COSMIC_ELUCIDATION) + + Battlefield.onBattlefieldLoss(self, player, battlefield) +end + content.groups = { { diff --git a/scripts/enum/mob_skill.lua b/scripts/enum/mob_skill.lua index 13b83d8fe3e..479aa70f301 100644 --- a/scripts/enum/mob_skill.lua +++ b/scripts/enum/mob_skill.lua @@ -485,11 +485,12 @@ xi.mobSkill = AMATSU_TORIMAI = 1390, AMATSU_KAZAKIRI = 1391, - + AMATSU_YUKIARASHI = 1392, + AMATSU_TSUKIOBORO = 1393, AMATSU_HANAIKUSA = 1394, AMATSU_TSUKIKAGE = 1395, COSMIC_ELUCIDATION = 1396, - + OISOYA = 1397, RANGED_ATTACK_TENZEN_1 = 1398, -- Tenzen Bow High RICEBALL_TENZEN = 1399, RANGED_ATTACK_TENZEN_2 = 1400, -- Tenzen Bow Low diff --git a/scripts/zones/Sealions_Den/IDs.lua b/scripts/zones/Sealions_Den/IDs.lua index a9aead9f6aa..fba1419ee07 100644 --- a/scripts/zones/Sealions_Den/IDs.lua +++ b/scripts/zones/Sealions_Den/IDs.lua @@ -25,6 +25,7 @@ zones[xi.zone.SEALIONS_DEN] = THE_PARTY_WILL_BE_REMOVED = 7425, -- If all party members' HP are still zero after # minute[/s], the party will be removed from the battlefield. CONQUEST_BASE = 7441, -- Tallying conquest results... ENTERING_THE_BATTLEFIELD_FOR = 7604, -- Entering the battlefield for [One to Be Feared/The Warrior's Path/The Warrior's Path/One to Be Feared]! + COSMIC_ELUCIDATION = 7900, -- You are overwhelmed by Tenzen's Cosmic Elucidation! TENZEN_MSG_OFFSET = 7932, -- You will fall to my blade! MAKKI_CHEBUKKI_OFFSET = 7936, -- Samurai Sky Pirate Power! KUKKI_CHEBUKKI_OFFSET = 7941, -- What? Nooo! @@ -32,6 +33,9 @@ zones[xi.zone.SEALIONS_DEN] = }, mob = { + CHERUKIKI = GetFirstID('Cherukiki'), + KUKKI_CHEBUKKI = GetFirstID('Kukki-Chebukki'), + MAKKI_CHEBUKKI = GetFirstID('Makki-Chebukki'), MAMMET_22_ZETA = GetFirstID('Mammet-22_Zeta'), TENZEN = GetFirstID('Tenzen'), }, diff --git a/scripts/zones/Sealions_Den/mobs/Cherukiki.lua b/scripts/zones/Sealions_Den/mobs/Cherukiki.lua index 2a4f524eb69..2949d9f3b28 100644 --- a/scripts/zones/Sealions_Den/mobs/Cherukiki.lua +++ b/scripts/zones/Sealions_Den/mobs/Cherukiki.lua @@ -8,6 +8,13 @@ mixins = { require('scripts/mixins/warriors_path_taru') } ---@type TMobEntity local entity = {} +entity.onMobInitialize = function(mob) + mob:addImmunity(xi.immunity.DARK_SLEEP) + mob:addImmunity(xi.immunity.LIGHT_SLEEP) + mob:addImmunity(xi.immunity.TERROR) + mob:addMod(xi.mod.SILENCE_RES_RANK, 9) +end + entity.onMobSpawn = function(mob) -- Leaving these mods here for visual: Tarus can't take damage, don't move, and have scripted fight interactions mob:setMobMod(xi.mobMod.MAGIC_COOL, 60) -- cherukiki casts magic aproximately every 25 seconds diff --git a/scripts/zones/Sealions_Den/mobs/Kukki-Chebukki.lua b/scripts/zones/Sealions_Den/mobs/Kukki-Chebukki.lua index 1f5b95e2d74..66f28d7cb5f 100644 --- a/scripts/zones/Sealions_Den/mobs/Kukki-Chebukki.lua +++ b/scripts/zones/Sealions_Den/mobs/Kukki-Chebukki.lua @@ -7,6 +7,13 @@ mixins = { require('scripts/mixins/warriors_path_taru') } ---@type TMobEntity local entity = {} +entity.onMobInitialize = function(mob) + mob:addImmunity(xi.immunity.DARK_SLEEP) + mob:addImmunity(xi.immunity.LIGHT_SLEEP) + mob:addImmunity(xi.immunity.TERROR) + mob:addMod(xi.mod.SILENCE_RES_RANK, 9) +end + entity.onMobSpawn = function(mob) -- Leaving these mods here for visual: Tarus can't take damage, don't move, and have scripted fight interactions mob:setMobMod(xi.mobMod.MAGIC_COOL, 60) diff --git a/scripts/zones/Sealions_Den/mobs/Makki-Chebukki.lua b/scripts/zones/Sealions_Den/mobs/Makki-Chebukki.lua index 36b14307fe1..233f467bdda 100644 --- a/scripts/zones/Sealions_Den/mobs/Makki-Chebukki.lua +++ b/scripts/zones/Sealions_Den/mobs/Makki-Chebukki.lua @@ -7,6 +7,12 @@ mixins = { require('scripts/mixins/warriors_path_taru') } ---@type TMobEntity local entity = {} +entity.onMobInitialize = function(mob) + mob:addImmunity(xi.immunity.DARK_SLEEP) + mob:addImmunity(xi.immunity.LIGHT_SLEEP) + mob:addImmunity(xi.immunity.TERROR) +end + entity.onMobSpawn = function(mob) mob:setMobMod(xi.mobMod.SPECIAL_COOL, 30) -- Makki Chebukki uses ranged attack every 30 seconds mob:setMobMod(xi.mobMod.NO_AGGRO, 1) diff --git a/scripts/zones/Sealions_Den/mobs/Tenzen.lua b/scripts/zones/Sealions_Den/mobs/Tenzen.lua index 5a3b38fa9ef..054691f4019 100644 --- a/scripts/zones/Sealions_Den/mobs/Tenzen.lua +++ b/scripts/zones/Sealions_Den/mobs/Tenzen.lua @@ -7,15 +7,45 @@ local ID = zones[xi.zone.SEALIONS_DEN] ---@type TMobEntity local entity = {} +local forms = +{ + SHEATHED = 3, + MELEE = 4, + BOW_LOW = 5, + BOW_HIGH = 6, +} + +local bowPhases = +{ + NONE = 0, + START = 1, + FAST = 2, + SLOW = 3, +} + local formTable = { - [0] = { 0, 0, xi.behavior.NONE, true }, -- Melee unseathed. - [1] = { 2056, -1200, xi.behavior.STANDBACK, false }, -- Bow low. - [2] = { 2055, -2400, xi.behavior.STANDBACK, false }, -- Bow high. - [3] = { 0, 0, xi.behavior.NONE, false }, -- Melee seathed. + [forms.SHEATHED] = { skill = 0, delay = 2000, standback = xi.behavior.NONE }, + [forms.MELEE ] = { skill = 0, delay = 2000, standback = xi.behavior.NONE }, + [forms.BOW_LOW ] = { skill = 2056, delay = 2400, standback = xi.behavior.STANDBACK }, + [forms.BOW_HIGH] = { skill = 2055, delay = 1500, standback = xi.behavior.STANDBACK }, +} + +local bowSequence = +{ + [bowPhases.START] = { form = forms.BOW_LOW, minShots = 1, maxShots = 2, nextPhase = bowPhases.FAST }, + [bowPhases.FAST ] = { form = forms.BOW_HIGH, minShots = 5, maxShots = 10, nextPhase = bowPhases.SLOW }, + [bowPhases.SLOW ] = { form = forms.BOW_LOW, minShots = 1, maxShots = 5, nextPhase = bowPhases.NONE }, } -local weaponskillTable = +local normalMeikyo = +{ + [0] = { xi.mobSkill.AMATSU_YUKIARASHI }, + [1] = { xi.mobSkill.AMATSU_TSUKIOBORO }, + [2] = { xi.mobSkill.AMATSU_HANAIKUSA }, +} + +local enrageMeikyo = { [0] = { xi.mobSkill.AMATSU_HANAIKUSA }, [1] = { xi.mobSkill.AMATSU_TORIMAI }, @@ -23,108 +53,194 @@ local weaponskillTable = [3] = { xi.mobSkill.AMATSU_TSUKIKAGE }, [4] = { xi.mobSkill.COSMIC_ELUCIDATION }, } + +local taruOffsets = +{ + [ID.mob.MAKKI_CHEBUKKI] = ID.text.MAKKI_CHEBUKKI_OFFSET, + [ID.mob.KUKKI_CHEBUKKI] = ID.text.KUKKI_CHEBUKKI_OFFSET, + [ID.mob.CHERUKIKI ] = ID.text.CHERUKIKI_OFFSET, +} + local function setupForm(mob, newForm) - mob:timer(1500, function(mobArg) - mobArg:setAnimationSub(newForm) - mobArg:setMobSkillAttack(formTable[newForm][1]) - mobArg:setMod(xi.mod.DELAY, formTable[newForm][2]) - mobArg:setBehavior(formTable[newForm][3]) - mobArg:setMobAbilityEnabled(formTable[newForm][4]) - end) + mob:setAnimationSub(newForm) + mob:setMobSkillAttack(formTable[newForm].skill) + mob:setDelay(formTable[newForm].delay) + mob:setBehavior(formTable[newForm].standback) + + -- Pause for animation change before enabling auto attacks + if newForm == forms.MELEE then + mob:timer(1500, function(mobArg) + mobArg:setAutoAttackEnabled(true) + mobArg:setMobAbilityEnabled(true) + end) + end +end + +-- Setup bow phase handling +local function setupBowPhase(mob, phase) + local config = bowSequence[phase] + + setupForm(mob, config.form) + + mob:setLocalVar('[Tenzen]BowPhase', phase) + mob:setLocalVar('[Tenzen]ShotCount', 0) + mob:setLocalVar('[Tenzen]ShouldOisoya', 0) + mob:setLocalVar('[Tenzen]TransitionActive', 0) + mob:setLocalVar('[Tenzen]ShotAmount', math.random(config.minShots, config.maxShots)) end local function wsSequence(mob) local step = mob:getLocalVar('[Tenzen]MeikyoStep') - local breakChain = (step <= 3 and not mob:hasStatusEffect(xi.effect.MEIKYO_SHISUI)) and true or false -- If "Amatsu Tsukikage" happens, Cosmic Euclidation happens. You loose. - - if breakChain then + local meikyoUsed = mob:getLocalVar('[Tenzen]MeikyoUsed') + local skillchain = meikyoUsed == 1 and normalMeikyo or enrageMeikyo + local maxSteps = meikyoUsed == 1 and 2 or 4 + + if step <= maxSteps then + mob:setTP(1000) + mob:useMobAbility(skillchain[step][1]) + mob:setLocalVar('[Tenzen]MeikyoStep', step + 1) + else mob:setAutoAttackEnabled(true) mob:setMobAbilityEnabled(true) - - mob:setLocalVar('[Tenzen]MorphingTime', mob:getBattleTime()) mob:setLocalVar('[Tenzen]MeikyoActive', 0) mob:setLocalVar('[Tenzen]MeikyoStep', 0) - - return end +end - -- Chance was given to break sequence. Continue. - mob:setTP(1000) - mob:useMobAbility(weaponskillTable[step][1]) - mob:setLocalVar('[Tenzen]MeikyoStep', step + 1) +entity.onMobInitialize = function(mob) + mob:addImmunity(xi.immunity.DARK_SLEEP) + mob:addImmunity(xi.immunity.TERROR) end entity.onMobSpawn = function(mob) mob:setMod(xi.mod.DEF, 350) mob:setMod(xi.mod.REGAIN, 30) - mob:setMobMod(xi.mobMod.ROAM_DISTANCE, 0) - mob:setMobMod(xi.mobMod.ROAM_TURNS, 0) + mob:setMobMod(xi.mobMod.BASE_DAMAGE_MULTIPLIER, 150) mob:setMobMod(xi.mobMod.SIGHT_RANGE, 10) + mob:setUnkillable(true) -- Setup melee form. - setupForm(mob, 0) - - -- Reset action usage - mob:setAutoAttackEnabled(true) - mob:setMobAbilityEnabled(true) - mob:setUnkillable(true) + setupForm(mob, forms.MELEE) -- Reset local vars. - mob:setLocalVar('[Tenzen]LastWeaponskill', 0) - mob:setLocalVar('[Tenzen]Riceball', 0) - mob:setLocalVar('[Tenzen]MorphingTime', 0) - mob:setLocalVar('[Tenzen]MeikyoActive', 0) - mob:setLocalVar('[Tenzen]MeikyoUses', 0) + mob:setLocalVar('[Tenzen]BowPhase', 0) + mob:setLocalVar('[Tenzen]ShotCount', 0) + mob:setLocalVar('[Tenzen]ShotAmount', 0) + mob:setLocalVar('[Tenzen]ShouldOisoya', 0) + mob:setLocalVar('[Tenzen]TransitionActive', 0) mob:setLocalVar('[Tenzen]MeikyoStep', 0) - mob:setLocalVar('[Tenzen]MeikyoHPP', 80) + mob:setLocalVar('[Tenzen]MeikyoActive', 0) + mob:setLocalVar('[Tenzen]MeikyoUsed', 0) + mob:setLocalVar('[Tenzen]ShiftTimer', 0) + mob:setLocalVar('[Tenzen]RiceBallTimer', 0) + mob:setLocalVar('[Tenzen]LastWeaponskill', 0) + mob:setLocalVar('[Tenzen]EnrageHP', math.random(25, 30)) + mob:setLocalVar('[Tenzen]MeikyoHP', math.random(60, 80)) end entity.onMobEngage = function(mob, target) - mob:showText(mob, ID.text.TENZEN_MSG_OFFSET + 1) + mob:showText(mob, ID.text.TENZEN_MSG_OFFSET) -- Engage message - -- Update Taru helpers enmity. - local mobId = mob:getID() + local currentTime = GetSystemTime() + mob:setLocalVar('[Tenzen]ShiftTimer', currentTime + 40) + mob:setLocalVar('[Tenzen]RiceBallTimer', currentTime + math.random(90, 120)) + -- Update Taru helpers enmity. + local mobId = mob:getID() for taruId = mobId + 1, mobId + 3 do GetMobByID(taruId):updateEnmity(target) end end +entity.onMobMobskillChoose = function(mob, target) + local form = mob:getAnimationSub() + local shouldOisoya = mob:getLocalVar('[Tenzen]ShouldOisoya') == 1 + local skill = 0 + local chosenSkill = 0 + + switch (form): caseof + { + [forms.MELEE] = function() + local tpList = + { + xi.mobSkill.AMATSU_HANAIKUSA, + xi.mobSkill.AMATSU_TSUKIKAGE, + xi.mobSkill.AMATSU_TORIMAI, + xi.mobSkill.AMATSU_KAZAKIRI, + xi.mobSkill.AMATSU_YUKIARASHI, + xi.mobSkill.AMATSU_TSUKIOBORO, + } + chosenSkill = tpList[math.random(1, #tpList)] + skill = chosenSkill + end, + + [forms.BOW_LOW] = function() + if shouldOisoya then + skill = xi.mobSkill.OISOYA + else + skill = xi.mobSkill.RANGED_ATTACK_TENZEN_1 + end + end, + + [forms.BOW_HIGH] = function() + if shouldOisoya then + skill = xi.mobSkill.OISOYA + else + skill = xi.mobSkill.RANGED_ATTACK_TENZEN_2 + end + end, + } + + return skill +end + entity.onMobWeaponSkill = function(target, mob, skill) local skillId = skill:getID() -- Track last time Tenzen did a mobskill. Dont Meikyo Shisui immediately after. - mob:setLocalVar('[Tenzen]LastWeaponskill', mob:getBattleTime()) - - -- Setup weaponskill chain. - if skillId == xi.mobSkill.MEIKYO_SHISUI_1 then - mob:setAutoAttackEnabled(false) - mob:setMobAbilityEnabled(false) - - mob:setLocalVar('[Tenzen]MeikyoActive', 1) - mob:setLocalVar('[Tenzen]MeikyoUses', mob:getLocalVar('[Tenzen]MeikyoUses') + 1) - mob:setLocalVar('[Tenzen]MeikyoHPP', 60) - - -- Chance of switching from high bow form to low bow form. - elseif skillId == xi.mobSkill.RANGED_ATTACK_TENZEN_1 then - if math.random(1, 100) <= 25 then - setupForm(mob, 1) - end - - -- Chance of switching from low bow form to high bow form. - elseif skillId == xi.mobSkill.RANGED_ATTACK_TENZEN_2 then - if math.random(1, 100) <= 25 then - setupForm(mob, 2) - end - - -- Loose battle. - elseif skillId == xi.mobSkill.COSMIC_ELUCIDATION then - mob:timer(2000, function(mobArg) - mobArg:setAnimationSub(3) - mobArg:showText(mobArg, ID.text.TENZEN_MSG_OFFSET + 1) - mobArg:getBattlefield():lose() - end) - end + mob:setLocalVar('[Tenzen]LastWeaponskill', GetSystemTime() + 5) + + switch (skillId): caseof + { + [xi.mobSkill.COSMIC_ELUCIDATION] = function() + mob:timer(2000, function(mobArg) + mobArg:setAnimationSub(3) + mobArg:showText(mobArg, ID.text.TENZEN_MSG_OFFSET + 1) + mobArg:getBattlefield():lose() + end) + end, + + [xi.mobSkill.MEIKYO_SHISUI_1] = function() + mob:setAutoAttackEnabled(false) + mob:setMobAbilityEnabled(false) + + mob:setLocalVar('[Tenzen]MeikyoActive', 1) + mob:setLocalVar('[Tenzen]MeikyoStep', 0) + mob:setLocalVar('[Tenzen]ShiftTimer', GetSystemTime() + math.random(25, 70)) + setupForm(mob, forms.MELEE) + wsSequence(mob) + end, + + [xi.mobSkill.OISOYA] = function() + mob:setLocalVar('[Tenzen]ShouldOisoya', 0) + end, + + [xi.mobSkill.RANGED_ATTACK_TENZEN_1] = function() + -- Increment shot count for bow attacks. + mob:setLocalVar('[Tenzen]ShotCount', mob:getLocalVar('[Tenzen]ShotCount') + 1) + end, + + [xi.mobSkill.RANGED_ATTACK_TENZEN_2] = function() + -- Increment shot count for bow attacks. + mob:setLocalVar('[Tenzen]ShotCount', mob:getLocalVar('[Tenzen]ShotCount') + 1) + end, + + default = function() + if mob:getLocalVar('[Tenzen]MeikyoActive') == 1 then + wsSequence(mob) + end + end, + } end entity.onMobFight = function(mob, target) @@ -132,8 +248,17 @@ entity.onMobFight = function(mob, target) -- Win battle. if mobHPP <= 15 then - mob:setAnimationSub(3) - mob:showText(target, ID.text.TENZEN_MSG_OFFSET + 2) + mob:setAnimationSub(forms.SHEATHED) + mob:showText(mob, ID.text.TENZEN_MSG_OFFSET + 2) + + local mobId = mob:getID() + for taruId = mobId + 1, mobId + 3 do + local taruMob = GetMobByID(taruId) + local offset = taruOffsets[taruId] + if taruMob then + taruMob:showText(taruMob, offset + 5) + end + end mob:timer(2000, function(mobArg) mobArg:getBattlefield():win() @@ -152,49 +277,86 @@ entity.onMobFight = function(mob, target) return end - -- Scripted sequence of weaponskills in order to potentially create the level 4 skillchain cosmic elucidation - if mob:getLocalVar('[Tenzen]MeikyoActive') == 1 then - mob:timer(1500, function(mobArg) - wsSequence(mobArg) - end) - - return + -- Only if in melee form, HP <= trigger, and not already used + local meikyoHP = mob:getLocalVar('[Tenzen]MeikyoHP') + local meikyoUsed = mob:getLocalVar('[Tenzen]MeikyoUsed') + local form = mob:getAnimationSub() + local lastWS = mob:getLocalVar('[Tenzen]LastWeaponskill') < GetSystemTime() + if mobHPP <= meikyoHP and meikyoUsed == 0 and lastWS then + if form == forms.MELEE then + mob:setLocalVar('[Tenzen]MeikyoUsed', 1) + mob:useMobAbility(xi.mobSkill.MEIKYO_SHISUI_1) + + return + + -- Loses ability to Meikyo if not in melee during trigger HP + else + mob:setLocalVar('[Tenzen]MeikyoUsed', 1) + end end - -- Rice ball + -- 5 min since engage or less than random enrage HP, start enrage weaponskill chain + local enrageHP = mob:getLocalVar('[Tenzen]EnrageHP') if - mob:getHPP() <= 70 and - mob:getLocalVar('[Tenzen]Riceball') == 0 + (mob:getBattleTime() >= 300 or mob:getHPP() <= enrageHP) and + meikyoUsed < 2 and + lastWS then - mob:showText(target, ID.text.TENZEN_MSG_OFFSET + 3) - mob:useMobAbility(xi.mobSkill.RICEBALL_TENZEN) - mob:setLocalVar('[Tenzen]Riceball', 1) + mob:setLocalVar('[Tenzen]MeikyoUsed', 2) + mob:useMobAbility(xi.mobSkill.MEIKYO_SHISUI_1) + return end - -- Meikyo Shisui - if - mob:getAnimationSub() == 0 and - mob:getLocalVar('[Tenzen]LastWeaponskill') <= mob:getBattleTime() - 5 and - mob:getLocalVar('[Tenzen]MeikyoActive') == 0 and - mob:getLocalVar('[Tenzen]MeikyoUses') <= 1 and - mob:getLocalVar('[Tenzen]MeikyoHPP') >= mobHPP - then - mob:useMobAbility(xi.mobSkill.MEIKYO_SHISUI_1) + -- Melee form: wait for shift timer then begin bow sequence. + local currentTime = GetSystemTime() + if form == forms.MELEE then + -- Rice ball + local riceballTimer = mob:getLocalVar('[Tenzen]RiceBallTimer') + if + riceballTimer > 0 and + currentTime >= riceballTimer + then + mob:useMobAbility(xi.mobSkill.RICEBALL_TENZEN) + mob:setLocalVar('[Tenzen]RiceBallTimer', 0) + mob:messageText(mob, ID.text.TENZEN_MSG_OFFSET + 3, false) + + return + end + + if currentTime >= mob:getLocalVar('[Tenzen]ShiftTimer') then + setupBowPhase(mob, bowPhases.START) + end + return end - local changeTime = mob:getBattleTime() - mob:getLocalVar('[Tenzen]MorphingTime') - local animationSub = mob:getAnimationSub() - local cooldown = animationSub == 0 and 90 or 45 - - if - changeTime > cooldown and - animationSub <= 1 - then - local newForm = animationSub == 0 and 1 or 0 - mob:setLocalVar('[Tenzen]MorphingTime', mob:getBattleTime()) - setupForm(mob, newForm) + -- Bow forms: handle phase transitions based on shot count. + if form == forms.BOW_LOW or form == forms.BOW_HIGH then + local phase = mob:getLocalVar('[Tenzen]BowPhase') + local shotCount = mob:getLocalVar('[Tenzen]ShotCount') + local shotAmount = mob:getLocalVar('[Tenzen]ShotAmount') + + -- All shots fired, transition to next phase. + if shotCount >= shotAmount then + local phaseConfig = bowSequence[phase] + + -- Return to melee + if not phaseConfig or phaseConfig.nextPhase == 0 then + mob:setLocalVar('[Tenzen]ShiftTimer', currentTime + math.random(25, 70)) + mob:setLocalVar('[Tenzen]ShotCount', 0) + mob:setLocalVar('[Tenzen]BowPhase', 0) + setupForm(mob, forms.MELEE) + + return + end + + -- Transition to next bow phase. + mob:setLocalVar('[Tenzen]ShouldOisoya', 1) + mob:timer(1500, function(mobArg) + setupBowPhase(mob, phaseConfig.nextPhase) + end) + end end end diff --git a/sql/mob_groups.sql b/sql/mob_groups.sql index c660724acf8..a74ace69a5d 100644 --- a/sql/mob_groups.sql +++ b/sql/mob_groups.sql @@ -1234,7 +1234,7 @@ INSERT INTO `mob_groups` VALUES (16,1160,31,'Earth_Elemental',0,128,733,0,0,99,9 INSERT INTO `mob_groups` VALUES (1,2500,32,'Mammet-22_Zeta',0,128,1585,4000,0,55,56,0); INSERT INTO `mob_groups` VALUES (2,2973,32,'Omega',0,128,0,14000,0,63,64,0); INSERT INTO `mob_groups` VALUES (3,4083,32,'Ultima',0,128,0,15000,0,63,64,0); -INSERT INTO `mob_groups` VALUES (4,3875,32,'Tenzen',0,128,0,15000,0,75,75,0); +INSERT INTO `mob_groups` VALUES (4,3875,32,'Tenzen',0,128,0,15000,0,70,70,0); INSERT INTO `mob_groups` VALUES (5,2492,32,'Makki-Chebukki',0,128,0,50000,0,67,67,0); INSERT INTO `mob_groups` VALUES (6,2293,32,'Kukki-Chebukki',0,128,0,50000,0,67,67,0); INSERT INTO `mob_groups` VALUES (7,710,32,'Cherukiki',0,128,0,50000,0,67,67,0); diff --git a/sql/mob_pools.sql b/sql/mob_pools.sql index 76af4993082..b4931ae6e2f 100644 --- a/sql/mob_pools.sql +++ b/sql/mob_pools.sql @@ -3931,7 +3931,7 @@ INSERT INTO `mob_pools` VALUES (3871,'Temple_Bee','Temple_Bee',48,0x000011010000 INSERT INTO `mob_pools` VALUES (3872,'Temple_Guardian','Temple_Guardian',85,0x0000300100000000000000000000000000000000,1,1,12,240,100,0,0,0,0,32,0,0,7,131,4,0,0,0,0,85,85,1,30); INSERT INTO `mob_pools` VALUES (3873,'Temple_Knight','Temple_Knight',145,0x0100020300100B201A301A401A50FA601C700080,7,1,3,240,100,0,0,0,0,0,0,0,0,3,0,0,4,0,0,145,145,1,8); INSERT INTO `mob_pools` VALUES (3874,'Temple_Opo-opo','Temple_Opo-opo',188,0x0000A00100000000000000000000000000000000,1,1,7,200,100,0,0,0,1,0,0,0,184,131,0,0,0,0,0,188,188,1,18); -INSERT INTO `mob_pools` VALUES (3875,'Tenzen','Tenzen',149,0x00009E0400000000000000000000000000000000,12,11,10,240,100,0,1,1,0,2,22560,32,33,155,0,0,0,0,0,149,149,1,10); +INSERT INTO `mob_pools` VALUES (3875,'Tenzen','Tenzen',149,0x00009E0400000000000000000000000000000000,12,11,10,200,100,0,1,1,0,18,0,32,33,155,0,0,0,0,0,149,149,1,10); INSERT INTO `mob_pools` VALUES (3876,'Ten_of_Batons','Ten_of_Batons',61,0x0000AF0100000000000000000000000000000000,4,4,12,240,100,0,1,0,1,0,0,0,284,131,8,0,2,0,0,61,61,1,12); INSERT INTO `mob_pools` VALUES (3877,'Ten_of_Coins','Ten_of_Coins',61,0x0000AF0100000000000000000000000000000000,5,5,11,240,100,0,1,0,1,0,0,0,257,131,8,0,3,0,0,61,61,1,12); INSERT INTO `mob_pools` VALUES (3878,'Ten_of_Cups','Ten_of_Cups',61,0x0000AF0100000000000000000000000000000000,3,3,12,240,100,0,1,0,1,0,0,0,2223,131,8,0,20,0,0,61,61,1,12); diff --git a/sql/mob_skills.sql b/sql/mob_skills.sql index a45890b3330..1b178a25d67 100644 --- a/sql/mob_skills.sql +++ b/sql/mob_skills.sql @@ -1420,10 +1420,10 @@ INSERT INTO `mob_skills` VALUES (1392,1039,'amatsu_yukiarashi',0,0.0,15.0,2000,1 INSERT INTO `mob_skills` VALUES (1393,1040,'amatsu_tsukioboro',0,0.0,15.0,2000,1000,4,0,0,0,10,5,0); INSERT INTO `mob_skills` VALUES (1394,1041,'amatsu_hanaikusa',0,0.0,15.0,2000,1000,4,0,0,0,11,2,0); INSERT INTO `mob_skills` VALUES (1395,1036,'amatsu_tsukikage',0,0.0,15.0,2000,1000,4,0,0,0,12,6,0); -INSERT INTO `mob_skills` VALUES (1396,1035,'cosmic_elucidation',0,0.0,15.0,2000,1000,4,0,0,0,0,0,0); -- cosmic elucidation +INSERT INTO `mob_skills` VALUES (1396,1035,'cosmic_elucidation',0,0.0,15.0,2000,0,4,0,0,0,0,0,0); -- cosmic elucidation INSERT INTO `mob_skills` VALUES (1397,1042,'oisoya',0,0.0,15.0,2000,1000,4,0,0,0,0,0,0); INSERT INTO `mob_skills` VALUES (1398,1034,'tenzen_ranged_high',0,0.0,25.0,2000,0,4,4,0,0,0,0,0); -- tenzen ranged attack -INSERT INTO `mob_skills` VALUES (1399,1032,'riceball',0,0.0,15.0,2000,1500,1,0,0,0,0,0,0); -- riceball eating +INSERT INTO `mob_skills` VALUES (1399,1032,'riceball',0,0.0,15.0,2000,0,1,0,0,0,0,0,0); -- riceball eating INSERT INTO `mob_skills` VALUES (1400,1033,'tenzen_ranged_low',0,0.0,25.0,2000,0,4,4,0,0,0,0,0); -- tenzen ranged attack INSERT INTO `mob_skills` VALUES (1401,138,'soul_accretion',0,0.0,7.0,2000,1500,4,0,0,0,0,0,0); -- INSERT INTO `mob_skills` VALUES (1402,1146,'.',0,0.0,7.0,2000,1500,4,0,0,0,0,0,0);