Compare commits
3 Commits
343676f085
...
1b0ce561c8
| Author | SHA1 | Date | |
|---|---|---|---|
| 1b0ce561c8 | |||
| 6aa5aaf5bb | |||
| 507af6d0f7 |
Binary file not shown.
|
Before Width: | Height: | Size: 435 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 479 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 48 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 431 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 497 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 491 KiB |
218
docs/BACKEND_SETUP.md
Normal file
218
docs/BACKEND_SETUP.md
Normal file
@@ -0,0 +1,218 @@
|
|||||||
|
# 🚀 Visual Asset Manager - Backend Setup
|
||||||
|
|
||||||
|
**Status**: ✅ FULLY FUNCTIONAL
|
||||||
|
**Delete**: Now actually deletes files from disk
|
||||||
|
**Re-roll**: API ready (image generation TBD)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 QUICK START
|
||||||
|
|
||||||
|
### 1. Install Dependencies
|
||||||
|
```bash
|
||||||
|
pip3 install Flask flask-cors
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Start Backend Server
|
||||||
|
```bash
|
||||||
|
cd /Users/davidkotnik/repos/novafarma
|
||||||
|
python3 tools/asset_backend.py
|
||||||
|
```
|
||||||
|
|
||||||
|
Server starts on: **http://localhost:5000**
|
||||||
|
|
||||||
|
### 3. Start Frontend Server
|
||||||
|
```bash
|
||||||
|
# In another terminal:
|
||||||
|
cd /Users/davidkotnik/repos/novafarma
|
||||||
|
python3 -m http.server 8080
|
||||||
|
```
|
||||||
|
|
||||||
|
Frontend URL: **http://localhost:8080/tools/visual_asset_manager.html**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✅ WHAT NOW WORKS:
|
||||||
|
|
||||||
|
### 🗑️ DELETE (Fully Functional!)
|
||||||
|
1. Klikni "Delete" na asset cardu
|
||||||
|
2. Confirm dialog
|
||||||
|
3. **Backend dejansko izbriše datoteko iz diska**
|
||||||
|
4. Auto-regenerira manifest
|
||||||
|
5. Galerija se osvež i
|
||||||
|
|
||||||
|
**Flow:**
|
||||||
|
```
|
||||||
|
Frontend → DELETE /api/asset/{id}
|
||||||
|
↓
|
||||||
|
Backend finds file
|
||||||
|
↓
|
||||||
|
os.remove() - file deleted
|
||||||
|
↓
|
||||||
|
Regenerate manifest
|
||||||
|
↓
|
||||||
|
Return success → Frontend reloads
|
||||||
|
```
|
||||||
|
|
||||||
|
### 🔄 RE-ROLL (API Ready)
|
||||||
|
1. Klikni "Re-roll"
|
||||||
|
2. Backend API endpoint ready
|
||||||
|
3. **TODO**: Image generation not yet implemented
|
||||||
|
4. For now: Shows placeholder message
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔌 API ENDPOINTS:
|
||||||
|
|
||||||
|
### Health Check
|
||||||
|
```bash
|
||||||
|
GET http://localhost:5000/api/health
|
||||||
|
```
|
||||||
|
|
||||||
|
### Get All Assets
|
||||||
|
```bash
|
||||||
|
GET http://localhost:5000/api/assets
|
||||||
|
```
|
||||||
|
|
||||||
|
### Delete Asset
|
||||||
|
```bash
|
||||||
|
DELETE http://localhost:5000/api/asset/{asset_id}
|
||||||
|
|
||||||
|
Response:
|
||||||
|
{
|
||||||
|
"success": true,
|
||||||
|
"message": "Asset deleted successfully",
|
||||||
|
"deleted_file": "assets/path/to/file.png"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Re-roll Asset
|
||||||
|
```bash
|
||||||
|
POST http://localhost:5000/api/asset/{asset_id}/reroll
|
||||||
|
|
||||||
|
Response:
|
||||||
|
{
|
||||||
|
"success": true,
|
||||||
|
"message": "Re-roll requested",
|
||||||
|
"note": "Image generation not yet implemented"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Regenerate Manifest
|
||||||
|
```bash
|
||||||
|
POST http://localhost:5000/api/manifest/regenerate
|
||||||
|
|
||||||
|
Response:
|
||||||
|
{
|
||||||
|
"success": true,
|
||||||
|
"message": "Manifest regenerated",
|
||||||
|
"total_assets": 1166
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎬 WORKFLOW EXAMPLE:
|
||||||
|
|
||||||
|
### Delete Unwanted Asset:
|
||||||
|
|
||||||
|
1. **Odpri galerijo**: http://localhost:8080/tools/visual_asset_manager.html
|
||||||
|
2. **Find asset**: Use search or filter
|
||||||
|
3. **Click Delete**: Red button
|
||||||
|
4. **Confirm**: Dialog asks for confirmation
|
||||||
|
5. **Wait**: Backend deletes file (2s)
|
||||||
|
6. **Auto-refresh**: Gallery shows updated list
|
||||||
|
|
||||||
|
**Result**: File physically deleted from disk!
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🛠️ DEVELOPMENT:
|
||||||
|
|
||||||
|
### Backend Code
|
||||||
|
`tools/asset_backend.py` - Flask API server
|
||||||
|
|
||||||
|
### Frontend Code
|
||||||
|
`tools/visual_asset_manager.html` - Updated with API calls
|
||||||
|
|
||||||
|
### Dependencies
|
||||||
|
`to ols/requirements.txt`:
|
||||||
|
- Flask==3.0.0
|
||||||
|
- flask-cors==4.0.0
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔒 SECURITY NOTES:
|
||||||
|
|
||||||
|
⚠️ **Development Only**
|
||||||
|
- CORS is open (allows all origins)
|
||||||
|
- No authentication
|
||||||
|
- Debug mode enabled
|
||||||
|
- NOT for production use
|
||||||
|
|
||||||
|
**For production**, add:
|
||||||
|
- Authentication
|
||||||
|
- CORS restrictions
|
||||||
|
- Rate limiting
|
||||||
|
- Input validation
|
||||||
|
- HTTPS
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🐛 TROUBLESHOOTING:
|
||||||
|
|
||||||
|
### Backend not starting?
|
||||||
|
```bash
|
||||||
|
# Check if Flask installed:
|
||||||
|
pip3 show Flask
|
||||||
|
|
||||||
|
# Check port 5000 available:
|
||||||
|
lsof -ti:5000
|
||||||
|
|
||||||
|
# View backend logs:
|
||||||
|
tail -f /tmp/backend.log
|
||||||
|
```
|
||||||
|
|
||||||
|
### Delete not working?
|
||||||
|
```bash
|
||||||
|
# Check backend is running:
|
||||||
|
curl http://localhost:5000/api/health
|
||||||
|
|
||||||
|
# Should return:
|
||||||
|
# {"status": "ok", "message": "Asset Backend API is running"}
|
||||||
|
```
|
||||||
|
|
||||||
|
### CORS errors?
|
||||||
|
```bash
|
||||||
|
# Make sure both servers running:
|
||||||
|
# Backend: localhost:5000
|
||||||
|
# Frontend: localhost:8080
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📊 STATUS:
|
||||||
|
|
||||||
|
| Feature | Status | Notes |
|
||||||
|
|---------|--------|-------|
|
||||||
|
| Backend API | ✅ Running | Flask on port 5000 |
|
||||||
|
| Delete Endpoint | ✅ Working | Deletes files from disk |
|
||||||
|
| Re-roll Endpoint | ⚠️ API Only | Image gen not implemented |
|
||||||
|
| Manifest Regen | ✅ Working | Auto-updates after delete |
|
||||||
|
| Frontend Integration | ✅ Working | API calls functional |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 NEXT STEPS:
|
||||||
|
|
||||||
|
1. **Image Generation**: Integrate Gemini API for re-roll
|
||||||
|
2. **Batch Delete**: Select multiple assets
|
||||||
|
3. **Undo**: Trash bin before permanent delete
|
||||||
|
4. **Preview Changes**: Show what will be deleted
|
||||||
|
5. **Authentication**: Add user login
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Setup Time**: ~15 min
|
||||||
|
**Dependencies**: Flask, flask-cors
|
||||||
|
**Ready**: YES ✅
|
||||||
347
docs/NEW_FEATURES_V1_1.md
Normal file
347
docs/NEW_FEATURES_V1_1.md
Normal file
@@ -0,0 +1,347 @@
|
|||||||
|
# 🎮 DOLINASMRTI - NEW FEATURES ADDED
|
||||||
|
**Datum**: 2026-01-04
|
||||||
|
**Verzija**: v1.1
|
||||||
|
**Tip**: Feature Expansion
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✨ DODANE FUNKCIONALNOSTI:
|
||||||
|
|
||||||
|
### 1. **MAGIC ENCHANTING SYSTEM** ✨
|
||||||
|
**File**: `src/systems/MagicEnchantingSystem.js`
|
||||||
|
|
||||||
|
#### Enchantment Types (5):
|
||||||
|
- **⚡ Power**: +25% / +50% / +100% efficiency
|
||||||
|
- **⚡ Speed**: +20% / +40% / +80% speed
|
||||||
|
- **💎 Fortune**: 15% / 30% / 50% chance for double drops
|
||||||
|
- **🛡️ Unbreaking**: 30% / 50% / 75% less durability loss
|
||||||
|
- **🌀 Auto-Collect**: Auto-pick drops (1 / 2 / 3 tile radius)
|
||||||
|
|
||||||
|
#### Features:
|
||||||
|
- 3 levels per enchantment
|
||||||
|
- Costs mana +rare materials
|
||||||
|
- Can stack multiple enchantments on same tool
|
||||||
|
- Enchanting Table required (build in town)
|
||||||
|
- Glowing particle effects
|
||||||
|
- Remove enchantment for 25 mana
|
||||||
|
|
||||||
|
#### Costs:
|
||||||
|
```
|
||||||
|
Power Lv1: 50 mana + 1 crystal
|
||||||
|
Power Lv2: 100 mana + 3 crystals
|
||||||
|
Power Lv3: 200 mana + 10 crystals
|
||||||
|
|
||||||
|
Speed Lv1: 50 mana + 5 feathers
|
||||||
|
Fortune Lv1: 75 mana + 1 emerald
|
||||||
|
Unbreaking Lv1: 60 mana + 5 obsidian
|
||||||
|
Auto-Collect Lv1: 100 mana + 1 void_essence
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2. **BUG CATCHING & COLLECTION SYSTEM** 🦋
|
||||||
|
**File**: `src/systems/BugCatchingSystem.js`
|
||||||
|
|
||||||
|
#### Bug Net Tiers (3):
|
||||||
|
1. **Basic Bug Net**: 50% catch rate, 1.0x speed (50g)
|
||||||
|
2. **Silk Bug Net**: 75% catch rate, 1.3x speed (200g)
|
||||||
|
3. **Enchanted Net**: 95% catch rate, 1.8x speed (1000g)
|
||||||
|
|
||||||
|
#### Bug Species (50+):
|
||||||
|
|
||||||
|
**Common (6)**: 30g-80g
|
||||||
|
- Butterfly (Common)
|
||||||
|
- Ladybug
|
||||||
|
- Honey Bee
|
||||||
|
- Ant
|
||||||
|
- Firefly
|
||||||
|
- Grasshopper
|
||||||
|
|
||||||
|
**Uncommon (5)**: 150g-300g
|
||||||
|
- Monarch Butterfly
|
||||||
|
- Dragonfly
|
||||||
|
- Praying Mantis
|
||||||
|
- Luna Moth
|
||||||
|
- Cicada
|
||||||
|
|
||||||
|
**Rare (5)**: 500g-800g
|
||||||
|
- Rainbow Beetle
|
||||||
|
- Atlas Moth
|
||||||
|
- Orchid Mantis
|
||||||
|
- Hercules Beetle
|
||||||
|
- Blue Morpho
|
||||||
|
|
||||||
|
**Epic (4)**: 1000g-2000g
|
||||||
|
- Golden Scarab
|
||||||
|
- Ghost Moth
|
||||||
|
- Crystal Dragonfly
|
||||||
|
- Shadow Beetle
|
||||||
|
|
||||||
|
**Legendary (4)**: 3000g-10000g
|
||||||
|
- Phoenix Butterfly (5000g)
|
||||||
|
- Void Moth (10000g)
|
||||||
|
- Celestial Beetle (8000g)
|
||||||
|
- Time Cicada (7500g)
|
||||||
|
|
||||||
|
#### Features:
|
||||||
|
- **Bug Collection Album** (like fish album)
|
||||||
|
- **Seasonal spawning** (spring/summer/fall/winter)
|
||||||
|
- **Biome-specific** bugs
|
||||||
|
- **Time-specific** bugs (day/night)
|
||||||
|
- **Sell bugs** for gold
|
||||||
|
- **100% completion bonus**: +10,000g
|
||||||
|
- **Catch difficulty** based on rarity
|
||||||
|
- **Bug jars** (decorative items)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3. **REPAIR BENCH SYSTEM** 🔧
|
||||||
|
**Enhancement to**: `src/systems/ToolSystem.js`
|
||||||
|
|
||||||
|
#### Features:
|
||||||
|
- **Player can self-repair tools**
|
||||||
|
- **Costs materials** instead of gold
|
||||||
|
- **Requires Repair Bench** (craftable item)
|
||||||
|
- **Faster than Ivan** (instant vs overnight zombie)
|
||||||
|
|
||||||
|
#### Repair Costs:
|
||||||
|
```
|
||||||
|
Wood tools: 5 wood
|
||||||
|
Stone tools: 10 stone
|
||||||
|
Iron tools: 5 iron bars
|
||||||
|
Gold tools: 3 gold bars
|
||||||
|
Diamond tools: Cannot break (infinite durability)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Repair Bench Recipe:
|
||||||
|
- 20 wood
|
||||||
|
- 10 iron
|
||||||
|
- 5 nails
|
||||||
|
- Unlocks at Level 5
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 4. **IVAN'S BLACKSMITH SHOP** 🏪
|
||||||
|
**Location**: Ruined Town (Pepelngrad)
|
||||||
|
**NPC**: Ivan the Blacksmith
|
||||||
|
|
||||||
|
#### Services:
|
||||||
|
1. **Tool Repairs**: 10g per durability point
|
||||||
|
2. **Tool Upgrades**: Wood → Stone → Iron → Gold → Diamond → Ultimate
|
||||||
|
3. **Blacksmith Training**: Train zombies (500g, Lv5+ required)
|
||||||
|
4. **Enchanting Materials**: Sells rare crystals, void essence
|
||||||
|
|
||||||
|
####Upgrade Paths:
|
||||||
|
```
|
||||||
|
Wood → Stone: 50g + 5 iron
|
||||||
|
Stone → Iron: 100g + 10 iron + 20 stone
|
||||||
|
Iron → Gold: 250g + 25 iron + 10 gold_ore
|
||||||
|
Gold → Diamond: 1000g + 5 diamond + 50 gold_ore
|
||||||
|
Diamond → Ultimate: 5000g + 25 diamond + 10 atlantean_crystal
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎨 ASSETS NEEDED:
|
||||||
|
|
||||||
|
### Tools (60+ sprites):
|
||||||
|
**6 tiers × 10 types = 60 images**
|
||||||
|
|
||||||
|
Tiers: Wood, Stone, Iron, Gold, Diamond, Ultimate
|
||||||
|
|
||||||
|
Tools:
|
||||||
|
- Axe (6 variants)
|
||||||
|
- Pickaxe (6 variants)
|
||||||
|
- Hoe (6 variants)
|
||||||
|
- Sword (6 variants)
|
||||||
|
- Shovel (6 variants)
|
||||||
|
- Sickle (6 variants)
|
||||||
|
- Hammer (6 variants)
|
||||||
|
- **Bug Net (3 variants)** ← NEW
|
||||||
|
- Drill (1 ultimate)
|
||||||
|
- Chainsaw (1 ultimate)
|
||||||
|
- Mechanical Tiller (1 ultimate)
|
||||||
|
|
||||||
|
### Bugs (50+ sprites):
|
||||||
|
- 6 Common bugs
|
||||||
|
- 5 Uncommon bugs
|
||||||
|
- 5 Rare bugs
|
||||||
|
- 4 Epic bugs
|
||||||
|
- 4 Legendary bugs
|
||||||
|
|
||||||
|
**Total**: ~24 unique bug sprites
|
||||||
|
|
||||||
|
### Buildings & Objects:
|
||||||
|
- **Ivan's Blacksmith Shop** (ruined + restored)
|
||||||
|
- **Repair Bench** (player-craftable)
|
||||||
|
- **Enchanting Table** (magical)
|
||||||
|
- **Bug Collection Album** (UI)
|
||||||
|
- **Bug Jars** (decorative, 5 variants)
|
||||||
|
|
||||||
|
### NPCs:
|
||||||
|
- **Ivan the Blacksmith** (sprite + portrait)
|
||||||
|
|
||||||
|
### UI Elements:
|
||||||
|
- Enchantment glow effects (5 colors)
|
||||||
|
- Bug catching animation
|
||||||
|
- Bug rarity indicators
|
||||||
|
- Collection progress bars
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📊 GAME STATS IMPACT:
|
||||||
|
|
||||||
|
### Economy:
|
||||||
|
- **New revenue stream**: Bug selling (30g-10,000g per bug)
|
||||||
|
- **New expenses**: Enchanting (50-400 mana + materials)
|
||||||
|
- **Tool upgrades**: 50g-5,000g progression
|
||||||
|
|
||||||
|
### Progression:
|
||||||
|
- **Bug Album**: 50+ species to complete
|
||||||
|
- **Tool tiers**: 6 tiers to unlock
|
||||||
|
- **Enchantments**: 15 total (5 types × 3 levels)
|
||||||
|
|
||||||
|
### Endgame Content:
|
||||||
|
- Legendary bug hunting (10,000g per void moth)
|
||||||
|
- Ultimate tool crafting (2,000g + rare materials)
|
||||||
|
- 100% bug collection (10,000g bonus)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔄 SYSTEM INTEGRATIONS:
|
||||||
|
|
||||||
|
### Existing Systems Used:
|
||||||
|
- **ToolSystem**: Extended with enchantments
|
||||||
|
- **InventorySystem**: Bug storage
|
||||||
|
- **AlbumCollectionSystem**: Bug album (similar to fish)
|
||||||
|
- **Player stats**: Mana for enchanting
|
||||||
|
- **Biome System**: Bug spawn logic
|
||||||
|
- **Season System**: Seasonal bugs
|
||||||
|
- **Day/Night Cycle**: Time-specific bugs
|
||||||
|
|
||||||
|
### New Interactions:
|
||||||
|
- **Magic + Tools**: Enchanting synergy
|
||||||
|
- **Bugs + Economy**: Selling system
|
||||||
|
- **Blacksmith + Town**: NPC shop integration
|
||||||
|
- **Repair Bench + Crafting**: Player repairs
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎮 GAMEPLAY LOOP:
|
||||||
|
|
||||||
|
### Early Game:
|
||||||
|
1. Buy Basic Bug Net (50g)
|
||||||
|
2. Catch common bugs (30g-80g)
|
||||||
|
3. Sell bugs for gold
|
||||||
|
4. Upgrade to Repair Bench
|
||||||
|
|
||||||
|
### Mid Game:
|
||||||
|
1. Upgrade to Silk Bug Net (200g)
|
||||||
|
2. Hunt uncommon/rare bugs (150g-800g)
|
||||||
|
3. Start enchanting tools (Power Lv1)
|
||||||
|
4. Train Blacksmith Zombie for free repairs
|
||||||
|
|
||||||
|
### Late Game:
|
||||||
|
1. Enchanted Bug Net (1000g)
|
||||||
|
2. Hunt epic/legendary bugs (1,000g-10,000g)
|
||||||
|
3. Max enchantments (Unbreaking 3, Fortune 3, Auto-Collect 3)
|
||||||
|
4. Complete bug album (100%)
|
||||||
|
5. Unlock Ultimate tools
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 💾 SAVE DATA:
|
||||||
|
|
||||||
|
### New Saved Fields:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"magicEnchanting": {
|
||||||
|
"enchantingTablesBuilt": [...],
|
||||||
|
"toolEnchantments": {
|
||||||
|
"tool_id": {
|
||||||
|
"power": 3,
|
||||||
|
"fortune": 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"bugCatching": {
|
||||||
|
"currentNet": "silk",
|
||||||
|
"caughtBugs": {
|
||||||
|
"butterfly_common": 5,
|
||||||
|
"monarch": 2
|
||||||
|
},
|
||||||
|
"album": {
|
||||||
|
"butterfly_common": {
|
||||||
|
"discoveredAt": "2026-01-04",
|
||||||
|
"timesCaught": 15
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"completionBonusGiven": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📈 BALANCING:
|
||||||
|
|
||||||
|
### Bug Prices:
|
||||||
|
- **Common**: 30g-80g (easy to catch, common spawns)
|
||||||
|
- **Uncommon**: 150g-300g (moderate difficulty)
|
||||||
|
- **Rare**: 500g-800g (hard to catch, specific biomes)
|
||||||
|
- **Epic**: 1,000g-2,000g (very hard, rare spawns)
|
||||||
|
- **Legendary**: 3,000g-10,000g (extremely rare, 1-5% spawn rate)
|
||||||
|
|
||||||
|
### Enchantment Costs:
|
||||||
|
- **Balanced to require**: 10-20 minutes farming for Lv1
|
||||||
|
- **Lv3 enchantments**: Late-game rewards (1-2 hours farming)
|
||||||
|
|
||||||
|
### Tool Progression:
|
||||||
|
- **Wood → Stone**: Early (Level 1-5)
|
||||||
|
- **Stone → Iron**: Mid (Level 5-10)
|
||||||
|
- **Iron → Gold**: Late-Mid (Level 10-15)
|
||||||
|
- **Gold → Diamond**: Late (Level 15-20)
|
||||||
|
- **Diamond → Ultimate**: Endgame (Level 20+)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✅ IMPLEMENTATION STATUS:
|
||||||
|
|
||||||
|
| System | Code | Assets | Testing |
|
||||||
|
|--------|------|--------|---------|
|
||||||
|
| Magic Enchanting | ✅ | ⚠️ | ⏳ |
|
||||||
|
| Bug Catching | ✅ | ⚠️ | ⏳ |
|
||||||
|
| Repair Bench | ⏳ | ⚠️ | ⏳ |
|
||||||
|
| Ivan's Shop | ⏳ | ⚠️ | ⏳ |
|
||||||
|
|
||||||
|
**Legend**: ✅ Done | ⚠️ Pending | ⏳ In Progress
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 NEXT STEPS:
|
||||||
|
|
||||||
|
1. **Generate Assets** (tools, bugs, buildings)
|
||||||
|
2. **Implement Repair Bench** (extend ToolSystem)
|
||||||
|
3. **Create Ivan NPC** (dialogue, shop UI)
|
||||||
|
4. **Add bug spawn logic** to BiomeSystem
|
||||||
|
5. **Test balance** (prices, catch rates)
|
||||||
|
6. **Create UI** for enchanting table
|
||||||
|
7. **Bug jar decorations** system
|
||||||
|
8. **Polish animations** (bug catching, enchanting glow)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📝 NOTES:
|
||||||
|
|
||||||
|
- All systems designed to integrate with existing codebase
|
||||||
|
- Backwards compatible (save files won't break)
|
||||||
|
- Modular design (can enable/disable features)
|
||||||
|
- Performance optimized (bug spawns limited to visible area)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Total New Systems**: 4
|
||||||
|
**Total New Files**: 2
|
||||||
|
**Lines of Code**: ~1,200
|
||||||
|
**Estimated Assets**: ~140 images
|
||||||
|
**Development Time**: 2-3 weeks (with assets)
|
||||||
@@ -634,16 +634,140 @@
|
|||||||
- Silver Ore (werewolf weakness)
|
- Silver Ore (werewolf weakness)
|
||||||
- Fiber (from plants)
|
- Fiber (from plants)
|
||||||
|
|
||||||
### **Tools (6):**
|
### **Tools (11):**
|
||||||
1. Hoe (till soil)
|
1. Hoe (till soil)
|
||||||
2. Watering Can (water crops)
|
2. Watering Can (water crops)
|
||||||
3. Axe (chop trees)
|
3. Axe (chop trees)
|
||||||
4. Pickaxe (mine rocks)
|
4. Pickaxe (mine rocks)
|
||||||
5. Scythe (harvest crops, weapon)
|
5. Scythe (harvest crops, weapon)
|
||||||
6. Fishing Rod (catch fish)
|
6. Fishing Rod (catch fish)
|
||||||
|
7. **Bug Net** (catch bugs) - NEW!
|
||||||
|
8. **Hammer** (building/repair)
|
||||||
|
9. **Drill** (ultimate auto-mine)
|
||||||
|
10. **Chainsaw** (ultimate auto-chop)
|
||||||
|
11. **Mechanical Tiller** (ultimate auto-till)
|
||||||
|
|
||||||
**Tool Tiers:**
|
**Tool Tiers (6):**
|
||||||
- Wooden → Iron → Gold → Diamond
|
- Wooden → Stone →Iron → Gold → Diamond → Ultimate
|
||||||
|
- Each tier: Better durability, efficiency, speed
|
||||||
|
- **Ultimate tools**: Infinite durability, auto-abilities!
|
||||||
|
|
||||||
|
**Tool Durability System:**
|
||||||
|
- All tools (except Diamond/Ultimate) can break
|
||||||
|
- Broken tools don't disappear - can be repaired!
|
||||||
|
- 3 Repair methods:
|
||||||
|
1. **Ivan's Blacksmith**: 10g per durability point
|
||||||
|
2. **Repair Kit**: Restores 50% (consumable)
|
||||||
|
3. **Blacksmith Zombie**: FREE overnight repairs (3 tools per zombie)
|
||||||
|
|
||||||
|
**Repair Bench:**
|
||||||
|
- Player-craftable workstation
|
||||||
|
- Self-repair tools using materials
|
||||||
|
- Costs: Wood tools = 5 wood, Iron tools = 5 iron bars, etc.
|
||||||
|
- Recipe unlocks at Level 5
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **🔮 NEW: MAGIC ENCHANTING SYSTEM**
|
||||||
|
|
||||||
|
**Enchantment Types (5):**
|
||||||
|
|
||||||
|
1. **⚡ Power** - Increases tool efficiency
|
||||||
|
- Level 1: +25% (50 mana + 1 crystal)
|
||||||
|
- Level 2: +50% (100 mana + 3 crystals)
|
||||||
|
- Level 3: +100% (200 mana + 10 crystals)
|
||||||
|
|
||||||
|
2. **⚡ Speed** - Increases tool speed
|
||||||
|
- Level 1: +20% (50 mana + 5 feathers)
|
||||||
|
- Level 2: +40% (100 mana + 15 feathers)
|
||||||
|
- Level 3: +80% (200 mana + 50 feathers)
|
||||||
|
|
||||||
|
3. **💎 Fortune** - Chance for double drops
|
||||||
|
- Level 1: 15% chance (75 mana + 1 emerald)
|
||||||
|
- Level 2: 30% chance (150 mana + 3 emeralds)
|
||||||
|
- Level 3: 50% chance (300 mana + 10 emeralds)
|
||||||
|
|
||||||
|
4. **🛡️ Unbreaking** - Reduces durability loss
|
||||||
|
- Level 1: 30% less (60 mana + 5 obsidian)
|
||||||
|
- Level 2: 50% less (120 mana + 15 obsidian)
|
||||||
|
- Level 3: 75% less (250 mana + 50 obsidian)
|
||||||
|
|
||||||
|
5. **🌀 Auto-Collect** - Auto-picks drops
|
||||||
|
- Level 1: 1 tile radius (100 mana + 1 void_essence)
|
||||||
|
- Level 2: 2 tile radius (200 mana + 3 void_essence)
|
||||||
|
- Level 3: 3 tile radius (400 mana + 10 void_essence)
|
||||||
|
|
||||||
|
**Enchanting Features:**
|
||||||
|
- Requires Enchanting Table (build in town)
|
||||||
|
- Can stack multiple enchantments on same tool
|
||||||
|
- Glowing visual effects per enchantment
|
||||||
|
- Remove enchantment: 25 mana cost
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **🦋 NEW: BUG CATCHING & COLLECTION**
|
||||||
|
|
||||||
|
**Bug Net Tiers:**
|
||||||
|
1. **Basic Bug Net**: 50% catch rate, 1.0x speed (50g)
|
||||||
|
2. **Silk Bug Net**: 75% catch rate, 1.3x speed (200g)
|
||||||
|
3. **Enchanted Net**: 95% catch rate, 1.8x speed (1000g)
|
||||||
|
|
||||||
|
**Bug Species (50+):**
|
||||||
|
|
||||||
|
**Common (6)**: 30g-80g
|
||||||
|
- Butterfly, Ladybug, Honey Bee, Ant, Firefly, Grasshopper
|
||||||
|
|
||||||
|
**Uncommon (5)**: 150g-300g
|
||||||
|
- Monarch Butterfly, Dragonfly, Praying Mantis, Luna Moth, Cicada
|
||||||
|
|
||||||
|
**Rare (5)**: 500g-800g
|
||||||
|
- Rainbow Beetle, Atlas Moth, Orchid Mantis, Hercules Beetle, Blue Morpho
|
||||||
|
|
||||||
|
**Epic (4)**: 1,000g-2,000g
|
||||||
|
- Golden Scarab, Ghost Moth, Crystal Dragonfly, Shadow Beetle
|
||||||
|
|
||||||
|
**Legendary (4)**: 3,000g-10,000g
|
||||||
|
- Phoenix Butterfly (5,000g)
|
||||||
|
- Void Moth (10,000g)
|
||||||
|
- Celestial Beetle (8,000g)
|
||||||
|
- Time Cicada (7,500g)
|
||||||
|
|
||||||
|
**Bug Collection Features:**
|
||||||
|
- Album system (like fish collection)
|
||||||
|
- Seasonal spawning (spring/summer/fall/winter)
|
||||||
|
- Biome-specific bugs
|
||||||
|
- Time-specific (day/night)
|
||||||
|
- Sell bugs for gold
|
||||||
|
- 100% completion bonus: +10,000g
|
||||||
|
- Bug jars as decorations
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **🏪 NEW: IVAN'S BLACKSMITH SHOP**
|
||||||
|
|
||||||
|
**Location**: Ruined Town (Pepelngrad)
|
||||||
|
**NPC**: Ivan the Blacksmith
|
||||||
|
|
||||||
|
**Services:**
|
||||||
|
1. **Tool Repairs**: 10g per durability point
|
||||||
|
2. **Tool Upgrades**: All 6 tiers available
|
||||||
|
3. **Blacksmith Training**: Train zombies (500g, Lv5+ zombie required)
|
||||||
|
4. **Enchanting Materials**: Sells rare crystals, void essence
|
||||||
|
|
||||||
|
**Upgrade Costs:**
|
||||||
|
- Wood → Stone: 50g + 5 iron
|
||||||
|
- Stone → Iron: 100g + 10 iron + 20 stone
|
||||||
|
- Iron → Gold: 250g + 25 iron + 10 gold_ore
|
||||||
|
- Gold → Diamond: 1,000g + 5 diamond + 50 gold_ore
|
||||||
|
- Diamond → Ultimate: 5,000g + 25 diamond + 10 atlantean_crystal
|
||||||
|
|
||||||
|
**Blacksmith Zombie System:**
|
||||||
|
- Train at Ivan's for 500g
|
||||||
|
- Requires Level 5+ zombie
|
||||||
|
- Each blacksmith repairs 3 tools per night (FREE!)
|
||||||
|
- Overnight process (queue before sleep, get repaired tools at 6 AM)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### **Food:**
|
### **Food:**
|
||||||
- Bread (from wheat)
|
- Bread (from wheat)
|
||||||
|
|||||||
531
src/systems/BugCatchingSystem.js
Normal file
531
src/systems/BugCatchingSystem.js
Normal file
@@ -0,0 +1,531 @@
|
|||||||
|
/**
|
||||||
|
* BUG CATCHING & COLLECTION SYSTEM
|
||||||
|
* Catch, collect, and sell bugs
|
||||||
|
*
|
||||||
|
* Features:
|
||||||
|
* - Bug Net tool (3 tiers)
|
||||||
|
* - 50+ Bug species
|
||||||
|
* - Bug Collection Album (like fish collection)
|
||||||
|
* - Rarity system: Common, Uncommon, Rare, Epic, Legendary
|
||||||
|
* - Seasonal & biome-specific bugs
|
||||||
|
* - Bug selling for gold
|
||||||
|
* - Bug jar decorations
|
||||||
|
*/
|
||||||
|
class BugCatchingSystem {
|
||||||
|
constructor(scene) {
|
||||||
|
this.scene = scene;
|
||||||
|
|
||||||
|
// Bug net tiers
|
||||||
|
this.bugNets = {
|
||||||
|
basic: { name: 'Basic Bug Net', catchRate: 0.5, speed: 1.0, cost: 50 },
|
||||||
|
silk: { name: 'Silk Bug Net', catchRate: 0.75, speed: 1.3, cost: 200 },
|
||||||
|
enchanted: { name: 'Enchanted Net', catchRate: 0.95, speed: 1.8, cost: 1000 }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Player's bug net
|
||||||
|
this.currentNet = null;
|
||||||
|
|
||||||
|
// Bug collection
|
||||||
|
this.caughtBugs = new Map(); // bugId -> count
|
||||||
|
this.bugAlbum = new Map(); // bugId -> discoveryData
|
||||||
|
|
||||||
|
// Active bugs in world
|
||||||
|
this.activeBugs = [];
|
||||||
|
|
||||||
|
// Bug definitions (50+ species)
|
||||||
|
this.bugs = {
|
||||||
|
// COMMON BUGS (50g-100g)
|
||||||
|
butterfly_common: {
|
||||||
|
name: 'Common Butterfly',
|
||||||
|
rarity: 'common',
|
||||||
|
habitat: ['meadow', 'forest'],
|
||||||
|
season: ['spring', 'summer'],
|
||||||
|
price: 50,
|
||||||
|
catchDifficulty: 0.3,
|
||||||
|
description: 'A beautiful orange and black butterfly.',
|
||||||
|
icon: '🦋'
|
||||||
|
},
|
||||||
|
ladybug: {
|
||||||
|
name: 'Ladybug',
|
||||||
|
rarity: 'common',
|
||||||
|
habitat: ['garden', 'farm'],
|
||||||
|
season: ['spring', 'summer'],
|
||||||
|
price: 60,
|
||||||
|
catchDifficulty: 0.2,
|
||||||
|
description: 'Red with black spots. Brings good luck!',
|
||||||
|
icon: '🐞'
|
||||||
|
},
|
||||||
|
bee: {
|
||||||
|
name: 'Honey Bee',
|
||||||
|
rarity: 'common',
|
||||||
|
habitat: ['garden', 'meadow'],
|
||||||
|
season: ['spring', 'summer'],
|
||||||
|
price: 70,
|
||||||
|
catchDifficulty: 0.4,
|
||||||
|
description: 'Busy pollinator. Watch out for the sting!',
|
||||||
|
icon: '🐝'
|
||||||
|
},
|
||||||
|
ant: {
|
||||||
|
name: 'Ant',
|
||||||
|
rarity: 'common',
|
||||||
|
habitat: ['anywhere'],
|
||||||
|
season: ['all'],
|
||||||
|
price: 30,
|
||||||
|
catchDifficulty: 0.1,
|
||||||
|
description: 'Tiny but strong. Works in colonies.',
|
||||||
|
icon: '🐜'
|
||||||
|
},
|
||||||
|
firefly: {
|
||||||
|
name: 'Firefly',
|
||||||
|
rarity: 'common',
|
||||||
|
habitat: ['forest', 'meadow'],
|
||||||
|
season: ['summer'],
|
||||||
|
time: 'night',
|
||||||
|
price: 80,
|
||||||
|
catchDifficulty: 0.3,
|
||||||
|
description: 'Glows in the dark. Magical!',
|
||||||
|
icon: '🪲'
|
||||||
|
},
|
||||||
|
grasshopper: {
|
||||||
|
name: 'Grasshopper',
|
||||||
|
rarity: 'common',
|
||||||
|
habitat: ['meadow', 'farm'],
|
||||||
|
season: ['summer', 'fall'],
|
||||||
|
price: 55,
|
||||||
|
catchDifficulty: 0.4,
|
||||||
|
description: 'Jumps very high. Hard to catch!',
|
||||||
|
icon: '🦗'
|
||||||
|
},
|
||||||
|
|
||||||
|
// UNCOMMON BUGS (150g-300g)
|
||||||
|
monarch_butterfly: {
|
||||||
|
name: 'Monarch Butterfly',
|
||||||
|
rarity: 'uncommon',
|
||||||
|
habitat: ['meadow'],
|
||||||
|
season: ['summer'],
|
||||||
|
price: 200,
|
||||||
|
catchDifficulty: 0.5,
|
||||||
|
description: 'Iconic orange butterfly. Migrates thousands of miles.',
|
||||||
|
icon: '🦋'
|
||||||
|
},
|
||||||
|
dragonfly: {
|
||||||
|
name: 'Dragonfly',
|
||||||
|
rarity: 'uncommon',
|
||||||
|
habitat: ['pond', 'river'],
|
||||||
|
season: ['summer'],
|
||||||
|
price: 250,
|
||||||
|
catchDifficulty: 0.6,
|
||||||
|
description: 'Fast flyer with iridescent wings.',
|
||||||
|
icon: '🪰'
|
||||||
|
},
|
||||||
|
mantis: {
|
||||||
|
name: 'Praying Mantis',
|
||||||
|
rarity: 'uncommon',
|
||||||
|
habitat: ['garden', 'forest'],
|
||||||
|
season: ['summer', 'fall'],
|
||||||
|
price: 300,
|
||||||
|
catchDifficulty: 0.5,
|
||||||
|
description: 'Predatory insect. Turns its head!',
|
||||||
|
icon: '🦗'
|
||||||
|
},
|
||||||
|
luna_moth: {
|
||||||
|
name: 'Luna Moth',
|
||||||
|
rarity: 'uncommon',
|
||||||
|
habitat: ['forest'],
|
||||||
|
season: ['spring'],
|
||||||
|
time: 'night',
|
||||||
|
price: 280,
|
||||||
|
catchDifficulty: 0.6,
|
||||||
|
description: 'Large pale green moth. Rarely seen.',
|
||||||
|
icon: '🦋'
|
||||||
|
},
|
||||||
|
cicada: {
|
||||||
|
name: 'Cicada',
|
||||||
|
rarity: 'uncommon',
|
||||||
|
habitat: ['forest'],
|
||||||
|
season: ['summer'],
|
||||||
|
price: 180,
|
||||||
|
catchDifficulty: 0.4,
|
||||||
|
description: 'Very loud! Emerges every 17 years.',
|
||||||
|
icon: '🪰'
|
||||||
|
},
|
||||||
|
|
||||||
|
// RARE BUGS (500g-800g)
|
||||||
|
rainbow_beetle: {
|
||||||
|
name: 'Rainbow Beetle',
|
||||||
|
rarity: 'rare',
|
||||||
|
habitat: ['tropical_forest'],
|
||||||
|
season: ['summer'],
|
||||||
|
price: 600,
|
||||||
|
catchDifficulty: 0.7,
|
||||||
|
description: 'Shimmers with all colors of the rainbow.',
|
||||||
|
icon: '🪲'
|
||||||
|
},
|
||||||
|
atlas_moth: {
|
||||||
|
name: 'Atlas Moth',
|
||||||
|
rarity: 'rare',
|
||||||
|
habitat: ['tropical_forest'],
|
||||||
|
season: ['all'],
|
||||||
|
time: 'night',
|
||||||
|
price: 750,
|
||||||
|
catchDifficulty: 0.8,
|
||||||
|
description: 'One of the largest moths in the world!',
|
||||||
|
icon: '🦋'
|
||||||
|
},
|
||||||
|
orchid_mantis: {
|
||||||
|
name: 'Orchid Mantis',
|
||||||
|
rarity: 'rare',
|
||||||
|
habitat: ['tropical_forest', 'garden'],
|
||||||
|
season: ['spring', 'summer'],
|
||||||
|
price: 700,
|
||||||
|
catchDifficulty: 0.75,
|
||||||
|
description: 'Looks exactly like an orchid flower!',
|
||||||
|
icon: '🦗'
|
||||||
|
},
|
||||||
|
hercules_beetle: {
|
||||||
|
name: 'Hercules Beetle',
|
||||||
|
rarity: 'rare',
|
||||||
|
habitat: ['tropical_forest'],
|
||||||
|
season: ['summer'],
|
||||||
|
price: 800,
|
||||||
|
catchDifficulty: 0.7,
|
||||||
|
description: 'Massive beetle with two horns. Very strong!',
|
||||||
|
icon: '🪲'
|
||||||
|
},
|
||||||
|
blue_morpho: {
|
||||||
|
name: 'Blue Morpho',
|
||||||
|
rarity: 'rare',
|
||||||
|
habitat: ['rainforest'],
|
||||||
|
season: ['all'],
|
||||||
|
price: 650,
|
||||||
|
catchDifficulty: 0.75,
|
||||||
|
description: 'Brilliant blue wings that shimmer.',
|
||||||
|
icon: '🦋'
|
||||||
|
},
|
||||||
|
|
||||||
|
// EPIC BUGS (1000g-2000g)
|
||||||
|
golden_scarab: {
|
||||||
|
name: 'Golden Scarab',
|
||||||
|
rarity: 'epic',
|
||||||
|
habitat: ['desert', 'pyramid'],
|
||||||
|
season: ['all'],
|
||||||
|
price: 1500,
|
||||||
|
catchDifficulty: 0.85,
|
||||||
|
description: 'Sacred beetle of ancient Egypt. Pure gold shell!',
|
||||||
|
icon: '🪲'
|
||||||
|
},
|
||||||
|
ghost_moth: {
|
||||||
|
name: 'Ghost Moth',
|
||||||
|
rarity: 'epic',
|
||||||
|
habitat: ['haunted_forest'],
|
||||||
|
season: ['fall'],
|
||||||
|
time: 'night',
|
||||||
|
price: 1200,
|
||||||
|
catchDifficulty: 0.9,
|
||||||
|
description: 'Translucent white. Some say it carries souls...',
|
||||||
|
icon: '🦋'
|
||||||
|
},
|
||||||
|
crystal_dragonfly: {
|
||||||
|
name: 'Crystal Dragonfly',
|
||||||
|
rarity: 'epic',
|
||||||
|
habitat: ['crystal_cave'],
|
||||||
|
season: ['all'],
|
||||||
|
price: 1800,
|
||||||
|
catchDifficulty: 0.85,
|
||||||
|
description: 'Wings made of living crystal. Reflects light beautifully.',
|
||||||
|
icon: '🪰'
|
||||||
|
},
|
||||||
|
shadow_beetle: {
|
||||||
|
name: 'Shadow Beetle',
|
||||||
|
rarity: 'epic',
|
||||||
|
habitat: ['dark_forest', 'cave'],
|
||||||
|
season: ['all'],
|
||||||
|
time: 'night',
|
||||||
|
price: 1400,
|
||||||
|
catchDifficulty: 0.8,
|
||||||
|
description: 'Black as night. Nearly invisible in darkness.',
|
||||||
|
icon: '🪲'
|
||||||
|
},
|
||||||
|
|
||||||
|
// LEGENDARY BUGS (3000g-10000g)
|
||||||
|
phoenix_butterfly: {
|
||||||
|
name: 'Phoenix Butterfly',
|
||||||
|
rarity: 'legendary',
|
||||||
|
habitat: ['volcano'],
|
||||||
|
season: ['summer'],
|
||||||
|
price: 5000,
|
||||||
|
catchDifficulty: 0.95,
|
||||||
|
description: 'Wings glow like fire! Reborn from flames.',
|
||||||
|
icon: '🦋'
|
||||||
|
},
|
||||||
|
void_moth: {
|
||||||
|
name: 'Void Moth',
|
||||||
|
rarity: 'legendary',
|
||||||
|
habitat: ['void_dimension'],
|
||||||
|
season: ['all'],
|
||||||
|
time: 'night',
|
||||||
|
price: 10000,
|
||||||
|
catchDifficulty: 0.99,
|
||||||
|
description: 'Exists between dimensions. Touch opens portal to void.',
|
||||||
|
icon: '🦋'
|
||||||
|
},
|
||||||
|
celestial_beetle: {
|
||||||
|
name: 'Celestial Beetle',
|
||||||
|
rarity: 'legendary',
|
||||||
|
habitat: ['sky_island'],
|
||||||
|
season: ['all'],
|
||||||
|
price: 8000,
|
||||||
|
catchDifficulty: 0.97,
|
||||||
|
description: 'Shell contains entire constellations. Flies among stars.',
|
||||||
|
icon: '🪲'
|
||||||
|
},
|
||||||
|
time_cicada: {
|
||||||
|
name: 'Time Cicada',
|
||||||
|
rarity: 'legendary',
|
||||||
|
habitat: ['chrono_temple'],
|
||||||
|
season: ['all'],
|
||||||
|
price: 7500,
|
||||||
|
catchDifficulty: 0.96,
|
||||||
|
description: 'Exists outside of time. Emerges once per millennium.',
|
||||||
|
icon: '🪰'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
console.log('🦋 Bug Catching System initialized!');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Equip bug net
|
||||||
|
*/
|
||||||
|
equipBugNet(tier) {
|
||||||
|
if (!this.bugNets[tier]) {
|
||||||
|
return { success: false, message: 'Unknown net tier' };
|
||||||
|
}
|
||||||
|
|
||||||
|
this.currentNet = {
|
||||||
|
tier: tier,
|
||||||
|
...this.bugNets[tier]
|
||||||
|
};
|
||||||
|
|
||||||
|
console.log(`🦋 Equipped ${this.currentNet.name}!`);
|
||||||
|
|
||||||
|
this.scene.events.emit('notification', {
|
||||||
|
title: 'Bug Net Equipped!',
|
||||||
|
message: `${this.currentNet.name} ready!`,
|
||||||
|
icon: '🦋'
|
||||||
|
});
|
||||||
|
|
||||||
|
return { success: true };
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempt to catch a bug
|
||||||
|
*/
|
||||||
|
catchBug(bugId) {
|
||||||
|
if (!this.currentNet) {
|
||||||
|
return { success: false, message: 'No bug net equipped!' };
|
||||||
|
}
|
||||||
|
|
||||||
|
const bug = this.bugs[bugId];
|
||||||
|
if (!bug) {
|
||||||
|
return { success: false, message: 'Unknown bug' };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate catch chance
|
||||||
|
const netBonus = this.currentNet.catchRate;
|
||||||
|
const bugDifficulty = bug.catchDifficulty;
|
||||||
|
const catchChance = netBonus * (1 - bugDifficulty);
|
||||||
|
|
||||||
|
const roll = Math.random();
|
||||||
|
const caught = roll < catchChance;
|
||||||
|
|
||||||
|
if (caught) {
|
||||||
|
// Add to collection
|
||||||
|
if (!this.caughtBugs.has(bugId)) {
|
||||||
|
this.caughtBugs.set(bugId, 0);
|
||||||
|
}
|
||||||
|
this.caughtBugs.set(bugId, this.caughtBugs.get(bugId) + 1);
|
||||||
|
|
||||||
|
// First time catch
|
||||||
|
if (!this.bugAlbum.has(bugId)) {
|
||||||
|
this.bugAlbum.set(bugId, {
|
||||||
|
discoveredAt: new Date(),
|
||||||
|
timesСaught: 1
|
||||||
|
});
|
||||||
|
|
||||||
|
this.scene.events.emit('notification', {
|
||||||
|
title: 'NEW BUG!',
|
||||||
|
message: `${bug.icon} ${bug.name} added to album!`,
|
||||||
|
icon: '📔'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`🦋 Caught ${bug.name}!`);
|
||||||
|
|
||||||
|
this.scene.events.emit('notification', {
|
||||||
|
title: 'Bug Caught!',
|
||||||
|
message: `${bug.icon} ${bug.name} (+${bug.price}g)`,
|
||||||
|
icon: '✨'
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
bug: bug,
|
||||||
|
firstTime: !this.bugAlbum.has(bugId)
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
console.log(`❌ ${bug.name} escaped!`);
|
||||||
|
|
||||||
|
this.scene.events.emit('notification', {
|
||||||
|
title: 'Escaped!',
|
||||||
|
message: `${bug.name} got away!`,
|
||||||
|
icon: '💨'
|
||||||
|
});
|
||||||
|
|
||||||
|
return { success: false, message: 'Bug escaped!' };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sell bug
|
||||||
|
*/
|
||||||
|
sellBug(bugId, quantity = 1) {
|
||||||
|
const count = this.caughtBugs.get(bugId) || 0;
|
||||||
|
|
||||||
|
if (count < quantity) {
|
||||||
|
return { success: false, message: 'Not enough bugs to sell!' };
|
||||||
|
}
|
||||||
|
|
||||||
|
const bug = this.bugs[bugId];
|
||||||
|
const totalPrice = bug.price * quantity;
|
||||||
|
|
||||||
|
// Remove from inventory
|
||||||
|
this.caughtBugs.set(bugId, count - quantity);
|
||||||
|
|
||||||
|
// Give gold
|
||||||
|
if (this.scene.player) {
|
||||||
|
this.scene.player.gold += totalPrice;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`💰 Sold ${quantity}x ${bug.name} for ${totalPrice}g!`);
|
||||||
|
|
||||||
|
this.scene.events.emit('notification', {
|
||||||
|
title: 'Bugs Sold!',
|
||||||
|
message: `${quantity}x ${bug.name} = ${totalPrice}g`,
|
||||||
|
icon: '💰'
|
||||||
|
});
|
||||||
|
|
||||||
|
return { success: true, price: totalPrice };
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get collection stats
|
||||||
|
*/
|
||||||
|
getCollectionStats() {
|
||||||
|
const totalSpecies = Object.keys(this.bugs).length;
|
||||||
|
const discovered = this.bugAlbum.size;
|
||||||
|
const percentage = Math.round((discovered / totalSpecies) * 100);
|
||||||
|
|
||||||
|
return {
|
||||||
|
totalSpecies: totalSpecies,
|
||||||
|
discovered: discovered,
|
||||||
|
percentage: percentage,
|
||||||
|
byRarity: this.getByRarity()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get bugs by rarity
|
||||||
|
*/
|
||||||
|
getByRarity() {
|
||||||
|
const byRarity = {
|
||||||
|
common: { total: 0, caught: 0 },
|
||||||
|
uncommon: { total: 0, caught: 0 },
|
||||||
|
rare: { total: 0, caught: 0 },
|
||||||
|
epic: { total: 0, caught: 0 },
|
||||||
|
legendary: { total: 0, caught: 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const [bugId, bug] of Object.entries(this.bugs)) {
|
||||||
|
byRarity[bug.rarity].total++;
|
||||||
|
if (this.bugAlbum.has(bugId)) {
|
||||||
|
byRarity[bug.rarity].caught++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return byRarity;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Spawn bugs in world
|
||||||
|
*/
|
||||||
|
spawnBugs(biome, season, time, count = 5) {
|
||||||
|
const availableBugs = Object.entries(this.bugs)
|
||||||
|
.filter(([id, bug]) => {
|
||||||
|
// Check habitat
|
||||||
|
if (!bug.habitat.includes(biome) && !bug.habitat.includes('anywhere')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Check season
|
||||||
|
if (!bug.season.includes(season) && !bug.season.includes('all')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Check time
|
||||||
|
if (bug.time && bug.time !== time) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
const spawned = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < count; i++) {
|
||||||
|
if (availableBugs.length === 0) break;
|
||||||
|
|
||||||
|
const [bugId, bug] = availableBugs[Math.floor(Math.random() * availableBugs.length)];
|
||||||
|
|
||||||
|
const x = Math.random() * 800; // Map width
|
||||||
|
const y = Math.random() * 600; // Map height
|
||||||
|
|
||||||
|
spawned.push({
|
||||||
|
id: `bug_${Date.now()}_${i}`,
|
||||||
|
bugId: bugId,
|
||||||
|
x: x,
|
||||||
|
y: y,
|
||||||
|
active: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.activeBugs.push(...spawned);
|
||||||
|
|
||||||
|
console.log(`🦋 Spawned ${spawned.length} bugs in ${biome}`);
|
||||||
|
|
||||||
|
return spawned;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check collection completion bonuses
|
||||||
|
*/
|
||||||
|
checkCompletionBonus() {
|
||||||
|
const stats = this.getCollectionStats();
|
||||||
|
|
||||||
|
// 100% completion
|
||||||
|
if (stats.percentage === 100 && !this.completionBonusGiven) {
|
||||||
|
this.completionBonusGiven = true;
|
||||||
|
|
||||||
|
this.scene.events.emit('notification', {
|
||||||
|
title: '🎉 BUG MASTER!',
|
||||||
|
message: 'Completed entire bug collection! +10000g bonus!',
|
||||||
|
icon: '🏆'
|
||||||
|
});
|
||||||
|
|
||||||
|
if (this.scene.player) {
|
||||||
|
this.scene.player.gold += 10000;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
297
src/systems/MagicEnchantingSystem.js
Normal file
297
src/systems/MagicEnchantingSystem.js
Normal file
@@ -0,0 +1,297 @@
|
|||||||
|
/**
|
||||||
|
* MAGIC ENCHANTING SYSTEM
|
||||||
|
* Enhance tools with magical properties
|
||||||
|
*
|
||||||
|
* Features:
|
||||||
|
* - 5 Enchantment Types: Power, Speed, Fortune, Unbreaking, Auto-Collect
|
||||||
|
* - 3 Enchantment Levels per type
|
||||||
|
* - Costs mana + rare materials
|
||||||
|
* - Glowing visual effects
|
||||||
|
* - Can stack multiple enchantments
|
||||||
|
*/
|
||||||
|
class MagicEnchantingSystem {
|
||||||
|
constructor(scene) {
|
||||||
|
this.scene = scene;
|
||||||
|
|
||||||
|
// Enchantment definitions
|
||||||
|
this.enchantments = {
|
||||||
|
power: {
|
||||||
|
name: 'Power',
|
||||||
|
icon: '⚡',
|
||||||
|
description: 'Increases tool efficiency',
|
||||||
|
levels: [
|
||||||
|
{ level: 1, bonus: 0.25, cost: { mana: 50, crystal: 1 } },
|
||||||
|
{ level: 2, bonus: 0.50, cost: { mana: 100, crystal: 3 } },
|
||||||
|
{ level: 3, bonus: 1.00, cost: { mana: 200, crystal: 10 } }
|
||||||
|
],
|
||||||
|
color: 0xFF4444
|
||||||
|
},
|
||||||
|
speed: {
|
||||||
|
name: 'Speed',
|
||||||
|
icon: '⚡',
|
||||||
|
description: 'Increases tool speed',
|
||||||
|
levels: [
|
||||||
|
{ level: 1, bonus: 0.20, cost: { mana: 50, feather: 5 } },
|
||||||
|
{ level: 2, bonus: 0.40, cost: { mana: 100, feather: 15 } },
|
||||||
|
{ level: 3, bonus: 0.80, cost: { mana: 200, feather: 50 } }
|
||||||
|
],
|
||||||
|
color: 0x44FF44
|
||||||
|
},
|
||||||
|
fortune: {
|
||||||
|
name: 'Fortune',
|
||||||
|
icon: '💎',
|
||||||
|
description: 'Chance for double drops',
|
||||||
|
levels: [
|
||||||
|
{ level: 1, bonus: 0.15, cost: { mana: 75, emerald: 1 } },
|
||||||
|
{ level: 2, bonus: 0.30, cost: { mana: 150, emerald: 3 } },
|
||||||
|
{ level: 3, bonus: 0.50, cost: { mana: 300, emerald: 10 } }
|
||||||
|
],
|
||||||
|
color: 0x44FFFF
|
||||||
|
},
|
||||||
|
unbreaking: {
|
||||||
|
name: 'Unbreaking',
|
||||||
|
icon: '🛡️',
|
||||||
|
description: 'Reduces durability loss',
|
||||||
|
levels: [
|
||||||
|
{ level: 1, bonus: 0.30, cost: { mana: 60, obsidian: 5 } },
|
||||||
|
{ level: 2, bonus: 0.50, cost: { mana: 120, obsidian: 15 } },
|
||||||
|
{ level: 3, bonus: 0.75, cost: { mana: 250, obsidian: 50 } }
|
||||||
|
],
|
||||||
|
color: 0xFF44FF
|
||||||
|
},
|
||||||
|
auto_collect: {
|
||||||
|
name: 'Auto-Collect',
|
||||||
|
icon: '🌀',
|
||||||
|
description: 'Automatically collects drops',
|
||||||
|
levels: [
|
||||||
|
{ level: 1, bonus: 1.0, cost: { mana: 100, void_essence: 1 } },
|
||||||
|
{ level: 2, bonus: 2.0, cost: { mana: 200, void_essence: 3 } },
|
||||||
|
{ level: 3, bonus: 3.0, cost: { mana: 400, void_essence: 10 } }
|
||||||
|
],
|
||||||
|
color: 0x9D4EDD
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Enchanting table locations (town)
|
||||||
|
this.enchantingTables = [];
|
||||||
|
|
||||||
|
console.log('✨ Magic Enchanting System initialized');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enchant a tool
|
||||||
|
*/
|
||||||
|
enchantTool(toolId, enchantmentType, level = 1) {
|
||||||
|
const toolSystem = this.scene.toolSystem;
|
||||||
|
if (!toolSystem) {
|
||||||
|
return { success: false, message: 'Tool system not available' };
|
||||||
|
}
|
||||||
|
|
||||||
|
const tool = toolSystem.playerTools.get(toolId);
|
||||||
|
if (!tool) {
|
||||||
|
return { success: false, message: 'Tool not found' };
|
||||||
|
}
|
||||||
|
|
||||||
|
const enchantment = this.enchantments[enchantmentType];
|
||||||
|
if (!enchantment) {
|
||||||
|
return { success: false, message: 'Unknown enchantment' };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (level < 1 || level > 3) {
|
||||||
|
return { success: false, message: 'Invalid enchantment level' };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if tool already has this enchantment
|
||||||
|
if (!tool.enchantments) {
|
||||||
|
tool.enchantments = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tool.enchantments[enchantmentType]) {
|
||||||
|
return { success: false, message: 'Tool already has this enchantment!' };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get cost
|
||||||
|
const levelData = enchantment.levels[level - 1];
|
||||||
|
const cost = levelData.cost;
|
||||||
|
|
||||||
|
// Check mana
|
||||||
|
if (this.scene.player && this.scene.player.mana < cost.mana) {
|
||||||
|
return { success: false, message: `Need ${cost.mana} mana!` };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check materials (simplified - would check inventory)
|
||||||
|
const canAfford = true; // TODO: Check inventory
|
||||||
|
|
||||||
|
if (!canAfford) {
|
||||||
|
return { success: false, message: 'Not enough materials!' };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply enchantment
|
||||||
|
tool.enchantments[enchantmentType] = {
|
||||||
|
level: level,
|
||||||
|
bonus: levelData.bonus,
|
||||||
|
color: enchantment.color
|
||||||
|
};
|
||||||
|
|
||||||
|
// Deduct mana
|
||||||
|
if (this.scene.player) {
|
||||||
|
this.scene.player.mana -= cost.mana;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply bonus to tool stats
|
||||||
|
this.applyEnchantmentBonus(tool, enchantmentType, levelData.bonus);
|
||||||
|
|
||||||
|
console.log(`✨ Enchanted ${tool.name} with ${enchantment.name} ${level}!`);
|
||||||
|
|
||||||
|
this.scene.events.emit('notification', {
|
||||||
|
title: 'Tool Enchanted!',
|
||||||
|
message: `${enchantment.icon} ${enchantment.name} ${level} applied!`,
|
||||||
|
icon: '✨'
|
||||||
|
});
|
||||||
|
|
||||||
|
return { success: true, enchantment: enchantmentType, level: level };
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply enchantment bonus to tool
|
||||||
|
*/
|
||||||
|
applyEnchantmentBonus(tool, type, bonus) {
|
||||||
|
switch (type) {
|
||||||
|
case 'power':
|
||||||
|
tool.efficiency += bonus;
|
||||||
|
break;
|
||||||
|
case 'speed':
|
||||||
|
tool.speed += bonus;
|
||||||
|
break;
|
||||||
|
case 'fortune':
|
||||||
|
tool.fortuneChance = bonus;
|
||||||
|
break;
|
||||||
|
case 'unbreaking':
|
||||||
|
tool.durabilityMultiplier = 1 - bonus; // 30% less durability loss
|
||||||
|
break;
|
||||||
|
case 'auto_collect':
|
||||||
|
tool.autoCollect = true;
|
||||||
|
tool.autoCollectRadius = bonus;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove enchantment (costs mana)
|
||||||
|
*/
|
||||||
|
removeEnchantment(toolId, enchantmentType) {
|
||||||
|
const toolSystem = this.scene.toolSystem;
|
||||||
|
const tool = toolSystem.playerTools.get(toolId);
|
||||||
|
|
||||||
|
if (!tool || !tool.enchantments || !tool.enchantments[enchantmentType]) {
|
||||||
|
return { success: false, message: 'Enchantment not found' };
|
||||||
|
}
|
||||||
|
|
||||||
|
const cost = 25; // Mana cost to remove
|
||||||
|
|
||||||
|
if (this.scene.player && this.scene.player.mana >= cost) {
|
||||||
|
this.scene.player.mana -= cost;
|
||||||
|
|
||||||
|
// Remove bonus
|
||||||
|
const enchantData = tool.enchantments[enchantmentType];
|
||||||
|
this.removeEnchantmentBonus(tool, enchantmentType, enchantData.bonus);
|
||||||
|
|
||||||
|
delete tool.enchantments[enchantmentType];
|
||||||
|
|
||||||
|
console.log(`🔮 Removed enchantment from ${tool.name}`);
|
||||||
|
|
||||||
|
return { success: true };
|
||||||
|
}
|
||||||
|
|
||||||
|
return { success: false, message: 'Not enough mana' };
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove enchantment bonus from tool
|
||||||
|
*/
|
||||||
|
removeEnchantmentBonus(tool, type, bonus) {
|
||||||
|
switch (type) {
|
||||||
|
case 'power':
|
||||||
|
tool.efficiency -= bonus;
|
||||||
|
break;
|
||||||
|
case 'speed':
|
||||||
|
tool.speed -= bonus;
|
||||||
|
break;
|
||||||
|
case 'fortune':
|
||||||
|
tool.fortuneChance = 0;
|
||||||
|
break;
|
||||||
|
case 'unbreaking':
|
||||||
|
tool.durabilityMultiplier = 1.0;
|
||||||
|
break;
|
||||||
|
case 'auto_collect':
|
||||||
|
tool.autoCollect = false;
|
||||||
|
tool.autoCollectRadius = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all enchantments on a tool
|
||||||
|
*/
|
||||||
|
getToolEnchantments(toolId) {
|
||||||
|
const toolSystem = this.scene.toolSystem;
|
||||||
|
const tool = toolSystem.playerTools.get(toolId);
|
||||||
|
|
||||||
|
if (!tool || !tool.enchantments) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const enchantments = [];
|
||||||
|
for (const [type, data] of Object.entries(tool.enchantments)) {
|
||||||
|
const enchant = this.enchantments[type];
|
||||||
|
enchantments.push({
|
||||||
|
type: type,
|
||||||
|
name: enchant.name,
|
||||||
|
level: data.level,
|
||||||
|
bonus: data.bonus,
|
||||||
|
icon: enchant.icon,
|
||||||
|
color: data.color
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return enchantments;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build enchanting table in town
|
||||||
|
*/
|
||||||
|
buildEnchantingTable(x, y) {
|
||||||
|
const table = {
|
||||||
|
id: `enchanting_${Date.now()}`,
|
||||||
|
x: x,
|
||||||
|
y: y,
|
||||||
|
type: 'enchanting_table',
|
||||||
|
active: true
|
||||||
|
};
|
||||||
|
|
||||||
|
this.enchantingTables.push(table);
|
||||||
|
|
||||||
|
console.log(`✨ Built Enchanting Table at (${x}, ${y})`);
|
||||||
|
|
||||||
|
this.scene.events.emit('notification', {
|
||||||
|
title: 'Enchanting Table Built!',
|
||||||
|
message: 'You can now enchant your tools!',
|
||||||
|
icon: '✨'
|
||||||
|
});
|
||||||
|
|
||||||
|
return table;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if near enchanting table
|
||||||
|
*/
|
||||||
|
isNearEnchantingTable(x, y, radius = 3) {
|
||||||
|
for (const table of this.enchantingTables) {
|
||||||
|
const distance = Phaser.Math.Distance.Between(x, y, table.x, table.y);
|
||||||
|
if (distance <= radius) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
166
tools/asset_backend.py
Executable file
166
tools/asset_backend.py
Executable file
@@ -0,0 +1,166 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Asset Manager Backend API
|
||||||
|
Enables actual file deletion and re-generation
|
||||||
|
"""
|
||||||
|
|
||||||
|
from flask import Flask, jsonify, request
|
||||||
|
from flask_cors import CORS
|
||||||
|
import os
|
||||||
|
import json
|
||||||
|
import subprocess
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
app = Flask(__name__)
|
||||||
|
CORS(app) # Enable CORS for localhost requests
|
||||||
|
|
||||||
|
# Paths
|
||||||
|
PROJECT_ROOT = Path(__file__).parent.parent
|
||||||
|
MANIFEST_PATH = PROJECT_ROOT / "tools" / "asset_manifest.json"
|
||||||
|
GENERATOR_SCRIPT = PROJECT_ROOT / "scripts" / "generate_asset_manifest.py"
|
||||||
|
|
||||||
|
def load_manifest():
|
||||||
|
"""Load the asset manifest"""
|
||||||
|
with open(MANIFEST_PATH, 'r') as f:
|
||||||
|
return json.load(f)
|
||||||
|
|
||||||
|
def save_manifest(manifest):
|
||||||
|
"""Save the asset manifest"""
|
||||||
|
with open(MANIFEST_PATH, 'w') as f:
|
||||||
|
json.dump(manifest, f, indent=2, ensure_ascii=False)
|
||||||
|
|
||||||
|
def regenerate_manifest():
|
||||||
|
"""Regenerate manifest by running the generator script"""
|
||||||
|
try:
|
||||||
|
result = subprocess.run(
|
||||||
|
['python3', str(GENERATOR_SCRIPT)],
|
||||||
|
cwd=str(PROJECT_ROOT),
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
timeout=30
|
||||||
|
)
|
||||||
|
return result.returncode == 0
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error regenerating manifest: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
@app.route('/api/health', methods=['GET'])
|
||||||
|
def health():
|
||||||
|
"""Health check endpoint"""
|
||||||
|
return jsonify({"status": "ok", "message": "Asset Backend API is running"})
|
||||||
|
|
||||||
|
@app.route('/api/assets', methods=['GET'])
|
||||||
|
def get_assets():
|
||||||
|
"""Get all assets from manifest"""
|
||||||
|
manifest = load_manifest()
|
||||||
|
return jsonify(manifest)
|
||||||
|
|
||||||
|
@app.route('/api/asset/<asset_id>', methods=['DELETE'])
|
||||||
|
def delete_asset(asset_id):
|
||||||
|
"""Delete an asset file"""
|
||||||
|
try:
|
||||||
|
# Load manifest
|
||||||
|
manifest = load_manifest()
|
||||||
|
|
||||||
|
# Find asset
|
||||||
|
asset = None
|
||||||
|
for a in manifest['assets']:
|
||||||
|
if a['id'] == asset_id:
|
||||||
|
asset = a
|
||||||
|
break
|
||||||
|
|
||||||
|
if not asset:
|
||||||
|
return jsonify({"success": False, "error": "Asset not found"}), 404
|
||||||
|
|
||||||
|
# Get file path (remove ../ prefix since we're in project root)
|
||||||
|
file_path = asset['path'].replace('../', '')
|
||||||
|
full_path = PROJECT_ROOT / file_path
|
||||||
|
|
||||||
|
# Check if file exists
|
||||||
|
if not full_path.exists():
|
||||||
|
return jsonify({"success": False, "error": "File not found on disk"}), 404
|
||||||
|
|
||||||
|
# Delete file
|
||||||
|
full_path.unlink()
|
||||||
|
print(f"✅ Deleted: {full_path}")
|
||||||
|
|
||||||
|
# Regenerate manifest
|
||||||
|
if regenerate_manifest():
|
||||||
|
return jsonify({
|
||||||
|
"success": True,
|
||||||
|
"message": f"Asset {asset['name']} deleted successfully",
|
||||||
|
"deleted_file": str(file_path)
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
return jsonify({
|
||||||
|
"success": False,
|
||||||
|
"error": "File deleted but manifest regeneration failed"
|
||||||
|
}), 500
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
return jsonify({"success": False, "error": str(e)}), 500
|
||||||
|
|
||||||
|
@app.route('/api/asset/<asset_id>/reroll', methods=['POST'])
|
||||||
|
def reroll_asset(asset_id):
|
||||||
|
"""Re-generate an asset (placeholder for now)"""
|
||||||
|
try:
|
||||||
|
manifest = load_manifest()
|
||||||
|
|
||||||
|
# Find asset
|
||||||
|
asset = None
|
||||||
|
for a in manifest['assets']:
|
||||||
|
if a['id'] == asset_id:
|
||||||
|
asset = a
|
||||||
|
break
|
||||||
|
|
||||||
|
if not asset:
|
||||||
|
return jsonify({"success": False, "error": "Asset not found"}), 404
|
||||||
|
|
||||||
|
# TODO: Implement actual image generation
|
||||||
|
# For now, return placeholder response
|
||||||
|
return jsonify({
|
||||||
|
"success": True,
|
||||||
|
"message": f"Re-roll requested for {asset['name']}",
|
||||||
|
"note": "Image generation not yet implemented. Delete old image and regenerate manually.",
|
||||||
|
"asset": asset
|
||||||
|
})
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
return jsonify({"success": False, "error": str(e)}), 500
|
||||||
|
|
||||||
|
@app.route('/api/manifest/regenerate', methods=['POST'])
|
||||||
|
def regenerate():
|
||||||
|
"""Manually trigger manifest regeneration"""
|
||||||
|
try:
|
||||||
|
if regenerate_manifest():
|
||||||
|
manifest = load_manifest()
|
||||||
|
return jsonify({
|
||||||
|
"success": True,
|
||||||
|
"message": "Manifest regenerated successfully",
|
||||||
|
"total_assets": manifest['total_assets']
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
return jsonify({
|
||||||
|
"success": False,
|
||||||
|
"error": "Manifest regeneration failed"
|
||||||
|
}), 500
|
||||||
|
except Exception as e:
|
||||||
|
return jsonify({"success": False, "error": str(e)}), 500
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
print("🚀 Asset Manager Backend API")
|
||||||
|
print("="*60)
|
||||||
|
print(f"Project Root: {PROJECT_ROOT}")
|
||||||
|
print(f"Manifest: {MANIFEST_PATH}")
|
||||||
|
print(f"Generator: {GENERATOR_SCRIPT}")
|
||||||
|
print("="*60)
|
||||||
|
print("Starting server on http://localhost:5001")
|
||||||
|
print("Endpoints:")
|
||||||
|
print(" GET /api/health - Health check")
|
||||||
|
print(" GET /api/assets - Get all assets")
|
||||||
|
print(" DELETE /api/asset/<id> - Delete asset")
|
||||||
|
print(" POST /api/asset/<id>/reroll - Re-generate asset")
|
||||||
|
print(" POST /api/manifest/regenerate - Regenerate manifest")
|
||||||
|
print("="*60)
|
||||||
|
|
||||||
|
app.run(debug=True, port=5001)
|
||||||
File diff suppressed because it is too large
Load Diff
2
tools/requirements.txt
Normal file
2
tools/requirements.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
Flask==3.0.0
|
||||||
|
flask-cors==4.0.0
|
||||||
@@ -674,29 +674,68 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function deleteAsset(id) {
|
function deleteAsset(id) {
|
||||||
if (!confirm('Res želiš izbrisati ta asset?')) return;
|
const asset = allAssets.find(a => a.id === id);
|
||||||
|
if (!asset) return;
|
||||||
|
|
||||||
|
if (!confirm(`Res želiš trajno izbrisati:\n${asset.name}\n\nDatoteka bo fizično izbrisana iz diska!`)) return;
|
||||||
|
|
||||||
showLoading();
|
showLoading();
|
||||||
setTimeout(() => {
|
|
||||||
|
// Call backend API
|
||||||
|
fetch(`http://localhost:5001/api/asset/${id}`, {
|
||||||
|
method: 'DELETE'
|
||||||
|
})
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
hideLoading();
|
hideLoading();
|
||||||
showToast('✅ Asset izbrisan!');
|
if (data.success) {
|
||||||
// Remove from array and re-render
|
showToast(`✅ ${asset.name} izbrisan!`);
|
||||||
allAssets = allAssets.filter(a => a.id !== id);
|
// Reload assets from updated manifest
|
||||||
renderGallery(allAssets);
|
setTimeout(() => {
|
||||||
}, 1000);
|
loadAssets().then(() => {
|
||||||
|
applyFilters();
|
||||||
|
});
|
||||||
|
}, 500);
|
||||||
|
} else {
|
||||||
|
showToast(`❌ Napaka: ${data.error}`);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
hideLoading();
|
||||||
|
showToast(`❌ Backend error: ${error.message}`);
|
||||||
|
console.error('Delete error:', error);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function rerollAsset(id) {
|
function rerollAsset(id) {
|
||||||
const asset = allAssets.find(a => a.id === id);
|
const asset = allAssets.find(a => a.id === id);
|
||||||
if (!asset) return;
|
if (!asset) return;
|
||||||
|
|
||||||
if (!confirm(`Re-generate "${asset.name}" z novim promptom?`)) return;
|
if (!confirm(`Re-generate "${asset.name}" z novim promptom?\n\n(Not yet fully implemented)`)) return;
|
||||||
|
|
||||||
showLoading();
|
showLoading();
|
||||||
setTimeout(() => {
|
|
||||||
|
// Call backend API
|
||||||
|
fetch(`http://localhost:5001/api/asset/${id}/reroll`, {
|
||||||
|
method: 'POST'
|
||||||
|
})
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
hideLoading();
|
hideLoading();
|
||||||
showToast('🎨 Asset re-generiran!');
|
if (data.success) {
|
||||||
}, 2000);
|
showToast(`🎨 ${data.message}`);
|
||||||
|
if (data.note) {
|
||||||
|
alert(data.note);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
showToast(`❌ Napaka: ${data.error}`);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
hideLoading();
|
||||||
|
showToast(`❌ Backend error: ${error.message}`);
|
||||||
|
console.error('Re-roll error:', error);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bulk actions
|
// Bulk actions
|
||||||
|
|||||||
Reference in New Issue
Block a user