diff --git a/scripts/actions/abilities/pets/altana_s_favor.lua b/scripts/actions/abilities/pets/altana_s_favor.lua new file mode 100644 index 00000000000..91d3f90c820 --- /dev/null +++ b/scripts/actions/abilities/pets/altana_s_favor.lua @@ -0,0 +1,35 @@ +--------------------------------------------- +-- Altana's Favor +--------------------------------------------- +local abilityObject = {} + +abilityObject.onAbilityCheck = function(player, target, ability) + local level = player:getMainLvl() * 2 + + if player:getMP() < level then + return 87, 0 + end + + return 0,0 +end + +abilityObject.onPetAbility = function(target, pet, skill, master, action) + if not target:isPC() then + skill:setMsg(xi.msg.basic.NO_EFFECT) + return 0 + end + + if target:isDead() then + target:sendRaise(5) + end + + if target:addStatusEffect(xi.effect.RERAISE, 3, 0, 0) then -- Infinite duration http://wiki.ffo.jp/html/30976.html + skill:setMsg(xi.msg.basic.IS_EFFECT) + return xi.effect.RERAISE + else + skill:setMsg(xi.msg.basic.NO_EFFECT) + return 0 + end +end + +return abilityObject diff --git a/scripts/actions/abilities/pets/eerie_eye.lua b/scripts/actions/abilities/pets/eerie_eye.lua new file mode 100644 index 00000000000..5dd61fb8d03 --- /dev/null +++ b/scripts/actions/abilities/pets/eerie_eye.lua @@ -0,0 +1,61 @@ +--------------------------------------------------- +-- Eerie Eye +-- silence + amnesia +--------------------------------------------------- +require("scripts/globals/settings") +require("scripts/globals/status") +require("scripts/globals/monstertpmoves") +require("scripts/globals/summon") +require("scripts/globals/msg") +--------------------------------------------------- + +function onAbilityCheck(player, target, ability) + return 0,0 +end + +function onPetAbility(target, pet, skill) + local returnEffect = xi.effect.NONE + local duration = 30 + local mpCost = 134 + local ele = xi.magic.ele.LIGHT + local bonus = pet:getStat(xi.mod.CHR) - target:getStat(xi.mod.CHR) - 10 + if pet:getMaster() ~= nil and (pet:getMaster()):isPC() then + bonus = bonus + getSummoningSkillOverCap(pet) + end + + local resist = applyResistanceAbility(pet,target,ele,xi.skill.ENFEEBLING_MAGIC,bonus) + + -- https://wikiwiki.jp/ffxi/%E5%8F%AC%E5%96%9A%E9%AD%94%E6%B3%95 + -- TL;DR 30s silence and 10s amnesia and amnesia is fire element + if resist >= 0.5 then --Do it! + if target:addStatusEffect(xi.effect.SILENCE, 1, 0, duration * resist) then + skill:setMsg(xi.msg.basic.SKILL_ENFEEB_IS) + local resist2 = applyResistanceAbility(pet,target,xi.magic.ele.FIRE,xi.skill.ENFEEBLING_MAGIC,bonus) + -- WINGSCUSTOM require 2 successful resistance checks (and actual application of SILENCE) + if resist * resist2 >= 1 and target:addStatusEffect(xi.effect.AMNESIA, 1, 0, duration * resist2 / 3) then + returnEffect = xi.effect.AMNESIA + else + returnEffect = xi.effect.SILENCE + end + else + skill:setMsg(xi.msg.basic.SKILL_NO_EFFECT) + end + else + skill:setMsg(xi.msg.basic.SKILL_NO_EFFECT) + end + + return returnEffect + + local duration = 180 + summoner:getMod(xi.mod.SUMMONING) + if duration > 350 then + duration = 350 + end + + if target:addStatusEffect(xi.effect.SLOW, 3000, 0, duration) then + skill:setMsg(xi.msg.basic.SKILL_ENFEEB_IS) + else + skill:setMsg(xi.msg.basic.SKILL_NO_EFFECT) + end + + return xi.effect.SLOW +end \ No newline at end of file diff --git a/scripts/actions/abilities/pets/level_X_holy.lua b/scripts/actions/abilities/pets/level_X_holy.lua new file mode 100644 index 00000000000..e788d75eea9 --- /dev/null +++ b/scripts/actions/abilities/pets/level_X_holy.lua @@ -0,0 +1,39 @@ +--------------------------------------------------- +-- Level X Holy +--------------------------------------------------- +local abilityObject = {} + +abilityObject.onAbilityCheck = function(player, target, ability) + return 0,0 +end + +abilityObject.onPetAbility = function(target, pet, skill, master, action) + local holyRollOneAnimID = 164 + local power = action:getAnimation(target:getID()) - holyRollOneAnimID + 1 + print(power) + local dMND = math.floor(pet:getStat(xi.mod.MND) - target:getStat(xi.mod.MND)) + local ele = xi.damageType.LIGHT + local dmg = 0 + + local dmgmod = 1 + local basedmg = pet:getMainLvl() * power + (dMND * 1.5) + if target:getMainLvl() % power == 0 then + local info = MobMagicalMove(pet, target, skill, basedmg, ele - 5, dmgmod, TP_NO_EFFECT, 10) + dmg = mobAddBonuses(pet, nil, target, info.dmg, ele - 5) + dmg = AvatarFinalAdjustments(dmg,pet,skill,target,xi.attackType.MAGICAL,ele,1) + + local skillchainTier, skillchainCount = FormMagicBurst(ele - 5, target) + if (skillchainTier > 0) then + skill:setMsg(747) + end + + target:takeDamage(dmg, pet, xi.attackType.MAGICAL, ele) + target:updateEnmityFromDamage(pet,dmg) + else + skill:setMsg(xi.msg.basic.SKILL_NO_EFFECT) + end + + return dmg +end + +return abilityObject diff --git a/scripts/actions/abilities/pets/mewing_lullaby.lua b/scripts/actions/abilities/pets/mewing_lullaby.lua new file mode 100644 index 00000000000..00843d79b6a --- /dev/null +++ b/scripts/actions/abilities/pets/mewing_lullaby.lua @@ -0,0 +1,43 @@ +--------------------------------------------------- +-- Mewing Lullaby +-- aoe light based sleep and lowers mob TP to zero +--------------------------------------------------- +require("scripts/globals/settings") +require("scripts/globals/status") +require("scripts/globals/monstertpmoves") +require("scripts/globals/summon") +require("scripts/globals/msg") +require("scripts/globals/magic") +--------------------------------------------------- + +function onAbilityCheck(player, target, ability) + return 0,0 +end + +function onPetAbility(target, pet, skill) + local mpCost = 61 + local duration = 35 + local bonus = pet:getStat(tpz.mod.CHR) - target:getStat(tpz.mod.CHR) - 10 + if pet:getMaster() ~= nil and (pet:getMaster()):isPC() then + bonus = bonus + getSummoningSkillOverCap(pet) + end + + local resist = applyResistanceAbility(pet,target,tpz.magic.element.LIGHT,tpz.skill.ENFEEBLING_MAGIC,bonus) + skill:setMsg(tpz.msg.basic.SKILL_NO_EFFECT) + + duration = math.ceil(duration * resist * tryBuildResistance(tpz.mod.RESBUILD_LULLABY, target)) + if resist >= 0.5 then --Do it! + if not (target:hasImmunity(1) or hasSleepEffects(target)) and target:addStatusEffect(tpz.effect.LULLABY, 1, 0, duration) then + skill:setMsg(tpz.msg.basic.SKILL_ENFEEB_IS) + -- WINGSCUSTOM require 2 successful resistance checks (and actual application of SLEEP) + local resist2 = applyResistanceAbility(pet,target,tpz.magic.element.LIGHT,tpz.skill.ENFEEBLING_MAGIC,bonus) + if resist * resist2 >= 1 and not target:isNM() then + target:setTP(0) + end + end + end + + pet:getMaster():addMP(math.floor(-mpCost/skill:getTotalTargets())) + + return tpz.effect.SLEEP_I +end \ No newline at end of file diff --git a/scripts/actions/abilities/pets/raise_ii.lua b/scripts/actions/abilities/pets/raise_ii.lua new file mode 100644 index 00000000000..54a9d5499b7 --- /dev/null +++ b/scripts/actions/abilities/pets/raise_ii.lua @@ -0,0 +1,26 @@ +--------------------------------------------- +-- Raise II +--------------------------------------------- +local abilityObject = {} + +abilityObject.onAbilityCheck = function(player, target, ability) + -- no restrition on being in party + if target:isAlive() then + return xi.msg.basic.UNABLE_TO_USE_JA, 0 + end + + return 0, 0 +end + +abilityObject.onPetAbility = function(target, pet, skill, master, action) + if not target:isPC() or target:isAlive() then + skill:setMsg(xi.msg.basic.NO_EFFECT) + return 0 + end + + skill:setMsg(xi.msg.basic.NONE) + target:sendRaise(2) + return 0 +end + +return abilityObject diff --git a/scripts/actions/abilities/pets/regal_scratch.lua b/scripts/actions/abilities/pets/regal_scratch.lua new file mode 100644 index 00000000000..1ebd103b503 --- /dev/null +++ b/scripts/actions/abilities/pets/regal_scratch.lua @@ -0,0 +1,34 @@ +--------------------------------------------------- +-- Regal Scratch +-- M=3,1 +--------------------------------------------------- +local abilityObject = {} + +abilityObject.onAbilityCheck = function(player, target, ability) + return 0,0 +end + +abilityObject.onPetAbility = function(target, pet, skill, master, action) + print(action:getAnimation(target:getID())) + local mpCost = 5 + local ele = tpz.damageType.LIGHT + local params = {} + params.str_wsc = 0.0 params.dex_wsc = 0.3 params.vit_wsc = 0.0 params.agi_wsc = 0.0 params.int_wsc = 0.0 params.mnd_wsc = 0.0 params.chr_wsc = 0.0 + params.ele = tpz.magic.element.LIGHT + local numhits = 3 + local accmod = -5 + local dmgmod = 3 + local dmgmodsubsequent = 1 + local totaldamage = 0 + + local damage = AvatarPhysicalMove(pet, target, skill, numhits, accmod, dmgmod, dmgmodsubsequent, TP_NO_EFFECT, 1, 2, 3, 0, params) + totaldamage = AvatarFinalAdjustments(damage.dmg, pet, skill, target, tpz.attackType.PHYSICAL, tpz.damageType.SLASHING, numhits) + + target:takeDamage(totaldamage, pet, tpz.attackType.PHYSICAL, tpz.damageType.SLASHING) + target:updateEnmityFromDamage(pet, totaldamage) + + pet:getMaster():addMP(-mpCost) + return totaldamage +end + +return abilityObject diff --git a/scripts/actions/abilities/pets/reraise_ii.lua b/scripts/actions/abilities/pets/reraise_ii.lua new file mode 100644 index 00000000000..5192f8f7b85 --- /dev/null +++ b/scripts/actions/abilities/pets/reraise_ii.lua @@ -0,0 +1,25 @@ +--------------------------------------------- +-- Reraise II +--------------------------------------------- +local abilityObject = {} + +abilityObject.onAbilityCheck = function(player, target, ability) + if not target:isAlive() then + return xi.msg.basic.UNABLE_TO_USE_JA, 0 + end + + return 0, 0 +end + +abilityObject.onPetAbility = function(target, pet, skill, master, action) + if not target:isPC() or not (target:addStatusEffect(xi.effect.RERAISE, 2, 0, 3600)) then + skill:setMsg(xi.msg.basic.NO_EFFECT) + return 0 + end + + skill:setMsg(xi.msg.basic.IS_EFFECT) + + return xi.effect.RERAISE +end + +return abilityObject diff --git a/scripts/actions/spells/summoning/cait_sith.lua b/scripts/actions/spells/summoning/cait_sith.lua new file mode 100644 index 00000000000..9343e0ec791 --- /dev/null +++ b/scripts/actions/spells/summoning/cait_sith.lua @@ -0,0 +1,32 @@ +----------------------------------- +-- Spell: Diabolos +-- Summons Diabolos to fight by your side +----------------------------------- +local spellObject = {} + +spellObject.onMagicCastingCheck = function(caster, target, spell) + if not caster:canUseMisc(xi.zoneMisc.PET) then + return xi.msg.basic.CANT_BE_USED_IN_AREA + elseif caster:hasPet() then + return xi.msg.basic.ALREADY_HAS_A_PET + elseif caster:getObjType() == xi.objType.PC then + return xi.summon.avatarMiniFightCheck(caster) + end + + return 0 +end + +spellObject.onSpellCast = function(caster, target, spell) + xi.pet.spawnPet(caster, xi.petId.CAIT_SITH) + + if caster:hasStatusEffect(xi.effect.AVATARS_FAVOR) then + local effect = caster:getStatusEffect(xi.effect.AVATARS_FAVOR) + effect:setPower(1) -- resummon resets effect + xi.avatarsFavor.applyAvatarsFavorAuraToPet(caster, effect) + xi.avatarsFavor.applyAvatarsFavorDebuffsToPet(caster) + end + + return 0 +end + +return spellObject diff --git a/sql/abilities.sql b/sql/abilities.sql index 9f7bc9c13cb..12493d31710 100644 --- a/sql/abilities.sql +++ b/sql/abilities.sql @@ -408,13 +408,13 @@ INSERT INTO `abilities` VALUES (517,'healing_ruby_ii',15,65,1,60,174,0,0,124,200 INSERT INTO `abilities` VALUES (518,'searing_light',15,1,4,60,173,0,0,0,2000,0,6,18.0,1,1,60,0,2,NULL); -- INSERT INTO `abilities` VALUES (519,'holy_misy',22,1,1,0,300,0,0,???,2000,0,6,20.0,0,450,900,0,0,NULL); -- INSERT INTO `abilities` VALUES (520,'soothing_ruby',22,1,1,0,300,0,0,???,2000,0,6,20.0,0,450,900,0,0,NULL); --- INSERT INTO `abilities` VALUES (521,'regal_scratch',22,1,1,0,300,0,0,???,2000,0,6,20.0,0,450,900,0,0,NULL); --- INSERT INTO `abilities` VALUES (522,'mewing_lullaby',22,1,1,0,300,0,0,???,2000,0,6,20.0,0,450,900,0,0,NULL); --- INSERT INTO `abilities` VALUES (523,'earie_eye',22,1,1,0,300,0,0,???,2000,0,6,20.0,0,450,900,0,0,NULL); --- INSERT INTO `abilities` VALUES (524,'level_?_holy',22,1,1,0,300,0,0,???,2000,0,6,20.0,0,450,900,0,0,NULL); --- INSERT INTO `abilities` VALUES (525,'raise_ii',22,1,1,0,300,0,0,???,2000,0,6,20.0,0,450,900,0,0,NULL); --- INSERT INTO `abilities` VALUES (526,'reraise_ii',22,1,1,0,300,0,0,???,2000,0,6,20.0,0,450,900,0,0,NULL); --- INSERT INTO `abilities` VALUES (527,'altana_s_favor',22,1,1,0,300,0,0,???,2000,0,6,20.0,0,450,900,0,0,NULL); +INSERT INTO `abilities` VALUES (521,'regal_scratch',15,1,4,60,173,0,0,5,2000,0,6,18.0,0,1,60,0,0,NULL); +INSERT INTO `abilities` VALUES (522,'mewing_lullaby',15,25,4,60,174,0,0,61,2000,0,6,18.0,0,1,60,0,0,NULL); +INSERT INTO `abilities` VALUES (523,'eerie_eye',15,55,4,60,174,0,0,134,2000,0,6,18.0,0,1,60,0,0,NULL); +INSERT INTO `abilities` VALUES (524,'level_X_holy',15,75,4,60,173,0,0,235,2000,0,6,18.0,0,1,60,0,0,NULL); +INSERT INTO `abilities` VALUES (525,'raise_ii',15,15,34,60,174,0,0,160,2000,0,6,18.0,0,1,60,0,0,NULL); +INSERT INTO `abilities` VALUES (526,'reraise_ii',15,30,3,60,174,0,0,80,2000,0,6,18.0,0,1,60,0,0,NULL); +INSERT INTO `abilities` VALUES (527,'altana_s_favor',15,1,1,60,174,0,0,0,2000,0,6,18.0,0,1,60,0,2,NULL); INSERT INTO `abilities` VALUES (528,'moonlit_charge',15,5,4,60,173,0,0,17,2000,0,6,18.0,0,1,60,0,0,NULL); INSERT INTO `abilities` VALUES (529,'crescent_fang',15,10,4,60,173,0,0,19,2000,0,6,18.0,0,1,60,0,0,NULL); INSERT INTO `abilities` VALUES (530,'lunar_cry',15,21,4,60,174,0,0,41,2000,0,6,18.0,0,1,60,0,0,NULL); diff --git a/sql/pet_list.sql b/sql/pet_list.sql index 174eb920ac0..cacbc3af62b 100644 --- a/sql/pet_list.sql +++ b/sql/pet_list.sql @@ -45,7 +45,7 @@ INSERT INTO `pet_list` VALUES (16,'Diabolos',4590,1,99,0,8); INSERT INTO `pet_list` VALUES (17,'Alexander',4589,1,99,0,7); INSERT INTO `pet_list` VALUES (18,'Odin',4591,1,99,0,8); INSERT INTO `pet_list` VALUES (19,'Atomos',1,1,99,0,0); -INSERT INTO `pet_list` VALUES (20,'CaitSith',1,1,99,0,0); +INSERT INTO `pet_list` VALUES (20,'CaitSith',5775,1,99,0,0); INSERT INTO `pet_list` VALUES (21,'SheepFamiliar',4598,23,35,3600,0); INSERT INTO `pet_list` VALUES (22,'HareFamiliar',4641,23,35,5400,0); INSERT INTO `pet_list` VALUES (23,'CrabFamiliar',4610,23,55,1800,0); diff --git a/sql/pet_skills.sql b/sql/pet_skills.sql index 8c3ceff3720..d97b98e36a0 100644 --- a/sql/pet_skills.sql +++ b/sql/pet_skills.sql @@ -42,6 +42,15 @@ CREATE TABLE `pet_skills` ( -- Table contents for `pet_skills` -- +-- Cait Sith +INSERT INTO `pet_skills` VALUES (521,161,'regal_scratch',0,18.0,2000,1000,4,317,@SKILLFLAG_SPECIAL | @SKILLFLAG_BLOODPACT_RAGE,0,13,0,4,0,0); -- Scission (4) +INSERT INTO `pet_skills` VALUES (522,162,'mewing_lullaby',1,12.0,2000,1000,4,317,@SKILLFLAG_SPECIAL | @SKILLFLAG_BLOODPACT_WARD,0,13,0,0,0,0); +INSERT INTO `pet_skills` VALUES (523,163,'eerie_eye',4,18.0,2000,1000,4,317,@SKILLFLAG_SPECIAL | @SKILLFLAG_BLOODPACT_RAGE,0,13,0,0,0,0); +INSERT INTO `pet_skills` VALUES (524,164,'level_X_holy',1,12.0,2000,1000,4,317,@SKILLFLAG_SPECIAL | @SKILLFLAG_BLOODPACT_RAGE,0,13,0,0,0,0); -- Animation ID is for die roll of 1: 164-169 +INSERT INTO `pet_skills` VALUES (525,159,'raise_ii',0,18.0,2000,1000,16,0,@SKILLFLAG_SPECIAL | @SKILLFLAG_BLOODPACT_WARD,0,13,0,0,0,0); +INSERT INTO `pet_skills` VALUES (526,160,'reraise_ii',0,18.0,2000,1000,16,0,@SKILLFLAG_SPECIAL | @SKILLFLAG_BLOODPACT_WARD,0,13,0,0,0,0); +INSERT INTO `pet_skills` VALUES (527,170,'altana_s_favor',1,18.0,2000,1000,35,0,@SKILLFLAG_ASTRAL_FLOW | @SKILLFLAG_SPECIAL | @SKILLFLAG_BLOODPACT_WARD,0,13,0,0,0,0); + -- Siren INSERT INTO `pet_skills` VALUES (960,175,'clarsach_call',1,7.0,2000,1000,4,317,@SKILLFLAG_ASTRAL_FLOW | @SKILLFLAG_SPECIAL | @SKILLFLAG_BLOODPACT_RAGE,0,13,0,0,0,0); INSERT INTO `pet_skills` VALUES (961,176,'welt',0,7.0,2000,1000,4,317,@SKILLFLAG_SPECIAL | @SKILLFLAG_BLOODPACT_RAGE,0,13,0,0,0,0); diff --git a/src/map/entities/petentity.cpp b/src/map/entities/petentity.cpp index b5b25517c62..3db96bb472b 100644 --- a/src/map/entities/petentity.cpp +++ b/src/map/entities/petentity.cpp @@ -473,6 +473,12 @@ void CPetEntity::OnPetSkillFinished(CPetSkillState& state, action_t& action) uint16 msg = 0; uint16 defaultMessage = PSkill->getMsg(); + auto animationID = PSkill->getAnimationID(); + if (PSkill->getID() == 524) + { + // Cait Sith randomizes Level ? Holy die between 1 and 6 (GetRandomNumber excludes the max) + animationID = animationID + xirand::GetRandomNumber(0, 6); + } bool first{ true }; for (auto&& PTargetFound : PAI->TargetFind->m_targets) @@ -486,15 +492,13 @@ void CPetEntity::OnPetSkillFinished(CPetSkillState& state, action_t& action) list.ActionTargetID = PTargetFound->id; target.reaction = REACTION::HIT; target.speceffect = SPECEFFECT::HIT; - target.animation = PSkill->getAnimationID(); + target.animation = animationID; target.messageID = PSkill->getMsg(); // reset the skill's message back to default PSkill->setMsg(defaultMessage); int32 damage = 0; - target.animation = PSkill->getAnimationID(); - /* if (petType == PET_TYPE::AUTOMATON) // TODO: figure out Automaton { damage = luautils::OnAutomatonAbility(PTarget, this, PSkill, PMaster, &action); diff --git a/src/map/lua/lua_petskill.cpp b/src/map/lua/lua_petskill.cpp index a9e76ecf1ce..ca14333740c 100644 --- a/src/map/lua/lua_petskill.cpp +++ b/src/map/lua/lua_petskill.cpp @@ -50,6 +50,11 @@ void CLuaPetSkill::setMsg(uint16 message) m_PLuaPetSkill->setMsg(message); } +uint16 CLuaPetSkill::getAnimationID() +{ + return m_PLuaPetSkill->getAnimationID(); +} + bool CLuaPetSkill::hasMissMsg() { return m_PLuaPetSkill->hasMissMsg(); @@ -113,6 +118,7 @@ void CLuaPetSkill::Register() { SOL_USERTYPE("CPetSkill", CLuaPetSkill); SOL_REGISTER("setMsg", CLuaPetSkill::setMsg); + SOL_REGISTER("getAnimationID", CLuaPetSkill::getAnimationID); SOL_REGISTER("getMsg", CLuaPetSkill::getMsg); SOL_REGISTER("hasMissMsg", CLuaPetSkill::hasMissMsg); SOL_REGISTER("isAoE", CLuaPetSkill::isAoE); diff --git a/src/map/lua/lua_petskill.h b/src/map/lua/lua_petskill.h index c5b0309f8c2..5209d912c3d 100644 --- a/src/map/lua/lua_petskill.h +++ b/src/map/lua/lua_petskill.h @@ -50,6 +50,7 @@ class CLuaPetSkill bool isSingle(); bool hasMissMsg(); void setMsg(uint16 message); + uint16 getAnimationID(); uint16 getMsg(); uint16 getTotalTargets(); diff --git a/src/map/utils/charutils.cpp b/src/map/utils/charutils.cpp index 5f51e8c52d3..957027cff1a 100644 --- a/src/map/utils/charutils.cpp +++ b/src/map/utils/charutils.cpp @@ -2915,7 +2915,7 @@ namespace charutils } else if (PetID == PETID_CAIT_SITH) { - if (PAbility->getID() > ABILITY_SOOTHING_RUBY && PAbility->getID() <= ABILITY_MOONLIT_CHARGE) + if (PAbility->getID() > ABILITY_SOOTHING_RUBY && PAbility->getID() < ABILITY_MOONLIT_CHARGE) { addPetAbility(PChar, PAbility->getID() - ABILITY_HEALING_RUBY); }