Compare commits

...

2 Commits

7 changed files with 278 additions and 35 deletions

View File

@@ -39,10 +39,7 @@ MonoBehaviour:
combinationRules: combinationRules:
- itemA: {fileID: 11400000, guid: 33e7ca06b22108d4e802486e08bcdfd1, type: 2} - itemA: {fileID: 11400000, guid: 33e7ca06b22108d4e802486e08bcdfd1, type: 2}
itemB: {fileID: 11400000, guid: 8b2616beb14825a46b9b1ed85ad3cb25, type: 2} itemB: {fileID: 11400000, guid: 8b2616beb14825a46b9b1ed85ad3cb25, type: 2}
result: {fileID: 11400000, guid: ecae2d83a5ab2a047a2733ebff607380, type: 2} resultPrefab: {fileID: 1610562450228973293, guid: 58654125374567147839eb382fcde422, type: 3}
- itemA: {fileID: 11400000, guid: 983414276ae3f004c854e9c450f27f88, type: 2}
itemB: {fileID: 11400000, guid: 0c6986639ca176a419c92f5a327d95ce, type: 2}
result: {fileID: 11400000, guid: 6934dcb56c610c44da228f7f24ca13c9, type: 2}
slotItemConfigs: slotItemConfigs:
- slotItem: {fileID: 11400000, guid: e0fad48a84a6b6346ac17c84bc512500, type: 2} - slotItem: {fileID: 11400000, guid: e0fad48a84a6b6346ac17c84bc512500, type: 2}
allowedItems: allowedItems:

View File

@@ -0,0 +1,107 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1001 &8143515500611931992
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
serializedVersion: 3
m_TransformParent: {fileID: 0}
m_Modifications:
- target: {fileID: 592045584872845087, guid: bf4b9d7045397f946b2125b1ad4a3fbd, type: 3}
propertyPath: itemData
value:
objectReference: {fileID: 11400000, guid: ecae2d83a5ab2a047a2733ebff607380, type: 2}
- target: {fileID: 1730119453103664125, guid: bf4b9d7045397f946b2125b1ad4a3fbd, type: 3}
propertyPath: m_LocalPosition.x
value: -8.48395
objectReference: {fileID: 0}
- target: {fileID: 1730119453103664125, guid: bf4b9d7045397f946b2125b1ad4a3fbd, type: 3}
propertyPath: m_LocalPosition.y
value: -1.95773
objectReference: {fileID: 0}
- target: {fileID: 1730119453103664125, guid: bf4b9d7045397f946b2125b1ad4a3fbd, type: 3}
propertyPath: m_LocalPosition.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1730119453103664125, guid: bf4b9d7045397f946b2125b1ad4a3fbd, type: 3}
propertyPath: m_LocalRotation.w
value: 1
objectReference: {fileID: 0}
- target: {fileID: 1730119453103664125, guid: bf4b9d7045397f946b2125b1ad4a3fbd, type: 3}
propertyPath: m_LocalRotation.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1730119453103664125, guid: bf4b9d7045397f946b2125b1ad4a3fbd, type: 3}
propertyPath: m_LocalRotation.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1730119453103664125, guid: bf4b9d7045397f946b2125b1ad4a3fbd, type: 3}
propertyPath: m_LocalRotation.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1730119453103664125, guid: bf4b9d7045397f946b2125b1ad4a3fbd, type: 3}
propertyPath: m_LocalEulerAnglesHint.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1730119453103664125, guid: bf4b9d7045397f946b2125b1ad4a3fbd, type: 3}
propertyPath: m_LocalEulerAnglesHint.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1730119453103664125, guid: bf4b9d7045397f946b2125b1ad4a3fbd, type: 3}
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3070149615425714466, guid: bf4b9d7045397f946b2125b1ad4a3fbd, type: 3}
propertyPath: m_SpriteTilingProperty.pivot.x
value: 0.5
objectReference: {fileID: 0}
- target: {fileID: 3070149615425714466, guid: bf4b9d7045397f946b2125b1ad4a3fbd, type: 3}
propertyPath: m_SpriteTilingProperty.pivot.y
value: 0.5
objectReference: {fileID: 0}
- target: {fileID: 3070149615425714466, guid: bf4b9d7045397f946b2125b1ad4a3fbd, type: 3}
propertyPath: m_SpriteTilingProperty.newSize.x
value: 0.69
objectReference: {fileID: 0}
- target: {fileID: 3070149615425714466, guid: bf4b9d7045397f946b2125b1ad4a3fbd, type: 3}
propertyPath: m_SpriteTilingProperty.newSize.y
value: 0.45
objectReference: {fileID: 0}
- target: {fileID: 3070149615425714466, guid: bf4b9d7045397f946b2125b1ad4a3fbd, type: 3}
propertyPath: m_SpriteTilingProperty.oldSize.x
value: 0.69
objectReference: {fileID: 0}
- target: {fileID: 3070149615425714466, guid: bf4b9d7045397f946b2125b1ad4a3fbd, type: 3}
propertyPath: m_SpriteTilingProperty.oldSize.y
value: 0.45
objectReference: {fileID: 0}
- target: {fileID: 3070149615425714466, guid: bf4b9d7045397f946b2125b1ad4a3fbd, type: 3}
propertyPath: m_SpriteTilingProperty.adaptiveTilingThreshold
value: 0.5
objectReference: {fileID: 0}
- target: {fileID: 7447346505753002421, guid: bf4b9d7045397f946b2125b1ad4a3fbd, type: 3}
propertyPath: m_Name
value: Meat
objectReference: {fileID: 0}
- target: {fileID: 7494677664706785084, guid: bf4b9d7045397f946b2125b1ad4a3fbd, type: 3}
propertyPath: m_Size.x
value: 0.69
objectReference: {fileID: 0}
- target: {fileID: 7494677664706785084, guid: bf4b9d7045397f946b2125b1ad4a3fbd, type: 3}
propertyPath: m_Size.y
value: 0.45
objectReference: {fileID: 0}
- target: {fileID: 7494677664706785084, guid: bf4b9d7045397f946b2125b1ad4a3fbd, type: 3}
propertyPath: m_Sprite
value:
objectReference: {fileID: 6282751622250221668, guid: 204325ac88be74d4d882a078c64cf5e1, type: 3}
- target: {fileID: 7494677664706785084, guid: bf4b9d7045397f946b2125b1ad4a3fbd, type: 3}
propertyPath: m_WasSpriteAssigned
value: 1
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
m_AddedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: bf4b9d7045397f946b2125b1ad4a3fbd, type: 3}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 58654125374567147839eb382fcde422
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -56,7 +56,7 @@ public class GameSettings : ScriptableObject
public class CombinationRule { public class CombinationRule {
public PickupItemData itemA; public PickupItemData itemA;
public PickupItemData itemB; public PickupItemData itemB;
public PickupItemData result; public GameObject resultPrefab; // The prefab to spawn as the result
} }
[System.Serializable] [System.Serializable]

