MrVauxs / pf2e-jb2a-macros

Discord: @vauxs
GNU General Public License v3.0
11 stars 27 forks source link

Add Animation for Elemental Blasts #179

Open ChasarooniZ opened 7 months ago

ChasarooniZ commented 7 months ago

Hi, started on a script for adding animation for elemental blasts, figured it would do the community good to share it.

const isMiss = args[1].hitTargets === false;
const target = args[1]?.allTargets?.[0];
const source = args[1]?.sourceToken;

if (!target) return;

let seq = new Sequence()
    .effect()
    .atLocation(source)
    .stretchTo(target)
    .missed(isMiss);

const flags = args[0].flags.pf2e.context;
const options = flags.options;
const traits = flags.traits;
const isTwoAction = options.includes('action:cost:2');
const isMelee = options.includes('melee');
const element = traits.find(t => ['air', 'earth', 'fire', 'metal', 'water', 'wood'].includes(t))

const isWeaponInfusion = options.includes('self:effect:weapon-infusion');
if (isWeaponInfusion) seq = weaponInfusionAnim(element, options, isMelee, source, target, isMiss)
if (traits.includes('air')) {
    if (!isWeaponInfusion) {
        if (isMelee) {
            seq.file("animated-spell-effects-cartoon.smoke.05");
        } else {
            seq.file("animated-spell-effects-cartoon.smoke.81");
        }
    }
    if (isTwoAction)
        seq.effect()
            .atLocation(target)
            .scaleToObject()
            .file("animated-spell-effects-cartoon.smoke.43")
            .missed(isMiss);

} else if (traits.includes('earth')) {
    if (!isWeaponInfusion) {
        if (isMelee) {
            seq.file("jb2a.boulder.toss.01.02");
        } else {
            seq.file("jb2a.slingshot");
        }
    }
    if (isTwoAction)
        seq.effect()
            .atLocation(target)
            .scaleToObject()
            .file("animated-spell-effects-cartoon.earth.debris.03")
            .missed(isMiss);
} else if (traits.includes('fire')) {
    if (!isWeaponInfusion) {
        if (isMelee) {
            seq.file("animated-spell-effects-cartoon.fire.25");
        } else {
            seq.file("animated-spell-effects-cartoon.fire.20");
        }
    }
    if (isTwoAction)
        seq.effect()
            .atLocation(target)
            .scaleToObject()
            .file("animated-spell-effects-cartoon.fire.15")
            .missed(isMiss);
} else if (traits.includes('metal')) {
    if (!isWeaponInfusion) {
        if (isMelee) {
            seq.file("jb2a.melee_generic.piercing.one_handed");
        } else {
            seq.file("jb2a.throwable.launch.missile.04");
        }
    }
    if (isTwoAction)
        seq.effect()
            .atLocation(target)
            .scaleToObject()
            .file("jb2a.impact.orange.11")
            .missed(isMiss);
} else if (traits.includes('water')) {
    if (!isWeaponInfusion) {
        if (isMelee) {
            seq.file("animated-spell-effects-cartoon.water.45");
        } else {
            seq.spriteRotation(90).spriteOffset({ x:2, y: -2 }, { gridUnits: true }) .file("animated-spell-effects-cartoon.water.71");
        }
    }
    if (isTwoAction)
        seq.effect()
            .atLocation(target)
            .scaleToObject()
            .file("animated-spell-effects-cartoon.water.55")
            .missed(isMiss);
} else if (traits.includes('wood')) {
    if (!isWeaponInfusion) {
        if (isMelee) {
            seq.file("jb2a.melee_generic.bludgeoning.one_handed");
        } else {
            seq.file("jb2a.bullet.03.green");
        }
    }
    if (isTwoAction)
        seq.effect()
            .atLocation(target)
            .scaleToObject()
            .file("animated-spell-effects-cartoon.earth.explosion.03")
            .missed(isMiss);
}
seq.play();

