diff --git a/Assets/GameMain/DataTables/Entity.txt b/Assets/GameMain/DataTables/Entity.txt
index 773b0a3..bd1e86b 100644
--- a/Assets/GameMain/DataTables/Entity.txt
+++ b/Assets/GameMain/DataTables/Entity.txt
@@ -10,5 +10,6 @@
202 武器手枪 WeaponHandgun
203 武器斧头 WeaponSlash
204 武器闪电 WeaponLightning
+ 205 武器长枪 WeaponLance
10001 金币实体 CoinEntity
10002 经验实体 ExpEntity
diff --git a/Assets/GameMain/DataTables/Goods.txt b/Assets/GameMain/DataTables/Goods.txt
index 3a18b18..7b83641 100644
--- a/Assets/GameMain/DataTables/Goods.txt
+++ b/Assets/GameMain/DataTables/Goods.txt
@@ -1,5 +1,4 @@
-# 商品表
-# Id GoodsType GoodsTypeId
+# Id 列1 GoodsType GoodsTypeId
# int GoodsType int
# 商品编号 策划备注 商品类型 商品对应物品Id
101 道具:药 Prop 101
@@ -26,3 +25,4 @@
122 Prop 120
123 Weapon 3
124 Weapon 4
+ 125 Weapon 5
diff --git a/Assets/GameMain/DataTables/Weapon.txt b/Assets/GameMain/DataTables/Weapon.txt
index 9c72174..5075f13 100644
--- a/Assets/GameMain/DataTables/Weapon.txt
+++ b/Assets/GameMain/DataTables/Weapon.txt
@@ -1,8 +1,8 @@
-# 武器表
-# Id EntityTypeId Title IconAssetName Rarity Price PriceRandomPercent Attack Cooldown AttackRange AttackSoundId Pramas Modifiers
+# Id 列1 EntityTypeId Title IconAssetName Rarity Price PriceRandomPercent Attack Cooldown AttackRange AttackSoundId Pramas Modifiers
# int int string string RarityType int float int float float int string[] StatModifier[]
# 武器编号 策划备注 武器实体编号 武器名 图标资源名 道具品质 武器价格 价格浮动 伤害 冷却 范围 攻击音效编号 额外参数 额外属性
1 玩家武器 201 小刀 Almighty_Icon White 120 0.05 100 1.5 5 10000 {"hitRadius":2} []
2 202 手枪 Almighty_Icon White 130 0.05 120 1 15 10000 {} []
- 3 203 斧头 Almighty_Icon White 100 0.1 150 2 5 10000 {"SectorAngle":120} []
+ 3 203 斧头 Almighty_Icon White 100 0.1 150 2 5 10000 {"sectorAngle":120} []
4 204 闪电 Almighty_Icon White 150 0.08 80 3 12 10000 {"hitRadius":3} []
+ 5 205 长枪 Almighty_Icon White 100 0.1 100 1.5 7 10000 {"hitRadius":0.3,"thrustDistance":1.2,"pierceLength":0.3}
diff --git a/Assets/GameMain/Entities/WeaponLance.prefab b/Assets/GameMain/Entities/WeaponLance.prefab
new file mode 100644
index 0000000..6cf8f57
--- /dev/null
+++ b/Assets/GameMain/Entities/WeaponLance.prefab
@@ -0,0 +1,225 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!1 &6354441506395502586
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 8872382261416578947}
+ - component: {fileID: 1092941560137749238}
+ - component: {fileID: 2293075059394330032}
+ m_Layer: 11
+ m_Name: Cylinder
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!4 &8872382261416578947
+Transform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 6354441506395502586}
+ serializedVersion: 2
+ m_LocalRotation: {x: 0.7071068, y: 0, z: 0, w: 0.7071068}
+ m_LocalPosition: {x: 0, y: 0, z: 0.4}
+ m_LocalScale: {x: 0.5, y: 0.3, z: 0.5}
+ m_ConstrainProportionsScale: 0
+ m_Children: []
+ m_Father: {fileID: 5097192555115739519}
+ m_LocalEulerAnglesHint: {x: 90, y: 0, z: 0}
+--- !u!33 &1092941560137749238
+MeshFilter:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 6354441506395502586}
+ m_Mesh: {fileID: 10206, guid: 0000000000000000e000000000000000, type: 0}
+--- !u!23 &2293075059394330032
+MeshRenderer:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 6354441506395502586}
+ m_Enabled: 1
+ m_CastShadows: 1
+ m_ReceiveShadows: 1
+ m_DynamicOccludee: 1
+ m_StaticShadowCaster: 0
+ m_MotionVectors: 1
+ m_LightProbeUsage: 1
+ m_ReflectionProbeUsage: 1
+ m_RayTracingMode: 2
+ m_RayTraceProcedural: 0
+ m_RenderingLayerMask: 1
+ m_RendererPriority: 0
+ m_Materials:
+ - {fileID: 2100000, guid: c4f37184fcb9306428d7d002f7dca96d, type: 2}
+ m_StaticBatchInfo:
+ firstSubMesh: 0
+ subMeshCount: 0
+ m_StaticBatchRoot: {fileID: 0}
+ m_ProbeAnchor: {fileID: 0}
+ m_LightProbeVolumeOverride: {fileID: 0}
+ m_ScaleInLightmap: 1
+ m_ReceiveGI: 1
+ m_PreserveUVs: 0
+ m_IgnoreNormalsForChartDetection: 0
+ m_ImportantGI: 0
+ m_StitchLightmapSeams: 1
+ m_SelectedEditorRenderState: 3
+ m_MinimumChartSize: 4
+ m_AutoUVMaxDistance: 0.5
+ m_AutoUVMaxAngle: 89
+ m_LightmapParameters: {fileID: 0}
+ m_SortingLayerID: 0
+ m_SortingLayer: 0
+ m_SortingOrder: 0
+ m_AdditionalVertexStreams: {fileID: 0}
+--- !u!1 &6722279723536450523
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 4238244161129684256}
+ - component: {fileID: 8136283925019532162}
+ - component: {fileID: 452598937405325984}
+ - component: {fileID: 6200741578935482964}
+ m_Layer: 11
+ m_Name: Cylinder 1
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!4 &4238244161129684256
+Transform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 6722279723536450523}
+ serializedVersion: 2
+ m_LocalRotation: {x: 0.7071068, y: 0, z: 0, w: 0.7071068}
+ m_LocalPosition: {x: 0, y: 0, z: 0.7}
+ m_LocalScale: {x: 0.2, y: 0.3, z: 0.2}
+ m_ConstrainProportionsScale: 0
+ m_Children: []
+ m_Father: {fileID: 5097192555115739519}
+ m_LocalEulerAnglesHint: {x: 90, y: 0, z: 0}
+--- !u!33 &8136283925019532162
+MeshFilter:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 6722279723536450523}
+ m_Mesh: {fileID: 10206, guid: 0000000000000000e000000000000000, type: 0}
+--- !u!23 &452598937405325984
+MeshRenderer:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 6722279723536450523}
+ m_Enabled: 1
+ m_CastShadows: 1
+ m_ReceiveShadows: 1
+ m_DynamicOccludee: 1
+ m_StaticShadowCaster: 0
+ m_MotionVectors: 1
+ m_LightProbeUsage: 1
+ m_ReflectionProbeUsage: 1
+ m_RayTracingMode: 2
+ m_RayTraceProcedural: 0
+ m_RenderingLayerMask: 1
+ m_RendererPriority: 0
+ m_Materials:
+ - {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, type: 2}
+ m_StaticBatchInfo:
+ firstSubMesh: 0
+ subMeshCount: 0
+ m_StaticBatchRoot: {fileID: 0}
+ m_ProbeAnchor: {fileID: 0}
+ m_LightProbeVolumeOverride: {fileID: 0}
+ m_ScaleInLightmap: 1
+ m_ReceiveGI: 1
+ m_PreserveUVs: 0
+ m_IgnoreNormalsForChartDetection: 0
+ m_ImportantGI: 0
+ m_StitchLightmapSeams: 1
+ m_SelectedEditorRenderState: 3
+ m_MinimumChartSize: 4
+ m_AutoUVMaxDistance: 0.5
+ m_AutoUVMaxAngle: 89
+ m_LightmapParameters: {fileID: 0}
+ m_SortingLayerID: 0
+ m_SortingLayer: 0
+ m_SortingOrder: 0
+ m_AdditionalVertexStreams: {fileID: 0}
+--- !u!136 &6200741578935482964
+CapsuleCollider:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 6722279723536450523}
+ m_Material: {fileID: 0}
+ m_IncludeLayers:
+ serializedVersion: 2
+ m_Bits: 0
+ m_ExcludeLayers:
+ serializedVersion: 2
+ m_Bits: 0
+ m_LayerOverridePriority: 0
+ m_IsTrigger: 0
+ m_ProvidesContacts: 0
+ m_Enabled: 1
+ serializedVersion: 2
+ m_Radius: 0.5000001
+ m_Height: 2
+ m_Direction: 1
+ m_Center: {x: 0.000000059604645, y: 0, z: -0.00000008940697}
+--- !u!1 &7825103691467368365
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 5097192555115739519}
+ m_Layer: 11
+ m_Name: WeaponLance
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!4 &5097192555115739519
+Transform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 7825103691467368365}
+ serializedVersion: 2
+ m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+ m_LocalPosition: {x: 0, y: 0, z: 0}
+ m_LocalScale: {x: 1, y: 1, z: 1}
+ m_ConstrainProportionsScale: 0
+ m_Children:
+ - {fileID: 8872382261416578947}
+ - {fileID: 4238244161129684256}
+ m_Father: {fileID: 0}
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
diff --git a/Assets/GameMain/Entities/WeaponLance.prefab.meta b/Assets/GameMain/Entities/WeaponLance.prefab.meta
new file mode 100644
index 0000000..541f6e3
--- /dev/null
+++ b/Assets/GameMain/Entities/WeaponLance.prefab.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 11143001bcbdc864b8d8fe2083142e5a
+PrefabImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/GameMain/Scripts/DataTable/DRWeapon.cs b/Assets/GameMain/Scripts/DataTable/DRWeapon.cs
index edf6b37..b2346c1 100644
--- a/Assets/GameMain/Scripts/DataTable/DRWeapon.cs
+++ b/Assets/GameMain/Scripts/DataTable/DRWeapon.cs
@@ -122,7 +122,7 @@ namespace DataTable
///
private Dictionary DeserializeParams(string rawParams)
{
- var dict = new Dictionary();
+ var dict = new Dictionary(StringComparer.OrdinalIgnoreCase);
if (string.IsNullOrWhiteSpace(rawParams))
{
return dict;
@@ -143,7 +143,7 @@ namespace DataTable
continue;
}
- dict[pair.Key.ToLower()] = pair.Value.ToString();
+ dict[pair.Key] = pair.Value.ToString();
}
}
catch (Exception exception)
diff --git a/Assets/GameMain/Scripts/Definition/Enum/WeaponType.cs b/Assets/GameMain/Scripts/Definition/Enum/WeaponType.cs
index f8c9520..cddd437 100644
--- a/Assets/GameMain/Scripts/Definition/Enum/WeaponType.cs
+++ b/Assets/GameMain/Scripts/Definition/Enum/WeaponType.cs
@@ -7,5 +7,6 @@ namespace Definition.Enum
WeaponHandgun = 2,
WeaponSlash = 3,
WeaponLightning = 4,
+ WeaponLance = 5,
}
}
diff --git a/Assets/GameMain/Scripts/Entity/EntityData/Enemy/EnemyData.cs b/Assets/GameMain/Scripts/Entity/EntityData/Enemy/EnemyData.cs
index 117a255..490eb8c 100644
--- a/Assets/GameMain/Scripts/Entity/EntityData/Enemy/EnemyData.cs
+++ b/Assets/GameMain/Scripts/Entity/EntityData/Enemy/EnemyData.cs
@@ -59,7 +59,7 @@ namespace Entity.EntityData
return false;
}
- return _drEnemy.Params.TryGetValue(key.ToLower(), out value);
+ return _drEnemy.Params.TryGetValue(key, out value);
}
}
}
diff --git a/Assets/GameMain/Scripts/Entity/EntityData/Weapon/WeaponData.cs b/Assets/GameMain/Scripts/Entity/EntityData/Weapon/WeaponData.cs
index b47958a..4483584 100644
--- a/Assets/GameMain/Scripts/Entity/EntityData/Weapon/WeaponData.cs
+++ b/Assets/GameMain/Scripts/Entity/EntityData/Weapon/WeaponData.cs
@@ -37,7 +37,7 @@ namespace Entity.EntityData
return false;
}
- return Params.TryGetValue(key.ToLower(), out value);
+ return Params.TryGetValue(key, out value);
}
protected TParams ParseParams() where TParams : new()
diff --git a/Assets/GameMain/Scripts/Entity/EntityData/Weapon/WeaponLanceData.cs b/Assets/GameMain/Scripts/Entity/EntityData/Weapon/WeaponLanceData.cs
new file mode 100644
index 0000000..c3c3cce
--- /dev/null
+++ b/Assets/GameMain/Scripts/Entity/EntityData/Weapon/WeaponLanceData.cs
@@ -0,0 +1,56 @@
+using System;
+using Definition.Enum;
+
+namespace Entity.EntityData
+{
+ [Serializable]
+ public sealed class WeaponLanceParamsData
+ {
+ ///
+ /// 枪尖命中半径。
+ ///
+ public float HitRadius { get; set; }
+
+ ///
+ /// 武器模型前刺的位移距离。
+ ///
+ public float ThrustDistance { get; set; }
+
+ ///
+ /// 实际判定的前刺长度。
+ ///
+ public float PierceLength { 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, int ownerId, CampType ownerCamp)
+ : base(entityId, WeaponType.WeaponLance, ownerId, ownerCamp)
+ {
+ ParamsData = ParseParams();
+ }
+ }
+}
diff --git a/Assets/GameMain/Scripts/Entity/EntityData/Weapon/WeaponLanceData.cs.meta b/Assets/GameMain/Scripts/Entity/EntityData/Weapon/WeaponLanceData.cs.meta
new file mode 100644
index 0000000..f16bacc
--- /dev/null
+++ b/Assets/GameMain/Scripts/Entity/EntityData/Weapon/WeaponLanceData.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 4d1a821e8ee1a9a4b912b70b0a1616eb
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/GameMain/Scripts/Entity/EntityLogic/Weapon/WeaponBase.cs b/Assets/GameMain/Scripts/Entity/EntityLogic/Weapon/WeaponBase.cs
index 754a296..3a4fd7c 100644
--- a/Assets/GameMain/Scripts/Entity/EntityLogic/Weapon/WeaponBase.cs
+++ b/Assets/GameMain/Scripts/Entity/EntityLogic/Weapon/WeaponBase.cs
@@ -37,7 +37,7 @@ namespace Entity.Weapon
protected ITargetSelector TargetSelector { get; set; }
protected Dictionary _states;
-
+
protected WeaponStateBase _currentState;
protected EntityBase _target;
@@ -50,7 +50,7 @@ namespace Entity.Weapon
private StatComponent _attackStatComponent;
private System.Action _attackStatCallback;
-
+
private static readonly List s_EmptyCandidates = new();
#region Lifecycle
@@ -304,11 +304,4 @@ namespace Entity.Weapon
public abstract void OnLeave();
public override string ToString() => State.ToString();
}
-
-
-
-
-
-}
-
-
+}
\ No newline at end of file
diff --git a/Assets/GameMain/Scripts/Entity/EntityLogic/Weapon/WeaponHandgun/WeaponHandgun.cs b/Assets/GameMain/Scripts/Entity/EntityLogic/Weapon/WeaponHandgun/WeaponHandgun.cs
index cae096f..22bd47d 100644
--- a/Assets/GameMain/Scripts/Entity/EntityLogic/Weapon/WeaponHandgun/WeaponHandgun.cs
+++ b/Assets/GameMain/Scripts/Entity/EntityLogic/Weapon/WeaponHandgun/WeaponHandgun.cs
@@ -46,22 +46,15 @@ namespace Entity.Weapon
{
FaceTargetImmediately();
- Vector3 fireOrigin = CachedTransform.TransformPoint(_fireOriginOffset);
- Vector3 fireDirection = CachedTransform.forward;
- float maxDistance = Mathf.Max(0.1f, _weaponData.AttackRange);
-
- if (Physics.Raycast(fireOrigin, fireDirection, out RaycastHit hit, maxDistance, _hitMask,
- QueryTriggerInteraction.Collide))
+ if (!TryResolveAttackTarget(out TargetableObject targetable, out Vector3 hitPosition))
{
- TargetableObject targetable = hit.collider.GetComponentInParent();
- if (targetable != null && targetable.Available && !targetable.IsDead)
- {
- _attackEffect?.Play(this, hit.point, targetable, 0f);
- _isAttacking = true;
- AIUtility.PerformCollision(targetable, this);
- _isAttacking = false;
- }
+ return;
}
+
+ _attackEffect?.Play(this, hitPosition, targetable, 0f);
+ _isAttacking = true;
+ AIUtility.PerformCollision(targetable, this);
+ _isAttacking = false;
}
protected override void Check()
@@ -95,6 +88,40 @@ namespace Entity.Weapon
CachedTransform.rotation = Quaternion.LookRotation(directionToTarget.normalized, Vector3.up);
}
+ private bool TryResolveAttackTarget(out TargetableObject targetable, out Vector3 hitPosition)
+ {
+ targetable = _target as TargetableObject;
+ hitPosition = CachedTransform.position;
+ if (targetable == null || !targetable.Available || targetable.IsDead)
+ {
+ return false;
+ }
+
+ Transform targetTransform = targetable.CachedTransform;
+ if (targetTransform == null)
+ {
+ return false;
+ }
+
+ hitPosition = targetTransform.position;
+
+ Vector3 fireOrigin = CachedTransform.TransformPoint(_fireOriginOffset);
+ Vector3 directionToTarget = targetTransform.position - fireOrigin;
+ float maxDistance = Mathf.Max(0.1f, _weaponData.AttackRange);
+ if (directionToTarget.sqrMagnitude > Mathf.Epsilon &&
+ Physics.Raycast(fireOrigin, directionToTarget.normalized, out RaycastHit hit, maxDistance, _hitMask,
+ QueryTriggerInteraction.Collide))
+ {
+ TargetableObject raycastTarget = hit.collider.GetComponentInParent();
+ if (raycastTarget == targetable)
+ {
+ hitPosition = hit.point;
+ }
+ }
+
+ return true;
+ }
+
#region Lifecycle
protected override bool OnWeaponShow(object userData)
diff --git a/Assets/GameMain/Scripts/Entity/EntityLogic/Weapon/WeaponLance.meta b/Assets/GameMain/Scripts/Entity/EntityLogic/Weapon/WeaponLance.meta
new file mode 100644
index 0000000..4d75326
--- /dev/null
+++ b/Assets/GameMain/Scripts/Entity/EntityLogic/Weapon/WeaponLance.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: aee5d5037e73e894cac11712e321b930
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/GameMain/Scripts/Entity/EntityLogic/Weapon/WeaponLance/WeaponLance.AttackState.cs b/Assets/GameMain/Scripts/Entity/EntityLogic/Weapon/WeaponLance/WeaponLance.AttackState.cs
new file mode 100644
index 0000000..394b447
--- /dev/null
+++ b/Assets/GameMain/Scripts/Entity/EntityLogic/Weapon/WeaponLance/WeaponLance.AttackState.cs
@@ -0,0 +1,31 @@
+namespace Entity.Weapon
+{
+ 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._currAttackTimer = 0f;
+ _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/Entity/EntityLogic/Weapon/WeaponLance/WeaponLance.AttackState.cs.meta b/Assets/GameMain/Scripts/Entity/EntityLogic/Weapon/WeaponLance/WeaponLance.AttackState.cs.meta
new file mode 100644
index 0000000..2ad423b
--- /dev/null
+++ b/Assets/GameMain/Scripts/Entity/EntityLogic/Weapon/WeaponLance/WeaponLance.AttackState.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: d9991ee189b733b4e9d40395357f5ef2
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/GameMain/Scripts/Entity/EntityLogic/Weapon/WeaponLance/WeaponLance.CheckInRangeState.cs b/Assets/GameMain/Scripts/Entity/EntityLogic/Weapon/WeaponLance/WeaponLance.CheckInRangeState.cs
new file mode 100644
index 0000000..2d1d3d2
--- /dev/null
+++ b/Assets/GameMain/Scripts/Entity/EntityLogic/Weapon/WeaponLance/WeaponLance.CheckInRangeState.cs
@@ -0,0 +1,49 @@
+namespace Entity.Weapon
+{
+ 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._currAttackTimer >= _weapon._weaponData.Cooldown)
+ {
+ _weapon.TransitionTo(WeaponStateType.Attack);
+ }
+ }
+
+ public override void OnUpdate(float elapseSeconds, float realElapseSeconds)
+ {
+ _weapon.Check();
+ _weapon.RotateToTarget(elapseSeconds);
+ _weapon._currAttackTimer += 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._currAttackTimer >= _weapon._weaponData.Cooldown)
+ {
+ _weapon.TransitionTo(WeaponStateType.Attack);
+ }
+ }
+
+ public override void OnLeave()
+ {
+ }
+ }
+ }
+}
diff --git a/Assets/GameMain/Scripts/Entity/EntityLogic/Weapon/WeaponLance/WeaponLance.CheckInRangeState.cs.meta b/Assets/GameMain/Scripts/Entity/EntityLogic/Weapon/WeaponLance/WeaponLance.CheckInRangeState.cs.meta
new file mode 100644
index 0000000..3e6f575
--- /dev/null
+++ b/Assets/GameMain/Scripts/Entity/EntityLogic/Weapon/WeaponLance/WeaponLance.CheckInRangeState.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 01edc8bb0ff46a14d8028e03af932b52
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/GameMain/Scripts/Entity/EntityLogic/Weapon/WeaponLance/WeaponLance.CheckOutRangeState.cs b/Assets/GameMain/Scripts/Entity/EntityLogic/Weapon/WeaponLance/WeaponLance.CheckOutRangeState.cs
new file mode 100644
index 0000000..93bf972
--- /dev/null
+++ b/Assets/GameMain/Scripts/Entity/EntityLogic/Weapon/WeaponLance/WeaponLance.CheckOutRangeState.cs
@@ -0,0 +1,39 @@
+namespace Entity.Weapon
+{
+ 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);
+ _weapon._currAttackTimer += 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/Entity/EntityLogic/Weapon/WeaponLance/WeaponLance.CheckOutRangeState.cs.meta b/Assets/GameMain/Scripts/Entity/EntityLogic/Weapon/WeaponLance/WeaponLance.CheckOutRangeState.cs.meta
new file mode 100644
index 0000000..416d391
--- /dev/null
+++ b/Assets/GameMain/Scripts/Entity/EntityLogic/Weapon/WeaponLance/WeaponLance.CheckOutRangeState.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 8009ad2c332a956438e3357ed5e30eb6
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/GameMain/Scripts/Entity/EntityLogic/Weapon/WeaponLance/WeaponLance.IdleState.cs b/Assets/GameMain/Scripts/Entity/EntityLogic/Weapon/WeaponLance/WeaponLance.IdleState.cs
new file mode 100644
index 0000000..f0ab6f0
--- /dev/null
+++ b/Assets/GameMain/Scripts/Entity/EntityLogic/Weapon/WeaponLance/WeaponLance.IdleState.cs
@@ -0,0 +1,33 @@
+namespace Entity.Weapon
+{
+ 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);
+ _weapon._currAttackTimer += elapseSeconds;
+
+ if (_weapon._target != null && _weapon._target.Available)
+ {
+ _weapon.TransitionTo(WeaponStateType.Check_OutRange);
+ }
+ }
+
+ public override void OnLeave()
+ {
+ }
+ }
+ }
+}
diff --git a/Assets/GameMain/Scripts/Entity/EntityLogic/Weapon/WeaponLance/WeaponLance.IdleState.cs.meta b/Assets/GameMain/Scripts/Entity/EntityLogic/Weapon/WeaponLance/WeaponLance.IdleState.cs.meta
new file mode 100644
index 0000000..4ad5fa9
--- /dev/null
+++ b/Assets/GameMain/Scripts/Entity/EntityLogic/Weapon/WeaponLance/WeaponLance.IdleState.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 4c9e98f5381e579469dcdac7bf3e1e25
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/GameMain/Scripts/Entity/EntityLogic/Weapon/WeaponLance/WeaponLance.cs b/Assets/GameMain/Scripts/Entity/EntityLogic/Weapon/WeaponLance/WeaponLance.cs
new file mode 100644
index 0000000..2a94a49
--- /dev/null
+++ b/Assets/GameMain/Scripts/Entity/EntityLogic/Weapon/WeaponLance/WeaponLance.cs
@@ -0,0 +1,325 @@
+using System.Collections.Generic;
+using CustomUtility;
+using Definition.DataStruct;
+using Definition.Enum;
+using DG.Tweening;
+using Entity.EntityData;
+using UnityEngine;
+using UnityGameFramework.Runtime;
+
+namespace Entity.Weapon
+{
+ public partial class WeaponLance : WeaponBase
+ {
+ // 长枪专用数据,包含强类型 ParamsData。
+ [SerializeField] private WeaponLanceData _weaponData;
+
+ private Quaternion _cachedRotation;
+ // 朝向目标时的旋转速度,可被 ParamsData.RotateSpeed 覆盖。
+ [SerializeField] private float _rotateSpeed = 5f;
+
+ private Sequence _attackSequence;
+ private Transform _attackParent;
+
+ // 前刺动画耗时。
+ [SerializeField] private float _attackDuration = 0.12f;
+ // 收枪返回耗时。
+ [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 _hitRadius;
+ // 从判定起点向前延伸的有效刺击长度。
+ private float _pierceLength;
+ // 判定起点相对武器当前位置的前移量。
+ private float _forwardOffset;
+ // 武器模型本身向前突刺的位移长度。
+ private float _thrustDistance;
+
+ 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());
+ }
+
+ protected override void Attack()
+ {
+ StopAttackTween(false);
+ FaceTargetImmediately();
+
+ _isAttacking = true;
+ _attackParent = CachedTransform.parent;
+ CachedTransform.SetParent(null);
+
+ Vector3 targetPos = CachedTransform.position + CachedTransform.forward * _thrustDistance;
+ _attackSequence = DOTween.Sequence();
+ _attackSequence.Append(CachedTransform.DOMove(targetPos, _attackDuration).SetEase(Ease.OutQuad));
+ _attackSequence.AppendCallback(() =>
+ {
+ Vector3 strikeCenter = GetStrikeCenter();
+ _attackEffect?.Play(this, strikeCenter, _target, _hitRadius);
+ ApplyPierceDamage();
+
+ if (_attackParent != null)
+ {
+ CachedTransform.SetParent(_attackParent);
+ }
+ });
+ _attackSequence.Append(CachedTransform.DOLocalMove(Vector3.zero, _returnDuration).SetEase(Ease.InQuad));
+ _attackSequence.AppendCallback(() =>
+ {
+ _isAttacking = false;
+ _attackSequence = null;
+ _attackParent = null;
+ });
+ }
+
+ 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 Vector3 GetStrikeStart()
+ {
+ Vector3 forward = CachedTransform.forward;
+ forward.y = 0f;
+ if (forward.sqrMagnitude <= Mathf.Epsilon)
+ {
+ forward = Vector3.forward;
+ }
+
+ forward.Normalize();
+ return CachedTransform.position + forward * _forwardOffset;
+ }
+
+ private Vector3 GetStrikeEnd()
+ {
+ Vector3 start = GetStrikeStart();
+ Vector3 forward = CachedTransform.forward;
+ forward.y = 0f;
+ if (forward.sqrMagnitude <= Mathf.Epsilon)
+ {
+ forward = Vector3.forward;
+ }
+
+ forward.Normalize();
+ return start + forward * _pierceLength;
+ }
+
+ private Vector3 GetStrikeCenter()
+ {
+ return Vector3.Lerp(GetStrikeStart(), GetStrikeEnd(), 0.5f);
+ }
+
+ private void ApplyPierceDamage()
+ {
+ if (_hitRadius <= 0f || _pierceLength <= 0f) return;
+
+ Vector3 strikeStart = GetStrikeStart();
+ Vector3 strikeEnd = GetStrikeEnd();
+ Vector3 strikeDirection = strikeEnd - strikeStart;
+ strikeDirection.y = 0f;
+ if (strikeDirection.sqrMagnitude <= Mathf.Epsilon) return;
+
+ strikeDirection.Normalize();
+ float halfAngle = Mathf.Rad2Deg * Mathf.Atan2(_hitRadius, Mathf.Max(0.01f, _pierceLength));
+ if (TryQueueSectorCollisionQuery(strikeStart, _pierceLength, in strikeDirection, halfAngle,
+ Mathf.Max(1, _maxHitColliders)))
+ {
+ _hitEntityIds.Clear();
+ return;
+ }
+
+ int capacity = Mathf.Max(1, _maxHitColliders);
+ float broadPhaseRadius = _pierceLength * 0.5f + _hitRadius;
+ Vector3 broadPhaseCenter = Vector3.Lerp(strikeStart, strikeEnd, 0.5f);
+
+ if (_hitResults == null || _hitResults.Length != capacity)
+ {
+ _hitResults = new Collider[capacity];
+ }
+
+ int hitCount = Physics.OverlapSphereNonAlloc(broadPhaseCenter, broadPhaseRadius, _hitResults, _hitMask,
+ QueryTriggerInteraction.Collide);
+
+ _hitEntityIds.Clear();
+ for (int i = 0; i < hitCount; i++)
+ {
+ Collider collider = _hitResults[i];
+ if (collider == null) continue;
+
+ TargetableObject targetable = collider.GetComponentInParent();
+ if (targetable == null || !targetable.Available || targetable.IsDead) continue;
+ if (!_hitEntityIds.Add(targetable.Id)) continue;
+
+ if (!IsTargetInsidePierce(targetable, strikeStart, strikeDirection)) continue;
+
+ AIUtility.PerformCollision(targetable, this);
+ }
+ }
+
+ private bool IsTargetInsidePierce(TargetableObject targetable, Vector3 strikeStart, Vector3 strikeDirection)
+ {
+ Vector3 toTarget = targetable.CachedTransform.position - strikeStart;
+ toTarget.y = 0f;
+
+ float projection = Vector3.Dot(toTarget, strikeDirection);
+ if (projection < 0f || projection > _pierceLength) return false;
+
+ Vector3 closestPoint = strikeStart + strikeDirection * projection;
+ Vector3 delta = targetable.CachedTransform.position - closestPoint;
+ delta.y = 0f;
+ return delta.sqrMagnitude <= _hitRadius * _hitRadius;
+ }
+
+ protected override bool OnWeaponShow(object userData)
+ {
+ _weaponData = RequireWeaponData(userData);
+ if (_weaponData == null) return false;
+ WeaponData = _weaponData;
+
+ _currAttackTimer = 0f;
+ _sqrRange = _weaponData.AttackRange * _weaponData.AttackRange;
+ _cachedRotation = CachedTransform.rotation;
+
+ WeaponLanceParamsData paramsData = _weaponData.ParamsData;
+ _hitRadius = paramsData != null && paramsData.HitRadius > 0f
+ ? Mathf.Max(0.1f, paramsData.HitRadius)
+ : 0.45f;
+ _thrustDistance = paramsData != null && paramsData.ThrustDistance > 0f
+ ? paramsData.ThrustDistance
+ : _weaponData.AttackRange;
+ _pierceLength = paramsData != null && paramsData.PierceLength > 0f
+ ? paramsData.PierceLength
+ : Mathf.Max(_weaponData.AttackRange, _thrustDistance);
+ _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)
+ {
+ _hitResults = new Collider[colliderCapacity];
+ }
+
+ _attackEffect = new KnifeRangeAttackEffect();
+
+ 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);
+ _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();
+ }
+
+ protected override void OnEnabledChanged(bool enabled)
+ {
+ if (!enabled)
+ {
+ StopAttackTween(true);
+ }
+ }
+
+ private void StopAttackTween(bool resetTransform)
+ {
+ if (_attackSequence != null)
+ {
+ _attackSequence.Kill();
+ _attackSequence = null;
+ }
+
+ _isAttacking = false;
+
+ if (resetTransform && _attackParent != null)
+ {
+ CachedTransform.SetParent(_attackParent);
+ CachedTransform.localPosition = Vector3.zero;
+ CachedTransform.rotation = _cachedRotation;
+ }
+
+ _attackParent = null;
+ _hitEntityIds.Clear();
+ }
+ }
+}
diff --git a/Assets/GameMain/Scripts/Entity/EntityLogic/Weapon/WeaponLance/WeaponLance.cs.meta b/Assets/GameMain/Scripts/Entity/EntityLogic/Weapon/WeaponLance/WeaponLance.cs.meta
new file mode 100644
index 0000000..b54effa
--- /dev/null
+++ b/Assets/GameMain/Scripts/Entity/EntityLogic/Weapon/WeaponLance/WeaponLance.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: f90612be7695ee549b39473c9b706122
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/GameMain/Scripts/Procedure/Game/GameStateBattle.cs b/Assets/GameMain/Scripts/Procedure/Game/GameStateBattle.cs
index b6a4ba2..2e3f13b 100644
--- a/Assets/GameMain/Scripts/Procedure/Game/GameStateBattle.cs
+++ b/Assets/GameMain/Scripts/Procedure/Game/GameStateBattle.cs
@@ -92,14 +92,9 @@ namespace Procedure
GameEntry.Entity.HideEntity(entity.Id);
}
- var enemyProjectiles = GameEntry.Entity.GetEntityGroup("EnemyProjectile")?.GetAllEntities();
- if (enemyProjectiles != null)
- {
- foreach (var projectile in enemyProjectiles)
- {
- GameEntry.Entity.HideEntity(projectile.Id);
- }
- }
+ HideEntityGroup("Bullet");
+ HideEntityGroup("Projectile");
+ HideEntityGroup("EnemyProjectile");
}
public override void OnDestroy(IFsm procedureOwner)
@@ -108,6 +103,21 @@ namespace Procedure
_procedureGame = null;
}
+ private static void HideEntityGroup(string groupName)
+ {
+ var entityGroup = GameEntry.Entity.GetEntityGroup(groupName);
+ var entities = entityGroup?.GetAllEntities();
+ if (entities == null)
+ {
+ return;
+ }
+
+ foreach (var entity in entities)
+ {
+ GameEntry.Entity.HideEntity(entity.Id);
+ }
+ }
+
#endregion
}
}
diff --git a/Assets/GameMain/Scripts/Simulation/Presentation/SimulationWorld.HitPresentation.cs b/Assets/GameMain/Scripts/Simulation/Presentation/SimulationWorld.HitPresentation.cs
index d2776e7..4c681ff 100644
--- a/Assets/GameMain/Scripts/Simulation/Presentation/SimulationWorld.HitPresentation.cs
+++ b/Assets/GameMain/Scripts/Simulation/Presentation/SimulationWorld.HitPresentation.cs
@@ -104,18 +104,8 @@ namespace Simulation
private void PlayHitMarker(ProjectileHitPresentationEventArgs args)
{
- EntityBase targetEntity = TryGetEntityById(args.TargetEntityId);
- if (targetEntity == null || !targetEntity.Available)
- {
- return;
- }
-
- _projectileHitMarkerEffect ??= new HandgunHitMarkerAttackEffect(
- Mathf.Max(0.01f, _world._projectileHitMarkerSize),
- _world._projectileHitMarkerYOffset,
- Mathf.Max(0.01f, _world._projectileHitMarkerDuration),
- _world._projectileHitMarkerColor);
- _projectileHitMarkerEffect.Play(null, args.HitPosition, targetEntity, 0f);
+ // Projectile hit markers were reusing the handgun marker effect and were
+ // visually indistinguishable from handgun lock/hit feedback.
}
private void PlayHitEffect(ProjectileHitPresentationEventArgs args)
@@ -142,4 +132,4 @@ namespace Simulation
}
}
}
-}
\ No newline at end of file
+}
diff --git a/Assets/GameMain/Scripts/UI/GameScene/Controller/DisplayItemInfoFormController.cs b/Assets/GameMain/Scripts/UI/GameScene/Controller/DisplayItemInfoFormController.cs
index 19ce4dc..47019ee 100644
--- a/Assets/GameMain/Scripts/UI/GameScene/Controller/DisplayItemInfoFormController.cs
+++ b/Assets/GameMain/Scripts/UI/GameScene/Controller/DisplayItemInfoFormController.cs
@@ -139,19 +139,7 @@ namespace UI
{
return;
}
-
- if (Context == null)
- {
- Log.Error("DisplayItemInfoFormController.DisplayItemInfoHide() Context is null.");
- return;
- }
-
- if (Form == null)
- {
- Log.Error("DisplayItemInfoFormController.DisplayItemInfoHide() Form is null.");
- return;
- }
-
+
if (args.Force)
{
GameEntry.UIRouter.CloseUI(UIFormType.DisplayItemInfoForm);
@@ -159,11 +147,8 @@ namespace UI
return;
}
- if (_locked && !IsCurrentFormSender(sender) && sender is not DisplayItem)
- {
- return;
- }
-
+ if (_locked && !args.Force) return;
+
GameEntry.UIRouter.CloseUI(UIFormType.DisplayItemInfoForm);
_locked = false;
}
diff --git a/Assets/GameMain/Scripts/UI/GameScene/Controller/ShopFormController.cs b/Assets/GameMain/Scripts/UI/GameScene/Controller/ShopFormController.cs
index 59b2a7b..97924b3 100644
--- a/Assets/GameMain/Scripts/UI/GameScene/Controller/ShopFormController.cs
+++ b/Assets/GameMain/Scripts/UI/GameScene/Controller/ShopFormController.cs
@@ -199,6 +199,12 @@ namespace UI
#region UI Methods
+ public override void CloseUI()
+ {
+ base.CloseUI();
+ GameEntry.Event.Fire(this, DisplayItemInfoHideEventArgs.Create(true));
+ }
+
public int? OpenUI(ShopFormRawData rawData)
{
ShopFormContext context = BuildContext(rawData);
@@ -535,4 +541,4 @@ namespace UI
#endregion
}
-}
+}
\ No newline at end of file
diff --git a/Assets/GameMain/Scripts/UI/GameScene/UseCase/ShopFormUseCase.cs b/Assets/GameMain/Scripts/UI/GameScene/UseCase/ShopFormUseCase.cs
index b7f37d5..32d6ac8 100644
--- a/Assets/GameMain/Scripts/UI/GameScene/UseCase/ShopFormUseCase.cs
+++ b/Assets/GameMain/Scripts/UI/GameScene/UseCase/ShopFormUseCase.cs
@@ -397,6 +397,8 @@ namespace UI
return new WeaponSlashData(entityId, ownerId, ownerCamp);
case WeaponType.WeaponLightning:
return new WeaponLightningData(entityId, ownerId, ownerCamp);
+ case WeaponType.WeaponLance:
+ return new WeaponLanceData(entityId, ownerId, ownerCamp);
default:
return null;
}
diff --git a/Assets/GameMain/Scripts/UI/GameScene/View/DisplayItemInfoForm.cs b/Assets/GameMain/Scripts/UI/GameScene/View/DisplayItemInfoForm.cs
index 0e49b07..0b15368 100644
--- a/Assets/GameMain/Scripts/UI/GameScene/View/DisplayItemInfoForm.cs
+++ b/Assets/GameMain/Scripts/UI/GameScene/View/DisplayItemInfoForm.cs
@@ -199,7 +199,7 @@ namespace UI
public void OnCancelButtonClick()
{
- GameEntry.Event.Fire(this, DisplayItemInfoHideEventArgs.Create());
+ GameEntry.Event.Fire(this, DisplayItemInfoHideEventArgs.Create(true));
}
}
}
diff --git a/Assets/GameMain/Scripts/Utility/ItemDescUtility.cs b/Assets/GameMain/Scripts/Utility/ItemDescUtility.cs
index 313a308..35f582d 100644
--- a/Assets/GameMain/Scripts/Utility/ItemDescUtility.cs
+++ b/Assets/GameMain/Scripts/Utility/ItemDescUtility.cs
@@ -4,16 +4,23 @@ using DataTable;
using Definition.DataStruct;
using Entity.EntityData;
using Entity.Weapon;
+using System;
using UnityGameFramework.Runtime;
namespace CustomUtility
{
public static class ItemDescUtility
{
- private static readonly Dictionary _paramsDict = new()
+ private static readonly Dictionary _paramsDict = new(StringComparer.OrdinalIgnoreCase)
{
- {"hitradius", "伤害范围"},
- {"sectorangle", "攻击角度"}
+ {"hitRadius", "伤害范围"},
+ {"sectorAngle", "攻击角度"},
+ {"pierceLength", "前戳距离"},
+ {"thrustDistance", "枪尖长度"},
+ {"forwardOffset", "前置偏移"},
+ {"rotateSpeed", "转向速度"},
+ {"attackDuration", "突刺时长"},
+ {"returnDuration", "收枪时长"}
};
public static string CreatePropDescription(StatModifier[] modifiers)
@@ -89,6 +96,11 @@ namespace CustomUtility
sb.Append(modifiersDesc);
}
+ if (@params == null || @params.Count == 0)
+ {
+ return sb.ToString();
+ }
+
foreach (var kvp in @params)
{
if (!_paramsDict.TryGetValue(kvp.Key, out string value))
@@ -102,4 +114,4 @@ namespace CustomUtility
return sb.ToString();
}
}
-}
\ No newline at end of file
+}
diff --git a/Assets/Launcher.unity b/Assets/Launcher.unity
index ebdc71f..d1fd2c2 100644
--- a/Assets/Launcher.unity
+++ b/Assets/Launcher.unity
@@ -731,7 +731,7 @@ PrefabInstance:
objectReference: {fileID: 0}
- target: {fileID: 11499388, guid: adb3eb1c35fcff14f89fba7b05c9d71c, type: 3}
propertyPath: m_EditorResourceMode
- value: 0
+ value: 1
objectReference: {fileID: 0}
- target: {fileID: 11499388, guid: adb3eb1c35fcff14f89fba7b05c9d71c, type: 3}
propertyPath: m_JsonHelperTypeName
diff --git a/数据表/Entity/Entity.xlsx b/数据表/Entity/Entity.xlsx
index 6e9a339..12ab48e 100644
Binary files a/数据表/Entity/Entity.xlsx and b/数据表/Entity/Entity.xlsx differ
diff --git a/数据表/Entity/Weapon.xlsx b/数据表/Entity/Weapon.xlsx
index 15e9b26..e3c5955 100644
Binary files a/数据表/Entity/Weapon.xlsx and b/数据表/Entity/Weapon.xlsx differ
diff --git a/数据表/Goods.xlsx b/数据表/Goods.xlsx
index 1740ccc..ccdf210 100644
Binary files a/数据表/Goods.xlsx and b/数据表/Goods.xlsx differ