Files
novafarma/EMERGENCY_SYSTEMS_RECOVERY/TransportSystem.js
2026-01-16 02:43:46 +01:00

645 lines
19 KiB
JavaScript

/**
* TransportSystem.js
* ==================
* Manages all transportation methods in the game
* - Horses (5 breeds, different speeds)
* - Carts & Wagons (cargo capacity)
* - Trains (track-based, high speed, high capacity)
* - Water transport (kayak, SUP, raft, boat)
* - Bicycles & Boards (longboard, mountain board, snowboard)
*
* Uses: transportation_vehicles_detailed_1766097668396.tsx
* train_repairs_3_states (broken → repairing → rideable)
*
* @author NovaFarma Team
* @date 2025-12-22
*/
export default class TransportSystem {
constructor(scene) {
this.scene = scene;
// Current state
this.currentVehicle = null;
this.ownedVehicles = new Map();
this.trainTracks = [];
// Vehicle definitions
this.vehicleData = this.defineVehicles();
// Train repair state
this.trainRepairProgress = 0;
console.log('🚂 TransportSystem initialized');
}
defineVehicles() {
return {
// ===== HORSES =====
horse_basic: {
name: 'Basic Horse',
type: 'mount',
speed: 200,
capacity: 0,
cost: 500,
unlockLevel: 3,
sprite: 'horse_brown',
waterAllowed: false,
description: 'Reliable companion for travel'
},
horse_fast: {
name: 'Racing Horse',
type: 'mount',
speed: 300,
capacity: 0,
cost: 1500,
unlockLevel: 7,
sprite: 'horse_white',
waterAllowed: false,
description: 'Swift steed for long distances'
},
horse_draft: {
name: 'Draft Horse',
type: 'mount',
speed: 150,
capacity: 50,
cost: 1200,
unlockLevel: 5,
sprite: 'horse_black',
waterAllowed: false,
description: 'Strong horse, can carry cargo'
},
// ===== CARTS & WAGONS =====
cart_wooden: {
name: 'Wooden Cart',
type: 'vehicle',
speed: 120,
capacity: 100,
cost: 800,
unlockLevel: 4,
blueprint: 'blueprint_cart',
sprite: 'cart_wooden',
waterAllowed: false,
requiresHorse: true,
description: 'Transport goods efficiently'
},
wagon_large: {
name: 'Large Wagon',
type: 'vehicle',
speed: 100,
capacity: 250,
cost: 2500,
unlockLevel: 8,
blueprint: 'blueprint_wagon',
sprite: 'wagon_large',
waterAllowed: false,
requiresHorse: true,
description: 'Massive cargo capacity'
},
// ===== TRAINS =====
train: {
name: 'Steam Train',
type: 'rail',
speed: 400,
capacity: 500,
cost: 10000,
unlockLevel: 15,
blueprint: 'blueprint_train',
sprite: 'train_rideable',
waterAllowed: false,
requiresTrack: true,
repairStages: ['broken', 'repairing', 'rideable'],
description: 'Ultimate transport - requires tracks'
},
// ===== WATER TRANSPORT =====
kayak: {
name: 'Kayak',
type: 'water',
speed: 150,
capacity: 20,
cost: 300,
unlockLevel: 6,
sprite: 'kayak',
waterOnly: true,
description: 'Navigate rivers and lakes'
},
sup: {
name: 'Stand-Up Paddleboard',
type: 'water',
speed: 100,
capacity: 5,
cost: 200,
unlockLevel: 5,
sprite: 'sup',
waterOnly: true,
description: 'Calm water exploration'
},
raft: {
name: 'Wooden Raft',
type: 'water',
speed: 80,
capacity: 50,
cost: 150,
unlockLevel: 3,
sprite: 'raft',
waterOnly: true,
description: 'Basic water transport'
},
boat: {
name: 'Fishing Boat',
type: 'water',
speed: 180,
capacity: 100,
cost: 1000,
unlockLevel: 10,
blueprint: 'blueprint_boat',
sprite: 'boat',
waterOnly: true,
description: 'Ocean-ready vessel'
},
// ===== BICYCLES & BOARDS =====
bicycle: {
name: 'Bicycle',
type: 'manual',
speed: 180,
capacity: 10,
cost: 250,
unlockLevel: 2,
sprite: 'bicycle',
waterAllowed: false,
description: 'Energy-efficient travel'
},
longboard: {
name: 'Longboard',
type: 'manual',
speed: 220,
capacity: 0,
cost: 150,
unlockLevel: 4,
sprite: 'longboard',
waterAllowed: false,
terrainBonus: { 'road': 1.5 }, // 50% faster on roads
description: 'Cruise downhill paths'
},
mountain_board: {
name: 'Mountain Board',
type: 'manual',
speed: 200,
capacity: 5,
cost: 300,
unlockLevel: 6,
sprite: 'mountain_board',
waterAllowed: false,
terrainBonus: { 'mountain': 1.3 },
description: 'Off-road board for rough terrain'
},
snowboard: {
name: 'Snowboard',
type: 'manual',
speed: 250,
capacity: 0,
cost: 200,
unlockLevel: 5,
sprite: 'snowboard',
waterAllowed: false,
terrainRequired: 'snow',
terrainBonus: { 'snow': 2.0 }, // 2x speed on snow
description: 'Winter transport - snow only'
}
};
}
// ===== VEHICLE MOUNTING =====
canMount(vehicleId, playerX, playerY) {
const vehicle = this.vehicleData[vehicleId];
if (!vehicle) {
return { canMount: false, reason: 'Vehicle not found' };
}
// Check if player owns this vehicle
if (!this.ownedVehicles.has(vehicleId)) {
return { canMount: false, reason: 'You don\'t own this vehicle' };
}
// Check if already mounted
if (this.currentVehicle) {
return { canMount: false, reason: 'Already using a vehicle' };
}
// Check level requirement
const playerLevel = this.scene.player?.stats?.level || 1;
if (playerLevel < vehicle.unlockLevel) {
return {
canMount: false,
reason: `Requires level ${vehicle.unlockLevel}`
};
}
// Check terrain compatibility
const currentTile = this.getTileAt(playerX, playerY);
if (vehicle.waterOnly && !currentTile.properties?.isWater) {
return { canMount: false, reason: 'Water vehicles require water' };
}
if (!vehicle.waterAllowed && currentTile.properties?.isWater) {
return { canMount: false, reason: 'Cannot use on water' };
}
if (vehicle.terrainRequired && currentTile.properties?.terrain !== vehicle.terrainRequired) {
return {
canMount: false,
reason: `Requires ${vehicle.terrainRequired} terrain`
};
}
// Check if train requires tracks
if (vehicle.requiresTrack && !this.isOnTrack(playerX, playerY)) {
return { canMount: false, reason: 'Train requires tracks' };
}
// Check if cart/wagon requires horse
if (vehicle.requiresHorse && !this.hasHorse()) {
return { canMount: false, reason: 'Requires a horse to pull' };
}
return { canMount: true };
}
mount(vehicleId) {
const check = this.canMount(vehicleId, this.scene.player.x, this.scene.player.y);
if (!check.canMount) {
this.scene.uiSystem?.showError(check.reason);
return false;
}
const vehicle = this.vehicleData[vehicleId];
// Update player speed
this.scene.player.baseSpeed = this.scene.player.baseSpeed || 100;
this.scene.player.setMaxVelocity(vehicle.speed);
// Change player sprite (riding animation)
const originalTexture = this.scene.player.texture.key;
this.scene.player.setTexture(`player_on_${vehicle.type}`);
// Store original state
this.currentVehicle = {
id: vehicleId,
data: vehicle,
originalSpeed: this.scene.player.baseSpeed,
originalTexture: originalTexture,
mountTime: Date.now()
};
// Show UI
this.scene.uiSystem?.showVehicleUI({
name: vehicle.name,
speed: vehicle.speed,
capacity: vehicle.capacity,
currentCargo: 0
});
// Emit event
this.scene.events.emit('vehicleMounted', { vehicleId, vehicle });
console.log(`🚴 Mounted ${vehicle.name} (${vehicle.speed} speed)`);
return true;
}
dismount() {
if (!this.currentVehicle) {
return false;
}
const vehicle = this.currentVehicle.data;
// Restore player speed
this.scene.player.setMaxVelocity(this.currentVehicle.originalSpeed);
// Restore player sprite
this.scene.player.setTexture(this.currentVehicle.originalTexture);
// Hide UI
this.scene.uiSystem?.hideVehicleUI();
// Emit event
this.scene.events.emit('vehicleDismounted', {
vehicleId: this.currentVehicle.id,
rideDuration: Date.now() - this.currentVehicle.mountTime
});
console.log(`🚶 Dismounted ${vehicle.name}`);
this.currentVehicle = null;
return true;
}
// ===== VEHICLE PURCHASING =====
canPurchase(vehicleId) {
const vehicle = this.vehicleData[vehicleId];
if (!vehicle) {
return { canPurchase: false, reason: 'Vehicle not found' };
}
// Check if already owned
if (this.ownedVehicles.has(vehicleId)) {
return { canPurchase: false, reason: 'Already owned' };
}
// Check level
const playerLevel = this.scene.player?.stats?.level || 1;
if (playerLevel < vehicle.unlockLevel) {
return {
canPurchase: false,
reason: `Requires level ${vehicle.unlockLevel}`
};
}
// Check blueprint (if required)
if (vehicle.blueprint && this.scene.recipeSystem) {
if (!this.scene.recipeSystem.unlockedRecipes.has(vehicle.blueprint)) {
return { canPurchase: false, reason: 'Blueprint not unlocked' };
}
}
// Check gold
const playerGold = this.getPlayerGold();
if (playerGold < vehicle.cost) {
return {
canPurchase: false,
reason: `Need ${vehicle.cost} gold (have ${playerGold})`
};
}
return { canPurchase: true };
}
purchase(vehicleId) {
const check = this.canPurchase(vehicleId);
if (!check.canPurchase) {
this.scene.uiSystem?.showError(check.reason);
return false;
}
const vehicle = this.vehicleData[vehicleId];
// Deduct gold
this.removeGold(vehicle.cost);
// Add to owned vehicles
this.ownedVehicles.set(vehicleId, {
purchaseDate: Date.now(),
totalDistance: 0,
totalTime: 0
});
// Save
this.saveOwnedVehicles();
// Notification
this.scene.uiSystem?.showNotification({
title: '🚗 Vehicle Purchased!',
message: `${vehicle.name} is now yours!`,
icon: vehicle.sprite,
duration: 4000,
color: '#00FF00'
});
// Emit event
this.scene.events.emit('vehiclePurchased', { vehicleId, vehicle });
console.log(`💰 Purchased ${vehicle.name} for ${vehicle.cost} gold`);
return true;
}
// ===== TRAIN REPAIR SYSTEM =====
repairTrain(workAmount = 10) {
if (this.trainRepairProgress >= 100) {
this.scene.uiSystem?.showError('Train already repaired!');
return false;
}
// Add progress
this.trainRepairProgress += workAmount;
this.trainRepairProgress = Math.min(100, this.trainRepairProgress);
// Get current state
const state = this.getTrainRepairState();
// Show progress
this.scene.uiSystem?.showNotification({
title: 'Train Repair',
message: `${state} - ${this.trainRepairProgress.toFixed(0)}%`,
icon: 'train',
duration: 2000
});
// Check if just completed
if (this.trainRepairProgress === 100 && state === 'Rideable') {
this.unlockTrain();
}
// Emit event
this.scene.events.emit('trainRepairProgress', {
progress: this.trainRepairProgress,
state
});
return true;
}
getTrainRepairState() {
if (this.trainRepairProgress < 33) {
return 'Broken';
} else if (this.trainRepairProgress < 100) {
return 'Repairing';
} else {
return 'Rideable';
}
}
unlockTrain() {
// Add train to owned vehicles
this.ownedVehicles.set('train', {
purchaseDate: Date.now(),
totalDistance: 0,
totalTime: 0
});
this.saveOwnedVehicles();
// Big notification
this.scene.uiSystem?.showNotification({
title: '🎉 TRAIN REPAIRED!',
message: 'The steam train is ready to ride!',
icon: 'train',
duration: 6000,
color: '#FFD700'
});
this.scene.events.emit('trainUnlocked');
console.log('🚂 Train fully repaired and unlocked!');
}
// ===== TERRAIN BONUS SYSTEM =====
getSpeedModifier(x, y) {
if (!this.currentVehicle) return 1.0;
const vehicle = this.currentVehicle.data;
const tile = this.getTileAt(x, y);
const terrain = tile.properties?.terrain;
if (vehicle.terrainBonus && terrain && vehicle.terrainBonus[terrain]) {
return vehicle.terrainBonus[terrain];
}
return 1.0;
}
getCurrentSpeed() {
if (!this.currentVehicle) {
return this.scene.player?.baseSpeed || 100;
}
const baseSpeed = this.currentVehicle.data.speed;
const modifier = this.getSpeedModifier(this.scene.player.x, this.scene.player.y);
return baseSpeed * modifier;
}
// ===== HELPER FUNCTIONS =====
hasHorse() {
return this.ownedVehicles.has('horse_basic') ||
this.ownedVehicles.has('horse_fast') ||
this.ownedVehicles.has('horse_draft');
}
isOnTrack(x, y) {
// Check if position has train tracks
const tile = this.getTileAt(x, y);
return tile.properties?.hasTrack || false;
}
getTileAt(x, y) {
// Get tile from terrain system
if (this.scene.terrainSystem) {
return this.scene.terrainSystem.getTileAtWorldXY(x, y);
}
// Fallback
return { properties: {} };
}
getPlayerGold() {
if (this.scene.inventorySystem) {
return this.scene.inventorySystem.getQuantity('gold');
}
return this.scene.player?.inventory?.gold || 0;
}
removeGold(amount) {
if (this.scene.inventorySystem) {
this.scene.inventorySystem.removeItem('gold', amount);
} else {
this.scene.player.inventory.gold -= amount;
}
}
// ===== GETTERS =====
getVehicle(vehicleId) {
return this.vehicleData[vehicleId];
}
getAllVehicles() {
return Object.entries(this.vehicleData).map(([id, data]) => ({
id,
...data,
owned: this.ownedVehicles.has(id)
}));
}
getOwnedVehicles() {
return Array.from(this.ownedVehicles.keys());
}
getVehiclesByType(type) {
return this.getAllVehicles().filter(v => v.type === type);
}
getPurchasableVehicles() {
return this.getAllVehicles().filter(v =>
this.canPurchase(v.id).canPurchase
);
}
getCurrentVehicle() {
return this.currentVehicle;
}
isRiding() {
return this.currentVehicle !== null;
}
// ===== DATA PERSISTENCE =====
saveOwnedVehicles() {
const data = {
owned: Array.from(this.ownedVehicles.entries()),
trainProgress: this.trainRepairProgress
};
localStorage.setItem('ownedVehicles', JSON.stringify(data));
}
loadOwnedVehicles() {
const saved = localStorage.getItem('ownedVehicles');
if (saved) {
const data = JSON.parse(saved);
this.ownedVehicles = new Map(data.owned);
this.trainRepairProgress = data.trainProgress || 0;
console.log('🚗 Loaded', this.ownedVehicles.size, 'owned vehicles');
}
}
// ===== UPDATE =====
update(time, delta) {
if (this.currentVehicle) {
// Track distance and time
const deltaSeconds = delta / 1000;
const speed = this.getCurrentSpeed();
const distance = (speed * deltaSeconds) / 60; // Approximate
const stats = this.ownedVehicles.get(this.currentVehicle.id);
if (stats) {
stats.totalDistance += distance;
stats.totalTime += deltaSeconds;
}
// Update speed modifier based on terrain
const modifier = this.getSpeedModifier(this.scene.player.x, this.scene.player.y);
if (modifier !== 1.0) {
this.scene.player.setMaxVelocity(this.currentVehicle.data.speed * modifier);
}
}
}
// ===== CLEANUP =====
destroy() {
this.saveOwnedVehicles();
this.ownedVehicles.clear();
this.trainTracks = [];
this.currentVehicle = null;
}
}