Error: Object not inherited from GDScript, triing to asign to TypedArray

Godot Version

4.3 & 4.2

Question

I get the error validate_object: Attempted to assign an object into a TypedArray, that does not inherit from 'GDScript'.
It seems to be related to Resources which export other resources. But because it is an C++ error I don’t know how to debug it.

If you have any idea how to find the error I would be relay grateful!

Can you show your resource-script?

1 Like

Thanks for the reply!
Its a bit complicated so:
The script that causes the error when I load the only relefant part is:
In Equipment (Parent resource):

@export var cards: Array[CardResource] = []

And when in CardRessource:

@export var effects: Array[CardEffect] = []

and there I add a card effect which is need for the error to occur.
The Whole resource scripts (Its a lot I know sorry):
Equipment:

@tool
class_name Equipment
extends Item

const CARD = preload("res://Units/Cards/Card.tscn")
const NUMBER_AVG_STATS: int = 3
const DIVIATION_PORTION: float = 0.3

@export var level: int = 0
@export var rarity: Rarity.Type = Rarity.Type.COMMON
@export var cards: Array[CardResource] = []

@export var stats: Array[StatsScale]
	#set(new):
		#if !stats_set:
			#stats_set = true
			#if new.is_empty():
				#return
		#stats = new

## Click to rerole stats & cards
@export var rerole: bool:
	set(new):
		if Engine.is_editor_hint():# && new == true:
			role_stats()

var __util_card: CardResource

func _init():
	# Only run code in game
	if Engine.is_editor_hint():
		return
	super()
	var switch = SpecialSwitchEquipment.new()
	switch.equipment = self
	var special = EffectSpecial.new()
	special.special = switch
	var switch_equipment = load("res://Units/Cards/General/SwitchEquipment.tres")
	__util_card = switch_equipment.duplicate()
	__util_card.add_effect(special)
	cards_changed()

func cards_changed():
	pass

## Roles new stats and cards
func role_stats():
	if !reroleable():
		return
	# Named & Divine weapons have specified stats & cards
	if rarity == Rarity.Type.NAMED || rarity == Rarity.Type.DIVINE:
		return
	stats = []
	cards = []
	
	# The price of a equipment determins the strength of stats
	var value = price
	
	
	var avg_per_stat: float  = value / NUMBER_AVG_STATS
	while true:
		var stat_type: EntityStats.StatType = randi_range(0, EntityStats.StatType.size() -1) as EntityStats.StatType
		var diviation = avg_per_stat*DIVIATION_PORTION
		var st_value = min(randfn(avg_per_stat, diviation), value)
		
		var result = HLP.first_element(stats, func(stat: StatsScale): return stat.type == stat_type)
		if result:
			result.amount += st_value
		else:
			stats.append(StatsScale.new(stat_type, st_value))
		value -= st_value
		
		if value == 0:
			break
		elif value < 0:
			printerr("Equipment | __role_stats: value < 0 => Weapon is better than should be")
			break
	
	# TODO impl
	#for i in 2:
		#var possible_cards = CardPiles.get_pile(EntityStats.Role.values().pick_random(), Rarity.Type.COMMON)
		#if !possible_cards.is_empty():
			#cards.append(possible_cards.pick_random())
	
	stats.sort_custom(func(a: StatsScale, b: StatsScale): return a.amount > b.amount)

func equip(unit: Unit):
	var entity_stats: EntityStats = unit.entity_stats
	for stat in stats:
		entity_stats.add_stat(stat.type, stat.amount)
func unequip(unit: Unit):
	var entity_stats: EntityStats = unit.entity_stats
	for stat in stats:
		entity_stats.add_stat(stat.type, -stat.amount)

func item_info_text() -> String:
	var text: String = __item_heading_text()
	text += "[img=16]res://Art/Icons/Stats/Level.png[/img]" + str(level)
	for i in stats.size():
		var stat_scale = stats[i]
		text += Kompendium.stat_string(stat_scale.type) + ": "
		text += HLP.to_decimal_string(stat_scale.amount, 1)
		if i < stats.size() - 1:
			text += ", "
		else:
			text += "\n"
	return text

## True if new stats can be generated 
## (False for food)
func reroleable() -> bool:
	return true

func util_card() -> CardResource:
	return __util_card

