Files
bansonic_beta_main/Assets/_eqpmtSys/equipmentRandomTestButton.cs
T

885 lines
31 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEngine;
using Bansonic;
#if UNITY_EDITOR
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEditorInternal;
#endif
public class equipmentRandomTestButton : MonoBehaviour
{
private const string EditorOutputFolder = "Assets/Resources/so/uEquip";
[Serializable]
public class GeneratedStatValue
{
public string statName;
public float value;
}
[Serializable]
public class GeneratedEffectValue
{
public equipmentSO.EquipmentSpecialEffectType effectType;
public string displayName;
public float value;
public Sprite displayIcon;
public int skillId;
}
[Header("Source")]
public equipmentRandomConfigSO randomConfig;
public equipmentSO sourceEquipment;
public bool saveGeneratedAssetInEditor = true;
public equipBag targetEquipBag;
[Header("Generated Preview")]
public equipmentSO lastGeneratedEquipment;
public List<GeneratedStatValue> generatedBasicAttributes = new List<GeneratedStatValue>();
public List<GeneratedEffectValue> generatedTypeSameEffects = new List<GeneratedEffectValue>();
public List<GeneratedEffectValue> generatedSpecialEffects = new List<GeneratedEffectValue>();
public List<GeneratedEffectValue> generatedIllusionEffects = new List<GeneratedEffectValue>();
[TextArea(4, 12)]
public string lastGenerationSummary;
public string lastGeneratedAssetPath;
[ContextMenu("Generate Equipment Preview")]
public void GenerateEquipmentPreview()
{
GenerateEquipmentSO();
}
[ContextMenu("Refresh Equipment List")]
public void RefreshEquipmentList()
{
if (targetEquipBag != null)
{
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")]
public void GenerateEquipmentSO()
{
generatedBasicAttributes.Clear();
generatedTypeSameEffects.Clear();
generatedSpecialEffects.Clear();
generatedIllusionEffects.Clear();
lastGenerationSummary = string.Empty;
lastGeneratedEquipment = null;
lastGeneratedAssetPath = string.Empty;
Debug.Log("[equipmentRandomTestButton] GenerateEquipmentSO invoked.", this);
if (randomConfig == null || sourceEquipment == null)
{
lastGenerationSummary = "Missing randomConfig or sourceEquipment.";
Debug.LogWarning("[equipmentRandomTestButton] Missing randomConfig or sourceEquipment.");
return;
}
randomConfig.NormalizeRuntimeData();
#if UNITY_EDITOR
if (!Application.isPlaying)
{
EditorUtility.SetDirty(randomConfig);
}
#endif
equipmentSO generated = Instantiate(sourceEquipment);
generated.name = equipmentGenerator.GenerateUniqueEquipmentName(sourceEquipment != null ? sourceEquipment.skillType : 0);
generated.hideFlags = HideFlags.None;
generated.level = 0;
generated.sa_skillID = 0;
generated.ia_skillID = 0;
generated.enableTypeSameEffects = sourceEquipment != null && sourceEquipment.enableTypeSameEffects;
generated.typeSameEffects = Array.Empty<equipmentSO.EquipmentSpecialEffect>();
ResetBasicGains(generated);
GenerateBasicAttributes(generated);
GenerateTypeSameEffects(generated);
GenerateSpecialEffects(generated);
GenerateIllusionEffects(generated);
lastGeneratedEquipment = PersistGeneratedEquipment(generated);
if (lastGeneratedEquipment != null)
{
gItemGet.display(gItemGet.FromEquipment(lastGeneratedEquipment, 1));
}
BuildSummary(generated);
RefreshEquipmentList();
MarkHostDirty();
}
private void GenerateBasicAttributes(equipmentSO generated)
{
if (generated == null)
{
return;
}
var candidates = new List<(string name, equipmentSO.EquipmentStatTuning tuning, equipmentRandomConfigSO.RandomBasicAttributeType type)>
{
("MaxHp", generated.maxHp, equipmentRandomConfigSO.RandomBasicAttributeType.MaxHp),
("Attack", generated.attack, equipmentRandomConfigSO.RandomBasicAttributeType.Attack),
("MaxMana", generated.maxMana, equipmentRandomConfigSO.RandomBasicAttributeType.MaxMana),
("DamageResistance", generated.damageResistance, equipmentRandomConfigSO.RandomBasicAttributeType.DamageResistance),
("ScoreEfficiency", generated.scoreEfficiency, equipmentRandomConfigSO.RandomBasicAttributeType.ScoreEfficiency)
};
candidates.RemoveAll(entry =>
entry.tuning == null ||
!randomConfig.TryGetBasicRange(entry.type, out _, out _));
int count = Mathf.Clamp(randomConfig.randomBasicAttributeCount, 0, candidates.Count);
for (int i = 0; i < count; i++)
{
int pickIndex = UnityEngine.Random.Range(0, candidates.Count);
var picked = candidates[pickIndex];
candidates.RemoveAt(pickIndex);
randomConfig.TryGetBasicRange(picked.type, out float minValue, out float maxValue);
float rolledValue = RollBiasedValue(minValue, maxValue);
picked.tuning.basicGain = rolledValue;
generatedBasicAttributes.Add(new GeneratedStatValue
{
statName = picked.name,
value = rolledValue
});
}
MarkEquipmentDirty(generated);
}
private void GenerateSpecialEffects(equipmentSO generated)
{
if (generated == null)
{
return;
}
int effectCount = RollSpecialEffectCount();
if (effectCount <= 0)
{
return;
}
HashSet<equipmentSO.EquipmentSpecialEffectType> selectedBasicTypes = GetSelectedBasicAttributeTypes(generated);
List<equipmentSO.EquipmentSpecialEffectType> valuePool = BuildSpecialEffectPool(selectedBasicTypes, generated.enableTypeSameEffects);
if (valuePool.Count == 0)
{
generated.specialEffects = Array.Empty<equipmentSO.EquipmentSpecialEffect>();
generated.sa_skillID = 0;
MarkEquipmentDirty(generated);
return;
}
for (int i = 0; i < effectCount; i++)
{
int pickIndex = UnityEngine.Random.Range(0, valuePool.Count);
equipmentSO.EquipmentSpecialEffectType effectType = valuePool[pickIndex];
if (!TryMapToSpecialRange(effectType, out equipmentRandomConfigSO.RandomSpecialEffectType rangeType))
{
continue;
}
if (!randomConfig.TryGetSpecialRange(rangeType, out float minValue, out float maxValue))
{
continue;
}
generatedSpecialEffects.Add(new GeneratedEffectValue
{
effectType = effectType,
displayName = effectType.ToString(),
value = RollBiasedValue(minValue, maxValue),
displayIcon = null,
skillId = 0
});
}
ResolveDuplicateEffects(generatedSpecialEffects);
TryGenerateSpecialSkill(generated);
generated.specialEffects = BuildGeneratedEffectArray(generatedSpecialEffects);
MarkEquipmentDirty(generated);
}
private void GenerateTypeSameEffects(equipmentSO generated)
{
if (generated == null)
{
return;
}
generated.typeSameEffects = Array.Empty<equipmentSO.EquipmentSpecialEffect>();
HashSet<equipmentSO.EquipmentSpecialEffectType> selectedBasicTypes = GetSelectedBasicAttributeTypes(generated);
if (selectedBasicTypes.Count == 0)
{
return;
}
var generatedEffects = new List<equipmentSO.EquipmentSpecialEffect>();
foreach (equipmentSO.EquipmentSpecialEffectType effectType in selectedBasicTypes)
{
if (!TryMapToSpecialRange(effectType, out equipmentRandomConfigSO.RandomSpecialEffectType rangeType))
{
continue;
}
if (!randomConfig.TryGetTypeSameEffectRange(rangeType, out float minValue, out float maxValue))
{
continue;
}
float rolledValue = RollBiasedValue(minValue, maxValue);
generatedEffects.Add(new equipmentSO.EquipmentSpecialEffect
{
effectType = effectType,
value = rolledValue
});
generatedTypeSameEffects.Add(new GeneratedEffectValue
{
effectType = effectType,
displayName = effectType.ToString(),
value = rolledValue,
displayIcon = null,
skillId = 0
});
}
generated.typeSameEffects = generatedEffects.ToArray();
MarkEquipmentDirty(generated);
}
private void TryGenerateSpecialSkill(equipmentSO generated)
{
if (generated == null || generatedSpecialEffects.Count == 0)
{
generated.sa_skillID = 0;
return;
}
if (UnityEngine.Random.value > randomConfig.sesp)
{
generated.sa_skillID = 0;
return;
}
if (!randomConfig.TryGetSpecialSkillId(generated.skillType, out int skillId) || skillId <= 0)
{
generated.sa_skillID = 0;
return;
}
int replaceIndex = UnityEngine.Random.Range(0, generatedSpecialEffects.Count);
generatedSpecialEffects.RemoveAt(replaceIndex);
generatedSpecialEffects.Add(new GeneratedEffectValue
{
effectType = equipmentSO.EquipmentSpecialEffectType.Skill,
displayName = "Skill",
value = 0f,
displayIcon = null,
skillId = skillId
});
generated.sa_skillID = skillId;
}
private List<equipmentSO.EquipmentSpecialEffectType> BuildSpecialEffectPool(
HashSet<equipmentSO.EquipmentSpecialEffectType> selectedBasicTypes,
bool alignToSelectedBasicTypes)
{
var pool = new List<equipmentSO.EquipmentSpecialEffectType>();
if (alignToSelectedBasicTypes && selectedBasicTypes != null && selectedBasicTypes.Count > 0)
{
foreach (equipmentSO.EquipmentSpecialEffectType effectType in selectedBasicTypes)
{
if (!TryMapToSpecialRange(effectType, out equipmentRandomConfigSO.RandomSpecialEffectType rangeType))
{
continue;
}
if (randomConfig.TryGetSpecialRange(rangeType, out _, out _))
{
pool.Add(effectType);
}
}
return pool;
}
equipmentSO.EquipmentSpecialEffectType[] allTypes =
{
equipmentSO.EquipmentSpecialEffectType.MaxHp,
equipmentSO.EquipmentSpecialEffectType.Attack,
equipmentSO.EquipmentSpecialEffectType.MaxMana,
equipmentSO.EquipmentSpecialEffectType.DamageResistance,
equipmentSO.EquipmentSpecialEffectType.ScoreEfficiency
};
for (int i = 0; i < allTypes.Length; i++)
{
if (!TryMapToSpecialRange(allTypes[i], out equipmentRandomConfigSO.RandomSpecialEffectType rangeType))
{
continue;
}
if (randomConfig.TryGetSpecialRange(rangeType, out _, out _))
{
pool.Add(allTypes[i]);
}
}
return pool;
}
private void GenerateIllusionEffects(equipmentSO generated)
{
if (generated == null || generated.illusionEffects == null || generated.illusionEffects.Length == 0)
{
return;
}
generated.ia_skillID = 0;
int effectCount = Mathf.Min(RollSpecialEffectCount(), generated.illusionEffects.Length);
List<equipmentSO.EquipmentSpecialEffect> skillPool = new List<equipmentSO.EquipmentSpecialEffect>();
List<equipmentSO.EquipmentSpecialEffect> valuePool = new List<equipmentSO.EquipmentSpecialEffect>();
for (int i = 0; i < generated.illusionEffects.Length; i++)
{
equipmentSO.EquipmentSpecialEffect effect = generated.illusionEffects[i];
if (effect == null)
{
continue;
}
if (effect.effectType == equipmentSO.EquipmentSpecialEffectType.Skill)
{
skillPool.Add(effect);
}
else if (TryMapToIllusionRange(effect.effectType, out _))
{
valuePool.Add(effect);
}
}
for (int slotIndex = 0; slotIndex < effectCount; slotIndex++)
{
bool shouldGenerateSkill = skillPool.Count > 0 && UnityEngine.Random.value <= GetIllusionSkillChance(slotIndex);
if (shouldGenerateSkill)
{
if (!randomConfig.TryGetIllusionSkillId(out int illusionSkillId) || illusionSkillId <= 0)
{
shouldGenerateSkill = false;
}
else
{
int pickSkillIndex = UnityEngine.Random.Range(0, skillPool.Count);
equipmentSO.EquipmentSpecialEffect skillEffect = skillPool[pickSkillIndex];
skillPool.RemoveAt(pickSkillIndex);
generatedIllusionEffects.Add(new GeneratedEffectValue
{
effectType = skillEffect.effectType,
displayName = "Skill",
value = 0f,
displayIcon = null,
skillId = illusionSkillId
});
generated.ia_skillID = illusionSkillId;
continue;
}
}
if (valuePool.Count == 0)
{
break;
}
int pickValueIndex = UnityEngine.Random.Range(0, valuePool.Count);
equipmentSO.EquipmentSpecialEffect effect = valuePool[pickValueIndex];
valuePool.RemoveAt(pickValueIndex);
if (!TryMapToIllusionRange(effect.effectType, out equipmentRandomConfigSO.RandomIllusionEffectType rangeType))
{
slotIndex--;
continue;
}
if (!randomConfig.TryGetIllusionRange(rangeType, out float minValue, out float maxValue))
{
slotIndex--;
continue;
}
generatedIllusionEffects.Add(new GeneratedEffectValue
{
effectType = effect.effectType,
displayName = effect.effectType.ToString(),
value = RollBiasedValue(minValue, maxValue),
displayIcon = null,
skillId = 0
});
}
generated.illusionEffects = BuildGeneratedEffectArray(generatedIllusionEffects);
MarkEquipmentDirty(generated);
}
private int RollSpecialEffectCount()
{
float roll = UnityEngine.Random.value;
if (roll <= randomConfig.se01p)
{
return 1;
}
if (roll <= randomConfig.se01p + randomConfig.se02p)
{
return 2;
}
return 3;
}
private float GetIllusionSkillChance(int index)
{
switch (index)
{
case 0: return randomConfig.ies01;
case 1: return randomConfig.ies02;
case 2: return randomConfig.ies03;
case 3: return randomConfig.ies04;
default: return 0f;
}
}
private static bool TryMapToSpecialRange(
equipmentSO.EquipmentSpecialEffectType effectType,
out equipmentRandomConfigSO.RandomSpecialEffectType rangeType)
{
switch (effectType)
{
case equipmentSO.EquipmentSpecialEffectType.MaxHp:
rangeType = equipmentRandomConfigSO.RandomSpecialEffectType.MaxHp;
return true;
case equipmentSO.EquipmentSpecialEffectType.Attack:
rangeType = equipmentRandomConfigSO.RandomSpecialEffectType.Attack;
return true;
case equipmentSO.EquipmentSpecialEffectType.MaxMana:
rangeType = equipmentRandomConfigSO.RandomSpecialEffectType.MaxMana;
return true;
case equipmentSO.EquipmentSpecialEffectType.DamageResistance:
rangeType = equipmentRandomConfigSO.RandomSpecialEffectType.DamageResistance;
return true;
case equipmentSO.EquipmentSpecialEffectType.ScoreEfficiency:
rangeType = equipmentRandomConfigSO.RandomSpecialEffectType.ScoreEfficiency;
return true;
default:
rangeType = default;
return false;
}
}
private static bool TryMapToIllusionRange(
equipmentSO.EquipmentSpecialEffectType effectType,
out equipmentRandomConfigSO.RandomIllusionEffectType rangeType)
{
switch (effectType)
{
case equipmentSO.EquipmentSpecialEffectType.MaxHp:
rangeType = equipmentRandomConfigSO.RandomIllusionEffectType.MaxHp;
return true;
case equipmentSO.EquipmentSpecialEffectType.Attack:
rangeType = equipmentRandomConfigSO.RandomIllusionEffectType.Attack;
return true;
case equipmentSO.EquipmentSpecialEffectType.MaxMana:
rangeType = equipmentRandomConfigSO.RandomIllusionEffectType.MaxMana;
return true;
case equipmentSO.EquipmentSpecialEffectType.DamageResistance:
rangeType = equipmentRandomConfigSO.RandomIllusionEffectType.DamageResistance;
return true;
case equipmentSO.EquipmentSpecialEffectType.ScoreEfficiency:
rangeType = equipmentRandomConfigSO.RandomIllusionEffectType.ScoreEfficiency;
return true;
case equipmentSO.EquipmentSpecialEffectType.HitManaRecovery:
rangeType = equipmentRandomConfigSO.RandomIllusionEffectType.HitManaRecovery;
return true;
case equipmentSO.EquipmentSpecialEffectType.HitDamageMultiplier:
rangeType = equipmentRandomConfigSO.RandomIllusionEffectType.HitDamageMultiplier;
return true;
case equipmentSO.EquipmentSpecialEffectType.HpLoseBase:
rangeType = equipmentRandomConfigSO.RandomIllusionEffectType.HpLoseBase;
return true;
default:
rangeType = default;
return false;
}
}
private void BuildSummary(equipmentSO generated)
{
StringBuilder builder = new StringBuilder();
builder.AppendLine("Basic Attributes:");
for (int i = 0; i < generatedBasicAttributes.Count; i++)
{
builder.AppendLine($"- {generatedBasicAttributes[i].statName}: {generatedBasicAttributes[i].value:0.####}");
}
builder.AppendLine("Special Effects:");
for (int i = 0; i < generatedSpecialEffects.Count; i++)
{
GeneratedEffectValue effect = generatedSpecialEffects[i];
if (effect.effectType == equipmentSO.EquipmentSpecialEffectType.Skill)
{
builder.AppendLine($"- Skill: {effect.skillId}");
}
else
{
builder.AppendLine($"- {effect.effectType}: {effect.value:0.####}");
}
}
builder.AppendLine("Type Same Effects:");
for (int i = 0; i < generatedTypeSameEffects.Count; i++)
{
GeneratedEffectValue effect = generatedTypeSameEffects[i];
builder.AppendLine($"- {effect.effectType}: {effect.value:0.####}");
}
builder.AppendLine("Illusion Effects:");
for (int i = 0; i < generatedIllusionEffects.Count; i++)
{
GeneratedEffectValue effect = generatedIllusionEffects[i];
if (effect.effectType == equipmentSO.EquipmentSpecialEffectType.Skill)
{
builder.AppendLine($"- Skill");
}
else
{
builder.AppendLine($"- {effect.effectType}: {effect.value:0.####}");
}
}
if (generated != null && generated.sa_skillID > 0)
{
builder.AppendLine($"sa_skillID: {generated.sa_skillID}");
}
if (generatedBasicAttributes.Count == 0 && generatedTypeSameEffects.Count == 0 && generatedSpecialEffects.Count == 0 && generatedIllusionEffects.Count == 0)
{
builder.AppendLine();
builder.AppendLine("No values generated.");
builder.AppendLine($"randomBasicAttributeCount={randomConfig.randomBasicAttributeCount}");
builder.AppendLine($"basicAttributeRangesDefined={(randomConfig.basicAttributeRanges == null ? 0 : randomConfig.basicAttributeRanges.Count)}");
builder.AppendLine($"specialEffectsDefined={(sourceEquipment.specialEffects == null ? 0 : sourceEquipment.specialEffects.Length)}");
builder.AppendLine($"illusionEffectsDefined={(sourceEquipment.illusionEffects == null ? 0 : sourceEquipment.illusionEffects.Length)}");
}
lastGenerationSummary = builder.ToString().TrimEnd();
Debug.Log("[equipmentRandomTestButton] Generated equipment preview:\n" + lastGenerationSummary, this);
}
private void ResetBasicGains(equipmentSO targetEquipment)
{
if (targetEquipment == null)
{
return;
}
if (targetEquipment.maxHp != null) targetEquipment.maxHp.basicGain = 0f;
if (targetEquipment.attack != null) targetEquipment.attack.basicGain = 0f;
if (targetEquipment.maxMana != null) targetEquipment.maxMana.basicGain = 0f;
if (targetEquipment.damageResistance != null) targetEquipment.damageResistance.basicGain = 0f;
if (targetEquipment.scoreEfficiency != null) targetEquipment.scoreEfficiency.basicGain = 0f;
}
private void MarkEquipmentDirty(equipmentSO targetEquipment)
{
#if UNITY_EDITOR
if (!Application.isPlaying && targetEquipment != null)
{
EditorUtility.SetDirty(targetEquipment);
AssetDatabase.SaveAssets();
}
#endif
}
private equipmentSO PersistGeneratedEquipment(equipmentSO generated)
{
if (generated == null)
{
return null;
}
#if UNITY_EDITOR
if (!Application.isPlaying && saveGeneratedAssetInEditor)
{
EnsureEditorOutputFolderExists();
string assetPath = AssetDatabase.GenerateUniqueAssetPath($"{EditorOutputFolder}/{generated.name}.asset");
AssetDatabase.CreateAsset(generated, assetPath);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
lastGeneratedAssetPath = assetPath;
return AssetDatabase.LoadAssetAtPath<equipmentSO>(assetPath);
}
#endif
return equipmentGenerator.RegisterGeneratedEquipment(generated);
}
private static void WriteGeneratedEffectsBack(
equipmentSO.EquipmentSpecialEffect[] targetEffects,
List<GeneratedEffectValue> generatedEffects)
{
if (targetEffects == null)
{
return;
}
for (int i = 0; i < targetEffects.Length; i++)
{
equipmentSO.EquipmentSpecialEffect target = targetEffects[i];
if (target == null)
{
continue;
}
target.value = 0f;
}
for (int i = 0; i < generatedEffects.Count; i++)
{
GeneratedEffectValue generated = generatedEffects[i];
if (generated.effectType == equipmentSO.EquipmentSpecialEffectType.Skill)
{
continue;
}
for (int j = 0; j < targetEffects.Length; j++)
{
equipmentSO.EquipmentSpecialEffect target = targetEffects[j];
if (target == null)
{
continue;
}
if (target.effectType == generated.effectType)
{
target.value = generated.value;
break;
}
}
}
}
private static equipmentSO.EquipmentSpecialEffect[] BuildGeneratedEffectArray(List<GeneratedEffectValue> generatedEffects)
{
if (generatedEffects == null || generatedEffects.Count == 0)
{
return Array.Empty<equipmentSO.EquipmentSpecialEffect>();
}
var results = new List<equipmentSO.EquipmentSpecialEffect>(generatedEffects.Count);
for (int i = 0; i < generatedEffects.Count; i++)
{
GeneratedEffectValue generated = generatedEffects[i];
results.Add(new equipmentSO.EquipmentSpecialEffect
{
effectType = generated.effectType,
value = generated.effectType == equipmentSO.EquipmentSpecialEffectType.Skill ? 0f : generated.value
});
}
return results.ToArray();
}
private HashSet<equipmentSO.EquipmentSpecialEffectType> GetSelectedBasicAttributeTypes(equipmentSO targetEquipment)
{
var selected = new HashSet<equipmentSO.EquipmentSpecialEffectType>();
if (targetEquipment == null)
{
return selected;
}
if (targetEquipment.maxHp != null && !Mathf.Approximately(targetEquipment.maxHp.basicGain, 0f))
selected.Add(equipmentSO.EquipmentSpecialEffectType.MaxHp);
if (targetEquipment.attack != null && !Mathf.Approximately(targetEquipment.attack.basicGain, 0f))
selected.Add(equipmentSO.EquipmentSpecialEffectType.Attack);
if (targetEquipment.maxMana != null && !Mathf.Approximately(targetEquipment.maxMana.basicGain, 0f))
selected.Add(equipmentSO.EquipmentSpecialEffectType.MaxMana);
if (targetEquipment.damageResistance != null && !Mathf.Approximately(targetEquipment.damageResistance.basicGain, 0f))
selected.Add(equipmentSO.EquipmentSpecialEffectType.DamageResistance);
if (targetEquipment.scoreEfficiency != null && !Mathf.Approximately(targetEquipment.scoreEfficiency.basicGain, 0f))
selected.Add(equipmentSO.EquipmentSpecialEffectType.ScoreEfficiency);
return selected;
}
#if UNITY_EDITOR
private static void EnsureEditorOutputFolderExists()
{
if (AssetDatabase.IsValidFolder(EditorOutputFolder))
{
return;
}
if (!AssetDatabase.IsValidFolder("Assets/Resources"))
{
AssetDatabase.CreateFolder("Assets", "Resources");
}
if (!AssetDatabase.IsValidFolder("Assets/Resources/so"))
{
AssetDatabase.CreateFolder("Assets/Resources", "so");
}
if (!AssetDatabase.IsValidFolder(EditorOutputFolder))
{
AssetDatabase.CreateFolder("Assets/Resources/so", "uEquip");
}
}
#endif
private void MarkHostDirty()
{
#if UNITY_EDITOR
if (!Application.isPlaying)
{
EditorUtility.SetDirty(this);
if (gameObject != null && gameObject.scene.IsValid())
{
EditorSceneManager.MarkSceneDirty(gameObject.scene);
}
InternalEditorUtility.RepaintAllViews();
}
#endif
}
private static float RollBiasedValue(float minValue, float maxValue)
{
if (Mathf.Approximately(minValue, maxValue))
{
return AvoidZero(minValue, maxValue, minValue);
}
if (maxValue < minValue)
{
float cached = minValue;
minValue = maxValue;
maxValue = cached;
}
float span = maxValue - minValue;
float roll = UnityEngine.Random.value;
if (roll <= 0.05f)
{
return AvoidZero(minValue, maxValue, UnityEngine.Random.Range(minValue, minValue + span * 0.1f));
}
if (roll >= 0.95f)
{
return AvoidZero(minValue, maxValue, UnityEngine.Random.Range(maxValue - span * 0.1f, maxValue));
}
float gaussian = SampleClampedGaussian01();
return AvoidZero(minValue, maxValue, Mathf.Lerp(minValue, maxValue, gaussian));
}
private static float SampleClampedGaussian01()
{
float u1 = Mathf.Clamp01(UnityEngine.Random.value);
float u2 = Mathf.Clamp01(UnityEngine.Random.value);
u1 = Mathf.Max(u1, 1e-6f);
float standardNormal = Mathf.Sqrt(-2f * Mathf.Log(u1)) * Mathf.Cos(2f * Mathf.PI * u2);
float centered = 0.5f + standardNormal * 0.18f;
return Mathf.Clamp01(centered);
}
private static void ResolveDuplicateEffects(List<GeneratedEffectValue> effects)
{
if (effects == null || effects.Count <= 1)
{
return;
}
var bestByType = new Dictionary<equipmentSO.EquipmentSpecialEffectType, GeneratedEffectValue>();
for (int i = 0; i < effects.Count; i++)
{
GeneratedEffectValue candidate = effects[i];
if (!bestByType.TryGetValue(candidate.effectType, out GeneratedEffectValue existing))
{
bestByType[candidate.effectType] = candidate;
continue;
}
bestByType[candidate.effectType] = ChoosePreferred(existing, candidate);
}
effects.Clear();
foreach (GeneratedEffectValue value in bestByType.Values)
{
effects.Add(value);
}
}
private static GeneratedEffectValue ChoosePreferred(GeneratedEffectValue left, GeneratedEffectValue right)
{
bool leftNegative = left.value < 0f;
bool rightNegative = right.value < 0f;
if (leftNegative && rightNegative)
{
return left.value <= right.value ? left : right;
}
if (!leftNegative && !rightNegative)
{
return left.value >= right.value ? left : right;
}
return Mathf.Abs(left.value) >= Mathf.Abs(right.value) ? left : right;
}
private static float AvoidZero(float minValue, float maxValue, float value)
{
if (!Mathf.Approximately(value, 0f))
{
return value;
}
if (minValue > 0f || maxValue < 0f)
{
return value;
}
float epsilon = Mathf.Min(0.0001f, Mathf.Max(Mathf.Abs(minValue), Mathf.Abs(maxValue), 0.0001f));
return UnityEngine.Random.value < 0.5f ? -epsilon : epsilon;
}
}