• Godot Help
  • Need help with implementing my mount&blade-style combat system

Hi!
I'm trying to make a mount&blade style 4-directional combat system and I got most of it working. A feature of the combat is that the player can chain attacks if he presses attack while already attacking. The problem Im having is that this chain function is working when I chain attacks in different directions each time, but not when I want to chain attacks in the same direction. So basically I want to be able to attack in this order: AttackLeft->AttackLeft...
whereas right now it goes like: AttackLeft->Idle->AttackLeft
If I'm Attacking in one direction, and I press attack in that direction again, I want the animation to smoothly transition back to the beginning of that animation, instead of going to the Idle Animation first and then going to the attack animation. I'm sorry if I'm not being clear enough. Here's a video where I try to explain it better(sry for the quality):
Video

This is the image for the State Machine that controls the attack animations:

I know its a mess lol.


@export var animTree:AnimationTree

var attack_pressed: bool
var attacking: bool

var attack_dir: String
var attackTransition: String

func _input(event):
### This is where I determine the attacking direction based on mouse-movement.
	if attack_pressed:
		if (event is InputEventMouseMotion):
			if event.relative.x >= 2 and event.relative.y > -2 and event.relative.y < 2:
				attack_dir = "Right"
			elif event.relative.x < -2 and event.relative.y > -2 and event.relative.y < 2:
				attack_dir = "Left"
			elif event.relative.y <= -2 and event.relative.x >= -2 and event.relative.x <= 2:
				attack_dir = "Up"
			elif event.relative.y > 2 and event.relative.x >= -2 and event.relative.x <= 2:
				attack_dir = "Down"
			else:
				attack_dir = ""
	else:
		attack_dir = ""

func _physics_process(delta):
	if Input.is_action_just_pressed("Attack"):
		attack_pressed = true
	elif (Input.is_action_just_released("Attack") and !attacking) or (attack_dir != "" and attacking):
		attack_pressed = false
	if attack_pressed and attack_dir != "":
		attackTransition = "parameters/OneHandedAttackTransition/transition_request"
		animTree.set(attackTransition, "Attacking")
		print("3")
		var playback = animTree.get("parameters/OneHandedAttacking/playback") as AnimationNodeStateMachinePlayback
		
		playback.travel("Attack"+str(attack_dir), false)

/// These two functions are called as methods within the attack animations
func attack_begin():
	attacking = true

func attack_end():
	attacking = false```


(I dont know why this part is getting put into my code. Its supposed to be part of the post.)
Again, really sorry for the mess, I'm not the best programmer. I realize this might be a lot and am not expecting someone else to do the whole thing for me. I'm just stuck with this small detail of my combat system and I'm appreciative of any help I can get.
  • Jesusemora replied to this.
  • SCIPIO You know the easiest might be to just duplicate each of the attack states and transition from AttackUp1 to AttackUp2 etc.

    There has to be a transition, but perhaps in addition to the idle there could be an empty or reset/clear etc. state. Something extremely short, even more basic than the idle. Essentially just a T-Pose if you will. A single keyframe animation state for a quick reset? Or alternatively if each attack animation is loopable then you maintain the state and let the animation loop?

    Got to keep a timer to count the amount of attacks in that case I guess, or log the inputs to count the attacks? But then what if the opponent interrupts? Oh you might want a state for interrupts too I guess...

      Megalomaniak I Couldn't fix it but I think I'll just leave it as it is. Might be more interesting because it forces the player to switch up their attacks and attack from different directions. But thanks for the help anyway!

        SCIPIO You know the easiest might be to just duplicate each of the attack states and transition from AttackUp1 to AttackUp2 etc.

          Megalomaniak I had already tried that before making the post and I couldn't get it to work but I tried it again and finally managed to make everything work perfectly! This is how the state machine looks now :')

          SCIPIO I don't know if you got an answer already, but use a BlendSpace2D connected to a OneShot in a blendtree inside your StateMachine, that's how I did it.

          I made something like this with movement but can't find it, it used a jump. But it's the same structure.
          When the character Jumps I trigger the one shot. The rest of the time I'm inputting directions to both blendspaces: the player movement and a blendspace2D with 4 jump directions. The OneShot triggers the animation from the beggining and the blendspace2D ensures that it's the correct direction.

            Jesusemora I got it working at last but admittedly your method seems cleaner and more intuitive so I tried to switch to it. But the issue I get now is that I can't chain attacks the way I want to. If I attack, and I hit attack again, it will cancel the first attack animation and immediately jump to the next, whereas I want it to finish the first attack animation and then smoothly transition to the next. For that reason I think I'm going to stick with the other method but thanks anyways.