Autosave: 20260306-003148
This commit is contained in:
parent
386719b74f
commit
c2a8442240
643
admin.php
643
admin.php
@ -408,8 +408,21 @@ if (isset($_GET['delete_resource'])) {
|
||||
exit;
|
||||
}
|
||||
|
||||
// Handle Guild System Config
|
||||
if ($_SERVER["REQUEST_METHOD"] === "POST" && isset($_POST["action"]) && $_POST["action"] === "update_guild_requirements") {
|
||||
$db->exec("DELETE FROM guild_creation_requirements");
|
||||
$stmt = $db->prepare("INSERT INTO guild_creation_requirements (resource_id, quantity) VALUES (?, ?)");
|
||||
foreach ($_POST as $key => $value) {
|
||||
if (strpos($key, "res_") === 0 && (int)$value > 0) {
|
||||
$res_id = (int)str_replace("res_", "", $key);
|
||||
$stmt->execute([$res_id, (int)$value]);
|
||||
}
|
||||
}
|
||||
header("Location: admin.php?tab=guilds&success=1");
|
||||
exit;
|
||||
}
|
||||
|
||||
// Handle Grade CRUD
|
||||
// Handle Lootbox CRUD
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'upsert_grade') {
|
||||
$id = (int)$_POST['id'];
|
||||
$name = trim($_POST['name']);
|
||||
@ -423,22 +436,6 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['
|
||||
exit;
|
||||
}
|
||||
|
||||
$image_url = null;
|
||||
if ($id > 0) {
|
||||
$stmt_img = $db->prepare("SELECT image_url FROM grades WHERE id = ?");
|
||||
$stmt_img->execute([$id]);
|
||||
$image_url = $stmt_img->fetchColumn();
|
||||
}
|
||||
if (isset($_FILES["image"]) && $_FILES["image"]["error"] === UPLOAD_ERR_OK) {
|
||||
$ext = pathinfo($_FILES["image"]["name"], PATHINFO_EXTENSION);
|
||||
$filename = "grade_" . time() . "." . $ext;
|
||||
if (!is_dir("assets/images/grades")) mkdir("assets/images/grades", 0775, true);
|
||||
$target = "assets/images/grades/" . $filename;
|
||||
if (move_uploaded_file($_FILES["image"]["tmp_name"], $target)) {
|
||||
$image_url = $target;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for overlap if user_type is 'utilisateur'
|
||||
if ($user_type === 'utilisateur') {
|
||||
$check = db()->prepare("SELECT id FROM grades WHERE user_type = 'utilisateur' AND id != ? AND NOT (max_level < ? OR min_level > ?)");
|
||||
@ -451,11 +448,11 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['
|
||||
|
||||
try {
|
||||
if ($id > 0) {
|
||||
$stmt = db()->prepare("UPDATE grades SET name = ?, slug = ?, user_type = ?, min_level = ?, max_level = ?, image_url = ? WHERE id = ?");
|
||||
$stmt->execute([$name, $slug, $user_type, $min_level, $max_level, $image_url, $id]);
|
||||
$stmt = db()->prepare("UPDATE grades SET name = ?, slug = ?, user_type = ?, min_level = ?, max_level = ? WHERE id = ?");
|
||||
$stmt->execute([$name, $slug, $user_type, $min_level, $max_level, $id]);
|
||||
} else {
|
||||
$stmt = db()->prepare("INSERT INTO grades (name, slug, user_type, min_level, max_level, image_url) VALUES (?, ?, ?, ?, ?, ?)");
|
||||
$stmt->execute([$name, $slug, $user_type, $min_level, $max_level, $image_url]);
|
||||
$stmt = db()->prepare("INSERT INTO grades (name, slug, user_type, min_level, max_level) VALUES (?, ?, ?, ?, ?)");
|
||||
$stmt->execute([$name, $slug, $user_type, $min_level, $max_level]);
|
||||
}
|
||||
header('Location: ?tab=ranks&success=1');
|
||||
exit;
|
||||
@ -464,7 +461,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['
|
||||
exit;
|
||||
}
|
||||
}
|
||||
if ($_SERVER["REQUEST_METHOD"] === "POST" && isset($_POST["action"]) && $_POST["action"] === "upsert_lootbox") {
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'upsert_lootbox') {
|
||||
$id = (int)$_POST['id'];
|
||||
$name = $_POST['name'];
|
||||
$slug = $_POST['slug'];
|
||||
@ -712,7 +709,7 @@ if ($tab === 'users') {
|
||||
</nav>
|
||||
</div>
|
||||
<div>
|
||||
<span style="font-weight: bold; color: #88c0d0;"><?php echo htmlspecialchars($_SESSION["display_name"] ?? $_SESSION["username"]); ?></span>
|
||||
<span style="font-weight: bold; color: #88c0d0;"><?php echo htmlspecialchars($_SESSION['username']); ?></span>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
@ -730,7 +727,11 @@ if ($tab === 'users') {
|
||||
<a href="?tab=users" class="tab-link <?php echo $tab === 'users' ? 'active' : ''; ?>"><i class="fa-solid fa-users"></i> Utilisateurs</a>
|
||||
<a href="?tab=levels" class="tab-link <?php echo $tab === 'levels' ? 'active' : ''; ?>"><i class="fa-solid fa-layer-group"></i> Niveaux</a>
|
||||
<a href="?tab=ranks" class="tab-link <?php echo $tab === 'ranks' ? 'active' : ''; ?>"><i class="fa-solid fa-medal"></i> Grades</a>
|
||||
} elseif ($tab === 'guilds') {
|
||||
$guild_requirements = $db->query("SELECT r.id, r.name, gr.quantity FROM game_resources r LEFT JOIN guild_creation_requirements gr ON r.id = gr.resource_id")->fetchAll();
|
||||
|
||||
<a href="?tab=badges" class="tab-link <?php echo $tab === 'badges' ? 'active' : ''; ?>"><i class="fa-solid fa-id-badge"></i> Titres & Badges</a>
|
||||
<a href="?tab=guilds" class="tab-link <?php echo $tab === "guilds" ? "active" : ""; ?>"><i class="fa-solid fa-building-shield"></i> Gestion de guilde</a>
|
||||
</div>
|
||||
|
||||
<!-- LIGNE 2 (JEU) -->
|
||||
@ -859,7 +860,7 @@ if ($tab === 'users') {
|
||||
|
||||
<div class="form-card">
|
||||
<h4>Ajouter / Modifier un Grade</h4>
|
||||
<form method="POST" id="rankForm" enctype="multipart/form-data">
|
||||
<form method="POST" id="rankForm">
|
||||
<input type="hidden" name="action" value="upsert_grade">
|
||||
<input type="hidden" name="id" id="rank_id" value="0">
|
||||
<div style="display: flex; gap: 20px; margin-bottom: 15px;">
|
||||
@ -879,10 +880,6 @@ if ($tab === 'users') {
|
||||
<option value="admin">Admin</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group" style="flex: 1;">
|
||||
<label>Image (PNG)</label>
|
||||
<input type="file" name="image" accept="image/png">
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: flex; gap: 20px;">
|
||||
<div class="form-group" style="flex: 1;">
|
||||
@ -904,7 +901,6 @@ if ($tab === 'users') {
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Image</th>
|
||||
<th>Nom</th>
|
||||
<th>Slug</th>
|
||||
<th>Type</th>
|
||||
@ -914,21 +910,14 @@ if ($tab === 'users') {
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php if (empty($ranks_list)): ?>
|
||||
<tr><td colspan="6" style="text-align: center;">Aucun grade configuré.</td></tr>
|
||||
<tr><td colspan="5" style="text-align: center;">Aucun grade configuré.</td></tr>
|
||||
<?php else: ?>
|
||||
<?php foreach ($ranks_list as $r): ?>
|
||||
<tr>
|
||||
<td>
|
||||
<?php if (!empty($r["image_url"])): ?>
|
||||
<img src="<?php echo htmlspecialchars($r["image_url"]); ?>?v=<?php echo time(); ?>" style="max-width: 40px; max-height: 40px;">
|
||||
<?php else: ?>
|
||||
-
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td><strong><?php echo htmlspecialchars($r['name']); ?></strong></td>
|
||||
<td><code><?php echo htmlspecialchars($r['slug']); ?></code></td>
|
||||
<td>
|
||||
<span class="badge"
|
||||
<span class="badge <?php echo $r['user_type'] === 'admin' ? 'tag-malus' : ($r['user_type'] === 'GM' ? 'tag-bonus' : ''); ?>"
|
||||
style="background: <?php echo $r['user_type'] === 'admin' ? '#bf616a' : ($r['user_type'] === 'GM' ? '#ebcb8b' : '#88c0d0'); ?>; color: #2e3440; padding: 2px 8px; border-radius: 10px; font-size: 10px; text-transform: uppercase; font-weight: bold;">
|
||||
<?php echo htmlspecialchars($r['user_type']); ?>
|
||||
</span>
|
||||
@ -950,6 +939,29 @@ if ($tab === 'users') {
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
} elseif ($tab === 'guilds') {
|
||||
$guild_requirements = $db->query("SELECT r.id, r.name, gr.quantity FROM game_resources r LEFT JOIN guild_creation_requirements gr ON r.id = gr.resource_id")->fetchAll();
|
||||
|
||||
<?php elseif ($tab === 'guilds'): ?>
|
||||
<h3 style="color: #88c0d0;">Gestion des Guildes</h3>
|
||||
<div class="form-card">
|
||||
<h4>Coût de création d'une guilde</h4>
|
||||
<form method="POST">
|
||||
<input type="hidden" name="action" value="update_guild_requirements">
|
||||
<table>
|
||||
<thead><tr><th>Ressource</th><th>Quantité requise</th></tr></thead>
|
||||
<tbody>
|
||||
<?php foreach ($guild_requirements as $req): ?>
|
||||
<tr>
|
||||
<td><?php echo htmlspecialchars($req["name"]); ?></td>
|
||||
<td><input type="number" name="res_<?php echo $req["id"]; ?>" value="<?php echo $req["quantity"] ?: 0; ?>"></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
<button type="submit" class="btn btn-add" style="margin-top: 15px;">ENREGISTRER</button>
|
||||
</form>
|
||||
</div>
|
||||
<?php elseif ($tab === 'badges'): ?>
|
||||
<h3 style="color: #88c0d0;">Titres & Badges</h3>
|
||||
<div class="form-card">
|
||||
@ -1679,11 +1691,6 @@ if ($tab === 'users') {
|
||||
document.getElementById('log_id').value = 0;
|
||||
document.getElementById('logForm').reset();
|
||||
}
|
||||
</script>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
|
||||
function toggleMS(id) {
|
||||
const d = document.getElementById(id);
|
||||
@ -1773,96 +1780,474 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
}
|
||||
});
|
||||
|
||||
// --- LOOTBOX SYSTEM ---
|
||||
const resourcesList = <?php echo json_encode($resources_list); ?>;
|
||||
function addRollRow(count = 1, prob = 100) {
|
||||
const container = document.getElementById('rolls_container');
|
||||
const row = document.createElement('div');
|
||||
row.className = 'sub-form-row';
|
||||
row.innerHTML = `
|
||||
<input type="number" name="rolls_count[]" value="${count}" placeholder="Nb total" min="0">
|
||||
<input type="number" name="rolls_prob[]" value="${prob}" placeholder="Chance %" step="0.01">
|
||||
<div class="btn-del-row" onclick="this.parentElement.remove()">×</div>
|
||||
`;
|
||||
container.appendChild(row);
|
||||
}
|
||||
function toggleItemType(cb) {
|
||||
const row = cb.closest('.sub-form-row');
|
||||
const probInput = row.querySelector('.item-prob-input');
|
||||
const typeLabel = row.querySelector('.type-label');
|
||||
if (cb.checked) {
|
||||
probInput.style.visibility = 'hidden';
|
||||
probInput.value = 100;
|
||||
typeLabel.textContent = 'DIRECT';
|
||||
typeLabel.style.color = '#a3be8c';
|
||||
} else {
|
||||
probInput.style.visibility = 'visible';
|
||||
typeLabel.textContent = 'POULE';
|
||||
typeLabel.style.color = '#8c92a3';
|
||||
}
|
||||
}
|
||||
function addItemRow(slug = '', prob = 0, qmin = 1, qmax = 1, isGuaranteed = 0) {
|
||||
const container = document.getElementById('items_container');
|
||||
const rowIdx = container.children.length;
|
||||
const row = document.createElement('div');
|
||||
row.className = 'sub-form-row';
|
||||
let options = '<option value="">(Rien)</option>';
|
||||
resourcesList.forEach(r => {
|
||||
options += `<option value="${r.slug}" ${slug === r.slug ? 'selected' : ''}>${r.name}</option>`;
|
||||
});
|
||||
|
||||
row.innerHTML = `
|
||||
<div class="toggle-container">
|
||||
<label class="switch">
|
||||
<input type="hidden" name="item_is_guaranteed[${rowIdx}]" value="0">
|
||||
<input type="checkbox" name="item_is_guaranteed[${rowIdx}]" value="1" ${isGuaranteed ? 'checked' : ''} onchange="toggleItemType(this)">
|
||||
<span class="slider"></span>
|
||||
</label>
|
||||
<span class="type-label" style="color: ${isGuaranteed ? '#a3be8c' : '#8c92a3'}">${isGuaranteed ? 'DIRECT' : 'POULE'}</span>
|
||||
</div>
|
||||
<select name="item_slug[${rowIdx}]" style="flex: 2;">${options}</select>
|
||||
<input type="number" name="item_prob[${rowIdx}]" value="${prob}" class="item-prob-input" style="flex: 1; ${isGuaranteed ? 'visibility:hidden' : ''}" placeholder="Prob %" step="0.01">
|
||||
<input type="number" name="item_qmin[${rowIdx}]" value="${qmin}" style="flex: 0 0 70px;" placeholder="Min">
|
||||
<input type="number" name="item_qmax[${rowIdx}]" value="${qmax}" style="flex: 0 0 70px;" placeholder="Max">
|
||||
<div class="btn-del-row" onclick="this.parentElement.remove()">×</div>
|
||||
`;
|
||||
container.appendChild(row);
|
||||
}
|
||||
function editLootbox(data) {
|
||||
document.getElementById('lb_id').value = data.id;
|
||||
document.getElementById('lb_name').value = data.name;
|
||||
document.getElementById('lb_slug').value = data.slug;
|
||||
document.getElementById('lb_desc').value = data.description || '';
|
||||
|
||||
document.getElementById('rolls_container').innerHTML = '';
|
||||
if (data.rolls && data.rolls.length > 0) {
|
||||
data.rolls.forEach(r => addRollRow(r.roll_count, r.probability));
|
||||
} else {
|
||||
addRollRow();
|
||||
}
|
||||
</script>
|
||||
|
||||
document.getElementById('items_container').innerHTML = '';
|
||||
if (data.items && data.items.length > 0) {
|
||||
data.items.forEach((i, idx) => addItemRow(i.resource_slug, i.probability, i.quantity_min, i.quantity_max, i.is_guaranteed));
|
||||
<?php elseif ($tab === 'lootboxes'): ?>
|
||||
<h3 style="color: #88c0d0;">Système de Lootboxes</h3>
|
||||
<div class="form-card">
|
||||
<h4>Créer / Modifier une Lootbox</h4>
|
||||
<form method="POST" id="lootboxForm">
|
||||
<input type="hidden" name="action" value="upsert_lootbox">
|
||||
<input type="hidden" name="id" id="lb_id" value="0">
|
||||
<div style="display: flex; gap: 20px;">
|
||||
<div class="form-group" style="flex: 2;">
|
||||
<label>Nom de la Lootbox</label>
|
||||
<input type="text" name="name" id="lb_name" required placeholder="Ex: Coffre Mystère">
|
||||
</div>
|
||||
<div class="form-group" style="flex: 1;">
|
||||
<label>Slug</label>
|
||||
<input type="text" name="slug" id="lb_slug" required placeholder="Ex: coffre_mystere">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Description</label>
|
||||
<textarea name="description" id="lb_desc" rows="2"></textarea>
|
||||
</div>
|
||||
|
||||
<div style="display: flex; gap: 20px; margin-top: 20px;">
|
||||
<!-- ROLLS SECTION -->
|
||||
<div style="flex: 0 0 350px; border: 1px solid #2d3545; padding: 15px; border-radius: 8px; background: #0f172a;">
|
||||
<label style="color: #88c0d0; font-weight: bold; font-size: 14px; margin-bottom: 15px; display: block; border-bottom: 1px solid #2d3545; padding-bottom: 5px;">
|
||||
Probabilité du nombre total d'objets
|
||||
</label>
|
||||
|
||||
<div class="sub-form-header">
|
||||
<div style="flex: 1;">Nb Total</div>
|
||||
<div style="flex: 1;">Chance (%)</div>
|
||||
<div class="btn-del-row-placeholder"></div>
|
||||
</div>
|
||||
|
||||
<div id="rolls_container">
|
||||
<!-- Dynamic rows for rolls -->
|
||||
</div>
|
||||
<button type="button" class="btn btn-ok" style="margin-top: 10px; width: 100%;" onclick="addRollRow()">+ Ajouter un palier</button>
|
||||
</div>
|
||||
|
||||
<!-- ITEMS SECTION -->
|
||||
<div style="flex: 1; border: 1px solid #2d3545; padding: 15px; border-radius: 8px; background: #0f172a;">
|
||||
<label style="color: #88c0d0; font-weight: bold; font-size: 14px; margin-bottom: 15px; display: block; border-bottom: 1px solid #2d3545; padding-bottom: 5px;">
|
||||
Objets en poule (Attribution direct ou pool aléatoire)
|
||||
</label>
|
||||
|
||||
<div class="sub-form-header">
|
||||
<div style="flex: 0 0 100px;">Type</div>
|
||||
<div style="flex: 2;">Ressource / Objet</div>
|
||||
<div style="flex: 1;" class="chance-header">Chance (%)</div>
|
||||
<div style="flex: 0 0 70px;">Qté Min</div>
|
||||
<div style="flex: 0 0 70px;">Qté Max</div>
|
||||
<div class="btn-del-row-placeholder"></div>
|
||||
</div>
|
||||
|
||||
<div id="items_container">
|
||||
<!-- Dynamic rows for items -->
|
||||
</div>
|
||||
<button type="button" class="btn btn-ok" style="margin-top: 10px; width: 100%;" onclick="addItemRow()">+ Ajouter un objet</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="margin-top: 30px; text-align: right;">
|
||||
<button type="button" class="btn" style="background: #4c566a; color: #fff; margin-right: 10px;" onclick="resetLootboxForm()">ANNULER TOUT</button>
|
||||
<button type="submit" class="btn btn-add" style="padding: 12px 30px;">ENREGISTRER LA CONFIGURATION</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<table>
|
||||
<thead><tr><th>Nom</th><th>Slug</th><th>Objets Directs (100%)</th><th>Nb Total (%)</th><th>Pool Aléatoire (%)</th><th>Actions</th></tr></thead>
|
||||
<tbody>
|
||||
<?php foreach ($lootboxes_list as $lb): ?>
|
||||
<tr>
|
||||
<td><strong><?php echo htmlspecialchars($lb['name']); ?></strong></td>
|
||||
<td><code><?php echo htmlspecialchars($lb['slug']); ?></code></td>
|
||||
<td>
|
||||
<small>
|
||||
<?php
|
||||
$directs = array_filter($lb['items'], fn($i) => $i['is_guaranteed']);
|
||||
foreach ($directs as $d): ?>
|
||||
<div style="margin-bottom: 2px; color: #a3be8c;">
|
||||
<i class="fa-solid fa-bolt"></i> <?php echo htmlspecialchars($d['resource_slug']); ?>
|
||||
<span style="color: #8c92a3;">(Qté: <?php echo $d['quantity_min']; ?>-<?php echo $d['quantity_max']; ?>)</span>
|
||||
</div>
|
||||
<?php endforeach; if(empty($directs)) echo "<em>Aucun</em>"; ?>
|
||||
</small>
|
||||
</td>
|
||||
<td>
|
||||
<small>
|
||||
<?php foreach ($lb['rolls'] as $r): ?>
|
||||
<div style="margin-bottom: 2px;">
|
||||
<span style="color: #88c0d0;"><?php echo $r['roll_count']; ?> objet(s)</span>:
|
||||
<strong><?php echo $r['probability']; ?>%</strong>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</small>
|
||||
</td>
|
||||
<td>
|
||||
<small>
|
||||
<?php
|
||||
$pool = array_filter($lb['items'], fn($i) => !$i['is_guaranteed']);
|
||||
foreach ($pool as $i): ?>
|
||||
<div style="margin-bottom: 2px;">
|
||||
<?php echo $i['resource_slug'] ?: '<em style="color:#bf616a">(Rien)</em>'; ?>:
|
||||
<strong><?php echo $i['probability']; ?>%</strong>
|
||||
<span style="color: #8c92a3;">(Qté: <?php echo $i['quantity_min']; ?>-<?php echo $i['quantity_max']; ?>)</span>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</small>
|
||||
</td>
|
||||
<td>
|
||||
<button class="btn btn-edit" onclick='editLootbox(<?php echo json_encode($lb, JSON_HEX_APOS); ?>)'>Editer</button>
|
||||
<a href="?tab=lootboxes&delete_lootbox=<?php echo $lb['id']; ?>" class="btn btn-del" onclick="return confirm('Supprimer cette lootbox ?')">Suppr</a>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// --- SHARED RESOURCES ---
|
||||
const resourcesList = <?php echo json_encode($resources_list); ?>;
|
||||
|
||||
function editObject(data) {
|
||||
document.getElementById('obj_id').value = data.id;
|
||||
document.getElementById('obj_name').value = data.name;
|
||||
document.getElementById('obj_slug').value = data.slug;
|
||||
document.getElementById('obj_icon').value = data.icon;
|
||||
document.getElementById('obj_desc').value = data.description;
|
||||
document.getElementById('obj_orbital_enabled').checked = data.orbital_control_enabled == 1;
|
||||
document.getElementById('obj_terrestrial_enabled').checked = data.terrestrial_control_enabled == 1;
|
||||
document.getElementById('obj_profile_id').value = data.status_profile_id || "";
|
||||
document.querySelectorAll('.modifier-checkbox').forEach(cb => cb.checked = false);
|
||||
if (data.modifier_ids) {
|
||||
data.modifier_ids.forEach(mid => {
|
||||
const cb = document.querySelector(`.modifier-checkbox[value="${mid}"]`);
|
||||
if (cb) cb.checked = true;
|
||||
});
|
||||
}
|
||||
window.scrollTo(0,0);
|
||||
}
|
||||
function resetObjectForm() { document.getElementById('objectForm').reset(); document.getElementById('obj_id').value = 0; document.querySelectorAll('.modifier-checkbox').forEach(cb => cb.checked = false); }
|
||||
|
||||
function editProfile(data) {
|
||||
document.getElementById("prof_id").value = data.id;
|
||||
document.getElementById("prof_name").value = data.name;
|
||||
document.getElementById("prof_slug").value = data.slug;
|
||||
}
|
||||
function resetProfileForm() {
|
||||
document.getElementById("prof_id").value = 0;
|
||||
document.getElementById("prof_name").value = "";
|
||||
document.getElementById("prof_slug").value = "";
|
||||
}
|
||||
function editStatus(data) {
|
||||
document.getElementById("st_id").value = data.id;
|
||||
document.getElementById("st_name").value = data.name;
|
||||
document.getElementById("st_slug").value = data.slug;
|
||||
|
||||
let color = data.color || "#000000";
|
||||
let isBlinking = color.includes(";blink");
|
||||
let pureColor = color.replace(";blink", "");
|
||||
|
||||
document.getElementById("st_color").value = pureColor;
|
||||
document.getElementById("st_is_blinking").checked = isBlinking;
|
||||
|
||||
if (document.getElementById("st_color_picker")) {
|
||||
document.getElementById("st_color_picker").value = pureColor.startsWith("#") ? pureColor : "#000000";
|
||||
}
|
||||
document.getElementById("st_desc").value = data.description;
|
||||
window.scrollTo(0,0);
|
||||
}
|
||||
function resetStatusForm() {
|
||||
document.getElementById("statusForm").reset();
|
||||
document.getElementById("st_id").value = 0;
|
||||
document.getElementById("st_color_picker").value = "#000000";
|
||||
document.getElementById("st_is_blinking").checked = false;
|
||||
}
|
||||
|
||||
function editRule(data) {
|
||||
document.getElementById('rule_id').value = data.id;
|
||||
document.getElementById('rule_name').value = data.name;
|
||||
document.getElementById('rule_profile_id').value = data.profile_id || "";
|
||||
document.getElementById('rule_status_id').value = data.status_id;
|
||||
document.getElementById('rule_priority').value = data.priority || 0;
|
||||
document.getElementById('rule_orb_op').value = data.orbital_count_op || "";
|
||||
document.getElementById('rule_orb_val').value = data.orbital_count_val !== null ? data.orbital_count_val : "";
|
||||
document.getElementById('rule_terr_op').value = data.terrestrial_count_op || "";
|
||||
document.getElementById('rule_terr_val').value = data.terrestrial_count_val !== null ? data.terrestrial_count_val : "";
|
||||
|
||||
// Set multi-selects
|
||||
const orbVals = (data.orbital_dominance || "").split(",");
|
||||
document.querySelectorAll('#ms_orb_list input').forEach(cb => {
|
||||
cb.checked = orbVals.includes(cb.value);
|
||||
});
|
||||
updateMSLabel('ms_orb');
|
||||
|
||||
const terrVals = (data.terrestrial_dominance || "").split(",");
|
||||
document.querySelectorAll('#ms_terr_list input').forEach(cb => {
|
||||
cb.checked = terrVals.includes(cb.value);
|
||||
});
|
||||
updateMSLabel('ms_terr');
|
||||
|
||||
document.getElementById('rule_empty').checked = data.is_empty_case == 1;
|
||||
document.getElementById('rule_combine').value = data.combine_mode || "OR";
|
||||
window.scrollTo(0,0);
|
||||
}
|
||||
function resetRuleForm() {
|
||||
document.getElementById('ruleForm').reset();
|
||||
document.getElementById('rule_id').value = 0; document.getElementById('rule_combine').value = 'OR';
|
||||
updateMSLabel('ms_orb');
|
||||
updateMSLabel('ms_terr');
|
||||
}
|
||||
|
||||
function editSettlementType(data) {
|
||||
document.getElementById('set_t_id').value = data.id;
|
||||
document.getElementById('set_t_name').value = data.name;
|
||||
document.getElementById('set_t_slug').value = data.slug;
|
||||
document.getElementById('set_t_desc').value = data.description;
|
||||
window.scrollTo(0,0);
|
||||
}
|
||||
function resetSettlementTypeForm() { document.getElementById('settlementTypeForm').reset(); document.getElementById('set_t_id').value = 0; }
|
||||
|
||||
function editModifier(data) {
|
||||
document.getElementById('mod_id').value = data.id;
|
||||
document.getElementById('mod_name').value = data.name;
|
||||
document.getElementById('mod_slug').value = data.slug || '';
|
||||
document.getElementById('mod_type').value = data.type;
|
||||
document.getElementById('mod_desc').value = data.description;
|
||||
window.scrollTo(0,0);
|
||||
}
|
||||
function resetModifierForm() { document.getElementById('modifierForm').reset(); document.getElementById('mod_id').value = 0; }
|
||||
|
||||
function editFaction(data) {
|
||||
document.getElementById('fac_id').value = data.id;
|
||||
document.getElementById('fac_name').value = data.name;
|
||||
document.getElementById('fac_slug').value = data.slug || '';
|
||||
const color = data.color || '#808080';
|
||||
document.getElementById('fac_color').value = color;
|
||||
if (document.getElementById('fac_color_picker')) {
|
||||
document.getElementById('fac_color_picker').value = color.startsWith('#') ? color : '#808080';
|
||||
}
|
||||
document.getElementById('fac_fa_icon').value = data.fa_icon || '';
|
||||
|
||||
// Handle Alliances
|
||||
document.querySelectorAll('.alliance-checkbox').forEach(cb => cb.checked = false);
|
||||
document.querySelectorAll('.alliance-label').forEach(lbl => lbl.style.display = 'flex');
|
||||
|
||||
// Hide current faction from alliance list
|
||||
const currentLabel = document.querySelector(`.alliance-label[data-id="${data.id}"]`);
|
||||
if (currentLabel) currentLabel.style.display = 'none';
|
||||
|
||||
if (data.alliance_ids) {
|
||||
data.alliance_ids.forEach(aid => {
|
||||
const cb = document.querySelector(`.alliance-checkbox[value="${aid}"]`);
|
||||
if (cb) cb.checked = true;
|
||||
});
|
||||
}
|
||||
window.scrollTo(0,0);
|
||||
}
|
||||
function resetFactionForm() {
|
||||
document.getElementById('factionForm').reset();
|
||||
document.getElementById('fac_id').value = 0;
|
||||
document.getElementById('fac_color').value = '#808080';
|
||||
document.getElementById('fac_color_picker').value = '#808080';
|
||||
document.querySelectorAll('.alliance-checkbox').forEach(cb => cb.checked = false);
|
||||
document.querySelectorAll('.alliance-label').forEach(lbl => lbl.style.display = 'flex');
|
||||
}
|
||||
|
||||
function editResource(data) {
|
||||
document.getElementById('res_id').value = data.id;
|
||||
document.getElementById('res_name').value = data.name;
|
||||
document.getElementById('res_slug').value = data.slug;
|
||||
document.getElementById('res_icon').value = data.icon || '';
|
||||
document.getElementById('res_desc').value = data.description || '';
|
||||
document.getElementById('res_show').checked = (data.show_in_header == 1);
|
||||
window.scrollTo(0,0);
|
||||
}
|
||||
function resetResourceForm() { document.getElementById('resourceForm').reset(); document.getElementById('res_id').value = 0; }
|
||||
|
||||
// --- LOOTBOX SYSTEM ---
|
||||
function addRollRow(count = 1, prob = 100) {
|
||||
const container = document.getElementById('rolls_container');
|
||||
const row = document.createElement('div');
|
||||
row.className = 'sub-form-row';
|
||||
row.innerHTML = `
|
||||
<input type="number" name="rolls_count[]" value="${count}" placeholder="Nb total" min="0">
|
||||
<input type="number" name="rolls_prob[]" value="${prob}" placeholder="Chance %" step="0.01">
|
||||
<div class="btn-del-row" onclick="this.parentElement.remove()">×</div>
|
||||
`;
|
||||
container.appendChild(row);
|
||||
}
|
||||
|
||||
function toggleItemType(cb) {
|
||||
const row = cb.closest('.sub-form-row');
|
||||
const probInput = row.querySelector('.item-prob-input');
|
||||
const typeLabel = row.querySelector('.type-label');
|
||||
if (cb.checked) {
|
||||
probInput.style.visibility = 'hidden';
|
||||
probInput.value = 100;
|
||||
typeLabel.textContent = 'DIRECT';
|
||||
typeLabel.style.color = '#a3be8c';
|
||||
} else {
|
||||
probInput.style.visibility = 'visible';
|
||||
typeLabel.textContent = 'POULE';
|
||||
typeLabel.style.color = '#8c92a3';
|
||||
}
|
||||
}
|
||||
|
||||
function addItemRow(slug = '', prob = 0, qmin = 1, qmax = 1, isGuaranteed = 0) {
|
||||
const container = document.getElementById('items_container');
|
||||
const rowIdx = container.children.length;
|
||||
const row = document.createElement('div');
|
||||
row.className = 'sub-form-row';
|
||||
let options = '<option value="">(Rien)</option>';
|
||||
resourcesList.forEach(r => {
|
||||
options += `<option value="${r.slug}" ${slug === r.slug ? 'selected' : ''}>${r.name}</option>`;
|
||||
});
|
||||
|
||||
row.innerHTML = `
|
||||
<div class="toggle-container">
|
||||
<label class="switch">
|
||||
<input type="hidden" name="item_is_guaranteed[${rowIdx}]" value="0">
|
||||
<input type="checkbox" name="item_is_guaranteed[${rowIdx}]" value="1" ${isGuaranteed ? 'checked' : ''} onchange="toggleItemType(this)">
|
||||
<span class="slider"></span>
|
||||
</label>
|
||||
<span class="type-label" style="color: ${isGuaranteed ? '#a3be8c' : '#8c92a3'}">${isGuaranteed ? 'DIRECT' : 'POULE'}</span>
|
||||
</div>
|
||||
<select name="item_slug[${rowIdx}]" style="flex: 2;">${options}</select>
|
||||
<input type="number" name="item_prob[${rowIdx}]" value="${prob}" class="item-prob-input" style="flex: 1; ${isGuaranteed ? 'visibility:hidden' : ''}" placeholder="Prob %" step="0.01">
|
||||
<input type="number" name="item_qmin[${rowIdx}]" value="${qmin}" style="flex: 0 0 70px;" placeholder="Min">
|
||||
<input type="number" name="item_qmax[${rowIdx}]" value="${qmax}" style="flex: 0 0 70px;" placeholder="Max">
|
||||
<div class="btn-del-row" onclick="this.parentElement.remove()">×</div>
|
||||
`;
|
||||
container.appendChild(row);
|
||||
}
|
||||
|
||||
function editLootbox(data) {
|
||||
document.getElementById('lb_id').value = data.id;
|
||||
document.getElementById('lb_name').value = data.name;
|
||||
document.getElementById('lb_slug').value = data.slug;
|
||||
document.getElementById('lb_desc').value = data.description || '';
|
||||
|
||||
document.getElementById('rolls_container').innerHTML = '';
|
||||
if (data.rolls && data.rolls.length > 0) {
|
||||
data.rolls.forEach(r => addRollRow(r.roll_count, r.probability));
|
||||
} else {
|
||||
addRollRow();
|
||||
}
|
||||
|
||||
document.getElementById('items_container').innerHTML = '';
|
||||
if (data.items && data.items.length > 0) {
|
||||
data.items.forEach((i, idx) => addItemRow(i.resource_slug, i.probability, i.quantity_min, i.quantity_max, i.is_guaranteed));
|
||||
} else {
|
||||
addItemRow();
|
||||
}
|
||||
window.scrollTo(0,0);
|
||||
}
|
||||
|
||||
function resetLootboxForm() {
|
||||
document.getElementById('lootboxForm').reset();
|
||||
document.getElementById('lb_id').value = 0;
|
||||
document.getElementById('rolls_container').innerHTML = '';
|
||||
document.getElementById('items_container').innerHTML = '';
|
||||
addRollRow();
|
||||
addItemRow();
|
||||
}
|
||||
|
||||
<?php if ($tab === 'lootboxes'): ?>
|
||||
window.onload = function() {
|
||||
if (document.getElementById('rolls_container').children.length === 0) addRollRow();
|
||||
if (document.getElementById('items_container').children.length === 0) addItemRow();
|
||||
};
|
||||
<?php endif; ?>
|
||||
|
||||
function toggleMS(id) {
|
||||
const d = document.getElementById(id);
|
||||
d.style.display = d.style.display === 'block' ? 'none' : 'block';
|
||||
}
|
||||
function updateMSLabel(containerId) {
|
||||
const container = document.getElementById(containerId);
|
||||
const checkboxes = container.querySelectorAll('input[type="checkbox"]:checked');
|
||||
const display = container.querySelector('.ms-display');
|
||||
if (checkboxes.length === 0) {
|
||||
display.innerText = "Toutes / Peu importe";
|
||||
} else {
|
||||
const labels = Array.from(checkboxes).map(cb => cb.parentElement.innerText.trim());
|
||||
display.innerText = labels.join(', ');
|
||||
}
|
||||
}
|
||||
document.addEventListener('click', function(e) {
|
||||
if (!e.target.closest('.ms-container')) {
|
||||
document.querySelectorAll('.ms-dropdown').forEach(d => d.style.display = 'none');
|
||||
}
|
||||
});
|
||||
|
||||
function editLevel(data) {
|
||||
document.getElementById("level_id").value = data.id;
|
||||
document.getElementById("level_name").value = data.name;
|
||||
document.getElementById("level_slug").value = data.slug;
|
||||
document.getElementById("level_resource_id").value = data.resource_id;
|
||||
document.getElementById("level_required_quantity").value = data.required_quantity;
|
||||
window.scrollTo(0,0);
|
||||
}
|
||||
function resetLevelForm() {
|
||||
document.getElementById("levelForm").reset();
|
||||
document.getElementById("level_id").value = 0;
|
||||
const select = document.getElementById("level_resource_id");
|
||||
for (let i = 0; i < select.options.length; i++) {
|
||||
if (select.options[i].text.toLowerCase().includes("expérience") || select.options[i].text.toLowerCase().includes("experience")) {
|
||||
select.selectedIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function updateRankFields() {
|
||||
const type = document.getElementById('rank_type').value;
|
||||
const min = document.getElementById('rank_min');
|
||||
const max = document.getElementById('rank_max');
|
||||
if (type === 'utilisateur') {
|
||||
min.disabled = false;
|
||||
max.disabled = false;
|
||||
min.required = true;
|
||||
max.required = true;
|
||||
min.style.opacity = '1';
|
||||
max.style.opacity = '1';
|
||||
} else {
|
||||
addItemRow();
|
||||
min.disabled = true;
|
||||
max.disabled = true;
|
||||
min.required = false;
|
||||
max.required = false;
|
||||
min.style.opacity = '0.5';
|
||||
max.style.opacity = '0.5';
|
||||
min.value = '';
|
||||
max.value = '';
|
||||
}
|
||||
window.scrollTo(0,0);
|
||||
}
|
||||
function resetLootboxForm() {
|
||||
document.getElementById('lootboxForm').reset();
|
||||
document.getElementById('lb_id').value = 0;
|
||||
document.getElementById('rolls_container').innerHTML = '';
|
||||
document.getElementById('items_container').innerHTML = '';
|
||||
addRollRow();
|
||||
addItemRow();
|
||||
|
||||
function editRank(rank) {
|
||||
document.getElementById('rank_id').value = rank.id;
|
||||
document.getElementById('rank_name').value = rank.name;
|
||||
document.getElementById('rank_slug').value = rank.slug;
|
||||
document.getElementById('rank_type').value = rank.user_type;
|
||||
document.getElementById('rank_min').value = rank.min_level || '';
|
||||
document.getElementById('rank_max').value = rank.max_level || '';
|
||||
updateRankFields();
|
||||
window.scrollTo({ top: 0, behavior: 'smooth' });
|
||||
}
|
||||
<?php if ($tab === 'lootboxes'): ?>
|
||||
window.onload = function() {
|
||||
if (document.getElementById('rolls_container').children.length === 0) addRollRow();
|
||||
if (document.getElementById('items_container').children.length === 0) addItemRow();
|
||||
};
|
||||
<?php endif; ?>
|
||||
|
||||
function resetRankForm() {
|
||||
document.getElementById('rankForm').reset();
|
||||
document.getElementById('rank_id').value = '0';
|
||||
updateRankFields();
|
||||
}
|
||||
|
||||
// Initial call to set fields on load
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
if (document.getElementById('rank_type')) {
|
||||
updateRankFields();
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
BIN
assets/pasted-20260306-003105-340a1f6d.png
Normal file
BIN
assets/pasted-20260306-003105-340a1f6d.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 295 KiB |
23
db/migrate_guild_system.php
Normal file
23
db/migrate_guild_system.php
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
require_once 'db/config.php';
|
||||
$pdo = db();
|
||||
|
||||
// Tables pour le système de guildes
|
||||
$pdo->exec("CREATE TABLE IF NOT EXISTS guilds (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
)");
|
||||
|
||||
$pdo->exec("CREATE TABLE IF NOT EXISTS guild_creation_requirements (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
resource_id INT NOT NULL,
|
||||
quantity INT NOT NULL,
|
||||
FOREIGN KEY (resource_id) REFERENCES game_resources(id)
|
||||
)");
|
||||
|
||||
$pdo->exec("CREATE TABLE IF NOT EXISTS guild_restrictions (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
restriction_key VARCHAR(255) NOT NULL,
|
||||
restriction_value TEXT
|
||||
)");
|
||||
Loading…
x
Reference in New Issue
Block a user