game/_incl_data/crons/DungeonBotLogic.php
2023-08-08 17:42:05 +03:00

449 lines
17 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
namespace crons;
class DungeonBotLogic
{
/**
* Перемещение ботов по пещере и напедение, когда игрок рядом.
* @return void
*/
public static function start()
{
# Выбираем всех ботов.
# В выборку включено: Позиция бота, Направление куда он может идти, Существует ли рядом Игрок, его координаты и в поединке ли он.
$sql = "
select
dnow.id as this_dn,
dnow.id2 as dn_id,
dbots.id2,
dbots.id_bot,
tb.login as login,
dbots.colvo,
dbots.go_bot,
dbots.x,
dbots.y,
dbots.s,
dbots.atack,
tb.agressor,
dmap.go_1 as goRight,
dmap.go_2 as goLeft,
dmap.go_3 as goTop,
dmap.go_4 as goBottom,
dmap.no_bot as noBot,
uinfo.id as userId,
uinfo.login as userLogin,
ustats.hpNow as userHP,
ustats.x as userPosX,
ustats.y as userPosY,
uinfo.battle as userBattle
from dungeon_now as dnow
left join dungeon_bots as dbots on dbots.dn = dnow.id
left join dungeon_map as dmap on (dmap.x = dbots.x and dmap.y = dbots.y and dmap.id_dng = dnow.id2)
left join test_bot as tb on dbots.id_bot = tb.id
left join stats as ustats on ((ustats.x+1 >= dbots.x and ustats.x-1 <= dbots.x) and (ustats.y+1 >= dbots.y and ustats.y-1 <= dbots.y) and ustats.dnow = dnow.id )
left join users as uinfo on ( ustats.id = uinfo.id )
where
dnow.time_finish = 0 and
dbots.atack = 0 and
dbots.delete = 0 and
dbots.for_dn = 0 and
((dbots.go_bot between unix_timestamp() - 32400 and unix_timestamp()) or dbots.go_bot = 1) and dbots.inBattle = 0
group by dbots.id2, dbots.go_bot
order by dbots.go_bot";
$botMovements = Db::getRows($sql);
foreach ($botMovements as $bot) {
$sTo = $bot['s'];
$xFrom = $bot['x']; # текущие координаты X
$yFrom = $bot['y']; # текущие координаты Y
$return = self::moveBots($bot['s'], $bot);
$xTo = $bot['x'] + $return['x'];
$yTo = $bot['y'] + $return['y'];
# Проверяем, имеется ли переход по клетке.
$inSight = 0;
if (isset($bot['id2'])) {
if ($xFrom == $xTo && $yFrom == $yTo) { # Если остаемся на месте.
$inSight = 1;
} elseif (isset($bot['goRight']) && $xFrom == $xTo - 1 && $bot['goRight'] == 1) { //право
$sTo = 4;
$inSight = 1;
} elseif (isset($bot['goLeft']) && $xFrom == $xTo + 1 && $bot['goLeft'] == 1) { //лево
$sTo = 2;
$inSight = 1;
} elseif (isset($bot['goTop']) && $yFrom == $yTo - 1 && $bot['goTop'] == 1) { //верх
$sTo = 1;
$inSight = 1;
} elseif (isset($bot['goBottom']) && $yFrom == $yTo + 1 && $bot['goBottom'] == 1) { //низ
$sTo = 3;
$inSight = 1;
}
}
if (
isset($bot['userId'], $bot['userPosY'], $bot['userPosX']) &&
$bot['userId'] != '' &&
$bot['agressor'] == 1 &&
(
($bot['userPosY'] == $bot['y'] + 1 && $bot['userPosX'] == $bot['x']) ||
($bot['userPosY'] == $bot['y'] - 1 && $bot['userPosX'] == $bot['x']) ||
($bot['userPosY'] == $bot['y'] && $bot['userPosX'] == $bot['x'] - 1) ||
($bot['userPosY'] == $bot['y'] && $bot['userPosX'] == $bot['x'] + 1)
)
) {
$bot['userPosY'] = $yFrom;
$bot['userPosX'] = $xFrom;
Db::sql('update stats set x = ?, y = ? where id = ?', [$xFrom, $yFrom, $bot['userId']]);
self::botAttack($bot, $bot);
} elseif (
isset($bot['userId'], $bot['userPosY'], $bot['userPosX']) &&
$bot['userId'] != '' &&
$inSight == 1 &&
$yTo == $bot['userPosY'] &&
$xTo == $bot['userPosX'] &&
$bot['atack'] == 1
) {
self::botAttack($bot, $bot);
} elseif ($inSight == 1) { // Передвижение ботов.
$bot['go_bot'] = time() + rand(7, 15);
Db::sql('update dungeon_bots set x = ?, y = ?, s = ?, go_bot = ? where id2 = ?', [$xTo, $yTo, $sTo, $bot['go_bot'], $bot['id2']]);
}
}
}
private static function moveBots($direction, $b): array
{
$toGoX = 0;
$toGoY = 0;
if (isset($b['noBot']) && $b['noBot'] != '0000') {
if ($b['noBot'][0] != '0') {
$b['goTop'] = 0;
}
if ($b['noBot'][1] != '0') {
$b['goLeft'] = 0;
}
if ($b['noBot'][2] != '0') {
$b['goBottom'] = 0;
}
if ($b['noBot'][3] != '0') {
$b['goRight'] = 0;
}
}
$go = [
1 => ['d' => $b['goTop'], 'go1' => $b['goLeft'], 'go2' => (int)$b['goRight'], 'x' => (int)$b['x'], 'y' => (int)$b['y'], 's' => (int)$b['s']],
2 => ['d' => $b['goLeft'], 'go1' => (int)$b['goBottom'], 'go2' => $b['goTop'], 'x' => (int)$b['x'], 'y' => (int)$b['y'], 's' => (int)$b['s']],
3 => ['d' => (int)$b['goBottom'], 'go1' => (int)$b['goRight'], 'go2' => $b['goLeft'], 'x' => (int)$b['x'], 'y' => (int)$b['y'], 's' => (int)$b['s']],
4 => ['d' => (int)$b['goRight'], 'go1' => $b['goTop'], 'go2' => (int)$b['goBottom'], 'x' => (int)$b['x'], 'y' => (int)$b['y'], 's' => (int)$b['s']],
];
$dir = [
1 => ['moveForward' => ['x' => '0', 'y' => '1'], 'moveBack' => ['x' => '0', 'y' => '-1'], 'moveGo1' => ['x' => '-1', 'y' => '0'], 'moveGo2' => ['x' => '1', 'y' => '0']],
2 => ['moveForward' => ['x' => '-1', 'y' => '0'], 'moveBack' => ['x' => '1', 'y' => '0'], 'moveGo1' => ['x' => '0', 'y' => '-1'], 'moveGo2' => ['x' => '0', 'y' => '1']],
3 => ['moveForward' => ['x' => '0', 'y' => '-1'], 'moveBack' => ['x' => '0', 'y' => '1'], 'moveGo1' => ['x' => '1', 'y' => '0'], 'moveGo2' => ['x' => '-1', 'y' => '0']],
4 => ['moveForward' => ['x' => '1', 'y' => '0'], 'moveBack' => ['x' => '-1', 'y' => '0'], 'moveGo1' => ['x' => '0', 'y' => '1'], 'moveGo2' => ['x' => '0', 'y' => '-1']],
];
$go = $go[$direction];
$dir = $dir[$direction];
if ($go['d'] == 1) {
$toGoY = $dir['moveForward']['y'];
$toGoX = $dir['moveForward']['x'];
if (rand(1, 100) > 66) {
if ($go['go1'] == 1 && $go['go2'] == 0) {
$toGoY = $dir['moveGo1']['y'];
$toGoX = $dir['moveGo1']['x'];
} elseif ($go['go1'] == 0 && $go['go2'] == 1) {
$toGoY = $dir['moveGo2']['y'];
$toGoX = $dir['moveGo2']['x'];
} elseif ($go['go1'] == 1 && $go['go2'] == 1) {
$a = rand(1, 2);
$toGoY = $dir['moveGo' . $a]['y'];
$toGoX = $dir['moveGo' . $a]['x'];
}
} elseif (rand(1, 100) > 96) {
$toGoY = $dir['moveBack']['y'];
$toGoX = $dir['moveBack']['x'];
}
} elseif ($go['d'] == 0) {
if ($go['go1'] == 1 && $go['go2'] == 1) {
if (rand(0, 1) == 1) {
$toGoY = $dir['moveGo1']['y'];
$toGoX = $dir['moveGo1']['x'];
} else {
$toGoY = $dir['moveGo2']['y'];
$toGoX = $dir['moveGo2']['x'];
}
} elseif ($go['go1'] == 1 && $go['go2'] == 0) {
$toGoY = $dir['moveGo1']['y'];
$toGoX = $dir['moveGo1']['x'];
} elseif ($go['go1'] == 0 && $go['go2'] == 1) {
$toGoY = $dir['moveGo2']['y'];
$toGoX = $dir['moveGo2']['x'];
} elseif ($go['go1'] == 0 && $go['go2'] == 0) {
$toGoY = $dir['moveBack']['y'];
$toGoX = $dir['moveBack']['x'];
}
}
return ['x' => (int)$toGoX, 'y' => (int)$toGoY];
}
/**
* Совершаем действие -> Нападение на игрока.
* @param array $bot
* @param array $user
* @return void
*/
private static function botAttack(array $bot, array $user)
{
if (Db::getValue('select count(*) from battle where id = ? and team_win = -1', [$user['userBattle']]) > 0) {
self::joinBattle($bot, $user['id'], $user['userBattle']);
} else { //Создаем поединок
$sql = 'insert into battle (dungeon, dn_id, x, y, city, time_start, type) values (?,?,?,?,?,unix_timestamp(),0)';
$args = [
$bot['dn_id'],
$bot['this_dn'],
$bot['x'],
$bot['y'],
$bot['userCity'],
];
Db::sql($sql, $args);
$battleId = Db::lastInsertId();
if ($battleId > 0) {
self::addBots($bot, $user['userId'], $battleId);
}
}
}
/**
* Вмешиваемся в поединок.
* @param array $bot
* @param int $userid
* @param int $battleid
* @return void
*/
private static function joinBattle(array $bot, int $userid, int $battleid)
{
$j = 0;
$jui = 1;
$loginsBot = [];
$loginsBotText = [];
$loginsBotVars = ['time1=' . time()];
$loginsBotInBattle = Db::getRows('select substring_index(login, ?, 1) as login2, count(login) as count, login from battle_users where battle = ? and team = 2 group by login2',
[' (', $battleid]);
foreach ($loginsBotInBattle as $row) {
$loginsBot[$row['login2']] = (int)$row['count'];
}
Db::sql('update dungeon_bots set inBattle = ? where id2 = ?', [$battleid, $bot['id2']]);
while ($jui <= $bot['colvo']) {
$k = self::botAddBattle($bot, $loginsBot);
$loginsBot = $k['logins_bot'];
$loginsBotText[] = ' <strong>' . $k['login'] . '</strong>';
if ($k) {
self::queryUsersSetBattle($battleid, $k['id']);
self::queryStatsSetTeam(2, $k['id']);
$j++;
}
$jui++;
}
if ($j > 0) {
$loginsBotText = '{tm1} В поединок вмешались: ' . implode(', ', $loginsBotText) . '.';
$loginsBotVars = implode('||', $loginsBotVars);
$battleLogTurnId = Db::getValue('select id_hod from battle_logs where battle = ? order by id_hod desc limit 1', [$battleid]);
if ($battleLogTurnId > 0) {
Db::sql('insert into battle_logs (time, battle, id_hod, text, vars, zona1, zonb1, zona2, zonb2, type) values (unix_timestamp(), ?,?,?,?,?,?,?,?,1)',
[$battleid, $battleLogTurnId + 1, $loginsBotText, $loginsBotVars, '', '', '', '']);
}
self::queryUsersSetBattle($battleid, $userid);
self::queryStatsSetTeam(1, $userid);
}
}
/**
* Совершаем нападение -> Добавляем Ботов в поединок
* @param array $bot
* @param array $loginsBot
* @return false|array
*/
private static function botAddBattle(array $bot, array $loginsBot)
{
$addBot = Db::getRow('select
login,
if(time_reg = 100, unix_timestamp(), time_reg) as time_reg,
align,
level,
name,
sex,
obraz,
stats,
upLevel,
itemsUse
from test_bot where id = ?', [$bot['id_bot']]);
if (!$addBot) {
return false;
}
if (isset($loginsBot[$addBot['login']])) {
$loginsBot[$addBot['login']]++;
$addBot['login'] = $addBot['login'] . ' (' . $loginsBot[$addBot['login']] . ')';
} else {
$loginsBot[$addBot['login']] = 1;
}
$sql = 'insert into users (align, login, level, pass, city, cityreg, name, sex, timereg, obraz, bot_id) values (?,?,?,?,?,?,?,?,?,?,?)';
$args = [
$addBot['align'],
$addBot['login'],
$addBot['level'],
password_hash($addBot['login'] . mt_rand(10, 99), PASSWORD_DEFAULT),
'Городские трущобы',
'Городские трущобы',
$addBot['name'],
$addBot['sex'],
$addBot['time_reg'],
$addBot['obraz'],
$bot['id_bot'],
];
Db::sql($sql, $args);
# Если бот успешно создан.
$botid = Db::lastInsertId();
Db::sql('insert into stats (id, stats, hpNow, upLevel, bot) values (?,?,1000000,?,1)', [$botid, $addBot['stats'], $addBot['upLevel']]);
//Добавляем значения не из базы.
$addBot['id'] = $botid;
$addBot['logins_bot'] = $loginsBot;
//Выдаем предметы
self::botWearItems(explode(',', $addBot['itemsUse']), $botid);
return $addBot;
}
/**
* Одеваем предметы в слоты бота.
* @param array $items
* @param int $botid
* @return void
*/
private static function botWearItems(array $items, int $botid)
{
$w3b = 0;
foreach ($items as $item) {
$idiu = self::botAddItem($item, $botid);
(int)$islot = Db::getValue('select inslot from items_main where id = ?', [$item]);
if (empty($islot)) {
$islot = 2000;
} else {
if ($islot === 3) {
if ($w3b === 1) {
$islot = 14;
} else {
$w3b = 1;
}
}
}
if (isset($idiu, $islot)) {
Db::sql('update items_users set inOdet = ? where id = ?', [$islot, $idiu]);
}
}
}
/**
* Выдаем предметы Боту.
* @param $itemId
* @param $botUid
* @return int
*/
private static function botAddItem($itemId, $botUid): int
{
$item = Db::getRow('select overTypei, data, iznosMAXi, magic_inci from items_main left join items_main_data on items_id = items_main.id where items_main.id = ?', [$itemId]);
if (!$item) {
return 0;
}
$sql = 'insert into items_users (overType, item_id, uid, data, iznosMAX, magic_inc, lastUPD, time_create) values (?,?,?,?,?,?,unix_timestamp(),unix_timestamp())';
$args = [
$item['overTypei'],
$itemId,
$botUid,
$item['data'],
$item['iznosMAXi'],
$item['magic_inci'],
];
Db::sql($sql, $args);
return (int)Db::lastInsertId();
}
private static function queryUsersSetBattle(int $battleId, int $userId): void
{
Db::sql('update users set battle = ? where id = ?', [$battleId, $userId]);
}
private static function queryStatsSetTeam(int $team, int $id)
{
if (!in_array($team, [1, 2])) {
return;
}
Db::sql('update stats set team = ? where id = ?', [$team, $id]);
}
/**
* Добавляем ботов.
* @param array $bot
* @param int $userid
* @param int $battleid
* @return void
*/
private static function addBots(array $bot, int $userid, int $battleid)
{
$j = 0;
$jui = 1;
$loginsBot = [];
Db::sql('update dungeon_bots set inBattle = ? where id2 = ?', [$battleid, $bot['id2']]);
while ($jui <= $bot['colvo']) {
$k = self::botAddBattle($bot, $loginsBot);
$loginsBot = $k['logins_bot'];
if ($k) {
self::queryUsersSetBattle($battleid, $k['id']);
self::queryStatsSetTeam(2, $k['id']);
$j++;
}
$jui++;
}
if ($j > 0) {
self::queryUsersSetBattle($battleid, $userid);
self::queryStatsSetTeam(1, $userid);
}
}
}
/**
* Запуск раз в миниту
*/
use Core\Db;
require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . 'autoload.php';
# Страница создана 0.0000
$mtime = explode(" ", microtime());
$tstart = $mtime[1] + $mtime[0];
# Запускаем выполнение процесса.
DungeonBotLogic::start();
$mtime = explode(" ", microtime());
$mtime = $mtime[1] + $mtime[0];
$totaltime = ($mtime - $tstart);
printf("Страница сгенерирована за %f секунд !", $totaltime);