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

319 lines
12 KiB
C#
Raw Normal View History

2026-06-12 17:11:39 -04:00
using System.Collections.Generic;
using Cielonos.MainGame.Characters;
using Cielonos.MainGame.Effects.Feedback;
2026-06-30 01:48:58 -04:00
using Cielonos.MainGame.FunctionalAnimation;
2026-06-12 17:11:39 -04:00
using Cielonos.MainGame.UI;
using SLSUtilities.Feedback;
using SLSUtilities.General;
using SLSUtilities.FunctionalAnimation;
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);
}
2026-06-27 12:52:03 -04:00
2026-06-30 01:48:58 -04:00
/*if (Keyboard.current.xKey.wasPressedThisFrame)
2026-06-27 12:52:03 -04:00
{
SetBlock();
player.reactionSc.blockSm.GetBlockSource("Polychrome_Block").PerfectBlock(null, player.CenterPosition + player.transform.forward);
RemoveBlock();
}
2026-06-30 01:48:58 -04:00
if (Keyboard.current.zKey.wasPressedThisFrame)
{
player.reactionSc.dodgeSm.ApplyDodge(DodgeSource.Default(player));
player.reactionSc.dodgeSm.GetCurrentDodgeSource()?.PerfectDodge(null);
player.reactionSc.dodgeSm.RemoveDodge("DefaultDodge");
}*/
2026-06-12 17:11:39 -04:00
}
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();
}
2026-07-01 06:32:50 -04:00
/// <summary>
/// 武器切入(换出至 Polychrome时的逻辑入口
/// </summary>
2026-06-12 17:11:39 -04:00
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);
2026-06-13 18:43:40 -04:00
Enemy target = CombatManager.EnemySm.GetScoredEnemies(availableEnemies).ApplyScoreModifier(disruptable, 0f, 1f).BestEnemy();
if (target != null)
2026-06-12 17:11:39 -04:00
{
2026-07-01 06:32:50 -04:00
comboSm.main.Reset();
PlayDisruptionAttack(target, "B");
2026-06-12 17:11:39 -04:00
}
2026-06-13 18:43:40 -04:00
SetBlock(equipBlockData, false);
player.selfTimeSm.AddLocalTimer(0.4f, () => RemoveBlock(equipBlockData));
2026-06-12 17:11:39 -04:00
}
else
{
PlayTargetedAnimation("EquipBlock");
SetBlock(equipBlockData);
player.selfTimeSm.AddLocalTimer(0.4f, () =>
{
RemoveBlock(equipBlockData);
fullBodyFuncAnimSm.Stop("EquipBlock");
});
}
}
2026-07-01 06:32:50 -04:00
/// <summary>
/// 轻攻击(普攻)输入处理
/// </summary>
2026-06-12 17:11:39 -04:00
public override void OnPrimaryPress()
{
2026-07-01 06:32:50 -04:00
if (player.statusSm.HasStatus(StatusType.Stun) ||
player.reactionSc.blockSm.HaveBlockSource(blockData.blockName))
2026-06-12 17:11:39 -04:00
{
return;
}
2026-07-01 06:32:50 -04:00
// 空中轻攻击连击
2026-06-12 17:11:39 -04:00
if (player.landMovementSc.isJumping)
{
2026-07-01 06:32:50 -04:00
if (_canAirLightAttack && functionSm["LightAttack"].IsAvailable())
2026-06-12 17:11:39 -04:00
{
2026-07-01 06:32:50 -04:00
string airNodeName = comboSm["AirLight"].GetNextNodeName("L");
if (PlayAirAttackL(airNodeName))
2026-06-12 17:11:39 -04:00
{
2026-07-01 06:32:50 -04:00
comboSm["AirLight"].NextCombo("L");
if (comboSm["AirLight"].GetCurrentNodeName() == "L1")
{
_canAirLightAttack = false;
}
2026-06-12 17:11:39 -04:00
}
}
return;
}
CharacterBase target = CombatManager.EnemySm.GetBestEnemy(5);
2026-07-01 06:32:50 -04:00
// 冲刺/奔跑攻击
2026-06-12 17:11:39 -04:00
if (player.landMovementSc.isSprinting && functionSm["LightAttack"].IsAvailable())
{
comboSm.main.Reset();
2026-07-01 06:32:50 -04:00
if (PlayRunAttack(target))
2026-06-12 17:11:39 -04:00
{
comboSm.main.NextCombo("L");
}
return;
}
2026-07-01 06:32:50 -04:00
// 常规地面轻攻击连击
2026-06-12 17:11:39 -04:00
if (functionSm["LightAttack"].IsAvailable())
{
string nextNodeName = comboSm.main.GetNextNodeName("L");
2026-07-01 06:32:50 -04:00
if (PlayNormalAttackL(target, nextNodeName))
2026-06-12 17:11:39 -04:00
{
comboSm.main.NextCombo("L");
}
}
}
2026-07-01 06:32:50 -04:00
/// <summary>
/// 重攻击/特殊/闪避反击输入处理
/// </summary>
2026-06-12 17:11:39 -04:00
public override void OnSecondaryPress()
{
if (player.statusSm.HasStatus(StatusType.Stun))
{
return;
}
List<Enemy> availableEnemies = CombatManager.EnemySm.GetEnemiesInRadius(player.transform.position, 4);
2026-07-01 06:32:50 -04:00
if (PlayParryAttack(availableEnemies)) return;
if (player.reactionSc.blockSm.HaveBlockSource(blockData.blockName)) return;
2026-06-12 17:11:39 -04:00
2026-07-01 06:32:50 -04:00
// 空中重攻击下砸
2026-06-12 17:11:39 -04:00
if (player.landMovementSc.isJumping)
{
2026-07-01 06:32:50 -04:00
if (_canAirHeavyAttack && functionSm["HeavyAttack"].IsAvailable())
2026-06-12 17:11:39 -04:00
{
comboSm.main.Reset();
2026-07-01 06:32:50 -04:00
if (PlayAirAttackR())
{
_canAirLightAttack = false;
_canAirHeavyAttack = false;
}
2026-06-12 17:11:39 -04:00
}
return;
}
2026-07-01 06:32:50 -04:00
// 颠覆攻击
2026-06-30 01:48:58 -04:00
if (player.inputSc.IsHoldingSpecialB)
2026-06-12 17:11:39 -04:00
{
if (functionSm["DisruptionAttack"].IsAvailable())
{
bool isEnhanced = _passionSystem.LevelIndex >= 3;
string suffix = isEnhanced ? "B" : "A";
List<Enemy> disruptable = CombatManager.EnemySm.GetDisruptableEnemies(availableEnemies);
2026-06-13 18:43:40 -04:00
Enemy target = CombatManager.EnemySm.GetScoredEnemies(availableEnemies).ApplyScoreModifier(disruptable, 0f, 1f).BestEnemy();
2026-07-01 06:32:50 -04:00
comboSm.main.Reset();
PlayDisruptionAttack(target, suffix);
2026-06-12 17:11:39 -04:00
}
return;
}
2026-07-01 06:32:50 -04:00
// 常规地面重攻击连击
2026-06-12 17:11:39 -04:00
if (functionSm["HeavyAttack"].IsAvailable())
{
2026-07-01 06:32:50 -04:00
Enemy target;
2026-06-30 01:48:58 -04:00
bool shouldWarp = false;
2026-07-01 06:32:50 -04:00
string suffix = comboSm.main.GetNextNodeName("R");
// 携带 PhotonWarper 时的中远距离敌人折跃判定
if (!HasExtender<PhotonWarper>())
2026-06-30 01:48:58 -04:00
{
2026-07-01 06:32:50 -04:00
target = CombatManager.EnemySm.GetBestEnemy(availableEnemies);
2026-06-30 01:48:58 -04:00
}
2026-07-01 06:32:50 -04:00
else
2026-06-30 01:48:58 -04:00
{
2026-07-01 06:32:50 -04:00
List<Enemy> fartherRange = CombatManager.EnemySm.GetEnemiesInRadius(player.transform.position, 15);
target = CombatManager.EnemySm.GetBestEnemy(fartherRange);
if (target != null && suffix == "RA")
2026-06-30 01:48:58 -04:00
{
2026-07-01 06:32:50 -04:00
float distance = Vector3.Distance(player.transform.position, target.transform.position);
if (distance > 2f)
2026-06-30 01:48:58 -04:00
{
2026-07-01 06:32:50 -04:00
shouldWarp = true;
player.movementSc.SmartTurnToTarget(target, 360, true);
}
2026-06-30 01:48:58 -04:00
}
2026-06-12 17:11:39 -04:00
}
2026-07-01 06:32:50 -04:00
if (PlayNormalAttackR(target, suffix))
2026-06-30 01:48:58 -04:00
{
2026-07-01 06:32:50 -04:00
comboSm.main.NextCombo("R");
if (shouldWarp)
{
FuncAnimInterval interval = fullBodyFuncAnimSm.currentData.Interval(IntervalType.Startup);
WarpToTarget(target, interval, 1f);
}
2026-06-30 01:48:58 -04:00
}
}
2026-06-12 17:11:39 -04:00
}
2026-07-01 06:32:50 -04:00
/// <summary>
/// 终极攻击(次元斩)输入处理
/// </summary>
2026-06-30 01:48:58 -04:00
public override void OnSpecialAPress()
{
2026-07-01 06:32:50 -04:00
if (player.statusSm.HasStatus(StatusType.Stun))
{
return;
}
2026-06-30 01:48:58 -04:00
if (functionSm["UltimateAttack"].IsAvailable())
{
PlayTargetedAnimation("UltimateAttack");
functionSm["UltimateAttack"].Execute();
2026-07-01 06:32:50 -04:00
ApplyUltimatePassionBoost();
2026-06-30 01:48:58 -04:00
}
}
2026-07-01 06:32:50 -04:00
/// <summary>
/// 格挡输入处理
/// </summary>
2026-06-12 17:11:39 -04:00
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);
}
}
}
2026-07-01 06:32:50 -04:00
/// <summary>
/// 格挡输入释放
/// </summary>
2026-06-12 17:11:39 -04:00
public override void OnSpecialCRelease()
{
if (upperBodyFuncAnimSm.currentRuntimeFuncAnim is { animationName: "Block" })
{
2026-07-01 06:32:50 -04:00
upperBodyFuncAnimSm.Stop(DisruptionType.Must);
2026-06-12 17:11:39 -04:00
}
player.selfTimeSm.AddLocalTimer(0.04f, () => RemoveBlock());
}
}
2026-07-01 06:32:50 -04:00
2026-06-12 17:11:39 -04:00
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);
}
}
}
}