Compare commits

...

4 commits

View file

@ -41,8 +41,10 @@
<p>Use this tool to create custom Kemoverse cards! Fill in the details below, upload your art, and generate a card image.</p> <p>Use this tool to create custom Kemoverse cards! Fill in the details below, upload your art, and generate a card image.</p>
<p>Note: The card ID is generated based on the details, so make sure to fill them out!</p> <p>Note: The card ID is generated based on the details, so make sure to fill them out!</p>
<div style="margin-bottom: 0.5rem;">
<input type="checkbox" id="restrictStatsToggle" checked>
<label for="restrictStatsToggle">Restrict stats by rarity</label>
</div>
<input type="text" id="nameInput" placeholder="Card Name" style="width: 100%; margin-bottom: 0.5rem;"><br> <input type="text" id="nameInput" placeholder="Card Name" style="width: 100%; margin-bottom: 0.5rem;"><br>
<input type="text" id="packInput" placeholder="Pack name" style="width: 100%; margin-bottom: 0.5rem;"><br> <input type="text" id="packInput" placeholder="Pack name" style="width: 100%; margin-bottom: 0.5rem;"><br>
@ -53,11 +55,11 @@
<input type="text" id="artistInput" placeholder="Artist Name" style="width: 100%; margin-bottom: 0.5rem;"><br> <input type="text" id="artistInput" placeholder="Artist Name" style="width: 100%; margin-bottom: 0.5rem;"><br>
<input type="file" id="uploadArt" style="margin-bottom: 0.5rem;"><br> <input type="file" id="uploadArt" style="margin-bottom: 0.5rem;"><br>
<select id="frameSelect" style="width: 100%; margin-bottom: 0.5rem;"> <select id="frameSelect" style="width: 100%; margin-bottom: 0.5rem;">
<option value="v1_common.png" selected>Common</option> <option value="v1_common.png" selected>Common (100)</option>
<option value="v1_uncommon.png">Uncommon</option> <option value="v1_uncommon.png">Uncommon (140)</option>
<option value="v1_rare.png">Rare</option> <option value="v1_rare.png">Rare (180)</option>
<option value="v1_epic.png">Epic</option> <option value="v1_epic.png">Epic (220)</option>
<option value="v1_legendary.png">Legendary</option> <option value="v1_legendary.png">Legendary (250)</option>
</select> </select>
<button id="downloadBtn" onclick="generateCard()">✨ Create Card</button> <button id="downloadBtn" onclick="generateCard()">✨ Create Card</button>
<p>All the processing is done in your browser, no data is sent to the server.</p> <p>All the processing is done in your browser, no data is sent to the server.</p>
@ -86,9 +88,19 @@ const artistInput = document.getElementById("artistInput");
const downloadBtn = document.getElementById("downloadBtn"); const downloadBtn = document.getElementById("downloadBtn");
const uploadArt = document.getElementById("uploadArt"); const uploadArt = document.getElementById("uploadArt");
const frameSelect = document.getElementById("frameSelect"); const frameSelect = document.getElementById("frameSelect");
const restrictStatsToggle = document.getElementById("restrictStatsToggle");
let frameImage = new Image(); let frameImage = new Image();
let uploadedImage = null; let uploadedImage = null;
// Rarity caps for stats
const rarityCaps = {
"v1_common.png": 100,
"v1_uncommon.png": 140,
"v1_rare.png": 180,
"v1_epic.png": 220,
"v1_legendary.png": 250
};
// Generate a unique ID for the card based on pack and card name // Generate a unique ID for the card based on pack and card name
async function generateCardId(...args) { async function generateCardId(...args) {
const encoder = new TextEncoder(); const encoder = new TextEncoder();
@ -130,6 +142,10 @@ frameSelect.addEventListener("change", updateFrame);
function drawCard() { function drawCard() {
ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.clearRect(0, 0, canvas.width, canvas.height);
// Place a white background
ctx.fillStyle = "#FFFFFF"; // white background
// make it smaller than the size of the canvas
ctx.fillRect(30, 30, canvas.width - 60, canvas.height - 60);
// Draw uploaded art as cropped and centered background if present // Draw uploaded art as cropped and centered background if present
if (uploadedImage) { if (uploadedImage) {
@ -226,6 +242,50 @@ function wrapText(text, x, y, maxWidth, lineHeight) {
input.addEventListener("input", drawCard); input.addEventListener("input", drawCard);
}); });
// Enforce stat caps based on rarity and frame
function enforceStatCap(changedInput) {
if (!restrictStatsToggle.checked) return;
const cap = rarityCaps[frameSelect.value] || 9999;
let power = parseInt(powerInput.value) || 0;
let charm = parseInt(charmInput.value) || 0;
let wit = parseInt(witInput.value) || 0;
let total = power + charm + wit;
if (total > cap) {
// Reduce the changed input to fit the cap
const excess = total - cap;
if (changedInput === powerInput) {
power = Math.max(0, power - excess);
powerInput.value = power;
} else if (changedInput === charmInput) {
charm = Math.max(0, charm - excess);
charmInput.value = charm;
} else if (changedInput === witInput) {
wit = Math.max(0, wit - excess);
witInput.value = wit;
}
}
}
[powerInput, charmInput, witInput].forEach(input => {
input.addEventListener("input", function() {
enforceStatCap(this);
drawCard();
});
});
frameSelect.addEventListener("change", function() {
if (restrictStatsToggle.checked) {
enforceStatCap();
}
updateFrame();
});
restrictStatsToggle.addEventListener("change", function() {
if (this.checked) {
enforceStatCap();
}
});
// Download button // Download button
downloadBtn.addEventListener("click", () => { downloadBtn.addEventListener("click", () => {
// Sanitize file name // Sanitize file name
@ -287,6 +347,7 @@ zipBtn.onclick = async () => {
const safePack = (packInput.value || "pack").replace(/[^a-z0-9_\-]/gi, "_"); const safePack = (packInput.value || "pack").replace(/[^a-z0-9_\-]/gi, "_");
const imgFileName = `kemoverse_${safePack}_${safeName}.webp`; const imgFileName = `kemoverse_${safePack}_${safeName}.webp`;
const jsonFileName = `kemoverse_${safePack}_${safeName}.json`; const jsonFileName = `kemoverse_${safePack}_${safeName}.json`;
const zipFileName = `kemoverse_${safePack}_${safeName}.zip`;
// Create ZIP // Create ZIP
const zip = new JSZip(); const zip = new JSZip();
@ -300,7 +361,7 @@ zipBtn.onclick = async () => {
const content = await zip.generateAsync({type: "blob"}); const content = await zip.generateAsync({type: "blob"});
const link = document.createElement("a"); const link = document.createElement("a");
link.href = URL.createObjectURL(content); link.href = URL.createObjectURL(content);
link.download = `kemoverse_${safePack}_${safeName}.zip`; link.download = zipFileName;
link.click(); link.click();
}; };