mirror of
https://github.com/bombsquad-community/plugin-manager.git
synced 2025-10-08 14:54:36 +00:00
[ci] auto-format
This commit is contained in:
parent
5e0280df5b
commit
23314581cc
1 changed files with 31 additions and 26 deletions
|
|
@ -26,7 +26,7 @@ from bastd.actor.spaz import Spaz
|
|||
|
||||
if TYPE_CHECKING:
|
||||
pass
|
||||
|
||||
|
||||
"""
|
||||
This mod is much more "technical" than my other mods.
|
||||
I highly recommend checking out the code of this mod once you have a good understanding of programming.
|
||||
|
|
@ -70,6 +70,8 @@ if TYPE_CHECKING:
|
|||
"""
|
||||
|
||||
# ba_meta export plugin
|
||||
|
||||
|
||||
class AutoRun(ba.Plugin):
|
||||
|
||||
# During my research and prototyping I figured I'd have to do some linear algebgra.
|
||||
|
|
@ -77,7 +79,7 @@ class AutoRun(ba.Plugin):
|
|||
# Because of this I made certain functions from scratch that are easily accessible.
|
||||
# If you are curious over the details, look these up on the Internet.
|
||||
# I'll only briefly cover their purpose in the context of the mod.
|
||||
|
||||
|
||||
# Here's the dot product function.
|
||||
# To keep it short, it returns the difference in angle between two vectors.
|
||||
# We're gonna use that knowledge to check how tight our turn is.
|
||||
|
|
@ -90,11 +92,11 @@ class AutoRun(ba.Plugin):
|
|||
def clamp(num, min_value, max_value):
|
||||
num = max(min(num, max_value), min_value)
|
||||
return num
|
||||
|
||||
|
||||
# A vector can be of any length, but we need them to be of length 1.
|
||||
# This vector normalization function changes the magnitude of a vector without changing its direction.
|
||||
def normalize(vector):
|
||||
length = math.hypot(vector[0], vector[1]) # Pythagoras says hi
|
||||
length = math.hypot(vector[0], vector[1]) # Pythagoras says hi
|
||||
# Sometimes we'll get a [0,0] vector and dividing by 0 is iffy.
|
||||
# Let's leave the vector unchanged if that's the case.
|
||||
if length > 0:
|
||||
|
|
@ -107,29 +109,29 @@ class AutoRun(ba.Plugin):
|
|||
# Here I'm defining a new spaz init function that'll be replaced.
|
||||
def new_init(func):
|
||||
def wrapper(*args, **kwargs):
|
||||
|
||||
|
||||
# Here's where we execute the original game's code, so it's not lost.
|
||||
# We want to add our code at the end of the existing code, so our code goes under that.
|
||||
func(*args, **kwargs)
|
||||
|
||||
|
||||
# We define some variables that we need to keep track of.
|
||||
# For future reference, if you see args[0] anywhere, that is "self" in the original function.
|
||||
args[0].autorun_timer: ba.Timer | None = None
|
||||
args[0].autorun_override = False
|
||||
|
||||
|
||||
# We wanna do our auto run calculations when the player moves their analog stick to make it responsive.
|
||||
# However doing this ONLY tracks changes in analog stick position and some bugs come up because of that.
|
||||
# For example moving via dpad on a gamepad can sometimes not execute the run at all.
|
||||
# To keep the behavior predictable, we also want to update our auto run functionality with a periodic timer.
|
||||
# We could ignore the update on analog stick movement, but then it feels terrible to play. We need both.
|
||||
# Update on analog movement for responsive controls, timer to foolproof everything else.
|
||||
|
||||
|
||||
# To make our timer, we want to have access to our function responsible for doing the auto run logic.
|
||||
# The issue is that timers only work when a function is created within the context of the game.
|
||||
# Timer throws a tantrum if it references the run_update function, but NOT if that function is an intermediary.
|
||||
def spaz_autorun_update():
|
||||
AutoRun.run_update(args[0])
|
||||
|
||||
|
||||
# We don't want this logic to be ran on bots, only players.
|
||||
# Check if we have a player assigned to that spaz. If we do, let's make our timer.
|
||||
if args[0].source_player:
|
||||
|
|
@ -138,8 +140,9 @@ class AutoRun(ba.Plugin):
|
|||
# Notice how it's the capital T Timer instead of the small letter.
|
||||
# That's important, because big T returns a timer object we can manipulate.
|
||||
# We need it assigned to a variable, because we have to delete it once it stops being relevant.
|
||||
args[0].autorun_timer = ba.Timer(0.1, spaz_autorun_update, timetype=TimeType.SIM, repeat=True)
|
||||
|
||||
args[0].autorun_timer = ba.Timer(
|
||||
0.1, spaz_autorun_update, timetype=TimeType.SIM, repeat=True)
|
||||
|
||||
return wrapper
|
||||
# Let's replace the original function with our modified version.
|
||||
bastd.actor.spaz.Spaz.__init__ = new_init(bastd.actor.spaz.Spaz.__init__)
|
||||
|
|
@ -151,31 +154,31 @@ class AutoRun(ba.Plugin):
|
|||
# On mobile it's always 0 and 1, but on gamepad you can have values between them
|
||||
# For example you can do a jog instead of a sprint.
|
||||
# We activate this function periodically via a timer and every time the player moves their analog stick.
|
||||
# The idea is to make it 1 when the player is running forward and make it 0
|
||||
# The idea is to make it 1 when the player is running forward and make it 0
|
||||
# when the player makes the tightest turn possible.
|
||||
# We also want to account for how far the analog stick is pushed.
|
||||
def run_update(self) -> None:
|
||||
# Let's not run this code if our character does not exist or the player decides to run "manually".
|
||||
if not self.node or self.autorun_override:
|
||||
return
|
||||
|
||||
|
||||
# Let's read our player's analog stick.
|
||||
# Notice how the vertical direction is inverted (there's a minus in front of the variable).
|
||||
# We want the directions to corespond to the game world.
|
||||
vertical = -self.node.move_up_down
|
||||
horizontal = self.node.move_left_right
|
||||
movement_vector = [horizontal, vertical]
|
||||
|
||||
|
||||
# Get our character's facing direction
|
||||
facing_direction = (self.node.position[0] - self.node.position_forward[0],
|
||||
facing_direction = (self.node.position[0] - self.node.position_forward[0],
|
||||
self.node.position[2] - self.node.position_forward[2])
|
||||
# We want our character's facing direction to be a normalized vector (magnitude of 1).
|
||||
facing_direction = AutoRun.normalize(facing_direction)
|
||||
|
||||
|
||||
# We don't want to run our code if the player has their analog stick in a neutral position.
|
||||
if movement_vector == [0.0, 0.0]:
|
||||
return
|
||||
|
||||
|
||||
# Get the difference between our current facing direction and where we plan on moving towards.
|
||||
# Check the dot function higher up in the script for details.
|
||||
dot = AutoRun.dot(facing_direction, AutoRun.normalize(movement_vector))
|
||||
|
|
@ -184,20 +187,21 @@ class AutoRun(ba.Plugin):
|
|||
# We want it from 0 to 1.
|
||||
# 0 being 180 degree turn, 1 being running exactly straight.
|
||||
dot = (dot + 1) / 2
|
||||
|
||||
|
||||
# Let's read how far our player pushed his stick. 1 being full tilt, 0 being neutral.
|
||||
run_power = math.hypot(movement_vector[0], movement_vector[1]) # Heres our homie Pythagoras once again
|
||||
|
||||
# Heres our homie Pythagoras once again
|
||||
run_power = math.hypot(movement_vector[0], movement_vector[1])
|
||||
|
||||
# I noticed the player starts running too fast if the stick is pushed half-way.
|
||||
# I changed the linear scale to be exponential.
|
||||
# easings.net is a great website that shows you different ways of converting a linear curve to some other kind.
|
||||
# Here I used the EaseInQuad easing, which is just raising the value to the power of 2.
|
||||
# This should make half-way pushes less severe.
|
||||
run_power = pow(run_power, 2)
|
||||
|
||||
|
||||
# Just in case let's clamp our value from 0 to 1.
|
||||
run_power = AutoRun.clamp(run_power, 0.0, 1.0)
|
||||
|
||||
|
||||
# Here we combine our dot result with how far we pushed our stick to get the final running value.
|
||||
# Clamping from 0 to 1 for good measure.
|
||||
self.node.run = AutoRun.clamp(run_power * dot, 0.0, 1.0)
|
||||
|
|
@ -215,7 +219,7 @@ class AutoRun(ba.Plugin):
|
|||
return wrapper
|
||||
# We replace the character running function with our modified version.
|
||||
bastd.actor.spaz.Spaz.on_run = new_onrun(bastd.actor.spaz.Spaz.on_run)
|
||||
|
||||
|
||||
# There's two function that are called when our player pushes the analog stick - two for each axis.
|
||||
# Here's for the vertical axis.
|
||||
def new_updown(func):
|
||||
|
|
@ -228,7 +232,7 @@ class AutoRun(ba.Plugin):
|
|||
return wrapper
|
||||
# You get the idea.
|
||||
bastd.actor.spaz.Spaz.on_move_up_down = new_updown(bastd.actor.spaz.Spaz.on_move_up_down)
|
||||
|
||||
|
||||
# Let's do the same for our horizontal axis.
|
||||
# Second verse same as the first.
|
||||
def new_leftright(func):
|
||||
|
|
@ -237,8 +241,9 @@ class AutoRun(ba.Plugin):
|
|||
if not args[0].autorun_override and args[0].source_player:
|
||||
AutoRun.run_update(args[0])
|
||||
return wrapper
|
||||
bastd.actor.spaz.Spaz.on_move_left_right = new_leftright(bastd.actor.spaz.Spaz.on_move_left_right)
|
||||
|
||||
bastd.actor.spaz.Spaz.on_move_left_right = new_leftright(
|
||||
bastd.actor.spaz.Spaz.on_move_left_right)
|
||||
|
||||
# There's one downside to the looping timer - it runs constantly even if the player is dead.
|
||||
# We don't want to waste computational power on something like that.
|
||||
# Let's kill our timer when the player dies.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue