Roll20 uses cookies to improve your experience on our site. Cookies enable you to enjoy certain features, social sharing functionality, and tailor message and display ads to your interests on our site and others. They also help us understand how our site is being used. By continuing to use our site, you consent to our use of cookies. Update your cookie preferences .
×
Create a free account

[Help] Learning to Coding - How to pass var for Global Mods and other items

1595226910

Edited 1595481602
Hello Again Tye here, My GM Game: D&amp;D 5e Sheet: 5e OGL Special Homebrew Note: on Critical Hits the extra die does max damage ( Dungeon Dudes - Better Critical Hits &nbsp;) I have been watching Nick O.'s Youtube videos on coding and his&nbsp; Creating Your Own Magic Missile: A Roll20 API Scripting Tutorial &nbsp;gave me a jump start on making one for Eldritch Blast. One of my players plays Alton a Light-foot Hal-fling Pact of the Fiend Warlock 6,&nbsp; He loves his EB with Hex.&nbsp; He has a Hex 1d6 global damage modifier made.&nbsp; With that said I am looking for the code string to pass to a variable for the following items on my Todo list:&nbsp; (please for give me if I have said or coded something wrong.&nbsp; Google is not very helpful to me 1. because I am not a coder (yet) thus not sure what key words to use. &amp; 2. I want to learn but cannot find any resources to aide me.&nbsp; Hence this post (sorry for the ramble). Look for active (check/ticked) Global Attack Modifiers Look for active (check/ticked) Global Damage Modifiers (i.e. Hex) Look at traits Eldritch Invocation&nbsp;for Spell Modifiers (i.e. Eldritch Invocation: Agonizing Blast (damage mod),&nbsp;&nbsp;Eldritch Spear (range mod), [Grasp of Hadar, Lance of Lethargy, Repelling Blast&nbsp;(description mods)] Code to make Abilities Macro for role type (aka rtype) (i.e.&nbsp;!customSpellbook eb 0 ?{Eldritch Blast Roll Type?|Normal|Advantage|Disadvantage}) Having issues here where chat populates the beam # out of order Look up for spell they ran through API to see if they have it and is prepared (not sure how to do this, will give it a go) Here is my link code thus far: <a href="https://gist.github.com/TooTallTye/52b32e0095a9562741ffd9fc6be0f7e1" rel="nofollow">https://gist.github.com/TooTallTye/52b32e0095a9562741ffd9fc6be0f7e1</a>
1595242804

Edited 1595242941
GiGs
Pro
Sheet Author
API Scripter
That's a lot to take in, and I'm not familiar with the sheet, and this kind of thing is dependent on knowledge of the sheet. But it sounds like you'll need to know the attribute names for each of the sttas you mention. These sound like they come from a repeating section:&nbsp; Eldritch Invocation: Agonizing Blast (damage mod),&nbsp;&nbsp;Eldritch Spear (range mod), [Grasp of Hadar, Lance of Lethargy, Repelling Blast&nbsp; So you'll need a function to search the repeating section and identify the repeating row that a particular spell is in, by searching the name field in each row the section, and then once you have the row you can get the values you need. Your situation is trickier than it could because it looks like you are grabbing the values of multiple different attributes within the section (range mod, damage mod, etc). I dont know how eldritch invocation works, so i have no idea how to go about doing what you need. If you can describe what you need to do, in extremely specific, point by point detail, we can point you in the right direction. (Or some scripter who knows the sheet and how the eldritch invocation ability works might be able to do it much quicker!).
1595264139

