def on_begin(self) -> None: super().on_begin() shared = SharedObjects.get() self.setup_standard_time_limit(self._time_limit) self.setup_standard_powerup_drops() self._flag_pos = self.map.get_flag_position(None) ba.timer(1.0, self._tick, repeat=True) self._flag_state = FlagState.NEW Flag.project_stand(self._flag_pos) self._flag = Flag(position=self._flag_pos, touchable=False, color=(1, 1, 1)) self._flag_light = ba.newnode('light', attrs={ 'position': self._flag_pos, 'intensity': 0.2, 'height_attenuated': False, 'radius': 0.4, 'color': (0.2, 0.2, 0.2) }) # Flag region. flagmats = [self._flag_region_material, shared.region_material] ba.newnode('region', attrs={ 'position': self._flag_pos, 'scale': (1.8, 1.8, 1.8), 'type': 'sphere', 'materials': flagmats }) self._update_flag_state()
def on_begin(self) -> None: super().on_begin() shared = SharedObjects.get() self.setup_standard_time_limit(self._time_limit) self.setup_standard_powerup_drops() self._flag_spawn_pos = self.map.get_flag_position(None) Flag.project_stand(self._flag_spawn_pos) self._set_chosen_one_player(None) pos = self._flag_spawn_pos ba.timer(1.0, call=self._tick, repeat=True) mat = self._reset_region_material = ba.Material() mat.add_actions( conditions=( 'they_have_material', shared.player_material, ), actions=( ('modify_part_collision', 'collide', True), ('modify_part_collision', 'physical', False), ('call', 'at_connect', ba.WeakCall(self._handle_reset_collide)), ), ) self._reset_region = ba.newnode('region', attrs={ 'position': (pos[0], pos[1] + 0.75, pos[2]), 'scale': (0.5, 0.5, 0.5), 'type': 'sphere', 'materials': [mat] })
def __init__(self, position: Tuple[float, float, float] = (0.0, 1.0, 0.0)): super().__init__() activity = self.activity assert isinstance(activity, EasterEggHuntGame) shared = SharedObjects.get() # Spawn just above the provided point. self._spawn_pos = (position[0], position[1] + 1.0, position[2]) ctex = (activity.egg_tex_1, activity.egg_tex_2, activity.egg_tex_3)[random.randrange(3)] mats = [shared.object_material, activity.egg_material] self.node = ba.newnode('prop', delegate=self, attrs={ 'model': activity.egg_model, 'color_texture': ctex, 'body': 'capsule', 'reflection': 'soft', 'model_scale': 0.5, 'body_scale': 0.6, 'density': 4.0, 'reflection_scale': [0.15], 'shadow_size': 0.6, 'position': self._spawn_pos, 'materials': mats })
def __init__(self, item: ba.Node, owner: ba.Node): self.item = item self.owner = owner self.node: ba.Node self.target: Optional[ba.Node] = None self.aim_zone: ba.Material = ba.Material() shared = SharedObjects.get() self.aim_zone.add_actions( conditions=(('they_have_material', shared.player_material)), actions=(('modify_part_collision', 'collide', True), ('modify_part_collision', 'physical', False), ('call', 'at_connect', self._touch_handler))) # raise the item a little self.item.extra_acceleration = (0, 20, 0) # if the item exists, then take its position, # else "turn the bench" if self.item.exists(): position = self.item.position else: return self.node = ba.newnode('region', attrs={ 'type': 'sphere', 'position': position, 'materials': [self.aim_zone]}) # aiming effect ba.animate_array(self.node, 'scale', 3, {0: (0.1, 0.1, 0.1), 1: (60, 60, 60)})
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.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 = ba.newnode('prop', delegate=self, attrs={ 'model': activity.puck_model, 'color_texture': activity.puck_tex, 'body': 'puck', 'reflection': 'soft', 'reflection_scale': [0.2], 'shadow_size': 1.0, 'is_area_of_interest': True, 'position': self._spawn_pos, 'materials': pmats }) ba.animate(self.node, 'model_scale', {0: 0, 0.2: 1.3, 0.26: 1})
def __init__(self, settings: dict): settings['map'] = 'Tower D' super().__init__(settings) shared = SharedObjects.get() self._preset = Preset(settings.get('preset', 'pro')) self._player_death_sound = ba.getsound('playerDeath') self._new_wave_sound = ba.getsound('scoreHit01') self._winsound = ba.getsound('score') self._cashregistersound = ba.getsound('cashRegister') self._bad_guy_score_sound = ba.getsound('shieldDown') self._heart_tex = ba.gettexture('heart') self._heart_model_opaque = ba.getmodel('heartOpaque') self._heart_model_transparent = ba.getmodel('heartTransparent') self._a_player_has_been_killed = False self._spawn_center = self._map_type.defs.points['spawn1'][0:3] self._tntspawnpos = self._map_type.defs.points['tnt_loc'][0:3] self._powerup_center = self._map_type.defs.boxes['powerup_region'][0:3] self._powerup_spread = ( self._map_type.defs.boxes['powerup_region'][6] * 0.5, self._map_type.defs.boxes['powerup_region'][8] * 0.5) self._score_region_material = ba.Material() self._score_region_material.add_actions( conditions=('they_have_material', shared.player_material), actions=( ('modify_part_collision', 'collide', True), ('modify_part_collision', 'physical', False), ('call', 'at_connect', self._handle_reached_end), )) self._last_wave_end_time = ba.time() self._player_has_picked_up_powerup = False self._scoreboard: Optional[Scoreboard] = None self._game_over = False self._wavenum = 0 self._can_end_wave = True self._score = 0 self._time_bonus = 0 self._score_region: Optional[ba.Actor] = None self._dingsound = ba.getsound('dingSmall') self._dingsoundhigh = ba.getsound('dingSmallHigh') self._exclude_powerups: Optional[List[str]] = None self._have_tnt: Optional[bool] = None self._waves: Optional[List[Wave]] = None self._bots = SpazBotSet() self._tntspawner: Optional[TNTSpawner] = None self._lives_bg: Optional[ba.NodeActor] = None self._start_lives = 10 self._lives = self._start_lives self._lives_text: Optional[ba.NodeActor] = None self._flawless = True self._time_bonus_timer: Optional[ba.Timer] = None self._time_bonus_text: Optional[ba.NodeActor] = None self._time_bonus_mult: Optional[float] = None self._wave_text: Optional[ba.NodeActor] = None self._flawless_bonus: Optional[int] = None self._wave_update_timer: Optional[ba.Timer] = None
def ice_off_callback(playerdata: PlayerData, args): from bastd.gameutils import SharedObjects shared = SharedObjects.get() activity = ba.getactivity() assert isinstance(activity, ba.GameActivity) activity.map.is_hockey = False activity.map.node.materials = [shared.footing_material] activity.map.floor.materials = [shared.footing_material]
def __init__(self) -> None: """Instantiate a PowerupBoxFactory. You shouldn't need to do this; call ba.Powerup.get_factory() to get a shared instance. """ from ba.internal import get_default_powerup_distribution shared = SharedObjects.get() self._lastpoweruptype: Optional[str] = None self.model = ba.getmodel('powerup') self.model_simple = ba.getmodel('powerupSimple') self.tex_bomb = ba.gettexture('powerupBomb') self.tex_punch = ba.gettexture('powerupPunch') self.tex_ice_bombs = ba.gettexture('powerupIceBombs') self.tex_sticky_bombs = ba.gettexture('powerupStickyBombs') self.tex_shield = ba.gettexture('powerupShield') self.tex_impact_bombs = ba.gettexture('powerupImpactBombs') self.tex_health = ba.gettexture('powerupHealth') self.tex_land_mines = ba.gettexture('powerupLandMines') self.tex_curse = ba.gettexture('powerupCurse') self.health_powerup_sound = ba.getsound('healthPowerup') self.powerup_sound = ba.getsound('powerup01') self.powerdown_sound = ba.getsound('powerdown01') self.drop_sound = ba.getsound('boxDrop') # Material for powerups. self.powerup_material = ba.Material() # Material for anyone wanting to accept powerups. self.powerup_accept_material = ba.Material() # Pass a powerup-touched message to applicable stuff. self.powerup_material.add_actions( conditions=('they_have_material', self.powerup_accept_material), actions=( ('modify_part_collision', 'collide', True), ('modify_part_collision', 'physical', False), ('message', 'our_node', 'at_connect', _TouchedMessage()), )) # We don't wanna be picked up. self.powerup_material.add_actions( conditions=('they_have_material', shared.pickup_material), actions=('modify_part_collision', 'collide', False), ) self.powerup_material.add_actions( conditions=('they_have_material', shared.footing_material), actions=('impact_sound', self.drop_sound, 0.5, 0.1), ) self._powerupdist: List[str] = [] for powerup, freq in get_default_powerup_distribution(): for _i in range(int(freq)): self._powerupdist.append(powerup)
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('puck') self.puck_tex = ba.gettexture('puckColor') 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', False)) 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._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._time_limit = float(settings['Time Limit'])
def __init__(self, position, form=ObstaclesForm.CUBE, mirror=False) -> None: ba.Actor.__init__(self) if form == ObstaclesForm.CUBE: model = 'tnt' body = 'crate' elif form == ObstaclesForm.SPHERE: model = 'bomb' body = 'sphere' else: # ObstaclesForm.RANDOM: model = random.choice(['tnt', 'bomb']) body = 'sphere' if model == 'bomb' else 'crate' self.node = ba.newnode( 'prop', delegate=self, attrs={ 'position': position, 'model': ba.getmodel(model), 'body': body, 'body_scale': 1.3, 'model_scale': 1.3, 'reflection': 'powerup', 'reflection_scale': [0.7], 'color_texture': ba.gettexture('bunnyColor'), 'materials': [SharedObjects.get().footing_material] if mirror else [ SharedObjects.get().object_material, SharedObjects.get().footing_material ] })
def __init__(self) -> None: self.ball_material = ba.Material() self.ball_material.add_actions( conditions=((('we_are_younger_than', 5), 'or', ('they_are_younger_than', 5)), 'and', ('they_have_material', SharedObjects.get().object_material)), actions=('modify_node_collision', 'collide', False)) self.ball_material.add_actions( conditions=('they_have_material', SharedObjects.get().pickup_material), actions=('modify_part_collision', 'use_node_collide', False)) self.ball_material.add_actions(actions=('modify_part_collision', 'friction', 0)) self.ball_material.add_actions( conditions=(('they_have_material', SharedObjects.get().footing_material), 'or', ('they_have_material', SharedObjects.get().object_material)), actions=('message', 'our_node', 'at_connect', ImpactMessage()))
def on_transition_in(self) -> None: super().on_transition_in() shared = SharedObjects.get() pts = self.map.get_def_points('race_point') mat = self.race_region_material = ba.Material() mat.add_actions(conditions=('they_have_material', shared.player_material), actions=( ('modify_part_collision', 'collide', True), ('modify_part_collision', 'physical', False), ('call', 'at_connect', self._handle_race_point_collide), )) for rpt in pts: self._regions.append(RaceRegion(rpt, len(self._regions)))
def on_sticky_gift(actor: stdbomb.Bomb, node: ba.Node) -> None: shared = SharedObjects.get() if (actor.node and node is not actor.owner and shared.player_material in node.materials): actor.node.sticky = True def wrapper(): if actor.node: actor.node.extra_acceleration = (0, 80, 0) if hasattr(actor, 'aim') and actor.aim: assert isinstance(actor.aim, AutoAim) actor.aim.off() ba.timer(0.01, wrapper)
def __init__(self): bomb_factory = stdbomb.BombFactory.get() shared = SharedObjects.get() self.sticky_gift_material = ba.Material() self.sticky_gift_material.add_actions( conditions=(('we_are_older_than', 200), 'and', ('they_are_older_than', 200), 'and', ('eval_colliding', ), 'and', (('they_dont_have_material', bomb_factory.land_mine_no_explode_material), 'and', (('they_have_material', shared.object_material), 'or', ('they_have_material', shared.player_material)))), actions=(('message', 'our_node', 'at_connect', SetStickyMessage()))) self.sticky_gift_texture = ba.gettexture('bg') self.sticky_gift_model = bomb_factory.sticky_bomb_model
def __init__(self, position: Sequence[float] = (0, 1, 0), lifetime: float = 0.5, highlight: bool = True): super().__init__() # array of nodes that received health kit self.cured_nodes: List[ba.Node] = [] self.area_material: ba.Material = ba.Material() shared = SharedObjects.get() self.area_material.add_actions( conditions=(('they_have_material', shared.player_material)), actions=(('modify_part_collision', 'collide', True), ('modify_part_collision', 'physical', False), ('call', 'at_connect', self._touch_handler))) # the area itself... self.node: ba.Node = ba.newnode('region', attrs={ 'type': 'sphere', 'scale': (2, 2, 2), 'position': position, 'materials': [self.area_material] }) ba.timer(lifetime, self.node.delete) # highlight the treatment area if highlight: self.area_highlight: ba.Node = ba.newnode( 'light', attrs={ 'color': (1, 1, 1), 'radius': 0.25, 'position': position, 'volume_intensity_scale': 1.0 }) # a little beautiful animation ba.animate(self.area_highlight, 'intensity', { 0: 0, lifetime / 2: 1.0, lifetime: 0 })
def __init__(self, position: Sequence[float] = (0, 1, 0), velocity: Sequence[float] = (0, 0, 0)): super().__init__() self.light: ba.Node self.picked: bool self.regen_timer = None self.phrase_text_node = None self.phrases: Sequence[Any] = get_locale('cube_companion_phrases') self.phrases_times: Sequence[float] = (10.0, 12.5, 15.0, 17.5, 20.0, 22.5, 25.0, 27.5, 30.0) self.phrases_time: float = random.choice(self.phrases_times) shared = SharedObjects.get() self.node: ba.Node = ba.newnode('prop', delegate=self, attrs={ 'body': 'crate', 'model': ba.getmodel('tnt'), 'light_model': ba.getmodel('tnt'), 'color_texture': ba.gettexture('landMineLit'), 'position': position, 'velocity': velocity, 'reflection': 'soft', 'reflection_scale': [0.25], 'materials': (shared.object_material, shared.footing_material) }) ba.animate(self.node, 'model_scale', {0: 0, 0.2: 1.3, 0.26: 1}) self.spawn_random_phrase_timer: ba.Timer = ba.Timer( self.phrases_time, self._spawn_random_phrase, repeat=True)
def create_team(self, sessionteam: ba.SessionTeam) -> Team: shared = SharedObjects.get() base_pos = self.map.get_flag_position(sessionteam.id) ba.newnode('light', attrs={ 'position': base_pos, 'intensity': 0.6, 'height_attenuated': False, 'volume_intensity_scale': 0.1, 'radius': 0.1, 'color': sessionteam.color }) Flag.project_stand(base_pos) flag = Flag(touchable=False, position=base_pos, color=sessionteam.color) team = Team(base_pos=base_pos, flag=flag) mat = self._base_region_materials[sessionteam.id] = ba.Material() mat.add_actions( conditions=('they_have_material', shared.player_material), actions=( ('modify_part_collision', 'collide', True), ('modify_part_collision', 'physical', False), ('call', 'at_connect', ba.Call(self._handle_base_collide, team)), ), ) ba.newnode('region', owner=flag.node, attrs={ 'position': (base_pos[0], base_pos[1] + 0.75, base_pos[2]), 'scale': (0.5, 0.5, 0.5), 'type': 'sphere', 'materials': [self._base_region_materials[sessionteam.id]] }) return team
def __init__(self, settings: Dict[str, Any]): super().__init__(settings) shared = SharedObjects.get() self._scoreboard = Scoreboard() self._score_sound = ba.getsound('score') self._swipsound = ba.getsound('swip') self._extraflagmat = ba.Material() self._flags: List[ConquestFlag] = [] self._epic_mode = bool(settings['Epic Mode']) self._time_limit = float(settings['Time Limit']) # Base class overrides. self.slow_motion = self._epic_mode self.default_music = (ba.MusicType.EPIC if self._epic_mode else ba.MusicType.GRAND_ROMP) # We want flags to tell us they've been hit but not react physically. self._extraflagmat.add_actions( conditions=('they_have_material', shared.player_material), actions=(('modify_part_collision', 'collide', True), ('call', 'at_connect', self._handle_flag_player_collide)))
def __init__(self, settings: Dict[str, Any]): super().__init__(settings) shared = SharedObjects.get() self._scoreboard = Scoreboard() self._swipsound = ba.getsound('swip') self._tick_sound = ba.getsound('tick') self._countdownsounds = { 10: ba.getsound('announceTen'), 9: ba.getsound('announceNine'), 8: ba.getsound('announceEight'), 7: ba.getsound('announceSeven'), 6: ba.getsound('announceSix'), 5: ba.getsound('announceFive'), 4: ba.getsound('announceFour'), 3: ba.getsound('announceThree'), 2: ba.getsound('announceTwo'), 1: ba.getsound('announceOne') } self._flag_pos: Optional[Sequence[float]] = None self._flag_state: Optional[FlagState] = None self._flag: Optional[Flag] = None self._flag_light: Optional[ba.Node] = None self._scoring_team: Optional[ReferenceType[Team]] = None self._hold_time = int(settings['Hold Time']) self._time_limit = float(settings['Time Limit']) self._flag_region_material = ba.Material() self._flag_region_material.add_actions( conditions=('they_have_material', shared.player_material), actions=( ('modify_part_collision', 'collide', True), ('modify_part_collision', 'physical', False), ('call', 'at_connect', ba.Call(self._handle_player_flag_region_collide, True)), ('call', 'at_disconnect', ba.Call(self._handle_player_flag_region_collide, False)), )) # Base class overrides. self.default_music = ba.MusicType.SCARY
def __init__(self, position=(0, 5, 0), velocity=(1, 0, 0), source_player=None, owner=None, color=(1.0, 0.2, 0.2)) -> None: super().__init__() self.source_player = source_player self.owner = owner self._color = color factory = RocketFactory.get() self.node = ba.newnode('prop', delegate=self, attrs={ 'position': position, 'velocity': velocity, 'model': ba.getmodel('impactBomb'), 'body': 'sphere', 'color_texture': ba.gettexture( 'bunnyColor'), 'model_scale': 0.2, 'is_area_of_interest': True, 'body_scale': 0.8, 'materials': [ SharedObjects.get().object_material, factory.ball_material] }) # yapf: disable self.node.extra_acceleration = (self.node.velocity[0] * 200, 0, self.node.velocity[2] * 200) self._life_timer = ba.Timer( 5, ba.WeakCall(self.handlemessage, ba.DieMessage())) self._emit_timer = ba.Timer(0.001, ba.WeakCall(self.emit), repeat=True) self.base_pos_y = self.node.position[1] ba.camerashake(5.0)
def __init__(self, settings: dict): super().__init__(settings) shared = SharedObjects.get() self._last_player_death_time = None self._scoreboard = Scoreboard() self.egg_model = ba.getmodel('egg') self.egg_tex_1 = ba.gettexture('eggTex1') self.egg_tex_2 = ba.gettexture('eggTex2') self.egg_tex_3 = ba.gettexture('eggTex3') self._collect_sound = ba.getsound('powerup01') self._pro_mode = settings.get('Pro Mode', False) self._max_eggs = 1.0 self.egg_material = ba.Material() self.egg_material.add_actions( conditions=('they_have_material', shared.player_material), actions=(('call', 'at_connect', self._on_egg_player_collide), )) self._eggs: List[Egg] = [] self._update_timer: Optional[ba.Timer] = None self._countdown: Optional[OnScreenCountdown] = None self._bots: Optional[SpazBotSet] = None # Base class overrides self.default_music = ba.MusicType.FORWARD_MARCH
def __init__(self, old_function: Callable, position=(0.0, 1.0, 0.0), velocity=(0.0, 0.0, 0.0), bomb_type: str = 'normal', blast_radius: float = 2.0, source_player: ba.Player = None, owner: ba.Node = None): """Create a new Bomb. bomb_type can be standard or one from declared with bd.me. Note that for impact or land_mine bombs you have to call arm() before they will go off. """ mebomb: MeBomb = get_mebomb(bomb_type) if mebomb is None: old_function(self, position, velocity, bomb_type, blast_radius, source_player, owner) return ba.Actor.__init__(self) factory = BombFactory.get() shared = SharedObjects.get() self.bomb_type = bomb_type self._exploded = False self.texture_sequence = None self.blast_radius = blast_radius self._explode_callbacks = [] # the player this came from self._source_player = source_player # by default our hit type/subtype is our own, but we pick up types of # whoever sets us off so we know what caused a chain reaction self.hit_type = 'explosion' self.hit_subtype = self.bomb_type # if no owner was provided, use an unconnected node ref # (nevermind; trying to use None in these type cases instead) # if owner is None: # owner = ba.Node(None) # the node this came from self.owner = owner # adding footing-materials to things can screw up jumping and flying # since players carrying those things # and thus touching footing objects will think they're on solid # ground.. perhaps we don't wanna add this even in the tnt case?.. materials: tuple materials = (factory.bomb_material, shared.object_material) if mebomb.is_impact: materials = materials + (factory.impact_blast_material,) elif mebomb.is_mine: materials = materials + (factory.land_mine_no_explode_material,) # TODO: add custom materials (now you may add they in mebomb.init) fuse_time = None mebomb = get_mebomb(self.bomb_type) fuse_time = mebomb.fuse_time self.blast_radius *= mebomb.blast_coefficient if mebomb.sticky: materials = materials + (factory.sticky_material,) else: materials = materials + (factory.normal_sound_material,) if mebomb.is_impact: materials = materials + (factory.impact_blast_material,) if mebomb.is_mine: materials = materials + (factory.land_mine_no_explode_material,) mebomb.init(self, position, velocity, materials) # Light the fuse!!! if fuse_time is not None: ba.timer(fuse_time, ba.WeakCall(self.handlemessage, ExplodeMessage())) ba.animate(self.node, "model_scale", {0: 0, 0.2: 1.3, 0.26: 1})
def __init__(self, position: Sequence[float] = (0.0, 1.0, 0.0), color: Sequence[float] = (1.0, 1.0, 1.0), materials: Sequence[ba.Material] = None, touchable: bool = True, dropped_timeout: int = None): """Instantiate a flag. If 'touchable' is False, the flag will only touch terrain; useful for things like king-of-the-hill where players should not be moving the flag around. 'materials can be a list of extra ba.Materials to apply to the flag. If 'dropped_timeout' is provided (in seconds), the flag will die after remaining untouched for that long once it has been moved from its initial position. """ super().__init__() self._initial_position: Optional[Sequence[float]] = None self._has_moved = False shared = SharedObjects.get() factory = FlagFactory.get() if materials is None: materials = [] elif not isinstance(materials, list): # In case they passed a tuple or whatnot. materials = list(materials) if not touchable: materials = [factory.no_hit_material] + materials finalmaterials = ([shared.object_material, factory.flagmaterial] + materials) self.node = ba.newnode('flag', attrs={ 'position': (position[0], position[1] + 0.75, position[2]), 'color_texture': factory.flag_texture, 'color': color, 'materials': finalmaterials }, delegate=self) if dropped_timeout is not None: dropped_timeout = int(dropped_timeout) self._dropped_timeout = dropped_timeout self._counter: Optional[ba.Node] if self._dropped_timeout is not None: self._count = self._dropped_timeout self._tick_timer = ba.Timer(1.0, call=ba.WeakCall(self._tick), repeat=True) self._counter = ba.newnode('text', owner=self.node, attrs={ 'in_world': True, 'color': (1, 1, 1, 0.7), 'scale': 0.015, 'shadow': 0.5, 'flatness': 1.0, 'h_align': 'center' }) else: self._counter = None self._held_count = 0 self._score_text: Optional[ba.Node] = None self._score_text_hide_timer: Optional[ba.Timer] = None
def __init__(self, position: Sequence[float] = (0.0, 1.0, 0.0), velocity: Sequence[float] = (0.0, 0.0, 0.0), bomb_type: str = 'normal', blast_radius: float = 2.0, bomb_scale: float = 1.0, source_player: ba.Player = None, owner: ba.Node = None): """Create a new Bomb. bomb_type can be 'ice','impact','land_mine','normal','sticky', or 'tnt'. Note that for impact or land_mine bombs you have to call arm() before they will go off. """ super().__init__() shared = SharedObjects.get() factory = BombFactory.get() if bomb_type not in ('ice', 'impact', 'land_mine', 'normal', 'sticky', 'tnt'): raise ValueError('invalid bomb type: ' + bomb_type) self.bomb_type = bomb_type self._exploded = False self.scale = bomb_scale self.texture_sequence: Optional[ba.Node] = None if self.bomb_type == 'sticky': self._last_sticky_sound_time = 0.0 self.blast_radius = blast_radius if self.bomb_type == 'ice': self.blast_radius *= 1.2 elif self.bomb_type == 'impact': self.blast_radius *= 0.7 elif self.bomb_type == 'land_mine': self.blast_radius *= 0.7 elif self.bomb_type == 'tnt': self.blast_radius *= 1.45 self._explode_callbacks: list[Callable[[Bomb, Blast], Any]] = [] # The player this came from. self._source_player = source_player # By default our hit type/subtype is our own, but we pick up types of # whoever sets us off so we know what caused a chain reaction. # UPDATE (July 2020): not inheriting hit-types anymore; this causes # weird effects such as land-mines inheriting 'punch' hit types and # then not being able to destroy certain things they normally could, # etc. Inheriting owner/source-node from things that set us off # should be all we need I think... self.hit_type = 'explosion' self.hit_subtype = self.bomb_type # The node this came from. # FIXME: can we unify this and source_player? self.owner = owner # Adding footing-materials to things can screw up jumping and flying # since players carrying those things and thus touching footing # objects will think they're on solid ground.. perhaps we don't # wanna add this even in the tnt case? materials: tuple[ba.Material, ...] if self.bomb_type == 'tnt': materials = (factory.bomb_material, shared.footing_material, shared.object_material) else: materials = (factory.bomb_material, shared.object_material) if self.bomb_type == 'impact': materials = materials + (factory.impact_blast_material, ) elif self.bomb_type == 'land_mine': materials = materials + (factory.land_mine_no_explode_material, ) if self.bomb_type == 'sticky': materials = materials + (factory.sticky_material, ) else: materials = materials + (factory.normal_sound_material, ) if self.bomb_type == 'land_mine': fuse_time = None self.node = ba.newnode('prop', delegate=self, attrs={ 'position': position, 'velocity': velocity, 'model': factory.land_mine_model, 'light_model': factory.land_mine_model, 'body': 'landMine', 'body_scale': self.scale, 'shadow_size': 0.44, 'color_texture': factory.land_mine_tex, 'reflection': 'powerup', 'reflection_scale': [1.0], 'materials': materials }) elif self.bomb_type == 'tnt': fuse_time = None self.node = ba.newnode('prop', delegate=self, attrs={ 'position': position, 'velocity': velocity, 'model': factory.tnt_model, 'light_model': factory.tnt_model, 'body': 'crate', 'body_scale': self.scale, 'shadow_size': 0.5, 'color_texture': factory.tnt_tex, 'reflection': 'soft', 'reflection_scale': [0.23], 'materials': materials }) elif self.bomb_type == 'impact': fuse_time = 20.0 self.node = ba.newnode('prop', delegate=self, attrs={ 'position': position, 'velocity': velocity, 'body': 'sphere', 'body_scale': self.scale, 'model': factory.impact_bomb_model, 'shadow_size': 0.3, 'color_texture': factory.impact_tex, 'reflection': 'powerup', 'reflection_scale': [1.5], 'materials': materials }) self.arm_timer = ba.Timer( 0.2, ba.WeakCall(self.handlemessage, ArmMessage())) self.warn_timer = ba.Timer( fuse_time - 1.7, ba.WeakCall(self.handlemessage, WarnMessage())) else: fuse_time = 3.0 if self.bomb_type == 'sticky': sticky = True model = factory.sticky_bomb_model rtype = 'sharper' rscale = 1.8 else: sticky = False model = factory.bomb_model rtype = 'sharper' rscale = 1.8 if self.bomb_type == 'ice': tex = factory.ice_tex elif self.bomb_type == 'sticky': tex = factory.sticky_tex else: tex = factory.regular_tex self.node = ba.newnode('bomb', delegate=self, attrs={ 'position': position, 'velocity': velocity, 'model': model, 'body_scale': self.scale, 'shadow_size': 0.3, 'color_texture': tex, 'sticky': sticky, 'owner': owner, 'reflection': rtype, 'reflection_scale': [rscale], 'materials': materials }) sound = ba.newnode('sound', owner=self.node, attrs={ 'sound': factory.fuse_sound, 'volume': 0.25 }) self.node.connectattr('position', sound, 'position') ba.animate(self.node, 'fuse_length', {0.0: 1.0, fuse_time: 0.0}) # Light the fuse!!! if self.bomb_type not in ('land_mine', 'tnt'): assert fuse_time is not None ba.timer(fuse_time, ba.WeakCall(self.handlemessage, ExplodeMessage())) ba.animate(self.node, 'model_scale', { 0: 0, 0.2: 1.3 * self.scale, 0.26: self.scale })
def __init__(self, position: Sequence[float] = (0.0, 1.0, 0.0), velocity: Sequence[float] = (0.0, 0.0, 0.0), blast_radius: float = 2.0, blast_type: str = 'normal', source_player: ba.Player = None, hit_type: str = 'explosion', hit_subtype: str = 'normal'): """Instantiate with given values.""" # bah; get off my lawn! # pylint: disable=too-many-locals # pylint: disable=too-many-statements super().__init__() shared = SharedObjects.get() factory = BombFactory.get() self.blast_type = blast_type self._source_player = source_player self.hit_type = hit_type self.hit_subtype = hit_subtype self.radius = blast_radius # Set our position a bit lower so we throw more things upward. rmats = (factory.blast_material, shared.attack_material) self.node = ba.newnode( 'region', delegate=self, attrs={ 'position': (position[0], position[1] - 0.1, position[2]), 'scale': (self.radius, self.radius, self.radius), 'type': 'sphere', 'materials': rmats }, ) ba.timer(0.05, self.node.delete) # Throw in an explosion and flash. evel = (velocity[0], max(-1.0, velocity[1]), velocity[2]) explosion = ba.newnode('explosion', attrs={ 'position': position, 'velocity': evel, 'radius': self.radius, 'big': (self.blast_type == 'tnt') }) if self.blast_type == 'ice': explosion.color = (0, 0.05, 0.4) ba.timer(1.0, explosion.delete) if self.blast_type != 'ice': ba.emitfx(position=position, velocity=velocity, count=int(1.0 + random.random() * 4), emit_type='tendrils', tendril_type='thin_smoke') ba.emitfx(position=position, velocity=velocity, count=int(4.0 + random.random() * 4), emit_type='tendrils', tendril_type='ice' if self.blast_type == 'ice' else 'smoke') ba.emitfx(position=position, emit_type='distortion', spread=1.0 if self.blast_type == 'tnt' else 2.0) # And emit some shrapnel. if self.blast_type == 'ice': def emit() -> None: ba.emitfx(position=position, velocity=velocity, count=30, spread=2.0, scale=0.4, chunk_type='ice', emit_type='stickers') # It looks better if we delay a bit. ba.timer(0.05, emit) elif self.blast_type == 'sticky': def emit() -> None: ba.emitfx(position=position, velocity=velocity, count=int(4.0 + random.random() * 8), spread=0.7, chunk_type='slime') ba.emitfx(position=position, velocity=velocity, count=int(4.0 + random.random() * 8), scale=0.5, spread=0.7, chunk_type='slime') ba.emitfx(position=position, velocity=velocity, count=15, scale=0.6, chunk_type='slime', emit_type='stickers') ba.emitfx(position=position, velocity=velocity, count=20, scale=0.7, chunk_type='spark', emit_type='stickers') ba.emitfx(position=position, velocity=velocity, count=int(6.0 + random.random() * 12), scale=0.8, spread=1.5, chunk_type='spark') # It looks better if we delay a bit. ba.timer(0.05, emit) elif self.blast_type == 'impact': def emit() -> None: ba.emitfx(position=position, velocity=velocity, count=int(4.0 + random.random() * 8), scale=0.8, chunk_type='metal') ba.emitfx(position=position, velocity=velocity, count=int(4.0 + random.random() * 8), scale=0.4, chunk_type='metal') ba.emitfx(position=position, velocity=velocity, count=20, scale=0.7, chunk_type='spark', emit_type='stickers') ba.emitfx(position=position, velocity=velocity, count=int(8.0 + random.random() * 15), scale=0.8, spread=1.5, chunk_type='spark') # It looks better if we delay a bit. ba.timer(0.05, emit) else: # Regular or land mine bomb shrapnel. def emit() -> None: if self.blast_type != 'tnt': ba.emitfx(position=position, velocity=velocity, count=int(4.0 + random.random() * 8), chunk_type='rock') ba.emitfx(position=position, velocity=velocity, count=int(4.0 + random.random() * 8), scale=0.5, chunk_type='rock') ba.emitfx(position=position, velocity=velocity, count=30, scale=1.0 if self.blast_type == 'tnt' else 0.7, chunk_type='spark', emit_type='stickers') ba.emitfx(position=position, velocity=velocity, count=int(18.0 + random.random() * 20), scale=1.0 if self.blast_type == 'tnt' else 0.8, spread=1.5, chunk_type='spark') # TNT throws splintery chunks. if self.blast_type == 'tnt': def emit_splinters() -> None: ba.emitfx(position=position, velocity=velocity, count=int(20.0 + random.random() * 25), scale=0.8, spread=1.0, chunk_type='splinter') ba.timer(0.01, emit_splinters) # Every now and then do a sparky one. if self.blast_type == 'tnt' or random.random() < 0.1: def emit_extra_sparks() -> None: ba.emitfx(position=position, velocity=velocity, count=int(10.0 + random.random() * 20), scale=0.8, spread=1.5, chunk_type='spark') ba.timer(0.02, emit_extra_sparks) # It looks better if we delay a bit. ba.timer(0.05, emit) lcolor = ((0.6, 0.6, 1.0) if self.blast_type == 'ice' else (1, 0.3, 0.1)) light = ba.newnode('light', attrs={ 'position': position, 'volume_intensity_scale': 10.0, 'color': lcolor }) scl = random.uniform(0.6, 0.9) scorch_radius = light_radius = self.radius if self.blast_type == 'tnt': light_radius *= 1.4 scorch_radius *= 1.15 scl *= 3.0 iscale = 1.6 ba.animate( light, 'intensity', { 0: 2.0 * iscale, scl * 0.02: 0.1 * iscale, scl * 0.025: 0.2 * iscale, scl * 0.05: 17.0 * iscale, scl * 0.06: 5.0 * iscale, scl * 0.08: 4.0 * iscale, scl * 0.2: 0.6 * iscale, scl * 2.0: 0.00 * iscale, scl * 3.0: 0.0 }) ba.animate( light, 'radius', { 0: light_radius * 0.2, scl * 0.05: light_radius * 0.55, scl * 0.1: light_radius * 0.3, scl * 0.3: light_radius * 0.15, scl * 1.0: light_radius * 0.05 }) ba.timer(scl * 3.0, light.delete) # Make a scorch that fades over time. scorch = ba.newnode('scorch', attrs={ 'position': position, 'size': scorch_radius * 0.5, 'big': (self.blast_type == 'tnt') }) if self.blast_type == 'ice': scorch.color = (1, 1, 1.5) ba.animate(scorch, 'presence', {3.000: 1, 13.000: 0}) ba.timer(13.0, scorch.delete) if self.blast_type == 'ice': ba.playsound(factory.hiss_sound, position=light.position) lpos = light.position ba.playsound(factory.random_explode_sound(), position=lpos) ba.playsound(factory.debris_fall_sound, position=lpos) ba.camerashake(intensity=5.0 if self.blast_type == 'tnt' else 1.0) # TNT is more epic. if self.blast_type == 'tnt': ba.playsound(factory.random_explode_sound(), position=lpos) def _extra_boom() -> None: ba.playsound(factory.random_explode_sound(), position=lpos) ba.timer(0.25, _extra_boom) def _extra_debris_sound() -> None: ba.playsound(factory.debris_fall_sound, position=lpos) ba.playsound(factory.wood_debris_fall_sound, position=lpos) ba.timer(0.4, _extra_debris_sound)
def __init__(self) -> None: """Instantiate a BombFactory. You shouldn't need to do this; call bastd.actor.bomb.get_factory() to get a shared instance. """ shared = SharedObjects.get() self.bomb_model = ba.getmodel('bomb') self.sticky_bomb_model = ba.getmodel('bombSticky') self.impact_bomb_model = ba.getmodel('impactBomb') self.land_mine_model = ba.getmodel('landMine') self.tnt_model = ba.getmodel('tnt') self.regular_tex = ba.gettexture('bombColor') self.ice_tex = ba.gettexture('bombColorIce') self.sticky_tex = ba.gettexture('bombStickyColor') self.impact_tex = ba.gettexture('impactBombColor') self.impact_lit_tex = ba.gettexture('impactBombColorLit') self.land_mine_tex = ba.gettexture('landMine') self.land_mine_lit_tex = ba.gettexture('landMineLit') self.tnt_tex = ba.gettexture('tnt') self.hiss_sound = ba.getsound('hiss') self.debris_fall_sound = ba.getsound('debrisFall') self.wood_debris_fall_sound = ba.getsound('woodDebrisFall') self.explode_sounds = (ba.getsound('explosion01'), ba.getsound('explosion02'), ba.getsound('explosion03'), ba.getsound('explosion04'), ba.getsound('explosion05')) self.freeze_sound = ba.getsound('freeze') self.fuse_sound = ba.getsound('fuse01') self.activate_sound = ba.getsound('activateBeep') self.warn_sound = ba.getsound('warnBeep') # Set up our material so new bombs don't collide with objects # that they are initially overlapping. self.bomb_material = ba.Material() self.normal_sound_material = ba.Material() self.sticky_material = ba.Material() self.bomb_material.add_actions( conditions=( ( ('we_are_younger_than', 100), 'or', ('they_are_younger_than', 100), ), 'and', ('they_have_material', shared.object_material), ), actions=('modify_node_collision', 'collide', False), ) # We want pickup materials to always hit us even if we're currently # not colliding with their node. (generally due to the above rule) self.bomb_material.add_actions( conditions=('they_have_material', shared.pickup_material), actions=('modify_part_collision', 'use_node_collide', False), ) self.bomb_material.add_actions(actions=('modify_part_collision', 'friction', 0.3)) self.land_mine_no_explode_material = ba.Material() self.land_mine_blast_material = ba.Material() self.land_mine_blast_material.add_actions( conditions=( ('we_are_older_than', 200), 'and', ('they_are_older_than', 200), 'and', ('eval_colliding', ), 'and', ( ('they_dont_have_material', self.land_mine_no_explode_material), 'and', ( ('they_have_material', shared.object_material), 'or', ('they_have_material', shared.player_material), ), ), ), actions=('message', 'our_node', 'at_connect', ImpactMessage()), ) self.impact_blast_material = ba.Material() self.impact_blast_material.add_actions( conditions=( ('we_are_older_than', 200), 'and', ('they_are_older_than', 200), 'and', ('eval_colliding', ), 'and', ( ('they_have_material', shared.footing_material), 'or', ('they_have_material', shared.object_material), ), ), actions=('message', 'our_node', 'at_connect', ImpactMessage()), ) self.blast_material = ba.Material() self.blast_material.add_actions( conditions=('they_have_material', shared.object_material), actions=( ('modify_part_collision', 'collide', True), ('modify_part_collision', 'physical', False), ('message', 'our_node', 'at_connect', ExplodeHitMessage()), ), ) self.dink_sounds = (ba.getsound('bombDrop01'), ba.getsound('bombDrop02')) self.sticky_impact_sound = ba.getsound('stickyImpact') self.roll_sound = ba.getsound('bombRoll01') # Collision sounds. self.normal_sound_material.add_actions( conditions=('they_have_material', shared.footing_material), actions=( ('impact_sound', self.dink_sounds, 2, 0.8), ('roll_sound', self.roll_sound, 3, 6), )) self.sticky_material.add_actions(actions=(('modify_part_collision', 'stiffness', 0.1), ('modify_part_collision', 'damping', 1.0))) self.sticky_material.add_actions( conditions=( ('they_have_material', shared.player_material), 'or', ('they_have_material', shared.footing_material), ), actions=('message', 'our_node', 'at_connect', SplatMessage()), )
def __init__(self) -> None: """Instantiate a FlagFactory. You shouldn't need to do this; call bastd.actor.flag.get_factory() to get a shared instance. """ shared = SharedObjects.get() self.flagmaterial = ba.Material() self.flagmaterial.add_actions( conditions=( ('we_are_younger_than', 100), 'and', ('they_have_material', shared.object_material), ), actions=('modify_node_collision', 'collide', False), ) self.flagmaterial.add_actions( conditions=( 'they_have_material', shared.footing_material, ), actions=( ('message', 'our_node', 'at_connect', 'footing', 1), ('message', 'our_node', 'at_disconnect', 'footing', -1), ), ) self.impact_sound = ba.getsound('metalHit') self.skid_sound = ba.getsound('metalSkid') self.flagmaterial.add_actions( conditions=( 'they_have_material', shared.footing_material, ), actions=( ('impact_sound', self.impact_sound, 2, 5), ('skid_sound', self.skid_sound, 2, 5), ), ) self.no_hit_material = ba.Material() self.no_hit_material.add_actions( conditions=( ('they_have_material', shared.pickup_material), 'or', ('they_have_material', shared.attack_material), ), actions=('modify_part_collision', 'collide', False), ) # We also don't want anything moving it. self.no_hit_material.add_actions( conditions=( ('they_have_material', shared.object_material), 'or', ('they_dont_have_material', shared.footing_material), ), actions=(('modify_part_collision', 'collide', False), ('modify_part_collision', 'physical', False)), ) self.flag_texture = ba.gettexture('flagColor')
def __init__(self) -> None: """Instantiate a factory object.""" # pylint: disable=cyclic-import # FIXME: should probably put these somewhere common so we don't # have to import them from a module that imports us. from bastd.actor.spaz import (PickupMessage, PunchHitMessage, CurseExplodeMessage) shared = SharedObjects.get() self.impact_sounds_medium = (ba.getsound('impactMedium'), ba.getsound('impactMedium2')) self.impact_sounds_hard = (ba.getsound('impactHard'), ba.getsound('impactHard2'), ba.getsound('impactHard3')) self.impact_sounds_harder = (ba.getsound('bigImpact'), ba.getsound('bigImpact2')) self.single_player_death_sound = ba.getsound('playerDeath') self.punch_sound = ba.getsound('punch01') self.punch_sound_strong = (ba.getsound('punchStrong01'), ba.getsound('punchStrong02')) self.punch_sound_stronger = ba.getsound('superPunch') self.swish_sound = ba.getsound('punchSwish') self.block_sound = ba.getsound('block') self.shatter_sound = ba.getsound('shatter') self.splatter_sound = ba.getsound('splatter') self.spaz_material = ba.Material() self.roller_material = ba.Material() self.punch_material = ba.Material() self.pickup_material = ba.Material() self.curse_material = ba.Material() footing_material = shared.footing_material object_material = shared.object_material player_material = shared.player_material region_material = shared.region_material # Send footing messages to spazzes so they know when they're on # solid ground. # Eww; this probably should just be built into the spaz node. self.roller_material.add_actions( conditions=('they_have_material', footing_material), actions=(('message', 'our_node', 'at_connect', 'footing', 1), ('message', 'our_node', 'at_disconnect', 'footing', -1))) self.spaz_material.add_actions( conditions=('they_have_material', footing_material), actions=(('message', 'our_node', 'at_connect', 'footing', 1), ('message', 'our_node', 'at_disconnect', 'footing', -1))) # Punches. self.punch_material.add_actions( conditions=('they_are_different_node_than_us', ), actions=( ('modify_part_collision', 'collide', True), ('modify_part_collision', 'physical', False), ('message', 'our_node', 'at_connect', PunchHitMessage()), )) # Pickups. self.pickup_material.add_actions( conditions=(('they_are_different_node_than_us', ), 'and', ('they_have_material', object_material)), actions=( ('modify_part_collision', 'collide', True), ('modify_part_collision', 'physical', False), ('message', 'our_node', 'at_connect', PickupMessage()), )) # Curse. self.curse_material.add_actions( conditions=( ('they_are_different_node_than_us', ), 'and', ('they_have_material', player_material), ), actions=('message', 'our_node', 'at_connect', CurseExplodeMessage()), ) self.foot_impact_sounds = (ba.getsound('footImpact01'), ba.getsound('footImpact02'), ba.getsound('footImpact03')) self.foot_skid_sound = ba.getsound('skid01') self.foot_roll_sound = ba.getsound('scamper01') self.roller_material.add_actions( conditions=('they_have_material', footing_material), actions=( ('impact_sound', self.foot_impact_sounds, 1, 0.2), ('skid_sound', self.foot_skid_sound, 20, 0.3), ('roll_sound', self.foot_roll_sound, 20, 3.0), )) self.skid_sound = ba.getsound('gravelSkid') self.spaz_material.add_actions( conditions=('they_have_material', footing_material), actions=( ('impact_sound', self.foot_impact_sounds, 20, 6), ('skid_sound', self.skid_sound, 2.0, 1), ('roll_sound', self.skid_sound, 2.0, 1), )) self.shield_up_sound = ba.getsound('shieldUp') self.shield_down_sound = ba.getsound('shieldDown') self.shield_hit_sound = ba.getsound('shieldHit') # We don't want to collide with stuff we're initially overlapping # (unless its marked with a special region material). self.spaz_material.add_actions( conditions=( ( ('we_are_younger_than', 51), 'and', ('they_are_different_node_than_us', ), ), 'and', ('they_dont_have_material', region_material), ), actions=('modify_node_collision', 'collide', False), ) self.spaz_media: dict[str, Any] = {} # Lets load some basic rules. # (allows them to be tweaked from the master server) self.shield_decay_rate = _ba.get_account_misc_read_val('rsdr', 10.0) self.punch_cooldown = _ba.get_account_misc_read_val('rpc', 400) self.punch_cooldown_gloves = (_ba.get_account_misc_read_val( 'rpcg', 300)) self.punch_power_scale = _ba.get_account_misc_read_val('rpp', 1.2) self.punch_power_scale_gloves = (_ba.get_account_misc_read_val( 'rppg', 1.4)) self.max_shield_spillover_damage = (_ba.get_account_misc_read_val( 'rsms', 500))
def __init__(self, color=(1, 1, 1), radius=1.25, first_position=(-3, 1, 0), second_position=(3, 1, 0)): super().__init__() self.first_position = first_position self.second_position = second_position self.radius = radius # self.cooldown = False self.already_teleported = {} self.node_radius = radius / 1.75 node_scale = { 0: (0, 0, 0), 0.5: (self.node_radius, self.node_radius, self.node_radius) } # portal materials self.first_portal_material = ba.Material() shared = SharedObjects.get() self.first_portal_material.add_actions( conditions=(('they_have_material', shared.player_material)), actions=(('modify_part_collision', 'collide', True), ('modify_part_collision', 'physical', False), ('call', 'at_connect', self._first_portal_teleportation))) self.first_portal_material.add_actions( conditions=(('they_have_material', shared.player_material), 'and', ('they_dont_have_material', shared.player_material)), actions=(('modify_part_collision', 'collide', True), ('modify_part_collision', 'physical', False), ('call', 'at_connect', self._first_portal_handler))) self.second_portal_material = ba.Material() self.second_portal_material.add_actions( conditions=(('they_have_material', shared.player_material)), actions=(('modify_part_collision', 'collide', True), ('modify_part_collision', 'physical', False), ('call', 'at_connect', self._second_portal_teleportation))) self.second_portal_material.add_actions( conditions=(('they_have_material', shared.object_material), 'and', ('they_dont_have_material', shared.player_material)), actions=(('modify_part_collision', 'collide', True), ('modify_part_collision', 'physical', False), ('call', 'at_connect', self._second_portal_handler))) # create a first portal self.first_node = ba.newnode('region', attrs={ 'type': 'sphere', 'position': self.first_position, 'materials': [self.first_portal_material] }) self.first_node_visualization = ba.newnode('shield', attrs={ 'color': color, 'position': self.first_position }) ba.animate(self.first_node_visualization, 'radius', { 0: 0, 0.5: radius }) # ba.animate_array(self.first_node, 'scale', 3, node_scale) # create a second portal self.second_node = ba.newnode('region', attrs={ 'type': 'sphere', 'position': self.second_position, 'materials': [self.second_portal_material] }) self.second_node_visualization = ba.newnode('shield', attrs={ 'color': color, 'position': self.second_position }) ba.animate(self.second_node_visualization, 'radius', { 0: 0, 0.5: radius }) # ba.animate_array(self.second_node, 'scale', 3, node_scale) # delete portals after some time ba.timer(10, self.delete)
def __init__(self, position: Sequence[float] = (0.0, 1.0, 0.0), poweruptype: str = 'triple_bombs', expire: bool = True): """Create a powerup-box of the requested type at the given position. see ba.Powerup.poweruptype for valid type strings. """ super().__init__() shared = SharedObjects.get() factory = PowerupBoxFactory.get() self.poweruptype = poweruptype self._powersgiven = False if poweruptype == 'triple_bombs': tex = factory.tex_bomb elif poweruptype == 'punch': tex = factory.tex_punch elif poweruptype == 'ice_bombs': tex = factory.tex_ice_bombs elif poweruptype == 'impact_bombs': tex = factory.tex_impact_bombs elif poweruptype == 'land_mines': tex = factory.tex_land_mines elif poweruptype == 'sticky_bombs': tex = factory.tex_sticky_bombs elif poweruptype == 'shield': tex = factory.tex_shield elif poweruptype == 'health': tex = factory.tex_health elif poweruptype == 'curse': tex = factory.tex_curse else: raise ValueError('invalid poweruptype: ' + str(poweruptype)) if len(position) != 3: raise ValueError('expected 3 floats for position') self.node = ba.newnode( 'prop', delegate=self, attrs={ 'body': 'box', 'position': position, 'model': factory.model, 'light_model': factory.model_simple, 'shadow_size': 0.5, 'color_texture': tex, 'reflection': 'powerup', 'reflection_scale': [1.0], 'materials': (factory.powerup_material, shared.object_material) }) # yapf: disable # Animate in. curve = ba.animate(self.node, 'model_scale', {0: 0, 0.14: 1.6, 0.2: 1}) ba.timer(0.2, curve.delete) if expire: ba.timer(DEFAULT_POWERUP_INTERVAL - 2.5, ba.WeakCall(self._start_flashing)) ba.timer(DEFAULT_POWERUP_INTERVAL - 1.0, ba.WeakCall(self.handlemessage, ba.DieMessage()))