- Edited
Godot Version
4.3
I have successfully setup most of a micro, turn-based RPG game. There are two attack types, one where the character himself moves towards the opponent and one where he shoots a projectile. The attack and heal moves are defined as a resource, but the main action happens in the character script which is shared by both player and enemy. The problem i am facing is that while the basic attack action is taking place as expected, the same thing happens when a fireball projectile is supposed to be hurled towards the opponent.
The resources, character and projectile scripts are as follows:
Resource
extends Resource
class_name CombatAction
enum Type {
Attack,
Heal
}
@export var display_name : String
@export var action_type : Type
@export_category("Damage")
@export var damage : int
@export var projectile_scene : PackedScene
@export_category("Heal")
@export var heal_amount : int
@export var heal_scene : PackedScene
Character
extends Area2D
signal on_health_change
signal on_die(character : Area2D)
@export var combat_actions : Array[CombatAction]
@export var opponent : Area2D
@export var is_player : bool
@export var character : Area2D
@export var current_health : int = 25
@export var max_health : int = 25
var start_position : Vector2
var attack_opponent : bool
var current_combat_action : CombatAction
func _ready():
start_position = position
get_parent().connect("on_begin_turn", on_begin_turn)
func heal(health_amount : int) -> void:
current_health += health_amount
if current_health > max_health:
current_health = max_health
emit_signal ("on_health_change")
func cast_combat_action(combat_action : CombatAction) -> void:
current_combat_action = combat_action
if combat_action.damage > 0:
attack_opponent = true
elif combat_action.projectile_scene != null:
var projectile_instance : Sprite2D = combat_action.projectile_scene.instantiate()
projectile_instance.initialize(opponent, get_parent().end_turn)
get_parent().add_child(projectile_instance)
projectile_instance.position = position
attack_opponent = false
elif combat_action.heal_amount > 0:
heal(combat_action.heal_amount)
get_parent().end_turn()
func _process(delta):
if attack_opponent:
position = position.move_toward(opponent.position, delta * 2500)
if attack_opponent == false:
position = position.move_toward(start_position, delta * 1500)
if position.x == opponent.position.x and attack_opponent:
attack_opponent = false
opponent.take_damage(current_combat_action.damage)
get_parent().end_turn()
func take_damage(damage_to_take : int) -> void:
current_health -= damage_to_take
emit_signal("on_health_change")
if current_health <= 0:
pass
func on_begin_turn(c: Area2D) -> void:
if character == c:
determine_combat_action()
func determine_combat_action() -> void:
var health_percentage : float = get_health_percentage()
var want_to_heal : bool
var ca : CombatAction
if health_percentage <= 35:
var random : int = randi() % 3
if random == 0:
want_to_heal = true
if want_to_heal and has_combat_action_of_type(CombatAction.Type.Heal):
ca = get_combat_action_of_type(CombatAction.Type.Heal)
elif has_combat_action_of_type(CombatAction.Type.Attack):
ca = get_combat_action_of_type(CombatAction.Type.Attack)
if ca != null:
cast_combat_action(ca)
else:
get_parent().end_turn()
func get_health_percentage() -> float:
return float(current_health) / float(max_health) * 100
func has_combat_action_of_type(type : CombatAction.Type) -> bool:
for element in combat_actions:
if element.action_type == type:
return true
return false
func get_combat_action_of_type(type : CombatAction.Type) -> CombatAction:
var available_actions : Array[CombatAction] = []
for element in combat_actions:
if element.action_type == type:
available_actions.append(element)
return available_actions[randi() % available_actions.size()]`
Projectile
extends Sprite2D
signal hit_callback
@export var damage : int
@export var speed: float
var target : Area2D
func initialize(projectile_target : Area2D, on_hit_callback: Callable) -> void:
target = projectile_target
hit_callback.connect(on_hit_callback)
func _process(delta):
if target == null:
return
position = position.move_toward(target.position, speed * delta)
if position == target.position:
target.take_damage(damage)
emit_signal("hit_callback")
queue_free()
Please let me know if you need further information to help me!