function weaponInfusionAnim(element, options, isMelee, source, target, isMiss) {
    const seq = new Sequence();
    if (isMelee) {
        seq.effect()
            .atLocation(source)
            .stretchTo(target)
            .missed(isMiss);
        if (options.includes("weapon-infusion:melee:agile")) {
            switch (element) {
                case 'air':
                    seq.file("jb2a.dagger.melee.fire.white");
                    break;
                case 'earth':
                    seq.file("jb2a.dagger.melee.fire.orange");
                    break;
                case 'fire':
                    seq.file("jb2a.dagger.melee.fire.red");
                    break;
                case 'metal':
                    seq.file("jb2a.dagger.melee.fire.pink")
                        .filter("ColorMatrix", { saturate: -1 });
                    break;
                case 'water':
                    seq.file("jb2a.dagger.melee.fire.blue");
                    break;
                case 'wood':
                    seq.file("jb2a.dagger.melee.fire.green");
                    break;
                default:
                    break;
            }
        } else if (options.includes("weapon-infusion:melee:backswing")) {
            switch (element) {
                case 'air':
                    seq.file("jb2a.glaive.melee.02.white");
                    break;
                case 'earth':
                    seq.file("jb2a.glaive.melee.02.orange")
                        .tint('#c9c9c9');
                    break;
                case 'fire':
                    seq.file("jb2a.glaive.melee.02.orange");
                    break;
                case 'metal':
                    seq.file("jb2a.glaive.melee.02.blue")
                        .filter("ColorMatrix", { saturate: -1 });;
                    break;
                case 'water':
                    seq.file("jb2a.glaive.melee.02.blue");
                    break;
                case 'wood':
                    seq.file("jb2a.glaive.melee.02.blue")
                        .filter("ColorMatrix", { hue: -84 });;
                    break;
                default:
                    break;
            }
        } else if (options.includes("weapon-infusion:melee:forceful")) {
            switch (element) {
                case 'air':
                    seq.file("jb2a.glaive.melee.01.white");
                    break;
                case 'earth':
                    seq.file("jb2a.glaive.melee.01.orange")
                        .tint('#c9c9c9');
                    break;
                case 'fire':
                    seq.file("jb2a.glaive.melee.01.orange");
                    break;
                case 'metal':
                    seq.file("jb2a.glaive.melee.01.blue")
                        .filter("ColorMatrix", { saturate: -1 });;
                    break;
                case 'water':
                    seq.file("jb2a.glaive.melee.01.blue");
                    break;
                case 'wood':
                    seq.file("jb2a.glaive.melee.01.blue")
                        .filter("ColorMatrix", { hue: -84 });;
                    break;
                default:
                    break;
            }
        } else if (options.includes("weapon-infusion:melee:reach")) {
            switch (element) {
                case 'air':
                    seq.file("jb2a.spear.melee.fire.white");
                    break;
                case 'earth':
                    seq.file("jb2a.spear.melee.fire.yellow");
                    break;
                case 'fire':
                    seq.file("jb2a.spear.melee.fire.red");
                    break;
                case 'metal':
                    seq.file("jb2a.spear.melee.fire.pink")
                        .filter("ColorMatrix", { saturate: -1 });
                    break;
                case 'water':
                    seq.file("jb2a.spear.melee.fire.blue");
                    break;
                case 'wood':
                    seq.file("jb2a.spear.melee.fire.green");
                    break;
                default:
                    break;
            }
        } else if (options.includes("weapon-infusion:melee:sweep")) {
            switch (element) {
                case 'air':
                    seq.file("jb2a.greataxe.melee.fire.white");
                    break;
                case 'earth':
                    seq.file("jb2a.greataxe.melee.fire.orange");
                    break;
                case 'fire':
                    seq.file("jb2a.greataxe.melee.fire.red");
                    break;
                case 'metal':
                    seq.file("jb2a.greataxe.melee.fire.pink")
                        .filter("ColorMatrix", { saturate: -1 });
                    break;
                case 'water':
                    seq.file("jb2a.greataxe.melee.fire.blue");
                    break;
                case 'wood':
                    seq.file("jb2a.greataxe.melee.fire.green");
                    break;
                default:
                    break;
            }
        }
    } else {
        seq.effect()
            .atLocation(source)
            .stretchTo(target)
            .missed(isMiss);
        if (options.includes("weapon-infusion:ranged:volley-30")) {
            switch (element) {
                case 'air':
                    seq.file("jb2a.arrow.physical.white.02");
                    break;
                case 'earth':
                    seq.file("jb2a.arrow.physical.orange");
                    break;
                case 'fire':
                    seq.file("jb2a.arrow.fire.red");
                    break;
                case 'metal':
                    seq.file("jb2a.arrow.lightning.purple")
                        .filter("ColorMatrix", { saturate: -1 });
                    break;
                case 'water':
                    seq.file("jb2a.arrow.cold.blue");
                    break;
                case 'wood':
                    seq.file("jb2a.arrow.poison.green.01");
                    break;
                default:
                    break;
            }
        } else if (options.includes("weapon-infusion:ranged:propulsive")) {
            switch (element) {
                case 'air':
                    seq.file("jb2a.bolt.physical.white");
                    break;
                case 'earth':
                    seq.file("jb2a.bolt.physical.orange");
                    break;
                case 'fire':
                    seq.file("jb2a.bolt.fire.red");
                    break;
                case 'metal':
                    seq.file("jb2a.bolt.lightning.purple")
                        .filter("ColorMatrix", { saturate: -1 });
                    break;
                case 'water':
                    seq.file("jb2a.bolt.cold.blue");
                    break;
                case 'wood':
                    seq.file("jb2a.bolt.poison.green");
                    break;
                default:
                    break;
            }
        } else if (options.includes("weapon-infusion:ranged:thrown")) {
            switch (element) {
                case 'air':
                    seq.file("jb2a.dagger.throw.01.pink");
                    break;
                case 'earth':
                    seq.file("jb2a.dagger.throw.01.red")
                        .tint("#b9ba63");
                    break;
                case 'fire':
                    seq.file("jb2a.dagger.throw.01.red");
                    break;
                case 'metal':
                    seq.file("jb2a.dagger.throw.01.white");
                    break;
                case 'water':
                    seq.file("jb2a.dagger.throw.01.blue");
                    break;
                case 'wood':
                    seq.file("jb2a.boomerang.01.white.01.throw");
                    break;
                default:
                    break;
            }
        }
    }
    return seq;
}
ThiefMaster commented 7 months ago

Really nice macro, but I noticed some bugs:

PS: You have some extra triple-backticks at the very end after the final }. Easy to remove but less technical people might not notice those and wonder why things break.

ChasarooniZ commented 7 months ago
  1. nice catch
  2. Incorrect for versatile blasts, as it only adds a trait, the original traits still remain for the attacks
ChasarooniZ commented 7 months ago

Fixed issue with offset of smaller one

ThiefMaster commented 7 months ago

Before I start creating a frankenmacro from yours and another one I found out there, do you have any plans to support the different elemental damage types?

This works nicely to get both the element and the damage type:

const roll = args[0].rolls.find((r) => r.options.action === 'elemental-blast');
const data = roll?.options.identifier;
const [element, damageType, meleeOrRanged, actionCost] = data.split('.');

But of course picking nice animations etc. is a lot of work :D

ChasarooniZ commented 7 months ago

Nah feel free to take a crack at it. My only kineticist in my campaign is deceased, so don't plan on spending the time to work on it while I don't have a player actively using it