CardResources:

@tool
class_name CardResource
extends Resource


@export var name: String
@export_range(0, 1000000) var level: int = 1
@export var rarit: Rarity.Type = Rarity.Type.COMMON
@export var reach: int = 1
@export var ap_cost: int = 1
@export var fatigue_cost: int = 1
@export var effects: Array[CardEffect] = []
@export var __target: Target.Type
@export var exile: bool = false
@export_range(0, 5) var charge: float = 0

# Should this card be used for auto attacks
var auto_attack: bool = false

func needs_target() -> Target.Type:
	return __target
	#var target: Target.Type = Target.Type.NONE
	#
	#for effect in __effects:
		#if !effect:
			#printerr("Resource | needs_target: effect is null in " + HLP.class_string(self))
		#target = Target.merge_targets(target, effect.needs_target())
	## Remove caster because they shouldn't be exported as target
	#if target == Target.Type.CASTER:
		#target = Target.Type.NONE
	#
	#return target

func calc_target():
	for effect in effects:
		if effect:
			__target = Target.merge_targets(__target, effect.needs_target())
	# Remove caster because they shouldn't be exported as target
	#if target == Target.Type.CASTER:
		#target = Target.Type.NONE
	
	return __target

func add_effect(effect: CardEffect):
	effects.append(effect)
	calc_target()

func get_effects():
	return effects

func generate(type: Item.Type, _previous_data: GeneratePreviousData):
	var reach_mean: float = 1
	if GenerateCard.equipment_different[type].has("reach"):
		reach_mean = GenerateCard.equipment_different[type].has("reach")
	var reach_div: float = 0
	if GenerateCard.equipment_different[type].has("re_div"):
		reach_div = GenerateCard.equipment_different[type].has("re_div")
	
	reach = max(0, round(randfn(reach_mean, reach_div)))
	_previous_data.reach = reach
	

CardEffect:

@tool
class_name CardEffect
extends Resource

@export var _target_type: Target.Type = Target.Type.INVALID:
	set = _new_target_set
var _parent_type: Target.Type

func _init():
	if Engine.is_editor_hint():
		_set_parent_type()
		_new_target_set(_target_type)

func _set_parent_type():
	_parent_type = Target.Type.INVALID

## Overrride to prohibit some values
func _new_target_set(new: Target.Type):
	if Target.is_sub_type(new, _parent_type):
		_target_type = new
	else:
		_target_type =  _parent_type

func apply_effect(_caster, _target, _card, _scale: float = 1):
	printerr("AbilityEffects | apply_effect: not impl in " + HLP.class_string(self))

func text_string(_data: Dictionary) -> String:
	printerr("AbilityEffects | apply_effect: not impl in " + HLP.class_string(self))
	return HLP.class_string(self) + ": not impl text_string()"

func get_targets(_caster, target, _card, _data: Dictionary) -> TargetPreview:
	var tp = TargetPreview.new()
	tp.add_target(target, "")
	return tp

func needs_target() -> Target.Type:
	if _target_type == Target.Type.CASTER:
		return Target.Type.NONE
	return _target_type

func generate(effect: CardEffect, previous_data: GeneratePreviousData) -> bool:
	printerr("GenerateEffect | generate: not impl in " + HLP.class_string(self))
	return false

func can_balance(previous_data: GeneratePreviousData) -> bool:
	printerr("GenerateEffect | can_balance: not impl in " + HLP.class_string(self))
	return false

EffectMove:

@tool
class_name EfffectMove
extends CardEffect

func _set_parent_type():
	_parent_type = Target.Type.TILE_OUTSIDE

func text_string(_data: Dictionary) -> String:
	return "[img=16]res://Art/Conditions/Move.png[/img]"

func apply_effect(_caster: Entity, target: Tile, card: Card, _scale: float = 1):
	var reach = card.card_res.reach
	if _caster.conditions.get_stacks(Conditions.Type.EAGLE_EYE) > 0:
			reach += 1
	var haste_stacks = _caster.conditions.get_stacks(Conditions.Type.HASTE)
	if haste_stacks > 0:
		reach += haste_stacks
	
	if _caster is Unit:
		await _caster.move_to(target, reach)

Is this error in the editor or when you run the game?

1 Like

When running the game

