From 0fd7c5bed18919410c1aad103a69680fc2c08dee Mon Sep 17 00:00:00 2001 From: brostosjoined Date: Thu, 1 Feb 2024 13:07:51 +0300 Subject: [PATCH] More --- plugins/minigames.json | 20 +- plugins/minigames/flag_day.py | 614 ++++++++++++++++++ plugins/utilities.json | 28 + plugins/utilities/bots_can_accept_powerups.py | 41 ++ plugins/utilities/cheat_menu.py | 355 ++++++++++ 5 files changed, 1055 insertions(+), 3 deletions(-) create mode 100644 plugins/minigames/flag_day.py create mode 100644 plugins/utilities/bots_can_accept_powerups.py create mode 100644 plugins/utilities/cheat_menu.py diff --git a/plugins/minigames.json b/plugins/minigames.json index 4cdc9ce..db4143e 100644 --- a/plugins/minigames.json +++ b/plugins/minigames.json @@ -1274,7 +1274,7 @@ "1.0.0": null } }, - "extinction_run": { + "extinction": { "description": "Survive the Extinction.", "external_url": "", "authors": [ @@ -1289,8 +1289,8 @@ } }, "fat_pigs": { - "description": "Survive the Extinction.", - "external_url": "Survive the pigs...", + "description": "Survive...", + "external_url": "", "authors": [ { "name": "Zacker Tz", @@ -1301,6 +1301,20 @@ "versions": { "1.0.0": null } + }, + "flag_day": { + "description": "Pick up flags to receive a prize.\nBut beware...", + "external_url": "https://youtu.be/ANDzdBicjA4?si=h8S_TPUAxSaG7nls", + "authors": [ + { + "name": "MattZ45986", + "email": "", + "discord": "" + } + ], + "versions": { + "1.0.0": null + } } } } \ No newline at end of file diff --git a/plugins/minigames/flag_day.py b/plugins/minigames/flag_day.py new file mode 100644 index 0000000..d5d473c --- /dev/null +++ b/plugins/minigames/flag_day.py @@ -0,0 +1,614 @@ + +#Ported by brostos to api 8 +# ba_meta require api 8 +# (see https://ballistica.net/wiki/meta-tag-system) + +from __future__ import annotations + +from typing import TYPE_CHECKING + +import babase +import bauiv1 as bui +import bascenev1 as bs +import _babase +import json +import math +import random +from bascenev1lib.game.elimination import Icon +from bascenev1lib.actor.bomb import Bomb, Blast +from bascenev1lib.actor.playerspaz import PlayerSpaz +from bascenev1lib.actor.scoreboard import Scoreboard +from bascenev1lib.actor.powerupbox import PowerupBox +from bascenev1lib.actor.flag import Flag, FlagPickedUpMessage +from bascenev1lib.actor.spazbot import SpazBotSet, BrawlerBotLite, SpazBotDiedMessage + +if TYPE_CHECKING: + from typing import Any, Sequence + + +lang = bs.app.lang.language +if lang == 'Spanish': + name = 'Día de la Bandera' + description = ('Recoge las banderas para recibir un premio.\n' + 'Pero ten cuidado...') + slow_motion_deaths = 'Muertes en Cámara Lenta' + credits = 'Creado por MattZ45986 en Github | Actualizado por byANG3L and brostos' + you_were = 'Estas' + cursed_text = 'MALDITO' + run = 'CORRE' + climb_top = 'Escala a la cima' + bomb_rain = '¡LLUVIA DE BOMBAS!' + lame_guys = 'Chicos Ligeros' + jackpot = '¡PREMIO MAYOR!' + diedtxt = '¡' + diedtxt2 = ' ha sido eliminado!' +else: + name = 'Flag Day' + description = 'Pick up flags to receive a prize.\nBut beware...' + slow_motion_deaths = 'Slow Motion Deaths' + credits = 'Created by MattZ45986 on Github | Updated by byANG3L and brostos' + you_were = 'You were' + cursed_text = 'CURSED' + run = 'RUN' + climb_top = 'Climb to the top' + bomb_rain = 'BOMB RAIN!' + lame_guys = 'Lame Guys' + jackpot = '!JACKPOT!' + diedtxt = '' + diedtxt2 = ' died!' + + +class Icon(Icon): + + def __init__( + self, + player: Player, + position: tuple[float, float], + scale: float, + show_lives: bool = True, + show_death: bool = True, + name_scale: float = 1.0, + name_maxwidth: float = 115.0, + flatness: float = 1.0, + shadow: float = 1.0, + dead: bool = False, + ): + super().__init__(player,position,scale,show_lives,show_death, + name_scale,name_maxwidth,flatness,shadow) + if dead: + self._name_text.opacity = 0.2 + self.node.color = (0.7, 0.3, 0.3) + self.node.opacity = 0.2 + + +class FlagBearer(PlayerSpaz): + def handlemessage(self, msg: Any) -> Any: + super().handlemessage(msg) + if isinstance(msg, bs.PowerupMessage): + activity = self.activity + player = self.getplayer(Player) + if not player.is_alive(): + return + if activity.last_prize == 'curse': + player.team.score += 25 + activity._update_scoreboard() + elif activity.last_prize == 'land_mines': + player.team.score += 15 + activity._update_scoreboard() + self.connect_controls_to_player() + elif activity.last_prize == 'climb': + player.team.score += 50 + activity._update_scoreboard() + if msg.poweruptype == 'health': + activity.round_timer = None + bs.timer(0.2, activity.setup_next_round) + + +class Player(bs.Player['Team']): + """Our player type for this game.""" + + def __init__(self) -> None: + self.dead = False + self.icons: list[Icon] = [] + +class Team(bs.Team[Player]): + """Our team type for this game.""" + + def __init__(self) -> None: + self.score = 0 + + +# ba_meta export bascenev1.GameActivity +class FlagDayGame(bs.TeamGameActivity[Player, Team]): + """A game type based on acquiring kills.""" + + name = name + description = description + + # Print messages when players die since it matters here. + announce_player_deaths = True + + allow_mid_activity_joins = False + + @classmethod + def get_available_settings( + cls, sessiontype: type[bs.Session] + ) -> list[babase.Setting]: + settings = [ + bs.BoolSetting(slow_motion_deaths, default=True), + bs.BoolSetting('Epic Mode', default=False), + ] + return settings + + @classmethod + def supports_session_type(cls, sessiontype: type[bs.Session]) -> bool: + return ( + issubclass(sessiontype, bs.CoopSession) + or issubclass(sessiontype, bs.DualTeamSession) + or issubclass(sessiontype, bs.FreeForAllSession) + ) + + @classmethod + def get_supported_maps(cls, sessiontype: type[bs.Session]) -> list[str]: + return ['Courtyard'] + + def __init__(self, settings: dict): + super().__init__(settings) + self.credits() + self._scoreboard = Scoreboard() + self._dingsound = bui.getsound('dingSmall') + self._epic_mode = bool(settings['Epic Mode']) + self._slow_motion_deaths = bool(settings[slow_motion_deaths]) + self.current_player: Player | None = None + self.prize_recipient: Player | None = None + self.bomb_survivor: Player | None = None + self.bad_guy_cost: int = 0 + self.player_index: int = 0 + self.bombs: list = [] + self.queue_line: list = [] + self._bots: SpazBotSet | None = None + self.light: bs.Node | None = None + self.last_prize = 'none' + self._flag: Flag | None = None + self._flag2: Flag | None = None + self._flag3: Flag | None = None + self._flag4: Flag | None = None + self._flag5: Flag | None = None + self._flag6: Flag | None = None + self._flag7: Flag | None = None + self._flag8: Flag | None = None + self.set = False + self.round_timer: bs.Timer | None = None + self.give_points_timer: bs.Timer | None = None + + self._jackpot_sound = bui.getsound('achievement') + self._round_sound = bui.getsound('powerup01') + self._dingsound = bui.getsound('dingSmall') + + # 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 on_team_join(self, team: Team) -> None: + if self.has_begun(): + self._update_scoreboard() + + def on_player_leave(self, player: Player) -> None: + if player is self.current_player: + self.setup_next_round() + self._check_end_game() + super().on_player_leave(player) + self.queue_line.remove(player) + self._update_icons() + + def on_begin(self) -> None: + super().on_begin() + for player in self.players: + if player.actor: + player.actor.handlemessage(bs.DieMessage()) + player.actor.node.delete() + self.queue_line.append(player) + self.spawn_player_spaz( + self.queue_line[self.player_index % len(self.queue_line)], + (0.0, 3.0, -2.0)) + self.current_player = self.queue_line[0] + # Declare a set of bots (enemies) that we will use later + self._bots = SpazBotSet() + self.reset_flags() + self._update_icons() + self._update_scoreboard() + + def credits(self) -> None: + bs.newnode( + 'text', + attrs={ + 'v_attach': 'bottom', + 'h_align': 'center', + 'vr_depth': 0, + 'color': (0, 0.2, 0), + 'shadow': 1.0, + 'flatness': 1.0, + 'position': (0,0), + 'scale': 0.8, + 'text': credits + }) + + def _update_icons(self) -> None: + # pylint: disable=too-many-branches + for player in self.queue_line: + player.icons = [] + if player == self.current_player: + xval = 0 + x_offs = -78 + player.icons.append( + Icon(player, + position=(xval, 65), + scale=1.0, + name_maxwidth=130, + name_scale=0.8, + flatness=0.0, + shadow=0.5, + show_death=True, + show_lives=False)) + elif player.dead: + xval = 65 + x_offs = 78 + player.icons.append( + Icon(player, + position=(xval, 50), + scale=0.5, + name_maxwidth=75, + name_scale=1.0, + flatness=1.0, + shadow=1.0, + show_death=False, + show_lives=False, + dead=True)) + xval += x_offs * 0.56 + else: + xval = -65 + x_offs = 78 + player.icons.append( + Icon(player, + position=(xval, 50), + scale=0.5, + name_maxwidth=75, + name_scale=1.0, + flatness=1.0, + shadow=1.0, + show_death=False, + show_lives=False)) + xval -= x_offs * 0.56 + + def give_prize(self, prize: int) -> None: + if prize == 1: + # Curse him aka make him blow up in 5 seconds + # give them a nice message + bs.broadcastmessage(you_were, color=(0.1, 0.1, 0.1)) + bs.broadcastmessage(cursed_text, color=(1.0, 0.0, 0.0)) + self.make_health_box((0.0, 0.0, 0.0)) + self.last_prize = 'curse' + self.prize_recipient.actor.curse() + # bs.timer(5.5, self.setup_next_round) + if prize == 2: + self.setup_rof() + bs.broadcastmessage(run, color=(1.0, 0.2, 0.1)) + self.last_prize = 'ring_of_fire' + if prize == 3: + self.last_prize = 'climb' + self.light = bs.newnode( + 'locator', + attrs={ + 'shape': 'circle', + 'position': (0.0, 3.0, -9.0), + 'color': (1.0, 1.0, 1.0), + 'opacity': 1.0, + 'draw_beauty': True, + 'additive': True + }) + bs.broadcastmessage(climb_top, color=(0.5, 0.5, 0.5)) + bs.timer(3.0, babase.Call(self.make_health_box, (0.0, 6.0, -9.0))) + self.round_timer = bs.Timer(10.0, self.setup_next_round) + if prize == 4: + self.last_prize = 'land_mines' + self.make_health_box((6.0, 5.0, -2.0)) + self.make_land_mines() + self.prize_recipient.actor.connect_controls_to_player( + enable_bomb=False) + self.prize_recipient.actor.node.handlemessage( + bs.StandMessage(position=(-6.0, 3.0, -2.0))) + self.round_timer = bs.Timer(7.0, self.setup_next_round) + if prize == 5: + # Make it rain bombs + self.bomb_survivor = self.prize_recipient + bs.broadcastmessage(bomb_rain, color=(1.0, 0.5, 0.16)) + # Set positions for the bombs to drop + for bzz in range(-5,6): + for azz in range(-5,2): + # for each position make a bomb drop there + self.make_bomb(bzz, azz) + self.give_points_timer = bs.Timer(3.3, self.give_points) + self.last_prize = 'bombrain' + if prize == 6: + self.setup_br() + self.bomb_survivor = self.prize_recipient + self.give_points_timer = bs.Timer(7.0, self.give_points) + self.last_prize = 'bombroad' + if prize == 7: + # makes killing a bad guy worth ten points + self.bad_guy_cost = 2 + bs.broadcastmessage(lame_guys, color=(1.0, 0.5, 0.16)) + # makes a set of nine positions + for a in range(-1, 2): + for b in range(-3, 0): + # and spawns one in each position + self._bots.spawn_bot(BrawlerBotLite, pos=(a, 2.5, b)) + # and we give our player boxing gloves and a shield + self._player.equip_boxing_gloves() + self._player.equip_shields() + self.last_prize = 'lameguys' + if prize == 8: + self._jackpot_sound.play() + bs.broadcastmessage(jackpot, color=(1.0, 0.0, 0.0)) + bs.broadcastmessage(jackpot, color=(0.0, 1.0, 0.0)) + bs.broadcastmessage(jackpot, color=(0.0, 0.0, 1.0)) + team = self.prize_recipient.team + # GIVE THEM A WHOPPING 50 POINTS!!! + team.score += 50 + # and update the scores + self._update_scoreboard() + self.last_prize = 'jackpot' + bs.timer(2.0, self.setup_next_round) + + def setup_next_round(self) -> None: + if self._slow_motion_deaths: + bs.getactivity().globalsnode.slow_motion = False + if self.set: + return + if self.light: + self.light.delete() + for bomb in self.bombs: + bomb.handlemessage(bs.DieMessage()) + self.kill_flags() + self._bots.clear() + self.reset_flags() + self.current_player.actor.handlemessage( + bs.DieMessage(how='game')) + self.current_player.actor.node.delete() + c = 0 + self.player_index += 1 + self.player_index %= len(self.queue_line) + if len(self.queue_line) > 0: + while self.queue_line[self.player_index].dead: + if c > len(self.queue_line): + return + self.player_index += 1 + self.player_index %= len(self.queue_line) + c += 1 + self.spawn_player_spaz( + self.queue_line[self.player_index], (0.0, 3.0, -2.0)) + self.current_player = self.queue_line[self.player_index] + self.last_prize = 'none' + self._update_icons() + + def check_bots(self) -> None: + if not self._bots.have_living_bots(): + self.setup_next_round() + + def make_land_mines(self) -> None: + self.bombs = [] + for i in range(-11, 7): + self.bombs.append(Bomb( + position=(0.0, 6.0, i/2.0), + bomb_type='land_mine', + blast_radius=2.0)) + self.bombs[i+10].arm() + + def give_points(self) -> None: + if self.bomb_survivor is not None and self.bomb_survivor.is_alive(): + self.bomb_survivor.team.score += 20 + self._update_scoreboard() + self.round_timer = bs.Timer(1.0, self.setup_next_round) + + def make_health_box(self, position: Sequence[float]) -> None: + if position == (0.0, 3.0, 0.0): + position = (random.randint(-6, 6), 6, random.randint(-6, 4)) + elif position == (0,0,0): + position = random.choice( + ((-7, 6, -5), (7, 6, -5), (-7, 6, 1), (7, 6, 1))) + self.health_box = PowerupBox( + position=position, poweruptype='health').autoretain() + + # called in prize #5 + def make_bomb(self, xpos: float, zpos: float) -> None: + # makes a bomb at the given position then auto-retains it aka: + # makes sure it doesn't disappear because there is no reference to it + self.bombs.append(Bomb(position=(xpos, 12, zpos))) + + def setup_br(self) -> None: + self.make_bomb_row(6) + self.prize_recipient.actor.handlemessage( + bs.StandMessage(position=(6.0, 3.0, -2.0))) + + def make_bomb_row(self, num: int) -> None: + if not self.prize_recipient.is_alive(): + return + if num == 0: + self.round_timer = bs.Timer(1.0, self.setup_next_round) + return + for i in range(-11, 7): + self.bombs.append( + Bomb(position=(-3, 3, i/2.0), + velocity=(12, 0.0, 0.0), + bomb_type='normal', + blast_radius=1.2)) + bs.timer(1.0, babase.Call(self.make_bomb_row, num-1)) + + def setup_rof(self) -> None: + self.make_blast_ring(10) + self.prize_recipient.actor.handlemessage( + bs.StandMessage(position=(0.0, 3.0, -2.0))) + + def make_blast_ring(self, length: float) -> None: + if not self.prize_recipient.is_alive(): + return + if length == 0: + self.setup_next_round() + self.prize_recipient.team.score += 50 + self._update_scoreboard() + return + for angle in range(0, 360, 45): + angle += random.randint(0, 45) + angle %= 360 + x = length * math.cos(math.radians(angle)) + z = length * math.sin(math.radians(angle)) + blast = Blast(position=(x, 2.2, z-2), blast_radius=3.5) + bs.timer(0.75, babase.Call(self.make_blast_ring, length-1)) + + # a method to remake the flags + def reset_flags(self) -> None: + # remake the flags + self._flag = Flag( + position=(0.0, 3.0, 1.0), touchable=True, color=(0.0, 0.0, 1.0)) + self._flag2 = Flag( + position=(0.0, 3.0, -5.0), touchable=True, color=(1.0, 0.0, 0.0)) + self._flag3 = Flag( + position=(3.0, 3.0, -2.0), touchable=True, color=(0.0, 1.0, 0.0)) + self._flag4 = Flag( + position=(-3.0, 3.0, -2.0), touchable=True, color=(1.0, 1.0, 1.0)) + self._flag5 = Flag( + position=(1.8, 3.0, 0.2), touchable=True, color=(0.0, 1.0, 1.0)) + self._flag6 = Flag( + position=(-1.8, 3.0, 0.2), touchable=True, color=(1.0, 0.0, 1.0)) + self._flag7 = Flag( + position=(1.8, 3.0, -3.8), touchable=True, color=(1.0, 1.0, 0.0)) + self._flag8 = Flag( + position=(-1.8, 3.0, -3.8), touchable=True, color=(0.0, 0.0, 0.0)) + + # a method to kill the flags + def kill_flags(self) -> None: + # destroy all the flags by erasing all references to them, + # indicated by None similar to null + self._flag.node.delete() + self._flag2.node.delete() + self._flag3.node.delete() + self._flag4.node.delete() + self._flag5.node.delete() # 132, 210 ,12 + self._flag6.node.delete() + self._flag7.node.delete() + self._flag8.node.delete() + + def _check_end_game(self) -> None: + for player in self.queue_line: + if not player.dead: + return + self.end_game() + + def spawn_player_spaz( + self, + player: PlayerT, + position: Sequence[float] = (0, 0, 0), + angle: float | None = None, + ) -> PlayerSpaz: + from babase import _math + from bascenev1._gameutils import animate + from bascenev1._coopsession import CoopSession + + angle = None + name = player.getname() + color = player.color + highlight = player.highlight + + light_color = _math.normalized_color(color) + display_color = babase.safecolor(color, target_intensity=0.75) + + spaz = FlagBearer(color=color, + highlight=highlight, + character=player.character, + player=player) + + player.actor = spaz + assert spaz.node + + spaz.node.name = name + spaz.node.name_color = display_color + spaz.connect_controls_to_player() + + # Move to the stand position and add a flash of light. + spaz.handlemessage( + bs.StandMessage( + position, + angle if angle is not None else random.uniform(0, 360))) + self._spawn_sound.play(1, position=spaz.node.position) + light = bs.newnode('light', attrs={'color': light_color}) + spaz.node.connectattr('position', light, 'position') + animate(light, 'intensity', {0: 0, 0.25: 1, 0.5: 0}) + bs.timer(0.5, light.delete) + return spaz + + def handlemessage(self, msg: Any) -> Any: + if isinstance(msg, bs.PlayerDiedMessage): + # give them a nice farewell + if bs.time() < 0.5: + return + if msg.how == 'game': + return + player = msg.getplayer(Player) + bs.broadcastmessage( + diedtxt + str(player.getname()) + diedtxt2, color=player.color) + player.dead = True + if player is self.current_player: + self.round_timer = None + self.give_points_timer = None + if not msg.how is bs.DeathType.FALL: + if self._slow_motion_deaths: + bs.getactivity().globalsnode.slow_motion = True + time = 0.5 + else: + time = 0.01 + # check to see if we can end the game + self._check_end_game() + bs.timer(time, self.setup_next_round) + elif isinstance(msg, FlagPickedUpMessage): + msg.flag.last_player_to_hold = msg.node.getdelegate( + FlagBearer, True + ).getplayer(Player, True) + self._player = msg.node.getdelegate( + FlagBearer, True + ) + self.prize_recipient = msg.node.getdelegate( + FlagBearer, True + ).getplayer(Player, True) + self.kill_flags() + self.give_prize(random.randint(1, 8)) + self._round_sound.play() + self.current_player = self.prize_recipient + elif isinstance(msg, SpazBotDiedMessage): + # find out which team the last person to hold a flag was on + team = self.prize_recipient.team + # give them their points + team.score += self.bad_guy_cost + self._dingsound.play(0.5) + # update the scores + for team in self.teams: + self._scoreboard.set_team_value(team, team.score) + bs.timer(0.3, self.check_bots) + return None + + def _update_scoreboard(self) -> None: + for player in self.queue_line: + if not player.dead: + if player.team.score > 0: + self._dingsound.play() + self._scoreboard.set_team_value(player.team, player.team.score) + + def end_game(self) -> None: + if self.set: + return + self.set = True + results = bs.GameResults() + for team in self.teams: + results.set_team_score(team, team.score) + self.end(results=results) diff --git a/plugins/utilities.json b/plugins/utilities.json index 0a5c094..b5f63eb 100644 --- a/plugins/utilities.json +++ b/plugins/utilities.json @@ -1175,6 +1175,34 @@ "versions": { "1.0.0": null } + }, + "bots_can_accept_powerups": { + "description": "Bots can steal your powerups", + "external_url": "", + "authors": [ + { + "name": "", + "email": "", + "discord": "" + } + ], + "versions": { + "1.0.0": null + } + }, + "cheat_menu": { + "description": "Cheat menu on the settings window", + "external_url": "", + "authors": [ + { + "name": "pranav", + "email": "", + "discord": "" + } + ], + "versions": { + "1.0.0": null + } } } } \ No newline at end of file diff --git a/plugins/utilities/bots_can_accept_powerups.py b/plugins/utilities/bots_can_accept_powerups.py new file mode 100644 index 0000000..7c00f67 --- /dev/null +++ b/plugins/utilities/bots_can_accept_powerups.py @@ -0,0 +1,41 @@ +# Ported to api 8 by brostos using baport.(https://github.com/bombsquad-community/baport) +# ba_meta require api 8 +# (see https://ballistica.net/wiki/meta-tag-system) + +from __future__ import annotations + +from typing import TYPE_CHECKING + +import babase +import bauiv1 as bui +import bascenev1 as bs +from bascenev1lib.actor.spazbot import SpazBot +from bascenev1lib.actor.powerupbox import PowerupBoxFactory + +if TYPE_CHECKING: + pass + + +# ba_meta export plugin +class BotsCanAcceptPowerupsPlugin(babase.Plugin): + def on_app_running(self) -> None: + SpazBot.oldinit = SpazBot.__init__ + def __init__(self) -> None: + self.oldinit() + pam = PowerupBoxFactory.get().powerup_accept_material + materials = self.node.materials + materials = list(materials) + materials.append(pam) + materials = tuple(materials) + self.node.materials = materials + roller_materials = self.node.roller_materials + roller_materials = list(roller_materials) + roller_materials.append(pam) + roller_materials = tuple(roller_materials) + self.node.roller_materials = roller_materials + extras_material = self.node.extras_material + extras_material = list(extras_material) + extras_material.append(pam) + extras_material = tuple(extras_material) + self.node.extras_material = extras_material + SpazBot.__init__ = __init__ diff --git a/plugins/utilities/cheat_menu.py b/plugins/utilities/cheat_menu.py new file mode 100644 index 0000000..8648dea --- /dev/null +++ b/plugins/utilities/cheat_menu.py @@ -0,0 +1,355 @@ +# Ported by brostos to api 8 +# Tool used to make porting easier.(https://github.com/bombsquad-community/baport) +"""CheatMenu | now cheat much as you can haha!! please eric sir dont kill me + + +Credits To: +Pranav"Modder"= Creator of the mod. +Emily"Skin and Modder"= Code and Mod Ideas.(pls dont be angry) :"( +And Me(Edited): Well Litterally Nothing lol. + +Important Note From the Creator: "I apreciate any kind of modification. So feel free to use or edit code or change credit string.... no problem. +this mod uses activity loop cheacks if change in config and update it on our player node" + +Really Awesome servers: + Bombsquad Consultancy Service - https://discord.gg/2RKd9QQdQY. + bombspot - https://discord.gg/ucyaesh. + cyclones - https://discord.gg/pJXxkbQ7kH. +""" +from __future__ import annotations + +__author__ = 'egg' +__version__ = 1.0 + +import babase +import bauiv1 as bui +import bascenev1 as bs +import _babase + +from baenv import TARGET_BALLISTICA_BUILD as build_number +from bauiv1lib.settings.allsettings import AllSettingsWindow +from bascenev1lib.actor.spaz import Spaz + +from typing import ( + Text, + Tuple, + Optional, + Union, + get_args +) +type + +# Default Confings/Settings +CONFIG = "CheatMenu" +APPCONFIG = babase.app.config +Configs = { + "Unlimited Heath": False, + "SpeedBoots": False, + "Fly": False, + "SuperPunch": False, + "ImpactOnly": False, + "StickyOnly": False, + "IceOnly" : False, + "Infinite Bombs": False, + "More Are Coming": False, + "Credits": False, +} + + +def setconfigs() -> None: + """Set required defualt configs for mod""" + if CONFIG not in APPCONFIG: + APPCONFIG[str(CONFIG)] = Configs + + for c in Configs: + if c not in APPCONFIG[str(CONFIG)]: + APPCONFIG[str(CONFIG)][str(c)] = Configs[str(c)] + else: + pass + APPCONFIG.apply_and_commit() + + +def update_config(config: str, change: any): + """update's given value in json config file of pluguin""" + APPCONFIG[str(CONFIG)][str(config)] = change + APPCONFIG.apply_and_commit() + + +# ba_meta require api 8 +# ba_meta export plugin +class Plugin(babase.Plugin): + def on_app_running(self) -> None: + if babase.app.build_number if build_number < 21282 else babase.app.env.build_number: + setconfigs() + self.overwrite() + + else: + babase.screenmessage(f'{__name__} only works on api 8') + + def overwrite(self) -> None: + AllSettingsWindow.init = AllSettingsWindow.__init__ + AllSettingsWindow.__init__ = AllSettingsWindowInit + + +# creating Cheat button, start button +def AllSettingsWindowInit(self, transition: str = 'in_right', origin_widget: bui.Widget = None): + self.init(transition) + + uiscale = bui.app.ui_v1.uiscale + btn_width = 720 if uiscale is babase.UIScale.SMALL else 400 + btn_height = 380 + + self.cheat_menu_btn = bui.buttonwidget( + parent=self._root_widget, + autoselect=True, + position=(btn_width, btn_height), + size=(105, 50), + icon=bui.gettexture('settingsIcon'), + label='Cheats', + button_type='square', + text_scale=1.2, + on_activate_call=babase.Call( + on_cheat_menu_btn_press, self)) + + +# on cheat button press call Window +def on_cheat_menu_btn_press(self): + bui.containerwidget(edit=self._root_widget, + transition='out_scale') + bui.app.ui_v1.set_main_menu_window( + CheatMenuWindow( + transition='in_right').get_root_widget(), from_window=self._root_widget) + + +class CheatMenuWindow(bui.Window): + def __init__(self, + transition: Optional[str] = 'in_right') -> None: + + # background window, main widget parameters + uiscale = bui.app.ui_v1.uiscale + self._width = 870.0 if uiscale is babase.UIScale.SMALL else 670.0 + self._height = (390.0 if uiscale is babase.UIScale.SMALL else + 450.0 if uiscale is babase.UIScale.MEDIUM else 520.0) + extra_x = 100 if uiscale is babase.UIScale.SMALL else 0 + self.extra_x = extra_x + top_extra = 20 if uiscale is babase.UIScale.SMALL else 0 + + # scroll widget parameters + self._scroll_width = self._width - (100 + 2 * extra_x) + self._scroll_height = self._height - 115.0 + self._sub_width = self._scroll_width * 0.95 + self._sub_height = 640.0 + self._spacing = 32 + self._extra_button_spacing = self._spacing * 2.5 + + super().__init__( + root_widget=bui.containerwidget( + size=(self._width, self._height), + transition=transition, + scale=(2.06 if uiscale is babase.UIScale.SMALL else + 1.4 if uiscale is babase.UIScale.MEDIUM else 1.0))) + + # back button widget + self._back_button = bui.buttonwidget( + parent=self._root_widget, + autoselect=True, + position=(52 + self.extra_x, + self._height - 60 - top_extra), + size=(60, 60), + scale=0.8, + label=babase.charstr(babase.SpecialChar.BACK), + button_type='backSmall', + on_activate_call=self._back) + bui.containerwidget(edit=self._root_widget, + cancel_button=self._back_button) + + # window title, apears in top center of window + self._title_text = bui.textwidget( + parent=self._root_widget, + position=(0, self._height - 40 - top_extra), + size=(self._width, 25), + text='Cheat Menu', + color=bui.app.ui_v1.title_color, + scale=1.2, + h_align='center', + v_align='top') + + self._scrollwidget = bui.scrollwidget( + parent=self._root_widget, + position=(50 + extra_x, 50 - top_extra), + simple_culling_v=20.0, + highlight=False, + size=(self._scroll_width, + self._scroll_height), + selection_loops_to_parent=True) + bui.widget(edit=self._scrollwidget, + right_widget=self._scrollwidget) + + # subcontainer represents scroll widget and used as parent + self._subcontainer = bui.containerwidget( + parent=self._scrollwidget, + size=(self._sub_width, + self._sub_height), + background=False, + selection_loops_to_parent=True) + + v = self._sub_height - 35 + v -= self._spacing * 1.2 + conf = APPCONFIG[str(CONFIG)] + + for checkbox in Configs: + bui.checkboxwidget( + parent=self._subcontainer, + autoselect=True, + position=(25.0, v), + size=(40, 40), + text=checkbox, + textcolor=(0.8, 0.8, 0.8), + value=APPCONFIG[CONFIG][checkbox], + on_value_change_call=babase.Call( + self.update, checkbox), + scale=1.4, + maxwidth=430) + v -= 70 + + def update(self, config: str, change) -> None: + """Change config and get our sounds + + Args: + config: str + change: any + """ + try: + if change == True and config == "Fly": + bui.screenmessage("Some maps may not work good for flying", + color=(1, 0, 0)) + update_config(config, change) + bui.getsound('gunCocking').play() + except Exception: + bui.screenmessage("error", color=(1, 0, 0)) + bui.getsound('error').play() + + try: + if change == True and config == "SuperPunch": + bui.screenmessage("SuperPunch Activated", + color=(1, 0, 0)) + elif change == False and config == "SuperPunch": + bui.screenmessage("Super Punch Deactivated", + color=(0.5,0,0)) + update_config(config, change) + bui.getsound('gunCocking').play() + except Exception: + bui.screenmessage("error", color=(1, 0, 0)) + bui.getsound('spazOw').play() + + try: + if change == True and config == "IceOnly": + bui.screenmessage("Ice Bombs Activated", + color=(0.1, 1, 1)) + elif change == False and config == "IceOnly": + bui.screenmessage("Ice Bombs Deactivated", + color=(1, 0, 0)) + update_config(config, change) + bui.getsound('gunCocking').play() + except Exception: + bui.screenmessage("error", color=(1, 0, 0)) + bui.getsound('spazOw').play() + try: + if change == True and config == "StickyOnly": + bui.screenmessage("Sticky Bombs Activated", + color=(0, 1, 0)) + elif change == False and config == "StickyOnly": + bui.screenmessage("Sticky Bombs Deactivated", + color=(1, 0, 0)) + update_config(config, change) + bui.getsound('gunCocking').play() + except Exception: + bui.screenmessage("error", color=(1, 0, 0)) + bui.getsound('spazOw').play() + + try: + if change == True and config == "ImpactOnly": + bui.screenmessage("Impact Bombs Activated", + color=(0.5, 0.5, 0.5)) + elif change == False and config == "ImpactOnly": + bui.screenmessage("Impact Bombs Deactivated", + color=(1, 0, 0)) + update_config(config, change) + bui.getsound('gunCocking').play() + except Exception: + bui.screenmessage("error", color=(1, 0, 0)) + bui.getsound('spazOw').play() + + try: + if change == True and config == "More Are Coming": + bui.screenmessage("Check out https://discord.gg/2RKd9QQdQY For More Mods", + color=(4, 9, 2)) + update_config(config, change) + bui.getsound('gunCocking').play() + except Exception: + bui.screenmessage("error", color=(1, 0, 0)) + bui.getsound('cheer').play() + + try: + if change == True and config == "Credits": + bui.screenmessage("To Pranav Made The Mod and Emily For Ideas, Thx", + color=(4, 9, 2)) + update_config(config, change) + bui.getsound('gunCocking').play() + except Exception: + bui.screenmessage("error", color=(1, 0, 0)) + bui.getsound('cheer').play() + + def _back(self) -> None: + """Kill the window and get back to previous one + """ + bui.containerwidget(edit=self._root_widget, + transition='out_scale') + bui.app.ui_v1.set_main_menu_window( + AllSettingsWindow( + transition='in_left').get_root_widget(), from_window=self._root_widget) + + +def ishost(): + session = bs.get_foreground_host_session() + with session.context: + for player in session.sessionplayers: + if player.inputdevice.client_id == -1: + return True + +def activity_loop(): + if bs.get_foreground_host_activity() is not None: + activity = bs.get_foreground_host_activity() + with activity.context: + for player in activity.players: + if not ishost() or not player.actor: + return + config = APPCONFIG[CONFIG] + + player.actor.node.invincible = config["Unlimited Heath"] + player.actor.node.fly = config["Fly"] + player.actor.node.hockey = config["SpeedBoots"] + + if config["SuperPunch"]: + player.actor._punch_power_scale = 2 + + elif not config["SuperPunch"]: + player.actor._punch_power_scale = 1.2 + + if config["IceOnly"]: + player.actor.bomb_type = 'ice' + elif not config["IceOnly"]: + player.actor.bomb_type = 'normal' + player.actor.bomb_count= 1 + + if config["ImpactOnly"]: + player.actor.bomb_type = 'impact' + player.actor.bomb_count = 1 + + if config["StickyOnly"]: + player.actor.bomb_type = 'sticky' + player.actor.bomb_count = 1 + + if config["Infinite Bombs"]: + player.actor.bomb_count = 100 +timer = babase.AppTimer(2, activity_loop,repeat=True) \ No newline at end of file