Shatteredvoid/src/database/migrations/006_combat_system_enhancement.js
MegaProxy d41d1e8125 feat: implement complete Phase 2 frontend foundation with React 18
Major milestone: Frontend implementation complete for Shattered Void MMO

FRONTEND IMPLEMENTATION:
- React 18 + TypeScript + Vite development environment
- Tailwind CSS with custom dark theme for sci-fi aesthetic
- Zustand state management with authentication persistence
- Socket.io WebSocket client with auto-reconnection
- Protected routing with authentication guards
- Responsive design with mobile-first approach

AUTHENTICATION SYSTEM:
- Login/register forms with comprehensive validation
- JWT token management with localStorage persistence
- Password strength validation and user feedback
- Protected routes and authentication guards

CORE GAME INTERFACE:
- Colony management dashboard with real-time updates
- Resource display with live production tracking
- WebSocket integration for real-time game events
- Navigation with connection status indicator
- Toast notifications for user feedback

BACKEND ENHANCEMENTS:
- Complete Research System with technology tree (23 technologies)
- Fleet Management System with ship designs and movement
- Enhanced Authentication with email verification and password reset
- Complete game tick integration for all systems
- Advanced WebSocket events for real-time updates

ARCHITECTURE FEATURES:
- Type-safe TypeScript throughout
- Component-based architecture with reusable UI elements
- API client with request/response interceptors
- Error handling and loading states
- Performance optimized builds with code splitting

Phase 2 Status: Frontend foundation complete (Week 1-2 objectives met)
Ready for: Colony management, fleet operations, research interface
Next: Enhanced gameplay features and admin interface

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-02 18:36:06 +00:00

292 lines
13 KiB
JavaScript

