Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Saving and loading system in my visual novel with INKGD #91

Open
st5rb0und opened this issue Jan 11, 2025 Discussed in #90 · 0 comments
Open

Saving and loading system in my visual novel with INKGD #91

st5rb0und opened this issue Jan 11, 2025 Discussed in #90 · 0 comments

Comments

@st5rb0und
Copy link

Discussed in #90

Originally posted by st5rb0und January 11, 2025
I'm having some trouble while implementing the Save/Load system for my game in Godot 4.3 because sometimes when loading (clicking more than once in the LOAD button) some dialogs are skipped. You will get it as soon as you see the video:

save_load_error.mp4

I have a really simple .ink file that i'll be uploading as test.txt and the following code that i have already checked so many times and i tried to keep as simple as posible:

extends Control
# Signals
signal text_finished

# Load scenes
var InkPlayer = load("res://addons/inkgd/ink_player.gd")
var button_scene = load("res://Scenes/dialogue_button.tscn")

# Nodes
@onready var dialog_text = $DialogueBox/MarginContainer/DialogText
@onready var options_box = $OptionsBox
@onready var top_menu = $"../TopMenu"
@onready var auto_button = $AutoButton
@onready var dialogue_box = $DialogueBox

# Control variables
var loaded_text: String = ""
var _ink_player = InkPlayer.new()

func _ready():
	top_menu.save_pressed.connect(_on_save_pressed)
	top_menu.load_pressed.connect(_on_load_pressed)
	
# This method is called for starting the dialog for the first time
func show_dialog(dialog_path : String):
	_ink_player = InkPlayer.new()
	add_child(_ink_player)
	_ink_player.ink_file = load(dialog_path)
	_ink_player.loads_in_background = true
	_ink_player.connect("loaded", Callable(self, "_story_loaded"))
	_ink_player.create_story()
	Globals.show_dialog = true


# Detects if the mouse is over the top menu:
#	* true: if is over
#	* false: if is not over
func is_click_over_top_menu_or_auto() -> bool:
	var mouse_position = get_viewport().get_mouse_position()
	#var top_menu = $"../TopMenu"  # Asegúrate de usar la ruta correcta
	if top_menu and top_menu is Control: 
		var rect = top_menu.get_global_rect()
		var rect2 = auto_button.get_global_rect()
		return rect.has_point(mouse_position) or rect2.has_point(mouse_position)
		
	return false
	
func _process(delta):
	# If user clicks for continue the dialog
	if (Input.is_action_just_pressed("click") and !is_click_over_top_menu_or_auto()) :
		text_finished.emit()
		

func _story_loaded(successfully: bool):
	if !successfully:
		print("Not loaded")
		return
		
	_continue_story()


func _continue_story():
	while _ink_player.can_continue:
		var text = _ink_player.continue_story()
		dialog_text.text = text
	
	if _ink_player.has_choices:
		var choices = _ink_player.current_choices
		# Check if the option is "Cont" to jump to the next dialog
		if choices.size() == 1 and str(choices[0].text) == "Cont":
			await text_finished
			_select_choice(0)
		
		else:
			var button_id = 0
			# Create buttons for each option
			for choice in _ink_player.current_choices:
				var button = button_scene.instantiate()
				# Set an ID for the button 
				button.set_id(button_id)
				button_id += 1
				# Put the text in
				button.text = choice.text
				options_box.add_child(button)
				button.connect("pressed", Callable(self, "_index_choose").bind(button))
	else:
		print("The End")
	

func _index_choose(button):
	if button.get_id() != -1:
		_select_choice(button.get_id())	

func _select_choice(index):
	# Erase options
	for button in options_box.get_children():
		options_box.remove_child(button)
	_ink_player.choose_choice_index(index)
	_continue_story()
	

func _on_save_pressed():
	print("Saving the game ...\n")
	var save_path = "res://Saves/save1.save"
	_ink_player.save_state_to_path(save_path)


func _on_load_pressed():
	print("\nLoading the game...")
	
	var save_path = "res://Saves/save1.save"
	if FileAccess.file_exists(save_path):
		
		# Load state to ink_player
		_ink_player.load_state_from_path(save_path)
		# Erase options
		for child in $OptionsBox.get_children():
			child.free()
			
		# Get the first text to put it on the textbox
		var content = _ink_player.get_state()
		var json = JSON.parse_string(content)
		loaded_text = (json['flows']['DEFAULT_FLOW']['outputStream'][0].replace("^", "").replace("#", "") + json['flows']['DEFAULT_FLOW']['outputStream'][1].replace("^", "").replace("#", ""))
		print(loaded_text)
		
		dialog_text.text = loaded_text
		_continue_story()
	
	else:
		print("File not found: ", save_path)

Please, i need help from any beautiful soul who can give me any clue about whats going on here and how can i fix it... 🙏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant