Closed asimone closed 3 years ago
This sounded like a really interesting feature to add, so I experimented with it and after poring over Midi-QOL's codebase was able to make most of it work. You can update to v0.2.18 to give it a try. The only limitation seems to be that On Use macros that use MidiQOL.DamageOnlyWorkflow might overwrite the damage rolls that Mob Attack Tool creates if you have "merge rolls to one card" enabled in Midi's settings. I've added a setting to Mob Attack Tool to help prevent that from happening, though.
At any rate, thanks for suggesting to add this feature! I wouldn't have thought of doing so without this issue you made, and that would've been unfortunate because it seems like a really useful feature. This is exactly why I always ask people to create issues for feature requests, so don't hesitate to make another. (Of course, I can't guarantee that I'll work on it as quickly as I did this time.)
Before I forget, could you download the new release and tell me if you run into any bugs? Just to make sure I didn't miss anything :)
Ooh, I'll definitely play with this today and let you know if I discover any bugs or weird edge cases.
I think the next step in developing the feature would be to directly hook into Automated Animations which does a lot of the "on use macro" like elements for you (I don't know if Otigon uses On Macro directly, tbh) and will even automate the use of animation based on item names on a character sheet in many instances.
Also, I totally understand if you can't get to any new features very quickly if I suggest more. I'm a product/project manager for a software company so I definitely know how this works. 😅
Okay, so this is a cool feature. Minor bug or, at least, a behavior that isn't ideal.
See video for above description https://user-images.githubusercontent.com/575279/122679728-9ab67f00-d1b1-11eb-90e6-fc122f8cb6ef.mp4
Ideal behavior: different tokens fire the animations on multiple hits on the same target
In the macro you used, can you check if it includes the following line?
let myToken = canvas.tokens.controlled [0];
If it does, could you replace it with the following line and try it again? Please let me know if that fixes it for you.
let myToken = canvas.tokens.get(args[0].tokenId);
This is exactly what I did in the example in the release notes, so that should work. Here's a video of it:
Changing the macro in this way shouldn't affect how it works outside of Mob Attack Tool, by the way, if you use Midi-QOL. Having said that, I think I need to improve the algorithm that determines how often macros are executed. It is currently mostly focused on making sure JB2A animations would originate from random tokens, but other macros may have different needs. So expect some improvements on that front in a later release. (Don't have time this week to code, though :( )
Edit: I somehow overlooked your second to last message. Thanks for the tip, I'll take a look how Automated Animations triggers such animations.
Apologies for the delay, my week went sideways at work and was focused on other stuff. The Macro I was using in full at the bottom, it's an compendium macro JB2A provides. It looks like it is using:
let myToken = canvas.tokens.controlled [0];
That fix didn't work, but the macros appear to be broken now, even the original isn't working, and I can't tell if it's an update I did or something else, so I'll need to investigate more. I'll update this ticket as I figure out the problem
/// This macro pulls from the JB2A list of Magic Missiles to throw 1 random path at targeted tokens
//folder01 targets the Magic Missile Folder
let folder01 = "modules/jb2a_patreon/Library/1st_Level/Magic_Missile/";
//Each file is then defined as a variable that will be stored in an array and then chose at random
let mmA = `${folder01}MagicMissile_01_Regular_Purple_30ft_01_1600x400.webm`;
let mmB = `${folder01}MagicMissile_01_Regular_Purple_30ft_02_1600x400.webm`;
let mmC = `${folder01}MagicMissile_01_Regular_Purple_30ft_03_1600x400.webm`;
let mmD = `${folder01}MagicMissile_01_Regular_Purple_30ft_04_1600x400.webm`;
let mmE = `${folder01}MagicMissile_01_Regular_Purple_30ft_05_1600x400.webm`;
let mmF = `${folder01}MagicMissile_01_Regular_Purple_30ft_06_1600x400.webm`;
let mmG = `${folder01}MagicMissile_01_Regular_Purple_30ft_07_1600x400.webm`;
let mmH = `${folder01}MagicMissile_01_Regular_Purple_30ft_08_1600x400.webm`;
let mmI = `${folder01}MagicMissile_01_Regular_Purple_30ft_09_1600x400.webm`;
let mmAA = `${folder01}MagicMissile_01_Regular_Purple_60ft_01_2800x400.webm`;
let mmBB = `${folder01}MagicMissile_01_Regular_Purple_60ft_02_2800x400.webm`;
let mmCC = `${folder01}MagicMissile_01_Regular_Purple_60ft_03_2800x400.webm`;
let mmDD = `${folder01}MagicMissile_01_Regular_Purple_60ft_04_2800x400.webm`;
let mmEE = `${folder01}MagicMissile_01_Regular_Purple_60ft_05_2800x400.webm`;
let mmFF = `${folder01}MagicMissile_01_Regular_Purple_60ft_06_2800x400.webm`;
let mmGG = `${folder01}MagicMissile_01_Regular_Purple_60ft_07_2800x400.webm`;
let mmHH = `${folder01}MagicMissile_01_Regular_Purple_60ft_08_2800x400.webm`;
let mmII = `${folder01}MagicMissile_01_Regular_Purple_60ft_09_2800x400.webm`;
///Check if Module dependencies are installed or returns an error to the user
if (!canvas.fxmaster) ui.notifications.error("This macro depends on the FXMaster module. Make sure it is installed and enabled");
if(game.user.targets.size == 0) ui.notifications.error('You must target at least one token');
if(canvas.tokens.controlled.length == 0) ui.notifications.error("Please select your token");
function random_itemA(itemsA)
{
return itemsA[Math.floor(Math.random()*itemsA.length)];
}
var itemsA = [mmA, mmB, mmC, mmD, mmE, mmF, mmG, mmH, mmI];
function random_itemB(itemsB)
{
return itemsB[Math.floor(Math.random()*itemsB.length)];
}
var itemsB = [mmAA, mmBB, mmCC, mmDD, mmEE, mmFF, mmGG, mmHH, mmII];
const wait = (delay) => new Promise((resolve) => setTimeout(resolve, delay))
async function Cast() {
var myStringArray = Array.from(game.user.targets)[0];
var arrayLength = game.user.targets.size;
for (var i = 0; i < arrayLength; i++) {
let mainTarget = Array.from(game.user.targets)[i];
let myToken = canvas.tokens.controlled [0];
let ray = new Ray(myToken.center, mainTarget.center);
let anDeg = -(ray.angle * 57.3);
let anDist = ray.distance;
let anFile = random_itemA(itemsA);
let anFileSize = 1200;
let anchorX = 0.125;
switch(true){
case (anDist<1800):
anFileSize = 1200;
anFile = random_itemA(itemsA);
anchorX = 0.125;
break;
default:
anFileSize = 2400;
anFile = random_itemB(itemsB);
anchorX = 0.071;
break;
}
let anScale = anDist / anFileSize;
let anScaleY = anScale;
if (anDist<=600){anScaleY = 0.5}
if (anDist>600 && anDist <1000){anScaleY = 0.66}
if (anDist>=1000 && anDist <1800){anScaleY = anScale}
if (anDist>=1800 && anDist <2400){anScaleY = 0.8}
if (anDist>=2400){anScaleY = anScale}
let spellAnim =
{
file: anFile,
position: myToken.center,
anchor: {
x: anchorX,
y: 0.5
},
angle: anDeg,
scale: {
x: anScale,
y: anScaleY
}
};
canvas.fxmaster.playVideo(spellAnim);
await wait (80);
game.socket.emit('module.fxmaster', spellAnim);
await wait (50);
}
}
Cast()
Interestingly, the macro you shared doesn't work for me either. However, it seems to be identical to JB2A's macro that I used. I think something may have gone wrong while copying. I don't have much time today either, but I can share the macro that I positively know works. This already has the changed line to make it work with Mob Attack Tool. Let me know if it works for you! And good luck with that work issue, of course.
/// This macro pulls from the JB2A list of Magic Missiles to throw 1 random path at targeted tokens
//folder01 targets the Magic Missile Folder
let folder01 = "modules/JB2A_DnD5e/Library/1st_Level/Magic_Missile/";
//Each file is then defined as a variable that will be stored in an array and then chose at random
let mmA = `${folder01}MagicMissile_01_Regular_Purple_30ft_01_1600x400.webm`;
let mmB = `${folder01}MagicMissile_01_Regular_Purple_30ft_02_1600x400.webm`;
let mmC = `${folder01}MagicMissile_01_Regular_Purple_30ft_03_1600x400.webm`;
let mmD = `${folder01}MagicMissile_01_Regular_Purple_30ft_04_1600x400.webm`;
let mmE = `${folder01}MagicMissile_01_Regular_Purple_30ft_05_1600x400.webm`;
let mmF = `${folder01}MagicMissile_01_Regular_Purple_30ft_06_1600x400.webm`;
let mmG = `${folder01}MagicMissile_01_Regular_Purple_30ft_07_1600x400.webm`;
let mmH = `${folder01}MagicMissile_01_Regular_Purple_30ft_08_1600x400.webm`;
let mmI = `${folder01}MagicMissile_01_Regular_Purple_30ft_09_1600x400.webm`;
let mmAA = `${folder01}MagicMissile_01_Regular_Purple_60ft_01_2800x400.webm`;
let mmBB = `${folder01}MagicMissile_01_Regular_Purple_60ft_02_2800x400.webm`;
let mmCC = `${folder01}MagicMissile_01_Regular_Purple_60ft_03_2800x400.webm`;
let mmDD = `${folder01}MagicMissile_01_Regular_Purple_60ft_04_2800x400.webm`;
let mmEE = `${folder01}MagicMissile_01_Regular_Purple_60ft_05_2800x400.webm`;
let mmFF = `${folder01}MagicMissile_01_Regular_Purple_60ft_06_2800x400.webm`;
let mmGG = `${folder01}MagicMissile_01_Regular_Purple_60ft_07_2800x400.webm`;
let mmHH = `${folder01}MagicMissile_01_Regular_Purple_60ft_08_2800x400.webm`;
let mmII = `${folder01}MagicMissile_01_Regular_Purple_60ft_09_2800x400.webm`;
///Check if Module dependencies are installed or returns an error to the user
if (!canvas.fxmaster) ui.notifications.error("This macro depends on the FXMaster module. Make sure it is installed and enabled");
if(game.user.targets.size == 0) ui.notifications.error('You must target at least one token');
if(canvas.tokens.controlled.length == 0) ui.notifications.error("Please select your token");
function random_itemA(itemsA)
{
return itemsA[Math.floor(Math.random()*itemsA.length)];
}
var itemsA = [mmA, mmB, mmC, mmD, mmE, mmF, mmG, mmH, mmI];
function random_itemB(itemsB)
{
return itemsB[Math.floor(Math.random()*itemsB.length)];
}
var itemsB = [mmAA, mmBB, mmCC, mmDD, mmEE, mmFF, mmGG, mmHH, mmII];
const wait = (delay) => new Promise((resolve) => setTimeout(resolve, delay))
async function Cast() {
var myStringArray = Array.from(game.user.targets)[0];
var arrayLength = game.user.targets.size;
for (var i = 0; i < arrayLength; i++) {
let mainTarget = Array.from(game.user.targets)[i];
let myToken = canvas.tokens.get(args[0].tokenId);
let ray = new Ray(myToken.center, mainTarget.center);
let anDeg = -(ray.angle * 57.3);
let anDist = ray.distance;
let anFile = random_itemA(itemsA);
let anFileSize = 1200;
let anchorX = 0.125;
switch(true){
case (anDist<1800):
anFileSize = 1200;
anFile = random_itemA(itemsA);
anchorX = 0.125;
break;
default:
anFileSize = 2400;
anFile = random_itemB(itemsB);
anchorX = 0.071;
break;
}
let anScale = anDist / anFileSize;
let anScaleY = anScale;
if (anDist<=600){anScaleY = 0.5}
if (anDist>600 && anDist <1000){anScaleY = 0.66}
if (anDist>=1000 && anDist <1800){anScaleY = anScale}
if (anDist>=1800 && anDist <2400){anScaleY = 0.8}
if (anDist>=2400){anScaleY = anScale}
let spellAnim =
{
file: anFile,
position: myToken.center,
anchor: {
x: anchorX,
y: 0.5
},
angle: anDeg,
scale: {
x: anScale,
y: anScaleY
}
};
canvas.fxmaster.playVideo(spellAnim);
await wait (80);
game.socket.emit('module.fxmaster', spellAnim);
await wait (50);
}
}
Cast()
That macro works! But with one tweak...apparently, the newest build of FXMaster broke all the JBA2 macros. I had to dig through some discord channels to figure this out, but it should work with this hack which Otigon, the Automated Animations dev, suggested.
Replace:
canvas.fxmaster.playVideo(/stuff)
with
canvas.specials.playVideo(/stuff)
Nice ! I'll hop into the conversation to say that Otigon's Automated Animations module Github describes how to call for animations like so : Here is the link to the Github : https://github.com/otigon/automated-jb2a-animations And the link to our JB2A Discord where you can ping @Otigon for further details if needed : https://discord.gg/gmd8MAPX4m Thanks for doing this, it's awesome !
As of the freshly released version 0.2.19, Mob Attack Tool supports Automated Animations. It's really cool to trigger dozens of animations at once (if your computer can handle it 😅 )!
I've also fixed the number of times that On Use Macro's are called. It now matches the number of successful attacks. Could you please update to v0.2.19 and tell me if you run into any bugs related to this? That'd be great :)
I'll need to play around with it a bit more, but my initial quick testing suggests it's working as intended!
https://user-images.githubusercontent.com/575279/124028795-05d63180-d9ba-11eb-9558-3427d176bc55.mp4
Me, just pushing the limits a little bit.
https://user-images.githubusercontent.com/575279/124059054-143f4000-d9f0-11eb-9fa7-24a5ff6dc637.mp4
That looks great! My poor Macbook Air would be burning a hole in my lap if I tried that too often, haha. In any case, I think this issue is ready to be closed. If related bugs do pop up in the future, please reopen this issue again. Cheers!
This is obviously not even remotely "core" or an MVP feature, but on use macros like MIDQOL doeswould open up the doors for some interesting use cases.
Imagine a group of archers firing at an actor each using the JB2A arrow animation (you can see it here) to get that "volley of arrows" effect.
This really is a fantastic module. I don't expect to see my enhancement soon (or even ever), but figured I'd mention it.