using Sirenix.OdinInspector; using UnityEngine; using VOID.Generic.Dict; using VOID.Generic.Objects.Abstract; using VOID.Generic.Objects.Unit.Data; using VOID.Generic.Objects.Unit.Events; using VOID.Generic.Objects.Weapon; namespace VOID.Generic.Objects.Unit { /// /// Contain and manages all generic data needed and used by or its children. /// [System.Serializable] public class UnitObjectData : ObjectComponent { #region Initialize protected override void SelfInitialize() { // Instantiate stats baseMaxResources = baseMaxResources with {}; maxResources = maxResources with {}; currentResources = currentResources with {}; baseMainAttributes = baseMainAttributes with {}; mainAttributes = mainAttributes with {}; baseSubAttributes = baseSubAttributes with {}; subAttributes = subAttributes with {}; } protected override void EventInitialize() { RegisterUpdateWeaponRelatedAttributes(); } #endregion #region Events private void RegisterUpdateWeaponRelatedAttributes() { parent.unitEvents.onEquipmentEquip.AddListener(equipEvent => { if (equipEvent.wearable is WeaponObject) UpdateWeaponRelatedAttributes(); }); parent.unitEvents.onEquipmentUnEquip.AddListener(equipEvent => { if (equipEvent.wearable is WeaponObject) UpdateWeaponRelatedAttributes(); }); } /// /// When changing weapons also inherit 's damage and critical attributes. /// private void UpdateWeaponRelatedAttributes() { var mainWeapon = parent.unitEquipment.GetEquipped(EquipmentSlotType.MainHand) as WeaponObject; var offWeapon = parent.unitEquipment.GetEquipped(EquipmentSlotType.OffHand) as WeaponObject; if (mainWeapon) { baseSubAttributes.damageMin = mainWeapon.weaponData.damageMin; baseSubAttributes.damageMax = mainWeapon.weaponData.damageMax; baseSubAttributes.criticalDamageChance = mainWeapon.weaponData.criticalDamageChange; baseSubAttributes.criticalDamageMultiplier = mainWeapon.weaponData.criticalDamageMultiplier; if (offWeapon) { baseSubAttributes.damageMin += offWeapon.weaponData.damageMin; baseSubAttributes.damageMax += offWeapon.weaponData.damageMax; } } else if (offWeapon) { baseSubAttributes.damageMin = offWeapon.weaponData.damageMin; baseSubAttributes.damageMax = offWeapon.weaponData.damageMax; baseSubAttributes.criticalDamageChance = offWeapon.weaponData.criticalDamageChange; baseSubAttributes.criticalDamageMultiplier = offWeapon.weaponData.criticalDamageMultiplier; } else { baseSubAttributes.damageMin = 1; baseSubAttributes.damageMax = 1; baseSubAttributes.criticalDamageChance = 0; baseSubAttributes.criticalDamageMultiplier = 1; } // Recalc those attributes parent.unitDataCalculator.Queue(SubAttributeType.DamageMin); parent.unitDataCalculator.Queue(SubAttributeType.DamageMax); parent.unitDataCalculator.Queue(SubAttributeType.CriticalDamageChance); parent.unitDataCalculator.Queue(SubAttributeType.CriticalDamageMultiplier); } #endregion [Title("Possible actions")] public bool canBeTalked; [Title("Possible actions to do")] public bool canMove = true; public bool canAttack = true; public bool canUse = true; public bool canTalk = true; public bool canTake = true; public bool canInspect = true; [Title("Unit Resources")] public UnitResources baseMaxResources; [ReadOnly] public UnitResources maxResources; [ReadOnly] public UnitResources currentResources; [Title("Main Attributes")] public MainAttributes baseMainAttributes; [ReadOnly] public MainAttributes mainAttributes; [Title("Sub Attributes")] public SubAttributes baseSubAttributes; [ReadOnly] public SubAttributes subAttributes; [Title("Interaction")] [MinValue(1f)] public float useRange = 1f; [MinValue(1f)] public float talkRange = 2f; [MinValue(1f)] public float takeRange = 2f; [MinValue(1f)] public float inspectRange = 20f; [Title("Offset positions")] [Required] public Transform castPosition; [Required] public Transform ladderPosition; [Required] public Transform rightHandPosition; [Required] public Transform leftHandPosition; [Title("Visual")] public GameObject topUnderwear; public GameObject bottomUnderwear; /// /// 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 dont have enough of it /// Returns TRUE if done successfully. public bool UseResource(UnitResourceType 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.unitEvents.onCurrentResourceChange.Invoke(new UnitResourceChangeEvent { unit = 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(UnitResourceType 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(UnitResourceType 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); } } }