diff --git a/plugins/minigames.json b/plugins/minigames.json index c0e19a8..8cf7288 100644 --- a/plugins/minigames.json +++ b/plugins/minigames.json @@ -21,6 +21,25 @@ "md5sum": "f4f0bb91f5d10cf8f591ecf7d2848182" } } + }, + "volleyball": { + "description": "Play Volleyball in teams of two", + "external_url": "", + "authors": [ + { + "name": "Freaku", + "email": "", + "discord": "[Just] Freak#4999" + } + ], + "versions": { + "1.1.0": { + "api_version": 7, + "commit_sha": "0553bb9", + "released_on": "31-08-2022", + "md5sum": "9cd1416e086597684ceb17a5712791b1" + } + } } } } \ No newline at end of file diff --git a/plugins/minigames/volleyball.py b/plugins/minigames/volleyball.py new file mode 100644 index 0000000..5d8907a --- /dev/null +++ b/plugins/minigames/volleyball.py @@ -0,0 +1,743 @@ +# Volley Ball (final) + +# Made by your friend: Freaku / @[Just] Freak#4999 + + +# Join BCS: +# https://discord.gg/ucyaesh + + +# My GitHub: +# https://github.com/Freaku17/BombSquad-Mods-byFreaku + + +# CHANGELOG: +""" +## 2021 +- Fixed Puck's mass/size/positions/texture/effects +- Fixed Goal positions +- Better center wall +- Added 1 more map +- Added more customisable options +- Map lights locators are now looped (thus reducing the size of the file and lengthy work...) +- Merged map & minigame in one file +- Puck spawns according to scored team +- Also puck now spawns in airrr +- Server support added :) +- Fixed **LOTS** of errors/bugs + +## 2022 +- Code cleanup +- No longer requires a plugin +- More accurate Goal positions +""" + + +# ba_meta require api 7 + +from __future__ import annotations + +from typing import TYPE_CHECKING + +import _ba +import ba +import random +from bastd.actor.playerspaz import PlayerSpaz +from bastd.actor.scoreboard import Scoreboard +from bastd.actor.powerupbox import PowerupBoxFactory +from bastd.actor.bomb import BombFactory +from bastd.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 + + +class Puck(ba.Actor): + def __init__(self, position: Sequence[float] = (0.0, 1.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.05, position[2]) + self.last_players_to_touch: Dict[int, Player] = {} + self.scored = False + assert activity is not None + assert isinstance(activity, VolleyBallGame) + pmats = [shared.object_material, activity.puck_material] + self.node = ba.newnode('prop', + delegate=self, + attrs={ + 'model': activity.puck_model, + 'color_texture': activity.puck_tex, + 'body': 'sphere', + 'reflection': 'soft', + 'reflection_scale': [0.2], + 'shadow_size': 0.6, + 'model_scale': 0.4, + 'body_scale': 1.07, + 'is_area_of_interest': True, + 'position': self._spawn_pos, + 'materials': pmats + }) + + # Since it rolls on spawn, lets make gravity + # to 0, and when another node (bomb/spaz) + # touches it. It'll act back as our normie puck! + ba.animate(self.node, 'gravity_scale', {0: -0.1, 0.2: 1}, False) + # When other node touches, it realises its new gravity_scale + + def handlemessage(self, msg: Any) -> Any: + if isinstance(msg, ba.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, ba.OutOfBoundsMessage): + assert self.node + self.node.position = self._spawn_pos + + elif isinstance(msg, ba.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(ba.Player['Team']): + """Our player type for this game.""" + + +class Team(ba.Team[Player]): + """Our team type for this game.""" + + def __init__(self) -> None: + self.score = 0 + + +# ba_meta export game +class VolleyBallGame(ba.TeamGameActivity[Player, Team]): + name = 'Volley Ball' + description = 'Score some goals.\nby \ue048Freaku' + available_settings = [ + ba.IntSetting( + 'Score to Win', + min_value=1, + default=1, + increment=1, + ), + ba.IntChoiceSetting( + 'Time Limit', + choices=[ + ('None', 0), + ('1 Minute', 60), + ('2 Minutes', 120), + ('5 Minutes', 300), + ('10 Minutes', 600), + ('20 Minutes', 1200), + ], + default=0, + ), + ba.FloatChoiceSetting( + 'Respawn Times', + choices=[ + ('Shorter', 0.25), + ('Short', 0.5), + ('Normal', 1.0), + ('Long', 2.0), + ('Longer', 4.0), + ], + default=1.0, + ), + ba.BoolSetting('Epic Mode', True), + ba.BoolSetting('Night Mode', False), + ba.BoolSetting('Icy Floor', True), + ba.BoolSetting('Disable Punch', False), + ba.BoolSetting('Disable Bombs', False), + ba.BoolSetting('Enable Bottom Credits', True), + ] + default_music = ba.MusicType.HOCKEY + + @classmethod + def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool: + return issubclass(sessiontype, ba.DualTeamSession) + + @classmethod + def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]: + return ['Open Field', 'Closed Arena'] + + def __init__(self, settings: dict): + super().__init__(settings) + shared = SharedObjects.get() + self._scoreboard = Scoreboard() + self._cheer_sound = ba.getsound('cheer') + self._chant_sound = ba.getsound('crowdChant') + self._foghorn_sound = ba.getsound('foghorn') + self._swipsound = ba.getsound('swip') + self._whistle_sound = ba.getsound('refWhistle') + self.puck_model = ba.getmodel('shield') + self.puck_tex = ba.gettexture('gameCircleIcon') + self._puck_sound = ba.getsound('metalHit') + self.puck_material = ba.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)) + + # 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', ba.DieMessage()))) + self._score_region_material = ba.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._wall_material = ba.Material() + self._fake_wall_material = ba.Material() + self._wall_material.add_actions( + + actions=( + ('modify_part_collision', 'friction', 100000), + )) + self._wall_material.add_actions( + conditions=('they_have_material', shared.pickup_material), + actions=( + ('modify_part_collision', 'collide', False), + )) + + self._wall_material.add_actions( + conditions=(('we_are_younger_than', 100), + 'and', + ('they_have_material', shared.object_material)), + actions=( + ('modify_part_collision', 'collide', False), + )) + self._wall_material.add_actions( + conditions=('they_have_material', shared.footing_material), + actions=( + ('modify_part_collision', 'friction', 9999.5), + )) + self._wall_material.add_actions( + conditions=('they_have_material', BombFactory.get().blast_material), + actions=( + ('modify_part_collision', 'collide', False), + ('modify_part_collision', 'physical', False) + + )) + self._fake_wall_material.add_actions( + conditions=('they_have_material', shared.player_material), + actions=( + ('modify_part_collision', 'collide', True), + ('modify_part_collision', 'physical', True) + + )) + self.blocks = [] + + self._net_wall_material = ba.Material() + self._net_wall_material.add_actions( + conditions=('they_have_material', shared.player_material), + actions=( + ('modify_part_collision', 'collide', True), + ('modify_part_collision', 'physical', True) + + )) + + self._net_wall_material.add_actions( + conditions=('they_have_material', shared.object_material), + actions=( + ('modify_part_collision', 'collide', True), + )) + self._net_wall_material.add_actions( + conditions=('they_have_material', self.puck_material), + actions=( + ('modify_part_collision', 'collide', True), + )) + self._net_wall_material.add_actions( + conditions=('we_are_older_than', 1), + actions=( + ('modify_part_collision', 'collide', True), + )) + self.net_blocc = [] + + self._puck_spawn_pos: Optional[Sequence[float]] = None + self._score_regions: Optional[List[ba.NodeActor]] = None + self._puck: Optional[Puck] = None + self._score_to_win = int(settings['Score to Win']) + self._punchie_ = bool(settings['Disable Punch']) + self._night_mode = bool(settings['Night Mode']) + self._bombies_ = bool(settings['Disable Bombs']) + self._time_limit = float(settings['Time Limit']) + self._icy_flooor = bool(settings['Icy Floor']) + self.credit_text = bool(settings['Enable Bottom Credits']) + self._epic_mode = bool(settings['Epic Mode']) + # Base class overrides. + self.slow_motion = self._epic_mode + self.default_music = (ba.MusicType.EPIC if self._epic_mode else + ba.MusicType.TO_THE_DEATH) + + 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) + if self._night_mode: + ba.getactivity().globalsnode.tint = (0.5, 0.7, 1) + self._puck_spawn_pos = self.map.get_flag_position(None) + self._spawn_puck() + + # Set up the two score regions. + self._score_regions = [] + self._score_regions.append( + ba.NodeActor( + ba.newnode('region', + attrs={ + 'position': (5.7, 0, -0.065), + 'scale': (10.7, 0.001, 8), + 'type': 'box', + 'materials': [self._score_region_material] + }))) + self._score_regions.append( + ba.NodeActor( + ba.newnode('region', + attrs={ + 'position': (-5.7, 0, -0.065), + 'scale': (10.7, 0.001, 8), + 'type': 'box', + 'materials': [self._score_region_material] + }))) + self._update_scoreboard() + ba.playsound(self._chant_sound) + import base64 + exec(base64.b64decode("aWYgc2VsZi5jcmVkaXRfdGV4dDoKICAgICMjIFBlb3BsZSBzdGVhbGVkIGNyZWRpdHMgc28gdGhhdHMgd2h5IEkgZW5jb2RlZCB0aGlzLi4uCiAgICAjIyBFdmVuIHRobyB0aGVyZSBpcyBhIG9wdGlvbiwgdGhleSBjaGFuZ2VkIGNyZWF0ZWQgYnkKICAgICMjIGxpa2Ugd3RmIGlzIHRoaWVyIHByb2JsZW0/PwogICAgCiAgICAjIyBBbnl3YXlzIGhhdmUgYSBnb29kIGRheSEKICAgIHQgPSBiYS5uZXdub2RlKCd0ZXh0JywKICAgICAgICAgICAgICAgYXR0cnM9eyAndGV4dCc6IkNyZWF0ZWQgYnkg7oGIRnJlYWt1XG5Wb2xsZXlCYWxsIiwgIyMgRGlzYWJsZSAnRW5hYmxlIEJvdHRvbSBDcmVkaXRzJyB3aGVuIG1ha2luZyBwbGF5bGlzdCwgTm8gbmVlZCB0byBlZGl0IHRoaXMgbG92ZWx5Li4uCiAgICAgICAgJ3NjYWxlJzowLjcsCiAgICAgICAgJ3Bvc2l0aW9uJzooMCwwKSwgI0xldHMgaG9wZSBoZSB1c2VzIFRWIGJvcmRlciBvZiBzZXR0aW5ncz5HcmFwaGljcwogICAgICAgICdzaGFkb3cnOjAuNSwKICAgICAgICAnZmxhdG5lc3MnOjEuMiwKICAgICAgICAnY29sb3InOigxLCAxLCAxKSwKICAgICAgICAnaF9hbGlnbic6J2NlbnRlcicsCiAgICAgICAgJ3ZfYXR0YWNoJzonYm90dG9tJ30p").decode('UTF-8')) + shared = SharedObjects.get() + self.blocks.append(ba.NodeActor(ba.newnode('region', attrs={'position': (0, 2.4, 0), 'scale': ( + 0.8, 6, 20), 'type': 'box', 'materials': (self._fake_wall_material, )}))) + + self.net_blocc.append(ba.NodeActor(ba.newnode('region', attrs={'position': (0, 0, 0), 'scale': ( + 0.6, 2.4, 20), 'type': 'box', 'materials': (self._net_wall_material, )}))) + + def on_team_join(self, team: Team) -> None: + self._update_scoreboard() + + def _handle_puck_player_collide(self) -> None: + collision = ba.getcollision() + try: + puck = collision.sourcenode.getdelegate(Puck, True) + player = collision.opposingnode.getdelegate(PlayerSpaz, + True).getplayer( + Player, True) + except ba.NotFoundError: + return + + puck.last_players_to_touch[player.team.id] = player + + def _kill_puck(self) -> None: + self._puck = None + + def _handle_score(self) -> None: + 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 = ba.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 + + # Change puck Spawn + if team.id == 0: # left side scored + self._puck_spawn_pos = (5, 0.42, 0) + elif team.id == 1: # right side scored + self._puck_spawn_pos = (-5, 0.42, 0) + else: # normally shouldn't occur + self._puck_spawn_pos = (0, 0.42, 0) + # Easy pizzy + + for player in team.players: + if player.actor: + player.actor.handlemessage(ba.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], + 100, + big_message=True) + + # End game if we won. + if team.score >= self._score_to_win: + self.end_game() + + ba.playsound(self._foghorn_sound) + ba.playsound(self._cheer_sound) + + self._puck.scored = True + + # Kill the puck (it'll respawn itself shortly). + ba.emitfx(position=ba.getcollision().position, count=int( + 6.0 + 7.0 * 12), scale=3, spread=0.5, chunk_type='spark') + ba.timer(0.7, self._kill_puck) + + ba.cameraflash(duration=7.0) + self._update_scoreboard() + + def end_game(self) -> None: + results = ba.GameResults() + for team in self.teams: + results.set_team_score(team, team.score) + self.end(results=results) + + def on_transition_in(self) -> None: + super().on_transition_in() + activity = ba.getactivity() + if self._icy_flooor: + activity.map.is_hockey = True + + def _update_scoreboard(self) -> None: + winscore = self._score_to_win + for team in self.teams: + self._scoreboard.set_team_value(team, team.score, winscore) + + # overriding the default character spawning.. + def spawn_player(self, player: Player) -> ba.Actor: + spaz = self.spawn_player_spaz(player) + + if self._bombies_: + # We want the button to work, just no bombs... + spaz.bomb_count = 0 + # Imagine not being able to swipe those colorful buttons ;( + + if self._punchie_: + spaz.connect_controls_to_player(enable_punch=False) + + return spaz + + def handlemessage(self, msg: Any) -> Any: + + # Respawn dead players if they're still in the game. + if isinstance(msg, ba.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(): + ba.timer(2.2, self._spawn_puck) + else: + super().handlemessage(msg) + + def _flash_puck_spawn(self) -> None: + # Effect >>>>>> Flashly + ba.emitfx(position=self._puck_spawn_pos, count=int( + 6.0 + 7.0 * 12), scale=1.7, spread=0.4, chunk_type='spark') + + def _spawn_puck(self) -> None: + ba.playsound(self._swipsound) + ba.playsound(self._whistle_sound) + self._flash_puck_spawn() + assert self._puck_spawn_pos is not None + self._puck = Puck(position=self._puck_spawn_pos) + + +class Pointzz: + points, boxes = {}, {} + points['spawn1'] = (-8.03866, 0.02275, 0.0) + (0.5, 0.05, 4.0) + points['spawn2'] = (8.82311, 0.01092, 0.0) + (0.5, 0.05, 4.0) + boxes['area_of_interest_bounds'] = (0.0, 1.18575, 0.43262) + \ + (0, 0, 0) + (29.81803, 11.57249, 18.89134) + boxes['map_bounds'] = (0.0, 1.185751251, 0.4326226188) + (0.0, 0.0, 0.0) + ( + 42.09506485, 22.81173179, 29.76723155) + + +class PointzzforH: + points, boxes = {}, {} + boxes['area_of_interest_bounds'] = (0.0, 0.7956858119, 0.0) + \ + (0.0, 0.0, 0.0) + (30.80223883, 0.5961646365, 13.88431707) + boxes['map_bounds'] = (0.0, 0.7956858119, -0.4689020853) + (0.0, 0.0, 0.0) + ( + 35.16182389, 12.18696164, 21.52869693) + points['spawn1'] = (-6.835352227, 0.02305323209, 0.0) + (1.0, 1.0, 3.0) + points['spawn2'] = (6.857415055, 0.03938567998, 0.0) + (1.0, 1.0, 3.0) + + +class VolleyBallMap(ba.Map): + defs = Pointzz() + name = "Open Field" + + @classmethod + def get_play_types(cls) -> List[str]: + return [] + + @classmethod + def get_preview_texture_name(cls) -> str: + return 'footballStadiumPreview' + + @classmethod + def on_preload(cls) -> Any: + data: Dict[str, Any] = { + 'model': ba.getmodel('footballStadium'), + 'vr_fill_model': ba.getmodel('footballStadiumVRFill'), + 'collide_model': ba.getcollidemodel('footballStadiumCollide'), + 'tex': ba.gettexture('footballStadium') + } + return data + + def __init__(self): + super().__init__() + shared = SharedObjects.get() + x = -5 + while x < 5: + self.zone = ba.newnode('locator', attrs={'shape': 'circle', 'position': (0, 0, x), + 'color': (1, 1, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]}) + self.zone = ba.newnode('locator', attrs={'shape': 'circle', 'position': (0, .25, x), + 'color': (1, 1, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]}) + self.zone = ba.newnode('locator', attrs={'shape': 'circle', 'position': (0, .5, x), + 'color': (1, 1, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]}) + self.zone = ba.newnode('locator', attrs={'shape': 'circle', 'position': (0, .75, x), + 'color': (1, 1, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]}) + self.zone = ba.newnode('locator', attrs={'shape': 'circle', 'position': (0, 1, x), + 'color': (1, 1, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]}) + x = x + 0.5 + + y = -1 + while y > -11: + self.zone = ba.newnode('locator', attrs={'shape': 'circle', 'position': (y, 0.01, 4), + 'color': (0, 0, 1), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]}) + self.zone = ba.newnode('locator', attrs={'shape': 'circle', 'position': (y, 0.01, -4), + 'color': (0, 0, 1), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]}) + self.zone = ba.newnode('locator', attrs={'shape': 'circle', 'position': (-y, 0.01, 4), + 'color': (1, 0, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]}) + self.zone = ba.newnode('locator', attrs={'shape': 'circle', 'position': (-y, 0.01, -4), + 'color': (1, 0, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]}) + y -= 1 + + z = 0 + while z < 5: + self.zone = ba.newnode('locator', attrs={'shape': 'circle', 'position': (11, 0.01, z), + 'color': (1, 0, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]}) + self.zone = ba.newnode('locator', attrs={'shape': 'circle', 'position': (11, 0.01, -z), + 'color': (1, 0, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]}) + self.zone = ba.newnode('locator', attrs={'shape': 'circle', 'position': (-11, 0.01, z), + 'color': (0, 0, 1), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]}) + self.zone = ba.newnode('locator', attrs={'shape': 'circle', 'position': (-11, 0.01, -z), + 'color': (0, 0, 1), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]}) + z += 1 + + self.node = ba.newnode( + 'terrain', + delegate=self, + attrs={ + 'model': self.preloaddata['model'], + 'collide_model': self.preloaddata['collide_model'], + 'color_texture': self.preloaddata['tex'], + 'materials': [shared.footing_material] + }) + ba.newnode('terrain', + attrs={ + 'model': self.preloaddata['vr_fill_model'], + 'lighting': False, + 'vr_only': True, + 'background': True, + 'color_texture': self.preloaddata['tex'] + }) + gnode = ba.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 + + +class VolleyBallMapH(ba.Map): + defs = PointzzforH() + name = 'Closed Arena' + + @classmethod + def get_play_types(cls) -> List[str]: + return [] + + @classmethod + def get_preview_texture_name(cls) -> str: + return 'hockeyStadiumPreview' + + @classmethod + def on_preload(cls) -> Any: + data: Dict[str, Any] = { + 'models': (ba.getmodel('hockeyStadiumOuter'), + ba.getmodel('hockeyStadiumInner')), + 'vr_fill_model': ba.getmodel('footballStadiumVRFill'), + 'collide_model': ba.getcollidemodel('hockeyStadiumCollide'), + 'tex': ba.gettexture('hockeyStadium'), + } + mat = ba.Material() + mat.add_actions(actions=('modify_part_collision', 'friction', 0.01)) + data['ice_material'] = mat + return data + + def __init__(self) -> None: + super().__init__() + shared = SharedObjects.get() + x = -5 + while x < 5: + self.zone = ba.newnode('locator', attrs={'shape': 'circle', 'position': (0, 0, x), + 'color': (1, 1, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]}) + self.zone = ba.newnode('locator', attrs={'shape': 'circle', 'position': (0, .25, x), + 'color': (1, 1, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]}) + self.zone = ba.newnode('locator', attrs={'shape': 'circle', 'position': (0, .5, x), + 'color': (1, 1, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]}) + self.zone = ba.newnode('locator', attrs={'shape': 'circle', 'position': (0, .75, x), + 'color': (1, 1, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]}) + self.zone = ba.newnode('locator', attrs={'shape': 'circle', 'position': (0, 1, x), + 'color': (1, 1, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]}) + x = x + 0.5 + + y = -1 + while y > -11: + self.zone = ba.newnode('locator', attrs={'shape': 'circle', 'position': (y, 0.01, 4), + 'color': (0, 0, 1), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]}) + self.zone = ba.newnode('locator', attrs={'shape': 'circle', 'position': (y, 0.01, -4), + 'color': (0, 0, 1), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]}) + self.zone = ba.newnode('locator', attrs={'shape': 'circle', 'position': (-y, 0.01, 4), + 'color': (1, 0, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]}) + self.zone = ba.newnode('locator', attrs={'shape': 'circle', 'position': (-y, 0.01, -4), + 'color': (1, 0, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]}) + y -= 1 + + z = 0 + while z < 5: + self.zone = ba.newnode('locator', attrs={'shape': 'circle', 'position': (11, 0.01, z), + 'color': (1, 0, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]}) + self.zone = ba.newnode('locator', attrs={'shape': 'circle', 'position': (11, 0.01, -z), + 'color': (1, 0, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]}) + self.zone = ba.newnode('locator', attrs={'shape': 'circle', 'position': (-11, 0.01, z), + 'color': (0, 0, 1), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]}) + self.zone = ba.newnode('locator', attrs={'shape': 'circle', 'position': (-11, 0.01, -z), + 'color': (0, 0, 1), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]}) + z += 1 + + self.node = ba.newnode('terrain', + delegate=self, + attrs={ + 'model': + None, + 'collide_model': + # we dont want Goalposts... + ba.getcollidemodel('footballStadiumCollide'), + 'color_texture': + self.preloaddata['tex'], + 'materials': [ + shared.footing_material] + }) + ba.newnode('terrain', + attrs={ + 'model': self.preloaddata['vr_fill_model'], + 'vr_only': True, + 'lighting': False, + 'background': True, + }) + mats = [shared.footing_material] + self.floor = ba.newnode('terrain', + attrs={ + 'model': self.preloaddata['models'][1], + 'color_texture': self.preloaddata['tex'], + 'opacity': 0.92, + 'opacity_in_low_or_medium_quality': 1.0, + 'materials': mats, + 'color': (0.4, 0.9, 0) + }) + + self.background = ba.newnode( + 'terrain', + attrs={ + 'model': ba.getmodel('natureBackground'), + 'lighting': False, + 'background': True, + 'color': (0.5, 0.30, 0.4) + }) + + gnode = ba.getactivity().globalsnode + gnode.floor_reflection = True + gnode.debris_friction = 0.3 + gnode.debris_kill_height = -0.3 + gnode.tint = (1.2, 1.3, 1.33) + gnode.ambient_color = (1.15, 1.25, 1.6) + gnode.vignette_outer = (0.66, 0.67, 0.73) + gnode.vignette_inner = (0.93, 0.93, 0.95) + gnode.vr_camera_offset = (0, -0.8, -1.1) + gnode.vr_near_clip = 0.5 + #self.is_hockey = True + + +ba._map.register_map(VolleyBallMap) +ba._map.register_map(VolleyBallMapH)