This commit is contained in:
2026-07-09 21:33:33 +02:00
commit 84a2a365f3
2364 changed files with 950134 additions and 0 deletions
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 3598e956cf8c4542a43aaa401f9bd61b
timeCreated: 1664306080
@@ -0,0 +1,142 @@
using System;
using System.Collections.Generic;
using Sirenix.OdinInspector;
using Sirenix.Utilities;
using UnityEngine;
using VOID.Generic.Dict;
using VOID.Generic.Objects.Abstract.Events;
using VOID.Generic.Triggers;
namespace VOID.Generic.Objects.Abstract
{
[SelectionBase]
[DisallowMultipleComponent]
[RequireComponent(typeof(Rigidbody))]
public abstract class AbstractObject : MonoBehaviour
{
[Title("=== BasicObject properties ===")]
public AbstractObjectData basicData;
public AbstractObjectEvents basicEvents;
public AbstractObjectStatusManager statusManager;
public AbstractObjectState basicState;
protected void OnValidate()
{
gameObject.GetComponent<Rigidbody>().hideFlags = HideFlags.NotEditable;
// Init RigidBody
var rb = GetComponent<Rigidbody>();
rb.mass = 0;
rb.linearDamping = 0;
rb.angularDamping = 0;
rb.automaticCenterOfMass = true;
rb.automaticInertiaTensor = true;
rb.useGravity = false;
rb.isKinematic = true;
rb.interpolation = RigidbodyInterpolation.None;
rb.constraints = RigidbodyConstraints.FreezeAll;
}
private void Awake()
{
GetObjectComponents().ForEach(component => component.SetParent(this));
GetObjectComponents().ForEach(component => component.DoSelfInitialize());
GetObjectComponents().ForEach(component => component.DoEventInitialize());
GetObjectComponents().ForEach(component => component.DoInitialize());
}
private void Start()
{
// Finally when this object is fully initialized then we can
basicEvents.onSpawn.Invoke();
}
protected void FixedUpdate()
{
basicEvents.onFixedUpdate.Invoke();
}
protected virtual List<ObjectComponent> GetObjectComponents()
{
return new List<ObjectComponent>
{
basicData,
basicEvents,
statusManager,
basicState
};
}
[Button]
public void TakeDamage(DamageEvent damageEvent)
{
if (basicState.isDead) return;
if (!basicData.canBeDestroyed) return;
basicEvents.onDamagedBefore.Invoke(damageEvent);
if (damageEvent.attacker) damageEvent.attacker.unitEvents.onDamageBefore.Invoke(damageEvent);
if (damageEvent.prevented) return;
var damage = damageEvent.amount;
var resistance = 1 - basicData.resistances.Get(damageEvent.damageType);
basicData.UseResource(BasicResourceType.Health, damage * resistance, true);
basicEvents.onDamagedAfter.Invoke(damageEvent);
if (damageEvent.attacker) damageEvent.attacker.unitEvents.onDamageAfter.Invoke(damageEvent);
if (basicData.currentResources.health <= 0f) Death();
}
[Button]
public void Death()
{
if (basicState.isDead) return;
if (!basicData.canBeDestroyed) return;
var deathEvent = new DeathEvent { obj = this };
basicEvents.onDeathBefore.Invoke(deathEvent);
if (deathEvent.prevented) return;
basicEvents.onDeathAfter.Invoke(deathEvent);
basicData.currentResources.health = 0f;
}
[Button]
public void Revive()
{
if (basicState.isDead == false) return;
basicData.SetResourcePercentage(BasicResourceType.Health, 0.3f);
basicEvents.onRevive.Invoke(new ReviveEvent { obj = this });
}
[Button]
public void Remove()
{
var removeEvent = new RemoveEvent { obj = this };
basicEvents.onRemove.Invoke(removeEvent);
Destroy(gameObject);
}
private void OnTriggerEnter(Collider other)
{
other.GetComponentsInParent<IDynamicTrigger>().ForEach(triggerArea => {
if (basicState.isDead == false) triggerArea.OnObjectEnter(this);
basicEvents.onTriggerEnter.Invoke(new TriggerEvent { obj = this, triggerArea = triggerArea });
});
}
private void OnTriggerExit(Collider other)
{
other.GetComponentsInParent<IDynamicTrigger>().ForEach(triggerArea => {
if (basicState.isDead == false) triggerArea.OnObjectExit(this);
basicEvents.onTriggerExit.Invoke(new TriggerEvent { obj = this, triggerArea = triggerArea });
});
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a31cf06e6e17cc54cb2c67298dbc5cfc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 85c7ecfed11eec14daa605a62c6639ab, type: 3}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,144 @@
using System;
using Sirenix.OdinInspector;
using UnityEngine;
using VOID.Generic.Dict;
using VOID.Generic.Objects.Abstract.Data;
using VOID.Generic.Objects.Abstract.Events;
using VOID.Generic.Objects.Item;
using Resources = VOID.Generic.Objects.Abstract.Data.Resources;
namespace VOID.Generic.Objects.Abstract
{
/// <summary>
/// Contain and manages all generic data needed and used by <see cref="AbstractObject"/> or its children.
/// </summary>
[Serializable]
public class AbstractObjectData : ObjectComponent<AbstractObject>
{
#region Initialize
protected override void SelfInitialize()
{
// Init resources values
foreach (BasicResourceType resourceType in Enum.GetValues(typeof(BasicResourceType)))
maxResources.Set(resourceType, baseMaxResources.Get(resourceType));
// Init resistances values
foreach (DamageType damageType in Enum.GetValues(typeof(DamageType)))
resistances.Set(damageType, baseResistances.Get(damageType));
}
protected override void Initialize()
{
// Instantiate stats
baseMaxResources = baseMaxResources with {};
maxResources = maxResources with {};
currentResources = currentResources with {};
baseResistances = baseResistances with {};
resistances = resistances with {};
}
#endregion
[Title("Possible actions")]
[LabelText("TODO: canBeSelected")] public bool canBeSelected = true;
public bool canBeDestroyed = true;
[LabelText("TODO: canBeInspected")] public bool canBeInspected = true;
[Title("Display in UI")]
public string name;
public string finalName => parent switch
{
ItemObject item => item.itemData.finalName,
_ => name
};
public Texture2D image;
[TextArea] public string description;
[Title("Size")]
[MinValue(1f)] public float height = 1f;
[MinValue(.25f)] public float radius = 0.25f;
[Title("Basic Resources")]
public Resources baseMaxResources;
[ReadOnly] public Resources maxResources;
[ReadOnly] public Resources currentResources;
[Title("Basic Resistances")]
public Resistances baseResistances;
[ReadOnly] public Resistances resistances;
/// <summary>
/// Uses given resource by given amount.<br/>
/// That means positive values decreases and negative values increases that resource.
/// </summary>
/// <param name="resourceType">Resource to use</param>
/// <param name="change">Amount to change</param>
/// <param name="force">If TRUE then we can use this resource even if we don't have enough of it</param>
/// <returns>Returns TRUE if done successfully.</returns>
public bool UseResource(BasicResourceType resourceType, float change, bool force = false)
{
var oldValue = currentResources.Get(resourceType);
var maxValue = maxResources.Get(resourceType);
// Attempt to use more than available
if (oldValue - change < 0f)
{
// If not forced - not enough resource
if (!force) return false;
// Else - use only remaining resource
change += oldValue - change;
}
// Attempt to go over limit
if (oldValue - change > maxValue)
{
change = oldValue - maxValue;
}
currentResources.Set(resourceType, oldValue - change);
parent.basicEvents.onCurrentResourceChange.Invoke(new BasicResourceChangeEvent
{
obj = parent,
type = resourceType,
oldValue = oldValue,
newValue = oldValue - change,
changedValue = change,
});
return true;
}
/// <summary>
/// Sets given resource to given value.<br/>
/// It uses <see cref="UseResource"/> so whole process will be executed as change from starting value to given value.
/// </summary>
/// <param name="resourceType">Resource type to set</param>
/// <param name="value">Value to set</param>
/// <returns>Return TRUE if done successfully.</returns>
public bool SetResource(BasicResourceType resourceType, float value)
{
var max = maxResources.Get(resourceType);
var oldValue = Mathf.Clamp(currentResources.Get(resourceType), 0f, max);
var change = oldValue - value;
return UseResource(resourceType, change, true);
}
/// <summary>
/// Sets given resource to percentage of its max value.<br/>
/// It uses <see cref="SetResource"/> so whole process will be executed as change from starting value to given value.
/// </summary>
/// <param name="resourceType">Resource type to set</param>
/// <param name="percentage">float as percent, value needs to be between 0 and 1</param>
/// <returns>Return TRUE if done successfully.</returns>
public bool SetResourcePercentage(BasicResourceType resourceType, float percentage)
{
percentage = Mathf.Clamp01(percentage);
var max = maxResources.Get(resourceType);
var value = percentage * max;
var oldValue = currentResources.Get(resourceType);
var change = oldValue - value;
return UseResource(resourceType, change, true);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a121af7cd1dd8b74aab63b7fba7ccd19
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,63 @@
using Sirenix.OdinInspector;
using UnityEngine.Events;
using VOID.Generic.Objects.Abstract.Events;
using VOID.Generic.Objects.Unit.Events;
namespace VOID.Generic.Objects.Abstract
{
[System.Serializable]
public class AbstractObjectEvents : ObjectComponent<AbstractObject>
{
[Title("Spawn")]
public UnityEvent onSpawn;
[Title("Destroy")]
public UnityEvent<RemoveEvent> onRemove;
[Title("Time")]
public UnityEvent onFixedUpdate;
// COMPONENT RELATED EVENTS
[Title("Statuses")]
public UnityEvent<StatusEvent> onStatusStart;
public UnityEvent<StatusEvent> onStatusEnd;
public UnityEvent<EffectEvent> onEffectStart;
public UnityEvent<EffectEvent> onEffectEnd;
[Title("Data")]
public UnityEvent<BasicResourceChangeEvent> onMaxResourceChange;
public UnityEvent<BasicResourceChangeEvent> onCurrentResourceChange;
// TURN RELATED EVENTS
// These should be ran only from `VOID.Generic.Turn.TurnManager`
// So all `Invoke()` related to turns will be inside that manager class
[Title("Turn")]
public UnityEvent<TurnEvent> onTurnQueueStart;
public UnityEvent<TurnEvent> onTurnQueueEnd;
public UnityEvent<TurnEvent> onTurnQueueSwap;
public UnityEvent<TurnEvent> onTurnQueueEnter;
public UnityEvent<TurnEvent> onTurnQueueLeave;
public UnityEvent<TurnEvent> onTurnSelfStart;
public UnityEvent<TurnEvent> onTurnSelfEnd;
// ACTION RELATED EVENTS
[Title("Death")]
public UnityEvent<DeathEvent> onDeathBefore;
public UnityEvent<DeathEvent> onDeathAfter;
[Title("Death")]
public UnityEvent<ReviveEvent> onRevive;
[Title("Being attacked")]
public UnityEvent<DamageEvent> onDamagedBefore;
public UnityEvent<DamageEvent> onDamagedAfter;
[Title("Being hit by ability")]
public UnityEvent<AbilityHitEvent> onAbilityHitBefore;
public UnityEvent<AbilityHitEvent> onAbilityHitAfter;
[Title("Being inspected")]
public UnityEvent onInspectedBefore;
public UnityEvent onInspectedAfter;
// PHYSICS RELATED EVENTS
[Title("TRIGGER ENTER & LEAVE")]
public UnityEvent<TriggerEvent> onTriggerEnter;
public UnityEvent<TriggerEvent> onTriggerExit;
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: d6976257b5e64b2e828f7a5321fd7c21
timeCreated: 1664306673
@@ -0,0 +1,78 @@
using System.Collections.Generic;
using Sirenix.OdinInspector;
using UnityEngine;
using VOID.Generic.Objects.Abstract.Events;
using VOID.Generic.Triggers;
using VOID.Generic.Turn;
namespace VOID.Generic.Objects.Abstract
{
[System.Serializable]
public class AbstractObjectState : ObjectComponent<AbstractObject>
{
#region Initialize
protected override void EventInitialize()
{
// Death & Revive events
parent.basicEvents.onDeathAfter.AddListener(OnDeath);
parent.basicEvents.onRevive.AddListener(OnRevive);
// Turn events
parent.basicEvents.onTurnQueueEnter.AddListener(OnTurnEnter);
parent.basicEvents.onTurnQueueLeave.AddListener(OnTurnLeave);
parent.basicEvents.onTurnQueueSwap.AddListener(OnTurnSwap);
// Trigger events
parent.basicEvents.onTriggerEnter.AddListener(OnTriggerEnter);
parent.basicEvents.onTriggerExit.AddListener(OnTriggerExit);
}
#endregion
[ShowInInspector, ReadOnly] public TurnManager turnManager { get; private set; }
private List<IDynamicTrigger> _triggerAreas = new();
public bool isDead;
private void OnTurnEnter(TurnEvent turnEvent)
{
turnManager = turnEvent.turnManager;
}
private void OnTurnLeave(TurnEvent turnEvent)
{
turnManager = null;
}
private void OnTurnSwap(TurnEvent turnEvent)
{
turnManager = turnEvent.turnManager;
}
private void OnDeath(DeathEvent deathEvent)
{
isDead = true;
_triggerAreas.RemoveAll(triggerArea => triggerArea as MonoBehaviour == null);
_triggerAreas.ForEach(triggerArea => triggerArea.OnObjectExit(parent));
if (turnManager) turnManager.ObjectExit(parent);
}
private void OnRevive(ReviveEvent reviveEvent)
{
isDead = false;
_triggerAreas.RemoveAll(triggerArea => triggerArea as MonoBehaviour == null);
_triggerAreas.ForEach(triggerArea => triggerArea.OnObjectEnter(parent));
}
private void OnTriggerEnter(TriggerEvent triggerEvent)
{
_triggerAreas.Add(triggerEvent.triggerArea);
}
private void OnTriggerExit(TriggerEvent triggerEvent)
{
_triggerAreas.Remove(triggerEvent.triggerArea);
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 7c981ec7d6b04481befd7320d974b587
timeCreated: 1686607159
@@ -0,0 +1,66 @@
using System.Collections.Generic;
using System.Linq;
using Sirenix.OdinInspector;
using UnityEngine;
using VOID.Generic.Objects.Abstract.Events;
using VOID.Generic.Objects.Unit;
using VOID.ScriptableObjects;
namespace VOID.Generic.Objects.Abstract
{
[System.Serializable]
public class AbstractObjectStatusManager : ObjectComponent<AbstractObject>
{
#region Initialize
protected override void EventInitialize()
{
// When realtime based gameplay is working
parent.basicEvents.onFixedUpdate.AddListener(OnRealTimeDecreaseDuration);
// When turn based gameplay is working
parent.basicEvents.onTurnSelfStart.AddListener(OnTurnSelfStart);
parent.basicEvents.onTurnSelfEnd.AddListener(OnTurnSelfEnd);
// When entering or leaving turn based gameplay
parent.basicEvents.onTurnQueueEnter.AddListener(OnTurnEnter);
parent.basicEvents.onTurnQueueLeave.AddListener(OnTurnLeave);
}
protected override void Initialize()
{
// Statuses already added via inspector need to be started this way
// Important thing - instantiate ScriptableObjects so we wont change original ones
for (var i = 0; i < statuses.Count; i++)
{
statuses[i] = Object.Instantiate(statuses[i]);
statuses[i].Init(parent);
statuses[i].Apply();
}
}
#endregion
[SerializeReference, DisableInPlayMode] private List<BasicStatus> statuses = new();
private void OnTurnEnter(TurnEvent turnEvent) => parent.basicEvents.onFixedUpdate.RemoveListener(OnRealTimeDecreaseDuration);
private void OnTurnLeave(TurnEvent turnEvent) => parent.basicEvents.onFixedUpdate.AddListener(OnRealTimeDecreaseDuration);
private void OnTurnSelfStart(TurnEvent turnEvent) => statuses.ForEach(status => status.OnTurnSelfStart());
private void OnTurnSelfEnd(TurnEvent turnEvent) => statuses.ToList().ForEach(status => status.OnTurnSelfEnd());
private void OnRealTimeDecreaseDuration() => statuses.ToList().ForEach(status => status.DecreaseDurationRealTime());
public void AddStatus(BasicStatus status, UnitObject source = null, bool instantiate = true)
{
// instantiate ScriptableObjects so we wont change original ones if needed
if (instantiate) status = Object.Instantiate(status);
statuses.Add(status);
status.Init(parent, source);
status.Apply();
}
public void RemoveStatus(BasicStatus status) => statuses.Remove(status);
public BasicStatus[] GetStatuses() => statuses.ToArray();
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1383959980310a349900e380980f8b6a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: c45b5a8066dd4cbd9656c671b7b4feb7
timeCreated: 1693742336
@@ -0,0 +1,56 @@
using System;
using VOID.Generic.Dict;
namespace VOID.Generic.Objects.Abstract.Data
{
[Serializable]
public record Resistances
{
public float physicalResistance = 0f;
public float magicalResistance = 0f;
public float fireResistance = 0f;
public float waterResistance = 0f;
public float earthResistance = 0f;
public float airResistance = 0f;
public float poisonResistance = 0f;
public float lightResistance = 0f;
public float darkResistance = 0f;
public float healResistance = 2f;
public float Get(DamageType type)
{
return type switch
{
DamageType.Physical => physicalResistance,
DamageType.Magical => magicalResistance,
DamageType.Fire => fireResistance,
DamageType.Water => waterResistance,
DamageType.Earth => earthResistance,
DamageType.Air => airResistance,
DamageType.Poison => poisonResistance,
DamageType.Light => lightResistance,
DamageType.Dark => darkResistance,
DamageType.Heal => healResistance,
_ => throw new ArgumentOutOfRangeException(nameof(type), type, null)
};
}
public void Set(DamageType type, float value)
{
switch(type)
{
case DamageType.Physical: physicalResistance = value; return;
case DamageType.Magical: magicalResistance = value; return;
case DamageType.Fire: fireResistance = value; return;
case DamageType.Water: waterResistance = value; return;
case DamageType.Earth: earthResistance = value; return;
case DamageType.Air: airResistance = value; return;
case DamageType.Poison: poisonResistance = value; return;
case DamageType.Light: lightResistance = value; return;
case DamageType.Dark: darkResistance = value; return;
case DamageType.Heal: healResistance = value; return;
default: throw new ArgumentOutOfRangeException(nameof(type), type, null);
};
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: e2097634927841769bcd90360a511ed1
timeCreated: 1693742351
@@ -0,0 +1,31 @@
using System;
using Sirenix.OdinInspector;
using VOID.Generic.Dict;
namespace VOID.Generic.Objects.Abstract.Data
{
[Serializable]
public record Resources
{
[MinValue(0f)]
public float health = 10f;
public float Get(BasicResourceType type)
{
return type switch
{
BasicResourceType.Health => health,
_ => throw new ArgumentOutOfRangeException(nameof(type), type, null)
};
}
public void Set(BasicResourceType type, float value)
{
switch(type)
{
case BasicResourceType.Health: health = value; return;
default: throw new ArgumentOutOfRangeException(nameof(type), type, null);
};
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f9a3fdf71177419da626c4f3ba6b0b27
timeCreated: 1693743887
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: c8f294cc39c5481d985ccf4dd724f25d
timeCreated: 1668634664
@@ -0,0 +1,7 @@
namespace VOID.Generic.Objects.Abstract.Events
{
public abstract class AbstractEvent
{
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 1ee6c0ca0efc40f8a2a0605b355f90f3
timeCreated: 1666901839
@@ -0,0 +1,13 @@
using VOID.Generic.Dict;
namespace VOID.Generic.Objects.Abstract.Events
{
public class BasicResourceChangeEvent : AbstractEvent
{
public AbstractObject obj;
public BasicResourceType type;
public float oldValue;
public float newValue;
public float changedValue;
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 767da03874a249c99966ae86ee48ae8f
timeCreated: 1693752577
@@ -0,0 +1,15 @@
using VOID.Generic.Dict;
using VOID.Generic.Objects.Unit;
namespace VOID.Generic.Objects.Abstract.Events
{
public class DamageEvent : AbstractEvent
{
public bool prevented = false;
public AbstractObject target;
public UnitObject attacker;
public float amount;
public DamageType damageType;
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: bca6a131b1c94d9ba67836be72a4c62c
timeCreated: 1668636901
@@ -0,0 +1,9 @@
namespace VOID.Generic.Objects.Abstract.Events
{
public class DeathEvent : AbstractEvent
{
public bool prevented = false;
public AbstractObject obj;
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a7373f77231b4c27b49e8352494e9fe3
timeCreated: 1675363800
@@ -0,0 +1,10 @@
using VOID.Generic.Status.Effect;
namespace VOID.Generic.Objects.Abstract.Events
{
public class EffectEvent : AbstractEvent
{
public AbstractObject obj;
public BasicEffect effect;
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 7540cd1428134f3884aa1660037ebbd6
timeCreated: 1674413226
@@ -0,0 +1,7 @@
namespace VOID.Generic.Objects.Abstract.Events
{
public class RemoveEvent : AbstractEvent
{
public AbstractObject obj;
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 3a06b6ad4d60443bb4f6421a8685ed8f
timeCreated: 1675789635
@@ -0,0 +1,7 @@
namespace VOID.Generic.Objects.Abstract.Events
{
public class ReviveEvent : AbstractEvent
{
public AbstractObject obj;
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 83a0d26632374a0a8a32b803e5c70a89
timeCreated: 1710964438
@@ -0,0 +1,10 @@
using VOID.ScriptableObjects;
namespace VOID.Generic.Objects.Abstract.Events
{
public class StatusEvent : AbstractEvent
{
public AbstractObject obj;
public BasicStatus status;
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 52a97addb7b74e31b985f8319b3c3d50
timeCreated: 1670355516
@@ -0,0 +1,10 @@
using VOID.Generic.Triggers;
namespace VOID.Generic.Objects.Abstract.Events
{
public class TriggerEvent : AbstractEvent
{
public AbstractObject obj;
public IDynamicTrigger triggerArea;
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 7c2a7cd182ef417da291d870148e8524
timeCreated: 1710969295
@@ -0,0 +1,10 @@
using VOID.Generic.Turn;
namespace VOID.Generic.Objects.Abstract.Events
{
public class TurnEvent : AbstractEvent
{
public AbstractObject obj;
public TurnManager turnManager;
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 0d2a167160234911a80d008f65ba2154
timeCreated: 1696968391
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 0185c5c61392435faf311ba1adff564d
timeCreated: 1673457196
@@ -0,0 +1,23 @@
using System.Collections.Generic;
using System.Linq;
using Sirenix.OdinInspector;
using VOID.Generic.Objects.Wearable;
namespace VOID.Generic.Objects.Accessory
{
public class AccessoryObject : WearableObject
{
[Title("=== AccessoryObject properties ===")]
public AccessoryObjectData accessoryData;
protected override List<ObjectComponent> GetObjectComponents()
{
return base.GetObjectComponents()
.Union(new[]
{
accessoryData
})
.ToList();
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 63f46d7a6604490f93800d82c0d655f4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: eba8ab9a5aff6ce47b1221f857316a43, type: 3}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,13 @@
using System;
using Sirenix.OdinInspector;
using VOID.Generic.Dict;
namespace VOID.Generic.Objects.Accessory
{
[Serializable]
public class AccessoryObjectData : ObjectComponent<AccessoryObject>
{
[Title("Basic")]
[Required] public AccessoryType accessoryType;
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 4e7ca7c83c8e49a5987d06d879705c29
timeCreated: 1705006270
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: fe37986b2c954d9d9784b28d05477828
timeCreated: 1673457179
@@ -0,0 +1,25 @@
using System.Collections.Generic;
using System.Linq;
using Sirenix.OdinInspector;
using VOID.Generic.Objects.Wearable;
namespace VOID.Generic.Objects.Armor
{
public class ArmorObject : WearableObject
{
[Title("=== ArmorObject properties ===")]
public ArmorObjectData armorData;
public ArmorObjectState armorState;
protected override List<ObjectComponent> GetObjectComponents()
{
return base.GetObjectComponents()
.Union(new List<ObjectComponent>
{
armorData,
armorState
})
.ToList();
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6eb1f4806e1248218f6a2b3c5e42a055
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 40d4d94b5847b2f4f9b1d23eba7f2dbe, type: 3}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,18 @@
using System;
using Sirenix.OdinInspector;
using VOID.Generic.Dict;
namespace VOID.Generic.Objects.Armor
{
[Serializable]
public class ArmorObjectData : ObjectComponent<ArmorObject>
{
[Title("Basic")]
[Required] public ArmorType armorType;
[Required] public ArmorSubType armorSubType;
[Title("Visual")]
public bool hideTopUnderwear;
public bool hideBottomUnderwear;
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: dae07605591c43cfb0479b77921728f2
timeCreated: 1705009430
@@ -0,0 +1,40 @@
using System;
using Sirenix.OdinInspector;
using UnityEngine;
using VOID.Generic.Dict;
using VOID.Generic.Objects.Wearable.Events;
namespace VOID.Generic.Objects.Armor
{
[Serializable]
public class ArmorObjectState : ObjectComponent<ArmorObject>
{
#region Initialize
protected override void EventInitialize()
{
parent.wearableEvents.onEquippedAfter.AddListener(OnEquip);
parent.wearableEvents.onUnEquippedAfter.AddListener(OnUnEquip);
}
#endregion
private void OnEquip(EquipEvent equipEvent)
{
// Hide top and bottom underwear if needed
if (parent.armorData.hideBottomUnderwear && equipEvent.unit.unitData.bottomUnderwear)
equipEvent.unit.unitData.bottomUnderwear.SetActive(false);
if (parent.armorData.hideTopUnderwear && equipEvent.unit.unitData.topUnderwear)
equipEvent.unit.unitData.topUnderwear.SetActive(false);
}
private void OnUnEquip(UnEquipEvent unEquipEvent)
{
// Show top and bottom underwear if needed
if (parent.armorData.hideBottomUnderwear && unEquipEvent.unit.unitData.bottomUnderwear)
unEquipEvent.unit.unitData.bottomUnderwear.SetActive(true);
if (parent.armorData.hideTopUnderwear && unEquipEvent.unit.unitData.topUnderwear)
unEquipEvent.unit.unitData.topUnderwear.SetActive(true);
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 7908638d19484a3d9134ff20ba78a8e8
timeCreated: 1733943128
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 1106c504dad9d924b848f59a6be3d5a4
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,27 @@
using System.Collections.Generic;
using System.Linq;
using Sirenix.OdinInspector;
using VOID.Generic.Objects.Item;
namespace VOID.Generic.Objects.Container
{
public class ContainerObject : ItemObject
{
[Title("=== Container properties ===")]
public ContainerObjectContent containerContent;
public ContainerObjectEvents containerEvents;
public ContainerObjectState containerState;
protected override List<ObjectComponent> GetObjectComponents()
{
return base.GetObjectComponents()
.Union(new List<ObjectComponent>
{
containerContent,
containerEvents,
containerState
})
.ToList();
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 37f8cee46dd9b8543acc23235bbe540b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 68c775dbd783c454186a68b886426716, type: 3}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,211 @@
using System;
using JetBrains.Annotations;
using Sirenix.OdinInspector;
using UnityEngine;
using VOID.Generic.Dict;
using VOID.Generic.Objects.Abstract.Events;
using VOID.Generic.Objects.Container.Events;
using VOID.Generic.Objects.Item;
using VOID.Generic.Objects.Unit;
using VOID.Generic.Util;
using Object = UnityEngine.Object;
namespace VOID.Generic.Objects.Container
{
[Serializable]
public class ContainerObjectContent : ObjectComponent<ContainerObject>
{
#region Initialize
protected override void SelfInitialize()
{
// Empty GameObject where all items from backpack are "attached"
_content = new GameObject("_content");
_content.transform.parent = parent.gameObject.transform;
_content.transform.localPosition = Vector3.zero;
}
protected override void Initialize()
{
// Instantiate all prefabs
for (var i = 0; i < _items.Length; i++)
{
if (!_items[i]) continue;
var item = _items[i];
_items[i] = null;
// Selected item is ASSET (prefab), we need to instantiate it first
if (!item.gameObject.scene.IsValid())
item = Object.Instantiate(item.gameObject).GetComponent<ItemObject>();
// Instantiate prefab and get references to its GameObject and ItemObject
MoveIn(i, item);
}
Resize();
}
#endregion
private GameObject _content;
// Items in content (list of ItemObjects and their GameObjects)
[SerializeField, DisableInPlayMode] private ItemObject[] _items = Array.Empty<ItemObject>();
public ItemObject[] items => _items;
public void MoveIn(int itemIndex, ItemObject item, UnitObject byWho = null)
{
if (items.Length <= itemIndex)
Resize(itemIndex);
if (items[itemIndex])
{
MoveIn(item, byWho);
return;
}
items[itemIndex] = item;
var moveInEvent = new ContainerMoveInEvent
{
byWho = byWho,
item = item,
slotIndex = itemIndex,
container = parent,
};
parent.containerEvents.onMoveIn.Invoke(moveInEvent);
item.itemEvents.onMovedIntoContainer.Invoke(moveInEvent);
var itemGameObject = item.gameObject;
itemGameObject.transform.parent = _content.transform;
itemGameObject.transform.localPosition = Vector3.zero;
itemGameObject.transform.localRotation = new Quaternion();
item.basicEvents.onRemove.AddListener(OnItemRemove);
Resize();
}
public void MoveIn(ItemObject item, UnitObject byWho = null)
{
// Find first free slot in backpack
var firstFreeIndex = Array.IndexOf(items, null);
// No free slots, we need to resize array
if (firstFreeIndex == -1)
{
firstFreeIndex = items.Length;
Resize();
}
MoveIn(firstFreeIndex, item, byWho);
}
public void MoveOut(int itemIndex, UnitObject byWho = null)
{
var tempMoveOutItem = items[itemIndex];
items[itemIndex].basicEvents.onRemove.RemoveListener(OnItemRemove);
items[itemIndex] = null;
var moveOutEvent = new ContainerMoveOutEvent
{
byWho = byWho,
item = tempMoveOutItem,
slotIndex = itemIndex,
container = parent,
};
parent.containerEvents.onMoveOut.Invoke(moveOutEvent);
tempMoveOutItem.itemEvents.onMovedOutOfContainer.Invoke(moveOutEvent);
var tempItemGameObject = tempMoveOutItem.gameObject;
tempItemGameObject.gameObject.transform.parent = null;
tempItemGameObject.gameObject.transform.position = parent.transform.position;
Resize();
}
public void MoveOut(ItemObject item, UnitObject byWho = null)
{
MoveOut(Array.IndexOf(items, item), byWho);
}
public void Swap(int firstItemIndex, int secondItemIndex, UnitObject byWho = null)
{
Resize(Math.Max(firstItemIndex, secondItemIndex));
(items[firstItemIndex], items[secondItemIndex]) = (items[secondItemIndex], items[firstItemIndex]);
var swapEvent = new ContainerSwapEvent
{
byWho = byWho,
firstSlotIndex = firstItemIndex,
firstItem = items[firstItemIndex],
secondSlotIndex = secondItemIndex,
secondItem = items[secondItemIndex],
};
parent.containerEvents.onSwap.Invoke(swapEvent);
Resize();
}
public void Sort(Func<ItemObject, IComparable> valueGetter, SortDirectionType sortDirection, [CanBeNull] UnitObject byWho = null) {
ItemObjectSortUtil.Sort(ref _items, valueGetter, sortDirection);
var containerSortEvent = new ContainerSortEvent {
container = parent,
byUnit = byWho
};
parent.containerEvents.onSort.Invoke(containerSortEvent);
Resize();
}
private void OnItemRemove(RemoveEvent removeEvent)
{
var removedItem = removeEvent.obj as ItemObject;
MoveOut(removedItem);
}
public void Resize(int minSize = 0, int rowSize = 10)
{
var beforeSlotCount = items.Length;
var lastItemIndex = 0;
// Find last slotIndex with existing item (not null)
for (var i = beforeSlotCount - 1; i >= 0; i--)
{
lastItemIndex = i;
if (items[i] is not null) break;
}
// Count how many slots backpack will have after resize
var afterSlotCount = Mathf.CeilToInt((Mathf.Max(lastItemIndex, minSize) + rowSize) / (float)rowSize) * rowSize;
// Size not changed, do nothing
if (beforeSlotCount == afterSlotCount) return;
// Resize backpack's arrays
var tempItems = items;
Array.Resize(ref tempItems, afterSlotCount);
_items = tempItems;
var containerResizeEvent = new ContainerResizeEvent
{
container = parent,
beforeSlotCount = beforeSlotCount,
afterSlotCount = afterSlotCount,
lastItemIndex = lastItemIndex,
};
parent.containerEvents.onResize.Invoke(containerResizeEvent);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 15d9b66f28cc25b43b63a1f5e103fc3e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,19 @@
using Sirenix.OdinInspector;
using UnityEngine.Events;
using VOID.Generic.Objects.Container.Events;
namespace VOID.Generic.Objects.Container
{
[System.Serializable]
public class ContainerObjectEvents : ObjectComponent<ContainerObject>
{
[Title("Usage")]
public UnityEvent<ContainerCloseEvent> onClose;
public UnityEvent<ContainerOpenEvent> onOpen;
public UnityEvent<ContainerMoveInEvent> onMoveIn;
public UnityEvent<ContainerMoveOutEvent> onMoveOut;
public UnityEvent<ContainerSwapEvent> onSwap;
public UnityEvent<ContainerResizeEvent> onResize;
public UnityEvent<ContainerSortEvent> onSort;
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: eb8542ecd6532ad409c44825793bab9f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,51 @@
using Sirenix.Utilities;
using System;
using System.Collections.Generic;
using VOID.Generic.Objects.Container;
using VOID.Generic.Objects.Container.Events;
using VOID.Generic.Objects.Item.Events;
using VOID.Generic.Objects.Unit;
namespace VOID.Generic.Objects.Item
{
[Serializable]
public class ContainerObjectState : ObjectComponent<ContainerObject>
{
#region Initialize
protected override void EventInitialize()
{
parent.containerEvents.onOpen.AddListener(OnOpen);
parent.containerEvents.onClose.AddListener(OnClose);
parent.itemEvents.onPickedAfter.AddListener(OnPick);
}
#endregion
public List<UnitObject> openedBy { get; private set; } = new();
private void OnOpen(ContainerOpenEvent containerOpenEvent)
{
openedBy.Add(containerOpenEvent.openedBy);
}
private void OnClose(ContainerCloseEvent containerCloseEvent)
{
openedBy.Remove(containerCloseEvent.closedBy);
}
private void OnPick(PickEvent pickEvent)
{
Array.FindAll(parent.containerContent.items, item => item != null).ForEach(item =>
{
var itemPickEvent = new PickEvent
{
item = item,
unit = pickEvent.unit
};
item.itemEvents.onPickedAfter.Invoke(itemPickEvent);
});
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: b35b3ac08e39415b9f1e00545c767359
timeCreated: 1694902221
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 2fc349196cde3db4aaaff97ae6ba8d1e
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,11 @@
using VOID.Generic.Objects.Abstract.Events;
using VOID.Generic.Objects.Unit;
namespace VOID.Generic.Objects.Container.Events
{
public class ContainerCloseEvent : AbstractEvent
{
public ContainerObject container;
public UnitObject closedBy;
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 70372499eaf8ddf40baa8eb28c12de8a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,14 @@
using VOID.Generic.Objects.Abstract.Events;
using VOID.Generic.Objects.Item;
using VOID.Generic.Objects.Unit;
namespace VOID.Generic.Objects.Container.Events
{
public class ContainerMoveInEvent : AbstractEvent
{
public ContainerObject container;
public ItemObject item;
public UnitObject byWho;
public int slotIndex;
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f13301de95085544aa495fd5f4fe1ecf
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,14 @@
using VOID.Generic.Objects.Abstract.Events;
using VOID.Generic.Objects.Item;
using VOID.Generic.Objects.Unit;
namespace VOID.Generic.Objects.Container.Events
{
public class ContainerMoveOutEvent : AbstractEvent
{
public ContainerObject container;
public ItemObject item;
public UnitObject byWho;
public int slotIndex;
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: be8a0191932d5b149af6d43b2c3a2be6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,11 @@
using VOID.Generic.Objects.Abstract.Events;
using VOID.Generic.Objects.Unit;
namespace VOID.Generic.Objects.Container.Events
{
public class ContainerOpenEvent : AbstractEvent
{
public ContainerObject container;
public UnitObject openedBy;
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a0c16043a285e284d9402cfa592c760c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,12 @@
using VOID.Generic.Objects.Abstract.Events;
namespace VOID.Generic.Objects.Container.Events
{
public class ContainerResizeEvent : AbstractEvent
{
public ContainerObject container;
public int beforeSlotCount;
public int afterSlotCount;
public int lastItemIndex;
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8963991c7bd010b41be0dfeb46facce8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,12 @@
using JetBrains.Annotations;
using VOID.Generic.Objects.Abstract.Events;
using VOID.Generic.Objects.Unit;
namespace VOID.Generic.Objects.Container.Events
{
public class ContainerSortEvent : AbstractEvent
{
public ContainerObject container;
[CanBeNull] public UnitObject byUnit;
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: d44467820dd6ab94b9f2b723623d5288
@@ -0,0 +1,16 @@
using VOID.Generic.Objects.Abstract.Events;
using VOID.Generic.Objects.Item;
using VOID.Generic.Objects.Unit;
namespace VOID.Generic.Objects.Container.Events
{
public class ContainerSwapEvent : AbstractEvent
{
public ContainerObject container;
public UnitObject byWho;
public int firstSlotIndex;
public ItemObject firstItem;
public int secondSlotIndex;
public ItemObject secondItem;
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ba97578f98b3599488f085ee67819676
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 3776533cdfcb4f0283766b4f3ee1edfe
timeCreated: 1707831925
@@ -0,0 +1,81 @@
using System.Collections.Generic;
using System.Linq;
using Sirenix.OdinInspector;
using UnityEngine;
using VOID.Generic.Objects.Abstract;
using VOID.Generic.Objects.Door.Events;
using VOID.Generic.Objects.Unit;
namespace VOID.Generic.Objects.Door
{
[RequireComponent(typeof(Animator))]
public class DoorObject : AbstractObject
{
[Title("=== Door properties ===")]
public DoorObjectEvents doorEvents;
public DoorObjectState doorState;
public DoorObjectAnimator doorAnimator;
protected new void OnValidate()
{
base.OnValidate();
gameObject.GetComponent<Animator>().hideFlags = HideFlags.NotEditable;
}
protected override List<ObjectComponent> GetObjectComponents()
{
return base.GetObjectComponents()
.Union(new List<ObjectComponent>
{
doorEvents,
doorState,
doorAnimator
})
.ToList();
}
[Button]
public void Open(UnitObject unit = null)
{
if (doorState.isLocked) return;
doorEvents.onOpen.Invoke(new DoorEvent
{
door = this,
unit = unit
});
}
[Button]
public void Close(UnitObject unit = null)
{
doorEvents.onClose.Invoke(new DoorEvent
{
door = this,
unit = unit
});
}
[Button]
public void Lock(UnitObject unit = null)
{
if (doorState.isOpen) return;
doorEvents.onLock.Invoke(new DoorEvent
{
door = this,
unit = unit
});
}
[Button]
public void Unlock(UnitObject unit = null)
{
doorEvents.onUnlock.Invoke(new DoorEvent
{
door = this,
unit = unit
});
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 134e091633404623a85e54fea54b3651
timeCreated: 1707831925
@@ -0,0 +1,37 @@
using Sirenix.OdinInspector;
using UnityEditor.Animations;
using UnityEngine;
namespace VOID.Generic.Objects.Door
{
[System.Serializable]
public class DoorObjectAnimator : ObjectComponent<DoorObject>
{
#region Initialize
protected override void SelfInitialize()
{
_animator = parent.GetComponent<Animator>();
_animator.runtimeAnimatorController = Object.Instantiate(animatorController);
}
#endregion
private static readonly int TriggerOpen = Animator.StringToHash("TRIGGER_OPEN");
private static readonly int TriggerClose = Animator.StringToHash("TRIGGER_CLOSE");
private Animator _animator;
[SerializeField, Required] private AnimatorController animatorController;
public void PlayOpen()
{
_animator.SetTrigger(TriggerOpen);
}
public void PlayClose()
{
_animator.SetTrigger(TriggerClose);
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 38f56c92901e4ff18f207fcdbb536a76
timeCreated: 1707845796
@@ -0,0 +1,17 @@
using System;
using Sirenix.OdinInspector;
using UnityEngine.Events;
using VOID.Generic.Objects.Door.Events;
namespace VOID.Generic.Objects.Door
{
[Serializable]
public class DoorObjectEvents : ObjectComponent<DoorObject>
{
[Title("Opening & Closing")]
public UnityEvent<DoorEvent> onOpen;
public UnityEvent<DoorEvent> onClose;
public UnityEvent<DoorEvent> onLock;
public UnityEvent<DoorEvent> onUnlock;
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 647f2a1fd449473fa329598a924293c2
timeCreated: 1707834284
@@ -0,0 +1,86 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Sirenix.OdinInspector;
using UnityEngine;
using UnityEngine.AI;
using VOID.Generic.Navigation;
using VOID.Generic.Objects.Door.Events;
using VOID.Generic.Objects.Door.State;
namespace VOID.Generic.Objects.Door
{
[Serializable]
public class DoorObjectState : ObjectComponent<DoorObject>
{
#region Initialize
protected override void SelfInitialize()
{
_doorObstacles = parent.GetComponents<NavMeshObstacle>().ToList();
parent.GetComponentInChildren<DoorOpenerTrigger>().door = parent;
}
protected override void EventInitialize()
{
parent.doorEvents.onOpen.AddListener(OnOpen);
parent.doorEvents.onClose.AddListener(OnClose);
parent.doorEvents.onLock.AddListener(OnLock);
parent.doorEvents.onUnlock.AddListener(OnUnlock);
}
protected override void Initialize()
{
if (isOpen)
{
parent.Unlock();
parent.Open();
return;
}
if (isLocked)
{
parent.Close();
parent.Lock();
return;
}
parent.Close();
parent.Unlock();
}
#endregion
private List<NavMeshObstacle> _doorObstacles;
[DisableInPlayMode] public bool isOpen;
[DisableInPlayMode] public bool isLocked;
private void OnOpen(DoorEvent doorEvent)
{
isOpen = true;
parent.doorAnimator.PlayOpen();
}
private void OnClose(DoorEvent doorEvent)
{
isOpen = false;
parent.doorAnimator.PlayClose();
}
private void OnLock(DoorEvent doorEvent)
{
isLocked = true;
_doorObstacles.ForEach(obstacle => obstacle.enabled = true);
NavigationManager.current.UpdateNavMesh(new Bounds(parent.transform.position, Vector3.one * parent.basicData.radius));
}
private void OnUnlock(DoorEvent doorEvent)
{
isLocked = false;
_doorObstacles.ForEach(obstacle => obstacle.enabled = false);
NavigationManager.current.UpdateNavMesh(new Bounds(parent.transform.position, Vector3.one * parent.basicData.radius));
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: b3f06f11936447ab873d886285686e5f
timeCreated: 1707831925
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 1bf4fd5ef34247ffb5c5ec67428bb145
timeCreated: 1707834322
@@ -0,0 +1,11 @@
using VOID.Generic.Objects.Abstract.Events;
using VOID.Generic.Objects.Unit;
namespace VOID.Generic.Objects.Door.Events
{
public class DoorEvent : AbstractEvent
{
public DoorObject door;
public UnitObject unit;
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 4fbbff99398b4b66a564e241909a66fc
timeCreated: 1707835249
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 3885ec636a8640d0bac953c4a2e80f4a
timeCreated: 1707919778
@@ -0,0 +1,34 @@
using UnityEngine;
using VOID.Generic.Objects.Abstract;
using VOID.Generic.Objects.Unit;
using VOID.Generic.Triggers;
namespace VOID.Generic.Objects.Door.State
{
public class DoorOpenerTrigger : MonoBehaviour, IDynamicTrigger
{
#region ParentGetterSetter
private DoorObject _door;
public DoorObject door
{
get => _door;
set
{
if (!_door) _door = value;
else Debug.LogWarning("Trying to set parent object " + _door.name + " again.");
}
}
#endregion
public void OnObjectEnter(AbstractObject obj)
{
if (obj is UnitObject && !door.doorState.isOpen) door.Open();
}
public void OnObjectExit(AbstractObject obj)
{
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: abf38a00ee3f4f50bcd018cd92d5034c
timeCreated: 1707919809
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: afce3a8b046945fcbee86c21495a8640
timeCreated: 1664306044
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: d23037a424044e309cd5d9d8888f073d
timeCreated: 1670860447
@@ -0,0 +1,13 @@
using VOID.Generic.Objects.Abstract.Events;
using VOID.Generic.Objects.Unit;
namespace VOID.Generic.Objects.Item.Events
{
public class DropEvent : AbstractEvent
{
public bool prevented = false;
public ItemObject item;
public UnitObject unit;
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: e203310941f54d02b47cef3f9e8c20d4
timeCreated: 1670866592
@@ -0,0 +1,14 @@
using UnityEngine;
using VOID.Generic.Objects.Abstract.Events;
using VOID.Generic.Objects.Unit;
namespace VOID.Generic.Objects.Item.Events
{
public class MoveItemEvent : AbstractEvent
{
public ItemObject item;
public UnitObject unit;
public Vector3 fromPosition;
public Vector3 toPosition;
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a453865967934a0a89b000580d5ac9c4
timeCreated: 1694902221
@@ -0,0 +1,13 @@
using VOID.Generic.Objects.Abstract.Events;
using VOID.Generic.Objects.Unit;
namespace VOID.Generic.Objects.Item.Events
{
public class PickEvent : AbstractEvent
{
public bool prevented = false;
public ItemObject item;
public UnitObject unit;
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6fb2036978d04f1791b5c913cdca486e
timeCreated: 1670862299
@@ -0,0 +1,92 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Sirenix.OdinInspector;
using UnityEngine;
using VOID.Generic.Objects.Abstract;
namespace VOID.Generic.Objects.Item
{
public class ItemObject : AbstractObject
{
[Title("=== ItemObject properties ===")]
public ItemObjectData itemData;
public ItemObjectEvents itemEvents;
public ItemObjectState itemState;
protected override List<ObjectComponent> GetObjectComponents()
{
return base.GetObjectComponents()
.Union(new List<ObjectComponent>
{
itemData,
itemEvents,
itemState
})
.ToList();
}
/// <summary>
/// Moves current item to given position
/// </summary>
/// <returns>TRUE if item can be moved</returns>
public bool Move(Vector3 moveTo)
{
// TODO: póki co przenoszenie za pomocą "teleportacji", kiedyś dorobić ładny ruch przedmiotu do tego miejsca
Debug.LogWarning("TODO: Action MoveItem: item teleported");
transform.position = moveTo;
transform.rotation = Quaternion.Euler(0, transform.rotation.eulerAngles.y, 0);
return true;
}
public bool CanStackWith(ItemObject otherItem) => CanStackWith(otherItem, out _);
public bool CanStackWith(ItemObject otherItem, out bool thisItemWillBeRemoved)
{
thisItemWillBeRemoved = false;
if (this == otherItem) return false;
if (!otherItem) return false;
if (itemData.uniqueId != otherItem.itemData.uniqueId) return false;
if (!itemData.stackable) return false;
if (!otherItem.itemData.stackable) return false;
if (itemData.stackSize + otherItem.itemData.stackSize > itemData.stackSizeMax) thisItemWillBeRemoved = true;
return true;
}
public void StackWith(ItemObject otherItem) => StackWith(otherItem, out _);
public void StackWith(ItemObject otherItem, out bool thisItemWillBeRemoved)
{
if (this == otherItem)
throw new Exception("Trying to stack with itself!");
if (!otherItem)
throw new Exception("Other item doesn't exist!");
if (itemData.uniqueId != otherItem.itemData.uniqueId)
throw new Exception("Trying to stack with item having different unique id!");
if (!itemData.stackable)
throw new Exception("This item is not stackable!");
if (!otherItem.itemData.stackable)
throw new Exception("other item is not stackable!");
var sum = itemData.stackSize + otherItem.itemData.stackSize;
var overflow = sum - itemData.stackSizeMax;
if (overflow > 0)
{
thisItemWillBeRemoved = false;
otherItem.itemData.stackSize = itemData.stackSizeMax;
itemData.stackSize = overflow;
}
else
{
thisItemWillBeRemoved = true;
otherItem.itemData.stackSize = sum;
Remove();
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c6e9588e995e3fb43964239ffbbd8d13
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: ae27aa9e9c30de644ba5cf18b511d34a, type: 3}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,34 @@
using System;
using Sirenix.OdinInspector;
using VOID.ScriptableObjects;
namespace VOID.Generic.Objects.Item
{
[Serializable]
[TypeInfoBox("Most values can be changed only in main prefab!")]
public class ItemObjectData : ObjectComponent<ItemObject>
{
[Title("Uniqueness")]
[EnableIn(PrefabKind.Regular)] public string uniqueId = Guid.NewGuid().ToString();
[Title("Display in UI")]
public string finalName => parent.basicData.name + (stackable ? $" ({stackSize})" : "");
public float finalWeight => stackable ? stackSize * weight : weight;
public int finalValue => stackable ? stackSize * value : value;
[Title("Possible actions")]
[EnableIn(PrefabKind.Regular)] public bool canBePicked = true;
[EnableIn(PrefabKind.Regular)] public bool canBeMoved = true;
[Title("Item base stats")]
[EnableIn(PrefabKind.Regular)] public ItemQuality quality;
[EnableIn(PrefabKind.Regular), MinValue(0)] public float weight = 1;
[EnableIn(PrefabKind.Regular), MinValue(0)] public int value = 0;
[Title("Stacking")]
[InfoBox("Stackable only available if both items have identical uniqueId.")]
[EnableIn(PrefabKind.Regular)] public bool stackable = false;
[ShowIf("stackable"), MinValue(1), MaxValue(nameof(stackSizeMax))] public int stackSize = 1;
[EnableIn(PrefabKind.Regular), ShowIf("stackable"), MinValue(1)] public int stackSizeMax = 1;
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d460d4d8409dc784c8328d2bcd40ee8f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Some files were not shown because too many files have changed in this diff Show More