MODIFIED escoria.gdgit add . Action manager extended to apply needed changes for monkey UI

This commit is contained in:
2023-03-07 00:29:46 +01:00
parent a19632eb27
commit 50ad55ce14
4 changed files with 373 additions and 2 deletions

View File

@@ -18,7 +18,8 @@ onready var main = $main
func _init():
escoria.inventory_manager = ESCInventoryManager.new()
escoria.action_manager = ESCActionManager.new()
# MODIFIED FOR RETURN TO MONKEY UI
escoria.action_manager = ESCActionManagerMonkey.new()
escoria.event_manager = ESCEventManager.new()
escoria.globals_manager = ESCGlobalsManager.new()
add_child(escoria.event_manager)

View File

@@ -0,0 +1,364 @@
# Manages currently carried out actions
# MODIFIED FOR RETURN TO MONKEY UI
extends ESCActionManager
class_name ESCActionManagerMonkey
# Set the current action verb
#
# ## Parameters
# - action: The action verb to set
func set_current_action(action: String):
# MODIFIED FOR RETURN TO MONKEY UI
if (action != current_action) && (action_state != ACTION_INPUT_STATE.AWAITING_TARGET_ITEM):
clear_current_tool()
current_action = action
if action_state == ACTION_INPUT_STATE.AWAITING_VERB_OR_ITEM:
set_action_input_state(ACTION_INPUT_STATE.AWAITING_ITEM)
elif action_state == ACTION_INPUT_STATE.AWAITING_VERB:
set_action_input_state(ACTION_INPUT_STATE.AWAITING_VERB_CONFIRM)
emit_signal("action_changed")
# Checks if the specified action is valid and returns the associated event;
# otherwise, we see if there's a "fallback" event and use that if necessary and,
# if not, we return no event as there's nothing to do.
#
# #### Parameters
#
# - action: Action to execute (defined in attached ESC file and in
# action verbs UI) eg: arrived, use, look, pickup...
# - target: Target ESC object
# - combine_with: ESC object to combine with
#
# *Returns* the appropriate ESCEvent to queue/run, or null if none can be found
# or there's a reason not to run an event.
func _get_event_to_queue(
action: String,
target: ESCObject,
combine_with: ESCObject = null
) -> ESCEvent:
escoria.logger.info(
self,
"Checking if action '%s' on '%s' is valid..." % [action, target]
)
var event_to_return: ESCEvent = null
# If we're using an action which item requires to combine
if target.node is ESCItem \
and (action in target.node.combine_when_selected_action_is_in
# MODIFIED FOR RETURN TO MONKEY UI
or (combine_with && action in combine_with.node.combine_when_selected_action_is_in)):
# Check if object must be in inventory to be used
if target.node.use_from_inventory_only:
if escoria.inventory_manager.inventory_has(target.global_id):
# Player has item in inventory, we check the element to use on
if combine_with:
var do_combine = true
if combine_with.node is ESCItem \
and combine_with.node.use_from_inventory_only\
and not escoria.inventory_manager.inventory_has(
combine_with.global_id
):
do_combine = false
if do_combine:
var target_event = "%s %s" % [
action,
combine_with.global_id
]
var combine_with_event = "%s %s" % [
action,
target.global_id
]
if target.events.has(target_event):
event_to_return = target.events[target_event]
elif combine_with.events.has(combine_with_event)\
and not combine_with.node.combine_is_one_way:
event_to_return = combine_with.events[combine_with_event]
else:
# Check to see if there isn't a "fallback" action to
# run before we declare this a failure.
if escoria.action_default_script \
and escoria.action_default_script.events.has(action):
event_to_return = escoria.action_default_script.events[action]
else:
var errors = [
"Attempted to execute action %s between item %s and item %s" % [
action,
target.global_id,
combine_with.global_id
]
]
if combine_with.node.combine_is_one_way:
errors.append(
("Reason: %s's item interaction " + \
"is one-way.") % combine_with.global_id
)
escoria.logger.warn(
self,
"Invalid action: " + str(errors)
)
else:
escoria.logger.warn(
self,
"Invalid action on item: " +
(
"Trying to combine object %s with %s, "+
"but %s is not in inventory."
) % [
target.global_id,
combine_with.global_id,
combine_with.global_id
]
)
else:
escoria.logger.warn(
self,
"Invalid action on item: " +
"Trying to run action %s on object %s, " %
[
action,
target.node.global_id
]
+ "but item must be in inventory."
)
else:
if target.events.has(action):
event_to_return = target.events[action]
elif escoria.action_default_script \
and escoria.action_default_script.events.has(action):
# If there's a "fallback" action to run, return it
event_to_return = escoria.action_default_script.events[action]
else:
escoria.logger.warn(
self,
"Invalid action: " +
"Event for action %s on object %s not found." % [
action,
target.global_id
]
)
return event_to_return
# Event handler when an object/item was clicked
#
# #### Parameters
#
# - obj: Object that was left clicked
# - event: Input event that was received
# - default_action: if true, run the inventory default action
func perform_inputevent_on_object(
obj: ESCObject,
event: InputEvent,
default_action: bool = false
):
"""
This algorithm:
- validates the requested action
- grabs the corresponding event for the action, if available
- makes the player move to the clicked object location, if needed
(if it is located in the room for example) and wait for reaching.
- when reached, performs an action depending on current defined action
* no current action defined: do nothing else
* current action defined:
* item requires no combination: perform the current action
on the item
* item requires combination: check the status of the combination
A combination requires 3 elements to fulfill:
1/ a verb action
2/ a first "tool" (item to use)
3/ a second "tool" (item to use ON)
Whatever the user inputs to fulfill the combination (this is
determined by gamedev in his game.gd script)
- combination not fulfilled: no not perform until fulfilled
- combination fulfilled: perform the combination.
* else do nothing, except if default_action is requested.
In this case, perform the default_action on the item.
"""
escoria.logger.info(
self,
"%s to perform event %s." % [obj.global_id, event]
)
# Don't interact after player movement towards object
# (because object is inactive for example)
var dont_interact = false
# We need to have the new action input state BEFORE initiating the player
# move so we determine now if the object clicked will require a combination
# depending on the used action verb.
var tool_just_set = _set_tool_and_action(obj, default_action)
# MODIFIED FOR RETURN TO MONKEY UI
var need_combine = _check_item_needs_combine_obj(obj)
# If the current tool was not set, this is our first item, make it the tool
if not current_tool or (current_tool and not need_combine):
current_tool = obj
# Else, if we have a tool and combination required, this is our second item,
# make it the target.
elif need_combine and not tool_just_set:
current_target = obj
# Update the action input state
if action_state == ACTION_INPUT_STATE.AWAITING_TARGET_ITEM and current_target:
set_action_input_state(ACTION_INPUT_STATE.COMPLETED)
elif action_state == ACTION_INPUT_STATE.AWAITING_ITEM and \
not need_combine:
set_action_input_state(ACTION_INPUT_STATE.COMPLETED)
elif action_state == ACTION_INPUT_STATE.AWAITING_ITEM and need_combine and not tool_just_set:
set_action_input_state(ACTION_INPUT_STATE.AWAITING_TARGET_ITEM)
var event_to_queue: ESCEvent = null
# Manage exits
if obj.node.is_exit and current_action in ["", ACTION_WALK]:
event_to_queue = _get_event_to_queue(ACTION_EXIT_SCENE, obj)
else:
# Manage movements towards object before activating it
if current_action in ["", ACTION_WALK] and \
not escoria.inventory_manager.inventory_has(obj.global_id):
event_to_queue = _get_event_to_queue(ACTION_ARRIVED, obj)
# Manage action on object
elif not current_action in ["", ACTION_WALK]:
if need_combine and current_target:
event_to_queue = _get_event_to_queue(
current_action,
current_tool,
current_target
)
else:
# Check if object must be in inventory to be used and update
# action state if necessary
if obj.node.use_from_inventory_only and \
escoria.inventory_manager.inventory_has(obj.global_id) and \
need_combine:
# We're missing a target here for our tool to be used on
current_tool = obj
set_action_input_state(
ACTION_INPUT_STATE.AWAITING_TARGET_ITEM
)
# We need to wait for that target
return
else:
event_to_queue = _get_event_to_queue(
current_action,
obj
)
# Get out of here if there's a specified action but an event couldn't be found.
# Note that `event_to_queue` may still be null, but we do need to start the
# player walking towards the destination.
if current_action and not event_to_queue:
clear_current_action()
emit_signal("action_finished")
return
var event_flags = event_to_queue.flags if event_to_queue else 0
if escoria.main.current_scene.player:
var destination_position: Vector2 = escoria.main.current_scene.player \
.global_position
# If clicked object not in inventory, player walks towards it
if not obj.node is ESCPlayer and \
not escoria.inventory_manager.inventory_has(obj.global_id) and \
not event_flags & ESCEvent.FLAG_TK:
var context = _walk_towards_object(
obj,
event.position,
event.doubleclick
)
if context is GDScriptFunctionState:
context = yield(context, "completed")
# In case of an interrupted walk, we don't want to proceed.
if context == null:
return
destination_position = context.target_position
dont_interact = context.dont_interact_on_arrival
var player_global_pos = escoria.main.current_scene.player.global_position
var clicked_position = event.position
# Using this instead of is_equal_approx due to
# https://github.com/godotengine/godot/issues/65257
if (player_global_pos - destination_position).length() > 1:
dont_interact = true
escoria.logger.info(
self,
"Player could not reach destination coordinates %s. " % str(destination_position) \
+ "Any requested action for %s will not fire." % obj.global_id
)
if escoria.event_manager.EVENT_CANT_REACH in obj.events:
escoria.event_manager.queue_event(obj.events[escoria.event_manager.EVENT_CANT_REACH])
else:
escoria.logger.info(
self,
"%s event not found for object %s so nothing to do." % \
[escoria.event_manager.EVENT_CANT_REACH, obj.global_id]
)
# If no interaction should happen after player has arrived, leave
# immediately.
if not dont_interact and event_to_queue:
_run_event(event_to_queue)
# Prepare the "obj" object for current_action: if required, set the object as
# current tool.
#
# #### Parameters
#
# - obj: the ESCObject to prepare
# - default_action: if true, the default action set on the item is used
#
# *Returns* True if the tool was set in this function
func _set_tool_and_action(obj: ESCObject, default_action: bool):
var tool_just_set: bool = false
# Check if current_action and current_tool are already set
if current_action and current_tool:
# MODIFIED FOR RETURN TO MONKEY UI
if (not current_action in escoria.action_manager\
.current_tool.node.combine_when_selected_action_is_in and not current_action in obj.node.combine_when_selected_action_is_in):
current_tool = obj
tool_just_set = true
elif default_action:
if escoria.inventory_manager.inventory_has(obj.global_id):
current_action = obj.node.default_action_inventory
else:
current_action = obj.node.default_action
elif current_action in obj.node.combine_when_selected_action_is_in:
current_tool = obj
tool_just_set = true
return tool_just_set
# Checks if object requires a combination with another, according to
# currently selected action verb (or check with default action of the item).
#
# *Returns* True if current action on "obj" requires a combination
# MODIFIED FOR RETURN TO MONKEY UI
func _check_item_needs_combine_obj(obj: ESCObject) -> bool:
return current_action \
and current_tool \
and (current_action in current_tool.node.combine_when_selected_action_is_in
# MODIFIED FOR RETURN TO MONKEY UI
or current_action in obj.node.combine_when_selected_action_is_in)

