Вход Регистрация
Файл: system/starter.php
Строк: 125
<?php
/* Обновление игры под PHP 8.4 / PDO, стартовое снаряжение и защита регистрации: by Метриум (Стэлп) */
declare(strict_types=1);

/**
 * Стартовые комплекты. Используются только реальные предметы из items/shop.
 * Все восемь слотов выдаются и надеваются атомарно при создании персонажа.
 */
function starter_kits(): array {
    return [
        
=> ['name' => 'Комплект воина',     'items' => [9,10,11,12,13,14,15,16]],
        
=> ['name' => 'Комплект охотника',  'items' => [25,26,27,28,29,30,31,32]],
    ];
}

function 
starter_state(): array {
    if (
session_status() !== PHP_SESSION_ACTIVEsession_start();
    
$kits starter_kits();
    
$state $_SESSION['_starter'] ?? [];
    if (!
is_array($state)) $state = [];
    
$sex = (int)($state['sex'] ?? 0);
    if (!
in_array($sex, [0,1], true)) $sex 0;
    
$kit = (int)($state['kit'] ?? 0);
    if (!isset(
$kits[$kit])) $kit 0;
    
$ref max(0, (int)($state['ref'] ?? 0));
    
$_SESSION['_starter'] = ['sex'=>$sex'kit'=>$kit'ref'=>$ref'updated'=>time()];
    return 
$_SESSION['_starter'];
}

function 
starter_set_ref(int $ref): void {
    
$state starter_state();
    
$state['ref'] = max(0$ref);
    
$state['updated'] = time();
    
$_SESSION['_starter'] = $state;
}

function 
starter_set_sex(int $sex): void {
    
$state starter_state();
    
$state['sex'] = $sex === 0;
    
$state['updated'] = time();
    
$_SESSION['_starter'] = $state;
}

function 
starter_next_kit(): void {
    
$state starter_state();
    
$kits starter_kits();
    
$keys array_keys($kits);
    
$pos array_search((int)$state['kit'], $keystrue);
    
$pos $pos === false : (($pos 1) % count($keys));
    
$state['kit'] = (int)$keys[$pos];
    
$state['updated'] = time();
    
$_SESSION['_starter'] = $state;
}

function 
starter_selected_kit(): array {
    
$state starter_state();
    return 
starter_kits()[(int)$state['kit']];
}

function 
starter_maneken_url(): string {
    
$state starter_state();
    
$kit starter_selected_kit();
    
$items array_map('intval'$kit['items']);
    return 
'/manekenImage/'.(int)$state['sex'].'/'.implode('/'$items).'/0/';
}

/**
 * Загружает параметры стартовых вещей из БД, а не доверяет данным формы/сессии.
 */
function starter_load_items(): array {
    
$kit starter_selected_kit();
    
$ids array_map('intval'$kit['items']);
    if (
count($ids) !== 8) throw new RuntimeException('Starter kit is incomplete');

    
$placeholders implode(','array_fill(0count($ids), '?'));
    
$stmt db_prepare(
        
"SELECT i.id,i.w,i.name,i.quality,i.skill,s.bonus,s._str,s._vit,s._agi,s._def
         FROM items i INNER JOIN shop s ON s.id=i.id
         WHERE i.id IN (
$placeholders)",
        
$ids
    
);
    
$rows $stmt->fetchAll(PDO::FETCH_ASSOC);
    
$bySlot = [];
    foreach (
$rows as $row) {
        
$slot = (int)$row['w'];
        if (
$slot >= && $slot <= 8$bySlot[$slot] = $row;
    }
    for (
$slot=1$slot<=8$slot++) {
        if (!isset(
$bySlot[$slot])) throw new RuntimeException('Starter item missing for slot '.$slot);
    }
    
ksort($bySlot);
    return 
$bySlot;
}

function 
starter_stats(): array {
    
$stats = ['str'=>0,'vit'=>0,'agi'=>0,'def'=>0];
    foreach (
starter_load_items() as $row) {
        
$stats['str'] += (int)$row['_str'];
        
$stats['vit'] += (int)$row['_vit'];
        
$stats['agi'] += (int)$row['_agi'];
        
$stats['def'] += (int)$row['_def'];
    }
    return 
$stats;
}

/**
 * Выдаёт и сразу надевает выбранный комплект.
 * Должно вызываться внутри транзакции сразу после INSERT users.
 */
function starter_grant_and_equip(PDO $pdoint $userId): array {
    if (
$userId <= 0) throw new InvalidArgumentException('Invalid user id');
    
$items starter_load_items();
    
$worn = [];
    
$sum = ['str'=>0,'vit'=>0,'agi'=>0,'def'=>0];

    
$insert $pdo->prepare(
        
'INSERT INTO `inv` (`user`,`item`,`quality`,`bonus`,`smith`,`equip`,`new`,`rune`,`_str`,`_vit`,`_agi`,`_def`,`place`)
         VALUES (:user,:item,:quality,:bonus,0,1,1,0,:str,:vit,:agi,:def,0)'
    
);
    foreach (
$items as $slot => $row) {
        
$insert->execute([
            
'user'=>$userId,
            
'item'=>(int)$row['id'],
            
'quality'=>(int)$row['quality'],
            
'bonus'=>(int)$row['bonus'],
            
'str'=>(int)$row['_str'],
            
'vit'=>(int)$row['_vit'],
            
'agi'=>(int)$row['_agi'],
            
'def'=>(int)$row['_def'],
        ]);
        
$invId = (int)$pdo->lastInsertId();
        if (
$invId <= 0) throw new RuntimeException('Cannot create starter inventory row');
        
$worn[$slot] = $invId;
        
$sum['str'] += (int)$row['_str'];
        
$sum['vit'] += (int)$row['_vit'];
        
$sum['agi'] += (int)$row['_agi'];
        
$sum['def'] += (int)$row['_def'];
    }

    
$sql 'UPDATE `users` SET '
         
'`sex`=:sex, '
         
'`str`=`str`+:str,`vit`=`vit`+:vit,`agi`=`agi`+:agi,`def`=`def`+:def, '
         
'`w_1`=:w1,`w_2`=:w2,`w_3`=:w3,`w_4`=:w4,`w_5`=:w5,`w_6`=:w6,`w_7`=:w7,`w_8`=:w8 '
         
'WHERE `id`=:id';
    
$state starter_state();
    
$stmt $pdo->prepare($sql);
    
$stmt->execute([
        
'sex'=>(int)$state['sex'],
        
'str'=>$sum['str'],'vit'=>$sum['vit'],'agi'=>$sum['agi'],'def'=>$sum['def'],
        
'w1'=>$worn[1],'w2'=>$worn[2],'w3'=>$worn[3],'w4'=>$worn[4],
        
'w5'=>$worn[5],'w6'=>$worn[6],'w7'=>$worn[7],'w8'=>$worn[8],
        
'id'=>$userId,
    ]);

    
// Текущее HP соответствует уже итоговой выносливости, MP — текущей мане.
    
$pdo->prepare('UPDATE `users` SET `hp`=`vit`*2, `mp`=`mana` WHERE `id`=?')->execute([$userId]);
    return [
'worn'=>$worn,'stats'=>$sum];
}

function 
starter_clear(): void {
    unset(
$_SESSION['_starter']);
}
Онлайн: 3
Реклама