Character Vault
Any Concept / Any System
Compendium
Your System Come To Life
Roll20 for Android
Streamlined for your Tablet
Roll20 for iPad
Streamlined for your Tablet

Personal tools

Select Attributes for Sheet Roll

From Roll20 Wiki

Jump to: navigation, search

Main Article: Building Character Sheets

This is an example for selecting attributes to be included in a Sheet Roll.

The key components are:

  • Update display of toggle buttons based on the associated flag, using Styling Checkboxes and Radios
  • Attribute name, button name, flag attribute name, and translation key all share the same base value.
  • Displaying the selected attributes (based on translation key)
  • Selected attribute list and dice pool value are stored in hidden input fields.
  • Roll button references the dice pool attribute with Auto-Calculating Values

HTML

<h1>Sheet Roller</h1>
<div class="roller">
  <textarea name="attr_dice_pool_display" tabindex="-1"></textarea>
  <div>
    <input type="text" name="attr_dice_pool" tab-index="-1"></input>
    <button type="roll" value="/roll @{dice_pool}d10"></button>
  </div>
</div>

<h1>Attributes</h1>
<div class="attributes">
  <div>
    <input type="hidden" class="flag" name="attr_intelligence_flag">
    <button type="action" class="toggle" name="act_intelligence" data-i18n="intelligence">Intelligence</button>
    <input type="number" name="attr_intelligence" value="1">
  </div>
  <div>
    <input type="hidden" class="flag" name="attr_wits_flag">
    <button type="action" class="toggle" name="act_wits" data-i18n="wits">Wits</button>
    <input type="number" name="attr_wits" value="1">
  </div>
  <div>
    <input type="hidden" class="flag" name="attr_resolve_flag">
    <button type="action" class="toggle" name="act_resolve" data-i18n="resolve">Resolve</button>
    <input type="number" name="attr_resolve" value="1">
  </div>
</div>

<input type="hidden" name="attr_dice_pool_attributes">
<input type="hidden" name="attr_dice_pool" value="0">

Sheet Worker

const attributes = ["intelligence", "wits", "resolve"];

attributes.forEach((attribute) => {
  on(`clicked:${attribute}`, () => {
    updateSheetRoll(attribute);
  });
});

const attributeChangeEvents = attributes.map((attribute) => `change:${attribute}`);
on(attributeChangeEvents.join(" "), () => {
  updateSheetRollPool();
});

const updateSheetRoll = function(attribute) {
  getAttrs(["dice_pool_attributes", ...attributes], (values) => {
    let poolAttributes = values["dice_pool_attributes"]
      .split(",")
      .filter((poolAttribute) => poolAttribute);

    if (poolAttributes.includes(attribute)) {
      // remove attribute from pool
      poolAttributes = poolAttributes
        .filter((poolAttribute) => poolAttribute !== attribute);
    }
    else {
      // add attribute to back of pool
      poolAttributes = poolAttributes.concat(attribute);
      
      // Truncate pool attributes to 2,
      // removing the oldest selected attributes
      poolAttributes = poolAttributes
        .reverse()
        .slice(0, 2)
        .reverse();
    }

    const pool = getSheetRollPool(poolAttributes, values);

    // Create display list of attributes
    const poolDisplay = poolAttributes
      .map((poolAttribute) => getTranslationByKey(poolAttribute))
      .join(" +\n");

    // Determine flag values
    const flags = attributes
      .map((flagAttribute) => ({
        flag: `${flagAttribute}_flag`,
        value: poolAttributes.includes(flagAttribute) ? 1 : 0
      }))
      .reduce((all, next) => ({ ...all, [next.flag]: next.value }), {});

    setAttrs({
      "dice_pool_attributes": poolAttributes.join(","),
      "dice_pool": pool,
      "dice_pool_display": poolDisplay,
      ...flags
    });
  });
}

const updateSheetRollPool = function() {
  getAttrs(["dice_pool_attributes", ...attributes], (values) => {
    const poolAttributes = values["dice_pool_attributes"]
      .split(",")
      .filter((poolAttribute) => poolAttribute);

    const pool = getSheetRollPool(poolAttributes, values);

    setAttrs({
      "dice_pool": pool
    });
  });
}

const getSheetRollPool = function(poolAttributes, values) {
  // Add up attribute values for dice pool
  const sum = poolAttributes
    .map((poolAttribute) => Number(values[poolAttribute]))
    .reduce((sum, value) => sum + value, 0);

  // Pool is always at least 1 die
  return Math.max(sum, 1);
}

CSS

/* Indicate that the toggle is active */
input.sheet-flag[value="1"] ~ button.sheet-toggle {
  border-color: blue;
  font-weight: bold;
}