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 modifiers; public readonly int supportSlotIndex; public PlayerEquipmentInputContext(PlayerEquipmentInputType inputType, List 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 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 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 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(); } } } }