# ba_meta require api 7 from __future__ import annotations from typing import TYPE_CHECKING import base64 import ba, _ba, random, time, datetime, weakref, json, os import baPowerupManager as pm from baPowerupManager import * from bastd.actor.spaz import (Spaz, SpazFactory, PickupMessage, PunchHitMessage, CurseExplodeMessage, BombDiedMessage) from bastd.actor.powerupbox import PowerupBox from baPowerupManager import NewPowerupBoxFactory from bastd.actor.image import Image from bastd.actor import bomb as stdbomb if TYPE_CHECKING: pass _sp_ = pm._sp_ def getlanguage(text, subs: str = None, almacen: list = []): if almacen == []: almacen = list(range(1000)) lang = _ba.app.lang.language translate = {"Complete": {"Spanish": "Completado", "English": "Complete", "Portuguese": "Completo"}, "Invincible Text": {"Spanish": "Inmune", "English": "immune", "Portuguese": "Imune"}, "Welfare": {"Spanish": "Bienestar", "English": "Welfare", "Portuguese": "Bem-estar"}, "Toxic Bombs": {"Spanish": "Bombas tóxicas", "English": "Toxic bombs", "Portuguese": "Bombas tóxicas"}, "Teleport Bombs": {"Spanish": "Telebombartación", "English": "Teleport bombs", "Portuguese": "Teletransportadoras"}, "Weakening Bombs": {"Spanish": "Bombas de debilitación", "English": "Weakening bombs", "Portuguese": "Bombas enfraquecedoras"}, "Karma": {"Spanish": "Intercambio", "English": "Exchange", "Portuguese": "Intercâmbio"}, "Big Lucky": {"Spanish": f'¡Felicitaciones! {_sp_} ¡GANASTE UN PREMIO ESPECIAL! {_sp_}"{subs}"', "English": f'Congratulations! {_sp_} YOU WON A SPECIAL PRIZE! {_sp_}"{subs}"', "Portuguese": f'Parabéns! {_sp_} GANHOU UM PRÉMIO ESPECIAL! {_sp_}"{subs}"'}, "Probability": {"Spanish": f"Premio Especial: {almacen[0]}% {_sp_} Monedas: {almacen[1]}%", "English": f"Special Award: {almacen[0]}% {_sp_} Coins: {almacen[1]}%", "Portuguese": f"Prêmio especial: {almacen[0]}% {_sp_} Moedas: {almacen[1]}%"}, "Happy Egg": {"Spanish": "El Huevón", "English": "Happy Egg", "Portuguese": "Ovo Vivo"}, "Lucky Store": {"Spanish": "Premio Misterioso", "English": "Surprise prize", "Portuguese": "Prêmio surpresa"}, } languages = ['Spanish', 'Portuguese', 'English'] if lang not in languages: lang = 'English' if text not in translate: return pm.getlanguage(text, subs, almacen) return translate[text][lang] # valuable def store_items(): oldstore = pm.store_items() newstore = {"Buy Lucky": False, "Lucky Karma": False, "Lucky Happy Egg": False} for c, v in newstore.items(): oldstore[c] = v return oldstore def default_powerups(): new_powers = {"Karma": 2, "Welfare": 1, "Teleport Bombs": 2, "Weakening Bombs": 2, "Toxic Bombs": 3, "Happy Egg": 1} powers = {} for (x, i) in pm.default_powerups().items(): powers[x] = i for (x, i) in new_powers.items(): powers[x] = i return powers apg = ba.app.config config = apg['PPM Settings'] powerups = config['Powerups'] for new_powers in default_powerups(): powerups = config['Powerups'] if new_powers not in powerups: for (x, i) in default_powerups().items(): powerups[x] = i for i, j in store_items().items(): store = apg['Bear Store'] if i not in store: if store.get(i) is None: store[i] = j if apg.get('Get Lucky') is None: apg['Get Lucky'] = 200 apg.apply_and_commit() # driving calculate = lambda s, i: (s * i / 100) users = {"toxic": [], "happEgg": [], "happeggObj": []} def powerup_dist(): powers = {'karma': powerups['Karma'], 'welfare': powerups['Welfare'], 'teleport_bombs': powerups['Teleport Bombs'], 'weakening_bombs': powerups['Weakening Bombs'], 'toxic_bombs': powerups['Toxic Bombs'], 'happy_egg': powerups['Happy Egg']} for (x, i) in pm.powerup_dist(): powers[x] = i return powers.items() def new_default_powerups(): return list(default_powerups()) def new_powerups(): from ba.internal import get_default_powerup_distribution old_power = [] for (x, j) in get_default_powerup_distribution(): old_power.append(x) new_power = [] for (x, j) in powerup_dist(): if x not in old_power: new_power.append(x) return new_power class EggBlastCooling: pass class NewBearStore(BearStore): def buy(self): if self.value == 'Buy Lucky': self.lucky() else: super().buy() def lucky(self): if not self.store: if self.coins >= (self.price): def confirm(): apg['Bear Coin'] -= int(self.price) self.certainty() def lag(): ba.timer(1.5, confirm) ConfirmWindow(getlanguage('Confirm Purchase', subs=self.coins), width=400, height=120, action=lag, ok_text=ba.Lstr(resource='okText')) else: ba.screenmessage(getlanguage('Coins 0'), (1, 0, 0)) ba.playsound(ba.getsound('error')) else: ba.screenmessage(getlanguage('Double Product'), (1, 0, 0)) ba.playsound(ba.getsound('error')) def certainty(self): getlucky = apg['Get Lucky'] if getlucky < 0: getlucky = 200 lucky = random.randint(1, getlucky) big_prizes = ["Lucky Karma", "Lucky Happy Egg"] prizes = [] for x in big_prizes: if not STORE[x]: prizes.append(x) reward = random.randint(50, 150) getlucky -= random.randint(5, 20) message = "Reward Code" sound = "cashRegister" if prizes != []: getprize = random.choice(prizes) if lucky == 1: reward = 0 getlucky = 200 message = "Big Lucky" sound = "cheer" STORE[getprize] = True prizes.remove(getprize) getprize = getprize.split('Lucky ')[1] if getlucky < 2: getlucky = 2 if prizes == []: getlucky = 0 STORE['Buy Lucky'] = True apg['Get Lucky'] = getlucky apg['Bear Coin'] += int(reward) if reward != 0: sub = reward ba.screenmessage(getlanguage('Reward Code', subs=sub), (0, 1, 0)) else: sub = getlanguage(getprize) ConfirmWindow(getlanguage(message, subs=sub.upper()), width=400, height=120, cancel_button=False, action=self.callback, ok_text=ba.Lstr(resource='okText')) ba.playsound(ba.getsound(sound)) apg.apply_and_commit() class EggPowerup(PowerupBox): def __init__(self, position: Sequence[float] = (0.0, 1.0, 0.0), velocity: Sequence[float] = (0.0, 1.0, 0.0), poweruptype: str = 'triple_bombs', expire: bool = True): super().__init__(position, poweruptype, expire) try: for x in self.texts: self.texts[x].delete() self.texts[x] = None self.texts = {} except: pass try: self.shield.delete() self.shield = None except: pass self.texts = {} self.node.velocity = velocity curve = ba.animate(self.node, 'model_scale', {0: 0, 0.14: 1.6, 0.2: 0.83}) ba.timer(0.2, curve.delete) class HappyEgg(ba.Actor): def __init__(self, format: str = 'powerup', position: Sequence[float] = (0.0, 1.0, 0.0), cooldown: float = 1.5, scale: float = 1.0, hitpoints: int = 3500, owner: ba.Node = None): super().__init__() self.tex = ba.gettexture('eggTex1') self.model = ba.getmodel('egg') self.model_simple = None self.shield = None self.info = None self.invincible = True self.objectives = [] self.session = ba.getsession() self.hitpoints = int(hitpoints) self.old_hitpoints = int(hitpoints) self.owner = owner self.scale = scale self.cooldown = cooldown self.format = format self.type = 'toxic' self.hit_type = 'explosion' self.eggname = owner.name self.eggcolor = owner.color self.eggnamecolor = self.owner.name_color self.dualteam = isinstance(self.session, ba.DualTeamSession) shared = SharedObjects.get() factory = PowerupBoxFactory.get() materials = (factory.powerup_material, shared.object_material, shared.player_material) self.node: ba.Node = ba.newnode('prop', delegate=self, attrs={'body': 'puck', 'position': position, 'model': self.model, 'light_model': self.model_simple, 'shadow_size': 0.5, 'density': 100, 'color_texture': self.tex, 'reflection': 'powerup', 'gravity_scale': 1, 'reflection_scale': [5.0], 'is_area_of_interest': True, 'model_scale': self.scale, 'body_scale': self.scale, 'materials': materials}) self.update() self.spaw_object(cooldown) ba.timer(6.0, ba.Call(self.immune, False)) def objective_mark(self, obj): mark = ba.newnode('light', attrs={'radius': 0.13, 'intensity': 1.2, 'color': (1.8, 0.3, 0.3)}) obj.connectattr('position', mark, 'position') ba.timer(2.5, mark.delete) def immunity_bubble(self): if self.shield is None and self.invincible: self.shield = ba.newnode('shield', owner=self.node, attrs={'color': (1.5, 1.5, 1.5), 'radius': 1.6}) self.node.connectattr('position', self.shield, 'position') if self.shield and not self.invincible: self.shield.delete() self.shield = None def egg_animate(self, time): eggsl = self.scale ba.animate(self.node, 'model_scale', {0: eggsl, 0.1: eggsl * 1.4, time: eggsl}) def immune(self, val: bool): self.invincible = val def spaw_object(self, time: float): self.obj_spaw_timer = ba.Timer(time, ba.WeakCall(self.handlemessage, EggBlastCooling()), repeat=True) def show_text(self, text: str, scale: float = 1.0, color: list = [1, 1, 1], position: list = [0, 0.7, 0], colors_name: bool = False, anim_text: bool = True): m = ba.newnode('math', owner=self.node, attrs={'input1': (position[0], position[1], position[2]), 'operation': 'add'}) self.node.connectattr('position', m, 'input2') if len(color) == 3: color = (color[0], color[1], color[2], 1.0) self.showpj = ba.newnode('text', owner=self.node, attrs={'text': str(text), 'in_world': True, 'scale': 0.02, 'shadow': 0.5, 'flatness': 1.0, 'color': color, 'h_align': 'center'}) m.connectattr('output', self.showpj, 'position') if anim_text: ba.animate(self.showpj, 'scale', {0: 0.017 * scale * 0.8, 0.4: 0.017 * scale * 0.8, 0.5: 0.01 * scale}) else: self.showpj.scale = (0.01 * scale) if colors_name: ba.animate_array(self.showpj, 'color', 3, {0: (1, 0, 0), 0.2: (1, 0.5, 0), 0.4: (1, 1, 0), 0.6: (0, 1, 0), 0.8: (0, 1, 1), 1.0: (1, 0, 1), 1.2: (1, 0, 0)}, True) return self.showpj def update(self): if self.format == 'bomb': decay = 3 decay_time = 0.9 else: decay = 1 decay_time = 1.0 if self.info is None: percentage = int(100 * self.hitpoints / self.old_hitpoints) text = ('HP: ' + str(self.hitpoints) + _sp_ + 'PCT: ' + str(percentage) + '%') if self.eggname != "": text = (str(self.eggname) + _sp_ + text) if self.dualteam: color = self.eggnamecolor else: color = (1.0, 1.0, 1.0) self.info = self.show_text(text, scale=1.1, color=color, position=(-1.4, 0.3, 0.0)) def decay_hp(): if not self.invincible: self.hitpoints -= decay self.hitpoints = int(self.hitpoints) def updall(): self.immunity_bubble() self.updtime() self.update_eggs() self.txt_timer = ba.Timer(0.1, ba.WeakCall(updall), repeat=True) self.decay_timer = ba.Timer(decay_time, ba.WeakCall(decay_hp), repeat=True) def updtime(self): percentage = (100 * self.hitpoints / self.old_hitpoints) percentage = 1 if percentage < 1 else int(percentage) text = ('HP: ' + str(self.hitpoints) + _sp_ + 'PCT: ' + str(percentage) + '%') if self.eggname != "": text = (str(self.eggname) + _sp_ + text) self.info.text = text if self.invincible: self.node.reflection_scale = [5.0] else: self.node.reflection_scale = [1.0] if percentage <= 1 and self.hitpoints <= 0: self.handlemessage(ba.DieMessage()) def update_owner(self): objectives = users['happeggObj'] if isinstance(self.session, ba.DualTeamSession): for sub_owner in objectives: if self.eggcolor == sub_owner.color: if sub_owner not in users['toxic']: users['toxic'].append(sub_owner) elif isinstance(self.session, ba.CoopSession): for sub_owner in objectives: if len(sub_owner.name) > 1: if sub_owner not in users['toxic']: users['toxic'].append(sub_owner) else: for owner in objectives: if self.eggname == owner.name: self.owner = owner if owner not in users['toxic']: users['toxic'].append(owner) def update_eggs(self): if users['happEgg'] != []: for s in users['happEgg']: if 'empty' in str(s.node): users['happEgg'].remove(s) if len(users['happEgg']) > 4: for x in users['happEgg']: x.node.handlemessage(ba.DieMessage(how=ba.DeathType.IMPACT)) break def add_users(self): objectives = users['happeggObj'] self.objectives = [] try: for obj in objectives: if 'empty' not in str(obj): if obj not in self.objectives: self.objectives.append(obj) for obj in self.objectives: if 'empty' in str(obj): self.objectives.remove(obj) for obj in objectives: if 'empty' in str(obj): users['happeggObj'].remove(obj) except: pass def fake_explosion(self, position: Sequence[float]): explosion = ba.newnode('explosion', attrs={'position': position, 'radius': 1.8, 'big': False}) ba.timer(1.0, explosion.delete) sounds = ['explosion0' + str(n) for n in range(1, 6)] sound = random.choice(sounds) ba.playsound(ba.getsound(sound)) def explosion(self, damage: float, position: Sequence[float]): blast = Blast(position=position, velocity=self.node.velocity, blast_radius=damage, blast_type=self.type, source_player=self.owner, hit_type=self.hit_type, hit_subtype=self.type).autoretain() return blast def handlemessage(self, msg: Any) -> Any: if isinstance(msg, EggBlastCooling): powers = [] for x, i in powerup_dist(): if x == 'happy_egg': continue powers.append(x) if not STORE['Buy Firebombs']: powers.remove('fire_bombs') i = self.node.position v = self.node.velocity vr = [random.uniform(-1, 2), random.uniform(-2, 3)] position = (i[0], i[1] + 1.2, i[2]) velocity = (v[0] + vr[1], v[1] + 13, v[2] + vr[0]) self.fake_explosion(position=(position[0], position[1] - 0.4, position[2])) self.egg_animate(0.5) if self.format == 'powerup': powerup = random.choice(powers) egg = EggPowerup(position=position, poweruptype=powerup, velocity=velocity, expire=False).autoretain() elif self.format == 'bomb': self.add_users() objectives_nodes = self.objectives if isinstance(self.session, ba.DualTeamSession): if objectives_nodes != []: players = [] for obj in objectives_nodes: if self.eggcolor == obj.color: players.append(obj) if players != []: for player in players: objectives_nodes.remove(player) elif isinstance(self.session, ba.CoopSession): if objectives_nodes != []: players = [] for obj in objectives_nodes: if len(obj.name) > 1: players.append(obj) if players != []: for player in players: objectives_nodes.remove(player) else: if objectives_nodes != []: players = [] for obj in objectives_nodes: if self.eggname == obj.name: players.append(obj) if players != []: for player in players: objectives_nodes.remove(player) vr = [random.uniform(-10, 10), random.uniform(-10, 10)] velocity = (velocity[0] * 1.2 + vr[0], velocity[1], velocity[2] * 1.2 + vr[1]) if objectives_nodes != []: velocity = (0, 13, 0) egg = Bomb(position=position, bomb_type='fire', velocity=velocity, owner=self.owner).autoretain() owner = random.choice(objectives_nodes) if objectives_nodes != [] else None egg.node.sticky = True if objectives_nodes != [] else False if any(objectives_nodes): self.objective_mark(owner) def aim_cooldown(): def aim_update(): if egg.node.exists(): bomb = egg.node egg.node.gravity_scale = 0 f = 8.2 position = ((owner.position[0] - bomb.position[0]) * f, (owner.position[1] - bomb.position[1]) * f, (owner.position[2] - bomb.position[2]) * f) egg.node.extra_acceleration = position egg.node.velocity = position else: self.aim_timer = None def stop(): self.aim_timer = None self.aim_timer = ba.Timer(0.1, ba.WeakCall(aim_update), repeat=True) ba.timer(2.0, stop) if objectives_nodes != []: ba.timer(0.2, aim_cooldown) elif isinstance(msg, ba.HitMessage): if not self.invincible: if msg.hit_type == 'punch': damage = calculate(106, msg.magnitude) if damage > 350: sound = ba.getsound('punchStrong02') elif damage > 90: sound = ba.getsound('punch01') else: sound = ba.getsound('punchWeak01') ba.playsound(sound, 1.0, position=self.node.position) elif msg.hit_type == 'explosion': damage = calculate(40, msg.magnitude) if msg.hit_subtype == 'fly': damage = calculate(7, msg.magnitude) self.node.handlemessage('impulse', msg.pos[0], msg.pos[1], msg.pos[2], msg.velocity[0], msg.velocity[1], msg.velocity[2], msg.magnitude, msg.velocity_magnitude, msg.radius, 0, msg.velocity[0], msg.velocity[1], msg.velocity[2]) else: damage = calculate(125, msg.magnitude) damage = int(damage) if msg.hit_type != 'explosion' and damage > 50: ba.show_damage_count('-' + str(damage) + 'HP', msg.pos, msg.force_direction) else: position = list(s for s in self.node.position) position[1] -= 0.8 self.popup_immune = PopupText(text=getlanguage('Invincible Text'), scale=1.5, position=position, color=(1, 1, 1)).autoretain() ba.playsound(SpazFactory.get().block_sound, 1.0, position=self.node.position) if self.node: self.hitpoints -= int(damage) if self.hitpoints <= 0: self.hitpoints = 0 if self.hitpoints == 0: self.handlemessage(ba.DieMessage()) elif isinstance(msg, ba.DieMessage): self.update_owner() if self.node: self.hitpoints = 0 ba.animate(self.node, 'model_scale', {0: self.scale, 0.1: 0}) self.txt_timer = None self.decay_timer = None self.obj_spaw_timer = None self.aim_timer = None self.explosion(damage=3, position=self.node.position) for happ in users['happEgg']: if happ.node == self.node: users['happEgg'].remove(happ) self.node.delete() elif isinstance(msg, ba.OutOfBoundsMessage): self.handlemessage(ba.DieMessage(how=ba.DeathType.FALL)) MainMenuActivity.noti = pm.new_on_transition_in def old_on_transition_in(self): self.bear_coin_message = False coins_message = GLOBAL['Coins Message'] self.noti() users['happEgg'] = [] users['happeggObj'] = [] items = list(store_items()) for X in store_items(): if STORE[X]: items.remove(X) if not self.bear_coin_message and any(items) and any(coins_message): if not apg['Bear Coin'] > 11000: result = 0 for r in coins_message: result += r ba.screenmessage(getlanguage('Coins Message', subs=result), (0, 1, 0)) ba.playsound(ba.getsound('cashRegister')) # Overwritten def powerup_translated(self, type: str): powerups_names = {'triple_bombs': ba.Lstr(resource='helpWindow.' + 'powerupBombNameText'), 'ice_bombs': ba.Lstr(resource='helpWindow.' + 'powerupIceBombsNameText'), 'punch': ba.Lstr(resource='helpWindow.' + 'powerupPunchNameText'), 'impact_bombs': ba.Lstr(resource='helpWindow.' + 'powerupImpactBombsNameText'), 'land_mines': ba.Lstr(resource='helpWindow.' + 'powerupLandMinesNameText'), 'sticky_bombs': ba.Lstr(resource='helpWindow.' + 'powerupStickyBombsNameText'), 'shield': ba.Lstr(resource='helpWindow.' + 'powerupShieldNameText'), 'health': ba.Lstr(resource='helpWindow.' + 'powerupHealthNameText'), 'curse': ba.Lstr(resource='helpWindow.' + 'powerupCurseNameText'), 'speed': getlanguage('Speed'), 'health_damage': getlanguage('Healing Damage'), 'goodbye': getlanguage('Goodbye'), 'ice_man': getlanguage('Ice Man'), 'tank_shield': getlanguage('Tank Shield'), 'impairment_bombs': getlanguage('Impairment Bombs'), 'fire_bombs': getlanguage('Fire Bombs'), 'fly_bombs': getlanguage('Fly Bombs'), 'karma': getlanguage('Karma'), 'teleport_bombs': getlanguage('Teleport Bombs'), 'toxic_bombs': getlanguage('Toxic Bombs'), 'weakening_bombs': getlanguage('Weakening Bombs'), 'welfare': getlanguage('Welfare'), 'happy_egg': getlanguage('Happy Egg')} if type not in powerups_names: powerups_names[type] = getlanguage(type) self.texts['Name'].text = powerups_names[type] pm.NewPowerupBoxFactory.superpowerupMEXP = pm.NewPowerupBoxFactory.__init__ def newNewPowerupBoxFactory(self): self.superpowerupMEXP() self.tex_karma = ba.gettexture('replayIcon') self.tex_welfare = ba.gettexture('achievementFootballShutout') self.tex_teleport_bombs = ba.gettexture('rightButton') self.tex_weakening_bombs = ba.gettexture('ouyaYButton') self.tex_toxic_bombs = ba.gettexture('logoEaster') self.tex_happy_egg = ba.gettexture('egg4') self._powerupdist = [] for powerup, freq in powerup_dist(): for _i in range(int(freq)): self._powerupdist.append(powerup) PowerupBox.super_powerup_box = PowerupBox.__init__ def plus_powerupbox(self, position: Sequence[float] = (0.0, 1.0, 0.0), poweruptype: str = 'triple_bombs', expire: bool = True): self.old_powerup = poweruptype factory = pm.NewPowerupBoxFactory.get() if self.old_powerup in new_powerups(): new_poweruptype = 'shield' else: new_poweruptype = poweruptype self.super_powerup_box(position, new_poweruptype, expire) try: if ('Name') in self.texts: self.texts['Name'].delete() except: None tex = self.node.color_texture if self.old_powerup == 'speed': tex = factory.tex_speed elif self.old_powerup == 'health_damage': tex = factory.tex_health_damage elif self.old_powerup == 'goodbye': tex = factory.tex_goodbye elif self.old_powerup == 'ice_man': tex = factory.tex_ice_man elif self.old_powerup == 'tank_shield': tex = factory.tex_tank_shield elif self.old_powerup == 'impairment_bombs': tex = factory.tex_impairment_bombs elif self.old_powerup == 'fire_bombs': tex = factory.tex_fire_bombs elif self.old_powerup == 'fly_bombs': tex = factory.tex_fly_bombs elif self.old_powerup == 'karma': tex = factory.tex_karma elif self.old_powerup == 'welfare': tex = factory.tex_welfare elif self.old_powerup == 'teleport_bombs': tex = factory.tex_teleport_bombs elif self.old_powerup == 'weakening_bombs': tex = factory.tex_weakening_bombs elif self.old_powerup == 'toxic_bombs': tex = factory.tex_toxic_bombs elif self.old_powerup == 'happy_egg': tex = factory.tex_happy_egg self.poweruptype = self.old_powerup self.node.color_texture = tex def util_text(type: str, text: str, scale: float = 1, color: list = [1, 1, 1], position: list = [0, 0.7, 0], colors_name: bool = False): m = ba.newnode('math', owner=self.node, attrs={'input1': (position[0], position[1], position[2]), 'operation': 'add'}) self.node.connectattr('position', m, 'input2') self.texts[type] = ba.newnode('text', owner=self.node, attrs={'text': str(text), 'in_world': True, 'scale': 0.02, 'shadow': 0.5, 'flatness': 1.0, 'color': (color[0], color[1], color[2]), 'h_align': 'center'}) m.connectattr('output', self.texts[type], 'position') ba.animate(self.texts[type], 'scale', {0: 0.017, 0.4: 0.017, 0.5: 0.01 * scale}) if colors_name: ba.animate_array(self.texts[type], 'color', 3, {0: (1, 0, 0), 0.2: (1, 0.5, 0), 0.4: (1, 1, 0), 0.6: (0, 1, 0), 0.8: (0, 1, 1), 1.0: (1, 0, 1), 1.2: (1, 0, 0)}, True) if config['Powerup Name']: util_text('Name', self.poweruptype, scale=1.2, position=[0, 0.4, 0], colors_name=True) powerup_translated(self, self.poweruptype) PowerupBox.super_pbhm = PowerupBox.handlemessage def spb_handlemessage(self, msg: Any) -> Any: if isinstance(msg, ba.HitMessage): if msg.hit_subtype != 'fly': self.super_pbhm(msg) else: self.node.handlemessage('impulse', msg.pos[0], msg.pos[1], msg.pos[2], msg.velocity[0], msg.velocity[1], msg.velocity[2], msg.magnitude, msg.velocity_magnitude, msg.radius, 0, msg.velocity[0], msg.velocity[1], msg.velocity[2]) else: self.super_pbhm(msg) # Bomb def bombInit(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): self.bm_type = bomb_type new_bomb_type = bomb_type bombs = ['ice_bubble', 'impairment', 'fire', 'fly'] self.ibombs = ['teleport', 'weakening', 'toxic'] if bomb_type in bombs: new_bomb_type = 'ice' if bomb_type in self.ibombs: new_bomb_type = 'impact' self._pm_old_bomb(position, velocity, new_bomb_type, blast_radius, bomb_scale, source_player, owner) bombShield = False sColor = (2.0, 2.0, 2.0) sScale = 0.6 tex = self.node.color_texture if self.bm_type == 'impairment': tex = ba.gettexture('eggTex3') elif self.bm_type == 'fly': tex = ba.gettexture('eggTex1') elif self.bm_type == 'teleport': tex = ba.gettexture('aliColorMask') self.node.gravity_scale = 0.5 elif self.bm_type == 'weakening': tex = ba.gettexture('ouyaYButton') self.node.model = ba.getmodel('frostyPelvis') elif self.bm_type == 'toxic': tex = ba.gettexture('landMine') elif self.bm_type == 'ice_bubble': self.node.model = None bombShield = True sColor = (0.5, 1.0, 7.0) elif self.bm_type == 'fire': self.node.model = None bombShield = True sColor = (6.5, 6.5, 2.0) self.fire_effect_time = ba.Timer(0.1, ba.WeakCall(pm.fire_effect, self), repeat=True) self.node.color_texture = tex self.bomb_type = self.bm_type self.hit_subtype = self.bomb_type if bombShield: self.bomb_shield = ba.newnode('shield', owner=self.node, attrs={'color': sColor, 'radius': sScale}) self.node.connectattr('position', self.bomb_shield, 'position') if self.bomb_type == 'toxic': if owner not in users['toxic']: users['toxic'].append(owner) if self.bomb_type == 'ice_bubble': self.blast_radius *= 1.2 elif self.bomb_type == 'fly': self.blast_radius *= 2.2 elif self.bomb_type == 'teleport': self.blast_radius *= 0.0 elif self.bomb_type == 'weakening': self.blast_radius *= 1.3 def handleImpact(self) -> None: node = ba.getcollision().opposingnode node_delegate = node.getdelegate(object) self.ibombs.append('impact') if node: if (self.bomb_type in self.ibombs and (node is self.owner or (isinstance(node_delegate, Bomb) and node_delegate.bomb_type in self.ibombs and node_delegate.owner is self.owner))): return self.handlemessage(bomb.ExplodeMessage()) Bomb.nht = Bomb._handle_hit def new_handle_hit(self, msg: ba.HitMessage) -> None: bomb = self.bomb_type if bomb in self.ibombs: self.bomb_type = 'impact' self.nht(msg) self.bomb_type = bomb Bomb.oldExplode = Bomb.explode def newExplode(self): self.oldExplode() if self.bomb_type == 'teleport': self._source_player.actor.node.handlemessage( ba.StandMessage(position=self.node.position)) elif self.bomb_type == 'toxic': ba.emitfx(position=self.node.position, scale=2, count=35, spread=0.5, chunk_type='slime') Bomb.nbhm = Bomb.handlemessage def bombhandlemessage(self, msg: Any) -> Any: if isinstance(msg, ba.HitMessage): if msg.hit_subtype != 'fly': self.nbhm(msg) else: self.node.handlemessage('impulse', msg.pos[0], msg.pos[1], msg.pos[2], msg.velocity[0], msg.velocity[1], msg.velocity[2], msg.magnitude, msg.velocity_magnitude, msg.radius, 0, msg.velocity[0], msg.velocity[1], msg.velocity[2]) else: self.nbhm(msg) def blast_handlemessage(self, msg: Any) -> Any: assert not self.expired if isinstance(msg, ba.DieMessage): if self.node: self.node.delete() elif isinstance(msg, bomb.ExplodeHitMessage): node = ba.getcollision().opposingnode assert self.node nodepos = self.node.position mag = 2000.0 if self.blast_type in ('ice', 'ice_bubble'): mag *= 0.5 elif self.blast_type == 'land_mine': mag *= 2.5 elif self.blast_type == 'tnt': mag *= 2.0 elif self.blast_type == 'fire': mag *= 0.46 elif self.blast_type == 'fly': mag *= 5.5 elif self.blast_type == 'weakening': mag *= 0.0 elif self.blast_type == 'teleport': mag *= 0.0 elif self.blast_type == 'toxic': mag *= 0.6 node.handlemessage( ba.HitMessage(pos=nodepos, velocity=(0, 0, 0), magnitude=mag, hit_type=self.hit_type, hit_subtype=self.hit_subtype, radius=self.radius, source_player=ba.existing(self._source_player))) if self.blast_type in ('ice', 'ice_bubble'): ba.playsound(bomb.BombFactory.get().freeze_sound, 10, position=nodepos) node.handlemessage(ba.FreezeMessage()) return None # Spaz def welfare_UcallF1(self): def welfe(): if self.shWelfare: self.shWelfare.delete() self.shWelfare = None if self.welfareGm: self.welfareGm = False self.node.invincible = False self.timW.delete() del self.txts['TimerWelfare'] self.timeWelfare = None try: ba.timer(4.0, ba.WeakCall(welfe)) except: pass self.wfare_timer = None self.welfare = False self.node.hurt = 0 hp = int(self.oldHP - self.hitpoints) if self.toxic_effect: reduction = int(calculate(85, hp)) hp = int(hp - reduction - 1) label = '+' + str(int(hp)) + 'HP' PopupText(text=label, scale=1.5, position=self.node.position, color=(0, 1, 0)).autoretain() ba.playsound(ba.getsound('healthPowerup')) self.hitpoints += hp def welfare_UcallF2(self): self.node.handlemessage('knockout', 1000) if self.shWelfare is None: self.shWelfare = ba.newnode('shield', owner=self.node, attrs={'color': (1, 1, 1), 'radius': 1.2}) self.node.connectattr('position_center', self.shWelfare, 'position') if not self.node.invincible: self.welfareGm = True self.node.invincible = True if self.timeWelfare is None: self.timeWelfare = 4 self.welfare100 = 0 self.welfare_pctj = self.timeWelfare self.timeWelfare -= 0.01 self.welfare100 += 0.01 self.timeWelfare = round(self.timeWelfare, 2) self.welfare100 = round(self.welfare100, 2) pctj = int(100 * self.welfare100 / self.welfare_pctj) type = 'TimerWelfare' up = ba.charstr(ba.SpecialChar.UP_ARROW) if type not in self.txts: self.timW = uText(self, type, color=(1.0, 1.0, 1.0), text=(up + str(pctj) + '%'), scale=1.8, position=(1.1, -0.6, 0.0)) self.timW.text = (up + str(pctj) + '%') if self.timeWelfare <= 0.0: welfare_UcallF1(self) animate_color = lambda a, b, c, d: ba.animate_array(self.timW, 'color', 3, {0: a, c[0]: b, c[1]: a}, d) animate_color2 = lambda a, b, c: ba.animate_array(self.timW, 'color', 3, {0: (a[0], a[1], a[2]), c[0]: (b[0], b[1], b[2]), c[1]: (a[0], a[1], a[2])}, True) if (pctj % 10) == 0: c = [(1.5, 1.5, 0.0), (0.0, 1.0, 0.0)] s = random.choice(c) animate_color(c[0], c[1], [0.3, 0.6], True) if pctj == 100: # Update animate_color2([0, 1, 1], [0.5, 0, 1], [0.2, 0.4]) self.timW.scale *= 0.89 self.timW.text += _sp_ + getlanguage('Complete') def welfare_call(self): if not self._dead: hp = int(calculate(10, self.oldHP)) if self.hitpoints <= (hp + 1): self.welfare_timer = None self.wfare_timer = ba.Timer(0.01, ba.WeakCall(welfare_UcallF2, self), repeat=True) else: self.welfare_timer = None def karma_effect(self): hp = int(calculate(30, self.oldHP)) if self.hitpoints <= (hp + 1): self.karma = True if self.karma and self.hitpoints >= 1: if self.karma_shield is None: self.karma_shield = ba.newnode('shield', owner=self.node, attrs={'color': (0, 1, 6), 'radius': 1.2}) self.node.connectattr('position_center', self.karma_shield, 'position') ba.playsound(ba.getsound('shieldUp')) self.karma_timer = None def cooldown_weakening_pctj(self, time: float): self.weakTimer = None self.weakTimer = ba.Timer(time, ba.WeakCall(weakening_pctj, self), repeat=True) def weakening_pctj(self, health: bool = False): if self.node and not self._dead: self.weakening_dmg += 1 pctj = self.weakening_dmg down = ba.charstr(ba.SpecialChar.DOWN_ARROW) if self.weakText is None: self.weakText = uText(self, 'Weakening', color=(1.0, 1.0, 1.0), text=(down + str(pctj) + '%'), scale=1.2, position=(-0.7, -0.35, -0.8)) self.weakText.text = (down + str(pctj) + '%') if self.weakening_dmg >= 100: time = float(calculate(1.5, self.weakening_dmg)) cooldown_weakening_pctj(self, time) if health: self.weakening_dmg = 0 try: self.weakText.delete() except: pass self.weakening = False self.weakText = None self.weakTimer = None else: self.weakTimer = None def hit_sound(self): sounds = random.choice(self.node.impact_sounds) return ba.playsound(sounds, volume=1.0, position=self.node.position) def spaw_happy_egg(self, format, time: float = 4.0): position = [s for s in self.node.position] position[1] += 0.5 egg = HappyEgg(position=position, cooldown=time, format=format, scale=1.2, hitpoints=4200, owner=self.node) users['happEgg'].append(egg) return egg def disable_powerup_effects(self, s=[]): if s != []: for x in s: if x == 'karma': if self.karma_shield: self.karma_shield.delete() self.karma_shield = None self.karma = None self.karma_life = False self.karma_timer = None elif x == 'welfare': if self.shWelfare: self.shWelfare.delete() self.shWelfare = None self.welfare_timer = None self.timeWelfare = None self.welfare = False elif x == 'tank': if self.tankshield['Shield']: self.tankshield['Shield'].delete() self.tankshield['Shield'] = None self.tankshield['Tank'] = False self.tankshield['Reduction'] = None elif x == 'autocure': if self.edg_eff: a = self.color[0] b = (2, 0, 0) c = (0, 2, 0) ba.animate_array(self.node, 'color', 3, {0: b, 0.6: c, 1.0: a}) self.edg_eff = False def uText(self, type: str, text: str, scale: float = 1.0, color: list = [1, 1, 1], position: list = [0, 0.7, 0], colors_name: bool = False, anim_text: bool = True): m = ba.newnode('math', owner=self.node, attrs={'input1': (position[0], position[1], position[2]), 'operation': 'add'}) self.node.connectattr('position_center', m, 'input2') if len(color) == 3: color = (color[0], color[1], color[2], 1.0) self.txts[type] = ba.newnode('text', owner=self.node, attrs={'text': str(text), 'in_world': True, 'scale': 0.02, 'shadow': 0.5, 'flatness': 1.0, 'color': color, 'h_align': 'center'}) m.connectattr('output', self.txts[type], 'position') if anim_text: ba.animate(self.txts[type], 'scale', {0: 0.017 * scale * 0.8, 0.4: 0.017 * scale * 0.8, 0.5: 0.01 * scale}) else: self.txts[type].scale = (0.01 * scale) if colors_name: ba.animate_array(self.txts[type], 'color', 3, {0: (1, 0, 0), 0.2: (1, 0.5, 0), 0.4: (1, 1, 0), 0.6: (0, 1, 0), 0.8: (0, 1, 1), 1.0: (1, 0, 1), 1.2: (1, 0, 0)}, True) return self.txts[type] def set_bombs_count(self, count: int, bomb_id: str = None) -> None: if bomb_id == 'teleport': self.teleport_count = count if self.node: if self.teleport_count != 0: self.node.counter_text = 'x' + str(self.teleport_count) self.node.counter_texture = ( pm.NewPowerupBoxFactory.get().tex_teleport_bombs) else: self.node.counter_text = '' elif bomb_id == 'weakening': self.weakening_count = count if self.node: if self.weakening_count != 0: self.node.counter_text = 'x' + str(self.weakening_count) self.node.counter_texture = ( pm.NewPowerupBoxFactory.get().tex_weakening_bombs) else: self.node.counter_text = '' def new_drop_bomb(self) -> Optional[stdbomb.Bomb]: if (self.land_mine_count <= 0 and self.bomb_count <= 0 and self.teleport_count <= 0) or self.frozen: return None assert self.node pos = self.node.position_forward vel = self.node.velocity if self.land_mine_count > 0: dropping_bomb = False self.set_land_mine_count(self.land_mine_count - 1) bomb_type = 'land_mine' elif self.teleport_count > 0: dropping_bomb = False bomb_type = 'teleport' set_bombs_count(self, self.teleport_count - 1, bomb_id=bomb_type) elif self.weakening_count > 0: dropping_bomb = False bomb_type = 'weakening' set_bombs_count(self, self.weakening_count - 1, bomb_id=bomb_type) else: dropping_bomb = True bomb_type = self.bomb_type bomb = stdbomb.Bomb(position=(pos[0], pos[1] - 0.0, pos[2]), velocity=(vel[0], vel[1], vel[2]), bomb_type=bomb_type, blast_radius=self.blast_radius, source_player=self.source_player, owner=self.node).autoretain() self.mybomb = bomb self.nodebomb = bomb.owner assert bomb.node if dropping_bomb: self.bomb_count -= 1 bomb.node.add_death_action( ba.WeakCall(self.handlemessage, BombDiedMessage())) self._pick_up(bomb.node) for clb in self._dropped_bomb_callbacks: clb(self, bomb) return bomb def update_toxic_users(): try: for user in users['toxic']: if 'empty' in str(user): users['toxic'].remove(user) except: pass Spaz.superSpaz = Spaz.__init__ def _init_spaz_(self, *args, **kwargs): self.superSpaz(*args, **kwargs) self.teleport_count = 0 self.weakening_count = 0 self.weakening_dmg = 0 self.toxic_time = 25 self.toxic_time += 1 self.txts = {} self.popupsList = {} self.oldHP = self.hitpoints self.karma_shield = None self.shWelfare = None self.timeWelfare = None self.welfareGm = None self.weakText = None self.nodebomb = None self.popupHurt = None self.karma = False self.karma_life = False self.welfare = False self.weakening = False self.toxic_effect = False self.toxic_popup = None self.sow_happy_egg = False users['happeggObj'].append(self.node) self.max_toxic_time = self.toxic_time Spaz.opps = Spaz.on_pickup_press Spaz.opps = Spaz.on_pickup_press def spaz_on_pickup_press(self) -> None: self.opps() if self.sow_happy_egg: spaw_happy_egg(self, 'powerup', time=3.8) ba.playsound(ba.getsound('powerup01')) self.sow_happy_egg = False Spaz.opp = Spaz.on_punch_press def spaz_on_punch_press(self) -> None: self.opp() if self.sow_happy_egg: spaw_happy_egg(self, 'bomb', time=5.2) ba.playsound(ba.getsound('powerup01')) self.sow_happy_egg = False def new_get_bomb_type_tex(self) -> ba.Texture: factory = NewPowerupBoxFactory.get() if self.bomb_type == 'sticky': return factory.tex_sticky_bombs if self.bomb_type == 'ice': return factory.tex_ice_bombs if self.bomb_type == 'impact': return factory.tex_impact_bombs if self.bomb_type == 'impairment': return factory.tex_impairment_bombs if self.bomb_type == 'fire': return factory.tex_fire_bombs if self.bomb_type == 'fly': return factory.tex_fly_bombs if self.bomb_type == 'toxic': return factory.tex_toxic_bombs raise ValueError('invalid bomb type') def newHandleMessage(self, msg: Any) -> Any: assert not self.expired update_toxic_users() if self.hitpoints > self.oldHP: self.oldHP = self.hitpoints if isinstance(msg, ba.PickedUpMessage): if self.node: self.node.handlemessage('hurt_sound') self.node.handlemessage('picked_up') self._num_times_hit += 1 elif isinstance(msg, ba.ShouldShatterMessage): ba.timer(0.001, ba.WeakCall(self.shatter)) elif isinstance(msg, ba.ImpactDamageMessage): ba.timer(0.001, ba.WeakCall(self._hit_self, msg.intensity)) elif isinstance(msg, ba.PowerupMessage): factory = NewPowerupBoxFactory.get() if self._dead or not self.node: return True if self.pick_up_powerup_callback is not None: self.pick_up_powerup_callback(self) if msg.poweruptype == 'triple_bombs': tex = PowerupBoxFactory.get().tex_bomb self._flash_billboard(tex) self.set_bomb_count(3) if self.powerups_expire: self.node.mini_billboard_1_texture = tex t_ms = ba.time(timeformat=ba.TimeFormat.MILLISECONDS) assert isinstance(t_ms, int) self.node.mini_billboard_1_start_time = t_ms self.node.mini_billboard_1_end_time = ( t_ms + POWERUP_WEAR_OFF_TIME) self._multi_bomb_wear_off_timer = (ba.Timer( (POWERUP_WEAR_OFF_TIME - 2000), ba.WeakCall(self._multi_bomb_wear_off_flash), timeformat=ba.TimeFormat.MILLISECONDS)) self._multi_bomb_wear_off_timer = (ba.Timer( POWERUP_WEAR_OFF_TIME, ba.WeakCall(self._multi_bomb_wear_off), timeformat=ba.TimeFormat.MILLISECONDS)) elif msg.poweruptype == 'land_mines': set_bombs_count(self, min(0, 1), bomb_id='teleport') set_bombs_count(self, min(0, 1), bomb_id='weakening') self.set_land_mine_count(min(self.land_mine_count + 3, 3)) elif msg.poweruptype == 'impact_bombs': self.bomb_type = 'impact' tex = self._get_bomb_type_tex() self._flash_billboard(tex) if self.powerups_expire: self.node.mini_billboard_2_texture = tex t_ms = ba.time(timeformat=ba.TimeFormat.MILLISECONDS) assert isinstance(t_ms, int) self.node.mini_billboard_2_start_time = t_ms self.node.mini_billboard_2_end_time = ( t_ms + POWERUP_WEAR_OFF_TIME) self._bomb_wear_off_flash_timer = (ba.Timer( POWERUP_WEAR_OFF_TIME - 2000, ba.WeakCall(self._bomb_wear_off_flash), timeformat=ba.TimeFormat.MILLISECONDS)) self._bomb_wear_off_timer = (ba.Timer( POWERUP_WEAR_OFF_TIME, ba.WeakCall(self._bomb_wear_off), timeformat=ba.TimeFormat.MILLISECONDS)) elif msg.poweruptype == 'sticky_bombs': self.bomb_type = 'sticky' tex = self._get_bomb_type_tex() self._flash_billboard(tex) if self.powerups_expire: self.node.mini_billboard_2_texture = tex t_ms = ba.time(timeformat=ba.TimeFormat.MILLISECONDS) assert isinstance(t_ms, int) self.node.mini_billboard_2_start_time = t_ms self.node.mini_billboard_2_end_time = ( t_ms + POWERUP_WEAR_OFF_TIME) self._bomb_wear_off_flash_timer = (ba.Timer( POWERUP_WEAR_OFF_TIME - 2000, ba.WeakCall(self._bomb_wear_off_flash), timeformat=ba.TimeFormat.MILLISECONDS)) self._bomb_wear_off_timer = (ba.Timer( POWERUP_WEAR_OFF_TIME, ba.WeakCall(self._bomb_wear_off), timeformat=ba.TimeFormat.MILLISECONDS)) elif msg.poweruptype == 'punch': self._has_boxing_gloves = True tex = PowerupBoxFactory.get().tex_punch self._flash_billboard(tex) self.equip_boxing_gloves() if self.powerups_expire: self.node.boxing_gloves_flashing = False self.node.mini_billboard_3_texture = tex t_ms = ba.time(timeformat=ba.TimeFormat.MILLISECONDS) assert isinstance(t_ms, int) self.node.mini_billboard_3_start_time = t_ms self.node.mini_billboard_3_end_time = ( t_ms + POWERUP_WEAR_OFF_TIME) self._boxing_gloves_wear_off_flash_timer = (ba.Timer( POWERUP_WEAR_OFF_TIME - 2000, ba.WeakCall(self._gloves_wear_off_flash), timeformat=ba.TimeFormat.MILLISECONDS)) self._boxing_gloves_wear_off_timer = (ba.Timer( POWERUP_WEAR_OFF_TIME, ba.WeakCall(self._gloves_wear_off), timeformat=ba.TimeFormat.MILLISECONDS)) elif msg.poweruptype == 'shield': factory = SpazFactory.get() self.equip_shields(decay=factory.shield_decay_rate > 0) elif msg.poweruptype == 'curse': self.curse() elif msg.poweruptype == 'ice_bombs': self.bomb_type = 'ice' tex = self._get_bomb_type_tex() self._flash_billboard(tex) if self.powerups_expire: self.node.mini_billboard_2_texture = tex t_ms = ba.time(timeformat=ba.TimeFormat.MILLISECONDS) assert isinstance(t_ms, int) self.node.mini_billboard_2_start_time = t_ms self.node.mini_billboard_2_end_time = ( t_ms + POWERUP_WEAR_OFF_TIME) self._bomb_wear_off_flash_timer = (ba.Timer( POWERUP_WEAR_OFF_TIME - 2000, ba.WeakCall(self._bomb_wear_off_flash), timeformat=ba.TimeFormat.MILLISECONDS)) self._bomb_wear_off_timer = (ba.Timer( POWERUP_WEAR_OFF_TIME, ba.WeakCall(self._bomb_wear_off), timeformat=ba.TimeFormat.MILLISECONDS)) elif msg.poweruptype == 'health': disable_powerup_effects(self, s=['tank', 'karma', 'autocure', 'walfere']) if self._cursed: self._cursed = False factory = SpazFactory.get() for attr in ['materials', 'roller_materials']: materials = getattr(self.node, attr) if factory.curse_material in materials: setattr( self.node, attr, tuple(m for m in materials if m != factory.curse_material)) self.node.curse_death_time = 0 if self.weakening: weakening_pctj(self, health=True) self.hitpoints = self.hitpoints_max self._flash_billboard(PowerupBoxFactory.get().tex_health) self.node.hurt = 0 self._last_hit_time = None self._num_times_hit = 0 if self.toxic_effect: reduction = int(calculate(85, self.hitpoints)) self.hitpoints = int(self.hitpoints - reduction) elif msg.poweruptype == 'weakening_bombs': self.set_land_mine_count(min(0, 3)) set_bombs_count(self, min(0, 1), bomb_id='teleport') set_bombs_count(self, min(self.weakening_count + 2, 3), bomb_id='weakening') elif msg.poweruptype == 'teleport_bombs': self.set_land_mine_count(min(0, 3)) set_bombs_count(self, min(0, 1), bomb_id='weakening') set_bombs_count(self, min(self.teleport_count + 1, 1), bomb_id='teleport') elif msg.poweruptype == 'welfare': disable_powerup_effects(self, s=['autocure', 'tank', 'karma']) hp = int(calculate(10, self.oldHP)) if not self.hitpoints <= (hp + 1): self.welfare = True self.welfare_timer = ba.Timer(0.01, ba.WeakCall(welfare_call, self), repeat=True) else: welfare_UcallF1(self) tex = factory.tex_welfare self._flash_billboard(tex) elif msg.poweruptype == 'happy_egg': tex = factory.tex_happy_egg self._flash_billboard(tex) self.sow_happy_egg = True elif msg.poweruptype == 'karma': disable_powerup_effects(self, s=['autocure', 'tank', 'welfare']) self.karma_life = True self.karma_timer = ba.Timer( 0.1, ba.WeakCall(karma_effect, self), repeat=True) tex = factory.tex_karma self._flash_billboard(tex) elif msg.poweruptype == 'tank_shield': disable_powerup_effects(self, s=['autocure', 'karma', 'welfare']) self.tankshield['Tank'] = True tex = factory.tex_tank_shield self._flash_billboard(tex) elif msg.poweruptype == 'health_damage': disable_powerup_effects(self, s=['tank', 'welfare', 'karma']) tex = factory.tex_health_damage self._flash_billboard(tex) self.edg_eff = True self.freeze_punch = False elif msg.poweruptype == 'goodbye': tex = factory.tex_goodbye self._flash_billboard(tex) self.kill_eff = True elif msg.poweruptype == 'fly_bombs': self.bomb_type = 'fly' tex = self._get_bomb_type_tex() self._flash_billboard(tex) if self.powerups_expire: self.node.mini_billboard_2_texture = tex t_ms = ba.time(timeformat=ba.TimeFormat.MILLISECONDS) assert isinstance(t_ms, int) self.node.mini_billboard_2_start_time = t_ms self.node.mini_billboard_2_end_time = ( t_ms + POWERUP_WEAR_OFF_TIME) self._bomb_wear_off_flash_timer = (ba.Timer( POWERUP_WEAR_OFF_TIME - 2000, ba.WeakCall(self._bomb_wear_off_flash), timeformat=ba.TimeFormat.MILLISECONDS)) self._bomb_wear_off_timer = (ba.Timer( POWERUP_WEAR_OFF_TIME, ba.WeakCall(self._bomb_wear_off), timeformat=ba.TimeFormat.MILLISECONDS)) elif msg.poweruptype == 'fire_bombs': self.bomb_type = 'fire' tex = self._get_bomb_type_tex() self._flash_billboard(tex) if self.powerups_expire: self.node.mini_billboard_2_texture = tex t_ms = ba.time(timeformat=ba.TimeFormat.MILLISECONDS) assert isinstance(t_ms, int) self.node.mini_billboard_2_start_time = t_ms self.node.mini_billboard_2_end_time = ( t_ms + POWERUP_WEAR_OFF_TIME) self._bomb_wear_off_flash_timer = (ba.Timer( POWERUP_WEAR_OFF_TIME - 2000, ba.WeakCall(self._bomb_wear_off_flash), timeformat=ba.TimeFormat.MILLISECONDS)) self._bomb_wear_off_timer = (ba.Timer( POWERUP_WEAR_OFF_TIME, ba.WeakCall(self._bomb_wear_off), timeformat=ba.TimeFormat.MILLISECONDS)) elif msg.poweruptype == 'impairment_bombs': self.bomb_type = 'impairment' tex = self._get_bomb_type_tex() self._flash_billboard(tex) if self.powerups_expire: self.node.mini_billboard_2_texture = tex t_ms = ba.time(timeformat=ba.TimeFormat.MILLISECONDS) assert isinstance(t_ms, int) self.node.mini_billboard_2_start_time = t_ms self.node.mini_billboard_2_end_time = ( t_ms + POWERUP_WEAR_OFF_TIME) self._bomb_wear_off_flash_timer = (ba.Timer( POWERUP_WEAR_OFF_TIME - 2000, ba.WeakCall(self._bomb_wear_off_flash), timeformat=ba.TimeFormat.MILLISECONDS)) self._bomb_wear_off_timer = (ba.Timer( POWERUP_WEAR_OFF_TIME, ba.WeakCall(self._bomb_wear_off), timeformat=ba.TimeFormat.MILLISECONDS)) elif msg.poweruptype == 'toxic_bombs': self.bomb_type = 'toxic' tex = self._get_bomb_type_tex() self._flash_billboard(tex) if self.powerups_expire: self.node.mini_billboard_2_texture = tex t_ms = ba.time(timeformat=ba.TimeFormat.MILLISECONDS) assert isinstance(t_ms, int) self.node.mini_billboard_2_start_time = t_ms self.node.mini_billboard_2_end_time = ( t_ms + POWERUP_WEAR_OFF_TIME) self._bomb_wear_off_flash_timer = (ba.Timer( POWERUP_WEAR_OFF_TIME - 2000, ba.WeakCall(self._bomb_wear_off_flash), timeformat=ba.TimeFormat.MILLISECONDS)) self._bomb_wear_off_timer = (ba.Timer( POWERUP_WEAR_OFF_TIME, ba.WeakCall(self._bomb_wear_off), timeformat=ba.TimeFormat.MILLISECONDS)) elif msg.poweruptype == 'ice_man': disable_powerup_effects(self, s=['autocure', 'tank', 'karma']) tex = factory.tex_ice_man self.bomb_type = 'ice_bubble' self.freeze_punch = True self.node.color = (0, 1, 4) self._flash_billboard(tex) if self.powerups_expire: ice_man_time = 17000 self.node.mini_billboard_2_texture = tex t_ms = ba.time(timeformat=ba.TimeFormat.MILLISECONDS) assert isinstance(t_ms, int) self.node.mini_billboard_2_start_time = t_ms self.node.mini_billboard_2_end_time = (t_ms + ice_man_time) self.ice_man_flash_timer = (ba.Timer( ice_man_time - 2000, ba.WeakCall(pm._ice_man_off_flash, self), timeformat=ba.TimeFormat.MILLISECONDS)) self.ice_man_timer = (ba.Timer(ice_man_time, ba.WeakCall(pm._ice_man_wear_off, self), timeformat=ba.TimeFormat.MILLISECONDS)) elif msg.poweruptype == 'speed': disable_powerup_effects(self, s=['autocure', 'tank']) self.node.hockey = True tex = factory.tex_speed self._flash_billboard(tex) if self.powerups_expire: speed_time = 15000 self.node.mini_billboard_2_texture = tex t_ms = ba.time(timeformat=ba.TimeFormat.MILLISECONDS) assert isinstance(t_ms, int) self.node.mini_billboard_2_start_time = t_ms self.node.mini_billboard_2_end_time = (t_ms + speed_time) self.speed_flash_timer = (ba.Timer( speed_time - 2000, ba.WeakCall(pm._speed_off_flash, self), timeformat=ba.TimeFormat.MILLISECONDS)) self.speed_timer = (ba.Timer(speed_time, ba.WeakCall(pm._speed_wear_off, self), timeformat=ba.TimeFormat.MILLISECONDS)) self.bmb_color: list = [] self.bmb_color.append(self.bomb_type) self.node.handlemessage('flash') if msg.sourcenode: msg.sourcenode.handlemessage(ba.PowerupAcceptMessage()) return True elif isinstance(msg, ba.FreezeMessage): if not self.node: return None if self.node.invincible: ba.playsound(SpazFactory.get().block_sound, 1.0, position=self.node.position) return None if self.shield: return None if not self.frozen: self.frozen = True self.node.frozen = True ba.timer(5.0, ba.WeakCall(self.handlemessage, ba.ThawMessage())) if self.hitpoints <= 0: self.shatter() if self.freeze_punch: self.handlemessage(ba.ThawMessage()) elif isinstance(msg, ba.ThawMessage): if self.frozen and not self.shattered and self.node: self.frozen = False self.node.frozen = False elif isinstance(msg, ba.HitMessage): yash_hidden = True if not self.node: return None if self.node.invincible: ba.playsound(SpazFactory.get().block_sound, 1.0, position=self.node.position) if self.shWelfare: try: if self.popupFireInv.node.exists(): popup = True else: popup = False self.popupFireInv = None except: popup = False self.popupFireInv = None if not popup: self.popupFireInv = PopupText(text=getlanguage('Invincible Text'), scale=1.5, position=self.node.position, color=(1, 1, 1)).autoretain() return True local_time = ba.time(timeformat=ba.TimeFormat.MILLISECONDS) assert isinstance(local_time, int) if (self._last_hit_time is None or local_time - self._last_hit_time > 1000): self._num_times_hit += 1 self._last_hit_time = local_time mag = msg.magnitude * self.impact_scale velocity_mag = msg.velocity_magnitude * self.impact_scale damage_scale = 0.22 def delete_popup(type: str, owner: ba.Node, time: int): if type not in self.popupsList: self.popupsList[type] = 0 self.popupsList[type] += 1 if self.popupsList[type] >= int(time) or self._dead: if type == 'Popup Hurt': self.popupHurtTimer = None elif type == 'Popup Autocure': self.popupAutoCureTimer = None del self.popupsList[type] owner.delete() if owner.exists(): return [type, self.popupsList[type]] return None def edgEff(damage, time=100, edg_eff_enable=True): porcentaje = percentage_health_damage() cure = int(damage * porcentaje) if not edg_eff_enable: cure = int(damage) if self.toxic_effect: reduction = int(calculate(85, cure)) cure = int(cure - reduction) try: if self.popupAutoCure.exists(): result = 0 popup = True if self.popupAutoCureDelete[1] is not None: t = self.popupAutoCureDelete[0] self.popupsList[t] = 0 self.popupAutoCureCount.append(cure) for x in self.popupAutoCureCount: result += x self.popupAutoCure.text = ('+' + str(result) + 'HP') else: result = 0 popup = False self.popupAutoCure = None self.popupAutoCureCount = [cure] except: result = 0 popup = False self.popupAutoCure = None self.popupAutoCureCount = [cure] self.hitpoints += cure if not popup: tag = ('Popup Autocure') self.popupAutoCure = uText(self, tag, (f'+{cure}HP'), scale=1.35, color=(0.25, 1.0, 0.25), position=(0, 1.3, 0), anim_text=False) self.popupAutoCureScale = self.popupAutoCure.scale self.popupAutoCureDelete = delete_popup(tag, self.popupAutoCure, time) self.popupAutoCureTimer = ba.Timer(0.01, ba.WeakCall(delete_popup, tag, self.popupAutoCure, time), repeat=True) scale = 1.0 if cure != 0: if cure >= 800 or result >= 800: scale = 1.30 elif cure >= 500 or result >= 500: scale = 1.20 elif cure >= 280 or result >= 280: scale = 1.10 s = (self.popupAutoCureScale * scale) c = self.popupAutoCure.scale ba.animate(self.popupAutoCure, 'scale', {0: c, 0.20: s}) ba.animate_array(self.node, 'color', 3, {0: (0, 1, 0), 0.39: (0, 2, 0), 0.4: self.color[0]}) ba.playsound(ba.getsound('healthPowerup')) def popup_effect(damage, time=100): try: if self.popupHurt.exists(): result = 0 popup = True if self.popupHurtDelete[1] is not None: t = self.popupHurtDelete[0] self.popupsList[t] = 0 self.popupHurtCount.append(damage) for x in self.popupHurtCount: result += x self.popupHurt.text = ('-' + str(result) + 'HP') else: result = 0 popup = False self.popupHurt = None self.popupHurtCount = [damage] except: result = 0 popup = False self.popupHurt = None self.popupHurtCount = [damage] if not popup: tag = ('Popup Hurt') self.popupHurt = uText(self, tag, (f'-{damage}HP'), scale=1.35, color=(1, 0.25, 0.25), position=(0, 0.65, 0), anim_text=False) self.popupHurtScale = self.popupHurt.scale self.popupHurtDelete = delete_popup(tag, self.popupHurt, time) self.popupHurtTimer = ba.Timer(0.01, ba.WeakCall(delete_popup, tag, self.popupHurt, time), repeat=True) scale = 1.0 if damage != 0: if damage >= 800 or result >= 800: scale = 1.30 elif damage >= 500 or result >= 500: scale = 1.20 elif damage >= 280 or result >= 280: scale = 1.10 s = (self.popupHurtScale * scale) c = self.popupHurt.scale ba.animate(self.popupHurt, 'scale', {0: c, 0.20: s}) def hurt_node(damage, time=100, popup=True): if self.weakening: nerf = int(calculate(self.weakening_dmg, damage)) damage = int(damage + nerf) if self.tankshield['Reduction']: porcentaje = percentage_tank_shield() dism = int(damage * porcentaje) damage = int(damage - dism) if self.edg_eff: edgEff(damage, time=time) if self.karma_shield: damage = int(damage * 0.02) if self.hitpoints < 0: if self.welfare and self.hitpoints <= 1: self.hitpoints = 1 elif self.karma_life and self.hitpoints <= 1: self.hitpoints = int(calculate(29, self.oldHP)) self.karma_life = False else: self.node.handlemessage(ba.DieMessage()) if popup: popup_effect(damage, time) return [self.popupHurt, damage] def fire_effect(): if not self.shield: if self.node.exists(): ba.emitfx(position=self.node.position, scale=3, count=50 * 2, spread=0.3, chunk_type='sweat') self.node.handlemessage('celebrate', 560) else: self._fire_time = None else: self._fire_time = None def fire(time, damage): if not self.node.invincible: if not self.shield and not self._dead: hurt = hurt_node(damage) dps = hurt[1] if self.hitpoints >= dps: hit_sound(self) self.hitpoints -= dps ba.playsound(ba.getsound('fuse01')) if duration != time: self._fire_time = ba.Timer(0.1, ba.Call(fire_effect), repeat=True) else: self._fire_time = None if self.hitpoints <= 0: self.node.handlemessage(ba.DieMessage()) else: s = [i for i in self.node.position] position = (s[0], s[1] - 1.2, s[2]) try: if self.popupFireInv.node.exists(): popup = True else: popup = False self.popupFireInv = None except: popup = False self.popupFireInv = None if not popup: self.popupFireInv = PopupText(text=getlanguage('Invincible Text'), scale=1.5, position=position, color=(1, 1, 1)).autoretain() self._fire_time = None def exchange(viceversa, position, sound=False): sym = "+" color = (0, 1, 0) if viceversa == 0: msg.get_source_player(ba.Player).actor.karma = True elif viceversa <= 0: sym = "" color = (1, 0, 0) if sound: ba.playsound(ba.getsound('laserReverse')) else: if sound: ba.playsound(ba.getsound('laser')) if viceversa != 0: actor = msg.get_source_player(ba.Player).actor if actor.karma_shield: actor.karma_shield.delete() actor.karma_shield = None actor.karma = False PopupText(text=f"{sym}{viceversa}HP", scale=1.5, position=position, color=color).autoretain() def karma_exchange(): try: actor = msg.get_source_player(ba.Player).actor self.mHp = actor.hitpoints self.mNode = actor.node self.yHp = self.hitpoints if actor.karma: if self.nodebomb != actor.node: self.hitpoints = self.mHp actor.hitpoints = self.yHp exchange(int(self.yHp - self.mHp), self.mNode.position, sound=True) exchange(int(self.mHp - self.yHp), self.node.position) except: pass def conectividad(): if self.node in users['toxic']: return True return False def toxic_cure(cure): if self.hitpoints != self.oldHP: if self.hitpoints < self.oldHP: edgEff(cure, edg_eff_enable=False) if self.hitpoints >= self.oldHP: self.hitpoints = self.oldHP def toxic_damage(time): self._multi_bomb_wear_off() self.toxic_time = self.max_toxic_time down = ba.charstr(ba.SpecialChar.DOWN_ARROW) if self.toxic_popup is None: self.toxic_popup = uText(self, 'Toxic Bomb', color=(1.0, 1.0, 1.0), text=(down + str(int(self.toxic_time)) + 's'), scale=1.5, position=(0.75, -0.60, -0.8)) def toxic(): if self.node and not self._dead: if self.toxic_time != 0: self.bomb_count = 0 self.toxic_effect = True self.toxic_popup.text = (down + str(int(self.toxic_time)) + 's') self.toxic_time = round(self.toxic_time - 0.1, 1) else: self.bomb_count = 1 self.toxic_effect = False self.toxic_popup.delete() self.toxic_popup = None self.toxic_bomb_effect_timer = None self.toxic_time = self.max_toxic_time else: self.toxic_bomb_effect_timer = None self.toxic_bomb_effect_timer = ba.Timer(0.1, ba.WeakCall(toxic), repeat=True) if msg.hit_subtype == 'fly': damage_scale = 0.0 if self.shield: self.node.handlemessage('impulse', msg.pos[0], msg.pos[1], msg.pos[2], msg.velocity[0], msg.velocity[1], msg.velocity[2], msg.magnitude, msg.velocity_magnitude, msg.radius, 0, msg.velocity[0], msg.velocity[1], msg.velocity[2]) self.shield_hitpoints -= 300 if self.shield_hitpoints < 0: self.shield.delete() self.shield = None ba.playsound(SpazFactory.get().shield_down_sound, 1.0, position=self.node.position) elif msg.hit_subtype == 'fire': index = 1 duration = 6 damage = 84 if not self.shield: for firex in range(duration): ba.timer(index, ba.WeakCall(fire, index, damage)) self._fire_time = ba.Timer(0.1, ba.Call(fire_effect), repeat=True) index += 1 else: self.shield_hitpoints -= 160 if self.shield_hitpoints <= 1: self.shield.delete() self.shield = None ba.playsound(SpazFactory.get().shield_down_sound, 1.0, position=self.node.position) elif msg.hit_subtype == 'impairment': damage_scale = 0 bckshield = False if self.shield: self.shield.delete() self.shield = None bckshield = True ba.playsound(SpazFactory.get().shield_down_sound, 1.0, position=self.node.position) elif msg.hit_subtype == 'weakening': actor = msg.get_source_player(ba.Player).actor damage_scale = 0 if self.nodebomb != actor.node: if not self.weakening: self.weakening = True weakening_pctj(self) self.weakTimer = ba.Timer(0.3, ba.WeakCall(weakening_pctj, self), repeat=True) else: plus = int(calculate(10, self.hitpoints)) s = self.weakText.position scale = self.weakText.scale * 120 self.weakening_dmg += plus weakening_pctj(self) position = (s[0], s[1] - 0.9, s[2]) PopupText(text=f"+{plus}%", scale=scale, position=position, color=(1, 1, 1)).autoretain() elif self.nodebomb == self.node: weakening_pctj(self, health=True) elif msg.hit_subtype == 'toxic': if conectividad(): damage_scale = 0 if self.karma_shield: disable_powerup_effects(self, s=['karma']) if self.node: yash_hidden = False cure = int(calculate(25, self.oldHP)) toxic_cure(cure) ba.timer(1.0, ba.Call(toxic_cure, cure)) else: time = 8 toxic_damage(time) if self.node in users['toxic']: users['toxic'].remove(self.node) if self.shield: if msg.flat_damage: damage = msg.flat_damage * self.impact_scale else: 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], mag, velocity_mag, msg.radius, 1, msg.force_direction[0], msg.force_direction[1], msg.force_direction[2]) damage = damage_scale * self.node.damage assert self.shield_hitpoints is not None self.shield_hitpoints -= int(damage) self.shield.hurt = (1.0 - float(self.shield_hitpoints) / self.shield_hitpoints_max) max_spillover = SpazFactory.get().max_shield_spillover_damage if self.shield_hitpoints <= 0: self.shield.delete() self.shield = None ba.playsound(SpazFactory.get().shield_down_sound, 1.0, position=self.node.position) npos = self.node.position ba.emitfx(position=(npos[0], npos[1] + 0.9, npos[2]), velocity=self.node.velocity, count=random.randrange(20, 30), scale=1.0, spread=0.6, chunk_type='spark') else: ba.playsound(SpazFactory.get().shield_hit_sound, 0.5, position=self.node.position) assert msg.force_direction is not None ba.emitfx(position=msg.pos, velocity=(msg.force_direction[0] * 1.0, msg.force_direction[1] * 1.0, msg.force_direction[2] * 1.0), count=min(30, 5 + int(damage * 0.005)), scale=0.5, spread=0.3, chunk_type='spark') if self.shield_hitpoints <= -max_spillover: leftover_damage = -max_spillover - self.shield_hitpoints shield_leftover_ratio = leftover_damage / damage mag *= shield_leftover_ratio velocity_mag *= shield_leftover_ratio else: return True else: shield_leftover_ratio = 1.0 if msg.flat_damage: damage = int(msg.flat_damage * self.impact_scale * shield_leftover_ratio) else: if yash_hidden: 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], mag, velocity_mag, msg.radius, 0, msg.force_direction[0], msg.force_direction[1], msg.force_direction[2]) damage = int(damage_scale * self.node.damage) if msg.hit_subtype == 'impairment': if not bckshield: hitpoints = int(calculate(80, self.hitpoints)) damage = int(hitpoints) hp = 100 if self.hitpoints < 0 or hitpoints < hp: self.node.handlemessage(ba.DieMessage()) hurtnode = hurt_node(damage, popup=False) damage = hurtnode[1] if (msg.hit_subtype == 'impairment' or self.tankshield['Reduction'] or self.karma_shield or self.weakening): popup_effect(damage) karma_exchange() self.node.handlemessage('hurt_sound') if msg.hit_type == 'punch': self.on_punched(damage) try: if msg.get_source_player(ba.Player).actor.freeze_punch: self.node.color = (0, 1, 4) ba.playsound(ba.getsound('freeze')) self.node.handlemessage(ba.FreezeMessage()) except: pass if damage > 350: assert msg.force_direction is not None ba.show_damage_count('-' + str(int(damage / 10)) + '%', msg.pos, msg.force_direction) if msg.hit_subtype == 'super_punch': ba.playsound(SpazFactory.get().punch_sound_stronger, 1.0, position=self.node.position) if damage > 500: sounds = SpazFactory.get().punch_sound_strong sound = sounds[random.randrange(len(sounds))] else: sound = SpazFactory.get().punch_sound ba.playsound(sound, 1.0, position=self.node.position) assert msg.force_direction is not None ba.emitfx(position=msg.pos, velocity=(msg.force_direction[0] * 0.5, msg.force_direction[1] * 0.5, msg.force_direction[2] * 0.5), count=min(10, 1 + int(damage * 0.0025)), scale=0.3, spread=0.03) ba.emitfx(position=msg.pos, chunk_type='sweat', velocity=(msg.force_direction[0] * 1.3, msg.force_direction[1] * 1.3 + 5.0, msg.force_direction[2] * 1.3), count=min(30, 1 + int(damage * 0.04)), scale=0.9, spread=0.28) hurtiness = damage * 0.003 punchpos = (msg.pos[0] + msg.force_direction[0] * 0.02, msg.pos[1] + msg.force_direction[1] * 0.02, msg.pos[2] + msg.force_direction[2] * 0.02) flash_color = (1.0, 0.8, 0.4) light = ba.newnode( 'light', attrs={ 'position': punchpos, 'radius': 0.12 + hurtiness * 0.12, 'intensity': 0.3 * (1.0 + 1.0 * hurtiness), 'height_attenuated': False, 'color': flash_color}) ba.timer(0.06, light.delete) flash = ba.newnode('flash', attrs={ 'position': punchpos, 'size': 0.17 + 0.17 * hurtiness, 'color': flash_color }) ba.timer(0.06, flash.delete) if msg.hit_type == 'impact': assert msg.force_direction is not None ba.emitfx(position=msg.pos, velocity=(msg.force_direction[0] * 2.0, msg.force_direction[1] * 2.0, msg.force_direction[2] * 2.0), count=min(10, 1 + int(damage * 0.01)), scale=0.4, spread=0.1) if self.hitpoints > 0: if msg.hit_type == 'impact' and damage > self.hitpoints: newdamage = max(damage - 200, self.hitpoints - 10) damage = newdamage self.node.handlemessage('flash') if damage > 0.0 and self.node.hold_node: self.node.hold_node = None self.hitpoints -= damage if self.welfare and self.hitpoints <= 1: self.hitpoints = 1 if (self.karma_life and self.hitpoints <= int(calculate(28, self.oldHP))): if not self.karma_shield: self.hitpoints = int(calculate(29, self.oldHP)) self.karma_life = False else: self.karma_life = False self.node.hurt = 1.0 - float( self.hitpoints) / self.hitpoints_max if self._cursed and damage > 0: ba.timer(0.05, ba.WeakCall(self.curse_explode, msg.get_source_player(ba.Player))) if self.frozen and (damage > 200 or self.hitpoints <= 0): self.shatter() elif self.hitpoints <= 0: self.node.handlemessage( ba.DieMessage(how=ba.DeathType.IMPACT)) if self.hitpoints <= 0: damage_avg = self.node.damage_smoothed * damage_scale if damage_avg > 1000: self.shatter() elif isinstance(msg, BombDiedMessage): self.bomb_count += 1 elif isinstance(msg, ba.DieMessage): def drop_bomb(): for xbomb in range(3): p = self.node.position pos = (p[0] + xbomb, p[1] + 5, p[2] - xbomb) ball = bomb.Bomb(position=pos, bomb_type='impact').autoretain() ball.node.model_scale = 0.6 ball.node.model = ba.getmodel('egg') ball.node.gravity_scale = 2 if self.edg_eff: self.edg_eff = False try: users['happeggObj'].remove(self.node) except: pass wasdead = self._dead self._dead = True self.hitpoints = 0 if msg.immediate: if self.node: self.node.delete() elif self.node: self.node.hurt = 1.0 if self.play_big_death_sound and not wasdead: ba.playsound(SpazFactory.get().single_player_death_sound) self.node.dead = True ba.timer(2.0, self.node.delete) t = 0 if self.kill_eff: for bombs in range(3): ba.timer(t, ba.WeakCall(drop_bomb)) t += 0.15 self.kill_eff = False elif isinstance(msg, ba.OutOfBoundsMessage): self.handlemessage(ba.DieMessage(how=ba.DeathType.FALL)) elif isinstance(msg, ba.StandMessage): self._last_stand_pos = (msg.position[0], msg.position[1], msg.position[2]) if self.node: self.node.handlemessage('stand', msg.position[0], msg.position[1], msg.position[2], msg.angle) elif isinstance(msg, CurseExplodeMessage): self.curse_explode() elif isinstance(msg, PunchHitMessage): if not self.node: return None node = ba.getcollision().opposingnode if node and (node not in self._punched_nodes): punch_momentum_angular = (self.node.punch_momentum_angular * self._punch_power_scale) punch_power = self.node.punch_power * self._punch_power_scale if node.getnodetype() != 'spaz': sounds = SpazFactory.get().impact_sounds_medium sound = sounds[random.randrange(len(sounds))] ba.playsound(sound, 1.0, position=self.node.position) ppos = self.node.punch_position punchdir = self.node.punch_velocity vel = self.node.punch_momentum_linear self._punched_nodes.add(node) node.handlemessage( ba.HitMessage( pos=ppos, velocity=vel, magnitude=punch_power * punch_momentum_angular * 110.0, velocity_magnitude=punch_power * 40, radius=0, srcnode=self.node, source_player=self.source_player, force_direction=punchdir, hit_type='punch', hit_subtype=('super_punch' if self._has_boxing_gloves else 'default'))) mag = -400.0 if self._hockey: mag *= 0.5 if len(self._punched_nodes) == 1: self.node.handlemessage('kick_back', ppos[0], ppos[1], ppos[2], punchdir[0], punchdir[1], punchdir[2], mag) elif isinstance(msg, PickupMessage): if not self.node: return None try: collision = ba.getcollision() opposingnode = collision.opposingnode opposingbody = collision.opposingbody except ba.NotFoundError: return True try: if opposingnode.invincible: return True except Exception: pass if (opposingnode.getnodetype() == 'spaz' and not opposingnode.shattered and opposingbody == 4): opposingbody = 1 held = self.node.hold_node if held and held.getnodetype() == 'flag': return True self.node.hold_body = opposingbody self.node.hold_node = opposingnode elif isinstance(msg, ba.CelebrateMessage): if self.node: self.node.handlemessage('celebrate', int(msg.duration * 1000)) return None class NewPowerupManagerWindow(pm.PowerupManagerWindow): def __init__(self, transition='in_right'): columns = 2 super().__init__(transition=transition) self.old_tabs = self.tab_buttons self.default_powerups = default_powerups() self.default_power_list = new_default_powerups() self.tab_buttons: set = {} self.tabdefs = {"Action 1": ['powerupIceBombs', (1, 1, 1)], "Action 2": ['settingsIcon', (0, 1, 0)], "Action 3": ['inventoryIcon', (1, 1, 1)], "Action 4": ['storeIcon', (1, 1, 1)], "Action 5": ['advancedIcon', (1, 1, 1)], "About": ['heart', (1.5, 0.3, 0.3)]} if (STORE['Buy Firebombs'] and STORE['Buy Option'] and STORE['Buy Percentage'] and STORE['Lucky Karma'] and STORE['Lucky Happy Egg']): self.tabdefs = {"Action 1": ['powerupIceBombs', (1, 1, 1)], "Action 2": ['settingsIcon', (0, 1, 0)], "Action 3": ['inventoryIcon', (1, 1, 1)], "About": ['heart', (1.5, 0.3, 0.3)]} self.listdef = list(self.tabdefs) self.count = len(self.tabdefs) if not STORE['Buy Firebombs']: powerups['Fire Bombs'] = 0 self.default_power_list.remove('Fire Bombs') if not STORE['Lucky Karma']: powerups['Karma'] = 0 self.default_power_list.remove('Karma') if not STORE['Lucky Happy Egg']: powerups['Happy Egg'] = 0 self.default_power_list.remove('Happy Egg') self.tabs(columns) self._set_tab(self._current_tab) def _set_tab(self, tab, sound: bool = False): super()._set_tab(tab, sound=sound) if tab in ('Action 1', 'Action 4', 'Percentage'): self._tab_container.delete() self._tab_container = None if tab == 'Action 4': self._refresh_coins_timer = ba.Timer(0.1, ba.WeakCall(self.refresh_coins), repeat=True) else: self._refresh_coins_timer = None if tab == 'Action 1': sub_height = len(self.default_power_list) * 90 v = sub_height - 55 width = 300 posi = 0 id_power = list(self.default_powerups) new_powerups = id_power[9:] self.listpower = {} self._tab_container = c = ba.containerwidget(parent=self._scrollwidget, size=(self._sub_width, sub_height), background=False, selection_loops_to_parent=True) for power in self.default_power_list: s = self.return_tex_and_label(power) text = s[0] tex = s[1] if power in new_powerups: label = getlanguage(power) else: label = ba.Lstr(resource=text) apperance = powerups[power] position = (90, v - posi) t = ba.textwidget(parent=c, position=(position[0] - 30, position[1] - 15), size=(width, 50), h_align="center", color=(ba.app.ui.title_color), text=label, v_align="center", maxwidth=width * 1.3) self.powprev = ba.imagewidget(parent=c, position=(position[0] - 70, position[1] - 10), size=(50, 50), texture=tex) dipos = 0 for direc in ['-', '+']: ba.buttonwidget(parent=c, autoselect=True, position=(position[0] + 270 + dipos, position[1] - 10), size=(100, 100), scale=0.4, label=direc, button_type='square', text_scale=4, on_activate_call=ba.Call(self.apperance_powerups, power, direc)) dipos += 100 textwidget = ba.textwidget(parent=c, position=(position[0] + 190, position[1] - 15), size=(width, 50), h_align="center", color=cls_pow_color()[apperance], text=str(apperance), v_align="center", maxwidth=width * 1.3) self.listpower[power] = textwidget posi += 90 elif tab == 'Action 4': sub_height = 370 width = 300 v = sub_height - 55 u = width - 60 self._tab_container = c = ba.containerwidget(parent=self._scrollwidget, size=(width + 750, sub_height), background=False, selection_loops_to_parent=True) sitems = list(pm.store_items()) sitems.append('Buy Lucky') position = (u + 100 * 4, v - 250) n_pos = 0 prices = [7560, 5150, 3360, 300] str_name = ["FireBombs Store", "Timer Store", "Percentages Store", "Lucky Store"] images = ["ouyaOButton", "settingsIcon", "inventoryIcon", "star"] index = 0 for store in sitems: p = prices[index] txt = str_name[index] label = getlanguage(txt) tx_pos = len(label) * 1.8 lb_scale = len(label) * 0.20 preview = images[index] if STORE[store]: text = getlanguage('Bought') icon = ba.gettexture('graphicsIcon') color = (0.52, 0.48, 0.63) txt_scale = 1.5 else: text = str(p) icon = ba.gettexture('coin') color = (0.5, 0.4, 0.93) txt_scale = 2 b = ba.buttonwidget(parent=c, autoselect=True, position=(position[0] + 210 - n_pos, position[1]), size=(250, 80), scale=0.7, label=text, text_scale=txt_scale, icon=icon, color=color, iconscale=1.7, on_activate_call=ba.Call(self._buy_object, store, p)) s = 180 b = ba.buttonwidget(parent=c, autoselect=True, position=(position[0] + 210 - n_pos, position[1] + 55), size=(s, s + 30), scale=1, label='', color=color, button_type='square', on_activate_call=ba.Call(self._buy_object, store, p)) s -= 80 i = ba.imagewidget(parent=c, draw_controller=b, position=(position[0] + 250 - n_pos, position[1] + 140), size=(s, s), texture=ba.gettexture(preview)) t = ba.textwidget(parent=c, position=(position[0] + 270 - n_pos, position[1] + 101), h_align="center", color=(ba.app.ui.title_color), text=label, v_align="center", maxwidth=130) if store == 'Buy Lucky': nb = ba.buttonwidget(parent=c, autoselect=True, position=(position[0] + 210 - n_pos + 130, position[1] + 150 * 1.7), size=(40, 40), scale=0.7, label="?", text_scale=1, color=(0.5, 0.5, 1), button_type='square', on_activate_call=ba.Call(self.lucky_info)) n_pos += 280 index += 1 if len(images) == index: break elif tab == 'Percentage': sub_height = len(self.default_power_list) * 90 v = sub_height - 55 width = 300 posi = 0 id_power = list(self.default_powerups) new_powerups = id_power[9:] self._tab_container = c = ba.containerwidget(parent=self._scrollwidget, size=(self._sub_width, sub_height), background=False, selection_loops_to_parent=True) for power in self.default_power_list: s = self.return_tex_and_label(power) text = s[0] tex = s[1] if power in new_powerups: label = getlanguage(power) else: label = ba.Lstr(resource=text) apperance = powerups[power] position = (90, v - posi) t = ba.textwidget(parent=c, position=(position[0] - 30, position[1] - 15), size=(width, 50), h_align="center", color=(ba.app.ui.title_color), text=label, v_align="center", maxwidth=width * 1.3) self.powprev = ba.imagewidget(parent=c, position=(position[0] - 70, position[1] - 10), size=(50, 50), texture=tex) ptg = str(self.total_percentage(power)) t = ba.textwidget(parent=c, position=(position[0] + 170, position[1] - 10), size=(width, 50), h_align="center", color=(0, 1, 0), text=(f'{ptg}%'), v_align="center", maxwidth=width * 1.3) posi += 90 def _set_concept(self, concept: str) -> None: GLOBAL['Cls Powerup'] = concept if concept == 'Reset': for power, deflt in default_powerups().items(): powerups[power] = deflt elif concept == 'Nothing': for power in default_powerups(): powerups[power] = 0 elif concept == 'Only Bombs': for power, deflt in default_powerups().items(): if 'Bombs' not in power: powerups[power] = 0 else: powerups[power] = 3 elif concept == 'Only Items': for power, deflt in default_powerups().items(): if 'Bombs' in power: powerups[power] = 0 else: powerups[power] = deflt elif concept == 'New': default_power = default_powerups() new_powerups = list(default_power)[9:] for power, deflt in default_power.items(): if power not in new_powerups: powerups[power] = 0 else: powerups[power] = deflt if not STORE['Buy Firebombs']: powerups['Fire Bombs'] = 0 if not STORE['Lucky Karma']: powerups['Karma'] = 0 if not STORE['Lucky Happy Egg']: powerups['Happy Egg'] = 0 self._set_tab('Action 1') def lucky_info(self): ply = apg['Get Lucky'] try: lucky = ply - 1 almacen = [round(100 * 1 / ply, 6), round(100 * lucky / ply, 6)] except: almacen = [0.00, 100.00] info = getlanguage('Probability', almacen=almacen) ConfirmWindow(info, width=200, height=100 * 1.5, cancel_button=False, ok_text=ba.Lstr(resource='okText')) def _buy_object(self, tag: str, price: int): store = NewBearStore(value=tag, price=price, callback=ba.Call(self.store_refresh, tag)) store.buy() def tabs(self, columns): index = 0 for tab in self.old_tabs: self.old_tabs[tab].delete() self.text.delete() self.image.delete() self.old_tabs = None for tab in range(self.count): for tab2 in range(columns): tag = self.listdef[index] position = (620 + (tab2 * 120), self._height - 50 * 2.5 - (tab * 120)) if tag == 'About': text = ba.Lstr(resource='gatherWindow.aboutText') elif tab == 'Action 4': text = ba.Lstr(resource='storeText') else: text = getlanguage(tag) self.tab_buttons[tag] = ba.buttonwidget(parent=self._root_widget, autoselect=True, position=position, size=(110, 110), scale=1, label='', enable_sound=False, button_type='square', on_activate_call=ba.Call(self._set_tab, tag, sound=True)) self.text = ba.textwidget(parent=self._root_widget, position=(position[0] + 55, position[1] + 30), size=(0, 0), scale=1, color=ba.app.ui.title_color, draw_controller=self.tab_buttons[tag], maxwidth=100, text=text, h_align='center', v_align='center') self.image = ba.imagewidget(parent=self._root_widget, size=(60, 60), color=self.tabdefs[tag][1], draw_controller=self.tab_buttons[tag], position=(position[0] + 25, position[1] + 40), texture=ba.gettexture(self.tabdefs[tag][0])) index += 1 if self.count == index: break if self.count == index: break def store_refresh(self, tag: str): if tag == 'Buy Firebombs': powerups['Fire Bombs'] = 3 self.default_power_list.append('Fire Bombs') elif tag == 'Buy Lucky': self._back() self._set_tab('Action 4') def refresh_coins(self): ba.buttonwidget(edit=self.button_coin, label=str(apg['Bear Coin'])) def return_tex_and_label(self, power) -> None: i = list(self.default_powerups) if power == i[0]: text = 'helpWindow.powerupShieldNameText' tex = ba.gettexture('powerupShield') elif power == i[1]: text = 'helpWindow.powerupPunchNameText' tex = ba.gettexture('powerupPunch') elif power == i[2]: text = 'helpWindow.powerupLandMinesNameText' tex = ba.gettexture('powerupLandMines') elif power == i[3]: text = 'helpWindow.powerupImpactBombsNameText' tex = ba.gettexture('powerupImpactBombs') elif power == i[4]: text = 'helpWindow.powerupIceBombsNameText' tex = ba.gettexture('powerupIceBombs') elif power == i[5]: text = 'helpWindow.powerupBombNameText' tex = ba.gettexture('powerupBomb') elif power == i[6]: text = 'helpWindow.powerupStickyBombsNameText' tex = ba.gettexture('powerupStickyBombs') elif power == i[7]: text = 'helpWindow.powerupCurseNameText' tex = ba.gettexture('powerupCurse') elif power == i[8]: text = 'helpWindow.powerupHealthNameText' tex = ba.gettexture('powerupHealth') elif power == i[9]: text = power tex = ba.gettexture('powerupSpeed') elif power == i[10]: text = power tex = ba.gettexture('heart') elif power == i[11]: text = "Goodbye!" tex = ba.gettexture('achievementOnslaught') elif power == i[12]: text = power tex = ba.gettexture('ouyaUButton') elif power == i[13]: text = power tex = ba.gettexture('achievementSuperPunch') elif power == i[14]: text = power tex = ba.gettexture('levelIcon') elif power == i[15]: text = power tex = ba.gettexture('ouyaOButton') elif power == i[16]: text = power tex = ba.gettexture('star') elif power == i[17]: text = power tex = ba.gettexture('replayIcon') elif power == i[18]: text = power tex = ba.gettexture('achievementFootballShutout') elif power == i[19]: text = power tex = ba.gettexture('rightButton') elif power == i[20]: text = power tex = ba.gettexture('ouyaYButton') elif power == i[21]: text = power tex = ba.gettexture('logoEaster') elif power == i[22]: text = power tex = ba.gettexture('egg4') return [text, tex] def _back(self): super()._back() self._refresh_coins_timer = None # Plugin_data def powerupManagerExpansion(): pm.NewPowerupBoxFactory.__init__ = newNewPowerupBoxFactory pm.PowerupManagerWindow = NewPowerupManagerWindow Spaz.__init__ = _init_spaz_ Spaz._get_bomb_type_tex = new_get_bomb_type_tex Spaz.on_punch_press = spaz_on_punch_press Spaz.on_pickup_press = spaz_on_pickup_press Spaz.handlemessage = newHandleMessage Spaz.drop_bomb = new_drop_bomb Bomb.__init__ = bombInit Bomb.explode = newExplode Bomb._handle_impact = handleImpact Bomb._handle_hit = new_handle_hit Bomb.handlemessage = bombhandlemessage PowerupBox.__init__ = plus_powerupbox PowerupBox.handlemessage = spb_handlemessage Blast.handlemessage = blast_handlemessage MainMenuActivity.on_transition_in = old_on_transition_in # ba_meta export plugin class PowerupManagerExpansion(pm.UltimatePowerupManager): powerupManagerExpansion()