Rock Paper Scissors system bugs

Godot Version

v4.5.1

Question

Hello, I’m working on a rock-paper-scissors style combat system for my game. I’m very new to coding and have come across two bugs.

If it was working correctly, then whenever the W, A or S keys were pressed, the script would choose an “attack”, compare it to the button pressed and determine an outcome: the player would be damaged, the enemy would be damaged or nothing. Firstly, the enemy seems to choose two attacks for every button press (or at least two attack types are printed in the terminal, sometimes the same, sometimes different ones) and secondly it doesn’t change tactics properly in the second phase. Below half HP it should choose from “intimidate” and “charm” attacks, but it sometimes throws in a “knowledge”, which it shouldn’t be able to do in the second half. Not sure why.

Enemy script:

extends CharacterBody2D

# signals
signal charming
signal knowledge
signal intimidating

# Choosing the move type variables
var movechoice
var movetype = KNOWLEDGE

enum {
	KNOWLEDGE,
	CHARM,
	INTIMIDATE
	}
	
# stats
var maxhealth = 200
var health = maxhealth
var charm = 10
var know = 6
var intimidate = 7

# choosing what move type to use when the player chooses a move
func _process(delta):
	if health > 100:
		if Input.is_action_just_pressed("input"):
			movechoice = randi() % 10
			if movechoice < 7:
				movetype = CHARM
				emit_signal("charming")
				print("charm")
			else:
				movetype = KNOWLEDGE
				emit_signal("knowledge")
				print("know")
	elif health <= 100:
		if Input.is_action_just_pressed("input"):
			movechoice = randi() % 10
			if movechoice < 7:
				movetype = INTIMIDATE
				emit_signal("intimidating")
				print("intim")
			else:
				movetype = CHARM
				emit_signal("charming")
				print("charm")


func _on_character_body_2d_2_attack():
	health = health - 10
	if health < 1:
		print("win")

Relevant bit of player script:

extends CharacterBody2D

signal attack

# health
var maxhealth = 100
var health = maxhealth

# signal checks and rock-paper-scissor stuff
func _on_character_body_2d_2_charming():
	if Input.is_action_just_pressed("w"):
		emit_signal("attack")
	elif Input.is_action_just_pressed("a"):
		health = health - 10
		if health < 1:
			print("lose")
	elif Input.is_action_just_pressed("s"):
		pass

func _on_character_body_2d_2_knowledge():
	if Input.is_action_just_pressed("w"):
		pass
	elif Input.is_action_just_pressed("a"):
		emit_signal("attack")
	elif Input.is_action_just_pressed("s"):
		health = health - 10
		if health < 1:
			print("lose")

func _on_character_body_2d_2_intimidating():
	if Input.is_action_just_pressed("w"):
		health = health - 10
		if health < 1:
			print("lose")
	elif Input.is_action_just_pressed("a"):
		pass
	elif Input.is_action_just_pressed("s"):
		emit_signal("attack")

Any and all help is appreciated!

Update: by printing out the “health” values, it seems like only the second “enemy attack output” matters. “Know” only appears as the first “attack output” which seems to be connected to a permanently maximum HP. I haven’t worked out why there’s a permanently max HP version and a normal interacting version of the enemy, but I suppose the system works overall even if I don’t find a solution?

Use print statements and debugger breakpoints to monitor where your program is going, and what are the values of relevant variables.

2 Likes

Hard to tell without all the code, but sure, create some breakpoints and prints to debug. For example to print out health of the enemy to see when or if it stays lower 100.

In addition, I would rethink all the logic. IMHO it is not good to catch is_action_just_pressed in the player and enemy script.

I would rather catch the Input event in the player _process and send a signal “key_pressed” to the enemy script.
Why you put the just_pressed in the character_body functions?

This is the whole code, since I’m building individual small prototypes to work out each element of the game and this one is just the combat system.

I tried using a signal for a bit, but it meant that holding the key would keep sending a signal to the enemy script. The way it is now, it only gives responses when I press individually, which is more the way I want it to work (though as mentioned above it gives two responses for each press when I only want one)

As for why I put just_pressed in the character_body functions, I don’t know. I am very new to this and that seemed like a good thing to do at the time. Is there a better place to put it?

I managed to fix the issue, I’m not sure what I did but it works now. I started the project again, I think it was something to do with how the scenes were connected up. Thanks for all the input!

I would put it in the player _process or _physic_process function.
When you are using just_pressed it should not send the signal the whole time.