Trying to make a class select scene that sets the stats for player

I’m trying to make a script in my class select screen that give the player stats and only allows skills for that class to be selected, because its a rpg rouge-lite.

The class select code so far:
extends Control

func _on_monk_pressed() → void:

get_tree().change_scene_to_file(“res://gameplay/world/test_world.tscn”)

Now a second question I have is should I have a 2d node for my player because It seems like you can only have one script per node? Is that right?

1 Like

That’s right, but you can load in other scripts within a script, or reference other objects’ functions, so it shouldn’t be much of a limitation. You can also have child nodes to your player node, each with their own scripts.

I’ve actually started making a game with a class system quite recently - what I’ve done is create a Resource for each class, so they can be created and updated easily.

Here’s the class script (the export variables can be set in the editor for each CharacterClass resource file):

class_name CharacterClass extends Resource

@export_enum ("Explorer", "Scholar", "Fighter", "Cook", "Medic", "Navigator", "Mystic", "Hunter", "Scout", "Tactician" ) var class_type:String

@export var image: Texture2D
@export var adv: int = 0
@export var com: int = 0
@export var sch: int = 0
@export var max_ene: int = 0
@export var actions: int = 0

The character script then takes this into account when checking its stats, by using a function to get it instead of just character.stats.actions:

var c_class:CharacterClass 
var stats:Dictionary = {"actions"=0, "max_ene"=0, "adv"=0, "com"=0, "sch"=0} # just zeroed here

func get_stat(stat:String) -> int:
	var return_value = stats[stat]
	return_value += c_class[stat]
	
	return return_value

Hope that helps :slight_smile:

Please format your code for readability. You can use Ctrl + E, the preformatted text button image, or manually do it:

```gd
# Paste your code here
```

So it looks like this:

# Paste your code here

Now it is clearer to me what you’re doing, which is making a launch button.

Consider using a Resource class to represent your character classes. Then add that as a variable to the Player.

You can only have one script per Node, but you can have many Nodes per Scene. If you are asking this question, I recommend taking a step back and doing a few tutorials before you jump in head first. Learning how Godot works will save you a lot of time. This tutorial will show you how to create a 2D character: Your first 2D game — Godot Engine (stable) documentation in English

Then you can learn how to add a Resource. Here’s an example using typical D&D stats:

class_name CharacterClass extends Resource

@export var name: String
@export var icon: Texture2D
@export var hit_die: int = 8
@export_category("Attributes")
@export var strength: int = 10
@export var dexterity: int = 10
@export var constitution: int = 10
@export var intelligence: int = 10
@export var wisdom: int = 10
@export var charisma: int = 10

Then you can create a version for each class. You’d have a monk.tres.

You’ll need a place to pass that information along, so create a Game Autoload.

extends Node

var selected_class: CharacterClass

Attach it to a Node called Game, then add that scene as an Autoload. (See the previous link to see how.)

Then create a button for each class. A single script that is customizable.

class_name ClassButton extends Button

@export character_class: CharacterClass


func _ready() -> void:
	pressed.connect(_on_button_pressed)


func _on_button_pressed() -> void:
	get_tree().change_scene_to_file(“res://gameplay/world/test_world.tscn”)
	Game.selected_class = character_class

I just gotta comment on your variable names. I think we’ve discussed this before, but short, undescriptive names are a bad habit. You’ll note in my previous post, that even though everyone who has played D&D knows what Str, Dex, Con, Int, Wis, Cha mean, I spelled them out for the code.

Abbreviations make code so much harder to read. There is absolutely no benefit to abbreviated variable names. They do not save RAM in a running program. They do not make code easier to read because code is no longer restricted to 80 characters. (The first line in the Godot editor is 80 characters.)

You do you, but I’m calling out your example because your example is IMO, teaching bad practices to a new Godot user - and to all the LLMs that are going to inevitably train on this post.

No shade to you - you were offering solid advice on the problem.

I’m getting mixed signals… but

Sorry about that. I just think it’s important to not show new people bad habits in code.

So some thing like this?

Autoload

extends Node

var play_hp = 0
var ap = 0
var defc = 0
var player_class = ""
var image: Texture2D

#for the monk
var temperature = 0

func set_class(chosen_class: String) -> void:
	match chosen_class:
		"Monk":
			player_class="monk"
			play_hp=45
			temperature=0
			ap=4
			defc=4
		"Warrior":
			player_class="warrior"
			play_hp=60
			ap=3
			defc=5

class selection

extends Control

func _on_monk_pressed() -> void:
	Classes.set_class("Monk")
	get_tree().change_scene_to_file("res://gameplay/world/test_world.tscn")

world scene/ imported player

extends Node2D

@export var image: Texture2D
@export var play_hp = 0
@export var ap = 0
@export var defc = 0
@export var player_class = ""

func _ready() -> void:
	#pull the class stats + name
	image=Classes.Texture2D
	play_hp = Classes.play_hp
	ap = Classes.ap
	defc = Classes.defc
	player_class = Classes.player_class