View File

@@ -28,19 +28,35 @@ public class CombineWithBehavior : InteractionRequirementBase
return false; return false;
} }
var rule = GameManager.Instance.GetCombinationRule(heldItem, pickup.itemData); var rule = GameManager.Instance.GetCombinationRule(heldItem, pickup.itemData);
if (rule != null && rule.result != null) if (rule != null && rule.resultPrefab != null)
{ {
// Remove both items and add result to follower's inventory // Instantiate the result prefab at the pickup's position
follower.SetHeldItem(rule.result); var resultObj = GameObject.Instantiate(rule.resultPrefab, pickup.transform.position, Quaternion.identity);
var resultPickup = resultObj.GetComponent<Pickup>();
if (resultPickup != null)
{
// Hide and parent to follower
resultObj.SetActive(false);
resultObj.transform.SetParent(follower.transform);
// Set held item and icon from the spawned prefab
follower.SetHeldItem(resultPickup.itemData, resultPickup.iconRenderer);
// Cache the spawned object as the held item
follower.CacheHeldPickupObject(resultObj);
follower.justCombined = true; follower.justCombined = true;
OnSuccess?.Invoke(); OnSuccess?.Invoke();
return true; return true;
} }
else else
{ {
string heldName = heldItem.itemName ?? "an item"; Debug.LogWarning("Result prefab does not have a Pickup component.");
string targetName = pickup.itemData.itemName ?? "target item"; GameObject.Destroy(resultObj);
// DebugUIMessage.Show($"Cannot combine {heldName} with {targetName}."); OnFailure?.Invoke();
return false;
}
}
else
{
// DebugUIMessage.Show($"Cannot combine {heldItem.itemName ?? \"an item\"} with {pickup.itemData.itemName ?? \"target item\"}.");
OnFailure?.Invoke(); OnFailure?.Invoke();
return true; return true;
} }

View File

