322 lines
11 KiB
GDScript
322 lines
11 KiB
GDScript
extends Node
|
||
|
||
# Scripts
|
||
onready var esc_compiler = $esc_compiler
|
||
onready var logger = load("res://addons/escoria-core/game/core-scripts/log/logging.gd").new()
|
||
onready var main = $main
|
||
onready var esc_runner = $esc_runner
|
||
onready var esc_level_runner = $esc_runner/esc_level_runner
|
||
onready var inputs_manager = $inputs_manager
|
||
onready var utils = load("res://addons/escoria-core/game/core-scripts/utils/utils.gd").new()
|
||
|
||
# INSTANCES
|
||
var main_menu_instance
|
||
|
||
## Dialog player instantiator. This instance is called directly for dialogs.
|
||
var dialog_player
|
||
## Inventory scene
|
||
var inventory
|
||
|
||
# Game variables
|
||
var room_terrain
|
||
|
||
enum GAME_STATE {
|
||
DEFAULT,
|
||
DIALOG,
|
||
WAIT
|
||
}
|
||
onready var current_state = GAME_STATE.DEFAULT
|
||
|
||
onready var game_size = get_viewport().size
|
||
|
||
# These are settings that the player can affect and save/load later
|
||
var settings : Dictionary
|
||
# These are default settings
|
||
var settings_default : Dictionary = {
|
||
# Text language
|
||
"text_lang": ProjectSettings.get_setting("escoria/main/text_lang"),
|
||
# Voice language
|
||
"voice_lang": ProjectSettings.get_setting("escoria/main/voice_lang"),
|
||
# Speech enabled
|
||
"speech_enabled": ProjectSettings.get_setting("escoria/sound/speech_enabled"),
|
||
# Master volume (max is 1.0)
|
||
"master_volume": ProjectSettings.get_setting("escoria/sound/master_volume"),
|
||
# Music volume (max is 1.0)
|
||
"music_volume": ProjectSettings.get_setting("escoria/sound/music_volume"),
|
||
# Sound effects volume (max is 1.0)
|
||
"sfx_volume": ProjectSettings.get_setting("escoria/sound/sfx_volume"),
|
||
# Voice volume (for speech only, max is 1.0)
|
||
"voice_volume": ProjectSettings.get_setting("escoria/sound/speech_volume"),
|
||
# Set fullscreen
|
||
"fullscreen": false,
|
||
# Allow dialog skipping
|
||
"skip_dialog": true,
|
||
# XXX: What is this? `achievements.gd` looks like iOS-only
|
||
"rate_shown": false,
|
||
}
|
||
|
||
|
||
func _init():
|
||
logger = load("res://addons/escoria-core/game/core-scripts/log/logging.gd").new()
|
||
|
||
##################################################################################
|
||
|
||
# Called by Main menu "start new game"
|
||
func new_game():
|
||
var actions = esc_compiler.load_esc_file(ProjectSettings.get_setting("escoria/main/game_start_script"))
|
||
$esc_runner.run_game(actions)
|
||
|
||
escoria.main.scene_transition.fade_in()
|
||
yield(escoria.main.scene_transition, "transition_done")
|
||
|
||
|
||
|
||
"""
|
||
Add object to the environement.
|
||
"""
|
||
func register_object(object : Object):
|
||
var object_id
|
||
if object.get("global_id"):
|
||
object_id = object.global_id
|
||
else:
|
||
object_id = object.name
|
||
|
||
if object is ESCDialogsPlayer:
|
||
dialog_player = object
|
||
|
||
if object is ESCPlayer:
|
||
$esc_runner.register_object(object_id, object, true)
|
||
|
||
if object is Position2D:
|
||
$esc_runner.register_object(object_id, object, true)
|
||
|
||
if object is ESCItem:
|
||
$esc_runner.register_object(object_id, object, true)
|
||
|
||
if object is ESCTerrain:
|
||
room_terrain = object
|
||
|
||
# if object is ESCBackground:
|
||
# $esc_runner.register_object(object_id, object, true)
|
||
|
||
if object is ESCCamera:
|
||
$esc_runner.register_object(object_id, object, true)
|
||
|
||
if object is ESCInventory:
|
||
inventory = object
|
||
|
||
if object is ESCTooltip:
|
||
if main.current_scene:
|
||
main.current_scene.game.tooltip_node = object
|
||
|
||
if object is ESCBackgroundMusic:
|
||
$esc_runner.register_object(object_id, object, true)
|
||
|
||
if object is ESCBackgroundSound:
|
||
$esc_runner.register_object(object_id, object, true)
|
||
|
||
|
||
|
||
|
||
"""
|
||
Generic action function that runs an action on an element of the room (eg player walk)
|
||
action: type of the action ()
|
||
"""
|
||
func do(action : String, params : Array = []) -> void:
|
||
if current_state == GAME_STATE.DEFAULT:
|
||
match action:
|
||
"walk":
|
||
# Reset current action.
|
||
esc_runner.clear_current_action()
|
||
|
||
# Check moving object.
|
||
if !escoria.esc_runner.check_obj(params[0], "escoria.do(walk)"):
|
||
escoria.logger.report_errors("escoria.gd:do()",
|
||
["Walk action requested on inexisting object: " + params[0]])
|
||
return
|
||
|
||
var moving_obj = escoria.esc_runner.get_object(params[0])
|
||
|
||
# Walk to Position2D.
|
||
if params[1] is Vector2:
|
||
var target_position = params[1]
|
||
var is_fast : bool = false
|
||
if params.size() > 2 and params[2] == true:
|
||
is_fast = true
|
||
var walk_context = {"fast": is_fast, "target": target_position}
|
||
moving_obj.walk_to(target_position, walk_context)
|
||
|
||
# Walk to object from its id
|
||
elif params[1] is String:
|
||
if !escoria.esc_runner.check_obj(params[1], "escoria.do(walk)"):
|
||
escoria.logger.report_errors("escoria.gd:do()",
|
||
["Walk action requested TOWARDS inexisting object: " + params[1]])
|
||
return
|
||
|
||
var object = escoria.esc_runner.get_object(params[1])
|
||
if object:
|
||
var target_position : Vector2 = object.interact_position
|
||
var is_fast : bool = false
|
||
if params.size() > 2 and params[2] == true:
|
||
is_fast = true
|
||
var walk_context = {"fast": is_fast, "target_object" : object}
|
||
|
||
moving_obj.walk_to(target_position, walk_context)
|
||
|
||
"item_left_click":
|
||
if params[0] is String:
|
||
escoria.logger.info("escoria.do() : item_left_click on item ", [params[0]])
|
||
var item = $esc_runner.get_object(params[0])
|
||
ev_left_click_on_item(item, params[1])
|
||
|
||
"item_right_click":
|
||
if params[0] is String:
|
||
escoria.logger.info("escoria.do() : item_right_click on item ", [params[0]])
|
||
ev_left_click_on_item($esc_runner.get_object(params[0]), params[1], true)
|
||
|
||
"trigger_in":
|
||
var trigger_id = params[0]
|
||
var object_id = params[1]
|
||
var trigger_in_verb = params[2]
|
||
escoria.logger.info("escoria.do() : trigger_in " + trigger_id + " by " + object_id)
|
||
esc_runner.run_event(esc_runner.objects_events_table[trigger_id][trigger_in_verb])
|
||
|
||
"trigger_out":
|
||
var trigger_id = params[0]
|
||
var object_id = params[1]
|
||
var trigger_out_verb = params[2]
|
||
escoria.logger.info("escoria.do() : trigger_out " + trigger_id + " by " + object_id)
|
||
esc_runner.run_event(esc_runner.objects_events_table[trigger_id][trigger_out_verb])
|
||
|
||
_:
|
||
escoria.logger.report_warnings("escoria.gd:do()",
|
||
["Action received:", action, "with params ", params])
|
||
elif current_state == GAME_STATE.WAIT:
|
||
pass
|
||
|
||
|
||
|
||
# PRIVATE
|
||
func ev_left_click_on_item(obj, event, default_action = false):
|
||
"""
|
||
Event occurring when an object/item is left clicked
|
||
obj : object that was left clicked
|
||
event :
|
||
"""
|
||
if obj is String:
|
||
obj = esc_runner.objects[obj]
|
||
escoria.logger.info(obj.global_id + " left-clicked with event ", [event])
|
||
|
||
var need_combine = false
|
||
# Check if current_action and current_tool are already set
|
||
if esc_runner.current_action:
|
||
if esc_runner.current_tool:
|
||
if esc_runner.current_action in esc_runner.current_tool.combine_if_action_used_among:
|
||
need_combine = true
|
||
else:
|
||
esc_runner.current_tool = obj
|
||
else:
|
||
if default_action:
|
||
if esc_runner.inventory_has(obj.global_id):
|
||
esc_runner.current_action = obj.default_action_inventory
|
||
else:
|
||
esc_runner.current_action = obj.default_action
|
||
elif esc_runner.current_action in obj.combine_if_action_used_among:
|
||
esc_runner.current_tool = obj
|
||
|
||
|
||
# Don't interact after player movement towards object (because object is inactive for example)
|
||
var dont_interact = false
|
||
var destination_position : Vector2 = main.current_scene.player.global_position
|
||
|
||
# Create walk context
|
||
var walk_context = {"fast": event.doubleclick, "target_object" : obj}
|
||
|
||
# If object not in inventory, player walks towards it
|
||
if !esc_runner.inventory_has(obj.global_id):
|
||
var clicked_object_has_interact_position = false
|
||
|
||
if esc_runner.get_interactive(obj.global_id):
|
||
# if obj.interact_positions.default != null:
|
||
# destination_position = obj.interact_positions.default#.global_position
|
||
# clicked_object_has_interact_position = true
|
||
# else:
|
||
# destination_position = obj.position
|
||
if obj.get_interact_position() != null:
|
||
destination_position = obj.get_interact_position()
|
||
clicked_object_has_interact_position = true
|
||
else:
|
||
destination_position = obj.position
|
||
else:
|
||
destination_position = event.position
|
||
dont_interact = true
|
||
|
||
# Use esc_runner for this?
|
||
var is_already_walking = main.current_scene.player.walk_to(destination_position, walk_context)
|
||
|
||
# Wait for the player to arrive before continuing with action.
|
||
var context = yield(main.current_scene.player, "arrived")
|
||
escoria.logger.info("Context arrived: ", [context])
|
||
if context.has("target_object") and walk_context.has("target_object"):
|
||
if (context.target_object.global_id != walk_context.target_object.global_id) \
|
||
or (context.target_object.global_id == walk_context.target_object.global_id and is_already_walking):
|
||
dont_interact = true
|
||
elif context.has("target") and walk_context.has("target"):
|
||
if (context.target.global_id != walk_context.target.global_id) \
|
||
or (context.target.global_id == walk_context.target.global_id and is_already_walking):
|
||
dont_interact = true
|
||
|
||
# If no interaction should happen after player has arrived, leave immediately.
|
||
if dont_interact:
|
||
return
|
||
|
||
var player_global_pos = main.current_scene.player.global_position
|
||
var clicked_position = event.position
|
||
|
||
# If player has arrived at the position he was supposed to reach so he can interact
|
||
if player_global_pos == destination_position:
|
||
# Manage exits
|
||
if obj.is_exit and $esc_runner.current_action == "" or $esc_runner.current_action == "walk":
|
||
var params = [obj]
|
||
$esc_runner.activate("exit_scene", params)
|
||
|
||
else:
|
||
# Manage movements towards object before activating it
|
||
if $esc_runner.current_action == "" or $esc_runner.current_action == "walk":
|
||
if destination_position != clicked_position \
|
||
and !esc_runner.inventory_has(obj.global_id):
|
||
esc_runner.activate("arrived", [obj])
|
||
# Manage action on object
|
||
elif $esc_runner.current_action != "" and $esc_runner.current_action != "walk":
|
||
# If apply_interact, perform combine between items
|
||
if need_combine:
|
||
esc_runner.activate(esc_runner.current_action, [esc_runner.current_tool, obj])
|
||
|
||
else:
|
||
esc_runner.activate(esc_runner.current_action, [obj])
|
||
|
||
# else:
|
||
## escoria.fallback("")
|
||
# pass
|
||
|
||
func _on_settings_loaded(p_settings : Dictionary):
|
||
escoria.logger.info("******* settings loaded", p_settings)
|
||
if p_settings != null:
|
||
settings = p_settings
|
||
else:
|
||
settings = {}
|
||
|
||
for k in settings_default:
|
||
if !(k in settings):
|
||
settings[k] = settings_default[k]
|
||
|
||
# TODO Apply globally
|
||
# AudioServer.set_fx_global_volume_scale(settings.sfx_volume)
|
||
AudioServer.set_bus_volume_db(AudioServer.get_bus_index("Master"), linear2db(settings.master_volume))
|
||
AudioServer.set_bus_volume_db(AudioServer.get_bus_index("SFX"), linear2db(settings.sfx_volume))
|
||
AudioServer.set_bus_volume_db(AudioServer.get_bus_index("Music"), linear2db(settings.music_volume))
|
||
TranslationServer.set_locale(settings.text_lang)
|
||
# music_volume_changed()
|
||
|
||
|