Merge pull request #233 from CrossJoy/main

Added and Updating my mods
This commit is contained in:
brostos 2024-02-14 15:32:48 +03:00 committed by GitHub
commit 7c4ffaf2e2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 660 additions and 585 deletions

View file

@ -826,7 +826,7 @@
} }
}, },
"disco_light": { "disco_light": {
"description": "Add disco light into the game.", "description": "Add disco light into the game. Do '/disco' to turn on and '/disco off' to turn off",
"external_url": "", "external_url": "",
"authors": [ "authors": [
{ {
@ -836,6 +836,12 @@
} }
], ],
"versions": { "versions": {
"2.1.0": {
"api_version": 8,
"commit_sha": "41046ae",
"released_on": "14-02-2024",
"md5sum": "bfffb346d61958c02015dde0b1520ca3"
},
"1.0.1": { "1.0.1": {
"api_version": 8, "api_version": 8,
"commit_sha": "2b5c9ee", "commit_sha": "2b5c9ee",
@ -851,7 +857,7 @@
} }
}, },
"practice_tools": { "practice_tools": {
"description": "Powerful and comprehensive tools for practice purpose. Practice tabs can be access through party window.", "description": "Powerful and comprehensive tools for practice purposes. Practice tabs can be accessed through party window.",
"external_url": "https://www.youtube.com/watch?v=7BeCcIYSXd0&t=113s&ab_channel=BOMBsquadlife", "external_url": "https://www.youtube.com/watch?v=7BeCcIYSXd0&t=113s&ab_channel=BOMBsquadlife",
"authors": [ "authors": [
{ {
@ -861,6 +867,12 @@
} }
], ],
"versions": { "versions": {
"2.2.0": {
"api_version": 8,
"commit_sha": "41046ae",
"released_on": "14-02-2024",
"md5sum": "b02de60a80039b092ef4d826b3d61cc1"
},
"2.1.1": { "2.1.1": {
"api_version": 8, "api_version": 8,
"commit_sha": "5422dd6", "commit_sha": "5422dd6",
@ -905,6 +917,25 @@
} }
} }
}, },
"health_indicator": {
"description": "Add a simple health indicator on every player and bot.",
"external_url": "",
"authors": [
{
"name": "Cross Joy",
"email": "cross.joy.official@gmail.com",
"discord": "crossjoy"
}
],
"versions": {
"1.2.0": {
"api_version": 8,
"commit_sha": "41046ae",
"released_on": "14-02-2024",
"md5sum": "e16123cf550f433c70e53b8ec41a4e46"
}
}
},
"autorun": { "autorun": {
"description": "Run without holding any buttons. Made for beginners or players on mobile. Keeps your character maneuverable. Start running as usual to override.", "description": "Run without holding any buttons. Made for beginners or players on mobile. Keeps your character maneuverable. Start running as usual to override.",
"external_url": "", "external_url": "",

View file

@ -1,12 +1,11 @@
# Porting to api 8 made easier by baport.(https://github.com/bombsquad-community/baport) """Disco Light Mod: V2.1
"""Disco Light Mod: V1.0
Made by Cross Joy""" Made by Cross Joy"""
# If anyone who wanna help me on giving suggestion/ fix bugs/ creating PR, # If anyone who wanna help me on giving suggestion/ fix bugs/ creating PR,
# Can visit my github https://github.com/CrossJoy/Bombsquad-Modding # Can visit my github https://github.com/CrossJoy/Bombsquad-Modding
# You can contact me through discord: # You can contact me through discord:
# My Discord Id: crossjoy # My Discord Id: Cross Joy#0721
# My BS Discord Server: https://discord.gg/JyBY6haARJ # My BS Discord Server: https://discord.gg/JyBY6haARJ
@ -19,11 +18,16 @@ Made by Cross Joy"""
# Coop and multiplayer compatible. # Coop and multiplayer compatible.
# Work on any 1.7 ver. # Work on any 1.7.20+ ver.
# Note: # Note:
# The plugin commands only works on the host with the plugin activated. # The plugin commands only works on the host with the plugin activated.
# Other clients/players can't use the commands. # Other clients/players can't use the commands.
# v2.1
# - Enhance compatibility with other mods
# - Tint change when /disco off will be more dynamic.
# ---------------------------------------------------------------------------- # ----------------------------------------------------------------------------
# ba_meta require api 8 # ba_meta require api 8
@ -33,255 +37,196 @@ from __future__ import annotations
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from baenv import TARGET_BALLISTICA_BUILD as build_number import bascenev1 as bs
from bauiv1lib import mainmenu
import babase import babase
import bauiv1 as bui import bauiv1 as bui
import bascenev1 as bs from bascenev1 import _gameutils
import _babase
from bascenev1 import _gameutils, animate
import random import random
from bascenev1 import animate
if TYPE_CHECKING: if TYPE_CHECKING:
from typing import Sequence, Union from typing import Sequence, Union
# Check game ver.
class DiscoLight:
def is_game_version_lower_than(version): def __init__(self):
""" activity = bs.get_foreground_host_activity()
Returns a boolean value indicating whether the current game self.globalnodes = activity.globalsnode.tint
version is lower than the passed version. Useful for addressing
any breaking changes within game versions.
"""
game_version = tuple(map(int, babase.app.version if build_number <
21282 else babase.app.env.split(".")))
version = tuple(map(int, version.split(".")))
return game_version < version
# Activate disco light.
def start(self):
activity = bs.get_foreground_host_activity()
with activity.context:
self.partyLight(True)
self.rainbow(activity)
# if is_game_version_lower_than("1.7.7"): # Deactivate disco light.
# ba_internal = _ba def stop(self):
# else: activity = bs.get_foreground_host_activity()
# ba_internal = babase.internal with activity.context:
self.partyLight(False)
self.stop_rainbow(activity)
# Create and animate colorful spotlight.
def partyLight(self, switch=True):
from bascenev1._nodeactor import NodeActor
x_spread = 10
y_spread = 5
positions = [[-x_spread, -y_spread], [0, -y_spread], [0, y_spread],
[x_spread, -y_spread], [x_spread, y_spread],
[-x_spread, y_spread]]
times = [0, 2700, 1000, 1800, 500, 1400]
# Activate disco light. # Store this on the current activity, so we only have one at a time.
def start(): activity = bs.getactivity()
activity = bs.get_foreground_host_activity() activity.camera_flash_data = [] # type: ignore
for i in range(6):
r = random.choice([0.5, 1])
g = random.choice([0.5, 1])
b = random.choice([0.5, 1])
light = NodeActor(
bs.newnode('light',
attrs={
'position': (
positions[i][0], 0, positions[i][1]),
'radius': 1.0,
'lights_volumes': False,
'height_attenuated': False,
'color': (r, g, b)
}))
sval = 1.87
iscale = 1.3
tcombine = bs.newnode('combine',
owner=light.node,
attrs={
'size': 3,
'input0': positions[i][0],
'input1': 0,
'input2': positions[i][1]
})
assert light.node
tcombine.connectattr('output', light.node, 'position')
xval = positions[i][0]
yval = positions[i][1]
spd = 1.0 + random.random()
spd2 = 1.0 + random.random()
animate(tcombine,
'input0', {
0.0: xval + 0,
0.069 * spd: xval + 10.0,
0.143 * spd: xval - 10.0,
0.201 * spd: xval + 0
},
loop=True)
animate(tcombine,
'input2', {
0.0: yval + 0,
0.15 * spd2: yval + 10.0,
0.287 * spd2: yval - 10.0,
0.398 * spd2: yval + 0
},
loop=True)
animate(light.node,
'intensity', {
0.0: 0,
0.02 * sval: 0,
0.05 * sval: 0.8 * iscale,
0.08 * sval: 0,
0.1 * sval: 0
},
loop=True,
offset=times[i])
if not switch:
bs.timer(0.1,
light.node.delete)
activity.camera_flash_data.append(light) # type: ignore
with activity.context: # Create RGB tint.
partyLight(True) def rainbow(self, activity) -> None:
rainbow(activity) """Create RGB tint."""
cnode = bs.newnode('combine',
attrs={
'input0': self.globalnodes[0],
'input1': self.globalnodes[1],
'input2': self.globalnodes[2],
'size': 3
})
# Deactivate disco light. _gameutils.animate(cnode, 'input0',
def stop(): {0.0: 1.0, 1.0: 1.0, 2.0: 1.0, 3.0: 1.0,
activity = bs.get_foreground_host_activity() 4.0: 0.2, 5.0: 0.1, 6.0: 0.5,
7.0: 1.0}, loop=True)
with activity.context: _gameutils.animate(cnode, 'input1',
partyLight(False) {0.0: 0.2, 1.0: 0.2, 2.0: 0.5, 3.0: 1.0,
stop_rainbow(activity) 4.0: 1.0, 5.0: 0.1, 6.0: 0.3,
7.0: 0.2}, loop=True)
_gameutils.animate(cnode, 'input2',
{0.0: 0.2, 1.0: 0.2, 2.0: 0.0, 3.0: 0.0,
4.0: 0.2, 5.0: 1.0, 6.0: 1.0,
7.0: 0.2}, loop=True)
# Create and animate colorful spotlight. cnode.connectattr('output', activity.globalsnode, 'tint')
def partyLight(switch=True):
from bascenev1._nodeactor import NodeActor
x_spread = 10
y_spread = 5
positions = [[-x_spread, -y_spread], [0, -y_spread], [0, y_spread],
[x_spread, -y_spread], [x_spread, y_spread],
[-x_spread, y_spread]]
times = [0, 2700, 1000, 1800, 500, 1400]
# Store this on the current activity, so we only have one at a time. # Revert to the original map tint.
activity = bs.getactivity() def stop_rainbow(self, activity):
activity.camera_flash_data = [] # type: ignore """Revert to the original map tint."""
for i in range(6): c_existing = activity.globalsnode.tint
r = random.choice([0.5, 1]) # map_name = activity.map.getname()
g = random.choice([0.5, 1]) tint = self.globalnodes
b = random.choice([0.5, 1])
light = NodeActor(
bs.newnode('light',
attrs={
'position': (positions[i][0], 0, positions[i][1]),
'radius': 1.0,
'lights_volumes': False,
'height_attenuated': False,
'color': (r, g, b)
}))
sval = 1.87
iscale = 1.3
tcombine = bs.newnode('combine',
owner=light.node,
attrs={
'size': 3,
'input0': positions[i][0],
'input1': 0,
'input2': positions[i][1]
})
assert light.node
tcombine.connectattr('output', light.node, 'position')
xval = positions[i][0]
yval = positions[i][1]
spd = 1.0 + random.random()
spd2 = 1.0 + random.random()
animate(tcombine,
'input0', {
0.0: xval + 0,
0.069 * spd: xval + 10.0,
0.143 * spd: xval - 10.0,
0.201 * spd: xval + 0
},
loop=True)
animate(tcombine,
'input2', {
0.0: yval + 0,
0.15 * spd2: yval + 10.0,
0.287 * spd2: yval - 10.0,
0.398 * spd2: yval + 0
},
loop=True)
animate(light.node,
'intensity', {
0.0: 0,
0.02 * sval: 0,
0.05 * sval: 0.8 * iscale,
0.08 * sval: 0,
0.1 * sval: 0
},
loop=True,
offset=times[i])
if not switch:
bs.timer(0.1,
light.node.delete)
activity.camera_flash_data.append(light) # type: ignore
cnode = bs.newnode('combine',
attrs={
'input0': c_existing[0],
'input1': c_existing[1],
'input2': c_existing[2],
'size': 3
})
# Create RGB tint. _gameutils.animate(cnode, 'input0', {0: c_existing[0], 1.0: tint[0]})
def rainbow(self) -> None: _gameutils.animate(cnode, 'input1', {0: c_existing[1], 1.0: tint[1]})
"""Create RGB tint.""" _gameutils.animate(cnode, 'input2', {0: c_existing[2], 1.0: tint[2]})
c_existing = self.globalsnode.tint
cnode = bs.newnode('combine',
attrs={
'input0': c_existing[0],
'input1': c_existing[1],
'input2': c_existing[2],
'size': 3
})
_gameutils.animate(cnode, 'input0', cnode.connectattr('output', activity.globalsnode, 'tint')
{0.0: 1.0, 1.0: 1.0, 2.0: 1.0, 3.0: 1.0,
4.0: 0.2, 5.0: 0.1, 6.0: 0.5,
7.0: 1.0}, loop=True)
_gameutils.animate(cnode, 'input1',
{0.0: 0.2, 1.0: 0.2, 2.0: 0.5, 3.0: 1.0,
4.0: 1.0, 5.0: 0.1, 6.0: 0.3,
7.0: 0.2}, loop=True)
_gameutils.animate(cnode, 'input2',
{0.0: 0.2, 1.0: 0.2, 2.0: 0.0, 3.0: 0.0,
4.0: 0.2, 5.0: 1.0, 6.0: 1.0,
7.0: 0.2}, loop=True)
cnode.connectattr('output', self.globalsnode, 'tint')
# Revert to the original map tint.
def stop_rainbow(self):
"""Revert to the original map tint."""
try:
c_existing = self.globalsnode.tint
map_name = self.map.getname()
tint = check_map_tint(map_name)
except:
tint = (1, 1, 1)
cnode = bs.newnode('combine',
attrs={
'input0': c_existing[0],
'input1': c_existing[1],
'input2': c_existing[2],
'size': 3
})
_gameutils.animate(cnode, 'input0', {0: c_existing[0], 1.0: tint[0]})
_gameutils.animate(cnode, 'input1', {0: c_existing[1], 1.0: tint[1]})
_gameutils.animate(cnode, 'input2', {0: c_existing[2], 1.0: tint[2]})
cnode.connectattr('output', self.globalsnode, 'tint')
# Check map name
def check_map_tint(map_name):
if map_name in 'Hockey Stadium':
tint = (1.2, 1.3, 1.33)
elif map_name in 'Football Stadium':
tint = (1.3, 1.2, 1.0)
elif map_name in 'Bridgit':
tint = (1.1, 1.2, 1.3)
elif map_name in 'Big G':
tint = (1.1, 1.2, 1.3)
elif map_name in 'Roundabout':
tint = (1.0, 1.05, 1.1)
elif map_name in 'Monkey Face':
tint = (1.1, 1.2, 1.2)
elif map_name in 'Zigzag':
tint = (1.0, 1.15, 1.15)
elif map_name in 'The Pad':
tint = (1.1, 1.1, 1.0)
elif map_name in 'Lake Frigid':
tint = (0.8, 0.9, 1.3)
elif map_name in 'Crag Castle':
tint = (1.15, 1.05, 0.75)
elif map_name in 'Tower D':
tint = (1.15, 1.11, 1.03)
elif map_name in 'Happy Thoughts':
tint = (1.3, 1.23, 1.0)
elif map_name in 'Step Right Up':
tint = (1.2, 1.1, 1.0)
elif map_name in 'Doom Shroom':
tint = (0.82, 1.10, 1.15)
elif map_name in 'Courtyard':
tint = (1.2, 1.17, 1.1)
elif map_name in 'Rampage':
tint = (1.2, 1.1, 0.97)
elif map_name in 'Tip Top':
tint = (0.8, 0.9, 1.3)
else:
tint = (1, 1, 1)
return tint
# Get the original game codes.
old_fcm = bs.chatmessage
# New chat func to add some commands to activate/deactivate the disco light. # New chat func to add some commands to activate/deactivate the disco light.
def new_chat_message(msg: Union[str, babase.Lstr], clients: Sequence[int] = None, def new_chat_message(func):
sender_override: str = None): def wrapper(*args, **kwargs):
old_fcm(msg, clients, sender_override) func(*args, **kwargs)
if msg == '/disco': activity = bs.get_foreground_host_activity()
start() with activity.context:
if msg == '/disco off': try:
stop() if not activity.disco_light:
activity.disco_light = DiscoLight()
except:
activity.disco_light = DiscoLight()
if args[0] == '/disco':
activity.disco_light.start()
elif args[0] == '/disco off':
activity.disco_light.stop()
return wrapper
class NewMainMenuWindow(mainmenu.MainMenuWindow): def new_begin(func):
def __init__(self, *args, **kwargs): """Runs when game is began."""
super().__init__(*args, **kwargs)
# Display chat icon, but if user open/close gather it may disappear def wrapper(*args, **kwargs):
func(*args, **kwargs)
bui.set_party_icon_always_visible(True) bui.set_party_icon_always_visible(True)
return wrapper
# Replace new chat func to the original game codes.
bs.chatmessage = new_chat_message
# ba_meta export plugin # ba_meta export plugin
class ByCrossJoy(babase.Plugin): class ByCrossJoy(babase.Plugin):
def on_app_running(self): def __init__(self):
mainmenu.MainMenuWindow = NewMainMenuWindow # Replace new chat func to the original game codes.
bs.chatmessage = new_chat_message(bs.chatmessage)
bs._activity.Activity.on_begin = new_begin(
bs._activity.Activity.on_begin)

View file

@ -0,0 +1,79 @@
"""Health Indicator mod v1.2
Made by Cross Joy
For 1.7.20+"""
# ----------------------
# v1.2 update
# Enhance compatibility with other mods.
# Fixed the health is not displaying accurately.
# ----------------------
# You can contact me through discord:
# My Discord Id: Cross Joy#0721
# My BS Discord Server: https://discord.gg/JyBY6haARJ
# Add a simple health indicator on every player and bot.
# ba_meta require api 8
from __future__ import annotations
import babase
import bascenev1lib.actor.spaz
from bascenev1lib.actor.spaz import Spaz
import bascenev1 as bs
import bascenev1lib
def new_init_spaz_(func):
def wrapper(*args, **kwargs):
func(*args, **kwargs)
m = bs.newnode('math',
owner=args[0].node,
attrs={'input1': (0, 0.7, 0),
'operation': 'add'})
args[0].node.connectattr('position', m, 'input2')
args[0]._hitpoint_text = bs.newnode(
'text',
owner=args[0].node,
attrs={'text': "\ue047" + str(args[0].hitpoints),
'in_world': True,
'shadow': 1.0,
'flatness': 1.0,
'color': (1, 1, 1),
'scale': 0.0,
'h_align': 'center'})
m.connectattr('output', args[0]._hitpoint_text, 'position')
bs.animate(args[0]._hitpoint_text, 'scale', {0: 0.0, 1.0: 0.01})
return wrapper
def new_handlemessage_spaz_(func):
def wrapper(*args, **kwargs):
def update_hitpoint_text(spaz):
spaz._hitpoint_text.text = "\ue047" + str(spaz.hitpoints)
r = spaz.hitpoints / 1000
spaz._hitpoint_text.color = (1, r, r, 1)
func(*args, **kwargs)
if isinstance(args[1], bs.PowerupMessage):
if args[1].poweruptype == 'health':
update_hitpoint_text(args[0])
if isinstance(
args[1], bs.HitMessage) or isinstance(
args[1], bs.ImpactDamageMessage):
update_hitpoint_text(args[0])
return wrapper
# ba_meta export plugin
class ByCrossJoy(babase.Plugin):
def __init__(self):
pass
def on_app_running(self) -> None:
Spaz.__init__ = new_init_spaz_(Spaz.__init__)
Spaz.handlemessage = new_handlemessage_spaz_(Spaz.handlemessage)

View file

@ -1,4 +1,4 @@
"""Practice Tools Mod: V2.1 """Practice Tools Mod: V2.2
Made by Cross Joy""" Made by Cross Joy"""
# If anyone who want to help me on giving suggestion/ fix bugs/ creating PR, # If anyone who want to help me on giving suggestion/ fix bugs/ creating PR,
@ -12,25 +12,12 @@ Made by Cross Joy"""
# Support link: https://www.buymeacoffee.com/CrossJoy # Support link: https://www.buymeacoffee.com/CrossJoy
# ---------------------------------------------------------------------------- # ----------------------------------------------------------------------------
# V2.1 update
# - Fix bug where the ui stuck if opened on server side.
# - Fix a bug to set party icon to always visible for newer bombsquad version.
# V2.0 update # V2.2 update
# - Updated to API 8 (1.7.20+) # - Enhance computability with other mods.
# - Added setting for permanent powerups.
# - Codes Optimization.
# V1.2 update
# - Added New Bot: Bomber Lite and Brawler Lite.
# - Added New Setting: Epic Mode Toggle.
# - Added immunity to curse if invincible.
# - Fixed Power Up mini billboard will not removed after debuff.
# - Fixed Power Up landmine count will not removed after debuff.
# - Fixed the config (Bot Picker, Count, Radius and Power Up Picker) will set to default when exit the practice tab.
# V1.1 update
# - Fixed Charger Bot Pro bot spawn with shield.
# - Fixed selecting Bruiser bot is not working.
# - Added screen message when pressing spawn/clear/debuff button.
# ---------------------------------------------------------------------------- # ----------------------------------------------------------------------------
# Powerful and comprehensive tools for practice purpose. # Powerful and comprehensive tools for practice purpose.
@ -72,7 +59,8 @@ import bascenev1lib
import bauiv1 as bui import bauiv1 as bui
from bauiv1lib import mainmenu from bauiv1lib import mainmenu
from babase import app, Plugin from babase import app, Plugin
from bascenev1lib.actor.powerupbox import PowerupBox from bascenev1lib.actor.powerupbox import PowerupBox, PowerupBoxFactory
from bascenev1lib.actor.bomb import Bomb
from bascenev1lib.actor.spaz import Spaz from bascenev1lib.actor.spaz import Spaz
from bascenev1lib.actor import spawner from bascenev1lib.actor import spawner
from bascenev1lib.actor.spazbot import (SpazBotSet, SpazBot, BrawlerBot, from bascenev1lib.actor.spazbot import (SpazBotSet, SpazBot, BrawlerBot,
@ -94,47 +82,35 @@ from bauiv1lib.tabs import TabRow
if TYPE_CHECKING: if TYPE_CHECKING:
from typing import Any, Sequence, Callable, Optional from typing import Any, Sequence, Callable, Optional
version = '2.1' version = '2.2'
try:
if babase.app.config.get("bombCountdown") is None:
babase.app.config["bombCountdown"] = False
else:
babase.app.config.get("bombCountdown")
except:
babase.app.config["bombCountdown"] = False
try: class ConfigLoader:
if babase.app.config.get("bombRadiusVisual") is None: def __init__(self):
babase.app.config["bombRadiusVisual"] = False self.config_data = {
else: "Practice Tab": False,
babase.app.config.get("bombRadiusVisual") "bombCountdown": False,
except: "bombRadiusVisual": False,
babase.app.config["bombRadiusVisual"] = False "stopBots": False,
"immortalDummy": False,
"powerupsExpire": False,
"invincible": False
}
self.config_names = ["Practice Tab", "bombCountdown",
"bombRadiusVisual", "stopBots",
"immortalDummy", "powerupsExpire", "invincible"]
try: def load_configs(self):
if babase.app.config.get("stopBots") is None: for config_name in self.config_names:
babase.app.config["stopBots"] = False try:
else: existing_config = babase.app.config.get(config_name)
babase.app.config.get("stopBots") if existing_config is None:
except: babase.app.config[config_name] = self.config_data[
babase.app.config["stopBots"] = False config_name]
else:
try: babase.app.config.get(config_name)
if babase.app.config.get("immortalDummy") is None: except:
babase.app.config["immortalDummy"] = False babase.app.config[config_name] = self.config_data[config_name]
else:
babase.app.config.get("immortalDummy")
except:
babase.app.config["immortalDummy"] = False
try:
if babase.app.config.get("invincible") is None:
babase.app.config["invincible"] = False
else:
babase.app.config.get("invincible")
except:
babase.app.config["invincible"] = False
class PartyWindow(bui.Window): class PartyWindow(bui.Window):
@ -174,7 +150,7 @@ def redefine_class(original_cls: object, cls: object) -> None:
def main(plugin: Plugin) -> None: def main(plugin: Plugin) -> None:
print(f'Plugins Tools v{plugin.__version__}') print(f'Practice Tools v{plugin.__version__}')
app.practice_tool = plugin app.practice_tool = plugin
redefine_class(OriginalPartyWindow, PartyWindow) redefine_class(OriginalPartyWindow, PartyWindow)
@ -185,10 +161,9 @@ class NewMainMenuWindow(mainmenu.MainMenuWindow):
# Display chat icon, but if user open/close gather it may disappear # Display chat icon, but if user open/close gather it may disappear
bui.set_party_icon_always_visible(True) bui.set_party_icon_always_visible(True)
# ba_meta require api 8 # ba_meta require api 8
# ba_meta export plugin # ba_meta export plugin
class Practice(Plugin): class Practice(Plugin):
__version__ = version __version__ = version
@ -202,334 +177,373 @@ class Practice(Plugin):
raise RuntimeError( raise RuntimeError(
'sad') 'sad')
mainmenu.MainMenuWindow = NewMainMenuWindow mainmenu.MainMenuWindow = NewMainMenuWindow
config_loader = ConfigLoader()
config_loader.load_configs()
return main(self) return main(self)
def new_bomb_init(func):
def setting(*args, **kwargs):
func(*args, **kwargs)
bomb_type = args[0].bomb_type def new_bomb_init(func):
fuse_bomb = ('land_mine', 'tnt', 'impact') def setting(*args, **kwargs):
func(*args, **kwargs)
if babase.app.config.get("bombRadiusVisual"): bomb_type = args[0].bomb_type
args[0].radius_visualizer = bs.newnode('locator', fuse_bomb = ('land_mine', 'tnt', 'impact')
owner=args[0].node,
# Remove itself when the bomb node dies.
attrs={
'shape': 'circle',
'color': (1, 0, 0),
'opacity': 0.05,
'draw_beauty': False,
'additive': False
})
args[0].node.connectattr('position', args[0].radius_visualizer,
'position')
bs.animate_array(args[0].radius_visualizer, 'size', 1, { if babase.app.config.get("bombRadiusVisual"):
0.0: [0.0], args[0].radius_visualizer = bs.newnode('locator',
0.2: [args[0].blast_radius * 2.2], owner=args[0].node,
0.25: [args[0].blast_radius * 2.0] # Remove itself when the bomb node dies.
}) attrs={
'shape': 'circle',
'color': (1, 0, 0),
'opacity': 0.05,
'draw_beauty': False,
'additive': False
})
args[0].node.connectattr('position', args[0].radius_visualizer,
'position')
args[0].radius_visualizer_circle = bs.newnode( bs.animate_array(args[0].radius_visualizer, 'size', 1, {
'locator', 0.0: [0.0],
owner=args[ 0.2: [args[0].blast_radius * 2.2],
0].node, 0.25: [args[0].blast_radius * 2.0]
# Remove itself when the bomb node dies.
attrs={
'shape': 'circleOutline',
'size': [
args[
0].blast_radius * 2.0],
# Here's that bomb's blast radius value again!
'color': (
1, 1, 0),
'draw_beauty': False,
'additive': True
})
args[0].node.connectattr('position',
args[0].radius_visualizer_circle,
'position')
bs.animate(
args[0].radius_visualizer_circle, 'opacity', {
0: 0.0,
0.4: 0.1
})
if bomb_type == 'tnt':
args[0].fatal = bs.newnode('locator',
owner=args[0].node,
# Remove itself when the bomb node dies.
attrs={
'shape': 'circle',
'color': (
0.7, 0, 0),
'opacity': 0.10,
'draw_beauty': False,
'additive': False
})
args[0].node.connectattr('position',
args[0].fatal,
'position')
bs.animate_array(args[0].fatal, 'size', 1, {
0.0: [0.0],
0.2: [args[0].blast_radius * 2.2 * 0.7],
0.25: [args[0].blast_radius * 2.0 * 0.7]
})
if babase.app.config.get(
"bombCountdown") and bomb_type not in fuse_bomb:
color = (1.0, 1.0, 0.0)
count_bomb(*args, count='3', color=color)
color = (1.0, 0.5, 0.0)
bs.timer(1, bs.Call(count_bomb, *args, count='2', color=color))
color = (1.0, 0.15, 0.15)
bs.timer(2, bs.Call(count_bomb, *args, count='1', color=color))
return setting
bascenev1lib.actor.bomb.Bomb.__init__ = new_bomb_init(
bascenev1lib.actor.bomb.Bomb.__init__)
Spaz._pm2_spz_old = Spaz.__init__
def _init_spaz_(self, *args, **kwargs):
self._pm2_spz_old(*args, **kwargs)
self.bot_radius = bs.newnode('locator',
owner=self.node,
# Remove itself when the bomb node dies.
attrs={
'shape': 'circle',
'color': (0, 0, 1),
'opacity': 0.0,
'draw_beauty': False,
'additive': False
})
self.node.connectattr('position',
self.bot_radius,
'position')
self.radius_visualizer_circle = bs.newnode(
'locator',
owner=self.node,
# Remove itself when the bomb node dies.
attrs={
'shape': 'circleOutline',
'size': [(self.hitpoints_max - self.hitpoints) * 0.0048],
# Here's that bomb's blast radius value again!
'color': (0, 1, 1),
'draw_beauty': False,
'additive': True
})
self.node.connectattr('position', self.radius_visualizer_circle,
'position')
self.curse_visualizer = bs.newnode('locator',
owner=self.node,
# Remove itself when the bomb node dies.
attrs={
'shape': 'circle',
'color': (1, 0, 0),
'size': (0.0, 0.0, 0.0),
'opacity': 0.05,
'draw_beauty': False,
'additive': False
})
self.node.connectattr('position', self.curse_visualizer,
'position')
self.curse_visualizer_circle = bs.newnode(
'locator',
owner=self.node,
# Remove itself when the bomb node dies.
attrs={
'shape': 'circleOutline',
'size': [3 * 2.0],
# Here's that bomb's blast radius value again!
'color': (
1, 1, 0),
'opacity': 0.0,
'draw_beauty': False,
'additive': True
})
self.node.connectattr('position',
self.curse_visualizer_circle,
'position')
self.curse_visualizer_fatal = bs.newnode('locator',
owner=self.node,
# Remove itself when the bomb node dies.
attrs={
'shape': 'circle',
'color': (
0.7, 0, 0),
'size': (0.0, 0.0, 0.0),
'opacity': 0.10,
'draw_beauty': False,
'additive': False
})
self.node.connectattr('position',
self.curse_visualizer_fatal,
'position')
def invincible() -> None:
for i in bs.get_foreground_host_activity().players:
try:
if i.node:
if babase.app.config.get("invincible"):
i.actor.node.invincible = True
else:
i.actor.node.invincible = False
except:
pass
bs.timer(1.001, bs.Call(invincible))
Spaz.__init__ = _init_spaz_
Spaz.super_curse = Spaz.curse
def new_cursed(self):
if self.node.invincible:
return
self.super_curse()
if babase.app.config.get("bombRadiusVisual"):
bs.animate_array(self.curse_visualizer, 'size', 1, {
0.0: [0.0],
0.2: [3 * 2.2],
0.5: [3 * 2.0],
5.0: [3 * 2.0],
5.1: [0.0],
})
bs.animate(
self.curse_visualizer_circle, 'opacity', {
0: 0.0,
0.4: 0.1,
5.0: 0.1,
5.1: 0.0,
}) })
bs.animate_array(self.curse_visualizer_fatal, 'size', 1, { args[0].radius_visualizer_circle = bs.newnode(
0.0: [0.0], 'locator',
0.2: [2.2], owner=args[
0.5: [2.0], 0].node,
5.0: [2.0], # Remove itself when the bomb node dies.
5.1: [0.0], attrs={
}) 'shape': 'circleOutline',
'size': [
args[
0].blast_radius * 2.0],
# Here's that bomb's blast radius value again!
'color': (
1, 1, 0),
'draw_beauty': False,
'additive': True
})
args[0].node.connectattr('position',
args[0].radius_visualizer_circle,
'position')
bs.animate(
args[0].radius_visualizer_circle, 'opacity', {
0: 0.0,
0.4: 0.1
})
if bomb_type == 'tnt':
args[0].fatal = bs.newnode('locator',
owner=args[0].node,
# Remove itself when the bomb node dies.
attrs={
'shape': 'circle',
'color': (
0.7, 0, 0),
'opacity': 0.10,
'draw_beauty': False,
'additive': False
})
args[0].node.connectattr('position',
args[0].fatal,
'position')
bs.animate_array(args[0].fatal, 'size', 1, {
0.0: [0.0],
0.2: [args[0].blast_radius * 2.2 * 0.7],
0.25: [args[0].blast_radius * 2.0 * 0.7]
})
if babase.app.config.get(
"bombCountdown") and bomb_type not in fuse_bomb:
color = (1.0, 1.0, 0.0)
count_bomb(*args, count='3', color=color)
color = (1.0, 0.5, 0.0)
bs.timer(1, bs.Call(count_bomb, *args, count='2', color=color))
color = (1.0, 0.15, 0.15)
bs.timer(2, bs.Call(count_bomb, *args, count='1', color=color))
return setting
Spaz.curse = new_cursed bascenev1lib.actor.bomb.Bomb.__init__ = new_bomb_init(
bascenev1lib.actor.bomb.Bomb.__init__)
Spaz.super_handlemessage = Spaz.handlemessage
def bot_handlemessage(self, msg: Any): def _init_spaz_(func):
if isinstance(msg, bs.PowerupMessage): def wrapper(*args, **kwargs):
if msg.poweruptype == 'health': func(*args, **kwargs)
if babase.app.config.get("bombRadiusVisual"): args[0].bot_radius = bs.newnode('locator',
if self._cursed: owner=args[0].node,
bs.animate_array(self.curse_visualizer, 'size', 1, { attrs={
0.0: [3 * 2.0], 'shape': 'circle',
0.2: [0.0], 'color': (0, 0, 1),
}) 'opacity': 0.0,
'draw_beauty': False,
'additive': False
})
args[0].node.connectattr('position',
args[0].bot_radius,
'position')
bs.animate( args[0].radius_visualizer_circle = bs.newnode(
self.curse_visualizer_circle, 'opacity', { 'locator',
0.0: 0.1, owner=args[0].node,
0.2: 0.0, attrs={
'shape': 'circleOutline',
'size': [(args[0].hitpoints_max - args[0].hitpoints) * 0.0048],
'color': (0, 1, 1),
'draw_beauty': False,
'additive': True
})
args[0].node.connectattr('position', args[0].radius_visualizer_circle,
'position')
args[0].curse_visualizer = bs.newnode('locator',
owner=args[0].node,
attrs={
'shape': 'circle',
'color': (1, 0, 0),
'size': (0.0, 0.0, 0.0),
'opacity': 0.05,
'draw_beauty': False,
'additive': False
})
args[0].node.connectattr('position', args[0].curse_visualizer,
'position')
args[0].curse_visualizer_circle = bs.newnode(
'locator',
owner=args[0].node,
attrs={
'shape': 'circleOutline',
'size': [3 * 2.0],
'color': (
1, 1, 0),
'opacity': 0.0,
'draw_beauty': False,
'additive': True
})
args[0].node.connectattr('position',
args[0].curse_visualizer_circle,
'position')
args[0].curse_visualizer_fatal = bs.newnode('locator',
owner=args[0].node,
attrs={
'shape': 'circle',
'color': (
0.7, 0, 0),
'size': (0.0, 0.0, 0.0),
'opacity': 0.10,
'draw_beauty': False,
'additive': False
})
args[0].node.connectattr('position',
args[0].curse_visualizer_fatal,
'position')
def invincible() -> None:
for i in bs.get_foreground_host_activity().players:
try:
if i.node:
if babase.app.config.get("invincible"):
i.actor.node.invincible = True
else:
i.actor.node.invincible = False
except:
pass
bs.timer(1.001, bs.Call(invincible))
return wrapper
Spaz.__init__ = _init_spaz_(Spaz.__init__)
def new_cursed(func):
def wrapper(*args, **kwargs):
if args[0].node.invincible:
return
func(*args, **kwargs)
if babase.app.config.get("bombRadiusVisual"):
bs.animate_array(args[0].curse_visualizer, 'size', 1, {
0.0: [0.0],
0.2: [3 * 2.2],
0.5: [3 * 2.0],
5.0: [3 * 2.0],
5.1: [0.0],
})
bs.animate(
args[0].curse_visualizer_circle, 'opacity', {
0: 0.0,
0.4: 0.1,
5.0: 0.1,
5.1: 0.0,
})
bs.animate_array(args[0].curse_visualizer_fatal, 'size', 1, {
0.0: [0.0],
0.2: [2.2],
0.5: [2.0],
5.0: [2.0],
5.1: [0.0],
})
return wrapper
Spaz.curse = new_cursed(Spaz.curse)
def bot_handlemessage(func):
def wrapper(*args, **kwargs):
if isinstance(args[1], bs.PowerupMessage):
if args[1].poweruptype == 'health':
if babase.app.config.get("bombRadiusVisual"):
if args[0]._cursed:
bs.animate_array(args[0].curse_visualizer, 'size', 1, {
0.0: [3 * 2.0],
0.2: [0.0],
}) })
bs.animate_array(self.curse_visualizer_fatal, 'size', 1, { bs.animate(
0.0: [2.0], args[0].curse_visualizer_circle, 'opacity', {
0.2: [0.0], 0.0: 0.1,
0.2: 0.0,
})
bs.animate_array(args[0].curse_visualizer_fatal, 'size',
1,
{
0.0: [2.0],
0.2: [0.0],
})
bs.animate_array(args[0].bot_radius, 'size', 1, {
0.0: [0],
0.25: [0]
}) })
bs.animate(args[0].bot_radius, 'opacity', {
bs.animate_array(self.bot_radius, 'size', 1, {
0.0: [0],
0.25: [0]
})
bs.animate(self.bot_radius, 'opacity', {
0.0: 0.00,
0.25: 0.0
})
bs.animate_array(self.radius_visualizer_circle, 'size', 1, {
0.0: [0],
0.25: [0]
})
bs.animate(
self.radius_visualizer_circle, 'opacity', {
0.0: 0.00, 0.0: 0.00,
0.25: 0.0 0.25: 0.0
}) })
self.super_handlemessage(msg) bs.animate_array(args[0].radius_visualizer_circle, 'size',
1, {
0.0: [0],
0.25: [0]
})
if isinstance(msg, bs.HitMessage): bs.animate(
if self.hitpoints <= 0: args[0].radius_visualizer_circle, 'opacity', {
bs.animate(self.bot_radius, 'opacity', { 0.0: 0.00,
0.0: 0.00 0.25: 0.0
}) })
bs.animate( if not (babase.app.config.get("powerupsExpire") and
self.radius_visualizer_circle, 'opacity', { args[0].powerups_expire):
if args[1].poweruptype == 'triple_bombs':
tex = PowerupBoxFactory.get().tex_bomb
args[0]._flash_billboard(tex)
args[0].set_bomb_count(3)
elif args[1].poweruptype == 'impact_bombs':
args[0].bomb_type = 'impact'
tex = args[0]._get_bomb_type_tex()
args[0]._flash_billboard(tex)
elif args[1].poweruptype == 'sticky_bombs':
args[0].bomb_type = 'sticky'
tex = args[0]._get_bomb_type_tex()
args[0]._flash_billboard(tex)
elif args[1].poweruptype == 'punch':
tex = PowerupBoxFactory.get().tex_punch
args[0]._flash_billboard(tex)
args[0].equip_boxing_gloves()
elif args[1].poweruptype == 'ice_bombs':
args[0].bomb_type = 'ice'
tex = args[0]._get_bomb_type_tex()
args[0]._flash_billboard(tex)
if args[1].poweruptype in ['triple_bombs', 'impact_bombs',
'sticky_bombs', 'punch',
'ice_bombs']:
args[0].node.handlemessage('flash')
if args[1].sourcenode:
args[1].sourcenode.handlemessage(
bs.PowerupAcceptMessage())
return True
func(*args, **kwargs)
if isinstance(args[1], bs.HitMessage):
if args[0].hitpoints <= 0:
bs.animate(args[0].bot_radius, 'opacity', {
0.0: 0.00 0.0: 0.00
}) })
elif babase.app.config.get('bombRadiusVisual'): bs.animate(
args[0].radius_visualizer_circle, 'opacity', {
0.0: 0.00
})
elif babase.app.config.get('bombRadiusVisual'):
bs.animate_array(self.bot_radius, 'size', 1, { bs.animate_array(args[0].bot_radius, 'size', 1, {
0.0: [(self.hitpoints_max - self.hitpoints) * 0.0045], 0.0: [(args[0].hitpoints_max - args[0].hitpoints) * 0.0045],
0.25: [(self.hitpoints_max - self.hitpoints) * 0.0045] 0.25: [(args[0].hitpoints_max - args[0].hitpoints) * 0.0045]
}) })
bs.animate(self.bot_radius, 'opacity', { bs.animate(args[0].bot_radius, 'opacity', {
0.0: 0.00,
0.25: 0.05
})
bs.animate_array(self.radius_visualizer_circle, 'size', 1, {
0.0: [(self.hitpoints_max - self.hitpoints) * 0.0045],
0.25: [(self.hitpoints_max - self.hitpoints) * 0.0045]
})
bs.animate(
self.radius_visualizer_circle, 'opacity', {
0.0: 0.00, 0.0: 0.00,
0.25: 0.1 0.25: 0.05
}) })
bs.animate_array(args[0].radius_visualizer_circle, 'size', 1, {
0.0: [(args[0].hitpoints_max - args[0].hitpoints) * 0.0045],
0.25: [(args[0].hitpoints_max - args[0].hitpoints) * 0.0045]
})
Spaz.handlemessage = bot_handlemessage bs.animate(
args[0].radius_visualizer_circle, 'opacity', {
0.0: 0.00,
0.25: 0.1
})
return wrapper
Spaz.handlemessage = bot_handlemessage(Spaz.handlemessage)
def count_bomb(*args, count, color): def count_bomb(*args, count, color):
text = bs.newnode('math', owner=args[0].node, if args[0].node.exists():
attrs={'input1': (0, 0.7, 0), text = bs.newnode('math', owner=args[0].node,
'operation': 'add'}) attrs={'input1': (0, 0.7, 0),
args[0].node.connectattr('position', text, 'input2') 'operation': 'add'})
args[0].spaztext = bs.newnode('text', args[0].node.connectattr('position', text, 'input2')
owner=args[0].node, args[0].spaztext = bs.newnode('text',
attrs={ owner=args[0].node,
'text': count, attrs={
'in_world': True, 'text': count,
'color': color, 'in_world': True,
'shadow': 1.0, 'color': color,
'flatness': 1.0, 'shadow': 1.0,
'scale': 0.012, 'flatness': 1.0,
'h_align': 'center', 'scale': 0.012,
}) 'h_align': 'center',
})
args[0].node.connectattr('position', args[0].spaztext, args[0].node.connectattr('position', args[0].spaztext,
'position') 'position')
bs.animate(args[0].spaztext, 'scale', bs.animate(args[0].spaztext, 'scale',
{0: 0, 0.3: 0.03, 0.5: 0.025, 0.8: 0.025, 1.0: 0.0}) {0: 0, 0.3: 0.03, 0.5: 0.025, 0.8: 0.025, 1.0: 0.0})
def doTestButton(self): def doTestButton(self):
@ -1211,8 +1225,9 @@ class PowerUpPracticeTab(PracticeTab):
'shield', 'sticky_bombs']) 'shield', 'sticky_bombs'])
self._icon_index = self.load_settings() self._icon_index = self.load_settings()
self.setting_name = (['Bomb Countdown', 'Bomb Radius Visualizer']) self.setting_name = (
self.config = (['bombCountdown', 'bombRadiusVisual']) ['Bomb Countdown', 'Bomb Radius Visualizer', 'Powerups Expire'])
self.config = (['bombCountdown', 'bombRadiusVisual', 'powerupsExpire'])
def on_activate( def on_activate(
self, self,
@ -1238,7 +1253,7 @@ class PowerUpPracticeTab(PracticeTab):
self._sub_width = self._scroll_width self._sub_width = self._scroll_width
self._sub_height = 200 self._sub_height = 200
self.container_h = 450 self.container_h = 550
power_height = self.container_h - 50 power_height = self.container_h - 50
self._subcontainer = bui.containerwidget( self._subcontainer = bui.containerwidget(
@ -1426,6 +1441,11 @@ class PowerUpPracticeTab(PracticeTab):
babase.app.config["bombRadiusVisual"] = True babase.app.config["bombRadiusVisual"] = True
else: else:
babase.app.config["bombRadiusVisual"] = False babase.app.config["bombRadiusVisual"] = False
elif setting == 2:
if value:
babase.app.config["powerupsExpire"] = True
else:
babase.app.config["powerupsExpire"] = False
def load_settings(self): def load_settings(self):
try: try:
@ -2204,9 +2224,9 @@ class InfoWindow(popup.PopupWindow):
text = ('Practice Tools Mod\n' text = ('Practice Tools Mod\n'
'Made By Cross Joy\n' 'Made By Cross Joy\n'
'version v' + version + '\n' 'version v' + version + '\n'
'\n' '\n'
'Thx to\n' 'Thx to\n'
'Mikirog for the Bomb radius visualizer mod.\n' 'Mikirog for the Bomb radius visualizer mod.\n'
) )
lines = text.splitlines() lines = text.splitlines()