#Custom Wild Magic Surge
1 messages ยท Page 1 of 1 (latest)
My game is tonight, so I can't do it right now, but I'll check it out during the week end !
Hm, how do I check that a WM was triggered ? Is just checking the result of the handler with .table enough ?
Yea, I still haven't fixed the return info
But a table does indicate a surge occured
Wait no, I need a post run, actually, since I'm defining the handler.
You can call the base handler for most of the work
Just change the target or roll value
In the script above, you see this exact process
Oh yeah.
How do you think I should store the information of the current threshold for an actor ? Directly in the actor ?
Resource pool could be used by something else.
That set property call above is doing that
Yea, a flag would be easy too
You can set it yourself or include it in the actor update field of the surge data
I'm unfamiliar with flag conventions. Should I scope the flag with the module name ?
/* surges on 1d20 <= X + 1, where X is the number of spells without surge since the last surge */
static async buildupHandler(actor, surgeData) {
const targetRoll = actor.getFlag(MODULE.data.name, 'wildMagicBuildupThreshold') ?? 1;
let surgeResult = await WildMagic.templates.handler(actor, surgeData, `${targetRoll}`);
actor.setFlag(MODULE.data.name, 'wildMagicBuildupThreshold', surgeResult.table ? 1 : targetRoll + 1);
return surgeResult;
}
Something like this maybe ?
Oh, really ? ok, world it is.
You won't have access to the MODULE namespace anyway
Isn't 'world' the global scope, though ?
Global to the world, yea, and intended for anything not from a module or the system
Which a world script falls into ๐
I mean, I am writing a pr to your module. My question was how to scope the flag then ^^
Ohhhh
Hmmm
Yea, using the module scope is correct
Sorry, forgot you were doing a PR
Import MODULE like you did initially, ๐
Ill make the PR tomorrow or on Sunday, I don't really want to mess with modules rn when I have session 1 in 1 hour x)
Hehehe, that's a smart move
I'll keep an eye out for it. Hopefully getting some dev time in this weekend with working AC!
Also, grats on having a well made API. Adding a homebrew in 5 lines of code is not something I'm used to.
That's wonderful to hear! I was pretty happy with being able to implement the stock handlers with as little top level code as it was
Flags seem to be broken on master btw. Tried to go back a couple of commits and it didnt fix itself.
https://github.com/trioderegion/dnd5e-helpers/pull/301 PR done, tested locally, seemed to work. Thanks for your help !
awesome! I'll double check the i18n keys as well. Thanks for the contribution!
a new homebrew surge rule in a handful of lines is pretty neat
so happy this api is working out!
@modern crypt Ah, there you are ๐ here is the WMS API thread that has two examples in it (over many many messages, hehe)
@severe nacelle
actually, incremental checks where implemented just above
but dont let me distract you, i'll just leave this here ๐
does it have auto-surge if tides is expended? I think that was the main one
not built in, but it would be an easy add
how easy would it be to trigger that macro Zhell made for me, instead of rolling a table?
cos if I can have the macro trigger, and the auto-surge, then I can do everything in helpers without needing outside stuff
It should be quite easy. Will take a world script to add the handler, but if you look in the scripts/plugins folder on the repo, you will see examples of the core handlers
Which are built using the exact same tools you are provided with
Full control over anything that causes the actor to be modified
I may need help doing it. I actually already use dnd5e helpers for a few other things (like the better diagonals, and I may start using the actions logging) so doing wild magic too would mean I could actually -reduce- my total modules!
from like... 109
to 108
I'm just looking through the plugin/scripts stuff now
this is the one that was developed and merged above: https://github.com/trioderegion/dnd5e-helpers/blob/053c60366ae63aa98d5c43e19aa0e8137c3e0536/scripts/plugins/wild-magic-surge.js#L47
so that seems to be what I wanted (mostly?) in that it is adding to the rolls if tides is discharged. Which may be enough... though I do think it may be worth just adding a tickbox for the whole wild magic options list that is 'auto surge if tides discharged' that would then work no matter what surge rules you were using. Just a thought. As a lot of DMs seem to use the rule where a surge always happens if tides is empty (or so it seems)
but how would I set up triggering a macro, instead of rolling on the table? That doesn't seem to be in that document (that I'm seeing)
after the v10 upgrade i can revisit things like that ๐
you would null out the table field in the return value (surgeResult), so the system doesnt roll it, and instead of using a macro, just put the code in right there
oh sure, I mean short term I can probably just make one of the options tidesCharged ? '' : ' + 1d20'} so it always triggers, I was just thinking for the future
just set surgeresult.surge to true if tides is charged
shouldnt even need the surge roll handler in that case
I might be being blind, but im not seeing the table field
you would breakpoint in that function, im not sure how well that ret value is documented...1 sec
that's the ret val
is the table in another js file? This one seems to return a value for surgeresult
the table is a table ID or UUID
oh no I meant the table field I needed to edit / delete / perform some kind of black magic upon
surgeResults.table = null
results.table = {
uuid: table?.uuid
}
This part, ok
not in the helpers code
in your plugin code
but yea, that's where i create the field on my side
oh, thats what confused me, cos the handler the other person did didn't have a results.table section
right, yea, they just let the default behavior go
simply modified the target based on the flag
yeh, while I'm happy with the default roll options, but want to add auto-surge and change the table-roll to a macro. So I'm :confused business dog at keyboard:
if (surgeResult.table) {
setProperty(surgeResult, 'actorUpdates.data.resources.secondary.value', 0)
} else {
const newValue = actor.data.data.resources.secondary.value + surgeData.spellLevel
setProperty(surgeResult, 'actorUpdates.data.resources.secondary.value', newValue)
}
Is there anything in this section that is actually necessary for my purposes? As far as I can see, its all related to adding or resetting their secondary resource (which I believe was where they stored their incremental tally)
that looks about right, log out the final surgeResult before returning, to double check
sorry, I meant that I was going to remove those lines entirely, not keep them (unless that's what you meant)
let surgeResult =
what value should this be to force a surge? I can't figure it out from the example
class WildMagicSurge {
static init() {
/* When called on by the WildMagic utility, register our surge handlers and pre checks */
Hooks.on('wmsRegister', () => {
/* use our modified inputs for the homebrew variants */
WildMagic.registerHandler('Soul Music', WildMagicSurge.soulHandler);
ui.notifications.notify("Hear the Music!");
});
}
/* surges on 1d20 <= spell level*/
static async soulHandler(actor, surgeData) {
/* increase the spell level by resource factor */
const targetRoll = `${surgeData.spellLevel}`
const surgeRoll = `1d20`
const tidesCharged = WildMagic.isTidesCharged(actor);
if (tidesCharged = true) {
let surgeResult = await WildMagic.templates.handler(actor, surgeData, targetRoll, surgeRoll);
}
else {
let surgeResult =
}
/* if (surgeResult.table) {
setProperty(surgeResult, 'actorUpdates.data.resources.secondary.value', 0)
} else {
const newValue = actor.data.data.resources.secondary.value + surgeData.spellLevel
setProperty(surgeResult, 'actorUpdates.data.resources.secondary.value', newValue)
} */
return surgeResult
}
}
/* When the WildMagic utility is ready, we can use its helpers
* and register ourselves */
Hooks.on('helpersReady', WildMagicSurge.init)
About as far as I could figure out lol. I don't even know if tidesCharged returns as true/false or something else entirely
Ha, I didn't know you could format discord as js. TIL
ahh yes
but what does surgeResult need to be to force a surge? I haven't been able to figure that out
I'll take another look at it tomorrow ๐
On another subject (as I'm currently working my way through my v10 compatibility list) I'm sure you get this all the time, but I was just curious if Squadron v10 was in the works? I only just installed it, but it's so good I already am not sure I would update to v10 without it lol
yes, but its still going to be a couple weeks
No rush, I probably won't update until Drag Ruler and Item Piles gets updated too anyway. I don't see how people play foundry without drag ruler !
(easily, hehe)
Needing a keyboard to move isn't great, at least not for my players who usually play while lounging on the sofa with their mouse
I dunno if core changed the controls since I last tried it though. I installed drag early on and never looked back
shrug couldnt say ๐
@copper mortar unlocked now?
Ok so I understand how I would register a custom handler using a hook in a world script, how would I add the custom class as well?
which custom class?
the handler class
oh, world script
right, what does adding a class look like? I know what catching a hook looks like. would i just add this to the world script?
static async myCustomHandler(actor, surgeData) {
// doing stuff
return surgeResult;
}
it would look similar to this, though more simple https://github.com/trioderegion/dnd5e-helpers/blob/master/scripts/plugins/wild-magic-surge.js
i implemented the helpers wild magic surge with its own API to serve as an example ๐ everything but that top import {MODULE}
oh sorry, I misread that. The class is WildMagicSurge , the handler is a function, my b.
So could i just add this to my world script and it'll add my custom handler to the class?
class WildMagicSurge {
static async myCustomHandler(actor, surgeData) {
// doing stuff
return surgeResult;
}
}
adding the stuff to the hook to register I understand, just unsure about what adding a function looks like
it would look like line 22, for example
WildMagic is the global namespace available after the helpersReady hook
yeah, thats the registering of the handler. I get that bit. how am I adding my custom function?
๐ค hmm, im not following
by registering the handler, the system takes it from there
lemme send a screenshot of my worldscript to give beter context
50-54 are registering the handler, 56-61 is where the code for that handler goes?
the myCustomHandler function is where all your logic goes, yea
making as much use of the WildMagic.templates functions as you can
API documented here: https://trioderegion.github.io/dnd5e-helpers/WildMagicAPI.templates.html#.handler
yeah, it will likely be very similar to the existing buildup handler, I just wanted to make sure the syntax for that function is correct in the worldscript. Just seems odd to me for some reason that I'm writing a function to a class that already exists by adding the class itself to the worldscript
oh, WildMagicSurge is just a local symbol in that plugin file I linked
you could call your class anything
the WildMagic symbol, however, is a global symbol provided by helpers to access its API
OHH, so I'm just writing a function inside a nothing class thats getting called by the wildmagicsurge handler? Do I even need the Class bit then? could I just write an orphan function?
you very much could write it as a free function, yep
my implementation had a bit more to it, so i opted for a slightly stricter organization
Ohh, so do world scripts just append all this code into the source? the implementation of it is new to me. You'd think I mightve been taught these things while studying computer science, but i guess scripting is just really different from OOP
world scripts are loaded akin to modules -- they are just world-specific
loaded into memory and executed
Ok yeah, just dont have a ton of experience with app building, so learning a lot here. thanks ๐ I'll come back if I have any questions implementing this
looks like you got a pretty good start, good luck!
is it feasible to add a dialog box within the handler to ask for special modifiers?
Yea, pretty sure they are async aware
okay i definitely dont know how to do this bit, I wrote code that should work in theory, but I dont know how to put my dialog box callback at the front of the queue to prevent the rest of the handler from running until i get a response
it basically, properly pulling up the dialog, but by the time the dialog has loaded, the code moves on and i'm getting errors because the variables I want to set with the dialog box aren't set yet
basically I dont know where to put "await" when it comes to dialog boxes
ooo, that one is much much easier in v10. Search #macro-polo for Dialog.prompt, Dialog.confirm, or Dialog.wait
@copper mortar
yeah, figured it out, ty
I was not expecting there to be a thread for the specific macro I wanted to make
nice
the topic has come up a few times and having this thread is handy reference ๐
several examples right here
so for example if I had the module and wanted a macro that just rolls on a custom wild magic table, I'd use surge([whatever the alias is for currently selected actor]) in it and change the settings of the module to target a different roll table I've made?
if i were to rephrase: you want a specific actor to use an alternate surge table rather than the one defined in the module options?
Yes
I actually also found https://github.com/johnnolan/wild-magic-surge-5e which has all the flexibility I need
Issue is figuring out how to trigger it with a macro instead of spells
the contacts lists the makers discord tag as JB#2780, but there doesn't seem to be anyone with that account name here
found them
And I don't think it is working. I tested the my-script.js file as far as I could in the console. When I load the edited world and my-script files I still see character casting via Tides of Chaos in the console window, and none of the console log stuff nor chatmessage stuff shows up. I suspect that my lack of knowledge is a root cause. The my-script.js file is saved in same folder as the world.json. I have attached the world.json and my-script.js files. Have now verified that the world.json is not the issue. Help Please!
im not really at a place i can dig through this too much, but the world manifest looks right, i do see a potential error when you are registering the handler:
WildMagic.registerHandler('BrokenSurges', WildMagicSurge.BrokenSurges);
I think you want that to just be BrokenSurges, which is the name of your function, below
mmmm
or im confused and read the indents wrong
you can remove all of that class wrapping you are doing
define your init function and your BrokenSurges functions individually
and pass the init function to the helper init hook like you are doing currently
that will at least simplify things
OH
yea, unwrapping would have helped, so i recommend doing that
Trying that now.
'ready' fires well after helpersReady
just have your init called from helpersReady
.....unless indentation got me AGAIN lolol, sorry
Its all good. I tried removing the wrapper. Still doesn't seem to work. But I also can't very well ask you to troubleshoot when you are busy. If I can't beat in to shape I will follow up tomorrow.
I have noticed that under special traits on character sheet I can't assign my wildmagicsurge variant which could be part of the problem.
go ahead and post the updated version when you get a chance, and you are 100% correct that the absence of your entry means something high level didnt quite work
i'll try to take a look at it over coffee tomorrow morning ๐ its been a while since ive used this code, personally, so I could be missing something
return values from the handlers could be one thing, just offhand ๐คทโโ๏ธ
Thanks! And now off to store. If I don't make dinner soon both roommate and girlfriend will be very sad.
Apparently store already closed. Guess I am making backup plan leftovers for dinner. ๐คฃ Also realized image I pasted was wrong folder.
And giving up for the night. Only changes are to the my-script.js function. Uploading current version and doing something non code until brian fog clears.
here we go, this is one issue
Hooks.on('helpersReady', WildMagicSurge.init)
i was likely reading from the wrong source code (old v9 helper's version)
the hook name is simbulsReady
@turbid barn
Still does not seem to be working.
In that It does not get as far as giving option for custom wild surge variant.
oh
there is another small one
that same line
WildMagicSurge.init, you are calling the core init function (already called). You want to call your init function, which is just init
and remove the static declarations from your functions
replace with function or async function
Also changed line 10 and it now loads and gives broken surges as an option. However it does not like the for loops I am using starting in line 40 for list comparison. Gives error variable ar is not defined. I assume I need to fix syntax on the for loops, or there may be a more efficient way to do list matching in this environment.
JS needs its variables declared, so similar to your outer for loop, for (const variable of list)
or for...in in this specific case
Gotcha. And I am used to python which would have a different form entirely for most of my commands. Looks like javascript prefers while statements for parsing lists.
Lets see if this fixes it.
mmmm, no no, i mean, a for loop is fine
one thing, change those var declarations to let if mutable, or const if read-only
and comparing objects directly is not usually what you wanna do
Fair. I just looked at some quick .js tutorials on list parsing. However it looks my declaration for casting mod is still an issue in that it parses it as a string?it is a string rather than an int?
for example:
for (ar in arcaneClass) {
/* breaks if there is no subclass
if (testClass == arcaneClass[i] || subClass == arcaneClass[i])
*/
if (testClass == arcaneClass[ar]) {
multiplier = 2;
console.log("matched arcane");
}
}
is better written
const hasArcane = arcaneClass.some( name => name == testClass)
nevermind, testClass was a string, not an object
let castingMod = actor.system.abilities[testClass].mod;
there is no ability with ID == testClass
abilities are 'str', 'dex', etc
That may be a more elegant /compact solution. I am going with the assumption that a given character could have multiple classes to parse. Ideally I would like to parse subclasses as well but am unsure how to handle cases where character is too low a level to have subclasses. The ideal flow for it is 1)generate list of subclass /class (probably only test subclass if length of list >0), 2) set multiplier based on list matches (lowest mult will be retained), 3)determine casting mod based on lowest multiplier classes stat, 4) roll vs DC and pass off for calculation.
i would use Array#filter to extract class and subclass items from the actor's items list
then convert those to class identifier strings via Array#map
the class identifiers are probably what you want to pay attention to
it would also help if you defined your arcane class names by the identifiers, rather than the item's name
I will Google a tutorial on that when I get home. I am not familiar with array#filter or Reay#map. When you say identifiers, what do you mean? The only way I could find to search was using tbr actor object. In a perfect world this function would know which classes spell slot uas used to cast but I suspect that would involve a lot more under the hood.
identifier is a property of a class item that defines the "key" for this class
subclasses link to their main class via this identifier
e.g. the "Wizard" class item in the srd has an identifier of wizard
Is there a simple way to query for an existing list of class keys from the console? It would be less cumbersome than building an npc of each class and testing manually.
the identifiers are 100% arbitrary
as in, you can change them to be whatever, even the SRD classes
so you would instead define your arcane classes based on the class identifiers you are using
That would simplify. And then just use filter to see if key is in list.
Still fighting with it. On upside probably learning more .js in the process. On downside, still have not beat it.
so that means somewhere in your code, you are accessing the system property of an undefined object (likely actor)
log out any variables using that system property and check for nulls
backtrack to figure out why its null
or do something like if (someVariable == undefined) console.log('Foo')
oh, there it is
let testClass = (charClasses[key].name);
/*if class in question grants spellcasting
and if we have a multiplier of >2
see if we have arcane caster*/
if (testClass.system.spellcasting.prog
testClass is a string
strings dont have a system property
Heh. Just ran into that one and was waitingg for a foundry reload before posting as root cause (for fear that it isn't).
and found the problem, but not the solution. the only way I have found to query for character classes is actor._classes. when I try to do a .keys() on it I get an error. Is there another way to extract the class names/subclass data?
dont dig into underscore variables
you can either filter the items collection, or maybe actor.itemTypes.class, maybe
here is some examples of item filtering
and a lot of the examples on that wiki use filter, map, reduce etc
so => is the command to search for items matching a type?
No, that is syntax for arrow functions
Filter is the array function to use
You send it a function to evaluate against
May need to do a lot more tutorials to get fluent in this. I don't think arrows exist as a concept in python. ๐คฃ On upside I now have it at the point where I think I am one line of understanding short of it working.
Works fine until it passes final string to handler to evaluate...then things get a bit wonky.
Making progress!!
But yeah, arrow functions are just shorthand for the more explicit async function etc etc. They have a few additional properties but are very handy. Highly recommend reading the MDN article on it
Getting 'logger.js:14 simbuls-wild-surges | ERROR | TypeError: roll.evaluate is not a function
at convertEval (DnDWildMagic.js:490:20)
at Object.commonSurgeHandler [as handler] (DnDWildMagic.js:497:32)
at async BrokenSurges (my-script.js:97:23)
at async DnDWildMagic._runHandler (DnDWildMagic.js:328:23)'
I suspect it is from passing it 1d20 +3 +2 in the form of j'''
let targetRoll = 10 + ${surgeData.spellLevel} * multiplier
/set up a surge roll/
let surgeRoll = 1d20 +${castingMod} +${prof}
console.log(prof);
console.log(castingMod)
console.log(targetRoll);
console.log(surgeRoll)
await ChatMessage.create({ content: ${surgeRoll} vs ${targetRoll} DC to cast spell});
let surgeResult = await WildMagic.templates.handler(actor, surgeData, targetRoll, surgeRoll)
return (surgeResult)
I need to step away for a bit, but you can place break points in your code by opening up the dev tools in your browser. I would put a breakpoint right at the top of the function that's breaking and just stepping through it. Looking at each variable as you go. That should both help find the problem quickly. And give you a lot of context
Here is most recent version with breakpoints dropped in starting at line 94. I suspect the formatting for either targetRoll or surgeRoll is what is breaking it. Code for my matching is a bit fugly but that is a tomorrow problem.
there it is, the console shows us, we just need to see what its saying
you see that TargetRoll output? and the SurgeRoll output?
TargetRoll is a number
not a string
look in your code where you are creating target roll and compare it to surgeroll
๐ค I was trying to figure out how to force SurgeRoll to be a nubmer as that is what I thought the module wanted. Ooops. It now runs.
Next step I figure out how to cancel spells and roll on wild magic table when surges occur.
Think I got a solution from past mesages in this gorup
depends on how you want to cancel, but rolling on a given table is handled by a return value from one of the handlers
results.table
you can give both actor and item updates as part of the return https://github.com/vtt-lair/simbuls-wild-surges/blob/fc0403561d02b67e7b941234e9ea16a968dde801/scripts/modules/DnDWildMagic.js#L499
since you are using the template handler, you can modify its return value as well if you dont want to generate the whole thing yourself
Will have to take a look at this tomorrow or later tonight. Time to start a grill.
Thai style dish kind of night you know?
gib
So if I understand I just rewrite the common surge handler function in my world script with the table I want to roll on and the dice I want to use to roll on that table?
shakes head i dont think that's needed
just take its normal return value and modify it to suit your needs
i.e. replacing the table uuid to indicate a table roll is needed
Ie I can put the uuid into the helper function directly?
call the handler like you are, capture its return value, modify its return value
and return that
so something like if(surgeResult.surge)==true{ // update chat content to fit my needs}
yea! thats the correct direction -- if you havent already, log out the return value from the template handler
it contains a bunch of information about what happened, and then you can inspect and modify as needed
already logged. Have a crude version working, just trying to streamline the chat .
but lets fix that syntax if (!!surgeResult.surge)
just a little more compact and expressive
"if we have a non false result from surging"
Ah. So that is the js convention. And presumably for true if (surgeResult.surge)
oops. meant if false (!surgeResult.surge)
Well that is done. Tomorrow I add reloads and potential misfires to firearms and finish off custom rule automation for the game world (at least for now)
Definitely. Prior to this I had zero javascript experience. I still expect that most of what I do will focus more on Python, but never know when a new skill will prove useful at work.
100% -- im finding nodejs scripts to be as easy...if not easier than throwing together a python script....
the package management environment alone is almost worth it
(npm)
Hi everyone. What is the situation with Wild Magic Surge? Can somebody please tell me what works well for you?
Meanwhile, I send a PR with fix for Wild Magic Surge 5e.
Does anyone know how to reach JB#2780?
unsure, really -- this thread was for Simbul's Wild Surge plugins ๐
Oh. My bad. How well it works? What is the difference?
i dont have a ton of insight as to its current state (i wrote the original module and plugin system) with dnd5e 4.x, but i think the 2014 stock version of wild magic surge (no interaction with Tides of Chaos) should still mostly work -- but im sure there are issues here and there
so far so good, now define your targetRoll
i.e. what the d20 is compared against
it may just be spellLevel from the surgeData
yep
good to go
almost done
so now, we have all the info that the stock handler needs (and you are basically doing a normal surge, just modified targets)
so next line is to call the stock handler:
let surgeResult = await WildMagic.templates.handler(actor, surgeData, targetRoll, surgeRoll);
(I don't know how to do the formatting for coding on discord)
/* surges on 1d20 <= spell level, reduced by number of charges */
static async faeHandler(actor, surgeData) {
/* increase the spell level by resource factor */
const targetRoll = `${surgeData.spellLevel}`
const surgeRoll = `1d20 - ${actor.data.data.resources.secondary.value}`
let surgeResult = await WildMagic.templates.handler(actor, surgeData, targetRoll, surgeRoll);
missed a closing backtick on targetRoll
/* surges on 1d20 <= spell level, reduced by number of charges */
static async faeHandler(actor, surgeData) {
/* increase the spell level by resource factor */
const targetRoll = `${surgeData.spellLevel}`
const surgeRoll = `1d20 - ${actor.data.data.resources.secondary.value}`
let surgeResult = await WildMagic.templates.handler(actor, surgeData, targetRoll, surgeRoll);
Aye
just checking the core code
So input this into the world file and edit the special traits under the character?
make sure its inside the "MyCoolClassName" class
but, last thing to do...
surgeResult.chatData.surgeOccured indicates if it surged
so check that result, and if true, we need to reset the resource counter
And if false, add surgeData to resource counter
precisely
surgeResult.actorUpdate is an update object that will be applied to the actor
so all you need to do is add in your update to that object for the resource
something like
setProperty(surgeResult.actorUpdate, 'data.resources.secondary.value', newValue)
then just return that surge result object and party!
Where would that go? Sorry I'm a little lost
after you call the template.handler function
After return, then?
if (surgeResult.chatData.surgeOccured)
not after return, we need to modify that surgeResult data before returning it
let surgeResult = ...
if (surgeResult.chatData.surgeOccured) {
//
} else {
//
}
return surgeResult
newValue would be surgeData?
newValue is whatever the new value for the secondary resource is now
you are telling the wild magic system what to change on the actor for this surge
So data.resources.secondary.value + surgeData?
Adding the spell level to the pre-existing value?
surgeData is an object
surgeData.spellLevel however, is a number ๐
you need to grab the previous value first
i.e. compute the full value, then use setProperty
You're... speaking eldritch now, sorry
Like, I understand what I must do, but I have no idea how
const newValue = actor.data.data.resources.secondary.value + surgeData.spellLevel
let surgeResult = await WildMagic.templates.handler(actor, surgeData, targetRoll, surgeRoll);
if (surgeResult.chatData.surgeOccured) {
//
} else
const newValue = actor.data.data.resources.secondary.value + surgeData.spellLevel
{setProperty(surgeResult.actorUpdate, 'data.resources.secondary.value', newValue)
//
}
return surgeResult
return WildMagic.templates.handler(actor, surgeData, targetRoll);
the syntax there isnt quite right and you are returning twice ๐คฃ one sec
let surgeResult = await WildMagic.templates.handler(actor, surgeData, targetRoll, surgeRoll);
if (surgeResult.chatData.surgeOccured) {
setProperty(surgeResult.actorUpdate, 'data.resources.secondary.value', 0)
} else {
const newValue = actor.data.data.resources.secondary.value + surgeData.spellLevel
setProperty(surgeResult.actorUpdate, 'data.resources.secondary.value', newValue)
}
return surgeResult
forgive the formatting
Bold of you to assume I can tell that it's bad
return surgeResult
I can include this in the final return together with the other properties (actor, surgeData, etc), right?
/* surges on 1d20 <= spell level, reduced by number of charges */
static async faeHandler(actor, surgeData) {
/* increase the spell level by resource factor */
const targetRoll = `${surgeData.spellLevel}`
const surgeRoll = `1d20 - ${actor.data.data.resources.secondary.value}`
let surgeResult = await WildMagic.templates.handler(actor, surgeData, targetRoll, surgeRoll);
if (surgeResult.chatData.surgeOccured) {
setProperty(surgeResult.actorUpdate, 'data.resources.secondary.value', 0)
} else {
const newValue = actor.data.data.resources.secondary.value + surgeData.spellLevel
setProperty(surgeResult.actorUpdate, 'data.resources.secondary.value', newValue)
}
return surgeResult
that looks right!
Let's spin those wheels then
now, only thing you need to do is substitute that in the register call
can you show me the register call you have now?
or just the whole script, actually
I've co-opted the script you sent earlier so
yep, just to make sure im looking at the right thing with all the changes
It's tiny but it's too many words for my humble discordness
delete the other 2 handler functions in there
and delete all the other registerHandler calls except yours
Doney
lets have a final look-see
// This example greets players with an on-screen notification once Foundry
// has finished its initial loading
Hooks.on("ready", () => ui.notifications.notify("Welcome to the World!"));
class WildMagicSurge {
static init() {
/* When called on by the WildMagic utility, register our surge handlers and pre checks */
Hooks.on('wmsRegister', () => {
/* Using the core "is slot expended?" preCheck for all variants (default, 3rd argument) */
/* use the core, default implementation for the PHB surge 1d20 == 1 */
WildMagic.registerHandler(game.i18n.localize("option.wmOptions.standard"), WildMagic.templates.handler);
/* use our modified inputs for the homebrew variants */
WildMagic.registerHandler(game.i18n.localize("option.wmOptions.fae"), WildMagicSurge.faeHandler);
});
}
/* surges on 1d20 <= spell level, reduced by number of charges */
static async faeHandler(actor, surgeData) {
/* increase the spell level by resource factor */
const targetRoll = `${surgeData.spellLevel}`
const surgeRoll = `1d20 - ${actor.data.data.resources.secondary.value}`
let surgeResult = await WildMagic.templates.handler(actor, surgeData, targetRoll, surgeRoll);
if (surgeResult.chatData.surgeOccured) {
setProperty(surgeResult.actorUpdate, 'data.resources.secondary.value', 0)
} else {
const newValue = actor.data.data.resources.secondary.value + surgeData.spellLevel
setProperty(surgeResult.actorUpdate, 'data.resources.secondary.value', newValue)
}
return surgeResult
}
}
/* When the WildMagic utility is ready, we can use its helpers
* and register ourselves */
Hooks.on('helpersReady', WildMagicSurge.init)
Fits here now
remove the standard register handler
and give this an actual string - game.i18n.localize("option.wmOptions.fae")
Very clean of you
because i dont have a translation string for that key
What does giving a string mean
that is the name of the handler that will show up in the special traits
so call it whatever it should be named like 'Fae Surges' or something
that would call my template handler ๐
Hooks.on('wmsRegister', () => {
/* Using the core "is slot expended?" preCheck for all variants (default, 3rd argument) */
/* use our modified inputs for the homebrew variants */
WildMagic.registerHandler('Fae Surges', WildMagicSurge.faeHandler);
});
boom
save, reload world, watch console for errors and check out the special traits and cast a spell!
๐ค
Nope, it do be borked
oh hmm
// This example greets players with an on-screen notification once Foundry
// has finished its initial loading
Hooks.on("ready", () => ui.notifications.notify("Welcome to the World!"));
class WildMagicSurge {
static init() {
/* When called on by the WildMagic utility, register our surge handlers and pre checks */
Hooks.on('wmsRegister', () => {
/* use our modified inputs for the homebrew variants */
WildMagic.registerHandler('Fae Surges', WildMagicSurge.faeHandler);
});
}
/* surges on 1d20 <= spell level, reduced by number of charges */
static async faeHandler(actor, surgeData) {
/* increase the spell level by resource factor */
const targetRoll = `${surgeData.spellLevel}`
const surgeRoll = `1d20 - ${actor.data.data.resources.secondary.value}`
let surgeResult = await WildMagic.templates.handler(actor, surgeData, targetRoll, surgeRoll);
if (surgeResult.chatData.surgeOccured) {
setProperty(surgeResult.actorUpdate, 'data.resources.secondary.value', 0)
} else {
const newValue = actor.data.data.resources.secondary.value + surgeData.spellLevel
setProperty(surgeResult.actorUpdate, 'data.resources.secondary.value', newValue)
}
return surgeResult
}
}
/* When the WildMagic utility is ready, we can use its helpers
* and register ourselves */
Hooks.on('helpersReady', WildMagicSurge.init)```
It's definitely the script, I think, because the other surges are working
yea, its how we are setting the resource update
one moment
lets try this instead
if (surgeResult.chatData.surgeOccured) {
setProperty(surgeResult, 'actorUpdate.data.resources.secondary.value', 0)
} else {
const newValue = actor.data.data.resources.secondary.value + surgeData.spellLevel
setProperty(surgeResult, 'actorUpdate.data.resources.secondary.value', newValue)
}
moving the actorUpdate object into the set property field
(which is an oversight on my side, not providing an empty actorUpdate field)
It's working for the roll itself
But not updating the resource field
It's not returning any errors though!
So to be entirely honest I don't wanna take up more of your time
ok, lemme put this in on my side and see what's up, im sure the update isn't quite right
As it is is way more than enough from what I thought I could achieve
no no, im glad you are doing this -- ive been needing an example of use like this!
can you re-paste the full script you have?
// This example greets players with an on-screen notification once Foundry
// has finished its initial loading
Hooks.on("ready", () => ui.notifications.notify("Welcome to the World!"));
class WildMagicSurge {
static init() {
/* When called on by the WildMagic utility, register our surge handlers and pre checks */
Hooks.on('wmsRegister', () => {
/* use our modified inputs for the homebrew variants */
WildMagic.registerHandler('Fae Surges', WildMagicSurge.faeHandler);
});
}
/* surges on 1d20 <= spell level, reduced by number of charges */
static async faeHandler(actor, surgeData) {
/* increase the spell level by resource factor */
const targetRoll = `${surgeData.spellLevel}`
const surgeRoll = `1d20 - ${actor.data.data.resources.secondary.value}`
let surgeResult = await WildMagic.templates.handler(actor, surgeData, targetRoll, surgeRoll);
if (surgeResult.chatData.surgeOccured) {
setProperty(surgeResult, 'actorUpdate.data.resources.secondary.value', 0)
} else {
const newValue = actor.data.data.resources.secondary.value + surgeData.spellLevel
setProperty(surgeResult, 'actorUpdate.data.resources.secondary.value', newValue)
}
return surgeResult
}
}
/* When the WildMagic utility is ready, we can use its helpers
* and register ourselves */
Hooks.on('helpersReady', WildMagicSurge.init)
I think I found it
let surgeResult = await WildMagic.templates.handler(actor, surgeData, targetRoll, surgeRoll);
Should be WildMagicSurge.faeHandler
Right?
shakes head
no, we are wrapping the core handler
im digging in, its stuff on my side
The actorUpdate fields are missing a .data from the actual resource values?
nah, they are intended for update, which sits inside the first data
its the "surgeOccured" field
looks like I dont....actually send that back, which is a bug on my side
i'll file an issue and get that fixed, but in the mean-time, we can be a bit tricky
It's alright, the way it's working right now is well enough
And session is in 15 minutes >:D
So absolutely let me know when you figure that out though
class WildMagicSurge {
static init() {
/* When called on by the WildMagic utility, register our surge handlers and pre checks */
Hooks.on('wmsRegister', () => {
/* use our modified inputs for the homebrew variants */
WildMagic.registerHandler('Fae Surges', WildMagicSurge.faeHandler);
ui.notifications.notify("Fae Surges Loaded!");
});
}
/* surges on 1d20 <= spell level, reduced by number of charges */
static async faeHandler(actor, surgeData) {
/* increase the spell level by resource factor */
const targetRoll = `${surgeData.spellLevel}`
const surgeRoll = `1d20 - ${actor.data.data.resources.secondary.value}`
let surgeResult = await WildMagic.templates.handler(actor, surgeData, targetRoll, surgeRoll);
if (surgeResult.table) {
setProperty(surgeResult, 'actorUpdates.data.resources.secondary.value', 0)
} else {
const newValue = actor.data.data.resources.secondary.value + surgeData.spellLevel
setProperty(surgeResult, 'actorUpdates.data.resources.secondary.value', newValue)
}
return surgeResult
}
}
/* When the WildMagic utility is ready, we can use its helpers
* and register ourselves */
Hooks.on('helpersReady', WildMagicSurge.init)
there we go
all fixed up and working ๐
this has given me a couple areas of improvement as well, so I appreciate the willingness to try this out โค๏ธ
shocjked gasp
33 lines for a custom surge implementation isn't too shabby ๐
๐ฅณ