Godot Version
4.5 stable
Question
I’m having trouble creating the architecture for different kinds of attacks in my game.
I’m making a 2D platformer. Characters can equip different Weapons, which are RefCounteds that contain data like the amount of damage they do. The reason they are RefCounteds, not Resources, is because weapons of the same type can have unique stats, and a base Resource called WeaponData is used to create and randomize them.
Finally, each weapon has a PackedScene exported to it, which is used to actually spawn the attack scene in the game world. This is because each kind of attack can have wildly different behavior. The scene should be given the data from the RefCounted Weapon class when it spawns.
So this is basically what this looks like:
class_name WeaponData extends Resource
@export var damage: float
@export var attack_scene: PackedScene
func create_weapon() -> Weapon:
var new_weapon = Weapon.new()
#Randomize damage here based on the exported var
new_weapon.damage = randomized_damage
return new_weapon
class_name Weapon extends RefCounted
var damage: float
var attack_scene: PackedScene
When a character actually uses an attack, they will instantiate the scene, then give it the data it needs.
This is the part where I’m stuck. I first made a base “Attack” class that extends Node2D, since I figured that every Attack scene should have some common properties and functions, like set_initial_position() or calculate_damage(), or a variable for the character who spawned the attack, etc.
But that doesn’t seem like it will work, because not every Attack will want a Node2D to be the root. For example, maybe some attacks have a CharacterBody2D as the root which needs to move_and_slide(). If a Node2D were the root, it wouldn’t move with the body, which could cause issues. It feels like a better idea to make every Attack with whatever root node works best for it. Yes?
But if I don’t share a common root node class for all Attack scenes, how can I pass the data from any Weapon to any Attack safely?
Should I be extending my Weapon class to create specific Weapons for each Attack?
Like this:
@abstract class_name Weapon extends RefCounted
var damage: float
var attack_scene: PackedScene
@abstract func instantiate_attack_scene(source_character: Character, target: Character)
func calculate_damage(source_character: Character):
//Some logic here for calculating base damage shared between all Weapons
class_name Explosion extends Weapon
func instantiate_attack_scene(source_character: Character, target: Character)
var scene = attack_scene.instantiate()
if scene is ExplosionAttack:
//Set up the scene however it needs to be set up, like by setting its damage and position...?
I’m not sure about this… it still feels off to me somehow. Does anyone have a similar system or some insight?