@@ -19,6 +19,45 @@ public class SlotItemBehavior : InteractionRequirementBase
/// </summary> /// </summary>
public SpriteRenderer slottedItemRenderer; public SpriteRenderer slottedItemRenderer;
private GameObject _cachedSlottedObject = null;
// Helper for slotting an object, with option to skip destruction (for swap)
private void SetSlottedObject(GameObject obj)
{
_cachedSlottedObject = obj;
if (_cachedSlottedObject != null)
{
_cachedSlottedObject.SetActive(false);
}
}
private void RemoveSlottedObject()
{
if (_cachedSlottedObject != null)
{
Destroy(_cachedSlottedObject);
_cachedSlottedObject = null;
}
}
private void CacheSlottedObject(GameObject obj)
{
// Only destroy if not swapping
RemoveSlottedObject();
SetSlottedObject(obj);
}
private void RestoreSlottedObject(Vector3 position)
{
if (_cachedSlottedObject != null)
{
_cachedSlottedObject.transform.position = position;
_cachedSlottedObject.transform.SetParent(null);
_cachedSlottedObject.SetActive(true);
_cachedSlottedObject = null;
}
}
/// <summary> /// <summary>
/// Attempts to interact with the slot, handling slotting, swapping, or picking up items. /// Attempts to interact with the slot, handling slotting, swapping, or picking up items.
/// </summary> /// </summary>
@@ -27,6 +66,7 @@ public class SlotItemBehavior : InteractionRequirementBase
public override bool TryInteract(FollowerController follower) public override bool TryInteract(FollowerController follower)
{ {
var heldItem = follower.CurrentlyHeldItem; var heldItem = follower.CurrentlyHeldItem;
var heldObj = follower.GetHeldPickupObject();
var pickup = GetComponent<Pickup>(); var pickup = GetComponent<Pickup>();
var slotItem = pickup != null ? pickup.itemData : null; var slotItem = pickup != null ? pickup.itemData : null;
var config = GameManager.Instance.GetSlotItemConfig(slotItem); var config = GameManager.Instance.GetSlotItemConfig(slotItem);
@@ -34,33 +74,44 @@ public class SlotItemBehavior : InteractionRequirementBase
var forbidden = config?.forbiddenItems ?? new List<PickupItemData>(); var forbidden = config?.forbiddenItems ?? new List<PickupItemData>();
// CASE 1: No held item, slot has item -> pick up slotted item // CASE 1: No held item, slot has item -> pick up slotted item
if (heldItem == null && currentlySlottedItem != null) if (heldItem == null && _cachedSlottedObject != null)
{ {
follower.SetHeldItem(currentlySlottedItem); follower.SetHeldItemFromObject(_cachedSlottedObject);
RemoveSlottedObject();
currentlySlottedItem = null; currentlySlottedItem = null;
UpdateSlottedSprite(); UpdateSlottedSprite();
return true; return true;
} }
// CASE 2: Held item, slot has item -> swap // CASE 2: Held item, slot has item -> swap
if (heldItem != null && currentlySlottedItem != null) if (heldItem != null && _cachedSlottedObject != null)
{ {
var temp = currentlySlottedItem; var followerHeldObj = heldObj;
currentlySlottedItem = heldItem; var followerHeldItem = heldItem;
var slotObj = _cachedSlottedObject;
var slotItemData = currentlySlottedItem;
// 1. Slot the follower's held object (do NOT destroy the old one)
SetSlottedObject(followerHeldObj);
currentlySlottedItem = followerHeldItem;
UpdateSlottedSprite(); UpdateSlottedSprite();
follower.SetHeldItem(temp);
// 2. Give the slot's object to the follower
follower.SetHeldItemFromObject(slotObj);
return true; return true;
} }
// CASE 3: Held item, slot empty -> slot the held item // CASE 3: Held item, slot empty -> slot the held item
if (heldItem != null && currentlySlottedItem == null) if (heldItem != null && _cachedSlottedObject == null)
{ {
if (forbidden.Contains(heldItem)) if (forbidden.Contains(heldItem))
{ {
DebugUIMessage.Show("Can't place that here."); DebugUIMessage.Show("Can't place that here.");
return false; return false;
} }
CacheSlottedObject(heldObj);
currentlySlottedItem = heldItem; currentlySlottedItem = heldItem;
UpdateSlottedSprite(); UpdateSlottedSprite();
follower.SetHeldItem(null); follower.ClearHeldItem();
if (allowed.Contains(heldItem)) if (allowed.Contains(heldItem))
{ {
OnSuccess?.Invoke(); OnSuccess?.Invoke();
@@ -74,7 +125,7 @@ public class SlotItemBehavior : InteractionRequirementBase
} }
} }
// CASE 4: No held item, slot empty -> show warning // CASE 4: No held item, slot empty -> show warning
if (heldItem == null && currentlySlottedItem == null) if (heldItem == null && _cachedSlottedObject == null)
{ {
DebugUIMessage.Show("This requires an item."); DebugUIMessage.Show("This requires an item.");
return false; return false;
@@ -110,4 +161,9 @@ public class SlotItemBehavior : InteractionRequirementBase
slottedItemRenderer.sprite = null; slottedItemRenderer.sprite = null;
} }
} }
void Update()
{
Debug.Log($"[SlotItemBehavior] _cachedSlottedObject: {_cachedSlottedObject} (GameObject name: {(_cachedSlottedObject != null ? _cachedSlottedObject.name : "null")})", this);
}
} }

