[Interactions] Pulver now swaps, slots and combines items

This commit is contained in:
Michal Pikulski
2025-09-04 14:24:28 +02:00
parent 0caf0d5209
commit 05a8a5445f
13 changed files with 612 additions and 4 deletions

View File

@@ -276,6 +276,12 @@ public class FollowerController : MonoBehaviour
var pickup = hit.GetComponent<Pickup>();
if (pickup != null)
{
var slotBehavior = pickup.GetComponent<SlotItemBehavior>();
if (slotBehavior != null)
{
// Slot item: do not destroy or swap, just return to player
break;
}
if (justCombined)
{
// Combination: just destroy the pickup, don't spawn anything

View File

@@ -57,5 +57,16 @@ public class GameManager : MonoBehaviour
}
return null;
}
public GameSettings.SlotItemConfig GetSlotItemConfig(PickupItemData slotItem)
{
if (gameSettings == null || gameSettings.slotItemConfigs == null || slotItem == null) return null;
foreach (var config in gameSettings.slotItemConfigs)
{
if (config.slotItem == slotItem)
return config;
}
return null;
}
// Add more accessors as needed
}

View File

@@ -35,8 +35,16 @@ public class GameSettings : ScriptableObject
public PickupItemData result;
}
[Header("Combination Rules")]
[System.Serializable]
public class SlotItemConfig {
public PickupItemData slotItem; // The slot object (SO reference)
public System.Collections.Generic.List<PickupItemData> allowedItems;
public System.Collections.Generic.List<PickupItemData> forbiddenItems;
}
[Header("Item Configuration")]
public System.Collections.Generic.List<CombinationRule> combinationRules;
public System.Collections.Generic.List<SlotItemConfig> slotItemConfigs;
// Singleton pattern
private static GameSettings _instance;

View File

@@ -127,6 +127,15 @@ public class Pickup : MonoBehaviour
playerController.OnArrivedAtTarget += OnPlayerArrived;
playerController.OnMoveToCancelled += OnPlayerMoveCancelled;
Vector3 stopPoint = transform.position + (playerObj.transform.position - transform.position).normalized * playerStopDistance;
playerController.MoveToAndNotify(stopPoint);
float dist = Vector2.Distance(new Vector2(playerObj.transform.position.x, playerObj.transform.position.y), new Vector2(stopPoint.x, stopPoint.y));
if (dist <= 0.2f)
{
// Already within stop range, trigger arrival logic immediately
OnPlayerArrived();
}
else
{
playerController.MoveToAndNotify(stopPoint);
}
}
}

View File

@@ -0,0 +1,96 @@
using UnityEngine;
using UnityEngine.Events;
using System.Collections.Generic;
[RequireComponent(typeof(Interactable))]
[RequireComponent(typeof(Pickup))]
public class SlotItemBehavior : InteractionRequirementBase
{
[Header("Slot State")]
public PickupItemData currentlySlottedItem;
public SpriteRenderer slottedItemRenderer;
public override bool TryInteract(FollowerController follower)
{
var heldItem = follower.currentlyHeldItem;
var pickup = GetComponent<Pickup>();
var slotItem = pickup != null ? pickup.itemData : null;
var config = GameManager.Instance.GetSlotItemConfig(slotItem);
var allowed = config?.allowedItems ?? new List<PickupItemData>();
var forbidden = config?.forbiddenItems ?? new List<PickupItemData>();
// CASE 1: No held item, slot has item -> pick up slotted item
if (heldItem == null && currentlySlottedItem != null)
{
follower.SetHeldItem(currentlySlottedItem);
currentlySlottedItem = null;
UpdateSlottedSprite();
return true;
}
// CASE 2: Held item, slot has item -> swap
if (heldItem != null && currentlySlottedItem != null)
{
var temp = currentlySlottedItem;
currentlySlottedItem = heldItem;
UpdateSlottedSprite();
follower.SetHeldItem(temp);
return true;
}
// CASE 3: Held item, slot empty -> slot the held item
if (heldItem != null && currentlySlottedItem == null)
{
if (forbidden.Contains(heldItem))
{
DebugUIMessage.Show("Can't place that here.");
return false;
}
currentlySlottedItem = heldItem;
UpdateSlottedSprite();
follower.SetHeldItem(null);
if (allowed.Contains(heldItem))
{
OnSuccess?.Invoke();
return true;
}
else
{
DebugUIMessage.Show("I'm not sure this works.");
OnFailure?.Invoke();
return true;
}
}
// CASE 4: No held item, slot empty -> show warning
if (heldItem == null && currentlySlottedItem == null)
{
DebugUIMessage.Show("This requires an item.");
return false;
}
return false;
}
private void UpdateSlottedSprite()
{
if (slottedItemRenderer != null && currentlySlottedItem != null && currentlySlottedItem.mapSprite != null)
{
slottedItemRenderer.sprite = currentlySlottedItem.mapSprite;
// Scale sprite to desired height, preserve aspect ratio, compensate for parent scale
float desiredHeight = GameManager.Instance.HeldIconDisplayHeight;
var sprite = currentlySlottedItem.mapSprite;
float spriteHeight = sprite.bounds.size.y;
float spriteWidth = sprite.bounds.size.x;
Vector3 parentScale = slottedItemRenderer.transform.parent != null
? slottedItemRenderer.transform.parent.localScale
: Vector3.one;
if (spriteHeight > 0f)
{
float uniformScale = desiredHeight / spriteHeight;
float scale = uniformScale / Mathf.Max(parentScale.x, parentScale.y);
slottedItemRenderer.transform.localScale = new Vector3(scale, scale, 1f);
}
}
else if (slottedItemRenderer != null)
{
slottedItemRenderer.sprite = null;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: ec1a2e6e32f746c4990c579e13b79104
timeCreated: 1756985692