Files
Cielonos/Assets/Scripts/MainGame/Items/Data/InputData.cs

164 lines
5.3 KiB
C#
Raw Normal View History

2026-07-18 03:16:20 -04:00
using System;
using System.Collections.Generic;
using System.Text;
using Cielonos.MainGame.Characters;
using Sirenix.OdinInspector;
using UnityEngine;
namespace Cielonos.MainGame.Inventory
{
public enum PlayerEquipmentInputType
{
MainWeaponPrimary,
MainWeaponSecondary,
MainWeaponSpecialA,
MainWeaponSpecialB,
MainWeaponSpecialC,
SupportEquipment0,
SupportEquipment1,
SupportEquipment2,
SupportEquipment3
}
public readonly struct PlayerEquipmentInputContext
{
public readonly PlayerEquipmentInputType inputType;
public readonly List<PlayerInputModifierType> modifiers;
public readonly int supportSlotIndex;
public PlayerEquipmentInputContext(PlayerEquipmentInputType inputType, List<PlayerInputModifierType> modifiers, int supportSlotIndex = -1)
{
this.inputType = inputType;
this.modifiers = modifiers;
this.supportSlotIndex = supportSlotIndex;
}
}
[Serializable]
public class EquipmentInputRule
{
public string name;
[HorizontalGroup("Rule", Width = 0.4f)]
[HideLabel]
public PlayerEquipmentInputType inputType;
[HorizontalGroup("Rule", Width = 0.2f)]
[LabelText("Preinput")]
public bool registerPreinput = true;
[HorizontalGroup("Rule", Width = 0.2f)]
[LabelText("Priority")]
[EnableIf(nameof(registerPreinput))]
public int preinputPriority;
[LabelText("Modifier Conditions")]
[ListDrawerSettings(ShowFoldout = true, DraggableItems = true, AddCopiesLastElement = true)]
public List<InputModifierCondition> modifierConditions = new();
public bool Matches(PlayerEquipmentInputContext context)
{
if (inputType != context.inputType) return false;
foreach (InputModifierCondition condition in modifierConditions)
{
if (condition == null) continue;
if (!condition.Matches(context.modifiers)) return false;
}
return true;
}
public int Specificity
{
get
{
HashSet<PlayerInputModifierType> modifierTypes = new();
foreach (InputModifierCondition condition in modifierConditions)
{
if (condition == null) continue;
modifierTypes.Add(condition.modifierType);
}
return modifierTypes.Count;
}
}
}
[CreateAssetMenu(fileName = "InputData", menuName = "Cielonos/Items/Input Data")]
public class InputData : ScriptableObject
{
[InfoBox("$HighPriorityWarningMessage", InfoMessageType.Warning, nameof(HasRuleAboveDashDodgePriority))]
[ListDrawerSettings(ShowFoldout = true, DraggableItems = true,
AddCopiesLastElement = true, ListElementLabelName = "name")]
public List<EquipmentInputRule> rules = new();
public bool TryGetPreinputPriority(PlayerEquipmentInputContext context, out int priority)
{
EquipmentInputRule bestRule = null;
int bestSpecificity = -1;
foreach (EquipmentInputRule rule in rules)
{
if (rule == null || !rule.Matches(context)) continue;
int specificity = rule.Specificity;
if (specificity >= bestSpecificity)
{
bestRule = rule;
bestSpecificity = specificity;
}
}
if (bestRule is not { registerPreinput: true })
{
priority = 0;
return false;
}
priority = bestRule.preinputPriority;
return true;
}
private bool HasRuleAboveDashDodgePriority()
{
if (rules == null) return false;
foreach (EquipmentInputRule rule in rules)
{
if (rule is not { registerPreinput: true }) continue;
if (rule.preinputPriority > PlayerInputSubcontroller.PlayerPreinputSubmodule.DashDodgePreinputPriority) return true;
}
return false;
}
private string HighPriorityWarningMessage
{
get
{
StringBuilder builder = new("以下 Input Rule 的优先级高于 Dash/Dodge (100)");
bool hasRule = false;
if (rules != null)
{
foreach (EquipmentInputRule rule in rules)
{
if (rule is not { registerPreinput: true }) continue;
if (rule.preinputPriority <= PlayerInputSubcontroller.PlayerPreinputSubmodule.DashDodgePreinputPriority) continue;
if (hasRule) builder.Append("、");
builder.Append(string.IsNullOrWhiteSpace(rule.name) ? rule.inputType.ToString() : rule.name);
hasRule = true;
}
}
if (!hasRule) return string.Empty;
builder.Append("。请确认这些输入确实应该高于 Dash/Dodge。");
return builder.ToString();
}
}
}
}