Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Animation for Elemental Blasts #179

Open
ChasarooniZ opened this issue Mar 8, 2024 · 5 comments
Open

Add Animation for Elemental Blasts #179

ChasarooniZ opened this issue Mar 8, 2024 · 5 comments

Comments

@ChasarooniZ
Copy link
Contributor

ChasarooniZ commented Mar 8, 2024

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
Copy link
Contributor

Really nice macro, but I noticed some bugs:

  • Water+Ranged has an offset that makes the blast show up in the wrong location. using spriteOffset({ x: 95, y: -90 }) is slightly better but also not great depending on the placement of the tokens
  • Looking at the traits is not reliable when using the Versatile Blasts feat (adds a second damage type option to each blast element)

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
Copy link
Contributor Author

ChasarooniZ commented Mar 15, 2024

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

@ChasarooniZ
Copy link
Contributor Author

ChasarooniZ commented Mar 15, 2024

Fixed issue with offset of smaller one

@ThiefMaster
Copy link
Contributor

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
Copy link
Contributor Author

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants