game/_incl_data/crons/DungeonBotLogic.php

449 lines
17 KiB
PHP
Raw Normal View History

2023-08-07 10:52:16 +00:00
<?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);