Вход Регистрация
Файл: pages/economy/cave.php
Строк: 363
<?php
/** Пещера — поиск и добыча ресурсов. */
declare(strict_types=1);
if(!
defined('GAME_ROOT')) define('GAME_ROOT',dirname(__DIR__,2));
chdir(GAME_ROOT);
if(
PHP_SAPI!=='cli'){$_SERVER['PHP_SELF']='/cave.php';$_SERVER['SCRIPT_NAME']='/cave.php';}
define('NO_GAME_LIVE_JS',true);
require_once 
'./system/common.php';require_once './system/functions.php';require_once './system/user.php';require_once './system/menu.php';
if(!
$user){header('Location:/');exit;}
$uid=(int)$user['id'];$title='Пещера';

function 
cave511_bootstrap(): void {
    static 
$done=false;if($done)return;$done=true;
    
db_query("CREATE TABLE IF NOT EXISTS `cave_v512_state` (
      `user_id` int unsigned NOT NULL,
      `stage` enum('idle','searching','found','gathering') NOT NULL DEFAULT 'idle',
      `ends_at` int unsigned NOT NULL DEFAULT 0,
      `res1` tinyint unsigned NOT NULL DEFAULT 0, `chance1` tinyint unsigned NOT NULL DEFAULT 0,
      `res2` tinyint unsigned NOT NULL DEFAULT 0, `chance2` tinyint unsigned NOT NULL DEFAULT 0,
      `res3` tinyint unsigned NOT NULL DEFAULT 0, `chance3` tinyint unsigned NOT NULL DEFAULT 0,
      `result_json` text NULL, `updated_at` int unsigned NOT NULL DEFAULT 0,
      PRIMARY KEY (`user_id`), KEY `stage_end` (`stage`,`ends_at`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci"
);
}
function 
cave511_row(int $uid): array {
    
$r=db_fetch_one('SELECT * FROM `cave_v512_state` WHERE `user_id`=:u LIMIT 1',['u'=>$uid]);
    if(!
$r){db_execute("INSERT INTO `cave_v512_state` (`user_id`,`stage`,`updated_at`) VALUES (:u,'idle',:t)",['u'=>$uid,'t'=>time()]);$r=db_fetch_one('SELECT * FROM `cave_v512_state` WHERE `user_id`=:u LIMIT 1',['u'=>$uid]);}
    return 
$r??['user_id'=>$uid,'stage'=>'idle','ends_at'=>0,'res1'=>0,'chance1'=>0,'res2'=>0,'chance2'=>0,'res3'=>0,'chance3'=>0,'result_json'=>null,'updated_at'=>0];
}
function 
cave511_name(int $id): string {return [1=>'Алмаз',2=>'Оникс',3=>'Малахит',4=>'Рубин',5=>'Сапфир',6=>'Амброзия',7=>'Мята',8=>'Аир',9=>'Рябина'][$id]??'Ресурс';}
function 
cave511_stage_seconds(string $stage,array $user): int {
    
$base=$stage==='searching'?1500:1800;$premium=false;
    if(isset(
$GLOBALS['premium1']))$premium=(bool)$GLOBALS['premium1'];if(isset($GLOBALS['premium'])&&is_array($GLOBALS['premium']))$premium=$premium||((int)($GLOBALS['premium']['time']??0)>time());
    if(
$premium)$base=(int)round($base*.90);$lab=db_fetch_one('SELECT `id` FROM `lab_` WHERE `user`=:u AND `type`=2 LIMIT 1',['u'=>(int)$user['id']]);if($lab)$base=(int)round($base*.80);$prof=$GLOBALS['profesion']??null;if(is_array($prof)&&(int)($prof['prof_cave']??0)===1)$base=(int)round($base*.85);return max(300,$base);
}
function 
cave511_speed_price(int $seconds,array $user): int {$minutes=max(1,(int)ceil(max(0,$seconds)/60));$perMinute=max(60,min(350,60+(int)($user['level']??1)*3));return min(50000,$minutes*$perMinute);}
function 
cave511_settle(int $uid): void {
    
$pdo=db_pdo();$pdo->beginTransaction();
    try{
        
$r=db_fetch_one('SELECT * FROM `cave_v512_state` WHERE `user_id`=:u LIMIT 1 FOR UPDATE',['u'=>$uid]);if(!$r){$pdo->commit();return;}$now=time();$stage=(string)$r['stage'];$end=(int)$r['ends_at'];if($end<=0||$end>$now){$pdo->commit();return;}
        if(
$stage==='searching'){$pool=range(1,9);shuffle($pool);$res=array_slice($pool,0,3);db_execute("UPDATE `cave_v512_state` SET `stage`='found',`ends_at`=0,`res1`=:r1,`chance1`=25,`res2`=:r2,`chance2`=35,`res3`=:r3,`chance3`=40,`updated_at`=:t WHERE `user_id`=:u",['r1'=>$res[0],'r2'=>$res[1],'r3'=>$res[2],'t'=>$now,'u'=>$uid]);$pdo->commit();return;}
        if(
$stage==='gathering'){
            
$result=[];$found=0;$stone=0;$grass=0;$sack=db_fetch_one('SELECT `id` FROM `sack` WHERE `user`=:u ORDER BY `id` DESC LIMIT 1 FOR UPDATE',['u'=>$uid]);if(!$sack){db_execute('INSERT INTO `sack` (`user`) VALUES (:u)',['u'=>$uid]);$sack=['id'=>(int)db_pdo()->lastInsertId()];}$sackId=(int)$sack['id'];
            for(
$i=1;$i<=3;$i++){$rid=max(1,min(9,(int)$r['res'.$i]));$chance=max(0,min(100,(int)$r['chance'.$i]));$ok=random_int(1,100)<=$chance;$result[]=['id'=>$rid,'chance'=>$chance,'ok'=>$ok];if($ok){$found++;if($rid<=5)$stone++;else$grass++;$col=(string)$rid;db_execute("UPDATE `sack` SET `$col`=`$col`+1 WHERE `id`=:i",['i'=>$sackId]);}}
            if(
$stone>0||$grass>0)db_execute('UPDATE `users` SET `stone`=`stone`+:st,`grass`=`grass`+:gr WHERE `id`=:u',['st'=>$stone,'gr'=>$grass,'u'=>$uid]);
            
db_execute("UPDATE `cave_v512_state` SET `stage`='idle',`ends_at`=0,`res1`=0,`chance1`=0,`res2`=0,`chance2`=0,`res3`=0,`chance3`=0,`result_json`=:j,`updated_at`=:t WHERE `user_id`=:u",['j'=>json_encode($result,JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES),'t'=>$now,'u'=>$uid]);$pdo->commit();if(function_exists('game_quest_progress_event'))game_quest_progress_event($uid,5,1,$found>0?1:0);return;
        }
        
$pdo->commit();
    }catch(
Throwable $e){if($pdo->inTransaction())$pdo->rollBack();throw $e;}
}

cave511_bootstrap();cave511_row($uid);
try{
cave511_settle($uid);}catch(Throwable $e){$_SESSION['err']='Не удалось завершить этап Пещеры. Попробуйте ещё раз.';if(function_exists('app_log_write'))app_log_write('CAVE','Cave settle failed',['user_id'=>$uid,'type'=>get_class($e),'message'=>$e->getMessage()]);}

if((
$_SERVER['REQUEST_METHOD']??'GET')==='POST'){
    try{
        
security_require_csrf();$act=(string)($_POST['act']??'');$pdo=db_pdo();$pdo->beginTransaction();$r=db_fetch_one('SELECT * FROM `cave_v512_state` WHERE `user_id`=:u LIMIT 1 FOR UPDATE',['u'=>$uid]);if(!$r)throw new RuntimeException('Следы в Пещере потеряны. Начните поиск заново.');$stage=(string)$r['stage'];$now=time();
        if(
$act==='start'){
            if(
$stage!=='idle')throw new RuntimeException('Предыдущий цикл ещё не завершён.');$sec=cave511_stage_seconds('searching',$user);db_execute("UPDATE `cave_v512_state` SET `stage`='searching',`ends_at`=:e,`result_json`=NULL,`updated_at`=:t WHERE `user_id`=:u",['e'=>$now+$sec,'t'=>$now,'u'=>$uid]);$pdo->commit();if(!empty($GLOBALS['clan']['id'])&&function_exists('game_clan_quest_is_week_open')&&game_clan_quest_is_week_open())game_clan_quest_increment((int)$GLOBALS['clan']['id'],5,$uid,1);$_SESSION['ok']='Поиск ресурсов начат.';
        }elseif(
$act==='speed'){
            if(!
in_array($stage,['searching','gathering'],true)||(int)$r['ends_at']<=$now)throw new RuntimeException('Сейчас нечего ускорять.');$price=cave511_speed_price((int)$r['ends_at']-$now,$user);$pay=db_prepare('UPDATE `users` SET `s`=`s`-:p WHERE `id`=:u AND `s`>=:p2',['p'=>$price,'u'=>$uid,'p2'=>$price]);if($pay->rowCount()!==1)throw new RuntimeException('Не хватает серебра.');db_execute('UPDATE `cave_v512_state` SET `ends_at`=:e,`updated_at`=:t WHERE `user_id`=:u',['e'=>$now,'t'=>$now,'u'=>$uid]);$pdo->commit();cave511_settle($uid);$_SESSION['ok']='Этап завершён досрочно.';
        }elseif(
$act==='boost'){
            if(
$stage!=='found')throw new RuntimeException('Сначала завершите поиск ресурсов.');$pay=db_prepare('UPDATE `users` SET `g`=`g`-16 WHERE `id`=:u AND `g`>=16',['u'=>$uid]);if($pay->rowCount()!==1)throw new RuntimeException('Нужно 16 золота.');db_execute('UPDATE `cave_v512_state` SET `chance1`=100,`chance2`=100,`chance3`=100,`updated_at`=:t WHERE `user_id`=:u',['t'=>$now,'u'=>$uid]);$pdo->commit();$_SESSION['ok']='Шанс добычи увеличен до 100%.';
        }elseif(
$act==='gather'){
            if(
$stage!=='found'||(int)$r['res1']<=0)throw new RuntimeException('Нет найденных ресурсов для добычи.');$sec=cave511_stage_seconds('gathering',$user);db_execute("UPDATE `cave_v512_state` SET `stage`='gathering',`ends_at`=:e,`updated_at`=:t WHERE `user_id`=:u",['e'=>$now+$sec,'t'=>$now,'u'=>$uid]);$pdo->commit();$_SESSION['ok']='Добыча начата.';
        }else throw new 
RuntimeException('Неизвестное действие.');
    }catch(
Throwable $e){if(isset($pdo)&&$pdo instanceof PDO&&$pdo->inTransaction())$pdo->rollBack();$_SESSION['err']=$e->getMessage();}
    
header('Location:/cave/');exit;
}

$state=cave511_row($uid);$result=[];if(!empty($state['result_json'])){$tmp=json_decode((string)$state['result_json'],true);if(is_array($tmp))$result=$tmp;}
require 
'./system/h.php';
if(!empty(
$_SESSION['ok'])){echo '<div class="ok center">'.security_system_text((string)$_SESSION['ok']).'</div>';unset($_SESSION['ok']);}
if(!empty(
$_SESSION['err'])){echo '<div class="error center">'.security_html((string)$_SESSION['err']).'</div>';unset($_SESSION['err']);}
?>
<div class="menuList"><li><a href="/city/"><img src="/images/icon/arrow.png" alt="">Назад</a></li></div>
<div class="title">Пещера</div><div class="block_zero center"><img src="/images/town/hd/cave.jpg" width="100%" alt="Пещера"></div>
<?php if($state['stage']==='searching'||$state['stage']==='gathering'):$left=max(0,(int)$state['ends_at']-time());$price=cave511_speed_price($left,$user);?>
<div class="block center"><div class="blue"><?=$state['stage']==='searching'?'Вы осматриваете пещеру':'Вы добываете найденные ресурсы'?></div><b>До конца: <?=security_html(_time($left))?></b><br><small>Этап завершится в <?=date('H:i',(int)$state['ends_at'])?></small><br><a href="/cave/">Осмотреть пещеру</a><form method="post" class="mt5"><?=security_csrf_field()?><input type="hidden" name="act" value="speed"><button class="old-btn" type="submit">Ускорить за <img src="/images/icon/silver.png" alt=""> <?=n_f($price)?></button></form><div class="small orange">Когда время закончится, осмотрите пещеру и заберите результат.</div></div>
<?php elseif($state['stage']==='found'):?>
<div class="block center blue">Осмотр пещеры завершён<br><b class="white">Вы нашли место с ресурсами:</b></div>
<?php for($i=1;$i<=3;$i++):$rid=(int)$state['res'.$i];$ch=(int)$state['chance'.$i];?><div class="block_zero"><img src="/images/res/<?=$rid?>.png" width="50" height="50" alt="" class="fl mr8"><b><?=security_html(cave511_name($rid))?></b><br>Шанс добыть: <b class="green"><?=$ch?>%</b><div class="clr"></div></div><?php endfor;?>
<div class="block center"><?php if((int)$state['chance1']<100||(int)$state['chance2']<100||(int)$state['chance3']<100):?><form method="post" class="mb5"><?=security_csrf_field()?><input type="hidden" name="act" value="boost"><button class="old-btn" type="submit">Увеличить шанс до 100% за <img src="/images/icon/gold.png" alt=""> 16</button></form><?php endif;?><form method="post"><?=security_csrf_field()?><input type="hidden" name="act" value="gather"><button class="old-btn" type="submit">Начать добычу</button></form></div>
<?php else:?>
<?php 
if($result):?><div class="block"><div class="blue center">Результат последней добычи</div><?php foreach($result as $row):$rid=(int)($row['id']??0);?><div class="block_zero"><img src="/images/res/<?=$rid?>.png" width="42" height="42" alt="" class="fl mr8"><b><?=security_html(cave511_name($rid))?></b><br><?=$row['ok']?'<span class="green">Ресурс добыт</span>':'<span class="red">Ресурс не добыт</span>'?> <span class="small grey">(шанс <?=(int)($row['chance']??0)?>%)</span><div class="clr"></div></div><?php endforeach;?></div><?php endif;?>
<div class="block center"><div class="blue">Начните новый поиск ресурсов</div><form method="post" class="mt5"><?=security_csrf_field()?><input type="hidden" name="act" value="start"><button class="old-btn" type="submit"><?=$result?'Новый поиск':'Начать поиск'?></button></form></div>
<?php endif;?>
<div class="mini-line"></div><ul class="hint"><li>Поиск и добыча продолжаются, даже если вы ушли в другую локацию.</li><li>После завершения этапа вернитесь в Пещеру, чтобы увидеть находку.</li><li>Результат хранится до начала нового поиска.</li></ul>
<?php require './system/f.php';?>
Онлайн: 3
Реклама