diff --git a/dist/ba_root/mods/games/air_soccer.py b/dist/ba_root/mods/games/air_soccer.py new file mode 100644 index 0000000..75e9ba4 --- /dev/null +++ b/dist/ba_root/mods/games/air_soccer.py @@ -0,0 +1,661 @@ +# Porting to api 8 made easier by baport.(https://github.com/bombsquad-community/baport) +# Released under the MIT License. See LICENSE for details. +# BY Stary_Agent +"""Hockey game and support classes.""" + +# 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 bascenev1 as bs +from bascenev1lib.actor.playerspaz import PlayerSpaz +from bascenev1lib.actor.scoreboard import Scoreboard +from bascenev1lib.actor.powerupbox import PowerupBoxFactory +from bascenev1lib.gameutils import SharedObjects + +if TYPE_CHECKING: + from typing import Any, Sequence, Dict, Type, List, Optional, Union + + +class PuckDiedMessage: + """Inform something that a puck has died.""" + + def __init__(self, puck: Puck): + self.puck = puck + + +def create_slope(self): + shared = SharedObjects.get() + x = 5 + y = 12 + for i in range(0, 10): + bs.newnode('region', attrs={'position': (x, y, -5.52), 'scale': (0.2, 0.1, 6), + 'type': 'box', 'materials': [shared.footing_material, self._real_wall_material]}) + x = x+0.3 + y = y+0.1 + + +class Puck(bs.Actor): + """A lovely giant hockey puck.""" + + def __init__(self, position: Sequence[float] = (0.0, 13.0, 0.0)): + super().__init__() + shared = SharedObjects.get() + activity = self.getactivity() + + # Spawn just above the provided point. + self._spawn_pos = (position[0], position[1] + 1.0, position[2]) + self.last_players_to_touch: Dict[int, Player] = {} + self.scored = False + assert activity is not None + assert isinstance(activity, HockeyGame) + pmats = [shared.object_material, activity.puck_material] + self.node = bs.newnode('prop', + delegate=self, + attrs={ + 'mesh': activity.puck_mesh, + 'color_texture': activity.puck_tex, + 'body': 'sphere', + 'reflection': 'soft', + 'reflection_scale': [0.2], + 'gravity_scale': 0.3, + 'shadow_size': 0.5, + 'is_area_of_interest': True, + 'position': self._spawn_pos, + 'materials': pmats + }) + bs.animate(self.node, 'mesh_scale', {0: 0, 0.2: 1.3, 0.26: 1}) + + def handlemessage(self, msg: Any) -> Any: + if isinstance(msg, bs.DieMessage): + assert self.node + self.node.delete() + activity = self._activity() + if activity and not msg.immediate: + activity.handlemessage(PuckDiedMessage(self)) + + # If we go out of bounds, move back to where we started. + elif isinstance(msg, bs.OutOfBoundsMessage): + assert self.node + self.node.position = self._spawn_pos + + elif isinstance(msg, bs.HitMessage): + assert self.node + assert msg.force_direction is not None + self.node.handlemessage( + 'impulse', msg.pos[0], msg.pos[1], msg.pos[2], msg.velocity[0], + msg.velocity[1], msg.velocity[2], 1.0 * msg.magnitude, + 1.0 * msg.velocity_magnitude, msg.radius, 0, + msg.force_direction[0], msg.force_direction[1], + msg.force_direction[2]) + + # If this hit came from a player, log them as the last to touch us. + s_player = msg.get_source_player(Player) + if s_player is not None: + activity = self._activity() + if activity: + if s_player in activity.players: + self.last_players_to_touch[s_player.team.id] = s_player + else: + super().handlemessage(msg) + + +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 AirSoccerGame(bs.TeamGameActivity[Player, Team]): + """Ice hockey game.""" + + name = 'Epic Air Soccer' + description = 'Score some goals.' + available_settings = [ + bs.IntSetting( + 'Score to Win', + min_value=1, + default=1, + 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.1), + ('Short', 0.5), + ('Normal', 1.0), + ('Long', 2.0), + ('Longer', 4.0), + ], + default=1.0, + ), + ] + default_music = bs.MusicType.HOCKEY + + @classmethod + def supports_session_type(cls, sessiontype: Type[bs.Session]) -> bool: + return issubclass(sessiontype, bs.DualTeamSession) + + @classmethod + def get_supported_maps(cls, sessiontype: Type[bs.Session]) -> List[str]: + return ['Creative Thoughts'] + + def __init__(self, settings: dict): + super().__init__(settings) + shared = SharedObjects.get() + self.slow_motion = True + self._scoreboard = Scoreboard() + self._cheer_sound = bs.getsound('cheer') + self._chant_sound = bs.getsound('crowdChant') + self._foghorn_sound = bs.getsound('foghorn') + self._swipsound = bs.getsound('swip') + self._whistle_sound = bs.getsound('refWhistle') + self.puck_mesh = bs.getmesh('bomb') + self.puck_tex = bs.gettexture('landMine') + self.puck_scored_tex = bs.gettexture('landMineLit') + self._puck_sound = bs.getsound('metalHit') + self.puck_material = bs.Material() + self.puck_material.add_actions(actions=(('modify_part_collision', + 'friction', 0.5))) + self.puck_material.add_actions(conditions=('they_have_material', + shared.pickup_material), + actions=('modify_part_collision', + 'collide', True)) + self.puck_material.add_actions( + conditions=( + ('we_are_younger_than', 100), + 'and', + ('they_have_material', shared.object_material), + ), + actions=('modify_node_collision', 'collide', False), + ) + self.puck_material.add_actions(conditions=('they_have_material', + shared.footing_material), + actions=('impact_sound', + self._puck_sound, 0.2, 5)) + self._real_wall_material = bs.Material() + self._real_wall_material.add_actions( + + actions=( + ('modify_part_collision', 'collide', True), + ('modify_part_collision', 'physical', True) + + )) + + self._real_wall_material.add_actions( + conditions=('they_have_material', shared.player_material), + actions=( + ('modify_part_collision', 'collide', True), + ('modify_part_collision', 'physical', True) + + )) + self._goal_post_material = bs.Material() + self._goal_post_material.add_actions( + + actions=( + ('modify_part_collision', 'collide', True), + ('modify_part_collision', 'physical', True) + + )) + + self._goal_post_material.add_actions( + conditions=('they_have_material', shared.player_material), + actions=( + ('modify_part_collision', 'collide', False), + ('modify_part_collision', 'physical', False) + + )) + # Keep track of which player last touched the puck + self.puck_material.add_actions( + conditions=('they_have_material', shared.player_material), + actions=(('call', 'at_connect', + self._handle_puck_player_collide), )) + + # We want the puck to kill powerups; not get stopped by them + self.puck_material.add_actions( + conditions=('they_have_material', + PowerupBoxFactory.get().powerup_material), + actions=(('modify_part_collision', 'physical', False), + ('message', 'their_node', 'at_connect', bs.DieMessage()))) + self._score_region_material = bs.Material() + self._score_region_material.add_actions( + conditions=('they_have_material', self.puck_material), + actions=(('modify_part_collision', 'collide', + True), ('modify_part_collision', 'physical', False), + ('call', 'at_connect', self._handle_score))) + self._puck_spawn_pos: Optional[Sequence[float]] = None + self._score_regions: Optional[List[bs.NodeActor]] = None + self._puck: Optional[Puck] = None + self._score_to_win = int(settings['Score to Win']) + self._time_limit = float(settings['Time Limit']) + + def get_instance_description(self) -> Union[str, Sequence]: + if self._score_to_win == 1: + return 'Score a goal.' + return 'Score ${ARG1} goals.', self._score_to_win + + def get_instance_description_short(self) -> Union[str, Sequence]: + if self._score_to_win == 1: + return 'score a goal' + return 'score ${ARG1} goals', self._score_to_win + + def on_begin(self) -> None: + super().on_begin() + + self.setup_standard_time_limit(self._time_limit) + self.setup_standard_powerup_drops() + self._puck_spawn_pos = (0, 16.9, -5.5) + self._spawn_puck() + self.make_map() + + # Set up the two score regions. + defs = self.map.defs + self._score_regions = [] + self._score_regions.append( + bs.NodeActor( + bs.newnode('region', + attrs={ + 'position': (17, 14.5, -5.52), + 'scale': (1, 3, 1), + 'type': 'box', + 'materials': [self._score_region_material] + }))) + self._score_regions.append( + bs.NodeActor( + bs.newnode('region', + attrs={ + 'position': (-17, 14.5, -5.52), + 'scale': (1, 3, 1), + 'type': 'box', + 'materials': [self._score_region_material] + }))) + self._update_scoreboard() + self._chant_sound.play() + + def on_team_join(self, team: Team) -> None: + self._update_scoreboard() + + def _handle_puck_player_collide(self) -> None: + collision = bs.getcollision() + try: + puck = collision.sourcenode.getdelegate(Puck, True) + player = collision.opposingnode.getdelegate(PlayerSpaz, + True).getplayer( + Player, True) + except bs.NotFoundError: + return + + puck.last_players_to_touch[player.team.id] = player + + def make_map(self): + shared = SharedObjects.get() + bs.get_foreground_host_activity()._map.leftwall.materials = [ + shared.footing_material, self._real_wall_material] + + bs.get_foreground_host_activity()._map.rightwall.materials = [ + shared.footing_material, self._real_wall_material] + + bs.get_foreground_host_activity()._map.topwall.materials = [ + shared.footing_material, self._real_wall_material] + self.floorwall = bs.newnode('region', attrs={'position': (0, 5, -5.52), 'scale': ( + 35.4, 0.2, 2), 'type': 'box', 'materials': [shared.footing_material, self._real_wall_material]}) + bs.newnode('locator', attrs={'shape': 'box', 'position': ( + 0, 5, -5.52), 'color': (0, 0, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': (35.4, 0.2, 2)}) + + self.create_goal_post(-16.65, 12.69) + self.create_goal_post(-16.65, 16.69) + + self.create_goal_post(16.65, 12.69) + self.create_goal_post(16.65, 16.69) + + self.create_static_step(0, 16.29) + + self.create_static_step(4.35, 11.1) + self.create_static_step(-4.35, 11.1) + + self.create_vertical(10, 15.6) + self.create_vertical(-10, 15.6) + + def create_static_step(self, x, y): + floor = "" + for i in range(0, 7): + floor += "_ " + shared = SharedObjects.get() + step = {} + step["r"] = bs.newnode('region', attrs={'position': (x, y, -5.52), 'scale': ( + 3, 0.1, 6), 'type': 'box', 'materials': [shared.footing_material, self._real_wall_material]}) + bs.newnode('locator', attrs={'shape': 'box', 'position': ( + x, y, -5.52), 'color': (1, 1, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': (3, 0.1, 2)}) + + return step + + def create_goal_post(self, x, y): + shared = SharedObjects.get() + if x > 0: + color = (1, 0, 0) # change to team specific color + else: + color = (0, 0, 1) + floor = "" + for i in range(0, 4): + floor += "_ " + bs.newnode('region', attrs={'position': (x-0.2, y, -5.52), 'scale': (1.8, 0.1, 6), + 'type': 'box', 'materials': [shared.footing_material, self._goal_post_material]}) + + bs.newnode('locator', attrs={'shape': 'box', 'position': ( + x-0.2, y, -5.52), 'color': color, 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': (1.8, 0.1, 2)}) + + def create_vertical(self, x, y): + shared = SharedObjects.get() + floor = "" + for i in range(0, 4): + floor += "|\n" + bs.newnode('region', attrs={'position': (x, y, -5.52), 'scale': (0.1, 2.8, 1), + 'type': 'box', 'materials': [shared.footing_material, self._real_wall_material]}) + bs.newnode('locator', attrs={'shape': 'box', 'position': ( + x, y, -5.52), 'color': (1, 1, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': (0.1, 2.8, 2)}) + + def spawn_player_spaz(self, + player: Player, + position: Sequence[float] = None, + angle: float = None) -> PlayerSpaz: + """Intercept new spazzes and add our team material for them.""" + if player.team.id == 0: + position = (-10.75152479, 5.057427485, -5.52) + elif player.team.id == 1: + position = (8.75152479, 5.057427485, -5.52) + + spaz = super().spawn_player_spaz(player, position, angle) + return spaz + + def _kill_puck(self) -> None: + self._puck = None + + def _handle_score(self) -> None: + """A point has been scored.""" + + assert self._puck is not None + assert self._score_regions is not None + + # Our puck might stick around for a second or two + # we don't want it to be able to score again. + if self._puck.scored: + return + + region = bs.getcollision().sourcenode + index = 0 + for index in range(len(self._score_regions)): + if region == self._score_regions[index].node: + break + + for team in self.teams: + if team.id == index: + scoring_team = team + team.score += 1 + + # Tell all players to celebrate. + for player in team.players: + if player.actor: + player.actor.handlemessage(bs.CelebrateMessage(2.0)) + + # If we've got the player from the scoring team that last + # touched us, give them points. + if (scoring_team.id in self._puck.last_players_to_touch + and self._puck.last_players_to_touch[scoring_team.id]): + self.stats.player_scored( + self._puck.last_players_to_touch[scoring_team.id], + 20, + big_message=True) + + # End game if we won. + if team.score >= self._score_to_win: + self.end_game() + + self._foghorn_sound.play() + self._cheer_sound.play() + + self._puck.scored = True + + # Change puck texture to something cool + self._puck.node.color_texture = self.puck_scored_tex + # Kill the puck (it'll respawn itself shortly). + bs.timer(1.0, self._kill_puck) + + light = bs.newnode('light', + attrs={ + 'position': bs.getcollision().position, + 'height_attenuated': False, + 'color': (1, 0, 0) + }) + bs.animate(light, 'intensity', {0: 0, 0.5: 1, 1.0: 0}, loop=True) + bs.timer(1.0, light.delete) + + bs.cameraflash(duration=10.0) + self._update_scoreboard() + + def end_game(self) -> None: + results = bs.GameResults() + for team in self.teams: + results.set_team_score(team, team.score) + self.end(results=results) + + def _update_scoreboard(self) -> None: + winscore = self._score_to_win + for team in self.teams: + self._scoreboard.set_team_value(team, team.score, winscore) + + def handlemessage(self, msg: Any) -> Any: + + # Respawn dead players if they're still in the game. + if isinstance(msg, bs.PlayerDiedMessage): + # Augment standard behavior... + super().handlemessage(msg) + self.respawn_player(msg.getplayer(Player)) + + # Respawn dead pucks. + elif isinstance(msg, PuckDiedMessage): + if not self.has_ended(): + bs.timer(3.0, self._spawn_puck) + else: + super().handlemessage(msg) + + def _flash_puck_spawn(self) -> None: + light = bs.newnode('light', + attrs={ + 'position': self._puck_spawn_pos, + 'height_attenuated': False, + 'color': (1, 0, 0) + }) + bs.animate(light, 'intensity', {0.0: 0, 0.25: 1, 0.5: 0}, loop=True) + bs.timer(1.0, light.delete) + + def _spawn_puck(self) -> None: + self._swipsound.play() + self._whistle_sound.play() + self._flash_puck_spawn() + assert self._puck_spawn_pos is not None + self._puck = Puck(position=self._puck_spawn_pos) + + +class mapdefs: + points = {} + # noinspection PyDictCreation + boxes = {} + boxes['area_of_interest_bounds'] = (-1.045859963, 12.67722855, + -5.401537075) + (0.0, 0.0, 0.0) + ( + 42.46156851, 20.94044653, 0.6931564611) + points['ffa_spawn1'] = (-9.295167711, 8.010664315, + -5.44451005) + (1.555840357, 1.453808816, 0.1165648888) + points['ffa_spawn2'] = (7.484707127, 8.172681752, -5.614479365) + ( + 1.553861796, 1.453808816, 0.04419853907) + points['ffa_spawn3'] = (9.55724115, 11.30789446, -5.614479365) + ( + 1.337925849, 1.453808816, 0.04419853907) + points['ffa_spawn4'] = (-11.55747023, 10.99170684, -5.614479365) + ( + 1.337925849, 1.453808816, 0.04419853907) + points['ffa_spawn5'] = (-1.878892369, 9.46490571, -5.614479365) + ( + 1.337925849, 1.453808816, 0.04419853907) + points['ffa_spawn6'] = (-0.4912812943, 5.077006397, -5.521672101) + ( + 1.878332089, 1.453808816, 0.007578097856) + points['flag1'] = (-11.75152479, 8.057427485, -5.52) + points['flag2'] = (9.840909039, 8.188634282, -5.52) + points['flag3'] = (-0.2195258696, 5.010273907, -5.52) + points['flag4'] = (-0.04605809154, 12.73369108, -5.52) + points['flag_default'] = (-0.04201942896, 12.72374492, -5.52) + boxes['map_bounds'] = (-0.8748348681, 9.212941713, -5.729538885) + ( + 0.0, 0.0, 0.0) + (42.09666006, 26.19950145, 7.89541168) + points['powerup_spawn1'] = (1.160232442, 6.745963662, -5.469115985) + points['powerup_spawn2'] = (-1.899700206, 10.56447241, -5.505721177) + points['powerup_spawn3'] = (10.56098871, 12.25165669, -5.576232453) + points['powerup_spawn4'] = (-12.33530337, 12.25165669, -5.576232453) + points['spawn1'] = (-9.295167711, 8.010664315, + -5.44451005) + (1.555840357, 1.453808816, 0.1165648888) + points['spawn2'] = (7.484707127, 8.172681752, + -5.614479365) + (1.553861796, 1.453808816, 0.04419853907) + points['spawn_by_flag1'] = (-9.295167711, 8.010664315, -5.44451005) + ( + 1.555840357, 1.453808816, 0.1165648888) + points['spawn_by_flag2'] = (7.484707127, 8.172681752, -5.614479365) + ( + 1.553861796, 1.453808816, 0.04419853907) + points['spawn_by_flag3'] = (-1.45994593, 5.038762459, -5.535288724) + ( + 0.9516389866, 0.6666414677, 0.08607244075) + points['spawn_by_flag4'] = (0.4932087091, 12.74493212, -5.598987003) + ( + 0.5245740665, 0.5245740665, 0.01941146064) + + +class CreativeThoughts(bs.Map): + """Freaking map by smoothy.""" + + defs = mapdefs + + name = 'Creative Thoughts' + + @classmethod + def get_play_types(cls) -> List[str]: + """Return valid play types for this map.""" + return [ + 'melee', 'keep_away', 'team_flag' + ] + + @classmethod + def get_preview_texture_name(cls) -> str: + return 'alwaysLandPreview' + + @classmethod + def on_preload(cls) -> Any: + data: Dict[str, Any] = { + 'mesh': bs.getmesh('alwaysLandLevel'), + 'bottom_mesh': bs.getmesh('alwaysLandLevelBottom'), + 'bgmesh': bs.getmesh('alwaysLandBG'), + 'collision_mesh': bs.getcollisionmesh('alwaysLandLevelCollide'), + 'tex': bs.gettexture('alwaysLandLevelColor'), + 'bgtex': bs.gettexture('alwaysLandBGColor'), + 'vr_fill_mound_mesh': bs.getmesh('alwaysLandVRFillMound'), + 'vr_fill_mound_tex': bs.gettexture('vrFillMound') + } + return data + + @classmethod + def get_music_type(cls) -> bs.MusicType: + return bs.MusicType.FLYING + + def __init__(self) -> None: + super().__init__(vr_overlay_offset=(0, -3.7, 2.5)) + shared = SharedObjects.get() + self._fake_wall_material = bs.Material() + self._real_wall_material = bs.Material() + self._fake_wall_material.add_actions( + conditions=(('they_are_younger_than', 9000), 'and', + ('they_have_material', shared.player_material)), + actions=( + ('modify_part_collision', 'collide', True), + ('modify_part_collision', 'physical', True) + + )) + self._real_wall_material.add_actions( + conditions=('they_have_material', shared.player_material), + actions=( + ('modify_part_collision', 'collide', True), + ('modify_part_collision', 'physical', True) + + )) + self.background = bs.newnode( + 'terrain', + attrs={ + 'mesh': self.preloaddata['bgmesh'], + 'lighting': False, + 'background': True, + 'color_texture': bs.gettexture("rampageBGColor") + }) + + self.leftwall = bs.newnode('region', attrs={'position': (-17.75152479, 13, -5.52), 'scale': ( + 0.1, 15.5, 2), 'type': 'box', 'materials': [shared.footing_material, self._real_wall_material]}) + self.rightwall = bs.newnode('region', attrs={'position': (17.75, 13, -5.52), 'scale': ( + 0.1, 15.5, 2), 'type': 'box', 'materials': [shared.footing_material, self._real_wall_material]}) + self.topwall = bs.newnode('region', attrs={'position': (0, 21.0, -5.52), 'scale': ( + 35.4, 0.2, 2), 'type': 'box', 'materials': [shared.footing_material, self._real_wall_material]}) + bs.newnode('locator', attrs={'shape': 'box', 'position': (-17.75152479, 13, -5.52), 'color': ( + 0, 0, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': (0.1, 15.5, 2)}) + bs.newnode('locator', attrs={'shape': 'box', 'position': (17.75, 13, -5.52), 'color': ( + 0, 0, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': (0.1, 15.5, 2)}) + bs.newnode('locator', attrs={'shape': 'box', 'position': (0, 21.0, -5.52), 'color': ( + 0, 0, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': (35.4, 0.2, 2)}) + + gnode = bs.getactivity().globalsnode + gnode.happy_thoughts_mode = True + gnode.shadow_offset = (0.0, 8.0, 5.0) + gnode.tint = (1.3, 1.23, 1.0) + gnode.ambient_color = (1.3, 1.23, 1.0) + gnode.vignette_outer = (0.64, 0.59, 0.69) + gnode.vignette_inner = (0.95, 0.95, 0.93) + gnode.vr_near_clip = 1.0 + self.is_flying = True + + # throw out some tips on flying + txt = bs.newnode('text', + attrs={ + 'text': babase.Lstr(resource='pressJumpToFlyText'), + 'scale': 1.2, + 'maxwidth': 800, + 'position': (0, 200), + 'shadow': 0.5, + 'flatness': 0.5, + 'h_align': 'center', + 'v_attach': 'bottom' + }) + cmb = bs.newnode('combine', + owner=txt, + attrs={ + 'size': 4, + 'input0': 0.3, + 'input1': 0.9, + 'input2': 0.0 + }) + bs.animate(cmb, 'input3', {3.0: 0, 4.0: 1, 9.0: 1, 10.0: 0}) + cmb.connectattr('output', txt, 'color') + bs.timer(10.0, txt.delete) + + +try: + bs._map.register_map(CreativeThoughts) +except: + pass diff --git a/dist/ba_root/mods/games/bridgit_mash.py b/dist/ba_root/mods/games/bridgit_mash.py new file mode 100644 index 0000000..f65b508 --- /dev/null +++ b/dist/ba_root/mods/games/bridgit_mash.py @@ -0,0 +1,236 @@ +from __future__ import annotations + +from typing import TYPE_CHECKING + +import babase +import bauiv1 as bui +import bascenev1 as bs +from bascenev1lib.gameutils import SharedObjects +from bascenev1lib.actor.playerspaz import PlayerSpaz +import random +if TYPE_CHECKING: + from typing import Any, List, Dict + + +class mapdefs: + points = {} + # noinspection PyDictCreation + boxes = {} + boxes['area_of_interest_bounds'] = (0.0, 1.185751251, 0.4326226188) + ( + 0.0, 0.0, 0.0) + (29.8180273, 11.57249038, 18.89134176) + boxes['edge_box'] = (-0.103873591, 0.4133341891, 0.4294651013) + ( + 0.0, 0.0, 0.0) + (22.48295719, 1.290242794, 8.990252454) + points['ffa_spawn1'] = (-0.08015551329, 0.02275111462, + -4.373674593) + (8.895057015, 1.0, 0.444350722) + points['ffa_spawn2'] = (-0.08015551329, 0.02275111462, + 4.076288941) + (8.895057015, 1.0, 0.444350722) + points['flag1'] = (-10.99027878, 0.05744967453, 0.1095578275) + points['flag2'] = (11.01486398, 0.03986567039, 0.1095578275) + points['flag_default'] = (-0.1001374046, 0.04180340146, 0.1095578275) + boxes['goal1'] = (12.22454533, 1.0, + 0.1087926362) + (0.0, 0.0, 0.0) + (2.0, 2.0, 12.97466313) + boxes['goal2'] = (-12.15961605, 1.0, + 0.1097860203) + (0.0, 0.0, 0.0) + (2.0, 2.0, 13.11856424) + boxes['map_bounds'] = (0.0, 1.185751251, 0.4326226188) + (0.0, 0.0, 0.0) + ( + 42.09506485, 22.81173179, 29.76723155) + points['powerup_spawn1'] = (5.414681236, 0.9515026107, -5.037912441) + points['powerup_spawn2'] = (-5.555402285, 0.9515026107, -5.037912441) + points['powerup_spawn3'] = (5.414681236, 0.9515026107, 5.148223181) + points['powerup_spawn4'] = (-5.737266365, 0.9515026107, 5.148223181) + points['spawn1'] = (-10.03866341, 0.02275111462, 0.0) + (0.5, 1.0, 4.0) + points['spawn2'] = (9.823107149, 0.01092306765, 0.0) + (0.5, 1.0, 4.0) + points['tnt1'] = (-0.08421587483, 0.9515026107, -0.7762602271) + + +class BridgitMash(bs.Map): + """Stadium map for football games.""" + defs = mapdefs + defs.points['spawn1'] = (-12.03866341, 0.02275111462, + 0.0) + (0.5, 1.0, 4.0) + defs.points['spawn2'] = ( + 12.823107149, 0.01092306765, 0.0) + (0.5, 1.0, 4.0) + + defs.points["flag1"] = (-9.6, 0.747, -2.949) + defs.points["flag2"] = (9.6, 0.747, 3.15) + defs.points["flag3"] = (-9.6, 0.747, 3.15) + defs.points["flag4"] = (-0.1, 0.747, -2.949) + defs.points["flag5"] = (-0.1, 0.747, 0.152) + defs.points["flag6"] = (-0.1, 0.747, 3.15) + defs.points["flag7"] = (9.6, 0.747, -2.949) + defs.points["flag8"] = (9.6, 0.747, 0.152) + defs.points["flag9"] = (-9.6, 0.747, 0.152) + + defs.points["spawn_by_flag1"] = (-9.6, 0.747, -2.949) + defs.points["spawn_by_flag2"] = (9.6, 0.747, 3.15) + defs.points["spawn_by_flag3"] = (-9.6, 0.747, 3.15) + defs.points["spawn_by_flag4"] = (-0.1, 0.747, -2.949) + defs.points["spawn_by_flag5"] = (-0.1, 0.747, 0.152) + defs.points["spawn_by_flag6"] = (-0.1, 0.747, 3.15) + defs.points["spawn_by_flag7"] = (9.6, 0.747, -2.949) + defs.points["spawn_by_flag8"] = (9.6, 0.747, 0.152) + defs.points["spawn_by_flag9"] = (-9.6, 0.747, 0.152) + + name = 'Bridgit Mash' + + @classmethod + def get_play_types(cls) -> list[str]: + """Return valid play types for this map.""" + return ['melee', 'football', 'team_flag', 'keep_away', 'conquest'] + + @classmethod + def get_preview_texture_name(cls) -> str: + return 'footballStadiumPreview' + + @classmethod + def on_preload(cls) -> Any: + data: dict[str, Any] = { + 'mesh': bs.getmesh('footballStadium'), + 'vr_fill_mesh': bs.getmesh('footballStadiumVRFill'), + 'collision_mesh': bs.getcollisionmesh('footballStadiumCollide'), + 'tex': bs.gettexture('footballStadium') + } + return data + + def __init__(self) -> None: + super().__init__() + shared = SharedObjects.get() + # TODO vr fill data + gnode = bs.getactivity().globalsnode + gnode.tint = (1.3, 1.2, 1.0) + gnode.ambient_color = (1.3, 1.2, 1.0) + gnode.vignette_outer = (0.57, 0.57, 0.57) + gnode.vignette_inner = (0.9, 0.9, 0.9) + gnode.vr_camera_offset = (0, -0.8, -1.1) + gnode.vr_near_clip = 0.5 + cols = [(0.10, 0.3, 0.5), (0.6, 0.3, 0.6), (0.6, 0.3, 0.1), + (0.2, 0.4, 0.1), (0.4, 0.3, 0.7), (0.10, 0.3, 0.5)] + self.background = bs.newnode( + 'terrain', + attrs={ + 'mesh': bs.getmesh('natureBackground'), + 'lighting': False, + 'background': True, + 'color': cols[random.randrange(0, 6)] + }) + self.map_extend() + + def is_point_near_edge(self, + point: babase.Vec3, + running: bool = False) -> bool: + box_position = self.defs.boxes['edge_box'][0:3] + box_scale = self.defs.boxes['edge_box'][6:9] + xpos = (point.x - box_position[0]) / box_scale[0] + zpos = (point.z - box_position[2]) / box_scale[2] + return xpos < -0.5 or xpos > 0.5 or zpos < -0.5 or zpos > 0.5 + + def map_extend(self): + self.create_ramp(0, 0) + self.create_ramp(10.9, 0) + self.create_ramp(0, -3) + self.create_ramp(10.9, -2.8) + self.create_ramp(0, 3.0) + self.create_ramp(10.9, 3.2) + self.ground() + # _babase.prop_axis(1, 0, 0) + + def ground(self): + shared = SharedObjects.get() + self._real_wall_material = bs.Material() + + self._real_wall_material.add_actions( + + actions=( + ('modify_part_collision', 'collide', True), + ('modify_part_collision', 'physical', True) + )) + self.mat = bs.Material() + self.mat.add_actions( + + actions=(('modify_part_collision', 'physical', False), + ('modify_part_collision', 'collide', False)) + ) + + def create_ramp(self, loc, z_marg): + # try: + # _babase.prop_axis(0, 0, 0) + # except: + # pass + shared = SharedObjects.get() + self._real_wall_material = bs.Material() + + self._real_wall_material.add_actions( + + actions=( + ('modify_part_collision', 'collide', True), + ('modify_part_collision', 'physical', True) + + )) + self.mat = bs.Material() + self.mat.add_actions( + + actions=(('modify_part_collision', 'physical', False), + ('modify_part_collision', 'collide', False)) + ) + spaz_collide_mat = bs.Material() + # spaz_collide_mat.add_actions( + # conditions=('they_have_material',shared.player_material), + # actions=( + # ('modify_part_collision', 'collide', True), + # ( 'call','at_connect',babase.Call(self._handle_player_pad_collide,real )), + # ), + # ) + pos = (-5.3 + loc, 0.7, 1.1+z_marg) + self.ud_1_r = bs.newnode('region', attrs={'position': pos, 'scale': ( + 2, 1, 2), 'type': 'box', 'materials': [shared.footing_material, spaz_collide_mat]}) + + self.node = bs.newnode('prop', + owner=self.ud_1_r, + attrs={ + 'mesh': bs.getmesh('bridgitLevelTop'), + 'light_mesh': bs.getmesh('powerupSimple'), + 'position': (2, 7, 2), + 'body': 'puck', + 'shadow_size': 0.0, + 'velocity': (0, 0, 0), + 'color_texture': bs.gettexture('bridgitLevelColor'), + 'mesh_scale': 0.72, + 'reflection_scale': [1.5], + 'materials': [self.mat, shared.object_material, shared.footing_material], + + 'density': 9000000000 + }) + self.node.changerotation(0, 0, 0) + mnode = bs.newnode('math', + owner=self.ud_1_r, + attrs={ + 'input1': (0, -2.9, 0), + 'operation': 'add' + }) + + self.ud_1_r.connectattr('position', mnode, 'input2') + mnode.connectattr('output', self.node, 'position') + + # /// region to stand long bar =============== + + pos = (-9.67+loc, 0.1, 0+z_marg) + self.left_region = bs.newnode('region', attrs={'position': pos, 'scale': (2.4, 0.7, 3.2), 'type': 'box', 'materials': [ + shared.footing_material, self._real_wall_material, spaz_collide_mat]}) + + pos = (-5.67+loc, 0.1, 0+z_marg) + self.center_region = bs.newnode('region', attrs={'position': pos, 'scale': ( + 8, 0.7, 1), 'type': 'box', 'materials': [shared.footing_material, self._real_wall_material, spaz_collide_mat]}) + pos = (-1.3+loc, 0.1, 0+z_marg) + self.right_region = bs.newnode('region', attrs={'position': pos, 'scale': (2.4, 0.7, 3.2), 'type': 'box', 'materials': [ + shared.footing_material, self._real_wall_material, spaz_collide_mat]}) + + def _handle_player_collide(self): + try: + player = bs.getcollision().opposingnode.getdelegate( + PlayerSpaz, True) + except bs.NotFoundError: + return + if player.is_alive(): + player.shatter(True) + + +bs._map.register_map(BridgitMash) diff --git a/dist/ba_root/mods/games/eggs_of_doom.py b/dist/ba_root/mods/games/eggs_of_doom.py new file mode 100644 index 0000000..dacc803 --- /dev/null +++ b/dist/ba_root/mods/games/eggs_of_doom.py @@ -0,0 +1,318 @@ +# Porting to api 8 made easier by baport.(https://github.com/bombsquad-community/baport) +# Released under the MIT License. See LICENSE for details. +# Created by Mr.Smoothy - +# https://discord.gg/ucyaesh +# https://bombsquad-community.web.app/home for more mods. +# +"""DeathMatch game and support classes.""" + +# ba_meta require api 8 +# (see https://ballistica.net/wiki/meta-tag-system) +from __future__ import annotations + +from typing import TYPE_CHECKING, override + +from bascenev1lib.actor.spazfactory import SpazFactory +import babase +import bascenev1 as bs +import random +import math +from bascenev1lib.actor.playerspaz import PlayerSpaz +from bascenev1lib.actor.scoreboard import Scoreboard +from bascenev1lib.gameutils import SharedObjects +from bascenev1lib.actor.bomb import BombFactory +from bascenev1lib.actor.bomb import Bomb + +from bascenev1lib.game.deathmatch import DeathMatchGame, Player, Team + +if TYPE_CHECKING: + from typing import Any, Union, Sequence, Optional + + +class _TouchedMessage: + pass + +# ba_meta export bascenev1.GameActivity + + +class FireChainGame(DeathMatchGame): + + """A game type based on acquiring kills.""" + + name = 'Eggs of Doom' + description = 'Kill a set number of enemies to win.' + + # 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), + ] + + # 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 ["Doom Shroom"] + + def __init__(self, settings: dict): + super().__init__(settings) + self._scoreboard = Scoreboard() + self._score_to_win: Optional[int] = None + self._dingsound = bs.getsound('dingSmall') + 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) + + self.wtindex = 0 + self.wttimer = bs.timer(5, babase.Call(self.wt_), repeat=True) + self.wthighlights = ["Created by Mr.Smoothy", + "hey smoothy youtube", "smoothy#multiverse"] + + def wt_(self): + node = bs.newnode('text', + attrs={ + 'text': self.wthighlights[self.wtindex], + 'flatness': 1.0, + 'h_align': 'center', + 'v_attach': 'bottom', + 'scale': 0.7, + 'position': (0, 20), + 'color': (0.5, 0.5, 0.5) + }) + + self.delt = bs.timer(4, node.delete) + self.wtindex = int((self.wtindex+1) % len(self.wthighlights)) + + def get_instance_description(self) -> Union[str, Sequence]: + return 'Crush ${ARG1} of your enemies.', self._score_to_win + + def get_instance_description_short(self) -> Union[str, Sequence]: + return 'kill ${ARG1} enemies', self._score_to_win + + def on_team_join(self, team: Team) -> None: + if self.has_begun(): + self._update_scoreboard() + + def on_begin(self) -> None: + super().on_begin() + self.setup_standard_time_limit(self._time_limit) + self.setup_standard_powerup_drops() + + # 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() + RollingEgg((0.5, 2.7, -4), 1.5) + RollingEgg((0.5, 2.7, -4), 2) + RollingEgg((0.5, 2.7, -4), 2.5) + RollingEgg((0.5, 2.7, -4), 3) + RollingEgg((0.5, 2.5, -4), 3.5) + RollingEgg((0.5, 2.5, -4), 4) + RollingEgg((0.5, 2.5, -4), 4.5) + RollingEgg((0.5, 2.5, -4), 5) + RollingEgg((0.5, 2.5, -4), 5.5) + + 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 + + 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) + + +class RollingEgg(bs.Actor): + def __init__(self, position, radius): + super().__init__() + shared = SharedObjects.get() + factory = SpazFactory.get() + self._spawn_pos = position + self.powerup_material = bs.Material() + self.powerup_material.add_actions( + conditions=('they_have_material', shared.player_material), + actions=( + ('modify_part_collision', 'collide', True), + ('modify_part_collision', 'physical', False), + ('message', 'our_node', 'at_connect', _TouchedMessage()), + ), + ) + self.direction = (0, 0, 0) + pmats = [shared.object_material, self.powerup_material] + self.node = bs.newnode('prop', + delegate=self, + attrs={ + 'mesh': bs.getmesh('egg'), + 'color_texture': bs.gettexture(random.choice(['eggTex1', 'eggTex2', 'eggTex3'])), + 'body': 'sphere', + 'reflection': 'soft', + 'reflection_scale': [0.2], + 'gravity_scale': 0.3, + 'mesh_scale': 0.5, + 'body_scale': 0.6, + 'shadow_size': 0.5, + 'is_area_of_interest': True, + 'position': position, + 'materials': pmats + }) + self.radius = radius + self.center = position + self.angle = 0 + self.surroundTimer = bs.Timer(0.3, self.update, repeat=True) + self.delta_time = 0.3 + self.angular_speed = math.pi / 2 + + def update(self): + # Calculate new angle based on time + self.angle += self.delta_time + + # Calculate new position + new_x = self.center[0] + self.radius * math.cos(self.angle) + new_z = self.center[2] + self.radius * math.sin(self.angle) + new_y = self.node.position[1] # rotation around the Y-axis + + new_position = (new_x, new_y, new_z) + + # Calculate velocity + self.direction = [new_position[i] - self.node.position[i] + for i in range(3)] + velocity = [self.direction[i] / self.delta_time for i in range(3)] + + self.node.velocity = velocity + + @override + def handlemessage(self, msg: Any) -> Any: + if isinstance(msg, bs.DieMessage): + if self.node: + self.node.position = self._spawn_pos + elif isinstance(msg, _TouchedMessage): + + node = bs.getcollision().opposingnode + node.handlemessage( + bs.HitMessage( + velocity=self.node.velocity, + velocity_magnitude=90, + radius=0, + srcnode=self.node, + force_direction=self.direction, + hit_type='punch', + ) + ) + elif isinstance(msg, bs.OutOfBoundsMessage): + assert self.node + self.node.position = self._spawn_pos + else: + return super().handlemessage(msg) diff --git a/dist/ba_root/mods/games/wooden_floor.py b/dist/ba_root/mods/games/wooden_floor.py new file mode 100644 index 0000000..8b14883 --- /dev/null +++ b/dist/ba_root/mods/games/wooden_floor.py @@ -0,0 +1,217 @@ +from __future__ import annotations + +from typing import TYPE_CHECKING + +import babase +import bauiv1 as bui +import bascenev1 as bs +from bascenev1lib.gameutils import SharedObjects +from bascenev1lib.actor.playerspaz import PlayerSpaz +import copy +if TYPE_CHECKING: + from typing import Any, List, Dict + + +class mapdefs: + points = {} + # noinspection PyDictCreation + boxes = {} + boxes['area_of_interest_bounds'] = (0.0, 1.185751251, 0.4326226188) + ( + 0.0, 0.0, 0.0) + (29.8180273, 11.57249038, 18.89134176) + boxes['edge_box'] = (-0.103873591, 0.4133341891, 0.4294651013) + ( + 0.0, 0.0, 0.0) + (22.48295719, 1.290242794, 8.990252454) + points['ffa_spawn1'] = (-0.08015551329, 0.02275111462, + -4.373674593) + (8.895057015, 1.0, 0.444350722) + points['ffa_spawn2'] = (-0.08015551329, 0.02275111462, + 4.076288941) + (8.895057015, 1.0, 0.444350722) + points['flag1'] = (-10.99027878, 0.05744967453, 0.1095578275) + points['flag2'] = (11.01486398, 0.03986567039, 0.1095578275) + points['flag_default'] = (-0.1001374046, 0.04180340146, 0.1095578275) + boxes['goal1'] = (12.22454533, 1.0, + 0.1087926362) + (0.0, 0.0, 0.0) + (2.0, 2.0, 12.97466313) + boxes['goal2'] = (-12.15961605, 1.0, + 0.1097860203) + (0.0, 0.0, 0.0) + (2.0, 2.0, 13.11856424) + boxes['map_bounds'] = (0.0, 1.185751251, 0.4326226188) + (0.0, 0.0, 0.0) + ( + 42.09506485, 22.81173179, 29.76723155) + points['powerup_spawn1'] = (5.414681236, 0.9515026107, -5.037912441) + points['powerup_spawn2'] = (-5.555402285, 0.9515026107, -5.037912441) + points['powerup_spawn3'] = (5.414681236, 0.9515026107, 5.148223181) + points['powerup_spawn4'] = (-5.737266365, 0.9515026107, 5.148223181) + points['spawn1'] = (-10.03866341, 0.02275111462, 0.0) + (0.5, 1.0, 4.0) + points['spawn2'] = (9.823107149, 0.01092306765, 0.0) + (0.5, 1.0, 4.0) + points['tnt1'] = (-0.08421587483, 0.9515026107, -0.7762602271) + + +class WoodenFloor(bs.Map): + """Stadium map for football games.""" + defs = mapdefs + defs.points['spawn1'] = (-12.03866341, 0.02275111462, + 0.0) + (0.5, 1.0, 4.0) + defs.points['spawn2'] = ( + 12.823107149, 0.01092306765, 0.0) + (0.5, 1.0, 4.0) + name = 'Wooden Floor' + + @classmethod + def get_play_types(cls) -> list[str]: + """Return valid play types for this map.""" + return ['melee', 'football', 'team_flag', 'keep_away'] + + @classmethod + def get_preview_texture_name(cls) -> str: + return 'footballStadiumPreview' + + @classmethod + def on_preload(cls) -> Any: + data: dict[str, Any] = { + + 'mesh_bg': bs.getmesh('doomShroomBG'), + 'bg_vr_fill_mesh': bs.getmesh('natureBackgroundVRFill'), + 'collision_mesh': bs.getcollisionmesh('bridgitLevelCollide'), + 'tex': bs.gettexture('bridgitLevelColor'), + 'mesh_bg_tex': bs.gettexture('doomShroomBGColor'), + 'collide_bg': bs.getcollisionmesh('natureBackgroundCollide'), + 'railing_collision_mesh': + (bs.getcollisionmesh('bridgitLevelRailingCollide')), + 'bg_material': bs.Material() + } + data['bg_material'].add_actions(actions=('modify_part_collision', + 'friction', 10.0)) + return data + + def __init__(self) -> None: + super().__init__() + shared = SharedObjects.get() + self.background = bs.newnode( + 'terrain', + attrs={ + 'mesh': self.preloaddata['mesh_bg'], + 'lighting': False, + 'background': True, + 'color_texture': self.preloaddata['mesh_bg_tex'] + }) + bs.newnode('terrain', + attrs={ + 'mesh': self.preloaddata['bg_vr_fill_mesh'], + 'lighting': False, + 'vr_only': True, + 'background': True, + 'color_texture': self.preloaddata['mesh_bg_tex'] + }) + gnode = bs.getactivity().globalsnode + gnode.tint = (1.3, 1.2, 1.0) + gnode.ambient_color = (1.3, 1.2, 1.0) + gnode.vignette_outer = (0.57, 0.57, 0.57) + gnode.vignette_inner = (0.9, 0.9, 0.9) + gnode.vr_camera_offset = (0, -0.8, -1.1) + gnode.vr_near_clip = 0.5 + # self.map_extend() + + def is_point_near_edge(self, + point: babase.Vec3, + running: bool = False) -> bool: + box_position = self.defs.boxes['edge_box'][0:3] + box_scale = self.defs.boxes['edge_box'][6:9] + xpos = (point.x - box_position[0]) / box_scale[0] + zpos = (point.z - box_position[2]) / box_scale[2] + return xpos < -0.5 or xpos > 0.5 or zpos < -0.5 or zpos > 0.5 + + def map_extend(self): + pass + # p=[-6,-4.3,-2.6,-0.9,0.8,2.5,4.2,5.9] + # q=[-4,-2.3,-0.6,1.1,2.8,4.5,6.2] + # for i in p: + # for j in q: + # self.create_ramp(i,j) + + # self.create_ramp(10.9) + # self.ground() + + def ground(self): + shared = SharedObjects.get() + self._real_wall_material = bs.Material() + + self._real_wall_material.add_actions( + + actions=( + ('modify_part_collision', 'collide', True), + ('modify_part_collision', 'physical', True) + + )) + self.mat = bs.Material() + self.mat.add_actions( + + actions=(('modify_part_collision', 'physical', False), + ('modify_part_collision', 'collide', False)) + ) + spaz_collide_mat = bs.Material() + spaz_collide_mat.add_actions( + conditions=('they_have_material', shared.player_material), + actions=( + ('modify_part_collision', 'collide', True), + ('call', 'at_connect', babase.Call(self._handle_player_collide)), + ), + ) + pos = (0, 0.1, -5) + self.main_region = bs.newnode('region', attrs={'position': pos, 'scale': (21, 0.001, 20), 'type': 'box', 'materials': [ + shared.footing_material, self._real_wall_material, spaz_collide_mat]}) + + def create_ramp_111(self, x, z): + + shared = SharedObjects.get() + self._real_wall_material = bs.Material() + + self._real_wall_material.add_actions( + + actions=( + ('modify_part_collision', 'collide', True), + ('modify_part_collision', 'physical', True) + + )) + self.mat = bs.Material() + self.mat.add_actions( + + actions=(('modify_part_collision', 'physical', False), + ('modify_part_collision', 'collide', False)) + ) + spaz_collide_mat = bs.Material() + + pos = (x, 0, z) + ud_1_r = bs.newnode('region', attrs={'position': pos, 'scale': ( + 1.5, 1, 1.5), 'type': 'box', 'materials': [shared.footing_material, self._real_wall_material]}) + + node = bs.newnode('prop', + owner=ud_1_r, + attrs={ + 'mesh': bs.getmesh('image1x1'), + 'light_mesh': bs.getmesh('powerupSimple'), + 'position': (2, 7, 2), + 'body': 'puck', + 'shadow_size': 0.0, + 'velocity': (0, 0, 0), + 'color_texture': bs.gettexture('tnt'), + 'mesh_scale': 1.5, + 'reflection_scale': [1.5], + 'materials': [self.mat, shared.object_material, shared.footing_material], + 'density': 9000000000 + }) + mnode = bs.newnode('math', + owner=ud_1_r, + attrs={ + 'input1': (0, 0.6, 0), + 'operation': 'add' + }) + node.changerotation(1, 0, 0) + ud_1_r.connectattr('position', mnode, 'input2') + mnode.connectattr('output', node, 'position') + + def _handle_player_collide(self): + try: + player = bs.getcollision().opposingnode.getdelegate( + PlayerSpaz, True) + except bs.NotFoundError: + return + if player.is_alive(): + player.shatter(True) + + +bs._map.register_map(WoodenFloor) diff --git a/dist/ba_root/mods/maps/bridgit_mash.py b/dist/ba_root/mods/maps/bridgit_mash.py new file mode 100644 index 0000000..f65b508 --- /dev/null +++ b/dist/ba_root/mods/maps/bridgit_mash.py @@ -0,0 +1,236 @@ +from __future__ import annotations + +from typing import TYPE_CHECKING + +import babase +import bauiv1 as bui +import bascenev1 as bs +from bascenev1lib.gameutils import SharedObjects +from bascenev1lib.actor.playerspaz import PlayerSpaz +import random +if TYPE_CHECKING: + from typing import Any, List, Dict + + +class mapdefs: + points = {} + # noinspection PyDictCreation + boxes = {} + boxes['area_of_interest_bounds'] = (0.0, 1.185751251, 0.4326226188) + ( + 0.0, 0.0, 0.0) + (29.8180273, 11.57249038, 18.89134176) + boxes['edge_box'] = (-0.103873591, 0.4133341891, 0.4294651013) + ( + 0.0, 0.0, 0.0) + (22.48295719, 1.290242794, 8.990252454) + points['ffa_spawn1'] = (-0.08015551329, 0.02275111462, + -4.373674593) + (8.895057015, 1.0, 0.444350722) + points['ffa_spawn2'] = (-0.08015551329, 0.02275111462, + 4.076288941) + (8.895057015, 1.0, 0.444350722) + points['flag1'] = (-10.99027878, 0.05744967453, 0.1095578275) + points['flag2'] = (11.01486398, 0.03986567039, 0.1095578275) + points['flag_default'] = (-0.1001374046, 0.04180340146, 0.1095578275) + boxes['goal1'] = (12.22454533, 1.0, + 0.1087926362) + (0.0, 0.0, 0.0) + (2.0, 2.0, 12.97466313) + boxes['goal2'] = (-12.15961605, 1.0, + 0.1097860203) + (0.0, 0.0, 0.0) + (2.0, 2.0, 13.11856424) + boxes['map_bounds'] = (0.0, 1.185751251, 0.4326226188) + (0.0, 0.0, 0.0) + ( + 42.09506485, 22.81173179, 29.76723155) + points['powerup_spawn1'] = (5.414681236, 0.9515026107, -5.037912441) + points['powerup_spawn2'] = (-5.555402285, 0.9515026107, -5.037912441) + points['powerup_spawn3'] = (5.414681236, 0.9515026107, 5.148223181) + points['powerup_spawn4'] = (-5.737266365, 0.9515026107, 5.148223181) + points['spawn1'] = (-10.03866341, 0.02275111462, 0.0) + (0.5, 1.0, 4.0) + points['spawn2'] = (9.823107149, 0.01092306765, 0.0) + (0.5, 1.0, 4.0) + points['tnt1'] = (-0.08421587483, 0.9515026107, -0.7762602271) + + +class BridgitMash(bs.Map): + """Stadium map for football games.""" + defs = mapdefs + defs.points['spawn1'] = (-12.03866341, 0.02275111462, + 0.0) + (0.5, 1.0, 4.0) + defs.points['spawn2'] = ( + 12.823107149, 0.01092306765, 0.0) + (0.5, 1.0, 4.0) + + defs.points["flag1"] = (-9.6, 0.747, -2.949) + defs.points["flag2"] = (9.6, 0.747, 3.15) + defs.points["flag3"] = (-9.6, 0.747, 3.15) + defs.points["flag4"] = (-0.1, 0.747, -2.949) + defs.points["flag5"] = (-0.1, 0.747, 0.152) + defs.points["flag6"] = (-0.1, 0.747, 3.15) + defs.points["flag7"] = (9.6, 0.747, -2.949) + defs.points["flag8"] = (9.6, 0.747, 0.152) + defs.points["flag9"] = (-9.6, 0.747, 0.152) + + defs.points["spawn_by_flag1"] = (-9.6, 0.747, -2.949) + defs.points["spawn_by_flag2"] = (9.6, 0.747, 3.15) + defs.points["spawn_by_flag3"] = (-9.6, 0.747, 3.15) + defs.points["spawn_by_flag4"] = (-0.1, 0.747, -2.949) + defs.points["spawn_by_flag5"] = (-0.1, 0.747, 0.152) + defs.points["spawn_by_flag6"] = (-0.1, 0.747, 3.15) + defs.points["spawn_by_flag7"] = (9.6, 0.747, -2.949) + defs.points["spawn_by_flag8"] = (9.6, 0.747, 0.152) + defs.points["spawn_by_flag9"] = (-9.6, 0.747, 0.152) + + name = 'Bridgit Mash' + + @classmethod + def get_play_types(cls) -> list[str]: + """Return valid play types for this map.""" + return ['melee', 'football', 'team_flag', 'keep_away', 'conquest'] + + @classmethod + def get_preview_texture_name(cls) -> str: + return 'footballStadiumPreview' + + @classmethod + def on_preload(cls) -> Any: + data: dict[str, Any] = { + 'mesh': bs.getmesh('footballStadium'), + 'vr_fill_mesh': bs.getmesh('footballStadiumVRFill'), + 'collision_mesh': bs.getcollisionmesh('footballStadiumCollide'), + 'tex': bs.gettexture('footballStadium') + } + return data + + def __init__(self) -> None: + super().__init__() + shared = SharedObjects.get() + # TODO vr fill data + gnode = bs.getactivity().globalsnode + gnode.tint = (1.3, 1.2, 1.0) + gnode.ambient_color = (1.3, 1.2, 1.0) + gnode.vignette_outer = (0.57, 0.57, 0.57) + gnode.vignette_inner = (0.9, 0.9, 0.9) + gnode.vr_camera_offset = (0, -0.8, -1.1) + gnode.vr_near_clip = 0.5 + cols = [(0.10, 0.3, 0.5), (0.6, 0.3, 0.6), (0.6, 0.3, 0.1), + (0.2, 0.4, 0.1), (0.4, 0.3, 0.7), (0.10, 0.3, 0.5)] + self.background = bs.newnode( + 'terrain', + attrs={ + 'mesh': bs.getmesh('natureBackground'), + 'lighting': False, + 'background': True, + 'color': cols[random.randrange(0, 6)] + }) + self.map_extend() + + def is_point_near_edge(self, + point: babase.Vec3, + running: bool = False) -> bool: + box_position = self.defs.boxes['edge_box'][0:3] + box_scale = self.defs.boxes['edge_box'][6:9] + xpos = (point.x - box_position[0]) / box_scale[0] + zpos = (point.z - box_position[2]) / box_scale[2] + return xpos < -0.5 or xpos > 0.5 or zpos < -0.5 or zpos > 0.5 + + def map_extend(self): + self.create_ramp(0, 0) + self.create_ramp(10.9, 0) + self.create_ramp(0, -3) + self.create_ramp(10.9, -2.8) + self.create_ramp(0, 3.0) + self.create_ramp(10.9, 3.2) + self.ground() + # _babase.prop_axis(1, 0, 0) + + def ground(self): + shared = SharedObjects.get() + self._real_wall_material = bs.Material() + + self._real_wall_material.add_actions( + + actions=( + ('modify_part_collision', 'collide', True), + ('modify_part_collision', 'physical', True) + )) + self.mat = bs.Material() + self.mat.add_actions( + + actions=(('modify_part_collision', 'physical', False), + ('modify_part_collision', 'collide', False)) + ) + + def create_ramp(self, loc, z_marg): + # try: + # _babase.prop_axis(0, 0, 0) + # except: + # pass + shared = SharedObjects.get() + self._real_wall_material = bs.Material() + + self._real_wall_material.add_actions( + + actions=( + ('modify_part_collision', 'collide', True), + ('modify_part_collision', 'physical', True) + + )) + self.mat = bs.Material() + self.mat.add_actions( + + actions=(('modify_part_collision', 'physical', False), + ('modify_part_collision', 'collide', False)) + ) + spaz_collide_mat = bs.Material() + # spaz_collide_mat.add_actions( + # conditions=('they_have_material',shared.player_material), + # actions=( + # ('modify_part_collision', 'collide', True), + # ( 'call','at_connect',babase.Call(self._handle_player_pad_collide,real )), + # ), + # ) + pos = (-5.3 + loc, 0.7, 1.1+z_marg) + self.ud_1_r = bs.newnode('region', attrs={'position': pos, 'scale': ( + 2, 1, 2), 'type': 'box', 'materials': [shared.footing_material, spaz_collide_mat]}) + + self.node = bs.newnode('prop', + owner=self.ud_1_r, + attrs={ + 'mesh': bs.getmesh('bridgitLevelTop'), + 'light_mesh': bs.getmesh('powerupSimple'), + 'position': (2, 7, 2), + 'body': 'puck', + 'shadow_size': 0.0, + 'velocity': (0, 0, 0), + 'color_texture': bs.gettexture('bridgitLevelColor'), + 'mesh_scale': 0.72, + 'reflection_scale': [1.5], + 'materials': [self.mat, shared.object_material, shared.footing_material], + + 'density': 9000000000 + }) + self.node.changerotation(0, 0, 0) + mnode = bs.newnode('math', + owner=self.ud_1_r, + attrs={ + 'input1': (0, -2.9, 0), + 'operation': 'add' + }) + + self.ud_1_r.connectattr('position', mnode, 'input2') + mnode.connectattr('output', self.node, 'position') + + # /// region to stand long bar =============== + + pos = (-9.67+loc, 0.1, 0+z_marg) + self.left_region = bs.newnode('region', attrs={'position': pos, 'scale': (2.4, 0.7, 3.2), 'type': 'box', 'materials': [ + shared.footing_material, self._real_wall_material, spaz_collide_mat]}) + + pos = (-5.67+loc, 0.1, 0+z_marg) + self.center_region = bs.newnode('region', attrs={'position': pos, 'scale': ( + 8, 0.7, 1), 'type': 'box', 'materials': [shared.footing_material, self._real_wall_material, spaz_collide_mat]}) + pos = (-1.3+loc, 0.1, 0+z_marg) + self.right_region = bs.newnode('region', attrs={'position': pos, 'scale': (2.4, 0.7, 3.2), 'type': 'box', 'materials': [ + shared.footing_material, self._real_wall_material, spaz_collide_mat]}) + + def _handle_player_collide(self): + try: + player = bs.getcollision().opposingnode.getdelegate( + PlayerSpaz, True) + except bs.NotFoundError: + return + if player.is_alive(): + player.shatter(True) + + +bs._map.register_map(BridgitMash) diff --git a/dist/ba_root/mods/maps/bridgit_parallelo.py b/dist/ba_root/mods/maps/bridgit_parallelo.py new file mode 100644 index 0000000..149e9e0 --- /dev/null +++ b/dist/ba_root/mods/maps/bridgit_parallelo.py @@ -0,0 +1,259 @@ +from __future__ import annotations + +from typing import TYPE_CHECKING + +import babase +import bauiv1 as bui +import bascenev1 as bs +from bascenev1lib.gameutils import SharedObjects +import copy +if TYPE_CHECKING: + from typing import Any, List, Dict + + +class mapdefs: + points = {} + # noinspection PyDictCreation + boxes = {} + boxes['area_of_interest_bounds'] = (-0.2457963347, 3.828181068, + -1.528362695) + (0.0, 0.0, 0.0) + ( + 19.14849937, 7.312788846, 8.436232726) + points['ffa_spawn1'] = (-5.869295124, 3.715437928, + -1.617274877) + (0.9410329222, 1.0, 1.818908238) + points['ffa_spawn2'] = (5.160809653, 3.761793434, + -1.443012115) + (0.7729807005, 1.0, 1.818908238) + points['ffa_spawn3'] = (-0.4266381164, 3.761793434, + -1.555562653) + (4.034151421, 1.0, 0.2731725824) + points['flag1'] = (-7.354603923, 3.770769731, -1.617274877) + points['flag2'] = (6.885846926, 3.770685211, -1.443012115) + points['flag_default'] = (-0.2227795102, 3.802429326, -1.562586233) + boxes['map_bounds'] = (-0.1916036665, 7.481446847, -1.311948055) + ( + 0.0, 0.0, 0.0) + (27.41996888, 18.47258973, 19.52220249) + points['powerup_spawn1'] = (6.82849491, 4.658454461, 0.1938139802) + points['powerup_spawn2'] = (-7.253381358, 4.728692078, 0.252121017) + points['powerup_spawn3'] = (6.82849491, 4.658454461, -3.461765427) + points['powerup_spawn4'] = (-7.253381358, 4.728692078, -3.40345839) + points['shadow_lower_bottom'] = (-0.2227795102, 2.83188898, 2.680075641) + points['shadow_lower_top'] = (-0.2227795102, 3.498267184, 2.680075641) + points['shadow_upper_bottom'] = (-0.2227795102, 6.305086402, 2.680075641) + points['shadow_upper_top'] = (-0.2227795102, 9.470923628, 2.680075641) + points['spawn1'] = (-5.869295124, 3.715437928, + -1.617274877) + (0.9410329222, 1.0, 1.818908238) + points['spawn2'] = (5.160809653, 3.761793434, + -1.443012115) + (0.7729807005, 1.0, 1.818908238) + + +class BridgitParallelo(bs.Map): + """Map with a narrow bridge in the middle.""" + defs = mapdefs + defs.points['powerup_spawn4'] = (-7.253381358, 4.728692078, -6.40345839) + defs.points['powerup_spawn3'] = (6.82849491, 4.658454461, -6.461765427) + defs.points['spawn1'] = (-5.869295124, 3.715437928, + -3.617274877) + (0.9410329222, 1.0, 0.818908238) + defs.boxes['area_of_interest_bounds'] = (-0.2457963347, 3.828181068, + -3.528362695) + (0.0, 0.0, 0.0) + ( + 19.14849937, 7.312788846, 6.436232726) + + name = 'Bridgit Parallelo' + dataname = 'bridgit' + + @classmethod + def get_play_types(cls) -> list[str]: + """Return valid play types for this map.""" + # print('getting playtypes', cls._getdata()['play_types']) + return ['melee', 'team_flag', 'keep_away'] + + @classmethod + def get_preview_texture_name(cls) -> str: + return 'bridgitPreview' + + @classmethod + def on_preload(cls) -> Any: + data: dict[str, Any] = { + 'mesh_top': bs.getmesh('bridgitLevelTop'), + 'mesh_bottom': bs.getmesh('bridgitLevelBottom'), + 'mesh_bg': bs.getmesh('natureBackground'), + 'bg_vr_fill_mesh': bs.getmesh('natureBackgroundVRFill'), + 'collision_mesh': bs.getcollisionmesh('bridgitLevelCollide'), + 'tex': bs.gettexture('bridgitLevelColor'), + 'mesh_bg_tex': bs.gettexture('natureBackgroundColor'), + 'collide_bg': bs.getcollisionmesh('natureBackgroundCollide'), + 'railing_collision_mesh': + (bs.getcollisionmesh('bridgitLevelRailingCollide')), + 'bg_material': bs.Material() + } + data['bg_material'].add_actions(actions=('modify_part_collision', + 'friction', 10.0)) + return data + + def __init__(self) -> None: + super().__init__() + shared = SharedObjects.get() + self.node = bs.newnode( + 'terrain', + delegate=self, + attrs={ + 'collision_mesh': self.preloaddata['collision_mesh'], + 'mesh': self.preloaddata['mesh_top'], + 'color_texture': self.preloaddata['tex'], + 'materials': [shared.footing_material] + }) + self.bottom = bs.newnode('terrain', + attrs={ + 'mesh': self.preloaddata['mesh_bottom'], + 'lighting': False, + 'color_texture': self.preloaddata['tex'] + }) + self.background = bs.newnode( + 'terrain', + attrs={ + 'mesh': self.preloaddata['mesh_bg'], + 'lighting': False, + 'background': True, + 'color_texture': self.preloaddata['mesh_bg_tex'] + }) + bs.newnode('terrain', + attrs={ + 'mesh': self.preloaddata['bg_vr_fill_mesh'], + 'lighting': False, + 'vr_only': True, + 'background': True, + 'color_texture': self.preloaddata['mesh_bg_tex'] + }) + # self.railing = bs.newnode( + # 'terrain', + # attrs={ + # 'collision_mesh': self.preloaddata['railing_collision_mesh'], + # 'materials': [shared.railing_material], + # 'bumper': False + # }) + self.bg_collide = bs.newnode('terrain', + attrs={ + 'collision_mesh': + self.preloaddata['collide_bg'], + 'materials': [ + shared.footing_material, + self.preloaddata['bg_material'], + shared.death_material + ] + }) + gnode = bs.getactivity().globalsnode + gnode.tint = (1.1, 1.2, 1.3) + gnode.ambient_color = (1.1, 1.2, 1.3) + gnode.vignette_outer = (0.65, 0.6, 0.55) + gnode.vignette_inner = (0.9, 0.9, 0.93) + self.map_extend() + + def is_point_near_edge(self, + point: babase.Vec3, + running: bool = False) -> bool: + box_position = self.defs.boxes['edge_box'][0:3] + box_scale = self.defs.boxes['edge_box'][6:9] + xpos = (point.x - box_position[0]) / box_scale[0] + zpos = (point.z - box_position[2]) / box_scale[2] + return xpos < -0.5 or xpos > 0.5 or zpos < -0.5 or zpos > 0.5 + + def map_extend(self): + + shared = SharedObjects.get() + self._real_wall_material = bs.Material() + + self._real_wall_material.add_actions( + + actions=( + ('modify_part_collision', 'collide', True), + ('modify_part_collision', 'physical', True) + + )) + self.mat = bs.Material() + self.mat.add_actions( + + actions=(('modify_part_collision', 'physical', False), + ('modify_part_collision', 'collide', False)) + ) + spaz_collide_mat = bs.Material() + # spaz_collide_mat.add_actions( + # conditions=('they_have_material',shared.player_material), + # actions=( + # ('modify_part_collision', 'collide', True), + # ( 'call','at_connect',babase.Call(self._handle_player_pad_collide,real )), + # ), + # ) + pos = (0.0, 3.004164695739746, -3.3991328477859497) + self.ud_1_r = bs.newnode('region', attrs={'position': pos, 'scale': (2, 1, 2), 'type': 'box', 'materials': [ + shared.footing_material, self._real_wall_material, spaz_collide_mat]}) + + self.node = bs.newnode('prop', + owner=self.ud_1_r, + attrs={ + 'mesh': bs.getmesh('bridgitLevelTop'), + 'light_mesh': bs.getmesh('powerupSimple'), + 'position': (2, 7, 2), + 'body': 'puck', + 'shadow_size': 0.0, + 'velocity': (0, 0, 0), + 'color_texture': bs.gettexture('bridgitLevelColor'), + + 'reflection_scale': [1.5], + 'materials': [self.mat, shared.object_material, shared.footing_material], + + 'density': 9000000000 + }) + self.node.changerotation(0, 0, 0) + mnode = bs.newnode('math', + owner=self.ud_1_r, + attrs={ + 'input1': (0, -2.9, 0), + 'operation': 'add' + }) + + self.ud_1_r.connectattr('position', mnode, 'input2') + mnode.connectattr('output', self.node, 'position') + + # base / bottom ==================================== + + pos = (0.0, 2.004164695739746, -3.3991328477859497) + self.ud_2_r = bs.newnode('region', attrs={'position': pos, 'scale': (2, 1, 2), 'type': 'box', 'materials': [ + shared.footing_material, self._real_wall_material, spaz_collide_mat]}) + + self.node2 = bs.newnode('prop', + owner=self.ud_2_r, + attrs={ + 'mesh': bs.getmesh('bridgitLevelBottom'), + 'light_mesh': bs.getmesh('powerupSimple'), + 'position': (2, 7, 2), + 'body': 'puck', + 'shadow_size': 0.0, + 'velocity': (0, 0, 0), + 'color_texture': bs.gettexture('bridgitLevelColor'), + + 'reflection_scale': [1.5], + 'materials': [self.mat, shared.object_material, shared.footing_material], + + 'density': 9000000000 + }) + mnode = bs.newnode('math', + owner=self.ud_2_r, + attrs={ + 'input1': (0, -1.8, 0), + 'operation': 'add' + }) + + self.ud_2_r.connectattr('position', mnode, 'input2') + mnode.connectattr('output', self.node2, 'position') + + # /// region to stand long bar =============== + + pos = (-6.25, 3.204164695739746, -5.3991328477859497) + self.v_region = bs.newnode('region', attrs={'position': pos, 'scale': (3.4, 1, 4), 'type': 'box', 'materials': [ + shared.footing_material, self._real_wall_material, spaz_collide_mat]}) + + pos = (0.5, 3.204164695739746, -4.7991328477859497) + self.h_1_region = bs.newnode('region', attrs={'position': pos, 'scale': (12, 1, 1.4), 'type': 'box', 'materials': [ + shared.footing_material, self._real_wall_material, spaz_collide_mat]}) + pos = (5.6, 3.204164695739746, -5.3991328477859497) + self.h_2_region = bs.newnode('region', attrs={'position': pos, 'scale': (3.4, 1, 4), 'type': 'box', 'materials': [ + shared.footing_material, self._real_wall_material, spaz_collide_mat]}) + + +bs._map.register_map(BridgitParallelo)