diff --git a/Assets/PerfectWorld/Prefab/Task/UI/DlgTask.prefab b/Assets/PerfectWorld/Prefab/Task/UI/DlgTask.prefab index 4fab5c1a01..f16454c889 100644 --- a/Assets/PerfectWorld/Prefab/Task/UI/DlgTask.prefab +++ b/Assets/PerfectWorld/Prefab/Task/UI/DlgTask.prefab @@ -3644,42 +3644,6 @@ MonoBehaviour: m_hasFontAssetChanged: 0 m_baseMaterial: {fileID: 0} m_maskOffset: {x: 0, y: 0, z: 0, w: 0} ---- !u!1 &3394019089264214037 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 5233116975597807035} - m_Layer: 5 - m_Name: Sliding Area - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!224 &5233116975597807035 -RectTransform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 3394019089264214037} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: - - {fileID: 2343337405992641122} - m_Father: {fileID: 4269318562826283412} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 0} - m_AnchorMax: {x: 1, y: 1} - m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: -20, y: -20} - m_Pivot: {x: 0.5, y: 0.5} --- !u!1 &3400309995061149671 GameObject: m_ObjectHideFlags: 0 @@ -4526,7 +4490,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: - {fileID: 3841808193842114691} - - {fileID: 4269318562826283412} m_Father: {fileID: 3413131598704007284} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} @@ -4594,9 +4557,9 @@ MonoBehaviour: m_ScrollSensitivity: 1 m_Viewport: {fileID: 3841808193842114691} m_HorizontalScrollbar: {fileID: 0} - m_VerticalScrollbar: {fileID: 8166044353254338} + m_VerticalScrollbar: {fileID: 0} m_HorizontalScrollbarVisibility: 2 - m_VerticalScrollbarVisibility: 2 + m_VerticalScrollbarVisibility: 1 m_HorizontalScrollbarSpacing: -3 m_VerticalScrollbarSpacing: -3 m_OnValueChanged: @@ -6441,9 +6404,9 @@ RectTransform: m_Father: {fileID: 3760164886363293420} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} - m_AnchorMax: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: 0, y: 0} + m_SizeDelta: {x: -17, y: 0} m_Pivot: {x: 0, y: 1} --- !u!222 &5693552902337398956 CanvasRenderer: @@ -6496,132 +6459,6 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: m_ShowMaskGraphic: 0 ---- !u!1 &6215509840863176641 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 4269318562826283412} - - component: {fileID: 3156760942193843661} - - component: {fileID: 5649692143959903235} - - component: {fileID: 8166044353254338} - m_Layer: 5 - m_Name: Scrollbar Vertical - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!224 &4269318562826283412 -RectTransform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6215509840863176641} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: - - {fileID: 5233116975597807035} - m_Father: {fileID: 3760164886363293420} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 1, y: 0} - m_AnchorMax: {x: 1, y: 1} - m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: 20, y: -17} - m_Pivot: {x: 1, y: 1} ---- !u!222 &3156760942193843661 -CanvasRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6215509840863176641} - m_CullTransparentMesh: 1 ---- !u!114 &5649692143959903235 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6215509840863176641} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, 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_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0} - m_Type: 1 - m_PreserveAspect: 0 - m_FillCenter: 1 - m_FillMethod: 4 - m_FillAmount: 1 - m_FillClockwise: 1 - m_FillOrigin: 0 - m_UseSpriteMesh: 0 - m_PixelsPerUnitMultiplier: 1 ---- !u!114 &8166044353254338 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6215509840863176641} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 2a4db7a114972834c8e4117be1d82ba3, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Navigation: - m_Mode: 3 - m_WrapAround: 0 - m_SelectOnUp: {fileID: 0} - m_SelectOnDown: {fileID: 0} - m_SelectOnLeft: {fileID: 0} - m_SelectOnRight: {fileID: 0} - m_Transition: 1 - m_Colors: - m_NormalColor: {r: 1, g: 1, b: 1, a: 1} - m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} - m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} - m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} - m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} - m_ColorMultiplier: 1 - m_FadeDuration: 0.1 - m_SpriteState: - m_HighlightedSprite: {fileID: 0} - m_PressedSprite: {fileID: 0} - m_SelectedSprite: {fileID: 0} - m_DisabledSprite: {fileID: 0} - m_AnimationTriggers: - m_NormalTrigger: Normal - m_HighlightedTrigger: Highlighted - m_PressedTrigger: Pressed - m_SelectedTrigger: Selected - m_DisabledTrigger: Disabled - m_Interactable: 1 - m_TargetGraphic: {fileID: 7392889747821849613} - m_HandleRect: {fileID: 2343337405992641122} - m_Direction: 2 - m_Value: 1 - m_Size: 0.5000001 - m_NumberOfSteps: 0 - m_OnValueChanged: - m_PersistentCalls: - m_Calls: [] --- !u!1 &6529812165440442340 GameObject: m_ObjectHideFlags: 0 @@ -6959,81 +6796,6 @@ MonoBehaviour: m_OnClick: m_PersistentCalls: m_Calls: [] ---- !u!1 &6825428412888061072 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 2343337405992641122} - - component: {fileID: 1253204253337680264} - - component: {fileID: 7392889747821849613} - m_Layer: 5 - m_Name: Handle - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!224 &2343337405992641122 -RectTransform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6825428412888061072} - 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: 5233116975597807035} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 0} - m_AnchorMax: {x: 0, y: 0} - m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: 20, y: 20} - m_Pivot: {x: 0.5, y: 0.5} ---- !u!222 &1253204253337680264 -CanvasRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6825428412888061072} - m_CullTransparentMesh: 1 ---- !u!114 &7392889747821849613 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6825428412888061072} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, 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_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} - m_Type: 1 - m_PreserveAspect: 0 - m_FillCenter: 1 - m_FillMethod: 4 - m_FillAmount: 1 - m_FillClockwise: 1 - m_FillOrigin: 0 - m_UseSpriteMesh: 0 - m_PixelsPerUnitMultiplier: 1 --- !u!1 &6853716367817320825 GameObject: m_ObjectHideFlags: 0 @@ -8864,7 +8626,7 @@ PrefabInstance: objectReference: {fileID: 0} - target: {fileID: 8395333742829132721, guid: 9456de25596014039bd4d0d3927b709a, type: 3} propertyPath: m_AnchoredPosition.y - value: 191.5136 + value: 336.93 objectReference: {fileID: 0} - target: {fileID: 8395333742829132721, guid: 9456de25596014039bd4d0d3927b709a, type: 3} propertyPath: m_LocalEulerAnglesHint.x diff --git a/Assets/PerfectWorld/Prefab/Task/UI/TreeViewItem.prefab b/Assets/PerfectWorld/Prefab/Task/UI/TreeViewItem.prefab index c399ff8ffc..bdaed314ee 100644 --- a/Assets/PerfectWorld/Prefab/Task/UI/TreeViewItem.prefab +++ b/Assets/PerfectWorld/Prefab/Task/UI/TreeViewItem.prefab @@ -10,8 +10,8 @@ GameObject: m_Component: - component: {fileID: 5053903421260846465} - component: {fileID: 4314770845850481090} - - component: {fileID: 4762263782091224632} - component: {fileID: 4986645933044111193} + - component: {fileID: 1062363862839909147} m_Layer: 5 m_Name: TreeViewItem m_TagString: Untagged @@ -31,7 +31,7 @@ RectTransform: m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: - - {fileID: 3882154025378162395} + - {fileID: 2024997316782034639} m_Father: {fileID: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} @@ -51,19 +51,36 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 3428dd2e9dd644e0b0cb408bd3202f21, type: 3} m_Name: m_EditorClassIdentifier: - m_text: {fileID: 1383932928540251694} + m_text: + legacy: {fileID: 0} + tmp: {fileID: 1383932928540251694} m_Button: {fileID: 1762532130762754577} - _levelSprites: - - {fileID: 21300000, guid: e09a5d2cb3c3f4c858754a1e90a44abd, type: 3} - - {fileID: 21300000, guid: 73873399fec964578b62204f20c40517, type: 3} - _expandButton: {fileID: 1715406348461528812} - _collapseButton: {fileID: 8676942769405651249} + _expandToggle: {fileID: 5502308808383608272} + _expandText: + legacy: {fileID: 0} + tmp: {fileID: 8373064842616042426} + _space: {fileID: 5541755240357469011} m_uItemData: 0 _treeLevel: 0 + isLastItem: 0 OnClick: m_PersistentCalls: m_Calls: [] ---- !u!114 &4762263782091224632 +--- !u!114 &4986645933044111193 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 700152255263326765} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 3245ec927659c4140ac4f8d17403cc18, type: 3} + m_Name: + m_EditorClassIdentifier: + m_HorizontalFit: 0 + m_VerticalFit: 1 +--- !u!114 &1062363862839909147 MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -82,27 +99,13 @@ MonoBehaviour: m_Bottom: 0 m_ChildAlignment: 0 m_Spacing: 0 - m_ChildForceExpandWidth: 0 - m_ChildForceExpandHeight: 0 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 1 m_ChildControlWidth: 0 m_ChildControlHeight: 0 m_ChildScaleWidth: 0 m_ChildScaleHeight: 0 m_ReverseArrangement: 0 ---- !u!114 &4986645933044111193 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 700152255263326765} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 3245ec927659c4140ac4f8d17403cc18, type: 3} - m_Name: - m_EditorClassIdentifier: - m_HorizontalFit: 0 - m_VerticalFit: 2 --- !u!1 &2040002976300010419 GameObject: m_ObjectHideFlags: 0 @@ -115,6 +118,7 @@ GameObject: - component: {fileID: 2230410216357545400} - component: {fileID: 9062463037674165507} - component: {fileID: 1762532130762754577} + - component: {fileID: 4801006375863435037} m_Layer: 5 m_Name: MainButton m_TagString: Untagged @@ -129,20 +133,18 @@ RectTransform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 2040002976300010419} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: - {fileID: 5827054231092576763} - - {fileID: 7277676979067820762} - - {fileID: 2849245307131571463} - m_Father: {fileID: 5053903421260846465} + m_Father: {fileID: 2024997316782034639} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: 313, y: 91} + m_SizeDelta: {x: 0, y: 0} m_Pivot: {x: 0.5, y: 0.5} --- !u!222 &2230410216357545400 CanvasRenderer: @@ -165,14 +167,14 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: m_Material: {fileID: 0} - m_Color: {r: 1, g: 1, b: 1, a: 1} + m_Color: {r: 1, g: 1, b: 1, a: 0.011764706} m_RaycastTarget: 1 m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} m_Maskable: 1 m_OnCullStateChanged: m_PersistentCalls: m_Calls: [] - m_Sprite: {fileID: 21300000, guid: e09a5d2cb3c3f4c858754a1e90a44abd, type: 3} + m_Sprite: {fileID: 0} m_Type: 0 m_PreserveAspect: 0 m_FillCenter: 1 @@ -226,6 +228,26 @@ MonoBehaviour: m_OnClick: m_PersistentCalls: m_Calls: [] +--- !u!114 &4801006375863435037 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2040002976300010419} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 306cc8c2b49d7114eaa3623786fc2126, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreLayout: 0 + m_MinWidth: 0 + m_MinHeight: -1 + m_PreferredWidth: -1 + m_PreferredHeight: -1 + m_FlexibleWidth: 0.5 + m_FlexibleHeight: -1 + m_LayoutPriority: 2 --- !u!1 &2916175606199835458 GameObject: m_ObjectHideFlags: 0 @@ -261,8 +283,8 @@ RectTransform: m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} - m_AnchoredPosition: {x: 0, y: 3.5497} - m_SizeDelta: {x: 0, y: -7.0993} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0.00000023841858} m_Pivot: {x: 0.5, y: 0.5} --- !u!222 &5842649278580849339 CanvasRenderer: @@ -319,14 +341,14 @@ MonoBehaviour: m_faceColor: serializedVersion: 2 rgba: 4294967295 - m_fontSize: 40 - m_fontSizeBase: 40 + m_fontSize: 24 + m_fontSizeBase: 24 m_fontWeight: 400 - m_enableAutoSizing: 1 + m_enableAutoSizing: 0 m_fontSizeMin: 15 m_fontSizeMax: 40 m_fontStyle: 0 - m_HorizontalAlignment: 2 + m_HorizontalAlignment: 1 m_VerticalAlignment: 512 m_textAlignment: 65535 m_characterSpacing: 0 @@ -383,7 +405,7 @@ MonoBehaviour: m_FlexibleWidth: -1 m_FlexibleHeight: -1 m_LayoutPriority: 1 ---- !u!1 &4773363917894322918 +--- !u!1 &6587684749681441909 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -391,133 +413,184 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 2849245307131571463} - - component: {fileID: 8656005255261122099} - - component: {fileID: 9103345587361145036} - - component: {fileID: 8676942769405651249} - - component: {fileID: 2374156541160748953} + - component: {fileID: 5062486824527634889} + - component: {fileID: 7099288759002186546} + - component: {fileID: 8373064842616042426} m_Layer: 5 - m_Name: CollapseBtn + m_Name: Text (TMP) m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!224 &2849245307131571463 +--- !u!224 &5062486824527634889 RectTransform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4773363917894322918} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_GameObject: {fileID: 6587684749681441909} + 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_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] - m_Father: {fileID: 3882154025378162395} + m_Father: {fileID: 7277676979067820762} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 0.5} - m_AnchorMax: {x: 0, y: 0.5} - m_AnchoredPosition: {x: 156.5, y: 3.5497} - m_SizeDelta: {x: 313, y: 83.901} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: -0.00048828125, y: 0} + m_SizeDelta: {x: 40.883, y: 40} m_Pivot: {x: 0.5, y: 0.5} ---- !u!222 &8656005255261122099 +--- !u!222 &7099288759002186546 CanvasRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4773363917894322918} + m_GameObject: {fileID: 6587684749681441909} m_CullTransparentMesh: 1 ---- !u!114 &9103345587361145036 +--- !u!114 &8373064842616042426 MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4773363917894322918} + m_GameObject: {fileID: 6587684749681441909} m_Enabled: 1 m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} m_Name: m_EditorClassIdentifier: m_Material: {fileID: 0} - m_Color: {r: 1, g: 1, b: 1, a: 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_Sprite: {fileID: 21300000, guid: 9de07872267c5419b9fa9c849eb45858, type: 3} - m_Type: 0 - m_PreserveAspect: 0 - m_FillCenter: 1 - m_FillMethod: 4 - m_FillAmount: 1 - m_FillClockwise: 1 - m_FillOrigin: 0 - m_UseSpriteMesh: 0 - m_PixelsPerUnitMultiplier: 1 ---- !u!114 &8676942769405651249 + m_text: + + 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: 36 + m_fontSizeBase: 36 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_HorizontalAlignment: 2 + 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: 1 + 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: 1 + 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 + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!1 &6592915584227539970 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2930138263853700511} + - component: {fileID: 5541755240357469011} + m_Layer: 5 + m_Name: Space + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &2930138263853700511 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6592915584227539970} + 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: 2024997316782034639} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &5541755240357469011 MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4773363917894322918} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Navigation: - m_Mode: 0 - m_WrapAround: 0 - m_SelectOnUp: {fileID: 0} - m_SelectOnDown: {fileID: 0} - m_SelectOnLeft: {fileID: 0} - m_SelectOnRight: {fileID: 0} - m_Transition: 1 - m_Colors: - m_NormalColor: {r: 1, g: 1, b: 1, a: 1} - m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} - m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} - m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} - m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} - m_ColorMultiplier: 1 - m_FadeDuration: 0.1 - m_SpriteState: - m_HighlightedSprite: {fileID: 0} - m_PressedSprite: {fileID: 0} - m_SelectedSprite: {fileID: 0} - m_DisabledSprite: {fileID: 0} - m_AnimationTriggers: - m_NormalTrigger: Normal - m_HighlightedTrigger: Highlighted - m_PressedTrigger: Pressed - m_SelectedTrigger: Selected - m_DisabledTrigger: Disabled - m_Interactable: 1 - m_TargetGraphic: {fileID: 9103345587361145036} - m_OnClick: - m_PersistentCalls: - m_Calls: [] ---- !u!114 &2374156541160748953 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4773363917894322918} + m_GameObject: {fileID: 6592915584227539970} m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 306cc8c2b49d7114eaa3623786fc2126, type: 3} m_Name: m_EditorClassIdentifier: - m_IgnoreLayout: 1 - m_MinWidth: -1 + m_IgnoreLayout: 0 + m_MinWidth: 0 m_MinHeight: -1 m_PreferredWidth: -1 m_PreferredHeight: -1 @@ -535,10 +608,10 @@ GameObject: - component: {fileID: 7277676979067820762} - component: {fileID: 885853373149276158} - component: {fileID: 1569122208421759741} - - component: {fileID: 1715406348461528812} - - component: {fileID: 9213068811979301399} + - component: {fileID: 5502308808383608272} + - component: {fileID: 8681673894369501558} m_Layer: 5 - m_Name: ExpandBtn + m_Name: ExpandToggle m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 @@ -555,13 +628,14 @@ RectTransform: m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 3882154025378162395} + m_Children: + - {fileID: 5062486824527634889} + m_Father: {fileID: 2024997316782034639} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 0.5} - m_AnchorMax: {x: 0, y: 0.5} - m_AnchoredPosition: {x: 156.5, y: 3.5497} - m_SizeDelta: {x: 313, y: 83.901} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} m_Pivot: {x: 0.5, y: 0.5} --- !u!222 &885853373149276158 CanvasRenderer: @@ -591,7 +665,7 @@ MonoBehaviour: m_OnCullStateChanged: m_PersistentCalls: m_Calls: [] - m_Sprite: {fileID: 0} + m_Sprite: {fileID: 252815192406529888, guid: a141ce1b94af3cf46aa0695ab5ed6cdd, type: 3} m_Type: 0 m_PreserveAspect: 0 m_FillCenter: 1 @@ -601,7 +675,7 @@ MonoBehaviour: m_FillOrigin: 0 m_UseSpriteMesh: 0 m_PixelsPerUnitMultiplier: 1 ---- !u!114 &1715406348461528812 +--- !u!114 &5502308808383608272 MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -610,11 +684,11 @@ MonoBehaviour: m_GameObject: {fileID: 6863650808120944178} m_Enabled: 1 m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} + m_Script: {fileID: 11500000, guid: 9085046f02f69544eb97fd06b6048fe2, type: 3} m_Name: m_EditorClassIdentifier: m_Navigation: - m_Mode: 0 + m_Mode: 3 m_WrapAround: 0 m_SelectOnUp: {fileID: 0} m_SelectOnDown: {fileID: 0} @@ -642,10 +716,14 @@ MonoBehaviour: m_DisabledTrigger: Disabled m_Interactable: 1 m_TargetGraphic: {fileID: 1569122208421759741} - m_OnClick: + toggleTransition: 1 + graphic: {fileID: 0} + m_Group: {fileID: 0} + onValueChanged: m_PersistentCalls: m_Calls: [] ---- !u!114 &9213068811979301399 + m_IsOn: 0 +--- !u!114 &8681673894369501558 MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -657,11 +735,76 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 306cc8c2b49d7114eaa3623786fc2126, type: 3} m_Name: m_EditorClassIdentifier: - m_IgnoreLayout: 1 + m_IgnoreLayout: 0 m_MinWidth: -1 m_MinHeight: -1 - m_PreferredWidth: -1 - m_PreferredHeight: -1 + m_PreferredWidth: 40 + m_PreferredHeight: 40 m_FlexibleWidth: -1 m_FlexibleHeight: -1 m_LayoutPriority: 1 +--- !u!1 &7973684205123875483 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2024997316782034639} + - component: {fileID: 6485915084394087119} + m_Layer: 5 + m_Name: MainContent + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &2024997316782034639 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7973684205123875483} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 2930138263853700511} + - {fileID: 7277676979067820762} + - {fileID: 3882154025378162395} + m_Father: {fileID: 5053903421260846465} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 400, y: 40} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &6485915084394087119 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7973684205123875483} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 30649d3a9faa99c48a7b1166b86bf2a0, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_ChildAlignment: 0 + m_Spacing: 0 + m_ChildForceExpandWidth: 0 + m_ChildForceExpandHeight: 1 + m_ChildControlWidth: 1 + m_ChildControlHeight: 1 + m_ChildScaleWidth: 1 + m_ChildScaleHeight: 1 + m_ReverseArrangement: 0 diff --git a/Assets/PerfectWorld/Resources/UI/Login/载入1280-15.jpg b/Assets/PerfectWorld/Resources/UI/Login/载入1280-15.jpg new file mode 100644 index 0000000000..637d40be2d Binary files /dev/null and b/Assets/PerfectWorld/Resources/UI/Login/载入1280-15.jpg differ diff --git a/Assets/PerfectWorld/UI/TaskIcon/TuChan.png.meta b/Assets/PerfectWorld/Resources/UI/Login/载入1280-15.jpg.meta similarity index 92% rename from Assets/PerfectWorld/UI/TaskIcon/TuChan.png.meta rename to Assets/PerfectWorld/Resources/UI/Login/载入1280-15.jpg.meta index 7bc9174a94..ecf32c16f9 100644 --- a/Assets/PerfectWorld/UI/TaskIcon/TuChan.png.meta +++ b/Assets/PerfectWorld/Resources/UI/Login/载入1280-15.jpg.meta @@ -1,12 +1,12 @@ fileFormatVersion: 2 -guid: cd36f0d3de378e94caea2807302f7a18 +guid: cfa464036967d9746abcfa0608211b2e TextureImporter: internalIDToNameTable: [] externalObjects: {} serializedVersion: 13 mipmaps: mipMapMode: 0 - enableMipMap: 1 + enableMipMap: 0 sRGBTexture: 1 linearTexture: 0 fadeOut: 0 @@ -34,16 +34,16 @@ TextureImporter: maxTextureSize: 2048 textureSettings: serializedVersion: 2 - filterMode: 1 + filterMode: 0 aniso: 1 mipBias: 0 - wrapU: 0 - wrapV: 0 + wrapU: 1 + wrapV: 1 wrapW: 0 - nPOTScale: 1 + nPOTScale: 0 lightmap: 0 compressionQuality: 50 - spriteMode: 0 + spriteMode: 1 spriteExtrude: 1 spriteMeshType: 1 alignment: 0 @@ -52,9 +52,9 @@ TextureImporter: spriteBorder: {x: 0, y: 0, z: 0, w: 0} spriteGenerateFallbackPhysicsShape: 1 alphaUsage: 1 - alphaIsTransparency: 0 + alphaIsTransparency: 1 spriteTessellationDetail: -1 - textureType: 0 + textureType: 8 textureShape: 1 singleChannelComponent: 0 flipbookRows: 1 @@ -113,7 +113,7 @@ TextureImporter: customData: physicsShape: [] bones: [] - spriteID: + spriteID: 5e97eb03825dee720800000000000000 internalID: 0 vertices: [] indices: diff --git a/Assets/PerfectWorld/Scene/LoginScene.unity b/Assets/PerfectWorld/Scene/LoginScene.unity index 96d09f5880..ffb3f922c7 100644 --- a/Assets/PerfectWorld/Scene/LoginScene.unity +++ b/Assets/PerfectWorld/Scene/LoginScene.unity @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f3553c5fdd68230c6a591df1fde22cf360896fc818007787595189f0cc036b5c -size 69312 +oid sha256:eadad766c90d9a2f8f33468f1b6b21e6fd78e55f555200887eb9f6198720424a +size 76688 diff --git a/Assets/PerfectWorld/Scripts/Common/DataProcess/generate_item_temp.cs b/Assets/PerfectWorld/Scripts/Common/DataProcess/generate_item_temp.cs index 484ff2555f..48dc7b3a76 100644 --- a/Assets/PerfectWorld/Scripts/Common/DataProcess/generate_item_temp.cs +++ b/Assets/PerfectWorld/Scripts/Common/DataProcess/generate_item_temp.cs @@ -347,7 +347,7 @@ public static class generate_item_temp itemdataman.set_to_classid(DATA_TYPE.DT_WEAPON_ESSENCE, data, -1); return 0; } - private static void generate_magic_defense(int[] res, List res_list , RAND_CLASS cls, + private static void generate_magic_defense(int[] res, List res_list , RAND_CLASS cls, bool b_fixed = false) // { float[] count_prop = {0.35f,0.25f,0.20f,0.15f,0.05f,0.051f}; @@ -403,6 +403,7 @@ public static class generate_item_temp data = new byte[size]; int offset = 0; short hole_num = 0; + if(normal_addon == GEN_ADDON_MODE.ADDON_LIST_DROP) { float[] drop_probability_socket = { ess.drop_probability_socket0, ess.drop_probability_socket1, ess.drop_probability_socket2 }; @@ -519,7 +520,7 @@ public static class generate_item_temp WriteInt(data, ref offset, element_data.RandNormal(ess.mp_enhance_low, ess.mp_enhance_high, cls, LOWER.LOWER_TREND)); WriteInt(data, ref offset, element_data.RandNormal(ess.hp_enhance_low, ess.hp_enhance_high, cls, LOWER.LOWER_TREND)); int[] res = {0,0,0,0,0}; - List res_list = ess.magic_defences.ToList(); + List res_list = ess.magic_defences.ToList(); generate_magic_defense(res, res_list, cls, ess.force_all_magic_defences != 0 || ess.fixed_props!=0); WriteInt(data, ref offset, res[0]); WriteInt(data, ref offset, res[1]); @@ -558,6 +559,413 @@ public static class generate_item_temp itemdataman.set_to_classid(DATA_TYPE.DT_ARMOR_ESSENCE, data, -1); return 0; } + public static int generate_decoration(uint id, ID_SPACE idspace, out byte[] data, out uint size, RAND_CLASS cls, + GEN_ADDON_MODE normal_addon ,item_tag_t tag,List sa_list = null) + { + DATA_TYPE datatype = DATA_TYPE.DT_INVALID; + int i=0; + data = new byte[0]; + size = 0; + object obj = itemdataman._edm.get_data_ptr(id, idspace, ref datatype); + if(obj == null || datatype != DATA_TYPE.DT_DECORATION_ESSENCE) + { + return -1; + } + DECORATION_ESSENCE ess = (DECORATION_ESSENCE)obj; + + size = (uint)(Marshal.SizeOf(typeof(item_data)) + Marshal.SizeOf(typeof(_item_content)) + Marshal.SizeOf(typeof(DECORATION_ESSENCE))); + // �׶� + uint hole_num = 0; //�׶�����Ŀ + + // ���addons + byte[] addon_buf = new byte[itemdataman.ELEMENTDATAMAN_MAX_NUM_ADDONS*Marshal.SizeOf(typeof(itemdataman._addon))]; + float[] probability_addon_num = { ess.probability_addon_num0, ess.probability_addon_num1, ess.probability_addon_num2, ess.probability_addon_num3, ess.probability_addon_num4 }; + uint addon_num = (uint)element_data.RandSelect(probability_addon_num.ToList(), cls, LOWER.LOWER_TREND); //���Ա���Ŀ����Ŀ + + uint addon_size = 0; + if(ess.fixed_props != 0) + { + addon_size = itemdataman.generate_equipment_addon_buffer_2(DATA_TYPE.DT_DECORATION_ESSENCE, ess.addons.Select(a => (int)a.id_addon).ToList(), addon_buf,0, addon_num); + } + else + { + if(normal_addon == GEN_ADDON_MODE.ADDON_LIST_DROP) + addon_size = itemdataman.generate_equipment_addon_buffer(DATA_TYPE.DT_DECORATION_ESSENCE, ess.addons.Select(a => (int)a.id_addon).ToList(), 32, addon_buf,0, addon_num); + else if(normal_addon == GEN_ADDON_MODE.ADDON_LIST_PRODUCE) + addon_size = itemdataman.generate_equipment_addon_buffer(DATA_TYPE.DT_DECORATION_ESSENCE, ess.rands.Select(a => (int)a.id_rand).ToList(), 32, addon_buf,0, addon_num); + else if (normal_addon == GEN_ADDON_MODE.ADDON_LIST_SPEC) + { + addon_size = itemdataman.generate_spec_addon_buffer(DATA_TYPE.DT_DECORATION_ESSENCE,addon_buf,0,itemdataman.ELEMENTDATAMAN_MAX_NUM_ADDONS, addon_num,sa_list); + } + else + { + addon_size = 0; + addon_num = 0; + } + } + size += addon_size; + + //����tag size + //ASSERT(tag_size >= sizeof(short)); + size += tag.size; + + + // allocate the buffer with exact length + data = new byte[size]; + int offset = 0; + + + WriteUInt(data, ref offset, id); //��Ʒ��ģ��ID + WriteUInt(data, ref offset, 1); //��Ʒ������ + WriteUInt(data, ref offset, (uint)ess.pile_num_max); //��Ʒ�Ķѵ����� + + object sub_type_temp = itemdataman._edm.get_data_ptr(ess.id_sub_type, ID_SPACE.ID_SPACE_ESSENCE, ref datatype); + if(sub_type_temp == null || datatype != DATA_TYPE.DT_DECORATION_SUB_TYPE) + { + return -1; + } + DECORATION_SUB_TYPE sub_type = (DECORATION_SUB_TYPE)sub_type_temp; + + WriteInt(data, ref offset, (int)(sub_type.equip_mask|(addon_num>0?0x40000000:0))); //��Ʒ�Ŀ�װ����־ + WriteUInt(data, ref offset, ess.proc_type); //��Ʒ�Ĵ�����ʽ + WriteInt(data, ref offset, (int)DATA_TYPE.DT_DECORATION_ESSENCE); //��Ʒ��Ӧ�����ID + WriteInt(data, ref offset, (int)DATA_TYPE.DT_DECORATION_ESSENCE); //��Ʒ��Ӧ�����ID + if(ess.has_guid == 1){ + int g1,g2; + itemdataman.get_item_guid(id,out g1,out g2); + WriteInt(data, ref offset, g1); //��Ʒ��Ӧ�����ID guid + WriteInt(data, ref offset, g2); //��Ʒ��Ӧ�����ID guid + } + else{ + WriteInt(data, ref offset, 0); //��Ʒ��Ӧ�����ID guid + WriteInt(data, ref offset, 0); //��Ʒ��Ӧ�����ID guid + } + WriteInt(data, ref offset, ess.price); //��Ʒ�ļ۸� + + WriteInt(data, ref offset, 0); //����ʱ�� + int content_length = 0; + int content_length_ptr = offset; + WriteInt(data, ref offset, 0); + int item_content = offset; + WriteInt(data, ref offset, 0); + content_length = (int)(size - offset); + WriteInt(data, ref content_length_ptr, content_length); + WriteInt(data, ref item_content, offset); + + // prerequisition + int require_ptr = offset; + WriteShort(data, ref offset, (short)ess.require_level); + WriteShort(data, ref offset, (short)(ess.character_combo_id&0xFFFF)); + WriteShort(data, ref offset, (short)ess.require_strength); + WriteShort(data, ref offset, (short)ess.require_tili); + WriteShort(data, ref offset, (short)ess.require_agility); + WriteShort(data, ref offset, (short)ess.require_energy); + + int temp2 = element_data.RandNormal(ess.durability_min, ess.durability_max, cls, LOWER.LOWER_TREND); + int temp; + if(normal_addon != GEN_ADDON_MODE.ADDON_LIST_DROP || (ess.proc_type & 0x1000) != 0) + { + temp = temp2; + } + else + { + temp = element_data.RandNormal(ess.durability_drop_min, ess.durability_drop_max, cls, UPPER.UPPER_TREND); + if(temp > temp2) temp = temp2; + } + WriteInt(data, ref offset, temp); //prerequisition durability + WriteInt(data, ref offset, temp2); //prerequisition max_durability + + //���������߱�ǩע���ǩ���ڱ����С�ͱ�������֮�� + WriteShort(data, ref offset, (short)Marshal.SizeOf(typeof(DECORATION_ESSENCE))); //װ�������С���ֽڣ� + + WriteByte(data, ref offset, tag.type); // MadeFrom + WriteByte(data, ref offset, (byte)tag.size); + + + // ���� + int essence_ptr = offset; + WriteInt(data, ref offset, element_data.RandNormal(ess.damage_low, ess.damage_high, cls, LOWER.LOWER_TREND)); //int damage; + WriteInt(data, ref offset, element_data.RandNormal(ess.magic_damage_low, ess.magic_damage_high, cls, LOWER.LOWER_TREND)); //int magic_damage; + WriteInt(data, ref offset, element_data.RandNormal(ess.defence_low, ess.defence_high, cls, LOWER.LOWER_TREND)); //int defense; + WriteInt(data, ref offset, element_data.RandNormal(ess.armor_enhance_low, ess.armor_enhance_high, cls, LOWER.LOWER_TREND)); //int armor; + + //���� + int[] res = {0,0,0,0,0}; + List res_list = ess.magic_defences.ToList(); + generate_magic_defense(res,res_list,cls,ess.fixed_props!=0); + + WriteInt(data, ref offset, res[0]); + WriteInt(data, ref offset, res[1]); + WriteInt(data, ref offset, res[2]); + WriteInt(data, ref offset, res[3]); + WriteInt(data, ref offset, res[4]); + + // �׶� + WriteShort(data, ref offset, (short)hole_num); //�׶�����Ŀ + WriteShort(data, ref offset, (short)0); //�׶��������������� + + // addon + WriteInt(data, ref offset, (int)addon_num); + int addon_sld = offset; + + addon_data addon_data = new addon_data(); + prerequisition prerequisition = new prerequisition(); + // Read prerequisition from data buffer (where it was written) once before the loop + int require_ptr_copy = require_ptr; + ReadPrerequisition(data, ref require_ptr_copy, out prerequisition); + for(i = 0; i < addon_num; i++) + { + ReadInt(addon_buf, ref addon_sld, out addon_data.id); + ReadAddonData(addon_buf, ref addon_sld, out addon_data); + itemdataman.addon_update_ess_data(addon_data, essence_ptr, Marshal.SizeOf(typeof(_weapon_essence)), prerequisition); + addon_sld += ((addon_data.id & 0x6000)>>13)*sizeof(int)+sizeof(int); + } + itemdataman.update_require_data(ref prerequisition); + int require_ptr_write = require_ptr; + WritePrerequisition(data, ref require_ptr_write, prerequisition); + if(addon_size > 0) + { + Array.Copy(addon_buf, 0, data, offset, (int)addon_size); + offset += (int)addon_size; + } + itemdataman.set_to_classid(DATA_TYPE.DT_DECORATION_ESSENCE, data, -1); + //if id == 335 log all addon data + if(id == 335) + { + BMLogger.Log("Log for item with id: " + id); + for(int j = 0; j < addon_num; j++) + { + ReadInt(addon_buf, ref addon_sld, out addon_data.id); + ReadAddonData(addon_buf, ref addon_sld, out addon_data); + BMLogger.Log("addon_data.id: " + addon_data.id); + } + } + return 0; + } + public static int generate_projectile(uint id, ID_SPACE idspace, out byte[] data, out uint size, RAND_CLASS cls) + { + DATA_TYPE datatype = DATA_TYPE.DT_INVALID; + data = new byte[0]; + size = 0; + object obj = itemdataman._edm.get_data_ptr(id, idspace, ref datatype); + if(obj == null || datatype != DATA_TYPE.DT_PROJECTILE_ESSENCE) + { + return -1; + } + PROJECTILE_ESSENCE ess = (PROJECTILE_ESSENCE)obj; + size = (uint)(Marshal.SizeOf(typeof(item_data)) + Marshal.SizeOf(typeof(_item_content)) + Marshal.SizeOf(typeof(PROJECTILE_ESSENCE))); + + byte[] addon_buf = new byte[itemdataman.ELEMENTDATAMAN_MAX_NUM_ADDONS*Marshal.SizeOf(typeof(itemdataman._addon))]; + uint addon_num = 4; //���Ա���Ŀ����Ŀ�̶� 4 + uint addon_size = 0; + + addon_size = itemdataman.generate_equipment_addon_buffer_2(DATA_TYPE.DT_PROJECTILE_ESSENCE, new List { (int)ess.id_addon0, (int)ess.id_addon1, (int)ess.id_addon2, (int)ess.id_addon3 }, addon_buf,0, addon_num); + size += addon_size; + + //����tag size + size += sizeof(short); + + // allocate the buffer with exact length + data = new byte[size]; + int offset = 0; + + WriteUInt(data, ref offset, id); //��Ʒ��ģ��ID + WriteUInt(data, ref offset, 1); //��Ʒ������ + WriteUInt(data, ref offset, (uint)ess.pile_num_max); //��Ʒ�Ķѵ����� + WriteInt(data, ref offset, (int)(itemdataman.ELEMENTDATAMAN_EQUIP_MASK_PROJECTILE|(addon_num>0?0x40000000:0))); //��Ʒ�Ŀ�װ����־ + WriteInt(data, ref offset, (int)ess.proc_type); //��Ʒ�Ĵ�����ʽ + WriteInt(data, ref offset, (int)DATA_TYPE.DT_PROJECTILE_ESSENCE); //��Ʒ��Ӧ�����ID + if(ess.has_guid == 1){ + int g1,g2; + itemdataman.get_item_guid(id,out g1,out g2); + WriteInt(data, ref offset, g1); //��Ʒ��Ӧ�����ID guid + WriteInt(data, ref offset, g2); //��Ʒ��Ӧ�����ID guid + } + else{ + WriteInt(data, ref offset, 0); //��Ʒ��Ӧ�����ID guid + WriteInt(data, ref offset, 0); //��Ʒ��Ӧ�����ID guid + } + WriteInt(data, ref offset, ess.price); //��Ʒ�ļ۸� + WriteInt(data, ref offset, 0); //����ʱ�� + + int content_length = 0; + int content_length_ptr = offset; + WriteInt(data, ref offset, 0); + int item_content = offset; + WriteInt(data, ref offset, 0); + content_length = (int)(size - offset); + WriteInt(data, ref content_length_ptr, content_length); + WriteInt(data, ref item_content, offset); + + // prerequisition + int require_ptr = offset; + //����int����6�� + WriteShort(data, ref offset, 0); //prerequisition level + WriteShort(data, ref offset, -1); // 0xFFFF = -1 + WriteShort(data, ref offset, 0); + WriteShort(data, ref offset, 0); //prerequisition strength + WriteShort(data, ref offset, 0); //prerequisition agility + WriteShort(data, ref offset, 0); //prerequisition energy + + WriteInt(data, ref offset, 1); //prerequisition durability + WriteInt(data, ref offset, 1); //prerequisition max_durability + WriteShort(data, ref offset, (short)Marshal.SizeOf(typeof(PROJECTILE_ESSENCE))); //װ�������С���ֽڣ� + WriteByte(data, ref offset, (byte)ITEM_MAKE_TAG.IMT_NULL); + WriteByte(data, ref offset, 0); + + // projectile_essence ���� + int essence_ptr = offset; + WriteInt(data, ref offset, (int)ess.type); //��ҩ���� + WriteInt(data, ref offset, ess.damage_enhance); //���������Ĺ����� + WriteInt(data, ref offset, ess.damage_scale_enhance); //���ձ������ӹ����� + WriteInt(data, ref offset, ess.require_weapon_level_min); //��Ҫ�����ȼ� + WriteInt(data, ref offset, ess.require_weapon_level_max); //��Ҫ�����ȼ� + + // �׶� + WriteShort(data, ref offset, (short)0); + WriteShort(data, ref offset, (short)0); + + + // addon + WriteInt(data, ref offset, (int)addon_num); + + int addon_sld = offset; + addon_data addon_data = new addon_data(); + prerequisition prerequisition = new prerequisition(); + // Read prerequisition from data buffer (where it was written) once before the loop + int require_ptr_copy = require_ptr; + ReadPrerequisition(data, ref require_ptr_copy, out prerequisition); + for(int i = 0; i < addon_num; i++) + { + ReadInt(addon_buf, ref addon_sld, out addon_data.id); + ReadAddonData(addon_buf, ref addon_sld, out addon_data); + itemdataman.addon_update_ess_data(addon_data, essence_ptr, Marshal.SizeOf(typeof(_weapon_essence)), prerequisition); + addon_sld += ((addon_data.id & 0x6000)>>13)*sizeof(int)+sizeof(int); + } + itemdataman.update_require_data(ref prerequisition); + int require_ptr_write = require_ptr; + WritePrerequisition(data, ref require_ptr_write, prerequisition); + if(addon_size > 0) + { + Array.Copy(addon_buf, 0, data, offset, (int)addon_size); + offset += (int)addon_size; + } + itemdataman.set_to_classid(DATA_TYPE.DT_PROJECTILE_ESSENCE, data, -1); + + return 0; + } + public static int generate_fashion_item(uint id, ID_SPACE idspace, out byte[] data, out uint size, RAND_CLASS cls, item_tag_t tag) + { + DATA_TYPE datatype = DATA_TYPE.DT_INVALID; + data = new byte[0]; + size = 0; + object obj = itemdataman._edm.get_data_ptr(id, idspace, ref datatype); + if(obj == null || datatype != DATA_TYPE.DT_FASHION_ESSENCE) + { + return -1; + } + FASHION_ESSENCE ess = (FASHION_ESSENCE)obj; + size = (uint)(Marshal.SizeOf(typeof(item_data)) + Marshal.SizeOf(typeof(FASHION_ESSENCE))); + + //ASSERT(tag_size >= 2); + size += tag.size; + object obj_sub_type = itemdataman._edm.get_data_ptr(ess.id_sub_type, idspace, ref datatype); + if(obj_sub_type == null || datatype != DATA_TYPE.DT_FASHION_SUB_TYPE) + { + return -1; + } + FASHION_SUB_TYPE sub_type = (FASHION_SUB_TYPE)obj_sub_type; + data = new byte[size]; + int offset =0; + WriteUInt(data, ref offset, id); //��Ʒ��ģ��ID + WriteUInt(data, ref offset, 1); //��Ʒ������ + WriteUInt(data, ref offset, (uint)ess.pile_num_max); //��Ʒ�Ķѵ����� + WriteUInt(data, ref offset, sub_type.equip_fashion_mask); //��Ʒ�Ŀ�װ����־���̶�ֵ���� + WriteInt(data, ref offset, (int)ess.proc_type); //��Ʒ�Ĵ�����ʽ + WriteInt(data, ref offset, (int)DATA_TYPE.DT_FASHION_ESSENCE); //��Ʒ��Ӧ�����ID + if(ess.has_guid == 1) + { + int g1,g2; + itemdataman.get_item_guid(id,out g1,out g2); + WriteInt(data, ref offset, g1); + WriteInt(data, ref offset, g2); + } + else + { + WriteInt(data, ref offset, 0); + WriteInt(data, ref offset, 0); + } + WriteInt(data, ref offset, ess.price); + WriteInt(data, ref offset, 0); + + int content_length = 0; + int content_length_ptr = offset; + WriteInt(data, ref offset, 0); + int item_content = offset; + WriteInt(data, ref offset, 0); + content_length = (int)(size - offset); + WriteInt(data, ref content_length_ptr, content_length); + WriteInt(data, ref item_content, offset); + + short color = (short)element_data.RandNormal(0, 0x7FFF, cls, ANY.ANY_TREND); + WriteShort(data, ref offset, (short)ess.require_level); + + WriteShort(data, ref offset, color); + WriteShort(data, ref offset, (short)ess.gender); + + WriteByte(data, ref offset, tag.type); + WriteByte(data, ref offset, (byte)tag.size); + + itemdataman.set_to_classid(DATA_TYPE.DT_FASHION_ESSENCE, data, -1); + return 0; + } + public static int generate_taskdice(uint id, ID_SPACE idspace, out byte[] data, out uint size, RAND_CLASS cls) + { + DATA_TYPE datatype = DATA_TYPE.DT_INVALID; + data = new byte[0]; + size = 0; + object obj = itemdataman._edm.get_data_ptr(id, idspace, ref datatype); + if(obj == null || datatype != DATA_TYPE.DT_TASKDICE_ESSENCE) + { + return -1; + } + TASKDICE_ESSENCE ess = (TASKDICE_ESSENCE)obj; + size = (uint)(Marshal.SizeOf(typeof(item_data)) + Marshal.SizeOf(typeof(TASKDICE_ESSENCE))); + data = new byte[size]; + int offset = 0; + WriteUInt(data, ref offset, id); + WriteUInt(data, ref offset, 1); + WriteInt(data, ref offset, ess.pile_num_max); + WriteInt(data, ref offset, 0); + WriteUInt(data, ref offset, ess.proc_type); + WriteInt(data, ref offset, (int)DATA_TYPE.DT_TASKDICE_ESSENCE); + if(ess.has_guid == 1) + { + int g1,g2; + itemdataman.get_item_guid(id,out g1,out g2); + WriteInt(data, ref offset, g1); + WriteInt(data, ref offset, g2); + } + else + { + WriteInt(data, ref offset, 0); + WriteInt(data, ref offset, 0); + } + WriteInt(data, ref offset, 0); + WriteInt(data, ref offset, 0); + + int content_length = 0; + int content_length_ptr = offset; + WriteInt(data, ref offset, 0); + int item_content = offset; + WriteInt(data, ref offset, 0); + content_length = (int)(size - offset); + WriteInt(data, ref content_length_ptr, content_length); + WriteInt(data, ref item_content, offset); + + itemdataman.set_to_classid(DATA_TYPE.DT_TASKDICE_ESSENCE, data, -1); + return 0; + } public static int generate_tasknormalmatter(uint id, ID_SPACE idspace, out byte[] data, out uint size, RAND_CLASS cls, GEN_ADDON_MODE normal_addon ,item_tag_t tag,List sa_list = null) { @@ -950,6 +1358,51 @@ public static class generate_item_temp itemdataman.set_to_classid(DATA_TYPE.DT_PET_FOOD_ESSENCE, data, -1); return 0; } + + public static int generate_townscroll(uint id, ID_SPACE idspace, out byte[] data, out uint size, RAND_CLASS cls) + { + DATA_TYPE datatype = DATA_TYPE.DT_INVALID; + data = new byte[0]; + size = 0; + object obj = itemdataman._edm.get_data_ptr(id, idspace, ref datatype); + if(obj == null || datatype != DATA_TYPE.DT_TOWNSCROLL_ESSENCE) + return -1; + TOWNSCROLL_ESSENCE ess = (TOWNSCROLL_ESSENCE)obj; + size = (uint)(Marshal.SizeOf(typeof(item_data)) + Marshal.SizeOf(typeof(TOWNSCROLL_ESSENCE))); + data = new byte[size]; + int offset = 0; + WriteUInt(data, ref offset, id); + WriteUInt(data, ref offset, 1); + WriteUInt(data, ref offset, (uint)ess.pile_num_max); + WriteInt(data, ref offset, 0); + WriteInt(data, ref offset, (int)ess.proc_type); + WriteInt(data, ref offset, (int)DATA_TYPE.DT_TOWNSCROLL_ESSENCE); + if(ess.has_guid == 1){ + int g1,g2; + itemdataman.get_item_guid(id,out g1,out g2); + WriteInt(data, ref offset, g1); + WriteInt(data, ref offset, g2); + } + else{ + WriteInt(data, ref offset, 0); + WriteInt(data, ref offset, 0); + } + WriteInt(data, ref offset, ess.price); + WriteInt(data, ref offset, 0); + + int content_length = 0; + int content_length_ptr = offset; + WriteInt(data, ref offset, 0); + int item_content = offset; + WriteInt(data, ref offset, 0); + content_length = (int)(size - offset); + WriteInt(data, ref content_length_ptr, content_length); + WriteInt(data, ref item_content, offset); + WriteInt(data, ref offset, (int )(ess.use_time * 20)); //ʹ��ʱ�� + + itemdataman.set_to_classid(DATA_TYPE.DT_TOWNSCROLL_ESSENCE, data, -1); + return 0; + } #region Write Functions private static void WriteUInt(byte[] buf, ref int offset, uint value) { diff --git a/Assets/PerfectWorld/Scripts/Common/DataProcess/itemdataman.cs b/Assets/PerfectWorld/Scripts/Common/DataProcess/itemdataman.cs index d5338b2ced..f484a59ba7 100644 --- a/Assets/PerfectWorld/Scripts/Common/DataProcess/itemdataman.cs +++ b/Assets/PerfectWorld/Scripts/Common/DataProcess/itemdataman.cs @@ -458,6 +458,20 @@ namespace BrewMonster ret = generate_item_temp.generate_armor(id, ID_SPACE.ID_SPACE_ESSENCE, out item,out size,SPECIFIC.SPECIFIC_RAND,GEN_ADDON_MODE.ADDON_LIST_SHOP,tag); break; + case DATA_TYPE.DT_DECORATION_ESSENCE: + ret = generate_item_temp.generate_decoration(id,ID_SPACE.ID_SPACE_ESSENCE, + out item,out size,SPECIFIC.SPECIFIC_RAND,GEN_ADDON_MODE.ADDON_LIST_SHOP,tag); + break; + case DATA_TYPE.DT_PROJECTILE_ESSENCE: + ret = generate_item_temp.generate_projectile(id,ID_SPACE.ID_SPACE_ESSENCE, + out item,out size,SPECIFIC.SPECIFIC_RAND); + break; + case DATA_TYPE.DT_FASHION_ESSENCE: + ret = generate_item_temp.generate_fashion_item(id, ID_SPACE.ID_SPACE_ESSENCE, out item, out size, SPECIFIC.SPECIFIC_RAND, tag); + break; + case DATA_TYPE.DT_TASKDICE_ESSENCE: + ret = generate_item_temp.generate_taskdice(id, ID_SPACE.ID_SPACE_ESSENCE, out item, out size, SPECIFIC.SPECIFIC_RAND); + break; case DATA_TYPE.DT_TASKNORMALMATTER_ESSENCE: ret = generate_item_temp.generate_tasknormalmatter(id,ID_SPACE.ID_SPACE_ESSENCE, out item,out size,SPECIFIC.SPECIFIC_RAND,GEN_ADDON_MODE.ADDON_LIST_SHOP,tag); @@ -477,6 +491,10 @@ namespace BrewMonster case DATA_TYPE.DT_PET_FOOD_ESSENCE: ret = generate_item_temp.generate_pet_food(id, ID_SPACE.ID_SPACE_ESSENCE, out item, out size, SPECIFIC.SPECIFIC_RAND); break; + case DATA_TYPE.DT_TOWNSCROLL_ESSENCE: + ret = generate_item_temp.generate_townscroll(id, ID_SPACE.ID_SPACE_ESSENCE, out item, out size, SPECIFIC.SPECIFIC_RAND); + break; + default: ret = -1; break; diff --git a/Assets/PerfectWorld/Scripts/GameData/ExpTypes.cs b/Assets/PerfectWorld/Scripts/GameData/ExpTypes.cs index 1a9494f9e8..4bd4f6926a 100644 --- a/Assets/PerfectWorld/Scripts/GameData/ExpTypes.cs +++ b/Assets/PerfectWorld/Scripts/GameData/ExpTypes.cs @@ -253,7 +253,12 @@ namespace BrewMonster + ByteToStringUtils.ByteArrayToCP936String(file_model_left) + "\n"; } } - + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct MagicDefence + { + public int low; // Minimum magic defense + public int high; // Maximum magic defense + } [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct ARMOR_MAJOR_TYPE { @@ -326,12 +331,7 @@ namespace BrewMonster public int defence_low; // Minimum physical defense public int defence_high; // Maximum physical defense - [StructLayout(LayoutKind.Sequential, Pack = 1)] - public struct MagicDefence - { - public int low; // Minimum magic defense - public int high; // Maximum magic defense - } + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)] public MagicDefence[] magic_defences; // Magic defenses for 5 elements @@ -495,13 +495,6 @@ namespace BrewMonster public int defence_low; // Minimum physical defense public int defence_high; // Maximum physical defense - [StructLayout(LayoutKind.Sequential, Pack = 1)] - public struct MagicDefence - { - public int low; // Minimum magic defense - public int high; // Maximum magic defense - } - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)] public MagicDefence[] magic_defences; // Magic defenses for 5 elements @@ -750,6 +743,7 @@ namespace BrewMonster [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] public ushort[] name; // Fashion sub-type name + public string Name => ByteToStringUtils.UshortArrayToCP936String(name); public uint equip_fashion_mask; // Fashion equipment slot mask } @@ -774,6 +768,8 @@ namespace BrewMonster [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)] public byte[] file_matter; // Matter model file path + public string FileMatter => ByteToStringUtils.ByteArrayToCP936String(file_matter); + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)] public byte[] file_icon; // Icon file path @@ -1512,16 +1508,16 @@ namespace BrewMonster [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)] public byte[] file_model; // Model file path - + public string FileModel => ByteToStringUtils.ByteArrayToCP936String(file_model); [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)] public byte[] file_model2; // Second model file path [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)] public byte[] file_matter; // Material file path - + public string FileMatter => ByteToStringUtils.ByteArrayToCP936String(file_matter); [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)] public byte[] file_icon; // Icon file path - + public string FileIcon => ByteToStringUtils.ByteArrayToCP936String(file_icon); public int price; // Price public int shop_price; // Shop price @@ -1605,10 +1601,11 @@ namespace BrewMonster [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)] public byte[] file_matter; // Material file path + public string FileMatter => ByteToStringUtils.ByteArrayToCP936String(file_matter); [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)] public byte[] file_icon; // Icon file path - + public string FileIcon => ByteToStringUtils.ByteArrayToCP936String(file_icon); public float use_time; // Use time (seconds) public int price; // Price @@ -1629,9 +1626,11 @@ namespace BrewMonster [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)] public byte[] file_matter; // Material file path + public string FileMatter => ByteToStringUtils.ByteArrayToCP936String(file_matter); [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)] public byte[] file_icon; // Icon file path + public string FileIcon => ByteToStringUtils.ByteArrayToCP936String(file_icon); public int price; // Price public int shop_price; // Shop price @@ -1746,6 +1745,7 @@ namespace BrewMonster [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)] public byte[] file_icon; // Icon file path + public string FileIcon { get { return ByteToStringUtils.ByteArrayToCP936String(file_icon); } } public int pile_num_max; // Max stack count public uint has_guid; // Whether item has GUID @@ -1762,9 +1762,11 @@ namespace BrewMonster [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)] public byte[] file_matter; // Material file path + public string FileMatter { get { return ByteToStringUtils.ByteArrayToCP936String(file_matter); } } [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)] public byte[] file_icon; // Icon file path + public string FileIcon { get { return ByteToStringUtils.ByteArrayToCP936String(file_icon); } } public int price; // Price public int shop_price; // Shop price @@ -1783,9 +1785,10 @@ namespace BrewMonster [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)] public byte[] file_matter; // matter file path - + public string FileMatter { get { return ByteToStringUtils.ByteArrayToCP936String(file_matter); } } [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)] public byte[] file_icon; // icon file path + public string FileIcon { get { return ByteToStringUtils.ByteArrayToCP936String(file_icon); } } [StructLayout(LayoutKind.Sequential)] public struct TaskList @@ -1854,6 +1857,7 @@ namespace BrewMonster [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] public ushort[] name; // name, max 15 chars + public string Name => ByteToStringUtils.UshortArrayToUnicodeString(name); } public struct PROJECTILE_ESSENCE @@ -1866,12 +1870,14 @@ namespace BrewMonster [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)] public byte[] file_model; // model file path + public string FileModel { get { return ByteToStringUtils.ByteArrayToCP936String(file_model); } } [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)] public byte[] file_matter; // matter file path - + public string FileMatter { get { return ByteToStringUtils.ByteArrayToCP936String(file_matter); } } [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)] public byte[] file_icon; // icon file path + public string FileIcon { get { return ByteToStringUtils.ByteArrayToCP936String(file_icon); } } [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)] public byte[] file_firegfx; // fire effect file @@ -3015,9 +3021,11 @@ namespace BrewMonster public string FileIcon1 => ByteToStringUtils.ByteArrayToCP936String(file_icon1); [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)] public byte[] file_icon2; // state 2 icon path + public string FileIcon2 => ByteToStringUtils.ByteArrayToCP936String(file_icon2); [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)] public byte[] file_icon3; // state 3 icon path + public string FileIcon3 => ByteToStringUtils.ByteArrayToCP936String(file_icon3); [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)] public byte[] file_icon4; // state 4 icon path diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrArrow.cs b/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrArrow.cs index 0dbbef4231..b196cf02e4 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrArrow.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrArrow.cs @@ -1,19 +1,170 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using System.IO; +using BrewMonster; +using ModelRenderer.Scripts.Common; +using ModelRenderer.Scripts.GameData; +using UnityEngine; +using PerfectWorld.Scripts.Managers; +using BrewMonster.Network; using BrewMonster.Scripts.Managers; +using BrewMonster.Scripts; +using CSNetwork.GPDataType; +using System.Runtime.InteropServices; namespace PerfectWorld.Scripts.Managers { + /// + /// Arrow item class (cac loai mui ten) + /// public class EC_IvtrArrow : EC_IvtrEquip { + protected IVTR_ESSENCE_ARROW m_Essence; // Arrow essence data + + // Data in database + protected PROJECTILE_TYPE m_pDBType; + protected PROJECTILE_ESSENCE m_pDBEssence; /// - /// Not create logic yet (add summary later) + /// Arrow item class (cac loai mui ten) /// /// Template id /// Expire date public EC_IvtrArrow(int tid, int expire_date) : base(tid, expire_date) { + m_iCID = (int)InventoryClassId.ICID_ARROW; + + m_Essence = new IVTR_ESSENCE_ARROW(); + + // Get database data + elementdataman pDB = ElementDataManProvider.GetElementDataMan(); + DATA_TYPE DataType = DATA_TYPE.DT_INVALID; + m_pDBEssence = (PROJECTILE_ESSENCE)pDB.get_data_ptr((uint)tid, ID_SPACE.ID_SPACE_ESSENCE, ref DataType); + m_pDBType = (PROJECTILE_TYPE)pDB.get_data_ptr((uint)m_pDBEssence.type, ID_SPACE.ID_SPACE_ESSENCE, ref DataType); + + m_iPileLimit = m_pDBEssence.pile_num_max; + m_iPrice = m_pDBEssence.price; + m_iShopPrice = m_pDBEssence.shop_price; + m_iProcType = (int)m_pDBEssence.proc_type; + m_i64EquipMask = EC_IvtrType.EQUIP_MASK64_PROJECTILE; } public EC_IvtrArrow(EC_IvtrArrow other) : base(other) { + m_pDBType = other.m_pDBType; + m_pDBEssence = other.m_pDBEssence; + m_Essence = other.m_Essence; } + + public override bool SetItemInfo(byte[] pInfoData, int iDataLen) + { + base.SetItemInfo(pInfoData, iDataLen); + + if (pInfoData == null || iDataLen == 0) + return true; + + try + { + CECDataReader dr = new CECDataReader(pInfoData, iDataLen); + + // Skip equip requirements and endurance + dr.Offset(5 * sizeof (int), CECDataReader.SEEK_CUR); + + int iEssenceSize = dr.ReadInt(); + //ASSERT(iEssenceSize == sizeof (IVTR_ESSENCE_ARROW)); + + m_Essence = new IVTR_ESSENCE_ARROW(dr.ReadData(iEssenceSize)); + } + catch (Exception e) + { + Debug.LogError("CECIvtrArrow::SetItemInfo, data read error (" + e.GetType() + e.StackTrace + ")"); + return false; + } + + return true; + } + + // Get item icon file name + public override string GetIconFile() + { + return m_pDBEssence.FileIcon; + } + + // Get item name + public override string GetName() + { + // Try Unicode first (for Vietnamese/wide char names), then fallback to CP936 + if (m_pDBEssence.name != null && m_pDBEssence.name.Length > 0) + { + string s = ByteToStringUtils.UshortArrayToUnicodeString(m_pDBEssence.name); + if (!string.IsNullOrEmpty(s) && !string.IsNullOrWhiteSpace(s)) + return s; + // Fallback to legacy CP936 if Unicode was empty + s = ByteToStringUtils.UshortArrayToCP936String(m_pDBEssence.name); + if (!string.IsNullOrEmpty(s)) + return s; + } + return base.GetName(); // Fallback to base class method + } + + // Get item description text + protected override string GetNormalDesc(bool bRepair) + { + if (m_bNeedUpdate) + return ""; + + // Build addon and refine properties and save it + m_strDesc = ""; + BuildAddOnPropDesc(null, null); + string strAddon = m_strDesc; + + m_strDesc = ""; + + // Try to build item description + CECStringTab pDescTab = EC_Game.GetItemDesc(); + int white = (int)DescriptipionMsg.ITEMDESC_COL_WHITE; + int namecol = DecideNameCol(); + + if (m_iCount > 1) + AddDescText(namecol, true, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_NAMENUMBER), GetName(), m_iCount); + else + AddDescText(namecol, true, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_NAME), GetName()); + + AddIDDescText(); + + AddExpireTimeDesc(); + + // Weapon requirement + AddDescText(white, true, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_WEAPONREQ), m_Essence.iWeaponReqLow, + m_Essence.iWeaponReqHigh, m_pDBType.Name); + + // Damage enhance + if (m_pDBEssence.damage_enhance != 0) + { + AddDescText(-1, false, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_ADDPHYDAMAGE)); + AddDescText(-1, true, " %+d", m_pDBEssence.damage_enhance); + } + + // Add addon properties + if (strAddon.Length > 0) + m_strDesc += strAddon; + + // Price + AddPriceDesc(white, bRepair); + + // Suite description + AddSuiteDesc(); + + // Extend description + AddExtDescText(); + + return m_strDesc; + } + + // Get drop model for shown + public override string GetDropModel() + { + return m_pDBEssence.FileMatter; + } + } } \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrEquip.cs b/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrEquip.cs index 260b3a7a3a..007fcd0393 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrEquip.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrEquip.cs @@ -720,7 +720,7 @@ namespace PerfectWorld.Scripts.Managers prop.Suite = (type & 0x10000) != 0; prop.Engraved = (type & 0x20000) != 0; prop.Local = false; - + for (int j = 0; j < prop.NumParam; j++) { prop.Params[j] = dr.ReadInt(); @@ -819,7 +819,7 @@ namespace PerfectWorld.Scripts.Managers /// /// Read maker information from binary data /// - private void ReadMakerInfo(CECDataReader dr) + protected void ReadMakerInfo(CECDataReader dr) { // Debug: Log the bytes at current position before reading // We need to check what bytes are actually at the reader position @@ -2409,7 +2409,7 @@ namespace PerfectWorld.Scripts.Managers /// private int VisualizeFloatPercent(int value) { - return value / 100; + return (int)(IntToFloat(value) * 100.0f + 0.5f); } /// @@ -2610,811 +2610,743 @@ namespace PerfectWorld.Scripts.Managers int p0 = param != null && param.Length > 0 ? param[0] : 0; int p1 = param != null && param.Length > 1 ? param[1] : 0; int p2 = param != null && param.Length > 2 ? param[2] : 0; - byte propType = GetPropertyType(idProp); int color = -1; if (!IsSharpenerProperty(propType)) { switch (propType) - { + { case 0: // ������ - - if(!local) - { - if (aPEEVals != null) - aPEEVals[PEEI_PHYDAMAGE] += p0; - } - - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_ADDPHYDAMAGE)); - AddDescText(color, true, " %+d", p0); - break; - - case 1: // ���������� - - if(local) - { - if(p0 != p1) + if (!local) { - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_MAXPHYDAMAGE), p0); - AddDescText(color, true, "~%d", p1); + if (aPEEVals != null) + aPEEVals[PEEI_PHYDAMAGE] += p0; + } + + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_ADDPHYDAMAGE)); + AddDescText(color, true, " %+d", p0); + break; + + case 1: // ���������� + if (local) + { + if (p0 != p1) + { + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_MAXPHYDAMAGE), p0); + AddDescText(color, true, "~%d", p1); + } + else + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_MAXPHYDAMAGE), p0); + } } else { + if (aPEEVals != null) + aPEEVals[PEEI_MAX_PHYDAMAGE] += p0; AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_MAXPHYDAMAGE), p0); } - } - else - { - if (aPEEVals != null) - aPEEVals[PEEI_MAX_PHYDAMAGE] += p0; + break; - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_MAXPHYDAMAGE), p0); - } - break; - case 2: // ������(%) - if(local) - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_PHYDMGEXTRA), VisualizeFloatPercent(p0)); - } - else - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_PHYDMGEXTRA), p0); - } - break; - + if (local) + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_PHYDMGEXTRA), VisualizeFloatPercent(p0)); + } + else + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_PHYDMGEXTRA), p0); + } + break; + case 3: // ħ������ - - if(!local) - { - if (aPEEVals != null) - aPEEVals[PEEI_MAGICDAMAGE] += p0; - } - - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_ADDMAGICDAMAGE)); - AddDescText(color, true, " %+d", p0); - break; - + if (!local) + { + if (aPEEVals != null) + aPEEVals[PEEI_MAGICDAMAGE] += p0; + } + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_ADDMAGICDAMAGE)); + AddDescText(color, true, " %+d", p0); + break; + case 4: // ħ���������� - - if(local) - { - if(p0 != p1) - { - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_MAXMAGICDAMAGE), p0); - AddDescText(color, true, "~%d", p1); - } - else - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_MAXMAGICDAMAGE), p0); - } - } - else - { - if (aPEEVals != null) - aPEEVals[PEEI_MAX_MAGICDAMAGE] += p0; - - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_MAXMAGICDAMAGE), p0); - } - break; - + if (local) + { + if (p0 != p1) + { + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_MAXMAGICDAMAGE), p0); + AddDescText(color, true, "~%d", p1); + } + else + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_MAXMAGICDAMAGE), p0); + } + } + else + { + if (aPEEVals != null) + aPEEVals[PEEI_MAX_MAGICDAMAGE] += p0; + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_MAXMAGICDAMAGE), p0); + } + break; + case 5: // ħ������(%) - - if(local) - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_MAGICDMGEXTRA), VisualizeFloatPercent(p0)); - } - else - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_MAGICDMGEXTRA), p0); - } - break; - + if (local) + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_MAGICDMGEXTRA), VisualizeFloatPercent(p0)); + } + else + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_MAGICDMGEXTRA), p0); + } + break; + case 6: // +���-�﹥ - - if(!local) - { - if (aPEEVals != null) - { - aPEEVals[PEEI_PHYDEF] += p0; - aPEEVals[PEEI_PHYDAMAGE] -= p1; - } - } - - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_PHYDEFENCE)); - AddDescText(color, true, " %+d", p0); - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_ADDPHYDAMAGE)); - AddDescText(color, true, " %+d", -p1); - break; - + if (!local) + { + if (aPEEVals != null) + { + aPEEVals[PEEI_PHYDEF] += p0; + aPEEVals[PEEI_PHYDAMAGE] -= p1; + } + } + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_PHYDEFENCE)); + AddDescText(color, true, " %+d", p0); + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_ADDPHYDAMAGE)); + AddDescText(color, true, " %+d", -p1); + break; + case 7: // +�﹥-��� - - if(!local) - { - if (aPEEVals != null) - { - aPEEVals[PEEI_PHYDAMAGE] += p0; - aPEEVals[PEEI_PHYDEF] -= p1; - } - } - - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_ADDPHYDAMAGE)); - AddDescText(color, true, " %+d", p0); - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_PHYDEFENCE)); - AddDescText(color, true, " %+d", -p1); - break; - + if (!local) + { + if (aPEEVals != null) + { + aPEEVals[PEEI_PHYDAMAGE] += p0; + aPEEVals[PEEI_PHYDEF] -= p1; + } + } + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_ADDPHYDAMAGE)); + AddDescText(color, true, " %+d", p0); + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_PHYDEFENCE)); + AddDescText(color, true, " %+d", -p1); + break; + case 8: // +ħ��-ħ�� - - if(!local) - { - if (aPEEVals != null) - { - aPEEVals[PEEI_MAGICDAMAGE] += p0; - aPEEVals[PEEI_GOLDDEF] -= p1; - aPEEVals[PEEI_WOODDEF] -= p1; - aPEEVals[PEEI_WATERDEF] -= p1; - aPEEVals[PEEI_FIREDEF] -= p1; - aPEEVals[PEEI_EARTHDEF] -= p1; - } - } - - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_ADDMAGICDAMAGE)); - AddDescText(color, true, " %+d", p0); - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_ALLMAGICDEF)); - AddDescText(color, true, " %+d", -p1); - break; - + if (!local) + { + if (aPEEVals != null) + { + aPEEVals[PEEI_MAGICDAMAGE] += p0; + aPEEVals[PEEI_GOLDDEF] -= p1; + aPEEVals[PEEI_WOODDEF] -= p1; + aPEEVals[PEEI_WATERDEF] -= p1; + aPEEVals[PEEI_FIREDEF] -= p1; + aPEEVals[PEEI_EARTHDEF] -= p1; + } + } + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_ADDMAGICDAMAGE)); + AddDescText(color, true, " %+d", p0); + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_ALLMAGICDEF)); + AddDescText(color, true, " %+d", -p1); + break; + case 9: // �����ٶ� - - if(local) - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_ATKTIME), -IntToFloat(p0)); - } - else - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_ATKTIME), -p0 * 0.05f); - } - break; - + if (local) + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_ATKTIME), -IntToFloat(p0)); + } + else + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_ATKTIME), -p0 * 0.05f); + } + break; + case 10: // �������� - { - - if(local) - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_ADDATKDIST), IntToFloat(p0)); - } - else - { - if (aPEEVals != null) - { - float fDist = IntToFloat(aPEEVals[PEEI_ATKDIST]) + IntToFloat(p0); - aPEEVals[PEEI_ATKDIST] = FloatToInt(fDist); - } - - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_ADDATKDIST), IntToFloat(p0)); - } - break; - } + if (local) + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_ADDATKDIST), IntToFloat(p0)); + } + else + { + if (aPEEVals != null) + { + float fDist = IntToFloat(aPEEVals[PEEI_ATKDIST]) + IntToFloat(p0); + aPEEVals[PEEI_ATKDIST] = FloatToInt(fDist); + } + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_ADDATKDIST), IntToFloat(p0)); + } + break; + case 11: // ����ʱ�� - - if(local) - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_CASTTIME), -VisualizeFloatPercent(p0)); - } - else - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_CASTTIME), -p0); - } - break; - + if (local) + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_CASTTIME), -VisualizeFloatPercent(p0)); + } + else + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_CASTTIME), -p0); + } + break; + case 12: // ������� - - if(!local) - { - if (aPEEVals != null) - aPEEVals[PEEI_PHYDEF] += p0; - } - - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_PHYDEFENCE)); - AddDescText(color, true, " %+d", p0); - break; - + if (!local) + { + if (aPEEVals != null) + aPEEVals[PEEI_PHYDEF] += p0; + } + + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_PHYDEFENCE)); + AddDescText(color, true, " %+d", p0); + break; + case 13: // �������(%) - - if(local) - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_PHYDEFEXTRA), VisualizeFloatPercent(p0)); - else - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_PHYDEFEXTRA), p0); - - break; + if (local) + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_PHYDEFEXTRA), VisualizeFloatPercent(p0)); + else + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_PHYDEFEXTRA), p0); + break; case 14: // ���з��� - - if(!local) - { - if (aPEEVals != null) - { - aPEEVals[PEEI_GOLDDEF] += p0; - aPEEVals[PEEI_WOODDEF] += p0; - aPEEVals[PEEI_WATERDEF] += p0; - aPEEVals[PEEI_FIREDEF] += p0; - aPEEVals[PEEI_EARTHDEF] += p0; - } - } - - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_ALLMAGICDEF)); - AddDescText(color, true, " %+d", p0); - break; - + if (!local) + { + if (aPEEVals != null) + { + aPEEVals[PEEI_GOLDDEF] += p0; + aPEEVals[PEEI_WOODDEF] += p0; + aPEEVals[PEEI_WATERDEF] += p0; + aPEEVals[PEEI_FIREDEF] += p0; + aPEEVals[PEEI_EARTHDEF] += p0; + } + } + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_ALLMAGICDEF)); + AddDescText(color, true, " %+d", p0); + break; + case 15: // ��� - - if(local) - { - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_GOLDDEFENCE)); - - if(p0 != p1) - AddDescText(color, true, " %d~%d", p0, p1); - else - AddDescText(color, true, " %d", p0); - } - else - { - if (aPEEVals != null) - aPEEVals[PEEI_GOLDDEF] += p0; - - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_GOLDDEFENCE)); - AddDescText(color, true, " %+d", p0); - } - break; - + if (local) + { + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_GOLDDEFENCE)); + if (p0 != p1) + AddDescText(color, true, " %d~%d", p0, p1); + else + AddDescText(color, true, " %d", p0); + } + else + { + if (aPEEVals != null) + aPEEVals[PEEI_GOLDDEF] += p0; + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_GOLDDEFENCE)); + AddDescText(color, true, " %+d", p0); + } + break; + case 16: // ���(%) - - if(local) - { - if((p0) != (p1)) - { - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_GOLDDEFEXTRA), (p0)); - AddDescText(color, true, "~-%.2f%%",p1); - } - else - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_GOLDDEFEXTRA), (p0)); - } - } - else - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_GOLDDEFEXTRA), (p0)); - } - break; + if (local) + { + if ((p0) != (p1)) + { + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_GOLDDEFEXTRA), (p0)); + AddDescText(color, true, "~-%.2f%%", p1); + } + else + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_GOLDDEFEXTRA), (p0)); + } + } + else + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_GOLDDEFEXTRA), (p0)); + } + break; case 17: // ľ�� - - if(local) - { - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_WOODDEFENCE)); - - if(p0 != p1) - AddDescText(color, true, " %d~%d", p0, p1); - else - AddDescText(color, true, " %d", p0); - } - else - { - if (aPEEVals != null) - aPEEVals[PEEI_WOODDEF] += p0; - - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_WOODDEFENCE)); - AddDescText(color, true, " %+d", p0); - } - break; - + if (local) + { + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_WOODDEFENCE)); + + if (p0 != p1) + AddDescText(color, true, " %d~%d", p0, p1); + else + AddDescText(color, true, " %d", p0); + } + else + { + if (aPEEVals != null) + aPEEVals[PEEI_WOODDEF] += p0; + + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_WOODDEFENCE)); + AddDescText(color, true, " %+d", p0); + } + break; + case 18: // ľ��(%) - - if(local) - { - if((p0) != (p1)) - { - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_WOODDEFEXTRA), (p0)); - AddDescText(color, true, "~-%.2f%%",p1); - } - else - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_WOODDEFEXTRA), (p0)); - } - } - else - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_WOODDEFEXTRA), (p0)); - } - break; - + if (local) + { + if ((p0) != (p1)) + { + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_WOODDEFEXTRA), (p0)); + AddDescText(color, true, "~-%.2f%%", p1); + } + else + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_WOODDEFEXTRA), (p0)); + } + } + else + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_WOODDEFEXTRA), (p0)); + } + break; + case 19: // ˮ�� - - if(local) - { - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_WATERDEFENCE)); - - if(p0 != p1) - AddDescText(color, true, " %d~%d", p0, p1); - else - AddDescText(color, true, " %d", p0); - } - else - { - if (aPEEVals != null) - aPEEVals[PEEI_WATERDEF] += p0; - - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_WATERDEFENCE)); - AddDescText(color, true, " %+d", p0); - } - break; - + if (local) + { + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_WATERDEFENCE)); + + if (p0 != p1) + AddDescText(color, true, " %d~%d", p0, p1); + else + AddDescText(color, true, " %d", p0); + } + else + { + if (aPEEVals != null) + aPEEVals[PEEI_WATERDEF] += p0; + + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_WATERDEFENCE)); + AddDescText(color, true, " %+d", p0); + } + break; + case 20: // ˮ��(%) - - if(local) - { - if((p0) != (p1)) - { - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_WATERDEFEXTRA), (p0)); - AddDescText(color, true, "~-%.2f%%",p1); - } - else - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_WATERDEFEXTRA), (p0)); - } - } - else - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_WATERDEFEXTRA), (p0)); - } - break; - + if (local) + { + if ((p0) != (p1)) + { + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_WATERDEFEXTRA), (p0)); + AddDescText(color, true, "~-%.2f%%", p1); + } + else + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_WATERDEFEXTRA), (p0)); + } + } + else + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_WATERDEFEXTRA), (p0)); + } + break; + case 21: // ��� - - if(local) - { - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_FIREDEFENCE)); - - if(p0 != p1) - AddDescText(color, true, " %d~%d", p0, p1); - else - AddDescText(color, true, " %d", p0); - } - else - { - if (aPEEVals != null) - aPEEVals[PEEI_FIREDEF] += p0; - - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_FIREDEFENCE)); - AddDescText(color, true, " %+d", p0); - } - break; - + if (local) + { + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_FIREDEFENCE)); + + if (p0 != p1) + AddDescText(color, true, " %d~%d", p0, p1); + else + AddDescText(color, true, " %d", p0); + } + else + { + if (aPEEVals != null) + aPEEVals[PEEI_FIREDEF] += p0; + + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_FIREDEFENCE)); + AddDescText(color, true, " %+d", p0); + } + break; + case 22: // ���(%) - - if(local) - { - if((p0) != (p1)) - { - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_FIREDEFEXTRA), (p0)); - AddDescText(color, true, "~-%.2f%%",p1); - } - else - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_FIREDEFEXTRA), (p0)); - } - } - else - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_FIREDEFEXTRA), (p0)); - } - break; - + if (local) + { + if ((p0) != (p1)) + { + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_FIREDEFEXTRA), (p0)); + AddDescText(color, true, "~-%.2f%%", p1); + } + else + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_FIREDEFEXTRA), (p0)); + } + } + else + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_FIREDEFEXTRA), (p0)); + } + break; + case 23: // ���� - - if(local) - { - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_EARTHDEFENCE)); - - if(p0 != p1) - AddDescText(color, true, " %d~%d", p0, p1); - else - AddDescText(color, true, " %d", p0); - } - else - { - if (aPEEVals != null) - aPEEVals[PEEI_EARTHDEF] += p0; - - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_EARTHDEFENCE)); - AddDescText(color, true, " %+d", p0); - } - - break; - + if (local) + { + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_EARTHDEFENCE)); + + if (p0 != p1) + AddDescText(color, true, " %d~%d", p0, p1); + else + AddDescText(color, true, " %d", p0); + } + else + { + if (aPEEVals != null) + aPEEVals[PEEI_EARTHDEF] += p0; + + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_EARTHDEFENCE)); + AddDescText(color, true, " %+d", p0); + } + break; + case 24: // ����(%) - - if(local) - { - if((p0) != (p1)) - { - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_EARTHDEFEXTRA), (p0)); - AddDescText(color, true, "~-%.2f%%",p1); - } - else - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_EARTHDEFEXTRA), (p0)); - } - } - else - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_EARTHDEFEXTRA), (p0)); - } - break; + if (local) + { + if ((p0) != (p1)) + { + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_EARTHDEFEXTRA), (p0)); + AddDescText(color, true, "~-%.2f%%", p1); + } + else + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_EARTHDEFEXTRA), (p0)); + } + } + else + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_EARTHDEFEXTRA), (p0)); + } + break; case 25: // +���(%)-���(%) - - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_GOLDDEFEXTRA), VisualizeFloatPercent(p0)); - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_FIREDEFEXTRA), -VisualizeFloatPercent(p1)); - break; - + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_GOLDDEFEXTRA), VisualizeFloatPercent(p0)); + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_FIREDEFEXTRA), -VisualizeFloatPercent(p1)); + break; + case 26: // +ľ��(%)-���(%) - - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_WOODDEFEXTRA), VisualizeFloatPercent(p0)); - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_GOLDDEFEXTRA), -VisualizeFloatPercent(p1)); - break; - + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_WOODDEFEXTRA), VisualizeFloatPercent(p0)); + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_GOLDDEFEXTRA), -VisualizeFloatPercent(p1)); + break; + case 27: // +ˮ��(%)-����(%) - - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_WATERDEFEXTRA), VisualizeFloatPercent(p0)); - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_EARTHDEFEXTRA), -VisualizeFloatPercent(p1)); - break; - + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_WATERDEFEXTRA), VisualizeFloatPercent(p0)); + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_EARTHDEFEXTRA), -VisualizeFloatPercent(p1)); + break; + case 28: // +���(%)-ˮ��(%) - - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_FIREDEFEXTRA), VisualizeFloatPercent(p0)); - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_WATERDEFEXTRA), -VisualizeFloatPercent(p1)); - break; - + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_FIREDEFEXTRA), VisualizeFloatPercent(p0)); + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_WATERDEFEXTRA), -VisualizeFloatPercent(p1)); + break; + case 29: // +����(%)-ľ��(%) - - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_EARTHDEFEXTRA), VisualizeFloatPercent(p0)); - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_WOODDEFEXTRA), -VisualizeFloatPercent(p1)); - break; - + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_EARTHDEFEXTRA), VisualizeFloatPercent(p0)); + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_WOODDEFEXTRA), -VisualizeFloatPercent(p1)); + break; + case 30: // +���-��� - - if(!local) - { - if (aPEEVals != null) - { - aPEEVals[PEEI_GOLDDEF] += p0; - aPEEVals[PEEI_FIREDEF] -= p1; - } - } - - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_GOLDDEFENCE)); - AddDescText(color, true, " %+d", p0); - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_FIREDEFENCE)); - AddDescText(color, true, " %+d", -p1); - break; - + if (!local) + { + if (aPEEVals != null) + { + aPEEVals[PEEI_GOLDDEF] += p0; + aPEEVals[PEEI_FIREDEF] -= p1; + } + } + + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_GOLDDEFENCE)); + AddDescText(color, true, " %+d", p0); + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_FIREDEFENCE)); + AddDescText(color, true, " %+d", -p1); + break; + case 31: // +ľ��-��� - - if(!local) - { - if (aPEEVals != null) - { - aPEEVals[PEEI_WOODDEF] += p0; - aPEEVals[PEEI_GOLDDEF] -= p1; - } - } - - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_WOODDEFENCE)); - AddDescText(color, true, " %+d", p0); - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_GOLDDEFENCE)); - AddDescText(color, true, " %+d", -p1); - break; - + if (!local) + { + if (aPEEVals != null) + { + aPEEVals[PEEI_WOODDEF] += p0; + aPEEVals[PEEI_GOLDDEF] -= p1; + } + } + + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_WOODDEFENCE)); + AddDescText(color, true, " %+d", p0); + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_GOLDDEFENCE)); + AddDescText(color, true, " %+d", -p1); + break; + case 32: // +ˮ��-���� - - if(!local) - { - if (aPEEVals != null) - { - aPEEVals[PEEI_WATERDEF] += p0; - aPEEVals[PEEI_EARTHDEF] -= p1; - } - } - - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_WATERDEFENCE)); - AddDescText(color, true, " %+d", p0); - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_EARTHDEFENCE)); - AddDescText(color, true, " %+d", -p1); - break; - + if (!local) + { + if (aPEEVals != null) + { + aPEEVals[PEEI_WATERDEF] += p0; + aPEEVals[PEEI_EARTHDEF] -= p1; + } + } + + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_WATERDEFENCE)); + AddDescText(color, true, " %+d", p0); + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_EARTHDEFENCE)); + AddDescText(color, true, " %+d", -p1); + break; + case 33: // +���-ˮ�� - - if(!local) - { - if (aPEEVals != null) - { - aPEEVals[PEEI_FIREDEF] += p0; - aPEEVals[PEEI_WATERDEF] -= p1; - } - } - - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_FIREDEFENCE)); - AddDescText(color, true, " %+d", p0); - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_WATERDEFENCE)); - AddDescText(color, true, " %+d", -p1); - break; - + if (!local) + { + if (aPEEVals != null) + { + aPEEVals[PEEI_FIREDEF] += p0; + aPEEVals[PEEI_WATERDEF] -= p1; + } + } + + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_FIREDEFENCE)); + AddDescText(color, true, " %+d", p0); + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_WATERDEFENCE)); + AddDescText(color, true, " %+d", -p1); + break; + case 34: // +����-ľ�� - - if(!local) - { - if (aPEEVals != null) - { - aPEEVals[PEEI_EARTHDEF] += p0; - aPEEVals[PEEI_WOODDEF] -= p1; - } - } - - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_EARTHDEFENCE)); - AddDescText(color, true, " %+d", p0); - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_WOODDEFENCE)); - AddDescText(color, true, " %+d", -p1); - break; - + if (!local) + { + if (aPEEVals != null) + { + aPEEVals[PEEI_EARTHDEF] += p0; + aPEEVals[PEEI_WOODDEF] -= p1; + } + } + + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_EARTHDEFENCE)); + AddDescText(color, true, " %+d", p0); + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_WOODDEFENCE)); + AddDescText(color, true, " %+d", -p1); + break; + case 35: // HP - - if(!local) - { - if (aPEEVals != null) - aPEEVals[PEEI_HP] += p0; - } - - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_ADDHP)); - AddDescText(color, true, " %+d", p0); - break; - + if (!local) + { + if (aPEEVals != null) + aPEEVals[PEEI_HP] += p0; + } + + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_ADDHP)); + AddDescText(color, true, " %+d", p0); + break; + case 36: // MP - - if(!local) - { - if (aPEEVals != null) - aPEEVals[PEEI_MP] += p0; - } - - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_ADDMP)); - AddDescText(color, true, " %+d", p0); - break; - + if (!local) + { + if (aPEEVals != null) + aPEEVals[PEEI_MP] += p0; + } + + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_ADDMP)); + AddDescText(color, true, " %+d", p0); + break; + case 37: // HP(%) - - if(local) - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_HPEXTRA), VisualizeFloatPercent(p0)); - } - else - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_HPEXTRA), p0); - } - break; - + if (local) + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_HPEXTRA), VisualizeFloatPercent(p0)); + } + else + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_HPEXTRA), p0); + } + break; + case 38: // MP(%) - - if(local) - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_MPEXTRA), VisualizeFloatPercent(p0)); - } - else - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_MPEXTRA), p0); - } - break; - + if (local) + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_MPEXTRA), VisualizeFloatPercent(p0)); + } + else + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_MPEXTRA), p0); + } + break; + case 39: // HP�ָ��ٶ� - - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_HPRECOVER), p0 / 2); - break; - + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_HPRECOVER), p0 / 2); + break; + case 40: // MP�ָ��ٶ� - - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_MPRECOVER), p0 / 2); - break; - + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_MPRECOVER), p0 / 2); + break; + case 41: // ���� - - if(local) - { - if(p0 != p1) - { - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_STRENGTH), p0); - AddDescText(color, true, "~%d", p1); - } - else - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_STRENGTH), p0); - } - } - else - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_STRENGTH), p0); - } - break; - + if (local) + { + if (p0 != p1) + { + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_STRENGTH), p0); + AddDescText(color, true, "~%d", p1); + } + else + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_STRENGTH), p0); + } + } + else + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_STRENGTH), p0); + } + break; + case 42: // ���� - - if(local) - { - if(p0 != p1) - { - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_AGILITY), p0); - AddDescText(color, true, "~%d", p1); - } - else - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_AGILITY), p0); - } - } - else - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_AGILITY), p0); - } - break; - + if (local) + { + if (p0 != p1) + { + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_AGILITY), p0); + AddDescText(color, true, "~%d", p1); + } + else + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_AGILITY), p0); + } + } + else + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_AGILITY), p0); + } + break; + case 43: // ���� - - if(local) - { - if(p0 != p1) - { - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_ENERGY), p0); - AddDescText(color, true, "~%d", p1); - } - else - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_ENERGY), p0); - } - } - else - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_ENERGY), p0); - } - break; - + if (local) + { + if (p0 != p1) + { + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_ENERGY), p0); + AddDescText(color, true, "~%d", p1); + } + else + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_ENERGY), p0); + } + } + else + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_ENERGY), p0); + } + break; + case 44: // ���� - - if(local) - { - if(p0 != p1) - { - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_VITALITY), p0); - AddDescText(color, true, "~%d", p1); - } - else - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_VITALITY), p0); - } - } - else - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_VITALITY), p0); - } - break; + if (local) + { + if (p0 != p1) + { + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_VITALITY), p0); + AddDescText(color, true, "~%d", p1); + } + else + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_VITALITY), p0); + } + } + else + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_VITALITY), p0); + } + break; case 45: // ����һ���� - - if(local) - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_DEADLYSTRIKE), VisualizeFloatPercent(p0)); - } - else - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_DEADLYSTRIKE), p0); - } - break; - + if (local) + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_DEADLYSTRIKE), VisualizeFloatPercent(p0)); + } + else + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_DEADLYSTRIKE), p0); + } + break; + case 46: // ���� - - if(local) - { - if(p0 != p1) - { - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_ATKRATING), p0); - AddDescText(color, true, "~%d", p1); - } - else - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_ATKRATING), p0); - } - } - else - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_ATKRATING), p0); - } - break; - + if (local) + { + if (p0 != p1) + { + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_ATKRATING), p0); + AddDescText(color, true, "~%d", p1); + } + else + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_ATKRATING), p0); + } + } + else + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_ATKRATING), p0); + } + break; + case 47: // ����(%) - - if(local) - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_ATKRATINGEXTRA), VisualizeFloatPercent(p0)); - } - else - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_ATKRATINGEXTRA), p0); - } - break; - + if (local) + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_ATKRATINGEXTRA), VisualizeFloatPercent(p0)); + } + else + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_ATKRATINGEXTRA), p0); + } + break; + case 48: // �ƶ��ٶ� - - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_RUNSPEED), IntToFloat(p0)); - break; - + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_RUNSPEED), IntToFloat(p0)); + break; + case 49: // �ƶ��ٶ�(%) - - if(local) - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_RUNSPEEDEXTRA), VisualizeFloatPercent(p0)); - } - else - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_RUNSPEEDEXTRA), p0); - } - break; - + if (local) + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_RUNSPEEDEXTRA), VisualizeFloatPercent(p0)); + } + else + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_RUNSPEEDEXTRA), p0); + } + break; + case 50: // ���� - - if(!local) - { - if (aPEEVals != null) - aPEEVals[PEEI_DODGE] += p0; - } - - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_DODGE)); - AddDescText(color, true, " %+d", p0); - break; - + if (!local) + { + if (aPEEVals != null) + aPEEVals[PEEI_DODGE] += p0; + } + + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_DODGE)); + AddDescText(color, true, " %+d", p0); + break; + case 51: // ����(%) - - if(local) - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_DODGEEXTRA), VisualizeFloatPercent(p0)); - } - else - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_DODGEEXTRA), p0); - } - break; - + if (local) + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_DODGEEXTRA), VisualizeFloatPercent(p0)); + } + else + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_DODGEEXTRA), p0); + } + break; + case 52: // �;ö� - - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_ENDURANCE)); - AddDescText(color, true, " %+d", p0); - break; - + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_ENDURANCE)); + AddDescText(color, true, " %+d", p0); + break; + case 53: // �;ö�(%) - - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_ENDURANCEEXTRA), VisualizeFloatPercent(p0)); - break; - + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_ENDURANCEEXTRA), VisualizeFloatPercent(p0)); + break; + case 54: // �������� - - if(local) - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_PHYRESIST), VisualizeFloatPercent(p0)); - } - else - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_PHYRESIST), p0); - } - break; - + if (local) + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_PHYRESIST), VisualizeFloatPercent(p0)); + } + else + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_PHYRESIST), p0); + } + break; + case 55: // ���Ӽ��� { // Get skill description - TODO: Implement skill description retrieval @@ -3422,108 +3354,94 @@ namespace PerfectWorld.Scripts.Managers AddDescText(color, true, "{0}", skillDesc); break; } + case 56: // װ������ - - if(local) - { - if(VisualizeFloatPercent(p0) != VisualizeFloatPercent(p1)) - { - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_REQEXTRA), -VisualizeFloatPercent(p0)); - AddDescText(color, true, "~%d", VisualizeFloatPercent(p1)); - } - else - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_REQEXTRA), -VisualizeFloatPercent(p0)); - } - } - else - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_REQEXTRA), -VisualizeFloatPercent(p0)); - } - break; - + if (local) + { + if (VisualizeFloatPercent(p0) != VisualizeFloatPercent(p1)) + { + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_REQEXTRA), -VisualizeFloatPercent(p0)); + AddDescText(color, true, "~%d", VisualizeFloatPercent(p1)); + } + else + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_REQEXTRA), -VisualizeFloatPercent(p0)); + } + } + else + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_REQEXTRA), -VisualizeFloatPercent(p0)); + } + break; + case 57: // δ֪���� - - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_RANDOMPROP)); - break; - + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_RANDOMPROP)); + break; + case 58: // ����ֵ�ӳ� - - if(local) - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_EXP), VisualizeFloatPercent(p0)); - } - else - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_EXP), p0); - } - break; - + if (local) + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_EXP), VisualizeFloatPercent(p0)); + } + else + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_EXP), p0); + } + break; + case 59: // �����ȼ� - - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_ATK_DEGREE), p0); - break; - + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_ATK_DEGREE), p0); + break; + case 60: // �����ȼ� - - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_DEF_DEGREE), p0); - break; - + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_DEF_DEGREE), p0); + break; + case 61: // ���з�����%�� - - if(local) - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_TOTAL_DEFENCE_ADD), VisualizeFloatPercent(p0)); - else - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_TOTAL_DEFENCE_ADD), (p0)); - - break; - + if (local) + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_TOTAL_DEFENCE_ADD), VisualizeFloatPercent(p0)); + else + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_TOTAL_DEFENCE_ADD), (p0)); + break; + case 62: // ����֮�� - - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_PROFVIEW)); - break; - + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_PROFVIEW)); + break; + case 63: // ���� - - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_SOULPOWER), p0); - break; - + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_SOULPOWER), p0); + break; + case 64: // ��ϵ����(%) - - AddResistDesc(color, DescriptipionMsg.ITEMDESC_GOLDRESIST, p0, local); - break; - + AddResistDesc(color, DescriptipionMsg.ITEMDESC_GOLDRESIST, p0, local); + break; + case 65: // ľϵ����(%) - - AddResistDesc(color, DescriptipionMsg.ITEMDESC_WOODRESIST, p0, local); - break; - + AddResistDesc(color, DescriptipionMsg.ITEMDESC_WOODRESIST, p0, local); + break; + case 66: // ˮϵ����(%) - - AddResistDesc(color, DescriptipionMsg.ITEMDESC_WATERRESIST, p0, local); - break; - + AddResistDesc(color, DescriptipionMsg.ITEMDESC_WATERRESIST, p0, local); + break; + case 67: // ��ϵ����(%) - - AddResistDesc(color, DescriptipionMsg.ITEMDESC_FIRERESIST, p0, local); - break; - + AddResistDesc(color, DescriptipionMsg.ITEMDESC_FIRERESIST, p0, local); + break; + case 68: // ��ϵ����(%) - - AddResistDesc(color, DescriptipionMsg.ITEMDESC_EARTHRESIST, p0, local); - break; - + AddResistDesc(color, DescriptipionMsg.ITEMDESC_EARTHRESIST, p0, local); + break; + case 69: // ���м���(%) - - if(local) - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_ALLMAGICRESIST), VisualizeFloatPercent(p0)); - } - else - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_ALLMAGICRESIST), p0); - } - break; + if (local) + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_ALLMAGICRESIST), VisualizeFloatPercent(p0)); + } + else + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_ALLMAGICRESIST), p0); + } + break; case 70: // �����ȼ���Χ������ֵ������ã� @@ -3544,273 +3462,226 @@ namespace PerfectWorld.Scripts.Managers { AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_ATK_DEGREE), p0); } - break; - + break; + case 71: // �����ȼ���Χ������ֵ������ã� - - AddRangeValueDescIdNormal(DescriptipionMsg.ITEMDESC_DEF_DEGREE, p0, p1, local, color); - break; - + AddRangeValueDescIdNormal(DescriptipionMsg.ITEMDESC_DEF_DEGREE, p0, p1, local, color); + break; + case 72: // ����һ����(%)��Χ������ֵ������ã� - - AddRangeValueDescIdPercent(DescriptipionMsg.ITEMDESC_DEADLYSTRIKE, p0, p1, local, color); - break; - + AddRangeValueDescIdPercent(DescriptipionMsg.ITEMDESC_DEADLYSTRIKE, p0, p1, local, color); + break; + case 73: // HP��Χ������ֵ������ã� - - AddRangeValueDescStrNormal(DescriptipionMsg.ITEMDESC_ADDHP, p0, p1, local, color); - break; - + AddRangeValueDescStrNormal(DescriptipionMsg.ITEMDESC_ADDHP, p0, p1, local, color); + break; + case 74: // MP��Χ������ֵ������ã� - - AddRangeValueDescStrNormal(DescriptipionMsg.ITEMDESC_ADDMP, p0, p1, local, color); - break; - + AddRangeValueDescStrNormal(DescriptipionMsg.ITEMDESC_ADDMP, p0, p1, local, color); + break; + case 75: // ����(%)��Χ������ֵ������ã� - - AddRangeValueDescIdPercent(DescriptipionMsg.ITEMDESC_ATKRATINGEXTRA, p0, p1, local, color); - break; - + AddRangeValueDescIdPercent(DescriptipionMsg.ITEMDESC_ATKRATINGEXTRA, p0, p1, local, color); + break; + case 76: // ���������Χ������ֵ������ã� - - AddRangeValueDescStrNormal(DescriptipionMsg.ITEMDESC_PHYDEFENCE, p0, p1, local, color); - break; - + AddRangeValueDescStrNormal(DescriptipionMsg.ITEMDESC_PHYDEFENCE, p0, p1, local, color); + break; + case 77: // ���з�����Χ������ֵ������ã� - - AddRangeValueDescStrNormal(DescriptipionMsg.ITEMDESC_ALLMAGICDEF, p0, p1, local, color); - break; - + AddRangeValueDescStrNormal(DescriptipionMsg.ITEMDESC_ALLMAGICDEF, p0, p1, local, color); + break; + case 78: // �������(%)��Χ������ֵ������ã� - - AddRangeValueDescIdPercent(DescriptipionMsg.ITEMDESC_PHYRESIST, p0, p1, local, color); - break; - + AddRangeValueDescIdPercent(DescriptipionMsg.ITEMDESC_PHYRESIST, p0, p1, local, color); + break; + case 79: // ���м���(%)��Χ������ֵ������ã� - - AddRangeValueDescIdPercent(DescriptipionMsg.ITEMDESC_ALLMAGICRESIST, p0, p1, local, color); - break; - + AddRangeValueDescIdPercent(DescriptipionMsg.ITEMDESC_ALLMAGICRESIST, p0, p1, local, color); + break; + case 80: // ����ʱ��(%)��Χ������ֵ������ã� - - AddRangeValueDescIdMinusPercent1(DescriptipionMsg.ITEMDESC_CASTTIME, p0, p1, local, color); - break; - + AddRangeValueDescIdMinusPercent1(DescriptipionMsg.ITEMDESC_CASTTIME, p0, p1, local, color); + break; + case 81: // �������뷶Χ������ֵ������ã� - - AddRangeValueDescIdFloat(DescriptipionMsg.ITEMDESC_ADDATKDIST, p0, p1, local, color); - break; - + AddRangeValueDescIdFloat(DescriptipionMsg.ITEMDESC_ADDATKDIST, p0, p1, local, color); + break; + case 82: // MP�ָ��ٶȷ�Χ������ֵ������ã� - - AddRangeValueDescIdHalf(DescriptipionMsg.ITEMDESC_MPRECOVER, p0, p1, local, color); - break; - + AddRangeValueDescIdHalf(DescriptipionMsg.ITEMDESC_MPRECOVER, p0, p1, local, color); + break; + case 83: // �������(%)��Χ������ֵ������ã� - - AddRangeValueDescIdPercent(DescriptipionMsg.ITEMDESC_PHYDEFEXTRA, p0, p1, local, color); - break; - + AddRangeValueDescIdPercent(DescriptipionMsg.ITEMDESC_PHYDEFEXTRA, p0, p1, local, color); + break; + case 84: // ���з���(%)��Χ������ֵ������ã� - - AddRangeValueDescIdPercent(DescriptipionMsg.ITEMDESC_TOTAL_DEFENCE_ADD, p0, p1, local, color); - break; - + AddRangeValueDescIdPercent(DescriptipionMsg.ITEMDESC_TOTAL_DEFENCE_ADD, p0, p1, local, color); + break; + case 85: // HP�ָ��ٶȷ�Χ������ֵ������ã� - - AddRangeValueDescIdHalf(DescriptipionMsg.ITEMDESC_HPRECOVER, p0, p1, local, color); - break; - + AddRangeValueDescIdHalf(DescriptipionMsg.ITEMDESC_HPRECOVER, p0, p1, local, color); + break; + case 86: // ������Χ������ֵ������ã� - - AddRangeValueDescStrNormal(DescriptipionMsg.ITEMDESC_DODGE, p0, p1, local, color); - break; - + AddRangeValueDescStrNormal(DescriptipionMsg.ITEMDESC_DODGE, p0, p1, local, color); + break; + case 87: // ���������޷�Χ������ֵ������ã� - - AddRangeValueDescIdNormal(DescriptipionMsg.ITEMDESC_MAXPHYDAMAGE, p0, p1, local, color); - break; - + AddRangeValueDescIdNormal(DescriptipionMsg.ITEMDESC_MAXPHYDAMAGE, p0, p1, local, color); + break; + case 88: // ħ���������޷�Χ������ֵ������ã� - - AddRangeValueDescIdNormal(DescriptipionMsg.ITEMDESC_MAXMAGICDAMAGE, p0, p1, local, color); - break; - + AddRangeValueDescIdNormal(DescriptipionMsg.ITEMDESC_MAXMAGICDAMAGE, p0, p1, local, color); + break; + case 89: // װ������Χ������ֵ������ã� - - AddRangeValueDescIdMinusPercent2(DescriptipionMsg.ITEMDESC_REQEXTRA, p0, p1, local, color); - break; + AddRangeValueDescIdMinusPercent2(DescriptipionMsg.ITEMDESC_REQEXTRA, p0, p1, local, color); + break; case 90: // ��ħ�ȼ� - - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_PENETRATION), p0); - break; - + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_PENETRATION), p0); + break; + case 91: // ��ħ�ȼ� - - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_RESILIENCE), p0); - break; - + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_RESILIENCE), p0); + break; + case 92: // +���+ħ�� - - if(!local) - { - if (aPEEVals != null) - { - aPEEVals[PEEI_PHYDEF] += p0; - aPEEVals[PEEI_GOLDDEF] += p1; - aPEEVals[PEEI_WOODDEF] += p1; - aPEEVals[PEEI_WATERDEF] += p1; - aPEEVals[PEEI_FIREDEF] += p1; - aPEEVals[PEEI_EARTHDEF] += p1; - } - } - - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_PHYDEFENCE)); - AddDescText(color, true, " %+d", p0); - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_ALLMAGICDEF)); - AddDescText(color, true, " %+d", p1); - break; - + if (!local) + { + if (aPEEVals != null) + { + aPEEVals[PEEI_PHYDEF] += p0; + aPEEVals[PEEI_GOLDDEF] += p1; + aPEEVals[PEEI_WOODDEF] += p1; + aPEEVals[PEEI_WATERDEF] += p1; + aPEEVals[PEEI_FIREDEF] += p1; + aPEEVals[PEEI_EARTHDEF] += p1; + } + } + + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_PHYDEFENCE)); + AddDescText(color, true, " %+d", p0); + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_ALLMAGICDEF)); + AddDescText(color, true, " %+d", p1); + break; + case 93: // ��ɫHP - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_ADDHP)); - AddDescText(color, true, " %+d", p0); - break; - + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_ADDHP)); + AddDescText(color, true, " %+d", p0); + break; + case 94: // ��ɫHP��Χ - AddRangeValueDescStrNormal(DescriptipionMsg.ITEMDESC_ADDHP, p0, p1, local, color); - break; - + AddRangeValueDescStrNormal(DescriptipionMsg.ITEMDESC_ADDHP, p0, p1, local, color); + break; + case 95: // ���� - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_STRENGTH), p0); - break; - + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_STRENGTH), p0); + break; + case 96: // ���� - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_AGILITY), p0); - break; - + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_AGILITY), p0); + break; + case 97: // ���� - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_ENERGY), p0); - break; - + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_ENERGY), p0); + break; + case 98: // ���� - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_VITALITY), p0); - break; - + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_VITALITY), p0); + break; + case 99: // ��ɫMP - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_ADDMP)); - AddDescText(color, true, " %+d", p0); - break; - + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_ADDMP)); + AddDescText(color, true, " %+d", p0); + break; + case 160: // �����̶�ֵ - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_VIGOUR)); - AddDescText(color, true, " %+d", p0); - break; - + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_VIGOUR)); + AddDescText(color, true, " %+d", p0); + break; + case 200: // ���������� - if (aRefines != null) - aRefines[REFINE_PHYDAMAGE] += p0; - - break; + aRefines[REFINE_PHYDAMAGE] += p0; + break; case 201: // ����ħ������ - if (aRefines != null) - aRefines[REFINE_MAGICDAMAGE] += p0; - - break; - + aRefines[REFINE_MAGICDAMAGE] += p0; + break; + case 202: // ����������� - if (aRefines != null) - aRefines[REFINE_PHYDEF] += p0; - - break; - + aRefines[REFINE_PHYDEF] += p0; + break; + case 203: // ������� - if (aRefines != null) - aRefines[REFINE_GOLDDEF] += p0; - - break; - + aRefines[REFINE_GOLDDEF] += p0; + break; + case 204: // ����ľ�� - if (aRefines != null) - aRefines[REFINE_WOODDEF] += p0; - - break; - + aRefines[REFINE_WOODDEF] += p0; + break; + case 205: // ����ˮ�� - if (aRefines != null) - aRefines[REFINE_WATERDEF] += p0; - - break; - + aRefines[REFINE_WATERDEF] += p0; + break; + case 206: // ������� - if (aRefines != null) - aRefines[REFINE_FIREDEF] += p0; - - break; - + aRefines[REFINE_FIREDEF] += p0; + break; + case 207: // �������� - if (aRefines != null) - aRefines[REFINE_EARTHDEF] += p0; - - break; - + aRefines[REFINE_EARTHDEF] += p0; + break; + case 208: // ����HP - if (aRefines != null) - aRefines[REFINE_HP] += p0; - - break; - + aRefines[REFINE_HP] += p0; + break; + case 209: // �������� - if (aRefines != null) - aRefines[REFINE_DODGE] += p0; - - break; - + aRefines[REFINE_DODGE] += p0; + break; + case 210: // �������з��� - if (aRefines != null) - { - aRefines[REFINE_GOLDDEF] += p0; - aRefines[REFINE_WOODDEF] += p0; - aRefines[REFINE_WATERDEF] += p0; - aRefines[REFINE_FIREDEF] += p0; - aRefines[REFINE_EARTHDEF] += p0; - } - - break; - + { + aRefines[REFINE_GOLDDEF] += p0; + aRefines[REFINE_WOODDEF] += p0; + aRefines[REFINE_WATERDEF] += p0; + aRefines[REFINE_FIREDEF] += p0; + aRefines[REFINE_EARTHDEF] += p0; + } + break; + case 211: // ���������� & ħ������ - if (aRefines != null) - { - aRefines[REFINE_PHYDAMAGE] += p0; - aRefines[REFINE_MAGICDAMAGE] += p0; - } - - break; - + { + aRefines[REFINE_PHYDAMAGE] += p0; + aRefines[REFINE_MAGICDAMAGE] += p0; + } + break; + case 212: // ����������� & ħ������ - if (aRefines != null) - { - aRefines[REFINE_PHYDEF] += p0; - aRefines[REFINE_GOLDDEF] += p0; - aRefines[REFINE_WOODDEF] += p0; - aRefines[REFINE_WATERDEF] += p0; - aRefines[REFINE_FIREDEF] += p0; - aRefines[REFINE_EARTHDEF] += p0; - } + { + aRefines[REFINE_PHYDEF] += p0; + aRefines[REFINE_GOLDDEF] += p0; + aRefines[REFINE_WOODDEF] += p0; + aRefines[REFINE_WATERDEF] += p0; + aRefines[REFINE_FIREDEF] += p0; + aRefines[REFINE_EARTHDEF] += p0; + } break; @@ -3822,230 +3693,203 @@ namespace PerfectWorld.Scripts.Managers break; case 121: // �Կ�ľ�� - - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_WOODDEFENCE)); - AddDescText(color, true, " %+d", p0); - break; - + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_WOODDEFENCE)); + AddDescText(color, true, " %+d", p0); + break; + case 122: // �Կ�ˮ�� - - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_WATERDEFENCE)); - AddDescText(color, true, " %+d", p0); - break; - + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_WATERDEFENCE)); + AddDescText(color, true, " %+d", p0); + break; + case 123: // �Կ̻�� - - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_FIREDEFENCE)); - AddDescText(color, true, " %+d", p0); - break; - + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_FIREDEFENCE)); + AddDescText(color, true, " %+d", p0); + break; + case 124: // �Կ����� - - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_EARTHDEFENCE)); - AddDescText(color, true, " %+d", p0); - break; - + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_EARTHDEFENCE)); + AddDescText(color, true, " %+d", p0); + break; + case 125: // �Կ����� - - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_ATKRATING), p0); - break; - + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_ATKRATING), p0); + break; + case 126: // �Կ̶��� - - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_DODGE)); - AddDescText(color, true, " %+d", p0); - break; - + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_DODGE)); + AddDescText(color, true, " %+d", p0); + break; + case 127: // �Կ�MP - - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_ADDMP)); - AddDescText(color, true, " %+d", p0); - break; - + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_ADDMP)); + AddDescText(color, true, " %+d", p0); + break; + case 128: // �Կ����� - - if(local) - { - if(p0 != p1) - { - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_VITALITY), p0); - AddDescText(color, true, "~%d", p1); - } - else - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_VITALITY), p0); - } - } - else - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_VITALITY), p0); - } - break; - + if (local) + { + if (p0 != p1) + { + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_VITALITY), p0); + AddDescText(color, true, "~%d", p1); + } + else + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_VITALITY), p0); + } + } + else + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_VITALITY), p0); + } + break; + case 129: // �Կ����� - - if(local) - { - if(p0 != p1) - { - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_STRENGTH), p0); - AddDescText(color, true, "~%d", p1); - } - else - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_STRENGTH), p0); - } - } - else - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_STRENGTH), p0); - } - break; - + if (local) + { + if (p0 != p1) + { + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_STRENGTH), p0); + AddDescText(color, true, "~%d", p1); + } + else + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_STRENGTH), p0); + } + } + else + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_STRENGTH), p0); + } + break; + case 130: // �Կ����� - - if(local) - { - if(p0 != p1) - { - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_AGILITY), p0); - AddDescText(color, true, "~%d", p1); - } - else - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_AGILITY), p0); - } - } - else - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_AGILITY), p0); - } - break; - + if (local) + { + if (p0 != p1) + { + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_AGILITY), p0); + AddDescText(color, true, "~%d", p1); + } + else + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_AGILITY), p0); + } + } + else + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_AGILITY), p0); + } + break; + case 131: // �Կ����� - - if(local) - { - if(p0 != p1) - { - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_ENERGY), p0); - AddDescText(color, true, "~%d", p1); - } - else - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_ENERGY), p0); - } - } - else - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_ENERGY), p0); - } - break; - + if (local) + { + if (p0 != p1) + { + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_ENERGY), p0); + AddDescText(color, true, "~%d", p1); + } + else + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_ENERGY), p0); + } + } + else + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_ENERGY), p0); + } + break; + case 132: // �Կ�HP - - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_ADDHP)); - AddDescText(color, true, " %+d", p0); - break; - + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_ADDHP)); + AddDescText(color, true, " %+d", p0); + break; + case 133: // �Կ�������� - - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_PHYDEFENCE)); - AddDescText(color, true, " %+d", p0); - break; - + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_PHYDEFENCE)); + AddDescText(color, true, " %+d", p0); + break; + case 134: // �Կ����з��� - - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_ALLMAGICDEF)); - AddDescText(color, true, " %+d", p0); - break; - + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_ALLMAGICDEF)); + AddDescText(color, true, " %+d", p0); + break; + case 135: // �Կ������� - - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_ADDPHYDAMAGE)); - AddDescText(color, true, " %+d", p0); - break; - + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_ADDPHYDAMAGE)); + AddDescText(color, true, " %+d", p0); + break; + case 136: // �Կ�ħ������ - - AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_ADDMAGICDAMAGE)); - AddDescText(color, true, " %+d", p0); - break; - + AddDescText(color, false, GetItemDescString(DescriptipionMsg.ITEMDESC_ADDMAGICDAMAGE)); + AddDescText(color, true, " %+d", p0); + break; + case 137: // �Կ̽�ϵ����(%) - - AddResistDesc(color, DescriptipionMsg.ITEMDESC_GOLDRESIST, p0, local); - break; - + AddResistDesc(color, DescriptipionMsg.ITEMDESC_GOLDRESIST, p0, local); + break; + case 138: // �Կ�ľϵ����(%) - - AddResistDesc(color, DescriptipionMsg.ITEMDESC_WOODRESIST, p0, local); - break; - + AddResistDesc(color, DescriptipionMsg.ITEMDESC_WOODRESIST, p0, local); + break; + case 139: // �Կ�ˮϵ����(%) - - AddResistDesc(color, DescriptipionMsg.ITEMDESC_WATERRESIST, p0, local); - break; - + AddResistDesc(color, DescriptipionMsg.ITEMDESC_WATERRESIST, p0, local); + break; + case 140: // �Կ̻�ϵ����(%) - - AddResistDesc(color, DescriptipionMsg.ITEMDESC_FIRERESIST, p0, local); - break; - + AddResistDesc(color, DescriptipionMsg.ITEMDESC_FIRERESIST, p0, local); + break; + case 141: // �Կ���ϵ����(%) - - AddResistDesc(color, DescriptipionMsg.ITEMDESC_EARTHRESIST, p0, local); - break; + AddResistDesc(color, DescriptipionMsg.ITEMDESC_EARTHRESIST, p0, local); + break; case 142: // �Կ����м���(%) - - if(local) - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_ALLMAGICRESIST), VisualizeFloatPercent(p0)); - } - else - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_ALLMAGICRESIST), p0); - } - break; - + if (local) + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_ALLMAGICRESIST), VisualizeFloatPercent(p0)); + } + else + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_ALLMAGICRESIST), p0); + } + break; + case 143: // �Կ�����һ���� - - if(local) - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_DEADLYSTRIKE), VisualizeFloatPercent(p0)); - } - else - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_DEADLYSTRIKE), p0); - } - break; - + if (local) + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_DEADLYSTRIKE), VisualizeFloatPercent(p0)); + } + else + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_DEADLYSTRIKE), p0); + } + break; + case 144: // �Կ̹����ȼ� - - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_ATK_DEGREE), p0); - break; - + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_ATK_DEGREE), p0); + break; + case 145: // �Կ̷����ȼ� - - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_DEF_DEGREE), p0); - break; - + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_DEF_DEGREE), p0); + break; + case 146: // �Կ��������� - - if(local) - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_PHYRESIST), VisualizeFloatPercent(p0)); - } - else - { - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_PHYRESIST), p0); - } - break; - - default: - - AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_ERRORPROP), idProp); + if (local) + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_PHYRESIST), VisualizeFloatPercent(p0)); + } + else + { + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_PHYRESIST), p0); + } + break; + + default: + AddDescText(color, true, GetItemDescString(DescriptipionMsg.ITEMDESC_ERRORPROP), idProp); break; } } diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrFashion.cs b/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrFashion.cs index 8b319c9e68..bc8f057142 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrFashion.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrFashion.cs @@ -1,8 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using System.IO; +using BrewMonster; +using ModelRenderer.Scripts.Common; +using ModelRenderer.Scripts.GameData; +using UnityEngine; +using PerfectWorld.Scripts.Managers; +using BrewMonster.Network; using BrewMonster.Scripts.Managers; +using BrewMonster.Scripts; +using CSNetwork.GPDataType; +using System.Runtime.InteropServices; namespace PerfectWorld.Scripts.Managers { - public class EC_IvtrFashion : EC_IvtrItem + public class EC_IvtrFashion : EC_IvtrEquip { + protected int m_iGender; // required gender + protected ushort m_wColor; // color in X1R5G5B5 format + protected uint m_color; // color in X8R8G8B8 format + + protected IVTR_ESSENCE_FASHION m_Essence; // Fashion essence data + + // Data in database + protected FASHION_MAJOR_TYPE m_pDBMajorType; + protected FASHION_SUB_TYPE m_pDBSubType; + protected FASHION_ESSENCE m_pDBEssence; /// /// Not create logic yet (add summary later) /// @@ -10,10 +33,210 @@ namespace PerfectWorld.Scripts.Managers /// Expire date public EC_IvtrFashion(int tid, int expire_date) : base(tid, expire_date) { + m_iCID = (int)InventoryClassId.ICID_FASHION; + + m_Essence = new IVTR_ESSENCE_FASHION(); + + // Get database data + elementdataman pDB = ElementDataManProvider.GetElementDataMan(); + DATA_TYPE DataType = DATA_TYPE.DT_INVALID; + m_pDBEssence = (FASHION_ESSENCE)pDB.get_data_ptr((uint)tid, ID_SPACE.ID_SPACE_ESSENCE, ref DataType); + m_pDBMajorType = (FASHION_MAJOR_TYPE)pDB.get_data_ptr(m_pDBEssence.id_major_type, ID_SPACE.ID_SPACE_ESSENCE, ref DataType); + m_pDBSubType = (FASHION_SUB_TYPE)pDB.get_data_ptr(m_pDBEssence.id_sub_type, ID_SPACE.ID_SPACE_ESSENCE, ref DataType); + + m_iPileLimit = m_pDBEssence.pile_num_max; + m_iPrice = m_pDBEssence.price; + m_iShopPrice = m_pDBEssence.shop_price; + m_i64EquipMask = m_pDBSubType.equip_fashion_mask; + m_iProcType = (int)m_pDBEssence.proc_type; + + // reset the info + DefaultInfo(); } public EC_IvtrFashion(EC_IvtrFashion other) : base(other) + { + m_pDBEssence = other.m_pDBEssence; + m_pDBMajorType = other.m_pDBMajorType; + m_pDBSubType = other.m_pDBSubType; + m_Essence = other.m_Essence; + m_iGender = other.m_iGender; + m_wColor = other.m_wColor; + m_color = other.m_color; + } + + // Set item detail information + public override bool SetItemInfo(byte[] pInfoData, int iDataLen) { + // Note: because fashion is not an absolute equipment, so skip + // CECIvtrEquip::SetItemInfo(). + + if (pInfoData == null || iDataLen == 0) + { + m_bNeedUpdate = false; + return true; + } + + try + { + CECDataReader dr = new CECDataReader(pInfoData, iDataLen); + var size = Marshal.SizeOf(); + m_Essence = new IVTR_ESSENCE_FASHION(dr.ReadData(size)); + } + catch (Exception e) + { + Debug.LogError("CECIvtrFashion::SetItemInfo, data read error (" + e.GetType() + e.StackTrace + ")"); + return false; + } + + LevelReq = m_Essence.require_level; + m_wColor = m_Essence.color; + m_iGender = m_Essence.gender; + + m_color = (uint)FASHION_WORDCOLOR_TO_A3DCOLOR(m_wColor).GetHashCode(); + + m_bNeedUpdate = false; + return true; + } + // Get item default information from database + public override void DefaultInfo() + { + LevelReq = m_pDBEssence.require_level; + m_wColor = 0x7fff; + m_iGender = m_pDBEssence.gender; + m_color = 0xffffffff; + + // these data also stored in essence, sync it here + m_Essence.require_level = LevelReq; + m_Essence.color = m_wColor; + m_Essence.gender = (ushort)m_iGender; + } + public static Color FASHION_WORDCOLOR_TO_A3DCOLOR(ushort color) + { + return new Color(((color & (0x1f << 10)) >> 7), ((color & (0x1f << 5)) >> 2), ((color & 0x1f) << 3)); + } + public string GetSubTypeName() + { + // Try Unicode first (for Vietnamese/wide char names), then fallback to CP936 + if (m_pDBSubType.name != null && m_pDBSubType.name.Length > 0) + { + string s = ByteToStringUtils.UshortArrayToUnicodeString(m_pDBSubType.name); + if (!string.IsNullOrEmpty(s) && !string.IsNullOrWhiteSpace(s)) + return s; + // Fallback to legacy CP936 if Unicode was empty + s = ByteToStringUtils.UshortArrayToCP936String(m_pDBSubType.name); + if (!string.IsNullOrEmpty(s)) + return s; + } + return ""; + } + + protected override string GetNormalDesc(bool bRepair) + { + if (m_bNeedUpdate) + return ""; + + m_strDesc = ""; + + // Try to build item description + CECStringTab pDescTab = EC_Game.GetItemDesc(); + CECHostPlayer pHost = EC_Game.GetGameRun().GetHostPlayer(); + int white = (int)DescriptipionMsg.ITEMDESC_COL_WHITE; + int red = (int)DescriptipionMsg.ITEMDESC_COL_RED; + int namecol = DecideNameCol(); + + // Item name + AddDescText(namecol, true, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_NAME), GetName()); + + AddIDDescText(); + + AddBindDescText(); + + AddExpireTimeDesc(); + + // Sub class name + AddDescText(white, true, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_CLASSNAME), GetSubTypeName()); + + // Color + // Use m_iScaleType == SCALE_BUY to judge whether this item is in NPC's pack, + // this may not be a valid way + if (m_pDBEssence.equip_location != (int)enumSkinShow.enumSkinShowArmet && m_pDBEssence.equip_location != (int)enumSkinShow.enumSkinShowHand) + { + if (m_iScaleType == (int)EC_IvtrItem.ScaleType.SCALE_BUY) + { + AddDescText(white, false, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_COLOR)); + AddDescText(white, true, (" ???")); + } + else + { + // Extract RGB components from m_color (X8R8G8B8 format) + int colorRed = (int)((m_color >> 16) & 0xFF); + int colorGreen = (int)((m_color >> 8) & 0xFF); + int colorBlue = (int)(m_color & 0xFF); + string szCol = string.Format("^{0:X2}{1:X2}{2:X2}", colorRed, colorGreen, colorBlue); + + AddDescText(white, false, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_COLOR)); + m_strDesc += " "; + AddDescText(-1, true, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_COLORRECT), szCol); + } + + } + // Level requirment + if (LevelReq > 0) + { + int lcol = pHost.GetMaxLevelSofar() >= LevelReq ? white : red; + AddDescText(lcol, true, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_LEVELREQ), LevelReq); + } + // fashion weapon profession requirment and weapon action type + if (m_pDBEssence.equip_location == (int)enumSkinShow.enumSkinShowHand) + { + AddDescText(-1, true, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_LEVEL), m_pDBEssence.level); + AddProfReqDesc(m_pDBEssence.character_combo_id); + AddActionTypeDescText((int)m_pDBEssence.action_type); + } + + // Gender requirement + CECStringTab pFixMsg = EC_Game.GetFixedMsgs(); + int col = (pHost.GetGender() == m_iGender) ? white : red; + AddDescText(col, false, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_GENDERREQ)); + m_strDesc += " "; + if (m_iGender == (int)GENDER.GENDER_MALE) + AddDescText(col, true, pFixMsg.GetWideString((int)FixedMsg.FIXMSG_GENDER_MALE)); + else + AddDescText(col, true, pFixMsg.GetWideString((int)FixedMsg.FIXMSG_GENDER_FEMALE)); + + // Price + AddPriceDesc(white, bRepair); + + // Fashion level + if (m_pDBEssence.level > 0) + { + m_strDesc += "\\r"; + m_strDesc += pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_COL_WHITE); + for (int i=0; i < m_pDBEssence.level; i++) + m_strDesc += pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_PENTAGON); + } + + // Extend description + AddExtDescText(); + + return m_strDesc; + } + public bool HasRandomProp() + { + return false; + } + + // Get drop model for shown + public override string GetDropModel() + { + return m_pDBEssence.FileMatter; + } + + public int GetFashionSuiteID() + { + Dictionary suiteEquipTab = EC_Game.GetSuiteEquipTab(); + return suiteEquipTab.ContainsKey(TemplateId) ? suiteEquipTab[TemplateId] : 0; } } } diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrFlysword.cs b/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrFlysword.cs index 5e37a8b04c..ce0fbe94e0 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrFlysword.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrFlysword.cs @@ -1,20 +1,228 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using System.IO; +using BrewMonster; +using ModelRenderer.Scripts.Common; +using ModelRenderer.Scripts.GameData; +using UnityEngine; +using PerfectWorld.Scripts.Managers; +using BrewMonster.Network; using BrewMonster.Scripts.Managers; +using BrewMonster.Scripts; +using CSNetwork.GPDataType; +using System.Runtime.InteropServices; namespace PerfectWorld.Scripts.Managers { - public class EC_IvtrFlysword : EC_IvtrItem + + /// + /// Flysword Item (Phi kiem). + /// + public class EC_IvtrFlysword : EC_IvtrEquip { + + protected int m_iCurTime; // Current time counter in ms + protected IVTR_ESSENCE_FLYSWORD m_Essence; + protected FLYSWORD_ESSENCE m_pDBEssence; /// - /// Not create logic yet (add summary later) + /// Flysword Item (Phi kiem) /// /// Template id /// Expire date public EC_IvtrFlysword(int tid, int expire_date) : base(tid, expire_date) { + m_iCID = (int)InventoryClassId.ICID_FLYSWORD; + + // Get database data + elementdataman pDB = ElementDataManProvider.GetElementDataMan(); + DATA_TYPE DataType = DATA_TYPE.DT_INVALID; + m_pDBEssence = (FLYSWORD_ESSENCE)pDB.get_data_ptr((uint)tid, ID_SPACE.ID_SPACE_ESSENCE, ref DataType); + m_iPileLimit = m_pDBEssence.pile_num_max; + m_iPrice = m_pDBEssence.price; + m_iShopPrice = m_pDBEssence.shop_price; + m_iProcType = (int)m_pDBEssence.proc_type; + m_i64EquipMask = EC_IvtrType.EQUIP_MASK64_FLYSWORD; + m_bUseable = true; + m_bNeedUpdate = false; } public EC_IvtrFlysword(EC_IvtrFlysword other) : base(other) { + m_iCurTime = other.m_iCurTime; + m_Essence = other.m_Essence; + m_pDBEssence = other.m_pDBEssence; + MadeFrom = other.MadeFrom; + Maker = other.Maker; } + + public override bool SetItemInfo(byte[] pInfoData, int iDataLen) + { + // Note: because fly sword isn't an absolute equipment, so skip + // CECIvtrEquip::SetItemInfo(). + + if (pInfoData == null || iDataLen == 0) + { + m_bNeedUpdate = false; + return true; + } + + try + { + CECDataReader dr = new CECDataReader(pInfoData, iDataLen); + + m_Essence = new IVTR_ESSENCE_FLYSWORD(dr.ReadData(Marshal.SizeOf())); + base.ReadMakerInfo(dr); + } + catch (Exception e) + { + Debug.LogError("CECIvtrFlySword::SetItemInfo, data read error (" + e.GetType() + ")"); + return false; + } + + LevelReq = m_Essence.require_level; + m_bNeedUpdate = false; + m_iCurTime = m_Essence.cur_time * 1000; + + return true; + } + + public override string GetIconFile() + { + return m_pDBEssence.FileIcon; + } + protected override string GetNormalDesc(bool bRepair) + { + if (m_bNeedUpdate) + return string.Empty; + + m_strDesc = ""; + + // Try to build item description + CECStringTab pDescTab = EC_Game.GetItemDesc(); + CECHostPlayer pHost = EC_Game.GetGameRun().GetHostPlayer(); + int white = (int)DescriptipionMsg.ITEMDESC_COL_WHITE; + int red = (int)DescriptipionMsg.ITEMDESC_COL_RED; + int namecol = DecideNameCol(); + + if (m_iCount > 1) + AddDescText(namecol, true, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_NAMENUMBER), GetName(), m_iCount); + else + AddDescText(namecol, true, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_NAME), GetName()); + + AddIDDescText(); + + AddBindDescText(); + + // Is destroying? + AddDestroyingDesc((int)m_pDBEssence.id_drop_after_damaged, m_pDBEssence.num_drop_after_damaged); + + AddExpireTimeDesc(); + + // level + AddDescText(white, true, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_LEVEL), m_Essence.level); + + // whether can be improved + if (IsImprovable()) + AddDescText((int)DescriptipionMsg.ITEMDESC_COL_GREEN,true,pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_FLYSWORD_IMPROVE),m_Essence.improve_level,GetMaxImproveLevel()); + else + AddDescText(white,true,pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_FLYSWORD_NOIMPROVED)); + + // Normal fly speed bonus + if (m_Essence.speed_increase > 0) + AddDescText(white, true, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_ADDFLYSPEED), m_Essence.speed_increase); + + // Quick fly speed bonus + if (m_Essence.speed_increase2 > 0) + AddDescText(white, true, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_ADDFLYSPEED2), m_Essence.speed_increase2); + + // Remain time + if (GetMaxTime() > 0) + AddDescText(white, true, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_REMAINTIME), GetCurTime(), GetMaxTime()); + + // Profession requirement + AddProfReqDesc((uint)m_Essence.profession); + + // Level requirement + if (LevelReq > 0) + { + int col = pHost.GetMaxLevelSofar() >= LevelReq ? white : red; + AddDescText(col, true, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_LEVELREQ), LevelReq); + } + + // Element consume + // AddDescText(white, true, pDescTab->GetWideString(ITEMDESC_ELEMENTTIME), m_Essence.time_per_element); + + // Price + AddPriceDesc(white, bRepair); + + AddMakerDesc(); + + // Suite description + AddSuiteDesc(); + + // Extend description + AddExtDescText(); + + return m_strDesc; + } + // Get max time + protected int GetMaxTime() + { + return (int)m_Essence.max_time; + } + + // Get max element number + protected int GetMaxElement() + { + return (int)((float)m_Essence.max_time / m_Essence.time_per_element + 0.5f); + } + + // Get time each element equal to + protected int GetElementTime() + { + return m_Essence.time_per_element; + } + // Get number of element if time is filled to full. This is just the number + // of element which has been used + protected int GetUsedElementNum() + { + return (int)((m_Essence.max_time - GetCurTime()) / (float)m_Essence.time_per_element); + } + + // Get drop model for shown + protected string GetDropModel() + { + return m_pDBEssence.FileMatter; + } + public override bool IsRare() + { + return base.IsRare() || m_Essence.level >= 6; + } + protected bool IsImprovable() + { + return m_pDBEssence.max_improve_level > 0 && m_pDBEssence.improve_config[0].require_item_num > 0; + } + protected bool CanBeImproved() + { + if(m_pDBEssence.max_improve_level <=0) return false; + + if(m_Essence.improve_level>= GetMaxImproveLevel()) return false; + + return m_pDBEssence.improve_config[m_Essence.improve_level].require_item_num > 0; + } + protected int GetMaxImproveLevel() + { + int maxL = m_pDBEssence.improve_config.Length; + int i = 0; + for (i = 0; i < maxL; i++) + { + if(m_pDBEssence.improve_config[i].require_item_num == 0) + break; + } + return Mathf.Min(m_pDBEssence.max_improve_level, i); + } + + protected int GetCurTime() { return m_Essence.cur_time; } } } diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrItem.cs b/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrItem.cs index 67ab258250..e3f462fe8f 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrItem.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrItem.cs @@ -807,7 +807,8 @@ namespace BrewMonster.Scripts.Managers var pItem = new EC_IvtrItem(tid, expire_date); DATA_TYPE DataType = DATA_TYPE.DT_INVALID; object data = ElementDataManProvider.GetElementDataMan().get_data_ptr((uint)tid, ID_SPACE.ID_SPACE_ESSENCE, ref DataType); - Debug.Log("Create item data: DataType: " + DataType); + //Active this to log the data type of item when creating an item + //Debug.Log("Create item data: DataType: " + DataType + " tid: " + tid ); switch(DataType) { case DATA_TYPE.DT_WEAPON_ESSENCE: @@ -844,7 +845,7 @@ namespace BrewMonster.Scripts.Managers pItem = new EC_IvtrFlysword(tid, expire_date); break; case DATA_TYPE.DT_TOWNSCROLL_ESSENCE: - pItem = new EC_IvtrTownscroll(tid, expire_date); + pItem = new EC_IvtrTownScroll(tid, expire_date); break; case DATA_TYPE.DT_UNIONSCROLL_ESSENCE: pItem = new EC_IvtrUnionscroll(tid, expire_date); @@ -859,7 +860,7 @@ namespace BrewMonster.Scripts.Managers pItem = new EC_IvtrTossMat(tid, expire_date); break; case DATA_TYPE.DT_TASKMATTER_ESSENCE: - pItem = new EC_IvtrTaskmatter(tid, expire_date); + pItem = new EC_IvtrTaskItem(tid, expire_date); break; case DATA_TYPE.DT_STONE_ESSENCE: pItem = new EC_IvtrStone(tid, expire_date); diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrMaterial.cs b/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrMaterial.cs index 8c19d7a8ca..c0a2f041e9 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrMaterial.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrMaterial.cs @@ -77,7 +77,6 @@ namespace PerfectWorld.Scripts.Managers CECStringTab pDescTab = EC_Game.GetItemDesc(); int white = (int)DescriptipionMsg.ITEMDESC_COL_WHITE; int namecol = DecideNameCol(); - BMLogger.Log("GetNormalDesc: m_pDBEssence.Name:" + m_pDBEssence.Name + " m_iCount:" + m_iCount); if (m_iCount > 1) AddDescText(namecol, true, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_NAMENUMBER), GetName(), m_iCount); else diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrPetEgg.cs b/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrPetEgg.cs index 4b1c0917e4..38dacf7996 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrPetEgg.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrPetEgg.cs @@ -194,8 +194,82 @@ namespace PerfectWorld.Scripts.Managers } private string GetRidingPetDesc(bool bRepair) { - Debug.Log("GetRidingPetDesc. This is not implemented yet."); - return ""; + if (m_bNeedUpdate) + return ""; + + m_strDesc = string.Empty; + + // Try to build item description + CECStringTab pDescTab = EC_Game.GetItemDesc(); + CECHostPlayer pHost = EC_Game.GetGameRun().GetHostPlayer(); + + int white = (int)DescriptipionMsg.ITEMDESC_COL_WHITE; + int red = (int)DescriptipionMsg.ITEMDESC_COL_RED; + int namecol = DecideNameCol(); + + // Item name: always use the name in template + if (m_iCount > 1) + AddDescText(namecol, true, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_NAMENUMBER), m_pDBEssence.name/* GetName() */, m_iCount); + else + AddDescText(namecol, true, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_NAME), m_pDBEssence.name/* GetName() */); + + AddIDDescText(); + + AddBindDescText(); + + AddExpireTimeDesc(); + + // ������ɫ��Ϣ + if (m_pPetEssence.id != 0 && m_pPetEssence.require_dye_count > 0) + { + if (m_iScaleType == (int)ScaleType.SCALE_BUY) + { + AddDescText(white, false, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_COLOR)); + AddDescText(white, true, " ???"); + } + else + { + Color clr = new Color(255, 255, 255); + if (RIDINGPET.GetColor(m_Essence.color, clr)) + clr = RIDINGPET.GetDefaultColor(); + string strColor = string.Format("^{0:X2}{1:X2}{2:X2}", clr.r, clr.g, clr.b); + AddDescText(white, false, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_COLOR)); + m_strDesc += " "; + AddDescText(-1, true, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_COLORRECT), strColor); + } + } + + // Food type requirement + AddFoodTypeDesc(); + + if (m_pPetEssence.id != 0) + { + // Pet level + AddDescText(white, true, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_PETLEVEL), m_Essence.level); + + // Move speed + float fSpeed = m_pPetEssence.speed_a + (m_Essence.level - 1) * m_pPetEssence.speed_b; + AddDescText(-1, true, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_MOVESPEED), fSpeed); + + // Profession requirement + AddProfReqDesc(m_pPetEssence.character_combo_id); + } + + // Level requirement + int iLevelReq = Mathf.Max((int)m_Essence.level, m_Essence.req_level); + if (iLevelReq > 0) + { + int col = pHost.GetMaxLevelSofar() >= iLevelReq ? white : red; + AddDescText(col, true, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_LEVELREQ), iLevelReq); + } + + // Price + AddPriceDesc(white, bRepair); + + // Extend description + AddExtDescText(); + + return m_strDesc; } private string GetCombatPetDesc(bool bRepair) { diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrTaskDice.cs b/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrTaskDice.cs index ea1a6c2c09..934066e194 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrTaskDice.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrTaskDice.cs @@ -1,19 +1,84 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using System.IO; +using BrewMonster; +using ModelRenderer.Scripts.Common; +using ModelRenderer.Scripts.GameData; +using UnityEngine; +using PerfectWorld.Scripts.Managers; +using BrewMonster.Network; using BrewMonster.Scripts.Managers; +using BrewMonster.Scripts; +using CSNetwork.GPDataType; +using System.Runtime.InteropServices; namespace PerfectWorld.Scripts.Managers { + /// + /// Task Dice Item (Tui qua random). + /// This is a part of IvtrTaskItem(C++) + /// public class EC_IvtrTaskDice : EC_IvtrItem { + protected TASKDICE_ESSENCE m_pDBEssence; + /// - /// Not create logic yet (add summary later) + /// Task Dice Item /// - /// Template id - /// Expire date - public EC_IvtrTaskDice(int tid, int expire_date) : base(tid, expire_date) + /// + /// + public EC_IvtrTaskDice(int tid, int expire_date) : base(tid, expire_date) { - } + m_iCID = (int)InventoryClassId.ICID_TASKDICE; + elementdataman pDB = ElementDataManProvider.GetElementDataMan(); + DATA_TYPE DataType = DATA_TYPE.DT_INVALID; + m_pDBEssence = (TASKDICE_ESSENCE)pDB.get_data_ptr((uint)tid, ID_SPACE.ID_SPACE_ESSENCE, ref DataType); + m_iPileLimit = m_pDBEssence.pile_num_max; + m_iPrice = 0; + m_iShopPrice = 0; + m_iProcType = (int)m_pDBEssence.proc_type; + m_bUseable = true; + m_bNeedUpdate = false; + } public EC_IvtrTaskDice(EC_IvtrTaskDice other) : base(other) { + m_pDBEssence = other.m_pDBEssence; + } + public override bool SetItemInfo(byte[] pInfoData, int iDataLen) + { + base.SetItemInfo(pInfoData, iDataLen); + return true; + } + public override string GetIconFile() + { + return m_pDBEssence.FileIcon; + } + protected override string GetNormalDesc(bool bRepair) + { + m_strDesc = ""; + // Try to build item description + CECStringTab pDescTab = EC_Game.GetItemDesc(); + int white = (int)DescriptipionMsg.ITEMDESC_COL_WHITE; + int namecol = DecideNameCol(); + + if (m_iCount > 1) + AddDescText(namecol, true, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_NAMENUMBER), GetName(), m_iCount); + else + AddDescText(namecol, true, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_NAME), GetName()); + AddIDDescText(); + AddExpireTimeDesc(); + + AddPriceDesc(white, bRepair); + + // Extend description + AddExtDescText(); + + return m_strDesc; + } + public override string GetDropModel() + { + return m_pDBEssence.FileMatter; } } } diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrTaskItem.cs b/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrTaskItem.cs new file mode 100644 index 0000000000..876649a2ca --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrTaskItem.cs @@ -0,0 +1,105 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using System.IO; +using BrewMonster; +using ModelRenderer.Scripts.Common; +using ModelRenderer.Scripts.GameData; +using UnityEngine; +using PerfectWorld.Scripts.Managers; +using BrewMonster.Network; +using BrewMonster.Scripts.Managers; +using BrewMonster.Scripts; +using CSNetwork.GPDataType; +using System.Runtime.InteropServices; +namespace PerfectWorld.Scripts.Managers +{ + public class EC_IvtrTaskItem : EC_IvtrItem + { + protected TASKMATTER_ESSENCE m_pDBEssence; + /// + /// Not create logic yet (add summary later) + /// + /// Template id + /// Expire date + public EC_IvtrTaskItem(int tid, int expire_date) : base(tid, expire_date) + { + m_iCID = (int)InventoryClassId.ICID_TASKITEM; + + // Get database data + elementdataman pDB = ElementDataManProvider.GetElementDataMan(); + DATA_TYPE DataType = DATA_TYPE.DT_INVALID; + m_pDBEssence = (TASKMATTER_ESSENCE)pDB.get_data_ptr((uint)tid, ID_SPACE.ID_SPACE_ESSENCE, ref DataType); + + m_iPileLimit = m_pDBEssence.pile_num_max; + m_iPrice = 0; + m_iShopPrice = 0; + m_iProcType = (int)m_pDBEssence.proc_type; + m_i64EquipMask = 0; + + m_bNeedUpdate = false; + } + + public EC_IvtrTaskItem(EC_IvtrTaskItem other) : base(other) + { + m_pDBEssence = other.m_pDBEssence; + } + + public override bool SetItemInfo(byte[] pInfoData, int iDataLen) + { + base.SetItemInfo(pInfoData, iDataLen); + return true; + } + + // Get item icon file name + public override string GetIconFile() + { + return m_pDBEssence.FileIcon; + } + + // Get item name + public override string GetName() + { + // Try Unicode first (for Vietnamese/wide char names), then fallback to CP936 + if (m_pDBEssence.name != null && m_pDBEssence.name.Length > 0) + { + string s = ByteToStringUtils.UshortArrayToUnicodeString(m_pDBEssence.name); + if (!string.IsNullOrEmpty(s) && !string.IsNullOrWhiteSpace(s)) + return s; + // Fallback to legacy CP936 if Unicode was empty + s = ByteToStringUtils.UshortArrayToCP936String(m_pDBEssence.name); + if (!string.IsNullOrEmpty(s)) + return s; + } + return base.GetName(); // Fallback to base class method + } + // Get item description text + protected override string GetNormalDesc(bool bRepair) + { + m_strDesc = string.Empty; + + // Try to build item description + CECStringTab pDescTab = EC_Game.GetItemDesc(); + int white = (int)DescriptipionMsg.ITEMDESC_COL_WHITE; + int namecol = DecideNameCol(); + + if (m_iCount > 1) + AddDescText(namecol, true, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_NAMENUMBER), GetName(), m_iCount); + else + AddDescText(namecol, true, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_NAME), GetName()); + + AddIDDescText(); + + AddExpireTimeDesc(); + + // Task item + AddDescText(white, false, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_TASKITEM)); + + // Extend description + AddExtDescText(); + + return m_strDesc; + } + } +} + diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrTaskItem.cs.meta b/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrTaskItem.cs.meta new file mode 100644 index 0000000000..a20bdd2538 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrTaskItem.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: ec738837a1a3f40e38926d3365da3df5 \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrTaskNmMatter.cs b/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrTaskNmMatter.cs index b76fe9960a..9212fb9644 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrTaskNmMatter.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrTaskNmMatter.cs @@ -1,20 +1,93 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using System.IO; +using BrewMonster; +using ModelRenderer.Scripts.Common; +using ModelRenderer.Scripts.GameData; +using UnityEngine; +using PerfectWorld.Scripts.Managers; +using BrewMonster.Network; using BrewMonster.Scripts.Managers; +using BrewMonster.Scripts; +using CSNetwork.GPDataType; +using System.Runtime.InteropServices; namespace PerfectWorld.Scripts.Managers { + /// + /// Task Normal Matter Item.(non interactable quest item). it is a part of IvtrTaskItem(C++) + /// public class EC_IvtrTaskNmMatter : EC_IvtrItem { + protected TASKNORMALMATTER_ESSENCE m_pDBEssence; /// - /// Not create logic yet (add summary later) + /// Constructor for Task Normal Matter Item. /// /// Template id /// Expire date public EC_IvtrTaskNmMatter(int tid, int expire_date) : base(tid, expire_date) { + m_iCID = (int)InventoryClassId.ICID_TASKNMMATTER; + + // Get database data + elementdataman pDB = ElementDataManProvider.GetElementDataMan(); + DATA_TYPE DataType = DATA_TYPE.DT_INVALID; + m_pDBEssence = (TASKNORMALMATTER_ESSENCE)pDB.get_data_ptr((uint)tid, ID_SPACE.ID_SPACE_ESSENCE, ref DataType); + + m_iPileLimit = m_pDBEssence.pile_num_max; + m_iPrice = m_pDBEssence.price; + m_iShopPrice = m_pDBEssence.shop_price; + m_iProcType = (int)m_pDBEssence.proc_type; + m_bNeedUpdate = false; } public EC_IvtrTaskNmMatter(EC_IvtrTaskNmMatter other) : base(other) { + m_pDBEssence = other.m_pDBEssence; } + public override bool SetItemInfo(byte[] pInfoData, int iDataLen) + { + base.SetItemInfo(pInfoData, iDataLen); + return true; + } + + // Get item icon file name + public override string GetIconFile() + { + return m_pDBEssence.FileIcon; + } + + // Get item description text + protected override string GetNormalDesc(bool bRepair) + { + m_strDesc = string.Empty; + + // Try to build item description + CECStringTab pDescTab = EC_Game.GetItemDesc(); + int white = (int)DescriptipionMsg.ITEMDESC_COL_WHITE; + int namecol = DecideNameCol(); + + if (m_iCount > 1) + AddDescText(namecol, true, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_NAMENUMBER), GetName(), m_iCount); + else + AddDescText(namecol, true, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_NAME), GetName()); + + AddIDDescText(); + + AddExpireTimeDesc(); + + // Price + AddPriceDesc(white, bRepair); + + // Extend description + AddExtDescText(); + + return m_strDesc; + } + public override string GetDropModel() + { + return m_pDBEssence.FileMatter; + } } } diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrTaskmatter.cs b/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrTaskmatter.cs deleted file mode 100644 index 902b9688bd..0000000000 --- a/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrTaskmatter.cs +++ /dev/null @@ -1,20 +0,0 @@ -using BrewMonster.Scripts.Managers; -namespace PerfectWorld.Scripts.Managers -{ - public class EC_IvtrTaskmatter : EC_IvtrItem - { - /// - /// Not create logic yet (add summary later) - /// - /// Template id - /// Expire date - public EC_IvtrTaskmatter(int tid, int expire_date) : base(tid, expire_date) - { - } - - public EC_IvtrTaskmatter(EC_IvtrTaskmatter other) : base(other) - { - } - } -} - diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrTaskmatter.cs.meta b/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrTaskmatter.cs.meta deleted file mode 100644 index a1f695d266..0000000000 --- a/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrTaskmatter.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: ee5181c9a0786409fb452d21d947eab7 \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrTownscroll.cs b/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrTownscroll.cs index 2c7934f0cf..ae7e84bf56 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrTownscroll.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrTownscroll.cs @@ -1,20 +1,95 @@ +using BrewMonster; +using ModelRenderer.Scripts.GameData; +using BrewMonster.Network; using BrewMonster.Scripts.Managers; +using BrewMonster.Scripts; +using CSNetwork.GPDataType; namespace PerfectWorld.Scripts.Managers { - public class EC_IvtrTownscroll : EC_IvtrItem + /// + /// Town scroll item class (hoi thanh phu). It is a part of EC_IvtrScroll(c++) + /// TownScroll allow player to teleport to towns inside one map. + /// + public class EC_IvtrTownScroll : EC_IvtrItem { + protected TOWNSCROLL_ESSENCE m_pDBEssence; /// - /// Not create logic yet (add summary later) + /// Constructor for Town Scroll /// /// Template id /// Expire date - public EC_IvtrTownscroll(int tid, int expire_date) : base(tid, expire_date) + public EC_IvtrTownScroll(int tid, int expire_date) : base(tid, expire_date) { + m_iCID = (int)InventoryClassId.ICID_TOWNSCROLL; + + // Get database data + elementdataman pDB = ElementDataManProvider.GetElementDataMan(); + DATA_TYPE DataType = DATA_TYPE.DT_INVALID; + m_pDBEssence = (TOWNSCROLL_ESSENCE)pDB.get_data_ptr((uint)tid, ID_SPACE.ID_SPACE_ESSENCE, ref DataType); + + m_iPileLimit = m_pDBEssence.pile_num_max; + m_iPrice = m_pDBEssence.price; + m_iShopPrice = m_pDBEssence.shop_price; + m_iProcType = (int)m_pDBEssence.proc_type; + m_i64EquipMask = 0; + m_bUseable = true; + m_dwUseFlags = (uint)UseCondition.USE_PERSIST; + + m_bNeedUpdate = false; } - public EC_IvtrTownscroll(EC_IvtrTownscroll other) : base(other) + public EC_IvtrTownScroll(EC_IvtrTownScroll other) : base(other) { + m_pDBEssence = other.m_pDBEssence; } + public override bool SetItemInfo(byte[] pInfoData, int iDataLen) + { + base.SetItemInfo(pInfoData, iDataLen); + return true; + } + public override string GetIconFile() + { + return m_pDBEssence.FileIcon; + } + // Get item cool time + public int GetCoolTime(ref int piMax) + { + CECHostPlayer pHost = EC_Game.GetGameRun().GetHostPlayer(); + return pHost ? pHost.GetCoolTime((int)CoolTimeIndex.GP_CT_TOWNSCROLL, ref piMax) : 0; + } + + protected override string GetNormalDesc(bool bRepair) + { + m_strDesc = string.Empty; + + // Try to build item description + CECStringTab pDescTab = EC_Game.GetItemDesc(); + int white = (int)DescriptipionMsg.ITEMDESC_COL_WHITE; + int namecol = DecideNameCol(); + + if (m_iCount > 1) + AddDescText(namecol, true, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_NAMENUMBER), GetName(), m_iCount); + else + AddDescText(namecol, true, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_NAME), GetName()); + + AddIDDescText(); + + AddExpireTimeDesc(); + + // Price + AddPriceDesc(white, bRepair); + + // Extend description + AddExtDescText(); + + return m_strDesc; + } + // Get drop model for shown + public override string GetDropModel() + { + return m_pDBEssence.FileMatter; + } + } } diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrTransmitScroll.cs b/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrTransmitScroll.cs index fd8e25ba6b..25fb933b02 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrTransmitScroll.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrTransmitScroll.cs @@ -1,19 +1,104 @@ +using BrewMonster; +using ModelRenderer.Scripts.GameData; +using BrewMonster.Network; using BrewMonster.Scripts.Managers; +using BrewMonster.Scripts; +using CSNetwork.GPDataType; namespace PerfectWorld.Scripts.Managers { + /// + /// Transmit scroll item(Da dich chuyen). It is a part of EC_IvtrConsume(c++) + /// TransmitScroll allow player to teleport to other maps' towns. + /// public class EC_IvtrTransmitScroll : EC_IvtrItem { + protected TRANSMITSCROLL_ESSENCE m_pDBEssence; /// - /// Not create logic yet (add summary later) + /// Constructor for Transmit Scroll /// /// Template id /// Expire date public EC_IvtrTransmitScroll(int tid, int expire_date) : base(tid, expire_date) { + m_iCID = (int)InventoryClassId.ICID_TRANSMITSCROLL; + + // Get database data + elementdataman pDB = ElementDataManProvider.GetElementDataMan(); + DATA_TYPE DataType = DATA_TYPE.DT_INVALID; + m_pDBEssence = (TRANSMITSCROLL_ESSENCE)pDB.get_data_ptr((uint)tid, ID_SPACE.ID_SPACE_ESSENCE, ref DataType); + + m_iPileLimit = m_pDBEssence.pile_num_max; + m_iPrice = m_pDBEssence.price; + m_iShopPrice = m_pDBEssence.shop_price; + m_iProcType = (int)m_pDBEssence.proc_type; + m_i64EquipMask = 0; + m_bUseable = true; + m_dwUseFlags = (uint)UseCondition.USE_PERSIST; + + m_bNeedUpdate = false; } public EC_IvtrTransmitScroll(EC_IvtrTransmitScroll other) : base(other) { + m_pDBEssence = other.m_pDBEssence; + } + public override bool SetItemInfo(byte[] pInfoData, int iDataLen) + { + base.SetItemInfo(pInfoData, iDataLen); + return true; + } + public override string GetIconFile() + { + return m_pDBEssence.FileIcon; + } + public int GetCoolTime(ref int piMax) + { + CECHostPlayer pHost = EC_Game.GetGameRun().GetHostPlayer(); + if (!pHost) + return 0; + int iTime = pHost.GetCoolTime((int)CoolTimeIndex.GP_CT_TOWNSCROLL, ref piMax); + return iTime; + } + + protected override string GetNormalDesc(bool bRepair) + { + m_strDesc = string.Empty; + + // Try to build item description + CECStringTab pDescTab = EC_Game.GetItemDesc(); + int white = (int)DescriptipionMsg.ITEMDESC_COL_WHITE; + int namecol = DecideNameCol(); + + if (m_iCount > 1) + AddDescText(namecol, true, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_NAMENUMBER), GetName(), m_iCount); + else + AddDescText(namecol, true, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_NAME), GetName()); + + AddIDDescText(); + + AddExpireTimeDesc(); + + // Price + AddPriceDesc(white, bRepair); + + // Extend description + AddExtDescText(); + + return m_strDesc; + } + // Get drop model for shown + public override string GetDropModel() + { + return m_pDBEssence.FileMatter; + } + + // Check item use condition + public override bool CheckUseCondition() + { + if( EC_Game.GetGameRun().GetHostPlayer().IsFighting() ) + return false; + + return true; } } } diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrType.cs b/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrType.cs index 67085b3509..07e9ab0e01 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrType.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrType.cs @@ -69,7 +69,6 @@ namespace BrewMonster.Scripts.Managers public float attack_short_range; public IVTR_ESSENCE_WEAPON( byte[] data) { - Debug.Log("IVTR_ESSENCE_WEAPON: data.Length: " + data.Length); CECDataReader dr = new (data, data.Length); weapon_type = dr.ReadShort(); weapon_dealy = dr.ReadShort(); @@ -87,12 +86,20 @@ namespace BrewMonster.Scripts.Managers }; public struct IVTR_ESSENCE_ARROW { - // TODO : implement data later - // DWORD dwBowMask; - // int iDamage; - // int iDamageScale; - // int iWeaponReqLow; - // int iWeaponReqHigh; + public int dwBowMask; + public int iDamage; + public int iDamageScale; + public int iWeaponReqLow; + public int iWeaponReqHigh; + public IVTR_ESSENCE_ARROW(byte[] data) + { + CECDataReader dr = new (data, data.Length); + dwBowMask = dr.ReadInt(); + iDamage = dr.ReadInt(); + iDamageScale = dr.ReadInt(); + iWeaponReqLow = dr.ReadInt(); + iWeaponReqHigh = dr.ReadInt(); + } }; public struct IVTR_ESSENCE_DECORATION { @@ -103,7 +110,6 @@ namespace BrewMonster.Scripts.Managers public int[] resistance; public IVTR_ESSENCE_DECORATION(byte[] data) { - Debug.Log("IVTR_ESSENCE_DECORATION: data.Length: " + data.Length); CECDataReader dr = new (data, data.Length); damage = dr.ReadInt(); magic_damage = dr.ReadInt(); @@ -141,23 +147,41 @@ namespace BrewMonster.Scripts.Managers }; public struct IVTR_ESSENCE_FASHION { - // TODO : implement data later - // int require_level; - // unsigned short color; - // unsigned short gender; + public int require_level; + public ushort color; + public ushort gender; + public IVTR_ESSENCE_FASHION(byte[] data) + { + CECDataReader dr = new (data, data.Length); + require_level = dr.ReadInt(); + color = dr.ReadUShort(); + gender = dr.ReadUShort(); + } }; public struct IVTR_ESSENCE_FLYSWORD { - // TODO : implement data later - // int cur_time; - // int max_time; - // short require_level; - // char level; - // char improve_level; - // int profession; - // size_t time_per_element; - // float speed_increase; - // float speed_increase2; + public int cur_time; + public int max_time; + public short require_level; + public char level; + public char improve_level; + public int profession; + public int time_per_element; + public float speed_increase; + public float speed_increase2; + public IVTR_ESSENCE_FLYSWORD(byte[] data) + { + CECDataReader dr = new (data, data.Length); + cur_time = dr.ReadInt(); + max_time = dr.ReadInt(); + require_level = dr.ReadShort(); + level = (char)dr.ReadByte(); + improve_level = (char)dr.ReadByte(); + profession = dr.ReadInt(); + time_per_element = dr.ReadInt(); + speed_increase = dr.ReadFloat(); + speed_increase2 = dr.ReadFloat(); + } }; public struct IVTR_ESSENCE_WING { diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrWeapon.cs b/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrWeapon.cs index 270faff894..7236b8ed82 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrWeapon.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrWeapon.cs @@ -211,7 +211,6 @@ namespace PerfectWorld.Scripts.Managers // Get item name public override string GetName() { - BMLogger.Log("[THN]EC_IvtrWeapon: GetName: m_pDBEssence.Name: " + m_pDBEssence.Name); return m_pDBEssence.Name; } // Get preview info diff --git a/Assets/PerfectWorld/Scripts/Move/CECPlayer.cs b/Assets/PerfectWorld/Scripts/Move/CECPlayer.cs index 04b76b0d7e..7fa718f687 100644 --- a/Assets/PerfectWorld/Scripts/Move/CECPlayer.cs +++ b/Assets/PerfectWorld/Scripts/Move/CECPlayer.cs @@ -81,6 +81,7 @@ namespace BrewMonster protected int m_iBoothState = 0; // Booth state. 0, none; 1, prepare; 2, open booth; 3, visite other's booth public int m_idFRole = GNETRoles._R_UNMEMBER; // ID of player's faction role + protected int m_idCountry = 0; // ¹úÕ½ÕóÓª id public static int MAX_REINCARNATION = 2; protected List m_aCurEffects = new List(); // Current effects @@ -1891,4 +1892,56 @@ namespace BrewMonster public static byte SKIN_FASHION_FOOT_INDEX = 9; public static byte NUM_SKIN_INDEX = 10; } + public enum enumSkinShow + { + enumSkinShowNone = 0, + enumSkinShowUpperBody, + enumSkinShowWrist, + enumSkinShowLowerBody, + enumSkinShowFoot, + enumSkinShowUpperAndLower, + enumSkinShowUpperAndWrist, + enumSkinShowLowerAndFoot, + enumSkinShowUpperLowerAndWrist, + enumSkinShowArmet, + enumSkinShowHand, + }; + /// + /// Place holder for riding pet. Not test logic yet. + /// + public struct RIDINGPET + { + public int id; + public ushort color; + + public RIDINGPET(bool isReset = true) + { + id = 0; + color = 0; + } + + public bool GetColor(Color clr) + { + // ��ȡ��ǰ����Ⱦɫ��ɫ + return id>0 && GetColor(color, clr); + } + + public static bool GetColor(ushort c, Color clr) + { + // ��ѯ��ǰ����Ƿ�Ⱦ��ɫ�����Ⱦ��ɫ�����ر�Ⱦ֮�����ɫ + bool bRet = false; + if ((c & (1<<(8-1))) != 0) + { + // unsigned short ��λΪ1ʱ����ʾȾ��ɫ����ʱ�ɻ�ȡ��ɫ + clr = new Color(((c) & (0x1f << 10)) >> 7, ((c) & (0x1f << 5)) >> 2, ((c) & 0x1f) << 3); + bRet = true; + } + return bRet; + } + + public static Color GetDefaultColor() + { + return new Color(255, 255, 255); + } + }; } \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/NPC/CECNPC.cs b/Assets/PerfectWorld/Scripts/NPC/CECNPC.cs index 8802f06b2e..4c5e2eb46a 100644 --- a/Assets/PerfectWorld/Scripts/NPC/CECNPC.cs +++ b/Assets/PerfectWorld/Scripts/NPC/CECNPC.cs @@ -68,53 +68,6 @@ public class CECNPC : CECObject m_pNPCModelPolicy = new CECNPCModelDefaultPolicy(this); } - // Add this field to CECNPC class - private bool m_bHasRelatedTask = false; - - private float _timerCheckTask = 0; - public void UpdateTaskIcon() - { - // Check if npcUI is assigned - if (m_npcUI == null) - { - m_npcUI = GetComponentInChildren(); - if (m_npcUI == null) return; - } - - // 2. Get Host Player & Interface - var host = CECGameRun.Instance.GetHostPlayer(); - if (host == null) return; - - var taskInterface = host.GetTaskInterface(); - if (taskInterface == null) - { - if (m_bHasRelatedTask) // only update if state changed - { - m_npcUI.SetTaskIconMain(false); - m_bHasRelatedTask = false; - } - return; - } - - // Get NPC Template ID - int npcTemplateID = m_NPCInfo.tid; - - // Check if there are tasks related to this NPC - bool hasTask = taskInterface.HasTaskRelatedToNPC(npcTemplateID); - - // Update icon only if state changed - if (m_bHasRelatedTask != hasTask) - { - m_bHasRelatedTask = hasTask; - m_npcUI.SetTaskIconMain(hasTask); - - if (hasTask) - { - Debug.Log($"[Icon] NPC {m_strName} (TID: {npcTemplateID})"); - } - } - } - public string GetName() { @@ -226,8 +179,6 @@ public class CECNPC : CECObject new Vector2(m_vServerPos.x, m_vServerPos.z), new Vector2(pHost.transform.position.x, pHost.transform.position.z)); } - - UpdateTaskIcon(); return true; } @@ -561,13 +512,6 @@ public class CECNPC : CECObject { StartAdjustTransparency(-1.0f, GetTransparentLimit(), 500); } - - _timerCheckTask += Time.deltaTime; - if (_timerCheckTask > 1.0f) - { - _timerCheckTask = 0; - UpdateTaskIcon(); - } } private void TickWork_Dead(float deltaTime) diff --git a/Assets/PerfectWorld/Scripts/NPC/CECNPCServer.cs b/Assets/PerfectWorld/Scripts/NPC/CECNPCServer.cs index 83d88af57c..396a07045f 100644 --- a/Assets/PerfectWorld/Scripts/NPC/CECNPCServer.cs +++ b/Assets/PerfectWorld/Scripts/NPC/CECNPCServer.cs @@ -1,4 +1,7 @@ using BrewMonster; +using BrewMonster.Network; +using BrewMonster.Scripts; +using BrewMonster.Scripts.Task; using CSNetwork.GPDataType; using System; using System.Runtime.InteropServices; @@ -10,12 +13,17 @@ public class CECNPCServer : CECNPC { NPC_ESSENCE? m_pDBEssence; MONSTER_ESSENCE? m_pMonEssence; - float m_fTaxRate = 0.05f; // Tax rate + float m_fTaxRate = 0.05f; // Tax rate + + private IconTaskType m_TaskIcon = IconTaskType.QI_NONE; + private CECCounter m_TaskCounter = new CECCounter(); + public override void SetUpCECNPC(CECNPCMan pNPCMan) { base.SetUpCECNPC(pNPCMan); m_iCID = (int)Class_ID.OCID_SERVER; m_pDBEssence = null; + m_TaskCounter.SetPeriod(1000); } public override bool Init(int tid, in info_npc info, ReadOnlySpan packet, int infoOffset) { @@ -57,11 +65,20 @@ public class CECNPCServer : CECNPC transform.position = EC_Utility.ToVector3(info.pos); StartWork((int)WorkType.WT_NOTHING, (int)WorkID.WORK_STAND); - - UpdateTaskIcon(); return true; } + protected override void Update() + { + base.Update(); + + if (m_TaskCounter.IncCounter(Time.deltaTime * 1000)) + { + m_TaskCounter.Reset(); + UpdateCurTaskIcon(); + } + } + // Get way point ID bound with this NPC public uint? GetWayPointID() { @@ -83,4 +100,222 @@ public class CECNPCServer : CECNPC { return 1.0f + m_pDBEssence.Value.tax_rate; } + + private void UpdateCurTaskIcon() + { + var pHost = CECGameRun.Instance.GetHostPlayer(); + if (pHost == null || pHost.GetTaskInterface() == null) + { + return; + } + + if (m_pDBEssence == null) + { + return; + } + + var pTaskMan = EC_Game.GetTaskTemplateMan(); + var pDataMan = ElementDataManProvider.GetElementDataMan(); + var pTask = pHost.GetTaskInterface(); + + const uint TASK_HAVE_COMPLETE = 0x10000000; + const uint TASK_COMPLETE = 0x01; + const uint TASK_INCOMPLETE = 0x02; + const uint TASK_CANGET = 0x04; + const uint TASK_CANNOTGET = 0x08; + const uint TASK_COMPLETE_TYPE1 = 0x10; + const uint TASK_CANGET_TYPE1 = 0x20; + const uint TASK_COMPLETE_TYPE2 = 0x40; + const uint TASK_CANGET_TYPE2 = 0x80; + const uint TASK_COMPLETE_TYPE3 = 0x100; + const uint TASK_CANGET_TYPE3 = 0x200; + const uint TASK_COMPLETE_TYPE4 = 0x400; + const uint TASK_CANGET_TYPE4 = 0x800; + + m_TaskIcon = IconTaskType.QI_NONE; + uint taskFlag = 0; + + BMLogger.Log($"[UpdateCurTaskIcon] NPC {m_NPCInfo.nid}, id_task_in_service={m_pDBEssence.Value.id_task_in_service}, id_task_out_service={m_pDBEssence.Value.id_task_out_service}"); + if (m_pDBEssence.Value.id_task_in_service != 0) + { + DATA_TYPE dt = DATA_TYPE.DT_INVALID; + var serviceData = pDataMan.get_data_ptr(m_pDBEssence.Value.id_task_in_service, ID_SPACE.ID_SPACE_ESSENCE, ref dt); + + if (serviceData != null && dt == DATA_TYPE.DT_NPC_TASK_IN_SERVICE) + { + var inService = (NPC_TASK_IN_SERVICE)serviceData; + + for (int i = 0; i < inService.id_tasks.Length; i++) + { + uint idTask = inService.id_tasks[i]; + if (idTask <= 0 || !pTask.HasTask(idTask)) + continue; + + BMLogger.Log($"[UpdateCurTaskIcon] Check IN task {idTask}, HasTask={pTask.HasTask(idTask)}, CanFinish={pTask.CanFinishTask((idTask))}"); + + var pTaskTemp = pTaskMan.GetTaskTemplByID(idTask); + if (pTaskTemp == null) + continue; + + if (pTask.CanFinishTask(idTask)) + { + taskFlag |= TASK_HAVE_COMPLETE; + + if (pTaskTemp.IsKeyTask()) + { + m_TaskIcon = IconTaskType.QI_IN_K; + BMLogger.Log($"[UpdateCurTaskIcon] Set icon QI_IN_K for task {idTask}"); + UpdateTaskIconUI(); + return; + } + else if (pTaskTemp.GetType() == (uint)ENUM_TASK_TYPE.enumTTEvent || pTaskTemp.GetType() == (uint)ENUM_TASK_TYPE.enumTTDaily) + { + taskFlag |= TASK_COMPLETE_TYPE3; + } + else if (pTaskTemp.GetType() == (uint)ENUM_TASK_TYPE.enumTTQiShaList) + { + taskFlag |= TASK_COMPLETE_TYPE2; + } + else if (pTaskTemp.GetType() == (uint)ENUM_TASK_TYPE.enumTTFaction || pTaskTemp.GetType() == (uint)ENUM_TASK_TYPE.enumTTFunction) + { + taskFlag |= TASK_COMPLETE_TYPE1; + } + else if (pTaskTemp.GetType() == (uint)ENUM_TASK_TYPE.enumTTMajor) + { + taskFlag |= TASK_COMPLETE_TYPE4; + } + else + { + taskFlag |= TASK_COMPLETE; + } + } + else + { + taskFlag |= TASK_INCOMPLETE; + } + } + } + } + + if ((taskFlag & TASK_HAVE_COMPLETE) != 0) + { + if ((taskFlag & TASK_COMPLETE_TYPE4) != 0) + m_TaskIcon = IconTaskType.QI_IN_TYPE4; + else if ((taskFlag & TASK_COMPLETE_TYPE3) != 0) + m_TaskIcon = IconTaskType.QI_IN_TYPE3; + else if ((taskFlag & TASK_COMPLETE_TYPE2) != 0) + m_TaskIcon = IconTaskType.QI_IN_TYPE2; + else if ((taskFlag & TASK_COMPLETE) != 0) + m_TaskIcon = IconTaskType.QI_IN; + else if ((taskFlag & TASK_COMPLETE_TYPE1) != 0) + m_TaskIcon = IconTaskType.QI_IN_TYPE1; + + BMLogger.Log($"[UpdateCurTaskIcon] Set complete icon {m_TaskIcon}"); + UpdateTaskIconUI(); + return; + } + + if (m_pDBEssence.Value.id_task_out_service != 0) + { + DATA_TYPE dt = DATA_TYPE.DT_INVALID; + var serviceData = pDataMan.get_data_ptr( + m_pDBEssence.Value.id_task_out_service, + ID_SPACE.ID_SPACE_ESSENCE, + ref dt + ); + + if (serviceData != null && dt == DATA_TYPE.DT_NPC_TASK_OUT_SERVICE) + { + var outService = (NPC_TASK_OUT_SERVICE)serviceData; + + if (outService.storage_id != 0 && outService.storage_open_item != 0) + { + var pack = pHost.GetInventory(InventoryConst.IVTRTYPE_PACK); + if (pack != null && pack.GetItemTotalNum((int)outService.storage_open_item) > 0) + { + taskFlag |= TASK_CANGET_TYPE2; + } + } + + // Check normal tasks + for (int i = 0; i < outService.id_tasks.Length; i++) + { + uint idTask = outService.id_tasks[i]; + if (idTask <= 0) + continue; + + BMLogger.Log($"[UpdateCurTaskIcon] Check OUT task {idTask}, CanShow={pTask.CanShowTask(idTask)}, CanDeliver={pTask.CanDeliverTask(idTask)}"); + + if (!pTask.CanShowTask(idTask)) + continue; + + var pTaskTemp = pTaskMan.GetTaskTemplByID(idTask); + if (pTaskTemp == null) + continue; + + if (pTask.CanDeliverTask(idTask) == 0) + { + if (pTaskTemp.IsKeyTask()) + { + m_TaskIcon = IconTaskType.QI_OUT_K; + BMLogger.Log($"[UpdateCurTaskIcon] Set icon QI_OUT_K for task {idTask}"); + UpdateTaskIconUI(); + return; + } + else if (pTaskTemp.GetType() == (uint)ENUM_TASK_TYPE.enumTTEvent || pTaskTemp.GetType() == (uint)ENUM_TASK_TYPE.enumTTDaily) + { + taskFlag |= TASK_CANGET_TYPE3; + } + else if (pTaskTemp.GetType() == (uint)ENUM_TASK_TYPE.enumTTQiShaList) + { + taskFlag |= TASK_CANGET_TYPE2; + } + else if (pTaskTemp.GetType() == (uint)ENUM_TASK_TYPE.enumTTFaction || pTaskTemp.GetType() == (uint)ENUM_TASK_TYPE.enumTTFunction) + { + taskFlag |= TASK_CANGET_TYPE1; + } + else if (pTaskTemp.GetType() == (uint)ENUM_TASK_TYPE.enumTTMajor) + { + taskFlag |= TASK_CANGET_TYPE4; + } + else + { + taskFlag |= TASK_CANGET; + } + } + else + { + taskFlag |= TASK_CANNOTGET; + } + } + } + } + + // Set icon by available task priority + if ((taskFlag & TASK_CANGET_TYPE4) != 0) + m_TaskIcon = IconTaskType.QI_OUT_TYPE4; + else if ((taskFlag & TASK_CANGET_TYPE3) != 0) + m_TaskIcon = IconTaskType.QI_OUT_TYPE3; + else if ((taskFlag & TASK_CANGET_TYPE2) != 0) + m_TaskIcon = IconTaskType.QI_OUT_TYPE2; + else if ((taskFlag & TASK_CANGET) != 0) + m_TaskIcon = IconTaskType.QI_OUT; + else if ((taskFlag & TASK_CANGET_TYPE1) != 0) + m_TaskIcon = IconTaskType.QI_OUT_TYPE1; + else if ((taskFlag & TASK_INCOMPLETE) != 0) + m_TaskIcon = IconTaskType.QI_IN_N; + else if ((taskFlag & TASK_CANNOTGET) != 0) + m_TaskIcon = IconTaskType.QI_OUT_N; + + BMLogger.Log($"[UpdateCurTaskIcon] Final icon {m_TaskIcon}, taskFlag={taskFlag}"); + UpdateTaskIconUI(); + } + + private void UpdateTaskIconUI() + { + if(m_npcUI != null) + { + m_npcUI.SetTaskIcon(m_TaskIcon); + } + } } diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/GameSession.cs b/Assets/PerfectWorld/Scripts/Network/CSNetwork/GameSession.cs index 56ec20638a..bde265edbb 100644 --- a/Assets/PerfectWorld/Scripts/Network/CSNetwork/GameSession.cs +++ b/Assets/PerfectWorld/Scripts/Network/CSNetwork/GameSession.cs @@ -1,1536 +1,1768 @@ -using BrewMonster; -using BrewMonster.Common; -using BrewMonster.Managers; -using BrewMonster.Network; -using BrewMonster.Scripts.Skills; -using BrewMonster.UI; -using CSNetwork.C2SCommand; -using CSNetwork.GPDataType; -using CSNetwork.Protocols; -using CSNetwork.Protocols.RPCData; -using System; -using System.Collections.Generic; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using UnityEngine; -using CommandID = CSNetwork.GPDataType.CommandID; - -namespace CSNetwork -{ - public class GameSession : IDisposable - { - private static IPrefixedLogger - _logger = LoggerFactory.GetLogger(nameof(GameSession)); // Get class-specific logger - - private NetworkManager _networkManager; - private string _host; - private int _port; - private string _username; - private string _password; - private int _currentUserId = -1; // To store the UserID after successful login - private int m_iCharID; - private int m_idLastSelTarget = 0; // ID of selected item last time - - CECStringTab m_ErrorMsgs; - - // State management for async operations and callbacks - private Action _loginCallback; - private Action> _roleListCallback; - private List _accumulatedRoles; - private Action _selectRoleCallback; - private RoleInfo _selectedRole; - public bool IsConnected => _networkManager?.IsConnected ?? false; - public static SynchronizationContext Context; - private CECC2SCmdCache m_CmdCache; // C2S command cache -#if UNITY_EDITOR - public bool isDebug; - public bool IsDebug - { - get => isDebug; - set => isDebug = value; - } -#endif - public CECC2SCmdCache CmdCache { get => m_CmdCache; } - - - public GameSession() - { - _networkManager = new NetworkManager(); - m_CmdCache = new CECC2SCmdCache(); - _networkManager.ProtocolReceived += OnProtocolReceived; - _networkManager.ErrorOccurred += OnErrorOccurred; - _networkManager.Disconnected += OnDisconnected; - } - - public void SetLogPath(string path) - { - LoggerFactory.SetFileLoggerImplementation(new FileLogger()); - _logger = LoggerFactory.GetCustomLogger(path, nameof(GameSession) + GetHashCode(), LoggerType.File); - _networkManager.SetLogPath(path); - } - - /// - /// Connects to the game server asynchronously. - /// - /// Server hostname or IP address. - /// Server port. - /// Task representing the asynchronous connect operation. Check IsConnected property or handle Disconnected event for status. - public async Task ConnectAsync(string host, int port) - { - if (IsConnected) - { - _logger.Log(LogType.Warning, "ConnectAsync called but already connected."); - return; - } - - _host = host; - _port = port; - _logger.Log(LogType.Info, $"Attempting to connect to {_host}:{_port}..."); - try - { - await _networkManager.ConnectAsync(_host, _port); - if (IsConnected) - { - _logger.Log(LogType.Info, "Connection established."); - } - else - { - _logger.Log(LogType.Warning, - "Connection failed after ConnectAsync completed (check NetworkManager logs/events)."); - } - } - catch (Exception ex) - { - _logger.Log(LogType.Error, $"Connection exception: {ex.Message}"); - _logger.LogException(ex); - OnDisconnected(); - } - } - - - public void Disconnect() - { - _networkManager.Disconnect(); - } - - /// - /// Initiates the login process asynchronously. - /// - /// Account username. - /// Account password. - /// Action invoked with true on successful login (OnlineAnnounce received), false otherwise. - public void LoginAsync(string username, string password, Action callback) - { - if (!IsConnected) - { - _logger.Log(LogType.Warning, "LoginAsync called but not connected."); - callback?.Invoke(false); - return; - } - - if (_loginCallback != null) - { - _logger.Log(LogType.Warning, "LoginAsync called while another login is already in progress."); - callback?.Invoke(false); - return; - } - - _username = username; - _password = password; - _loginCallback = callback; - _currentUserId = -1; // Reset user ID - - _logger.Log(LogType.Info, $"Initiating login for user '{_username}'..."); - } - - /// - /// Initiates fetching the role list asynchronously. Requires successful login. - /// - /// Action invoked with the complete list of roles, or null/empty list on failure. - public void GetRoleListAsync(Action> callback) - { - if (!IsConnected) - { - _logger.Log(LogType.Warning, "GetRoleListAsync called but not connected."); - callback?.Invoke(null); - return; - } - - if (_currentUserId == -1) - { - _logger.Log(LogType.Warning, "GetRoleListAsync called but not logged in."); - callback?.Invoke(null); - return; - } - - if (_roleListCallback != null) - { - _logger.Log(LogType.Warning, - "GetRoleListAsync called while another role list retrieval is already in progress."); - callback?.Invoke(null); - return; - } - - _roleListCallback = callback; - _accumulatedRoles = new List(); - _logger.Log(LogType.Info, "Requesting role list..."); - RequestRoleListInternal(); - } - - public RoleInfo GetRoleInfo() - { - return _selectedRole; - } - - public void SelectRoleAsync(RoleInfo role, Action callback) - { - _selectedRole = role; - _selectRoleCallback = callback; - SetCharacterID(role.roleid); - SendProtocol(new selectrole() - { - Roleid = role.roleid, - Flag = 0 - }); - } - - public void EnterWorldAsync(RoleInfo role, Action callback) - { - SendProtocol(new enterworld() - { - Roleid = _selectedRole.roleid, - Provider_link_id = 0, - }, callback); - } - - public void RequestDropIvtrItem(byte index, int amount) - { - gamedatasend gamedatasendRequest = new gamedatasend(); - gamedatasendRequest.Data = C2SCommandFactory.CreateDropIvtrItem(index, amount); - SendProtocol(gamedatasendRequest); - } - - public void RequestDropEquipItem(byte index) - { - gamedatasend gamedatasendRequest = new gamedatasend(); - gamedatasendRequest.Data = C2SCommandFactory.CreateDropEquipItem(index); - SendProtocol(gamedatasendRequest); - } - - public void RequestPickupItem(int idItem, int tid) - { - gamedatasend gamedatasendRequest = new gamedatasend(); - gamedatasendRequest.Data = C2SCommandFactory.CreatePickupItem(idItem, tid); - SendProtocol(gamedatasendRequest); - } - - public void c2s_SendCmdGetIvtrDetailData(byte byPackage, Action callback) - { - gamedatasend gamedatasendRequest = new gamedatasend(); - gamedatasendRequest.Data = CSNetwork.C2SCommand.C2SCommandFactory.c2s_SendCmdGetIvtrDetailData(byPackage); - SendProtocol(gamedatasendRequest, callback); - } - - public void c2s_SendCmdQueryCashInfo() - { - gamedatasend gamedatasendRequest = new gamedatasend(); - gamedatasendRequest.Data = C2SCommandFactory.c2s_SendCmdQueryCashInfo(); - SendProtocol(gamedatasendRequest); - } - - public void c2s_SendCmdOpenFashionTrash(string password) - { - gamedatasend gamedatasendRequest = new gamedatasend(); - gamedatasendRequest.Data = C2SCommandFactory.c2s_SendCmdOpenFashionTrash(password); - SendProtocol(gamedatasendRequest); - } - - public void c2s_SendCmdEquipItem(byte iIvtrIdx, byte iEquipIdx, Action callback) - { - gamedatasend gamedatasendRequest = new gamedatasend(); - gamedatasendRequest.Data = CSNetwork.C2SCommand.C2SCommandFactory.c2s_SendCmdEquipItem(iIvtrIdx, iEquipIdx); - SendProtocol(gamedatasendRequest, callback); - } - - public void c2s_SendCmdReviveVillage(int param = 0) - { - gamedatasend gamedatasendRequest = new gamedatasend(); - gamedatasendRequest.Data = C2SCommandFactory.c2s_SendCmdReviveVillage(param); - SendProtocol(gamedatasendRequest); - } - public void c2s_SendCmdReviveItem(int param = 0) - { - gamedatasend gamedatasendRequest = new gamedatasend(); - gamedatasendRequest.Data = C2SCommandFactory.c2s_SendCmdReviveVillage(param); - SendProtocol(gamedatasendRequest); - } - public void RequestReviveByPlayer(int param = 0) - { - gamedatasend gamedatasendRequest = new gamedatasend(); - gamedatasendRequest.Data = C2SCommandFactory.c2s_SendCmdReviveVillage(param); - SendProtocol(gamedatasendRequest); - } - - - public void c2s_SendCmdMallShopping(uint count, CMD_MallShopping.goods[] goodsArray) - { - gamedatasend gamedatasendRequest = new gamedatasend(); - gamedatasendRequest.Data = CSNetwork.C2SCommand.C2SCommandFactory.CreateGetMallShopping(count, goodsArray); - SendProtocol(gamedatasendRequest); - } - public void c2s_SendCmdGatherMaterial(int idMatter, int iToolPack, int idToolIndex, int idTool, int idTask) - { - gamedatasend gamedatasendRequest = new gamedatasend(); - gamedatasendRequest.Data = CSNetwork.C2SCommand.C2SCommandFactory.c2s_SendCmdGatherMaterial(idMatter, iToolPack, idToolIndex, idTool, idTask); - SendProtocol(gamedatasendRequest); - } - - public void RequestOwnItemInfoAsync( - byte byPackage, - byte bySlot, - int type, - int expire_date, - int state, - uint count, - ushort crc, - ushort content_length, - byte[] content, - Action callback) - { - gamedatasend gamedatasendRequest = new gamedatasend(); - gamedatasendRequest.Data = C2SCommandFactory.CreateOwnItemInfo(byPackage, bySlot, type, expire_date, state, - count, crc, content_length, content); - SendProtocol(gamedatasendRequest, callback); - } - - // --- Protocol Sending --- - public void SendProtocol(Protocol protocol, Action complete = null) - { - if (IsConnected) - { - _logger.Log(LogType.Debug, - $"Sending protocol: {protocol.GetType().Name} (Detail: {protocol.ToString})"); - _networkManager.Send(protocol); - complete?.Invoke(); - } - else - { - _logger.Log(LogType.Warning, $"Cannot send protocol ({protocol.GetType().Name}), not connected."); - } - } - - // --- Event Handlers (from NetworkManager) --- - - private void OnProtocolReceived(Protocol protocol) - { - _logger.Log(LogType.Debug, $"Received protocol: {protocol.GetType().Name} (Type: {protocol.Type})"); - if (protocol is null) - return; - - - // Route protocol to appropriate handler - switch (protocol.GetPType()) - { - case ProtocolType.PROTOCOL_CHALLENGE: - HandleChallenge((challenge)protocol); - break; - case ProtocolType.PROTOCOL_KEYEXCHANGE: - HandleKeyExchange((KeyExchange)protocol); - break; - case ProtocolType.PROTOCOL_ONLINEANNOUNCE: - HandleOnlineAnnounce((onlineannounce)protocol); - break; - case ProtocolType.PROTOCOL_ROLELIST_RE: - HandleRoleListResponse((RoleListResponse)protocol); - break; - // Add cases for other protocols GameSession might need to handle - case ProtocolType.PROTOCOL_SELECTROLE_RE: - HandleSelectRoleResponse((SelectRole_Re)protocol); - //_networkManager.IgnoreBytes = 2; - break; - case ProtocolType.PROTOCOL_S2CGAMEDATASEND: - case ProtocolType.PROTOCOL_GAMEDATASEND: - HandleServerDataSend((gamedatasend)protocol); - break; - case ProtocolType.PROTOCOL_CHATMESSAGE: - _logger.Log(LogType.Warning, $"HoangDev :ProtocolType.PROTOCOL_CHATMESSAGE {protocol.GetPType()}"); - OnPrtcChatMessage(protocol, false); - break; - case ProtocolType.PROTOCOL_PLAYERBASEINFO_RE: - OnPrtcPlayerBaseInfoRe(protocol); - break; - case ProtocolType.PROTOCOL_GETUICONFIG_RE: OnPrtcGetConfigRe(protocol); break; - - case ProtocolType.PROTOCOL_AUTOTEAMSETGOAL_RE: - { - // CECAutoTeam pAutoTeam = CECGameRun.Instance.GetHostPlayer().GetAutoTeam(); - // if( pAutoTeam !=null) - // pAutoTeam.OnPrtcAutoTeamSetGoalRe((AutoTeamSetGoal_Re)protocol); - } - break; - - default: - _logger.Log(LogType.Warning, $"Received unhandled protocol type: {protocol.GetPType()}"); - break; - } - } - - private void HandleServerDataSend(gamedatasend protocol) - { - int lenghtHeader = Marshal.SizeOf(); - var pDataBuf = new byte[protocol.Data.ByteArray.Length - lenghtHeader]; - var byteArrHeader = new byte[lenghtHeader]; - long dwDataSize = protocol.Data.Size; - - if (dwDataSize < Marshal.SizeOf()) - { - _logger.Error($"### GameDataSend: size invalid {dwDataSize}"); - return; - } - - dwDataSize -= Marshal.SizeOf(); // subtract the header size (ushort) - for (int i = 0; i < protocol.Data.ByteArray.Length; i++) - { - if (i < lenghtHeader) - { - byteArrHeader[i] = protocol.Data.ByteArray[i]; - } - else - { - pDataBuf[i - lenghtHeader] = protocol.Data.ByteArray[i]; - } - } - - var pCmdHeader = BitConverter.ToUInt16(byteArrHeader); - //sss -#if UNITY_EDITOR - if (isDebug) - { - BMLogger.LogError($"### GameDataSend: CMDID {pCmdHeader}"); - } -#endif - int iHostID = _selectedRole.roleid; - switch (pCmdHeader) - { - case CommandID.PLAYER_INFO_2: - case CommandID.PLAYER_INFO_3: - case CommandID.PLAYER_INFO_4: - case CommandID.PLAYER_INFO_2_LIST: - case CommandID.PLAYER_INFO_3_LIST: - case CommandID.PLAYER_INFO_23_LIST: - - break; - - case CommandID.PLAYER_INFO_1: - case CommandID.PLAYER_ENTER_WORLD: - case CommandID.PLAYER_ENTER_SLICE: - case CommandID.PLAYER_INFO_1_LIST: - case CommandID.PLAYER_INFO_00: - case CommandID.SELF_INFO_1: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERINFO, (int)MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, - pCmdHeader, iHostID); - break; - case CommandID.OBJECT_MOVE: - int lenghtDataType = Marshal.SizeOf(); - byte[] arrByteData = GetBytes(pDataBuf, lenghtDataType, 0); - int idObjMove = BitConverter.ToInt32(arrByteData); - if (ISPLAYERID(idObjMove)) - { - EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERMOVE, (int)MANAGER_INDEX.MAN_PLAYER, -1, - pDataBuf, pCmdHeader, iHostID); - } - else if (ISNPCID(idObjMove)) - { - EC_ManMessage.PostMessage(EC_MsgDef.MSG_NM_NPCMOVE, (int)MANAGER_INDEX.MAN_NPC, 0, pDataBuf, - pCmdHeader); - } - - break; - case CommandID.OBJECT_STOP_MOVE: - { - int id1 = GPDataTypeHelper.FromBytes(pDataBuf); - - if (ISPLAYERID(id1)) - { - EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERSTOPMOVE, (int)MANAGER_INDEX.MAN_PLAYER, -1, - pDataBuf, pCmdHeader); - } - else if (ISNPCID(id1)) - { - EC_ManMessage.PostMessage(EC_MsgDef.MSG_NM_NPCSTOPMOVE, (int)MANAGER_INDEX.MAN_NPC, 0, pDataBuf, - pCmdHeader); - } - - break; - } - case CommandID.OBJECT_LEAVE_SLICE: - { - int id = GPDataTypeHelper.FromBytes(pDataBuf); - if (ISPLAYERID(id)) - { - EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERRUNOUT, (int)MANAGER_INDEX.MAN_PLAYER, -1, - pDataBuf, pCmdHeader); - } - else if (ISNPCID(id)) - { - EC_ManMessage.PostMessage(EC_MsgDef.MSG_NM_NPCRUNOUT, (int)MANAGER_INDEX.MAN_NPC, 0, pDataBuf, - pCmdHeader); - } - - break; - } - case CommandID.OWN_IVTR_DATA: - case CommandID.OWN_IVTR_DETAIL_DATA: - case CommandID.GET_OWN_MONEY: - case CommandID.CHANGE_IVTR_SIZE: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_IVTRINFO, (int)MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, - pCmdHeader, iHostID); - break; - case CommandID.EXG_IVTR_ITEM: - case CommandID.MOVE_IVTR_ITEM: - case CommandID.PLAYER_DROP_ITEM: - case CommandID.EXG_EQUIP_ITEM: - case CommandID.EQUIP_ITEM: - case CommandID.MOVE_EQUIP_ITEM: - case CommandID.UNFREEZE_IVTR_SLOT: - case CommandID.PLAYER_EQUIP_TRASHBOX_ITEM: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_ITEMOPERATION, (int)MANAGER_INDEX.MAN_PLAYER, 0, - pDataBuf, pCmdHeader); - break; - case CommandID.PLAYER_CASH: - { - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_IVTRINFO, (int)MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, - pCmdHeader, iHostID); - break; - } - case CommandID.MATTER_INFO_LIST: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_MM_MATTERINFO, (int)MANAGER_INDEX.MAN_MATTER, 0, pDataBuf, - pCmdHeader); - break; - case CommandID.MATTER_ENTER_WORLD: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_MM_MATTERENTWORLD, (int)MANAGER_INDEX.MAN_MATTER, 0, - pDataBuf, pCmdHeader); - break; - case CommandID.PICKUP_ITEM: - case CommandID.HOST_OBTAIN_ITEM: - case CommandID.PRODUCE_ONCE: - case CommandID.TASK_DELIVER_ITEM: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_PICKUPITEM, (int)MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, - pCmdHeader); - break; - case CommandID.MATTER_PICKUP: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PICKUPMATTER, (int)MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader); - break; - case CommandID.PICKUP_MONEY: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_PICKUPMONEY, (int)MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, - pCmdHeader); - break; - case CommandID.HOST_CORRECT_POS: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_CORRECTPOS, (int)MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, - pCmdHeader, iHostID); - break; - case CommandID.OWN_ITEM_INFO: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_OWNITEMINFO, (int)MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, - pCmdHeader, iHostID); - break; - case CommandID.PLAYER_DIED: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERDIED, (int)MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader); - break; - case CommandID.HOST_DIED: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_DIED, (int)MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); - break; - case CommandID.PLAYER_REVIVE: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERREVIVE, (int)MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader); - break; - case CommandID.NOTIFY_HOSTPOS: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_GOTO, (int)MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); - break; - case CommandID.NPC_ENTER_SLICE: - case CommandID.NPC_INFO_LIST: - case CommandID.NPC_INFO_00: - case CommandID.NPC_ENTER_WORLD: - case CommandID.NPC_VISIBLE_TID_NOTIFY: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_NM_NPCINFO, (int)MANAGER_INDEX.MAN_NPC, 0, pDataBuf, - pCmdHeader, dwDataSize); - break; - case CommandID.TASK_DATA: - case CommandID.TASK_VAR_DATA: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_TASKDATA, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, - pCmdHeader, dwDataSize); - break; - case CommandID.BE_HURT: - case CommandID.HURT_RESULT: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_HURTRESULT, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, - pCmdHeader); - break; - case CommandID.OBJECT_ATTACK_RESULT: - //int id = GPDataTypeHelper.FromBytes(pDataBuf); - cmd_object_atk_result pCmdAtk = GPDataTypeHelper.FromBytes(pDataBuf); - //BMLogger.LogError($"OBJECT_ATTACK_RESULT: npc ? " + ISNPCID(id)); - - if (ISPLAYERID(pCmdAtk.attacker_id)) - EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERATKRESULT, MANAGER_INDEX.MAN_PLAYER, -1, - pDataBuf, pCmdHeader); - else if (ISNPCID(pCmdAtk.attacker_id)) - EC_ManMessage.PostMessage(EC_MsgDef.MSG_NM_NPCATKRESULT, MANAGER_INDEX.MAN_NPC, 0, pDataBuf, pCmdHeader); - break; - case CommandID.HOST_ATTACKRESULT: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_ATKRESULT, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, - pCmdHeader); - break; - case CommandID.HOST_ATTACKED: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_ATTACKED, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, - pCmdHeader); - break; - - case CommandID.ERROR_MESSAGE: - { - int errRaw = BitConverter.ToInt32(pDataBuf, 0); - // Note: _logger may be configured as a file logger via SetLogPath(), so also log to console for visibility. - _logger.Info($"### GameDataSend: ERROR_MESSAGE: {errRaw}"); -#if UNITY_EDITOR - BMLogger.LogError($"### GameDataSend: ERROR_MESSAGE: {errRaw}"); -#endif - cmd_error_msg pCmd = GPDataTypeHelper.FromBytes(pDataBuf); -#if UNITY_EDITOR - BMLogger.LogError($"### GameDataSend: ERROR_MESSAGE parsed iMessage={pCmd.iMessage}"); -#endif - - if (pCmd.iMessage != 0) - { - // string szMsg = m_ErrorMsgs.GetWideString(pCmd.iMessage); - // if (string.IsNullOrEmpty(szMsg)) - // BMLogger.LogError("SERVER - unknown error !"); - //else if (pCmd.iMessage != 2) - //g_pGame.GetGameRun().AddChatMessage(szMsg, GP_CHAT_MISC); - } - - if (pCmd.iMessage == 2) - { - // Attack target is too far - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_TARGETISFAR, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); - } - else if (pCmd.iMessage == 20) - { - // Failed to cast skill - //pGameRun.PostMessage(MSG_PM_CASTSKILL, MAN_PLAYER, 0, (DWORD)pDataBuf, pCmdHeader.cmd); - } - else if (pCmd.iMessage == 133 || pCmd.iMessage == 134) - { - // deal failed - //pGameRun.PostMessage(MSG_HST_BUY_SELL_FAIL, MAN_PLAYER, 0, (DWORD)pDataBuf, pCmdHeader.cmd); - } - else if (pCmd.iMessage == 158) - { - // µ±Ç°»ãÂʲ»¶Ô£¬ÖØÐÂÈ¡»ãÂÊ - //c2s_CmdGetCashMoneyRate(); - } - else if (pCmd.iMessage == 108 /*&& pGameRun.GetHostPlayer().IsInKingService()*/) - { - /* CECGameUIMan* pGameUI = pGameRun.GetUIManager().GetInGameUIMan(); - if (pGameUI) - pGameUI.EndNPCService();*/ - } - else if - (pCmd.iMessage == 108 /*&& pGameRun.GetHostPlayer().GetOfflineShopCtrl().GetNPCSevFlag() != COfflineShopCtrl::NPCSEV_NULL*/ - ) - { - /* CECGameUIMan* pGameUI = pGameRun.GetUIManager().GetInGameUIMan(); - if (pGameUI) - pGameUI.EndNPCService();*/ - } - else if (pCmd.iMessage == 175) - { - //c2s_CmdQueryParallelWorld(); - } - else if (pCmd.iMessage == 6) - { - //AP_ActionEvent(AP_EVENT_CANNOTPICKUP); - } - - break; - } - case CommandID.SELECT_TARGET: - case CommandID.UNSELECT: - - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_SELTARGET, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, - pCmdHeader); - break; - case CommandID.NPC_DIED: - case CommandID.NPC_DIED2: - - EC_ManMessage.PostMessage(EC_MsgDef.MSG_NM_NPCDIED, MANAGER_INDEX.MAN_NPC, 0, pDataBuf, pCmdHeader); - break; - case CommandID.OBJECT_DISAPPEAR: - { - int lenghtDataType1 = Marshal.SizeOf(); - byte[] arrByteData1 = GetBytes(pDataBuf, lenghtDataType1, 0); - int objectId = BitConverter.ToInt32(arrByteData1); - if (ISPLAYERID(objectId)) - EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERDISAPPEAR, MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader); - else if (ISNPCID(objectId)) - EC_ManMessage.PostMessage(EC_MsgDef.MSG_NM_NPCDISAPPEAR, MANAGER_INDEX.MAN_NPC, 0, pDataBuf, pCmdHeader); - else if (ISMATTERID(objectId)) - EC_ManMessage.PostMessage(EC_MsgDef.MSG_MM_MATTERDISAPPEAR, MANAGER_INDEX.MAN_MATTER, 0, pDataBuf, pCmdHeader); - - break; - } - case CommandID.SELF_INFO_00: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_INFO00, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, - pCmdHeader); - break; - case CommandID.NPC_GREETING: - { - // If this greeting is from the skill-learn NPC, record it (C++ skill dialog relies on this). - try - { - cmd_npc_greeting greet = GPDataTypeHelper.FromBytes(pDataBuf); - CECHostSkillModel.Instance.OnNpcGreeting(greet.idObject); - } - catch (Exception ex) - { - _logger.Log(LogType.Warning, $"Failed to parse NPC_GREETING payload: {ex.Message}"); - } - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_NPCGREETING, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); - break; - } - case CommandID.ACTIVATE_WAYPOINT: - case CommandID.WAYPOINT_LIST: - - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_WAYPOINT, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); - break; - case CommandID.SERVER_TIME: - { - cmd_server_time pcmd_server_time = GPDataTypeHelper.FromBytes(pDataBuf); - EC_ManMessage.PostMessage(EC_MsgDef.MSG_SERVERTIME, -1, 0, pcmd_server_time.time, pcmd_server_time.timebias); - break; - } - case CommandID.SCENE_SERVICE_NPC_LIST: - { - CECHostSkillModel.Instance.RecvNPCServiceList(protocol.Data); - break; - } - case CommandID.SKILL_DATA: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_SKILLDATA, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); - break; - case CommandID.OBJECT_CAST_SKILL: - case CommandID.OBJECT_CAST_INSTANT_SKILL: - case CommandID.OBJECT_CAST_POS_SKILL: - { - cmd_object_cast_skill pCmd2 = GPDataTypeHelper.FromBytes(pDataBuf,true); - if (ISPLAYERID(pCmd2.caster)) - EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_CASTSKILL, MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader); - else if (ISNPCID(pCmd2.caster)) - EC_ManMessage.PostMessage(EC_MsgDef.MSG_NM_NPCCASTSKILL, MANAGER_INDEX.MAN_NPC, 0, pDataBuf, pCmdHeader); - - break; - } - case CommandID.LEVEL_UP: - { - cmd_level_up pCmdLevelUp = GPDataTypeHelper.FromBytes(pDataBuf); ; - if (ISPLAYERID(pCmdLevelUp.id)) - EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERLEVELUP, MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader); - else if (ISNPCID(pCmdLevelUp.id)) - EC_ManMessage.PostMessage(EC_MsgDef.MSG_NM_NPCLEVELUP, MANAGER_INDEX.MAN_NPC, 0, pDataBuf, pCmdHeader); - break; - } - case CommandID.HOST_START_ATTACK: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_STARTATTACK, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader, dwDataSize); - break; - case CommandID.HOST_STOPATTACK: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_STOPATTACK, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader, dwDataSize); - break; - case CommandID.HOST_SKILL_ATTACK_RESULT: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_SKILLRESULT, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); - break; - case CommandID.CHANGE_FACE_START: - case CommandID.CHANGE_FACE_END: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_CHANGEFACE, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader, dwDataSize); - break; - case CommandID.ENCHANT_RESULT: - cmd_enchant_result pCmd3 = GPDataTypeHelper.FromBytes(pDataBuf); - if (ISPLAYERID(pCmd3.caster)) - EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_ENCHANTRESULT, MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader); - else if (ISNPCID(pCmd3.caster)) - EC_ManMessage.PostMessage(EC_MsgDef.MSG_NM_ENCHANTRESULT, MANAGER_INDEX.MAN_NPC, 0, pDataBuf, pCmdHeader); - break; - case CommandID.SKILL_PERFORM: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_CASTSKILL, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); - break; - case CommandID.SET_COOLDOWN: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_SETCOOLTIME, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); - break; - case CommandID.COMBO_SKILL_PREPARE: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_COMBO_SKILL_PREPARE, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader, dwDataSize); - break; - case CommandID.PLAYER_EXT_PROP_BASE: - case CommandID.PLAYER_EXT_PROP_MOVE: - case CommandID.PLAYER_EXT_PROP_ATK: - case CommandID.PLAYER_EXT_PROP_DEF: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYEREXTPROP, MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader); - break; - case CommandID.OWN_EXT_PROP: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_OWNEXTPROP, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); - break; - case CommandID.OBJECT_DO_EMOTE: - case CommandID.OBJECT_EMOTE_RESTORE: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERDOEMOTE, MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader); - break; - case CommandID.OUT_OF_SIGHT_LIST: - { - cmd_out_of_sight_list pCmd5 = default; - pCmd5.uCount = GPDataTypeHelper.FromBytes(pDataBuf); - int offset2 = sizeof(uint); - pCmd5.idList = new int[pCmd5.uCount]; - for (int i = 0; i < pCmd5.uCount; i++) - { - pCmd5.idList[i] = GPDataTypeHelper.FromBytes(pDataBuf, offset2); - offset2 += 4;//sizeof int; - } - - for (uint n = 0; n < pCmd5.uCount; n++) - { - if (ISPLAYERID(pCmd5.idList[n])) - EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYEROUTOFVIEW, MANAGER_INDEX.MAN_PLAYER, -1, pCmd5.idList[n], pCmdHeader); - else if (ISNPCID(pCmd5.idList[n])) - EC_ManMessage.PostMessage(EC_MsgDef.MSG_NM_NPCOUTOFVIEW, MANAGER_INDEX.MAN_NPC, 0, pCmd5.idList[n], pCmdHeader); - else if (ISMATTERID(pCmd5.idList[n])) - EC_ManMessage.PostMessage(EC_MsgDef.MSG_MM_MATTEROUTOFVIEW, MANAGER_INDEX.MAN_MATTER, 0, pCmd5.idList[n], pCmdHeader); - } - - break; - } - case CommandID.PLAYER_GATHER_START: - case CommandID.PLAYER_GATHER_STOP: - case CommandID.MINE_GATHERED: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERGATHER, MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader); - break; - case CommandID.COOLTIME_DATA: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_COOLTIMEDATA, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); - break; - case CommandID.OBJECT_TAKEOFF: - { - cmd_object_takeoff pCmdTakeOff = GPDataTypeHelper.FromBytes((byte[])pDataBuf); - if (ISPLAYERID(pCmdTakeOff.object_id)) - EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERFLY, MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader); - break; - } - case CommandID.OBJECT_LANDING: - { - cmd_object_landing pCmdLanding = GPDataTypeHelper.FromBytes((byte[])pDataBuf); - if (ISPLAYERID(pCmdLanding.object_id)) - EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERFLY, MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader); - break; - } - case CommandID.HOST_RUSH_FLY: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERFLY, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); - break; - case CommandID.FLYSWORD_TIME: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_FLYSWORDTIME, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); - break; - case CommandID.PRODUCE_START: - case CommandID.PRODUCE_END: - case CommandID.PRODUCE_NULL: - // Post MSG_HST_PRODUCEITEM message with command ID as parameter (matches C++ behavior) - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_PRODUCEITEM, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); - break; - - - case CommandID.LEARN_SKILL: - BMLogger.LogError("### GameDataSend: LEARN_SKILL"); - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_LEARNSKILL, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); - break; - case CommandID.EMBED_ITEM: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_EMBEDITEM, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); - break; - default: -#if UNITY_EDITOR - if (isDebug) - { - BMLogger.LogError($"### GameDataSend: Unhandled CMDID {pCmdHeader} (payloadBytes={pDataBuf?.Length ?? 0})"); - } -#endif - break; - } - } - - - private void HandleSelectRoleResponse(SelectRole_Re protocol) - { - _logger.Info($"Select role response {protocol.result}"); - _selectRoleCallback?.Invoke(_selectedRole); - } - - private void OnErrorOccurred(string errorMessage) - { - _logger.Log(LogType.Error, $"Network Error: {errorMessage}"); - FailLoginInProgress(errorMessage); - FailRoleListInProgress(errorMessage); - } - - private void OnDisconnected() - { - _logger.Log(LogType.Info, "Disconnected from server."); - _currentUserId = -1; - FailLoginInProgress("Disconnected"); - FailRoleListInProgress("Disconnected"); - // Clear command cache - m_CmdCache.RemoveAllCmds(); - } - - // --- Protocol Handling Logic --- - - private void HandleChallenge(challenge challenge) - { - if (_loginCallback == null || string.IsNullOrEmpty(_username)) - { - _logger.Log(LogType.Warning, "Received Challenge but not expecting it or username not set."); - return; - } - - _logger.Log(LogType.Info, "Handling Challenge..."); - - response response = new response(); - byte[] usernameBytes = Encoding.ASCII.GetBytes(_username); - byte[] passwordBytes = Encoding.ASCII.GetBytes(_password); - response.identity.Replace(usernameBytes); - response.Setup(new Octets(usernameBytes), new Octets(passwordBytes), challenge.nonce); - - uint clientId = 0xffffffff; - byte[] clientIdBytes = BitConverter.GetBytes(clientId); - response.cli_fingerprint.Replace(clientIdBytes); - response.use_token = 0; - - _networkManager.SetNonce(response.response_data); - SendProtocol(response); - _logger.Log(LogType.Info, "Sent Response."); - } - - private void HandleKeyExchange(KeyExchange keyExchange) - { - if (_loginCallback == null || string.IsNullOrEmpty(_username)) - { - _logger.Log(LogType.Warning, "Received KeyExchange but not expecting it."); - return; - } - - _logger.Log(LogType.Info, "Handling KeyExchange..."); - keyExchange.Setup(_networkManager, _username); - keyExchange.Blkickuser = 1; - SendProtocol(keyExchange); - _logger.Log(LogType.Info, "Sent KeyExchange acknowledgment/response."); - } - - private void HandleOnlineAnnounce(onlineannounce announce) - { - if (_loginCallback == null) - { - _logger.Log(LogType.Warning, "Received OnlineAnnounce but not expecting it."); - return; - } - - _logger.Log(LogType.Info, $"Login successful! UserID: {announce.Userid}, LocalSID: {announce.Localsid}"); - _currentUserId = announce.Userid; - - var callback = _loginCallback; - _loginCallback = null; - callback?.Invoke(true); - } - - private void RequestRoleListInternal(int lastHandle = -1) - { - rolelist rolelistRequest = new rolelist(); - rolelistRequest.Userid = _currentUserId; - rolelistRequest.Localsid = 0; - rolelistRequest.Handle = lastHandle; - - SendProtocol(rolelistRequest); - - - //gamedatasend gamedatasendRequest = new gamedatasend(); - //gamedatasendRequest.Data = C2SCommandFactory.CreatePlayerMove(); - - //SendProtocol(gamedatasendRequest); - } - - private void HandleRoleListResponse(RoleListResponse response) - { - if (_roleListCallback == null || _accumulatedRoles == null) - { - _logger.Log(LogType.Warning, "Received RoleListResponse but not expecting it."); - return; - } - - _logger.Log(LogType.Debug, - $"Received RoleListResponse. Handle: {response.handle}, Result: {response.result}, Count: {response.rolelist.Count}"); - - if (response.result == 0) - { - _accumulatedRoles.AddRange(response.rolelist); - - foreach (var role in response.rolelist) - { - try - { - string roleName = Encoding.UTF8.GetString(role.name.ByteArray, 0, role.name.Length); - _logger.Log(LogType.Info, $" - Role ID: {role.roleid}, Name: {roleName}, Level: {role.level}"); - } - catch (Exception ex) - { - _logger.Log(LogType.Error, $" - Error decoding role name: {ex.Message}"); - _logger.LogException(ex); - } - } - - if (response.handle != -1) - { - _logger.Log(LogType.Debug, $"Requesting next batch of roles (handle: {response.handle})..."); - RequestRoleListInternal(response.handle); - } - else - { - _logger.Log(LogType.Info, $"Finished fetching roles. Total count: {_accumulatedRoles.Count}"); - var callback = _roleListCallback; - var result = _accumulatedRoles; - _roleListCallback = null; - _accumulatedRoles = null; - callback?.Invoke(result); - } - } - else - { - _logger.Log(LogType.Error, $"Role list retrieval failed. Result code: {response.result}"); - FailRoleListInProgress($"Role list retrieval failed (Result: {response.result})"); - } - } - - // --- Helper methods for failure handling --- - private void FailLoginInProgress(string reason) - { - if (_loginCallback != null) - { - _logger.Log(LogType.Error, $"Login failed: {reason}"); - var callback = _loginCallback; - _loginCallback = null; - callback?.Invoke(false); - } - } - - private void FailRoleListInProgress(string reason) - { - if (_roleListCallback != null) - { - _logger.Log(LogType.Error, $"Role list retrieval failed: {reason}"); - var callback = _roleListCallback; - _roleListCallback = null; - _accumulatedRoles = null; - callback?.Invoke(null); - } - } - - // --- IDisposable Implementation --- - private bool disposedValue = false; - - protected virtual void Dispose(bool disposing) - { - if (!disposedValue) - { - if (disposing) - { - if (_networkManager != null) - { - _logger.Log(LogType.Info, "[DUCK] Disposing GameSession and disconnecting..."); - _networkManager.ProtocolReceived -= OnProtocolReceived; - _networkManager.ErrorOccurred -= OnErrorOccurred; - _networkManager.Disconnected -= OnDisconnected; - _networkManager.Disconnect(); - _networkManager.Dispose(); - _networkManager = null; - } - - _loginCallback = null; - _roleListCallback = null; - _accumulatedRoles = null; - } - - disposedValue = true; - } - } - - public void Dispose() - { - Dispose(true); - // GC.SuppressFinalize(this); - } - - public bool ISPLAYERID(int id) - { - return id != 0 && (id & 0x80000000) == 0; - } - public bool ISNPCID(int id) => ((id & 0x80000000) != 0) && ((id & 0x40000000) == 0); - public bool ISMATTERID(int id) => ((id) & 0xC0000000) == 0xC0000000; - private byte[] GetBytes(byte[] bytes, int length, int index) - { - byte[] arrByteData = new byte[length]; - for (int i = 0; i < length; i++) - { - arrByteData[i] = bytes[i + index]; - } - - return arrByteData; - } - - public void c2s_CmdPlayerMove(in Vector3 vCurPos, in Vector3 vDest, - int iTime, float fSpeed, int iMoveMode, ushort wStamp) - { - gamedatasend gamedatasend = new gamedatasend(); - - gamedatasend.Data = - C2SCommandFactory.CreatePlayerMove(vCurPos, vDest, (ushort)iTime, fSpeed, (byte)iMoveMode, wStamp); - SendProtocol(gamedatasend); - } - public void c2s_SendCmdCastSkill(int idSkill, byte byPVPMask, int iNumTarget, int[] aTargets) - { - gamedatasend gamedatasend = new gamedatasend(); - - gamedatasend.Data = - C2SCommandFactory.CreatePlayerCastSkill(idSkill, byPVPMask, iNumTarget, aTargets); - - SendProtocol(gamedatasend); - } - - public void c2s_SendCmdCastInstantSkill(int idSkill, byte byPVPMask, int iNumTarget, int[] aTargets) - { - gamedatasend gamedatasend = new gamedatasend(); - - gamedatasend.Data = - C2SCommandFactory.CreatePlayerCastInstantSkill(idSkill, byPVPMask, iNumTarget, aTargets); - - SendProtocol(gamedatasend); - } - - public void c2s_CmdCastPosSkill(int idSkill, Vector3 vDest, byte byPVPMask, int iNumTarget, int aTargets) - { - gamedatasend gamedatasend = new gamedatasend(); - - gamedatasend.Data = - C2SCommandFactory.CreatePlayerCastPosSkill(idSkill, vDest, byPVPMask, iNumTarget, aTargets); - - SendProtocol(gamedatasend); - } - public void c2s_SendCmdContinueAction() - { - gamedatasend gamedatasend = new gamedatasend(); - gamedatasend.Data = C2SCommandFactory.CreateNakeCmd(C2SCommand.CommandID.CONTINUE_ACTION); - SendProtocol(gamedatasend); - } - public void c2s_SendCmdStopMove(in Vector3 vDest, float fSpeed, int iMoveMode, - byte byDir, ushort wStamp, int iTime) - { - gamedatasend gamedatasend = new gamedatasend(); - - gamedatasend.Data = - C2SCommandFactory.CreatePlayerStop(vDest, fSpeed, (byte)iMoveMode, byDir, wStamp, (ushort)iTime); - SendProtocol(gamedatasend); - } - - public void c2s_CmdSendEnterPKPrecinctint() - { - gamedatasend gamedatasend = new gamedatasend(); - gamedatasend.Data = C2SCommandFactory.CreateNakeCmd(C2SCommand.CommandID.ENTER_PK_PROTECTED); - SendProtocol(gamedatasend); - } - public void SendChatData(byte cChannel, in string szMsg, int iPack, int iSlot) - { - publicchat publicChat = new publicchat(); - publicChat.Channel = cChannel; - publicChat.Roleid = m_iCharID; - - byte[] unicodeBytes = Encoding.Unicode.GetBytes(szMsg); - publicChat.Msg.Replace(unicodeBytes); - _logger.Log(LogType.Warning, $"HoangDev : publicChat {publicChat}"); - SendProtocol(publicChat); - } - public void LoadConfigData() - { - getuiconfig p = new getuiconfig(); - p.Roleid = m_iCharID; - SendProtocol(p); - } - private void SetCharacterID(int iCharID) - { - m_iCharID = iCharID; - } - - private void OnPrtcChatMessage(Protocol pProtocol, bool bCalledagain) - { - chatmessage p = (chatmessage)pProtocol; - - string strTemp = System.Text.Encoding.Unicode.GetString(p.Msg.ToArray(), 0, p.Msg.Length); - - _logger.Log(LogType.Warning, $"HoangDev : OnPrtcChatMessage :{strTemp}"); - EventBus.Publish(new ChatMessageEvent(strTemp)); - } - - public struct ChatMessageEvent - { - public string context; - - public ChatMessageEvent(string context) - { - this.context = context; - } - } - public void OnPrtcGetConfigRe(Protocol pProtocol) - { - getuiconfig_re p = (getuiconfig_re)pProtocol; - if (p.Result != (int)ErrCode.ERR_SUCCESS) - BMLogger.LogError("CECGameSession::OnPrtcGetConfigRe, link return error code of " + p.Result); - else - { - if (!CECGameRun.Instance.LoadConfigsFromServer(p.UiConfig.RawBuffer, p.UiConfig.Size)) - { - // if load failed then use current setting directly - //TODO : fix later - EC_Game.GetConfigs().ApplyUserSetting(); - } - - // Now, Get config data request is sent after all host initial data ready. - // so when we receive this reply, we can do some last work before game - // really starts. Maybe it's not the best place to do these work, but - // now we do it here. - // Enalbe game UI - CECGameUIMan pGameUI = (CECGameUIMan)EC_Game.GetGameRun().GetUIManager().GetInGameUIMan(); - if (pGameUI != null) - { - pGameUI.EnableUI(true); - - // Get referral name for adding friend or other display - //TODO: a Hung lam phan select role info di - /* RoleInfo info = EC_Game.GetGameRun().GetSelectedRoleInfo(); - if (info.referrer_role > 0) - GetPlayerBriefInfo(1, info.referrer_role, 2);*/ - } - - CECHostPlayer pHost = EC_Game.GetGameRun().GetHostPlayer(); - pHost.OnAllInitDataReady(); - - /* if (pHost.IsGM()) - { - CDlgCountryMap pDlgCountryMap = (CDlgCountryMap)pGameUI.GetDialog("Win_CountryMap"); - pDlgCountryMap.GetConfig(); - } - - g_pGame.GetConfigs().ApplyOptimizeSetting(); - - if (g_pGame.GetConfigs().IsMiniClient()) - CECMCDownload::GetInstance().SendGetDownloadOK();*/ - } - } - private void OnPrtcPlayerBaseInfoRe(Protocol pProtocol) - { - playerbaseinfo_re p = (playerbaseinfo_re)pProtocol; - BMLogger.Log($"OnPrtcPlayerBaseInfoRe: {p.Roleid} {p.Player.cls} {p.Player.gender}"); - EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERBASEINFO, MANAGER_INDEX.MAN_PLAYER, -1, p); - } - - public void c2s_CmdNPCSevAcceptTask(int idTask, int idStorage, int idRefreshItem) - { - gamedatasend gamedatasend = new gamedatasend(); - gamedatasend.Data = C2SCommandFactory.CreateCmdNPCSevAcceptTask(idTask, idStorage, idRefreshItem); - SendProtocol(gamedatasend); - } - - public void c2s_SendCmdGetAllData(bool byPack, bool byEquip, bool byTask) - { - gamedatasend gamedatasend = new gamedatasend(); - - gamedatasend.Data = C2SCommandFactory.CreateGetAllDataCommand(byPack, byEquip, byTask); - _logger.Log(LogType.Warning, $"[Dat]- SendCmdGetAllData {byPack},{byEquip},{byTask}"); - SendProtocol(gamedatasend); - } - - public void c2s_SendCmdNPCSevHello(int nid) - { - gamedatasend gamedatasend = new gamedatasend(); - gamedatasend.Data = C2SCommandFactory.CreateNPCSevHelloDataCommand(nid); - SendProtocol(gamedatasend); - } - - public void c2s_CmdNormalAttack(byte byPVPMask) - { - gamedatasend gamedatasend = new gamedatasend(); - gamedatasend.Data = C2SCommandFactory.CreateNormalAttackDataCmd(byPVPMask); - SendProtocol(gamedatasend); - } - - public void c2s_SendCmdCancelAction() - { - gamedatasend gamedatasend = new gamedatasend(); - gamedatasend.Data = C2SCommandFactory.CreateNakeCmd(CSNetwork.C2SCommand.CommandID.CANCEL_ACTION); - SendProtocol(gamedatasend); - } - - public void c2s_CmdUnselect() - { - gamedatasend gamedatasend = new gamedatasend(); - gamedatasend.Data = C2SCommandFactory.CreateNakeCmd(CSNetwork.C2SCommand.CommandID.UNSELECT); - SendProtocol(gamedatasend); - } - - public void c2s_SendCmdSelectTarget(int idTarget) - { - gamedatasend gamedatasend = new gamedatasend(); - gamedatasend.Data = C2SCommandFactory.CreateSelectTarget(idTarget); - SendProtocol(gamedatasend); - } - - public void c2s_SendCmdNPCSevWaypoint() - { - gamedatasend gamedatasend = new gamedatasend(); - gamedatasend.Data = C2SCommandFactory.CreateNPCSevWaypointCmd(NPC_service_type.GP_NPCSEV_WAYPOINT, 0); - SendProtocol(gamedatasend); - } - public void c2s_SendCmdNPCSevMakeItem(int idSkill, int idItem, uint dwCount) - { - gamedatasend gamedatasend = new gamedatasend(); - gamedatasend.Data = C2SCommandFactory.CreateNPCSevMakeItemCmd(idSkill, idItem, dwCount); - SendProtocol(gamedatasend); - } - public void GetRoleBaseInfo(int iNumRole, List aRoleIDs) - { - int iNumLimit = 128; - playerbaseinfo p = null; - int iCount = 0; - - while (iCount < iNumRole) - { - p = new(); - p.Roleid = _selectedRole.roleid; - - int iNumSend = iNumLimit; - if (iCount + iNumLimit > iNumRole) - iNumSend = iNumRole - iCount; - - if (iNumSend > 0) - { - p.playerList = new(); - for (int i = 0; i < iNumSend; i++) - p.playerList.Add(aRoleIDs[iCount + i]); - - SendProtocol(p); - } - - - iCount += iNumSend; - } - } - - public void c2s_SendCmdGetOtherEquip(int iNumID, List aIDs) - { - // int iNumLimit = 250; - // int iCount = 0; - - // while (iCount < iNumID) - // { - // int iNumSend = iNumLimit; - // if (iCount + iNumLimit > iNumID) - // iNumSend = iNumID - iCount; - - // if (iNumSend > 0) - // { - // } - // } - } - - public void c2s_SendCmdNPCSevAcceptTask(int idTask, int idStorage, int idRefreshItem) - { - gamedatasend gamedatasend = new gamedatasend(); - gamedatasend.Data = C2SCommandFactory.CreateCmdNPCSevAcceptTask( - idTask, - idStorage, - idRefreshItem); - SendProtocol(gamedatasend); - } - - public void c2s_SendCmdNPCSevReturnTask(int idTask, int iChoice) - { - gamedatasend gamedatasend = new gamedatasend(); - gamedatasend.Data = C2SCommandFactory.CreateNPCSevReturnTaskCmd( - idTask, - iChoice); - SendProtocol(gamedatasend); - } - - public void c2s_SendCmdNPCSevTaskMatter(int idTask) - { - gamedatasend gamedatasend = new gamedatasend(); - gamedatasend.Data = C2SCommandFactory.CreateNPCSevTaskMatterCmd(idTask); - SendProtocol(gamedatasend); - } - - public void c2s_SendCmdNPCSevLearnSkill(int idSkill) - { - gamedatasend gamedatasend = new gamedatasend(); - gamedatasend.Data = C2SCommandFactory.CreateNPCSevLearnSkillCmd(idSkill); - BMLogger.LogError("HoangDev : c2s_SendCmdNPCSevLearnSkill gamedatasend.Data : " + gamedatasend.Data.Size); - BMLogger.LogError("HoangDev : c2s_SendCmdNPCSevLearnSkill idSkill : " + idSkill); - SendProtocol(gamedatasend); - } - - public void c2s_SendCmdNPCSevBuy(int itemNum, C2SCommand.npc_trade_item[] items) - { - if (itemNum <= 0 || items == null || items.Length < itemNum) - return; - - gamedatasend gamedatasend = new gamedatasend(); - gamedatasend.Data = C2SCommandFactory.CreateNPCSevBuyCmd(itemNum, items); - SendProtocol(gamedatasend); - } - - public void c2s_SendCmdNPCSevSell(int itemNum, C2SCommand.npc_sell_item[] items) - { - if (itemNum <= 0 || items == null || items.Length < itemNum) - return; - - gamedatasend gamedatasend = new gamedatasend(); - gamedatasend.Data = C2SCommandFactory.CreateNPCSevSellCmd(itemNum, items); - SendProtocol(gamedatasend); - } - - public void GetRoleCustomizeData(int iNumRole, List aRoleIDs) - { - if (iNumRole <= 0 || aRoleIDs == null || aRoleIDs.Count == 0) return; - - int iNumLimit = 240; - int iCount = 0; - - while (iCount < iNumRole) - { - getcustomdata p = new(); - p.Roleid = _selectedRole.roleid; - - int iNumSend = iNumLimit; - if (iCount + iNumLimit > iNumRole) - iNumSend = iNumRole - iCount; - - for (int i = 0; i < iNumSend; i++) - p.playerlist.Add(aRoleIDs[iCount + i]); - - SendProtocol(p); - - iCount += iNumSend; - } - } - public void c2s_SendCmdEmoteAction(uint wPose) - { - gamedatasend gamedatasend = new gamedatasend(); - gamedatasend.Data = C2SCommandFactory.CreateEmoteActionCmd((int)wPose); - SendProtocol(gamedatasend); - } - public void c2s_SendCmdTaskNotify(byte[] pData, uint dwDataSize) - { - gamedatasend gamedatasend = new gamedatasend(); - gamedatasend.Data = C2SCommandFactory.CreateTaskNotifyCmd( pData, dwDataSize); - BMLogger.Log($"[MH Task] c2s_SendCmdTaskNotify Command ID : {pData[0]} Size: {dwDataSize}"); - SendProtocol(gamedatasend); - } - - public void c2s_SendCmdStandUp() - { - gamedatasend gamedatasend = new gamedatasend(); - gamedatasend.Data = C2SCommandFactory.CreateNakeCmd(C2SCommand.CommandID.STAND_UP); - SendProtocol(gamedatasend); - } - - public void c2s_SendCmdAutoTeamSetGoal(int type, int goal_id, int op) - { - gamedatasend gamedatasend = new gamedatasend(); - gamedatasend.Data = C2SCommandFactory.CreateAutoTeamSetGoalCommand(type,goal_id, op); - SendProtocol(gamedatasend); - } - - public void c2s_CmdGoto(float x, float y, float z) - { - c2s_SendCmdGoto(x, y, z); - } - - // Send C2S::GOTO command data - void c2s_SendCmdGoto(float x, float y, float z) - { - gamedatasend gamedatasend = new gamedatasend(); - gamedatasend.Data = C2SCommandFactory.CreateGoToCommed( x, y, z); - SendProtocol(gamedatasend); - } - - public void c2s_SendCmdUseItem(byte byPackage, byte bySlot, int tid, byte byCount) - { - gamedatasend gamedatasend = new gamedatasend(); - gamedatasend.Data = C2SCommandFactory.CreateUseItemCmd(byPackage, bySlot, tid, byCount); - SendProtocol(gamedatasend); - } - - public void c2s_SendCmdGetExtProps() - { - gamedatasend gamedatasend = new gamedatasend(); - gamedatasend.Data = C2SCommandFactory.CreateNakeCmd(C2SCommand.CommandID.GET_EXT_PROP); - SendProtocol(gamedatasend); - } - - public void c2s_SendCmdGivePresent(int roleid, int mail_id, int goods_id, int goods_index, int goods_slot) - { - gamedatasend gamedatasend = new gamedatasend(); - gamedatasend.Data = C2SCommandFactory.CreateGivePresentCmd(roleid, mail_id, goods_id, goods_index, goods_slot); - SendProtocol(gamedatasend); - } - - public void c2s_SendCmdEnterSanctuary(int id) - { - gamedatasend gamedatasend = new gamedatasend(); - gamedatasend.Data = C2SCommandFactory.CreateEnterSanctuaryCmd(id); - SendProtocol(gamedatasend); - } - - public void c2s_SendCmdEnterInstance(int iTransIdx, int idInst) - { - gamedatasend gamedatasend = new gamedatasend(); - gamedatasend.Data = C2SCommandFactory.CreateEnterInstanceCmd(iTransIdx, idInst); - SendProtocol(gamedatasend); - } - - public void c2s_SendCmdActiveRushFly(bool bActive) - { - gamedatasend gamedatasend = new gamedatasend(); - gamedatasend.Data = C2SCommandFactory.CreateActiveRushFlyCmd(bActive); - SendProtocol(gamedatasend); - } - - public void c2s_SendCmdPetCtrl(int idTarget, int cmd, byte[] pParamBuf, int iParamLen) - { - gamedatasend gamedatasend = new gamedatasend(); - gamedatasend.Data = C2SCommandFactory.CreatePetCtrlCmd(idTarget, cmd, pParamBuf, iParamLen); - SendProtocol(gamedatasend); - } - - public void c2s_SendCmdQueryFactionPVPInfo(int faction_id) - { - gamedatasend gamedatasend = new gamedatasend(); - gamedatasend.Data = C2SCommandFactory.CreateQueryFactionPVPInfo(faction_id); - SendProtocol(gamedatasend); - } - public void c2s_SendCmdNPCSevEmbed(ushort wStoneIdx, ushort wEquipIdx, int tidStone, int tidEquip) - { - gamedatasend gamedatasend = new gamedatasend(); - gamedatasend.Data = C2SCommandFactory.CreateNPCSevEmbedCmd(wStoneIdx, wEquipIdx, tidStone, tidEquip); - SendProtocol(gamedatasend); - } - public void c2s_SendCmdGetItemInfo(byte byPackage, int bySlot) - { - gamedatasend gamedatasend = new gamedatasend(); - gamedatasend.Data = C2SCommandFactory.CreateGetItemInfoCmd(byPackage, bySlot); - SendProtocol(gamedatasend); - } - } +using BrewMonster; +using BrewMonster.Common; +using BrewMonster.Managers; +using BrewMonster.Network; +using BrewMonster.Scripts.Skills; +using BrewMonster.UI; +using CSNetwork.C2SCommand; +using CSNetwork.GPDataType; +using CSNetwork.Protocols; +using CSNetwork.Protocols.RPCData; +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using UnityEngine; +using CommandID = CSNetwork.GPDataType.CommandID; + +namespace CSNetwork +{ + public class GameSession : IDisposable + { + private static IPrefixedLogger + _logger = LoggerFactory.GetLogger(nameof(GameSession)); // Get class-specific logger + + private NetworkManager _networkManager; + private string _host; + private int _port; + private string _username; + private string _password; + private int _currentUserId = -1; // To store the UserID after successful login + private uint _localsid = 0; // To store the LocalSID from onlineannounce + private int m_iCharID; + private int m_idLastSelTarget = 0; // ID of selected item last time + + CECStringTab m_ErrorMsgs; + + // State management for async operations and callbacks + private Action _loginCallback; + private Action> _roleListCallback; + private List _accumulatedRoles; + private Action _selectRoleCallback; + private Action _createRoleCallback; + private RoleInfo _selectedRole; + public bool IsConnected => _networkManager?.IsConnected ?? false; + public static SynchronizationContext Context; + private CECC2SCmdCache m_CmdCache; // C2S command cache + + private static void PostToUnityContext(Action action) + { + if (action == null) return; + var ctx = Context; + if (ctx != null) + { + ctx.Post(_ => action(), null); + } + else + { + action(); + } + } +#if UNITY_EDITOR + public bool isDebug; + public bool IsDebug + { + get => isDebug; + set => isDebug = value; + } +#endif + public CECC2SCmdCache CmdCache { get => m_CmdCache; } + + + public GameSession() + { + _networkManager = new NetworkManager(); + m_CmdCache = new CECC2SCmdCache(); + _networkManager.ProtocolReceived += OnProtocolReceived; + _networkManager.ErrorOccurred += OnErrorOccurred; + _networkManager.Disconnected += OnDisconnected; + } + + public void SetLogPath(string path) + { + LoggerFactory.SetFileLoggerImplementation(new FileLogger()); + _logger = LoggerFactory.GetCustomLogger(path, nameof(GameSession) + GetHashCode(), LoggerType.File); + _networkManager.SetLogPath(path); + } + + /// + /// Connects to the game server asynchronously. + /// + /// Server hostname or IP address. + /// Server port. + /// Task representing the asynchronous connect operation. Check IsConnected property or handle Disconnected event for status. + public async Task ConnectAsync(string host, int port) + { + if (IsConnected) + { + _logger.Log(LogType.Warning, "ConnectAsync called but already connected."); + return; + } + + _host = host; + _port = port; + _logger.Log(LogType.Info, $"Attempting to connect to {_host}:{_port}..."); + try + { + await _networkManager.ConnectAsync(_host, _port); + if (IsConnected) + { + _logger.Log(LogType.Info, "Connection established."); + } + else + { + _logger.Log(LogType.Warning, + "Connection failed after ConnectAsync completed (check NetworkManager logs/events)."); + } + } + catch (Exception ex) + { + _logger.Log(LogType.Error, $"Connection exception: {ex.Message}"); + _logger.LogException(ex); + OnDisconnected(); + } + } + + + public void Disconnect() + { + _networkManager.Disconnect(); + } + + /// + /// Initiates the login process asynchronously. + /// + /// Account username. + /// Account password. + /// Action invoked with true on successful login (OnlineAnnounce received), false otherwise. + public void LoginAsync(string username, string password, Action callback) + { + if (!IsConnected) + { + _logger.Log(LogType.Warning, "LoginAsync called but not connected."); + callback?.Invoke(false); + return; + } + + if (_loginCallback != null) + { + _logger.Log(LogType.Warning, "LoginAsync called while another login is already in progress."); + callback?.Invoke(false); + return; + } + + _username = username; + _password = password; + _loginCallback = callback; + _currentUserId = -1; // Reset user ID + + _logger.Log(LogType.Info, $"Initiating login for user '{_username}'..."); + } + + /// + /// Initiates fetching the role list asynchronously. Requires successful login. + /// + /// Action invoked with the complete list of roles, or null/empty list on failure. + public void GetRoleListAsync(Action> callback) + { + if (!IsConnected) + { + _logger.Log(LogType.Warning, "GetRoleListAsync called but not connected."); + callback?.Invoke(null); + return; + } + + if (_currentUserId == -1) + { + _logger.Log(LogType.Warning, "GetRoleListAsync called but not logged in."); + callback?.Invoke(null); + return; + } + + if (_roleListCallback != null) + { + _logger.Log(LogType.Warning, + "GetRoleListAsync called while another role list retrieval is already in progress."); + callback?.Invoke(null); + return; + } + + _roleListCallback = callback; + _accumulatedRoles = new List(); + _logger.Log(LogType.Info, "Requesting role list..."); + RequestRoleListInternal(); + } + + public RoleInfo GetRoleInfo() + { + return _selectedRole; + } + + public void SelectRoleAsync(RoleInfo role, Action callback) + { + _selectedRole = role; + _selectRoleCallback = callback; + SetCharacterID(role.roleid); + SendProtocol(new selectrole() + { + Roleid = role.roleid, + Flag = 0 + }); + } + + public void CreateRoleAsync(RoleInfo roleInfo, Octets referId, Action callback) + { + if (!IsConnected) + { + callback?.Invoke(null); + return; + } + + if (_currentUserId == -1) + { + callback?.Invoke(null); + return; + } + + if (_createRoleCallback != null) + { + callback?.Invoke(null); + return; + } + + _createRoleCallback = callback; + + createrole createRoleProtocol = new createrole() + { + Userid = _currentUserId, + Localsid = _localsid, + Roleinfo = roleInfo, + Referid = referId ?? new Octets() + }; + + Debug.Log($"[GameSession] Creating role - UserID: {_currentUserId}, Localsid: {_localsid}, Profession: {roleInfo.occupation}, Gender: {roleInfo.gender}"); + Debug.Log($"[GameSession] RoleInfo details - Name size: {roleInfo.name?.Size ?? 0}, Equipment count: {roleInfo.equipment?.Count ?? 0}, Custom data size: {roleInfo.custom_data?.Size ?? 0}, Race: {roleInfo.race}"); + + // Log first few bytes of custom_data for debugging + if (roleInfo.custom_data != null && roleInfo.custom_data.Size > 0) + { + byte[] customDataPreview = new byte[Math.Min(16, (int)roleInfo.custom_data.Size)]; + Array.Copy(roleInfo.custom_data.ByteArray, 0, customDataPreview, 0, customDataPreview.Length); + string hexPreview = BitConverter.ToString(customDataPreview).Replace("-", " "); + Debug.Log($"[GameSession] Custom_data preview (first 16 bytes): {hexPreview}"); + } + + Debug.Log($"[GameSession] Sending createrole protocol (Type: {createRoleProtocol.Type})"); + SendProtocol(createRoleProtocol); + } + + /// + /// Helper method to create a new RoleInfo for character creation. + /// Matches C++ NewCharacterImpl behavior. + /// + public static RoleInfo CreateNewRoleInfo(string name, int profession, int gender) + { + RoleInfo roleInfo = new RoleInfo(); + + // Set basic info + roleInfo.occupation = (byte)profession; + roleInfo.gender = (byte)gender; + roleInfo.level = 1; + roleInfo.level2 = 0; + roleInfo.status = 0; // _ROLE_STATUS_NORMAL + roleInfo.delete_time = 0; + roleInfo.create_time = 0; // Server will set this + roleInfo.lastlogin_time = 0; + roleInfo.posx = 0.0f; + roleInfo.posy = 0.0f; + roleInfo.posz = 0.0f; + roleInfo.worldtag = 0; // Server will set this + roleInfo.referrer_role = 0; + roleInfo.cash_add = 0; + + // Set name - C++ uses Unicode encoding (ACHAR = wchar_t) + if (!string.IsNullOrEmpty(name)) + { + byte[] nameBytes = Encoding.Unicode.GetBytes(name); + roleInfo.name = new Octets(nameBytes); + } + else + { + roleInfo.name = new Octets(); + } + + // Initialize equipment list with 29 empty items (IVTRSIZE_EQUIPPACK = 29) + roleInfo.equipment = new List(); + for (int i = 0; i < 29; i++) + { + // Important: GRoleInventory.data must be non-null or Marshal() will fail and the packet won't send. + roleInfo.equipment.Add(new GRoleInventory + { + id = 0, + pos = i, + count = 0, + max_count = 0, + data = new Octets(), + proctype = 0, + expire_date = 0, + guid1 = 0, + guid2 = 0, + mask = 0 + }); + } + + // Initialize custom data exactly as C++ does: memset to 0, then set specific values + // This matches C++ LoadDefaultCustomizeData behavior + roleInfo.custom_data = CreateDefaultCustomizeData(profession, gender); + + // Initialize other empty custom data fields + roleInfo.custom_status = new Octets(); + roleInfo.charactermode = new Octets(); + roleInfo.reincarnation_data = new Octets(); + roleInfo.realm_data = new Octets(); + + // Race is typically determined by profession, but we'll leave it at 0 for now + // Server may set it based on profession + roleInfo.race = 0; + + return roleInfo; + } + + /// + /// Creates default customize data exactly matching C++ LoadDefaultCustomizeData behavior. + /// Structure layout - trying multiple sizes due to potential padding: + /// - DWORD dwVersion (offset 0-3, 4 bytes) = 0x10007001 + /// - FACE_CUSTOMIZEDATA faceData (offset 4-87, 84 bytes) = all zeros + /// - unsigned short bodyID (offset 88-89, 2 bytes) = 0 + /// - A3DCOLOR colorBody (offset 90-93, 4 bytes) = 0xffffffff + /// - 6 unsigned char scales (offset 94-99, 6 bytes) = all 128 + /// Note: C++ sizeof might include padding, trying 100, 104, 108 bytes + /// + private static Octets CreateDefaultCustomizeData(int profession, int gender) + { + // C++ sizeof(PLAYER_CUSTOMIZEDATA) - Based on server response, it expects 176 bytes + // The C++ code sends: sizeof(CECPlayer::PLAYER_CUSTOMIZEDATA) which appears to be 176 bytes + // Server response shows: custom_data size=176, so server expects/receives 176 bytes + // Structure layout (176 bytes total): + // - DWORD dwVersion (4 bytes, offset 0) = 0x10007001 + // - FACE_CUSTOMIZEDATA faceData (84 bytes, offset 4) = all zeros for now + // - unsigned short bodyID (2 bytes, offset 88) = 0 + // - A3DCOLOR colorBody (4 bytes, offset 90) = 0xffffffff + // - 6 unsigned char scales (6 bytes, offset 94) = all 128 + // - Padding/additional fields (76 bytes, offset 100-175) = all zeros + const int CUSTOMIZE_DATA_SIZE = 176; // Match server expectation (176 bytes from response) + const uint CUSTOMIZE_DATA_VERSION = 0x10007001; // CUSTOMIZE_DATA_VERSION from C++ + byte[] customDataBytes = new byte[CUSTOMIZE_DATA_SIZE]; + + // Step 1: memset to 0 (already done by new byte[]) + + // Step 2: Set dwVersion at offset 0-3 (little-endian) + byte[] versionBytes = BitConverter.GetBytes(CUSTOMIZE_DATA_VERSION); + Array.Copy(versionBytes, 0, customDataBytes, 0, 4); + + // Step 3: FACE_CUSTOMIZEDATA at offset 4-87 is already zero (84 bytes) + // (In C++ this would be loaded from INI, but for now we use zeros) + + // Step 4: bodyID at offset 88-89 is already zero (2 bytes) + // Note: There might be 2 bytes padding here if struct is 4-byte aligned + + // Step 5: Set colorBody to 0xffffffff + // Try offset 90 first (no padding), if that doesn't work try 92 (with padding) + byte[] colorBodyBytes = BitConverter.GetBytes(0xffffffffu); + Array.Copy(colorBodyBytes, 0, customDataBytes, 90, 4); // Try 90 first + + // Step 6: Set all 6 scale fields to 128 + // Try offset 94 first (no padding), if that doesn't work try 96 (with padding) + for (int i = 94; i < 100; i++) + { + customDataBytes[i] = 128; + } + + return new Octets(customDataBytes); + } + + public void EnterWorldAsync(RoleInfo role, Action callback) + { + SendProtocol(new enterworld() + { + Roleid = _selectedRole.roleid, + Provider_link_id = 0, + }, callback); + } + + public void RequestDropIvtrItem(byte index, int amount) + { + gamedatasend gamedatasendRequest = new gamedatasend(); + gamedatasendRequest.Data = C2SCommandFactory.CreateDropIvtrItem(index, amount); + SendProtocol(gamedatasendRequest); + } + + public void RequestDropEquipItem(byte index) + { + gamedatasend gamedatasendRequest = new gamedatasend(); + gamedatasendRequest.Data = C2SCommandFactory.CreateDropEquipItem(index); + SendProtocol(gamedatasendRequest); + } + + public void RequestPickupItem(int idItem, int tid) + { + gamedatasend gamedatasendRequest = new gamedatasend(); + gamedatasendRequest.Data = C2SCommandFactory.CreatePickupItem(idItem, tid); + SendProtocol(gamedatasendRequest); + } + + public void c2s_SendCmdGetIvtrDetailData(byte byPackage, Action callback) + { + gamedatasend gamedatasendRequest = new gamedatasend(); + gamedatasendRequest.Data = CSNetwork.C2SCommand.C2SCommandFactory.c2s_SendCmdGetIvtrDetailData(byPackage); + SendProtocol(gamedatasendRequest, callback); + } + + public void c2s_SendCmdQueryCashInfo() + { + gamedatasend gamedatasendRequest = new gamedatasend(); + gamedatasendRequest.Data = C2SCommandFactory.c2s_SendCmdQueryCashInfo(); + SendProtocol(gamedatasendRequest); + } + + public void c2s_SendCmdOpenFashionTrash(string password) + { + gamedatasend gamedatasendRequest = new gamedatasend(); + gamedatasendRequest.Data = C2SCommandFactory.c2s_SendCmdOpenFashionTrash(password); + SendProtocol(gamedatasendRequest); + } + + public void c2s_SendCmdEquipItem(byte iIvtrIdx, byte iEquipIdx, Action callback) + { + gamedatasend gamedatasendRequest = new gamedatasend(); + gamedatasendRequest.Data = CSNetwork.C2SCommand.C2SCommandFactory.c2s_SendCmdEquipItem(iIvtrIdx, iEquipIdx); + SendProtocol(gamedatasendRequest, callback); + } + + public void c2s_SendCmdReviveVillage(int param = 0) + { + gamedatasend gamedatasendRequest = new gamedatasend(); + gamedatasendRequest.Data = C2SCommandFactory.c2s_SendCmdReviveVillage(param); + SendProtocol(gamedatasendRequest); + } + public void c2s_SendCmdReviveItem(int param = 0) + { + gamedatasend gamedatasendRequest = new gamedatasend(); + gamedatasendRequest.Data = C2SCommandFactory.c2s_SendCmdReviveVillage(param); + SendProtocol(gamedatasendRequest); + } + public void RequestReviveByPlayer(int param = 0) + { + gamedatasend gamedatasendRequest = new gamedatasend(); + gamedatasendRequest.Data = C2SCommandFactory.c2s_SendCmdReviveVillage(param); + SendProtocol(gamedatasendRequest); + } + + + public void c2s_SendCmdMallShopping(uint count, CMD_MallShopping.goods[] goodsArray) + { + gamedatasend gamedatasendRequest = new gamedatasend(); + gamedatasendRequest.Data = CSNetwork.C2SCommand.C2SCommandFactory.CreateGetMallShopping(count, goodsArray); + SendProtocol(gamedatasendRequest); + } + public void c2s_SendCmdGatherMaterial(int idMatter, int iToolPack, int idToolIndex, int idTool, int idTask) + { + gamedatasend gamedatasendRequest = new gamedatasend(); + gamedatasendRequest.Data = CSNetwork.C2SCommand.C2SCommandFactory.c2s_SendCmdGatherMaterial(idMatter, iToolPack, idToolIndex, idTool, idTask); + SendProtocol(gamedatasendRequest); + } + + public void RequestOwnItemInfoAsync( + byte byPackage, + byte bySlot, + int type, + int expire_date, + int state, + uint count, + ushort crc, + ushort content_length, + byte[] content, + Action callback) + { + gamedatasend gamedatasendRequest = new gamedatasend(); + gamedatasendRequest.Data = C2SCommandFactory.CreateOwnItemInfo(byPackage, bySlot, type, expire_date, state, + count, crc, content_length, content); + SendProtocol(gamedatasendRequest, callback); + } + + // --- Protocol Sending --- + public void SendProtocol(Protocol protocol, Action complete = null) + { + if (IsConnected) + { + _logger.Log(LogType.Debug, + $"Sending protocol: {protocol.GetType().Name} (Detail: {protocol.ToString})"); + Debug.Log($"[GameSession] Sending protocol: {protocol.GetType().Name} (Type: {protocol.GetPType()})"); + _networkManager.Send(protocol); + complete?.Invoke(); + } + else + { + _logger.Log(LogType.Warning, $"Cannot send protocol ({protocol.GetType().Name}), not connected."); + Debug.LogError($"[GameSession] Cannot send protocol ({protocol.GetType().Name}), not connected."); + } + } + + // --- Event Handlers (from NetworkManager) --- + + private void OnProtocolReceived(Protocol protocol) + { + _logger.Log(LogType.Debug, $"Received protocol: {protocol.GetType().Name} (Type: {protocol.Type})"); + if (protocol is null) + return; + + + // Route protocol to appropriate handler + switch (protocol.GetPType()) + { + case ProtocolType.PROTOCOL_CHALLENGE: + HandleChallenge((challenge)protocol); + break; + case ProtocolType.PROTOCOL_KEYEXCHANGE: + HandleKeyExchange((KeyExchange)protocol); + break; + case ProtocolType.PROTOCOL_ONLINEANNOUNCE: + HandleOnlineAnnounce((onlineannounce)protocol); + break; + case ProtocolType.PROTOCOL_ROLELIST_RE: + HandleRoleListResponse((RoleListResponse)protocol); + break; + // Add cases for other protocols GameSession might need to handle + case ProtocolType.PROTOCOL_SELECTROLE_RE: + HandleSelectRoleResponse((SelectRole_Re)protocol); + //_networkManager.IgnoreBytes = 2; + break; + case ProtocolType.PROTOCOL_CREATEROLE_RE: + HandleCreateRoleResponse((createrole_re)protocol); + break; + case ProtocolType.PROTOCOL_ERRORINFO: + HandleErrorInfo((errorinfo)protocol); + break; + case ProtocolType.PROTOCOL_S2CGAMEDATASEND: + case ProtocolType.PROTOCOL_GAMEDATASEND: + HandleServerDataSend((gamedatasend)protocol); + break; + case ProtocolType.PROTOCOL_CHATMESSAGE: + _logger.Log(LogType.Warning, $"HoangDev :ProtocolType.PROTOCOL_CHATMESSAGE {protocol.GetPType()}"); + OnPrtcChatMessage(protocol, false); + break; + case ProtocolType.PROTOCOL_PLAYERBASEINFO_RE: + OnPrtcPlayerBaseInfoRe(protocol); + break; + case ProtocolType.PROTOCOL_GETUICONFIG_RE: OnPrtcGetConfigRe(protocol); break; + + case ProtocolType.PROTOCOL_AUTOTEAMSETGOAL_RE: + { + // CECAutoTeam pAutoTeam = CECGameRun.Instance.GetHostPlayer().GetAutoTeam(); + // if( pAutoTeam !=null) + // pAutoTeam.OnPrtcAutoTeamSetGoalRe((AutoTeamSetGoal_Re)protocol); + } + break; + + default: + _logger.Log(LogType.Warning, $"Received unhandled protocol type: {protocol.GetPType()}"); + break; + } + } + + private void HandleServerDataSend(gamedatasend protocol) + { + int lenghtHeader = Marshal.SizeOf(); + var pDataBuf = new byte[protocol.Data.ByteArray.Length - lenghtHeader]; + var byteArrHeader = new byte[lenghtHeader]; + long dwDataSize = protocol.Data.Size; + + if (dwDataSize < Marshal.SizeOf()) + { + _logger.Error($"### GameDataSend: size invalid {dwDataSize}"); + return; + } + + dwDataSize -= Marshal.SizeOf(); // subtract the header size (ushort) + for (int i = 0; i < protocol.Data.ByteArray.Length; i++) + { + if (i < lenghtHeader) + { + byteArrHeader[i] = protocol.Data.ByteArray[i]; + } + else + { + pDataBuf[i - lenghtHeader] = protocol.Data.ByteArray[i]; + } + } + + var pCmdHeader = BitConverter.ToUInt16(byteArrHeader); + //sss +#if UNITY_EDITOR + if (isDebug) + { + BMLogger.LogError($"### GameDataSend: CMDID {pCmdHeader}"); + } +#endif + int iHostID = _selectedRole.roleid; + switch (pCmdHeader) + { + case CommandID.PLAYER_INFO_2: + case CommandID.PLAYER_INFO_3: + case CommandID.PLAYER_INFO_4: + case CommandID.PLAYER_INFO_2_LIST: + case CommandID.PLAYER_INFO_3_LIST: + case CommandID.PLAYER_INFO_23_LIST: + + break; + + case CommandID.PLAYER_INFO_1: + case CommandID.PLAYER_ENTER_WORLD: + case CommandID.PLAYER_ENTER_SLICE: + case CommandID.PLAYER_INFO_1_LIST: + case CommandID.PLAYER_INFO_00: + case CommandID.SELF_INFO_1: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERINFO, (int)MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, + pCmdHeader, iHostID); + break; + case CommandID.OBJECT_MOVE: + int lenghtDataType = Marshal.SizeOf(); + byte[] arrByteData = GetBytes(pDataBuf, lenghtDataType, 0); + int idObjMove = BitConverter.ToInt32(arrByteData); + if (ISPLAYERID(idObjMove)) + { + EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERMOVE, (int)MANAGER_INDEX.MAN_PLAYER, -1, + pDataBuf, pCmdHeader, iHostID); + } + else if (ISNPCID(idObjMove)) + { + EC_ManMessage.PostMessage(EC_MsgDef.MSG_NM_NPCMOVE, (int)MANAGER_INDEX.MAN_NPC, 0, pDataBuf, + pCmdHeader); + } + + break; + case CommandID.OBJECT_STOP_MOVE: + { + int id1 = GPDataTypeHelper.FromBytes(pDataBuf); + + if (ISPLAYERID(id1)) + { + EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERSTOPMOVE, (int)MANAGER_INDEX.MAN_PLAYER, -1, + pDataBuf, pCmdHeader); + } + else if (ISNPCID(id1)) + { + EC_ManMessage.PostMessage(EC_MsgDef.MSG_NM_NPCSTOPMOVE, (int)MANAGER_INDEX.MAN_NPC, 0, pDataBuf, + pCmdHeader); + } + + break; + } + case CommandID.OBJECT_LEAVE_SLICE: + { + int id = GPDataTypeHelper.FromBytes(pDataBuf); + if (ISPLAYERID(id)) + { + EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERRUNOUT, (int)MANAGER_INDEX.MAN_PLAYER, -1, + pDataBuf, pCmdHeader); + } + else if (ISNPCID(id)) + { + EC_ManMessage.PostMessage(EC_MsgDef.MSG_NM_NPCRUNOUT, (int)MANAGER_INDEX.MAN_NPC, 0, pDataBuf, + pCmdHeader); + } + + break; + } + case CommandID.OWN_IVTR_DATA: + case CommandID.OWN_IVTR_DETAIL_DATA: + case CommandID.GET_OWN_MONEY: + case CommandID.CHANGE_IVTR_SIZE: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_IVTRINFO, (int)MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, + pCmdHeader, iHostID); + break; + case CommandID.EXG_IVTR_ITEM: + case CommandID.MOVE_IVTR_ITEM: + case CommandID.PLAYER_DROP_ITEM: + case CommandID.EXG_EQUIP_ITEM: + case CommandID.EQUIP_ITEM: + case CommandID.MOVE_EQUIP_ITEM: + case CommandID.UNFREEZE_IVTR_SLOT: + case CommandID.PLAYER_EQUIP_TRASHBOX_ITEM: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_ITEMOPERATION, (int)MANAGER_INDEX.MAN_PLAYER, 0, + pDataBuf, pCmdHeader); + break; + case CommandID.PLAYER_CASH: + { + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_IVTRINFO, (int)MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, + pCmdHeader, iHostID); + break; + } + case CommandID.MATTER_INFO_LIST: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_MM_MATTERINFO, (int)MANAGER_INDEX.MAN_MATTER, 0, pDataBuf, + pCmdHeader); + break; + case CommandID.MATTER_ENTER_WORLD: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_MM_MATTERENTWORLD, (int)MANAGER_INDEX.MAN_MATTER, 0, + pDataBuf, pCmdHeader); + break; + case CommandID.PICKUP_ITEM: + case CommandID.HOST_OBTAIN_ITEM: + case CommandID.PRODUCE_ONCE: + case CommandID.TASK_DELIVER_ITEM: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_PICKUPITEM, (int)MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, + pCmdHeader); + break; + case CommandID.MATTER_PICKUP: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PICKUPMATTER, (int)MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader); + break; + case CommandID.PICKUP_MONEY: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_PICKUPMONEY, (int)MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, + pCmdHeader); + break; + case CommandID.HOST_CORRECT_POS: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_CORRECTPOS, (int)MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, + pCmdHeader, iHostID); + break; + case CommandID.OWN_ITEM_INFO: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_OWNITEMINFO, (int)MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, + pCmdHeader, iHostID); + break; + case CommandID.PLAYER_DIED: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERDIED, (int)MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader); + break; + case CommandID.HOST_DIED: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_DIED, (int)MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); + break; + case CommandID.PLAYER_REVIVE: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERREVIVE, (int)MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader); + break; + case CommandID.NOTIFY_HOSTPOS: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_GOTO, (int)MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); + break; + case CommandID.NPC_ENTER_SLICE: + case CommandID.NPC_INFO_LIST: + case CommandID.NPC_INFO_00: + case CommandID.NPC_ENTER_WORLD: + case CommandID.NPC_VISIBLE_TID_NOTIFY: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_NM_NPCINFO, (int)MANAGER_INDEX.MAN_NPC, 0, pDataBuf, + pCmdHeader, dwDataSize); + break; + case CommandID.TASK_DATA: + case CommandID.TASK_VAR_DATA: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_TASKDATA, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, + pCmdHeader, dwDataSize); + break; + case CommandID.BE_HURT: + case CommandID.HURT_RESULT: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_HURTRESULT, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, + pCmdHeader); + break; + case CommandID.OBJECT_ATTACK_RESULT: + //int id = GPDataTypeHelper.FromBytes(pDataBuf); + cmd_object_atk_result pCmdAtk = GPDataTypeHelper.FromBytes(pDataBuf); + //BMLogger.LogError($"OBJECT_ATTACK_RESULT: npc ? " + ISNPCID(id)); + + if (ISPLAYERID(pCmdAtk.attacker_id)) + EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERATKRESULT, MANAGER_INDEX.MAN_PLAYER, -1, + pDataBuf, pCmdHeader); + else if (ISNPCID(pCmdAtk.attacker_id)) + EC_ManMessage.PostMessage(EC_MsgDef.MSG_NM_NPCATKRESULT, MANAGER_INDEX.MAN_NPC, 0, pDataBuf, pCmdHeader); + break; + case CommandID.HOST_ATTACKRESULT: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_ATKRESULT, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, + pCmdHeader); + break; + case CommandID.HOST_ATTACKED: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_ATTACKED, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, + pCmdHeader); + break; + + case CommandID.ERROR_MESSAGE: + { + int errRaw = BitConverter.ToInt32(pDataBuf, 0); + // Note: _logger may be configured as a file logger via SetLogPath(), so also log to console for visibility. + _logger.Info($"### GameDataSend: ERROR_MESSAGE: {errRaw}"); +#if UNITY_EDITOR + BMLogger.LogError($"### GameDataSend: ERROR_MESSAGE: {errRaw}"); +#endif + cmd_error_msg pCmd = GPDataTypeHelper.FromBytes(pDataBuf); +#if UNITY_EDITOR + BMLogger.LogError($"### GameDataSend: ERROR_MESSAGE parsed iMessage={pCmd.iMessage}"); +#endif + + if (pCmd.iMessage != 0) + { + // string szMsg = m_ErrorMsgs.GetWideString(pCmd.iMessage); + // if (string.IsNullOrEmpty(szMsg)) + // BMLogger.LogError("SERVER - unknown error !"); + //else if (pCmd.iMessage != 2) + //g_pGame.GetGameRun().AddChatMessage(szMsg, GP_CHAT_MISC); + } + + if (pCmd.iMessage == 2) + { + // Attack target is too far + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_TARGETISFAR, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); + } + else if (pCmd.iMessage == 20) + { + // Failed to cast skill + //pGameRun.PostMessage(MSG_PM_CASTSKILL, MAN_PLAYER, 0, (DWORD)pDataBuf, pCmdHeader.cmd); + } + else if (pCmd.iMessage == 133 || pCmd.iMessage == 134) + { + // deal failed + //pGameRun.PostMessage(MSG_HST_BUY_SELL_FAIL, MAN_PLAYER, 0, (DWORD)pDataBuf, pCmdHeader.cmd); + } + else if (pCmd.iMessage == 158) + { + // µ±Ç°»ãÂʲ»¶Ô£¬ÖØÐÂÈ¡»ãÂÊ + //c2s_CmdGetCashMoneyRate(); + } + else if (pCmd.iMessage == 108 /*&& pGameRun.GetHostPlayer().IsInKingService()*/) + { + /* CECGameUIMan* pGameUI = pGameRun.GetUIManager().GetInGameUIMan(); + if (pGameUI) + pGameUI.EndNPCService();*/ + } + else if + (pCmd.iMessage == 108 /*&& pGameRun.GetHostPlayer().GetOfflineShopCtrl().GetNPCSevFlag() != COfflineShopCtrl::NPCSEV_NULL*/ + ) + { + /* CECGameUIMan* pGameUI = pGameRun.GetUIManager().GetInGameUIMan(); + if (pGameUI) + pGameUI.EndNPCService();*/ + } + else if (pCmd.iMessage == 175) + { + //c2s_CmdQueryParallelWorld(); + } + else if (pCmd.iMessage == 6) + { + //AP_ActionEvent(AP_EVENT_CANNOTPICKUP); + } + + break; + } + case CommandID.SELECT_TARGET: + case CommandID.UNSELECT: + + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_SELTARGET, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, + pCmdHeader); + break; + case CommandID.NPC_DIED: + case CommandID.NPC_DIED2: + + EC_ManMessage.PostMessage(EC_MsgDef.MSG_NM_NPCDIED, MANAGER_INDEX.MAN_NPC, 0, pDataBuf, pCmdHeader); + break; + case CommandID.OBJECT_DISAPPEAR: + { + int lenghtDataType1 = Marshal.SizeOf(); + byte[] arrByteData1 = GetBytes(pDataBuf, lenghtDataType1, 0); + int objectId = BitConverter.ToInt32(arrByteData1); + if (ISPLAYERID(objectId)) + EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERDISAPPEAR, MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader); + else if (ISNPCID(objectId)) + EC_ManMessage.PostMessage(EC_MsgDef.MSG_NM_NPCDISAPPEAR, MANAGER_INDEX.MAN_NPC, 0, pDataBuf, pCmdHeader); + else if (ISMATTERID(objectId)) + EC_ManMessage.PostMessage(EC_MsgDef.MSG_MM_MATTERDISAPPEAR, MANAGER_INDEX.MAN_MATTER, 0, pDataBuf, pCmdHeader); + + break; + } + case CommandID.SELF_INFO_00: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_INFO00, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, + pCmdHeader); + break; + case CommandID.NPC_GREETING: + { + // If this greeting is from the skill-learn NPC, record it (C++ skill dialog relies on this). + try + { + cmd_npc_greeting greet = GPDataTypeHelper.FromBytes(pDataBuf); + CECHostSkillModel.Instance.OnNpcGreeting(greet.idObject); + } + catch (Exception ex) + { + _logger.Log(LogType.Warning, $"Failed to parse NPC_GREETING payload: {ex.Message}"); + } + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_NPCGREETING, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); + break; + } + case CommandID.ACTIVATE_WAYPOINT: + case CommandID.WAYPOINT_LIST: + + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_WAYPOINT, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); + break; + case CommandID.SERVER_TIME: + { + cmd_server_time pcmd_server_time = GPDataTypeHelper.FromBytes(pDataBuf); + EC_ManMessage.PostMessage(EC_MsgDef.MSG_SERVERTIME, -1, 0, pcmd_server_time.time, pcmd_server_time.timebias); + break; + } + case CommandID.SCENE_SERVICE_NPC_LIST: + { + CECHostSkillModel.Instance.RecvNPCServiceList(protocol.Data); + break; + } + case CommandID.SKILL_DATA: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_SKILLDATA, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); + break; + case CommandID.OBJECT_CAST_SKILL: + case CommandID.OBJECT_CAST_INSTANT_SKILL: + case CommandID.OBJECT_CAST_POS_SKILL: + { + cmd_object_cast_skill pCmd2 = GPDataTypeHelper.FromBytes(pDataBuf,true); + if (ISPLAYERID(pCmd2.caster)) + EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_CASTSKILL, MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader); + else if (ISNPCID(pCmd2.caster)) + EC_ManMessage.PostMessage(EC_MsgDef.MSG_NM_NPCCASTSKILL, MANAGER_INDEX.MAN_NPC, 0, pDataBuf, pCmdHeader); + + break; + } + case CommandID.LEVEL_UP: + { + cmd_level_up pCmdLevelUp = GPDataTypeHelper.FromBytes(pDataBuf); ; + if (ISPLAYERID(pCmdLevelUp.id)) + EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERLEVELUP, MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader); + else if (ISNPCID(pCmdLevelUp.id)) + EC_ManMessage.PostMessage(EC_MsgDef.MSG_NM_NPCLEVELUP, MANAGER_INDEX.MAN_NPC, 0, pDataBuf, pCmdHeader); + break; + } + case CommandID.HOST_START_ATTACK: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_STARTATTACK, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader, dwDataSize); + break; + case CommandID.HOST_STOPATTACK: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_STOPATTACK, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader, dwDataSize); + break; + case CommandID.HOST_SKILL_ATTACK_RESULT: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_SKILLRESULT, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); + break; + case CommandID.CHANGE_FACE_START: + case CommandID.CHANGE_FACE_END: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_CHANGEFACE, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader, dwDataSize); + break; + case CommandID.ENCHANT_RESULT: + cmd_enchant_result pCmd3 = GPDataTypeHelper.FromBytes(pDataBuf); + if (ISPLAYERID(pCmd3.caster)) + EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_ENCHANTRESULT, MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader); + else if (ISNPCID(pCmd3.caster)) + EC_ManMessage.PostMessage(EC_MsgDef.MSG_NM_ENCHANTRESULT, MANAGER_INDEX.MAN_NPC, 0, pDataBuf, pCmdHeader); + break; + case CommandID.SKILL_PERFORM: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_CASTSKILL, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); + break; + case CommandID.SET_COOLDOWN: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_SETCOOLTIME, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); + break; + case CommandID.COMBO_SKILL_PREPARE: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_COMBO_SKILL_PREPARE, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader, dwDataSize); + break; + case CommandID.PLAYER_EXT_PROP_BASE: + case CommandID.PLAYER_EXT_PROP_MOVE: + case CommandID.PLAYER_EXT_PROP_ATK: + case CommandID.PLAYER_EXT_PROP_DEF: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYEREXTPROP, MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader); + break; + case CommandID.OWN_EXT_PROP: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_OWNEXTPROP, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); + break; + case CommandID.OBJECT_DO_EMOTE: + case CommandID.OBJECT_EMOTE_RESTORE: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERDOEMOTE, MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader); + break; + case CommandID.OUT_OF_SIGHT_LIST: + { + cmd_out_of_sight_list pCmd5 = default; + pCmd5.uCount = GPDataTypeHelper.FromBytes(pDataBuf); + int offset2 = sizeof(uint); + pCmd5.idList = new int[pCmd5.uCount]; + for (int i = 0; i < pCmd5.uCount; i++) + { + pCmd5.idList[i] = GPDataTypeHelper.FromBytes(pDataBuf, offset2); + offset2 += 4;//sizeof int; + } + + for (uint n = 0; n < pCmd5.uCount; n++) + { + if (ISPLAYERID(pCmd5.idList[n])) + EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYEROUTOFVIEW, MANAGER_INDEX.MAN_PLAYER, -1, pCmd5.idList[n], pCmdHeader); + else if (ISNPCID(pCmd5.idList[n])) + EC_ManMessage.PostMessage(EC_MsgDef.MSG_NM_NPCOUTOFVIEW, MANAGER_INDEX.MAN_NPC, 0, pCmd5.idList[n], pCmdHeader); + else if (ISMATTERID(pCmd5.idList[n])) + EC_ManMessage.PostMessage(EC_MsgDef.MSG_MM_MATTEROUTOFVIEW, MANAGER_INDEX.MAN_MATTER, 0, pCmd5.idList[n], pCmdHeader); + } + + break; + } + case CommandID.PLAYER_GATHER_START: + case CommandID.PLAYER_GATHER_STOP: + case CommandID.MINE_GATHERED: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERGATHER, MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader); + break; + case CommandID.COOLTIME_DATA: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_COOLTIMEDATA, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); + break; + case CommandID.OBJECT_TAKEOFF: + { + cmd_object_takeoff pCmdTakeOff = GPDataTypeHelper.FromBytes((byte[])pDataBuf); + if (ISPLAYERID(pCmdTakeOff.object_id)) + EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERFLY, MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader); + break; + } + case CommandID.OBJECT_LANDING: + { + cmd_object_landing pCmdLanding = GPDataTypeHelper.FromBytes((byte[])pDataBuf); + if (ISPLAYERID(pCmdLanding.object_id)) + EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERFLY, MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader); + break; + } + case CommandID.HOST_RUSH_FLY: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERFLY, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); + break; + case CommandID.FLYSWORD_TIME: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_FLYSWORDTIME, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); + break; + case CommandID.PRODUCE_START: + case CommandID.PRODUCE_END: + case CommandID.PRODUCE_NULL: + // Post MSG_HST_PRODUCEITEM message with command ID as parameter (matches C++ behavior) + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_PRODUCEITEM, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); + break; + + + case CommandID.LEARN_SKILL: + BMLogger.LogError("### GameDataSend: LEARN_SKILL"); + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_LEARNSKILL, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); + break; + case CommandID.EMBED_ITEM: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_EMBEDITEM, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); + break; + default: +#if UNITY_EDITOR + if (isDebug) + { + BMLogger.LogError($"### GameDataSend: Unhandled CMDID {pCmdHeader} (payloadBytes={pDataBuf?.Length ?? 0})"); + } +#endif + break; + } + } + + + private void HandleSelectRoleResponse(SelectRole_Re protocol) + { + _logger.Info($"Select role response {protocol.result}"); + var callback = _selectRoleCallback; + PostToUnityContext(() => callback?.Invoke(_selectedRole)); + } + + private void HandleCreateRoleResponse(createrole_re protocol) + { + Debug.Log($"[GameSession] HandleCreateRoleResponse - result: {protocol.result}, roleid: {protocol.roleid}"); + + if (protocol.result != (int)ErrCode.ERR_SUCCESS) + { + string errorMsg = $"Create role failed with result code: {protocol.result} (ERR_SUCCESS = {(int)ErrCode.ERR_SUCCESS})"; + _logger.Log(LogType.Error, errorMsg); + Debug.LogError($"[GameSession] {errorMsg}"); + var callback = _createRoleCallback; + _createRoleCallback = null; + PostToUnityContext(() => callback?.Invoke(null)); + return; + } + + Debug.Log($"[GameSession] Create role successful! RoleID: {protocol.roleid}"); + var successCallback = _createRoleCallback; + _createRoleCallback = null; + PostToUnityContext(() => successCallback?.Invoke(protocol.roleinfo)); + } + + private void HandleErrorInfo(errorinfo protocol) + { + Debug.LogError($"[GameSession] Server error - Errcode: {protocol.Errcode}"); + + // If we're waiting for create role response and get an error, fail the callback + if (_createRoleCallback != null) + { + Debug.LogError($"[GameSession] Create role failed due to server error: {protocol.Errcode}"); + var callback = _createRoleCallback; + _createRoleCallback = null; + PostToUnityContext(() => callback?.Invoke(null)); + } + } + + private void OnErrorOccurred(string errorMessage) + { + _logger.Log(LogType.Error, $"Network Error: {errorMessage}"); + FailLoginInProgress(errorMessage); + FailRoleListInProgress(errorMessage); + } + + private void OnDisconnected() + { + _logger.Log(LogType.Info, "Disconnected from server."); + _currentUserId = -1; + FailLoginInProgress("Disconnected"); + FailRoleListInProgress("Disconnected"); + // Clear command cache + m_CmdCache.RemoveAllCmds(); + } + + // --- Protocol Handling Logic --- + + private void HandleChallenge(challenge challenge) + { + if (_loginCallback == null || string.IsNullOrEmpty(_username)) + { + _logger.Log(LogType.Warning, "Received Challenge but not expecting it or username not set."); + return; + } + + _logger.Log(LogType.Info, "Handling Challenge..."); + + response response = new response(); + byte[] usernameBytes = Encoding.ASCII.GetBytes(_username); + byte[] passwordBytes = Encoding.ASCII.GetBytes(_password); + response.identity.Replace(usernameBytes); + response.Setup(new Octets(usernameBytes), new Octets(passwordBytes), challenge.nonce); + + uint clientId = 0xffffffff; + byte[] clientIdBytes = BitConverter.GetBytes(clientId); + response.cli_fingerprint.Replace(clientIdBytes); + response.use_token = 0; + + _networkManager.SetNonce(response.response_data); + SendProtocol(response); + _logger.Log(LogType.Info, "Sent Response."); + } + + private void HandleKeyExchange(KeyExchange keyExchange) + { + if (_loginCallback == null || string.IsNullOrEmpty(_username)) + { + _logger.Log(LogType.Warning, "Received KeyExchange but not expecting it."); + return; + } + + _logger.Log(LogType.Info, "Handling KeyExchange..."); + keyExchange.Setup(_networkManager, _username); + keyExchange.Blkickuser = 1; + SendProtocol(keyExchange); + _logger.Log(LogType.Info, "Sent KeyExchange acknowledgment/response."); + } + + private void HandleOnlineAnnounce(onlineannounce announce) + { + if (_loginCallback == null) + { + _logger.Log(LogType.Warning, "Received OnlineAnnounce but not expecting it."); + return; + } + + _logger.Log(LogType.Info, $"Login successful! UserID: {announce.Userid}, LocalSID: {announce.Localsid}"); + _currentUserId = announce.Userid; + _localsid = announce.Localsid; + + var callback = _loginCallback; + _loginCallback = null; + callback?.Invoke(true); + } + + private void RequestRoleListInternal(int lastHandle = -1) + { + rolelist rolelistRequest = new rolelist(); + rolelistRequest.Userid = _currentUserId; + rolelistRequest.Localsid = 0; + rolelistRequest.Handle = lastHandle; + + SendProtocol(rolelistRequest); + + + //gamedatasend gamedatasendRequest = new gamedatasend(); + //gamedatasendRequest.Data = C2SCommandFactory.CreatePlayerMove(); + + //SendProtocol(gamedatasendRequest); + } + + private void HandleRoleListResponse(RoleListResponse response) + { + if (_roleListCallback == null || _accumulatedRoles == null) + { + _logger.Log(LogType.Warning, "Received RoleListResponse but not expecting it."); + return; + } + + _logger.Log(LogType.Debug, + $"Received RoleListResponse. Handle: {response.handle}, Result: {response.result}, Count: {response.rolelist.Count}"); + + if (response.result == 0) + { + _accumulatedRoles.AddRange(response.rolelist); + + foreach (var role in response.rolelist) + { + try + { + string roleName = Encoding.UTF8.GetString(role.name.ByteArray, 0, role.name.Length); + _logger.Log(LogType.Info, $" - Role ID: {role.roleid}, Name: {roleName}, Level: {role.level}"); + } + catch (Exception ex) + { + _logger.Log(LogType.Error, $" - Error decoding role name: {ex.Message}"); + _logger.LogException(ex); + } + } + + if (response.handle != -1) + { + _logger.Log(LogType.Debug, $"Requesting next batch of roles (handle: {response.handle})..."); + RequestRoleListInternal(response.handle); + } + else + { + _logger.Log(LogType.Info, $"Finished fetching roles. Total count: {_accumulatedRoles.Count}"); + var callback = _roleListCallback; + var result = _accumulatedRoles; + _roleListCallback = null; + _accumulatedRoles = null; + PostToUnityContext(() => callback?.Invoke(result)); + } + } + else + { + _logger.Log(LogType.Error, $"Role list retrieval failed. Result code: {response.result}"); + FailRoleListInProgress($"Role list retrieval failed (Result: {response.result})"); + } + } + + // --- Helper methods for failure handling --- + private void FailLoginInProgress(string reason) + { + if (_loginCallback != null) + { + _logger.Log(LogType.Error, $"Login failed: {reason}"); + var callback = _loginCallback; + _loginCallback = null; + PostToUnityContext(() => callback?.Invoke(false)); + } + } + + private void FailRoleListInProgress(string reason) + { + if (_roleListCallback != null) + { + _logger.Log(LogType.Error, $"Role list retrieval failed: {reason}"); + var callback = _roleListCallback; + _roleListCallback = null; + _accumulatedRoles = null; + PostToUnityContext(() => callback?.Invoke(null)); + } + } + + // --- IDisposable Implementation --- + private bool disposedValue = false; + + protected virtual void Dispose(bool disposing) + { + if (!disposedValue) + { + if (disposing) + { + if (_networkManager != null) + { + _logger.Log(LogType.Info, "[DUCK] Disposing GameSession and disconnecting..."); + _networkManager.ProtocolReceived -= OnProtocolReceived; + _networkManager.ErrorOccurred -= OnErrorOccurred; + _networkManager.Disconnected -= OnDisconnected; + _networkManager.Disconnect(); + _networkManager.Dispose(); + _networkManager = null; + } + + _loginCallback = null; + _roleListCallback = null; + _accumulatedRoles = null; + } + + disposedValue = true; + } + } + + public void Dispose() + { + Dispose(true); + // GC.SuppressFinalize(this); + } + + public bool ISPLAYERID(int id) + { + return id != 0 && (id & 0x80000000) == 0; + } + public bool ISNPCID(int id) => ((id & 0x80000000) != 0) && ((id & 0x40000000) == 0); + public bool ISMATTERID(int id) => ((id) & 0xC0000000) == 0xC0000000; + private byte[] GetBytes(byte[] bytes, int length, int index) + { + byte[] arrByteData = new byte[length]; + for (int i = 0; i < length; i++) + { + arrByteData[i] = bytes[i + index]; + } + + return arrByteData; + } + + public void c2s_CmdPlayerMove(in Vector3 vCurPos, in Vector3 vDest, + int iTime, float fSpeed, int iMoveMode, ushort wStamp) + { + gamedatasend gamedatasend = new gamedatasend(); + + gamedatasend.Data = + C2SCommandFactory.CreatePlayerMove(vCurPos, vDest, (ushort)iTime, fSpeed, (byte)iMoveMode, wStamp); + SendProtocol(gamedatasend); + } + public void c2s_SendCmdCastSkill(int idSkill, byte byPVPMask, int iNumTarget, int[] aTargets) + { + gamedatasend gamedatasend = new gamedatasend(); + + gamedatasend.Data = + C2SCommandFactory.CreatePlayerCastSkill(idSkill, byPVPMask, iNumTarget, aTargets); + + SendProtocol(gamedatasend); + } + + public void c2s_SendCmdCastInstantSkill(int idSkill, byte byPVPMask, int iNumTarget, int[] aTargets) + { + gamedatasend gamedatasend = new gamedatasend(); + + gamedatasend.Data = + C2SCommandFactory.CreatePlayerCastInstantSkill(idSkill, byPVPMask, iNumTarget, aTargets); + + SendProtocol(gamedatasend); + } + + public void c2s_CmdCastPosSkill(int idSkill, Vector3 vDest, byte byPVPMask, int iNumTarget, int aTargets) + { + gamedatasend gamedatasend = new gamedatasend(); + + gamedatasend.Data = + C2SCommandFactory.CreatePlayerCastPosSkill(idSkill, vDest, byPVPMask, iNumTarget, aTargets); + + SendProtocol(gamedatasend); + } + public void c2s_SendCmdContinueAction() + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateNakeCmd(C2SCommand.CommandID.CONTINUE_ACTION); + SendProtocol(gamedatasend); + } + public void c2s_SendCmdStopMove(in Vector3 vDest, float fSpeed, int iMoveMode, + byte byDir, ushort wStamp, int iTime) + { + gamedatasend gamedatasend = new gamedatasend(); + + gamedatasend.Data = + C2SCommandFactory.CreatePlayerStop(vDest, fSpeed, (byte)iMoveMode, byDir, wStamp, (ushort)iTime); + SendProtocol(gamedatasend); + } + + public void c2s_CmdSendEnterPKPrecinctint() + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateNakeCmd(C2SCommand.CommandID.ENTER_PK_PROTECTED); + SendProtocol(gamedatasend); + } + public void SendChatData(byte cChannel, in string szMsg, int iPack, int iSlot) + { + publicchat publicChat = new publicchat(); + publicChat.Channel = cChannel; + publicChat.Roleid = m_iCharID; + + byte[] unicodeBytes = Encoding.Unicode.GetBytes(szMsg); + publicChat.Msg.Replace(unicodeBytes); + _logger.Log(LogType.Warning, $"HoangDev : publicChat {publicChat}"); + SendProtocol(publicChat); + } + public void LoadConfigData() + { + getuiconfig p = new getuiconfig(); + p.Roleid = m_iCharID; + SendProtocol(p); + } + private void SetCharacterID(int iCharID) + { + m_iCharID = iCharID; + } + + private void OnPrtcChatMessage(Protocol pProtocol, bool bCalledagain) + { + chatmessage p = (chatmessage)pProtocol; + + string strTemp = System.Text.Encoding.Unicode.GetString(p.Msg.ToArray(), 0, p.Msg.Length); + + _logger.Log(LogType.Warning, $"HoangDev : OnPrtcChatMessage :{strTemp}"); + EventBus.Publish(new ChatMessageEvent(strTemp)); + } + + public struct ChatMessageEvent + { + public string context; + + public ChatMessageEvent(string context) + { + this.context = context; + } + } + public void OnPrtcGetConfigRe(Protocol pProtocol) + { + getuiconfig_re p = (getuiconfig_re)pProtocol; + if (p.Result != (int)ErrCode.ERR_SUCCESS) + BMLogger.LogError("CECGameSession::OnPrtcGetConfigRe, link return error code of " + p.Result); + else + { + if (!CECGameRun.Instance.LoadConfigsFromServer(p.UiConfig.RawBuffer, p.UiConfig.Size)) + { + // if load failed then use current setting directly + //TODO : fix later + EC_Game.GetConfigs().ApplyUserSetting(); + } + + // Now, Get config data request is sent after all host initial data ready. + // so when we receive this reply, we can do some last work before game + // really starts. Maybe it's not the best place to do these work, but + // now we do it here. + // Enalbe game UI + CECGameUIMan pGameUI = (CECGameUIMan)EC_Game.GetGameRun().GetUIManager().GetInGameUIMan(); + if (pGameUI != null) + { + pGameUI.EnableUI(true); + + // Get referral name for adding friend or other display + //TODO: a Hung lam phan select role info di + /* RoleInfo info = EC_Game.GetGameRun().GetSelectedRoleInfo(); + if (info.referrer_role > 0) + GetPlayerBriefInfo(1, info.referrer_role, 2);*/ + } + + CECHostPlayer pHost = EC_Game.GetGameRun().GetHostPlayer(); + pHost.OnAllInitDataReady(); + + /* if (pHost.IsGM()) + { + CDlgCountryMap pDlgCountryMap = (CDlgCountryMap)pGameUI.GetDialog("Win_CountryMap"); + pDlgCountryMap.GetConfig(); + } + + g_pGame.GetConfigs().ApplyOptimizeSetting(); + + if (g_pGame.GetConfigs().IsMiniClient()) + CECMCDownload::GetInstance().SendGetDownloadOK();*/ + } + } + private void OnPrtcPlayerBaseInfoRe(Protocol pProtocol) + { + playerbaseinfo_re p = (playerbaseinfo_re)pProtocol; + BMLogger.Log($"OnPrtcPlayerBaseInfoRe: {p.Roleid} {p.Player.cls} {p.Player.gender}"); + EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERBASEINFO, MANAGER_INDEX.MAN_PLAYER, -1, p); + } + + public void c2s_CmdNPCSevAcceptTask(int idTask, int idStorage, int idRefreshItem) + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateCmdNPCSevAcceptTask(idTask, idStorage, idRefreshItem); + SendProtocol(gamedatasend); + } + + public void c2s_SendCmdGetAllData(bool byPack, bool byEquip, bool byTask) + { + gamedatasend gamedatasend = new gamedatasend(); + + gamedatasend.Data = C2SCommandFactory.CreateGetAllDataCommand(byPack, byEquip, byTask); + _logger.Log(LogType.Warning, $"[Dat]- SendCmdGetAllData {byPack},{byEquip},{byTask}"); + SendProtocol(gamedatasend); + } + + public void c2s_SendCmdNPCSevHello(int nid) + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateNPCSevHelloDataCommand(nid); + SendProtocol(gamedatasend); + } + + public void c2s_CmdNormalAttack(byte byPVPMask) + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateNormalAttackDataCmd(byPVPMask); + SendProtocol(gamedatasend); + } + + public void c2s_SendCmdCancelAction() + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateNakeCmd(CSNetwork.C2SCommand.CommandID.CANCEL_ACTION); + SendProtocol(gamedatasend); + } + + public void c2s_CmdUnselect() + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateNakeCmd(CSNetwork.C2SCommand.CommandID.UNSELECT); + SendProtocol(gamedatasend); + } + + public void c2s_SendCmdSelectTarget(int idTarget) + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateSelectTarget(idTarget); + SendProtocol(gamedatasend); + } + + public void c2s_SendCmdNPCSevWaypoint() + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateNPCSevWaypointCmd(NPC_service_type.GP_NPCSEV_WAYPOINT, 0); + SendProtocol(gamedatasend); + } + public void c2s_SendCmdNPCSevMakeItem(int idSkill, int idItem, uint dwCount) + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateNPCSevMakeItemCmd(idSkill, idItem, dwCount); + SendProtocol(gamedatasend); + } + public void GetRoleBaseInfo(int iNumRole, List aRoleIDs) + { + int iNumLimit = 128; + playerbaseinfo p = null; + int iCount = 0; + + while (iCount < iNumRole) + { + p = new(); + p.Roleid = _selectedRole.roleid; + + int iNumSend = iNumLimit; + if (iCount + iNumLimit > iNumRole) + iNumSend = iNumRole - iCount; + + if (iNumSend > 0) + { + p.playerList = new(); + for (int i = 0; i < iNumSend; i++) + p.playerList.Add(aRoleIDs[iCount + i]); + + SendProtocol(p); + } + + + iCount += iNumSend; + } + } + + public void c2s_SendCmdGetOtherEquip(int iNumID, List aIDs) + { + // int iNumLimit = 250; + // int iCount = 0; + + // while (iCount < iNumID) + // { + // int iNumSend = iNumLimit; + // if (iCount + iNumLimit > iNumID) + // iNumSend = iNumID - iCount; + + // if (iNumSend > 0) + // { + // } + // } + } + + public void c2s_SendCmdNPCSevAcceptTask(int idTask, int idStorage, int idRefreshItem) + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateCmdNPCSevAcceptTask( + idTask, + idStorage, + idRefreshItem); + SendProtocol(gamedatasend); + } + + public void c2s_SendCmdNPCSevReturnTask(int idTask, int iChoice) + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateNPCSevReturnTaskCmd( + idTask, + iChoice); + SendProtocol(gamedatasend); + } + + public void c2s_SendCmdNPCSevTaskMatter(int idTask) + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateNPCSevTaskMatterCmd(idTask); + SendProtocol(gamedatasend); + } + + public void c2s_SendCmdNPCSevLearnSkill(int idSkill) + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateNPCSevLearnSkillCmd(idSkill); + BMLogger.LogError("HoangDev : c2s_SendCmdNPCSevLearnSkill gamedatasend.Data : " + gamedatasend.Data.Size); + BMLogger.LogError("HoangDev : c2s_SendCmdNPCSevLearnSkill idSkill : " + idSkill); + SendProtocol(gamedatasend); + } + + public void c2s_SendCmdNPCSevBuy(int itemNum, C2SCommand.npc_trade_item[] items) + { + if (itemNum <= 0 || items == null || items.Length < itemNum) + return; + + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateNPCSevBuyCmd(itemNum, items); + SendProtocol(gamedatasend); + } + + public void c2s_SendCmdNPCSevSell(int itemNum, C2SCommand.npc_sell_item[] items) + { + if (itemNum <= 0 || items == null || items.Length < itemNum) + return; + + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateNPCSevSellCmd(itemNum, items); + SendProtocol(gamedatasend); + } + + public void GetRoleCustomizeData(int iNumRole, List aRoleIDs) + { + if (iNumRole <= 0 || aRoleIDs == null || aRoleIDs.Count == 0) return; + + int iNumLimit = 240; + int iCount = 0; + + while (iCount < iNumRole) + { + getcustomdata p = new(); + p.Roleid = _selectedRole.roleid; + + int iNumSend = iNumLimit; + if (iCount + iNumLimit > iNumRole) + iNumSend = iNumRole - iCount; + + for (int i = 0; i < iNumSend; i++) + p.playerlist.Add(aRoleIDs[iCount + i]); + + SendProtocol(p); + + iCount += iNumSend; + } + } + public void c2s_SendCmdEmoteAction(uint wPose) + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateEmoteActionCmd((int)wPose); + SendProtocol(gamedatasend); + } + public void c2s_SendCmdTaskNotify(byte[] pData, uint dwDataSize) + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateTaskNotifyCmd( pData, dwDataSize); + BMLogger.Log($"[MH Task] c2s_SendCmdTaskNotify Command ID : {pData[0]} Size: {dwDataSize}"); + SendProtocol(gamedatasend); + } + + public void c2s_SendCmdStandUp() + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateNakeCmd(C2SCommand.CommandID.STAND_UP); + SendProtocol(gamedatasend); + } + + public void c2s_SendCmdAutoTeamSetGoal(int type, int goal_id, int op) + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateAutoTeamSetGoalCommand(type,goal_id, op); + SendProtocol(gamedatasend); + } + + public void c2s_CmdGoto(float x, float y, float z) + { + c2s_SendCmdGoto(x, y, z); + } + + // Send C2S::GOTO command data + void c2s_SendCmdGoto(float x, float y, float z) + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateGoToCommed( x, y, z); + SendProtocol(gamedatasend); + } + + public void c2s_SendCmdUseItem(byte byPackage, byte bySlot, int tid, byte byCount) + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateUseItemCmd(byPackage, bySlot, tid, byCount); + SendProtocol(gamedatasend); + } + + public void c2s_SendCmdGetExtProps() + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateNakeCmd(C2SCommand.CommandID.GET_EXT_PROP); + SendProtocol(gamedatasend); + } + + public void c2s_SendCmdGivePresent(int roleid, int mail_id, int goods_id, int goods_index, int goods_slot) + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateGivePresentCmd(roleid, mail_id, goods_id, goods_index, goods_slot); + SendProtocol(gamedatasend); + } + + public void c2s_SendCmdEnterSanctuary(int id) + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateEnterSanctuaryCmd(id); + SendProtocol(gamedatasend); + } + + public void c2s_SendCmdEnterInstance(int iTransIdx, int idInst) + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateEnterInstanceCmd(iTransIdx, idInst); + SendProtocol(gamedatasend); + } + + public void c2s_SendCmdActiveRushFly(bool bActive) + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateActiveRushFlyCmd(bActive); + SendProtocol(gamedatasend); + } + + public void c2s_SendCmdPetCtrl(int idTarget, int cmd, byte[] pParamBuf, int iParamLen) + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreatePetCtrlCmd(idTarget, cmd, pParamBuf, iParamLen); + SendProtocol(gamedatasend); + } + + public void c2s_SendCmdQueryFactionPVPInfo(int faction_id) + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateQueryFactionPVPInfo(faction_id); + SendProtocol(gamedatasend); + } + public void c2s_SendCmdNPCSevEmbed(ushort wStoneIdx, ushort wEquipIdx, int tidStone, int tidEquip) + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateNPCSevEmbedCmd(wStoneIdx, wEquipIdx, tidStone, tidEquip); + SendProtocol(gamedatasend); + } + public void c2s_SendCmdGetItemInfo(byte byPackage, int bySlot) + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateGetItemInfoCmd(byPackage, bySlot); + SendProtocol(gamedatasend); + } + } } \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/createrole.cs b/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/createrole.cs index 5bfe6615bf..9f7019acfb 100644 --- a/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/createrole.cs +++ b/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/createrole.cs @@ -1,23 +1,27 @@ using System; using System.Collections.Generic; +using CSNetwork.Protocols.RPCData; namespace CSNetwork.Protocols { public class createrole : Protocol { public int Userid { get; set; } - public int Localsid { get; set; } + public uint Localsid { get; set; } + public RoleInfo Roleinfo { get; set; } public Octets Referid { get; set; } public createrole() : base(ProtocolType.PROTOCOL_CREATEROLE) { Referid = new Octets(); + Roleinfo = new RoleInfo(); } public override Protocol Clone() => new createrole { Userid = Userid, Localsid = Localsid, + Roleinfo = Roleinfo?.Clone(), Referid = new Octets(Referid.ToArray()) }; @@ -25,13 +29,23 @@ namespace CSNetwork.Protocols { os.Write(Userid); os.Write(Localsid); + if (Roleinfo != null) + { + Roleinfo.Marshal(os); + } + else + { + new RoleInfo().Marshal(os); + } os.Write(Referid); } public override void Unmarshal(OctetsStream os) { Userid = os.ReadInt32(); - Localsid = os.ReadInt32(); + Localsid = os.ReadUInt32(); + Roleinfo = new RoleInfo(); + Roleinfo.Unmarshal(os); Referid = os.ReadOctets(); } diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/createrole_re.cs b/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/createrole_re.cs new file mode 100644 index 0000000000..fccf37d8b0 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/createrole_re.cs @@ -0,0 +1,58 @@ +using System; +using CSNetwork.Protocols.RPCData; + +namespace CSNetwork.Protocols +{ + public class createrole_re : Protocol + { + public int result { get; set; } + public int roleid { get; set; } + public uint localsid { get; set; } + public RoleInfo roleinfo { get; set; } + public int refretcode { get; set; } + + public createrole_re() : base(ProtocolType.PROTOCOL_CREATEROLE_RE) + { + roleinfo = new RoleInfo(); + } + + public override Protocol Clone() => new createrole_re + { + result = result, + roleid = roleid, + localsid = localsid, + roleinfo = roleinfo?.Clone(), + refretcode = refretcode + }; + + public override void Marshal(OctetsStream os) + { + os.Write(result); + os.Write(roleid); + os.Write(localsid); + if (roleinfo != null) + { + roleinfo.Marshal(os); + } + else + { + new RoleInfo().Marshal(os); + } + os.Write(refretcode); + } + + public override void Unmarshal(OctetsStream os) + { + result = os.ReadInt32(); + roleid = os.ReadInt32(); + localsid = os.ReadUInt32(); + roleinfo = new RoleInfo(); + roleinfo.Unmarshal(os); + refretcode = os.ReadInt32(); + } + + public override int PriorPolicy() => 101; + + public override bool SizePolicy(int size) => size <= 8192; + } +} diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/createrole_re.cs.meta b/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/createrole_re.cs.meta new file mode 100644 index 0000000000..9dfcaf18de --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/createrole_re.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 3640555d366b4e34bbefbbf040f7f339 \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/rpcdata/GRoleInventory.cs b/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/rpcdata/GRoleInventory.cs index a9d2a545ef..5dd802d59e 100644 --- a/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/rpcdata/GRoleInventory.cs +++ b/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/rpcdata/GRoleInventory.cs @@ -35,7 +35,8 @@ namespace CSNetwork.Protocols.RPCData os.Write(pos); os.Write(count); os.Write(max_count); - os.Write(data); + // Server-side expects an Octets field here; null will crash encoding. + os.Write(data ?? new Octets()); os.Write(proctype); os.Write(expire_date); os.Write(guid1); diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/rpcdata/RoleInfo.cs b/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/rpcdata/RoleInfo.cs index 2929615f2f..ec05255c04 100644 --- a/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/rpcdata/RoleInfo.cs +++ b/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/rpcdata/RoleInfo.cs @@ -69,9 +69,10 @@ namespace CSNetwork.Protocols.RPCData os.Write(occupation); os.Write(level); os.Write(level2); - os.Write(name); - os.Write(custom_data); - os.WriteList(equipment); + // Avoid null Octets/List crashing protocol.Encode() + os.Write(name ?? new Octets()); + os.Write(custom_data ?? new Octets()); + os.WriteList(equipment ?? new List()); os.Write(status); os.Write(delete_time); os.Write(create_time); @@ -80,12 +81,12 @@ namespace CSNetwork.Protocols.RPCData os.Write(posy); os.Write(posz); os.Write(worldtag); - os.Write(custom_status); - os.Write(charactermode); + os.Write(custom_status ?? new Octets()); + os.Write(charactermode ?? new Octets()); os.Write(referrer_role); os.Write(cash_add); - os.Write(reincarnation_data); - os.Write(realm_data); + os.Write(reincarnation_data ?? new Octets()); + os.Write(realm_data ?? new Octets()); } public void Unmarshal(OctetsStream os) diff --git a/Assets/PerfectWorld/Scripts/Network/UnityGameSession.cs b/Assets/PerfectWorld/Scripts/Network/UnityGameSession.cs index 4db362886e..a23f1aa2af 100644 --- a/Assets/PerfectWorld/Scripts/Network/UnityGameSession.cs +++ b/Assets/PerfectWorld/Scripts/Network/UnityGameSession.cs @@ -1,4 +1,4 @@ -using BrewMonster; +using BrewMonster; using BrewMonster.Common; using CSNetwork; using CSNetwork.C2SCommand; @@ -171,6 +171,12 @@ namespace BrewMonster.Network { Instance._gameSession.SelectRoleAsync(roleInfo, callback); } + + public static void CreateRoleAsync(RoleInfo roleInfo, Octets referId, Action callback = null) + { + Instance._gameSession.CreateRoleAsync(roleInfo, referId, callback); + } + public static void EnterWorldAsync(RoleInfo roleInfo, Action callback = null) { Debug.Log("EnterWorldAsync !!!!! nay "); diff --git a/Assets/PerfectWorld/Scripts/Task/ATaskTemplMan.cs b/Assets/PerfectWorld/Scripts/Task/ATaskTemplMan.cs index b3a1af2b43..efae8f7f98 100644 --- a/Assets/PerfectWorld/Scripts/Task/ATaskTemplMan.cs +++ b/Assets/PerfectWorld/Scripts/Task/ATaskTemplMan.cs @@ -300,96 +300,28 @@ namespace BrewMonster.Scripts.Task return tasks; } - // Add this method to ATaskTemplMan class if not exists - public List GetAllTopTasks() + public int GetStorageRefreshPerDay(uint storageId) { - List topTasks = new List(); + if (storageId == 0 || storageId > TaskInterfaceConstants.TASK_STORAGE_COUNT) + return 0; - // Iterate through all task templates and collect top-level tasks - // Assuming you have a dictionary or collection of all tasks - foreach (var kvp in m_TaskTemplMap) // Replace with your actual collection name + if (!m_StorageEssenseMap.TryGetValue(storageId, out uint essenceId)) + return 0; + + DATA_TYPE dt = DATA_TYPE.DT_INVALID; + var serviceData = m_pEleDataMan.get_data_ptr( + essenceId, + ID_SPACE.ID_SPACE_ESSENCE, + ref dt + ); + + if (serviceData != null && dt == DATA_TYPE.DT_NPC_TASK_OUT_SERVICE) { - var templ = kvp.Value; - if (templ != null && templ.m_pParent == null) // Top-level task has no parent - { - topTasks.Add(templ); - } + var outService = (NPC_TASK_OUT_SERVICE)serviceData; + return (int)outService.storage_refresh_per_day; } - return topTasks; - } - - // Alternative method if you want to check by NPC ID directly - public List GetAvailableTasksForNPC(int npcID) - { - List availableTasks = new List(); - - foreach (var kvp in m_TaskTemplMap) // Replace with your actual collection name - { - var templ = kvp.Value; - if (templ != null && - templ.m_pParent == null && - templ.m_FixedData.m_ulDelvNPC == npcID) - { - availableTasks.Add(templ); - } - } - - return availableTasks; - } - - // Add this method to ATaskTemplMan class - - /// - /// Get all task templates (for iterating to find available tasks) - /// Lấy tất cả task templates (để duyệt tìm nhiệm vụ có thể nhận) - /// - public List GetAllTaskTemplates() - { - List allTasks = new List(); - - // Assuming you have a collection storing all task templates - // Replace m_TaskMap with your actual collection name - if (m_TaskTemplMap != null) - { - foreach (var kvp in m_TaskTemplMap) - { - if (kvp.Value != null) - { - allTasks.Add(kvp.Value); - } - } - } - - return allTasks; - } - - /// - /// Get list of tasks delivered by a specific NPC - /// - public List GetTasksFromNPC(int npcID) - { - var result = new List(); - - // Check if NPC info map is available - if (m_NPCInfoMap != null && m_NPCInfoMap.TryGetValue((uint)npcID, out var npcInfo)) - { - return new List(); - } - else - { - // Fallback - foreach (var kvp in m_TaskTemplMap) - { - var templ = kvp.Value; - if (templ != null && templ.m_FixedData.m_ulDelvNPC == npcID) - { - result.Add(templ); - } - } - } - - return result; + return 0; } // General method to read a struct from a FileStream diff --git a/Assets/PerfectWorld/Scripts/Task/CECTaskInterface.cs b/Assets/PerfectWorld/Scripts/Task/CECTaskInterface.cs index 2a6ca41983..86a961fd34 100644 --- a/Assets/PerfectWorld/Scripts/Task/CECTaskInterface.cs +++ b/Assets/PerfectWorld/Scripts/Task/CECTaskInterface.cs @@ -531,85 +531,6 @@ namespace BrewMonster.Scripts.Task return m_pActiveListBuf; } - // Trong file CECTaskInterface.cs - - public bool HasTaskRelatedToNPC(int npcID) - { - // Check tasks is active - ActiveTaskList activeList = GetActiveTaskList(); - if (activeList != null && activeList.m_TaskEntries != null) - { - for (int i = 0; i < activeList.m_uTaskCount; i++) - { - var entry = activeList.m_TaskEntries[i]; - if (entry == null) continue; - - ATaskTempl templ = entry.GetTempl(); - if (templ == null) continue; - - // Check if this NPC is the target of the task - if (IsNPCTargetOfTask(templ, entry, npcID)) - { - return true; - } - } - } - - // Check tasks new - ATaskTemplMan taskMan = GetTaskTemplMan(); - if (taskMan != null) - { - List npcTasks = taskMan.GetTasksFromNPC(npcID); - if (npcTasks != null) - { - uint ulCurTime = GetCurTime(); - foreach (var templ in npcTasks) - { - // Check prerequisite - if (templ.CheckPrerequisite(this, activeList, ulCurTime) == 0) - { - return true; - } - } - } - } - - return false; - } - - // Check NPC is target of the task - private bool IsNPCTargetOfTask(ATaskTempl templ, ActiveTaskEntry entry, int npcID) - { - var data = templ.m_FixedData; - - // Task completed case - if (entry.IsFinished()) - { - if (data.m_ulAwardNPC == npcID) return true; - } - else - { - // NPC target - if (data.m_ulNPCMoving == npcID) return true; - - // Pos target - if (data.m_ulNPCDestSite == npcID) return true; - - // Security target - if (data.m_ulNPCToProtect == npcID) return true; - - if (data.m_enumMethod == (ulong)TaskCompletionMethod.enumTMTalkToNPC) - { - if (data.m_ulNPCMoving == 0 && data.m_ulAwardNPC == npcID) - { - return true; - } - } - } - return false; - } - - // private void InitActiveTaskList() // { // ActiveTaskList pLst = GetActiveTaskList(); diff --git a/Assets/PerfectWorld/Scripts/Task/UI/DlgTask.cs b/Assets/PerfectWorld/Scripts/Task/UI/DlgTask.cs index 9a64ab3266..4452bbd2b6 100644 --- a/Assets/PerfectWorld/Scripts/Task/UI/DlgTask.cs +++ b/Assets/PerfectWorld/Scripts/Task/UI/DlgTask.cs @@ -193,8 +193,7 @@ namespace BrewMonster.Scripts.Task.UI }); trigger.triggers.Add(entry); - UnityEngine.Debug.Log($"[DlgTask] Awake: Added EventTrigger for PointerClick to m_pTxt_QuestItem (like C++ WM_LBUTTONDOWN)"); - } + } OnInitDialog(); } @@ -484,6 +483,7 @@ namespace BrewMonster.Scripts.Task.UI if (pTempl == null) return string.Empty; var type = (ENUM_TASK_TYPE)pTempl.m_FixedData.m_ulType; string rawName = ModelRenderer.Scripts.Common.ByteToStringUtils.UshortArrayToUnicodeString(pTempl.m_FixedData.m_szName); + if (type == ENUM_TASK_TYPE.enumTTQiShaList && !string.IsNullOrEmpty(rawName) && rawName[0] == '^') { // 如果是七杀榜任务且已经加了颜色,则颜色不变 // If QiShaList task already has color, keep it @@ -493,6 +493,25 @@ namespace BrewMonster.Scripts.Task.UI string strColorPreFix = A3DColorToString(GetTaskColor(pTempl)); return strColorPreFix + strTaskName; } + private string GetTaskNameWithColor(ATaskTempl pTempl, out Color color) + { + if (pTempl == null) { + color = Color.white; + return string.Empty; + } + var type = (ENUM_TASK_TYPE)pTempl.m_FixedData.m_ulType; + string rawName = ModelRenderer.Scripts.Common.ByteToStringUtils.UshortArrayToUnicodeString(pTempl.m_FixedData.m_szName); + + if (type == ENUM_TASK_TYPE.enumTTQiShaList && !string.IsNullOrEmpty(rawName) && rawName[0] == '^') + { + // 如果是七杀榜任务且已经加了颜色,则颜色不变 // If QiShaList task already has color, keep it + color = GetTaskColor(pTempl); + return rawName; + } + string strTaskName = GetTaskNameWithOutColor(pTempl); + color = GetTaskColor(pTempl); + return strTaskName; + } // static ACString GetTaskNameWithOutColor(const ATaskTempl* pTempl); private static string GetTaskNameWithOutColor(ATaskTempl pTempl) { @@ -520,6 +539,7 @@ namespace BrewMonster.Scripts.Task.UI } Color result; EC_Utility.STRING_TO_A3DCOLOR(GetStringFromTable(idType - (int)ENUM_TASK_TYPE.enumTTDaily + 3121), out result); + Debug.Log("[DlgTask] GetTaskColor result : " + result); return result; // return UnityEngine.Color.white; } @@ -684,7 +704,6 @@ namespace BrewMonster.Scripts.Task.UI if( idTask != m_idLastTask ) { _nameTaskText.SetText(EC_Utility.FormatForTextMeshPro(GetTaskNameWithColor(pTemp))); - //pTextDesc->SetText(FormatTaskText(pTemp->GetDescription(), pTextDesc->GetColor())); pTextDesc.SetText(EC_Utility.FormatForTextMeshPro(pTemp.GetDescription())); m_idLastTask = idTask; @@ -800,7 +819,7 @@ namespace BrewMonster.Scripts.Task.UI if (idTask != m_idLastTask) { _nameTaskText.SetText(EC_Utility.FormatForTextMeshPro(GetTaskNameWithColor(pTemp))); - + Debug.Log("[DlgTask] SearchForTask name task: " + _nameTaskText.text); if (pTextDesc != null) pTextDesc.SetText(EC_Utility.FormatForTextMeshPro(pTemp.GetDescription())); m_idLastTask = idTask; bLastTaskChanged = true; @@ -1049,8 +1068,10 @@ namespace BrewMonster.Scripts.Task.UI while (child != null) { uint id = child.m_FixedData.m_ID; - string text = GetTaskNameWithColor(child); + Color disPlayColor=Color.white; + string text = GetTaskNameWithColor(child,out disPlayColor); var pItem = pTreeTask.InsertItem(text, pRoot, null); + pItem.SetItemTextColor(disPlayColor); if (pItem != null) { pTreeTask.SetItemData(pItem, id); @@ -1065,6 +1086,7 @@ namespace BrewMonster.Scripts.Task.UI InsertTaskChildren(pItem, id, bExpand, bKey); child = child.m_pNextSibling; } + } // [中文] 仅插入“已接任务(Active)”中的子任务(基于 ActiveTaskList 的 Child/NextSbl 索引) @@ -1093,9 +1115,11 @@ namespace BrewMonster.Scripts.Task.UI uint childId = childEntry.m_ID; ATaskTempl childTempl = pMan.GetTaskTemplByID(childId); - string text = childTempl != null ? GetTaskNameWithColor(childTempl) : $"Task {childId}"; - + Color disPlayColor=Color.white; + string text = childTempl != null ? GetTaskNameWithColor(childTempl,out disPlayColor) : $"Task {childId}"; + Debug.Log("[DlgTask] InsertActiveTaskChildren text: " + text); var pItem = pTreeTask.InsertItem(text, pRoot, null); + pItem.SetItemTextColor(disPlayColor); if (pItem != null) { pTreeTask.SetItemData(pItem, childId); @@ -1742,10 +1766,12 @@ namespace BrewMonster.Scripts.Task.UI } // add Biggest node if not exist + string strItem = GetTaskNameWithColor(pTemp, out Color color); if(pParent ==null) { pParent = pTreeTask.InsertItem(GetStringFromTable(3101 + nTaskType - 100), null, pAfter); - // TODO: Expand tree node + pParent.SetItemTextColor(color); + // TODO: Expand tree node // pTreeTask.Expand(pParent, AUITREEVIEW_EXPAND_EXPAND); pTreeTask.SetItemData(pParent, nTaskType); @@ -1755,17 +1781,16 @@ namespace BrewMonster.Scripts.Task.UI CECTaskInterface pTask = GetHostPlayer()?.GetTaskInterface(); if (pTask == null) return; - string strItem = GetTaskNameWithColor(pTemp); bool bTaskPushed = pMan.IsTaskToPush(id) && !pTask.HasTask((uint)id); if (bTaskPushed) { strItem += GetStringFromTable(3100); } pItem = pTreeTask.InsertItem(strItem, pParent, null); - - if( pTemp.IsKeyTask() ) - // pTreeTask.SetItemTextColor(pItem, GetTaskColor((int)ENUM_TASK_TYPE.enumTTLevel2)); + pItem.SetItemTextColor(color); + if( pTemp.IsKeyTask() ) + { pItem.SetItemTextColor(GetTaskColor((int)ENUM_TASK_TYPE.enumTTLevel2)); - // pTreeTask.SetItemHint(pItem, pTemp->GetSignature()); // TODO + } pTreeTask.SetItemData(pItem, (uint)id); // HaveQuest view: children should reflect ActiveTaskList, not template tree (otherwise they never disappear on completion) if (m_iType == 0) diff --git a/Assets/PerfectWorld/Scripts/Task/UI/TaskTreeView.cs b/Assets/PerfectWorld/Scripts/Task/UI/TaskTreeView.cs index e502b0d71e..fca186c3c6 100644 --- a/Assets/PerfectWorld/Scripts/Task/UI/TaskTreeView.cs +++ b/Assets/PerfectWorld/Scripts/Task/UI/TaskTreeView.cs @@ -53,6 +53,11 @@ namespace BrewMonster.Scripts.Task.UI { // Create a new item GameObject and component TaskTreeViewItem pItem = Instantiate(m_pTreeViewItemPrefab); + if(pParent != null) + { + pParent.SetLastItem(false); + } + pItem.SetLastItem(true); GameObject go = pItem.gameObject; // go.name = $"Task_{}"; if (pItem == null) return null; diff --git a/Assets/PerfectWorld/Scripts/Task/UI/TaskTreeViewItem.cs b/Assets/PerfectWorld/Scripts/Task/UI/TaskTreeViewItem.cs index 57caf2cb56..e34184a6ee 100644 --- a/Assets/PerfectWorld/Scripts/Task/UI/TaskTreeViewItem.cs +++ b/Assets/PerfectWorld/Scripts/Task/UI/TaskTreeViewItem.cs @@ -4,22 +4,22 @@ using UnityEngine; using UnityEngine.Events; using UnityEngine.EventSystems; using UnityEngine.UI; - +using BrewMonster.Scripts.UI; namespace BrewMonster.Scripts.Task.UI { public class TaskTreeViewItem : MonoBehaviour, IRefreshLayout { - [SerializeField] private TMP_Text m_text; + [SerializeField] private TextOutlet m_text; [SerializeField] private Button m_Button; - [SerializeField] private Sprite[] _levelSprites; - [SerializeField] private Button _expandButton; - [SerializeField] private Button _collapseButton; + [SerializeField] private Toggle _expandToggle; + [SerializeField] private TextOutlet _expandText; + [SerializeField] private LayoutElement _space; [Header("DEBUG")] [SerializeField] private uint m_uItemData; [SerializeField] private int _treeLevel; private RectTransform _rectTransform; - + public bool isLastItem = true; public UnityEvent OnClick = new UnityEvent(); #region UNITY_METHODS @@ -27,10 +27,10 @@ namespace BrewMonster.Scripts.Task.UI private void Awake() { m_Button.onClick.AddListener(OnBtnClick); - _expandButton.onClick.AddListener(OnExpandBtnClicked); - _collapseButton.onClick.AddListener(OnCollapseBtnClicked); - _expandButton.gameObject.SetActive(false); - _collapseButton.gameObject.SetActive(false); + //_expandButton.onClick.AddListener(OnExpandBtnClicked); + //_collapseButton.onClick.AddListener(OnCollapseBtnClicked); + // _expandButton.gameObject.SetActive(false); + // _collapseButton.gameObject.SetActive(false); _rectTransform = GetComponent(); } @@ -66,24 +66,36 @@ namespace BrewMonster.Scripts.Task.UI if (m_text != null) { - m_text.color = color; + m_text.SetColor(color); + _expandText.SetColor(color); + } + } + public void SetLastItem(bool isLastItem) + { + this.isLastItem = isLastItem; + if(isLastItem) + { + _expandText.Set("●"); // thís not show in tmp text + _expandToggle.onValueChanged.RemoveAllListeners(); + } + else + { + _expandText.Set("+"); + _expandToggle.onValueChanged.AddListener(OnExpandToggleValueChanged); } } - public void SetItemText(string text) { if (m_text != null) { - m_text.text = text; + m_text.Set(text); } } public void SetTreeLevel(int level) { _treeLevel = level; - Image btnImage = m_Button.GetComponent(); - btnImage.sprite = _treeLevel < _levelSprites.Length ? _levelSprites[_treeLevel] : _levelSprites[^1]; - btnImage.SetNativeSize(); + _space.preferredWidth = level * 40; } public int GetTreeLevel() => _treeLevel; @@ -98,8 +110,8 @@ namespace BrewMonster.Scripts.Task.UI children[i].gameObject.SetActive(expand); } - _expandButton.gameObject.SetActive(!expand); - _collapseButton.gameObject.SetActive(expand); + //_expandButton.gameObject.SetActive(!expand); + //_collapseButton.gameObject.SetActive(expand); RefreshLayout(); } @@ -147,6 +159,19 @@ namespace BrewMonster.Scripts.Task.UI { SetExpand(false); } + + void OnExpandToggleValueChanged(bool isOn) + { + SetExpand(isOn); + if(isOn) + { + _expandText.Set("-"); + } + else + { + _expandText.Set("+"); + } + } } public struct TaskItemClickEvent diff --git a/Assets/PerfectWorld/Scripts/UI/GamePlay/UINPC.cs b/Assets/PerfectWorld/Scripts/UI/GamePlay/UINPC.cs index dac452d005..e025511e22 100644 --- a/Assets/PerfectWorld/Scripts/UI/GamePlay/UINPC.cs +++ b/Assets/PerfectWorld/Scripts/UI/GamePlay/UINPC.cs @@ -5,6 +5,27 @@ using UnityEngine.UI; namespace BrewMonster { + + public enum IconTaskType + { + QI_NONE = -1, + QI_OUT = 2, // task tu chan (nhan) + QI_IN = 2, // task tu chan (hoan thanh) + QI_OUT_N = 3, // chua du dieu kien nhan task + QI_IN_N = 3, // task nhan nhung chua lam (chua xong) + QI_OUT_K = 0, // chua biet + QI_IN_K = 5, // chua biet + + QI_OUT_TYPE1 = 5, // task bang hoi (nhan) + QI_IN_TYPE1 = 5, // task bang hoi (hoan thanh) + QI_OUT_TYPE2 = 1, // chua biet + QI_IN_TYPE2 = 1, // chua biet + QI_OUT_TYPE3 = -1, // task daily (nhan) + QI_IN_TYPE3 = -1, // task daily (hoan thanh) + QI_OUT_TYPE4 = 0, // task chinh (nhan) + QI_IN_TYPE4 = 4, // task chinh (hoan thanh) + } + public class UINPC : MonoBehaviour { [SerializeField] private TextMeshProUGUI _nameText; @@ -13,6 +34,21 @@ namespace BrewMonster [Header("List Icon Task")] [SerializeField] private GameObject _iconTaskMain; + [SerializeField] private List _listIconTask; + + private Image _cachedIconImage; + + private void Awake() + { + if (_iconTaskMain != null) + { + _cachedIconImage = _iconTaskMain.GetComponent(); + if (_cachedIconImage == null) + { + BMLogger.LogError($"[UINPC] _iconTaskMain doesn't have Image component!"); + } + } + } // Start is called once before the first execution of Update after the MonoBehaviour is created public void SetName(string name) @@ -30,10 +66,30 @@ namespace BrewMonster _healthText.text = healthText; } + public void SetTaskIcon(IconTaskType iconType) + { + if (_iconTaskMain == null || _cachedIconImage == null) + { + return; + } + int iconIndex = (int)iconType; + + if (iconIndex >= 0 && _listIconTask != null && iconIndex < _listIconTask.Count) + { + _cachedIconImage.sprite = _listIconTask[iconIndex]; + _iconTaskMain.SetActive(true); + } + else + { + _iconTaskMain.SetActive(false); + } + } + public void SetTaskIconMain(bool isShow) { - if(_iconTaskMain != null) + if (_iconTaskMain != null) _iconTaskMain.SetActive(isShow); } } } + diff --git a/Assets/PerfectWorld/Scripts/UI/Login/CreateCharacterScreen.cs b/Assets/PerfectWorld/Scripts/UI/Login/CreateCharacterScreen.cs new file mode 100644 index 0000000000..47b5ad4bf7 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/UI/Login/CreateCharacterScreen.cs @@ -0,0 +1,249 @@ +using System; +using System.Text; +using BrewMonster.Network; +using CSNetwork; +using CSNetwork.GPDataType; +using CSNetwork.Protocols; +using CSNetwork.Protocols.RPCData; +using TMPro; +using UnityEngine; +using UnityEngine.UI; +using BrewMonster.Scripts; + +namespace BrewMonster.UI +{ + /// + /// UI screen for creating a new character. + /// Equivalent to CDlgCreateGenderName + CDlgCreateProfession in C++. + /// + public class CreateCharacterScreen : MonoBehaviour + { + [SerializeField] private GameObject professionSelectionPanel; + [SerializeField] private Button[] professionButtons; + [SerializeField] private Button maleGenderButton; + [SerializeField] private Button femaleGenderButton; + [SerializeField] private TMP_InputField nameInputField; + [SerializeField] private Button confirmButton; + [SerializeField] private Button cancelButton; + [SerializeField] private Button backButton; + + private int _currentProfession = -1; + private int _currentGender = -1; + + private Action _onCreateComplete; + private Action _onCancel; + + // Static array matching s_bShowMale[NUM_PROFESSION] from original C++ code (EC_ProfConfigs.cpp) + // true = show male, false = show female + private static readonly bool[] s_bShowMale = new bool[] + { + true, // 0: Warrior (武侠) + false, // 1: Mage (法师) + false, // 2: Priest (巫师) + false, // 3: Assassin (妖精) + true, // 4: Orc (妖兽) + true, // 5: Monk (刺客) + true, // 6: Elf (羽芒) + false, // 7: Elf (羽灵) + true, // 8: Ling (剑灵) + false, // 9: Ling (魅灵) + true, // 10: Oboro (夜影) + false, // 11: Oboro (月仙) + }; + + private void Start() + { + if (confirmButton != null) + confirmButton.onClick.AddListener(OnConfirmClicked); + if (cancelButton != null) + cancelButton.onClick.AddListener(OnCancelClicked); + if (backButton != null) + backButton.onClick.AddListener(OnCancelClicked); + + if (maleGenderButton != null) + maleGenderButton.onClick.AddListener(() => OnGenderSelected(GENDER.GENDER_MALE)); + if (femaleGenderButton != null) + femaleGenderButton.onClick.AddListener(() => OnGenderSelected(GENDER.GENDER_FEMALE)); + + // Setup profession buttons + if (professionButtons != null) + { + for (int i = 0; i < professionButtons.Length && i < 12; i++) + { + int prof = i; // Capture for closure + if (professionButtons[i] != null) + professionButtons[i].onClick.AddListener(() => OnProfessionSelected(prof)); + } + } + + if (nameInputField != null) + { + nameInputField.onSubmit.AddListener((text) => { if (CanConfirm()) OnConfirmClicked(); }); + } + } + + public void Show(Action onCreateComplete, Action onCancel) + { + _onCreateComplete = onCreateComplete; + _onCancel = onCancel; + _currentProfession = -1; + _currentGender = -1; + + gameObject.SetActive(true); + + if (nameInputField != null) + { + nameInputField.text = ""; + nameInputField.Select(); + } + + UpdateConfirmButtonState(); + } + + public void Hide() + { + gameObject.SetActive(false); + } + + private void OnProfessionSelected(int profession) + { + if (profession < 0 || profession >= (int)Profession.NUM_PROFESSION) + return; + + _currentProfession = profession; + + // Update UI to show selected profession + if (professionButtons != null) + { + for (int i = 0; i < professionButtons.Length; i++) + { + if (professionButtons[i] != null) + { + // Visual feedback for selected profession + var colors = professionButtons[i].colors; + colors.normalColor = (i == profession) ? Color.yellow : Color.white; + professionButtons[i].colors = colors; + } + } + } + + // Auto-select gender based on profession (matching original C++ logic from EC_ProfConfigs.cpp) + // This matches the s_bShowMale array in CanShowOnCreate function + int autoGender = GetDefaultGenderForProfession(profession); + OnGenderSelected(autoGender); + + UpdateConfirmButtonState(); + } + + /// + /// Gets the default gender for a profession based on the original C++ logic. + /// Matches the s_bShowMale array from EC_ProfConfigs.cpp CanShowOnCreate function. + /// + private int GetDefaultGenderForProfession(int profession) + { + if (profession >= 0 && profession < s_bShowMale.Length) + { + return s_bShowMale[profession] ? GENDER.GENDER_MALE : GENDER.GENDER_FEMALE; + } + + // Fallback to male if profession is invalid + return GENDER.GENDER_MALE; + } + + private void OnGenderSelected(int gender) + { + if (gender != GENDER.GENDER_MALE && gender != GENDER.GENDER_FEMALE) + return; + + _currentGender = gender; + + // Update UI to show selected gender + if (maleGenderButton != null) + { + var colors = maleGenderButton.colors; + colors.normalColor = (gender == GENDER.GENDER_MALE) ? Color.yellow : Color.white; + maleGenderButton.colors = colors; + } + + if (femaleGenderButton != null) + { + var colors = femaleGenderButton.colors; + colors.normalColor = (gender == GENDER.GENDER_FEMALE) ? Color.yellow : Color.white; + femaleGenderButton.colors = colors; + } + + UpdateConfirmButtonState(); + } + + private void OnConfirmClicked() + { + if (!CanConfirm()) + return; + + string characterName = nameInputField != null ? nameInputField.text : ""; + if (string.IsNullOrWhiteSpace(characterName)) + { + Debug.LogWarning("Character name cannot be empty"); + return; + } + + // Create RoleInfo using helper method + RoleInfo roleInfo = GameSession.CreateNewRoleInfo(characterName, _currentProfession, _currentGender); + + // Create role via network + Debug.Log($"Calling CreateRoleAsync for character: {characterName}, profession: {_currentProfession}, gender: {_currentGender}"); + UnityGameSession.CreateRoleAsync(roleInfo, new Octets(), (createdRole) => + { + if (createdRole != null) + { + Debug.Log($"Character created successfully: {characterName}, RoleID: {createdRole.roleid}"); + Hide(); + _onCreateComplete?.Invoke(createdRole); + } + else + { + Debug.LogError($"Failed to create character: {characterName}. Check GameSession logs for error details."); + // TODO: Show error message to user + } + }); + } + + private void OnCancelClicked() + { + Hide(); + _onCancel?.Invoke(); + } + + private bool CanConfirm() + { + if (_currentProfession < 0 || _currentProfession >= (int)Profession.NUM_PROFESSION) + return false; + + if (_currentGender != GENDER.GENDER_MALE && _currentGender != GENDER.GENDER_FEMALE) + return false; + + string name = nameInputField != null ? nameInputField.text : ""; + if (string.IsNullOrWhiteSpace(name)) + return false; + + return true; + } + + private void UpdateConfirmButtonState() + { + if (confirmButton != null) + { + confirmButton.interactable = CanConfirm(); + } + } + + private void Update() + { + // Update confirm button state in case name changes + if (nameInputField != null && nameInputField.isFocused) + { + UpdateConfirmButtonState(); + } + } + } +} diff --git a/Assets/PerfectWorld/Scripts/UI/Login/CreateCharacterScreen.cs.meta b/Assets/PerfectWorld/Scripts/UI/Login/CreateCharacterScreen.cs.meta new file mode 100644 index 0000000000..5a22e1e624 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/UI/Login/CreateCharacterScreen.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: aa9de023137e92348983cee3c59d620b \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/UI/Login/LoginScreenUI.cs b/Assets/PerfectWorld/Scripts/UI/Login/LoginScreenUI.cs index 0664d235eb..559b51cac9 100644 --- a/Assets/PerfectWorld/Scripts/UI/Login/LoginScreenUI.cs +++ b/Assets/PerfectWorld/Scripts/UI/Login/LoginScreenUI.cs @@ -1,193 +1,282 @@ -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using BrewMonster.Network; -using CSNetwork.Protocols; -using CSNetwork.Protocols.RPCData; -using TMPro; -using UnityEngine; -using UnityEngine.SceneManagement; -using UnityEngine.UI; - -namespace BrewMonster.UI -{ - /// - /// Login Flow: - /// 1. Enter username and password - /// 2. Click login button - /// 3. Login success, get the list of characters - /// 4. Open the select character screen - /// - public class LoginScreenUI : MonoBehaviour - { - [SerializeField] private TMP_InputField _usernameInputField; - [SerializeField] private TMP_InputField _passwordInputField; - [SerializeField] private Button _loginButton; - [SerializeField] private SelecScreenCharacter _selectCharacterScreen; - - private List _roleInfos; - bool isDoneWorldRender = false; - bool isDoneNPCRender = false; - private SynchronizationContext context; - public AudioClip loginBGM; - void Start() - { - AudioManager.Instance.PlayBGM(loginBGM, 1.5f); - _loginButton.onClick.AddListener(OnLoginButtonClicked); - context = SynchronizationContext.Current; - - _usernameInputField.text = PlayerPrefs.GetString("username", ""); - _passwordInputField.text = PlayerPrefs.GetString("password", ""); - - } - - // Update is called once per frame - void Update() - { - if (_roleInfos != null) - { - _selectCharacterScreen.InitScreen(_roleInfos, OnClickSelectCharacter); - _roleInfos = null; - } - -#if UNITY_EDITOR - if (Input.GetKeyUp(KeyCode.LeftAlt)) - { - _usernameInputField.text = "test004"; - _passwordInputField.text = "123456"; - } - - if (Input.GetKeyUp(KeyCode.Tab)) - { - _usernameInputField.text = "test002"; - _passwordInputField.text = "123456"; - OnLoginButtonClicked(); - } -#endif - } - - public async void OnLoginButtonClicked() - { - BMLogger.Log("OnLoginButtonClicked"); - string username = _usernameInputField.text; - string password = _passwordInputField.text; - // UnityGameSession.SetConnectionInfo("103.182.22.52", 29000); - UnityGameSession.SetConnectionInfo("103.51.120.195", 29000); - PlayerPrefs.SetString("username", username); - PlayerPrefs.SetString("password", password); - PlayerPrefs.Save(); - await UnityGameSession.Login(username, password, OnLoginComplete); - _selectCharacterScreen.gameObject.SetActive(true); - } - - /// - /// Callback when the login is complete. - /// Then get the list of characters - /// - private void OnLoginComplete(bool result) - { - if (!result) - { - BMLogger.LogError("Login failed"); - return; - } - - UnityGameSession.GetRoleListAsync(OnGetRoleListComplete); - } - - /// - /// Callback when the list of characters is retrieved. - /// Then move to the select character screen - /// - private void OnGetRoleListComplete(List roleInfos) - { - _roleInfos = roleInfos; - } - - private void OnClickSelectCharacter(RoleInfo roleInfo) - { - UnityGameSession.SelectRoleAsync(roleInfo, OnSelectRoleComplete); - } - - private void OnSelectRoleComplete(RoleInfo roleInfo) - { - context.Post(_ => - { - isDoneWorldRender = false; - isDoneNPCRender = false; - Action actLoadChar = () => - { - if (!isDoneNPCRender || !isDoneWorldRender) - { - return; - } - }; - SceneLoader.SceneLoadProcess = SceneLoadProcess.Loading; - SceneLoader.LoadingProgress = 0; - LoadingSceneController.Instance.ShowLoadingScene(true); -#if TESTFAST - string nameScene = "LoginScene"; - SceneManager.UnloadSceneAsync(nameScene); - isDoneNPCRender = true; - isDoneWorldRender = true; - actLoadChar?.Invoke(); - UnityGameSession.EnterWorldAsync(roleInfo, OnEnterWorldComplete); -#else - string nameScene = "NPCRender"; - UnityGameSession.Instance.LoadScene(nameScene, LoadSceneMode.Single, (value) => - { - isDoneNPCRender = value; - actLoadChar?.Invoke(); - }); - nameScene = "a61"; - UnityGameSession.Instance.LoadScene(nameScene, LoadSceneMode.Additive, (value) => - { - isDoneWorldRender = value; - actLoadChar?.Invoke(); - UnityGameSession.EnterWorldAsync(roleInfo, OnEnterWorldComplete); - - }); -#endif - }, null); - } - - private async void OnEnterWorldComplete() - { - await Task.Delay(2000); - // Request all known packages: 0=Inventory,1=Equipment,2=Task - UnityGameSession.RequestAllInventoriesAsync(() => { /*BMLogger.Log("Sent Inventory Detail Requests (all packs)");*/ }, 0, 1, 2); - await Task.Delay(1000); - UnityGameSession.RequestCheckSecurityPassWd(""); - await Task.Delay(1000); - } - - //private void OnInventoryReceived(List inventoryData) - //{ - // _inventoryUI.DisplayInventory(inventoryData); - //} - -#if UNITY_EDITOR - private void OnValidate() - { - if (_usernameInputField == null) - { - // find childrend with name "username" - _usernameInputField = transform.Find("username").GetComponent(); - } - - if (_passwordInputField == null) - { - // find childrend with name "password" - _passwordInputField = transform.Find("password").GetComponent(); - } - - if (_loginButton == null) - { - // find childrend with name "LoginBtn" - _loginButton = transform.Find("LoginBtn").GetComponent