View File

@@ -65,7 +65,7 @@ global_id = "l_exit"
esc_script = "res://gymkhana/rooms/trasera_cocina/esc/entrada_cocina.esc"
is_exit = true
tooltip_name = "Esto es una puerta y tiene una descripcion mu larga"
combine_when_selected_action_is_in = [ ]
combine_when_selected_action_is_in = [ "action4" ]
dialog_color = Color( 1, 1, 1, 1 )
action1_text = "Esto es una puerta y tiene una descripcion mu larga"
action2_text = "Entrar! con descricion..."

View File

@@ -149,6 +149,11 @@ _global_script_classes=[ {
"language": "GDScript",
"path": "res://addons/escoria-core/game/core-scripts/esc/esc_action_manager.gd"
}, {
"base": "ESCActionManager",
"class": "ESCActionManagerMonkey",
"language": "GDScript",
"path": "res://gymkhana/addons/escoria-ui-return-monkey-island/esc/esc_action_manager_monkey.gd"
}, {
"base": "Resource",
"class": "ESCAnimationName",
"language": "GDScript",
@@ -733,6 +738,7 @@ _global_script_class_icons={
"DialogSayFinish": "",
"DialogVisible": "",
"ESCActionManager": "",
"ESCActionManagerMonkey": "",
"ESCAnimationName": "",
"ESCAnimationPlayer": "",
"ESCAnimationResource": "",