tposney / midi-qol

Other
5 stars 0 forks source link

[Suggestion] Add Spells you cast ignore XXX Resist flag #268

Open tposney opened 3 years ago

tposney commented 3 years ago

In GitLab by @dineshm on Mar 9, 2021, 12:02

The Elemental Adept feat in 5e has the following effects: "Spells you cast ignore resistance to [fire] damage, and when you roll damage for a spell you cast that deals [fire] damage, you can treat any 1 on a damage die as a 2." You can choose this feat for any of: acid, cold, fire, lightning, or thunder.

This request is to add a flag and associated MQoL automation that allows for the first half of that effect to happen: have spells you cast ignore specific types of resistances (but not immunities) on the target. This feat only works for spells, but perhaps there are similar features for normal physical attacks as well, or will be some day, so it might make sense to add those at the same time, I'll leave that to you to consider.

As an aside, when using DAE to add spell resistances, I notice that the DAE editor has a dropdown that includes both fire and -fire. I am not really sure how the -fire and related items are supposed to work. Are those intended to mean "remove fire resistance", or maybe "ignore fire resistance"? If so, that might fit the bill here, but I don't know how to make it work in an actual attack workflow, because the ability is on a feature that affects the caster, not on the attack itself, so it can't work as a normal non-transfer effect that is applied to the spell target on a hit. I guess you could put the effect on every spell attack Item, but that would be a highly manual and duplicative process - making this a flag on the caster that gets applied during the damage calc workflow would be much better.

I will create a separate request for the second part of this feature effect.

tposney commented 3 years ago

The -fire, says remove fire resistance from the actor on which the effect exists, so it won't be of help to you here.

The first part of the request might be tricky. By the time midi comes to work out resistance/immunity it longer has access to the actor that caused the damage and it would have to look back to the actor to see if that flag is set.

But I'll have a look and see what can be done.

tposney commented 3 years ago

In GitLab by @mike-marshall0164 on Mar 12, 2021, 11:12

I kinda made a macro setup to accomplish this using ItemMacro. I'm still pretty new at this, but maybe it'll help! Here's an example for my Fireball spell that reduces damage by 1 tier. @tposney Interestingly my first approach was an attempt at adding a DAE effect of the -Fire effect with duration until damage. But there was an error that kept coming up with the gm summary thing at the end while it was trying to do traits.map ? This solution works specifically because we don't actually mutate the actor permanently.

let hitTargets = [];
args[0].hitTargets.forEach(i => {

    hitTargets.push(canvas.tokens.get(i._id));
    reduceFireResTemp(canvas.tokens.get(i._id).actor);

});
let numDice = 8 + (args[0].spellLevel - 3);

let damageRoll = new Roll(`${numDice}d6r1`).roll();
let target = canvas.tokens.get(args[0].hitTargets[0]._id)

await game.dice3d.showForRoll(damageRoll, game.user, true, null, false);

new MidiQOL.DamageOnlyWorkflow(actor, token, damageRoll.total, "fire", hitTargets, damageRoll, {flavor: "Fire Bolt - Damage Roll", itemCardId: args[0].itemCardId});

function reduceFireResTemp(actor) {

let resistances = actor.data.data.traits.dr?.value;
let immunities = actor.data.data.traits.di?.value;
let vulnerabilities = actor.data.data.traits.dv?.value;
    if(immunities.includes("fire")) {

        console.log("temp removing fire immunity");
        //add temp effect of burning
        actor.data.data.traits.di.value = [];
        actor.data.data.traits.dr.value = ["fire"];
        return;
    }

    if(resistances.includes("fire")) {
        //add temp effect of burning
        console.log("temp removing fire res");
        actor.data.data.traits.dr.value = [];

        return;
    }

    if(!resistances.includes("fire") && !immunities.includes("fire") && !vulnerabilities.includes("fire")) {
        //add temp effect of burning
        console.log("temp adding fire vulnerabilities");
        actor.data.data.traits.dv.value = ["fire"];

        return;
    }

}
tposney commented 3 years ago

I understand the request, however there is a war of attrition starting here. you have an effect that gives you resistance to fire. Then there is an effect that overrides the resistance to fire. The next stage would be an effect that overrides the override and so on....

I'm not sure I have any idea on what a sensible solution would be, nor how to implement it.

tposney commented 3 years ago

In GitLab by @dineshm on Mar 18, 2021, 01:36

I don't think the dnd5e rules address this either, so it's understandable that we don't really know what should happen in this "war of attrition". Having said that, before they implemented something that would cause such a 3rd stage effect to be part of the rules, hopefully they would create a rule to address the confusion as well.

As an interim compromise, perhaps treat it like advantage and disadvantage? if there is an ability that grants immun/resistance/vulnerability, and another that pierces that grant, or causes a "step down" in effect, then they cancel each other out and a normal roll is made, no matter how many extra effects are on one side over the other.

tposney commented 3 years ago

In GitLab by @LunaEclipse on Apr 27, 2021, 06:50

The feat is actually specific, it says "ignore resistance" which means the only thing that can override that is full immunity. It doesn't matter how much resistance a target has, or how many times its applied because the feat ignores it.

I don't know the modules code and wouldn't know where to start looking, but the logic is simple enough, I can explain with psudeo-code.

Elemental adept feat applies a flag for example elementalAdept: fire

1. Player casts spell.
2. check if target is immune to damage type and return if they are.
3. check if damageType === elementalAdept flag value
4.     do damage roll, count number of ones rolled and add that number to total, thus simulating them changing from one to two.
5.     apply the modified damage.
6. else
7.     do damage roll accounting for resistance if the target has it.
tposney commented 3 years ago

Couple of things here.
Midi does nothing to modify the dice rolls and leaves that up to the dnd5e system. So ignoring 1's would be a change to the spell that the elemental adept had (i.e. changing the damage roll accordingly) and would not be handled by midi.

The problem with the resistance ignoring is that by the time midi looks to see what resistances the target has it only has the target and the damage and damage type, there is no reference to the actor that caused the damage. So making it an actor flag is not ideal.

Ideally it would be a per item flag, since that is bound up with the attack, but there is no way to specify that at present. If it is an actor flag it would have to be specifically an elemental adept flag since it only affects spells with the specific damage type, not any other attack with the same damage type.

I have shied away from putting in specific ability flags, rather trying to create tools to implement such things.

tposney commented 3 years ago

In GitLab by @LunaEclipse on Apr 27, 2021, 13:28

I just commented here because I have actually been looking at this issue myself, but I am new to foundry, and new to JavaScript, though I have C#, VB and LUA programming knowledge, so at present I am trying to convert that knowledge to JavaScript, and learn the Foundry API.

I understand your issue, I had hoped to find an event I could hook such as a preRoll hook, but there is nothing, which is why you are obviously using the renderChatMessage hook, I had hoped that because you were condensing the attack cards, you were able to modify the information before condensing it, but as I said, I had not looked at your code, and I didn't realize the actor data was not available.

Obviously I can edit spells on any characters with this feat of the type they have chosen, I was hoping for a more automatic effort that could be applied in a general sense, now and in the future. This would also apply similar to Life Clerics receiving extra healing on their healing spells as well.

It looks like this is more a suggestion for the DND5e system module instead.