diff --git a/classes/Battles/Arena.php b/classes/Battles/Arena.php index 6d441fb..c3b317b 100644 --- a/classes/Battles/Arena.php +++ b/classes/Battles/Arena.php @@ -1,169 +1,117 @@ createDb($dbname); + if ( + $this->isOnArena() && + $this->hasNoPendingFights() && + $this->hasNoActiveFights() && + in_array($startTime, [1,3,5,10]) + ) { + $query1 = 'insert into fights_pending (fight_id, start_time, members_limit, groups_limit) VALUES (?,?,?,?)'; + $query2 = 'insert into fights_pending_users (fight_id, user_id, team_id) values (?,?,?)'; + $startTime = strtotime("+{$startTime}minutes"); + $uid = User::getInstance()->getId(); + //последовательность важна! + Db::getInstance()->execute($query1, [$uid, $startTime, $membersLimit, $groupsLimit]); + Db::getInstance()->execute($query2, [$uid, $uid, 1]); } } - private function createDb($dbname) + function join(int $fight_id, int $team_id) { - $this->db = new SQLite3($dbname); - $this->db->query(self::DB_TEMPLATE); - } - - // array type: [[uid1,teamid1], [uid2,teamid2], ..., [uid_N,teamid_N]]. - public function Init(array $fighters) - { - $init_db_query = 'create table if not exists fighters ( - uid integer not null, - strength integer not null, - dexterity integer not null, - intuition integer not null, - endurance integer not null, - intelligence integer not null, - wisdom integer not null, - accuracy integer not null, - evasion integer not null, - criticals integer not null, - health integer not null, - max_health integer not null, - mana integer not null, - max_mana integer not null, - melee_min integer not null, - melee_max integer not null, - teamid integer not null, - rowid integer not null, - turn_timeout integer)'; - $init_table_query = 'insert into fighters ( - uid, - strength, dexterity, intuition, endurance, intelligence, wisdom, - accuracy, evasion, criticals, - health, max_health, mana, max_mana, melee_min, melee_max, - teamid, rowid) - values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'; - $stmt = $this->db->prepare($init_table_query); - foreach ($fighters as [$uid, $team]) { - $fighter = new UserStats($uid); - $stats = $fighter->getFullStats(); - $stmt->bindValue(1, $fighter->getId()); - $stmt->bindValue(2, $stats->strength); - $stmt->bindValue(3, $stats->dexterity); - $stmt->bindValue(4, $stats->intuition); - $stmt->bindValue(5, $stats->endurance); - $stmt->bindValue(6, $stats->intelligence); - $stmt->bindValue(7, $stats->wisdom); - $stmt->bindValue(8, $stats->accuracy); - $stmt->bindValue(9, $stats->evasion); - $stmt->bindValue(10, $stats->criticals); - $stmt->bindValue(11, $fighter->getHealth()); - $stmt->bindValue(12, $fighter->getMaxHealth()); - $stmt->bindValue(13, $fighter->getMana()); - $stmt->bindValue(14, $fighter->getMaxMana()); - $stmt->bindValue(15, $stats->min_physical_damage); - $stmt->bindValue(16, $stats->min_physical_damage); - $stmt->bindValue(17, $team); - $stmt->bindValue(18, 1); - $stmt->execute(); + $this->fight_id = $fight_id; + $this->team_id = $team_id; + if ( + $this->hasNoClanEnemies() && + $this->hasFreeSpace() && + $this->isOnArena() && + $this->hasNoPendingFights() && + $this->hasNoActiveFights() + ) { + $query = 'insert into fights_pending_users (fight_id, user_id, team_id) values (?,?,?)'; + Db::getInstance()->execute($query, [$fight_id, User::getInstance()->getId(), $team_id]); } } - public function playerTurn(int $action, int $uid): void + function leave() { - // Перед ходом проверить, а жив ли ты вообще? - if (empty($this->turn_timeout)) { - $this->turn_timeout = $this->db->querySingle('select turn_timeout from fighters where uid = ' . $uid); + // чтобы не вылететь из заявки в момент начала поединка + if ( + $this->hasNoActiveFights() && + !$this->isFightStarter() + ) { + Db::getInstance()->execute('delete from fights_pending_users where user_id = ?', User::getInstance()->getId()); } - $now = date('U'); + } - /* select from last_turn_time and look at $now_plus_3_minutes - if ok, continue, if no, do nothing */ - if ($now > $this->turn_timeout && !in_array($action, [self::MELEE_ATTACK, self::RANGED_ATTACK, self::USE_MAGIC, self::MOVE, self::PASS, self::FLEE])) { - $action = self::PASS; - $stmt_update_timer = $this->db->prepare('update fighters set last_turn_time = ? where uid = ?'); - $stmt_update_timer->bindValue(1, date('U', strtotime('+3 minute'))); - $stmt_update_timer->bindValue(2, $uid); - } + function getPendingList(): object + { + return new \stdClass(); + /** !!PLACEHOLDER!! */ + } - if ($action === self::MELEE_ATTACK) { - //Выполнимо только с клетки 1, только по вражеской клетке 1. - //Выполнимо по клетке 2, если клетка 1 пуста _у всех сторон_; - //Выполнимо по клетке 3, если клетка 2 пуста _у всех сторон_; - //Стоя на клетке 2 при пустой клетке 1 - атака невозможна! - echo 'Melee!'; - } + public static function fight(): self + { + return new self(); + } - if ($action === self::RANGED_ATTACK) { - //С клетки 1 атака на вражеские клетки 1 и 2; - //С клетки 2 атака на свою клетку 1 и вражескую клетку 1; - //С клетки 2 атака на вражескую 2, только если пустая клетка 1, либо нет клеток 1 _ни у одной из сторон_. - echo 'Ranged!'; + // проверка на соклана + private function hasNoClanEnemies(): bool + { + $query = 'select user_id from fights_pending_users where fight_id = ? and team_id = ?'; + $enemies = Db::getInstance()->ofetchAll($query, [$this->fight_id, $this->team_id]); + foreach ($enemies as $enemy) { + if (User::getInstance()->getClan() && User::getInstance()->getClan() === User::getInstance($enemy->user_id)->getClan()) { + return false; + } } + return true; + } - if ($action === self::USE_MAGIC) { - //Достаёт кого угодно откуда угодно в любых обстоятельствах. - //ОЧЕНЬ внимательно проверять цель. Случайный хил трупа вызовёт апокалипсис в логике. - echo '!MAGIC!'; - } + // проверка на переполнение + private function hasFreeSpace(): bool + { + $query = 'select members_limit, groups_limit from fights_pending where fight_id = ?'; + $query2 = 'select count(*) from fights_pending_users where fight_id = ? and team_id = ?'; + $limits = Db::getInstance()->ofetch($query, $this->fight_id); + $currentUsers = Db::getInstance()->fetchColumn($query2, [$this->fight_id, $this->team_id]); + return $limits->members_limit > $currentUsers && $limits->groups_limit >= $this->team_id; + } - if ($action === self::MOVE) { - //клетка 1 - ближний ряд, только шаг назад - //клетка 2 - средний ряд, вперёд или назад - //клетка 3 - тыл, только вперёд - //В момент хода при соблюдении условий удара может прилететь неблокируемая атака на расстоянии. - //Перемещение - это ручной гарантированный уворот от всех летящих физических атак. - //Перемещение на пустующую клетку 1 с клетки 2 - это ручной гарантированный уворот всех стоящих на клетке 2 от всех летящих немагических атак по всей клетке. - echo 'I have legs!!'; - } - if ($action === self::FLEE) { - //побег из боя, только с клетки 3. - echo 'Help me, mommy!'; - } - if ($action === self::PASS) { - //Пропуск хода. - echo 'I pass this turn.'; - } + // проверка на нахождение в комнате (1 = арена) + private function isOnArena(): bool + { + return User::getInstance()->getRoom() === 1; + } - // ПИСАТЬ РЕЗУЛЬТАТ ХОДА ТОЛЬКО ПОСЛЕ ПОВТОРНОЙ ПРОВЕРКИ НА НАЛИЧИЕ ПРОТИВНИКА - ОН МОГ УСПЕТЬ ОТОЙТИ! - // !!ИЛИ УМЕРЕТЬ!! - $stmt_update_timer->execute(); + // проверка на нахождение в другой заявке + public function hasNoPendingFights(): bool + { + $query = 'select count(*) from fights_pending_users where user_id = ?'; + return Db::getInstance()->fetchColumn($query, User::getInstance()->getId()) > 0; + } + + // проверка на нахождение в поединке + public function hasNoActiveFights(): bool + { + $query = 'select count(*) from fighters where user_id = ?'; + return Db::getInstance()->fetchColumn($query, User::getInstance()->getId()) > 0; + } + + // проверка на создателя поединка + private function isFightStarter(): bool + { + $query = 'select count(*) from fights_pending_users where user_id = fight_id and user_id = ?'; + return Db::getInstance()->fetchColumn($query, User::getInstance()->getId()) > 0; } } \ No newline at end of file diff --git a/classes/Battles/Fight.php b/classes/Battles/Fight.php new file mode 100644 index 0000000..45d7bb8 --- /dev/null +++ b/classes/Battles/Fight.php @@ -0,0 +1,142 @@ +timer->format('U'); + $query = 'insert into fighters ( + user_id, + strength, + dexterity, + intuition, + endurance, + intelligence, + wisdom, + accuracy, + evasion, + criticals, + health, + max_health, + mana, + max_mana, + melee_min, + melee_max, + battle_id, + team_id, + row_id, + turn_timeout + ) values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)'; + $i = 1; + $mergedOptions = []; + foreach ($fighters as $fighter) { + $statsObj = new UserStats($fighter->user_id); + $stats = $statsObj->getFullStats(); + $options[$i] = [ + $fighter->user_id, + $stats->strength, + $stats->dexterity, + $stats->intuition, + $stats->endurance, + $stats->intelligence, + $stats->wisdom, + $stats->accuracy, + $stats->evasion, + $stats->criticals, + $statsObj->getHealth(), + $statsObj->getMaxHealth(), + $statsObj->getMana(), + $statsObj->getMaxMana(), + $stats->min_physical_damage, + $stats->max_physical_damage, + $fighter->fight_id, + $fighter->team_id, + $defaultRow, + $defaultTimer, + ]; + if ($i > 1) { + $query .= ', (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)'; + $mergedOptions = array_merge_recursive($mergedOptions, $options[$i]); + } + $i++; + } + Db::getInstance()->execute($query, $mergedOptions); + } + + public function playerTurn(int $action, int $uid): void + { + // Перед ходом проверить, а жив ли ты вообще? + if (empty($this->turn_timeout)) { + $this->turn_timeout = $this->db->querySingle('select turn_timeout from fighters where uid = ' . $uid); + } + $now = date('U'); + + /* select from last_turn_time and look at $now_plus_3_minutes - if ok, continue, if no, do nothing */ + if ($now > $this->turn_timeout && !in_array($action, [self::MELEE_ATTACK, self::RANGED_ATTACK, self::USE_MAGIC, self::MOVE, self::PASS, self::FLEE])) { + $action = self::PASS; + $stmt_update_timer = $this->db->prepare('update fighters set last_turn_time = ? where uid = ?'); + $stmt_update_timer->bindValue(1, date('U', strtotime('+3 minute'))); + $stmt_update_timer->bindValue(2, $uid); + } + + if ($action === self::MELEE_ATTACK) { + //Выполнимо только с клетки 1, только по вражеской клетке 1. + //Выполнимо по клетке 2, если клетка 1 пуста _у всех сторон_; + //Выполнимо по клетке 3, если клетка 2 пуста _у всех сторон_; + //Стоя на клетке 2 при пустой клетке 1 - атака невозможна! + echo 'Melee!'; + } + + if ($action === self::RANGED_ATTACK) { + //С клетки 1 атака на вражеские клетки 1 и 2; + //С клетки 2 атака на свою клетку 1 и вражескую клетку 1; + //С клетки 2 атака на вражескую 2, только если пустая клетка 1, либо нет клеток 1 _ни у одной из сторон_. + echo 'Ranged!'; + } + + if ($action === self::USE_MAGIC) { + //Достаёт кого угодно откуда угодно в любых обстоятельствах. + //ОЧЕНЬ внимательно проверять цель. Случайный хил трупа вызовёт апокалипсис в логике. + echo '!MAGIC!'; + } + + if ($action === self::MOVE) { + //клетка 1 - ближний ряд, только шаг назад + //клетка 2 - средний ряд, вперёд или назад + //клетка 3 - тыл, только вперёд + //В момент хода при соблюдении условий удара может прилететь неблокируемая атака на расстоянии. + //Перемещение - это ручной гарантированный уворот от всех летящих физических атак. + //Перемещение на пустующую клетку 1 с клетки 2 - это ручной гарантированный уворот всех стоящих на клетке 2 от всех летящих немагических атак по всей клетке. + echo 'I have legs!!'; + } + if ($action === self::FLEE) { + //побег из боя, только с клетки 3. + echo 'Help me, mommy!'; + } + if ($action === self::PASS) { + //Пропуск хода. + echo 'I pass this turn.'; + } + + // ПИСАТЬ РЕЗУЛЬТАТ ХОДА ТОЛЬКО ПОСЛЕ ПОВТОРНОЙ ПРОВЕРКИ НА НАЛИЧИЕ ПРОТИВНИКА - ОН МОГ УСПЕТЬ ОТОЙТИ! + // !!ИЛИ УМЕРЕТЬ!! + $stmt_update_timer->execute(); + } + +} \ No newline at end of file