Files
DuckovMods/HitFeedback/Config.cs

285 lines
12 KiB
C#
Raw Normal View History

2025-11-05 21:34:21 +08:00
using System;
using System.Collections.Generic;
2025-11-05 21:34:21 +08:00
using System.Globalization;
2025-11-04 17:05:34 +08:00
using System.IO;
using UnityEngine; // 假设在Unity环境中使用Debug.LogError
namespace HitFeedback
{
public class Config
{
2025-11-04 17:05:34 +08:00
public KeyCode hotKey = KeyCode.F8;
public Dictionary<string, float> probability = new Dictionary<string, float>();
2025-11-04 17:05:34 +08:00
2025-11-05 21:34:21 +08:00
/// <summary>
/// 当伤害具有这些特性之一时,将播放音频反馈。
/// </summary>
public HashSet<DamageFeature> audioDamageFeatures = new HashSet<DamageFeature>();
2025-11-04 17:05:34 +08:00
public void LoadConfig(string filename)
{
if (!File.Exists(filename))
{
Debug.LogError($"Config file not found: {filename}");
2025-11-05 21:34:21 +08:00
return;
2025-11-04 17:05:34 +08:00
}
probability.Clear();
2025-11-05 21:34:21 +08:00
audioDamageFeatures.Clear(); // 清空旧的音频伤害特性数据
2025-11-04 17:05:34 +08:00
try
{
using (var sr = new StreamReader(filename))
{
string line;
2025-11-05 21:34:21 +08:00
var lineNumber = 0;
string currentSection = ""; // 用于解析节
2025-11-04 17:05:34 +08:00
while ((line = sr.ReadLine()) != null)
{
lineNumber++;
2025-11-05 21:34:21 +08:00
line = line.Trim();
2025-11-04 17:05:34 +08:00
// 忽略空行和注释行
if (string.IsNullOrEmpty(line) || line.StartsWith(";") || line.StartsWith("#"))
{
continue;
}
2025-11-05 21:34:21 +08:00
// 处理节标题,例如 [General] 或 [AudioFeatures]
if (line.StartsWith("[") && line.EndsWith("]"))
{
currentSection = line.Substring(1, line.Length - 2).Trim();
continue; // 跳过节标题行
}
2025-11-04 17:05:34 +08:00
// 查找等号
var separatorIndex = line.IndexOf('=');
if (separatorIndex == -1)
{
2025-11-05 21:34:21 +08:00
Debug.LogWarning(
$"Skipping malformed line in config file '{filename}' at line {lineNumber}: No '=' found. Line: '{line}'");
2025-11-04 17:05:34 +08:00
continue;
}
var key = line.Substring(0, separatorIndex).Trim();
var valueStr = line.Substring(separatorIndex + 1).Trim();
2025-11-05 21:34:21 +08:00
if (currentSection.Equals("General", StringComparison.OrdinalIgnoreCase))
{
// 解析 hotKey
if (key.Equals("hotKey", StringComparison.OrdinalIgnoreCase))
{
try
{
hotKey = (KeyCode)Enum.Parse(typeof(KeyCode), valueStr, true);
}
catch (ArgumentException)
{
Debug.LogError(
$"Invalid KeyCode '{valueStr}' in config file '{filename}' at line {lineNumber}. Using default F8.");
hotKey = KeyCode.F8;
}
}
}
else if (currentSection.Equals("Probabilities", StringComparison.OrdinalIgnoreCase))
2025-11-04 17:05:34 +08:00
{
2025-11-05 21:34:21 +08:00
// 解析 probability 字典项
if (float.TryParse(valueStr, NumberStyles.Float, CultureInfo.InvariantCulture,
out var probValue))
2025-11-04 17:05:34 +08:00
{
2025-11-05 21:34:21 +08:00
probability[key] = probValue;
2025-11-04 17:05:34 +08:00
}
2025-11-05 21:34:21 +08:00
else
2025-11-04 17:05:34 +08:00
{
2025-11-05 21:34:21 +08:00
Debug.LogWarning(
$"Invalid float value '{valueStr}' for key '{key}' in config file '{filename}' at line {lineNumber}. Skipping entry.");
2025-11-04 17:05:34 +08:00
}
}
2025-11-05 21:34:21 +08:00
else if (currentSection.Equals("AudioFeatures", StringComparison.OrdinalIgnoreCase))
2025-11-04 17:05:34 +08:00
{
2025-11-05 21:34:21 +08:00
// 解析 audioDamageFeatures 集合项
// 键是 'feature' (或者可以随意定义,只要值是我们关心的)
// 值是 ExtendedDamageFeature 的枚举名称
if (key.Equals("feature", StringComparison.OrdinalIgnoreCase)) // 假设所有特征都用同一个键"feature"
2025-11-04 17:05:34 +08:00
{
2025-11-05 21:34:21 +08:00
foreach (var featureName in valueStr.Split(new char[] { ',', '|' },
StringSplitOptions.RemoveEmptyEntries))
{
try
{
// 确保 ExtendedDamageFeature 是 [Flags] 枚举
var feature = (DamageFeature)Enum.Parse(typeof(DamageFeature),
featureName.Trim(), true);
audioDamageFeatures.Add(feature);
}
catch (ArgumentException)
{
Debug.LogWarning(
$"Invalid ExtendedDamageFeature '{featureName.Trim()}' in config file '{filename}' at line {lineNumber}. Skipping entry.");
}
}
2025-11-04 17:05:34 +08:00
}
else
{
2025-11-05 21:34:21 +08:00
try
{
var feature =
(DamageFeature)Enum.Parse(typeof(DamageFeature), key, true);
if (bool.TryParse(valueStr, out bool includeFeature) && includeFeature)
{
audioDamageFeatures.Add(feature);
}
// 如果是 false则不添加到集合或者可以从集合中移除如果默认是都包含
}
catch (ArgumentException)
{
Debug.LogWarning(
$"Invalid ExtendedDamageFeature key '{key}' in config file '{filename}' at line {lineNumber}. Skipping entry.");
}
2025-11-04 17:05:34 +08:00
}
}
2025-11-05 21:34:21 +08:00
// 如果存在其他节,可以在这里添加 else if 处理
2025-11-04 17:05:34 +08:00
}
}
}
2025-11-05 21:34:21 +08:00
catch (Exception ex)
2025-11-04 17:05:34 +08:00
{
Debug.LogError($"Error reading config file '{filename}': {ex.Message}");
}
}
2025-11-05 21:34:21 +08:00
2025-11-04 17:05:34 +08:00
/// <summary>
/// 将当前配置存储到指定INI文件。
/// </summary>
/// <param name="filename">要保存的INI文件的路径。</param>
public void SaveConfig(string filename)
{
try
{
var directory = Path.GetDirectoryName(filename);
if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
}
2025-11-05 21:34:21 +08:00
2025-11-04 17:05:34 +08:00
using (var sw = new StreamWriter(filename))
{
sw.WriteLine("; HitFeedback Configuration File");
sw.WriteLine("; Generated by HitFeedback.Config class");
2025-11-05 21:34:21 +08:00
sw.WriteLine();
2025-11-04 17:05:34 +08:00
sw.WriteLine("[General]");
sw.WriteLine($"hotKey = {hotKey.ToString()}");
sw.WriteLine();
if (probability.Count > 0)
{
sw.WriteLine("[Probabilities]");
foreach (var kvp in probability)
{
2025-11-05 21:34:21 +08:00
sw.WriteLine($"{kvp.Key} = {kvp.Value.ToString(CultureInfo.InvariantCulture)}");
2025-11-04 17:05:34 +08:00
}
}
else
{
sw.WriteLine("; No probabilities currently configured.");
}
2025-11-05 21:34:21 +08:00
sw.WriteLine();
if (audioDamageFeatures.Count > 0)
{
sw.WriteLine("[AudioFeatures]");
// 假设每个特性一行,值为 true
foreach (var feature in audioDamageFeatures)
{
sw.WriteLine($"{feature.ToString()} = True");
}
// 或者如果你想用一个键存储所有特性(用逗号或竖线分隔)
// sw.WriteLine($"features = {string.Join(",", audioDamageFeatures.Select(f => f.ToString()))}");
}
else
{
sw.WriteLine("; No audio damage features currently configured.");
}
2025-11-04 17:05:34 +08:00
sw.WriteLine();
}
2025-11-05 21:34:21 +08:00
2025-11-04 17:05:34 +08:00
Debug.Log($"Config saved to: {filename}");
}
2025-11-05 21:34:21 +08:00
catch (Exception ex)
2025-11-04 17:05:34 +08:00
{
Debug.LogError($"Error saving config file '{filename}': {ex.Message}");
}
}
2025-11-05 21:34:21 +08:00
/// <summary>
/// 根据DamageInfo的特性判断是否应该播放音频反馈。
/// 如果DamageInfo的任何一个特性在audioDamageFeatures集合中则返回true。
/// </summary>
/// <param name="damageInfo">要检查的DamageInfo对象。</param>
/// <returns>如果应该播放音频反馈则为true否则为false。</returns>
public bool ShouldPlayAudioFeedback(DamageInfo damageInfo)
{
if (audioDamageFeatures.Count == 0)
{
return false;
}
// 将DamageInfo的各种布尔属性/条件转换为DamageFeature组合
DamageFeature currentDamageFeatures = DamageFeature.Undefined;
if (damageInfo.damageType == DamageTypes.normal)
{
currentDamageFeatures |= DamageFeature.NormalDamage;
}
else if (damageInfo.damageType == DamageTypes.realDamage)
{
currentDamageFeatures |= DamageFeature.RealDamage;
}
if (damageInfo.isFromBuffOrEffect)
{
currentDamageFeatures |= DamageFeature.BuffOrEffectDamage;
}
if (damageInfo.ignoreArmor)
{
currentDamageFeatures |= DamageFeature.ArmorIgnoringDamage;
}
if (damageInfo.crit > 0) // crit > 0 表示是暴击
{
currentDamageFeatures |= DamageFeature.CriticalDamage;
}
if (damageInfo.armorPiercing > 0)
{
currentDamageFeatures |= DamageFeature.ArmorPiercingDamage;
}
if (damageInfo.isExplosion)
{
currentDamageFeatures |= DamageFeature.ExplosionDamage;
}
if (damageInfo.armorBreak > 0)
{
currentDamageFeatures |= DamageFeature.ArmorBreakingDamage;
}
if (damageInfo.elementFactors != null && damageInfo.elementFactors.Count > 0)
{
currentDamageFeatures |= DamageFeature.ElementalDamage;
}
if (damageInfo.buffChance > 0 || damageInfo.buff != null)
{
currentDamageFeatures |= DamageFeature.OnHitBuffApply;
}
if (damageInfo.bleedChance > 0)
{
currentDamageFeatures |= DamageFeature.OnHitBleed;
}
foreach (var configuredFeature in audioDamageFeatures)
{
if (configuredFeature == DamageFeature.Undefined)
{
continue;
}
if ((currentDamageFeatures & configuredFeature) == configuredFeature)
{
return true;
}
}
return false;
}
}
2025-11-04 17:05:34 +08:00
}