From 13f848373b6c2863b131c8e3aa87da4f0358a4d2 Mon Sep 17 00:00:00 2001 From: Skold <113406182+Skold177@users.noreply.github.com> Date: Mon, 4 May 2026 22:03:33 -0400 Subject: [PATCH] [lua] [sql] Pulling the Strings Implements Pulling the Strings --- scripts/actions/mobskills/arcuballista.lua | 37 + scripts/actions/mobskills/barrage.lua | 16 +- scripts/actions/mobskills/blood_pact.lua | 21 + scripts/actions/mobskills/chimera_ripper.lua | 15 +- scripts/actions/mobskills/counterstance_4.lua | 23 + scripts/actions/mobskills/daze.lua | 38 + scripts/actions/mobskills/jump_6.lua | 36 + scripts/actions/mobskills/knockout.lua | 36 + scripts/actions/mobskills/meditate.lua | 22 + scripts/actions/mobskills/shield_bash_1.lua | 36 + scripts/actions/mobskills/sic.lua | 21 + scripts/actions/mobskills/steal.lua | 23 + scripts/actions/mobskills/string_clipper.lua | 15 +- scripts/actions/mobskills/warcry.lua | 19 + scripts/actions/mobskills/weapon_bash.lua | 36 + .../Mine_Shaft_2716/pulling_the_strings.lua | 27 +- scripts/enum/mob_skill.lua | 134 ++- .../packets/s2c/0x028_battle2/mobskills.lua | 2 +- .../zones/Mine_Shaft_2716/mobs/Fantoccini.lua | 809 ++++++++++++++++++ .../mobs/Fantoccini_Automaton.lua | 94 ++ .../mobs/Fantoccini_Avatar.lua | 179 ++++ .../mobs/Fantoccini_Monster.lua | 109 +++ .../mobs/Moblin_Fantocciniman.lua | 52 +- sql/mob_groups.sql | 10 +- sql/mob_pools.sql | 6 +- sql/mob_skills.sql | 34 +- sql/mob_spawn_points.sql | 36 +- 27 files changed, 1792 insertions(+), 94 deletions(-) create mode 100644 scripts/actions/mobskills/arcuballista.lua create mode 100644 scripts/actions/mobskills/blood_pact.lua create mode 100644 scripts/actions/mobskills/counterstance_4.lua create mode 100644 scripts/actions/mobskills/daze.lua create mode 100644 scripts/actions/mobskills/jump_6.lua create mode 100644 scripts/actions/mobskills/knockout.lua create mode 100644 scripts/actions/mobskills/meditate.lua create mode 100644 scripts/actions/mobskills/shield_bash_1.lua create mode 100644 scripts/actions/mobskills/sic.lua create mode 100644 scripts/actions/mobskills/steal.lua create mode 100644 scripts/actions/mobskills/warcry.lua create mode 100644 scripts/actions/mobskills/weapon_bash.lua create mode 100644 scripts/zones/Mine_Shaft_2716/mobs/Fantoccini_Automaton.lua create mode 100644 scripts/zones/Mine_Shaft_2716/mobs/Fantoccini_Avatar.lua create mode 100644 scripts/zones/Mine_Shaft_2716/mobs/Fantoccini_Monster.lua diff --git a/scripts/actions/mobskills/arcuballista.lua b/scripts/actions/mobskills/arcuballista.lua new file mode 100644 index 00000000000..30ef36ef7f7 --- /dev/null +++ b/scripts/actions/mobskills/arcuballista.lua @@ -0,0 +1,37 @@ +----------------------------------- +-- Arcuballista +-- Family: Automaton +-- Description: Delivers a single ranged attack. Damage varies with TP. +----------------------------------- +---@type TMobSkill +local mobskillObject = {} + +mobskillObject.onMobSkillCheck = function(target, mob, skill) + return 0 +end + +mobskillObject.onMobWeaponSkill = function(mob, target, skill, action) + local params = {} + + params.baseDamage = mob:getWeaponDmg() + params.numHits = 1 + params.fTP = { 2.5, 3.0, 4.0 } + params.accuracyModifier = { 100, 100, 100 } + params.dex_wSC = 0.5 + params.attackType = xi.attackType.RANGED + params.damageType = xi.damageType.PIERCING + params.shadowBehavior = xi.mobskills.shadowBehavior.NUMSHADOWS_1 + params.skipParry = true + params.skipGuard = true + params.skipBlock = true + + local info = xi.mobskills.mobRangedMove(mob, target, skill, action, params) + + if xi.mobskills.processDamage(mob, target, skill, action, info) then + target:takeDamage(info.damage, mob, info.attackType, info.damageType) + end + + return info.damage +end + +return mobskillObject diff --git a/scripts/actions/mobskills/barrage.lua b/scripts/actions/mobskills/barrage.lua index fca0ed153d6..f398c0ff60e 100644 --- a/scripts/actions/mobskills/barrage.lua +++ b/scripts/actions/mobskills/barrage.lua @@ -15,21 +15,7 @@ end mobskillObject.onMobWeaponSkill = function(mob, target, skill, action) action:setCategory(xi.action.category.JOBABILITY_FINISH) - local level = mob:getMainLvl() - local projectileCount - if level >= 90 then - projectileCount = 7 - elseif level >= 75 then - projectileCount = 6 - elseif level >= 60 then - projectileCount = 5 - elseif level >= 30 then - projectileCount = 4 - else - projectileCount = 3 - end - - mob:addStatusEffect(xi.effect.BARRAGE, { power = projectileCount, duration = 60, origin = mob }) + mob:addStatusEffect(xi.effect.BARRAGE, { duration = 60, origin = mob }) skill:setMsg(xi.msg.basic.USES) diff --git a/scripts/actions/mobskills/blood_pact.lua b/scripts/actions/mobskills/blood_pact.lua new file mode 100644 index 00000000000..f61f1f39cc5 --- /dev/null +++ b/scripts/actions/mobskills/blood_pact.lua @@ -0,0 +1,21 @@ +----------------------------------- +-- Blood Pact +-- Family : Humanoid Job Ability +-- Description : Orders avatar to use an ability +----------------------------------- +---@type TMobSkill +local mobskillObject = {} + +mobskillObject.onMobSkillCheck = function(target, mob, skill) + return 0 +end + +mobskillObject.onMobWeaponSkill = function(mob, target, skill, action) + action:setCategory(xi.action.category.JOBABILITY_FINISH) + + skill:setMsg(xi.msg.basic.USES) + + return 0 +end + +return mobskillObject diff --git a/scripts/actions/mobskills/chimera_ripper.lua b/scripts/actions/mobskills/chimera_ripper.lua index 4eb7e7cf82a..ce7e4e4e226 100644 --- a/scripts/actions/mobskills/chimera_ripper.lua +++ b/scripts/actions/mobskills/chimera_ripper.lua @@ -1,5 +1,7 @@ ----------------------------------- -- Chimera Ripper +-- Family: Automaton +-- Description: Delivers a single attack. Damage varies with TP. ----------------------------------- ---@type TMobSkill local mobskillObject = {} @@ -11,12 +13,13 @@ end mobskillObject.onMobWeaponSkill = function(mob, target, skill, action) local params = {} - params.baseDamage = mob:getWeaponDmg() - params.numHits = 1 - params.fTP = { 6.0, 8.5, 11.0 } - params.attackType = xi.attackType.PHYSICAL - params.damageType = xi.damageType.SLASHING - params.shadowBehavior = xi.mobskills.shadowBehavior.NUMSHADOWS_1 + params.baseDamage = mob:getWeaponDmg() + params.numHits = 1 + params.fTP = { 1.5, 2.0, 3.0 } + params.accuracyModifier = { 100, 100, 100 } + params.attackType = xi.attackType.PHYSICAL + params.damageType = xi.damageType.SLASHING + params.shadowBehavior = xi.mobskills.shadowBehavior.NUMSHADOWS_1 local info = xi.mobskills.mobPhysicalMove(mob, target, skill, action, params) diff --git a/scripts/actions/mobskills/counterstance_4.lua b/scripts/actions/mobskills/counterstance_4.lua new file mode 100644 index 00000000000..2136f2111bd --- /dev/null +++ b/scripts/actions/mobskills/counterstance_4.lua @@ -0,0 +1,23 @@ +----------------------------------- +-- Ability: Counterstance +-- Family : Humanoid Job Ability +-- Description : Increases chance to counter but lowers defense. +----------------------------------- +---@type TMobSkill +local mobskillObject = {} + +mobskillObject.onMobSkillCheck = function(target, mob, skill) + return 0 +end + +mobskillObject.onMobWeaponSkill = function(mob, target, skill, action) + action:setCategory(xi.action.category.JOBABILITY_FINISH) + + xi.mobskills.mobBuffMove(mob, xi.effect.COUNTERSTANCE, 45, 0, 300) + + skill:setMsg(xi.msg.basic.NONE) + + return xi.effect.COUNTERSTANCE +end + +return mobskillObject diff --git a/scripts/actions/mobskills/daze.lua b/scripts/actions/mobskills/daze.lua new file mode 100644 index 00000000000..e45fb169816 --- /dev/null +++ b/scripts/actions/mobskills/daze.lua @@ -0,0 +1,38 @@ +----------------------------------- +-- Daze +-- Family: Automaton +-- Description: Delivers a single ranged attack. Damage varies with TP. Additional Effect: Stun. +----------------------------------- +---@type TMobSkill +local mobskillObject = {} + +mobskillObject.onMobSkillCheck = function(target, mob, skill) + return 0 +end + +mobskillObject.onMobWeaponSkill = function(mob, target, skill, action) + local params = {} + + params.baseDamage = mob:getWeaponDmg() + params.numHits = 1 + params.fTP = { 5.0, 5.5, 6.0 } + params.accuracyModifier = { 150, 150, 150 } + params.attackType = xi.attackType.RANGED + params.damageType = xi.damageType.PIERCING + params.shadowBehavior = xi.mobskills.shadowBehavior.NUMSHADOWS_1 + params.skipParry = true + params.skipGuard = true + params.skipBlock = true + + local info = xi.mobskills.mobRangedMove(mob, target, skill, action, params) + + if xi.mobskills.processDamage(mob, target, skill, action, info) then + target:takeDamage(info.damage, mob, info.attackType, info.damageType) + + xi.mobskills.mobStatusEffectMove(mob, target, xi.effect.STUN, 1, 0, 4) + end + + return info.damage +end + +return mobskillObject diff --git a/scripts/actions/mobskills/jump_6.lua b/scripts/actions/mobskills/jump_6.lua new file mode 100644 index 00000000000..325fa3b9695 --- /dev/null +++ b/scripts/actions/mobskills/jump_6.lua @@ -0,0 +1,36 @@ +----------------------------------- +-- Jump +-- Family: Humanoid Job Ability +-- Description: Delivers a short jumping attack on a targeted enemy. +----------------------------------- +---@type TMobSkill +local mobskillObject = {} + +mobskillObject.onMobSkillCheck = function(target, mob, skill) + return 0 +end + +mobskillObject.onMobWeaponSkill = function(mob, target, skill, action) + action:setCategory(xi.action.category.JOBABILITY_FINISH) + + local params = {} + + local fTP = 1 + mob:getStat(xi.mod.VIT) / 256 + + params.baseDamage = mob:getWeaponDmg() + params.numHits = 1 + params.fTP = { fTP, fTP, fTP } + params.attackType = xi.attackType.PHYSICAL + params.damageType = xi.damageType.PIERCING + params.shadowBehavior = xi.mobskills.shadowBehavior.NUMSHADOWS_1 + + local info = xi.mobskills.mobPhysicalMove(mob, target, skill, action, params) + + if xi.mobskills.processDamage(mob, target, skill, action, info) then + target:takeDamage(info.damage, mob, info.attackType, info.damageType) + end + + return info.damage +end + +return mobskillObject diff --git a/scripts/actions/mobskills/knockout.lua b/scripts/actions/mobskills/knockout.lua new file mode 100644 index 00000000000..a6f48ab7158 --- /dev/null +++ b/scripts/actions/mobskills/knockout.lua @@ -0,0 +1,36 @@ +----------------------------------- +-- Knockout +-- Family: Automaton +-- Description: Delivers a single hit attack. Additional Effect: Evasion Down. +----------------------------------- +---@type TMobSkill +local mobskillObject = {} + +mobskillObject.onMobSkillCheck = function(target, mob, skill) + return 0 +end + +mobskillObject.onMobWeaponSkill = function(mob, target, skill, action) + local params = {} + + params.baseDamage = mob:getWeaponDmg() + params.numHits = 1 + params.fTP = { 4.0, 4.5, 5.0 } + params.accuracyModifier = { 50, 50, 50 } + params.agi_wSC = 0.85 + params.attackType = xi.attackType.PHYSICAL + params.damageType = xi.damageType.BLUNT + params.shadowBehavior = xi.mobskills.shadowBehavior.NUMSHADOWS_1 + + local info = xi.mobskills.mobPhysicalMove(mob, target, skill, action, params) + + if xi.mobskills.processDamage(mob, target, skill, action, info) then + target:takeDamage(info.damage, mob, info.attackType, info.damageType) + + xi.mobskills.mobStatusEffectMove(mob, target, xi.effect.EVASION_DOWN, 20, 0, 30) + end + + return info.damage +end + +return mobskillObject diff --git a/scripts/actions/mobskills/meditate.lua b/scripts/actions/mobskills/meditate.lua new file mode 100644 index 00000000000..9b1b992ee13 --- /dev/null +++ b/scripts/actions/mobskills/meditate.lua @@ -0,0 +1,22 @@ +----------------------------------- +-- Meditate +-- Gradually charges TP. +----------------------------------- +---@type TMobSkill +local mobskillObject = {} + +mobskillObject.onMobSkillCheck = function(target, mob, skill) + return 0 +end + +mobskillObject.onMobWeaponSkill = function(mob, target, skill, action) + action:setCategory(xi.action.category.JOBABILITY_FINISH) + + mob:addStatusEffect(xi.effect.MEDITATE, { power = 20, duration = 15, tick = 3, origin = mob, icon = 0 }) + + skill:setMsg(xi.msg.basic.USES) + + return xi.effect.MEDITATE +end + +return mobskillObject diff --git a/scripts/actions/mobskills/shield_bash_1.lua b/scripts/actions/mobskills/shield_bash_1.lua new file mode 100644 index 00000000000..e6247fcae42 --- /dev/null +++ b/scripts/actions/mobskills/shield_bash_1.lua @@ -0,0 +1,36 @@ +----------------------------------- +-- Shield Bash +-- Family: Humanoid / Animated Weapon +-- Description: Delivers a physical attack to a single target. Additional Effect: Stun +----------------------------------- +---@type TMobSkill +local mobskillObject = {} + +mobskillObject.onMobSkillCheck = function(target, mob, skill) + return 0 +end + +mobskillObject.onMobWeaponSkill = function(mob, target, skill, action) + action:setCategory(xi.action.category.WEAPONSKILL_FINISH) + + local params = {} + + params.baseDamage = mob:getWeaponDmg() + params.numHits = 1 + params.fTP = { 1.0, 1.0, 1.0 } + params.attackType = xi.attackType.PHYSICAL + params.damageType = xi.damageType.BLUNT + params.shadowBehavior = xi.mobskills.shadowBehavior.NUMSHADOWS_1 + + local info = xi.mobskills.mobPhysicalMove(mob, target, skill, action, params) + + if xi.mobskills.processDamage(mob, target, skill, action, info) then + target:takeDamage(info.damage, mob, info.attackType, info.damageType) + + xi.mobskills.mobStatusEffectMove(mob, target, xi.effect.STUN, 1, 0, 7) + end + + return info.damage +end + +return mobskillObject diff --git a/scripts/actions/mobskills/sic.lua b/scripts/actions/mobskills/sic.lua new file mode 100644 index 00000000000..2576d827684 --- /dev/null +++ b/scripts/actions/mobskills/sic.lua @@ -0,0 +1,21 @@ +----------------------------------- +-- Sic +-- Family : Humanoid Job Ability +-- Description : Orders pet to use an ability +----------------------------------- +---@type TMobSkill +local mobskillObject = {} + +mobskillObject.onMobSkillCheck = function(target, mob, skill) + return 0 +end + +mobskillObject.onMobWeaponSkill = function(mob, target, skill, action) + action:setCategory(xi.action.category.JOBABILITY_FINISH) + + skill:setMsg(xi.msg.basic.USES) + + return 0 +end + +return mobskillObject diff --git a/scripts/actions/mobskills/steal.lua b/scripts/actions/mobskills/steal.lua new file mode 100644 index 00000000000..5448b8b4790 --- /dev/null +++ b/scripts/actions/mobskills/steal.lua @@ -0,0 +1,23 @@ +----------------------------------- +-- Ability: Steal +-- Family : Humanoid Job Ability +-- Description : Removes a random piece of the players equipment. +----------------------------------- +---@type TMobSkill +local mobskillObject = {} + +mobskillObject.onMobSkillCheck = function(target, mob, skill) + return 0 +end + +mobskillObject.onMobWeaponSkill = function(mob, target, skill, action) + action:setCategory(xi.action.category.WEAPONSKILL_FINISH) + + xi.mobskills.unequipRandomSlots(target, 1) + + skill:setMsg(xi.msg.basic.USES) + + return 0 +end + +return mobskillObject diff --git a/scripts/actions/mobskills/string_clipper.lua b/scripts/actions/mobskills/string_clipper.lua index 3d6b69158f9..2768b354340 100644 --- a/scripts/actions/mobskills/string_clipper.lua +++ b/scripts/actions/mobskills/string_clipper.lua @@ -1,5 +1,7 @@ ----------------------------------- -- String Clipper +-- Family: Automaton +-- Description: Delivers a twofold attack. ----------------------------------- ---@type TMobSkill local mobskillObject = {} @@ -11,12 +13,13 @@ end mobskillObject.onMobWeaponSkill = function(mob, target, skill, action) local params = {} - params.baseDamage = mob:getWeaponDmg() - params.numHits = 2 - params.fTP = { 3.5, 3.5, 3.5 } - params.attackType = xi.attackType.PHYSICAL - params.damageType = xi.damageType.SLASHING - params.shadowBehavior = xi.mobskills.shadowBehavior.NUMSHADOWS_2 + params.baseDamage = mob:getWeaponDmg() + params.numHits = 2 + params.fTP = { 2.0, 2.0, 2.0 } + params.attackMultiplier = { 1.25, 1.25, 1.25 } + params.attackType = xi.attackType.PHYSICAL + params.damageType = xi.damageType.SLASHING + params.shadowBehavior = xi.mobskills.shadowBehavior.NUMSHADOWS_2 local info = xi.mobskills.mobPhysicalMove(mob, target, skill, action, params) diff --git a/scripts/actions/mobskills/warcry.lua b/scripts/actions/mobskills/warcry.lua new file mode 100644 index 00000000000..fa360213370 --- /dev/null +++ b/scripts/actions/mobskills/warcry.lua @@ -0,0 +1,19 @@ +----------------------------------- +-- Warcry +----------------------------------- +---@type TMobSkill +local mobskillObject = {} + +mobskillObject.onMobSkillCheck = function(target, mob, skill) + return 0 +end + +mobskillObject.onMobWeaponSkill = function(mob, target, skill, action) + action:setCategory(xi.action.category.JOBABILITY_FINISH) + + skill:setMsg(xi.mobskills.mobBuffMove(mob, xi.effect.WARCRY, 8, 0, 30)) + + return xi.effect.WARCRY +end + +return mobskillObject diff --git a/scripts/actions/mobskills/weapon_bash.lua b/scripts/actions/mobskills/weapon_bash.lua new file mode 100644 index 00000000000..cfaf124af6a --- /dev/null +++ b/scripts/actions/mobskills/weapon_bash.lua @@ -0,0 +1,36 @@ +----------------------------------- +-- Ability: Weapon Bash +-- Family : Humanoid Job Ability +-- Description : Delivers an attack that can stun the target. Two-handed weapon required. +----------------------------------- +---@type TMobSkill +local mobskillObject = {} + +mobskillObject.onMobSkillCheck = function(target, mob, skill) + return 0 +end + +mobskillObject.onMobWeaponSkill = function(mob, target, skill, action) + action:setCategory(xi.action.category.WEAPONSKILL_FINISH) + + local params = {} + + params.baseDamage = mob:getWeaponDmg() + params.numHits = 1 + params.fTP = { 1.0, 1.0, 1.0 } -- TODO: Capture shadowBehavior + params.attackType = xi.attackType.PHYSICAL + params.damageType = xi.damageType.BLUNT + params.shadowBehavior = xi.mobskills.shadowBehavior.NUMSHADOWS_1 + + local info = xi.mobskills.mobPhysicalMove(mob, target, skill, action, params) + + if xi.mobskills.processDamage(mob, target, skill, action, info) then + target:takeDamage(info.damage, mob, info.attackType, info.damageType) + + xi.mobskills.mobStatusEffectMove(mob, target, xi.effect.STUN, 1, 0, 7) + end + + return info.damage +end + +return mobskillObject diff --git a/scripts/battlefields/Mine_Shaft_2716/pulling_the_strings.lua b/scripts/battlefields/Mine_Shaft_2716/pulling_the_strings.lua index 2e625a23307..87fd4a7f6ee 100644 --- a/scripts/battlefields/Mine_Shaft_2716/pulling_the_strings.lua +++ b/scripts/battlefields/Mine_Shaft_2716/pulling_the_strings.lua @@ -12,7 +12,6 @@ local content = Battlefield:new({ maxPlayers = 1, levelCap = 60, allowSubjob = false, - experimental = true, timeLimit = utils.minutes(15), index = 3, entryNpc = '_0d0', @@ -76,6 +75,7 @@ content.groups = mineshaftID.mob.MOBLIN_FANTOCCINIMAN + 14, }, }, + superlinkGroup = 1, }, { @@ -93,7 +93,7 @@ content.groups = mineshaftID.mob.MOBLIN_FANTOCCINIMAN + 16, }, }, - + superlinkGroup = 1, allDeath = utils.bind(content.handleAllMonstersDefeated, content), }, @@ -121,6 +121,7 @@ content.groups = mineshaftID.mob.MOBLIN_FANTOCCINIMAN + 20, -- Automaton }, }, + superlinkGroup = 1, spawned = false, }, } @@ -151,18 +152,20 @@ local lootTables = } local function getLootPool(battlefield) - -- Get loot table based on job. PUP gets a chance to drop an additional attachment. - local key = battlefield:getLocalVar('initiatorJob') - local lootPool = lootTables[key] - local bonusLootPool = nil + -- Get loot table based on job. PUP gets two chances to drop an additional attachment. + local key = battlefield:getLocalVar('initiatorJob') + local lootPool = lootTables[key] + local bonusLootPools = {} if type(lootPool) == 'table' then lootPool = utils.randomEntry(lootPool) - -- 20 percent chance to drop an additional attachment if the initiator is a PUP. - if key == xi.job.PUP and math.random(1, 100) <= 20 then - local bonusAttachment = lootTables[key] - if type(bonusAttachment) == 'table' then - bonusLootPool = utils.randomEntry(bonusAttachment) + -- Two independent 20 percent chances to drop additional attachments if the initiator is a PUP. + local bonusAttachment = lootTables[key] + if key == xi.job.PUP and type(bonusAttachment) == 'table' then + for _ = 1, 2 do + if math.random(1, 100) <= 20 then + table.insert(bonusLootPools, utils.randomEntry(bonusAttachment)) + end end end end @@ -181,7 +184,7 @@ local function getLootPool(battlefield) }, } - if bonusLootPool then + for _, bonusLootPool in ipairs(bonusLootPools) do table.insert(lootTable, { { itemId = bonusLootPool, weight = 10000 }, diff --git a/scripts/enum/mob_skill.lua b/scripts/enum/mob_skill.lua index 13ad8bfeb11..85209ee284d 100644 --- a/scripts/enum/mob_skill.lua +++ b/scripts/enum/mob_skill.lua @@ -12,8 +12,13 @@ xi.mobSkill = HOWLING_FIST_1 = 7, DRAGON_KICK_1 = 8, + WASP_STING_1 = 16, + VIPER_BITE = 17, SHADOWSTITCH = 18, - + GUST_SLASH = 19, + CYCLONE = 20, + ENERGY_STEAL = 21, + ENERGY_DRAIN = 22, DANCING_EDGE = 23, SHARK_BITE = 24, EVISCERATION = 25, @@ -40,28 +45,77 @@ xi.mobSkill = DIMIDIATION_1 = 61, + RAGING_AXE = 64, + SMASH_AXE = 65, + GALE_AXE = 66, + AVALANCHE_AXE = 67, + SPINNING_AXE = 68, + RAMPAGE_1 = 69, + + STURMWIND = 82, + ARMOR_BREAK = 83, + WEAPON_BREAK = 85, + RAGING_RUSH = 86, + + SLICE = 96, + DARK_HARVEST = 97, + SHADOW_OF_DEATH = 98, + NIGHTMARE_SCYTHE = 99, + SPINNING_SCYTHE_1 = 100, VORPAL_SCYTHE = 101, GUILLOTINE_1 = 102, SPIRAL_HELL = 104, + DOUBLE_THRUST = 112, + THUNDER_THRUST = 113, RAIDEN_THRUST_1 = 114, - + LEG_SWEEP = 115, PENTA_THRUST = 116, - + VORPAL_THRUST = 117, SKEWER = 118, WHEELING_THRUST = 119, IMPULSE_DRIVE = 120, + BLADE_RIN = 128, + BLADE_RETSU = 129, + BLADE_TEKI = 130, + BLADE_TO = 131, + BLADE_CHI = 132, + BLADE_EI = 133, + BLADE_JIN = 134, + + TACHI_ENPI = 144, + TACHI_HOBAKU = 145, + TACHI_GOTEN_1 = 146, + TACHI_KAGERO = 147, + TACHI_JINPU = 148, + TACHI_KOKI = 149, + TACHI_YUKIKAZE_1 = 150, + SHINING_STRIKE_1 = 160, SERAPH_STRIKE_1 = 161, BRAINSHAKER_1 = 162, - - SKULLBREAKER_1 = 165, - TRUE_STRIKE_1 = 166, + STARLIGHT = 163, + MOONLIGHT = 164, + SKULLBREAKER_1 = 165, + TRUE_STRIKE_1 = 166, RANDGRITH_1 = 170, + HEAVY_SWING = 176, + ROCK_CRUSHER = 177, + EARTH_CRUSHER = 178, + STARBURST = 179, + SUNBURST = 180, + SHELL_CRUSHER = 181, + FULL_SWING = 182, + + FLAMING_ARROW = 192, + PIERCING_ARROW = 193, + DULLING_ARROW = 194, + SIDEWINDER_1 = 196, + HOT_SHOT_1 = 208, SPLIT_SHOT_1 = 209, SNIPER_SHOT_1 = 210, @@ -194,9 +248,13 @@ xi.mobSkill = CATHARSIS = 440, MICROQUAKE = 441, -- Mammet-800 - BIG_SCISSORS = 444, + BUBBLE_SHOWER_1 = 442, + BUBBLE_CURTAIN_1 = 443, + BIG_SCISSORS_1 = 444, + SCISSOR_GUARD_1 = 445, PERCUSSIVE_FOIN = 447, -- Mammet-800 + METALLIC_BODY_1 = 448, GRAVITY_WHEEL = 457, -- Mammet-800 @@ -433,22 +491,58 @@ xi.mobSkill = MOONLIT_CHARGE = 831, CRESCENT_FANG = 832, LUNAR_CRY = 833, - + ECLIPTIC_GROWL = 834, LUNAR_ROAR = 835, ECLIPSE_BITE = 836, - + ECLIPTIC_HOWL = 837, HOWLING_MOON_1 = 838, -- Unknown usage. HOWLING_MOON_2 = 839, -- Confirmed usage: "The Moonlit Path" bcnm (Fenrir). + PUNCH = 840, + FIRE_II = 841, + BURNING_STRIKE = 842, + DOUBLE_PUNCH = 843, + CRIMSON_HOWL = 844, + FIRE_IV = 845, INFERNO_1 = 848, -- Confirmed usage: "Trial by Fire" bcnm. Regular avatar-type mobs (Ifrit). + ROCK_THROW = 849, + STONE_II = 850, + ROCK_BUSTER = 851, + MEGALITH_THROW = 852, + EARTHEN_WARD = 853, + STONE_IV = 854, EARTHEN_FURY_1 = 857, -- Confirmed usage: "Trial by Earth" bcnm. Regular avatar-type mobs (Titan). + BARRACUDA_DIVE = 858, + WATER_II = 859, + TAIL_WHIP = 860, + SPRING_WATER = 861, + SLOWGA = 862, + WATER_IV = 863, TIDAL_WAVE_1 = 866, -- Confirmed usage: "Trial by Water" bcnm. Regular avatar-type mobs (Leviathan). + CLAW = 867, + AERO_II = 868, + WHISPERING_WIND = 869, + HASTEGA = 870, + AERIAL_ARMOR = 871, + AERO_IV = 872, AERIAL_BLAST_1 = 875, -- Confirmed usage: "Trial by Wind" bcnm. Regular avatar-type mobs (Garuda). + AXE_KICK = 876, + BLIZZARD_II = 877, + FROST_ARMOR = 878, + SLEEPGA = 879, + DOUBLE_SLAP = 880, + BLIZZARD_IV = 881, DIAMOND_DUST_1 = 884, -- Confirmed usage: "Trial by Ice" bcnm. Regular avatar-type mobs (Shiva). + SHOCK_STRIKE = 885, + THUNDER_II = 886, + ROLLING_THUNDER = 887, + THUNDERSPARK = 888, + LIGHTNING_ARMOR = 889, + THUNDER_IV = 890, JUDGMENT_BOLT_1 = 893, -- Confirmed usage: "Trial by Lightning" bcnm. Regular avatar-type mobs (Ramuh). @@ -462,6 +556,11 @@ xi.mobSkill = PET_SAND_BREATH = 903, PET_LIGHTNING_BREATH = 904, PET_HYDRO_BREATH = 905, + HEALING_RUBY = 906, + POISON_NAILS = 907, + SHINING_RUBY = 908, + GLITTERING_RUBY = 909, + METEORITE = 910, SEARING_LIGHT_1 = 912, -- Confirmed usage: Regular avatar-type mobs (Carbuncle). INFERNO_2 = 913, -- Confirmed usage: Untargetable avatar astral flow. (Ex. Kirin) (Ifrit model avatar) @@ -752,6 +851,17 @@ xi.mobSkill = MARIONETTE_DICE_12 = 1425, MARIONETTE_DICE_14 = 1427, + WARCRY = 1428, + COUNTERSTANCE_4 = 1429, + STEAL = 1430, + SHIELD_BASH_1 = 1431, + WEAPON_BASH = 1432, + + SIC = 1433, + BARRAGE = 1434, + + MEDITATE = 1436, + BLOOD_PACT = 1438, ACTINIC_BURST = 1441, @@ -886,6 +996,9 @@ xi.mobSkill = WARP_OUT_GESSHO = 1938, WARP_IN_GESSHO = 1939, + CHIMERA_RIPPER = 1940, + STRING_CLIPPER = 1941, + ARCUBALLISTA = 1942, SLAPSTICK = 1943, SHIELD_BASH_AUTOMATON = 1944, -- Used by the trust Mnejing but may also be used by mobs. PROVOKE_AUTOMATON = 1945, -- Used by the trust Mnejing but may also be used by mobs. @@ -931,6 +1044,9 @@ xi.mobSkill = -- HUNDRED_FISTS = 2020, + DAZE = 2066, + KNOCKOUT = 2067, + -- MIJIN_GAKURE = 2105, NOCTURNAL_SERVITUDE = 2112, diff --git a/scripts/tests/packets/s2c/0x028_battle2/mobskills.lua b/scripts/tests/packets/s2c/0x028_battle2/mobskills.lua index a5b2b6a9efd..3d4b769e26e 100644 --- a/scripts/tests/packets/s2c/0x028_battle2/mobskills.lua +++ b/scripts/tests/packets/s2c/0x028_battle2/mobskills.lua @@ -392,7 +392,7 @@ local packets = { test = function(player) local mob = player.entities:moveTo('Clipper') - mob:useMobAbility(xi.mobSkill.BIG_SCISSORS, player, 10) + mob:useMobAbility(xi.mobSkill.BIG_SCISSORS_1, player, 10) xi.test.world:tickEntity(mob) mob:setHP(0) -- Kill mob while in "ready" state xi.test.world:skipTime(3) -- Process death and interrupt diff --git a/scripts/zones/Mine_Shaft_2716/mobs/Fantoccini.lua b/scripts/zones/Mine_Shaft_2716/mobs/Fantoccini.lua index cbcfdb3a7cd..26801baf2a1 100644 --- a/scripts/zones/Mine_Shaft_2716/mobs/Fantoccini.lua +++ b/scripts/zones/Mine_Shaft_2716/mobs/Fantoccini.lua @@ -3,7 +3,811 @@ local entity = {} ----------------------------------- local ID = zones[xi.zone.MINE_SHAFT_2716] ----------------------------------- +-- TODO : More complete / accurate spell lists - accurate weaponskill lists. +-- TODO : Accurate Double-Up Logic for Corsair +----------------------------------- + +local jobTable = +{ + [xi.job.WAR] = + { + modelId = 1209, + hp = 3750, + delay = 300, + skillList = + { + xi.mobSkill.RAGING_AXE, + xi.mobSkill.SMASH_AXE, + xi.mobSkill.GALE_AXE, + xi.mobSkill.AVALANCHE_AXE, + xi.mobSkill.SPINNING_AXE, + xi.mobSkill.RAMPAGE_1, + }, + jobAbility = { xi.mobSkill.WARCRY }, + twoHour = xi.mobSkill.MIGHTY_STRIKES_1, + isPetJob = false, + logicType = 1, + }, + + [xi.job.MNK] = + { + modelId = 1210, + hp = 5000, + delay = 420, + skillList = + { + xi.mobSkill.COMBO_1, + xi.mobSkill.SHOULDER_TACKLE_1, + xi.mobSkill.ONE_INCH_PUNCH_1, + xi.mobSkill.BACKHAND_BLOW_1, + xi.mobSkill.RAGING_FISTS_1, + xi.mobSkill.SPINNING_ATTACK_1, + xi.mobSkill.HOWLING_FIST_1, + }, + jobAbility = { xi.mobSkill.COUNTERSTANCE_4 }, + twoHour = xi.mobSkill.HUNDRED_FISTS_1, + isPetJob = false, + logicType = 1, + }, + + [xi.job.WHM] = + { + modelId = 1214, + hp = 2750, + delay = 300, + skillList = + { + xi.mobSkill.SHINING_STRIKE_1, + xi.mobSkill.BRAINSHAKER_1, + xi.mobSkill.SERAPH_STRIKE_1, + xi.mobSkill.SKULLBREAKER_1, + xi.mobSkill.TRUE_STRIKE_1, + }, + spellList = + { + xi.magic.spell.PROTECT_III, + xi.magic.spell.SHELL_III, + xi.magic.spell.CURE_IV, + xi.magic.spell.DIA_II, + xi.magic.spell.HOLY, + xi.magic.spell.SLOW, + xi.magic.spell.PARALYZE, + }, + twoHour = xi.mobSkill.BENEDICTION_1, + isPetJob = false, + logicType = 2, + }, + + [xi.job.BLM] = + { + modelId = 1215, + hp = 4000, + delay = 300, + skillList = + { + xi.mobSkill.SHINING_STRIKE_1, + xi.mobSkill.BRAINSHAKER_1, + xi.mobSkill.SERAPH_STRIKE_1, + xi.mobSkill.SKULLBREAKER_1, + xi.mobSkill.TRUE_STRIKE_1, + }, + spellList = + { + xi.magic.spell.FIRAGA_II, + xi.magic.spell.FLARE, + xi.magic.spell.AERO_III, + xi.magic.spell.TORNADO, + xi.magic.spell.WATER_III, + xi.magic.spell.BLIZZAGA_II, + }, + twoHour = xi.mobSkill.MANAFONT_1, + isPetJob = false, + logicType = 2, + }, + + [xi.job.RDM] = + { + modelId = 1216, + hp = 3500, + delay = 300, + skillList = + { + xi.mobSkill.FAST_BLADE_1, + xi.mobSkill.BURNING_BLADE_1, + xi.mobSkill.RED_LOTUS_BLADE_1, + xi.mobSkill.FLAT_BLADE_1, + xi.mobSkill.SHINING_BLADE_1, + xi.mobSkill.SERAPH_BLADE_1, + xi.mobSkill.CIRCLE_BLADE_1, + xi.mobSkill.SPIRITS_WITHIN_1, + }, + spellList = + { + xi.magic.spell.THUNDER_II, + xi.magic.spell.SHOCK_SPIKES, + xi.magic.spell.PROTECT_III, + xi.magic.spell.SHELL_III, + xi.magic.spell.CURE_IV, + xi.magic.spell.DIA_II, + xi.magic.spell.ENTHUNDER, + xi.magic.spell.SLOW, + xi.magic.spell.PARALYZE, + xi.magic.spell.SILENCE, + }, + twoHour = xi.mobSkill.CHAINSPELL_1, + isPetJob = false, + logicType = 2, + }, + + [xi.job.THF] = + { + modelId = 1218, + hp = 2750, + delay = 300, + skillList = + { + xi.mobSkill.WASP_STING_1, + xi.mobSkill.VIPER_BITE, + xi.mobSkill.SHADOWSTITCH, + xi.mobSkill.GUST_SLASH, + xi.mobSkill.CYCLONE, + xi.mobSkill.DANCING_EDGE, + }, + jobAbility = { xi.mobSkill.STEAL }, + twoHour = xi.mobSkill.PERFECT_DODGE_1, + isPetJob = false, + logicType = 1, + }, + + [xi.job.PLD] = + { + modelId = 1219, + hp = 2750, + delay = 300, + shieldBlock = true, + skillList = + { + xi.mobSkill.FAST_BLADE_1, + xi.mobSkill.BURNING_BLADE_1, + xi.mobSkill.RED_LOTUS_BLADE_1, + xi.mobSkill.FLAT_BLADE_1, + xi.mobSkill.SHINING_BLADE_1, + xi.mobSkill.SERAPH_BLADE_1, + xi.mobSkill.CIRCLE_BLADE_1, + xi.mobSkill.SPIRITS_WITHIN_1, + xi.mobSkill.VORPAL_BLADE_1, + }, + jobAbility = { xi.mobSkill.SHIELD_BASH_1 }, + twoHour = xi.mobSkill.INVINCIBLE_1, + isPetJob = false, + logicType = 1, + }, + + [xi.job.DRK] = + { + modelId = 1220, + hp = 3250, + delay = 590, + skillList = + { + xi.mobSkill.SLICE, + xi.mobSkill.DARK_HARVEST, + xi.mobSkill.SHADOW_OF_DEATH, + xi.mobSkill.NIGHTMARE_SCYTHE, + xi.mobSkill.SPINNING_SCYTHE_1, + xi.mobSkill.VORPAL_SCYTHE, + xi.mobSkill.GUILLOTINE_1, + }, + jobAbility = { xi.mobSkill.WEAPON_BASH }, + twoHour = xi.mobSkill.BLOOD_WEAPON_1, + isPetJob = false, + logicType = 1, + }, + + [xi.job.BST] = + { + modelId = 1224, + hp = 3750, + delay = 300, + skillList = + { + xi.mobSkill.RAGING_AXE, + xi.mobSkill.SMASH_AXE, + xi.mobSkill.GALE_AXE, + xi.mobSkill.AVALANCHE_AXE, + xi.mobSkill.SPINNING_AXE, + xi.mobSkill.RAMPAGE_1, + }, + jobAbility = { xi.mobSkill.SIC }, + twoHour = xi.mobSkill.FAMILIAR_1, + isPetJob = true, + logicType = 3, + + pet = + { + offset = 1, + name = 'Fantoccini_Monster', + params = + { + callPetJob = xi.job.BST, + inactiveTime = 3000, + superLink = true, + dieWithOwner = true, + maxSpawns = 1, + }, + }, + }, + + [xi.job.BRD] = + { + modelId = 1227, + hp = 3000, + delay = 300, + skillList = + { + xi.mobSkill.WASP_STING_1, + xi.mobSkill.GUST_SLASH, + xi.mobSkill.SHADOWSTITCH, + xi.mobSkill.VIPER_BITE, + xi.mobSkill.CYCLONE, + }, + spellList = + { + xi.magic.spell.ARMYS_PAEON_IV, + xi.magic.spell.CARNAGE_ELEGY, + xi.magic.spell.DRAGONFOE_MAMBO, + xi.magic.spell.FOE_REQUIEM_V, + xi.magic.spell.KNIGHTS_MINNE_III, + xi.magic.spell.VALOR_MINUET_III, + xi.magic.spell.VICTORY_MARCH, + }, + twoHour = xi.mobSkill.SOUL_VOICE_1, + isPetJob = false, + logicType = 2, + }, + + [xi.job.RNG] = + { + modelId = 1228, + hp = 4500, + delay = 300, + rangedAttack = 14, + skillList = + { + xi.mobSkill.FLAMING_ARROW, + xi.mobSkill.PIERCING_ARROW, + xi.mobSkill.DULLING_ARROW, + xi.mobSkill.SIDEWINDER_1, + }, + jobAbility = { xi.mobSkill.BARRAGE }, + twoHour = xi.mobSkill.EES_MAAT, + isPetJob = false, + logicType = 1, + }, + + [xi.job.SAM] = + { + modelId = 1229, + hp = 3750, + delay = 580, + skillList = + { + xi.mobSkill.TACHI_ENPI, + xi.mobSkill.TACHI_HOBAKU, + xi.mobSkill.TACHI_GOTEN_1, + xi.mobSkill.TACHI_KAGERO, + xi.mobSkill.TACHI_JINPU, + xi.mobSkill.TACHI_KOKI, + xi.mobSkill.TACHI_YUKIKAZE_1, + }, + jobAbility = { xi.mobSkill.MEDITATE }, + twoHour = xi.mobSkill.MEIKYO_SHISUI_1, + isPetJob = false, + logicType = 1, + }, + + [xi.job.NIN] = + { + modelId = 1232, + hp = 3750, + delay = 280, + dualWield = true, + skillList = + { + xi.mobSkill.BLADE_RIN, + xi.mobSkill.BLADE_RETSU, + xi.mobSkill.BLADE_TEKI, + xi.mobSkill.BLADE_TO, + xi.mobSkill.BLADE_CHI, + xi.mobSkill.BLADE_EI, + xi.mobSkill.BLADE_JIN, + }, + spellList = + { + xi.magic.spell.KATON_NI, + xi.magic.spell.HYOTON_NI, + xi.magic.spell.HUTON_NI, + xi.magic.spell.DOTON_NI, + xi.magic.spell.RAITON_NI, + xi.magic.spell.SUITON_NI, + xi.magic.spell.UTSUSEMI_NI, + xi.magic.spell.JUBAKU_ICHI, + xi.magic.spell.HOJO_NI, + xi.magic.spell.KURAYAMI_NI, + xi.magic.spell.DOKUMORI_ICHI, + }, + twoHour = xi.mobSkill.MIJIN_GAKURE_1, + isPetJob = false, + logicType = 2, + }, + + [xi.job.DRG] = + { + modelId = 1234, + hp = 3750, + delay = 580, + skillList = + { + xi.mobSkill.DOUBLE_THRUST, + xi.mobSkill.THUNDER_THRUST, + xi.mobSkill.RAIDEN_THRUST_1, + xi.mobSkill.LEG_SWEEP, + xi.mobSkill.PENTA_THRUST, + xi.mobSkill.VORPAL_THRUST, + xi.mobSkill.SKEWER, + }, + jobAbility = { xi.mobSkill.JUMP_1 }, + twoHour = xi.mobSkill.CALL_WYVERN_1, + isPetJob = true, -- Wyvern only summoned via two-hour ability. + logicType = 1, + + pet = + { + offset = 2, + name = 'Fantoccini_Wyvern', + params = + { + callPetJob = xi.job.DRG, + superLink = true, + dieWithOwner = true, + maxSpawns = 1, + }, + }, + }, + + [xi.job.SMN] = + { + modelId = 1235, + hp = 3250, + delay = 480, + skillList = + { + xi.mobSkill.HEAVY_SWING, + xi.mobSkill.ROCK_CRUSHER, + xi.mobSkill.EARTH_CRUSHER, + xi.mobSkill.STARBURST, + xi.mobSkill.SUNBURST, + xi.mobSkill.SHELL_CRUSHER, + xi.mobSkill.FULL_SWING, + }, + jobAbility = { xi.mobSkill.BLOOD_PACT }, + twoHour = xi.mobSkill.ASTRAL_FLOW_1, + isPetJob = true, + logicType = 3, + + pet = + { + offset = 3, + name = 'Fantoccini_Avatar', + params = + { + callPetJob = xi.job.SMN, + inactiveTime = 3000, + superLink = true, + dieWithOwner = true, + maxSpawns = 1, + }, + }, + }, + + [xi.job.BLU] = + { + modelId = 1396, + hp = 3250, + delay = 300, + skillList = + { + xi.mobSkill.FAST_BLADE_1, + xi.mobSkill.BURNING_BLADE_1, + xi.mobSkill.RED_LOTUS_BLADE_1, + xi.mobSkill.FLAT_BLADE_1, + xi.mobSkill.SHINING_BLADE_1, + xi.mobSkill.SERAPH_BLADE_1, + xi.mobSkill.CIRCLE_BLADE_1, + xi.mobSkill.SPIRITS_WITHIN_1, + xi.mobSkill.VORPAL_BLADE_1, + }, + twoHour = xi.mobSkill.AZURE_LORE, + isPetJob = false, + logicType = 2, + }, + + [xi.job.COR] = + { + modelId = 1397, + hp = 3750, + delay = 300, + rangedAttack = 14, + skillList = + { + xi.mobSkill.HOT_SHOT_1, + xi.mobSkill.SPLIT_SHOT_1, + xi.mobSkill.SNIPER_SHOT_1, + xi.mobSkill.SLUG_SHOT_1, + }, + jobAbility = + { + xi.ja.FIGHTERS_ROLL, + xi.ja.ROGUES_ROLL, + xi.ja.GALLANTS_ROLL, + xi.ja.CHAOS_ROLL, + xi.ja.HUNTERS_ROLL, + xi.ja.NINJA_ROLL, + }, + twoHour = xi.mobSkill.WILD_CARD, + isPetJob = false, + logicType = 4, + }, + + [xi.job.PUP] = + { + modelId = 1398, + hp = 3500, + delay = 420, + skillList = + { + xi.mobSkill.COMBO_1, + xi.mobSkill.SHOULDER_TACKLE_1, + xi.mobSkill.ONE_INCH_PUNCH_1, + xi.mobSkill.BACKHAND_BLOW_1, + xi.mobSkill.RAGING_FISTS_1, + }, + jobAbility = + { + xi.mobSkill.FIRE_MANEUVER, + xi.mobSkill.ICE_MANEUVER, + xi.mobSkill.WIND_MANEUVER, + xi.mobSkill.EARTH_MANEUVER, + xi.mobSkill.THUNDER_MANEUVER, + xi.mobSkill.WATER_MANEUVER, + }, + twoHour = xi.mobSkill.OVERDRIVE, + isPetJob = true, + logicType = 3, + pet = + { + offset = 4, + name = 'Fantoccini_Automaton', + params = + { + callPetJob = xi.job.PUP, + inactiveTime = 3000, + superLink = true, + dieWithOwner = true, + maxSpawns = 1, + }, + }, + }, +} + +entity.onMobInitialize = function(mob) + mob:addImmunity(xi.immunity.SILENCE) + mob:addImmunity(xi.immunity.BIND) + mob:addImmunity(xi.immunity.LIGHT_SLEEP) + mob:addImmunity(xi.immunity.DARK_SLEEP) + mob:setMobMod(xi.mobMod.MAGIC_COOL, 15) +end + +entity.onMobSpawn = function(mob) + local battlefield = mob:getBattlefield() + + if not battlefield then + return + end + + local initiatorJob = battlefield:getLocalVar('initiatorJob') + local jobInfo = jobTable[initiatorJob] + + if not jobInfo then + return + end + + mob:setLocalVar('initiatorJob', initiatorJob) -- Store as local variable so battlefield only needs to be fetched on spawn. + mob:setMobMod(xi.mobMod.CAN_PARRY, 1) + mob:setMobMod(xi.mobMod.DUAL_WIELD, jobInfo.dualWield and 1 or 0) + mob:setMobMod(xi.mobMod.CAN_SHIELD_BLOCK, jobInfo.shieldBlock and 1 or 0) + + mob:changeJob(initiatorJob) + mob:setDelay(jobInfo.delay) + mob:setModelId(jobInfo.modelId) + mob:setMobAbilityEnabled(false) + mob:setMagicCastingEnabled(false) + mob:setAutoAttackEnabled(true) + mob:setRangedAttackEnabled(false) + + if + initiatorJob == xi.job.RNG or + initiatorJob == xi.job.COR + then + mob:setRangedAttackEnabled(true) + mob:setMobMod(xi.mobMod.RANGED_ATTACK_RANGE, jobInfo.rangedAttack) + end + + mob:setMaxHP(jobInfo.hp or mob:getMaxHP()) + mob:setHP(mob:getMaxHP() + 50) + + mob:setLocalVar('diceRoll', 0) + + ----------------------------------- + --- If pet job, set pet parameters. + ----------------------------------- + if jobInfo.isPetJob then + mob:setLocalVar('petSummonTime', 0) + local petData = jobInfo.pet + xi.pet.setMobPet(mob, petData.offset, petData.name) + + if initiatorJob == xi.job.SMN then + mob:setMobMod(xi.mobMod.ASTRAL_PET_OFFSET, petData.offset) + end + end + + ----------------------------------- + -- If BLM, RDM, BLU allow free-casting while 2-hour ability is active. + -- If SAM, allow free weaponskill usage after Meikyo Shisui is used. + ----------------------------------- + if + initiatorJob == xi.job.BLM or + initiatorJob == xi.job.RDM or + initiatorJob == xi.job.BLU or + initiatorJob == xi.job.BRD or + initiatorJob == xi.job.SAM + then + mob:addListener('EFFECT_GAIN', 'TWO_HOUR_EFFECT_GAIN', function(mobArg, effect) + local effectType = effect:getEffectType() + + if + effectType == xi.effect.MANAFONT or + effectType == xi.effect.CHAINSPELL or + effectType == xi.effect.AZURE_LORE or + effectType == xi.effect.SOUL_VOICE + then + mobArg:setMagicCastingEnabled(true) + if + initiatorJob == xi.job.BLM or + initiatorJob == xi.job.RDM or + initiatorJob == xi.job.BLU + then + mobArg:setMobMod(xi.mobMod.MAGIC_COOL, 0) + end + end + + if effectType == xi.effect.MEIKYO_SHISUI then + mobArg:setMobAbilityEnabled(true) + end + end) + mob:addListener('EFFECT_LOSE', 'TWO_HOUR_EFFECT_LOSE', function(mobArg, effect) + local effectType = effect:getEffectType() + + if + effectType == xi.effect.MANAFONT or + effectType == xi.effect.CHAINSPELL or + effectType == xi.effect.AZURE_LORE or + effectType == xi.effect.SOUL_VOICE + then + mobArg:setMagicCastingEnabled(false) + mobArg:setMobMod(xi.mobMod.MAGIC_COOL, 15) + end + + if effectType == xi.effect.MEIKYO_SHISUI then + mobArg:setMobAbilityEnabled(false) + end + end) + end +end + +----------------------------------- +-- Main Combat Loop - Checks for Dice Rolls and executes appropriate actions - also handles pet summoning logic for pet jobs. +----------------------------------- +entity.onMobFight = function(mob, target) + local initiatorJob = mob:getLocalVar('initiatorJob') + local jobInfo = jobTable[initiatorJob] + + if not jobInfo then + return + end + + local logicType = jobInfo.logicType + + if not logicType then + return + end + + local diceRoll = mob:getLocalVar('diceRoll') + local jobAbility = jobInfo.jobAbility + + if diceRoll == 8 then + mob:setMobAbilityEnabled(true) + end + + switch(logicType): caseof + { + ----------------------------------- + -- Logic Type 1 : WAR, MNK, DRK, PLD, SAM, DRG + ----------------------------------- + [1] = function() + if diceRoll == 7 then + if #jobAbility > 0 then + mob:useMobAbility(jobAbility[math.random(1, #jobAbility)]) + end + elseif diceRoll == 14 then + if initiatorJob == xi.job.DRG then + local petData = jobInfo.pet + local petId = mob:getID() + petData.offset + local pet = GetMobByID(petId) + + if pet and pet:isAlive() then + return + end + + xi.mob.callPets(mob, petId, petData.params) + else + mob:useMobAbility(jobInfo.twoHour) + end + end + end, + + ----------------------------------- + -- Logic Type 2 : WHM, BLM, RDM, BRD, NIN, BLU + ----------------------------------- + [2] = function() + if diceRoll == 7 then + mob:setMagicCastingEnabled(true) + elseif diceRoll == 14 then + mob:useMobAbility(jobInfo.twoHour) + end + end, + + ----------------------------------- + -- Logic Type 3 : BST, SMN, PUP + ----------------------------------- + [3] = function() + local petData = jobInfo.pet + local petId = mob:getID() + petData.offset + local pet = GetMobByID(petId) + local currentTime = GetSystemTime() + + if not pet then + return + end + + if diceRoll == 7 then + if #jobAbility > 0 and pet:isAlive() then + mob:useMobAbility(jobAbility[math.random(1, #jobAbility)]) + pet:setLocalVar('jobAbilityUsed', 1) -- Used for Sic, Blood Pact & Maneuvers. + end + elseif diceRoll == 14 then + mob:useMobAbility(jobInfo.twoHour) + if initiatorJob == xi.job.SMN then + pet:setLocalVar('twoHourUsed', 1) -- Used for Astal Flow. + end + end + + -- If pet is alive, return. + if pet:isAlive() then + return + end + + -- If it's time to resummon our pet, summon it. + if currentTime >= mob:getLocalVar('petSummonTime') then + xi.mob.callPets(mob, petId, petData.params) + end + end, + + ----------------------------------- + -- Logic Type 4 : COR + ----------------------------------- + [4] = function() + if diceRoll == 7 then + mob:useJobAbility(jobAbility[math.random(1, #jobAbility)], mob) + -- TODO: Don't use a timer, add actual double up logic. Double ups each roll once. + mob:timer(4000, function(mobArg) + mobArg:useJobAbility(xi.ja.DOUBLE_UP, mobArg) + end) + elseif diceRoll == 14 then + mob:useMobAbility(jobInfo.twoHour) + end + end, + } + + if diceRoll ~= 0 then + mob:setLocalVar('diceRoll', 0) + end +end + +----------------------------------- +-- When mob:setMobAbilityEnabled is (true) - pull from associated job weapon skills. +----------------------------------- +entity.onMobMobskillChoose = function(mob, target, skillId) + local initiatorJob = mob:getLocalVar('initiatorJob') + local jobInfo = jobTable[initiatorJob] + + local skillList = jobInfo.skillList + + return skillList[math.random(1, #skillList)] +end + +----------------------------------- +-- If Meditate or Wild Card was used, enable weaponskill usage, and reset ability enabled to false after any weaponskill executed. +----------------------------------- +entity.onMobWeaponSkill = function(mob, target, skill, action) + local skillUsed = skill:getID() + + if + skillUsed == xi.mobSkill.MEDITATE or + skillUsed == xi.mobSkill.WILD_CARD + then + mob:setMobAbilityEnabled(true) + end + + if + skillUsed ~= xi.mobSkill.MEDITATE and + skillUsed ~= xi.mobSkill.WILD_CARD and + not mob:hasStatusEffect(xi.effect.MEIKYO_SHISUI) + then + mob:setMobAbilityEnabled(false) -- Disables weaponskill use after 1 weaponskill unless effected by Meikyo Shisui. + end +end + +----------------------------------- +-- Spellcasting Logic +----------------------------------- +entity.onMobSpellChoose = function(mob, target, spellId) + local initiatorJob = mob:getLocalVar('initiatorJob') + local jobInfo = jobTable[initiatorJob] + + -- If not under the effects of a two-hour ability, turn off spell casting. (Lets this spell pass) + if + not mob:hasStatusEffect(xi.effect.MANAFONT) and + not mob:hasStatusEffect(xi.effect.CHAINSPELL) and + not mob:hasStatusEffect(xi.effect.AZURE_LORE) and + not mob:hasStatusEffect(xi.effect.SOUL_VOICE) + then + mob:setMagicCastingEnabled(false) + end + + -- if initiator job is BLU, populate spell list with players set Blue Magic + Frypan + if initiatorJob == xi.job.BLU then + local player = mob:getBattlefield():getPlayers()[1] + + if not player then + return + end + + local blueMageSpellList = player:getSetBlueSpells() + + table.insert(blueMageSpellList, xi.magic.spell.FRYPAN) + + return blueMageSpellList[math.random(1, #blueMageSpellList)] + -- If initiator job is any other caster, return a random spell from their spell list. + else + return jobInfo.spellList[math.random(1, #jobInfo.spellList)] + end +end + +----------------------------------- +-- On Death, despawn Moblin Fantoccini and play flavor text. +----------------------------------- entity.onMobDeath = function(mob, player, optParams) if optParams.isKiller or optParams.noKiller then local moblinFantoccini = GetMobByID(mob:getID() - 2) @@ -17,4 +821,9 @@ entity.onMobDeath = function(mob, player, optParams) end end +entity.onMobDespawn = function(mob) + mob:removeListener('TWO_HOUR_EFFECT_GAIN') + mob:removeListener('TWO_HOUR_EFFECT_LOSE') +end + return entity diff --git a/scripts/zones/Mine_Shaft_2716/mobs/Fantoccini_Automaton.lua b/scripts/zones/Mine_Shaft_2716/mobs/Fantoccini_Automaton.lua new file mode 100644 index 00000000000..35a362c4654 --- /dev/null +++ b/scripts/zones/Mine_Shaft_2716/mobs/Fantoccini_Automaton.lua @@ -0,0 +1,94 @@ +---@type TMobEntity +local entity = {} + +local petTable = +{ + { + name = 'Melee Automaton', + modelId = 1983, + job = xi.job.PLD, + skillList = + { + xi.mobSkill.CHIMERA_RIPPER, + xi.mobSkill.STRING_CLIPPER, + }, + }, + + { + name = 'Ranged Automaton', + modelId = 1990, + job = xi.job.RNG, + skillList = + { + xi.mobSkill.ARCUBALLISTA, + xi.mobSkill.DAZE, + }, + }, + + { + name = 'Magic Automaton', + modelId = 1994, + job = xi.job.RDM, + skillList = + { + xi.mobSkill.SLAPSTICK, + xi.mobSkill.KNOCKOUT, + }, + }, +} + +entity.onMobInitialize = function(mob) + mob:setMobMod(xi.mobMod.MAGIC_COOL, 27) +end + +entity.onMobSpawn = function(mob) + local petChosen = math.random(1, #petTable) + local petInfo = petTable[petChosen] + + mob:setModelId(petInfo.modelId) + + if petInfo.job == xi.job.PLD then + mob:setMobMod(xi.mobMod.CAN_SHIELD_BLOCK, 1) + else + mob:setMobMod(xi.mobMod.CAN_SHIELD_BLOCK, 0) + end + + if petInfo.job == xi.job.RNG then + mob:setRangedAttackEnabled(true) + mob:setMobMod(xi.mobMod.RANGED_ATTACK_RANGE, 14) + else + mob:setRangedAttackEnabled(false) + end + + if petInfo.job == xi.job.RDM then + mob:setMagicCastingEnabled(true) + else + mob:setMagicCastingEnabled(false) + end + + mob:setLocalVar('petIndex', petChosen) +end + +entity.onMobMobskillChoose = function(mob, target, skillId) + local petInfo = petTable[mob:getLocalVar('petIndex')] + + if not petInfo then + return 0 + end + + return petInfo.skillList[math.random(1, #petInfo.skillList)] +end + +entity.onMobDeath = function(mob, player, optParams) + if optParams.isKiller or optParams.noKiller then + local fantoccini = mob:getMaster() + + if not fantoccini then + return + end + + fantoccini:setLocalVar('petSummonTime', GetSystemTime() + 45) + end +end + +return entity diff --git a/scripts/zones/Mine_Shaft_2716/mobs/Fantoccini_Avatar.lua b/scripts/zones/Mine_Shaft_2716/mobs/Fantoccini_Avatar.lua new file mode 100644 index 00000000000..bbfb02e027a --- /dev/null +++ b/scripts/zones/Mine_Shaft_2716/mobs/Fantoccini_Avatar.lua @@ -0,0 +1,179 @@ +---@type TMobEntity +local entity = {} + +-- TODO : Change Family Type? + +local avatarTable = +{ + { + name = 'Carbuncle', + modelId = 791, + skillList = + { + xi.mobSkill.HEALING_RUBY, + xi.mobSkill.POISON_NAILS, + xi.mobSkill.SHINING_RUBY, + xi.mobSkill.GLITTERING_RUBY, + xi.mobSkill.METEORITE, + }, + twoHour = xi.mobSkill.SEARING_LIGHT_1, + }, + + { + name = 'Fenrir', + modelId = 792, + skillList = + { + xi.mobSkill.MOONLIT_CHARGE, + xi.mobSkill.CRESCENT_FANG, + xi.mobSkill.LUNAR_CRY, + xi.mobSkill.LUNAR_ROAR, + xi.mobSkill.ECLIPTIC_GROWL, + xi.mobSkill.ECLIPTIC_HOWL, + }, + twoHour = xi.mobSkill.HOWLING_MOON_2, + }, + + { + name = 'Ifrit', + modelId = 793, + skillList = + { + xi.mobSkill.PUNCH, + xi.mobSkill.FIRE_II, + xi.mobSkill.BURNING_STRIKE, + xi.mobSkill.DOUBLE_PUNCH, + xi.mobSkill.CRIMSON_HOWL, + xi.mobSkill.FIRE_IV, + }, + twoHour = xi.mobSkill.INFERNO_1, + }, + + { + name = 'Titan', + modelId = 794, + skillList = + { + xi.mobSkill.ROCK_THROW, + xi.mobSkill.STONE_II, + xi.mobSkill.ROCK_BUSTER, + xi.mobSkill.MEGALITH_THROW, + xi.mobSkill.EARTHEN_WARD, + xi.mobSkill.STONE_IV, + }, + twoHour = xi.mobSkill.EARTHEN_FURY_1, + }, + + { + name = 'Leviathan', + modelId = 795, + skillList = + { + xi.mobSkill.BARRACUDA_DIVE, + xi.mobSkill.WATER_II, + xi.mobSkill.TAIL_WHIP, + xi.mobSkill.SLOWGA, + xi.mobSkill.SPRING_WATER, + xi.mobSkill.WATER_IV, + }, + twoHour = xi.mobSkill.TIDAL_WAVE_1, + }, + + { + name = 'Garuda', + modelId = 796, + skillList = + { + xi.mobSkill.CLAW, + xi.mobSkill.AERO_II, + xi.mobSkill.AERIAL_ARMOR, + xi.mobSkill.WHISPERING_WIND, + xi.mobSkill.HASTEGA, + xi.mobSkill.AERO_IV, + }, + twoHour = xi.mobSkill.AERIAL_BLAST_1, + }, + + { + name = 'Shiva', + modelId = 797, + skillList = + { + xi.mobSkill.AXE_KICK, + xi.mobSkill.BLIZZARD_II, + xi.mobSkill.FROST_ARMOR, + xi.mobSkill.SLEEPGA, + xi.mobSkill.DOUBLE_SLAP, + xi.mobSkill.BLIZZARD_IV, + }, + twoHour = xi.mobSkill.DIAMOND_DUST_1, + }, + + { + name = 'Ramuh', + modelId = 798, + skillList = + { + xi.mobSkill.SHOCK_STRIKE, + xi.mobSkill.THUNDER_II, + xi.mobSkill.THUNDERSPARK, + xi.mobSkill.ROLLING_THUNDER, + xi.mobSkill.LIGHTNING_ARMOR, + xi.mobSkill.THUNDER_IV, + }, + twoHour = xi.mobSkill.JUDGMENT_BOLT_1, + }, +} + +entity.onMobSpawn = function(mob) + mob:setMagicCastingEnabled(false) + + local avatarChosen = math.random(1, #avatarTable) + local avatarInfo = avatarTable[avatarChosen] + + mob:setModelId(avatarInfo.modelId) + mob:setLocalVar('avatarIndex', avatarChosen) +end + +entity.onMobFight = function(mob, target) + local avatarInfo = avatarTable[mob:getLocalVar('avatarIndex')] + + if not avatarInfo then + return + end + + if mob:getLocalVar('twoHourUsed') == 1 then + mob:setLocalVar('twoHourUsed', 0) + mob:useMobAbility(avatarInfo.twoHour) + end + + if mob:getLocalVar('jobAbilityUsed') == 1 then + mob:setLocalVar('jobAbilityUsed', 0) + mob:useMobAbility(avatarInfo.skillList[math.random(1, #avatarInfo.skillList)]) + end +end + +entity.onMobMobskillChoose = function(mob, target, skillId) + local avatarInfo = avatarTable[mob:getLocalVar('avatarIndex')] + + if not avatarInfo then + return 0 + end + + return avatarInfo.skillList[math.random(1, #avatarInfo.skillList)] +end + +entity.onMobDeath = function(mob, player, optParams) + if optParams.isKiller or optParams.noKiller then + local currentTime = GetSystemTime() + local fantoccini = mob:getMaster() + + if not fantoccini then + return + end + + fantoccini:setLocalVar('petSummonTime', currentTime + 45) + end +end + +return entity diff --git a/scripts/zones/Mine_Shaft_2716/mobs/Fantoccini_Monster.lua b/scripts/zones/Mine_Shaft_2716/mobs/Fantoccini_Monster.lua new file mode 100644 index 00000000000..cbcadf71f50 --- /dev/null +++ b/scripts/zones/Mine_Shaft_2716/mobs/Fantoccini_Monster.lua @@ -0,0 +1,109 @@ +---@type TMobEntity +local entity = {} + +-- TODO : Change Family Type? + +local petTable = +{ + { + name = 'Lizard', + modelId = 328, + skillList = + { + xi.mobSkill.TAIL_BLOW_1, + xi.mobSkill.FIREBALL_1, + xi.mobSkill.BLOCKHEAD_1, + xi.mobSkill.BRAIN_CRUSH_1, + xi.mobSkill.INFRASONICS_1, + xi.mobSkill.SECRETION_1, + }, + }, + + { + name = 'Sheep', + modelId = 340, + skillList = + { + xi.mobSkill.LAMB_CHOP_1, + xi.mobSkill.RAGE_1, + xi.mobSkill.SHEEP_CHARGE_1, + xi.mobSkill.SHEEP_SONG_1, + }, + }, + + { + name = 'Funguar', + modelId = 376, + skillList = + { + xi.mobSkill.FROGKICK_1, + xi.mobSkill.SPORE_1, + xi.mobSkill.QUEASYSHROOM_1, + xi.mobSkill.NUMBSHROOM_1, + xi.mobSkill.SHAKESHROOM_1, + xi.mobSkill.COUNTERSPORE_1, + xi.mobSkill.SILENCE_GAS_1, + xi.mobSkill.DARK_SPORE_1, + }, + }, + + { + name = 'Crab', + modelId = 356, + skillList = + { + xi.mobSkill.BUBBLE_SHOWER_1, + xi.mobSkill.BUBBLE_CURTAIN_1, + xi.mobSkill.BIG_SCISSORS_1, + xi.mobSkill.SCISSOR_GUARD_1, + xi.mobSkill.METALLIC_BODY_1, + }, + }, +} + +entity.onMobSpawn = function(mob) + mob:setMagicCastingEnabled(false) + + local petChosen = math.random(1, #petTable) + local petInfo = petTable[petChosen] + + mob:setModelId(petInfo.modelId) + mob:setLocalVar('petIndex', petChosen) +end + +entity.onMobFight = function(mob, target) + local petInfo = petTable[mob:getLocalVar('petIndex')] + + if not petInfo then + return + end + + if mob:getLocalVar('jobAbilityUsed') == 1 then + mob:setLocalVar('jobAbilityUsed', 0) + mob:useMobAbility(petInfo.skillList[math.random(1, #petInfo.skillList)]) + end +end + +entity.onMobMobskillChoose = function(mob, target, skillId) + local petInfo = petTable[mob:getLocalVar('petIndex')] + + if not petInfo then + return 0 + end + + return petInfo.skillList[math.random(1, #petInfo.skillList)] +end + +entity.onMobDeath = function(mob, player, optParams) + if optParams.isKiller or optParams.noKiller then + local fantoccini = mob:getMaster() + + if not fantoccini then + return + end + + fantoccini:setLocalVar('petSummonTime', GetSystemTime() + 45) + end +end + +return entity diff --git a/scripts/zones/Mine_Shaft_2716/mobs/Moblin_Fantocciniman.lua b/scripts/zones/Mine_Shaft_2716/mobs/Moblin_Fantocciniman.lua index 33030a4e28c..6e0098c477e 100644 --- a/scripts/zones/Mine_Shaft_2716/mobs/Moblin_Fantocciniman.lua +++ b/scripts/zones/Mine_Shaft_2716/mobs/Moblin_Fantocciniman.lua @@ -9,6 +9,11 @@ local entity = {} local ID = zones[xi.zone.MINE_SHAFT_2716] ----------------------------------- +-- TODO: Possible rolls are weighted? + +----------------------------------- +--- Marionette Dice Table +----------------------------------- local marionetteDice = { -- Main target: Player. @@ -29,6 +34,33 @@ local marionetteDice = [13] = xi.mobSkill.MARIONETTE_DICE_14, -- Fantoccini uses 2-hour ability } +----------------------------------- +-- Function to get the possible rolls based off the initiators job. If they are not a spell caster, mana rolls get excluded. +----------------------------------- +local function getPossibleRolls(mob) + local battlefield = mob:getBattlefield() + + if not battlefield then + return + end + + local initiatorJob = battlefield:getLocalVar('initiatorJob') + local possibleRolls = { 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13 } + + if + initiatorJob == xi.job.WHM or + initiatorJob == xi.job.BLM or + initiatorJob == xi.job.RDM or + initiatorJob == xi.job.SMN or + initiatorJob == xi.job.BLU + then + table.insert(possibleRolls, 2) + table.insert(possibleRolls, 12) + end + + return possibleRolls +end + entity.onMobInitialize = function(mob) mob:addImmunity(xi.immunity.SILENCE) mob:addImmunity(xi.immunity.BIND) @@ -52,10 +84,19 @@ end entity.onMobFight = function(mob, target) local currentTime = GetSystemTime() + ----------------------------------- + -- Marionette Dice Roll - Fetches possible rolls based off job and chooses one at random every 25-30 seconds. + ----------------------------------- if currentTime >= mob:getLocalVar('marionetteDiceTime') then mob:messageText(mob, ID.text.HO_HO + 2) -- Roly-poly, roly-poly♪ - local randomRoll = math.random(1, #marionetteDice) + local possibleRolls = getPossibleRolls(mob) + + if not possibleRolls then + return + end + + local randomRoll = possibleRolls[math.random(1, #possibleRolls)] if randomRoll >= 7 then local fantoccini = GetMobByID(mob:getID() + 2) if fantoccini and fantoccini:isAlive() then @@ -72,7 +113,10 @@ entity.onMobFight = function(mob, target) return end - if mob:getHPP() < 100 then + ----------------------------------- + -- If the moblin is attacked and goes below 95% HP, attack the player. (They can still be enfeebled without this triggering) + ----------------------------------- + if mob:getHPP() < 95 then mob:messageText(mob, ID.text.HO_HO + 11) -- Ow-ow, ow-ow! You make me mad now! mob:setLocalVar('moblinAttacked', 1) mob:setAutoAttackEnabled(true) @@ -84,7 +128,9 @@ end entity.onMobWeaponSkill = function(mob, target, skill, action) local skillUsed = skill:getID() + ----------------------------------- -- If the skill used is not Marionette Dice, return. + ----------------------------------- if skillUsed < xi.mobSkill.MARIONETTE_DICE_2 or skillUsed > xi.mobSkill.MARIONETTE_DICE_15 @@ -92,8 +138,10 @@ entity.onMobWeaponSkill = function(mob, target, skill, action) return end + ----------------------------------- -- If the Marionette Dice is good for the moblin, play emote 3, if its good for the player, play 1. -- We use a 5 second timer to delay the emote usage and to emulate the look of retail. 5 seconds looks excellent. + ----------------------------------- if skillUsed >= xi.mobSkill.MARIONETTE_DICE_7 and skillUsed < xi.mobSkill.MARIONETTE_DICE_15 diff --git a/sql/mob_groups.sql b/sql/mob_groups.sql index 3dc291a6f7e..27ff1fad6a9 100644 --- a/sql/mob_groups.sql +++ b/sql/mob_groups.sql @@ -556,11 +556,11 @@ INSERT INTO `mob_groups` VALUES (7,2707,13,'Moblin_Wisewoman',0,128,0,0,0,0,NULL INSERT INTO `mob_groups` VALUES (8,2688,13,'Moblin_Clergyman',0,128,0,0,0,0,NULL); INSERT INTO `mob_groups` VALUES (9,569,13,'Bugboy',0,128,0,19500,0,0,NULL); INSERT INTO `mob_groups` VALUES (10,2693,13,'Moblin_Fantocciniman',0,128,0,3800,0,0,NULL); -INSERT INTO `mob_groups` VALUES (11,1296,13,'Fantoccini',0,128,0,0,0,0,NULL); -INSERT INTO `mob_groups` VALUES (12,1299,13,'Fantoccini_Monster',0,128,0,0,0,0,NULL); -INSERT INTO `mob_groups` VALUES (13,1300,13,'Fantoccini_Wyvern',0,128,0,0,0,0,NULL); -INSERT INTO `mob_groups` VALUES (14,1298,13,'Fantoccini_Avatar',0,128,0,0,0,0,NULL); -INSERT INTO `mob_groups` VALUES (15,1297,13,'Fantoccini_Automaton',0,128,0,0,0,0,NULL); +INSERT INTO `mob_groups` VALUES (11,1296,13,'Fantoccini',0,128,0,8000,8000,0,NULL); +INSERT INTO `mob_groups` VALUES (12,1299,13,'Fantoccini_Monster',0,128,0,750,0,0,NULL); +INSERT INTO `mob_groups` VALUES (13,1300,13,'Fantoccini_Wyvern',0,128,0,750,0,0,NULL); +INSERT INTO `mob_groups` VALUES (14,1298,13,'Fantoccini_Avatar',0,128,0,750,0,0,NULL); +INSERT INTO `mob_groups` VALUES (15,1297,13,'Fantoccini_Automaton',0,128,0,750,8000,0,NULL); INSERT INTO `mob_groups` VALUES (16,2006,13,'Hume_Automaton',0,128,0,3000,3000,0,NULL); INSERT INTO `mob_groups` VALUES (17,1206,13,'Elvaan_Automaton',0,128,0,3000,3000,0,NULL); INSERT INTO `mob_groups` VALUES (18,3850,13,'Tarutaru_Automaton',0,128,0,2000,2000,0,NULL); diff --git a/sql/mob_pools.sql b/sql/mob_pools.sql index 4993e92ca25..ada542d3e67 100644 --- a/sql/mob_pools.sql +++ b/sql/mob_pools.sql @@ -1351,10 +1351,10 @@ INSERT INTO `mob_pools` VALUES (1292,'Fallen_Volunteer','Fallen_Volunteer',360,0 INSERT INTO `mob_pools` VALUES (1293,'Falsespinner_Bhudbrodd','Falsespinner_Bhudbrodd',189,0x0000020800000000000000000000000000000000,2,2,1,480,100,0,1,1,1,2,0,32,27,669,8,0,0,0,0,334,334,2,17); INSERT INTO `mob_pools` VALUES (1294,'Faluuya','Faluuya',149,0x05005B0700000000000000000000000000000000,6,6,3,240,100,0,0,0,0,0,0,0,0,0,0,0,0,0,0,149,149,1,17); INSERT INTO `mob_pools` VALUES (1295,'Fantasma','Fantasma',121,0x0000700100000000000000000000000000000000,1,4,12,240,100,0,1,0,0,0,0,0,155,131,0,0,28,0,0,121,121,1,8); -INSERT INTO `mob_pools` VALUES (1296,'Fantoccini','Fantoccini',149,0x0500D20400000000000000000000000000000000,1,1,0,240,100,0,0,0,1,16,0,0,8160,131,0,0,0,0,0,149,149,1,17); -INSERT INTO `mob_pools` VALUES (1297,'Fantoccini_Automaton','Fantoccini_Automaton',28,0x0600B90700000000000000000000000000000000,1,1,5,320,100,0,1,1,0,18,0,0,1712,2179,0,0,0,0,0,28,28,NULL,NULL); +INSERT INTO `mob_pools` VALUES (1296,'Fantoccini','Fantoccini',149,0x0500D20400000000000000000000000000000000,1,1,0,240,100,0,0,0,1,16,0,0,8160,131,0,0,1,0,0,149,149,1,17); +INSERT INTO `mob_pools` VALUES (1297,'Fantoccini_Automaton','Fantoccini_Automaton',28,0x0600B90700000000000000000000000000000000,1,5,5,320,100,0,1,1,0,18,0,0,1712,131,0,0,3,0,0,363,28,NULL,NULL); INSERT INTO `mob_pools` VALUES (1298,'Fantoccini_Avatar','Fantoccini_Avatar',34,0x0000170300000000000000000000000000000000,4,4,7,240,100,0,1,1,0,16,0,0,6651,131,0,0,2,0,0,34,34,1,24); -INSERT INTO `mob_pools` VALUES (1299,'Fantoccini_Monster','Fantoccini_Monster',206,0x00000C0100000000000000000000000000000000,6,6,7,240,100,0,1,0,1,16,0,0,2316,2177,0,0,0,0,0,206,206,0,20); +INSERT INTO `mob_pools` VALUES (1299,'Fantoccini_Monster','Fantoccini_Monster',206,0x00000C0100000000000000000000000000000000,6,6,7,240,100,0,1,0,1,16,0,0,2316,131,0,0,0,0,0,206,206,0,20); INSERT INTO `mob_pools` VALUES (1300,'Fantoccini_Wyvern','Fantoccini_Wyvern',193,0x0000180000000000000000000000000000000000,1,1,7,200,100,0,1,1,0,16,0,0,0,3,0,0,0,0,0,714,193,1,8); INSERT INTO `mob_pools` VALUES (1301,'Farfadet','Farfadet',195,0x0000EE0700000000000000000000000000000000,3,3,12,240,100,0,0,0,1,0,0,0,0,515,8,0,20,0,0,195,195,1,8); INSERT INTO `mob_pools` VALUES (1302,'Farlarder_the_Shrewd','Farlarder_the_Shrewd',246,0x0600B00600000000000000000000000000000000,2,2,1,480,100,0,1,1,1,2,0,32,0,159,4,0,0,0,0,246,246,3,17); diff --git a/sql/mob_skills.sql b/sql/mob_skills.sql index 58388e2bce1..18d71dfd93d 100644 --- a/sql/mob_skills.sql +++ b/sql/mob_skills.sql @@ -1456,17 +1456,17 @@ INSERT INTO `mob_skills` VALUES (1424,1053,'marionette_dice_11',0,0.0,15.0,2000, INSERT INTO `mob_skills` VALUES (1425,1053,'marionette_dice_12',0,0.0,15.0,2000,1500,65,4,0,0,0,0,0); -- INSERT INTO `mob_skills` VALUES (1426,1054,'marionette_dice_13',0,0.0,15.0,2000,1500,65,4,0,0,0,0,0); -- Unused INSERT INTO `mob_skills` VALUES (1427,1054,'marionette_dice_14',0,0.0,15.0,2000,1500,65,4,0,0,0,0,0); --- INSERT INTO `mob_skills` VALUES (1428,1172,'warcry',0,0.0,7.0,2000,1500,4,0,0,0,0,0,0); --- INSERT INTO `mob_skills` VALUES (1429,1173,'counterstance_4',0,0.0,7.0,2000,1500,4,0,0,0,0,0,0); --- INSERT INTO `mob_skills` VALUES (1430,1174,'steal',0,0.0,7.0,2000,1500,4,0,0,0,0,0,0); -INSERT INTO `mob_skills` VALUES (1431,803,'shield_bash',0,0.0,7.0,2000,1500,4,4,0,0,0,0,0); --- INSERT INTO `mob_skills` VALUES (1432,1176,'weapon_bash',0,0.0,7.0,2000,1500,4,0,0,0,0,0,0); --- INSERT INTO `mob_skills` VALUES (1433,1177,'sic',0,0.0,7.0,2000,1500,4,0,0,0,0,0,0); +INSERT INTO `mob_skills` VALUES (1428,28,'warcry',0,0.0,7.0,2000,0,1,0,0,0,0,0,0); -- Finish 6 +INSERT INTO `mob_skills` VALUES (1429,8,'counterstance_4',0,0.0,7.0,2000,0,1,0,0,0,0,0,0); -- Finish 6 +INSERT INTO `mob_skills` VALUES (1430,181,'steal',0,0.0,7.0,2000,0,4,0,0,0,0,0,0); -- Finish 3 +INSERT INTO `mob_skills` VALUES (1431,185,'shield_bash_1',0,0.0,7.0,2000,0,4,4,0,0,0,0,0); -- Finish 3 +INSERT INTO `mob_skills` VALUES (1432,202,'weapon_bash',0,0.0,7.0,2000,0,4,0,0,0,0,0,0); -- Finish 3 +INSERT INTO `mob_skills` VALUES (1433,83,'sic',0,0.0,7.0,2000,0,1,0,0,0,0,0,0); -- Finish 6 INSERT INTO `mob_skills` VALUES (1434,23,'barrage',0,0.0,7.0,2000,0,1,0,0,0,0,0,0); --- INSERT INTO `mob_skills` VALUES (1435,1179,'.',0,0.0,7.0,2000,1500,4,0,0,0,0,0,0); --- INSERT INTO `mob_skills` VALUES (1436,1180,'meditate',0,0.0,7.0,2000,1500,4,0,0,0,0,0,0); --- INSERT INTO `mob_skills` VALUES (1437,1181,'jump',0,0.0,7.0,2000,1500,4,0,0,0,0,0,0); --- INSERT INTO `mob_skills` VALUES (1438,1182,'blood_pact',0,0.0,7.0,2000,1500,4,0,0,0,0,0,0); +-- INSERT INTO `mob_skills` VALUES (1435,1179,'',0,0.0,7.0,2000,1500,4,0,0,0,0,0,0); -- Unused +INSERT INTO `mob_skills` VALUES (1436,25,'meditate',0,0.0,7.0,2000,0,1,0,0,0,0,0,0); -- Finish 6 +INSERT INTO `mob_skills` VALUES (1437,204,'jump_6',0,0.0,7.0,2000,0,4,0,0,0,0,0,0); -- Finish 3 +INSERT INTO `mob_skills` VALUES (1438,94,'blood_pact',0,0.0,7.0,2000,0,1,0,0,0,0,0,0); -- Finish 6 -- INSERT INTO `mob_skills` VALUES (1439,1057,'aetheral_toxin',0,0.0,7.0,2000,1500,4,0,0,0,0,0,0); -- INSERT INTO `mob_skills` VALUES (1440,1058,'edge_of_death',0,0.0,7.0,2000,1500,4,0,0,0,0,0,0); INSERT INTO `mob_skills` VALUES (1441,1065,'actinic_burst',1,0.0,10.0,2000,1500,4,0,0,0,0,0,0); @@ -2013,13 +2013,13 @@ INSERT INTO `mob_skills` VALUES (1980,1197,'boreas_mantle',0,0.0,7.0,2000,1500,1 -- INSERT INTO `mob_skills` VALUES (1982,1726,'nullifying_dropkick',0,0.0,7.0,2000,1500,4,0,0,0,0,0,0); -- INSERT INTO `mob_skills` VALUES (1983,1727,'auroral_uppercut',0,0.0,7.0,2000,1500,4,0,0,0,0,0,0); -- INSERT INTO `mob_skills` VALUES (1984,1728,'wisecrack',0,0.0,10.0,2000,1500,4,0,0,0,0,0,0); --- INSERT INTO `mob_skills` VALUES (1985,1729,'fighters_roll',0,0.0,7.0,2000,1500,4,0,0,0,0,0,0); --- INSERT INTO `mob_skills` VALUES (1986,1730,'rogues_roll',0,0.0,7.0,2000,1500,4,0,0,0,0,0,0); --- INSERT INTO `mob_skills` VALUES (1987,1731,'gallants_roll',0,0.0,7.0,2000,1500,4,0,0,0,0,0,0); --- INSERT INTO `mob_skills` VALUES (1988,1732,'chaos_roll',0,0.0,7.0,2000,1500,4,0,0,0,0,0,0); --- INSERT INTO `mob_skills` VALUES (1989,1733,'hunters_roll',0,0.0,7.0,2000,1500,4,0,0,0,0,0,0); --- INSERT INTO `mob_skills` VALUES (1990,1734,'ninja_roll',0,0.0,7.0,2000,1500,4,0,0,0,0,0,0); --- INSERT INTO `mob_skills` VALUES (1991,1735,'double-up',0,0.0,7.0,2000,1500,4,0,0,0,0,0,0); +-- INSERT INTO `mob_skills` VALUES (1985,1729,'fighters_roll',1,8.0,7.0,2000,1500,1,0,0,0,0,0,0); +-- INSERT INTO `mob_skills` VALUES (1986,1730,'rogues_roll',1,8.0,7.0,2000,1500,1,0,0,0,0,0,0); +-- INSERT INTO `mob_skills` VALUES (1987,1731,'gallants_roll',1,8.0,7.0,2000,1500,1,0,0,0,0,0,0); +-- INSERT INTO `mob_skills` VALUES (1988,1732,'chaos_roll',1,8.0,7.0,2000,1500,1,0,0,0,0,0,0); +-- INSERT INTO `mob_skills` VALUES (1989,1733,'hunters_roll',1,8.0,7.0,2000,1500,1,0,0,0,0,0,0); +-- INSERT INTO `mob_skills` VALUES (1990,1734,'ninja_roll',1,8.0,7.0,2000,1500,1,0,0,0,0,0,0); +-- INSERT INTO `mob_skills` VALUES (1991,1735,'double-up',1,8.0,7.0,2000,1500,1,0,0,0,0,0,0); INSERT INTO `mob_skills` VALUES (1992,94,'fire_maneuver',0,0.0,7.0,2000,0,1,4,0,0,0,0,0); INSERT INTO `mob_skills` VALUES (1993,94,'ice_maneuver',0,0.0,7.0,2000,0,1,4,0,0,0,0,0); INSERT INTO `mob_skills` VALUES (1994,94,'wind_maneuver',0,0.0,7.0,2000,0,1,4,0,0,0,0,0); diff --git a/sql/mob_spawn_points.sql b/sql/mob_spawn_points.sql index 55fb7244a57..18464396b2f 100644 --- a/sql/mob_spawn_points.sql +++ b/sql/mob_spawn_points.sql @@ -2750,24 +2750,24 @@ INSERT INTO `mob_spawn_points` VALUES (16830503,0,'Bugboy','Bugboy',9,80,80,20.1 INSERT INTO `mob_spawn_points` VALUES (16830505,0,'Bugboy','Bugboy',9,80,80,500.362,-118.468,16.365,64); -- Pulling the Strings -INSERT INTO `mob_spawn_points` VALUES (16830507,0,'Moblin_Fantocciniman','Moblin Fantocciniman',10,62,62,-460.744,121.500,9.581,64); -INSERT INTO `mob_spawn_points` VALUES (16830509,0,'Fantoccini','Fantoccini',11,55,55,-460.877,120.524,3.321,40); -INSERT INTO `mob_spawn_points` VALUES (16830510,0,'Fantoccini_Monster','Fantoccini Monster',12,49,49,-458.769,121.532,19.387,39); -INSERT INTO `mob_spawn_points` VALUES (16830511,0,'Fantoccini_Wyvern','Fantoccini Wyvern',13,49,49,0.000,0.000,0.000,0); -INSERT INTO `mob_spawn_points` VALUES (16830512,0,'Fantoccini_Avatar','Fantoccini Avatar',14,49,49,-461.058,119.431,-14.295,192); -INSERT INTO `mob_spawn_points` VALUES (16830513,0,'Fantoccini_Automaton','Fantoccini Automaton',15,49,49,-461.140,121.491,8.490,63); -INSERT INTO `mob_spawn_points` VALUES (16830514,0,'Moblin_Fantocciniman','Moblin Fantocciniman',10,62,62,16.000,1.704,26.000,64); -INSERT INTO `mob_spawn_points` VALUES (16830516,0,'Fantoccini','Fantoccini',11,55,55,20.000,1.532,20.000,40); -INSERT INTO `mob_spawn_points` VALUES (16830517,0,'Fantoccini_Monster','Fantoccini Monster',12,49,49,21.213,1.532,19.324,39); -INSERT INTO `mob_spawn_points` VALUES (16830518,0,'Fantoccini_Wyvern','Fantoccini Wyvern',13,49,49,0.000,0.000,0.000,0); -INSERT INTO `mob_spawn_points` VALUES (16830519,0,'Fantoccini_Avatar','Fantoccini Avatar',14,49,49,18.924,-0.569,-14.358,192); -INSERT INTO `mob_spawn_points` VALUES (16830520,0,'Fantoccini_Automaton','Fantoccini Automaton',15,49,49,20.773,1.532,18.013,63); -INSERT INTO `mob_spawn_points` VALUES (16830521,0,'Moblin_Fantocciniman','Moblin Fantocciniman',10,62,62,500.144,-119.946,1.794,64); -INSERT INTO `mob_spawn_points` VALUES (16830523,0,'Fantoccini','Fantoccini',11,55,55,500.503,-120.500,-3.613,40); -INSERT INTO `mob_spawn_points` VALUES (16830524,0,'Fantoccini_Monster','Fantoccini Monster',12,49,49,501.182,-118.468,19.328,39); -INSERT INTO `mob_spawn_points` VALUES (16830525,0,'Fantoccini_Wyvern','Fantoccini Wyvern',13,49,49,0.000,0.000,0.000,0); -INSERT INTO `mob_spawn_points` VALUES (16830526,0,'Fantoccini_Avatar','Fantoccini Avatar',14,49,49,498.893,-120.569,-14.354,192); -INSERT INTO `mob_spawn_points` VALUES (16830527,0,'Fantoccini_Automaton','Fantoccini Automaton',15,49,49,501.054,-118.864,5.299,63); +INSERT INTO `mob_spawn_points` VALUES (16830507,0,'Moblin_Fantocciniman','Moblin Fantocciniman',10,62,62,-464,121.704,26,64); +INSERT INTO `mob_spawn_points` VALUES (16830509,0,'Fantoccini','Fantoccini',11,60,60,-460,121.532,20,64); +INSERT INTO `mob_spawn_points` VALUES (16830510,0,'Fantoccini_Monster','Fantoccini Monster',12,57,57,-460,121.532,20,64); +INSERT INTO `mob_spawn_points` VALUES (16830511,0,'Fantoccini_Wyvern','Fantoccini Wyvern',13,57,57,-460,121.532,20,64); +INSERT INTO `mob_spawn_points` VALUES (16830512,0,'Fantoccini_Avatar','Fantoccini Avatar',14,57,57,-460,121.532,20,64); +INSERT INTO `mob_spawn_points` VALUES (16830513,0,'Fantoccini_Automaton','Fantoccini Automaton',15,57,57,-460,121.532,20,64); +INSERT INTO `mob_spawn_points` VALUES (16830514,0,'Moblin_Fantocciniman','Moblin Fantocciniman',10,62,62,16.000,2.204,26.000,64); +INSERT INTO `mob_spawn_points` VALUES (16830516,0,'Fantoccini','Fantoccini',11,60,60,20.000,2.032,20.000,64); +INSERT INTO `mob_spawn_points` VALUES (16830517,0,'Fantoccini_Monster','Fantoccini Monster',12,57,57,20.000,2.032,20.000,64); +INSERT INTO `mob_spawn_points` VALUES (16830518,0,'Fantoccini_Wyvern','Fantoccini Wyvern',13,57,57,20.000,2.032,20.000,64); +INSERT INTO `mob_spawn_points` VALUES (16830519,0,'Fantoccini_Avatar','Fantoccini Avatar',14,57,57,20.000,2.032,20.000,64); +INSERT INTO `mob_spawn_points` VALUES (16830520,0,'Fantoccini_Automaton','Fantoccini Automaton',15,57,57,20.000,2.032,20.000,64); +INSERT INTO `mob_spawn_points` VALUES (16830521,0,'Moblin_Fantocciniman','Moblin Fantocciniman',10,62,62,496.191,-117.796,26.297,64); +INSERT INTO `mob_spawn_points` VALUES (16830523,0,'Fantoccini','Fantoccini',11,60,60,500.191,-117.968,20.297,64); +INSERT INTO `mob_spawn_points` VALUES (16830524,0,'Fantoccini_Monster','Fantoccini Monster',12,57,57,500.191,-117.968,20.297,64); +INSERT INTO `mob_spawn_points` VALUES (16830525,0,'Fantoccini_Wyvern','Fantoccini Wyvern',13,57,57,500.191,-117.968,20.297,64); +INSERT INTO `mob_spawn_points` VALUES (16830526,0,'Fantoccini_Avatar','Fantoccini Avatar',14,57,57,500.191,-117.968,20.297,64); +INSERT INTO `mob_spawn_points` VALUES (16830527,0,'Fantoccini_Automaton','Fantoccini Automaton',15,57,57,500.191,-117.968,20.297,64); -- Automaton Assault INSERT INTO `mob_spawn_points` VALUES (16830529,0,'Hume_Automaton','Hume Automaton',16,62,62,-466,121.704,26,64);