狗屎Minimax坏我代码
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
using MoreMountains.FeedbacksForThirdParty;
|
||||
using Cielonos.MainGame.Effects.Feedback;
|
||||
using SLSUtilities.General;
|
||||
using UnityEngine;
|
||||
|
||||
@@ -11,24 +11,20 @@ namespace Cielonos.MainGame.Characters
|
||||
if (player.movementSc.canDash && player.movementSc.canDodge && fullBodyFuncAnimSm.Play("Dash"))
|
||||
{
|
||||
length = length < 0 ? player.attributeSm["DashLength"] : length;
|
||||
//Debug.Log($"Dash length: {length}");
|
||||
float dashMultiplier = length / fullBodyFuncAnimSm.collection["Dash"].variableCollection.GetVariable<float>("RootMoveZ");
|
||||
player.landMovementSc.dashMoveMultiplier = dashMultiplier;
|
||||
Vector3 cameraForward = player.viewSc.playerCamera.transform.forward.Flatten();
|
||||
Vector3 dashCameraRotation;
|
||||
|
||||
if (isInputDirection)
|
||||
{
|
||||
player.landMovementSc.TurnToInputDirection(direction);
|
||||
Vector3 playerForward = player.transform.forward.Flatten();
|
||||
dashCameraRotation = CalculateDashAngles(playerForward, cameraForward);
|
||||
}
|
||||
else
|
||||
{
|
||||
player.landMovementSc.TurnToDirection(direction, 0f);
|
||||
dashCameraRotation = CalculateDashAngles(direction, cameraForward);
|
||||
}
|
||||
player.feedbackSc["Dash"].feedback.GetFeedbackOfType<MMF_CinemachineRotation>().RotationAmplitude = dashCameraRotation;
|
||||
player.feedbackSc["Dash"].feedback.GetFeedbackOfType<MMF_RadialBlur>().TargetCenter = player.GetNormalizedScreenPosition();
|
||||
|
||||
// 计算冲刺方向用于相机震动方向设置
|
||||
// Dash反馈的方向设置将在DashStart中通过新Feedback系统统一处理
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +32,10 @@ namespace Cielonos.MainGame.Characters
|
||||
{
|
||||
player.landMovementSc.isDashing = true;
|
||||
player.audioSc.PlayDashSound();
|
||||
player.feedbackSc["Dash"]?.Play();
|
||||
|
||||
// 使用新Feedback系统播放Dash反馈
|
||||
player.feedbackSc.PlayFeedback("Dash");
|
||||
|
||||
//player.renderSc.dashTrails.ForEach(ds => ds.active = true);
|
||||
//player.renderSc.dashTrails.ForEach(ds => ds.Restart());
|
||||
|
||||
@@ -70,11 +69,8 @@ namespace Cielonos.MainGame.Characters
|
||||
length = length < 0 ? player.attributeSm["DodgeLength"] : length;
|
||||
float dashMultiplier = length / fullBodyFuncAnimSm.collection["Dodge"].variableCollection.GetVariable<float>("RootMoveZ");
|
||||
player.landMovementSc.dashMoveMultiplier = dashMultiplier;
|
||||
Vector3 playerBackward = -player.transform.forward.Flatten();
|
||||
Vector3 cameraForward = player.viewSc.playerCamera.transform.forward.Flatten();
|
||||
Vector3 dodgeCameraRotation = CalculateDashAngles(playerBackward, cameraForward);
|
||||
player.feedbackSc["Dodge"].feedback.GetFeedbackOfType<MMF_CinemachineRotation>().RotationAmplitude = dodgeCameraRotation;
|
||||
player.feedbackSc["Dodge"].feedback.GetFeedbackOfType<MMF_RadialBlur>().TargetCenter = player.GetNormalizedScreenPosition();
|
||||
|
||||
// Dodge反馈将在DodgeStart中通过新Feedback系统统一处理
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,7 +78,10 @@ namespace Cielonos.MainGame.Characters
|
||||
{
|
||||
player.landMovementSc.isDashing = true;
|
||||
player.audioSc.PlayDashSound();
|
||||
player.feedbackSc["Dodge"]?.Play();
|
||||
|
||||
// 使用新Feedback系统播放Dodge反馈
|
||||
player.feedbackSc.PlayFeedback("Dodge");
|
||||
|
||||
//player.renderSc.dashTrails.ForEach(ds => ds.active = true);
|
||||
//player.renderSc.dashTrails.ForEach(ds => ds.Restart());
|
||||
|
||||
|
||||
@@ -3,10 +3,12 @@ using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using Cielonos.MainGame.Characters;
|
||||
using Cielonos.MainGame.Effects.Feedback;
|
||||
using Cielonos.MainGame.FunctionalAnimation;
|
||||
using MoreMountains.Feedbacks;
|
||||
using MoreMountains.FeedbacksForThirdParty;
|
||||
using Sirenix.OdinInspector;
|
||||
using SLSUtilities.Feedback;
|
||||
using SLSUtilities.WwiseAssistance;
|
||||
using SLSUtilities.FunctionalAnimation;
|
||||
using UnityEngine;
|
||||
@@ -30,11 +32,13 @@ namespace Cielonos.MainGame.Characters.Inventory
|
||||
public ViewObjectData viewObjectData;
|
||||
public VFXData vfxData;
|
||||
public AttributeData passiveAttributeData;
|
||||
public UpgradeData upgradeData;
|
||||
public ComboData comboData;
|
||||
public AttackData attackData;
|
||||
public FunctionData functionData;
|
||||
public AmmoData ammoData;
|
||||
public BlockData blockData;
|
||||
public OverloadData overloadData;
|
||||
|
||||
[TitleGroup("Audio")]
|
||||
public AudioContainer audioContainer;
|
||||
@@ -44,6 +48,7 @@ namespace Cielonos.MainGame.Characters.Inventory
|
||||
public ComboSubmodule comboSm;
|
||||
public FunctionSubmodule functionSm;
|
||||
public AmmoSubmodule ammoSm;
|
||||
public OverloadSubmodule overloadSm;
|
||||
|
||||
[TitleGroup("Subcontrollers")]
|
||||
public FeedbackSubcontroller feedbackSc;
|
||||
@@ -57,10 +62,12 @@ namespace Cielonos.MainGame.Characters.Inventory
|
||||
public virtual void Initialize()
|
||||
{
|
||||
vfxData?.Initialize(player);
|
||||
feedbackSc?.Initialize();
|
||||
if(comboData != null) comboSm = new ComboSubmodule(this, comboData);
|
||||
if(functionData != null) functionSm = new FunctionSubmodule(this, functionData);
|
||||
if(ammoData != null) ammoSm = new AmmoSubmodule(this, ammoData);
|
||||
if(passiveAttributeData != null) passiveAttributeSm = new AttributeSubmodule(this, passiveAttributeData);
|
||||
if(passiveAttributeData != null) passiveAttributeSm = new AttributeSubmodule(this, passiveAttributeData, upgradeData);
|
||||
if(overloadData != null) overloadSm = new OverloadSubmodule(this, overloadData);
|
||||
}
|
||||
|
||||
public virtual void OnObtained()
|
||||
@@ -73,9 +80,23 @@ namespace Cielonos.MainGame.Characters.Inventory
|
||||
passiveAttributeSm?.RefreshAllModifiedAttributes();
|
||||
}
|
||||
|
||||
[Button("Upgrade")]
|
||||
public virtual void Upgrade()
|
||||
{
|
||||
if (upgradeData == null || passiveAttributeSm == null)
|
||||
{
|
||||
Debug.LogWarning($"{GetType().Name}: Cannot upgrade - missing UpgradeData or AttributeSubmodule.");
|
||||
return;
|
||||
}
|
||||
|
||||
passiveAttributeSm.level++;
|
||||
passiveAttributeSm.RefreshAllModifiedAttributes();
|
||||
}
|
||||
|
||||
protected virtual void Update()
|
||||
{
|
||||
functionSm?.Update(player.selfTimeSm.DeltaTime);
|
||||
overloadSm?.Update(player.selfTimeSm.DeltaTime);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,31 +178,25 @@ namespace Cielonos.MainGame.Characters.Inventory
|
||||
|
||||
protected virtual void Swing(string feedBackName, Vector3 swingRotation = default, Vector3 swingPosition = default)
|
||||
{
|
||||
Vector3 playerForward = player.transform.forward;
|
||||
Vector3 cameraForward = player.viewSc.playerCamera.transform.forward;
|
||||
|
||||
Vector3 flatPlayerFwd = Vector3.ProjectOnPlane(playerForward, Vector3.up).normalized;
|
||||
Vector3 flatCameraFwd = Vector3.ProjectOnPlane(cameraForward, Vector3.up).normalized;
|
||||
|
||||
Quaternion deltaRotation = Quaternion.FromToRotation(flatCameraFwd, flatPlayerFwd);
|
||||
Vector3 tempRotVec = new Vector3(swingRotation.y, swingRotation.x, swingRotation.z);
|
||||
Vector3 rotatedTemp = deltaRotation * tempRotVec;
|
||||
Vector3 finalRotation = new Vector3(rotatedTemp.y, rotatedTemp.x, rotatedTemp.z);
|
||||
Vector3 finalPosition = deltaRotation * swingPosition;
|
||||
|
||||
MMF_CinemachineRotation cinemachineRotation = feedbackSc[feedBackName].feedback.GetFeedbackOfType<MMF_CinemachineRotation>();
|
||||
if (cinemachineRotation != null)
|
||||
feedbackSc.feedbackDataCollection.TryGet(feedBackName, out FeedbackData feedBackData);
|
||||
var cameraTrack = feedBackData.tracks.Find(track => track.trackName == "Camera");
|
||||
if (cameraTrack == null)
|
||||
{
|
||||
cinemachineRotation.RotationAmplitude = finalRotation;
|
||||
Debug.LogWarning($"没有找到名为 'Camera' 的轨道,请检查 FeedbackData '{feedBackName}' 的设置。");
|
||||
return;
|
||||
}
|
||||
|
||||
MMF_CinemachinePosition cinemachinePosition = feedbackSc[feedBackName].feedback.GetFeedbackOfType<MMF_CinemachinePosition>();
|
||||
if (cinemachinePosition != null)
|
||||
if (cameraTrack.clips.Find(clip => clip.action is CameraPositionShakeAction)?.action is CameraPositionShakeAction positionShakeAction)
|
||||
{
|
||||
cinemachinePosition.PositionAmplitude = finalPosition;
|
||||
positionShakeAction.amplitude = swingPosition;
|
||||
}
|
||||
|
||||
if (cameraTrack.clips.Find(clip => clip.action is CameraRotationShakeAction)?.action is CameraRotationShakeAction rotationShakeAction)
|
||||
{
|
||||
rotationShakeAction.amplitude = swingRotation;
|
||||
}
|
||||
|
||||
feedbackSc[feedBackName].Play();
|
||||
feedbackSc.PlayFeedback(feedBackName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ namespace Cielonos.MainGame.Characters.Inventory
|
||||
{
|
||||
if (player.inventorySc.equipmentSm.currentMainWeapon == this)
|
||||
{
|
||||
functionSm?.Update(player.selfTimeSm.DeltaTime);
|
||||
base.Update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ namespace Cielonos.MainGame.Characters.Inventory
|
||||
protected override void Update()
|
||||
{
|
||||
functionSm?.Update(player.selfTimeSm.DeltaTime);
|
||||
overloadSm?.Update(player.selfTimeSm.DeltaTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -35,7 +35,7 @@ namespace Cielonos.MainGame.Characters.Inventory
|
||||
{
|
||||
if (player.inventorySc.equipmentSm.currentSupportEquipments.Contains(this))
|
||||
{
|
||||
functionSm?.Update(player.selfTimeSm.DeltaTime);
|
||||
base.Update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,6 +47,9 @@ namespace Cielonos.MainGame.Characters.Inventory
|
||||
public BreakthroughType breakthroughType = BreakthroughType.Weak;
|
||||
public DisruptionType disruptionType = DisruptionType.NormalExternal;
|
||||
|
||||
[Title("Tags")]
|
||||
public List<string> tags = new List<string>();
|
||||
|
||||
[Title("Hit VFX")]
|
||||
public bool useVFXDataHit;
|
||||
[HideIf("useVFXDataHit")]
|
||||
@@ -69,7 +72,7 @@ namespace Cielonos.MainGame.Characters.Inventory
|
||||
{
|
||||
bool isCritical = Random.value < GetFinalCriticalChance();
|
||||
float finalDamage = isCritical ? GetFinalCriticalDamage() : GetFinalRegularDamage();
|
||||
return new AttackValue(attacker, isCritical, finalDamage, attackType, disruptionType, breakthroughType);
|
||||
return new AttackValue(attacker, isCritical, finalDamage, attackType, disruptionType, breakthroughType, tags);
|
||||
}
|
||||
|
||||
public GameObject GetHitVFX()
|
||||
|
||||
@@ -8,7 +8,8 @@ namespace Cielonos.MainGame.Characters.Inventory
|
||||
[CreateAssetMenu(fileName = "AttributeData", menuName = "Cielonos/Items/AttributeData")]
|
||||
public class AttributeData : SerializedScriptableObject
|
||||
{
|
||||
[Title("Item Attributes")] public SerializedDictionary<string, float> itemAttributes = new();
|
||||
[Title("Item Attributes")]
|
||||
public SerializedDictionary<string, float> itemAttributes = new();
|
||||
|
||||
[Title("Character Attribute Changes")] [DictionaryTitle("Numeric")]
|
||||
public SerializedDictionary<string, float, CharacterAttributePair> chaAttrNumericChange = new();
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Cielonos.MainGame.Characters.Inventory
|
||||
{
|
||||
[CreateAssetMenu(fileName = "OverloadData", menuName = "Cielonos/Items/OverloadData")]
|
||||
public class OverloadData : SerializedScriptableObject
|
||||
{
|
||||
[Title("Overload Configuration")]
|
||||
[LabelText("Trigger Threshold (Max Overload)")]
|
||||
public float maxOverload = 200f;
|
||||
|
||||
[LabelText("Absorption Weight")]
|
||||
public float overloadWeight = 1f;
|
||||
|
||||
[LabelText("Cooldown After Trigger (Seconds)")]
|
||||
public float triggerCooldown = 8f;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c3e872bf5164c1b449783ffe50bdab9c
|
||||
@@ -34,6 +34,11 @@ namespace Cielonos.MainGame.Characters.Inventory
|
||||
{
|
||||
if (upgradeMode == UpgradeMode.ManualList)
|
||||
{
|
||||
if (valueList.Count == 0)
|
||||
{
|
||||
return defaultUpgradeValue * level;
|
||||
}
|
||||
|
||||
if (level < valueList.Count)
|
||||
{
|
||||
return valueList[level];
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
using System.Collections.Generic;
|
||||
using ChocDino.UIFX;
|
||||
using Cielonos.MainGame.Buffs.Character;
|
||||
using Cielonos.MainGame.Effects.Feedback;
|
||||
using Cielonos.MainGame.UI;
|
||||
using MoreMountains.Feedbacks;
|
||||
using MoreMountains.FeedbacksForThirdParty;
|
||||
using MoreMountains.FeedbacksForThirdParty.Cielonos;
|
||||
using SLSUtilities.Feedback;
|
||||
using SLSUtilities.General;
|
||||
using SLSUtilities.FunctionalAnimation;
|
||||
using SLSUtilities.WwiseAssistance;
|
||||
@@ -194,10 +196,10 @@ namespace Cielonos.MainGame.Characters.Inventory.Collections
|
||||
{
|
||||
if (BattleManager.EnemySm.GetDisruptableEnemies(availableEnemies).Count > 0)
|
||||
{
|
||||
float duration = fullBodyFuncAnimSm.collection["DisruptionAttack" + suffix].Interval(IntervalType.Startup).Duration * 2;
|
||||
player.feedbackSc["DisruptionBulletTime"].feedback.GetFeedbackOfType<CIF_TimeScaleModifier>().Duration = duration;
|
||||
player.feedbackSc["DisruptionBulletTime"].feedback.GetFeedbackOfType<MMF_ColorAdjustments_URP>().ShakeDuration = duration;
|
||||
player.feedbackSc["DisruptionBulletTime"].Play();
|
||||
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");
|
||||
}
|
||||
|
||||
if (suffix == "B")
|
||||
@@ -281,10 +283,10 @@ namespace Cielonos.MainGame.Characters.Inventory.Collections
|
||||
GenerateHeavySlash(p.str0, attackData[p.str1]);
|
||||
}
|
||||
|
||||
private void FAPF_GenerateParrySlash(RuntimeFuncAnim rtFuncAnim)
|
||||
private void FAPF_GenerateUltimateSlash(RuntimeFuncAnim rtFuncAnim)
|
||||
{
|
||||
CustomFunction.PC_StringString p = rtFuncAnim.GetParams<CustomFunction.PC_StringString>();
|
||||
GenerateParrySlash(p.str0, attackData[p.str1]);
|
||||
GenerateUltimateSlash(p.str0, attackData[p.str1]);
|
||||
}
|
||||
|
||||
private void FAPF_GenerateDisruptionSlash(RuntimeFuncAnim rtFuncAnim)
|
||||
@@ -308,25 +310,25 @@ namespace Cielonos.MainGame.Characters.Inventory.Collections
|
||||
|
||||
slash.Initialize<NormalArea>(player, this, Fraction.Enemy)
|
||||
.SetAttackSubmodule<NormalArea>(attackUnit)
|
||||
.SetTimeSubmodule<NormalArea>(1f, 0.04f)
|
||||
.SetTimeSubmodule<NormalArea>(1f, 0.02f)
|
||||
.SetHitSubmodule<NormalArea>()
|
||||
.SetForceSubmodule<NormalArea>(1.5f, true);
|
||||
|
||||
slash.attackSm.breakthroughAction = (enemy, hitPosition) =>
|
||||
{
|
||||
AudioManager.Post(AK.EVENTS.DISRUPT, hitPosition);
|
||||
//ApplyElectronicParalysis(enemy, attackUnit);
|
||||
};
|
||||
|
||||
slash.hitSm.AddHitSound(AK.EVENTS.POLYCHROME_LIGHTATTACKHIT)
|
||||
.AddHitEvent((enemy, hitPosition) =>
|
||||
{
|
||||
feedbackSc[feedback].feedback.GetFeedbackOfType<MMF_CinemachinePosition>().PositionAmplitude =
|
||||
vfxData.Get(vfxName).slashScreenPosition.normalized * 0.1f;
|
||||
feedbackSc[feedback].Play();
|
||||
//ApplyElectronicParalysis(enemy, attackUnit);
|
||||
var positionShakeAction = feedbackSc.GetFeedbackData(feedback).Action<CameraPositionShakeAction>("Camera");
|
||||
float magnitude = feedback == "SingleNormalHit" ? 0.12f : 0.06f;
|
||||
positionShakeAction.amplitude = vfxData.Get(vfxName).slashScreenPosition.normalized * magnitude;
|
||||
feedbackSc.PlayFeedback(feedback);
|
||||
|
||||
|
||||
ModifyTechniqueScore(0.02f);
|
||||
|
||||
if (attackUnit.unitName == "InstantAttack")
|
||||
{
|
||||
if (enemy.buffSm.HasBuff<ElectronicParalysis>())
|
||||
@@ -354,7 +356,7 @@ namespace Cielonos.MainGame.Characters.Inventory.Collections
|
||||
|
||||
slash.Initialize<NormalArea>(player, this, Fraction.Enemy)
|
||||
.SetAttackSubmodule<NormalArea>(attackUnit)
|
||||
.SetTimeSubmodule<NormalArea>(1f, 0.06f)
|
||||
.SetTimeSubmodule<NormalArea>(1f, 0.04f)
|
||||
.SetHitSubmodule<NormalArea>()
|
||||
.SetForceSubmodule<NormalArea>(3f, true);
|
||||
|
||||
@@ -368,9 +370,10 @@ namespace Cielonos.MainGame.Characters.Inventory.Collections
|
||||
slash.hitSm.AddHitSound(AK.EVENTS.POLYCHROME_HEAVYATTACKLHIT)
|
||||
.AddHitEvent((enemy, hitPosition) =>
|
||||
{
|
||||
feedbackSc["HeavyHitFirst"].feedback.GetFeedbackOfType<MMF_CinemachinePosition>().PositionAmplitude =
|
||||
vfxData.Get(vfxName).slashScreenPosition.normalized * 0.15f;
|
||||
feedbackSc["HeavyHitFirst"].Play();
|
||||
var positionShakeAction = feedbackSc.GetFeedbackData("HeavyHit").Action<CameraPositionShakeAction>("Camera");
|
||||
positionShakeAction.amplitude = vfxData.Get(vfxName).slashScreenPosition.normalized * 0.18f;
|
||||
feedbackSc.PlayFeedback("HeavyHit");
|
||||
|
||||
ModifyTechniqueScore(0.05f);
|
||||
ApplyElectronicParalysis(enemy, attackUnit);
|
||||
});
|
||||
@@ -384,36 +387,35 @@ namespace Cielonos.MainGame.Characters.Inventory.Collections
|
||||
|
||||
slash.Initialize<NormalArea>(player, this, Fraction.Enemy)
|
||||
.SetAttackSubmodule<NormalArea>(attackUnit)
|
||||
.SetTimeSubmodule<NormalArea>(1f, 0.04f, 0.06f)
|
||||
.SetTimeSubmodule<NormalArea>(1f, 0.04f)
|
||||
.SetHitSubmodule<NormalArea>()
|
||||
.SetForceSubmodule<NormalArea>(3f, true);
|
||||
|
||||
slash.attackSm.breakthroughAction = (enemy, hitPosition) =>
|
||||
{
|
||||
ModifyTechniqueScore(0.2f);
|
||||
feedbackSc.PlayFeedback("Breakthrough");
|
||||
AudioManager.Post(AK.EVENTS.DISRUPT, hitPosition);
|
||||
ApplyElectronicParalysis(enemy, attackUnit);
|
||||
};
|
||||
|
||||
slash.hitSm
|
||||
.AddHitSound(AK.EVENTS.POLYCHROME_HEAVYATTACKLHIT)
|
||||
.AddHitEvent((enemy, hitPosition) =>
|
||||
{
|
||||
feedbackSc["HeavyHitFirst"].feedback.GetFeedbackOfType<MMF_CinemachinePosition>().PositionAmplitude =
|
||||
vfxData.Get(vfxName).slashScreenPosition.normalized * 0.15f;
|
||||
feedbackSc["HeavyHitFirst"].Play();
|
||||
ApplyElectronicParalysis(enemy, attackUnit);
|
||||
var positionShakeAction = feedbackSc.GetFeedbackData("HeavyHit").Action<CameraPositionShakeAction>("Camera");
|
||||
positionShakeAction.amplitude = vfxData.Get(vfxName).slashScreenPosition.normalized * 0.18f;
|
||||
feedbackSc.PlayFeedback("HeavyHit");
|
||||
});
|
||||
return slash;
|
||||
}
|
||||
|
||||
private NormalArea GenerateParrySlash(string vfxName, AttackUnit attackUnit)
|
||||
private NormalArea GenerateUltimateSlash(string vfxName, AttackUnit attackUnit)
|
||||
{
|
||||
NormalArea slash = vfxData.SpawnVFX(vfxName).GetComponentInChildren<NormalArea>();
|
||||
|
||||
slash.Initialize<NormalArea>(player, this, Fraction.Enemy)
|
||||
.SetAttackSubmodule<NormalArea>(attackUnit)
|
||||
.SetTimeSubmodule<NormalArea>(1f, 0.06f)
|
||||
.SetTimeSubmodule<NormalArea>(1f, 0.04f)
|
||||
.SetHitSubmodule<NormalArea>()
|
||||
.SetForceSubmodule<NormalArea>(10f, true);
|
||||
|
||||
@@ -426,8 +428,10 @@ namespace Cielonos.MainGame.Characters.Inventory.Collections
|
||||
.AddHitSound(AK.EVENTS.POLYCHROME_HEAVYATTACKLHIT)
|
||||
.AddHitEvent((enemy, hitPosition) =>
|
||||
{
|
||||
feedbackSc["ParryHit"].Play();
|
||||
new ElectronicParalysis(5f).Apply(enemy);
|
||||
var positionShakeAction = feedbackSc.GetFeedbackData("HeavyHit").Action<CameraPositionShakeAction>("Camera");
|
||||
positionShakeAction.amplitude = vfxData.Get(vfxName).slashScreenPosition.normalized * 0.18f;
|
||||
feedbackSc.PlayFeedback("HeavyHit");
|
||||
feedbackSc.PlayFeedback("Breakthrough");
|
||||
});
|
||||
|
||||
return slash;
|
||||
@@ -450,17 +454,13 @@ namespace Cielonos.MainGame.Characters.Inventory.Collections
|
||||
{
|
||||
_blockAnimName = _blockAnimName == "BlockL" ? "BlockR" : "BlockL";
|
||||
animationSc.fullBodyFuncAnimSm.Play(_blockAnimName, 1, 0);
|
||||
player.selfTimeSm.ModifyTimeScale(0.06f, 0.4f);
|
||||
attackArea.creator.selfTimeSm.ModifyTimeScale(0.06f, 0.4f);
|
||||
|
||||
if (_blockAnimName == "BlockL")
|
||||
{
|
||||
feedbackSc["NormalBlockLeft"].Play();
|
||||
}
|
||||
else
|
||||
{
|
||||
feedbackSc["NormalBlockRight"].Play();
|
||||
}
|
||||
var rotationShakeAction = feedbackSc.GetFeedbackData("NormalBlock").Action<CameraRotationShakeAction>("Camera");
|
||||
rotationShakeAction.amplitude = _blockAnimName == "BlockL" ?
|
||||
new Vector3(-0f, -2f, 1f) :
|
||||
new Vector3(-0f, 2f, -1f);
|
||||
|
||||
feedbackSc.PlayFeedback("NormalBlock");
|
||||
|
||||
if (attackArea is NormalArea)
|
||||
{
|
||||
@@ -472,17 +472,13 @@ namespace Cielonos.MainGame.Characters.Inventory.Collections
|
||||
{
|
||||
_blockAnimName = _blockAnimName == "BlockL" ? "BlockR" : "BlockL";
|
||||
animationSc.fullBodyFuncAnimSm.Play(_blockAnimName, 1, 0);
|
||||
player.selfTimeSm.ModifyTimeScale(0.12f, EaseType.InQuint, 0.2f);
|
||||
attackArea.creator.selfTimeSm.ModifyTimeScale(0.12f, EaseType.InQuint, 0.2f);
|
||||
|
||||
if (_blockAnimName == "BlockL")
|
||||
{
|
||||
feedbackSc["PerfectBlockLeft"].Play();
|
||||
}
|
||||
else
|
||||
{
|
||||
feedbackSc["PerfectBlockRight"].Play();
|
||||
}
|
||||
var rotationShakeAction = feedbackSc.GetFeedbackData("PerfectBlock").Action<CameraRotationShakeAction>("Camera");
|
||||
rotationShakeAction.amplitude = _blockAnimName == "BlockL" ?
|
||||
new Vector3(0f, -4f, 2f) :
|
||||
new Vector3(0f, 4f, -2f);
|
||||
|
||||
feedbackSc.PlayFeedback("PerfectBlock");
|
||||
|
||||
if (attackArea is NormalArea)
|
||||
{
|
||||
|
||||
@@ -22,13 +22,7 @@ namespace Cielonos.MainGame.Characters.Inventory.Collections
|
||||
{
|
||||
player.reactionSc.reflectionSm.ApplyReflection(player, this, "Deflector_Reflection", 0, 0.01f,
|
||||
area => area is Projectile,
|
||||
area =>
|
||||
{
|
||||
if (area is Projectile projectile)
|
||||
{
|
||||
projectile.Reflect(player);
|
||||
}
|
||||
});
|
||||
area => (area as Projectile)!.Reflect(player));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
using System;
|
||||
using Cielonos.MainGame.Characters;
|
||||
using SLSUtilities.General;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Cielonos.MainGame.Characters.Inventory.Collections
|
||||
{
|
||||
public class OverloadBattery : PassiveEquipmentBase
|
||||
{
|
||||
private bool _isBuffActive = false;
|
||||
|
||||
public override void OnObtained()
|
||||
{
|
||||
// 直接订阅由 OverloadSubmodule 抛出的满溢满充爆气事件
|
||||
if (overloadSm != null)
|
||||
{
|
||||
overloadSm.OnTriggered += TriggerOverloadEffect;
|
||||
}
|
||||
}
|
||||
|
||||
public void TriggerOverloadEffect()
|
||||
{
|
||||
// 挂载增伤 Buff
|
||||
_isBuffActive = true;
|
||||
|
||||
// 为下一次攻击进行截流修饰(利用上一个阶段优化提升完毕的 EventSubmodule 架构)
|
||||
Action<AttackAreaBase, CharacterBase, AttackResult> onStartAttack = OnStartAttack;
|
||||
|
||||
if (!player.eventSm.onStartAttack.ContainsKey("OverloadBattery_DamageBoost"))
|
||||
{
|
||||
player.eventSm.onStartAttack.Add("OverloadBattery_DamageBoost", onStartAttack.ToPrioritized());
|
||||
MainGameManager.BaseCollection.InfoText().Spawn(player.centerPosition, "Overload Battery Boost").SetScale(0.5f);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnStartAttack(AttackAreaBase attackArea, CharacterBase target, AttackResult attackResult)
|
||||
{
|
||||
if (!_isBuffActive) return;
|
||||
|
||||
// 拦截检查:必须是重突破等级(BreakthroughType.Heavy)
|
||||
// 如果不是重攻击,我们就避让不进行任何修饰,且不消耗掉 Buff 的开启状态
|
||||
if (attackResult.attackValue.breakthroughType != BreakthroughType.Heavy) return;
|
||||
|
||||
// 最终伤害提升 50%。上个方案中我们留下了 damageMultiplier,天然完美支持翻倍操作。
|
||||
attackResult.attackValue.damageMultiplier += 0.5f;
|
||||
_isBuffActive = false;
|
||||
// “一次性”触发,修饰完毕后从玩家的攻击起手事件池里销毁自身,不沾染下一次无关的攻击。
|
||||
player.eventSm.onStartAttack.Remove("OverloadBattery_DamageBoost");
|
||||
}
|
||||
|
||||
public override void OnDiscarded()
|
||||
{
|
||||
base.OnDiscarded();
|
||||
|
||||
player.eventSm.onStartAttack.Remove("OverloadBattery_DamageBoost");
|
||||
|
||||
if (overloadSm != null)
|
||||
{
|
||||
overloadSm.OnTriggered -= TriggerOverloadEffect;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ac011093fb4cf5849942d64e342ea931
|
||||
@@ -0,0 +1,9 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Cielonos.MainGame.Characters.Inventory.Collections
|
||||
{
|
||||
public class SpatialWarpCaliper : PassiveEquipmentBase
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 31abb4a87db9f6340b3cd13cfd7ffb54
|
||||
@@ -6,30 +6,60 @@ namespace Cielonos.MainGame.Characters.Inventory
|
||||
{
|
||||
public class AttributeSubmodule : SubmoduleBase<ItemBase>
|
||||
{
|
||||
public int level;
|
||||
|
||||
public AttributeGroup attributeGroup;
|
||||
public Dictionary<string, float> numericChange;
|
||||
public Dictionary<string, float> percentageChangeOfAccumulation;
|
||||
public Dictionary<string, float> percentageChangeOfMultiplication;
|
||||
|
||||
private UpgradeData _upgradeData;
|
||||
|
||||
public bool Has(string attributeName) => attributeGroup.current.ContainsKey(attributeName);
|
||||
public float Get(string attributeName, float defaultValue) => attributeGroup.current.GetValueOrDefault(attributeName, defaultValue);
|
||||
|
||||
public AttributeSubmodule(ItemBase owner, AttributeData data) : base(owner)
|
||||
public float this[string attributeName]
|
||||
{
|
||||
get => attributeGroup.current.GetValueOrDefault(attributeName, attributeName.Contains("Multiplier") ? 1 : 0);
|
||||
set => attributeGroup.current[attributeName] = value;
|
||||
}
|
||||
|
||||
public AttributeSubmodule(ItemBase owner, AttributeData data, UpgradeData upgradeData = null) : base(owner)
|
||||
{
|
||||
this.attributeGroup = new AttributeGroup(data.itemAttributes.ToDictionary());
|
||||
this.numericChange = new Dictionary<string, float>(data.chaAttrNumericChange);
|
||||
this.percentageChangeOfAccumulation = new Dictionary<string, float>(data.chaAttrPercentageChangeOfAccumulation);
|
||||
this.percentageChangeOfMultiplication = new Dictionary<string, float>(data.chaAttrPercentageChangeOfMultiplication);
|
||||
this._upgradeData = upgradeData;
|
||||
}
|
||||
|
||||
public void GetAttributeChanges(string attributeName, out float numeric, out float pAccumulation, out float pMultiplication)
|
||||
{
|
||||
numeric = numericChange.GetValueOrDefault(attributeName, 0f);
|
||||
numeric = numericChange.GetValueOrDefault(attributeName, 0f) + GetUpgradeNumericValue(attributeName);
|
||||
pAccumulation = percentageChangeOfAccumulation.GetValueOrDefault(attributeName, 0f);
|
||||
pMultiplication = percentageChangeOfMultiplication.GetValueOrDefault(attributeName, 1f);
|
||||
}
|
||||
|
||||
public void ApplyAttributeChanges(string attributeName, ref float numeric, ref float pAccumulation, ref float pMultiplication)
|
||||
{
|
||||
numeric += numericChange.GetValueOrDefault(attributeName, 0f);
|
||||
numeric += numericChange.GetValueOrDefault(attributeName, 0f) + GetUpgradeNumericValue(attributeName);
|
||||
pAccumulation += percentageChangeOfAccumulation.GetValueOrDefault(attributeName, 0f);
|
||||
pMultiplication *= percentageChangeOfMultiplication.GetValueOrDefault(attributeName, 1f);
|
||||
}
|
||||
|
||||
private float GetUpgradeNumericValue(string attributeName)
|
||||
{
|
||||
if (_upgradeData == null || level == 0) return 0f;
|
||||
|
||||
foreach (var upgradeInfo in _upgradeData.upgrades)
|
||||
{
|
||||
if (upgradeInfo.attributeKey == attributeName)
|
||||
{
|
||||
return upgradeInfo.GetValue(level);
|
||||
}
|
||||
}
|
||||
return 0f;
|
||||
}
|
||||
|
||||
public List<string> RefreshAllModifiedAttributes()
|
||||
{
|
||||
@@ -37,7 +67,13 @@ namespace Cielonos.MainGame.Characters.Inventory
|
||||
modifiedAttributes.AddRange(numericChange.Select(kvp => kvp.Key));
|
||||
modifiedAttributes.AddRange(percentageChangeOfAccumulation.Select(kvp => kvp.Key));
|
||||
modifiedAttributes.AddRange(percentageChangeOfMultiplication.Select(kvp => kvp.Key));
|
||||
|
||||
|
||||
if (_upgradeData != null)
|
||||
{
|
||||
modifiedAttributes.AddRange(_upgradeData.upgrades.Select(u => u.attributeKey));
|
||||
}
|
||||
|
||||
modifiedAttributes = modifiedAttributes.Distinct().ToList();
|
||||
modifiedAttributes.ForEach(attr => owner.player.attributeSm.RefreshAttribute(attr));
|
||||
|
||||
return modifiedAttributes;
|
||||
|
||||
@@ -23,10 +23,24 @@ namespace Cielonos.MainGame.Characters.Inventory
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
if (owner?.player != null)
|
||||
_timeProvider = new CharacterFeedbackTimeProvider(owner.player);
|
||||
}
|
||||
|
||||
public FeedbackData GetFeedbackData(string feedbackName)
|
||||
{
|
||||
if (feedbackDataCollection == null)
|
||||
{
|
||||
_timeProvider = new CharacterFeedbackTimeProvider(owner.player);
|
||||
Debug.LogWarning($"[Item.FeedbackSubcontroller] feedbackDataCollection is null on {owner?.name}.");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!feedbackDataCollection.TryGet(feedbackName, out FeedbackData data))
|
||||
{
|
||||
Debug.LogWarning($"[Item.FeedbackSubcontroller] FeedbackData '{feedbackName}' not found on {owner?.name}.");
|
||||
return null;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -109,7 +123,7 @@ namespace Cielonos.MainGame.Characters.Inventory
|
||||
}
|
||||
|
||||
// 新系统驱动
|
||||
float dt = Time.unscaledDeltaTime;
|
||||
float dt = Time.deltaTime;
|
||||
for (int i = _activePlayers.Count - 1; i >= 0; i--)
|
||||
{
|
||||
FeedbackPlayer player = _activePlayers[i];
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
using System;
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Cielonos.MainGame.Characters.Inventory
|
||||
{
|
||||
public class OverloadSubmodule : SubmoduleBase<ItemBase>
|
||||
{
|
||||
public float maximumOverload;
|
||||
public float currentOverload;
|
||||
public float minimumCooldown;
|
||||
public float cooldownTimer;
|
||||
[ShowInInspector]
|
||||
public float currentWeight => cooldownTimer > 0f ? 0f : owner.overloadData.overloadWeight;
|
||||
|
||||
[HideInInspector]
|
||||
public Action OnTriggered;
|
||||
public OverloadSubmodule(ItemBase owner, OverloadData data) : base(owner)
|
||||
{
|
||||
this.maximumOverload = data.maxOverload;
|
||||
this.minimumCooldown = data.triggerCooldown;
|
||||
}
|
||||
|
||||
public void Update(float deltaTime)
|
||||
{
|
||||
if (cooldownTimer > 0f)
|
||||
{
|
||||
cooldownTimer -= deltaTime;
|
||||
if (cooldownTimer <= 0f)
|
||||
{
|
||||
cooldownTimer = 0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ReceiveEnergy(float amount)
|
||||
{
|
||||
if (cooldownTimer > 0f) return;
|
||||
|
||||
currentOverload += amount;
|
||||
|
||||
if (currentOverload >= maximumOverload)
|
||||
{
|
||||
currentOverload = 0f; // 清空能量
|
||||
cooldownTimer = minimumCooldown; // 开始冷却
|
||||
OnTriggered?.Invoke(); // 触发监听件
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 78c68ec19d139584b86cb8f01cd86c10
|
||||
@@ -53,6 +53,10 @@ namespace Cielonos.MainGame.Characters
|
||||
eventSm.onAfterGetAttacked.InsertByPriority("Feedback_GetAttacked", new PrioritizedAction<AttackAreaBase, AttackResult>(Feedback_GetAttacked));
|
||||
eventSm.onHealthChanged.InsertByPriority("UI_HealthBarUpdate", new PrioritizedAction<float>(UI_HealthBarUpdate));
|
||||
eventSm.onEnergyChanged.InsertByPriority("UI_EnergyBarUpdate", new PrioritizedAction<float>(UI_EnergyBarUpdate));
|
||||
|
||||
eventSm.onDodgeStart.InsertByPriority("Feedback_DodgeStart", new PrioritizedAction(() => { feedbackSc.PlayFeedback("PerfectDodge"); }));
|
||||
eventSm.onNormalDodgeSuccess.InsertByPriority("Feedback_NormalDodge", new PrioritizedAction<AttackAreaBase, DodgeSource>(Feedback_NormalDodge));
|
||||
eventSm.onPerfectDodgeSuccess.InsertByPriority("Feedback_PerfectDodge", new PrioritizedAction<AttackAreaBase, DodgeSource>(Feedback_PerfectDodge));
|
||||
}
|
||||
|
||||
protected override void InitializeSubcontrollers()
|
||||
@@ -118,5 +122,15 @@ namespace Cielonos.MainGame.Characters
|
||||
float intensity = Mathf.Lerp(0.25f, 1f, ratio);
|
||||
feedbackSc["GetAttacked"]?.Play();
|
||||
}
|
||||
|
||||
private void Feedback_PerfectDodge(AttackAreaBase attackArea, DodgeSource dodgeSource)
|
||||
{
|
||||
feedbackSc.PlayFeedback("PerfectDodge");
|
||||
}
|
||||
|
||||
private void Feedback_NormalDodge(AttackAreaBase attackArea, DodgeSource dodgeSource)
|
||||
{
|
||||
feedbackSc.PlayFeedback("NormalDodge");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using Cielonos.MainGame.UI;
|
||||
using SLSUtilities.General;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Cielonos.MainGame.Characters
|
||||
@@ -12,7 +13,7 @@ namespace Cielonos.MainGame.Characters
|
||||
{
|
||||
private void Regeneration()
|
||||
{
|
||||
float healthRegenRate = attributeSm["HealthRegen"] * deltaTime;
|
||||
float healthRegenRate = attributeSm["HealthRegeneration"] * deltaTime;
|
||||
|
||||
if (healthRegenRate != 0)
|
||||
{
|
||||
@@ -21,13 +22,87 @@ namespace Cielonos.MainGame.Characters
|
||||
PlayerCanvas.Instance.playerInfoUIArea.UpdateHealth(true);
|
||||
}
|
||||
|
||||
float energyRegenRate = attributeSm["EnergyRegen"] * deltaTime;
|
||||
|
||||
float energyRegenRate = attributeSm["EnergyRegeneration"] * deltaTime;
|
||||
if (energyRegenRate != 0)
|
||||
{
|
||||
attributeSm["Energy"] += energyRegenRate;
|
||||
attributeSm["Energy"] = Mathf.Min(attributeSm["Energy"], attributeSm["MaximumEnergy"]);
|
||||
PlayerCanvas.Instance.playerInfoUIArea.UpdateEnergy(true);
|
||||
AddEnergy(energyRegenRate);
|
||||
}
|
||||
}
|
||||
|
||||
public void AddEnergy(float amount)
|
||||
{
|
||||
if (amount == 0) return;
|
||||
|
||||
if (amount > 0)
|
||||
{
|
||||
float current = attributeSm["Energy"];
|
||||
float max = attributeSm["MaximumEnergy"];
|
||||
float availableSpace = max - current;
|
||||
|
||||
if (amount > availableSpace)
|
||||
{
|
||||
attributeSm["Energy"] = max;
|
||||
|
||||
float conversionRate = attributeSm.Has("OverloadConversionRate") ? attributeSm["OverloadConversionRate"] : 1f;
|
||||
float overflowEnergy = (amount - availableSpace) * conversionRate;
|
||||
DistributeOverloadEnergy(overflowEnergy);
|
||||
}
|
||||
else
|
||||
{
|
||||
attributeSm["Energy"] += amount;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
attributeSm["Energy"] += amount;
|
||||
attributeSm["Energy"] = Mathf.Max(0, attributeSm["Energy"]);
|
||||
}
|
||||
|
||||
PlayerCanvas.Instance.playerInfoUIArea.UpdateEnergy(true);
|
||||
eventSm.onEnergyChanged.Invoke(amount);
|
||||
}
|
||||
|
||||
private void DistributeOverloadEnergy(float totalOverflowAmount)
|
||||
{
|
||||
if (totalOverflowAmount <= 0) return;
|
||||
|
||||
var overloadSubmodules = new System.Collections.Generic.List<Inventory.OverloadSubmodule>();
|
||||
|
||||
if (inventorySc.equipmentSm.currentMainWeapon?.overloadSm != null)
|
||||
{
|
||||
overloadSubmodules.Add(inventorySc.equipmentSm.currentMainWeapon.overloadSm);
|
||||
}
|
||||
|
||||
foreach (var equip in inventorySc.equipmentSm.currentSupportEquipments)
|
||||
{
|
||||
if (equip?.overloadSm != null)
|
||||
{
|
||||
overloadSubmodules.Add(equip.overloadSm);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var equip in inventorySc.backpack.passiveEquipments)
|
||||
{
|
||||
if (equip?.overloadSm != null)
|
||||
{
|
||||
overloadSubmodules.Add(equip.overloadSm);
|
||||
}
|
||||
}
|
||||
|
||||
if (overloadSubmodules.Count == 0) return;
|
||||
|
||||
float totalWeight = 0;
|
||||
foreach (var sm in overloadSubmodules)
|
||||
{
|
||||
totalWeight += sm.currentWeight;
|
||||
}
|
||||
|
||||
if (totalWeight <= 0) return;
|
||||
|
||||
foreach (var sm in overloadSubmodules)
|
||||
{
|
||||
float assignedAmount = totalOverflowAmount * (sm.currentWeight / totalWeight);
|
||||
sm.ReceiveEnergy(assignedAmount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -238,13 +238,22 @@ namespace Cielonos.MainGame.Characters
|
||||
isJumping = true;
|
||||
gravitationalMovement = Vector3.zero;
|
||||
}
|
||||
|
||||
|
||||
protected override void UpdateFinalMovement()
|
||||
{
|
||||
base.UpdateFinalMovement();
|
||||
float horizontalSpeed = horizontalMovement.magnitude / DeltaTime;
|
||||
float remapFactor = Mathf.InverseLerp(10f, 15f, horizontalSpeed);
|
||||
PostProcessingManager.Instance.speedLinesSm.SetRemap(1 - remapFactor);
|
||||
|
||||
if (!isDashing && !isDodging)
|
||||
{
|
||||
PostProcessingManager.Instance.speedLinesSm.remap.IsPausing = false;
|
||||
float horizontalSpeed = horizontalMovement.magnitude / DeltaTime;
|
||||
float remapFactor = Mathf.InverseLerp(10f, 15f, horizontalSpeed);
|
||||
PostProcessingManager.Instance.speedLinesSm.SetRemap(1 - remapFactor);
|
||||
}
|
||||
else
|
||||
{
|
||||
PostProcessingManager.Instance.speedLinesSm.remap.IsPausing = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user