document.addEventListener('DOMContentLoaded', function() {
// Initialize counters
let classCount = 0;
let raceCount = 0;
// Generate RPG button functionality
document.querySelector('button.bg-primary-500').addEventListener('click', function() {
// Collect all form data
const formData = {
worldName: document.querySelector('input[type="text"]').value,
backgroundStory: document.querySelector('textarea').value,
majorFactions: document.querySelectorAll('input[type="text"]')[1].value,
races: [],
classes: [],
settings: {
sessionLength: document.querySelector('select').value,
difficulty: document.querySelectorAll('select')[1].value,
playerCount: document.querySelector('input[type="number"]').value,
experienceSystem: document.querySelectorAll('select')[2].value
}
};
// Collect races data
document.querySelectorAll('.race-card').forEach(card => {
formData.races.push({
name: card.querySelector('h3').textContent,
description: card.querySelector('textarea').value,
size: card.querySelector('select').value,
speed: card.querySelector('input[type="text"]').value,
traits: Array.from(card.querySelectorAll('.traits-container input')).map(input => input.value)
});
});
// Collect classes data
document.querySelectorAll('.class-card').forEach(card => {
formData.classes.push({
name: card.querySelector('h3').textContent,
attribute: card.querySelector('select').value,
hitPoints: card.querySelector('input[type="text"]').value,
armor: card.querySelectorAll('select')[1].value,
description: card.querySelector('textarea').value,
abilities: Array.from(card.querySelectorAll('.abilities-container input')).map(input => input.value)
});
});
// Create download link
const dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(formData, null, 2));
const downloadAnchor = document.createElement('a');
downloadAnchor.setAttribute('href', dataStr);
downloadAnchor.setAttribute('download', `${formData.worldName || 'rpg'}_settings.json`);
document.body.appendChild(downloadAnchor);
downloadAnchor.click();
document.body.removeChild(downloadAnchor);
});
// Handle lore file upload
document.getElementById('lore-upload').addEventListener('change', function(e) {
const file = e.target.files[0];
if (!file) return;
const reader = new FileReader();
reader.onload = function(e) {
try {
let loreData;
if (file.name.endsWith('.doc') || file.name.endsWith('.docx')) {
// For DOC files, we'll just display the raw text
loreData = {
worldName: 'Imported DOC File',
backgroundStory: e.target.result,
majorFactions: 'From imported DOC file'
};
} else {
loreData = JSON.parse(e.target.result);
}
// Populate lore fields with uploaded data
if (loreData.worldName) {
document.querySelector('input[type="text"]').value = loreData.worldName;
}
if (loreData.backgroundStory) {
document.querySelector('textarea').value = loreData.backgroundStory;
}
if (loreData.majorFactions) {
document.querySelectorAll('input[type="text"]')[1].value = loreData.majorFactions;
}
} catch (error) {
alert('Error parsing lore file. Please check the format.');
}
};
reader.readAsText(file);
});
// Handle races file upload
document.getElementById('races-upload').addEventListener('change', function(e) {
const file = e.target.files[0];
if (!file) return;
const reader = new FileReader();
reader.onload = function(e) {
try {
let racesData;
if (file.name.endsWith('.doc') || file.name.endsWith('.docx')) {
// For DOC files, we'll parse into structured data
const docContent = e.target.result;
const lines = docContent.split('\n');
racesData = [];
let currentRace = {};
lines.forEach(line => {
if (line.trim().startsWith('Race:')) {
if (Object.keys(currentRace).length > 0) {
racesData.push(currentRace);
}
currentRace = {
name: line.replace('Race:', '').trim(),
description: '',
size: 'Medium',
speed: '30',
traits: []
};
} else if (line.trim().startsWith('Description:')) {
currentRace.description = line.replace('Description:', '').trim();
} else if (line.trim().startsWith('Trait:')) {
currentRace.traits.push(line.replace('Trait:', '').trim());
}
});
if (Object.keys(currentRace).length > 0) {
racesData.push(currentRace);
}
if (racesData.length === 0) {
racesData = [{name: 'Imported DOC', description: e.target.result}];
}
} else {
racesData = JSON.parse(e.target.result);
}
const container = document.getElementById('races-container');
container.innerHTML = ''; // Clear existing races
racesData.forEach((raceData, index) => {
raceCount++;
const raceCard = document.createElement('div');
raceCard.className = 'race-card bg-gray-50 p-4 rounded-lg border border-gray-200 mb-4';
raceCard.innerHTML = `
${raceData.name || `New Race #${index+1}`}
${raceData.traits ? raceData.traits.map(trait => `
`).join('') : ''}
`;
container.appendChild(raceCard);
feather.replace();
// Add event listener for delete button
raceCard.querySelector('button').addEventListener('click', function() {
container.removeChild(raceCard);
raceCount--;
});
// Add event listener for add trait button
const traitsBtn = raceCard.querySelector('.traits-container').nextElementSibling;
traitsBtn.addEventListener('click', function() {
addTraitField(this.previousElementSibling);
});
});
} catch (error) {
alert('Error processing races file. Showing raw content.');
const container = document.getElementById('races-container');
container.innerHTML = `
File Content
${e.target.result}
`;
}
};
if (file.name.endsWith('.doc') || file.name.endsWith('.docx')) {
reader.readAsText(file);
} else {
reader.readAsText(file);
}
});
// Handle classes file upload
document.getElementById('classes-upload').addEventListener('change', function(e) {
const file = e.target.files[0];
if (!file) return;
const reader = new FileReader();
reader.onload = function(e) {
try {
let classesData;
if (file.name.endsWith('.doc') || file.name.endsWith('.docx')) {
// For DOC files, we'll parse into structured data
const docContent = e.target.result;
const lines = docContent.split('\n');
classesData = [];
let currentClass = {};
lines.forEach(line => {
if (line.trim().startsWith('Class:')) {
if (Object.keys(currentClass).length > 0) {
classesData.push(currentClass);
}
currentClass = {
name: line.replace('Class:', '').trim(),
attribute: 'Strength',
hitPoints: '1d8',
armor: 'Light',
description: '',
abilities: []
};
} else if (line.trim().startsWith('Description:')) {
currentClass.description = line.replace('Description:', '').trim();
} else if (line.trim().startsWith('Ability:')) {
currentClass.abilities.push(line.replace('Ability:', '').trim());
}
});
if (Object.keys(currentClass).length > 0) {
classesData.push(currentClass);
}
if (classesData.length === 0) {
classesData = [{name: 'Imported DOC', description: e.target.result}];
}
} else {
classesData = JSON.parse(e.target.result);
}
const container = document.getElementById('classes-container');
container.innerHTML = ''; // Clear existing classes
classesData.forEach((classData, index) => {
classCount++;
const classCard = document.createElement('div');
classCard.className = 'class-card bg-gray-50 p-4 rounded-lg border border-gray-200 mb-4';
classCard.innerHTML = `
${classData.name || `New Class #${index+1}`}
`;
container.appendChild(classCard);
feather.replace();
// Add event listener for delete button
classCard.querySelector('button').addEventListener('click', function() {
container.removeChild(classCard);
classCount--;
});
// Add event listeners for abilities
const abilitiesBtn = classCard.querySelector('.abilities-container').nextElementSibling;
abilitiesBtn.addEventListener('click', function() {
addAbilityField(this.previousElementSibling);
});
// Add event listeners for existing ability delete buttons
classCard.querySelectorAll('.abilities-container button').forEach(btn => {
btn.addEventListener('click', function() {
this.parentElement.remove();
});
});
});
} catch (error) {
alert('Error parsing classes file. Please check the format.');
}
};
reader.readAsText(file);
});
function addAbilityField(container) {
const abilityDiv = document.createElement('div');
abilityDiv.className = 'flex items-center';
abilityDiv.innerHTML = `
`;
container.appendChild(abilityDiv);
feather.replace();
// Add event listener for delete ability button
abilityDiv.querySelector('button').addEventListener('click', function() {
container.removeChild(abilityDiv);
});
}
// Add race button functionality
document.getElementById('add-race-btn').addEventListener('click', function() {
raceCount++;
const container = document.getElementById('races-container');
const raceCard = document.createElement('div');
raceCard.className = 'race-card bg-gray-50 p-4 rounded-lg border border-gray-200 mb-4';
raceCard.innerHTML = `
New Race #${raceCount}
`;
container.appendChild(raceCard);
feather.replace();
// Add event listener for delete button
raceCard.querySelector('button').addEventListener('click', function() {
container.removeChild(raceCard);
raceCount--;
});
// Add event listener for add trait button
const traitsBtn = raceCard.querySelector('.traits-container').nextElementSibling;
traitsBtn.addEventListener('click', function() {
const traitsContainer = this.previousElementSibling;
const traitDiv = document.createElement('div');
traitDiv.className = 'flex items-center';
traitDiv.innerHTML = `
`;
traitsContainer.appendChild(traitDiv);
feather.replace();
// Add event listener for delete trait button
traitDiv.querySelector('button').addEventListener('click', function() {
traitsContainer.removeChild(traitDiv);
});
});
});
// Add class button functionality
document.getElementById('add-class-btn').addEventListener('click', function() {
classCount++;
const container = document.getElementById('classes-container');
const classCard = document.createElement('div');
classCard.className = 'class-card bg-gray-50 p-4 rounded-lg border border-gray-200 mb-4';
classCard.innerHTML = `
New Class #${classCount}
`;
container.appendChild(classCard);
feather.replace();
// Add event listener for delete button
classCard.querySelector('button').addEventListener('click', function() {
container.removeChild(classCard);
classCount--;
});
// Add event listener for add ability button
const abilitiesBtn = classCard.querySelector('.abilities-container').nextElementSibling;
abilitiesBtn.addEventListener('click', function() {
const abilitiesContainer = this.previousElementSibling;
const abilityDiv = document.createElement('div');
abilityDiv.className = 'flex items-center';
abilityDiv.innerHTML = `
`;
abilitiesContainer.appendChild(abilityDiv);
feather.replace();
// Add event listener for delete ability button
abilityDiv.querySelector('button').addEventListener('click', function() {
abilitiesContainer.removeChild(abilityDiv);
});
});
});
// Initialize tooltips for icons
const tooltipTriggers = document.querySelectorAll('[data-tooltip]');
tooltipTriggers.forEach(trigger => {
const tooltip = document.createElement('div');
tooltip.className = 'tooltip hidden absolute bg-black text-white text-xs px-2 py-1 rounded whitespace-nowrap -mt-8';
tooltip.textContent = trigger.getAttribute('data-tooltip');
trigger.appendChild(tooltip);
trigger.addEventListener('mouseenter', () => {
tooltip.classList.remove('hidden');
});
trigger.addEventListener('mouseleave', () => {
tooltip.classList.add('hidden');
});
});
});