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

Retrieve all attributes in a character sheet

March 16 (3 years ago)
Grinning Gecko
Pro
Sheet Author

Is there a way to retrieve all attributes in a character sheet? I've tried the following:

    const characters = findObjs({ _type: "character", name: characterName });
    log(characters);
    const attributes = findObjs({
      _type: "attribute",
      _characterid: characters[0].id,
    });
    const attributeNames = attributes.map((a) => a.get("name"));
    log(attributeNames);
But it only gives me attributes that have values set, not all attributes in the sheet.

Ideally I'd like to do this via a sheetworker, but I'll settle for the API if that's not possible.
March 16 (3 years ago)
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator

Via sheetworkers is going to be easier as the sheetworker can get attributes that are still at their default value.

Admittedly, you need to build the array of attributes to get. With a vanilla sheet, that's going to require lots of manual data entry. My K-Scaffold sheet framework does this all automatically though and is built around always having the values of all attributes accessible in the sheetworkers.

March 16 (3 years ago)

Edited March 16 (3 years ago)
Grinning Gecko
Pro
Sheet Author

Ya, I have a massive array of attribute names in my sheet. But it's really annoying to maintain if I add/change attribute names. That's why I want some automatic way of getting them all - so that I can generate that massive array on-the-fly, or just run a script periodically so I can copy/paste into the code to update it.

I see how your framework works. The author defines the attributes, and your framework both creates the code for them and maintains an array of them. Clever. Too bad it would require a huge refactor to use that in my current sheet.

March 17 (3 years ago)
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator

Heh that's where I was several projects ago, and why I initially started creating the K-scaffold. Switching over is a fair bit of work, but I haven't looked back since as it's made every project since magnitudes easier, and has even paid itself off in the maintenance improvements on sheets I have switched over.

March 17 (3 years ago)
Ernest P.
Pro
API Scripter

Pardon my ignorance, but isn't this what getAllObjs() does? 

- E

March 17 (3 years ago)
The Aaron
Roll20 Production Team
API Scripter


Ernest P. said:

Pardon my ignorance, but isn't this what getAllObjs() does? 

- E

No, because character sheet attributes without a value assigned do not get attribute objects created.  Also, getAllObjs() returns all the objects associated with a game, not just the attributes.

March 18 (3 years ago)

Edited March 18 (3 years ago)
Oosh
Sheet Author
API Scripter

Another method is to pinch it from the HTML. You can run this from the browser console while in Campaign.

It's an async function, but top level await is available in recent browsers, so if you want to assign it to a variable you should be able to with:

const myVar = await getAllAttributes()

though it does also output to console. You might want to throw it into a variable though, to sort alphabetically or whatever.

The regex is pretty strict on the attributes in the HTML being written as "attr_<name here>" ... but I don't think there's an alternatives that work for Roll20 anyway?


const getAllAttributes = async () => {
  const getCharsheetDataFB = async () => {
    const e = `/editor/charsheetdata/${window.campaign_id}`;
    return new Promise((t, i) => {
      let n = 0;
      const o = () => {
        $.ajax({
          url: e,
          type: "GET",
          error: e => {
            n < 2 ? (n += 1, o()) : i(e)
          },
          success: e => {
            const i = JSON.parse(e);
            t(i)
          }
        })
      };
      o()
    })
  }
  const decodeCharsheetData = async (data) => {
    if (data.html) data.html = window.BASE64.decode(data.html);
    if (data.css) data.css = window.BASE64.decode(data.css);
    if (data.translation) data.translation = window.BASE64.decode(data.translation);
    return data;
  }
  const sheetData = await getCharsheetDataFB().then(async (csd) => decodeCharsheetData(csd));
  const html = sheetData.html,
    attributeRx = /"attr_([^"]+)/gi,
    matches = html.matchAll(attributeRx);
  let output = [];
  matches.forEach(m => {
    if (m[1] && !output.includes(m[1])) output.push(m[1]);
  });
  console.info(output.filter(v=>v));
  return output.filter(v=>v);
}