LandSandBoat / server

:sailboat: LandSandBoat - a server emulator for Final Fantasy XI
https://landsandboat.github.io/server/
GNU General Public License v3.0
301 stars 603 forks source link

🐛 DRG Wyvern Breath Attacks only Using Fire Breath #4521

Open Chawizawd08 opened 1 year ago

Chawizawd08 commented 1 year ago

I affirm:

OS / platform the server is running (if known)

Branch affected by issue

base

Steps to reproduce

DRG Wyvern Pet Breath Attacks only use Fire Breath

Expected behavior

DRG Wyvern pet Breath Attacks should be used based on Mob's Resistance

Chawizawd08 commented 1 year ago

scrips/globals/job_utils/dragoon.lua by changing lines 770-775 target:getMod(xi.mod.FIRE_RES_RANK), target:getMod(xi.mod.ICE_RES_RANK), target:getMod(xi.mod.WIND_RES_RANK), target:getMod(xi.mod.EARTH_RES_RANK), target:getMod(xi.mod.THUNDER_RES_RANK), target:getMod(xi.mod.WATER_RES_RANK), I was able to get the wyvern to use Sand Breath on Torama(coeurl) and the water breath on Labyrinth Manticore in the zone Labyrinth of Onzozo

claywar commented 1 year ago
    -- Magic Evasion versus elements
    -- This has been repeatedly mixed up with SDT - be careful!
    FIRE_MEVA                       = 15,
    ICE_MEVA                        = 16,
    WIND_MEVA                       = 17,
    EARTH_MEVA                      = 18,
    THUNDER_MEVA                    = 19,
    WATER_MEVA                      = 20,
    LIGHT_MEVA                      = 21,
    DARK_MEVA                       = 22,

These are defined in scripts/enum/mod.lua, and should be available

Chawizawd08 commented 1 year ago

something isnt right. with those variables the wyvern only uses fire breath.

Chawizawd08 commented 1 year ago

does that file need to be in the top of the code "required" to be referenced correctly?

claywar commented 1 year ago

Nope, all enums are loaded prior to any other script, and do not depend on other items

Chawizawd08 commented 1 year ago

im sorry, im not seeing where the Enums MEVAs are being calculated. is this in the core or maybe the client. i see the RES_RANKs in the Data base, and they atleast get the wyvern to choose the lowest number for its breath attacks.

cocosolos commented 1 year ago

It looks like in other places we use a combination of magic resist rank and magic evasion to get the actual evasion. I'm not sure what's up with the MEVA mods. There's like 1 entry in mob_family_mods, a couple in mob_pool_mods, some in mob_spawn_mods, some in scripts. Are the resist ranks supposed to be like inherent evasion and the mods are more for adjustments? In core it looks like they're only used for player enspell damage.

Xaver-DaRed commented 1 year ago

MEVA

xi.combat.magicHitRate.calculateTargetMagicEvasion = function(actor, target, spellElement, isEnfeeble, mEvaMod, rankModifier)
    local magicEva   = target:getMod(xi.mod.MEVA) -- Base MACC.
    local resistRank = 0 -- Elemental specific Resistance rank. Acts as multiplier to base MACC.
    local resMod     = 0 -- Elemental specific magic evasion. Acts as a additive bonus to base MACC after affected by resistance rank.
    local levelDiff  = target:getMainLvl() - actor:getMainLvl()

    -- Elemental magic evasion.
    if spellElement ~= xi.element.NONE then
        -- Mod set in database for mobs. Base 0 means not resistant nor weak. Bar-element spells included here.
        resMod     = target:getMod(xi.combat.element.elementalMagicEva[spellElement])
        resistRank = utils.clamp(target:getMod(xi.combat.element.resistRankMod[spellElement]), -3, 11)

        if resistRank > 4 then
            resistRank = utils.clamp(resistRank - rankModifier, 4, 11)
        end

        magicEva = math.floor(magicEva * resistRankMultiplier[resistRank]) + resMod
    end

    -- Magic evasion against specific status effects.
    if isEnfeeble then
        magicEva = magicEva + target:getMod(mEvaMod) + target:getMod(xi.mod.STATUS_MEVA)
    end

    -- Level correction. Target gets a bonus the higher the level if it's a mob. Never a penalty.
    if
        levelDiff > 0 and
        xi.combat.levelCorrection.isLevelCorrectedZone(actor) and
        not target:isPC()
    then
        magicEva = magicEva + levelDiff * 4
    end

    return magicEva
end

In short: MEVA * resis_rank_rate + ELEMENTAL_MEVA

ELEMENTAL_MEVA is a flat number, used by certain effects, additive to the corrected MEVA

Xaver-DaRed commented 1 year ago

So yeah, IDK how smart wyverns are. If they were smart in retail, they would check the whole calculation for each element and use the lowest.

But if I had to bet, in retail they only check their resistance rank, making their breath selection sub-optimal under certain circustances.

cocosolos commented 1 year ago

Wiki says effects like Threnody are factored into the choice so yeah it looks like whole calculation.

TeoTwawki commented 1 year ago

So yeah, IDK how smart wyverns are. If they were smart in retail, they would check the whole calculation for each element and use the lowest.

But if I had to bet, in retail they only check their resistance rank, making their breath selection sub-optimal under certain circustances.

Def sub optimal on retail, my wyvern uses water breath on crabs man. There is gear that makes it choose breaths smarter but stock un-enhanced wyvern is an idiot.

TeoTwawki commented 1 year ago

regarding seemingly random placed meva mods, just remember we're likely to still find some old ones that didn't get removed yet. carried forward for the last 6-8 yrs.

cocosolos commented 1 year ago

So bg-wiki says AF head doesn't do anything, but then on the item page it says it makes the wyvern target enemy weakness. Wikia says (last edited in 2008 btw) the choice is random. So is it supposed to be random if you're not wearing the AF head, or does it always target weaknesses and if it does why does the bg-wiki page for the +3 version still say it makes the wyvern target weakness.

Xaver-DaRed commented 1 year ago

Well, so the solution, I think, would be to factor both. Not a hard change, really. One can even reuse the function I linked and make it run per element, like so...


local meva           = xi.combat.magicHitRate.calculateTargetMagicEvasion(actor, target, 1, false, 0, 0)
local newMeva        = 0
local weakestElement = 1 -- What we want.

for i = 2, 8 do
    newMeva = xi.combat.magicHitRate.calculateTargetMagicEvasion(actor, target, i, false, 0, 0)

    if newMeva < meva then
        meva            = newMeva
        weakestElement  = i
    end
end
WinterSolstice8 commented 1 year ago

Drachen armet doesn't do anything for damage breaths as of some time recently on retail -- it always picks the element that has the least chance of resisting. It just doesn't make sense to equip Vishap Armet +3 which would only give you a tiny amount of extra damage from the wyvern as opposed to one of the numerous other powerful items to make WS stronger

Vishap_Armet_+3_description

TeoTwawki commented 1 year ago

So bg-wiki says AF head doesn't do anything, but then on the item page it says it makes the wyvern target enemy weakness. Wikia says (last edited in 2008 btw) the choice is random. So is it supposed to be random if you're not wearing the AF head, or does it always target weaknesses and if it does why does the bg-wiki page for the +3 version still say it makes the wyvern target weakness.

image

cocosolos commented 1 year ago

Elemental damage breath will more accurately target the monster's weakness.

Yeah so I'm guessing this line has just been copy/pasted forward with each version of the item and just never got removed when the wyvern was improved. It dates all the way back to the original 2008 creation of the AF helm page.

TeoTwawki commented 1 year ago

copy🍝 strikes again