Edited 1595264645
Thanks Gigs for the reply. I not really sure what I need. My thought was to 1. create a variables that would store the names of all the names of their traits.&nbsp; Not sure how to code that but thought was var traits = something something in repeating traits area ("name").toLowerCase(); var ebTraits = ""; then some kind of loop looking for each var in 'traits'&nbsp; and you could have more than one Agonizing Blast,( When you cast&nbsp; Eldritch Blast , add your Charisma modifier to the damage it deals on a hit. ) Eldritch Spear, ( When you cast&nbsp; Eldritch Blast , its range is 300 feet.) Grasp of Hadar, ( Once on each of your turns when you hit a creature with your&nbsp; Eldritch Blast , you can move that creature in a straight line 10 feet closer to yourself.) Lance of Lethargy, ( Once on each of your turns when you hit a creature with your&nbsp; Eldritch Blast , you can reduce that creature’s speed by 10 feet until the end of your next turn.) Repelling Blast ( When you hit a creature with&nbsp; Eldritch Blast , you can push the creature up to 10 feet away from you in a straight line.) then if these are found store them in ebTraits then pass ebTraits to through a loop adding appropriate&nbsp;text to the corresponding trait&nbsp; something like&nbsp; //will need to set some variable not already added on org script var damage = "[[1d10]]"; var chr = Number(getAttrByName(charID, 'charisma_mod')); switch(ebTraits){ case "agonizing blast": damage ="[[1d10+${chr}]]"; } functionality I am uncertain but looking for any code of text that would help Thanks, Tye
1595265083
GiGs
Pro
Sheet Author
API Scripter
Tye said: 1. create a variables that would store the names of all the names of their traits.&nbsp; Not sure how to code that but thought was var traits = something something in repeating traits area ("name").toLowerCase(); var ebTraits = ""; You can grab all the attributes for a repeating section using a roll20 function findObjs, and a javascript function filter, something like this var sectionAttributes = findObjs ({ _characterid: charID, _type: "attribute" , }).filter(att =&gt; att.get("name").startsWith('repeating_traits_')); The findObjs returns an array of all attributes on charID, then filter keeps only those that start with repeating_traits_. So you end up with all the attributes in the repeating section, on every row. (I'm half-asleep but I think that's the correct code!) You can then loop through those attributes to find the ones you need, or create new variables with data organised however you need it. Whatever you want.
GiGs said: You can grab all the attributes for a repeating section using a roll20 function findObjs, and a javascript function filter, something like this var sectionAttributes = findObjs ({ _characterid: charID, _type: "attribute" , }).filter(att =&gt; att.get("name").startsWith('repeating_traits_')); The findObjs returns an array of all attributes on charID, then filter keeps only those that start with repeating_traits_. So you end up with all the attributes in the repeating section, on every row. (I'm half-asleep but I think that's the correct code!) You can then loop through those attributes to find the ones you need, or create new variables with data organised however you need it. Whatever you want. &nbsp;Get some rest Gigs Thanks for the code: not sure its pulling right added this to my code: var sectionAttributes = findObjs({ _characterid: charID, _type: "attribute", }).filter(att =&gt; att.get("name").startsWith('repeating_traits_')); log(sectionAttributes) and I get this in log [{"name":"repeating_traits_-LyKFcooHETThDQncEMq_name","current":"Dark One's Blessing","max":"","_id":"-LyKFcrq3ULZIhZfzI_r","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKFcooHETThDQncEMq_description","current":"Starting at 1st level, when you reduce a hostile creature to 0 hit points, you gain temporary hit points equal to your Charisma modifier + your warlock level (minimum of 1).","max":"","_id":"-LyKFcrxDD33qmaiKYdE","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKFcooHETThDQncEMq_source","current":"Class","max":"","_id":"-LyKFcs4kiZiPnHDj3yH","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKFcooHETThDQncEMq_source_type","current":"The Fiend","max":"","_id":"-LyKFcsCvjZrdtDOkeol","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKFcooHETThDQncEMq_options-flag","current":"0","max":"","_id":"-LyKFcsK4Suazg6ii5E9","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKFcooHETThDQncEMq_display_flag","current":"on","max":"","_id":"-LyKFcsT3r7OGO8kcTES","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKFcop80oHUmrJF9T9_name","current":"Lucky","max":"","_id":"-LyKFcsq9YEroKkhT51B","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKFcop80oHUmrJF9T9_description","current":"When you roll a 1 on an attack roll, ability check, or saving throw, you can reroll the die and must use the new roll.","max":"","_id":"-LyKFct-Ks4Ey-PmY8a8","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKFcop80oHUmrJF9T9_source","current":"Racial","max":"","_id":"-LyKFct6lvWjUN4i-pu7","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKFcop80oHUmrJF9T9_source_type","current":"Halfling","max":"","_id":"-LyKFctHV0fJ1ourS_Oa","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKFcop80oHUmrJF9T9_options-flag","current":"0","max":"","_id":"-LyKFctPkt45sz9I65ft","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKFcop80oHUmrJF9T9_display_flag","current":"on","max":"","_id":"-LyKFctXs2Hlr8IIxhmH","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKFcop80oHUmrJF9TA_name","current":"Brave","max":"","_id":"-LyKFctdTXnHmEgYwfWx","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKFcop80oHUmrJF9TA_description","current":"You have advantage on saving throws against being frightened.","max":"","_id":"-LyKFctlIwZsx49I-g3A","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKFcop80oHUmrJF9TA_source","current":"Racial","max":"","_id":"-LyKFcttCDPAzh_mnYdg","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKFcop80oHUmrJF9TA_source_type","current":"Halfling","max":"","_id":"-LyKFcu1o6EZnY1NupN9","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKFcop80oHUmrJF9TA_options-flag","current":"0","max":"","_id":"-LyKFcu9T9ssepkrffu5","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKFcop80oHUmrJF9TA_display_flag","current":"on","max":"","_id":"-LyKFcuHeh3HYevkfmR3","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKFcoqB6zt6VFMA21j_name","current":"Halfling Nimbleness","max":"","_id":"-LyKFcuQRBLSLQfmBfIx","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKFcoqB6zt6VFMA21j_description","current":"You can move through the space of any creature that is of a size larger than yours.","max":"","_id":"-LyKFcuZ64eYrISeM1Fs","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKFcoqB6zt6VFMA21j_source","current":"Racial","max":"","_id":"-LyKFcughXzOeji4LALX","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKFcoqB6zt6VFMA21j_source_type","current":"Halfling","max":"","_id":"-LyKFcusep07EUGiAkKv","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKFcoqB6zt6VFMA21j_options-flag","current":0,"max":"","_id":"-LyKFcvNRMZ1r8TG20kv","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKFcoqB6zt6VFMA21j_display_flag","current":"on","max":"","_id":"-LyKFcvXTc5rM-Sc47BF","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKFcosR2XC56VO19eE_name","current":"Naturally Stealthy","max":"","_id":"-LyKFcweFS_6MsYzOc7Q","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKFcosR2XC56VO19eE_description","current":"You can attempt to hide even when you are obscured only by a creature that is at least one size larger than you.","max":"","_id":"-LyKFcwmeYD-74wUaYbR","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKFcosR2XC56VO19eE_source","current":"Racial","max":"","_id":"-LyKFcww_p95mcFhQES1","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKFcosR2XC56VO19eE_source_type","current":"Lightfoot Halfling","max":"","_id":"-LyKFcx7rE9I7xPr3HUS","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKFcosR2XC56VO19eE_options-flag","current":"0","max":"","_id":"-LyKFcxHt-DW3THCwu3V","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKFcosR2XC56VO19eE_display_flag","current":"on","max":"","_id":"-LyKFcxQNRhCLcY9ePw3","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKFcouB4TnZllgaq1k_name","current":"Criminal Contact","max":"","_id":"-LyKFcyJsZst_nwzG57L","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKFcouB4TnZllgaq1k_description","current":"You have a reliable and trustworthy contact who acts as your liaison to a network of other criminals. You know how to get messages to and from your contact, even over great distances; specifically, you know the local messengers, corrupt caravan masters, and seedy sailors who can deliver messages for you.","max":"","_id":"-LyKFcyWYihRm1_ebEZf","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKFcouB4TnZllgaq1k_source","current":"Background","max":"","_id":"-LyKFcydADInc8m4pn3c","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKFcouB4TnZllgaq1k_source_type","current":"Criminal","max":"","_id":"-LyKFcylpZsgE7c18zGr","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKFcouB4TnZllgaq1k_options-flag","current":"0","max":"","_id":"-LyKFcysYMQqOhHsAIbW","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKFcouB4TnZllgaq1k_display_flag","current":"on","max":"","_id":"-LyKFcz-UyG-8ICfwjY9","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKHfDTQ3cagDYQTZC5_name","current":"Eldritch Invocations","max":"","_id":"-LyKHfFakbMNUEU_IMRl","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKHfDTQ3cagDYQTZC5_description","current":"In your study of occult lore, you have unearthed eldritch invocations, fragments of forbidden knowledge that imbue you with an abiding magical ability. At 2nd level, you gain two eldritch invocations of your choice. Your invocation options are detailed at the end of the class description. When you gain certain warlock levels, you gain additional invocations of your choice, as shown in the Invocations Known column of the Warlock table. Additionally, when you gain a level in this class, you can choose one of the invocations you know and replace it with another invocation that you could learn at that level.","max":"","_id":"-LyKHfFyWSo5p8yfSsJT","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKHfDTQ3cagDYQTZC5_source","current":"Class","max":"","_id":"-LyKHfGBReUeBeQbs5kU","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKHfDTQ3cagDYQTZC5_source_type","current":"Warlock","max":"","_id":"-LyKHfGPwGhHmpSy4XAE","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKHfDTQ3cagDYQTZC5_options-flag","current":"0","max":"","_id":"-LyKHfGbVjdCa9O2G10H","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKHfDTQ3cagDYQTZC5_display_flag","current":"on","max":"","_id":"-LyKHfGpBfmiQCcmbWiM","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKHfDXsYkgMaTbh3v3_name","current":"Eldritch Invocation: Agonizing Blast","max":"","_id":"-LyKHfH19e9F-FQ-Hc7_","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKHfDXsYkgMaTbh3v3_description","current":"When you cast eldritch blast, add your Charisma modifier to the damage it deals on a hit.","max":"","_id":"-LyKHfHn_vZ1BxmLrAhp","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKHfDXsYkgMaTbh3v3_source","current":"Class","max":"","_id":"-LyKHfI3hXM9CXJ1Tmcx","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKHfDXsYkgMaTbh3v3_source_type","current":"Warlock","max":"","_id":"-LyKHfId1-wPup9zlVKb","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKHfDXsYkgMaTbh3v3_options-flag","current":"0","max":"","_id":"-LyKHfIzPFq2PoiYd1zX","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKHfDXsYkgMaTbh3v3_display_flag","current":"0","max":"","_id":"-LyKHfJOi1kQDppduPY9","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKHfDXsYkgMaTbh3v4_name","current":"Eldritch Invocation: Repelling Blast","max":"","_id":"-LyKHfJl87TP0Av2DQfg","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKHfDXsYkgMaTbh3v4_description","current":"When you hit a creature with Eldritch Blast, you can push the creature up to 10 feet away from you in a straight line.","max":"","_id":"-LyKHfK4KEpD16TzMmdi","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKHfDXsYkgMaTbh3v4_source","current":"Class","max":"","_id":"-LyKHfKJRcnBTbk1mX_p","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKHfDXsYkgMaTbh3v4_source_type","current":"Warlock","max":"","_id":"-LyKHfKZNZrBfD5-Sbzi","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKHfDXsYkgMaTbh3v4_options-flag","current":"0","max":"","_id":"-LyKHfKkYQL_ER3Tax19","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKHfDXsYkgMaTbh3v4_display_flag","current":"on","max":"","_id":"-LyKHfKz-wN_ZPfFil3w","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKKn5J7lpJI0U9eO1Y_name","current":"Pact of the Tome","max":"","_id":"-LyKKn7rHfeQkAAGLrGy","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKKn5J7lpJI0U9eO1Y_description","current":"Your patron gives you a grimoire called a Book of Shadows. When you gain this feature, choose three cantrips from any class’s spell list. While the book is on your person, you can cast those cantrips at will. They don’t count against your number of cantrips known. If you lose your Book of Shadows, you can perform a 1-hour ceremony to receive a replacement from your patron. This ceremony can be performed during a short or long rest, and it destroys the previous book. The book turns to ash when you die.","max":"","_id":"-LyKKn8A0_YthPkksej2","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKKn5J7lpJI0U9eO1Y_source","current":"Class","max":"","_id":"-LyKKn8dTZGZmuUlOxiN","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKKn5J7lpJI0U9eO1Y_source_type","current":"Warlock","max":"","_id":"-LyKKn8xFuhT2FdPJDSu","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKKn5J7lpJI0U9eO1Y_options-flag","current":"0","max":"","_id":"-LyKKn9tAhkI_puUGTMf","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKKn5J7lpJI0U9eO1Y_display_flag","current":"on","max":"","_id":"-LyKKnA93-g3jvP2NWEO","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKMzgmRVxudVAOn5uP_name","current":"Eldritch Invocation: Devil’s Sight","max":"","_id":"-LyKMzjLRYgfjkoM0slX","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKMzgmRVxudVAOn5uP_description","current":"You can see normally in darkness, both magical and nonmagical, to a distance of 120 feet.","max":"","_id":"-LyKMzkEtA3VLH_qbNGJ","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKMzgmRVxudVAOn5uP_source","current":"Class","max":"","_id":"-LyKMzkvzJLrhp0Ennxb","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKMzgmRVxudVAOn5uP_source_type","current":"Warlock","max":"","_id":"-LyKMzlKm_dW5UkMWGFN","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKMzgmRVxudVAOn5uP_options-flag","current":"0","max":"","_id":"-LyKMzleFlDKpK9ij4i7","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-LyKMzgmRVxudVAOn5uP_display_flag","current":"on","max":"","_id":"-LyKMzmdTP4UgiBz-0Ne","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-M5j4B0xHpQgIo72sARo_name","current":"Dark One’s Own Luck","max":"","_id":"-M5j4B5RddOAA8yl8Lc9","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-M5j4B0xHpQgIo72sARo_description","current":"Starting at 6th level, you can call on your patron to alter fate in your favor. When you make an ability check or a saving throw, you can use this feature to add a d10 to your roll. You can do so after seeing the initial roll but before any of the roll’s effects occur. Once you use this feature, you can’t use it again until you finish a short or long rest.","max":"","_id":"-M5j4B5eBrXEX-UIn8mE","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-M5j4B0xHpQgIo72sARo_source_type","current":"The Fiend","max":"","_id":"-M5j4B5suehPLXSSEzva","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-M5j4B0xHpQgIo72sARo_source","current":"Class","max":"","_id":"-M5j4B6359Ksc7Dcn1Ab","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-M5j4B0xHpQgIo72sARo_options-flag","current":"0","max":"","_id":"-M5j4B6EFpzl1uYf1ytX","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"},{"name":"repeating_traits_-M5j4B0xHpQgIo72sARo_display_flag","current":"on","max":"","_id":"-M5j4B6R5LxsEPFL8GQ2","_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"}]
1595282749

