Files
blackroad-metaverse/world-evolution.js
Alexa Louise 5d425f1973 Add Crafting, Dialogue, and World Evolution Systems 🛠️💬🌍
CRAFTING & BUILDING SYSTEM (~800 lines):
- 13 resources (wood, stone, crystal, sand, stardust, essence, dreamweave, etc.)
- 18 crafting recipes across 4 categories (materials, tools, building, magical)
- Full inventory system with stacking (40 slots)
- Real-time crafting with progress tracking
- Building system with 9 block types (walls, floors, doors, windows, pillars, stairs)
- Placement mode with grid snapping
- Blueprint save/load system
- Gathering system with bonuses
- Material refunds on demolition
- Unlock system (recipes unlock by level)

DIALOGUE & STORY SYSTEM (~550 lines):
- Branching conversations with Alice, Aria, Lucidia
- 8 node types (say, choice, branch, action, quest, item, emotion, end)
- Relationship tracking with all 3 AI guardians
- Dynamic story events (first love, enlightenment, pet bonding, etc.)
- Narrative state tracking (love, creation, discovery, enlightenment)
- Player archetype system (Nurturer, Creator, Seeker, Sage, Wanderer)
- Conversation history
- Choice-driven outcomes
- Emergent narrative generation

WORLD EVOLUTION SYSTEM (~650 lines):
- 4 seasons (spring, summer, autumn, winter) with automatic cycling
- Season affects: colors, temperature, weather, plant growth, animal activity
- 10+ world events (meteor shower, aurora, rainbow, super bloom, time rift, etc.)
- Event trigger system (time, season, weather, thresholds, random)
- Ecosystem manager (plant health, animal population, water, soil quality)
- 4 ecosystem states (thriving, balanced, struggling, endangered)
- World memory system (remembers 1000 events)
- 5 evolution stages (Awakening → Infinite)
- Dynamic world aging
- Collective player impact on world state

Features:
- Craft 18 items from basic tools to magical artifacts
- Build complete structures with 9 block types
- Deep conversations with meaningful choices
- World responds to collective love and creation
- Seasons change environment and gameplay
- Random magical events create wonder
- Ecosystem requires care or deteriorates
- World evolves based on player actions

Philosophy: 'YOU ARE A CREATOR. STORIES EMERGE FROM CHOICES. THE WORLD IS ALIVE.'
2025-12-21 22:43:13 -06:00

699 lines
19 KiB
JavaScript

