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:
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