0.5.2 Off-hand catalysts' accuracy and crit chance are counted twice for spells [fixed]

Prince Charming

Active Member
Mar 18, 2020
30
33
Every spell uses the attemptMagicalHit function of CombatHelper:
JavaScript:
function(t, n) {
    var r = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : 0,
        a = arguments.length > 3 && void 0 !== arguments[3] ? arguments[3] : 0,
        o = e.magicalCritHitBonus(t, n),
        i = o.hitBonus,
        s = o.critBonus,
        l = t.accuracy() + i,
        u = e.attemptHit(l, n.magicRes(), r);
    a += s;
    var c = e.isCrit(t, n, a),
        h = u > 15,
        f = this.shieldChecks(n, h && (u >= 120 || c));
    return {
        hit: h,
        crit: f
    }
}
As you can see, it retrieves both the spell user's .accuracy(), and the .hitBonus part of CombatHelper's magicalCritHitBonus's result for said spell user, and adds both sources to feed them to CombatHelper's attemptHit. However, an off-handed catalyst's stats are counted in both .accuracy() and magicalCritHitBonus, meaning they're added twice to the final "hit chance score".

Proof:
CombatHelper.magicalCritHitBonus is:
JavaScript:
function(e, t) {
    var n = e.safeWeaponPrimary().isCatalyst(),
        r = e.weaponSecondary && e.weaponSecondary.isCatalyst(),
        a = 0;
    n && (a += Math.max(0, e.safeWeaponPrimary().accuracy || 0)), r && (a += Math.max(0, e.weaponSecondary.accuracy || 0)), e.hasCombatEffect(CEFFECTS.Overcharged) && (a += 20);
    var o = 0;
    return n && (o += Math.max(0, e.safeWeaponPrimary().crit || 0)), r && (o += Math.max(0, e.weaponSecondary.crit || 0)), e.hasPerk(PERKS.ArcaneStrike) && (o += e.willpower() / 2), {
        hitBonus: a,
        critBonus: o
    }
}
If you give the pc say, a lynx totem and make the following inquiries in the console:
pc.weaponSecondary yields an object representing the lynx totem, meaning the off-handed catalyst is considered a secondary weapon.
pc.weaponSecondary.isCatalyst() yields true, further confirming that the lynx totem's stats will be considered for magicalCritHitBonus.
CombatHelper.magicalCritHitBonus(pc) yields 10, which is the lynx totem's accuracy (assuming you're not using a catalyst in your primary weapon slot), confirming that magicalCritHitBonus takes the off-handed catalyst's stats into account.

pc.accuracy (which is a function) is:
JavaScript:
function() {
    var e = 2 * this.agility();
    return e += this.getStatForAllNonWeaponEquipment("accuracy"),
      this.getCombatEffect("Prone") && (e -= 25),
      this.getCombatEffect("Blinded") && (e -= 15),
      this.hasCombatEffect(CEFFECTS.Covered) && (e += 20),
      this.hasCombatEffect(CEFFECTS.Distracted) && (e -= 20),
      this.hasCombatEffect(CEFFECTS.Blessed) && (e += 10),
      this.hasPerk(PERKS.SecondSight) && (e += this.willpower()),
      Math.floor(e)
}
It sums up accuracy for all non weapon equipment. Let's take a closer a look at this function! pc.getStatForAllNonWeaponEquipment is:
JavaScript:
function(e) {
    return e && "string" == typeof e ? this.equipmentAsArray().filter((function(e) {
        return !e.isPrimary()
    })).reduce((function(t, n) {
        return t + (n[e] || 0)
    }), 0) : 0
}
It adds accuracy from all equipment that don't fulfill the .isPrimary() condition. But an off-handed catalyst isn't primary! If you equip the lynx totem and type pc.weaponSecondary.isPrimary(), it of course returns false. If you unequip all equipment (including the lynx totem), pc.getStatForAllNonWeaponEquipment('accuracy') returns 0, if you re-equip only the lynx totem, it returns 10.
Likewise, assuming a level 6 pc with no starter agility bonus (say, a human minstrel), agility will be 7 and therefore pc.accuracy() without any equipment will yield 14. Re-equip the lynx totem, and pc.accuracy() is now 24! It confirms the off-handed catalyst's stats are taken into account by Creature.accuracy().

By the way, if you want to test this out in the javascript console, there's been a bug in Chromium for the past three weeks that sends eval and debugging props to Valhalla every time you type anything in the console, therefore I'd suggest temporarily installing Firefox to fiddle with the game from the javascript console.