JSFiddle - React, Tailwind, and code Playground

by Gwyn Milcote

HTML

Demo: total stats are a combination of many numbers.

<ul>
    <li>
        <b>Inborn</b>
        <br>A set of stats is calculated for each newborn, according to the % of each breed in their ancestry. There's a little random variation, +/- 10 points for each stat. 
        <br><b>Limit:</b> none
    </li>
    <li>
        <b>Pedigree</b>
        <br>Offspring are born with +2 bonus for all stats (+16 total), for every Grand Achievement made by a parent.
        <br><b>Limit:</b> +40 points per stat (+320 total) if both parents have 10/10 GA each.
    </li>
    <li>
        <b>Childhood</b>
        <br>While playing with Juvenile and Adolescent Mythics, they may randomly gain points in certain stats, depending on the actions.
        <br><b>Limit:</b> +20 points per stat (+160 total)
    </li>
    <li>
        <b>Level Up</b>
        <br>The primary way to gain stats. When a Mythic gains a level, they get points for some/all stats, depending on the Class they're currently in. After 20 levels in the same Class, it will be 'mastered' and no more levels can be gained; change to another Class to continue levelling up, up to 100.
        <br><b>Limit:</b> none
    </li>
    <li>
        <b>Tasks</b>
        <br>Taking part in Battles, Errands, Trials, Colosseum Games and other activities may randomly award points in certain stats, depending on the activity.
        <br><b>Limit:</b> +100 points per stat (+800 total)
    </li>
    <li>
        <b>Promotion</b>
        <br>A one-time, permanent bonus to all stats. Points depend on the breed. An Adult Mythic must have made at least 1 Grand Achievement to get promoted.
        <br><b>Limit:</b> none
    </li>
    <li>
        <b>Equipment</b>
        <br>You can give up to 5 pieces of equipment, and 3 enchantments. Each of these items may apply a bonus and/or malus to certain stat(s).
        <br><b>Limit:</b> no upper limit. Maluses can't bring any stat below 20 points.
    </li>
    <li>
        <b>Companion</b>
       ...

CSS

ul li {
    margin-bottom: 15px;
}

JavaScript

const db = {

    //
    //
    //
    //
    abilities: [
        {
            id: 1, name: "",
            desc: "",
            
        }
    ],
    
    mythics: [],
    
    // Which abilities are known by which mythics.
    // Can be permanent or temp (given by item/comp/sth).
    mythics_abilities: [
        {mythicId: 1, abilityId: 1, isTemporary: 0}
    ],
    
    // single row per type, per stat, per mythic?
    // one row per mythic, per stat? type cols?
    // or one row per mythic, all stat + type cols?
    stats: [
        {
            mythicId: 1,
            hp_base: 50,
            hp_pedigree: 12,
            hp_play: 14,
            hp_levels: 128,
            hp_tasks: 53,
            hp_promotion: 10,
            hp_equipment: 25,
            hp_companion: 5,
            hp_chance: 7,
            hp_items: 20
        }
    ]

};

function getAbility(id){
    return db.abilities.find(row => row.id == id);
}

function renderAbilities(ids){
    // Separate by type.
    // Inborn, from personality, then others
    let html = "";
    for(let id of ids){
        let a = getAbility(id);
        html += renderAbility(a);
    }
    return html;
}

function renderAbility(a){
    let html = "<div class='myp-ability'>";
    
    html += "<div class='ability-image'>";
    html += "<img src='..' loading='lazy'>";
    html += "</div>";
    
    html += "<div class='ability-name'>";
    html += a.name;
    html += "</div>";
    
    html += "<div class='ability-desc'>";
    html += a.desc;
    html += "</div>";
    
    html += "</div>";
    return html;
}