[ci] auto-format

This commit is contained in:
TheMikirog 2023-01-01 20:03:15 +00:00 committed by Rikko
parent 5e0280df5b
commit 23314581cc

View file

@ -26,7 +26,7 @@ from bastd.actor.spaz import Spaz
if TYPE_CHECKING: if TYPE_CHECKING:
pass pass
""" """
This mod is much more "technical" than my other mods. 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. 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 # ba_meta export plugin
class AutoRun(ba.Plugin): class AutoRun(ba.Plugin):
# During my research and prototyping I figured I'd have to do some linear algebgra. # 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. # 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. # 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. # I'll only briefly cover their purpose in the context of the mod.
# Here's the dot product function. # Here's the dot product function.
# To keep it short, it returns the difference in angle between two vectors. # 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. # 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): def clamp(num, min_value, max_value):
num = max(min(num, max_value), min_value) num = max(min(num, max_value), min_value)
return num return num
# A vector can be of any length, but we need them to be of length 1. # 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. # This vector normalization function changes the magnitude of a vector without changing its direction.
def normalize(vector): 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. # 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. # Let's leave the vector unchanged if that's the case.
if length > 0: if length > 0:
@ -107,29 +109,29 @@ class AutoRun(ba.Plugin):
# Here I'm defining a new spaz init function that'll be replaced. # Here I'm defining a new spaz init function that'll be replaced.
def new_init(func): def new_init(func):
def wrapper(*args, **kwargs): def wrapper(*args, **kwargs):
# Here's where we execute the original game's code, so it's not lost. # 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. # We want to add our code at the end of the existing code, so our code goes under that.
func(*args, **kwargs) func(*args, **kwargs)
# We define some variables that we need to keep track of. # 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. # 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_timer: ba.Timer | None = None
args[0].autorun_override = False args[0].autorun_override = False
# We wanna do our auto run calculations when the player moves their analog stick to make it responsive. # 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. # 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. # 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. # 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. # 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. # 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. # 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. # 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. # Timer throws a tantrum if it references the run_update function, but NOT if that function is an intermediary.
def spaz_autorun_update(): def spaz_autorun_update():
AutoRun.run_update(args[0]) AutoRun.run_update(args[0])
# We don't want this logic to be ran on bots, only players. # 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. # Check if we have a player assigned to that spaz. If we do, let's make our timer.
if args[0].source_player: 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. # 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. # 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. # 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 return wrapper
# Let's replace the original function with our modified version. # Let's replace the original function with our modified version.
bastd.actor.spaz.Spaz.__init__ = new_init(bastd.actor.spaz.Spaz.__init__) 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 # 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. # 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. # 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. # when the player makes the tightest turn possible.
# We also want to account for how far the analog stick is pushed. # We also want to account for how far the analog stick is pushed.
def run_update(self) -> None: def run_update(self) -> None:
# Let's not run this code if our character does not exist or the player decides to run "manually". # 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: if not self.node or self.autorun_override:
return return
# Let's read our player's analog stick. # Let's read our player's analog stick.
# Notice how the vertical direction is inverted (there's a minus in front of the variable). # 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. # We want the directions to corespond to the game world.
vertical = -self.node.move_up_down vertical = -self.node.move_up_down
horizontal = self.node.move_left_right horizontal = self.node.move_left_right
movement_vector = [horizontal, vertical] movement_vector = [horizontal, vertical]
# Get our character's facing direction # 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]) self.node.position[2] - self.node.position_forward[2])
# We want our character's facing direction to be a normalized vector (magnitude of 1). # We want our character's facing direction to be a normalized vector (magnitude of 1).
facing_direction = AutoRun.normalize(facing_direction) 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. # 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]: if movement_vector == [0.0, 0.0]:
return return
# Get the difference between our current facing direction and where we plan on moving towards. # 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. # Check the dot function higher up in the script for details.
dot = AutoRun.dot(facing_direction, AutoRun.normalize(movement_vector)) dot = AutoRun.dot(facing_direction, AutoRun.normalize(movement_vector))
@ -184,20 +187,21 @@ class AutoRun(ba.Plugin):
# We want it from 0 to 1. # We want it from 0 to 1.
# 0 being 180 degree turn, 1 being running exactly straight. # 0 being 180 degree turn, 1 being running exactly straight.
dot = (dot + 1) / 2 dot = (dot + 1) / 2
# Let's read how far our player pushed his stick. 1 being full tilt, 0 being neutral. # 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 noticed the player starts running too fast if the stick is pushed half-way.
# I changed the linear scale to be exponential. # 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. # 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. # 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. # This should make half-way pushes less severe.
run_power = pow(run_power, 2) run_power = pow(run_power, 2)
# Just in case let's clamp our value from 0 to 1. # Just in case let's clamp our value from 0 to 1.
run_power = AutoRun.clamp(run_power, 0.0, 1.0) 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. # 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. # Clamping from 0 to 1 for good measure.
self.node.run = AutoRun.clamp(run_power * dot, 0.0, 1.0) self.node.run = AutoRun.clamp(run_power * dot, 0.0, 1.0)
@ -215,7 +219,7 @@ class AutoRun(ba.Plugin):
return wrapper return wrapper
# We replace the character running function with our modified version. # We replace the character running function with our modified version.
bastd.actor.spaz.Spaz.on_run = new_onrun(bastd.actor.spaz.Spaz.on_run) 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. # There's two function that are called when our player pushes the analog stick - two for each axis.
# Here's for the vertical axis. # Here's for the vertical axis.
def new_updown(func): def new_updown(func):
@ -228,7 +232,7 @@ class AutoRun(ba.Plugin):
return wrapper return wrapper
# You get the idea. # You get the idea.
bastd.actor.spaz.Spaz.on_move_up_down = new_updown(bastd.actor.spaz.Spaz.on_move_up_down) 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. # Let's do the same for our horizontal axis.
# Second verse same as the first. # Second verse same as the first.
def new_leftright(func): def new_leftright(func):
@ -237,8 +241,9 @@ class AutoRun(ba.Plugin):
if not args[0].autorun_override and args[0].source_player: if not args[0].autorun_override and args[0].source_player:
AutoRun.run_update(args[0]) AutoRun.run_update(args[0])
return wrapper 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. # 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. # We don't want to waste computational power on something like that.
# Let's kill our timer when the player dies. # Let's kill our timer when the player dies.