# BetterDeathMatch # Made by your friend: @[Just] Freak#4999 """Defines a very-customisable DeathMatch mini-game""" # ba_meta require api 9 from __future__ import annotations from typing import TYPE_CHECKING import babase import bauiv1 as bui import bascenev1 as bs from bascenev1lib.actor.playerspaz import PlayerSpaz from bascenev1lib.actor.scoreboard import Scoreboard if TYPE_CHECKING: from typing import Any, Type, List, Union, Sequence, Optional class Player(bs.Player['Team']): """Our player type for this game.""" class Team(bs.Team[Player]): """Our team type for this game.""" def __init__(self) -> None: self.score = 0 # ba_meta export bascenev1.GameActivity class BetterDeathMatchGame(bs.TeamGameActivity[Player, Team]): """A game type based on acquiring kills.""" name = 'Btrr Death Match' description = 'Kill a set number of enemies to win.\nbyFREAK' # Print messages when players die since it matters here. announce_player_deaths = True @classmethod def get_available_settings( cls, sessiontype: Type[bs.Session]) -> List[babase.Setting]: settings = [ bs.IntSetting( 'Kills to Win Per Player', min_value=1, default=5, increment=1, ), bs.IntChoiceSetting( 'Time Limit', choices=[ ('None', 0), ('1 Minute', 60), ('2 Minutes', 120), ('5 Minutes', 300), ('10 Minutes', 600), ('20 Minutes', 1200), ], default=0, ), bs.FloatChoiceSetting( 'Respawn Times', choices=[ ('Shorter', 0.25), ('Short', 0.5), ('Normal', 1.0), ('Long', 2.0), ('Longer', 4.0), ], default=1.0, ), bs.BoolSetting('Epic Mode', default=False), ## Add settings ## bs.BoolSetting('Enable Gloves', False), bs.BoolSetting('Enable Powerups', True), bs.BoolSetting('Night Mode', False), bs.BoolSetting('Icy Floor', False), bs.BoolSetting('One Punch Kill', False), bs.BoolSetting('Spawn with Shield', False), bs.BoolSetting('Punching Only', False), ## Add settings ## ] # In teams mode, a suicide gives a point to the other team, but in # free-for-all it subtracts from your own score. By default we clamp # this at zero to benefit new players, but pro players might like to # be able to go negative. (to avoid a strategy of just # suiciding until you get a good drop) if issubclass(sessiontype, bs.FreeForAllSession): settings.append( bs.BoolSetting('Allow Negative Scores', default=False)) return settings @classmethod def supports_session_type(cls, sessiontype: Type[bs.Session]) -> bool: return (issubclass(sessiontype, bs.DualTeamSession) or issubclass(sessiontype, bs.FreeForAllSession)) @classmethod def get_supported_maps(cls, sessiontype: Type[bs.Session]) -> List[str]: return bs.app.classic.getmaps('melee') def __init__(self, settings: dict): super().__init__(settings) self._scoreboard = Scoreboard() self._score_to_win: Optional[int] = None self._dingsound = bui.getsound('dingSmall') ## Take applied settings ## self._boxing_gloves = bool(settings['Enable Gloves']) self._enable_powerups = bool(settings['Enable Powerups']) self._night_mode = bool(settings['Night Mode']) self._icy_floor = bool(settings['Icy Floor']) self._one_punch_kill = bool(settings['One Punch Kill']) self._shield_ = bool(settings['Spawn with Shield']) self._only_punch = bool(settings['Punching Only']) ## Take applied settings ## self._epic_mode = bool(settings['Epic Mode']) self._kills_to_win_per_player = int( settings['Kills to Win Per Player']) self._time_limit = float(settings['Time Limit']) self._allow_negative_scores = bool( settings.get('Allow Negative Scores', False)) # Base class overrides. self.slow_motion = self._epic_mode self.default_music = (bs.MusicType.EPIC if self._epic_mode else bs.MusicType.TO_THE_DEATH) def get_instance_description(self) -> Union[str, Sequence]: return 'Crush ${ARG1} of your enemies. byFREAK', self._score_to_win def get_instance_description_short(self) -> Union[str, Sequence]: return 'kill ${ARG1} enemies. byFREAK', self._score_to_win def on_team_join(self, team: Team) -> None: if self.has_begun(): self._update_scoreboard() ## Run settings related: IcyFloor ## def on_transition_in(self) -> None: super().on_transition_in() activity = bs.getactivity() if self._icy_floor: activity.map.is_hockey = True else: return ## Run settings related: IcyFloor ## def on_begin(self) -> None: super().on_begin() self.setup_standard_time_limit(self._time_limit) ## Run settings related: NightMode,Powerups ## if self._night_mode: bs.getactivity().globalsnode.tint = (0.5, 0.7, 1) else: pass # -# Tried return here, pfft. Took me 30mins to figure out why pwps spawning only on NightMode # -# Now its fixed :) if self._enable_powerups: self.setup_standard_powerup_drops() else: pass ## Run settings related: NightMode,Powerups ## # Base kills needed to win on the size of the largest team. self._score_to_win = (self._kills_to_win_per_player * max(1, max(len(t.players) for t in self.teams))) self._update_scoreboard() def handlemessage(self, msg: Any) -> Any: if isinstance(msg, bs.PlayerDiedMessage): # Augment standard behavior. super().handlemessage(msg) player = msg.getplayer(Player) self.respawn_player(player) killer = msg.getkillerplayer(Player) if killer is None: return None # Handle team-kills. if killer.team is player.team: # In free-for-all, killing yourself loses you a point. if isinstance(self.session, bs.FreeForAllSession): new_score = player.team.score - 1 if not self._allow_negative_scores: new_score = max(0, new_score) player.team.score = new_score # In teams-mode it gives a point to the other team. else: self._dingsound.play() for team in self.teams: if team is not killer.team: team.score += 1 # Killing someone on another team nets a kill. else: killer.team.score += 1 self._dingsound.play() # In FFA show scores since its hard to find on the scoreboard. if isinstance(killer.actor, PlayerSpaz) and killer.actor: killer.actor.set_score_text(str(killer.team.score) + '/' + str(self._score_to_win), color=killer.team.color, flash=True) self._update_scoreboard() # If someone has won, set a timer to end shortly. # (allows the dust to clear and draws to occur if deaths are # close enough) assert self._score_to_win is not None if any(team.score >= self._score_to_win for team in self.teams): bs.timer(0.5, self.end_game) else: return super().handlemessage(msg) return None ## Run settings related: Spaz ## def spawn_player(self, player: Player) -> bs.Actor: spaz = self.spawn_player_spaz(player) if self._boxing_gloves: spaz.equip_boxing_gloves() if self._one_punch_kill: spaz._punch_power_scale = 15 if self._shield_: spaz.equip_shields() if self._only_punch: spaz.connect_controls_to_player(enable_bomb=False, enable_pickup=False) return spaz ## Run settings related: Spaz ## def _update_scoreboard(self) -> None: for team in self.teams: self._scoreboard.set_team_value(team, team.score, self._score_to_win) def end_game(self) -> None: results = bs.GameResults() for team in self.teams: results.set_team_score(team, team.score) self.end(results=results)