diff --git a/scripts/commands/addalltrusts.lua b/scripts/commands/addalltrusts.lua index 79d001ca87d..1a69231417b 100644 --- a/scripts/commands/addalltrusts.lua +++ b/scripts/commands/addalltrusts.lua @@ -20,8 +20,9 @@ function onTrigger(player, target) 896, 897, 898, 899, 900, 901, 902, 903, 904, 905, 906, 907, 908, 909, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 930, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, - 971, 972, 973, 974, 975, 976, 977, 978, 979, 980, 981, 982, 983, 984, 985, 986, 987, 1004, 1005, 1006, 1007, 1008, 1009, - 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1017, 1018, 1019 + 971, 972, 973, 974, 975, 976, 977, 978, 979, 980, 981, 982, 983, 984, 985, 986, 987, 988, 989, 990, 991, 992, 993, 994, 995, + 996, 997, 998, 999, + 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1017, 1018, 1019, } -- validate target diff --git a/scripts/globals/gambits.lua b/scripts/globals/gambits.lua index 357c31402f8..f355a007b8d 100644 --- a/scripts/globals/gambits.lua +++ b/scripts/globals/gambits.lua @@ -11,11 +11,15 @@ ai = ai or {} -- Target ai.target = { - SELF = 0, - PARTY = 1, - TARGET = 2, - MASTER = 3, - TANK = 4, + SELF = 0, + PARTY = 1, + TARGET = 2, + MASTER = 3, + TANK = 4, + MELEE = 5, + RANGED = 6, + CASTER = 7, + TOP_ENMITY = 8, } ai.t = ai.target @@ -70,7 +74,7 @@ ai.select = ai.s = ai.select -- TP Move Trigger -ai.tp = +ai.tp = { ASAP = 0, RANDOM = 1, diff --git a/scripts/globals/msg.lua b/scripts/globals/msg.lua index bd55ed0c957..1ca8cc9e1dc 100644 --- a/scripts/globals/msg.lua +++ b/scripts/globals/msg.lua @@ -330,8 +330,8 @@ tpz.msg.basic = ROE_BONUS_ITEM_PLURAL = 709, -- As a special bonus for your valiant efforts, you have been awarded the following: x! -- TRUST & ALTER EGO - TRUST_NO_CAST_TRUST = 700, -- You are unable to use Trust magic at this time. - TRUST_NO_CALL_AE = 717, -- You cannot call forth alter egos here. + TRUST_NO_CAST_TRUST = 700, -- You are unable to use Trust magic at this time. + TRUST_NO_CALL_AE = 717, -- You cannot call forth alter egos here. } ------------------------------------ diff --git a/scripts/globals/spells/trust/ajido-marujido.lua b/scripts/globals/spells/trust/ajido-marujido.lua index 708000e7f10..148a63b018a 100644 --- a/scripts/globals/spells/trust/ajido-marujido.lua +++ b/scripts/globals/spells/trust/ajido-marujido.lua @@ -7,6 +7,8 @@ require("scripts/globals/status") require("scripts/globals/trust") ----------------------------------------- +local message_page_offset = 8 + function onMagicCastingCheck(caster, target, spell) return tpz.trust.canCast(caster, spell) end @@ -16,7 +18,7 @@ function onSpellCast(caster, target, spell) end function onMobSpawn(mob) - tpz.trust.teamworkMessage(mob, { + tpz.trust.teamworkMessage(mob, message_page_offset, { [tpz.magic.spell.SHANTOTTO] = tpz.trust.message_offset.TEAMWORK_1, [tpz.magic.spell.STAR_SIBYL] = tpz.trust.message_offset.TEAMWORK_2, [tpz.magic.spell.KORU_MORU] = tpz.trust.message_offset.TEAMWORK_3, @@ -38,9 +40,9 @@ function onMobSpawn(mob) end function onMobDespawn(mob) - tpz.trust.message(mob, tpz.trust.message_offset.DESPAWN) + tpz.trust.message(mob, message_page_offset, tpz.trust.message_offset.DESPAWN) end function onMobDeath(mob) - tpz.trust.message(mob, tpz.trust.message_offset.DEATH) + tpz.trust.message(mob, message_page_offset, tpz.trust.message_offset.DEATH) end diff --git a/scripts/globals/spells/trust/ayame.lua b/scripts/globals/spells/trust/ayame.lua index 46f00c47e0f..46e8fd4d07a 100644 --- a/scripts/globals/spells/trust/ayame.lua +++ b/scripts/globals/spells/trust/ayame.lua @@ -9,6 +9,8 @@ require("scripts/globals/trust") require("scripts/globals/weaponskillids") ----------------------------------------- +local message_page_offset = 4 + function onMagicCastingCheck(caster, target, spell) return tpz.trust.canCast(caster, spell, tpz.magic.spell.AYAME_UC) end @@ -18,7 +20,7 @@ function onSpellCast(caster, target, spell) end function onMobSpawn(mob) - tpz.trust.teamworkMessage(mob, { + tpz.trust.teamworkMessage(mob, message_page_offset, { [tpz.magic.spell.NAJI] = tpz.trust.message_offset.TEAMWORK_1, [tpz.magic.spell.GILGAMESH] = tpz.trust.message_offset.TEAMWORK_2, }) @@ -51,9 +53,9 @@ function onMobSpawn(mob) end function onMobDespawn(mob) - tpz.trust.message(mob, tpz.trust.message_offset.DESPAWN) + tpz.trust.message(mob, message_page_offset, tpz.trust.message_offset.DESPAWN) end function onMobDeath(mob) - tpz.trust.message(mob, tpz.trust.message_offset.DEATH) + tpz.trust.message(mob, message_page_offset, tpz.trust.message_offset.DEATH) end diff --git a/scripts/globals/spells/trust/curilla.lua b/scripts/globals/spells/trust/curilla.lua index f424bbbd1d6..a7ca6dde2ee 100644 --- a/scripts/globals/spells/trust/curilla.lua +++ b/scripts/globals/spells/trust/curilla.lua @@ -9,6 +9,8 @@ require("scripts/globals/trust") require("scripts/globals/weaponskillids") ----------------------------------------- +local message_page_offset = 6 + function onMagicCastingCheck(caster, target, spell) return tpz.trust.canCast(caster, spell) end @@ -18,7 +20,7 @@ function onSpellCast(caster, target, spell) end function onMobSpawn(mob) - tpz.trust.teamworkMessage(mob, { + tpz.trust.teamworkMessage(mob, message_page_offset, { [tpz.magic.spell.TRION] = tpz.trust.message_offset.TEAMWORK_1, [tpz.magic.spell.RAINEMARD] = tpz.trust.message_offset.TEAMWORK_2, [tpz.magic.spell.RAHAL] = tpz.trust.message_offset.TEAMWORK_3, @@ -36,9 +38,9 @@ function onMobSpawn(mob) end function onMobDespawn(mob) - tpz.trust.message(mob, tpz.trust.message_offset.DESPAWN) + tpz.trust.message(mob, message_page_offset, tpz.trust.message_offset.DESPAWN) end function onMobDeath(mob) - tpz.trust.message(mob, tpz.trust.message_offset.DEATH) + tpz.trust.message(mob, message_page_offset, tpz.trust.message_offset.DEATH) end diff --git a/scripts/globals/spells/trust/excenmille.lua b/scripts/globals/spells/trust/excenmille.lua index d983651e653..bbea91223c6 100644 --- a/scripts/globals/spells/trust/excenmille.lua +++ b/scripts/globals/spells/trust/excenmille.lua @@ -10,6 +10,8 @@ require("scripts/globals/weaponskillids") require("scripts/globals/zone") ----------------------------------------- +local message_page_offset = 3 + function onMagicCastingCheck(caster, target, spell) return tpz.trust.canCast(caster, spell, tpz.magic.spell.EXCENMILLE_S) end @@ -26,7 +28,7 @@ function onSpellCast(caster, target, spell) end function onMobSpawn(mob) - tpz.trust.teamworkMessage(mob, { + tpz.trust.teamworkMessage(mob, message_page_offset, { [tpz.magic.spell.RAHAL] = tpz.trust.message_offset.TEAMWORK_1, }) @@ -43,9 +45,9 @@ function onMobSpawn(mob) end function onMobDespawn(mob) - tpz.trust.message(mob, tpz.trust.message_offset.DESPAWN) + tpz.trust.message(mob, message_page_offset, tpz.trust.message_offset.DESPAWN) end function onMobDeath(mob) - tpz.trust.message(mob, tpz.trust.message_offset.DEATH) + tpz.trust.message(mob, message_page_offset, tpz.trust.message_offset.DEATH) end diff --git a/scripts/globals/spells/trust/iron_eater.lua b/scripts/globals/spells/trust/iron_eater.lua index 12370dc43f2..c2303e846f1 100644 --- a/scripts/globals/spells/trust/iron_eater.lua +++ b/scripts/globals/spells/trust/iron_eater.lua @@ -9,6 +9,8 @@ require("scripts/globals/trust") require("scripts/globals/weaponskillids") ----------------------------------------- +local message_page_offset = 21 + function onMagicCastingCheck(caster, target, spell) return tpz.trust.canCast(caster, spell) end @@ -18,7 +20,7 @@ function onSpellCast(caster, target, spell) end function onMobSpawn(mob) - tpz.trust.teamworkMessage(mob, { + tpz.trust.teamworkMessage(mob, message_page_offset, { [tpz.magic.spell.NAJI] = tpz.trust.message_offset.TEAMWORK_1, }) @@ -27,9 +29,9 @@ function onMobSpawn(mob) end function onMobDespawn(mob) - tpz.trust.message(mob, tpz.trust.message_offset.DESPAWN) + tpz.trust.message(mob, message_page_offset, tpz.trust.message_offset.DESPAWN) end function onMobDeath(mob) - tpz.trust.message(mob, tpz.trust.message_offset.DEATH) + tpz.trust.message(mob, message_page_offset, tpz.trust.message_offset.DEATH) end diff --git a/scripts/globals/spells/trust/koru-moru.lua b/scripts/globals/spells/trust/koru-moru.lua index 38d4584fa8f..e76673de81a 100644 --- a/scripts/globals/spells/trust/koru-moru.lua +++ b/scripts/globals/spells/trust/koru-moru.lua @@ -1,9 +1,16 @@ ----------------------------------------- -- Trust: Koru-Moru ----------------------------------------- +require("scripts/globals/ability") +require("scripts/globals/gambits") +require("scripts/globals/magic") +require("scripts/globals/status") require("scripts/globals/trust") +require("scripts/globals/utils") ----------------------------------------- +local message_page_offset = 57 + function onMagicCastingCheck(caster, target, spell) return tpz.trust.canCast(caster, spell) end @@ -11,3 +18,41 @@ end function onSpellCast(caster, target, spell) return tpz.trust.spawn(caster, spell) end + +function onMobSpawn(mob) + tpz.trust.teamworkMessage(mob, message_page_offset, { + [tpz.magic.spell.SHANTOTTO] = tpz.trust.message_offset.TEAMWORK_1, + [tpz.magic.spell.SHANTOTTO_II] = tpz.trust.message_offset.TEAMWORK_1, + [tpz.magic.spell.AJIDO_MARUJIDO] = tpz.trust.message_offset.TEAMWORK_2, + }) + + mob:addSimpleGambit(ai.t.SELF, ai.c.MPP_LT, 5, + ai.r.JA, ai.s.SPECIFIC, tpz.ja.CONVERT) + + mob:addSimpleGambit(ai.t.PARTY, ai.c.HPP_LT, 50, ai.r.MA, ai.s.HIGHEST, tpz.magic.spellFamily.CURE) + + mob:addSimpleGambit(ai.t.MELEE, ai.c.NOT_STATUS, tpz.effect.HASTE, ai.r.MA, ai.s.HIGHEST, tpz.magic.spellFamily.HASTE) + mob:addSimpleGambit(ai.t.CASTER, ai.c.NOT_STATUS, tpz.effect.REFRESH, ai.r.MA, ai.s.HIGHEST, tpz.magic.spellFamily.REFRESH) + mob:addSimpleGambit(ai.t.RANGED, ai.c.NOT_STATUS, tpz.effect.FLURRY, ai.r.MA, ai.s.HIGHEST, tpz.magic.spellFamily.FLURRY) + mob:addSimpleGambit(ai.t.TOP_ENMITY, ai.c.NOT_STATUS, tpz.effect.PHALANX, ai.r.MA, ai.s.HIGHEST, tpz.magic.spellFamily.PHALANX) + + mob:addSimpleGambit(ai.t.TARGET, ai.c.STATUS_FLAG, tpz.effectFlag.DISPELABLE, ai.r.MA, ai.s.SPECIFIC, tpz.magic.spell.DISPEL) + + mob:addSimpleGambit(ai.t.TARGET, ai.c.NOT_STATUS, tpz.effect.DIA, ai.r.MA, ai.s.HIGHEST, tpz.magic.spellFamily.DIA, 60) + mob:addSimpleGambit(ai.t.TARGET, ai.c.NOT_STATUS, tpz.effect.SLOW, ai.r.MA, ai.s.HIGHEST, tpz.magic.spellFamily.SLOW, 60) + mob:addSimpleGambit(ai.t.TARGET, ai.c.NOT_STATUS, tpz.effect.EVASION_DOWN, ai.r.MA, ai.s.HIGHEST, tpz.magic.spellFamily.DISTRACT, 60) + mob:addSimpleGambit(ai.t.TARGET, ai.c.NOT_STATUS, tpz.effect.DIA, ai.r.MA, ai.s.HIGHEST, tpz.magic.spellFamily.DIA, 60) + + mob:addSimpleGambit(ai.t.PARTY, ai.c.NOT_STATUS, tpz.effect.PROTECT, ai.r.MA, ai.s.HIGHEST, tpz.magic.spellFamily.PROTECT) + mob:addSimpleGambit(ai.t.PARTY, ai.c.NOT_STATUS, tpz.effect.SHELL, ai.r.MA, ai.s.HIGHEST, tpz.magic.spellFamily.SHELL) + + mob:SetAutoAttackEnabled(false) +end + +function onMobDespawn(mob) + tpz.trust.message(mob, message_page_offset, tpz.trust.message_offset.DESPAWN) +end + +function onMobDeath(mob) + tpz.trust.message(mob, message_page_offset, tpz.trust.message_offset.DEATH) +end diff --git a/scripts/globals/spells/trust/kupipi.lua b/scripts/globals/spells/trust/kupipi.lua index d3eb111b592..a5c78fce27b 100644 --- a/scripts/globals/spells/trust/kupipi.lua +++ b/scripts/globals/spells/trust/kupipi.lua @@ -10,6 +10,7 @@ require("scripts/globals/weaponskillids") require("scripts/globals/zone") ----------------------------------------- +local message_page_offset = 2 function onMagicCastingCheck(caster, target, spell) return tpz.trust.canCast(caster, spell) @@ -27,7 +28,7 @@ function onSpellCast(caster, target, spell) end function onMobSpawn(mob) - tpz.trust.teamworkMessage(mob, { + tpz.trust.teamworkMessage(mob, message_page_offset, { [tpz.magic.spell.SHANTOTTO] = tpz.trust.message_offset.TEAMWORK_1, [tpz.magic.spell.STAR_SIBYL] = tpz.trust.message_offset.TEAMWORK_2, }) @@ -61,9 +62,9 @@ function onMobSpawn(mob) end function onMobDespawn(mob) - tpz.trust.message(mob, tpz.trust.message_offset.DESPAWN) + tpz.trust.message(mob, message_page_offset, tpz.trust.message_offset.DESPAWN) end function onMobDeath(mob) - tpz.trust.message(mob, tpz.trust.message_offset.DEATH) + tpz.trust.message(mob, message_page_offset, tpz.trust.message_offset.DEATH) end diff --git a/scripts/globals/spells/trust/maat.lua b/scripts/globals/spells/trust/maat.lua index 8e8d5d37bb7..efb8e2af8dd 100644 --- a/scripts/globals/spells/trust/maat.lua +++ b/scripts/globals/spells/trust/maat.lua @@ -7,6 +7,8 @@ require("scripts/globals/status") require("scripts/globals/trust") ----------------------------------------- +local message_page_offset = 37 + function onMagicCastingCheck(caster, target, spell) return tpz.trust.canCast(caster, spell, 1006) end @@ -16,7 +18,7 @@ function onSpellCast(caster, target, spell) end function onMobSpawn(mob) - tpz.trust.message(mob, tpz.trust.message_offset.SPAWN) + tpz.trust.message(mob, message_page_offset, tpz.trust.message_offset.SPAWN) -- On cooldown mob:addSimpleGambit(ai.t.SELF, ai.c.ALWAYS, 0, @@ -24,9 +26,9 @@ function onMobSpawn(mob) end function onMobDespawn(mob) - tpz.trust.message(mob, tpz.trust.message_offset.DESPAWN) + tpz.trust.message(mob, message_page_offset, tpz.trust.message_offset.DESPAWN) end function onMobDeath(mob) - tpz.trust.message(mob, tpz.trust.message_offset.DEATH) + tpz.trust.message(mob, message_page_offset, tpz.trust.message_offset.DEATH) end diff --git a/scripts/globals/spells/trust/monberaux.lua b/scripts/globals/spells/trust/monberaux.lua index 7dc96b8aba4..df166de20c0 100644 --- a/scripts/globals/spells/trust/monberaux.lua +++ b/scripts/globals/spells/trust/monberaux.lua @@ -4,6 +4,8 @@ require("scripts/globals/trust") ----------------------------------------- +local message_page_offset = 120 + function onMagicCastingCheck(caster, target, spell) return tpz.trust.canCast(caster, spell) end @@ -11,3 +13,15 @@ end function onSpellCast(caster, target, spell) return tpz.trust.spawn(caster, spell) end + +function onMobSpawn(mob) + tpz.trust.message(mob, message_page_offset, tpz.trust.message_offset.SPAWN) +end + +function onMobDespawn(mob) + tpz.trust.message(mob, message_page_offset, tpz.trust.message_offset.DESPAWN) +end + +function onMobDeath(mob) + tpz.trust.message(mob, message_page_offset, tpz.trust.message_offset.DEATH) +end diff --git a/scripts/globals/spells/trust/naji.lua b/scripts/globals/spells/trust/naji.lua index b5cbb0fc467..5567a3e112d 100644 --- a/scripts/globals/spells/trust/naji.lua +++ b/scripts/globals/spells/trust/naji.lua @@ -10,6 +10,8 @@ require("scripts/globals/weaponskillids") require("scripts/globals/zone") ----------------------------------------- +local message_page_offset = 1 + function onMagicCastingCheck(caster, target, spell) return tpz.trust.canCast(caster, spell) end @@ -26,7 +28,7 @@ function onSpellCast(caster, target, spell) end function onMobSpawn(mob) - tpz.trust.teamworkMessage(mob, { + tpz.trust.teamworkMessage(mob, message_page_offset, { [tpz.magic.spell.AYAME] = tpz.trust.message_offset.TEAMWORK_1, }) @@ -35,9 +37,9 @@ function onMobSpawn(mob) end function onMobDespawn(mob) - tpz.trust.message(mob, tpz.trust.message_offset.DESPAWN) + tpz.trust.message(mob, message_page_offset, tpz.trust.message_offset.DESPAWN) end function onMobDeath(mob) - tpz.trust.message(mob, tpz.trust.message_offset.DEATH) + tpz.trust.message(mob, message_page_offset, tpz.trust.message_offset.DEATH) end diff --git a/scripts/globals/spells/trust/nanaa_mihgo.lua b/scripts/globals/spells/trust/nanaa_mihgo.lua index 9e6608a94ff..03fe72254de 100644 --- a/scripts/globals/spells/trust/nanaa_mihgo.lua +++ b/scripts/globals/spells/trust/nanaa_mihgo.lua @@ -8,6 +8,8 @@ require("scripts/globals/trust") require("scripts/globals/weaponskillids") ----------------------------------------- +local message_page_offset = 5 + function onMagicCastingCheck(caster, target, spell) return tpz.trust.canCast(caster, spell) end @@ -17,7 +19,7 @@ function onSpellCast(caster, target, spell) end function onMobSpawn(mob) - tpz.trust.teamworkMessage(mob, { + tpz.trust.teamworkMessage(mob, message_page_offset, { [tpz.magic.spell.ROMAA_MIHGO] = tpz.trust.message_offset.TEAMWORK_1, }) @@ -28,9 +30,9 @@ function onMobSpawn(mob) end function onMobDespawn(mob) - tpz.trust.message(mob, tpz.trust.message_offset.DESPAWN) + tpz.trust.message(mob, message_page_offset, tpz.trust.message_offset.DESPAWN) end function onMobDeath(mob) - tpz.trust.message(mob, tpz.trust.message_offset.DEATH) + tpz.trust.message(mob, message_page_offset, tpz.trust.message_offset.DEATH) end diff --git a/scripts/globals/spells/trust/prishe.lua b/scripts/globals/spells/trust/prishe.lua index 41035a46798..650158ca0fb 100644 --- a/scripts/globals/spells/trust/prishe.lua +++ b/scripts/globals/spells/trust/prishe.lua @@ -6,6 +6,8 @@ require("scripts/globals/magic") require("scripts/globals/trust") ----------------------------------------- +local message_page_offset = 17 + function onMagicCastingCheck(caster, target, spell) return tpz.trust.canCast(caster, spell, 1011) end @@ -15,7 +17,7 @@ function onSpellCast(caster, target, spell) end function onMobSpawn(mob) - tpz.trust.teamworkMessage(mob, { + tpz.trust.teamworkMessage(mob, message_page_offset, { [tpz.magic.spell.ULMIA] = tpz.trust.message_offset.TEAMWORK_1, [tpz.magic.spell.CHERUKIKI] = tpz.trust.message_offset.TEAMWORK_2, [tpz.magic.spell.KUKKI_CHEBUKKI] = tpz.trust.message_offset.TEAMWORK_3, @@ -27,9 +29,9 @@ function onMobSpawn(mob) end function onMobDespawn(mob) - tpz.trust.message(mob, tpz.trust.message_offset.DESPAWN) + tpz.trust.message(mob, message_page_offset, tpz.trust.message_offset.DESPAWN) end function onMobDeath(mob) - tpz.trust.message(mob, tpz.trust.message_offset.DEATH) + tpz.trust.message(mob, message_page_offset, tpz.trust.message_offset.DEATH) end diff --git a/scripts/globals/spells/trust/sakura.lua b/scripts/globals/spells/trust/sakura.lua index bcdd27235ed..b86cc8b7e5f 100644 --- a/scripts/globals/spells/trust/sakura.lua +++ b/scripts/globals/spells/trust/sakura.lua @@ -1,9 +1,13 @@ ----------------------------------------- -- Trust: Sakura ----------------------------------------- +require("scripts/globals/magic") +require("scripts/globals/status") require("scripts/globals/trust") ----------------------------------------- +local message_page_offset = 31 + function onMagicCastingCheck(caster, target, spell) return tpz.trust.canCast(caster, spell) end @@ -11,3 +15,34 @@ end function onSpellCast(caster, target, spell) return tpz.trust.spawn(caster, spell) end + +function onMobSpawn(mob) + tpz.trust.message(mob, message_page_offset, tpz.trust.message_offset.SPAWN) + + local mlvl = mob:getMainLvl() + local tick_amount + if mlvl == 99 then + tick_amount = 6 + elseif mlvl < 99 then + tick_amount = 5 + elseif mlvl <= 87 then + tick_amount = 4 + elseif mlvl <= 73 then + tick_amount = 3 + elseif mlvl <= 51 then + tick_amount = 2 + else + tick_amount = 1 + end + + mob:addStatusEffectEx(tpz.effect.COLURE_ACTIVE, tpz.effect.COLURE_ACTIVE, 6, 3, 0, tpz.effect.GEO_REGEN, tick_amount, tpz.auraTarget.ALLIES, tpz.effectFlag.AURA) + mob:SetAutoAttackEnabled(false) +end + +function onMobDespawn(mob) + tpz.trust.message(mob, message_page_offset, tpz.trust.message_offset.DESPAWN) +end + +function onMobDeath(mob) + tpz.trust.message(mob, message_page_offset, tpz.trust.message_offset.DEATH) +end diff --git a/scripts/globals/spells/trust/shantotto.lua b/scripts/globals/spells/trust/shantotto.lua index c7cd16c2235..201985eb26c 100644 --- a/scripts/globals/spells/trust/shantotto.lua +++ b/scripts/globals/spells/trust/shantotto.lua @@ -6,6 +6,8 @@ require("scripts/globals/magic") require("scripts/globals/trust") ----------------------------------------- +local message_page_offset = 0 + function onMagicCastingCheck(caster, target, spell) return tpz.trust.canCast(caster, spell, tpz.magic.spell.SHANTOTTO_II) end @@ -15,7 +17,7 @@ function onSpellCast(caster, target, spell) end function onMobSpawn(mob) - tpz.trust.teamworkMessage(mob, { + tpz.trust.teamworkMessage(mob, message_page_offset, { [tpz.magic.spell.AJIDO_MARUJIDO] = tpz.trust.message_offset.TEAMWORK_1, [tpz.magic.spell.STAR_SIBYL] = tpz.trust.message_offset.TEAMWORK_2, [tpz.magic.spell.KORU_MORU] = tpz.trust.message_offset.TEAMWORK_3, @@ -52,9 +54,9 @@ function onMobSpawn(mob) end function onMobDespawn(mob) - tpz.trust.message(mob, tpz.trust.message_offset.DESPAWN) + tpz.trust.message(mob, message_page_offset, tpz.trust.message_offset.DESPAWN) end function onMobDeath(mob) - tpz.trust.message(mob, tpz.trust.message_offset.DEATH) + tpz.trust.message(mob, message_page_offset, tpz.trust.message_offset.DEATH) end diff --git a/scripts/globals/spells/trust/shantotto_ii.lua b/scripts/globals/spells/trust/shantotto_ii.lua index 1254620ae80..75745228b35 100644 --- a/scripts/globals/spells/trust/shantotto_ii.lua +++ b/scripts/globals/spells/trust/shantotto_ii.lua @@ -6,6 +6,8 @@ require("scripts/globals/magic") require("scripts/globals/trust") ----------------------------------------- +local message_page_offset = 112 + function onMagicCastingCheck(caster, target, spell) return tpz.trust.canCast(caster, spell, tpz.magic.spell.SHANTOTTO) end @@ -15,7 +17,7 @@ function onSpellCast(caster, target, spell) end function onMobSpawn(mob) - -- tpz.trust.message(mob, tpz.trust.message_offset.SPAWN) + tpz.trust.message(mob, message_page_offset, tpz.trust.message_offset.SPAWN) mob:addSimpleGambit(ai.t.TARGET, ai.c.MB_AVAILABLE, 0, ai.r.MA, ai.s.MB_ELEMENT, tpz.magic.spellFamily.NONE) mob:addSimpleGambit(ai.t.TARGET, ai.c.NOT_SC_AVAILABLE, 0, ai.r.MA, ai.s.HIGHEST, tpz.magic.spellFamily.NONE, 30) @@ -28,9 +30,9 @@ function onMobSpawn(mob) end function onMobDespawn(mob) - -- tpz.trust.message(mob, tpz.trust.message_offset.DESPAWN) + tpz.trust.message(mob, message_page_offset, tpz.trust.message_offset.DESPAWN) end function onMobDeath(mob) - -- tpz.trust.message(mob, tpz.trust.message_offset.DEATH) + tpz.trust.message(mob, message_page_offset, tpz.trust.message_offset.DEATH) end diff --git a/scripts/globals/spells/trust/trion.lua b/scripts/globals/spells/trust/trion.lua index fb1361167b2..aa08f84929c 100644 --- a/scripts/globals/spells/trust/trion.lua +++ b/scripts/globals/spells/trust/trion.lua @@ -9,6 +9,8 @@ require("scripts/globals/trust") require("scripts/globals/weaponskillids") ----------------------------------------- +local message_page_offset = 9 + function onMagicCastingCheck(caster, target, spell) return tpz.trust.canCast(caster, spell) end @@ -18,7 +20,7 @@ function onSpellCast(caster, target, spell) end function onMobSpawn(mob) - tpz.trust.teamworkMessage(mob, { + tpz.trust.teamworkMessage(mob, message_page_offset, { [tpz.magic.spell.CURILLA] = tpz.trust.message_offset.TEAMWORK_1, [tpz.magic.spell.RAHAL] = tpz.trust.message_offset.TEAMWORK_2, [tpz.magic.spell.HALVER] = tpz.trust.message_offset.TEAMWORK_3, @@ -35,9 +37,9 @@ function onMobSpawn(mob) end function onMobDespawn(mob) - tpz.trust.message(mob, tpz.trust.message_offset.DESPAWN) + tpz.trust.message(mob, message_page_offset, tpz.trust.message_offset.DESPAWN) end function onMobDeath(mob) - tpz.trust.message(mob, tpz.trust.message_offset.DEATH) + tpz.trust.message(mob, message_page_offset, tpz.trust.message_offset.DEATH) end diff --git a/scripts/globals/spells/trust/volker.lua b/scripts/globals/spells/trust/volker.lua index e33d94c1ee7..c5c70e5c491 100644 --- a/scripts/globals/spells/trust/volker.lua +++ b/scripts/globals/spells/trust/volker.lua @@ -9,6 +9,8 @@ require("scripts/globals/trust") require("scripts/globals/weaponskillids") ----------------------------------------- +local message_page_offset = 7 + function onMagicCastingCheck(caster, target, spell) return tpz.trust.canCast(caster, spell) end @@ -18,7 +20,7 @@ function onSpellCast(caster, target, spell) end function onMobSpawn(mob) - tpz.trust.teamworkMessage(mob, { + tpz.trust.teamworkMessage(mob, message_page_offset, { [tpz.magic.spell.NAJI] = tpz.trust.message_offset.TEAMWORK_1, [tpz.magic.spell.CID] = tpz.trust.message_offset.TEAMWORK_2, [tpz.magic.spell.KLARA] = tpz.trust.message_offset.TEAMWORK_3, @@ -29,9 +31,9 @@ function onMobSpawn(mob) end function onMobDespawn(mob) - tpz.trust.message(mob, tpz.trust.message_offset.DESPAWN) + tpz.trust.message(mob, message_page_offset, tpz.trust.message_offset.DESPAWN) end function onMobDeath(mob) - tpz.trust.message(mob, tpz.trust.message_offset.DEATH) + tpz.trust.message(mob, message_page_offset, tpz.trust.message_offset.DEATH) end diff --git a/scripts/globals/spells/trust/zeid_ii.lua b/scripts/globals/spells/trust/zeid_ii.lua index cb8b57d525e..3e29ac56e89 100644 --- a/scripts/globals/spells/trust/zeid_ii.lua +++ b/scripts/globals/spells/trust/zeid_ii.lua @@ -9,6 +9,8 @@ require("scripts/globals/trust") require("scripts/globals/weaponskillids") ----------------------------------------- +local message_page_offset = 86 + function onMagicCastingCheck(caster, target, spell) return tpz.trust.canCast(caster, spell, 906) end @@ -18,7 +20,7 @@ function onSpellCast(caster, target, spell) end function onMobSpawn(mob) - tpz.trust.message(mob, tpz.trust.message_offset.SPAWN) + tpz.trust.message(mob, message_page_offset, tpz.trust.message_offset.SPAWN) -- Stun all the things! mob:addSimpleGambit(ai.t.TARGET, ai.c.READYING_WS, 0, @@ -44,9 +46,9 @@ function onMobSpawn(mob) end function onMobDespawn(mob) - tpz.trust.message(mob, tpz.trust.message_offset.DESPAWN) + tpz.trust.message(mob, message_page_offset, tpz.trust.message_offset.DESPAWN) end function onMobDeath(mob) - tpz.trust.message(mob, tpz.trust.message_offset.DEATH) + tpz.trust.message(mob, message_page_offset, tpz.trust.message_offset.DEATH) end diff --git a/scripts/globals/trust.lua b/scripts/globals/trust.lua index 75e683b0b4a..ffff7d6bf75 100644 --- a/scripts/globals/trust.lua +++ b/scripts/globals/trust.lua @@ -24,6 +24,8 @@ tpz.trust.message_offset = SPECIAL_MOVE_1 = 18, } +local MAX_MESSAGE_PAGE = 120 + local rovKIBattlefieldIDs = set{ 5, -- Shattering Stars (WAR LB5) 6, -- Shattering Stars (BLM LB5) @@ -47,7 +49,7 @@ local rovKIBattlefieldIDs = set{ 1154, -- The Beast Within (BLU LB5) -- TODO: GEO LB5 -- TODO: RUN LB5 -} +} tpz.trust.canCast = function(caster, spell, not_allowed_trust_ids) -- Trusts not allowed in an alliance @@ -79,7 +81,7 @@ tpz.trust.canCast = function(caster, spell, not_allowed_trust_ids) caster:messageSystem(tpz.msg.system.TRUST_DELAY_NEW_PARTY_MEMBER) return -1 end - + -- Trusts cannot be summoned if you have hate if caster:hasEnmity() then caster:messageSystem(tpz.msg.system.TRUST_NO_ENMITY) @@ -147,12 +149,20 @@ tpz.trust.spawn = function(caster, spell) return 0 end -tpz.trust.message = function(mob, message_offset) - local trust_offset = tpz.msg.system.GLOBAL_TRUST_OFFSET + (mob:getTrustID() - 896) * 100 +-- page_offset is: (summon_message_id - 1) / 100 +-- Example: Shantotto II summon message ID: 11201 +-- page_offset: (11201 - 1) / 100 = 112 +tpz.trust.message = function(mob, page_offset, message_offset) + + if page_offset > MAX_MESSAGE_PAGE then + return + end + + local trust_offset = tpz.msg.system.GLOBAL_TRUST_OFFSET + (page_offset * 100) mob:trustPartyMessage(trust_offset + message_offset) end -tpz.trust.teamworkMessage = function(mob, teamwork_messages) +tpz.trust.teamworkMessage = function(mob, page_offset, teamwork_messages) local messages = {} local master = mob:getMaster() @@ -168,16 +178,16 @@ tpz.trust.teamworkMessage = function(mob, teamwork_messages) end if table.getn(messages) > 0 then - tpz.trust.message(mob, messages[math.random(#messages)]) + tpz.trust.message(mob, page_offset, messages[math.random(#messages)]) else -- Defaults to regular spawn message - tpz.trust.message(mob, tpz.trust.message_offset.SPAWN) + tpz.trust.message(mob, page_offset, tpz.trust.message_offset.SPAWN) end end -- For debugging and lining up teamwork messages -tpz.trust.dumpMessages = function(mob) +tpz.trust.dumpMessages = function(mob, page_offset) for i=0, 20 do - tpz.trust.message(mob, i) + tpz.trust.message(mob, page_offset, i) end end diff --git a/sql/mob_pools.sql b/sql/mob_pools.sql index baff7bd4d4d..a03c9fee1b8 100644 --- a/sql/mob_pools.sql +++ b/sql/mob_pools.sql @@ -5954,25 +5954,25 @@ INSERT INTO `mob_pools` VALUES (5893,'Gloombound_Lurker','Gloombound_Lurker',221 INSERT INTO `mob_pools` VALUES (5894,'Lesath','Lesath',217,0x00001C0100000000000000000000000000000000,1,1,7,280,100,0,1,0,1,2,7,0,238,141,0,0,0,1,0,370); INSERT INTO `mob_pools` VALUES (5895,'Donggu','Donggu',116,0x0000780100000000000000000000000000000000,1,1,11,240,100,0,0,0,1,2,7,0,0,133,0,0,0,1,0,116); -- Trusts -INSERT INTO `mob_pools` VALUES (5896,'shantotto','Shantotto',153,0x0000B80B00000000000000000000000000000000,4,0,2,240,40,0,2,0,0,0,0,32,0,3,0,0,308,1,0,1011); +INSERT INTO `mob_pools` VALUES (5896,'shantotto','Shantotto',153,0x0000B80B00000000000000000000000000000000,4,0,2,240,40,1,2,0,0,0,0,32,0,3,0,0,308,1,0,1011); INSERT INTO `mob_pools` VALUES (5897,'naji','Naji',149,0x0000B90B00000000000000000000000000000000,1,0,2,240,100,0,2,0,0,0,0,32,0,3,0,0,309,1,0,1012); -INSERT INTO `mob_pools` VALUES (5898,'kupipi','Kupipi',153,0x0000BA0B00000000000000000000000000000000,3,0,11,230,40,2,0,0,0,0,0,32,0,3,0,0,310,1,0,1013); +INSERT INTO `mob_pools` VALUES (5898,'kupipi','Kupipi',153,0x0000BA0B00000000000000000000000000000000,3,0,11,230,40,1,0,0,0,0,0,32,0,3,0,0,310,1,0,1013); INSERT INTO `mob_pools` VALUES (5899,'excenmille','Excenmille',145,0x0000BB0B00000000000000000000000000000000,7,0,8,390,150,0,0,0,0,0,0,32,0,3,0,0,311,1,0,1014); INSERT INTO `mob_pools` VALUES (5900,'ayame','Ayame',149,0x0000BC0B00000000000000000000000000000000,12,0,10,440,150,0,0,0,0,0,0,32,0,3,0,0,312,1,0,1015); INSERT INTO `mob_pools` VALUES (5901,'nanaa_mihgo','NanaaMihgo',151,0x0000BD0B00000000000000000000000000000000,6,0,2,190,60,0,0,0,0,0,0,32,0,3,0,0,313,1,0,1016); INSERT INTO `mob_pools` VALUES (5902,'curilla','Curilla',145,0x0000BE0B00000000000000000000000000000000,7,0,3,240,100,0,0,0,0,0,0,32,0,3,0,0,314,1,0,1017); INSERT INTO `mob_pools` VALUES (5903,'volker','Volker',149,0x0000BF0B00000000000000000000000000000000,1,0,3,240,100,0,0,0,0,0,0,32,0,3,0,0,315,1,0,1018); -INSERT INTO `mob_pools` VALUES (5904,'ajido-marujido','Ajido-Marujido',153,0x0000C00B00000000000000000000000000000000,4,5,1,400,40,0,0,0,0,0,0,32,0,3,0,0,316,1,0,1019); +INSERT INTO `mob_pools` VALUES (5904,'ajido-marujido','Ajido-Marujido',153,0x0000C00B00000000000000000000000000000000,4,5,1,400,40,1,0,0,0,0,0,32,0,3,0,0,316,1,0,1019); INSERT INTO `mob_pools` VALUES (5905,'trion','Trion',145,0x0000C10B00000000000000000000000000000000,7,1,3,240,100,0,0,0,0,0,0,32,0,3,0,0,317,1,0,1020); INSERT INTO `mob_pools` VALUES (5906,'zeid','Zeid',146,0x0000C20B00000000000000000000000000000000,8,0,3,240,100,0,0,0,0,0,0,32,0,3,0,0,318,1,0,1021); INSERT INTO `mob_pools` VALUES (5907,'lion','Lion',149,0x0000C30B00000000000000000000000000000000,6,0,3,240,100,0,0,0,0,0,0,32,0,3,0,0,319,1,0,1022); INSERT INTO `mob_pools` VALUES (5908,'tenzen','Tenzen',149,0x0000C40B00000000000000000000000000000000,12,0,3,240,100,0,0,0,0,0,0,32,0,3,0,0,320,1,0,1023); INSERT INTO `mob_pools` VALUES (5909,'mihli_aliapoh','MihliAliapoh',151,0x0000C50B00000000000000000000000000000000,3,0,3,240,100,0,0,0,0,0,0,32,0,3,0,0,321,1,0,1024); INSERT INTO `mob_pools` VALUES (5910,'valaineral','Valaineral',145,0x0000C60B00000000000000000000000000000000,7,1,3,240,100,0,0,0,0,0,0,32,0,3,0,0,322,1,0,1025); -INSERT INTO `mob_pools` VALUES (5911,'joachim','Joachim',149,0x0000C70B00000000000000000000000000000000,10,3,3,240,100,0,0,0,0,0,0,32,0,3,0,0,323,1,0,1026); +INSERT INTO `mob_pools` VALUES (5911,'joachim','Joachim',149,0x0000C70B00000000000000000000000000000000,10,3,3,240,100,2,0,0,0,0,0,32,0,3,0,0,323,1,0,1026); INSERT INTO `mob_pools` VALUES (5912,'naja_salaheem','NajaSalaheem',151,0x0000C80B00000000000000000000000000000000,2,1,3,240,100,0,0,0,0,0,0,32,0,3,0,0,324,1,0,1027); INSERT INTO `mob_pools` VALUES (5913,'prishe','Prishe',145,0x0000C90B00000000000000000000000000000000,2,3,3,240,100,0,0,0,0,0,0,32,0,3,0,0,325,1,0,1028); -INSERT INTO `mob_pools` VALUES (5914,'ulmia','Ulmia',145,0x0000CA0B00000000000000000000000000000000,10,0,3,240,100,0,0,0,0,0,0,32,0,3,0,0,326,1,0,1029); +INSERT INTO `mob_pools` VALUES (5914,'ulmia','Ulmia',145,0x0000CA0B00000000000000000000000000000000,10,0,3,240,100,2,0,0,0,0,0,32,0,3,0,0,326,1,0,1029); INSERT INTO `mob_pools` VALUES (5915,'shikaree_z','ShikareeZ',151,0x0000CB0B00000000000000000000000000000000,14,3,3,240,100,0,0,0,0,0,0,32,0,3,0,0,327,1,0,1030); INSERT INTO `mob_pools` VALUES (5916,'cherukiki','Cherukiki',153,0x0000CC0B00000000000000000000000000000000,3,0,3,240,100,0,0,0,0,0,0,32,0,3,0,0,328,1,0,1031); INSERT INTO `mob_pools` VALUES (5917,'iron_eater','IronEater',146,0x0000CD0B00000000000000000000000000000000,1,0,3,240,150,0,0,0,0,0,0,32,0,3,0,0,329,1,0,1032); @@ -5998,7 +5998,7 @@ INSERT INTO `mob_pools` VALUES (5936,'karaha-baruha','Karaha-Baruha',153,0x0000E INSERT INTO `mob_pools` VALUES (5937,'cid','Cid',149,0x0000E10B00000000000000000000000000000000,1,0,3,240,100,0,0,0,0,0,0,32,0,3,0,0,349,1,0,1052); INSERT INTO `mob_pools` VALUES (5938,'gilgamesh','Gilgamesh',149,0x0000E20B00000000000000000000000000000000,12,0,3,240,100,0,0,0,0,0,0,32,0,3,0,0,350,1,0,1053); INSERT INTO `mob_pools` VALUES (5939,'areuhat','Areuhat',145,0x0000E30B00000000000000000000000000000000,1,0,3,240,100,0,0,0,0,0,0,32,0,3,0,0,351,1,0,1054); -INSERT INTO `mob_pools` VALUES (5940,'semih_lafihna','SemihLafihna',151,0x0000E40B00000000000000000000000000000000,11,0,3,240,100,0,0,0,0,0,0,32,0,3,0,0,352,1,0,1055); +INSERT INTO `mob_pools` VALUES (5940,'semih_lafihna','SemihLafihna',151,0x0000E40B00000000000000000000000000000000,11,0,3,240,100,3,0,0,0,0,0,32,0,3,0,0,352,1,0,1055); INSERT INTO `mob_pools` VALUES (5941,'elivira','Elivira',149,0x0000E50B00000000000000000000000000000000,11,1,3,240,100,0,0,0,0,0,0,32,0,3,0,0,353,1,0,1056); INSERT INTO `mob_pools` VALUES (5942,'noillurie','Noillurie',145,0x0000E60B00000000000000000000000000000000,12,7,3,240,100,0,0,0,0,0,0,32,0,3,0,0,354,1,0,1057); INSERT INTO `mob_pools` VALUES (5943,'lhu_mhakaracca','LhuMhakaracca',151,0x0000E70B00000000000000000000000000000000,9,1,3,240,100,0,0,0,0,0,0,32,0,3,0,0,355,1,0,1058); @@ -6010,7 +6010,7 @@ INSERT INTO `mob_pools` VALUES (5948,'klara','Klara',149,0x0000ED0B0000000000000 INSERT INTO `mob_pools` VALUES (5949,'romaa_mihgo','RomaaMihgo',151,0x0000EE0B00000000000000000000000000000000,6,1,3,240,100,0,0,0,0,0,0,32,0,3,0,0,361,1,0,1064); INSERT INTO `mob_pools` VALUES (5950,'kuyin_hathdenna','KuyinHathdenna',151,0x0000EF0B00000000000000000000000000000000,21,0,3,240,100,0,0,0,0,0,0,32,0,3,0,0,362,1,0,1065); INSERT INTO `mob_pools` VALUES (5951,'rahal','Rahal',145,0x0000F00B00000000000000000000000000000000,7,1,3,240,100,0,0,0,0,0,0,32,0,3,0,0,363,1,0,1066); -INSERT INTO `mob_pools` VALUES (5952,'koru-moru','Koru-Moru',153,0x0000F10B00000000000000000000000000000000,5,0,3,240,100,0,0,0,0,0,0,32,0,3,0,0,364,1,0,1067); +INSERT INTO `mob_pools` VALUES (5952,'koru-moru','Koru-Moru',153,0x0000F10B00000000000000000000000000000000,5,0,3,240,100,1,0,0,0,0,0,32,0,3,0,0,364,1,0,1067); INSERT INTO `mob_pools` VALUES (5953,'pieuje_uc','Pieuje',145,0x0000F20B00000000000000000000000000000000,3,0,3,240,100,0,0,0,0,0,0,32,0,3,0,0,365,1,0,1068); INSERT INTO `mob_pools` VALUES (5954,'i_shield_uc','InvincibleShld',146,0x0000F40B00000000000000000000000000000000,1,2,3,240,100,0,0,0,0,0,0,32,0,3,0,0,367,1,0,1069); INSERT INTO `mob_pools` VALUES (5955,'apururu_uc','Apururu',153,0x0000F50B00000000000000000000000000000000,3,5,3,240,100,0,0,0,0,0,0,32,0,3,0,0,368,1,0,1070); @@ -6077,7 +6077,7 @@ INSERT INTO `mob_pools` VALUES (6015,'mumor_ii','Mumor',149,0x0000200C0000000000 INSERT INTO `mob_pools` VALUES (6016,'ingrid_ii','Ingrid',149,0x00001E0C00000000000000000000000000000000,3,0,3,240,100,0,0,0,0,0,0,32,0,3,0,0,425,1,0,1131); INSERT INTO `mob_pools` VALUES (6017,'arciela_ii','Arciela',149,0x00000D0C00000000000000000000000000000000,5,0,3,240,100,0,0,0,0,0,0,32,0,3,0,0,426,1,0,1132); INSERT INTO `mob_pools` VALUES (6018,'iroha_ii','Iroha',149,0x0000280C00000000000000000000000000000000,12,3,3,240,100,0,0,0,0,0,0,32,0,3,0,0,427,1,0,1133); -INSERT INTO `mob_pools` VALUES (6019,'shantotto_ii','Shantotto',153,0x0000260C00000000000000000000000000000000,4,0,2,240,100,0,2,0,0,0,0,32,0,3,0,0,428,1,0,1134); +INSERT INTO `mob_pools` VALUES (6019,'shantotto_ii','Shantotto',153,0x0000260C00000000000000000000000000000000,4,0,2,240,100,1,2,0,0,0,0,32,0,3,0,0,428,1,0,1134); -- Reserved for future Trust 6020 -- Reserved for future Trust 6021 -- Reserved for future Trust 6022 diff --git a/src/map/ai/controllers/trust_controller.cpp b/src/map/ai/controllers/trust_controller.cpp index 80551ec75f7..12da42532fa 100644 --- a/src/map/ai/controllers/trust_controller.cpp +++ b/src/map/ai/controllers/trust_controller.cpp @@ -97,57 +97,85 @@ void CTrustController::DoCombatTick(time_point tick) m_LastTopEnmity = nullptr; } - auto PMaster = static_cast(POwner->PMaster); - float currentDistance = distance(POwner->loc.p, POwner->PMaster->loc.p); + CTrustEntity* PTrust = static_cast(POwner); + CCharEntity* PMaster = static_cast(POwner->PMaster); PTarget = POwner->GetBattleTarget(); - uint8 currentPartyPos = GetPartyPosition(); if (PTarget) { - if (POwner->PAI->CanFollowPath()) + if (POwner->PAI->CanFollowPath() && POwner->speed > 0) { + float currentDistanceToTarget = distance(POwner->loc.p, PTarget->loc.p); + float currentDistanceToMaster = distance(POwner->loc.p, PMaster->loc.p); + + if (currentDistanceToTarget > WarpDistance) + { + POwner->PAI->PathFind->WarpTo(PTarget->loc.p); + } + POwner->PAI->PathFind->LookAt(PTarget->loc.p); - std::unique_ptr err; - if (!POwner->CanAttack(PTarget, err) && POwner->speed > 0) + + switch (PTrust->m_MovementType) + { + case NO_MOVE: { - if (currentDistance > WarpDistance) + if (currentDistanceToMaster > CastingDistance) { - POwner->PAI->PathFind->WarpTo(PTarget->loc.p); + POwner->PAI->PathFind->PathAround(PMaster->loc.p, 10.0f, PATHFLAG_RUN | PATHFLAG_WALLHACK); } - else if (currentDistance > RoamDistance) + else if (currentDistanceToTarget > CastingDistance) { - if (currentDistance < RoamDistance * 3.0f && POwner->PAI->PathFind->PathAround(PTarget->loc.p, RoamDistance, PATHFLAG_RUN | PATHFLAG_WALLHACK)) - { - POwner->PAI->PathFind->FollowPath(); - } - else if (POwner->GetSpeed() > 0) - { - POwner->PAI->PathFind->StepTo(PTarget->loc.p, true); - } + POwner->PAI->PathFind->PathAround(PTarget->loc.p, 10.0f, PATHFLAG_RUN | PATHFLAG_WALLHACK); } + break; + } + case MID_RANGE: + { + PathOutToDistance(PTarget, 6.0f); + break; + } + case LONG_RANGE: + { + PathOutToDistance(PTarget, 12.0f); + break; } - else + case MELEE_RANGE: + default: { - for (auto POtherTrust : PMaster->PTrusts) + std::unique_ptr err; + if (!POwner->CanAttack(PTarget, err) && POwner->speed > 0) { - if (POtherTrust != POwner && !POtherTrust->PAI->PathFind->IsFollowingPath() && distance(POtherTrust->loc.p, POwner->loc.p) < 2.0f) + if (currentDistanceToTarget > RoamDistance) { - auto angle = getangle(POwner->loc.p, PTarget->loc.p) + 64; - auto amount = (currentPartyPos % 2) ? 1.0f : -1.0f; - position_t new_pos{ POwner->loc.p.x - (cosf(rotationToRadian(angle)) * amount), - PTarget->loc.p.y, POwner->loc.p.z + (sinf(rotationToRadian(angle)) * amount), 0, 0 }; - - if (POwner->PAI->PathFind->ValidPosition(new_pos)) + if (currentDistanceToTarget < RoamDistance * 3.0f && POwner->PAI->PathFind->PathAround(PTarget->loc.p, RoamDistance, PATHFLAG_RUN | PATHFLAG_WALLHACK)) + { + POwner->PAI->PathFind->FollowPath(); + } + else if (POwner->GetSpeed() > 0) { - POwner->PAI->PathFind->PathTo(new_pos, PATHFLAG_RUN | PATHFLAG_WALLHACK); + POwner->PAI->PathFind->StepTo(PTarget->loc.p, true); } - break; } } + break; + } + } + + if (!POwner->PAI->PathFind->IsFollowingPath()) + { + Declump(PMaster, PTarget); } + POwner->PAI->PathFind->FollowPath(); } + // If repositioning, bail out until you arrive + if (m_InTransit) + { + // TODO: This is too unreliable for now + // return; + } + m_GambitsContainer->Tick(tick); auto currentTopEnmity = GetTopEnmity(); @@ -212,7 +240,7 @@ void CTrustController::DoRoamTick(time_point tick) if (POwner->CanRest() && m_Tick - m_CombatEndTime > 10s && - m_Tick - m_LastHealTickTime > 3s) + m_Tick - m_LastHealTickTime > 10s) { if (POwner->health.hp != POwner->health.maxhp || POwner->health.mp != POwner->health.maxmp) { @@ -227,6 +255,77 @@ void CTrustController::DoRoamTick(time_point tick) } } +void CTrustController::Declump(CCharEntity* PMaster, CBattleEntity* PTarget) +{ + uint8 currentPartyPos = GetPartyPosition(); + for (auto POtherTrust : PMaster->PTrusts) + { + if (POtherTrust != POwner && !POtherTrust->PAI->PathFind->IsFollowingPath() && distance(POtherTrust->loc.p, POwner->loc.p) < 2.0f) + { + auto angle = getangle(POwner->loc.p, PTarget->loc.p) + 64; + auto amount = (currentPartyPos % 2) ? 1.0f : -1.0f; + position_t new_pos {POwner->loc.p.x - (cosf(rotationToRadian(angle)) * amount), + PTarget->loc.p.y, POwner->loc.p.z + (sinf(rotationToRadian(angle)) * amount), 0, 0}; + + if (POwner->PAI->PathFind->ValidPosition(new_pos)) + { + POwner->PAI->PathFind->PathTo(new_pos, PATHFLAG_RUN | PATHFLAG_WALLHACK); + } + break; + } + } +} + +void CTrustController::PathOutToDistance(CBattleEntity* PTarget, float amount) +{ + float currentDistanceToTarget = distance(POwner->loc.p, PTarget->loc.p); + position_t target_position = POwner->loc.p; + + // Invalidate position and pick new one (limit: every 3s) + if ((currentDistanceToTarget < amount - 2.5f || currentDistanceToTarget > amount + 2.5f || !POwner->PAI->PathFind->ValidPosition(POwner->loc.p)) && + m_Tick - m_LastRepositionTime > 3s) + { + // Away from target, +/- 45 degrees + auto half_sector_size = 32 + (10 * m_failedRepositionAttempts); + auto angle = getangle(PTarget->loc.p, POwner->loc.p) + 128 + tpzrand::GetRandomNumber(-half_sector_size, half_sector_size); + position_t potential_position = {PTarget->loc.p.x - (cosf(rotationToRadian(angle)) * amount), + PTarget->loc.p.y, PTarget->loc.p.z + (sinf(rotationToRadian(angle)) * amount), 0, 0}; + + // Validate position + if (POwner->PAI->PathFind->ValidPosition(potential_position) && + POwner->loc.zone->m_navMesh->raycast(PTarget->loc.p, potential_position) && + !POwner->loc.zone->m_navMesh->findPath(POwner->loc.p, potential_position).empty()) + { + m_InTransit = true; + target_position = potential_position; + m_LastRepositionTime = m_Tick; + } + else + { + ++m_failedRepositionAttempts; + } + + // If stuck, reset + if (m_failedRepositionAttempts > 3) + { + m_InTransit = true; + target_position = POwner->PMaster->loc.p; + m_LastRepositionTime = m_Tick; + } + } + + // Get somewhat close to the target destination + if (distance(POwner->loc.p, target_position) > 2.5f) + { + POwner->PAI->PathFind->PathTo(target_position, PATHFLAG_RUN | PATHFLAG_WALLHACK); + } + else + { + m_failedRepositionAttempts = 0; + m_InTransit = false; + } +} + bool CTrustController::Ability(uint16 targid, uint16 abilityid) { if (static_cast(POwner)->PRecastContainer->HasRecast(RECAST_ABILITY, abilityid, 0)) diff --git a/src/map/ai/controllers/trust_controller.h b/src/map/ai/controllers/trust_controller.h index 297b4e4fec3..e6e455b7e4f 100644 --- a/src/map/ai/controllers/trust_controller.h +++ b/src/map/ai/controllers/trust_controller.h @@ -48,6 +48,7 @@ class CTrustController : public CMobController static constexpr float RoamDistance{ 2.0f }; static constexpr float SpawnDistance{ 3.0f }; + static constexpr float CastingDistance { 15.0f }; static constexpr float WarpDistance{ 30.0f }; // TODO: Replace with reverse enmity container @@ -59,11 +60,17 @@ class CTrustController : public CMobController void DoCombatTick(time_point tick) override; void DoRoamTick(time_point tick) override; + void Declump(CCharEntity* PMaster, CBattleEntity* PTarget); + void PathOutToDistance(CBattleEntity* PTarget, float amount); + uint8 GetPartyPosition(); CBattleEntity* m_LastTopEnmity; time_point m_CombatEndTime; time_point m_LastHealTickTime; + time_point m_LastRepositionTime; + bool m_InTransit; + uint8 m_failedRepositionAttempts; }; #endif // _TRUSTCONTROLLER diff --git a/src/map/ai/helpers/gambits_container.cpp b/src/map/ai/helpers/gambits_container.cpp index 1372034b8ab..715030f25df 100644 --- a/src/map/ai/helpers/gambits_container.cpp +++ b/src/map/ai/helpers/gambits_container.cpp @@ -1,6 +1,7 @@ #include "gambits_container.h" #include "../../ability.h" +#include "../../enmity_container.h" #include "../../spell.h" #include "../../mobskill.h" #include "../../weapon_skill.h" @@ -66,6 +67,11 @@ void CGambitsContainer::Tick(time_point tick) auto runPredicate = [&](Predicate_t& predicate) -> bool { + auto isValidMember = [&](CBattleEntity* PPartyTarget) -> bool + { + return PPartyTarget->isAlive() && POwner->loc.zone == PPartyTarget->loc.zone && distance(POwner->loc.p, PPartyTarget->loc.p) <= 15.0f; + }; + if (predicate.target == G_TARGET::SELF) { return CheckTrigger(POwner, predicate); @@ -76,13 +82,6 @@ void CGambitsContainer::Tick(time_point tick) } else if (predicate.target == G_TARGET::PARTY) { - auto isValidMember = [&](CBattleEntity* PPartyTarget) -> bool - { - return PPartyTarget->isAlive() && - POwner->loc.zone == PPartyTarget->loc.zone && - distance(POwner->loc.p, PPartyTarget->loc.p) <= 15.0f; - }; - auto result = false; static_cast(POwner->PMaster)->ForPartyWithTrusts([&](CBattleEntity* PMember) { @@ -91,13 +90,75 @@ void CGambitsContainer::Tick(time_point tick) result = true; } }); - return result; } else if (predicate.target == G_TARGET::MASTER) { return CheckTrigger(POwner->PMaster, predicate); } + else if (predicate.target == G_TARGET::TANK) + { + auto result = false; + static_cast(POwner->PMaster)->ForPartyWithTrusts([&](CBattleEntity* PMember) + { + if (isValidMember(PMember) && CheckTrigger(PMember, predicate) && (PMember->GetMJob() == JOB_PLD || PMember->GetMJob() == JOB_RUN)) + { + result = true; + } + }); + return result; + } + else if (predicate.target == G_TARGET::MELEE) + { + auto result = false; + static_cast(POwner->PMaster)->ForPartyWithTrusts([&](CBattleEntity* PMember) + { + if (isValidMember(PMember) && CheckTrigger(PMember, predicate) && melee_jobs.find(PMember->GetMJob()) != melee_jobs.end()) + { + result = true; + } + }); + return result; + } + else if (predicate.target == G_TARGET::RANGED) + { + auto result = false; + static_cast(POwner->PMaster)->ForPartyWithTrusts([&](CBattleEntity* PMember) + { + if (isValidMember(PMember) && CheckTrigger(PMember, predicate) && (PMember->GetMJob() == JOB_RNG || PMember->GetMJob() == JOB_COR)) + { + result = true; + } + }); + return result; + } + else if (predicate.target == G_TARGET::CASTER) + { + auto result = false; + static_cast(POwner->PMaster)->ForPartyWithTrusts([&](CBattleEntity* PMember) + { + if (isValidMember(PMember) && CheckTrigger(PMember, predicate) && caster_jobs.find(PMember->GetMJob()) != caster_jobs.end()) + { + result = true; + } + }); + return result; + } + else if (predicate.target == G_TARGET::TOP_ENMITY) + { + auto result = false; + if (auto PMob = dynamic_cast(POwner->GetBattleTarget())) + { + static_cast(POwner->PMaster)->ForPartyWithTrusts([&](CBattleEntity* PMember) + { + if (isValidMember(PMember) && CheckTrigger(PMember, predicate) && PMob->PEnmityContainer->GetHighestEnmity() == PMember) + { + result = true; + } + }); + } + return result; + } // Fallthrough return false; @@ -124,6 +185,11 @@ void CGambitsContainer::Tick(time_point tick) } if (!all_predicates_true) { break; } + auto isValidMember = [this](CBattleEntity* PSettableTarget, CBattleEntity* PPartyTarget) + { + return !PSettableTarget && PPartyTarget->isAlive() && POwner->loc.zone == PPartyTarget->loc.zone && distance(POwner->loc.p, PPartyTarget->loc.p) <= 15.0f; + }; + // TODO: This whole section is messy and bonkers // Try and extract target out the first predicate CBattleEntity* target = nullptr; @@ -138,16 +204,9 @@ void CGambitsContainer::Tick(time_point tick) } else if (gambit.predicates[0].target == G_TARGET::PARTY) { - auto isValidMember = [&](CBattleEntity* PPartyTarget) - { - return !target && PPartyTarget->isAlive() && - POwner->loc.zone == PPartyTarget->loc.zone && - distance(POwner->loc.p, PPartyTarget->loc.p) <= 15.0f; - }; - static_cast(POwner->PMaster)->ForPartyWithTrusts([&](CBattleEntity* PMember) { - if (isValidMember(PMember) && CheckTrigger(PMember, gambit.predicates[0])) + if (isValidMember(target, PMember) && CheckTrigger(PMember, gambit.predicates[0])) { target = PMember; } @@ -159,7 +218,56 @@ void CGambitsContainer::Tick(time_point tick) } else if (gambit.predicates[0].target == G_TARGET::TANK) { - // TODO + static_cast(POwner->PMaster)->ForPartyWithTrusts([&](CBattleEntity* PMember) + { + if (isValidMember(target, PMember) && CheckTrigger(PMember, gambit.predicates[0]) && (PMember->GetMJob() == JOB_PLD || PMember->GetMJob() == JOB_RUN)) + { + target = PMember; + } + }); + } + else if (gambit.predicates[0].target == G_TARGET::MELEE) + { + static_cast(POwner->PMaster)->ForPartyWithTrusts([&](CBattleEntity* PMember) + { + if (isValidMember(target, PMember) && CheckTrigger(PMember, gambit.predicates[0]) && melee_jobs.find(PMember->GetMJob()) != melee_jobs.end()) + { + target = PMember; + } + }); + } + else if (gambit.predicates[0].target == G_TARGET::RANGED) + { + static_cast(POwner->PMaster)->ForPartyWithTrusts([&](CBattleEntity* PMember) + { + if (isValidMember(target, PMember) && CheckTrigger(PMember, gambit.predicates[0]) && (PMember->GetMJob() == JOB_RNG || PMember->GetMJob() == JOB_COR)) + { + target = PMember; + } + }); + } + else if (gambit.predicates[0].target == G_TARGET::CASTER) + { + static_cast(POwner->PMaster)->ForPartyWithTrusts([&](CBattleEntity* PMember) + { + if (isValidMember(target, PMember) && CheckTrigger(PMember, gambit.predicates[0]) && caster_jobs.find(PMember->GetMJob()) != caster_jobs.end()) + { + target = PMember; + } + }); + } + else if (gambit.predicates[0].target == G_TARGET::TOP_ENMITY) + { + if (auto PMob = dynamic_cast(POwner->GetBattleTarget())) + { + static_cast(POwner->PMaster)->ForPartyWithTrusts([&](CBattleEntity* PMember) + { + if (isValidMember(target, PMember) && CheckTrigger(PMember, gambit.predicates[0]) && PMob->PEnmityContainer->GetHighestEnmity() == PMember) + { + target = PMember; + } + }); + } } if (!target) diff --git a/src/map/ai/helpers/gambits_container.h b/src/map/ai/helpers/gambits_container.h index e8c5b8d2214..afe59c8d3f8 100644 --- a/src/map/ai/helpers/gambits_container.h +++ b/src/map/ai/helpers/gambits_container.h @@ -10,16 +10,22 @@ #include "../../status_effect.h" #include "../../status_effect_container.h" +#include + namespace gambits { enum class G_TARGET : uint16 { - SELF = 0, - PARTY = 1, - TARGET = 2, - MASTER = 3, - TANK = 4, + SELF = 0, + PARTY = 1, + TARGET = 2, + MASTER = 3, + TANK = 4, + MELEE = 5, + RANGED = 6, + CASTER = 7, + TOP_ENMITY = 8, }; enum class G_CONDITION : uint16 @@ -159,7 +165,10 @@ struct TrustSkill_t class CGambitsContainer { public: - CGambitsContainer(CTrustEntity* trust) : POwner(trust) {} + CGambitsContainer(CTrustEntity* trust) + : POwner(trust) + { + } ~CGambitsContainer() = default; void AddGambit(Gambit_t gambit); @@ -177,6 +186,36 @@ class CGambitsContainer CTrustEntity* POwner; time_point m_lastAction; std::vector gambits; + + std::set melee_jobs = + { + JOB_WAR, + JOB_MNK, + JOB_THF, + JOB_PLD, + JOB_DRK, + JOB_BST, + JOB_SAM, + JOB_NIN, + JOB_DRG, + JOB_BLU, + JOB_PUP, + JOB_DNC, + JOB_RUN, + }; + + std::set caster_jobs = + { + JOB_WHM, + JOB_BLM, + JOB_RDM, + JOB_BRD, + JOB_SMN, + JOB_BLU, + JOB_SCH, + JOB_GEO, + JOB_RUN, + }; }; } // namespace gambits diff --git a/src/map/entities/charentity.cpp b/src/map/entities/charentity.cpp index aa5a54d4b3a..32ff83e49e8 100644 --- a/src/map/entities/charentity.cpp +++ b/src/map/entities/charentity.cpp @@ -494,6 +494,10 @@ void CCharEntity::RemoveTrust(CTrustEntity* PTrust) auto trustIt = std::find_if(PTrusts.begin(), PTrusts.end(), [PTrust](auto trust) { return PTrust == trust; }); if (trustIt != PTrusts.end()) { + if (PTrust->animation == ANIMATION_DESPAWN) + { + luautils::OnMobDespawn(PTrust); + } PTrust->PAI->Despawn(); PTrusts.erase(trustIt); } diff --git a/src/map/entities/trustentity.h b/src/map/entities/trustentity.h index 9014bbc8e18..7b2f83651fb 100644 --- a/src/map/entities/trustentity.h +++ b/src/map/entities/trustentity.h @@ -24,6 +24,16 @@ #include "mobentity.h" +// PTrust->m_MovementType is read from 'behaviour' in a trust's mob_pool entry +enum TRUST_MOVEMENT_TYPE +{ + MELEE_RANGE = 0, // Default + NO_MOVE = 1, + MID_RANGE = 2, + LONG_RANGE = 3, + LAST_MOVEMENT_TYPE = 4, +}; + class CCharEntity; class CTrustEntity : public CMobEntity @@ -45,6 +55,7 @@ class CTrustEntity : public CMobEntity void OnWeaponSkillFinished(CWeaponSkillState& state, action_t& action) override; uint32 m_TrustID{}; + TRUST_MOVEMENT_TYPE m_MovementType; }; #endif diff --git a/src/map/packet_system.cpp b/src/map/packet_system.cpp index 6f01eabb77b..b4543fa9f6c 100644 --- a/src/map/packet_system.cpp +++ b/src/map/packet_system.cpp @@ -48,6 +48,7 @@ along with this program. If not, see http://www.gnu.org/licenses/ #include "roe.h" #include "entities/mobentity.h" #include "entities/npcentity.h" +#include "entities/trustentity.h" #include "entities/charentity.h" #include "spell.h" #include "utils/synthutils.h" @@ -662,6 +663,7 @@ void SmallPacket0x01A(map_session_data_t* session, CCharEntity* PChar, CBasicPac CBaseEntity* PTrust = PChar->GetEntity(TargID, TYPE_TRUST); if (PTrust != nullptr) { + ((CTrustEntity*)PTrust)->animation = ANIMATION_DESPAWN; PChar->RemoveTrust((CTrustEntity*)PTrust); } diff --git a/src/map/packets/message_basic.h b/src/map/packets/message_basic.h index dfd8d3f84e0..8e610479288 100644 --- a/src/map/packets/message_basic.h +++ b/src/map/packets/message_basic.h @@ -91,7 +91,7 @@ enum MSGBASIC_ID : uint16 /* Gardening */ MSGBASIC_GARDENING_SEED_SOWN = 256, /* In this flower pot: Seeds sown: */ MSGBASIC_GARDENING_CRYSTAL_NONE = 257, /* Crystal used: none*/ - MSGBASIC_GARDENING_CRYSTAL_USED = 258, /* Crystal used: */ + MSGBASIC_GARDENING_CRYSTAL_USED = 258, /* Crystal used: */ /* Ranged */ MSGBASIC_NO_RANGED_WEAPON = 216, /* You do not have an appropriate ranged weapon equipped. */ MSGBASIC_CANNOT_SEE = 217, /* You cannot see . */ @@ -130,14 +130,13 @@ enum MSGBASIC_ID : uint16 MSGBASIC_TREASURE_HUNTER_UP = 603, /* Additional effect: Treasure Hunter effectiveness against increases to .. */ /* DNC */ MSGBASIC_NO_FINISHINGMOVES = 524, - /* TRUST & ALTER EGO */ - MSGBASIC_TRUST_NO_CAST_TRUST = 700, // You are unable to use Trust magic at this time. - MSGBASIC_TRUST_NO_CALL_AE = 717, // You cannot call forth alter egos here. - /* ROE */ + /* TRUST & ALTER EGO */ + MSGBASIC_TRUST_NO_CAST_TRUST = 700, // You are unable to use Trust magic at this time. + MSGBASIC_TRUST_NO_CALL_AE = 717, // You cannot call forth alter egos here. + /* ROE */ MSGBASIC_ROE_START = 704, MSGBASIC_ROE_RECORD = 697, // Records of Eminence: . MSGBASIC_ROE_PROGRESS = 698, // Progress: /. - /* DEBUG MESSAGES */ MSGBASIC_DEBUG_RESISTED_SPELL = 66, /* Debug: Resisted spell! */ MSGBASIC_DEBUG_RECEIVED_STATUS = 73, /* Debug: 's status is now .. */ diff --git a/src/map/utils/trustutils.cpp b/src/map/utils/trustutils.cpp index fae517f9ad9..7b45dce1415 100644 --- a/src/map/utils/trustutils.cpp +++ b/src/map/utils/trustutils.cpp @@ -51,6 +51,8 @@ struct Trust_t uint8 size; // размер модели uint16 m_Family; + uint16 behaviour; + uint8 mJob; uint8 sJob; float HPscale; // HP boost percentage @@ -191,7 +193,7 @@ void BuildTrust(uint32 TrustID) trust->cmbDmgMult = (uint16)Sql_GetIntData(SqlHandle, 8); trust->cmbDelay = (uint16)Sql_GetIntData(SqlHandle, 9); trust->name_prefix = (uint8)Sql_GetUIntData(SqlHandle, 10); - // Behaviour + trust->behaviour = (uint16)Sql_GetUIntData(SqlHandle, 11); trust->m_MobSkillList = (uint16)Sql_GetUIntData(SqlHandle, 12); // SpellID trust->size = Sql_GetUIntData(SqlHandle, 14); @@ -300,6 +302,7 @@ CTrustEntity* LoadTrust(CCharEntity* PMaster, uint32 TrustID) PTrust->status = STATUS_NORMAL; PTrust->m_ModelSize = trustData->size; PTrust->m_EcoSystem = trustData->EcoSystem; + PTrust->m_MovementType = static_cast(trustData->behaviour); PTrust->SetMJob(trustData->mJob); PTrust->SetSJob(trustData->sJob); @@ -352,18 +355,19 @@ void LoadTrustStatsAndSkills(CTrustEntity* PTrust) //float subHPGrowth = 1.0f + ((7.0f - (float)jobHPGrade) / 100.0f); float subMPGrowth = 1.0f + ((7.0f - (float)jobMPGrade) / 100.0f); - float base = 15.0f; + float hpBase = 14.0f; + float mpBase = 8.0f; - PTrust->health.maxhp = static_cast(base * pow(mLvl, hpGrowth) * PTrust->HPscale * map_config.alter_ego_hp_multiplier); + PTrust->health.maxhp = static_cast(hpBase * pow(mLvl, hpGrowth) * PTrust->HPscale * map_config.alter_ego_hp_multiplier); if (sjobMPGrade) { - PTrust->health.maxmp = static_cast(base * pow(sLvl, subMPGrowth) * PTrust->MPscale * map_config.alter_ego_mp_multiplier); + PTrust->health.maxmp = static_cast(mpBase * pow(sLvl, subMPGrowth) * PTrust->MPscale * map_config.alter_ego_mp_multiplier); } if (jobMPGrade) { - PTrust->health.maxmp = static_cast(base * pow(mLvl, mpGrowth) * PTrust->MPscale * map_config.alter_ego_mp_multiplier); + PTrust->health.maxmp = static_cast(mpBase * pow(mLvl, mpGrowth) * PTrust->MPscale * map_config.alter_ego_mp_multiplier); } PTrust->health.tp = 0;