init
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user