Compare commits
10 Commits
5c04b7a1ed
...
84fbf31f75
| Author | SHA1 | Date | |
|---|---|---|---|
| 84fbf31f75 | |||
| 7a9d4d49f4 | |||
| eff021b40f | |||
| dfb5304edb | |||
| b9c49d7212 | |||
| d98c60284b | |||
| 2cbdad181f | |||
| 33f736946d | |||
| 82a3f0ea8a | |||
| 4d35905481 |
316
.agent/workflows/no_pixelation_rule.md
Normal file
@@ -0,0 +1,316 @@
|
||||
---
|
||||
description: NO PIXELATION - Vector-Style Smooth Lines Enforcement
|
||||
---
|
||||
|
||||
# 🚫 NO PIXELATION RULE - Style 32 Smooth Lines
|
||||
|
||||
**CRITICAL:** Style 32 is **NOT** pixel art! It uses smooth, vector-style lines with ZERO pixelation.
|
||||
|
||||
---
|
||||
|
||||
## ✅ GOLD STANDARD REFERENCE
|
||||
|
||||
**MANDATORY REFERENCE:** `/references/main_characters/ana/master_reference_nobg.png`
|
||||
|
||||
**Why Ana is the GOLD STANDARD:**
|
||||
- ✅ **SMOOTH, CLEAN LINES** - No stair-stepping, no chunky pixels
|
||||
- ✅ **5px THICK OUTLINES** - Consistent, sharp, vector-quality
|
||||
- ✅ **HIGH-RES RENDERING** - Fluid, polished, film-quality
|
||||
- ✅ **FLAT CEL SHADING** - Clean color fills, no pixelation
|
||||
- ✅ **SHARP EDGES** - Like vector art, not retro pixel sprites
|
||||
|
||||
**THIS is Style 32. Everything else must match Ana's visual quality.**
|
||||
|
||||
---
|
||||
|
||||
## 🚫 WHAT IS FORBIDDEN (Pixel Art)
|
||||
|
||||
### **Pixel Art Characteristics (NEVER USE):**
|
||||
- ❌ **Stair-stepping edges** (jagged diagonal lines)
|
||||
- ❌ **Chunky, blocky appearance** (visible pixel grid)
|
||||
- ❌ **Low resolution** (< 64px for characters)
|
||||
- ❌ **Dithering patterns** (checkerboard shading)
|
||||
- ❌ **Limited color palette** (8-bit/16-bit restrictions)
|
||||
- ❌ **Retro game aesthetic** (NES, SNES, Game Boy style)
|
||||
|
||||
**Example of WRONG style:**
|
||||
```
|
||||
🔴 Pixelated character with visible 8x8 pixel blocks
|
||||
🔴 Diagonal lines look like stairs (█▄▀)
|
||||
🔴 Low resolution, chunky sprites
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ✅ REQUIRED STYLE (Vector-Smooth, High-Res)
|
||||
|
||||
### **Style 32 Smooth Characteristics:**
|
||||
|
||||
#### **1. SMOOTH, ANTI-ALIASED CURVES**
|
||||
- Outline curves are fluid (like vector art)
|
||||
- No jagged edges or stair-stepping
|
||||
- Diagonal lines are smooth gradients
|
||||
- Round shapes are perfectly circular
|
||||
|
||||
#### **2. HIGH-RESOLUTION RENDERING**
|
||||
- Characters: Minimum 64x64px (prefer 128x128px or higher)
|
||||
- NPCs: 64x64px to 160x160px
|
||||
- Buildings: 128x128px to 256x256px
|
||||
- Render at high resolution, downscale if needed (preserves smooth edges)
|
||||
|
||||
#### **3. THICK 5px OUTLINES (SMOOTH)**
|
||||
- 5px black outlines `#000000`
|
||||
- Outlines are vector-smooth (not pixel-chunky)
|
||||
- Consistent thickness around entire shape
|
||||
- Corners are rounded, not blocky
|
||||
|
||||
#### **4. FLAT CEL SHADING (CLEAN)**
|
||||
- Solid color fills (no dithering)
|
||||
- Sharp shadow boundaries (but smooth edges)
|
||||
- No pixel noise or grain texture
|
||||
- Colors are vibrant and solid
|
||||
|
||||
#### **5. FILM-QUALITY POLISH**
|
||||
- Looks like animation cel (Cult of the Lamb, Don't Starve)
|
||||
- NOT like retro game sprite (Mario, Zelda classic)
|
||||
- Professional, modern indie game quality
|
||||
- Fluid, dynamic, alive
|
||||
|
||||
---
|
||||
|
||||
## 🔍 VISUAL COMPARISON
|
||||
|
||||
### **✅ CORRECT (Ana Reference):**
|
||||
```
|
||||
Smooth outlines ───────────────► Vector-quality curves
|
||||
Thick 5px edges ───────────────► Consistent, clean
|
||||
High resolution ───────────────► 128px+, sharp details
|
||||
Flat shading ──────────────────► Solid colors, no grain
|
||||
Film quality ──────────────────► Professional, polished
|
||||
```
|
||||
|
||||
### **❌ WRONG (Pixel Art):**
|
||||
```
|
||||
Jagged edges ──────────────────► Stair-stepping (█▄▀)
|
||||
Thin/blocky outlines ──────────► Inconsistent thickness
|
||||
Low resolution ────────────────► < 32px, chunky
|
||||
Dithered shading ──────────────► Checkerboard patterns
|
||||
Retro aesthetic ───────────────► Old-school 8-bit look
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ GENERATION ENFORCEMENT
|
||||
|
||||
### **MANDATORY PROMPT ADDITIONS:**
|
||||
|
||||
**ALWAYS include these phrases:**
|
||||
```
|
||||
"SMOOTH vector-style lines (NOT pixel art),
|
||||
anti-aliased curves, high-resolution rendering,
|
||||
thick 5px black outlines with clean edges,
|
||||
matches Ana reference quality from /references/main_characters/ana/,
|
||||
film-quality polish, NO pixelation, NO stair-stepping,
|
||||
Cult of the Lamb aesthetic (smooth, not retro)."
|
||||
```
|
||||
|
||||
### **FORBIDDEN PHRASES (Never Use):**
|
||||
```
|
||||
❌ "pixel art"
|
||||
❌ "8-bit style"
|
||||
❌ "retro game sprite"
|
||||
❌ "low resolution"
|
||||
❌ "chunky pixels"
|
||||
❌ "Game Boy style"
|
||||
❌ "NES aesthetic"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔄 AUTO-REROLL TRIGGERS
|
||||
|
||||
**IMMEDIATE REROLL if generated image has:**
|
||||
|
||||
1. **Jagged diagonal lines** (stair-stepping visible)
|
||||
- Reroll with: "SMOOTH anti-aliased diagonals, NO stair-stepping"
|
||||
|
||||
2. **Blocky, chunky appearance** (pixel grid visible)
|
||||
- Reroll with: "High-resolution vector-smooth, NO chunky pixels"
|
||||
|
||||
3. **Thin or inconsistent outlines** (< 4px or varying thickness)
|
||||
- Reroll with: "Consistent 5px thick black outlines, smooth edges"
|
||||
|
||||
4. **Low resolution** (character < 64px or looks pixelated when zoomed)
|
||||
- Reroll with: "High-resolution 128px+, film-quality rendering"
|
||||
|
||||
5. **Dithering or grain texture** (checkerboard shading)
|
||||
- Reroll with: "Flat cel shading, solid colors, NO dithering"
|
||||
|
||||
**Maximum 3 rerolls. If still pixelated after 3 attempts, report to user.**
|
||||
|
||||
---
|
||||
|
||||
## 📋 PRE-GENERATION CHECKLIST
|
||||
|
||||
**BEFORE generating ANY asset:**
|
||||
|
||||
- [ ] Viewed Ana reference (`master_reference_nobg.png`)
|
||||
- [ ] Understood smooth line quality required
|
||||
- [ ] Prompt includes "SMOOTH vector-style lines (NOT pixel art)"
|
||||
- [ ] Prompt includes "matches Ana reference quality"
|
||||
- [ ] Prompt includes "NO pixelation, NO stair-stepping"
|
||||
- [ ] Prompt specifies high resolution (64px+ minimum)
|
||||
- [ ] Prompt specifies 5px thick smooth outlines
|
||||
- [ ] Avoided ALL pixel art keywords
|
||||
|
||||
---
|
||||
|
||||
## 📋 POST-GENERATION VERIFICATION
|
||||
|
||||
**AFTER generating asset:**
|
||||
|
||||
1. **Zoom In Test:**
|
||||
- Zoom to 200-400%
|
||||
- Check for jagged edges or stair-stepping
|
||||
- If visible → REJECT, reroll
|
||||
|
||||
2. **Outline Smoothness:**
|
||||
- Inspect outline curves
|
||||
- Must be fluid, not blocky
|
||||
- If blocky → REJECT, reroll
|
||||
|
||||
3. **Compare to Ana:**
|
||||
- Side-by-side with Ana reference
|
||||
- Match line quality?
|
||||
- Match outline thickness?
|
||||
- Match overall polish?
|
||||
- If NO → REJECT, reroll
|
||||
|
||||
4. **Resolution Check:**
|
||||
- Character sprites: 64px minimum (prefer 128px+)
|
||||
- Quality should survive zoom
|
||||
- If too low-res → REJECT, reroll
|
||||
|
||||
---
|
||||
|
||||
## 🎨 SPECIFIC ASSET TYPES
|
||||
|
||||
### **Characters & NPCs:**
|
||||
- **Resolution:** 128x128px to 160x160px (high-res)
|
||||
- **Style:** Match Ana exactly (smooth, polished)
|
||||
- **Reference:** Ana's skin texture, outline quality, shading style
|
||||
|
||||
### **Buildings:**
|
||||
- **Resolution:** 160x256px to 256x256px
|
||||
- **Style:** Smooth outlines, clean architecture
|
||||
- **NOT:** Minecraft-style blocky buildings
|
||||
|
||||
### **Crops & Plants:**
|
||||
- **Resolution:** 64x64px minimum
|
||||
- **Style:** Smooth leaves, organic curves
|
||||
- **NOT:** Square pixel leaves
|
||||
|
||||
### **UI Elements:**
|
||||
- **Resolution:** Vector-based or high-res PNG
|
||||
- **Style:** Sharp, modern, smooth
|
||||
- **NOT:** Retro pixelated UI
|
||||
|
||||
### **VFX & Particles:**
|
||||
- **Resolution:** 64x64px to 128x128px
|
||||
- **Style:** Smooth glows, fluid effects
|
||||
- **NOT:** Chunky pixel sparkles
|
||||
|
||||
---
|
||||
|
||||
## 🚨 EMERGENCY PIXELATION FIX
|
||||
|
||||
**If asset was already generated with pixelation:**
|
||||
|
||||
1. **Identify Issue:**
|
||||
- "This asset is pixelated (pixel art style)"
|
||||
- "Required: Smooth vector-style like Ana reference"
|
||||
|
||||
2. **Regenerate Immediately:**
|
||||
- Use corrected prompt with ALL smooth-line keywords
|
||||
- Reference Ana directly in prompt
|
||||
- Emphasize "NOT pixel art" explicitly
|
||||
|
||||
3. **Compare Before/After:**
|
||||
- Old (pixelated) vs New (smooth)
|
||||
- Verify improvement
|
||||
- Only accept if matches Ana quality
|
||||
|
||||
4. **Replace File:**
|
||||
- Delete pixelated version
|
||||
- Save smooth version with same filename
|
||||
- Update manifest
|
||||
|
||||
---
|
||||
|
||||
## 📊 QUALITY STANDARDS
|
||||
|
||||
### **MINIMUM ACCEPTABLE:**
|
||||
- Resolution: 64x64px for small assets
|
||||
- Outline: 5px thick, smooth edges
|
||||
- Shading: Flat cel, no dithering
|
||||
- Style: Matches Ana's polish level
|
||||
|
||||
### **PREFERRED:**
|
||||
- Resolution: 128x128px or higher
|
||||
- Outline: Perfect vector-smooth curves
|
||||
- Shading: Professional cel animation quality
|
||||
- Style: Indistinguishable from Ana reference
|
||||
|
||||
### **UNACCEPTABLE:**
|
||||
- ANY visible pixelation or stair-stepping
|
||||
- Chunky, blocky appearance
|
||||
- Retro game aesthetic
|
||||
- Low-resolution sprites (< 32px)
|
||||
- Dithered or grainy textures
|
||||
|
||||
---
|
||||
|
||||
## 🎯 STYLE 32 = SMOOTH, NOT PIXELS
|
||||
|
||||
**Remember:**
|
||||
- **Style 32** refers to the "32" in "Cult of the Lamb" inspiration (modern smooth indie)
|
||||
- **NOT** referring to "32-bit" (which could imply pixel art)
|
||||
- **ALWAYS** smooth, vector-quality, film-polished
|
||||
- **NEVER** chunky, pixelated, retro
|
||||
|
||||
---
|
||||
|
||||
## 📚 REFERENCE LIBRARY UPDATE
|
||||
|
||||
**Ana is now PRIMARY reference for line quality:**
|
||||
- Kai, Gronk, all NPCs must match Ana's smoothness
|
||||
- Buildings, crops, all assets use Ana's line quality
|
||||
- NO exceptions
|
||||
|
||||
**Secondary references (must also be smooth):**
|
||||
- Cult of the Lamb (game) - smooth indie style
|
||||
- Don't Starve (game) - vector-style characters
|
||||
- Hollow Knight (game) - clean, sharp lines
|
||||
|
||||
**NOT references (these are pixel art):**
|
||||
- Stardew Valley - pixel art style
|
||||
- Terraria - pixel art style
|
||||
- Celeste - pixel art style
|
||||
|
||||
---
|
||||
|
||||
**ACTIVATION:** ALWAYS active (mandatory for ALL asset generation)
|
||||
**PRIORITY:** MAXIMUM - overrides everything
|
||||
**VERIFICATION:** Compare to Ana reference EVERY time
|
||||
|
||||
---
|
||||
|
||||
**🎯 SUMMARY:**
|
||||
|
||||
1. Ana = Gold Standard (smooth, vector-quality)
|
||||
2. NO pixel art, EVER
|
||||
3. Smooth lines, high-res, film-quality
|
||||
4. Auto-reroll if pixelated
|
||||
5. Compare to Ana every time
|
||||
|
||||
**EVERYTHING must look like Ana. No exceptions.**
|
||||
172
.agent/workflows/pixel_art_fix_protocol.md
Normal file
@@ -0,0 +1,172 @@
|
||||
# 🔒 PIXEL ART FIX PROTOCOL - Protect Good Assets
|
||||
|
||||
**Purpose:** Identify and replace ONLY pixelated images, protect already-smooth Style 32 assets.
|
||||
|
||||
---
|
||||
|
||||
## ✅ PROTECTED ASSETS (DO NOT TOUCH)
|
||||
|
||||
**These are LOCKED - already smooth Style 32:**
|
||||
|
||||
### **Main Characters:**
|
||||
- ✅ `/references/main_characters/ana/master_reference_nobg.png` - **GOLD STANDARD**
|
||||
- ✅ `/references/main_characters/ana/master_reference.png` - **GOLD STANDARD**
|
||||
|
||||
### **Test Assets:**
|
||||
- ✅ `/references/BIOME_CROP_TEST_SHEET.png` - **SMOOTH QUALITY CONFIRMED**
|
||||
|
||||
### **Any asset USER confirms is smooth:**
|
||||
- User will specify which assets are already good
|
||||
- These remain untouched
|
||||
|
||||
---
|
||||
|
||||
## 🔴 IDENTIFY PIXELATED ASSETS (Need Regeneration)
|
||||
|
||||
**Process:**
|
||||
1. User identifies which portraits/sprites are pixelated
|
||||
2. Create list of files needing regeneration
|
||||
3. Regenerate ONLY those files
|
||||
4. Replace old pixelated versions
|
||||
|
||||
---
|
||||
|
||||
## 📋 REGENERATION CHECKLIST
|
||||
|
||||
**For EACH pixelated asset identified:**
|
||||
|
||||
### **Step 1: Verify Old File Exists**
|
||||
```bash
|
||||
ls -la references/npcs/[npc_name]/master_reference.png
|
||||
```
|
||||
|
||||
### **Step 2: View Original (Note Details)**
|
||||
- Character name
|
||||
- Features (hair, clothes, piercings)
|
||||
- Pose/angle
|
||||
|
||||
### **Step 3: Generate Smooth Replacement**
|
||||
**Prompt Template:**
|
||||
```
|
||||
[Character Name] portrait. EXACT Style 32 matching Ana reference quality:
|
||||
SMOOTH vector-style lines (NOT pixel art),
|
||||
5px thick black outlines #000000,
|
||||
anti-aliased curves,
|
||||
high-resolution 256x256px rendering,
|
||||
flat cel shading,
|
||||
NO pixelation, NO stair-stepping, NO chunky pixels,
|
||||
[Character specific features: hair color, outfit, etc.],
|
||||
Film-quality polish, Cult of the Lamb aesthetic,
|
||||
Transparent background.
|
||||
```
|
||||
|
||||
### **Step 4: Verify Quality**
|
||||
- [ ] Smooth lines (no stair-stepping)
|
||||
- [ ] 5px black outlines
|
||||
- [ ] Matches Ana's smoothness level
|
||||
- [ ] High resolution
|
||||
- [ ] Vibrant colors
|
||||
|
||||
### **Step 5: Replace Old File**
|
||||
```bash
|
||||
# Backup old (optional)
|
||||
mv references/npcs/[npc]/master_reference.png references/npcs/[npc]/master_reference_OLD_PIXELATED.png
|
||||
|
||||
# Copy new smooth version
|
||||
cp ~/.gemini/.../[new_smooth_file].png references/npcs/[npc]/master_reference.png
|
||||
```
|
||||
|
||||
### **Step 6: Update Manifest**
|
||||
```bash
|
||||
python3 scripts/generate_asset_manifest.py
|
||||
git add -A
|
||||
git commit -m "Fixed pixelated [NPC name] portrait - replaced with smooth Style 32 version"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎯 BATCH REPLACEMENT WORKFLOW
|
||||
|
||||
### **Phase 1: Identification**
|
||||
**USER PROVIDES LIST of pixelated assets:**
|
||||
```
|
||||
Example:
|
||||
- ivan_kovac: PIXELATED ❌
|
||||
- kustos: PIXELATED ❌
|
||||
- tehnik: PIXELATED ❌
|
||||
- pek: SMOOTH ✅ (keep)
|
||||
- sivilja: SMOOTH ✅ (keep)
|
||||
```
|
||||
|
||||
### **Phase 2: Regeneration (Only Pixelated)**
|
||||
For each PIXELATED asset:
|
||||
1. View original
|
||||
2. Generate smooth replacement
|
||||
3. Verify quality
|
||||
4. Replace file
|
||||
5. Commit change
|
||||
|
||||
### **Phase 3: Confirmation**
|
||||
```
|
||||
Report to user:
|
||||
"Regenerated [X] pixelated portraits:
|
||||
- [NPC 1]: FIXED ✅
|
||||
- [NPC 2]: FIXED ✅
|
||||
- [NPC 3]: FIXED ✅
|
||||
|
||||
Protected [Y] already-smooth assets:
|
||||
- Ana: PROTECTED ✅
|
||||
- [Other smooth NPCs]: PROTECTED ✅
|
||||
|
||||
All pixelated images are now replaced with smooth Style 32 versions."
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚫 WHAT NOT TO DO
|
||||
|
||||
**NEVER:**
|
||||
- ❌ Regenerate Ana's smooth reference (it's the gold standard)
|
||||
- ❌ Regenerate test sheet (already smooth)
|
||||
- ❌ Blindly regenerate everything without checking
|
||||
- ❌ Replace smooth assets with new versions (keep originals)
|
||||
- ❌ Generate without viewing original first
|
||||
|
||||
**ALWAYS:**
|
||||
- ✅ Ask user which assets are pixelated
|
||||
- ✅ Protect confirmed smooth assets
|
||||
- ✅ Only regenerate confirmed pixelated ones
|
||||
- ✅ Verify smoothness before replacing
|
||||
- ✅ Keep backups of old files (optional)
|
||||
|
||||
---
|
||||
|
||||
## 📋 CURRENT STATUS
|
||||
|
||||
**Awaiting USER input:**
|
||||
- Which NPCs are pixelated? (need regeneration)
|
||||
- Which NPCs are already smooth? (protect)
|
||||
- Which main characters need fixing? (Kai, Gronk?)
|
||||
|
||||
**Once USER provides list:**
|
||||
- Execute batch regeneration ONLY for pixelated assets
|
||||
- Protect all smooth assets
|
||||
- Confirm completion
|
||||
|
||||
---
|
||||
|
||||
## 🎯 QUALITY STANDARD
|
||||
|
||||
**Every regenerated asset must match:**
|
||||
- Ana's smoothness level (GOLD STANDARD)
|
||||
- Test sheet quality (CONFIRMED SMOOTH)
|
||||
- 5px outlines, no pixelation
|
||||
- Film-quality polish
|
||||
|
||||
**If regenerated asset is still pixelated:**
|
||||
- Auto-reroll (max 3 attempts)
|
||||
- Report to user if can't achieve smoothness
|
||||
|
||||
---
|
||||
|
||||
**AWAITING USER INPUT: Please specify which NPCs/characters are pixelated and need fixing.**
|
||||
|
After Width: | Height: | Size: 624 KiB |
|
After Width: | Height: | Size: 658 KiB |
|
After Width: | Height: | Size: 427 KiB |
|
After Width: | Height: | Size: 668 KiB |
|
After Width: | Height: | Size: 551 KiB |
|
After Width: | Height: | Size: 603 KiB |
|
After Width: | Height: | Size: 742 KiB |
|
After Width: | Height: | Size: 624 KiB |
|
After Width: | Height: | Size: 595 KiB |
|
After Width: | Height: | Size: 702 KiB |
|
After Width: | Height: | Size: 621 KiB |
|
After Width: | Height: | Size: 786 KiB |
121
docs/REMAINING_SYSTEMS_PLAN.md
Normal file
@@ -0,0 +1,121 @@
|
||||
# 🎮 REMAINING SYSTEMS IMPLEMENTATION PLAN
|
||||
**Date:** 2026-01-05 18:44 CET
|
||||
**Status:** 2/9 systems complete, 7 remaining
|
||||
|
||||
---
|
||||
|
||||
## ✅ COMPLETED SYSTEMS (2/9)
|
||||
1. ✅ **TownRestorationLogic.js** - Full 14-building restoration system
|
||||
2. ✅ **MuseumEvolutionSystem.js** - 3-stage museum + artifact collection
|
||||
|
||||
---
|
||||
|
||||
## 🔴 REMAINING SYSTEMS (7/9)
|
||||
|
||||
### **PRIORITY 1: Combat & Survival**
|
||||
|
||||
#### **3. Zombie Scout Leveling System (1-20)**
|
||||
**File:** `src/systems/ZombieScoutLevelingSystem.js`
|
||||
**Features:**
|
||||
- XP gain from combat, exploration, digging
|
||||
- Level 1-20 progression
|
||||
- Stat increases per level
|
||||
- Visual level-up effects
|
||||
- Skill point unlocks
|
||||
|
||||
#### **4. Zombie Scout Skills**
|
||||
**File:** `src/systems/ZombieScoutSkills.js`
|
||||
**Features:**
|
||||
- Skill tree (digging, combat, utility)
|
||||
- Active skills (special attacks)
|
||||
- Passive bonuses
|
||||
- Skill point allocation
|
||||
- Visual skill effects
|
||||
|
||||
#### **5. Nomad Raider AI**
|
||||
**File:** `src/systems/NomadRaiderAI.js`
|
||||
**Features:**
|
||||
- Raider spawn logic
|
||||
- Pathfinding to farm
|
||||
- Combat AI
|
||||
- Loot stealing behavior
|
||||
- Difficulty scaling
|
||||
|
||||
#### **6. Farm Raid System**
|
||||
**File:** `src/systems/FarmRaidSystem.js`
|
||||
**Features:**
|
||||
- Raid triggers (fame, resources)
|
||||
- Wave spawning
|
||||
- Defense response
|
||||
- Damage to buildings/crops
|
||||
- Raid rewards (defending)
|
||||
|
||||
---
|
||||
|
||||
### **PRIORITY 2: Town Evolution**
|
||||
|
||||
#### **7. School Buff System**
|
||||
**File:** `src/systems/SchoolBuffSystem.js`
|
||||
**Features:**
|
||||
- Teacher NPC unlocks system
|
||||
- Skill learning (farming, combat)
|
||||
- Temporary buffs
|
||||
- Knowledge tree
|
||||
- Student progression
|
||||
|
||||
#### **8. NPC Settlement System (Magic Helpers)**
|
||||
**File:** `src/systems/NPCSettlementSystem.js`
|
||||
**Features:**
|
||||
- NPC auto-assistance
|
||||
- Task delegation
|
||||
- Worker efficiency
|
||||
- Happiness/loyalty
|
||||
- NPC housing
|
||||
|
||||
#### **9. City Gratitude Gift System**
|
||||
**File:** `src/systems/CityGratitudeSystem.js`
|
||||
**Features:**
|
||||
- Population milestones
|
||||
- Gift unlocks
|
||||
- Unique rewards
|
||||
- City reputation
|
||||
- Special equipment
|
||||
|
||||
---
|
||||
|
||||
## 📋 IMPLEMENTATION ORDER
|
||||
|
||||
**Batch 1 (Combat Priority):**
|
||||
1. ZombieScoutLevelingSystem.js
|
||||
2. ZombieScoutSkills.js
|
||||
3. NomadRaiderAI.js
|
||||
4. FarmRaidSystem.js
|
||||
|
||||
**Batch 2 (Town Evolution):**
|
||||
5. SchoolBuffSystem.js
|
||||
6. NPCSettlementSystem.js
|
||||
7. CityGratitudeSystem.js
|
||||
|
||||
---
|
||||
|
||||
## 🎯 ESTIMATED COMPLETION
|
||||
|
||||
**Per System:** ~20-30 minutes
|
||||
**Total Time:** ~2.5-3.5 hours
|
||||
**Current Time:** 18:44 CET
|
||||
**Est. Completion:** 21:30 CET (tonight)
|
||||
|
||||
---
|
||||
|
||||
## 📦 DELIVERABLES
|
||||
|
||||
Each system includes:
|
||||
- Full JavaScript implementation
|
||||
- Integration with existing systems
|
||||
- Visual feedback
|
||||
- Quest hooks
|
||||
- Save/load support
|
||||
|
||||
---
|
||||
|
||||
**STARTING IMPLEMENTATION NOW...**
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"activeFile": "assets/maps 🟣/novafarma_clean.tmx",
|
||||
"activeFile": "assets/maps 🟣/MINIMAL_TEMPLATE.tmx",
|
||||
"expandedProjectPaths": [
|
||||
"assets/maps"
|
||||
],
|
||||
@@ -24,13 +24,16 @@
|
||||
"scaleInDock": 1
|
||||
},
|
||||
"assets/maps 🟣/MINIMAL_TEMPLATE.tmx": {
|
||||
"scale": 0.5452604166666667,
|
||||
"selectedLayer": 0,
|
||||
"scale": 0.25,
|
||||
"selectedLayer": 2,
|
||||
"viewCenter": {
|
||||
"x": 625.3892444359537,
|
||||
"y": 465.8324577323527
|
||||
"x": 268,
|
||||
"y": 516
|
||||
}
|
||||
},
|
||||
"assets/maps 🟣/base_level1_tent_1767411185506.tsx": {
|
||||
"scaleInDock": 0.25
|
||||
},
|
||||
"assets/maps 🟣/fresh_workspace.tmx": {
|
||||
"scale": 0.23156249999999998,
|
||||
"selectedLayer": 1,
|
||||
@@ -70,6 +73,9 @@
|
||||
"assets/maps 🟣/novafarma_clean.tmx#crops_tomatoes": {
|
||||
"scaleInDock": 1
|
||||
},
|
||||
"assets/maps 🟣/teren_farmland_tilled_style32.tsx": {
|
||||
"scaleInDock": 1
|
||||
},
|
||||
"assets/maps/01_Ground.tsx": {
|
||||
"scaleInDock": 1
|
||||
},
|
||||
@@ -244,15 +250,14 @@
|
||||
},
|
||||
"last.externalTilesetPath": "/Users/davidkotnik/repos/novafarma/assets/maps",
|
||||
"openFiles": [
|
||||
"assets/maps 🟣/fresh_workspace.tmx",
|
||||
"assets/maps 🟣/novafarma_clean.tmx"
|
||||
"assets/maps 🟣/MINIMAL_TEMPLATE.tmx"
|
||||
],
|
||||
"project": "novafarma.tiled-project",
|
||||
"recentFiles": [
|
||||
"assets/maps 🟣/MINIMAL_TEMPLATE.tmx",
|
||||
"assets/maps 🟣/narava_rastline_grass_flowers_style32.tsx",
|
||||
"assets/maps 🟣/fresh_workspace.tmx",
|
||||
"assets/maps 🟣/novafarma_clean.tmx",
|
||||
"assets/maps 🟣/MINIMAL_TEMPLATE.tmx",
|
||||
"assets/maps/testni_travnik.tmx",
|
||||
"assets/maps/TownSquare.json",
|
||||
"assets/maps/NovaFarma.json",
|
||||
|
||||
430
references/BIOME_CROP_MASTER_SPEC.md
Normal file
@@ -0,0 +1,430 @@
|
||||
# 🌍🌾 BIOME & CROP MASTER REFERENCE
|
||||
|
||||
**Purpose:** Single master reference sheet showing seasonal terrain changes and crop growth cycles across all 4 seasons.
|
||||
|
||||
**File:** `BIOME_CROP_MASTER.jpg` (to be created)
|
||||
**Location:** `/references/BIOME_CROP_MASTER.jpg`
|
||||
|
||||
---
|
||||
|
||||
## 📐 MASTER SHEET LAYOUT
|
||||
|
||||
### **Sheet Dimensions:** 2048 x 2048px (high-resolution)
|
||||
|
||||
### **Grid Layout:**
|
||||
```
|
||||
┌─────────────────┬─────────────────┬─────────────────┬─────────────────┐
|
||||
│ 🌸 SPRING │ ☀️ SUMMER │ 🍂 AUTUMN │ ❄️ WINTER │
|
||||
│ (Pomlad) │ (Poletje) │ (Jesen) │ (Zima) │
|
||||
├─────────────────┼─────────────────┼─────────────────┼─────────────────┤
|
||||
│ TERRAIN SECTION │ TERRAIN SECTION │ TERRAIN SECTION │ TERRAIN SECTION │
|
||||
│ - Grass │ - Grass │ - Grass │ - Snow/Ice │
|
||||
│ - Soil │ - Soil │ - Soil │ - Frozen Soil │
|
||||
│ - Path │ - Path │ - Path │ - Icy Path │
|
||||
├─────────────────┼─────────────────┼─────────────────┼─────────────────┤
|
||||
│ WHEAT GROWTH │ WHEAT GROWTH │ WHEAT GROWTH │ WHEAT GROWTH │
|
||||
│ Stage 1-8 │ Stage 1-8 │ Stage 1-8 │ Stage 1-8 │
|
||||
│ (all stages) │ (all stages) │ (all stages) │ (all stages) │
|
||||
└─────────────────┴─────────────────┴─────────────────┴─────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🌍 PART 1: BIOME TERRAIN (Seasonal Changes)
|
||||
|
||||
### **🌸 SPRING COLUMN (Pomlad)**
|
||||
|
||||
**Grass:**
|
||||
- **Color:** `#90EE90` (Light Green) - Fresh, bright
|
||||
- **Texture:** Smooth Style 32, 5px black outlines
|
||||
- **Details:** New growth, vibrant, alive
|
||||
- **Flowers:** Small pink/yellow dots scattered
|
||||
|
||||
**Soil:**
|
||||
- **Color:** `#8B4513` (Saddle Brown) - Rich, moist
|
||||
- **Texture:** Tilled furrows visible (smooth lines)
|
||||
- **Details:** Fresh, ready for planting
|
||||
|
||||
**Path/Dirt:**
|
||||
- **Color:** `#D2B48C` (Tan) - Light brown
|
||||
- **Texture:** Smooth, slightly wet appearance
|
||||
|
||||
**Overall Mood:** Fresh, new life, vibrant greens
|
||||
|
||||
---
|
||||
|
||||
### **☀️ SUMMER COLUMN (Poletje)**
|
||||
|
||||
**Grass:**
|
||||
- **Color:** `#228B22` (Forest Green) - Deep, rich
|
||||
- **Texture:** Lush, full coverage
|
||||
- **Details:** Maximum growth, sun-kissed
|
||||
- **Flowers:** Full blooms, colorful
|
||||
|
||||
**Soil:**
|
||||
- **Color:** `#8B4513` (Saddle Brown) - Dry, warm
|
||||
- **Texture:** Compact, sun-baked
|
||||
- **Details:** Established crops growing
|
||||
|
||||
**Path/Dirt:**
|
||||
- **Color:** `#CD853F` (Peru) - Warmer brown
|
||||
- **Texture:** Dry, dusty appearance
|
||||
|
||||
**Overall Mood:** Hot, vibrant, peak growth
|
||||
|
||||
---
|
||||
|
||||
### **🍂 AUTUMN COLUMN (Jesen)**
|
||||
|
||||
**Grass:**
|
||||
- **Color:** `#DAA520` (Goldenrod) + `#FF8C00` (Dark Orange)
|
||||
- **Texture:** Mixed green/yellow/orange patches
|
||||
- **Details:** Dying grass, harvest colors
|
||||
- **Fallen Leaves:** Orange/red scattered on ground
|
||||
|
||||
**Soil:**
|
||||
- **Color:** `#8B4513` (Saddle Brown) - Cooling down
|
||||
- **Texture:** Loose, harvest-ready
|
||||
- **Details:** Post-harvest stubble
|
||||
|
||||
**Path/Dirt:**
|
||||
- **Color:** `#A0522D` (Sienna) - Rich brown
|
||||
- **Texture:** Crisp, dry autumn ground
|
||||
|
||||
**Overall Mood:** Warm tones, harvest time, transition
|
||||
|
||||
---
|
||||
|
||||
### **❄️ WINTER COLUMN (Zima)**
|
||||
|
||||
**Snow/Grass:**
|
||||
- **Color:** `#F0F8FF` (Alice Blue) - White snow
|
||||
- **Under-snow:** `#556B2F` (Dark Olive) - Dead grass patches
|
||||
- **Texture:** Snow drifts, smooth curves (NOT chunky pixels)
|
||||
- **Details:** Sparse brown grass poking through
|
||||
|
||||
**Frozen Soil:**
|
||||
- **Color:** `#708090` (Slate Gray) - Frozen hard
|
||||
- **Texture:** Icy, cracked surface (smooth Style 32)
|
||||
- **Details:** Frost patterns (simple, stylized)
|
||||
|
||||
**Icy Path:**
|
||||
- **Color:** `#B0E0E6` (Powder Blue) - Ice patches
|
||||
- **Texture:** Reflective, slippery look
|
||||
- **Details:** Snow footprints (if any)
|
||||
|
||||
**Overall Mood:** Cold, dormant, blue-gray tones
|
||||
|
||||
---
|
||||
|
||||
## 🌾 PART 2: WHEAT CROP GROWTH (8 Stages × 4 Seasons = 32 Sprites)
|
||||
|
||||
### **Layout per Season Column:**
|
||||
```
|
||||
Stage 1: Seed/Sprout
|
||||
Stage 2: Seedling
|
||||
Stage 3: Young Plant
|
||||
Stage 4: Vegetative
|
||||
Stage 5: Pre-Flowering
|
||||
Stage 6: Flowering
|
||||
Stage 7: Maturing
|
||||
Stage 8: Harvest Ready ✨
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### **SPRING WHEAT (Stages 1-8):**
|
||||
|
||||
**Stage 1 (Seed):**
|
||||
- Tilled soil, tiny green sprout (2px)
|
||||
- Color: `#90EE90` (Light Green)
|
||||
- Size: 8x8px visible portion
|
||||
|
||||
**Stage 2 (Seedling):**
|
||||
- 2 small leaves
|
||||
- Color: `#90EE90`
|
||||
- Size: 16x16px
|
||||
|
||||
**Stage 3 (Young):**
|
||||
- 4-6 blade leaves
|
||||
- Color: `#32CD32` (Lime)
|
||||
- Size: 24x24px
|
||||
|
||||
**Stage 4 (Vegetative):**
|
||||
- Bushy, many leaves
|
||||
- Color: `#228B22` (Forest Green)
|
||||
- Size: 32x32px
|
||||
|
||||
**Stage 5 (Pre-Flower):**
|
||||
- Tall stalks, beginning to shoot up
|
||||
- Color: `#228B22`
|
||||
- Size: 40x40px
|
||||
|
||||
**Stage 6 (Flowering):**
|
||||
- White flowers appearing on tips
|
||||
- Color: Green `#228B22` + white blooms
|
||||
- Size: 48x48px
|
||||
|
||||
**Stage 7 (Maturing):**
|
||||
- Light green grain forming
|
||||
- Color: `#9ACD32` (Yellow Green)
|
||||
- Size: 56x56px
|
||||
|
||||
**Stage 8 (Harvest):**
|
||||
- Golden grain, ready
|
||||
- Color: `#F0E68C` (Khaki) - early harvest
|
||||
- Size: 64x64px, sparkle ✨
|
||||
|
||||
---
|
||||
|
||||
### **SUMMER WHEAT (Stages 1-8):**
|
||||
|
||||
**Stages 1-4:** Same as Spring but slightly deeper greens
|
||||
- Use `#228B22` instead of lime earlier
|
||||
|
||||
**Stage 5-7:** Faster growth, more robust
|
||||
- Stalks thicker, darker green
|
||||
|
||||
**Stage 8 (Harvest):**
|
||||
- **FULL GOLDEN COLOR:** `#FFD700` (Gold)
|
||||
- Maximum size, full heads
|
||||
- 64x64px, bright sparkle ✨
|
||||
- **This is PRIME harvest time**
|
||||
|
||||
---
|
||||
|
||||
### **AUTUMN WHEAT (Stages 1-8):**
|
||||
|
||||
**Stages 1-3:** Slower growth, cooler colors
|
||||
- Light green with slight yellow tint
|
||||
|
||||
**Stages 4-6:** Struggling growth
|
||||
- Mix of green and early yellowing
|
||||
|
||||
**Stage 7-8 (Late Harvest):**
|
||||
- **Over-ripe:** `#8B4513` (Saddle Brown) - drying out
|
||||
- Stalks bent, seeds falling
|
||||
- Must harvest NOW or lose crop
|
||||
- Faded sparkle (amber/brown)
|
||||
|
||||
---
|
||||
|
||||
### **WINTER WHEAT (Stages 1-8):**
|
||||
|
||||
**ALL STAGES:**
|
||||
- **DORMANT or DEAD** (outdoor crops)
|
||||
- Snow covering plants
|
||||
- Brown/dead stalks visible
|
||||
- Color: `#8B4513` (brown) + `#F0F8FF` (snow)
|
||||
|
||||
**Exception: Greenhouse Wheat (optional note)**
|
||||
- Can grow indoors
|
||||
- Slower but still green
|
||||
- Artificial warmth allows growth
|
||||
|
||||
**Outdoor Winter Wheat:**
|
||||
- Stages 1-8: All show dead/frozen plants
|
||||
- NO harvest possible
|
||||
- Must plant in Spring
|
||||
|
||||
---
|
||||
|
||||
## 🎨 STYLE REQUIREMENTS (ALL ELEMENTS)
|
||||
|
||||
### **✅ MANDATORY:**
|
||||
- **Smooth vector-style lines** (matches Ana reference)
|
||||
- **5px thick black outlines** on ALL elements
|
||||
- **High-resolution rendering** (2048px total sheet)
|
||||
- **Flat cel shading** (no gradients except ground shadows)
|
||||
- **Vibrant seasonal colors** (not muted/realistic)
|
||||
- **Transparent background** OR white reference grid
|
||||
- **Cult of the Lamb aesthetic** (smooth, polished)
|
||||
|
||||
### **❌ FORBIDDEN:**
|
||||
- NO pixel art / stair-stepping
|
||||
- NO chunky blocks
|
||||
- NO low-resolution sprites
|
||||
- NO dithering/grain
|
||||
- NO realistic photo textures
|
||||
|
||||
---
|
||||
|
||||
## 📏 DETAILED SPECIFICATIONS
|
||||
|
||||
### **Individual Element Sizes:**
|
||||
|
||||
**Terrain Tiles (each season):**
|
||||
- **Grass tile:** 128x128px
|
||||
- **Soil tile:** 128x128px
|
||||
- **Path tile:** 128x128px
|
||||
- Show tileable edges (seamless repeat)
|
||||
|
||||
**Wheat Sprites (each stage, each season):**
|
||||
- **Stage 1:** 16x16px (tiny)
|
||||
- **Stage 2:** 24x24px
|
||||
- **Stage 3:** 32x32px
|
||||
- **Stage 4:** 40x40px
|
||||
- **Stage 5:** 48x48px
|
||||
- **Stage 6:** 56x56px
|
||||
- **Stage 7:** 60x60px
|
||||
- **Stage 8:** 64x64px (maximum)
|
||||
|
||||
**Spacing:**
|
||||
- 20px padding between elements
|
||||
- Clear labels for each season/stage
|
||||
- Grid lines (thin, light gray) for organization
|
||||
|
||||
---
|
||||
|
||||
## 🏷️ LABELS & ANNOTATIONS
|
||||
|
||||
### **Season Headers (top of each column):**
|
||||
```
|
||||
🌸 SPRING (Pomlad)
|
||||
Fresh Growth · Bright Greens · New Life
|
||||
|
||||
☀️ SUMMER (Poletje)
|
||||
Peak Growth · Rich Colors · Heat
|
||||
|
||||
🍂 AUTUMN (Jesen)
|
||||
Harvest Time · Warm Tones · Transition
|
||||
|
||||
❄️ WINTER (Zima)
|
||||
Dormancy · Cold Blues · Snow
|
||||
```
|
||||
|
||||
### **Wheat Stage Labels (left side):**
|
||||
```
|
||||
Stage 1: Seed/Sprout (0-10%)
|
||||
Stage 2: Seedling (10-20%)
|
||||
Stage 3: Young (20-40%)
|
||||
Stage 4: Vegetative (40-60%)
|
||||
Stage 5: Pre-Flower (60-70%)
|
||||
Stage 6: Flowering (70-85%)
|
||||
Stage 7: Maturing (85-95%)
|
||||
Stage 8: Harvest ✨ (95-100%)
|
||||
```
|
||||
|
||||
### **Color Code Key (bottom of sheet):**
|
||||
```
|
||||
GRASS COLORS:
|
||||
Spring #90EE90 → Summer #228B22 → Autumn #DAA520 → Winter #F0F8FF
|
||||
|
||||
WHEAT COLORS:
|
||||
Young #32CD32 → Mature #228B22 → Flowering #9ACD32 → Harvest #FFD700
|
||||
|
||||
SOIL COLORS:
|
||||
Spring/Summer #8B4513 → Autumn #A0522D → Winter #708090
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚀 USAGE INSTRUCTIONS
|
||||
|
||||
### **When generating ANY biome terrain:**
|
||||
1. Open `BIOME_CROP_MASTER.jpg`
|
||||
2. Identify season (Spring/Summer/Autumn/Winter)
|
||||
3. Extract EXACT grass/soil colors from reference
|
||||
4. Use exact hex codes in prompt
|
||||
5. Match smoothness/style to master reference
|
||||
|
||||
### **When generating ANY crop:**
|
||||
1. Open `BIOME_CROP_MASTER.jpg`
|
||||
2. Identify growth stage (1-8)
|
||||
3. Identify season
|
||||
4. Find corresponding wheat sprite in grid
|
||||
5. Match size, color, style exactly
|
||||
6. Apply same logic to new crop (tomato, carrot, etc.)
|
||||
|
||||
### **Color Extraction:**
|
||||
- Use eyedropper tool on reference
|
||||
- Copy exact hex codes
|
||||
- Include in generation prompt
|
||||
- NO guessing colors
|
||||
|
||||
---
|
||||
|
||||
## ✅ VERIFICATION CHECKLIST
|
||||
|
||||
Before approving BIOME_CROP_MASTER.jpg:
|
||||
|
||||
**Overall:**
|
||||
- [ ] 2048x2048px high-resolution
|
||||
- [ ] 4 clear season columns
|
||||
- [ ] All terrain types shown per season
|
||||
- [ ] All 8 wheat stages per season (32 total sprites)
|
||||
- [ ] Smooth Style 32 lines (matches Ana)
|
||||
- [ ] 5px black outlines on everything
|
||||
- [ ] Clear labels and color key
|
||||
- [ ] Professional, polished appearance
|
||||
|
||||
**Spring Column:**
|
||||
- [ ] Light green grass (#90EE90)
|
||||
- [ ] Fresh soil (#8B4513)
|
||||
- [ ] Light tan path (#D2B48C)
|
||||
- [ ] Wheat stages 1-8 in spring colors
|
||||
|
||||
**Summer Column:**
|
||||
- [ ] Dark green grass (#228B22)
|
||||
- [ ] Dry soil (#8B4513)
|
||||
- [ ] Warmer path (#CD853F)
|
||||
- [ ] Wheat stages 1-8, golden harvest (#FFD700)
|
||||
|
||||
**Autumn Column:**
|
||||
- [ ] Orange/yellow grass (#DAA520)
|
||||
- [ ] Rich soil (#A0522D)
|
||||
- [ ] Autumn path (#A0522D)
|
||||
- [ ] Wheat stages 1-8, over-ripe (#8B4513)
|
||||
|
||||
**Winter Column:**
|
||||
- [ ] Snow/ice (#F0F8FF)
|
||||
- [ ] Frozen soil (#708090)
|
||||
- [ ] Icy path (#B0E0E6)
|
||||
- [ ] Wheat stages 1-8, dead/dormant
|
||||
|
||||
**Style:**
|
||||
- [ ] NO pixelation anywhere
|
||||
- [ ] Smooth curves (vector-quality)
|
||||
- [ ] Consistent outline thickness (5px)
|
||||
- [ ] Vibrant colors (not muted)
|
||||
- [ ] Matches Ana reference quality
|
||||
|
||||
---
|
||||
|
||||
## 🎯 CRITICAL NOTES
|
||||
|
||||
### **This reference will be used for:**
|
||||
- ALL 20 biomes (terrain base)
|
||||
- ALL crops (growth pattern template)
|
||||
- ALL seasonal variations (color reference)
|
||||
- ALL terrain tiles (style guide)
|
||||
|
||||
### **Every vegetation asset MUST:**
|
||||
1. Check this master reference FIRST
|
||||
2. Match seasonal colors exactly
|
||||
3. Match growth stage size/detail
|
||||
4. Match smooth line quality
|
||||
5. Use exact hex codes provided
|
||||
|
||||
### **This is THE definitive seasonal & growth reference.**
|
||||
- No guessing seasonal colors
|
||||
- No inventing growth stages
|
||||
- No style deviations
|
||||
- Everything checks against this master
|
||||
|
||||
---
|
||||
|
||||
**STATUS:** Specification complete, awaiting image creation
|
||||
**PRIORITY:** CRITICAL - needed before generating any more vegetation/terrain
|
||||
**FILE:** `/references/BIOME_CROP_MASTER.jpg` (to be generated)
|
||||
|
||||
---
|
||||
|
||||
**Once this master reference exists, ALL future biome/crop generation becomes:**
|
||||
1. Open master reference
|
||||
2. Find relevant season + stage
|
||||
3. Copy exact colors/style
|
||||
4. Generate matching asset
|
||||
5. Verify against master
|
||||
|
||||
**No more inconsistency. One source of truth.** 🎯
|
||||
BIN
references/BIOME_CROP_TEST_SHEET.png
Normal file
|
After Width: | Height: | Size: 784 KiB |
293
references/DEFINITIVE_IMAGE_STANDARD.md
Normal file
@@ -0,0 +1,293 @@
|
||||
# 🎯 DEFINITIVNI STANDARD ZA SLIKE - Style 32
|
||||
|
||||
**Datum:** 2026-01-05
|
||||
**Status:** APPROVED by user - ta kvaliteta je točno prava!
|
||||
|
||||
---
|
||||
|
||||
## ✅ USPEŠNI PRIMERI (Uporabi kot referenco)
|
||||
|
||||
### **GOLD STANDARD NPCs (Generated 2026-01-05):**
|
||||
- `/references/npcs/arborist/master_reference.png` ✅
|
||||
- `/references/npcs/kustos/master_reference.png` ✅
|
||||
- `/references/npcs/mayor/master_reference.png` ✅
|
||||
- `/references/npcs/miro_pravnik/master_reference.png` ✅
|
||||
- `/references/npcs/pek/master_reference.png` ✅
|
||||
- `/references/npcs/sivilja/master_reference.png` ✅
|
||||
- `/references/npcs/teacher/master_reference.png` ✅
|
||||
- `/references/npcs/tehnik/master_reference.png` ✅
|
||||
|
||||
### **Original Ana Reference:**
|
||||
- `/references/main_characters/ana/master_reference_nobg.png` ✅
|
||||
|
||||
### **Test Quality Reference:**
|
||||
- `/references/BIOME_CROP_TEST_SHEET.png` ✅
|
||||
|
||||
---
|
||||
|
||||
## 📐 EXACT SPECIFICATIONS (Ta kvaliteta!)
|
||||
|
||||
### **1. OUTLINES (Črne obrobe):**
|
||||
```
|
||||
Debelina: 5px (thick, consistent)
|
||||
Barva: #000000 (pure black)
|
||||
Stil: Smooth anti-aliased (NO stair-stepping)
|
||||
Koti: Rounded (not blocky)
|
||||
```
|
||||
|
||||
### **2. SHADING (Senčenje):**
|
||||
```
|
||||
Tip: Flat cel shading (cartoon style)
|
||||
Prehodi: Sharp boundaries (ne mehko)
|
||||
Barve: Solid fills (no gradients except shadows)
|
||||
Tekstura: Clean (no grain, no dithering)
|
||||
```
|
||||
|
||||
### **3. PROPORTIONS (Razmerja):**
|
||||
```
|
||||
Stil: Chibi 1:1 (glava = telo)
|
||||
Velikost: 256x256px (high resolution)
|
||||
Oči: Large, expressive
|
||||
Telo: Compact, cute
|
||||
```
|
||||
|
||||
### **4. COLORS (Barve):**
|
||||
```
|
||||
Lasje: Vibrant (neon pink, green, blue, purple, orange)
|
||||
Koža: Wheat #F5DEB3, Tan #D2B48C
|
||||
Oblačila: Punk colors (dark + bright accents)
|
||||
Fon: Transparent (100% prosojno)
|
||||
```
|
||||
|
||||
### **5. STYLE QUALITY:**
|
||||
```
|
||||
Linij: SMOOTH vector-style (NOT pixel art)
|
||||
Robovi: Anti-aliased curves (gladki)
|
||||
Ločljivost: High-res (256px minimum)
|
||||
Finish: Film-quality polish (profesionalno)
|
||||
Aesthetic: Cult of the Lamb inspired
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎨 PROMPT TEMPLATE (Vsak nov NPC)
|
||||
|
||||
**Uporabi TOČNO TO strukturo:**
|
||||
|
||||
```
|
||||
[Character Name] [profession] portrait.
|
||||
|
||||
EXACT smooth quality matching approved NPCs (Kustos, Mayor, Pek style):
|
||||
- THICK black outlines (5px) #000000
|
||||
- Clean cel shading (flat, sharp boundaries)
|
||||
- Chibi 1:1 proportions (head = body)
|
||||
- Smooth anti-aliased curves (NO pixel art, NO stair-stepping)
|
||||
|
||||
Character details:
|
||||
- [Hair color] colored hair [or dreadlocks]
|
||||
- [Specific outfit/tools for profession]
|
||||
- [Distinguishing features]
|
||||
- 2-3 piercings (nose, ear, face)
|
||||
- [Expression type] expression
|
||||
- Post-apocalyptic punk aesthetic
|
||||
|
||||
Technical specs:
|
||||
- 256x256px high-resolution rendering
|
||||
- Transparent background
|
||||
- Vibrant colors (not muted)
|
||||
- Professional film-quality polish
|
||||
- Cult of the Lamb aesthetic
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📋 QUALITY CHECKLIST (Pred odobritvijo)
|
||||
|
||||
**VSE mora biti ✅:**
|
||||
|
||||
### **Visual Quality:**
|
||||
- [ ] Smooth lines (NO jagged edges)
|
||||
- [ ] Thick 5px black outlines (consistent)
|
||||
- [ ] Clean cel shading (NO soft gradients)
|
||||
- [ ] Vibrant colors (NOT muted/realistic)
|
||||
- [ ] High resolution (256px+)
|
||||
- [ ] Transparent background (NO green screen)
|
||||
|
||||
### **Style Match:**
|
||||
- [ ] Matches approved NPCs (Kustos, Mayor, etc.)
|
||||
- [ ] Chibi proportions (cute, 1:1)
|
||||
- [ ] Punk aesthetic (piercings, colored hair)
|
||||
- [ ] Professional polish (film-quality)
|
||||
- [ ] Cult of the Lamb vibe
|
||||
|
||||
### **Character Details:**
|
||||
- [ ] Colored hair OR dreadlocks (NO natural brown/black)
|
||||
- [ ] 2-3 piercings visible
|
||||
- [ ] Profession-appropriate outfit/tools
|
||||
- [ ] Post-apocalyptic wear (torn, patched)
|
||||
- [ ] Expressive face
|
||||
|
||||
### **Technical:**
|
||||
- [ ] File size reasonable (< 2MB)
|
||||
- [ ] PNG format with alpha channel
|
||||
- [ ] 256x256px dimensions
|
||||
- [ ] No compression artifacts
|
||||
- [ ] Clean transparent edges
|
||||
|
||||
---
|
||||
|
||||
## 🚫 FORBIDDEN (NIKOLI ne uporabljaj)
|
||||
|
||||
**Style Errors:**
|
||||
- ❌ Pixel art (chunky blocks, stair-stepping)
|
||||
- ❌ Low resolution (< 128px)
|
||||
- ❌ Soft gradients (only flat cel shading)
|
||||
- ❌ Thin outlines (< 3px)
|
||||
- ❌ Realistic shading (photographic)
|
||||
- ❌ Green/colored backgrounds (must be transparent)
|
||||
|
||||
**Character Errors:**
|
||||
- ❌ Natural hair colors (brown, black without dreads)
|
||||
- ❌ Clean corporate look (must be punk)
|
||||
- ❌ No piercings
|
||||
- ❌ Muted colors
|
||||
- ❌ Realistic proportions (not chibi)
|
||||
|
||||
**Technical Errors:**
|
||||
- ❌ Compression artifacts (save as PNG)
|
||||
- ❌ Non-transparent background
|
||||
- ❌ Inconsistent outline thickness
|
||||
- ❌ Blurry edges
|
||||
|
||||
---
|
||||
|
||||
## ✅ GENERATION WORKFLOW
|
||||
|
||||
### **Step 1: Check References**
|
||||
```bash
|
||||
# View approved examples first
|
||||
open references/npcs/kustos/master_reference.png
|
||||
open references/npcs/mayor/master_reference.png
|
||||
open references/npcs/pek/master_reference.png
|
||||
```
|
||||
|
||||
### **Step 2: Use Exact Prompt Template**
|
||||
- Copy template from above
|
||||
- Fill in character-specific details
|
||||
- Include ALL technical specifications
|
||||
- Emphasize "matching approved NPCs"
|
||||
|
||||
### **Step 3: Generate**
|
||||
- Use 256x256px minimum
|
||||
- Request transparent background explicitly
|
||||
- Specify smooth anti-aliased lines
|
||||
- Reference approved examples in prompt
|
||||
|
||||
### **Step 4: Verify Quality**
|
||||
```
|
||||
Compare side-by-side with approved NPCs:
|
||||
- Line smoothness matches? ✅
|
||||
- Outline thickness matches? ✅
|
||||
- Color vibrancy matches? ✅
|
||||
- Chibi proportions match? ✅
|
||||
- Overall polish matches? ✅
|
||||
```
|
||||
|
||||
### **Step 5: Save & Commit**
|
||||
```bash
|
||||
cp [generated_file].png references/npcs/[npc_name]/master_reference.png
|
||||
python3 scripts/generate_asset_manifest.py
|
||||
git add -A
|
||||
git commit -m "Added [NPC name] portrait - SMOOTH Style 32 matching approved quality"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎯 SUCCESS CRITERIA
|
||||
|
||||
**Slika je uspešna, če:**
|
||||
|
||||
1. **Uporabnik pove:** "To so pa že top slike!" ✅
|
||||
2. **Matches test image** (uploaded chibi reference)
|
||||
3. **Matches Ana's smoothness** (gold standard)
|
||||
4. **Matches approved 8 NPCs** (Kustos, Mayor, etc.)
|
||||
5. **NO pixelation** when zoomed 200-400%
|
||||
6. **Professional quality** (like commercial indie game)
|
||||
|
||||
**Če katerikoli od teh ni izpolnjen → reroll malo!**
|
||||
|
||||
---
|
||||
|
||||
## 📊 BATCH GENERATION
|
||||
|
||||
**Za množično generiranje (npr. 20 NPCjev):**
|
||||
|
||||
1. **Prepare list** with character names + professions
|
||||
2. **Use SAME prompt template** for all
|
||||
3. **Generate in batches** of 4-5
|
||||
4. **Verify each batch** before continuing
|
||||
5. **Replace files** systematically
|
||||
6. **Update manifest** after all done
|
||||
7. **Single commit** with all changes
|
||||
|
||||
**Example batch commit:**
|
||||
```
|
||||
"Regenerated 20 NPCs in SMOOTH Style 32:
|
||||
[list names]. Matching approved quality standard.
|
||||
Thick outlines, cel shading, chibi proportions."
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔄 IF QUALITY DROPS
|
||||
|
||||
**Simptomi:**
|
||||
- Pixelation appears
|
||||
- Outlines become thin
|
||||
- Colors become muted
|
||||
- Proportions change
|
||||
|
||||
**Fix:**
|
||||
1. **Stop immediately**
|
||||
2. **Re-read this document**
|
||||
3. **View approved references again**
|
||||
4. **Adjust prompt** to be more explicit
|
||||
5. **Add "matching [approved NPC name]"** to prompt
|
||||
6. **Regenerate** with corrected prompt
|
||||
7. **Verify** before replacing files
|
||||
|
||||
---
|
||||
|
||||
## 📚 REFERENCE HIERARCHY
|
||||
|
||||
**Vedno preveri v tem vrstnem redu:**
|
||||
|
||||
1. **Approved 8 NPCs** (2026-01-05) - DEFINITIVE STANDARD
|
||||
2. **Ana reference** (original gold standard)
|
||||
3. **Test sheet** (quality benchmark)
|
||||
4. **COLOR_MASTER.md** (exact hex codes)
|
||||
5. **This document** (specifications)
|
||||
|
||||
**Nikoli ne improvizirati - vedno se sklicuj na reference!**
|
||||
|
||||
---
|
||||
|
||||
## 🎯 FINAL REMINDER
|
||||
|
||||
**Ta kvaliteta (Kustos, Mayor, Pek, etc.) je TOČNO PRAVA.**
|
||||
|
||||
**Ne spreminjaj:**
|
||||
- Outline thickness
|
||||
- Shading style
|
||||
- Color vibrancy
|
||||
- Smoothness level
|
||||
- Chibi proportions
|
||||
|
||||
**Samo repliciraj to kvaliteto za vse nove NPCje!**
|
||||
|
||||
---
|
||||
|
||||
**APPROVED STANDARD - Use this for ALL future NPC generation!**
|
||||
|
||||
**Datum odobritve:** 2026-01-05 18:28
|
||||
**Status:** LOCKED ✅
|
||||
|
Before Width: | Height: | Size: 574 KiB After Width: | Height: | Size: 560 KiB |
BIN
references/npcs/ivan_kovac/master_reference.png
Normal file
|
After Width: | Height: | Size: 427 KiB |
|
Before Width: | Height: | Size: 698 KiB After Width: | Height: | Size: 686 KiB |
|
Before Width: | Height: | Size: 368 KiB After Width: | Height: | Size: 646 KiB |
|
Before Width: | Height: | Size: 510 KiB After Width: | Height: | Size: 689 KiB |
|
Before Width: | Height: | Size: 539 KiB After Width: | Height: | Size: 672 KiB |
|
Before Width: | Height: | Size: 574 KiB After Width: | Height: | Size: 705 KiB |
|
Before Width: | Height: | Size: 538 KiB After Width: | Height: | Size: 625 KiB |
|
Before Width: | Height: | Size: 604 KiB After Width: | Height: | Size: 649 KiB |
57
references/trees/dead/README.md
Normal file
@@ -0,0 +1,57 @@
|
||||
# 💀 Dead Tree References (Universal)
|
||||
|
||||
**Tree Type:** Dead/Withered - Any biome
|
||||
**Seasonal Changes:** NO (already dead)
|
||||
|
||||
---
|
||||
|
||||
## Required References:
|
||||
|
||||
### **Master References Needed:**
|
||||
- `dead_tree_default.png` - Standard dead tree
|
||||
- Optional: `dead_tree_burnt.png` - Charred (volcanic biome)
|
||||
|
||||
### **Size Standards:**
|
||||
- Small Dead Tree: 96x96px
|
||||
- Medium Dead Tree: 160x160px
|
||||
- Large Dead Tree: 192x192px
|
||||
|
||||
---
|
||||
|
||||
## Visual Specifications:
|
||||
|
||||
**Trunk:**
|
||||
- Color: `#696969` (Dim Gray)
|
||||
- Texture: Weathered, cracked
|
||||
- Features: Holes, missing bark pieces
|
||||
|
||||
**Branches:**
|
||||
- Bare (NO leaves)
|
||||
- Broken/jagged ends
|
||||
- Tilted/bent (showing decay)
|
||||
- Some branches snapped off
|
||||
|
||||
**Highlights:**
|
||||
- Color: `#D3D3D3` (Light Gray) - sun-bleached
|
||||
- Shadows: `#2F4F4F` (Dark Slate Gray)
|
||||
|
||||
**Optional (Burnt Variant):**
|
||||
- Color: `#2F4F4F` (Dark Slate) + black char
|
||||
- Charred appearance
|
||||
- For volcanic/fire biomes
|
||||
|
||||
---
|
||||
|
||||
## Style Requirements:
|
||||
|
||||
✅ **MUST HAVE:**
|
||||
- SMOOTH vector-style lines (NOT pixel art)
|
||||
- THICK 5px black outlines `#000000`
|
||||
- Flat cel shading
|
||||
- Weathered, spooky appearance
|
||||
- Transparent background
|
||||
|
||||
❌ **NEVER:**
|
||||
- Any leaves/greenery
|
||||
- Healthy-looking bark
|
||||
- Pixelated
|
||||
60
references/trees/oak/README.md
Normal file
@@ -0,0 +1,60 @@
|
||||
# 🌲 Oak Tree References (Deciduous)
|
||||
|
||||
**Tree Type:** Oak - Broad-leafed deciduous tree
|
||||
**Seasonal Changes:** YES (4 seasons)
|
||||
|
||||
---
|
||||
|
||||
## Required References:
|
||||
|
||||
### **Master References Needed:**
|
||||
- `oak_spring.png` - Light green leaves, fresh growth
|
||||
- `oak_summer.png` - Dark green full canopy
|
||||
- `oak_autumn.png` - Orange/red/yellow leaves
|
||||
- `oak_winter.png` - Bare branches, snow
|
||||
|
||||
### **Size Standards:**
|
||||
- Small Oak (sapling): 96x96px
|
||||
- Medium Oak: 160x160px
|
||||
- Large Oak (ancient): 192x192px or 256x256px
|
||||
|
||||
---
|
||||
|
||||
## Visual Specifications:
|
||||
|
||||
**Trunk:**
|
||||
- Color: `#8B4513` (Saddle Brown)
|
||||
- Texture: Simplified bark lines (3-5 vertical)
|
||||
- Style: Thick, chibi-proportioned
|
||||
|
||||
**Leaves (Summer):**
|
||||
- Color: `#228B22` (Forest Green)
|
||||
- Style: Leaf clusters (NOT individual leaves)
|
||||
- Clusters: 5-10 leaves per shape
|
||||
|
||||
**Autumn Colors:**
|
||||
- Orange: `#FF8C00`
|
||||
- Gold: `#FFD700`
|
||||
- Red: `#FF4500`
|
||||
|
||||
**Winter:**
|
||||
- Bare branches visible
|
||||
- Snow on top: `#F0F8FF` (Alice Blue)
|
||||
- Optional icicles
|
||||
|
||||
---
|
||||
|
||||
## Style Requirements:
|
||||
|
||||
✅ **MUST HAVE:**
|
||||
- SMOOTH vector-style lines (NOT pixel art)
|
||||
- THICK 5px black outlines `#000000`
|
||||
- Flat cel shading
|
||||
- Chibi cute proportions
|
||||
- Transparent background
|
||||
|
||||
❌ **NEVER:**
|
||||
- Pixelated/chunky
|
||||
- Individual leaf sprites
|
||||
- Realistic textures
|
||||
- Thin outlines
|
||||
52
references/trees/palm/README.md
Normal file
@@ -0,0 +1,52 @@
|
||||
# 🌴 Palm Tree References (Tropical)
|
||||
|
||||
**Tree Type:** Palm - Tropical tree
|
||||
**Seasonal Changes:** MINIMAL (tropical climate)
|
||||
|
||||
---
|
||||
|
||||
## Required References:
|
||||
|
||||
### **Master References Needed:**
|
||||
- `palm_default.png` - Standard palm tree
|
||||
- Optional: `palm_coconuts.png` - With fruit
|
||||
|
||||
### **Size Standards:**
|
||||
- Small Palm: 96x96px
|
||||
- Medium Palm: 160x160px
|
||||
- Large Palm: 192x192px
|
||||
|
||||
---
|
||||
|
||||
## Visual Specifications:
|
||||
|
||||
**Trunk:**
|
||||
- Color: `#CD853F` (Peru)
|
||||
- Texture: Curved/bent (characteristic palm shape)
|
||||
- Style: Textured bark rings (simplified)
|
||||
|
||||
**Fronds (Leaves):**
|
||||
- Color: `#228B22` (Forest Green)
|
||||
- Count: 5-7 large fronds at top
|
||||
- Style: Fan-shaped, spreading outward
|
||||
|
||||
**Optional Coconuts:**
|
||||
- Color: `#8B4513` (Saddle Brown)
|
||||
- Size: Small clusters
|
||||
- Position: Below frond crown
|
||||
|
||||
---
|
||||
|
||||
## Style Requirements:
|
||||
|
||||
✅ **MUST HAVE:**
|
||||
- SMOOTH vector-style lines
|
||||
- THICK 5px black outlines `#000000`
|
||||
- Flat cel shading
|
||||
- Curved trunk (NOT straight like pine)
|
||||
- Transparent background
|
||||
|
||||
❌ **NEVER:**
|
||||
- Pixelated
|
||||
- Individual leaves
|
||||
- Straight vertical trunk
|
||||
52
references/trees/pine/README.md
Normal file
@@ -0,0 +1,52 @@
|
||||
# 🌲 Pine Tree References (Evergreen)
|
||||
|
||||
**Tree Type:** Pine - Coniferous evergreen
|
||||
**Seasonal Changes:** NO (stays green, adds snow in winter)
|
||||
|
||||
---
|
||||
|
||||
## Required References:
|
||||
|
||||
### **Master References Needed:**
|
||||
- `pine_default.png` - Standard green pine
|
||||
- `pine_winter.png` - Same tree with snow
|
||||
|
||||
### **Size Standards:**
|
||||
- Small Pine: 96x96px
|
||||
- Medium Pine: 160x192px
|
||||
- Tall Pine: 192x256px (vertical)
|
||||
|
||||
---
|
||||
|
||||
## Visual Specifications:
|
||||
|
||||
**Trunk:**
|
||||
- Color: `#8B4513` (Saddle Brown)
|
||||
- Style: Straight, vertical
|
||||
- Shape: Conical taper
|
||||
|
||||
**Needles:**
|
||||
- Color: `#2E8B57` (Sea Green) - STAYS GREEN ALL YEAR
|
||||
- Style: Triangular tiers/layers
|
||||
- NOT individual needles - simplified clusters
|
||||
|
||||
**Winter Addition:**
|
||||
- Snow accumulation on branches
|
||||
- Snow color: `#F0F8FF` (Alice Blue)
|
||||
- Heavier, snow-laden look
|
||||
|
||||
---
|
||||
|
||||
## Style Requirements:
|
||||
|
||||
✅ **MUST HAVE:**
|
||||
- SMOOTH vector-style lines
|
||||
- THICK 5px black outlines `#000000`
|
||||
- Conical/triangular silhouette
|
||||
- Layered branch tiers
|
||||
- Transparent background
|
||||
|
||||
❌ **NEVER:**
|
||||
- Pixelated
|
||||
- Realistic pine needles
|
||||
- Changing needle color (always green!)
|
||||
344
src/systems/MuseumEvolutionSystem.js
Normal file
@@ -0,0 +1,344 @@
|
||||
/**
|
||||
* MUSEUM EVOLUTION SYSTEM
|
||||
* 3-stage museum restoration with artifact collection
|
||||
* Integrates with Kustos NPC and quest system
|
||||
*/
|
||||
|
||||
export class MuseumEvolutionSystem {
|
||||
constructor(scene) {
|
||||
this.scene = scene;
|
||||
|
||||
// Museum evolution stages
|
||||
this.currentStage = 0; // 0 = ruined, 1 = partial, 2 = advanced, 3 = complete
|
||||
|
||||
// Artifact collection
|
||||
this.artifacts = new Map(); // artifactId → artifactData
|
||||
this.collectedArtifacts = new Set();
|
||||
|
||||
// Album tracking
|
||||
this.albumCategories = new Map();
|
||||
|
||||
this.init();
|
||||
}
|
||||
|
||||
init() {
|
||||
this.initializeArtifactDatabase();
|
||||
this.initializeAlbumCategories();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize all collectible artifacts
|
||||
*/
|
||||
initializeArtifactDatabase() {
|
||||
const artifacts = [
|
||||
// Pre-war artifacts
|
||||
{ id: 'dino_skull', name: 'Dinosaur Skull', category: 'prehistory', rarity: 'legendary', discoveryReward: 500 },
|
||||
{ id: 'ancient_vase', name: 'Ancient Vase', category: 'prehistory', rarity: 'rare', discoveryReward: 100 },
|
||||
{ id: 'fossil', name: 'Fossil', category: 'prehistory', rarity: 'common', discoveryReward: 50 },
|
||||
|
||||
// 2084 tech artifacts
|
||||
{ id: 'ai_core', name: 'AI Core Fragment', category: '2084_tech', rarity: 'legendary', discoveryReward: 800 },
|
||||
{ id: 'hologram_projector', name: 'Hologram Projector', category: '2084_tech', rarity: 'rare', discoveryReward: 150 },
|
||||
{ id: 'old_smartphone', name: 'Pre-War Smartphone', category: '2084_tech', rarity: 'uncommon', discoveryReward: 80 },
|
||||
|
||||
// Cultural artifacts
|
||||
{ id: 'religious_icon', name: 'Religious Icon', category: 'culture', rarity: 'rare', discoveryReward: 120 },
|
||||
{ id: 'painting', name: 'Old Painting', category: 'culture', rarity: 'uncommon', discoveryReward: 90 },
|
||||
{ id: 'book_collection', name: 'Rare Book Collection', category: 'culture', rarity: 'rare', discoveryReward: 110 },
|
||||
|
||||
// Post-apocalypse relics
|
||||
{ id: 'first_cannabis_seed', name: 'First Cannabis Seed', category: 'post_apo', rarity: 'legendary', discoveryReward: 600 },
|
||||
{ id: 'zombie_variant_sample', name: 'Zombie Variant Sample', category: 'post_apo', rarity: 'rare', discoveryReward: 140 },
|
||||
{ id: 'survival_journal', name: "Survivor's Journal", category: 'post_apo', rarity: 'uncommon', discoveryReward: 70 }
|
||||
];
|
||||
|
||||
artifacts.forEach(artifact => {
|
||||
this.artifacts.set(artifact.id, {
|
||||
...artifact,
|
||||
discovered: false,
|
||||
donatedToMuseum: false,
|
||||
discoveryDate: null
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize album categories for organization
|
||||
*/
|
||||
initializeAlbumCategories() {
|
||||
this.albumCategories.set('prehistory', {
|
||||
name: 'Prehistoric Era',
|
||||
description: 'Artifacts from Earth\'s ancient past',
|
||||
totalArtifacts: 3,
|
||||
collected: 0
|
||||
});
|
||||
|
||||
this.albumCategories.set('2084_tech', {
|
||||
name: '2084 Technology',
|
||||
description: 'Advanced tech from before The Collapse',
|
||||
totalArtifacts: 3,
|
||||
collected: 0
|
||||
});
|
||||
|
||||
this.albumCategories.set('culture', {
|
||||
name: 'Cultural Heritage',
|
||||
description: 'Art, religion, and culture of the old world',
|
||||
totalArtifacts: 3,
|
||||
collected: 0
|
||||
});
|
||||
|
||||
this.albumCategories.set('post_apo', {
|
||||
name: 'Post-Apocalypse',
|
||||
description: 'Relics from the new world',
|
||||
totalArtifacts: 3,
|
||||
collected: 0
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Discover artifact (player finds it)
|
||||
*/
|
||||
discoverArtifact(artifactId, location) {
|
||||
const artifact = this.artifacts.get(artifactId);
|
||||
if (!artifact) return false;
|
||||
|
||||
if (artifact.discovered) {
|
||||
console.warn(`Artifact ${artifactId} already discovered`);
|
||||
return false;
|
||||
}
|
||||
|
||||
artifact.discovered = true;
|
||||
artifact.discoveryDate = Date.now();
|
||||
artifact.discoveryLocation = location;
|
||||
|
||||
// Add to player inventory
|
||||
this.scene.inventorySystem.addItem(artifactId, 1);
|
||||
|
||||
// Notification
|
||||
this.scene.uiSystem?.showNotification(
|
||||
`Artifact discovered: ${artifact.name}!`,
|
||||
'discovery',
|
||||
{ rarity: artifact.rarity }
|
||||
);
|
||||
|
||||
// Reward currency
|
||||
this.scene.economySystem.addCurrency(artifact.discoveryReward);
|
||||
|
||||
// VFX
|
||||
this.scene.vfxSystem?.playEffect('artifact_discovery', this.scene.player.x, this.scene.player.y);
|
||||
|
||||
console.log(`✨ Discovered artifact: ${artifact.name} (+${artifact.discoveryReward} coins)`);
|
||||
|
||||
// Kustos dialogue trigger
|
||||
if (!artifact.donatedToMuseum) {
|
||||
this.triggerKustosDialogue(artifactId);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Donate artifact to museum (Kustos interaction)
|
||||
*/
|
||||
donateArtifact(artifactId) {
|
||||
const artifact = this.artifacts.get(artifactId);
|
||||
if (!artifact || !artifact.discovered || artifact.donatedToMuseum) return false;
|
||||
|
||||
// Remove from player inventory
|
||||
if (!this.scene.inventorySystem.hasItem(artifactId, 1)) {
|
||||
console.warn('Player does not have artifact in inventory');
|
||||
return false;
|
||||
}
|
||||
|
||||
this.scene.inventorySystem.removeItem(artifactId, 1);
|
||||
|
||||
// Mark as donated
|
||||
artifact.donatedToMuseum = true;
|
||||
this.collectedArtifacts.add(artifactId);
|
||||
|
||||
// Update category progress
|
||||
const category = this.albumCategories.get(artifact.category);
|
||||
category.collected++;
|
||||
|
||||
// Kustos thanks dialogue
|
||||
this.scene.dialogueSystem?.startDialogue('kustos', 'thank_donation', { artifact: artifact.name });
|
||||
|
||||
// Check for museum evolution
|
||||
this.checkEvolutionTrigger();
|
||||
|
||||
// Achievement check
|
||||
this.checkCompletionAchievements();
|
||||
|
||||
console.log(`📦 Donated ${artifact.name} to museum`);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if museum should evolve to next stage
|
||||
*/
|
||||
checkEvolutionTrigger() {
|
||||
const totalDonated = this.collectedArtifacts.size;
|
||||
|
||||
// Stage thresholds
|
||||
const stageThresholds = {
|
||||
1: 4, // Stage 1: 4 artifacts donated
|
||||
2: 8, // Stage 2: 8 artifacts donated
|
||||
3: 12 // Stage 3: All 12 artifacts donated
|
||||
};
|
||||
|
||||
// Check for evolution
|
||||
for (let stage = 3; stage >= 1; stage--) {
|
||||
if (totalDonated >= stageThresholds[stage] && this.currentStage < stage) {
|
||||
this.evolveMuseum(stage);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Evolve museum to next stage
|
||||
*/
|
||||
evolveMuseum(newStage) {
|
||||
if (newStage <= this.currentStage) return;
|
||||
|
||||
this.currentStage = newStage;
|
||||
|
||||
// Update building visual
|
||||
this.updateMuseumVisual(newStage);
|
||||
|
||||
// VFX: Building evolution
|
||||
this.scene.vfxSystem?.playEffect('museum_evolution', 1500, 600);
|
||||
|
||||
// Notification
|
||||
const stageNames = {
|
||||
1: 'Partial Collection',
|
||||
2: 'Advanced Exhibition',
|
||||
3: 'World-Class Museum'
|
||||
};
|
||||
|
||||
this.scene.uiSystem?.showNotification(
|
||||
`Museum evolved: ${stageNames[newStage]}!`,
|
||||
'success'
|
||||
);
|
||||
|
||||
// Kustos special dialogue
|
||||
this.scene.dialogueSystem?.startDialogue('kustos', `museum_stage_${newStage}`);
|
||||
|
||||
// Grant benefits
|
||||
this.grantStageBenefits(newStage);
|
||||
|
||||
console.log(`🏛️ Museum evolved to Stage ${newStage}: ${stageNames[newStage]}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update museum building sprite
|
||||
*/
|
||||
updateMuseumVisual(stage) {
|
||||
// Load corresponding sprite: museum_stage_1, museum_stage_2, museum_stage_3
|
||||
const sprite = this.scene.buildingSystem.getBuilding('museum');
|
||||
if (sprite) {
|
||||
sprite.setTexture(`museum_stage_${stage}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Grant benefits for reaching museum stage
|
||||
*/
|
||||
grantStageBenefits(stage) {
|
||||
switch (stage) {
|
||||
case 1:
|
||||
// Stage 1: Basic lore access
|
||||
this.scene.gameState.unlocks.lore_system = true;
|
||||
this.scene.uiSystem?.unlockTab('lore');
|
||||
break;
|
||||
case 2:
|
||||
// Stage 2: Research bonuses
|
||||
this.scene.gameState.buffs.research_speed = 1.25; // +25% research
|
||||
break;
|
||||
case 3:
|
||||
// Stage 3: Full collection bonus
|
||||
this.scene.gameState.buffs.artifact_discovery = 2.0; // 2x artifact find rate
|
||||
this.scene.achievementSystem?.unlock('master_curator');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger Kustos dialogue about found artifact
|
||||
*/
|
||||
triggerKustosDialogue(artifactId) {
|
||||
const artifact = this.artifacts.get(artifactId);
|
||||
|
||||
// Show notification to visit Kustos
|
||||
this.scene.uiSystem?.showNotification(
|
||||
`Kustos might be interested in the ${artifact.name}`,
|
||||
'info',
|
||||
{ icon: 'museum' }
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for collection completion achievements
|
||||
*/
|
||||
checkCompletionAchievements() {
|
||||
// Check category completion
|
||||
this.albumCategories.forEach((category, categoryId) => {
|
||||
if (category.collected === category.totalArtifacts) {
|
||||
this.scene.achievementSystem?.unlock(`complete_${categoryId}_collection`);
|
||||
}
|
||||
});
|
||||
|
||||
// Check total completion
|
||||
if (this.collectedArtifacts.size === this.artifacts.size) {
|
||||
this.scene.achievementSystem?.unlock('complete_museum_collection');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get album progress
|
||||
*/
|
||||
getAlbumProgress() {
|
||||
const categories = {};
|
||||
|
||||
this.albumCategories.forEach((category, categoryId) => {
|
||||
categories[categoryId] = {
|
||||
...category,
|
||||
progress: Math.round((category.collected / category.totalArtifacts) * 100)
|
||||
};
|
||||
});
|
||||
|
||||
return {
|
||||
categories,
|
||||
totalArtifacts: this.artifacts.size,
|
||||
totalCollected: this.collectedArtifacts.size,
|
||||
overallProgress: Math.round((this.collectedArtifacts.size / this.artifacts.size) * 100)
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get artifacts by category for UI display
|
||||
*/
|
||||
getArtifactsByCategory(categoryId) {
|
||||
return Array.from(this.artifacts.values())
|
||||
.filter(a => a.category === categoryId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get museum stage info
|
||||
*/
|
||||
getStageInfo() {
|
||||
const stageData = {
|
||||
0: { name: 'Ruined', description: 'Museum is destroyed' },
|
||||
1: { name: 'Partial Collection', description: '4 artifacts displayed' },
|
||||
2: { name: 'Advanced Exhibition', description: '8 artifacts displayed' },
|
||||
3: { name: 'World-Class Museum', description: 'All 12 artifacts displayed' }
|
||||
};
|
||||
|
||||
return {
|
||||
currentStage: this.currentStage,
|
||||
...stageData[this.current Stage],
|
||||
nextStageRequirement: this.currentStage < 3 ? [4, 8, 12][this.currentStage] : null,
|
||||
currentArtifacts: this.collectedArtifacts.size
|
||||
};
|
||||
}
|
||||
}
|
||||
474
src/systems/TownRestorationLogic.js
Normal file
@@ -0,0 +1,474 @@
|
||||
/**
|
||||
* TOWN RESTORATION LOGIC SYSTEM
|
||||
* Complete logic for restoring buildings in Mrtva Dolina
|
||||
* Handles material requirements, construction progress, worker assignments, NPC unlocks
|
||||
*/
|
||||
|
||||
export class TownRestorationLogic {
|
||||
constructor(scene) {
|
||||
this.scene = scene;
|
||||
|
||||
// Building states
|
||||
this.buildings = new Map(); //buildingId → buildingData
|
||||
|
||||
// Construction queues
|
||||
this.activeConstructions = [];
|
||||
|
||||
// Worker management
|
||||
this.assignedWorkers = new Map(); // buildingId → [workerIds]
|
||||
|
||||
// NPC unlock tracking
|
||||
this.unlockedNPCs = new Set();
|
||||
|
||||
this.init();
|
||||
}
|
||||
|
||||
init() {
|
||||
this.initializeBuildingDatabase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize all 14 buildings with restoration data
|
||||
*/
|
||||
initializeBuildingDatabase() {
|
||||
const buildingSpecs = [
|
||||
{
|
||||
id: 'hospital',
|
||||
name: 'Hospital',
|
||||
npcUnlock: 'Ana', // Doctor Ana unlocked
|
||||
materials: {
|
||||
wood: 150,
|
||||
stone: 100,
|
||||
metal: 50,
|
||||
tools: 20
|
||||
},
|
||||
constructionTime: 3600, // 1 hour
|
||||
stages: 3,
|
||||
benefits: ['healing', 'medical_supplies']
|
||||
},
|
||||
{
|
||||
id: 'police',
|
||||
name: 'Police Station',
|
||||
npcUnlock: null,
|
||||
materials: {
|
||||
wood: 100,
|
||||
stone: 150,
|
||||
metal: 80,
|
||||
weapons: 10
|
||||
},
|
||||
constructionTime: 3600,
|
||||
stages: 3,
|
||||
benefits: ['security', 'patrol_unlock']
|
||||
},
|
||||
{
|
||||
id: 'mayor_office',
|
||||
name: "Mayor's Office",
|
||||
npcUnlock: 'Župan', // Mayor unlocked
|
||||
materials: {
|
||||
wood: 120,
|
||||
stone: 80,
|
||||
metal: 40,
|
||||
papers: 50
|
||||
},
|
||||
constructionTime: 2400,
|
||||
stages: 3,
|
||||
benefits: ['election_unlock', 'city_management']
|
||||
},
|
||||
{
|
||||
id: 'tech_workshop',
|
||||
name: 'Tech Workshop',
|
||||
npcUnlock: 'Tehnik', // Technician unlocked
|
||||
materials: {
|
||||
wood: 80,
|
||||
stone: 60,
|
||||
metal: 150,
|
||||
electronics: 30
|
||||
},
|
||||
constructionTime: 3000,
|
||||
stages: 3,
|
||||
benefits: ['tech_upgrades', 'electronics_crafting']
|
||||
},
|
||||
{
|
||||
id: 'tailor',
|
||||
name: 'Tailor Shop',
|
||||
npcUnlock: 'Šivilja', // Seamstress unlocked
|
||||
materials: {
|
||||
wood: 60,
|
||||
fabric: 100,
|
||||
thread: 50,
|
||||
tools: 15
|
||||
},
|
||||
constructionTime: 1800,
|
||||
stages: 3,
|
||||
benefits: ['armor_crafting', 'clothing_upgrades']
|
||||
},
|
||||
{
|
||||
id: 'museum',
|
||||
name: 'Museum',
|
||||
npcUnlock: 'Kustos', // Curator unlocked
|
||||
materials: {
|
||||
wood: 100,
|
||||
stone: 120,
|
||||
glass: 40,
|
||||
artifacts: 10
|
||||
},
|
||||
constructionTime: 4800, // 80 minutes - complex restoration
|
||||
stages: 3,
|
||||
benefits: ['lore_unlock', 'artifact_collection']
|
||||
},
|
||||
{
|
||||
id: 'school',
|
||||
name: 'School',
|
||||
npcUnlock: 'Teacher', // Teacher unlocked
|
||||
materials: {
|
||||
wood: 90,
|
||||
stone: 70,
|
||||
books: 50,
|
||||
tools: 20
|
||||
},
|
||||
constructionTime: 3600,
|
||||
stages: 3,
|
||||
benefits: ['buff_unlock', 'education_system']
|
||||
},
|
||||
{
|
||||
id: 'church',
|
||||
name: 'Church',
|
||||
npcUnlock: 'Župnik', // Priest unlocked
|
||||
materials: {
|
||||
wood: 80,
|
||||
stone: 200,
|
||||
metal: 30,
|
||||
religious_items: 5
|
||||
},
|
||||
constructionTime: 5400, // 90 minutes - sacred restoration
|
||||
stages: 3,
|
||||
benefits: ['blessing_system', 'graveyard_access']
|
||||
},
|
||||
{
|
||||
id: 'blacksmith',
|
||||
name: 'Blacksmith',
|
||||
npcUnlock: 'Ivan Kovač', // Already available
|
||||
materials: {
|
||||
wood: 50,
|
||||
stone: 100,
|
||||
metal: 120,
|
||||
coal: 80
|
||||
},
|
||||
constructionTime: 3000,
|
||||
stages: 3,
|
||||
benefits: ['weapon_crafting', 'tool_upgrades']
|
||||
},
|
||||
{
|
||||
id: 'bakery',
|
||||
name: 'Bakery',
|
||||
npcUnlock: 'Pek', // Baker unlocked
|
||||
materials: {
|
||||
wood: 70,
|
||||
stone: 50,
|
||||
flour: 100,
|
||||
tools: 10
|
||||
},
|
||||
constructionTime: 2400,
|
||||
stages: 3,
|
||||
benefits: ['food_production', 'energy_bonus']
|
||||
}
|
||||
];
|
||||
|
||||
buildingSpecs.forEach(spec => {
|
||||
this.buildings.set(spec.id, {
|
||||
...spec,
|
||||
currentState: 'ruined', // ruined, under_construction, restored
|
||||
currentStage: 0, // 0 = ruined, 1-3 = construction stages
|
||||
progress: 0, // 0-100% construction progress
|
||||
workersAssigned: 0,
|
||||
materialsPaid: false,
|
||||
completionTime: null
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if player can start building restoration
|
||||
*/
|
||||
canStartRestoration(buildingId) {
|
||||
const building = this.buildings.get(buildingId);
|
||||
if (!building) return { canStart: false, reason: 'Building not found' };
|
||||
|
||||
if (building.currentState !== 'ruined') {
|
||||
return { canStart: false, reason: 'Building already restored or under construction' };
|
||||
}
|
||||
|
||||
// Check materials
|
||||
const inventory = this.scene.inventorySystem;
|
||||
for (const [material, amount] of Object.entries(building.materials)) {
|
||||
if (!inventory.hasItem(material, amount)) {
|
||||
return {
|
||||
canStart: false,
|
||||
reason: `Not enough ${material}. Need ${amount}, have ${inventory.getItemCount(material)}`
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return { canStart: true };
|
||||
}
|
||||
|
||||
/**
|
||||
* Start building restoration
|
||||
*/
|
||||
startRestoration(buildingId) {
|
||||
const check = this.canStartRestoration(buildingId);
|
||||
if (!check.canStart) {
|
||||
console.warn(`Cannot start restoration: ${check.reason}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
const building = this.buildings.get(buildingId);
|
||||
const inventory = this.scene.inventorySystem;
|
||||
|
||||
// Deduct materials
|
||||
for (const [material, amount] of Object.entries(building.materials)) {
|
||||
inventory.removeItem(material, amount);
|
||||
}
|
||||
|
||||
// Start construction
|
||||
building.currentState = 'under_construction';
|
||||
building.currentStage = 1;
|
||||
building.progress = 0;
|
||||
building.materialsPaid = true;
|
||||
building.completionTime = Date.now() + (building.constructionTime * 1000);
|
||||
|
||||
this.activeConstructions.push(buildingId);
|
||||
|
||||
// Spawn scaffolding visual
|
||||
this.spawnConstructionVisuals(buildingId);
|
||||
|
||||
console.log(`Started restoration of ${building.name}`);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign workers to speed up construction
|
||||
*/
|
||||
assignWorker(buildingId, workerType = 'zombie') {
|
||||
const building = this.buildings.get(buildingId);
|
||||
if (!building || building.currentState !== 'under_construction') return false;
|
||||
|
||||
const speedBonus = {
|
||||
'zombie': 0.1, // 10% faster per zombie
|
||||
'human': 0.25, // 25% faster per human NPC
|
||||
'kai': 0.5 // Kai works fastest
|
||||
};
|
||||
|
||||
building.workersAssigned++;
|
||||
|
||||
if (!this.assignedWorkers.has(buildingId)) {
|
||||
this.assignedWorkers.set(buildingId, []);
|
||||
}
|
||||
this.assignedWorkers.get(buildingId).push({ type: workerType, bonus: speedBonus[workerType] });
|
||||
|
||||
console.log(`Assigned ${workerType} to ${building.name}. Speed bonus: +${speedBonus[workerType] * 100}%`);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update construction progress
|
||||
*/
|
||||
update(deltaTime) {
|
||||
this.activeConstructions.forEach(buildingId => {
|
||||
const building = this.buildings.get(buildingId);
|
||||
|
||||
// Calculate progress speed (base: 100% over constructionTime)
|
||||
let baseSpeed = (100 / building.constructionTime) * (deltaTime / 1000);
|
||||
|
||||
// Apply worker bonuses
|
||||
if (this.assignedWorkers.has(buildingId)) {
|
||||
const workers = this.assignedWorkers.get(buildingId);
|
||||
const totalBonus = workers.reduce((sum, w) => sum + w.bonus, 0);
|
||||
baseSpeed *= (1 + totalBonus);
|
||||
}
|
||||
|
||||
building.progress += baseSpeed;
|
||||
|
||||
// Check stage transitions
|
||||
if (building.progress >= 33 && building.currentStage === 1) {
|
||||
building.currentStage = 2;
|
||||
this.updateBuildingVisual(buildingId, 2);
|
||||
} else if (building.progress >= 66 && building.currentStage === 2) {
|
||||
building.currentStage = 3;
|
||||
this.updateBuildingVisual(buildingId, 3);
|
||||
}
|
||||
|
||||
// Check completion
|
||||
if (building.progress >= 100) {
|
||||
this.completeRestoration(buildingId);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Complete building restoration
|
||||
*/
|
||||
completeRestoration(buildingId) {
|
||||
const building = this.buildings.get(buildingId);
|
||||
|
||||
building.currentState = 'restored';
|
||||
building.currentStage = 3;
|
||||
building.progress = 100;
|
||||
|
||||
// Remove from active constructions
|
||||
const index = this.activeConstructions.indexOf(buildingId);
|
||||
if (index > -1) this.activeConstructions.splice(index, 1);
|
||||
|
||||
// Remove scaffolding
|
||||
this.removeConstructionVisuals(buildingId);
|
||||
|
||||
// Update building sprite to restored
|
||||
this.updateBuildingVisual(buildingId, 'restored');
|
||||
|
||||
// VFX: Building restoration sparkles
|
||||
this.scene.vfxSystem?.playEffect('building_restoration', building.x, building.y);
|
||||
|
||||
// Unlock NPC if applicable
|
||||
if (building.npcUnlock) {
|
||||
this.unlockNPC(building.npcUnlock);
|
||||
}
|
||||
|
||||
// Grant benefits
|
||||
this.grantBuildingBenefits(buildingId);
|
||||
|
||||
console.log(`✅ ${building.name} restored! NPC unlocked: ${building.npcUnlock || 'None'}`);
|
||||
|
||||
// Quest completion check
|
||||
this.scene.questSystem?.checkBuildingRestoration(buildingId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlock NPC after building restoration
|
||||
*/
|
||||
unlockNPC(npcName) {
|
||||
if (this.unlockedNPCs.has(npcName)) return;
|
||||
|
||||
this.unlockedNPCs.add(npcName);
|
||||
|
||||
// Spawn NPC in town
|
||||
const npcData = this.getNPCSpawnData(npcName);
|
||||
this.scene.npcSystem?.spawnNPC(npcName, npcData.x, npcData.y);
|
||||
|
||||
// Notification
|
||||
this.scene.uiSystem?.showNotification(`${npcName} has arrived in Mrtva Dolina!`, 'success');
|
||||
|
||||
console.log(`🎉 NPC unlocked: ${npcName}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get NPC spawn location based on their building
|
||||
*/
|
||||
getNPCSpawnData(npcName) {
|
||||
const spawnLocations = {
|
||||
'Ana': { x: 1200, y: 800 }, // Hospital
|
||||
'Župan': { x: 1400, y: 700 }, // Mayor's Office
|
||||
'Tehnik': { x: 1100, y: 900 }, // Tech Workshop
|
||||
'Šivilja': { x: 1300, y: 1000 }, // Tailor
|
||||
'Kustos': { x: 1500, y: 600 }, // Museum
|
||||
'Teacher': { x: 1000, y: 700 }, // School
|
||||
'Župnik': { x: 1600, y: 500 }, // Church
|
||||
'Pek': { x: 900, y: 800 } // Bakery
|
||||
};
|
||||
|
||||
return spawnLocations[npcName] || { x: 1200, y: 800 };
|
||||
}
|
||||
|
||||
/**
|
||||
* Grant building benefits to player
|
||||
*/
|
||||
grantBuildingBenefits(buildingId) {
|
||||
const building = this.buildings.get(buildingId);
|
||||
|
||||
building.benefits.forEach(benefit => {
|
||||
switch (benefit) {
|
||||
case 'healing':
|
||||
this.scene.gameState.unlocks.healing = true;
|
||||
break;
|
||||
case 'security':
|
||||
this.scene.defenseSystem?.unlockPatrols();
|
||||
break;
|
||||
case 'election_unlock':
|
||||
this.scene.electionSystem?.unlockElections();
|
||||
break;
|
||||
case 'tech_upgrades':
|
||||
this.scene.craftingSystem?.unlockCategory('electronics');
|
||||
break;
|
||||
case 'armor_crafting':
|
||||
this.scene.craftingSystem?.unlockCategory('armor');
|
||||
break;
|
||||
case 'lore_unlock':
|
||||
this.scene.gameState.unlocks.museum = true;
|
||||
break;
|
||||
case 'buff_unlock':
|
||||
this.scene.schoolSystem?.enable();
|
||||
break;
|
||||
case 'blessing_system':
|
||||
this.scene.churchSystem?.enable();
|
||||
break;
|
||||
case 'weapon_crafting':
|
||||
this.scene.craftingSystem?.unlockCategory('weapons');
|
||||
break;
|
||||
case 'food_production':
|
||||
this.scene.gameState.unlocks.bakery = true;
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Visual updates
|
||||
*/
|
||||
spawnConstructionVisuals(buildingId) {
|
||||
// Spawn scaffolding sprite
|
||||
// Spawn worker NPCs/zombies
|
||||
// Add construction sounds
|
||||
}
|
||||
|
||||
removeConstructionVisuals(buildingId) {
|
||||
// Remove scaffolding
|
||||
// Remove workers
|
||||
// Stop construction sounds
|
||||
}
|
||||
|
||||
updateBuildingVisual(buildingId, stageOrState) {
|
||||
// Update building sprite to show construction progress or restored state
|
||||
// stages: 1 (10-30% built), 2 (30-70% built), 3 (70-100% built)
|
||||
// 'restored' = final completed building
|
||||
}
|
||||
|
||||
/**
|
||||
* Get building restoration status
|
||||
*/
|
||||
getBuildingStatus(buildingId) {
|
||||
return this.buildings.get(buildingId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all restorable buildings
|
||||
*/
|
||||
getAllBuildings() {
|
||||
return Array.from(this.buildings.values());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get restoration progress summary
|
||||
*/
|
||||
getRestorationProgress() {
|
||||
const total = this.buildings.size;
|
||||
const restored = Array.from(this.buildings.values()).filter(b => b.currentState === 'restored').length;
|
||||
const underConstruction = this.activeConstructions.length;
|
||||
|
||||
return {
|
||||
total,
|
||||
restored,
|
||||
underConstruction,
|
||||
ruined: total - restored - underConstruction,
|
||||
percentComplete: Math.round((restored / total) * 100)
|
||||
};
|
||||
}
|
||||
}
|
||||
340
src/systems/ZombieScoutLevelingSystem.js
Normal file
@@ -0,0 +1,340 @@
|
||||
/**
|
||||
* ZOMBIE SCOUT LEVELING SYSTEM (1-20)
|
||||
* XP progression, stat increases, level-up rewards
|
||||
* Integrates with ZombieScout companion
|
||||
*/
|
||||
|
||||
export class ZombieScoutLevelingSystem {
|
||||
constructor(scene) {
|
||||
this.scene = scene;
|
||||
|
||||
// Current stats
|
||||
this.currentLevel = 1;
|
||||
this.currentXP = 0;
|
||||
this.skillPoints = 0;
|
||||
|
||||
// Stats per level
|
||||
this.baseStats = {
|
||||
health: 50,
|
||||
attack: 5,
|
||||
digSpeed: 1.0,
|
||||
moveSpeed: 100,
|
||||
defense: 0
|
||||
};
|
||||
|
||||
this.currentStats = { ...this.baseStats };
|
||||
|
||||
// XP curve
|
||||
this.xpRequirements = this.generateXPCurve();
|
||||
|
||||
// Level rewards
|
||||
this.levelRewards = new Map();
|
||||
|
||||
this.init();
|
||||
}
|
||||
|
||||
init() {
|
||||
this.initializeLevelRewards();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate XP requirements for each level (exponential curve)
|
||||
*/
|
||||
generateXPCurve() {
|
||||
const curve = [0]; // Level 1 = 0 XP
|
||||
|
||||
for (let level = 2; level <= 20; level++) {
|
||||
// Formula: baseXP * (level ^ 1.5)
|
||||
const baseXP = 100;
|
||||
const requiredXP = Math.floor(baseXP * Math.pow(level, 1.5));
|
||||
curve.push(requiredXP);
|
||||
}
|
||||
|
||||
return curve;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize rewards for each level
|
||||
*/
|
||||
initializeLevelRewards() {
|
||||
// Skill points every level
|
||||
for (let level = 2; level <= 20; level++) {
|
||||
this.levelRewards.set(level, {
|
||||
skillPoints: 1,
|
||||
statBonus: this.getStatBonusForLevel(level),
|
||||
specialUnlock: this.getSpecialUnlockForLevel(level)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get stat bonus for specific level
|
||||
*/
|
||||
getStatBonusForLevel(level) {
|
||||
const bonuses = {
|
||||
health: 10, // +10 HP per level
|
||||
attack: 1, // +1 attack per level
|
||||
digSpeed: 0.05, // +5% dig speed per level
|
||||
defense: 0.5 // +0.5 defense per level
|
||||
};
|
||||
|
||||
// Every 5 levels: bonus move speed
|
||||
if (level % 5 === 0) {
|
||||
bonuses.moveSpeed = 10; // +10 speed at levels 5, 10, 15, 20
|
||||
}
|
||||
|
||||
return bonuses;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get special unlock for milestone levels
|
||||
*/
|
||||
getSpecialUnlockForLevel(level) {
|
||||
const unlocks = {
|
||||
5: { type: 'skill', name: 'Basic Attack', description: 'Zombie can attack enemies' },
|
||||
10: { type: 'skill', name: 'Speed Dig', description: 'Dig 50% faster for 10 seconds' },
|
||||
15: { type: 'skill', name: 'Treasure Sense', description: 'Reveal nearby buried items' },
|
||||
20: { type: 'evolution', name: 'Scout Commander', description: 'Zombie becomes elite unit' }
|
||||
};
|
||||
|
||||
return unlocks[level] || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Award XP to Zombie Scout
|
||||
*/
|
||||
awardXP(amount, source = 'general') {
|
||||
this.currentXP += amount;
|
||||
|
||||
// Visual feedback
|
||||
this.showXPGain(amount, source);
|
||||
|
||||
// Check for level up
|
||||
this.checkLevelUp();
|
||||
|
||||
console.log(`+${amount} XP from ${source} (${this.currentXP}/${this.getRequiredXP()})`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if Zombie Scout should level up
|
||||
*/
|
||||
checkLevelUp() {
|
||||
if (this.currentLevel >= 20) return; // Max level cap
|
||||
|
||||
const requiredXP = this.getRequiredXP();
|
||||
|
||||
if (this.currentXP >= requiredXP) {
|
||||
this.levelUp();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Level up Zombie Scout
|
||||
*/
|
||||
levelUp() {
|
||||
this.currentLevel++;
|
||||
this.currentXP -= this.getRequiredXP(this.currentLevel - 1); // Carry over excess XP
|
||||
|
||||
// Apply stat bonuses
|
||||
const rewards = this.levelRewards.get(this.currentLevel);
|
||||
if (rewards) {
|
||||
// Apply stat increases
|
||||
for (const [stat, bonus] of Object.entries(rewards.statBonus)) {
|
||||
this.currentStats[stat] += bonus;
|
||||
}
|
||||
|
||||
// Award skill points
|
||||
this.skillPoints += rewards.skillPoints;
|
||||
|
||||
// Special unlock
|
||||
if (rewards.specialUnlock) {
|
||||
this.unlockSpecial(rewards.specialUnlock);
|
||||
}
|
||||
}
|
||||
|
||||
// Visual effects
|
||||
this.playLevelUpEffects();
|
||||
|
||||
// Notification
|
||||
this.scene.uiSystem?.showNotification(
|
||||
`Zombie Scout reached Level ${this.currentLevel}!`,
|
||||
'level_up',
|
||||
{ skillPoints: this.skillPoints }
|
||||
);
|
||||
|
||||
// Update Zombie Scout sprite if evolution
|
||||
if (this.currentLevel === 20) {
|
||||
this.evolveScout();
|
||||
}
|
||||
|
||||
console.log(`🎉 LEVEL UP! Zombie Scout is now Level ${this.currentLevel}`);
|
||||
console.log(`Stats:`, this.currentStats);
|
||||
console.log(`Skill Points: ${this.skillPoints}`);
|
||||
|
||||
// Quest check
|
||||
this.scene.questSystem?.checkScoutLevel(this.currentLevel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlock special ability or feature
|
||||
*/
|
||||
unlockSpecial(unlock) {
|
||||
console.log(`✨ Special Unlock: ${unlock.name} - ${unlock.description}`);
|
||||
|
||||
if (unlock.type === 'skill') {
|
||||
this.scene.zombieScoutSkills?.unlockSkill(unlock.name);
|
||||
} else if (unlock.type === 'evolution') {
|
||||
// Mark for visual evolution
|
||||
this.isEvolved = true;
|
||||
}
|
||||
|
||||
this.scene.uiSystem?.showNotification(
|
||||
`Unlocked: ${unlock.name}!`,
|
||||
'unlock',
|
||||
{ description: unlock.description }
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Visual evolution at level 20
|
||||
*/
|
||||
evolveScout() {
|
||||
// Update sprite to "Commander" version
|
||||
const scout = this.scene.zombieScout;
|
||||
if (scout) {
|
||||
scout.setTexture('zombie_scout_commander');
|
||||
scout.setScale(scout.scale * 1.2); // Slightly larger
|
||||
|
||||
// VFX: Evolution animation
|
||||
this.scene.vfxSystem?.playEffect('evolution', scout.x, scout.y);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Award XP for different actions
|
||||
*/
|
||||
onCombatKill(enemyType) {
|
||||
const xpValues = {
|
||||
'zombie': 10,
|
||||
'raider': 25,
|
||||
'mutant': 50,
|
||||
'boss': 200
|
||||
};
|
||||
|
||||
this.awardXP(xpValues[enemyType] || 10, 'combat');
|
||||
}
|
||||
|
||||
onDigComplete(itemRarity) {
|
||||
const xpValues = {
|
||||
'common': 5,
|
||||
'uncommon': 15,
|
||||
'rare': 30,
|
||||
'legendary': 100
|
||||
};
|
||||
|
||||
this.awardXP(xpValues[itemRarity] || 5, 'digging');
|
||||
}
|
||||
|
||||
onExplorationProgress() {
|
||||
// Award XP for exploring new areas
|
||||
this.awardXP(20, 'exploration');
|
||||
}
|
||||
|
||||
onQuestComplete(questDifficulty) {
|
||||
const xpValues = {
|
||||
'easy': 50,
|
||||
'medium': 100,
|
||||
'hard': 200,
|
||||
'story': 300
|
||||
};
|
||||
|
||||
this.awardXP(xpValues[questDifficulty] || 50, 'quest');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get required XP for current or specific level
|
||||
*/
|
||||
getRequiredXP(level = this.currentLevel) {
|
||||
return this.xpRequirements[level] || 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get XP progress percentage
|
||||
*/
|
||||
getXPProgress() {
|
||||
if (this.currentLevel >= 20) return 100;
|
||||
|
||||
const required = this.getRequiredXP();
|
||||
return Math.min(100, Math.floor((this.currentXP / required) * 100));
|
||||
}
|
||||
|
||||
/**
|
||||
* Visual effects
|
||||
*/
|
||||
showXPGain(amount, source) {
|
||||
// Floating text above Zombie Scout
|
||||
const scout = this.scene.zombieScout;
|
||||
if (scout) {
|
||||
this.scene.vfxSystem?.floatingText(`+${amount} XP`, scout.x, scout.y - 30, '#FFD700');
|
||||
}
|
||||
}
|
||||
|
||||
playLevelUpEffects() {
|
||||
const scout = this.scene.zombieScout;
|
||||
if (!scout) return;
|
||||
|
||||
// VFX: Level up particles
|
||||
this.scene.vfxSystem?.playEffect('level_up', scout.x, scout.y);
|
||||
|
||||
// SFX: Level up sound
|
||||
this.scene.soundSystem?.play('level_up');
|
||||
|
||||
// Camera shake
|
||||
this.scene.cameras.main.shake(200, 0.005);
|
||||
|
||||
// Flash
|
||||
this.scene.cameras.main.flash(300, 255, 215, 0); // Gold flash
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current level data
|
||||
*/
|
||||
getLevelData() {
|
||||
return {
|
||||
level: this.currentLevel,
|
||||
xp: this.currentXP,
|
||||
requiredXP: this.getRequiredXP(),
|
||||
progress: this.getXPProgress(),
|
||||
stats: { ...this.currentStats },
|
||||
skillPoints: this.skillPoints,
|
||||
isMaxLevel: this.currentLevel >= 20,
|
||||
nextUnlock: this.levelRewards.get(this.currentLevel + 1)?.specialUnlock || null
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Save/Load support
|
||||
*/
|
||||
getSaveData() {
|
||||
return {
|
||||
currentLevel: this.currentLevel,
|
||||
currentXP: this.currentXP,
|
||||
skillPoints: this.skillPoints,
|
||||
currentStats: this.currentStats,
|
||||
isEvolved: this.isEvolved || false
|
||||
};
|
||||
}
|
||||
|
||||
loadSaveData(data) {
|
||||
this.currentLevel = data.currentLevel || 1;
|
||||
this.currentXP = data.currentXP || 0;
|
||||
this.skillPoints = data.skillPoints || 0;
|
||||
this.currentStats = data.currentStats || { ...this.baseStats };
|
||||
this.isEvolved = data.isEvolved || false;
|
||||
|
||||
// Apply visual evolution if loaded at level 20
|
||||
if (this.isEvolved) {
|
||||
this.evolveScout();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"generated_at": "2026-01-05T15:19:05.114915",
|
||||
"generated_at": "2026-01-05T18:27:51.153646",
|
||||
"total_assets": 1415,
|
||||
"total_size": "699.1 MB",
|
||||
"total_size_bytes": 733011645,
|
||||
|
||||