You've done really well. If you don't mind, I have a couple of suggestions to simplify your code. This section for instance includes some repetition you can remove: var x = randomInteger(20) if (x === 1) location = "Head"; if (x === 2) location = "Head"; if (x === 3) location = "Right Arm"; if (x === 4) location = "Right Arm"; if (x === 5) location = "Right Arm"; if (x === 6) location = "Left Arm"; if (x === 7) location = "Left Arm"; if (x === 8) location = "Left Arm"; if (x === 9) location = "Torso"; if (x === 10) location = "Torso"; if (x === 11) location = "Torso"; if (x === 12) location = "Torso"; if (x === 13) location = "Torso"; if (x === 14) location = "Torso"; if (x === 15) location = "Right Leg"; if (x === 16) location = "Right Leg"; if (x === 17) location = "Right Arm"; if (x === 18) location = "Left Leg"; if (x === 19) location = "Left Leg"; if (x === 20) location = "Left Leg"; if (location === "Head") armor = head; if (location === "Torso") armor = torso; if (location === "Right Arm") armor = rightarm; if (location === "Left Arm") armor = leftleg; if (location === "Right Leg") armor = rightleg; if (location === "Left Leg") armor = leftleg; Like so: //Now to roll the table and match the results var x = randomInteger(20) if (x <= 2) { location = "Head"; armor = head; } else if (x <= 5) { location = "Right Arm"; armor = rightarm; } else if (x <= 8) { location = "Left Arm"; armor = leftarm; } else if (x <= 14) { location = "Torso"; armor = torso; } else if (x <= 17) { location = "Right Arm"; armor = rightleg; } else { location = "Left Leg"; armor = leftleg; } Using <, >, <=, and >= can shorten a lot of if statements of this sort, but you have to be careful to build them correctly. Expressions of this form: If {something) else (something) will stop at the first matching result, is if you starting at the bottom of the table use < and if starting at the top of the range use >. By the way, i noticed your code has a typo, look at if (location === "Left Arm") armor = leftleg; Another tip is when you find yourself doing the same thing over and over, use a function to simplify it. For example this is repeated: let torso = parseInt((findObjs({ type: 'attribute', characterid: c.id, name: 'Torso_Soak' })[0]||{get:()=>-1}).get('current')); You can create a function like (this isn't finished, but I;ll walk you through the steps: const getLocation = function() {
let location = parseInt((findObjs({ type: 'attribute', characterid: c.id, name: 'Torso_Soak' })[0]||{get:()=>-1}).get('current'));
return location;
}; If you placed that in your script just after the on('ready') and before on(change) you could then call it later with let torso = getLocation(); The problem is it wont work, because of this line characterid: c.id, It's using a variable that doesnt exist in that function. So you need a way to pass the c.id value from the main body to it. You do that by changing the function like so: const getLocation = function( id ) { // we declare a parameter here, similar to creating variables
let location = parseInt((findObjs({ type: 'attribute', characterid: id, // and we use the parameter here. name: 'Torso_Soak' })[0]||{get:()=>-1}).get('current'));
return location;
}; And then you call it like so let torso = getLocation(c.id); In this way you send the c.id value to the function. The id parameter in that function accepts the c.id value and uses it wherever id is in the function. Now thats not very useful yet. It still only returns the torso location. But we can use the same technique to make it reusable. const getLocation = function(id, choice ) {
let location = parseInt((findObjs({ type: 'attribute', characterid: id, name: choice })[0]||{get:()=>-1}).get('current'));
return location;
}; Here we add a second parameter, choice, which will hold the location we want to get. Now we can call it with let torso = getLocation(c.id, 'Torso_Soak'); let head = getLocation(c.id, 'Head_Soak'); let leftarm = getLocation(c.id, 'LA_Soak'); let rightarm = getLocation(c.id, 'RA_Soak'); let leftleg = getLocation(c.id, 'LL_Soak');
let rightleg = getLocation(c.id, 'RL_Soak'); But there's at least one more optimisation we can do. In the above code we call all 6 location attributes, but we actually only need one of them. The revised code below only calls the one we need. // wait till the ready event before registering a chat handler on('ready', () => { // create a function to return attribute value, given character id and attribute name. const getLocation = function(id, choice) { let location = parseInt((findObjs({ type: 'attribute', characterid: id, name: choice })[0] || { get: () => -1 }).get('current')); return location; }; // register a function to run for chat messages on('chat:message', (msg) => { // make sure the message is an api command, then verify it starts with !infdice if ('api' === msg.type && /^!infattack\b/i.test(msg.content)) { // break into an array of arguments on spaces let args = msg.content.split(/\s+/); // grab the characger in the 2nd parameter let c = getObj('character', args[1]); // verify we got a character if (c) { //Now to roll the table and match the results
// and we grab the location armour only after we know which one we need.
let location, armor; //initialize these variables, we;ll need them later var x = randomInteger(20) if (x <= 2) { location = "Head"; armor = getLocation(c.id, 'Head_Soak'); } else if (x <= 5) { location = "Right Arm"; armor = getLocation(c.id, 'RA_Soak'); } else if (x <= 8) { location = "Left Arm"; armor = getLocation(c.id, 'LA_Soak'); } else if (x <= 14) { location = "Torso"; armor = getLocation(c.id, 'Torso_Soak'); } else if (x <= 17) { location = "Right Arm"; armor = getLocation(c.id, 'RL_Soak'); } else { location = "Left Leg"; armor = getLocation(c.id, 'LL_Soak'); } // output the location and attribute sendChat('', `${location} ${armor}`); } else { // error for no matching character sendChat('', `No character found for id <code>${args[1]}</code>`); } } }); }); Hope you find this useful in your future coding!