View File

@@ -60,11 +60,20 @@ public class FollowerController : MonoBehaviour
/// Cache for the currently picked-up GameObject (hidden while held). /// Cache for the currently picked-up GameObject (hidden while held).
/// </summary> /// </summary>
private GameObject _cachedPickupObject = null; private GameObject _cachedPickupObject = null;
public bool justCombined = false;
/// <summary> /// <summary>
/// Set to true if the follower just combined items. /// Caches the given pickup object as the currently held item, hides it, and parents it to the follower.
/// </summary> /// </summary>
public bool justCombined = false; public void CacheHeldPickupObject(GameObject obj)
{
// Do not destroy the previous object; just replace and hide
_cachedPickupObject = obj;
if (_cachedPickupObject != null)
{
_cachedPickupObject.SetActive(false);
}
}
void Awake() void Awake()
{ {
@@ -281,6 +290,45 @@ public class FollowerController : MonoBehaviour
_lastInteractionSuccess = success; _lastInteractionSuccess = success;
} }
public GameObject GetHeldPickupObject()
{
return _cachedPickupObject;
}
public void SetHeldItemFromObject(GameObject obj)
{
if (obj == null)
{
ClearHeldItem();
return;
}
var pickup = obj.GetComponent<Pickup>();
if (pickup != null)
{
SetHeldItem(pickup.itemData, pickup.iconRenderer);
CacheHeldPickupObject(obj);
}
else
{
ClearHeldItem();
}
}
public void ClearHeldItem()
{
if (_cachedPickupObject != null)
{
// Destroy(_cachedPickupObject);
_cachedPickupObject = null;
}
_currentlyHeldItem = null;
if (heldObjectRenderer != null)
{
heldObjectRenderer.sprite = null;
heldObjectRenderer.enabled = false;
}
}
private System.Collections.IEnumerator PickupSequence(Vector2 itemPosition, Transform playerTransform) private System.Collections.IEnumerator PickupSequence(Vector2 itemPosition, Transform playerTransform)
{ {
_isManualFollowing = false; _isManualFollowing = false;
@@ -314,12 +362,6 @@ public class FollowerController : MonoBehaviour
} }
if (justCombined) if (justCombined)
{ {
// Combination: just destroy the pickup, don't spawn anything
if (_cachedPickupObject != null)
{
Destroy(_cachedPickupObject);
_cachedPickupObject = null;
}
GameObject.Destroy(pickup.gameObject); GameObject.Destroy(pickup.gameObject);
justCombined = false; justCombined = false;
break; break;
@@ -334,10 +376,7 @@ public class FollowerController : MonoBehaviour
_cachedPickupObject = null; _cachedPickupObject = null;
} }
SetHeldItem(pickup.itemData, pickup.iconRenderer); SetHeldItem(pickup.itemData, pickup.iconRenderer);
// Cache and hide the picked up object CacheHeldPickupObject(pickup.gameObject);
_cachedPickupObject = pickup.gameObject;
_cachedPickupObject.SetActive(false);
_cachedPickupObject.transform.SetParent(this.transform);
break; break;
} }
} }
@@ -367,6 +406,27 @@ public class FollowerController : MonoBehaviour
_pickupCoroutine = null; _pickupCoroutine = null;
} }
/// <summary>
/// Drop the held item at the specified position, unparenting and activating it.
/// </summary>
/// <param name="position">The world position to drop the item at.</param>
public void DropHeldItemAt(Vector3 position)
{
if (_cachedPickupObject != null)
{
_cachedPickupObject.transform.position = position;
_cachedPickupObject.transform.SetParent(null);
_cachedPickupObject.SetActive(true);
_cachedPickupObject = null;
_currentlyHeldItem = null;
if (heldObjectRenderer != null)
{
heldObjectRenderer.sprite = null;
heldObjectRenderer.enabled = false;
}
}
}
void OnDrawGizmos() void OnDrawGizmos()
{ {
if (debugDrawTarget && Application.isPlaying) if (debugDrawTarget && Application.isPlaying)