Final(ish)

This commit is contained in:
Gergely Polonkai 2025-06-05 00:05:42 +02:00
commit a6cf245321
No known key found for this signature in database
GPG Key ID: 38F402C8471DDE93

199
index.html Normal file
View File

@ -0,0 +1,199 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Cypher Player Assistant</title>
<style>
:root {
--dark-bg: black;
--dark-fg: white;
--light-bg: white;
--light-fg: black;
--bg: var(--dark-bg);
--fg: var(--dark-fg);
}
* {
background-color: black;
color: white;
}
h1 {
text-align: center;
}
#darkness-control {
display: inline;
}
.ability {
width: 25%;
display: inline-block;
border: 1px solid white;
}
.ability input {
width: 30%;
}
</style>
</head>
<body>
<h1>Cypher Player Assistant</h1>
<div id="darkness-control">
<input type="checkbox" checked>Dark Mode
</div>
<select></select><button>Load Character</button>
<div>
Campaign <input type="text">
Name <input type="text">
<button>Save Character</button>
</div>
Maximum Effort <input type="number" id="max-effort" min="0" value="0">
Armor <input type="number">
<div id="ability-container">
<div class="ability" id="might-column">
<h3>
<input type="radio" name="pool-choice" id="pool-choice-might" value="might">
Might
</h3>
Pool <input type="number" id="pool-value-might"> / <input type="number" id="pool-max-might">
Edge <input type="number" id="pool-edge-might">
</div>
<div class="ability" id="speed-column">
<h3>
<input type="radio" name="pool-choice" id="pool-choice-speed" value="speed">
Speed
</h3>
Pool <input type="number" id="pool-value-speed"> / <input type="number" id="pool-max-speed">
Edge <input type="number" id="pool-edge-speed">
</div>
<div class="ability" id="intellect-column">
<h3>
<input type="radio" name="pool-choice" id="pool-choice-intellect" value="intellect">
Intellect
</h3>
Pool <input type="number" id="pool-value-intellect"> / <input type="number" id="pool-max-intellect">
Edge <input type="number" id="pool-edge-intellect">
</div>
</div>
<h2>Use Ability</h2>
<select id="ability-selector">
<option>Custom</option>
<option data-pool="might" data-cost="3">Golem Grip</option>
<option data-pool="speed" data-cost="1">Some Speedy Thing</option>
</select>
Initial cost <input type="number" id="ability-cost">
Effort <input type="number" id="ability-effort">
<span id="ability-cost-display"></span>
<button id="roll-ability">Do it!</button>
<h2>Do a Task</h2>
Training <select>
<option>Inability</option>
<option selected>Practised</option>
<option>Trained</option>
<option>Specialised</option>
</select>
Effort <input type="number">
<button>Roll!</button>
<button>Do it!</button>
<h2>Take Damage</h2>
<input type="number"><button>Ouch!</button>
<script>
const maxEffort = document.getElementById("max-effort")
const abilitySelector = document.getElementById("ability-selector");
const abilityInitialCost = document.getElementById("ability-cost");
const abilityEffort = document.getElementById("ability-effort");
const abilityRoller = document.getElementById("roll-ability");
const abilityCostDisplay = document.getElementById("ability-cost-display");
const poolChoices = {
might: document.getElementById("pool-choice-might"),
speed: document.getElementById("pool-choice-speed"),
intellect: document.getElementById("pool-choice-intellect"),
};
const poolValues = {
might: document.getElementById("pool-value-might"),
speed: document.getElementById("pool-value-speed"),
intellect: document.getElementById("pool-value-intellect"),
};
const poolEdges = {
might: document.getElementById("pool-edge-might"),
speed: document.getElementById("pool-edge-speed"),
intellect: document.getElementById("pool-edge-intellect"),
};
const d20 = () => Math.floor(Math.random() * 20) + 1;
const getSelectedAttribute = () => {
var currentPoolSelector = document.querySelector("input[name=pool-choice]:checked");
return (currentPoolSelector === null) ? null : currentPoolSelector.value;
};
const getSelectedPool = () => {
if ((currentPool = getSelectedAttribute()) === null) {
return 0;
}
return Number(poolValues[currentPool].value);
};
const getSelectedEdge = () => {
if ((currentPool = getSelectedAttribute()) === null) {
return 0;
}
return Number(poolEdges[currentPool].value);
};
const calculateAbilityCost = () => {
var cost = Number(abilityInitialCost.value);
var usedEffort = Number(abilityEffort.value);
var effortCost = (usedEffort > 0) ? 3 + Math.max(usedEffort - 1, 0) * 2 : 0;
cost += effortCost - getSelectedEdge();
return Math.max(cost, 0);
};
const updateAbilityCost = () => {
var cost = calculateAbilityCost();
abilityCostDisplay.innerHTML = String(cost);
};
abilitySelector.addEventListener(
"change",
(evt) => {
var selectedOption = evt.target.selectedOptions[0];
if (selectedOption.dataset.pool !== null) {
var poolChooser = poolChoices[selectedOption.dataset.pool];
poolChooser.checked = true;
abilityInitialCost.value = Number(selectedOption.dataset.cost);
}
},
);
abilityInitialCost.addEventListener("input", updateAbilityCost);
var abilityEffortChecking = false;
abilityEffort.addEventListener(
"input",
(evt) => {
if (abilityEffortChecking) return;
abilityEffortChecking = true;
if (evt.target.value < 0) {
evt.target.value = 0;
} else if (evt.target.value >= maxEffort.value) {
evt.target.value = maxEffort.value;
}
updateAbilityCost();
abilityEffortChecking = false;
},
);
</script>
</body>
</html>