2025-09-11 13:00:26 +02:00
|
|
|
|
using Input;
|
|
|
|
|
|
using UnityEngine;
|
2025-09-01 16:14:21 +02:00
|
|
|
|
using System;
|
2025-10-07 10:57:11 +00:00
|
|
|
|
using System.Collections.Generic;
|
2025-09-11 13:00:26 +02:00
|
|
|
|
using UnityEngine.Events;
|
2025-10-07 10:57:11 +00:00
|
|
|
|
using System.Threading.Tasks;
|
2025-10-14 15:53:58 +02:00
|
|
|
|
using Core;
|
2025-11-07 15:38:31 +00:00
|
|
|
|
using Core.Lifecycle;
|
2025-09-01 16:14:21 +02:00
|
|
|
|
|
2025-09-11 13:00:26 +02:00
|
|
|
|
namespace Interactions
|
2025-09-01 16:14:21 +02:00
|
|
|
|
{
|
2025-09-11 13:00:26 +02:00
|
|
|
|
public enum CharacterToInteract
|
2025-09-01 16:14:21 +02:00
|
|
|
|
{
|
2025-10-07 10:57:11 +00:00
|
|
|
|
None,
|
2025-09-11 13:00:26 +02:00
|
|
|
|
Trafalgar,
|
2025-10-07 10:57:11 +00:00
|
|
|
|
Pulver,
|
|
|
|
|
|
Both
|
2025-09-01 16:14:21 +02:00
|
|
|
|
}
|
2025-10-07 10:57:11 +00:00
|
|
|
|
|
2025-09-05 15:03:52 +02:00
|
|
|
|
/// <summary>
|
Refactoring of the interaction system and preliminary integration of save/load functionality across the game. (#44)
### Interactables Architecture Refactor
- Converted composition to inheritance, moved from component-based to class-based interactables. No more requirement for chain of "Interactable -> Item" etc.
- Created `InteractableBase` abstract base class with common functionality that replaces the old component
- Specialized child classes: `Pickup`, `ItemSlot`, `LevelSwitch`, `MinigameSwitch`, `CombinationItem`, `OneClickInteraction` are now children classes
- Light updates to the interactable inspector, moved some things arround, added collapsible inspector sections in the UI for better editor experience
### State Machine Integration
- Custom `AppleMachine` inheritong from Pixelplacement's StateMachine which implements our own interface for saving, easy place for future improvements
- Replaced all previous StateMachines by `AppleMachine`
- Custom `AppleState` extends from default `State`. Added serialization, split state logic into "EnterState", "RestoreState", "ExitState" allowing for separate logic when triggering in-game vs loading game
- Restores directly to target state without triggering transitional logic
- Migration tool converts existing instances
### Prefab Organization
- Saved changes from scenes into prefabs
- Cleaned up duplicated components, confusing prefabs hierarchies
- Created prefab variants where possible
- Consolidated Environment prefabs and moved them out of Placeholders subfolder into main Environment folder
- Organized item prefabs from PrefabsPLACEHOLDER into proper Items folder
- Updated prefab references - All scene references updated to new locations
- Removed placeholder files from Characters, Levels, UI, and Minigames folders
### Scene Updates
- Quarry scene with major updates
- Saved multiple working versions (Quarry, Quarry_Fixed, Quarry_OLD)
- Added proper lighting data
- Updated all interactable components to new architecture
### Minor editor tools
- New tool for testing cards from an editor window (no in-scene object required)
- Updated Interactable Inspector
- New debug option to opt in-and-out of the save/load system
- Tooling for easier migration
Co-authored-by: Michal Pikulski <michal.a.pikulski@gmail.com>
Reviewed-on: https://homelab.tailf7f81b.ts.net/tschesky/AppleHillsProduction/pulls/44
2025-11-03 10:12:51 +00:00
|
|
|
|
/// Base class for interactable objects that can respond to tap input events.
|
|
|
|
|
|
/// Subclasses should override OnCharacterArrived() to implement interaction-specific logic.
|
2025-09-05 15:03:52 +02:00
|
|
|
|
/// </summary>
|
2025-11-07 15:38:31 +00:00
|
|
|
|
public class InteractableBase : ManagedBehaviour, ITouchInputConsumer
|
2025-09-04 13:08:14 +02:00
|
|
|
|
{
|
2025-09-11 13:00:26 +02:00
|
|
|
|
[Header("Interaction Settings")]
|
2025-10-07 10:57:11 +00:00
|
|
|
|
public bool isOneTime;
|
2025-09-11 13:00:26 +02:00
|
|
|
|
public float cooldown = -1f;
|
|
|
|
|
|
public CharacterToInteract characterToInteract = CharacterToInteract.Pulver;
|
|
|
|
|
|
|
|
|
|
|
|
[Header("Interaction Events")]
|
|
|
|
|
|
public UnityEvent<PlayerTouchController, FollowerController> interactionStarted;
|
|
|
|
|
|
public UnityEvent interactionInterrupted;
|
|
|
|
|
|
public UnityEvent characterArrived;
|
|
|
|
|
|
public UnityEvent<bool> interactionComplete;
|
2025-09-29 09:34:15 +00:00
|
|
|
|
|
2025-11-07 15:38:31 +00:00
|
|
|
|
private PlayerTouchController playerRef;
|
|
|
|
|
|
protected FollowerController FollowerController;
|
|
|
|
|
|
private bool isActive = true;
|
2025-09-11 13:00:26 +02:00
|
|
|
|
|
2025-10-07 10:57:11 +00:00
|
|
|
|
// Action component system
|
|
|
|
|
|
private List<InteractionActionBase> _registeredActions = new List<InteractionActionBase>();
|
|
|
|
|
|
|
2025-11-07 15:38:31 +00:00
|
|
|
|
// ManagedBehaviour configuration
|
|
|
|
|
|
public override int ManagedAwakePriority => 100; // Gameplay base classes
|
|
|
|
|
|
|
2025-09-11 13:00:26 +02:00
|
|
|
|
|
2025-10-07 10:57:11 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Register an action component with this interactable
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public void RegisterAction(InteractionActionBase action)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!_registeredActions.Contains(action))
|
|
|
|
|
|
{
|
|
|
|
|
|
_registeredActions.Add(action);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Unregister an action component from this interactable
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public void UnregisterAction(InteractionActionBase action)
|
|
|
|
|
|
{
|
|
|
|
|
|
_registeredActions.Remove(action);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Dispatch an interaction event to all registered actions and await their completion
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private async Task DispatchEventAsync(InteractionEventType eventType)
|
|
|
|
|
|
{
|
|
|
|
|
|
// Collect all tasks from actions that want to respond
|
|
|
|
|
|
List<Task<bool>> tasks = new List<Task<bool>>();
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var action in _registeredActions)
|
|
|
|
|
|
{
|
2025-11-07 15:38:31 +00:00
|
|
|
|
Task<bool> task = action.OnInteractionEvent(eventType, playerRef, FollowerController);
|
2025-10-07 10:57:11 +00:00
|
|
|
|
if (task != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
tasks.Add(task);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (tasks.Count > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
// Wait for all tasks to complete
|
|
|
|
|
|
await Task.WhenAll(tasks);
|
|
|
|
|
|
}
|
|
|
|
|
|
// If no tasks were added, the method will complete immediately (no need for await)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-11 13:00:26 +02:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Handles tap input. Triggers interaction logic.
|
2025-11-07 15:38:31 +00:00
|
|
|
|
/// Can be overridden for fully custom interaction logic.
|
2025-09-11 13:00:26 +02:00
|
|
|
|
/// </summary>
|
2025-11-07 15:38:31 +00:00
|
|
|
|
public virtual void OnTap(Vector2 worldPosition)
|
2025-09-11 13:00:26 +02:00
|
|
|
|
{
|
2025-11-07 15:38:31 +00:00
|
|
|
|
// 1. High-level validation
|
|
|
|
|
|
if (!CanBeClicked())
|
2025-09-11 13:00:26 +02:00
|
|
|
|
{
|
2025-11-07 15:38:31 +00:00
|
|
|
|
return; // Silent failure
|
2025-09-11 13:00:26 +02:00
|
|
|
|
}
|
2025-11-07 15:38:31 +00:00
|
|
|
|
|
2025-10-14 15:53:58 +02:00
|
|
|
|
Logging.Debug($"[Interactable] OnTap at {worldPosition} on {gameObject.name}");
|
2025-10-07 10:57:11 +00:00
|
|
|
|
|
|
|
|
|
|
// Start the interaction process asynchronously
|
2025-11-07 15:38:31 +00:00
|
|
|
|
_ = StartInteractionFlowAsync();
|
2025-09-11 13:00:26 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-07 15:38:31 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Template method that orchestrates the entire interaction flow.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private async Task StartInteractionFlowAsync()
|
2025-09-11 13:00:26 +02:00
|
|
|
|
{
|
2025-11-07 15:38:31 +00:00
|
|
|
|
// 2. Find characters
|
|
|
|
|
|
playerRef = FindFirstObjectByType<PlayerTouchController>();
|
|
|
|
|
|
FollowerController = FindFirstObjectByType<FollowerController>();
|
2025-09-11 13:00:26 +02:00
|
|
|
|
|
2025-11-07 15:38:31 +00:00
|
|
|
|
// 3. Virtual hook: Setup
|
|
|
|
|
|
OnInteractionStarted();
|
2025-09-11 13:00:26 +02:00
|
|
|
|
|
2025-11-07 15:38:31 +00:00
|
|
|
|
// 4. Fire events
|
|
|
|
|
|
interactionStarted?.Invoke(playerRef, FollowerController);
|
2025-10-07 10:57:11 +00:00
|
|
|
|
await DispatchEventAsync(InteractionEventType.InteractionStarted);
|
|
|
|
|
|
|
2025-11-07 15:38:31 +00:00
|
|
|
|
// 5. Orchestrate character movement
|
|
|
|
|
|
await MoveCharactersAsync();
|
|
|
|
|
|
|
|
|
|
|
|
// 6. Virtual hook: Arrival reaction
|
|
|
|
|
|
OnInteractingCharacterArrived();
|
|
|
|
|
|
|
|
|
|
|
|
// 7. Fire arrival events
|
|
|
|
|
|
characterArrived?.Invoke();
|
|
|
|
|
|
await DispatchEventAsync(InteractionEventType.InteractingCharacterArrived);
|
|
|
|
|
|
|
|
|
|
|
|
// 8. Validation (base + child)
|
|
|
|
|
|
var (canProceed, errorMessage) = ValidateInteraction();
|
|
|
|
|
|
if (!canProceed)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!string.IsNullOrEmpty(errorMessage))
|
|
|
|
|
|
{
|
|
|
|
|
|
DebugUIMessage.Show(errorMessage, Color.yellow);
|
|
|
|
|
|
}
|
|
|
|
|
|
FinishInteraction(false);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 9. Virtual main logic: Do the thing!
|
|
|
|
|
|
bool success = DoInteraction();
|
|
|
|
|
|
|
|
|
|
|
|
// 10. Finish up
|
|
|
|
|
|
FinishInteraction(success);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#region Virtual Lifecycle Methods
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// High-level clickability check. Called BEFORE interaction starts.
|
|
|
|
|
|
/// Override to add custom high-level validation (is active, on cooldown, etc.)
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns>True if interaction can start, false for silent rejection</returns>
|
|
|
|
|
|
protected virtual bool CanBeClicked()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!isActive) return false;
|
|
|
|
|
|
// Note: isOneTime and cooldown handled in FinishInteraction
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Called after characters are found but before movement starts.
|
|
|
|
|
|
/// Override to perform setup logic.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
protected virtual void OnInteractionStarted()
|
|
|
|
|
|
{
|
|
|
|
|
|
// Default: do nothing
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Called when the interacting character reaches destination.
|
|
|
|
|
|
/// Override to trigger animations or other arrival reactions.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
protected virtual void OnInteractingCharacterArrived()
|
|
|
|
|
|
{
|
|
|
|
|
|
// Default: do nothing
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Main interaction logic. OVERRIDE THIS in child classes.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns>True if interaction succeeded, false otherwise</returns>
|
|
|
|
|
|
protected virtual bool DoInteraction()
|
|
|
|
|
|
{
|
2025-11-10 13:03:36 +01:00
|
|
|
|
Logging.Warning($"[Interactable] DoInteraction not implemented for {GetType().Name}");
|
2025-11-07 15:38:31 +00:00
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Called after interaction completes. Override to perform cleanup logic.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="success">Whether the interaction succeeded</param>
|
|
|
|
|
|
protected virtual void OnInteractionFinished(bool success)
|
|
|
|
|
|
{
|
|
|
|
|
|
// Default: do nothing
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Child-specific validation. Override to add interaction-specific validation.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns>Tuple of (canProceed, errorMessage)</returns>
|
|
|
|
|
|
protected virtual (bool canProceed, string errorMessage) CanProceedWithInteraction()
|
|
|
|
|
|
{
|
|
|
|
|
|
return (true, null); // Default: always allow
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region Validation
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Combines base and child validation.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private (bool, string) ValidateInteraction()
|
|
|
|
|
|
{
|
|
|
|
|
|
// Base validation (always runs)
|
|
|
|
|
|
var (baseValid, baseError) = ValidateInteractionBase();
|
|
|
|
|
|
if (!baseValid)
|
|
|
|
|
|
return (false, baseError);
|
|
|
|
|
|
|
|
|
|
|
|
// Child validation (optional override)
|
|
|
|
|
|
var (childValid, childError) = CanProceedWithInteraction();
|
|
|
|
|
|
if (!childValid)
|
|
|
|
|
|
return (false, childError);
|
|
|
|
|
|
|
|
|
|
|
|
return (true, null);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Base validation that always runs. Checks puzzle step locks and common prerequisites.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private (bool canProceed, string errorMessage) ValidateInteractionBase()
|
|
|
|
|
|
{
|
|
|
|
|
|
// Check if there's an ObjectiveStepBehaviour attached
|
|
|
|
|
|
var step = GetComponent<PuzzleS.ObjectiveStepBehaviour>();
|
|
|
|
|
|
if (step != null && !step.IsStepUnlocked())
|
|
|
|
|
|
{
|
|
|
|
|
|
// Special case: ItemSlots can still be interacted with when locked (to swap items)
|
|
|
|
|
|
if (!(this is ItemSlot))
|
|
|
|
|
|
{
|
|
|
|
|
|
return (false, "This step is locked!");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return (true, null);
|
2025-10-07 10:57:11 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-07 15:38:31 +00:00
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region Character Movement Orchestration
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Orchestrates character movement based on characterToInteract setting.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private async Task MoveCharactersAsync()
|
2025-10-07 10:57:11 +00:00
|
|
|
|
{
|
2025-11-07 15:38:31 +00:00
|
|
|
|
if (playerRef == null)
|
2025-09-11 13:00:26 +02:00
|
|
|
|
{
|
2025-10-14 15:53:58 +02:00
|
|
|
|
Logging.Debug($"[Interactable] Player character could not be found. Aborting interaction.");
|
2025-09-11 13:00:26 +02:00
|
|
|
|
interactionInterrupted.Invoke();
|
2025-10-07 10:57:11 +00:00
|
|
|
|
await DispatchEventAsync(InteractionEventType.InteractionInterrupted);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-07 15:38:31 +00:00
|
|
|
|
// If characterToInteract is None, skip movement
|
2025-10-07 10:57:11 +00:00
|
|
|
|
if (characterToInteract == CharacterToInteract.None)
|
|
|
|
|
|
{
|
2025-11-07 15:38:31 +00:00
|
|
|
|
return; // Continue to arrival
|
2025-09-11 13:00:26 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-07 15:38:31 +00:00
|
|
|
|
// Move player and optionally follower based on characterToInteract setting
|
|
|
|
|
|
if (characterToInteract == CharacterToInteract.Trafalgar)
|
|
|
|
|
|
{
|
|
|
|
|
|
await MovePlayerAsync();
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (characterToInteract == CharacterToInteract.Pulver || characterToInteract == CharacterToInteract.Both)
|
|
|
|
|
|
{
|
|
|
|
|
|
await MovePlayerAsync(); // Move player to range first
|
|
|
|
|
|
await MoveFollowerAsync(); // Then move follower to interaction point
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Moves the player to the interaction point or custom target.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private async Task MovePlayerAsync()
|
|
|
|
|
|
{
|
|
|
|
|
|
Vector3 stopPoint = transform.position; // Default to interactable position
|
2025-10-07 10:57:11 +00:00
|
|
|
|
bool customTargetFound = false;
|
|
|
|
|
|
|
2025-11-07 15:38:31 +00:00
|
|
|
|
// Check for a CharacterMoveToTarget component for Trafalgar or Both
|
2025-10-07 10:57:11 +00:00
|
|
|
|
CharacterMoveToTarget[] moveTargets = GetComponentsInChildren<CharacterMoveToTarget>();
|
|
|
|
|
|
foreach (var target in moveTargets)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (target.characterType == CharacterToInteract.Trafalgar || target.characterType == CharacterToInteract.Both)
|
|
|
|
|
|
{
|
|
|
|
|
|
stopPoint = target.GetTargetPosition();
|
|
|
|
|
|
customTargetFound = true;
|
2025-11-07 15:38:31 +00:00
|
|
|
|
break;
|
2025-10-07 10:57:11 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-07 15:38:31 +00:00
|
|
|
|
// If no custom target, use default distance
|
2025-10-07 10:57:11 +00:00
|
|
|
|
if (!customTargetFound)
|
|
|
|
|
|
{
|
|
|
|
|
|
Vector3 interactablePos = transform.position;
|
2025-11-07 15:38:31 +00:00
|
|
|
|
Vector3 playerPos = playerRef.transform.position;
|
2025-10-07 10:57:11 +00:00
|
|
|
|
float stopDistance = characterToInteract == CharacterToInteract.Pulver
|
|
|
|
|
|
? GameManager.Instance.PlayerStopDistance
|
|
|
|
|
|
: GameManager.Instance.PlayerStopDistanceDirectInteraction;
|
|
|
|
|
|
Vector3 toPlayer = (playerPos - interactablePos).normalized;
|
|
|
|
|
|
stopPoint = interactablePos + toPlayer * stopDistance;
|
|
|
|
|
|
}
|
2025-09-11 13:00:26 +02:00
|
|
|
|
|
2025-11-07 15:38:31 +00:00
|
|
|
|
// Wait for player to arrive
|
|
|
|
|
|
var tcs = new TaskCompletionSource<bool>();
|
2025-09-11 13:00:26 +02:00
|
|
|
|
|
2025-11-07 15:38:31 +00:00
|
|
|
|
void OnPlayerArrivedLocal()
|
2025-09-11 13:00:26 +02:00
|
|
|
|
{
|
2025-11-07 15:38:31 +00:00
|
|
|
|
if (playerRef != null)
|
2025-10-07 10:57:11 +00:00
|
|
|
|
{
|
2025-11-07 15:38:31 +00:00
|
|
|
|
playerRef.OnArrivedAtTarget -= OnPlayerArrivedLocal;
|
|
|
|
|
|
playerRef.OnMoveToCancelled -= OnPlayerMoveCancelledLocal;
|
2025-10-07 10:57:11 +00:00
|
|
|
|
}
|
2025-11-07 15:38:31 +00:00
|
|
|
|
tcs.TrySetResult(true);
|
2025-09-11 13:00:26 +02:00
|
|
|
|
}
|
2025-11-07 15:38:31 +00:00
|
|
|
|
|
|
|
|
|
|
void OnPlayerMoveCancelledLocal()
|
2025-10-07 10:57:11 +00:00
|
|
|
|
{
|
2025-11-07 15:38:31 +00:00
|
|
|
|
if (playerRef != null)
|
2025-10-07 10:57:11 +00:00
|
|
|
|
{
|
2025-11-07 15:38:31 +00:00
|
|
|
|
playerRef.OnArrivedAtTarget -= OnPlayerArrivedLocal;
|
|
|
|
|
|
playerRef.OnMoveToCancelled -= OnPlayerMoveCancelledLocal;
|
2025-10-07 10:57:11 +00:00
|
|
|
|
}
|
2025-11-07 15:38:31 +00:00
|
|
|
|
_ = HandleInteractionCancelledAsync();
|
|
|
|
|
|
tcs.TrySetResult(false);
|
2025-09-11 13:00:26 +02:00
|
|
|
|
}
|
2025-11-07 15:38:31 +00:00
|
|
|
|
|
|
|
|
|
|
playerRef.OnArrivedAtTarget += OnPlayerArrivedLocal;
|
|
|
|
|
|
playerRef.OnMoveToCancelled += OnPlayerMoveCancelledLocal;
|
|
|
|
|
|
playerRef.MoveToAndNotify(stopPoint);
|
|
|
|
|
|
|
|
|
|
|
|
await tcs.Task;
|
2025-09-11 13:00:26 +02:00
|
|
|
|
}
|
2025-11-07 15:38:31 +00:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Moves the follower to the interaction point or custom target.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private async Task MoveFollowerAsync()
|
2025-09-11 13:00:26 +02:00
|
|
|
|
{
|
2025-11-07 15:38:31 +00:00
|
|
|
|
if (FollowerController == null)
|
2025-09-11 13:00:26 +02:00
|
|
|
|
return;
|
|
|
|
|
|
|
2025-11-07 15:38:31 +00:00
|
|
|
|
// Check for a CharacterMoveToTarget component for Pulver or Both
|
|
|
|
|
|
Vector3 targetPosition = transform.position;
|
|
|
|
|
|
CharacterMoveToTarget[] moveTargets = GetComponentsInChildren<CharacterMoveToTarget>();
|
|
|
|
|
|
foreach (var target in moveTargets)
|
2025-10-07 10:57:11 +00:00
|
|
|
|
{
|
2025-11-07 15:38:31 +00:00
|
|
|
|
if (target.characterType == CharacterToInteract.Pulver || target.characterType == CharacterToInteract.Both)
|
2025-10-07 10:57:11 +00:00
|
|
|
|
{
|
2025-11-07 15:38:31 +00:00
|
|
|
|
targetPosition = target.GetTargetPosition();
|
2025-10-07 10:57:11 +00:00
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-09-11 13:00:26 +02:00
|
|
|
|
|
2025-11-07 15:38:31 +00:00
|
|
|
|
// Wait for follower to arrive
|
|
|
|
|
|
var tcs = new TaskCompletionSource<bool>();
|
2025-10-07 10:57:11 +00:00
|
|
|
|
|
2025-11-07 15:38:31 +00:00
|
|
|
|
void OnFollowerArrivedLocal()
|
2025-09-11 13:00:26 +02:00
|
|
|
|
{
|
2025-11-07 15:38:31 +00:00
|
|
|
|
if (FollowerController != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
FollowerController.OnPickupArrived -= OnFollowerArrivedLocal;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Tell follower to return to player
|
|
|
|
|
|
if (FollowerController != null && playerRef != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
FollowerController.ReturnToPlayer(playerRef.transform);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
tcs.TrySetResult(true);
|
2025-09-11 13:00:26 +02:00
|
|
|
|
}
|
2025-10-07 10:57:11 +00:00
|
|
|
|
|
2025-11-07 15:38:31 +00:00
|
|
|
|
FollowerController.OnPickupArrived += OnFollowerArrivedLocal;
|
|
|
|
|
|
FollowerController.GoToPoint(targetPosition);
|
Refactoring of the interaction system and preliminary integration of save/load functionality across the game. (#44)
### Interactables Architecture Refactor
- Converted composition to inheritance, moved from component-based to class-based interactables. No more requirement for chain of "Interactable -> Item" etc.
- Created `InteractableBase` abstract base class with common functionality that replaces the old component
- Specialized child classes: `Pickup`, `ItemSlot`, `LevelSwitch`, `MinigameSwitch`, `CombinationItem`, `OneClickInteraction` are now children classes
- Light updates to the interactable inspector, moved some things arround, added collapsible inspector sections in the UI for better editor experience
### State Machine Integration
- Custom `AppleMachine` inheritong from Pixelplacement's StateMachine which implements our own interface for saving, easy place for future improvements
- Replaced all previous StateMachines by `AppleMachine`
- Custom `AppleState` extends from default `State`. Added serialization, split state logic into "EnterState", "RestoreState", "ExitState" allowing for separate logic when triggering in-game vs loading game
- Restores directly to target state without triggering transitional logic
- Migration tool converts existing instances
### Prefab Organization
- Saved changes from scenes into prefabs
- Cleaned up duplicated components, confusing prefabs hierarchies
- Created prefab variants where possible
- Consolidated Environment prefabs and moved them out of Placeholders subfolder into main Environment folder
- Organized item prefabs from PrefabsPLACEHOLDER into proper Items folder
- Updated prefab references - All scene references updated to new locations
- Removed placeholder files from Characters, Levels, UI, and Minigames folders
### Scene Updates
- Quarry scene with major updates
- Saved multiple working versions (Quarry, Quarry_Fixed, Quarry_OLD)
- Added proper lighting data
- Updated all interactable components to new architecture
### Minor editor tools
- New tool for testing cards from an editor window (no in-scene object required)
- Updated Interactable Inspector
- New debug option to opt in-and-out of the save/load system
- Tooling for easier migration
Co-authored-by: Michal Pikulski <michal.a.pikulski@gmail.com>
Reviewed-on: https://homelab.tailf7f81b.ts.net/tschesky/AppleHillsProduction/pulls/44
2025-11-03 10:12:51 +00:00
|
|
|
|
|
2025-11-07 15:38:31 +00:00
|
|
|
|
await tcs.Task;
|
2025-09-11 13:00:26 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
Refactoring of the interaction system and preliminary integration of save/load functionality across the game. (#44)
### Interactables Architecture Refactor
- Converted composition to inheritance, moved from component-based to class-based interactables. No more requirement for chain of "Interactable -> Item" etc.
- Created `InteractableBase` abstract base class with common functionality that replaces the old component
- Specialized child classes: `Pickup`, `ItemSlot`, `LevelSwitch`, `MinigameSwitch`, `CombinationItem`, `OneClickInteraction` are now children classes
- Light updates to the interactable inspector, moved some things arround, added collapsible inspector sections in the UI for better editor experience
### State Machine Integration
- Custom `AppleMachine` inheritong from Pixelplacement's StateMachine which implements our own interface for saving, easy place for future improvements
- Replaced all previous StateMachines by `AppleMachine`
- Custom `AppleState` extends from default `State`. Added serialization, split state logic into "EnterState", "RestoreState", "ExitState" allowing for separate logic when triggering in-game vs loading game
- Restores directly to target state without triggering transitional logic
- Migration tool converts existing instances
### Prefab Organization
- Saved changes from scenes into prefabs
- Cleaned up duplicated components, confusing prefabs hierarchies
- Created prefab variants where possible
- Consolidated Environment prefabs and moved them out of Placeholders subfolder into main Environment folder
- Organized item prefabs from PrefabsPLACEHOLDER into proper Items folder
- Updated prefab references - All scene references updated to new locations
- Removed placeholder files from Characters, Levels, UI, and Minigames folders
### Scene Updates
- Quarry scene with major updates
- Saved multiple working versions (Quarry, Quarry_Fixed, Quarry_OLD)
- Added proper lighting data
- Updated all interactable components to new architecture
### Minor editor tools
- New tool for testing cards from an editor window (no in-scene object required)
- Updated Interactable Inspector
- New debug option to opt in-and-out of the save/load system
- Tooling for easier migration
Co-authored-by: Michal Pikulski <michal.a.pikulski@gmail.com>
Reviewed-on: https://homelab.tailf7f81b.ts.net/tschesky/AppleHillsProduction/pulls/44
2025-11-03 10:12:51 +00:00
|
|
|
|
/// <summary>
|
2025-11-07 15:38:31 +00:00
|
|
|
|
/// Handles interaction being cancelled (player stopped moving).
|
Refactoring of the interaction system and preliminary integration of save/load functionality across the game. (#44)
### Interactables Architecture Refactor
- Converted composition to inheritance, moved from component-based to class-based interactables. No more requirement for chain of "Interactable -> Item" etc.
- Created `InteractableBase` abstract base class with common functionality that replaces the old component
- Specialized child classes: `Pickup`, `ItemSlot`, `LevelSwitch`, `MinigameSwitch`, `CombinationItem`, `OneClickInteraction` are now children classes
- Light updates to the interactable inspector, moved some things arround, added collapsible inspector sections in the UI for better editor experience
### State Machine Integration
- Custom `AppleMachine` inheritong from Pixelplacement's StateMachine which implements our own interface for saving, easy place for future improvements
- Replaced all previous StateMachines by `AppleMachine`
- Custom `AppleState` extends from default `State`. Added serialization, split state logic into "EnterState", "RestoreState", "ExitState" allowing for separate logic when triggering in-game vs loading game
- Restores directly to target state without triggering transitional logic
- Migration tool converts existing instances
### Prefab Organization
- Saved changes from scenes into prefabs
- Cleaned up duplicated components, confusing prefabs hierarchies
- Created prefab variants where possible
- Consolidated Environment prefabs and moved them out of Placeholders subfolder into main Environment folder
- Organized item prefabs from PrefabsPLACEHOLDER into proper Items folder
- Updated prefab references - All scene references updated to new locations
- Removed placeholder files from Characters, Levels, UI, and Minigames folders
### Scene Updates
- Quarry scene with major updates
- Saved multiple working versions (Quarry, Quarry_Fixed, Quarry_OLD)
- Added proper lighting data
- Updated all interactable components to new architecture
### Minor editor tools
- New tool for testing cards from an editor window (no in-scene object required)
- Updated Interactable Inspector
- New debug option to opt in-and-out of the save/load system
- Tooling for easier migration
Co-authored-by: Michal Pikulski <michal.a.pikulski@gmail.com>
Reviewed-on: https://homelab.tailf7f81b.ts.net/tschesky/AppleHillsProduction/pulls/44
2025-11-03 10:12:51 +00:00
|
|
|
|
/// </summary>
|
2025-11-07 15:38:31 +00:00
|
|
|
|
private async Task HandleInteractionCancelledAsync()
|
Refactoring of the interaction system and preliminary integration of save/load functionality across the game. (#44)
### Interactables Architecture Refactor
- Converted composition to inheritance, moved from component-based to class-based interactables. No more requirement for chain of "Interactable -> Item" etc.
- Created `InteractableBase` abstract base class with common functionality that replaces the old component
- Specialized child classes: `Pickup`, `ItemSlot`, `LevelSwitch`, `MinigameSwitch`, `CombinationItem`, `OneClickInteraction` are now children classes
- Light updates to the interactable inspector, moved some things arround, added collapsible inspector sections in the UI for better editor experience
### State Machine Integration
- Custom `AppleMachine` inheritong from Pixelplacement's StateMachine which implements our own interface for saving, easy place for future improvements
- Replaced all previous StateMachines by `AppleMachine`
- Custom `AppleState` extends from default `State`. Added serialization, split state logic into "EnterState", "RestoreState", "ExitState" allowing for separate logic when triggering in-game vs loading game
- Restores directly to target state without triggering transitional logic
- Migration tool converts existing instances
### Prefab Organization
- Saved changes from scenes into prefabs
- Cleaned up duplicated components, confusing prefabs hierarchies
- Created prefab variants where possible
- Consolidated Environment prefabs and moved them out of Placeholders subfolder into main Environment folder
- Organized item prefabs from PrefabsPLACEHOLDER into proper Items folder
- Updated prefab references - All scene references updated to new locations
- Removed placeholder files from Characters, Levels, UI, and Minigames folders
### Scene Updates
- Quarry scene with major updates
- Saved multiple working versions (Quarry, Quarry_Fixed, Quarry_OLD)
- Added proper lighting data
- Updated all interactable components to new architecture
### Minor editor tools
- New tool for testing cards from an editor window (no in-scene object required)
- Updated Interactable Inspector
- New debug option to opt in-and-out of the save/load system
- Tooling for easier migration
Co-authored-by: Michal Pikulski <michal.a.pikulski@gmail.com>
Reviewed-on: https://homelab.tailf7f81b.ts.net/tschesky/AppleHillsProduction/pulls/44
2025-11-03 10:12:51 +00:00
|
|
|
|
{
|
2025-11-07 15:38:31 +00:00
|
|
|
|
interactionInterrupted?.Invoke();
|
|
|
|
|
|
await DispatchEventAsync(InteractionEventType.InteractionInterrupted);
|
Refactoring of the interaction system and preliminary integration of save/load functionality across the game. (#44)
### Interactables Architecture Refactor
- Converted composition to inheritance, moved from component-based to class-based interactables. No more requirement for chain of "Interactable -> Item" etc.
- Created `InteractableBase` abstract base class with common functionality that replaces the old component
- Specialized child classes: `Pickup`, `ItemSlot`, `LevelSwitch`, `MinigameSwitch`, `CombinationItem`, `OneClickInteraction` are now children classes
- Light updates to the interactable inspector, moved some things arround, added collapsible inspector sections in the UI for better editor experience
### State Machine Integration
- Custom `AppleMachine` inheritong from Pixelplacement's StateMachine which implements our own interface for saving, easy place for future improvements
- Replaced all previous StateMachines by `AppleMachine`
- Custom `AppleState` extends from default `State`. Added serialization, split state logic into "EnterState", "RestoreState", "ExitState" allowing for separate logic when triggering in-game vs loading game
- Restores directly to target state without triggering transitional logic
- Migration tool converts existing instances
### Prefab Organization
- Saved changes from scenes into prefabs
- Cleaned up duplicated components, confusing prefabs hierarchies
- Created prefab variants where possible
- Consolidated Environment prefabs and moved them out of Placeholders subfolder into main Environment folder
- Organized item prefabs from PrefabsPLACEHOLDER into proper Items folder
- Updated prefab references - All scene references updated to new locations
- Removed placeholder files from Characters, Levels, UI, and Minigames folders
### Scene Updates
- Quarry scene with major updates
- Saved multiple working versions (Quarry, Quarry_Fixed, Quarry_OLD)
- Added proper lighting data
- Updated all interactable components to new architecture
### Minor editor tools
- New tool for testing cards from an editor window (no in-scene object required)
- Updated Interactable Inspector
- New debug option to opt in-and-out of the save/load system
- Tooling for easier migration
Co-authored-by: Michal Pikulski <michal.a.pikulski@gmail.com>
Reviewed-on: https://homelab.tailf7f81b.ts.net/tschesky/AppleHillsProduction/pulls/44
2025-11-03 10:12:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-07 15:38:31 +00:00
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region Finalization
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Finalizes the interaction after DoInteraction completes.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private async void FinishInteraction(bool success)
|
2025-09-11 13:00:26 +02:00
|
|
|
|
{
|
2025-11-07 15:38:31 +00:00
|
|
|
|
// Virtual hook: Cleanup
|
|
|
|
|
|
OnInteractionFinished(success);
|
|
|
|
|
|
|
|
|
|
|
|
// Fire completion events
|
|
|
|
|
|
interactionComplete?.Invoke(success);
|
2025-10-07 10:57:11 +00:00
|
|
|
|
await DispatchEventAsync(InteractionEventType.InteractionComplete);
|
|
|
|
|
|
|
2025-11-07 15:38:31 +00:00
|
|
|
|
// Handle one-time / cooldown
|
2025-09-11 13:00:26 +02:00
|
|
|
|
if (success)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (isOneTime)
|
|
|
|
|
|
{
|
2025-11-07 15:38:31 +00:00
|
|
|
|
isActive = false;
|
2025-09-11 13:00:26 +02:00
|
|
|
|
}
|
|
|
|
|
|
else if (cooldown >= 0f)
|
|
|
|
|
|
{
|
|
|
|
|
|
StartCoroutine(HandleCooldown());
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-11-07 15:38:31 +00:00
|
|
|
|
|
|
|
|
|
|
// Reset state
|
|
|
|
|
|
playerRef = null;
|
|
|
|
|
|
FollowerController = null;
|
2025-09-11 13:00:26 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private System.Collections.IEnumerator HandleCooldown()
|
|
|
|
|
|
{
|
2025-11-07 15:38:31 +00:00
|
|
|
|
isActive = false;
|
2025-09-11 13:00:26 +02:00
|
|
|
|
yield return new WaitForSeconds(cooldown);
|
2025-11-07 15:38:31 +00:00
|
|
|
|
isActive = true;
|
2025-09-11 13:00:26 +02:00
|
|
|
|
}
|
2025-11-07 15:38:31 +00:00
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region Legacy Methods & Compatibility
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// DEPRECATED: Override DoInteraction() instead.
|
|
|
|
|
|
/// This method is kept temporarily for backward compatibility during migration.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
[Obsolete("Override DoInteraction() instead")]
|
|
|
|
|
|
protected virtual void OnCharacterArrived()
|
2025-09-11 13:00:26 +02:00
|
|
|
|
{
|
2025-11-07 15:38:31 +00:00
|
|
|
|
// Default implementation does nothing
|
|
|
|
|
|
// Children should override DoInteraction() in the new pattern
|
2025-09-11 13:00:26 +02:00
|
|
|
|
}
|
2025-11-07 15:38:31 +00:00
|
|
|
|
|
Refactoring of the interaction system and preliminary integration of save/load functionality across the game. (#44)
### Interactables Architecture Refactor
- Converted composition to inheritance, moved from component-based to class-based interactables. No more requirement for chain of "Interactable -> Item" etc.
- Created `InteractableBase` abstract base class with common functionality that replaces the old component
- Specialized child classes: `Pickup`, `ItemSlot`, `LevelSwitch`, `MinigameSwitch`, `CombinationItem`, `OneClickInteraction` are now children classes
- Light updates to the interactable inspector, moved some things arround, added collapsible inspector sections in the UI for better editor experience
### State Machine Integration
- Custom `AppleMachine` inheritong from Pixelplacement's StateMachine which implements our own interface for saving, easy place for future improvements
- Replaced all previous StateMachines by `AppleMachine`
- Custom `AppleState` extends from default `State`. Added serialization, split state logic into "EnterState", "RestoreState", "ExitState" allowing for separate logic when triggering in-game vs loading game
- Restores directly to target state without triggering transitional logic
- Migration tool converts existing instances
### Prefab Organization
- Saved changes from scenes into prefabs
- Cleaned up duplicated components, confusing prefabs hierarchies
- Created prefab variants where possible
- Consolidated Environment prefabs and moved them out of Placeholders subfolder into main Environment folder
- Organized item prefabs from PrefabsPLACEHOLDER into proper Items folder
- Updated prefab references - All scene references updated to new locations
- Removed placeholder files from Characters, Levels, UI, and Minigames folders
### Scene Updates
- Quarry scene with major updates
- Saved multiple working versions (Quarry, Quarry_Fixed, Quarry_OLD)
- Added proper lighting data
- Updated all interactable components to new architecture
### Minor editor tools
- New tool for testing cards from an editor window (no in-scene object required)
- Updated Interactable Inspector
- New debug option to opt in-and-out of the save/load system
- Tooling for easier migration
Co-authored-by: Michal Pikulski <michal.a.pikulski@gmail.com>
Reviewed-on: https://homelab.tailf7f81b.ts.net/tschesky/AppleHillsProduction/pulls/44
2025-11-03 10:12:51 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Call this from subclasses to mark the interaction as complete.
|
2025-11-07 15:38:31 +00:00
|
|
|
|
/// NOTE: In the new pattern, just return true/false from DoInteraction().
|
|
|
|
|
|
/// This is kept for backward compatibility during migration.
|
Refactoring of the interaction system and preliminary integration of save/load functionality across the game. (#44)
### Interactables Architecture Refactor
- Converted composition to inheritance, moved from component-based to class-based interactables. No more requirement for chain of "Interactable -> Item" etc.
- Created `InteractableBase` abstract base class with common functionality that replaces the old component
- Specialized child classes: `Pickup`, `ItemSlot`, `LevelSwitch`, `MinigameSwitch`, `CombinationItem`, `OneClickInteraction` are now children classes
- Light updates to the interactable inspector, moved some things arround, added collapsible inspector sections in the UI for better editor experience
### State Machine Integration
- Custom `AppleMachine` inheritong from Pixelplacement's StateMachine which implements our own interface for saving, easy place for future improvements
- Replaced all previous StateMachines by `AppleMachine`
- Custom `AppleState` extends from default `State`. Added serialization, split state logic into "EnterState", "RestoreState", "ExitState" allowing for separate logic when triggering in-game vs loading game
- Restores directly to target state without triggering transitional logic
- Migration tool converts existing instances
### Prefab Organization
- Saved changes from scenes into prefabs
- Cleaned up duplicated components, confusing prefabs hierarchies
- Created prefab variants where possible
- Consolidated Environment prefabs and moved them out of Placeholders subfolder into main Environment folder
- Organized item prefabs from PrefabsPLACEHOLDER into proper Items folder
- Updated prefab references - All scene references updated to new locations
- Removed placeholder files from Characters, Levels, UI, and Minigames folders
### Scene Updates
- Quarry scene with major updates
- Saved multiple working versions (Quarry, Quarry_Fixed, Quarry_OLD)
- Added proper lighting data
- Updated all interactable components to new architecture
### Minor editor tools
- New tool for testing cards from an editor window (no in-scene object required)
- Updated Interactable Inspector
- New debug option to opt in-and-out of the save/load system
- Tooling for easier migration
Co-authored-by: Michal Pikulski <michal.a.pikulski@gmail.com>
Reviewed-on: https://homelab.tailf7f81b.ts.net/tschesky/AppleHillsProduction/pulls/44
2025-11-03 10:12:51 +00:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
protected void CompleteInteraction(bool success)
|
2025-09-11 13:00:26 +02:00
|
|
|
|
{
|
2025-11-07 15:38:31 +00:00
|
|
|
|
// For now, this manually triggers completion
|
|
|
|
|
|
// After migration, DoInteraction() return value will replace this
|
2025-09-11 13:00:26 +02:00
|
|
|
|
interactionComplete?.Invoke(success);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
Refactoring of the interaction system and preliminary integration of save/load functionality across the game. (#44)
### Interactables Architecture Refactor
- Converted composition to inheritance, moved from component-based to class-based interactables. No more requirement for chain of "Interactable -> Item" etc.
- Created `InteractableBase` abstract base class with common functionality that replaces the old component
- Specialized child classes: `Pickup`, `ItemSlot`, `LevelSwitch`, `MinigameSwitch`, `CombinationItem`, `OneClickInteraction` are now children classes
- Light updates to the interactable inspector, moved some things arround, added collapsible inspector sections in the UI for better editor experience
### State Machine Integration
- Custom `AppleMachine` inheritong from Pixelplacement's StateMachine which implements our own interface for saving, easy place for future improvements
- Replaced all previous StateMachines by `AppleMachine`
- Custom `AppleState` extends from default `State`. Added serialization, split state logic into "EnterState", "RestoreState", "ExitState" allowing for separate logic when triggering in-game vs loading game
- Restores directly to target state without triggering transitional logic
- Migration tool converts existing instances
### Prefab Organization
- Saved changes from scenes into prefabs
- Cleaned up duplicated components, confusing prefabs hierarchies
- Created prefab variants where possible
- Consolidated Environment prefabs and moved them out of Placeholders subfolder into main Environment folder
- Organized item prefabs from PrefabsPLACEHOLDER into proper Items folder
- Updated prefab references - All scene references updated to new locations
- Removed placeholder files from Characters, Levels, UI, and Minigames folders
### Scene Updates
- Quarry scene with major updates
- Saved multiple working versions (Quarry, Quarry_Fixed, Quarry_OLD)
- Added proper lighting data
- Updated all interactable components to new architecture
### Minor editor tools
- New tool for testing cards from an editor window (no in-scene object required)
- Updated Interactable Inspector
- New debug option to opt in-and-out of the save/load system
- Tooling for easier migration
Co-authored-by: Michal Pikulski <michal.a.pikulski@gmail.com>
Reviewed-on: https://homelab.tailf7f81b.ts.net/tschesky/AppleHillsProduction/pulls/44
2025-11-03 10:12:51 +00:00
|
|
|
|
/// <summary>
|
2025-11-07 15:38:31 +00:00
|
|
|
|
/// Legacy method for backward compatibility.
|
Refactoring of the interaction system and preliminary integration of save/load functionality across the game. (#44)
### Interactables Architecture Refactor
- Converted composition to inheritance, moved from component-based to class-based interactables. No more requirement for chain of "Interactable -> Item" etc.
- Created `InteractableBase` abstract base class with common functionality that replaces the old component
- Specialized child classes: `Pickup`, `ItemSlot`, `LevelSwitch`, `MinigameSwitch`, `CombinationItem`, `OneClickInteraction` are now children classes
- Light updates to the interactable inspector, moved some things arround, added collapsible inspector sections in the UI for better editor experience
### State Machine Integration
- Custom `AppleMachine` inheritong from Pixelplacement's StateMachine which implements our own interface for saving, easy place for future improvements
- Replaced all previous StateMachines by `AppleMachine`
- Custom `AppleState` extends from default `State`. Added serialization, split state logic into "EnterState", "RestoreState", "ExitState" allowing for separate logic when triggering in-game vs loading game
- Restores directly to target state without triggering transitional logic
- Migration tool converts existing instances
### Prefab Organization
- Saved changes from scenes into prefabs
- Cleaned up duplicated components, confusing prefabs hierarchies
- Created prefab variants where possible
- Consolidated Environment prefabs and moved them out of Placeholders subfolder into main Environment folder
- Organized item prefabs from PrefabsPLACEHOLDER into proper Items folder
- Updated prefab references - All scene references updated to new locations
- Removed placeholder files from Characters, Levels, UI, and Minigames folders
### Scene Updates
- Quarry scene with major updates
- Saved multiple working versions (Quarry, Quarry_Fixed, Quarry_OLD)
- Added proper lighting data
- Updated all interactable components to new architecture
### Minor editor tools
- New tool for testing cards from an editor window (no in-scene object required)
- Updated Interactable Inspector
- New debug option to opt in-and-out of the save/load system
- Tooling for easier migration
Co-authored-by: Michal Pikulski <michal.a.pikulski@gmail.com>
Reviewed-on: https://homelab.tailf7f81b.ts.net/tschesky/AppleHillsProduction/pulls/44
2025-11-03 10:12:51 +00:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
[Obsolete("Use CompleteInteraction instead")]
|
|
|
|
|
|
public void BroadcastInteractionComplete(bool success)
|
|
|
|
|
|
{
|
|
|
|
|
|
CompleteInteraction(success);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-07 15:38:31 +00:00
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region ITouchInputConsumer Implementation
|
|
|
|
|
|
|
|
|
|
|
|
public void OnHoldStart(Vector2 position)
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new NotImplementedException();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void OnHoldMove(Vector2 position)
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new NotImplementedException();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void OnHoldEnd(Vector2 position)
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new NotImplementedException();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
2025-09-11 13:00:26 +02:00
|
|
|
|
#if UNITY_EDITOR
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Draws gizmos for pickup interaction range in the editor.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
void OnDrawGizmos()
|
|
|
|
|
|
{
|
2025-09-24 13:33:43 +00:00
|
|
|
|
float playerStopDistance = characterToInteract == CharacterToInteract.Trafalgar
|
|
|
|
|
|
? AppleHills.SettingsAccess.GetPlayerStopDistanceDirectInteraction()
|
|
|
|
|
|
: AppleHills.SettingsAccess.GetPlayerStopDistance();
|
2025-09-11 13:00:26 +02:00
|
|
|
|
|
|
|
|
|
|
Gizmos.color = Color.yellow;
|
|
|
|
|
|
Gizmos.DrawWireSphere(transform.position, playerStopDistance);
|
|
|
|
|
|
GameObject playerObj = GameObject.FindGameObjectWithTag("Player");
|
|
|
|
|
|
if (playerObj != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
Vector3 stopPoint = transform.position +
|
|
|
|
|
|
(playerObj.transform.position - transform.position).normalized * playerStopDistance;
|
|
|
|
|
|
Gizmos.color = Color.cyan;
|
|
|
|
|
|
Gizmos.DrawSphere(stopPoint, 0.15f);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
#endif
|
2025-09-09 13:38:03 +02:00
|
|
|
|
}
|
2025-09-01 16:14:21 +02:00
|
|
|
|
}
|