Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # DuelArena will start automatically if at least 3 players
- # opted in (!duel or !d) to the queue.
- # DuelArena will be deactivated automatically if connected players
- # exceed the player_limit (default 5), or if there are only 2 players left, or
- # if too many players opted out.
- import minqlx
- from hamcrest import *
- import unittest
- MIN_ACTIVE_PLAYERS = 3 # with <3 connected and subscribed players we deactive DuelArena
- MAX_ACTIVE_PLAYERS = 5 # with >5 connected players we deactivate DuelArena
- class TestDuelArenaWorker(unittest.TestCase):
- def setUp(self):
- self.duelarena = DuelArenaWorker()
- def test_enqueue_players(self):
- self.enqueue("Player 1", "Player 2", "Player 3")
- assert_that(self.duelarena.queue, contains("Player 3", "Player 2", "Player 1"))
- def test_nextPlayer(self):
- self.enqueue("Player 1", "Player 2", "Player 3")
- newplayer = self.duelarena.playerLost("Player 4")
- assert_that(newplayer, "Player 1")
- def enqueue(self, *items):
- for item in items:
- self.duelarena.enqueuePlayer(item)
- def test_lost_player_gets_requeued(self):
- self.enqueue("Player 1", "Player 2", "Player 3")
- self.duelarena.playerLost("Player 4")
- assert_that(self.duelarena.queue, contains("Player 4", "Player 3", "Player 2"))
- def test_removing_a_player(self):
- self.enqueue("Player 1", "Player 2", "Player 3")
- self.duelarena.dequeuePlayer("Player 3")
- assert_that(self.duelarena.queue, contains("Player 2", "Player 1"))
- def test_removing_a_non_existing_player(self):
- self.enqueue("Player 1", "Player 2", "Player 3")
- self.duelarena.dequeuePlayer("Player 4")
- assert_that(self.duelarena.queue, contains("Player 3", "Player 2", "Player 1"))
- class DuelArenaWorker():
- def __init__(self):
- self.queue = []
- def enqueuePlayer(self, player):
- self.queue.insert(0, player)
- def dequeuePlayer(self, player):
- try:
- self.queue.remove(player)
- except ValueError:
- pass
- def nextPlayer(self):
- return self.queue.pop()
- def playerLost(self, player):
- self.enqueuePlayer(player)
- return self.nextPlayer()
- class duelarena(minqlx.Plugin):
- def __init__(self):
- self.initialize_hooks_and_commands()
- self.duelarena = DuelArenaWorker()
- self.duelmode = False # global gametype switch
- self.initduel = False # initial player setup switch
- self.psub = [] # steam_ids of players subscribed to DuelArena
- self.red_score = 0 # previous score to determine winner team
- self.blue_score = 0 # previous score to determine winner team
- self.player_red = 0 # force spec exception for this player
- self.player_blue = 0 # force spec exception for this player
- def initialize_hooks_and_commands(self):
- self.add_hook("team_switch", self.handle_switch)
- self.add_hook("player_disconnect", self.handle_player_disco)
- self.add_hook("player_connect", self.handle_player_connect)
- self.add_hook("game_start", self.handle_game_start)
- self.add_hook("round_end", self.handle_round_end)
- self.add_hook("game_end", self.handle_game_end)
- self.add_command(("duel", "d"), self.cmd_duel)
- self.add_command(("queue", "q"), self.cmd_printqueue)
- def handle_switch(self, player, old, new):
- # don't allow anyone to join manually when DuelArena is activ
- if self.game and new in ['red', 'blue'] and self.duelmode and self.game.state != "warmup":
- # except we auto join him
- if player == self.player_red or player == self.player_blue:
- return
- player.put("spectator")
- player.tell(
- "^3Server is in DuelArena mode. You will automatically join. Type ^2!duel ^3or ^2!d ^3to enter or to leave the queue")
- @minqlx.delay(3)
- def handle_player_connect(self, player):
- playercount = self.connected_players()
- if playercount == 3 or playercount == 5 and not self.duelmode:
- self.center_print("^3Type ^2!d ^3for DuelArena!")
- self.msg("^3Type ^2!d ^3for DuelArena!")
- self.duelarena_switch()
- dbg = "echo DUELARENA DBG: playercount {} duelmode: {} psub: {}"
- minqlx.console_command(dbg.format(playercount, self.duelmode, len(self.psub)))
- def handle_player_disco(self, player, reason):
- playercount = self.connected_players()
- if playercount == 3 or playercount == 5 and not self.duelmode:
- self.center_print("^3Type ^2!d ^3for DuelArena!")
- self.msg("^3Type ^2!d ^3for DuelArena!")
- self.duelarena_switch()
- self.duelarena.dequeuePlayer(player)
- @minqlx.delay(3)
- def handle_game_start(self, game):
- if self.duelmode:
- self.red_score = 0
- self.blue_score = 0
- self.init_duel()
- def handle_game_end(self, *args, **kwargs):
- # put both players back to the queue, winner first position, loser last position
- if self.duelmode:
- teams = self.teams()
- if self.game.blue_score > self.blue_score:
- empty_team = "red"
- winner_team = "blue"
- elif self.game.red_score > self.red_score:
- empty_team = "blue"
- winner_team = "red"
- else:
- return
- for _p in teams[empty_team]:
- loser = _p
- self.duelarena.playerLost(loser)
- @minqlx.delay(1.5)
- def handle_round_end(self, round_number):
- # Not in CA? Do nothing
- if (self.game is None) or (self.game.type_short != "ca"): return
- if self.initduel:
- self.init_duel()
- return
- if self.duelmode:
- if self.game.blue_score > self.blue_score:
- empty_team = "red"
- elif self.game.red_score > self.red_score:
- empty_team = "blue"
- else:
- return # Draw or first round? Do nothing
- self.blue_score = self.game.blue_score
- self.red_score = self.game.red_score
- next_player = self.duelarena.nextPlayer()
- cancelduel = True
- teams = self.teams()
- for _p in teams[empty_team]:
- loser = _p
- for _p in teams['spectator']:
- if _p.steam_id == next_player.steam_id:
- self.player_blue = _p
- self.player_red = _p
- _p.put(empty_team)
- self.queue.insert(0, loser.steam_id)
- loser.put("spectator")
- cancelduel = False
- if cancelduel: self.duelmode = False # no specs found? Deactivate DuelArena
- def cmd_duel(self, player, msg, channel):
- if self.connected_players() > MAX_ACTIVE_PLAYERS:
- player.tell(
- "^3!duel command not available with {} or more players connected".format(MAX_ACTIVE_PLAYERS + 1))
- return
- if player.steam_id not in self.psub:
- if player.steam_id not in self.queue: self.queue.insert(0, player.steam_id)
- self.psub.append(player.steam_id)
- indicator = len(self.queue) - self.queue.index(player.steam_id)
- player.tell(
- "^3You successfully opted in to the DuelArena queue. Type ^2!queue ^3or ^2!q ^3to get your queue position. Your position is ^2{}.".format(
- indicator))
- countdown = 3 - len(self.psub)
- if not self.duelmode and countdown > 0:
- self.msg(
- "{} ^3entered the DuelArena queue. ^1{} ^3more players needed to start DuelArena. Type ^2!duel ^3or ^2!d ^3to enter DuelArena queue.".format(
- player.name, countdown))
- else:
- self.msg(
- "{} ^3entered the DuelArena. Type ^2!duel ^3or ^2!d ^3to join DuelArena queue.".format(player.name))
- elif player.steam_id in self.psub:
- if player.steam_id in self.queue: self.queue.remove(player.steam_id)
- self.psub.remove(player.steam_id)
- self.msg("{} ^3left DuelArena.".format(player.name))
- self.duelarena_switch()
- def cmd_printqueue(self, player, msg, channel):
- if self.connected_players() > MAX_ACTIVE_PLAYERS:
- player.tell(
- "^3!queue command not available with {} or more players connected".format(MAX_ACTIVE_PLAYERS + 1))
- return
- qstring = ""
- for s_id in self.queue:
- p = self.player(s_id)
- indicator = len(self.queue) - self.queue.index(s_id)
- if indicator == 1:
- place = "1st"
- elif indicator == 2:
- place = "2nd"
- elif indicator == 3:
- place = "3rd"
- elif indicator == 4:
- place = "4th"
- elif indicator == 5:
- place = "5th"
- qstring = qstring + ("^3{}^7: ^2{} ".format(place, p.name))
- if qstring != "":
- self.msg(qstring)
- else:
- self.msg("^3There's no one in the queue yet. Type ^2!d ^3or ^2!duel ^3to enter the queue.")
- def init_duel(self):
- self.checklists()
- teams = self.teams()
- self.player_red = self.player(self.queue.pop())
- self.player_blue = self.player(self.queue.pop())
- self.player_red.put("red")
- self.player_blue.put("blue")
- # put all other players to spec
- for _p in teams['red'] + teams['blue']:
- if _p != self.player_red and _p != self.player_blue:
- _p.put("spectator")
- self.initduel = False
- def duelarena_switch(self):
- self.checklists()
- if self.duelmode:
- player_count = self.connected_players()
- if player_count > MAX_ACTIVE_PLAYERS or player_count < MIN_ACTIVE_PLAYERS or len(
- self.psub) < MIN_ACTIVE_PLAYERS:
- self.duelmode = False
- self.msg("^3DuelArena has been deactivated! You are free to join.")
- elif not self.duelmode:
- if len(self.psub) >= MIN_ACTIVE_PLAYERS and len(self.psub) <= MAX_ACTIVE_PLAYERS:
- self.duelmode = True
- self.msg("^3DuelArena activated! Type ^2!d ^3to join or leave the queue.")
- self.center_print("^3DuelArena activated! Type ^2!d ^3to join.")
- if self.game and self.game.state == "in_progress":
- self.initduel = True
- self.red_score = self.game.blue_score
- self.red_score = self.game.red_score
- def checklists(self):
- for sid in self.queue:
- if not self.player(sid): self.queue.remove(sid)
- for sid in self.psub:
- if not self.player(sid): self.psub.remove(sid)
- for p in self.players():
- if p.ping >= 990:
- if p.steam_id in self.queue: self.queue.remove(p.steam_id)
- if p.steam_id in self.psub: self.psub.remove(p.steam_id)
- ## Helper functions
- def connected_players(self):
- teams = self.teams()
- players = int(len(teams["red"] + teams["blue"] + teams["spectator"] + teams["free"]))
- return players
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement