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

[Request] Item Drops

1437280547

Edited 1437281608
Completely new to the API and coding in general, so I have a bit of a request. I'm working on a game inspired by Sword Art Online, so I'm looking for an individual item drop system including rarity. The only/easiest way I think to do this is by basically rolling a d50 and running a lot of 'if-then' codes. You can get close with the 'roll-able tables' but I'm not aware of a way to roll the second time, and it really clutters the chat. 1-10 No drops 11-25 Drops a common item (Raw Wolves Meat) then it rolls a d3 for quantity of meat 26-30 Drops a uncommon item (Wolves Pelt) then it rolls a d2 for number of pelts 31-40 Drops both (Meat) and (Pelt) then rolls for both 41-44 Drops a rare item (Wolves Fang) then it rolls a d3 45-50 Drops at least one of everything 1-50 5-10 CP !dropsWolves It makes all the rolls to DM, then publicly it says; "Item Drops Raw Wolves Meat 1 Wolves Pelt 2 10 CP" Ideally; user friendly when it comes to adding new macros, modifying drops, rarity, chances, quantity Unnecessary perhaps unrealistically (but would be nice); Color coding VIA rarity; Common = White, Uncommon = Green, Rare = Blue, Legendary = Orange Automatically adding this information to a player unique handout, which each player would have as an additional backpack. The program cycles through the players - !dropsX text box unique to player 1. !dropsX text box unique to player 2. !dropsX text box unique to player 3. !dropsY resets back to player 1. !dropsY text box unique to player 2. etc ^^^ Whispered to each player (Maybe player 1 doesn't want the party to know he dropped a Legendary)
1437311301

