using System; using System.Collections.Generic; using System.Linq; using NUnit.Framework; using Sirenix.Utilities; using Test.Util; using UnityEditor; using UnityEngine; using UnityEngine.AI; using VOID.Generic.Dict; using VOID.Generic.Objects.Accessory; using VOID.Generic.Objects.Armor; using VOID.Generic.Objects.Item; using VOID.Generic.Objects.Unit; using VOID.Generic.Objects.Unit.Animations; using VOID.Generic.Objects.Unit.Equipment; using VOID.Generic.Objects.Weapon; using VOID.Generic.Objects.Wearable; namespace Test.EditMode.Prefabs.Generic { public class UnitObjectTest { private List _gameObjects = new(); [OneTimeSetUp] public void Setup() { AssetDatabase.FindAssets($"t:{nameof(GameObject)}").ForEach(gameObjectGuid => { var gameObjectPath = AssetDatabase.GUIDToAssetPath(gameObjectGuid); var gameObject = AssetDatabase.LoadAssetAtPath(gameObjectPath); var unitObjects = gameObject.GetComponentsInChildren(); // If prefab have any ArmorObject - take it, we will test it if (unitObjects.Length > 0) _gameObjects.Add(gameObject); }); } [OneTimeTearDown] public void Cleanup() { _gameObjects?.Clear(); _gameObjects = null; } [Test] public void UnitData_Portrait() { _gameObjects.ForEach(gameObject => { var unitObject = gameObject.GetComponent(); var prefabPath = AssetDatabase.GetAssetPath(gameObject.GetInstanceID()); var prefabPathHyperlink = DebugLogUtil.Hyperlink(prefabPath); if (!unitObject.basicData.image) Debug.LogError($"{nameof(UnitObject)}'s portrait is not selected: {prefabPathHyperlink}", unitObject); if (unitObject.basicData.image.width > unitObject.basicData.image.height) Debug.LogWarning($"{nameof(UnitObject)}'s portrait size proportions are invalid (width > height): {prefabPathHyperlink}"); }); } [Test] public void UnitData_Resources() { _gameObjects.ForEach(gameObject => { var unitObject = gameObject.GetComponent(); var prefabPath = AssetDatabase.GetAssetPath(gameObject.GetInstanceID()); var prefabPathHyperlink = DebugLogUtil.Hyperlink(prefabPath); var currentResources = unitObject.unitData.currentResources; var baseMaxResources = unitObject.unitData.baseMaxResources; Enum.GetValues(typeof(UnitResourceType)) .Cast() .Where(resourceType => currentResources.Get(resourceType) > baseMaxResources.Get(resourceType)) .ForEach(resourceType => Debug.LogError($"{nameof(UnitObject)}'s {resourceType} current value is greater than base max: {prefabPathHyperlink}", unitObject)); }); } [Test] public void UnitData_MainAttributes() { _gameObjects.ForEach(gameObject => { var unitObject = gameObject.GetComponent(); var prefabPath = AssetDatabase.GetAssetPath(gameObject.GetInstanceID()); var prefabPathHyperlink = DebugLogUtil.Hyperlink(prefabPath); var baseMainAttributes = unitObject.unitData.baseMainAttributes; Enum.GetValues(typeof(MainAttributeType)) .Cast() .Where(mainAttributeType => baseMainAttributes.Get(mainAttributeType) < 1) .ForEach(mainAttributeType => Debug.LogError($"{nameof(UnitObject)}'s {mainAttributeType} is lesser than 1: {prefabPathHyperlink}", unitObject)); }); } [Test] public void UnitData_SubAttributes() { // Nothing to test } [Test] public void UnitData_Ranges() { _gameObjects.ForEach(gameObject => { var unitObject = gameObject.GetComponent(); var prefabPath = AssetDatabase.GetAssetPath(gameObject.GetInstanceID()); var prefabPathHyperlink = DebugLogUtil.Hyperlink(prefabPath); var useRange = unitObject.unitData.useRange; var talkRange = unitObject.unitData.talkRange; var takeRange = unitObject.unitData.takeRange; var inspectRange = unitObject.unitData.inspectRange; if (useRange < 1) Debug.LogError($"{nameof(UnitObject)}'s use range is lesser than 1: {prefabPathHyperlink}", unitObject); if (talkRange < 1) Debug.LogError($"{nameof(UnitObject)}'s talk range is lesser than 1: {prefabPathHyperlink}", unitObject); if (takeRange < 1) Debug.LogError($"{nameof(UnitObject)}'s take range is lesser than 1: {prefabPathHyperlink}", unitObject); if (inspectRange < 1) Debug.LogError($"{nameof(UnitObject)}'s inspect range is lesser than 1: {prefabPathHyperlink}", unitObject); }); } [Test] public void UnitData_CastPosition() { _gameObjects.ForEach(gameObject => { var unitObject = gameObject.GetComponent(); var prefabPath = AssetDatabase.GetAssetPath(gameObject.GetInstanceID()); var prefabPathHyperlink = DebugLogUtil.Hyperlink(prefabPath); var castPosition = unitObject.unitData.castPosition; if (!castPosition) Debug.LogError($"{nameof(UnitObject)}'s cast position is not selected: {prefabPathHyperlink}", unitObject); }); } [Test] public void UnitAnimator_Events() { // Nothing to test } [Test] public void UnitAnimator_ActionQueue() { // Nothing to test } [Test] public void UnitAnimator_Animator() { _gameObjects.ForEach(gameObject => { var unitObject = gameObject.GetComponent(); var prefabPath = AssetDatabase.GetAssetPath(gameObject.GetInstanceID()); var prefabPathHyperlink = DebugLogUtil.Hyperlink(prefabPath); var animator = SerializedUtil.GetProperty(unitObject, "unitAnimator.animator"); if (!animator) Debug.LogError($"{nameof(UnitObject)}'s {nameof(UnitObjectAnimator)} have missing {nameof(Animator)}: {prefabPathHyperlink}", unitObject); var animatorCallbacks = SerializedUtil.GetProperty(unitObject, "unitAnimator.unitAnimatorCallbacks"); if (!animatorCallbacks) Debug.LogError($"{nameof(UnitObject)}'s {nameof(UnitObjectAnimator)} have missing {nameof(UnitAnimatorCallbacks)}: {prefabPathHyperlink}", unitObject); }); } [Test] public void UnitNavMeshAgent_NavMeshAgent() { _gameObjects.ForEach(gameObject => { var unitObject = gameObject.GetComponent(); var prefabPath = AssetDatabase.GetAssetPath(gameObject.GetInstanceID()); var prefabPathHyperlink = DebugLogUtil.Hyperlink(prefabPath); var navMeshAgent = SerializedUtil.GetProperty(unitObject, "unitNavMeshAgent.navMeshAgent"); if (navMeshAgent == null) Debug.LogError($"{nameof(UnitObject)}'s {nameof(UnitObjectNavAgent)} have missing {nameof(NavMeshAgent)}: {prefabPathHyperlink}", unitObject); }); } [Test] public void UnitDataCalculator_Formulas_TODO() { // TODO: dodać testy Debug.LogWarning("TODO: zrobić weryfikacje formuł"); _gameObjects.ForEach(gameObject => { }); } [Test] public void UnitBackpack_PredefinedItems() { _gameObjects.ForEach(gameObject => { var unitObject = gameObject.GetComponent(); var prefabPath = AssetDatabase.GetAssetPath(gameObject.GetInstanceID()); var prefabPathHyperlink = DebugLogUtil.Hyperlink(prefabPath); var itemPrefabs = SerializedUtil.GetPropertyArray(unitObject, "unitBackpack.gameObjectItems"); itemPrefabs.ForEach(prefab => { if (!prefab) return; var itemObject = prefab.GetComponent(); if (!itemObject) Debug.LogError( $"{nameof(UnitObject)}'s backpack: prefab '{prefab.name}' is not an {nameof(ItemObject)}: {prefabPathHyperlink}", unitObject); }); }); } [Test] public void UnitEquipment_PredefinedWearables() { var canWearInSlot = new Dictionary> { [EquipmentSlotType.MainHand] = wearable => wearable is WeaponObject, [EquipmentSlotType.OffHand] = wearable => wearable is WeaponObject, [EquipmentSlotType.Helmet] = wearable => wearable is ArmorObject helmet && helmet.armorData.armorType == ArmorType.Helmet, [EquipmentSlotType.Armor] = wearable => wearable is ArmorObject armor && armor.armorData.armorType == ArmorType.Armor, [EquipmentSlotType.Pants] = wearable => wearable is ArmorObject pants && pants.armorData.armorType == ArmorType.Pants, [EquipmentSlotType.Belt] = wearable => wearable is ArmorObject belt && belt.armorData.armorType == ArmorType.Belt, [EquipmentSlotType.Boots] = wearable => wearable is ArmorObject boots && boots.armorData.armorType == ArmorType.Boots, [EquipmentSlotType.Gloves] = wearable => wearable is ArmorObject gloves && gloves.armorData.armorType == ArmorType.Gloves, [EquipmentSlotType.Necklace] = wearable => wearable is AccessoryObject necklace && necklace.accessoryData.accessoryType == AccessoryType.Necklace, [EquipmentSlotType.RingOne] = wearable => wearable is AccessoryObject ring && ring.accessoryData.accessoryType == AccessoryType.Ring, [EquipmentSlotType.RingTwo] = wearable => wearable is AccessoryObject ring && ring.accessoryData.accessoryType == AccessoryType.Ring, }; _gameObjects.ForEach(gameObject => { var unitObject = gameObject.GetComponent(); var prefabPath = AssetDatabase.GetAssetPath(gameObject.GetInstanceID()); var prefabPathHyperlink = DebugLogUtil.Hyperlink(prefabPath); Enum.GetValues(typeof(EquipmentSlotType)) .Cast() .ForEach(equipmentSlotType => { var equipmentSlotName = equipmentSlotType.ToString()[..1].ToLower() + equipmentSlotType.ToString()[1..]; var equippedItem = SerializedUtil.GetProperty(unitObject, $"unitEquipment.{equipmentSlotName}"); if (equippedItem == null || !equippedItem.gameObject) return; var wearableObject = equippedItem.gameObject.GetComponent(); var canBePlaced = canWearInSlot.GetValueOrDefault(equipmentSlotType).Invoke(wearableObject); if (!wearableObject || !canBePlaced) Debug.LogError( $"{nameof(UnitObject)}'s equipment: prefab '{equippedItem.gameObject.name}' can't be placed in {equipmentSlotName}: {prefabPathHyperlink}", unitObject); }); }); } [Test] public void UnitAbilityBook_DefaultAttackAbility() { _gameObjects.ForEach(gameObject => { var unitObject = gameObject.GetComponent(); var prefabPath = AssetDatabase.GetAssetPath(gameObject.GetInstanceID()); var prefabPathHyperlink = DebugLogUtil.Hyperlink(prefabPath); var defaultAttack = unitObject.unitAbilityBook.defaultAttackAbility; if (defaultAttack == null) Debug.LogError( $"{nameof(UnitObject)}'s ability book: default attack ability is not selected: {prefabPathHyperlink}", unitObject); }); } } }