- Complete combat system with instant, turn-based, and tactical combat - Plugin-based architecture with CombatPluginManager for extensibility - Real-time combat events via WebSocket - Fleet vs fleet and fleet vs colony combat support - Comprehensive combat statistics and history tracking - Admin panel for combat management and configuration - Database migrations for combat tables and fleet system - Complete test suite for combat functionality - Combat middleware for validation and logging - Service locator pattern for dependency management Combat system features: • Multiple combat resolution types with plugin support • Real-time combat events and spectator support • Detailed combat logs and casualty calculations • Experience gain and veterancy system for ships • Fleet positioning and tactical formations • Combat configurations and modifiers • Queue system for battle processing • Comprehensive admin controls and monitoring 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
314 lines
No EOL
12 KiB
JavaScript
314 lines
No EOL
12 KiB
JavaScript
#!/usr/bin/env node
|
||
|
||
/**
|
||
* Combat System Setup Script
|
||
* Initializes combat configurations and sample data
|
||
*/
|
||
|
||
const db = require('../src/database/connection');
|
||
const logger = require('../src/utils/logger');
|
||
|
||
async function setupCombatSystem() {
|
||
try {
|
||
console.log('🚀 Setting up combat system...');
|
||
|
||
// Insert default combat configurations
|
||
console.log('📝 Adding default combat configurations...');
|
||
|
||
const existingConfigs = await db('combat_configurations').select('id');
|
||
if (existingConfigs.length === 0) {
|
||
await db('combat_configurations').insert([
|
||
{
|
||
config_name: 'instant_combat',
|
||
combat_type: 'instant',
|
||
config_data: JSON.stringify({
|
||
auto_resolve: true,
|
||
preparation_time: 5,
|
||
damage_variance: 0.15,
|
||
experience_gain: 1.0,
|
||
casualty_rate_min: 0.05,
|
||
casualty_rate_max: 0.75,
|
||
loot_multiplier: 1.0,
|
||
spectator_limit: 50,
|
||
priority: 100
|
||
}),
|
||
description: 'Standard instant combat resolution with quick results',
|
||
is_active: true,
|
||
created_at: new Date(),
|
||
updated_at: new Date()
|
||
},
|
||
{
|
||
config_name: 'turn_based_combat',
|
||
combat_type: 'turn_based',
|
||
config_data: JSON.stringify({
|
||
auto_resolve: true,
|
||
preparation_time: 10,
|
||
max_rounds: 15,
|
||
round_duration: 3,
|
||
damage_variance: 0.2,
|
||
experience_gain: 1.5,
|
||
casualty_rate_min: 0.1,
|
||
casualty_rate_max: 0.8,
|
||
loot_multiplier: 1.2,
|
||
spectator_limit: 100,
|
||
priority: 150
|
||
}),
|
||
description: 'Detailed turn-based combat with round-by-round resolution',
|
||
is_active: true,
|
||
created_at: new Date(),
|
||
updated_at: new Date()
|
||
},
|
||
{
|
||
config_name: 'tactical_combat',
|
||
combat_type: 'tactical',
|
||
config_data: JSON.stringify({
|
||
auto_resolve: true,
|
||
preparation_time: 15,
|
||
max_rounds: 20,
|
||
round_duration: 4,
|
||
damage_variance: 0.25,
|
||
experience_gain: 2.0,
|
||
casualty_rate_min: 0.15,
|
||
casualty_rate_max: 0.85,
|
||
loot_multiplier: 1.5,
|
||
spectator_limit: 200,
|
||
priority: 200
|
||
}),
|
||
description: 'Advanced tactical combat with positioning and formations',
|
||
is_active: true,
|
||
created_at: new Date(),
|
||
updated_at: new Date()
|
||
}
|
||
]);
|
||
|
||
console.log('✅ Combat configurations added successfully');
|
||
} else {
|
||
console.log('ℹ️ Combat configurations already exist, skipping...');
|
||
}
|
||
|
||
// Update combat types table with default plugin reference
|
||
console.log('📝 Updating combat types...');
|
||
|
||
const existingCombatTypes = await db('combat_types').select('id');
|
||
if (existingCombatTypes.length === 0) {
|
||
await db('combat_types').insert([
|
||
{
|
||
name: 'instant_resolution',
|
||
description: 'Basic instant combat resolution with detailed logs',
|
||
plugin_name: 'instant_combat',
|
||
config: JSON.stringify({
|
||
calculate_experience: true,
|
||
detailed_logs: true,
|
||
enable_spectators: true
|
||
}),
|
||
is_active: true
|
||
},
|
||
{
|
||
name: 'turn_based_resolution',
|
||
description: 'Turn-based combat with round-by-round progression',
|
||
plugin_name: 'turn_based_combat',
|
||
config: JSON.stringify({
|
||
calculate_experience: true,
|
||
detailed_logs: true,
|
||
enable_spectators: true,
|
||
show_round_details: true
|
||
}),
|
||
is_active: true
|
||
},
|
||
{
|
||
name: 'tactical_resolution',
|
||
description: 'Advanced tactical combat with formations and positioning',
|
||
plugin_name: 'tactical_combat',
|
||
config: JSON.stringify({
|
||
calculate_experience: true,
|
||
detailed_logs: true,
|
||
enable_spectators: true,
|
||
enable_formations: true,
|
||
enable_positioning: true
|
||
}),
|
||
is_active: true
|
||
}
|
||
]);
|
||
|
||
console.log('✅ Combat types added successfully');
|
||
} else {
|
||
console.log('ℹ️ Combat types already exist, skipping...');
|
||
}
|
||
|
||
// Ensure combat plugins are properly registered
|
||
console.log('📝 Checking combat plugins...');
|
||
|
||
const combatPlugins = await db('plugins').where('plugin_type', 'combat');
|
||
const pluginNames = combatPlugins.map(p => p.name);
|
||
|
||
const requiredPlugins = [
|
||
{
|
||
name: 'instant_combat',
|
||
version: '1.0.0',
|
||
description: 'Basic instant combat resolution system',
|
||
plugin_type: 'combat',
|
||
is_active: true,
|
||
config: JSON.stringify({
|
||
damage_variance: 0.15,
|
||
experience_gain: 1.0
|
||
}),
|
||
dependencies: JSON.stringify([]),
|
||
hooks: JSON.stringify(['pre_combat', 'post_combat', 'damage_calculation'])
|
||
},
|
||
{
|
||
name: 'turn_based_combat',
|
||
version: '1.0.0',
|
||
description: 'Turn-based combat resolution system with detailed rounds',
|
||
plugin_type: 'combat',
|
||
is_active: true,
|
||
config: JSON.stringify({
|
||
max_rounds: 15,
|
||
damage_variance: 0.2,
|
||
experience_gain: 1.5
|
||
}),
|
||
dependencies: JSON.stringify([]),
|
||
hooks: JSON.stringify(['pre_combat', 'post_combat', 'round_start', 'round_end', 'damage_calculation'])
|
||
},
|
||
{
|
||
name: 'tactical_combat',
|
||
version: '1.0.0',
|
||
description: 'Advanced tactical combat with formations and positioning',
|
||
plugin_type: 'combat',
|
||
is_active: true,
|
||
config: JSON.stringify({
|
||
enable_formations: true,
|
||
enable_positioning: true,
|
||
damage_variance: 0.25,
|
||
experience_gain: 2.0
|
||
}),
|
||
dependencies: JSON.stringify([]),
|
||
hooks: JSON.stringify(['pre_combat', 'post_combat', 'formation_change', 'position_update', 'damage_calculation'])
|
||
}
|
||
];
|
||
|
||
for (const plugin of requiredPlugins) {
|
||
if (!pluginNames.includes(plugin.name)) {
|
||
await db('plugins').insert(plugin);
|
||
console.log(`✅ Added combat plugin: ${plugin.name}`);
|
||
} else {
|
||
console.log(`ℹ️ Combat plugin ${plugin.name} already exists`);
|
||
}
|
||
}
|
||
|
||
// Add sample ship designs if none exist (for testing)
|
||
console.log('📝 Checking for sample ship designs...');
|
||
|
||
const existingDesigns = await db('ship_designs').where('is_public', true);
|
||
if (existingDesigns.length === 0) {
|
||
await db('ship_designs').insert([
|
||
{
|
||
name: 'Basic Fighter',
|
||
ship_class: 'fighter',
|
||
hull_type: 'light',
|
||
components: JSON.stringify({
|
||
weapons: ['laser_cannon'],
|
||
shields: ['basic_shield'],
|
||
engines: ['ion_drive']
|
||
}),
|
||
stats: JSON.stringify({
|
||
hp: 75,
|
||
attack: 12,
|
||
defense: 8,
|
||
speed: 6
|
||
}),
|
||
cost: JSON.stringify({
|
||
scrap: 80,
|
||
energy: 40
|
||
}),
|
||
build_time: 20,
|
||
is_public: true,
|
||
is_active: true,
|
||
hull_points: 75,
|
||
shield_points: 20,
|
||
armor_points: 5,
|
||
attack_power: 12,
|
||
attack_speed: 1.2,
|
||
movement_speed: 6,
|
||
cargo_capacity: 0,
|
||
special_abilities: JSON.stringify([]),
|
||
damage_resistances: JSON.stringify({}),
|
||
created_at: new Date(),
|
||
updated_at: new Date()
|
||
},
|
||
{
|
||
name: 'Heavy Cruiser',
|
||
ship_class: 'cruiser',
|
||
hull_type: 'heavy',
|
||
components: JSON.stringify({
|
||
weapons: ['plasma_cannon', 'missile_launcher'],
|
||
shields: ['reinforced_shield'],
|
||
engines: ['fusion_drive']
|
||
}),
|
||
stats: JSON.stringify({
|
||
hp: 200,
|
||
attack: 25,
|
||
defense: 18,
|
||
speed: 3
|
||
}),
|
||
cost: JSON.stringify({
|
||
scrap: 300,
|
||
energy: 180,
|
||
rare_elements: 5
|
||
}),
|
||
build_time: 120,
|
||
is_public: true,
|
||
is_active: true,
|
||
hull_points: 200,
|
||
shield_points: 60,
|
||
armor_points: 25,
|
||
attack_power: 25,
|
||
attack_speed: 0.8,
|
||
movement_speed: 3,
|
||
cargo_capacity: 50,
|
||
special_abilities: JSON.stringify(['heavy_armor', 'shield_boost']),
|
||
damage_resistances: JSON.stringify({
|
||
kinetic: 0.1,
|
||
energy: 0.05
|
||
}),
|
||
created_at: new Date(),
|
||
updated_at: new Date()
|
||
}
|
||
]);
|
||
|
||
console.log('✅ Added sample ship designs');
|
||
} else {
|
||
console.log('ℹ️ Ship designs already exist, skipping...');
|
||
}
|
||
|
||
console.log('🎉 Combat system setup completed successfully!');
|
||
console.log('');
|
||
console.log('Combat system is now ready for use with:');
|
||
console.log('- 3 combat configurations (instant, turn-based, tactical)');
|
||
console.log('- 3 combat resolution plugins');
|
||
console.log('- Sample ship designs for testing');
|
||
console.log('');
|
||
console.log('You can now:');
|
||
console.log('• Create fleets and initiate combat via /api/combat/initiate');
|
||
console.log('• View combat history via /api/combat/history');
|
||
console.log('• Manage combat system via admin endpoints');
|
||
|
||
} catch (error) {
|
||
console.error('❌ Combat system setup failed:', error);
|
||
throw error;
|
||
}
|
||
}
|
||
|
||
// Main execution
|
||
if (require.main === module) {
|
||
setupCombatSystem()
|
||
.then(() => {
|
||
console.log('✨ Setup completed successfully');
|
||
process.exit(0);
|
||
})
|
||
.catch(error => {
|
||
console.error('💥 Setup failed:', error);
|
||
process.exit(1);
|
||
});
|
||
}
|
||
|
||
module.exports = { setupCombatSystem }; |