In my project I will have items with the same base behavior and attributes with different values (i.e durability is 20 for one variant and 40 for another)
They way I have it currently, I have an abstract class then a script for each variant which changes the attributes. This would mean I would end up with a bunch (at least 100) of ~10 line scripts.
Alternatively I can just have one script and use _init() function to set the attributes, then depending on the required variant, passing in different values.
I’m just wondering if there is a standard or recommended way to go about this?
As an example, I have an UpgradableEntity base class for anything I want to upgrade, this class handles the live state of the entity but also holds the “definition” resource. This resource is exported so I can define it in the inspector easily.
As for the “definition”, it looks something like this.
class_name UpgradableEntityDefinition
extends Resource
@export_group(“General”)
@export var display_name: String = “”
@export var description: String = “”
@export var currency_type: GameEnum.CURRENCY_TYPE = GameEnum.CURRENCY_TYPE.INGOT
@export var entity_type: GameEnum.ENTITY_TYPE = GameEnum.ENTITY_TYPE.BUILDING
@export_group(“Progression”)
@export_range(1, 8) var maximum_tier: int = 8
@export_range(1, 100) var levels_per_tier: int = 10
@export var level_progression: LevelProgressionDefinition
@export_group(“Purchase Cost”)
@export var base_purchase_cost: float = 100.0
@export var purchase_tier_multiplier: float = 3.0
@export_group(“Promotion Cost”)
@export var base_promotion_cost: float = 1000.0
@export var promotion_tier_multiplier: float = 3.0
func get_entity_type() → GameEnum.ENTITY_TYPE:
return entity_type
func get_display_name(_tier: int = 0) → String:
return display_name
func get_description(_tier: int = 0) → String:
return description
Then inside of the inspector, I can make adjustments. (Note: TowerDefinition extends UpgradableEntityDefinition)
This is just one of many ways to use the system. In some cases I also define these numbers in the definition and have the inspector be there in case I want to make one-off adjustments for whatever reason.
class_name TowerDefinition
extends UpgradableEntityDefinition
const NAME_BY_TYPE: Dictionary[GameEnum.TOWER_TYPE, String] = {
GameEnum.TOWER_TYPE.ARROW: “Arrow Tower”,
GameEnum.TOWER_TYPE.MAGE: “Mage Tower”,
}
const DESCRIPTION_BY_TYPE: Dictionary[GameEnum.TOWER_TYPE, String] = {
GameEnum.TOWER_TYPE.ARROW: “Fires fast attacking arrows that target enemies at a distance.”,
GameEnum.TOWER_TYPE.MAGE: “Casts magical orbs at the enemy deal small amounts of splash damage to nearby enemies.”,
}
const PURCHASE_COST_BY_TYPE: Dictionary[GameEnum.TOWER_TYPE, int] = {
GameEnum.TOWER_TYPE.ARROW: 100,
GameEnum.TOWER_TYPE.MAGE: 300,
}
@export var sub_entity_type: GameEnum.TOWER_TYPE = GameEnum.TOWER_TYPE.ARROW
func get_display_name(_tier: int = 0) → String:
return NAME_BY_TYPE.get(sub_entity_type)
func get_description(_tier: int = 0) → String:
return DESCRIPTION_BY_TYPE.get(sub_entity_type)
func get_sub_entity_type() → GameEnum.TOWER_TYPE:
return sub_entity_type
func get_purchase_cost(_tier: int = 1) → int:
return PURCHASE_COST_BY_TYPE.get(sub_entity_type, 100)