Files
Cielonos/Assets/Scripts/MainGame/Characters/Base/CharacterBase.cs
SoulliesOfficial f7af60351b 阶段性完成
2025-12-08 05:27:53 -05:00

191 lines
6.4 KiB
C#

using System;
using Sirenix.OdinInspector;
using SLSFramework.WwiseAssistance;
using SLSUtilities.FunctionalAnimation;
using UniRx;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.Serialization;
namespace Cielonos.MainGame.Characters
{
public enum Fraction
{
Player = 0,
AlliedMinion = 1,
Enemy = 10,
Neutral = 20
}
public partial class CharacterBase : SerializedMonoBehaviour
{
public Fraction fraction;
public Transform flexibleCenterPoint;
public Transform footPoint;
[TitleGroup("Data & Presets")]
public AttributeData attributeData;
public BaseAnimationGroup baseAnimationGroup;
[TitleGroup("Submodules")]
public SelfTimeSubmodule selfTimeSm;
public AttributeSubmodule attributeSm;
public AdditionalForceSubmodule additionalForceSm;
public EventSubmodule eventSm;
public BuffSubmodule buffSm;
public StatusSubmodule statusSm;
public CompositeDisposable disposables;
[TitleGroup("Subcontrollers")]
public CollisionSubcontrollerBase collisionSc;
public MovementSubcontrollerBase movementSc;
[Required]
public AnimationSubcontrollerBase animationSc;
[Required]
public RenderSubcontrollerBase renderSc;
public BodyPartsSubcontroller bodyPartsSc;
public AudioSubcontroller audioSc;
public ReactionSubcontroller reactionSc;
public FeedbackSubcontroller feedbackSc;
protected virtual void Awake()
{
InitializeSubmodules();
InitializeSubcontrollers();
}
#if UNITY_EDITOR
private void Reset()
{
InitializeSubmodules();
}
#endif
protected virtual void Start()
{
if (fraction == Fraction.Enemy)
{
BattleManager.EnemySm.activeEnemiesList.Add(this);
}
}
protected virtual void Update()
{
buffSm.Update();
}
public virtual void Die()
{
Destroy(gameObject);//TODO: 后续改为死亡动画+回收
}
}
public partial class CharacterBase
{
protected virtual void InitializeSubmodules()
{
selfTimeSm ??= new SelfTimeSubmodule(this);
attributeSm ??= new AttributeSubmodule(this);
additionalForceSm ??= new AdditionalForceSubmodule(this);
eventSm ??= new EventSubmodule(this);
buffSm ??= new BuffSubmodule(this);
statusSm ??= new StatusSubmodule(this);
disposables ??= new CompositeDisposable();
}
protected virtual void InitializeSubcontrollers()
{
renderSc?.Initialize();
movementSc?.Initialize();
animationSc?.Initialize();
collisionSc?.Initialize();
bodyPartsSc?.Initialize();
audioSc?.Initialize();
reactionSc?.Initialize();
feedbackSc?.Initialize();
}
}
public partial class CharacterBase
{
public AttackResult DealAttack(AttackValue attackValue, out bool isDead)
{
AttackResult result = new AttackResult(attackValue.damage);
/*if (statusModule.IsInvincible)
{
isDead = false;
GeneralUtilities.InstantiateInfo(flexibleCenterPoint.position, "无敌");
return finalDamage;
}*/
float finalDamage = GetDamageValueAfterResistance(attackValue);
if (attributeSm.HasAttribute("Shield") && attributeSm["Shield"] > 0)
{
result.blockedDamage = Mathf.Min(finalDamage, attributeSm["Shield"]);
//GeneralUtilities.InstantiateBlockedDamageNumber(flexibleCenterPoint.position, blockedDamage);
if(finalDamage > attributeSm["Shield"])
{
finalDamage -= attributeSm["Shield"];
attributeSm["Shield"] = 0;
}
else
{
attributeSm["Shield"] -= finalDamage;
finalDamage = 0;
}
}
attributeSm["Health"] -= finalDamage;
result.finalDamage = finalDamage;
if (attributeSm["Health"] <= 0)
{
isDead = true;
attributeSm["Health"] = 0;
Die();
}
else
{
isDead = false;
}
return result;
}
public float GetDamageValueAfterResistance(AttackValue attackValue)
{
/*float reductionRate = attributeModule.currentAttributes.TryGetValue("DamageReduction", out float rate) ? rate : 0;
return attackValue.attackType switch
{
AttackType.Energy => attackValue.damage * GetDamageReduction(attributeModule.GetCurrentAttribute("EnergyAttackResistance"), reductionRate),
AttackType.Kinetics => attackValue.damage * GetDamageReduction(attributeModule.GetCurrentAttribute("KineticAttackResistance"), reductionRate),
AttackType.Explosion => attackValue.damage * GetDamageReduction(attributeModule.GetCurrentAttribute("ExplosionAttackResistance"), reductionRate),
AttackType.Magic => attackValue.damage * GetDamageReduction(attributeModule.GetCurrentAttribute("MagicAttackResistance"), reductionRate),
AttackType.Elemental => attackValue.damage * GetDamageReduction(attributeModule.GetCurrentAttribute("ElementalAttackResistance"), reductionRate),
AttackType.Pure => attackValue.damage * GetDamageReduction(0, reductionRate),
_ => throw new ArgumentOutOfRangeException()
};*/
return attackValue.damage;
}
}
public partial class CharacterBase
{
public virtual bool GetHit(BreakthroughType breakthroughType,
DisruptionType disruptionType = DisruptionType.NormalExternal, Vector3 direction = default)
{
renderSc.GetHitBlink();
if (animationSc.SetGetHitDisruption(disruptionType, breakthroughType))
{
animationSc.PlayGetHitMediumAnimation(direction);
return true;
}
return false;
}
}
}