diff --git a/Assets/GameMain/Scripts/Base/Definition/Constant/Constant.Layer.cs b/Assets/GameMain/Scripts/Base/Definition/Constant/Constant.Layer.cs index 8698f46..3eb5447 100644 --- a/Assets/GameMain/Scripts/Base/Definition/Constant/Constant.Layer.cs +++ b/Assets/GameMain/Scripts/Base/Definition/Constant/Constant.Layer.cs @@ -18,12 +18,55 @@ namespace SepCore.Definition { public const string DefaultLayerName = "Default"; public static readonly int DefaultLayerId = LayerMask.NameToLayer(DefaultLayerName); + public static readonly LayerMask DefaultLayerMask = 1 << DefaultLayerId; + + public const string TransparentFXLayerName = "TransparentFX"; + public static readonly int TransparentLayerId = LayerMask.NameToLayer(TransparentFXLayerName); + public static readonly LayerMask TransparentLayerMask = 1 << TransparentLayerId; + + public const string IgnoreRaycastLayerName = "Ignore Raycast"; + public static readonly int IgnoreLayerId = LayerMask.NameToLayer(IgnoreRaycastLayerName); + public static readonly LayerMask IgnoreLayerMask = 1 << IgnoreLayerId; + + public const string WaterLayerName = "Water"; + public static readonly int WaterLayerId = LayerMask.NameToLayer(WaterLayerName); + public static readonly LayerMask WaterLayerMask = 1 << WaterLayerId; public const string UILayerName = "UI"; public static readonly int UILayerId = LayerMask.NameToLayer(UILayerName); + public static readonly LayerMask UILayerMask = 1 << UILayerId; public const string TargetableObjectLayerName = "Targetable Object"; public static readonly int TargetableObjectLayerId = LayerMask.NameToLayer(TargetableObjectLayerName); + public static readonly LayerMask TargetableObjectLayerMask = 1 << TargetableObjectLayerId; + + public const string PlayerLayerName = "Player"; + public static readonly int PlayerLayerId = LayerMask.NameToLayer(PlayerLayerName); + public static readonly LayerMask PlayerLayerMask = 1 << PlayerLayerId; + + public const string EnemyLayerName = "Enemy"; + public static readonly int EnemyLayerId = LayerMask.NameToLayer(EnemyLayerName); + public static readonly LayerMask EnemyLayerMask = 1 << EnemyLayerId; + + public const string PlayerBulletLayerName = "PlayerBullet"; + public static readonly int PlayerBulletLayerId = LayerMask.NameToLayer(PlayerBulletLayerName); + public static readonly LayerMask PlayerBulletLayerMask = 1 << PlayerBulletLayerId; + + public const string EnemyBulletLayerName = "EnemyBullet"; + public static readonly int EnemyBulletLayerId = LayerMask.NameToLayer(EnemyBulletLayerName); + public static readonly LayerMask EnemyBulletLayerMask = 1 << EnemyBulletLayerId; + + public const string PlayerWeaponLayerName = "PlayerWeapon"; + public static readonly int PlayerWeaponLayerId = LayerMask.NameToLayer(PlayerWeaponLayerName); + public static readonly LayerMask PlayerWeaponLayerMask = 1 << PlayerWeaponLayerId; + + public const string EnemyWeaponLayerName = "EnemyWeapon"; + public static readonly int EnemyWeaponLayerId = LayerMask.NameToLayer(EnemyWeaponLayerName); + public static readonly LayerMask EnemyWeaponLayerMask = 1 << EnemyWeaponLayerId; + + public const string DropLayerName = "Drop"; + public static readonly int DropLayerId = LayerMask.NameToLayer(DropLayerName); + public static readonly LayerMask DropLayerMask = 1 << DropLayerId; } } } diff --git a/Assets/GameMain/Scripts/Base/EntityData/Weapon/WeaponData.cs b/Assets/GameMain/Scripts/Base/EntityData/Weapon/WeaponData.cs index 5b6df7e..c799e46 100644 --- a/Assets/GameMain/Scripts/Base/EntityData/Weapon/WeaponData.cs +++ b/Assets/GameMain/Scripts/Base/EntityData/Weapon/WeaponData.cs @@ -1,59 +1,66 @@ using System; using System.Collections.Generic; using SepCore.Definition; +using UnityGameFramework.Runtime; namespace SepCore.Entity { [Serializable] public class WeaponData : AccessoryObjectData { - private readonly WeaponConfig _weaponConfig; + public WeaponConfig Config { get; } public WeaponData(int entityId, WeaponConfig weaponConfig, int ownerId, CampType ownerCamp) : base(weaponConfig.Prefab, entityId, ownerId, ownerCamp) { - _weaponConfig = weaponConfig; + Config = weaponConfig; } - public WeaponConfig Config => _weaponConfig; + public WeaponType WeaponType => Config.WeaponType; - public WeaponType WeaponType => _weaponConfig.WeaponType; + public string LogicType => Config.LogicType; - public string LogicType => _weaponConfig.LogicType; + public int Attack => Config.Attack; - public int Attack => _weaponConfig.Attack; + public string Title => Config.WeaponType.ToString(); - public string Title => _weaponConfig.WeaponType.ToString(); + public string Sprite => Config.Sprite; - public string IconAssetName => _weaponConfig.Sprite; + public Rarity Rarity => Config.Rarity; - public Rarity Rarity => _weaponConfig.Rarity; + public int Price => Config.Price; - public int Price => _weaponConfig.Price; + public float Cooldown => Config.Cooldown / 1000f; - public float Cooldown => _weaponConfig.Cooldown / 1000f; + public float AttackRange => Config.AttackRange / 1000f; - public float AttackRange => _weaponConfig.AttackRange / 1000f; + public int AttackSoundId => Config.AttackSoundId; - public int AttackSoundId => _weaponConfig.AttackSoundId; + public IReadOnlyDictionary Parameters => Config.Parameters; - public IReadOnlyDictionary Parameters => _weaponConfig.Parameters; + public IReadOnlyList Modifiers => Config.Modifiers; - public IReadOnlyList Modifiers => _weaponConfig.Modifiers; - - public int GetParam(ParamType paramType, int defaultValue = 0) + public int GetParam(ParamType paramType) { - return _weaponConfig.Parameters.TryGetValue(paramType, out int value) ? value : defaultValue; + if (Config.Parameters.TryGetValue(paramType, out int value)) + { + return value; + } + + Log.Error("Weapon parameter '{0}' not found for weapon '{1}'.", paramType, Config.WeaponType); + return 0; } - public float GetParamFloat(ParamType paramType, float defaultValue = 0f) + public float GetParamFloat(ParamType paramType) { - if (_weaponConfig.Parameters.TryGetValue(paramType, out int val)) + if (Config.Parameters.TryGetValue(paramType, out int val)) { return paramType == ParamType.SectorAngle ? val : val / 1000f; } - return defaultValue; + Log.Error("Weapon parameter '{0}' not found for weapon '{1}'.", paramType, Config.WeaponType); + return 0f; } } } + diff --git a/Assets/GameMain/Scripts/Base/EntityData/Weapon/WeaponHandgunData.cs b/Assets/GameMain/Scripts/Base/EntityData/Weapon/WeaponHandgunData.cs deleted file mode 100644 index deafdc5..0000000 --- a/Assets/GameMain/Scripts/Base/EntityData/Weapon/WeaponHandgunData.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; -using SepCore.Definition; - -namespace SepCore.Entity -{ - [Serializable] - public sealed class WeaponHandgunParamsData - { - } - - public class WeaponHandgunData : WeaponData - { - public WeaponHandgunParamsData ParamsData { get; } - - public WeaponHandgunData(int entityId, WeaponConfig weaponConfig, int ownerId, CampType ownerCamp) - : base(entityId, weaponConfig, ownerId, ownerCamp) - { - ParamsData = new WeaponHandgunParamsData(); - } - } -} diff --git a/Assets/GameMain/Scripts/Base/EntityData/Weapon/WeaponKnifeData.cs b/Assets/GameMain/Scripts/Base/EntityData/Weapon/WeaponKnifeData.cs deleted file mode 100644 index 25d90f3..0000000 --- a/Assets/GameMain/Scripts/Base/EntityData/Weapon/WeaponKnifeData.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using SepCore.Definition; - -namespace SepCore.Entity -{ - [Serializable] - public sealed class WeaponKnifeParamsData - { - public float HitRadius { get; set; } - } - - public class WeaponKnifeData : WeaponData - { - public WeaponKnifeParamsData ParamsData { get; } - - public WeaponKnifeData(int entityId, WeaponConfig weaponConfig, int ownerId, CampType ownerCamp) - : base(entityId, weaponConfig, ownerId, ownerCamp) - { - ParamsData = new WeaponKnifeParamsData - { - HitRadius = GetParamFloat(ParamType.HitRadius) - }; - } - } -} diff --git a/Assets/GameMain/Scripts/Base/EntityData/Weapon/WeaponLanceData.cs b/Assets/GameMain/Scripts/Base/EntityData/Weapon/WeaponLanceData.cs deleted file mode 100644 index e247dc8..0000000 --- a/Assets/GameMain/Scripts/Base/EntityData/Weapon/WeaponLanceData.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System; -using SepCore.Definition; - -namespace SepCore.Entity -{ - [Serializable] - public sealed class WeaponLanceParamsData - { - /// - /// 横向半宽,表示前戳矩形判定的一半宽度。 - /// - public float HitHalfWidth { get; set; } - - /// - /// 旧字段兼容,未配置 HitHalfWidth 时回退使用。 - /// - public float HitRadius { get; set; } - - /// - /// 前戳判定盒体的总高度。 - /// - public float HitHeight { get; set; } - - /// - /// 判定盒体中心相对战斗平面的高度偏移。 - /// - public float HitCenterYOffset { get; set; } - - /// - /// 前刺距离,同时驱动武器位移和命中长度。 - /// - public float PierceLength { get; set; } - - /// - /// 旧字段兼容,未配置 PierceLength 时回退使用。 - /// - public float ThrustDistance { get; set; } - - /// - /// 判定起点相对武器当前位置的前置偏移。 - /// - public float ForwardOffset { get; set; } - - /// - /// 追踪目标时的转向速度。 - /// - public float RotateSpeed { get; set; } - - /// - /// 向前突刺阶段耗时。 - /// - public float AttackDuration { get; set; } - - /// - /// 收枪返回阶段耗时。 - /// - public float ReturnDuration { get; set; } - } - - [Serializable] - public class WeaponLanceData : WeaponData - { - public WeaponLanceParamsData ParamsData { get; } - - public WeaponLanceData(int entityId, WeaponConfig weaponConfig, int ownerId, CampType ownerCamp) - : base(entityId, weaponConfig, ownerId, ownerCamp) - { - ParamsData = new WeaponLanceParamsData - { - HitHalfWidth = GetParamFloat(ParamType.HitHalfWidth), - PierceLength = GetParamFloat(ParamType.PierceLength), - HitHeight = GetParamFloat(ParamType.HitHeight) - }; - } - } -} diff --git a/Assets/GameMain/Scripts/Base/EntityData/Weapon/WeaponLightningData.cs b/Assets/GameMain/Scripts/Base/EntityData/Weapon/WeaponLightningData.cs deleted file mode 100644 index eadda4c..0000000 --- a/Assets/GameMain/Scripts/Base/EntityData/Weapon/WeaponLightningData.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using SepCore.Definition; - -namespace SepCore.Entity -{ - [Serializable] - public sealed class WeaponLightningParamsData - { - public float HitRadius { get; set; } - public float HoverHeight { get; set; } - } - - public class WeaponLightningData : WeaponData - { - public WeaponLightningParamsData ParamsData { get; } - - public WeaponLightningData(int entityId, WeaponConfig weaponConfig, int ownerId, CampType ownerCamp) - : base(entityId, weaponConfig, ownerId, ownerCamp) - { - ParamsData = new WeaponLightningParamsData - { - HitRadius = GetParamFloat(ParamType.HitRadius), - HoverHeight = 0f - }; - } - } -} diff --git a/Assets/GameMain/Scripts/Base/EntityData/Weapon/WeaponLightningData.cs.meta b/Assets/GameMain/Scripts/Base/EntityData/Weapon/WeaponLightningData.cs.meta deleted file mode 100644 index 77f60c8..0000000 --- a/Assets/GameMain/Scripts/Base/EntityData/Weapon/WeaponLightningData.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 25b0006918fd46959c7f6b8ec1bbc8ab -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: \ No newline at end of file diff --git a/Assets/GameMain/Scripts/Base/EntityData/Weapon/WeaponSlashData.cs b/Assets/GameMain/Scripts/Base/EntityData/Weapon/WeaponSlashData.cs deleted file mode 100644 index c38018e..0000000 --- a/Assets/GameMain/Scripts/Base/EntityData/Weapon/WeaponSlashData.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using SepCore.Definition; - -namespace SepCore.Entity -{ - [Serializable] - public sealed class WeaponSlashParamsData - { - public float SectorAngle { get; set; } - } - - public class WeaponSlashData : WeaponData - { - public WeaponSlashParamsData ParamsData { get; } - - public WeaponSlashData(int entityId, WeaponConfig weaponConfig, int ownerId, CampType ownerCamp) - : base(entityId, weaponConfig, ownerId, ownerCamp) - { - ParamsData = new WeaponSlashParamsData - { - SectorAngle = GetParamFloat(ParamType.SectorAngle) - }; - } - } -} diff --git a/Assets/GameMain/Scripts/Base/EntityData/Weapon/WeaponSlashData.cs.meta b/Assets/GameMain/Scripts/Base/EntityData/Weapon/WeaponSlashData.cs.meta deleted file mode 100644 index a111bea..0000000 --- a/Assets/GameMain/Scripts/Base/EntityData/Weapon/WeaponSlashData.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 4aa6473525dc4c62aeee02ff562ec453 -timeCreated: 1771484661 \ No newline at end of file diff --git a/Assets/GameMain/Scripts/Base/Gen/WeaponStateType.cs b/Assets/GameMain/Scripts/Base/Gen/WeaponStateType.cs new file mode 100644 index 0000000..840ec7f --- /dev/null +++ b/Assets/GameMain/Scripts/Base/Gen/WeaponStateType.cs @@ -0,0 +1,42 @@ + +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + + + +namespace SepCore.Definition +{ + /// + /// 武器状态 + /// + public enum WeaponStateType : byte + { + /// + /// 无 + /// + None = 0, + /// + /// 攻击 + /// + Attack = 1, + /// + /// 待机 + /// + Idle = 2, + /// + /// 搜索 + /// + Seek = 3, + /// + /// 瞄准 + /// + Aim = 4, + } + +} + diff --git a/Assets/GameMain/Scripts/Base/EntityData/Weapon/WeaponLanceData.cs.meta b/Assets/GameMain/Scripts/Base/Gen/WeaponStateType.cs.meta similarity index 83% rename from Assets/GameMain/Scripts/Base/EntityData/Weapon/WeaponLanceData.cs.meta rename to Assets/GameMain/Scripts/Base/Gen/WeaponStateType.cs.meta index f16bacc..80d3ea6 100644 --- a/Assets/GameMain/Scripts/Base/EntityData/Weapon/WeaponLanceData.cs.meta +++ b/Assets/GameMain/Scripts/Base/Gen/WeaponStateType.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 4d1a821e8ee1a9a4b912b70b0a1616eb +guid: 1065e2570786f184c9553db06202a6a7 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Assets/GameMain/Scripts/Presentation/ItemTooltip/ItemTooltipContext.cs b/Assets/GameMain/Scripts/Presentation/ItemTooltip/ItemTooltipContext.cs index 217b9a6..15862e7 100644 --- a/Assets/GameMain/Scripts/Presentation/ItemTooltip/ItemTooltipContext.cs +++ b/Assets/GameMain/Scripts/Presentation/ItemTooltip/ItemTooltipContext.cs @@ -41,7 +41,7 @@ namespace SepCore.UI if (ItemType == ItemType.Weapon) { var data = rawData.WeaponData; - IconAssetName = data.IconAssetName; + IconAssetName = data.Sprite; Title = data.Title; Description = ItemDescUtility.CreateWeaponDescription(data); } diff --git a/Assets/GameMain/Scripts/Presentation/Shop/ShopController.BuildContext.cs b/Assets/GameMain/Scripts/Presentation/Shop/ShopController.BuildContext.cs index d7ec1f7..8fc12cb 100644 --- a/Assets/GameMain/Scripts/Presentation/Shop/ShopController.BuildContext.cs +++ b/Assets/GameMain/Scripts/Presentation/Shop/ShopController.BuildContext.cs @@ -95,7 +95,7 @@ namespace SepCore.UI { return new DisplayItemContext { - IconAssetName = weaponBase.WeaponData.IconAssetName, + IconAssetName = weaponBase.WeaponData.Sprite, Rarity = weaponBase.WeaponData.Rarity, IsWeapon = true }; @@ -124,7 +124,7 @@ namespace SepCore.UI ItemType.Weapon => await SpriteLoader.LoadSpriteByKeyAsync(rawData.DataRow switch { WeaponConfig weaponConfig => weaponConfig.Sprite, - WeaponData weaponData => weaponData.IconAssetName, + WeaponData weaponData => weaponData.Sprite, _ => string.Empty }), ItemType.Prop => await SpriteLoader.LoadSpriteByKeyAsync(((PropConfig)rawData.DataRow).Sprite), diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Enemy/EnemyBase.cs b/Assets/GameMain/Scripts/Runtime/EntityLogic/Enemy/EnemyBase.cs index 3a5f5ea..4f27cfd 100644 --- a/Assets/GameMain/Scripts/Runtime/EntityLogic/Enemy/EnemyBase.cs +++ b/Assets/GameMain/Scripts/Runtime/EntityLogic/Enemy/EnemyBase.cs @@ -2,7 +2,6 @@ using SepCore.AsyncTask; using SepCore.Definition; using SepCore.Entity; -using SepCore.Timer; using UnityEngine; public abstract class EnemyBase : TargetableObject @@ -16,29 +15,6 @@ public abstract class EnemyBase : TargetableObject protected EnemyData _enemyData; - protected bool _canAttack; - protected TimerHandle _attackTimerHandle; - - protected void StartAttackCooldown(float cooldown) - { - _canAttack = false; - _attackTimerHandle = GameEntry.Timer.ScheduleOnce(cooldown, () => _canAttack = true, this); - } - - protected void ResetAttackCooldown(float cooldown) - { - GameEntry.Timer.Cancel(_attackTimerHandle); - _canAttack = false; - _attackTimerHandle = GameEntry.Timer.ScheduleOnce(cooldown, () => _canAttack = true, this); - } - - protected void CancelAttackCooldown() - { - GameEntry.Timer.Cancel(_attackTimerHandle); - _attackTimerHandle = TimerHandle.Invalid; - _canAttack = false; - } - protected override void OnShow(object userData) { base.OnShow(userData); diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Enemy/EnemyProjectile.cs b/Assets/GameMain/Scripts/Runtime/EntityLogic/Enemy/EnemyProjectile.cs index df28e51..afac194 100644 --- a/Assets/GameMain/Scripts/Runtime/EntityLogic/Enemy/EnemyProjectile.cs +++ b/Assets/GameMain/Scripts/Runtime/EntityLogic/Enemy/EnemyProjectile.cs @@ -53,11 +53,11 @@ namespace SepCore.Entity if (_projectileData.OwnerCamp == CampType.Player) { - gameObject.layer = LayerMask.NameToLayer("PlayerWeapon"); + gameObject.layer = Constant.Layer.PlayerWeaponLayerId; } else if (_projectileData.OwnerCamp == CampType.Enemy) { - gameObject.layer = LayerMask.NameToLayer("EnemyWeapon"); + gameObject.layer = Constant.Layer.EnemyWeaponLayerId; } SetColliderEnabled(false); diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/EntityBase.cs b/Assets/GameMain/Scripts/Runtime/EntityLogic/EntityBase.cs index 1dcc733..0a1145d 100644 --- a/Assets/GameMain/Scripts/Runtime/EntityLogic/EntityBase.cs +++ b/Assets/GameMain/Scripts/Runtime/EntityLogic/EntityBase.cs @@ -1,4 +1,5 @@ using SepCore.Entity; +using SepCore.Timer; using GameFramework; using UnityEngine; using UnityGameFramework.Runtime; @@ -9,6 +10,11 @@ namespace SepCore.Entity { [SerializeField] private EntityDataBase _entityData = null; + protected bool _canAttack; + protected TimerHandle _attackTimerHandle; + + public bool CanAttack => _canAttack; + public int Id => Entity.Id; public Animation CachedAnimation { get; private set; } @@ -47,6 +53,26 @@ namespace SepCore.Entity base.OnHide(isShutdown, userData); } + protected void StartAttackCooldown(float cooldown) + { + _canAttack = false; + _attackTimerHandle = GameEntry.Timer.ScheduleOnce(cooldown, () => _canAttack = true, this); + } + + public void ResetAttackCooldown(float cooldown) + { + GameEntry.Timer.Cancel(_attackTimerHandle); + _canAttack = false; + _attackTimerHandle = GameEntry.Timer.ScheduleOnce(cooldown, () => _canAttack = true, this); + } + + protected void CancelAttackCooldown() + { + GameEntry.Timer.Cancel(_attackTimerHandle); + _attackTimerHandle = TimerHandle.Invalid; + _canAttack = false; + } + protected override void OnAttached(EntityLogic childEntity, Transform parentTransform, object userData) { base.OnAttached(childEntity, parentTransform, userData); diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/FSM.meta b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/FSM.meta new file mode 100644 index 0000000..6d1b743 --- /dev/null +++ b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/FSM.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 299f47fcfb4de4c4ea5a78d7ed206291 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/FSM/WeaponStateBase.cs b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/FSM/WeaponStateBase.cs new file mode 100644 index 0000000..c81c8ef --- /dev/null +++ b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/FSM/WeaponStateBase.cs @@ -0,0 +1,17 @@ +using SepCore.Definition; + +namespace SepCore.Entity +{ + /// + /// 武器状态基类。 + /// + public abstract class WeaponStateBase + { + public abstract WeaponStateType State { get; } + public abstract void OnInit(WeaponBase weapon); + public abstract void OnEnter(); + public abstract void OnUpdate(float elapseSeconds, float realElapseSeconds); + public abstract void OnLeave(); + public override string ToString() => State.ToString(); + } +} diff --git a/Assets/GameMain/Scripts/Base/EntityData/Weapon/WeaponHandgunData.cs.meta b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/FSM/WeaponStateBase.cs.meta similarity index 83% rename from Assets/GameMain/Scripts/Base/EntityData/Weapon/WeaponHandgunData.cs.meta rename to Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/FSM/WeaponStateBase.cs.meta index 53b24f0..a67812e 100644 --- a/Assets/GameMain/Scripts/Base/EntityData/Weapon/WeaponHandgunData.cs.meta +++ b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/FSM/WeaponStateBase.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 574d105bf89bf7546a682ed407708034 +guid: 64f43677dac08f744848382cab8588fb MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/FSM/WeaponStateMachine.cs b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/FSM/WeaponStateMachine.cs new file mode 100644 index 0000000..694cd7e --- /dev/null +++ b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/FSM/WeaponStateMachine.cs @@ -0,0 +1,52 @@ +using System.Collections.Generic; +using SepCore.Definition; + +namespace SepCore.Entity +{ + /// + /// 武器状态机。负责状态注册、切换与驱动。 + /// + public class WeaponStateMachine + { + private readonly WeaponBase _weapon; + private readonly Dictionary _states = new(); + + private WeaponStateBase _currentState; + + public WeaponStateMachine(WeaponBase weapon) + { + _weapon = weapon; + } + + public bool IsBuilt => _states.Count > 0; + + public bool Contains(WeaponStateType stateType) + { + return _states.ContainsKey(stateType); + } + + public void Register(WeaponStateBase state) + { + state.OnInit(_weapon); + _states[state.State] = state; + } + + public void Update(float elapseSeconds, float realElapseSeconds) + { + _currentState?.OnUpdate(elapseSeconds, realElapseSeconds); + } + + public bool TryTransition(WeaponStateType stateType) + { + if (!_states.TryGetValue(stateType, out WeaponStateBase nextState)) + { + return false; + } + + _currentState?.OnLeave(); + _currentState = nextState; + _currentState.OnEnter(); + return true; + } + } +} diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/TargetSelector/HighestHealthTargetSelector.cs.meta b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/FSM/WeaponStateMachine.cs.meta similarity index 83% rename from Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/TargetSelector/HighestHealthTargetSelector.cs.meta rename to Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/FSM/WeaponStateMachine.cs.meta index 88b7756..48e3322 100644 --- a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/TargetSelector/HighestHealthTargetSelector.cs.meta +++ b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/FSM/WeaponStateMachine.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 54932952c9fa3fd4dbe6d21f2a484b4d +guid: d29897e3011246748bb0c939e54a0ca5 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/TargetSelector/HighestHealthTargetSelector.cs b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/TargetSelector/HighestHealthTargetSelector.cs deleted file mode 100644 index 44f6f1d..0000000 --- a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/TargetSelector/HighestHealthTargetSelector.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System.Collections.Generic; -using SepCore.Components; -using SepCore.CustomUtility; - -namespace SepCore.Entity -{ - public sealed class HighestHealthTargetSelector : ITargetSelector - { - public EntityBase SelectTarget(WeaponBase weapon, IEnumerable candidates, float maxSqrRange) - { - if (weapon == null || candidates == null) - { - return null; - } - - EntityBase target = null; - float maxHp = float.MinValue; - float maxSqr = maxSqrRange > 0f ? maxSqrRange : float.MaxValue; - - foreach (var candidate in candidates) - { - if (candidate == null || !candidate.Available) continue; - - if (maxSqrRange > 0f && AIUtility.GetSqrMagnitudeXZ(weapon, candidate) >= maxSqr) continue; - - if (!TryGetCurrentHealth(candidate, out var hp)) continue; - - if (hp <= maxHp) continue; - - maxHp = hp; - target = candidate; - } - - return target; - } - - private static bool TryGetCurrentHealth(EntityBase target, out float health) - { - health = 0f; - if (target == null) return false; - - var healthComponent = target.GetComponent(); - if (healthComponent == null) return false; - - health = healthComponent.CurrentHealth; - return true; - } - } -} diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/TargetSelector/LowestHealthTargetSelector.cs b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/TargetSelector/LowestHealthTargetSelector.cs deleted file mode 100644 index 9af4ba1..0000000 --- a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/TargetSelector/LowestHealthTargetSelector.cs +++ /dev/null @@ -1,53 +0,0 @@ -using System.Collections.Generic; -using SepCore.Components; -using SepCore.Definition; -using SepCore.CustomUtility; - -namespace SepCore.Entity -{ - public sealed class LowestHealthTargetSelector : ITargetSelector - { - public EntityBase SelectTarget(WeaponBase weapon, IEnumerable candidates, float maxSqrRange) - { - if (weapon == null || candidates == null) - { - return null; - } - - EntityBase target = null; - float minHp = float.MaxValue; - float maxSqr = maxSqrRange > 0f ? maxSqrRange : float.MaxValue; - - foreach (var candidate in candidates) - { - if (candidate == null || !candidate.Available) continue; - - if (maxSqrRange > 0f && AIUtility.GetSqrMagnitudeXZ(weapon, candidate) >= maxSqr) continue; - - if (!TryGetHealth(candidate, out var hp)) continue; - - if (hp >= minHp) continue; - - minHp = hp; - target = candidate; - } - - return target; - } - - private static bool TryGetHealth(EntityBase target, out float health) - { - health = 0f; - if (target == null) return false; - - var statComponent = target.GetComponent(); - if (statComponent == null) return false; - - var hpStat = statComponent.GetStat(StatType.MaxHealth); - if (hpStat == null) return false; - - health = hpStat.Value; - return true; - } - } -} diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/TargetSelector/LowestHealthTargetSelector.cs.meta b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/TargetSelector/LowestHealthTargetSelector.cs.meta deleted file mode 100644 index cba2a2d..0000000 --- a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/TargetSelector/LowestHealthTargetSelector.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 081d67a491f5792479306d88091168e3 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/TargetSelector/TargetSelectorType.cs b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/TargetSelector/TargetSelectorType.cs deleted file mode 100644 index 3b4ef8d..0000000 --- a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/TargetSelector/TargetSelectorType.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace SepCore.Entity -{ - public enum TargetSelectorType - { - Nearest = 0, - HighestHealth = 1, - LowestHealth = 2 - } -} diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/TargetSelector/TargetSelectorType.cs.meta b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/TargetSelector/TargetSelectorType.cs.meta deleted file mode 100644 index ea2704e..0000000 --- a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/TargetSelector/TargetSelectorType.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 4eb1e0b99139fdd4280c8616804a8f77 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponBase.cs b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponBase.cs index 88df126..b662234 100644 --- a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponBase.cs +++ b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponBase.cs @@ -1,58 +1,48 @@ using System.Collections.Generic; using SepCore.Components; using SepCore.Definition; -using SepCore.Entity; using GameFramework; using SepCore.CustomUtility; -using SepCore.Timer; using UnityEngine; using UnityGameFramework.Runtime; namespace SepCore.Entity { - public enum WeaponStateType - { - Disabled, - Attack, - Idle, - Check_OutRange, - Check_InRange, - } - /// /// 武器类。 /// public abstract class WeaponBase : EntityBase { - protected const string AttachPoint = "Weapon Point"; - protected bool _isAttacking = false; [SerializeField] protected bool _isEnabled = false; public WeaponData WeaponData { get; protected set; } + public float AttackCooldown => WeaponData.Cooldown; + public bool IsAttacking => _isAttacking; - protected ITargetSelector TargetSelector { get; set; } + protected ITargetSelector TargetSelector { get; private set; } - protected Dictionary _states; - - protected WeaponStateBase _currentState; + protected WeaponStateMachine StateMachine { get; private set; } protected EntityBase _target; - protected bool _canAttack; - protected TimerHandle _attackTimerHandle; - protected float _sqrRange; + public EntityBase Target => _target; + + public float SqrRange => _sqrRange; + protected StatProperty AttackStat { get; private set; } = new(); private StatComponent _attackStatComponent; private System.Action _attackStatCallback; - private static readonly List s_EmptyCandidates = new(); + [SerializeField] protected float _rotateSpeed = 5f; + [SerializeField] protected LayerMask _hitMask = ~0; + protected Quaternion _cachedRotation; #region Lifecycle @@ -60,16 +50,31 @@ namespace SepCore.Entity { base.OnInit(userData); - if (TargetSelector == null) - { - TargetSelector = CreateSelector(DefaultTargetSelectorType); - } + TargetSelector = new NearestTargetSelector(); } protected sealed override void OnShow(object userData) { base.OnShow(userData); + WeaponData = RequireWeaponData(userData); + if (WeaponData == null) return; + + StartAttackCooldown(WeaponData.Cooldown); + _sqrRange = WeaponData.AttackRange * WeaponData.AttackRange; + _cachedRotation = CachedTransform.rotation; + + if (WeaponData.OwnerCamp == CampType.Player) + { + gameObject.layer = Constant.Layer.PlayerWeaponLayerId; + _hitMask = Constant.Layer.EnemyLayerMask; + } + else if (WeaponData.OwnerCamp == CampType.Enemy) + { + gameObject.layer = Constant.Layer.EnemyWeaponLayerId; + _hitMask = Constant.Layer.PlayerLayerMask; + } + if (!OnWeaponShow(userData)) return; EnsureStatesBuilt(); @@ -78,6 +83,7 @@ namespace SepCore.Entity protected sealed override void OnHide(bool isShutdown, object userData) { + CancelAttackCooldown(); ReleaseAttackStatSubscription(); OnWeaponHide(userData); base.OnHide(isShutdown, userData); @@ -107,29 +113,69 @@ namespace SepCore.Entity protected virtual void OnWeaponAttach(EntityLogic parentEntity, Transform parentTransform, object userData) { + BindAttackStatFromOwner(parentEntity); } protected virtual void OnWeaponDetach(EntityLogic parentEntity, object userData) { + ReleaseAttackStatSubscription(); } protected override void OnUpdate(float elapseSeconds, float realElapseSeconds) { base.OnUpdate(elapseSeconds, realElapseSeconds); - if (!_isEnabled) return; - _currentState?.OnUpdate(elapseSeconds, realElapseSeconds); + if (!_isEnabled || StateMachine == null) return; + StateMachine.Update(elapseSeconds, realElapseSeconds); } #endregion - public abstract ImpactData GetImpactData(); - protected abstract void Attack(); - protected abstract void Check(); + public virtual ImpactData GetImpactData() + { + return new ImpactData(WeaponData.OwnerCamp, WeaponData.Attack, AttackStat); + } + + public abstract void Attack(); + + public virtual void Check() + { + _target = SelectTarget(_sqrRange); + } + + public virtual void RotateToTarget(float elapseSeconds) + { + if (_target == null || !_target.Available) return; + + Vector3 directionToTarget = _target.CachedTransform.position - CachedTransform.position; + directionToTarget.y = 0f; + if (directionToTarget.sqrMagnitude <= Mathf.Epsilon) return; + + Quaternion startRotation = CachedTransform.rotation; + Quaternion targetRotation = Quaternion.LookRotation(directionToTarget.normalized, Vector3.up); + CachedTransform.rotation = Quaternion.Slerp(startRotation, targetRotation, _rotateSpeed * elapseSeconds); + } + + public virtual void RotateToOrigin(float elapseSeconds) + { + Quaternion startRotation = CachedTransform.rotation; + CachedTransform.rotation = Quaternion.Slerp(startRotation, _cachedRotation, _rotateSpeed * elapseSeconds); + } + + protected void FaceTargetImmediately() + { + if (_target == null || !_target.Available) return; + + Vector3 directionToTarget = _target.CachedTransform.position - CachedTransform.position; + directionToTarget.y = 0f; + if (directionToTarget.sqrMagnitude <= Mathf.Epsilon) return; + + CachedTransform.rotation = Quaternion.LookRotation(directionToTarget.normalized, Vector3.up); + } + protected abstract void BuildStates(); - protected virtual WeaponStateType InitialState => WeaponStateType.Idle; - protected virtual TargetSelectorType DefaultTargetSelectorType => TargetSelectorType.Nearest; + protected WeaponStateType InitialState => WeaponStateType.Idle; protected void RegisterState(WeaponStateBase state) { @@ -139,38 +185,34 @@ namespace SepCore.Entity return; } - state.OnInit(this); - _states[state.State] = state; + StateMachine.Register(state); } protected void EnsureStatesBuilt() { - if (_states != null) return; + if (StateMachine != null) return; - _states = new Dictionary(); + StateMachine = new WeaponStateMachine(this); BuildStates(); } - protected virtual void TransitionTo(WeaponStateType newState) + public void TransitionTo(WeaponStateType newState) { - if (_states == null || !_states.TryGetValue(newState, out var nextState)) + if (!StateMachine.TryTransition(newState)) { Log.Error("Weapon state not found: {0}", newState); - return; } - - _currentState?.OnLeave(); - _currentState = nextState; - _currentState.OnEnter(); } public void SetEnabled(bool value) { + if (value == _isEnabled) return; + _isEnabled = value; OnEnabledChanged(value); - if (_states == null || _states.Count == 0) return; + if (StateMachine == null || !StateMachine.IsBuilt) return; if (value) { @@ -178,9 +220,9 @@ namespace SepCore.Entity return; } - if (_states.ContainsKey(WeaponStateType.Disabled)) + if (StateMachine.Contains(WeaponStateType.None)) { - TransitionTo(WeaponStateType.Disabled); + TransitionTo(WeaponStateType.None); } } @@ -199,23 +241,17 @@ namespace SepCore.Entity return data; } - protected virtual IEnumerable GetCandidates() + protected IEnumerable GetCandidates() { - var enemyManager = GameEntry.EnemyManager; - return enemyManager != null ? enemyManager.Enemies : s_EmptyCandidates; + return GameEntry.EnemyManager.Enemies; } protected EntityBase SelectTarget(float maxSqrRange) { - return TargetSelector != null ? TargetSelector.SelectTarget(this, GetCandidates(), maxSqrRange) : null; + return TargetSelector.SelectTarget(this, GetCandidates(), maxSqrRange); } - protected float GetSqrDistance(EntityBase target) - { - return target != null ? AIUtility.GetSqrMagnitudeXZ(this, target) : float.MaxValue; - } - - protected bool IsInRange(EntityBase target, float sqrRange) + public bool IsInRange(EntityBase target, float sqrRange) { if (target == null) return false; return AIUtility.GetSqrMagnitudeXZ(this, target) < sqrRange; @@ -223,61 +259,22 @@ namespace SepCore.Entity protected bool TryQueueAreaCollisionQuery(in Vector3 center, float radius, int maxTargets = 16) { - var simulationWorld = GameEntry.SimulationWorld; - if (simulationWorld == null) - { - return false; - } - - int ownerEntityId = WeaponData != null ? WeaponData.OwnerId : Id; - return simulationWorld.TryRequestAreaCollision(Id, ownerEntityId, in center, radius, maxTargets); + return GameEntry.SimulationWorld.TryRequestAreaCollision(Id, WeaponData.OwnerId, in center, radius, + maxTargets); } protected bool TryQueueSectorCollisionQuery(in Vector3 center, float radius, in Vector3 direction, float halfAngleDeg, int maxTargets = 16) { - var simulationWorld = GameEntry.SimulationWorld; - if (simulationWorld == null) - { - return false; - } - - int ownerEntityId = WeaponData != null ? WeaponData.OwnerId : Id; - return simulationWorld.TryRequestSectorCollision(Id, ownerEntityId, in center, radius, in direction, - halfAngleDeg, maxTargets); + return GameEntry.SimulationWorld.TryRequestSectorCollision(Id, WeaponData.OwnerId, in center, radius, + in direction, halfAngleDeg, maxTargets); } protected bool TryQueueRectangleCollisionQuery(in Vector3 center, float halfWidth, float halfLength, in Vector3 direction, int maxTargets = 16) { - var simulationWorld = GameEntry.SimulationWorld; - if (simulationWorld == null) - { - return false; - } - - int ownerEntityId = WeaponData != null ? WeaponData.OwnerId : Id; - return simulationWorld.TryRequestRectangleCollision(Id, ownerEntityId, in center, halfWidth, halfLength, - in direction, maxTargets); - } - - protected void SetTargetSelector(TargetSelectorType selectorType) - { - TargetSelector = CreateSelector(selectorType); - } - - protected static ITargetSelector CreateSelector(TargetSelectorType selectorType) - { - switch (selectorType) - { - case TargetSelectorType.HighestHealth: - return new HighestHealthTargetSelector(); - case TargetSelectorType.LowestHealth: - return new LowestHealthTargetSelector(); - case TargetSelectorType.Nearest: - default: - return new NearestTargetSelector(); - } + return GameEntry.SimulationWorld.TryRequestRectangleCollision(Id, WeaponData.OwnerId, in center, + halfWidth, halfLength, in direction, maxTargets); } protected void BindAttackStatFromOwner(EntityLogic parentEntity) @@ -308,35 +305,5 @@ namespace SepCore.Entity _attackStatCallback = null; AttackStat = new StatProperty(); } - - protected void StartAttackCooldown(float cooldown) - { - _canAttack = false; - _attackTimerHandle = GameEntry.Timer.ScheduleOnce(cooldown, () => _canAttack = true, this); - } - - protected void ResetAttackCooldown(float cooldown) - { - GameEntry.Timer.Cancel(_attackTimerHandle); - _canAttack = false; - _attackTimerHandle = GameEntry.Timer.ScheduleOnce(cooldown, () => _canAttack = true, this); - } - - protected void CancelAttackCooldown() - { - GameEntry.Timer.Cancel(_attackTimerHandle); - _attackTimerHandle = TimerHandle.Invalid; - _canAttack = false; - } - } - - public abstract class WeaponStateBase - { - public abstract WeaponStateType State { get; } - public abstract void OnInit(WeaponBase weapon); - public abstract void OnEnter(); - public abstract void OnUpdate(float elapseSeconds, float realElapseSeconds); - public abstract void OnLeave(); - public override string ToString() => State.ToString(); } } diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponHandgun/WeaponHandgun.AttackState.cs b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponHandgun/WeaponHandgun.AttackState.cs deleted file mode 100644 index 4e3dcac..0000000 --- a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponHandgun/WeaponHandgun.AttackState.cs +++ /dev/null @@ -1,25 +0,0 @@ -namespace SepCore.Entity -{ - public partial class WeaponHandgun - { - private class AttackState : WeaponStateBase - { - private WeaponHandgun _weapon; - public override WeaponStateType State => WeaponStateType.Attack; - public override void OnInit(WeaponBase weapon) => _weapon = weapon as WeaponHandgun; - - public override void OnEnter() - { - _weapon.ResetAttackCooldown(_weapon._weaponData.Cooldown); - _weapon.Attack(); - } - - public override void OnUpdate(float elapseSeconds, float realElapseSeconds) - { - _weapon.TransitionTo(WeaponStateType.Check_InRange); - } - - public override void OnLeave() { } - } - } -} diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponHandgun/WeaponHandgun.AttackState.cs.meta b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponHandgun/WeaponHandgun.AttackState.cs.meta deleted file mode 100644 index 14646b2..0000000 --- a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponHandgun/WeaponHandgun.AttackState.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 4e72df067466464fa3be92bfd049dd0d -timeCreated: 1771579220 \ No newline at end of file diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponHandgun/WeaponHandgun.CheckInRangeState.cs b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponHandgun/WeaponHandgun.CheckInRangeState.cs deleted file mode 100644 index ad8f9a6..0000000 --- a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponHandgun/WeaponHandgun.CheckInRangeState.cs +++ /dev/null @@ -1,45 +0,0 @@ -namespace SepCore.Entity -{ - public partial class WeaponHandgun - { - private class CheckInRangeState : WeaponStateBase - { - private WeaponHandgun _weapon; - public override WeaponStateType State => WeaponStateType.Check_InRange; - public override void OnInit(WeaponBase weapon) => _weapon = weapon as WeaponHandgun; - - public override void OnEnter() - { - if (_weapon._canAttack) - { - _weapon.TransitionTo(WeaponStateType.Attack); - } - } - - public override void OnUpdate(float elapseSeconds, float realElapseSeconds) - { - _weapon.Check(); - _weapon.RotateToTarget(elapseSeconds); - - if (_weapon._target == null || !_weapon._target.Available) - { - _weapon.TransitionTo(WeaponStateType.Idle); - return; - } - - if (!_weapon.IsInRange(_weapon._target, _weapon._sqrRange)) - { - _weapon.TransitionTo(WeaponStateType.Check_OutRange); - return; - } - - if (_weapon._canAttack) - { - _weapon.TransitionTo(WeaponStateType.Attack); - } - } - - public override void OnLeave() { } - } - } -} diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponHandgun/WeaponHandgun.CheckInRangeState.cs.meta b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponHandgun/WeaponHandgun.CheckInRangeState.cs.meta deleted file mode 100644 index d807587..0000000 --- a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponHandgun/WeaponHandgun.CheckInRangeState.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: bfd76c0fb7284ceaa28f78c702f595da -timeCreated: 1771579231 \ No newline at end of file diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponHandgun/WeaponHandgun.CheckOutRangeState.cs b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponHandgun/WeaponHandgun.CheckOutRangeState.cs deleted file mode 100644 index 99e9058..0000000 --- a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponHandgun/WeaponHandgun.CheckOutRangeState.cs +++ /dev/null @@ -1,32 +0,0 @@ -namespace SepCore.Entity -{ - public partial class WeaponHandgun - { - private class CheckOutRangeState : WeaponStateBase - { - private WeaponHandgun _weapon; - public override WeaponStateType State => WeaponStateType.Check_OutRange; - public override void OnInit(WeaponBase weapon) => _weapon = weapon as WeaponHandgun; - public override void OnEnter() { } - - public override void OnUpdate(float elapseSeconds, float realElapseSeconds) - { - _weapon.Check(); - _weapon.RotateToTarget(elapseSeconds); - - if (_weapon._target == null || !_weapon._target.Available) - { - _weapon.TransitionTo(WeaponStateType.Idle); - return; - } - - if (_weapon.IsInRange(_weapon._target, _weapon._sqrRange)) - { - _weapon.TransitionTo(WeaponStateType.Check_InRange); - } - } - - public override void OnLeave() { } - } - } -} diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponHandgun/WeaponHandgun.CheckOutRangeState.cs.meta b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponHandgun/WeaponHandgun.CheckOutRangeState.cs.meta deleted file mode 100644 index 45f7a6c..0000000 --- a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponHandgun/WeaponHandgun.CheckOutRangeState.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 3a9f936d3c8643f7bf632734548f800c -timeCreated: 1771579241 \ No newline at end of file diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponHandgun/WeaponHandgun.IdleState.cs b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponHandgun/WeaponHandgun.IdleState.cs deleted file mode 100644 index 81bbaee..0000000 --- a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponHandgun/WeaponHandgun.IdleState.cs +++ /dev/null @@ -1,26 +0,0 @@ -namespace SepCore.Entity -{ - public partial class WeaponHandgun - { - private class IdleState : WeaponStateBase - { - private WeaponHandgun _weapon; - public override WeaponStateType State => WeaponStateType.Idle; - public override void OnInit(WeaponBase weapon) => _weapon = weapon as WeaponHandgun; - public override void OnEnter() { } - - public override void OnUpdate(float elapseSeconds, float realElapseSeconds) - { - _weapon.Check(); - _weapon.RotateToOrigin(elapseSeconds); - - if (_weapon._target != null && _weapon._target.Available) - { - _weapon.TransitionTo(WeaponStateType.Check_OutRange); - } - } - - public override void OnLeave() { } - } - } -} diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponHandgun/WeaponHandgun.IdleState.cs.meta b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponHandgun/WeaponHandgun.IdleState.cs.meta deleted file mode 100644 index 85dfec6..0000000 --- a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponHandgun/WeaponHandgun.IdleState.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 9c5341944d1a467b8553d31bc3d81d5b -timeCreated: 1771579252 \ No newline at end of file diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponHandgun/WeaponHandgun.cs b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponHandgun/WeaponHandgun.cs index 61bcb2d..482c1cf 100644 --- a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponHandgun/WeaponHandgun.cs +++ b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponHandgun/WeaponHandgun.cs @@ -1,20 +1,12 @@ -using SepCore.Definition; using SepCore.CustomUtility; using UnityEngine; -using UnityGameFramework.Runtime; namespace SepCore.Entity { - public partial class WeaponHandgun : WeaponBase + public class WeaponHandgun : WeaponBase { #region Property - private WeaponHandgunData _weaponData; - - private Quaternion _cachedRotation; - - [SerializeField] private float _rotateSpeed = 6f; - [SerializeField] private LayerMask _hitMask = ~0; [SerializeField] private Vector3 _fireOriginOffset = Vector3.zero; [SerializeField] private float _hitMarkerSize = 0.2f; @@ -26,21 +18,15 @@ namespace SepCore.Entity #endregion - - public override ImpactData GetImpactData() - { - return new ImpactData(_weaponData.OwnerCamp, _weaponData.Attack, AttackStat); - } - protected override void BuildStates() { - RegisterState(new IdleState()); - RegisterState(new CheckOutRangeState()); - RegisterState(new CheckInRangeState()); - RegisterState(new AttackState()); + RegisterState(new WeaponHandgunIdleState()); + RegisterState(new WeaponHandgunSeekState()); + RegisterState(new WeaponHandgunAimState()); + RegisterState(new WeaponHandgunAttackState()); } - protected override void Attack() + public override void Attack() { FaceTargetImmediately(); @@ -49,43 +35,12 @@ namespace SepCore.Entity return; } - _attackEffect?.Play(this, hitPosition, targetable, 0f); + _attackEffect.Play(this, hitPosition, targetable, 0f); _isAttacking = true; AIUtility.PerformCollision(targetable, this); _isAttacking = false; } - protected override void Check() - { - _target = SelectTarget(_sqrRange); - } - - private void RotateToTarget(float elapseSeconds) - { - if (_target == null || !_target.Available) return; - - Vector3 directionToTarget = (_target.CachedTransform.position - CachedTransform.position).normalized; - Quaternion targetRotation = Quaternion.LookRotation(directionToTarget, Vector3.up); - CachedTransform.rotation = Quaternion.Slerp(CachedTransform.rotation, targetRotation, - _rotateSpeed * elapseSeconds); - } - - private void RotateToOrigin(float elapseSeconds) - { - CachedTransform.rotation = Quaternion.Slerp(CachedTransform.rotation, _cachedRotation, - _rotateSpeed * elapseSeconds); - } - - private void FaceTargetImmediately() - { - if (_target == null || !_target.Available) return; - - Vector3 directionToTarget = _target.CachedTransform.position - CachedTransform.position; - if (directionToTarget.sqrMagnitude <= Mathf.Epsilon) return; - - CachedTransform.rotation = Quaternion.LookRotation(directionToTarget.normalized, Vector3.up); - } - private bool TryResolveAttackTarget(out TargetableObject targetable, out Vector3 hitPosition) { targetable = _target as TargetableObject; @@ -95,17 +50,12 @@ namespace SepCore.Entity return false; } - Transform targetTransform = targetable.CachedTransform; - if (targetTransform == null) - { - return false; - } - - hitPosition = targetTransform.position; + Vector3 targetPosition = targetable.CachedTransform.position; + hitPosition = targetPosition; Vector3 fireOrigin = CachedTransform.TransformPoint(_fireOriginOffset); - Vector3 directionToTarget = targetTransform.position - fireOrigin; - float maxDistance = Mathf.Max(0.1f, _weaponData.AttackRange); + Vector3 directionToTarget = targetPosition - fireOrigin; + float maxDistance = WeaponData.AttackRange; if (directionToTarget.sqrMagnitude > Mathf.Epsilon && Physics.Raycast(fireOrigin, directionToTarget.normalized, out RaycastHit hit, maxDistance, _hitMask, QueryTriggerInteraction.Collide)) @@ -124,46 +74,16 @@ namespace SepCore.Entity protected override bool OnWeaponShow(object userData) { - _weaponData = RequireWeaponData(userData); - if (_weaponData == null) return false; - - WeaponData = _weaponData; - StartAttackCooldown(_weaponData.Cooldown); - _sqrRange = _weaponData.AttackRange * _weaponData.AttackRange; - _cachedRotation = CachedTransform.rotation; _attackEffect = new HandgunHitMarkerAttackEffect(_hitMarkerSize, _hitMarkerYOffset, _hitMarkerDuration, _hitMarkerColor); - - if (_weaponData.OwnerCamp == CampType.Player) - { - gameObject.layer = LayerMask.NameToLayer("PlayerWeapon"); - _hitMask = LayerMask.GetMask("Enemy"); - } - else if (_weaponData.OwnerCamp == CampType.Enemy) - { - gameObject.layer = LayerMask.NameToLayer("EnemyWeapon"); - _hitMask = LayerMask.GetMask("Player"); - } - return true; } protected override void OnWeaponHide(object userData) { - CancelAttackCooldown(); _attackEffect = null; } - protected override void OnWeaponAttach(EntityLogic parentEntity, Transform parentTransform, object userData) - { - BindAttackStatFromOwner(parentEntity); - } - - protected override void OnWeaponDetach(EntityLogic parentEntity, object userData) - { - ReleaseAttackStatSubscription(); - } - #endregion } } diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponHandgun/WeaponHandgunAimState.cs b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponHandgun/WeaponHandgunAimState.cs new file mode 100644 index 0000000..ec21025 --- /dev/null +++ b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponHandgun/WeaponHandgunAimState.cs @@ -0,0 +1,51 @@ +using SepCore.Definition; + +namespace SepCore.Entity +{ + /// + /// 手枪的瞄准状态。 + /// + public sealed class WeaponHandgunAimState : WeaponStateBase + { + private WeaponHandgun _weapon; + + public override WeaponStateType State => WeaponStateType.Aim; + + public override void OnInit(WeaponBase weapon) => _weapon = (WeaponHandgun)weapon; + + public override void OnEnter() + { + if (_weapon.CanAttack) + { + _weapon.TransitionTo(WeaponStateType.Attack); + } + } + + public override void OnUpdate(float elapseSeconds, float realElapseSeconds) + { + _weapon.Check(); + _weapon.RotateToTarget(elapseSeconds); + + if (_weapon.Target == null || !_weapon.Target.Available) + { + _weapon.TransitionTo(WeaponStateType.Idle); + return; + } + + if (!_weapon.IsInRange(_weapon.Target, _weapon.SqrRange)) + { + _weapon.TransitionTo(WeaponStateType.Seek); + return; + } + + if (_weapon.CanAttack) + { + _weapon.TransitionTo(WeaponStateType.Attack); + } + } + + public override void OnLeave() + { + } + } +} diff --git a/Assets/GameMain/Scripts/Base/EntityData/Weapon/WeaponKnifeData.cs.meta b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponHandgun/WeaponHandgunAimState.cs.meta similarity index 83% rename from Assets/GameMain/Scripts/Base/EntityData/Weapon/WeaponKnifeData.cs.meta rename to Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponHandgun/WeaponHandgunAimState.cs.meta index a087ed2..fefdc42 100644 --- a/Assets/GameMain/Scripts/Base/EntityData/Weapon/WeaponKnifeData.cs.meta +++ b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponHandgun/WeaponHandgunAimState.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: da25d8e0669f0194d8f56f4283c67b38 +guid: 71e311baa75a23448a593f2abb05999c MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponHandgun/WeaponHandgunAttackState.cs b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponHandgun/WeaponHandgunAttackState.cs new file mode 100644 index 0000000..e0c0b5b --- /dev/null +++ b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponHandgun/WeaponHandgunAttackState.cs @@ -0,0 +1,34 @@ +using SepCore.Definition; + +namespace SepCore.Entity +{ + /// + /// 手枪的攻击状态。 + /// + public sealed class WeaponHandgunAttackState : WeaponStateBase + { + private WeaponHandgun _weapon; + + public override WeaponStateType State => WeaponStateType.Attack; + + public override void OnInit(WeaponBase weapon) => _weapon = (WeaponHandgun)weapon; + + public override void OnEnter() + { + _weapon.ResetAttackCooldown(_weapon.AttackCooldown); + _weapon.Attack(); + } + + public override void OnUpdate(float elapseSeconds, float realElapseSeconds) + { + if (!_weapon.IsAttacking) + { + _weapon.TransitionTo(WeaponStateType.Aim); + } + } + + public override void OnLeave() + { + } + } +} diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponHandgun/WeaponHandgunAttackState.cs.meta b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponHandgun/WeaponHandgunAttackState.cs.meta new file mode 100644 index 0000000..64fe420 --- /dev/null +++ b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponHandgun/WeaponHandgunAttackState.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f0513d1d0592c344b93c8df22f892ea0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponHandgun/WeaponHandgunIdleState.cs b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponHandgun/WeaponHandgunIdleState.cs new file mode 100644 index 0000000..89cbf3a --- /dev/null +++ b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponHandgun/WeaponHandgunIdleState.cs @@ -0,0 +1,35 @@ +using SepCore.Definition; + +namespace SepCore.Entity +{ + /// + /// 手枪的待机状态。 + /// + public sealed class WeaponHandgunIdleState : WeaponStateBase + { + private WeaponHandgun _weapon; + + public override WeaponStateType State => WeaponStateType.Idle; + + public override void OnInit(WeaponBase weapon) => _weapon = (WeaponHandgun)weapon; + + public override void OnEnter() + { + } + + public override void OnUpdate(float elapseSeconds, float realElapseSeconds) + { + _weapon.Check(); + _weapon.RotateToOrigin(elapseSeconds); + + if (_weapon.Target != null && _weapon.Target.Available) + { + _weapon.TransitionTo(WeaponStateType.Seek); + } + } + + public override void OnLeave() + { + } + } +} diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponHandgun/WeaponHandgunIdleState.cs.meta b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponHandgun/WeaponHandgunIdleState.cs.meta new file mode 100644 index 0000000..8a80571 --- /dev/null +++ b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponHandgun/WeaponHandgunIdleState.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bd6af23da5725ce4385e23b49b0d4811 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponHandgun/WeaponHandgunSeekState.cs b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponHandgun/WeaponHandgunSeekState.cs new file mode 100644 index 0000000..51eed39 --- /dev/null +++ b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponHandgun/WeaponHandgunSeekState.cs @@ -0,0 +1,41 @@ +using SepCore.Definition; + +namespace SepCore.Entity +{ + /// + /// 手枪的搜寻状态。 + /// + public sealed class WeaponHandgunSeekState : WeaponStateBase + { + private WeaponHandgun _weapon; + + public override WeaponStateType State => WeaponStateType.Seek; + + public override void OnInit(WeaponBase weapon) => _weapon = (WeaponHandgun)weapon; + + public override void OnEnter() + { + } + + public override void OnUpdate(float elapseSeconds, float realElapseSeconds) + { + _weapon.Check(); + _weapon.RotateToTarget(elapseSeconds); + + if (_weapon.Target == null || !_weapon.Target.Available) + { + _weapon.TransitionTo(WeaponStateType.Idle); + return; + } + + if (_weapon.IsInRange(_weapon.Target, _weapon.SqrRange)) + { + _weapon.TransitionTo(WeaponStateType.Aim); + } + } + + public override void OnLeave() + { + } + } +} diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponHandgun/WeaponHandgunSeekState.cs.meta b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponHandgun/WeaponHandgunSeekState.cs.meta new file mode 100644 index 0000000..e71f81e --- /dev/null +++ b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponHandgun/WeaponHandgunSeekState.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3e7a9fee7c4ec5f498756d6e17b1259e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponKnife/WeaponKnife.AttackState.cs b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponKnife/WeaponKnife.AttackState.cs deleted file mode 100644 index 834fa11..0000000 --- a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponKnife/WeaponKnife.AttackState.cs +++ /dev/null @@ -1,31 +0,0 @@ -namespace SepCore.Entity -{ - public partial class WeaponKnife - { - private class AttackState : WeaponStateBase - { - private WeaponKnife _weapon; - - public override WeaponStateType State => WeaponStateType.Attack; - public override void OnInit(WeaponBase weapon) => _weapon = weapon as WeaponKnife; - - public override void OnEnter() - { - _weapon.ResetAttackCooldown(_weapon._weaponData.Cooldown); - _weapon.Attack(); - } - - public override void OnUpdate(float elapseSeconds, float realElapseSeconds) - { - if (!_weapon._isAttacking) - { - _weapon.TransitionTo(WeaponStateType.Check_InRange); - } - } - - public override void OnLeave() - { - } - } - } -} diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponKnife/WeaponKnife.AttackState.cs.meta b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponKnife/WeaponKnife.AttackState.cs.meta deleted file mode 100644 index 177f872..0000000 --- a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponKnife/WeaponKnife.AttackState.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 417516ffe5574e0c998105fcaa073de7 -timeCreated: 1771578955 \ No newline at end of file diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponKnife/WeaponKnife.CheckInRangeState.cs b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponKnife/WeaponKnife.CheckInRangeState.cs deleted file mode 100644 index 9c6fe94..0000000 --- a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponKnife/WeaponKnife.CheckInRangeState.cs +++ /dev/null @@ -1,48 +0,0 @@ -namespace SepCore.Entity -{ - public partial class WeaponKnife - { - private class CheckInRangeState : WeaponStateBase - { - private WeaponKnife _weapon; - - public override WeaponStateType State => WeaponStateType.Check_InRange; - public override void OnInit(WeaponBase weapon) => _weapon = weapon as WeaponKnife; - - public override void OnEnter() - { - if (_weapon._canAttack) - { - _weapon.TransitionTo(WeaponStateType.Attack); - } - } - - public override void OnUpdate(float elapseSeconds, float realElapseSeconds) - { - _weapon.Check(); - _weapon.RotateToTarget(elapseSeconds); - - if (_weapon._target == null || !_weapon._target.Available) - { - _weapon.TransitionTo(WeaponStateType.Idle); - return; - } - - if (!_weapon.IsInRange(_weapon._target, _weapon._sqrRange)) - { - _weapon.TransitionTo(WeaponStateType.Check_OutRange); - return; - } - - if (_weapon._canAttack) - { - _weapon.TransitionTo(WeaponStateType.Attack); - } - } - - public override void OnLeave() - { - } - } - } -} diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponKnife/WeaponKnife.CheckInRangeState.cs.meta b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponKnife/WeaponKnife.CheckInRangeState.cs.meta deleted file mode 100644 index 4eb0912..0000000 --- a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponKnife/WeaponKnife.CheckInRangeState.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 59644093364644768c26261b24bdb820 -timeCreated: 1771578916 \ No newline at end of file diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponKnife/WeaponKnife.CheckOutRangeState.cs b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponKnife/WeaponKnife.CheckOutRangeState.cs deleted file mode 100644 index bd7f76d..0000000 --- a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponKnife/WeaponKnife.CheckOutRangeState.cs +++ /dev/null @@ -1,38 +0,0 @@ -namespace SepCore.Entity -{ - public partial class WeaponKnife - { - private class CheckOutRangeState : WeaponStateBase - { - private WeaponKnife _weapon; - - public override WeaponStateType State => WeaponStateType.Check_OutRange; - public override void OnInit(WeaponBase weapon) => _weapon = weapon as WeaponKnife; - - public override void OnEnter() - { - } - - public override void OnUpdate(float elapseSeconds, float realElapseSeconds) - { - _weapon.Check(); - _weapon.RotateToTarget(elapseSeconds); - - if (_weapon._target == null || !_weapon._target.Available) - { - _weapon.TransitionTo(WeaponStateType.Idle); - return; - } - - if (_weapon.IsInRange(_weapon._target, _weapon._sqrRange)) - { - _weapon.TransitionTo(WeaponStateType.Check_InRange); - } - } - - public override void OnLeave() - { - } - } - } -} \ No newline at end of file diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponKnife/WeaponKnife.CheckOutRangeState.cs.meta b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponKnife/WeaponKnife.CheckOutRangeState.cs.meta deleted file mode 100644 index 520dce9..0000000 --- a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponKnife/WeaponKnife.CheckOutRangeState.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: d9e1a63869694e72a360afe29cc94cfb -timeCreated: 1771578994 \ No newline at end of file diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponKnife/WeaponKnife.IdleState.cs b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponKnife/WeaponKnife.IdleState.cs deleted file mode 100644 index ff2bc3a..0000000 --- a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponKnife/WeaponKnife.IdleState.cs +++ /dev/null @@ -1,32 +0,0 @@ -namespace SepCore.Entity -{ - public partial class WeaponKnife - { - public class IdleState : WeaponStateBase - { - private WeaponKnife _weapon; - - public override WeaponStateType State => WeaponStateType.Idle; - public override void OnInit(WeaponBase weapon) => _weapon = weapon as WeaponKnife; - - public override void OnEnter() - { - } - - public override void OnUpdate(float elapseSeconds, float realElapseSeconds) - { - _weapon.Check(); - _weapon.RotateToOrigin(elapseSeconds); - - if (_weapon._target != null && _weapon._target.Available) - { - _weapon.TransitionTo(WeaponStateType.Check_OutRange); - } - } - - public override void OnLeave() - { - } - } - } -} \ No newline at end of file diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponKnife/WeaponKnife.IdleState.cs.meta b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponKnife/WeaponKnife.IdleState.cs.meta deleted file mode 100644 index 520eac7..0000000 --- a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponKnife/WeaponKnife.IdleState.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: b4d66ec44b064640aa95c6aa71ff3846 -timeCreated: 1771578662 \ No newline at end of file diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponKnife/WeaponKnife.cs b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponKnife/WeaponKnife.cs index 7c065e7..632674c 100644 --- a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponKnife/WeaponKnife.cs +++ b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponKnife/WeaponKnife.cs @@ -2,50 +2,36 @@ using System.Collections.Generic; using SepCore.CustomUtility; using SepCore.Definition; using DG.Tweening; -using SepCore.Entity; using UnityEngine; using UnityGameFramework.Runtime; namespace SepCore.Entity { - public partial class WeaponKnife : WeaponBase + public class WeaponKnife : WeaponBase { - private WeaponKnifeData _weaponData; - - private Quaternion _cachedRotation; - [SerializeField] private float _rotateSpeed = 4f; - private Sequence _attackSequence; private Transform _attackParent; private Vector3 _attackCenter; - [SerializeField] private float attackDuration = 0.15f; - [SerializeField] private float returnDuration = 0.2f; - - [SerializeField] private LayerMask _hitMask = ~0; + [SerializeField] private float _attackDuration = 0.15f; + [SerializeField] private float _returnDuration = 0.2f; [SerializeField] private int _maxHitColliders = 32; private IWeaponAttackEffect _attackEffect; private Collider[] _hitResults; private readonly HashSet _hitEntityIds = new(); - private float _hitRadius; - private float _hitRadiusSqr; - - public override ImpactData GetImpactData() - { - return new ImpactData(_weaponData.OwnerCamp, _weaponData.Attack, AttackStat); - } + public float HitRadius => WeaponData.GetParamFloat(ParamType.HitRadius); protected override void BuildStates() { - RegisterState(new IdleState()); - RegisterState(new CheckInRangeState()); - RegisterState(new CheckOutRangeState()); - RegisterState(new AttackState()); + RegisterState(new WeaponKnifeIdleState()); + RegisterState(new WeaponKnifeAimState()); + RegisterState(new WeaponKnifeSeekState()); + RegisterState(new WeaponKnifeAttackState()); } - protected override void Attack() + public override void Attack() { StopAttackTween(false); FaceTargetImmediately(); @@ -56,12 +42,12 @@ namespace SepCore.Entity _attackCenter = _target != null ? _target.CachedTransform.position : CachedTransform.position; CachedTransform.SetParent(null); - Vector3 targetPos = CachedTransform.position + CachedTransform.forward * _weaponData.AttackRange; + Vector3 targetPos = CachedTransform.position + CachedTransform.forward * WeaponData.AttackRange; _attackSequence = DOTween.Sequence(); - _attackSequence.Append(CachedTransform.DOMove(targetPos, attackDuration).SetEase(Ease.OutQuad)); + _attackSequence.Append(CachedTransform.DOMove(targetPos, _attackDuration).SetEase(Ease.OutQuad)); _attackSequence.AppendCallback(() => { - _attackEffect?.Play(this, _attackCenter, null, _hitRadius); + _attackEffect.Play(this, _attackCenter, null, HitRadius); ApplyGroundAreaDamage(); if (_attackParent != null) { @@ -69,7 +55,7 @@ namespace SepCore.Entity } }); _attackSequence.Append( - CachedTransform.DOLocalMove(Vector3.zero, returnDuration * 0.5f).SetEase(Ease.InQuad)); + CachedTransform.DOLocalMove(Vector3.zero, _returnDuration * 0.5f).SetEase(Ease.InQuad)); _attackSequence.AppendCallback(() => { _isAttacking = false; @@ -78,54 +64,22 @@ namespace SepCore.Entity }); } - protected override void Check() - { - _target = SelectTarget(_sqrRange); - } - - private void RotateToTarget(float elapseSeconds) - { - if (_target == null || !_target.Available) return; - - Vector3 directionToTarget = _target.CachedTransform.position - CachedTransform.position; - if (directionToTarget.sqrMagnitude <= Mathf.Epsilon) return; - - Quaternion targetRotation = Quaternion.LookRotation(directionToTarget.normalized, Vector3.up); - CachedTransform.rotation = - Quaternion.Slerp(CachedTransform.rotation, targetRotation, _rotateSpeed * elapseSeconds); - } - - public void RotateToOrigin(float elapseSeconds) - { - CachedTransform.rotation = - Quaternion.Slerp(CachedTransform.rotation, _cachedRotation, _rotateSpeed * elapseSeconds); - } - - private void FaceTargetImmediately() - { - if (_target == null || !_target.Available) return; - - Vector3 directionToTarget = _target.CachedTransform.position - CachedTransform.position; - if (directionToTarget.sqrMagnitude <= Mathf.Epsilon) return; - - CachedTransform.rotation = Quaternion.LookRotation(directionToTarget.normalized, Vector3.up); - } - private void ApplyGroundAreaDamage() { - if (_hitRadius <= 0f) return; + float radius = HitRadius; + if (radius <= 0f) return; - if (TryQueueAreaCollisionQuery(_attackCenter, _hitRadius, Mathf.Max(1, _maxHitColliders))) + if (TryQueueAreaCollisionQuery(_attackCenter, radius, Mathf.Max(1, _maxHitColliders))) { - _hitEntityIds.Clear(); return; } if (_hitResults == null || _hitResults.Length == 0) return; - int hitCount = Physics.OverlapSphereNonAlloc(_attackCenter, _hitRadius, _hitResults, _hitMask, + int hitCount = Physics.OverlapSphereNonAlloc(_attackCenter, radius, _hitResults, _hitMask, QueryTriggerInteraction.Collide); + float radiusSqr = radius * radius; _hitEntityIds.Clear(); for (int i = 0; i < hitCount; i++) { @@ -138,7 +92,7 @@ namespace SepCore.Entity Vector3 delta = targetable.CachedTransform.position - _attackCenter; delta.y = 0f; - if (delta.sqrMagnitude > _hitRadiusSqr) continue; + if (delta.sqrMagnitude > radiusSqr) continue; AIUtility.PerformCollision(targetable, this); } @@ -146,18 +100,6 @@ namespace SepCore.Entity protected override bool OnWeaponShow(object userData) { - _weaponData = RequireWeaponData(userData); - if (_weaponData == null) return false; - WeaponData = _weaponData; - - StartAttackCooldown(_weaponData.Cooldown); - _sqrRange = _weaponData.AttackRange * _weaponData.AttackRange; - _cachedRotation = CachedTransform.rotation; - - float configuredHitRadius = _weaponData.ParamsData != null ? _weaponData.ParamsData.HitRadius : 0f; - _hitRadius = configuredHitRadius > 0f ? Mathf.Max(0.1f, configuredHitRadius) : _weaponData.AttackRange; - - _hitRadiusSqr = _hitRadius * _hitRadius; _attackEffect = new KnifeRangeAttackEffect(); int colliderCapacity = Mathf.Max(1, _maxHitColliders); @@ -166,36 +108,19 @@ namespace SepCore.Entity _hitResults = new Collider[colliderCapacity]; } - if (_weaponData.OwnerCamp == CampType.Player) - { - gameObject.layer = LayerMask.NameToLayer("PlayerWeapon"); - _hitMask = LayerMask.GetMask("Enemy"); - } - else if (_weaponData.OwnerCamp == CampType.Enemy) - { - gameObject.layer = LayerMask.NameToLayer("EnemyWeapon"); - _hitMask = LayerMask.GetMask("Player"); - } - return true; } protected override void OnWeaponHide(object userData) { StopAttackTween(true); - CancelAttackCooldown(); _attackEffect = null; } - protected override void OnWeaponAttach(EntityLogic parentEntity, Transform parentTransform, object userData) - { - BindAttackStatFromOwner(parentEntity); - } - protected override void OnWeaponDetach(EntityLogic parentEntity, object userData) { StopAttackTween(true); - ReleaseAttackStatSubscription(); + base.OnWeaponDetach(parentEntity, userData); } protected override void OnEnabledChanged(bool enabled) diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponKnife/WeaponKnifeAimState.cs b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponKnife/WeaponKnifeAimState.cs new file mode 100644 index 0000000..38863e3 --- /dev/null +++ b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponKnife/WeaponKnifeAimState.cs @@ -0,0 +1,51 @@ +using SepCore.Definition; + +namespace SepCore.Entity +{ + /// + /// 小刀的瞄准状态。 + /// + public sealed class WeaponKnifeAimState : WeaponStateBase + { + private WeaponKnife _weapon; + + public override WeaponStateType State => WeaponStateType.Aim; + + public override void OnInit(WeaponBase weapon) => _weapon = (WeaponKnife)weapon; + + public override void OnEnter() + { + if (_weapon.CanAttack) + { + _weapon.TransitionTo(WeaponStateType.Attack); + } + } + + public override void OnUpdate(float elapseSeconds, float realElapseSeconds) + { + _weapon.Check(); + _weapon.RotateToTarget(elapseSeconds); + + if (_weapon.Target == null || !_weapon.Target.Available) + { + _weapon.TransitionTo(WeaponStateType.Idle); + return; + } + + if (!_weapon.IsInRange(_weapon.Target, _weapon.SqrRange)) + { + _weapon.TransitionTo(WeaponStateType.Seek); + return; + } + + if (_weapon.CanAttack) + { + _weapon.TransitionTo(WeaponStateType.Attack); + } + } + + public override void OnLeave() + { + } + } +} diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponKnife/WeaponKnifeAimState.cs.meta b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponKnife/WeaponKnifeAimState.cs.meta new file mode 100644 index 0000000..bebb44f --- /dev/null +++ b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponKnife/WeaponKnifeAimState.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0fb5d24a4e6deac4b8c64d1acc697adc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponKnife/WeaponKnifeAttackState.cs b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponKnife/WeaponKnifeAttackState.cs new file mode 100644 index 0000000..999a18e --- /dev/null +++ b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponKnife/WeaponKnifeAttackState.cs @@ -0,0 +1,34 @@ +using SepCore.Definition; + +namespace SepCore.Entity +{ + /// + /// 小刀的攻击状态。 + /// + public sealed class WeaponKnifeAttackState : WeaponStateBase + { + private WeaponKnife _weapon; + + public override WeaponStateType State => WeaponStateType.Attack; + + public override void OnInit(WeaponBase weapon) => _weapon = (WeaponKnife)weapon; + + public override void OnEnter() + { + _weapon.ResetAttackCooldown(_weapon.AttackCooldown); + _weapon.Attack(); + } + + public override void OnUpdate(float elapseSeconds, float realElapseSeconds) + { + if (!_weapon.IsAttacking) + { + _weapon.TransitionTo(WeaponStateType.Aim); + } + } + + public override void OnLeave() + { + } + } +} diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponKnife/WeaponKnifeAttackState.cs.meta b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponKnife/WeaponKnifeAttackState.cs.meta new file mode 100644 index 0000000..cab5688 --- /dev/null +++ b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponKnife/WeaponKnifeAttackState.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: aad966d918f5cdb45912c0275826ef5c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponKnife/WeaponKnifeIdleState.cs b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponKnife/WeaponKnifeIdleState.cs new file mode 100644 index 0000000..0e7a470 --- /dev/null +++ b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponKnife/WeaponKnifeIdleState.cs @@ -0,0 +1,35 @@ +using SepCore.Definition; + +namespace SepCore.Entity +{ + /// + /// 小刀的待机状态。 + /// + public sealed class WeaponKnifeIdleState : WeaponStateBase + { + private WeaponKnife _weapon; + + public override WeaponStateType State => WeaponStateType.Idle; + + public override void OnInit(WeaponBase weapon) => _weapon = (WeaponKnife)weapon; + + public override void OnEnter() + { + } + + public override void OnUpdate(float elapseSeconds, float realElapseSeconds) + { + _weapon.Check(); + _weapon.RotateToOrigin(elapseSeconds); + + if (_weapon.Target != null && _weapon.Target.Available) + { + _weapon.TransitionTo(WeaponStateType.Seek); + } + } + + public override void OnLeave() + { + } + } +} diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponKnife/WeaponKnifeIdleState.cs.meta b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponKnife/WeaponKnifeIdleState.cs.meta new file mode 100644 index 0000000..8e04f78 --- /dev/null +++ b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponKnife/WeaponKnifeIdleState.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 393f986a051df42409d687426bb213b7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponKnife/WeaponKnifeSeekState.cs b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponKnife/WeaponKnifeSeekState.cs new file mode 100644 index 0000000..361e27a --- /dev/null +++ b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponKnife/WeaponKnifeSeekState.cs @@ -0,0 +1,41 @@ +using SepCore.Definition; + +namespace SepCore.Entity +{ + /// + /// 小刀的搜寻状态。 + /// + public sealed class WeaponKnifeSeekState : WeaponStateBase + { + private WeaponKnife _weapon; + + public override WeaponStateType State => WeaponStateType.Seek; + + public override void OnInit(WeaponBase weapon) => _weapon = (WeaponKnife)weapon; + + public override void OnEnter() + { + } + + public override void OnUpdate(float elapseSeconds, float realElapseSeconds) + { + _weapon.Check(); + _weapon.RotateToTarget(elapseSeconds); + + if (_weapon.Target == null || !_weapon.Target.Available) + { + _weapon.TransitionTo(WeaponStateType.Idle); + return; + } + + if (_weapon.IsInRange(_weapon.Target, _weapon.SqrRange)) + { + _weapon.TransitionTo(WeaponStateType.Aim); + } + } + + public override void OnLeave() + { + } + } +} diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponKnife/WeaponKnifeSeekState.cs.meta b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponKnife/WeaponKnifeSeekState.cs.meta new file mode 100644 index 0000000..7d6f23a --- /dev/null +++ b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponKnife/WeaponKnifeSeekState.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ac6681a70a0b3a6429a876bac61166cc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLance/WeaponLance.AttackState.cs b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLance/WeaponLance.AttackState.cs deleted file mode 100644 index 38e49a7..0000000 --- a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLance/WeaponLance.AttackState.cs +++ /dev/null @@ -1,31 +0,0 @@ -namespace SepCore.Entity -{ - public partial class WeaponLance - { - private class AttackState : WeaponStateBase - { - private WeaponLance _weapon; - - public override WeaponStateType State => WeaponStateType.Attack; - public override void OnInit(WeaponBase weapon) => _weapon = weapon as WeaponLance; - - public override void OnEnter() - { - _weapon.ResetAttackCooldown(_weapon._weaponData.Cooldown); - _weapon.Attack(); - } - - public override void OnUpdate(float elapseSeconds, float realElapseSeconds) - { - if (!_weapon._isAttacking) - { - _weapon.TransitionTo(WeaponStateType.Check_InRange); - } - } - - public override void OnLeave() - { - } - } - } -} diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLance/WeaponLance.AttackState.cs.meta b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLance/WeaponLance.AttackState.cs.meta deleted file mode 100644 index 2ad423b..0000000 --- a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLance/WeaponLance.AttackState.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: d9991ee189b733b4e9d40395357f5ef2 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLance/WeaponLance.CheckInRangeState.cs b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLance/WeaponLance.CheckInRangeState.cs deleted file mode 100644 index f549537..0000000 --- a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLance/WeaponLance.CheckInRangeState.cs +++ /dev/null @@ -1,48 +0,0 @@ -namespace SepCore.Entity -{ - public partial class WeaponLance - { - private class CheckInRangeState : WeaponStateBase - { - private WeaponLance _weapon; - - public override WeaponStateType State => WeaponStateType.Check_InRange; - public override void OnInit(WeaponBase weapon) => _weapon = weapon as WeaponLance; - - public override void OnEnter() - { - if (_weapon._canAttack) - { - _weapon.TransitionTo(WeaponStateType.Attack); - } - } - - public override void OnUpdate(float elapseSeconds, float realElapseSeconds) - { - _weapon.Check(); - _weapon.RotateToTarget(elapseSeconds); - - if (_weapon._target == null || !_weapon._target.Available) - { - _weapon.TransitionTo(WeaponStateType.Idle); - return; - } - - if (!_weapon.IsInRange(_weapon._target, _weapon._sqrRange)) - { - _weapon.TransitionTo(WeaponStateType.Check_OutRange); - return; - } - - if (_weapon._canAttack) - { - _weapon.TransitionTo(WeaponStateType.Attack); - } - } - - public override void OnLeave() - { - } - } - } -} diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLance/WeaponLance.CheckInRangeState.cs.meta b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLance/WeaponLance.CheckInRangeState.cs.meta deleted file mode 100644 index 3e6f575..0000000 --- a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLance/WeaponLance.CheckInRangeState.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 01edc8bb0ff46a14d8028e03af932b52 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLance/WeaponLance.CheckOutRangeState.cs b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLance/WeaponLance.CheckOutRangeState.cs deleted file mode 100644 index 864fd97..0000000 --- a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLance/WeaponLance.CheckOutRangeState.cs +++ /dev/null @@ -1,38 +0,0 @@ -namespace SepCore.Entity -{ - public partial class WeaponLance - { - private class CheckOutRangeState : WeaponStateBase - { - private WeaponLance _weapon; - - public override WeaponStateType State => WeaponStateType.Check_OutRange; - public override void OnInit(WeaponBase weapon) => _weapon = weapon as WeaponLance; - - public override void OnEnter() - { - } - - public override void OnUpdate(float elapseSeconds, float realElapseSeconds) - { - _weapon.Check(); - _weapon.RotateToTarget(elapseSeconds); - - if (_weapon._target == null || !_weapon._target.Available) - { - _weapon.TransitionTo(WeaponStateType.Idle); - return; - } - - if (_weapon.IsInRange(_weapon._target, _weapon._sqrRange)) - { - _weapon.TransitionTo(WeaponStateType.Check_InRange); - } - } - - public override void OnLeave() - { - } - } - } -} diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLance/WeaponLance.CheckOutRangeState.cs.meta b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLance/WeaponLance.CheckOutRangeState.cs.meta deleted file mode 100644 index 416d391..0000000 --- a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLance/WeaponLance.CheckOutRangeState.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 8009ad2c332a956438e3357ed5e30eb6 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLance/WeaponLance.IdleState.cs b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLance/WeaponLance.IdleState.cs deleted file mode 100644 index 9a55e5b..0000000 --- a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLance/WeaponLance.IdleState.cs +++ /dev/null @@ -1,32 +0,0 @@ -namespace SepCore.Entity -{ - public partial class WeaponLance - { - public class IdleState : WeaponStateBase - { - private WeaponLance _weapon; - - public override WeaponStateType State => WeaponStateType.Idle; - public override void OnInit(WeaponBase weapon) => _weapon = weapon as WeaponLance; - - public override void OnEnter() - { - } - - public override void OnUpdate(float elapseSeconds, float realElapseSeconds) - { - _weapon.Check(); - _weapon.RotateToOrigin(elapseSeconds); - - if (_weapon._target != null && _weapon._target.Available) - { - _weapon.TransitionTo(WeaponStateType.Check_OutRange); - } - } - - public override void OnLeave() - { - } - } - } -} diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLance/WeaponLance.IdleState.cs.meta b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLance/WeaponLance.IdleState.cs.meta deleted file mode 100644 index 4ad5fa9..0000000 --- a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLance/WeaponLance.IdleState.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 4c9e98f5381e579469dcdac7bf3e1e25 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLance/WeaponLance.cs b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLance/WeaponLance.cs index 5415084..f07b92b 100644 --- a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLance/WeaponLance.cs +++ b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLance/WeaponLance.cs @@ -9,15 +9,8 @@ using UnityGameFramework.Runtime; namespace SepCore.Entity { - public partial class WeaponLance : WeaponBase + public class WeaponLance : WeaponBase { - // 长枪专用数据,包含强类型 ParamsData。 - [SerializeField] private WeaponLanceData _weaponData; - - private Quaternion _cachedRotation; - // 朝向目标时的旋转速度,可被 ParamsData.RotateSpeed 覆盖。 - [SerializeField] private float _rotateSpeed = 5f; - private Sequence _attackSequence; private Transform _attackParent; @@ -26,57 +19,46 @@ namespace SepCore.Entity // 收枪返回耗时。 [SerializeField] private float _returnDuration = 0.18f; - [SerializeField] private LayerMask _hitMask = ~0; [SerializeField] private int _maxHitColliders = 32; private IWeaponAttackEffect _attackEffect; private Collider[] _hitResults; private readonly HashSet _hitEntityIds = new(); - // 前戳矩形判定的横向半宽。 - private float _hitHalfWidth; - // 前戳矩形判定盒体的总高度。 - private float _hitHeight; - // 盒体中心相对战斗平面的高度偏移。 - private float _hitCenterYOffset; - // 从判定起点向前延伸的有效刺击长度。 - private float _pierceLength; - // 判定起点相对武器当前位置的前移量。 - private float _forwardOffset; + public float HitHalfWidth => WeaponData.GetParamFloat(ParamType.HitHalfWidth); + public float HitHeight => WeaponData.GetParamFloat(ParamType.HitHeight); + public float PierceLength => WeaponData.GetParamFloat(ParamType.PierceLength); + public Vector3 StrikeDirection => _strikeDirection; + // 本次攻击锁定的前戳方向,避免受位移动画中的武器位置影响。 private Vector3 _strikeDirection = Vector3.forward; // 本次攻击锁定的矩形判定中心。 private Vector3 _strikeCenter; - public override ImpactData GetImpactData() - { - return new ImpactData(_weaponData.OwnerCamp, _weaponData.Attack, AttackStat); - } - protected override void BuildStates() { - RegisterState(new IdleState()); - RegisterState(new CheckInRangeState()); - RegisterState(new CheckOutRangeState()); - RegisterState(new AttackState()); + RegisterState(new WeaponLanceIdleState()); + RegisterState(new WeaponLanceAimState()); + RegisterState(new WeaponLanceSeekState()); + RegisterState(new WeaponLanceAttackState()); } - protected override void Attack() + public override void Attack() { StopAttackTween(false); FaceTargetImmediately(); + _attackParent = CachedTransform.parent; CacheStrikeSnapshot(); _isAttacking = true; - _attackParent = CachedTransform.parent; CachedTransform.SetParent(null); - Vector3 targetPos = CachedTransform.position + _strikeDirection * _pierceLength; + Vector3 targetPos = CachedTransform.position + _strikeDirection * PierceLength; _attackSequence = DOTween.Sequence(); _attackSequence.Append(CachedTransform.DOMove(targetPos, _attackDuration).SetEase(Ease.OutQuad)); _attackSequence.AppendCallback(() => { - _attackEffect?.Play(this, _strikeCenter, _target, _hitHalfWidth); + _attackEffect.Play(this, _strikeCenter, _target, HitHalfWidth); ApplyPierceDamage(); if (_attackParent != null) @@ -93,49 +75,12 @@ namespace SepCore.Entity }); } - protected override void Check() - { - _target = SelectTarget(_sqrRange); - } - - private void RotateToTarget(float elapseSeconds) - { - if (_target == null || !_target.Available) return; - - Vector3 directionToTarget = _target.CachedTransform.position - CachedTransform.position; - directionToTarget.y = 0f; - if (directionToTarget.sqrMagnitude <= Mathf.Epsilon) return; - - Quaternion targetRotation = Quaternion.LookRotation(directionToTarget.normalized, Vector3.up); - CachedTransform.rotation = - Quaternion.Slerp(CachedTransform.rotation, targetRotation, _rotateSpeed * elapseSeconds); - } - - private void RotateToOrigin(float elapseSeconds) - { - CachedTransform.rotation = - Quaternion.Slerp(CachedTransform.rotation, _cachedRotation, _rotateSpeed * elapseSeconds); - } - - private void FaceTargetImmediately() - { - if (_target == null || !_target.Available) return; - - Vector3 directionToTarget = _target.CachedTransform.position - CachedTransform.position; - directionToTarget.y = 0f; - if (directionToTarget.sqrMagnitude <= Mathf.Epsilon) return; - - CachedTransform.rotation = Quaternion.LookRotation(directionToTarget.normalized, Vector3.up); - } - private void CacheStrikeSnapshot() { _strikeDirection = ResolvePlanarForward(); Vector3 strikeStart = CachedTransform.position; strikeStart.y = ResolveStrikePlaneY(); - strikeStart += _strikeDirection * _forwardOffset; - _strikeCenter = strikeStart + _strikeDirection * (_pierceLength * 0.5f); - _strikeCenter.y += _hitCenterYOffset; + _strikeCenter = strikeStart + _strikeDirection * (PierceLength * 0.5f); } private Vector3 ResolvePlanarForward() @@ -153,7 +98,7 @@ namespace SepCore.Entity private void ApplyPierceDamage() { - if (_hitHalfWidth <= 0f || _pierceLength <= 0f) return; + if (HitHalfWidth <= 0f || PierceLength <= 0f) return; Vector3 strikeDirection = _strikeDirection; if (strikeDirection.sqrMagnitude <= Mathf.Epsilon) return; @@ -161,20 +106,15 @@ namespace SepCore.Entity Vector3 broadPhaseCenter = _strikeCenter; Quaternion broadPhaseRotation = Quaternion.LookRotation(strikeDirection, Vector3.up); - if (TryQueueRectangleCollisionQuery(broadPhaseCenter, _hitHalfWidth, _pierceLength * 0.5f, + if (TryQueueRectangleCollisionQuery(broadPhaseCenter, HitHalfWidth, PierceLength * 0.5f, strikeDirection, Mathf.Max(1, _maxHitColliders))) { - _hitEntityIds.Clear(); return; } - int capacity = Mathf.Max(1, _maxHitColliders); - if (_hitResults == null || _hitResults.Length != capacity) - { - _hitResults = new Collider[capacity]; - } + if (_hitResults == null || _hitResults.Length == 0) return; - Vector3 halfExtents = new(_hitHalfWidth, _hitHeight * 0.5f, _pierceLength * 0.5f); + Vector3 halfExtents = new(HitHalfWidth, HitHeight * 0.5f, PierceLength * 0.5f); int hitCount = Physics.OverlapBoxNonAlloc(broadPhaseCenter, halfExtents, _hitResults, broadPhaseRotation, _hitMask, QueryTriggerInteraction.Collide); _hitEntityIds.Clear(); @@ -203,8 +143,8 @@ namespace SepCore.Entity float lateralDistance = Vector3.Dot(delta, right); float targetRadius = ResolveTargetCollisionRadius(targetable); - return Mathf.Abs(forwardDistance) <= _pierceLength * 0.5f + targetRadius && - Mathf.Abs(lateralDistance) <= _hitHalfWidth + targetRadius; + return Mathf.Abs(forwardDistance) <= PierceLength * 0.5f + targetRadius && + Mathf.Abs(lateralDistance) <= HitHalfWidth + targetRadius; } private static float ResolveTargetCollisionRadius(TargetableObject targetable) @@ -225,64 +165,11 @@ namespace SepCore.Entity return _target.CachedTransform.position.y; } - if (_attackParent != null) - { - return _attackParent.position.y; - } - - if (CachedTransform.parent != null) - { - return CachedTransform.parent.position.y; - } - - return CachedTransform.position.y; + return _attackParent != null ? _attackParent.position.y : CachedTransform.position.y; } protected override bool OnWeaponShow(object userData) { - _weaponData = RequireWeaponData(userData); - if (_weaponData == null) return false; - WeaponData = _weaponData; - - StartAttackCooldown(_weaponData.Cooldown); - _sqrRange = _weaponData.AttackRange * _weaponData.AttackRange; - _cachedRotation = CachedTransform.rotation; - - WeaponLanceParamsData paramsData = _weaponData.ParamsData; - float configuredHalfWidth = paramsData != null && paramsData.HitHalfWidth > 0f - ? paramsData.HitHalfWidth - : paramsData != null && paramsData.HitRadius > 0f - ? paramsData.HitRadius - : 0.45f; - _hitHalfWidth = Mathf.Max(0.1f, configuredHalfWidth); - _hitHeight = paramsData != null && paramsData.HitHeight > 0f - ? Mathf.Max(0.2f, paramsData.HitHeight) - : 4f; - _hitCenterYOffset = paramsData != null ? paramsData.HitCenterYOffset : 0f; - _pierceLength = paramsData != null && paramsData.PierceLength > 0f - ? paramsData.PierceLength - : paramsData != null && paramsData.ThrustDistance > 0f - ? paramsData.ThrustDistance - : _weaponData.AttackRange; - _forwardOffset = paramsData != null && paramsData.ForwardOffset > 0f - ? paramsData.ForwardOffset - : 0f; - - if (paramsData != null && paramsData.RotateSpeed > 0f) - { - _rotateSpeed = paramsData.RotateSpeed; - } - - if (paramsData != null && paramsData.AttackDuration > 0f) - { - _attackDuration = paramsData.AttackDuration; - } - - if (paramsData != null && paramsData.ReturnDuration > 0f) - { - _returnDuration = paramsData.ReturnDuration; - } - int colliderCapacity = Mathf.Max(1, _maxHitColliders); if (_hitResults == null || _hitResults.Length != colliderCapacity) { @@ -290,37 +177,19 @@ namespace SepCore.Entity } _attackEffect = new LanceThrustAttackEffect(); - - if (_weaponData.OwnerCamp == CampType.Player) - { - gameObject.layer = LayerMask.NameToLayer("PlayerWeapon"); - _hitMask = LayerMask.GetMask("Enemy"); - } - else if (_weaponData.OwnerCamp == CampType.Enemy) - { - gameObject.layer = LayerMask.NameToLayer("EnemyWeapon"); - _hitMask = LayerMask.GetMask("Player"); - } - return true; } protected override void OnWeaponHide(object userData) { StopAttackTween(true); - CancelAttackCooldown(); _attackEffect = null; } - protected override void OnWeaponAttach(EntityLogic parentEntity, Transform parentTransform, object userData) - { - BindAttackStatFromOwner(parentEntity); - } - protected override void OnWeaponDetach(EntityLogic parentEntity, object userData) { StopAttackTween(true); - ReleaseAttackStatSubscription(); + base.OnWeaponDetach(parentEntity, userData); } protected override void OnEnabledChanged(bool enabled) @@ -351,9 +220,5 @@ namespace SepCore.Entity _attackParent = null; _hitEntityIds.Clear(); } - - public float HitHalfWidth => _hitHalfWidth; - public float PierceLength => _pierceLength; - public Vector3 StrikeDirection => _strikeDirection; } } diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLance/WeaponLanceAimState.cs b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLance/WeaponLanceAimState.cs new file mode 100644 index 0000000..245a72a --- /dev/null +++ b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLance/WeaponLanceAimState.cs @@ -0,0 +1,51 @@ +using SepCore.Definition; + +namespace SepCore.Entity +{ + /// + /// 长枪的瞄准状态。 + /// + public sealed class WeaponLanceAimState : WeaponStateBase + { + private WeaponLance _weapon; + + public override WeaponStateType State => WeaponStateType.Aim; + + public override void OnInit(WeaponBase weapon) => _weapon = (WeaponLance)weapon; + + public override void OnEnter() + { + if (_weapon.CanAttack) + { + _weapon.TransitionTo(WeaponStateType.Attack); + } + } + + public override void OnUpdate(float elapseSeconds, float realElapseSeconds) + { + _weapon.Check(); + _weapon.RotateToTarget(elapseSeconds); + + if (_weapon.Target == null || !_weapon.Target.Available) + { + _weapon.TransitionTo(WeaponStateType.Idle); + return; + } + + if (!_weapon.IsInRange(_weapon.Target, _weapon.SqrRange)) + { + _weapon.TransitionTo(WeaponStateType.Seek); + return; + } + + if (_weapon.CanAttack) + { + _weapon.TransitionTo(WeaponStateType.Attack); + } + } + + public override void OnLeave() + { + } + } +} diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLance/WeaponLanceAimState.cs.meta b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLance/WeaponLanceAimState.cs.meta new file mode 100644 index 0000000..2a305a3 --- /dev/null +++ b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLance/WeaponLanceAimState.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b871ce786fd5a4b44832f9437a752880 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLance/WeaponLanceAttackState.cs b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLance/WeaponLanceAttackState.cs new file mode 100644 index 0000000..6de10c1 --- /dev/null +++ b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLance/WeaponLanceAttackState.cs @@ -0,0 +1,34 @@ +using SepCore.Definition; + +namespace SepCore.Entity +{ + /// + /// 长枪的攻击状态。 + /// + public sealed class WeaponLanceAttackState : WeaponStateBase + { + private WeaponLance _weapon; + + public override WeaponStateType State => WeaponStateType.Attack; + + public override void OnInit(WeaponBase weapon) => _weapon = (WeaponLance)weapon; + + public override void OnEnter() + { + _weapon.ResetAttackCooldown(_weapon.AttackCooldown); + _weapon.Attack(); + } + + public override void OnUpdate(float elapseSeconds, float realElapseSeconds) + { + if (!_weapon.IsAttacking) + { + _weapon.TransitionTo(WeaponStateType.Aim); + } + } + + public override void OnLeave() + { + } + } +} diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLance/WeaponLanceAttackState.cs.meta b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLance/WeaponLanceAttackState.cs.meta new file mode 100644 index 0000000..b0a52eb --- /dev/null +++ b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLance/WeaponLanceAttackState.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b3529471ff522fa4dbbf7ca2005b9358 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLance/WeaponLanceIdleState.cs b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLance/WeaponLanceIdleState.cs new file mode 100644 index 0000000..6e913de --- /dev/null +++ b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLance/WeaponLanceIdleState.cs @@ -0,0 +1,35 @@ +using SepCore.Definition; + +namespace SepCore.Entity +{ + /// + /// 长枪的待机状态。 + /// + public sealed class WeaponLanceIdleState : WeaponStateBase + { + private WeaponLance _weapon; + + public override WeaponStateType State => WeaponStateType.Idle; + + public override void OnInit(WeaponBase weapon) => _weapon = (WeaponLance)weapon; + + public override void OnEnter() + { + } + + public override void OnUpdate(float elapseSeconds, float realElapseSeconds) + { + _weapon.Check(); + _weapon.RotateToOrigin(elapseSeconds); + + if (_weapon.Target != null && _weapon.Target.Available) + { + _weapon.TransitionTo(WeaponStateType.Seek); + } + } + + public override void OnLeave() + { + } + } +} diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLance/WeaponLanceIdleState.cs.meta b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLance/WeaponLanceIdleState.cs.meta new file mode 100644 index 0000000..d8371cc --- /dev/null +++ b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLance/WeaponLanceIdleState.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1a33cf2ffd5d4d54194406a6d9eb68a5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLance/WeaponLanceSeekState.cs b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLance/WeaponLanceSeekState.cs new file mode 100644 index 0000000..f6a721d --- /dev/null +++ b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLance/WeaponLanceSeekState.cs @@ -0,0 +1,41 @@ +using SepCore.Definition; + +namespace SepCore.Entity +{ + /// + /// 长枪的搜寻状态。 + /// + public sealed class WeaponLanceSeekState : WeaponStateBase + { + private WeaponLance _weapon; + + public override WeaponStateType State => WeaponStateType.Seek; + + public override void OnInit(WeaponBase weapon) => _weapon = (WeaponLance)weapon; + + public override void OnEnter() + { + } + + public override void OnUpdate(float elapseSeconds, float realElapseSeconds) + { + _weapon.Check(); + _weapon.RotateToTarget(elapseSeconds); + + if (_weapon.Target == null || !_weapon.Target.Available) + { + _weapon.TransitionTo(WeaponStateType.Idle); + return; + } + + if (_weapon.IsInRange(_weapon.Target, _weapon.SqrRange)) + { + _weapon.TransitionTo(WeaponStateType.Aim); + } + } + + public override void OnLeave() + { + } + } +} diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLance/WeaponLanceSeekState.cs.meta b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLance/WeaponLanceSeekState.cs.meta new file mode 100644 index 0000000..4d033ed --- /dev/null +++ b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLance/WeaponLanceSeekState.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 366f9a214870cfb4b90fc2682c74f127 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLightning/WeaponLightning.AttackState.cs b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLightning/WeaponLightning.AttackState.cs deleted file mode 100644 index d82da22..0000000 --- a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLightning/WeaponLightning.AttackState.cs +++ /dev/null @@ -1,31 +0,0 @@ -namespace SepCore.Entity -{ - public partial class WeaponLightning - { - private class AttackState : WeaponStateBase - { - private WeaponLightning _weapon; - - public override WeaponStateType State => WeaponStateType.Attack; - public override void OnInit(WeaponBase weapon) => _weapon = weapon as WeaponLightning; - - public override void OnEnter() - { - _weapon.ResetAttackCooldown(_weapon._weaponData.Cooldown); - _weapon.Attack(); - } - - public override void OnUpdate(float elapseSeconds, float realElapseSeconds) - { - if (!_weapon._isAttacking) - { - _weapon.TransitionTo(WeaponStateType.Check_InRange); - } - } - - public override void OnLeave() - { - } - } - } -} diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLightning/WeaponLightning.AttackState.cs.meta b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLightning/WeaponLightning.AttackState.cs.meta deleted file mode 100644 index 36aa280..0000000 --- a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLightning/WeaponLightning.AttackState.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 25854832a7d3416dacab67bcfef2a2fa -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: \ No newline at end of file diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLightning/WeaponLightning.CheckInRangeState.cs b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLightning/WeaponLightning.CheckInRangeState.cs deleted file mode 100644 index 4438a9d..0000000 --- a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLightning/WeaponLightning.CheckInRangeState.cs +++ /dev/null @@ -1,48 +0,0 @@ -namespace SepCore.Entity -{ - public partial class WeaponLightning - { - private class CheckInRangeState : WeaponStateBase - { - private WeaponLightning _weapon; - - public override WeaponStateType State => WeaponStateType.Check_InRange; - public override void OnInit(WeaponBase weapon) => _weapon = weapon as WeaponLightning; - - public override void OnEnter() - { - if (_weapon._canAttack) - { - _weapon.TransitionTo(WeaponStateType.Attack); - } - } - - public override void OnUpdate(float elapseSeconds, float realElapseSeconds) - { - _weapon.Check(); - _weapon.RotateToTarget(elapseSeconds); - - if (_weapon._target == null || !_weapon._target.Available) - { - _weapon.TransitionTo(WeaponStateType.Idle); - return; - } - - if (!_weapon.IsInRange(_weapon._target, _weapon._sqrRange)) - { - _weapon.TransitionTo(WeaponStateType.Check_OutRange); - return; - } - - if (_weapon._canAttack) - { - _weapon.TransitionTo(WeaponStateType.Attack); - } - } - - public override void OnLeave() - { - } - } - } -} diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLightning/WeaponLightning.CheckInRangeState.cs.meta b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLightning/WeaponLightning.CheckInRangeState.cs.meta deleted file mode 100644 index 46164eb..0000000 --- a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLightning/WeaponLightning.CheckInRangeState.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 25404ad172434ba38609e797b6d96919 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: \ No newline at end of file diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLightning/WeaponLightning.CheckOutRangeState.cs b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLightning/WeaponLightning.CheckOutRangeState.cs deleted file mode 100644 index c96b847..0000000 --- a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLightning/WeaponLightning.CheckOutRangeState.cs +++ /dev/null @@ -1,38 +0,0 @@ -namespace SepCore.Entity -{ - public partial class WeaponLightning - { - private class CheckOutRangeState : WeaponStateBase - { - private WeaponLightning _weapon; - - public override WeaponStateType State => WeaponStateType.Check_OutRange; - public override void OnInit(WeaponBase weapon) => _weapon = weapon as WeaponLightning; - - public override void OnEnter() - { - } - - public override void OnUpdate(float elapseSeconds, float realElapseSeconds) - { - _weapon.Check(); - _weapon.RotateToTarget(elapseSeconds); - - if (_weapon._target == null || !_weapon._target.Available) - { - _weapon.TransitionTo(WeaponStateType.Idle); - return; - } - - if (_weapon.IsInRange(_weapon._target, _weapon._sqrRange)) - { - _weapon.TransitionTo(WeaponStateType.Check_InRange); - } - } - - public override void OnLeave() - { - } - } - } -} diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLightning/WeaponLightning.CheckOutRangeState.cs.meta b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLightning/WeaponLightning.CheckOutRangeState.cs.meta deleted file mode 100644 index e9c3d49..0000000 --- a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLightning/WeaponLightning.CheckOutRangeState.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: f3aa479abb79491d83e8de76806faf7a -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: \ No newline at end of file diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLightning/WeaponLightning.IdleState.cs b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLightning/WeaponLightning.IdleState.cs deleted file mode 100644 index 44955c1..0000000 --- a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLightning/WeaponLightning.IdleState.cs +++ /dev/null @@ -1,32 +0,0 @@ -namespace SepCore.Entity -{ - public partial class WeaponLightning - { - private class IdleState : WeaponStateBase - { - private WeaponLightning _weapon; - - public override WeaponStateType State => WeaponStateType.Idle; - public override void OnInit(WeaponBase weapon) => _weapon = weapon as WeaponLightning; - - public override void OnEnter() - { - } - - public override void OnUpdate(float elapseSeconds, float realElapseSeconds) - { - _weapon.Check(); - _weapon.RotateToOrigin(elapseSeconds); - - if (_weapon._target != null && _weapon._target.Available) - { - _weapon.TransitionTo(WeaponStateType.Check_OutRange); - } - } - - public override void OnLeave() - { - } - } - } -} diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLightning/WeaponLightning.IdleState.cs.meta b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLightning/WeaponLightning.IdleState.cs.meta deleted file mode 100644 index 70343bd..0000000 --- a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLightning/WeaponLightning.IdleState.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 3464037c29774c3ea326dc93fe33551e -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: \ No newline at end of file diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLightning/WeaponLightning.cs b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLightning/WeaponLightning.cs index 69027d6..9748ca9 100644 --- a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLightning/WeaponLightning.cs +++ b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLightning/WeaponLightning.cs @@ -8,13 +8,8 @@ using UnityGameFramework.Runtime; namespace SepCore.Entity { - public partial class WeaponLightning : WeaponBase + public class WeaponLightning : WeaponBase { - private WeaponLightningData _weaponData; - - private Quaternion _cachedRotation; - [SerializeField] private float _rotateSpeed = 5f; - [SerializeField] private float _takeOffDuration = 0.3f; [SerializeField] private float _flyToTargetDuration = 0.2f; [SerializeField] private float _strikeDuration = 0.1f; @@ -22,7 +17,6 @@ namespace SepCore.Entity [SerializeField] private float _hoverHeight = 15f; - [SerializeField] private LayerMask _hitMask = ~0; [SerializeField] private int _maxHitColliders = 32; private Sequence _attackSequence; @@ -32,25 +26,19 @@ namespace SepCore.Entity private Collider[] _hitResults; private readonly HashSet _hitEntityIds = new(); - private float _hitRadius; - private float _hitRadiusSqr; + public float HitRadius => WeaponData.GetParamFloat(ParamType.HitRadius); private IWeaponAttackEffect _attackEffect; - public override ImpactData GetImpactData() - { - return new ImpactData(_weaponData.OwnerCamp, _weaponData.Attack, AttackStat); - } - protected override void BuildStates() { - RegisterState(new IdleState()); - RegisterState(new CheckOutRangeState()); - RegisterState(new CheckInRangeState()); - RegisterState(new AttackState()); + RegisterState(new WeaponLightningIdleState()); + RegisterState(new WeaponLightningSeekState()); + RegisterState(new WeaponLightningAimState()); + RegisterState(new WeaponLightningAttackState()); } - protected override void Attack() + public override void Attack() { StopAttackTween(false); FaceTargetImmediately(); @@ -70,7 +58,7 @@ namespace SepCore.Entity _attackSequence.Append(CachedTransform.DOMove(_lockedStrikePoint, _strikeDuration).SetEase(Ease.InQuad)); _attackSequence.AppendCallback(() => { - _attackEffect?.Play(this, _lockedStrikePoint, _target, _hitRadius); + _attackEffect.Play(this, _lockedStrikePoint, _target, HitRadius); ApplyGroundAreaDamage(); if (_attackParent != null) @@ -87,11 +75,6 @@ namespace SepCore.Entity }); } - protected override void Check() - { - _target = SelectTarget(_sqrRange); - } - private Vector3 ResolveStrikePoint() { if (_target != null && _target.Available) @@ -104,19 +87,20 @@ namespace SepCore.Entity private void ApplyGroundAreaDamage() { - if (_hitRadius <= 0f) return; + float radius = HitRadius; + if (radius <= 0f) return; - if (TryQueueAreaCollisionQuery(_lockedStrikePoint, _hitRadius, Mathf.Max(1, _maxHitColliders))) + if (TryQueueAreaCollisionQuery(_lockedStrikePoint, radius, Mathf.Max(1, _maxHitColliders))) { - _hitEntityIds.Clear(); return; } if (_hitResults == null || _hitResults.Length == 0) return; - int hitCount = Physics.OverlapSphereNonAlloc(_lockedStrikePoint, _hitRadius, _hitResults, _hitMask, + int hitCount = Physics.OverlapSphereNonAlloc(_lockedStrikePoint, radius, _hitResults, _hitMask, QueryTriggerInteraction.Collide); + float radiusSqr = radius * radius; _hitEntityIds.Clear(); for (int i = 0; i < hitCount; i++) { @@ -129,61 +113,14 @@ namespace SepCore.Entity Vector3 delta = targetable.CachedTransform.position - _lockedStrikePoint; delta.y = 0f; - if (delta.sqrMagnitude > _hitRadiusSqr) continue; + if (delta.sqrMagnitude > radiusSqr) continue; AIUtility.PerformCollision(targetable, this); } } - private void RotateToTarget(float elapseSeconds) - { - if (_target == null || !_target.Available) return; - - Vector3 directionToTarget = _target.CachedTransform.position - CachedTransform.position; - directionToTarget.y = 0f; - if (directionToTarget.sqrMagnitude <= Mathf.Epsilon) return; - - Quaternion targetRotation = Quaternion.LookRotation(directionToTarget.normalized, Vector3.up); - CachedTransform.rotation = - Quaternion.Slerp(CachedTransform.rotation, targetRotation, _rotateSpeed * elapseSeconds); - } - - private void RotateToOrigin(float elapseSeconds) - { - CachedTransform.rotation = - Quaternion.Slerp(CachedTransform.rotation, _cachedRotation, _rotateSpeed * elapseSeconds); - } - - private void FaceTargetImmediately() - { - if (_target == null || !_target.Available) return; - - Vector3 directionToTarget = _target.CachedTransform.position - CachedTransform.position; - directionToTarget.y = 0f; - if (directionToTarget.sqrMagnitude <= Mathf.Epsilon) return; - - CachedTransform.rotation = Quaternion.LookRotation(directionToTarget.normalized, Vector3.up); - } - protected override bool OnWeaponShow(object userData) { - _weaponData = RequireWeaponData(userData); - if (_weaponData == null) return false; - WeaponData = _weaponData; - - StartAttackCooldown(_weaponData.Cooldown); - _sqrRange = _weaponData.AttackRange * _weaponData.AttackRange; - _cachedRotation = CachedTransform.rotation; - - float configuredHitRadius = _weaponData.ParamsData != null ? _weaponData.ParamsData.HitRadius : 0f; - _hitRadius = configuredHitRadius > 0f ? Mathf.Max(0.1f, configuredHitRadius) : _weaponData.AttackRange; - _hitRadiusSqr = _hitRadius * _hitRadius; - float configuredHoverHeight = _weaponData.ParamsData != null ? _weaponData.ParamsData.HoverHeight : 0f; - if (configuredHoverHeight > 0f) - { - _hoverHeight = Mathf.Max(0.1f, configuredHoverHeight); - } - int colliderCapacity = Mathf.Max(1, _maxHitColliders); if (_hitResults == null || _hitResults.Length != colliderCapacity) { @@ -191,37 +128,19 @@ namespace SepCore.Entity } _attackEffect = new LightningStrikeAttackEffect(); - - if (_weaponData.OwnerCamp == CampType.Player) - { - gameObject.layer = LayerMask.NameToLayer("PlayerWeapon"); - _hitMask = LayerMask.GetMask("Enemy"); - } - else if (_weaponData.OwnerCamp == CampType.Enemy) - { - gameObject.layer = LayerMask.NameToLayer("EnemyWeapon"); - _hitMask = LayerMask.GetMask("Player"); - } - return true; } protected override void OnWeaponHide(object userData) { StopAttackTween(true); - CancelAttackCooldown(); _attackEffect = null; } - protected override void OnWeaponAttach(EntityLogic parentEntity, Transform parentTransform, object userData) - { - BindAttackStatFromOwner(parentEntity); - } - protected override void OnWeaponDetach(EntityLogic parentEntity, object userData) { StopAttackTween(true); - ReleaseAttackStatSubscription(); + base.OnWeaponDetach(parentEntity, userData); } protected override void OnEnabledChanged(bool enabled) diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLightning/WeaponLightningAimState.cs b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLightning/WeaponLightningAimState.cs new file mode 100644 index 0000000..0d8c88a --- /dev/null +++ b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLightning/WeaponLightningAimState.cs @@ -0,0 +1,51 @@ +using SepCore.Definition; + +namespace SepCore.Entity +{ + /// + /// 闪电的瞄准状态。 + /// + public sealed class WeaponLightningAimState : WeaponStateBase + { + private WeaponLightning _weapon; + + public override WeaponStateType State => WeaponStateType.Aim; + + public override void OnInit(WeaponBase weapon) => _weapon = (WeaponLightning)weapon; + + public override void OnEnter() + { + if (_weapon.CanAttack) + { + _weapon.TransitionTo(WeaponStateType.Attack); + } + } + + public override void OnUpdate(float elapseSeconds, float realElapseSeconds) + { + _weapon.Check(); + _weapon.RotateToTarget(elapseSeconds); + + if (_weapon.Target == null || !_weapon.Target.Available) + { + _weapon.TransitionTo(WeaponStateType.Idle); + return; + } + + if (!_weapon.IsInRange(_weapon.Target, _weapon.SqrRange)) + { + _weapon.TransitionTo(WeaponStateType.Seek); + return; + } + + if (_weapon.CanAttack) + { + _weapon.TransitionTo(WeaponStateType.Attack); + } + } + + public override void OnLeave() + { + } + } +} diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLightning/WeaponLightningAimState.cs.meta b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLightning/WeaponLightningAimState.cs.meta new file mode 100644 index 0000000..0cc235a --- /dev/null +++ b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLightning/WeaponLightningAimState.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 472efc8d8802b4941892df6907b98d03 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLightning/WeaponLightningAttackState.cs b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLightning/WeaponLightningAttackState.cs new file mode 100644 index 0000000..8c51a07 --- /dev/null +++ b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLightning/WeaponLightningAttackState.cs @@ -0,0 +1,34 @@ +using SepCore.Definition; + +namespace SepCore.Entity +{ + /// + /// 闪电的攻击状态。 + /// + public sealed class WeaponLightningAttackState : WeaponStateBase + { + private WeaponLightning _weapon; + + public override WeaponStateType State => WeaponStateType.Attack; + + public override void OnInit(WeaponBase weapon) => _weapon = (WeaponLightning)weapon; + + public override void OnEnter() + { + _weapon.ResetAttackCooldown(_weapon.AttackCooldown); + _weapon.Attack(); + } + + public override void OnUpdate(float elapseSeconds, float realElapseSeconds) + { + if (!_weapon.IsAttacking) + { + _weapon.TransitionTo(WeaponStateType.Aim); + } + } + + public override void OnLeave() + { + } + } +} diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLightning/WeaponLightningAttackState.cs.meta b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLightning/WeaponLightningAttackState.cs.meta new file mode 100644 index 0000000..0f14743 --- /dev/null +++ b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLightning/WeaponLightningAttackState.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9d4b2a83cb82e1442826effabf6c9351 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLightning/WeaponLightningIdleState.cs b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLightning/WeaponLightningIdleState.cs new file mode 100644 index 0000000..009c0e7 --- /dev/null +++ b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLightning/WeaponLightningIdleState.cs @@ -0,0 +1,35 @@ +using SepCore.Definition; + +namespace SepCore.Entity +{ + /// + /// 闪电的待机状态。 + /// + public sealed class WeaponLightningIdleState : WeaponStateBase + { + private WeaponLightning _weapon; + + public override WeaponStateType State => WeaponStateType.Idle; + + public override void OnInit(WeaponBase weapon) => _weapon = (WeaponLightning)weapon; + + public override void OnEnter() + { + } + + public override void OnUpdate(float elapseSeconds, float realElapseSeconds) + { + _weapon.Check(); + _weapon.RotateToOrigin(elapseSeconds); + + if (_weapon.Target != null && _weapon.Target.Available) + { + _weapon.TransitionTo(WeaponStateType.Seek); + } + } + + public override void OnLeave() + { + } + } +} diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLightning/WeaponLightningIdleState.cs.meta b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLightning/WeaponLightningIdleState.cs.meta new file mode 100644 index 0000000..ff54197 --- /dev/null +++ b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLightning/WeaponLightningIdleState.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1f6fccbd2de0c494fa2f33e0fba04d4f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLightning/WeaponLightningSeekState.cs b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLightning/WeaponLightningSeekState.cs new file mode 100644 index 0000000..8201aae --- /dev/null +++ b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLightning/WeaponLightningSeekState.cs @@ -0,0 +1,41 @@ +using SepCore.Definition; + +namespace SepCore.Entity +{ + /// + /// 闪电的搜寻状态。 + /// + public sealed class WeaponLightningSeekState : WeaponStateBase + { + private WeaponLightning _weapon; + + public override WeaponStateType State => WeaponStateType.Seek; + + public override void OnInit(WeaponBase weapon) => _weapon = (WeaponLightning)weapon; + + public override void OnEnter() + { + } + + public override void OnUpdate(float elapseSeconds, float realElapseSeconds) + { + _weapon.Check(); + _weapon.RotateToTarget(elapseSeconds); + + if (_weapon.Target == null || !_weapon.Target.Available) + { + _weapon.TransitionTo(WeaponStateType.Idle); + return; + } + + if (_weapon.IsInRange(_weapon.Target, _weapon.SqrRange)) + { + _weapon.TransitionTo(WeaponStateType.Aim); + } + } + + public override void OnLeave() + { + } + } +} diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLightning/WeaponLightningSeekState.cs.meta b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLightning/WeaponLightningSeekState.cs.meta new file mode 100644 index 0000000..1f06fff --- /dev/null +++ b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponLightning/WeaponLightningSeekState.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9fe264206ae0d0d4492b94b952d6d698 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponSlash/WeaponSlash.AttackState.cs b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponSlash/WeaponSlash.AttackState.cs deleted file mode 100644 index bb848b9..0000000 --- a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponSlash/WeaponSlash.AttackState.cs +++ /dev/null @@ -1,30 +0,0 @@ -namespace SepCore.Entity -{ - public partial class WeaponSlash - { - private class AttackState : WeaponStateBase - { - private WeaponSlash _weapon; - public override WeaponStateType State => WeaponStateType.Attack; - public override void OnInit(WeaponBase weapon) => _weapon = weapon as WeaponSlash; - - public override void OnEnter() - { - _weapon.ResetAttackCooldown(_weapon._weaponData.Cooldown); - _weapon.Attack(); - } - - public override void OnUpdate(float elapseSeconds, float realElapseSeconds) - { - if (!_weapon._isAttacking) - { - _weapon.TransitionTo(WeaponStateType.Check_InRange); - } - } - - public override void OnLeave() - { - } - } - } -} \ No newline at end of file diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponSlash/WeaponSlash.AttackState.cs.meta b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponSlash/WeaponSlash.AttackState.cs.meta deleted file mode 100644 index 89d8e6a..0000000 --- a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponSlash/WeaponSlash.AttackState.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 96b136ec326941a0821f66ddf750de29 -timeCreated: 1771579419 \ No newline at end of file diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponSlash/WeaponSlash.CheckInRangeState.cs b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponSlash/WeaponSlash.CheckInRangeState.cs deleted file mode 100644 index c50059f..0000000 --- a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponSlash/WeaponSlash.CheckInRangeState.cs +++ /dev/null @@ -1,47 +0,0 @@ -namespace SepCore.Entity -{ - public partial class WeaponSlash - { - private class CheckInRangeState : WeaponStateBase - { - private WeaponSlash _weapon; - public override WeaponStateType State => WeaponStateType.Check_InRange; - public override void OnInit(WeaponBase weapon) => _weapon = weapon as WeaponSlash; - - public override void OnEnter() - { - if (_weapon._canAttack) - { - _weapon.TransitionTo(WeaponStateType.Attack); - } - } - - public override void OnUpdate(float elapseSeconds, float realElapseSeconds) - { - _weapon.Check(); - _weapon.RotateToTarget(elapseSeconds); - - if (_weapon._target == null || !_weapon._target.Available) - { - _weapon.TransitionTo(WeaponStateType.Idle); - return; - } - - if (!_weapon.IsInRange(_weapon._target, _weapon._sqrRange)) - { - _weapon.TransitionTo(WeaponStateType.Check_OutRange); - return; - } - - if (_weapon._canAttack) - { - _weapon.TransitionTo(WeaponStateType.Attack); - } - } - - public override void OnLeave() - { - } - } - } -} \ No newline at end of file diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponSlash/WeaponSlash.CheckInRangeState.cs.meta b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponSlash/WeaponSlash.CheckInRangeState.cs.meta deleted file mode 100644 index 5b75111..0000000 --- a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponSlash/WeaponSlash.CheckInRangeState.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 57a936178b5a4ff2938df369b77631e6 -timeCreated: 1771579430 \ No newline at end of file diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponSlash/WeaponSlash.CheckOutRangeState.cs b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponSlash/WeaponSlash.CheckOutRangeState.cs deleted file mode 100644 index e3e3a21..0000000 --- a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponSlash/WeaponSlash.CheckOutRangeState.cs +++ /dev/null @@ -1,37 +0,0 @@ -namespace SepCore.Entity -{ - public partial class WeaponSlash - { - private class CheckOutRangeState : WeaponStateBase - { - private WeaponSlash _weapon; - public override WeaponStateType State => WeaponStateType.Check_OutRange; - public override void OnInit(WeaponBase weapon) => _weapon = weapon as WeaponSlash; - - public override void OnEnter() - { - } - - public override void OnUpdate(float elapseSeconds, float realElapseSeconds) - { - _weapon.Check(); - _weapon.RotateToTarget(elapseSeconds); - - if (_weapon._target == null || !_weapon._target.Available) - { - _weapon.TransitionTo(WeaponStateType.Idle); - return; - } - - if (_weapon.IsInRange(_weapon._target, _weapon._sqrRange)) - { - _weapon.TransitionTo(WeaponStateType.Check_InRange); - } - } - - public override void OnLeave() - { - } - } - } -} \ No newline at end of file diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponSlash/WeaponSlash.CheckOutRangeState.cs.meta b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponSlash/WeaponSlash.CheckOutRangeState.cs.meta deleted file mode 100644 index 1cb2f25..0000000 --- a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponSlash/WeaponSlash.CheckOutRangeState.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 89988d7be9104b0f83a423d1de2398b1 -timeCreated: 1771579440 \ No newline at end of file diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponSlash/WeaponSlash.IdleState.cs b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponSlash/WeaponSlash.IdleState.cs deleted file mode 100644 index 3189b71..0000000 --- a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponSlash/WeaponSlash.IdleState.cs +++ /dev/null @@ -1,31 +0,0 @@ -namespace SepCore.Entity -{ - public partial class WeaponSlash - { - private class IdleState : WeaponStateBase - { - private WeaponSlash _weapon; - public override WeaponStateType State => WeaponStateType.Idle; - public override void OnInit(WeaponBase weapon) => _weapon = weapon as WeaponSlash; - - public override void OnEnter() - { - } - - public override void OnUpdate(float elapseSeconds, float realElapseSeconds) - { - _weapon.Check(); - _weapon.RotateToOrigin(elapseSeconds); - - if (_weapon._target != null && _weapon._target.Available) - { - _weapon.TransitionTo(WeaponStateType.Check_OutRange); - } - } - - public override void OnLeave() - { - } - } - } -} \ No newline at end of file diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponSlash/WeaponSlash.IdleState.cs.meta b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponSlash/WeaponSlash.IdleState.cs.meta deleted file mode 100644 index eeb31e1..0000000 --- a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponSlash/WeaponSlash.IdleState.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: bec8a4a6cb974111bbd70072754f9fdb -timeCreated: 1771579452 \ No newline at end of file diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponSlash/WeaponSlash.cs b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponSlash/WeaponSlash.cs index b98ceb6..96b61d0 100644 --- a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponSlash/WeaponSlash.cs +++ b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponSlash/WeaponSlash.cs @@ -8,51 +8,37 @@ using UnityGameFramework.Runtime; namespace SepCore.Entity { - public partial class WeaponSlash : WeaponBase + public class WeaponSlash : WeaponBase { #region Property - private WeaponSlashData _weaponData; - - private Quaternion _cachedRotation; - [SerializeField] private float _rotateSpeed = 4f; - private Sequence _attackSequence; private Vector3 _attackCenter; private Quaternion _cachedAttackRotation; private IWeaponAttackEffect _attackEffect; - [SerializeField] private float attackDuration = 0.4f; - [SerializeField] private float returnDuration = 0.4f; + [SerializeField] private float _attackDuration = 0.4f; + [SerializeField] private float _returnDuration = 0.4f; [SerializeField] private float _swingAngleScale = 1f; - [SerializeField] private LayerMask _hitMask = ~0; [SerializeField] private int _maxHitColliders = 32; private Collider[] _hitResults; private readonly HashSet _hitEntityIds = new(); - private float _attackRadius; - private float _attackRadiusSqr; - private float _sectorAngle; + public float SectorAngle => WeaponData.GetParamFloat(ParamType.SectorAngle); #endregion - - public override ImpactData GetImpactData() - { - return new ImpactData(_weaponData.OwnerCamp, _weaponData.Attack, AttackStat); - } - protected override void BuildStates() { - RegisterState(new IdleState()); - RegisterState(new CheckInRangeState()); - RegisterState(new CheckOutRangeState()); - RegisterState(new AttackState()); + RegisterState(new WeaponSlashIdleState()); + RegisterState(new WeaponSlashAimState()); + RegisterState(new WeaponSlashSeekState()); + RegisterState(new WeaponSlashAttackState()); } - protected override void Attack() + public override void Attack() { StopAttackTween(false); FaceTargetImmediately(); @@ -61,20 +47,20 @@ namespace SepCore.Entity _attackCenter = CachedTransform.position; _cachedAttackRotation = CachedTransform.rotation; - float swingAngle = Mathf.Clamp(_sectorAngle * Mathf.Max(0.1f, _swingAngleScale), 15f, 170f); + float swingAngle = Mathf.Clamp(SectorAngle * Mathf.Max(0.1f, _swingAngleScale), 15f, 170f); Quaternion startRotation = Quaternion.AngleAxis(-swingAngle * 0.5f, Vector3.up) * _cachedAttackRotation; Quaternion endRotation = Quaternion.AngleAxis(swingAngle * 0.5f, Vector3.up) * _cachedAttackRotation; CachedTransform.rotation = startRotation; _attackSequence = DOTween.Sequence(); _attackSequence.Append( - CachedTransform.DORotateQuaternion(endRotation, attackDuration).SetEase(Ease.OutSine)); - _attackSequence.InsertCallback(attackDuration * 0.5f, () => + CachedTransform.DORotateQuaternion(endRotation, _attackDuration).SetEase(Ease.OutSine)); + _attackSequence.InsertCallback(_attackDuration * 0.5f, () => { - _attackEffect?.Play(this, _attackCenter, _target, _attackRadius); + _attackEffect.Play(this, _attackCenter, _target, WeaponData.AttackRange); ApplySectorDamage(); }); - _attackSequence.Append(CachedTransform.DORotateQuaternion(_cachedAttackRotation, returnDuration) + _attackSequence.Append(CachedTransform.DORotateQuaternion(_cachedAttackRotation, _returnDuration) .SetEase(Ease.InSine)); _attackSequence.AppendCallback(() => { @@ -83,14 +69,10 @@ namespace SepCore.Entity }); } - protected override void Check() - { - _target = SelectTarget(_sqrRange); - } - private void ApplySectorDamage() { - if (_attackRadius <= 0f) return; + float attackRadius = WeaponData.AttackRange; + if (attackRadius <= 0f) return; Vector3 forward = CachedTransform.forward; forward.y = 0f; @@ -100,19 +82,19 @@ namespace SepCore.Entity } forward.Normalize(); - float halfAngle = _sectorAngle * 0.5f; - if (TryQueueSectorCollisionQuery(_attackCenter, _attackRadius, in forward, halfAngle, + float halfAngle = SectorAngle * 0.5f; + if (TryQueueSectorCollisionQuery(_attackCenter, attackRadius, in forward, halfAngle, Mathf.Max(1, _maxHitColliders))) { - _hitEntityIds.Clear(); return; } if (_hitResults == null || _hitResults.Length == 0) return; - int hitCount = Physics.OverlapSphereNonAlloc(_attackCenter, _attackRadius, _hitResults, _hitMask, + int hitCount = Physics.OverlapSphereNonAlloc(_attackCenter, attackRadius, _hitResults, _hitMask, QueryTriggerInteraction.Collide); + float attackRadiusSqr = attackRadius * attackRadius; _hitEntityIds.Clear(); for (int i = 0; i < hitCount; i++) { @@ -127,7 +109,7 @@ namespace SepCore.Entity toTarget.y = 0f; float sqrDistance = toTarget.sqrMagnitude; - if (sqrDistance <= Mathf.Epsilon || sqrDistance > _attackRadiusSqr) continue; + if (sqrDistance <= Mathf.Epsilon || sqrDistance > attackRadiusSqr) continue; float angle = Vector3.Angle(forward, toTarget.normalized); if (angle > halfAngle) continue; @@ -136,53 +118,11 @@ namespace SepCore.Entity } } - private void RotateToTarget(float elapseSeconds) - { - if (_target == null || !_target.Available) return; - - Vector3 directionToTarget = _target.CachedTransform.position - CachedTransform.position; - directionToTarget.y = 0f; - if (directionToTarget.sqrMagnitude <= Mathf.Epsilon) return; - - Quaternion targetRotation = Quaternion.LookRotation(directionToTarget.normalized, Vector3.up); - CachedTransform.rotation = - Quaternion.Slerp(CachedTransform.rotation, targetRotation, _rotateSpeed * elapseSeconds); - } - - private void RotateToOrigin(float elapseSeconds) - { - CachedTransform.rotation = - Quaternion.Slerp(CachedTransform.rotation, _cachedRotation, _rotateSpeed * elapseSeconds); - } - - private void FaceTargetImmediately() - { - if (_target == null || !_target.Available) return; - - Vector3 directionToTarget = _target.CachedTransform.position - CachedTransform.position; - directionToTarget.y = 0f; - if (directionToTarget.sqrMagnitude <= Mathf.Epsilon) return; - - CachedTransform.rotation = Quaternion.LookRotation(directionToTarget.normalized, Vector3.up); - } - #region Lifecycle protected override bool OnWeaponShow(object userData) { - _weaponData = RequireWeaponData(userData); - if (_weaponData == null) return false; - WeaponData = _weaponData; - - StartAttackCooldown(_weaponData.Cooldown); - _sqrRange = _weaponData.AttackRange * _weaponData.AttackRange; - _cachedRotation = CachedTransform.rotation; - - _attackRadius = Mathf.Max(0.1f, _weaponData.AttackRange); - _attackRadiusSqr = _attackRadius * _attackRadius; - - float configuredSectorAngle = _weaponData.ParamsData != null ? _weaponData.ParamsData.SectorAngle : 0f; - _sectorAngle = configuredSectorAngle > 0f ? Mathf.Clamp(configuredSectorAngle, 1f, 360f) : 90f; + _cachedAttackRotation = _cachedRotation; int capacity = Mathf.Max(1, _maxHitColliders); if (_hitResults == null || _hitResults.Length != capacity) @@ -191,37 +131,19 @@ namespace SepCore.Entity } _attackEffect = new SlashSectorAttackEffect(); - - if (_weaponData.OwnerCamp == CampType.Player) - { - gameObject.layer = LayerMask.NameToLayer("PlayerWeapon"); - _hitMask = LayerMask.GetMask("Enemy"); - } - else if (_weaponData.OwnerCamp == CampType.Enemy) - { - gameObject.layer = LayerMask.NameToLayer("EnemyWeapon"); - _hitMask = LayerMask.GetMask("Player"); - } - return true; } protected override void OnWeaponHide(object userData) { StopAttackTween(true); - CancelAttackCooldown(); _attackEffect = null; } - protected override void OnWeaponAttach(EntityLogic parentEntity, Transform parentTransform, object userData) - { - BindAttackStatFromOwner(parentEntity); - } - protected override void OnWeaponDetach(EntityLogic parentEntity, object userData) { StopAttackTween(true); - ReleaseAttackStatSubscription(); + base.OnWeaponDetach(parentEntity, userData); } protected override void OnEnabledChanged(bool enabled) @@ -234,7 +156,6 @@ namespace SepCore.Entity #endregion - private void StopAttackTween(bool resetTransform) { if (_attackSequence != null) @@ -252,7 +173,5 @@ namespace SepCore.Entity _hitEntityIds.Clear(); } - - public float SectorAngle => _sectorAngle; } } diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponSlash/WeaponSlashAimState.cs b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponSlash/WeaponSlashAimState.cs new file mode 100644 index 0000000..0d3ffd6 --- /dev/null +++ b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponSlash/WeaponSlashAimState.cs @@ -0,0 +1,51 @@ +using SepCore.Definition; + +namespace SepCore.Entity +{ + /// + /// 斩击的瞄准状态。 + /// + public sealed class WeaponSlashAimState : WeaponStateBase + { + private WeaponSlash _weapon; + + public override WeaponStateType State => WeaponStateType.Aim; + + public override void OnInit(WeaponBase weapon) => _weapon = (WeaponSlash)weapon; + + public override void OnEnter() + { + if (_weapon.CanAttack) + { + _weapon.TransitionTo(WeaponStateType.Attack); + } + } + + public override void OnUpdate(float elapseSeconds, float realElapseSeconds) + { + _weapon.Check(); + _weapon.RotateToTarget(elapseSeconds); + + if (_weapon.Target == null || !_weapon.Target.Available) + { + _weapon.TransitionTo(WeaponStateType.Idle); + return; + } + + if (!_weapon.IsInRange(_weapon.Target, _weapon.SqrRange)) + { + _weapon.TransitionTo(WeaponStateType.Seek); + return; + } + + if (_weapon.CanAttack) + { + _weapon.TransitionTo(WeaponStateType.Attack); + } + } + + public override void OnLeave() + { + } + } +} diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponSlash/WeaponSlashAimState.cs.meta b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponSlash/WeaponSlashAimState.cs.meta new file mode 100644 index 0000000..43e843d --- /dev/null +++ b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponSlash/WeaponSlashAimState.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c7414da82794ead4da61b1999fc7e744 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponSlash/WeaponSlashAttackState.cs b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponSlash/WeaponSlashAttackState.cs new file mode 100644 index 0000000..f8080e4 --- /dev/null +++ b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponSlash/WeaponSlashAttackState.cs @@ -0,0 +1,34 @@ +using SepCore.Definition; + +namespace SepCore.Entity +{ + /// + /// 斩击的攻击状态。 + /// + public sealed class WeaponSlashAttackState : WeaponStateBase + { + private WeaponSlash _weapon; + + public override WeaponStateType State => WeaponStateType.Attack; + + public override void OnInit(WeaponBase weapon) => _weapon = (WeaponSlash)weapon; + + public override void OnEnter() + { + _weapon.ResetAttackCooldown(_weapon.AttackCooldown); + _weapon.Attack(); + } + + public override void OnUpdate(float elapseSeconds, float realElapseSeconds) + { + if (!_weapon.IsAttacking) + { + _weapon.TransitionTo(WeaponStateType.Aim); + } + } + + public override void OnLeave() + { + } + } +} diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponSlash/WeaponSlashAttackState.cs.meta b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponSlash/WeaponSlashAttackState.cs.meta new file mode 100644 index 0000000..5818fed --- /dev/null +++ b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponSlash/WeaponSlashAttackState.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8eb95376ed449de4482bcdce19c7fbb7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponSlash/WeaponSlashIdleState.cs b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponSlash/WeaponSlashIdleState.cs new file mode 100644 index 0000000..cb2db26 --- /dev/null +++ b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponSlash/WeaponSlashIdleState.cs @@ -0,0 +1,35 @@ +using SepCore.Definition; + +namespace SepCore.Entity +{ + /// + /// 斩击的待机状态。 + /// + public sealed class WeaponSlashIdleState : WeaponStateBase + { + private WeaponSlash _weapon; + + public override WeaponStateType State => WeaponStateType.Idle; + + public override void OnInit(WeaponBase weapon) => _weapon = (WeaponSlash)weapon; + + public override void OnEnter() + { + } + + public override void OnUpdate(float elapseSeconds, float realElapseSeconds) + { + _weapon.Check(); + _weapon.RotateToOrigin(elapseSeconds); + + if (_weapon.Target != null && _weapon.Target.Available) + { + _weapon.TransitionTo(WeaponStateType.Seek); + } + } + + public override void OnLeave() + { + } + } +} diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponSlash/WeaponSlashIdleState.cs.meta b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponSlash/WeaponSlashIdleState.cs.meta new file mode 100644 index 0000000..8b49adb --- /dev/null +++ b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponSlash/WeaponSlashIdleState.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 001c3370c7d371b40a0d7821281a14f8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponSlash/WeaponSlashSeekState.cs b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponSlash/WeaponSlashSeekState.cs new file mode 100644 index 0000000..c2f5a64 --- /dev/null +++ b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponSlash/WeaponSlashSeekState.cs @@ -0,0 +1,41 @@ +using SepCore.Definition; + +namespace SepCore.Entity +{ + /// + /// 斩击的搜寻状态。 + /// + public sealed class WeaponSlashSeekState : WeaponStateBase + { + private WeaponSlash _weapon; + + public override WeaponStateType State => WeaponStateType.Seek; + + public override void OnInit(WeaponBase weapon) => _weapon = (WeaponSlash)weapon; + + public override void OnEnter() + { + } + + public override void OnUpdate(float elapseSeconds, float realElapseSeconds) + { + _weapon.Check(); + _weapon.RotateToTarget(elapseSeconds); + + if (_weapon.Target == null || !_weapon.Target.Available) + { + _weapon.TransitionTo(WeaponStateType.Idle); + return; + } + + if (_weapon.IsInRange(_weapon.Target, _weapon.SqrRange)) + { + _weapon.TransitionTo(WeaponStateType.Aim); + } + } + + public override void OnLeave() + { + } + } +} diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponSlash/WeaponSlashSeekState.cs.meta b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponSlash/WeaponSlashSeekState.cs.meta new file mode 100644 index 0000000..7045ee5 --- /dev/null +++ b/Assets/GameMain/Scripts/Runtime/EntityLogic/Weapon/WeaponSlash/WeaponSlashSeekState.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1f296d8dc7c2e6a459556c44496a4619 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Runtime/Utility/EntityDataFactory.cs b/Assets/GameMain/Scripts/Runtime/Utility/EntityDataFactory.cs index 42fecae..655e8ee 100644 --- a/Assets/GameMain/Scripts/Runtime/Utility/EntityDataFactory.cs +++ b/Assets/GameMain/Scripts/Runtime/Utility/EntityDataFactory.cs @@ -20,21 +20,12 @@ namespace SepCore.CustomUtility public static WeaponData Create(int entityId, WeaponType weaponType, int ownerId, CampType ownerCamp) { var config = GameEntry.Luban.Get((int)weaponType); - return weaponType switch - { - WeaponType.Handgun => new WeaponHandgunData(entityId, config, ownerId, ownerCamp), - WeaponType.Knife => new WeaponKnifeData(entityId, config, ownerId, ownerCamp), - WeaponType.Axe => new WeaponSlashData(entityId, config, ownerId, ownerCamp), - WeaponType.Lightning => new WeaponLightningData(entityId, config, ownerId, ownerCamp), - WeaponType.Lance => new WeaponLanceData(entityId, config, ownerId, ownerCamp), - _ => throw new NotImplementedException($"Unsupported weapon type '{weaponType}'.") - }; + return new WeaponData(entityId, config, ownerId, ownerCamp); } public static WeaponData Create(int entityId, WeaponConfig config, int ownerId, CampType ownerCamp) { - WeaponType type = config.WeaponType; - return Create(entityId, type, ownerId, ownerCamp); + return new WeaponData(entityId, config, ownerId, ownerCamp); } } } diff --git a/数据表/Datas/WeaponConfig_武器配置.xlsx b/数据表/Datas/WeaponConfig_武器配置.xlsx index 1e629a8..3073538 100644 Binary files a/数据表/Datas/WeaponConfig_武器配置.xlsx and b/数据表/Datas/WeaponConfig_武器配置.xlsx differ diff --git a/数据表/Datas/__enums__.xlsx b/数据表/Datas/__enums__.xlsx index 48ed9b5..c821c30 100644 Binary files a/数据表/Datas/__enums__.xlsx and b/数据表/Datas/__enums__.xlsx differ