添加武器长枪 + bug fix
- WeaponLance:Entity/Goods/Weapon 表,状态机 - Battle -> Shop/LevelUp:隐藏子弹
This commit is contained in:
parent
f31babdb85
commit
8d21d53c4d
|
|
@ -10,5 +10,6 @@
|
||||||
202 武器手枪 WeaponHandgun
|
202 武器手枪 WeaponHandgun
|
||||||
203 武器斧头 WeaponSlash
|
203 武器斧头 WeaponSlash
|
||||||
204 武器闪电 WeaponLightning
|
204 武器闪电 WeaponLightning
|
||||||
|
205 武器长枪 WeaponLance
|
||||||
10001 金币实体 CoinEntity
|
10001 金币实体 CoinEntity
|
||||||
10002 经验实体 ExpEntity
|
10002 经验实体 ExpEntity
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
# 商品表
|
# Id 列1 GoodsType GoodsTypeId
|
||||||
# Id GoodsType GoodsTypeId
|
|
||||||
# int GoodsType int
|
# int GoodsType int
|
||||||
# 商品编号 策划备注 商品类型 商品对应物品Id
|
# 商品编号 策划备注 商品类型 商品对应物品Id
|
||||||
101 道具:药 Prop 101
|
101 道具:药 Prop 101
|
||||||
|
|
@ -26,3 +25,4 @@
|
||||||
122 Prop 120
|
122 Prop 120
|
||||||
123 Weapon 3
|
123 Weapon 3
|
||||||
124 Weapon 4
|
124 Weapon 4
|
||||||
|
125 Weapon 5
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
# 武器表
|
# Id 列1 EntityTypeId Title IconAssetName Rarity Price PriceRandomPercent Attack Cooldown AttackRange AttackSoundId Pramas Modifiers
|
||||||
# Id 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[]
|
# 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} []
|
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 {} []
|
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} []
|
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}
|
||||||
|
|
|
||||||
|
|
@ -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}
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 11143001bcbdc864b8d8fe2083142e5a
|
||||||
|
PrefabImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -122,7 +122,7 @@ namespace DataTable
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private Dictionary<string, string> DeserializeParams(string rawParams)
|
private Dictionary<string, string> DeserializeParams(string rawParams)
|
||||||
{
|
{
|
||||||
var dict = new Dictionary<string, string>();
|
var dict = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||||
if (string.IsNullOrWhiteSpace(rawParams))
|
if (string.IsNullOrWhiteSpace(rawParams))
|
||||||
{
|
{
|
||||||
return dict;
|
return dict;
|
||||||
|
|
@ -143,7 +143,7 @@ namespace DataTable
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
dict[pair.Key.ToLower()] = pair.Value.ToString();
|
dict[pair.Key] = pair.Value.ToString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception exception)
|
catch (Exception exception)
|
||||||
|
|
|
||||||
|
|
@ -7,5 +7,6 @@ namespace Definition.Enum
|
||||||
WeaponHandgun = 2,
|
WeaponHandgun = 2,
|
||||||
WeaponSlash = 3,
|
WeaponSlash = 3,
|
||||||
WeaponLightning = 4,
|
WeaponLightning = 4,
|
||||||
|
WeaponLance = 5,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ namespace Entity.EntityData
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return _drEnemy.Params.TryGetValue(key.ToLower(), out value);
|
return _drEnemy.Params.TryGetValue(key, out value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ namespace Entity.EntityData
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Params.TryGetValue(key.ToLower(), out value);
|
return Params.TryGetValue(key, out value);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected TParams ParseParams<TParams>() where TParams : new()
|
protected TParams ParseParams<TParams>() where TParams : new()
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
using System;
|
||||||
|
using Definition.Enum;
|
||||||
|
|
||||||
|
namespace Entity.EntityData
|
||||||
|
{
|
||||||
|
[Serializable]
|
||||||
|
public sealed class WeaponLanceParamsData
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 枪尖命中半径。
|
||||||
|
/// </summary>
|
||||||
|
public float HitRadius { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 武器模型前刺的位移距离。
|
||||||
|
/// </summary>
|
||||||
|
public float ThrustDistance { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 实际判定的前刺长度。
|
||||||
|
/// </summary>
|
||||||
|
public float PierceLength { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 判定起点相对武器当前位置的前置偏移。
|
||||||
|
/// </summary>
|
||||||
|
public float ForwardOffset { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 追踪目标时的转向速度。
|
||||||
|
/// </summary>
|
||||||
|
public float RotateSpeed { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 向前突刺阶段耗时。
|
||||||
|
/// </summary>
|
||||||
|
public float AttackDuration { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 收枪返回阶段耗时。
|
||||||
|
/// </summary>
|
||||||
|
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<WeaponLanceParamsData>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 4d1a821e8ee1a9a4b912b70b0a1616eb
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -304,11 +304,4 @@ namespace Entity.Weapon
|
||||||
public abstract void OnLeave();
|
public abstract void OnLeave();
|
||||||
public override string ToString() => State.ToString();
|
public override string ToString() => State.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -46,23 +46,16 @@ namespace Entity.Weapon
|
||||||
{
|
{
|
||||||
FaceTargetImmediately();
|
FaceTargetImmediately();
|
||||||
|
|
||||||
Vector3 fireOrigin = CachedTransform.TransformPoint(_fireOriginOffset);
|
if (!TryResolveAttackTarget(out TargetableObject targetable, out Vector3 hitPosition))
|
||||||
Vector3 fireDirection = CachedTransform.forward;
|
{
|
||||||
float maxDistance = Mathf.Max(0.1f, _weaponData.AttackRange);
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (Physics.Raycast(fireOrigin, fireDirection, out RaycastHit hit, maxDistance, _hitMask,
|
_attackEffect?.Play(this, hitPosition, targetable, 0f);
|
||||||
QueryTriggerInteraction.Collide))
|
|
||||||
{
|
|
||||||
TargetableObject targetable = hit.collider.GetComponentInParent<TargetableObject>();
|
|
||||||
if (targetable != null && targetable.Available && !targetable.IsDead)
|
|
||||||
{
|
|
||||||
_attackEffect?.Play(this, hit.point, targetable, 0f);
|
|
||||||
_isAttacking = true;
|
_isAttacking = true;
|
||||||
AIUtility.PerformCollision(targetable, this);
|
AIUtility.PerformCollision(targetable, this);
|
||||||
_isAttacking = false;
|
_isAttacking = false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Check()
|
protected override void Check()
|
||||||
{
|
{
|
||||||
|
|
@ -95,6 +88,40 @@ namespace Entity.Weapon
|
||||||
CachedTransform.rotation = Quaternion.LookRotation(directionToTarget.normalized, Vector3.up);
|
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<TargetableObject>();
|
||||||
|
if (raycastTarget == targetable)
|
||||||
|
{
|
||||||
|
hitPosition = hit.point;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
#region Lifecycle
|
#region Lifecycle
|
||||||
|
|
||||||
protected override bool OnWeaponShow(object userData)
|
protected override bool OnWeaponShow(object userData)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: aee5d5037e73e894cac11712e321b930
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -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()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: d9991ee189b733b4e9d40395357f5ef2
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -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()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 01edc8bb0ff46a14d8028e03af932b52
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -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()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 8009ad2c332a956438e3357ed5e30eb6
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -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()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 4c9e98f5381e579469dcdac7bf3e1e25
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -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<int> _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<TargetableObject>();
|
||||||
|
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<WeaponLanceData>(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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: f90612be7695ee549b39473c9b706122
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -92,14 +92,9 @@ namespace Procedure
|
||||||
GameEntry.Entity.HideEntity(entity.Id);
|
GameEntry.Entity.HideEntity(entity.Id);
|
||||||
}
|
}
|
||||||
|
|
||||||
var enemyProjectiles = GameEntry.Entity.GetEntityGroup("EnemyProjectile")?.GetAllEntities();
|
HideEntityGroup("Bullet");
|
||||||
if (enemyProjectiles != null)
|
HideEntityGroup("Projectile");
|
||||||
{
|
HideEntityGroup("EnemyProjectile");
|
||||||
foreach (var projectile in enemyProjectiles)
|
|
||||||
{
|
|
||||||
GameEntry.Entity.HideEntity(projectile.Id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnDestroy(IFsm<IProcedureManager> procedureOwner)
|
public override void OnDestroy(IFsm<IProcedureManager> procedureOwner)
|
||||||
|
|
@ -108,6 +103,21 @@ namespace Procedure
|
||||||
_procedureGame = null;
|
_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
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -104,18 +104,8 @@ namespace Simulation
|
||||||
|
|
||||||
private void PlayHitMarker(ProjectileHitPresentationEventArgs args)
|
private void PlayHitMarker(ProjectileHitPresentationEventArgs args)
|
||||||
{
|
{
|
||||||
EntityBase targetEntity = TryGetEntityById(args.TargetEntityId);
|
// Projectile hit markers were reusing the handgun marker effect and were
|
||||||
if (targetEntity == null || !targetEntity.Available)
|
// visually indistinguishable from handgun lock/hit feedback.
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PlayHitEffect(ProjectileHitPresentationEventArgs args)
|
private void PlayHitEffect(ProjectileHitPresentationEventArgs args)
|
||||||
|
|
|
||||||
|
|
@ -140,18 +140,6 @@ namespace UI
|
||||||
return;
|
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)
|
if (args.Force)
|
||||||
{
|
{
|
||||||
GameEntry.UIRouter.CloseUI(UIFormType.DisplayItemInfoForm);
|
GameEntry.UIRouter.CloseUI(UIFormType.DisplayItemInfoForm);
|
||||||
|
|
@ -159,10 +147,7 @@ namespace UI
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_locked && !IsCurrentFormSender(sender) && sender is not DisplayItem)
|
if (_locked && !args.Force) return;
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
GameEntry.UIRouter.CloseUI(UIFormType.DisplayItemInfoForm);
|
GameEntry.UIRouter.CloseUI(UIFormType.DisplayItemInfoForm);
|
||||||
_locked = false;
|
_locked = false;
|
||||||
|
|
|
||||||
|
|
@ -199,6 +199,12 @@ namespace UI
|
||||||
|
|
||||||
#region UI Methods
|
#region UI Methods
|
||||||
|
|
||||||
|
public override void CloseUI()
|
||||||
|
{
|
||||||
|
base.CloseUI();
|
||||||
|
GameEntry.Event.Fire(this, DisplayItemInfoHideEventArgs.Create(true));
|
||||||
|
}
|
||||||
|
|
||||||
public int? OpenUI(ShopFormRawData rawData)
|
public int? OpenUI(ShopFormRawData rawData)
|
||||||
{
|
{
|
||||||
ShopFormContext context = BuildContext(rawData);
|
ShopFormContext context = BuildContext(rawData);
|
||||||
|
|
|
||||||
|
|
@ -397,6 +397,8 @@ namespace UI
|
||||||
return new WeaponSlashData(entityId, ownerId, ownerCamp);
|
return new WeaponSlashData(entityId, ownerId, ownerCamp);
|
||||||
case WeaponType.WeaponLightning:
|
case WeaponType.WeaponLightning:
|
||||||
return new WeaponLightningData(entityId, ownerId, ownerCamp);
|
return new WeaponLightningData(entityId, ownerId, ownerCamp);
|
||||||
|
case WeaponType.WeaponLance:
|
||||||
|
return new WeaponLanceData(entityId, ownerId, ownerCamp);
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -199,7 +199,7 @@ namespace UI
|
||||||
|
|
||||||
public void OnCancelButtonClick()
|
public void OnCancelButtonClick()
|
||||||
{
|
{
|
||||||
GameEntry.Event.Fire(this, DisplayItemInfoHideEventArgs.Create());
|
GameEntry.Event.Fire(this, DisplayItemInfoHideEventArgs.Create(true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,16 +4,23 @@ using DataTable;
|
||||||
using Definition.DataStruct;
|
using Definition.DataStruct;
|
||||||
using Entity.EntityData;
|
using Entity.EntityData;
|
||||||
using Entity.Weapon;
|
using Entity.Weapon;
|
||||||
|
using System;
|
||||||
using UnityGameFramework.Runtime;
|
using UnityGameFramework.Runtime;
|
||||||
|
|
||||||
namespace CustomUtility
|
namespace CustomUtility
|
||||||
{
|
{
|
||||||
public static class ItemDescUtility
|
public static class ItemDescUtility
|
||||||
{
|
{
|
||||||
private static readonly Dictionary<string, string> _paramsDict = new()
|
private static readonly Dictionary<string, string> _paramsDict = new(StringComparer.OrdinalIgnoreCase)
|
||||||
{
|
{
|
||||||
{"hitradius", "伤害范围"},
|
{"hitRadius", "伤害范围"},
|
||||||
{"sectorangle", "攻击角度"}
|
{"sectorAngle", "攻击角度"},
|
||||||
|
{"pierceLength", "前戳距离"},
|
||||||
|
{"thrustDistance", "枪尖长度"},
|
||||||
|
{"forwardOffset", "前置偏移"},
|
||||||
|
{"rotateSpeed", "转向速度"},
|
||||||
|
{"attackDuration", "突刺时长"},
|
||||||
|
{"returnDuration", "收枪时长"}
|
||||||
};
|
};
|
||||||
|
|
||||||
public static string CreatePropDescription(StatModifier[] modifiers)
|
public static string CreatePropDescription(StatModifier[] modifiers)
|
||||||
|
|
@ -89,6 +96,11 @@ namespace CustomUtility
|
||||||
sb.Append(modifiersDesc);
|
sb.Append(modifiersDesc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (@params == null || @params.Count == 0)
|
||||||
|
{
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var kvp in @params)
|
foreach (var kvp in @params)
|
||||||
{
|
{
|
||||||
if (!_paramsDict.TryGetValue(kvp.Key, out string value))
|
if (!_paramsDict.TryGetValue(kvp.Key, out string value))
|
||||||
|
|
|
||||||
|
|
@ -731,7 +731,7 @@ PrefabInstance:
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 11499388, guid: adb3eb1c35fcff14f89fba7b05c9d71c, type: 3}
|
- target: {fileID: 11499388, guid: adb3eb1c35fcff14f89fba7b05c9d71c, type: 3}
|
||||||
propertyPath: m_EditorResourceMode
|
propertyPath: m_EditorResourceMode
|
||||||
value: 0
|
value: 1
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 11499388, guid: adb3eb1c35fcff14f89fba7b05c9d71c, type: 3}
|
- target: {fileID: 11499388, guid: adb3eb1c35fcff14f89fba7b05c9d71c, type: 3}
|
||||||
propertyPath: m_JsonHelperTypeName
|
propertyPath: m_JsonHelperTypeName
|
||||||
|
|
|
||||||
Binary file not shown.
Binary file not shown.
BIN
数据表/Goods.xlsx
BIN
数据表/Goods.xlsx
Binary file not shown.
Loading…
Reference in New Issue