MAJOR UPDATE: DrugEconomySystem (marijuana slow-mo/chill + mushroom hallucinations), CourierSystem (hearts/material rewards), updated CHARACTER_DESIGN_GUIDELINES to EXTREMIST standard (mandatory colored hair/massive plugs), added ROADMAP sections for City Evolution (Vape Factory@50pop), Drug Effects, Courier Missions. All systems integrated with quest/reward mechanics.
This commit is contained in:
@@ -1,35 +1,45 @@
|
||||
# 🎨 CHARACTER DESIGN GUIDELINES - Mrtva Dolina
|
||||
**Style:** Post-Apocalyptic Punk (Style 32 Dark-Chibi Noir)
|
||||
**Last Updated:** 2026-01-05 14:04 CET
|
||||
**Style:** Post-Apocalyptic EXTREMIST Punk (Style 32 Dark-Chibi Noir)
|
||||
**Last Updated:** 2026-01-05 14:19 CET
|
||||
**Standard:** EXTREMIST - Maximum punk aesthetic
|
||||
|
||||
---
|
||||
|
||||
## 🔥 **ZAŠČITNI ZNAK - Punk Aesthetic**
|
||||
## 🔥 **ZAŠČITNI ZNAK - EXTREMIST Punk Aesthetic**
|
||||
|
||||
**POMEMBNO:** Ne delaj preveč normalnih ljudi! Post-apokalipsa = punk survival look.
|
||||
**KRITIČNO:** NI normalnih ljudi! VSI morajo biti extreme punk survivors!
|
||||
|
||||
### **Core Features (Mix & Match)**
|
||||
NPC-ji naj imajo **raznolike kombinacije** teh elementov, ne vsi vse:
|
||||
### **MANDATORY Features (All NPCs)**
|
||||
|
||||
#### **Pirsinge** 🔩
|
||||
- Nos ring
|
||||
#### **Pirsinge** 🔩 - **ZAŽELENI PRI VSEH**
|
||||
- Nos ring (very common)
|
||||
- Lip ring
|
||||
- Eyebrow piercing
|
||||
- Multiple ear piercings
|
||||
- **Ne rabijo vsi!** En NPC lahko ima samo 1 piercing
|
||||
- **Minimum:** Vsak NPC naj ima vsaj 2+ piercings
|
||||
|
||||
#### **Ear Gauges** 👂
|
||||
- Razširjena ušesa (stretched ear lobes)
|
||||
- Različne velikosti (majhni do veliki)
|
||||
- Opcijsko - ni mandatory
|
||||
#### **Ear Plugs/Gauges** 👂 - **VARIABLE MASSIVE SIZES**
|
||||
- Razširjena ušesa (stretched ear lobes) - **ZAŽELENI**
|
||||
- **Velikost variira:**
|
||||
- Small plugs (5mm)
|
||||
- Medium plugs (10-15mm)
|
||||
- **MASSIVE plugs (20-30mm+)** ← Lahko tudi ekstremni!
|
||||
- **Stil:** Metal rings, wooden plugs, decorative tunnels
|
||||
|
||||
#### **LASJE - OBVEZNO POBARVANI** 💈
|
||||
**NOVA PRAVILA:**
|
||||
- **ČE NIMA DREADOV → LASE OBVEZNO POBARVAJ!**
|
||||
- **Barve:** Neon zelena, pink, modra, purple, orange, red
|
||||
- **NO natural colors** (črna/rjava dovoljena SAMO z dreads)
|
||||
- **Kombinacije:** Rainbow, two-tone, highlights
|
||||
|
||||
#### **Dreadlokse** 🌿
|
||||
- **VARIACIJE:**
|
||||
- Full head dreads (kot Kai, Gronk)
|
||||
- **Partial dreads:** Ubrita glava z 6 dredloksi odzadi
|
||||
- **Colored dreads:** Pink, green, purple, gray
|
||||
- **Colored dreads:** Pink, green, purple, gray (MANDATORY COLOR)
|
||||
- Kratki vs. dolgi
|
||||
- **Ne rabijo vsi!** Lahko ima NPC samo normalne lase
|
||||
- **ALI ima dreads ALI pobarvane lase (ne plain)**
|
||||
|
||||
#### **Tatuji** 🖋️
|
||||
- Neck tattoos
|
||||
|
||||
@@ -279,6 +279,58 @@
|
||||
|
||||
---
|
||||
|
||||
## 🏙️ **CITY EVOLUTION & POPULATION MILESTONES**
|
||||
|
||||
| Milestone | Population | Unlock | Priority | Status |
|
||||
|-----------|------------|--------|----------|--------|
|
||||
| **Election System** | 5 NPCs | Volitve za Župana, Social Order | ⭐⭐⭐⭐⭐ | ✅ Implemented |
|
||||
| **Zombie Economy** | 10 NPCs | Worker Zombies, Sanitation | ⭐⭐⭐⭐ | ✅ Implemented |
|
||||
| **Vape Factory** | **50 NPCs** | First major industrial building | ⭐⭐⭐⭐ | 🔴 Planned (Faza 3) |
|
||||
| **Police Force** | 75 NPCs | Drug trade becomes illegal/risky | ⭐⭐⭐⭐ | 🔴 Planned |
|
||||
| **Full Infrastructure** | 100 NPCs | All systems unlocked | ⭐⭐⭐⭐⭐ | 🔴 Future |
|
||||
|
||||
### **Vape Factory (Faza 3 - Industrija)**
|
||||
- **Unlock:** 50 residents in Capital City
|
||||
- **Requirements:** Rare chemicals from ruins (Tehnik processing)
|
||||
- **Features:** Custom liquid crafting, mod building
|
||||
- **Workforce:** Delovni Zombiji + Tehnik supervision
|
||||
|
||||
---
|
||||
|
||||
## 🌿 **SOCIAL & ECONOMY SYSTEMS**
|
||||
|
||||
### **Drug Effects & Illegal Trade**
|
||||
|
||||
| System | Features | Priority | Status |
|
||||
|--------|----------|----------|--------|
|
||||
| **Marijuana Effects** | Slow-mo, chill music, energy regen +100%, -15% walk speed | ⭐⭐⭐⭐ | ✅ Implemented |
|
||||
| **Mushroom Hallucinations** | Psychedelic shader, moving objects, ghost visions, reality warps | ⭐⭐⭐⭐ | ✅ Implemented |
|
||||
| **Black Market Trade** | Free trade until police established (30% bust risk after) | ⭐⭐⭐⭐ | ✅ Implemented |
|
||||
| **Crop Systems** | Cannabis & magic mushroom farming | ⭐⭐⭐⭐ | 🟡 In progress |
|
||||
|
||||
**Psychedelic Visual Effects:**
|
||||
- **Marijuana:** Subtle blur, light green tint, chill lo-fi music
|
||||
- **Mushrooms:** Color cycling, object movement, ghost NPCs, camera distortion
|
||||
|
||||
### **Courier Mission System**
|
||||
|
||||
| Feature | Details | Priority | Status |
|
||||
|---------|---------|----------|--------|
|
||||
| **Delivery Quests** | Random NPC requests for materials (wheat, water, glass, steel) | ⭐⭐⭐⭐ | ✅ Implemented |
|
||||
| **Hearts Reward** | Social Status increases (+5% per heart) | ⭐⭐⭐⭐ | ✅ Implemented |
|
||||
| **Material Reward** | Random loot from pools (common/uncommon/rare) | ⭐⭐⭐⭐ | ✅ Implemented |
|
||||
| **Social Benefits** | Shop discounts, priority quests, VIP access | ⭐⭐⭐ | ✅ Implemented |
|
||||
| **Quest Expiration** | 10-minute timer per delivery | ⭐⭐⭐ | ✅ Implemented |
|
||||
|
||||
**Social Status Tiers:**
|
||||
- 20%: 5% shop discount
|
||||
- 40%: Priority quests
|
||||
- 60%: VIP area access
|
||||
- 80%: +10% rare gift chance
|
||||
- 100%: Maximum respect
|
||||
|
||||
---
|
||||
|
||||
## 📝 NOTES
|
||||
|
||||
**Design Philosophy:**
|
||||
|
||||
337
src/systems/CourierSystem.js
Normal file
337
src/systems/CourierSystem.js
Normal file
@@ -0,0 +1,337 @@
|
||||
/**
|
||||
* COURIER & DELIVERY SYSTEM
|
||||
* Mrtva Dolina - Side-Quest Material Deliveries
|
||||
*
|
||||
* Features:
|
||||
* - Random delivery quests from NPCs
|
||||
* - Rewards: Hearts (social status) OR random materials
|
||||
* - Material types: wheat, water, glass, steel, wood, plastic
|
||||
* - Reputation system
|
||||
*/
|
||||
|
||||
export class CourierSystem {
|
||||
constructor(scene) {
|
||||
this.scene = scene;
|
||||
|
||||
// Social status (hearts)
|
||||
this.socialStatus = 0; // 0-100
|
||||
this.hearts = 0; // Visual hearts earned
|
||||
|
||||
// Active courier quests
|
||||
this.activeDeliveries = [];
|
||||
|
||||
// NPC delivery requests database
|
||||
this.deliveryTemplates = [
|
||||
// PEK
|
||||
{ npc: 'pek', item: 'wheat', quantity: [5, 10], reward: { type: 'hearts', amount: 2 }, message: 'Rabim pšenico za kruh!' },
|
||||
{ npc: 'pek', item: 'water', quantity: [3, 5], reward: { type: 'material', pool: ['wood', 'stone'] }, message: 'Dej mi vodo, pa ti dam material!' },
|
||||
|
||||
// ŠIVILJA
|
||||
{ npc: 'sivilja', item: 'cloth', quantity: [10, 20], reward: { type: 'hearts', amount: 3 }, message: 'Material rabim za šivanje, prosim!' },
|
||||
{
|
||||
npc: 'sivilja', item: 'water', quantity: [2, 4], reward: { type: 'material', pool: ['cloth', 'leather'] }, message: 'Vodo za barv
|
||||
|
||||
anje potrebujem!' },
|
||||
|
||||
// TEHNIK
|
||||
{ npc: 'tehnik', item: 'glass', quantity: [3, 7], reward: { type: 'hearts', amount: 4 }, message: 'Steklo za elektroniko!' },
|
||||
{ npc: 'tehnik', item: 'steel', quantity: [5, 10], reward: { type: 'material', pool: ['circuit_board', 'wire'] }, message: 'Jeklo za stroje!' },
|
||||
|
||||
// IVAN KOVAČ
|
||||
{ npc: 'ivan_kovac', item: 'steel', quantity: [8, 15], reward: { type: 'hearts', amount: 3 }, message: 'Potrebujem jeklo za kovačijo!' },
|
||||
{ npc: 'ivan_kovac', item: 'wood', quantity: [10, 20], reward: { type: 'material', pool: ['steel', 'iron_ore'] }, message: 'Les za oglje!' },
|
||||
|
||||
// KUSTOS
|
||||
{ npc: 'kustos', item: 'glass', quantity: [2, 5], reward: { type: 'hearts', amount: 2 }, message: 'Steklo za razstavne omare!' },
|
||||
{ npc: 'kustos', item: 'rare_artifact', quantity: [1, 1], reward: { type: 'material', pool: ['ancient_relic', 'museum_piece'] }, message: 'Artefakt za muzejsko zbirko!' },
|
||||
|
||||
// SMETAR
|
||||
{ npc: 'glavni_smetar', item: 'plastic', quantity: [15, 30], reward: { type: 'hearts', amount: 1 }, message: 'Plastiko moram zbrat iz ruševin!' },
|
||||
{ npc: 'glavni_smetar', item: 'wood', quantity: [5, 10], reward: { type: 'material', pool: ['broom', 'cleaning_supplies'] }, message: 'Les za nove metle!' }
|
||||
];
|
||||
|
||||
// Material loot pools
|
||||
this.materialPools = {
|
||||
common: ['wood', 'stone', 'plastic', 'water'],
|
||||
uncommon: ['steel', 'glass', 'cloth', 'leather'],
|
||||
rare: ['circuit_board', 'wire', 'ancient_relic', 'museum_piece']
|
||||
};
|
||||
|
||||
this.init();
|
||||
}
|
||||
|
||||
init() {
|
||||
// Start quest generation
|
||||
this.startQuestGeneration();
|
||||
|
||||
// Listen for delivery completions
|
||||
this.scene.events.on('courier:delivery_complete', this.onDeliveryComplete, this);
|
||||
|
||||
console.log('✅ CourierSystem initialized - Side-quests active');
|
||||
}
|
||||
|
||||
/**
|
||||
* QUEST GENERATION
|
||||
*/
|
||||
startQuestGeneration() {
|
||||
// Generate random delivery quest every 2-5 minutes
|
||||
const generateQuest = () => {
|
||||
if (this.activeDeliveries.length < 5) { // Max 5 active
|
||||
this.generateDeliveryQuest();
|
||||
}
|
||||
|
||||
// Schedule next generation
|
||||
const nextTime = Phaser.Math.Between(120000, 300000); // 2-5 minutes
|
||||
setTimeout(generateQuest, nextTime);
|
||||
};
|
||||
|
||||
// Start initial quest immediately
|
||||
generateQuest();
|
||||
}
|
||||
|
||||
generateDeliveryQuest() {
|
||||
const template = Phaser.Utils.Array.GetRandom(this.deliveryTemplates);
|
||||
|
||||
const quest = {
|
||||
id: `delivery_${Date.now()}`,
|
||||
npc: template.npc,
|
||||
item: template.item,
|
||||
quantity: Phaser.Math.Between(template.quantity[0], template.quantity[1]),
|
||||
reward: template.reward,
|
||||
message: template.message,
|
||||
timeCreated: Date.now(),
|
||||
expiresIn: 600000, // 10 minutes
|
||||
completed: false
|
||||
};
|
||||
|
||||
this.activeDeliveries.push(quest);
|
||||
|
||||
// Notify player
|
||||
this.scene.events.emit('show-notification', {
|
||||
title: '📦 Nova Dostava',
|
||||
message: `${template.npc}: ${template.message}`,
|
||||
icon: '📬',
|
||||
duration: 5000,
|
||||
color: '#FFD700'
|
||||
});
|
||||
|
||||
// Show on NPC
|
||||
this.scene.events.emit('npc:show_quest_marker', template.npc);
|
||||
|
||||
console.log(`📦 New delivery quest: ${template.npc} needs ${quest.quantity}x ${quest.item}`);
|
||||
|
||||
return quest;
|
||||
}
|
||||
|
||||
/**
|
||||
* ACCEPT DELIVERY QUEST
|
||||
*/
|
||||
acceptQuest(questId) {
|
||||
const quest = this.activeDeliveries.find(q => q.id === questId);
|
||||
if (!quest) return false;
|
||||
|
||||
quest.accepted = true;
|
||||
|
||||
// Add to player's active quest log
|
||||
if (this.scene.questSystem) {
|
||||
this.scene.questSystem.startQuest(questId);
|
||||
}
|
||||
|
||||
console.log(`✅ Accepted delivery quest: ${questId}`);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* DELIVER ITEMS
|
||||
*/
|
||||
deliverItems(questId) {
|
||||
const quest = this.activeDeliveries.find(q => q.id === questId);
|
||||
if (!quest || quest.completed) return false;
|
||||
|
||||
// Check if player has items
|
||||
if (!this.scene.inventorySystem.hasItem(quest.item, quest.quantity)) {
|
||||
this.scene.events.emit('show-notification', {
|
||||
title: '❌ Ni dovolj',
|
||||
message: `Rabiš še ${quest.quantity}x ${quest.item}!`,
|
||||
icon: '📦',
|
||||
duration: 3000,
|
||||
color: '#FF4444'
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remove items from inventory
|
||||
this.scene.inventorySystem.removeItem(quest.item, quest.quantity);
|
||||
|
||||
// Mark as complete
|
||||
quest.completed = true;
|
||||
|
||||
// Award reward
|
||||
this.awardReward(quest.reward);
|
||||
|
||||
// Remove from active
|
||||
this.activeDeliveries = this.activeDeliveries.filter(q => q.id !== questId);
|
||||
|
||||
// Notify completion
|
||||
this.scene.events.emit('show-notification', {
|
||||
title: '✅ Dostava Končana',
|
||||
message: `${quest.npc} je zadovoljen!`,
|
||||
icon: '🎉',
|
||||
duration: 4000,
|
||||
color: '#00FF00'
|
||||
});
|
||||
|
||||
// Remove quest marker
|
||||
this.scene.events.emit('npc:remove_quest_marker', quest.npc);
|
||||
|
||||
console.log(`✅ Delivery completed: ${questId}`);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* AWARD REWARD
|
||||
*/
|
||||
awardReward(reward) {
|
||||
if (reward.type === 'hearts') {
|
||||
this.addHearts(reward.amount);
|
||||
} else if (reward.type === 'material') {
|
||||
this.awardRandomMaterial(reward.pool);
|
||||
}
|
||||
}
|
||||
|
||||
addHearts(amount) {
|
||||
this.hearts += amount;
|
||||
this.socialStatus = Math.min(100, this.socialStatus + (amount * 5));
|
||||
|
||||
// Visual heart animation
|
||||
for (let i = 0; i < amount; i++) {
|
||||
setTimeout(() => {
|
||||
this.spawnHeart();
|
||||
}, i * 300);
|
||||
}
|
||||
|
||||
// Show status update
|
||||
this.scene.events.emit('show-floating-text', {
|
||||
x: this.scene.player.x,
|
||||
y: this.scene.player.y - 50,
|
||||
text: `+${amount} ❤️`,
|
||||
color: '#FF69B4',
|
||||
fontSize: '32px'
|
||||
});
|
||||
|
||||
console.log(`❤️ +${amount} hearts (Total: ${this.hearts}, Status: ${this.socialStatus}%)`);
|
||||
}
|
||||
|
||||
spawnHeart() {
|
||||
const heart = this.scene.add.sprite(
|
||||
this.scene.player.x + Phaser.Math.Between(-30, 30),
|
||||
this.scene.player.y - 50,
|
||||
'heart_icon'
|
||||
);
|
||||
heart.setScale(0);
|
||||
heart.setDepth(50);
|
||||
|
||||
// Animate heart
|
||||
this.scene.tweens.add({
|
||||
targets: heart,
|
||||
scaleX: 1,
|
||||
scaleY: 1,
|
||||
y: heart.y - 100,
|
||||
alpha: 0,
|
||||
duration: 1500,
|
||||
ease: 'Cubic.easeOut',
|
||||
onComplete: () => heart.destroy()
|
||||
});
|
||||
}
|
||||
|
||||
awardRandomMaterial(pool) {
|
||||
// Random material from pool
|
||||
const material = Phaser.Utils.Array.GetRandom(pool);
|
||||
const quantity = Phaser.Math.Between(1, 5);
|
||||
|
||||
if (this.scene.inventorySystem) {
|
||||
this.scene.inventorySystem.addItem(material, quantity);
|
||||
}
|
||||
|
||||
// Show notification
|
||||
this.scene.events.emit('show-notification', {
|
||||
title: '🎁 Material',
|
||||
message: `Prejel si: ${quantity}x ${material}`,
|
||||
icon: '🔧',
|
||||
duration: 4000,
|
||||
color: '#FFD700'
|
||||
});
|
||||
|
||||
console.log(`🎁 Awarded random material: ${quantity}x ${material}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* QUEST EXPIRATION
|
||||
*/
|
||||
update(delta) {
|
||||
const now = Date.now();
|
||||
|
||||
// Check for expired quests
|
||||
this.activeDeliveries.forEach(quest => {
|
||||
if (!quest.completed && (now - quest.timeCreated) > quest.expiresIn) {
|
||||
// Quest expired
|
||||
this.expireQuest(quest.id);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
expireQuest(questId) {
|
||||
const quest = this.activeDeliveries.find(q => q.id === questId);
|
||||
if (!quest) return;
|
||||
|
||||
this.activeDeliveries = this.activeDeliveries.filter(q => q.id !== questId);
|
||||
|
||||
// Notify player
|
||||
this.scene.events.emit('show-notification', {
|
||||
title: '⏰ Quest Expired',
|
||||
message: `${quest.npc} je našel drugega kurirja.`,
|
||||
icon: '😞',
|
||||
duration: 3000,
|
||||
color: '#999999'
|
||||
});
|
||||
|
||||
// Remove marker
|
||||
this.scene.events.emit('npc:remove_quest_marker', quest.npc);
|
||||
|
||||
console.log(`⏰ Quest expired: ${questId}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* GET SOCIAL STATUS BENEFITS
|
||||
*/
|
||||
getSocialBenefits() {
|
||||
const benefits = [];
|
||||
|
||||
if (this.socialStatus >= 20) benefits.push('5% discount at shops');
|
||||
if (this.socialStatus >= 40) benefits.push('Priority quests from NPCs');
|
||||
if (this.socialStatus >= 60) benefits.push('Access to VIP areas');
|
||||
if (this.socialStatus >= 80) benefits.push('Rare gift chance +10%');
|
||||
if (this.socialStatus >= 100) benefits.push('Maximum respect - All NPCs love you!');
|
||||
|
||||
return benefits;
|
||||
}
|
||||
|
||||
/**
|
||||
* GET UI DATA
|
||||
*/
|
||||
getActiveQuests() {
|
||||
return this.activeDeliveries.filter(q => !q.completed).map(q => ({
|
||||
id: q.id,
|
||||
npc: q.npc,
|
||||
item: q.item,
|
||||
quantity: q.quantity,
|
||||
reward: q.reward,
|
||||
timeRemaining: q.expiresIn - (Date.now() - q.timeCreated)
|
||||
}));
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.activeDeliveries = [];
|
||||
}
|
||||
}
|
||||
476
src/systems/DrugEconomySystem.js
Normal file
476
src/systems/DrugEconomySystem.js
Normal file
@@ -0,0 +1,476 @@
|
||||
/**
|
||||
* DRUG & NARCO-ECONOMY SYSTEM
|
||||
* Mrtva Dolina - Psychedelic Effects & Illegal Trade
|
||||
*
|
||||
* Features:
|
||||
* - Marijuana effects (slow-mo, chill, energy regen)
|
||||
* - Mushroom hallucinations (color distortion, ghosts)
|
||||
* - Free trade (no police until Mayor establishes it)
|
||||
* - Drug economy & black market
|
||||
*/
|
||||
|
||||
export class DrugEconomySystem {
|
||||
constructor(scene) {
|
||||
this.scene = scene;
|
||||
|
||||
// Drug effects tracking
|
||||
this.activeEffects = {
|
||||
marijuana: false,
|
||||
mushrooms: false
|
||||
};
|
||||
|
||||
// Duration timers
|
||||
this.effectTimers = {};
|
||||
|
||||
// Police state
|
||||
this.policeEstablished = false;
|
||||
|
||||
// Black market prices
|
||||
this.prices = {
|
||||
marijuana: { buy: 50, sell: 80 },
|
||||
mushrooms: { buy: 100, sell: 150 },
|
||||
marijuana_edible: { buy: 75, sell: 120 }
|
||||
};
|
||||
|
||||
// Effects configuration
|
||||
this.effectConfig = {
|
||||
marijuana: {
|
||||
duration: 180000, // 3 minutes
|
||||
timeScale: 0.7, // 70% speed (slower)
|
||||
energyRegenBonus: 2.0, // 2x regen
|
||||
walkSpeedMultiplier: 0.85, // 15% slower walk
|
||||
musicFilter: 'chill', // Music becomes chill
|
||||
visualFilter: 'subtle_blur'
|
||||
},
|
||||
mushrooms: {
|
||||
duration: 300000, // 5 minutes
|
||||
colorShift: true,
|
||||
hallucinationChance: 0.3, // 30% chance per second
|
||||
objectMovement: true,
|
||||
ghostVisions: true,
|
||||
psychedelicShader: 'trippy_colors'
|
||||
}
|
||||
};
|
||||
|
||||
this.init();
|
||||
}
|
||||
|
||||
init() {
|
||||
// Listen for consumption events
|
||||
this.scene.events.on('player:consume_drug', this.onDrugConsumed, this);
|
||||
this.scene.events.on('police:established', this.onPoliceEstablished, this);
|
||||
|
||||
console.log('✅ DrugEconomySystem initialized - Free trade active');
|
||||
}
|
||||
|
||||
/**
|
||||
* CONSUME DRUG
|
||||
*/
|
||||
onDrugConsumed(drugType, method = 'smoke') {
|
||||
if (drugType === 'marijuana') {
|
||||
this.consumeMarijuana(method);
|
||||
} else if (drugType === 'mushrooms') {
|
||||
this.consumeMushrooms();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* MARIJUANA EFFECTS
|
||||
*/
|
||||
consumeMarijuana(method) {
|
||||
if (this.activeEffects.marijuana) {
|
||||
console.log('🌿 Already high on marijuana');
|
||||
return;
|
||||
}
|
||||
|
||||
this.activeEffects.marijuana = true;
|
||||
const config = this.effectConfig.marijuana;
|
||||
|
||||
console.log(`🌿 Marijuana consumed (${method}) - Chill mode activated`);
|
||||
|
||||
// Visual effects
|
||||
this.applyMarijuanaVisuals(config);
|
||||
|
||||
// Gameplay effects
|
||||
this.applyMarijuanaGameplay(config);
|
||||
|
||||
// Audio effects
|
||||
this.applyMarijuanaAudio(config);
|
||||
|
||||
// Show notification
|
||||
this.scene.events.emit('show-notification', {
|
||||
title: '🌿 Chill Mode',
|
||||
message: 'Čas se upočasni... vse je bolj mirno...',
|
||||
icon: '😌',
|
||||
duration: 5000,
|
||||
color: '#90EE90'
|
||||
});
|
||||
|
||||
// Set duration timer
|
||||
this.effectTimers.marijuana = setTimeout(() => {
|
||||
this.endMarijuanaEffects();
|
||||
}, config.duration);
|
||||
}
|
||||
|
||||
applyMarijuanaVisuals(config) {
|
||||
// Subtle blur filter
|
||||
const camera = this.scene.cameras.main;
|
||||
|
||||
// Add slight vignette and blur
|
||||
this.scene.tweens.add({
|
||||
targets: camera,
|
||||
scrollX: camera.scrollX + 2,
|
||||
scrollY: camera.scrollY + 2,
|
||||
duration: 2000,
|
||||
yoyo: true,
|
||||
repeat: -1,
|
||||
ease: 'Sine.easeInOut'
|
||||
});
|
||||
|
||||
// Subtle color tint (light green)
|
||||
camera.setTint(0xE8F5E9); // Very light green tint
|
||||
}
|
||||
|
||||
applyMarijuanaGameplay(config) {
|
||||
// Slow down time
|
||||
this.scene.time.timeScale = config.timeScale;
|
||||
|
||||
// Increase energy regen
|
||||
if (this.scene.player) {
|
||||
this.scene.player.energyRegenRate *= config.energyRegenBonus;
|
||||
this.scene.player.walkSpeed *= config.walkSpeedMultiplier;
|
||||
}
|
||||
}
|
||||
|
||||
applyMarijuanaAudio(config) {
|
||||
// Change music to chill variant
|
||||
const currentMusic = this.scene.sound.get('background_music');
|
||||
if (currentMusic) {
|
||||
// Fade out current
|
||||
this.scene.tweens.add({
|
||||
targets: currentMusic,
|
||||
volume: 0,
|
||||
duration: 2000,
|
||||
onComplete: () => {
|
||||
currentMusic.stop();
|
||||
// Play chill music
|
||||
this.scene.sound.play('music_chill_lofi', {
|
||||
loop: true,
|
||||
volume: 0.4
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
endMarijuanaEffects() {
|
||||
this.activeEffects.marijuana = false;
|
||||
|
||||
// Restore time scale
|
||||
this.scene.time.timeScale = 1.0;
|
||||
|
||||
// Restore player stats
|
||||
if (this.scene.player) {
|
||||
this.scene.player.energyRegenRate /= this.effectConfig.marijuana.energyRegenBonus;
|
||||
this.scene.player.walkSpeed /= this.effectConfig.marijuana.walkSpeedMultiplier;
|
||||
}
|
||||
|
||||
// Remove visual effects
|
||||
const camera = this.scene.cameras.main;
|
||||
camera.clearTint();
|
||||
this.scene.tweens.killTweensOf(camera);
|
||||
|
||||
// Restore original music
|
||||
const chillMusic = this.scene.sound.get('music_chill_lofi');
|
||||
if (chillMusic) {
|
||||
this.scene.tweens.add({
|
||||
targets: chillMusic,
|
||||
volume: 0,
|
||||
duration: 2000,
|
||||
onComplete: () => {
|
||||
chillMusic.stop();
|
||||
this.scene.sound.play('background_music', { loop: true, volume: 0.5 });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
console.log('🌿 Marijuana effects ended');
|
||||
}
|
||||
|
||||
/**
|
||||
* MUSHROOM HALLUCINATION EFFECTS
|
||||
*/
|
||||
consumeMushrooms() {
|
||||
if (this.activeEffects.mushrooms) {
|
||||
console.log('🍄 Already tripping on mushrooms');
|
||||
return;
|
||||
}
|
||||
|
||||
this.activeEffects.mushrooms = true;
|
||||
const config = this.effectConfig.mushrooms;
|
||||
|
||||
console.log('🍄 Mushrooms consumed - Reality dissolving...');
|
||||
|
||||
// Apply psychedelic shader
|
||||
this.applyPsychedelicShader(config);
|
||||
|
||||
// Start hallucination events
|
||||
this.startHallucinations(config);
|
||||
|
||||
// Show notification
|
||||
this.scene.events.emit('show-notification', {
|
||||
title: '🍄 Hallucinacije',
|
||||
message: 'Barve... gibanje... duhovi iz preteklosti...',
|
||||
icon: '🌀',
|
||||
duration: 7000,
|
||||
color: '#FF1493'
|
||||
});
|
||||
|
||||
// Set duration timer
|
||||
this.effectTimers.mushrooms = setTimeout(() => {
|
||||
this.endMushroomEffects();
|
||||
}, config.duration);
|
||||
}
|
||||
|
||||
applyPsychedelicShader(config) {
|
||||
const camera = this.scene.cameras.main;
|
||||
|
||||
// Extreme color shifting
|
||||
this.colorShiftTimer = setInterval(() => {
|
||||
const hue = Phaser.Math.Between(0, 360);
|
||||
const color = Phaser.Display.Color.HSVToRGB(hue / 360, 0.8, 0.9);
|
||||
camera.setTint(color.color);
|
||||
}, 500); // Change every 500ms
|
||||
|
||||
// Camera shake (mild)
|
||||
camera.shake(config.duration, 0.002);
|
||||
|
||||
// Zoom pulse
|
||||
this.scene.tweens.add({
|
||||
targets: camera,
|
||||
zoom: 1.05,
|
||||
duration: 3000,
|
||||
yoyo: true,
|
||||
repeat: -1,
|
||||
ease: 'Sine.easeInOut'
|
||||
});
|
||||
}
|
||||
|
||||
startHallucinations(config) {
|
||||
// Periodic hallucination events
|
||||
this.hallucinationInterval = setInterval(() => {
|
||||
if (Math.random() < config.hallucinationChance) {
|
||||
this.triggerHallucination();
|
||||
}
|
||||
}, 1000); // Check every second
|
||||
}
|
||||
|
||||
triggerHallucination() {
|
||||
const hallucinationTypes = [
|
||||
'moving_objects',
|
||||
'ghost_vision',
|
||||
'color_trails',
|
||||
'reality_distortion'
|
||||
];
|
||||
|
||||
const type = Phaser.Utils.Array.GetRandom(hallucinationTypes);
|
||||
|
||||
switch (type) {
|
||||
case 'moving_objects':
|
||||
this.hallucinateMovingObjects();
|
||||
break;
|
||||
case 'ghost_vision':
|
||||
this.hallucinateGhostVision();
|
||||
break;
|
||||
case 'color_trails':
|
||||
this.hallucinateColorTrails();
|
||||
break;
|
||||
case 'reality_distortion':
|
||||
this.hallucinateRealityDistortion();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
hallucinateMovingObjects() {
|
||||
// Random game objects start floating/moving
|
||||
const objects = this.scene.children.list.filter(obj =>
|
||||
obj.type === 'Sprite' && obj !== this.scene.player
|
||||
);
|
||||
|
||||
if (objects.length === 0) return;
|
||||
|
||||
const obj = Phaser.Utils.Array.GetRandom(objects);
|
||||
const originalX = obj.x;
|
||||
const originalY = obj.y;
|
||||
|
||||
this.scene.tweens.add({
|
||||
targets: obj,
|
||||
x: originalX + Phaser.Math.Between(-30, 30),
|
||||
y: originalY + Phaser.Math.Between(-30, 30),
|
||||
duration: 2000,
|
||||
yoyo: true,
|
||||
ease: 'Sine.easeInOut',
|
||||
onComplete: () => {
|
||||
obj.x = originalX;
|
||||
obj.y = originalY;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
hallucinateGhostVision() {
|
||||
// Spawn ghost from Kai's past
|
||||
const ghosts = ['ana_ghost', 'family_ghost', 'memory_ghost'];
|
||||
const ghostType = Phaser.Utils.Array.GetRandom(ghosts);
|
||||
|
||||
const x = this.scene.player.x + Phaser.Math.Between(-200, 200);
|
||||
const y = this.scene.player.y + Phaser.Math.Between(-200, 200);
|
||||
|
||||
const ghost = this.scene.add.sprite(x, y, ghostType);
|
||||
ghost.setAlpha(0);
|
||||
ghost.setDepth(20);
|
||||
ghost.setTint(0x9966FF); // Purple ghost tint
|
||||
|
||||
// Fade in
|
||||
this.scene.tweens.add({
|
||||
targets: ghost,
|
||||
alpha: 0.7,
|
||||
duration: 1000,
|
||||
onComplete: () => {
|
||||
// Ghost speaks
|
||||
this.scene.events.emit('show-speech-bubble', {
|
||||
x: ghost.x,
|
||||
y: ghost.y - 50,
|
||||
text: this.getGhostMessage(),
|
||||
duration: 3000
|
||||
});
|
||||
|
||||
// Fade out
|
||||
this.scene.tweens.add({
|
||||
targets: ghost,
|
||||
alpha: 0,
|
||||
duration: 2000,
|
||||
delay: 3000,
|
||||
onComplete: () => ghost.destroy()
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
getGhostMessage() {
|
||||
const messages = [
|
||||
"Kai... ne pozabi...",
|
||||
"Ana te išče...",
|
||||
"Spomniti se moraš...",
|
||||
"Vrni se domov..."
|
||||
];
|
||||
return Phaser.Utils.Array.GetRandom(messages);
|
||||
}
|
||||
|
||||
hallucinateColorTrails() {
|
||||
// Player leaves colorful trails when moving
|
||||
if (!this.scene.player.isMoving) return;
|
||||
|
||||
const trail = this.scene.add.sprite(
|
||||
this.scene.player.x,
|
||||
this.scene.player.y,
|
||||
this.scene.player.texture.key
|
||||
);
|
||||
trail.setFrame(this.scene.player.frame.name);
|
||||
trail.setAlpha(0.5);
|
||||
trail.setTint(Phaser.Math.Between(0x000000, 0xFFFFFF));
|
||||
|
||||
this.scene.tweens.add({
|
||||
targets: trail,
|
||||
alpha: 0,
|
||||
duration: 1000,
|
||||
onComplete: () => trail.destroy()
|
||||
});
|
||||
}
|
||||
|
||||
hallucinateRealityDistortion() {
|
||||
// Screen warps/ripples
|
||||
const camera = this.scene.cameras.main;
|
||||
|
||||
this.scene.tweens.add({
|
||||
targets: camera,
|
||||
scrollX: camera.scrollX + Phaser.Math.Between(-20, 20),
|
||||
scrollY: camera.scrollY + Phaser.Math.Between(-20, 20),
|
||||
duration: 500,
|
||||
yoyo: true,
|
||||
repeat: 3
|
||||
});
|
||||
}
|
||||
|
||||
endMushroomEffects() {
|
||||
this.activeEffects.mushrooms = false;
|
||||
|
||||
// Stop color shift
|
||||
if (this.colorShiftTimer) {
|
||||
clearInterval(this.colorShiftTimer);
|
||||
this.colorShiftTimer = null;
|
||||
}
|
||||
|
||||
// Stop hallucinations
|
||||
if (this.hallucinationInterval) {
|
||||
clearInterval(this.hallucinationInterval);
|
||||
this.hallucinationInterval = null;
|
||||
}
|
||||
|
||||
// Restore camera
|
||||
const camera = this.scene.cameras.main;
|
||||
camera.clearTint();
|
||||
camera.setZoom(1.0);
|
||||
this.scene.tweens.killTweensOf(camera);
|
||||
|
||||
console.log('🍄 Mushroom effects ended - Reality restored');
|
||||
}
|
||||
|
||||
/**
|
||||
* BLACK MARKET TRADE
|
||||
*/
|
||||
sellDrug(drugType, quantity) {
|
||||
if (this.policeEstablished) {
|
||||
// Risk of getting caught!
|
||||
if (Math.random() < 0.3) { // 30% chance
|
||||
this.scene.events.emit('police:drug_bust', drugType, quantity);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const price = this.prices[drugType].sell;
|
||||
const earnings = price * quantity;
|
||||
|
||||
if (this.scene.inventorySystem) {
|
||||
this.scene.inventorySystem.removeItem(drugType, quantity);
|
||||
this.scene.inventorySystem.addGold(earnings);
|
||||
}
|
||||
|
||||
console.log(`💰 Sold ${quantity}x ${drugType} for ${earnings} gold`);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* POLICE ESTABLISHMENT
|
||||
*/
|
||||
onPoliceEstablished() {
|
||||
this.policeEstablished = true;
|
||||
|
||||
this.scene.events.emit('show-notification', {
|
||||
title: '🚔 Policija Ustanovljena',
|
||||
message: 'Previdno! Zdaj ti lahko zaseže droge!',
|
||||
icon: '⚠️',
|
||||
duration: 5000,
|
||||
color: '#FF0000'
|
||||
});
|
||||
|
||||
console.log('🚔 Police established - Drug trade now illegal and risky');
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.endMarijuanaEffects();
|
||||
this.endMushroomEffects();
|
||||
|
||||
if (this.effectTimers.marijuana) clearTimeout(this.effectTimers.marijuana);
|
||||
if (this.effectTimers.mushrooms) clearTimeout(this.effectTimers.mushrooms);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user