147 lines
5.2 KiB
JavaScript
147 lines
5.2 KiB
JavaScript
/**
|
|
* PPE SAFETY CHALLENGE - DYNAMIC 2D WORKER AVATAR SYSTEM
|
|
* Uses the step-by-step transparent character images from ppe_character_steps_transparent_png!
|
|
* Dynamically switches character states as safety gear is equipped.
|
|
*/
|
|
|
|
class WorkerAvatar {
|
|
constructor(containerId) {
|
|
this.container = document.getElementById(containerId);
|
|
this.equippedItems = new Set();
|
|
this.render();
|
|
}
|
|
|
|
setEquipped(itemIds) {
|
|
this.equippedItems = new Set(itemIds);
|
|
this.updateLayers();
|
|
}
|
|
|
|
equip(itemId) {
|
|
this.equippedItems.add(itemId);
|
|
this.updateLayers();
|
|
}
|
|
|
|
unequip(itemId) {
|
|
this.equippedItems.delete(itemId);
|
|
this.updateLayers();
|
|
}
|
|
|
|
has(itemId) {
|
|
return this.equippedItems.has(itemId);
|
|
}
|
|
|
|
getAvatarCenterCoordinates() {
|
|
if (!this.container) return { x: 170, y: 220, eyeX: 170, eyeY: 110, handX: 230, handY: 260 };
|
|
const rect = this.container.getBoundingClientRect();
|
|
const parentRect = this.container.parentElement.getBoundingClientRect();
|
|
const relX = rect.left - parentRect.left + (rect.width * 0.5);
|
|
const relY = rect.top - parentRect.top + (rect.height * 0.5);
|
|
return {
|
|
x: relX,
|
|
y: relY,
|
|
eyeX: relX,
|
|
eyeY: relY - 130,
|
|
handX: relX + 55,
|
|
handY: relY + 30
|
|
};
|
|
}
|
|
|
|
getStepImagePath() {
|
|
const hasHelmet = this.equippedItems.has('safety_helmet_grind') || this.equippedItems.has('safety_helmet_chem');
|
|
const hasGoggles = this.equippedItems.has('chem_splash_goggles') || this.equippedItems.has('safety_goggles_grind');
|
|
const hasFaceShield = this.equippedItems.has('face_shield_grind') || this.equippedItems.has('face_shield_chem');
|
|
const hasHearing = this.equippedItems.has('hearing_protection_grind') || this.equippedItems.has('hearing_protection_chem');
|
|
const hasLeatherGloves = this.equippedItems.has('leather_grinding_gloves');
|
|
const hasWorkGloves = this.equippedItems.has('work_gloves_grind') || this.equippedItems.has('standard_work_gloves');
|
|
const hasChemGloves = this.equippedItems.has('chem_resistant_gloves');
|
|
const hasVest = this.equippedItems.has('reflective_vest_grind');
|
|
const hasApron = this.equippedItems.has('chem_resistant_apron');
|
|
const hasCottonCoat = this.equippedItems.has('cotton_coat_chem');
|
|
const hasBoots = this.equippedItems.has('steel_toe_boots_grind') || this.equippedItems.has('chem_safety_shoes');
|
|
const hasMask = this.equippedItems.has('dust_mask_grind');
|
|
|
|
// 10. Full PPE with Mask
|
|
if (hasMask) {
|
|
return 'images/steps/10_full_ppe_with_mask.png';
|
|
}
|
|
|
|
// 9. Full Grinding Set with Boots
|
|
if (hasHelmet && (hasGoggles || hasFaceShield) && hasHearing && (hasLeatherGloves || hasChemGloves) && (hasVest || hasApron || hasBoots)) {
|
|
return 'images/steps/09_helmet_goggles_hearing_leather_gloves_vest_boots.png';
|
|
}
|
|
|
|
// 8. With Vest / Body Wear
|
|
if (hasHelmet && (hasGoggles || hasFaceShield) && hasHearing && (hasLeatherGloves || hasChemGloves) && (hasVest || hasApron || hasCottonCoat)) {
|
|
return 'images/steps/08_helmet_goggles_hearing_leather_gloves_vest.png';
|
|
}
|
|
|
|
// 7. With Leather / Chem Gloves
|
|
if (hasHelmet && (hasGoggles || hasFaceShield) && hasHearing && (hasLeatherGloves || hasChemGloves)) {
|
|
return 'images/steps/07_helmet_goggles_hearing_leather_gloves.png';
|
|
}
|
|
|
|
// 6. With Work Gloves
|
|
if (hasHelmet && (hasGoggles || hasFaceShield) && hasHearing && hasWorkGloves) {
|
|
return 'images/steps/06_helmet_goggles_hearing_work_gloves.png';
|
|
}
|
|
|
|
// 5. With Earmuffs / Hearing Protection
|
|
if (hasHelmet && (hasGoggles || hasFaceShield) && hasHearing) {
|
|
return 'images/steps/05_helmet_goggles_hearing.png';
|
|
}
|
|
|
|
// 4. With Face Shield
|
|
if (hasFaceShield || (hasHelmet && hasFaceShield)) {
|
|
return 'images/steps/04_helmet_goggles_face_shield.png';
|
|
}
|
|
|
|
// 3. With Goggles & Helmet
|
|
if (hasHelmet && hasGoggles) {
|
|
return 'images/steps/03_helmet_goggles.png';
|
|
}
|
|
|
|
// 2. Helmet Only
|
|
if (hasHelmet) {
|
|
return 'images/steps/02_helmet.png';
|
|
}
|
|
|
|
// Individual items
|
|
if (hasFaceShield) return 'images/steps/04_helmet_goggles_face_shield.png';
|
|
if (hasGoggles) return 'images/steps/03_helmet_goggles.png';
|
|
if (hasHearing) return 'images/steps/05_helmet_goggles_hearing.png';
|
|
if (hasLeatherGloves) return 'images/steps/07_helmet_goggles_hearing_leather_gloves.png';
|
|
if (hasWorkGloves) return 'images/steps/06_helmet_goggles_hearing_work_gloves.png';
|
|
|
|
// 1. Base Worker (No PPE)
|
|
return 'images/steps/01_no_ppe.png';
|
|
}
|
|
|
|
render() {
|
|
if (!this.container) return;
|
|
|
|
this.container.innerHTML = `
|
|
<div class="avatar-step-container" id="avatar-step-container">
|
|
<!-- Floor Contact Shadow -->
|
|
<div class="avatar-floor-shadow"></div>
|
|
|
|
<!-- Dynamic Character Step Image -->
|
|
<img src="images/steps/01_no_ppe.png" alt="Worker Character" class="avatar-step-img" id="avatar-step-img" />
|
|
</div>
|
|
`;
|
|
|
|
this.updateLayers();
|
|
}
|
|
|
|
updateLayers() {
|
|
if (!this.container) return;
|
|
|
|
const imgEl = document.getElementById('avatar-step-img');
|
|
if (imgEl) {
|
|
const targetSrc = this.getStepImagePath();
|
|
if (imgEl.getAttribute('src') !== targetSrc) {
|
|
imgEl.src = targetSrc;
|
|
}
|
|
}
|
|
}
|
|
}
|