diff --git a/admin.php b/admin.php index 68cc25d..51b5060 100644 --- a/admin.php +++ b/admin.php @@ -171,6 +171,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST[' $name = $_POST['name']; $slug = $_POST['slug']; $fa_icon = $_POST['fa_icon']; + $color = $_POST['color']; $image_url = null; if ($id > 0) { $stmt_img = $db->prepare("SELECT image_url FROM factions WHERE id = ?"); @@ -186,11 +187,11 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST[' } } if ($id > 0) { - $stmt = $db->prepare("UPDATE factions SET name = ?, slug = ?, image_url = ?, fa_icon = ? WHERE id = ?"); - $stmt->execute([$name, $slug, $image_url, $fa_icon, $id]); + $stmt = $db->prepare("UPDATE factions SET name = ?, slug = ?, image_url = ?, fa_icon = ?, color = ? WHERE id = ?"); + $stmt->execute([$name, $slug, $image_url, $fa_icon, $color, $id]); } else { - $stmt = $db->prepare("INSERT INTO factions (name, slug, image_url, fa_icon) VALUES (?, ?, ?, ?)"); - $stmt->execute([$name, $slug, $image_url, $fa_icon]); + $stmt = $db->prepare("INSERT INTO factions (name, slug, image_url, fa_icon, color) VALUES (?, ?, ?, ?, ?)"); + $stmt->execute([$name, $slug, $image_url, $fa_icon, $color]); } header("Location: admin.php?tab=factions&success=1"); exit; @@ -410,7 +411,7 @@ if ($tab === 'users') {
| Visuel | Nom | Slug | Actions | |
|---|---|---|---|---|
| Couleur | Visuel | Nom | Slug | Actions |
|
|
@@ -992,10 +998,11 @@ if ($tab === 'users') { document.getElementById('fac_id').value = data.id; document.getElementById('fac_name').value = data.name; document.getElementById('fac_slug').value = data.slug || ''; + document.getElementById('fac_color').value = data.color || '#808080'; document.getElementById('fac_fa_icon').value = data.fa_icon || ''; window.scrollTo(0,0); } - function resetFactionForm() { document.getElementById('factionForm').reset(); document.getElementById('fac_id').value = 0; } + function resetFactionForm() { document.getElementById('factionForm').reset(); document.getElementById('fac_id').value = 0; document.getElementById('fac_color').value = '#808080'; } function editResource(data) { document.getElementById('res_id').value = data.id; diff --git a/assets/images/celestial/obj_planet_tempered_01_1771805362.png b/assets/images/celestial/obj_planet_tempered_01_1771805362.png new file mode 100644 index 0000000..10f69c0 Binary files /dev/null and b/assets/images/celestial/obj_planet_tempered_01_1771805362.png differ diff --git a/db/add_color_to_factions.php b/db/add_color_to_factions.php new file mode 100644 index 0000000..a4b2143 --- /dev/null +++ b/db/add_color_to_factions.php @@ -0,0 +1,11 @@ +exec("ALTER TABLE factions ADD COLUMN color VARCHAR(7) DEFAULT '#808080' AFTER fa_icon"); + echo "Successfully added 'color' column to 'factions' table.\n"; +} catch (PDOException $e) { + echo "Error adding column: " . $e->getMessage() . "\n"; +} + diff --git a/db/migrate_orbital_control.sql b/db/migrate_orbital_control.sql new file mode 100644 index 0000000..0de6a9d --- /dev/null +++ b/db/migrate_orbital_control.sql @@ -0,0 +1,9 @@ +-- Create table for orbital faction control +CREATE TABLE IF NOT EXISTS planet_faction_control ( + planet_id INT(11) NOT NULL, + faction_id INT(11) NOT NULL, + control_level INT(11) NOT NULL DEFAULT 0, + PRIMARY KEY (planet_id, faction_id), + CONSTRAINT fk_planet_faction_control_planet FOREIGN KEY (planet_id) REFERENCES planets(id) ON DELETE CASCADE, + CONSTRAINT fk_planet_faction_control_faction FOREIGN KEY (faction_id) REFERENCES factions(id) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; diff --git a/gm_console.php b/gm_console.php index 5dc6475..2244020 100644 --- a/gm_console.php +++ b/gm_console.php @@ -32,33 +32,96 @@ $factions_map = []; foreach($factions_db as $f) $factions_map[$f['id']] = $f; // Handle Planet/Slot Update if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'update_slot') { - $slot_id = (int)$_POST['slot_id']; - $galaxy_id = (int)$_POST['galaxy_id']; - $sector_id = (int)$_POST['sector_id']; - $slot_num = (int)$_POST['slot_num']; - $name = $_POST['name']; - $type = $_POST['type']; - $status = $_POST['status']; - $faction_id = (int)$_POST['faction_id']; - $orbital = (int)$_POST['orbital_control']; - $terrestrial = (int)$_POST['terrestrial_control']; + $slot_id = (int)($_POST['slot_id'] ?? 0); + $galaxy_id = (int)($_POST['galaxy_id'] ?? 1); + $sector_id = (int)($_POST['sector_id'] ?? 1); + $slot_num = (int)($_POST['slot_num'] ?? 0); + $name = $_POST['name'] ?? 'Inconnu'; + $type = $_POST['type'] ?? 'empty'; + + // Orbital control is now detailed by faction + $orbital_controls = $_POST['orbital_controls'] ?? []; + $dominant_orbital_val = 0; + $dominant_orbital_faction = null; + foreach($orbital_controls as $fid => $val) { + if ((int)$val > $dominant_orbital_val && (int)$fid != 1) { // Not "Aucune" + $dominant_orbital_val = (int)$val; + $dominant_orbital_faction = (int)$fid; + } + } + + // Derive Status and Faction from Settlements + $status = 'sta_empty'; + $faction_id = null; + $total_non_aucun = 0; + $active_factions = []; + $num_cities = 0; + $avg_terrestrial_control = 0; + + if (isset($_POST['cities']) && is_array($_POST['cities'])) { + foreach ($_POST['cities'] as $city_data) { + if (empty($city_data['name'])) continue; + $num_cities++; + if (isset($city_data['controls']) && is_array($city_data['controls'])) { + foreach ($city_data['controls'] as $f_id => $lvl) { + $lvl = (int)$lvl; + if ($lvl > 0 && $f_id != 1) { // 1 is "Aucune" + $total_non_aucun += $lvl; + $active_factions[$f_id] = ($active_factions[$f_id] ?? 0) + $lvl; + $avg_terrestrial_control += $lvl; + } + } + } + } + } + + if ($num_cities > 0) { + $avg_terrestrial_control = round($avg_terrestrial_control / $num_cities); + } + + if ($num_cities > 0 && $total_non_aucun > 0) { + arsort($active_factions); + $faction_id = (int)key($active_factions); + + if (count($active_factions) > 1) { + $status = 'sta_hostile'; + } else { + if ($total_non_aucun >= ($num_cities * 100)) { + $status = 'sta_controlled'; + } else { + $status = 'sta_contested'; + } + } + } else if ($type !== 'empty') { + $status = 'sta_empty'; + $faction_id = null; + } if ($type === 'empty') { if ($slot_id > 0) { $db->prepare("DELETE FROM cities WHERE planet_id = ?")->execute([$slot_id]); + $db->prepare("DELETE FROM planet_faction_control WHERE planet_id = ?")->execute([$slot_id]); $db->prepare("DELETE FROM planets WHERE id = ?")->execute([$slot_id]); } } else { if ($slot_id > 0) { $stmt = $db->prepare("UPDATE planets SET name = ?, type = ?, status = ?, faction_id = ?, orbital_control = ?, terrestrial_control = ? WHERE id = ?"); - $stmt->execute([$name, $type, $status, $faction_id, $orbital, $terrestrial, $slot_id]); + $stmt->execute([$name, $type, $status, $faction_id, $dominant_orbital_val, $avg_terrestrial_control, $slot_id]); $planet_id = $slot_id; } else { $stmt = $db->prepare("INSERT INTO planets (galaxy_id, sector_id, slot, name, type, status, faction_id, orbital_control, terrestrial_control) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"); - $stmt->execute([$galaxy_id, $sector_id, $slot_num, $name, $type, $status, $faction_id, $orbital, $terrestrial]); + $stmt->execute([$galaxy_id, $sector_id, $slot_num, $name, $type, $status, $faction_id, $dominant_orbital_val, $avg_terrestrial_control]); $planet_id = $db->lastInsertId(); } + // Handle Orbital Faction Control + $db->prepare("DELETE FROM planet_faction_control WHERE planet_id = ?")->execute([$planet_id]); + foreach($orbital_controls as $fid => $lvl) { + if ((int)$lvl > 0) { + $db->prepare("INSERT INTO planet_faction_control (planet_id, faction_id, control_level) VALUES (?, ?, ?)")->execute([$planet_id, (int)$fid, (int)$lvl]); + } + } + // Handle Multiple Settlements $sent_city_ids = []; if (isset($_POST['cities']) && is_array($_POST['cities'])) { @@ -67,20 +130,32 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST[' $c_id = (int)($city_data['id'] ?? 0); $c_name = $city_data['name']; - $c_type_id = (int)$city_data['type_id']; + $c_type_id = !empty($city_data['type_id']) ? (int)$city_data['type_id'] : null; if ($c_id > 0) { $stmt = $db->prepare("UPDATE cities SET name = ?, settlement_type_id = ? WHERE id = ? AND planet_id = ?"); $stmt->execute([$c_name, $c_type_id, $c_id, $planet_id]); - $sent_city_ids[] = $c_id; + $city_id = $c_id; } else { $stmt = $db->prepare("INSERT INTO cities (planet_id, name, settlement_type_id) VALUES (?, ?, ?)"); - $stmt->execute([$c_name, $c_type_id]); - $sent_city_ids[] = $db->lastInsertId(); + $stmt->execute([$planet_id, $c_name, $c_type_id]); + $city_id = $db->lastInsertId(); + } + $sent_city_ids[] = $city_id; + + // Handle Faction Control + $db->prepare("DELETE FROM city_faction_control WHERE city_id = ?")->execute([$city_id]); + if (isset($city_data['controls']) && is_array($city_data['controls'])) { + foreach ($city_data['controls'] as $fac_id => $control_lvl) { + $control_lvl = (int)$control_lvl; + if ($control_lvl > 0) { + $stmt = $db->prepare("INSERT INTO city_faction_control (city_id, faction_id, control_level) VALUES (?, ?, ?)"); + $stmt->execute([$city_id, (int)$fac_id, $control_lvl]); + } + } } } } - // Delete cities that were removed in the UI if ($planet_id > 0) { if (empty($sent_city_ids)) { $db->prepare("DELETE FROM cities WHERE planet_id = ?")->execute([$planet_id]); @@ -100,8 +175,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST[' if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'update_sector') { $sector_id = (int)$_POST['sector_id']; $galaxy_id = (int)$_POST['galaxy_id']; - $s_name = $_POST['sector_name']; - $s_status = $_POST['sector_status']; + $s_name = $_POST['sector_name'] ?? "Secteur $sector_id"; + $s_status = $_POST['sector_status'] ?? 'unexplored'; $stmt = $db->prepare("INSERT INTO sectors (id, galaxy_id, name, status) VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE name = ?, status = ?"); $stmt->execute([$sector_id, $galaxy_id, $s_name, $s_status, $s_name, $s_status]); @@ -126,14 +201,42 @@ if ($view === 'sector') { $grid[$obj['slot']] = $obj; $planet_ids[] = $obj['id']; $grid[$obj['slot']]['cities'] = []; + $grid[$obj['slot']]['orbital_controls'] = []; } if (!empty($planet_ids)) { + // Fetch Orbital Controls $placeholders = implode(',', array_fill(0, count($planet_ids), '?')); + $stmt = $db->prepare("SELECT * FROM planet_faction_control WHERE planet_id IN ($placeholders)"); + $stmt->execute($planet_ids); + $orb_controls_raw = $stmt->fetchAll(PDO::FETCH_ASSOC); + foreach ($orb_controls_raw as $ocr) { + foreach ($grid as &$slot_data) { + if ($slot_data && $slot_data['id'] == $ocr['planet_id']) { + $slot_data['orbital_controls'][$ocr['faction_id']] = $ocr['control_level']; + } + } + } + + // Fetch Cities $stmt = $db->prepare("SELECT * FROM cities WHERE planet_id IN ($placeholders)"); $stmt->execute($planet_ids); - $all_cities = $stmt->fetchAll(); + $all_cities = $stmt->fetchAll(PDO::FETCH_ASSOC); + + $city_ids = array_column($all_cities, 'id'); + $city_controls = []; + if (!empty($city_ids)) { + $c_placeholders = implode(',', array_fill(0, count($city_ids), '?')); + $c_stmt = $db->prepare("SELECT * FROM city_faction_control WHERE city_id IN ($c_placeholders)"); + $c_stmt->execute($city_ids); + $controls_raw = $c_stmt->fetchAll(PDO::FETCH_ASSOC); + foreach ($controls_raw as $cr) { + $city_controls[$cr['city_id']][$cr['faction_id']] = $cr['control_level']; + } + } + foreach ($all_cities as $city) { + $city['controls'] = $city_controls[$city['id']] ?? []; foreach ($grid as &$slot_data) { if ($slot_data && $slot_data['id'] == $city['planet_id']) { $slot_data['cities'][] = $city; @@ -141,7 +244,7 @@ if ($view === 'sector') { } } } - $stmt = $db->prepare("SELECT name FROM sectors WHERE id = ?"); + $stmt = $db->prepare("SELECT name, status FROM sectors WHERE id = ?"); $stmt->execute([$sector_id]); $sector_info = $stmt->fetch(); } else { @@ -263,19 +366,8 @@ function getStatusColor($status, $type, $statuses_map, $object_types_map) { text-shadow: 0 0 4px rgba(0,0,0,0.8); } - .sector-grid { - display: grid; - grid-template-columns: repeat(6, 180px); - grid-template-rows: repeat(6, 180px); - gap: 15px; - } - .sector-card { background: rgba(10, 15, 30, 0.95); border: 1px solid #2d3545; padding: 20px; display: flex; flex-direction: column; align-items: center; justify-content: center; text-decoration: none; color: #fff; transition: all 0.2s; width: 180px; height: 180px; box-sizing: border-box; } - .sector-card:hover { border-color: #88c0d0; background: #1a202c; transform: translateY(-3px); } - .mini-map { display: grid; grid-template-columns: repeat(6, 12px); gap: 4px; margin-bottom: 10px; background: #000; padding: 6px; } - .mini-dot { width: 12px; height: 12px; border-radius: 1px; } - #editModal, #sectorModal { display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.8); z-index: 1000; align-items: center; justify-content: center; } - .modal-content { background: #1e293b; padding: 30px; border: 1px solid #88c0d0; width: 550px; max-height: 90vh; overflow-y: auto; border-radius: 8px; box-shadow: 0 10px 30px rgba(0,0,0,0.5); } + .modal-content { background: #1e293b; padding: 30px; border: 1px solid #88c0d0; width: 650px; max-height: 90vh; overflow-y: auto; border-radius: 8px; box-shadow: 0 10px 30px rgba(0,0,0,0.5); } .form-group { margin-bottom: 20px; } .form-group label { display: block; font-size: 12px; color: #8c92a3; margin-bottom: 8px; font-weight: bold; } .form-group input, .form-group select, .form-group textarea { width: 100%; background: #0f172a; border: 1px solid #334155; color: #fff; padding: 10px; box-sizing: border-box; border-radius: 4px; font-size: 14px; } @@ -287,8 +379,28 @@ function getStatusColor($status, $type, $statuses_map, $object_types_map) { .btn-remove-settlement { position: absolute; right: 8px; top: 8px; background: #bf616a; color: #fff; border: none; width: 22px; height: 22px; cursor: pointer; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 12px; font-weight: bold; } .btn-add-settlement { background: #81a1c1; color: #000; border: none; padding: 8px 15px; cursor: pointer; font-size: 11px; font-weight: bold; border-radius: 4px; width: 100%; margin-bottom: 15px; transition: 0.2s; } .btn-add-settlement:hover { background: #88c0d0; } - .compact-row { display: flex; gap: 15px; align-items: flex-end; } + .compact-row { display: flex; gap: 15px; align-items: flex-end; margin-bottom: 15px; } .compact-row .form-group { margin-bottom: 0; } + + .control-bars { margin-top: 15px; display: flex; flex-direction: column; gap: 10px; padding-top: 10px; border-top: 1px dashed #334155; } + .control-bar-row { display: flex; align-items: center; gap: 10px; } + .control-bar-label { width: 100px; font-size: 11px; color: #eceff4; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; display: flex; align-items: center; gap: 5px; } + .control-bar-input { flex: 1; -webkit-appearance: none; height: 8px; background: #0f172a; border-radius: 4px; outline: none; } + .control-bar-input::-webkit-slider-thumb { -webkit-appearance: none; width: 16px; height: 16px; background: #88c0d0; border-radius: 50%; cursor: pointer; } + .control-bar-value { width: 35px; text-align: right; font-size: 11px; color: #88c0d0; font-weight: bold; } + + .sector-grid { + display: grid; + grid-template-columns: repeat(6, 180px); + grid-template-rows: repeat(6, 180px); + gap: 15px; + } + .sector-card { background: rgba(10, 15, 30, 0.95); border: 1px solid #2d3545; padding: 20px; display: flex; flex-direction: column; align-items: center; justify-content: center; text-decoration: none; color: #fff; transition: all 0.2s; width: 180px; height: 180px; box-sizing: border-box; } + .sector-card:hover { border-color: #88c0d0; background: #1a202c; transform: translateY(-3px); } + .mini-map { display: grid; grid-template-columns: repeat(6, 12px); gap: 4px; margin-bottom: 10px; background: #000; padding: 6px; } + .mini-dot { width: 12px; height: 12px; border-radius: 1px; } + + .faction-dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; } @@ -302,7 +414,7 @@ function getStatusColor($status, $type, $statuses_map, $object_types_map) { - |