using System.Collections.Generic; using Cielonos.MainGame.Buffs.Character; using Cielonos.MainGame.Characters; using Cielonos.MainGame.UI; using MoreMountains.FeedbacksForThirdParty; using MoreMountains.FeedbacksForThirdParty.Cielonos; using SLSUtilities.General; using SLSUtilities.FunctionalAnimation; using SLSUtilities.WwiseAssistance; using UniRx; using UnityEngine; namespace Cielonos.MainGame.Inventory.Collections { public partial class Polychrome : MainWeaponBase { private bool canAirLightAttack; private bool canAirHeavyAttack; protected override void Update() { if (player.inventorySc.equipmentSm.currentMainWeapon == this) { functionSm?.Update(player.selfTimeSm.DeltaTime); perfectBlockedTimer -= player.selfTimeSm.DeltaTime; } } public override void OnEquipped() { base.OnEquipped(); player.eventSm.onFirstJump.Add("PolyChrome_OnFirstJump", new PrioritizedAction(() => { canAirLightAttack = true; canAirHeavyAttack = true; comboSm["AirLight"].Reset(); })); RegisterFunctionsToAnimSc(StayBlocking); viewObjects["Katana"].SetFadeAnim(0.2f); viewObjects["Saya"].SetFadeAnim(0.2f); PlayerCanvas.Instance.mainWeaponUIArea.displayer.SetFrameOutline(0.4f); PlayTargetedAnimation("EquipBlock"); SetBlock(equipBlockData); player.selfTimeSm.AddLocalTimer(0.4f, () => { RemoveBlock(equipBlockData); fullBodyFuncAnimSm.Stop("EquipBlock"); }); } public override void OnUnequipped() { base.OnUnequipped(); player.eventSm.onFirstJump.Remove("PolyChrome_OnFirstJump"); } public override void OnPrimaryPress() { 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 = BattleManager.EnemySm.GetNearestEnemy(5); if (PlayTargetedAnimation("AttackRC", target)) { 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 = BattleManager.EnemySm.GetNearestEnemy(8); PlayTargetedAnimation("RunAttack", target); comboSm.main.NextCombo("L"); //player.viewSc.cameraRotationSm.TriggerCameraRecenter(player.transform.forward); return; } if (functionSm["LightAttack"].IsAvailable()) { CharacterBase target = BattleManager.EnemySm.GetNearestEnemy(5); string nextNodeName = comboSm.main.GetNextNodeName("L"); bool keepAdsorption = nextNodeName is "L4" or "L5" or "RC"; if (PlayTargetedAnimation("Attack" + comboSm.main.GetNextNodeName("L"), target, 1f, keepAdsorption)) { comboSm.main.NextCombo("L"); functionSm["LightAttack"].Execute(); } //player.viewSc.cameraRotationSm.TriggerCameraRecenter(player.transform.forward); } } public override void OnSecondaryPress() { if (perfectBlockedTimer > 0f && functionSm["HeavyAttack"].IsAvailable()) { CharacterBase target = BattleManager.EnemySm.GetNearestEnemy(5); if (PlayTargetedAnimation("ParryAttack", target)) { perfectBlockedTimer = 0f; comboSm.main.Reset(); functionSm["HeavyAttack"].Execute(); } //player.viewSc.cameraRotationSm.TriggerCameraRecenter(player.transform.forward); return; } 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; } List availableEnemies = BattleManager.EnemySm.GetEnemiesInRadius(player.transform.position, 5); if (player.inputSc.IsHoldingSpecialA && functionSm["HeavyAttack"].IsAvailable()) { if (BattleManager.EnemySm.GetDisruptableEnemies(availableEnemies).Count > 0) { float duration = fullBodyFuncAnimSm.collection["DisruptionAttack"].Interval(IntervalType.Startup).Duration * 2; player.feedbackSc["DisruptionBulletTime"].feedback.GetFeedbackOfType().Duration = duration; player.feedbackSc["DisruptionBulletTime"].feedback.GetFeedbackOfType().ShakeDuration = duration; player.feedbackSc["DisruptionBulletTime"].Play(); } CharacterBase target = BattleManager.EnemySm.GetNearestEnemy(availableEnemies); if (PlayTargetedAnimation("DisruptionAttack", target)) { comboSm.main.Reset(); functionSm["HeavyAttack"].Execute(); } return; } if (functionSm["HeavyAttack"].IsAvailable()) { CharacterBase target = BattleManager.EnemySm.GetNearestEnemy(5); if (PlayTargetedAnimation("Attack" + comboSm.main.GetNextNodeName("R"), target)) { comboSm.main.NextCombo("R"); functionSm["HeavyAttack"].Execute(); } //player.viewSc.cameraRotationSm.TriggerCameraRecenter(player.transform.forward); } } public override void OnSpecialCPress() { 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)) { comboSm.main.Reset(); SetBlock(); } } public override void OnSpecialCRelease() { if (upperBodyFuncAnimSm.currentRuntimeFuncAnim is { animationName: "Block" }) { upperBodyFuncAnimSm.Stop(DisruptionType.ForcedAction); } player.selfTimeSm.AddLocalTimer(0.04f, () => RemoveBlock()); } } public partial class Polychrome { private void FAPF_GenerateNormalSlash(RuntimeFuncAnim rtFuncAnim) { CustomFunction.PC_StringString p = rtFuncAnim.GetParams(); GenerateNormalSlash(p.str0, attackData[p.str1], Vector3.zero); } private void FAPF_GenerateHeavySlash(RuntimeFuncAnim rtFuncAnim) { CustomFunction.PC_StringString p = rtFuncAnim.GetParams(); GenerateHeavySlash(p.str0, attackData[p.str1], Vector3.zero); } private void FAPF_GenerateParrySlash(RuntimeFuncAnim rtFuncAnim) { CustomFunction.PC_StringString p = rtFuncAnim.GetParams(); GenerateParrySlash(p.str0, attackData[p.str1], new Vector3(5, 3, -8)); } private void FAPF_GenerateDisruptionSlash(RuntimeFuncAnim rtFuncAnim) { CustomFunction.PC_StringString p = rtFuncAnim.GetParams(); GenerateDisruptionSlash(p.str0, attackData[p.str1], new Vector3(4, 0, 0)); } private void FAPF_GenerateMovingSlash(RuntimeFuncAnim rtFuncAnim) { CustomFunction.PC_StringString p = rtFuncAnim.GetParams(); GenerateDisruptionSlash(p.str0, attackData[p.str1], new Vector3(4, 0, 0)); } } public partial class Polychrome { private NormalArea GenerateNormalSlash(string vfxName, AttackUnit attackUnit, Vector3 swingRotation) { NormalArea slash = vfxData.SpawnVFX(vfxName).GetComponentInChildren(); slash.Initialize(player, this, Fraction.Enemy) .SetAttackSubmodule(attackUnit) .SetTimeSubmodule(1f, 0.04f, 0.06f) .SetHitSubmodule() .SetForceSubmodule(1.5f, true); slash.hitSm.AddHitSound("NormalHit") .AddHitEvent((enemy, hitPosition) => { feedbackSc["NormalHit"].Play(); ApplyElectronicParalysis(enemy, attackUnit); if (attackUnit.unitName == "InstantAttack") { if (enemy.buffSm.HasBuff()) { slash.attackSm.attackValue.damage *= 2f; } } }); //Swing("NormalSwing", "NormalSwing", swingRotation); return slash; } /*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); });*/ private NormalArea GenerateHeavySlash(string vfxName, AttackUnit attackUnit, Vector3 swingRotation) { NormalArea slash = vfxData.SpawnVFX(vfxName).GetComponentInChildren(); slash.Initialize(player, this, Fraction.Enemy) .SetAttackSubmodule(attackUnit) .SetTimeSubmodule(1f, 0.04f, 0.06f) .SetHitSubmodule() .SetForceSubmodule(3f, true); slash.hitSm.AddHitSound("HeavyHit") .AddHitEvent((enemy, hitPosition) => { feedbackSc["HeavyHitFirst"].Play(); ApplyElectronicParalysis(enemy, attackUnit); }); //Swing("HeavySwing", "HeavySwing", swingRotation); return slash; } private NormalArea GenerateParrySlash(string vfxName, AttackUnit attackUnit, Vector3 swingForce) { NormalArea slash = vfxData.SpawnVFX(vfxName).GetComponentInChildren(); slash.Initialize(player, this, Fraction.Enemy) .SetAttackSubmodule(attackUnit) .SetTimeSubmodule(1f, 0.04f, 0.06f) .SetHitSubmodule() .SetForceSubmodule(3f, true); slash.hitSm.AddHitSound("HeavyHit") .AddHitEvent((enemy, hitPosition) => { feedbackSc["ParryHit"].Play(); /*player.selfTimeSm.ModifyTimeScale(0.12f); enemy.selfTimeSm.ModifyTimeScale(0.12f); player.selfTimeSm.AddGlobalTimer(0.12f, () => { player.selfTimeSm.ModifyTimeScale(0.2f, 0.3f); enemy.selfTimeSm.ModifyTimeScale(0.2f, 0.3f); });*/ ApplyElectronicParalysis(enemy, attackUnit); }); //Swing("HeavySwing", "HeavySwing", swingForce); return slash; } private NormalArea GenerateDisruptionSlash(string vfxName, AttackUnit attackUnit, Vector3 swingForce) { NormalArea slash = vfxData.SpawnVFX(vfxName).GetComponentInChildren(); slash.Initialize(player, this, Fraction.Enemy) .SetAttackSubmodule(attackUnit) .SetTimeSubmodule(1f, 0.04f, 0.06f) .SetHitSubmodule() .SetForceSubmodule(3f, true); slash.hitSm.AddHitSound("HeavyHit") .AddHitEvent((enemy, hitPosition) => { feedbackSc["DisruptHit"].Play(); ApplyElectronicParalysis(enemy, attackUnit); }); //Swing("HeavySwing", "HeavySwing", swingForce); return slash; } } public partial class Polychrome { public BlockData equipBlockData; public float perfectBlockedTimer; 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); player.selfTimeSm.ModifyTimeScale(0.06f, 0.4f); attackArea.creator.selfTimeSm.ModifyTimeScale(0.06f, 0.4f); if (blockAnimName == "BlockL") { feedbackSc["NormalBlockLeft"].Play(); } else { feedbackSc["NormalBlockRight"].Play(); } if (attackArea is NormalArea) { new ElectronicParalysis.Progress(2).Apply(attackArea.creator, player, this); } }; blockSource.onPerfectBlock = (attackArea) => { blockAnimName = blockAnimName == "BlockL" ? "BlockR" : "BlockL"; animationSc.fullBodyFuncAnimSm.Play(blockAnimName, 1, 0); player.selfTimeSm.ModifyTimeScale(0.12f, EaseType.InQuint, 0.2f); attackArea.creator.selfTimeSm.ModifyTimeScale(0.12f, EaseType.InQuint, 0.2f); if (blockAnimName == "BlockL") { feedbackSc["PerfectBlockLeft"].Play(); } else { feedbackSc["PerfectBlockRight"].Play(); } perfectBlockedTimer = 0.5f; if (attackArea is NormalArea) { new ElectronicParalysis.Progress(10).Apply(attackArea.creator, player, this); } }; 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 void ApplyElectronicParalysis(CharacterBase enemy, AttackUnit attackUnit) { if (attackUnit.TryGetSubModule(out AttackUnit.ParameterSubmodule parameterSubmodule)) { int progress = parameterSubmodule.GetParameter("EP_Progress"); new ElectronicParalysis.Progress(progress).Apply(enemy, player, this); } } } }