164 lines
5.3 KiB
C#
164 lines
5.3 KiB
C#
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();
|
||
}
|
||
}
|
||
}
|
||
}
|