inheritancegodot

When setting up stat code for 3 inherited scenes, an error is generated


So I have an enemy scene which has an enemy.gd script.

In there, I have the following.

extends CharacterBody2D
class_name Enemy

signal player_detected


@export var speed := 100
@export var knockback_resistance := 100.0
@export var knockback_strength := 150
@export var damage := GlobalFunctions.roll_dice(1,5,+5)
@export var xp := GlobalFunctions.roll_dice(1,3)
@export var attack_cooldown := 3

I have an Inherited scene which I changed the sprites and such.. But I want to change the defaults.

extends Enemy

@export var speed := 50
@export var knockback_resistance := 25.0
@export var knockback_strength := 75
@export var damage := GlobalFunctions.roll_dice(1,20,+5)

Note that the xp and attack_cooldown should be the default. But when I do this, I get the error...

"The member speed already exists in parent class Enemy"

If I just do

speed = 100

then I get

unexpected identifier "speed" in class body

I tried changing enemy.gd to

extends CharacterBody2D
class_name Enemy

signal player_detected


@export var stats: EnemyStats

and green_slime.gd to

extends Enemy
class_name EnemyStats

@export var enemy_type := "Slime"
@export var speed := 100
@export var knockback_resistance := 100.0
@export var knockback_strength := 150
@export var damage := GlobalFunctions.roll_dice(1,5,+5)
@export var xp := GlobalFunctions.roll_dice(1,3)
@export var attack_cooldown := 3

@export var hp := GlobalFunctions.roll_dice(3,10,+5):
    set(value):
        hp = value
        if value <= 0:
            player.player_xp += stats.xp
            animation_player.play("dead")

But then I get

class "EnemyStats" hides a global script class.

on green_slime.gd. Even if I attach it to the root of that scene (which is using the green_slime.gd script).

I have no globals set to this class name. I do have 3 files with

class_name EnemyStats

But since I am accessing that class name from enemy.gd (the location of all the movement and attacks and such), wouldn't it just use the script attached to that node (which would ignore blue_slime.gd and t_rex.gd)?

enter image description here

https://imgur.com/xjBLz0C

https://imgur.com/hEFOJtT

What am I doing wrong here? Should I just make lots of scenes and lots of scripts for each type of enemy? I feel like I should be able to Set defaults and in the inherited script, I change them.

I can't remove them from enemy.gd because some of the functions there rely on those values being present. Also, if I want to (for example) code in a "boost" in speed, then I need speed in that inherited script, don't I?

I feel like I'm missing something important here.


Solution

  • Since speed already exists in the parent, you can just change it in child classes. In the global space of a script (outside a function), you can only add declarations (functions, variables, signals).

    So if you want to define the properties of parents in children, you'll need to do so as early as possible, in a function, i.e. in the _ready function, for example.

    The code of the inheriting class would then be:

    extends Enemy
    
    func _ready():
        speed = 50
        knockback_resistance = 25.0
        knockback_strength = 75
        damage = GlobalFunctions.roll_dice(1,20,+5)