From c1235491314144796895c8ccdafc20ef84044e9f Mon Sep 17 00:00:00 2001 From: Skold177 <113406182+Skold177@users.noreply.github.com> Date: Thu, 1 Jan 2026 12:41:01 -0500 Subject: [PATCH 1/2] [lua] [sql] KSNM Contaminated Colosseum Updates Contaminated Colosseum with a capture from retail. --- .../mobskills/extremely_bad_breath.lua | 12 +- scripts/actions/mobskills/impale_bind.lua | 20 +++ scripts/enum/mob_skill.lua | 2 +- .../zones/Horlais_Peak/mobs/Evil_Oscar.lua | 159 +++++++++++------- sql/mob_groups.sql | 2 +- sql/mob_pools.sql | 2 +- sql/mob_skill_lists.sql | 1 + sql/mob_skills.sql | 4 +- sql/mob_spawn_points.sql | 4 +- 9 files changed, 131 insertions(+), 75 deletions(-) create mode 100644 scripts/actions/mobskills/impale_bind.lua diff --git a/scripts/actions/mobskills/extremely_bad_breath.lua b/scripts/actions/mobskills/extremely_bad_breath.lua index aeaa7aed353..d82a1d5bd70 100644 --- a/scripts/actions/mobskills/extremely_bad_breath.lua +++ b/scripts/actions/mobskills/extremely_bad_breath.lua @@ -1,13 +1,10 @@ ----------------------------------- -- Extremely Bad Breath --- A horrific case of halitosis instantly K.O.'s any players in a fan-shaped area of effect. --- --- Description +-- Description : A horrific case of halitosis instantly K.O.'s any players in a fan-shaped area of effect. -- Family: Morbol -- Type: Breath --- Can be dispelled: N/A +-- Range: 12' AoE -- Utsusemi/Blink absorb: Ignores shadows --- Range: Unknown cone -- Notes: Only used by Evil Oscar, Cirrate Christelle, Lividroot Amooshah, Eccentric Eve, Deranged Ameretat, and Melancholic Moira. ----------------------------------- ---@type TMobSkill @@ -17,10 +14,11 @@ mobskillObject.onMobSkillCheck = function(target, mob, skill) return 0 end +-- TODO: Death resistance check mobskillObject.onMobWeaponSkill = function(target, mob, skill) - local dmg = target:getHP() + skill:setMsg(xi.msg.basic.FALL_TO_GROUND) target:setHP(0) - return dmg + return 0 end return mobskillObject diff --git a/scripts/actions/mobskills/impale_bind.lua b/scripts/actions/mobskills/impale_bind.lua new file mode 100644 index 00000000000..8b2e98dcea3 --- /dev/null +++ b/scripts/actions/mobskills/impale_bind.lua @@ -0,0 +1,20 @@ +----------------------------------- +-- Impale (Bind version) +-- Description: Inflicts Bind on a single target +-- TODO: Check if this is supposed to ignore shadows or not & exact range. +-- NOTE: Does not deal damage, a miss returns "no effect". +----------------------------------- +---@type TMobSkill +local mobskillObject = {} + +mobskillObject.onMobSkillCheck = function(target, mob, skill) + return 0 +end + +mobskillObject.onMobWeaponSkill = function(target, mob, skill) + skill:setMsg(xi.mobskills.mobStatusEffectMove(mob, target, xi.effect.BIND, 1, 0, 15)) + + return xi.effect.BIND +end + +return mobskillObject diff --git a/scripts/enum/mob_skill.lua b/scripts/enum/mob_skill.lua index 1e953c3fbe1..9c36adcb910 100644 --- a/scripts/enum/mob_skill.lua +++ b/scripts/enum/mob_skill.lua @@ -456,7 +456,7 @@ xi.mobSkill = HOOF_VOLLEY = 1330, COUNTERSTANCE = 1331, -- The Waughroon Kid - + EXTREMELY_BAD_BREATH_1 = 1332, CONTAGION_TRANSFER = 1333, CONTAMINATION = 1334, TOXIC_PICK = 1335, diff --git a/scripts/zones/Horlais_Peak/mobs/Evil_Oscar.lua b/scripts/zones/Horlais_Peak/mobs/Evil_Oscar.lua index ef5d0630087..00e125c4186 100644 --- a/scripts/zones/Horlais_Peak/mobs/Evil_Oscar.lua +++ b/scripts/zones/Horlais_Peak/mobs/Evil_Oscar.lua @@ -1,91 +1,128 @@ ----------------------------------- -- Area: Horlais Peak -- Mob: Evil Oscar --- KSNM30 --- --- DONE: If you are out of range of EBB, the move will be lost --- TODO: There should be a 'No targets within range' message --- --- ['Evil Oscar-17346750'] = --- { --- [4] = --- { --- -- NOTE: This looks to be the no target message --- [0] = { ['name']='', ['category']=4, ['id']=0, ['animation']=508, ['message']=76, }, --- }, --- --- [11] = --- { --- [317] = { ['name']='Vampiric Lash', ['category']=11, ['id']=317, ['animation']=61, ['message']=31, }, --- [320] = { ['name']='Sweet Breath', ['category']=11, ['id']=320, ['animation']=64, ['message']=185, }, --- [1332] = { ['name']='Extremely Bad Breath', ['category']=11, ['id']=1332, ['animation']=63, ['message']=406, }, --- }, --- }, +-- KSNM30: Contaminated Colliseum ----------------------------------- local ID = zones[xi.zone.HORLAIS_PEAK] ----------------------------------- ---@type TMobEntity local entity = {} -local extremelyBadBreathID = 1332 +-- { Phase HP%, First Inhale Delay, Interval Delay } +local breathTimers = +{ + [1] = { 30, 10, 4 }, + [2] = { 40, 12, 6 }, + [3] = { 50, 14, 8 }, + [4] = { 60, 16, 10 }, + [5] = { 70, 18, 12 }, + [6] = { 80, 20, 14 }, + [7] = { 90, 22, 16 }, + [8] = { 99, 24, 18 }, + [9] = { 100, 26, 20 }, +} -local sendMessage = function(players) - for _, member in pairs(players) do - member:messageSpecial(ID.text.EVIL_OSCAR_BEGINS_FILLING) +local function sendInhaleMessage(players) + for _, player in pairs(players) do + player:messageSpecial(ID.text.EVIL_OSCAR_BEGINS_FILLING) end end -local evilOscarFillsHisLungs -evilOscarFillsHisLungs = function(mob) - if not mob:isAlive() then +local function setupPhase(mob, phase) + mob:setLocalVar('currentPhase', phase) + mob:setLocalVar('firstDelay', breathTimers[phase][2]) + mob:setLocalVar('intervalDelay', breathTimers[phase][3]) +end + +entity.onMobInitialize = function(mob) + mob:setMobMod(xi.mobMod.ADD_EFFECT, 1) + mob:addImmunity(xi.immunity.LIGHT_SLEEP) + mob:addImmunity(xi.immunity.DARK_SLEEP) + mob:addImmunity(xi.immunity.PARALYZE) + mob:addImmunity(xi.immunity.PETRIFY) + mob:addImmunity(xi.immunity.STUN) + mob:addImmunity(xi.immunity.TERROR) + mob:setMobMod(xi.mobMod.BASE_DAMAGE_MULTIPLIER, 150) +end + +entity.onMobSpawn = function(mob) + mob:setMod(xi.mod.DOUBLE_ATTACK, 65) + mob:addListener('WEAPONSKILL_STATE_EXIT', 'EXTREMELY_BAD_BREATH_ATTEMPTED', function(mobArg, skillId) + if skillId == xi.mobSkill.EXTREMELY_BAD_BREATH_1 then + -- If we have readied Extremely Bad Breath, kick off the next cycle + local firstDelay = mobArg:getLocalVar('firstDelay') + + mobArg:setLocalVar('inhaleCount', 0) + mobArg:setLocalVar('nextInhaleTime', GetSystemTime() + firstDelay) + end + end) +end + +entity.onMobEngage = function(mob, target) + setupPhase(mob, 9) -- Start at phase 9 (100% HP) + mob:setLocalVar('inhaleCount', 0) + mob:setLocalVar('nextInhaleTime', GetSystemTime() + 15) -- First inhale is 15 seconds after engaging +end + +entity.onMobFight = function(mob, target) + if xi.combat.behavior.isEntityBusy(mob) then return end - local battlefield = mob:getBattlefield() - local players = battlefield:getPlayers() + local currentPhase = mob:getLocalVar('currentPhase') + + -- Check for phase transition based off of HP Percent, if so, call setPhase to update intervals - if were in the last phase, skip this + if currentPhase > 1 then + local mobHPP = mob:getHPP() + local phaseHPP = breathTimers[currentPhase][1] - local someoneIsAlive = false - for _, member in pairs(players) do - if member:isAlive() then - someoneIsAlive = true + -- If we dropped below the next HP threshold, go to the next phase and update timers + if mobHPP < phaseHPP then + currentPhase = currentPhase - 1 + setupPhase(mob, currentPhase) end end - if someoneIsAlive then - local ebbBreathCounter = mob:getLocalVar('EBB_BREATH_COUNTER') - if ebbBreathCounter < 2 then -- Charge two breaths - sendMessage(players) - mob:setLocalVar('EBB_BREATH_COUNTER', ebbBreathCounter + 1) - else -- On the third breath, fire straight away! - sendMessage(players) - mob:setLocalVar('EBB_BREATH_COUNTER', 0) - mob:useMobAbility(extremelyBadBreathID) - end + local inhaleCount = mob:getLocalVar('inhaleCount') - -- Every 10-20 seconds - mob:timer(math.random(10000, 20000), evilOscarFillsHisLungs) - end -end + -- If inhale count is less than 3, check to see if it's time to inhale again + if inhaleCount < 3 then + local currentTime = GetSystemTime() + local nextInhaleTime = mob:getLocalVar('nextInhaleTime') -entity.onMobInitialize = function(mob) - -- Melee attacks have Additional effect: Weight. - mob:setMobMod(xi.mobMod.ADD_EFFECT, 1) - mob:setMobMod(xi.mobMod.BASE_DAMAGE_MULTIPLIER, 150) -end + -- If its not time yet, return + if currentTime < nextInhaleTime then + return + end -entity.onAdditionalEffect = function(mob, target, damage) - return xi.mob.onAddEffect(mob, target, damage, xi.mob.ae.WEIGHT) -end + -- It's time to inhale, send message to players in battlefield regardless of distance and increment inhale count + local battlefield = mob:getBattlefield() + if battlefield then + sendInhaleMessage(battlefield:getPlayers()) + end -entity.onMobSpawn = function(mob) -end + inhaleCount = inhaleCount + 1 + mob:setLocalVar('inhaleCount', inhaleCount) -entity.onMobEngage = function(mob, target) - -- Start breaths rotation after 10-20 seconds - mob:timer(math.random(10000, 20000), evilOscarFillsHisLungs) + if inhaleCount < 3 then + local intervalDelay = mob:getLocalVar('intervalDelay') + mob:setLocalVar('nextInhaleTime', currentTime + intervalDelay) + else + mob:setLocalVar('nextInhaleTime', 0) + end + end + + -- If we've inhaled 3 times, use Extremely Bad Breath when the target is in range and not busy + if + inhaleCount >= 3 and + mob:checkDistance(target) <= 10 + then + mob:useMobAbility(xi.mobSkill.EXTREMELY_BAD_BREATH_1) + end end -entity.onMobDeath = function(mob, player, optParams) +entity.onAdditionalEffect = function(mob, target, damage) + return xi.mob.onAddEffect(mob, target, damage, xi.mob.ae.WEIGHT, { chance = 10, power = 75 }) end return entity diff --git a/sql/mob_groups.sql b/sql/mob_groups.sql index ae7838858aa..0d96a996309 100644 --- a/sql/mob_groups.sql +++ b/sql/mob_groups.sql @@ -10487,7 +10487,7 @@ INSERT INTO `mob_groups` VALUES (31,3026,139,'Orcish_Onager',0,128,0,0,0,60,60,0 INSERT INTO `mob_groups` VALUES (32,1100,139,'Dragonian_Berzerker',0,128,0,8250,0,75,75,0); INSERT INTO `mob_groups` VALUES (33,1101,139,'Dragonian_Minstrel',0,128,0,8250,0,75,75,0); INSERT INTO `mob_groups` VALUES (34,230,139,'Aries',0,128,0,12400,12600,79,79,0); -INSERT INTO `mob_groups` VALUES (35,1265,139,'Evil_Oscar',0,128,0,13790,0,80,80,0); +INSERT INTO `mob_groups` VALUES (35,1265,139,'Evil_Oscar',0,128,0,13000,0,80,80,0); INSERT INTO `mob_groups` VALUES (36,6861,139,'Malodorous_Mort',0,128,0,0,0,0,0,0); INSERT INTO `mob_groups` VALUES (37,6862,139,'Mortobello',0,128,0,0,0,0,0,0); INSERT INTO `mob_groups` VALUES (38,6863,139,'Bruteborn_Krushkosh',0,128,0,0,0,0,0,0); diff --git a/sql/mob_pools.sql b/sql/mob_pools.sql index 4e2124a6565..667d548f047 100644 --- a/sql/mob_pools.sql +++ b/sql/mob_pools.sql @@ -1320,7 +1320,7 @@ INSERT INTO `mob_pools` VALUES (1261,'Eurymedon','Eurymedon',126,0x0000800200000 INSERT INTO `mob_pools` VALUES (1262,'Eurytos','Eurytos',126,0x0000C30200000000000000000000000000000000,11,1,5,240,100,0,1,0,1,2,0,32,0,1181,0,0,0,0,0,126,126,2,34); INSERT INTO `mob_pools` VALUES (1263,'Evil_Armory','Evil_Armory',110,0x0000DE0100000000000000000000000000000000,5,5,3,240,100,0,1,1,1,18,0,0,2887,1671,16,0,3,0,256,110,110,NULL,NULL); INSERT INTO `mob_pools` VALUES (1264,'Evil_Eye','Evil_Eye',4,0x0000080100000000000000000000000000000000,1,4,11,240,100,0,1,0,0,0,0,0,1104,1155,16,0,11,0,0,4,4,1,24); -INSERT INTO `mob_pools` VALUES (1265,'Evil_Oscar','Evil_Oscar',186,0x00007C0100000000000000000000000000000000,1,1,7,200,100,0,1,1,0,18,6152,32,1642,1183,0,0,0,0,0,1157,186,3,44); +INSERT INTO `mob_pools` VALUES (1265,'Evil_Oscar','Evil_Oscar',186,0x00007C0100000000000000000000000000000000,1,1,7,260,100,0,1,1,0,18,6152,32,1642,1183,0,0,0,0,0,1157,186,3,44); INSERT INTO `mob_pools` VALUES (1266,'Evil_Spirit','Evil_Spirit',121,0x0000700100000000000000000000000000000000,4,4,12,240,100,0,1,0,0,0,0,0,292,1155,0,0,28,0,0,121,121,1,8); INSERT INTO `mob_pools` VALUES (1267,'Evil_Weapon','Evil_Weapon',110,0x0000C30100000000000000000000000000000000,1,1,3,240,100,0,1,0,0,0,0,0,1294,1667,8,0,0,0,0,110,110,1,20); INSERT INTO `mob_pools` VALUES (1268,'Bigclaw_fished','Bigclaw',77,0x0000640100000000000000000000000000000000,7,7,4,240,100,0,1,0,0,4,0,0,85,131,0,0,0,0,0,77,77,1,13); diff --git a/sql/mob_skill_lists.sql b/sql/mob_skill_lists.sql index 96539d18f38..8508371cc24 100644 --- a/sql/mob_skill_lists.sql +++ b/sql/mob_skill_lists.sql @@ -3729,6 +3729,7 @@ INSERT INTO `mob_skill_lists` VALUES ('Galarhigg',1156,625); -- vulture_2 INSERT INTO `mob_skill_lists` VALUES ('Galarhigg',1156,626); -- vulture_3 INSERT INTO `mob_skill_lists` VALUES ('Galarhigg',1156,627); -- vulture_4 +INSERT INTO `mob_skill_lists` VALUES ('Evil_Oscar',1157,316); -- Impale (Bind effect) INSERT INTO `mob_skill_lists` VALUES ('Evil_Oscar',1157,317); -- Vampiric Lash INSERT INTO `mob_skill_lists` VALUES ('Evil_Oscar',1157,320); -- Sweet Breath diff --git a/sql/mob_skills.sql b/sql/mob_skills.sql index c49b6ff1683..7bd0c0b25c6 100644 --- a/sql/mob_skills.sql +++ b/sql/mob_skills.sql @@ -340,7 +340,7 @@ INSERT INTO `mob_skills` VALUES (312,56,'shakeshroom',0,0.0,14.7,2000,1500,4,0,0 INSERT INTO `mob_skills` VALUES (313,201,'counterspore',0,0.0,15.0,2000,0,4,0,0,4,0,0,0); INSERT INTO `mob_skills` VALUES (314,58,'silence_gas',4,0.0,17.0,2000,1500,4,0,0,0,0,0,0); INSERT INTO `mob_skills` VALUES (315,59,'dark_spore',4,0.0,17.0,2000,1500,4,0,0,0,0,0,0); -INSERT INTO `mob_skills` VALUES (316,60,'impale',0,0.0,7.0,2000,1500,4,0,0,0,0,0,0); +INSERT INTO `mob_skills` VALUES (316,60,'impale_bind',0,0.0,7.0,2000,1500,4,0,0,0,0,0,0); INSERT INTO `mob_skills` VALUES (317,61,'vampiric_lash',0,0.0,7.0,2000,1500,4,0,0,0,0,0,0); INSERT INTO `mob_skills` VALUES (318,401,'somersault',0,0.0,7.0,2000,1500,4,0,0,0,0,0,0); INSERT INTO `mob_skills` VALUES (319,63,'bad_breath',4,0.0,15.0,2000,1500,4,0,0,0,0,0,0); @@ -1356,7 +1356,7 @@ INSERT INTO `mob_skills` VALUES (1328,991,'ink_jet_fee',0,0.0,12.0,2000,0,4,4,0, INSERT INTO `mob_skills` VALUES (1329,990,'gala_macabre',1,0.0,10.0,2000,1500,4,0,0,0,0,0,0); INSERT INTO `mob_skills` VALUES (1330,910,'hoof_volley',0,0.0,7.0,2000,1500,4,0,0,6,0,0,0); INSERT INTO `mob_skills` VALUES (1331,437,'counterstance',0,0.0,7.0,2000,0,1,0,0,0,0,0,0); -INSERT INTO `mob_skills` VALUES (1332,63,'extremely_bad_breath',4,0.0,10.0,2000,1500,4,0,0,0,0,0,0); +INSERT INTO `mob_skills` VALUES (1332,63,'extremely_bad_breath',1,0.0,12.0,2000,4000,4,4,0,0,0,0,0); INSERT INTO `mob_skills` VALUES (1333,152,'contagion_transfer',0,0.0,7.0,2000,1500,4,0,0,0,0,0,0); INSERT INTO `mob_skills` VALUES (1334,154,'contamination',1,0.0,16.0,2000,1500,4,0,0,0,0,0,0); INSERT INTO `mob_skills` VALUES (1335,151,'toxic_pick',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 231123d75af..3828b79956f 100644 --- a/sql/mob_spawn_points.sql +++ b/sql/mob_spawn_points.sql @@ -50139,10 +50139,10 @@ INSERT INTO `mob_spawn_points` VALUES (17346742,0,'Dragonian_Minstrel','Dragonia -- Today's Horoscope INSERT INTO `mob_spawn_points` VALUES (17346744,0,'Aries','Aries',34,-396.153,94.703,-64.349,46); INSERT INTO `mob_spawn_points` VALUES (17346746,0,'Aries','Aries',34,-156.218,-25.306,115.621,46); -INSERT INTO `mob_spawn_points` VALUES (17346748,0,'Aries','Aries',34,83.775,-145.323,295.455,46); +INSERT INTO `mob_spawn_points` VALUES (17346748,0,'Aries','Aries',34,83.834,-145.788,295.622,46); -- Contaminated Colosseum -INSERT INTO `mob_spawn_points` VALUES (17346750,0,'Evil_Oscar','Evil Oscar',35,-396.000,94.000,-63.000,46); +INSERT INTO `mob_spawn_points` VALUES (17346750,0,'Evil_Oscar','Evil Oscar',35,-396.153,94.703,-64.349,46); INSERT INTO `mob_spawn_points` VALUES (17346752,0,'Evil_Oscar','Evil Oscar',35,-156.065,-26.009,116.970,46); INSERT INTO `mob_spawn_points` VALUES (17346754,0,'Evil_Oscar','Evil Oscar',35,83.928,-146.026,296.804,46); From e36c8d70d5ec1e571480ff72a8039fe4e33e61e2 Mon Sep 17 00:00:00 2001 From: Xaver-DaRed Date: Fri, 2 Jan 2026 15:56:33 +0100 Subject: [PATCH 2/2] Add "resist death" logic and simplify combat flow --- .../mobskills/extremely_bad_breath.lua | 10 +- scripts/actions/spells/black/death.lua | 7 +- .../zones/Horlais_Peak/mobs/Evil_Oscar.lua | 99 +++++++------------ 3 files changed, 45 insertions(+), 71 deletions(-) diff --git a/scripts/actions/mobskills/extremely_bad_breath.lua b/scripts/actions/mobskills/extremely_bad_breath.lua index d82a1d5bd70..e5217bbe923 100644 --- a/scripts/actions/mobskills/extremely_bad_breath.lua +++ b/scripts/actions/mobskills/extremely_bad_breath.lua @@ -14,10 +14,14 @@ mobskillObject.onMobSkillCheck = function(target, mob, skill) return 0 end --- TODO: Death resistance check mobskillObject.onMobWeaponSkill = function(target, mob, skill) - skill:setMsg(xi.msg.basic.FALL_TO_GROUND) - target:setHP(0) + if math.random(1, 100) <= target:getMod(xi.mod.DEATHRES) then + skill:setMsg(xi.msg.basic.SKILL_MISS) + else + skill:setMsg(xi.msg.basic.FALL_TO_GROUND) + target:setHP(0) + end + return 0 end diff --git a/scripts/actions/spells/black/death.lua b/scripts/actions/spells/black/death.lua index 32ead402dae..628e08256cd 100644 --- a/scripts/actions/spells/black/death.lua +++ b/scripts/actions/spells/black/death.lua @@ -46,10 +46,11 @@ spellObject.onSpellCast = function(caster, target, spell) -- Not-player spell. else - if math.random(1, 100) > target:getMod(xi.mod.DEATHRES) then - target:setHP(0) - else + if math.random(1, 100) <= target:getMod(xi.mod.DEATHRES) then + spell:setModifier(xi.msg.actionModifier.RESIST) -- Resist! spell:setMsg(xi.msg.basic.MAGIC_NO_EFFECT) + else + target:setHP(0) end return 0 diff --git a/scripts/zones/Horlais_Peak/mobs/Evil_Oscar.lua b/scripts/zones/Horlais_Peak/mobs/Evil_Oscar.lua index 00e125c4186..97df4da5596 100644 --- a/scripts/zones/Horlais_Peak/mobs/Evil_Oscar.lua +++ b/scripts/zones/Horlais_Peak/mobs/Evil_Oscar.lua @@ -22,46 +22,37 @@ local breathTimers = [9] = { 100, 26, 20 }, } -local function sendInhaleMessage(players) - for _, player in pairs(players) do - player:messageSpecial(ID.text.EVIL_OSCAR_BEGINS_FILLING) +local function calculatePhase(mob) + local mobHPP = mob:getHPP() + for phase = 1, 9 do + if mobHPP <= breathTimers[phase][1] then + return phase + end end end -local function setupPhase(mob, phase) - mob:setLocalVar('currentPhase', phase) - mob:setLocalVar('firstDelay', breathTimers[phase][2]) - mob:setLocalVar('intervalDelay', breathTimers[phase][3]) -end - entity.onMobInitialize = function(mob) - mob:setMobMod(xi.mobMod.ADD_EFFECT, 1) mob:addImmunity(xi.immunity.LIGHT_SLEEP) mob:addImmunity(xi.immunity.DARK_SLEEP) mob:addImmunity(xi.immunity.PARALYZE) mob:addImmunity(xi.immunity.PETRIFY) mob:addImmunity(xi.immunity.STUN) mob:addImmunity(xi.immunity.TERROR) - mob:setMobMod(xi.mobMod.BASE_DAMAGE_MULTIPLIER, 150) + + mob:setMobMod(xi.mobMod.ADD_EFFECT, 1) end entity.onMobSpawn = function(mob) mob:setMod(xi.mod.DOUBLE_ATTACK, 65) - mob:addListener('WEAPONSKILL_STATE_EXIT', 'EXTREMELY_BAD_BREATH_ATTEMPTED', function(mobArg, skillId) - if skillId == xi.mobSkill.EXTREMELY_BAD_BREATH_1 then - -- If we have readied Extremely Bad Breath, kick off the next cycle - local firstDelay = mobArg:getLocalVar('firstDelay') + mob:setMobMod(xi.mobMod.BASE_DAMAGE_MULTIPLIER, 150) - mobArg:setLocalVar('inhaleCount', 0) - mobArg:setLocalVar('nextInhaleTime', GetSystemTime() + firstDelay) - end - end) + mob:setLocalVar('inhaleCount', 0) end entity.onMobEngage = function(mob, target) - setupPhase(mob, 9) -- Start at phase 9 (100% HP) - mob:setLocalVar('inhaleCount', 0) - mob:setLocalVar('nextInhaleTime', GetSystemTime() + 15) -- First inhale is 15 seconds after engaging + if mob:getLocalVar('nextInhaleTime') == 0 then + mob:setLocalVar('nextInhaleTime', GetSystemTime() + 15) -- First inhale is 15 seconds after engaging. + end end entity.onMobFight = function(mob, target) @@ -69,56 +60,34 @@ entity.onMobFight = function(mob, target) return end - local currentPhase = mob:getLocalVar('currentPhase') - - -- Check for phase transition based off of HP Percent, if so, call setPhase to update intervals - if were in the last phase, skip this - if currentPhase > 1 then - local mobHPP = mob:getHPP() - local phaseHPP = breathTimers[currentPhase][1] - - -- If we dropped below the next HP threshold, go to the next phase and update timers - if mobHPP < phaseHPP then - currentPhase = currentPhase - 1 - setupPhase(mob, currentPhase) - end - end - + -- If we've inhaled 3 times, use Extremely Bad Breath when the target is in range. local inhaleCount = mob:getLocalVar('inhaleCount') - - -- If inhale count is less than 3, check to see if it's time to inhale again - if inhaleCount < 3 then - local currentTime = GetSystemTime() - local nextInhaleTime = mob:getLocalVar('nextInhaleTime') - - -- If its not time yet, return - if currentTime < nextInhaleTime then - return - end - - -- It's time to inhale, send message to players in battlefield regardless of distance and increment inhale count - local battlefield = mob:getBattlefield() - if battlefield then - sendInhaleMessage(battlefield:getPlayers()) - end - - inhaleCount = inhaleCount + 1 - mob:setLocalVar('inhaleCount', inhaleCount) - - if inhaleCount < 3 then - local intervalDelay = mob:getLocalVar('intervalDelay') - mob:setLocalVar('nextInhaleTime', currentTime + intervalDelay) - else - mob:setLocalVar('nextInhaleTime', 0) - end - end - - -- If we've inhaled 3 times, use Extremely Bad Breath when the target is in range and not busy if inhaleCount >= 3 and mob:checkDistance(target) <= 10 then mob:useMobAbility(xi.mobSkill.EXTREMELY_BAD_BREATH_1) + mob:setLocalVar('inhaleCount', 0) + mob:setLocalVar('nextInhaleTime', GetSystemTime() + breathTimers[calculatePhase(mob)][2]) + return + end + + -- Inhale: Timer check. + if GetSystemTime() < mob:getLocalVar('nextInhaleTime') then + return end + + -- Inhale: Message handling. + local battlefield = mob:getBattlefield() + if battlefield then + for _, player in pairs(battlefield:getPlayers()) do + player:messageSpecial(ID.text.EVIL_OSCAR_BEGINS_FILLING) + end + end + + -- Inhale: Timer and count handling. + mob:setLocalVar('inhaleCount', inhaleCount + 1) + mob:setLocalVar('nextInhaleTime', GetSystemTime() + breathTimers[calculatePhase(mob)][3]) end entity.onAdditionalEffect = function(mob, target, damage)