Using resources to create custom model stats and weapon stats

Godot Version

Godot 4.4.1

Question

I’m trying to make a system using resources where I can link a resource in another resource and have a script create effects. For example, one resource might be from class “modelstat” and the other “weaponstat.” A resource using weaponstat would be linked in another resource that utilizes modelstat. Then I want a separate script that might calculate the damage combining a stat in modelstat and weaponstat.
I have attempted this with code already but am getting an error for "Having an error of “Invalid access to property or key ‘weapon’ on a base object of type 'GDScript” The script I’m using is

extends Card
var modelstat := ModelStats
func apply_effects(targets: Array[Node]) → void:
var damage_effect := DamageEffect.new()
damage_effect.amount = modelstat.weapon.ammo * modelstat.weapon.damage
damage_effect.execute(targets)

This applies an effect where the damage amount is the weapon’s ammo multiplied by the weapons damage stat, which is attached to the modelstat.
I have tested the code without modelstat.weapon.ammo/damage and it worked, applying the effect to the targets. The moment I edited the code to call upon the modelstats weapon, it stopped working.

A few things:

You should put multi-line code under ``` for it to be properly formatted:
```
extends Card
var modelstat := ModelStats
func apply_effects(targets: Array[Node]) → void:
var damage_effect := DamageEffect.new()
damage_effect.amount = modelstat.weapon.ammo * modelstat.weapon.damage
damage_effect.execute(targets)
```
That will look like this:

extends Card
var modelstat := ModelStats
func apply_effects(targets: Array[Node]) → void:
	var damage_effect := DamageEffect.new()
	damage_effect.amount = modelstat.weapon.ammo * modelstat.weapon.damage
	damage_effect.execute(targets)

Inline code should be under `, like this: `inline code`, and that looks like this: inline code.

Now, for the error you are getting. This line is the (main) problem:

var modelstat := ModelStats

I am guessing that ModelStats is a script. Consider what the := operator does. When you do, for instance:

var value := 10

You say that value is a variable of type int whose value is 10. Godot inferred the type of the variable and assigned the value after :=. You wouldn’t do this:

var value := int

So the line:

var modelstat := ModelStats

sets the value (and NOT the type) of modelstat to ModelStats, and its type is GDScript.

How would I set the type to ModelStats?

I would need to see how ModelStats is defined in the first place.

This is how ModelStats is defined

class_name ModelStats

signal stats_changed

@export var model_id: String
@export var art: Texture
@export_group("Basic Stats")
@export var max_health := 5
@export var move := 6
@export var accuracy := 2
@export var strength := 2
@export var agility := 2
@export var willpower := 2

@export var armor := 0
@export var weapon : Weapon

var health: int : set = set_health

func set_health(value: int) -> void:
	health = clampi(value, 0, max_health)
	stats_changed.emit()

func set_accuracy(value: int) -> void:
	accuracy = clampi(value, 0, 100)
	stats_changed.emit()

func set_strength(value: int) -> void:
	strength = clampi(value, 0, 100)
	stats_changed.emit()

func set_agility(value: int) -> void:
	agility = clampi(value, 0, 100)
	stats_changed.emit()

func set_willpower(value: int) -> void:
	willpower = clampi(value, 0, 100)
	stats_changed.emit()

func set_armor(value: int) -> void:
	armor = clampi(value, 0, 100)
	stats_changed.emit

func take_damage(damage: int) -> void:
	if damage <= 0:
		return
	var initial_damage = damage
	damage = clampi(initial_damage - armor, 0, damage)
	self.health -= damage

func heal(amount : int) -> void:
	self.health += amount

func create_instance() -> Resource:
	var instance: ModelStats = self.duplicate()
	instance.health = max_health
	return instance```

Try:

var modelstat := ModelStats.new()

I also changed ModelStats definition code for the weapon to

var weapon := Weapon.new()

This seemed to fix all my issues, thank you!

1 Like

I have a unforeseen issue now, where the weapon stats aren’t being imported correctly. Instead they assume the default values, for example: I have a model with weapon ‘assault rifle’ which I’ve set to have 3 damage and 2 ammo. The default values are 3 damage and 3 ammo, and it’ll deal 9 damage when I play full auto. How would I get it to reference the specific model utilizing the action?

Where do you set it to have non-default values?

You can try this:

var modelstat := ModelStats.new()
modelstat.weapon = custom_weapon

This is my weapon resource definition

extends Resource
class_name Weapon

@export var weapon_id : String

@export_group("Weapon Attributes")
@export var damage := 3
@export var weapon_range := 12
@export var ammo := 3

This is inputted as a value into the ModelStats which I want to call upon whenever I use this action

How do you define ‘assault rifle’, and where do you use it?

I create a new resource using that script, weapon_id is ‘assault rifle’ and the damage and ammo is respectively 2 and 3.
Then in ModelStats script, i have

 @export var weapon: Weapon

so I can attach a weapon when a create a modelstat resource. Finally, the action ‘full auto’ is a separate script action which is the 1st script I included

extends Card
var modelstat := ModelStats
func apply_effects(targets: Array[Node]) → void:
var damage_effect := DamageEffect.new()
damage_effect.amount = modelstat.weapon.ammo * modelstat.weapon.damage
damage_effect.execute(targets)

I want full auto to activate when I choose the model that has the ‘assault rifle’ equipped, using the weapon attached to that model. There will be multiple models to choose from in my final game so I’m trying to debug how the action system is working.

Maybe you want to export the model stats info instead? Do you have these resources saved elsewhere?

@export var modelstat: ModelStats # no equals = sign, only colon : for type

Would this call upon that specific resource based on which model I have selected in game?

No. How does your selection process work? You will need to reference that modelstat into the card script, where in relation to the card call is the selected model?

Currently there isn’t a selection process, I’m just trying to get it to automatically attach a model resource to the card action. Assume the model is a “trooper,” I have only one trooper right now that I am trying to get it to automatically input that trooper into the card action.
Once I program it, the selection process will be me clicking on a model

Right, how will that data go from “trooper” to this card’s apply_effects that’s the big question. Does “trooper” exist in the scene tree? Does card? Where are these two thing relative to one another?

Trooper does exist in the scene tree, so does the cards. They both exist in the same major scene.

Ok so how does the Card know the Trooper is calling apply_effects, if you want exact help on this you will need to supply much more of the scripts and a screenshot of the scene tree.

Ah sorry about my questions as I’m still learning. Seems I needed to add a selection script to even test this functionality.