'use strict';
/*
* PetSprite — единый источник модели питомца для /pet и /dashboard.
* Канонические PET_PALETTES + shadeColor + renderPetSVG. pet.html и
* dashboard.html используют window.PetSprite.render(...) — без дублей.
*/
(function () {
const PET_PALETTES = {
purple:'#9B5DE5', cyan:'#06D6E0', gold:'#F9C74F',
red:'#F94144', green:'#38D95A', blue:'#4A90D9',
pink:'#F15BB5', orange:'#FB8B24', teal:'#0CA5B8',
lime:'#7FB800', indigo:'#5E60CE',
};
function shadeColor(hex, pct) {
const n = parseInt(hex.slice(1), 16);
const r = Math.min(255,Math.max(0,(n>>16)+pct));
const g = Math.min(255,Math.max(0,((n>>8)&0xff)+pct));
const b = Math.min(255,Math.max(0,(n&0xff)+pct));
return `rgb(${r},${g},${b})`;
}
function renderPetSVG(level, mood, accessories = [], colorKey = 'purple', streak = 0, pattern = 'none') {
const col = PET_PALETTES[colorKey] || '#9B5DE5';
const dark = shadeColor(col, -45);
const light = shadeColor(col, 52);
const uid = `pg${level}${mood[0]}${colorKey[0]}`;
const bodyPath = 'M55,22 C70,22 86,37 87,56 C89,75 78,94 55,97 C32,94 21,75 23,56 C24,37 40,22 55,22 Z';
const eyeY = 52, eyeX1 = 40, eyeX2 = 70;
/* ── Eyebrows ── */
let eyebrows = '';
if (mood !== 'sleeping') {
if (mood === 'ecstatic') {
eyebrows = `
`;
} else if (mood === 'sad' || mood === 'hungry') {
eyebrows = `
`;
} else {
eyebrows = `
`;
}
}
/* ── Eyes ── */
let eyeGroups = '', cheeks = '', extras = '';
if (mood === 'sleeping') {
eyeGroups = `
`;
} else {
const ry1 = mood === 'ecstatic' ? 13 : mood === 'happy' ? 12 : 10.5;
const prx = mood === 'ecstatic' ? 7 : mood === 'happy' ? 6.5 : 5.5;
const pry = mood === 'ecstatic' ? 8 : mood === 'happy' ? 7.5 : 6.5;
const pOff = (mood === 'sad' || mood === 'hungry') ? 3 : 2;
eyeGroups = `
`;
}
/* ── Nose ── */
const nose = mood !== 'sleeping'
? `` : '';
/* ── Mouth + cheeks ── */
let mouth = '';
if (mood === 'sleeping') {
mouth = ``;
} else if (mood === 'ecstatic') {
mouth = ``;
cheeks = `
`;
} else if (mood === 'happy') {
mouth = ``;
cheeks = `
`;
} else if (mood === 'sad' || mood === 'hungry') {
mouth = ``;
if (mood === 'hungry')
extras = ``;
} else {
mouth = ``;
}
/* ── Animated tail (all levels) ── */
const tail = `
`;
/* ── Ears (level 2+) ── */
let ears = '';
if (level >= 2) {
ears = `
`;
}
/* ── Antennae (level 3+) ── */
let antennae = '';
if (level >= 3) {
antennae = `
`;
}
/* ── Wings with flutter (level 4+) ── */
let wings = '';
if (level >= 4) {
wings = `
`;
}
/* ── Paws with fingers ── */
const paws = `
`;
/* ── Accessories (гардероб: строго по equipped-списку, без авто по уровню) ── */
let accSvg = '';
if (accessories.includes('party')) {
accSvg += `
`;
}
if (accessories.includes('sunglasses')) {
accSvg += `
`;
}
if (accessories.includes('scarf')) {
accSvg += `
`;
}
if (accessories.includes('flower')) {
accSvg += ``;
}
if (accessories.includes('beanie')) {
accSvg += `
`;
}
if (accessories.includes('halo')) {
accSvg += `
`;
}
if (accessories.includes('monocle')) {
accSvg += `
`;
}
if (accessories.includes('medal')) {
accSvg += `
`;
}
if (accessories.includes('earrings')) {
accSvg += `
`;
}
if (accessories.includes('wand')) {
accSvg += `
`;
}
if (accessories.includes('balloon')) {
accSvg += `
`;
}
if (accessories.includes('headphones')) {
accSvg += `
`;
}
if (accessories.includes('grad')) {
accSvg += `
`;
}
if (accessories.includes('hat')) {
accSvg += `
`;
}
if (accessories.includes('crown')) {
accSvg += `
`;
}
if (accessories.includes('glasses')) {
accSvg += `
`;
}
if (accessories.includes('bowtie')) {
accSvg += `
`;
}
if (accessories.includes('star')) {
accSvg += ``;
}
/* ── Aura ring (level 4+) ── */
let aura = '';
if (level >= 4) {
aura = `
`;
}
/* ── B3 Rainbow collar (streak ≥ 7) ── */
let rainbowCollar = '';
if (streak >= 7) {
rainbowCollar = `
`;
}
/* ── Orbital particles (level 5+) ── */
let orbitals = '';
if (level >= 5) {
const oData = [
{ start: 0, dur: 2.8, r: 46, size: 4, fill: col, op: .85 },
{ start: 120, dur: 3.6, r: 43, size: 3, fill: light, op: .7 },
{ start: 240, dur: 2.2, r: 48, size: 3.5, fill: 'white', op: .6 },
];
// Extra orbitals for level 6+
if (level >= 6) {
oData.push(
{ start: 60, dur: 1.9, r: 51, size: 2.5, fill: light, op: .65 },
{ start: 180, dur: 4.1, r: 40, size: 2, fill: col, op: .55 },
{ start: 300, dur: 3.0, r: 54, size: 3, fill: 'white', op: .5 },
);
}
// Even more for level 8
if (level >= 8) {
oData.push(
{ start: 45, dur: 1.5, r: 56, size: 3.5, fill: '#FFD700', op: .9 },
{ start: 225, dur: 2.4, r: 38, size: 2.5, fill: '#FFD700', op: .75 },
);
}
orbitals = oData.map(o => `
`).join('\n');
}
/* ── Second aura ring (level 6+) ── */
if (level >= 6) {
aura += `
`;
}
/* ── Crystal halo (level 7+) ── */
let halo = '';
if (level >= 7) {
halo = `
`;
}
/* ── Second wing pair (level 7+) ── */
if (level >= 7) {
wings += `
`;
}
/* ── Third aura + body shimmer (level 8) ── */
let shimmer = '';
if (level >= 8) {
aura += `
`;
shimmer = ``;
}
// Узор тела (клипуется по силуэту)
let patternSvg = '';
if (pattern && pattern !== 'none') {
let pin = '';
if (pattern === 'spots') pin = ``;
else if (pattern === 'stripes') pin = `${[-10,8,26,44,62,80,98].map(x => ``).join('')}`;
else if (pattern === 'galaxy') pin = ``;
else if (pattern === 'gradient') pin = ``;
else if (pattern === 'hearts') pin = [[40,44],[68,40],[57,70],[36,73],[76,63],[52,33]].map(p => ``).join('');
else if (pattern === 'stars') pin = [[40,44],[68,40],[57,70],[36,73],[76,63],[52,33]].map(p => ``).join('');
else if (pattern === 'checker') pin = Array.from({ length: 42 }, (_, i) => { const c = i % 6, r = (i / 6) | 0; return ((r + c) % 2) ? '' : ``; }).join('');
patternSvg = `${pin}`;
}
return ``;
}
var MOOD_RU = {
ecstatic: 'в восторге', happy: 'в духе', neutral: 'бодр',
sad: 'скучает', hungry: 'голоден', sleeping: 'спит',
};
window.PetSprite = {
PALETTES: PET_PALETTES,
shade: shadeColor,
render: renderPetSVG,
moodLabel: function (m) { return MOOD_RU[m] || 'бодр'; },
};
})();