@playerStats.@implicit_new()

Godot Version

4.5.stable

Question

Hey there, been running into a bit of a brick wall so here i am. Working on a roguelike project so wanting to make it so that stats can be changed on the fly as the player progresses and gets items and such. I’ve set up a playerStats class which is currently attached to my character through an empty 3d node. Looks like this:

extends Node3D
class_name playerStats

#init stats
var player:Node3D;
var save_path := "res://player_data.ini";
var config_file := ConfigFile.new();
@export var spd = config_file.get_value("Player", "speed", player.spd);
@export var health = config_file.get_value("Player", "health", player.health);
@export var sprint = config_file.get_value("Player", "health", player.spd * 1.3);
@onready var stats = load("res://player_data.ini");

func new() -> void:
	config_file.set_value("Player", "speed", 4.5);
	config_file.set_value("Player", "health", 50);

#save stats
func save() -> void:
	config_file.set_value("Player", "speed", player.spd);
	config_file.set_value("Player", "health", player.health);
	var error := config_file.save(save_path)
	if error:
		print("An error happened while saving data: ", error);
		return;

#load stats
func load():
	var error := config_file.load(save_path)
	if error:
		print("An error happened while loading data: ", error)
	return

There is related code in my player controller. I’ve truncated it for brevity and do not feel any farther info would help at this time as the variables are just called later on in the function. It was giving issues where it wasnt calling the values but i believe that was due to them not having been set and not part of my current issue.

extends CharacterBody3D

#constants
const sense = 0.0075;
const headBobFreq = 1.8;
const headBobAmp = 0.05;
var headBobDelta = 0.0;
var bullet = load("res://tscn/bullet.tscn");
var instB;
var player = playerStats.new;
#stats
const JUMP_VELOCITY = 4.5

#calling for later
@onready var head = $Head;
@onready var camera = $Head/Camera3D;
@onready var gunAni = $Head/Camera3D/PLHD_Gun/AnimationPlayer;
@onready var barrel = $Head/Camera3D/PLHD_Gun/RayCast3D;

finally, the error being thrown is this

E 0:00:01:360   playerStats.@implicit_new: Invalid access to property or key 'spd' on a base object of type 'Nil'.
  <GDScript Source>basePlayerStats.gd:8 @ playerStats.@implicit_new()
  <Stack Trace> basePlayerStats.gd:8 @ @implicit_new()

what im gathering is that, for some reason, the variables from playerStats are private or something in that realm. so here we are. appreciate any help. thank you all <3

new is a keyword. You shouldn’t be using it to name your function.

2 Likes

woops, musta missed that, changed it back to
_ready() → void:
still giving the same error though

@export var spd = config_file.get_value("Player", "speed", player.spd);

Here’ you’re trying to access player.spd while player is not initialized, i.e. it’s null.

my understanding is the line
var player:Node3D;
is initializing the player var and thus should work for the later calling of player.spd

mind if i ask how its not and what you would suggest? my assumption is i would need to make the player var a section to take in the config_file values?

Nope, that’s a simple variable declaration

2 Likes

With which particular node it initializes it? You never assign anything to it yet expect it to have properties defined in player script.

In addition to the other responses this line is not giving you what you think it is.
Since you do not add the () after new and since you do not give player a type it infers a type.
player becomes a callable that contains the new function. It does not become an instance of the playerStats class.
This is exactly the kind of error that typing your variables can avoid.
var player:playerStats = playerStats.new()