Files
Cielonos/Assets/Scripts/MainGame/Items/MainWeapons/Polychrome/Polychrome.cs
SoulliesOfficial 6d7ebc5825 Passion & UI
2026-06-12 17:11:39 -04:00

418 lines
15 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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, BA级
{
if (_currentKatanaParticle != string.Empty)
{
GetParticle().Stop();
_currentKatanaParticle = string.Empty;
}
}
else if (level <= 4) // SSS级 (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);
// }
}
*/
}