Do you know which typed array is causing the issue? When exactly does the error appear, when the game starts, mid-game? Is there any more to the error message?

1 Like

In the moment the game starts before auto load classes are called.
Yes if I have an Element in the cards: Array[CardResource], that has an member in its own effects: Array[CardEffect], which is not the parent class (CardEffect), but an inheritance of this class.

The Complete Error message is:

E 0:00:00:0304   validate_object: Attempted to assign an object into a TypedArray, that does not inherit from 'GDScript'.
  <C++ Error>    Condition "!other_script->inherits_script(script)" is true. Returning: false
  <C++ Source>   core/variant/container_type_validate.h:140 @ validate_object()

And another one that seems contected:

E 0:00:00:0304   assign: Unable to convert array index 0 from "Object" to "Object".
  <C++ Error>    Method/function failed.
  <C++ Source>   core/variant/array.cpp:238 @ assign()

Do you create the resource in the scene or did you also save it somewhere?

1 Like

It is saved and I don’t create it during runtime only use it.

Can you send the content of the resource here (from the .tres-file)?

Sure its this one:

[gd_resource type="Resource" script_class="Sword" load_steps=9 format=3 uid="uid://bwc3vcpc75ddu"]

[ext_resource type="Script" path="res://Units/Inventory/Items/sword.gd" id="1_wqm7j"]
[ext_resource type="Texture2D" uid="uid://caxpn668u7b6f" path="res://Art/Conditions/None.png" id="2_01o5s"]
[ext_resource type="Resource" uid="uid://c7a6i7fix2xiu" path="res://Units/Cards/General/move.tres" id="2_h7o4w"]
[ext_resource type="Script" path="res://Units/Cards/card_resource.gd" id="5_2qakv"]
[ext_resource type="Script" path="res://Units/Stats/stats_scale.gd" id="5_die0y"]

[sub_resource type="Resource" id="Resource_tlhud"]
script = ExtResource("5_die0y")
type = 3
amount = 5.65385

[sub_resource type="Resource" id="Resource_1hk00"]
script = ExtResource("5_die0y")
type = 0
amount = 3.97442

[sub_resource type="Resource" id="Resource_o35d8"]
script = ExtResource("5_die0y")
type = 4
amount = 0.371724

[resource]
script = ExtResource("1_wqm7j")
level = 0
rarity = 1
cards = Array[ExtResource("5_2qakv")]([ExtResource("2_h7o4w")])
stats = Array[ExtResource("5_die0y")]([SubResource("Resource_tlhud"), SubResource("Resource_1hk00"), SubResource("Resource_o35d8")])
rerole = false
name = "No Name"
price = 10.0
weight = 1.0
texture = ExtResource("2_01o5s")

also the “move.tres”?

1 Like

Sure thanks for the help:

[gd_resource type="Resource" script_class="CardResource" load_steps=5 format=3 uid="uid://c7a6i7fix2xiu"]

[ext_resource type="Script" path="res://Units/Cards/Effects/card_effect.gd" id="1_8deoy"]
[ext_resource type="Script" path="res://Units/Cards/Effects/Direct/effect_move.gd" id="1_ldp8v"]
[ext_resource type="Script" path="res://Units/Cards/card_resource.gd" id="1_p72jm"]

[sub_resource type="Resource" id="Resource_lifvo"]
script = ExtResource("1_ldp8v")
_target_type = 6

[resource]
script = ExtResource("1_p72jm")
name = "Move"
level = 1
rarit = 1
reach = 2
ap_cost = 2
fatigue_cost = 2
effects = Array[ExtResource("1_8deoy")]([SubResource("Resource_lifvo")])
__target = 6
exile = false
charge = 0.0

What is effect_move.gd?
EDIT: nvm

1 Like

The last script in my first reply.

1 Like

Can you try to save the effect_move also in a resource or is it already saved?

Yes I did it, why?

And whats inside the .tres?

1 Like
[gd_resource type="Resource" script_class="EfffectMove" load_steps=2 format=3 uid="uid://btifb2y6326ds"]

[ext_resource type="Script" path="res://Units/Cards/Effects/Direct/effect_move.gd" id="1_4fagn"]

[resource]
script = ExtResource("1_4fagn")
_target_type = 6
1 Like