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,23 @@
using System;
using System.Collections.Generic;
using Sirenix.OdinInspector;
namespace VOID.Generic.DropTable
{
[Serializable]
public class DropTable
{
[BoxGroup]
[MinValue(1)]
[InfoBox("How many times random group will taken. Groups can be taken multiple times unless limit provided.")]
public int count = 1;
[BoxGroup]
[RequiredListLength(MinLength = 1)]
[HideReferenceObjectPicker]
[ListDrawerSettings(CustomAddFunction = nameof(AddGroup))]
public List<DropTableGroup> groups = new();
private DropTableGroup AddGroup() => new();
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: b5fc0efb0a7b41e58970b8abe14100c5
timeCreated: 1717678849
@@ -0,0 +1,162 @@
using System.Collections.Generic;
using System.Linq;
using Sirenix.OdinInspector;
using UnityEngine;
using UnityEngine.AI;
using VOID.Generic.Objects.Abstract;
using VOID.Generic.Objects.Abstract.Events;
using VOID.Generic.Objects.Container;
using VOID.Generic.Objects.Item;
using VOID.Generic.Objects.Item.Events;
using VOID.Generic.Objects.Unit;
using VOID.Generic.Util;
namespace VOID.Generic.DropTable
{
public class DropTableComponent : MonoBehaviour
{
// Serialized properties
[InfoBox("<u><b>OnSpawn</b></u> gives items instantly to target, but works only on Unit and Container\n" +
"<u><b>OnDeath</b></u> gives or spawns when target dies, works on any object")]
[SerializeField, EnumToggleButtons] private DropTableTrigger _trigger;
[SerializeField, HideLabel, Title("Drop Table")] private MultiSourceWrapper<DropTable> _dropTable;
// Public accessors
public DropTableTrigger trigger => _trigger;
public DropTable dropTable => _dropTable.value;
// Cached object attached to
private AbstractObject _obj;
/// <summary>
/// Start listening for attached object events.
/// If object already spawned and OnSpawn selected then run immediately
/// </summary>
private void Start()
{
_obj = GetComponent<AbstractObject>();
if (_trigger is DropTableTrigger.OnSpawn)
{
if (_obj.didStart)
{
OnSpawn();
}
else
{
_obj.basicEvents.onSpawn.AddListener(OnSpawn);
}
}
if (_trigger is DropTableTrigger.OnDeath)
{
_obj.basicEvents.onDeathAfter.AddListener(OnDeath);
}
}
/// <summary>
/// Return randomized items from given DropTable
/// </summary>
/// <returns></returns>
private List<ItemObject> GetRandomItemsFromDropTable()
{
var itemList = new List<ItemObject>();
var groups = _dropTable.value.groups.ToList();
var groupCounter = new Dictionary<DropTableGroup, int>();
for (var i = 0; i < _dropTable.value.count; i++)
{
var randomGroup = RandomUtil.RandomElementByWeight(groups, group => group.weight);
itemList.AddRange(randomGroup.items);
if (!randomGroup.isLimited) continue;
groupCounter.TryAdd(randomGroup, 0);
groupCounter[randomGroup]++;
if (groupCounter[randomGroup] < randomGroup.limit) continue;
groups.Remove(randomGroup);
}
return itemList;
}
/// <summary>
/// Run when attached object spawn
/// </summary>
private void OnSpawn()
{
_obj.basicEvents.onSpawn.RemoveListener(OnSpawn);
if (_obj is UnitObject unitObject)
{
GetRandomItemsFromDropTable().ForEach(item => GiveItemToUnit(item, unitObject));
return;
}
if (_obj is ContainerObject containerObject)
{
GetRandomItemsFromDropTable().ForEach(item => GiveItemToContainer(item, containerObject));
return;
}
Debug.LogError($"{_obj.GetType()} can't contain items! Selected trigger won't work!");
}
/// <summary>
/// Run when attached object die
/// </summary>
private void OnDeath(DeathEvent deathEvent)
{
_obj.basicEvents.onDeathAfter.RemoveListener(OnDeath);
if (_obj is UnitObject unitObject)
{
GetRandomItemsFromDropTable().ForEach(item => GiveItemToUnit(item, unitObject));
return;
}
GetRandomItemsFromDropTable().ForEach(item => DropItemFromObject(item, _obj));
}
/// <summary>
/// Instantiate given item prefab and put directly to attached unit's backpack
/// </summary>
private void GiveItemToUnit(ItemObject item, UnitObject unit)
{
var newItemGameObject = Instantiate(item.gameObject);
var newItem = newItemGameObject.GetComponent<ItemObject>();
var pickEvent = new PickEvent
{
item = newItem,
unit = unit
};
newItem.itemEvents.onPickedBefore.Invoke(pickEvent);
newItem.itemEvents.onPickedAfter.Invoke(pickEvent);
unit.unitBackpack.Take(newItem);
}
/// <summary>
/// Instantiate given item prefab and put directly to attached container's content
/// </summary>
private void GiveItemToContainer(ItemObject item, ContainerObject container)
{
var newItemGameObject = Instantiate(item.gameObject);
var newItem = newItemGameObject.GetComponent<ItemObject>();
container.containerContent.MoveIn(newItem);
}
/// <summary>
/// Instantiate given item prefab and "pop" it randomly near attached object
/// </summary>
private void DropItemFromObject(ItemObject item, AbstractObject obj)
{
const float dropDistance = 1f;
var newItemGameObject = Instantiate(item, obj.transform.position, obj.transform.rotation);
var newItem = newItemGameObject.GetComponent<ItemObject>();
NavMesh.SamplePosition(obj.transform.position + Random.insideUnitSphere, out var hit, dropDistance, NavAreaManager.Walkable);
if (hit.hit) newItem.Move(hit.position);
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 3d8541f0412245ec98f426ec64159e5b
timeCreated: 1717614671
@@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using Sirenix.OdinInspector;
using VOID.Generic.Objects.Item;
namespace VOID.Generic.DropTable
{
[Serializable]
public class DropTableGroup
{
[AssetsOnly]
[RequiredListLength(MinLength = 1)]
public List<ItemObject> items = new();
[MinValue(0)]
public float weight = 1;
[HorizontalGroup]
[OnValueChanged(nameof(OnIsLimitedChanged))]
public bool isLimited;
[HorizontalGroup]
[HideLabel]
[EnableIf(nameof(isLimited))]
[MinValue(1)]
public int limit = 1;
private void OnIsLimitedChanged()
{
limit = isLimited ? 1 : 9999;
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: e58aaa821f4c4e94948ef6ad29f83911
timeCreated: 1717614205
@@ -0,0 +1,8 @@
namespace VOID.Generic.DropTable
{
public enum DropTableTrigger
{
OnSpawn,
OnDeath
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a8b483b8d269465ca8bce72cb441f116
timeCreated: 1717681944