Passion & UI
This commit is contained in:
@@ -18,11 +18,15 @@ namespace Cielonos.MainGame.Inventory.Collections
|
||||
{
|
||||
base.OnEquipped();
|
||||
RegisterFunctionsToAnimSc();
|
||||
if(!player.inputSc.IsMoving) PlayTargetedAnimation("Equip");
|
||||
viewObjects["Wand"].SetFadeAnim(0.5f);
|
||||
//PlayerCanvas.MainWeaponUIArea.displayer.SetFrameOutline(1);
|
||||
}
|
||||
|
||||
|
||||
public override void OnSwitchIn()
|
||||
{
|
||||
if(!player.inputSc.IsMoving) PlayTargetedAnimation("Equip");
|
||||
}
|
||||
|
||||
public override void OnPrimaryPress()
|
||||
{
|
||||
if (!_isHoldingAttack && player.inputSc.IsHoldingSpecialA)
|
||||
|
||||
@@ -1,664 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using ChocDino.UIFX;
|
||||
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;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Cielonos.MainGame.Inventory.Collections
|
||||
{
|
||||
public partial class Polychrome : MainWeaponBase
|
||||
{
|
||||
public float techniqueScore;
|
||||
private PolychromeExtraUIContainer ExtraUIContainer => extraUIContainer as PolychromeExtraUIContainer;
|
||||
|
||||
private bool _canAirLightAttack;
|
||||
private bool _canAirHeavyAttack;
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
if (player.inventorySc.equipmentSm.currentMainWeapon == this)
|
||||
{
|
||||
functionSm?.Update(player.selfTimeSm.DeltaTime);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnEquipped()
|
||||
{
|
||||
base.OnEquipped();
|
||||
|
||||
extraUIContainer = Instantiate(extraUIContainerPrefab, PlayerCanvas.MainWeaponUIArea.transform).GetComponent<MainWeaponExtraUIContainer>();
|
||||
extraUIContainer.mainWeapon = this;
|
||||
_currentKatanaParticle = string.Empty;
|
||||
|
||||
player.eventSm.onFirstJump.TryAdd(nameof(Polychrome), new PrioritizedAction(() =>
|
||||
{
|
||||
_canAirLightAttack = true;
|
||||
_canAirHeavyAttack = true;
|
||||
comboSm["AirLight"].Reset();
|
||||
}));
|
||||
|
||||
player.eventSm.onAfterGetAttacked.TryAdd(nameof(Polychrome), new PrioritizedAction<AttackAreaBase, Attack.Result>((_, _) =>
|
||||
{
|
||||
ModifyTechniqueScore(-0.2f);
|
||||
}));
|
||||
|
||||
RegisterFunctionsToAnimSc(StayBlocking);
|
||||
viewObjects["Katana"].SetFadeAnim(0.2f);
|
||||
viewObjects["Saya"].SetFadeAnim(0.2f);
|
||||
|
||||
PlayTargetedAnimation("EquipBlock");
|
||||
SetBlock(equipBlockData);
|
||||
player.selfTimeSm.AddLocalTimer(0.4f, () =>
|
||||
{
|
||||
RemoveBlock(equipBlockData);
|
||||
fullBodyFuncAnimSm.Stop("EquipBlock");
|
||||
});
|
||||
}
|
||||
|
||||
public override void OnUnequipped()
|
||||
{
|
||||
base.OnUnequipped();
|
||||
Destroy(extraUIContainer.gameObject);
|
||||
ClearTechniqueScore();
|
||||
player.eventSm.onFirstJump.Remove(nameof(Polychrome));
|
||||
player.eventSm.onAfterGetAttacked.Remove(nameof(Polychrome));
|
||||
}
|
||||
|
||||
|
||||
public override void OnPrimaryPress()
|
||||
{
|
||||
if (player.statusSm.HasStatus(StatusType.Stun))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (player.reactionSc.blockSm.HaveBlockSource(blockData.blockName))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (player.landMovementSc.isJumping)
|
||||
{
|
||||
if (!_canAirLightAttack || !functionSm["LightAttack"].IsAvailable())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (PlayTargetedAnimation("AirAttack" + comboSm["AirLight"].GetNextNodeName("L")))
|
||||
{
|
||||
comboSm["AirLight"].NextCombo("L");
|
||||
functionSm["LightAttack"].Execute();
|
||||
|
||||
if (comboSm["AirLight"].GetCurrentNodeName() == "L1")
|
||||
{
|
||||
_canAirLightAttack = false;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*if (player.inputSc.IsHoldingSpecialA && functionSm["LightAttack"].IsAvailable())
|
||||
{
|
||||
CharacterBase target = CombatManager.EnemySm.GetBestEnemy(5);
|
||||
if (PlayTargetedAnimation("AttackRC", target, 1f, true))
|
||||
{
|
||||
comboSm.main.NextCombo("L");
|
||||
functionSm["LightAttack"].Execute();
|
||||
}
|
||||
return;
|
||||
}*/
|
||||
|
||||
if (player.landMovementSc.isSprinting && functionSm["LightAttack"].IsAvailable() && fullBodyFuncAnimSm.CheckPlayability())
|
||||
{
|
||||
comboSm.main.Reset();
|
||||
functionSm["LightAttack"].Execute();
|
||||
CharacterBase target = CombatManager.EnemySm.GetBestEnemy(8);
|
||||
PlayTargetedAnimation("RunAttack", target);
|
||||
comboSm.main.NextCombo("L");
|
||||
return;
|
||||
}
|
||||
|
||||
if (functionSm["LightAttack"].IsAvailable())
|
||||
{
|
||||
CharacterBase target = CombatManager.EnemySm.GetBestEnemy(5);
|
||||
string nextNodeName = comboSm.main.GetNextNodeName("L");
|
||||
bool keepAdsorption = nextNodeName is "L4" or "L5";
|
||||
if (PlayTargetedAnimation("Attack" + comboSm.main.GetNextNodeName("L"), target, 1f, keepAdsorption))
|
||||
{
|
||||
float totalTime = 0f;
|
||||
CombatManager.EnemySm.activeEnemiesList.ForEach(enemy =>
|
||||
{
|
||||
(enemy as Enemy).behaviorSc.DispatchContextEvent("PlayerLightAttack", totalTime);
|
||||
});
|
||||
|
||||
comboSm.main.NextCombo("L");
|
||||
functionSm["LightAttack"].Execute();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnSecondaryPress()
|
||||
{
|
||||
if (player.statusSm.HasStatus(StatusType.Stun))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
List<Enemy> availableEnemies = CombatManager.EnemySm.GetEnemiesInRadius(player.transform.position, 4);
|
||||
BlockSubmodule blockSm = player.reactionSc.blockSm;
|
||||
if (!blockSm.afterPerfectBlockTimer.isCompleted)
|
||||
{
|
||||
Enemy blockedTarget = blockSm.perfectBlockedTarget as Enemy;
|
||||
bool successPlayed;
|
||||
if (blockedTarget != null && !availableEnemies.Contains(blockedTarget))
|
||||
{
|
||||
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");
|
||||
}
|
||||
|
||||
if(successPlayed)
|
||||
{
|
||||
blockSm.afterPerfectBlockTimer.Complete();
|
||||
RemoveBlock();
|
||||
}
|
||||
}
|
||||
|
||||
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))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (player.landMovementSc.isJumping)
|
||||
{
|
||||
if (!_canAirHeavyAttack || !functionSm["HeavyAttack"].IsAvailable())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (PlayTargetedAnimation("AirAttackRStart"))
|
||||
{
|
||||
player.landMovementSc.ExtraJump(10f);
|
||||
comboSm.main.Reset();
|
||||
functionSm["HeavyAttack"].Execute();
|
||||
_canAirLightAttack = false;
|
||||
_canAirHeavyAttack = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (player.inputSc.IsHoldingSpecialA)
|
||||
{
|
||||
if (functionSm["DisruptionAttack"].IsAvailable())
|
||||
{
|
||||
string suffix = techniqueScore switch
|
||||
{
|
||||
< 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)
|
||||
{
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (functionSm["HeavyAttack"].IsAvailable())
|
||||
{
|
||||
Enemy target = CombatManager.EnemySm.GetBestEnemy(availableEnemies);
|
||||
string nextNodeName = comboSm.main.GetNextNodeName("R");
|
||||
bool keepAdsorption = nextNodeName is "RC";
|
||||
if (PlayTargetedAnimation("Attack" + nextNodeName, target, 1f, keepAdsorption))
|
||||
{
|
||||
float totalTime = fullBodyFuncAnimSm.GetIntervalScaledDuration(IntervalType.Startup) - 0.2f;
|
||||
CombatManager.EnemySm.activeEnemiesList.ForEach(enemy =>
|
||||
{
|
||||
(enemy as Enemy)!.behaviorSc.DispatchContextEvent("PlayerHeavyAttack", totalTime);
|
||||
});
|
||||
comboSm.main.NextCombo("R");
|
||||
functionSm["HeavyAttack"].Execute();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnSpecialCPress()
|
||||
{
|
||||
comboSm.main.Reset();
|
||||
SetBlock();
|
||||
|
||||
if (!player.statusSm.HasStatus(StatusType.Stun))
|
||||
{
|
||||
CharacterBase target = CombatManager.EnemySm.GetBestEnemy(5);
|
||||
if (fullBodyFuncAnimSm.Stop(DisruptionType.ForcedAction))
|
||||
{
|
||||
PlayTargetedAnimation("Block", target, 2f, false, true, upperBodyFuncAnimSm, 1f, 0.1f, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnSpecialCRelease()
|
||||
{
|
||||
if (upperBodyFuncAnimSm.currentRuntimeFuncAnim is { animationName: "Block" })
|
||||
{
|
||||
upperBodyFuncAnimSm.Stop(DisruptionType.ForcedAction);
|
||||
}
|
||||
|
||||
player.selfTimeSm.AddLocalTimer(0.04f, () => RemoveBlock());
|
||||
}
|
||||
|
||||
public override void OnSpecialBPress()
|
||||
{
|
||||
//测试完美格挡和完美闪避
|
||||
|
||||
/*SetBlock();
|
||||
player.reactionSc.blockSm.GetCurrentBlockSource().PerfectBlock(null, player.centerPosition);
|
||||
RemoveBlock();*/
|
||||
|
||||
player.operationSc.Dodge();
|
||||
DodgeSource defaultDodge = DodgeSource.Default(player);
|
||||
player.reactionSc.dodgeSm.ApplyDodge(defaultDodge);
|
||||
player.reactionSc.dodgeSm.GetCurrentDodgeSource().PerfectDodge(null);
|
||||
player.reactionSc.dodgeSm.RemoveDodge("DefaultDodge");
|
||||
}
|
||||
}
|
||||
|
||||
public partial class Polychrome
|
||||
{
|
||||
private void FAPF_GenerateNormalSlash(RuntimeFuncAnim rtFuncAnim)
|
||||
{
|
||||
CustomFunction.PC_StringString p = rtFuncAnim.GetParams<CustomFunction.PC_StringString>();
|
||||
string hitFeedback = p.str1 switch
|
||||
{
|
||||
"ProbingAttack" => "SingleNormalHit",
|
||||
_ => "MultiNormalHit"
|
||||
};
|
||||
GenerateNormalSlash(p.str0, attackData[p.str1], hitFeedback);
|
||||
}
|
||||
|
||||
private void FAPF_GenerateAirNormalSlash(RuntimeFuncAnim rtFuncAnim)
|
||||
{
|
||||
CustomFunction.PC_StringString p = rtFuncAnim.GetParams<CustomFunction.PC_StringString>();
|
||||
GenerateNormalSlash(p.str0, attackData[p.str1], "SingleNormalHit");
|
||||
}
|
||||
|
||||
private void FAPF_GenerateHeavySlash(RuntimeFuncAnim rtFuncAnim)
|
||||
{
|
||||
CustomFunction.PC_StringString p = rtFuncAnim.GetParams<CustomFunction.PC_StringString>();
|
||||
GenerateHeavySlash(p.str0, attackData[p.str1]);
|
||||
}
|
||||
|
||||
private void FAPF_GenerateUltimateSlash(RuntimeFuncAnim rtFuncAnim)
|
||||
{
|
||||
CustomFunction.PC_StringString p = rtFuncAnim.GetParams<CustomFunction.PC_StringString>();
|
||||
GenerateUltimateSlash(p.str0, attackData[p.str1]);
|
||||
}
|
||||
|
||||
private void FAPF_GenerateDisruptionSlash(RuntimeFuncAnim rtFuncAnim)
|
||||
{
|
||||
CustomFunction.PC_StringString p = rtFuncAnim.GetParams<CustomFunction.PC_StringString>();
|
||||
GenerateDisruptionSlash(p.str0, attackData[p.str1]);
|
||||
}
|
||||
|
||||
private void FAPF_GenerateMovingSlash(RuntimeFuncAnim rtFuncAnim)
|
||||
{
|
||||
CustomFunction.PC_StringString p = rtFuncAnim.GetParams<CustomFunction.PC_StringString>();
|
||||
GenerateDisruptionSlash(p.str0, attackData[p.str1]);
|
||||
}
|
||||
}
|
||||
|
||||
public partial class Polychrome
|
||||
{
|
||||
private NormalArea GenerateNormalSlash(string vfxName, AttackUnit attackUnit, string hitFeedback)
|
||||
{
|
||||
NormalArea slash = vfxData.SpawnVFX(vfxName, player).GetComponentInChildren<NormalArea>();
|
||||
|
||||
slash.Initialize<NormalArea>(player, this, Fraction.Enemy)
|
||||
.SetAttackSubmodule<NormalArea>(attackUnit)
|
||||
.SetTimeSubmodule<NormalArea>(1f, 0.02f)
|
||||
.SetHitSubmodule<NormalArea>();
|
||||
slash.SetImpulseSubmodule().WithRepulsion(2f);
|
||||
|
||||
slash.attackSm.breakthroughAction = (enemy, hitPosition) =>
|
||||
{
|
||||
AudioManager.Post(AK.EVENTS.DISRUPT, hitPosition);
|
||||
};
|
||||
|
||||
slash.hitSm.AddHitSound(AK.EVENTS.POLYCHROME_LIGHTATTACKHIT)
|
||||
.AddHitEvent((enemy, hitPosition) =>
|
||||
{
|
||||
var positionShakeAction = feedbackSc.GetFeedbackData(hitFeedback).Action<CameraPositionShakeAction>("Camera");
|
||||
float magnitude = hitFeedback == "SingleNormalHit" ? 0.12f : 0.06f;
|
||||
positionShakeAction.amplitude = vfxData.Get(vfxName).slashScreenPosition.normalized * magnitude;
|
||||
feedbackSc.PlayFeedback(hitFeedback);
|
||||
|
||||
ModifyTechniqueScore(0.02f);
|
||||
/*if (attackUnit.unitName == "InstantAttack")
|
||||
{
|
||||
if (enemy.buffSm.HasBuff<ElectronicParalysis>())
|
||||
{
|
||||
slash.attackSm.attackValue.damage *= 2f;
|
||||
}
|
||||
}*/
|
||||
});
|
||||
|
||||
return slash;
|
||||
}
|
||||
|
||||
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.SetImpulseSubmodule(1f).WithRepulsion(5f);
|
||||
|
||||
slash.attackSm.breakthroughAction = (enemy, hitPosition) =>
|
||||
{
|
||||
ModifyTechniqueScore(0.2f);
|
||||
AudioManager.Post(AK.EVENTS.DISRUPT, hitPosition);
|
||||
};
|
||||
|
||||
slash.hitSm.AddHitSound(AK.EVENTS.POLYCHROME_HEAVYATTACKLHIT)
|
||||
.AddHitEvent((enemy, hitPosition) =>
|
||||
{
|
||||
var positionShakeAction = feedbackSc.GetFeedbackData("HeavyHit").Action<CameraPositionShakeAction>("Camera");
|
||||
positionShakeAction.amplitude = vfxData.Get(vfxName).slashScreenPosition.normalized * 0.18f;
|
||||
feedbackSc.PlayFeedback("HeavyHit");
|
||||
|
||||
ModifyTechniqueScore(0.05f);
|
||||
});
|
||||
|
||||
return slash;
|
||||
}
|
||||
|
||||
private NormalArea GenerateDisruptionSlash(string vfxName, AttackUnit attackUnit)
|
||||
{
|
||||
NormalArea slash = vfxData.SpawnVFX(vfxName, player).GetComponentInChildren<NormalArea>();
|
||||
|
||||
slash.Initialize<NormalArea>(player, this, Fraction.Enemy)
|
||||
.SetAttackSubmodule<NormalArea>(attackUnit)
|
||||
.SetTimeSubmodule<NormalArea>(1f, 0.04f)
|
||||
.SetHitSubmodule<NormalArea>();
|
||||
slash.SetImpulseSubmodule().WithRepulsion(5f);
|
||||
|
||||
slash.attackSm.breakthroughAction = (enemy, hitPosition) =>
|
||||
{
|
||||
ModifyTechniqueScore(0.2f);
|
||||
feedbackSc.PlayFeedback("Breakthrough");
|
||||
AudioManager.Post(AK.EVENTS.DISRUPT, hitPosition);
|
||||
};
|
||||
|
||||
slash.hitSm
|
||||
.AddHitSound(AK.EVENTS.POLYCHROME_HEAVYATTACKLHIT)
|
||||
.AddHitEvent((enemy, hitPosition) =>
|
||||
{
|
||||
var positionShakeAction = feedbackSc.GetFeedbackData("HeavyHit").Action<CameraPositionShakeAction>("Camera");
|
||||
positionShakeAction.amplitude = vfxData.Get(vfxName).slashScreenPosition.normalized * 0.18f;
|
||||
feedbackSc.PlayFeedback("HeavyHit");
|
||||
});
|
||||
return slash;
|
||||
}
|
||||
|
||||
private NormalArea GenerateUltimateSlash(string vfxName, AttackUnit attackUnit)
|
||||
{
|
||||
NormalArea slash = vfxData.SpawnVFX(vfxName, player).GetComponentInChildren<NormalArea>();
|
||||
|
||||
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) =>
|
||||
{
|
||||
AudioManager.Post(AK.EVENTS.DISRUPT, hitPosition);
|
||||
};
|
||||
|
||||
slash.hitSm.AddHitSound(AK.EVENTS.POLYCHROME_HEAVYATTACKLHIT)
|
||||
.AddHitEvent((enemy, hitPosition) =>
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
public partial class Polychrome
|
||||
{
|
||||
public BlockData equipBlockData;
|
||||
private string _blockAnimName = "BlockL";
|
||||
|
||||
private void SetBlock(BlockData blockData = null)
|
||||
{
|
||||
blockData ??= this.blockData;
|
||||
BlockSource blockSource = blockData.CreateBlockSource(player, this);
|
||||
player.landMovementSc.canDash = false;
|
||||
player.landMovementSc.canDodge = false;
|
||||
|
||||
blockSource.onNormalBlock = (attackArea) =>
|
||||
{
|
||||
_blockAnimName = _blockAnimName == "BlockL" ? "BlockR" : "BlockL";
|
||||
animationSc.fullBodyFuncAnimSm.Play(_blockAnimName, 1, 0);
|
||||
|
||||
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)
|
||||
{
|
||||
ModifyTechniqueScore(-0.1f);
|
||||
}
|
||||
};
|
||||
|
||||
blockSource.onPerfectBlock = (attackArea) =>
|
||||
{
|
||||
_blockAnimName = _blockAnimName == "BlockL" ? "BlockR" : "BlockL";
|
||||
animationSc.fullBodyFuncAnimSm.Play(_blockAnimName, 1, 0);
|
||||
|
||||
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)
|
||||
{
|
||||
ModifyTechniqueScore(0.2f);
|
||||
if (HasExtender<PhotonPolarizer>())
|
||||
{
|
||||
attackArea.creator.GetHit(Breakthrough.Type.Forced, out _);
|
||||
attackArea.creator.movementSc.impulseSm.ApplyKnockback(player.transform.forward, 6f);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
player.reactionSc.blockSm.ApplyBlock(blockSource);
|
||||
}
|
||||
|
||||
private void StayBlocking()
|
||||
{
|
||||
if (player.inputSc.IsHoldingSpecialB)
|
||||
{
|
||||
player.movementSc.canMove.Modify(true);
|
||||
player.movementSc.canRotate.Modify(true);
|
||||
OnSpecialBPress();
|
||||
}
|
||||
}
|
||||
|
||||
private void RemoveBlock(BlockData blockData = null)
|
||||
{
|
||||
blockData ??= this.blockData;
|
||||
player.landMovementSc.canDash = true;
|
||||
player.landMovementSc.canDodge = true;
|
||||
player.reactionSc.blockSm.RemoveBlock(blockData.blockName);
|
||||
}
|
||||
}
|
||||
|
||||
public partial class Polychrome
|
||||
{
|
||||
private string _currentKatanaParticle;
|
||||
|
||||
/// <summary>
|
||||
/// 清空技巧分数
|
||||
/// </summary>
|
||||
private void ClearTechniqueScore()
|
||||
{
|
||||
techniqueScore = 0;
|
||||
UpdateTechniqueVisuals();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 增减技巧分数(0~3),当减少时不会扣除整数部分
|
||||
/// </summary>
|
||||
private void ModifyTechniqueScore(float amount, bool protectInteger = true)
|
||||
{
|
||||
if (amount > 0)
|
||||
{
|
||||
techniqueScore = Mathf.Clamp(techniqueScore + amount, 0, 5);
|
||||
}
|
||||
else
|
||||
{
|
||||
float floor = Mathf.Floor(techniqueScore);
|
||||
if (protectInteger)
|
||||
{
|
||||
techniqueScore = Mathf.Max(techniqueScore + amount, floor);
|
||||
}
|
||||
else
|
||||
{
|
||||
techniqueScore = Mathf.Max(techniqueScore + amount, 0);
|
||||
}
|
||||
}
|
||||
|
||||
UpdateTechniqueVisuals();
|
||||
}
|
||||
|
||||
private void UpdateTechniqueVisuals()
|
||||
{
|
||||
//开关粒子特效
|
||||
if (techniqueScore < 1)
|
||||
{
|
||||
if (_currentKatanaParticle != string.Empty)
|
||||
{
|
||||
viewObjects["Katana"].functionalParts[_currentKatanaParticle].GetComponent<ParticleSystem>().Stop();
|
||||
_currentKatanaParticle = string.Empty;
|
||||
//PlayerCanvas.MainWeaponUIArea.displayer.frame.GetComponent<GlowFilter>().Strength = 0f;
|
||||
}
|
||||
}
|
||||
else if (techniqueScore >= 1 && techniqueScore < 3)
|
||||
{
|
||||
if (_currentKatanaParticle != "ParticleStage0")
|
||||
{
|
||||
if (_currentKatanaParticle != string.Empty)
|
||||
{
|
||||
viewObjects["Katana"].functionalParts[_currentKatanaParticle].GetComponent<ParticleSystem>().Stop();
|
||||
}
|
||||
_currentKatanaParticle = "ParticleStage0";
|
||||
viewObjects["Katana"].functionalParts[_currentKatanaParticle].GetComponent<ParticleSystem>().Play();
|
||||
//PlayerCanvas.MainWeaponUIArea.displayer.frame.GetComponent<GlowFilter>().Strength = 0.3f;
|
||||
}
|
||||
}
|
||||
else if (techniqueScore >= 3)
|
||||
{
|
||||
if (_currentKatanaParticle != "ParticleStage1")
|
||||
{
|
||||
if (_currentKatanaParticle != string.Empty)
|
||||
{
|
||||
viewObjects["Katana"].functionalParts[_currentKatanaParticle].GetComponent<ParticleSystem>().Stop();
|
||||
}
|
||||
_currentKatanaParticle = "ParticleStage1";
|
||||
viewObjects["Katana"].functionalParts[_currentKatanaParticle].GetComponent<ParticleSystem>().Play();
|
||||
//PlayerCanvas.MainWeaponUIArea.displayer.frame.GetComponent<GlowFilter>().Strength = 0.5f;
|
||||
}
|
||||
}
|
||||
|
||||
//设置UI星星数量
|
||||
ExtraUIContainer.SetStars(Mathf.FloorToInt(techniqueScore));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cf9abeac90b4c334b91136fbc464e06d
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,418 @@
|
||||
using System.Collections.Generic;
|
||||
using ChocDino.UIFX;
|
||||
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;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Cielonos.MainGame.Inventory.Collections
|
||||
{
|
||||
public partial class Polychrome : MainWeaponBase
|
||||
{
|
||||
private PassionSystem _passionSystem;
|
||||
|
||||
private bool _canAirLightAttack;
|
||||
private bool _canAirHeavyAttack;
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
if (player.inventorySc.equipmentSm.currentMainWeapon == this)
|
||||
{
|
||||
functionSm?.Update(player.selfTimeSm.DeltaTime);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnEquipped()
|
||||
{
|
||||
base.OnEquipped();
|
||||
|
||||
_currentKatanaParticle = string.Empty;
|
||||
|
||||
player.eventSm.onFirstJump.TryAdd(nameof(Polychrome), new PrioritizedAction(() =>
|
||||
{
|
||||
_canAirLightAttack = true;
|
||||
_canAirHeavyAttack = true;
|
||||
comboSm["AirLight"].Reset();
|
||||
}));
|
||||
|
||||
_passionSystem = CombatManager.GetCombatSystem<PassionSystem>();
|
||||
_passionSystem.OnLevelChanged += OnPassionLevelChanged;
|
||||
|
||||
RegisterFunctionsToAnimSc(StayBlocking);
|
||||
viewObjects["Katana"].SetFadeAnim(0.2f);
|
||||
viewObjects["Saya"].SetFadeAnim(0.2f);
|
||||
|
||||
UpdateViewObjectVisuals();
|
||||
}
|
||||
|
||||
public override void OnUnequipped()
|
||||
{
|
||||
base.OnUnequipped();
|
||||
_passionSystem.OnLevelChanged -= OnPassionLevelChanged;
|
||||
player.eventSm.onFirstJump.Remove(nameof(Polychrome));
|
||||
}
|
||||
|
||||
private void OnPassionLevelChanged(int oldLevel, int newLevel)
|
||||
{
|
||||
UpdateViewObjectVisuals();
|
||||
}
|
||||
|
||||
public override void OnSwitchIn()
|
||||
{
|
||||
if (_passionSystem.LevelIndex >= 3)
|
||||
{
|
||||
List<Enemy> availableEnemies = CombatManager.EnemySm.GetEnemiesInRadius(player.transform.position, 4);
|
||||
List<Enemy> disruptable = CombatManager.EnemySm.GetDisruptableEnemies(availableEnemies);
|
||||
Enemy target = CombatManager.EnemySm.GetScoredEnemies(availableEnemies)
|
||||
.ApplyScoreModifier(disruptable, 0f, 1f).BestEnemy();
|
||||
|
||||
if (PlayTargetedAnimation("DisruptionAttackB", target))
|
||||
{
|
||||
FeedbackClip timeScaleModifierClip = player.feedbackSc.GetFeedbackData("DisruptionStartup")
|
||||
.Clip<TimeScaleModifierAction>("Time");
|
||||
float duration = fullBodyFuncAnimSm.collection["DisruptionAttackB"]
|
||||
.Interval(IntervalType.Startup).Duration * 2;
|
||||
|
||||
timeScaleModifierClip.duration = duration;
|
||||
player.feedbackSc.PlayFeedback("DisruptionStartup");
|
||||
comboSm.main.Reset();
|
||||
_passionSystem.DecreasePassion(100, false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PlayTargetedAnimation("EquipBlock");
|
||||
SetBlock(equipBlockData);
|
||||
player.selfTimeSm.AddLocalTimer(0.4f, () =>
|
||||
{
|
||||
RemoveBlock(equipBlockData);
|
||||
fullBodyFuncAnimSm.Stop("EquipBlock");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnPrimaryPress()
|
||||
{
|
||||
if (player.statusSm.HasStatus(StatusType.Stun))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (player.reactionSc.blockSm.HaveBlockSource(blockData.blockName))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (player.landMovementSc.isJumping)
|
||||
{
|
||||
if (!_canAirLightAttack || !functionSm["LightAttack"].IsAvailable())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (PlayTargetedAnimation("AirAttack" + comboSm["AirLight"].GetNextNodeName("L")))
|
||||
{
|
||||
comboSm["AirLight"].NextCombo("L");
|
||||
functionSm["LightAttack"].Execute();
|
||||
|
||||
if (comboSm["AirLight"].GetCurrentNodeName() == "L1")
|
||||
{
|
||||
_canAirLightAttack = false;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
CharacterBase target = CombatManager.EnemySm.GetBestEnemy(5);
|
||||
|
||||
if (player.landMovementSc.isSprinting && functionSm["LightAttack"].IsAvailable())
|
||||
{
|
||||
comboSm.main.Reset();
|
||||
if (PlayTargetedAnimation("RunAttack", target))
|
||||
{
|
||||
comboSm.main.NextCombo("L");
|
||||
}
|
||||
|
||||
functionSm["LightAttack"].Execute();
|
||||
return;
|
||||
}
|
||||
|
||||
if (functionSm["LightAttack"].IsAvailable())
|
||||
{
|
||||
string nextNodeName = comboSm.main.GetNextNodeName("L");
|
||||
bool keepAdsorption = nextNodeName is "L4" or "L5";
|
||||
if (PlayTargetedAnimation("Attack" + comboSm.main.GetNextNodeName("L"), target, 1f, keepAdsorption))
|
||||
{
|
||||
float totalTime = 0f;
|
||||
CombatManager.EnemySm.activeEnemiesList.ForEach(enemy =>
|
||||
{
|
||||
(enemy as Enemy).behaviorSc.DispatchContextEvent("PlayerLightAttack", totalTime);
|
||||
});
|
||||
|
||||
comboSm.main.NextCombo("L");
|
||||
functionSm["LightAttack"].Execute();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool TryPlayParryAttack(Enemy parryTarget, List<Enemy> availableEnemies)
|
||||
{
|
||||
if (parryTarget != null && !availableEnemies.Contains(parryTarget))
|
||||
{
|
||||
float distance = Vector3.Distance(player.transform.position.Flatten(), parryTarget.transform.position.Flatten());
|
||||
return PlayTargetedAnimation(distance > 2f ? "DodgeParryAttack" : "BlockParryAttack", parryTarget);
|
||||
}
|
||||
return PlayTargetedAnimation("BlockParryAttack");
|
||||
}
|
||||
|
||||
public override void OnSecondaryPress()
|
||||
{
|
||||
if (player.statusSm.HasStatus(StatusType.Stun))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
List<Enemy> availableEnemies = CombatManager.EnemySm.GetEnemiesInRadius(player.transform.position, 4);
|
||||
BlockSubmodule blockSm = player.reactionSc.blockSm;
|
||||
if (!blockSm.afterPerfectBlockTimer.isCompleted)
|
||||
{
|
||||
Enemy blockedTarget = blockSm.perfectBlockedTarget as Enemy;
|
||||
if (TryPlayParryAttack(blockedTarget, availableEnemies))
|
||||
{
|
||||
blockSm.afterPerfectBlockTimer.Complete();
|
||||
RemoveBlock();
|
||||
}
|
||||
}
|
||||
|
||||
DodgeSubmodule dodgeSm = player.reactionSc.dodgeSm;
|
||||
if (!dodgeSm.afterPerfectDodgeTimer.isCompleted)
|
||||
{
|
||||
Enemy dodgedTarget = dodgeSm.perfectDodgedTarget as Enemy;
|
||||
if (TryPlayParryAttack(dodgedTarget, availableEnemies))
|
||||
{
|
||||
dodgeSm.afterPerfectDodgeTimer.Complete();
|
||||
}
|
||||
}
|
||||
|
||||
if (player.reactionSc.blockSm.HaveBlockSource(blockData.blockName))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (player.landMovementSc.isJumping)
|
||||
{
|
||||
if (!_canAirHeavyAttack || !functionSm["HeavyAttack"].IsAvailable())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (PlayTargetedAnimation("AirAttackRStart"))
|
||||
{
|
||||
player.landMovementSc.ExtraJump(10f);
|
||||
comboSm.main.Reset();
|
||||
functionSm["HeavyAttack"].Execute();
|
||||
_canAirLightAttack = false;
|
||||
_canAirHeavyAttack = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (player.inputSc.IsHoldingSpecialA)
|
||||
{
|
||||
if (functionSm["DisruptionAttack"].IsAvailable())
|
||||
{
|
||||
bool isEnhanced = _passionSystem.LevelIndex >= 3;
|
||||
string suffix = isEnhanced ? "B" : "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)
|
||||
{
|
||||
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 (isEnhanced)
|
||||
{
|
||||
_passionSystem.DecreasePassion(100f, false);
|
||||
}
|
||||
|
||||
comboSm.main.Reset();
|
||||
functionSm["DisruptionAttack"].Execute();
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (functionSm["HeavyAttack"].IsAvailable())
|
||||
{
|
||||
Enemy target = CombatManager.EnemySm.GetBestEnemy(availableEnemies);
|
||||
string nextNodeName = comboSm.main.GetNextNodeName("R");
|
||||
bool keepAdsorption = nextNodeName is "RC";
|
||||
if (PlayTargetedAnimation("Attack" + nextNodeName, target, 1f, keepAdsorption))
|
||||
{
|
||||
float totalTime = fullBodyFuncAnimSm.GetIntervalScaledDuration(IntervalType.Startup) - 0.2f;
|
||||
CombatManager.EnemySm.activeEnemiesList.ForEach(enemy =>
|
||||
{
|
||||
(enemy as Enemy)!.behaviorSc.DispatchContextEvent("PlayerHeavyAttack", totalTime);
|
||||
});
|
||||
comboSm.main.NextCombo("R");
|
||||
functionSm["HeavyAttack"].Execute();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnSpecialCPress()
|
||||
{
|
||||
comboSm.main.Reset();
|
||||
SetBlock();
|
||||
|
||||
if (!player.statusSm.HasStatus(StatusType.Stun))
|
||||
{
|
||||
CharacterBase target = CombatManager.EnemySm.GetBestEnemy(5);
|
||||
if (fullBodyFuncAnimSm.Stop(DisruptionType.ForcedAction))
|
||||
{
|
||||
PlayTargetedAnimation("Block", target, 2f, false, true, upperBodyFuncAnimSm, 1f, 0.1f, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnSpecialCRelease()
|
||||
{
|
||||
if (upperBodyFuncAnimSm.currentRuntimeFuncAnim is { animationName: "Block" })
|
||||
{
|
||||
upperBodyFuncAnimSm.Stop(DisruptionType.ForcedAction);
|
||||
}
|
||||
|
||||
player.selfTimeSm.AddLocalTimer(0.04f, () => RemoveBlock());
|
||||
}
|
||||
|
||||
public override void OnSpecialBPress()
|
||||
{
|
||||
player.operationSc.Dodge();
|
||||
DodgeSource defaultDodge = DodgeSource.Default(player);
|
||||
player.reactionSc.dodgeSm.ApplyDodge(defaultDodge);
|
||||
player.reactionSc.dodgeSm.GetCurrentDodgeSource().PerfectDodge(null);
|
||||
player.reactionSc.dodgeSm.RemoveDodge("DefaultDodge");
|
||||
}
|
||||
}
|
||||
|
||||
public partial class Polychrome
|
||||
{
|
||||
private string _currentKatanaParticle;
|
||||
|
||||
private void UpdateViewObjectVisuals()
|
||||
{
|
||||
if (_passionSystem == null) return;
|
||||
|
||||
int level = _passionSystem.LevelIndex;
|
||||
|
||||
// 开关粒子特效
|
||||
if (level < 3) // C, B,A级
|
||||
{
|
||||
if (_currentKatanaParticle != string.Empty)
|
||||
{
|
||||
GetParticle().Stop();
|
||||
_currentKatanaParticle = string.Empty;
|
||||
}
|
||||
}
|
||||
else if (level <= 4) // S,SS级 (2)
|
||||
{
|
||||
if (_currentKatanaParticle != "ParticleStage0")
|
||||
{
|
||||
if (_currentKatanaParticle != string.Empty)
|
||||
{
|
||||
GetParticle().Stop();
|
||||
}
|
||||
_currentKatanaParticle = "ParticleStage0";
|
||||
GetParticle().Play();
|
||||
}
|
||||
}
|
||||
else // SSS级及以上
|
||||
{
|
||||
if (_currentKatanaParticle != "ParticleStage1")
|
||||
{
|
||||
if (_currentKatanaParticle != string.Empty)
|
||||
{
|
||||
GetParticle().Stop();
|
||||
}
|
||||
_currentKatanaParticle = "ParticleStage1";
|
||||
GetParticle().Play();
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
ParticleSystem GetParticle()
|
||||
{
|
||||
return viewObjects["Katana"].functionalParts.TryGetValue(_currentKatanaParticle, out GameObject particleObj) ?
|
||||
particleObj.GetComponent<ParticleSystem>() : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public partial class Polychrome
|
||||
{
|
||||
public override Dictionary<string, string> GetDescriptionArgs()
|
||||
{
|
||||
var args = new Dictionary<string, string>();
|
||||
if (attackData == null) return args;
|
||||
|
||||
// TODO: 将下列 AttackUnit key 替换为 AttackData ScriptableObject 中的实际 key 名
|
||||
TryPopulateAttack(args, "light", "ProbingAttack");
|
||||
// TryPopulateAttack(args, "heavy", "HeavySlash");
|
||||
// TryPopulateAttack(args, "disruption_a", "DisruptionA");
|
||||
// TryPopulateAttack(args, "disruption_b", "DisruptionB");
|
||||
// TryPopulateAttack(args, "disruption_c", "DisruptionC");
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
private void TryPopulateAttack(Dictionary<string, string> args, string prefix, string unitKey)
|
||||
{
|
||||
if (attackData.attackUnits.TryGetValue(unitKey, out AttackUnit unit))
|
||||
{
|
||||
DisplayTextResolver.PopulateAttackArgs(args, prefix, unit, player);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// =================================================================
|
||||
// 以下为已废弃的 ExtraUIContainer 相关代码 / Deprecated ExtraUIContainer Codes
|
||||
// =================================================================
|
||||
/*
|
||||
public partial class Polychrome
|
||||
{
|
||||
private PolychromeExtraUIContainer ExtraUIContainer => extraUIContainer as PolychromeExtraUIContainer;
|
||||
|
||||
// OnEquipped:
|
||||
// extraUIContainer = Instantiate(extraUIContainerPrefab, PlayerCanvas.MainWeaponUIArea.transform).GetComponent<MainWeaponExtraUIContainer>();
|
||||
// extraUIContainer.mainWeapon = this;
|
||||
|
||||
// OnUnequipped:
|
||||
// Destroy(extraUIContainer.gameObject);
|
||||
|
||||
// UpdateVisuals:
|
||||
// if (ExtraUIContainer != null)
|
||||
// {
|
||||
// ExtraUIContainer.SetStars(level);
|
||||
// }
|
||||
}
|
||||
*/
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using ChocDino.UIFX;
|
||||
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;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Cielonos.MainGame.Inventory.Collections
|
||||
{
|
||||
public partial class Polychrome
|
||||
{
|
||||
private void FAPF_GenerateNormalSlash(RuntimeFuncAnim rtFuncAnim)
|
||||
{
|
||||
CustomFunction.PC_StringString p = rtFuncAnim.GetParams<CustomFunction.PC_StringString>();
|
||||
string hitFeedback = p.str1 switch
|
||||
{
|
||||
"ProbingAttack" => "SingleNormalHit",
|
||||
_ => "MultiNormalHit"
|
||||
};
|
||||
GenerateNormalSlash(p.str0, attackData[p.str1], hitFeedback);
|
||||
}
|
||||
|
||||
private void FAPF_GenerateAirNormalSlash(RuntimeFuncAnim rtFuncAnim)
|
||||
{
|
||||
CustomFunction.PC_StringString p = rtFuncAnim.GetParams<CustomFunction.PC_StringString>();
|
||||
GenerateNormalSlash(p.str0, attackData[p.str1], "SingleNormalHit");
|
||||
}
|
||||
|
||||
private void FAPF_GenerateHeavySlash(RuntimeFuncAnim rtFuncAnim)
|
||||
{
|
||||
CustomFunction.PC_StringString p = rtFuncAnim.GetParams<CustomFunction.PC_StringString>();
|
||||
GenerateHeavySlash(p.str0, attackData[p.str1]);
|
||||
}
|
||||
|
||||
private void FAPF_GenerateUltimateSlash(RuntimeFuncAnim rtFuncAnim)
|
||||
{
|
||||
CustomFunction.PC_StringString p = rtFuncAnim.GetParams<CustomFunction.PC_StringString>();
|
||||
GenerateUltimateSlash(p.str0, attackData[p.str1]);
|
||||
}
|
||||
|
||||
private void FAPF_GenerateDisruptionSlash(RuntimeFuncAnim rtFuncAnim)
|
||||
{
|
||||
CustomFunction.PC_StringString p = rtFuncAnim.GetParams<CustomFunction.PC_StringString>();
|
||||
GenerateDisruptionSlash(p.str0, attackData[p.str1]);
|
||||
}
|
||||
|
||||
private void FAPF_GenerateMovingSlash(RuntimeFuncAnim rtFuncAnim)
|
||||
{
|
||||
CustomFunction.PC_StringString p = rtFuncAnim.GetParams<CustomFunction.PC_StringString>();
|
||||
GenerateDisruptionSlash(p.str0, attackData[p.str1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 203220f978ce416996bd6fcafbebae8c
|
||||
@@ -0,0 +1,127 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using ChocDino.UIFX;
|
||||
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;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Cielonos.MainGame.Inventory.Collections
|
||||
{
|
||||
public partial class Polychrome
|
||||
{
|
||||
private NormalArea CreateBaseSlash(string vfxName, AttackUnit attackUnit, float timeDuration = 1f, float hitActiveDuration = 0.04f)
|
||||
{
|
||||
NormalArea slash = vfxData.SpawnVFX(vfxName, player).GetComponentInChildren<NormalArea>();
|
||||
|
||||
slash.Initialize<NormalArea>(player, this, Fraction.Enemy)
|
||||
.SetAttackSubmodule<NormalArea>(attackUnit)
|
||||
.SetTimeSubmodule<NormalArea>(timeDuration, hitActiveDuration)
|
||||
.SetHitSubmodule<NormalArea>();
|
||||
|
||||
slash.attackSm.breakthroughAction = (enemy, hitPosition) =>
|
||||
{
|
||||
AudioManager.Post(AK.EVENTS.DISRUPT, hitPosition);
|
||||
};
|
||||
|
||||
return slash;
|
||||
}
|
||||
|
||||
private NormalArea GenerateNormalSlash(string vfxName, AttackUnit attackUnit, string hitFeedback)
|
||||
{
|
||||
NormalArea slash = CreateBaseSlash(vfxName, attackUnit, 1f, 0.02f);
|
||||
slash.SetImpulseSubmodule().WithRepulsion(2f);
|
||||
|
||||
slash.hitSm.AddHitSound(AK.EVENTS.POLYCHROME_LIGHTATTACKHIT)
|
||||
.AddHitEvent((enemy, hitPosition) =>
|
||||
{
|
||||
var positionShakeAction = feedbackSc.GetFeedbackData(hitFeedback).Action<CameraPositionShakeAction>("Camera");
|
||||
float magnitude = hitFeedback == "SingleNormalHit" ? 0.12f : 0.06f;
|
||||
positionShakeAction.amplitude = vfxData.Get(vfxName).slashScreenPosition.normalized * magnitude;
|
||||
feedbackSc.PlayFeedback(hitFeedback);
|
||||
});
|
||||
|
||||
return slash;
|
||||
}
|
||||
|
||||
private NormalArea GenerateHeavySlash(string vfxName, AttackUnit attackUnit)
|
||||
{
|
||||
NormalArea slash;
|
||||
if (!HasExtender<PhotonDissociator>())
|
||||
{
|
||||
slash = CreateBaseSlash(vfxName, attackUnit, 1f, 0.04f);
|
||||
}
|
||||
else // 如果有Photon Dissociator,重攻击拆分为五段,每段伤害为原来的30%,时间和判定也相应调整
|
||||
{
|
||||
AttackUnit modifiedUnit = attackUnit.Clone();
|
||||
modifiedUnit.startDamage *= 0.5f;
|
||||
|
||||
slash = vfxData.SpawnVFX(vfxName, player).GetComponentInChildren<NormalArea>();
|
||||
slash.Initialize<NormalArea>(player, this, Fraction.Enemy)
|
||||
.SetAttackSubmodule<NormalArea>(modifiedUnit)
|
||||
.SetTimeSubmodule<NormalArea>(1f, 0.04f, 0.4f)
|
||||
.SetHitSubmodule<NormalArea>(0.1f, 3);
|
||||
|
||||
slash.attackSm.breakthroughAction = (enemy, hitPosition) =>
|
||||
{
|
||||
AudioManager.Post(AK.EVENTS.DISRUPT, hitPosition);
|
||||
};
|
||||
}
|
||||
|
||||
slash.SetImpulseSubmodule(1f).WithRepulsion(5f);
|
||||
|
||||
slash.hitSm.AddHitSound(AK.EVENTS.POLYCHROME_HEAVYATTACKLHIT)
|
||||
.AddHitEvent((enemy, hitPosition) =>
|
||||
{
|
||||
var positionShakeAction = feedbackSc.GetFeedbackData("HeavyHit").Action<CameraPositionShakeAction>("Camera");
|
||||
positionShakeAction.amplitude = vfxData.Get(vfxName).slashScreenPosition.normalized * 0.18f;
|
||||
feedbackSc.PlayFeedback("HeavyHit");
|
||||
});
|
||||
|
||||
return slash;
|
||||
}
|
||||
|
||||
private NormalArea GenerateDisruptionSlash(string vfxName, AttackUnit attackUnit)
|
||||
{
|
||||
NormalArea slash = CreateBaseSlash(vfxName, attackUnit, 1f, 0.04f);
|
||||
slash.SetImpulseSubmodule().WithRepulsion(5f);
|
||||
|
||||
slash.attackSm.breakthroughAction = (enemy, hitPosition) =>
|
||||
{
|
||||
feedbackSc.PlayFeedback("Breakthrough");
|
||||
AudioManager.Post(AK.EVENTS.DISRUPT, hitPosition);
|
||||
};
|
||||
|
||||
slash.hitSm.AddHitSound(AK.EVENTS.POLYCHROME_HEAVYATTACKLHIT)
|
||||
.AddHitEvent((enemy, hitPosition) =>
|
||||
{
|
||||
var positionShakeAction = feedbackSc.GetFeedbackData("HeavyHit").Action<CameraPositionShakeAction>("Camera");
|
||||
positionShakeAction.amplitude = vfxData.Get(vfxName).slashScreenPosition.normalized * 0.18f;
|
||||
feedbackSc.PlayFeedback("HeavyHit");
|
||||
});
|
||||
return slash;
|
||||
}
|
||||
|
||||
private NormalArea GenerateUltimateSlash(string vfxName, AttackUnit attackUnit)
|
||||
{
|
||||
NormalArea slash = CreateBaseSlash(vfxName, attackUnit, 1f, 0.04f);
|
||||
slash.SetImpulseSubmodule(1f).WithRepulsion(5f);
|
||||
|
||||
slash.hitSm.AddHitSound(AK.EVENTS.POLYCHROME_HEAVYATTACKLHIT)
|
||||
.AddHitEvent((enemy, hitPosition) =>
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 74fd17b16e9d4f9db2c66c437c071b42
|
||||
@@ -0,0 +1,71 @@
|
||||
using Cielonos.MainGame.Characters;
|
||||
using Cielonos.MainGame.Effects.Feedback;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Cielonos.MainGame.Inventory.Collections
|
||||
{
|
||||
public partial class Polychrome
|
||||
{
|
||||
public BlockData equipBlockData;
|
||||
private string _blockAnimName = "BlockL";
|
||||
|
||||
private void PlayBlockReaction(string feedbackName, float amplitudeScale)
|
||||
{
|
||||
_blockAnimName = _blockAnimName == "BlockL" ? "BlockR" : "BlockL";
|
||||
animationSc.fullBodyFuncAnimSm.Play(_blockAnimName, 1, 0);
|
||||
|
||||
var rotationShakeAction = feedbackSc.GetFeedbackData(feedbackName).Action<CameraRotationShakeAction>("Camera");
|
||||
Vector3 baseAmplitude = _blockAnimName == "BlockL" ? new Vector3(0f, -2f, 1f) : new Vector3(0f, 2f, -1f);
|
||||
rotationShakeAction.amplitude = baseAmplitude * amplitudeScale;
|
||||
|
||||
feedbackSc.PlayFeedback(feedbackName);
|
||||
}
|
||||
|
||||
private void SetBlock(BlockData blockData = null)
|
||||
{
|
||||
blockData ??= this.blockData;
|
||||
BlockSource blockSource = blockData.CreateBlockSource(player, this);
|
||||
player.landMovementSc.canDash = false;
|
||||
player.landMovementSc.canDodge = false;
|
||||
|
||||
blockSource.onNormalBlock = (attackArea) =>
|
||||
{
|
||||
PlayBlockReaction("NormalBlock", 1f);
|
||||
};
|
||||
|
||||
blockSource.onPerfectBlock = (attackArea) =>
|
||||
{
|
||||
PlayBlockReaction("PerfectBlock", 2f);
|
||||
|
||||
if (attackArea is NormalArea)
|
||||
{
|
||||
if (HasExtender<PhotonPolarizer>()) // 如果有Photon Polarizer,完美格挡会弹开并打断敌人
|
||||
{
|
||||
attackArea.creator.GetHit(Breakthrough.Type.Forced, out _);
|
||||
attackArea.creator.movementSc.impulseSm.ApplyKnockback(player.transform.forward, 6f);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
player.reactionSc.blockSm.ApplyBlock(blockSource);
|
||||
}
|
||||
|
||||
private void StayBlocking()
|
||||
{
|
||||
if (player.inputSc.IsHoldingSpecialB)
|
||||
{
|
||||
player.movementSc.canMove.Modify(true);
|
||||
player.movementSc.canRotate.Modify(true);
|
||||
OnSpecialBPress();
|
||||
}
|
||||
}
|
||||
|
||||
private void RemoveBlock(BlockData blockData = null)
|
||||
{
|
||||
blockData ??= this.blockData;
|
||||
player.landMovementSc.canDash = true;
|
||||
player.landMovementSc.canDodge = true;
|
||||
player.reactionSc.blockSm.RemoveBlock(blockData.blockName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c0162c88523a431b94eef1774904165c
|
||||
Reference in New Issue
Block a user