UI调整
This commit is contained in:
@@ -1,62 +1,88 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using Cielonos.MainGame.Characters;
|
||||
using Sirenix.OdinInspector;
|
||||
using SLSUtilities.General;
|
||||
using SoftCircuits.Collections;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
namespace Cielonos.MainGame.Inventory
|
||||
{
|
||||
[CreateAssetMenu(fileName = "FunctionData", menuName = "Cielonos/Items/FunctionData")]
|
||||
public partial class FunctionData : SerializedScriptableObject
|
||||
{
|
||||
[DictionaryDrawerSettings(KeyLabel = "Function Unit", DisplayMode = DictionaryDisplayOptions.ExpandedFoldout)]
|
||||
[ListDrawerSettings(ShowIndexLabels = false, ListElementLabelName = "unitName", CustomAddFunction = "AddFunctionUnit")]
|
||||
[Searchable]
|
||||
public Dictionary<string, FunctionUnit> functionUnits = new Dictionary<string, FunctionUnit>();
|
||||
public List<FunctionUnit> functionUnitList = new List<FunctionUnit>();
|
||||
|
||||
[OnInspectorGUI("UpdateUnits")]
|
||||
public void UpdateUnits()
|
||||
{
|
||||
foreach (var unit in functionUnits.Values)
|
||||
foreach (var unit in functionUnitList)
|
||||
{
|
||||
unit.parentData = this;
|
||||
}
|
||||
}
|
||||
|
||||
private FunctionUnit AddFunctionUnit()
|
||||
{
|
||||
FunctionUnit newUnit = new FunctionUnit
|
||||
{
|
||||
unitName = $"Function {functionUnitList.Count + 1}",
|
||||
parentData = this
|
||||
};
|
||||
return newUnit;
|
||||
}
|
||||
}
|
||||
|
||||
public partial class FunctionData
|
||||
{
|
||||
public enum IntervalReductionType
|
||||
public enum CooldownReductionType
|
||||
{
|
||||
None = 0,
|
||||
Cooldown = 1,
|
||||
AttackSpeed = 10
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class FunctionUnit
|
||||
{
|
||||
[ReadOnly]
|
||||
public FunctionData parentData;
|
||||
|
||||
|
||||
[TitleGroup("Information")]
|
||||
public string unitName;
|
||||
[TitleGroup("Information")]
|
||||
public bool shownInUI;
|
||||
[TitleGroup("Information")]
|
||||
[HideIf("shownInUI")]
|
||||
public bool isMain;
|
||||
[TitleGroup("Information")]
|
||||
[ShowIf("@shownInUI || isMain")]
|
||||
public Sprite icon;
|
||||
[TitleGroup("Information")]
|
||||
public List<string> operation;
|
||||
public List<string> operation = new List<string>();
|
||||
[TitleGroup("Information")]
|
||||
[ValueDropdown("Tags")]
|
||||
public List<string> tags = new List<string>();
|
||||
|
||||
[TitleGroup("Costs")]
|
||||
public float energyCost;
|
||||
[TitleGroup("Costs")]
|
||||
public int ammoCost;
|
||||
|
||||
[TitleGroup("Interval")]
|
||||
public float interval;
|
||||
[TitleGroup("Interval")]
|
||||
public float intervalLowerLimit;
|
||||
[TitleGroup("Interval")]
|
||||
public IntervalReductionType intervalReductionType;
|
||||
[FormerlySerializedAs("interval")] [TitleGroup("Cooldown")]
|
||||
public float cooldown;
|
||||
[FormerlySerializedAs("intervalLowerLimit")] [TitleGroup("Cooldown")]
|
||||
public float cooldownLowerLimit;
|
||||
[FormerlySerializedAs("intervalReductionType")] [TitleGroup("Cooldown")]
|
||||
public CooldownReductionType cooldownReductionType;
|
||||
|
||||
public static List<string> Tags = new()
|
||||
{
|
||||
"Disruption"
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
8
Assets/Scripts/MainGame/Items/Extenders/Polychrome.meta
Normal file
8
Assets/Scripts/MainGame/Items/Extenders/Polychrome.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f9eeb85c7bb082046b999e5e098bca4e
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,13 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Cielonos.MainGame.Inventory.Collections
|
||||
{
|
||||
/// <summary>
|
||||
/// 光子解离器 / Photon Dissociator
|
||||
/// Polychrome的扩展器,重攻击拆分为3段,每段伤害为原来的50%。
|
||||
/// </summary>
|
||||
public class PhotonDissociator : ExtenderBase
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dfcb853ac3666fc45a65e43107958eaf
|
||||
@@ -0,0 +1,13 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Cielonos.MainGame.Inventory.Collections
|
||||
{
|
||||
/// <summary>
|
||||
/// 光子偏振器 / Photon Polarizer
|
||||
/// Polychrome的扩展器,可以使完美格挡弹开敌人,阻止敌人的连招
|
||||
/// </summary>
|
||||
public class PhotonPolarizer : ExtenderBase
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b6b2bf502e7cd5c4ca858a7492f332a9
|
||||
@@ -20,7 +20,7 @@ namespace Cielonos.MainGame.Inventory.Collections
|
||||
RegisterFunctionsToAnimSc();
|
||||
if(!player.inputSc.IsMoving) PlayTargetedAnimation("Equip");
|
||||
viewObjects["Wand"].SetFadeAnim(0.5f);
|
||||
PlayerCanvas.MainWeaponUIArea.displayer.SetFrameOutline(1);
|
||||
//PlayerCanvas.MainWeaponUIArea.displayer.SetFrameOutline(1);
|
||||
}
|
||||
|
||||
public override void OnPrimaryPress()
|
||||
|
||||
@@ -4,6 +4,7 @@ using Cielonos.MainGame.Buffs.Character;
|
||||
using Cielonos.MainGame.Characters;
|
||||
using Cielonos.MainGame.Effects.Feedback;
|
||||
using Cielonos.MainGame.UI;
|
||||
using SLSUtilities.Feedback;
|
||||
using SLSUtilities.General;
|
||||
using SLSUtilities.FunctionalAnimation;
|
||||
using SLSUtilities.WwiseAssistance;
|
||||
@@ -51,8 +52,6 @@ namespace Cielonos.MainGame.Inventory.Collections
|
||||
viewObjects["Katana"].SetFadeAnim(0.2f);
|
||||
viewObjects["Saya"].SetFadeAnim(0.2f);
|
||||
|
||||
PlayerCanvas.MainWeaponUIArea.displayer.SetFrameOutline(0.4f);
|
||||
|
||||
PlayTargetedAnimation("EquipBlock");
|
||||
SetBlock(equipBlockData);
|
||||
player.selfTimeSm.AddLocalTimer(0.4f, () =>
|
||||
@@ -105,7 +104,7 @@ namespace Cielonos.MainGame.Inventory.Collections
|
||||
return;
|
||||
}
|
||||
|
||||
if (player.inputSc.IsHoldingSpecialA && functionSm["LightAttack"].IsAvailable())
|
||||
/*if (player.inputSc.IsHoldingSpecialA && functionSm["LightAttack"].IsAvailable())
|
||||
{
|
||||
CharacterBase target = CombatManager.EnemySm.GetBestEnemy(5);
|
||||
if (PlayTargetedAnimation("AttackRC", target, 1f, true))
|
||||
@@ -114,7 +113,7 @@ namespace Cielonos.MainGame.Inventory.Collections
|
||||
functionSm["LightAttack"].Execute();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}*/
|
||||
|
||||
if (player.landMovementSc.isSprinting && functionSm["LightAttack"].IsAvailable() && fullBodyFuncAnimSm.CheckPlayability())
|
||||
{
|
||||
@@ -153,30 +152,48 @@ namespace Cielonos.MainGame.Inventory.Collections
|
||||
}
|
||||
|
||||
List<Enemy> availableEnemies = CombatManager.EnemySm.GetEnemiesInRadius(player.transform.position, 4);
|
||||
|
||||
//完美格挡+反击
|
||||
if (player.reactionSc.blockSm.afterPerfectBlockTimer > 0)
|
||||
BlockSubmodule blockSm = player.reactionSc.blockSm;
|
||||
if (!blockSm.afterPerfectBlockTimer.isCompleted)
|
||||
{
|
||||
Enemy target = CombatManager.EnemySm.GetBestEnemy(availableEnemies);
|
||||
if (PlayTargetedAnimation("BlockParryAttack", target))
|
||||
Enemy blockedTarget = blockSm.perfectBlockedTarget as Enemy;
|
||||
bool successPlayed;
|
||||
if (blockedTarget != null && !availableEnemies.Contains(blockedTarget))
|
||||
{
|
||||
player.reactionSc.blockSm.afterPerfectBlockTimer = 0;
|
||||
RemoveBlock();
|
||||
Debug.Log(blockedTarget.name);
|
||||
float distance = Vector3.Distance(player.transform.position.Flatten(), blockedTarget.transform.position.Flatten());
|
||||
successPlayed = PlayTargetedAnimation(distance > 2f ? "DodgeParryAttack" : "BlockParryAttack", blockedTarget);
|
||||
}
|
||||
else
|
||||
{
|
||||
successPlayed = PlayTargetedAnimation("BlockParryAttack");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//完美闪避+反击
|
||||
if (player.reactionSc.dodgeSm.afterPerfectDodgeTimer > 0)
|
||||
{
|
||||
CharacterBase target = CombatManager.EnemySm.GetBestEnemy(12);
|
||||
if (PlayTargetedAnimation("DodgeParryAttack", target))
|
||||
if(successPlayed)
|
||||
{
|
||||
player.reactionSc.dodgeSm.afterPerfectDodgeTimer = 0;
|
||||
blockSm.afterPerfectBlockTimer.Complete();
|
||||
RemoveBlock();
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
DodgeSubmodule dodgeSm = player.reactionSc.dodgeSm;
|
||||
if (!dodgeSm.afterPerfectDodgeTimer.isCompleted)
|
||||
{
|
||||
Enemy dodgedTarget = dodgeSm.perfectDodgedTarget as Enemy;
|
||||
bool successPlayed;
|
||||
if (dodgedTarget != null && !availableEnemies.Contains(dodgedTarget))
|
||||
{
|
||||
float distance = Vector3.Distance(player.transform.position.Flatten(), dodgedTarget.transform.position.Flatten());
|
||||
successPlayed = PlayTargetedAnimation(distance > 2f ? "DodgeParryAttack" : "BlockParryAttack", dodgedTarget);
|
||||
}
|
||||
else
|
||||
{
|
||||
successPlayed = PlayTargetedAnimation("BlockParryAttack");
|
||||
}
|
||||
|
||||
if(successPlayed)
|
||||
{
|
||||
dodgeSm.afterPerfectDodgeTimer.Complete();
|
||||
}
|
||||
}
|
||||
|
||||
if (player.reactionSc.blockSm.HaveBlockSource(blockData.blockName))
|
||||
@@ -202,46 +219,49 @@ namespace Cielonos.MainGame.Inventory.Collections
|
||||
return;
|
||||
}
|
||||
|
||||
if (player.inputSc.IsHoldingSpecialA && functionSm["HeavyAttack"].IsAvailable())
|
||||
if (player.inputSc.IsHoldingSpecialA)
|
||||
{
|
||||
string suffix = techniqueScore switch
|
||||
if (functionSm["DisruptionAttack"].IsAvailable())
|
||||
{
|
||||
< 1f => "A",
|
||||
< 3f => "B",
|
||||
>= 3f => "C",
|
||||
_ => "A"
|
||||
};
|
||||
|
||||
List<Enemy> disruptable = CombatManager.EnemySm.GetDisruptableEnemies(availableEnemies);
|
||||
Enemy target = CombatManager.EnemySm.GetScoredEnemies(availableEnemies)
|
||||
.ApplyScoreModifier(disruptable, 0f, 1f).BestEnemy();
|
||||
|
||||
if (PlayTargetedAnimation("DisruptionAttack" + suffix, target))
|
||||
{
|
||||
if (disruptable.Count > 0)
|
||||
string suffix = techniqueScore switch
|
||||
{
|
||||
var timeScaleModifierClip = player.feedbackSc
|
||||
.GetFeedbackData("DisruptionStartup")
|
||||
.Clip<TimeScaleModifierAction>("Time");
|
||||
float duration = fullBodyFuncAnimSm.collection["DisruptionAttack" + suffix]
|
||||
.Interval(IntervalType.Startup).Duration * 2;
|
||||
|
||||
timeScaleModifierClip.duration = duration;
|
||||
player.feedbackSc.PlayFeedback("DisruptionStartup");
|
||||
}
|
||||
< 1f => "A",
|
||||
< 3f => "B",
|
||||
>= 3f => "C",
|
||||
_ => "A"
|
||||
};
|
||||
|
||||
if (suffix == "B")
|
||||
List<Enemy> disruptable = CombatManager.EnemySm.GetDisruptableEnemies(availableEnemies);
|
||||
Enemy target = CombatManager.EnemySm.GetScoredEnemies(availableEnemies)
|
||||
.ApplyScoreModifier(disruptable, 0f, 1f).BestEnemy();
|
||||
|
||||
if (PlayTargetedAnimation("DisruptionAttack" + suffix, target))
|
||||
{
|
||||
ModifyTechniqueScore(-1, false);
|
||||
if (disruptable.Count > 0)
|
||||
{
|
||||
FeedbackClip timeScaleModifierClip = player.feedbackSc.GetFeedbackData("DisruptionStartup")
|
||||
.Clip<TimeScaleModifierAction>("Time");
|
||||
float duration = fullBodyFuncAnimSm.collection["DisruptionAttack" + suffix]
|
||||
.Interval(IntervalType.Startup).Duration * 2;
|
||||
|
||||
timeScaleModifierClip.duration = duration;
|
||||
player.feedbackSc.PlayFeedback("DisruptionStartup");
|
||||
}
|
||||
|
||||
if (suffix == "B")
|
||||
{
|
||||
ModifyTechniqueScore(-1, false);
|
||||
}
|
||||
else if (suffix == "C")
|
||||
{
|
||||
ModifyTechniqueScore(-3, false);
|
||||
}
|
||||
|
||||
comboSm.main.Reset();
|
||||
functionSm["DisruptionAttack"].Execute();
|
||||
}
|
||||
else if (suffix == "C")
|
||||
{
|
||||
ModifyTechniqueScore(-3, false);
|
||||
}
|
||||
|
||||
comboSm.main.Reset();
|
||||
functionSm["HeavyAttack"].Execute();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -299,7 +319,7 @@ namespace Cielonos.MainGame.Inventory.Collections
|
||||
player.operationSc.Dodge();
|
||||
DodgeSource defaultDodge = DodgeSource.Default(player);
|
||||
player.reactionSc.dodgeSm.ApplyDodge(defaultDodge);
|
||||
player.reactionSc.dodgeSm.GetCurrentDodgeSource().PerfectDodge();
|
||||
player.reactionSc.dodgeSm.GetCurrentDodgeSource().PerfectDodge(null);
|
||||
player.reactionSc.dodgeSm.RemoveDodge("DefaultDodge");
|
||||
}
|
||||
}
|
||||
@@ -372,17 +392,15 @@ namespace Cielonos.MainGame.Inventory.Collections
|
||||
float magnitude = hitFeedback == "SingleNormalHit" ? 0.12f : 0.06f;
|
||||
positionShakeAction.amplitude = vfxData.Get(vfxName).slashScreenPosition.normalized * magnitude;
|
||||
feedbackSc.PlayFeedback(hitFeedback);
|
||||
|
||||
new ElectronicParalysis.Progress(100f).Apply(enemy, player, this);
|
||||
|
||||
ModifyTechniqueScore(0.02f);
|
||||
if (attackUnit.unitName == "InstantAttack")
|
||||
/*if (attackUnit.unitName == "InstantAttack")
|
||||
{
|
||||
if (enemy.buffSm.HasBuff<ElectronicParalysis>())
|
||||
{
|
||||
slash.attackSm.attackValue.damage *= 2f;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
});
|
||||
|
||||
return slash;
|
||||
@@ -391,11 +409,25 @@ namespace Cielonos.MainGame.Inventory.Collections
|
||||
private NormalArea GenerateHeavySlash(string vfxName, AttackUnit attackUnit)
|
||||
{
|
||||
NormalArea slash = vfxData.SpawnVFX(vfxName, player).GetComponentInChildren<NormalArea>();
|
||||
|
||||
slash.Initialize<NormalArea>(player, this, Fraction.Enemy);
|
||||
|
||||
if (!HasExtender<PhotonDissociator>())
|
||||
{
|
||||
slash.SetAttackSubmodule<NormalArea>(attackUnit)
|
||||
.SetTimeSubmodule<NormalArea>(1f, 0.04f)
|
||||
.SetHitSubmodule<NormalArea>();
|
||||
}
|
||||
else // 如果有Photon Dissociator,重攻击拆分为五段,每段伤害为原来的30%,时间和判定也相应调整
|
||||
{
|
||||
AttackUnit modifiedUnit = attackUnit.Clone();
|
||||
modifiedUnit.startDamage *= 0.5f;
|
||||
|
||||
slash.SetAttackSubmodule<NormalArea>(modifiedUnit)
|
||||
.SetTimeSubmodule<NormalArea>(1f, 0.04f, 0.4f)
|
||||
.SetHitSubmodule<NormalArea>(0.1f, 3);
|
||||
}
|
||||
|
||||
slash.Initialize<NormalArea>(player, this, Fraction.Enemy)
|
||||
.SetAttackSubmodule<NormalArea>(attackUnit)
|
||||
.SetTimeSubmodule<NormalArea>(1f, 0.04f)
|
||||
.SetHitSubmodule<NormalArea>();
|
||||
slash.SetImpulseSubmodule(1f).WithRepulsion(5f);
|
||||
|
||||
slash.attackSm.breakthroughAction = (enemy, hitPosition) =>
|
||||
@@ -500,8 +532,6 @@ namespace Cielonos.MainGame.Inventory.Collections
|
||||
if (attackArea is NormalArea)
|
||||
{
|
||||
ModifyTechniqueScore(-0.1f);
|
||||
//attackArea.creator.GetHit(Breakthrough.Type.Disruption, out _);
|
||||
//attackArea.creator.movementSc.impulseSm.ApplyKnockback(player.transform.forward, 5f);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -516,12 +546,15 @@ namespace Cielonos.MainGame.Inventory.Collections
|
||||
new Vector3(0f, 4f, -2f);
|
||||
|
||||
feedbackSc.PlayFeedback("PerfectBlock");
|
||||
|
||||
|
||||
if (attackArea is NormalArea)
|
||||
{
|
||||
ModifyTechniqueScore(0.2f);
|
||||
//attackArea.creator.GetHit(Breakthrough.Type.Disruption, out _);
|
||||
//attackArea.creator.movementSc.impulseSm.ApplyKnockback(player.transform.forward, 5f);
|
||||
if (HasExtender<PhotonPolarizer>())
|
||||
{
|
||||
attackArea.creator.GetHit(Breakthrough.Type.Forced, out _);
|
||||
attackArea.creator.movementSc.impulseSm.ApplyKnockback(player.transform.forward, 6f);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
using System;
|
||||
using Cielonos.MainGame.Buffs;
|
||||
using Cielonos.MainGame.Buffs.Character;
|
||||
using Cielonos.MainGame.Characters;
|
||||
using SLSUtilities.General;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Cielonos.MainGame.Inventory.Collections
|
||||
{
|
||||
/// <summary>
|
||||
/// 穿甲弹头 / Armor Piercing Round
|
||||
/// Kinetics 攻击命中时降低目标护甲。
|
||||
/// </summary>
|
||||
public partial class ArmorPiercingRound : PassiveEquipmentBase
|
||||
{
|
||||
private const string EventKey = nameof(ArmorPiercingRound);
|
||||
|
||||
public override void OnObtained()
|
||||
{
|
||||
base.OnObtained();
|
||||
Action<AttackAreaBase, CharacterBase, Attack.Context> onStartAttack = OnStartAttack;
|
||||
player.eventSm.onStartAttack.Add(EventKey, onStartAttack.ToPrioritized());
|
||||
}
|
||||
|
||||
public override void OnDiscarded()
|
||||
{
|
||||
player.eventSm.onStartAttack.Remove(EventKey);
|
||||
base.OnDiscarded();
|
||||
}
|
||||
|
||||
private void OnStartAttack(AttackAreaBase attackArea, CharacterBase target, Attack.Context context)
|
||||
{
|
||||
if (context.value.type == Attack.Type.Kinetics)
|
||||
{
|
||||
int armorReduction = Mathf.RoundToInt(passiveAttributeSm.GetItemAttribute("ArmorReduction"));
|
||||
new ArmorReduction(5f, armorReduction).Apply(target, player, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public partial class ArmorPiercingRound
|
||||
{
|
||||
/// <summary>
|
||||
/// 穿甲弹头的Buff,默认降低目标等于unitedStack层数的护甲,持续5秒
|
||||
/// </summary>
|
||||
public class ArmorReduction : CharacterBuffBase
|
||||
{
|
||||
public ArmorReduction(float duration, int stack)
|
||||
{
|
||||
Initialize(BuffType.Positive, BuffDispelLevel.Basic);
|
||||
|
||||
this.contentSubmodule = new ContentSubmodule(this);
|
||||
this.timeSubmodule = new TimeSubmodule(this, duration);
|
||||
this.unitedStackSubmodule = new UnitedStackSubmodule(this, stack);
|
||||
this.attributeSubmodule = new AttributeSubmodule(this);
|
||||
}
|
||||
|
||||
public override bool OnBuffApply(out CharacterBuffBase existingBuff)
|
||||
{
|
||||
if (FindExistingSameBuff(out ArmorReduction existing))
|
||||
{
|
||||
existingBuff = existing;
|
||||
existing.timeSubmodule.RefreshDuration();
|
||||
existing.unitedStackSubmodule.PickHigherStack(this.unitedStackSubmodule);
|
||||
existing.UpdateArmorValue(existing.unitedStackSubmodule.stackAmount);
|
||||
return false;
|
||||
}
|
||||
|
||||
existingBuff = null;
|
||||
UpdateArmorValue(unitedStackSubmodule.stackAmount);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据当前层数更新护甲加成数值。
|
||||
/// </summary>
|
||||
private void UpdateArmorValue(int stacks)
|
||||
{
|
||||
attributeSubmodule.numericChange[CharacterAttribute.Armor] = -stacks;
|
||||
attributeSubmodule.RefreshAllModifiedAttributes();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 46a4b90939f53e04c8b0211785d581d5
|
||||
@@ -1,5 +1,3 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Cielonos.MainGame.Inventory.Collections
|
||||
{
|
||||
public class Ascension : PassiveEquipmentBase
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
using System;
|
||||
using Cielonos.MainGame.Buffs.Character;
|
||||
using Cielonos.MainGame.Characters;
|
||||
using SLSUtilities.General;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Cielonos.MainGame.Inventory.Collections
|
||||
{
|
||||
/// <summary>
|
||||
/// 助燃剂 / Combustion Enhancer
|
||||
/// 每次攻击到敌人后,如果敌人处于燃烧Buff,那么为燃烧Buff持续时间延长0.1秒
|
||||
/// </summary>
|
||||
public class CombustionEnhancer : PassiveEquipmentBase
|
||||
{
|
||||
private const string EventKey = nameof(CombustionEnhancer);
|
||||
|
||||
public override void OnObtained()
|
||||
{
|
||||
base.OnObtained();
|
||||
Action<AttackAreaBase, CharacterBase, Attack.Result> onFinishAttack = OnFinishAttack;
|
||||
player.eventSm.onFinishAttack.Add(EventKey, onFinishAttack.ToPrioritized());
|
||||
}
|
||||
|
||||
public override void OnDiscarded()
|
||||
{
|
||||
player.eventSm.onFinishAttack.Remove(EventKey);
|
||||
base.OnDiscarded();
|
||||
}
|
||||
|
||||
private void OnFinishAttack(AttackAreaBase attackArea, CharacterBase target, Attack.Result result)
|
||||
{
|
||||
Burn burn = target.buffSm.GetBuff<Burn>();
|
||||
burn?.timeSubmodule.AddDuration(0.1f);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d9bbfaab77002de4f98d00e15a5b6466
|
||||
@@ -20,9 +20,9 @@ namespace Cielonos.MainGame.Inventory
|
||||
public FunctionSubmodule(ItemBase owner, FunctionData data) : base(owner)
|
||||
{
|
||||
functionUnits = new Dictionary<string, RuntimeFunctionUnit>();
|
||||
foreach (var kvp in data.functionUnits)
|
||||
foreach (var unit in data.functionUnitList)
|
||||
{
|
||||
functionUnits[kvp.Key] = new RuntimeFunctionUnit(this, kvp.Value);
|
||||
functionUnits[unit.unitName] = new RuntimeFunctionUnit(this, unit);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ namespace Cielonos.MainGame.Inventory
|
||||
public RuntimeFunctionUnit(FunctionSubmodule owner, FunctionData.FunctionUnit data) : base(owner)
|
||||
{
|
||||
this.data = data;
|
||||
maxCooldown = data.interval;
|
||||
maxCooldown = data.cooldown;
|
||||
currentCooldown = 0f;
|
||||
}
|
||||
|
||||
@@ -60,30 +60,49 @@ namespace Cielonos.MainGame.Inventory
|
||||
{
|
||||
bool cooldownAvailable = currentCooldown <= 0f;
|
||||
bool energyAvailable = character.attributeSm[CharacterAttribute.Energy] >= GetEffectiveEnergyCost();
|
||||
return cooldownAvailable && energyAvailable;
|
||||
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 MinCooldownMultiplier = 0.1f;
|
||||
private const float MaxCooldownReduction = 0.9f;
|
||||
private const float MaxEnergyCostReduction = 0.9f;
|
||||
|
||||
/// <summary> 计算应用 EnergyCostReduction 后的实际能量消耗。 </summary>
|
||||
private float GetEffectiveEnergyCost()
|
||||
{
|
||||
float ecr = Mathf.Clamp(character.attributeSm[CharacterAttribute.EnergyCostReduction], 0f, MaxEnergyCostReduction);
|
||||
return data.energyCost * (1f - ecr);
|
||||
float energyCostReduction = Mathf.Clamp(character.attributeSm[CharacterAttribute.EnergyCostReduction], 0f, MaxEnergyCostReduction);
|
||||
return data.energyCost * (1f - energyCostReduction);
|
||||
}
|
||||
|
||||
private void ResetCooldown()
|
||||
{
|
||||
float cdr = Mathf.Clamp(character.attributeSm[CharacterAttribute.CooldownReduction], 0f, 1f - MinCooldownMultiplier);
|
||||
currentCooldown = maxCooldown * (1f - cdr);
|
||||
float cooldownReduction = Mathf.Clamp(character.attributeSm[CharacterAttribute.CooldownReduction], 0f, MaxCooldownReduction);
|
||||
currentCooldown = maxCooldown * (1f - cooldownReduction);
|
||||
}
|
||||
|
||||
private void ConsumeEnergy()
|
||||
|
||||
Reference in New Issue
Block a user