The Character Sheet I work on does this. It is a combination of HTML and Javascript (on an API Script). The files for the Sheet/API are @  <a href="https://github.com/KnowlegeRhino/GenesysRPG" rel="nofollow">https://github.com/KnowlegeRhino/GenesysRPG</a>  .  Include the lines of code below, but they have a bunch of logic for the game and i am not useful enough at javascript to just strip out what you need.  On the HTML (Line 7535);  <option value="!eed npcinit rollPlayer(character:@{NPCName1}|skill:presence,rankCool) label(skill:NPC-Initiative Cool|NPC Type:@{groupmission-NPCtype1}) @{NPCInitModifiers1} @{dicePool} (gmdice)">Cool</option>  On the API Script (Lines 1948-2015);   eote.process.rollPlayer = function (cmd, diceObj) {
    //Build cmd string
    //get characterID
    //get skills
    //get encum
    //remove rollPlayer(xxxx) from string
    var match = {
        skill: /skill:(.*?)[\|\)]/,
        encum: /encum/,
        character: /character:(.*?)[\|\)]/
    };
    var characterMatch = cmd[1].match(match.character);
    var companion = null;
    var character = null;
    if (characterMatch) {
        var charObj = findObjs({ _type: "character", name: characterMatch[1] });
        if (charObj.length > 0) {
            diceObj.vars.characterName = charObj[0].get('name');
            diceObj.vars.characterID = charObj[0].id;
        }
        else {
            sendChat("Alert", "Can't find character. Please update character, or npc, name field to match sheet character name and try again.");
            return false;
        }
    }
    else {
        sendChat("Alert", "Please update character, or npc, name field.");
        return false;
    }
    var encumMatch = cmd[1].match(match.encum);
    var attr_1 = null;
    var attr_2 = null;
    if (encumMatch) {
        //encumbrance
        attr_1 = getAttrByName(diceObj.vars.characterID, 'encumbrance', 'max');
        attr_2 = getAttrByName(diceObj.vars.characterID, 'encumbrance');
        var cmdEncum = ['encum(' + attr_1 + '|' + attr_2 + ')']; //["encum(3|5)"]
        diceObj = eote.process.encum(cmdEncum, diceObj);
    }
    var skillMatch = cmd[1].match(match.skill);
    if (eote.defaults.globalVars.debugScript) sendChat("Alert", "skillmatch=" + skillMatch.toString());
    if (skillMatch) {
        var attrArray = skillMatch[1].split(',');
        attr_1 = getAttrByName(diceObj.vars.characterID, attrArray[0]);
        attr_2 = getAttrByName(diceObj.vars.characterID, attrArray[1]);
        if (eote.defaults.globalVars.debugScript) {
            sendChat("Alert", "attr_1 = " + attr_1);
            sendChat("Alert", "attr_2 = " + attr_2);
        }
        var cmdSkill;
        if (!isNaN((parseFloat(attr_1)) && isFinite(attr_1))) { // is numeric
            cmdSkill = ['skill(' + attr_1 + '|' + attr_2 + ')']; //['skill(0|2)']
        } else {
            var attr_3 = getAttrByName(diceObj.vars.characterID, attr_1.substr(2, attr_1.length - 3));
            cmdSkill = ['skill(' + attr_3 + '|' + attr_2 + ')']; //['skill(0|2)']
        }
        diceObj = eote.process.skill(cmdSkill, diceObj);
    }
    return diceObj;
};