diff --git a/plugins/utilities/disco_light.py b/plugins/utilities/disco_light.py new file mode 100644 index 0000000..c9e7fb3 --- /dev/null +++ b/plugins/utilities/disco_light.py @@ -0,0 +1,271 @@ +"""Disco Light Mod: V1.0 +Made by Cross Joy""" + +# If anyone who wanna help me on giving suggestion/ fix bugs/ creating PR, +# Can visit my github https://github.com/CrossJoy/Bombsquad-Modding + +# You can contact me through discord: +# My Discord Id: Cross Joy#0721 +# My BS Discord Server: https://discord.gg/JyBY6haARJ + + +# ---------------------------------------------------------------------------- +# Add disco light into the game, so you can +# play with your friends under the colorful light. :) + +# type '/disco' in your chat box to activate or +# type '/disco off' to deactivate the disco light. + + +# Coop and multiplayer compatible. +# Work on any 1.7 ver. + +# Note: +# The plugin commands only works on the host with the plugin activated. +# Other clients/players can't use the commands. +# ---------------------------------------------------------------------------- + +# ba_meta require api 7 + + +from __future__ import annotations + +from typing import TYPE_CHECKING + +import ba +import _ba +from ba import _gameutils +import random + +from ba import animate + +if TYPE_CHECKING: + from typing import Sequence, Union + +# Check game ver. +def is_game_version_lower_than(version): + """ + Returns a boolean value indicating whether the current game + version is lower than the passed version. Useful for addressing + any breaking changes within game versions. + """ + game_version = tuple(map(int, ba.app.version.split("."))) + version = tuple(map(int, version.split("."))) + return game_version < version + + +if is_game_version_lower_than("1.7.7"): + ba_internal = _ba +else: + ba_internal = ba.internal + + +# Activate disco light. +def start(): + activity = _ba.get_foreground_host_activity() + + with ba.Context(activity): + partyLight(True) + rainbow(activity) + + +# Deactivate disco light. +def stop(): + activity = _ba.get_foreground_host_activity() + + with ba.Context(activity): + partyLight(False) + stop_rainbow(activity) + + +# Create and animate colorful spotlight. +def partyLight(switch=True): + from ba._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. + activity = _ba.getactivity() + 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( + _ba.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 = _ba.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: + _ba.timer(0.1, + light.node.delete) + activity.camera_flash_data.append(light) # type: ignore + + +# Create RGB tint. +def rainbow(self) -> None: + """Create RGB tint.""" + c_existing = self.globalsnode.tint + cnode = _ba.newnode('combine', + attrs={ + 'input0': c_existing[0], + 'input1': c_existing[1], + 'input2': c_existing[2], + 'size': 3 + }) + + _gameutils.animate(cnode, 'input0', + {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.""" + c_existing = self.globalsnode.tint + map_name = self.map.getname() + tint = check_map_tint(map_name) + + cnode = _ba.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 = ba_internal.chatmessage + + +# New chat func to add some commands to activate/deactivate the disco light. +def new_chat_message(msg: Union[str, ba.Lstr], clients: Sequence[int] = None, + sender_override: str = None): + old_fcm(msg, clients, sender_override) + if msg == '/disco': + start() + if msg == '/disco off': + stop() + + +# Replace new chat func to the original game codes. +ba_internal.chatmessage = new_chat_message +if not ba_internal.is_party_icon_visible(): + ba_internal.set_party_icon_always_visible(True) + + +# ba_meta export plugin +class ByCrossJoy(ba.Plugin): + def __init__(self): pass