Merge remote-tracking branch 'origin/develop' into feature/Addessable_CDN

This commit is contained in:
CuongNV
2026-05-13 10:48:39 +07:00
69 changed files with 66482 additions and 658 deletions
@@ -285,6 +285,11 @@ MonoBehaviour:
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 47e6c4feb83f4494ebe7d862483ca89e
m_Address: "gfx/\u4EBA\u7269/\u6280\u80FD/\u6B66\u4FA0/\u9738\u738B\u65AD\u5CB3\u9884\u5907.gfx"
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 48582ea91cdc6ab4a95e1b58797d046b
m_Address: "gfx/\u7B56\u5212\u8054\u5165/\u4EBA\u7269\u6280\u80FD/\u51FB\u4E2D/\u72EE\u5B50\u543C\u51FB\u4E2D.gfx"
m_ReadOnly: 0
@@ -515,6 +520,11 @@ MonoBehaviour:
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 77a6e958f81eaa944b9bbed7fbbb1603
m_Address: "gfx/\u4EBA\u7269/\u6280\u80FD/\u6B66\u4FA0/\u9738\u738B\u66B4\u6012\u9884\u5907.gfx"
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 7887d4c9101722741b42a2a2392a6ada
m_Address: "gfx/\u7A0B\u5E8F\u8054\u5165/\u88C5\u5907\u5B9D\u77F3\u9576\u5D4C/\u767D\u8272\u80F8\u75321\u7EA7.gfx"
m_ReadOnly: 0
@@ -900,6 +910,11 @@ MonoBehaviour:
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: e177087afce72de419bc651787c342d4
m_Address: "gfx/\u4EBA\u7269/\u6280\u80FD/\u6B66\u4FA0/\u9738\u738B\u65AD\u5CB3\u65BD\u653E.gfx"
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: e2aad3a6b5254724bace8867b7bf5cce
m_Address: "gfx/\u7B56\u5212\u8054\u5165/\u72B6\u6001\u6548\u679C/\u5B9A\u8EAB.gfx"
m_ReadOnly: 0
@@ -940,6 +955,11 @@ MonoBehaviour:
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: f6712134b0daeab49ab9ada508269f1c
m_Address: "gfx/\u4EBA\u7269/\u6280\u80FD/\u6B66\u4FA0/\u9738\u738B\u66B4\u6012\u9884\u59071.gfx"
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: f7afdff4d28a54f4487905be81edc8a9
m_Address: "gfx/\u7A0B\u5E8F\u8054\u5165/\u51FB\u4E2D/\u9738\u738B\u732E\u9F0E.gfx"
m_ReadOnly: 0
@@ -0,0 +1,209 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 8
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: "\u8840\u96FE2"
m_Shader: {fileID: 4800000, guid: 0a016a83287664641b867743f19faf14, type: 3}
m_Parent: {fileID: 0}
m_ModifiedSerializedProperties: 0
m_ValidKeywords:
- _DISSOLVETEXUVS_NORMAL
- _DISTORTTEXUVS_NORMAL
- _MAINTEXUVS_NORMAL
- _MASKTEXUVS_NORMAL
m_InvalidKeywords:
- _DISSOLVETEXAR_ON
- _DISTORTTEXAR_ON
- _MASKTEXAR_ON
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap: {}
disabledShaderPasses:
- MOTIONVECTORS
m_LockedProperties:
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- _BaseMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _BumpMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailAlbedoMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailMask:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailNormalMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DissolveTex:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DistortTex:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _EmissionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 2800000, guid: 6df8da3ee3e96df44915bdc952b46254, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MaskTex:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MetallicGlossMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _OcclusionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _ParallaxMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _SpecGlossMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- unity_Lightmaps:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- unity_LightmapsInd:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- unity_ShadowMasks:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Ints: []
m_Floats:
- _AddPrecomputedVelocity: 0
- _AlphaClip: 0
- _AlphaCutoff: 0.5
- _AlphaToMask: 0
- _Blend: 0
- _BlendMode: 1
- _BlendModePreserveSpecular: 1
- _BumpScale: 1
- _ClearCoatMask: 0
- _ClearCoatSmoothness: 0
- _Cull: 2
- _CullMode: 0
- _CustomDissolve: 0
- _CustomMainTex: 0
- _Cutoff: 0.5
- _DepthFade: 1
- _DetailAlbedoMapScale: 1
- _DetailNormalMapScale: 1
- _DissolveFactor: 0
- _DissolveSoft: 0.1
- _DissolveTexAR: 1
- _DissolveTexClampU: 0
- _DissolveTexClampV: 0
- _DissolveTexRotate: 0
- _DissolveTexUSpeed: 0
- _DissolveTexUVS: 0
- _DissolveTexVSpeed: 0
- _DissolveWide: 0.05
- _DistortDissolveTex: 0
- _DistortFactor: 0
- _DistortMainTex: 0
- _DistortMaskTex: 0
- _DistortTexAR: 1
- _DistortTexClampU: 0
- _DistortTexClampV: 0
- _DistortTexRotate: 0
- _DistortTexUSpeed: 0
- _DistortTexUVS: 0
- _DistortTexVSpeed: 0
- _Dst: 1
- _DstBlend: 0
- _DstBlendAlpha: 0
- _EnvironmentReflections: 1
- _FDepth: 0
- _FDissolveTex: 0
- _FDistortTex: 0
- _FFnl: 0
- _FMaskTex: 0
- _FnlPower: 1
- _FnlScale: 0
- _GlossMapScale: 0
- _Glossiness: 0
- _GlossyReflections: 0
- _MainAlpha: 0.5
- _MainTexAR: 0
- _MainTexClampU: 0
- _MainTexClampV: 0
- _MainTexRotate: 0
- _MainTexUSpeed: 0
- _MainTexUVS: 0
- _MainTexVSpeed: 0
- _MaskTexAR: 1
- _MaskTexClampU: 0
- _MaskTexClampV: 0
- _MaskTexRotate: 0
- _MaskTexUSpeed: 0
- _MaskTexUVS: 0
- _MaskTexVSpeed: 0
- _Metallic: 0
- _OcclusionStrength: 1
- _Parallax: 0.005
- _QueueOffset: 0
- _ReFnl: 0
- _ReceiveShadows: 1
- _Scr: 1
- _Smoothness: 0.5
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1
- _SrcBlendAlpha: 1
- _Surface: 0
- _WorkflowMode: 1
- _ZWrite: 1
m_Colors:
- _BaseColor: {r: 1, g: 1, b: 1, a: 1}
- _Color: {r: 1, g: 1, b: 1, a: 1}
- _DissolveColor: {r: 1, g: 1, b: 1, a: 1}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
- _FnlColor: {r: 1, g: 1, b: 1, a: 1}
- _MainColor: {r: 2, g: 2, b: 2, a: 1}
- _SpecColor: {r: 0.2, g: 0.2, b: 0.2, a: 1}
m_BuildTextureStacks: []
m_AllowLocking: 1
--- !u!114 &8741123340869993700
MonoBehaviour:
m_ObjectHideFlags: 11
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3}
m_Name:
m_EditorClassIdentifier:
version: 9
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: a793ccccbe99e2e4ba4b265f9d0d7d0c
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 2100000
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.
@@ -0,0 +1,107 @@
fileFormatVersion: 2
guid: fccf64069712ca94fbfd28e787e835ce
ModelImporter:
serializedVersion: 22200
internalIDToNameTable: []
externalObjects: {}
materials:
materialImportMode: 2
materialName: 0
materialSearch: 1
materialLocation: 1
animations:
legacyGenerateAnimations: 4
bakeSimulation: 0
resampleCurves: 1
optimizeGameObjects: 0
removeConstantScaleCurves: 0
motionNodeName:
animationImportErrors:
animationImportWarnings:
animationRetargetingWarnings:
animationDoRetargetingWarnings: 0
importAnimatedCustomProperties: 0
importConstraints: 0
animationCompression: 1
animationRotationError: 0.5
animationPositionError: 0.5
animationScaleError: 0.5
animationWrapMode: 0
extraExposedTransformPaths: []
extraUserProperties: []
clipAnimations: []
isReadable: 0
meshes:
lODScreenPercentages: []
globalScale: 1
meshCompression: 0
addColliders: 0
useSRGBMaterialColor: 1
sortHierarchyByName: 1
importPhysicalCameras: 1
importVisibility: 1
importBlendShapes: 1
importCameras: 1
importLights: 1
nodeNameCollisionStrategy: 1
fileIdsGeneration: 2
swapUVChannels: 0
generateSecondaryUV: 0
useFileUnits: 1
keepQuads: 0
weldVertices: 1
bakeAxisConversion: 0
preserveHierarchy: 0
skinWeightsMode: 0
maxBonesPerVertex: 4
minBoneWeight: 0.001
optimizeBones: 1
meshOptimizationFlags: -1
indexFormat: 0
secondaryUVAngleDistortion: 8
secondaryUVAreaDistortion: 15.000001
secondaryUVHardAngle: 88
secondaryUVMarginMethod: 1
secondaryUVMinLightmapResolution: 40
secondaryUVMinObjectScale: 1
secondaryUVPackMargin: 4
useFileScale: 1
strictVertexDataChecks: 0
tangentSpace:
normalSmoothAngle: 60
normalImportMode: 0
tangentImportMode: 3
normalCalculationMode: 4
legacyComputeAllNormalsFromSmoothingGroupsWhenMeshHasBlendShapes: 0
blendShapeNormalImportMode: 1
normalSmoothingSource: 0
referencedClips: []
importAnimation: 1
humanDescription:
serializedVersion: 3
human: []
skeleton: []
armTwist: 0.5
foreArmTwist: 0.5
upperLegTwist: 0.5
legTwist: 0.5
armStretch: 0.05
legStretch: 0.05
feetSpacing: 0
globalScale: 1
rootMotionBoneName:
hasTranslationDoF: 0
hasExtraRoot: 0
skeletonHasParents: 1
lastHumanDescriptionAvatarSource: {instanceID: 0}
autoGenerateAvatarMappingIfUnspecified: 1
animationType: 2
humanoidOversampling: 1
avatarSetup: 0
addHumanoidExtraRootOnlyWhenUsingAvatar: 1
importBlendShapeDeformPercent: 1
remapMaterialsIfMaterialImportModeIsNone: 0
additionalBone: 0
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,21 @@
fileFormatVersion: 2
guid: 6df8da3ee3e96df44915bdc952b46254
IHVImageFormatImporter:
externalObjects: {}
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 0
wrapV: 0
wrapW: 0
isReadable: 0
sRGBTexture: 1
streamingMipmaps: 0
streamingMipmapsPriority: 0
ignoreMipmapLimit: 0
mipmapLimitGroupName:
userData:
assetBundleName:
assetBundleVariant:
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: e177087afce72de419bc651787c342d4
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 47e6c4feb83f4494ebe7d862483ca89e
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 77a6e958f81eaa944b9bbed7fbbb1603
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: f6712134b0daeab49ab9ada508269f1c
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: da26e4066a8a74045b324d5939f84fae
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,210 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &-9125591884435407841
MonoBehaviour:
m_ObjectHideFlags: 11
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3}
m_Name:
m_EditorClassIdentifier:
version: 10
--- !u!21 &2100000
Material:
serializedVersion: 8
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: trail012_clamp
m_Shader: {fileID: 4800000, guid: 0a016a83287664641b867743f19faf14, type: 3}
m_Parent: {fileID: 0}
m_ModifiedSerializedProperties: 0
m_ValidKeywords:
- _DISSOLVETEXUVS_NORMAL
- _DISTORTTEXUVS_NORMAL
- _MAINTEXUVS_NORMAL
- _MASKTEXUVS_NORMAL
m_InvalidKeywords:
- _CUSTOMMAINTEX_ON
- _DISSOLVETEXAR_ON
- _DISTORTTEXAR_ON
- _MASKTEXAR_ON
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap: {}
disabledShaderPasses:
- MOTIONVECTORS
m_LockedProperties:
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- _BaseMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _BumpMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailAlbedoMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailMask:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailNormalMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DissolveTex:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DistortTex:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _EmissionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 2800000, guid: f296ce99babd3364ea800e15e7efa080, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MaskTex:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MetallicGlossMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _OcclusionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _ParallaxMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _SpecGlossMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- unity_Lightmaps:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- unity_LightmapsInd:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- unity_ShadowMasks:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Ints: []
m_Floats:
- _AddPrecomputedVelocity: 0
- _AlphaClip: 0
- _AlphaCutoff: 0.5
- _AlphaToMask: 0
- _Blend: 0
- _BlendMode: 1
- _BlendModePreserveSpecular: 1
- _BumpScale: 1
- _ClearCoatMask: 0
- _ClearCoatSmoothness: 0
- _Cull: 2
- _CullMode: 0
- _CustomDissolve: 0
- _CustomMainTex: 1
- _Cutoff: 0.5
- _DepthFade: 1
- _DetailAlbedoMapScale: 1
- _DetailNormalMapScale: 1
- _DissolveFactor: 0
- _DissolveSoft: 0.1
- _DissolveTexAR: 1
- _DissolveTexClampU: 0
- _DissolveTexClampV: 0
- _DissolveTexRotate: 0
- _DissolveTexUSpeed: 0
- _DissolveTexUVS: 0
- _DissolveTexVSpeed: 0
- _DissolveWide: 0.05
- _DistortDissolveTex: 0
- _DistortFactor: 0
- _DistortMainTex: 0
- _DistortMaskTex: 0
- _DistortTexAR: 1
- _DistortTexClampU: 0
- _DistortTexClampV: 0
- _DistortTexRotate: 0
- _DistortTexUSpeed: 0
- _DistortTexUVS: 0
- _DistortTexVSpeed: 0
- _Dst: 1
- _DstBlend: 0
- _DstBlendAlpha: 0
- _EnvironmentReflections: 1
- _FDepth: 0
- _FDissolveTex: 0
- _FDistortTex: 0
- _FFnl: 0
- _FMaskTex: 0
- _FnlPower: 1
- _FnlScale: 0
- _GlossMapScale: 0
- _Glossiness: 0
- _GlossyReflections: 0
- _MainAlpha: 1
- _MainTexAR: 0
- _MainTexClampU: 0
- _MainTexClampV: 0
- _MainTexRotate: 0
- _MainTexUSpeed: 0
- _MainTexUVS: 0
- _MainTexVSpeed: 0
- _MaskTexAR: 1
- _MaskTexClampU: 0
- _MaskTexClampV: 0
- _MaskTexRotate: 0
- _MaskTexUSpeed: 0
- _MaskTexUVS: 0
- _MaskTexVSpeed: 0
- _Metallic: 0
- _OcclusionStrength: 1
- _Parallax: 0.005
- _QueueOffset: 0
- _ReFnl: 0
- _ReceiveShadows: 1
- _Scr: 1
- _Smoothness: 0.5
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1
- _SrcBlendAlpha: 1
- _Surface: 0
- _WorkflowMode: 1
- _ZWrite: 1
m_Colors:
- _BaseColor: {r: 1, g: 1, b: 1, a: 1}
- _Color: {r: 1, g: 1, b: 1, a: 1}
- _DissolveColor: {r: 1, g: 1, b: 1, a: 1}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
- _FnlColor: {r: 1, g: 1, b: 1, a: 1}
- _MainColor: {r: 1, g: 1, b: 1, a: 1}
- _SpecColor: {r: 0.19999996, g: 0.19999996, b: 0.19999996, a: 1}
m_BuildTextureStacks: []
m_AllowLocking: 1
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: a26bcf269d08a484e9258128a24da667
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 2100000
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 11717a108c8cc3a44a4210df59ff1d49
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,209 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &-6650086867172505828
MonoBehaviour:
m_ObjectHideFlags: 11
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3}
m_Name:
m_EditorClassIdentifier:
version: 10
--- !u!21 &2100000
Material:
serializedVersion: 8
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: "\u4E94\u4F53\u7B26\u91CA\u653E"
m_Shader: {fileID: 4800000, guid: 0a016a83287664641b867743f19faf14, type: 3}
m_Parent: {fileID: 0}
m_ModifiedSerializedProperties: 0
m_ValidKeywords:
- _DISSOLVETEXUVS_NORMAL
- _DISTORTTEXUVS_NORMAL
- _MAINTEXUVS_NORMAL
- _MASKTEXUVS_NORMAL
m_InvalidKeywords:
- _DISSOLVETEXAR_ON
- _DISTORTTEXAR_ON
- _MASKTEXAR_ON
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap: {}
disabledShaderPasses:
- MOTIONVECTORS
m_LockedProperties:
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- _BaseMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _BumpMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailAlbedoMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailMask:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailNormalMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DissolveTex:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DistortTex:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _EmissionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 2800000, guid: af21047088feebe46972adf29984e3cc, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MaskTex:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MetallicGlossMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _OcclusionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _ParallaxMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _SpecGlossMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- unity_Lightmaps:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- unity_LightmapsInd:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- unity_ShadowMasks:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Ints: []
m_Floats:
- _AddPrecomputedVelocity: 0
- _AlphaClip: 0
- _AlphaCutoff: 0.5
- _AlphaToMask: 0
- _Blend: 0
- _BlendMode: 1
- _BlendModePreserveSpecular: 1
- _BumpScale: 1
- _ClearCoatMask: 0
- _ClearCoatSmoothness: 0
- _Cull: 2
- _CullMode: 0
- _CustomDissolve: 0
- _CustomMainTex: 0
- _Cutoff: 0.5
- _DepthFade: 1
- _DetailAlbedoMapScale: 1
- _DetailNormalMapScale: 1
- _DissolveFactor: 0
- _DissolveSoft: 0.1
- _DissolveTexAR: 1
- _DissolveTexClampU: 0
- _DissolveTexClampV: 0
- _DissolveTexRotate: 0
- _DissolveTexUSpeed: 0
- _DissolveTexUVS: 0
- _DissolveTexVSpeed: 0
- _DissolveWide: 0.05
- _DistortDissolveTex: 0
- _DistortFactor: 0
- _DistortMainTex: 0
- _DistortMaskTex: 0
- _DistortTexAR: 1
- _DistortTexClampU: 0
- _DistortTexClampV: 0
- _DistortTexRotate: 0
- _DistortTexUSpeed: 0
- _DistortTexUVS: 0
- _DistortTexVSpeed: 0
- _Dst: 1
- _DstBlend: 0
- _DstBlendAlpha: 0
- _EnvironmentReflections: 1
- _FDepth: 0
- _FDissolveTex: 0
- _FDistortTex: 0
- _FFnl: 0
- _FMaskTex: 0
- _FnlPower: 1
- _FnlScale: 0
- _GlossMapScale: 0
- _Glossiness: 0
- _GlossyReflections: 0
- _MainAlpha: 1
- _MainTexAR: 0
- _MainTexClampU: 0
- _MainTexClampV: 0
- _MainTexRotate: 270
- _MainTexUSpeed: 0
- _MainTexUVS: 0
- _MainTexVSpeed: 0
- _MaskTexAR: 1
- _MaskTexClampU: 0
- _MaskTexClampV: 0
- _MaskTexRotate: 0
- _MaskTexUSpeed: 0
- _MaskTexUVS: 0
- _MaskTexVSpeed: 0
- _Metallic: 0
- _OcclusionStrength: 1
- _Parallax: 0.005
- _QueueOffset: 0
- _ReFnl: 0
- _ReceiveShadows: 1
- _Scr: 1
- _Smoothness: 0.5
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1
- _SrcBlendAlpha: 1
- _Surface: 0
- _WorkflowMode: 1
- _ZWrite: 1
m_Colors:
- _BaseColor: {r: 1, g: 1, b: 1, a: 1}
- _Color: {r: 1, g: 1, b: 1, a: 1}
- _DissolveColor: {r: 1, g: 1, b: 1, a: 1}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
- _FnlColor: {r: 1, g: 1, b: 1, a: 1}
- _MainColor: {r: 1, g: 1, b: 1, a: 1}
- _SpecColor: {r: 0.19999996, g: 0.19999996, b: 0.19999996, a: 1}
m_BuildTextureStacks: []
m_AllowLocking: 1
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 45a63d0bb9112ed45802dca4835b63c0
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 2100000
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,21 @@
fileFormatVersion: 2
guid: f296ce99babd3364ea800e15e7efa080
IHVImageFormatImporter:
externalObjects: {}
textureSettings:
serializedVersion: 2
filterMode: 0
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 0
wrapW: 0
isReadable: 0
sRGBTexture: 1
streamingMipmaps: 0
streamingMipmapsPriority: 0
ignoreMipmapLimit: 0
mipmapLimitGroupName:
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,21 @@
fileFormatVersion: 2
guid: af21047088feebe46972adf29984e3cc
IHVImageFormatImporter:
externalObjects: {}
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 0
wrapV: 0
wrapW: 0
isReadable: 0
sRGBTexture: 1
streamingMipmaps: 0
streamingMipmapsPriority: 0
ignoreMipmapLimit: 0
mipmapLimitGroupName:
userData:
assetBundleName:
assetBundleVariant:
@@ -127,6 +127,8 @@ namespace ModelViewer.Common
public int m_nMinLoops;
public int m_nMaxLoops;
public bool IsInfinite() { return m_nMinLoops == -1 || m_nMaxLoops == -1; }
public int CalcLoopNum() { return IsInfinite() ? -1 : Random.Range(m_nMinLoops, m_nMaxLoops); }
public bool Load(FileStream fileStream, StreamReader file, uint dwVersion)
{
bool isBinary = fileStream != null;
@@ -174,6 +176,21 @@ namespace ModelViewer.Common
}
}
public class ACTIONDYN_DATA
{
private int m_nLoopNum;
ACTION_INFO m_pInfo;
public ACTIONDYN_DATA(int nLoopNum = 0, ACTION_INFO pInfo = null)
{
m_nLoopNum = nLoopNum;
m_pInfo = pInfo;
}
public int GetLoopNum() { return m_nLoopNum; }
public ACTION_INFO GetActInfo() { return m_pInfo; }
public int GetTimeSpan() { return 1/*m_pInfo.GetTimeSpan()*/; }
public int GetTotalTime() { return GetLoopNum() * GetTimeSpan(); }
}
[System.Serializable]
public class EVENT_INFO
{
@@ -487,7 +504,7 @@ namespace ModelViewer.Common
public string m_strName;
public int m_nLoops;
public bool IsLooping()
{
if (m_ActLst.Count == 0)
@@ -0,0 +1,442 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &1543847492617740573
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 6334829773751692483}
- component: {fileID: 6547720173392539073}
- component: {fileID: 8536791987006931629}
- component: {fileID: 4134555565657198633}
- component: {fileID: 2552605511170143642}
- component: {fileID: 1692684095153756201}
m_Layer: 0
m_Name: DamageText
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &6334829773751692483
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1543847492617740573}
m_LocalRotation: {x: 0.5536698, y: -0.42243594, z: -0.38702753, w: -0.60432386}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 8480017899206466389}
m_Father: {fileID: 8147088653703454787}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 0, y: 9000}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0, y: 1}
--- !u!23 &6547720173392539073
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1543847492617740573}
m_Enabled: 1
m_CastShadows: 0
m_ReceiveShadows: 0
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RayTraceProcedural: 0
m_RayTracingAccelStructBuildFlagsOverride: 0
m_RayTracingAccelStructBuildFlags: 1
m_SmallMeshCulling: 1
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, 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!114 &8536791987006931629
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1543847492617740573}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 9541d86e2fd84c1d9990edf0852d74ab, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_text: asdasd123123123213213123
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
m_fontColor32:
serializedVersion: 2
rgba: 4294967295
m_fontColor: {r: 1, g: 1, b: 1, a: 1}
m_enableVertexGradient: 0
m_colorMode: 3
m_fontColorGradient:
topLeft: {r: 1, g: 1, b: 1, a: 1}
topRight: {r: 1, g: 1, b: 1, a: 1}
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
bottomRight: {r: 1, g: 1, b: 1, a: 1}
m_fontColorGradientPreset: {fileID: 0}
m_spriteAsset: {fileID: 0}
m_tintAllSprites: 0
m_StyleSheet: {fileID: 0}
m_TextStyleHashCode: -1183493901
m_overrideHtmlColors: 0
m_faceColor:
serializedVersion: 2
rgba: 4294967295
m_fontSize: 2
m_fontSizeBase: 2
m_fontWeight: 400
m_enableAutoSizing: 0
m_fontSizeMin: 18
m_fontSizeMax: 72
m_fontStyle: 0
m_HorizontalAlignment: 1
m_VerticalAlignment: 512
m_textAlignment: 65535
m_characterSpacing: 0
m_wordSpacing: 0
m_lineSpacing: 0
m_lineSpacingMax: 0
m_paragraphSpacing: 0
m_charWidthMaxAdj: 0
m_TextWrappingMode: 0
m_wordWrappingRatios: 0.4
m_overflowMode: 0
m_linkedTextComponent: {fileID: 0}
parentLinkedComponent: {fileID: 0}
m_enableKerning: 0
m_ActiveFontFeatures: 6e72656b
m_enableExtraPadding: 0
checkPaddingRequired: 0
m_isRichText: 1
m_EmojiFallbackSupport: 1
m_parseCtrlCharacters: 1
m_isOrthographic: 0
m_isCullingEnabled: 0
m_horizontalMapping: 0
m_verticalMapping: 0
m_uvLineOffset: 0
m_geometrySortingOrder: 0
m_IsTextObjectScaleStatic: 0
m_VertexBufferAutoSizeReduction: 0
m_useMaxVisibleDescender: 1
m_pageToDisplay: 1
m_margin: {x: 0, y: 0, z: 0, w: 0}
m_isUsingLegacyAnimationComponent: 0
m_isVolumetricText: 0
_SortingLayer: 0
_SortingLayerID: 0
_SortingOrder: 0
m_hasFontAssetChanged: 0
m_renderer: {fileID: 6547720173392539073}
m_maskType: 0
--- !u!114 &4134555565657198633
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1543847492617740573}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 1a05efb08a5fbef42b3e8414040b6c33, type: 3}
m_Name:
m_EditorClassIdentifier:
targetCamera: {fileID: 0}
mode: 0
--- !u!114 &2552605511170143642
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1543847492617740573}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 0515aed5525ee47d4b5249804a555471, type: 3}
m_Name:
m_EditorClassIdentifier:
text: {fileID: 8536791987006931629}
ingameIcon: {fileID: 3067997925100767011}
--- !u!114 &1692684095153756201
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1543847492617740573}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 3245ec927659c4140ac4f8d17403cc18, type: 3}
m_Name:
m_EditorClassIdentifier:
m_HorizontalFit: 1
m_VerticalFit: 1
--- !u!1 &2762109714019950995
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 8480017899206466389}
- component: {fileID: 3067997925100767011}
m_Layer: 0
m_Name: Square
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &8480017899206466389
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2762109714019950995}
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: []
m_Father: {fileID: 6334829773751692483}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 1}
m_AnchorMax: {x: 0, y: 1}
m_AnchoredPosition: {x: -0.2, y: -0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!212 &3067997925100767011
SpriteRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2762109714019950995}
m_Enabled: 1
m_CastShadows: 0
m_ReceiveShadows: 0
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 0
m_RayTraceProcedural: 0
m_RayTracingAccelStructBuildFlagsOverride: 0
m_RayTracingAccelStructBuildFlags: 1
m_SmallMeshCulling: 1
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 2100000, guid: 9dfc825aed78fcd4ba02077103263b40, 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: 0
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_Sprite: {fileID: 21300000, guid: 0a2f50f2fe381024996b30c94befd165, type: 3}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_FlipX: 0
m_FlipY: 0
m_DrawMode: 0
m_Size: {x: 1, y: 1}
m_AdaptiveModeThreshold: 0.5
m_SpriteTileMode: 0
m_WasSpriteAssigned: 1
m_MaskInteraction: 0
m_SpriteSortPoint: 0
--- !u!1 &6052681567744256686
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 8147088653703454787}
- component: {fileID: 992389339466371540}
- component: {fileID: 6488498381958245340}
- component: {fileID: 4526882482662561821}
- component: {fileID: 3112717333377324765}
m_Layer: 0
m_Name: NPC Manager
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &8147088653703454787
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6052681567744256686}
serializedVersion: 2
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 741.23157, y: -3.0202653, z: 153.50998}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 6334829773751692483}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &992389339466371540
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6052681567744256686}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 87558530baa52164fbafe0b6dc828de0, type: 3}
m_Name:
m_EditorClassIdentifier:
modelPlayerCharacter: {fileID: 0}
--- !u!114 &6488498381958245340
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6052681567744256686}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 92009c5b4b0fd894790865cf674545fa, type: 3}
m_Name:
m_EditorClassIdentifier:
skillStateActionConfig: {fileID: 11400000, guid: 7a26a1c8cf0cc58478b7baa61913020d, type: 2}
m_AttackList: []
--- !u!114 &4526882482662561821
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6052681567744256686}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: c410036615d7e2f4fb76258c665dc6ee, type: 3}
m_Name:
m_EditorClassIdentifier:
modelNPCList:
- {fileID: 6990335153834195374, guid: 28a9794edd04941a6ba1ab1a6e87bbd4, type: 3}
- {fileID: 4093304155662634189, guid: 70f8fa699f9ed4f88b1c335f2ccbb198, type: 3}
- {fileID: 6811279203144701007, guid: 64b5a0083181a4d30911efb9c3059678, type: 3}
- {fileID: 437287848253420420, guid: 6be116f35d3d446c7b8d3d61ca617690, type: 3}
- {fileID: 1737665070947335222, guid: 7cc56a2fa301a46db92681b17c10d6b0, type: 3}
- {fileID: 1816778744457515645, guid: 4dcc3634bebc24bebb88a7ba3e23753c, type: 3}
- {fileID: 4601171410544804222, guid: bc0279413de8f43fb899a8761a22f4f3, type: 3}
- {fileID: 8898003383210139779, guid: a32fc20843e62442ab1494d8a8e48794, type: 3}
- {fileID: 9064255407888235132, guid: 39e34e0b093c74c65a24bcfa1a655c51, type: 3}
- {fileID: 2903211823832813862, guid: ed84be8c5044746ca895fb75aca9bc66, type: 3}
- {fileID: 287010356842850335, guid: 09a50785f77bc43369476f9ab93a9b3a, type: 3}
- {fileID: 8599254418566033129, guid: 04e8f383637dd42a58a6a23c48c64eb5, type: 3}
- {fileID: 7945738885635973730, guid: 19ef711ad91474765a847a631f5da9ca, type: 3}
- {fileID: 8995620757399750888, guid: 03e5dab5f51374e55904db72229b775e, type: 3}
- {fileID: 5605758169409286178, guid: d865ad4bc902a4a299da74aaba68e9eb, type: 3}
- {fileID: 2657305733640386924, guid: d14e87db729e843a4b31c7b1065ab677, type: 3}
- {fileID: 5676130487765305938, guid: 62555210fd2944f329f43aa25b44d2c4, type: 3}
- {fileID: 4681428346907282479, guid: 47002ca46d55c4938b9315f763d1d66c, type: 3}
- {fileID: 7585364034339110012, guid: b058f8968d5aa4a8f9285fa891b7b9ba, type: 3}
- {fileID: 4491434428197274843, guid: 46453b542df6540ae817c89b1dfff21e, type: 3}
- {fileID: 5062117593937043970, guid: b2aa264cdbd9d4fb18f8df100175f4c3, type: 3}
- {fileID: 8373977607867880534, guid: fd4b330a3588f40a18d44e22798e3ddc, type: 3}
- {fileID: 4118378869440003053, guid: 6858c050d424a416a9a6aed20d93a150, type: 3}
- {fileID: 7231649790395308121, guid: 12e232ba9bff147e3bc0cc208f8b78a0, type: 3}
- {fileID: 2539724145744991562, guid: 0fb08f2ce83384471ac95b41dc602ace, type: 3}
- {fileID: 3742448964403956444, guid: a5922b6b6f63f46e7b047300c07948fa, type: 3}
- {fileID: 919132149155446097, guid: 91928ba4c1a3643b98bfadeb477ec8af, type: 3}
- {fileID: 1821586701514404843, guid: 3e3944509a65042eb8a31cfb74a0edf5, type: 3}
- {fileID: 4373439416244800714, guid: 5e76cb69b081a4673a5816fd9da89533, type: 3}
- {fileID: 6763320176570713132, guid: 576e84b3fd877477eb7f0a424f30d5df, type: 3}
- {fileID: 5552012344809293004, guid: 7daa10b47beb04798927c05cc7148951, type: 3}
- {fileID: 2358403188266590158, guid: c9c25f71f361f43f1aa0510d4f96312d, type: 3}
npcFolder: {fileID: 102900000, guid: 2193743d8dcc4db4792272c0a62fb72d, type: 3}
--- !u!114 &3112717333377324765
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6052681567744256686}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 8635fe618431341d796413e99407c5fc, type: 3}
m_Name:
m_EditorClassIdentifier:
floatTextIconPrefab: {fileID: 2552605511170143642}
poolSize: 20
offset: {x: 0, y: 2, z: 0}
riseDistance: 1.5
riseDuration: 0.8
staggerIntervalSeconds: 0.3
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 598017775c842ef4ab72d8eabe909d6c
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -69,7 +69,7 @@ TextureImporter:
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 4096
maxTextureSize: 8192
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
@@ -106,6 +106,32 @@ TextureImporter:
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: VisionOS
maxTextureSize: 4096
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: iOS
maxTextureSize: 4096
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites:
+2 -2
View File
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:98acfc6d78af21396b1c3dcadcb4387954e34ff5863aa8a628f4011b26888168
size 313916
oid sha256:5caea7b0b45c434cbea3545800922c7604e8773fe7cbcf675b091934c7c39505
size 306512
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 51ffa1643315ae94f8efced3044b5d68
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,127 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 922bd889af2211b488dc6019c1022191, type: 3}
m_Name: skill_state_action
m_EditorClassIdentifier:
entries:
- skill: 2244
state: 117
beHitAction: "\u88AB\u51FB\u5012_\u901A\u7528"
stayDownAction: "\u762B\u75EA_\u901A\u7528"
- skill: 2245
state: 117
beHitAction: "\u88AB\u51FB\u5012_\u901A\u7528"
stayDownAction: "\u762B\u75EA_\u901A\u7528"
- skill: 2236
state: 117
beHitAction: "\u88AB\u51FB\u5012_\u901A\u7528"
stayDownAction: "\u762B\u75EA_\u901A\u7528"
- skill: 2237
state: 117
beHitAction: "\u88AB\u51FB\u5012_\u901A\u7528"
stayDownAction: "\u762B\u75EA_\u901A\u7528"
- skill: 2374
state: 117
beHitAction: "\u88AB\u6311\u8D77_\u901A\u7528"
stayDownAction: "\u762B\u75EA_\u901A\u7528"
- skill: 2375
state: 117
beHitAction: "\u88AB\u6311\u8D77_\u901A\u7528"
stayDownAction: "\u762B\u75EA_\u901A\u7528"
- skill: 2554
state: 117
beHitAction: "\u88AB\u6311\u8D77_\u901A\u7528"
stayDownAction: "\u762B\u75EA_\u901A\u7528"
- skill: 2568
state: 117
beHitAction: "\u88AB\u6311\u8D77_\u901A\u7528"
stayDownAction: "\u88AB\u51FB\u5012_\u901A\u7528"
- skill: 2558
state: 117
beHitAction: "\u88AB\u51FB\u5012_\u901A\u7528"
stayDownAction: "\u762B\u75EA_\u901A\u7528"
- skill: 2557
state: 117
beHitAction: "\u88AB\u51FB\u5012_\u901A\u7528"
stayDownAction: "\u762B\u75EA_\u901A\u7528"
- skill: 2551
state: 117
beHitAction: "\u88AB\u51FB\u5012_\u901A\u7528"
stayDownAction: "\u762B\u75EA_\u901A\u7528"
- skill: 2742
state: 117
beHitAction: "\u88AB\u6311\u8D77_\u901A\u7528"
stayDownAction: "\u762B\u75EA_\u901A\u7528"
- skill: 2743
state: 117
beHitAction: "\u88AB\u6311\u8D77_\u901A\u7528"
stayDownAction: "\u762B\u75EA_\u901A\u7528"
- skill: 2768
state: 117
beHitAction: "\u88AB\u6311\u8D77_\u901A\u7528"
stayDownAction: "\u88AB\u51FB\u5012_\u901A\u7528"
- skill: 2769
state: 117
beHitAction: "\u88AB\u6311\u8D77_\u901A\u7528"
stayDownAction: "\u88AB\u51FB\u5012_\u901A\u7528"
- skill: 2750
state: 117
beHitAction: "\u88AB\u51FB\u5012_\u901A\u7528"
stayDownAction: "\u762B\u75EA_\u901A\u7528"
- skill: 2751
state: 117
beHitAction: "\u88AB\u51FB\u5012_\u901A\u7528"
stayDownAction: "\u762B\u75EA_\u901A\u7528"
- skill: 2748
state: 117
beHitAction: "\u88AB\u51FB\u5012_\u901A\u7528"
stayDownAction: "\u762B\u75EA_\u901A\u7528"
- skill: 2749
state: 117
beHitAction: "\u88AB\u51FB\u5012_\u901A\u7528"
stayDownAction: "\u762B\u75EA_\u901A\u7528"
- skill: 2736
state: 117
beHitAction: "\u88AB\u51FB\u5012_\u901A\u7528"
stayDownAction: "\u762B\u75EA_\u901A\u7528"
- skill: 2737
state: 117
beHitAction: "\u88AB\u51FB\u5012_\u901A\u7528"
stayDownAction: "\u762B\u75EA_\u901A\u7528"
- skill: 2905
state: 117
beHitAction: "\u88AB\u51FB\u5012_\u901A\u7528"
stayDownAction: "\u762B\u75EA_\u901A\u7528"
- skill: 2906
state: 117
beHitAction: "\u88AB\u51FB\u5012_\u901A\u7528"
stayDownAction: "\u762B\u75EA_\u901A\u7528"
- skill: 3284
state: 117
beHitAction: "\u88AB\u51FB\u5012_\u901A\u7528"
stayDownAction: "\u762B\u75EA_\u901A\u7528"
- skill: 3285
state: 117
beHitAction: "\u88AB\u51FB\u5012_\u901A\u7528"
stayDownAction: "\u762B\u75EA_\u901A\u7528"
- skill: 3286
state: 117
beHitAction: "\u88AB\u6311\u8D77_\u901A\u7528"
stayDownAction: "\u762B\u75EA_\u901A\u7528"
- skill: 3287
state: 117
beHitAction: "\u88AB\u6311\u8D77_\u901A\u7528"
stayDownAction: "\u762B\u75EA_\u901A\u7528"
- skill: 3212
state: 117
beHitAction: "\u88AB\u51FB\u5012_\u901A\u7528"
stayDownAction: "\u762B\u75EA_\u901A\u7528"
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 7a26a1c8cf0cc58478b7baa61913020d
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:
+8
View File
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 7e810e737f9dbd34c91dc8ea77c0caad
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 45f90f4f1beb54142ab4507a13118e9b
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,237 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using BrewMonster.Config;
using UnityEditor;
using UnityEngine;
namespace BrewMonster.Config.Editor
{
public static class SkillStateActionConfigImporter
{
private const string MenuRoot = "PerfectWorld/Skill State Action/";
[MenuItem(MenuRoot + "Import TXT Into New Asset…")]
public static void ImportTxtIntoNewAsset()
{
string txtPath = EditorUtility.OpenFilePanel("Import skill_state_action.txt", "", "txt");
if (string.IsNullOrEmpty(txtPath))
return;
string text;
try
{
text = ReadAllTextLegacyPwConfig(txtPath);
}
catch (IOException ex)
{
EditorUtility.DisplayDialog("Import failed", $"Could not read file:\n{ex.Message}", "OK");
return;
}
if (!ValidateImportedTxtSource(txtPath, text))
return;
var warnings = new List<string>();
List<SkillStateActionRow> rows = SkillStateActionTextParser.Parse(text, warnings);
LogWarnings(warnings);
NotifyIfZeroRows(rows.Count);
string assetPath = EditorUtility.SaveFilePanelInProject(
"Save Skill State Action Config",
"skill_state_action",
"asset",
"Choose asset path under Assets/");
if (string.IsNullOrEmpty(assetPath))
return;
var asset = ScriptableObject.CreateInstance<SkillStateActionConfig>();
AssetDatabase.CreateAsset(asset, assetPath);
WriteSerializedEntries(asset, rows);
EditorUtility.SetDirty(asset);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
EditorUtility.FocusProjectWindow();
Selection.activeObject = asset;
Debug.Log($"SkillStateActionConfigImporter: wrote {rows.Count} rows to {assetPath}");
}
[MenuItem(MenuRoot + "Import TXT Into Selected Asset…", true)]
public static bool ImportTxtIntoSelectedValidate()
{
return Selection.activeObject is SkillStateActionConfig;
}
[MenuItem(MenuRoot + "Import TXT Into Selected Asset…")]
public static void ImportTxtIntoSelected()
{
if (!(Selection.activeObject is SkillStateActionConfig cfg))
return;
string txtPath = EditorUtility.OpenFilePanel("Import skill_state_action.txt", "", "txt");
if (string.IsNullOrEmpty(txtPath))
return;
string text;
try
{
text = ReadAllTextLegacyPwConfig(txtPath);
}
catch (IOException ex)
{
EditorUtility.DisplayDialog("Import failed", $"Could not read file:\n{ex.Message}", "OK");
return;
}
if (!ValidateImportedTxtSource(txtPath, text))
return;
var warnings = new List<string>();
List<SkillStateActionRow> rows = SkillStateActionTextParser.Parse(text, warnings);
LogWarnings(warnings);
NotifyIfZeroRows(rows.Count);
Undo.RecordObject(cfg, "Import Skill State Action");
WriteSerializedEntries(cfg, rows);
EditorUtility.SetDirty(cfg);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
Debug.Log($"SkillStateActionConfigImporter: replaced {rows.Count} rows on {AssetDatabase.GetAssetPath(cfg)}");
}
/// <summary>
/// PW client configs are often GBK (Windows code page 936). Reading those bytes as UTF-8 produces mojibake ( / gibberish).
/// After optional UTF-8 BOM: decode as strict UTF-8; if invalid, use GBK — consistent with OctetsStream / globaldataman.
/// </summary>
private static string ReadAllTextLegacyPwConfig(string path)
{
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
byte[] bytes = File.ReadAllBytes(path);
int start = 0;
if (bytes.Length >= 3 && bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF)
start = 3;
int len = bytes.Length - start;
if (len <= 0)
return string.Empty;
try
{
var utf8Strict = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true);
return utf8Strict.GetString(bytes, start, len);
}
catch (DecoderFallbackException)
{
return Encoding.GetEncoding(936).GetString(bytes, start, len);
}
}
/// <summary>
/// Writes list via SerializedProperty so Unity persists nested structs reliably (Inspector shows Size &gt; 0).
/// </summary>
private static void WriteSerializedEntries(SkillStateActionConfig cfg, List<SkillStateActionRow> rows)
{
SerializedObject so = new SerializedObject(cfg);
SerializedProperty entriesProp = so.FindProperty("entries");
if (entriesProp == null)
{
Debug.LogError("SkillStateActionConfigImporter: serialized field 'entries' not found — check SkillStateActionConfig.");
return;
}
entriesProp.ClearArray();
int n = rows?.Count ?? 0;
entriesProp.arraySize = n;
for (int i = 0; i < n; i++)
{
SerializedProperty elem = entriesProp.GetArrayElementAtIndex(i);
SkillStateActionRow r = rows[i];
elem.FindPropertyRelative("skill").intValue = r.skill;
elem.FindPropertyRelative("state").intValue = r.state;
elem.FindPropertyRelative("beHitAction").stringValue = r.beHitAction ?? string.Empty;
elem.FindPropertyRelative("stayDownAction").stringValue = r.stayDownAction ?? string.Empty;
}
so.ApplyModifiedProperties();
}
/// <summary>
/// Ensure the user picked gameplay config text (skill_state_action.txt), not a Unity YAML .asset/.meta.
/// </summary>
private static bool ValidateImportedTxtSource(string path, string text)
{
string ext = Path.GetExtension(path);
if (ext.Equals(".asset", StringComparison.OrdinalIgnoreCase) ||
ext.Equals(".meta", StringComparison.OrdinalIgnoreCase))
{
EditorUtility.DisplayDialog(
"Wrong file — pick skill_state_action.txt",
"You selected a Unity project file (" + ext + "), not the classic PW config.\n\n" +
"Use the plain text table exported from the game/client:\n" +
" skill_state_action.txt\n\n" +
"Each line looks like:\n" +
" skillId,stateId,beHitAction[,stayDownAction]\n\n" +
"Do not choose skill_state_action.asset (that is the ScriptableObject we fill).",
"OK");
return false;
}
if (string.IsNullOrEmpty(text))
{
EditorUtility.DisplayDialog("Import failed", "The chosen file is empty.", "OK");
return false;
}
string head = text.Length <= 2048 ? text : text.Substring(0, 2048);
string trimmedHead = head.TrimStart('\uFEFF', ' ', '\t', '\r', '\n');
if (trimmedHead.StartsWith("%YAML", StringComparison.Ordinal))
{
EditorUtility.DisplayDialog(
"Wrong file — this is Unity YAML",
"The file begins with %YAML (Unity serialized asset).\n\n" +
"Select skill_state_action.txt instead — the comma-separated gameplay table — not .asset or scene YAML.",
"OK");
return false;
}
if (head.IndexOf("m_Script:", StringComparison.Ordinal) >= 0 &&
head.IndexOf("fileID:", StringComparison.Ordinal) >= 0)
{
EditorUtility.DisplayDialog(
"Wrong file — Unity ScriptableObject YAML",
"This content looks like a Unity .asset (m_Script / fileID).\n\n" +
"You must pick skill_state_action.txt (plain rows: skillId,stateId,...).\n\n" +
"Tip: copy skill_state_action.txt from client configs or Assets/Resources if you still keep it there.",
"OK");
return false;
}
return true;
}
private static void NotifyIfZeroRows(int count)
{
if (count != 0)
return;
EditorUtility.DisplayDialog(
"Skill State Action import",
"Parsed 0 rows.\n\n" +
"If you meant to import rows, check that you chose skill_state_action.txt, not .asset.\n\n" +
"Open the Console for line warnings.\n\n" +
"Expected per line:\n" +
" skillId,stateId,beHitAction[,stayDownAction]\n" +
"or the same columns separated by TAB.\n\n" +
"First two columns must be integers.",
"OK");
}
private static void LogWarnings(List<string> warnings)
{
if (warnings == null || warnings.Count == 0)
return;
foreach (string w in warnings)
Debug.LogWarning($"SkillStateActionConfigImporter: {w}");
}
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: a33fc0453d431914d9015eb9f0d89a63
@@ -0,0 +1,115 @@
using System;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
namespace BrewMonster.Config
{
/// <summary>One row of skill_state_action.txt: skill id, visible state id, be-hit action, optional stay-down action.</summary>
[Serializable]
public struct SkillStateActionRow
{
public int skill;
public int state;
public string beHitAction;
public string stayDownAction;
}
/// <summary>Parses the classic comma-separated skill_state_action table (same rules as legacy client / CECAttacksMan TextAsset loader).</summary>
public static class SkillStateActionTextParser
{
/// <summary>
/// Strip CSV-style wrapping quotes (Excel export often writes "2244","117",...).
/// Handles doubled-quote escapes inside a quoted field.
/// </summary>
private static string UnquoteCsvField(string raw)
{
if (string.IsNullOrEmpty(raw))
return string.Empty;
string s = raw.Trim().TrimStart('\uFEFF');
while (s.Length >= 2 && s[0] == '"' && s[s.Length - 1] == '"')
{
s = s.Substring(1, s.Length - 2).Replace("\"\"", "\"").Trim();
}
// Odd exports / naive splits can leave stray " on one side.
s = s.Trim('"').Trim();
return s;
}
public static List<SkillStateActionRow> Parse(string text, ICollection<string> warnings = null)
{
var rows = new List<SkillStateActionRow>();
if (string.IsNullOrEmpty(text))
return rows;
// Saved-as-UTF-8-with-BOM breaks int.TryParse on the first column of line 1 (\ufeff123,...).
text = text.TrimStart('\uFEFF');
using (var reader = new StringReader(text))
{
string line;
int lineNum = 0;
while ((line = reader.ReadLine()) != null)
{
lineNum++;
string trimmed = line.TrimStart('\uFEFF').Trim();
if (trimmed.Length == 0 || trimmed.StartsWith("//") || trimmed.StartsWith("#"))
continue;
string[] v = trimmed.Split(',');
// Some configs use tabs instead of commas.
if (v.Length < 3)
v = trimmed.Split('\t');
if (v.Length < 3)
{
warnings?.Add($"Line {lineNum}: need at least 3 comma-separated fields");
continue;
}
string s0 = UnquoteCsvField(v[0]);
string s1 = UnquoteCsvField(v[1]);
if (!int.TryParse(s0, System.Globalization.NumberStyles.Integer,
System.Globalization.CultureInfo.InvariantCulture, out int skillId) ||
!int.TryParse(s1, System.Globalization.NumberStyles.Integer,
System.Globalization.CultureInfo.InvariantCulture, out int stateId))
{
warnings?.Add($"Line {lineNum}: invalid skill or state id (got \"{s0}\", \"{s1}\")");
continue;
}
string beHit = UnquoteCsvField(v[2]);
string stayDown = v.Length > 3 ? UnquoteCsvField(v[3]) : string.Empty;
rows.Add(new SkillStateActionRow
{
skill = skillId,
state = stateId,
beHitAction = beHit,
stayDownAction = stayDown
});
}
}
return rows;
}
}
[CreateAssetMenu(fileName = "skill_state_action", menuName = "PerfectWorld/Skill State Action Config")]
public class SkillStateActionConfig : ScriptableObject
{
[SerializeField] private List<SkillStateActionRow> entries = new List<SkillStateActionRow>();
public IReadOnlyList<SkillStateActionRow> Entries => entries;
#if UNITY_EDITOR
/// <summary>Editor / tools: replace serialized rows after import.</summary>
public void SetEntries(List<SkillStateActionRow> newEntries)
{
entries = newEntries ?? new List<SkillStateActionRow>();
}
#endif
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 922bd889af2211b488dc6019c1022191
@@ -18,4 +18,4 @@ namespace BrewMonster
public GameObject NpcServerPrefab => npcServerPrefab.gameObject;
public GameObject TestVfxPrefab => testVfxPrefab;
}
}
}
@@ -7,9 +7,9 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using ModelRenderer.Scripts.Common;
using BrewMonster.Scripts;
using BrewMonster.Config;
using UnityEngine;
using Cysharp.Threading.Tasks;
@@ -17,6 +17,18 @@ namespace BrewMonster
{
public class CECAttacksMan : MonoSingleton<CECAttacksMan>
{
[SerializeField] private SkillStateActionConfig skillStateActionConfig;
private struct SkillStateActionEntry
{
public int skill;
public int state;
public string beHitAction;
public string stayDownAction;
}
private readonly List<SkillStateActionEntry> m_SkillStateActionVec = new List<SkillStateActionEntry>();
private LinkedList<CECAttackEvent> m_targets = new LinkedList<CECAttackEvent>();
public CECMultiSectionSkillMan m_pMultiSkillGfxComposerMan;
protected A3DSkillGfxComposerMan m_pSkillGfxComposerMan;
@@ -27,16 +39,20 @@ namespace BrewMonster
{
base.Awake();
}
protected override void OnDestroy()
{
m_targets = null;
m_SkillStateActionVec.Clear();
SkillGfxMan.InstanceSub.Dispose();
base.OnDestroy();
}
private void Start()
{
StartLoad();
}
private async void StartLoad()
{
SetupAttacksMan();
@@ -50,7 +66,6 @@ namespace BrewMonster
}
LoadAllSkillGfxAsync();
}
/// <summary>
@@ -74,7 +89,8 @@ namespace BrewMonster
(string flyGFXPath, string hitGrdGFXPath, string hitGFXPath) = ElementSkill.GetAllGFX(skillId);
// Pass skillStub to LoadOneComposerAsync / 将技能存根传递给LoadOneComposerAsync
bool loaded = await m_pSkillGfxComposerMan.LoadOneComposerAsync((int)skillId, skillStub, flyGFXPath, hitGrdGFXPath, hitGFXPath);
bool loaded = await m_pSkillGfxComposerMan.LoadOneComposerAsync((int)skillId, skillStub, flyGFXPath,
hitGrdGFXPath, hitGFXPath);
if (!loaded)
{
BMLogger.LogWarning($"CECAttacksMan::LoadSkillGfxOnDemand() - Failed to load GFX for skill {skillId}");
@@ -106,7 +122,8 @@ namespace BrewMonster
SkillStub skillStub = SkillStub.GetStub(idSkill);
if (skillStub == null)
{
BMLogger.LogWarning($"CECAttacksMan::LoadAllSkillGfxAsync() - SkillStub not found for skill {idSkill}");
BMLogger.LogWarning(
$"CECAttacksMan::LoadAllSkillGfxAsync() - SkillStub not found for skill {idSkill}");
failedCount++;
continue;
}
@@ -115,7 +132,8 @@ namespace BrewMonster
// Use await instead of blocking .Result to prevent freezing
// Pass skillStub to LoadOneComposerAsync / 将技能存根传递给LoadOneComposerAsync
bool loaded = await m_pSkillGfxComposerMan.LoadOneComposerAsync((int)idSkill, skillStub, flyGFXPath, hitGrdGFXPath, hitGFXPath);
bool loaded = await m_pSkillGfxComposerMan.LoadOneComposerAsync((int)idSkill, skillStub, flyGFXPath,
hitGrdGFXPath, hitGFXPath);
if (loaded)
loadedCount++;
else
@@ -128,20 +146,20 @@ namespace BrewMonster
}
}
BMLogger.Log($"CECAttacksMan::LoadAllSkillGfxAsync() - Complete. Loaded: {loadedCount}, Failed: {failedCount}");
BMLogger.Log(
$"CECAttacksMan::LoadAllSkillGfxAsync() - Complete. Loaded: {loadedCount}, Failed: {failedCount}");
//TODO: convert this part
/* char szMultiSectionFile[MAX_PATH] = { 0 };
strcpy(szMultiSectionFile, "configs\\multi_section_skill.txt");
m_pMultiSkillGfxComposerMan = new CECMultiSectionSkillMan();
if (!m_pMultiSkillGfxComposerMan || !m_pMultiSkillGfxComposerMan->LoadConfig(szMultiSectionFile))
{
a_LogOutput(1, "CECAttacksMan::CECAttacksMan(), failed to load multi skill sgc config file [%s]", szMultiSectionFile);
}
m_pMultiSkillGfxComposerMan = new CECMultiSectionSkillMan();
if (m_pMultiSkillGfxComposerMan == null || !m_pMultiSkillGfxComposerMan.LoadConfig("multi_section_skill"))
{
BMLogger.LogError("CECAttacksMan::CECAttacksMan(), failed to load multi skill sgc config file ");
}
strcpy(szMultiSectionFile, "configs\\skill_state_action.txt");
if (!LoadSkillStateActionConfig(szMultiSectionFile))
a_LogOutput(1, "CECAttacksMan::CECAttacksMan(), failed to load multi skill action config file [%s]", szMultiSectionFile);*/
if (!LoadSkillStateActionConfig())
BMLogger.LogError(
"CECAttacksMan::LoadSkillStateActionConfig(), failed — assign Skill State Action Config on CECAttacksMan.");
}
public void SetupAttacksMan()
{
m_pSkillGfxComposerMan = new A3DSkillGfxComposerMan();
@@ -149,6 +167,62 @@ namespace BrewMonster
uint idSkill = 0;
}
/// <summary>
/// Loads skill/state → action names into <see cref="m_SkillStateActionVec"/> from <see cref="skillStateActionConfig"/> (parity with C++ <c>CECAttacksMan::LoadSkillStateActionConfig</c>).
/// </summary>
public bool LoadSkillStateActionConfig()
{
m_SkillStateActionVec.Clear();
SkillStateActionConfig cfg = skillStateActionConfig;
if (cfg == null)
{
BMLogger.LogWarning(
"CECAttacksMan::LoadSkillStateActionConfig(), skillStateActionConfig is not assigned on CECAttacksMan.");
return false;
}
IReadOnlyList<SkillStateActionRow> rows = cfg.Entries;
if (rows == null || rows.Count == 0)
{
BMLogger.LogWarning("CECAttacksMan::LoadSkillStateActionConfig(), config has no entries.");
return false;
}
for (int i = 0; i < rows.Count; i++)
{
SkillStateActionRow r = rows[i];
m_SkillStateActionVec.Add(new SkillStateActionEntry
{
skill = r.skill,
state = r.state,
beHitAction = r.beHitAction ?? string.Empty,
stayDownAction = r.stayDownAction ?? string.Empty
});
}
return true;
}
public bool GetSkillStateActionName(int skill, int state, out string name1, out string name2)
{
name1 = string.Empty;
name2 = string.Empty;
for (int i = 0; i < m_SkillStateActionVec.Count; i++)
{
SkillStateActionEntry e = m_SkillStateActionVec[i];
if (e.skill == skill && e.state == state)
{
name1 = e.beHitAction ?? string.Empty;
name2 = e.stayDownAction ?? string.Empty;
return true;
}
}
return false;
}
private void Update()
{
uint dwDeltaTime = (uint)(Time.deltaTime * 1000);
@@ -168,6 +242,7 @@ namespace BrewMonster
{
node.Value.Tick(dwDeltaTime);
}
node = next;
}
@@ -206,6 +281,7 @@ namespace BrewMonster
//BMLogger.LogError($"[SKILL_GFX_DEBUG] OnDrawGizmos: Drawing {gizmoCount} gizmo(s)");
}
}
SkillGfxGizmoDrawer.DrawGizmos();
}
@@ -225,6 +301,7 @@ namespace BrewMonster
string fullPath = Path.Combine(Application.streamingAssetsPath, relativePath);
return System.IO.File.Exists(fullPath);
}
public CECAttackerEvents FindAttackByAttacker(int idHost)
{
CECAttackerEvents result = new CECAttackerEvents();
@@ -240,30 +317,33 @@ namespace BrewMonster
return result;
}
public CECAttackEvent AddMeleeAttack(int idHost, int idTarget, int idWeapon, uint dwModifier, int nDamage, int nTimeFly = 10)
public CECAttackEvent AddMeleeAttack(int idHost, int idTarget, int idWeapon, uint dwModifier, int nDamage,
int nTimeFly = 10)
{
var newEvent = new CECAttackEvent(
this,
idHost,
0, // idCastTarget
idTarget,
idWeapon,
0, // idSkill
0, // nSkillLevel
dwModifier,
nDamage,
200, // timeToBeFired
nTimeFly // timeToDoDamage
);
this,
idHost,
0, // idCastTarget
idTarget,
idWeapon,
0, // idSkill
0, // nSkillLevel
dwModifier,
nDamage,
200, // timeToBeFired
nTimeFly // timeToDoDamage
);
m_targets.AddLast(newEvent);
newEvent.UpdateTargetFlag();
return m_targets.Last.Value;
}
public A3DSkillGfxComposerMan GetSkillGfxComposerMan()
{
return m_pSkillGfxComposerMan;
}
public bool GetSkillSectionActionSuffix(int skill, int section, out string suffix)
{
// TODO: Implement multi-section skill logic
@@ -277,12 +357,14 @@ namespace BrewMonster
return true;
}
}
suffix = null;
return false;
}
public CECAttackEvent AddSkillAttack(int idHost, int idCastTarget, int idTarget, int idWeapon, int idSkill, int nSkillLevel, uint dwModifier, int nDamage)
{
public CECAttackEvent AddSkillAttack(int idHost, int idCastTarget, int idTarget, int idWeapon, int idSkill,
int nSkillLevel, uint dwModifier, int nDamage)
{
var newEvent = new CECAttackEvent(
this,
idHost,
@@ -293,8 +375,8 @@ namespace BrewMonster
nSkillLevel,
dwModifier,
nDamage,
200, // timeToBeFired
1000 // timeToDoDamage
200, // timeToBeFired
1000 // timeToDoDamage
);
m_targets.AddLast(newEvent);
#if UNITY_EDITOR
@@ -311,16 +393,15 @@ namespace BrewMonster
{
m_targets.AddLast(evt);
}
}
public class TARGET_DATA
{
public int idTarget;
public uint dwModifier;
public int nDamage;
}
/// <summary>
/// Manager for multi-section skills
/// 多段技能管理器
@@ -334,10 +415,10 @@ namespace BrewMonster
[Serializable]
public class SectionInfo
{
public int skill_id; // 技能ID / Skill ID
public byte section; // 段号 / Section number
public string action_suffix; // 动作后缀 / Action suffix
public A3DSkillGfxComposer pComposer; // 技能特效组合器 / Skill GFX composer
public int skill_id; // 技能ID / Skill ID
public byte section; // 段号 / Section number
public string action_suffix; // 动作后缀 / Action suffix
public A3DSkillGfxComposer pComposer; // 技能特效组合器 / Skill GFX composer
public SectionInfo()
{
@@ -349,7 +430,8 @@ namespace BrewMonster
}
// 用于多段技能的sgc映射 / Map for multi-section skill SGC files
private readonly Dictionary<string, A3DSkillGfxComposer> m_SgcName2ComposerMap = new Dictionary<string, A3DSkillGfxComposer>();
private readonly Dictionary<string, A3DSkillGfxComposer> m_SgcName2ComposerMap =
new Dictionary<string, A3DSkillGfxComposer>();
// 多段技能组合器列表 / Multi-section skill composer list
private readonly List<SectionInfo> m_MultiSectionSkillComposerVec = new List<SectionInfo>();
@@ -357,6 +439,7 @@ namespace BrewMonster
public CECMultiSectionSkillMan()
{
}
~CECMultiSectionSkillMan()
{
Release();
@@ -424,16 +507,19 @@ namespace BrewMonster
/// <param name="Targets">Target data list / 目标数据列表</param>
/// <param name="bIsGoblinSkill">Is goblin skill / 是否为精灵技能</param>
public void Play(int nSkillID, int section, int nHostID, int nCastTargetID,
List<TARGET_DATA> Targets, bool bIsGoblinSkill = false)
List<TARGET_DATA> Targets, bool bIsGoblinSkill = false)
{
BMLogger.Log($"[SKILL_GFX_FLOW] >>> CECMultiSectionSkillMan.Play called | SkillID: {nSkillID}, Section: {section}, HostID: {nHostID}, CastTargetID: {nCastTargetID}, Targets: {Targets?.Count ?? 0}, IsGoblin: {bIsGoblinSkill}");
BMLogger.Log($"[SKILL_GFX_FLOW] >>> Searching through {m_MultiSectionSkillComposerVec.Count} multi-section skill entries");
BMLogger.Log(
$"[SKILL_GFX_FLOW] >>> CECMultiSectionSkillMan.Play called | SkillID: {nSkillID}, Section: {section}, HostID: {nHostID}, CastTargetID: {nCastTargetID}, Targets: {Targets?.Count ?? 0}, IsGoblin: {bIsGoblinSkill}");
BMLogger.Log(
$"[SKILL_GFX_FLOW] >>> Searching through {m_MultiSectionSkillComposerVec.Count} multi-section skill entries");
foreach (var info in m_MultiSectionSkillComposerVec)
{
if (nSkillID == info.skill_id && section == info.section && info.pComposer != null)
{
BMLogger.Log($"[SKILL_GFX_FLOW] >>> Found matching multi-section skill composer! | ActionSuffix: {info.action_suffix}");
BMLogger.Log(
$"[SKILL_GFX_FLOW] >>> Found matching multi-section skill composer! | ActionSuffix: {info.action_suffix}");
BMLogger.Log($"[SKILL_GFX_FLOW] >>> Calling multi-section composer.Play");
info.pComposer.Play(nHostID, nCastTargetID, Targets, bIsGoblinSkill);
@@ -443,7 +529,8 @@ namespace BrewMonster
}
}
BMLogger.LogWarning($"[SKILL_GFX_FLOW] >>> No matching multi-section skill composer found for SkillID: {nSkillID}, Section: {section}");
BMLogger.LogWarning(
$"[SKILL_GFX_FLOW] >>> No matching multi-section skill composer found for SkillID: {nSkillID}, Section: {section}");
}
/// <summary>
@@ -462,6 +549,7 @@ namespace BrewMonster
return info.pComposer;
}
}
return null;
}
@@ -481,13 +569,14 @@ namespace BrewMonster
return info;
}
}
return null;
}
}
public partial class A3DSkillGfxComposer
{
public uint m_dwFlyTime; // 飞行时间 / Fly time in milliseconds
public uint m_dwFlyTime; // 飞行时间 / Fly time in milliseconds
private bool m_bTraceTarget;
GfxCluster m_FlyCluster;
GFX_SKILL_PARAM m_param;
@@ -563,27 +652,37 @@ namespace BrewMonster
/// 从文件加载组合器
/// </summary>
public string hitGfxName;
public string flyGfxName;
public string hitGrdGfxName;
public async UniTask<bool> Load(SkillStub skillStub, string flyGFXPath, string hitGrdGFXPath, string hitGFXPath)
{
flyGfxName = flyGFXPath;
hitGfxName = hitGFXPath;
hitGrdGfxName = hitGrdGFXPath;
m_szFlyGfx = string.IsNullOrEmpty(flyGfxName) ? null : await AddressableManager.Instance.LoadPrefabAsync("gfx/" + flyGfxName);
m_szHitGfx = string.IsNullOrEmpty(hitGfxName) ? null : await AddressableManager.Instance.LoadPrefabAsync("gfx/" + hitGfxName);
m_szHitGrndGfx = string.IsNullOrEmpty(hitGrdGfxName) ? null : await AddressableManager.Instance.LoadPrefabAsync("gfx/" + hitGrdGfxName);
m_szFlyGfx = string.IsNullOrEmpty(flyGfxName)
? null
: await AddressableManager.Instance.LoadPrefabAsync("gfx/" + flyGfxName);
m_szHitGfx = string.IsNullOrEmpty(hitGfxName)
? null
: await AddressableManager.Instance.LoadPrefabAsync("gfx/" + hitGfxName);
m_szHitGrndGfx = string.IsNullOrEmpty(hitGrdGfxName)
? null
: await AddressableManager.Instance.LoadPrefabAsync("gfx/" + hitGrdGfxName);
// BMLogger.LogError("HoangDev: Load A3DSkillGfxComposer GFX name: " + hitGfxName);
if (m_szFlyGfx == null && !string.IsNullOrEmpty(flyGfxName))
{
m_szFlyGfx = Resources.Load<GameObject>("GFX/" + "PlaceHolder");
}
if (m_szHitGfx == null && !string.IsNullOrEmpty(hitGfxName))
{
m_szHitGfx = Resources.Load<GameObject>("GFX/" + "PlaceHolder");
}
if (m_szHitGrndGfx == null && !string.IsNullOrEmpty(hitGrdGfxName))
{
m_szHitGrndGfx = Resources.Load<GameObject>("GFX/" + "PlaceHolder");
@@ -647,6 +746,7 @@ namespace BrewMonster
return true;
}
// SpawnGFX temp hack REMOVED — GFX spawning now handled by CECSkillGfxEvent state machine
// SpawnGFX临时代码已删除 — GFX生成现在由CECSkillGfxEvent状态机处理
/// <summary>
@@ -687,7 +787,8 @@ namespace BrewMonster
}
else
{
BMLogger.LogWarning($"[SKILL_GFX_DEBUG] Composer.Play: Target {tar.idTarget} is destroyed, skipping");
BMLogger.LogWarning(
$"[SKILL_GFX_DEBUG] Composer.Play: Target {tar.idTarget} is destroyed, skipping");
}
}
@@ -716,7 +817,8 @@ namespace BrewMonster
// 在添加前验证施法目标是否存在
if (!ValidateTargetExists(nCastTargetID))
{
BMLogger.LogWarning($"[SKILL_GFX_DEBUG] Composer.Play: Cast target {nCastTargetID} is destroyed, skipping");
BMLogger.LogWarning(
$"[SKILL_GFX_DEBUG] Composer.Play: Cast target {nCastTargetID} is destroyed, skipping");
return;
}
@@ -726,7 +828,6 @@ namespace BrewMonster
AddOneTarget(nCastTargetID, nHostID, szFly, szHit, tar, false, bIsGoblinSkill);
}
}
/// <summary>
@@ -765,8 +866,10 @@ namespace BrewMonster
return false;
}
}
return false;
}
public void AddOneTarget(
int nCastTargetID,
int nHostID,
@@ -812,6 +915,7 @@ namespace BrewMonster
{
szFly = null;
}
if (m_AttHitMode == GfxAttackMode.enumAttArea)
{
szHit = null;
@@ -843,10 +947,10 @@ namespace BrewMonster
bIsGoblinSkill,
bReverse
);
}
}
}
[Serializable]
public class CECAttackEvent
{
@@ -873,11 +977,13 @@ public class CECAttackEvent
#if UNITY_EDITOR
int debugCounter = 0; // Debug counter to track Tick calls
#endif
public CECAttackEvent() { }
public CECAttackEvent()
{
}
public CECAttackEvent(CECAttacksMan? pManager, int idHost, int idCastTarget, int idTarget,
int idWeapon, int idSkill, int nSkillLevel, uint dwModifier,
int nDamage, int nTimeToBeFired, int nTimeToDoDamage)
int idWeapon, int idSkill, int nSkillLevel, uint dwModifier,
int nDamage, int nTimeToBeFired, int nTimeToDoDamage)
{
m_pManager = pManager;
m_idHost = idHost;
@@ -894,6 +1000,7 @@ public class CECAttackEvent
AddTarget(idTarget, dwModifier, nDamage);
}
public bool Tick(uint dwDeltaTime)
{
m_timeLived += dwDeltaTime;
@@ -939,14 +1046,18 @@ public class CECAttackEvent
return true;
}
public void SetSkillSection(int nSection) { m_nSkillSection = nSection; }
public void SetSkillSection(int nSection)
{
m_nSkillSection = nSection;
}
bool DoFire()
{
m_bDoFired = true;
if (GPDataTypeHelper.ISPLAYERID(m_idHost))
{
if (m_idSkill != 0)
{
A3DSkillGfxComposer pComposer = null;
@@ -988,14 +1099,16 @@ public class CECAttackEvent
}
}
if (pComposer != null && pComposer.m_dwFlyTime == 0) // 技能gfx没有飞行实际,则马上头顶冒字 / Skill has no fly time, show damage immediately
if (pComposer != null &&
pComposer.m_dwFlyTime == 0) // 技能gfx没有飞行实际,则马上头顶冒字 / Skill has no fly time, show damage immediately
{
m_timeToDoDamage = 1;
}
else
{
// now we estimated a time to do damage / 现在估算伤害时间
if (m_targets.Count > 0 && GetPosByID(m_idHost, out Vector3 vecHost) && GetPosByID(m_targets[0].idTarget, out Vector3 vecTarget))
if (m_targets.Count > 0 && GetPosByID(m_idHost, out Vector3 vecHost) &&
GetPosByID(m_targets[0].idTarget, out Vector3 vecTarget))
{
float distance = (vecHost - vecTarget).magnitude;
m_timeToDoDamage = (uint)Mathf.Max(distance / 20.0f * 1000.0f, 10.0f);
@@ -1004,7 +1117,6 @@ public class CECAttackEvent
{
}
}
}
else if (m_idWeapon != 0)
{
@@ -1014,7 +1126,8 @@ public class CECAttackEvent
// using weapon gfx / 使用武器特效
DATA_TYPE dt = DATA_TYPE.DT_INVALID;
var pData = ElementDataManProvider.GetElementDataMan().get_data_ptr((uint)m_idWeapon, ID_SPACE.ID_SPACE_ESSENCE, ref dt);
var pData = ElementDataManProvider.GetElementDataMan()
.get_data_ptr((uint)m_idWeapon, ID_SPACE.ID_SPACE_ESSENCE, ref dt);
if (dt == DATA_TYPE.DT_PROJECTILE_ESSENCE)
{
@@ -1028,14 +1141,16 @@ public class CECAttackEvent
szHitGFX = ByteToStringUtils.ByteArrayToCP936String(pProjectile.file_hitgfx);
BMLogger.Log($"{ByteToStringUtils.UshortArrayToUnicodeString(pProjectile.name)} Use hit effect: {szHitGFX}");
BMLogger.Log(
$"{ByteToStringUtils.UshortArrayToUnicodeString(pProjectile.name)} Use hit effect: {szHitGFX}");
}
else if (dt == DATA_TYPE.DT_WEAPON_ESSENCE)
{
// 近程物理攻击,使用武器的效果 / Melee physical attack, use weapon effects
WEAPON_ESSENCE pWeapon = (WEAPON_ESSENCE)pData;
DATA_TYPE dtSub = DATA_TYPE.DT_INVALID;
var pWeaponTypeData = ElementDataManProvider.GetElementDataMan().get_data_ptr(pWeapon.id_sub_type, ID_SPACE.ID_SPACE_ESSENCE, ref dtSub);
var pWeaponTypeData = ElementDataManProvider.GetElementDataMan()
.get_data_ptr(pWeapon.id_sub_type, ID_SPACE.ID_SPACE_ESSENCE, ref dtSub);
WEAPON_SUB_TYPE pWeaponType = (WEAPON_SUB_TYPE)pWeaponTypeData;
// szflyGFX = null;
@@ -1044,7 +1159,8 @@ public class CECAttackEvent
szHitGFX = ByteToStringUtils.ByteArrayToCP936String(pWeaponType.file_hitgfx);
BMLogger.Log($"{ByteToStringUtils.UshortArrayToUnicodeString(pWeapon.name)} Use hit effect: {szHitGFX}");
BMLogger.Log(
$"{ByteToStringUtils.UshortArrayToUnicodeString(pWeapon.name)} Use hit effect: {szHitGFX}");
}
bool bHideFlyGfx = false; // TODO: !CECOptimize.Instance.GetGFX().CanShowFly(m_idHost);
@@ -1054,13 +1170,14 @@ public class CECAttackEvent
{
TARGET_DATA data = m_targets[i];
string pszflyGFX = "";//szflyGFX?.ToLower();
string pszHitGFX = "";//szHitGFX?.ToLower();
string pszflyGFX = ""; //szflyGFX?.ToLower();
string pszHitGFX = ""; //szHitGFX?.ToLower();
if (!string.IsNullOrEmpty(szflyGFX))
{
pszflyGFX = szflyGFX.ToLower().Replace("\\", "/");
}
if (!string.IsNullOrEmpty(szHitGFX))
{
pszHitGFX = szHitGFX.ToLower().Replace("\\", "/");
@@ -1092,7 +1209,8 @@ public class CECAttackEvent
// without weapon / 没有武器
// 使用拳套类的击中效果 / Use fist/glove hit effects
DATA_TYPE dt = DATA_TYPE.DT_INVALID;
var pData = ElementDataManProvider.GetElementDataMan().get_data_ptr(183, ID_SPACE.ID_SPACE_ESSENCE, ref dt);
var pData = ElementDataManProvider.GetElementDataMan()
.get_data_ptr(183, ID_SPACE.ID_SPACE_ESSENCE, ref dt);
WEAPON_SUB_TYPE pWeaponType = (WEAPON_SUB_TYPE)pData;
bool bHideHitGfx = false; // TODO: !CECOptimize.Instance.GetGFX().CanShowHit(m_idHost);
@@ -1130,7 +1248,6 @@ public class CECAttackEvent
}
else if (GPDataTypeHelper.ISNPCID(m_idHost))
{
if (m_idSkill != 0)
{
A3DSkillGfxComposer pComposer = null;
@@ -1155,14 +1272,16 @@ public class CECAttackEvent
}
}
if (pComposer != null && pComposer.m_dwFlyTime == 0) // 技能没有飞行时间,则直接头顶冒字 / Skill has no fly time, show damage immediately
if (pComposer != null &&
pComposer.m_dwFlyTime == 0) // 技能没有飞行时间,则直接头顶冒字 / Skill has no fly time, show damage immediately
{
m_timeToDoDamage = 1;
}
else
{
// now we estimated a time to do damage / 现在估算伤害时间
if (m_targets.Count > 0 && GetPosByID(m_idHost, out Vector3 vecHost) && GetPosByID(m_targets[0].idTarget, out Vector3 vecTarget))
if (m_targets.Count > 0 && GetPosByID(m_idHost, out Vector3 vecHost) &&
GetPosByID(m_targets[0].idTarget, out Vector3 vecTarget))
{
m_timeToDoDamage = (uint)Mathf.Max((vecHost - vecTarget).magnitude / 20.0f * 1000.0f, 10.0f);
}
@@ -1312,7 +1431,6 @@ public class CECAttackEvent
}
else if (GPDataTypeHelper.ISPLAYERID(idTarget))
{
CECPlayer pPlayer = EC_ManMessageMono.Instance.GetECManPlayer.GetPlayer(idTarget);
//BMLogger.LogError("HoangDev: CECPlayer pPlayer = " + pPlayer );
@@ -1352,6 +1470,7 @@ public class CECAttackEvent
});
return true;
}
public bool UpdateTargetFlag()
{
int nNumTargets = m_targets.Count;
@@ -1363,6 +1482,7 @@ public class CECAttackEvent
return true;
}
}
public class CECAttackerEvents
{
private readonly List<CECAttackEvent> m_list = new List<CECAttackEvent>();
@@ -1383,6 +1503,7 @@ public class CECAttackerEvents
if (evt.m_idSkill == idSkill && evt.m_nSkillSection == nSkillSection)
return evt;
}
return null;
}
@@ -1395,6 +1516,7 @@ public class CECAttackerEvents
BMLogger.Log($"[SKILL_GFX_FLOW] Signaling event | SkillID: {evt.m_idSkill}, HostID: {evt.m_idHost}");
evt.m_bSignaled = true;
}
m_list.Clear();
}
@@ -1403,39 +1525,42 @@ public class CECAttackerEvents
return !events.IsEmpty();
}
}
public enum MOD
{
MOD_PHYSIC_ATTACK_RUNE = 0x0001, // ÎïÀí¹¥»÷ÓÅ»¯·ûÉúЧ
MOD_MAGIC_ATTACK_RUNE = 0x0002, // ·¨Êõ¹¥»÷ÓÅ»¯·ûÉúЧ
MOD_PHYSIC_DEFENCE_RUNE = 0x0004, // ÎïÀí·ÀÓùÓÅ»¯·ûÉúЧ
MOD_MAGIC_DEFENCE_RUNE = 0x0008, // ·¨Êõ·ÀÓùÓÅ»¯·ûÉúЧ
MOD_CRITICAL_STRIKE = 0x0010, // ±¬»÷
MOD_RETORT = 0x0020, // ·´Õð
MOD_NULLITY = 0x0040, // ÎÞЧ¹¥»÷
MOD_IMMUNE = 0x0080, // ÃâÒßÁ˴˴ι¥»÷£¬ÓÅÏȼ¶¸ßÓÚÎÞЧ
MOD_ENCHANT_FAILED = 0x0100, // enchant ʧ°Ü
MOD_SUCCESS = 0x0200, // ³É¹¦
MOD_DODGE_DAMAGE = 0x0400, // É˺¦¶ãÉÁ
MOD_DODGE_DEBUFF = 0x0800, // ״̬¶ãÉÁ
MOD_ATTACK_AURA = 0x1000, // ¹â»·¹¥»÷
MOD_REBOUND = 0x2000, // ·´µ¯
MOD_BEAT_BACK = 0x4000, // ·´»÷
MOD_PHYSIC_ATTACK_RUNE = 0x0001, // ÎïÀí¹¥»÷ÓÅ»¯·ûÉúЧ
MOD_MAGIC_ATTACK_RUNE = 0x0002, // ·¨Êõ¹¥»÷ÓÅ»¯·ûÉúЧ
MOD_PHYSIC_DEFENCE_RUNE = 0x0004, // ÎïÀí·ÀÓùÓÅ»¯·ûÉúЧ
MOD_MAGIC_DEFENCE_RUNE = 0x0008, // ·¨Êõ·ÀÓùÓÅ»¯·ûÉúЧ
MOD_CRITICAL_STRIKE = 0x0010, // ±¬»÷
MOD_RETORT = 0x0020, // ·´Õð
MOD_NULLITY = 0x0040, // ÎÞЧ¹¥»÷
MOD_IMMUNE = 0x0080, // ÃâÒßÁ˴˴ι¥»÷£¬ÓÅÏȼ¶¸ßÓÚÎÞЧ
MOD_ENCHANT_FAILED = 0x0100, // enchant ʧ°Ü
MOD_SUCCESS = 0x0200, // ³É¹¦
MOD_DODGE_DAMAGE = 0x0400, // É˺¦¶ãÉÁ
MOD_DODGE_DEBUFF = 0x0800, // ״̬¶ãÉÁ
MOD_ATTACK_AURA = 0x1000, // ¹â»·¹¥»÷
MOD_REBOUND = 0x2000, // ·´µ¯
MOD_BEAT_BACK = 0x4000, // ·´»÷
};
public enum GfxMoveMode
{
enumLinearMove = 0, // Linear
enumParabolicMove, // Parabolic
enumMissileMove, // Missile
enumMeteoricMove, // Meteoric (shooting star)
enumHelixMove, // Helix (spiral)
enumCurvedMove, // Curved
enumAccMove, // Accelerated
enumOnTarget, // Targeted
enumLink, // Linked
enumRandMove, // Random movement
enumLinearMove = 0, // Linear
enumParabolicMove, // Parabolic
enumMissileMove, // Missile
enumMeteoricMove, // Meteoric (shooting star)
enumHelixMove, // Helix (spiral)
enumCurvedMove, // Curved
enumAccMove, // Accelerated
enumOnTarget, // Targeted
enumLink, // Linked
enumRandMove, // Random movement
enumMoveModeNum
};
public enum GfxTargetMode
{
enumHostToTarget = 0,
@@ -1450,6 +1575,7 @@ public enum GfxTargetMode
enumTargetLinkHost,
enumTargetModeNum
};
public enum GfxAttackMode
{
enumAttPoint,
@@ -1462,6 +1588,7 @@ public struct GfxCluster
public uint m_ulCount;
public uint m_dwInterv;
};
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct GFX_SKILL_PARAM
{
@@ -1474,16 +1601,14 @@ public struct GFX_SKILL_PARAM
[StructLayout(LayoutKind.Explicit)]
public struct ValueUnion
{
[FieldOffset(0)]
public bool bVal;
[FieldOffset(0)] public bool bVal;
[FieldOffset(0)]
public int nVal;
[FieldOffset(0)] public int nVal;
[FieldOffset(0)]
public float fVal;
[FieldOffset(0)] public float fVal;
}
}
public enum EmitShape
{
enumBox = 0,
@@ -1499,23 +1624,3 @@ public enum GfxSkillValType
enumGfxSkillFloat,
enumGfxSkillValTypeNum
};
@@ -87,6 +87,8 @@ namespace PerfectWorld.Scripts.Managers
OnMsgMatterDisappear(Msg);
break;
}
case EC_MsgDef.MSG_MM_MATTEROUTOFVIEW: OnMsgMatterOutOfView(Msg); break;
case EC_MsgDef.MSG_MM_INVALIDOBJECT: OnMsgInvalidObject(Msg); break;
}
}
@@ -346,5 +348,18 @@ namespace PerfectWorld.Scripts.Managers
{
return null;
}
bool OnMsgMatterOutOfView(ECMSG Msg)
{
MatterLeave(Convert.ToInt32(Msg.dwParam1));
return true;
}
bool OnMsgInvalidObject(ECMSG Msg)
{
cmd_invalid_object pCmd = GPDataTypeHelper.FromBytes<cmd_invalid_object>((byte[])Msg.dwParam1);
MatterLeave(pCmd.id);
return true;
}
}
}
@@ -87,7 +87,15 @@ namespace PerfectWorld.Scripts.Managers
case EC_MsgDef.MSG_PM_PLAYEREXTPROP:
OnMsgPlayerExtProp(Msg);
break;
case EC_MsgDef.MSG_PM_PLAYERDISAPPEAR:
OnMsgPlayerDisappear(Msg);
break;
case EC_MsgDef.MSG_PM_PLAYEROUTOFVIEW:
OnMsgPlayerOutOfView(Msg);
break;
case EC_MsgDef.MSG_PM_INVALIDOBJECT:
OnMsgInvalidObject(Msg);
break;
case int value when value == EC_MsgDef.MSG_PM_PLAYERDUELOPT:
// PLAYER_DUEL_START (229): server may send to both duelists; update host state if host is one of them
// dwParam2 is ushort (pCmdHeader from GameSession); use Convert to avoid InvalidCastException when unboxing
@@ -525,7 +533,11 @@ namespace PerfectWorld.Scripts.Managers
private EC_ElsePlayer CreateElsePlayer(info_player_1 info, int iAppearFlag)
{
GameObject ob = CECGameRun.Instance.InitCharacter(info);
EC_ElsePlayer elsePlayer = ob.AddComponent<EC_ElsePlayer>();
EC_ElsePlayer elsePlayer;
if (!ob.TryGetComponent<EC_ElsePlayer>(out elsePlayer))
{
elsePlayer = ob.AddComponent<EC_ElsePlayer>();
}
elsePlayer.Init(info, iAppearFlag);
return elsePlayer;
@@ -618,7 +630,11 @@ namespace PerfectWorld.Scripts.Managers
}
// Destroy the player GameObject
if (pPlayer.gameObject != null)
UnityEngine.Object.Destroy(pPlayer.gameObject);
{
PoolManager.Instance.Despawn(pPlayer.m_pPlayerCECModel.m_pPlayerModel);
PrefabPoolManager.Instance.Despawn(pPlayer.gameObject);
GameObject.Destroy(pPlayer);
}
}
}
@@ -917,6 +933,32 @@ namespace PerfectWorld.Scripts.Managers
ElsePlayerLeave(pCmd.id, true);
return true;
}
bool OnMsgPlayerOutOfView(ECMSG Msg)
{
int id = Convert.ToInt32(Msg.dwParam1);
ElsePlayerLeave(id, false);
return true;
}
bool OnMsgPlayerDisappear(ECMSG Msg)
{
var pCmd = Convert.ToInt32(Msg.dwParam1);
ElsePlayerLeave(pCmd, false);
return true;
}
bool OnMsgInvalidObject(ECMSG Msg)
{
cmd_invalid_object pCmd = GPDataTypeHelper.FromBytes<cmd_invalid_object>((byte[])Msg.dwParam1);
// Remove the player if it exists
EC_ElsePlayer pPlayer = GetElsePlayer(pCmd.id);
if (pPlayer)
{
ElsePlayerLeave(pCmd.id, false);
}
return true;
}
}
}
public struct EC_PLAYERLOADRESULT
@@ -103,17 +103,17 @@ namespace BrewMonster.Scripts.Managers
public async Task<GameObject> GetModelPlayer(byte profession, byte gender)
{
var prefab = await AddressableManager.Instance.LoadPrefabAsync(_playerModelPaths[profession * GENDER.NUM_GENDER + gender]);
var playerOb = await PoolManager.Instance.SpawnAsync(_playerModelPaths[profession * GENDER.NUM_GENDER + gender], Vector3.zero, Quaternion.identity, memoryReleaseTTL: 0f);
BMLogger.LogError("_playerModelPaths[profession * GENDER.NUM_GENDER + gender] = " + _playerModelPaths[profession * GENDER.NUM_GENDER + gender]);
if (prefab == null)
if (playerOb == null)
{
BMLogger.LogError( $" [NPC Manager] Not found Prefab from Addressable with profession : {profession} gender : {gender}");
return null;
}
var player = Instantiate(prefab);
player.SetActive(true);
return player;
//var player = Instantiate(prefab);
playerOb.SetActive(true);
return playerOb;
}
public async Task<GameObject> GetDummyModel(int iShape)
{
+13 -18
View File
@@ -87,6 +87,8 @@ namespace BrewMonster
protected int NUM_WEAPON_TYPE = 15;
public static readonly int[] m_sciStateIDForStateAction = { 117 };
/// <summary>Skill id for pending skill/state hit reaction (see skill_state_action.txt).</summary>
protected int m_SkillIDForStateAction;
private static Dictionary<uint, PLAYER_ACTION_INFO_CONFIG> _default_skill_actions
= new Dictionary<uint, PLAYER_ACTION_INFO_CONFIG>();
@@ -101,7 +103,7 @@ namespace BrewMonster
// 需要是可能 || Need is possible
protected bool m_bHangerOn = false;
protected int m_iCurAction;
protected bool m_bAboutToDie = false;
protected bool m_bAboutToDie = false;
public bool m_bCandHangerOn = false;
public bool m_bPetInSanctuary = false; // true, the pet pet of the player is in sanctuary
//The ID of the currently summoned pet
@@ -362,6 +364,7 @@ namespace BrewMonster
m_aEquips = new int[(int)IndexOfIteminEquipmentInventory.SIZE_ALL_EQUIPIVTR];
queueActionEvent = new QueueActionEvent("", null, false, null, 200);
TickInvoker.Instance.RegisterTickable(this);
m_SkillIDForStateAction = 0;
}
protected virtual void OnDestroy()
@@ -2278,6 +2281,7 @@ namespace BrewMonster
// Just play a wounded action
if (!OnDamaged(skill))
{
BMLogger.LogError(("HoangDev PlayAction((int)PLAYER_ACTION_TYPE.ACT_WOUNDED);"));
PlayAction((int)PLAYER_ACTION_TYPE.ACT_WOUNDED);
}
if ((dwModifier & (uint)MOD.MOD_IMMUNE) != 0)
@@ -2299,7 +2303,9 @@ namespace BrewMonster
p1 |= 0x0002;
if (!OnDamaged(skill))
{
PlayAction((int)PLAYER_ACTION_TYPE.ACT_WOUNDED);
}
if ((dwModifier & (uint)MOD.MOD_IMMUNE) != 0)
BubbleText((int)BubbleTextType.BUBBLE_IMMUNE, 0);
@@ -2531,15 +2537,17 @@ namespace BrewMonster
string name1, name2;
BMLogger.LogError("HoangDev: OnDamaged skill:"+skill + ", m_sciStateIDForStateAction.Length:"+m_sciStateIDForStateAction.Length);
for (int i = 0; i < m_sciStateIDForStateAction.Length; i++)
{
/* if (atkMan.GetSkillStateActionName(skill, m_sciStateIDForStateAction[i], out name1, out name2))
if (atkMan.GetSkillStateActionName(skill, m_sciStateIDForStateAction[i], out name1, out name2))
{
m_SkillIDForStateAction = skill;
BMLogger.LogError("HoangDev: atkMan.GetSkillStateActionName(ski");
return true;
}*/
}
}
BMLogger.LogError(("HoangDev: atkMan.GetSkillStateActionName(ski\" return false;"));
return false;
}
public CECSkill GetCurSkill() { return m_pCurSkill; }
@@ -2780,19 +2788,6 @@ namespace BrewMonster
{
return (m_dwStates & PlayerNPCState.GP_STATE_PARIAH) != 0;
}
bool GetSkillStateActionName(int skill, int state, string name1, string name2)
{
/* for (int i = 0; i < (int)m_SkillStateActionVec.size(); i++)
{
if (m_SkillStateActionVec[i].skill == skill && m_SkillStateActionVec[i].state == state)
{
name1 = m_SkillStateActionVec[i].beHitAction;
name2 = m_SkillStateActionVec[i].stayDownAction;
return true;
}
}*/
return false;
}
public virtual bool IsFighting() { return m_bFight; }
public float GetGroundSpeed()
{
@@ -3450,7 +3445,7 @@ namespace BrewMonster
}
try
{
m_PetModelVisual = await PoolManager.Instance.SpawnAsync(AFile.NormalizePath(szPetPath.ToLower(), true), Vector3.zero, Quaternion.identity, 15f);
m_PetModelVisual = await PoolManager.Instance.SpawnAsync(AFile.NormalizePath(szPetPath.ToLower(), true), Vector3.zero, Quaternion.identity, memoryReleaseTTL: 0f);
if(m_PetModelVisual == null)
{
m_PetModelVisual = GameObject.CreatePrimitive(PrimitiveType.Capsule);
+143 -30
View File
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using BrewMonster.Scripts;
using CSNetwork.GPDataType;
@@ -15,6 +16,7 @@ using BrewMonster;
using BrewMonster.Scripts.ECModel;
using Cysharp.Threading.Tasks;
using Unity.VisualScripting.FullSerializer;
using Unity.VisualScripting;
public enum ECMScript
{
enumECMScriptStartAction = 0,
@@ -93,6 +95,7 @@ public class A3DCombActDynData
public List<string> m_ActionNames = new List<string>();
public List<string> m_SFXNames = new List<string>();
public List<GameObject> m_GFXObjects = new List<GameObject>();
public bool IsActionStopped() { return m_ActionNames.Count == 0; }
/// <summary>True when there is no attack or damage has been applied. / 无攻击事件或已造成伤害则为 true</summary>
public bool IsAllEventFinished() { return (ActiveAttackEvent == null || ActiveAttackEvent.m_bDoDamaged); }
@@ -138,18 +141,11 @@ public class A3DCombActDynData
m_bSetSpeedWhenActStart = false;
m_fModelScale = 1.0f;
var actInfoList = pAct.m_ActLst;
// {
// ActInfoList& actInfoList = pAct->m_ActLst;
// ALISTPOSITION pos = actInfoList.GetHeadPosition();
// while (pos)
// {
// PACTION_INFO pAct = actInfoList.GetNext(pos);
// int nDynLoopNum = pAct->CalcLoopNum();
// m_arrActLoopNum.Add(ACTIONDYN_DATA(nDynLoopNum, pAct));
// if (!m_bIsInfiniteComAct && nDynLoopNum < 0) m_bIsInfiniteComAct = true;
// }
// CalcDynComActSpan();
// }
foreach(var actInfo in actInfoList)
{
int nDynLoopNum = actInfo.CalcLoopNum();
if (!m_bIsInfiniteComAct && nDynLoopNum < 0) m_bIsInfiniteComAct = true;
}
}
/// <param name="triggerVisualAndFx">
@@ -197,12 +193,13 @@ public class A3DCombActDynData
ChannelAct channelAct = m_pECModel.GetChannelAct(m_nChannel);
if (channelAct != null)
{
bool isLoop = m_pAct.m_nLoops == 1;
bool isLoop = m_bIsInfiniteComAct;
int ownerId = m_pECModel.GetId();
EventBus.PublishChannel(ownerId, new PlayActionEvent(ref channelAct, actionInfos[0].m_strName, m_nTransTime, bForceStopPrevious, ActiveAttackEvent, isLoop, channelRank));
m_ActionNames.Add(actionInfos[0].m_strName);
for(int i = 1; i < actionInfos.Count; i++)
{
isLoop = m_bIsInfiniteComAct;
EventBus.PublishChannelClass(ownerId, new QueueActionEvent(ref channelAct, actionInfos[i].m_strName, null, false, null, m_nTransTime, false, isLoop, channelRank));
m_ActionNames.Add(actionInfos[i].m_strName);
}
@@ -213,7 +210,7 @@ public class A3DCombActDynData
/// <summary>
/// Sound events embedded in combined action; skip gfx paths. / 组合动作内嵌音效事件;跳过 gfx 路径。
/// </summary>
void TriggerSFxFromEventList()
async void TriggerSFxFromEventList()
{
if (m_bNoFx || m_pAct == null)
return;
@@ -228,27 +225,83 @@ public class A3DCombActDynData
{
if (sfx.m_strFilePaths != null && sfx.m_strFilePaths.Count > 0)
{
string soundpath = AFile.NormalizePath(sfx.m_strFilePaths[0], true);
if (soundpath.Contains("gfx"))
continue;
soundpath = soundpath.ToLower();
m_SFXNames.Add(soundpath);
string path = AFile.NormalizePath(sfx.m_strFilePaths[0], true);
if (path.Contains("gfx"))
goto GFX;
path = path.ToLower();
m_SFXNames.Add(path);
try
{
SFXManager.Instance
.PlaySkillSfxAtPointAsync(soundpath, Vector3.zero).Forget();
.PlaySkillSfxAtPointAsync(path, Vector3.zero).Forget();
}
finally
{
// remove AFTER sound finished
m_SFXNames.Remove(soundpath);
m_SFXNames.Remove(path);
}
goto END;
GFX:
{
path = "gfx/" + path;
GameObject prefab = await AddressableManager.Instance.LoadPrefabAsync(path);
GameObject fx = null;
if(prefab != null && m_pECModel != null)
{
// LoadPrefabAsync returns the prefab asset; must Instantiate before modifying transform.
// LoadPrefabAsync 返回的是预制体资源,必须先 Instantiate 再改 Transform。
fx = GameObject.Instantiate(prefab, m_pECModel.transform);
fx.SetActive(true);
fx.transform.localPosition = Vector3.zero;
fx.transform.localRotation = Quaternion.identity;
fx.transform.localScale = Vector3.one;
ParticleSystem ps = fx.GetComponent<ParticleSystem>();
if (ps != null)
ps.Play();
}
else if (prefab == null)
{
GameObject prefab2 = Resources.Load<GameObject>("GFX/" + "PlaceHolder");
if(prefab2 != null && m_pECModel != null)
{
fx = GameObject.Instantiate(prefab2, m_pECModel.transform);
fx.SetActive(true);
fx.transform.localPosition = Vector3.zero;
fx.transform.localRotation = Quaternion.identity;
fx.transform.localScale = Vector3.one;
ParticleSystem ps2 = fx.GetComponent<ParticleSystem>();
if (ps2 != null)
ps2.Play();
}
}
if(fx != null)
{
m_GFXObjects.Add(fx);
}
// var gfxLogPath = Path.Combine(Application.dataPath, "PerfectWorld", "Scripts", "NPC", "GFXLOG.txt");
// var lines = new List<string>();
// if (File.Exists(gfxLogPath))
// {
// foreach (var line in File.ReadAllLines(gfxLogPath))
// {
// if (string.Equals(line.Trim(), path, StringComparison.OrdinalIgnoreCase))
// continue;
// lines.Add(line);
// }
// }
// lines.Add(path);
// File.WriteAllLines(gfxLogPath, lines);
}
END:
continue;
}
}
}
}
public void Stop(bool bStopAct, bool bForceStopFx = false )
{
RemoveAllActiveFx();
// FlushDamageInfo();
// ClearParentInfo();
@@ -280,7 +333,24 @@ public class A3DCombActDynData
// if (pChannel)
// pChannel->StopAction(m_pAct->GetRank(m_nChannel));
}
public void UpdateAct(uint dwUpdateTime)
{
if(IsActionStopped())
{
RemoveAllActiveFx();
}
}
public void RemoveAllActiveFx()
{
foreach(var fx in m_GFXObjects)
{
if(fx != null)
{
GameObject.Destroy(fx);
}
}
m_GFXObjects.Clear();
}
public void SetUserData(int dwUserData) { m_dwUserData = dwUserData; }
public void SetTransTime(int nTransTime) { m_nTransTime = nTransTime; }
public void SetStopPrevAct(bool bStopPrevAct) { m_bStopPrevAct = bStopPrevAct; }
@@ -314,12 +384,13 @@ public class ChannelActNode
}
public void RemoveQueuedActs()
{
m_pActive.RemoveAllActiveFx();
m_QueuedActs.Clear();
}
}
public class ChannelAct
{
public List<ChannelActNode> m_RankNodes;
public List<ChannelActNode> m_RankNodes = new List<ChannelActNode>();
public ChannelAct()
{
@@ -332,6 +403,16 @@ public class ChannelAct
{
m_RankNodes = new List<ChannelActNode>();
}
else
{
foreach(var node in m_RankNodes)
{
if(node != null)
{
node.RemoveQueuedActs();
}
}
}
m_RankNodes.Clear();
}
@@ -493,7 +574,6 @@ public class CECModelStaticData
private string m_strPixelShader = string.Empty;
private string m_strShaderTex = string.Empty;
private readonly List<object> m_vecPSConsts = new List<object>();
public CECModelStaticData()
{
ResetOuterData();
@@ -718,6 +798,7 @@ public class CECModel
private Dictionary<string, CECModel> m_childModels = new Dictionary<string, CECModel>();
private Transform m_transform;
private bool m_bAbsTrack = false;
private bool m_bFirstActPlayed = false;
public bool InheritParentId() => m_bInheritParentId;
public void SetId(int nId) => m_nId = nId;
public int GetId() => m_nId;
@@ -1027,11 +1108,41 @@ public class CECModel
{
return false;
}
var pNode = m_ChannelActs[nChannel].GetNodeByRank(0);
byte rank = 0;
ChannelAct ca = m_ChannelActs[nChannel];
ChannelActNode pNode = ca.GetNodeByRank(rank);
A3DCombActDynData pActive;
if (pNode != null)
{
pActive = pNode.m_pActive;
pNode.RemoveQueuedActs();
}
else
{
pActive = null;
}
if (!bRestart && pActive != null && pActive.GetComAct().m_strName == szActName)
return true;
// if (m_pBlurInfo != null && m_pBlurInfo.m_bRoot && m_pBlurInfo.m_bStopWhenActChange)
// RemoveMotionBlurInfo();
if (pActive != null)
{
pActive.Stop(bForceStop);
pActive = null;
}
else if (!m_bFirstActPlayed)
{
m_bFirstActPlayed = true;
nTransTime = 0;
}
if (pNode == null)
{
pNode = new ChannelActNode { m_Rank = 0 };
m_ChannelActs[nChannel].m_RankNodes.Add(pNode);
pNode = new ChannelActNode();
pNode.m_Rank = rank;
ca.m_RankNodes.Add(pNode);
}
pNode.m_pActive = new A3DCombActDynData(combinedAction, this, attackEvent);
pNode.m_pActive.SetUserData((int)dwUserData);
@@ -1158,7 +1269,6 @@ public class CECModel
if (node.m_QueuedActs.Count > 0)
{
A3DCombActDynData pNext = node.m_QueuedActs[0];
node.m_QueuedActs.RemoveAt(0);
if (pNext.GetStopPrevAct())
{
@@ -1180,6 +1290,7 @@ public class CECModel
node.m_pActive = pNext;
node.m_pActive.Play(i, 1f, node.m_pActive.GetTransTime(), 0/**m_EventMasks[i]*/, true, m_bAbsTrack, pNext.GetNoFxFlag());
//pNext.UpdateAct(dwUpdateTime);
node.m_QueuedActs.RemoveAt(0);
m_bAbsTrack = false;
}
else
@@ -1188,8 +1299,10 @@ public class CECModel
rankNodes.RemoveAt(n);
}
}
// else
// node.m_pActive.UpdateAct(dwUpdateTime);
else
{
node.m_pActive.UpdateAct(dwUpdateTime);
}
}
}
}
+4 -6
View File
@@ -66,8 +66,6 @@ public class CECNPC : CECObject
[SerializeField] protected bool isDebug;
[SerializeField] protected NPCVisual npcVisual;
GameObject m_modelVisual = null;
float m_fDistShowModelVisual = 25f; // Display distance model NPC
float m_fDistHideModelVisual = 40f; // Hide/display distance model NPC
protected static CECStringTab m_ActionNames;
/* public string NameNPC => m_strName;
@@ -262,7 +260,7 @@ public class CECNPC : CECObject
// [中文] 处理服务器发来的扩展状态更新消息,驱动状态 GFX 的添加与移除
// [English] Handle server ext-state update message — drives state GFX add/remove
// [中文] 更新扩展状态并刷新 GFX 显示
// [English] Update the ext-state arrays and refresh GFX display
@@ -638,11 +636,11 @@ public class CECNPC : CECObject
if(m_modelVisual != null)
{
if(m_fDistToHostH < m_fDistShowModelVisual)
if(m_fDistToHostH < AddressResourceConfig.m_fDistShowModelVisual)
{
m_modelVisual.SetActive(true);
}
else if(m_fDistToHostH > m_fDistHideModelVisual)
else if(m_fDistToHostH > AddressResourceConfig.m_fDistHideModelVisual)
{
m_modelVisual.SetActive(false);
}
@@ -962,7 +960,7 @@ public class CECNPC : CECObject
EventBus.PublishChannel(m_NPCInfo.nid, new ClearComActFlagEvent(true));
}
public void Damaged(int iDamage, uint dwModifier/* 0 */)
public void Damaged(int iDamage, uint dwModifier = 0/* 0 */)
{
if (iDamage == -1 || iDamage == -2)
{
@@ -30,7 +30,7 @@ public class NPCBuilder : MonoSingleton<NPCBuilder>
public async Task<GameObject> GetModelByPath(string path)
{
//return await AddressableManager.Instance.LoadPrefabAsync(AFile.NormalizePath(path));
return await PoolManager.Instance.SpawnAsync(AFile.NormalizePath(path), Vector3.zero, Quaternion.identity, memoryReleaseTTL: 15f, autoDespawnTime: 0f);
return await PoolManager.Instance.SpawnAsync(AFile.NormalizePath(path), Vector3.zero, Quaternion.identity, memoryReleaseTTL: 0f, autoDespawnTime: 0f);
}
#if UNITY_EDITOR
@@ -16,6 +16,7 @@ public class NPCVisual : MonoBehaviour
private const FadeMode FadeMode = Animancer.FadeMode.FixedDuration;
public CECNPC.INFO GetNPCINFO => m_NPCInfo;
public bool TryPlayAction(string animationName, CECAttackEvent cECAttackEvent, bool isHit = false, bool bRestart = true)
{
// BMLogger.LogMono(this, "HoangDev: TryPlayAction: " + animationName);
@@ -50,6 +51,7 @@ public class NPCVisual : MonoBehaviour
BMLogger.LogWarning("animancer == null");
return;
}
namedAnimancer.Animator.cullingMode = AnimatorCullingMode.CullUpdateTransforms;
EventBus.SubscribeChannel<QueueNPCActionEvent>(m_NPCInfo.nid, OnQueueAction);
EventBus.SubscribeChannel<ClearComActFlagEvent>(m_NPCInfo.nid, OnClearComActFlagEvent);
}
File diff suppressed because it is too large Load Diff
@@ -808,7 +808,7 @@ namespace CSNetwork
m_CmdCache.RemoveAllCmds();
// int iFlag;
// switch (p->result)
// switch (p.result)
// {
// case _PLAYER_LOGOUT_FULL: iFlag = 0; break;
// case _PLAYER_LOGOUT_HALF: iFlag = 1; break;
@@ -822,13 +822,13 @@ namespace CSNetwork
default: iFlag = 2; break;
}
// g_pGame->GetGameRun()->SetLogoutFlag(iFlag);
// g_pGame.GetGameRun().SetLogoutFlag(iFlag);
EC_Game.GetGameRun().SetLogoutFlag(iFlag);
// if (!IsConnected() && g_pGame->GetGameRun()->GetLogoutFlag() == 1)
// if (!IsConnected() && g_pGame.GetGameRun().GetLogoutFlag() == 1)
// {
// a_LogOutput(1, "CECGameSession::OnPrtcPlayerLogout, LogoutFlag=1 replaced by 2.");
// g_pGame->GetGameRun()->SetLogoutFlag(2);
// g_pGame.GetGameRun().SetLogoutFlag(2);
// }
// Keep half logout as role-select even if the server closes the socket.
// LoginScene will reconnect with saved credentials if needed.
@@ -1021,7 +1021,7 @@ namespace CSNetwork
case CommandID.EQUIP_DATA:
case CommandID.EQUIP_DATA_CHANGED:
// BMLogger.Log($"### EQUIP_DATA: CMDID {pCmdHeader}");
// MSG_PM_PLAYEREQUIPDATA, MAN_PLAYER, -1, (DWORD)pDataBuf, pCmdHeader->cmd, dwDataSize);
// MSG_PM_PLAYEREQUIPDATA, MAN_PLAYER, -1, (DWORD)pDataBuf, pCmdHeader.cmd, dwDataSize);
EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYEREQUIPDATA, MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader);
break;
case CommandID.PLAYER_EQUIP_DETAIL:
@@ -1555,9 +1555,20 @@ namespace CSNetwork
}
case CommandID.HOST_NOTIFY_ROOT:
case CommandID.HOST_DISPEL_ROOT:
EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_ROOTNOTIFY, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader);
break;
case CommandID.INVALID_OBJECT:
{
cmd_invalid_object pCmd = GPDataTypeHelper.FromBytes<cmd_invalid_object>((byte[])pDataBuf);
if (ISPLAYERID(pCmd.id))
EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_INVALIDOBJECT, MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader);
else if (ISNPCID(pCmd.id))
EC_ManMessage.PostMessage(EC_MsgDef.MSG_NM_INVALIDOBJECT, MANAGER_INDEX.MAN_NPC, 0, pDataBuf, pCmdHeader);
else if (ISMATTERID(pCmd.id))
EC_ManMessage.PostMessage(EC_MsgDef.MSG_MM_INVALIDOBJECT, MANAGER_INDEX.MAN_MATTER, 0, pDataBuf, pCmdHeader);
break;
}
default:
#if UNITY_EDITOR
if (isDebug)
@@ -1576,7 +1587,7 @@ namespace CSNetwork
var callback = _selectRoleCallback;
PostToUnityContext(() => callback?.Invoke(_selectedRole));
// in C++: we call CECGameRun() via pLoginUIMan->LaunchLoading();
// in C++: we call CECGameRun() via pLoginUIMan.LaunchLoading();
// now: quick hack to start game immediately after role selection - can refactor later if needed
EC_Game.GetGameRun().StartGame(0, Vector3.zero);
}
@@ -2628,15 +2639,15 @@ namespace CSNetwork
if (!pBuf)
return;
((cmd_header*)pBuf)->cmd = C2S::GET_OTHER_EQUIP;
((cmd_header*)pBuf).cmd = C2S::GET_OTHER_EQUIP;
cmd_get_other_equip* pCmd = (cmd_get_other_equip*)(pBuf + sizeof (cmd_header));
pCmd->size = (WORD)iNumSend;
pCmd.size = (WORD)iNumSend;
for (int i=0; i < iNumSend; i++)
pCmd->idlist[i] = aIDs[iCount+i];
pCmd.idlist[i] = aIDs[iCount+i];
g_pGame->GetGameSession()->SendGameData(pBuf, iSize);
g_pGame.GetGameSession().SendGameData(pBuf, iSize);
a_freetemp(pBuf);
//*/
@@ -38,6 +38,8 @@ namespace BrewMonster.Network
private string _username = "";
private string _password = "";
private bool _isIntentionalDisconnect = false;
private bool _wasUnexpectedlyDisconnected = false;
// When true, prevent all outgoing protocols (background ticks, tasks, etc.) from sending.
private bool _suppressOutgoing = false;
@@ -267,7 +269,10 @@ namespace BrewMonster.Network
if (entryTarget == LogoutFlowState.LoginEntryTarget.LoginUI)
{
// Account logout only; half logout keeps SDK credentials so LoginScene can reopen role select.
Tech3CSDKWrapper.Instance.Logout();
if (Tech3CSDKWrapper.Instance.EnsureInitialized())
{
Tech3CSDKWrapper.Instance.Logout();
}
}
}
@@ -357,6 +362,14 @@ namespace BrewMonster.Network
SceneManager.UnloadSceneAsync(currentScene);
}
public bool ConsumeUnexpectedDisconnect()
{
bool value = _wasUnexpectedlyDisconnected;
_wasUnexpectedlyDisconnected = false;
return value;
}
private Task WaitForDisconnectAsync(int timeoutMs)
{
if (_gameSession == null || !_gameSession.IsConnected)
@@ -803,6 +816,8 @@ namespace BrewMonster.Network
return;
}
_wasUnexpectedlyDisconnected = true;
// Show disconnect message box
CECUIManager.Instance?.ShowMessageBoxYes("Disconnected", "Connection to the server has been lost.", null,
() =>
@@ -813,6 +828,15 @@ namespace BrewMonster.Network
}
public bool TryConsumeUnexpectedDisconnect()
{
if(!_wasUnexpectedlyDisconnected)
return false;
_wasUnexpectedlyDisconnected = false;
return true;
}
public static void c2s_CmdGoto(float x, float y, float z)
{
Instance._gameSession.c2s_CmdGoto(x, y, z);
@@ -162,7 +162,7 @@ namespace PerfectWorld.Scripts
string filePath = ByteToStringUtils.ByteArrayToCP936String((byte[])fileMatterValue);
//var matterPrefab = await AddressableManager.Instance.LoadPrefabAsync(AFile.NormalizePath(filePath.ToLower(), true));
var matterObject = await PoolManager.Instance.SpawnAsync(AFile.NormalizePath(filePath.ToLower(), true), Vector3.zero, Quaternion.identity, 15f);
var matterObject = await PoolManager.Instance.SpawnAsync(AFile.NormalizePath(filePath.ToLower(), true), Vector3.zero, Quaternion.identity, memoryReleaseTTL: 0f);
if (matterObject != null)
{
//var matterObject = Instantiate(matterPrefab);
@@ -447,6 +447,17 @@ namespace BrewMonster
{
m_fDistToHost = CalcDist(pHost.GetPos(), true);
m_fDistToHostH = CalcDist(pHost.GetPos(), false);
if (m_pPlayerModel != null)
{
if (m_fDistToHostH < AddressResourceConfig.m_fDistShowModelVisual)
{
m_pPlayerModel.SetActive(true);
}
else if (m_fDistToHostH > AddressResourceConfig.m_fDistHideModelVisual)
{
m_pPlayerModel.SetActive(false);
}
}
}
m_pEPWorkMan?.Tick(Time.deltaTime);
}
@@ -33,7 +33,6 @@ namespace BrewMonster.Scripts
/// </summary>
public void InitForWorld(int worldTag)
{
BMLogger.LogError("HoangDev: InitForWorld worldTag:"+worldTag);
AudioManager.Instance.StopBGM(1f);
SetupAudioSources(worldTag).Forget();
}
@@ -37,28 +37,40 @@ namespace BrewMonster.Scripts
SetupCallbacks();
// Auto-initialize SDK
if (!string.IsNullOrEmpty(clientId) && !string.IsNullOrEmpty(clientSecret))
EnsureInitialized();
BMLogger.Log("[SDK] Tech3C SDK Started");
}
public bool EnsureInitialized()
{
if (Tech3CSDK.Instance.IsInitialized)
{
BMLogger.Log($"Initializing Tech3C SDK...\n Client ID: {clientId}");
Tech3CSDK.Instance.Initialize(clientId, clientSecret);
if (Tech3CSDK.Instance.IsInitialized)
{
BMLogger.Log("[SDK] SDK Initialized Successfully!");
}
else
{
BMLogger.Log("[SDK] Failed to initialize SDK");
}
isInitialized = true;
return true;
}
if(string.IsNullOrEmpty(clientId) || string.IsNullOrEmpty(clientSecret))
{
BMLogger.LogError("[SDK] Client ID and/or Client Secret not set. Please configure in Inspector.");
isInitialized = false;
return false;
}
BMLogger.Log($"Initializing Tech3C SDK...\n Client ID: {clientId}");
Tech3CSDK.Instance.Initialize(clientId, clientSecret);
if (Tech3CSDK.Instance.IsInitialized)
{
BMLogger.Log("[SDK] SDK Initialized Successfully!");
}
else
{
BMLogger.Log("[SDK] Client ID and/or Client Secret not set. Please configure in Inspector.");
BMLogger.Log("[SDK] Failed to initialize SDK");
}
BMLogger.Log("[SDK] Tech3C SDK Started");
isInitialized = true;
isInitialized = Tech3CSDK.Instance.IsInitialized;
return isInitialized;
}
private void SetupCallbacks()
@@ -205,4 +217,4 @@ namespace BrewMonster.Scripts
#endregion
}
}
}
@@ -276,8 +276,6 @@ namespace BrewMonster
int curSp = GetHostPlayer().GetBasicProps().iSP;
uint curMoney = GetHostPlayer().GetMoneyAmount();
if (m_skillID == 1)
BMLogger.LogError($"HoangDev: UpdateUpgradeBtn curSp:{curSp}, needSp:{needSp}, curMoney:{curMoney}, needMoney:{needMoney}");
bool spOK = curSp >= needSp;
bool moneyOK = curMoney >= needMoney;
bool preSkillOK = true;
@@ -47,10 +47,20 @@ namespace BrewMonster.UI
void OnClickYes()
{
CECGameRun.Instance.GetPendingLogOut().AppendForSaveConfig(new CECPendingLogoutHalf());
if (!UnityGameSession.Instance.GameSession.IsConnectedInternet)
if (UnityGameSession.Instance != null && UnityGameSession.Instance.TryConsumeUnexpectedDisconnect())
{
EC_Game.GetGameRun().SetLogoutFlag(1);
UnityGameSession.LogoutAccount();
return;
}
if (UnityGameSession.Instance == null || !UnityGameSession.Instance.GameSession.IsConnected)
{
//force log out half
EC_Game.GetGameRun().SetLogoutFlag(1);
UnityGameSession.LogoutAccount();
return;
}
}
@@ -138,16 +138,37 @@ namespace BrewMonster.UI
_loginInProgress = true;
if (_loginButton != null) _loginButton.interactable = false;
bool sdkReady = Tech3CSDKWrapper.Instance.EnsureInitialized();
// If username or password is empty, use Tech3C SDK login UI.
if (string.IsNullOrEmpty(_usernameInputField.text) || string.IsNullOrEmpty(_passwordInputField.text))
{
// Use Tech3C SDK login UI.
bool started = Tech3CSDKWrapper.Instance.Login();
if (!started)
if (sdkReady)
{
// Fallback: manual username/password login (useful in dev if SDK not configured).
BMLogger.LogWarning("[LoginScreenUI] Tech3CSDKWrapper.Login() failed, fallback to manual login.");
await BeginGameLoginAsync(_usernameInputField.text, _passwordInputField.text);
// Use Tech3C SDK login UI.
bool started = Tech3CSDKWrapper.Instance.Login();
if (!started)
{
// Fallback: manual username/password login (useful in dev if SDK not configured).
BMLogger.LogWarning("[LoginScreenUI] Tech3CSDKWrapper.Login() failed, fallback to manual login.");
await BeginGameLoginAsync(_usernameInputField.text, _passwordInputField.text);
}
}
else
{
string savedUsername = PlayerPrefs.GetString("username", "");
string savedPassword = PlayerPrefs.GetString("password", "");
if (!string.IsNullOrEmpty(savedUsername) && !string.IsNullOrEmpty(savedPassword))
{
BMLogger.LogWarning("[LoginScreenUI] Tech3C SDK not ready, using saved username/password for login.");
await BeginGameLoginAsync(savedUsername, savedPassword);
}
else
{
BMLogger.LogError("[LoginScreenUI] Tech3C SDK not ready and no saved username/password.");
_loginInProgress = false;
if (_loginButton != null) _loginButton.interactable = true;
}
}
}
else
@@ -156,7 +177,6 @@ namespace BrewMonster.UI
BMLogger.LogError("[LoginScreenUI] Username/password empty.");
await BeginGameLoginAsync(_usernameInputField.text, _passwordInputField.text);
}
}
private async Task BeginGameLoginAsync(string username, string password)
@@ -528,7 +528,6 @@ namespace BrewMonster
ClearPendingComboAssign();
ClearPendingActionAssign();
assignedSkill = CECGameRun.Instance.GetHostPlayer().GetPositiveSkillByID(obj.skillID);
Debug.Log($"HoangDev: OnAssignSkillSelectionChanged: skillID={obj.skillID} currentSelectedSlotIndex={currentSelectedSlotIndex}");
if (currentSelectedSlotIndex != -1)
{
CreateSkillShortcut();
@@ -9,5 +9,9 @@ namespace BrewMonster
public static string TestVfxPrefab = "Prefabs/Vfx/TestVfx";
public static string PetServerPrefab = "Pet/PetPrefab";
public static string PetMountServerPrefab = "Pet/PetMount/PetMountPrefab";
public static float m_fDistShowModelVisual = 25f; // Display distance model NPC
public static float m_fDistHideModelVisual = 40f; // Hide/display distance model NPC
}
}
@@ -50,7 +50,7 @@ TextureImporter:
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
spriteGenerateFallbackPhysicsShape: 0
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
@@ -69,7 +69,7 @@ TextureImporter:
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
maxTextureSize: 8192
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
@@ -119,6 +119,19 @@ TextureImporter:
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: VisionOS
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
@@ -69,7 +69,7 @@ TextureImporter:
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
maxTextureSize: 8192
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
+279
View File
@@ -0,0 +1,279 @@
skill: 2212
{
(1,1,gfx\\sgc\\刺客_连击改_击中.sgc),
(2,2,gfx\\sgc\\刺客_连击改_击中.sgc)
}
skill: 2213
{
(1,1,gfx\\sgc\\刺客_连击改_击中.sgc),
(2,2,gfx\\sgc\\刺客_连击改_击中.sgc)
}
skill: 2214
{
(1,1,gfx\\sgc\\刺客_斩杀改_击中.sgc),
(2,2,gfx\\sgc\\刺客_斩杀改_击中.sgc),
(3,3,gfx\\sgc\\刺客_斩杀改_击中.sgc),
(4,4,gfx\\sgc\\刺客_斩杀改_击中.sgc),
(5,5,gfx\\sgc\\刺客_斩杀改_击中.sgc)
}
skill: 2215
{
(1,1,gfx\\sgc\\刺客_斩杀改_击中.sgc),
(2,2,gfx\\sgc\\刺客_斩杀改_击中.sgc),
(3,3,gfx\\sgc\\刺客_斩杀改_击中.sgc),
(4,4,gfx\\sgc\\刺客_斩杀改_击中.sgc),
(5,5,gfx\\sgc\\刺客_斩杀改_击中.sgc)
}
skill: 2452
{
(1,1,gfx\\sgc\\法师_冰火两重天_冰击中.sgc),
(2,2,gfx\\sgc\\法师_冰火两重天_火击中.sgc)
}
skill: 2453
{
(1,1,gfx\\sgc\\法师_冰火两重天_冰击中.sgc),
(2,2,gfx\\sgc\\法师_冰火两重天_火击中.sgc)
}
skill: 2316
{
(1,1,gfx\\sgc\\刺客_连击改_击中.sgc),
(2,2,gfx\\sgc\\刺客_连击改_击中.sgc)
}
skill: 2366
{
(1,1,gfx\\sgc\\刺客_神威狱_击中.sgc),
(2,2,gfx\\sgc\\刺客_神威狱_击中.sgc),
(3,3,gfx\\sgc\\刺客_神威狱_击中.sgc),
(4,4,gfx\\sgc\\刺客_神威狱_击中.sgc)
}
skill: 2451
{
(1,1,gfx\\sgc\\刺客_神威狱_击中.sgc),
(2,2,gfx\\sgc\\刺客_神威狱_击中.sgc),
(3,3,gfx\\sgc\\刺客_神威狱_击中.sgc),
(4,4,gfx\\sgc\\刺客_神威狱_击中.sgc)
}
skill: 2591
{
(1,1,gfx\\sgc\\月仙_月华乱舞_击中.sgc),
(2,2,gfx\\sgc\\月仙_月华乱舞_击中.sgc),
(3,3,gfx\\sgc\\月仙_月华乱舞_击中.sgc),
(4,4,gfx\\sgc\\月仙_月华乱舞_击中.sgc)
}
skill: 2582
{
(1,1,gfx\\sgc\\月仙_蜓水引_击中.sgc),
(2,2,gfx\\sgc\\月仙_蜓水引_击中.sgc),
(3,3,gfx\\sgc\\月仙_蜓水引_击中.sgc)
}
skill: 2557
{
(1,1,gfx\\sgc\\夜影_定风波_击中.sgc),
(2,2,gfx\\sgc\\夜影_定风波_击中.sgc),
(3,3,gfx\\sgc\\夜影_定风波_击中.sgc),
(4,4,gfx\\sgc\\夜影_定风波_击中.sgc)
}
skill: 2558
{
(1,1,gfx\\sgc\\夜影_影狩_击中.sgc),
(2,2,gfx\\sgc\\夜影_影狩_击中.sgc)
}
skill: 2567
{
(1,1,gfx\\sgc\\夜影_恨天_击中.sgc),
(2,2,gfx\\sgc\\夜影_恨天_击中.sgc),
(3,3,gfx\\sgc\\夜影_恨天_击中.sgc)
}
skill: 2568
{
(1,1,gfx\\sgc\\夜影_苍鸟_击中01.sgc),
(2,2,gfx\\sgc\\夜影_苍鸟_击中02.sgc)
}
skill: 2551
{
(1,1,gfx\\sgc\\夜影_狱龙牙_击中.sgc),
(2,2,gfx\\sgc\\夜影_狱龙牙_击中.sgc),
(3,3,gfx\\sgc\\夜影_狱龙牙_击中.sgc),
(4,4,gfx\\sgc\\夜影_狱龙牙_击中.sgc)
}
skill: 2775
{
(1,1,gfx\\sgc\\夜影_狱龙牙_击中.sgc),
(2,2,gfx\\sgc\\夜影_狱龙牙_击中.sgc),
(3,3,gfx\\sgc\\夜影_狱龙牙_击中.sgc),
(4,4,gfx\\sgc\\夜影_狱龙牙_击中.sgc)
}
skill: 2821
{
(1,1,gfx\\sgc\\夜影_狱龙牙_击中.sgc),
(2,2,gfx\\sgc\\夜影_狱龙牙_击中.sgc),
(3,3,gfx\\sgc\\夜影_狱龙牙_击中.sgc),
(4,4,gfx\\sgc\\夜影_狱龙牙_击中.sgc)
}
skill: 2768
{
(1,1,gfx\\sgc\\夜影_苍鸟_击中01.sgc),
(2,2,gfx\\sgc\\夜影_苍鸟_击中02.sgc)
}
skill: 2769
{
(1,1,gfx\\sgc\\夜影_苍鸟_击中01.sgc),
(2,2,gfx\\sgc\\夜影_苍鸟_击中02.sgc)
}
skill: 2811
{
(1,1,gfx\\sgc\\月仙_月华乱舞_击中.sgc),
(2,2,gfx\\sgc\\月仙_月华乱舞_击中.sgc),
(3,3,gfx\\sgc\\月仙_月华乱舞_击中.sgc),
(4,4,gfx\\sgc\\月仙_月华乱舞_击中.sgc)
}
skill: 2812
{
(1,1,gfx\\sgc\\月仙_月华乱舞_击中.sgc),
(2,2,gfx\\sgc\\月仙_月华乱舞_击中.sgc),
(3,3,gfx\\sgc\\月仙_月华乱舞_击中.sgc),
(4,4,gfx\\sgc\\月仙_月华乱舞_击中.sgc)
}
skill: 2793
{
(1,1,gfx\\sgc\\月仙_蜓水引_击中.sgc),
(2,2,gfx\\sgc\\月仙_蜓水引_击中.sgc),
(3,3,gfx\\sgc\\月仙_蜓水引_击中.sgc)
}
skill: 2794
{
(1,1,gfx\\sgc\\月仙_蜓水引_击中.sgc),
(2,2,gfx\\sgc\\月仙_蜓水引_击中.sgc),
(3,3,gfx\\sgc\\月仙_蜓水引_击中.sgc)
}
skill: 2736
{
(1,1,gfx\\sgc\\夜影_狱龙牙_击中.sgc),
(2,2,gfx\\sgc\\夜影_狱龙牙_击中.sgc),
(3,3,gfx\\sgc\\夜影_狱龙牙_击中.sgc),
(4,4,gfx\\sgc\\夜影_狱龙牙_击中.sgc)
}
skill: 2737
{
(1,1,gfx\\sgc\\夜影_狱龙牙_击中.sgc),
(2,2,gfx\\sgc\\夜影_狱龙牙_击中.sgc),
(3,3,gfx\\sgc\\夜影_狱龙牙_击中.sgc),
(4,4,gfx\\sgc\\夜影_狱龙牙_击中.sgc)
}
skill: 2748
{
(1,1,gfx\\sgc\\夜影_定风波_击中.sgc),
(2,2,gfx\\sgc\\夜影_定风波_击中.sgc),
(3,3,gfx\\sgc\\夜影_定风波_击中.sgc),
(4,4,gfx\\sgc\\夜影_定风波_击中.sgc)
}
skill: 2749
{
(1,1,gfx\\sgc\\夜影_定风波_击中.sgc),
(2,2,gfx\\sgc\\夜影_定风波_击中.sgc),
(3,3,gfx\\sgc\\夜影_定风波_击中.sgc),
(4,4,gfx\\sgc\\夜影_定风波_击中.sgc)
}
skill: 2750
{
(1,1,gfx\\sgc\\夜影_影狩_击中.sgc),
(2,2,gfx\\sgc\\夜影_影狩_击中.sgc)
}
skill: 2751
{
(1,1,gfx\\sgc\\夜影_影狩_击中.sgc),
(2,2,gfx\\sgc\\夜影_影狩_击中.sgc)
}
skill: 2766
{
(1,1,gfx\\sgc\\夜影_恨天_击中.sgc),
(2,2,gfx\\sgc\\夜影_恨天_击中.sgc),
(3,3,gfx\\sgc\\夜影_恨天_击中.sgc)
}
skill: 2767
{
(1,1,gfx\\sgc\\夜影_恨天_击中.sgc),
(2,2,gfx\\sgc\\夜影_恨天_击中.sgc),
(3,3,gfx\\sgc\\夜影_恨天_击中.sgc)
}
skill: 2905
{
(1,1,gfx\\sgc\\夜影_影狩_击中.sgc),
(2,2,gfx\\sgc\\夜影_影狩_击中.sgc)
}
skill: 2906
{
(1,1,gfx\\sgc\\夜影_影狩_击中.sgc),
(2,2,gfx\\sgc\\夜影_影狩_击中.sgc)
}
skill: 2922
{
(1,1,gfx\\sgc\\夜影_狱龙牙_击中.sgc),
(2,2,gfx\\sgc\\夜影_狱龙牙_击中.sgc),
(3,3,gfx\\sgc\\夜影_狱龙牙_击中.sgc),
(4,4,gfx\\sgc\\夜影_狱龙牙_击中.sgc)
}
skill: 2923
{
(1,1,gfx\\sgc\\夜影_狱龙牙_击中.sgc),
(2,2,gfx\\sgc\\夜影_狱龙牙_击中.sgc),
(3,3,gfx\\sgc\\夜影_狱龙牙_击中.sgc),
(4,4,gfx\\sgc\\夜影_狱龙牙_击中.sgc)
}
skill: 2901
{
(1,1,gfx\\sgc\\夜影_恨天_击中.sgc),
(2,2,gfx\\sgc\\夜影_恨天_击中.sgc),
(3,3,gfx\\sgc\\夜影_恨天_击中.sgc)
}
skill: 2902
{
(1,1,gfx\\sgc\\夜影_恨天_击中.sgc),
(2,2,gfx\\sgc\\夜影_恨天_击中.sgc),
(3,3,gfx\\sgc\\夜影_恨天_击中.sgc)
}
skill: 2913
{
(1,1,gfx\\sgc\\月仙_月华乱舞_击中.sgc),
(2,2,gfx\\sgc\\月仙_月华乱舞_击中.sgc),
(3,3,gfx\\sgc\\月仙_月华乱舞_击中.sgc),
(4,4,gfx\\sgc\\月仙_月华乱舞_击中.sgc)
}
skill: 2914
{
(1,1,gfx\\sgc\\月仙_月华乱舞_击中.sgc),
(2,2,gfx\\sgc\\月仙_月华乱舞_击中.sgc),
(3,3,gfx\\sgc\\月仙_月华乱舞_击中.sgc),
(4,4,gfx\\sgc\\月仙_月华乱舞_击中.sgc)
}
skill: 3284
{
(1,1,gfx\\sgc\\夜影_定风波_击中.sgc),
(2,2,gfx\\sgc\\夜影_定风波_击中.sgc),
(3,3,gfx\\sgc\\夜影_定风波_击中.sgc),
(4,4,gfx\\sgc\\夜影_定风波_击中.sgc)
}
skill: 3285
{
(1,1,gfx\\sgc\\夜影_定风波_击中.sgc),
(2,2,gfx\\sgc\\夜影_定风波_击中.sgc),
(3,3,gfx\\sgc\\夜影_定风波_击中.sgc),
(4,4,gfx\\sgc\\夜影_定风波_击中.sgc)
}
skill: 3217
{
(1,1,gfx\\sgc\\妖精_粉色落.sgc),
(2,2,gfx\\sgc\\妖精_橘色落.sgc),
(3,3,gfx\\sgc\\妖精_白蓝色落.sgc),
(4,4,gfx\\sgc\\妖精_黄色落.sgc),
(5,5,gfx\\sgc\\妖精_蓝紫色落.sgc)
}
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: f219fd5cb4f73c944bedb14e6d305c8d
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+6 -6
View File
@@ -129,32 +129,32 @@ namespace BrewMonster
private void OnMsgHstHurtResult(ECMSG Msg)
{
//BMLogger.LogError("HoangDev : OnMsgHstHurtResult");
/* int cmd = Convert.ToInt32(Msg.dwParam2);
int cmd = Convert.ToInt32(Msg.dwParam2);
if (cmd == CommandID.BE_HURT)
{
cmd_be_hurt pCmd = (cmd_be_hurt)Msg.dwParam1;
cmd_be_hurt pCmd = GPDataTypeHelper.FromBytes<cmd_be_hurt>((byte[])Msg.dwParam1 );
if (pCmd.damage != 0)
Damaged(pCmd.damage);
}
else if (cmd == CommandID.HURT_RESULT)
{
cmd_hurt_result pCmd = (cmd_hurt_result)Msg.dwParam1;
cmd_hurt_result pCmd = GPDataTypeHelper.FromBytes<cmd_hurt_result>((byte[])Msg.dwParam1 );
if (pCmd.target_id == m_PlayerInfo.cid)
return; // Host himself will receive BE_HURT, so ignore this.
if (UnityGameSession.Instance.GameSession.ISPLAYERID(pCmd.target_id))
{
CECElsePlayer pTarget = m_pPlayerMan.GetElsePlayer(pCmd.target_id);
EC_ElsePlayer pTarget = m_pPlayerMan.GetElsePlayer(pCmd.target_id);
if (pTarget)
pTarget.Damaged(pCmd.damage);
}
else if (UnityGameSession.Instance.GameSession.ISNPCID(pCmd.target_id))
{
CECNPC pTarget = EC_ManMessageMono.Instance._CECNPCMan.GetNPC(pCmd.target_id);
CECNPC pTarget = EC_ManMessageMono.Instance.CECNPCMan.GetNPC(pCmd.target_id);
if (pTarget)
pTarget.Damaged(pCmd.damage);
}
}*/
}
}
private void OnMsgHstStartAttack(in ECMSG Msg)
+3 -2
View File
@@ -145,6 +145,7 @@ public partial class CECGameRun : ITickable
{
BMLogger.LogWarning("CECGameRun::LoadPrefabs, Loading prefabs from Resources. Consider using Addressables for better performance and memory management.");
_playerPrefab = Resources.Load<GameObject>(AddressResourceConfig.PlayerPrefab);
PrefabPoolManager.Instance.InitPool(_playerPrefab);
_monsterPrefab = Resources.Load<GameObject>(AddressResourceConfig.MonsterPrefab);
PrefabPoolManager.Instance.InitPool(_monsterPrefab, defaultCapacity: 200, maxSize: 250);
_npcServerPrefab = Resources.Load<GameObject>(AddressResourceConfig.NpcServerPrefab);
@@ -386,7 +387,7 @@ public partial class CECGameRun : ITickable
}
CECPlayer.InitStaticRes();
m_pHostPlayer = ObjectSpawner.Instance.InstantiateObject(_playerPrefab, setThisAsParent: true).AddComponent<CECHostPlayer>();
m_pHostPlayer = PrefabPoolManager.Instance.Spawn(_playerPrefab, Vector3.zero, Quaternion.identity, ObjectSpawner.Instance.transform).AddComponent<CECHostPlayer>();
m_pHostPlayer.InitCharacter(info);
if (m_pHostPlayer != null)
@@ -453,7 +454,7 @@ public partial class CECGameRun : ITickable
Debug.LogError("null prefab");
return null;
}
GameObject character = ObjectSpawner.Instance.InstantiateObject(_playerPrefab, setThisAsParent: true);
GameObject character = PrefabPoolManager.Instance.Spawn(_playerPrefab, Vector3.zero, Quaternion.identity, ObjectSpawner.Instance.transform);
return character.gameObject;
}
+36 -30
View File
@@ -46,20 +46,27 @@ namespace BrewMonster
}
if (_animationQueue.Count > 0)
{
_animationQueue.Enqueue(new AnimationQueue
if(@event.IsForceStopPrevious)
{
AnimationName = @event.AnimationName,
IsForceStopPrevious = @event.IsForceStopPrevious,
AttackEvent = @event.AttackEvent,
ChannelAct = @event.ChannelAct,
Rank = @event.Rank
});
_animationList = _animationQueue.Select(q => q.AnimationName).ToList();
return;
_animationQueue.Clear();
}
else
{
_animationQueue.Enqueue(new AnimationQueue
{
AnimationName = @event.AnimationName,
IsForceStopPrevious = @event.IsForceStopPrevious,
AttackEvent = @event.AttackEvent,
ChannelAct = @event.ChannelAct,
Rank = @event.Rank
});
_animationList = _animationQueue.Select(q => q.AnimationName).ToList();
return;
}
}
previousAnimationName = @event.AnimationName;
InternalPlayAnimation(@event.AnimationName, @event.ITransTime, FadeMode, @event.IsLoop);
ApplyAnimationEndCallbacks(@event.AttackEvent, @event.ChannelAct, @event.Rank, @event.AnimationName);
InternalPlayAnimation(@event.AnimationName, @event.ITransTime, FadeMode);
ApplyAnimationEndCallbacks(@event.AttackEvent, @event.ChannelAct, @event.Rank, @event.AnimationName, @event.IsLoop);
}
public void InitPlayerEventDoneHandler()
{
@@ -195,6 +202,7 @@ namespace BrewMonster
AttackEvent = null,
IsLoop = true
});
Debug.Log($"EnqueueAnimationForLooping: {animationName}, _animationQueue: {string.Join(", ", _animationList)}");
_animationList = _animationQueue.Select(q => q.AnimationName).ToList();
return true;
}
@@ -205,14 +213,6 @@ namespace BrewMonster
{
return;
}
else
{
string animationQueueString = "";
foreach(var animation in _animationQueue)
{
animationQueueString += animation.AnimationName + ", ";
}
}
if (_animationQueue.Peek().IsForceStopPrevious)
{
@@ -227,21 +227,26 @@ namespace BrewMonster
var animationQueue = _animationQueue.Dequeue();
_animationList = _animationQueue.Select(q => q.AnimationName).ToList();
previousAnimationName = animationQueue.AnimationName;
InternalPlayAnimation(animationQueue.AnimationName, animationQueue.ITransTime, FadeMode, animationQueue.IsLoop);
ApplyAnimationEndCallbacks(animationQueue.AttackEvent, animationQueue.ChannelAct, animationQueue.Rank, animationQueue.AnimationName);
InternalPlayAnimation(animationQueue.AnimationName, animationQueue.ITransTime, FadeMode);
ApplyAnimationEndCallbacks(animationQueue.AttackEvent, animationQueue.ChannelAct, animationQueue.Rank, animationQueue.AnimationName,animationQueue.IsLoop);
}
private void ApplyAnimationEndCallbacks(CECAttackEvent attackEvent, ChannelAct channelAct, int rank, string animationName)
private void ApplyAnimationEndCallbacks(CECAttackEvent attackEvent, ChannelAct channelAct, int rank, string animationName, bool isLoop)
{
if (_currentState == null) return;
_currentState.Events.OnEnd = () =>
{
if (attackEvent != null)
attackEvent.m_bSignaled = true;
if(isLoop)
{
EnqueueAnimationForLooping(animationName);
}
if (channelAct == null || string.IsNullOrEmpty(animationName))
return;
var node = channelAct.GetNodeByRank((byte)rank);
node?.m_pActive?.m_ActionNames?.Remove(animationName);
};
}
void ApplyDamage()
@@ -258,6 +263,12 @@ namespace BrewMonster
{
UnregisterPlayerEventHandlers();
}
private void OnDisable()
{
UnregisterPlayerEventHandlers();
}
public bool IsAnimationExist(string animationName)
{
var exists = namedAnimancer.States.TryGet("ActionName", out var existingState) ? true : false;
@@ -271,7 +282,7 @@ namespace BrewMonster
/// <param name="animationName"></param>
/// <param name="duration"></param>
/// <param name="fadeMode"></param>
private void InternalPlayAnimation(string animationName, float duration = FadeTime, FadeMode fadeMode = FadeMode, bool isLoop = false)
private void InternalPlayAnimation(string animationName, float duration = FadeTime, FadeMode fadeMode = FadeMode)
{
if (namedAnimancer == null)
{
@@ -281,13 +292,8 @@ namespace BrewMonster
if (isState)
{
_currentState = namedAnimancer.TryPlay(animationName, duration / 1000, fadeMode);
_currentState.Time = 0;
_currentAnimationName = animationName;
//if the animation is looping and the current state is not looping, play the animation again
if(isLoop == true && _currentState.IsLooping == false)
{
_currentState.Time = 0;
_currentState.Events.OnEnd = () => EnqueueAnimationForLooping(animationName);
}
return;
}
//BMLogger.LogError($"Null name animation: {animationName}");
@@ -395,4 +401,4 @@ namespace BrewMonster
return true;
}
}
}
}
+1 -1
View File
@@ -26,7 +26,7 @@ MonoBehaviour:
m_SupportsHDR: 1
m_HDRColorBufferPrecision: 0
m_MSAA: 1
m_RenderScale: 0.7
m_RenderScale: 0.6
m_UpscalingFilter: 0
m_FsrOverrideSharpness: 0
m_FsrSharpness: 0.92