Autosave: 20260415-231211
This commit is contained in:
parent
de33ca704e
commit
0965f47f80
@ -18726,3 +18726,52 @@ CREATE TABLE IF NOT EXISTS tbl_page_access (
|
||||
cl_allow_member TINYINT(1) NOT NULL DEFAULT 0,
|
||||
cl_updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS tbl_sccharacters (
|
||||
cl_sccharacter_id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
cl_sccharacter_owner_auth_id INT UNSIGNED NOT NULL,
|
||||
cl_sccharacter_name VARCHAR(190) NOT NULL,
|
||||
cl_sccharacter_role VARCHAR(190) NOT NULL DEFAULT '',
|
||||
cl_sccharacter_faction VARCHAR(190) NOT NULL DEFAULT '',
|
||||
cl_sccharacter_avatar_url VARCHAR(255) NOT NULL DEFAULT '',
|
||||
cl_sccharacter_description TEXT DEFAULT NULL,
|
||||
cl_sccharacter_notes TEXT DEFAULT NULL,
|
||||
cl_sccharacter_share_token VARCHAR(64) NOT NULL,
|
||||
cl_sccharacter_share_enabled TINYINT(1) NOT NULL DEFAULT 0,
|
||||
cl_sccharacter_created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
cl_sccharacter_updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uq_sccharacter_share_token (cl_sccharacter_share_token),
|
||||
KEY idx_sccharacter_owner (cl_sccharacter_owner_auth_id),
|
||||
KEY idx_sccharacter_name (cl_sccharacter_name),
|
||||
CONSTRAINT fk_sccharacter_owner_auth FOREIGN KEY (cl_sccharacter_owner_auth_id)
|
||||
REFERENCES tbl_auth (cl_auth_id)
|
||||
ON DELETE CASCADE
|
||||
ON UPDATE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS tbl_sccharacteritems (
|
||||
cl_sccharacteritem_id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
cl_sccharacteritem_character_id INT UNSIGNED NOT NULL,
|
||||
cl_sccharacteritem_source ENUM('base', 'custom') NOT NULL DEFAULT 'base',
|
||||
cl_sccharacteritem_scobjs_id INT UNSIGNED DEFAULT NULL,
|
||||
cl_sccharacteritem_scitemcustom_id INT(11) DEFAULT NULL,
|
||||
cl_sccharacteritem_slot VARCHAR(120) NOT NULL DEFAULT '',
|
||||
cl_sccharacteritem_note TEXT DEFAULT NULL,
|
||||
cl_sccharacteritem_created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
KEY idx_sccharacteritem_character (cl_sccharacteritem_character_id),
|
||||
KEY idx_sccharacteritem_scobjs (cl_sccharacteritem_scobjs_id),
|
||||
KEY idx_sccharacteritem_scitemcustom (cl_sccharacteritem_scitemcustom_id),
|
||||
CONSTRAINT fk_sccharacteritem_character FOREIGN KEY (cl_sccharacteritem_character_id)
|
||||
REFERENCES tbl_sccharacters (cl_sccharacter_id)
|
||||
ON DELETE CASCADE
|
||||
ON UPDATE CASCADE,
|
||||
CONSTRAINT fk_sccharacteritem_scobjs FOREIGN KEY (cl_sccharacteritem_scobjs_id)
|
||||
REFERENCES tbl_scobjs (cl_scobjs_id)
|
||||
ON DELETE SET NULL
|
||||
ON UPDATE CASCADE,
|
||||
CONSTRAINT fk_sccharacteritem_scitemcustom FOREIGN KEY (cl_sccharacteritem_scitemcustom_id)
|
||||
REFERENCES tbl_scitemcustom (cl_scitemcustom_id)
|
||||
ON DELETE SET NULL
|
||||
ON UPDATE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
@ -205,3 +205,52 @@ CREATE TABLE IF NOT EXISTS tbl_page_access (
|
||||
cl_allow_member TINYINT(1) NOT NULL DEFAULT 0,
|
||||
cl_updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS tbl_sccharacters (
|
||||
cl_sccharacter_id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
cl_sccharacter_owner_auth_id INT UNSIGNED NOT NULL,
|
||||
cl_sccharacter_name VARCHAR(190) NOT NULL,
|
||||
cl_sccharacter_role VARCHAR(190) NOT NULL DEFAULT '',
|
||||
cl_sccharacter_faction VARCHAR(190) NOT NULL DEFAULT '',
|
||||
cl_sccharacter_avatar_url VARCHAR(255) NOT NULL DEFAULT '',
|
||||
cl_sccharacter_description TEXT DEFAULT NULL,
|
||||
cl_sccharacter_notes TEXT DEFAULT NULL,
|
||||
cl_sccharacter_share_token VARCHAR(64) NOT NULL,
|
||||
cl_sccharacter_share_enabled TINYINT(1) NOT NULL DEFAULT 0,
|
||||
cl_sccharacter_created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
cl_sccharacter_updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uq_sccharacter_share_token (cl_sccharacter_share_token),
|
||||
KEY idx_sccharacter_owner (cl_sccharacter_owner_auth_id),
|
||||
KEY idx_sccharacter_name (cl_sccharacter_name),
|
||||
CONSTRAINT fk_sccharacter_owner_auth FOREIGN KEY (cl_sccharacter_owner_auth_id)
|
||||
REFERENCES tbl_auth (cl_auth_id)
|
||||
ON DELETE CASCADE
|
||||
ON UPDATE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS tbl_sccharacteritems (
|
||||
cl_sccharacteritem_id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
cl_sccharacteritem_character_id INT UNSIGNED NOT NULL,
|
||||
cl_sccharacteritem_source ENUM('base', 'custom') NOT NULL DEFAULT 'base',
|
||||
cl_sccharacteritem_scobjs_id INT UNSIGNED DEFAULT NULL,
|
||||
cl_sccharacteritem_scitemcustom_id INT(11) DEFAULT NULL,
|
||||
cl_sccharacteritem_slot VARCHAR(120) NOT NULL DEFAULT '',
|
||||
cl_sccharacteritem_note TEXT DEFAULT NULL,
|
||||
cl_sccharacteritem_created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
KEY idx_sccharacteritem_character (cl_sccharacteritem_character_id),
|
||||
KEY idx_sccharacteritem_scobjs (cl_sccharacteritem_scobjs_id),
|
||||
KEY idx_sccharacteritem_scitemcustom (cl_sccharacteritem_scitemcustom_id),
|
||||
CONSTRAINT fk_sccharacteritem_character FOREIGN KEY (cl_sccharacteritem_character_id)
|
||||
REFERENCES tbl_sccharacters (cl_sccharacter_id)
|
||||
ON DELETE CASCADE
|
||||
ON UPDATE CASCADE,
|
||||
CONSTRAINT fk_sccharacteritem_scobjs FOREIGN KEY (cl_sccharacteritem_scobjs_id)
|
||||
REFERENCES tbl_scobjs (cl_scobjs_id)
|
||||
ON DELETE SET NULL
|
||||
ON UPDATE CASCADE,
|
||||
CONSTRAINT fk_sccharacteritem_scitemcustom FOREIGN KEY (cl_sccharacteritem_scitemcustom_id)
|
||||
REFERENCES tbl_scitemcustom (cl_scitemcustom_id)
|
||||
ON DELETE SET NULL
|
||||
ON UPDATE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
@ -469,6 +469,7 @@ function auth_navigation_items(): array
|
||||
['file' => 'scitems.php', 'label' => 'Base d\'Objets'],
|
||||
['file' => 'scstatsitem.php', 'label' => 'Stats Item'],
|
||||
['file' => 'scitemcustom.php', 'label' => 'Objets perso.'],
|
||||
['file' => 'sccharacters.php', 'label' => 'Personnages'],
|
||||
['file' => 'scmining.php', 'label' => 'Scanner Minage'],
|
||||
['file' => 'scmanufactures.php', 'label' => 'Manufactures'],
|
||||
['file' => 'scvaisseaux.php', 'label' => 'Vaisseaux'],
|
||||
|
||||
456
db/sccharacters.php
Normal file
456
db/sccharacters.php
Normal file
@ -0,0 +1,456 @@
|
||||
<?php
|
||||
|
||||
require_once __DIR__ . '/config.php';
|
||||
|
||||
function sccharacters_column_exists(PDO $db, string $table, string $column): bool
|
||||
{
|
||||
$stmt = $db->query("SHOW COLUMNS FROM `{$table}` LIKE " . $db->quote($column));
|
||||
|
||||
return (bool) $stmt->fetch();
|
||||
}
|
||||
|
||||
function sccharacters_index_exists(PDO $db, string $table, string $index): bool
|
||||
{
|
||||
$stmt = $db->query("SHOW INDEX FROM `{$table}` WHERE Key_name = " . $db->quote($index));
|
||||
|
||||
return (bool) $stmt->fetch();
|
||||
}
|
||||
|
||||
function sccharacters_foreign_key_exists(PDO $db, string $table, string $constraint): bool
|
||||
{
|
||||
$stmt = $db->prepare(
|
||||
"SELECT COUNT(*)
|
||||
FROM information_schema.TABLE_CONSTRAINTS
|
||||
WHERE TABLE_SCHEMA = DATABASE()
|
||||
AND TABLE_NAME = :table_name
|
||||
AND CONSTRAINT_NAME = :constraint_name
|
||||
AND CONSTRAINT_TYPE = 'FOREIGN KEY'"
|
||||
);
|
||||
$stmt->execute([
|
||||
'table_name' => $table,
|
||||
'constraint_name' => $constraint,
|
||||
]);
|
||||
|
||||
return (int) $stmt->fetchColumn() > 0;
|
||||
}
|
||||
|
||||
function sccharacters_bootstrap(): void
|
||||
{
|
||||
static $bootstrapped = false;
|
||||
|
||||
if ($bootstrapped) {
|
||||
return;
|
||||
}
|
||||
|
||||
$db = db();
|
||||
|
||||
$db->exec(
|
||||
"CREATE TABLE IF NOT EXISTS tbl_sccharacters (
|
||||
cl_sccharacter_id INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
cl_sccharacter_owner_auth_id INT UNSIGNED NOT NULL,
|
||||
cl_sccharacter_name VARCHAR(190) NOT NULL,
|
||||
cl_sccharacter_role VARCHAR(190) NOT NULL DEFAULT '',
|
||||
cl_sccharacter_faction VARCHAR(190) NOT NULL DEFAULT '',
|
||||
cl_sccharacter_avatar_url VARCHAR(255) NOT NULL DEFAULT '',
|
||||
cl_sccharacter_description TEXT DEFAULT NULL,
|
||||
cl_sccharacter_notes TEXT DEFAULT NULL,
|
||||
cl_sccharacter_share_token VARCHAR(64) NOT NULL,
|
||||
cl_sccharacter_share_enabled TINYINT(1) NOT NULL DEFAULT 0,
|
||||
cl_sccharacter_created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
cl_sccharacter_updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (cl_sccharacter_id),
|
||||
UNIQUE KEY uq_sccharacter_share_token (cl_sccharacter_share_token),
|
||||
KEY idx_sccharacter_owner (cl_sccharacter_owner_auth_id),
|
||||
KEY idx_sccharacter_name (cl_sccharacter_name),
|
||||
CONSTRAINT fk_sccharacter_owner_auth FOREIGN KEY (cl_sccharacter_owner_auth_id)
|
||||
REFERENCES tbl_auth (cl_auth_id)
|
||||
ON DELETE CASCADE
|
||||
ON UPDATE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci"
|
||||
);
|
||||
|
||||
if (!sccharacters_column_exists($db, 'tbl_sccharacters', 'cl_sccharacter_owner_auth_id')) {
|
||||
$db->exec(
|
||||
'ALTER TABLE tbl_sccharacters
|
||||
ADD COLUMN cl_sccharacter_owner_auth_id INT UNSIGNED NULL AFTER cl_sccharacter_id'
|
||||
);
|
||||
}
|
||||
|
||||
if (!sccharacters_column_exists($db, 'tbl_sccharacters', 'cl_sccharacter_share_token')) {
|
||||
$db->exec(
|
||||
"ALTER TABLE tbl_sccharacters
|
||||
ADD COLUMN cl_sccharacter_share_token VARCHAR(64) NOT NULL DEFAULT '' AFTER cl_sccharacter_notes"
|
||||
);
|
||||
}
|
||||
|
||||
if (!sccharacters_column_exists($db, 'tbl_sccharacters', 'cl_sccharacter_share_enabled')) {
|
||||
$db->exec(
|
||||
'ALTER TABLE tbl_sccharacters
|
||||
ADD COLUMN cl_sccharacter_share_enabled TINYINT(1) NOT NULL DEFAULT 0 AFTER cl_sccharacter_share_token'
|
||||
);
|
||||
}
|
||||
|
||||
if (!sccharacters_index_exists($db, 'tbl_sccharacters', 'idx_sccharacter_owner')) {
|
||||
$db->exec(
|
||||
'ALTER TABLE tbl_sccharacters
|
||||
ADD INDEX idx_sccharacter_owner (cl_sccharacter_owner_auth_id)'
|
||||
);
|
||||
}
|
||||
|
||||
if (!sccharacters_index_exists($db, 'tbl_sccharacters', 'uq_sccharacter_share_token')) {
|
||||
$db->exec(
|
||||
'ALTER TABLE tbl_sccharacters
|
||||
ADD UNIQUE KEY uq_sccharacter_share_token (cl_sccharacter_share_token)'
|
||||
);
|
||||
}
|
||||
|
||||
if (!sccharacters_foreign_key_exists($db, 'tbl_sccharacters', 'fk_sccharacter_owner_auth')) {
|
||||
$db->exec(
|
||||
'ALTER TABLE tbl_sccharacters
|
||||
ADD CONSTRAINT fk_sccharacter_owner_auth FOREIGN KEY (cl_sccharacter_owner_auth_id)
|
||||
REFERENCES tbl_auth (cl_auth_id)
|
||||
ON DELETE CASCADE
|
||||
ON UPDATE CASCADE'
|
||||
);
|
||||
}
|
||||
|
||||
$db->exec(
|
||||
"CREATE TABLE IF NOT EXISTS tbl_sccharacteritems (
|
||||
cl_sccharacteritem_id INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
cl_sccharacteritem_character_id INT UNSIGNED NOT NULL,
|
||||
cl_sccharacteritem_source ENUM('base', 'custom') NOT NULL DEFAULT 'base',
|
||||
cl_sccharacteritem_scobjs_id INT UNSIGNED DEFAULT NULL,
|
||||
cl_sccharacteritem_scitemcustom_id INT(11) DEFAULT NULL,
|
||||
cl_sccharacteritem_slot VARCHAR(120) NOT NULL DEFAULT '',
|
||||
cl_sccharacteritem_note TEXT DEFAULT NULL,
|
||||
cl_sccharacteritem_created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (cl_sccharacteritem_id),
|
||||
KEY idx_sccharacteritem_character (cl_sccharacteritem_character_id),
|
||||
KEY idx_sccharacteritem_scobjs (cl_sccharacteritem_scobjs_id),
|
||||
KEY idx_sccharacteritem_scitemcustom (cl_sccharacteritem_scitemcustom_id),
|
||||
CONSTRAINT fk_sccharacteritem_character FOREIGN KEY (cl_sccharacteritem_character_id)
|
||||
REFERENCES tbl_sccharacters (cl_sccharacter_id)
|
||||
ON DELETE CASCADE
|
||||
ON UPDATE CASCADE,
|
||||
CONSTRAINT fk_sccharacteritem_scobjs FOREIGN KEY (cl_sccharacteritem_scobjs_id)
|
||||
REFERENCES tbl_scobjs (cl_scobjs_id)
|
||||
ON DELETE SET NULL
|
||||
ON UPDATE CASCADE,
|
||||
CONSTRAINT fk_sccharacteritem_scitemcustom FOREIGN KEY (cl_sccharacteritem_scitemcustom_id)
|
||||
REFERENCES tbl_scitemcustom (cl_scitemcustom_id)
|
||||
ON DELETE SET NULL
|
||||
ON UPDATE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci"
|
||||
);
|
||||
|
||||
if (!sccharacters_column_exists($db, 'tbl_sccharacteritems', 'cl_sccharacteritem_scobjs_id')) {
|
||||
$db->exec(
|
||||
'ALTER TABLE tbl_sccharacteritems
|
||||
ADD COLUMN cl_sccharacteritem_scobjs_id INT UNSIGNED NULL AFTER cl_sccharacteritem_source'
|
||||
);
|
||||
}
|
||||
|
||||
if (!sccharacters_column_exists($db, 'tbl_sccharacteritems', 'cl_sccharacteritem_scitemcustom_id')) {
|
||||
$db->exec(
|
||||
'ALTER TABLE tbl_sccharacteritems
|
||||
ADD COLUMN cl_sccharacteritem_scitemcustom_id INT(11) NULL AFTER cl_sccharacteritem_scobjs_id'
|
||||
);
|
||||
}
|
||||
|
||||
if (!sccharacters_index_exists($db, 'tbl_sccharacteritems', 'idx_sccharacteritem_character')) {
|
||||
$db->exec(
|
||||
'ALTER TABLE tbl_sccharacteritems
|
||||
ADD INDEX idx_sccharacteritem_character (cl_sccharacteritem_character_id)'
|
||||
);
|
||||
}
|
||||
|
||||
if (!sccharacters_index_exists($db, 'tbl_sccharacteritems', 'idx_sccharacteritem_scobjs')) {
|
||||
$db->exec(
|
||||
'ALTER TABLE tbl_sccharacteritems
|
||||
ADD INDEX idx_sccharacteritem_scobjs (cl_sccharacteritem_scobjs_id)'
|
||||
);
|
||||
}
|
||||
|
||||
if (!sccharacters_index_exists($db, 'tbl_sccharacteritems', 'idx_sccharacteritem_scitemcustom')) {
|
||||
$db->exec(
|
||||
'ALTER TABLE tbl_sccharacteritems
|
||||
ADD INDEX idx_sccharacteritem_scitemcustom (cl_sccharacteritem_scitemcustom_id)'
|
||||
);
|
||||
}
|
||||
|
||||
if (!sccharacters_foreign_key_exists($db, 'tbl_sccharacteritems', 'fk_sccharacteritem_character')) {
|
||||
$db->exec(
|
||||
'ALTER TABLE tbl_sccharacteritems
|
||||
ADD CONSTRAINT fk_sccharacteritem_character FOREIGN KEY (cl_sccharacteritem_character_id)
|
||||
REFERENCES tbl_sccharacters (cl_sccharacter_id)
|
||||
ON DELETE CASCADE
|
||||
ON UPDATE CASCADE'
|
||||
);
|
||||
}
|
||||
|
||||
if (!sccharacters_foreign_key_exists($db, 'tbl_sccharacteritems', 'fk_sccharacteritem_scobjs')) {
|
||||
$db->exec(
|
||||
'ALTER TABLE tbl_sccharacteritems
|
||||
ADD CONSTRAINT fk_sccharacteritem_scobjs FOREIGN KEY (cl_sccharacteritem_scobjs_id)
|
||||
REFERENCES tbl_scobjs (cl_scobjs_id)
|
||||
ON DELETE SET NULL
|
||||
ON UPDATE CASCADE'
|
||||
);
|
||||
}
|
||||
|
||||
if (!sccharacters_foreign_key_exists($db, 'tbl_sccharacteritems', 'fk_sccharacteritem_scitemcustom')) {
|
||||
$db->exec(
|
||||
'ALTER TABLE tbl_sccharacteritems
|
||||
ADD CONSTRAINT fk_sccharacteritem_scitemcustom FOREIGN KEY (cl_sccharacteritem_scitemcustom_id)
|
||||
REFERENCES tbl_scitemcustom (cl_scitemcustom_id)
|
||||
ON DELETE SET NULL
|
||||
ON UPDATE CASCADE'
|
||||
);
|
||||
}
|
||||
|
||||
$stmt_missing_tokens = $db->query(
|
||||
"SELECT cl_sccharacter_id
|
||||
FROM tbl_sccharacters
|
||||
WHERE cl_sccharacter_share_token IS NULL
|
||||
OR cl_sccharacter_share_token = ''"
|
||||
);
|
||||
|
||||
$stmt_update_token = $db->prepare(
|
||||
'UPDATE tbl_sccharacters
|
||||
SET cl_sccharacter_share_token = :token
|
||||
WHERE cl_sccharacter_id = :id'
|
||||
);
|
||||
|
||||
foreach ($stmt_missing_tokens->fetchAll() as $row) {
|
||||
$stmt_update_token->execute([
|
||||
'token' => sccharacters_generate_share_token($db),
|
||||
'id' => (int) $row['cl_sccharacter_id'],
|
||||
]);
|
||||
}
|
||||
|
||||
$bootstrapped = true;
|
||||
}
|
||||
|
||||
function sccharacters_generate_share_token(PDO $db): string
|
||||
{
|
||||
do {
|
||||
$token = bin2hex(random_bytes(16));
|
||||
$stmt = $db->prepare(
|
||||
'SELECT cl_sccharacter_id
|
||||
FROM tbl_sccharacters
|
||||
WHERE cl_sccharacter_share_token = :token
|
||||
LIMIT 1'
|
||||
);
|
||||
$stmt->execute(['token' => $token]);
|
||||
} while ($stmt->fetch());
|
||||
|
||||
return $token;
|
||||
}
|
||||
|
||||
|
||||
function sccharacters_item_category_options(): array
|
||||
{
|
||||
return [
|
||||
'weapon' => 'Armes',
|
||||
'armor' => 'Armures',
|
||||
'tools' => 'Outils',
|
||||
'consumables' => 'Consommables',
|
||||
'ammunition' => 'Munitions',
|
||||
'attachments' => 'Accessoires',
|
||||
'clothing' => 'Vêtements',
|
||||
'cargo' => 'Cargo / Conteneurs',
|
||||
'ship' => 'Composants / Véhicule',
|
||||
'access' => 'Accès / Mobilier',
|
||||
'misc' => 'Divers',
|
||||
];
|
||||
}
|
||||
|
||||
function sccharacters_item_category_label(string $category): string
|
||||
{
|
||||
$options = sccharacters_item_category_options();
|
||||
|
||||
return $options[$category] ?? $options['misc'];
|
||||
}
|
||||
|
||||
function sccharacters_item_category_slug(string $value): string
|
||||
{
|
||||
$value = trim($value);
|
||||
if ($value == '') {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (function_exists('iconv')) {
|
||||
$converted = @iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $value);
|
||||
if ($converted !== false) {
|
||||
$value = $converted;
|
||||
}
|
||||
}
|
||||
|
||||
$value = strtolower($value);
|
||||
$value = preg_replace('/[^a-z0-9]+/', '_', $value) ?? '';
|
||||
|
||||
return trim($value, '_');
|
||||
}
|
||||
|
||||
function sccharacters_string_contains_any(string $haystack, array $needles): bool
|
||||
{
|
||||
foreach ($needles as $needle) {
|
||||
if ($needle !== '' && strpos($haystack, $needle) !== false) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function sccharacters_normalize_item_category(?string $value): string
|
||||
{
|
||||
$slug = sccharacters_item_category_slug((string) $value);
|
||||
if ($slug === '' || in_array($slug, ['auto', 'automatic', 'automatique', 'default', 'defaut'], true)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$options = sccharacters_item_category_options();
|
||||
if (isset($options[$slug])) {
|
||||
return $slug;
|
||||
}
|
||||
|
||||
$exact_aliases = [
|
||||
'arme' => 'weapon',
|
||||
'armes' => 'weapon',
|
||||
'weapon' => 'weapon',
|
||||
'weapons' => 'weapon',
|
||||
'armure' => 'armor',
|
||||
'armures' => 'armor',
|
||||
'armor' => 'armor',
|
||||
'armors' => 'armor',
|
||||
'outil' => 'tools',
|
||||
'outils' => 'tools',
|
||||
'tool' => 'tools',
|
||||
'tools' => 'tools',
|
||||
'consommable' => 'consumables',
|
||||
'consommables' => 'consumables',
|
||||
'usable' => 'consumables',
|
||||
'food' => 'consumables',
|
||||
'drink' => 'consumables',
|
||||
'munition' => 'ammunition',
|
||||
'munitions' => 'ammunition',
|
||||
'ammo' => 'ammunition',
|
||||
'ammunition' => 'ammunition',
|
||||
'accessoire' => 'attachments',
|
||||
'accessoires' => 'attachments',
|
||||
'attachment' => 'attachments',
|
||||
'attachments' => 'attachments',
|
||||
'vetement' => 'clothing',
|
||||
'vetements' => 'clothing',
|
||||
'clothing' => 'clothing',
|
||||
'clothes' => 'clothing',
|
||||
'cargo' => 'cargo',
|
||||
'container' => 'cargo',
|
||||
'conteneur' => 'cargo',
|
||||
'conteneurs' => 'cargo',
|
||||
'composant' => 'ship',
|
||||
'composants' => 'ship',
|
||||
'component' => 'ship',
|
||||
'components' => 'ship',
|
||||
'vaisseau' => 'ship',
|
||||
'vaisseaux' => 'ship',
|
||||
'vehicule' => 'ship',
|
||||
'vehicules' => 'ship',
|
||||
'acces' => 'access',
|
||||
'access' => 'access',
|
||||
'mobilier' => 'access',
|
||||
'divers' => 'misc',
|
||||
'misc' => 'misc',
|
||||
'autre' => 'misc',
|
||||
'autres' => 'misc',
|
||||
'other' => 'misc',
|
||||
];
|
||||
|
||||
if (isset($exact_aliases[$slug])) {
|
||||
return $exact_aliases[$slug];
|
||||
}
|
||||
|
||||
$contains_aliases = [
|
||||
'weapon' => ['arme', 'weapon', 'pistol', 'rifle', 'shotgun', 'sniper', 'knife', 'blade'],
|
||||
'armor' => ['armure', 'armor', 'plating'],
|
||||
'tools' => ['outil', 'tool', 'tractor', 'mining', 'multitool', 'multi_tool', 'gadget'],
|
||||
'consumables' => ['consommable', 'consumable', 'usable', 'food', 'drink', 'med', 'medical', 'heal'],
|
||||
'ammunition' => ['munition', 'ammo', 'ammunition', 'magazine', 'grenade', 'rocket'],
|
||||
'attachments' => ['attachment', 'accessoire', 'scope', 'optic', 'silencer', 'sight', 'barrel'],
|
||||
'clothing' => ['clothing', 'vetement', 'apparel', 'outfit', 'char_clothing', 'char_head'],
|
||||
'cargo' => ['cargo', 'container', 'crate', 'box'],
|
||||
'ship' => ['component', 'composant', 'vaisseau', 'vehicule', 'thruster', 'quantum', 'powerplant', 'cooler', 'radar', 'sensor', 'shield', 'turret', 'missilelauncher', 'docking', 'flightcontroller', 'fueltank', 'fuelintake', 'aimodule'],
|
||||
'access' => ['door', 'seat', 'access', 'display', 'controlpanel', 'dashboard', 'mobilier'],
|
||||
];
|
||||
|
||||
foreach ($contains_aliases as $category => $needles) {
|
||||
if (sccharacters_string_contains_any($slug, $needles)) {
|
||||
return $category;
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
function sccharacters_guess_item_category(?string $type, ?string $subtype = null): string
|
||||
{
|
||||
$haystack = strtolower(trim(((string) $type) . ' ' . ((string) $subtype)));
|
||||
$slug = sccharacters_item_category_slug($haystack);
|
||||
|
||||
if ($slug === '') {
|
||||
return 'misc';
|
||||
}
|
||||
|
||||
if (sccharacters_string_contains_any($slug, ['char_clothing', 'char_head', 'clothing', 'apparel', 'outfit', 'hat', 'beard', 'piercing'])) {
|
||||
return 'clothing';
|
||||
}
|
||||
|
||||
if (sccharacters_string_contains_any($slug, ['weaponattachment', 'attachment', 'scope', 'optic', 'sight', 'silencer', 'barrel', 'mag_mount'])) {
|
||||
return 'attachments';
|
||||
}
|
||||
|
||||
if (sccharacters_string_contains_any($slug, ['missile', 'ammo', 'ammunition', 'magazine', 'rocket'])) {
|
||||
return 'ammunition';
|
||||
}
|
||||
|
||||
if (sccharacters_string_contains_any($slug, ['armor', 'armure'])) {
|
||||
return 'armor';
|
||||
}
|
||||
|
||||
if (sccharacters_string_contains_any($slug, ['weapon', 'gun', 'rifle', 'pistol', 'shotgun', 'sniper', 'knife', 'blade'])) {
|
||||
return 'weapon';
|
||||
}
|
||||
|
||||
if (sccharacters_string_contains_any($slug, ['usable', 'consumable', 'food', 'drink', 'fps_consumable', 'med', 'medical'])) {
|
||||
return 'consumables';
|
||||
}
|
||||
|
||||
if (sccharacters_string_contains_any($slug, ['tool', 'outil', 'mining', 'tractor', 'gadget', 'utility'])) {
|
||||
return 'tools';
|
||||
}
|
||||
|
||||
if (sccharacters_string_contains_any($slug, ['cargo', 'container', 'crate', 'box'])) {
|
||||
return 'cargo';
|
||||
}
|
||||
|
||||
if (sccharacters_string_contains_any($slug, ['door', 'seat', 'access', 'display', 'controlpanel', 'dashboard', 'shopdisplay', 'player'])) {
|
||||
return 'access';
|
||||
}
|
||||
|
||||
if (sccharacters_string_contains_any($slug, ['thruster', 'quantum', 'powerplant', 'cooler', 'radar', 'sensor', 'shield', 'turret', 'flightcontroller', 'fueltank', 'fuelintake', 'a_module', 'aimodule', 'docking', 'attachedpart'])) {
|
||||
return 'ship';
|
||||
}
|
||||
|
||||
return 'misc';
|
||||
}
|
||||
|
||||
function sccharacters_resolve_item_category(?string $storedValue, ?string $type, ?string $subtype = null): string
|
||||
{
|
||||
$normalized = sccharacters_normalize_item_category($storedValue);
|
||||
if ($normalized !== '') {
|
||||
return $normalized;
|
||||
}
|
||||
|
||||
return sccharacters_guess_item_category($type, $subtype);
|
||||
}
|
||||
430
sccharacter.php
Normal file
430
sccharacter.php
Normal file
@ -0,0 +1,430 @@
|
||||
<?php
|
||||
|
||||
require_once __DIR__ . '/db/auth.php';
|
||||
require_once __DIR__ . '/db/scstatsitem.php';
|
||||
require_once __DIR__ . '/db/scitemcustom.php';
|
||||
require_once __DIR__ . '/db/sccharacters.php';
|
||||
|
||||
auth_start_session();
|
||||
auth_bootstrap();
|
||||
scstatsitem_bootstrap();
|
||||
scitemcustom_bootstrap();
|
||||
sccharacters_bootstrap();
|
||||
|
||||
$db = db();
|
||||
$share_token = trim((string) ($_GET['share'] ?? ''));
|
||||
$character = null;
|
||||
$character_items = [];
|
||||
$custom_stats_by_itemcustom = [];
|
||||
|
||||
if ($share_token !== '') {
|
||||
$stmt_character = $db->prepare(
|
||||
'SELECT c.*, COALESCE(NULLIF(TRIM(a.cl_auth_user), \'\'), \'Inconnu\') AS cl_sccharacter_creator_name
|
||||
FROM tbl_sccharacters c
|
||||
LEFT JOIN tbl_auth a ON a.cl_auth_id = c.cl_sccharacter_owner_auth_id
|
||||
WHERE c.cl_sccharacter_share_token = :share_token
|
||||
AND c.cl_sccharacter_share_enabled = 1
|
||||
LIMIT 1'
|
||||
);
|
||||
$stmt_character->execute(['share_token' => $share_token]);
|
||||
$character = $stmt_character->fetch() ?: null;
|
||||
}
|
||||
|
||||
if ($character) {
|
||||
$stmt_items = $db->prepare(
|
||||
"SELECT
|
||||
ci.*,
|
||||
bo.cl_scobjs_name AS cl_sccharacteritem_base_name,
|
||||
bo.cl_scobjs_type AS cl_sccharacteritem_base_type,
|
||||
bo.cl_scobjs_subtype AS cl_sccharacteritem_base_subtype,
|
||||
bo.cl_scobjs_uuid AS cl_sccharacteritem_base_uuid,
|
||||
oo.cl_scobjs_name AS cl_sccharacteritem_custom_name,
|
||||
oo.cl_scobjs_type AS cl_sccharacteritem_custom_type,
|
||||
oo.cl_scobjs_subtype AS cl_sccharacteritem_custom_subtype,
|
||||
oo.cl_scobjs_uuid AS cl_sccharacteritem_custom_uuid
|
||||
FROM tbl_sccharacteritems ci
|
||||
LEFT JOIN tbl_scobjs bo ON bo.cl_scobjs_id = ci.cl_sccharacteritem_scobjs_id
|
||||
LEFT JOIN tbl_scitemcustom co ON co.cl_scitemcustom_id = ci.cl_sccharacteritem_scitemcustom_id
|
||||
LEFT JOIN tbl_scobjs oo ON oo.cl_scobjs_id = co.cl_scitemcustom_obj_id
|
||||
WHERE ci.cl_sccharacteritem_character_id = :character_id
|
||||
ORDER BY
|
||||
CASE WHEN TRIM(ci.cl_sccharacteritem_slot) = '' THEN 1 ELSE 0 END,
|
||||
ci.cl_sccharacteritem_slot ASC,
|
||||
COALESCE(oo.cl_scobjs_name, bo.cl_scobjs_name, 'ZZZ') ASC,
|
||||
ci.cl_sccharacteritem_id ASC"
|
||||
);
|
||||
$stmt_items->execute(['character_id' => (int) $character['cl_sccharacter_id']]);
|
||||
$character_items = $stmt_items->fetchAll();
|
||||
|
||||
$custom_item_ids = [];
|
||||
foreach ($character_items as $row) {
|
||||
if (($row['cl_sccharacteritem_source'] ?? '') === 'custom' && !empty($row['cl_sccharacteritem_scitemcustom_id'])) {
|
||||
$custom_item_ids[] = (int) $row['cl_sccharacteritem_scitemcustom_id'];
|
||||
}
|
||||
}
|
||||
$custom_item_ids = array_values(array_unique(array_filter($custom_item_ids)));
|
||||
|
||||
if ($custom_item_ids !== []) {
|
||||
$placeholders = implode(',', array_fill(0, count($custom_item_ids), '?'));
|
||||
$stmt_stats = $db->prepare(
|
||||
"SELECT
|
||||
cs.cl_scitemcustomstat_itemcustom_id,
|
||||
st.cl_scstatsitem_name,
|
||||
st.cl_scstatsitem_unit,
|
||||
cs.cl_scitemcustomstat_sign,
|
||||
cs.cl_scitemcustomstat_value
|
||||
FROM tbl_scitemcustomstat cs
|
||||
INNER JOIN tbl_scstatsitem st ON st.cl_scstatsitem_id = cs.cl_scitemcustomstat_stat_id
|
||||
WHERE cs.cl_scitemcustomstat_itemcustom_id IN ({$placeholders})
|
||||
ORDER BY st.cl_scstatsitem_name ASC, cs.cl_scitemcustomstat_id ASC"
|
||||
);
|
||||
$stmt_stats->execute($custom_item_ids);
|
||||
|
||||
foreach ($stmt_stats->fetchAll() as $stat_row) {
|
||||
$itemcustom_id = (int) $stat_row['cl_scitemcustomstat_itemcustom_id'];
|
||||
if (!isset($custom_stats_by_itemcustom[$itemcustom_id])) {
|
||||
$custom_stats_by_itemcustom[$itemcustom_id] = [];
|
||||
}
|
||||
$custom_stats_by_itemcustom[$itemcustom_id][] = $stat_row;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
http_response_code(404);
|
||||
}
|
||||
|
||||
$item_category_options = sccharacters_item_category_options();
|
||||
$character_items_by_category = [];
|
||||
foreach (array_keys($item_category_options) as $category_key) {
|
||||
$character_items_by_category[$category_key] = [];
|
||||
}
|
||||
foreach ($character_items as $item_row) {
|
||||
$is_custom = ($item_row['cl_sccharacteritem_source'] ?? '') === 'custom';
|
||||
$type = $is_custom
|
||||
? (string) ($item_row['cl_sccharacteritem_custom_type'] ?? '')
|
||||
: (string) ($item_row['cl_sccharacteritem_base_type'] ?? '');
|
||||
$subtype = $is_custom
|
||||
? (string) ($item_row['cl_sccharacteritem_custom_subtype'] ?? '')
|
||||
: (string) ($item_row['cl_sccharacteritem_base_subtype'] ?? '');
|
||||
$category_key = sccharacters_resolve_item_category(
|
||||
(string) ($item_row['cl_sccharacteritem_slot'] ?? ''),
|
||||
$type,
|
||||
$subtype
|
||||
);
|
||||
if (!isset($character_items_by_category[$category_key])) {
|
||||
$character_items_by_category[$category_key] = [];
|
||||
}
|
||||
$character_items_by_category[$category_key][] = $item_row;
|
||||
}
|
||||
$character_items_by_category = array_filter(
|
||||
$character_items_by_category,
|
||||
static fn(array $items): bool => $items !== []
|
||||
);
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title><?php echo htmlspecialchars($character ? ((string) $character['cl_sccharacter_name'] . ' | Personnage partagé') : 'Personnage introuvable', ENT_QUOTES, 'UTF-8'); ?></title>
|
||||
<style>
|
||||
:root {
|
||||
--primary: #a29b78;
|
||||
--primary-soft: rgba(162, 155, 120, 0.18);
|
||||
--primary-border: rgba(162, 155, 120, 0.3);
|
||||
--bg: #080a0f;
|
||||
--card: rgba(20, 24, 33, 0.88);
|
||||
--text-main: #ece9df;
|
||||
--text-soft: rgba(236, 233, 223, 0.72);
|
||||
}
|
||||
|
||||
* { box-sizing: border-box; }
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
min-height: 100vh;
|
||||
background: radial-gradient(circle at top right, #1d2234 0%, #0a0d13 55%, #050608 100%);
|
||||
color: var(--text-main);
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
}
|
||||
|
||||
.page {
|
||||
max-width: 1180px;
|
||||
margin: 0 auto;
|
||||
padding: 2rem 1rem 3rem;
|
||||
}
|
||||
|
||||
.hero,
|
||||
.card,
|
||||
.message {
|
||||
background: var(--card);
|
||||
border: 1px solid var(--primary-border);
|
||||
border-radius: 20px;
|
||||
box-shadow: 0 22px 50px rgba(0,0,0,0.28);
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
.hero {
|
||||
padding: 1.4rem;
|
||||
display: grid;
|
||||
grid-template-columns: 120px minmax(0, 1fr);
|
||||
gap: 1.2rem;
|
||||
margin-bottom: 1.3rem;
|
||||
}
|
||||
|
||||
.avatar,
|
||||
.avatar-fallback {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
border-radius: 28px;
|
||||
object-fit: cover;
|
||||
background: linear-gradient(145deg, rgba(162, 155, 120, 0.3), rgba(255,255,255,0.08));
|
||||
border: 1px solid rgba(255,255,255,0.08);
|
||||
}
|
||||
|
||||
.avatar-fallback {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 2.2rem;
|
||||
color: var(--primary);
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
h1 { margin: 0 0 0.65rem; font-size: 2rem; }
|
||||
p { line-height: 1.6; }
|
||||
|
||||
.meta,
|
||||
.stats,
|
||||
.tags {
|
||||
display: flex;
|
||||
gap: 0.55rem;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.tag {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
padding: 0.34rem 0.62rem;
|
||||
border-radius: 999px;
|
||||
background: rgba(255,255,255,0.06);
|
||||
border: 1px solid rgba(255,255,255,0.08);
|
||||
font-size: 0.84rem;
|
||||
}
|
||||
|
||||
.tag-primary {
|
||||
background: var(--primary-soft);
|
||||
border-color: rgba(162, 155, 120, 0.35);
|
||||
color: #f6eebf;
|
||||
}
|
||||
|
||||
.muted { color: var(--text-soft); }
|
||||
|
||||
.equipment-sections {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.equipment-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.8rem;
|
||||
}
|
||||
|
||||
.equipment-section-head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 0.8rem;
|
||||
}
|
||||
|
||||
.equipment-section-title {
|
||||
margin: 0;
|
||||
color: var(--primary);
|
||||
letter-spacing: 0.08em;
|
||||
text-transform: uppercase;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.card {
|
||||
padding: 1rem;
|
||||
display: flex;
|
||||
gap: 0.95rem;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.thumb,
|
||||
.thumb-fallback {
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
border-radius: 18px;
|
||||
object-fit: cover;
|
||||
flex: 0 0 68px;
|
||||
background: rgba(255,255,255,0.06);
|
||||
border: 1px solid rgba(255,255,255,0.08);
|
||||
}
|
||||
|
||||
.thumb-fallback {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: var(--primary);
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
.card-body { min-width: 0; }
|
||||
.card-body h3 { margin: 0 0 0.45rem; font-size: 1.05rem; }
|
||||
.stats { margin-top: 0.7rem; }
|
||||
|
||||
.stat {
|
||||
padding: 0.32rem 0.55rem;
|
||||
border-radius: 999px;
|
||||
background: rgba(255,255,255,0.06);
|
||||
border: 1px solid rgba(255,255,255,0.08);
|
||||
font-size: 0.78rem;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
margin: 1.2rem 0 0.8rem;
|
||||
color: var(--primary);
|
||||
letter-spacing: 0.08em;
|
||||
text-transform: uppercase;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.message {
|
||||
padding: 1.4rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@media (max-width: 860px) {
|
||||
.hero,
|
||||
.grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="page">
|
||||
<?php if (!$character): ?>
|
||||
<div class="message">
|
||||
<h1>Personnage introuvable</h1>
|
||||
<p class="muted">Ce lien public est invalide, désactivé ou n’est plus disponible.</p>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<?php
|
||||
$avatar = trim((string) ($character['cl_sccharacter_avatar_url'] ?? ''));
|
||||
$initial = function_exists('mb_substr')
|
||||
? mb_strtoupper(mb_substr((string) $character['cl_sccharacter_name'], 0, 1, 'UTF-8'), 'UTF-8')
|
||||
: strtoupper(substr((string) $character['cl_sccharacter_name'], 0, 1));
|
||||
?>
|
||||
<section class="hero">
|
||||
<?php if ($avatar !== ''): ?>
|
||||
<img class="avatar" src="<?php echo htmlspecialchars($avatar, ENT_QUOTES, 'UTF-8'); ?>" alt="Avatar de <?php echo htmlspecialchars((string) $character['cl_sccharacter_name'], ENT_QUOTES, 'UTF-8'); ?>" loading="lazy" onerror="this.replaceWith(Object.assign(document.createElement('div'), {className:'avatar-fallback', textContent:'<?php echo htmlspecialchars($initial, ENT_QUOTES, 'UTF-8'); ?>'}));">
|
||||
<?php else: ?>
|
||||
<div class="avatar-fallback"><?php echo htmlspecialchars($initial, ENT_QUOTES, 'UTF-8'); ?></div>
|
||||
<?php endif; ?>
|
||||
<div>
|
||||
<h1><?php echo htmlspecialchars((string) $character['cl_sccharacter_name'], ENT_QUOTES, 'UTF-8'); ?></h1>
|
||||
<div class="meta">
|
||||
<?php if (trim((string) $character['cl_sccharacter_role']) !== ''): ?>
|
||||
<span class="tag tag-primary"><?php echo htmlspecialchars((string) $character['cl_sccharacter_role'], ENT_QUOTES, 'UTF-8'); ?></span>
|
||||
<?php endif; ?>
|
||||
<?php if (trim((string) $character['cl_sccharacter_faction']) !== ''): ?>
|
||||
<span class="tag"><?php echo htmlspecialchars((string) $character['cl_sccharacter_faction'], ENT_QUOTES, 'UTF-8'); ?></span>
|
||||
<?php endif; ?>
|
||||
<span class="tag muted">Créé par <?php echo htmlspecialchars((string) $character['cl_sccharacter_creator_name'], ENT_QUOTES, 'UTF-8'); ?></span>
|
||||
<span class="tag muted"><?php echo count($character_items); ?> équipement(s)</span>
|
||||
</div>
|
||||
<p><?php echo nl2br(htmlspecialchars(trim((string) $character['cl_sccharacter_description']) !== '' ? (string) $character['cl_sccharacter_description'] : 'Aucune description publique fournie pour ce personnage.', ENT_QUOTES, 'UTF-8')); ?></p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<h2 class="section-title">Équipement</h2>
|
||||
<?php if ($character_items === []): ?>
|
||||
<div class="message">
|
||||
<p class="muted">Ce personnage n’a pas encore d’équipement attribué.</p>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div class="equipment-sections">
|
||||
<?php foreach ($character_items_by_category as $category_key => $category_items): ?>
|
||||
<section class="equipment-section">
|
||||
<div class="equipment-section-head">
|
||||
<h3 class="equipment-section-title"><?php echo htmlspecialchars(sccharacters_item_category_label((string) $category_key), ENT_QUOTES, 'UTF-8'); ?></h3>
|
||||
<span class="tag muted"><?php echo count($category_items); ?> objet(s)</span>
|
||||
</div>
|
||||
<div class="grid">
|
||||
<?php foreach ($category_items as $item_row): ?>
|
||||
<?php
|
||||
$is_custom = ($item_row['cl_sccharacteritem_source'] ?? '') === 'custom';
|
||||
$name = $is_custom
|
||||
? (string) ($item_row['cl_sccharacteritem_custom_name'] ?? 'Objet personnalisé indisponible')
|
||||
: (string) ($item_row['cl_sccharacteritem_base_name'] ?? 'Objet indisponible');
|
||||
$type = $is_custom
|
||||
? (string) ($item_row['cl_sccharacteritem_custom_type'] ?? '')
|
||||
: (string) ($item_row['cl_sccharacteritem_base_type'] ?? '');
|
||||
$subtype = $is_custom
|
||||
? (string) ($item_row['cl_sccharacteritem_custom_subtype'] ?? '')
|
||||
: (string) ($item_row['cl_sccharacteritem_base_subtype'] ?? '');
|
||||
$uuid = $is_custom
|
||||
? (string) ($item_row['cl_sccharacteritem_custom_uuid'] ?? '')
|
||||
: (string) ($item_row['cl_sccharacteritem_base_uuid'] ?? '');
|
||||
$category = sccharacters_resolve_item_category(
|
||||
(string) ($item_row['cl_sccharacteritem_slot'] ?? ''),
|
||||
$type,
|
||||
$subtype
|
||||
);
|
||||
$note = trim((string) ($item_row['cl_sccharacteritem_note'] ?? ''));
|
||||
$stats = $is_custom ? ($custom_stats_by_itemcustom[(int) ($item_row['cl_sccharacteritem_scitemcustom_id'] ?? 0)] ?? []) : [];
|
||||
?>
|
||||
<article class="card">
|
||||
<?php if ($uuid !== ''): ?>
|
||||
<img class="thumb" src="https://cstone.space/uifimages/<?php echo htmlspecialchars($uuid, ENT_QUOTES, 'UTF-8'); ?>.png" alt="Aperçu de <?php echo htmlspecialchars($name, ENT_QUOTES, 'UTF-8'); ?>" loading="lazy" onerror="this.replaceWith(Object.assign(document.createElement('div'), {className:'thumb-fallback', textContent:'◈'}));">
|
||||
<?php else: ?>
|
||||
<div class="thumb-fallback">◈</div>
|
||||
<?php endif; ?>
|
||||
<div class="card-body">
|
||||
<h3><?php echo htmlspecialchars($name, ENT_QUOTES, 'UTF-8'); ?></h3>
|
||||
<div class="tags">
|
||||
<span class="tag <?php echo $is_custom ? 'tag-primary' : ''; ?>"><?php echo $is_custom ? 'Objet perso.' : 'Base d’objets'; ?></span>
|
||||
<span class="tag"><?php echo htmlspecialchars(sccharacters_item_category_label($category), ENT_QUOTES, 'UTF-8'); ?></span>
|
||||
<?php if ($type !== ''): ?><span class="tag muted"><?php echo htmlspecialchars($type, ENT_QUOTES, 'UTF-8'); ?></span><?php endif; ?>
|
||||
<?php if ($subtype !== ''): ?><span class="tag muted"><?php echo htmlspecialchars($subtype, ENT_QUOTES, 'UTF-8'); ?></span><?php endif; ?>
|
||||
</div>
|
||||
<?php if ($stats !== []): ?>
|
||||
<div class="stats">
|
||||
<?php foreach ($stats as $stat_row): ?>
|
||||
<?php
|
||||
$sign = (string) ($stat_row['cl_scitemcustomstat_sign'] ?? '');
|
||||
$value = rtrim(rtrim(number_format((float) ($stat_row['cl_scitemcustomstat_value'] ?? 0), 2, '.', ''), '0'), '.');
|
||||
if ($value === '') {
|
||||
$value = '0';
|
||||
}
|
||||
?>
|
||||
<span class="stat"><?php echo htmlspecialchars((string) $stat_row['cl_scstatsitem_name'] . ' : ' . $sign . $value . ' ' . (string) $stat_row['cl_scstatsitem_unit'], ENT_QUOTES, 'UTF-8'); ?></span>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php if ($note !== ''): ?>
|
||||
<p class="muted"><?php echo nl2br(htmlspecialchars($note, ENT_QUOTES, 'UTF-8')); ?></p>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</article>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</section>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
2099
sccharacters.php
Normal file
2099
sccharacters.php
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user