using System; using System.Collections.Generic; using System.Reflection; using System.Text; using Cielonos.MainGame.Effects.Feedback; using Cielonos.MainGame.FunctionalAnimation; using Sirenix.OdinInspector; using SLSUtilities.Feedback; using SLSUtilities.WwiseAssistance; using SLSUtilities.FunctionalAnimation; using UnityEngine; namespace Cielonos.MainGame.Characters.Inventory { public abstract partial class ItemBase : SerializedMonoBehaviour { public Player player => MainGameManager.Instance.player; protected PlayerAnimationSubcontroller animationSc => player.animationSc; protected FunctionalAnimationSubmodule fullBodyFuncAnimSm => animationSc.fullBodyFuncAnimSm; protected FunctionalAnimationSubmodule upperBodyFuncAnimSm => animationSc.upperBodyFuncAnimSm; [HideInInspector] private List registeredFunctionNames = new List(); [TitleGroup("Data")] public FuncAnimDataCollection fullBodyFuncAnims; public FuncAnimDataCollection upperBodyFuncAnims; public ContentData contentData; public ViewObjectData viewObjectData; public VFXData vfxData; public AttributeData passiveAttributeData; public UpgradeData upgradeData; public ComboData comboData; public AttackData attackData; public FunctionData functionData; public AmmoData ammoData; public BlockData blockData; public OverloadData overloadData; [TitleGroup("Audio")] public AudioContainer audioContainer; [TitleGroup("Submodules")] public AttributeSubmodule passiveAttributeSm; public ComboSubmodule comboSm; public FunctionSubmodule functionSm; public AmmoSubmodule ammoSm; public OverloadSubmodule overloadSm; [TitleGroup("Subcontrollers")] public FeedbackSubcontroller feedbackSc; [TitleGroup("View Objects")] public Dictionary viewObjects = new Dictionary(); } public partial class ItemBase { public virtual void Initialize() { vfxData?.Initialize(player); feedbackSc?.Initialize(); if(comboData != null) comboSm = new ComboSubmodule(this, comboData); if(functionData != null) functionSm = new FunctionSubmodule(this, functionData); if(ammoData != null) ammoSm = new AmmoSubmodule(this, ammoData); if(passiveAttributeData != null) passiveAttributeSm = new AttributeSubmodule(this, passiveAttributeData, upgradeData); if(overloadData != null) overloadSm = new OverloadSubmodule(this, overloadData); } public virtual void OnObtained() { passiveAttributeSm?.RefreshAllModifiedAttributes(); } public virtual void OnDiscarded() { passiveAttributeSm?.RefreshAllModifiedAttributes(); } [Button("Upgrade")] public virtual void Upgrade() { if (upgradeData == null || passiveAttributeSm == null) { Debug.LogWarning($"{GetType().Name}: Cannot upgrade - missing UpgradeData or AttributeSubmodule."); return; } passiveAttributeSm.level++; passiveAttributeSm.RefreshAllModifiedAttributes(); } protected virtual void Update() { functionSm?.Update(player.selfTimeSm.DeltaTime); overloadSm?.Update(player.selfTimeSm.DeltaTime); } } public partial class ItemBase { protected void SpawnViewObjects() { if (viewObjectData != null) { foreach (ViewObjectData.ViewObjectDataUnit unit in viewObjectData.viewObjectUnits) { Transform attachPoint = !unit.isCustomAttachPoint ? player.bodyPartsSc.GetPart(unit.normalAttachBodyPart) : player.bodyPartsSc.GetPart(unit.customAttachPartName); if (attachPoint != null) { ItemViewObject view = Instantiate(unit.objectPrefab, attachPoint).GetComponent(); if (unit.applyOffset) { view.transform.localPosition = unit.positionOffset; view.transform.localEulerAngles = unit.rotationOffset; } viewObjects[unit.objectName] = view; } } } } public void DespawnViewObjects() { foreach (KeyValuePair kvp in viewObjects) { Destroy(kvp.Value.gameObject); } viewObjects.Clear(); } } public partial class ItemBase { protected bool PlayTargetedAnimation(string animationName, CharacterBase target = null, float adsorptionMinDistance = 1f, bool keepAdsorption = false, bool autoRotate = true, FunctionalAnimationSubmodule funcAnimSm = null, float animationSpeedMultiplier = 1f, float transitionDuration = 0.1f, bool isNormalizedTransition = false, string comboTreeName = "Main") { funcAnimSm ??= fullBodyFuncAnimSm; FuncAnimData data = funcAnimSm.collection[animationName]; if (data.animInfo.tags.Contains("Attack") && data.animInfo.isAffectedBySpeedMultiplier) { animationSpeedMultiplier *= player.attributeSm["AttackSpeed"]; } if (funcAnimSm.Play(data, animationSpeedMultiplier, transitionDuration, isNormalizedTransition)) { float actionCoolDownTime = funcAnimSm.currentData.Interval(IntervalType.ActionDisruption).StartTime / funcAnimSm.currentPlaySpeedMultiplier; comboSm?[comboTreeName].SuspendThenSetup(actionCoolDownTime); if (target != null) { if (autoRotate) { //float angleLimit = player.viewSc.lockTargetModule.isLocking ? 240 : 150; player.landMovementSc.SmartTurnToTarget(target); } if (keepAdsorption) { funcAnimSm.currentRuntimeFuncAnim.AddUpdateEvent(new SetRootAdsorptionAdjustment.Keep(target, adsorptionMinDistance)); } else { funcAnimSm.currentRuntimeFuncAnim.AddUpdateUntilEvent(new SetRootAdsorptionAdjustment.Once(target, adsorptionMinDistance)); } } return true; } return false; } protected virtual void Swing(string feedBackName, Vector3 swingRotation = default, Vector3 swingPosition = default) { feedbackSc.feedbackDataCollection.TryGet(feedBackName, out FeedbackData feedBackData); var cameraTrack = feedBackData.tracks.Find(track => track.trackName == "Camera"); if (cameraTrack == null) { Debug.LogWarning($"没有找到名为 'Camera' 的轨道,请检查 FeedbackData '{feedBackName}' 的设置。"); return; } var positionShakeAction = feedBackData.Action("Camera"); if (positionShakeAction != null) { positionShakeAction.amplitude = swingPosition; } var rotationShakeAction = feedBackData.Action("Camera"); if (rotationShakeAction != null) { rotationShakeAction.amplitude = swingRotation; } feedbackSc.PlayFeedback(feedBackName); } } public partial class ItemBase { public void RegisterFuncAnims() { if (fullBodyFuncAnims == null) return; foreach (FuncAnimData funcAnim in fullBodyFuncAnims.animDataList) { player.animationSc.fullBodyFuncAnimSm.Add(funcAnim); } foreach (FuncAnimData funcAnim in upperBodyFuncAnims.animDataList) { player.animationSc.upperBodyFuncAnimSm.Add(funcAnim); } } protected virtual void RegisterFunctionsToAnimSc(params Action[] functions) { RegisterFunctionsToAnimSc(); foreach (Action function in functions) { string functionName = function.Method.Name; if (!player.animationSc.registeredFunctions.TryAdd(functionName, anim => function())) { Debug.LogWarning($"Function {functionName} is already registered."); } else { registeredFunctionNames.Add(functionName); } } } protected virtual void RegisterFunctionsToAnimSc() { foreach (CustomFunction function in fullBodyFuncAnims.preloadFunctions) { string functionName = function.functionName; string FAPF_functionName = new StringBuilder(functionName).Insert(0, "FAPF_").ToString(); MethodInfo method = GetType().GetMethod(FAPF_functionName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method == null) { Debug.LogWarning($"Function {functionName} not found in {this.GetType().Name}. Skipping registration."); continue; } Action action = Delegate.CreateDelegate(typeof(Action), this, method) as Action; registeredFunctionNames.Add(functionName); player.animationSc.registeredFunctions.TryAdd(functionName, action); } } protected void RemoveAllRegisteredFunctions() { foreach (string functionName in registeredFunctionNames) { if (!player.animationSc.registeredFunctions.Remove(functionName)) { Debug.LogWarning($"Function {functionName} is not found."); } } registeredFunctionNames.Clear(); } } public partial class ItemBase { protected virtual void FAPF_Swing(RuntimeFuncAnim rtFuncAnim) { CustomFunction.PC_StringVector3Vector3 p = rtFuncAnim.GetParams(); Swing(p.str0, p.vec3_0, p.vec3_1); } } }