449 lines
17 KiB
PHP
449 lines
17 KiB
PHP
|
<?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);
|