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

[Performance] FullyFunctionalMooks

1464694710

Edited 1464694876
I have written a script which makes mooks fully functional. Characters for which the checkbox "is_mook" is set will be copied when their token is dropped to the table. The dropped token will be representing the copy of the orginal "mook_master". When a token is deleted which had been linked to a mook - but not a master, therefore a copy - the character will be deleted, along with all attributes and abilities associated with it. This works fine as long as I do it once a time and pretty slowly but it can easily crash the API when I drag multiple tokens to the table at once. I would appreciate any feedback on how to make this script faster and robust against the API. Essentially I do 3 things: 1. use findObjs once to retrieve all characters and test against this set if "character X" exists to find a unique name for the copy. 2. use findObj once to retrieve all attributes of the original character and iterate through this set and create one attribute for each attribute. For attributes in repeating items I extract the id and then use replace to replace the id with a newly generated one with the code posted by aaron here on the forum how to replicate the ID generation. 3. Repeat 2 for abilities. <a href="https://gist.github.com/NoxMortem/c732af87acfdee09" rel="nofollow">https://gist.github.com/NoxMortem/c732af87acfdee09</a>...
That's pretty awesome! I know that that'll clear up many GMs' Journal Pages. If only this could become a part of the actual R20 system. I'd totally use this if I could.
1464839074
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator
Not a critique, but an honest question since I'm not imaginative enough, but how does this improve on using the "link token, link bars, unlink bars, set fully-set-up token as default token for character" method?
1464839145
Silvyre
Forum Champion
Scott C. said: how does this improve on using the "link token, link bars, unlink bars, set fully-set-up token as default token for character" method? Allows for independent sets of Attributes.
1464839311
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator
ah, cool, like I said, not imaginative enough.
1464852292
Chris D.
Pro
Sheet Author
API Scripter
Compendium Curator
This approach is probably much easier than the one I am halfway though.&nbsp; I am attempting to upgrade my Earthdawn sheet so that each token has heavy use of status markers to set modifiers.&nbsp; For example if one token has the status marker that I have dubbed "Aggressive Attack" And another has both "Knocked Down" and "Increased Armor +2", then every action looks at both the attackers and defenders status markers and makes the appropriate adjustments. Thus every mook has only one character sheet, but each token can have heavily customized conditions and modifications. It is a complex approach.&nbsp;
1464867769

Edited 1464868033
Lithl
Pro
Sheet Author
API Scripter
Instead of finding all characters, and then filtering that list N+1 times, you could try: var characters = _.sortBy(filterObjs(function(obj) { return obj.get('type') === 'character' && obj.get('name').indexOf(name) === 0; }), function(chr) { var chrName = chr.get('name'), index = parseInt(chrName.substring(name.length + 1)); return isNaN(index) ? Infinity : -index; }), // [Mook 5, Mook 4, Mook 3, Mook 2, Mook] master = characters[characters.length - 1], highestNumbered = characters[0], nextNumber, newName; if (!highestNumbered) { log(`No character "${name}" found`); return; } if (highestNumbered === master) { nextNumber = 2; } else { nextNumber = parseInt(highestNumbered.get('name').substring(name.length + 1)) + 1; } newName = `${name} + ${nextNumber}`; The filterObjs call here is essentially combining your findObjs and your first filter call. The sortBy omits the need to search the list of characters in a while loop repeatedly. The above code does &nbsp;allow for fragmentation of mook numbers (eg, if you have Mook, Mook 2, Mook 3, Mook 4, and Mook 5, delete Mook 3 and create a new mook, you'll be creating Mook 6 instead of a new Mook 3), but that doesn't seem like a major issue when the primary interest is unique names over densely packed numerals. The only other thing I can think of that might give you a speedup would be storing your RegExp objects outside your loop instead of creating new ones each loop iteration (also, the double replace call for removing the repeating attribute prefix ought to be possible to bring down to a single replace with a slightly different regex), but it shouldn't make very much of a difference if there's any.
Not a critique, but an honest question since I'm not imaginative enough, but how does this improve on using the "link token, link bars, unlink bars, set fully-set-up token as default token for character" method? It is a necessity for everything that goes beyound the three linked attributes - and it is even with a copy that takes seconds - faster. For example, if you have a skill which applies a buff to selected tokens, which then will alter the attribute for this token and this token only, this is impossible with the roll20 default mook system. Script Workers and Scripts would not work anymore as all tokens would reference to the same character. I for example use Aarons Group Initiative script to roll initiative for a set of selected tokens. As long as you only read attributes, everything is fine, the second you want to have 2 tokens where one attribute which is not a linked token bar attribute, to change, you can not do this (at least only very difficult with scripts). Creating a copy of the character is the dumb way to be sure that Script Workers and Scripts can work on all tokens equally. If only this could become a part of the actual R20 system. I'd totally use this if I could. If they implement something similar like this I wish they implement it in a Copy-On-Write semantic way. This would mean it would not be necessary to copy any attribute until you write to an attribute of the copy, at which point only this particular attribute would be copied. However, this is not easily implemented with scripts, as you would have to track for all the scripts if the script is running on a copy or the original and there are so many side effects you would have to check. @Brian, thank you so much, I will try this as soon as I find time for it!
1469580346

Edited 1469581195
I'm not entirely sure how to use this exactly. There's no is_mook checkbox.
Agree, not sure what you mean by is_mook?
1469632621

Edited 1469632787
I assume there has been some confusion: The script above was a tech showcase on how to implement it and not the release of an easily shareable script :) The linked code only does the copy of a character and is not linked to any events yet. With the help of Aaron I also have made some more improvements like adding asynchronous copy which made the script way more stable but this now also added additional code and complexity. It still is a pain-in-the-ass as copying characters on roll20 is super slow and tedious. If someone needs the latest asynchronous version to build upon it, just let me know, but this thread was not the release of a script, but more a request to others for additional input how to make this faster and more stable as this functionality is such a huge amount of workload it can easily kill your API sandbox (for several characters or a huge character sheet with a lot of data)