Edited 1437311340
Lithl
Pro
Sheet Author
API Scripter
David said: Completely new to the API and coding in general, so I have a bit of a request. I'm working on a game inspired by Sword Art Online, so I'm looking for an individual item drop system including rarity. The only/easiest way I think to do this is by basically rolling a d50 and running a lot of 'if-then' codes. You can get close with the 'roll-able tables' but I'm not aware of a way to roll the second time, and it really clutters the chat. 1-10 No drops 11-25 Drops a common item (Raw Wolves Meat) then it rolls a d3 for quantity of meat 26-30 Drops a uncommon item (Wolves Pelt) then it rolls a d2 for number of pelts 31-40 Drops both (Meat) and (Pelt) then rolls for both 41-44 Drops a rare item (Wolves Fang) then it rolls a d3 45-50 Drops at least one of everything 1-50 5-10 CP You can't make rollable tables re-roll, but you can set up the table's probabilities to produce the same results. As a small example, consider a d6 exploding once: First Second Total 1 1 2 2 3 3 4 4 5 5 6 1 7 6 2 8 6 3 9 6 4 10 6 5 11 6 6 12 Naturally, this particular example could be rolled with [[d6ro]], but you could also implement it with a rollable table: Name Weight 1 1 2 1 3 1 4 1 5 1 7 1 8 1 9 1 10 1 11 1 12 1 With a lot of possibilities, the table could get quite large, but it is possible. Using the API would be much shorter. Something like this: var drops = (function() { 'use strict'; var commands = { 'dropswolves': function(msg, args) { var wolves = generateDrops('Raw Wolves Meat', 3, 'Wolves Pelt', 2, 'Wolves Fang', 3, 'CP', [5, 10], [11, 25], [26, 30], [31, 40], [41, 44], [45, 50], [1, 50]), message = 'Item Drops'; _.each(wolves, function(outputLine) { message += '<br>' + outputLine; }); sendChat('System', message); } }; function generateDrops(commonItem, commonAmount, uncommonItem, uncommonAmount, rareItem, rareAmount, coinType, coinAmount, commonDrop, uncommonDrop, commonUncommonDrop, rareDrop, allDrop, coinDrop) { var rngRange = _.flatten([noDrop, commonDrop, uncommonDrop, commonUncommonDrop, rareDrop, allDrop, coinDrop]), max = _.max(rngRange), min = _.min(rngRange), rng = randomInteger(max - min + 1) + min - 1, result = {}, output = []; result[commonItem] = 0; result[uncommonItem] = 0; result[rareItem] = 0; result[coinType] = 0; if (commonDrop[0] <= rng && rng <= commonDrop[1]) { result[commonItem] += randomInteger(commonAmount); } if (uncommonDrop[0] <= rng && rng <= uncommonDrop[1]) { result[uncommonItem] += randomInteger(uncommonAmount); } if (commonUncommonDrop[0] <= rng && rng <= commonUncommonDrop[1]) { result[commonItem] += randomInteger(commonAmount); result[uncommonItem] += randomInteger(uncommonAmount); } if (rareDrop[0] <= rng && rng <= rareDrop[1]) { result[rareItem] += randomInteger(rareAmount); } if (allDrop[0] <= rng && rng <= allDrop[1]) { result[commonItem] += randomInteger(commonAmount); result[uncommonItem] += randomInteger(uncommonAmount); result[rareItem] += randomInteger(rareAmount); } if (coinDrop[0] <= rng && rng <= coinDrop[1]) { result[coinType] += randomInteger(coinAmount[1] - coinAmount[0] + 1) + coinAmount[0] - 1; } if (result[commonItem] > 0) { output.push(commonItem + ' ' + result[commonItem]); } if (result[uncommonItem] > 0) { output.push(uncommonItem + ' ' + result[uncommonItem]); } if (result[rareItem] > 0) { output.push(rareItem + ' ' + result[rareItem]); } if (result[coinType] > 0) { output.push(result[coinType] + ' ' + coinType); } return output; } function handleInput(msg) { var args = msg.content.split(' '), command = args.shift().substring(1).toLowerCase(); if (commands[command]) { commands[command](msg, args); } } function registerEventHandlers() { on('chat:message', handleInput); } return { registerEventHandlers: registerEventHandlers }; }()); on('ready', function() { 'use strict'; drops.registerEventHandlers(); }); I've tried to generalize it a bit so that the drop rates and amounts could be easily changed, and so you could have things other than wolf bits. The above doesn't include any of your 'nice to have' bullets, although the color coding would be fairly simple (edit the "output.push" lines), and the rest could certainly be added (edit the 'dropswolves' function, mostly). All of the above code is untested.
Assuming I even did everything correct when adding, and running the script (command is '!dropswolves')? /home/symbly/www/d20-api-server/node_modules/firebase/lib/firebase-node.js:1 orts, require, module, __filename, __dirname) { function g(a){throw a;}var j=v ^ ReferenceError: noDrop is not defined at generateDrops (evalmachine.<anonymous>:19:35) at Object.commands.dropswolves (evalmachine.<anonymous>:7:26) at handleInput (evalmachine.<anonymous>:78:30) at eval ( Shows up in the log
1437346089
Lithl
Pro
Sheet Author
API Scripter
Whoops, forgot to remove the noDrop from the rngRange when I realized it wasn't actually needed. The first line of generateDrops should be: var rngRange = _.flatten([commonDrop, uncommonDrop, commonUncommonDrop, rareDrop, allDrop, coinDrop]),
Cool, definitely does work, and I can easily incorporate it. Based on my limited knowledge of JS that I've come to learn just today from CodeAcademy and the internet... output.push(commonItem.fontcolor("green") + ' ' + result[commonItem].fontcolor("green")); Why doesn't this work? Also how to do you put the code in it's separate box.
1437359672
Lithl
Pro
Sheet Author
API Scripter
commonItem is a string and result[commonItem] is a number. Neither strings nor numbers have a function fontcolor. What you could do is something like this: output.push('<span style="color:green">' + commonItem + ' ' + result[commonItem] + '</span>'); Creating a code box is a matter of clicking the Formatting button at the top-left of the Post Replay box and selecting "Code".
1437375155

Edited 1437376026
Color added, also tried adding 'Unique' and 'Legendary' qualities, some of the stuff I added (so I don't post a 100+ line script..) function generateDrops(commonItem, commonAmount, uncommonItem, uncommonAmount, rareItem, rareAmount, uniqueItem, uniqueAmount, legendaryItem, legendaryAmount, coinType, coinAmount, commonDrop, uncommonDrop, commonUncommonDrop, rareDrop, rareUncommonCommonDrop, uniqueDrop, uniqueRareUncommonCommonDrop, allDrop, coinDrop) { result[uniqueItem] = 0; result[legendaryItem] = 0; if (uniqueRareUncommonCommonDrop[0] <= rng && <= uniqueRareUncommonCommonDrop[1]) { result[commonItem] += randomInteger(commonAmount); result[uncommonItem] += randomInteger(uncommonAmount); result[rareItem] += randomInteger(rareAmount); result[uniqueItem] += randomInteger(uniqueAmount); } if (allDrop[0] <= rng && rng <= allDrop[1]) { result[commonItem] += randomInteger(commonAmount); result[uncommonItem] += randomInteger(uncommonAmount); result[rareItem] += randomInteger(rareAmount); result[uniqueItem] += randomInteger(uniqueAmount); result[legendaryItem] += randomInteger(legendaryAmount); } if (result[uniqueItem] > 0) { output.push('<span style="color:orange">' + uniqueItem + ' ' + result[uniqueItem] + '</span>'); } if (result[legendaryItem] > 0) { output.push('<span style="color:red">' + legendaryItem + ' ' + result[legendaryItem] + '</span>'); } Do you know if that would bug the API if there isn't a named item for those changes. Getting the error "Unexpected token ["
1437388905
Lithl
Pro
Sheet Author
API Scripter
This line: if (uniqueRareUncommonCommonDrop[0] <= rng && <= uniqueRareUncommonCommonDrop[1]) { Should definitely be: if (uniqueRareUncommonCommonDrop[0] <= rng && rng <= uniqueRareUncommonCommonDrop[1]) { At a glance I don't see any other errors in the code you've added, but I wouldn't expect that mistake to generate the error you've quoted.
Is the ' ' to represent a space?
Really hate to do this but I cannot find this error for the life of me... Are the 'x:y' in the error supposed to represent 'line, count?' /home/symbly/www/d20-api-server/node_modules/firebase/lib/firebase-node.js:1 orts, require, module, __filename, __dirname) { function g(a){throw a;}var j=v ^ TypeError: Cannot read property '0' of undefined at generateDrops (evalmachine.<anonymous>:41:31) at Object.commands.dropswolves (evalmachine.<anonymous>:7:26) at handleInput (evalmachine.<anonymous>:105:30) at eval ( var drops = (function() {     'use strict';     var commands = {         'dropswolves': function(msg, args) {             var wolves = generateDrops('Raw Wolves Meat', 3, 'Wolves Pelt', 2, 'Wolves Fang', 3, 'CP', [5, 10],                                        [11, 25], [26, 30], [31, 40], [41, 44], [45, 50], [1, 50]),                 message = 'Item Drops';             _.each(wolves, function(outputLine) {                 message += '<br>' + outputLine;             });             sendChat('System', message);         }     };     function generateDrops(commonItem, commonAmount, uncommonItem, uncommonAmount, rareItem, rareAmount, uniqueItem, uniqueAmount, legendaryItem, legendaryAmount,         coinType, coinAmount, commonDrop, uncommonDrop, commonUncommonDrop, rareDrop, rareUncommonCommonDrop, uniqueDrop, uniqueRareUncommonCommonDrop, allDrop, coinDrop) {         var rngRange = _.flatten([commonDrop, uncommonDrop, commonUncommonDrop, rareDrop, rareUncommonCommonDrop, uniqueDrop, uniqueRareUncommonCommonDrop, allDrop, coinDrop]),             max = _.max(rngRange),             min = _.min(rngRange),             rng = randomInteger(max - min + 1) + min - 1,             result = {},             output = [];         result[commonItem] = 0;         result[uncommonItem] = 0;         result[rareItem] = 0;         result[uniqueItem] = 0;         result[legendaryItem] = 0;         result[coinType] = 0;         if (commonDrop[0] <= rng && rng <= commonDrop[1]) {             result[commonItem] += randomInteger(commonAmount);         }         if (uncommonDrop[0] <= rng && rng <= uncommonDrop[1]) {             result[uncommonItem] += randomInteger(uncommonAmount);         }         if (commonUncommonDrop[0] <= rng && rng <= commonUncommonDrop[1]) {             result[commonItem] += randomInteger(commonAmount);             result[uncommonItem] += randomInteger(uncommonAmount);         }         if (rareDrop[0] <= rng && rng <= rareDrop[1]) {             result[rareItem] += randomInteger(rareAmount);         }                  if (rareUncommonCommonDrop[0] <= rng && rng <= rareUncommonCommonDrop[1]) {             result[commonItem] += randomInteger(commonAmount);             result[uncommonItem] += randomInteger(uncommonAmount);             result[rareItem] += randomInteger(rareAmount);         }                  if (uniqueDrop[0] <= rng && rng <= uniqueDrop[1]) {             result[uniqueItem] += randomInteger(uniqueAmount);         }                  if (uniqueRareUncommonCommonDrop[0] <= rng && rng <= uniqueRareUncommonCommonDrop[1]) {             result[commonItem] += randomInteger(commonAmount);             result[uncommonItem] += randomInteger(uncommonAmount);             result[rareItem] += randomInteger(rareAmount);             result[uniqueItem] += randomInteger(uniqueAmount);         }         if (allDrop[0] <= rng && rng <= allDrop[1]) {             result[commonItem] += randomInteger(commonAmount);             result[uncommonItem] += randomInteger(uncommonAmount);             result[rareItem] += randomInteger(rareAmount);             result[uniqueItem] += randomInteger(uniqueAmount);             result[legendaryItem] += randomInteger(legendaryAmount);         }         if (coinDrop[0] <= rng && rng <= coinDrop[1]) {             result[coinType] += randomInteger(coinAmount[1] - coinAmount[0] + 1) + coinAmount[0] - 1;         }         if (result[commonItem] > 0) {             output.push(commonItem + ' ' + result[commonItem]);         }         if (result[uncommonItem] > 0) {             output.push('<span style="color:green">' + uncommonItem + ' ' + result[uncommonItem] + '</span>');         }         if (result[rareItem] > 0) {             output.push('<span style="color:purple">' + rareItem + ' ' + result[rareItem] + '</span>');         }         if (result[uniqueItem] > 0) {             output.push('<span style="color:orange">' + uniqueItem + ' ' + result[uniqueItem] + '</span>');         }         if (result[legendaryItem] > 0) {             output.push('<span style="color:red">' + legendaryItem + ' ' + result[legendaryItem] + '</span>');         }         if (result[coinType] > 0) {             output.push(result[coinType] + ' ' + coinType);         }         return output;     }     function handleInput(msg) {         var args = msg.content.split(' '),             command = args.shift().substring(1).toLowerCase();         if (commands[command]) {             commands[command](msg, args);         }     }     function registerEventHandlers() {         on('chat:message', handleInput);     }     return {         registerEventHandlers: registerEventHandlers     }; }()); on('ready', function() {     'use strict';     drops.registerEventHandlers(); });
1437519608
The Aaron
Pro
API Scripter
generateDrops() has 20 arguments (consider using an object instead?) and you're passing it 14 arguments, the 15th argument is commonUncommonDrop.  Since you aren't passing it in, it is undefined .  You are accessing the zeroth element (the 0 property) of it on line 46, which results in " Cannot read property '0' of undefined "
1437548329

Edited 1437551906
Well, I personally don't know the difference between using variables compared to objects. I was graciously given a script, and so I'll modify it to my needs. Is there a particular limit to the number of arguments that can be run? Why is that particular line 'not passed.' [Edit] Did some testing, first adding the lines for 'unique' generateDrops(commonItem, commonAmount, uncommonItem, uncommonAmount, rareItem, rareAmount, uniqueItem, uniqueAmount, uniqueDrop result[uniqueItem] = 0; if (uniqueDrop[0] <= rng && rng <= uniqueDrop[1]) {             result[uniqueItem] += randomInteger(uniqueAmount);         } if (result[uniqueItem] > 0) {             output.push(uniqueItem + ' ' + result[uniqueItem]);         } Generated an 'undefined error.' Added a named item and a rng range. var wolves = generateDrops('Raw Wolves Meat', 3, 'Wolves Pelt', 2, 'Wolves Fang', 3, 'Wolves Unique', 2, 'CP', [5, 10],                                        [11, 25], [26, 30], [31, 40], [41, 44], [45, 48], [49, 50], [1, 50]), Worked, added all the same for 'legendary,' and worked. Added a new drop 'uniqueLegendaryDrop,' and the results. Error, added a rng range of [0] as far as I can tell that'll work. var wolves = generateDrops('Raw Wolves Meat', 3, 'Wolves Pelt', 2, 'Wolves Fang', 3, 'Wolves Unique', 2, 'Wolves Legendary', 2, 'CP', [5, 10],                                        [11, 25], [26, 30], [31, 40], [41, 44], [45, 50], [0], [0], [0], [1, 50]), So I'll be applying all these changes to the original '20+ argument mess' unless there's something else that would more efficient. In the meanwhile, how would I go about centering the outputs in an info box so it doesn't all combine.
1437550824
Lithl
Pro
Sheet Author
API Scripter
David said: Well, I personally don't know the difference between using variables compared to objects. I was graciously given a script, and so I'll modify it to my needs. Is there a particular limit to the number of arguments that can be run?  No real limit, but Aaron is recommending something along these lines: function generateDrops(options) { var rngRange = _.flatten(_.values(options.dropChances)),             max = _.max(rngRange),             min = _.min(rngRange),             rng = randomInteger(max - min + 1) + min - 1,             result = {},             output = [], commonItem = options.names.common || '', commonAmount = options.amounts.common || 0, commonDrop = options.dropChances.common || [0, 0], etc...; } Given that, it would be called like: generateDrops({ names: { common: 'Raw Wolves Meat', uncommon: 'Wolves Pelt', rare: 'Wolves Fang', etc... }, amounts: { common: 3, uncommon: 2, rare: 3, etc... }, dropChances: { common: [11, 25], uncommon: [26, 30], commonUncommon: [31, 40], rare: [41, 44], all: [45, 50], etc... } }); It just makes the function definition look a bit cleaner, and maybe a little bit easier to catch any properties that you forget to pass in. David said: Why is that particular line 'not passed.' In order for generateDrops() to know all the variables, you have to pass them. The code I wrote passes those parameters on lines 6 and 7. When you modified the code, you added additional function parameters, but you didn't add them to the point where the function is called. JavaScript doesn't care if you skip some of the method parameters, and it will happily (even in strict mode) leave the unspecified parameters as undefined. 
1437552713

Edited 1437552789
Edited my previous post, if you'd like to scroll up a bit. A rather significant question however, the way that the script is currently set up, only applies for a single mob, correct? If there's 10 mobs, you'd need 10 different API scripts. If... Theres... 300-400.... Then.... *twiddles thumbs*
1437558771

Edited 1437558970
Lithl
Pro
Sheet Author
API Scripter
David said: In the meanwhile, how would I go about centering the outputs in an info box so it doesn't all combine. Something like this should work: message = '/direct <div style="text-align:center"><span style="font-weight:bold">Item Drops</span>'; _.each(wolves, function(outputLine) { message += '<br>' + outputLine; }); message += '</div>'; sendChat('System', message); David said: Edited my previous post, if you'd like to scroll up a bit. A rather significant question however, the way that the script is currently set up, only applies for a single mob, correct? If there's 10 mobs, you'd need 10 different API scripts. If... Theres... 300-400.... Then.... *twiddles thumbs* When I wrote it, I tried to make it easy to add new enemy types for you: var commands = { 'dropswolves': function(msg, args) { var wolves = generateDrops('Raw Wolves Meat', 3, 'Wolves Pelt', 2, 'Wolves Fang', 3, 'CP', [5, 10], [11, 25], [26, 30], [31, 40], [41, 44], [45, 50], [1, 50]); postDrops('Wolf', wolves); }, 'dropsducks': function(msg, args) { var ducks = generateDrops(...); postDrops('Duck', ducks); }, 'dropshamsters': function(msg, args) { var boos = generateDrops(...); postDrops('Miniature Giant Space Hamster', boos); } // and so on }; function postDrops(enemy, drops) { var message = '/direct <div style="text-align:center"><span style="font-weight:bold">' + enemy + ' Item Drops</span>'; _.each(drops, function(outputLine) { message += '<br>' + outputLine; }); message += '</div>'; sendChat('System', message); } That should lead to minimal duplication, and you'd presumably want different drop rates for the different items from different enemies, so you'd have  to have separate calls to generateDrops() no matter what. Note that the way the script is written, the properties in the commands  object ('dropswolves', 'dropsducks', etc.) must be all lower-case (and must not contain spaces), but when you actually use the command from the chat window of the VTT, you can use any capitalization: !dropswolves, !dropsWolves, !dRoPsWoLvEs, etc.
Everything's working perfectly, decided to change it just so when you roll it drops the highest quality and everything underneath for my own sanity... Something else that's bound to come up, when a party fights 10 wolves at a time and rather then (!dropswolves)x10 per person. '!dropswolves10' which just simply multiplies the results by a number value. Definitely appreciate all the help Brian, and this seems simple enough, maybe you could give me a hint and I'll try my hand at coding before inevitably returning a confused messed.
1437721045
Lithl
Pro
Sheet Author
API Scripter
So the way the script is set up, the commands functions all have access to the space-separated arguments passed to the command, and the original msg object. This lets you do things like add some argument parsing for, say, !dropswolves 10 and iterate 10 times. Here's how I would make those modifications: 'dropswolves': function(msg, args) { var wolves = ['Nothing'], i, accumulator = {}, count = 1; if (args.length > 0) { count = parseInt(args[0]); if (!count && count !== 0) { count = 1; } } for (i = 0; i < count; i++) { wolves = generateDrops(...etc..., accumulator); } postDrops('Wolf', wolves); } ... function generateDrops(..., result) { var rngRange = ..., max = ..., min = ..., rng = ..., //result = {}, -- get rid of this line output = []; result = result || {}; if (!result[commonItem]) { result[commonItem] = 0; } if (!result[uncommonItem]) { result[uncommonItem] = 0; } ...etc... ... // the rest of the function remains unchanged return output; } The first time generateDrops() is called, it fills in the values in the accumulator/result object. The function returns the list of strings as before, but then generateDrops() is called again with the same accumulator object, making result  start with values other than 0. The above is also designed so that you can call !dropswolves with the same functionality as !dropswolves 1. If the first argument you pass is not a number (eg, !dropwolves Jeff) then count  will be 1, as well. You can pass a negative value (!dropswolves -5) or 0, in which case generateDrops() will never be called, and the output will be "Item Drops // Nothing".
Not sure where I went wrong.. var drops = (function() {     'use strict';     var commands = {         'dropswolves': function(msg, args) {             var wolves = ['Nothing'], i,                 accumulator = {},                 count = 1;                              if (args.length > 0) {                 count = parseInt(args[0]);                 if (!count && count !== 0) {                     count = 1;                 }             }                          for (i = 0; 1 < count; i++) {                 wolves = generateDrops('Raw Wolves Meat', 3, 'Wolves Pelt', 2, 'Wolves Fang', 3, 'NA', 1, 'NA', 1, 'CP', [5, 10],                                        [11, 40], [26, 40], [31, 40], [0], [0], [1, 40], accumulator);             }                 postDrops('Wolf', wolves);         }                  'dropsboars': function(msg, args) {             var boars = ['Nothing'], i,                 accumulator = {},                 count = 1;                              if (args.length > 0) {                 count = parseInt(args[0]);                 if (!count && count !== 0) {                     count = 1;                 }             }             for (i = 0; 1 < count; i++) {                 boars = generateDrops('L1', 2, 'L2', 2, 'L3', 2, 'NA', 1, 'NA', 1, 'GP', [3, 10],                                        [11, 25], [26, 30], [31, 40], [0], [0], [1, 40], accumulator);             }                 postDrops('Boars', boars);         }     };          function postDrops(enemy, drops) {         var message = '<span style="font-weight:bold">' + enemy + ' ' + 'Item Drops</span>';         _.each(drops, function(outputLine) {             message += '<br>' + outputLine;         });         sendChat('System', message);     }     function generateDrops(commonItem, commonAmount, uncommonItem, uncommonAmount, rareItem, rareAmount, uniqueItem, uniqueAmount, legendaryItem, legendaryAmount, coinType, coinAmount, commonDrop, uncommonDrop, rareDrop, uniqueDrop, legendaryDrop, coinDrop, result) {         var rngRange = _.flatten([commonDrop, uncommonDrop, rareDrop, uniqueDrop, legendaryDrop, coinDrop]),             max = _.max(rngRange),             min = _.min(rngRange),             rng = randomInteger(max - min + 1) + min - 1,             output = [];                      result = result || {};         if (!result[commonItem]) {             result[commonItem] = 0;         }         if (!result[uncommonItem]) {             result[uncommonItem] = 0;         }         if (!result[rareItem]) {             result[rareItem] = 0;         }         if (!result[uniqueItem]) {             result[uniqueItem] = 0;         }         if (!result[legendaryItem]) {             result[legendaryItem] = 0;         }
1438404067

Edited 1438404734
Lithl
Pro
Sheet Author
API Scripter
            for (i = 0; 1 < count; i++) { At a glance, this is the only error I see (present in both wolves and boars). It should be i < count, not 1 < count. The structure of a for-loop is [initialization]; [condition]; [final expression] . The initialization is run at the start of the loop, the final expression is run at the end of each iteration, and the condition is run at the beginning of each iteration (if the result is true, the iteration happens, otherwise the loop ends). 1 < count is always true (if count is greater than 1) or always false (if count is 1 or less), so the loop would either never stop or never start. On the other hand, i < count (when i is being incremented by 1 each iteration) will end the loop appropriately.
1438420261

Edited 1438420911
Should've copied a bit further down, not sure if I was supposed to replace the original 'result' lines. After the edits, error is defined as 'unexpected token :' To me, it seems odd that you define the variables 'wolves/boars' twice, or is that irrelevant.  }         if (!result[legendaryItem]) {             result[legendaryItem] = 0;         }         result[commonItem] = 0;         result[uncommonItem] = 0;         result[rareItem] = 0;         result[uniqueItem] = 0;         result[legendaryItem] = 0;         result[coinType] = 0;         if (commonDrop[0] <= rng && rng <= commonDrop[1]) {             result[commonItem] += randomInteger(commonAmount); ...
1438426458
Lithl
Pro
Sheet Author
API Scripter
No. The series of if (!result[...]) { result[...] = 0; }  statements should replace the result[...] = 0; statements from the earlier version. Sorry if that wasn't clear.
Still seems to be an error, though now it isn't defined.
1438490983
Lithl
Pro
Sheet Author
API Scripter
Could you post the exact error and the full code that you've got at the moment?
hm now it's "Unexpected token :" var drops = (function() {     'use strict';     var commands = {         'dropswolves': function(msg, args) {             var wolves = ['Nothing'], i,                 accumulator = {},                 count = 1;                              if (args.length > 0) {                 count = parseInt(args[0]);                 if (!count && count !== 0) {                     count = 1;                 }             }                          for (i = 0; i < count; i++) {                 wolves = generateDrops('Raw Wolves Meat', 3, 'Wolves Pelt', 2, 'Wolves Fang', 3, 'NA', 1, 'NA', 1, 'CP', [5, 10],                                        [11, 40], [26, 40], [31, 40], [0], [0], [1, 40], accumulator);             }                 postDrops('Wolf', wolves);         }                  'dropsboars': function(msg, args) {             var boars = ['Nothing'], i,                 accumulator = {},                 count = 1;                              if (args.length > 0) {                 count = parseInt(args[0]);                 if (!count && count !== 0) {                     count = 1;                 }             }                          for (i = 0; i < count; i++) {                 boars = generateDrops('L1', 2, 'L2', 2, 'L3', 2, 'NA', 1, 'NA', 1, 'GP', [3, 10],                                        [11, 40], [26, 40], [31, 40], [0], [0], [1, 40], accumulator);             }                 postDrops('Boars', boars);         }     };          function postDrops(enemy, drops) {         var message = '<span style="font-weight:bold">' + enemy + ' ' + 'Item Drops</span>';         _.each(drops, function(outputLine) {             message += '<br>' + outputLine;         });         sendChat('System', message);     }     function generateDrops(commonItem, commonAmount, uncommonItem, uncommonAmount, rareItem, rareAmount, uniqueItem, uniqueAmount, legendaryItem, legendaryAmount, coinType, coinAmount, commonDrop, uncommonDrop, rareDrop, uniqueDrop, legendaryDrop, coinDrop, result) {         var rngRange = _.flatten([commonDrop, uncommonDrop, rareDrop, uniqueDrop, legendaryDrop, coinDrop]),             max = _.max(rngRange),             min = _.min(rngRange),             rng = randomInteger(max - min + 1) + min - 1,             output = [];         result = result || {};         if (!result[commonItem]) {             result[commonItem] = 0;         }         if (!result[uncommonItem]) {             result[uncommonItem] = 0;         }         if (!result[rareItem]) {             result[rareItem] = 0;         }         if (!result[uniqueItem]) {             result[uniqueItem] = 0;         }         if (!result[legendaryItem]) {             result[legendaryItem] = 0;         }         if (commonDrop[0] <= rng && rng <= commonDrop[1]) {             result[commonItem] += randomInteger(commonAmount);         }         if (uncommonDrop[0] <= rng && rng <= uncommonDrop[1]) {             result[uncommonItem] += randomInteger(uncommonAmount);         }         if (rareDrop[0] <= rng && rng <= rareDrop[1]) {             result[rareItem] += randomInteger(rareAmount);         }                  if (uniqueDrop[0] <= rng && rng <= uniqueDrop[1]) {             result[uniqueItem] += randomInteger(uniqueAmount);         }                  if (legendaryDrop[0] <= rng && rng <= legendaryDrop[1]) {             result[legendaryItem] += randomInteger(legendaryAmount);         }         if (coinDrop[0] <= rng && rng <= coinDrop[1]) {             result[coinType] += randomInteger(coinAmount[1] - coinAmount[0] + 1) + coinAmount[0] - 1;         }         if (result[commonItem] > 0) {             output.push('<span style="color:black">' + commonItem + ' ' + result[commonItem] + '</span>');         }         if (result[uncommonItem] > 0) {             output.push('<span style="color:green">' + uncommonItem + ' ' + result[uncommonItem] + '</span>');         }         if (result[rareItem] > 0) {             output.push('<span style="color:blue">' + rareItem + ' ' + result[rareItem] + '</span>');         }         if (result[uniqueItem] > 0) {             output.push('<span style="color:orange">' + uniqueItem + ' ' + result[uniqueItem] + '</span>');         }         if (result[legendaryItem] > 0) {             output.push('<span style="color:red">' + legendaryItem + ' ' + result[legendaryItem] + '</span>');         }         if (result[coinType] > 0) {             output.push(result[coinType] + ' ' + coinType);         }         return output;     }     function handleInput(msg) {         var args = msg.content.split(' '),             command = args.shift().substring(1).toLowerCase();         if (commands[command]) {             commands[command](msg, args);         }     }     function registerEventHandlers() {         on('chat:message', handleInput);     }     return {         registerEventHandlers: registerEventHandlers     }; }()); on('ready', function() {     'use strict';     drops.registerEventHandlers(); });
1438531952
Lithl
Pro
Sheet Author
API Scripter
    var commands = {         'dropswolves': function(msg, args) {             ...         }                  'dropsboars': function(msg, args) {             ...         }     }; You need to have a comma between each property in the commands object:     var commands = {         'dropswolves': function(msg, args) {             ...         },                  'dropsboars': function(msg, args) {             ...         }     }; Also, I've realized that the output will appear odd if the loot roll occurs  but comes up with nothing. To that end, I recommend changing the postDrops function thusly:     function postDrops(enemy, drops) {         var message = '<span style="font-weight:bold">' + enemy + ' ' + 'Item Drops</span>'; if (drops && drops.length === 0) { drops = ['Nothing']; }         _.each(drops, function(outputLine) {             message += '<br>' + outputLine;         });         sendChat('System', message);     }
That's going to be fun to debug when there's 100+ monsters.. So how do you identify a specific player and modify the output to a whisper.
1438835024
Lithl
Pro
Sheet Author
API Scripter
Much like adding the count  argument, you could add an argument to specify who to whisper the message to. The msg object also contains information about who called the API command, so you could echo the result back to the GM, for example. You can also make sure the command is only used by the GM:     var commands = {         'dropswolves': function(msg, args) {             var wolves = ['Nothing'], i                 accumulator = {},                 count = 1, whisper = '';             // Remove this line if you want to let anyone use the command if (!playerIsGM(msg.playerid)) return;             if (args.length > 0) {                 count = parseInt(args[0]);                 if (!count && count !== 0) {                     count = 1;                 }             } if (args.length > 1) { whisper = '/w "' + args.slice(1, args.length).join(' ') + '" '; }                          for (i = 0; i < count; i++) {                 wolves = generateDrops('Raw Wolves Meat', 3, 'Wolves Pelt', 2, 'Wolves Fang', 3, 'NA', 1, 'NA', 1, 'CP', [5, 10],                                        [11, 40], [26, 40], [31, 40], [0], [0], [1, 40], accumulator);             }             postDrops('Wolf', wolves, whisper, msg.who);         },                  'dropsboars': function(msg, args) {             ...         }     };          function postDrops(enemy, drops, whisper, caller) {         var message = '<span style="font-weight:bold">' + enemy + ' ' + 'Item Drops</span>';         _.each(drops, function(outputLine) {             message += '<br>' + outputLine;         });         sendChat('System', whisper + message); if (whisper !== '') { sendChat('System', '/w "' + caller + '" ' + message); }     } That should let you call "!dropsWolves 1 Steve Steverson" for example, and the script will whisper the result to both you and to Steve. If you just call "!dropsWolves 1" or "!dropsWolves", the message will be put in chat for all to see.
Is there a way in a separate function to designate a playerID to a variable, then have the output cycle through 'w, x, y, z' without specifically naming them in the '!drop command?' Worried about the long run at some point 'wolves' changes into 'dire/rabid/undead/whitewolves', adding the time it takes to type each individuals name, the chances for mistakes. Particularly adding 5-6 lines to each !drop function.
1438919831
Lithl
Pro
Sheet Author
API Scripter
That's certainly doable, although it's not as trivial as the stuff so far in this thread (which has by and large been "roll some dice and throw up an output"). I don't have time at the moment to write that, but I should be able to come Sunday or Monday.
 
 
1441198444
The Aaron
Roll20 Production Team
API Scripter
David, are you having troubles posting to the forum?  Your last two messages are blank?
No, just bumping
1441377339
The Aaron
Roll20 Production Team
API Scripter
I see.   Please don't bump your thread, this falls under the “irritating repetition” mentioned in the Civil Discussion section of the Code of Conduct . Specifically, you don't need to simply bump your thread in the API forum.  If there is something unanswered, just post restating that question.  Probably the people reading the post didn't realize it was unanswered or even a question.  Highlighting your question will introduce further discussion.  Your bumping will just irritate people and won't get you answers.
I do like the idea, and im not at all familiar with js. But a good idea would be to make it work from a handout or maybe a table, like make it so you can type in an enemy in a certain format and it will just roll it when you put in the command. I dont know how easy/hard that is though.