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
{
///
/// Contain and manages all generic data needed and used by or its children.
///
[Serializable]
public class AbstractObjectData : ObjectComponent
{
#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;
///
/// Uses given resource by given amount.
/// That means positive values decreases and negative values increases that resource.
///
/// Resource to use
/// Amount to change
/// If TRUE then we can use this resource even if we don't have enough of it
/// Returns TRUE if done successfully.
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;
}
///
/// Sets given resource to given value.
/// It uses so whole process will be executed as change from starting value to given value.
///
/// Resource type to set
/// Value to set
/// Return TRUE if done successfully.
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);
}
///
/// Sets given resource to percentage of its max value.
/// It uses so whole process will be executed as change from starting value to given value.
///
/// Resource type to set
/// float as percent, value needs to be between 0 and 1
/// Return TRUE if done successfully.
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);
}
}
}