2022-11-13 19:41:14 +01:00
|
|
|
"""
|
|
|
|
|
Quickturn by TheMikirog
|
|
|
|
|
|
|
|
|
|
Super Smash Bros Melee's wavedash mechanic ported and tuned for BombSquad.
|
|
|
|
|
|
|
|
|
|
Sharp turns while running (releasing run button, changing direction, holding run again) are much faster with this mod, allowing for more dynamic, aggressive play.
|
|
|
|
|
Version 3
|
|
|
|
|
|
2022-11-13 20:45:11 +01:00
|
|
|
No Rights Reserved
|
2022-11-13 19:41:14 +01:00
|
|
|
"""
|
|
|
|
|
|
2025-01-21 22:31:30 +05:30
|
|
|
# ba_meta require api 9
|
2022-11-13 19:41:14 +01:00
|
|
|
|
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
|
|
from typing import TYPE_CHECKING
|
|
|
|
|
|
2024-01-16 15:06:45 +03:00
|
|
|
import babase
|
|
|
|
|
import bascenev1 as bs
|
2022-11-13 19:41:14 +01:00
|
|
|
import math
|
2024-01-16 15:06:45 +03:00
|
|
|
import bascenev1lib
|
2022-11-13 19:41:14 +01:00
|
|
|
|
|
|
|
|
if TYPE_CHECKING:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
# ba_meta export plugin
|
2022-11-13 20:06:02 +00:00
|
|
|
|
|
|
|
|
|
2024-01-16 15:06:45 +03:00
|
|
|
class Quickturn(babase.Plugin):
|
2022-11-13 19:41:14 +01:00
|
|
|
|
|
|
|
|
class FootConnectMessage:
|
|
|
|
|
"""Spaz started touching the ground"""
|
2022-11-13 20:06:02 +00:00
|
|
|
|
2022-11-13 19:41:14 +01:00
|
|
|
class FootDisconnectMessage:
|
|
|
|
|
"""Spaz stopped touching the ground"""
|
2022-11-13 20:06:02 +00:00
|
|
|
|
2022-11-13 19:41:14 +01:00
|
|
|
def wavedash(self) -> None:
|
|
|
|
|
if not self.node:
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
isMoving = abs(self.node.move_up_down) >= 0.5 or abs(self.node.move_left_right) >= 0.5
|
2022-11-13 20:06:02 +00:00
|
|
|
|
2022-11-13 19:41:14 +01:00
|
|
|
if self._dead or not self.grounded or not isMoving:
|
|
|
|
|
return
|
2022-11-13 20:06:02 +00:00
|
|
|
|
2022-11-13 19:41:14 +01:00
|
|
|
if self.node.knockout > 0.0 or self.frozen or self.node.hold_node:
|
|
|
|
|
return
|
2022-11-13 20:06:02 +00:00
|
|
|
|
2024-01-16 15:06:45 +03:00
|
|
|
t_ms = bs.time() * 1000
|
2022-11-13 19:41:14 +01:00
|
|
|
assert isinstance(t_ms, int)
|
2022-11-13 20:06:02 +00:00
|
|
|
|
2022-11-13 19:41:14 +01:00
|
|
|
if t_ms - self.last_wavedash_time_ms >= self._wavedash_cooldown:
|
2022-11-13 20:06:02 +00:00
|
|
|
|
2022-11-13 19:41:14 +01:00
|
|
|
move = [self.node.move_left_right, -self.node.move_up_down]
|
|
|
|
|
vel = [self.node.velocity[0], self.node.velocity[2]]
|
2022-11-13 20:06:02 +00:00
|
|
|
|
2022-11-13 19:41:14 +01:00
|
|
|
move_length = math.hypot(move[0], move[1])
|
|
|
|
|
vel_length = math.hypot(vel[0], vel[1])
|
2022-11-13 20:06:02 +00:00
|
|
|
if vel_length < 0.6:
|
|
|
|
|
return
|
2022-11-13 19:41:14 +01:00
|
|
|
move_norm = [m/move_length for m in move]
|
|
|
|
|
vel_norm = [v/vel_length for v in vel]
|
2022-11-13 20:06:02 +00:00
|
|
|
dot = sum(x*y for x, y in zip(move_norm, vel_norm))
|
|
|
|
|
turn_power = min(round(math.acos(dot) / math.pi, 2)*1.3, 1)
|
|
|
|
|
|
2022-11-13 19:41:14 +01:00
|
|
|
# https://easings.net/#easeInOutQuart
|
|
|
|
|
if turn_power < 0.55:
|
|
|
|
|
turn_power = 8 * turn_power * turn_power * turn_power * turn_power
|
|
|
|
|
else:
|
|
|
|
|
turn_power = 0.55 - pow(-2 * turn_power + 2, 4) / 2
|
2022-11-13 20:06:02 +00:00
|
|
|
if turn_power < 0.1:
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
boost_power = math.sqrt(math.pow(vel[0], 2) + math.pow(vel[1], 2)) * 8
|
|
|
|
|
boost_power = min(pow(boost_power, 8), 160)
|
|
|
|
|
|
2022-11-13 19:41:14 +01:00
|
|
|
self.last_wavedash_time_ms = t_ms
|
2022-11-13 20:06:02 +00:00
|
|
|
|
2022-11-13 19:41:14 +01:00
|
|
|
# FX
|
2024-01-16 15:06:45 +03:00
|
|
|
bs.emitfx(position=self.node.position,
|
2022-11-13 20:06:02 +00:00
|
|
|
velocity=(vel[0]*0.5, -1, vel[1]*0.5),
|
2022-11-13 19:41:14 +01:00
|
|
|
chunk_type='spark',
|
|
|
|
|
count=5,
|
|
|
|
|
scale=boost_power / 160 * turn_power,
|
2022-11-13 20:06:02 +00:00
|
|
|
spread=0.25)
|
|
|
|
|
|
2022-11-13 19:41:14 +01:00
|
|
|
# Boost itself
|
|
|
|
|
pos = self.node.position
|
|
|
|
|
for i in range(6):
|
2022-11-13 20:06:02 +00:00
|
|
|
self.node.handlemessage('impulse', pos[0], 0.2+pos[1]+i*0.1, pos[2],
|
|
|
|
|
0, 0, 0,
|
|
|
|
|
boost_power * turn_power,
|
|
|
|
|
boost_power * turn_power, 0, 0,
|
|
|
|
|
move[0], 0, move[1])
|
|
|
|
|
|
2022-11-13 19:41:14 +01:00
|
|
|
def new_spaz_init(func):
|
|
|
|
|
def wrapper(*args, **kwargs):
|
|
|
|
|
|
|
|
|
|
func(*args, **kwargs)
|
2022-11-13 20:06:02 +00:00
|
|
|
|
2022-11-13 19:41:14 +01:00
|
|
|
# args[0] = self
|
|
|
|
|
args[0]._wavedash_cooldown = 170
|
|
|
|
|
args[0].last_wavedash_time_ms = -9999
|
|
|
|
|
args[0].grounded = 0
|
2022-11-13 20:06:02 +00:00
|
|
|
|
2022-11-13 19:41:14 +01:00
|
|
|
return wrapper
|
2024-01-16 15:06:45 +03:00
|
|
|
bascenev1lib.actor.spaz.Spaz.__init__ = new_spaz_init(bascenev1lib.actor.spaz.Spaz.__init__)
|
2022-11-13 20:06:02 +00:00
|
|
|
|
2022-11-13 19:41:14 +01:00
|
|
|
def new_factory(func):
|
|
|
|
|
def wrapper(*args, **kwargs):
|
|
|
|
|
func(*args, **kwargs)
|
|
|
|
|
|
|
|
|
|
args[0].roller_material.add_actions(
|
2022-11-13 20:06:02 +00:00
|
|
|
conditions=('they_have_material',
|
2024-01-16 15:06:45 +03:00
|
|
|
bascenev1lib.gameutils.SharedObjects.get().footing_material),
|
2022-11-13 20:06:02 +00:00
|
|
|
actions=(('message', 'our_node', 'at_connect', Quickturn.FootConnectMessage),
|
|
|
|
|
('message', 'our_node', 'at_disconnect', Quickturn.FootDisconnectMessage)))
|
2022-11-13 19:41:14 +01:00
|
|
|
return wrapper
|
2024-01-16 15:06:45 +03:00
|
|
|
bascenev1lib.actor.spazfactory.SpazFactory.__init__ = new_factory(
|
|
|
|
|
bascenev1lib.actor.spazfactory.SpazFactory.__init__)
|
2022-11-13 20:06:02 +00:00
|
|
|
|
2022-11-13 19:41:14 +01:00
|
|
|
def new_handlemessage(func):
|
|
|
|
|
def wrapper(*args, **kwargs):
|
|
|
|
|
if args[1] == Quickturn.FootConnectMessage:
|
|
|
|
|
args[0].grounded += 1
|
|
|
|
|
elif args[1] == Quickturn.FootDisconnectMessage:
|
2022-11-13 20:06:02 +00:00
|
|
|
if args[0].grounded > 0:
|
|
|
|
|
args[0].grounded -= 1
|
|
|
|
|
|
2022-11-13 19:41:14 +01:00
|
|
|
func(*args, **kwargs)
|
|
|
|
|
return wrapper
|
2024-01-18 13:41:11 +00:00
|
|
|
bascenev1lib.actor.spaz.Spaz.handlemessage = new_handlemessage(
|
|
|
|
|
bascenev1lib.actor.spaz.Spaz.handlemessage)
|
2022-11-13 20:06:02 +00:00
|
|
|
|
2022-11-13 19:41:14 +01:00
|
|
|
def new_on_run(func):
|
|
|
|
|
def wrapper(*args, **kwargs):
|
|
|
|
|
if args[0]._last_run_value < args[1] and args[1] > 0.8:
|
|
|
|
|
Quickturn.wavedash(args[0])
|
|
|
|
|
func(*args, **kwargs)
|
|
|
|
|
return wrapper
|
2024-01-16 15:06:45 +03:00
|
|
|
bascenev1lib.actor.spaz.Spaz.on_run = new_on_run(bascenev1lib.actor.spaz.Spaz.on_run)
|