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-04-18 13:57:19 -04:00
|
|
|
|
using Cielonos.MainGame.Effects.Feedback;
|
2026-02-13 09:22:11 -05:00
|
|
|
|
using Cielonos.MainGame.UI;
|
2026-04-18 13:57:19 -04:00
|
|
|
|
using SLSUtilities.Feedback;
|
2026-02-13 09:22:11 -05:00
|
|
|
|
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-03-20 12:07:44 -04:00
|
|
|
|
namespace Cielonos.MainGame.Characters.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-03-20 12:07:44 -04:00
|
|
|
|
extraUIContainer = Instantiate(extraUIContainerPrefab, mainWeaponUIArea.transform).GetComponent<MainWeaponExtraUIContainer>();
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
player.eventSm.onAfterGetAttacked.Add("PolyChrome_OnAfterGetAttacked", new PrioritizedAction<AttackAreaBase, AttackResult>((_, _) =>
|
|
|
|
|
|
{
|
|
|
|
|
|
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-01-03 18:19:39 -05:00
|
|
|
|
PlayerCanvas.Instance.mainWeaponUIArea.displayer.SetFrameOutline(0.4f);
|
|
|
|
|
|
|
|
|
|
|
|
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())
|
|
|
|
|
|
{
|
|
|
|
|
|
CharacterBase target = BattleManager.EnemySm.GetNearestEnemy(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();
|
|
|
|
|
|
CharacterBase target = BattleManager.EnemySm.GetNearestEnemy(8);
|
2026-02-13 09:22:11 -05:00
|
|
|
|
PlayTargetedAnimation("RunAttack", target);
|
|
|
|
|
|
comboSm.main.NextCombo("L");
|
2025-12-17 04:19:38 -05:00
|
|
|
|
//player.viewSc.cameraRotationSm.TriggerCameraRecenter(player.transform.forward);
|
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
|
|
|
|
{
|
|
|
|
|
|
CharacterBase target = BattleManager.EnemySm.GetNearestEnemy(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;
|
|
|
|
|
|
BattleManager.EnemySm.activeEnemiesList.ForEach(enemy =>
|
|
|
|
|
|
{
|
|
|
|
|
|
(enemy as Enemy).behaviorSc.DispatchContextEvent("PlayerLightAttack", totalTime);
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2026-01-17 11:35:49 -05:00
|
|
|
|
comboSm.main.NextCombo("L");
|
|
|
|
|
|
functionSm["LightAttack"].Execute();
|
|
|
|
|
|
}
|
2025-12-17 04:19:38 -05:00
|
|
|
|
//player.viewSc.cameraRotationSm.TriggerCameraRecenter(player.transform.forward);
|
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;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (player.reactionSc.blockSm.HaveBlockSource(blockData.blockName))
|
|
|
|
|
|
{
|
|
|
|
|
|
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
|
|
|
|
List<CharacterBase> availableEnemies = BattleManager.EnemySm.GetEnemiesInRadius(player.transform.position, 5);
|
|
|
|
|
|
if (player.inputSc.IsHoldingSpecialA && functionSm["HeavyAttack"].IsAvailable())
|
2025-12-08 05:27:53 -05:00
|
|
|
|
{
|
2026-02-13 09:22:11 -05:00
|
|
|
|
CharacterBase target = BattleManager.EnemySm.GetNearestEnemy(availableEnemies);
|
2026-03-20 12:07:44 -04:00
|
|
|
|
string suffix = techniqueScore switch
|
|
|
|
|
|
{
|
|
|
|
|
|
< 1f => "A",
|
|
|
|
|
|
< 3f => "B",
|
|
|
|
|
|
>= 3f => "C",
|
|
|
|
|
|
_ => "A"
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
if (PlayTargetedAnimation("DisruptionAttack" + suffix, target))
|
2026-02-13 09:22:11 -05:00
|
|
|
|
{
|
2026-03-20 12:07:44 -04:00
|
|
|
|
if (BattleManager.EnemySm.GetDisruptableEnemies(availableEnemies).Count > 0)
|
|
|
|
|
|
{
|
2026-04-18 13:57:19 -04:00
|
|
|
|
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");
|
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-03-20 12:07:44 -04:00
|
|
|
|
CharacterBase target = BattleManager.EnemySm.GetNearestEnemy(availableEnemies);
|
|
|
|
|
|
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;
|
|
|
|
|
|
BattleManager.EnemySm.activeEnemiesList.ForEach(enemy =>
|
|
|
|
|
|
{
|
|
|
|
|
|
(enemy as Enemy).behaviorSc.DispatchContextEvent("PlayerHeavyAttack", totalTime);
|
|
|
|
|
|
});
|
2026-01-17 11:35:49 -05:00
|
|
|
|
comboSm.main.NextCombo("R");
|
|
|
|
|
|
functionSm["HeavyAttack"].Execute();
|
|
|
|
|
|
}
|
2025-12-17 04:19:38 -05:00
|
|
|
|
//player.viewSc.cameraRotationSm.TriggerCameraRecenter(player.transform.forward);
|
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-04-12 02:11:15 -04:00
|
|
|
|
CharacterBase target = BattleManager.EnemySm.GetNearestEnemy(5);
|
|
|
|
|
|
if (functionSm["Block"].IsAvailable() &&
|
|
|
|
|
|
fullBodyFuncAnimSm.Stop(DisruptionType.ForcedAction) &&
|
|
|
|
|
|
PlayTargetedAnimation("Block", target, 2f, false, true, upperBodyFuncAnimSm, 1f, 0.1f, true))
|
|
|
|
|
|
{
|
|
|
|
|
|
feedbackSc.PlayFeedback("TestFeedBack");
|
|
|
|
|
|
}
|
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
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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-03-20 12:07:44 -04:00
|
|
|
|
string feedback = p.str1 switch
|
|
|
|
|
|
{
|
|
|
|
|
|
"ProbingAttack" => "SingleNormalHit",
|
|
|
|
|
|
_ => "MultiNormalHit"
|
|
|
|
|
|
};
|
|
|
|
|
|
GenerateNormalSlash(p.str0, attackData[p.str1], feedback);
|
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-03-20 12:07:44 -04:00
|
|
|
|
private NormalArea GenerateNormalSlash(string vfxName, AttackUnit attackUnit, string feedback)
|
2025-12-08 05:27:53 -05:00
|
|
|
|
{
|
|
|
|
|
|
NormalArea slash = vfxData.SpawnVFX(vfxName).GetComponentInChildren<NormalArea>();
|
|
|
|
|
|
|
|
|
|
|
|
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)
|
2025-12-08 05:27:53 -05:00
|
|
|
|
.SetHitSubmodule<NormalArea>()
|
2026-04-30 07:06:38 -04:00
|
|
|
|
.SetForceSubmodule<NormalArea>(2f, true);
|
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-04-18 13:57:19 -04:00
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
return slash;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-13 09:22:11 -05:00
|
|
|
|
/*int progress = Mathf.RoundToInt(attackData["LightAttack"].paramCollection[vfxName]);
|
|
|
|
|
|
Observable.EveryUpdate()
|
|
|
|
|
|
.Where(_ => (enemy.movementSc is AutomataLandMovementSubcontroller subcontroller &&
|
|
|
|
|
|
subcontroller.finalMovementVelocity.y <= 0f))
|
|
|
|
|
|
.First().Subscribe(_ =>
|
|
|
|
|
|
{
|
|
|
|
|
|
(enemy.movementSc as AutomataLandMovementSubcontroller).gravitationalMovement = Vector3.zero;
|
|
|
|
|
|
new VerticalMoveModification(1f, 0.1f).Apply(enemy, player, this);
|
|
|
|
|
|
});*/
|
|
|
|
|
|
|
2026-03-20 12:07:44 -04:00
|
|
|
|
private NormalArea GenerateHeavySlash(string vfxName, AttackUnit attackUnit)
|
2025-12-08 05:27:53 -05:00
|
|
|
|
{
|
|
|
|
|
|
NormalArea slash = vfxData.SpawnVFX(vfxName).GetComponentInChildren<NormalArea>();
|
|
|
|
|
|
|
|
|
|
|
|
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-02-13 09:22:11 -05:00
|
|
|
|
.SetHitSubmodule<NormalArea>()
|
2026-04-30 07:06:38 -04:00
|
|
|
|
.SetForceSubmodule<NormalArea>(4f, true);
|
2025-12-22 18:36:29 -05:00
|
|
|
|
|
2026-03-20 12:07:44 -04:00
|
|
|
|
slash.attackSm.breakthroughAction = (enemy, hitPosition) =>
|
|
|
|
|
|
{
|
|
|
|
|
|
ModifyTechniqueScore(0.2f);
|
|
|
|
|
|
AudioManager.Post(AK.EVENTS.DISRUPT, hitPosition);
|
|
|
|
|
|
ApplyElectronicParalysis(enemy, attackUnit);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
ApplyElectronicParalysis(enemy, attackUnit);
|
|
|
|
|
|
});
|
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
|
|
|
|
{
|
|
|
|
|
|
NormalArea slash = vfxData.SpawnVFX(vfxName).GetComponentInChildren<NormalArea>();
|
|
|
|
|
|
|
|
|
|
|
|
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)
|
2025-12-08 05:27:53 -05:00
|
|
|
|
.SetHitSubmodule<NormalArea>()
|
2026-04-30 07:06:38 -04:00
|
|
|
|
.SetForceSubmodule<NormalArea>(4f, true);
|
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
|
|
|
|
{
|
|
|
|
|
|
NormalArea slash = vfxData.SpawnVFX(vfxName).GetComponentInChildren<NormalArea>();
|
|
|
|
|
|
|
|
|
|
|
|
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)
|
2025-12-08 05:27:53 -05:00
|
|
|
|
.SetHitSubmodule<NormalArea>()
|
2026-04-30 07:06:38 -04:00
|
|
|
|
.SetForceSubmodule<NormalArea>(8f, true);
|
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);
|
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);
|
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
|
|
|
|
|
|
{
|
|
|
|
|
|
private void ApplyElectronicParalysis(CharacterBase enemy, AttackUnit attackUnit)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (attackUnit.TryGetSubModule(out AttackUnit.ParameterSubmodule parameterSubmodule))
|
|
|
|
|
|
{
|
|
|
|
|
|
int progress = parameterSubmodule.GetParameter<int>("EP_Progress");
|
|
|
|
|
|
new ElectronicParalysis.Progress(progress).Apply(enemy, player, this);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
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;
|
|
|
|
|
|
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();
|
|
|
|
|
|
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();
|
|
|
|
|
|
mainWeaponUIArea.displayer.frame.GetComponent<GlowFilter>().Strength = 0.5f;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//设置UI星星数量
|
|
|
|
|
|
ExtraUIContainer.SetStars(Mathf.FloorToInt(techniqueScore));
|
|
|
|
|
|
}
|
2026-02-13 09:22:11 -05:00
|
|
|
|
}
|
2025-12-08 05:27:53 -05:00
|
|
|
|
}
|