115 lines
4.0 KiB
C#
115 lines
4.0 KiB
C#
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using Cielonos.MainGame.Characters;
|
|
using Cielonos.MainGame.UI;
|
|
using Sirenix.OdinInspector;
|
|
using SLSUtilities.General;
|
|
using UnityEngine;
|
|
|
|
namespace Cielonos.MainGame.Inventory
|
|
{
|
|
public class FunctionSubmodule : SubmoduleBase<ItemBase>
|
|
{
|
|
[ReadOnly]
|
|
public Dictionary<string, RuntimeFunctionUnit> functionUnits;
|
|
|
|
public RuntimeFunctionUnit mainFunction => functionUnits.Count > 0 ? functionUnits.Values.First() : null;
|
|
|
|
public RuntimeFunctionUnit this[string functionName] => functionUnits.ContainsKey(functionName) ? functionUnits[functionName] : null;
|
|
|
|
public FunctionSubmodule(ItemBase owner, FunctionData data) : base(owner)
|
|
{
|
|
functionUnits = new Dictionary<string, RuntimeFunctionUnit>();
|
|
foreach (var unit in data.functionUnitList)
|
|
{
|
|
functionUnits[unit.unitName] = new RuntimeFunctionUnit(this, unit);
|
|
}
|
|
}
|
|
|
|
public void Update(float deltaTime)
|
|
{
|
|
foreach (var unit in functionUnits.Values)
|
|
{
|
|
unit.Update(deltaTime);
|
|
}
|
|
}
|
|
}
|
|
|
|
public class RuntimeFunctionUnit : SubmoduleBase<FunctionSubmodule>
|
|
{
|
|
private CharacterBase character => owner.owner.player;
|
|
|
|
public FunctionData.FunctionUnit data;
|
|
public float currentCooldown;
|
|
public float maxCooldown;
|
|
|
|
public RuntimeFunctionUnit(FunctionSubmodule owner, FunctionData.FunctionUnit data) : base(owner)
|
|
{
|
|
this.data = data;
|
|
maxCooldown = data.cooldown;
|
|
currentCooldown = 0f;
|
|
}
|
|
|
|
public void Update(float deltaTime)
|
|
{
|
|
currentCooldown -= deltaTime;
|
|
currentCooldown = Mathf.Max(currentCooldown, 0f);
|
|
}
|
|
|
|
public bool IsAvailable()
|
|
{
|
|
bool cooldownAvailable = currentCooldown <= 0f;
|
|
bool energyAvailable = character.attributeSm[CharacterAttribute.Energy] >= GetEffectiveEnergyCost();
|
|
bool available = cooldownAvailable && energyAvailable;
|
|
|
|
if (!available)
|
|
{
|
|
if(character is Player && owner.owner is MainWeaponBase)
|
|
{
|
|
if (data.shownInUI || data.isMain)
|
|
{
|
|
PlayerCanvas.MainWeaponUIArea.functionIconDict[data.unitName].SetFrameOutline(0.25f, Color.red);
|
|
}
|
|
}
|
|
}
|
|
return available;
|
|
}
|
|
|
|
public RuntimeFunctionUnit Execute()
|
|
{
|
|
ResetCooldown();
|
|
ConsumeEnergy();
|
|
if(character is Player && owner.owner is MainWeaponBase)
|
|
{
|
|
if (data.shownInUI || data.isMain)
|
|
{
|
|
PlayerCanvas.MainWeaponUIArea.functionIconDict[data.unitName].SetFrameOutline(0.25f);
|
|
}
|
|
}
|
|
return this;
|
|
}
|
|
|
|
private const float MaxCooldownReduction = 0.9f;
|
|
private const float MaxEnergyCostReduction = 0.9f;
|
|
|
|
/// <summary> 计算应用 EnergyCostReduction 后的实际能量消耗。 </summary>
|
|
private float GetEffectiveEnergyCost()
|
|
{
|
|
float energyCostReduction = Mathf.Clamp(character.attributeSm[CharacterAttribute.EnergyCostReduction], 0f, MaxEnergyCostReduction);
|
|
return data.energyCost * (1f - energyCostReduction);
|
|
}
|
|
|
|
private void ResetCooldown()
|
|
{
|
|
float cooldownReduction = Mathf.Clamp(character.attributeSm[CharacterAttribute.CooldownReduction], 0f, MaxCooldownReduction);
|
|
currentCooldown = maxCooldown * (1f - cooldownReduction);
|
|
}
|
|
|
|
private void ConsumeEnergy()
|
|
{
|
|
float cost = GetEffectiveEnergyCost();
|
|
character.attributeSm[CharacterAttribute.Energy] -= cost;
|
|
// onEnergyChanged 已由 AttributeSubmodule 值变更回调自动触发
|
|
}
|
|
}
|
|
} |