Файл: system/clan_quests.php
Строк: 333
<?php
declare(strict_types=1);
/**
* Клановые задания v50.6.
* Единая конфигурация, безопасные POST-действия и уведомления (+).
* by Метриум (Стэлп)
*/
function game_clan_quest_defs(): array {
return [
1=>['title'=>'Воин арены','description'=>'Проведи 80 боёв на арене.','goal'=>80,'route'=>'/arena/','gold'=>10,'exp'=>150],
2=>['title'=>'Легендарный воин арены','description'=>'Проведи 55 боёв на арене.','goal'=>55,'route'=>'/arena/','gold'=>10,'exp'=>150],
3=>['title'=>'Гладиатор','description'=>'Проведи 30 боёв в лиге.','goal'=>30,'route'=>'/league/','gold'=>15,'exp'=>250],
4=>['title'=>'Легендарный гладиатор','description'=>'Проведи 20 боёв в лиге.','goal'=>20,'route'=>'/league/','gold'=>25,'exp'=>350],
5=>['title'=>'Поиск ресурсов','description'=>'Проведи 15 поисков в пещере.','goal'=>15,'route'=>'/cave/','gold'=>5,'exp'=>100],
6=>['title'=>'Дуэльный мастер','description'=>'Проведи 20 боёв в дуэлях.','goal'=>20,'route'=>'/duel/','gold'=>20,'exp'=>200],
7=>['title'=>'Победная серия клана','description'=>'Одержи 25 побед на арене.','goal'=>25,'route'=>'/arena/','gold'=>25,'exp'=>320],
8=>['title'=>'Охота бессмертных','description'=>'Победи 15 врагов в Долине бессмертных.','goal'=>15,'route'=>'/undying/','gold'=>30,'exp'=>420],
];
}
function game_clan_quest_row(int $clanId,bool $create=true): ?array {
if($clanId<=0) return null;
$row=db_fetch_one('SELECT * FROM `clans_q` WHERE `clans`=:c ORDER BY `id` ASC LIMIT 1',['c'=>$clanId]);
if(!$row && $create){
db_execute('INSERT INTO `clans_q` (`clans`) VALUES (:c)',['c'=>$clanId]);
$row=db_fetch_one('SELECT * FROM `clans_q` WHERE `clans`=:c ORDER BY `id` ASC LIMIT 1',['c'=>$clanId]);
}
return $row ?: null;
}
function game_clan_quest_is_week_open(?int $ts=null): bool {
$w=(int)date('w',$ts??time());
return $w!==0 && $w!==6;
}
function game_clan_quest_expire(int $clanId,array &$row): void {
$now=time(); $changed=false;
foreach(game_clan_quest_defs() as $qid=>$def){
$primary=(int)($row['user_'.$qid]??0);
if($primary<=0) continue;
$a=db_fetch_one('SELECT `time` FROM `clan_q_user` WHERE `clans`=:c AND `user`=:u ORDER BY `id` DESC LIMIT 1',['c'=>$clanId,'u'=>$primary]);
if($a && (int)$a['time']>0 && (int)$a['time']<=$now){
db_execute("UPDATE `clans_q` SET `user_$qid`=0,`user_{$qid}_p`=0,`q_$qid`=0 WHERE `clans`=:c",['c'=>$clanId]);
db_execute('DELETE FROM `clan_q_user` WHERE `clans`=:c AND (`user`=:u1 OR `user`=:u2)',['c'=>$clanId,'u1'=>$primary,'u2'=>(int)($row['user_'.$qid.'_p']??0)]);
$row['user_'.$qid]=0; $row['user_'.$qid.'_p']=0; $row['q_'.$qid]=0; $changed=true;
}
$cool=(int)($row[$qid.'_time']??0);
if($cool>0 && $cool<=$now){
db_execute("UPDATE `clans_q` SET `{$qid}_time`=0 WHERE `clans`=:c",['c'=>$clanId]);
$row[$qid.'_time']=0; $changed=true;
}
}
if($changed){ $fresh=game_clan_quest_row($clanId,false); if($fresh)$row=$fresh; }
}
function game_clan_quest_user_busy(array $row,int $uid): bool {
if($uid<=0) return true;
foreach(game_clan_quest_defs() as $qid=>$def){
if((int)($row['user_'.$qid]??0)===$uid || (int)($row['user_'.$qid.'_p']??0)===$uid) return true;
}
return false;
}
function game_clan_quest_start(int $clanId,int $qid,int $uid): array {
$defs=game_clan_quest_defs(); if($clanId<=0||$uid<=0||!isset($defs[$qid])) return [false,'Некорректное задание.'];
$row=game_clan_quest_row($clanId,true); if(!$row) return [false,'Не удалось загрузить задания клана.']; game_clan_quest_expire($clanId,$row);
if((int)($row[$qid.'_time']??0)>time()) return [false,'Это задание ещё на перезарядке.'];
if((int)($row['user_'.$qid]??0)>0) return [false,'Задание уже выполняет другой участник.'];
if(game_clan_quest_user_busy($row,$uid)) return [false,'Одновременно можно выполнять или помогать только в одном клановом задании.'];
db_pdo()->beginTransaction();
try{
db_execute("UPDATE `clans_q` SET `user_$qid`=:u,`user_{$qid}_p`=0,`q_$qid`=0 WHERE `clans`=:c",['u'=>$uid,'c'=>$clanId]);
db_execute('DELETE FROM `clan_q_user` WHERE `clans`=:c AND `user`=:u',['c'=>$clanId,'u'=>$uid]);
db_execute('INSERT INTO `clan_q_user` (`clans`,`user`,`time`) VALUES (:c,:u,:t)',['c'=>$clanId,'u'=>$uid,'t'=>time()+172800]);
db_pdo()->commit();
return [true,'Клановое задание начато.'];
}catch(Throwable $e){ if(db_pdo()->inTransaction())db_pdo()->rollBack(); throw $e; }
}
function game_clan_quest_help(int $clanId,int $qid,int $uid): array {
$defs=game_clan_quest_defs(); if($clanId<=0||$uid<=0||!isset($defs[$qid])) return [false,'Некорректное задание.'];
$row=game_clan_quest_row($clanId,true); if(!$row) return [false,'Не удалось загрузить задания клана.']; game_clan_quest_expire($clanId,$row);
$primary=(int)($row['user_'.$qid]??0);
if($primary<=0) return [false,'Сначала кто-то должен взять это задание.'];
if($primary===$uid) return [false,'Вы уже выполняете это задание.'];
if((int)($row['user_'.$qid.'_p']??0)>0) return [false,'У задания уже есть помощник.'];
if(game_clan_quest_user_busy($row,$uid)) return [false,'Одновременно можно выполнять или помогать только в одном клановом задании.'];
db_execute("UPDATE `clans_q` SET `user_{$qid}_p`=:u WHERE `clans`=:c AND `user_$qid`>0 AND `user_{$qid}_p`=0",['u'=>$uid,'c'=>$clanId]);
db_execute('DELETE FROM `clan_q_user` WHERE `clans`=:c AND `user`=:u',['c'=>$clanId,'u'=>$uid]);
db_execute('INSERT INTO `clan_q_user` (`clans`,`user`,`time`) VALUES (:c,:u,:t)',['c'=>$clanId,'u'=>$uid,'t'=>time()+172800]);
return [true,'Вы присоединились к выполнению задания.'];
}
function game_clan_quest_cancel(int $clanId,int $qid,int $uid): array {
$defs=game_clan_quest_defs(); if(!isset($defs[$qid])) return [false,'Некорректное задание.'];
$row=game_clan_quest_row($clanId,false); if(!$row) return [false,'Задание не найдено.'];
$primary=(int)($row['user_'.$qid]??0); $helper=(int)($row['user_'.$qid.'_p']??0);
if($uid===$primary){
db_execute("UPDATE `clans_q` SET `user_$qid`=0,`user_{$qid}_p`=0,`q_$qid`=0 WHERE `clans`=:c",['c'=>$clanId]);
db_execute('DELETE FROM `clan_q_user` WHERE `clans`=:c AND (`user`=:u1 OR `user`=:u2)',['c'=>$clanId,'u1'=>$primary,'u2'=>$helper]);
return [true,'Клановое задание отменено.'];
}
if($uid===$helper){
db_execute("UPDATE `clans_q` SET `user_{$qid}_p`=0 WHERE `clans`=:c",['c'=>$clanId]);
db_execute('DELETE FROM `clan_q_user` WHERE `clans`=:c AND `user`=:u',['c'=>$clanId,'u'=>$uid]);
return [true,'Вы перестали помогать в задании.'];
}
return [false,'Вы не участвуете в этом задании.'];
}
function game_clan_quest_claim(int $clanId,int $qid,int $uid): array {
$defs=game_clan_quest_defs(); if(!isset($defs[$qid])) return [false,'Некорректное задание.']; $def=$defs[$qid];
$row=game_clan_quest_row($clanId,false); if(!$row) return [false,'Задание не найдено.']; game_clan_quest_expire($clanId,$row);
$primary=(int)($row['user_'.$qid]??0); $helper=(int)($row['user_'.$qid.'_p']??0); $progress=(int)($row['q_'.$qid]??0);
if($primary!==$uid) return [false,'Завершить задание может участник, который его взял.'];
if($progress<(int)$def['goal']) return [false,'Задание ещё не выполнено.'];
$crystal=random_int(1,10); $now=time();
db_pdo()->beginTransaction();
try{
db_execute('UPDATE `users` SET `g`=LEAST(2000000000,`g`+:g),`exp`=LEAST(9000000000000000000,`exp`+:e) WHERE `id`=:u',['g'=>(int)$def['gold'],'e'=>(int)$def['exp'],'u'=>$uid]);
db_execute('UPDATE `clans` SET `plat`=LEAST(2000000000,`plat`+:p) WHERE `id`=:c',['p'=>$crystal,'c'=>$clanId]);
db_execute('UPDATE `clan_memb` SET `plat`=LEAST(2000000000,`plat`+:p) WHERE `clan`=:c AND `user`=:u',['p'=>$crystal,'c'=>$clanId,'u'=>$uid]);
db_execute("UPDATE `clans_q` SET `user_$qid`=0,`user_{$qid}_p`=0,`q_$qid`=0,`{$qid}_time`=:t WHERE `clans`=:c",['t'=>$now+72000,'c'=>$clanId]);
db_execute('DELETE FROM `clan_q_user` WHERE `clans`=:c AND (`user`=:u1 OR `user`=:u2)',['c'=>$clanId,'u1'=>$primary,'u2'=>$helper]);
$text='<a href="/user/'.$uid.'/">'.security_html((string)(db_result(db_query('SELECT `login` FROM `users` WHERE `id`='.$uid.' LIMIT 1'),0)?:'Игрок')).'</a> выполнил клановое задание «'.security_html((string)$def['title']).'» и добыл <img src="/images/icon/crys/diamond.png" alt="*"> '.$crystal.' кристаллов.';
db_execute('INSERT INTO `chat` (`clan`,`user`,`text`,`time`) VALUES (:c,0,:x,:t)',['c'=>$clanId,'x'=>$text,'t'=>$now]);
db_pdo()->commit();
return [true,'Награда: <img src="/images/icon/gold.png" alt="*"> '.n_f((int)$def['gold']).' <img src="/images/icon/exp.png" alt="*"> '.n_f((int)$def['exp']).' <img src="/images/icon/crys/diamond.png" alt="*"> '.$crystal];
}catch(Throwable $e){ if(db_pdo()->inTransaction())db_pdo()->rollBack(); throw $e; }
}
function game_clan_quest_increment(int $clanId,int $qid,int $uid,int $amount=1): bool {
$defs=game_clan_quest_defs(); if($clanId<=0||$uid<=0||$amount<=0||!isset($defs[$qid])) return false;
$goal=(int)$defs[$qid]['goal'];
$sql="UPDATE `clans_q` SET `q_$qid`=LEAST(`q_$qid`+:a,:g) WHERE `clans`=:c AND `{$qid}_time`=0 AND (`user_$qid`=:u1 OR `user_{$qid}_p`=:u2)";
$st=db_prepare($sql,['a'=>$amount,'g'=>$goal,'c'=>$clanId,'u1'=>$uid,'u2'=>$uid]);
$changed=$st->rowCount()>0;
if($changed){
$q=(int)(db_result(db_query("SELECT `q_$qid` FROM `clans_q` WHERE `clans`=".$clanId." LIMIT 1"),0)?:0);
if($q>=$goal && function_exists('game_activity_mark')) game_activity_mark('clan_quests',1);
}
return $changed;
}
function game_clan_quest_completed_count(int $clanId): int {
if($clanId<=0 || !game_clan_quest_is_week_open()) return 0;
$row=game_clan_quest_row($clanId,false); if(!$row) return 0;
$n=0; foreach(game_clan_quest_defs() as $qid=>$def){ if((int)($row['user_'.$qid]??0)>0 && (int)($row['q_'.$qid]??0)>=(int)$def['goal'])$n++; }
return $n;
}
function game_clan_quest_user_completed_count(int $clanId,int $uid): int {
if($clanId<=0||$uid<=0||!game_clan_quest_is_week_open()) return 0;
$row=game_clan_quest_row($clanId,false); if(!$row)return 0; $n=0;
foreach(game_clan_quest_defs() as $qid=>$def){
if((int)($row['q_'.$qid]??0)>=(int)$def['goal'] && ((int)($row['user_'.$qid]??0)===$uid || (int)($row['user_'.$qid.'_p']??0)===$uid)) $n++;
}
return $n;
}