0 votes

So I am coding a prototype for my game to get a test model and to mess around with battle mechanics before I commit to a full dive. There have definitely been hurdles but I've managed to overcome all of them up till now.

The code I'm using to tell the game to attack a target(Either the player or enemy) seems to only work once for each target and then stops working altogether.

Below is my BattleHandler Script for any who wants to brave the answer:

extends Node
onready var ActionButtons = $UI/ActionButtons
onready var Victory = $UI/Victory
onready var Enemy = $Enemy
signal end_turn

# Player Initialization
var JobData = load("res://Jobs/Base Jobs/Squire.tres")
var WeaponData = load("res://Items/Weapons/Squire's Sword.tres")
var ArmorData = load("res://Items/Armors/Tweed Tunic.tres")
var PlayerHealth = 0
var PlayerAttackStat = WeaponData.BaseAttack + JobData.Strength
var PlayerDefenseStat = ArmorData.BaseDefense + JobData.Vitality

# Enemy Initialization
signal EnemyDefeated
var EnemyData = load("res://Enemies/Gellie.tres")
var EnemyHealth = 0
var EnemyAttackStat = EnemyData.BaseAttack + EnemyData.Strength
var EnemyDefenseStat = EnemyData.BaseDefense + EnemyData.Vitality

# Battle Functions
func SetHealth(Target, TargetLabel):
    TargetLabel.value = Target

func Attack(Damage, Target, TargetLabel):
    Target = Target - Damage
    SetHealth(Target, TargetLabel)
    emit_signal("end_turn")

func _ready():
    Victory.hide()
    EnemyHealth = EnemyData.MaxHealth
    SetHealth(EnemyHealth, $Enemy/Health)
    PlayerHealth = JobData.MaxHealth
    SetHealth(PlayerHealth, $Player/Health)
    StartPlayerTurn()

func StartEnemyTurn():
    ActionButtons.hide()
    if EnemyHealth <= 0:
        emit_signal("EnemyDefeated")
        VictoryScreen()
        pass
    if EnemyData != null:
        yield(get_tree().create_timer(0.4),"timeout")
        Attack(3, PlayerHealth, $Player/Health)
    StartPlayerTurn()

func StartPlayerTurn():
    ActionButtons.show()
    yield(self, "end_turn")
    StartEnemyTurn()

func _on_AttackButton_pressed():
    Attack(3, EnemyHealth, $Enemy/Health)

func VictoryScreen():
    EnemyData = null
    Enemy.hide()
    Victory.show()
Godot version 3.4
in Engine by (24 points)

1 Answer

+1 vote
Best answer

I had a look at the code and i think your functions do get called as expected.

The problem is your EnemyHealth and PlayerHealth variables are not modified after you set them in _ready().
Integer variable (i'm assuming your vars are still int after _ready) are passed by value, not by reference.

What you can do is make your Attack function calculate and return new Health value and then assign that value to either PlayerHealth or EnemyHealth. Something like this (the function can now be static so i made is such):

static func Attack(Damage, Target):
    return Target - Damage

and use it like this

if EnemyData != null:
        yield(get_tree().create_timer(0.4),"timeout")
        PlayerHealth = Attack(3, PlayerHealth)
        SetHealth(PlayerHealth, $Player/Health)
        emit_signal("end_turn")
by (2,298 points)
selected by

Hmmm, didn't even occur to me to do that, thanks so much mate. I ended up reworking the whole script out of frustration and it works now, but I will definitely remember this for if I encounter this problem again. Thanks for the help.

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read Frequently asked questions and How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to [email protected] with your username.