CharakterCreator: Unterschied zwischen den Versionen

Aus Dunkelherzen Wiki
Keine Bearbeitungszusammenfassung
Markierung: Manuelle Zurücksetzung
Keine Bearbeitungszusammenfassung
Zeile 1: Zeile 1:
<!DOCTYPE html>
<html>
<html>
<head>
<head>
Zeile 8: Zeile 9:
       font-family: sans-serif;
       font-family: sans-serif;
     }
     }
     .creator-form label {
     .creator-form label {
       font-weight: bold;
       font-weight: bold;
Zeile 14: Zeile 14:
       margin-top: 10px;
       margin-top: 10px;
     }
     }
     .creator-form input,
     .creator-form input,
     .creator-form select {
     .creator-form select {
Zeile 21: Zeile 20:
       margin-bottom: 10px;
       margin-bottom: 10px;
     }
     }
     .creator-form button {
     .creator-form button {
       margin-top: 15px;
       margin-top: 15px;
Zeile 27: Zeile 25:
       width: 100%;
       width: 100%;
     }
     }
     .attribute-inputs {
     .attribute-inputs {
       display: grid;
       display: grid;
Zeile 33: Zeile 30:
       gap: 10px;
       gap: 10px;
     }
     }
     .output {
     .output {
       margin-top: 20px;
       margin-top: 20px;
Zeile 41: Zeile 37:
       white-space: pre-wrap;
       white-space: pre-wrap;
     }
     }
     .points-remaining {
     .points-remaining {
       font-weight: bold;
       font-weight: bold;
Zeile 50: Zeile 45:
</head>
</head>
<body>
<body>
  <div class="creator-form">
<div class="creator-form">
    <h2>Charakter Creator</h2>
  <h2>Charakter Creator</h2>


    <label for="name">Name:</label>
  <label for="name">Name:</label>
    <input type="text" id="name" placeholder="Name des Charakters">
  <input type="text" id="name" placeholder="Name des Charakters">


    <label for="speziestyp">Speziestyp:</label>
  <label for="speziestyp">Speziestyp:</label>
    <select id="speziestyp">
  <select id="speziestyp">
      <option value="">Keine</option>
    <option value="">Keine</option>
      <option value="Humanoid">Humanoid</option>
    <option value="Humanoid">Humanoid</option>
      <option value="Ätherer">Ätherer</option>
    <option value="Ätherer">Ätherer</option>
      <option value="Mensch-Ätherer">Mensch-Ätherer</option>
    <option value="Mensch-Ätherer">Mensch-Ätherer</option>
      <option value="Andere Ätherer">Andere Ätherer</option>
    <option value="Andere Ätherer">Andere Ätherer</option>
      <option value="Non-Humanoide / Andere">Non-Humanoide / Andere</option>
    <option value="Non-Humanoide / Andere">Non-Humanoide / Andere</option>
      <option value="Xeutano">Xeutano</option>
    <option value="Xeutano">Xeutano</option>
      <option value="Androidenartige">Androidenartige</option>
    <option value="Androidenartige">Androidenartige</option>
    </select>
  </select>


    <label for="rasse">Rasse:</label>
  <label for="rasse">Rasse:</label>
    <select id="rasse">
  <select id="rasse">
      <option value="">Keine</option>
    <option value="">Keine</option>
      <option value="Mensch">Mensch</option>
  </select>
      <option value="Elf">Elf</option>
    </select>


    <label for="subspezies">Subspezies:</label>
  <label for="subspezies">Subspezies:</label>
    <select id="subspezies">
  <select id="subspezies">
      <option value="">Keine (+20 GP Ausgleich)</option>
    <option value="">Keine (+20 GP Ausgleich)</option>
      <option value="Waldelf">Waldelf</option>
    <option value="Waldelf">Waldelf</option>
      <option value="Stadelf">Stadelf</option>
    <option value="Stadelf">Stadelf</option>
    </select>
  </select>


    <label for="klasse">Klasse:</label>
  <label for="klasse">Klasse:</label>
    <select id="klasse">
  <select id="klasse">
      <option value="">Keine</option>
    <option value="">Keine</option>
      <option value="Arbeiter">Arbeiter</option>
    <option value="Arbeiter">Arbeiter</option>
      <option value="Barde">Barde</option>
    <option value="Barde">Barde</option>
      <option value="Bote">Bote</option>
    <option value="Bote">Bote</option>
      <option value="Gelehrter">Gelehrter</option>
    <option value="Gelehrter">Gelehrter</option>
      <option value="Gläubiger">Gläubiger</option>
    <option value="Gläubiger">Gläubiger</option>
      <option value="Kind">Kind</option>
    <option value="Kind">Kind</option>
      <option value="Krieger">Krieger</option>
    <option value="Krieger">Krieger</option>
      <option value="Schurke">Schurke</option>
    <option value="Schurke">Schurke</option>
      <option value="Schütze">Schütze</option>
    <option value="Schütze">Schütze</option>
      <option value="Seelenkünstler">Seelenkünstler</option>
    <option value="Seelenkünstler">Seelenkünstler</option>
      <option value="Soldat">Soldat</option>
    <option value="Soldat">Soldat</option>
      <option value="Techniker">Techniker</option>
    <option value="Techniker">Techniker</option>
      <option value="Vagabunde">Vagabunde</option>
    <option value="Vagabunde">Vagabunde</option>
    </select>
  </select>


    <label for="subklasse">Subklasse:</label>
  <label for="subklasse">Subklasse:</label>
    <select id="subklasse">
  <select id="subklasse">
      <option value="">Keine (+15 GP Ausgleich)</option>
    <option value="">Keine (+15 GP Ausgleich)</option>
      <option value="Auserwählter">Auserwählter</option>
    <option value="Auserwählter">Auserwählter</option>
      <option value="Diener">Diener</option>
    <option value="Diener">Diener</option>
      <option value="Drogenjunkie">Drogenjunkie</option>
    <option value="Drogenjunkie">Drogenjunkie</option>
      <option value="Dummkopf">Dummkopf</option>
    <option value="Dummkopf">Dummkopf</option>
      <option value="Dunkler Künstler">Dunkler Künstler</option>
    <option value="Dunkler Künstler">Dunkler Künstler</option>
      <option value="Gesetzloser">Gesetzloser</option>
    <option value="Gesetzloser">Gesetzloser</option>
      <option value="Glücksspieler">Glücksspieler</option>
    <option value="Glücksspieler">Glücksspieler</option>
      <option value="Händler">Händler</option>
    <option value="Händler">Händler</option>
      <option value="Koch">Koch</option>
    <option value="Koch">Koch</option>
      <option value="Kopfgeldjäger">Kopfgeldjäger</option>
    <option value="Kopfgeldjäger">Kopfgeldjäger</option>
      <option value="Ödländer">Ödländer</option>
    <option value="Ödländer">Ödländer</option>
      <option value="Okkultist">Okkultist</option>
    <option value="Okkultist">Okkultist</option>
      <option value="Pazifist">Pazifist</option>
    <option value="Pazifist">Pazifist</option>
      <option value="Politiker">Politiker</option>
    <option value="Politiker">Politiker</option>
      <option value="Revolutionär">Revolutionär</option>
    <option value="Revolutionär">Revolutionär</option>
      <option value="Seefahrer">Seefahrer</option>
    <option value="Seefahrer">Seefahrer</option>
      <option value="Spion">Spion</option>
    <option value="Spion">Spion</option>
      <option value="Mutant">Mutant</option>
    <option value="Mutant">Mutant</option>
    </select>
  </select>


    <label for="gegenstaende">Gegenstände wählen:</label>
  <label for="gegenstaende">Gegenstände wählen:</label>
    <select id="gegenstaende">
  <select id="gegenstaende">
      <option value="0">Keine</option>
    <option value="0">Keine</option>
      <option value="1">1 Gegenstand (-10 GP)</option>
    <option value="1">1 Gegenstand (-10 GP)</option>
      <option value="2">2 Gegenstände (-20 GP)</option>
    <option value="2">2 Gegenstände (-20 GP)</option>
      <option value="3">3 Gegenstände (-30 GP)</option>
    <option value="3">3 Gegenstände (-30 GP)</option>
    </select>
  </select>


    <div class="points-remaining" id="punkteInfo"></div>
  <div class="points-remaining" id="punkteInfo"></div>


    <label>Attribute:</label>
  <label>Attribute:</label>
    <div class="attribute-inputs" id="attributeInputs"></div>
  <div class="attribute-inputs" id="attributeInputs"></div>


    <button onclick="berechneCharakter()">Charakter berechnen</button>
  <button onclick="berechneCharakter()">Charakter berechnen</button>
    <button onclick="exportiereCharakter()">Exportieren</button>
  <button onclick="exportiereCharakter()">Exportieren</button>


    <div class="output" id="ausgabe"></div>
  <div class="output" id="ausgabe"></div>
  </div>
</div>


  <script>
<script>
    const attributeListe = [
  const attributeListe = [
      "Agilität", "Ausdauer", "Charisma", "Geschick",
    "Agilität", "Ausdauer", "Charisma", "Geschick",
      "Intelligenz", "Konstitution", "Resistenz",
    "Intelligenz", "Konstitution", "Resistenz",
      "Stärke", "Wahrnehmung"
    "Stärke", "Wahrnehmung"
    ];
  ];


    const basisPunkte = 160;
  const basisPunkte = 160;


    const zeroBoni = () =>
  const zeroBoni = () => Object.fromEntries(attributeListe.map(attr => [attr, 0]));
      Object.fromEntries(attributeListe.map(attr => [attr, 0]));


    const klassenBoni = Object.fromEntries([
  const klassenBoni = Object.fromEntries([
      "Arbeiter", "Barde", "Bote", "Gelehrter", "Gläubiger", "Kind", "Krieger", "Schurke",
    "Arbeiter", "Barde", "Bote", "Gelehrter", "Gläubiger", "Kind", "Krieger", "Schurke",
      "Schütze", "Seelenkünstler", "Soldat", "Techniker", "Vagabunde"
    "Schütze", "Seelenkünstler", "Soldat", "Techniker", "Vagabunde"
    ].map(name => [name, zeroBoni()]));
  ].map(name => [name, zeroBoni()]));


    const subklassenBoni = Object.fromEntries([
  const subklassenBoni = Object.fromEntries([
      "Auserwählter", "Diener", "Drogenjunkie", "Dummkopf", "Dunkler Künstler", "Gesetzloser",
    "Auserwählter", "Diener", "Drogenjunkie", "Dummkopf", "Dunkler Künstler", "Gesetzloser",
      "Glücksspieler", "Händler", "Koch", "Kopfgeldjäger", "Ödländer", "Okkultist",
    "Glücksspieler", "Händler", "Koch", "Kopfgeldjäger", "Ödländer", "Okkultist",
      "Pazifist", "Politiker", "Revolutionär", "Seefahrer", "Spion", "Mutant"
    "Pazifist", "Politiker", "Revolutionär", "Seefahrer", "Spion", "Mutant"
    ].map(name => [name, zeroBoni()]));
  ].map(name => [name, zeroBoni()]));


    const speziestypBoni = Object.fromEntries([
  const speziestypBoni = Object.fromEntries([
      "Humanoid", "Ätherer", "Mensch-Ätherer", "Andere Ätherer",
    "Humanoid", "Ätherer", "Mensch-Ätherer", "Andere Ätherer",
      "Non-Humanoide / Andere", "Xeutano", "Androidenartige"
    "Non-Humanoide / Andere", "Xeutano", "Androidenartige"
    ].map(name => [name, zeroBoni()]));
  ].map(name => [name, zeroBoni()]));


    const rassenBoni = {
  const speciesByType = {
       "Mensch": { "Agilität": 0, "Ausdauer": 0, "Charisma": 1, "Geschick": 0, "Intelligenz": 0, "Konstitution": 0, "Resistenz": 0, "Stärke": 0, "Wahrnehmung": 0 },
    "Humanoid": [
      "Elf":   { "Agilität": 1, "Ausdauer": 0, "Charisma": 0, "Geschick": 1, "Intelligenz": 0, "Konstitution": 0, "Resistenz": 0, "Stärke": 0, "Wahrnehmung": 0 }
       "Arcadier / Byzantone", "Astroma", "Caesaren", "Fijen", "Floratia", "Kalani",
    };
      "Lugier", "Nore", "Pendräa", "Rubinnia", "Sowi", "Varene", "Zarcore"
    ],
    "Ätherer": ["Maggarn", "Sapiée"],
    "Mensch-Ätherer": ["Cilina", "Gaimane"],
    "Andere Ätherer": ["Matari"],
    "Non-Humanoide / Andere": [],
    "Xeutano": [],
    "Androidenartige": []
  };


    const subspeziesBoni = {
  const rassenBoni = Object.fromEntries(
      "Waldelf": { "Agilität": 0, "Ausdauer": 0, "Charisma": 0, "Geschick": 1, "Intelligenz": 0, "Konstitution": 0, "Resistenz": 0, "Stärke": 0, "Wahrnehmung": 1 },
    Object.values(speciesByType).flat().map(name => [name, zeroBoni()])
      "Stadelf": { "Agilität": 0, "Ausdauer": 0, "Charisma": 1, "Geschick": 0, "Intelligenz": 1, "Konstitution": 0, "Resistenz": 0, "Stärke": 0, "Wahrnehmung": 0 }
  );
    };


    const attributeInputs = document.getElementById("attributeInputs");
  const subspeziesBoni = {
     attributeListe.forEach(attr => {
    "Waldelf": { "Agilität": 0, "Ausdauer": 0, "Charisma": 0, "Geschick": 1, "Intelligenz": 0, "Konstitution": 0, "Resistenz": 0, "Stärke": 0, "Wahrnehmung": 1 },
      const input = document.createElement("input");
     "Stadelf": { "Agilität": 0, "Ausdauer": 0, "Charisma": 1, "Geschick": 0, "Intelligenz": 1, "Konstitution": 0, "Resistenz": 0, "Stärke": 0, "Wahrnehmung": 0 }
      input.type = "number";
  };
      input.min = "0";
      input.value = "0";
      input.id = `attr_${attr}`;
      input.oninput = updateRemainingPoints;
      const label = document.createElement("label");
      label.textContent = attr;
      label.htmlFor = input.id;
      attributeInputs.appendChild(label);
      attributeInputs.appendChild(input);
    });


     function getBonus(boni, key) {
  // Dynamisches Umschalten der Rassen je nach Speziestyp
       return boni[key] || zeroBoni();
  document.getElementById("speziestyp").addEventListener("change", function () {
    const typ = this.value;
    const rasseSelect = document.getElementById("rasse");
     rasseSelect.innerHTML = "<option value=''>Keine</option>";
    if (speciesByType[typ]) {
       speciesByType[typ].forEach(rasse => {
        const opt = document.createElement("option");
        opt.value = rasse;
        opt.textContent = rasse;
        rasseSelect.appendChild(opt);
      });
     }
     }
  });
  const attributeInputs = document.getElementById("attributeInputs");
  attributeListe.forEach(attr => {
    const input = document.createElement("input");
    input.type = "number";
    input.min = "0";
    input.value = "0";
    input.id = `attr_${attr}`;
    input.oninput = updateRemainingPoints;
    const label = document.createElement("label");
    label.textContent = attr;
    label.htmlFor = input.id;
    attributeInputs.appendChild(label);
    attributeInputs.appendChild(input);
  });
  function getBonus(boni, key) {
    return boni[key] || zeroBoni();
  }


    function sumUserInput() {
  function sumUserInput() {
      return attributeListe.reduce((sum, attr) => {
    return attributeListe.reduce((sum, attr) => {
        const val = parseInt(document.getElementById(`attr_${attr}`).value) || 0;
      const val = parseInt(document.getElementById(`attr_${attr}`).value) || 0;
        return sum + val;
      return sum + val;
      }, 0);
    }, 0);
    }
  }


    function updateRemainingPoints() {
  function updateRemainingPoints() {
      let total = basisPunkte;
    let total = basisPunkte;
      if (!document.getElementById("subspezies").value) total += 20;
    if (!document.getElementById("subspezies").value) total += 20;
      if (!document.getElementById("subklasse").value) total += 15;
    if (!document.getElementById("subklasse").value) total += 15;


      const gegenstaende = parseInt(document.getElementById("gegenstaende").value) || 0;
    const gegenstaende = parseInt(document.getElementById("gegenstaende").value) || 0;
      total -= gegenstaende * 10;
    total -= gegenstaende * 10;


      const used = sumUserInput();
    const used = sumUserInput();
      const remaining = total - used;
    const remaining = total - used;


      document.getElementById("punkteInfo").textContent = `Verbleibende Punkte: ${remaining} / ${total}`;
    document.getElementById("punkteInfo").textContent = `Verbleibende Punkte: ${remaining} / ${total}`;
    }
  }


    function berechneCharakter() {
  function berechneCharakter() {
      const name = document.getElementById("name").value;
    const name = document.getElementById("name").value;
      const speziestyp = document.getElementById("speziestyp").value;
    const speziestyp = document.getElementById("speziestyp").value;
      const rasse = document.getElementById("rasse").value;
    const rasse = document.getElementById("rasse").value;
      const subspezies = document.getElementById("subspezies").value;
    const subspezies = document.getElementById("subspezies").value;
      const klasse = document.getElementById("klasse").value;
    const klasse = document.getElementById("klasse").value;
      const subklasse = document.getElementById("subklasse").value;
    const subklasse = document.getElementById("subklasse").value;
      const gegenstaende = parseInt(document.getElementById("gegenstaende").value) || 0;
    const gegenstaende = parseInt(document.getElementById("gegenstaende").value) || 0;


      const basisAttribute = {};
    const basisAttribute = {};
      attributeListe.forEach(attr => {
    attributeListe.forEach(attr => {
        basisAttribute[attr] = parseInt(document.getElementById(`attr_${attr}`).value) || 0;
      basisAttribute[attr] = parseInt(document.getElementById(`attr_${attr}`).value) || 0;
      });
    });


      const gesamt = {};
    const gesamt = {};
      attributeListe.forEach(attr => {
    attributeListe.forEach(attr => {
        gesamt[attr] =
      gesamt[attr] =
          basisAttribute[attr] +
        basisAttribute[attr] +
          getBonus(speziestypBoni, speziestyp)[attr] +
        getBonus(speziestypBoni, speziestyp)[attr] +
          getBonus(rassenBoni, rasse)[attr] +
        getBonus(rassenBoni, rasse)[attr] +
          getBonus(subspeziesBoni, subspezies)[attr] +
        getBonus(subspeziesBoni, subspezies)[attr] +
          getBonus(klassenBoni, klasse)[attr] +
        getBonus(klassenBoni, klasse)[attr] +
          getBonus(subklassenBoni, subklasse)[attr];
        getBonus(subklassenBoni, subklasse)[attr];
      });
    });


      const daten = {
    const daten = {
        Name: name,
      Name: name,
        Speziestyp: speziestyp,
      Speziestyp: speziestyp,
        Rasse: rasse,
      Rasse: rasse,
        Subspezies: subspezies || "Keine (20 Punkte erhalten)",
      Subspezies: subspezies || "Keine (20 Punkte erhalten)",
        Klasse: klasse,
      Klasse: klasse,
        Subklasse: subklasse || "Keine (15 Punkte erhalten)",
      Subklasse: subklasse || "Keine (15 Punkte erhalten)",
        Gegenstände: `${gegenstaende} (${gegenstaende * 10} Punkte abgezogen)`,
      Gegenstände: `${gegenstaende} (${gegenstaende * 10} Punkte abgezogen)`,
        Verwendete_Punkte: sumUserInput(),
      Verwendete_Punkte: sumUserInput(),
        Gesamt_Punkte: basisPunkte + (subklasse ? 0 : 15) + (subspezies ? 0 : 20) - (gegenstaende * 10),
      Gesamt_Punkte: basisPunkte + (subklasse ? 0 : 15) + (subspezies ? 0 : 20) - (gegenstaende * 10),
        Attribute: gesamt
      Attribute: gesamt
      };
    };


      document.getElementById("ausgabe").textContent = JSON.stringify(daten, null, 2);
    document.getElementById("ausgabe").textContent = JSON.stringify(daten, null, 2);
    }
  }


    function exportiereCharakter() {
  function exportiereCharakter() {
      const daten = document.getElementById("ausgabe").textContent;
    const daten = document.getElementById("ausgabe").textContent;
      if (!daten) {
    if (!daten) {
        alert("Bitte zuerst berechnen!");
      alert("Bitte zuerst berechnen!");
        return;
      return;
      }
      const blob = new Blob([daten], { type: "application/json" });
      const url = URL.createObjectURL(blob);
      const a = document.createElement("a");
      a.href = url;
      a.download = "charakter.json";
      a.click();
      URL.revokeObjectURL(url);
     }
     }
    const blob = new Blob([daten], { type: "application/json" });
    const url = URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = url;
    a.download = "charakter.json";
    a.click();
    URL.revokeObjectURL(url);
  }


    document.addEventListener("DOMContentLoaded", function () {
  document.addEventListener("DOMContentLoaded", function () {
      const inputs = document.querySelectorAll("select, input[type='number']");
    const inputs = document.querySelectorAll("select, input[type='number']");
      inputs.forEach(el => {
    inputs.forEach(el => {
        el.addEventListener("input", updateRemainingPoints);
      el.addEventListener("input", updateRemainingPoints);
        el.addEventListener("change", updateRemainingPoints);
      el.addEventListener("change", updateRemainingPoints);
      });
      updateRemainingPoints();
     });
     });
   </script>
    updateRemainingPoints();
   });
</script>
</body>
</body>
</html>
</html>

Version vom 29. Juli 2025, 16:16 Uhr

<!DOCTYPE html>

Charakter Creator