Files
Cielonos/Assets/Scripts/MainGame/Characters/Player/Items/Base/ItemBase.cs

286 lines
11 KiB
C#
Raw Normal View History

2025-11-25 08:19:33 -05:00
using System;
using System.Collections.Generic;
2026-01-17 11:35:49 -05:00
using System.Reflection;
using System.Text;
2025-11-25 08:19:33 -05:00
using Cielonos.MainGame.Characters;
2026-04-18 13:57:19 -04:00
using Cielonos.MainGame.Effects.Feedback;
2025-11-25 08:19:33 -05:00
using Cielonos.MainGame.FunctionalAnimation;
2026-02-13 09:22:11 -05:00
using MoreMountains.Feedbacks;
using MoreMountains.FeedbacksForThirdParty;
2025-11-25 08:19:33 -05:00
using Sirenix.OdinInspector;
2026-04-18 13:57:19 -04:00
using SLSUtilities.Feedback;
2026-02-13 09:22:11 -05:00
using SLSUtilities.WwiseAssistance;
2025-11-25 08:19:33 -05:00
using SLSUtilities.FunctionalAnimation;
using UnityEngine;
using UnityEngine.Serialization;
2026-03-20 12:07:44 -04:00
namespace Cielonos.MainGame.Characters.Inventory
2025-11-25 08:19:33 -05:00
{
public abstract partial class ItemBase : SerializedMonoBehaviour
{
public Player player => MainGameManager.Instance.player;
protected PlayerAnimationSubcontroller animationSc => player.animationSc;
protected FunctionalAnimationSubmodule fullBodyFuncAnimSm => animationSc.fullBodyFuncAnimSm;
2026-02-13 09:22:11 -05:00
protected FunctionalAnimationSubmodule upperBodyFuncAnimSm => animationSc.upperBodyFuncAnimSm;
2025-11-25 08:19:33 -05:00
[HideInInspector]
private List<string> registeredFunctionNames = new List<string>();
2026-01-03 18:19:39 -05:00
[TitleGroup("Data")]
2026-01-17 11:35:49 -05:00
public FuncAnimDataCollection fullBodyFuncAnims;
2026-02-13 09:22:11 -05:00
public FuncAnimDataCollection upperBodyFuncAnims;
2026-01-03 18:19:39 -05:00
public ContentData contentData;
2025-12-23 19:47:06 -05:00
public ViewObjectData viewObjectData;
2025-11-25 08:19:33 -05:00
public VFXData vfxData;
2026-01-03 18:19:39 -05:00
public AttributeData passiveAttributeData;
2026-04-18 13:57:19 -04:00
public UpgradeData upgradeData;
2025-11-25 08:19:33 -05:00
public ComboData comboData;
public AttackData attackData;
public FunctionData functionData;
public AmmoData ammoData;
public BlockData blockData;
2026-04-18 13:57:19 -04:00
public OverloadData overloadData;
2025-11-25 08:19:33 -05:00
2026-01-03 18:19:39 -05:00
[TitleGroup("Audio")]
2025-11-25 08:19:33 -05:00
public AudioContainer audioContainer;
2026-01-03 18:19:39 -05:00
[TitleGroup("Submodules")]
public AttributeSubmodule passiveAttributeSm;
2025-11-25 08:19:33 -05:00
public ComboSubmodule comboSm;
public FunctionSubmodule functionSm;
public AmmoSubmodule ammoSm;
2026-04-18 13:57:19 -04:00
public OverloadSubmodule overloadSm;
2025-11-25 08:19:33 -05:00
2026-01-03 18:19:39 -05:00
[TitleGroup("Subcontrollers")]
2025-11-25 08:19:33 -05:00
public FeedbackSubcontroller feedbackSc;
2026-01-03 18:19:39 -05:00
[TitleGroup("View Objects")]
2025-12-23 19:47:06 -05:00
public Dictionary<string, ItemViewObject> viewObjects = new Dictionary<string, ItemViewObject>();
2026-01-03 18:19:39 -05:00
}
public partial class ItemBase
{
public virtual void Initialize()
{
vfxData?.Initialize(player);
2026-04-18 13:57:19 -04:00
feedbackSc?.Initialize();
2026-01-03 18:19:39 -05:00
if(comboData != null) comboSm = new ComboSubmodule(this, comboData);
if(functionData != null) functionSm = new FunctionSubmodule(this, functionData);
if(ammoData != null) ammoSm = new AmmoSubmodule(this, ammoData);
2026-04-18 13:57:19 -04:00
if(passiveAttributeData != null) passiveAttributeSm = new AttributeSubmodule(this, passiveAttributeData, upgradeData);
if(overloadData != null) overloadSm = new OverloadSubmodule(this, overloadData);
2026-01-03 18:19:39 -05:00
}
public virtual void OnObtained()
{
passiveAttributeSm?.RefreshAllModifiedAttributes();
}
public virtual void OnDiscarded()
{
passiveAttributeSm?.RefreshAllModifiedAttributes();
}
2025-12-23 19:47:06 -05:00
2026-04-18 13:57:19 -04:00
[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();
}
2025-12-08 05:27:53 -05:00
protected virtual void Update()
2025-11-25 08:19:33 -05:00
{
2025-12-23 19:47:06 -05:00
functionSm?.Update(player.selfTimeSm.DeltaTime);
2026-04-18 13:57:19 -04:00
overloadSm?.Update(player.selfTimeSm.DeltaTime);
2025-11-25 08:19:33 -05:00
}
}
public partial class ItemBase
{
2026-01-03 18:19:39 -05:00
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<ItemViewObject>();
if (unit.applyOffset)
{
view.transform.localPosition = unit.positionOffset;
view.transform.localEulerAngles = unit.rotationOffset;
}
viewObjects[unit.objectName] = view;
}
}
}
}
public void DespawnViewObjects()
2025-11-25 08:19:33 -05:00
{
2026-01-03 18:19:39 -05:00
foreach (KeyValuePair<string, ItemViewObject> kvp in viewObjects)
{
Destroy(kvp.Value.gameObject);
}
viewObjects.Clear();
2025-11-25 08:19:33 -05:00
}
}
public partial class ItemBase
{
2026-02-13 09:22:11 -05:00
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")
2025-11-25 08:19:33 -05:00
{
funcAnimSm ??= fullBodyFuncAnimSm;
2026-02-13 09:22:11 -05:00
FuncAnimData data = funcAnimSm.collection[animationName];
if (data.animInfo.tags.Contains("Attack") && data.animInfo.isAffectedBySpeedMultiplier)
{
animationSpeedMultiplier *= player.attributeSm["AttackSpeed"];
}
2025-11-25 08:19:33 -05:00
2026-02-13 09:22:11 -05:00
if (funcAnimSm.Play(data, animationSpeedMultiplier, transitionDuration, isNormalizedTransition))
2025-11-25 08:19:33 -05:00
{
2026-02-13 09:22:11 -05:00
float actionCoolDownTime = funcAnimSm.currentData.Interval(IntervalType.ActionDisruption).StartTime /
funcAnimSm.currentPlaySpeedMultiplier;
2026-01-17 11:35:49 -05:00
comboSm?[comboTreeName].SuspendThenSetup(actionCoolDownTime);
2025-11-25 08:19:33 -05:00
if (target != null)
{
2026-04-28 15:46:32 -04:00
if (autoRotate)
{
float angleLimit = player.viewSc.lockTargetModule.isLocking ? 240 : 150;
player.landMovementSc.SmartTurnToTarget(target, angleLimit);
}
2026-03-20 12:07:44 -04:00
if (keepAdsorption)
2026-02-13 09:22:11 -05:00
{
2026-03-20 12:07:44 -04:00
funcAnimSm.currentRuntimeFuncAnim.AddUpdateEvent(new SetRootAdsorptionAdjustment.Keep(target, adsorptionMinDistance));
2026-02-13 09:22:11 -05:00
}
else
{
2026-03-20 12:07:44 -04:00
funcAnimSm.currentRuntimeFuncAnim.AddUpdateUntilEvent(new SetRootAdsorptionAdjustment.Once(target, adsorptionMinDistance));
2026-02-13 09:22:11 -05:00
}
2025-11-25 08:19:33 -05:00
}
2026-02-13 09:22:11 -05:00
2026-01-17 11:35:49 -05:00
return true;
2025-11-25 08:19:33 -05:00
}
2026-01-17 11:35:49 -05:00
return false;
2025-11-25 08:19:33 -05:00
}
2026-02-13 09:22:11 -05:00
protected virtual void Swing(string feedBackName, Vector3 swingRotation = default, Vector3 swingPosition = default)
{
2026-04-18 13:57:19 -04:00
feedbackSc.feedbackDataCollection.TryGet(feedBackName, out FeedbackData feedBackData);
var cameraTrack = feedBackData.tracks.Find(track => track.trackName == "Camera");
if (cameraTrack == null)
2026-02-13 09:22:11 -05:00
{
2026-04-18 13:57:19 -04:00
Debug.LogWarning($"没有找到名为 'Camera' 的轨道,请检查 FeedbackData '{feedBackName}' 的设置。");
return;
2026-02-13 09:22:11 -05:00
}
2026-04-28 15:46:32 -04:00
var positionShakeAction = feedBackData.Action<CameraPositionShakeAction>("Camera");
if (positionShakeAction != null)
2026-04-18 13:57:19 -04:00
{
positionShakeAction.amplitude = swingPosition;
}
2026-04-28 15:46:32 -04:00
var rotationShakeAction = feedBackData.Action<CameraRotationShakeAction>("Camera");
if (rotationShakeAction != null)
2026-02-13 09:22:11 -05:00
{
2026-04-18 13:57:19 -04:00
rotationShakeAction.amplitude = swingRotation;
2026-02-13 09:22:11 -05:00
}
2026-04-18 13:57:19 -04:00
feedbackSc.PlayFeedback(feedBackName);
2026-02-13 09:22:11 -05:00
}
2025-11-25 08:19:33 -05:00
}
public partial class ItemBase
{
2026-02-13 09:22:11 -05:00
public void RegisterFuncAnims()
2025-11-25 08:19:33 -05:00
{
2026-01-17 11:35:49 -05:00
if (fullBodyFuncAnims == null) return;
foreach (FuncAnimData funcAnim in fullBodyFuncAnims.animDataList)
2025-11-25 08:19:33 -05:00
{
player.animationSc.fullBodyFuncAnimSm.Add(funcAnim);
}
2026-02-13 09:22:11 -05:00
foreach (FuncAnimData funcAnim in upperBodyFuncAnims.animDataList)
{
player.animationSc.upperBodyFuncAnimSm.Add(funcAnim);
}
2025-11-25 08:19:33 -05:00
}
protected virtual void RegisterFunctionsToAnimSc(params Action[] functions)
{
2026-02-13 09:22:11 -05:00
RegisterFunctionsToAnimSc();
2025-11-25 08:19:33 -05:00
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);
}
}
}
2026-01-17 11:35:49 -05:00
protected virtual void RegisterFunctionsToAnimSc()
2025-11-25 08:19:33 -05:00
{
2026-01-17 11:35:49 -05:00
foreach (CustomFunction function in fullBodyFuncAnims.preloadFunctions)
2025-11-25 08:19:33 -05:00
{
2026-01-17 11:35:49 -05:00
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)
2025-11-25 08:19:33 -05:00
{
2026-01-17 11:35:49 -05:00
Debug.LogWarning($"Function {functionName} not found in {this.GetType().Name}. Skipping registration.");
continue;
}
Action<RuntimeFuncAnim> action = Delegate.CreateDelegate(typeof(Action<RuntimeFuncAnim>), this, method) as Action<RuntimeFuncAnim>;
registeredFunctionNames.Add(functionName);
player.animationSc.registeredFunctions.TryAdd(functionName, action);
2025-11-25 08:19:33 -05:00
}
}
protected void RemoveAllRegisteredFunctions()
{
foreach (string functionName in registeredFunctionNames)
{
if (!player.animationSc.registeredFunctions.Remove(functionName))
{
Debug.LogWarning($"Function {functionName} is not found.");
}
}
registeredFunctionNames.Clear();
}
}
2026-02-13 09:22:11 -05:00
public partial class ItemBase
{
protected virtual void FAPF_Swing(RuntimeFuncAnim rtFuncAnim)
{
CustomFunction.PC_StringVector3Vector3 p = rtFuncAnim.GetParams<CustomFunction.PC_StringVector3Vector3>();
Swing(p.str0, p.vec3_0, p.vec3_1);
}
}
2025-11-25 08:19:33 -05:00
}