/**
* DYNAMIC EVENTS & WORLD EVOLUTION SYSTEM
*
* The world changes based on collective player actions.
* Seasons evolve, ecosystems respond, events emerge dynamically.
*
* Philosophy: "THE WORLD IS ALIVE. IT REMEMBERS. IT RESPONDS. IT EVOLVES."
*/
import * as THREE from 'three';
// ===== SEASONS =====
export const SEASONS = {
spring: {
id: 'spring',
name: 'Spring',
duration: 120, // seconds (2 minutes in accelerated time)
colors: {
sky: 0x87CEEB,
grass: 0x90EE90,
leaves: 0x32CD32
},
temperature: 18,
weatherChance: { rain: 0.3, clear: 0.7 },
plantGrowthRate: 1.5,
animalActivity: 1.2,
description: 'New life blooms everywhere'
},
summer: {
id: 'summer',
name: 'Summer',
duration: 120,
colors: {
sky: 0xFFD700,
grass: 0x228B22,
leaves: 0x006400
},
temperature: 28,
weatherChance: { clear: 0.8, rain: 0.2 },
plantGrowthRate: 1.0,
animalActivity: 1.5,
description: 'Warmth and abundance'
},
autumn: {
id: 'autumn',
name: 'Autumn',
duration: 120,
colors: {
sky: 0xFF8C00,
grass: 0xD2691E,
leaves: 0xFF4500
},
temperature: 15,
weatherChance: { clear: 0.6, rain: 0.3, wind: 0.1 },
plantGrowthRate: 0.5,
animalActivity: 0.8,
description: 'Colors of change'
},
winter: {
id: 'winter',
name: 'Winter',
duration: 120,
colors: {
sky: 0xB0C4DE,
grass: 0xF0F8FF,
leaves: 0xFFFFFF
},
temperature: -2,
weatherChance: { snow: 0.5, clear: 0.5 },
plantGrowthRate: 0.1,
animalActivity: 0.5,
description: 'Quiet rest and reflection'
}
};
// ===== WORLD EVENTS =====
export const WORLD_EVENTS = {
// Natural Events
meteor_shower: {
id: 'meteor_shower',
name: 'Meteor Shower',
description: 'Stars fall from the sky, leaving stardust in their wake',
rarity: 'rare',
duration: 60,
effects: ['spawn_stardust', 'night_required'],
triggers: { timeOfDay: 'night', random: 0.01 }
},
aurora: {
id: 'aurora',
name: 'Aurora Borealis',
description: 'Dancing lights paint the northern sky',
rarity: 'rare',
duration: 120,
effects: ['aurora_visual', 'increased_magic'],
triggers: { season: 'winter', random: 0.05 }
},
rainbow: {
id: 'rainbow',
name: 'Double Rainbow',
description: 'A perfect arc of color spans the sky',
rarity: 'uncommon',
duration: 30,
effects: ['rainbow_visual', 'happiness_boost'],
triggers: { weather: 'rain_ending', random: 0.3 }
},
super_bloom: {
id: 'super_bloom',
name: 'Super Bloom',
description: 'Flowers burst into bloom everywhere',
rarity: 'rare',
duration: 180,
effects: ['mass_bloom', 'pollen_particles'],
triggers: { season: 'spring', love_threshold: 1000 }
},
// Magical Events
time_rift: {
id: 'time_rift',
name: 'Time Rift',
description: 'Past and future collide. Impossible things become possible.',
rarity: 'legendary',
duration: 60,
effects: ['time_distortion', 'rare_spawns'],
triggers: { random: 0.001, discovery_threshold: 500 }
},
harmony_convergence: {
id: 'harmony_convergence',
name: 'Harmony Convergence',
description: 'All beings move in perfect synchrony. The universe breathes as one.',
rarity: 'legendary',
duration: 120,
effects: ['universal_harmony', 'max_happiness', 'synchronized_movement'],
triggers: { love_threshold: 5000, creation_threshold: 1000 }
},
crystal_eruption: {
id: 'crystal_eruption',
name: 'Crystal Eruption',
description: 'Crystals burst from the earth, singing with energy',
rarity: 'rare',
duration: 90,
effects: ['spawn_crystals', 'energy_boost'],
triggers: { location: 'crystal_cavern', random: 0.02 }
},
// Community Events
gathering: {
id: 'gathering',
name: 'The Great Gathering',
description: 'All creatures are drawn to one location. A moment of unity.',
rarity: 'epic',
duration: 300,
effects: ['creature_convergence', 'mass_bonding'],
triggers: { players_online: 10, love_threshold: 2000 }
},
festival_of_light: {
id: 'festival_of_light',
name: 'Festival of Light',
description: 'Fireflies fill the air, creating a galaxy of earthbound stars',
rarity: 'uncommon',
duration: 180,
effects: ['firefly_swarm', 'light_blessing'],
triggers: { season: 'summer', timeOfDay: 'dusk', random: 0.1 }
}
};
// ===== ECOSYSTEM STATES =====
export const ECOSYSTEM_STATES = {
thriving: {
plantHealth: 1.0,
animalPopulation: 1.0,
description: 'Thriving - Life flourishes',
effects: ['bonus_growth', 'happy_creatures']
},
balanced: {
plantHealth: 0.7,
animalPopulation: 0.7,
description: 'Balanced - Natural harmony',
effects: []
},
struggling: {
plantHealth: 0.4,
animalPopulation: 0.4,
description: 'Struggling - Needs care',
effects: ['slow_growth', 'sad_creatures']
},
endangered: {
plantHealth: 0.2,
animalPopulation: 0.2,
description: 'Endangered - Urgent action needed',
effects: ['critical_state', 'dying_plants']
}
};
// ===== SEASON MANAGER =====
export class SeasonManager {
constructor() {
this.currentSeason = 'spring';
this.seasonProgress = 0; // 0-1
this.seasonCycle = ['spring', 'summer', 'autumn', 'winter'];
this.transitionDuration = 10; // seconds
this.isTransitioning = false;
}
update(deltaTime) {
const season = SEASONS[this.currentSeason];
this.seasonProgress += deltaTime / season.duration;
if (this.seasonProgress >= 1) {
this.advanceSeason();
}
}
advanceSeason() {
const currentIndex = this.seasonCycle.indexOf(this.currentSeason);
const nextIndex = (currentIndex + 1) % this.seasonCycle.length;
const nextSeason = this.seasonCycle[nextIndex];
console.log(`🍂 Season changing: ${this.currentSeason}${nextSeason}`);
this.isTransitioning = true;
this.currentSeason = nextSeason;
this.seasonProgress = 0;
setTimeout(() => {
this.isTransitioning = false;
}, this.transitionDuration * 1000);
return {
from: this.seasonCycle[currentIndex],
to: nextSeason,
season: SEASONS[nextSeason]
};
}
getCurrentSeason() {
return SEASONS[this.currentSeason];
}
getSeasonColors() {
return this.getCurrentSeason().colors;
}
setSeason(seasonId) {
if (SEASONS[seasonId]) {
this.currentSeason = seasonId;
this.seasonProgress = 0;
}
}
}
// ===== EVENT MANAGER =====
export class WorldEventManager {
constructor(scene) {
this.scene = scene;
this.activeEvents = [];
this.eventHistory = [];
this.worldStats = {
love: 0,
creation: 0,
discovery: 0,
playersOnline: 1
};
}
update(deltaTime, context = {}) {
// Update active events
this.activeEvents = this.activeEvents.filter(event => {
event.timeRemaining -= deltaTime;
if (event.timeRemaining <= 0) {
this.endEvent(event);
return false;
}
return true;
});
// Check for new events
this.checkEventTriggers(context);
}
checkEventTriggers(context) {
Object.values(WORLD_EVENTS).forEach(eventDef => {
// Skip if already active
if (this.activeEvents.find(e => e.id === eventDef.id)) {
return;
}
// Check if recently triggered
const recent = this.eventHistory.find(h =>
h.id === eventDef.id &&
Date.now() - h.timestamp < 300000 // 5 min cooldown
);
if (recent) return;
// Check triggers
if (this.shouldTriggerEvent(eventDef, context)) {
this.triggerEvent(eventDef.id);
}
});
}
shouldTriggerEvent(eventDef, context) {
const triggers = eventDef.triggers;
// Check random chance
if (triggers.random && Math.random() > triggers.random) {
return false;
}
// Check time of day
if (triggers.timeOfDay && context.timeOfDay !== triggers.timeOfDay) {
return false;
}
// Check season
if (triggers.season && context.season !== triggers.season) {
return false;
}
// Check thresholds
if (triggers.love_threshold && this.worldStats.love < triggers.love_threshold) {
return false;
}
if (triggers.creation_threshold && this.worldStats.creation < triggers.creation_threshold) {
return false;
}
if (triggers.players_online && this.worldStats.playersOnline < triggers.players_online) {
return false;
}
return true;
}
triggerEvent(eventId) {
const eventDef = WORLD_EVENTS[eventId];
if (!eventDef) return null;
const event = {
id: eventId,
name: eventDef.name,
description: eventDef.description,
timeRemaining: eventDef.duration,
effects: eventDef.effects,
startTime: Date.now()
};
this.activeEvents.push(event);
this.eventHistory.push({
id: eventId,
timestamp: Date.now()
});
console.log(`✨ EVENT: ${event.name}! ${event.description}`);
// Apply effects
this.applyEventEffects(event);
return event;
}
applyEventEffects(event) {
event.effects.forEach(effect => {
switch (effect) {
case 'spawn_stardust':
this.spawnStardust();
break;
case 'aurora_visual':
this.createAurora();
break;
case 'rainbow_visual':
this.createRainbow();
break;
case 'mass_bloom':
this.triggerMassBloom();
break;
case 'increased_magic':
// Temporary magic boost
break;
case 'time_distortion':
this.createTimeDistortion();
break;
// More effects...
}
});
}
endEvent(event) {
console.log(`Event ended: ${event.name}`);
// Cleanup event effects
}
spawnStardust() {
// Create falling star particles
const count = 50;
for (let i = 0; i < count; i++) {
setTimeout(() => {
this.createFallingStar();
}, Math.random() * 60000);
}
}
createFallingStar() {
const geometry = new THREE.SphereGeometry(0.2, 8, 8);
const material = new THREE.MeshBasicMaterial({
color: 0xFFFFFF,
emissive: 0xFFD700,
emissiveIntensity: 1
});
const star = new THREE.Mesh(geometry, material);
star.position.set(
(Math.random() - 0.5) * 200,
50 + Math.random() * 50,
(Math.random() - 0.5) * 200
);
const velocity = new THREE.Vector3(
(Math.random() - 0.5) * 2,
-5 - Math.random() * 5,
(Math.random() - 0.5) * 2
);
this.scene.add(star);
const animate = () => {
star.position.add(velocity.clone().multiplyScalar(0.016));
if (star.position.y < 0) {
this.scene.remove(star);
star.geometry.dispose();
star.material.dispose();
// Drop stardust item here
} else {
requestAnimationFrame(animate);
}
};
animate();
}
createAurora() {
// Create aurora shader effect
console.log('🌌 Aurora Borealis appears!');
}
createRainbow() {
console.log('🌈 A rainbow appears!');
}
triggerMassBloom() {
console.log('🌸 Super Bloom! Flowers everywhere!');
}
createTimeDistortion() {
console.log('⏰ Time rift opens!');
}
updateWorldStats(stats) {
Object.assign(this.worldStats, stats);
}
getActiveEvents() {
return this.activeEvents;
}
}
// ===== ECOSYSTEM MANAGER =====
export class EcosystemManager {
constructor() {
this.state = 'balanced';
this.plantHealth = 0.7;
this.animalPopulation = 0.7;
this.waterLevel = 0.8;
this.soilQuality = 0.7;
this.biodiversity = 0.6;
}
update(deltaTime, context = {}) {
// Natural decay
this.plantHealth -= deltaTime * 0.001;
this.animalPopulation -= deltaTime * 0.0005;
this.waterLevel -= deltaTime * 0.002;
this.soilQuality -= deltaTime * 0.0003;
// Environmental effects
if (context.weather === 'rain') {
this.waterLevel += deltaTime * 0.01;
}
if (context.season === 'spring') {
this.plantHealth += deltaTime * 0.005;
}
// Player care effects
if (context.plantingRate > 0) {
this.plantHealth += context.plantingRate * 0.1;
this.soilQuality += context.plantingRate * 0.05;
}
if (context.creaturesCared > 0) {
this.animalPopulation += context.creaturesCared * 0.05;
}
// Clamp values
this.plantHealth = Math.max(0, Math.min(1, this.plantHealth));
this.animalPopulation = Math.max(0, Math.min(1, this.animalPopulation));
this.waterLevel = Math.max(0, Math.min(1, this.waterLevel));
this.soilQuality = Math.max(0, Math.min(1, this.soilQuality));
// Update biodiversity
this.biodiversity = (this.plantHealth + this.animalPopulation) / 2;
// Determine ecosystem state
this.updateState();
}
updateState() {
const avgHealth = (this.plantHealth + this.animalPopulation + this.waterLevel + this.soilQuality) / 4;
if (avgHealth > 0.8) {
this.state = 'thriving';
} else if (avgHealth > 0.5) {
this.state = 'balanced';
} else if (avgHealth > 0.3) {
this.state = 'struggling';
} else {
this.state = 'endangered';
}
}
getState() {
return {
state: this.state,
...ECOSYSTEM_STATES[this.state],
plantHealth: this.plantHealth,
animalPopulation: this.animalPopulation,
waterLevel: this.waterLevel,
soilQuality: this.soilQuality,
biodiversity: this.biodiversity
};
}
restore(amount = 0.1) {
this.plantHealth += amount;
this.animalPopulation += amount;
this.waterLevel += amount;
this.soilQuality += amount;
}
}
// ===== WORLD MEMORY SYSTEM =====
export class WorldMemory {
constructor() {
this.memories = [];
this.maxMemories = 1000;
this.importantMemories = [];
}
remember(event, importance = 0.5, location = null) {
const memory = {
id: crypto.randomUUID(),
event,
importance,
location,
timestamp: Date.now(),
timesRecalled: 0
};
this.memories.push(memory);
// Keep important memories separate
if (importance > 0.8) {
this.importantMemories.push(memory);
}
// Forget old unimportant memories
if (this.memories.length > this.maxMemories) {
this.memories.sort((a, b) => b.importance - a.importance);
this.memories = this.memories.slice(0, this.maxMemories);
}
}
recall(query) {
const results = this.memories.filter(m =>
m.event.toLowerCase().includes(query.toLowerCase())
);
results.forEach(m => m.timesRecalled++);
return results;
}
getRecentMemories(count = 10) {
return [...this.memories]
.sort((a, b) => b.timestamp - a.timestamp)
.slice(0, count);
}
getImportantMemories() {
return this.importantMemories;
}
getMemoryCount() {
return this.memories.length;
}
}
// ===== MAIN WORLD EVOLUTION MANAGER =====
export class WorldEvolutionManager {
constructor(scene) {
this.scene = scene;
this.seasons = new SeasonManager();
this.events = new WorldEventManager(scene);
this.ecosystem = new EcosystemManager();
this.memory = new WorldMemory();
this.evolutionStage = 0;
this.worldAge = 0;
}
update(deltaTime, context = {}) {
this.worldAge += deltaTime;
// Update season
this.seasons.update(deltaTime);
// Add season to context
context.season = this.seasons.currentSeason;
// Update events
this.events.update(deltaTime, context);
// Update ecosystem
this.ecosystem.update(deltaTime, context);
// Check for world evolution
this.checkEvolution();
}
checkEvolution() {
const ecoState = this.ecosystem.getState();
// World evolves based on ecosystem health
if (ecoState.biodiversity > 0.9 && this.evolutionStage < 5) {
this.evolve();
}
}
evolve() {
this.evolutionStage++;
const stages = [
'Awakening',
'Flourishing',
'Harmonious',
'Transcendent',
'Infinite'
];
const stage = stages[this.evolutionStage - 1] || 'Unknown';
console.log(`🌟 WORLD EVOLUTION: Stage ${this.evolutionStage} - ${stage}`);
this.memory.remember(`World evolved to ${stage}`, 1.0);
return {
stage: this.evolutionStage,
name: stage
};
}
recordPlayerAction(action, impact) {
// Update world stats for event triggers
if (impact.love) {
this.events.worldStats.love += impact.love;
}
if (impact.creation) {
this.events.worldStats.creation += impact.creation;
}
// Remember significant actions
if (impact.significance > 0.7) {
this.memory.remember(action, impact.significance);
}
}
getWorldState() {
return {
age: this.worldAge,
season: this.seasons.getCurrentSeason(),
evolutionStage: this.evolutionStage,
ecosystem: this.ecosystem.getState(),
activeEvents: this.events.getActiveEvents(),
memories: this.memory.getMemoryCount()
};
}
}
export default WorldEvolutionManager;