装备系统完结,修复并加入很多

This commit is contained in:
FloatGaming
2026-04-03 19:15:02 +08:00
parent 538085b64f
commit d9376833b6
378 changed files with 62464 additions and 16756 deletions
+320 -10
View File
@@ -1,4 +1,5 @@
using System;
using System;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
@@ -12,7 +13,11 @@ namespace Bansonic
{
private const string EditorOutputFolder = "Assets/Resources/so/uEquip";
private const string RuntimeOutputFolder = "so/uEquip";
private const string NextGeneratedIdPrefsKey = "bansonic_equipment_next_id_v1";
private const string RuntimeSaveCategory = "runtime_equipment";
private const string RuntimeSaveKey = "generated_list";
private static readonly List<equipmentSO> RuntimeGeneratedEquipments = new List<equipmentSO>();
private static bool runtimeGeneratedLoaded;
private enum QualityRollMode { Default, High }
@@ -23,7 +28,81 @@ namespace Bansonic
public int skillId;
}
public static IReadOnlyList<equipmentSO> GetRuntimeGeneratedEquipments() => RuntimeGeneratedEquipments;
[Serializable]
private class RuntimeGeneratedEquipmentListPayload
{
public List<RuntimeGeneratedEquipmentPayload> items = new List<RuntimeGeneratedEquipmentPayload>();
}
[Serializable]
private class RuntimeGeneratedEquipmentPayload
{
public string name;
public int skillType;
public int level;
public string tierNameConfigName;
public bool enableTypeSameEffects;
public int saSkillId;
public int iaSkillId;
public StatPayload maxHp;
public StatPayload attack;
public StatPayload maxMana;
public StatPayload damageResistance;
public StatPayload scoreEfficiency;
public List<EffectPayload> specialEffects = new List<EffectPayload>();
public List<EffectPayload> typeSameEffects = new List<EffectPayload>();
public List<EffectPayload> illusionEffects = new List<EffectPayload>();
public List<EffectPayload> maxLevelEffects = new List<EffectPayload>();
}
[Serializable]
private class StatPayload
{
public float basicGain;
public float cultivationInterval;
}
[Serializable]
private class EffectPayload
{
public int effectType;
public float value;
}
public static IReadOnlyList<equipmentSO> GetRuntimeGeneratedEquipments()
{
EnsureRuntimeGeneratedLoaded();
return RuntimeGeneratedEquipments;
}
public static equipmentSO RegisterGeneratedEquipment(equipmentSO generated)
{
return Persist(generated);
}
public static string GenerateUniqueEquipmentName(equipmentSO.EquipmentSkillType type)
{
return BuildGeneratedName(type);
}
public static void RemoveRuntimeGeneratedEquipment(equipmentSO equipment)
{
EnsureRuntimeGeneratedLoaded();
if (equipment == null)
{
return;
}
RuntimeGeneratedEquipments.RemoveAll(item => item == null || item == equipment || item.name == equipment.name);
SaveRuntimeGeneratedState();
}
public static void ClearRuntimeGeneratedPersistence()
{
RuntimeGeneratedEquipments.Clear();
runtimeGeneratedLoaded = true;
SecureSaveVault.Delete(RuntimeSaveCategory, RuntimeSaveKey);
}
public static List<equipmentSO> generateEquipment(
int quantity,
@@ -64,7 +143,11 @@ namespace Bansonic
return results;
}
public static equipmentSO GenerateFromSmeltReward(smeltStageRewardSO rewardSo, smeltStageRewardSO.SmeltStageRewardRequirement requirement)
public static equipmentSO GenerateFromSmeltReward(
smeltStageRewardSO rewardSo,
smeltStageRewardSO.SmeltStageRewardRequirement requirement,
equipmentSO.EquipmentSkillType? forcedType = null,
int forcedSkillGroupId = 0)
{
if (rewardSo == null || requirement == null || rewardSo.rewardRandomConfig == null)
{
@@ -75,9 +158,9 @@ namespace Bansonic
config.NormalizeRuntimeData();
equipmentSO generated = CreateBaseEquipment(rewardSo.rewardTemplate);
generated.skillType = requirement.equipmentType == smeltStageRewardSO.equipType.selfChosenType
generated.skillType = forcedType ?? (requirement.equipmentType == smeltStageRewardSO.equipType.selfChosenType
? requirement.chosenSkillType
: RollRandomSkillType();
: RollRandomSkillType());
generated.name = BuildGeneratedName(generated.skillType);
generated.level = 0;
generated.sa_skillID = 0;
@@ -90,7 +173,7 @@ namespace Bansonic
ResetBasicGains(generated);
GenerateBasicAttributes(generated, config, mode);
GenerateTypeSameEffects(generated, config, mode);
GenerateSpecialEffects(generated, config, mode, requirement.skillRequirement == smeltStageRewardSO.skillOwned.mustHave);
GenerateSpecialEffects(generated, config, mode, requirement.skillRequirement == smeltStageRewardSO.skillOwned.mustHave, forcedSkillGroupId);
GenerateIllusionEffects(generated, config, mode);
return Persist(generated);
}
@@ -152,7 +235,7 @@ namespace Bansonic
}
generated.typeSameEffects = results.ToArray();
}
private static void GenerateSpecialEffects(equipmentSO generated, equipmentRandomConfigSO config, QualityRollMode mode, bool mustHaveSkill)
private static void GenerateSpecialEffects(equipmentSO generated, equipmentRandomConfigSO config, QualityRollMode mode, bool mustHaveSkill, int forcedSkillGroupId = 0)
{
int count = RollSpecialEffectCount(config);
var pool = BuildSpecialEffectPool(generated, config);
@@ -173,9 +256,22 @@ namespace Bansonic
}
ResolveDuplicateEffects(generatedEffects);
bool hasForcedSkill = forcedSkillGroupId > 0;
bool shouldGenerateSkill = mustHaveSkill || UnityEngine.Random.value <= config.sesp;
if (shouldGenerateSkill && generatedEffects.Count > 0 && config.TryGetSpecialSkillId(generated.skillType, out int skillId) && skillId > 0)
if ((hasForcedSkill || shouldGenerateSkill) && generatedEffects.Count > 0)
{
int skillId = 0;
if (hasForcedSkill)
{
skillId = forcedSkillGroupId;
}
else if (!config.TryGetSpecialSkillId(generated.skillType, out skillId) || skillId <= 0)
{
generated.sa_skillID = 0;
generated.specialEffects = BuildGeneratedEffects(generatedEffects);
return;
}
int replace = UnityEngine.Random.Range(0, generatedEffects.Count);
generatedEffects[replace] = new GeneratedEffectValue { effectType = equipmentSO.EquipmentSpecialEffectType.Skill, value = 0f, skillId = skillId };
generated.sa_skillID = skillId;
@@ -307,8 +403,10 @@ namespace Bansonic
}
}
#endif
EnsureRuntimeGeneratedLoaded();
RuntimeGeneratedEquipments.RemoveAll(item => item == null || item.name == generated.name);
RuntimeGeneratedEquipments.Add(generated);
SaveRuntimeGeneratedState();
return generated;
}
@@ -322,7 +420,8 @@ namespace Bansonic
private static int GetNextGeneratedId()
{
int maxId = 0;
EnsureRuntimeGeneratedLoaded();
int maxId = Mathf.Max(0, PlayerPrefs.GetInt(NextGeneratedIdPrefsKey, 0));
for (int i = 0; i < RuntimeGeneratedEquipments.Count; i++)
{
if (RuntimeGeneratedEquipments[i] != null)
@@ -350,7 +449,10 @@ namespace Bansonic
}
}
#endif
return maxId + 1;
int nextId = maxId + 1;
PlayerPrefs.SetInt(NextGeneratedIdPrefsKey, nextId);
PlayerPrefs.Save();
return nextId;
}
private static void TryUpdateMaxId(string fileName, ref int maxId)
@@ -440,7 +542,8 @@ namespace Bansonic
if (Mathf.Approximately(minValue, maxValue)) return AvoidZero(minValue, maxValue, minValue);
if (maxValue < minValue) { float cached = minValue; minValue = maxValue; maxValue = cached; }
float span = maxValue - minValue;
return AvoidZero(minValue, maxValue, UnityEngine.Random.Range(maxValue - span * 0.2f, maxValue));
float tail = Mathf.Max(span * 0.2f, 0.0001f);
return AvoidZero(minValue, maxValue, UnityEngine.Random.Range(Mathf.Max(minValue, maxValue - tail), maxValue));
}
private static float RollBiasedValue(float minValue, float maxValue)
@@ -506,5 +609,212 @@ namespace Bansonic
if (!AssetDatabase.IsValidFolder(EditorOutputFolder)) AssetDatabase.CreateFolder("Assets/Resources/so", "uEquip");
}
#endif
private static void EnsureRuntimeGeneratedLoaded()
{
if (runtimeGeneratedLoaded)
{
return;
}
runtimeGeneratedLoaded = true;
RuntimeGeneratedEquipments.Clear();
RuntimeGeneratedEquipmentListPayload payload;
if (!SecureSaveVault.TryLoadJson(RuntimeSaveCategory, RuntimeSaveKey, out payload) || payload == null || payload.items == null)
{
return;
}
for (int i = 0; i < payload.items.Count; i++)
{
RuntimeGeneratedEquipmentPayload itemPayload = payload.items[i];
equipmentSO restored = BuildEquipmentFromPayload(itemPayload);
if (restored != null)
{
RuntimeGeneratedEquipments.Add(restored);
}
}
}
private static void SaveRuntimeGeneratedState()
{
RuntimeGeneratedEquipmentListPayload payload = new RuntimeGeneratedEquipmentListPayload();
for (int i = 0; i < RuntimeGeneratedEquipments.Count; i++)
{
equipmentSO equipment = RuntimeGeneratedEquipments[i];
if (equipment == null)
{
continue;
}
payload.items.Add(BuildPayload(equipment));
}
SecureSaveVault.SaveJson(RuntimeSaveCategory, RuntimeSaveKey, payload);
}
private static RuntimeGeneratedEquipmentPayload BuildPayload(equipmentSO equipment)
{
return new RuntimeGeneratedEquipmentPayload
{
name = equipment.name ?? string.Empty,
skillType = (int)equipment.skillType,
level = equipment.level,
tierNameConfigName = equipment.tierNameConfig != null ? equipment.tierNameConfig.name : string.Empty,
enableTypeSameEffects = equipment.enableTypeSameEffects,
saSkillId = equipment.sa_skillID,
iaSkillId = equipment.ia_skillID,
maxHp = BuildStatPayload(equipment.maxHp),
attack = BuildStatPayload(equipment.attack),
maxMana = BuildStatPayload(equipment.maxMana),
damageResistance = BuildStatPayload(equipment.damageResistance),
scoreEfficiency = BuildStatPayload(equipment.scoreEfficiency),
specialEffects = BuildEffectPayloads(equipment.specialEffects),
typeSameEffects = BuildEffectPayloads(equipment.typeSameEffects),
illusionEffects = BuildEffectPayloads(equipment.illusionEffects),
maxLevelEffects = BuildEffectPayloads(equipment.maxLevelEffects)
};
}
private static equipmentSO BuildEquipmentFromPayload(RuntimeGeneratedEquipmentPayload payload)
{
if (payload == null || string.IsNullOrWhiteSpace(payload.name))
{
return null;
}
equipmentSO equipment = ScriptableObject.CreateInstance<equipmentSO>();
equipment.name = payload.name;
equipment.skillType = (equipmentSO.EquipmentSkillType)Mathf.Clamp(payload.skillType, 0, Enum.GetValues(typeof(equipmentSO.EquipmentSkillType)).Length - 1);
equipment.level = Mathf.Max(0, payload.level);
equipment.tierNameConfig = ResolveTierNameConfig(payload.tierNameConfigName);
equipment.enableTypeSameEffects = payload.enableTypeSameEffects;
equipment.sa_skillID = Mathf.Max(0, payload.saSkillId);
equipment.ia_skillID = Mathf.Max(0, payload.iaSkillId);
ApplyStatPayload(equipment.maxHp, payload.maxHp);
ApplyStatPayload(equipment.attack, payload.attack);
ApplyStatPayload(equipment.maxMana, payload.maxMana);
ApplyStatPayload(equipment.damageResistance, payload.damageResistance);
ApplyStatPayload(equipment.scoreEfficiency, payload.scoreEfficiency);
equipment.specialEffects = BuildEffectsFromPayload(payload.specialEffects);
equipment.typeSameEffects = BuildEffectsFromPayload(payload.typeSameEffects);
equipment.illusionEffects = BuildEffectsFromPayload(payload.illusionEffects);
equipment.maxLevelEffects = BuildEffectsFromPayload(payload.maxLevelEffects);
equipment.NormalizeIllusionEffectsInPlace();
equipment.hideFlags = HideFlags.None;
return equipment;
}
private static StatPayload BuildStatPayload(equipmentSO.EquipmentStatTuning tuning)
{
return new StatPayload
{
basicGain = tuning != null ? tuning.basicGain : 0f,
cultivationInterval = tuning != null ? tuning.cultivationInterval : 0f
};
}
private static void ApplyStatPayload(equipmentSO.EquipmentStatTuning tuning, StatPayload payload)
{
if (tuning == null || payload == null)
{
return;
}
tuning.basicGain = payload.basicGain;
tuning.cultivationInterval = payload.cultivationInterval;
}
private static List<EffectPayload> BuildEffectPayloads(equipmentSO.EquipmentSpecialEffect[] effects)
{
List<EffectPayload> payloads = new List<EffectPayload>();
if (effects == null)
{
return payloads;
}
for (int i = 0; i < effects.Length; i++)
{
equipmentSO.EquipmentSpecialEffect effect = effects[i];
if (effect == null)
{
continue;
}
payloads.Add(new EffectPayload
{
effectType = (int)effect.effectType,
value = effect.value
});
}
return payloads;
}
private static equipmentSO.EquipmentSpecialEffect[] BuildEffectsFromPayload(List<EffectPayload> payloads)
{
if (payloads == null || payloads.Count == 0)
{
return Array.Empty<equipmentSO.EquipmentSpecialEffect>();
}
equipmentSO.EquipmentSpecialEffect[] effects = new equipmentSO.EquipmentSpecialEffect[payloads.Count];
for (int i = 0; i < payloads.Count; i++)
{
EffectPayload payload = payloads[i];
effects[i] = new equipmentSO.EquipmentSpecialEffect
{
effectType = (equipmentSO.EquipmentSpecialEffectType)Mathf.Clamp(payload.effectType, 0, Enum.GetValues(typeof(equipmentSO.EquipmentSpecialEffectType)).Length - 1),
value = payload.value
};
}
return effects;
}
private static equipmentTierNameConfigSO ResolveTierNameConfig(string configName)
{
#if UNITY_EDITOR
if (!Application.isPlaying)
{
if (!string.IsNullOrWhiteSpace(configName))
{
string[] guids = AssetDatabase.FindAssets($"t:equipmentTierNameConfigSO {configName}");
for (int i = 0; i < guids.Length; i++)
{
string path = AssetDatabase.GUIDToAssetPath(guids[i]);
equipmentTierNameConfigSO config = AssetDatabase.LoadAssetAtPath<equipmentTierNameConfigSO>(path);
if (config != null && string.Equals(config.name, configName, StringComparison.Ordinal))
{
return config;
}
}
}
equipmentTierNameConfigSO directEditorConfig = AssetDatabase.LoadAssetAtPath<equipmentTierNameConfigSO>("Assets/_eqpmtSys/EquipmentTierNameConfig.asset");
if (directEditorConfig != null)
{
return directEditorConfig;
}
}
#endif
if (string.IsNullOrWhiteSpace(configName))
{
return Resources.Load<equipmentTierNameConfigSO>("EquipmentTierNameConfig");
}
equipmentTierNameConfigSO[] configs = Resources.LoadAll<equipmentTierNameConfigSO>(string.Empty);
for (int i = 0; i < configs.Length; i++)
{
if (configs[i] != null && string.Equals(configs[i].name, configName, StringComparison.Ordinal))
{
return configs[i];
}
}
return Resources.Load<equipmentTierNameConfigSO>("EquipmentTierNameConfig");
}
}
}
+2 -2
View File
@@ -97,7 +97,7 @@ MonoBehaviour:
maxValue: 0
specialSkillPool:
- skillType: 0
skillIds: 69c7c9016ac7c9016bc7c9016cc7c901
skillIds: 79eec9017aeec9017beec9017ceec9017deec9017eeec9017feec901
- skillType: 1
skillIds:
- skillType: 2
@@ -112,4 +112,4 @@ MonoBehaviour:
skillIds:
- skillType: 7
skillIds:
illusionSkillPool: 79eec9017aeec9017beec9017ceec901
illusionSkillPool: 8915ca018a15ca018b15ca018c15ca018d15ca018e15ca018f15ca01
@@ -0,0 +1,151 @@
using System.Collections.Generic;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
public static class EquipmentSkillGroupLibrary
{
private static readonly string[] SpecialResourcesPaths =
{
"so/skill_equipSkills/mmrEffectSkills",
"so/skill_equipSkills/\u8bb0\u5fc6\u7279\u6548\u6280\u80fd"
};
private static readonly string[] IllusionResourcesPaths =
{
"so/skill_equipSkills/illusionSkills",
"so/skill_equipSkills/\u5e7b\u5316\u6280\u80fd"
};
#if UNITY_EDITOR
private static readonly string[] SpecialAssetFolders =
{
"Assets/Resources/so/skill_equipSkills/mmrEffectSkills",
"Assets/Resources/so/skill_equipSkills/\u8bb0\u5fc6\u7279\u6548\u6280\u80fd"
};
private static readonly string[] IllusionAssetFolders =
{
"Assets/Resources/so/skill_equipSkills/illusionSkills",
"Assets/Resources/so/skill_equipSkills/\u5e7b\u5316\u6280\u80fd"
};
#endif
public static SkillGroup ResolveSpecialSkillGroup(int skillGroupId)
{
return ResolveSkillGroup(skillGroupId, EquipmentSkillGroupSO.EquipmentSkillCategory.Special);
}
public static SkillGroup ResolveIllusionSkillGroup(int skillGroupId)
{
return ResolveSkillGroup(skillGroupId, EquipmentSkillGroupSO.EquipmentSkillCategory.Illusion);
}
public static SkillGroup ResolveSkillGroup(int skillGroupId)
{
SkillGroup group = ResolveSpecialSkillGroup(skillGroupId);
if (group != null)
{
return group;
}
return ResolveIllusionSkillGroup(skillGroupId);
}
public static SkillGroup ResolveSkillGroup(int skillGroupId, EquipmentSkillGroupSO.EquipmentSkillCategory category)
{
if (skillGroupId <= 0)
{
return null;
}
EquipmentSkillGroupSO asset = FindAsset(skillGroupId, category);
return asset != null ? asset.skillGroup : null;
}
public static EquipmentSkillGroupSO FindAsset(int skillGroupId, EquipmentSkillGroupSO.EquipmentSkillCategory category)
{
if (skillGroupId <= 0)
{
return null;
}
var assets = LoadAssets(category);
for (int i = 0; i < assets.Count; i++)
{
EquipmentSkillGroupSO asset = assets[i];
if (asset == null || asset.skillGroup == null)
{
continue;
}
if (asset.skillGroup.skillGroupID == skillGroupId)
{
return asset;
}
}
return null;
}
public static List<EquipmentSkillGroupSO> LoadAssets(EquipmentSkillGroupSO.EquipmentSkillCategory category)
{
var results = new List<EquipmentSkillGroupSO>();
#if UNITY_EDITOR
if (!Application.isPlaying)
{
string[] folders = category == EquipmentSkillGroupSO.EquipmentSkillCategory.Special ? SpecialAssetFolders : IllusionAssetFolders;
var dedupe = new HashSet<string>();
for (int folderIndex = 0; folderIndex < folders.Length; folderIndex++)
{
if (!AssetDatabase.IsValidFolder(folders[folderIndex]))
{
continue;
}
string[] guids = AssetDatabase.FindAssets("t:EquipmentSkillGroupSO", new[] { folders[folderIndex] });
for (int i = 0; i < guids.Length; i++)
{
string path = AssetDatabase.GUIDToAssetPath(guids[i]);
if (!dedupe.Add(path))
{
continue;
}
EquipmentSkillGroupSO asset = AssetDatabase.LoadAssetAtPath<EquipmentSkillGroupSO>(path);
if (asset != null)
{
results.Add(asset);
}
}
}
return results;
}
#endif
string[] resourcePaths = category == EquipmentSkillGroupSO.EquipmentSkillCategory.Special ? SpecialResourcesPaths : IllusionResourcesPaths;
var seen = new HashSet<EquipmentSkillGroupSO>();
for (int i = 0; i < resourcePaths.Length; i++)
{
EquipmentSkillGroupSO[] loaded = Resources.LoadAll<EquipmentSkillGroupSO>(resourcePaths[i]);
if (loaded == null || loaded.Length == 0)
{
continue;
}
for (int j = 0; j < loaded.Length; j++)
{
if (loaded[j] != null && seen.Add(loaded[j]))
{
results.Add(loaded[j]);
}
}
}
return results;
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: f074a56fea526fe4081c979b0a46c5ae
+32
View File
@@ -0,0 +1,32 @@
using UnityEngine;
[CreateAssetMenu(fileName = "NewEquipmentSkillGroup", menuName = "Equipment/Equipment Skill Group")]
public class EquipmentSkillGroupSO : ScriptableObject
{
public enum EquipmentSkillCategory
{
Special,
Illusion
}
[Header("Category")]
public EquipmentSkillCategory category = EquipmentSkillCategory.Special;
[Header("Skill Group")]
public SkillGroup skillGroup = new SkillGroup();
public int SkillGroupID => skillGroup != null ? Mathf.Max(0, skillGroup.skillGroupID) : 0;
private void OnValidate()
{
if (skillGroup == null)
{
skillGroup = new SkillGroup();
}
if (skillGroup.skillGroupID < 0)
{
skillGroup.skillGroupID = 0;
}
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 5c8a4b40778922c47aee8e4ccf03b4f1
+41 -41
View File
@@ -1,4 +1,4 @@
%YAML 1.1
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
@@ -16,136 +16,136 @@ MonoBehaviour:
- skillType: 0
stagePresentations:
- tierName: "\u9898\u6D77\u7834\u6D6A"
equipmentSprite: {fileID: 21300000, guid: 2ca0f01bbfea44aacb78e56edc48fc71, type: 3}
equipmentSprite: {fileID: 21300000, guid: a01f5b74ad536f24e86c74fdd669c680, type: 3}
tierDescription: "\u7834\u9898\u5982\u7834\u6D6A\uFF0C\u601D\u8DEF\u6108\u6218\u6108\u5F00\u3002"
- tierName: "\u9898\u6E0A\u65AD\u6F6E"
equipmentSprite: {fileID: 0}
equipmentSprite: {fileID: 21300000, guid: d890f7dd6732bc347889ad5b21d51459, type: 3}
tierDescription:
- tierName: "\u88C2\u6D77\u65A9"
equipmentSprite: {fileID: 0}
equipmentSprite: {fileID: 21300000, guid: 814f39e3a1e204c4586f75b514a06601, type: 3}
tierDescription:
- tierName: "\u6CA7\u6E9F\u6740\u53F7"
equipmentSprite: {fileID: 0}
equipmentSprite: {fileID: 21300000, guid: 4ce68bd00ecc6f64baefd01ce27f33f9, type: 3}
tierDescription:
- tierName: "\u68A6\u9192\xB7\u9010\u6D6A\u6781\u610F"
equipmentSprite: {fileID: 21300000, guid: b20bb1f822693463499065afa6c27f4c, type: 3}
equipmentSprite: {fileID: 21300000, guid: ffa9c656cac7ffb458e861b457ea3ef9, type: 3}
tierDescription:
- skillType: 1
stagePresentations:
- tierName: "\u8BDB\u6740\u53F7"
equipmentSprite: {fileID: 0}
equipmentSprite: {fileID: 21300000, guid: a01f5b74ad536f24e86c74fdd669c680, type: 3}
tierDescription:
- tierName: "\u6E05\u5F02\u5203"
equipmentSprite: {fileID: 0}
equipmentSprite: {fileID: 21300000, guid: d890f7dd6732bc347889ad5b21d51459, type: 3}
tierDescription:
- tierName: "\u65AD\u9006\u950B"
equipmentSprite: {fileID: 0}
equipmentSprite: {fileID: 21300000, guid: 814f39e3a1e204c4586f75b514a06601, type: 3}
tierDescription:
- tierName: "\u706D\u5F02\u88C1\u51B3"
equipmentSprite: {fileID: 0}
equipmentSprite: {fileID: 21300000, guid: 4ce68bd00ecc6f64baefd01ce27f33f9, type: 3}
tierDescription:
- tierName: "\u68A6\u9192\xB7\u7EDD\u706D\u7981\u4EE4"
equipmentSprite: {fileID: 21300000, guid: 0d613dfdfe017447c99d4a4c509cbf25, type: 3}
equipmentSprite: {fileID: 21300000, guid: ffa9c656cac7ffb458e861b457ea3ef9, type: 3}
tierDescription: "\u88C1\u51B3\u964D\u4E34\uFF0C\u4E00\u5207\u76EE\u6807\u5F52\u96F6"
- skillType: 2
stagePresentations:
- tierName: "\u540C\u4E50\u5951"
equipmentSprite: {fileID: 0}
equipmentSprite: {fileID: 21300000, guid: a01f5b74ad536f24e86c74fdd669c680, type: 3}
tierDescription:
- tierName: "\u5171\u8C0B\u73AF"
equipmentSprite: {fileID: 0}
equipmentSprite: {fileID: 21300000, guid: d890f7dd6732bc347889ad5b21d51459, type: 3}
tierDescription:
- tierName: "\u534F\u5F8B\u5370"
equipmentSprite: {fileID: 0}
equipmentSprite: {fileID: 21300000, guid: 814f39e3a1e204c4586f75b514a06601, type: 3}
tierDescription:
- tierName: "\u9038\u4E50\u5171\u632F"
equipmentSprite: {fileID: 0}
equipmentSprite: {fileID: 21300000, guid: 4ce68bd00ecc6f64baefd01ce27f33f9, type: 3}
tierDescription:
- tierName: "\u68A6\u9192\xB7\u5929\u548C\u540C\u5951"
equipmentSprite: {fileID: 0}
equipmentSprite: {fileID: 21300000, guid: ffa9c656cac7ffb458e861b457ea3ef9, type: 3}
tierDescription:
- skillType: 3
stagePresentations:
- tierName: "\u7CBE\u4FEE\u4EF6"
equipmentSprite: {fileID: 0}
equipmentSprite: {fileID: 21300000, guid: a01f5b74ad536f24e86c74fdd669c680, type: 3}
tierDescription:
- tierName: "\u6781\u81F4\u6838"
equipmentSprite: {fileID: 0}
equipmentSprite: {fileID: 21300000, guid: d890f7dd6732bc347889ad5b21d51459, type: 3}
tierDescription:
- tierName: "\u5B8C\u6574\u4F53"
equipmentSprite: {fileID: 0}
equipmentSprite: {fileID: 21300000, guid: 814f39e3a1e204c4586f75b514a06601, type: 3}
tierDescription:
- tierName: "\u81F3\u4E0A\u6784\u578B"
equipmentSprite: {fileID: 0}
equipmentSprite: {fileID: 21300000, guid: 4ce68bd00ecc6f64baefd01ce27f33f9, type: 3}
tierDescription:
- tierName: "\u68A6\u9192\xB7\u5B8C\u7F8E\u7EC8\u5F0F"
equipmentSprite: {fileID: 0}
equipmentSprite: {fileID: 21300000, guid: ffa9c656cac7ffb458e861b457ea3ef9, type: 3}
tierDescription:
- skillType: 4
stagePresentations:
- tierName: "\u9759\u5FC3\u8BC0"
equipmentSprite: {fileID: 0}
equipmentSprite: {fileID: 21300000, guid: a01f5b74ad536f24e86c74fdd669c680, type: 3}
tierDescription:
- tierName: "\u517B\u6C14\u6CD5"
equipmentSprite: {fileID: 0}
equipmentSprite: {fileID: 21300000, guid: d890f7dd6732bc347889ad5b21d51459, type: 3}
tierDescription:
- tierName: "\u6F84\u660E\u5883"
equipmentSprite: {fileID: 0}
equipmentSprite: {fileID: 21300000, guid: 814f39e3a1e204c4586f75b514a06601, type: 3}
tierDescription:
- tierName: "\u5FC3\u517B\u5F52\u4E00"
equipmentSprite: {fileID: 0}
equipmentSprite: {fileID: 21300000, guid: 4ce68bd00ecc6f64baefd01ce27f33f9, type: 3}
tierDescription:
- tierName: "\u68A6\u9192\xB7\u65E0\u5C18\u771F\u5883"
equipmentSprite: {fileID: 0}
equipmentSprite: {fileID: 21300000, guid: ffa9c656cac7ffb458e861b457ea3ef9, type: 3}
tierDescription:
- skillType: 5
stagePresentations:
- tierName: "\u540C\u5FC3\u5370"
equipmentSprite: {fileID: 0}
equipmentSprite: {fileID: 21300000, guid: a01f5b74ad536f24e86c74fdd669c680, type: 3}
tierDescription:
- tierName: "\u534F\u529B\u73AF"
equipmentSprite: {fileID: 0}
equipmentSprite: {fileID: 21300000, guid: d890f7dd6732bc347889ad5b21d51459, type: 3}
tierDescription:
- tierName: "\u5171\u9E23\u9635"
equipmentSprite: {fileID: 0}
equipmentSprite: {fileID: 21300000, guid: 814f39e3a1e204c4586f75b514a06601, type: 3}
tierDescription:
- tierName: "\u4F17\u5FD7\u58C1\u5792"
equipmentSprite: {fileID: 0}
equipmentSprite: {fileID: 21300000, guid: 4ce68bd00ecc6f64baefd01ce27f33f9, type: 3}
tierDescription:
- tierName: "\u68A6\u9192\xB7\u4E0D\u7834\u57CE\u57DF"
equipmentSprite: {fileID: 0}
equipmentSprite: {fileID: 21300000, guid: ffa9c656cac7ffb458e861b457ea3ef9, type: 3}
tierDescription:
- skillType: 6
stagePresentations:
- tierName: "\u66B4\u6012"
equipmentSprite: {fileID: 0}
equipmentSprite: {fileID: 21300000, guid: a01f5b74ad536f24e86c74fdd669c680, type: 3}
tierDescription:
- tierName: "\u72C2\u6012"
equipmentSprite: {fileID: 0}
equipmentSprite: {fileID: 21300000, guid: d890f7dd6732bc347889ad5b21d51459, type: 3}
tierDescription:
- tierName: "\u5D29\u89E3"
equipmentSprite: {fileID: 0}
equipmentSprite: {fileID: 21300000, guid: 814f39e3a1e204c4586f75b514a06601, type: 3}
tierDescription:
- tierName: "\u5168\u529B\u4E00\u51FB"
equipmentSprite: {fileID: 0}
equipmentSprite: {fileID: 21300000, guid: 4ce68bd00ecc6f64baefd01ce27f33f9, type: 3}
tierDescription:
- tierName: "\u68A6\u9192\xB7\u661F\u8FB0\u8D2F\u7A7F"
equipmentSprite: {fileID: 0}
equipmentSprite: {fileID: 21300000, guid: ffa9c656cac7ffb458e861b457ea3ef9, type: 3}
tierDescription:
- skillType: 7
stagePresentations:
- tierName: "\u521D\u6784"
equipmentSprite: {fileID: 0}
equipmentSprite: {fileID: 21300000, guid: a01f5b74ad536f24e86c74fdd669c680, type: 3}
tierDescription:
- tierName: "\u91CD\u6784"
equipmentSprite: {fileID: 0}
equipmentSprite: {fileID: 21300000, guid: d890f7dd6732bc347889ad5b21d51459, type: 3}
tierDescription:
- tierName: "\u4E8C\u91CD\u6784"
equipmentSprite: {fileID: 0}
equipmentSprite: {fileID: 21300000, guid: 814f39e3a1e204c4586f75b514a06601, type: 3}
tierDescription:
- tierName: "\u4E09\u91CD\u6784"
equipmentSprite: {fileID: 0}
equipmentSprite: {fileID: 21300000, guid: 4ce68bd00ecc6f64baefd01ce27f33f9, type: 3}
tierDescription:
- tierName: "\u68A6\u9192\xB7\u91CD\u91CD\u6784"
equipmentSprite: {fileID: 0}
equipmentSprite: {fileID: 21300000, guid: ffa9c656cac7ffb458e861b457ea3ef9, type: 3}
tierDescription:
+178 -41
View File
@@ -2,6 +2,9 @@
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
#if UNITY_EDITOR
using UnityEditor;
#endif
public class eqpmtDesPrefab : MonoBehaviour
{
@@ -29,6 +32,7 @@ public class eqpmtDesPrefab : MonoBehaviour
public Text eqpmtDescription;
[Header("body")]
public Text eqpmtType;
public Text baTitle;
public Text baDetail;
public GameObject baSpace;
@@ -43,12 +47,19 @@ public class eqpmtDesPrefab : MonoBehaviour
public GameObject iaSpace;
public Text mlTitle;
public Text mlDetail;
public GameObject eqpSpace;
public GameObject whoEquipping;
public Image equipperProfile;
public Text equipperName;
[Header("objs")]
public GameObject eqpmtSkillPrefab;
public Transform sasParent;
public Transform iasParent;
public Transform mlsParent;
[Header("es description")]
public GameObject esDesPrefab;
public Vector2 esDesPrefabOffset = new Vector2(20f, 30f);
private RectTransform rectTransform;
private Canvas rootCanvas;
@@ -148,17 +159,21 @@ public class eqpmtDesPrefab : MonoBehaviour
ApplyEffectSection(taTitle, taDetail, taSpace, null, string.Empty, null, false);
ApplyEffectSection(iaTitle, iaDetail, iaSpace, iasParent, string.Empty, null, false);
ApplyEffectSection(mlTitle, mlDetail, null, mlsParent, string.Empty, null, false);
ApplyEquipperInfo(null);
return;
}
equipmentSO.EquipmentTierPresentation presentation = ResolveTierPresentation(eSO);
string displayName = presentation != null && !string.IsNullOrWhiteSpace(presentation.tierName)
? presentation.tierName
: eSO.name;
string displayName = eSO.GetDisplayTierName();
if (string.IsNullOrWhiteSpace(displayName))
{
displayName = eSO.name;
}
Sprite displaySprite = presentation != null ? presentation.equipmentSprite : null;
string description = presentation != null ? presentation.tierDescription : string.Empty;
string description = eSO.GetDisplayTierDescription();
ApplyHeader(displayName, displaySprite, GetQualityVisualIndex(eSO.level), description);
ApplyHeader(displayName, displaySprite, GetQualityVisualIndex(eSO), description);
ApplyEquipperInfo(eSO);
string basicText = BuildBasicAttributesText(eSO);
ApplyBasicSection(basicText, displayBasicAttributes && !string.IsNullOrWhiteSpace(basicText));
@@ -212,6 +227,84 @@ public class eqpmtDesPrefab : MonoBehaviour
displayMaxLevelEffects && HasSectionContent(eSO.maxLevelEffects, 0));
}
private void ApplyEquipperInfo(equipmentSO equipment)
{
AllyHero_SO equipper = FindEquipper(equipment);
bool hasEquipper = equipper != null;
if (whoEquipping != null)
{
whoEquipping.SetActive(hasEquipper);
}
if (eqpSpace != null)
{
eqpSpace.SetActive(hasEquipper);
}
if (equipperProfile != null)
{
equipperProfile.sprite = hasEquipper ? equipper.ally_hero_squareProfile : null;
equipperProfile.color = hasEquipper && equipper.ally_hero_squareProfile != null ? Color.white : new Color(1f, 1f, 1f, 0f);
}
if (equipperName != null)
{
equipperName.text = hasEquipper ? equipper.ally_heroName : string.Empty;
}
}
private AllyHero_SO FindEquipper(equipmentSO equipment)
{
if (equipment == null)
{
return null;
}
AllyHero_SO[] heroes = LoadHeroAssets();
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 == equipment || (!string.IsNullOrWhiteSpace(equipped?.name) && equipped.name == equipment.name))
{
return hero;
}
}
return null;
}
private AllyHero_SO[] LoadHeroAssets()
{
#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 equipmentSO.EquipmentTierPresentation ResolveTierPresentation(equipmentSO equipment)
{
if (equipment == null)
@@ -220,7 +313,7 @@ public class eqpmtDesPrefab : MonoBehaviour
}
if (equipment.tierNameConfig != null &&
equipment.tierNameConfig.TryGetStagePresentation(equipment.skillType, equipment.GetTierStageIndex(), out equipmentTierNameConfigSO.StagePresentation stage) &&
equipment.tierNameConfig.TryGetStagePresentation(equipment.skillType, equipment.GetVisualTierStageIndex(), out equipmentTierNameConfigSO.StagePresentation stage) &&
stage != null)
{
return new equipmentSO.EquipmentTierPresentation
@@ -231,7 +324,7 @@ public class eqpmtDesPrefab : MonoBehaviour
};
}
return equipment.GetCurrentTierPresentation();
return equipment.GetVisualTierPresentation();
}
private void ApplyHeader(string displayName, Sprite displaySprite, int qualityIndex, string description)
@@ -257,6 +350,11 @@ public class eqpmtDesPrefab : MonoBehaviour
eqpmtDescription.text = description;
}
if (eqpmtType != null)
{
eqpmtType.text = eSO != null ? eSO.skillType.ToString() : string.Empty;
}
if (eqpmtIcon != null)
{
eqpmtIcon.sprite = displaySprite;
@@ -333,6 +431,19 @@ public class eqpmtDesPrefab : MonoBehaviour
GameObject instance = Instantiate(eqpmtSkillPrefab, parent);
instance.name = $"eqpmtSkill_{skillId}";
SkillGroup skillGroup = EquipmentSkillGroupLibrary.ResolveSkillGroup(skillId);
string displayName = skillGroup != null && !string.IsNullOrWhiteSpace(skillGroup.groupName)
? skillGroup.groupName
: $"Skill {skillId}";
Sprite displayIcon = skillGroup != null ? skillGroup.groupIcon : null;
esPrefab legacyItem = instance.GetComponent<esPrefab>();
if (legacyItem != null)
{
legacyItem.BindSkillGroup(skillId, displayName, displayIcon, esDesPrefab, transform as RectTransform, esDesPrefabOffset);
return;
}
eqpmtSkillPrefabItem item = instance.GetComponent<eqpmtSkillPrefabItem>();
if (item != null)
@@ -346,7 +457,7 @@ public class eqpmtDesPrefab : MonoBehaviour
{
if (texts[i] != null)
{
texts[i].text = $"Skill {skillId}";
texts[i].text = displayName;
break;
}
}
@@ -454,15 +565,15 @@ public class eqpmtDesPrefab : MonoBehaviour
}
var lines = new List<string>();
AppendBasicLine(lines, "最大生命", equipment.maxHp);
AppendBasicLine(lines, "攻击力", equipment.attack);
AppendBasicLine(lines, "最大法力", equipment.maxMana);
AppendBasicLine(lines, "伤害减免", equipment.damageResistance);
AppendBasicLine(lines, "得分效率", equipment.scoreEfficiency);
AppendBasicLine(lines, "最大生命", equipment.maxHp, equipmentSO.EquipmentSpecialEffectType.MaxHp);
AppendBasicLine(lines, "攻击力", equipment.attack, equipmentSO.EquipmentSpecialEffectType.Attack);
AppendBasicLine(lines, "最大法力", equipment.maxMana, equipmentSO.EquipmentSpecialEffectType.MaxMana);
AppendBasicLine(lines, "伤害减免", equipment.damageResistance, equipmentSO.EquipmentSpecialEffectType.DamageResistance);
AppendBasicLine(lines, "得分效率", equipment.scoreEfficiency, equipmentSO.EquipmentSpecialEffectType.ScoreEfficiency);
return string.Join("\n", lines);
}
private void AppendBasicLine(List<string> lines, string label, equipmentSO.EquipmentStatTuning tuning)
private void AppendBasicLine(List<string> lines, string label, equipmentSO.EquipmentStatTuning tuning, equipmentSO.EquipmentSpecialEffectType effectType)
{
if (lines == null || tuning == null)
{
@@ -476,17 +587,27 @@ public class eqpmtDesPrefab : MonoBehaviour
}
float levelGain = eSO != null ? Mathf.Max(0, eSO.level) * tuning.cultivationInterval : 0f;
float total = baseValue + levelGain;
float finalDreamGain = GetMaxLevelBoost(effectType);
float total = baseValue + levelGain + finalDreamGain;
if (eSO == null || Mathf.Max(0, eSO.level) <= 0 || Mathf.Approximately(levelGain, 0f))
if (eSO == null || (Mathf.Max(0, eSO.level) <= 0 && Mathf.Approximately(finalDreamGain, 0f)))
{
lines.Add($"{label}{FormatTotalPercent(baseValue)}");
lines.Add($"{label}{FormatTotalPercent(baseValue + finalDreamGain)}");
return;
}
lines.Add(
$"{label}{FormatTotalPercent(total)} " +
$"(<color=#ADD8E6>{FormatComponentPercent(baseValue)}</color>+<color=#F0E68C>{FormatComponentPercent(levelGain)}</color>)");
string componentText = $"<color=#ADD8E6>{FormatComponentPercent(baseValue)}</color>";
if (!Mathf.Approximately(levelGain, 0f))
{
componentText += $"+<color=#F0E68C>{FormatComponentPercent(levelGain)}</color>";
}
if (!Mathf.Approximately(finalDreamGain, 0f))
{
componentText += $"+<color=#FF67A4>{FormatComponentPercent(finalDreamGain)}</color>";
}
lines.Add($"{label}{FormatTotalPercent(total)} ({componentText})");
}
private string BuildEffectText(equipmentSO.EquipmentSpecialEffect[] effects, out int skillId)
@@ -506,6 +627,8 @@ public class eqpmtDesPrefab : MonoBehaviour
return string.Empty;
}
bool isTypeSameEffectSection = effects == eSO?.typeSameEffects;
bool isMaxLevelEffectSection = effects == eSO?.maxLevelEffects;
var lines = new List<string>();
for (int i = 0; i < effects.Length; i++)
{
@@ -525,12 +648,36 @@ public class eqpmtDesPrefab : MonoBehaviour
continue;
}
lines.Add($"{GetEffectDisplayName(effect.effectType)}{FormatSignedValue(effect.value)}");
string valueText = (isTypeSameEffectSection || isMaxLevelEffectSection)
? FormatSignedPercent(effect.value)
: FormatSignedValue(effect.value);
lines.Add($"{GetEffectDisplayName(effect.effectType)}{valueText}");
}
return string.Join("\n", lines);
}
private float GetMaxLevelBoost(equipmentSO.EquipmentSpecialEffectType effectType)
{
if (eSO == null || eSO.maxLevelEffects == null)
{
return 0f;
}
for (int i = 0; i < eSO.maxLevelEffects.Length; i++)
{
equipmentSO.EquipmentSpecialEffect effect = eSO.maxLevelEffects[i];
if (effect == null || effect.effectType != effectType)
{
continue;
}
return effect.value;
}
return 0f;
}
private Sprite GetBottomSprite(int qualityIndex)
{
if (eqpmtBtmSprites == null || eqpmtBtmSprites.Length == 0)
@@ -553,29 +700,14 @@ public class eqpmtDesPrefab : MonoBehaviour
return profilebtmColor[safeIndex];
}
private static int GetQualityVisualIndex(int level)
private static int GetQualityVisualIndex(equipmentSO equipment)
{
if (level >= 20)
if (equipment == null)
{
return 5;
return 0;
}
if (level >= 15)
{
return 4;
}
if (level >= 10)
{
return 3;
}
if (level >= 5)
{
return 2;
}
return 1;
return equipment.GetVisualQualityColorIndex();
}
private static string GetEffectDisplayName(equipmentSO.EquipmentSpecialEffectType effectType)
@@ -612,6 +744,12 @@ public class eqpmtDesPrefab : MonoBehaviour
return $"{(value >= 0f ? "+" : string.Empty)}{value:0.####}";
}
private static string FormatSignedPercent(float value)
{
float percent = value * 100f;
return $"{(percent >= 0f ? "+" : string.Empty)}{percent:0.##}%";
}
private static string BuildDisplayEquipmentId(equipmentSO equipment)
{
if (equipment == null || string.IsNullOrWhiteSpace(equipment.name))
@@ -637,4 +775,3 @@ public class eqpmtDesPrefab : MonoBehaviour
equipment.name.Contains("(TourPreview)");
}
}
File diff suppressed because it is too large Load Diff
+71 -2
View File
@@ -1,5 +1,6 @@
using UnityEngine;
using UnityEngine.UI;
using TMPro;
public class eqpmtSkillPrefabItem : MonoBehaviour
{
@@ -11,20 +12,88 @@ public class eqpmtSkillPrefabItem : MonoBehaviour
public void Bind(int id)
{
skillId = id;
SkillGroup skillGroup = EquipmentSkillGroupLibrary.ResolveSkillGroup(skillId);
string displayName = skillGroup != null && !string.IsNullOrWhiteSpace(skillGroup.groupName)
? skillGroup.groupName
: $"Skill {skillId}";
Sprite displayIcon = skillGroup != null ? skillGroup.groupIcon : null;
EnsureFallbackReferences();
if (skillName != null)
{
skillName.text = $"Skill {skillId}";
skillName.text = displayName;
}
else
{
TMP_Text tmpName = GetFirstTmpTextExcludingId();
if (tmpName != null)
{
tmpName.text = displayName;
}
}
if (skillIdText != null)
{
skillIdText.text = skillId.ToString();
}
else
{
TMP_Text tmpId = GetLastTmpText();
if (tmpId != null)
{
tmpId.text = skillId.ToString();
}
}
if (skillIcon != null)
{
skillIcon.enabled = skillIcon.sprite != null;
skillIcon.sprite = displayIcon;
skillIcon.enabled = displayIcon != null;
}
}
private void EnsureFallbackReferences()
{
if (skillIcon == null)
{
Image[] images = GetComponentsInChildren<Image>(true);
for (int i = 0; i < images.Length; i++)
{
if (images[i] != null && images[i] != GetComponent<Image>())
{
skillIcon = images[i];
break;
}
}
}
if (skillName == null || skillIdText == null)
{
Text[] texts = GetComponentsInChildren<Text>(true);
if (texts.Length > 0)
{
if (skillName == null)
{
skillName = texts[0];
}
if (skillIdText == null && texts.Length > 1)
{
skillIdText = texts[texts.Length - 1];
}
}
}
}
private TMP_Text GetFirstTmpTextExcludingId()
{
TMP_Text[] texts = GetComponentsInChildren<TMP_Text>(true);
return texts.Length > 0 ? texts[0] : null;
}
private TMP_Text GetLastTmpText()
{
TMP_Text[] texts = GetComponentsInChildren<TMP_Text>(true);
return texts.Length > 1 ? texts[texts.Length - 1] : null;
}
}
+358 -40
View File
@@ -1,7 +1,9 @@
using System;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UI;
using Bansonic;
#if UNITY_EDITOR
@@ -10,15 +12,81 @@ using UnityEditor;
public class equipBag : MonoBehaviour
{
private enum EquipFilterMode
{
All,
HasSpecialSkill,
HasIllusionSkill,
HasAnySkill,
HasNoSkill,
HasDualSkill,
Type0,
Type1,
Type2,
Type3,
Type4,
Type5,
Type6,
Type7
}
private enum EquipOrderMode
{
AcquireAsc,
AcquireDesc,
QualityAsc,
QualityDesc
}
[Header("prefab")]
public GameObject eqpmtItemPrefab;
public Transform eqpmtItemParent;
[Header("dropdown")]
public Dropdown orderDropdown;
public Dropdown filterDropdown;
[Header("source paths")]
public string runtimeEquipmentFolder = "so/uEquip";
public string editorEquipmentFolder = "Assets/Resources/so/uEquip";
[Header("async spawn")]
public int spawnBatchSize = 12;
private readonly List<GameObject> spawnedItems = new List<GameObject>();
private Coroutine rebuildCoroutine;
private bool suppressDropdownCallbacks;
private static readonly (EquipFilterMode mode, string label)[] FilterOptions =
{
(EquipFilterMode.All, "全部"),
(EquipFilterMode.HasSpecialSkill, "含特效技能"),
(EquipFilterMode.HasIllusionSkill, "含巡演技能"),
(EquipFilterMode.HasAnySkill, "含技能"),
(EquipFilterMode.HasNoSkill, "不含技能"),
(EquipFilterMode.HasDualSkill, "含双技能"),
(EquipFilterMode.Type0, equipmentSO.EquipmentSkillType..ToString()),
(EquipFilterMode.Type1, equipmentSO.EquipmentSkillType..ToString()),
(EquipFilterMode.Type2, equipmentSO.EquipmentSkillType..ToString()),
(EquipFilterMode.Type3, equipmentSO.EquipmentSkillType..ToString()),
(EquipFilterMode.Type4, equipmentSO.EquipmentSkillType..ToString()),
(EquipFilterMode.Type5, equipmentSO.EquipmentSkillType..ToString()),
(EquipFilterMode.Type6, equipmentSO.EquipmentSkillType..ToString()),
(EquipFilterMode.Type7, equipmentSO.EquipmentSkillType..ToString())
};
private static readonly (EquipOrderMode mode, string label)[] OrderOptions =
{
(EquipOrderMode.AcquireAsc, "获取时间升序"),
(EquipOrderMode.AcquireDesc, "获取时间降序"),
(EquipOrderMode.QualityAsc, "品质升序"),
(EquipOrderMode.QualityDesc, "品质降序")
};
private void Awake()
{
InitializeDropdowns();
}
private void Start()
{
@@ -27,11 +95,37 @@ public class equipBag : MonoBehaviour
private void OnEnable()
{
InitializeDropdowns();
Rebuild();
}
private void OnDisable()
{
if (orderDropdown != null)
{
orderDropdown.onValueChanged.RemoveListener(HandleOrderChanged);
}
if (filterDropdown != null)
{
filterDropdown.onValueChanged.RemoveListener(HandleFilterChanged);
}
if (rebuildCoroutine != null)
{
StopCoroutine(rebuildCoroutine);
rebuildCoroutine = null;
}
}
public void Rebuild()
{
if (rebuildCoroutine != null)
{
StopCoroutine(rebuildCoroutine);
rebuildCoroutine = null;
}
ClearSpawnedItems();
if (eqpmtItemPrefab == null || eqpmtItemParent == null)
@@ -39,41 +133,133 @@ public class equipBag : MonoBehaviour
return;
}
equipmentSO[] equipments = LoadEquipments();
if (equipments == null || equipments.Length == 0)
List<equipmentSO> equipments = LoadEquipments()
.Where(equipment => equipment != null
&& !equipSmelt.IsEquipmentAssignedToSmeltPool(equipment)
&& !equipSmelt.ShouldHideConsumedEquipment(equipment))
.Where(MatchesCurrentFilter)
.ToList();
SortEquipments(equipments);
if (Application.isPlaying && isActiveAndEnabled && gameObject.activeInHierarchy)
{
rebuildCoroutine = StartCoroutine(RebuildAsync(equipments));
return;
}
SpawnAllImmediate(equipments);
}
private void InitializeDropdowns()
{
InitializeFilterDropdown();
InitializeOrderDropdown();
}
private void InitializeFilterDropdown()
{
if (filterDropdown == null)
{
return;
}
equipments = equipments
.Where(equipment => equipment != null
&& !equipSmelt.IsEquipmentAssignedToSmeltPool(equipment)
&& !equipSmelt.IsEquipmentConsumedBySmelt(equipment))
.ToArray();
suppressDropdownCallbacks = true;
filterDropdown.onValueChanged.RemoveListener(HandleFilterChanged);
filterDropdown.ClearOptions();
filterDropdown.AddOptions(FilterOptions.Select(option => new Dropdown.OptionData(option.label)).ToList());
filterDropdown.value = 0;
filterDropdown.RefreshShownValue();
filterDropdown.onValueChanged.AddListener(HandleFilterChanged);
suppressDropdownCallbacks = false;
}
Array.Sort(equipments, CompareEquipments);
for (int i = 0; i < equipments.Length; i++)
private void InitializeOrderDropdown()
{
if (orderDropdown == null)
{
equipmentSO equipment = equipments[i];
if (equipment == null)
{
continue;
}
GameObject instance = Instantiate(eqpmtItemPrefab, eqpmtItemParent);
instance.name = string.IsNullOrWhiteSpace(equipment.GetCurrentTierDisplayName())
? equipment.name
: equipment.GetCurrentTierDisplayName();
equipItemPrefab item = instance.GetComponent<equipItemPrefab>();
if (item != null)
{
item.Bind(equipment, HandleEquipmentClicked);
}
spawnedItems.Add(instance);
return;
}
suppressDropdownCallbacks = true;
orderDropdown.onValueChanged.RemoveListener(HandleOrderChanged);
orderDropdown.ClearOptions();
orderDropdown.AddOptions(OrderOptions.Select(option => new Dropdown.OptionData(option.label)).ToList());
orderDropdown.value = 0;
orderDropdown.RefreshShownValue();
orderDropdown.onValueChanged.AddListener(HandleOrderChanged);
suppressDropdownCallbacks = false;
}
private void HandleFilterChanged(int _)
{
if (!suppressDropdownCallbacks)
{
Rebuild();
}
}
private void HandleOrderChanged(int _)
{
if (!suppressDropdownCallbacks)
{
Rebuild();
}
}
private IEnumerator RebuildAsync(List<equipmentSO> equipments)
{
if (equipments == null || equipments.Count == 0)
{
rebuildCoroutine = null;
yield break;
}
int batchSize = Mathf.Max(1, spawnBatchSize);
for (int i = 0; i < equipments.Count; i++)
{
SpawnOne(equipments[i]);
if ((i + 1) % batchSize == 0)
{
yield return null;
}
}
rebuildCoroutine = null;
}
private void SpawnAllImmediate(List<equipmentSO> equipments)
{
if (equipments == null)
{
return;
}
for (int i = 0; i < equipments.Count; i++)
{
SpawnOne(equipments[i]);
}
}
private void SpawnOne(equipmentSO equipment)
{
if (equipment == null || eqpmtItemPrefab == null || eqpmtItemParent == null)
{
return;
}
GameObject instance = Instantiate(eqpmtItemPrefab, eqpmtItemParent);
string displayName = equipment.GetDisplayTierName();
instance.name = string.IsNullOrWhiteSpace(displayName) ? equipment.name : displayName;
equipItemPrefab item = instance.GetComponent<equipItemPrefab>();
if (item != null)
{
item.Bind(equipment, HandleEquipmentClicked);
}
spawnedItems.Add(instance);
}
private equipmentSO[] LoadEquipments()
@@ -104,9 +290,7 @@ public class equipBag : MonoBehaviour
}
}
return results
.Where(equipment => equipment != null)
.ToArray();
return results.Where(equipment => equipment != null).ToArray();
}
#if UNITY_EDITOR
@@ -119,7 +303,6 @@ public class equipBag : MonoBehaviour
string[] guids = AssetDatabase.FindAssets("t:equipmentSO", new[] { editorEquipmentFolder });
var result = new List<equipmentSO>(guids.Length);
for (int i = 0; i < guids.Length; i++)
{
string path = AssetDatabase.GUIDToAssetPath(guids[i]);
@@ -134,6 +317,75 @@ public class equipBag : MonoBehaviour
}
#endif
private bool MatchesCurrentFilter(equipmentSO equipment)
{
if (equipment == null)
{
return false;
}
EquipFilterMode mode = GetSelectedFilterMode();
bool hasSpecialSkill = equipment.sa_skillID > 0;
bool hasIllusionSkill = equipment.ia_skillID > 0;
switch (mode)
{
case EquipFilterMode.All:
return true;
case EquipFilterMode.HasSpecialSkill:
return hasSpecialSkill;
case EquipFilterMode.HasIllusionSkill:
return hasIllusionSkill;
case EquipFilterMode.HasAnySkill:
return hasSpecialSkill || hasIllusionSkill;
case EquipFilterMode.HasNoSkill:
return !hasSpecialSkill && !hasIllusionSkill;
case EquipFilterMode.HasDualSkill:
return hasSpecialSkill && hasIllusionSkill;
case EquipFilterMode.Type0:
return equipment.skillType == equipmentSO.EquipmentSkillType.;
case EquipFilterMode.Type1:
return equipment.skillType == equipmentSO.EquipmentSkillType.;
case EquipFilterMode.Type2:
return equipment.skillType == equipmentSO.EquipmentSkillType.;
case EquipFilterMode.Type3:
return equipment.skillType == equipmentSO.EquipmentSkillType.;
case EquipFilterMode.Type4:
return equipment.skillType == equipmentSO.EquipmentSkillType.;
case EquipFilterMode.Type5:
return equipment.skillType == equipmentSO.EquipmentSkillType.;
case EquipFilterMode.Type6:
return equipment.skillType == equipmentSO.EquipmentSkillType.;
case EquipFilterMode.Type7:
return equipment.skillType == equipmentSO.EquipmentSkillType.;
default:
return true;
}
}
private void SortEquipments(List<equipmentSO> equipments)
{
if (equipments == null)
{
return;
}
EquipOrderMode mode = GetSelectedOrderMode();
equipments.Sort((left, right) => CompareEquipments(left, right, mode));
}
private EquipFilterMode GetSelectedFilterMode()
{
int index = filterDropdown != null ? Mathf.Clamp(filterDropdown.value, 0, FilterOptions.Length - 1) : 0;
return FilterOptions[index].mode;
}
private EquipOrderMode GetSelectedOrderMode()
{
int index = orderDropdown != null ? Mathf.Clamp(orderDropdown.value, 0, OrderOptions.Length - 1) : 0;
return OrderOptions[index].mode;
}
private void HandleEquipmentClicked(equipmentSO equipment)
{
if (equipment == null)
@@ -170,7 +422,7 @@ public class equipBag : MonoBehaviour
spawnedItems.Clear();
}
private static int CompareEquipments(equipmentSO left, equipmentSO right)
private static int CompareEquipments(equipmentSO left, equipmentSO right, EquipOrderMode mode)
{
if (left == right)
{
@@ -187,14 +439,80 @@ public class equipBag : MonoBehaviour
return -1;
}
int levelCompare = right.level.CompareTo(left.level);
if (levelCompare != 0)
switch (mode)
{
return levelCompare;
case EquipOrderMode.AcquireAsc:
return CompareAcquire(left, right, false);
case EquipOrderMode.AcquireDesc:
return CompareAcquire(left, right, true);
case EquipOrderMode.QualityAsc:
return CompareQuality(left, right, false);
case EquipOrderMode.QualityDesc:
return CompareQuality(left, right, true);
default:
return CompareAcquire(left, right, false);
}
}
private static int CompareAcquire(equipmentSO left, equipmentSO right, bool descending)
{
ParseEquipmentSortKey(left, out long leftDate, out long leftId);
ParseEquipmentSortKey(right, out long rightDate, out long rightId);
int dateCompare = leftDate.CompareTo(rightDate);
if (dateCompare != 0)
{
return descending ? -dateCompare : dateCompare;
}
string leftName = left.GetCurrentTierDisplayName();
string rightName = right.GetCurrentTierDisplayName();
return string.Compare(leftName, rightName, StringComparison.Ordinal);
int idCompare = leftId.CompareTo(rightId);
if (idCompare != 0)
{
return descending ? -idCompare : idCompare;
}
string leftName = left.GetDisplayTierName();
string rightName = right.GetDisplayTierName();
int nameCompare = string.Compare(leftName, rightName, StringComparison.Ordinal);
return descending ? -nameCompare : nameCompare;
}
private static int CompareQuality(equipmentSO left, equipmentSO right, bool descending)
{
int qualityCompare = left.GetVisualQualityColorIndex().CompareTo(right.GetVisualQualityColorIndex());
if (qualityCompare != 0)
{
return descending ? -qualityCompare : qualityCompare;
}
return CompareAcquire(left, right, true);
}
private static void ParseEquipmentSortKey(equipmentSO equipment, out long datePart, out long idPart)
{
datePart = 0L;
idPart = 0L;
if (equipment == null || string.IsNullOrWhiteSpace(equipment.name))
{
return;
}
string raw = equipment.name;
if (raw.StartsWith("type", StringComparison.OrdinalIgnoreCase))
{
int firstUnderscore = raw.IndexOf('_');
if (firstUnderscore >= 0 && firstUnderscore + 1 < raw.Length)
{
raw = raw.Substring(firstUnderscore + 1);
}
}
string[] parts = raw.Split('_');
if (parts.Length >= 2)
{
long.TryParse(parts[0], out datePart);
long.TryParse(parts[1], out idPart);
}
}
}
+192 -22
View File
@@ -3,6 +3,9 @@ using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using UnityEngine.UI;
#if UNITY_EDITOR
using UnityEditor;
#endif
public class equipItemPrefab : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler, IPointerClickHandler
{
@@ -29,7 +32,11 @@ public class equipItemPrefab : MonoBehaviour, IBeginDragHandler, IDragHandler, I
public bool allowDrag = true;
public bool allowQuickTransfer = true;
[Header("equipperProfile")]
public Image equipperProfileIcon;
private Action<equipmentSO> clickHandler;
private Func<equipmentSO, bool> rightClickHandler;
private GameObject spawnedDescription;
private bool suppressNextClick;
private Canvas rootCanvas;
@@ -58,22 +65,25 @@ public class equipItemPrefab : MonoBehaviour, IBeginDragHandler, IDragHandler, I
}
}
public void Bind(equipmentSO so, Action<equipmentSO> onClick = null)
public void Bind(equipmentSO so, Action<equipmentSO> onClick = null, Func<equipmentSO, bool> onRightClick = null)
{
itemSO = so;
clickHandler = onClick;
rightClickHandler = onRightClick;
if (itemSO == null)
{
ApplyProfileSprite(null);
ApplyBottomColor(0);
ApplyEquipperProfile(null);
return;
}
equipmentSO.EquipmentTierPresentation presentation = itemSO.GetCurrentTierPresentation();
equipmentSO.EquipmentTierPresentation presentation = itemSO.GetVisualTierPresentation();
Sprite displaySprite = presentation != null ? presentation.equipmentSprite : null;
ApplyProfileSprite(displaySprite);
ApplyBottomColor(GetQualityColorIndex(itemSO.level));
ApplyBottomColor(itemSO.GetVisualQualityColorIndex());
ApplyEquipperProfile(FindEquipper(itemSO));
}
private void HandleClicked()
@@ -214,7 +224,12 @@ public class equipItemPrefab : MonoBehaviour, IBeginDragHandler, IDragHandler, I
isDraggingWithLeftButton = false;
equipUpdate matchedUpdateTarget = FindMatchingUpdateTarget(eventData);
equipIllusion matchedIllusionTarget = matchedUpdateTarget == null ? FindMatchingIllusionTarget(eventData) : null;
equipSmelt matchedSmeltTarget = matchedUpdateTarget == null && matchedIllusionTarget == null ? FindMatchingSmeltTarget(eventData) : null;
eFinalDream matchedFinalDreamTarget = matchedUpdateTarget == null && matchedIllusionTarget == null ? FindMatchingFinalDreamTarget(eventData) : null;
equipTransfer matchedTransferTarget = matchedUpdateTarget == null && matchedIllusionTarget == null && matchedFinalDreamTarget == null ? FindMatchingTransferTarget(eventData) : null;
equipTransfer.TransferDropSlot matchedTransferSlot = matchedTransferTarget != null
? matchedTransferTarget.GetHoveredDropSlot(eventData != null ? eventData.position : (Vector2)Input.mousePosition, eventData != null && eventData.pressEventCamera != null ? eventData.pressEventCamera : uiCamera)
: equipTransfer.TransferDropSlot.None;
equipSmelt matchedSmeltTarget = matchedUpdateTarget == null && matchedIllusionTarget == null && matchedFinalDreamTarget == null && matchedTransferTarget == null ? FindMatchingSmeltTarget(eventData) : null;
bool cameFromSmeltPool = equipSmelt.IsEquipmentAssignedToSmeltPool(itemSO);
SetAllDragTargetsVisible(false);
@@ -232,6 +247,21 @@ public class equipItemPrefab : MonoBehaviour, IBeginDragHandler, IDragHandler, I
return;
}
if (matchedFinalDreamTarget != null)
{
matchedFinalDreamTarget.AcceptDraggedEquipment(itemSO);
return;
}
if (matchedTransferTarget != null)
{
if (matchedTransferSlot != equipTransfer.TransferDropSlot.None)
{
matchedTransferTarget.AcceptDraggedEquipment(itemSO, matchedTransferSlot);
return;
}
}
if (matchedSmeltTarget != null)
{
matchedSmeltTarget.AcceptDraggedEquipment(itemSO);
@@ -246,17 +276,41 @@ public class equipItemPrefab : MonoBehaviour, IBeginDragHandler, IDragHandler, I
public void OnPointerClick(PointerEventData eventData)
{
if (!allowQuickTransfer || eventData == null || eventData.button != PointerEventData.InputButton.Right || itemSO == null)
if (eventData == null || itemSO == null)
{
return;
}
if (equipSmelt.TryHandleQuickTransfer(itemSO))
if (eventData.button == PointerEventData.InputButton.Right)
{
isDraggingWithLeftButton = false;
SetAllDragTargetsVisible(false);
DestroyDragGhost();
suppressNextClick = true;
if (rightClickHandler != null && rightClickHandler.Invoke(itemSO))
{
isDraggingWithLeftButton = false;
SetAllDragTargetsVisible(false);
DestroyDragGhost();
suppressNextClick = true;
return;
}
if (!allowQuickTransfer)
{
return;
}
if (equipSmelt.TryHandleQuickTransfer(itemSO))
{
isDraggingWithLeftButton = false;
SetAllDragTargetsVisible(false);
DestroyDragGhost();
suppressNextClick = true;
}
return;
}
if (eventData.button != PointerEventData.InputButton.Left)
{
return;
}
}
@@ -329,6 +383,52 @@ public class equipItemPrefab : MonoBehaviour, IBeginDragHandler, IDragHandler, I
return null;
}
private equipTransfer FindMatchingTransferTarget(PointerEventData eventData)
{
equipTransfer[] targets = FindObjectsOfType<equipTransfer>(true);
if (targets == null || targets.Length == 0)
{
return null;
}
Vector2 pointerPosition = eventData != null ? eventData.position : (Vector2)Input.mousePosition;
Camera eventCamera = eventData != null && eventData.pressEventCamera != null ? eventData.pressEventCamera : uiCamera;
for (int i = 0; i < targets.Length; i++)
{
equipTransfer target = targets[i];
if (target != null && target.gameObject.activeInHierarchy && target.GetHoveredDropSlot(pointerPosition, eventCamera) != equipTransfer.TransferDropSlot.None)
{
return target;
}
}
return null;
}
private eFinalDream FindMatchingFinalDreamTarget(PointerEventData eventData)
{
eFinalDream[] targets = FindObjectsOfType<eFinalDream>(true);
if (targets == null || targets.Length == 0)
{
return null;
}
Vector2 pointerPosition = eventData != null ? eventData.position : (Vector2)Input.mousePosition;
Camera eventCamera = eventData != null && eventData.pressEventCamera != null ? eventData.pressEventCamera : uiCamera;
for (int i = 0; i < targets.Length; i++)
{
eFinalDream target = targets[i];
if (target != null && target.gameObject.activeInHierarchy && target.IsPointerOverDropArea(pointerPosition, eventCamera))
{
return target;
}
}
return null;
}
private void CreateDragGhost()
{
DestroyDragGhost();
@@ -467,6 +567,30 @@ public class equipItemPrefab : MonoBehaviour, IBeginDragHandler, IDragHandler, I
}
}
}
eFinalDream[] finalDreamTargets = FindObjectsOfType<eFinalDream>(true);
if (finalDreamTargets != null)
{
for (int i = 0; i < finalDreamTargets.Length; i++)
{
if (finalDreamTargets[i] != null && finalDreamTargets[i].gameObject.activeInHierarchy)
{
finalDreamTargets[i].SetDragPreviewVisible(visible);
}
}
}
equipTransfer[] transferTargets = FindObjectsOfType<equipTransfer>(true);
if (transferTargets != null)
{
for (int i = 0; i < transferTargets.Length; i++)
{
if (transferTargets[i] != null && transferTargets[i].gameObject.activeInHierarchy)
{
transferTargets[i].SetDragPreviewVisible(visible);
}
}
}
}
private void ApplyProfileSprite(Sprite sprite)
@@ -495,29 +619,75 @@ public class equipItemPrefab : MonoBehaviour, IBeginDragHandler, IDragHandler, I
itemBtm.color = color;
}
private static int GetQualityColorIndex(int level)
private void ApplyEquipperProfile(AllyHero_SO hero)
{
if (level >= 20)
if (equipperProfileIcon == null)
{
return 5;
return;
}
if (level >= 15)
Sprite sprite = hero != null ? hero.ally_hero_squareProfile : null;
equipperProfileIcon.sprite = sprite;
equipperProfileIcon.color = sprite != null ? Color.white : new Color(1f, 1f, 1f, 0f);
equipperProfileIcon.enabled = true;
}
private AllyHero_SO FindEquipper(equipmentSO equipment)
{
if (equipment == null)
{
return 4;
return null;
}
if (level >= 10)
AllyHero_SO[] heroes = LoadHeroAssets();
for (int i = 0; i < heroes.Length; i++)
{
return 3;
AllyHero_SO hero = heroes[i];
if (hero == null)
{
continue;
}
hero.LoadEquippedEquipmentFromLocal();
equipmentSO equipped = hero.GetEquippedEquipmentResolved();
if (equipped == equipment || (!string.IsNullOrWhiteSpace(equipped?.name) && equipped.name == equipment.name))
{
return hero;
}
}
if (level >= 5)
{
return 2;
}
return null;
}
return 1;
private AllyHero_SO[] LoadHeroAssets()
{
#if UNITY_EDITOR
if (!Application.isPlaying)
{
string[] guids = AssetDatabase.FindAssets("t:AllyHero_SO", new[] { "Assets/Resources/so/ally" });
var heroes = new AllyHero_SO[guids.Length];
int count = 0;
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[count++] = hero;
}
}
if (count == heroes.Length)
{
return heroes;
}
Array.Resize(ref heroes, count);
return heroes;
}
#endif
return Resources.LoadAll<AllyHero_SO>("so/ally");
}
public void SetInteractionOptions(bool dragEnabled, bool quickTransferEnabled)
+79
View File
@@ -34,6 +34,7 @@ RectTransform:
m_Children:
- {fileID: 8306989158517587553}
- {fileID: 4501911813970791622}
- {fileID: 6659102487498592916}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
@@ -80,6 +81,9 @@ MonoBehaviour:
onItemClicked:
m_PersistentCalls:
m_Calls: []
allowDrag: 1
allowQuickTransfer: 1
equipperProfileIcon: {fileID: 6153289789242379004}
--- !u!114 &2742497410143989620
MonoBehaviour:
m_ObjectHideFlags: 0
@@ -308,3 +312,78 @@ MonoBehaviour:
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &9173486993486932335
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 6659102487498592916}
- component: {fileID: 6606557728545243211}
- component: {fileID: 6153289789242379004}
m_Layer: 5
m_Name: equipperProfile
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &6659102487498592916
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 9173486993486932335}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 4791772059149409634}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 38.993774, y: -38.993774}
m_SizeDelta: {x: 30.1081, y: 30.1081}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &6606557728545243211
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 9173486993486932335}
m_CullTransparentMesh: 1
--- !u!114 &6153289789242379004
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 9173486993486932335}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 0}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
@@ -0,0 +1,231 @@
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
public class chooseSkillPrefab : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler
{
public Image this_skillProfile;
public Text this_skillName;
public Button this_skillDesButton;
public GameObject sskilldetialPrefab;
public Vector2 detailPrefabOffset = new Vector2(20f, 0f);
public float hoverDetailDelay = 0.25f;
private int boundSkillGroupId;
private string boundDescription;
private Sprite boundIcon;
private string boundName;
private GameObject spawnedDetail;
private Coroutine hoverDetailCoroutine;
private bool detailPinnedByButton;
private int detailOpenedFrame = -1;
public void Bind(int skillGroupId, string skillName, Sprite skillIcon, string skillDescription, System.Action<int> onSelected)
{
boundSkillGroupId = skillGroupId;
boundName = skillName ?? string.Empty;
boundIcon = skillIcon;
boundDescription = skillDescription ?? string.Empty;
if (this_skillName != null)
{
this_skillName.text = boundName;
}
if (this_skillProfile != null)
{
this_skillProfile.sprite = boundIcon;
this_skillProfile.enabled = boundIcon != null;
}
Button rootButton = GetComponent<Button>();
if (rootButton != null)
{
rootButton.onClick.RemoveAllListeners();
rootButton.onClick.AddListener(() => onSelected?.Invoke(boundSkillGroupId));
}
if (this_skillDesButton != null)
{
this_skillDesButton.onClick.RemoveAllListeners();
this_skillDesButton.onClick.AddListener(TogglePinnedDetail);
}
}
private void Update()
{
if (!detailPinnedByButton || spawnedDetail == null)
{
return;
}
if (detailOpenedFrame == Time.frameCount)
{
return;
}
if (!Input.GetMouseButtonDown(0))
{
return;
}
Vector2 screenPoint = Input.mousePosition;
if (IsPointerInside(screenPoint))
{
return;
}
CloseDetail();
}
public void OnPointerEnter(PointerEventData eventData)
{
if (detailPinnedByButton)
{
return;
}
StopHoverCoroutine();
hoverDetailCoroutine = StartCoroutine(ShowHoverDetailDelayed());
}
public void OnPointerExit(PointerEventData eventData)
{
StopHoverCoroutine();
if (!detailPinnedByButton)
{
CloseDetail();
}
}
private System.Collections.IEnumerator ShowHoverDetailDelayed()
{
yield return new WaitForSeconds(hoverDetailDelay);
if (!detailPinnedByButton)
{
ShowDetail(false);
}
}
private void TogglePinnedDetail()
{
StopHoverCoroutine();
if (detailPinnedByButton)
{
CloseDetail();
return;
}
ShowDetail(true);
}
private void ShowDetail(bool pinnedByButton)
{
if (sskilldetialPrefab == null)
{
return;
}
if (spawnedDetail != null)
{
Destroy(spawnedDetail);
spawnedDetail = null;
}
detailPinnedByButton = pinnedByButton;
detailOpenedFrame = Time.frameCount;
Transform parent = transform.root != null ? transform.root : transform;
spawnedDetail = Instantiate(sskilldetialPrefab, parent);
RectTransform selfRect = transform as RectTransform;
RectTransform detailRect = spawnedDetail.transform as RectTransform;
RectTransform parentRect = parent as RectTransform;
if (selfRect != null && detailRect != null && parentRect != null)
{
Vector3 worldPoint = selfRect.TransformPoint(new Vector3(selfRect.rect.xMax, selfRect.rect.center.y, 0f));
RectTransformUtility.ScreenPointToLocalPointInRectangle(
parentRect,
RectTransformUtility.WorldToScreenPoint(null, worldPoint),
null,
out Vector2 localPoint);
detailRect.anchoredPosition = localPoint + detailPrefabOffset;
}
esDesPrefab detail = spawnedDetail.GetComponent<esDesPrefab>();
if (detail != null)
{
detail.Bind(boundName, boundIcon, boundDescription);
}
}
private bool IsPointerInside(Vector2 screenPoint)
{
if (IsScreenPointInside(transform as RectTransform, screenPoint))
{
return true;
}
if (this_skillDesButton != null && IsScreenPointInside(this_skillDesButton.transform as RectTransform, screenPoint))
{
return true;
}
if (spawnedDetail != null && IsScreenPointInside(spawnedDetail.transform as RectTransform, screenPoint))
{
return true;
}
return false;
}
private static bool IsScreenPointInside(RectTransform rectTransform, Vector2 screenPoint)
{
if (rectTransform == null || !rectTransform.gameObject.activeInHierarchy)
{
return false;
}
Canvas canvas = rectTransform.GetComponentInParent<Canvas>();
Camera eventCamera = null;
if (canvas != null && canvas.renderMode != RenderMode.ScreenSpaceOverlay)
{
eventCamera = canvas.worldCamera;
}
return RectTransformUtility.RectangleContainsScreenPoint(rectTransform, screenPoint, eventCamera);
}
private void StopHoverCoroutine()
{
if (hoverDetailCoroutine == null)
{
return;
}
StopCoroutine(hoverDetailCoroutine);
hoverDetailCoroutine = null;
}
private void CloseDetail()
{
detailPinnedByButton = false;
detailOpenedFrame = -1;
if (spawnedDetail != null)
{
Destroy(spawnedDetail);
spawnedDetail = null;
}
}
private void OnDisable()
{
StopHoverCoroutine();
CloseDetail();
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 4a002a533d952044e99ced618da6b97b
@@ -0,0 +1,496 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &173329114046312084
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 6948992549612643637}
- component: {fileID: 3797265141853648049}
- component: {fileID: 2179590550443923467}
- component: {fileID: 8722769725204961295}
m_Layer: 5
m_Name: detailBtn
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &6948992549612643637
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 173329114046312084}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 520209867874083116}
m_Father: {fileID: 5682187843182433583}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 166.44, y: 0}
m_SizeDelta: {x: 57.159, y: 30}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &3797265141853648049
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 173329114046312084}
m_CullTransparentMesh: 1
--- !u!114 &2179590550443923467
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 173329114046312084}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 21300000, guid: 7f3b1220317607e44bbb8f0e1998044a, type: 3}
m_Type: 1
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 3
--- !u!114 &8722769725204961295
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 173329114046312084}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Navigation:
m_Mode: 3
m_WrapAround: 0
m_SelectOnUp: {fileID: 0}
m_SelectOnDown: {fileID: 0}
m_SelectOnLeft: {fileID: 0}
m_SelectOnRight: {fileID: 0}
m_Transition: 1
m_Colors:
m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
m_ColorMultiplier: 1
m_FadeDuration: 0.1
m_SpriteState:
m_HighlightedSprite: {fileID: 0}
m_PressedSprite: {fileID: 0}
m_SelectedSprite: {fileID: 0}
m_DisabledSprite: {fileID: 0}
m_AnimationTriggers:
m_NormalTrigger: Normal
m_HighlightedTrigger: Highlighted
m_PressedTrigger: Pressed
m_SelectedTrigger: Selected
m_DisabledTrigger: Disabled
m_Interactable: 1
m_TargetGraphic: {fileID: 2179590550443923467}
m_OnClick:
m_PersistentCalls:
m_Calls: []
--- !u!1 &498629673022906363
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 8418499460120133954}
- component: {fileID: 2431993488817707215}
- component: {fileID: 1689633676752662567}
m_Layer: 5
m_Name: Text (Legacy)
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &8418499460120133954
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 498629673022906363}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 5682187843182433583}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 26.263, y: 0}
m_SizeDelta: {x: -52.526, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &2431993488817707215
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 498629673022906363}
m_CullTransparentMesh: 1
--- !u!114 &1689633676752662567
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 498629673022906363}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_FontData:
m_Font: {fileID: 12800000, guid: dfa10de3e2846524089b5073175cd151, type: 3}
m_FontSize: 20
m_FontStyle: 0
m_BestFit: 0
m_MinSize: 1
m_MaxSize: 40
m_Alignment: 3
m_AlignByGeometry: 0
m_RichText: 1
m_HorizontalOverflow: 0
m_VerticalOverflow: 0
m_LineSpacing: 1
m_Text: "\u8FD9\u662F\u6280\u80FD\u7684\u540D\u5B57"
--- !u!1 &2926807448563683594
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 7467472050194746834}
- component: {fileID: 2938015134650813531}
- component: {fileID: 3338892377370932306}
m_Layer: 5
m_Name: Image
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &7467472050194746834
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2926807448563683594}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 5682187843182433583}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: -181.8, y: 0}
m_SizeDelta: {x: 25, y: 25}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &2938015134650813531
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2926807448563683594}
m_CullTransparentMesh: 1
--- !u!114 &3338892377370932306
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2926807448563683594}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 0}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &5568386552701306322
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 5682187843182433583}
- component: {fileID: 224023005441735778}
- component: {fileID: 3266770909553366933}
- component: {fileID: 87417905198980801}
- component: {fileID: 7270931476603073231}
m_Layer: 5
m_Name: chooseSkillPrefab
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &5682187843182433583
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5568386552701306322}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 8418499460120133954}
- {fileID: 7467472050194746834}
- {fileID: 6948992549612643637}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 1}
m_AnchorMax: {x: 0, y: 1}
m_AnchoredPosition: {x: 251.5, y: -27.5}
m_SizeDelta: {x: 420, y: 45}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &224023005441735778
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5568386552701306322}
m_CullTransparentMesh: 1
--- !u!114 &3266770909553366933
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5568386552701306322}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 4a002a533d952044e99ced618da6b97b, type: 3}
m_Name:
m_EditorClassIdentifier:
this_skillProfile: {fileID: 3338892377370932306}
this_skillName: {fileID: 1689633676752662567}
this_skillDesButton: {fileID: 8722769725204961295}
sskilldetialPrefab: {fileID: 2219571326304505587, guid: bde76837f913f3943836d4f83292618b, type: 3}
--- !u!114 &87417905198980801
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5568386552701306322}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: -7090641179508505894, guid: a92c5df7eef6ddc4ba91ad5dd2892af9, type: 3}
m_Type: 1
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 2
--- !u!114 &7270931476603073231
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5568386552701306322}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Navigation:
m_Mode: 3
m_WrapAround: 0
m_SelectOnUp: {fileID: 0}
m_SelectOnDown: {fileID: 0}
m_SelectOnLeft: {fileID: 0}
m_SelectOnRight: {fileID: 0}
m_Transition: 2
m_Colors:
m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
m_ColorMultiplier: 1
m_FadeDuration: 0.1
m_SpriteState:
m_HighlightedSprite: {fileID: 7919194353434859991, guid: b35fcaa46fa9f3e49b71c103f69df698, type: 3}
m_PressedSprite: {fileID: -52179173452712981, guid: be120bf969ae2c84fa997ecca6dd28e6, type: 3}
m_SelectedSprite: {fileID: -52179173452712981, guid: be120bf969ae2c84fa997ecca6dd28e6, type: 3}
m_DisabledSprite: {fileID: 0}
m_AnimationTriggers:
m_NormalTrigger: Normal
m_HighlightedTrigger: Highlighted
m_PressedTrigger: Pressed
m_SelectedTrigger: Selected
m_DisabledTrigger: Disabled
m_Interactable: 1
m_TargetGraphic: {fileID: 87417905198980801}
m_OnClick:
m_PersistentCalls:
m_Calls: []
--- !u!1 &8028886353611533317
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 520209867874083116}
- component: {fileID: 5250530122962945396}
- component: {fileID: 5860927567573704556}
m_Layer: 5
m_Name: Text (Legacy)
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &520209867874083116
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8028886353611533317}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 6948992549612643637}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &5250530122962945396
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8028886353611533317}
m_CullTransparentMesh: 1
--- !u!114 &5860927567573704556
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8028886353611533317}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_FontData:
m_Font: {fileID: 12800000, guid: dfa10de3e2846524089b5073175cd151, type: 3}
m_FontSize: 16
m_FontStyle: 0
m_BestFit: 0
m_MinSize: 1
m_MaxSize: 40
m_Alignment: 4
m_AlignByGeometry: 0
m_RichText: 1
m_HorizontalOverflow: 0
m_VerticalOverflow: 0
m_LineSpacing: 1
m_Text: "\u6548\u679C"
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 57c33f443e4107047a20a08158d45834
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,33 @@
using UnityEngine;
using UnityEngine.UI;
public class chooseTypePrefab : MonoBehaviour
{
public Text thisTypeName;
private equipmentSO.EquipmentSkillType boundType;
private System.Action<equipmentSO.EquipmentSkillType, chooseTypePrefab> onSelected;
public void Bind(equipmentSO.EquipmentSkillType skillType, System.Action<equipmentSO.EquipmentSkillType, chooseTypePrefab> onClick)
{
boundType = skillType;
onSelected = onClick;
if (thisTypeName != null)
{
thisTypeName.text = skillType.ToString();
}
Button button = GetComponent<Button>();
if (button != null)
{
button.onClick.RemoveAllListeners();
button.onClick.AddListener(HandleClicked);
}
}
private void HandleClicked()
{
onSelected?.Invoke(boundType, this);
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: d6f5c769df46c9441968db17e71ac515
@@ -0,0 +1,216 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &509855605911930734
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 287364384811699215}
- component: {fileID: 4444376122921135145}
- component: {fileID: 4398512319981001754}
- component: {fileID: 4580862515622367541}
- component: {fileID: 6643463829291932832}
m_Layer: 5
m_Name: chooseTypePrefab
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &287364384811699215
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 509855605911930734}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 8600346538228960391}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 90, y: 45}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &4444376122921135145
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 509855605911930734}
m_CullTransparentMesh: 1
--- !u!114 &4398512319981001754
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 509855605911930734}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: d6f5c769df46c9441968db17e71ac515, type: 3}
m_Name:
m_EditorClassIdentifier:
thisTypeName: {fileID: 5147610004911796692}
--- !u!114 &4580862515622367541
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 509855605911930734}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: -7090641179508505894, guid: a92c5df7eef6ddc4ba91ad5dd2892af9, type: 3}
m_Type: 1
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 2
--- !u!114 &6643463829291932832
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 509855605911930734}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Navigation:
m_Mode: 3
m_WrapAround: 0
m_SelectOnUp: {fileID: 0}
m_SelectOnDown: {fileID: 0}
m_SelectOnLeft: {fileID: 0}
m_SelectOnRight: {fileID: 0}
m_Transition: 2
m_Colors:
m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
m_ColorMultiplier: 1
m_FadeDuration: 0.1
m_SpriteState:
m_HighlightedSprite: {fileID: 7919194353434859991, guid: b35fcaa46fa9f3e49b71c103f69df698, type: 3}
m_PressedSprite: {fileID: -52179173452712981, guid: be120bf969ae2c84fa997ecca6dd28e6, type: 3}
m_SelectedSprite: {fileID: -52179173452712981, guid: be120bf969ae2c84fa997ecca6dd28e6, type: 3}
m_DisabledSprite: {fileID: 0}
m_AnimationTriggers:
m_NormalTrigger: Normal
m_HighlightedTrigger: Highlighted
m_PressedTrigger: Pressed
m_SelectedTrigger: Selected
m_DisabledTrigger: Disabled
m_Interactable: 1
m_TargetGraphic: {fileID: 4580862515622367541}
m_OnClick:
m_PersistentCalls:
m_Calls: []
--- !u!1 &6254854280988552205
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 8600346538228960391}
- component: {fileID: 1309857627089563026}
- component: {fileID: 5147610004911796692}
m_Layer: 5
m_Name: typeName
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &8600346538228960391
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6254854280988552205}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 287364384811699215}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0.000015258789}
m_SizeDelta: {x: 0, y: -0.000034332}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &1309857627089563026
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6254854280988552205}
m_CullTransparentMesh: 1
--- !u!114 &5147610004911796692
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6254854280988552205}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 0, g: 0, b: 0, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_FontData:
m_Font: {fileID: 12800000, guid: dfa10de3e2846524089b5073175cd151, type: 3}
m_FontSize: 18
m_FontStyle: 0
m_BestFit: 0
m_MinSize: 0
m_MaxSize: 40
m_Alignment: 4
m_AlignByGeometry: 0
m_RichText: 1
m_HorizontalOverflow: 0
m_VerticalOverflow: 0
m_LineSpacing: 1
m_Text: "\u9898\u6D77\u6218\u672F"
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 2532da4b61996d84481013479d675aa7
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+354
View File
@@ -0,0 +1,354 @@
using UnityEngine;
using UnityEngine.UI;
using System;
using System.Collections.Generic;
public class ctasPrefab : MonoBehaviour
{
[Header("template SO")]
public equipmentSO eTemplate;
public equipmentRandomConfigSO randomConfig;
[Header("objs")]
public GameObject select_type_obj;
public GameObject select_skill_obj;
[Header("prefab and parent")]
public GameObject select_typePrefab;
public Transform select_typeParent;
public GameObject select_skillPrefab;
public Transform select_skillParent;
[Header("text")]
public Text currentSelectText;
[Header("buttons")]
public Button yesSelectThis;
public Button noWaitButton;
private readonly List<GameObject> spawnedTypeItems = new List<GameObject>();
private readonly List<GameObject> spawnedSkillItems = new List<GameObject>();
private equipmentSO.EquipmentSkillType selectedType;
private int selectedSkillGroupId;
private string selectedSkillGroupName = string.Empty;
private GameObject selectedTypeObject;
private bool hasSelectedType;
private bool allowTypeSelection = true;
private bool allowSkillSelection;
private bool initializedExternally;
private Action<equipmentSO.EquipmentSkillType, int> onConfirmSelection;
private Action onClosed;
private void Start()
{
if (initializedExternally)
{
return;
}
BindButtons();
BuildTypeOptions();
ApplySelectionModeState();
UpdateCurrentSelectText();
RefreshButtons();
}
public void Initialize(equipmentSO template, equipmentRandomConfigSO config, bool requireTypeSelection, bool requireSkillSelection, Action<equipmentSO.EquipmentSkillType, int> onConfirm, Action closeCallback = null)
{
eTemplate = template;
randomConfig = config;
allowTypeSelection = requireTypeSelection;
allowSkillSelection = requireSkillSelection;
initializedExternally = true;
onConfirmSelection = onConfirm;
onClosed = closeCallback;
selectedType = default;
hasSelectedType = false;
selectedSkillGroupId = 0;
selectedSkillGroupName = string.Empty;
if (eTemplate != null)
{
eTemplate.sa_skillID = 0;
}
if (!requireTypeSelection)
{
selectedType = eTemplate != null ? eTemplate.skillType : default;
hasSelectedType = true;
}
BindButtons();
BuildTypeOptions();
ApplySelectionModeState();
UpdateCurrentSelectText();
RefreshButtons();
}
private void BindButtons()
{
if (yesSelectThis != null)
{
yesSelectThis.onClick.RemoveListener(HandleConfirmClicked);
yesSelectThis.onClick.AddListener(HandleConfirmClicked);
}
if (noWaitButton != null)
{
noWaitButton.onClick.RemoveListener(HandleCancelClicked);
noWaitButton.onClick.AddListener(HandleCancelClicked);
}
}
private void BuildTypeOptions()
{
ClearSpawned(spawnedTypeItems, select_typeParent);
selectedTypeObject = null;
if (select_typePrefab == null || select_typeParent == null)
{
return;
}
Array values = Enum.GetValues(typeof(equipmentSO.EquipmentSkillType));
for (int i = 0; i < values.Length; i++)
{
equipmentSO.EquipmentSkillType skillType = (equipmentSO.EquipmentSkillType)values.GetValue(i);
GameObject instance = Instantiate(select_typePrefab, select_typeParent);
spawnedTypeItems.Add(instance);
chooseTypePrefab item = instance.GetComponent<chooseTypePrefab>();
if (item != null)
{
item.Bind(skillType, HandleTypeSelected);
}
if (hasSelectedType && skillType == selectedType)
{
selectedTypeObject = instance;
}
}
}
private void HandleTypeSelected(equipmentSO.EquipmentSkillType skillType, chooseTypePrefab source)
{
selectedType = skillType;
hasSelectedType = true;
selectedTypeObject = source != null ? source.gameObject : null;
if (eTemplate != null)
{
eTemplate.skillType = skillType;
}
if (allowSkillSelection)
{
selectedSkillGroupId = 0;
selectedSkillGroupName = string.Empty;
if (eTemplate != null)
{
eTemplate.sa_skillID = 0;
}
if (select_skill_obj != null)
{
select_skill_obj.SetActive(true);
}
BuildSkillOptions(skillType);
}
else
{
ClearSpawned(spawnedSkillItems, select_skillParent);
}
UpdateCurrentSelectText();
RefreshButtons();
}
private void BuildSkillOptions(equipmentSO.EquipmentSkillType skillType)
{
ClearSpawned(spawnedSkillItems, select_skillParent);
if (select_skillPrefab == null || select_skillParent == null || randomConfig == null || randomConfig.specialSkillPool == null)
{
return;
}
for (int i = 0; i < randomConfig.specialSkillPool.Count; i++)
{
equipmentRandomConfigSO.SpecialSkillPoolEntry entry = randomConfig.specialSkillPool[i];
if (entry == null || entry.skillType != skillType || entry.skillIds == null)
{
continue;
}
for (int skillIndex = 0; skillIndex < entry.skillIds.Count; skillIndex++)
{
int skillGroupId = Mathf.Max(0, entry.skillIds[skillIndex]);
if (skillGroupId <= 0)
{
continue;
}
SkillGroup group = EquipmentSkillGroupLibrary.ResolveSpecialSkillGroup(skillGroupId);
if (group == null)
{
continue;
}
GameObject instance = Instantiate(select_skillPrefab, select_skillParent);
spawnedSkillItems.Add(instance);
chooseSkillPrefab item = instance.GetComponent<chooseSkillPrefab>();
if (item != null)
{
item.Bind(skillGroupId, group.groupName, group.groupIcon, group.skillDescriptionsText, HandleSkillSelected);
}
}
}
}
private void HandleSkillSelected(int skillGroupId)
{
selectedSkillGroupId = Mathf.Max(0, skillGroupId);
selectedSkillGroupName = ResolveSkillGroupName(selectedSkillGroupId);
if (eTemplate != null)
{
eTemplate.skillType = selectedType;
eTemplate.sa_skillID = selectedSkillGroupId;
}
UpdateCurrentSelectText();
RefreshButtons();
}
private void ApplySelectionModeState()
{
if (select_type_obj != null)
{
select_type_obj.SetActive(allowTypeSelection);
}
if (select_skill_obj != null)
{
bool shouldShowSkillSelector = allowSkillSelection && (!allowTypeSelection || hasSelectedType);
select_skill_obj.SetActive(shouldShowSkillSelector);
}
if (allowSkillSelection && select_skill_obj != null && select_skill_obj.activeSelf)
{
BuildSkillOptions(selectedType);
}
else if (!allowSkillSelection)
{
ClearSpawned(spawnedSkillItems, select_skillParent);
}
}
private void RefreshButtons()
{
if (yesSelectThis != null)
{
yesSelectThis.interactable = IsSelectionValid();
}
}
private bool IsSelectionValid()
{
if (allowTypeSelection && !hasSelectedType)
{
return false;
}
if (allowSkillSelection && selectedSkillGroupId <= 0)
{
return false;
}
return true;
}
private void UpdateCurrentSelectText()
{
if (currentSelectText == null)
{
return;
}
if (!hasSelectedType)
{
currentSelectText.text = "当前未选择装备类型";
return;
}
if (allowSkillSelection && selectedSkillGroupId > 0 && !string.IsNullOrWhiteSpace(selectedSkillGroupName))
{
currentSelectText.text = $"当前选择 <b>{selectedType}</b> 装备,必定带有 <b>{selectedSkillGroupName}</b> 技能";
return;
}
currentSelectText.text = $"当前选择 <b>{selectedType}</b> 装备";
}
private void HandleConfirmClicked()
{
if (!IsSelectionValid())
{
return;
}
onConfirmSelection?.Invoke(selectedType, selectedSkillGroupId);
Destroy(gameObject);
}
private void HandleCancelClicked()
{
Destroy(gameObject);
}
private void OnDestroy()
{
if (eTemplate != null && (eTemplate.hideFlags & HideFlags.DontSave) != 0)
{
Destroy(eTemplate);
}
onClosed?.Invoke();
}
private static string ResolveSkillGroupName(int skillGroupId)
{
if (skillGroupId <= 0)
{
return string.Empty;
}
SkillGroup group = EquipmentSkillGroupLibrary.ResolveSpecialSkillGroup(skillGroupId);
return group != null ? group.groupName : string.Empty;
}
private static void ClearSpawned(List<GameObject> spawned, Transform parent)
{
if (parent != null)
{
for (int i = parent.childCount - 1; i >= 0; i--)
{
Transform child = parent.GetChild(i);
if (child != null)
{
Destroy(child.gameObject);
}
}
}
if (spawned != null)
{
spawned.Clear();
}
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 3f5db959c0111f24ba4277e7af293fb8
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 4094c58a53fbfea47a443249662f8a7f
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 5b6fe5e6d2906be4c99e5b7dab4eb490
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,659 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
#if UNITY_EDITOR
using UnityEditor;
#endif
public class eFinalDream : MonoBehaviour
{
[Header("so")]
public Player_SO playerSO;
public equipmentSO eqp_p_SO;
public eUpdate_mtrSO need_mtrSO;
[Header("status")]
public GameObject beforeObj;
public GameObject toObj;
public GameObject nextObj;
[Header("dropdown")]
public Dropdown selectFinalBoost;
[Header("dragging")]
public GameObject dragPrev;
[Header("transforms")]
public Transform prevEquip;
public Transform nextLevelEquip;
public GameObject eip;
[Header("texts")]
public Text prevText;
public Text nextText;
public Text reasonWhy;
[Header("materials")]
public GameObject mtrPrefab;
public Transform mtrParent;
public Text mtrInfo;
[Header("sprites")]
public Sprite memoryFragmentSprite;
public Sprite coinSprite;
[Header("button")]
public Button yesDreamUpButton;
private GameObject spawnedPrevInstance;
private GameObject spawnedNextInstance;
private equipmentSO previewSO;
private readonly List<GameObject> spawnedMaterialItems = new List<GameObject>();
private readonly List<equipmentSO.EquipmentSpecialEffectType> availableFinalBoostTypes = new List<equipmentSO.EquipmentSpecialEffectType>();
private equipmentSO cachedFinalBoostEquipment;
private bool suppressFinalBoostCallback;
private void Awake()
{
InitializeBindings();
SetDragPreviewVisible(false);
RefreshAll();
}
private void OnEnable()
{
InitializeBindings();
SetDragPreviewVisible(false);
RefreshAll();
}
private void OnDisable()
{
if (yesDreamUpButton != null)
{
yesDreamUpButton.onClick.RemoveListener(HandleYesDreamClicked);
}
if (selectFinalBoost != null)
{
selectFinalBoost.onValueChanged.RemoveListener(HandleFinalBoostChanged);
}
}
private void InitializeBindings()
{
if (playerSO != null)
{
PlayerEconomyLedger.EnsureInstance().AttachPlayerData(playerSO);
}
if (selectFinalBoost != null)
{
selectFinalBoost.onValueChanged.RemoveListener(HandleFinalBoostChanged);
selectFinalBoost.onValueChanged.AddListener(HandleFinalBoostChanged);
}
if (yesDreamUpButton != null)
{
yesDreamUpButton.onClick.RemoveListener(HandleYesDreamClicked);
yesDreamUpButton.onClick.AddListener(HandleYesDreamClicked);
}
}
public void SetDragPreviewVisible(bool visible)
{
if (dragPrev == null)
{
return;
}
if (!gameObject.activeInHierarchy)
{
dragPrev.SetActive(false);
return;
}
dragPrev.SetActive(visible);
}
public bool IsPointerOverDropArea(Vector2 screenPoint, Camera eventCamera)
{
if (dragPrev == null || !dragPrev.activeInHierarchy)
{
return false;
}
RectTransform rectTransform = dragPrev.transform as RectTransform;
if (rectTransform == null)
{
return false;
}
return RectTransformUtility.RectangleContainsScreenPoint(rectTransform, screenPoint, eventCamera);
}
public void AcceptDraggedEquipment(equipmentSO equipment)
{
if (equipment == null)
{
return;
}
eqp_p_SO = equipment;
cachedFinalBoostEquipment = null;
RefreshAll();
}
private void HandleFinalBoostChanged(int _)
{
if (suppressFinalBoostCallback)
{
return;
}
RefreshPreviewStateOnly();
}
private void RefreshAll()
{
EnsureFinalBoostOptions();
RefreshPrevPreview();
RefreshNextPreview();
RefreshStateObjects();
RefreshTexts();
RefreshMaterials();
RefreshReasonWhy();
RefreshActionState();
}
private void RefreshPreviewStateOnly()
{
RefreshNextPreview();
RefreshStateObjects();
RefreshTexts();
RefreshReasonWhy();
RefreshActionState();
}
private void RefreshPrevPreview()
{
DestroySpawned(ref spawnedPrevInstance);
if (eqp_p_SO == null || eip == null || prevEquip == null)
{
return;
}
spawnedPrevInstance = Instantiate(eip, prevEquip);
spawnedPrevInstance.name = $"{eqp_p_SO.name}_FinalDreamPrev";
spawnedPrevInstance.SetActive(true);
equipItemPrefab item = spawnedPrevInstance.GetComponent<equipItemPrefab>();
if (item != null)
{
item.Bind(eqp_p_SO);
item.SetInteractionOptions(false, false);
}
}
private void RefreshNextPreview()
{
DestroySpawned(ref spawnedNextInstance);
DestroyPreviewEquipment();
if (!CanPreview())
{
return;
}
previewSO = Instantiate(eqp_p_SO);
previewSO.name = $"{eqp_p_SO.name}(FinalPreview)";
ApplyFinalBoost(previewSO, GetSelectedBoostType(), 0.01f);
spawnedNextInstance = Instantiate(eip, nextLevelEquip);
spawnedNextInstance.name = $"{eqp_p_SO.name}_FinalDreamNext";
spawnedNextInstance.SetActive(true);
equipItemPrefab item = spawnedNextInstance.GetComponent<equipItemPrefab>();
if (item != null)
{
item.Bind(previewSO);
item.SetInteractionOptions(false, false);
}
}
private void RefreshStateObjects()
{
if (beforeObj != null)
{
beforeObj.SetActive(true);
}
bool canPreview = CanPreview();
if (toObj != null)
{
toObj.SetActive(canPreview);
}
if (nextObj != null)
{
nextObj.SetActive(canPreview);
}
}
private void RefreshTexts()
{
if (prevText != null)
{
prevText.text = eqp_p_SO != null ? ResolveEquipmentName(eqp_p_SO) : string.Empty;
prevText.color = eqp_p_SO != null
? ResolveEquipmentColor(eqp_p_SO.GetVisualQualityColorIndex())
: Color.black;
}
if (nextText != null)
{
nextText.text = previewSO != null ? ResolveEquipmentName(previewSO) : string.Empty;
nextText.color = previewSO != null
? ResolveEquipmentColor(previewSO.GetVisualQualityColorIndex())
: Color.black;
}
}
private void RefreshMaterials()
{
ClearSpawnedMaterialItems();
if (mtrInfo == null)
{
return;
}
string structuralReason = GetStructuralFailureReason();
if (!string.IsNullOrEmpty(structuralReason))
{
mtrInfo.text = structuralReason;
return;
}
mtrInfo.text = string.Empty;
SpawnMaterialItems();
}
private void SpawnMaterialItems()
{
if (mtrPrefab == null || mtrParent == null || need_mtrSO == null)
{
return;
}
int materialRequired = need_mtrSO.GetFinalDreamMaterialRequired();
int coinRequired = need_mtrSO.GetFinalDreamCoinsRequired();
int memoryRequired = need_mtrSO.GetFinalDreamMemoryFragmentRequired();
if (materialRequired > 0 && need_mtrSO.finalDreamMaterial != null)
{
SpawnMaterialItem(
need_mtrSO.finalDreamMaterial.consumableSprite,
need_mtrSO.finalDreamMaterial.consumableName,
EquipmentConsumableLedger.EnsureInstance().GetCount(need_mtrSO.finalDreamMaterial.consumableKind),
materialRequired);
}
if (coinRequired > 0)
{
SpawnMaterialItem(coinSprite, "Coins", PlayerEconomyLedger.EnsureInstance().GetCoins(), coinRequired);
}
if (memoryRequired > 0)
{
SpawnMaterialItem(memoryFragmentSprite, "记忆碎片", PlayerEconomyLedger.EnsureInstance().GetMaterial(), memoryRequired);
}
}
private void SpawnMaterialItem(Sprite sprite, string displayName, int ownedAmount, int requiredAmount)
{
GameObject instance = Instantiate(mtrPrefab, mtrParent);
instance.SetActive(true);
spawnedMaterialItems.Add(instance);
materialPrefab item = instance.GetComponent<materialPrefab>();
if (item != null)
{
item.BindOwnedRequired(sprite, displayName, ownedAmount, requiredAmount, true, false, null);
item.SetSelected(true);
if (item.materialButton != null)
{
item.materialButton.interactable = false;
}
}
}
private void RefreshReasonWhy()
{
if (reasonWhy != null)
{
reasonWhy.text = GetActionFailureReason();
}
}
private void RefreshActionState()
{
if (yesDreamUpButton != null)
{
yesDreamUpButton.interactable = string.IsNullOrEmpty(GetActionFailureReason());
}
}
private string GetStructuralFailureReason()
{
if (eqp_p_SO == null)
{
return "需要选择一个记忆";
}
if (eqp_p_SO.level < 0 || eqp_p_SO.level > 20)
{
return "非法等级";
}
if (eqp_p_SO.level != 20)
{
return "要求20追忆等级";
}
if (need_mtrSO == null)
{
return "未配置登顶强化规则";
}
if (need_mtrSO.finalDreamMaterial == null)
{
return "未配置登顶材料";
}
if (availableFinalBoostTypes.Count == 0)
{
return "当前记忆没有可登顶的基础属性";
}
return string.Empty;
}
private string GetActionFailureReason()
{
string structuralReason = GetStructuralFailureReason();
if (!string.IsNullOrEmpty(structuralReason))
{
return structuralReason;
}
int materialRequired = need_mtrSO.GetFinalDreamMaterialRequired();
int coinRequired = need_mtrSO.GetFinalDreamCoinsRequired();
int memoryRequired = need_mtrSO.GetFinalDreamMemoryFragmentRequired();
if (materialRequired > 0 && EquipmentConsumableLedger.EnsureInstance().GetCount(need_mtrSO.finalDreamMaterial.consumableKind) < materialRequired)
{
return "登顶材料不足";
}
if (!PlayerEconomyLedger.EnsureInstance().HasEnoughCoins(coinRequired))
{
return "硬币不足";
}
if (!PlayerEconomyLedger.EnsureInstance().HasEnoughMaterial(memoryRequired))
{
return "记忆碎片不足";
}
return string.Empty;
}
private void HandleYesDreamClicked()
{
string failureReason = GetActionFailureReason();
if (!string.IsNullOrEmpty(failureReason))
{
RefreshAll();
return;
}
int materialRequired = need_mtrSO.GetFinalDreamMaterialRequired();
int coinRequired = need_mtrSO.GetFinalDreamCoinsRequired();
int memoryRequired = need_mtrSO.GetFinalDreamMemoryFragmentRequired();
if (materialRequired > 0 && !EquipmentConsumableLedger.EnsureInstance().TryConsume(need_mtrSO.finalDreamMaterial.consumableKind, materialRequired))
{
RefreshAll();
return;
}
if (coinRequired > 0 && !PlayerEconomyLedger.EnsureInstance().TrySpendCoins(coinRequired))
{
if (materialRequired > 0)
{
EquipmentConsumableLedger.EnsureInstance().Add(need_mtrSO.finalDreamMaterial.consumableKind, materialRequired);
}
RefreshAll();
return;
}
if (memoryRequired > 0 && !PlayerEconomyLedger.EnsureInstance().TrySpendMaterial(memoryRequired))
{
if (coinRequired > 0)
{
PlayerEconomyLedger.EnsureInstance().AddCoins(coinRequired);
}
if (materialRequired > 0)
{
EquipmentConsumableLedger.EnsureInstance().Add(need_mtrSO.finalDreamMaterial.consumableKind, materialRequired);
}
RefreshAll();
return;
}
ApplyFinalBoost(eqp_p_SO, GetSelectedBoostType(), 0.01f);
PersistEquipment(eqp_p_SO);
RefreshAllEquipBags();
RefreshAll();
}
private bool CanPreview()
{
return string.IsNullOrEmpty(GetStructuralFailureReason()) &&
availableFinalBoostTypes.Count > 0 &&
eip != null &&
nextLevelEquip != null;
}
private equipmentSO.EquipmentSpecialEffectType GetSelectedBoostType()
{
if (availableFinalBoostTypes.Count == 0)
{
return equipmentSO.EquipmentSpecialEffectType.MaxHp;
}
int index = selectFinalBoost != null ? Mathf.Clamp(selectFinalBoost.value, 0, availableFinalBoostTypes.Count - 1) : 0;
return availableFinalBoostTypes[index];
}
private void EnsureFinalBoostOptions()
{
if (selectFinalBoost == null)
{
return;
}
if (cachedFinalBoostEquipment == eqp_p_SO && selectFinalBoost.options != null && selectFinalBoost.options.Count == availableFinalBoostTypes.Count)
{
return;
}
int currentValue = selectFinalBoost.value;
availableFinalBoostTypes.Clear();
var options = new List<Dropdown.OptionData>(5);
AppendFinalBoostOption(eqp_p_SO != null && !Mathf.Approximately(eqp_p_SO.maxHp.basicGain, 0f), equipmentSO.EquipmentSpecialEffectType.MaxHp, "最大生命值", options);
AppendFinalBoostOption(eqp_p_SO != null && !Mathf.Approximately(eqp_p_SO.attack.basicGain, 0f), equipmentSO.EquipmentSpecialEffectType.Attack, "攻击力", options);
AppendFinalBoostOption(eqp_p_SO != null && !Mathf.Approximately(eqp_p_SO.maxMana.basicGain, 0f), equipmentSO.EquipmentSpecialEffectType.MaxMana, "最大法力值", options);
AppendFinalBoostOption(eqp_p_SO != null && !Mathf.Approximately(eqp_p_SO.damageResistance.basicGain, 0f), equipmentSO.EquipmentSpecialEffectType.DamageResistance, "伤害减免", options);
AppendFinalBoostOption(eqp_p_SO != null && !Mathf.Approximately(eqp_p_SO.scoreEfficiency.basicGain, 0f), equipmentSO.EquipmentSpecialEffectType.ScoreEfficiency, "得分效率", options);
suppressFinalBoostCallback = true;
selectFinalBoost.ClearOptions();
selectFinalBoost.AddOptions(options);
if (options.Count > 0)
{
selectFinalBoost.value = Mathf.Clamp(currentValue, 0, options.Count - 1);
}
selectFinalBoost.RefreshShownValue();
suppressFinalBoostCallback = false;
cachedFinalBoostEquipment = eqp_p_SO;
}
private void AppendFinalBoostOption(bool include, equipmentSO.EquipmentSpecialEffectType effectType, string displayName, List<Dropdown.OptionData> options)
{
if (!include)
{
return;
}
availableFinalBoostTypes.Add(effectType);
options.Add(new Dropdown.OptionData(displayName));
}
private static void ApplyFinalBoost(equipmentSO equipment, equipmentSO.EquipmentSpecialEffectType effectType, float boostValue)
{
equipment.maxLevelEffects = new[]
{
new equipmentSO.EquipmentSpecialEffect
{
effectType = effectType,
value = boostValue
}
};
}
private static bool HasMaxLevelEffect(equipmentSO equipment)
{
return equipment != null && equipment.maxLevelEffects != null && equipment.maxLevelEffects.Length > 0;
}
private static string ResolveEquipmentName(equipmentSO equipment)
{
if (equipment == null)
{
return string.Empty;
}
string displayName = equipment.GetDisplayTierName();
return string.IsNullOrWhiteSpace(displayName) ? equipment.name : displayName;
}
private static Color ResolveEquipmentColor(int colorIndex)
{
equipItemPrefab reference = Object.FindObjectOfType<equipItemPrefab>(true);
if (reference == null || reference.itemBtmColors == null || reference.itemBtmColors.Length == 0)
{
return Color.white;
}
int safeIndex = Mathf.Clamp(colorIndex, 0, reference.itemBtmColors.Length - 1);
return reference.itemBtmColors[safeIndex];
}
private void ClearSpawnedMaterialItems()
{
if (mtrParent != null)
{
for (int i = mtrParent.childCount - 1; i >= 0; i--)
{
Transform child = mtrParent.GetChild(i);
if (child == null)
{
continue;
}
#if UNITY_EDITOR
if (!Application.isPlaying)
{
DestroyImmediate(child.gameObject);
}
else
#endif
{
Destroy(child.gameObject);
}
}
}
spawnedMaterialItems.Clear();
}
private void DestroySpawned(ref GameObject instance)
{
if (instance == null)
{
return;
}
#if UNITY_EDITOR
if (!Application.isPlaying)
{
DestroyImmediate(instance);
}
else
#endif
{
Destroy(instance);
}
instance = null;
}
private void DestroyPreviewEquipment()
{
if (previewSO == null)
{
return;
}
#if UNITY_EDITOR
if (!Application.isPlaying)
{
DestroyImmediate(previewSO);
}
else
#endif
{
Destroy(previewSO);
}
previewSO = null;
}
private static void PersistEquipment(equipmentSO equipment)
{
if (equipment == null)
{
return;
}
#if UNITY_EDITOR
EditorUtility.SetDirty(equipment);
AssetDatabase.SaveAssets();
#endif
}
private static void RefreshAllEquipBags()
{
equipBag[] bags = Object.FindObjectsOfType<equipBag>(true);
for (int i = 0; i < bags.Length; i++)
{
if (bags[i] != null)
{
bags[i].Rebuild();
}
}
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 3bf1091d681d13746840d9ed472d8ec0
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 5b4324b6cbdbd3244b2b89486c4c2280
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -232,7 +232,7 @@ public class equipIllusion : MonoBehaviour
}
prevLevelText.text = ResolveTourStageName(eqp_p_SO.level);
prevLevelText.color = ResolveEquipmentColor(GetQualityColorIndex(eqp_p_SO.level));
prevLevelText.color = ResolveEquipmentColor(eqp_p_SO.GetVisualQualityColorIndex());
}
private void RefreshNextLevelText()
@@ -249,7 +249,7 @@ public class equipIllusion : MonoBehaviour
}
nextLevelText.text = ResolveTourStageName(nextLevelPreviewSO.level);
nextLevelText.color = ResolveEquipmentColor(GetQualityColorIndex(nextLevelPreviewSO.level));
nextLevelText.color = ResolveEquipmentColor(nextLevelPreviewSO.GetVisualQualityColorIndex());
}
private void RefreshMaterialRequirements()
@@ -276,7 +276,7 @@ public class equipIllusion : MonoBehaviour
if (level >= 20)
{
mtrInfo.text = "<color=#FF67A4>梦醒时分记忆无法巡演</color>";
mtrInfo.text = "已完成全部巡演";
return;
}
@@ -306,7 +306,8 @@ public class equipIllusion : MonoBehaviour
SpawnMaterialItem(
need_mtrSO.breakthroughMaterial.consumableSprite,
need_mtrSO.breakthroughMaterial.consumableName,
materialRequired.ToString());
EquipmentConsumableLedger.EnsureInstance().GetCount(need_mtrSO.breakthroughMaterial.consumableKind),
materialRequired);
}
if (coinRequired > 0)
@@ -314,7 +315,8 @@ public class equipIllusion : MonoBehaviour
SpawnMaterialItem(
coinSprite,
"Coins",
coinRequired.ToString());
PlayerEconomyLedger.EnsureInstance().GetCoins(),
coinRequired);
}
if (memoryRequired > 0)
@@ -322,11 +324,12 @@ public class equipIllusion : MonoBehaviour
SpawnMaterialItem(
memoryFragmentSprite,
"记忆碎片",
memoryRequired.ToString());
PlayerEconomyLedger.EnsureInstance().GetMaterial(),
memoryRequired);
}
}
private void SpawnMaterialItem(Sprite sprite, string displayName, string amountText)
private void SpawnMaterialItem(Sprite sprite, string displayName, int ownedAmount, int requiredAmount)
{
GameObject instance = Instantiate(mtrPrefab, merParent);
instance.SetActive(true);
@@ -335,7 +338,7 @@ public class equipIllusion : MonoBehaviour
materialPrefab item = instance.GetComponent<materialPrefab>();
if (item != null)
{
item.Bind(sprite, displayName, amountText, true, false, null);
item.BindOwnedRequired(sprite, displayName, ownedAmount, requiredAmount, true, false, null);
item.SetSelected(true);
if (item.materialButton != null)
{
@@ -378,7 +381,7 @@ public class equipIllusion : MonoBehaviour
if (eqp_p_SO.level >= 20)
{
return "梦醒时分记忆无法巡演";
return "此记忆已完成全部巡演";
}
if (!IsTourEligibleLevel(eqp_p_SO.level))
@@ -517,16 +520,29 @@ public class equipIllusion : MonoBehaviour
}
}
for (int i = 0; i < effects.Count; i++)
float bestExistingValue = float.MinValue;
bool hasDuplicate = false;
for (int i = effects.Count - 1; i >= 0; i--)
{
if (effects[i].effectType != effectType)
{
continue;
}
float best = Mathf.Max(effects[i].value, rolledValue);
effects[i].value = best + Mathf.Abs(best) * 0.2f;
eqp_p_SO.illusionEffects = effects.ToArray();
hasDuplicate = true;
bestExistingValue = Mathf.Max(bestExistingValue, effects[i].value);
effects.RemoveAt(i);
}
if (hasDuplicate)
{
float best = Mathf.Max(bestExistingValue, rolledValue);
effects.Add(new equipmentSO.EquipmentSpecialEffect
{
effectType = effectType,
value = best + Mathf.Abs(best) * 0.2f
});
eqp_p_SO.illusionEffects = NormalizeIllusionEffects(effects);
return;
}
@@ -535,7 +551,18 @@ public class equipIllusion : MonoBehaviour
effectType = effectType,
value = rolledValue
});
eqp_p_SO.illusionEffects = NormalizeIllusionEffects(effects);
}
private equipmentSO.EquipmentSpecialEffect[] NormalizeIllusionEffects(List<equipmentSO.EquipmentSpecialEffect> effects)
{
if (effects == null || effects.Count == 0)
{
return System.Array.Empty<equipmentSO.EquipmentSpecialEffect>();
}
eqp_p_SO.illusionEffects = effects.ToArray();
return eqp_p_SO.GetNormalizedIllusionEffects();
}
private List<equipmentSO.EquipmentSpecialEffectType> BuildIllusionEffectPool()
@@ -785,31 +812,6 @@ public class equipIllusion : MonoBehaviour
return itemPrefab.itemBtmColors[safeIndex];
}
private static int GetQualityColorIndex(int level)
{
if (level >= 20)
{
return 5;
}
if (level >= 15)
{
return 4;
}
if (level >= 10)
{
return 3;
}
if (level >= 5)
{
return 2;
}
return 1;
}
private static void PersistEquipment(equipmentSO equipment)
{
if (equipment == null)
@@ -15,7 +15,8 @@ MonoBehaviour:
simpleRewardAmount: 40
_1skillRewardAmount: 100
_2skillRewardAmount: 300
quickFinishCost: 200
startSmeltCost: 0
quickFinishCost: 0
rewardRandomConfig: {fileID: 11400000, guid: ca394ccb04190524fb487491eedb36e7, type: 2}
rewardTemplate: {fileID: 11400000, guid: 40fe16e436a81644aa688c80436aa1c1, type: 2}
smeltEquipmentCapacity: 60
@@ -33,13 +34,13 @@ MonoBehaviour:
chosenSkillType: 0
equipRewardName: "60 \u81EA\u9009\u8BB0\u5FC6"
requiredAmount: 60
- equipmentType: 0
qualityType: 0
- equipmentType: 1
qualityType: 1
skillRequirement: 0
chosenSkillType: 0
equipRewardName: "200 \u81EA\u9009\u9AD8\u5929\u8D4B\u8BB0\u5FC6"
requiredAmount: 120
- equipmentType: 0
requiredAmount: 200
- equipmentType: 1
qualityType: 0
skillRequirement: 1
chosenSkillType: 0
@@ -1,5 +1,6 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UI;
using Bansonic;
@@ -11,7 +12,10 @@ public class equipSmelt : MonoBehaviour
{
private static readonly List<equipmentSO> SmeltPoolEquipments = new List<equipmentSO>();
private static readonly HashSet<equipmentSO> SmeltPoolLookup = new HashSet<equipmentSO>();
private static readonly HashSet<string> ConsumedSmeltEquipmentIds = new HashSet<string>(StringComparer.Ordinal);
private static readonly HashSet<equipmentSO> ConsumedSmeltEquipments = new HashSet<equipmentSO>();
private const string SmeltStatePrefsKey = "equip_smelt_state_v1";
private static bool persistenceLoaded;
private static readonly List<equipSmelt> Instances = new List<equipSmelt>();
private static bool isSmeltingState;
@@ -22,6 +26,19 @@ public class equipSmelt : MonoBehaviour
private static int pendingStoredFragmentsState;
private static int storedSmeltEnergyState;
[Serializable]
private sealed class SmeltPersistentState
{
public bool isSmelting;
public bool smeltCompleted;
public int gamesRequired;
public int gamesCompleted;
public int pendingDirectFragments;
public int pendingStoredFragments;
public int storedSmeltEnergy;
public string[] consumedEquipmentIds;
}
[Header("so")]
public smeltStageRewardSO ssrso;
@@ -69,9 +86,11 @@ public class equipSmelt : MonoBehaviour
public Transform ctasParent;
private readonly List<GameObject> spawnedPoolItems = new List<GameObject>();
private GameObject activeCtasInstance;
private void Awake()
{
EnsurePersistentStateLoaded();
RegisterInstance();
BindButtons();
RefreshAllUi();
@@ -81,35 +100,44 @@ public class equipSmelt : MonoBehaviour
{
RegisterInstance();
BindButtons();
settlementController.OnSettlementCompleted -= HandleSettlementCompleted;
settlementController.OnSettlementCompleted += HandleSettlementCompleted;
RefreshAllUi();
}
private void OnDisable()
{
settlementController.OnSettlementCompleted -= HandleSettlementCompleted;
CloseActiveCtas();
Instances.Remove(this);
}
private void OnDestroy()
{
settlementController.OnSettlementCompleted -= HandleSettlementCompleted;
CloseActiveCtas();
Instances.Remove(this);
}
public static bool IsEquipmentAssignedToSmeltPool(equipmentSO equipment)
{
EnsurePersistentStateLoaded();
return equipment != null && SmeltPoolLookup.Contains(equipment);
}
public static bool IsEquipmentConsumedBySmelt(equipmentSO equipment)
{
EnsurePersistentStateLoaded();
return equipment != null && ConsumedSmeltEquipments.Contains(equipment);
}
public static bool ShouldHideConsumedEquipment(equipmentSO equipment)
{
EnsurePersistentStateLoaded();
return equipment != null
&& (ConsumedSmeltEquipments.Contains(equipment)
|| (!string.IsNullOrWhiteSpace(equipment.name) && ConsumedSmeltEquipmentIds.Contains(equipment.name)));
}
public static bool RemoveEquipmentFromSmeltPool(equipmentSO equipment)
{
EnsurePersistentStateLoaded();
if (equipment == null)
{
return false;
@@ -121,6 +149,7 @@ public class equipSmelt : MonoBehaviour
}
SmeltPoolEquipments.Remove(equipment);
SavePersistentState();
RefreshAllSmeltPools();
RefreshAllEquipBags();
return true;
@@ -128,6 +157,7 @@ public class equipSmelt : MonoBehaviour
public static bool TryHandleQuickTransfer(equipmentSO equipment)
{
EnsurePersistentStateLoaded();
if (equipment == null || IsEquipmentConsumedBySmelt(equipment))
{
return false;
@@ -148,6 +178,23 @@ public class equipSmelt : MonoBehaviour
return IsEquipmentAssignedToSmeltPool(equipment);
}
public static void ReinstateRewardEquipment(equipmentSO equipment)
{
EnsurePersistentStateLoaded();
if (equipment == null)
{
return;
}
ConsumedSmeltEquipments.Remove(equipment);
if (!string.IsNullOrWhiteSpace(equipment.name))
{
ConsumedSmeltEquipmentIds.Remove(equipment.name);
}
SavePersistentState();
}
public void SetDragPreviewVisible(bool visible)
{
if (dragObj == null)
@@ -197,6 +244,7 @@ public class equipSmelt : MonoBehaviour
public void AcceptDraggedEquipment(equipmentSO equipment)
{
EnsurePersistentStateLoaded();
if (equipment == null || IsEquipmentConsumedBySmelt(equipment) || !IsPoolOpenForTransfers())
{
return;
@@ -211,6 +259,7 @@ public class equipSmelt : MonoBehaviour
if (SmeltPoolLookup.Add(equipment))
{
SmeltPoolEquipments.Add(equipment);
SavePersistentState();
RefreshAllUi();
RefreshAllEquipBags();
}
@@ -256,6 +305,13 @@ public class equipSmelt : MonoBehaviour
return;
}
int startCost = GetStartSmeltCost();
if (!PlayerEconomyLedger.EnsureInstance().TrySpendCoins(startCost))
{
RefreshAllUi();
return;
}
isSmeltingState = true;
smeltCompletedState = false;
gamesCompletedForCurrentBatchState = 0;
@@ -266,6 +322,7 @@ public class equipSmelt : MonoBehaviour
pendingStoredFragmentsState = Mathf.Max(0, totalFragments - pendingDirectFragmentsState);
ConsumeCurrentPoolEquipments();
SavePersistentState();
RefreshAllUi();
RefreshAllEquipBags();
}
@@ -285,26 +342,40 @@ public class equipSmelt : MonoBehaviour
gamesCompletedForCurrentBatchState = gamesRequiredForCurrentBatchState;
smeltCompletedState = true;
SavePersistentState();
RefreshAllUi();
}
private void HandleSettlementCompleted()
public static void NotifySettlementCompleted()
{
if (!isSmeltingState || smeltCompletedState)
{
return;
}
if (GameConfig.autoPlayEnabled)
{
return;
}
gamesCompletedForCurrentBatchState = Mathf.Min(gamesRequiredForCurrentBatchState, gamesCompletedForCurrentBatchState + 1);
if (gamesCompletedForCurrentBatchState >= gamesRequiredForCurrentBatchState)
{
smeltCompletedState = true;
ClaimCurrentBatchRewardsStatic();
return;
}
RefreshAllUi();
SavePersistentState();
RefreshAllSmeltPools();
}
private void ClaimCurrentBatchRewards()
{
ClaimCurrentBatchRewardsStatic();
}
private static void ClaimCurrentBatchRewardsStatic()
{
if (!smeltCompletedState)
{
@@ -316,7 +387,7 @@ public class equipSmelt : MonoBehaviour
PlayerEconomyLedger.EnsureInstance().AddMaterial(pendingDirectFragmentsState);
}
storedSmeltEnergyState = Mathf.Clamp(storedSmeltEnergyState + pendingStoredFragmentsState, 0, GetSmeltStorageCapacity());
storedSmeltEnergyState = Mathf.Clamp(storedSmeltEnergyState + pendingStoredFragmentsState, 0, GetSmeltStorageCapacityStatic());
pendingDirectFragmentsState = 0;
pendingStoredFragmentsState = 0;
@@ -324,18 +395,8 @@ public class equipSmelt : MonoBehaviour
gamesCompletedForCurrentBatchState = 0;
isSmeltingState = false;
smeltCompletedState = false;
if (d_mf_Amount != null)
{
d_mf_Amount.text = "0";
}
if (s_mf_Amount != null)
{
s_mf_Amount.text = "0";
}
RefreshAllUi();
SavePersistentState();
RefreshAllSmeltPools();
RefreshAllEquipBags();
}
@@ -353,15 +414,13 @@ public class equipSmelt : MonoBehaviour
return;
}
equipmentSO generated = equipmentGenerator.GenerateFromSmeltReward(ssrso, requirement);
if (generated == null)
if (RequiresRewardSelection(requirement))
{
OpenRewardSelector(requirement);
return;
}
storedSmeltEnergyState = Mathf.Max(0, storedSmeltEnergyState - requiredAmount);
RefreshAllUi();
RefreshAllEquipBags();
GrantReward(requirement, null, 0);
}
private void HandleRewardSelectionChanged(int _)
@@ -369,6 +428,127 @@ public class equipSmelt : MonoBehaviour
RefreshButtons();
}
private bool RequiresRewardSelection(smeltStageRewardSO.SmeltStageRewardRequirement requirement)
{
if (requirement == null)
{
return false;
}
return RequiresTypeSelection(requirement)
|| RequiresSkillSelection(requirement);
}
private bool RequiresTypeSelection(smeltStageRewardSO.SmeltStageRewardRequirement requirement)
{
if (requirement == null)
{
return false;
}
if (requirement.equipmentType == smeltStageRewardSO.equipType.selfChosenType)
{
return true;
}
return !string.IsNullOrWhiteSpace(requirement.equipRewardName)
&& requirement.equipRewardName.Contains("自选", StringComparison.Ordinal);
}
private bool RequiresSkillSelection(smeltStageRewardSO.SmeltStageRewardRequirement requirement)
{
return requirement != null
&& requirement.skillRequirement == smeltStageRewardSO.skillOwned.selfChosen;
}
private void OpenRewardSelector(smeltStageRewardSO.SmeltStageRewardRequirement requirement)
{
if (ctasPrefab == null || ctasParent == null || ssrso == null || ssrso.rewardRandomConfig == null)
{
return;
}
CloseActiveCtas();
GameObject instance = Instantiate(ctasPrefab, ctasParent);
activeCtasInstance = instance;
global::ctasPrefab selector = instance.GetComponent<global::ctasPrefab>();
if (selector == null)
{
return;
}
equipmentSO selectionTemplate = ssrso.rewardTemplate != null
? UnityEngine.Object.Instantiate(ssrso.rewardTemplate)
: ScriptableObject.CreateInstance<equipmentSO>();
selectionTemplate.hideFlags = HideFlags.DontSave;
selectionTemplate.sa_skillID = 0;
selectionTemplate.ia_skillID = 0;
bool requireTypeSelection = RequiresTypeSelection(requirement);
bool requireSkillSelection = RequiresSkillSelection(requirement);
if (requireTypeSelection)
{
selectionTemplate.skillType = requirement.chosenSkillType;
}
selector.Initialize(
selectionTemplate,
ssrso.rewardRandomConfig,
requireTypeSelection,
requireSkillSelection,
(selectedType, selectedSkillGroupId) => HandleRewardSelectionConfirmed(requirement, selectedType, selectedSkillGroupId),
HandleRewardSelectorClosed);
}
private void HandleRewardSelectionConfirmed(smeltStageRewardSO.SmeltStageRewardRequirement requirement, equipmentSO.EquipmentSkillType selectedType, int selectedSkillGroupId)
{
activeCtasInstance = null;
GrantReward(requirement, selectedType, selectedSkillGroupId);
}
private void GrantReward(smeltStageRewardSO.SmeltStageRewardRequirement requirement, equipmentSO.EquipmentSkillType? selectedTypeOverride, int selectedSkillGroupId)
{
if (requirement == null)
{
return;
}
int requiredAmount = Mathf.Max(0, requirement.requiredAmount);
if (requiredAmount > storedSmeltEnergyState)
{
return;
}
equipmentSO generated = equipmentGenerator.GenerateFromSmeltReward(ssrso, requirement, selectedTypeOverride, selectedSkillGroupId);
if (generated == null)
{
return;
}
ReinstateRewardEquipment(generated);
storedSmeltEnergyState = Mathf.Max(0, storedSmeltEnergyState - requiredAmount);
SavePersistentState();
RefreshAllUi();
RefreshAllEquipBags();
}
private void HandleRewardSelectorClosed()
{
activeCtasInstance = null;
RefreshButtons();
}
private void CloseActiveCtas()
{
if (activeCtasInstance != null)
{
Destroy(activeCtasInstance);
activeCtasInstance = null;
}
}
private void ConsumeCurrentPoolEquipments()
{
if (SmeltPoolEquipments.Count == 0)
@@ -385,6 +565,10 @@ public class equipSmelt : MonoBehaviour
}
ConsumedSmeltEquipments.Add(equipment);
if (!string.IsNullOrWhiteSpace(equipment.name))
{
ConsumedSmeltEquipmentIds.Add(equipment.name);
}
#if UNITY_EDITOR
string assetPath = AssetDatabase.GetAssetPath(equipment);
@@ -402,6 +586,8 @@ public class equipSmelt : MonoBehaviour
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
#endif
SavePersistentState();
}
private void RefreshAllUi()
@@ -520,6 +706,11 @@ public class equipSmelt : MonoBehaviour
private void RefreshProgressDisplay()
{
if (costText != null)
{
costText.text = GetStartSmeltCost().ToString();
}
if (qf_cost_text != null)
{
qf_cost_text.text = GetQuickFinishCost().ToString();
@@ -578,6 +769,10 @@ public class equipSmelt : MonoBehaviour
return;
}
int previousValue = selectAReward.options != null && selectAReward.options.Count > 0
? Mathf.Max(0, selectAReward.value)
: 0;
selectAReward.ClearOptions();
if (selectAReward.captionText != null)
{
@@ -610,7 +805,7 @@ public class equipSmelt : MonoBehaviour
}
selectAReward.AddOptions(options);
selectAReward.value = 0;
selectAReward.value = Mathf.Clamp(previousValue, 0, options.Count - 1);
selectAReward.RefreshShownValue();
}
@@ -618,7 +813,10 @@ public class equipSmelt : MonoBehaviour
{
if (startSmeltButton != null)
{
startSmeltButton.interactable = smeltCompletedState || (!isSmeltingState && SmeltPoolEquipments.Count > 0);
bool canStart = !isSmeltingState
&& SmeltPoolEquipments.Count > 0
&& PlayerEconomyLedger.EnsureInstance().HasEnoughCoins(GetStartSmeltCost());
startSmeltButton.interactable = smeltCompletedState || canStart;
Text startButtonText = startSmeltButton.GetComponentInChildren<Text>(true);
if (startButtonText != null)
{
@@ -634,7 +832,7 @@ public class equipSmelt : MonoBehaviour
if (getReward != null)
{
smeltStageRewardSO.SmeltStageRewardRequirement requirement = GetSelectedRewardRequirement();
getReward.interactable = requirement != null && Mathf.Max(0, requirement.requiredAmount) <= storedSmeltEnergyState;
getReward.interactable = (activeCtasInstance == null) && requirement != null && Mathf.Max(0, requirement.requiredAmount) <= storedSmeltEnergyState;
}
}
@@ -670,6 +868,12 @@ public class equipSmelt : MonoBehaviour
}
reasonWhy.text = string.Empty;
if (!PlayerEconomyLedger.EnsureInstance().HasEnoughCoins(GetStartSmeltCost()))
{
reasonWhy.text = "硬币不足";
return;
}
}
private int CalculateTotalFragmentsForCurrentPool()
@@ -739,11 +943,30 @@ public class equipSmelt : MonoBehaviour
return Mathf.Clamp(ssrso.smeltStorageCapacity, 0, 5000);
}
private static int GetSmeltStorageCapacityStatic()
{
for (int i = 0; i < Instances.Count; i++)
{
equipSmelt instance = Instances[i];
if (instance != null && instance.ssrso != null)
{
return Mathf.Clamp(instance.ssrso.smeltStorageCapacity, 0, 5000);
}
}
return 5000;
}
private int GetQuickFinishCost()
{
return ssrso != null ? Mathf.Max(0, ssrso.quickFinishCost) : 0;
}
private int GetStartSmeltCost()
{
return ssrso != null ? Mathf.Max(0, ssrso.startSmeltCost) : 0;
}
private smeltStageRewardSO.SmeltStageRewardRequirement GetSelectedRewardRequirement()
{
if (ssrso == null || ssrso.rewardRequirements == null || ssrso.rewardRequirements.Length == 0)
@@ -802,6 +1025,122 @@ public class equipSmelt : MonoBehaviour
}
}
private void OnApplicationPause(bool pauseStatus)
{
if (pauseStatus)
{
SavePersistentState();
}
}
private void OnApplicationQuit()
{
SavePersistentState();
}
private static void EnsurePersistentStateLoaded()
{
if (persistenceLoaded)
{
return;
}
persistenceLoaded = true;
ConsumedSmeltEquipmentIds.Clear();
if (!PlayerPrefs.HasKey(SmeltStatePrefsKey))
{
return;
}
string json = PlayerPrefs.GetString(SmeltStatePrefsKey, string.Empty);
if (string.IsNullOrWhiteSpace(json))
{
return;
}
SmeltPersistentState state = null;
try
{
state = JsonUtility.FromJson<SmeltPersistentState>(json);
}
catch (Exception ex)
{
Debug.LogWarning($"[equipSmelt] Failed to parse persistent state: {ex.Message}");
}
if (state == null)
{
return;
}
isSmeltingState = state.isSmelting;
smeltCompletedState = state.smeltCompleted;
gamesRequiredForCurrentBatchState = Mathf.Max(0, state.gamesRequired);
gamesCompletedForCurrentBatchState = Mathf.Clamp(state.gamesCompleted, 0, gamesRequiredForCurrentBatchState);
pendingDirectFragmentsState = Mathf.Max(0, state.pendingDirectFragments);
pendingStoredFragmentsState = Mathf.Max(0, state.pendingStoredFragments);
storedSmeltEnergyState = Mathf.Max(0, state.storedSmeltEnergy);
if (state.consumedEquipmentIds != null)
{
for (int i = 0; i < state.consumedEquipmentIds.Length; i++)
{
string id = state.consumedEquipmentIds[i];
if (!string.IsNullOrWhiteSpace(id))
{
ConsumedSmeltEquipmentIds.Add(id);
}
}
}
}
private static void SavePersistentState()
{
if (!persistenceLoaded)
{
return;
}
var state = new SmeltPersistentState
{
isSmelting = isSmeltingState,
smeltCompleted = smeltCompletedState,
gamesRequired = gamesRequiredForCurrentBatchState,
gamesCompleted = gamesCompletedForCurrentBatchState,
pendingDirectFragments = pendingDirectFragmentsState,
pendingStoredFragments = pendingStoredFragmentsState,
storedSmeltEnergy = storedSmeltEnergyState,
consumedEquipmentIds = ConsumedSmeltEquipmentIds.Count > 0 ? ConsumedSmeltEquipmentIds.ToArray() : Array.Empty<string>()
};
PlayerPrefs.SetString(SmeltStatePrefsKey, JsonUtility.ToJson(state));
PlayerPrefs.Save();
}
public static void ClearPersistentState()
{
SmeltPoolEquipments.Clear();
SmeltPoolLookup.Clear();
ConsumedSmeltEquipments.Clear();
ConsumedSmeltEquipmentIds.Clear();
isSmeltingState = false;
smeltCompletedState = false;
gamesRequiredForCurrentBatchState = 0;
gamesCompletedForCurrentBatchState = 0;
pendingDirectFragmentsState = 0;
pendingStoredFragmentsState = 0;
storedSmeltEnergyState = 0;
persistenceLoaded = true;
PlayerPrefs.DeleteKey(SmeltStatePrefsKey);
PlayerPrefs.Save();
RefreshAllSmeltPools();
RefreshAllEquipBags();
}
private static void RefreshAllSmeltPools()
{
for (int i = 0; i < Instances.Count; i++)
@@ -830,3 +1169,4 @@ public class equipSmelt : MonoBehaviour
}
}
}
@@ -26,6 +26,7 @@ public class smeltStageRewardSO : ScriptableObject
public int simpleRewardAmount = 40;
public int _1skillRewardAmount = 100;
public int _2skillRewardAmount = 300;
public int startSmeltCost = 200;
public int quickFinishCost = 200;
[Header("reward generation")]
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 0b8c0900eca58b54f977cb5892e79735
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,892 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using Bansonic;
#if UNITY_EDITOR
using UnityEditor;
#endif
public class equipTransfer : MonoBehaviour
{
public enum TransferMode
{
MemoryEntrust = 0,
TourEntrust = 1
}
public enum TransferDropSlot
{
None = 0,
Main = 1,
Need = 2
}
[Header("so")]
public Player_SO playerSO;
public equipmentSO eqp_p_SO;
public equipmentSO eqp_need_SO;
public eUpdate_mtrSO need_mtrSO;
[Header("sprites")]
public Sprite memoryFragment;
public Sprite coins;
[Header("state objects")]
public GameObject mainEquipObj;
public GameObject toObj;
public GameObject needEquipObj;
public GameObject previewObj;
[Header("drag")]
public GameObject dragMainEquip;
public GameObject dragNeedEquip;
[Header("transforms")]
public Transform mainEquip;
public Transform needEquip;
public Transform previewEquip;
public GameObject eip;
[Header("choose")]
public Dropdown chooseType;
[Header("texts")]
public Text mainEquipText;
public Text needEquipText;
public Text previewEquipText;
public Text reasonWhy;
[Header("materials")]
public GameObject mtrPrefab;
public Transform mtrParent;
public Text mtrInfo;
[Header("buttons")]
public Button yesTransferButton;
private GameObject spawnedMainEquipInstance;
private GameObject spawnedNeedEquipInstance;
private GameObject spawnedPreviewEquipInstance;
private equipmentSO previewEquipSO;
private readonly List<GameObject> spawnedMaterialItems = new List<GameObject>();
private void Awake()
{
InitializeBindings();
SetDragPreviewVisible(false);
RefreshAll();
}
private void OnEnable()
{
InitializeBindings();
SetDragPreviewVisible(false);
RefreshAll();
}
private void OnDisable()
{
if (yesTransferButton != null)
{
yesTransferButton.onClick.RemoveListener(HandleYesTransferClicked);
}
if (chooseType != null)
{
chooseType.onValueChanged.RemoveListener(HandleChooseTypeChanged);
}
}
private void InitializeBindings()
{
if (playerSO != null)
{
PlayerEconomyLedger.EnsureInstance().AttachPlayerData(playerSO);
}
if (chooseType != null)
{
EnsureChooseTypeOptions();
chooseType.onValueChanged.RemoveListener(HandleChooseTypeChanged);
chooseType.onValueChanged.AddListener(HandleChooseTypeChanged);
}
if (yesTransferButton != null)
{
yesTransferButton.onClick.RemoveListener(HandleYesTransferClicked);
yesTransferButton.onClick.AddListener(HandleYesTransferClicked);
}
}
public void SetDragPreviewVisible(bool visible)
{
if (!gameObject.activeInHierarchy)
{
if (dragMainEquip != null)
{
dragMainEquip.SetActive(false);
}
if (dragNeedEquip != null)
{
dragNeedEquip.SetActive(false);
}
return;
}
if (dragMainEquip != null)
{
dragMainEquip.SetActive(visible);
}
if (dragNeedEquip != null)
{
dragNeedEquip.SetActive(visible);
}
}
public TransferDropSlot GetHoveredDropSlot(Vector2 screenPoint, Camera eventCamera)
{
if (IsPointerOverDropObject(dragMainEquip, screenPoint, eventCamera))
{
return TransferDropSlot.Main;
}
if (IsPointerOverDropObject(dragNeedEquip, screenPoint, eventCamera))
{
return TransferDropSlot.Need;
}
return TransferDropSlot.None;
}
public void AcceptDraggedEquipment(equipmentSO equipment, TransferDropSlot slot)
{
if (equipment == null)
{
return;
}
switch (slot)
{
case TransferDropSlot.Main:
eqp_p_SO = equipment;
break;
case TransferDropSlot.Need:
eqp_need_SO = equipment;
break;
default:
return;
}
RefreshAll();
}
private void HandleChooseTypeChanged(int _)
{
RefreshAll();
}
private void RefreshAll()
{
RefreshSlotObjects();
RefreshMainEquipPreview();
RefreshNeedEquipPreview();
RefreshTransferPreview();
RefreshPreviewState();
RefreshMaterialRequirements();
RefreshReasonWhy();
RefreshActionState();
}
private void RefreshSlotObjects()
{
if (mainEquipObj != null)
{
mainEquipObj.SetActive(true);
}
if (needEquipObj != null)
{
needEquipObj.SetActive(true);
}
}
private void RefreshMainEquipPreview()
{
DestroyGeneratedChild(mainEquip, "_TransferMain");
DestroySpawned(ref spawnedMainEquipInstance);
if (eqp_p_SO == null || eip == null || mainEquip == null)
{
return;
}
spawnedMainEquipInstance = Instantiate(eip, mainEquip);
spawnedMainEquipInstance.name = $"{eqp_p_SO.name}_TransferMain";
spawnedMainEquipInstance.SetActive(true);
spawnedMainEquipInstance.transform.SetAsLastSibling();
equipItemPrefab item = spawnedMainEquipInstance.GetComponent<equipItemPrefab>();
if (item != null)
{
item.Bind(eqp_p_SO);
item.SetInteractionOptions(false, false);
}
}
private void RefreshNeedEquipPreview()
{
DestroyGeneratedChild(needEquip, "_TransferNeed");
DestroySpawned(ref spawnedNeedEquipInstance);
if (eqp_need_SO == null || eip == null || needEquip == null)
{
return;
}
spawnedNeedEquipInstance = Instantiate(eip, needEquip);
spawnedNeedEquipInstance.name = $"{eqp_need_SO.name}_TransferNeed";
spawnedNeedEquipInstance.SetActive(true);
spawnedNeedEquipInstance.transform.SetAsLastSibling();
equipItemPrefab item = spawnedNeedEquipInstance.GetComponent<equipItemPrefab>();
if (item != null)
{
item.Bind(eqp_need_SO);
item.SetInteractionOptions(false, false);
}
}
private void RefreshTransferPreview()
{
DestroyGeneratedChild(previewEquip, "_TransferPreview");
DestroySpawned(ref spawnedPreviewEquipInstance);
DestroyPreviewEquipment();
string previewFailureReason = GetPreviewFailureReason();
if (!string.IsNullOrEmpty(previewFailureReason) || eip == null || previewEquip == null || eqp_p_SO == null || eqp_need_SO == null)
{
return;
}
previewEquipSO = Instantiate(eqp_p_SO);
previewEquipSO.name = $"{eqp_p_SO.name}(TransferPreview)";
if (GetCurrentMode() == TransferMode.MemoryEntrust)
{
previewEquipSO.specialEffects = CloneEffects(eqp_need_SO.specialEffects);
previewEquipSO.sa_skillID = Mathf.Max(0, eqp_need_SO.sa_skillID);
}
else
{
previewEquipSO.illusionEffects = CloneEffects(eqp_need_SO.illusionEffects);
previewEquipSO.ia_skillID = Mathf.Max(0, eqp_need_SO.ia_skillID);
}
spawnedPreviewEquipInstance = Instantiate(eip, previewEquip);
spawnedPreviewEquipInstance.name = $"{eqp_p_SO.name}_TransferPreview";
spawnedPreviewEquipInstance.SetActive(true);
spawnedPreviewEquipInstance.transform.SetAsLastSibling();
equipItemPrefab item = spawnedPreviewEquipInstance.GetComponent<equipItemPrefab>();
if (item != null)
{
item.Bind(previewEquipSO);
item.SetInteractionOptions(false, false);
}
}
private void RefreshPreviewState()
{
string previewFailureReason = GetPreviewFailureReason();
bool hasPreview = string.IsNullOrEmpty(previewFailureReason) && spawnedPreviewEquipInstance != null;
if (toObj != null)
{
toObj.SetActive(true);
}
if (previewObj != null)
{
previewObj.SetActive(hasPreview);
}
if (previewEquipText != null)
{
previewEquipText.text = hasPreview ? string.Empty : previewFailureReason;
previewEquipText.gameObject.SetActive(!hasPreview && !string.IsNullOrEmpty(previewFailureReason));
}
}
private void RefreshMaterialRequirements()
{
ClearSpawnedMaterialItems();
if (mtrInfo == null)
{
return;
}
string materialReason = GetMaterialFailureReason();
string structuralReason = GetMaterialStructuralFailureReason();
if (!string.IsNullOrEmpty(structuralReason))
{
mtrInfo.text = structuralReason;
return;
}
mtrInfo.text = string.Empty;
SpawnTransferMaterials();
}
private void SpawnTransferMaterials()
{
if (need_mtrSO == null || mtrPrefab == null || mtrParent == null)
{
return;
}
int transferRequired;
int memoryRequired;
int coinRequired;
GetCurrentCosts(out transferRequired, out memoryRequired, out coinRequired);
if (transferRequired > 0 && need_mtrSO.propertyTransferMaterial != null)
{
SpawnMaterialItem(
need_mtrSO.propertyTransferMaterial.consumableSprite,
need_mtrSO.propertyTransferMaterial.consumableName,
EquipmentConsumableLedger.EnsureInstance().GetCount(need_mtrSO.propertyTransferMaterial.consumableKind),
transferRequired);
}
if (coinRequired > 0)
{
SpawnMaterialItem(coins, "Coins", PlayerEconomyLedger.EnsureInstance().GetCoins(), coinRequired);
}
if (memoryRequired > 0)
{
SpawnMaterialItem(memoryFragment, "记忆碎片", PlayerEconomyLedger.EnsureInstance().GetMaterial(), memoryRequired);
}
}
private void SpawnMaterialItem(Sprite sprite, string displayName, int ownedAmount, int requiredAmount)
{
GameObject instance = Instantiate(mtrPrefab, mtrParent);
instance.SetActive(true);
spawnedMaterialItems.Add(instance);
materialPrefab item = instance.GetComponent<materialPrefab>();
if (item != null)
{
item.BindOwnedRequired(sprite, displayName, ownedAmount, requiredAmount, true, false, null);
item.SetSelected(true);
if (item.materialButton != null)
{
item.materialButton.interactable = false;
}
}
}
private void RefreshReasonWhy()
{
if (reasonWhy != null)
{
reasonWhy.text = GetActionFailureReason();
}
}
private void RefreshActionState()
{
if (yesTransferButton != null)
{
yesTransferButton.interactable = string.IsNullOrEmpty(GetActionFailureReason());
}
}
private string GetPreviewFailureReason()
{
if (eqp_p_SO == null || eqp_need_SO == null)
{
return "需要选择主记忆和副记忆";
}
if (eqp_p_SO == eqp_need_SO)
{
return "不能选择同一件记忆";
}
if (eqp_p_SO.skillType != eqp_need_SO.skillType)
{
return "需要同类型记忆";
}
if (GetCurrentMode() == TransferMode.TourEntrust && GetLevelBucket(eqp_p_SO.level) != GetLevelBucket(eqp_need_SO.level))
{
return "巡演嘱托需要相同巡演阶段";
}
return string.Empty;
}
private string GetMaterialFailureReason()
{
int transferRequired;
int memoryRequired;
int coinRequired;
GetCurrentCosts(out transferRequired, out memoryRequired, out coinRequired);
if (transferRequired > 0 && EquipmentConsumableLedger.EnsureInstance().GetCount(need_mtrSO.propertyTransferMaterial.consumableKind) < transferRequired)
{
return "洗炼材料不足";
}
if (!PlayerEconomyLedger.EnsureInstance().HasEnoughCoins(coinRequired))
{
return "硬币不足";
}
if (!PlayerEconomyLedger.EnsureInstance().HasEnoughMaterial(memoryRequired))
{
return "记忆碎片不足";
}
return string.Empty;
}
private string GetMaterialStructuralFailureReason()
{
if (eqp_p_SO == null || eqp_need_SO == null)
{
return "需要选择主记忆和副记忆";
}
string previewFailureReason = GetPreviewFailureReason();
if (!string.IsNullOrEmpty(previewFailureReason))
{
return previewFailureReason;
}
if (need_mtrSO == null)
{
return "未配置洗炼规则";
}
if (need_mtrSO.propertyTransferMaterial == null)
{
return "未配置洗炼材料";
}
return string.Empty;
}
private string GetActionFailureReason()
{
if (eqp_p_SO == null || eqp_need_SO == null)
{
return "需要选择主记忆和副记忆";
}
if (eqp_p_SO == eqp_need_SO)
{
return "不能选择同一件记忆";
}
string previewFailureReason = GetPreviewFailureReason();
if (!string.IsNullOrEmpty(previewFailureReason))
{
return previewFailureReason;
}
string structuralReason = GetMaterialStructuralFailureReason();
if (!string.IsNullOrEmpty(structuralReason))
{
return structuralReason;
}
return GetMaterialFailureReason();
}
private void HandleYesTransferClicked()
{
string failureReason = GetActionFailureReason();
if (!string.IsNullOrEmpty(failureReason))
{
RefreshAll();
return;
}
int transferRequired;
int memoryRequired;
int coinRequired;
GetCurrentCosts(out transferRequired, out memoryRequired, out coinRequired);
if (transferRequired > 0 && !EquipmentConsumableLedger.EnsureInstance().TryConsume(need_mtrSO.propertyTransferMaterial.consumableKind, transferRequired))
{
RefreshAll();
return;
}
if (coinRequired > 0 && !PlayerEconomyLedger.EnsureInstance().TrySpendCoins(coinRequired))
{
if (transferRequired > 0)
{
EquipmentConsumableLedger.EnsureInstance().Add(need_mtrSO.propertyTransferMaterial.consumableKind, transferRequired);
}
RefreshAll();
return;
}
if (memoryRequired > 0 && !PlayerEconomyLedger.EnsureInstance().TrySpendMaterial(memoryRequired))
{
if (coinRequired > 0)
{
PlayerEconomyLedger.EnsureInstance().AddCoins(coinRequired);
}
if (transferRequired > 0)
{
EquipmentConsumableLedger.EnsureInstance().Add(need_mtrSO.propertyTransferMaterial.consumableKind, transferRequired);
}
RefreshAll();
return;
}
if (GetCurrentMode() == TransferMode.MemoryEntrust)
{
eqp_p_SO.specialEffects = CloneEffects(eqp_need_SO.specialEffects);
eqp_p_SO.sa_skillID = Mathf.Max(0, eqp_need_SO.sa_skillID);
}
else
{
eqp_p_SO.illusionEffects = CloneEffects(eqp_need_SO.illusionEffects);
eqp_p_SO.ia_skillID = Mathf.Max(0, eqp_need_SO.ia_skillID);
}
PersistEquipment(eqp_p_SO);
DeleteEquipment(eqp_need_SO);
eqp_need_SO = null;
RefreshAllEquipBags();
RefreshAll();
}
private void GetCurrentCosts(out int transferRequired, out int memoryRequired, out int coinRequired)
{
if (need_mtrSO == null)
{
transferRequired = 0;
memoryRequired = 0;
coinRequired = 0;
return;
}
if (GetCurrentMode() == TransferMode.MemoryEntrust)
{
transferRequired = need_mtrSO.GetMemoryEntrustTransferMaterialRequired();
memoryRequired = need_mtrSO.GetMemoryEntrustMemoryFragmentRequired();
coinRequired = need_mtrSO.GetMemoryEntrustCoinsRequired();
return;
}
int level = eqp_p_SO != null ? eqp_p_SO.level : 0;
transferRequired = need_mtrSO.GetTourEntrustTransferMaterialRequired(level);
memoryRequired = need_mtrSO.GetTourEntrustMemoryFragmentRequired(level);
coinRequired = need_mtrSO.GetTourEntrustCoinsRequired(level);
}
private TransferMode GetCurrentMode()
{
if (chooseType == null)
{
return TransferMode.MemoryEntrust;
}
return chooseType.value == (int)TransferMode.TourEntrust
? TransferMode.TourEntrust
: TransferMode.MemoryEntrust;
}
private void EnsureChooseTypeOptions()
{
if (chooseType == null)
{
return;
}
bool rebuild = chooseType.options == null
|| chooseType.options.Count != 2
|| chooseType.options[0].text != "记忆嘱托"
|| chooseType.options[1].text != "巡演嘱托";
if (!rebuild)
{
return;
}
chooseType.ClearOptions();
chooseType.AddOptions(new List<Dropdown.OptionData>
{
new Dropdown.OptionData("记忆嘱托"),
new Dropdown.OptionData("巡演嘱托")
});
chooseType.value = 0;
chooseType.RefreshShownValue();
}
private static equipmentSO.EquipmentSpecialEffect[] CloneEffects(equipmentSO.EquipmentSpecialEffect[] source)
{
if (source == null || source.Length == 0)
{
return System.Array.Empty<equipmentSO.EquipmentSpecialEffect>();
}
var clone = new equipmentSO.EquipmentSpecialEffect[source.Length];
for (int i = 0; i < source.Length; i++)
{
equipmentSO.EquipmentSpecialEffect effect = source[i];
clone[i] = effect == null
? null
: new equipmentSO.EquipmentSpecialEffect
{
effectType = effect.effectType,
value = effect.value
};
}
return clone;
}
private static int GetLevelBucket(int level)
{
if (level < 0)
{
return -1;
}
if (level >= 20)
{
return 4;
}
if (level >= 15)
{
return 3;
}
if (level >= 10)
{
return 2;
}
if (level >= 5)
{
return 1;
}
return 0;
}
private static bool IsPointerOverDropObject(GameObject dropObject, Vector2 screenPoint, Camera eventCamera)
{
if (dropObject == null || !dropObject.activeInHierarchy)
{
return false;
}
RectTransform[] rects = dropObject.GetComponentsInChildren<RectTransform>(true);
for (int i = 0; i < rects.Length; i++)
{
RectTransform rect = rects[i];
if (rect == null || rect == dropObject.transform)
{
continue;
}
if (RectTransformUtility.RectangleContainsScreenPoint(rect, screenPoint, eventCamera))
{
return true;
}
}
RectTransform selfRect = dropObject.transform as RectTransform;
return selfRect != null && RectTransformUtility.RectangleContainsScreenPoint(selfRect, screenPoint, eventCamera);
}
private void ClearSpawnedMaterialItems()
{
if (mtrParent != null)
{
for (int i = mtrParent.childCount - 1; i >= 0; i--)
{
Transform child = mtrParent.GetChild(i);
if (child == null)
{
continue;
}
#if UNITY_EDITOR
if (!Application.isPlaying)
{
DestroyImmediate(child.gameObject);
}
else
#endif
{
Destroy(child.gameObject);
}
}
}
for (int i = spawnedMaterialItems.Count - 1; i >= 0; i--)
{
GameObject instance = spawnedMaterialItems[i];
if (instance == null)
{
continue;
}
#if UNITY_EDITOR
if (!Application.isPlaying)
{
DestroyImmediate(instance);
}
else
#endif
{
Destroy(instance);
}
}
spawnedMaterialItems.Clear();
}
private void DestroySpawned(ref GameObject instance)
{
if (instance == null)
{
return;
}
#if UNITY_EDITOR
if (!Application.isPlaying)
{
DestroyImmediate(instance);
}
else
#endif
{
Destroy(instance);
}
instance = null;
}
private static void DestroyGeneratedChild(Transform parent, string suffix)
{
if (parent == null || string.IsNullOrEmpty(suffix))
{
return;
}
for (int i = parent.childCount - 1; i >= 0; i--)
{
Transform child = parent.GetChild(i);
if (child == null || !child.name.EndsWith(suffix))
{
continue;
}
#if UNITY_EDITOR
if (!Application.isPlaying)
{
DestroyImmediate(child.gameObject);
}
else
#endif
{
Destroy(child.gameObject);
}
}
}
private void DestroyPreviewEquipment()
{
if (previewEquipSO == null)
{
return;
}
#if UNITY_EDITOR
if (!Application.isPlaying)
{
DestroyImmediate(previewEquipSO);
}
else
#endif
{
Destroy(previewEquipSO);
}
previewEquipSO = null;
}
private static void PersistEquipment(equipmentSO equipment)
{
if (equipment == null)
{
return;
}
#if UNITY_EDITOR
EditorUtility.SetDirty(equipment);
AssetDatabase.SaveAssets();
#endif
}
private static void DeleteEquipment(equipmentSO equipment)
{
if (equipment == null)
{
return;
}
equipmentGenerator.RemoveRuntimeGeneratedEquipment(equipment);
#if UNITY_EDITOR
string assetPath = AssetDatabase.GetAssetPath(equipment);
if (!string.IsNullOrWhiteSpace(assetPath))
{
AssetDatabase.DeleteAsset(assetPath);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
return;
}
#endif
#if UNITY_EDITOR
if (!Application.isPlaying)
{
Object.DestroyImmediate(equipment);
}
else
#endif
{
Object.Destroy(equipment);
}
}
private static void RefreshAllEquipBags()
{
equipBag[] bags = FindObjectsOfType<equipBag>(true);
for (int i = 0; i < bags.Length; i++)
{
if (bags[i] != null)
{
bags[i].Rebuild();
}
}
}
}
@@ -14,6 +14,8 @@ MonoBehaviour:
m_EditorClassIdentifier:
upgradeMaterial: {fileID: 11400000, guid: 4b7d886fc44e4cbe9db602da8c2f9c11, type: 2}
breakthroughMaterial: {fileID: 11400000, guid: 6b403344b9414dbba95b7311c3ff57fa, type: 2}
propertyTransferMaterial: {fileID: 11400000, guid: 11164239e74f4101ac94d6f7b80ac547, type: 2}
finalDreamMaterial: {fileID: 11400000, guid: 7b38bd4f8a8d45d8bd5bd6de3893b995, type: 2}
upgradeMaterialBase: 3
upgradeMaterialGrowth: 3
upgradeCoinsBase: 3
@@ -29,3 +31,27 @@ MonoBehaviour:
coinRequired: 4000
- materialRequired: 200
coinRequired: 10000
memoryEntrustCost:
transferMaterialRequired: 1
memoryFragmentRequired: 100
coinRequired: 1000
tourEntrustStageCosts:
- transferMaterialRequired: 1
memoryFragmentRequired: 100
coinRequired: 1000
- transferMaterialRequired: 2
memoryFragmentRequired: 250
coinRequired: 2497
- transferMaterialRequired: 3
memoryFragmentRequired: 500
coinRequired: 5000
- transferMaterialRequired: 4
memoryFragmentRequired: 800
coinRequired: 8000
- transferMaterialRequired: 5
memoryFragmentRequired: 1200
coinRequired: 12000
finalDreamCost:
transferMaterialRequired: 1
memoryFragmentRequired: 500
coinRequired: 5000
@@ -12,11 +12,26 @@ public class eUpdate_mtrSO : ScriptableObject
public int coinRequired;
}
[System.Serializable]
public class PropertyTransferCost
{
[Tooltip("78121 required count")]
public int transferMaterialRequired;
[Tooltip("player_material required count")]
public int memoryFragmentRequired;
[Tooltip("coin required count")]
public int coinRequired;
}
[Header("Material Definitions")]
[Tooltip("Fixed equipment upgrade consumable definition: 78101")]
public equipmentConsumableSO upgradeMaterial;
[Tooltip("Fixed equipment breakthrough consumable definition: 78111")]
public equipmentConsumableSO breakthroughMaterial;
[Tooltip("Fixed equipment transfer consumable definition: 78121")]
public equipmentConsumableSO propertyTransferMaterial;
[Tooltip("Fixed equipment final dream consumable definition: 78131")]
public equipmentConsumableSO finalDreamMaterial;
[Header("Upgrade Cost")]
[Tooltip("Upgrade material required count = base + level * growth")]
@@ -33,6 +48,15 @@ public class eUpdate_mtrSO : ScriptableObject
[Tooltip("Index 0-3 -> level 4/9/14/19")]
public BreakthroughStageCost[] breakthroughStageCosts = new BreakthroughStageCost[4];
[Header("Property Transfer Cost")]
[Tooltip("Fixed cost for 记忆嘱托")]
public PropertyTransferCost memoryEntrustCost = new PropertyTransferCost();
[Tooltip("Index 0-4 -> level 0-4 / 5-9 / 10-14 / 15-19 / 20")]
public PropertyTransferCost[] tourEntrustStageCosts = new PropertyTransferCost[5];
[Header("Final Dream Cost")]
public PropertyTransferCost finalDreamCost = new PropertyTransferCost();
public int GetUpgradeMaterialRequired(int level)
{
return Mathf.Max(0, upgradeMaterialBase + Mathf.Max(0, level) * upgradeMaterialGrowth);
@@ -70,6 +94,54 @@ public class eUpdate_mtrSO : ScriptableObject
return Mathf.Max(0, breakthroughStageCosts[stageIndex].coinRequired);
}
public int GetMemoryEntrustTransferMaterialRequired()
{
return memoryEntrustCost != null ? Mathf.Max(0, memoryEntrustCost.transferMaterialRequired) : 0;
}
public int GetMemoryEntrustMemoryFragmentRequired()
{
return memoryEntrustCost != null ? Mathf.Max(0, memoryEntrustCost.memoryFragmentRequired) : 0;
}
public int GetMemoryEntrustCoinsRequired()
{
return memoryEntrustCost != null ? Mathf.Max(0, memoryEntrustCost.coinRequired) : 0;
}
public int GetTourEntrustTransferMaterialRequired(int level)
{
PropertyTransferCost cost = GetTourEntrustCost(level);
return cost != null ? Mathf.Max(0, cost.transferMaterialRequired) : 0;
}
public int GetTourEntrustMemoryFragmentRequired(int level)
{
PropertyTransferCost cost = GetTourEntrustCost(level);
return cost != null ? Mathf.Max(0, cost.memoryFragmentRequired) : 0;
}
public int GetTourEntrustCoinsRequired(int level)
{
PropertyTransferCost cost = GetTourEntrustCost(level);
return cost != null ? Mathf.Max(0, cost.coinRequired) : 0;
}
public int GetFinalDreamMaterialRequired()
{
return finalDreamCost != null ? Mathf.Max(0, finalDreamCost.transferMaterialRequired) : 0;
}
public int GetFinalDreamMemoryFragmentRequired()
{
return finalDreamCost != null ? Mathf.Max(0, finalDreamCost.memoryFragmentRequired) : 0;
}
public int GetFinalDreamCoinsRequired()
{
return finalDreamCost != null ? Mathf.Max(0, finalDreamCost.coinRequired) : 0;
}
public int GetBreakthroughStageIndex(int level)
{
switch (level)
@@ -87,6 +159,47 @@ public class eUpdate_mtrSO : ScriptableObject
}
}
public int GetTransferStageIndex(int level)
{
if (level < 0)
{
return -1;
}
if (level >= 20)
{
return 4;
}
if (level >= 15)
{
return 3;
}
if (level >= 10)
{
return 2;
}
if (level >= 5)
{
return 1;
}
return 0;
}
private PropertyTransferCost GetTourEntrustCost(int level)
{
int stageIndex = GetTransferStageIndex(level);
if (stageIndex < 0 || tourEntrustStageCosts == null || stageIndex >= tourEntrustStageCosts.Length)
{
return null;
}
return tourEntrustStageCosts[stageIndex];
}
private void OnValidate()
{
if (breakthroughStageCosts == null || breakthroughStageCosts.Length != 4)
@@ -109,5 +222,37 @@ public class eUpdate_mtrSO : ScriptableObject
breakthroughStageCosts[i].materialRequired = Mathf.Max(0, breakthroughStageCosts[i].materialRequired);
breakthroughStageCosts[i].coinRequired = Mathf.Max(0, breakthroughStageCosts[i].coinRequired);
}
memoryEntrustCost ??= new PropertyTransferCost();
memoryEntrustCost.transferMaterialRequired = Mathf.Max(0, memoryEntrustCost.transferMaterialRequired);
memoryEntrustCost.memoryFragmentRequired = Mathf.Max(0, memoryEntrustCost.memoryFragmentRequired);
memoryEntrustCost.coinRequired = Mathf.Max(0, memoryEntrustCost.coinRequired);
if (tourEntrustStageCosts == null || tourEntrustStageCosts.Length != 5)
{
var resized = new PropertyTransferCost[5];
if (tourEntrustStageCosts != null)
{
for (int i = 0; i < Mathf.Min(tourEntrustStageCosts.Length, resized.Length); i++)
{
resized[i] = tourEntrustStageCosts[i];
}
}
tourEntrustStageCosts = resized;
}
for (int i = 0; i < tourEntrustStageCosts.Length; i++)
{
tourEntrustStageCosts[i] ??= new PropertyTransferCost();
tourEntrustStageCosts[i].transferMaterialRequired = Mathf.Max(0, tourEntrustStageCosts[i].transferMaterialRequired);
tourEntrustStageCosts[i].memoryFragmentRequired = Mathf.Max(0, tourEntrustStageCosts[i].memoryFragmentRequired);
tourEntrustStageCosts[i].coinRequired = Mathf.Max(0, tourEntrustStageCosts[i].coinRequired);
}
finalDreamCost ??= new PropertyTransferCost();
finalDreamCost.transferMaterialRequired = Mathf.Max(0, finalDreamCost.transferMaterialRequired);
finalDreamCost.memoryFragmentRequired = Mathf.Max(0, finalDreamCost.memoryFragmentRequired);
finalDreamCost.coinRequired = Mathf.Max(0, finalDreamCost.coinRequired);
}
}
@@ -242,7 +242,7 @@ public class equipUpdate : MonoBehaviour
}
prevLevelText.text = $"{Mathf.Max(0, eqp_p_SO.level)}追忆等级";
prevLevelText.color = ResolveEquipmentColor(GetQualityColorIndex(eqp_p_SO.level));
prevLevelText.color = ResolveEquipmentColor(eqp_p_SO.GetVisualQualityColorIndex());
}
private void RefreshNextLevelText()
@@ -259,7 +259,7 @@ public class equipUpdate : MonoBehaviour
}
nextLevelText.text = $"{Mathf.Max(0, nextLevelPreviewSO.level)}追忆等级";
nextLevelText.color = ResolveEquipmentColor(GetQualityColorIndex(nextLevelPreviewSO.level));
nextLevelText.color = ResolveEquipmentColor(nextLevelPreviewSO.GetVisualQualityColorIndex());
}
private void RefreshMaterialRequirements()
@@ -281,7 +281,7 @@ public class equipUpdate : MonoBehaviour
{
if (mtrInfo != null)
{
mtrInfo.text = "装备不合法";
mtrInfo.text = "记忆不合法";
}
return;
}
@@ -290,7 +290,7 @@ public class equipUpdate : MonoBehaviour
{
if (mtrInfo != null)
{
mtrInfo.text = "<color=#FF69B4>梦醒装备已满级</color>";
mtrInfo.text = "已完成全部追忆";
}
return;
}
@@ -328,7 +328,8 @@ public class equipUpdate : MonoBehaviour
SpawnMaterialItem(
need_mtrSO.upgradeMaterial.consumableSprite,
need_mtrSO.upgradeMaterial.consumableName,
upgradeMaterialRequired.ToString());
EquipmentConsumableLedger.EnsureInstance().GetCount(need_mtrSO.upgradeMaterial.consumableKind),
upgradeMaterialRequired);
}
if (upgradeCoinsRequired > 0)
@@ -336,7 +337,8 @@ public class equipUpdate : MonoBehaviour
SpawnMaterialItem(
coinSprite,
"Coins",
upgradeCoinsRequired.ToString());
PlayerEconomyLedger.EnsureInstance().GetCoins(),
upgradeCoinsRequired);
}
if (upgradeMemoryRequired > 0)
@@ -344,11 +346,12 @@ public class equipUpdate : MonoBehaviour
SpawnMaterialItem(
MemoryFragmentSprite,
"记忆碎片",
upgradeMemoryRequired.ToString());
PlayerEconomyLedger.EnsureInstance().GetMaterial(),
upgradeMemoryRequired);
}
}
private void SpawnMaterialItem(Sprite sprite, string displayName, string amountText)
private void SpawnMaterialItem(Sprite sprite, string displayName, int ownedAmount, int requiredAmount)
{
GameObject instance = Instantiate(mtrPrefab, mtrParent);
instance.SetActive(true);
@@ -357,7 +360,7 @@ public class equipUpdate : MonoBehaviour
materialPrefab item = instance.GetComponent<materialPrefab>();
if (item != null)
{
item.Bind(sprite, displayName, amountText, true, false, null);
item.BindOwnedRequired(sprite, displayName, ownedAmount, requiredAmount, true, false, null);
item.SetSelected(true);
if (item.materialButton != null)
{
@@ -408,7 +411,7 @@ public class equipUpdate : MonoBehaviour
if (level >= 20)
{
return "梦醒装备已满级";
return "此记忆已完成全部追忆";
}
if (RequiresTour(level))
@@ -544,31 +547,6 @@ public class equipUpdate : MonoBehaviour
return itemPrefab.itemBtmColors[safeIndex];
}
private static int GetQualityColorIndex(int level)
{
if (level >= 20)
{
return 5;
}
if (level >= 15)
{
return 4;
}
if (level >= 10)
{
return 3;
}
if (level >= 5)
{
return 2;
}
return 1;
}
private static bool IsLegalLevel(int level)
{
return level >= 0 && level <= 20;
@@ -1,16 +0,0 @@
using UnityEngine;
public class equipTransfer : MonoBehaviour
{
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}
+18 -48
View File
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEngine;
using Bansonic;
#if UNITY_EDITOR
using UnityEditor;
using UnityEditor.SceneManagement;
@@ -60,6 +61,20 @@ public class equipmentRandomTestButton : MonoBehaviour
{
targetEquipBag.Rebuild();
}
equipBag[] bags = FindObjectsOfType<equipBag>(true);
if (bags == null)
{
return;
}
for (int i = 0; i < bags.Length; i++)
{
if (bags[i] != null && bags[i] != targetEquipBag)
{
bags[i].Rebuild();
}
}
}
[ContextMenu("Generate Equipment SO")]
@@ -91,7 +106,7 @@ public class equipmentRandomTestButton : MonoBehaviour
#endif
equipmentSO generated = Instantiate(sourceEquipment);
generated.name = BuildGeneratedName(sourceEquipment);
generated.name = equipmentGenerator.GenerateUniqueEquipmentName(sourceEquipment != null ? sourceEquipment.skillType : 0);
generated.hideFlags = HideFlags.None;
generated.level = 0;
generated.sa_skillID = 0;
@@ -617,7 +632,7 @@ public class equipmentRandomTestButton : MonoBehaviour
}
#if UNITY_EDITOR
if (saveGeneratedAssetInEditor)
if (!Application.isPlaying && saveGeneratedAssetInEditor)
{
EnsureEditorOutputFolderExists();
string assetPath = AssetDatabase.GenerateUniqueAssetPath($"{EditorOutputFolder}/{generated.name}.asset");
@@ -629,52 +644,7 @@ public class equipmentRandomTestButton : MonoBehaviour
}
#endif
return generated;
}
private static string BuildGeneratedName(equipmentSO source)
{
int typeIndex = source != null ? (int)source.skillType : 0;
int nextId = GetNextGeneratedId();
return $"type{typeIndex}_{DateTime.Now:yyyyMMdd}_{nextId:00000000}";
}
private static int GetNextGeneratedId()
{
#if UNITY_EDITOR
string absoluteFolder = Path.Combine(Directory.GetCurrentDirectory(), "Assets", "Resources", "so", "uEquip");
if (!Directory.Exists(absoluteFolder))
{
return 1;
}
int maxId = 0;
string[] files = Directory.GetFiles(absoluteFolder, "*.asset", SearchOption.TopDirectoryOnly);
for (int i = 0; i < files.Length; i++)
{
string fileName = Path.GetFileNameWithoutExtension(files[i]);
if (string.IsNullOrWhiteSpace(fileName))
{
continue;
}
int lastUnderscore = fileName.LastIndexOf('_');
if (lastUnderscore < 0 || lastUnderscore >= fileName.Length - 1)
{
continue;
}
string idPart = fileName.Substring(lastUnderscore + 1);
if (int.TryParse(idPart, out int parsedId) && parsedId > maxId)
{
maxId = parsedId;
}
}
return maxId + 1;
#else
return 1;
#endif
return equipmentGenerator.RegisterGeneratedEquipment(generated);
}
private static void WriteGeneratedEffectsBack(
+128
View File
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu(fileName = "NewEquipment", menuName = "Equipment/Equipment SO")]
@@ -101,6 +102,11 @@ public class equipmentSO : ScriptableObject
public int sa_skillID;
public int ia_skillID;
public bool HasFinalDreamEffect()
{
return maxLevelEffects != null && maxLevelEffects.Length > 0;
}
public int GetTierStageIndex()
{
if (level >= 20)
@@ -126,11 +132,63 @@ public class equipmentSO : ScriptableObject
return 0;
}
public int GetVisualTierStageIndex()
{
if (level >= 20 && !HasFinalDreamEffect())
{
return 3;
}
return GetTierStageIndex();
}
public int GetVisualQualityColorIndex()
{
return GetVisualTierStageIndex() + 1;
}
public EquipmentTierPresentation GetCurrentTierPresentation()
{
return GetTierPresentationByStageIndex(GetTierStageIndex());
}
public EquipmentTierPresentation GetVisualTierPresentation()
{
return GetTierPresentationByStageIndex(GetVisualTierStageIndex());
}
public EquipmentTierPresentation GetIdentityTierPresentation()
{
if (level >= 20)
{
return GetTierPresentationByStageIndex(3);
}
return GetTierPresentationByStageIndex(GetTierStageIndex());
}
public string GetDisplayTierName()
{
string baseName = GetIdentityTierPresentation() != null ? GetIdentityTierPresentation().tierName : string.Empty;
if (level >= 20 && HasFinalDreamEffect())
{
return string.IsNullOrWhiteSpace(baseName) ? "梦醒记忆" : $"梦醒·{baseName}";
}
string visualName = GetVisualTierPresentation() != null ? GetVisualTierPresentation().tierName : string.Empty;
return !string.IsNullOrWhiteSpace(visualName) ? visualName : baseName;
}
public string GetDisplayTierDescription()
{
if (level >= 20 && HasFinalDreamEffect())
{
return GetIdentityTierPresentation() != null ? GetIdentityTierPresentation().tierDescription : string.Empty;
}
return GetVisualTierPresentation() != null ? GetVisualTierPresentation().tierDescription : string.Empty;
}
public EquipmentTierPresentation GetTierPresentationByStageIndex(int stageIndex)
{
if (tierNameConfig == null)
@@ -163,13 +221,83 @@ public class equipmentSO : ScriptableObject
return current != null ? current.equipmentSprite : null;
}
public SkillGroup GetSpecialSkillGroup()
{
return EquipmentSkillGroupLibrary.ResolveSpecialSkillGroup(sa_skillID);
}
public SkillGroup GetIllusionSkillGroup()
{
return EquipmentSkillGroupLibrary.ResolveIllusionSkillGroup(ia_skillID);
}
public EquipmentSpecialEffect[] GetNormalizedIllusionEffects()
{
if (illusionEffects == null || illusionEffects.Length == 0)
{
return Array.Empty<EquipmentSpecialEffect>();
}
var normalized = new List<EquipmentSpecialEffect>();
var bestValues = new Dictionary<EquipmentSpecialEffectType, float>();
bool hasSkill = false;
for (int i = 0; i < illusionEffects.Length; i++)
{
EquipmentSpecialEffect effect = illusionEffects[i];
if (effect == null)
{
continue;
}
if (effect.effectType == EquipmentSpecialEffectType.Skill)
{
if (!hasSkill)
{
normalized.Add(new EquipmentSpecialEffect
{
effectType = EquipmentSpecialEffectType.Skill,
value = effect.value
});
hasSkill = true;
}
continue;
}
if (!bestValues.TryGetValue(effect.effectType, out float currentBest) || effect.value > currentBest)
{
bestValues[effect.effectType] = effect.value;
}
}
foreach (KeyValuePair<EquipmentSpecialEffectType, float> pair in bestValues)
{
normalized.Add(new EquipmentSpecialEffect
{
effectType = pair.Key,
value = pair.Value
});
}
return normalized.ToArray();
}
public void NormalizeIllusionEffectsInPlace()
{
illusionEffects = GetNormalizedIllusionEffects();
}
private void OnValidate()
{
level = Mathf.Max(0, level);
sa_skillID = Mathf.Max(0, sa_skillID);
ia_skillID = Mathf.Max(0, ia_skillID);
maxHp?.Normalize();
attack?.Normalize();
maxMana?.Normalize();
damageResistance?.Normalize();
scoreEfficiency?.Normalize();
NormalizeIllusionEffectsInPlace();
}
}
+44
View File
@@ -0,0 +1,44 @@
using UnityEngine;
using UnityEngine.UI;
public class esDesPrefab : MonoBehaviour
{
public Image skillProfile;
public Text skillName;
public Text skillDescription;
public Text skill_story;
public void Bind(string displayName, Sprite icon, string description)
{
if (skillProfile != null)
{
skillProfile.sprite = icon;
skillProfile.enabled = icon != null;
}
if (skillName != null)
{
skillName.text = displayName ?? string.Empty;
}
string mainText = description ?? string.Empty;
string storyText = string.Empty;
int splitIndex = mainText.IndexOf("\n\n", System.StringComparison.Ordinal);
if (splitIndex >= 0)
{
storyText = mainText.Substring(splitIndex + 2).Trim();
mainText = mainText.Substring(0, splitIndex).Trim();
}
if (skillDescription != null)
{
skillDescription.text = mainText;
}
if (skill_story != null)
{
skill_story.text = storyText;
skill_story.gameObject.SetActive(!string.IsNullOrWhiteSpace(storyText));
}
}
}
+2
View File
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: d5bd4d3da9ce5f7469a0da1ab89898dc
+613
View File
@@ -0,0 +1,613 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &1612139607783385169
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 924515356628486074}
- component: {fileID: 2049021961984502307}
- component: {fileID: 1269994992563019816}
- component: {fileID: 1344281549264830262}
m_Layer: 5
m_Name: space
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &924515356628486074
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1612139607783385169}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 988958299287877993}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 1}
m_AnchorMax: {x: 0, y: 1}
m_AnchoredPosition: {x: 124.06795, y: -57}
m_SizeDelta: {x: 208.1359, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &2049021961984502307
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1612139607783385169}
m_CullTransparentMesh: 1
--- !u!114 &1269994992563019816
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1612139607783385169}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 0
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 0
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_FontData:
m_Font: {fileID: 12800000, guid: bd4be44636ad6c24a9b117a7108a75e9, type: 3}
m_FontSize: 10
m_FontStyle: 0
m_BestFit: 0
m_MinSize: 1
m_MaxSize: 40
m_Alignment: 0
m_AlignByGeometry: 0
m_RichText: 1
m_HorizontalOverflow: 0
m_VerticalOverflow: 0
m_LineSpacing: 1
m_Text:
--- !u!114 &1344281549264830262
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1612139607783385169}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 3245ec927659c4140ac4f8d17403cc18, type: 3}
m_Name:
m_EditorClassIdentifier:
m_HorizontalFit: 0
m_VerticalFit: 2
--- !u!1 &2219571326304505587
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 9054828609818255886}
- component: {fileID: 7998650243502776085}
m_Layer: 5
m_Name: esDesPrefab
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &9054828609818255886
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2219571326304505587}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 988958299287877993}
- {fileID: 7423510225050775796}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 100, y: 100}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &7998650243502776085
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2219571326304505587}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: d5bd4d3da9ce5f7469a0da1ab89898dc, type: 3}
m_Name:
m_EditorClassIdentifier:
skillProfile: {fileID: 1406394923191429614}
skillName: {fileID: 6902465092920455358}
skillDescription: {fileID: 2059384551927036819}
skill_story: {fileID: 3532520328048197567}
--- !u!1 &2248368019032796126
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 988958299287877993}
- component: {fileID: 2584086730511143375}
- component: {fileID: 204172398640256117}
- component: {fileID: 831017849665891528}
- component: {fileID: 2721093110854513819}
m_Layer: 5
m_Name: btm
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &988958299287877993
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2248368019032796126}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 8815412670136324479}
- {fileID: 924515356628486074}
- {fileID: 8309952930913086256}
m_Father: {fileID: 9054828609818255886}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 0, y: 49.05}
m_SizeDelta: {x: 250, y: 0}
m_Pivot: {x: 0.5, y: 1}
--- !u!222 &2584086730511143375
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2248368019032796126}
m_CullTransparentMesh: 1
--- !u!114 &204172398640256117
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2248368019032796126}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 0, g: 0, b: 0, a: 0.88235295}
m_RaycastTarget: 0
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 0
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 21300000, guid: 7f3b1220317607e44bbb8f0e1998044a, type: 3}
m_Type: 1
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 2
--- !u!114 &831017849665891528
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2248368019032796126}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 59f8146938fff824cb5fd77236b75775, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Padding:
m_Left: 20
m_Right: 0
m_Top: 57
m_Bottom: 10
m_ChildAlignment: 0
m_Spacing: 0
m_ChildForceExpandWidth: 1
m_ChildForceExpandHeight: 1
m_ChildControlWidth: 0
m_ChildControlHeight: 0
m_ChildScaleWidth: 0
m_ChildScaleHeight: 0
m_ReverseArrangement: 0
--- !u!114 &2721093110854513819
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2248368019032796126}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 3245ec927659c4140ac4f8d17403cc18, type: 3}
m_Name:
m_EditorClassIdentifier:
m_HorizontalFit: 0
m_VerticalFit: 2
--- !u!1 &3143097149929748427
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 7423510225050775796}
- component: {fileID: 9039629176871680988}
- component: {fileID: 1406394923191429614}
m_Layer: 5
m_Name: profile
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &7423510225050775796
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3143097149929748427}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 666282125204121527}
m_Father: {fileID: 9054828609818255886}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: -93.8, y: 21.4}
m_SizeDelta: {x: 25, y: 25}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &9039629176871680988
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3143097149929748427}
m_CullTransparentMesh: 1
--- !u!114 &1406394923191429614
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3143097149929748427}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 0
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 0
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 0}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &3501875630358650327
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 8309952930913086256}
- component: {fileID: 2792857840598114499}
- component: {fileID: 3532520328048197567}
- component: {fileID: 2440302725371450655}
m_Layer: 5
m_Name: extraSentence
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &8309952930913086256
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3501875630358650327}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 988958299287877993}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 1}
m_AnchorMax: {x: 0, y: 1}
m_AnchoredPosition: {x: 124.06795, y: -57}
m_SizeDelta: {x: 208.1359, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &2792857840598114499
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3501875630358650327}
m_CullTransparentMesh: 1
--- !u!114 &3532520328048197567
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3501875630358650327}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 0
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 0
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_FontData:
m_Font: {fileID: 12800000, guid: bd4be44636ad6c24a9b117a7108a75e9, type: 3}
m_FontSize: 12
m_FontStyle: 2
m_BestFit: 0
m_MinSize: 1
m_MaxSize: 40
m_Alignment: 0
m_AlignByGeometry: 0
m_RichText: 1
m_HorizontalOverflow: 0
m_VerticalOverflow: 0
m_LineSpacing: 1
m_Text: New Text
--- !u!114 &2440302725371450655
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3501875630358650327}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 3245ec927659c4140ac4f8d17403cc18, type: 3}
m_Name:
m_EditorClassIdentifier:
m_HorizontalFit: 0
m_VerticalFit: 2
--- !u!1 &4565270283902900141
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 8815412670136324479}
- component: {fileID: 1487207466561665800}
- component: {fileID: 2059384551927036819}
- component: {fileID: 8235204285893949131}
m_Layer: 5
m_Name: skillifo
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &8815412670136324479
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4565270283902900141}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 988958299287877993}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 1}
m_AnchorMax: {x: 0, y: 1}
m_AnchoredPosition: {x: 124.06795, y: -57}
m_SizeDelta: {x: 208.1359, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &1487207466561665800
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4565270283902900141}
m_CullTransparentMesh: 1
--- !u!114 &2059384551927036819
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4565270283902900141}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 0
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 0
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_FontData:
m_Font: {fileID: 12800000, guid: bd4be44636ad6c24a9b117a7108a75e9, type: 3}
m_FontSize: 16
m_FontStyle: 0
m_BestFit: 0
m_MinSize: 1
m_MaxSize: 40
m_Alignment: 0
m_AlignByGeometry: 0
m_RichText: 1
m_HorizontalOverflow: 0
m_VerticalOverflow: 0
m_LineSpacing: 1
m_Text: New Text
--- !u!114 &8235204285893949131
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4565270283902900141}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 3245ec927659c4140ac4f8d17403cc18, type: 3}
m_Name:
m_EditorClassIdentifier:
m_HorizontalFit: 0
m_VerticalFit: 2
--- !u!1 &7517354069297951484
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 666282125204121527}
- component: {fileID: 2051176798838203983}
- component: {fileID: 6902465092920455358}
m_Layer: 5
m_Name: skillName
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &666282125204121527
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7517354069297951484}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 7423510225050775796}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 107.89009, y: 0}
m_SizeDelta: {x: 184.1802, y: 30}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &2051176798838203983
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7517354069297951484}
m_CullTransparentMesh: 1
--- !u!114 &6902465092920455358
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7517354069297951484}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 0
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 0
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_FontData:
m_Font: {fileID: 12800000, guid: dfa10de3e2846524089b5073175cd151, type: 3}
m_FontSize: 18
m_FontStyle: 0
m_BestFit: 0
m_MinSize: 1
m_MaxSize: 40
m_Alignment: 3
m_AlignByGeometry: 0
m_RichText: 1
m_HorizontalOverflow: 0
m_VerticalOverflow: 0
m_LineSpacing: 1
m_Text: "\u6CA1\u843D\u9B54\u672F\u5E08\u7684\u8C06\u8C06\u6559\u8BF2"
+7
View File
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: bde76837f913f3943836d4f83292618b
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+127 -1
View File
@@ -1,8 +1,134 @@
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
public class esPrefab : MonoBehaviour
public class esPrefab : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler
{
public Image esIcon;
public Text esName;
private int skillGroupId;
private GameObject descriptionPrefab;
private RectTransform descriptionRoot;
private GameObject spawnedDescription;
private RectTransform rectTransform;
private Canvas rootCanvas;
private Camera uiCamera;
private Vector2 descriptionOffset = new Vector2(20f, 30f);
private void Awake()
{
rectTransform = transform as RectTransform;
rootCanvas = GetComponentInParent<Canvas>();
if (rootCanvas != null && rootCanvas.renderMode != RenderMode.ScreenSpaceOverlay)
{
uiCamera = rootCanvas.worldCamera;
}
}
private void OnDisable()
{
DestroyDescription();
}
private void OnDestroy()
{
DestroyDescription();
}
public void BindSkillGroup(int groupId, string displayName, Sprite icon, GameObject desPrefab, RectTransform ownerRoot, Vector2 offset)
{
skillGroupId = Mathf.Max(0, groupId);
descriptionPrefab = desPrefab;
descriptionRoot = ownerRoot;
descriptionOffset = offset;
if (esName != null)
{
esName.text = displayName ?? string.Empty;
}
if (esIcon != null)
{
esIcon.sprite = icon;
esIcon.enabled = icon != null;
}
}
public void OnPointerEnter(PointerEventData eventData)
{
ShowDescription();
}
public void OnPointerExit(PointerEventData eventData)
{
DestroyDescription();
}
private void ShowDescription()
{
if (spawnedDescription != null || descriptionPrefab == null || descriptionRoot == null || skillGroupId <= 0)
{
return;
}
SkillGroup skillGroup = EquipmentSkillGroupLibrary.ResolveSkillGroup(skillGroupId);
if (skillGroup == null)
{
return;
}
spawnedDescription = Instantiate(descriptionPrefab, descriptionRoot);
spawnedDescription.SetActive(true);
spawnedDescription.transform.SetAsLastSibling();
esDesPrefab description = spawnedDescription.GetComponent<esDesPrefab>();
if (description != null)
{
description.Bind(skillGroup.groupName, skillGroup.groupIcon, skillGroup.skillDescriptionsText);
}
PositionDescription(spawnedDescription.transform as RectTransform);
}
private void PositionDescription(RectTransform descriptionRect)
{
if (descriptionRect == null || rectTransform == null || descriptionRoot == null)
{
return;
}
Vector3[] corners = new Vector3[4];
rectTransform.GetWorldCorners(corners);
Vector3 rightCenterWorld = (corners[2] + corners[3]) * 0.5f;
Vector2 screenPoint = RectTransformUtility.WorldToScreenPoint(uiCamera, rightCenterWorld);
if (!RectTransformUtility.ScreenPointToLocalPointInRectangle(descriptionRoot, screenPoint, uiCamera, out Vector2 localPoint))
{
return;
}
descriptionRect.anchorMin = new Vector2(0f, 1f);
descriptionRect.anchorMax = new Vector2(0f, 1f);
descriptionRect.pivot = new Vector2(0f, 1f);
descriptionRect.anchoredPosition = localPoint + descriptionOffset;
}
private void DestroyDescription()
{
if (spawnedDescription == null)
{
return;
}
if (Application.isPlaying)
{
Destroy(spawnedDescription);
}
else
{
DestroyImmediate(spawnedDescription);
}
spawnedDescription = null;
}
}