Files
2026-04-30 02:14:25 +00:00

967 lines
28 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Avatar Creator - GamerComp</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
:root {
--bg-dark: #1a1a2e;
--bg-panel: #16213e;
--bg-item: #0f3460;
--accent: #e94560;
--accent-hover: #ff6b6b;
--text: #eee;
--text-muted: #aaa;
--border: #2a3a5e;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: var(--bg-dark);
color: var(--text);
min-height: 100vh;
display: flex;
flex-direction: column;
}
header {
background: var(--bg-panel);
padding: 1rem 2rem;
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 2px solid var(--border);
}
header h1 {
font-size: 1.5rem;
color: var(--accent);
}
.btn {
padding: 0.6rem 1.5rem;
border: none;
border-radius: 8px;
font-size: 1rem;
cursor: pointer;
transition: all 0.2s;
}
.btn-primary {
background: var(--accent);
color: white;
}
.btn-primary:hover {
background: var(--accent-hover);
transform: scale(1.02);
}
.btn-secondary {
background: var(--bg-item);
color: var(--text);
border: 1px solid var(--border);
}
.btn-secondary:hover {
background: var(--border);
}
main {
flex: 1;
display: flex;
padding: 1rem;
gap: 1rem;
}
/* Preview Panel */
.preview-panel {
width: 300px;
background: var(--bg-panel);
border-radius: 12px;
padding: 1.5rem;
display: flex;
flex-direction: column;
align-items: center;
}
.preview-canvas-container {
background: linear-gradient(135deg, #2a3a5e, #1a2a4e);
border-radius: 12px;
padding: 2rem;
margin-bottom: 1.5rem;
}
#previewCanvas {
display: block;
}
.preview-modes {
display: flex;
gap: 0.5rem;
margin-bottom: 1rem;
flex-wrap: wrap;
justify-content: center;
}
.preview-modes button {
padding: 0.4rem 0.8rem;
font-size: 0.75rem;
border-radius: 6px;
background: var(--bg-item);
border: 1px solid var(--border);
color: var(--text-muted);
cursor: pointer;
}
.preview-modes button.active {
background: var(--accent);
color: white;
border-color: var(--accent);
}
.preview-animations {
display: flex;
gap: 0.5rem;
flex-wrap: wrap;
justify-content: center;
}
.preview-animations button {
padding: 0.3rem 0.6rem;
font-size: 0.7rem;
border-radius: 4px;
background: var(--bg-dark);
border: 1px solid var(--border);
color: var(--text-muted);
cursor: pointer;
}
.preview-animations button:hover {
border-color: var(--accent);
color: var(--text);
}
/* Customization Panel */
.customization-panel {
flex: 1;
background: var(--bg-panel);
border-radius: 12px;
display: flex;
flex-direction: column;
overflow: hidden;
}
.category-tabs {
display: flex;
background: var(--bg-dark);
padding: 0.5rem;
gap: 0.5rem;
overflow-x: auto;
}
.category-tab {
padding: 0.6rem 1rem;
border-radius: 8px;
background: transparent;
border: none;
color: var(--text-muted);
cursor: pointer;
white-space: nowrap;
font-size: 0.9rem;
transition: all 0.2s;
}
.category-tab:hover {
color: var(--text);
}
.category-tab.active {
background: var(--accent);
color: white;
}
.options-container {
flex: 1;
overflow-y: auto;
padding: 1rem;
}
.option-group {
margin-bottom: 1.5rem;
}
.option-group h3 {
font-size: 0.9rem;
color: var(--text-muted);
margin-bottom: 0.75rem;
text-transform: uppercase;
letter-spacing: 1px;
}
.option-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(50px, 1fr));
gap: 0.5rem;
}
.option-grid.colors {
grid-template-columns: repeat(auto-fill, minmax(36px, 1fr));
}
.option-item {
aspect-ratio: 1;
border-radius: 8px;
border: 2px solid transparent;
background: var(--bg-item);
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.2s;
position: relative;
}
.option-item:hover {
border-color: var(--text-muted);
transform: scale(1.05);
}
.option-item.selected {
border-color: var(--accent);
box-shadow: 0 0 10px rgba(233, 69, 96, 0.4);
}
.option-item.color-swatch {
border-radius: 50%;
}
.option-item img, .option-item canvas {
max-width: 80%;
max-height: 80%;
}
.option-item .label {
font-size: 0.6rem;
color: var(--text-muted);
position: absolute;
bottom: 2px;
left: 50%;
transform: translateX(-50%);
white-space: nowrap;
}
/* Accessories Panel */
.accessories-panel {
width: 280px;
background: var(--bg-panel);
border-radius: 12px;
padding: 1rem;
display: flex;
flex-direction: column;
}
.accessories-panel h2 {
font-size: 1rem;
margin-bottom: 1rem;
color: var(--accent);
}
.accessory-section {
margin-bottom: 1rem;
}
.accessory-section h3 {
font-size: 0.8rem;
color: var(--text-muted);
margin-bottom: 0.5rem;
}
.accessory-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 0.5rem;
}
.accessory-item {
aspect-ratio: 1;
border-radius: 6px;
background: var(--bg-item);
border: 2px solid transparent;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
position: relative;
transition: all 0.2s;
}
.accessory-item:hover {
border-color: var(--text-muted);
}
.accessory-item.equipped {
border-color: var(--accent);
}
.accessory-item.locked {
opacity: 0.4;
cursor: not-allowed;
}
.accessory-item .level-badge {
position: absolute;
top: 2px;
right: 2px;
font-size: 0.55rem;
background: var(--bg-dark);
padding: 1px 4px;
border-radius: 3px;
color: var(--text-muted);
}
.rarity-common { border-color: #9d9d9d !important; }
.rarity-uncommon { border-color: #1eff00 !important; }
.rarity-rare { border-color: #0070dd !important; }
.rarity-epic { border-color: #a335ee !important; }
.rarity-legendary { border-color: #ff8000 !important; }
.rarity-mythic { border-color: #e6cc80 !important; }
/* Randomize Button */
.randomize-btn {
margin-top: auto;
width: 100%;
padding: 0.8rem;
border-radius: 8px;
background: var(--bg-item);
border: 1px dashed var(--border);
color: var(--text);
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
}
.randomize-btn:hover {
border-color: var(--accent);
color: var(--accent);
}
/* Responsive */
@media (max-width: 900px) {
main {
flex-direction: column;
}
.preview-panel, .accessories-panel {
width: 100%;
}
.preview-canvas-container {
padding: 1rem;
}
}
</style>
</head>
<body>
<header>
<h1>Avatar Creator</h1>
<div style="display: flex; gap: 0.5rem;">
<button class="btn btn-secondary" id="resetBtn">Reset</button>
<button class="btn btn-primary" id="saveBtn">Save Avatar</button>
</div>
</header>
<main>
<!-- Preview Panel -->
<div class="preview-panel">
<div class="preview-canvas-container">
<canvas id="previewCanvas" width="128" height="256"></canvas>
</div>
<div class="preview-modes">
<button data-mode="HEAD_ONLY">Head</button>
<button data-mode="HEAD_AND_SHOULDERS">Shoulders</button>
<button data-mode="UPPER_BODY">Upper</button>
<button data-mode="FULL_BODY" class="active">Full</button>
</div>
<div class="preview-animations">
<button data-anim="idle">Idle</button>
<button data-anim="walk">Walk</button>
<button data-anim="run">Run</button>
<button data-anim="jump">Jump</button>
<button data-anim="wave">Wave</button>
<button data-anim="celebrate">Celebrate</button>
</div>
</div>
<!-- Customization Panel -->
<div class="customization-panel">
<div class="category-tabs">
<button class="category-tab active" data-category="face">Face</button>
<button class="category-tab" data-category="eyes">Eyes</button>
<button class="category-tab" data-category="hair">Hair</button>
<button class="category-tab" data-category="body">Body</button>
<button class="category-tab" data-category="clothing">Clothing</button>
</div>
<div class="options-container" id="optionsContainer">
<!-- Options populated by JavaScript -->
</div>
</div>
<!-- Accessories Panel -->
<div class="accessories-panel">
<h2>Equipped Accessories</h2>
<div class="accessory-section">
<h3>Eyewear</h3>
<div class="accessory-grid" id="eyewearGrid">
<!-- Populated by JavaScript -->
</div>
</div>
<div class="accessory-section">
<h3>Headwear</h3>
<div class="accessory-grid" id="headwearGrid">
<!-- Populated by JavaScript -->
</div>
</div>
<div class="accessory-section">
<h3>Effects</h3>
<div class="accessory-grid" id="effectsGrid">
<!-- Populated by JavaScript -->
</div>
</div>
<button class="randomize-btn" id="randomizeBtn">
<span>🎲</span> Randomize
</button>
</div>
</main>
<!-- Load Avatar System -->
<script src="/assets/avatar/avatarData.js"></script>
<script src="/assets/avatar/animations.js"></script>
<script src="/assets/avatar/accessories.js"></script>
<script src="/assets/avatar/avatarRenderer.js"></script>
<script src="/assets/avatar/accessoryRenderer.js"></script>
<script src="/assets/avatar/avatarSystem.js"></script>
<script>
(function() {
'use strict';
// Current avatar state
var avatar = null;
var currentMode = 'FULL_BODY';
var currentAnimation = 'idle';
var animationFrame = 0;
var lastFrameTime = 0;
// Canvas setup
var canvas = document.getElementById('previewCanvas');
var ctx = canvas.getContext('2d');
// Initialize
function init() {
// Create default avatar
avatar = AvatarSystem.createDefault();
// For demo, give some earned accessories
avatar.earned = {
eyewear: ['sunglasses-classic', 'nerd-glasses', 'aviator'],
headwear: ['baseball-cap', 'beanie', 'crown-gold'],
effects: ['sparkle-trail']
};
avatar.level = 42;
// Setup UI
setupCategoryTabs();
setupModeButtons();
setupAnimationButtons();
setupAccessoriesPanel();
renderOptions('face');
// Start render loop
requestAnimationFrame(renderLoop);
}
// Render loop
function renderLoop(time) {
// Update animation frame
var anim = window.AvatarAnimations && AvatarAnimations.getAnimation(currentMode, currentAnimation);
if (anim) {
var frameDuration = anim.frameDuration || 100;
if (time - lastFrameTime > frameDuration) {
animationFrame = (animationFrame + 1) % anim.frameCount;
lastFrameTime = time;
}
}
// Clear and render
ctx.clearRect(0, 0, canvas.width, canvas.height);
var modeSize = window.AvatarSystem ? AvatarSystem.getModeSize(currentMode) : { width: 64, height: 160 };
var scale = Math.min(
(canvas.width - 20) / modeSize.width,
(canvas.height - 20) / modeSize.height
);
var x = canvas.width / 2;
var y = canvas.height / 2 + (modeSize.height * scale) / 4;
if (window.AvatarSystem) {
AvatarSystem.render(avatar, currentMode, ctx, x, y, {
scale: scale,
animation: currentAnimation,
frame: animationFrame,
time: time / 1000
});
} else {
// Fallback placeholder
ctx.fillStyle = '#e94560';
ctx.beginPath();
ctx.arc(x, y - 40, 30, 0, Math.PI * 2);
ctx.fill();
ctx.fillStyle = '#16213e';
ctx.fillRect(x - 20, y - 5, 40, 50);
}
requestAnimationFrame(renderLoop);
}
// Category tabs
function setupCategoryTabs() {
var tabs = document.querySelectorAll('.category-tab');
tabs.forEach(function(tab) {
tab.addEventListener('click', function() {
tabs.forEach(function(t) { t.classList.remove('active'); });
tab.classList.add('active');
renderOptions(tab.dataset.category);
});
});
}
// Mode buttons
function setupModeButtons() {
var buttons = document.querySelectorAll('.preview-modes button');
buttons.forEach(function(btn) {
btn.addEventListener('click', function() {
buttons.forEach(function(b) { b.classList.remove('active'); });
btn.classList.add('active');
currentMode = btn.dataset.mode;
animationFrame = 0;
});
});
}
// Animation buttons
function setupAnimationButtons() {
var buttons = document.querySelectorAll('.preview-animations button');
buttons.forEach(function(btn) {
btn.addEventListener('click', function() {
currentAnimation = btn.dataset.anim;
animationFrame = 0;
});
});
}
// Render customization options
function renderOptions(category) {
var container = document.getElementById('optionsContainer');
container.innerHTML = '';
if (!window.AvatarData) {
container.innerHTML = '<p style="color: var(--text-muted); padding: 2rem;">Loading options...</p>';
return;
}
switch (category) {
case 'face':
renderFaceOptions(container);
break;
case 'eyes':
renderEyeOptions(container);
break;
case 'hair':
renderHairOptions(container);
break;
case 'body':
renderBodyOptions(container);
break;
case 'clothing':
renderClothingOptions(container);
break;
}
}
function renderFaceOptions(container) {
// Face Shape
var group1 = createOptionGroup('Face Shape');
var grid1 = createOptionGrid();
AvatarData.FACE_SHAPES.forEach(function(shape) {
var item = createOptionItem(shape.name, shape.id === avatar.base.faceShape);
item.addEventListener('click', function() {
avatar.base.faceShape = shape.id;
renderOptions('face');
});
grid1.appendChild(item);
});
group1.appendChild(grid1);
container.appendChild(group1);
// Skin Tone
var group2 = createOptionGroup('Skin Tone');
var grid2 = createOptionGrid('colors');
AvatarData.SKIN_TONES.forEach(function(tone) {
var item = createColorSwatch(tone.hex, avatar.base.skinTone === tone.hex);
item.addEventListener('click', function() {
avatar.base.skinTone = tone.hex;
renderOptions('face');
});
grid2.appendChild(item);
});
group2.appendChild(grid2);
container.appendChild(group2);
// Nose
var group3 = createOptionGroup('Nose');
var grid3 = createOptionGrid();
AvatarData.NOSE_SHAPES.forEach(function(nose) {
var item = createOptionItem(nose.name, nose.id === avatar.base.nose);
item.addEventListener('click', function() {
avatar.base.nose = nose.id;
renderOptions('face');
});
grid3.appendChild(item);
});
group3.appendChild(grid3);
container.appendChild(group3);
// Mouth
var group4 = createOptionGroup('Mouth');
var grid4 = createOptionGrid();
AvatarData.MOUTH_SHAPES.forEach(function(mouth) {
var item = createOptionItem(mouth.name, mouth.id === avatar.base.mouth);
item.addEventListener('click', function() {
avatar.base.mouth = mouth.id;
renderOptions('face');
});
grid4.appendChild(item);
});
group4.appendChild(grid4);
container.appendChild(group4);
}
function renderEyeOptions(container) {
// Eye Shape
var group1 = createOptionGroup('Eye Shape');
var grid1 = createOptionGrid();
AvatarData.EYE_SHAPES.forEach(function(shape) {
var item = createOptionItem(shape.name, shape.id === avatar.base.eyes.shape);
item.addEventListener('click', function() {
avatar.base.eyes.shape = shape.id;
renderOptions('eyes');
});
grid1.appendChild(item);
});
group1.appendChild(grid1);
container.appendChild(group1);
// Eye Color
var group2 = createOptionGroup('Eye Color');
var grid2 = createOptionGrid('colors');
AvatarData.EYE_COLORS.forEach(function(color) {
var item = createColorSwatch(color.hex, color.id === avatar.base.eyes.color);
item.addEventListener('click', function() {
avatar.base.eyes.color = color.id;
renderOptions('eyes');
});
grid2.appendChild(item);
});
group2.appendChild(grid2);
container.appendChild(group2);
// Eyebrows
var group3 = createOptionGroup('Eyebrows');
var grid3 = createOptionGrid();
AvatarData.EYEBROW_SHAPES.forEach(function(brow) {
var item = createOptionItem(brow.name, brow.id === avatar.base.eyebrows);
item.addEventListener('click', function() {
avatar.base.eyebrows = brow.id;
renderOptions('eyes');
});
grid3.appendChild(item);
});
group3.appendChild(grid3);
container.appendChild(group3);
}
function renderHairOptions(container) {
// Hair Style
var group1 = createOptionGroup('Hair Style');
var grid1 = createOptionGrid();
AvatarData.HAIR_STYLES.forEach(function(style) {
var item = createOptionItem(style.name, style.id === avatar.base.hair.style);
item.addEventListener('click', function() {
avatar.base.hair.style = style.id;
renderOptions('hair');
});
grid1.appendChild(item);
});
group1.appendChild(grid1);
container.appendChild(group1);
// Hair Color
var group2 = createOptionGroup('Hair Color');
var grid2 = createOptionGrid('colors');
AvatarData.HAIR_COLORS.forEach(function(color) {
var item = createColorSwatch(color.hex, avatar.base.hair.color === color.hex);
item.addEventListener('click', function() {
avatar.base.hair.color = color.hex;
renderOptions('hair');
});
grid2.appendChild(item);
});
group2.appendChild(grid2);
container.appendChild(group2);
// Facial Hair
var group3 = createOptionGroup('Facial Hair');
var grid3 = createOptionGrid();
AvatarData.FACIAL_HAIR.forEach(function(fh) {
var item = createOptionItem(fh.name, fh.id === avatar.base.facialHair);
item.addEventListener('click', function() {
avatar.base.facialHair = fh.id;
renderOptions('hair');
});
grid3.appendChild(item);
});
group3.appendChild(grid3);
container.appendChild(group3);
}
function renderBodyOptions(container) {
// Body Type
var group1 = createOptionGroup('Body Type');
var grid1 = createOptionGrid();
AvatarData.BODY_TYPES.forEach(function(type) {
var item = createOptionItem(type.name, type.id === avatar.base.body.type);
item.addEventListener('click', function() {
avatar.base.body.type = type.id;
renderOptions('body');
});
grid1.appendChild(item);
});
group1.appendChild(grid1);
container.appendChild(group1);
}
function renderClothingOptions(container) {
// Clothing Style
var group1 = createOptionGroup('Style');
var grid1 = createOptionGrid();
AvatarData.CLOTHING_STYLES.forEach(function(style) {
var item = createOptionItem(style.name, style.id === avatar.base.clothing.style);
item.addEventListener('click', function() {
avatar.base.clothing.style = style.id;
renderOptions('clothing');
});
grid1.appendChild(item);
});
group1.appendChild(grid1);
container.appendChild(group1);
// Shirt Color
var group2 = createOptionGroup('Shirt Color');
var grid2 = createOptionGrid('colors');
AvatarData.CLOTHING_COLORS.forEach(function(color) {
var item = createColorSwatch(color, avatar.base.clothing.shirtColor === color);
item.addEventListener('click', function() {
avatar.base.clothing.shirtColor = color;
renderOptions('clothing');
});
grid2.appendChild(item);
});
group2.appendChild(grid2);
container.appendChild(group2);
// Pants Color
var group3 = createOptionGroup('Pants Color');
var grid3 = createOptionGrid('colors');
AvatarData.CLOTHING_COLORS.forEach(function(color) {
var item = createColorSwatch(color, avatar.base.clothing.pantsColor === color);
item.addEventListener('click', function() {
avatar.base.clothing.pantsColor = color;
renderOptions('clothing');
});
grid3.appendChild(item);
});
group3.appendChild(grid3);
container.appendChild(group3);
}
// Accessories panel
function setupAccessoriesPanel() {
updateAccessoriesUI();
document.getElementById('randomizeBtn').addEventListener('click', randomizeAvatar);
document.getElementById('resetBtn').addEventListener('click', function() {
avatar = AvatarSystem.createDefault();
avatar.earned = { eyewear: ['sunglasses-classic'], headwear: ['baseball-cap'], effects: [] };
avatar.level = 1;
renderOptions('face');
updateAccessoriesUI();
});
document.getElementById('saveBtn').addEventListener('click', function() {
// Would save to API
console.log('Saving avatar:', JSON.stringify(avatar, null, 2));
alert('Avatar saved! (Check console for data)');
});
}
function updateAccessoriesUI() {
if (!window.AvatarAccessories) return;
// Eyewear
var eyewearGrid = document.getElementById('eyewearGrid');
eyewearGrid.innerHTML = '';
var eyewearItems = AvatarAccessories.getByCategory('eyewear').slice(0, 8);
eyewearItems.forEach(function(item) {
var el = createAccessoryItem(item, 'eyewear');
eyewearGrid.appendChild(el);
});
// Headwear
var headwearGrid = document.getElementById('headwearGrid');
headwearGrid.innerHTML = '';
var headwearItems = AvatarAccessories.getByCategory('headwear').slice(0, 8);
headwearItems.forEach(function(item) {
var el = createAccessoryItem(item, 'headwear');
headwearGrid.appendChild(el);
});
// Effects
var effectsGrid = document.getElementById('effectsGrid');
effectsGrid.innerHTML = '';
var effectItems = AvatarAccessories.getByCategory('effect').slice(0, 8);
effectItems.forEach(function(item) {
var el = createAccessoryItem(item, 'effect');
effectsGrid.appendChild(el);
});
}
function createAccessoryItem(item, category) {
var div = document.createElement('div');
div.className = 'accessory-item';
var earned = avatar.earned[category === 'effect' ? 'effects' : category] || [];
var isEarned = earned.includes(item.id);
var isEquipped = avatar.equipped[category] === item.id;
if (!isEarned) {
div.classList.add('locked');
div.innerHTML = '<span class="level-badge">Lv' + item.unlockLevel + '</span>';
} else {
div.classList.add('rarity-' + item.rarity);
if (isEquipped) div.classList.add('equipped');
div.innerHTML = '<span style="font-size:1.2rem">' + getAccessoryEmoji(item.id) + '</span>';
div.addEventListener('click', function() {
if (isEquipped) {
avatar.equipped[category] = null;
} else {
avatar.equipped[category] = item.id;
}
updateAccessoriesUI();
});
}
div.title = item.name;
return div;
}
function getAccessoryEmoji(id) {
var emojis = {
'sunglasses-classic': '🕶️', 'aviator': '🥽', 'nerd-glasses': '🤓',
'baseball-cap': '🧢', 'beanie': '🎿', 'crown-gold': '👑',
'sparkle-trail': '✨', 'fire-aura': '🔥', 'lightning-crackle': '⚡'
};
return emojis[id] || '🎁';
}
// Helper functions
function createOptionGroup(title) {
var div = document.createElement('div');
div.className = 'option-group';
var h3 = document.createElement('h3');
h3.textContent = title;
div.appendChild(h3);
return div;
}
function createOptionGrid(type) {
var div = document.createElement('div');
div.className = 'option-grid' + (type ? ' ' + type : '');
return div;
}
function createOptionItem(label, selected) {
var div = document.createElement('div');
div.className = 'option-item' + (selected ? ' selected' : '');
var span = document.createElement('span');
span.className = 'label';
span.textContent = label.length > 8 ? label.substring(0, 7) + '…' : label;
div.appendChild(span);
return div;
}
function createColorSwatch(color, selected) {
var div = document.createElement('div');
div.className = 'option-item color-swatch' + (selected ? ' selected' : '');
div.style.backgroundColor = color;
return div;
}
function randomizeAvatar() {
if (!window.AvatarData) return;
function pick(arr) { return arr[Math.floor(Math.random() * arr.length)]; }
avatar.base.faceShape = pick(AvatarData.FACE_SHAPES).id;
avatar.base.skinTone = pick(AvatarData.SKIN_TONES).hex;
avatar.base.eyes.shape = pick(AvatarData.EYE_SHAPES).id;
avatar.base.eyes.color = pick(AvatarData.EYE_COLORS).id;
avatar.base.eyebrows = pick(AvatarData.EYEBROW_SHAPES).id;
avatar.base.nose = pick(AvatarData.NOSE_SHAPES).id;
avatar.base.mouth = pick(AvatarData.MOUTH_SHAPES).id;
avatar.base.hair.style = pick(AvatarData.HAIR_STYLES).id;
avatar.base.hair.color = pick(AvatarData.HAIR_COLORS).hex;
avatar.base.facialHair = pick(AvatarData.FACIAL_HAIR).id;
avatar.base.body.type = pick(AvatarData.BODY_TYPES).id;
avatar.base.clothing.style = pick(AvatarData.CLOTHING_STYLES).id;
avatar.base.clothing.shirtColor = pick(AvatarData.CLOTHING_COLORS);
avatar.base.clothing.pantsColor = pick(AvatarData.CLOTHING_COLORS);
renderOptions(document.querySelector('.category-tab.active').dataset.category);
}
// Initialize when ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}
})();
</script>
</body>
</html>