装备系统完结,修复并加入很多
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
|
||||
[CreateAssetMenu(fileName = "NewAllyHero", menuName = "SO_Data/AllyHero")]
|
||||
public class AllyHero_SO : ScriptableObject
|
||||
@@ -24,6 +27,7 @@ public class AllyHero_SO : ScriptableObject
|
||||
public string ally_heroDesignation;
|
||||
public int ally_heroID;
|
||||
public bool isUnlocked;
|
||||
public equipmentSO.EquipmentSkillType allyType;
|
||||
|
||||
[Header("Inspector")]
|
||||
public Sprite ally_heroImage;
|
||||
@@ -129,6 +133,10 @@ public class AllyHero_SO : ScriptableObject
|
||||
[Tooltip("Equipped skill group IDs for this ally. Each int references a skillGroupID defined in skillGroups. Use 0 to indicate empty.")]
|
||||
public int[] equippedSkillGroupIDs = new int[0];
|
||||
|
||||
[Header("Equipments")]
|
||||
public equipmentSO equippedEquipment;
|
||||
public string equippedEquipmentId;
|
||||
|
||||
public SkillDefinition GetPrimarySkill()
|
||||
{
|
||||
if (availableSkills == null || primarySkillIndex < 0 || primarySkillIndex >= availableSkills.Length) return null;
|
||||
@@ -137,11 +145,10 @@ public class AllyHero_SO : ScriptableObject
|
||||
|
||||
public SkillGroup GetPrimarySkillGroup()
|
||||
{
|
||||
if (skillGroups == null || skillGroups.Length == 0) return null;
|
||||
|
||||
if (equippedSkillGroupIDs != null && equippedSkillGroupIDs.Length > 0)
|
||||
int[] runtimeGroupIds = GetEffectiveEquippedSkillGroupIDs();
|
||||
if (runtimeGroupIds != null && runtimeGroupIds.Length > 0)
|
||||
{
|
||||
foreach (int gid in equippedSkillGroupIDs)
|
||||
foreach (int gid in runtimeGroupIds)
|
||||
{
|
||||
if (gid == 0) continue;
|
||||
SkillGroup group = GetSkillGroupByID(gid);
|
||||
@@ -149,9 +156,12 @@ public class AllyHero_SO : ScriptableObject
|
||||
}
|
||||
}
|
||||
|
||||
foreach (SkillGroup group in skillGroups)
|
||||
if (skillGroups != null)
|
||||
{
|
||||
if (group != null) return group;
|
||||
foreach (SkillGroup group in skillGroups)
|
||||
{
|
||||
if (group != null) return group;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -159,12 +169,191 @@ public class AllyHero_SO : ScriptableObject
|
||||
|
||||
public SkillGroup GetSkillGroupByID(int groupID)
|
||||
{
|
||||
if (skillGroups == null || skillGroups.Length == 0) return null;
|
||||
foreach (SkillGroup group in skillGroups)
|
||||
if (skillGroups != null && skillGroups.Length > 0)
|
||||
{
|
||||
if (group != null && group.skillGroupID == groupID) return group;
|
||||
foreach (SkillGroup group in skillGroups)
|
||||
{
|
||||
if (group != null && group.skillGroupID == groupID) return group;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
return EquipmentSkillGroupLibrary.ResolveSkillGroup(groupID);
|
||||
}
|
||||
|
||||
public int[] GetEffectiveEquippedSkillGroupIDs()
|
||||
{
|
||||
var result = new List<int>();
|
||||
var dedupe = new HashSet<int>();
|
||||
int heroSkillSlotsRemaining = GetEffectiveSkillSlotLimit();
|
||||
|
||||
if (equippedSkillGroupIDs != null)
|
||||
{
|
||||
for (int i = 0; i < equippedSkillGroupIDs.Length; i++)
|
||||
{
|
||||
if (heroSkillSlotsRemaining <= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
int groupId = equippedSkillGroupIDs[i];
|
||||
if (groupId <= 0 || !dedupe.Add(groupId))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
result.Add(groupId);
|
||||
heroSkillSlotsRemaining--;
|
||||
}
|
||||
}
|
||||
|
||||
equipmentSO equipment = GetEquippedEquipmentResolved();
|
||||
if (equipment != null)
|
||||
{
|
||||
TryAddEquipmentSkillGroupId(result, dedupe, equipment.sa_skillID);
|
||||
TryAddEquipmentSkillGroupId(result, dedupe, equipment.ia_skillID);
|
||||
}
|
||||
|
||||
return result.ToArray();
|
||||
}
|
||||
|
||||
public int GetEffectiveSkillSlotLimit()
|
||||
{
|
||||
AllyLevelInfo currentLevelInfo = GetEffectiveLevelForCurrentEXP();
|
||||
int slotLimit = currentLevelInfo != null ? Mathf.Max(0, currentLevelInfo.skill_slot_limited) : 0;
|
||||
|
||||
if (HasExclusiveIllusionExtraSlotBonus())
|
||||
{
|
||||
slotLimit += 1;
|
||||
}
|
||||
|
||||
return slotLimit;
|
||||
}
|
||||
|
||||
public AllyLevelInfo GetEffectiveLevelInfoWithEquipment(AllyLevelInfo baseInfo)
|
||||
{
|
||||
if (baseInfo == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
AllyLevelInfo resolved = CloneLevelInfo(baseInfo);
|
||||
resolved.skill_slot_limited = GetEffectiveSkillSlotLimit();
|
||||
|
||||
equipmentSO equipment = GetEquippedEquipmentResolved();
|
||||
if (equipment == null)
|
||||
{
|
||||
return resolved;
|
||||
}
|
||||
|
||||
resolved.maxHP = ApplyIntEquipmentBonus(
|
||||
resolved.maxHP,
|
||||
equipment.maxHp,
|
||||
equipment,
|
||||
equipmentSO.EquipmentSpecialEffectType.MaxHp);
|
||||
resolved.attack = ApplyIntEquipmentBonus(
|
||||
resolved.attack,
|
||||
equipment.attack,
|
||||
equipment,
|
||||
equipmentSO.EquipmentSpecialEffectType.Attack);
|
||||
resolved.maxMana = ApplyIntEquipmentBonus(
|
||||
resolved.maxMana,
|
||||
equipment.maxMana,
|
||||
equipment,
|
||||
equipmentSO.EquipmentSpecialEffectType.MaxMana);
|
||||
resolved.damageResistance = ApplyFloatEquipmentBonus(
|
||||
resolved.damageResistance,
|
||||
equipment.damageResistance,
|
||||
equipment,
|
||||
equipmentSO.EquipmentSpecialEffectType.DamageResistance);
|
||||
resolved.scoreEfficiency = ApplyFloatEquipmentBonus(
|
||||
resolved.scoreEfficiency,
|
||||
equipment.scoreEfficiency,
|
||||
equipment,
|
||||
equipmentSO.EquipmentSpecialEffectType.ScoreEfficiency);
|
||||
|
||||
return resolved;
|
||||
}
|
||||
|
||||
private bool HasExclusiveIllusionExtraSlotBonus()
|
||||
{
|
||||
equipmentSO equipment = GetEquippedEquipmentResolved();
|
||||
if (equipment == null || equipment.ia_skillID != 30021007)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
AllyHero_SO winner = ResolveExclusiveIllusionExtraSlotOwner();
|
||||
return winner != null && winner.ally_heroID == ally_heroID;
|
||||
}
|
||||
|
||||
private static AllyHero_SO ResolveExclusiveIllusionExtraSlotOwner()
|
||||
{
|
||||
AllyHero_SO[] heroes = LoadAllHeroAssetsForEquipmentChecks();
|
||||
if (heroes == null || heroes.Length == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
AllyHero_SO selected = null;
|
||||
for (int i = 0; i < heroes.Length; i++)
|
||||
{
|
||||
AllyHero_SO hero = heroes[i];
|
||||
if (hero == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
hero.LoadEquippedEquipmentFromLocal();
|
||||
equipmentSO equipped = hero.GetEquippedEquipmentResolved();
|
||||
if (equipped == null || equipped.ia_skillID != 30021007)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (selected == null
|
||||
|| hero.ally_heroID < selected.ally_heroID
|
||||
|| (hero.ally_heroID == selected.ally_heroID
|
||||
&& string.CompareOrdinal(hero.ally_heroName ?? string.Empty, selected.ally_heroName ?? string.Empty) < 0))
|
||||
{
|
||||
selected = hero;
|
||||
}
|
||||
}
|
||||
|
||||
return selected;
|
||||
}
|
||||
|
||||
private static AllyHero_SO[] LoadAllHeroAssetsForEquipmentChecks()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
if (!Application.isPlaying)
|
||||
{
|
||||
string[] guids = AssetDatabase.FindAssets("t:AllyHero_SO", new[] { "Assets/Resources/so/ally" });
|
||||
var heroes = new List<AllyHero_SO>(guids.Length);
|
||||
for (int i = 0; i < guids.Length; i++)
|
||||
{
|
||||
string path = AssetDatabase.GUIDToAssetPath(guids[i]);
|
||||
AllyHero_SO hero = AssetDatabase.LoadAssetAtPath<AllyHero_SO>(path);
|
||||
if (hero != null)
|
||||
{
|
||||
heroes.Add(hero);
|
||||
}
|
||||
}
|
||||
|
||||
return heroes.ToArray();
|
||||
}
|
||||
#endif
|
||||
|
||||
return Resources.LoadAll<AllyHero_SO>("so/ally");
|
||||
}
|
||||
|
||||
private static void TryAddEquipmentSkillGroupId(List<int> result, HashSet<int> dedupe, int groupId)
|
||||
{
|
||||
if (groupId <= 0 || result == null || dedupe == null || !dedupe.Add(groupId))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
result.Add(groupId);
|
||||
}
|
||||
|
||||
public AllyLevelInfo GetEffectiveLevelForCurrentEXP()
|
||||
@@ -190,17 +379,119 @@ public class AllyHero_SO : ScriptableObject
|
||||
return sorted[unlockedTierIndex];
|
||||
}
|
||||
|
||||
private AllyLevelInfo CloneLevelInfo(AllyLevelInfo source)
|
||||
{
|
||||
return new AllyLevelInfo
|
||||
{
|
||||
levelName = source.levelName,
|
||||
levelID = source.levelID,
|
||||
attack = source.attack,
|
||||
maxHP = source.maxHP,
|
||||
damageResistance = source.damageResistance,
|
||||
maxMana = source.maxMana,
|
||||
scoreEfficiency = source.scoreEfficiency,
|
||||
requiredEXP = source.requiredEXP,
|
||||
skill_slot_limited = source.skill_slot_limited,
|
||||
manaGainGood = source.manaGainGood,
|
||||
manaGainGreat = source.manaGainGreat,
|
||||
manaGainPerfect = source.manaGainPerfect,
|
||||
manaGainOnMiss = source.manaGainOnMiss,
|
||||
damageMultiplierGood = source.damageMultiplierGood,
|
||||
damageMultiplierGreat = source.damageMultiplierGreat,
|
||||
damageMultiplierPerfect = source.damageMultiplierPerfect,
|
||||
missHpLossBase = source.missHpLossBase
|
||||
};
|
||||
}
|
||||
|
||||
private int ApplyIntEquipmentBonus(int baseValue, equipmentSO.EquipmentStatTuning tuning, equipmentSO equipment, equipmentSO.EquipmentSpecialEffectType effectType)
|
||||
{
|
||||
float percent = GetEquipmentPercentBonus(tuning, equipment, effectType);
|
||||
float flat = GetEquipmentFlatBonus(equipment, effectType);
|
||||
return Mathf.Max(0, Mathf.FloorToInt(baseValue * (1f + percent) + flat));
|
||||
}
|
||||
|
||||
private float ApplyFloatEquipmentBonus(float baseValue, equipmentSO.EquipmentStatTuning tuning, equipmentSO equipment, equipmentSO.EquipmentSpecialEffectType effectType)
|
||||
{
|
||||
float percent = GetEquipmentPercentBonus(tuning, equipment, effectType);
|
||||
float flat = GetEquipmentFlatBonus(equipment, effectType);
|
||||
return Mathf.Max(0f, (baseValue * (1f + percent)) + flat);
|
||||
}
|
||||
|
||||
private float GetEquipmentPercentBonus(equipmentSO.EquipmentStatTuning tuning, equipmentSO equipment, equipmentSO.EquipmentSpecialEffectType effectType)
|
||||
{
|
||||
float total = 0f;
|
||||
if (tuning != null)
|
||||
{
|
||||
if (!Mathf.Approximately(tuning.basicGain, 0f))
|
||||
{
|
||||
total += tuning.basicGain;
|
||||
total += Mathf.Max(0, equipment.level) * tuning.cultivationInterval;
|
||||
}
|
||||
}
|
||||
|
||||
if (equipment.enableTypeSameEffects && equipment.skillType == allyType)
|
||||
{
|
||||
total += SumEffectValues(equipment.typeSameEffects, effectType);
|
||||
}
|
||||
|
||||
total += SumEffectValues(equipment.maxLevelEffects, effectType);
|
||||
return total;
|
||||
}
|
||||
|
||||
private float GetEquipmentFlatBonus(equipmentSO equipment, equipmentSO.EquipmentSpecialEffectType effectType)
|
||||
{
|
||||
float total = 0f;
|
||||
total += SumEffectValues(equipment.specialEffects, effectType);
|
||||
|
||||
equipmentSO.EquipmentSpecialEffect[] normalizedIllusionEffects = equipment.GetNormalizedIllusionEffects();
|
||||
total += SumEffectValues(normalizedIllusionEffects, effectType);
|
||||
return total;
|
||||
}
|
||||
|
||||
private static float SumEffectValues(equipmentSO.EquipmentSpecialEffect[] effects, equipmentSO.EquipmentSpecialEffectType effectType)
|
||||
{
|
||||
if (effects == null || effects.Length == 0)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
|
||||
float total = 0f;
|
||||
for (int i = 0; i < effects.Length; i++)
|
||||
{
|
||||
equipmentSO.EquipmentSpecialEffect effect = effects[i];
|
||||
if (effect == null || effect.effectType != effectType)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
total += effect.value;
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
private class EquippedSkillGroupIDsPayload
|
||||
{
|
||||
public int[] equippedSkillGroupIDs;
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
private class EquippedEquipmentPayload
|
||||
{
|
||||
public string equippedEquipmentId;
|
||||
}
|
||||
|
||||
private string GetEquippedSkillsPrefsKey()
|
||||
{
|
||||
return "ally_equippedSkillGroupIDs_" + ally_heroID;
|
||||
}
|
||||
|
||||
private string GetEquippedEquipmentPrefsKey()
|
||||
{
|
||||
return "ally_equippedEquipment_" + ally_heroID;
|
||||
}
|
||||
|
||||
public void SaveEquippedSkillsToLocal()
|
||||
{
|
||||
var payload = new EquippedSkillGroupIDsPayload { equippedSkillGroupIDs = equippedSkillGroupIDs ?? new int[0] };
|
||||
@@ -220,6 +511,136 @@ public class AllyHero_SO : ScriptableObject
|
||||
equippedSkillGroupIDs = payload.equippedSkillGroupIDs ?? new int[0];
|
||||
}
|
||||
|
||||
public void SaveEquippedEquipmentToLocal()
|
||||
{
|
||||
equippedEquipmentId = equippedEquipment != null ? equippedEquipment.name : string.Empty;
|
||||
var payload = new EquippedEquipmentPayload { equippedEquipmentId = equippedEquipmentId ?? string.Empty };
|
||||
string json = JsonUtility.ToJson(payload);
|
||||
PlayerPrefs.SetString(GetEquippedEquipmentPrefsKey(), json);
|
||||
PlayerPrefs.Save();
|
||||
}
|
||||
|
||||
public void LoadEquippedEquipmentFromLocal()
|
||||
{
|
||||
string key = GetEquippedEquipmentPrefsKey();
|
||||
if (!PlayerPrefs.HasKey(key))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
string json = PlayerPrefs.GetString(key, string.Empty);
|
||||
if (string.IsNullOrEmpty(json))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
EquippedEquipmentPayload payload = JsonUtility.FromJson<EquippedEquipmentPayload>(json);
|
||||
if (payload == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
equippedEquipmentId = payload.equippedEquipmentId ?? string.Empty;
|
||||
equippedEquipment = ResolveEquippedEquipmentById(equippedEquipmentId);
|
||||
}
|
||||
|
||||
public void SetEquippedEquipment(equipmentSO equipment, bool persist = true)
|
||||
{
|
||||
equippedEquipment = equipment;
|
||||
equippedEquipmentId = equipment != null ? equipment.name : string.Empty;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
if (!Application.isPlaying)
|
||||
{
|
||||
UnityEditor.EditorUtility.SetDirty(this);
|
||||
if (persist)
|
||||
{
|
||||
UnityEditor.AssetDatabase.SaveAssets();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (persist)
|
||||
{
|
||||
SaveEquippedEquipmentToLocal();
|
||||
}
|
||||
}
|
||||
|
||||
public equipmentSO GetEquippedEquipmentResolved()
|
||||
{
|
||||
if (equippedEquipment != null)
|
||||
{
|
||||
return equippedEquipment;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(equippedEquipmentId))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
equippedEquipment = ResolveEquippedEquipmentById(equippedEquipmentId);
|
||||
return equippedEquipment;
|
||||
}
|
||||
|
||||
public void ClearEquippedEquipment()
|
||||
{
|
||||
equippedEquipment = null;
|
||||
equippedEquipmentId = string.Empty;
|
||||
PlayerPrefs.DeleteKey(GetEquippedEquipmentPrefsKey());
|
||||
PlayerPrefs.Save();
|
||||
#if UNITY_EDITOR
|
||||
if (!Application.isPlaying)
|
||||
{
|
||||
UnityEditor.EditorUtility.SetDirty(this);
|
||||
UnityEditor.AssetDatabase.SaveAssets();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
private equipmentSO ResolveEquippedEquipmentById(string equipmentId)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(equipmentId))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
if (!Application.isPlaying)
|
||||
{
|
||||
string[] guids = UnityEditor.AssetDatabase.FindAssets("t:equipmentSO", new[] { "Assets/Resources/so/uEquip" });
|
||||
for (int i = 0; i < guids.Length; i++)
|
||||
{
|
||||
string path = UnityEditor.AssetDatabase.GUIDToAssetPath(guids[i]);
|
||||
equipmentSO equipment = UnityEditor.AssetDatabase.LoadAssetAtPath<equipmentSO>(path);
|
||||
if (equipment != null && equipment.name == equipmentId)
|
||||
{
|
||||
return equipment;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
equipmentSO[] runtimeEquipments = Resources.LoadAll<equipmentSO>("so/uEquip");
|
||||
for (int i = 0; i < runtimeEquipments.Length; i++)
|
||||
{
|
||||
if (runtimeEquipments[i] != null && runtimeEquipments[i].name == equipmentId)
|
||||
{
|
||||
return runtimeEquipments[i];
|
||||
}
|
||||
}
|
||||
|
||||
var generatedEquipments = Bansonic.equipmentGenerator.GetRuntimeGeneratedEquipments();
|
||||
for (int i = 0; i < generatedEquipments.Count; i++)
|
||||
{
|
||||
if (generatedEquipments[i] != null && generatedEquipments[i].name == equipmentId)
|
||||
{
|
||||
return generatedEquipments[i];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void ClearEquippedSkills()
|
||||
{
|
||||
equippedSkillGroupIDs = Array.Empty<int>();
|
||||
|
||||
Reference in New Issue
Block a user