added: item pickups with online persistency

This commit is contained in:
Chris
2025-09-08 16:40:13 -04:00
parent 8bdf0b31cc
commit 7a0499f36a
39 changed files with 8228 additions and 208 deletions

View File

@@ -9,6 +9,8 @@ namespace NodeCanvas.Tasks.Conditions {
public BBParameter<string> observerLabel;
public BBParameter<RaycastHit> outputHitTo;
public bool deactivateOnFinish = true;
protected override string info{
get {
return $"Check Environment Observer, [\"{observerLabel.value}\"]";
@@ -33,7 +35,9 @@ namespace NodeCanvas.Tasks.Conditions {
//Called whenever the condition gets disabled.
protected override void OnDisable() {
agent.FindObserverFromString(observerLabel.value).active = false;
if (deactivateOnFinish){
agent.FindObserverFromString(observerLabel.value).active = false;
}
}
//Called once per frame while the condition is active.

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using NodeCanvas.Framework;
using ParadoxNotion;
using ParadoxNotion.Design;
using ParadoxNotion.Services;
using UnityEngine;
using UnityEngine.InputSystem;
@@ -12,15 +13,31 @@ namespace NodeCanvas.Tasks.Conditions {
public class CheckInput : ConditionTask<Transform>{
public BBParameter<string> actionName;
public BBParameter<InputActionPhase> actionPhase;
private bool blocked;
private SignalDefinition signalDefinition;
// Add buffered input here
private SignalDefinition inputSignalDefinition;
private SignalDefinition blockInputDefinition;
protected override string info {
get { return $"Input <b>{actionName.value}</b> was <b>{actionPhase.value}</b>"; }
}
protected override string OnInit(){
MonoManager.current.onLateUpdate += UnblockOnFrameEnd;
try {
signalDefinition = Resources.Load<SignalDefinition>("InputSignal");
inputSignalDefinition = Resources.Load<SignalDefinition>("InputSignal");
} catch (Exception e) {
Debug.LogError($"Error finding the Input Signal defintion: {e.Message}");
throw;
}
try {
blockInputDefinition = Resources.Load<SignalDefinition>("BlockInputSignal");
} catch (Exception e) {
Debug.LogError($"Error finding the Input Signal defintion: {e.Message}");
throw;
@@ -30,25 +47,52 @@ namespace NodeCanvas.Tasks.Conditions {
}
protected override void OnEnable() {
signalDefinition.onInvoke -= OnSignalInvoke;
signalDefinition.onInvoke += OnSignalInvoke;
inputSignalDefinition.onInvoke -= InputSignalInvoke;
inputSignalDefinition.onInvoke += InputSignalInvoke;
blockInputDefinition.onInvoke -= BlockInputDefinition;
blockInputDefinition.onInvoke += BlockInputDefinition;
}
protected override void OnDisable() {
signalDefinition.onInvoke -= OnSignalInvoke;
inputSignalDefinition.onInvoke -= InputSignalInvoke;
blockInputDefinition.onInvoke -= BlockInputDefinition;
}
void OnSignalInvoke(Transform sender, Transform receiver, bool isGlobal, params object[] args){
void InputSignalInvoke(Transform sender, Transform receiver, bool isGlobal, params object[] args){
// Take the input arguments as objects and convert them to InputAction & Phases
InputAction thisAction = (InputAction)args[0];
InputActionPhase thisActionPhase = (InputActionPhase)args[1];
if (actionName.value == thisAction.name && actionPhase.value == thisActionPhase) {
// Debug.Log(thisActionPhase);
if (actionName.value == thisAction.name && actionPhase.value == thisActionPhase && !blocked) {
Debug.Log($"Recieved an unblocked {thisAction} @ {Time.time}.");
YieldReturn(true);
}
}
void BlockInputDefinition(Transform sender, Transform receiver, bool isGlobal, params object[] args){
// Take the input arguments as objects and convert them to InputAction & Phases
string thisAction = (string)args[0];
if (actionName.value == thisAction) {
Debug.Log($"Blocking {thisAction} @ {Time.time}.");
blocked = true;
}
}
void UnblockOnFrameEnd(){
if (blocked) {
blocked = false;
Debug.Log($"Unblocking {actionName} @ {Time.time}.");
}
}
protected override bool OnCheck() { return false; }
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f5b80d83b4b96aa4896eed8add126e99
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,6 @@
using UnityEngine;
public interface IInteractable{
public void Interact();
public void CancelInteract();
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 002886b8496bd41498825928776fb5a1

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 594c244f5e4b6df43bef28acad6091b4
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,7 @@
using UnityEngine;
namespace Reset.Items{
public class Ability : Item, IEquipable{
public NodeCanvas.Framework.Graph behaviourGraph;
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: faa811a7ade12ef44b5e4d2065b28401

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 78ad34c56119132409b8757bdf2fbd98
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,6 @@
using UnityEngine;
public interface IEquipable
{
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: a09cb950a163e5c49bddf8d6c2187148

View File

@@ -0,0 +1,24 @@
using System.Collections.Generic;
using Unity.Netcode;
using UnityEngine;
namespace Reset.Items{
public abstract class Item : ScriptableObject{
public string itemName{ get; set; }
public float permanency;
public float essenceRequiredForPermanency;
private Event onDropDelegates;
public void DropItem(){
}
public virtual ItemDrop CreateItemDropFrom(){
ItemDrop newItemDrop = new GameObject().AddComponent<ItemDrop>();
newItemDrop.item = this;
return newItemDrop;
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: ae19a9c5003b14c4d9d8a23d3278be2e

View File

@@ -0,0 +1,38 @@
using System;
using Unity.Netcode;
using UnityEngine;
namespace Reset.Items{
public class ItemDrop : NetworkBehaviour, IInteractable{
public Item item;
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start(){
}
// Update is called once per frame
void Update(){
}
public void Interact(){
if (NetworkManager.Singleton.IsHost || NetworkManager.Singleton.IsConnectedClient) {
Debug.Log("RPC Sent");
DestroyOnOwnerRpc();
} else {
Debug.Log("Destroyed");
Destroy(gameObject);
}
}
public void CancelInteract(){
throw new NotImplementedException();
}
[Rpc(SendTo.Owner)]
public void DestroyOnOwnerRpc(){
Destroy(gameObject);
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 47fcfe0cd0436de41a99c2ed60f488a8

View File

@@ -0,0 +1,15 @@
using System;
using NodeCanvas.StateMachines;
using UnityEngine;
namespace Reset.Items{
[CreateAssetMenu(menuName = "Reset/Weapon", fileName = "New Weapon")]
public class Weapon : Item, IEquipable{
public GameObject weaponModel;
public NodeCanvas.Framework.Graph weaponFSM;
void Awake(){
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: b7f2c6caae048f64f91b54ae1442694c

View File

@@ -0,0 +1,49 @@
using Reset.Items;
using UnityEngine;
using UnityEngine.InputSystem;
namespace Reset.Units{
public class InteractionHandler : MonoBehaviour{
private PlayerEnvironmentManager envManager;
private Inventory inventory;
private EnvironmentObserver observer;
void Awake(){
envManager = GetComponent<PlayerEnvironmentManager>();
inventory = GetComponent<Inventory>();
observer = envManager.FindObserverFromString("itemdrop");
observer.active = true;
}
public void InteractWith(GameObject target){
IInteractable interactable = target.GetComponent<IInteractable>();
if (interactable == null) {
Debug.LogError("This item cannot be interacted with, it has no Interactable interface");
return;
}
if (target.GetComponent<ItemDrop>()) {
inventory.AddToInventory(target.GetComponent<ItemDrop>().item);
}
interactable.Interact();
// Don't do any actions that use the same button (hard set to Jump for now)
Debug.Log($"Just collected the item, consuming the input @ {Time.time}.");
GetComponent<PlayerControls>().SendInputBlock("Jump");
}
void OnInteract(){
CheckForInteraction();
}
private void CheckForInteraction(){
if (observer.active && observer.Evaluate(gameObject)) {
InteractWith(observer.hit.transform.gameObject);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 96023d711211b9843b01db23192fa84c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: -101
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,31 @@
using System.Collections.Generic;
using Reset.Items;
using UnityEngine;
namespace Reset.Units{
public class Inventory : MonoBehaviour{
public Weapon rangedWeapon;
public Weapon meleeWeapon;
public Ability spellAbility1;
public Ability spellAbility2;
public Ability toolAbility1;
public Ability toolAbility2;
public List<Item> storedItems = new List<Item>(15);
void Start(){
}
public void AddToInventory(Item newItem){
storedItems.Add(newItem);
}
// Update is called once per frame
void Update(){
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: d57ab8ec1cbbdcf46813f268625d3494

View File

@@ -10,13 +10,15 @@ using ParadoxNotion;
using Reset;
using Sirenix.OdinInspector;
using Unity.Cinemachine;
using Object = UnityEngine.Object;
public class PlayerControls : MonoBehaviour{
// References
private Player thisPlayer;
private PlayerInput input;
public SignalDefinition inputSignal;
private SignalDefinition inputSignal;
private SignalDefinition blockSignal;
// TODO: Turn these into accessors
public Vector2 rawMoveInput;
@@ -25,6 +27,21 @@ public class PlayerControls : MonoBehaviour{
public GraphOwner graph;
void Awake(){
try {
inputSignal = Resources.Load<SignalDefinition>("InputSignal");
} catch (Exception e) {
Debug.LogError($"Error finding the Input Signal defintion: {e.Message}");
throw;
}
try {
blockSignal = Resources.Load<SignalDefinition>("BlockInputSignal");
} catch (Exception e) {
Debug.LogError($"Error finding the Input Signal defintion: {e.Message}");
throw;
}
thisPlayer = GetComponent<Player>();
graph = GetComponent<GraphOwner>();
input = GetComponent<PlayerInput>();
@@ -34,29 +51,34 @@ public class PlayerControls : MonoBehaviour{
// Add the delegates for each method
foreach (InputAction action in input.actions) {
action.started += SendToGraph;
action.canceled += SendToGraph;
action.performed += SendToGraph;
action.started += SendInputSignal;
action.canceled += SendInputSignal;
action.performed += SendInputSignal;
}
}
// Remove the delegates for each method
void OnDisable(){
foreach (InputAction action in input.actions) {
action.started -= SendToGraph;
action.canceled -= SendToGraph;
action.performed -= SendToGraph;
action.started -= SendInputSignal;
action.canceled -= SendInputSignal;
action.performed -= SendInputSignal;
}
}
// This will call the OnSignalInvoke for this type of Signal Defintion. CheckInput is the recieving end.
public void SendToGraph(InputAction.CallbackContext ctx){
// This will call the SignalInvoke for this type of Signal Defintion. CheckInput is the recieving end.
public void SendInputSignal(InputAction.CallbackContext ctx){
inputSignal.Invoke(transform, transform, false, new object[]{
ctx.action,
ctx.phase
});
}
public void SendInputBlock(string actionName){
Debug.Log($"Sending block request...");
blockSignal.Invoke(transform, transform, false, new object[]{actionName});
}
public void OnMove(InputValue value){
rawMoveInput.x = value.Get<Vector2>().x;
rawMoveInput.y = value.Get<Vector2>().y;