Files
Cielonos/Assets/Scripts/MainGame/Items/MainWeapons/Polychrome.cs

631 lines
25 KiB
C#
Raw Normal View History

2026-02-13 09:22:11 -05:00
using System.Collections.Generic;
2026-03-20 12:07:44 -04:00
using ChocDino.UIFX;
2026-02-13 09:22:11 -05:00
using Cielonos.MainGame.Buffs.Character;
2026-05-23 08:27:50 -04:00
using Cielonos.MainGame.Characters;
2026-04-18 13:57:19 -04:00
using Cielonos.MainGame.Effects.Feedback;
2026-02-13 09:22:11 -05:00
using Cielonos.MainGame.UI;
using SLSUtilities.General;
2025-12-08 05:27:53 -05:00
using SLSUtilities.FunctionalAnimation;
2026-02-13 09:22:11 -05:00
using SLSUtilities.WwiseAssistance;
2025-12-08 05:27:53 -05:00
using UnityEngine;
2026-05-23 08:27:50 -04:00
namespace Cielonos.MainGame.Inventory.Collections
2025-12-08 05:27:53 -05:00
{
public partial class Polychrome : MainWeaponBase
{
2026-03-20 12:07:44 -04:00
public float techniqueScore;
private PolychromeExtraUIContainer ExtraUIContainer => extraUIContainer as PolychromeExtraUIContainer;
private bool _canAirLightAttack;
private bool _canAirHeavyAttack;
2025-12-08 05:27:53 -05:00
protected override void Update()
{
2025-12-23 19:47:06 -05:00
if (player.inventorySc.equipmentSm.currentMainWeapon == this)
{
functionSm?.Update(player.selfTimeSm.DeltaTime);
}
2025-12-08 05:27:53 -05:00
}
public override void OnEquipped()
{
2025-12-23 19:47:06 -05:00
base.OnEquipped();
2026-01-17 11:35:49 -05:00
2026-05-10 11:47:55 -04:00
extraUIContainer = Instantiate(extraUIContainerPrefab, PlayerCanvas.MainWeaponUIArea.transform).GetComponent<MainWeaponExtraUIContainer>();
2026-03-20 12:07:44 -04:00
extraUIContainer.mainWeapon = this;
_currentKatanaParticle = string.Empty;
2026-01-17 11:35:49 -05:00
player.eventSm.onFirstJump.Add("PolyChrome_OnFirstJump", new PrioritizedAction(() =>
{
2026-03-20 12:07:44 -04:00
_canAirLightAttack = true;
_canAirHeavyAttack = true;
2026-01-17 11:35:49 -05:00
comboSm["AirLight"].Reset();
}));
2026-03-20 12:07:44 -04:00
2026-05-23 08:27:50 -04:00
player.eventSm.onAfterGetAttacked.Add("PolyChrome_OnAfterGetAttacked", new PrioritizedAction<AttackAreaBase, Attack.Result>((_, _) =>
2026-03-20 12:07:44 -04:00
{
ModifyTechniqueScore(-0.2f);
}));
2026-02-13 09:22:11 -05:00
RegisterFunctionsToAnimSc(StayBlocking);
2026-01-12 03:22:16 -05:00
viewObjects["Katana"].SetFadeAnim(0.2f);
viewObjects["Saya"].SetFadeAnim(0.2f);
2026-05-10 11:47:55 -04:00
PlayerCanvas.MainWeaponUIArea.displayer.SetFrameOutline(0.4f);
2026-01-03 18:19:39 -05:00
PlayTargetedAnimation("EquipBlock");
2025-12-24 16:58:51 -05:00
SetBlock(equipBlockData);
2026-01-03 18:19:39 -05:00
player.selfTimeSm.AddLocalTimer(0.4f, () =>
{
RemoveBlock(equipBlockData);
fullBodyFuncAnimSm.Stop("EquipBlock");
});
2025-12-08 05:27:53 -05:00
}
2026-01-17 11:35:49 -05:00
public override void OnUnequipped()
{
base.OnUnequipped();
2026-03-20 12:07:44 -04:00
Destroy(extraUIContainer.gameObject);
ClearTechniqueScore();
2026-01-17 11:35:49 -05:00
player.eventSm.onFirstJump.Remove("PolyChrome_OnFirstJump");
2026-03-20 12:07:44 -04:00
player.eventSm.onAfterGetAttacked.Remove("PolyChrome_OnAfterGetAttacked");
2026-01-17 11:35:49 -05:00
}
2025-12-08 05:27:53 -05:00
public override void OnPrimaryPress()
{
2026-03-20 12:07:44 -04:00
if (player.statusSm.HasStatus(StatusType.Stun))
{
return;
}
2026-02-13 09:22:11 -05:00
if (player.reactionSc.blockSm.HaveBlockSource(blockData.blockName))
{
return;
}
2026-01-17 11:35:49 -05:00
if (player.landMovementSc.isJumping)
2025-12-08 05:27:53 -05:00
{
2026-03-20 12:07:44 -04:00
if (!_canAirLightAttack || !functionSm["LightAttack"].IsAvailable())
2026-01-17 11:35:49 -05:00
{
return;
}
2026-02-13 09:22:11 -05:00
if (PlayTargetedAnimation("AirAttack" + comboSm["AirLight"].GetNextNodeName("L")))
2026-01-17 11:35:49 -05:00
{
comboSm["AirLight"].NextCombo("L");
functionSm["LightAttack"].Execute();
2026-02-13 09:22:11 -05:00
if (comboSm["AirLight"].GetCurrentNodeName() == "L1")
2026-01-17 11:35:49 -05:00
{
2026-03-20 12:07:44 -04:00
_canAirLightAttack = false;
2026-01-17 11:35:49 -05:00
}
}
2025-12-08 05:27:53 -05:00
return;
}
2026-02-13 09:22:11 -05:00
if (player.inputSc.IsHoldingSpecialA && functionSm["LightAttack"].IsAvailable())
{
2026-05-23 08:27:50 -04:00
CharacterBase target = CombatManager.EnemySm.GetBestEnemy(5);
2026-03-20 12:07:44 -04:00
if (PlayTargetedAnimation("AttackRC", target, 1f, true))
2026-02-13 09:22:11 -05:00
{
comboSm.main.NextCombo("L");
functionSm["LightAttack"].Execute();
}
return;
}
2025-12-08 05:27:53 -05:00
if (player.landMovementSc.isSprinting && functionSm["LightAttack"].IsAvailable() && fullBodyFuncAnimSm.CheckPlayability())
{
2026-01-17 11:35:49 -05:00
comboSm.main.Reset();
2025-12-08 05:27:53 -05:00
functionSm["LightAttack"].Execute();
2026-05-23 08:27:50 -04:00
CharacterBase target = CombatManager.EnemySm.GetBestEnemy(8);
2026-02-13 09:22:11 -05:00
PlayTargetedAnimation("RunAttack", target);
comboSm.main.NextCombo("L");
2025-12-08 05:27:53 -05:00
return;
}
2026-01-17 11:35:49 -05:00
if (functionSm["LightAttack"].IsAvailable())
2025-12-08 05:27:53 -05:00
{
2026-05-23 08:27:50 -04:00
CharacterBase target = CombatManager.EnemySm.GetBestEnemy(5);
2026-02-13 09:22:11 -05:00
string nextNodeName = comboSm.main.GetNextNodeName("L");
2026-03-20 12:07:44 -04:00
bool keepAdsorption = nextNodeName is "L4" or "L5";
2026-02-13 09:22:11 -05:00
if (PlayTargetedAnimation("Attack" + comboSm.main.GetNextNodeName("L"), target, 1f, keepAdsorption))
2026-01-17 11:35:49 -05:00
{
2026-03-20 12:07:44 -04:00
float totalTime = 0f;
2026-05-23 08:27:50 -04:00
CombatManager.EnemySm.activeEnemiesList.ForEach(enemy =>
2026-03-20 12:07:44 -04:00
{
(enemy as Enemy).behaviorSc.DispatchContextEvent("PlayerLightAttack", totalTime);
});
2026-01-17 11:35:49 -05:00
comboSm.main.NextCombo("L");
functionSm["LightAttack"].Execute();
}
2025-12-08 05:27:53 -05:00
}
}
public override void OnSecondaryPress()
{
2026-03-20 12:07:44 -04:00
if (player.statusSm.HasStatus(StatusType.Stun))
2026-02-13 09:22:11 -05:00
{
return;
}
2026-05-23 08:27:50 -04:00
List<CharacterBase> availableEnemies = CombatManager.EnemySm.GetEnemiesInRadius(player.transform.position, 4);
2026-05-11 15:22:30 -04:00
//完美格挡+反击
if (player.reactionSc.blockSm.afterPerfectBlockTimer > 0)
{
2026-05-23 08:27:50 -04:00
CharacterBase target = CombatManager.EnemySm.GetBestEnemy(availableEnemies);
if (PlayTargetedAnimation("BlockParryAttack", target))
{
player.reactionSc.blockSm.afterPerfectBlockTimer = 0;
RemoveBlock();
}
2026-05-11 15:22:30 -04:00
return;
}
2026-05-23 08:27:50 -04:00
//完美闪避+反击
if (player.reactionSc.dodgeSm.afterPerfectDodgeTimer > 0)
2026-02-13 09:22:11 -05:00
{
2026-05-23 08:27:50 -04:00
CharacterBase target = CombatManager.EnemySm.GetBestEnemy(12);
if (PlayTargetedAnimation("DodgeParryAttack", target))
{
player.reactionSc.dodgeSm.afterPerfectDodgeTimer = 0;
}
2026-02-13 09:22:11 -05:00
return;
}
2026-05-23 08:27:50 -04:00
if (player.reactionSc.blockSm.HaveBlockSource(blockData.blockName))
2026-05-11 15:22:30 -04:00
{
return;
}
2026-01-17 11:35:49 -05:00
if (player.landMovementSc.isJumping)
2026-01-12 03:22:16 -05:00
{
2026-03-20 12:07:44 -04:00
if (!_canAirHeavyAttack || !functionSm["HeavyAttack"].IsAvailable())
2026-01-17 11:35:49 -05:00
{
return;
}
2026-02-13 09:22:11 -05:00
if (PlayTargetedAnimation("AirAttackRStart"))
2026-01-17 11:35:49 -05:00
{
2026-02-13 09:22:11 -05:00
player.landMovementSc.ExtraJump(10f);
2026-01-17 11:35:49 -05:00
comboSm.main.Reset();
functionSm["HeavyAttack"].Execute();
2026-03-20 12:07:44 -04:00
_canAirLightAttack = false;
_canAirHeavyAttack = false;
2026-01-17 11:35:49 -05:00
}
return;
2026-01-12 03:22:16 -05:00
}
2026-02-13 09:22:11 -05:00
if (player.inputSc.IsHoldingSpecialA && functionSm["HeavyAttack"].IsAvailable())
2025-12-08 05:27:53 -05:00
{
2026-03-20 12:07:44 -04:00
string suffix = techniqueScore switch
{
< 1f => "A",
< 3f => "B",
>= 3f => "C",
_ => "A"
};
2026-05-23 08:27:50 -04:00
List<CharacterBase> disruptable = CombatManager.EnemySm.GetDisruptableEnemies(availableEnemies);
CharacterBase target = CombatManager.EnemySm.GetScoredEnemies(availableEnemies)
.ApplyScoreModifier(disruptable, 0f, 1f).BestEnemy();
2026-03-20 12:07:44 -04:00
if (PlayTargetedAnimation("DisruptionAttack" + suffix, target))
2026-02-13 09:22:11 -05:00
{
2026-05-23 08:27:50 -04:00
if (disruptable.Count > 0)
2026-03-20 12:07:44 -04:00
{
2026-05-23 08:27:50 -04:00
var timeScaleModifierClip = player.feedbackSc
.GetFeedbackData("DisruptionStartup")
.Clip<TimeScaleModifierAction>("Time");
float duration = fullBodyFuncAnimSm.collection["DisruptionAttack" + suffix]
.Interval(IntervalType.Startup).Duration * 2;
2026-04-18 13:57:19 -04:00
timeScaleModifierClip.duration = duration;
player.feedbackSc.PlayFeedback("DisruptionStartup");
2026-03-20 12:07:44 -04:00
}
if (suffix == "B")
{
ModifyTechniqueScore(-1, false);
}
else if (suffix == "C")
{
ModifyTechniqueScore(-3, false);
}
2026-02-13 09:22:11 -05:00
comboSm.main.Reset();
functionSm["HeavyAttack"].Execute();
}
2025-12-08 05:27:53 -05:00
return;
}
2026-01-17 11:35:49 -05:00
if (functionSm["HeavyAttack"].IsAvailable())
2025-12-08 05:27:53 -05:00
{
2026-05-23 08:27:50 -04:00
CharacterBase target = CombatManager.EnemySm.GetBestEnemy(availableEnemies);
2026-03-20 12:07:44 -04:00
string nextNodeName = comboSm.main.GetNextNodeName("R");
bool keepAdsorption = nextNodeName is "RC";
if (PlayTargetedAnimation("Attack" + nextNodeName, target, 1f, keepAdsorption))
2026-01-17 11:35:49 -05:00
{
2026-03-20 12:07:44 -04:00
float totalTime = fullBodyFuncAnimSm.GetIntervalScaledDuration(IntervalType.Startup) - 0.2f;
2026-05-23 08:27:50 -04:00
CombatManager.EnemySm.activeEnemiesList.ForEach(enemy =>
2026-03-20 12:07:44 -04:00
{
2026-05-10 11:47:55 -04:00
(enemy as Enemy)!.behaviorSc.DispatchContextEvent("PlayerHeavyAttack", totalTime);
2026-03-20 12:07:44 -04:00
});
2026-01-17 11:35:49 -05:00
comboSm.main.NextCombo("R");
functionSm["HeavyAttack"].Execute();
}
2025-12-08 05:27:53 -05:00
}
2026-01-17 11:35:49 -05:00
}
2026-02-13 09:22:11 -05:00
public override void OnSpecialCPress()
2026-01-17 11:35:49 -05:00
{
2026-04-12 02:11:15 -04:00
comboSm.main.Reset();
SetBlock();
if (!player.statusSm.HasStatus(StatusType.Stun))
2025-12-08 05:27:53 -05:00
{
2026-05-23 08:27:50 -04:00
CharacterBase target = CombatManager.EnemySm.GetBestEnemy(5);
2026-05-10 11:47:55 -04:00
if (functionSm["Block"].IsAvailable() && fullBodyFuncAnimSm.Stop(DisruptionType.ForcedAction))
2026-04-12 02:11:15 -04:00
{
2026-05-10 11:47:55 -04:00
PlayTargetedAnimation("Block", target, 2f, false, true, upperBodyFuncAnimSm, 1f, 0.1f, true);
2026-04-12 02:11:15 -04:00
}
2025-12-08 05:27:53 -05:00
}
}
2026-02-13 09:22:11 -05:00
public override void OnSpecialCRelease()
2025-12-08 05:27:53 -05:00
{
2026-02-13 09:22:11 -05:00
if (upperBodyFuncAnimSm.currentRuntimeFuncAnim is { animationName: "Block" })
2025-12-08 05:27:53 -05:00
{
2026-02-13 09:22:11 -05:00
upperBodyFuncAnimSm.Stop(DisruptionType.ForcedAction);
2025-12-08 05:27:53 -05:00
}
2026-02-13 09:22:11 -05:00
player.selfTimeSm.AddLocalTimer(0.04f, () => RemoveBlock());
2025-12-08 05:27:53 -05:00
}
2026-05-10 11:47:55 -04:00
public override void OnSpecialBPress()
{
//测试完美格挡和完美闪避
/*SetBlock();
player.reactionSc.blockSm.GetCurrentBlockSource().PerfectBlock(null, player.centerPosition);
RemoveBlock();*/
2026-05-23 08:27:50 -04:00
/*player.operationSc.Dodge();
DodgeSource defaultDodge = DodgeSource.Default(player);
2026-05-10 11:47:55 -04:00
player.reactionSc.dodgeSm.ApplyDodge(defaultDodge);
player.reactionSc.dodgeSm.GetCurrentDodgeSource().PerfectDodge();
player.reactionSc.dodgeSm.RemoveDodge("DefaultDodge");*/
}
2025-12-08 05:27:53 -05:00
}
public partial class Polychrome
{
2026-01-17 11:35:49 -05:00
private void FAPF_GenerateNormalSlash(RuntimeFuncAnim rtFuncAnim)
{
2026-02-13 09:22:11 -05:00
CustomFunction.PC_StringString p = rtFuncAnim.GetParams<CustomFunction.PC_StringString>();
2026-05-10 11:47:55 -04:00
string hitFeedback = p.str1 switch
2026-03-20 12:07:44 -04:00
{
"ProbingAttack" => "SingleNormalHit",
_ => "MultiNormalHit"
};
2026-05-10 11:47:55 -04:00
GenerateNormalSlash(p.str0, attackData[p.str1], hitFeedback);
2026-01-17 11:35:49 -05:00
}
2026-05-23 08:27:50 -04:00
private void FAPF_GenerateAirNormalSlash(RuntimeFuncAnim rtFuncAnim)
{
CustomFunction.PC_StringString p = rtFuncAnim.GetParams<CustomFunction.PC_StringString>();
NormalArea slash = GenerateNormalSlash(p.str0, attackData[p.str1], "SingleNormalHit");
}
2026-01-17 11:35:49 -05:00
private void FAPF_GenerateHeavySlash(RuntimeFuncAnim rtFuncAnim)
{
2026-02-13 09:22:11 -05:00
CustomFunction.PC_StringString p = rtFuncAnim.GetParams<CustomFunction.PC_StringString>();
2026-03-20 12:07:44 -04:00
GenerateHeavySlash(p.str0, attackData[p.str1]);
2026-02-13 09:22:11 -05:00
}
2026-04-18 13:57:19 -04:00
private void FAPF_GenerateUltimateSlash(RuntimeFuncAnim rtFuncAnim)
2026-02-13 09:22:11 -05:00
{
CustomFunction.PC_StringString p = rtFuncAnim.GetParams<CustomFunction.PC_StringString>();
2026-04-18 13:57:19 -04:00
GenerateUltimateSlash(p.str0, attackData[p.str1]);
2026-02-13 09:22:11 -05:00
}
private void FAPF_GenerateDisruptionSlash(RuntimeFuncAnim rtFuncAnim)
{
CustomFunction.PC_StringString p = rtFuncAnim.GetParams<CustomFunction.PC_StringString>();
2026-03-20 12:07:44 -04:00
GenerateDisruptionSlash(p.str0, attackData[p.str1]);
2026-01-17 11:35:49 -05:00
}
2026-02-13 09:22:11 -05:00
private void FAPF_GenerateMovingSlash(RuntimeFuncAnim rtFuncAnim)
{
CustomFunction.PC_StringString p = rtFuncAnim.GetParams<CustomFunction.PC_StringString>();
2026-03-20 12:07:44 -04:00
GenerateDisruptionSlash(p.str0, attackData[p.str1]);
2026-02-13 09:22:11 -05:00
}
2025-12-08 05:27:53 -05:00
}
public partial class Polychrome
{
2026-05-10 11:47:55 -04:00
private NormalArea GenerateNormalSlash(string vfxName, AttackUnit attackUnit, string hitFeedback)
2025-12-08 05:27:53 -05:00
{
2026-05-23 08:27:50 -04:00
NormalArea slash = vfxData.SpawnVFX(vfxName, player).GetComponentInChildren<NormalArea>();
2025-12-08 05:27:53 -05:00
slash.Initialize<NormalArea>(player, this, Fraction.Enemy)
2026-02-13 09:22:11 -05:00
.SetAttackSubmodule<NormalArea>(attackUnit)
2026-04-18 13:57:19 -04:00
.SetTimeSubmodule<NormalArea>(1f, 0.02f)
2026-05-23 08:27:50 -04:00
.SetHitSubmodule<NormalArea>();
slash.SetImpulseSubmodule().WithRepulsion(2f);
2026-03-20 12:07:44 -04:00
slash.attackSm.breakthroughAction = (enemy, hitPosition) =>
{
AudioManager.Post(AK.EVENTS.DISRUPT, hitPosition);
};
2025-12-08 05:27:53 -05:00
2026-03-20 12:07:44 -04:00
slash.hitSm.AddHitSound(AK.EVENTS.POLYCHROME_LIGHTATTACKHIT)
2025-12-08 05:27:53 -05:00
.AddHitEvent((enemy, hitPosition) =>
{
2026-05-10 11:47:55 -04:00
var positionShakeAction = feedbackSc.GetFeedbackData(hitFeedback).Action<CameraPositionShakeAction>("Camera");
float magnitude = hitFeedback == "SingleNormalHit" ? 0.12f : 0.06f;
2026-04-18 13:57:19 -04:00
positionShakeAction.amplitude = vfxData.Get(vfxName).slashScreenPosition.normalized * magnitude;
2026-05-10 11:47:55 -04:00
feedbackSc.PlayFeedback(hitFeedback);
2026-04-18 13:57:19 -04:00
2026-03-20 12:07:44 -04:00
ModifyTechniqueScore(0.02f);
2026-02-13 09:22:11 -05:00
if (attackUnit.unitName == "InstantAttack")
2025-12-08 05:27:53 -05:00
{
2026-02-13 09:22:11 -05:00
if (enemy.buffSm.HasBuff<ElectronicParalysis>())
{
slash.attackSm.attackValue.damage *= 2f;
}
2025-12-08 05:27:53 -05:00
}
});
2026-05-23 08:27:50 -04:00
2025-12-08 05:27:53 -05:00
return slash;
}
2026-03-20 12:07:44 -04:00
private NormalArea GenerateHeavySlash(string vfxName, AttackUnit attackUnit)
2025-12-08 05:27:53 -05:00
{
2026-05-23 08:27:50 -04:00
NormalArea slash = vfxData.SpawnVFX(vfxName, player).GetComponentInChildren<NormalArea>();
2025-12-08 05:27:53 -05:00
slash.Initialize<NormalArea>(player, this, Fraction.Enemy)
2026-02-13 09:22:11 -05:00
.SetAttackSubmodule<NormalArea>(attackUnit)
2026-04-18 13:57:19 -04:00
.SetTimeSubmodule<NormalArea>(1f, 0.04f)
2026-05-23 08:27:50 -04:00
.SetHitSubmodule<NormalArea>();
slash.SetImpulseSubmodule(1f).WithRepulsion(5f);
2026-03-20 12:07:44 -04:00
slash.attackSm.breakthroughAction = (enemy, hitPosition) =>
{
ModifyTechniqueScore(0.2f);
AudioManager.Post(AK.EVENTS.DISRUPT, hitPosition);
};
slash.hitSm.AddHitSound(AK.EVENTS.POLYCHROME_HEAVYATTACKLHIT)
2025-12-08 05:27:53 -05:00
.AddHitEvent((enemy, hitPosition) =>
{
2026-04-18 13:57:19 -04:00
var positionShakeAction = feedbackSc.GetFeedbackData("HeavyHit").Action<CameraPositionShakeAction>("Camera");
positionShakeAction.amplitude = vfxData.Get(vfxName).slashScreenPosition.normalized * 0.18f;
feedbackSc.PlayFeedback("HeavyHit");
2026-03-20 12:07:44 -04:00
ModifyTechniqueScore(0.05f);
2026-02-13 09:22:11 -05:00
});
2025-12-08 05:27:53 -05:00
return slash;
}
2026-03-20 12:07:44 -04:00
private NormalArea GenerateDisruptionSlash(string vfxName, AttackUnit attackUnit)
2025-12-08 05:27:53 -05:00
{
2026-05-23 08:27:50 -04:00
NormalArea slash = vfxData.SpawnVFX(vfxName, player).GetComponentInChildren<NormalArea>();
2025-12-08 05:27:53 -05:00
slash.Initialize<NormalArea>(player, this, Fraction.Enemy)
2026-02-13 09:22:11 -05:00
.SetAttackSubmodule<NormalArea>(attackUnit)
2026-04-18 13:57:19 -04:00
.SetTimeSubmodule<NormalArea>(1f, 0.04f)
2026-05-23 08:27:50 -04:00
.SetHitSubmodule<NormalArea>();
slash.SetImpulseSubmodule().WithRepulsion(5f);
2026-03-20 12:07:44 -04:00
slash.attackSm.breakthroughAction = (enemy, hitPosition) =>
{
ModifyTechniqueScore(0.2f);
2026-04-18 13:57:19 -04:00
feedbackSc.PlayFeedback("Breakthrough");
2026-03-20 12:07:44 -04:00
AudioManager.Post(AK.EVENTS.DISRUPT, hitPosition);
};
2025-12-08 05:27:53 -05:00
2026-03-20 12:07:44 -04:00
slash.hitSm
.AddHitSound(AK.EVENTS.POLYCHROME_HEAVYATTACKLHIT)
2025-12-08 05:27:53 -05:00
.AddHitEvent((enemy, hitPosition) =>
{
2026-04-18 13:57:19 -04:00
var positionShakeAction = feedbackSc.GetFeedbackData("HeavyHit").Action<CameraPositionShakeAction>("Camera");
positionShakeAction.amplitude = vfxData.Get(vfxName).slashScreenPosition.normalized * 0.18f;
feedbackSc.PlayFeedback("HeavyHit");
2025-12-08 05:27:53 -05:00
});
return slash;
}
2026-04-18 13:57:19 -04:00
private NormalArea GenerateUltimateSlash(string vfxName, AttackUnit attackUnit)
2025-12-08 05:27:53 -05:00
{
2026-05-23 08:27:50 -04:00
NormalArea slash = vfxData.SpawnVFX(vfxName, player).GetComponentInChildren<NormalArea>();
2025-12-08 05:27:53 -05:00
slash.Initialize<NormalArea>(player, this, Fraction.Enemy)
2026-02-13 09:22:11 -05:00
.SetAttackSubmodule<NormalArea>(attackUnit)
2026-04-18 13:57:19 -04:00
.SetTimeSubmodule<NormalArea>(1f, 0.04f)
2026-05-23 08:27:50 -04:00
.SetHitSubmodule<NormalArea>();
slash.SetImpulseSubmodule(1f).WithRepulsion(5f);
2025-12-08 05:27:53 -05:00
2026-03-20 12:07:44 -04:00
slash.attackSm.breakthroughAction = (enemy, hitPosition) =>
{
AudioManager.Post(AK.EVENTS.DISRUPT, hitPosition);
};
slash.hitSm
.AddHitSound(AK.EVENTS.POLYCHROME_HEAVYATTACKLHIT)
2025-12-08 05:27:53 -05:00
.AddHitEvent((enemy, hitPosition) =>
{
2026-04-18 13:57:19 -04:00
var positionShakeAction = feedbackSc.GetFeedbackData("HeavyHit").Action<CameraPositionShakeAction>("Camera");
positionShakeAction.amplitude = vfxData.Get(vfxName).slashScreenPosition.normalized * 0.18f;
feedbackSc.PlayFeedback("HeavyHit");
feedbackSc.PlayFeedback("Breakthrough");
2025-12-08 05:27:53 -05:00
});
return slash;
}
2026-02-13 09:22:11 -05:00
}
2025-12-08 05:27:53 -05:00
2026-02-13 09:22:11 -05:00
public partial class Polychrome
{
public BlockData equipBlockData;
2026-03-20 12:07:44 -04:00
private string _blockAnimName = "BlockL";
2025-12-08 05:27:53 -05:00
2025-12-24 16:58:51 -05:00
private void SetBlock(BlockData blockData = null)
2025-12-08 05:27:53 -05:00
{
2025-12-24 16:58:51 -05:00
blockData ??= this.blockData;
2025-12-08 05:27:53 -05:00
BlockSource blockSource = blockData.CreateBlockSource(player, this);
2026-02-13 09:22:11 -05:00
player.landMovementSc.canDash = false;
player.landMovementSc.canDodge = false;
2025-12-08 05:27:53 -05:00
blockSource.onNormalBlock = (attackArea) =>
{
2026-03-20 12:07:44 -04:00
_blockAnimName = _blockAnimName == "BlockL" ? "BlockR" : "BlockL";
animationSc.fullBodyFuncAnimSm.Play(_blockAnimName, 1, 0);
2025-12-22 18:36:29 -05:00
2026-04-18 13:57:19 -04:00
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");
2025-12-22 18:36:29 -05:00
2025-12-08 05:27:53 -05:00
if (attackArea is NormalArea)
{
2026-03-20 12:07:44 -04:00
ModifyTechniqueScore(-0.1f);
2026-05-23 08:27:50 -04:00
//attackArea.creator.GetHit(Breakthrough.Type.Disruption, out _);
//attackArea.creator.movementSc.impulseSm.ApplyKnockback(player.transform.forward, 5f);
2025-12-08 05:27:53 -05:00
}
};
2026-02-13 09:22:11 -05:00
2025-12-08 05:27:53 -05:00
blockSource.onPerfectBlock = (attackArea) =>
{
2026-03-20 12:07:44 -04:00
_blockAnimName = _blockAnimName == "BlockL" ? "BlockR" : "BlockL";
animationSc.fullBodyFuncAnimSm.Play(_blockAnimName, 1, 0);
2025-12-22 18:36:29 -05:00
2026-04-18 13:57:19 -04:00
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");
2025-12-22 18:36:29 -05:00
2025-12-08 05:27:53 -05:00
if (attackArea is NormalArea)
{
2026-03-20 12:07:44 -04:00
ModifyTechniqueScore(0.2f);
2026-05-23 08:27:50 -04:00
//attackArea.creator.GetHit(Breakthrough.Type.Disruption, out _);
//attackArea.creator.movementSc.impulseSm.ApplyKnockback(player.transform.forward, 5f);
2025-12-08 05:27:53 -05:00
}
};
2026-03-20 12:07:44 -04:00
2025-12-08 05:27:53 -05:00
player.reactionSc.blockSm.ApplyBlock(blockSource);
}
private void StayBlocking()
{
if (player.inputSc.IsHoldingSpecialB)
{
player.movementSc.canMove.Modify(true);
player.movementSc.canRotate.Modify(true);
OnSpecialBPress();
}
}
2026-01-03 18:19:39 -05:00
private void RemoveBlock(BlockData blockData = null)
2025-12-08 05:27:53 -05:00
{
2026-01-03 18:19:39 -05:00
blockData ??= this.blockData;
2026-02-13 09:22:11 -05:00
player.landMovementSc.canDash = true;
player.landMovementSc.canDodge = true;
2025-12-08 05:27:53 -05:00
player.reactionSc.blockSm.RemoveBlock(blockData.blockName);
}
}
2026-02-13 09:22:11 -05:00
public partial class Polychrome
{
2026-03-20 12:07:44 -04:00
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;
2026-05-10 11:47:55 -04:00
PlayerCanvas.MainWeaponUIArea.displayer.frame.GetComponent<GlowFilter>().Strength = 0f;
2026-03-20 12:07:44 -04:00
}
}
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();
2026-05-10 11:47:55 -04:00
PlayerCanvas.MainWeaponUIArea.displayer.frame.GetComponent<GlowFilter>().Strength = 0.3f;
2026-03-20 12:07:44 -04:00
}
}
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();
2026-05-10 11:47:55 -04:00
PlayerCanvas.MainWeaponUIArea.displayer.frame.GetComponent<GlowFilter>().Strength = 0.5f;
2026-03-20 12:07:44 -04:00
}
}
//设置UI星星数量
ExtraUIContainer.SetStars(Mathf.FloorToInt(techniqueScore));
}
2026-02-13 09:22:11 -05:00
}
2025-12-08 05:27:53 -05:00
}