/**
* Combat System Enhancement Migration
* Adds comprehensive combat tables and enhancements for production-ready combat system
*/
exports.up = function (knex) {
return knex.schema
// Combat types table - defines different combat resolution types
.createTable('combat_types', (table) => {
table.increments('id').primary();
table.string('name', 100).unique().notNullable();
table.text('description');
table.string('plugin_name', 100); // References plugins table
table.jsonb('config');
table.boolean('is_active').defaultTo(true);
table.index(['is_active']);
table.index(['plugin_name']);
})
// Main battles table - tracks all combat encounters
.createTable('battles', (table) => {
table.bigIncrements('id').primary();
table.string('battle_type', 50).notNullable(); // 'fleet_vs_fleet', 'fleet_vs_colony', 'siege'
table.string('location', 20).notNullable();
table.integer('combat_type_id').references('combat_types.id');
table.jsonb('participants').notNullable(); // Array of fleet/player IDs
table.string('status', 20).notNullable().defaultTo('pending'); // 'pending', 'active', 'completed', 'cancelled'
table.jsonb('battle_data'); // Additional battle configuration
table.jsonb('result'); // Final battle results
table.timestamp('started_at').defaultTo(knex.fn.now());
table.timestamp('completed_at').nullable();
table.timestamp('created_at').defaultTo(knex.fn.now());
table.index(['location']);
table.index(['status']);
table.index(['completed_at']);
table.index(['started_at']);
})
// Combat encounters table for detailed battle tracking
.createTable('combat_encounters', (table) => {
table.bigIncrements('id').primary();
table.integer('battle_id').references('battles.id').onDelete('CASCADE');
table.integer('attacker_fleet_id').references('fleets.id').onDelete('CASCADE').notNullable();
table.integer('defender_fleet_id').references('fleets.id').onDelete('CASCADE');
table.integer('defender_colony_id').references('colonies.id').onDelete('CASCADE');
table.string('encounter_type', 50).notNullable(); // 'fleet_vs_fleet', 'fleet_vs_colony', 'siege'
table.string('location', 20).notNullable();
table.jsonb('initial_forces').notNullable(); // Starting forces for both sides
table.jsonb('final_forces').notNullable(); // Remaining forces after combat
table.jsonb('casualties').notNullable(); // Detailed casualty breakdown
table.jsonb('combat_log').notNullable(); // Round-by-round combat log
table.decimal('experience_gained', 10, 2).defaultTo(0);
table.jsonb('loot_awarded'); // Resources/items awarded to winner
table.string('outcome', 20).notNullable(); // 'attacker_victory', 'defender_victory', 'draw'
table.integer('duration_seconds').notNullable(); // Combat duration
table.timestamp('started_at').notNullable();
table.timestamp('completed_at').notNullable();
table.timestamp('created_at').defaultTo(knex.fn.now());
table.index(['battle_id']);
table.index(['attacker_fleet_id']);
table.index(['defender_fleet_id']);
table.index(['defender_colony_id']);
table.index(['location']);
table.index(['outcome']);
table.index(['started_at']);
})
// Combat logs for detailed event tracking
.createTable('combat_logs', (table) => {
table.bigIncrements('id').primary();
table.bigInteger('encounter_id').references('combat_encounters.id').onDelete('CASCADE').notNullable();
table.integer('round_number').notNullable();
table.string('event_type', 50).notNullable(); // 'damage', 'destruction', 'ability_use', 'experience_gain'
table.jsonb('event_data').notNullable(); // Detailed event information
table.timestamp('timestamp').defaultTo(knex.fn.now());
table.index(['encounter_id', 'round_number']);
table.index(['event_type']);
table.index(['timestamp']);
})
// Combat statistics for analysis and balancing
.createTable('combat_statistics', (table) => {
table.bigIncrements('id').primary();
table.integer('player_id').references('players.id').onDelete('CASCADE').notNullable();
table.integer('battles_initiated').defaultTo(0);
table.integer('battles_won').defaultTo(0);
table.integer('battles_lost').defaultTo(0);
table.integer('ships_lost').defaultTo(0);
table.integer('ships_destroyed').defaultTo(0);
table.bigInteger('total_damage_dealt').defaultTo(0);
table.bigInteger('total_damage_received').defaultTo(0);
table.decimal('total_experience_gained', 15, 2).defaultTo(0);
table.jsonb('resources_looted').defaultTo('{}');
table.timestamp('last_battle').nullable();
table.timestamp('created_at').defaultTo(knex.fn.now());
table.timestamp('updated_at').defaultTo(knex.fn.now());
table.index(['player_id']);
table.index(['battles_won']);
table.index(['last_battle']);
})
// Ship combat experience and veterancy
.createTable('ship_combat_experience', (table) => {
table.bigIncrements('id').primary();
table.integer('fleet_id').references('fleets.id').onDelete('CASCADE').notNullable();
table.integer('ship_design_id').references('ship_designs.id').onDelete('CASCADE').notNullable();
table.integer('battles_survived').defaultTo(0);
table.integer('enemies_destroyed').defaultTo(0);
table.bigInteger('damage_dealt').defaultTo(0);
table.decimal('experience_points', 15, 2).defaultTo(0);
table.integer('veterancy_level').defaultTo(1);
table.jsonb('combat_bonuses').defaultTo('{}'); // Experience-based bonuses
table.timestamp('last_combat').nullable();
table.timestamp('created_at').defaultTo(knex.fn.now());
table.timestamp('updated_at').defaultTo(knex.fn.now());
table.unique(['fleet_id', 'ship_design_id']);
table.index(['fleet_id']);
table.index(['veterancy_level']);
table.index(['last_combat']);
})
// Combat configurations for different combat types
.createTable('combat_configurations', (table) => {
table.increments('id').primary();
table.string('config_name', 100).unique().notNullable();
table.string('combat_type', 50).notNullable(); // 'instant', 'turn_based', 'real_time'
table.jsonb('config_data').notNullable(); // Combat-specific configuration
table.boolean('is_active').defaultTo(true);
table.string('description', 500);
table.timestamp('created_at').defaultTo(knex.fn.now());
table.timestamp('updated_at').defaultTo(knex.fn.now());
table.index(['combat_type']);
table.index(['is_active']);
})
// Combat modifiers for temporary effects
.createTable('combat_modifiers', (table) => {
table.bigIncrements('id').primary();
table.string('entity_type', 50).notNullable(); // 'fleet', 'colony', 'player'
table.integer('entity_id').notNullable();
table.string('modifier_type', 50).notNullable(); // 'attack_bonus', 'defense_bonus', 'speed_bonus'
table.decimal('modifier_value', 8, 4).notNullable();
table.string('source', 100).notNullable(); // 'technology', 'event', 'building', 'experience'
table.timestamp('start_time').defaultTo(knex.fn.now());
table.timestamp('end_time').nullable();
table.boolean('is_active').defaultTo(true);
table.jsonb('metadata'); // Additional modifier information
table.index(['entity_type', 'entity_id']);
table.index(['modifier_type']);
table.index(['is_active']);
table.index(['end_time']);
})
// Fleet positioning for tactical combat
.createTable('fleet_positions', (table) => {
table.bigIncrements('id').primary();
table.integer('fleet_id').references('fleets.id').onDelete('CASCADE').notNullable();
table.string('location', 20).notNullable();
table.decimal('position_x', 8, 2).defaultTo(0);
table.decimal('position_y', 8, 2).defaultTo(0);
table.decimal('position_z', 8, 2).defaultTo(0);
table.string('formation', 50).defaultTo('standard'); // 'standard', 'defensive', 'aggressive', 'flanking'
table.jsonb('tactical_settings').defaultTo('{}'); // Formation-specific settings
table.timestamp('last_updated').defaultTo(knex.fn.now());
table.unique(['fleet_id']);
table.index(['location']);
table.index(['formation']);
})
// Combat queue for processing battles
.createTable('combat_queue', (table) => {
table.bigIncrements('id').primary();
table.bigInteger('battle_id').references('battles.id').onDelete('CASCADE').notNullable();
table.string('queue_status', 20).defaultTo('pending'); // 'pending', 'processing', 'completed', 'failed'
table.integer('priority').defaultTo(100);
table.timestamp('scheduled_at').defaultTo(knex.fn.now());
table.timestamp('started_processing').nullable();
table.timestamp('completed_at').nullable();
table.integer('retry_count').defaultTo(0);
table.text('error_message').nullable();
table.jsonb('processing_metadata');
table.index(['queue_status']);
table.index(['priority', 'scheduled_at']);
table.index(['battle_id']);
})
// Extend battles table with additional fields
.alterTable('battles', (table) => {
table.integer('combat_configuration_id').references('combat_configurations.id');
table.jsonb('tactical_settings').defaultTo('{}');
table.integer('spectator_count').defaultTo(0);
table.jsonb('environmental_effects'); // Weather, nebulae, asteroid fields
table.decimal('estimated_duration', 8, 2); // Estimated battle duration in seconds
})
// Extend fleets table with combat-specific fields
.alterTable('fleets', (table) => {
table.decimal('combat_rating', 10, 2).defaultTo(0); // Calculated combat effectiveness
table.integer('total_ship_count').defaultTo(0);
table.jsonb('fleet_composition').defaultTo('{}'); // Ship type breakdown
table.timestamp('last_combat').nullable();
table.integer('combat_victories').defaultTo(0);
table.integer('combat_defeats').defaultTo(0);
})
// Extend ship_designs table with detailed combat stats
.alterTable('ship_designs', (table) => {
table.integer('hull_points').defaultTo(100);
table.integer('shield_points').defaultTo(0);
table.integer('armor_points').defaultTo(0);
table.decimal('attack_power', 8, 2).defaultTo(10);
table.decimal('attack_speed', 6, 2).defaultTo(1.0); // Attacks per second
table.decimal('movement_speed', 6, 2).defaultTo(1.0);
table.integer('cargo_capacity').defaultTo(0);
table.jsonb('special_abilities').defaultTo('[]');
table.jsonb('damage_resistances').defaultTo('{}');
})
// Colony defense enhancements
.alterTable('colonies', (table) => {
table.integer('defense_rating').defaultTo(0);
table.integer('shield_strength').defaultTo(0);
table.boolean('under_siege').defaultTo(false);
table.timestamp('last_attacked').nullable();
table.integer('successful_defenses').defaultTo(0);
table.integer('times_captured').defaultTo(0);
});
};
exports.down = function (knex) {
return knex.schema
// Remove added columns first
.alterTable('colonies', (table) => {
table.dropColumn('defense_rating');
table.dropColumn('shield_strength');
table.dropColumn('under_siege');
table.dropColumn('last_attacked');
table.dropColumn('successful_defenses');
table.dropColumn('times_captured');
})
.alterTable('ship_designs', (table) => {
table.dropColumn('hull_points');
table.dropColumn('shield_points');
table.dropColumn('armor_points');
table.dropColumn('attack_power');
table.dropColumn('attack_speed');
table.dropColumn('movement_speed');
table.dropColumn('cargo_capacity');
table.dropColumn('special_abilities');
table.dropColumn('damage_resistances');
})
.alterTable('fleets', (table) => {
table.dropColumn('combat_rating');
table.dropColumn('total_ship_count');
table.dropColumn('fleet_composition');
table.dropColumn('last_combat');
table.dropColumn('combat_victories');
table.dropColumn('combat_defeats');
})
.alterTable('battles', (table) => {
table.dropColumn('combat_configuration_id');
table.dropColumn('tactical_settings');
table.dropColumn('spectator_count');
table.dropColumn('environmental_effects');
table.dropColumn('estimated_duration');
})
// Drop new tables
.dropTableIfExists('combat_queue')
.dropTableIfExists('fleet_positions')
.dropTableIfExists('combat_modifiers')
.dropTableIfExists('combat_configurations')
.dropTableIfExists('ship_combat_experience')
.dropTableIfExists('combat_statistics')
.dropTableIfExists('combat_logs')
.dropTableIfExists('combat_encounters')
.dropTableIfExists('battles')
.dropTableIfExists('combat_types');
};