battles/functions.php
Igor Barkov (iwork) 3502904656 Рефакторинг, очистка, работа над ошибками, связанными с базой, отказ от глобальной переменной $user во многих файлах.
Singleton в некоторых местах вместо решения #42.
Новые шаги для решения #16 и #52.
Closes #42.
Closes #32.
Closes #31.
2022-01-27 01:15:33 +02:00

606 lines
22 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* Copyright (c) 2018.
* Author: Igor Barkov <lopar.4ever@gmail.com>
* Project name: Battles-Game
*/
use Battles\Database\Db;
use Battles\DressedItems;
use Battles\InventoryItem;
use Battles\Travel;
use Battles\User;
use Battles\UserStats;
require_once 'config.php';
if (empty($_SESSION['uid'])) {
header("Location: index.php");
exit;
}
if (User::getInstance()->getBlock()) {
exit('user blocked!');
}
/*
* Проверки на соответствие скрипта и комнаты, которые были натыканы по всем файлам.
*/
$fbattleCheckFiles = [
'c_haos_in.php',
'c_haos.php',
'c_park.php',
'city.php',
'enter_cave.php',
'library.php',
'atk.php',
'podzem_dialog.php',
'post.php',
'shop.php',
'tournament.php',
'vxod.php',
'bank.php',
'canalizaciya,php',
'forest.php',
'main.php',
'repair.php',
'towerstamp.php',
'hell.php',
'ul_clans.php',
'labirint.php',
'akadem.php',
'towerin.php',
'user_anketa.php',
'zayavka.php',
];
//Может просто отовсюду? О_о
if (User::getInstance()->getBattle() && in_array(pathinfo(debug_backtrace()[0]['file'])['basename'], $fbattleCheckFiles)) {
header('location: fbattle.php');
exit;
}
$towerinCheckFiles = ['main.php', 'city.php', 'tower.php'];
if (User::getInstance()->getInTower() && in_array(pathinfo(debug_backtrace()[0]['file'])['basename'], $towerinCheckFiles)) {
header('location: towerin.php');
exit;
}
$roomsCheck = [22, 23, 25, 27, 29, 30, 31, 37, 38, 39, 40, 41, 45, 53, 61, 401, 402, 600, 601, 602, 621, 650, 1051, 1052];
// Если я в одной из этих комнат,
// [И] Имя файла который инклюдит файл с проверкой не совпадает с именем файла локации в которой я нахожусь
// [И] Номер комнаты который я пытаюсь открыть есть в списке проверяемых
if (in_array(User::getInstance()->getRoom(), $roomsCheck)
&& pathinfo(debug_backtrace()[0]['file'])['basename'] != Travel::$roomFileName[User::getInstance()->getRoom()]
&& in_array(array_search(pathinfo(debug_backtrace()[0]['file'])['basename'], Travel::$roomFileName), $roomsCheck)) {
header('location: main.php');
exit;
}
if (!empty($_GET['goto']) && !empty($_GET['tStamp']) && !empty($_GET['vcode']) && $_GET['vcode'] == md5(sha1($_GET['goto'] . $_GET['tStamp']))) {
$query = 'update users u, online o set u.room = ?, o.room = ? where user_id = id and user_id = ?';
Db::getInstance()->execute($query, [$_GET['goto'], $_GET['goto'], User::getInstance()->getId()]);
User::getInstance()->setRoom(intval($_GET['goto']));
}
function createbot($bot, $login = "")
{
$rec = db::c()->query('SELECT `id`, `login`, `maxhp` FROM `users` WHERE `id` = "?s" LIMIT 1', $bot)->fetch_assoc();
if (isset($rec['id'])) {
if ($login) {
$rec['login'] = $login;
}
$botname = $rec['login'];
db::c()->query('INSERT INTO `bots` (`name`, `prototype`, `hp`) VALUES ("?s", "?s", "?s")', $botname, $bot, $rec['maxhp']);
$nid = db::c()->getLastInsertId();
return ["id" => $nid, "login" => $botname];
} else {
return false;
}
}
$var_map = [
'cell_1' => 'Березовая роща', 'cell_2' => 'Березовая просека', 'cell_3' => 'Тёмный угол', 'cell_4' => 'Мрачная опушка',
'cell_5' => 'Тёмное урочище', 'cell_6' => 'Бурелом', 'cell_7' => 'Старая ива', 'cell_8' => 'Разнолесье',
'cell_9' => 'Сосновая тропа', 'cell_10' => 'Забытая дорога', 'cell_11' => 'Новая дорога', 'cell_12' => 'Мщаник',
'cell_13' => 'Ясная поляна', 'cell_14' => 'Заросший тракт', 'cell_15' => 'Смутный ельник', 'cell_16' => 'Сосновый бор',
'cell_17' => 'Тихоход', 'cell_18' => 'Сосновый гай', 'cell_19' => 'Смешаный лес', 'cell_20' => 'Темная поляна',
'cell_21' => 'Осенний угол', 'cell_22' => 'Грибное место', 'cell_23' => 'Опушка', 'cell_24' => 'Рыжий лес',
'cell_25' => 'Полесье',
];
const _BOTSEPARATOR_ = 10000000;
function savecavedata($cavedata, $caveleader, $floor)
{
$f1 = fopen("cavedata/$caveleader-$floor.dat", "wb+");
flock($f1, LOCK_EX);
fwrite($f1, serialize($cavedata));
flock($f1, LOCK_UN);
fclose($f1);
}
function GiveExp($id, $exp)
{
db::c()->query('UPDATE users SET exp = exp + ?i WHERE id = ?i', $exp, $id);
}
/**
* Генератор прогрессбара.
* @param $current - Текущее значение.
* @param $maximum - Максимальное значение.
* @param string $line_color - Цвет полоски прогрессбара.
* @param string $bg_color - Фон прогрессбара.
* @return string
*/
function showProgressBar($current, $maximum, string $line_color = 'limegreen', string $bg_color = 'silver'): string
{
$bar = round($current / $maximum * 100);
return <<<HTML
<div style="width: 100%; height: 16px; background: $bg_color; overflow: hidden; border-radius: 3px;">
<div style="height: 16px; background: $line_color; border-radius: 3px; width: $bar%;"></div>
</div>
<div style="width: 100%; height: 16px; font-size: 14px; text-align: center; margin-top: -16px;">
$current / $maximum
</div>
HTML;
}
/**
* Функция отображает слот для свитков в окне персонажа.
*
* @param $slot
*
* @throws \Krugozor\Database\Mysql\Exception
*/
function echoscroll($slot)
{
$all_magic = 0;
if (User::getInstance()->getBattle()) {
$script = 'fbattle';
$bat = db::c()->query('SELECT `magic` FROM `battle` WHERE `id` = ?i', User::getInstance()->getBattle())->fetch_assoc();
$all_magic = unserialize($bat['magic']);
} else {
$script = 'main';
}
$dress = db::c()->query('SELECT `id`, `magic`, `name`, `img`, `duration`, `maxdur` FROM `inventory` WHERE `id` = ?i', User::getInstance()->$slot)->fetch_assoc();
$need_charge = db::c()->query('SELECT `needcharge` FROM `magic` WHERE `id` = ?i', $dress['magic'])->fetch_assoc();
if ((User::getInstance()->$slot > 0) && ($all_magic[User::getInstance()->getId()] < 1 || empty($need_charge['needcharge']))) {
$row['id'] = User::getInstance()->$slot;
if ($dress['magic']) {
$magic = db::c()->query('SELECT targeted FROM `magic` WHERE `id` = ?i', $dress['magic'])->fetch_assoc();
echo "<a onclick=\"";
if ($magic['targeted'] == 1) {
echo "okno('Введите название предмета', '" . $script . ".php?use={$row['id']}', 'target'); ";
} else
if ($magic['targeted'] == 2) {
echo "findlogin('Введите имя персонажа', '" . $script . ".php?use={$row['id']}', 'target'); ";
} else {
echo "if(confirm('Использовать сейчас?')) { window.location='" . $script . ".php?use=" . $row['id'] . "';}";
}
echo "\"href='#'>";
}
echo <<<ACTIVE_SCROLL
<img class='tooltip' src="i/sh/{$dress['img']}" width='40' title="<b>{$dress['name']}</b><br> Прочность {$dress['duration']} / {$dress['maxdur']} " height='25' alt="Свиток"></a>
ACTIVE_SCROLL;
} elseif ((User::getInstance()->$slot > 0) && ($all_magic[User::getInstance()->getId()] >= 1) && $need_charge['needcharge'] > 0) {
echo <<<INACTIVE_SCROLL
<img src="i/sh/magicclock.gif" width="40" height="25" title='Произведите размен ударами и магия снова станет доступна' alt="Свиток">
INACTIVE_SCROLL;
} else {
echo <<<EMPTY_SLOT
<img class="tooltip" src="i/w13.gif" width="40" height="25" title='<b>Пустой слот магия</b>' alt="Слот для свитка">
EMPTY_SLOT;
}
}
// ссылка на магию
function showhrefmagic($dress)
{
$user = db::c()->query('SELECT `battle` FROM `users` WHERE `id` = ?i', $_SESSION['uid'])->fetch_assoc();
$magic = db::c()->query('SELECT * FROM `magic` WHERE `id` = ?i', $dress['includemagic'])->fetch_assoc();
$r = '';
$script = 'main';
if ($user['battle']) {
$script = 'fbattle';
}
$r .= "<a onclick=\"";
if ($magic['targeted'] == 1) {
$r .= "okno('Введите название предмета', '{$script}.php?use={$dress['id']}', 'target')";
} elseif ($magic['targeted'] == 2) {
$r .= "findlogin('" . $magic['name'] . "', '{$script}.php?use={$dress['id']}', 'target')";
} else {
$r .= "if (confirm('Использовать сейчас?')) window.location='" . $script . ".php?use=" . $dress['id'] . "';";
}
$r .= "\"href='#'>";
$r .= "<img src=\"i/sh/{$dress['img']}\" style=\"filter:shadow(color=red, direction=90, strength=3);\" title=\"" . $dress['name'] . (($dress['text'] != null) ? "<br />На оружии выгравировано '{$dress['text']}'" : "") . "\"><br>";
return $r;
}
function timeOut($ttm)
{
$out = '';
$time_still = $ttm;
$tmp = floor($time_still / 2592000);
$id = 0;
if ($tmp > 0) {
$id++;
if ($id < 3) {
$out .= $tmp . " мес. ";
}
$time_still = $time_still - $tmp * 2592000;
}
$tmp = floor($time_still / 86400);
if ($tmp > 0) {
$id++;
if ($id < 3) {
$out .= $tmp . " дн. ";
}
$time_still = $time_still - $tmp * 86400;
}
$tmp = floor($time_still / 3600);
if ($tmp > 0) {
$id++;
if ($id < 3) {
$out .= $tmp . " ч. ";
}
$time_still = $time_still - $tmp * 3600;
}
$tmp = floor($time_still / 60);
if ($tmp > 0) {
$id++;
if ($id < 3) {
$out .= $tmp . " мин. ";
}
}
if ($out == '') {
if ($time_still < 0) {
$time_still = 0;
}
$out = $time_still . ' сек.';
}
return $out;
}
/**
* @param $time
* @param $vars
* @param $vls
* @param $uid
*
* @return bool
*/
function addActions($time, $vars, $vls, $uid)
{
db::c()->query('LOCK TABLES `actions` WRITE');
$ins = db::c()->query('INSERT INTO `actions` (`uid`,`time`,`city`,`room`,`vars`,`ip`,`vals`) VALUES (?i, ?i, "?s", ?i, "?s", "?s", "?s")', $uid, $time, "capitalcity", 0, $vars, $_SERVER['REMOTE_ADDR'], $vls);
db::c()->query('UNLOCK TABLES');
return $ins;
}
#15
function ref_drop()
{
//сможет держать
function derj($id)
{
$user = db::c()->query('SELECT `id`, `align` FROM `users` WHERE `id` = ?i', $_SESSION['uid'])->fetch_assoc();
$ts = db::c()->query('SELECT `id`, `nalign` FROM `inventory` WHERE `id` = ?i', $id)->fetch_assoc();
$al = '(1 = 1)';
if ($ts['nalign'] == 1.1) {
$al = '(1 = 2)';
}
$dd = db::c()->query('SELECT `i`.`id` FROM `users` AS `u`, `inventory` AS `i`
WHERE
`i`.`needident` = 0 AND
`i`.`id` = ?i AND
`i`.`duration` < `i`.`maxdur` AND
`i`.`owner` = ?i AND
`u`.`sila` >= `i`.`nsila` AND
`u`.`lovk` >= `i`.`nlovk` AND
`u`.`inta` >= `i`.`ninta` AND
`u`.`vinos` >= `i`.`nvinos` AND
`u`.`intel` >= `i`.`nintel` AND
`u`.`mudra` >= `i`.`nmudra` AND
`u`.`level` >= `i`.`nlevel` AND
("?s" OR (?i = `i`.`nalign`) or (`i`.`nalign` = 0)) AND
`u`.`noj` >= `i`.`nnoj` AND
`u`.`topor` >= `i`.`ntopor` AND
`u`.`dubina` >= `i`.`ndubina` AND
`u`.`mec` >= `i`.`nmech` AND
`u`.`mfire` >= `i`.`nfire` AND
`u`.`mwater` >= `i`.`nwater` AND
`u`.`mair` >= `i`.`nair` AND
`u`.`mearth` >= `i`.`nearth` AND
`u`.`mlight` >= `i`.`nlight` AND
`u`.`mgray` >= `i`.`ngray` AND
`u`.`mdark` >= `i`.`ndark` AND
`i`.`setsale` = 0 AND
`u`.`id` = ?i', $id, $user['id'], $al, $user['align'], $user['id']);
return $dd->getNumRows() > 0;
}
$slot = ['sergi', 'kulon', 'weap', 'bron', 'r1', 'r2', 'r3', 'helm', 'perchi', 'shit', 'boots', 'm1', 'm2', 'm3', 'm4', 'm5', 'm6', 'm7', 'm8', 'm9', 'm10'];
$user = db::c()->query('SELECT `sergi`,`kulon`,`weap`,`bron`,`r1`,`r2`,`r3`,`helm`,`perchi`,`shit`,`boots`,`m1`,`m2`,`m3`,`m4`,`m5`,`m6`,`m7`,`m8`,`m9`,`m10` FROM `users` WHERE id = ?i', $_SESSION['uid'])->fetch_assoc();
for ($i = 0; $i <= 20; $i++) {
if ($user[$slot[$i]] && !derj($user[$slot[$i]])) {
$item = new DressedItems($_SESSION['uid']);
$item->undressItem($i + 1);
$user[$slot[$i]] = null;
}
}
}
// использовать магию
function usemagic($id, $target)
{
$user = Db::getInstance()->fetch('select * from users where id = ?', $_SESSION['uid']);
$row = db::c()->query('SELECT * FROM `inventory` WHERE `owner` = ?i AND id = ?i', User::getInstance()->getId(), $id)->fetch_assoc_array();
$bat = db::c()->query('SELECT * FROM `battle` WHERE `id` = ?i', User::getInstance()->getBattle())->fetch_assoc_array();
$all_magic = unserialize($bat['magic']);
$charge = 0;
$magic = db::c()->query('SELECT * FROM `magic` WHERE `id` = ?i', $row['magic'])->fetch_assoc_array();
if ($magic['needcharge'] > 0) {
$charge = $magic['needcharge'];
}
$incmagic = db::c()->query('SELECT * FROM `magic` WHERE `id` = ?i', $row['includemagic'])->fetch_assoc_array();
if ($incmagic['needcharge'] > 0) {
$charge = $incmagic['needcharge'];
}
//Переделать под новую базу
if (($all_magic[User::getInstance()->getId()] < 1 || $charge == 0) &&
($user['sila'] >= $row['nsila'] &&
$user['lovk'] >= $row['nlovk'] &&
$user['inta'] >= $row['ninta'] &&
$user['vinos'] >= $row['nvinos'] &&
$user['intel'] >= $row['nintel'] &&
$user['level'] >= $row['nlevel'] &&
(($user['align'] > 7 && $user['align'] < 8) || ((int)$user['align'] == (int)$row['nalign']) || ($row['nalign'] == 0)) &&
$user['noj'] >= $row['nnoj'] &&
$user['topor'] >= $row['ntopor'] &&
$user['dubina'] >= $row['ndubina'] &&
$user['mec'] >= $row['nmech'] &&
($row['type'] < 13 || $row['type'] == 50) && ($user['mfire'] >= $row['nfire']) &&
$user['mwater'] >= $row['nwater'] &&
$user['mair'] >= $row['nair'] &&
$user['mearth'] >= $row['nearth'] &&
$user['mlight'] >= $row['nlight'] &&
$user['mgray'] >= $row['ngray'] &&
$user['mdark'] >= $row['ndark'] &&
$row['needident'] == 0
) || $row['magic'] == 48 || $row['magic'] == 50) {
if (!$row['magic']) {
$incmagic['name'] = $row['includemagicname'];
$incmagic['cur'] = $row['includemagicdex'];
$incmagic['max'] = $row['includemagicmax'];
if ($incmagic['cur'] <= 0) {
return false;
}
$magic['targeted'] = $incmagic['targeted'];
echo "<span class='error'>";
include("magic/" . $incmagic['file']);
echo "</span>";
} else {
echo "<span class='error'>";
include("magic/" . $magic['file']);
echo "</span>";
}
if ($bat) {
if ($row['maxdur'] <= ($row['duration'] + 1)) {
InventoryItem::destroyItem($row['id']);
} else {
if (!$row['magic']) {
$query = 'update inventory set includemagicdex = includemagicdex - ? where item_id = ?';
} else {
$query = 'update inventory set durability = durability + ? where item_id = ?';
}
Db::getInstance()->execute($query, [$bat, $row['id']]);
}
if (!$charge) {
$charge = 0;
}
//ограничение по кол-ву за ход
if (User::getInstance()->getBattle()) {
$batMagic = Db::getInstance()->fetchColumn('select magic from battle where battle_id = ?', User::getInstance()->getBattle());
}
if (empty($batMagic)) {
$all_magic = [];
} else {
$all_magic = unserialize($batMagic);
}
$all_magic[User::getInstance()->getId()] += $charge;
Db::getInstance()->execute('update battle set magic = ? where battle_id = ?', [serialize($all_magic), User::getInstance()->getBattle()]);
}
}
return false;
}
/* ВАЖНО! (#44)
* addch() и addchp() заменяются на Chat::class->addSYSMessage($message, [optional]$receiver);
* Для addchp() используется второй опциональный ключ.
* Это 150+ вхождений в куче файлов, где надо менять структуру вызова функции из-за их несовместимости.
* Возможно, приоритетом стоит сделать унификацию свитков нападения, которых самих около 20 и которые
* по нескольку раз вызывают эти функции.
*/
function addch($text, $room = 0)
{
if ($room == 0) {
$room = User::getInstance()->getRoom();
}
if ($fp = @fopen("tmp/chat.txt", "a")) { //открытие
flock($fp, LOCK_EX); //БЛОКИРОВКА ФАЙЛА
fputs($fp, ":[" . time() . "]:[!sys!!]:[" . ($text) . "]:[" . $room . "]\r\n"); //работа с файлом
fflush($fp); //ОЧИЩЕНИЕ ФАЙЛОВОГО БУФЕРА И ЗАПИСЬ В ФАЙЛ
flock($fp, LOCK_UN); //СНЯТИЕ БЛОКИРОВКИ
fclose($fp); //закрытие
}
}
function addchp($text, $who, $room = 0)
{
if ($room == 0) {
$room = User::getInstance()->getRoom();
}
$fp = fopen("tmp/chat.txt", "a"); //открытие
flock($fp, LOCK_EX); //БЛОКИРОВКА ФАЙЛА
fputs($fp, ":[" . time() . "]:[{$who}]:[" . ($text) . "]:[" . $room . "]\r\n"); //работа с файлом
fflush($fp); //ОЧИЩЕНИЕ ФАЙЛОВОГО БУФЕРА И ЗАПИСЬ В ФАЙЛ
flock($fp, LOCK_UN); //СНЯТИЕ БЛОКИРОВКИ
fclose($fp); //закрытие
}
function err($t)
{
echo '<span class="error">' . $t . '</span>';
}
/**
* @param int $userId
* @param string $text
*
*/
function telegraph(int $userId, string $text)
{
if (Db::getInstance()->ofetch('SELECT 1 FROM users WHERE id = ?', $userId)) {
Db::getInstance()->execute('INSERT INTO chat (user_id,receiver_id,msg,type) VALUES (-1,?,?,?)', [$userId, $text, 'sms']);
}
}
function SolveExp($at_id, $def_id, $damage): float
{
$mods = [
'bloodb' => 1.2,
'btl_1' => 1,
'btl_2' => 0.5,
'btl_3' => 0.05,
];
$baseexp = [
"0" => "2",
"1" => "5",
"2" => "10",
"3" => "15",
"4" => "30",
"5" => "60",
"6" => "90",
"7" => "115",
"8" => "300",
"9" => "400",
"10" => "500",
"11" => "600",
"12" => "700",
"13" => "800",
"14" => "900",
"15" => "1000",
"16" => "1100",
"17" => "1200",
"18" => "1300",
"19" => "1400",
"20" => "1500",
"21" => "1600",
];
$expmf = 0;
$bot_active = false;
$bot_def = false;
if ($at_id > _BOTSEPARATOR_) {
$at_id = Db::getInstance()->fetchColumn('select prototype from bots where bot_id = ?', $at_id);
$bot_active = true;
}
$query = 'select greatest(1, sum(price)) as allprice from users left join inventory on users.id = inventory.owner_id where id = ?';
$atAllPrice = Db::getInstance()->fetchColumn($query, $at_id);
$defAllPrice = Db::getInstance()->fetchColumn($query, $def_id);
$atInfo = new UserStats($at_id);
$defInfo = new UserStats($def_id);
$table_name = $at_id > _BOTSEPARATOR_ ? 'bots' : 'users';
$bt = Db::getInstance()->ofetch('select blood, type, t1, t2 from battle where battle_id = (select battle from ? where id = ?)', [$table_name, $at_id]);
if ($def_id > _BOTSEPARATOR_) {
$def_id = Db::getInstance()->fetchColumn('select prototype from bots where bot_id = ?', $def_id);
$bot_def = true;
}
if ($bt->blood) {
$expmf = $mods['bloodb'];
}
$filebtl = '/tmp/' . $at_id . '.btl';
if ($bt->type == 1 && file_exists($filebtl)) {
$btfl = fopen($filebtl, 'r');
$contents = fread($btfl, filesize($filebtl));
fclose($btfl);
$cnt = substr_count($contents, $def_id);
$exmod = 1;
if ($cnt <= 1) {
$exmod = $mods['btl_1'];
} elseif ($cnt == 2) {
$exmod = $mods['btl_2'];
} elseif ($cnt > 2) {
$exmod = $mods['btl_3'];
}
$expmf = $expmf * $exmod;
}
$standart = [
"0" => 1,
"1" => 1,
"2" => 15,
"3" => 111,
"4" => 265,
"5" => 526,
"6" => 882,
"7" => 919,
"8" => 919,
"9" => 919,
"10" => 919,
"11" => 919,
"12" => 919,
"13" => 919,
"14" => 919,
"15" => 919,
"16" => 919,
"17" => 919,
"18" => 919,
"19" => 919,
"20" => 919,
"21" => 919,
"22" => 919,
"23" => 919,
"24" => 919,
"25" => 919
];
$mfit = ($atAllPrice / ($standart[$atInfo->getLevel()] / 3));
if ($mfit < 0.8) {
$mfit = 0.8;
}
if ($mfit > 1.5) {
$mfit = 1.5;
}
$pls = count(explode(";", $bt->t1)) + count(explode(";", $bt->t2));
if ($pls > 2) {
$mfbot = $bot_active ? 0.3 : 1;
$mfbot2 = $bot_def ? 0.7 : 1;
} else {
$mfbot = 1;
$mfbot2 = 1;
}
if ($expmf == 0) {
$expmf = 1;
}
return round((($baseexp[$defInfo->getLevel()]) * ($defAllPrice / (($atAllPrice + $defAllPrice) / 2)) * ($damage / $defInfo->getMaxHealth()) * $expmf * $mfit * $mfbot * $mfbot2) / 3);
}