Edited 1595283862
David M.
Pro
API Scripter
Not to step on any toes, but going on the assumption that GiGs is sleeping and since it's only around 6PM in my time zone, I'll take a stab at your last question that might get you on the right track. It looks like you successfully found all of your repeating trait objects (each one in between curly brackets in your log, and each consisting of some number of property:value pairs) and they are now in your sectionAttributes array (with each object element separated by commas in your log).&nbsp; Now all you need to do is just loop through the objects in that array like GiGs suggested. Using the _.each method will go through each object in your array (one at a time, in order) and "do something" with the information contained in your objects.&nbsp; var sectionAttributes = findObjs({&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; _characterid: charID, &nbsp; _type: "attribute", }).filter(att =&gt; att.get("name").startsWith('repeating_traits_')); _.each(sectionAttributes , function(obj) {&nbsp; &nbsp;&nbsp; &nbsp; //"do something" with each obj }); BTW, I'm just a noob, too, so I'll yield the floor back to GiGs :)&nbsp;
1595305317
GiGs
Pro
Sheet Author
API Scripter
David is correct. That log is showing you an array of attribute objects.&nbsp; An array is a comma separated list of things, and it can include anything. So an array of every even number 2 and 10 would look like [2, 4, 6, 8, 10]. You could then loop through them using functions like _.each, or do things with it like the filter function i already used. So if you wanted to grab every number that was above 6, you could do let mynewset = [2, 4, 6, 8, 10].filter(num =&gt; num &gt;6); that would give you an array like this [8,10] Before I continue, let me say that you are embarking on a pretty complex task. This should give you a taste of the complexity. Don't let it put you off, we are here to help. Now what that sectionAttributes array gives is an array of attribute objects, not numbers, and each attribute object looks like this (picking one out at random): {"name":"repeating_traits_-LyKFcop80oHUmrJF9TA_name","current":"Brave","max":"","_id":"-LyKFctdTXnHmEgYwfWx", "_type":"attribute","_characterid":"-Ly2-LwB7XAjc7-qstEi"}, Everything inside the curly brackets there is one attribute. Notice it has a name a "current" value, a "max" value, an "id", a "type" (attribute), and a "characterid" (which character this attribute belongs to). The underscores at the start of some of property names tells you its a readonly property - you cant change it. Any examples I write assume you have already done this to get the initial array: let sectionAttributes = findObjs({&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; _characterid: charID, &nbsp; _type: "attribute", }).filter(att =&gt; att.get("name").startsWith('repeating_traits_')); What you need from here is a list of unique row ids, so you can loop through the rows. This weird little function will do that: let rowids = sectionAttributes.map(att =&gt; att.get('name').split('_')[2]) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.filter((value, index, self) =&gt; self.indexOf(value) === index); There's a lot going on here. Looking at the first line: .map() &nbsp;is a function that loops through an array. In this case, each attribute is - one at a time - assigned to att , then att is passed to this function: att.get('name').split('_')[2] When you want a value out of an attribute object you have to use the .get('name') function. So with each attribute, this gets the name of that attribute, which will be something like: "repeating_traits_-MCjJ2DC6r1iJpFKqzQH_name" that is the attribute name, from the character sheet. The row id is always in the same place, between the 2nd and third underscores, so you can get it by using .split('_')[2] since split gives an array, and [2] picks the 3rd item out of that array. Whew, so at this point we have a list of all the ids. BUT many attributes or on the same row, so there'll be a lot of duplicates, That's where the second line comes in: .filter((value, index, self) =&gt; self.indexOf(value) === index); Filter essentially loops through an array, and you can pass one or more properties of each item in the array. value is the item's value, like " -MCjJ2DC6r1iJpFKqzQH " index &nbsp;is the items position in the array, which will be a number like 0, 1, 2, etc. self &nbsp;is the actual array your working with. In this function you need to be able to act on that. So for each id in the array, we do this self.indexOf(value) === index) When doing indexOf, it returns the index of the first &nbsp;matching item. Now in this array, which may have a row id at indexes of 0, 1, 2, 3, and 4, because every attribute on the same row has the same id. So, this checks: is the index of the item we are checking now equal to the very first matching item. If it is, thats true,&nbsp; so we keep it. If its not (it's the second or later instance of that same row id), we discard it. So with this function we now have a unique list of row ids. So putting those together: let sectionAttributes = findObjs({&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; _characterid: charID, &nbsp; _type: "attribute", }).filter(att =&gt; att.get("name").startsWith('repeating_traits_')); let rowids = sectionAttributes.map(att =&gt; att.get('name').split('_')[2]) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.filter((value, index, self) =&gt; self.indexOf(value) === index); You can now get the value of any attribute in the repeating section, and can loop through the rows. Using these two arrays, and some of the techniques used to build them (like .get(), filter and the split('_')[2] trick), you can do whatever you need to with a repeating section. for some things, you'll want to loop through the entire set of attributes, for others you'll want to loop throgh the unique ids and check specific attributes on each row, by building up attribute names, like let attr_name = 'repeating_trait_' + rowid + '_whatever-attribute-i-want-to-check'; that would be inside a loop, like rowids.forEach(rowid =&gt; { &nbsp; &nbsp; let attr_name = 'repeating_trait_' + rowid + '_whatever-attribute-i-want-to-check'; &nbsp; &nbsp; // do something&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;return result-of-operation }); Anyway, this very complex, so good luck and if you need more help ask away.
1595313093

Edited 1595315257
Thank you both so much!&nbsp; I have sent some time working on this,&nbsp; I will post my updated code below&nbsp; This code was what I tried on my own before I saw your posts I will look and study what you have suggested As of Now I have managed to get the 5 traits I am looking to post the correct info in the template.&nbsp; The only problem is that I have 3 items that will effect the desc field.&nbsp; Since you may have one or all 3 I need to append the desc field but that is not working var desc = "" I thought that desc+= would append text but I feel that is not the case here var sectionAttributes = findObjs({ _characterid: charID, _type: "attribute", }).filter(att =&gt; att.get("name").startsWith('repeating_traits_')); _.each(sectionAttributes, function(attCurrentName){ attCurrentName = attCurrentName.get("current"); //log(attCurrentName) switch(attCurrentName){ case "Eldritch Invocation: Agonizing Blast": damage = `[[1d10+${chr}[Chr]]]`; sendChat("EB","/w gm Agonizing Blast found"); break; case "Eldritch Invocation: Eldritch Spear": range = "300" sendChat("EB","/w gm Eldritch Spear found"); break; case "Eldritch Invocation: Grasp of Hadar": desc = `{{desc=${graspOfHadar}`; sendChat("EB","/w gm Grasp of Hadar found"); break; case "Eldritch Invocation: Lance of Lethargy": if(desc === ""){ desc = `{{desc=${lanceOfLethargy}`; } else { desc+=`&lt;br&gt;+${lanceOfLethargy}`; }; sendChat("EB","/w gm Lance of Lethargy found"); break; case "Eldritch Invocation: Repelling Blast": if(desc === ""){ desc = `{{desc=${repellingBlast}`; } else { desc+=`&lt;br&gt;+${repellingBlast}`; }; sendChat("EB","/w gm Repelling Blast found"); break; default: //log(attCurrentName+" not EB Item"); break; }; }); if(desc !== ""){ desc +="}}"}; EB(casterLevel, spellAtkBonus, characterName, rtype, damage, range, character, player, desc); break; here is the EB function&nbsp; function EB(casterLevel, spellAtkBonus, characterName, rtype, damage, range, character, player, desc){ var numberOfBeams = (Math.floor((casterLevel + 1)/6)+1); var beamOutput = ""; //Having issues here where chat populates the beam # out of order for(counter=1;counter&lt;=numberOfBeams;counter++){ var outputMessage = `&amp;{template:atkdmg} {{mod=${spellAtkBonus}}} {{rname=Eldritch Blast ${counter}}} {{r1=[[1d20+${spellAtkBonus} [Spell]]]}} ${rtype}+${spellAtkBonus} [Spell]]]}} {{attack=1}} ${desc} {{range=${range}ft}} {{damage=1}} {{dmg1flag=1}} {{dmg1=${damage}}} {{dmg1type=force}} {{crit1=[[10]]}} {{crit2=[[10]]}}{{spelllevel= Cantrip}} {{charname=${characterName}}}`; log(outputMessage) //this if statment sends chat message as the who sent message if (character) sendChat('character|'+character.id, character.get('name')+outputMessage); else sendChat('player|'+player.id, player.get('displayname')+outputMessage); }; here is the log outputMessage "&amp;{template:atkdmg} {{mod=12}} {{rname=Eldritch Blast 1}} {{r1=[[1d20+12 [Spell]]]}} {{normal=1}} {{r2=[[0d20+12 [Spell]]]}} {{attack=1}} {{desc=Once on each of your turns when you hit a creature with your Eldritch Blast, you can move that creature in a straight line 10 feet closer to yourself.}} {{range=120ft}} {{damage=1}} {{dmg1flag=1}} {{dmg1=[[1d10+6[Chr]]]}} {{dmg1type=force}} {{crit1=[[10]]}} {{crit2=[[10]]}}{{spelllevel= Cantrip}} {{charname=Alton Ashfall}}" Here are the 3 "found" send chat items 2:46AM (From EB): &nbsp;Agonizing Blast found 2:46AM (From EB): &nbsp;Repelling Blast found 2:46AM (From EB): &nbsp;Grasp of Hadar found Thus Repelling Blast text is not being added to in the desc text UPDATED CODE as of 7/21/2020 at 0219 EST&nbsp; on("ready",function(){ log('Custom Spellbook Online'); on("chat:message", function(msg) { if (msg.type == "api" &amp;&amp; msg.content.indexOf("!customSpellbook") == 0){ var args = msg.content.split(/\s+/); var spellName = args[1].toLowerCase(); var spellLevel = Number(args[2]); var selected = msg.selected; if (selected===undefined) { sendChat("Custom Spellbook", "/w gm no token selected"); return; } var character = findObjs({ type: 'character', name: msg.who })[0], player = getObj('player', msg.playerid); var tokenid = selected[0]._id; var token = getObj("graphic",tokenid); var charID = token.get("represents"); var characterName = token.get("name"); var casterLevel = Number(getAttrByName(charID, 'level')); var spellAtkBonus = Number(getAttrByName(charID, 'spell_attack_bonus')); var chr = Number(getAttrByName(charID, 'charisma_mod')); var desc = "" var graspOfHadar = "Once on each of your turns when you hit a creature with your Eldritch Blast, you can move that creature in a straight line 10 feet closer to yourself." var lanceOfLethargy = "Once on each of your turns when you hit a creature with your Eldritch Blast, you can reduce that creature’s speed by 10 feet until the end of your next turn." var repellingBlast = "When you hit a creature with Eldritch Blast, you can push the creature up to 10 feet away from you in a straight line." switch(spellName){ case "magicmissile": magicMissile(spellLevel); break; case "eb": var damage = "[[1d10]]"; var range = "120" var rtype = args[3]; if (rtype === undefined) { sendChat("CSB - Eldritch Blast", "No Roll type provided, Please state **Normal, Advantage, or Disadvantage**"); return; } rtype = args[3].toLowerCase(); switch(rtype){ case "normal": rtype ="{{normal=1}} {{r2=[[0d20"; break; case "advantage": rtype = "{{advantage=1}} {{r2=[[1d20ro"; break; case "disadvantage": rtype = "{{disadvantage=1}} {{r2=[[1d20ro"; break; default: sendChat("CSB - Eldritch Blast", "Roll type not properly identified, Please state either **Normal, Advantage, or Disadvantage**"); return; } var sectionAttributes = findObjs({ _characterid: charID, _type: "attribute", }).filter(att =&gt; att.get("name").startsWith('repeating_traits_')); _.each(sectionAttributes, function(attCurrentName){ attCurrentName = attCurrentName.get("current"); //log(attCurrentName) switch(attCurrentName){ case "Eldritch Invocation: Agonizing Blast": damage = `[[1d10+${chr}[Chr]]]`; sendChat("EB","/w gm Agonizing Blast found"); break; case "Eldritch Invocation: Eldritch Spear": range = "300" sendChat("EB","/w gm Eldritch Spear found"); break; case "Eldritch Invocation: Grasp of Hadar": desc = `{{desc=${graspOfHadar}`; sendChat("EB","/w gm Grasp of Hadar found"); break; case "Eldritch Invocation: Lance of Lethargy": if(desc === ""){ desc = `{{desc=${lanceOfLethargy}`; } else { desc+=`&lt;br&gt;+${lanceOfLethargy}`; }; sendChat("EB","/w gm Lance of Lethargy found"); break; case "Eldritch Invocation: Repelling Blast": if(desc === ""){ desc = `{{desc=${repellingBlast}`; } else { desc+=`&lt;br&gt;+${repellingBlast}`; }; sendChat("EB","/w gm Repelling Blast found"); break; default: //log(attCurrentName+" not EB Item"); break; }; }); if(desc !== ""){ desc +="}}"}; EB(casterLevel, spellAtkBonus, characterName, rtype, damage, range, character, player, desc); break; } //Nick's code to reduce used spells (turned off until I know where to put this since I've added cantrips i.e. Eldritch Blast) //sendChat("API",`!modbattr --charid @{${charID}} --lvl${spellLevel}_slots_expended|-1`); //sendChat("API",`!modbattr --charid @{${charID}} --SpellsCasted|+1`); } }); function magicMissile(spellLevel){ var numberOfDarts = spellLevel + 2; var dartOutput = ""; for(counter=1;counter&lt;=numberOfDarts;counter++){ dartOutput+=`{{Dart ${counter} = [[1d4+1]]}}`; } var outputMessage = `&amp;{template:default} {{name=Magic Missile}} ${dartOutput}`; sendChat("API",outputMessage); }; function EB(casterLevel, spellAtkBonus, characterName, rtype, damage, range, character, player, desc){ var numberOfBeams = (Math.floor((casterLevel + 1)/6)+1); var beamOutput = ""; //Having issues here where chat populates the beam # out of order for(counter=1;counter&lt;=numberOfBeams;counter++){ var outputMessage = `&amp;{template:atkdmg} {{mod=${spellAtkBonus}}} {{rname=Eldritch Blast ${counter}}} {{r1=[[1d20+${spellAtkBonus} [Spell]]]}} ${rtype}+${spellAtkBonus} [Spell]]]}} {{attack=1}} ${desc} {{range=${range}ft}} {{damage=1}} {{dmg1flag=1}} {{dmg1=${damage}}} {{dmg1type=force}} {{crit1=[[10]]}} {{crit2=[[10]]}}{{spelllevel= Cantrip}} {{charname=${characterName}}}`; log(outputMessage) //this if statment sends chat message as the who sent message if (character) sendChat('character|'+character.id, character.get('name')+outputMessage); else sendChat('player|'+player.id, player.get('displayname')+outputMessage); //sendChat(characterName,outputMessage); }; }; });
1595315485
GiGs
Pro
Sheet Author
API Scripter
What happens with desc +=? Does the script crash or does it just fail to return the expected value? desc += whatever; should work. But if it doesnt, try this instead: desc = desc +&nbsp;whatever; or even desc = `${desc} ${whatever}`; In any case, I would recommend removing the {{desc= part from your loop. Running through the loop adding the bits together, then after the loop, do something like desc = desc ? `{{desc=${desc} }}` : ''; that avoids the need to test if desc == '' several times during the loop. Note that the above is a ternary operator, its an if statement in one line. It's the same as doing: if(desc) { &nbsp; &nbsp; desc =&nbsp;`{{desc=${desc} }}`; } else { &nbsp; &nbsp; desc = ''; } Just a lot more compact. if(desc) will be true if desc has been assigned a value, and false if it is still ''.
1595316481
GiGs
Pro
Sheet Author
API Scripter
I see your note about EB sending chat messages out of order. The way to avoid that is to build all the text into one string, and send just one sendChat message. In fact you should build all output from the entire script into one message, and just use one sendChat to send it.&nbsp; Here's the function rewritten to send one chat message: function&nbsp;EB(casterLevel,&nbsp;spellAtkBonus,&nbsp;characterName,&nbsp;rtype,&nbsp;damage,&nbsp;range,&nbsp;character,&nbsp;player,&nbsp;desc){ &nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;numberOfBeams&nbsp;=&nbsp;(Math.floor((casterLevel&nbsp;+&nbsp;1)/6)+1); &nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;beamarray&nbsp;=&nbsp;[]; &nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;outputMessage&nbsp;=&nbsp;`&amp;{template:atkdmg}&nbsp;{{mod=${spellAtkBonus}}}&nbsp;{{rname=Eldritch&nbsp;Blast&nbsp;${counter}}}&nbsp;{{r1=[[1d20+${spellAtkBonus}&nbsp;[Spell]]]}}&nbsp;${rtype}+${spellAtkBonus}&nbsp;[Spell]]]}}&nbsp;{{attack=1}}&nbsp;${desc}&nbsp;{{range=${range}ft}}&nbsp;{{damage=1}}&nbsp;{{dmg1flag=1}}&nbsp;{{dmg1=${damage}}}&nbsp;{{dmg1type=force}}&nbsp;{{crit1=[[10]]}}&nbsp;{{crit2=[[10]]}}{{spelllevel=&nbsp;Cantrip}}&nbsp;{{charname=${characterName}}}`; &nbsp;&nbsp;&nbsp;&nbsp;//this&nbsp;makes&nbsp;an&nbsp;array&nbsp;with&nbsp;as&nbsp;mean&nbsp;copies&nbsp;of&nbsp;the&nbsp;outputmeassage&nbsp;as&nbsp;needed &nbsp;&nbsp;&nbsp;&nbsp;for(counter=1;counter&lt;=numberOfBeams;counter++){ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;beamarray.push(outputMessage); &nbsp;&nbsp;&nbsp;&nbsp;}; &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;this&nbsp;converts&nbsp;the&nbsp;array&nbsp;into&nbsp;a&nbsp;string,&nbsp;with&nbsp;newlines&nbsp;between&nbsp;each&nbsp;on,&nbsp;so&nbsp;they&nbsp;each&nbsp;go&nbsp;on&nbsp;a&nbsp;new&nbsp;line. &nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;beamOutput&nbsp;=&nbsp;beamarray.join(`\n`); &nbsp;&nbsp;&nbsp;&nbsp;//this&nbsp;if&nbsp;statment&nbsp;sends&nbsp;chat&nbsp;message&nbsp;as&nbsp;the&nbsp;who&nbsp;sent&nbsp;message &nbsp;&nbsp;&nbsp;&nbsp;//sendChat(characterName,outputMessage); &nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(character)&nbsp;sendChat('character|'+character.id,&nbsp;character.get('name')&nbsp;+&nbsp;beamOutput); &nbsp;&nbsp;&nbsp;&nbsp;else&nbsp;sendChat('player|'+player.id,&nbsp;player.get('displayname')&nbsp;+&nbsp;beamOutput); };&nbsp;&nbsp;&nbsp;&nbsp; Though it really should end with: &nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;beamOutput&nbsp;=&nbsp;beamarray.join(`\n`); &nbsp;&nbsp;&nbsp;&nbsp;//return this to the calling script, toi then be included with other chat messages into one. &nbsp;&nbsp;&nbsp;&nbsp;return beamOutput; };&nbsp;&nbsp;&nbsp;&nbsp; and in your switch case you'd call it with something like var message = EB(casterLevel, spellAtkBonus, characterName, rtype, damage, range, character, player, desc); and can then combine it with other message strings, to create a single output message.
GiGs said: What happens with desc +=? Does the script crash or does it just fail to return the expected value? desc += whatever; should work. But if it doesnt, try this instead: desc = desc +&nbsp;whatever; or even desc = `${desc} ${whatever}`; It fails to return a value with any of the 3: You lost me with this: In any case, I would recommend removing the {{desc= part from your loop. Running through the loop adding the bits together, then after the loop, do something like desc = desc ? `{{desc=${desc} }}` : ''; that avoids the need to test if desc == '' several times during the loop. Note that the above is a ternary operator, its an if statement in one line. It's the same as doing: if(desc) { &nbsp; &nbsp; desc =&nbsp;`{{desc=${desc} }}`; } else { &nbsp; &nbsp; desc = ''; } Just a lot more compact. if(desc) will be true if desc has been assigned a value, and false if it is still ''.
GiGs said: I see your note about EB sending chat messages out of order. The way to avoid that is to build all the text into one string, and send just one sendChat message. In fact you should build all output from the entire script into one message, and just use one sendChat to send it.&nbsp; Here's the function rewritten to send one chat message: function&nbsp;EB(casterLevel,&nbsp;spellAtkBonus,&nbsp;characterName,&nbsp;rtype,&nbsp;damage,&nbsp;range,&nbsp;character,&nbsp;player,&nbsp;desc){ &nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;numberOfBeams&nbsp;=&nbsp;(Math.floor((casterLevel&nbsp;+&nbsp;1)/6)+1); &nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;beamarray&nbsp;=&nbsp;[]; &nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;outputMessage&nbsp;=&nbsp;`&amp;{template:atkdmg}&nbsp;{{mod=${spellAtkBonus}}}&nbsp;{{rname=Eldritch&nbsp;Blast&nbsp;${counter}}}&nbsp;{{r1=[[1d20+${spellAtkBonus}&nbsp;[Spell]]]}}&nbsp;${rtype}+${spellAtkBonus}&nbsp;[Spell]]]}}&nbsp;{{attack=1}}&nbsp;${desc}&nbsp;{{range=${range}ft}}&nbsp;{{damage=1}}&nbsp;{{dmg1flag=1}}&nbsp;{{dmg1=${damage}}}&nbsp;{{dmg1type=force}}&nbsp;{{crit1=[[10]]}}&nbsp;{{crit2=[[10]]}}{{spelllevel=&nbsp;Cantrip}}&nbsp;{{charname=${characterName}}}`; &nbsp;&nbsp;&nbsp;&nbsp;//this&nbsp;makes&nbsp;an&nbsp;array&nbsp;with&nbsp;as&nbsp;mean&nbsp;copies&nbsp;of&nbsp;the&nbsp;outputmeassage&nbsp;as&nbsp;needed &nbsp;&nbsp;&nbsp;&nbsp;for(counter=1;counter&lt;=numberOfBeams;counter++){ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;beamarray.push(outputMessage); &nbsp;&nbsp;&nbsp;&nbsp;}; &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;this&nbsp;converts&nbsp;the&nbsp;array&nbsp;into&nbsp;a&nbsp;string,&nbsp;with&nbsp;newlines&nbsp;between&nbsp;each&nbsp;on,&nbsp;so&nbsp;they&nbsp;each&nbsp;go&nbsp;on&nbsp;a&nbsp;new&nbsp;line. &nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;beamOutput&nbsp;=&nbsp;beamarray.join(`\n`); &nbsp;&nbsp;&nbsp;&nbsp;//this&nbsp;if&nbsp;statment&nbsp;sends&nbsp;chat&nbsp;message&nbsp;as&nbsp;the&nbsp;who&nbsp;sent&nbsp;message &nbsp;&nbsp;&nbsp;&nbsp;//sendChat(characterName,outputMessage); &nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(character)&nbsp;sendChat('character|'+character.id,&nbsp;character.get('name')&nbsp;+&nbsp;beamOutput); &nbsp;&nbsp;&nbsp;&nbsp;else&nbsp;sendChat('player|'+player.id,&nbsp;player.get('displayname')&nbsp;+&nbsp;beamOutput); };&nbsp;&nbsp;&nbsp;&nbsp; Though it really should end with: &nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;beamOutput&nbsp;=&nbsp;beamarray.join(`\n`); &nbsp;&nbsp;&nbsp;&nbsp;//return this to the calling script, toi then be included with other chat messages into one. &nbsp;&nbsp;&nbsp;&nbsp;return beamOutput; };&nbsp;&nbsp;&nbsp;&nbsp; and in your switch case you'd call it with something like var message = EB(casterLevel, spellAtkBonus, characterName, rtype, damage, range, character, player, desc); and can then combine it with other message strings, to create a single output message. I updated Switch Case to your var message..... Updated EB function when no errors on save, get a&nbsp; &nbsp; ReferenceError: counter is not defined when running the API command
1595318674
GiGs
Pro
Sheet Author
API Scripter
weird that it doesn't work now but apparently worked before? It's lacking a variable declaration for counter, so change the for line to &nbsp;for(let counter=1;counter&lt;=numberOfBeams;counter++){
1595318998

Edited 1595319951
GiGs said: weird that it doesn't work now but apparently worked before? It's lacking a variable declaration for counter, so change the for line to &nbsp;for(let counter=1;counter&lt;=numberOfBeams;counter++){ Nope same error
1595319150
GiGs
Pro
Sheet Author
API Scripter
Tye said: You lost me with this: In any case, I would recommend removing the {{desc= part from your loop. Running through the loop adding the bits together, then after the loop, do something like desc = desc ? `{{desc=${desc} }}` : ''; that avoids the need to test if desc == '' several times during the loop. Note that the above is a ternary operator, its an if statement in one line. It's the same as doing: if(desc) { &nbsp; &nbsp; desc =&nbsp;`{{desc=${desc} }}`; } else { &nbsp; &nbsp; desc = ''; } Just a lot more compact. if(desc) will be true if desc has been assigned a value, and false if it is still ''. I was suggesting something like changing these bits &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case "Eldritch Invocation: Lance of Lethargy": if(desc === ""){ desc = `{{desc=${lanceOfLethargy}`; } else { desc+=`&lt;br&gt;+${lanceOfLethargy}`; }; sendChat("EB","/w gm Lance of Lethargy found"); break; to &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case "Eldritch Invocation: Lance of Lethargy": desc+=`&lt;br&gt;+${lanceOfLethargy}`; sendChat("EB","/w gm Lance of Lethargy found"); break; then at the end where you have&nbsp; if(desc !== ""){ desc +="}}"}; you can change that to&nbsp; if(desc !== ""){ desc = `{{desc=${desc}}}`; } Though it would be better to use the array method. So just before the each loop starts, create let descarray = []; then the above sections would be like case "Eldritch Invocation: Lance of Lethargy": descarray.push(lanceOfLethargy); sendChat("EB","/w gm Lance of Lethargy found"); break; Then the end part can use .join('&lt;br&gt;') to join them and put a line break in each one/ if(desc !== ""){ desc = `{{desc=${descarray.join('&lt;br/&gt;')} }}`; }
Thanks GiGs I will look at it later time to get some zzzz
1595319594

Edited 1595319605
GiGs
Pro
Sheet Author
API Scripter
Tye said: GiGs said: weird that it doesn't work now but apparently worked before? It's lacking a variable declaration for counter, so change the for line to &nbsp;for(let counter=1;counter&lt;=numberOfBeams;counter++){ Nope same error Check that the outputMessage on the line before ends properly. The problem might not be with counter, but with improper syntax just before the loop. When you have hard to define errors, one useful thing to do is disable all other scripts, so you can use the line its reporting the error on, though that might not help here. I'm confused why its not working now and was working before, and think some other change in the code might be responsible.
I see that counter is in the var outputMessage var outputMessage = `&amp;{template:atkdmg} {{mod=${spellAtkBonus}}} {{rname=Eldritch Blast ${counter}}} which is before the new for(let
1595320198
GiGs
Pro
Sheet Author
API Scripter
aha, well spotted, i didnt notice you had a count in there. That's the source of the error. Change the function to this: function&nbsp;EB(casterLevel,&nbsp;spellAtkBonus,&nbsp;characterName,&nbsp;rtype,&nbsp;damage,&nbsp;range,&nbsp;character,&nbsp;player,&nbsp;desc){ &nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;numberOfBeams&nbsp;=&nbsp;(Math.floor((casterLevel&nbsp;+&nbsp;1)/6)+1); &nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;beamarray&nbsp;=&nbsp;[]; &nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;outputMessage&nbsp;=&nbsp;counter&nbsp;=&gt;&nbsp;`&amp;{template:atkdmg}&nbsp;{{mod=${spellAtkBonus}}}&nbsp;{{rname=Eldritch&nbsp;Blast&nbsp;${counter}}}&nbsp;{{r1=[[1d20+${spellAtkBonus}&nbsp;[Spell]]]}}&nbsp;${rtype}+${spellAtkBonus}&nbsp;[Spell]]]}}&nbsp;{{attack=1}}&nbsp;${desc}&nbsp;{{range=${range}ft}}&nbsp;{{damage=1}}&nbsp;{{dmg1flag=1}}&nbsp;{{dmg1=${damage}}}&nbsp;{{dmg1type=force}}&nbsp;{{crit1=[[10]]}}&nbsp;{{crit2=[[10]]}}{{spelllevel=&nbsp;Cantrip}}&nbsp;{{charname=${characterName}}}`; &nbsp;&nbsp;&nbsp;&nbsp;//this&nbsp;makes&nbsp;an&nbsp;array&nbsp;with&nbsp;as&nbsp;many&nbsp;copies&nbsp;of&nbsp;the&nbsp;outputmeassage&nbsp;as&nbsp;needed &nbsp;&nbsp;&nbsp;&nbsp;for(let&nbsp;counter=1;counter&lt;=numberOfBeams;counter++){ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;beamarray.push(outputMessage(counter)); &nbsp;&nbsp;&nbsp;&nbsp;}; &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;this&nbsp;converts&nbsp;the&nbsp;array&nbsp;into&nbsp;a&nbsp;string,&nbsp;with&nbsp;newlines&nbsp;between&nbsp;each&nbsp;on,&nbsp;so&nbsp;they&nbsp;each&nbsp;go&nbsp;on&nbsp;a&nbsp;new&nbsp;line. &nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;beamOutput&nbsp;=&nbsp;beamarray.join(`\n`); &nbsp;&nbsp;&nbsp;&nbsp;//this&nbsp;if&nbsp;statment&nbsp;sends&nbsp;chat&nbsp;message&nbsp;as&nbsp;the&nbsp;who&nbsp;sent&nbsp;message &nbsp;&nbsp;&nbsp;&nbsp;//sendChat(characterName,outputMessage); &nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(character)&nbsp;sendChat('character|'+character.id,&nbsp;character.get('name')&nbsp;+&nbsp;beamOutput); &nbsp;&nbsp;&nbsp;&nbsp;else&nbsp;sendChat('player|'+player.id,&nbsp;player.get('displayname')&nbsp;+&nbsp;beamOutput); };&nbsp;&nbsp;&nbsp;&nbsp; this changes the outputmessage to a function, that accepts the counter.
1595320388
GiGs
Pro
Sheet Author
API Scripter
There might still be a problem: What's the purpose of the character.get('name') at the start of the sendchat message: if&nbsp;(character)&nbsp;sendChat('character|'+character.id,&nbsp;character.get('name')&nbsp;+&nbsp;beamOutput); There's no /w &nbsp;there, so I dont understand why you are putting the character name at the start of the message.&nbsp;
GiGs &nbsp;said: Though it would be better to use the array method. So just before the each loop starts, create let descarray = []; then the above sections would be like case "Eldritch Invocation: Lance of Lethargy": descarray.push(lanceOfLethargy); sendChat("EB","/w gm Lance of Lethargy found"); break; Then the end part can use .join('&lt;br&gt;') to join them and put a line break in each one/ if(desc !== ""){ desc = `{{desc=${descarray.join('&lt;br/&gt;')} }}`; } the descarry is not adding to the desc variable var desc = "" being sent to EB function notice the extra space in log between&nbsp;{{attack=1}}&nbsp; {{range=120ft}} that is were the {{desc=}} would go per our outputMessage variable "&amp;{template:atkdmg} {{mod=12}} {{rname=Eldritch Blast 1}} {{r1=[[1d20+12 [Spell]]]}} {{normal=1}} {{r2=[[0d20+12 [Spell]]]}} {{attack=1}} {{range=120ft}} {{damage=1}} {{dmg1flag=1}} {{dmg1=[[1d10+6[Chr]]]}} {{dmg1type=force}} {{crit1=[[10]]}} {{crit2=[[10]]}}{{spelllevel= Cantrip}} {{charname=Alton Ashfall}}"
1595321395
GiGs
Pro
Sheet Author
API Scripter
We know there's something up with your text values. I dont wee why they aren't working, but I noticed these lines are missing semi-colons at the end: &nbsp;var&nbsp;desc&nbsp;=&nbsp;'' &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;graspOfHadar&nbsp;=&nbsp;'Once&nbsp;on&nbsp;each&nbsp;of&nbsp;your&nbsp;turns&nbsp;when&nbsp;you&nbsp;hit&nbsp;a&nbsp;creature&nbsp;with&nbsp;your&nbsp;Eldritch&nbsp;Blast,&nbsp;you&nbsp;can&nbsp;move&nbsp;that&nbsp;creature&nbsp;in&nbsp;a&nbsp;straight&nbsp;line&nbsp;10&nbsp;feet&nbsp;closer&nbsp;to&nbsp;yourself.' &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;lanceOfLethargy&nbsp;=&nbsp;'Once&nbsp;on&nbsp;each&nbsp;of&nbsp;your&nbsp;turns&nbsp;when&nbsp;you&nbsp;hit&nbsp;a&nbsp;creature&nbsp;with&nbsp;your&nbsp;Eldritch&nbsp;Blast,&nbsp;you&nbsp;can&nbsp;reduce&nbsp;that&nbsp;creature’s&nbsp;speed&nbsp;by&nbsp;10&nbsp;feet&nbsp;until&nbsp;the&nbsp;end&nbsp;of&nbsp;your&nbsp;next&nbsp;turn.' &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;repellingBlast&nbsp;=&nbsp;'When&nbsp;you&nbsp;hit&nbsp;a&nbsp;creature&nbsp;with&nbsp;Eldritch&nbsp;Blast,&nbsp;you&nbsp;can&nbsp;push&nbsp;the&nbsp;creature&nbsp;up&nbsp;to&nbsp;10&nbsp;feet&nbsp;away&nbsp;from&nbsp;you&nbsp;in&nbsp;a&nbsp;straight&nbsp;line.' Add a semi colon to the end of each line and corss your fingers that it makes a difference...
The fix to the counter error worked added ; to the 3 lines the desc is still not being passed value remains ""
1595321878
GiGs
Pro
Sheet Author
API Scripter
You should also log those variables to make sure they have the correct values, like case&nbsp;'Eldritch&nbsp;Invocation:&nbsp;Lance&nbsp;of&nbsp;Lethargy': &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;descarray.push(lanceOfLethargy); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sendChat('EB','/w&nbsp;gm&nbsp;Lance&nbsp;of&nbsp;Lethargy&nbsp;found'); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sendChat('lanceOfLethargy',lanceOfLethargy); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;log(`Lance is: ${lanceOfLethargy}`); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;log(descarray); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break; This is more log messages than I'd normally use, but you can delete them after checking things have the values they are supposed to.
GiGs said: You should also log those variables to make sure they have the correct values, like case&nbsp;'Eldritch&nbsp;Invocation:&nbsp;Lance&nbsp;of&nbsp;Lethargy': &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;descarray.push(lanceOfLethargy); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sendChat('EB','/w&nbsp;gm&nbsp;Lance&nbsp;of&nbsp;Lethargy&nbsp;found'); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sendChat('lanceOfLethargy',lanceOfLethargy); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;log(`Lance is: ${lanceOfLethargy}`); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;log(descarray); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break; This is more log messages than I'd normally use, but you can delete them after checking things have the values they are supposed to. (From EB): &nbsp;Agonizing Blast found 5:12AM (From EB): &nbsp;Repelling Blast found 5:12AM repellingBlast: When you hit a creature with Eldritch Blast, you can push the creature up to 10 feet away from you in a straight line. 5:12AM graspOfHada: Once on each of your turns when you hit a creature with your Eldritch Blast, you can move that creature in a straight line 10 feet closer to yourself. 5:12AM (From EB): &nbsp;Grasp of Hadar found 5:12AM (From EB): &nbsp;Lance of Lethargy found 5:12AM lanceOfLethargy: Once on each of your turns when you hit a creature with your Eldritch Blast, you can reduce that creature’s speed by 10 feet until the end of your next turn. "Repelling Blast is: When you hit a creature with Eldritch Blast, you can push the creature up to 10 feet away from you in a straight line." ["When you hit a creature with Eldritch Blast, you can push the creature up to 10 feet away from you in a straight line."] "Grasp of Hadar is: Once on each of your turns when you hit a creature with your Eldritch Blast, you can move that creature in a straight line 10 feet closer to yourself." ["When you hit a creature with Eldritch Blast, you can push the creature up to 10 feet away from you in a straight line.","Once on each of your turns when you hit a creature with your Eldritch Blast, you can move that creature in a straight line 10 feet closer to yourself."] "Lance is: Once on each of your turns when you hit a creature with your Eldritch Blast, you can reduce that creature’s speed by 10 feet until the end of your next turn." ["When you hit a creature with Eldritch Blast, you can push the creature up to 10 feet away from you in a straight line.","Once on each of your turns when you hit a creature with your Eldritch Blast, you can move that creature in a straight line 10 feet closer to yourself.","Once on each of your turns when you hit a creature with your Eldritch Blast, you can reduce that creature’s speed by 10 feet until the end of your next turn."]
Those work but not passing into desc
1595326243
GiGs
Pro
Sheet Author
API Scripter
at least we know the variables are being passed properly, and the descarray is being built properly. I just realised I didnt change this part to account for using the array: if(desc !== ""){ desc = `{{desc=${descarray.join('&lt;br/&gt;')} }}`; } It should be if(descarray.length &gt; 0){ desc = `{{desc=${descarray.join('&lt;br/&gt;')} }}`; }
GiGs said: at least we know the variables are being passed properly, and the descarray is being built properly. I just realised I didnt change this part to account for using the array: if(desc !== ""){ desc = `{{desc=${descarray.join('&lt;br/&gt;')} }}`; } It should be if(descarray.length &gt; 0){ desc = `{{desc=${descarray.join('&lt;br/&gt;')} }}`; } That worked EB is done!!!! YES!!!! Thanks!!!! now on to another variation damage mod LOL will updated org. Post of progress Thank you so much GiGs to add to my Toolbox!!! &nbsp;
1595344220
GiGs
Pro
Sheet Author
API Scripter
Yay, thats great to hear.
Ok Changes I have made today: I have added the desc to be updated for all 5 invocations var sectionAttributes = findObjs({ _characterid: charID, _type: "attribute", }).filter(att =&gt; att.get("name").startsWith('repeating_traits_')); let descarray = []; _.each(sectionAttributes, function(attCurrentName){ attCurrentName = attCurrentName.get("current"); switch(attCurrentName){ case "Eldritch Invocation: Agonizing Blast": damage = `[[1d10+${chr}[Chr]]]`; descarray.push(agonizingBlast); break; case "Eldritch Invocation: Eldritch Spear": range = "300" descarray.push(eldritchSpear); break; case "Eldritch Invocation: Grasp of Hadar": descarray.push(graspOfHadar); break; case 'Eldritch Invocation: Lance of Lethargy': descarray.push(lanceOfLethargy); break; case "Eldritch Invocation: Repelling Blast": descarray.push(repellingBlast); break; default: added Global Damage Mod and Type to pass through a for/else to see if damage mod is 0 or has damage dice amounts made dmg2 turn on and off with damage mods.&nbsp; if no checked damaged mods dmg2 is off.&nbsp;&nbsp; var globalDamageMod = getAttrByName(charID, 'global_damage_mod_roll'); var dmg2 = []; var globalDamageType = getAttrByName(charID, 'global_damage_mod_type'); here is the for/else added just before calling the EB function if(globalDamageMod == "0") { dmg2 = "{{dmg2flag=}} {{dmg2=}}"; log("True: "+dmg2); } else { dmg2 = `{{dmg2flag=1}} {{dmg2type=${globalDamageType}}} {{dmg2=[[${globalDamageMod}]]}}`; log("false: "+dmg2); } var message = EB(casterLevel, spellAtkBonus, characterName, rtype, damage, range, character, player, desc, dmg2); break; lastly added dmg2 to the outputMessage in the EB function. Updated gitthub with code found here&nbsp; <a href="https://gist.github.com/TooTallTye/52b32e0095a9562741ffd9fc6be0f7e1" rel="nofollow">https://gist.github.com/TooTallTye/52b32e0095a9562741ffd9fc6be0f7e1</a> updated org. post with todo's need to find code or way add Global Attack Mods&nbsp;
Ok I think I have managed to finish all of my tasks except make a marco from an API..... For Eldritch Blast: The running&nbsp;!customSpellbook eb 0 ?{Eldritch Blast Roll Type?|Normal|Advantage|Disadvantage} will cast the correct number of Blasts (will number each blast), add any Attack Modifiers to the attack roll, will also add a 2nd set of damage rolls for any Damage Modifiers. Also roll Normal, Advantage, or at Disadvantage. It will also send the message from who sent the message (chat as), look within the traits for of the 5 Invocations that effect Eldritch Blast and update the spell attack cards as needed.&nbsp; For each Invocation the&nbsp; appropriate description will be added into the description field each on it's own line. 1. Eldritch Invocation: Agonizing Blast&nbsp; When you cast Eldritch Blast, add your Charisma modifier to the damage it deals on a hit. 2. Eldritch Invocation: Eldritch Spear When you cast Eldritch Blast, its range is 300 feet. 3. Eldritch Invocation: Grasp of Hadar Once on each of your turns when you hit a creature with your Eldritch Blast, you can move that creature in a straight line 10 feet closer to yourself. 4. Eldritch Invocation: Lance of Lethargy Once on each of your turns when you hit a creature with your Eldritch Blast, you can reduce that creature’s speed by 10 feet until the end of your next turn. 5. Eldritch Invocation: Repelling Blast When you hit a creature with Eldritch Blast, you can push the creature up to 10 feet away from you in a straight line. Here are 2 images of the chat messages from the API,&nbsp; The Character Alton Ashfall&nbsp;a Lightfoot Halfling, Pact of the Fiend Warlock 6 with a bless 1d4 attack mod, and Hex 1d6 Narcotic and for ease of showing all 5 invocations. Image 1 Basic Eldritch Blast Lv6 player no Invocations: Image 2 Fully Loaded (Range now 300, Chr added to damage, bless added (the +1 and +4) to attack, hex added in damage 2 block) &nbsp;
1595480978
GiGs
Pro
Sheet Author
API Scripter
Nice work!
Thanks for your help and advice
Hello Everyone, the spells that I have coded in are Scorching Ray, Eldritch Blast, and Magic Missile.&nbsp; All results appear in chat in the correct damage or atkdmg roll templates for 5e OGL. I have it even looking to see if they are able to cast that level of spells and if they have any available. Which is only needed for Magic Missile and Scorching Ray at the moment. Adds Attack and Damage mods as needed even subtracts the spell when used and displays a message in chat of how many remaining. Here is the link to my code. <a href="https://gist.github.com/TooTallTye/52b32e0095a9562741ffd9fc6be0f7e1" rel="nofollow">https://gist.github.com/TooTallTye/52b32e0095a9562741ffd9fc6be0f7e1</a> What I want to know is how can I streamline the code,&nbsp; not sure how to convey it but to remove redundant bits of code as well as clean up the formatting, make if more readable to the coders who would read this.&nbsp; Everything works.&nbsp; I want to add more spells but keep it simple. Please advise. Thanks Tye&nbsp;
I also would like to somehow tie is this other code that Nick showed me how to make for AOE spells. When I add more spell I want to be able to have this code fire as well if the spell is an AOE type spell //commands //!AOE [TYPE] [unit Height] [Unit Width] //TYPE are either LINE, CIRCLE, CONE, SQUARE //UNITS is number of feet, default is 5 feet on("ready",function(){ log('AOE Script READY'); on("chat:message",function(msg){ if(msg.type=="api" &amp;&amp; msg.content.indexOf("!AOE")==0) { var args = msg.content.split(" "); //looks for augment after !AOE for type height and width var AOEType = args[1] if(args[1]===undefined) { sendChat("AOE API","Type, Height or Width was not entered"); return; } //Height - Feet to pixel conversion var HeightFeet = Number(args[2])*.2 if(args[2]===undefined) { HeightFeet=5*.2; } var ht=70*HeightFeet if(isNaN(ht)){ sendChat("AOE API","Please enter a vaild number for Height"); return; } //Width - Feet to pixel conversion var WidthFeet = Number(args[3])*.2 if(args[3]===undefined) { WidthFeet=5*.2; } var wt=70*WidthFeet if(isNaN(wt)){ sendChat("AOE API","Please enter a vaild number for Width"); return; } //Making sure a character was selected var selected = msg.selected; if(selected===undefined) { sendChat("AOE API","Please Select a Token"); return; } //setting imgscr var by AOE type var AOEimg var ChatText switch(AOEType){ case "Line": AOEimg = "<a href="https://s3.amazonaws.com/files.d20.io/images/126640672/RsRo9Z1l_eLjsZ6ymnvXDw/thumb.png?158770167055" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/126640672/RsRo9Z1l_eLjsZ6ymnvXDw/thumb.png?158770167055</a>"; ChatText = "is using an AOE Template of a Line " + HeightFeet/.2 +"ft. long by " + WidthFeet/.2 + "ft. wide"; break; case "Circle": AOEimg = "<a href="https://s3.amazonaws.com/files.d20.io/images/126640666/njSD_xUkdGPirWLvOiUhTg/thumb.png?15877016695" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/126640666/njSD_xUkdGPirWLvOiUhTg/thumb.png?15877016695</a>"; ChatText = "is using an AOE Template of a Circle or Sphere with at Diameter of "+ WidthFeet/.2 + "ft. wide"; break; case "Cone": AOEimg = "<a href="https://s3.amazonaws.com/files.d20.io/images/126640680/WbEAoDFGjh_T6fIDOA9C2w/thumb.png?15877016735" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/126640680/WbEAoDFGjh_T6fIDOA9C2w/thumb.png?15877016735</a>"; ChatText = "is using an AOE Template of a Cone "+ WidthFeet/.2 + "ft. long"; break; case "Square": AOEimg = "<a href="https://s3.amazonaws.com/files.d20.io/images/126640653/xEykgzycg3KXenncO2NfOw/thumb.png?15877016675" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/126640653/xEykgzycg3KXenncO2NfOw/thumb.png?15877016675</a>"; ChatText = "is using an AOE Template of a " + HeightFeet/.2 + "ft. Square or Cube"; break; default: sendChat("AOE API","Please select Square, Line, Circle, or Cone for AOE Type"); return; } var tok = getObj("graphic",selected[0]._id); var character = getObj("character",tok.get("represents")); var playerList = character.get("controlledby"); //current math sets location under selected var objLeft = tok.get("left"); var objTop = tok.get("top")+((ht/2)-(70/2))+70; createObj("graphic",{ left:objLeft, top:objTop, height:ht, width:wt, pageid:tok.get("pageid"), layer:"objects", imgsrc:AOEimg, name:tok.get("name") + "'s " + AOEType, controlledby:playerList, isdrawing:true }); sendChat(tok.get("name"),ChatText); switch(AOEType){ case "Line": spawnFxBetweenPoints({x:tok.get("left"), y:tok.get("top")},{x:tok.get("left"), y:tok.get("top")+ht}, "beam-holy", tok.get("pageid")); break; case "Circle": spawnFx(objLeft, objTop,"burst-death",tok.get("pageid")); break; case "Cone": spawnFxBetweenPoints({x:tok.get("left"), y:tok.get("top")},{x:tok.get("left"), y:tok.get("top")+ht}, "breath-fire", tok.get("pageid")); break; case "Square": spawnFx(objLeft, objTop,"bomb-water",tok.get("pageid")); break; default: sendChat("AOE API","Please select Square, Line, Circle, or Cone for AOE Type"); return; } } }); });&nbsp;