Merge remote-tracking branch 'origin/develop' into feature/character_info
# Conflicts: # Assets/PerfectWorld/Scripts/Network/CSNetwork/GameSession.cs # Assets/PerfectWorld/Scripts/Network/UnityGameSession.cs # Assets/PerfectWorld/Scripts/UI/Login/LoginScreenUI.cs
This commit is contained in:
@@ -1,5 +1,126 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1 &99051929539797809
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 4915293664251870536}
|
||||
- component: {fileID: 7416811990837147698}
|
||||
- component: {fileID: 6809282891346298764}
|
||||
- component: {fileID: 7010901635634620631}
|
||||
m_Layer: 5
|
||||
m_Name: ButtonNo
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &4915293664251870536
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 99051929539797809}
|
||||
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: 2385775756193422540}
|
||||
m_Father: {fileID: 2782318616460798463}
|
||||
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: 205.9258, y: 56.2433}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &7416811990837147698
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 99051929539797809}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &6809282891346298764
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 99051929539797809}
|
||||
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: 0.14578143, g: 0.7924528, b: 0.1864423, 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: 0}
|
||||
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 &7010901635634620631
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 99051929539797809}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, 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: 6809282891346298764}
|
||||
m_OnClick:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
--- !u!1 &1448650841350251410
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -168,10 +289,10 @@ RectTransform:
|
||||
m_Children: []
|
||||
m_Father: {fileID: 7906706137011413807}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
||||
m_AnchoredPosition: {x: 0, y: -81}
|
||||
m_SizeDelta: {x: 200, y: 50}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 1, y: 1}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 0}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &5808684862484431307
|
||||
CanvasRenderer:
|
||||
@@ -201,7 +322,7 @@ MonoBehaviour:
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_text: OK
|
||||
m_text: "\u0110\u1ED3ng \xDD(Y)"
|
||||
m_isRightToLeft: 0
|
||||
m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
|
||||
m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
|
||||
@@ -228,10 +349,10 @@ MonoBehaviour:
|
||||
m_faceColor:
|
||||
serializedVersion: 2
|
||||
rgba: 4294967295
|
||||
m_fontSize: 36
|
||||
m_fontSize: 44.25
|
||||
m_fontSizeBase: 36
|
||||
m_fontWeight: 400
|
||||
m_enableAutoSizing: 0
|
||||
m_enableAutoSizing: 1
|
||||
m_fontSizeMin: 18
|
||||
m_fontSizeMax: 72
|
||||
m_fontStyle: 0
|
||||
@@ -272,6 +393,70 @@ MonoBehaviour:
|
||||
m_hasFontAssetChanged: 0
|
||||
m_baseMaterial: {fileID: 0}
|
||||
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
|
||||
--- !u!1 &4140524140714306011
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 2782318616460798463}
|
||||
- component: {fileID: 6567280976245013390}
|
||||
m_Layer: 5
|
||||
m_Name: Buttons
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &2782318616460798463
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4140524140714306011}
|
||||
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: 4915293664251870536}
|
||||
- {fileID: 7906706137011413807}
|
||||
m_Father: {fileID: 8578995796031649400}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 1, y: 0}
|
||||
m_AnchoredPosition: {x: 0, y: 41.609}
|
||||
m_SizeDelta: {x: 0, y: 83.217}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!114 &6567280976245013390
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4140524140714306011}
|
||||
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: 4
|
||||
m_Spacing: 11.43
|
||||
m_ChildForceExpandWidth: 0
|
||||
m_ChildForceExpandHeight: 1
|
||||
m_ChildControlWidth: 0
|
||||
m_ChildControlHeight: 0
|
||||
m_ChildScaleWidth: 0
|
||||
m_ChildScaleHeight: 0
|
||||
m_ReverseArrangement: 0
|
||||
--- !u!1 &4839074738306786208
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -285,7 +470,7 @@ GameObject:
|
||||
- component: {fileID: 8250962023850685786}
|
||||
- component: {fileID: 7766051278568089760}
|
||||
m_Layer: 5
|
||||
m_Name: ButtonExit
|
||||
m_Name: ButtonOk
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
@@ -298,18 +483,18 @@ RectTransform:
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4839074738306786208}
|
||||
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: 7677644201189461152}
|
||||
m_Father: {fileID: 8578995796031649400}
|
||||
m_Father: {fileID: 2782318616460798463}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 0, y: 0}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 160, y: 30}
|
||||
m_SizeDelta: {x: 205.9258, y: 56.2433}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &8280971203118505009
|
||||
CanvasRenderer:
|
||||
@@ -332,7 +517,7 @@ MonoBehaviour:
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_Color: {r: 0.14578143, g: 0.7924528, b: 0.1864423, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
@@ -425,10 +610,10 @@ RectTransform:
|
||||
m_Children: []
|
||||
m_Father: {fileID: 8578995796031649400}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
||||
m_AnchoredPosition: {x: 0, y: 3}
|
||||
m_SizeDelta: {x: 200, y: 50}
|
||||
m_AnchorMin: {x: 0, y: 0.5}
|
||||
m_AnchorMax: {x: 1, y: 0.5}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 50}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &655909173274991632
|
||||
CanvasRenderer:
|
||||
@@ -487,10 +672,10 @@ MonoBehaviour:
|
||||
m_faceColor:
|
||||
serializedVersion: 2
|
||||
rgba: 4294967295
|
||||
m_fontSize: 36
|
||||
m_fontSize: 44.75
|
||||
m_fontSizeBase: 36
|
||||
m_fontWeight: 400
|
||||
m_enableAutoSizing: 0
|
||||
m_enableAutoSizing: 1
|
||||
m_fontSizeMin: 18
|
||||
m_fontSizeMax: 72
|
||||
m_fontStyle: 0
|
||||
@@ -562,15 +747,15 @@ RectTransform:
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
- {fileID: 7906706137011413807}
|
||||
- {fileID: 1931146730219979515}
|
||||
- {fileID: 6428994832978992641}
|
||||
- {fileID: 2782318616460798463}
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
||||
m_AnchoredPosition: {x: 0, y: 30.6318}
|
||||
m_SizeDelta: {x: 434.6896, y: 248.9211}
|
||||
m_SizeDelta: {x: 1067.9689, y: 248.9211}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &2243330050876855902
|
||||
CanvasRenderer:
|
||||
@@ -625,3 +810,140 @@ MonoBehaviour:
|
||||
titleText: {fileID: 5031655611580643013}
|
||||
messageText: {fileID: 7448521238108099750}
|
||||
okButton: {fileID: 7766051278568089760}
|
||||
_noButton: {fileID: 7010901635634620631}
|
||||
--- !u!1 &5664175764923475105
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 2385775756193422540}
|
||||
- component: {fileID: 8838082653881325633}
|
||||
- component: {fileID: 438315464709753381}
|
||||
m_Layer: 5
|
||||
m_Name: Text (TMP)
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &2385775756193422540
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5664175764923475105}
|
||||
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: 4915293664251870536}
|
||||
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: 0, y: 0}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &8838082653881325633
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5664175764923475105}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &438315464709753381
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5664175764923475105}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
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: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_text: "H\u1EE7y(N)"
|
||||
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: 4278190080
|
||||
m_fontColor: {r: 0, g: 0, b: 0, 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: 50.3
|
||||
m_fontSizeBase: 36
|
||||
m_fontWeight: 400
|
||||
m_enableAutoSizing: 1
|
||||
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: 0
|
||||
m_wordWrappingRatios: 0.4
|
||||
m_overflowMode: 0
|
||||
m_linkedTextComponent: {fileID: 0}
|
||||
parentLinkedComponent: {fileID: 0}
|
||||
m_enableKerning: 0
|
||||
m_ActiveFontFeatures: 6e72656b
|
||||
m_enableExtraPadding: 0
|
||||
checkPaddingRequired: 0
|
||||
m_isRichText: 1
|
||||
m_EmojiFallbackSupport: 1
|
||||
m_parseCtrlCharacters: 1
|
||||
m_isOrthographic: 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}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -39,3 +39,5 @@ MonoBehaviour:
|
||||
prefab: {fileID: 6310702841431484757, guid: 6620f766cee7c8f4cb00dd457ac77675, type: 3}
|
||||
- id: Win_ArrangeTeam
|
||||
prefab: {fileID: 2452003196178065293, guid: 5a3e828efd5c542469d1f17565205ded, type: 3}
|
||||
- id: DlgMessageBox
|
||||
prefab: {fileID: 5492547392745930423, guid: 54cccb2c6a758a24183474cd385ccb2c, type: 3}
|
||||
|
||||
@@ -0,0 +1,454 @@
|
||||
// EC_AutoPolicy.cs
|
||||
// Converted from EC_AutoPolicy.h / EC_AutoPolicy.cpp
|
||||
|
||||
using BrewMonster.Assets.PerfectWorld.Scripts.Players;
|
||||
using BrewMonster.Network;
|
||||
using CSNetwork.GPDataType;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
public sealed class CECAutoPolicy
|
||||
{
|
||||
// policy type
|
||||
public const int POLICY_AUTOKILLMONSTER = 0;
|
||||
|
||||
// system events
|
||||
public const int EVENT_BEHURT = 1;
|
||||
public const int EVENT_SKILLINTERRUPT = 2;
|
||||
public const int EVENT_RETURNTOWNOK = 3;
|
||||
public const int EVENT_CONFIGCHANGED = 4;
|
||||
|
||||
public struct CONFIG
|
||||
{
|
||||
public int attack_skill;
|
||||
public bool attack_iscombo;
|
||||
public int assist_skill;
|
||||
public bool assist_iscombo;
|
||||
public int nAssistInterval;
|
||||
public int nTime;
|
||||
public int iAutoPickMode; // 0 none, 1 all, 2 only money
|
||||
public int nPetrolRadius;
|
||||
|
||||
public CONFIG(bool _ = true)
|
||||
{
|
||||
attack_skill = 0;
|
||||
attack_iscombo = false;
|
||||
assist_skill = 0;
|
||||
assist_iscombo = false;
|
||||
nAssistInterval = 60000;
|
||||
nTime = 3600000;
|
||||
iAutoPickMode = 0;
|
||||
nPetrolRadius = 500;
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly CECAutoPolicy _instance = new CECAutoPolicy();
|
||||
public static CECAutoPolicy GetInstance() => _instance;
|
||||
|
||||
private CONFIG m_Config;
|
||||
private CECPlayerWrapper m_pPlayer;
|
||||
private string m_strCurPolicy;
|
||||
|
||||
private readonly CECCounter m_cntTick;
|
||||
private uint m_dwKeepingTime;
|
||||
private uint m_dwCurrentTime;
|
||||
|
||||
private CECAutoPolicy()
|
||||
{
|
||||
m_pPlayer = null;
|
||||
m_cntTick = new CECCounter(); // 100ms => 10 ticks/sec
|
||||
m_cntTick.SetPeriod(100);
|
||||
m_dwKeepingTime = 0;
|
||||
m_dwCurrentTime = 0;
|
||||
m_strCurPolicy = string.Empty;
|
||||
m_Config = new CONFIG();
|
||||
}
|
||||
|
||||
public bool Init()
|
||||
{
|
||||
// load lua file list: configs/autopolicy/allfiles.txt
|
||||
// (token-based in C++; here read whitespace tokens)
|
||||
var listPath = Path.Combine("configs", "autopolicy", "allfiles.txt");
|
||||
if (!File.Exists(listPath))
|
||||
{
|
||||
// a_LogOutput equivalent: adapt in your project
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (var line in File.ReadLines(listPath))
|
||||
{
|
||||
var s = line.Trim();
|
||||
if (string.IsNullOrEmpty(s)) continue;
|
||||
if (s.StartsWith("#") || s.StartsWith("//")) continue;
|
||||
|
||||
// token 0
|
||||
var parts = s.Split((char[])null, StringSplitOptions.RemoveEmptyEntries);
|
||||
if (parts.Length == 0) continue;
|
||||
|
||||
var luaFile = Path.Combine("configs", "autopolicy", parts[0]);
|
||||
LoadLuaFile(luaFile);
|
||||
}
|
||||
|
||||
// Register player API: _InitPlayerAPI(g_LuaStateMan.GetAIState());
|
||||
AutoPolicyLuaHooks.InitPlayerAPI?.Invoke();
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Release()
|
||||
{
|
||||
m_pPlayer = null;
|
||||
}
|
||||
|
||||
public void OnEnterWorld()
|
||||
{
|
||||
if (m_pPlayer == null)
|
||||
m_pPlayer = new CECPlayerWrapper(EC_Game.GetGameRun().GetHostPlayer());
|
||||
|
||||
LoadConfigData();
|
||||
}
|
||||
|
||||
public void OnLeaveWorld()
|
||||
{
|
||||
if (m_pPlayer != null)
|
||||
{
|
||||
SaveConfigData();
|
||||
m_pPlayer = null;
|
||||
}
|
||||
|
||||
SetCurPolicy(string.Empty);
|
||||
m_dwCurrentTime = 0;
|
||||
}
|
||||
|
||||
public void Tick(uint dwDeltaTime)
|
||||
{
|
||||
if (EC_Game.GetGameRun().GetGameState() != (int)GameState.GS_GAME)
|
||||
return;
|
||||
|
||||
m_pPlayer?.Tick(dwDeltaTime);
|
||||
|
||||
if (m_cntTick.IncCounter(dwDeltaTime))
|
||||
{
|
||||
var args = new List<CScriptValue> { new CScriptValue((double)m_dwKeepingTime) };
|
||||
var ret = new List<CScriptValue>();
|
||||
CallLuaFunc("AIManager", "OnTick", args, ret);
|
||||
|
||||
m_cntTick.Reset();
|
||||
m_dwKeepingTime = 0;
|
||||
}
|
||||
|
||||
m_dwKeepingTime += dwDeltaTime;
|
||||
if (IsAutoPolicyEnabled())
|
||||
m_dwCurrentTime += dwDeltaTime;
|
||||
}
|
||||
|
||||
public void Render()
|
||||
{
|
||||
// C++ draws debug text with A3DFont. Implement your own debug UI if needed.
|
||||
// In C++ it uses: m_pPlayer.m_iAttackErrCnt / m_iPickupErrCnt / action queue list
|
||||
}
|
||||
|
||||
public void StartPolicy(int policyType)
|
||||
{
|
||||
string[] policyMap =
|
||||
{
|
||||
"AutoKillMonster", // POLICY_AUTOKILLMONSTER
|
||||
};
|
||||
|
||||
// FIXED: original C++ has a sizeof bug. Correct is policyMap.Length.
|
||||
if (policyType < 0 || policyType >= policyMap.Length)
|
||||
return;
|
||||
|
||||
string policyName = policyMap[policyType];
|
||||
SetCurPolicy(policyName);
|
||||
m_dwCurrentTime = 0;
|
||||
|
||||
if (m_pPlayer != null)
|
||||
{
|
||||
m_pPlayer.GetHostPlayer().ClearComboSkill();
|
||||
m_pPlayer.SetOrigPos(m_pPlayer.GetHostPlayer().GetPos());
|
||||
}
|
||||
|
||||
var pGameUI = EC_Game.GetGameRun().GetUIManager().GetInGameUIMan();
|
||||
//pGameUI?.AddChatMessage(pGameUI.GetStringFromTable(10920), EC_GPDataType.GP_CHAT_MISC);
|
||||
}
|
||||
// Put this inside CECAutoPolicy class
|
||||
|
||||
private void SetCurPolicy(string strPolicy)
|
||||
{
|
||||
// normalize null
|
||||
strPolicy ??= string.Empty;
|
||||
|
||||
// no change
|
||||
if (string.Equals(m_strCurPolicy, strPolicy, StringComparison.Ordinal))
|
||||
return;
|
||||
|
||||
// stop old policy (if any)
|
||||
if (!string.IsNullOrEmpty(m_strCurPolicy))
|
||||
{
|
||||
// Try a few common Lua callbacks (depending on your lua side implementation).
|
||||
// You can keep only the one that exists in your project.
|
||||
try
|
||||
{
|
||||
CallLuaFunc("AIManager", "OnStopPolicy",
|
||||
new List<CScriptValue> { new CScriptValue(m_strCurPolicy) }, null);
|
||||
}
|
||||
catch { /* ignore if function not exist */ }
|
||||
|
||||
try
|
||||
{
|
||||
CallLuaFunc("AIManager", "OnChangePolicy",
|
||||
new List<CScriptValue> { new CScriptValue(m_strCurPolicy), new CScriptValue(strPolicy) }, null);
|
||||
}
|
||||
catch { /* ignore if function not exist */ }
|
||||
}
|
||||
|
||||
// assign
|
||||
m_strCurPolicy = strPolicy;
|
||||
|
||||
// start new policy (if any)
|
||||
if (!string.IsNullOrEmpty(m_strCurPolicy))
|
||||
{
|
||||
try
|
||||
{
|
||||
CallLuaFunc("AIManager", "OnStartPolicy",
|
||||
new List<CScriptValue> { new CScriptValue(m_strCurPolicy) }, null);
|
||||
}
|
||||
catch { /* ignore if function not exist */ }
|
||||
}
|
||||
}
|
||||
public void StopPolicy()
|
||||
{
|
||||
SetCurPolicy(string.Empty);
|
||||
m_pPlayer?.OnStopPolicy();
|
||||
m_dwCurrentTime = 0;
|
||||
|
||||
var pGameUI = EC_Game.GetGameRun().GetUIManager().GetInGameUIMan();
|
||||
//pGameUI?.AddChatMessage(pGameUI.GetStringFromTable(10921), ChatChannel.GP_CHAT_MISC);
|
||||
}
|
||||
|
||||
public void SendEvent_BeHurt(int attacker)
|
||||
{
|
||||
var args = new List<CScriptValue>
|
||||
{
|
||||
new CScriptValue((double)EVENT_BEHURT),
|
||||
new CScriptValue((double)attacker),
|
||||
};
|
||||
CallLuaFunc("AIManager", "OnEvent", args, null);
|
||||
|
||||
if (GPDataTypeHelper.ISNPCID(attacker) && m_pPlayer != null)
|
||||
m_pPlayer.OnMonsterAttackMe(attacker);
|
||||
}
|
||||
|
||||
public void SendEvent_SkillInterrupt(int skill_id)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void SendEvent_ReturnTown()
|
||||
{
|
||||
var args = new List<CScriptValue>
|
||||
{
|
||||
new CScriptValue((double)EVENT_RETURNTOWNOK),
|
||||
};
|
||||
CallLuaFunc("AIManager", "OnEvent", args, null);
|
||||
}
|
||||
|
||||
public void SendEvent_ConfigChanged()
|
||||
{
|
||||
var args = new List<CScriptValue>
|
||||
{
|
||||
new CScriptValue((double)EVENT_CONFIGCHANGED),
|
||||
};
|
||||
CallLuaFunc("AIManager", "OnEvent", args, null);
|
||||
|
||||
// C++: m_pPlayer->m_InvalidObj.clear();
|
||||
// In C# wrapper keeps it protected; clear via StopPolicy-style reset or expose method if you want exact parity.
|
||||
// If you need exact parity, add a method on wrapper to ClearInvalidObj().
|
||||
}
|
||||
|
||||
public CECPlayerWrapper GetPlayerWrapper() => m_pPlayer;
|
||||
|
||||
public bool IsAutoPolicyEnabled() => !string.IsNullOrEmpty(m_strCurPolicy);
|
||||
|
||||
public string GetCurPolicy() => m_strCurPolicy;
|
||||
|
||||
public CONFIG GetConfigData() => m_Config;
|
||||
|
||||
public void SetConfigData(CONFIG data)
|
||||
{
|
||||
m_Config = data;
|
||||
SaveConfigData();
|
||||
}
|
||||
|
||||
public uint GetRemainTime()
|
||||
{
|
||||
if (m_Config.nTime > (int)m_dwCurrentTime)
|
||||
return (uint)(m_Config.nTime - (int)m_dwCurrentTime);
|
||||
return 0;
|
||||
}
|
||||
|
||||
private bool LoadLuaFile(string filename)
|
||||
{
|
||||
// C++ uses LuaState lock + RegisterFile. Provide hooks.
|
||||
return AutoPolicyLuaHooks.RegisterFile?.Invoke(filename) ?? false;
|
||||
}
|
||||
|
||||
private void CallLuaFunc(string szTable, string szName, List<CScriptValue> args, List<CScriptValue> ret)
|
||||
{
|
||||
AutoPolicyLuaHooks.CallLua?.Invoke(szTable, szName, args, ret);
|
||||
}
|
||||
|
||||
private bool LoadConfigData()
|
||||
{
|
||||
if (m_pPlayer == null) return false;
|
||||
|
||||
string strFile = Path.Combine("userdata", "autopolicy", $"{m_pPlayer.GetHostPlayer().GetCharacterID()}.ini");
|
||||
|
||||
if (!File.Exists(strFile))
|
||||
{
|
||||
SaveConfigData();
|
||||
return false;
|
||||
}
|
||||
|
||||
var ini = SimpleIni.Load(strFile);
|
||||
|
||||
m_Config.attack_skill = ini.GetInt("config", "attack_skill", 0);
|
||||
m_Config.attack_iscombo = ini.GetBool("config", "attack_iscombo", false);
|
||||
m_Config.assist_skill = ini.GetInt("config", "assist_skill", 0);
|
||||
m_Config.assist_iscombo = ini.GetBool("config", "assist_iscombo", false);
|
||||
m_Config.nAssistInterval = ini.GetInt("config", "assist_interval", 60000);
|
||||
m_Config.nTime = ini.GetInt("config", "keeping_time", 3600000);
|
||||
m_Config.iAutoPickMode = ini.GetInt("config", "autopick", 1);
|
||||
m_Config.nPetrolRadius = ini.GetInt("config", "petrol_radius", 500);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void SaveConfigData()
|
||||
{
|
||||
Directory.CreateDirectory(Path.Combine("userdata", "autopolicy"));
|
||||
|
||||
var ini = new SimpleIni();
|
||||
ini.SetInt("config", "attack_skill", m_Config.attack_skill);
|
||||
ini.SetBool("config", "attack_iscombo", m_Config.attack_iscombo);
|
||||
ini.SetInt("config", "assist_skill", m_Config.assist_skill);
|
||||
ini.SetBool("config", "assist_iscombo", m_Config.assist_iscombo);
|
||||
ini.SetInt("config", "assist_interval", m_Config.nAssistInterval);
|
||||
ini.SetInt("config", "keeping_time", m_Config.nTime);
|
||||
ini.SetInt("config", "autopick", m_Config.iAutoPickMode);
|
||||
ini.SetInt("config", "petrol_radius", m_Config.nPetrolRadius);
|
||||
|
||||
if (m_pPlayer != null)
|
||||
{
|
||||
string strFile = Path.Combine("userdata", "autopolicy", $"{m_pPlayer.GetHostPlayer().GetCharacterID()}.ini");
|
||||
ini.Save(strFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ===================== Hooks & tiny helpers =====================
|
||||
// Keep these minimal; replace by your real Lua + script value types.
|
||||
|
||||
public static class AutoPolicyLuaHooks
|
||||
{
|
||||
// return true if file registered/loaded
|
||||
public static Func<string, bool> RegisterFile;
|
||||
|
||||
// table, func, args, ret (ret can be null)
|
||||
public static Action<string, string, List<CScriptValue>, List<CScriptValue>> CallLua;
|
||||
|
||||
public static Action InitPlayerAPI;
|
||||
}
|
||||
|
||||
// Minimal script value
|
||||
public readonly struct CScriptValue
|
||||
{
|
||||
public readonly object Value;
|
||||
public CScriptValue(object v) { Value = v; }
|
||||
}
|
||||
|
||||
// Very small INI helper (enough for this file)
|
||||
public sealed class SimpleIni
|
||||
{
|
||||
private readonly Dictionary<string, Dictionary<string, string>> _data = new(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
public static SimpleIni Load(string path)
|
||||
{
|
||||
var ini = new SimpleIni();
|
||||
string section = "";
|
||||
foreach (var raw in File.ReadLines(path))
|
||||
{
|
||||
var line = raw.Trim();
|
||||
if (line.Length == 0) continue;
|
||||
if (line.StartsWith(";") || line.StartsWith("#") || line.StartsWith("//")) continue;
|
||||
|
||||
if (line.StartsWith("[") && line.EndsWith("]"))
|
||||
{
|
||||
section = line.Substring(1, line.Length - 2).Trim();
|
||||
if (!ini._data.ContainsKey(section))
|
||||
ini._data[section] = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
continue;
|
||||
}
|
||||
|
||||
int eq = line.IndexOf('=');
|
||||
if (eq <= 0) continue;
|
||||
|
||||
string key = line.Substring(0, eq).Trim();
|
||||
string val = line.Substring(eq + 1).Trim();
|
||||
|
||||
if (!ini._data.TryGetValue(section, out var dict))
|
||||
{
|
||||
dict = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
ini._data[section] = dict;
|
||||
}
|
||||
|
||||
dict[key] = val;
|
||||
}
|
||||
|
||||
return ini;
|
||||
}
|
||||
|
||||
public int GetInt(string section, string key, int def)
|
||||
{
|
||||
if (_data.TryGetValue(section, out var s) && s.TryGetValue(key, out var v) && int.TryParse(v, out var r))
|
||||
return r;
|
||||
return def;
|
||||
}
|
||||
|
||||
public bool GetBool(string section, string key, bool def)
|
||||
{
|
||||
if (_data.TryGetValue(section, out var s) && s.TryGetValue(key, out var v))
|
||||
{
|
||||
if (v == "1") return true;
|
||||
if (v == "0") return false;
|
||||
if (bool.TryParse(v, out var r)) return r;
|
||||
}
|
||||
return def;
|
||||
}
|
||||
|
||||
public void SetInt(string section, string key, int value) => Set(section, key, value.ToString());
|
||||
public void SetBool(string section, string key, bool value) => Set(section, key, value ? "1" : "0");
|
||||
|
||||
private void Set(string section, string key, string value)
|
||||
{
|
||||
if (!_data.TryGetValue(section, out var s))
|
||||
{
|
||||
s = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
_data[section] = s;
|
||||
}
|
||||
s[key] = value;
|
||||
}
|
||||
|
||||
public void Save(string path)
|
||||
{
|
||||
using var sw = new StreamWriter(path);
|
||||
foreach (var sect in _data)
|
||||
{
|
||||
sw.WriteLine($"[{sect.Key}]");
|
||||
foreach (var kv in sect.Value)
|
||||
sw.WriteLine($"{kv.Key}={kv.Value}");
|
||||
sw.WriteLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: df3c9b50fb2b12f4889649c8666fa10e
|
||||
@@ -1875,7 +1875,6 @@ namespace ModelRenderer.Scripts.GameData
|
||||
// }
|
||||
// return id;
|
||||
//}
|
||||
|
||||
public object[] GetAllDataOfType(ID_SPACE idSpace, DATA_TYPE dataType)
|
||||
{
|
||||
List<object> results = new List<object>();
|
||||
|
||||
@@ -787,6 +787,11 @@ namespace BrewMonster
|
||||
|
||||
public void DefaultUserSettings(ref EC_SYSTEM_SETTING pss, ref EC_VIDEO_SETTING pvs, ref EC_GAME_SETTING pgs, ref EC_BLACKLIST_SETTING pbs, ref EC_COMPUTER_AIDED_SETTING pcas)
|
||||
{
|
||||
pss = new EC_SYSTEM_SETTING();
|
||||
pvs = new EC_VIDEO_SETTING();
|
||||
pgs = new EC_GAME_SETTING();
|
||||
pbs = new EC_BLACKLIST_SETTING();
|
||||
pcas = new EC_COMPUTER_AIDED_SETTING();
|
||||
pss.Reset();
|
||||
pvs.Reset();
|
||||
pgs.Reset();
|
||||
@@ -1075,7 +1080,7 @@ namespace BrewMonster
|
||||
using (BinaryReader reader = new BinaryReader(ms))
|
||||
{
|
||||
uint dwVer = reader.ReadUInt32();
|
||||
|
||||
|
||||
if (dwVer < 15)
|
||||
{
|
||||
DefaultUserConfigData();
|
||||
@@ -1115,9 +1120,9 @@ namespace BrewMonster
|
||||
// Note: Would need EC_Game reference
|
||||
// g_pGame->GetA3DGFXExMan()->SetPriority(m_vs.nEffect);
|
||||
// Send force attack to server
|
||||
/* byte forceAttack = glb_BuildPVPMask(false);
|
||||
byte refuseBless = glb_BuildRefuseBLSMask();
|
||||
UnityGameSession.Instance.c2s_CmdNotifyForceAttack(forceAttack, refuseBless);*/
|
||||
byte forceAttack = EC_Utility.glb_BuildPVPMask(false);
|
||||
byte refuseBless = EC_Utility.glb_BuildRefuseBLSMask();
|
||||
UnityGameSession.c2s_SendCmdNotifyForceAttack(forceAttack, refuseBless);
|
||||
}
|
||||
|
||||
public void SetSceneLoadRadius(float fRadius)
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace BrewMonster
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1c12399ff0e62e146b5951b866e5ab91
|
||||
@@ -17,5 +17,10 @@ namespace BrewMonster
|
||||
if (_instance.IsValueCreated)
|
||||
throw new InvalidOperationException($"Singleton<{typeof(T).Name}> already created!");
|
||||
}
|
||||
|
||||
protected virtual void Initialize()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+24
-22
@@ -17,9 +17,9 @@ namespace PerfectWorld.Scripts.Managers
|
||||
/// <summary>
|
||||
/// Arrow item class (cac loai mui ten)
|
||||
/// </summary>
|
||||
public class EC_IvtrArrow : EC_IvtrEquip
|
||||
public class CECIvtrArrow : EC_IvtrEquip
|
||||
{
|
||||
protected IVTR_ESSENCE_ARROW m_Essence; // Arrow essence data
|
||||
protected IVTR_ESSENCE_ARROW m_Essence; // Arrow essence data
|
||||
|
||||
// Data in database
|
||||
protected PROJECTILE_TYPE m_pDBType;
|
||||
@@ -29,30 +29,30 @@ namespace PerfectWorld.Scripts.Managers
|
||||
/// </summary>
|
||||
/// <param name="tid">Template id</param>
|
||||
/// <param name="expire_date">Expire date</param>
|
||||
public EC_IvtrArrow(int tid, int expire_date) : base(tid, expire_date)
|
||||
public CECIvtrArrow(int tid, int expire_date) : base(tid, expire_date)
|
||||
{
|
||||
m_iCID = (int)InventoryClassId.ICID_ARROW;
|
||||
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_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;
|
||||
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)
|
||||
public CECIvtrArrow(CECIvtrArrow other) : base(other)
|
||||
{
|
||||
m_pDBType = other.m_pDBType;
|
||||
m_pDBEssence = other.m_pDBEssence;
|
||||
m_Essence = other.m_Essence;
|
||||
m_pDBType = other.m_pDBType;
|
||||
m_pDBEssence = other.m_pDBEssence;
|
||||
m_Essence = other.m_Essence;
|
||||
}
|
||||
|
||||
public override bool SetItemInfo(byte[] pInfoData, int iDataLen)
|
||||
@@ -67,11 +67,11 @@ namespace PerfectWorld.Scripts.Managers
|
||||
CECDataReader dr = new CECDataReader(pInfoData, iDataLen);
|
||||
|
||||
// Skip equip requirements and endurance
|
||||
dr.Offset(5 * sizeof (int), CECDataReader.SEEK_CUR);
|
||||
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)
|
||||
@@ -105,6 +105,8 @@ namespace PerfectWorld.Scripts.Managers
|
||||
}
|
||||
return base.GetName(); // Fallback to base class method
|
||||
}
|
||||
public IVTR_ESSENCE_ARROW GetEssence() { return m_Essence; }
|
||||
public PROJECTILE_TYPE GetDBSubType() { return m_pDBType; }
|
||||
|
||||
// Get item description text
|
||||
protected override string GetNormalDesc(bool bRepair)
|
||||
@@ -128,22 +130,22 @@ namespace PerfectWorld.Scripts.Managers
|
||||
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,
|
||||
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)
|
||||
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;
|
||||
@@ -153,7 +155,7 @@ namespace PerfectWorld.Scripts.Managers
|
||||
|
||||
// Suite description
|
||||
AddSuiteDesc();
|
||||
|
||||
|
||||
// Extend description
|
||||
AddExtDescText();
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f479e02d3a184f94bb046bc6cbf64ba1
|
||||
+39
-3
@@ -67,7 +67,7 @@ namespace PerfectWorld.Scripts.Managers
|
||||
/// <summary>
|
||||
/// Weapon item class (cac loai vu khi)
|
||||
/// </summary>
|
||||
public class EC_IvtrWeapon : EC_IvtrEquip
|
||||
public class CECIvtrWeapon : EC_IvtrEquip
|
||||
{
|
||||
//Attributes
|
||||
//Weapon essence data
|
||||
@@ -82,7 +82,7 @@ namespace PerfectWorld.Scripts.Managers
|
||||
/// Constructor for weapon item (cac loai vu khi)
|
||||
/// </summary>
|
||||
/// <param name="tid">Template id</param>
|
||||
public EC_IvtrWeapon(int tid, int expire_date) : base(tid, expire_date)
|
||||
public CECIvtrWeapon(int tid, int expire_date) : base(tid, expire_date)
|
||||
{
|
||||
m_iCID = (int)InventoryClassId.ICID_WEAPON;
|
||||
elementdataman pDB = ElementDataManProvider.GetElementDataMan();
|
||||
@@ -100,7 +100,7 @@ namespace PerfectWorld.Scripts.Managers
|
||||
RepairFee = m_pDBEssence.repairfee;
|
||||
ReputationReq = m_pDBEssence.require_reputation;
|
||||
}
|
||||
public EC_IvtrWeapon(EC_IvtrWeapon other) : base(other)
|
||||
public CECIvtrWeapon(CECIvtrWeapon other) : base(other)
|
||||
{
|
||||
m_pDBEssence = other.m_pDBEssence;
|
||||
m_pDBMajorType = other.m_pDBMajorType;
|
||||
@@ -437,5 +437,41 @@ namespace PerfectWorld.Scripts.Managers
|
||||
{
|
||||
return m_Essence.weapon_level;
|
||||
}
|
||||
|
||||
// Clone item
|
||||
public override EC_IvtrItem Clone()
|
||||
{
|
||||
return new CECIvtrWeapon(this);
|
||||
}
|
||||
|
||||
// Get equipment type
|
||||
public virtual int GetEquipmentType()
|
||||
{
|
||||
return 0; // EQUIP_WEAPON = 0
|
||||
}
|
||||
|
||||
// The weapon is range weapon ?
|
||||
public bool IsRangeWeapon()
|
||||
{
|
||||
return m_Essence.weapon_type == (int)WEAPON_TYPE.WEAPON_TYPE_RANGE;
|
||||
}
|
||||
|
||||
// Get essence data
|
||||
public IVTR_ESSENCE_WEAPON GetEssence()
|
||||
{
|
||||
return m_Essence;
|
||||
}
|
||||
|
||||
// Get database data
|
||||
public WEAPON_MAJOR_TYPE GetDBMajorType()
|
||||
{
|
||||
return m_pDBMajorType;
|
||||
}
|
||||
|
||||
public WEAPON_SUB_TYPE GetDBSubType()
|
||||
{
|
||||
return m_pDBSubType;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d252cb1fcb2e946688fd6836548fd0d4
|
||||
@@ -165,8 +165,9 @@ namespace PerfectWorld.Scripts.Managers
|
||||
}
|
||||
|
||||
// Get item cool time
|
||||
public int GetCoolTime(ref int piMax)
|
||||
public override int GetCoolTime(out int piMax)
|
||||
{
|
||||
piMax = 0;
|
||||
CECHostPlayer pHost = EC_Game.GetGameRun().GetHostPlayer();
|
||||
return pHost != null ? pHost.GetCoolTime((int)CoolTimeIndex.GP_CT_AUTOMP, out piMax) : 0;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@ namespace PerfectWorld.Scripts.Managers
|
||||
{
|
||||
public class EC_IvtrGeneralCard : EC_IvtrItem
|
||||
{
|
||||
private IVTR_ESSENCE_GENERALCARD m_Essence;
|
||||
|
||||
/// <summary>
|
||||
/// Not create logic yet (add summary later)
|
||||
/// </summary>
|
||||
@@ -15,6 +17,11 @@ namespace PerfectWorld.Scripts.Managers
|
||||
public EC_IvtrGeneralCard(EC_IvtrGeneralCard other) : base(other)
|
||||
{
|
||||
}
|
||||
|
||||
public IVTR_ESSENCE_GENERALCARD GetEssence()
|
||||
{
|
||||
return m_Essence;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ namespace BrewMonster.Scripts.Managers
|
||||
if (edm == null) return CacheAndReturn(templateId, "");
|
||||
uint id = unchecked((uint)templateId);
|
||||
DATA_TYPE dATA_TYPE = default;
|
||||
object data = edm.get_data_ptr(id, ID_SPACE.ID_SPACE_ESSENCE,ref dATA_TYPE);
|
||||
object data = edm.get_data_ptr(id, ID_SPACE.ID_SPACE_ESSENCE, ref dATA_TYPE);
|
||||
string name = ExtractNameFromElement(data);
|
||||
if (string.IsNullOrEmpty(name))
|
||||
{
|
||||
@@ -107,15 +107,15 @@ namespace BrewMonster.Scripts.Managers
|
||||
private Sprite LoadIconSpriteByKey(string key)
|
||||
{
|
||||
if (string.IsNullOrEmpty(key)) return null;
|
||||
|
||||
|
||||
// Load multi-sprite atlas if not already loaded
|
||||
if (_multiSpriteAtlas == null)
|
||||
{
|
||||
LoadMultiSpriteAtlas();
|
||||
}
|
||||
|
||||
|
||||
if (_multiSpriteAtlas == null) return null;
|
||||
|
||||
|
||||
// Try to find sprite by name in the atlas
|
||||
if (_spriteNameToIndexCache.TryGetValue(key, out var index))
|
||||
{
|
||||
@@ -124,7 +124,7 @@ namespace BrewMonster.Scripts.Managers
|
||||
return _multiSpriteAtlas[index];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Fallback: try to find by name directly in the atlas
|
||||
foreach (var sprite in _multiSpriteAtlas)
|
||||
{
|
||||
@@ -133,7 +133,7 @@ namespace BrewMonster.Scripts.Managers
|
||||
return sprite;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Try lowercase/uppercase variants as fallback
|
||||
foreach (var sprite in _multiSpriteAtlas)
|
||||
{
|
||||
@@ -143,10 +143,10 @@ namespace BrewMonster.Scripts.Managers
|
||||
return sprite;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private void LoadMultiSpriteAtlas()
|
||||
{
|
||||
try
|
||||
@@ -156,7 +156,7 @@ namespace BrewMonster.Scripts.Managers
|
||||
if (atlasSprites != null && atlasSprites.Length > 0)
|
||||
{
|
||||
_multiSpriteAtlas = atlasSprites;
|
||||
|
||||
|
||||
// Build name-to-index cache for faster lookups
|
||||
_spriteNameToIndexCache.Clear();
|
||||
for (int i = 0; i < atlasSprites.Length; i++)
|
||||
@@ -166,7 +166,7 @@ namespace BrewMonster.Scripts.Managers
|
||||
_spriteNameToIndexCache[atlasSprites[i].name] = i;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -280,7 +280,7 @@ namespace BrewMonster.Scripts.Managers
|
||||
{
|
||||
if (data == null) return "";
|
||||
var t = data.GetType();
|
||||
|
||||
|
||||
// Debug: Log all available fields and properties
|
||||
// Debug.Log($"[Inventory] Data type: {t.Name}");
|
||||
var fields = t.GetFields(BindingFlags.Public | BindingFlags.Instance);
|
||||
@@ -301,7 +301,7 @@ namespace BrewMonster.Scripts.Managers
|
||||
// Debug.Log($"[Inventory] Method: {m.Name} ({m.ReturnType.Name})");
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
// Prefer decoding the raw fields first to control encoding (Unicode for Vietnamese),
|
||||
// then fall back to any string properties if needed.
|
||||
var fieldName = t.GetField("name", BindingFlags.Public | BindingFlags.Instance);
|
||||
@@ -313,7 +313,7 @@ namespace BrewMonster.Scripts.Managers
|
||||
{
|
||||
var rawData = string.Join(",", arr.Take(Math.Min(10, arr.Length)));
|
||||
}
|
||||
|
||||
|
||||
// Vietnamese names are stored as wide chars; decode as Unicode first.
|
||||
var s = ByteToStringUtils.UshortArrayToUnicodeString(arr);
|
||||
// Debug log to see what we're getting
|
||||
@@ -476,62 +476,62 @@ namespace BrewMonster.Scripts.Managers
|
||||
return hex;
|
||||
}
|
||||
|
||||
public int GetPileLimit(int templateId)
|
||||
{
|
||||
if (templateId <= 0) return 1;
|
||||
if (_pileLimitCache.TryGetValue(templateId, out var cached)) return cached;
|
||||
int limit = 1;
|
||||
try
|
||||
{
|
||||
var edm = ElementDataManProvider.GetElementDataMan();
|
||||
if (edm != null)
|
||||
{
|
||||
uint id = unchecked((uint)templateId);
|
||||
DATA_TYPE dt = DATA_TYPE.DT_INVALID;
|
||||
object data = edm.get_data_ptr(id, ID_SPACE.ID_SPACE_ESSENCE, ref dt);
|
||||
limit = ExtractPileLimitFromElement(data);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
if (limit <= 0) limit = 1;
|
||||
_pileLimitCache[templateId] = limit;
|
||||
return limit;
|
||||
}
|
||||
public int GetPileLimit(int templateId)
|
||||
{
|
||||
if (templateId <= 0) return 1;
|
||||
if (_pileLimitCache.TryGetValue(templateId, out var cached)) return cached;
|
||||
int limit = 1;
|
||||
try
|
||||
{
|
||||
var edm = ElementDataManProvider.GetElementDataMan();
|
||||
if (edm != null)
|
||||
{
|
||||
uint id = unchecked((uint)templateId);
|
||||
DATA_TYPE dt = DATA_TYPE.DT_INVALID;
|
||||
object data = edm.get_data_ptr(id, ID_SPACE.ID_SPACE_ESSENCE, ref dt);
|
||||
limit = ExtractPileLimitFromElement(data);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
if (limit <= 0) limit = 1;
|
||||
_pileLimitCache[templateId] = limit;
|
||||
return limit;
|
||||
}
|
||||
|
||||
private int ExtractPileLimitFromElement(object data)
|
||||
{
|
||||
if (data == null) return 1;
|
||||
var t = data.GetType();
|
||||
// Common field/property names across item essences
|
||||
string[] names = new[]
|
||||
{
|
||||
"pilelimit", "pile_limit", "pileLimit", "stack", "stack_max", "stackMax", "max_stack", "maxStack"
|
||||
};
|
||||
foreach (var name in names)
|
||||
{
|
||||
var f = t.GetField(name, BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);
|
||||
if (f != null && (f.FieldType == typeof(int) || f.FieldType == typeof(uint) || f.FieldType == typeof(short) || f.FieldType == typeof(ushort) || f.FieldType == typeof(byte)))
|
||||
{
|
||||
try
|
||||
{
|
||||
var val = f.GetValue(data);
|
||||
int limit = Convert.ToInt32(val);
|
||||
if (limit > 0) return limit;
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
var p = t.GetProperty(name, BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);
|
||||
if (p != null && (p.PropertyType == typeof(int) || p.PropertyType == typeof(uint) || p.PropertyType == typeof(short) || p.PropertyType == typeof(ushort) || p.PropertyType == typeof(byte)))
|
||||
{
|
||||
try
|
||||
{
|
||||
var val = p.GetValue(data, null);
|
||||
int limit = Convert.ToInt32(val);
|
||||
if (limit > 0) return limit;
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
private int ExtractPileLimitFromElement(object data)
|
||||
{
|
||||
if (data == null) return 1;
|
||||
var t = data.GetType();
|
||||
// Common field/property names across item essences
|
||||
string[] names = new[]
|
||||
{
|
||||
"pilelimit", "pile_limit", "pileLimit", "stack", "stack_max", "stackMax", "max_stack", "maxStack"
|
||||
};
|
||||
foreach (var name in names)
|
||||
{
|
||||
var f = t.GetField(name, BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);
|
||||
if (f != null && (f.FieldType == typeof(int) || f.FieldType == typeof(uint) || f.FieldType == typeof(short) || f.FieldType == typeof(ushort) || f.FieldType == typeof(byte)))
|
||||
{
|
||||
try
|
||||
{
|
||||
var val = f.GetValue(data);
|
||||
int limit = Convert.ToInt32(val);
|
||||
if (limit > 0) return limit;
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
var p = t.GetProperty(name, BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);
|
||||
if (p != null && (p.PropertyType == typeof(int) || p.PropertyType == typeof(uint) || p.PropertyType == typeof(short) || p.PropertyType == typeof(ushort) || p.PropertyType == typeof(byte)))
|
||||
{
|
||||
try
|
||||
{
|
||||
var val = p.GetValue(data, null);
|
||||
int limit = Convert.ToInt32(val);
|
||||
if (limit > 0) return limit;
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -703,6 +703,7 @@ namespace BrewMonster.Scripts.Managers
|
||||
public string m_strDesc = ""; // Item description
|
||||
public bool m_bIsInNPCPack; // true, this item is in NPC package
|
||||
public bool m_bLocalDetailData; // true, data from GetDetailDataFromLocal
|
||||
public int m_iCurEndurance; // Current endurance
|
||||
|
||||
public EC_Inventory m_pDescIvtr; // Inventory only used to get item description
|
||||
|
||||
@@ -738,6 +739,8 @@ namespace BrewMonster.Scripts.Managers
|
||||
m_bIsInNPCPack = false;
|
||||
m_bLocalDetailData = false;
|
||||
m_pDescIvtr = null;
|
||||
m_iCurEndurance = 0;
|
||||
|
||||
}
|
||||
|
||||
public EC_IvtrItem(int tid, int expire_date)
|
||||
@@ -810,15 +813,14 @@ 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);
|
||||
//Active this to log the data type of item when creating an item
|
||||
//Debug.Log("Create item data: DataType: " + DataType + " tid: " + tid );
|
||||
switch(DataType)
|
||||
//Debug.Log("Create item data: DataType: " + DataType);
|
||||
switch (DataType)
|
||||
{
|
||||
case DATA_TYPE.DT_WEAPON_ESSENCE:
|
||||
pItem = new EC_IvtrWeapon(tid, expire_date);
|
||||
pItem = new CECIvtrWeapon(tid, expire_date);
|
||||
break;
|
||||
case DATA_TYPE.DT_PROJECTILE_ESSENCE:
|
||||
pItem = new EC_IvtrArrow(tid, expire_date);
|
||||
pItem = new CECIvtrArrow(tid, expire_date);
|
||||
break;
|
||||
case DATA_TYPE.DT_ARMOR_ESSENCE:
|
||||
pItem = new EC_IvtrArmor(tid, expire_date);
|
||||
@@ -1262,6 +1264,7 @@ namespace BrewMonster.Scripts.Managers
|
||||
#endregion
|
||||
|
||||
#region Simple property-style accessors (1:1 with C++)
|
||||
public int GetCurEndurance() { return m_iCurEndurance; }
|
||||
|
||||
public int GetClassID() => m_iCID;
|
||||
public int GetTemplateID() => m_tid;
|
||||
@@ -1346,7 +1349,7 @@ namespace BrewMonster.Scripts.Managers
|
||||
{
|
||||
//itemdataman* pItemDataMan = g_pGame->GetItemDataMan();
|
||||
object pData_temp = itemdataman.get_item_for_sell((uint)m_tid);
|
||||
if(pData_temp == null)
|
||||
if (pData_temp == null)
|
||||
{
|
||||
SetItemInfo(null, 0);
|
||||
SetLocalProps();
|
||||
@@ -1416,34 +1419,34 @@ namespace BrewMonster.Scripts.Managers
|
||||
}
|
||||
|
||||
// use specific color for the item price
|
||||
if((int)DescriptipionMsg.ITEMDESC_COL_WHITE == col)
|
||||
if ((int)DescriptipionMsg.ITEMDESC_COL_WHITE == col)
|
||||
{
|
||||
if( m_iPrice >= 100000000) // 100 million
|
||||
if (m_iPrice >= 100000000) // 100 million
|
||||
col = (int)DescriptipionMsg.ITEMDESC_COL_GREEN;
|
||||
else if ( m_iPrice >= 10000000) // 10 million
|
||||
else if (m_iPrice >= 10000000) // 10 million
|
||||
col = (int)DescriptipionMsg.ITEMDESC_COL_DARKGOLD;
|
||||
else if ( m_iPrice >= 1000000) // 1 million
|
||||
else if (m_iPrice >= 1000000) // 1 million
|
||||
col = (int)DescriptipionMsg.ITEMDESC_COL_YELLOW;
|
||||
}
|
||||
|
||||
|
||||
CECStringTab pDescTab = EC_Game.GetItemDesc();
|
||||
if (m_iScaleType == (int)ScaleType.SCALE_OFFLINESHOP)
|
||||
{
|
||||
AddDescText(col, false, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_PRICE));
|
||||
|
||||
string s1,s2;
|
||||
string s1, s2;
|
||||
BuildPriceNumberStr(m_iPrice, out s1);
|
||||
if (GetCount()>1)
|
||||
if (GetCount() > 1)
|
||||
{
|
||||
s2 = (m_iPrice * (long)GetCount()).ToString();
|
||||
s2 = (m_iPrice * (long)GetCount()).ToString();
|
||||
AddDescText(-1, false, " %s (%s)", s1, s2);
|
||||
}
|
||||
else
|
||||
AddDescText(-1, false, " %s", s1);
|
||||
AddDescText(-1, false, " %s", s1);
|
||||
}
|
||||
else if (m_iScaleType == (int)ScaleType.SCALE_BOOTH || m_tid == 21652) // 21651: yinpiao
|
||||
{
|
||||
string s1;
|
||||
string s1;
|
||||
BuildPriceNumberStr(m_iPrice, out s1);
|
||||
|
||||
AddDescText(col, false, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_UNITPRICE));
|
||||
@@ -1457,7 +1460,7 @@ namespace BrewMonster.Scripts.Managers
|
||||
|
||||
AddDescText(col, false, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_PRICE));
|
||||
AddDescText(-1, false, " %s (%s)", s1, s2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
string s1;
|
||||
@@ -1648,7 +1651,7 @@ namespace BrewMonster.Scripts.Managers
|
||||
var pDescTab = EC_Game.GetItemDesc();
|
||||
// Note: ITEMDESC_COL2_BRIGHTBLUE constant - adjust based on actual string table / 注意:ITEMDESC_COL2_BRIGHTBLUE常量 - 根据实际字符串表调整
|
||||
int green = (int)DescriptipionMsg.ITEMDESC_COL2_BRIGHTBLUE; // ITEMDESC_COL2_BRIGHTBLUE placeholder - adjust this value
|
||||
|
||||
|
||||
if (m_iCID != (int)InventoryClassId.ICID_GOBLIN) // goblin does not need to display these special properties / 地精不需要显示这些特殊属性
|
||||
{
|
||||
// Exact C++ logic: (PROC_NO_USER_TRASH) || (!PROC_BINDING && (PROC_DROPWHENDIE || ...))
|
||||
@@ -1679,7 +1682,7 @@ namespace BrewMonster.Scripts.Managers
|
||||
m_strDesc += "\\r";
|
||||
if (pDescTab != null && pDescTab.IsInitialized())
|
||||
{
|
||||
string desc = pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_DEAD_PROTECT);
|
||||
string desc = pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_DEAD_PROTECT);
|
||||
if (!string.IsNullOrEmpty(desc))
|
||||
m_strDesc += desc;
|
||||
}
|
||||
@@ -1689,7 +1692,7 @@ namespace BrewMonster.Scripts.Managers
|
||||
m_strDesc += "\\r";
|
||||
if (pDescTab != null && pDescTab.IsInitialized())
|
||||
{
|
||||
string desc = pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_NO_DROP);
|
||||
string desc = pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_NO_DROP);
|
||||
if (!string.IsNullOrEmpty(desc))
|
||||
m_strDesc += desc;
|
||||
}
|
||||
@@ -1699,7 +1702,7 @@ namespace BrewMonster.Scripts.Managers
|
||||
m_strDesc += "\\r";
|
||||
if (pDescTab != null && pDescTab.IsInitialized())
|
||||
{
|
||||
string desc = pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_NO_TRADE);
|
||||
string desc = pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_NO_TRADE);
|
||||
if (!string.IsNullOrEmpty(desc))
|
||||
m_strDesc += desc;
|
||||
}
|
||||
@@ -1709,7 +1712,7 @@ namespace BrewMonster.Scripts.Managers
|
||||
m_strDesc += "\\r";
|
||||
if (pDescTab != null && pDescTab.IsInitialized())
|
||||
{
|
||||
string desc = pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_NO_PLAYER_TRADE);
|
||||
string desc = pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_NO_PLAYER_TRADE);
|
||||
if (!string.IsNullOrEmpty(desc))
|
||||
m_strDesc += desc;
|
||||
}
|
||||
@@ -1719,7 +1722,7 @@ namespace BrewMonster.Scripts.Managers
|
||||
m_strDesc += "\\r";
|
||||
if (pDescTab != null && pDescTab.IsInitialized())
|
||||
{
|
||||
string desc = pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_LEAVE_SCENE_DISAPEAR);
|
||||
string desc = pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_LEAVE_SCENE_DISAPEAR);
|
||||
if (!string.IsNullOrEmpty(desc))
|
||||
m_strDesc += desc;
|
||||
}
|
||||
@@ -1729,7 +1732,7 @@ namespace BrewMonster.Scripts.Managers
|
||||
m_strDesc += "\\r";
|
||||
if (pDescTab != null && pDescTab.IsInitialized())
|
||||
{
|
||||
string desc = pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_USE_AFTER_PICK_UP);
|
||||
string desc = pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_USE_AFTER_PICK_UP);
|
||||
if (!string.IsNullOrEmpty(desc))
|
||||
m_strDesc += desc;
|
||||
}
|
||||
@@ -1739,7 +1742,7 @@ namespace BrewMonster.Scripts.Managers
|
||||
m_strDesc += "\\r";
|
||||
if (pDescTab != null && pDescTab.IsInitialized())
|
||||
{
|
||||
string desc = pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_DROP_WHEN_DEAD);
|
||||
string desc = pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_DROP_WHEN_DEAD);
|
||||
if (!string.IsNullOrEmpty(desc))
|
||||
m_strDesc += desc;
|
||||
}
|
||||
@@ -1749,7 +1752,7 @@ namespace BrewMonster.Scripts.Managers
|
||||
m_strDesc += "\\r";
|
||||
if (pDescTab != null && pDescTab.IsInitialized())
|
||||
{
|
||||
string desc = pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_DROP_WHEN_OFFLINE);
|
||||
string desc = pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_DROP_WHEN_OFFLINE);
|
||||
if (!string.IsNullOrEmpty(desc))
|
||||
m_strDesc += desc;
|
||||
}
|
||||
@@ -1759,7 +1762,7 @@ namespace BrewMonster.Scripts.Managers
|
||||
m_strDesc += "\\r";
|
||||
if (pDescTab != null && pDescTab.IsInitialized())
|
||||
{
|
||||
string desc = pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_UNREPAIRABLE);
|
||||
string desc = pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_UNREPAIRABLE);
|
||||
if (!string.IsNullOrEmpty(desc))
|
||||
m_strDesc += desc;
|
||||
}
|
||||
@@ -1769,7 +1772,7 @@ namespace BrewMonster.Scripts.Managers
|
||||
m_strDesc += "\\r";
|
||||
if (pDescTab != null && pDescTab.IsInitialized())
|
||||
{
|
||||
string desc = pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_NO_USER_TRASH);
|
||||
string desc = pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_NO_USER_TRASH);
|
||||
if (!string.IsNullOrEmpty(desc))
|
||||
m_strDesc += desc;
|
||||
}
|
||||
@@ -1810,10 +1813,10 @@ namespace BrewMonster.Scripts.Managers
|
||||
protected void AddIDDescText()
|
||||
{
|
||||
// Optional: show internal id for debugging
|
||||
#if UNITY_EDITOR
|
||||
AddDescText(0, true, "ID: {0}", m_tid);
|
||||
#endif
|
||||
|
||||
#if UNITY_EDITOR
|
||||
AddDescText(0, true, "ID: {0}", m_tid);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
protected void AddBindDescText()
|
||||
@@ -1948,7 +1951,7 @@ namespace BrewMonster.Scripts.Managers
|
||||
public string GetExtendedDescText()
|
||||
{
|
||||
string result = string.Empty;
|
||||
|
||||
|
||||
// Get extended description from item_ext_desc.txt using tid / 使用tid从item_ext_desc.txt获取扩展描述
|
||||
string szExtDesc = TryGetItemExtDesc();
|
||||
// Note: Original C++ had early return commented out / 注意:原始C++代码的早期返回被注释掉了
|
||||
|
||||
@@ -80,6 +80,11 @@ namespace PerfectWorld.Scripts.Managers
|
||||
{
|
||||
return m_pDBEssence.FileMatter;
|
||||
}
|
||||
|
||||
public TASKDICE_ESSENCE GetDBEssence()
|
||||
{
|
||||
return m_pDBEssence;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -51,25 +51,25 @@ namespace BrewMonster.Scripts.Managers
|
||||
SIZE_GENERALCARD_EQUIPIVTR = SIZE_ALL_EQUIPIVTR - EQUIPIVTR_GENERALCARD1,
|
||||
}
|
||||
#region Inventory Essence Struct
|
||||
#pragma pack(1)
|
||||
#pragma pack(1)
|
||||
public struct IVTR_ESSENCE_WEAPON
|
||||
{
|
||||
public short weapon_type;
|
||||
public short weapon_dealy;
|
||||
public int weapon_class;
|
||||
public int weapon_level;
|
||||
public int require_projectile; // ��Ҫ��ҩ������
|
||||
public int damage_low; // ����������С��ֵ
|
||||
public int damage_high; // ������������ֵ
|
||||
public int magic_damage_low; // ħ������
|
||||
public int magic_damage_high; // ħ������
|
||||
// public int attack; // ������
|
||||
public int attack_speed;
|
||||
public float attack_range;
|
||||
public float attack_short_range;
|
||||
public IVTR_ESSENCE_WEAPON( byte[] data)
|
||||
public short weapon_type;
|
||||
public short weapon_dealy;
|
||||
public int weapon_class;
|
||||
public int weapon_level;
|
||||
public int require_projectile; // ��Ҫ��ҩ������
|
||||
public int damage_low; // ����������С��ֵ
|
||||
public int damage_high; // ������������ֵ
|
||||
public int magic_damage_low; // ħ������
|
||||
public int magic_damage_high; // ħ������
|
||||
// public int attack; // ������
|
||||
public int attack_speed;
|
||||
public float attack_range;
|
||||
public float attack_short_range;
|
||||
public IVTR_ESSENCE_WEAPON(byte[] data)
|
||||
{
|
||||
CECDataReader dr = new (data, data.Length);
|
||||
CECDataReader dr = new(data, data.Length);
|
||||
weapon_type = dr.ReadShort();
|
||||
weapon_dealy = dr.ReadShort();
|
||||
weapon_class = dr.ReadInt();
|
||||
@@ -86,14 +86,14 @@ namespace BrewMonster.Scripts.Managers
|
||||
};
|
||||
public struct IVTR_ESSENCE_ARROW
|
||||
{
|
||||
public int dwBowMask;
|
||||
public int iDamage;
|
||||
public int iDamageScale;
|
||||
public int iWeaponReqLow;
|
||||
public 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);
|
||||
CECDataReader dr = new(data, data.Length);
|
||||
dwBowMask = dr.ReadInt();
|
||||
iDamage = dr.ReadInt();
|
||||
iDamageScale = dr.ReadInt();
|
||||
@@ -103,20 +103,20 @@ namespace BrewMonster.Scripts.Managers
|
||||
};
|
||||
public struct IVTR_ESSENCE_DECORATION
|
||||
{
|
||||
public int damage;
|
||||
public int magic_damage;
|
||||
public int defense;
|
||||
public int armor;
|
||||
public int[] resistance;
|
||||
public int damage;
|
||||
public int magic_damage;
|
||||
public int defense;
|
||||
public int armor;
|
||||
public int[] resistance;
|
||||
public IVTR_ESSENCE_DECORATION(byte[] data)
|
||||
{
|
||||
CECDataReader dr = new (data, data.Length);
|
||||
CECDataReader dr = new(data, data.Length);
|
||||
damage = dr.ReadInt();
|
||||
magic_damage = dr.ReadInt();
|
||||
defense = dr.ReadInt();
|
||||
armor = dr.ReadInt();
|
||||
resistance = new int[InventoryConst.NUM_MAGICCLASS];
|
||||
for(int i = 0; i < InventoryConst.NUM_MAGICCLASS; i++)
|
||||
for (int i = 0; i < InventoryConst.NUM_MAGICCLASS; i++)
|
||||
{
|
||||
resistance[i] = dr.ReadInt();
|
||||
}
|
||||
@@ -134,12 +134,12 @@ namespace BrewMonster.Scripts.Managers
|
||||
{
|
||||
Debug.Log("IVTR_ESSENCE_ARMOR: data.Length: " + data.Length);
|
||||
resistance = new int[InventoryConst.NUM_MAGICCLASS];
|
||||
CECDataReader dr = new (data, data.Length);
|
||||
CECDataReader dr = new(data, data.Length);
|
||||
defense = dr.ReadInt();
|
||||
armor = dr.ReadInt();
|
||||
mp_enhance = dr.ReadInt();
|
||||
hp_enhance = dr.ReadInt();
|
||||
for(int i = 0; i < InventoryConst.NUM_MAGICCLASS; i++)
|
||||
for (int i = 0; i < InventoryConst.NUM_MAGICCLASS; i++)
|
||||
{
|
||||
resistance[i] = dr.ReadInt();
|
||||
}
|
||||
@@ -152,7 +152,7 @@ namespace BrewMonster.Scripts.Managers
|
||||
public ushort gender;
|
||||
public IVTR_ESSENCE_FASHION(byte[] data)
|
||||
{
|
||||
CECDataReader dr = new (data, data.Length);
|
||||
CECDataReader dr = new(data, data.Length);
|
||||
require_level = dr.ReadInt();
|
||||
color = dr.ReadUShort();
|
||||
gender = dr.ReadUShort();
|
||||
@@ -160,18 +160,18 @@ namespace BrewMonster.Scripts.Managers
|
||||
};
|
||||
public struct IVTR_ESSENCE_FLYSWORD
|
||||
{
|
||||
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 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);
|
||||
CECDataReader dr = new(data, data.Length);
|
||||
cur_time = dr.ReadInt();
|
||||
max_time = dr.ReadInt();
|
||||
require_level = dr.ReadShort();
|
||||
@@ -193,46 +193,46 @@ namespace BrewMonster.Scripts.Managers
|
||||
};
|
||||
public struct IVTR_ESSENCE_AUTOHP
|
||||
{
|
||||
public int hp_left;
|
||||
public int hp_left;
|
||||
public float trigger;
|
||||
public IVTR_ESSENCE_AUTOHP(byte[] data)
|
||||
{
|
||||
CECDataReader dr = new (data, data.Length);
|
||||
CECDataReader dr = new(data, data.Length);
|
||||
hp_left = dr.ReadInt();
|
||||
trigger = dr.ReadFloat();
|
||||
}
|
||||
};
|
||||
public struct IVTR_ESSENCE_AUTOMP
|
||||
{
|
||||
public int mp_left;
|
||||
public int mp_left;
|
||||
public float trigger;
|
||||
public IVTR_ESSENCE_AUTOMP(byte[] data)
|
||||
{
|
||||
CECDataReader dr = new (data, data.Length);
|
||||
CECDataReader dr = new(data, data.Length);
|
||||
mp_left = dr.ReadInt();
|
||||
trigger = dr.ReadFloat();
|
||||
}
|
||||
};
|
||||
public struct IVTR_ESSENCE_PETEGG
|
||||
{
|
||||
public int req_level;
|
||||
public int req_class;
|
||||
public int honor_point;
|
||||
public int pet_tid;
|
||||
public int pet_vis_tid;
|
||||
public int pet_egg_tid;
|
||||
public int pet_class;
|
||||
public short level;
|
||||
public ushort color;
|
||||
public int exp;
|
||||
public int skill_point;
|
||||
public ushort name_len;
|
||||
public ushort skill_count;
|
||||
public int req_level;
|
||||
public int req_class;
|
||||
public int honor_point;
|
||||
public int pet_tid;
|
||||
public int pet_vis_tid;
|
||||
public int pet_egg_tid;
|
||||
public int pet_class;
|
||||
public short level;
|
||||
public ushort color;
|
||||
public int exp;
|
||||
public int skill_point;
|
||||
public ushort name_len;
|
||||
public ushort skill_count;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
|
||||
public ushort[] name;
|
||||
public ushort[] name;
|
||||
public IVTR_ESSENCE_PETEGG(byte[] data)
|
||||
{
|
||||
CECDataReader dr = new (data, data.Length);
|
||||
CECDataReader dr = new(data, data.Length);
|
||||
req_level = dr.ReadInt();
|
||||
req_class = dr.ReadInt();
|
||||
honor_point = dr.ReadInt();
|
||||
@@ -247,7 +247,7 @@ namespace BrewMonster.Scripts.Managers
|
||||
name_len = dr.ReadUShort();
|
||||
skill_count = dr.ReadUShort();
|
||||
name = new ushort[8];
|
||||
for(int i = 0; i < 8; i++)
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
name[i] = dr.ReadUShort();
|
||||
}
|
||||
@@ -270,14 +270,14 @@ namespace BrewMonster.Scripts.Managers
|
||||
public short agility;
|
||||
public short vitality;
|
||||
public short energy;
|
||||
public short total_genius;
|
||||
public short[] genius ;
|
||||
public short total_genius;
|
||||
public short[] genius;
|
||||
public short refine_level;
|
||||
public int stamina;
|
||||
public int status_value;
|
||||
public int stamina;
|
||||
public int status_value;
|
||||
public _GOBLIN_DATA(byte[] data)
|
||||
{
|
||||
CECDataReader dr = new (data, data.Length);
|
||||
CECDataReader dr = new(data, data.Length);
|
||||
exp = dr.ReadUInt();
|
||||
level = dr.ReadShort();
|
||||
total_attribute = dr.ReadShort();
|
||||
@@ -287,7 +287,7 @@ namespace BrewMonster.Scripts.Managers
|
||||
energy = dr.ReadShort();
|
||||
total_genius = dr.ReadShort();
|
||||
genius = new short[5];
|
||||
for(int i = 0; i < 5; i++)
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
genius[i] = dr.ReadShort();
|
||||
}
|
||||
@@ -301,7 +301,7 @@ namespace BrewMonster.Scripts.Managers
|
||||
public int skill_cnt;
|
||||
public IVTR_ESSENCE_GOBLIN(byte[] data)
|
||||
{
|
||||
CECDataReader dr = new (data, data.Length);
|
||||
CECDataReader dr = new(data, data.Length);
|
||||
// Calculate size manually: uint(4) + 7*short(14) + short[5](10) + short(2) + 2*int(8) = 40 bytes
|
||||
const int GOBLIN_DATA_SIZE = 40;
|
||||
this.data = new _GOBLIN_DATA(dr.ReadData(GOBLIN_DATA_SIZE));
|
||||
@@ -348,7 +348,7 @@ namespace BrewMonster.Scripts.Managers
|
||||
public struct IVTR_ESSENCE_GENERALCARD
|
||||
{
|
||||
// TODO : implement data later
|
||||
// int type;
|
||||
public int type;
|
||||
// int rank;
|
||||
// int require_level;
|
||||
// int require_leadership;
|
||||
@@ -357,8 +357,8 @@ namespace BrewMonster.Scripts.Managers
|
||||
// int exp;
|
||||
// int rebirth_times;
|
||||
};
|
||||
#pragma pack()
|
||||
|
||||
#pragma pack()
|
||||
|
||||
#endregion
|
||||
public static class EC_IvtrType
|
||||
{
|
||||
@@ -728,9 +728,9 @@ namespace BrewMonster.Scripts.Managers
|
||||
{
|
||||
if (sub.id != armorSubTypeId) continue;
|
||||
uint mask = sub.equip_mask;
|
||||
|
||||
|
||||
// Check finger slots first - try to find an empty one
|
||||
if ((mask & (1u << (int)IndexOfIteminEquipmentInventory.EQUIPIVTR_FINGER1)) != 0 ||
|
||||
if ((mask & (1u << (int)IndexOfIteminEquipmentInventory.EQUIPIVTR_FINGER1)) != 0 ||
|
||||
(mask & (1u << (int)IndexOfIteminEquipmentInventory.EQUIPIVTR_FINGER2)) != 0)
|
||||
{
|
||||
var availableFingerSlot = GetAvailableFingerSlot();
|
||||
@@ -739,7 +739,7 @@ namespace BrewMonster.Scripts.Managers
|
||||
return availableFingerSlot;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// For other slots, return the first matching one (original behavior)
|
||||
if ((mask & (1u << (int)IndexOfIteminEquipmentInventory.EQUIPIVTR_HEAD)) != 0) return IndexOfIteminEquipmentInventory.EQUIPIVTR_HEAD;
|
||||
if ((mask & (1u << (int)IndexOfIteminEquipmentInventory.EQUIPIVTR_SHOULDER)) != 0) return IndexOfIteminEquipmentInventory.EQUIPIVTR_SHOULDER;
|
||||
@@ -764,9 +764,9 @@ namespace BrewMonster.Scripts.Managers
|
||||
{
|
||||
if (sub.id != decorationSubTypeId) continue;
|
||||
uint mask = sub.equip_mask;
|
||||
|
||||
|
||||
// Check finger slots first - try to find an empty one
|
||||
if ((mask & (1u << (int)IndexOfIteminEquipmentInventory.EQUIPIVTR_FINGER1)) != 0 ||
|
||||
if ((mask & (1u << (int)IndexOfIteminEquipmentInventory.EQUIPIVTR_FINGER1)) != 0 ||
|
||||
(mask & (1u << (int)IndexOfIteminEquipmentInventory.EQUIPIVTR_FINGER2)) != 0)
|
||||
{
|
||||
var availableFingerSlot = GetAvailableFingerSlot();
|
||||
@@ -775,7 +775,7 @@ namespace BrewMonster.Scripts.Managers
|
||||
return availableFingerSlot;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// For other slots, return the first matching one (original behavior)
|
||||
if ((mask & (1u << (int)IndexOfIteminEquipmentInventory.EQUIPIVTR_NECK)) != 0) return IndexOfIteminEquipmentInventory.EQUIPIVTR_NECK;
|
||||
if ((mask & (1u << (int)IndexOfIteminEquipmentInventory.EQUIPIVTR_WAIST)) != 0) return IndexOfIteminEquipmentInventory.EQUIPIVTR_WAIST;
|
||||
@@ -801,18 +801,35 @@ namespace BrewMonster.Scripts.Managers
|
||||
{
|
||||
return IndexOfIteminEquipmentInventory.EQUIPIVTR_FINGER1;
|
||||
}
|
||||
|
||||
|
||||
// Check if FINGER2 slot is empty
|
||||
var finger2Item = equipInv?.GetItem((int)IndexOfIteminEquipmentInventory.EQUIPIVTR_FINGER2, false);
|
||||
if (finger2Item == null)
|
||||
{
|
||||
return IndexOfIteminEquipmentInventory.EQUIPIVTR_FINGER2;
|
||||
}
|
||||
|
||||
|
||||
// Both slots are occupied, return FINGER1 as fallback (original behavior)
|
||||
return IndexOfIteminEquipmentInventory.EQUIPIVTR_FINGER1;
|
||||
}
|
||||
}
|
||||
// Weapon type
|
||||
public enum WeaponType
|
||||
{
|
||||
WEAPONTYPE_MELEE = 0,
|
||||
WEAPONTYPE_RANGE = 1,
|
||||
};
|
||||
public enum InventoryType
|
||||
{
|
||||
IVTRTYPE_PACK = 0, // Normal pack
|
||||
IVTRTYPE_EQUIPPACK, // Equipment
|
||||
IVTRTYPE_TASKPACK, // Task pack
|
||||
IVTRTYPE_TRASHBOX, // Trash box
|
||||
IVTRTYPE_TRASHBOX2, // Trash box - material box
|
||||
IVTRTYPE_TRASHBOX3, // Trash box - fashion box
|
||||
IVTRTYPE_ACCOUNT_BOX, // User account box
|
||||
IVTRTYPE_GENERALCARD_BOX, // ¿¨Åưü¹ü
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -75,6 +75,7 @@ namespace BrewMonster
|
||||
// CECSkill class
|
||||
public class CECSkill
|
||||
{
|
||||
|
||||
// Skill type enum
|
||||
public enum SkillType
|
||||
{
|
||||
@@ -194,7 +195,6 @@ namespace BrewMonster
|
||||
// iTotalTime: total cooling time, 0 means to use cooling time in database
|
||||
public void StartCooling(int iTotalTime, int iStartCnt)
|
||||
{
|
||||
BMLogger.LogError($"StartCooling iTotalTime={iTotalTime}, iStartCnt={iStartCnt}");
|
||||
m_iCoolTime = iTotalTime != 0 ? iTotalTime : GetCoreCoolingTime();
|
||||
m_iCoolCnt = iStartCnt;
|
||||
m_bCooling = true;
|
||||
@@ -293,15 +293,28 @@ namespace BrewMonster
|
||||
return string.Empty;
|
||||
|
||||
StringBuilder sb = new StringBuilder(1024);
|
||||
var skillStr = l_SkillStr as SkillStr;
|
||||
string result = m_pSkillCore.GetIntroduction(sb, 1024, skillStr);
|
||||
return result;
|
||||
m_pSkillCore.GetIntroduction(sb, l_SkillStr);
|
||||
return sb.ToString();
|
||||
}
|
||||
public static bool GetDesc(int idSkill, int iLevel, string szText, int iBufLen)
|
||||
{
|
||||
if (szText == null || iBufLen == 0)
|
||||
return false;
|
||||
|
||||
CECSkill pSkill = new CECSkill(idSkill, iLevel);
|
||||
if (pSkill == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
string sz = pSkill.GetDesc();
|
||||
|
||||
return true;
|
||||
}
|
||||
public int GetCoreCoolingTime()
|
||||
{
|
||||
return m_pSkillCore != null ? m_pSkillCore.GetCoolingTime() : 0;
|
||||
}
|
||||
public int GetComboSkPreSkill() { return m_pSkillCore.GetComboSkPreSkill(); }
|
||||
|
||||
public int GetExecuteTime()
|
||||
{
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
using BrewMonster.Scripts.Skills;
|
||||
using NUnit.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
@@ -19,7 +22,19 @@ namespace BrewMonster
|
||||
|
||||
set => instance = value;
|
||||
}
|
||||
private Dictionary<uint, CECSkill> m_inherentSkillMap = new Dictionary<uint, CECSkill>();
|
||||
private readonly Dictionary<uint, CECSkill> m_inherentSkillMap = new Dictionary<uint, CECSkill>();
|
||||
private readonly List<uint> m_activeSkills = new();
|
||||
private readonly List<uint> m_skillStayTime = new();
|
||||
private readonly List<bool> m_skillTimeOut = new();
|
||||
List<uint> m_preSkillSet = new List<uint>(); // 所有是其它技能前提的技能
|
||||
|
||||
uint m_dwStartTime; // 技能激活开始时间
|
||||
|
||||
public ComboSkillState m_comboSkillState { get; private set; }
|
||||
public DateTime? ComboStateStartTime { get; private set; }
|
||||
public IReadOnlyList<uint> ActiveComboSkills => m_activeSkills;
|
||||
public IReadOnlyList<uint> SkillStayTimes => m_skillStayTime;
|
||||
public IReadOnlyList<bool> SkillTimeouts => m_skillTimeOut;
|
||||
|
||||
public CECSkill GetInherentSkillByID(uint skillID)
|
||||
{
|
||||
@@ -32,5 +47,158 @@ namespace BrewMonster
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetComboSkillState(Dictionary<uint, int> skillDic, ref ComboSkillState state)
|
||||
{
|
||||
m_comboSkillState = state;
|
||||
if (state.skillid != 0)
|
||||
{
|
||||
m_dwStartTime = (uint)Time.realtimeSinceStartup * 1000;
|
||||
SetActiveComboSkills(skillDic);
|
||||
/* CECComboSkillChange change(CECComboSkillChange::COMBOSKILL_ACTIVE);
|
||||
NotifyObservers(&change);*/
|
||||
}
|
||||
else
|
||||
{
|
||||
m_dwStartTime = 0;
|
||||
m_activeSkills.Clear();
|
||||
m_skillStayTime.Clear();
|
||||
m_skillTimeOut.Clear();
|
||||
/*CECComboSkillChange change(CECComboSkillChange::COMBOSKILL_STOP);
|
||||
NotifyObservers(&change);*/
|
||||
}
|
||||
}
|
||||
public ComboSkillState GetComboSkillState()
|
||||
{
|
||||
return m_comboSkillState;
|
||||
}
|
||||
void SetActiveComboSkills(Dictionary<uint, int> dic)
|
||||
{
|
||||
Dictionary<uint, int> newList = new Dictionary<uint, int>();
|
||||
FilterComboSkills(dic, newList);
|
||||
|
||||
m_activeSkills.Clear();
|
||||
m_skillStayTime.Clear();
|
||||
m_skillTimeOut.Clear();
|
||||
List<uint> juniorSkills = new List<uint>();
|
||||
int i;
|
||||
foreach (var skill in newList)
|
||||
{
|
||||
int skillID = (int)skill.Key;
|
||||
int skillTime = skill.Value;
|
||||
m_activeSkills.Add((uint)skillID);
|
||||
m_skillStayTime.Add((uint)skillTime);
|
||||
m_skillTimeOut.Add(false);
|
||||
if (m_inherentSkillMap.ContainsKey((uint)skillID))
|
||||
{
|
||||
juniorSkills.Add((uint)GetFirstChildRecursively(skillID));
|
||||
}
|
||||
else
|
||||
{
|
||||
juniorSkills.Add((uint)skillID);
|
||||
}
|
||||
|
||||
}
|
||||
// 冒泡排序:有后续技能的放在前面;最原始的初级技能id小的放在前面
|
||||
int j;
|
||||
for (i = m_activeSkills.Count - 1; i > 0; i--)
|
||||
{
|
||||
for (j = 0; j < i; j++)
|
||||
{
|
||||
bool bPreSkill1 = IsComboPreSkill(juniorSkills[j]);
|
||||
bool bPreSkill2 = IsComboPreSkill(juniorSkills[j + 1]);
|
||||
if ((!bPreSkill1 && bPreSkill2) || (bPreSkill1 == bPreSkill2 && juniorSkills[j] > juniorSkills[j + 1]))
|
||||
{
|
||||
EC_Utility.Swap(m_activeSkills, j, j + 1);
|
||||
EC_Utility.Swap(m_skillStayTime, j, j + 1);
|
||||
EC_Utility.Swap(juniorSkills, j, j + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public bool IsActiveComboSkill(uint skillID)
|
||||
{
|
||||
for (int i = 0; i < m_activeSkills.Count; i++)
|
||||
{
|
||||
if (m_activeSkills[i] == skillID && m_skillTimeOut[i] == false)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool IsComboPreSkill(uint skillID)
|
||||
{
|
||||
return m_preSkillSet.Contains(skillID);
|
||||
}
|
||||
int GetFirstChildRecursively(int iSkillID)
|
||||
{
|
||||
Dictionary<uint, int> vecJuniors = CECHostSkillModel.Instance.GetJunior(iSkillID);
|
||||
if (vecJuniors.Count == 0)
|
||||
{
|
||||
return iSkillID;
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var skill in vecJuniors)
|
||||
{
|
||||
int iComboPreSkill = ElementSkill.GetComboSkPreSkill(skill.Key);
|
||||
if (iComboPreSkill != 0)
|
||||
{
|
||||
return GetFirstChildRecursively((int)skill.Key);
|
||||
}
|
||||
}
|
||||
return iSkillID;
|
||||
}
|
||||
}
|
||||
void FilterComboSkills(Dictionary<uint, int> inDic, Dictionary<uint, int> outDic)
|
||||
{
|
||||
outDic.Clear();
|
||||
CECTaoistRank pCurTaoistRank = CECTaoistRank.GetTaoistRank(CECGameRun.Instance.GetHostPlayer().GetBasicProps().iLevel2);
|
||||
CECHostSkillModel hostSkillModel = CECHostSkillModel.Instance;
|
||||
uint i;
|
||||
foreach (var skill in inDic)
|
||||
{
|
||||
uint uiSkillID = skill.Key;
|
||||
if (!m_inherentSkillMap.ContainsKey(uiSkillID))
|
||||
{
|
||||
// 如果不是天生技能,则执行过滤
|
||||
enumEvilGod skillEvilGod = hostSkillModel.GetSkillEvilGod((int)uiSkillID);
|
||||
enumSkillLearnedState skillLearnState = hostSkillModel.GetSkillLearnedState((int)uiSkillID);
|
||||
// 如果该技能已被覆盖,则去掉
|
||||
if (enumSkillLearnedState.SKILL_OVERRIDDEN == skillLearnState)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
// 如果是魔技能且人物修真为普通或仙,则去掉
|
||||
if (enumEvilGod.SKILL_EVIL == skillEvilGod)
|
||||
{
|
||||
if (pCurTaoistRank.IsBaseRank() || pCurTaoistRank.IsGodRank())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// 如果是仙技能且人物修真为普通或魔,则去掉
|
||||
if (enumEvilGod.SKILL_GOD == skillEvilGod)
|
||||
{
|
||||
if (pCurTaoistRank.IsBaseRank() || pCurTaoistRank.IsEvilRank())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// 如果是仙魔技能且未学习,则去掉
|
||||
if (enumEvilGod.SKILL_GOD == skillEvilGod || skillEvilGod == enumEvilGod.SKILL_EVIL)
|
||||
{
|
||||
if (enumSkillLearnedState.SKILL_NOT_LEARNED == skillLearnState)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
outDic[skill.Key] = skill.Value;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,7 @@ namespace BrewMonster
|
||||
BMLogger.Log("CECTaoistRank OnPlay Reset");
|
||||
initComplete = false;
|
||||
CECTaoistRank[] s_allTaoistRanks = new CECTaoistRank[(int)ToaistRank.TotalRankCount];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
public int GetID()
|
||||
{
|
||||
@@ -75,7 +75,10 @@ namespace BrewMonster
|
||||
init();
|
||||
return s_allTaoistRanks[(int)ToaistRank.BaseRankCount + (int)ToaistRank.GodRankCount - 1];
|
||||
}
|
||||
|
||||
public bool IsBaseRank()
|
||||
{
|
||||
return !IsGodRank() && !IsEvilRank();
|
||||
}
|
||||
public bool IsEvilRank()
|
||||
{
|
||||
CECTaoistRank EvilRank;
|
||||
|
||||
@@ -1414,7 +1414,10 @@ namespace BrewMonster
|
||||
}
|
||||
// Get character ID
|
||||
|
||||
// Play Gfx on Models
|
||||
public static int GetRealmLayer(int realmLevel) { return realmLevel != 0 ? (realmLevel + 9) / 10 : 0; }
|
||||
|
||||
public static int GetRealmSubLevel(int realmLevel) { return realmLevel != 0 ? (realmLevel % 10 != 0 ? realmLevel % 10 : 10) : 0; }
|
||||
|
||||
protected bool PlayGfx(string szPath, string szHook, float fScale /*1.0f*/, uint iShapeTypeMask /*(1<<PLAYERMODEL_MAJOR)*/, bool bForceNoRecord = false)
|
||||
{
|
||||
// bool bPlayed(false);
|
||||
|
||||
@@ -208,7 +208,7 @@ public class CECNPC : CECObject
|
||||
|
||||
private void OnMsgNPCInvisible(ECMSG Msg)
|
||||
{
|
||||
cmd_object_invisible pCmd = GPDataTypeHelper.FromBytes< cmd_object_invisible>((byte[])Msg.dwParam1);
|
||||
cmd_object_invisible pCmd = GPDataTypeHelper.FromBytes<cmd_object_invisible>((byte[])Msg.dwParam1);
|
||||
|
||||
if (pCmd.invisible_degree > 0)
|
||||
{
|
||||
@@ -1032,7 +1032,7 @@ public class CECNPC : CECObject
|
||||
}
|
||||
public void StopMoveTo(cmd_object_stop_move cmd)
|
||||
{
|
||||
BMLogger.LogMono(this,"CECNPC::StopMoveTo");
|
||||
BMLogger.LogMono(this, "CECNPC::StopMoveTo");
|
||||
if (IsDead())
|
||||
return;
|
||||
BMLogger.LogMono(this, "CECNPC::StopMoveTo not dead");
|
||||
@@ -1517,6 +1517,7 @@ public class CECNPC : CECObject
|
||||
m_pNPCModelPolicy.PlayModelAction(iAction, bRestart, null);
|
||||
}
|
||||
bool IsDisappearing() { return m_DisappearCnt.GetCounter() != 0 ? true : false; }
|
||||
public int GetTemplateID() { return m_NPCInfo.tid; }
|
||||
|
||||
public float GetTouchRadius() { return m_fTouchRad; }
|
||||
|
||||
|
||||
@@ -341,6 +341,16 @@ namespace CSNetwork.C2SCommand
|
||||
var cmdBuf = SerializeCommand(CommandID.CAST_POS_SKILL, cmd);
|
||||
return cmdBuf;
|
||||
}
|
||||
public static Octets CreateNotifyForceAttack(int iForceAttack, byte refuseBless)
|
||||
{
|
||||
var cmd = new cmd_notify_force_attack
|
||||
{
|
||||
force_attack = (byte)iForceAttack,
|
||||
refuse_bless = refuseBless
|
||||
};
|
||||
var cmdBuf = SerializeCommand(CommandID.NOTIFY_FORCE_ATTACK, cmd);
|
||||
return cmdBuf;
|
||||
}
|
||||
|
||||
public static short FloatToFix8(float x)
|
||||
{
|
||||
|
||||
@@ -1253,6 +1253,14 @@ namespace CSNetwork.GPDataType
|
||||
public uint content_length;
|
||||
public byte[] content;
|
||||
};
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct cmd_combo_skill_prepare
|
||||
{
|
||||
public int skill_id;
|
||||
public int timestamp;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
|
||||
public int[] args;
|
||||
};
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
struct cmd_host_start_attack
|
||||
@@ -1643,7 +1651,7 @@ namespace CSNetwork.GPDataType
|
||||
{
|
||||
return (id & 0x80000000) != 0 && (id & 0x40000000) == 0;
|
||||
}
|
||||
public static string ReplacePercentD(string fmt, params object[] args)
|
||||
public static string ReplacePercentD(string fmt, params object[] args)
|
||||
{
|
||||
if (string.IsNullOrEmpty(fmt) || args == null || args.Length == 0)
|
||||
return fmt;
|
||||
@@ -2271,30 +2279,31 @@ namespace CSNetwork.GPDataType
|
||||
public byte is_active;
|
||||
};
|
||||
public struct cmd_reincarnation_tome_info
|
||||
{
|
||||
public int tome_exp;
|
||||
public char tome_active; // 1����0���
|
||||
public int count;
|
||||
public struct _entry
|
||||
{
|
||||
public int level;
|
||||
public int timestamp;
|
||||
public int exp;
|
||||
};
|
||||
{
|
||||
public int tome_exp;
|
||||
public char tome_active; // 1����0���
|
||||
public int count;
|
||||
public struct _entry
|
||||
{
|
||||
public int level;
|
||||
public int timestamp;
|
||||
public int exp;
|
||||
};
|
||||
public _entry[] records;
|
||||
public bool CheckValid(int buf_size, out int sz)
|
||||
{ sz = 0;
|
||||
if (count < 0)
|
||||
return false;
|
||||
sz = Marshal.SizeOf<cmd_reincarnation_tome_info>() - Marshal.SizeOf<_entry[]>();
|
||||
sz += count * Marshal.SizeOf<_entry>();
|
||||
return buf_size >= sz;
|
||||
}
|
||||
};
|
||||
public bool CheckValid(int buf_size, out int sz)
|
||||
{
|
||||
sz = 0;
|
||||
if (count < 0)
|
||||
return false;
|
||||
sz = Marshal.SizeOf<cmd_reincarnation_tome_info>() - Marshal.SizeOf<_entry[]>();
|
||||
sz += count * Marshal.SizeOf<_entry>();
|
||||
return buf_size >= sz;
|
||||
}
|
||||
};
|
||||
|
||||
// Pet type
|
||||
public enum GP_PET_TYPE
|
||||
{
|
||||
{
|
||||
GP_PET_CLASS_INVALID = -1,
|
||||
GP_PET_CLASS_MOUNT = 0, // ���
|
||||
GP_PET_CLASS_COMBAT, // ս������
|
||||
@@ -2304,13 +2313,13 @@ namespace CSNetwork.GPDataType
|
||||
GP_PET_CLASS_EVOLUTION, // ������
|
||||
GP_PET_CLASS_MAX,
|
||||
};
|
||||
|
||||
|
||||
public struct PetSkill
|
||||
{
|
||||
public int skill;
|
||||
public int level;
|
||||
|
||||
}
|
||||
}
|
||||
public struct _evo_prop
|
||||
{
|
||||
public int r_attack;
|
||||
@@ -2322,29 +2331,29 @@ namespace CSNetwork.GPDataType
|
||||
}
|
||||
public enum GP_PET_SKILL_NUM
|
||||
{
|
||||
GP_PET_SKILL_NUM = 8
|
||||
GP_PET_SKILL_NUM = 8
|
||||
};
|
||||
public struct info_pet
|
||||
{
|
||||
public int honor_point; // �øж�
|
||||
public int hunger; // ������
|
||||
public int feed_time; // �ϴ�ι�������ڵ�ʱ��
|
||||
public int pet_tid; // ������ID
|
||||
public int pet_vis_tid; // ����Ŀɼ�ID�����Ϊ0�����ʾ������ɼ�ID��
|
||||
public int pet_egg_tid; // ���ﵰ��ID
|
||||
public int pet_class; // �������� ս�裬��裬���ͳ�
|
||||
public float hp_factor; // Ѫ��������������ջ�ʱʹ�ã� 0��Ϊ����
|
||||
public short level; // ���V��
|
||||
public ushort color; // ������ɫ�����λΪ1��ʾ��Ч��Ŀǰ���������Ч
|
||||
public int exp; // ���ﵱǰ����
|
||||
public int skill_point; // ʣ�༼�ܵ�
|
||||
public char is_bind; // �Ƿ����˺�һ��������һ��Mask��0x01 ���˺�һ��0x02 Ѱ�����ɽ���
|
||||
public char unused; // Ŀǰ������Ч
|
||||
public ushort name_len; // ���ֳ��� Ŀǰ������Ч����Ϊ��������������
|
||||
public char[] name; // ��������
|
||||
public PetSkill[] skills;
|
||||
{
|
||||
public int honor_point; // �øж�
|
||||
public int hunger; // ������
|
||||
public int feed_time; // �ϴ�ι�������ڵ�ʱ��
|
||||
public int pet_tid; // ������ID
|
||||
public int pet_vis_tid; // ����Ŀɼ�ID�����Ϊ0�����ʾ������ɼ�ID��
|
||||
public int pet_egg_tid; // ���ﵰ��ID
|
||||
public int pet_class; // �������� ս�裬��裬���ͳ�
|
||||
public float hp_factor; // Ѫ��������������ջ�ʱʹ�ã� 0��Ϊ����
|
||||
public short level; // ���V��
|
||||
public ushort color; // ������ɫ�����λΪ1��ʾ��Ч��Ŀǰ���������Ч
|
||||
public int exp; // ���ﵱǰ����
|
||||
public int skill_point; // ʣ�༼�ܵ�
|
||||
public char is_bind; // �Ƿ����˺�һ��������һ��Mask��0x01 ���˺�һ��0x02 Ѱ�����ɽ���
|
||||
public char unused; // Ŀǰ������Ч
|
||||
public ushort name_len; // ���ֳ��� Ŀǰ������Ч����Ϊ��������������
|
||||
public char[] name; // ��������
|
||||
public PetSkill[] skills;
|
||||
public _evo_prop evo_prop;
|
||||
public int[] reserved; // �
|
||||
public int[] reserved; // �
|
||||
public info_pet(bool isDefault = true)
|
||||
{
|
||||
honor_point = 0;
|
||||
@@ -2364,7 +2373,8 @@ namespace CSNetwork.GPDataType
|
||||
name_len = 0;
|
||||
name = new char[16];
|
||||
skills = new PetSkill[(int)GP_PET_SKILL_NUM.GP_PET_SKILL_NUM];
|
||||
evo_prop = new _evo_prop{
|
||||
evo_prop = new _evo_prop
|
||||
{
|
||||
r_attack = 0,
|
||||
r_defense = 0,
|
||||
r_hp = 0,
|
||||
@@ -2374,6 +2384,17 @@ namespace CSNetwork.GPDataType
|
||||
};
|
||||
reserved = new int[10];
|
||||
}
|
||||
};
|
||||
};
|
||||
public enum REFUSE_BLESS_MASK : byte
|
||||
{
|
||||
REFUSE_NEUTRAL_BLESS = 0x0001, // ²»½ÓÊÜÖÐÐÔ×£¸£
|
||||
REFUSE_NON_TEAMMATE_BLESS = 0x0002, // ²»½ÓÊܷǶÓÓÑ×£¸£
|
||||
};
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct cmd_notify_force_attack
|
||||
{
|
||||
public byte force_attack;
|
||||
public byte refuse_bless;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -994,6 +994,8 @@ namespace CSNetwork
|
||||
else if (ISNPCID(pCmd3.caster))
|
||||
EC_ManMessage.PostMessage(EC_MsgDef.MSG_NM_ENCHANTRESULT, MANAGER_INDEX.MAN_NPC, 0, pDataBuf, pCmdHeader);
|
||||
break;
|
||||
case CommandID.HOST_STOP_SKILL:
|
||||
case CommandID.SELF_SKILL_INTERRUPTED:
|
||||
case CommandID.SKILL_PERFORM:
|
||||
EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_CASTSKILL, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader);
|
||||
break;
|
||||
@@ -1399,6 +1401,12 @@ namespace CSNetwork
|
||||
|
||||
SendProtocol(gamedatasend);
|
||||
}
|
||||
public void c2s_SendCmdNotifyForceAttack(int iForceAttack, byte refuseBless)
|
||||
{
|
||||
gamedatasend gamedatasend = new gamedatasend();
|
||||
gamedatasend.Data = C2SCommandFactory.CreateNotifyForceAttack(iForceAttack, refuseBless);
|
||||
SendProtocol(gamedatasend);
|
||||
}
|
||||
public void c2s_SendCmdContinueAction()
|
||||
{
|
||||
gamedatasend gamedatasend = new gamedatasend();
|
||||
|
||||
@@ -510,6 +510,10 @@ namespace BrewMonster.Network
|
||||
public static void c2s_CmdNPCSevHeal()
|
||||
{
|
||||
|
||||
}
|
||||
public static void c2s_SendCmdNotifyForceAttack(int iForceAttack, byte refuseBless)
|
||||
{
|
||||
Instance._gameSession.c2s_SendCmdNotifyForceAttack(iForceAttack, refuseBless);
|
||||
}
|
||||
public static void c2s_CmdNPCSevAcceptTask(int idTask,int idStorage,int idRefreshItem)
|
||||
{
|
||||
|
||||
@@ -10,15 +10,22 @@
|
||||
*
|
||||
* Copyright (c) 2005 Archosaur Studio, All Rights Reserved.
|
||||
*/
|
||||
|
||||
using static BrewMonster.CECSCCommand.CommandID;
|
||||
using static BrewMonster.Scripts.RoleExpression;
|
||||
using static BrewMonster.Scripts.DescriptipionMsg;
|
||||
using BrewMonster.Assets.PerfectWorld.Scripts.Skills;
|
||||
using BrewMonster.Network;
|
||||
using BrewMonster.Scripts;
|
||||
using BrewMonster.Scripts.Skills;
|
||||
using CSNetwork.C2SCommand;
|
||||
using CSNetwork.GPDataType;
|
||||
using CSNetwork.S2CCommand;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Unity.VisualScripting;
|
||||
using UnityEngine;
|
||||
using static BrewMonster.EC_Resource;
|
||||
using static BrewMonster.IconResourceType;
|
||||
|
||||
namespace BrewMonster
|
||||
{
|
||||
@@ -123,7 +130,7 @@ namespace BrewMonster
|
||||
/// <summary>
|
||||
/// Create a skill group shortcut at specified position
|
||||
/// </summary>
|
||||
/* public bool CreateSkillGroupShortcut(int iSlot, int iGroupIdx)
|
||||
public bool CreateSkillGroupShortcut(int iSlot, int iGroupIdx)
|
||||
{
|
||||
CECSCSkillGrp pSkillGrpSC = new CECSCSkillGrp();
|
||||
if (pSkillGrpSC == null)
|
||||
@@ -137,7 +144,7 @@ namespace BrewMonster
|
||||
|
||||
SetShortcut(iSlot, pSkillGrpSC);
|
||||
return true;
|
||||
}*/
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a pet shortcut at specified position
|
||||
@@ -260,11 +267,6 @@ namespace BrewMonster
|
||||
{
|
||||
m_aShortcuts[iSlot] = null;
|
||||
}
|
||||
CECSCSkill skill;
|
||||
if ((skill = pShortcut as CECSCSkill) != null)
|
||||
{
|
||||
BMLogger.LogError("SetShortcut: Setting shortcut at slot " + iSlot + $" skill = {skill.GetSkill().GetName()}");
|
||||
}
|
||||
m_aShortcuts[iSlot] = pShortcut;
|
||||
}
|
||||
|
||||
@@ -636,100 +638,100 @@ namespace BrewMonster
|
||||
break;
|
||||
}
|
||||
|
||||
/* case CECShortcut.ShortcutType.SCT_ITEM:
|
||||
{
|
||||
int iPack = BitConverter.ToInt32(pDataBuf, offset);
|
||||
offset += sizeof(int);
|
||||
int iIvtrSlot = BitConverter.ToInt32(pDataBuf, offset);
|
||||
offset += sizeof(int);
|
||||
int idItem = BitConverter.ToInt32(pDataBuf, offset);
|
||||
offset += sizeof(int);
|
||||
/* case CECShortcut.ShortcutType.SCT_ITEM:
|
||||
{
|
||||
int iPack = BitConverter.ToInt32(pDataBuf, offset);
|
||||
offset += sizeof(int);
|
||||
int iIvtrSlot = BitConverter.ToInt32(pDataBuf, offset);
|
||||
offset += sizeof(int);
|
||||
int idItem = BitConverter.ToInt32(pDataBuf, offset);
|
||||
offset += sizeof(int);
|
||||
|
||||
CECInventory pPack = pHost.GetPack(iPack);
|
||||
if (pPack == null)
|
||||
{
|
||||
Debug.LogError("CECShortcutSet::LoadConfigData - Invalid inventory");
|
||||
return false;
|
||||
}
|
||||
CECInventory pPack = pHost.GetPack(iPack);
|
||||
if (pPack == null)
|
||||
{
|
||||
Debug.LogError("CECShortcutSet::LoadConfigData - Invalid inventory");
|
||||
return false;
|
||||
}
|
||||
|
||||
CECIvtrItem pItem = pPack.GetItem(iIvtrSlot);
|
||||
if (pItem != null)
|
||||
CreateItemShortcut(iSlot, iPack, iIvtrSlot, pItem);
|
||||
CECIvtrItem pItem = pPack.GetItem(iIvtrSlot);
|
||||
if (pItem != null)
|
||||
CreateItemShortcut(iSlot, iPack, iIvtrSlot, pItem);
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}*/
|
||||
|
||||
case CECShortcut.ShortcutType.SCT_SKILLGRP:
|
||||
{
|
||||
if (dwVer >= 3)
|
||||
{
|
||||
int iGroupIdx = BitConverter.ToInt32(pDataBuf, offset);
|
||||
offset += sizeof(int);
|
||||
case CECShortcut.ShortcutType.SCT_SKILLGRP:
|
||||
{
|
||||
if (dwVer >= 3)
|
||||
{
|
||||
int iGroupIdx = BitConverter.ToInt32(pDataBuf, offset);
|
||||
offset += sizeof(int);
|
||||
|
||||
if (iGroupIdx >= 0)
|
||||
CreateSkillGroupShortcut(iSlot, iGroupIdx);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("CECShortcutSet::LoadConfigData - Invalid version for skill group");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (iGroupIdx >= 0)
|
||||
CreateSkillGroupShortcut(iSlot, iGroupIdx);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("CECShortcutSet::LoadConfigData - Invalid version for skill group");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case CECShortcut.ShortcutType.SCT_PET:
|
||||
{
|
||||
if (dwVer >= 4)
|
||||
{
|
||||
int iPetIndex = BitConverter.ToInt32(pDataBuf, offset);
|
||||
offset += sizeof(int);
|
||||
/*case CECShortcut.ShortcutType.SCT_PET:
|
||||
{
|
||||
if (dwVer >= 4)
|
||||
{
|
||||
int iPetIndex = BitConverter.ToInt32(pDataBuf, offset);
|
||||
offset += sizeof(int);
|
||||
|
||||
if (iPetIndex >= 0)
|
||||
CreatePetShortcut(iSlot, iPetIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("CECShortcutSet::LoadConfigData - Invalid version for pet");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (iPetIndex >= 0)
|
||||
CreatePetShortcut(iSlot, iPetIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("CECShortcutSet::LoadConfigData - Invalid version for pet");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case CECShortcut.ShortcutType.SCT_AUTOFASHION:
|
||||
{
|
||||
if (dwVer >= 5)
|
||||
{
|
||||
int iAutoFashionIndex = BitConverter.ToInt32(pDataBuf, offset);
|
||||
offset += sizeof(int);
|
||||
case CECShortcut.ShortcutType.SCT_AUTOFASHION:
|
||||
{
|
||||
if (dwVer >= 5)
|
||||
{
|
||||
int iAutoFashionIndex = BitConverter.ToInt32(pDataBuf, offset);
|
||||
offset += sizeof(int);
|
||||
|
||||
if (iAutoFashionIndex >= 0)
|
||||
CreateAutoFashionShortcut(iSlot, iAutoFashionIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("CECShortcutSet::LoadConfigData - Invalid version for auto fashion");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (iAutoFashionIndex >= 0)
|
||||
CreateAutoFashionShortcut(iSlot, iAutoFashionIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("CECShortcutSet::LoadConfigData - Invalid version for auto fashion");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case CECShortcut.ShortcutType.SCT_SYSMODULE:
|
||||
{
|
||||
if (dwVer > 10)
|
||||
{
|
||||
int iSys = BitConverter.ToInt32(pDataBuf, offset);
|
||||
offset += sizeof(int);
|
||||
case CECShortcut.ShortcutType.SCT_SYSMODULE:
|
||||
{
|
||||
if (dwVer > 10)
|
||||
{
|
||||
int iSys = BitConverter.ToInt32(pDataBuf, offset);
|
||||
offset += sizeof(int);
|
||||
|
||||
if (iSys >= 0)
|
||||
CreateSystemModuleShortcut(iSlot, iSys);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("CECShortcutSet::LoadConfigData - Invalid version for system module");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}*/
|
||||
if (iSys >= 0)
|
||||
CreateSystemModuleShortcut(iSlot, iSys);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("CECShortcutSet::LoadConfigData - Invalid version for system module");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}*/
|
||||
|
||||
/* default:
|
||||
//TODO: uncomment
|
||||
@@ -759,7 +761,7 @@ namespace BrewMonster
|
||||
#region Placeholder Classes
|
||||
// These classes are referenced but not defined in the provided files
|
||||
// They should be implemented separately based on EC_Shortcut.h/cpp
|
||||
|
||||
[Serializable]
|
||||
public class CECShortcut
|
||||
{
|
||||
protected int m_iSCType;
|
||||
@@ -781,25 +783,37 @@ namespace BrewMonster
|
||||
{
|
||||
return m_iSCType;
|
||||
}
|
||||
public virtual string GetDesc() { return ""; }
|
||||
|
||||
public virtual CECShortcut Clone()
|
||||
{
|
||||
return new CECShortcut();
|
||||
}
|
||||
public virtual bool Execute() { return true; }
|
||||
|
||||
public virtual int GetCoolTime(ref int piMax)
|
||||
{
|
||||
piMax = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
public virtual string GetIconFile()
|
||||
public virtual string GetIconFile()
|
||||
{
|
||||
return "";
|
||||
// Return a default icon file name
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
// Shortcut type
|
||||
public enum ShortcutType
|
||||
|
||||
{
|
||||
SCT_UNKNOWN = -1,
|
||||
SCT_SKILL = 0,
|
||||
SCT_ITEM,
|
||||
SCT_COMMAND,
|
||||
SCT_SKILLGRP,
|
||||
SCT_PET,
|
||||
SCT_AUTOFASHION,
|
||||
SCT_SYSMODULE,
|
||||
};
|
||||
public class CECSCCommand : CECShortcut
|
||||
{
|
||||
private int m_iCommand; // Command ID
|
||||
@@ -813,7 +827,7 @@ namespace BrewMonster
|
||||
CMD_FINDTARGET,
|
||||
CMD_ASSISTATTACK,
|
||||
CMD_INVITETOTEAM,
|
||||
CMD_LEAVETEAM,
|
||||
CMD_LEAVETEAM,
|
||||
CMD_KICKTEAMMEM,
|
||||
CMD_FINDTEAM,
|
||||
CMD_STARTTRADE,
|
||||
@@ -829,25 +843,93 @@ namespace BrewMonster
|
||||
}
|
||||
public CECSCCommand(int iCommand)
|
||||
{
|
||||
m_iSCType = (int)ShortcutType.SCT_COMMAND;
|
||||
m_iSCType = (int)ShortcutType.SCT_COMMAND;
|
||||
m_iCommand = iCommand;
|
||||
m_dwParam = 0;
|
||||
m_dwParam = 0;
|
||||
}
|
||||
public override string GetDesc()
|
||||
{
|
||||
CECStringTab pDescTab = EC_Game.GetItemDesc();
|
||||
string szDesc = ("");
|
||||
|
||||
switch ((CommandID)m_iCommand)
|
||||
{
|
||||
case CMD_SITDOWN: szDesc = pDescTab.GetWideString((int)CMDDESC_SITDOWN); break;
|
||||
case CMD_WALKRUN: szDesc = pDescTab.GetWideString((int)CMDDESC_WALKRUN); break;
|
||||
case CMD_NORMALATTACK: szDesc = pDescTab.GetWideString((int)CMDDESC_NORMALATTACK); break;
|
||||
case CMD_FINDTARGET: szDesc = pDescTab.GetWideString((int)CMDDESC_FINDTARGET); break;
|
||||
case CMD_ASSISTATTACK: szDesc = pDescTab.GetWideString((int)CMDDESC_ASSISTATTACK); break;
|
||||
case CMD_INVITETOTEAM: szDesc = pDescTab.GetWideString((int)CMDDESC_INVITETOTEAM); break;
|
||||
case CMD_LEAVETEAM: szDesc = pDescTab.GetWideString((int)CMDDESC_LEAVETEAM); break;
|
||||
case CMD_KICKTEAMMEM: szDesc = pDescTab.GetWideString((int)CMDDESC_KICKTEAMMEM); break;
|
||||
case CMD_FINDTEAM: szDesc = pDescTab.GetWideString((int)CMDDESC_FINDTEAM); break;
|
||||
case CMD_STARTTRADE: szDesc = pDescTab.GetWideString((int)CMDDESC_STARTTRADE); break;
|
||||
case CMD_SELLBOOTH: szDesc = pDescTab.GetWideString((int)CMDDESC_SELLBOOTH); break;
|
||||
case CMD_BUYBOOTH: szDesc = pDescTab.GetWideString((int)CMDDESC_BUYBOOTH); break;
|
||||
case CMD_INVITETOFACTION: szDesc = pDescTab.GetWideString((int)CMDDESC_INVITETOFACTION); break;
|
||||
case CMD_FLY: szDesc = pDescTab.GetWideString((int)CMDDESC_FLY); break;
|
||||
case CMD_PICKUP: szDesc = pDescTab.GetWideString((int)CMDDESC_PICKUP); break;
|
||||
case CMD_GATHER: szDesc = pDescTab.GetWideString((int)CMDDESC_GATHER); break;
|
||||
case CMD_RUSHFLY: szDesc = pDescTab.GetWideString((int)CMDDESC_RUSHFLY); break;
|
||||
case CMD_BINDBUDDY: szDesc = pDescTab.GetWideString((int)CMDDESC_BINDBUDDY); break;
|
||||
|
||||
case CMD_PLAYPOSE:
|
||||
{
|
||||
switch ((RoleExpression)m_dwParam)
|
||||
{
|
||||
case ROLEEXP_WAVE: szDesc = pDescTab.GetWideString((int)FACEDESC_WAVEHAND); break;
|
||||
case ROLEEXP_NOD: szDesc = pDescTab.GetWideString((int)FACEDESC_NOD); break;
|
||||
case ROLEEXP_SHAKEHEAD: szDesc = pDescTab.GetWideString((int)FACEDESC_SHADEHEAD); break;
|
||||
case ROLEEXP_SHRUG: szDesc = pDescTab.GetWideString((int)FACEDESC_SHRUG); break;
|
||||
case ROLEEXP_LAUGH: szDesc = pDescTab.GetWideString((int)FACEDESC_LAUGH); break;
|
||||
case ROLEEXP_ANGRY: szDesc = pDescTab.GetWideString((int)FACEDESC_ANGRY); break;
|
||||
case ROLEEXP_STUN: szDesc = pDescTab.GetWideString((int)FACEDESC_FAINT); break;
|
||||
case ROLEEXP_DEPRESSED: szDesc = pDescTab.GetWideString((int)FACEDESC_SAD); break;
|
||||
case ROLEEXP_KISSHAND: szDesc = pDescTab.GetWideString((int)FACEDESC_KISSHAND); break;
|
||||
case ROLEEXP_SHY: szDesc = pDescTab.GetWideString((int)FACEDESC_SHY); break;
|
||||
case ROLEEXP_SALUTE: szDesc = pDescTab.GetWideString((int)FACEDESC_SALUTE); break;
|
||||
case ROLEEXP_SITDOWN: szDesc = pDescTab.GetWideString((int)FACEDESC_SITDOWN); break;
|
||||
case ROLEEXP_ASSAULT: szDesc = pDescTab.GetWideString((int)FACEDESC_CHARGE); break;
|
||||
case ROLEEXP_THINK: szDesc = pDescTab.GetWideString((int)FACEDESC_THINK); break;
|
||||
case ROLEEXP_DEFIANCE: szDesc = pDescTab.GetWideString((int)FACEDESC_CHALLENGE); break;
|
||||
case ROLEEXP_VICTORY: szDesc = pDescTab.GetWideString((int)FACEDESC_WIN); break;
|
||||
case ROLEEXP_GAPE: szDesc = pDescTab.GetWideString((int)FACEDESC_GAPE); break;
|
||||
case ROLEEXP_KISS: szDesc = pDescTab.GetWideString((int)FACEDESC_KISS); break;
|
||||
case ROLEEXP_FIGHT: szDesc = pDescTab.GetWideString((int)FACEDESC_FIGHT); break;
|
||||
case ROLEEXP_ATTACK1: szDesc = pDescTab.GetWideString((int)FACEDESC_ATTACK1); break;
|
||||
case ROLEEXP_ATTACK2: szDesc = pDescTab.GetWideString((int)FACEDESC_ATTACK2); break;
|
||||
case ROLEEXP_ATTACK3: szDesc = pDescTab.GetWideString((int)FACEDESC_ATTACK3); break;
|
||||
case ROLEEXP_ATTACK4: szDesc = pDescTab.GetWideString((int)FACEDESC_ATTACK4); break;
|
||||
case ROLEEXP_DEFENCE: szDesc = pDescTab.GetWideString((int)FACEDESC_DEFENCE); break;
|
||||
case ROLEEXP_FALL: szDesc = pDescTab.GetWideString((int)FACEDESC_FALL); break;
|
||||
case ROLEEXP_FALLONGROUND: szDesc = pDescTab.GetWideString((int)FACEDESC_FALLONGROUND); break;
|
||||
case ROLEEXP_LOOKAROUND: szDesc = pDescTab.GetWideString((int)FACEDESC_LOOKAROUND); break;
|
||||
case ROLEEXP_DANCE: szDesc = pDescTab.GetWideString((int)FACEDESC_DANCE); break;
|
||||
case ROLEEXP_FASHIONWEAPON: szDesc = pDescTab.GetWideString((int)FACEDESC_FASHIONWEAPON); break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return ("");
|
||||
}
|
||||
|
||||
return szDesc;
|
||||
}
|
||||
public CECSCCommand(CECSCCommand src)
|
||||
{
|
||||
m_iCommand = src.m_iCommand;
|
||||
m_dwParam = src.m_dwParam;
|
||||
m_dwParam = src.m_dwParam;
|
||||
}
|
||||
public const int CMD_PLAYPOSE = 1; // Example constant
|
||||
// public override ShortcutType GetType() => ShortcutType.SCT_COMMAND;
|
||||
public override CECShortcut Clone() => new CECSCCommand(this);
|
||||
public int GetCommandID() => 0;
|
||||
public int GetParam() => 0;
|
||||
|
||||
|
||||
// Set / Get command parameter
|
||||
public void SetParam(uint dwParam) { m_dwParam = dwParam; }
|
||||
|
||||
|
||||
// Execute shortcut
|
||||
public override bool Execute()
|
||||
{
|
||||
@@ -863,44 +945,112 @@ namespace BrewMonster
|
||||
//
|
||||
// if (bForbidCmd)
|
||||
// {
|
||||
// g_pGame->GetGameRun()->AddFixedMessage(FIXMSG_CMD_INCOOLTIME);
|
||||
// g_pGame.GetGameRun().AddFixedMessage(FIXMSG_CMD_INCOOLTIME);
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
switch (m_iCommand)
|
||||
{
|
||||
// case CMD_SITDOWN: pHost->CmdSitDown(!pHost->IsSitting()); break;
|
||||
// case CMD_WALKRUN: pHost->CmdWalkRun(!pHost->GetWalkRunFlag()); break;
|
||||
// case CMD_NORMALATTACK: pHost->CmdNormalAttack(); break;
|
||||
// case CMD_FINDTARGET: pHost->CmdFindTarget(); break;
|
||||
// case CMD_ASSISTATTACK: pHost->CmdAssistAttack(); break;
|
||||
// case CMD_INVITETOTEAM: pHost->CmdInviteToTeam(); break;
|
||||
// case CMD_LEAVETEAM: pHost->CmdLeaveTeam(); break;
|
||||
// case CMD_KICKTEAMMEM: pHost->CmdKickTeamMember(); break;
|
||||
// case CMD_FINDTEAM: pHost->CmdFindTeam(); break;
|
||||
// case CMD_STARTTRADE: pHost->CmdStartTrade(); break;
|
||||
// case CMD_SELLBOOTH: pHost->CmdSellBooth(); break;
|
||||
// case CMD_BUYBOOTH: pHost->CmdBuyBooth(); break;
|
||||
// case CMD_SITDOWN: pHost.CmdSitDown(!pHost.IsSitting()); break;
|
||||
// case CMD_WALKRUN: pHost.CmdWalkRun(!pHost.GetWalkRunFlag()); break;
|
||||
// case CMD_NORMALATTACK: pHost.CmdNormalAttack(); break;
|
||||
// case CMD_FINDTARGET: pHost.CmdFindTarget(); break;
|
||||
// case CMD_ASSISTATTACK: pHost.CmdAssistAttack(); break;
|
||||
// case CMD_INVITETOTEAM: pHost.CmdInviteToTeam(); break;
|
||||
// case CMD_LEAVETEAM: pHost.CmdLeaveTeam(); break;
|
||||
// case CMD_KICKTEAMMEM: pHost.CmdKickTeamMember(); break;
|
||||
// case CMD_FINDTEAM: pHost.CmdFindTeam(); break;
|
||||
// case CMD_STARTTRADE: pHost.CmdStartTrade(); break;
|
||||
// case CMD_SELLBOOTH: pHost.CmdSellBooth(); break;
|
||||
// case CMD_BUYBOOTH: pHost.CmdBuyBooth(); break;
|
||||
case (int)CommandID.CMD_PLAYPOSE: pHost.CmdStartPose((int)m_dwParam); break;
|
||||
// case CMD_INVITETOFACTION: pHost->CmdInviteToFaction(); break;
|
||||
// case CMD_INVITETOFACTION: pHost.CmdInviteToFaction(); break;
|
||||
// case CMD_FLY:
|
||||
// {
|
||||
// // Èç¹ûÆï³ËÒª·ÉÐУ¬ÔòÕâЩ action switcher£¬·ñÔò CmdFly
|
||||
// if (!pHost->GetActionSwitcher() || !pHost->GetActionSwitcher()->OnRideToFlyAction())
|
||||
// pHost->CmdFly();
|
||||
// if (!pHost.GetActionSwitcher() || !pHost.GetActionSwitcher().OnRideToFlyAction())
|
||||
// pHost.CmdFly();
|
||||
// break;
|
||||
// }
|
||||
// case CMD_PICKUP: pHost->CmdPickup(); break;
|
||||
// case CMD_GATHER: pHost->CmdGather(); break;
|
||||
// case CMD_RUSHFLY: pHost->CmdRushFly(); break;
|
||||
// case CMD_BINDBUDDY: pHost->CmdBindBuddy(pHost->GetSelectedTarget()); break;
|
||||
// case CMD_PICKUP: pHost.CmdPickup(); break;
|
||||
// case CMD_GATHER: pHost.CmdGather(); break;
|
||||
// case CMD_RUSHFLY: pHost.CmdRushFly(); break;
|
||||
// case CMD_BINDBUDDY: pHost.CmdBindBuddy(pHost.GetSelectedTarget()); break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override string GetIconFile()
|
||||
{
|
||||
string szIconFile = "";
|
||||
switch ((CommandID)m_iCommand)
|
||||
{
|
||||
case CommandID.CMD_SITDOWN: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_SITDOWN); break;
|
||||
case CommandID.CMD_WALKRUN: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_WALKRUN); break;
|
||||
case CommandID.CMD_NORMALATTACK: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_NORMALATTACK); break;
|
||||
case CommandID.CMD_FINDTARGET: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_FINDTARGET); break;
|
||||
case CommandID.CMD_ASSISTATTACK: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_ASSISTATTACK); break;
|
||||
case CommandID.CMD_INVITETOTEAM: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_INVITETOTEAM); break;
|
||||
case CommandID.CMD_LEAVETEAM: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_LEAVETEAM); break;
|
||||
case CommandID.CMD_KICKTEAMMEM: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_KICKTEAMMEM); break;
|
||||
case CommandID.CMD_FINDTEAM: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_FINDTEAM); break;
|
||||
case CommandID.CMD_STARTTRADE: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_STARTTRADE); break;
|
||||
case CommandID.CMD_SELLBOOTH: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_SELLBOOTH); break;
|
||||
case CommandID.CMD_BUYBOOTH: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_BUYBOOTH); break;
|
||||
case CommandID.CMD_INVITETOFACTION: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_INVITETOFACTION); break;
|
||||
case CommandID.CMD_FLY: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_FLY); break;
|
||||
case CommandID.CMD_PICKUP: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_PICKUP); break;
|
||||
case CommandID.CMD_GATHER: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_GATHER); break;
|
||||
case CommandID.CMD_RUSHFLY: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_RUSHFLY); break;
|
||||
case CommandID.CMD_BINDBUDDY: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_BINDBUDDY); break;
|
||||
|
||||
case CommandID.CMD_PLAYPOSE:
|
||||
{
|
||||
switch ((RoleExpression)m_dwParam)
|
||||
{
|
||||
case RoleExpression.ROLEEXP_WAVE: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_EXP_WAVE); break;
|
||||
case RoleExpression.ROLEEXP_NOD: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_EXP_NOD); break;
|
||||
case RoleExpression.ROLEEXP_SHAKEHEAD: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_EXP_SHAKEHEAD); break;
|
||||
case RoleExpression.ROLEEXP_SHRUG: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_EXP_SHRUG); break;
|
||||
case RoleExpression.ROLEEXP_LAUGH: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_EXP_LAUGH); break;
|
||||
case RoleExpression.ROLEEXP_ANGRY: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_EXP_ANGRY); break;
|
||||
case RoleExpression.ROLEEXP_STUN: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_EXP_STUN); break;
|
||||
case RoleExpression.ROLEEXP_DEPRESSED: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_EXP_DEPRESSED); break;
|
||||
case RoleExpression.ROLEEXP_KISSHAND: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_EXP_KISSHAND); break;
|
||||
case RoleExpression.ROLEEXP_SHY: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_EXP_SHY); break;
|
||||
case RoleExpression.ROLEEXP_SALUTE: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_EXP_SALUTE); break;
|
||||
case RoleExpression.ROLEEXP_SITDOWN: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_EXP_SITDOWN); break;
|
||||
case RoleExpression.ROLEEXP_ASSAULT: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_EXP_ASSAULT); break;
|
||||
case RoleExpression.ROLEEXP_THINK: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_EXP_THINK); break;
|
||||
case RoleExpression.ROLEEXP_DEFIANCE: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_EXP_DEFIANCE); break;
|
||||
case RoleExpression.ROLEEXP_VICTORY: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_EXP_VICTORY); break;
|
||||
case RoleExpression.ROLEEXP_GAPE: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_EXP_GAPE); break;
|
||||
case RoleExpression.ROLEEXP_KISS: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_EXP_KISS); break;
|
||||
case RoleExpression.ROLEEXP_FIGHT: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_EXP_FIGHT); break;
|
||||
case RoleExpression.ROLEEXP_ATTACK1: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_EXP_ATTACK1); break;
|
||||
case RoleExpression.ROLEEXP_ATTACK2: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_EXP_ATTACK2); break;
|
||||
case RoleExpression.ROLEEXP_ATTACK3: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_EXP_ATTACK3); break;
|
||||
case RoleExpression.ROLEEXP_ATTACK4: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_EXP_ATTACK4); break;
|
||||
case RoleExpression.ROLEEXP_DEFENCE: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_EXP_DEFENCE); break;
|
||||
case RoleExpression.ROLEEXP_FALL: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_EXP_FALL); break;
|
||||
case RoleExpression.ROLEEXP_FALLONGROUND: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_EXP_FALLONGROUND); break;
|
||||
case RoleExpression.ROLEEXP_LOOKAROUND: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_EXP_LOOKAROUND); break;
|
||||
case RoleExpression.ROLEEXP_DANCE: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_EXP_DANCE); break;
|
||||
case RoleExpression.ROLEEXP_FASHIONWEAPON: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_EXP_FASHIONWEAPON); break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
|
||||
return szIconFile;
|
||||
}
|
||||
// Get item cool time
|
||||
int GetCoolTime(ref int piMax/* NULL */)
|
||||
{
|
||||
@@ -920,15 +1070,15 @@ namespace BrewMonster
|
||||
break;
|
||||
|
||||
case CommandID.CMD_BINDBUDDY:
|
||||
{
|
||||
// CECCounter& cnt = pHost->GetBindCmdCoolCnt();
|
||||
// iTime = cnt.GetPeriod() - cnt.GetCounter();
|
||||
//
|
||||
// if (piMax)
|
||||
// *piMax = cnt.GetPeriod();
|
||||
{
|
||||
// CECCounter& cnt = pHost.GetBindCmdCoolCnt();
|
||||
// iTime = cnt.GetPeriod() - cnt.GetCounter();
|
||||
//
|
||||
// if (piMax)
|
||||
// *piMax = cnt.GetPeriod();
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
||||
// if (piMax) *piMax = 0;
|
||||
@@ -939,37 +1089,37 @@ namespace BrewMonster
|
||||
}
|
||||
}
|
||||
|
||||
/* public class CECSCSkill : CECShortcut
|
||||
{
|
||||
private CECSkill m_pSkill;
|
||||
public override ShortcutType GetType() => ShortcutType.SCT_SKILL;
|
||||
public override CECShortcut Clone() => null;
|
||||
public bool Init(CECSkill pSkill) { m_pSkill = pSkill; return true; }
|
||||
public CECSkill GetSkill() => m_pSkill;
|
||||
public void SetSkill(CECSkill pSkill) { m_pSkill = pSkill; }
|
||||
}
|
||||
/* public class CECSCSkill : CECShortcut
|
||||
{
|
||||
private CECSkill m_pSkill;
|
||||
public override ShortcutType GetType() => ShortcutType.SCT_SKILL;
|
||||
public override CECShortcut Clone() => null;
|
||||
public bool Init(CECSkill pSkill) { m_pSkill = pSkill; return true; }
|
||||
public CECSkill GetSkill() => m_pSkill;
|
||||
public void SetSkill(CECSkill pSkill) { m_pSkill = pSkill; }
|
||||
}
|
||||
|
||||
public class CECSCItem : CECShortcut
|
||||
{
|
||||
private int m_iInventory;
|
||||
private int m_iIvtrSlot;
|
||||
private int m_iItemTID;
|
||||
private bool m_bAutoFind;
|
||||
public class CECSCItem : CECShortcut
|
||||
{
|
||||
private int m_iInventory;
|
||||
private int m_iIvtrSlot;
|
||||
private int m_iItemTID;
|
||||
private bool m_bAutoFind;
|
||||
|
||||
public override ShortcutType GetType() => ShortcutType.SCT_ITEM;
|
||||
public override CECShortcut Clone() => null;
|
||||
public bool Init(int iIvtr, int iSlot, CECIvtrItem pItem)
|
||||
{
|
||||
m_iInventory = iIvtr;
|
||||
m_iIvtrSlot = iSlot;
|
||||
return true;
|
||||
}
|
||||
public int GetInventory() => m_iInventory;
|
||||
public int GetIvtrSlot() => m_iIvtrSlot;
|
||||
public int GetItemTID() => m_iItemTID;
|
||||
public bool GetAutoFindFlag() => m_bAutoFind;
|
||||
public void MoveItem(int iIvtr, int iSlot) { m_iInventory = iIvtr; m_iIvtrSlot = iSlot; }
|
||||
}*/
|
||||
public override ShortcutType GetType() => ShortcutType.SCT_ITEM;
|
||||
public override CECShortcut Clone() => null;
|
||||
public bool Init(int iIvtr, int iSlot, CECIvtrItem pItem)
|
||||
{
|
||||
m_iInventory = iIvtr;
|
||||
m_iIvtrSlot = iSlot;
|
||||
return true;
|
||||
}
|
||||
public int GetInventory() => m_iInventory;
|
||||
public int GetIvtrSlot() => m_iIvtrSlot;
|
||||
public int GetItemTID() => m_iItemTID;
|
||||
public bool GetAutoFindFlag() => m_bAutoFind;
|
||||
public void MoveItem(int iIvtr, int iSlot) { m_iInventory = iIvtr; m_iIvtrSlot = iSlot; }
|
||||
}*/
|
||||
|
||||
/* public class CECSCSkillGrp : CECShortcut
|
||||
{
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -12,8 +12,12 @@
|
||||
* Copyright (c) 2005 Archosaur Studio, All Rights Reserved.
|
||||
*/
|
||||
|
||||
using BrewMonster.Assets.PerfectWorld.Scripts.Players;
|
||||
using BrewMonster.Network;
|
||||
using BrewMonster.Scripts.Skills;
|
||||
using CSNetwork;
|
||||
using UnityEngine;
|
||||
using static CECPlayerWrapper;
|
||||
|
||||
namespace BrewMonster
|
||||
{
|
||||
@@ -79,12 +83,9 @@ namespace BrewMonster
|
||||
m_bIgnoreAtkLoop = bIgnoreAtkLoop;
|
||||
|
||||
// TODO: Get combo skill configuration from CECConfigs
|
||||
// CECConfigs pCfg = g_pGame.GetConfigs();
|
||||
// m_cs = pCfg.GetVideoSettings().comboSkill[iGroup];
|
||||
// For now, we'll just initialize with empty data
|
||||
m_cs = new EC_COMBOSKILL(true);
|
||||
CECConfigs pCfg = EC_Game.GetConfigs();
|
||||
m_cs = pCfg.GetVideoSettings().comboSkill[iGroup];
|
||||
|
||||
// Find the last loop start flag - 查找最后一个循环开始标记 / Find the last loop start flag
|
||||
m_iLoopStart = -1;
|
||||
for (int i = 0; i < EC_ConfigConstants.EC_COMBOSKILL_LEN; i++)
|
||||
{
|
||||
@@ -130,7 +131,7 @@ namespace BrewMonster
|
||||
return false;
|
||||
|
||||
// TODO: Get PlayerWrapper from CECAutoPolicy
|
||||
// CECPlayerWrapper pWrapper = CECAutoPolicy.GetInstance().GetPlayerWrapper();
|
||||
CECPlayerWrapper pWrapper = CECAutoPolicy.GetInstance().GetPlayerWrapper();
|
||||
|
||||
int idSkill = GetNextSkill();
|
||||
if (idSkill > 0)
|
||||
@@ -143,27 +144,27 @@ namespace BrewMonster
|
||||
if (!IsStop())
|
||||
{
|
||||
// TODO: Post message to continue combo skill
|
||||
// g_pGame.GetGameRun().PostMessage(MSG_HST_CONTINUECOMBOSKILL, MAN_PLAYER, 0, bMeleeing ? 1 : 0, m_iGroup);
|
||||
EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_CONTINUECOMBOSKILL, MANAGER_INDEX.MAN_PLAYER, 0, bMeleeing ? 1 : 0, m_iGroup);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 连击技能停止 / Combo skill finish
|
||||
// TODO: AP_ActionEvent(AP_EVENT_COMBOFINISH);
|
||||
AP_ActionEvent((int)AP_EVENT. AP_EVENT_COMBOFINISH);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Handle auto policy events
|
||||
// if (CECAutoPolicy.GetInstance().IsAutoPolicyEnabled())
|
||||
// pWrapper.AddAttackError();
|
||||
if (CECAutoPolicy.GetInstance().IsAutoPolicyEnabled())
|
||||
pWrapper.AddAttackError();
|
||||
|
||||
// 检测自己施放是否追加 / Check if self-cast should be tracked
|
||||
int iSelfCureFlag = 0;
|
||||
if (m_pHost.GetPrepSkill() != null)
|
||||
iSelfCureFlag = 1;
|
||||
|
||||
// TODO: AP_ActionEvent(AP_EVENT_COMBOCONTINUE, iSelfCureFlag);
|
||||
AP_ActionEvent((int)AP_EVENT.AP_EVENT_COMBOCONTINUE, iSelfCureFlag);
|
||||
}
|
||||
}
|
||||
else if (idSkill == (short)SpecialSkillID.SID_ATTACK)
|
||||
@@ -175,10 +176,10 @@ namespace BrewMonster
|
||||
if (bRet)
|
||||
{
|
||||
// TODO: Handle auto policy events
|
||||
// if (CECAutoPolicy.GetInstance().IsAutoPolicyEnabled())
|
||||
// pWrapper.AddAttackError();
|
||||
if (CECAutoPolicy.GetInstance().IsAutoPolicyEnabled())
|
||||
pWrapper.AddAttackError();
|
||||
|
||||
// TODO: AP_ActionEvent(AP_EVENT_COMBOCONTINUE);
|
||||
AP_ActionEvent((int)AP_EVENT.AP_EVENT_COMBOCONTINUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -186,12 +187,12 @@ namespace BrewMonster
|
||||
if (!IsStop())
|
||||
{
|
||||
// TODO: Post message to continue combo skill
|
||||
// g_pGame.GetGameRun().PostMessage(MSG_HST_CONTINUECOMBOSKILL, MAN_PLAYER, 0, bMeleeing ? 1 : 0, m_iGroup);
|
||||
EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_CONTINUECOMBOSKILL, MANAGER_INDEX.MAN_PLAYER, 0, bMeleeing ? 1 : 0, m_iGroup);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 连击技能停止 / Combo skill finish
|
||||
// TODO: AP_ActionEvent(AP_EVENT_COMBOFINISH);
|
||||
AP_ActionEvent((int)AP_EVENT.AP_EVENT_COMBOFINISH);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -203,12 +204,12 @@ namespace BrewMonster
|
||||
if (!IsStop())
|
||||
{
|
||||
// TODO: Post message to continue combo skill
|
||||
// g_pGame.GetGameRun().PostMessage(MSG_HST_CONTINUECOMBOSKILL, MAN_PLAYER, 0, bMeleeing ? 1 : 0, m_iGroup);
|
||||
EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_CONTINUECOMBOSKILL, MANAGER_INDEX.MAN_PLAYER, 0, bMeleeing ? 1 : 0, m_iGroup);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 连击技能停止 / Combo skill finish
|
||||
// TODO: AP_ActionEvent(AP_EVENT_COMBOFINISH);
|
||||
AP_ActionEvent((int)AP_EVENT.AP_EVENT_COMBOFINISH);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -326,6 +327,16 @@ namespace BrewMonster
|
||||
{
|
||||
return m_iGroup;
|
||||
}
|
||||
public void AP_ActionEvent(int iEvent, int iParam = 0)
|
||||
{
|
||||
if (!CECAutoPolicy.GetInstance().IsAutoPolicyEnabled())
|
||||
return;
|
||||
|
||||
CECPlayerWrapper pWrapper = CECAutoPolicy.GetInstance().GetPlayerWrapper();
|
||||
if (pWrapper != null) pWrapper.OnActionEvent(iEvent, iParam);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
using BrewMonster.Network;
|
||||
using BrewMonster.Scripts;
|
||||
using BrewMonster.Scripts.Skills;
|
||||
using CSNetwork.GPDataType;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BrewMonster
|
||||
{
|
||||
/// <summary>
|
||||
/// Shortcut representing a combo skill group.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class CECSCSkillGrp : CECShortcut
|
||||
{
|
||||
private int m_iGroupIdx;
|
||||
private string m_strDesc;
|
||||
|
||||
public CECSCSkillGrp()
|
||||
{
|
||||
m_iSCType = (int)ShortcutType.SCT_SKILLGRP;
|
||||
m_iGroupIdx = -1;
|
||||
m_strDesc = string.Empty;
|
||||
}
|
||||
|
||||
private CECSCSkillGrp(CECSCSkillGrp src)
|
||||
{
|
||||
m_iSCType = src.m_iSCType;
|
||||
m_iGroupIdx = src.m_iGroupIdx;
|
||||
m_strDesc = src.m_strDesc;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the shortcut and build its description from the string tables.
|
||||
/// </summary>
|
||||
public bool Init(int iGroupIdx)
|
||||
{
|
||||
m_iGroupIdx = iGroupIdx;
|
||||
var strTab = EC_Game.GetItemDesc();
|
||||
string format = strTab?.GetWideString((int)DescriptipionMsg.CMDDESC_SKILLGROUP);
|
||||
|
||||
if (string.IsNullOrEmpty(format))
|
||||
m_strDesc = $"Skill Group {m_iGroupIdx}";
|
||||
else
|
||||
m_strDesc = GPDataTypeHelper.ReplacePercentD(format, m_iGroupIdx);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public int GetGroupIndex() => m_iGroupIdx;
|
||||
|
||||
public string GetDesc() => m_strDesc;
|
||||
|
||||
public override CECShortcut Clone() => new CECSCSkillGrp(this);
|
||||
|
||||
public override bool Execute()
|
||||
{
|
||||
CECHostPlayer host = EC_Game.GetGameRun().GetHostPlayer();
|
||||
if (host == null) {
|
||||
BMLogger.LogError("HostPlayer = null in CECSCSkillGrp::Execute");
|
||||
return false;
|
||||
}
|
||||
|
||||
host.ApplyComboSkill(m_iGroupIdx, false, -1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 512f4bac6274464499a0be2923ed4d63
|
||||
@@ -0,0 +1,85 @@
|
||||
// Filename : CECSkillConvert.cs
|
||||
// Creator : zhangyitian
|
||||
// Date : 2014/07/09
|
||||
// Converted to C# from EC_SkillConvert.cpp
|
||||
|
||||
using CSNetwork.GPDataType;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace BrewMonster.Scripts.Skills
|
||||
{
|
||||
// 神魔转换查询表 // God-Evil skill conversion table
|
||||
public class CECSkillConvert
|
||||
{
|
||||
private static CECSkillConvert instance;
|
||||
private Dictionary<int, int> m_convertTable;
|
||||
private bool m_bInitialized;
|
||||
|
||||
private CECSkillConvert()
|
||||
{
|
||||
m_convertTable = new Dictionary<int, int>();
|
||||
m_bInitialized = false;
|
||||
}
|
||||
|
||||
// 单例 // Singleton
|
||||
public static CECSkillConvert Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
instance = new CECSkillConvert();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
private void Initialize()
|
||||
{
|
||||
var pDB = ElementDataManProvider.GetElementDataMan();
|
||||
|
||||
var dt = DATA_TYPE.DT_GOD_EVIL_CONVERT_CONFIG;
|
||||
var map = pDB.GetAllDataTypeWithType(ID_SPACE.ID_SPACE_CONFIG, dt);
|
||||
if (map == null)
|
||||
{
|
||||
BMLogger.LogError("CECSkillConvert Initialize failed: no data found for DT_GOD_EVIL_CONVERT_CONFIG");
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var obj in map)
|
||||
{
|
||||
GOD_EVIL_CONVERT_CONFIG config = (GOD_EVIL_CONVERT_CONFIG)obj;
|
||||
if (config.skill_map != null)
|
||||
{
|
||||
for (int i = 0; i + 1 < map.Length; i += 2)
|
||||
{
|
||||
if (config.skill_map[i] != 0 &&
|
||||
config.skill_map[i+128] != 0)
|
||||
{
|
||||
m_convertTable[config.skill_map[i]] = config.skill_map[i + 128];
|
||||
m_convertTable[config.skill_map[i+128]] = config.skill_map[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_bInitialized = true;
|
||||
}
|
||||
|
||||
// 获得转换后的技能,返回0表示没有转换的技能 // Get the converted skill, return 0 if no conversion exists
|
||||
public int GetConvertSkill(int skillID)
|
||||
{
|
||||
if (!m_bInitialized)
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
|
||||
if (m_convertTable.TryGetValue(skillID, out int convertedSkillID))
|
||||
{
|
||||
return convertedSkillID;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7d3e4a2b8c9f4e1a9b6c5d8e7f3a2b1c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -44,13 +44,13 @@ namespace BrewMonster.Scripts.Skills
|
||||
{
|
||||
BMLogger.LogError("CECHostSkillModel BeforeSceneLoad Reset");
|
||||
Instance = null;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
public IReadOnlyDictionary<int, List<int>> GetAllRankProfSkills()
|
||||
{
|
||||
return m_allRankProfSkills;
|
||||
}
|
||||
public CECHostSkillModel()
|
||||
public CECHostSkillModel()
|
||||
{
|
||||
m_skillLearnNPCNID = 0;
|
||||
m_bReceivedNPCGreeting = false;
|
||||
@@ -84,6 +84,24 @@ namespace BrewMonster.Scripts.Skills
|
||||
//BMLogger.LogError($"[Skill] Sent SEVNPC_HELLO to skill-learn NPC nid={m_skillLearnNPCNID}");
|
||||
}
|
||||
}
|
||||
public enumEvilGod GetSkillEvilGod(int skillID)
|
||||
{
|
||||
CECSkill skill = new CECSkill(skillID, 1);
|
||||
int rank = skill.GetRank();
|
||||
CECTaoistRank taoistRank = CECTaoistRank.GetTaoistRank(rank);
|
||||
if (taoistRank.IsGodRank())
|
||||
{
|
||||
return enumEvilGod.SKILL_GOD;
|
||||
}
|
||||
else if (taoistRank.IsEvilRank())
|
||||
{
|
||||
return enumEvilGod.SKILL_EVIL;
|
||||
}
|
||||
else
|
||||
{
|
||||
return enumEvilGod.SKILL_BASE;
|
||||
}
|
||||
}
|
||||
public enumSkillLearnedState GetSkillLearnedState(int skillID)
|
||||
{
|
||||
CECSkill pSkill = CECGameRun.Instance.GetHostPlayer().GetNormalSkill(skillID);
|
||||
@@ -286,6 +304,16 @@ namespace BrewMonster.Scripts.Skills
|
||||
{
|
||||
return CECGameRun.Instance.GetHostPlayer().CheckSkillLearnCondition(skillID, true);
|
||||
}
|
||||
public string GetSkillDescription(int skillID, int level)
|
||||
{
|
||||
string tmp = "";
|
||||
if (CECSkill.GetDesc(skillID, level, tmp, 1024))
|
||||
{
|
||||
return (tmp);
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}
|
||||
public int GetRequiredBook(int skillID, int level)
|
||||
{
|
||||
int itemId = ElementSkill.GetRequiredBook((uint)skillID, level);
|
||||
@@ -372,9 +400,9 @@ namespace BrewMonster.Scripts.Skills
|
||||
var juniors = GetJunior(rootSkillID);
|
||||
int maxHeight = 0;
|
||||
|
||||
for (int i = 0; i < juniors.Count; i++)
|
||||
foreach(var skill in juniors)
|
||||
{
|
||||
int subHeight = GetSkillTreeHeight((int)juniors[i].id);
|
||||
int subHeight = GetSkillTreeHeight((int)skill.Key);
|
||||
if (subHeight > maxHeight)
|
||||
{
|
||||
maxHeight = subHeight;
|
||||
@@ -383,7 +411,7 @@ namespace BrewMonster.Scripts.Skills
|
||||
|
||||
return 1 + maxHeight;
|
||||
}
|
||||
private List<(uint id, int level)> GetJunior(int skillID)
|
||||
public Dictionary<uint, int> GetJunior(int skillID)
|
||||
{
|
||||
if (!m_allProfSkills.TryGetValue(skillID, out var skill))
|
||||
{
|
||||
@@ -391,14 +419,13 @@ namespace BrewMonster.Scripts.Skills
|
||||
}
|
||||
|
||||
var juniors = skill.GetJunior();
|
||||
var ret = new List<(uint id, int level)>();
|
||||
var ret = new Dictionary<uint, int>();
|
||||
|
||||
foreach (var (id, level) in juniors)
|
||||
{
|
||||
if (id != 0)
|
||||
ret.Add((id, level));
|
||||
ret[id] = level;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
private HashSet<int> GetRootSkillSet()
|
||||
@@ -436,7 +463,7 @@ namespace BrewMonster.Scripts.Skills
|
||||
{
|
||||
ElementSkill pSkill = ElementSkill.Create(skillService.id_skills[i], 1);
|
||||
|
||||
if (pSkill == null)
|
||||
if (pSkill == null)
|
||||
{
|
||||
//BMLogger.LogError($"Hoang Dev pSkill is null for skill {i} :" + skillService.id_skills[i]);
|
||||
continue;
|
||||
|
||||
@@ -100,8 +100,8 @@ namespace BrewMonster.Scripts.Skills
|
||||
public int move_env; //�ƶ����� // Movement environment
|
||||
public bool is_combat; //�Ƿ�ս��״̬ // Whether in combat state
|
||||
public int hp; //��ǰhp // Current HP
|
||||
public int max_hp; //���hp // Maximum HP
|
||||
// public ComboSkillState combo_state; //���������� // Combo skill state
|
||||
public int max_hp; //���hp // Maximum HP
|
||||
public ComboSkillState combo_state; //���������� // Combo skill state
|
||||
};
|
||||
|
||||
public struct GoblinUseRequirement
|
||||
@@ -191,7 +191,7 @@ namespace BrewMonster.Scripts.Skills
|
||||
return "";
|
||||
}
|
||||
// ����˵��
|
||||
public virtual string GetIntroduction(StringBuilder buf, int len, SkillStr table) { return ""; }
|
||||
public virtual void GetIntroduction(StringBuilder buf, SkillStr table) { }
|
||||
// ����ְҵ����
|
||||
public virtual int GetCls() { return -1; }
|
||||
// ������ȴʱ�䣬��λ����
|
||||
@@ -240,13 +240,30 @@ namespace BrewMonster.Scripts.Skills
|
||||
int ret = skill.GetRequiredBook();
|
||||
return ret;
|
||||
}
|
||||
// ѧϰ����ȼ�?
|
||||
public static int GetRequiredLevel(uint id, int level)
|
||||
{
|
||||
Skill s = Skill.Create(id, level);
|
||||
if (s == null)
|
||||
return 0;
|
||||
|
||||
int ret = s.GetRequiredLevel();
|
||||
return ret;
|
||||
}
|
||||
public virtual int GetRequiredRealmLevel() { return 0; }
|
||||
|
||||
public static int GetRequiredRealmLevel(uint id, int level)
|
||||
{
|
||||
Skill s = Skill.Create(id, level);
|
||||
if (s == null)
|
||||
return 0;
|
||||
|
||||
int ret = s.GetRequiredRealmLevel();
|
||||
return ret;
|
||||
}
|
||||
|
||||
public virtual Dictionary<uint, int> GetRequiredSkill() => new Dictionary<uint, int>();
|
||||
|
||||
|
||||
public virtual int GetShowOrder() { return 0; }
|
||||
|
||||
|
||||
public virtual int SetLevel(int level) { return 0; }
|
||||
|
||||
public static int SetLevel(uint id, int level)
|
||||
@@ -326,6 +343,41 @@ namespace BrewMonster.Scripts.Skills
|
||||
return s.IsMovingSkill();
|
||||
return false;
|
||||
}
|
||||
|
||||
public static Dictionary<uint, int> GetComboSkActivated(ComboSkillState comboState)
|
||||
{
|
||||
var result = new Dictionary<uint, int>();
|
||||
if (comboState.skillid == 0)
|
||||
return result;
|
||||
|
||||
if (SkillStub.GetComboSkMap().TryGetValue(comboState.skillid, out List<uint> postSkills) && postSkills != null)
|
||||
{
|
||||
foreach (uint skillId in postSkills)
|
||||
{
|
||||
Skill skill = Skill.Create(skillId, 1);
|
||||
if (skill == null)
|
||||
continue;
|
||||
|
||||
ref ComboArg comboArg = ref skill.GetPlayer().GetComboarg();
|
||||
for (int i = 0; i < ComboArg.MAX_COMBO_ARG; i++)
|
||||
{
|
||||
int argValue = 0;
|
||||
if (comboState.arg != null && i < comboState.arg.Length)
|
||||
{
|
||||
argValue = comboState.arg[i];
|
||||
}
|
||||
comboArg.SetValue((uint)i, argValue);
|
||||
}
|
||||
|
||||
if (skill.CheckComboSkExtraCondition())
|
||||
{
|
||||
result[skill.GetId()] = skill.GetComboSkInterval();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
// �����ܷ��ڵ�ǰ����״̬��ʹ�� // Whether skill can be used in current form state
|
||||
public bool IsValidForm(byte form)
|
||||
{
|
||||
@@ -363,13 +415,13 @@ namespace BrewMonster.Scripts.Skills
|
||||
skill = Skill.Create(id, ilevel);
|
||||
if (skill == null)
|
||||
return 5;
|
||||
|
||||
|
||||
int ret = 0;
|
||||
SkillWrapper wrapper = SkillWrapper.Instance;
|
||||
|
||||
if (wrapper.IsOverridden(id))
|
||||
return 11;
|
||||
|
||||
|
||||
int srank, prank;
|
||||
srank = skill.GetRank();
|
||||
prank = info.rank;
|
||||
@@ -389,17 +441,17 @@ namespace BrewMonster.Scripts.Skills
|
||||
ret = 4;
|
||||
else if (info.level < skill.GetRequiredLevel())
|
||||
ret = 2;
|
||||
|
||||
|
||||
if (ret != 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
if (info.sp < skill.GetRequiredSp())
|
||||
ret = 1;
|
||||
else if (info.money < skill.GetRequiredMoney())
|
||||
ret = 6;
|
||||
|
||||
|
||||
var pre_skills = skill.GetRequiredSkill();
|
||||
foreach (var kvp in pre_skills)
|
||||
{
|
||||
@@ -419,65 +471,75 @@ namespace BrewMonster.Scripts.Skills
|
||||
if (ability > 0 && wrapper.GetAbility(id) < ability)
|
||||
ret = 10;
|
||||
}
|
||||
|
||||
|
||||
if (info.realm_level < skill.GetRequiredRealmLevel())
|
||||
ret = 12;
|
||||
|
||||
return ret;
|
||||
}
|
||||
// 0:�ɹ� 1:����SP���� 2:�����츳�㲻��
|
||||
// 3:���� 4:���ܸ������� 5:����ID
|
||||
// 6:��Ǯ���� 7:��С���鼼�� 8:û�м�����
|
||||
// 9:�ȼ����� 10:���������� 11:ְҵ��ƥ��
|
||||
// 12:���������㣬��ְҵ��ƥ��
|
||||
// 3:���� 4:���ܸ������� 5:����ID
|
||||
// 6:��Ǯ���� 7:��С���鼼�� 8:û�м�����
|
||||
// 9:�ȼ����� 10:���������� 11:ְҵ��ƥ��
|
||||
// 12:���������㣬��ְҵ��ƥ��
|
||||
public static int GoblinLearn(uint id, GoblinRequirement info, int level)
|
||||
{
|
||||
Skill s = Skill.Create(id, level);
|
||||
if(s == null)
|
||||
if (s == null)
|
||||
return 5;
|
||||
if(level<1 || level> s.GetMaxLevel())
|
||||
if (level < 1 || level > s.GetMaxLevel())
|
||||
return 3;
|
||||
if(s.GetCls() != 258)
|
||||
if (s.GetCls() != 258)
|
||||
return 7;
|
||||
|
||||
|
||||
int ret = 0;
|
||||
|
||||
int[] iReqGen = new int[5] {0, 0, 0, 0, 0};
|
||||
|
||||
int[] iReqGen = new int[5] { 0, 0, 0, 0, 0 };
|
||||
int iReqLevel = s.GetRequiredLevel();
|
||||
// iReqLevelΪ7λ�����������λΪ�ȼ���ǰ5λΪ�츳���������λΪ��
|
||||
int iLevelRequirement = iReqLevel%100;
|
||||
if(info.level < iLevelRequirement)
|
||||
int iLevelRequirement = iReqLevel % 100;
|
||||
if (info.level < iLevelRequirement)
|
||||
return 9;
|
||||
|
||||
iReqLevel /= 100;
|
||||
|
||||
int i;
|
||||
for(i=0;i<5;i++)
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
iReqGen[4-i] = iReqLevel%10;
|
||||
iReqGen[4 - i] = iReqLevel % 10;
|
||||
iReqLevel /= 10;
|
||||
}
|
||||
|
||||
for(i=0;i<5;i++)
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
if(info.genius[i] < iReqGen[4-i])
|
||||
if (info.genius[i] < iReqGen[4 - i])
|
||||
return 2;
|
||||
}
|
||||
|
||||
if(info.sp < s.GetRequiredSp())
|
||||
|
||||
if (info.sp < s.GetRequiredSp())
|
||||
ret = 1;
|
||||
//else if(info.money<s->GetRequiredMoney(id, level))
|
||||
// ret = 6;
|
||||
|
||||
if(info.mp < s.GetMpCost() &&
|
||||
if (info.mp < s.GetMpCost() &&
|
||||
((s.GetCls() != 0) && (((1 << info.profession) & s.GetCls()) == 0)))
|
||||
ret = 12;
|
||||
else if(info.mp < s.GetMpCost())
|
||||
else if (info.mp < s.GetMpCost())
|
||||
ret = 10;
|
||||
else if((s.GetCls() != 0) && (((1 << info.profession) & s.GetCls()) == 0))
|
||||
else if ((s.GetCls() != 0) && (((1 << info.profession) & s.GetCls()) == 0))
|
||||
ret = 11;
|
||||
|
||||
return ret;
|
||||
}
|
||||
public virtual int GetComboSkPreSkill() { return 0; }
|
||||
public static int GetComboSkPreSkill(uint id)
|
||||
{
|
||||
SkillStub s = SkillStub.GetStub(id);
|
||||
if (s != null)
|
||||
{
|
||||
return s.combosk_preskill;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,260 @@
|
||||
# Comparison: OnMsgPlayerCastSkill - C++ vs C# Conversion
|
||||
|
||||
## Summary
|
||||
The conversion from C++ to C# is **mostly complete** but has some **missing elements** and **commented-out code** that should be reviewed.
|
||||
|
||||
## All Switch Cases Present ✅
|
||||
All 9 switch cases are present in both versions:
|
||||
1. ✅ `OBJECT_CAST_SKILL`
|
||||
2. ✅ `SKILL_PERFORM`
|
||||
3. ✅ `HOST_STOP_SKILL`
|
||||
4. ✅ `SELF_SKILL_INTERRUPTED`
|
||||
5. ✅ `OBJECT_CAST_INSTANT_SKILL`
|
||||
6. ✅ `OBJECT_CAST_POS_SKILL`
|
||||
7. ✅ `PLAYER_CAST_RUNE_SKILL`
|
||||
8. ✅ `PLAYER_CAST_RUNE_INSTANT_SKILL`
|
||||
9. ✅ `ERROR_MESSAGE`
|
||||
10. ✅ `default` case
|
||||
|
||||
## Missing/Incomplete Elements
|
||||
|
||||
### 1. Missing Assertion Check in OBJECT_CAST_SKILL ❌
|
||||
**C++ (line 5876):**
|
||||
```cpp
|
||||
ASSERT(pCmd->caster == m_PlayerInfo.cid);
|
||||
```
|
||||
|
||||
**C# (line 916):**
|
||||
```csharp
|
||||
// MISSING: No assertion check for pCmd.caster == m_PlayerInfo.cid
|
||||
```
|
||||
|
||||
**Impact:** Medium - This is a safety check that validates the caster ID matches the player's ID.
|
||||
|
||||
### 2. Commented Out AP_ActionEvent in HOST_STOP_SKILL ⚠️
|
||||
**C++ (line 5958):**
|
||||
```cpp
|
||||
AP_ActionEvent(AP_EVENT_STOPSKILL);
|
||||
```
|
||||
|
||||
**C# (line 1025):**
|
||||
```csharp
|
||||
//AP_ActionEvent(AP_EVENT_STOPSKILL);
|
||||
```
|
||||
|
||||
**Impact:** Medium - Action event notification is disabled. May affect auto-policy or other systems that listen to this event.
|
||||
|
||||
### 3. Commented Out AP_ActionEvent in SELF_SKILL_INTERRUPTED ⚠️
|
||||
**C++ (line 6005):**
|
||||
```cpp
|
||||
AP_ActionEvent(AP_EVENT_STOPSKILL);
|
||||
```
|
||||
|
||||
**C# (line 1084):**
|
||||
```csharp
|
||||
//AP_ActionEvent(AP_EVENT_STOPSKILL);
|
||||
```
|
||||
|
||||
**Impact:** Medium - Same as above.
|
||||
|
||||
### 4. Missing Fixed Message in SELF_SKILL_INTERRUPTED ⚠️
|
||||
**C++ (line 6003):**
|
||||
```cpp
|
||||
g_pGame->GetGameRun()->AddFixedMessage(FIXMSG_SKILLINTERRUPT);
|
||||
```
|
||||
|
||||
**C# (line 1081):**
|
||||
```csharp
|
||||
// g_pGame.GetGameRun().AddFixedMessage(FIXMSG_SKILLINTERRUPT);
|
||||
Debug.Log("Skill interrupted!");
|
||||
```
|
||||
|
||||
**Impact:** Low - Replaced with Debug.Log, but the fixed message system might be needed for UI notifications.
|
||||
|
||||
### 5. Missing Auto-Policy Event in SELF_SKILL_INTERRUPTED ⚠️
|
||||
**C++ (line 6008):**
|
||||
```cpp
|
||||
CECAutoPolicy::GetInstance().SendEvent_SkillInterrupt(skill_id);
|
||||
```
|
||||
|
||||
**C# (line 1087):**
|
||||
```csharp
|
||||
// CECAutoPolicy::GetInstance().SendEvent_SkillInterrupt(skill_id);
|
||||
```
|
||||
|
||||
**Impact:** Medium - Auto-policy system won't be notified of skill interruptions, which may affect automated gameplay features.
|
||||
|
||||
### 6. Commented Out Camera Update in OBJECT_CAST_POS_SKILL ⚠️
|
||||
**C++ (line 6080):**
|
||||
```cpp
|
||||
UpdateFollowCamera(false, 10);
|
||||
```
|
||||
|
||||
**C# (line 1165):**
|
||||
```csharp
|
||||
//UpdateFollowCamera(false, 10);
|
||||
```
|
||||
|
||||
**Impact:** Low - Camera update is disabled. May affect camera behavior for certain skills.
|
||||
|
||||
## Differences That Are Acceptable
|
||||
|
||||
### 1. Logging System Differences ✅
|
||||
**C++:**
|
||||
```cpp
|
||||
g_pGame->RuntimeDebugInfo(0xffffffff, _AL("Cast skill(%d): %s"), ...);
|
||||
```
|
||||
|
||||
**C#:**
|
||||
```csharp
|
||||
Debug.Log($"Cast skill({m_pCurSkill.GetSkillID()})");
|
||||
```
|
||||
|
||||
**Status:** Acceptable - Different logging systems, functionality preserved.
|
||||
|
||||
### 2. Additional Logging in C# ✅
|
||||
C# has extra logging for return-to-town skill (ID 167):
|
||||
```csharp
|
||||
if (m_pCurSkill.GetSkillID() == ID_RETURNTOWN_SKILL)
|
||||
{
|
||||
Debug.Log($"Return-to-town skill (167) cast - State2 should trigger SetReturntown(1) on server");
|
||||
}
|
||||
```
|
||||
|
||||
**Status:** Acceptable - Additional debugging/logging is fine.
|
||||
|
||||
### 3. Memory Management Differences ✅
|
||||
**C++:**
|
||||
```cpp
|
||||
if(m_pTargetItemSkill)
|
||||
{
|
||||
delete m_pTargetItemSkill;
|
||||
m_pTargetItemSkill = NULL;
|
||||
}
|
||||
```
|
||||
|
||||
**C#:**
|
||||
```csharp
|
||||
if (m_pTargetItemSkill != null)
|
||||
{
|
||||
m_pTargetItemSkill = null; // GC will handle cleanup
|
||||
}
|
||||
```
|
||||
|
||||
**Status:** Acceptable - C# uses garbage collection, no explicit delete needed.
|
||||
|
||||
### 4. Type Casting Differences ✅
|
||||
**C++:**
|
||||
```cpp
|
||||
cmd_object_cast_skill* pCmd = (cmd_object_cast_skill*)Msg.dwParam1;
|
||||
```
|
||||
|
||||
**C#:**
|
||||
```csharp
|
||||
cmd_object_cast_skill pCmd = GPDataTypeHelper.FromBytes<cmd_object_cast_skill>((byte[])Msg.dwParam1);
|
||||
```
|
||||
|
||||
**Status:** Acceptable - Different serialization approach, functionality preserved.
|
||||
|
||||
### 5. Switch Statement Syntax ✅
|
||||
**C++:**
|
||||
```cpp
|
||||
switch (Msg.dwParam2)
|
||||
{
|
||||
case OBJECT_CAST_SKILL:
|
||||
```
|
||||
|
||||
**C#:**
|
||||
```csharp
|
||||
switch (Convert.ToInt32(Msg.dwParam2))
|
||||
{
|
||||
case int value2 when value2 == CommandID.OBJECT_CAST_SKILL:
|
||||
```
|
||||
|
||||
**Status:** Acceptable - C# pattern matching syntax, functionality preserved.
|
||||
|
||||
## Post-Switch Code Comparison
|
||||
|
||||
### Action Start Event ✅
|
||||
**C++ (line 6241-6242):**
|
||||
```cpp
|
||||
if( bActionStartSkill )
|
||||
AP_ActionEvent(AP_EVENT_STARTSKILL, iActionTime);
|
||||
```
|
||||
|
||||
**C# (line 1338-1339):**
|
||||
```csharp
|
||||
if (bActionStartSkill)
|
||||
AP.AP_ActionEvent((int)AP_EVENT.AP_EVENT_STARTSKILL, iActionTime);
|
||||
```
|
||||
|
||||
**Status:** ✅ Complete - Properly converted and active.
|
||||
|
||||
### Do Other Thing Logic ✅
|
||||
**C++ (line 6244-6258):**
|
||||
```cpp
|
||||
if (bDoOtherThing)
|
||||
{
|
||||
if (m_pComboSkill && !m_pComboSkill->IsStop())
|
||||
{
|
||||
if( CECAutoPolicy::GetInstance().IsAutoPolicyEnabled() )
|
||||
g_pGame->GetGameRun()->PostMessage(MSG_HST_CONTINUECOMBOSKILL, MAN_PLAYER, 0, 0, m_pComboSkill->GetGroupIndex());
|
||||
else
|
||||
m_pComboSkill->Continue(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
if( idTarget && idTarget != m_PlayerInfo.cid )
|
||||
NormalAttackObject(idTarget, true);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**C# (line 1341-1357):**
|
||||
```csharp
|
||||
if (bDoOtherThing)
|
||||
{
|
||||
if (m_pComboSkill != null && !m_pComboSkill.IsStop())
|
||||
{
|
||||
if (CECAutoPolicy.GetInstance().IsAutoPolicyEnabled())
|
||||
EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_CONTINUECOMBOSKILL, MANAGER_INDEX.MAN_PLAYER, 0, 0, m_pComboSkill.GetGroupIndex());
|
||||
else
|
||||
m_pComboSkill.Continue(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (idTarget != 0 && idTarget != m_PlayerInfo.cid)
|
||||
NormalAttackObject(idTarget, true);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Status:** ✅ Complete - Properly converted with equivalent logic.
|
||||
|
||||
## Recommendations
|
||||
|
||||
### High Priority
|
||||
1. **Add missing assertion check** in `OBJECT_CAST_SKILL` case:
|
||||
```csharp
|
||||
Debug.Assert(pCmd.caster == m_PlayerInfo.cid, "Caster ID mismatch");
|
||||
```
|
||||
|
||||
### Medium Priority
|
||||
2. **Uncomment and verify** `AP_ActionEvent(AP_EVENT_STOPSKILL)` calls if the AP system is implemented in C#.
|
||||
3. **Uncomment** `CECAutoPolicy::GetInstance().SendEvent_SkillInterrupt(skill_id)` if auto-policy is needed.
|
||||
|
||||
### Low Priority
|
||||
4. **Review** if `UpdateFollowCamera` is needed for `OBJECT_CAST_POS_SKILL` case.
|
||||
5. **Consider** implementing `AddFixedMessage` system if UI notifications are needed for skill interruptions.
|
||||
|
||||
## Conclusion
|
||||
|
||||
**Conversion Completeness: ~90%**
|
||||
|
||||
The conversion is functionally complete with all major logic paths implemented. However, several safety checks and event notifications are commented out or missing, which may affect:
|
||||
- Auto-policy system integration
|
||||
- UI notifications for skill interruptions
|
||||
- Camera behavior for position-based skills
|
||||
- Safety validation (caster ID check)
|
||||
|
||||
These should be reviewed and either implemented or confirmed as intentionally disabled.
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 09b07dfdbdd8c094d9ded2ba81316847
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,625 @@
|
||||
# Flow: Create Skill Combo by Drag-Drop - C++ Implementation
|
||||
|
||||
## Overview
|
||||
This document describes the complete flow for creating a skill combo by drag-dropping individual skills into the combo skill list in the skill edit dialog. This is the process of building a combo skill sequence that can later be placed in the quick bar.
|
||||
|
||||
---
|
||||
|
||||
## Entry Points
|
||||
|
||||
### 1. **Open Skill Edit Dialog**
|
||||
|
||||
**Location:** `DlgSkillSubOther.cpp:49-57`
|
||||
|
||||
The user can open the skill edit dialog in two ways:
|
||||
|
||||
#### **A. Create New Combo Skill** (Button: "Btn_ConNew")
|
||||
```cpp
|
||||
// DlgSkillSubOther.cpp:54-57
|
||||
void CDlgSkillSubOther::OnCommandNew(const char * szCommand) {
|
||||
GetGameUIMan()->m_pDlgSkillEdit->SetData(0); // 0 = new combo
|
||||
GetGameUIMan()->m_pDlgSkillEdit->Show(true);
|
||||
}
|
||||
```
|
||||
|
||||
#### **B. Edit Existing Combo Skill** (Button: "Btn_ConEdi")
|
||||
```cpp
|
||||
// DlgSkillSubOther.cpp:49-52
|
||||
void CDlgSkillSubOther::OnCommandEdit(const char * szCommand) {
|
||||
GetGameUIMan()->m_pDlgSkillEdit->SetData(m_nComboSelect); // 1-based combo index
|
||||
GetGameUIMan()->m_pDlgSkillEdit->Show(true);
|
||||
}
|
||||
```
|
||||
|
||||
**Flow:**
|
||||
1. User clicks "New" or "Edit" button
|
||||
2. Set combo skill index (0 for new, 1-based for existing)
|
||||
3. Show skill edit dialog (`Win_SkillEdit`)
|
||||
|
||||
---
|
||||
|
||||
## Detailed Flow: Drag-Drop Skill to Combo List
|
||||
|
||||
### **Step 1: Skill Edit Dialog Initialization**
|
||||
|
||||
**Location:** `DlgSkillEdit.cpp:143-231` - `OnShowDialog()`
|
||||
|
||||
When the skill edit dialog is shown, it initializes the combo skill list:
|
||||
|
||||
```cpp
|
||||
// DlgSkillEdit.cpp:143-207
|
||||
void CDlgSkillEdit::OnShowDialog() {
|
||||
EC_VIDEO_SETTING setting = GetGame()->GetConfigs()->GetVideoSettings();
|
||||
|
||||
// If creating new combo (GetData() == 0), find first empty slot
|
||||
if( GetData() == 0 ) {
|
||||
for (i = 0; i < EC_COMBOSKILL_NUM; i++)
|
||||
if( setting.comboSkill[i].nIcon == 0 ) {
|
||||
SetData(i + 1); // Set to 1-based index
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Load existing combo skill data if editing
|
||||
if( setting.comboSkill[GetData() - 1].nIcon != 0 ) {
|
||||
// Load existing skills from config
|
||||
for (i = 0; i < EC_COMBOSKILL_LEN; i++) {
|
||||
int idSkill = setting.comboSkill[GetData() - 1].idSkill[i];
|
||||
if( idSkill > 0 ) {
|
||||
CECSkill *pSkill = GetHostPlayer()->GetNormalSkill(idSkill);
|
||||
if (!pSkill) pSkill = GetHostPlayer()->GetEquipSkillByID(idSkill);
|
||||
GetGameUIMan()->m_pDlgSkillSubOther->SetImage(pImage, pSkill);
|
||||
}
|
||||
else {
|
||||
// Special icons (Attack, Loop Start)
|
||||
int iType = -idSkill;
|
||||
SetSpecialIcon(pImage, iType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Key Points:**
|
||||
- Dialog displays empty slots (`Item_1`, `Item_2`, ..., `Item_N`) for combo skill list
|
||||
- Each slot can hold a skill or special icon (Attack, Loop Start)
|
||||
- Existing combo skills are loaded from `EC_VIDEO_SETTING.comboSkill[]`
|
||||
|
||||
---
|
||||
|
||||
### **Step 2: User Drags Skill from Skill List**
|
||||
|
||||
**Location:** `DlgSkillSubOther.cpp:235-253` - `OnEventLButtonDownFixed()` / `OnEventLButtonDownItem()`
|
||||
|
||||
Skills can be dragged from multiple sources:
|
||||
|
||||
#### **A. Fixed Skills** (`Img_InSkill*`)
|
||||
```cpp
|
||||
// DlgSkillSubOther.cpp:235-243
|
||||
void CDlgSkillSubOther::OnEventLButtonDownFixed(WPARAM wParam, LPARAM lParam, AUIObject * pObj) {
|
||||
if (pObj->GetDataPtr("ptr_CECSkill") == 0) {
|
||||
return; // No skill data
|
||||
}
|
||||
|
||||
A3DVIEWPORTPARAM *p = m_pA3DEngine->GetActiveViewport()->GetParam();
|
||||
GetGameUIMan()->m_ptLButtonDown.x = GET_X_LPARAM(lParam) - p->X;
|
||||
GetGameUIMan()->m_ptLButtonDown.y = GET_Y_LPARAM(lParam) - p->Y;
|
||||
GetGameUIMan()->InvokeDragDrop(this, pObj, GetGameUIMan()->m_ptLButtonDown);
|
||||
}
|
||||
```
|
||||
|
||||
#### **B. Item Skills** (`Img_ItemSkill*`)
|
||||
```cpp
|
||||
// DlgSkillSubOther.cpp:245-253
|
||||
void CDlgSkillSubOther::OnEventLButtonDownItem(WPARAM wParam, LPARAM lParam, AUIObject * pObj) {
|
||||
if (pObj->GetDataPtr("ptr_CECSkill") == 0) {
|
||||
return; // No skill data
|
||||
}
|
||||
|
||||
A3DVIEWPORTPARAM *p = m_pA3DEngine->GetActiveViewport()->GetParam();
|
||||
GetGameUIMan()->m_ptLButtonDown.x = GET_X_LPARAM(lParam) - p->X;
|
||||
GetGameUIMan()->m_ptLButtonDown.y = GET_Y_LPARAM(lParam) - p->Y;
|
||||
GetGameUIMan()->InvokeDragDrop(this, pObj, GetGameUIMan()->m_ptLButtonDown);
|
||||
}
|
||||
```
|
||||
|
||||
**Key Points:**
|
||||
- Skill data is stored via `SetDataPtr(pSkill, "ptr_CECSkill")` when skill icon is created
|
||||
- Mouse position is captured for drag operation
|
||||
- `InvokeDragDrop()` initiates the drag-drop system
|
||||
|
||||
---
|
||||
|
||||
### **Step 3: Drag-Drop System Routes to Handler**
|
||||
|
||||
**Location:** `DlgDragDrop.cpp:79-124` - `OnEventLButtonUp()`
|
||||
|
||||
When user releases mouse button, the drag-drop system processes the drop:
|
||||
|
||||
```cpp
|
||||
// DlgDragDrop.cpp:79-124
|
||||
void CDlgDragDrop::OnEventLButtonUp(WPARAM wParam, LPARAM lParam, AUIObject *pObj) {
|
||||
PAUIOBJECT pObjSrc = (PAUIOBJECT)pItem->GetDataPtr("ptr_AUIObject");
|
||||
if( !pObjSrc ) return;
|
||||
|
||||
// Get destination dialog and object via hit test
|
||||
PAUIDIALOG pDlgOver;
|
||||
PAUIOBJECT pObjOver;
|
||||
GetGameUIMan()->HitTest(x, y, &pDlgOver, &pObjOver, this);
|
||||
|
||||
PAUIDIALOG pDlgSrc = pObjSrc->GetParent();
|
||||
|
||||
// Route to appropriate handler
|
||||
OnGeneralScene(pDlgSrc, pObjSrc, pDlgOver, pObjOver, pIvtrSrc);
|
||||
}
|
||||
```
|
||||
|
||||
**Flow:**
|
||||
1. Get source object from drag item
|
||||
2. Hit test to find destination dialog and object
|
||||
3. Route to `OnGeneralScene()` for processing
|
||||
|
||||
---
|
||||
|
||||
### **Step 4: Skill Drag-Drop Handler**
|
||||
|
||||
**Location:** `DlgDragDrop.cpp:589-627` - `OnSkillDragDrop()`
|
||||
|
||||
The handler checks if drop is on skill edit dialog:
|
||||
|
||||
```cpp
|
||||
// DlgDragDrop.cpp:589-627
|
||||
void CDlgDragDrop::OnSkillDragDrop(PAUIDIALOG pDlgSrc, PAUIOBJECT pObjSrc,
|
||||
PAUIDIALOG pDlgOver, PAUIOBJECT pObjOver,
|
||||
CECIvtrItem* pIvtrSrc) {
|
||||
// Check if dropped on skill edit dialog
|
||||
if( pDlgOver && stricmp(pDlgOver->GetName(), "Win_SkillEdit") == 0
|
||||
&& pObjOver && strstr(pObjOver->GetName(), "Item_")
|
||||
&& !strstr(pObjSrc->GetName(), "Img_ConSkill")) // Don't allow combo icons
|
||||
{
|
||||
GetGameUIMan()->m_pDlgSkillEdit->DragDropItem(pDlgSrc, pObjSrc, pObjOver);
|
||||
}
|
||||
// ... other handlers (quick bar, auto policy, etc.)
|
||||
}
|
||||
```
|
||||
|
||||
**Key Points:**
|
||||
- Only processes drops on `Win_SkillEdit` dialog
|
||||
- Destination must be an `Item_*` slot (combo skill list slot)
|
||||
- Prevents dragging combo skill icons into combo list (prevents recursion)
|
||||
|
||||
---
|
||||
|
||||
### **Step 5: Add Skill to Combo List**
|
||||
|
||||
**Location:** `DlgSkillEdit.cpp:249-293` - `DragDropItem()`
|
||||
|
||||
This is the core function that adds the skill to the combo list:
|
||||
|
||||
```cpp
|
||||
// DlgSkillEdit.cpp:249-293
|
||||
void CDlgSkillEdit::DragDropItem(PAUIDIALOG pDlgSrc, PAUIOBJECT pObjSrc, PAUIOBJECT pObjOver) {
|
||||
if( pObjSrc == pObjOver )
|
||||
return; // Same object, do nothing
|
||||
|
||||
if( !pObjOver ) {
|
||||
// Dropped outside - remove skill from source
|
||||
if( !(pDlgSrc == this && strstr(pObjSrc->GetName(), "Special")) )
|
||||
GetGameUIMan()->m_pDlgSkillSubOther->SetImage((PAUIIMAGEPICTURE)pObjSrc, NULL);
|
||||
}
|
||||
else {
|
||||
// Extract target slot number (1-based)
|
||||
int iSlot = atoi(pObjOver->GetName() + strlen("Item_"));
|
||||
|
||||
// Check if source is special icon (Attack, Loop Start)
|
||||
if( strstr(pObjSrc->GetName(), "Special_") ) {
|
||||
int iType = atoi(pObjSrc->GetName() + strlen("Special_"));
|
||||
SetSpecialIcon((PAUIIMAGEPICTURE)pObjOver, iType);
|
||||
}
|
||||
else {
|
||||
// Regular skill drag-drop
|
||||
CECSkill *pSkill = (CECSkill *)pObjSrc->GetDataPtr("ptr_CECSkill");
|
||||
int iType = pObjSrc->GetData();
|
||||
|
||||
if( pDlgSrc != this ) {
|
||||
// Dragging from external dialog (skill list)
|
||||
if( iType != 0)
|
||||
SetSpecialIcon((PAUIIMAGEPICTURE)pObjOver, iType);
|
||||
else
|
||||
GetGameUIMan()->m_pDlgSkillSubOther->SetImage((PAUIIMAGEPICTURE)pObjOver, pSkill);
|
||||
}
|
||||
else {
|
||||
// Dragging within skill edit dialog (reordering)
|
||||
CECSkill *pSkill1 = (CECSkill *)pObjOver->GetDataPtr("ptr_CECSkill");
|
||||
int iType1 = pObjOver->GetData();
|
||||
|
||||
// Swap skills
|
||||
if( iType != 0)
|
||||
SetSpecialIcon((PAUIIMAGEPICTURE)pObjOver, iType);
|
||||
else
|
||||
GetGameUIMan()->m_pDlgSkillSubOther->SetImage((PAUIIMAGEPICTURE)pObjOver, pSkill);
|
||||
|
||||
if( iType1 != 0)
|
||||
SetSpecialIcon((PAUIIMAGEPICTURE)pObjSrc, iType1);
|
||||
else
|
||||
GetGameUIMan()->m_pDlgSkillSubOther->SetImage((PAUIIMAGEPICTURE)pObjSrc, pSkill1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Key Points:**
|
||||
- **External Drag (from skill list):** Adds skill to target slot, clears source if needed
|
||||
- **Internal Drag (within dialog):** Swaps skills between slots (reordering)
|
||||
- **Special Icons:** Can add Attack (`Special_1`) or Loop Start (`Special_2`) icons
|
||||
- Uses `SetImage()` to display skill icon in target slot
|
||||
- Skill data is stored via `SetDataPtr(pSkill, "ptr_CECSkill")`
|
||||
|
||||
---
|
||||
|
||||
### **Step 6: Save Combo Skill Configuration (Local)**
|
||||
|
||||
**Location:** `DlgSkillEdit.cpp:56-85` - `OnCommandConfirm()`
|
||||
|
||||
When user clicks "Confirm" button, the combo skill is saved locally:
|
||||
|
||||
```cpp
|
||||
// DlgSkillEdit.cpp:56-85
|
||||
void CDlgSkillEdit::OnCommandConfirm(const char *szCommand) {
|
||||
EC_VIDEO_SETTING setting = GetGame()->GetConfigs()->GetVideoSettings();
|
||||
|
||||
// Save icon index
|
||||
setting.comboSkill[GetData() - 1].nIcon = m_nIcon;
|
||||
|
||||
// Save skill sequence
|
||||
int i;
|
||||
int j = 0;
|
||||
for (i = 0; ; i++) {
|
||||
AString strName;
|
||||
strName.Format("Item_%d", i + 1);
|
||||
PAUIIMAGEPICTURE pImage = static_cast<PAUIIMAGEPICTURE>(GetDlgItem(strName));
|
||||
if (!pImage) break;
|
||||
|
||||
CECSkill *pSkill = (CECSkill *)pImage->GetDataPtr("ptr_CECSkill");
|
||||
int iType = pImage->GetData();
|
||||
|
||||
if( iType == 0 && pSkill ) {
|
||||
// Regular skill
|
||||
setting.comboSkill[GetData() - 1].idSkill[j] = pSkill->GetSkillID();
|
||||
j++;
|
||||
}
|
||||
else {
|
||||
// Special icon (Attack = -1, Loop Start = -2)
|
||||
setting.comboSkill[GetData() - 1].idSkill[j] = -iType;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
// Save to local config (does NOT send to server immediately)
|
||||
GetGame()->GetConfigs()->SetVideoSettings(setting);
|
||||
Show(false);
|
||||
|
||||
// Update combo skill display
|
||||
GetGameUIMan()->m_pDlgSkillSubOther->UpdateComboSkill();
|
||||
}
|
||||
```
|
||||
|
||||
**Key Points:**
|
||||
- Saves icon index (`nIcon`) for combo skill
|
||||
- Saves skill sequence to `idSkill[]` array:
|
||||
- **Positive values:** Skill IDs
|
||||
- **Negative values:** Special icons (-1 = Attack, -2 = Loop Start)
|
||||
- Updates combo skill icons in main skill dialog
|
||||
- **Note:** This only saves to local memory (`m_vs`), does NOT send to server yet
|
||||
|
||||
---
|
||||
|
||||
### **Step 7: Send Combo Skill to Server**
|
||||
|
||||
**Location:** `EC_GameRun.cpp:1942-2061` - `SaveConfigsToServer()`
|
||||
|
||||
Combo skill data is sent to server as part of the user configuration when:
|
||||
- Player logs out
|
||||
- Periodically during gameplay
|
||||
- When explicitly triggered (e.g., via UI command)
|
||||
|
||||
```cpp
|
||||
// EC_GameRun.cpp:1942-2061
|
||||
DWORD CECGameRun::SaveConfigsToServer() {
|
||||
// ... validation checks ...
|
||||
|
||||
// Calculate total size needed
|
||||
int iTotalSize = 0;
|
||||
iTotalSize += sizeof(DWORD); // Version
|
||||
|
||||
// Host player config (shortcuts, etc.)
|
||||
int iHostSize = 0;
|
||||
pHost->SaveConfigData(NULL, &iHostSize);
|
||||
iTotalSize += sizeof(int) + iHostSize;
|
||||
|
||||
// UI layout config
|
||||
DWORD dwUISize = 0;
|
||||
pGameUI->GetUserLayout(NULL, dwUISize);
|
||||
iTotalSize += sizeof(int) + (int)dwUISize;
|
||||
|
||||
// User settings config (INCLUDES COMBO SKILLS!)
|
||||
int iSettingSize = 0;
|
||||
g_pGame->GetConfigs()->SaveUserConfigData(NULL, &iSettingSize);
|
||||
iTotalSize += sizeof(int) + iSettingSize;
|
||||
|
||||
// Allocate buffer and pack data
|
||||
void* pDataBuf = a_malloctemp(iTotalSize);
|
||||
// ... pack all data ...
|
||||
|
||||
// Compress and send to server
|
||||
g_pGame->GetGameSession()->SaveConfigData(pCompBuf, dwCompLen+iVerLen);
|
||||
}
|
||||
```
|
||||
|
||||
**Key Function:** `EC_Configs::SaveUserConfigData()`
|
||||
|
||||
**Location:** `EC_Configs.cpp:569-615`
|
||||
|
||||
```cpp
|
||||
// EC_Configs.cpp:569-615
|
||||
bool CECConfigs::SaveUserConfigData(void* pDataBuf, int* piSize) {
|
||||
int iTotalSize = 0;
|
||||
BYTE* pData = (BYTE*)pDataBuf;
|
||||
|
||||
// Version
|
||||
iTotalSize += sizeof(DWORD);
|
||||
if (pDataBuf) {
|
||||
*((DWORD*)pData) = EC_CONFIG_VERSION;
|
||||
pData += sizeof(DWORD);
|
||||
}
|
||||
|
||||
// ⭐ SAVE VIDEO SETTINGS (INCLUDES COMBO SKILLS!)
|
||||
iTotalSize += sizeof(EC_VIDEO_SETTING);
|
||||
if (pDataBuf) {
|
||||
*((EC_VIDEO_SETTING*)pData) = m_vs; // Contains comboSkill[] array!
|
||||
pData += sizeof(EC_VIDEO_SETTING);
|
||||
}
|
||||
|
||||
// ... other settings (game, blacklist, computer aided) ...
|
||||
}
|
||||
```
|
||||
|
||||
**Key Points:**
|
||||
- **Entire `EC_VIDEO_SETTING` structure is sent**, which includes:
|
||||
- `comboSkill[EC_COMBOSKILL_NUM]` array
|
||||
- Each combo skill contains `nIcon` and `idSkill[]` array
|
||||
- **Data is compressed** before sending to reduce network traffic
|
||||
- **Sent asynchronously** - not immediately when combo is saved
|
||||
- **Server stores** this data and sends it back when player logs in
|
||||
|
||||
---
|
||||
|
||||
### **Step 8: Server Receives and Stores Combo Skill Data**
|
||||
|
||||
**Location:** Server-side (not in client codebase)
|
||||
|
||||
When server receives the config data:
|
||||
1. Server decompresses the data
|
||||
2. Server parses `EC_VIDEO_SETTING` structure
|
||||
3. Server extracts `comboSkill[]` array
|
||||
4. Server stores combo skill data in player's account/profile
|
||||
5. Server sends combo skill data back to client on next login
|
||||
|
||||
**Note:** The server does NOT validate or execute combo skills - they are purely client-side UI configurations. The server only stores them for persistence across sessions.
|
||||
|
||||
---
|
||||
|
||||
## Complete Flow Diagram
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ STEP 1: Open Skill Edit Dialog │
|
||||
│ Location: DlgSkillSubOther.cpp:49-57 │
|
||||
│ - User clicks "New" or "Edit" button │
|
||||
│ - SetData(0) for new, SetData(n) for existing │
|
||||
│ - Show Win_SkillEdit dialog │
|
||||
└──────────────────────┬──────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ STEP 2: Dialog Initialization │
|
||||
│ Location: DlgSkillEdit.cpp:143-231 │
|
||||
│ - Load existing combo skill if editing │
|
||||
│ - Display empty slots (Item_1, Item_2, ...) │
|
||||
│ - Show special icons (Attack, Loop Start) │
|
||||
└──────────────────────┬──────────────────────────────────────┘
|
||||
│
|
||||
│ (User drags skill from skill list)
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ STEP 3: Drag Initiation │
|
||||
│ Location: DlgSkillSubOther.cpp:235-253 │
|
||||
│ - OnEventLButtonDownFixed() or OnEventLButtonDownItem() │
|
||||
│ - Capture mouse position │
|
||||
│ - InvokeDragDrop(this, pObj, pt) │
|
||||
└──────────────────────┬──────────────────────────────────────┘
|
||||
│
|
||||
│ (User drags to combo list slot)
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ STEP 4: Drop Processing │
|
||||
│ Location: DlgDragDrop.cpp:79-124 │
|
||||
│ - OnEventLButtonUp() detects drop │
|
||||
│ - Hit test to find destination │
|
||||
│ - Route to OnSkillDragDrop() │
|
||||
└──────────────────────┬──────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ STEP 5: Skill Drag Handler │
|
||||
│ Location: DlgDragDrop.cpp:589-627 │
|
||||
│ - Check: pDlgOver == "Win_SkillEdit" │
|
||||
│ - Check: pObjOver name contains "Item_" │
|
||||
│ - Call DragDropItem() │
|
||||
└──────────────────────┬──────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ STEP 6: Add Skill to Combo List │
|
||||
│ Location: DlgSkillEdit.cpp:249-293 │
|
||||
│ - Extract target slot: atoi("Item_N") │
|
||||
│ - Get skill: pObjSrc->GetDataPtr("ptr_CECSkill") │
|
||||
│ - SetImage(pObjOver, pSkill) │
|
||||
│ - Store skill data in slot │
|
||||
└──────────────────────┬──────────────────────────────────────┘
|
||||
│
|
||||
│ (User can drag more skills)
|
||||
│ (User can reorder by dragging within dialog)
|
||||
│
|
||||
│ (User clicks "Confirm" button)
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ STEP 6: Save Configuration (Local) │
|
||||
│ Location: DlgSkillEdit.cpp:56-85 │
|
||||
│ - Loop through all Item_* slots │
|
||||
│ - Extract skill IDs or special icon types │
|
||||
│ - Save to setting.comboSkill[n].idSkill[] │
|
||||
│ - Save icon: setting.comboSkill[n].nIcon │
|
||||
│ - SetVideoSettings(setting) → saves to m_vs (local only) │
|
||||
│ - UpdateComboSkill() to refresh display │
|
||||
└──────────────────────┬──────────────────────────────────────┘
|
||||
│
|
||||
│ (Later: on logout, periodically, or explicit save)
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ STEP 7: Send to Server │
|
||||
│ Location: EC_GameRun.cpp:1942-2061 │
|
||||
│ - SaveConfigsToServer() called │
|
||||
│ - SaveUserConfigData() includes entire EC_VIDEO_SETTING │
|
||||
│ - Combo skills included in m_vs.comboSkill[] │
|
||||
│ - Data compressed and sent via SaveConfigData() │
|
||||
└──────────────────────┬──────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ STEP 8: Server Storage │
|
||||
│ Location: Server-side (not in client code) │
|
||||
│ - Server receives compressed config data │
|
||||
│ - Server decompresses and parses EC_VIDEO_SETTING │
|
||||
│ - Server stores comboSkill[] in player account │
|
||||
│ - Server sends back on next login │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Data Structures
|
||||
|
||||
### **EC_VIDEO_SETTING.comboSkill[]**
|
||||
```cpp
|
||||
struct COMBO_SKILL {
|
||||
short nIcon; // Icon index (1-based, 0 = empty)
|
||||
short idSkill[EC_COMBOSKILL_LEN]; // Skill sequence array
|
||||
// idSkill values:
|
||||
// > 0: Skill ID
|
||||
// -1: Attack (SID_ATTACK)
|
||||
// -2: Loop Start (SID_LOOPSTART)
|
||||
// 0: Empty slot
|
||||
};
|
||||
```
|
||||
|
||||
### **Skill Storage in UI Objects**
|
||||
- **Skill Pointer:** `pImage->SetDataPtr(pSkill, "ptr_CECSkill")`
|
||||
- **Special Icon Type:** `pImage->SetData(iType)` where `iType = 1` (Attack) or `2` (Loop Start)
|
||||
- **Regular Skill:** `pImage->SetData(0)`
|
||||
|
||||
---
|
||||
|
||||
## Key Constants
|
||||
|
||||
- **EC_COMBOSKILL_NUM:** Maximum number of combo skill groups (typically 8-12)
|
||||
- **EC_COMBOSKILL_LEN:** Maximum number of skills per combo (typically 8-16)
|
||||
- **SID_ATTACK:** Special skill ID for normal attack (typically -1)
|
||||
- **SID_LOOPSTART:** Special skill ID for loop start marker (typically -2)
|
||||
|
||||
---
|
||||
|
||||
## Important Notes
|
||||
|
||||
1. **Index Conversion:**
|
||||
- Combo group index is **1-based** in UI (`GetData()` returns 1, 2, 3, ...)
|
||||
- Array index is **0-based** in config (`comboSkill[GetData() - 1]`)
|
||||
|
||||
2. **Skill Sources:**
|
||||
- Skills can be dragged from:
|
||||
- `Win_SkillSubOther` (Fixed skills, Item skills)
|
||||
- `Win_SkillSubPool` (Skill pool)
|
||||
- `Win_SkillSubListSkillItem` (Skill list items)
|
||||
|
||||
3. **Special Icons:**
|
||||
- Attack icon (`Special_1`) = Normal attack in combo
|
||||
- Loop Start icon (`Special_2`) = Marks where combo should loop back
|
||||
|
||||
4. **Reordering:**
|
||||
- Users can drag skills within the skill edit dialog to reorder
|
||||
- `DragDropItem()` handles swapping when `pDlgSrc == this`
|
||||
|
||||
5. **Validation:**
|
||||
- Combo skill icons cannot be dragged into combo list (prevents recursion)
|
||||
- Empty slots are allowed (stored as 0 in `idSkill[]`)
|
||||
|
||||
---
|
||||
|
||||
## Related Files
|
||||
|
||||
- **DlgSkillEdit.cpp/h:** Skill edit dialog implementation
|
||||
- **DlgSkillSubOther.cpp/h:** Skill sub-other panel (source of skills)
|
||||
- **DlgDragDrop.cpp/h:** Drag-drop system handler
|
||||
- **EC_Configs.cpp/h:** Configuration management (stores combo skills locally)
|
||||
- **EC_GameRun.cpp/h:** Game run logic (saves configs to server)
|
||||
- **EC_GameSession.cpp/h:** Network session (sends config data to server)
|
||||
- **EC_ComboSkill.cpp/h:** Combo skill execution logic
|
||||
|
||||
---
|
||||
|
||||
## Network Protocol Details
|
||||
|
||||
### **Protocol Command**
|
||||
- **Command:** `SaveConfigData` (via `EC_GameSession::SaveConfigData()`)
|
||||
- **Data Format:** Compressed binary blob containing:
|
||||
1. Version (DWORD)
|
||||
2. Host player config (shortcuts, etc.)
|
||||
3. UI layout config
|
||||
4. **User settings config (includes combo skills)**
|
||||
|
||||
### **Data Structure Sent**
|
||||
```cpp
|
||||
struct USER_CONFIG_DATA {
|
||||
DWORD version; // USERCFG_VERSION
|
||||
int hostConfigSize;
|
||||
BYTE hostConfig[hostConfigSize]; // Host player shortcuts, etc.
|
||||
int uiLayoutSize;
|
||||
BYTE uiLayout[uiLayoutSize]; // UI window positions, etc.
|
||||
int settingsSize;
|
||||
BYTE settings[settingsSize]; // EC_VIDEO_SETTING + other settings
|
||||
};
|
||||
|
||||
// Inside settings:
|
||||
struct EC_VIDEO_SETTING {
|
||||
// ... other video settings ...
|
||||
EC_COMBOSKILL comboSkill[EC_COMBOSKILL_NUM]; // ⭐ COMBO SKILLS HERE!
|
||||
};
|
||||
|
||||
struct EC_COMBOSKILL {
|
||||
short nIcon; // Icon index (0 = empty)
|
||||
short idSkill[EC_COMBOSKILL_LEN]; // Skill sequence
|
||||
};
|
||||
```
|
||||
|
||||
### **When Data is Sent**
|
||||
1. **On Logout:** `DlgExit.cpp` triggers `SaveConfigsToServer()`
|
||||
2. **Periodically:** Game may auto-save configs during gameplay
|
||||
3. **Explicit Save:** UI commands can trigger save (e.g., `EC_GameUICommand.cpp:143`)
|
||||
4. **Pending Actions:** Various pending actions append save requests
|
||||
|
||||
### **Important Notes**
|
||||
- **Combo skills are NOT sent immediately** when saved - they're queued for next config save
|
||||
- **Server does NOT validate combo skills** - they're client-side UI configurations
|
||||
- **Combo skills are NOT executed on server** - execution is purely client-side
|
||||
- **Server only stores for persistence** - so player's combo skills persist across sessions
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4abca7ea223861b47b89d130f6902111
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,820 @@
|
||||
# Flow: CreateSkillGroupShortcut - C++ Implementation
|
||||
|
||||
## Overview
|
||||
This document describes the complete flow for creating a skill combo group shortcut in the C++ codebase. A skill group shortcut (`CECSCSkillGrp`) represents a combo skill sequence that can be placed in the quick bar and executed with a single click.
|
||||
|
||||
---
|
||||
|
||||
## Entry Points
|
||||
|
||||
### 1. **From UI Drag & Drop** (DlgDragDrop.cpp:603)
|
||||
When a user drags a combo skill icon from the combo skill panel to a shortcut slot:
|
||||
|
||||
```cpp
|
||||
// DlgDragDrop.cpp:595-604
|
||||
if (strstr(pObjSrc->GetName(), "Img_ConSkill")) // Combo skill icon
|
||||
{
|
||||
int nCombo = pObjSrc->GetData(); // Get combo group index (1-based)
|
||||
int iSlot = atoi(pObjOver->GetName() + strlen("Item_")); // Get target slot (1-based)
|
||||
|
||||
CECShortcutSet *pSCS = CECGameUIMan::GetSCSByDlg(pDlgOver->GetName());
|
||||
if (!pSCS->GetShortcut(iSlot-1) || !g_pGame->GetConfigs()->GetGameSettings().bLockQuickBar)
|
||||
pSCS->CreateSkillGroupShortcut(iSlot - 1, nCombo - 1); // Convert to 0-based
|
||||
}
|
||||
```
|
||||
|
||||
**Flow:**
|
||||
1. User drags combo skill icon (`Img_ConSkill`) to shortcut slot
|
||||
2. Extract combo group index from source object data (1-based)
|
||||
3. Extract target slot number from destination object name (1-based)
|
||||
4. Get the appropriate `CECShortcutSet` based on dialog
|
||||
5. Check if slot is empty or quick bar is unlocked
|
||||
6. Call `CreateSkillGroupShortcut` with 0-based indices
|
||||
|
||||
---
|
||||
|
||||
## Detailed Analysis: UI Drag & Drop Flow
|
||||
|
||||
### **Step 1: Combo Skill Icon Creation & Data Initialization**
|
||||
|
||||
**Location:** `DlgSkillSubOther.cpp:71-99` - `UpdateComboSkill()`
|
||||
|
||||
This function is called when the skill dialog is shown (`OnShowDialog()` at line 193) and creates/updates all combo skill icons:
|
||||
|
||||
```cpp
|
||||
// DlgSkillSubOther.cpp:71-99
|
||||
void CDlgSkillSubOther::UpdateComboSkill() {
|
||||
EC_VIDEO_SETTING setting = GetGame()->GetConfigs()->GetVideoSettings();
|
||||
|
||||
// Loop through all possible combo skill groups (typically 8-12)
|
||||
for(int i = 0; i < EC_COMBOSKILL_NUM; i++)
|
||||
{
|
||||
// Create icon name: "Img_ConSkill01", "Img_ConSkill02", etc.
|
||||
AString strName;
|
||||
strName.Format("Img_ConSkill%02d", i + 1);
|
||||
|
||||
// Get the image picture object from dialog
|
||||
PAUIIMAGEPICTURE pImage = static_cast<PAUIIMAGEPICTURE>(GetDlgItem(strName));
|
||||
if( pImage )
|
||||
{
|
||||
// Check if this combo skill group is configured (has an icon)
|
||||
if( setting.comboSkill[i].nIcon != 0 )
|
||||
{
|
||||
// Set the icon image from sprite sheet
|
||||
pImage->SetCover(
|
||||
GetGameUIMan()->m_pA2DSpriteIcons[CECGameUIMan::ICONS_SKILLGRP],
|
||||
setting.comboSkill[i].nIcon + 1);
|
||||
|
||||
// ⭐ KEY: Store the combo group index (1-based) in the icon's data
|
||||
// i is 0-based (0, 1, 2, ...), so i+1 is 1-based (1, 2, 3, ...)
|
||||
pImage->SetData(i + 1);
|
||||
|
||||
// Set a flag pointer (just indicates this is a valid combo skill)
|
||||
pImage->SetDataPtr((void*)1);
|
||||
|
||||
// Set tooltip/hint text
|
||||
ACString strText;
|
||||
strText.Format(GetStringFromTable(804), i);
|
||||
pImage->SetHint(strText);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Empty/invalid combo skill - clear the icon
|
||||
pImage->SetCover(NULL, -1);
|
||||
pImage->SetData(0); // No data = invalid
|
||||
pImage->SetDataPtr(NULL);
|
||||
pImage->SetHint(_AL(""));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Key Points:**
|
||||
- **Icon Naming:** Icons are named `"Img_ConSkill%02d"` where `%02d` is the 1-based index (01, 02, 03, ...)
|
||||
- **Data Storage:** The combo group index is stored via `SetData(i + 1)`:
|
||||
- `i` is 0-based array index (0, 1, 2, ...)
|
||||
- `i + 1` is 1-based group number (1, 2, 3, ...)
|
||||
- This 1-based value is what gets retrieved during drag & drop
|
||||
- **Validation:** If `nIcon == 0`, the combo skill doesn't exist, so `SetData(0)` marks it as invalid
|
||||
- **Icon Source:** Icon image comes from `ICONS_SKILLGRP` sprite sheet at index `nIcon + 1`
|
||||
|
||||
---
|
||||
|
||||
### **Step 2: User Initiates Drag Operation**
|
||||
|
||||
**Location:** `DlgSkillSubOther.cpp:219-232` - `OnEventLButtonDownCombo()`
|
||||
|
||||
When user clicks and holds on a combo skill icon:
|
||||
|
||||
```cpp
|
||||
// DlgSkillSubOther.cpp:219-232
|
||||
void CDlgSkillSubOther::OnEventLButtonDownCombo(WPARAM wParam, LPARAM lParam, AUIObject * pObj) {
|
||||
// ⭐ Validation: Check if icon has valid data (combo skill exists)
|
||||
if( pObj->GetData() == 0 )
|
||||
return; // No combo skill configured, can't drag
|
||||
|
||||
// Get viewport coordinates
|
||||
A3DVIEWPORTPARAM *p = m_pA3DEngine->GetActiveViewport()->GetParam();
|
||||
POINT pt =
|
||||
{
|
||||
GET_X_LPARAM(lParam) - p->X,
|
||||
GET_Y_LPARAM(lParam) - p->Y,
|
||||
};
|
||||
|
||||
// Store drag start position
|
||||
GetGameUIMan()->m_ptLButtonDown = pt;
|
||||
|
||||
// ⭐ Start drag & drop operation
|
||||
// This passes the source object (pObj) which contains the data
|
||||
GetGameUIMan()->InvokeDragDrop(this, pObj, pt);
|
||||
}
|
||||
```
|
||||
|
||||
**Key Points:**
|
||||
- **Event Mapping:** The event is mapped via `AUI_ON_EVENT("Img_ConSkill*", WM_LBUTTONDOWN, OnEventLButtonDownCombo)` (line 19)
|
||||
- **Validation:** Checks `GetData() == 0` to ensure combo skill exists before allowing drag
|
||||
- **Data Preservation:** The `pObj` (icon object) is passed to `InvokeDragDrop()`, preserving the data stored in Step 1
|
||||
|
||||
---
|
||||
|
||||
### **Step 3: Drag & Drop Processing**
|
||||
|
||||
**Location:** `DlgDragDrop.cpp:79-127` - `OnEventLButtonUp()`
|
||||
|
||||
When user releases mouse button, the drag & drop system processes the drop:
|
||||
|
||||
```cpp
|
||||
// DlgDragDrop.cpp:79-127 (simplified)
|
||||
void CDlgDragDrop::OnEventLButtonUp(WPARAM wParam, LPARAM lParam, AUIObject *pObj)
|
||||
{
|
||||
// Get the source object that was being dragged
|
||||
PAUIOBJECT pObjSrc = (PAUIOBJECT)pItem->GetDataPtr("ptr_AUIObject");
|
||||
if( !pObjSrc )
|
||||
return;
|
||||
|
||||
// Get destination (where mouse was released)
|
||||
PAUIDIALOG pDlgOver;
|
||||
PAUIOBJECT pObjOver;
|
||||
// ... hit test to find what's under the mouse ...
|
||||
GetGameUIMan()->HitTest(x, y, &pDlgOver, &pObjOver, this);
|
||||
|
||||
// Route to appropriate handler based on source dialog
|
||||
// ... routing logic ...
|
||||
|
||||
// For skill-related drags, calls:
|
||||
OnSkillDragDrop(pDlgSrc, pObjSrc, pDlgOver, pObjOver, pIvtrSrc);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### **Step 4: Skill Drag & Drop Handler**
|
||||
|
||||
**Location:** `DlgDragDrop.cpp:589-627` - `OnSkillDragDrop()`
|
||||
|
||||
This is where the combo skill icon data is extracted and used:
|
||||
|
||||
```cpp
|
||||
// DlgDragDrop.cpp:589-627
|
||||
void CDlgDragDrop::OnSkillDragDrop(PAUIDIALOG pDlgSrc, PAUIOBJECT pObjSrc,
|
||||
PAUIDIALOG pDlgOver, PAUIOBJECT pObjOver, CECIvtrItem* pIvtrSrc)
|
||||
{
|
||||
// Check if dropping on quick bar dialog
|
||||
if( pDlgOver && strstr(pDlgOver->GetName(), "Win_Quickbar")
|
||||
&& pObjOver && strstr(pObjOver->GetName(), "Item_") )
|
||||
{
|
||||
// ⭐ Check if source is a combo skill icon
|
||||
if( strstr(pObjSrc->GetName(), "Img_ConSkill") )
|
||||
{
|
||||
// ⭐ Extract combo group index from icon's stored data (1-based)
|
||||
int nCombo = pObjSrc->GetData(); // Returns the value set in UpdateComboSkill()
|
||||
|
||||
// Extract target slot number from destination object name
|
||||
// Destination name format: "Item_1", "Item_2", etc. (1-based)
|
||||
int iSlot = atoi(pObjOver->GetName() + strlen("Item_")); // "Item_1" -> 1
|
||||
|
||||
// Get the shortcut set for this dialog
|
||||
CECShortcutSet *pSCS = CECGameUIMan::GetSCSByDlg(pDlgOver->GetName());
|
||||
|
||||
// Check if slot is empty or quick bar is unlocked
|
||||
if( !pSCS->GetShortcut(iSlot-1) ||
|
||||
!g_pGame->GetConfigs()->GetGameSettings().bLockQuickBar )
|
||||
{
|
||||
// ⭐ Create skill group shortcut
|
||||
// Convert both indices to 0-based:
|
||||
// - iSlot: 1-based -> 0-based (slot 1 -> index 0)
|
||||
// - nCombo: 1-based -> 0-based (group 1 -> index 0)
|
||||
pSCS->CreateSkillGroupShortcut(iSlot - 1, nCombo - 1);
|
||||
}
|
||||
}
|
||||
// Handle regular skill drag (not combo)
|
||||
else
|
||||
{
|
||||
CECSkill *pSkill = (CECSkill *)pObjSrc->GetDataPtr("ptr_CECSkill");
|
||||
// ... create regular skill shortcut ...
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Key Points:**
|
||||
- **Icon Identification:** `strstr(pObjSrc->GetName(), "Img_ConSkill")` identifies combo skill icons
|
||||
- **Data Retrieval:** `pObjSrc->GetData()` retrieves the 1-based group index stored in Step 1
|
||||
- **Slot Extraction:** Destination slot is extracted from object name `"Item_N"` where N is 1-based
|
||||
- **Index Conversion:** Both indices are converted from 1-based to 0-based before calling `CreateSkillGroupShortcut()`
|
||||
|
||||
---
|
||||
|
||||
### **Complete Data Flow Diagram**
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ STEP 1: Icon Creation (UpdateComboSkill) │
|
||||
│ Location: DlgSkillSubOther.cpp:71-99 │
|
||||
└──────────────────────┬──────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────────────────────────────┐
|
||||
│ For each combo skill group (i=0..N): │
|
||||
│ │
|
||||
│ 1. Create icon name: │
|
||||
│ "Img_ConSkill%02d" (i+1) │
|
||||
│ │
|
||||
│ 2. If combo exists (nIcon != 0): │
|
||||
│ - Set icon image │
|
||||
│ - ⭐ SetData(i + 1) │
|
||||
│ (stores 1-based group index) │
|
||||
│ - SetDataPtr((void*)1) │
|
||||
│ - Set hint text │
|
||||
└──────────────────┬───────────────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────────────────────────────┐
|
||||
│ Icon Object Created │
|
||||
│ - Name: "Img_ConSkill01", etc. │
|
||||
│ - Data: 1, 2, 3, ... (1-based) │
|
||||
│ - DataPtr: (void*)1 │
|
||||
│ - Icon: Sprite sheet image │
|
||||
└──────────────────┬───────────────────┘
|
||||
│
|
||||
│ (User clicks and drags)
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ STEP 2: Drag Initiation (OnEventLButtonDownCombo) │
|
||||
│ Location: DlgSkillSubOther.cpp:219-232 │
|
||||
└──────────────────────┬──────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────────────────────────────┐
|
||||
│ 1. Validate: GetData() != 0 │
|
||||
│ 2. Get mouse position │
|
||||
│ 3. InvokeDragDrop(this, pObj, pt) │
|
||||
│ (pObj contains the data!) │
|
||||
└──────────────────┬───────────────────┘
|
||||
│
|
||||
│ (User drags to quick bar)
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ STEP 3: Drop Processing (OnEventLButtonUp) │
|
||||
│ Location: DlgDragDrop.cpp:79-127 │
|
||||
└──────────────────────┬──────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────────────────────────────┐
|
||||
│ 1. Get source object (pObjSrc) │
|
||||
│ 2. Hit test to find destination │
|
||||
│ 3. Route to OnSkillDragDrop() │
|
||||
└──────────────────┬───────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ STEP 4: Skill Drag Handler (OnSkillDragDrop) │
|
||||
│ Location: DlgDragDrop.cpp:589-627 │
|
||||
└──────────────────────┬──────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────────────────────────────┐
|
||||
│ 1. Check: strstr(name, "Img_ConSkill")│
|
||||
│ 2. ⭐ Extract: nCombo = GetData() │
|
||||
│ (retrieves 1-based group index) │
|
||||
│ 3. Extract: iSlot from "Item_N" │
|
||||
│ 4. Get shortcut set │
|
||||
│ 5. Validate slot/quick bar │
|
||||
│ 6. CreateSkillGroupShortcut( │
|
||||
│ iSlot-1, nCombo-1) │
|
||||
│ (convert to 0-based) │
|
||||
└──────────────────┬───────────────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────────────────────────────┐
|
||||
│ CreateSkillGroupShortcut() │
|
||||
│ Creates CECSCSkillGrp with │
|
||||
│ group index (0-based) │
|
||||
└──────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### **Data Storage Summary**
|
||||
|
||||
| Component | Storage Method | Value Type | Example |
|
||||
|-----------|---------------|------------|---------|
|
||||
| **Combo Group Index** | `AUIObject::SetData(int)` | 1-based integer | 1, 2, 3, ... |
|
||||
| **Icon Name** | Object name | String pattern | "Img_ConSkill01", "Img_ConSkill02" |
|
||||
| **Icon Image** | `SetCover()` | Sprite sheet index | `nIcon + 1` |
|
||||
| **Validation Flag** | `SetDataPtr((void*)1)` | Pointer flag | `(void*)1` = valid, `NULL` = invalid |
|
||||
|
||||
**Important Notes:**
|
||||
1. **The icon DOES contain the data needed** - it's stored via `SetData(i + 1)` during icon creation
|
||||
2. **The data is 1-based** - stored as 1, 2, 3, ... but converted to 0-based (0, 1, 2, ...) when creating the shortcut
|
||||
3. **Data is validated** - `GetData() == 0` means no combo skill, so drag is prevented
|
||||
4. **Icon name pattern** - `"Img_ConSkill*"` is used to identify combo skill icons during drag & drop
|
||||
|
||||
---
|
||||
|
||||
### 2. **From Config Data Loading** (EC_ShortcutSet.cpp:600-616)
|
||||
When loading shortcut configuration from server/save file:
|
||||
|
||||
```cpp
|
||||
// EC_ShortcutSet.cpp:600-616
|
||||
case CECShortcut::SCT_SKILLGRP:
|
||||
{
|
||||
if (dwVer >= 3) // Version check - skill groups added in version 3
|
||||
{
|
||||
int iGroupIdx = *(int*)pData; // Read group index from config data
|
||||
pData += sizeof(int);
|
||||
|
||||
if (iGroupIdx >= 0)
|
||||
CreateSkillGroupShortcut(iSlot, iGroupIdx);
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(0);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
```
|
||||
|
||||
**Flow:**
|
||||
1. Read shortcut type from config data
|
||||
2. If type is `SCT_SKILLGRP` and version >= 3:
|
||||
- Read group index from binary data
|
||||
- Validate group index (>= 0)
|
||||
- Call `CreateSkillGroupShortcut`
|
||||
|
||||
---
|
||||
|
||||
### 3. **From AssignSkillGrpShortcut** (EC_HostPlayer.cpp:7934-7941)
|
||||
When assigning skill group shortcuts from configuration array:
|
||||
|
||||
```cpp
|
||||
// EC_HostPlayer.cpp:7934-7941
|
||||
void CECHostPlayer::AssignSkillGrpShortcut(
|
||||
const std::vector<SkillGrpShortCutConfig> & skillGrpSCConfigArray,
|
||||
CECShortcutSet** aSCSets)
|
||||
{
|
||||
std::vector<SkillGrpShortCutConfig>::const_iterator it;
|
||||
for (it = skillGrpSCConfigArray.begin(); it != skillGrpSCConfigArray.end(); it++)
|
||||
{
|
||||
if(it->groupIndex != -1) // -1 means invalid/empty
|
||||
aSCSets[it->setNum]->CreateSkillGroupShortcut(it->slotNum, it->groupIndex);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Flow:**
|
||||
1. Iterate through skill group shortcut configuration array
|
||||
2. For each valid config (groupIndex != -1):
|
||||
- Get the appropriate shortcut set by `setNum`
|
||||
- Call `CreateSkillGroupShortcut` with slot and group index
|
||||
|
||||
**Note:** Before calling this, `ConvertSkillGrpShortcut` is called to validate combo skills exist:
|
||||
```cpp
|
||||
// EC_HostPlayer.cpp:7915-7923
|
||||
void CECHostPlayer::ConvertSkillGrpShortcut(std::vector<SkillGrpShortCutConfig> & skillGrpSCConfigArray)
|
||||
{
|
||||
std::vector<SkillGrpShortCutConfig>::iterator it;
|
||||
for (it = skillGrpSCConfigArray.begin(); it != skillGrpSCConfigArray.end(); it++)
|
||||
{
|
||||
EC_VIDEO_SETTING vs = g_pGame->GetConfigs()->GetVideoSettings();
|
||||
if (vs.comboSkill[it->groupIndex].nIcon == 0) // Combo skill doesn't exist
|
||||
it->groupIndex = -1; // Mark as invalid
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Core Implementation
|
||||
|
||||
### **CreateSkillGroupShortcut** (EC_ShortcutSet.cpp:135-150)
|
||||
|
||||
```cpp
|
||||
// EC_ShortcutSet.cpp:135-150
|
||||
bool CECShortcutSet::CreateSkillGroupShortcut(int iSlot, int iGroupIdx)
|
||||
{
|
||||
// 1. Create new CECSCSkillGrp object
|
||||
CECSCSkillGrp* pSkillGrpSC = new CECSCSkillGrp;
|
||||
if (!pSkillGrpSC)
|
||||
return false;
|
||||
|
||||
// 2. Initialize with group index
|
||||
if (!pSkillGrpSC->Init(iGroupIdx))
|
||||
{
|
||||
delete pSkillGrpSC;
|
||||
a_LogOutput(1, "CECShortcutSet::CreateSkillGroupShortcut, Failed to initialize skill group shortcut");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 3. Set shortcut in slot (replaces any existing shortcut at this slot)
|
||||
SetShortcut(iSlot, pSkillGrpSC);
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
**Flow:**
|
||||
1. **Allocate** new `CECSCSkillGrp` object
|
||||
2. **Initialize** with group index
|
||||
3. **Set** shortcut in the specified slot (automatically releases old shortcut if exists)
|
||||
|
||||
---
|
||||
|
||||
## CECSCSkillGrp Class
|
||||
|
||||
### **Class Definition** (EC_Shortcut.h:282-309)
|
||||
|
||||
```cpp
|
||||
class CECSCSkillGrp : public CECShortcut
|
||||
{
|
||||
public:
|
||||
CECSCSkillGrp();
|
||||
CECSCSkillGrp(const CECSCSkillGrp& src);
|
||||
virtual ~CECSCSkillGrp() {}
|
||||
|
||||
// Initialize object
|
||||
bool Init(int iGroupIdx);
|
||||
|
||||
// Virtual functions from CECShortcut
|
||||
virtual CECShortcut* Clone();
|
||||
virtual bool Execute(); // Executes the combo skill
|
||||
virtual const char* GetIconFile();
|
||||
virtual const wchar_t* GetDesc();
|
||||
virtual int GetCoolTime(int* piMax=NULL);
|
||||
|
||||
private:
|
||||
int m_iGroupIdx; // Combo skill group index (0-based)
|
||||
CECString m_strDesc; // Description text
|
||||
};
|
||||
```
|
||||
|
||||
### **Initialization** (EC_Shortcut.cpp:696-703)
|
||||
|
||||
```cpp
|
||||
// EC_Shortcut.cpp:696-703
|
||||
bool CECSCSkillGrp::Init(int iGroupIdx)
|
||||
{
|
||||
m_iGroupIdx = iGroupIdx; // Store group index
|
||||
|
||||
// Format description: "Skill Group {index}"
|
||||
CECStringTab* pStrTab = g_pGame->GetItemDesc();
|
||||
m_strDesc.Format(pStrTab->GetWideString(CMDDESC_SKILLGROUP), m_iGroupIdx);
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
**Flow:**
|
||||
1. Store group index
|
||||
2. Format description string from string table
|
||||
3. Return success
|
||||
|
||||
### **Execution** (EC_Shortcut.cpp:712-717)
|
||||
|
||||
```cpp
|
||||
// EC_Shortcut.cpp:712-717
|
||||
bool CECSCSkillGrp::Execute()
|
||||
{
|
||||
CECHostPlayer* pHost = g_pGame->GetGameRun()->GetHostPlayer();
|
||||
pHost->ApplyComboSkill(m_iGroupIdx); // Apply combo skill with stored group index
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
**Flow:**
|
||||
1. Get host player instance
|
||||
2. Call `ApplyComboSkill` with the stored group index
|
||||
3. This triggers the combo skill sequence execution
|
||||
|
||||
---
|
||||
|
||||
## ApplyComboSkill Flow
|
||||
|
||||
### **ApplyComboSkill** (EC_HostPlayer.cpp:7710-7737)
|
||||
|
||||
```cpp
|
||||
// EC_HostPlayer.cpp:7710-7737
|
||||
bool CECHostPlayer::ApplyComboSkill(int iGroup, bool bIgnoreAtkLoop, int iForceAtk)
|
||||
{
|
||||
a_LogOutput(1, "HoangDEv: ApplyComboSkill - Applying combo skill, group=%d, target=%d, ignoreAtkLoop=%d, forceAtk=%d",
|
||||
iGroup, m_idSelTarget, bIgnoreAtkLoop, iForceAtk);
|
||||
|
||||
// 1. Clear current combo skill if exists
|
||||
ClearComboSkill();
|
||||
|
||||
// 2. Create new combo skill object
|
||||
if (!(m_pComboSkill = new CECComboSkill))
|
||||
{
|
||||
ASSERT(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 3. Initialize combo skill
|
||||
bool bForceAttack = (iForceAtk != 0);
|
||||
if (!(m_pComboSkill->Init(this, iGroup, m_idSelTarget, bForceAttack, bIgnoreAtkLoop)))
|
||||
{
|
||||
delete m_pComboSkill;
|
||||
m_pComboSkill = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
// 4. Start combo skill execution
|
||||
m_pComboSkill->Continue(m_bMelee);
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
**Flow:**
|
||||
1. **Clear** any existing combo skill
|
||||
2. **Create** new `CECComboSkill` object
|
||||
3. **Initialize** with:
|
||||
- Host player (this)
|
||||
- Group index
|
||||
- Target ID
|
||||
- Force attack flag
|
||||
- Ignore attack loop flag
|
||||
4. **Start** combo skill execution with `Continue()`
|
||||
|
||||
---
|
||||
|
||||
## Combo Skill Data Structure
|
||||
|
||||
### **EC_COMBOSKILL Structure**
|
||||
|
||||
Combo skills are stored in `EC_VIDEO_SETTING`:
|
||||
|
||||
```cpp
|
||||
// From configs/video settings
|
||||
struct EC_COMBOSKILL
|
||||
{
|
||||
int nIcon; // Icon ID (0 = empty/invalid)
|
||||
int idSkill[EC_COMBOSKILL_LEN]; // Array of skill IDs in combo sequence
|
||||
// ... other fields
|
||||
};
|
||||
|
||||
EC_VIDEO_SETTING vs;
|
||||
vs.comboSkill[EC_COMBOSKILL_NUM]; // Array of combo skill groups
|
||||
```
|
||||
|
||||
**Constants:**
|
||||
- `EC_COMBOSKILL_NUM`: Number of combo skill groups (typically 8-12)
|
||||
- `EC_COMBOSKILL_LEN`: Maximum number of skills in a combo sequence
|
||||
|
||||
### **Combo Skill Initialization** (EC_ComboSkill.cpp:74-92)
|
||||
|
||||
```cpp
|
||||
// EC_ComboSkill.cpp:74-92
|
||||
bool CECComboSkill::Init(CECHostPlayer* pHost, int iGroup, int idTarget,
|
||||
bool bForceAttack, bool bIgnoreAtkLoop)
|
||||
{
|
||||
// 1. Validate group index
|
||||
if (iGroup < 0 || iGroup >= EC_COMBOSKILL_NUM)
|
||||
{
|
||||
ASSERT(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 2. Store parameters
|
||||
m_pHost = pHost;
|
||||
m_iGroup = iGroup;
|
||||
m_iCursor = 0; // Start at first skill in combo
|
||||
m_bStop = false;
|
||||
m_idTarget = idTarget;
|
||||
m_bForceAtk = bForceAttack;
|
||||
m_bIgnoreAtkLoop = bIgnoreAtkLoop;
|
||||
|
||||
// 3. Load combo skill data from config
|
||||
CECConfigs* pCfg = g_pGame->GetConfigs();
|
||||
m_cs = pCfg->GetVideoSettings().comboSkill[iGroup];
|
||||
|
||||
// 4. Find loop start position (if any)
|
||||
// ... (finds SID_LOOPSTART marker)
|
||||
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Complete Flow Diagram
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ USER ACTION / CONFIG LOAD │
|
||||
└──────────────────────┬────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────────────────────┐
|
||||
│ Entry Point Selection │
|
||||
└──────────┬───────────────────┘
|
||||
│
|
||||
┌──────────┴──────────┐
|
||||
│ │
|
||||
▼ ▼
|
||||
┌──────────────┐ ┌──────────────────────┐
|
||||
│ UI Drag&Drop │ │ LoadConfigData │
|
||||
│ (DlgDragDrop)│ │ (EC_ShortcutSet) │
|
||||
└──────┬───────┘ └──────────┬───────────┘
|
||||
│ │
|
||||
└──────────┬───────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────┐
|
||||
│ CreateSkillGroupShortcut │
|
||||
│ (EC_ShortcutSet) │
|
||||
└──────────┬──────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────┐
|
||||
│ new CECSCSkillGrp │
|
||||
└──────────┬──────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────┐
|
||||
│ CECSCSkillGrp::Init(iGroup) │
|
||||
│ - Store group index │
|
||||
│ - Format description │
|
||||
└──────────┬──────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────┐
|
||||
│ SetShortcut(iSlot, pSC) │
|
||||
│ - Replace old shortcut │
|
||||
└──────────┬──────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────┐
|
||||
│ SHORTCUT CREATED │
|
||||
│ Ready for execution │
|
||||
└─────────────────────────────┘
|
||||
│
|
||||
│ (When user clicks shortcut)
|
||||
▼
|
||||
┌─────────────────────────────┐
|
||||
│ CECSCSkillGrp::Execute() │
|
||||
└──────────┬──────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────┐
|
||||
│ ApplyComboSkill(iGroup) │
|
||||
│ (EC_HostPlayer) │
|
||||
└──────────┬─────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────┐
|
||||
│ new CECComboSkill │
|
||||
└──────────┬──────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────┐
|
||||
│ CECComboSkill::Init() │
|
||||
│ - Load combo data from config│
|
||||
│ - Set cursor to start │
|
||||
└──────────┬──────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────┐
|
||||
│ CECComboSkill::Continue() │
|
||||
│ - Execute first skill │
|
||||
│ - Chain to next skills │
|
||||
└─────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Key Data Structures
|
||||
|
||||
### **SkillGrpShortCutConfig**
|
||||
|
||||
```cpp
|
||||
struct SkillGrpShortCutConfig
|
||||
{
|
||||
int setNum; // Shortcut set number (which quick bar)
|
||||
int slotNum; // Slot index within the set (0-based)
|
||||
int groupIndex; // Combo skill group index (0-based, -1 = invalid)
|
||||
};
|
||||
```
|
||||
|
||||
### **CECSCSkillGrp Members**
|
||||
|
||||
```cpp
|
||||
class CECSCSkillGrp : public CECShortcut
|
||||
{
|
||||
int m_iGroupIdx; // Combo skill group index (0-based)
|
||||
CECString m_strDesc; // Description: "Skill Group {index}"
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Validation & Error Handling
|
||||
|
||||
### **Group Index Validation**
|
||||
|
||||
1. **In CreateSkillGroupShortcut:**
|
||||
- No explicit validation (assumes caller validates)
|
||||
- `Init()` may fail if group index is invalid
|
||||
|
||||
2. **In ConvertSkillGrpShortcut:**
|
||||
```cpp
|
||||
if (vs.comboSkill[it->groupIndex].nIcon == 0)
|
||||
it->groupIndex = -1; // Mark as invalid
|
||||
```
|
||||
|
||||
3. **In CECComboSkill::Init:**
|
||||
```cpp
|
||||
if (iGroup < 0 || iGroup >= EC_COMBOSKILL_NUM)
|
||||
{
|
||||
ASSERT(0);
|
||||
return false;
|
||||
}
|
||||
```
|
||||
|
||||
### **Slot Validation**
|
||||
|
||||
- Slot index must be within bounds of shortcut set size
|
||||
- `SetShortcut()` handles slot bounds checking internally
|
||||
|
||||
---
|
||||
|
||||
## Related Functions
|
||||
|
||||
### **ClearComboSkill** (EC_HostPlayer.cpp:7740-7747)
|
||||
|
||||
```cpp
|
||||
void CECHostPlayer::ClearComboSkill()
|
||||
{
|
||||
if (m_pComboSkill)
|
||||
{
|
||||
delete m_pComboSkill;
|
||||
m_pComboSkill = NULL;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### **GetGroupIndex** (EC_Shortcut.h)
|
||||
|
||||
```cpp
|
||||
int GetGroupIndex() const { return m_iGroupIdx; }
|
||||
```
|
||||
|
||||
Used to retrieve the group index from a shortcut for UI display or validation.
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
**CreateSkillGroupShortcut Flow:**
|
||||
|
||||
1. **Entry Points:**
|
||||
- UI drag & drop operation
|
||||
- Config data loading from server/save
|
||||
- Programmatic assignment from config array
|
||||
|
||||
2. **Core Process:**
|
||||
- Create `CECSCSkillGrp` object
|
||||
- Initialize with group index
|
||||
- Store in shortcut set at specified slot
|
||||
|
||||
3. **Execution:**
|
||||
- When shortcut is clicked, `Execute()` is called
|
||||
- Calls `ApplyComboSkill()` on host player
|
||||
- Creates and initializes `CECComboSkill` object
|
||||
- Starts combo skill sequence execution
|
||||
|
||||
4. **Data Source:**
|
||||
- Combo skill definitions stored in `EC_VIDEO_SETTING.comboSkill[]`
|
||||
- Each combo group contains array of skill IDs
|
||||
- Group index (0-based) references position in array
|
||||
|
||||
---
|
||||
|
||||
## Conversion Notes for C#
|
||||
|
||||
When converting to C#:
|
||||
- Replace `new`/`delete` with C# object allocation
|
||||
- Use `List<>` instead of `std::vector`
|
||||
- Use `string` instead of `CECString`
|
||||
- Use nullable types for optional values
|
||||
- Use `IDisposable` pattern for cleanup
|
||||
- Consider using events/delegates for shortcut execution
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f3fdcd3d58e16de40b0541be0d654c69
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -3,7 +3,6 @@ using UnityEngine;
|
||||
|
||||
namespace BrewMonster
|
||||
{
|
||||
|
||||
public class PlayerInfo { }
|
||||
|
||||
public struct ComboArg
|
||||
|
||||
@@ -141,18 +141,14 @@ namespace BrewMonster
|
||||
public override int GetRequiredMoney(Skill skill) => RequiredMoneyArray[skill.GetLevel() - 1];
|
||||
|
||||
#if SKILL_CLIENT
|
||||
public int GetIntroduction(Skill skill, StringBuilder buffer, int length, string format)
|
||||
public override int GetIntroduction(Skill skill, StringBuilder buffer, string format)
|
||||
{
|
||||
string result = string.Format(format,
|
||||
skill.GetLevel(),
|
||||
-5 + 7 * skill.GetLevel(),
|
||||
1.9 * skill.GetLevel() * skill.GetLevel() + 64 * skill.GetLevel() + 36.7);
|
||||
if (result.Length < length)
|
||||
{
|
||||
buffer.Append(result);
|
||||
return result.Length;
|
||||
}
|
||||
return 0;
|
||||
buffer.Append(result);
|
||||
return result.Length;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
using BrewMonster.Assets.PerfectWorld.Scripts.Skills;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
using static UnityEngine.Rendering.DebugUI;
|
||||
|
||||
namespace BrewMonster.Scripts.Skills
|
||||
{
|
||||
@@ -74,7 +77,10 @@ namespace BrewMonster.Scripts.Skills
|
||||
}
|
||||
public override int GetRangeType() { return stub.GetRange().type; }
|
||||
public override int GetRequiredLevel() { return stub.GetRequiredLevel(this); }
|
||||
|
||||
public override void GetIntroduction(StringBuilder buf, SkillStr table)
|
||||
{
|
||||
int n = stub.GetIntroduction(this, buf, table.Find((int)stub.id * 10 + 1));
|
||||
}
|
||||
public override int GetTargetType()
|
||||
{
|
||||
if (stub.restrict_corpse == 1)
|
||||
@@ -89,6 +95,7 @@ namespace BrewMonster.Scripts.Skills
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
public override int GetComboSkPreSkill() { return stub.combosk_preskill; }
|
||||
public override byte GetType() { return stub.type; }
|
||||
public override int GetCommonCoolDown() { return stub.commoncooldown; }
|
||||
|
||||
@@ -97,6 +104,7 @@ namespace BrewMonster.Scripts.Skills
|
||||
return stub.GetIcon();
|
||||
}
|
||||
public int GetAbility() { return SkillWrapper.Instance.GetAbility(id); }
|
||||
public bool CheckComboSkExtraCondition() { return stub.CheckComboSkExtraCondition(this); }
|
||||
|
||||
public override string GetName() { return stub.GetName(); }
|
||||
public override float GetPrayRange(float range, float prayplus)
|
||||
@@ -131,6 +139,7 @@ namespace BrewMonster.Scripts.Skills
|
||||
public int GetRequiredRealmLevel() { return stub.GetRequiredRealmLevel(this); }
|
||||
public int GetMaxability() { return stub.GetMaxAbility(this); }
|
||||
public uint GetId() { return id; }
|
||||
public int GetComboSkInterval() { return stub.combosk_interval; }
|
||||
|
||||
}
|
||||
|
||||
@@ -232,7 +241,12 @@ namespace BrewMonster.Scripts.Skills
|
||||
}
|
||||
public static List<uint> GetInherentSkillList(uint cls)
|
||||
{
|
||||
return inheritSkillMap[cls];
|
||||
if (!inheritSkillMap.TryGetValue(cls, out List<uint> list))
|
||||
{
|
||||
list = new List<uint>();
|
||||
inheritSkillMap[cls] = list;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public static SkillStub GetStub(uint i)
|
||||
@@ -243,11 +257,20 @@ namespace BrewMonster.Scripts.Skills
|
||||
public static void InitStaticData()
|
||||
{
|
||||
var map = GetMap();
|
||||
var comboMap = GetComboSkMap();
|
||||
foreach (var skill in map)
|
||||
{
|
||||
SkillStub sk = skill.Value;
|
||||
if (sk.is_inherent) GetInherentSkillList((uint)sk.cls).Add(sk.id);
|
||||
if (sk.combosk_preskill > 0) GetComboSkMap()[(uint)sk.combosk_preskill].Add(sk.id);
|
||||
if (sk.combosk_preskill > 0)
|
||||
{
|
||||
if (!comboMap.TryGetValue((uint)sk.combosk_preskill, out List<uint> comboList))
|
||||
{
|
||||
comboList = new List<uint>();
|
||||
comboMap[(uint)sk.combosk_preskill] = comboList;
|
||||
}
|
||||
comboList.Add(sk.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -281,7 +304,7 @@ namespace BrewMonster.Scripts.Skills
|
||||
public virtual int GetExecutetime(Skill skill) { return 1000; }
|
||||
public virtual bool CheckHpCondition(int hp, int max_hp) { return true; }
|
||||
public virtual bool CheckComboSkExtraCondition(Skill skill) { return true; }
|
||||
public virtual int GetIntroduction(Skill skill, ushort[] descBuffer, int descBufferLen, ushort[] titleBuffer) { return 0; }
|
||||
public virtual int GetIntroduction(Skill skill, StringBuilder descBuffer, string titleBuffer) { return 0; }
|
||||
|
||||
// ������Ч�Լ�� // Validate weapon restriction
|
||||
public bool ValidWeapon(int weapon)
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9cfabbaaddd233a4a9d4f07a3577d3a2
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,207 @@
|
||||
using Tech3C;
|
||||
using BrewMonster;
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BrewMonster.Scripts
|
||||
{
|
||||
public enum LOGIN_ERROR_CODE
|
||||
{
|
||||
SUCCESS = 0,
|
||||
CANCELLED = -1
|
||||
}
|
||||
|
||||
public class Tech3CSDKWrapper : Singleton<Tech3CSDKWrapper>
|
||||
{
|
||||
public string clientId = "";
|
||||
public string clientSecret = "";
|
||||
|
||||
private AuthCallback authCallback;
|
||||
private LogoutCallback logoutCallback;
|
||||
|
||||
/// <summary>
|
||||
/// After Tech3C SDK returns result, this callback will be called. <br/>
|
||||
/// (errorCode, userId, password)
|
||||
/// </summary>
|
||||
public Action<int, string, string> onLoginCallback;
|
||||
public Action<int, string> onLogOutCallback;
|
||||
|
||||
public bool isInitialized = false;
|
||||
public bool isProcessing = false; // true if the SDK is processing a request (login or logout)
|
||||
|
||||
#region private functions
|
||||
protected override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SetupCallbacks();
|
||||
|
||||
// Auto-initialize SDK
|
||||
if (!string.IsNullOrEmpty(clientId) && !string.IsNullOrEmpty(clientSecret))
|
||||
{
|
||||
BMLogger.Log($"Initializing Tech3C SDK...\n Client ID: {clientId}");
|
||||
Tech3CSDK.Instance.Initialize(clientId, clientSecret);
|
||||
|
||||
if (Tech3CSDK.Instance.IsInitialized)
|
||||
{
|
||||
BMLogger.Log("[SDK] SDK Initialized Successfully!");
|
||||
}
|
||||
else
|
||||
{
|
||||
BMLogger.Log("[SDK] Failed to initialize SDK");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BMLogger.Log("[SDK] Client ID and/or Client Secret not set. Please configure in Inspector.");
|
||||
}
|
||||
|
||||
BMLogger.Log("[SDK] Tech3C SDK Simple Demo Started");
|
||||
|
||||
isInitialized = true;
|
||||
}
|
||||
|
||||
private void SetupCallbacks()
|
||||
{
|
||||
// Auth callback
|
||||
authCallback = new AuthCallback();
|
||||
authCallback.OnAuthSuccessEvent += OnAuthSuccessEvent;
|
||||
authCallback.OnAuthCancelledEvent += OnAuthCancelledEvent;
|
||||
authCallback.OnAuthErrorEvent += OnAuthErrorEvent;
|
||||
|
||||
// Logout callback
|
||||
logoutCallback = new LogoutCallback();
|
||||
logoutCallback.OnLogoutSuccessEvent += OnLogoutSuccessEvent;
|
||||
logoutCallback.OnLogoutErrorEvent += OnLogoutErrorEvent;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region SDK Callbacks
|
||||
private void OnAuthSuccessEvent(string userId, string password, string accessToken, string refreshToken, LoginType loginType, long expiryTime)
|
||||
{
|
||||
isProcessing = false;
|
||||
BMLogger.Log($"[SDK] Auth Success!\n User ID: {userId}\n Password: {password}\n Login Type: {loginType}\n Token: {accessToken?.Substring(0, Mathf.Min(20, accessToken?.Length ?? 0))}...");
|
||||
onLoginCallback?.Invoke((byte)LOGIN_ERROR_CODE.SUCCESS, userId, password);
|
||||
}
|
||||
|
||||
private void OnAuthCancelledEvent()
|
||||
{
|
||||
isProcessing = false;
|
||||
BMLogger.Log("[SDK] Auth Cancelled by user");
|
||||
onLoginCallback?.Invoke((int)LOGIN_ERROR_CODE.CANCELLED, "", "");
|
||||
}
|
||||
|
||||
private void OnAuthErrorEvent(int errorCode, string errorMessage)
|
||||
{
|
||||
isProcessing = false;
|
||||
BMLogger.Log($"[SDK] Auth Error [{errorCode}]: {errorMessage}");
|
||||
onLoginCallback?.Invoke(errorCode, errorMessage, string.Empty);
|
||||
}
|
||||
|
||||
private void OnLogoutSuccessEvent()
|
||||
{
|
||||
isProcessing = false;
|
||||
BMLogger.Log("[SDK] Logout Successful");
|
||||
onLogOutCallback?.Invoke((int)LOGIN_ERROR_CODE.SUCCESS, "");
|
||||
}
|
||||
|
||||
private void OnLogoutErrorEvent(int errorCode, string errorMessage)
|
||||
{
|
||||
isProcessing = false;
|
||||
BMLogger.Log($"[SDK] Logout Error [{errorCode}]: {errorMessage}");
|
||||
onLogOutCallback?.Invoke(errorCode, errorMessage);
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region public functions
|
||||
|
||||
public void SetLoginCallback(Action<int, string, string> callback)
|
||||
{
|
||||
if (callback != null)
|
||||
{
|
||||
BMLogger.LogWarning("[SDK] Login callback is already set, it will be overridden");
|
||||
}
|
||||
onLoginCallback = callback;
|
||||
}
|
||||
|
||||
public void RemoveLoginCallback()
|
||||
{
|
||||
onLoginCallback = null;
|
||||
}
|
||||
|
||||
public void SetLogoutCallback(Action<int, string> callback)
|
||||
{
|
||||
if (callback != null)
|
||||
{
|
||||
BMLogger.LogWarning("[SDK] Logout callback is already set, it will be overridden");
|
||||
}
|
||||
onLogOutCallback = callback;
|
||||
}
|
||||
|
||||
public void RemoveLogoutCallback()
|
||||
{
|
||||
onLogOutCallback = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Show Tech3C SDK login screen.
|
||||
/// Callback will be called after login success or failed.
|
||||
/// </summary>
|
||||
public bool Login()
|
||||
{
|
||||
if (!isInitialized)
|
||||
{
|
||||
BMLogger.LogError("[SDK] SDK is not initialized, please call Initialize() first");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isProcessing)
|
||||
{
|
||||
BMLogger.LogError("[SDK] SDK is already processing a request, please wait for the current request to complete");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (onLoginCallback == null)
|
||||
{
|
||||
BMLogger.LogError("[SDK] Login callback is not set, please set it using SetLoginCallback");
|
||||
return false;
|
||||
}
|
||||
|
||||
isProcessing = true;
|
||||
|
||||
Tech3CSDK.Instance.ShowAuth(authCallback);
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool Logout()
|
||||
{
|
||||
if (!isInitialized)
|
||||
{
|
||||
BMLogger.LogError("[SDK] SDK is not initialized, please call Initialize() first");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isProcessing)
|
||||
{
|
||||
BMLogger.LogError("[SDK] SDK is already processing a request, please wait for the current request to complete");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (onLogOutCallback == null)
|
||||
{
|
||||
BMLogger.LogError("[SDK] Logout callback is not set, please set it using SetLogoutCallback");
|
||||
return false;
|
||||
}
|
||||
|
||||
isProcessing = true;
|
||||
|
||||
Tech3CSDK.Instance.Logout(logoutCallback);
|
||||
return true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 61795692226b05849aec56bf168c905a
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 11093b8e0b61f8e46a8847e31fe74326
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,121 @@
|
||||
using BrewMonster.Assets.PerfectWorld.Scripts.UI.GamePlay;
|
||||
using BrewMonster.UI;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using static UnityEditor.AddressableAssets.Build.Layout.BuildLayout;
|
||||
|
||||
namespace BrewMonster
|
||||
{
|
||||
public class CDlgSkillSubAction : MonoBehaviour
|
||||
{
|
||||
[SerializeField] List<ActionInfo> m_aActionInfo = new List<ActionInfo>();
|
||||
[SerializeField] Transform orderContain;
|
||||
[SerializeField] AUIImagePicture orderTemplate;
|
||||
[SerializeField] AUIImagePicture actionTemplate;
|
||||
[SerializeField] Transform actionContain;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (orderContain == null)
|
||||
{
|
||||
BMLogger.LogError("CDlgSkillSubAction: orderContain is not assigned!");
|
||||
return;
|
||||
}
|
||||
;
|
||||
if (actionContain == null)
|
||||
{
|
||||
BMLogger.LogError("CDlgSkillSubAction: actionContain is not assigned!");
|
||||
return;
|
||||
}
|
||||
|
||||
Init();
|
||||
}
|
||||
private void OnEnable()
|
||||
{
|
||||
OnShowDialog();
|
||||
}
|
||||
public void Init()
|
||||
{
|
||||
int[] objCount = { 8, 2, 2, 27 };
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
for (int j = 0; j < objCount[i]; j++)
|
||||
{
|
||||
var orderTP = Instantiate(orderTemplate, orderContain);
|
||||
orderTP.gameObject.SetActive(true);
|
||||
m_aActionInfo.Add(new ActionInfo
|
||||
{
|
||||
image = orderTP,
|
||||
pLabel = orderTP.GetComponentInChildren<TextMeshProUGUI>()
|
||||
});
|
||||
}
|
||||
}
|
||||
for (int j = 0; j < 27; j++)
|
||||
{
|
||||
var actionTP = Instantiate(actionTemplate, actionContain);
|
||||
actionTP.gameObject.SetActive(true);
|
||||
m_aActionInfo.Add(new ActionInfo
|
||||
{
|
||||
image = actionTP,
|
||||
pLabel = actionTP.GetComponentInChildren<TextMeshProUGUI>()
|
||||
});
|
||||
}
|
||||
}
|
||||
public void OnShowDialog()
|
||||
{
|
||||
AUIImagePicture pImage;
|
||||
TextMeshProUGUI pLabel;
|
||||
CECShortcut pSCThis;
|
||||
string strFile = "";
|
||||
var gameUIMan = CECUIManager.Instance.GetInGameUIMan();
|
||||
|
||||
CECGameRun pGameRun = CECGameRun.Instance;
|
||||
int[] objCount = { 8, 2, 2, 27 };
|
||||
CECShortcutSet[] a_pSC =
|
||||
{
|
||||
pGameRun.GetGenCmdShortcuts(),
|
||||
pGameRun.GetTeamCmdShortcuts(),
|
||||
pGameRun.GetTradeCmdShortcuts(),
|
||||
pGameRun.GetPoseCmdShortcuts()
|
||||
};
|
||||
int count = 0;
|
||||
for (int i = 0; i < a_pSC.Length; i++)
|
||||
{
|
||||
for (int j = 0; j < objCount[i]; j++)
|
||||
{
|
||||
pImage = m_aActionInfo[count].image;
|
||||
pLabel = m_aActionInfo[count].pLabel;
|
||||
|
||||
if (!pImage) break;
|
||||
|
||||
if (j < a_pSC[i].GetShortcutNum())
|
||||
{
|
||||
pSCThis = a_pSC[i].GetShortcut(j);
|
||||
pImage.SetDataPtr(pSCThis, "ptr_CECShortcut");
|
||||
|
||||
strFile = pSCThis.GetIconFile();
|
||||
gameUIMan.SetCover(pImage, strFile, EC_GAMEUI_ICONS.ICONS_ACTION);
|
||||
|
||||
pLabel.SetText(pSCThis.GetDesc());
|
||||
}
|
||||
else
|
||||
{
|
||||
/* pImage->Show(false);
|
||||
pLabel->Show(false);*/
|
||||
}
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
[Serializable]
|
||||
public struct ActionInfo
|
||||
{
|
||||
public AUIImagePicture image;
|
||||
public TextMeshProUGUI pLabel;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1eda03e6b4326e14b95d57bf324b96bb
|
||||
@@ -1,28 +1,79 @@
|
||||
using BrewMonster.UI;
|
||||
using System;
|
||||
using BrewMonster.UI;
|
||||
using UnityEngine;
|
||||
using static CECUIManager;
|
||||
|
||||
namespace BrewMonster
|
||||
{
|
||||
public enum MessageBoxType
|
||||
{
|
||||
YesButton,
|
||||
NoButton,
|
||||
BothYesNoButton,
|
||||
}
|
||||
public struct MessageBoxData
|
||||
{
|
||||
public string Title;
|
||||
public string Message;
|
||||
public MessageBoxType MessageBoxType;
|
||||
public Action OnClickedYes;
|
||||
public Action OnClickedNo;
|
||||
}
|
||||
public class CDlgMessageBox : AUIDialog
|
||||
{
|
||||
[SerializeField] private TMPro.TextMeshProUGUI titleText;
|
||||
[SerializeField] private TMPro.TextMeshProUGUI messageText;
|
||||
[SerializeField] private UnityEngine.UI.Button okButton;
|
||||
private void Awake()
|
||||
[SerializeField] private UnityEngine.UI.Button _noButton;
|
||||
|
||||
private MessageBoxData _messageData;
|
||||
|
||||
public override void OnEnable()
|
||||
{
|
||||
okButton.onClick.RemoveAllListeners();
|
||||
base.OnEnable();
|
||||
okButton.onClick.AddListener(OnOkClicked);
|
||||
_noButton.onClick.AddListener(OnNoClicked);
|
||||
}
|
||||
|
||||
public override void OnDisable()
|
||||
{
|
||||
okButton.onClick.RemoveListener(OnOkClicked);
|
||||
_noButton.onClick.RemoveListener(OnNoClicked);
|
||||
}
|
||||
|
||||
private void OnOkClicked()
|
||||
{
|
||||
EventBus.Publish(new MessageBoxEvent(1,this));
|
||||
_messageData.OnClickedYes?.Invoke();
|
||||
Show(false);
|
||||
}
|
||||
public void ShowMessageBox(string title, string message)
|
||||
private void OnNoClicked()
|
||||
{
|
||||
SetName(title);
|
||||
messageText.text = message;
|
||||
EventBus.Publish(new MessageBoxEvent(0,this));
|
||||
_messageData.OnClickedNo?.Invoke();
|
||||
Show(false);
|
||||
}
|
||||
public void ShowMessageBox(MessageBoxData messageBoxData)
|
||||
{
|
||||
_messageData = messageBoxData;
|
||||
SetName(messageBoxData.Title);
|
||||
messageText.text = messageBoxData.Message;
|
||||
|
||||
okButton.gameObject.SetActive(false);
|
||||
_noButton.gameObject.SetActive(false);
|
||||
switch (_messageData.MessageBoxType)
|
||||
{
|
||||
case MessageBoxType.YesButton:
|
||||
okButton.gameObject.SetActive(true);
|
||||
break;
|
||||
case MessageBoxType.NoButton:
|
||||
_noButton.gameObject.SetActive(true);
|
||||
break;
|
||||
case MessageBoxType.BothYesNoButton:
|
||||
okButton.gameObject.SetActive(true);
|
||||
_noButton.gameObject.SetActive(true);
|
||||
break;
|
||||
}
|
||||
Show(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
using BrewMonster.Network;
|
||||
using BrewMonster.UI;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BrewMonster
|
||||
{
|
||||
public class CDlgDragDrop : MonoBehaviour
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
private void Update()
|
||||
{
|
||||
if (Input.GetKeyDown(KeyCode.S))
|
||||
OnSkillDragDrop();
|
||||
}
|
||||
#endif
|
||||
public void OnSkillDragDrop()
|
||||
{
|
||||
var iSlot = 2;
|
||||
var nCombo = 2;
|
||||
CECShortcutSet pSCS = CECUIManager.Instance.GetInGameUIMan().GetSCSByDlg(1);
|
||||
if (pSCS.GetShortcut(iSlot - 1) == null || !EC_Game.GetConfigs().GetGameSettings().bLockQuickBar)
|
||||
pSCS.CreateSkillGroupShortcut(iSlot - 1, nCombo - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*AString s = WC2AS(*pstr); // convert wide -> ansi/utf8 tùy macro bạn định nghĩa
|
||||
a_LogOutput(0, "HoangDev: 1 n=%d, pstr=%s", n, static_cast <const char*>(s));*/
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ad855801e0cddfe46a48b448016ee952
|
||||
@@ -0,0 +1,540 @@
|
||||
using System.Collections.Generic;
|
||||
using BrewMonster;
|
||||
using BrewMonster.Scripts.Skills;
|
||||
using BrewMonster.UI;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using TMPro;
|
||||
using BrewMonster.Assets.PerfectWorld.Scripts.UI.GamePlay;
|
||||
using BrewMonster.Network;
|
||||
|
||||
namespace BrewMonster.UI
|
||||
{
|
||||
/// <summary>
|
||||
/// Skill dialog sub-other panel - displays combo skills, fixed skills, item skills, and produce skills
|
||||
/// Converted from DlgSkillSubOther.cpp/h
|
||||
/// </summary>
|
||||
[DisallowMultipleComponent]
|
||||
public class CDlgSkillSubOther : AUIDialog
|
||||
{
|
||||
private const int ITEM_SKILL_MAX_COUNT = 8;
|
||||
private const int FIXED_SKILL_MAX_COUNT = 4;
|
||||
|
||||
[Header("Combo Skill Images")]
|
||||
[SerializeField] private List<AUIImagePicture> m_comboSkillImages = new List<AUIImagePicture>();
|
||||
|
||||
[Header("Fixed Skill Components")]
|
||||
[SerializeField] private List<AUIImagePicture> m_fixedImgPics = new List<AUIImagePicture>();
|
||||
[SerializeField] private List<TextMeshProUGUI> m_fixedTxts = new List<TextMeshProUGUI>();
|
||||
|
||||
[Header("Item Skill Images")]
|
||||
[SerializeField] private List<AUIImagePicture> m_itemSkillImages = new List<AUIImagePicture>();
|
||||
|
||||
[Header("Produce Skill Components")]
|
||||
[SerializeField] private List<AUIImagePicture> m_produceImgIcons = new List<AUIImagePicture>();
|
||||
[SerializeField] private List<TextMeshProUGUI> m_produceNameLabels = new List<TextMeshProUGUI>();
|
||||
[SerializeField] private List<TextMeshProUGUI> m_produceSkilledTxtLabels = new List<TextMeshProUGUI>();
|
||||
[SerializeField] private List<TextMeshProUGUI> m_produceSkilledExpLabels = new List<TextMeshProUGUI>();
|
||||
[SerializeField] private List<TextMeshProUGUI> m_produceLevelLabels = new List<TextMeshProUGUI>();
|
||||
|
||||
[Header("Buttons")]
|
||||
[SerializeField] private Button m_btnEdit;
|
||||
[SerializeField] private Button m_btnDelete;
|
||||
[SerializeField] private Button m_btnNew;
|
||||
|
||||
private int m_nComboSelect = 0;
|
||||
|
||||
private readonly List<uint> m_fixedSkills = new List<uint>();
|
||||
private readonly List<uint> m_produceSkills = new List<uint>();
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
// Initialize fixed skills - 167 is return skill
|
||||
m_fixedSkills.Add(167);
|
||||
|
||||
// Initialize produce skills - respectively: weapon crafting, armor crafting, accessory crafting, alchemy
|
||||
m_produceSkills.Add(158);
|
||||
m_produceSkills.Add(159);
|
||||
m_produceSkills.Add(160);
|
||||
m_produceSkills.Add(161);
|
||||
|
||||
// Setup button listeners
|
||||
if (m_btnEdit != null)
|
||||
m_btnEdit.onClick.AddListener(OnCommandEdit);
|
||||
if (m_btnDelete != null)
|
||||
m_btnDelete.onClick.AddListener(OnCommandDelete);
|
||||
if (m_btnNew != null)
|
||||
m_btnNew.onClick.AddListener(OnCommandNew);
|
||||
}
|
||||
|
||||
public override void OnShowDialogue()
|
||||
{
|
||||
base.OnShowDialogue();
|
||||
Debug.Log("CDlgSkillSubOther::OnShowDialog()");
|
||||
UpdateComboSkill();
|
||||
UpdateFixedSkill();
|
||||
UpdateItemSkill();
|
||||
UpdateProduceSkill();
|
||||
}
|
||||
|
||||
/*public override bool Render()
|
||||
{
|
||||
if (!base.Render())
|
||||
return false;
|
||||
|
||||
if (!gameObject.activeInHierarchy)
|
||||
return true;
|
||||
|
||||
// Item skills and produce skills may change, update them
|
||||
UpdateItemSkill();
|
||||
UpdateProduceSkill();
|
||||
|
||||
// Update fixed skill cooldowns
|
||||
CECHostPlayer host = GetHostPlayer();
|
||||
for (int i = 0; i < m_fixedSkills.Count && i < m_fixedImgPics.Count; i++)
|
||||
{
|
||||
if (m_fixedImgPics[i] != null && host != null)
|
||||
{
|
||||
CECSkill pSkill = host.GetPositiveSkillByID(m_fixedSkills[i]);
|
||||
UpdateImagePictureCD(m_fixedImgPics[i], pSkill);
|
||||
}
|
||||
}
|
||||
|
||||
// Update item skill cooldowns
|
||||
int equipSkillNum = host != null ? host.GetEquipSkillNum() : 0;
|
||||
for (int i = 0; i < equipSkillNum && i < ITEM_SKILL_MAX_COUNT && i < m_itemSkillImages.Count; i++)
|
||||
{
|
||||
if (m_itemSkillImages[i] != null && host != null)
|
||||
{
|
||||
CECSkill pSkill = host.GetEquipSkillByIndex(i);
|
||||
UpdateImagePictureCD(m_itemSkillImages[i], pSkill);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}*/
|
||||
|
||||
// Edit combo skill - called from DlgSkill
|
||||
public void OnCommandEdit()
|
||||
{
|
||||
// TODO: Implement DlgSkillEdit equivalent
|
||||
// GetGameUIMan()->m_pDlgSkillEdit->SetData(m_nComboSelect);
|
||||
// GetGameUIMan()->m_pDlgSkillEdit->Show(true);
|
||||
Debug.Log($"OnCommandEdit: combo select = {m_nComboSelect}");
|
||||
}
|
||||
|
||||
// New combo skill - called from DlgSkill
|
||||
public void OnCommandNew()
|
||||
{
|
||||
// TODO: Implement DlgSkillEdit equivalent
|
||||
// GetGameUIMan()->m_pDlgSkillEdit->SetData(0);
|
||||
// GetGameUIMan()->m_pDlgSkillEdit->Show(true);
|
||||
Debug.Log("OnCommandNew");
|
||||
}
|
||||
|
||||
// Delete combo skill - called from DlgSkill
|
||||
public void OnCommandDelete()
|
||||
{
|
||||
if (m_nComboSelect < 0 || m_nComboSelect > EC_ConfigConstants.EC_COMBOSKILL_NUM)
|
||||
return;
|
||||
|
||||
CECConfigs configs = EC_Game.GetConfigs();
|
||||
if (configs == null)
|
||||
return;
|
||||
|
||||
EC_VIDEO_SETTING setting = configs.GetVideoSettings();
|
||||
setting.comboSkill[m_nComboSelect - 1].nIcon = 0;
|
||||
m_nComboSelect = 0;
|
||||
configs.SetVideoSettings(setting);
|
||||
UpdateComboSkill();
|
||||
}
|
||||
|
||||
// Helper dictionary to store combo skill data
|
||||
private Dictionary<AUIImagePicture, uint> m_comboSkillData = new Dictionary<AUIImagePicture, uint>();
|
||||
|
||||
// Helper dictionary to store skill data for images
|
||||
private Dictionary<AUIImagePicture, CECSkill> m_skillData = new Dictionary<AUIImagePicture, CECSkill>();
|
||||
|
||||
// Update combo skill icons - called from DlgSkill
|
||||
public void UpdateComboSkill()
|
||||
{
|
||||
/*CECConfigs configs = EC_Game.GetConfigs();
|
||||
if (configs == null)
|
||||
return;
|
||||
|
||||
EC_VIDEO_SETTING setting = configs.GetVideoSettings();
|
||||
CECGameUIMan gameUIMan = GetGameUIMan();
|
||||
|
||||
for (int i = 0; i < EC_ConfigConstants.EC_COMBOSKILL_NUM; i++)
|
||||
{
|
||||
AUIImagePicture pImage = m_comboSkillImages[i];
|
||||
if (pImage != null)
|
||||
{
|
||||
if (setting.comboSkill[i].nIcon != 0)
|
||||
{
|
||||
// TODO: Set icon from sprite sheet
|
||||
//pImage->SetCover(GetGameUIMan()->m_pA2DSpriteIcons[CECGameUIMan::ICONS_SKILLGRP],
|
||||
// setting.comboSkill[i].nIcon + 1);
|
||||
m_comboSkillData[pImage] = (uint)(i + 1);
|
||||
//pImage.SetDataPtr(new object(), "ptr_Valid"); // Equivalent to (void*)1
|
||||
|
||||
string hintText = GetStringFromTable(804);
|
||||
if (!string.IsNullOrEmpty(hintText))
|
||||
{
|
||||
hintText = string.Format(hintText, i);
|
||||
// TODO: Set hint text
|
||||
// pImage->SetHint(hintText);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Clear icon
|
||||
// pImage->SetCover(NULL, -1);
|
||||
m_comboSkillData[pImage] = 0;
|
||||
pImage.SetDataPtr(null);
|
||||
// pImage->SetHint("");
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
// Update fixed skill display
|
||||
public void UpdateFixedSkill()
|
||||
{
|
||||
// First hide all fixed skill components
|
||||
/*for (int i = 0; i < FIXED_SKILL_MAX_COUNT; i++)
|
||||
{
|
||||
if (i < m_fixedImgPics.Count && m_fixedImgPics[i] != null)
|
||||
m_fixedImgPics[i].gameObject.SetActive(false);
|
||||
if (i < m_fixedTxts.Count && m_fixedTxts[i] != null)
|
||||
m_fixedTxts[i].gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
Debug.Assert(m_fixedSkills.Count <= FIXED_SKILL_MAX_COUNT, "Fixed skills count exceeds max");
|
||||
|
||||
CECHostPlayer host = GetHostPlayer();
|
||||
for (int i = 0; i < m_fixedSkills.Count; i++)
|
||||
{
|
||||
if (i < m_fixedImgPics.Count && m_fixedImgPics[i] != null)
|
||||
m_fixedImgPics[i].gameObject.SetActive(true);
|
||||
if (i < m_fixedTxts.Count && m_fixedTxts[i] != null)
|
||||
m_fixedTxts[i].gameObject.SetActive(true);
|
||||
|
||||
CECSkill pSkill = host?.GetPositiveSkillByID(m_fixedSkills[i]);
|
||||
if (pSkill != null)
|
||||
{
|
||||
SetImage(m_fixedImgPics[i], pSkill);
|
||||
if (i < m_fixedTxts.Count && m_fixedTxts[i] != null)
|
||||
m_fixedTxts[i].text = pSkill.GetNameDisplay();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (i < m_fixedImgPics.Count && m_fixedImgPics[i] != null)
|
||||
{
|
||||
m_fixedImgPics[i].gameObject.SetActive(false);
|
||||
SetImage(m_fixedImgPics[i], null);
|
||||
}
|
||||
if (i < m_fixedTxts.Count && m_fixedTxts[i] != null)
|
||||
m_fixedTxts[i].gameObject.SetActive(false);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
// Update item skill display
|
||||
public void UpdateItemSkill()
|
||||
{
|
||||
CECHostPlayer host = GetHostPlayer();
|
||||
if (host == null)
|
||||
return;
|
||||
|
||||
int equipSkillNum = host.GetEquipSkillNum();
|
||||
for (int i = 0; i < ITEM_SKILL_MAX_COUNT && i < m_itemSkillImages.Count; i++)
|
||||
{
|
||||
AUIImagePicture pImgPic = m_itemSkillImages[i];
|
||||
if (pImgPic != null)
|
||||
{
|
||||
if (i < equipSkillNum)
|
||||
{
|
||||
CECSkill pSkill = host.GetEquipSkillByIndex(i);
|
||||
SetImage(pImgPic, pSkill);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetImage(pImgPic, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update produce skill display
|
||||
public void UpdateProduceSkill()
|
||||
{
|
||||
CECHostPlayer host = GetHostPlayer();
|
||||
if (host == null)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < m_produceSkills.Count; i++)
|
||||
{
|
||||
AUIImagePicture imgIcon = i < m_produceImgIcons.Count ? m_produceImgIcons[i] : null;
|
||||
TextMeshProUGUI lblName = i < m_produceNameLabels.Count ? m_produceNameLabels[i] : null;
|
||||
TextMeshProUGUI lblSkilledTxt = i < m_produceSkilledTxtLabels.Count ? m_produceSkilledTxtLabels[i] : null;
|
||||
TextMeshProUGUI lblSkilledExp = i < m_produceSkilledExpLabels.Count ? m_produceSkilledExpLabels[i] : null;
|
||||
TextMeshProUGUI lblLevel = i < m_produceLevelLabels.Count ? m_produceLevelLabels[i] : null;
|
||||
|
||||
if (imgIcon != null)
|
||||
imgIcon.gameObject.SetActive(true);
|
||||
if (lblName != null)
|
||||
lblName.gameObject.SetActive(true);
|
||||
|
||||
//CECSkill pSkill = host.GetPassiveSkillByID(m_produceSkills[i]);
|
||||
/* if (pSkill == null)
|
||||
{
|
||||
if (lblSkilledTxt != null)
|
||||
lblSkilledTxt.gameObject.SetActive(false);
|
||||
if (lblSkilledExp != null)
|
||||
lblSkilledExp.gameObject.SetActive(false);
|
||||
if (lblLevel != null)
|
||||
lblLevel.gameObject.SetActive(false);
|
||||
|
||||
if (imgIcon != null)
|
||||
{
|
||||
// Set gray color
|
||||
Image img = imgIcon.GetComponent<Image>();
|
||||
if (img != null)
|
||||
img.color = new Color(0.5f, 0.5f, 0.5f, 1f); // RGB(128, 128, 128)
|
||||
}
|
||||
|
||||
CECSkill tmpSkill = new CECSkill(m_produceSkills[i], 1);
|
||||
SetImage(imgIcon, tmpSkill);
|
||||
if (lblName != null)
|
||||
lblName.text = tmpSkill.GetNameDisplay();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lblSkilledTxt != null)
|
||||
lblSkilledTxt.gameObject.SetActive(true);
|
||||
if (lblSkilledExp != null)
|
||||
lblSkilledExp.gameObject.SetActive(true);
|
||||
if (lblLevel != null)
|
||||
lblLevel.gameObject.SetActive(true);
|
||||
|
||||
if (imgIcon != null)
|
||||
{
|
||||
// Set white color
|
||||
Image img = imgIcon.GetComponent<Image>();
|
||||
if (img != null)
|
||||
img.color = Color.white; // RGB(255, 255, 255)
|
||||
}
|
||||
|
||||
SetImage(imgIcon, pSkill);
|
||||
if (lblName != null)
|
||||
lblName.text = pSkill.GetNameDisplay();*/
|
||||
|
||||
/* int maxAbility = ElementSkill.GetMaxAbility(m_produceSkills[i], pSkill.GetSkillLevel());
|
||||
int ability = ElementSkill.GetAbility(m_produceSkills[i]);*/
|
||||
|
||||
/* if (lblSkilledExp != null)
|
||||
lblSkilledExp.text = $"{ability}/{maxAbility}";*/
|
||||
/*if (lblLevel != null)
|
||||
{
|
||||
string levelFormat = GetStringFromTable(11323);
|
||||
if (!string.IsNullOrEmpty(levelFormat))
|
||||
lblLevel.text = string.Format(levelFormat, pSkill.GetSkillLevel());
|
||||
}*/
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
// Get combo skill data for an image
|
||||
private uint GetComboSkillData(AUIImagePicture pImage)
|
||||
{
|
||||
if (pImage == null)
|
||||
return 0;
|
||||
return m_comboSkillData.TryGetValue(pImage, out uint data) ? data : 0;
|
||||
}
|
||||
|
||||
// Handle combo skill icon click for drag - called from DlgSkill
|
||||
public void OnEventLButtonDownCombo(AUIImagePicture pObj)
|
||||
{
|
||||
uint data = GetComboSkillData(pObj);
|
||||
if (pObj == null || data == 0)
|
||||
return;
|
||||
|
||||
// TODO: Implement drag and drop
|
||||
// A3DVIEWPORTPARAM *p = m_pA3DEngine->GetActiveViewport()->GetParam();
|
||||
// POINT pt = { GET_X_LPARAM(lParam) - p->X, GET_Y_LPARAM(lParam) - p->Y };
|
||||
// GetGameUIMan()->m_ptLButtonDown = pt;
|
||||
// GetGameUIMan()->InvokeDragDrop(this, pObj, pt);
|
||||
Debug.Log($"OnEventLButtonDownCombo: combo skill {data}");
|
||||
}
|
||||
|
||||
// Handle fixed skill icon click for drag
|
||||
public void OnEventLButtonDownFixed(AUIImagePicture pObj)
|
||||
{
|
||||
if (pObj == null)
|
||||
return;
|
||||
|
||||
/* CECSkill skill = GetSkillFromImage(pObj);
|
||||
if (skill == null)
|
||||
return;*/
|
||||
|
||||
// TODO: Implement drag and drop
|
||||
// GetGameUIMan()->m_ptLButtonDown = ...;
|
||||
// GetGameUIMan()->InvokeDragDrop(this, pObj, GetGameUIMan()->m_ptLButtonDown);
|
||||
Debug.Log("OnEventLButtonDownFixed");
|
||||
}
|
||||
|
||||
// Handle item skill icon click for drag
|
||||
public void OnEventLButtonDownItem(AUIImagePicture pObj)
|
||||
{
|
||||
if (pObj == null)
|
||||
return;
|
||||
|
||||
/* CECSkill skill = GetSkillFromImage(pObj);
|
||||
if (skill == null)
|
||||
return;*/
|
||||
|
||||
// TODO: Implement drag and drop
|
||||
// GetGameUIMan()->m_ptLButtonDown = ...;
|
||||
// GetGameUIMan()->InvokeDragDrop(this, pObj, GetGameUIMan()->m_ptLButtonDown);
|
||||
Debug.Log("OnEventLButtonDownItem");
|
||||
}
|
||||
|
||||
// Select combo skill - called from DlgSkill
|
||||
public void SelectComboSkill(int n)
|
||||
{
|
||||
if (n < 1 || n > m_comboSkillImages.Count)
|
||||
return;
|
||||
|
||||
if (m_nComboSelect == n)
|
||||
{
|
||||
// Deselect
|
||||
AUIImagePicture pImage = m_comboSkillImages[n - 1];
|
||||
if (pImage != null)
|
||||
{
|
||||
Image img = pImage.GetComponent<Image>();
|
||||
if (img != null)
|
||||
img.color = Color.white; // RGB(255, 255, 255)
|
||||
}
|
||||
m_nComboSelect = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Deselect previous
|
||||
if (m_nComboSelect != 0 && m_nComboSelect <= m_comboSkillImages.Count)
|
||||
{
|
||||
AUIImagePicture pImage = m_comboSkillImages[m_nComboSelect - 1];
|
||||
if (pImage != null)
|
||||
{
|
||||
Image img = pImage.GetComponent<Image>();
|
||||
if (img != null)
|
||||
img.color = Color.white; // RGB(255, 255, 255)
|
||||
}
|
||||
}
|
||||
|
||||
// Select new
|
||||
m_nComboSelect = n;
|
||||
AUIImagePicture pNewImage = m_comboSkillImages[n - 1];
|
||||
if (pNewImage != null)
|
||||
{
|
||||
Image img = pNewImage.GetComponent<Image>();
|
||||
if (img != null)
|
||||
img.color = new Color(0.627f, 0.627f, 0.627f, 1f); // RGB(160, 160, 160)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set image for an AUIImagePicture with a skill - called from DlgSkill
|
||||
public void SetImage(AUIImagePicture pImage, CECSkill pSkill)
|
||||
{
|
||||
if (pImage == null)
|
||||
return;
|
||||
|
||||
if (pSkill != null)
|
||||
{
|
||||
// TODO: Set icon from sprite sheet
|
||||
// AString strFile;
|
||||
// af_GetFileTitle(pSkill->GetIconFile(), strFile);
|
||||
// strFile.MakeLower();
|
||||
// pImage->SetCover(
|
||||
// GetGameUIMan()->m_pA2DSpriteIcons[CECGameUIMan::ICONS_SKILL],
|
||||
// GetGameUIMan()->m_IconMap[CECGameUIMan::ICONS_SKILL][strFile]);
|
||||
|
||||
// Store skill in dictionary for retrieval
|
||||
m_skillData[pImage] = pSkill;
|
||||
|
||||
// Try to set as shortcut if possible
|
||||
/* if (pSkill is CECShortcut shortcut)
|
||||
pImage.SetDataPtr(shortcut, "ptr_CECSkill");*/
|
||||
// TODO: Set hint
|
||||
// pImage->SetHint(pSkill->GetDesc());
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Clear icon
|
||||
// pImage->SetCover(NULL, -1);
|
||||
m_skillData.Remove(pImage);
|
||||
pImage.SetDataPtr(null);
|
||||
// pImage->SetHint("");
|
||||
}
|
||||
}
|
||||
|
||||
// Get skill from image
|
||||
/* private CECSkill GetSkillFromImage(AUIImagePicture pImage)
|
||||
{
|
||||
if (pImage == null)
|
||||
return null;
|
||||
|
||||
// Try dictionary first
|
||||
if (m_skillData.TryGetValue(pImage, out CECSkill skill))
|
||||
return skill;
|
||||
|
||||
// Try shortcut
|
||||
CECShortcut shortcut = pImage.GetDataPtr();
|
||||
return shortcut as CECSkill;
|
||||
}*/
|
||||
|
||||
// Update image picture cooldown display
|
||||
private void UpdateImagePictureCD(AUIImagePicture pImgPic, CECSkill pSkill)
|
||||
{
|
||||
if (pImgPic == null)
|
||||
return;
|
||||
|
||||
CECHostPlayer pHost = GetHostPlayer();
|
||||
if (pHost == null)
|
||||
return;
|
||||
|
||||
AUIClockIcon pClock = pImgPic.GetClockIcon();
|
||||
if (pClock == null)
|
||||
return;
|
||||
|
||||
Image img = pImgPic.GetComponent<Image>();
|
||||
if (img == null)
|
||||
return;
|
||||
|
||||
if (pSkill != null && pSkill.ReadyToCast() && pHost.GetPrepSkill() != pSkill)
|
||||
{
|
||||
if (pHost.CheckSkillCastCondition(pSkill) == 0)
|
||||
img.color = Color.white; // RGB(255, 255, 255)
|
||||
else
|
||||
img.color = new Color(0.5f, 0.5f, 0.5f, 1f); // RGB(128, 128, 128)
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set clock color
|
||||
Image clockImg = pClock.GetClockIcon();
|
||||
if (clockImg != null)
|
||||
clockImg.color = new Color(0, 0, 0, 0.5f); // RGBA(0, 0, 0, 128)
|
||||
}
|
||||
|
||||
if (pSkill != null && (pSkill.GetCoolingTime() > 0 || pHost.GetPrepSkill() == pSkill))
|
||||
{
|
||||
pClock.SetProgressRange(0, pSkill.GetCoolingTime());
|
||||
if (pHost.GetPrepSkill() == pSkill)
|
||||
pClock.SetProgressPos(0);
|
||||
else
|
||||
pClock.SetProgressPos(pSkill.GetCoolingTime() - pSkill.GetCoolingCnt());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 27624565938535e4593764faffe78bbf
|
||||
@@ -33,6 +33,7 @@ namespace BrewMonster
|
||||
[SerializeField] private Button m_BtnCancel;
|
||||
|
||||
[SerializeField] private Sprite khung_item;
|
||||
[SerializeField] private Transform itemInventoryRoot;
|
||||
|
||||
private EC_IvtrItem m_SelectedEquip;
|
||||
private EC_IvtrItem m_SelectedMaterial;
|
||||
@@ -50,12 +51,28 @@ namespace BrewMonster
|
||||
RegisterClick(m_SlotSecondlParent, OnClickMaterialSlot);
|
||||
}
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
#if UNITY_EDITOR || UNITY_STANDALONE
|
||||
if (Input.GetMouseButtonDown(0))
|
||||
{
|
||||
CheckHidePanel(Input.mousePosition);
|
||||
}
|
||||
#else
|
||||
if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began)
|
||||
{
|
||||
CheckHidePanel(Input.GetTouch(0).position);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public override void OnEnable()
|
||||
{
|
||||
base.OnEnable();
|
||||
//todo need to set from other class
|
||||
// SetName("Win_Enchase");
|
||||
m_BtnMerge.onClick.AddListener(OnClickedMerge);
|
||||
m_BtnCancel.onClick.AddListener(OnClickedCancel);
|
||||
m_install_price = -1;
|
||||
}
|
||||
|
||||
@@ -63,11 +80,7 @@ namespace BrewMonster
|
||||
{
|
||||
base.OnDisable();
|
||||
m_BtnMerge.onClick.RemoveListener(OnClickedMerge);
|
||||
}
|
||||
|
||||
public void OpenInstall(uint npcId)
|
||||
{
|
||||
|
||||
m_BtnCancel.onClick.RemoveListener(OnClickedCancel);
|
||||
}
|
||||
|
||||
public void CloseInstall()
|
||||
@@ -217,6 +230,12 @@ namespace BrewMonster
|
||||
else
|
||||
detailedItem.GetDetailDataFromLocal();
|
||||
|
||||
if (m_FirstInvSlot >= 0)
|
||||
{
|
||||
var previosBtn = FindInventoryButtonBySlot(m_FirstInvSlot);
|
||||
SetInventorySlotGray(previosBtn, false);
|
||||
}
|
||||
|
||||
m_SelectedEquip?.Freeze(false);
|
||||
m_SelectedEquip = detailedItem;
|
||||
m_FirstInvSlot = slotIndex;
|
||||
@@ -227,8 +246,6 @@ namespace BrewMonster
|
||||
SetInventorySlotGray(btn, true);
|
||||
|
||||
detailedItem.Freeze(true);
|
||||
|
||||
Debug.Log($"[Install] Equipment: {detailedItem.m_tid} from slot {slotIndex}");
|
||||
}
|
||||
|
||||
private void OnDropMaterial(PointerEventData eventData)
|
||||
@@ -252,6 +269,12 @@ namespace BrewMonster
|
||||
else
|
||||
detailedItem.GetDetailDataFromLocal();
|
||||
|
||||
if (m_SecondInvSlot >= 0)
|
||||
{
|
||||
var previosBtn = FindInventoryButtonBySlot(m_SecondInvSlot);
|
||||
SetInventorySlotGray(previosBtn, false);
|
||||
}
|
||||
|
||||
m_SelectedMaterial?.Freeze(false);
|
||||
m_SelectedMaterial = detailedItem;
|
||||
m_SelectedMaterial?.Freeze(true);
|
||||
@@ -297,8 +320,6 @@ namespace BrewMonster
|
||||
// a_sprintf(szText, _AL("%d"), nAmount);
|
||||
// m_pTxtGold->SetText(szText);
|
||||
// }
|
||||
|
||||
Debug.Log($"[Install] Material: {detailedItem.m_tid} from slot {slotIndex}");
|
||||
}
|
||||
|
||||
private void SetInventorySlotGray(Button btn, bool gray)
|
||||
@@ -343,23 +364,19 @@ namespace BrewMonster
|
||||
private void ClearEquipSlot()
|
||||
{
|
||||
m_SelectedEquip?.Freeze(false);
|
||||
m_SelectedMaterial?.Freeze(false);
|
||||
m_SelectedEquip = null;
|
||||
m_FirstInvSlot = -1;
|
||||
m_TxtFirstName.text = "___";
|
||||
ClearSlotIcon(m_SlotFirstParent);
|
||||
|
||||
Debug.Log("[Install] Equipment slot cleared");
|
||||
}
|
||||
|
||||
private void ClearMaterialSlot()
|
||||
{
|
||||
m_SelectedMaterial?.Freeze(false);
|
||||
m_SelectedMaterial = null;
|
||||
m_SecondInvSlot = -1;
|
||||
m_TxtSecondName.text = "___";
|
||||
ClearSlotIcon(m_SlotSecondlParent);
|
||||
|
||||
Debug.Log("[Install] Material slot cleared");
|
||||
}
|
||||
|
||||
private void ClearSlotIcon(Transform slot)
|
||||
@@ -385,8 +402,8 @@ namespace BrewMonster
|
||||
if( nMoney > pHost.GetMoneyAmount() )
|
||||
{
|
||||
message = GetGameUIMan().GetStringFromTable(226);
|
||||
Debug.LogError(message);
|
||||
// GetGameUIMan()->MessageBox("", GetGameUIMan().GetStringFromTable(226), MB_OK,
|
||||
CECUIManager.Instance.ShowMessageBox("", message);
|
||||
// GetGameUIMan().GetDialog("")
|
||||
// A3DCOLORRGBA(255, 255, 255, 160), &pMsgBox);
|
||||
// pMsgBox->SetLife(3);
|
||||
return;
|
||||
@@ -396,7 +413,7 @@ namespace BrewMonster
|
||||
if( !pIvtrA.IsEquipment() )
|
||||
{
|
||||
message = GetGameUIMan().GetStringFromTable(223);
|
||||
Debug.LogError(message);
|
||||
CECUIManager.Instance.ShowMessageBox("", message);
|
||||
// GetGameUIMan().MessageBox("", GetGameUIMan().GetStringFromTable(223), MB_OK,
|
||||
// A3DCOLORRGBA(255, 255, 255, 160), &pMsgBox);
|
||||
// pMsgBox.SetLife(3);
|
||||
@@ -410,7 +427,7 @@ namespace BrewMonster
|
||||
if( pEquipA.GetEmptyHoleNum() <= 0 )
|
||||
{
|
||||
message = GetGameUIMan().GetStringFromTable(224);
|
||||
Debug.LogError(message);
|
||||
CECUIManager.Instance.ShowMessageBox("", message);
|
||||
// GetGameUIMan().MessageBox("", GetGameUIMan()->GetStringFromTable(224), MB_OK,
|
||||
// A3DCOLORRGBA(255, 255, 255, 160), &pMsgBox);
|
||||
// pMsgBox.SetLife(3);
|
||||
@@ -421,7 +438,7 @@ namespace BrewMonster
|
||||
if(pIvtrB == null || !pIvtrB.IsEmbeddable() )
|
||||
{
|
||||
message = GetGameUIMan().GetStringFromTable(225);
|
||||
Debug.LogError(message);
|
||||
CECUIManager.Instance.ShowMessageBox("", message);
|
||||
// GetGameUIMan().MessageBox("", GetGameUIMan().GetStringFromTable(225), MB_OK,
|
||||
// A3DCOLORRGBA(255, 255, 255, 160), &pMsgBox);
|
||||
// pMsgBox.SetLife(3);
|
||||
@@ -436,7 +453,7 @@ namespace BrewMonster
|
||||
switch( pEquipA.GetClassID() )
|
||||
{
|
||||
case (int)EC_IvtrEquip.EQUIP_CLASS_ID.ICID_WEAPON:
|
||||
nEquipLevel = ((EC_IvtrWeapon)pEquipA).GetDBEssence().level;
|
||||
nEquipLevel = ((CECIvtrWeapon)pEquipA).GetDBEssence().level;
|
||||
break;
|
||||
case (int)EC_IvtrEquip.EQUIP_CLASS_ID.ICID_ARMOR:
|
||||
nEquipLevel = ((EC_IvtrArmor)pEquipA).GetDBEssence().level;
|
||||
@@ -449,7 +466,7 @@ namespace BrewMonster
|
||||
if( nStoneLevel > nEquipLevel )
|
||||
{
|
||||
message = GetGameUIMan().GetStringFromTable(300);
|
||||
Debug.LogError(message);
|
||||
CECUIManager.Instance.ShowMessageBox("", message);
|
||||
// GetGameUIMan().MessageBox("", GetGameUIMan().GetStringFromTable(300), MB_OK,
|
||||
// A3DCOLORRGBA(255, 255, 255, 160), &pMsgBox);
|
||||
// pMsgBox.SetLife(3);
|
||||
@@ -464,7 +481,7 @@ namespace BrewMonster
|
||||
pHost.GetPack(InventoryConst.IVTRTYPE_PACK).UnfreezeAllItems();
|
||||
|
||||
message = GetGameUIMan().GetStringFromTable(228);
|
||||
Debug.LogError(message);
|
||||
CECUIManager.Instance.ShowMessageBox("", message);
|
||||
// GetGameUIMan().MessageBox("", GetGameUIMan().GetStringFromTable(228),
|
||||
// MB_OK, A3DCOLORRGBA(255, 255, 255, 160), &pMsgBox);
|
||||
// pMsgBox.SetLife(3);
|
||||
@@ -484,5 +501,41 @@ namespace BrewMonster
|
||||
// MB_OKCANCEL, A3DCOLORRGBA(255, 255, 255, 160));
|
||||
// }
|
||||
}
|
||||
private void OnClickedCancel()
|
||||
{
|
||||
Show(false);
|
||||
}
|
||||
|
||||
public void ResetInstallUI()
|
||||
{
|
||||
RestoreInventoryColors();
|
||||
|
||||
m_SelectedEquip = null;
|
||||
m_SelectedMaterial = null;
|
||||
|
||||
m_FirstInvSlot = -1;
|
||||
m_SecondInvSlot = -1;
|
||||
|
||||
m_TxtFirstName.text = "___";
|
||||
m_TxtSecondName.text = "___";
|
||||
m_TxtMoney.text = "0";
|
||||
m_install_price = -1;
|
||||
|
||||
ClearSlotIcon(m_SlotFirstParent);
|
||||
ClearSlotIcon(m_SlotSecondlParent);
|
||||
|
||||
gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
private void CheckHidePanel(Vector2 screenPos)
|
||||
{
|
||||
if (!RectTransformUtility.RectangleContainsScreenPoint(
|
||||
itemInventoryRoot as RectTransform, screenPos,
|
||||
Camera.main))
|
||||
{
|
||||
if(itemInventoryRoot!=null)
|
||||
itemInventoryRoot.gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3406,27 +3406,9 @@ namespace BrewMonster.UI
|
||||
if (pCurNPCEssence.HasValue)
|
||||
{
|
||||
uint npcID = pCurNPCEssence.Value.id;
|
||||
DlgInstall dlgInstall = FindFirstObjectByType<DlgInstall>();
|
||||
if (dlgInstall == null)
|
||||
{
|
||||
CECGameUIMan gameUIMan = GetGameUIMan();
|
||||
DialogScriptTableObject dialogResource = gameUIMan.GetDialogResource();
|
||||
Canvas canvas = gameUIMan.GetCanvas();
|
||||
|
||||
if(dialogResource != null && canvas != null)
|
||||
{
|
||||
GameObject ob = dialogResource.GetPrefabDialog("Win_Enchase");
|
||||
if (ob != null)
|
||||
{
|
||||
dlgInstall = GameObject.Instantiate(ob, canvas.transform).GetComponent<DlgInstall>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(dlgInstall != null)
|
||||
{
|
||||
dlgInstall.OpenInstall(npcID);
|
||||
}
|
||||
|
||||
var dlgInstall =GetGameUIMan().GetDialog("Win_Enchase");
|
||||
dlgInstall.Show(true);
|
||||
}
|
||||
//pShow1 = m_pAUIManager.GetDialog("Win_Enchase");
|
||||
//pShow2 = m_pAUIManager.GetDialog("Win_Inventory");
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6d97873e24020e642b7c6f6b79ea8c2c
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,15 @@
|
||||
using BrewMonster.UI;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BrewMonster
|
||||
{
|
||||
public class CDlgTaskAction : AUIDialog
|
||||
{
|
||||
public void OnShowDialog()
|
||||
{
|
||||
uint param = GetData();
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a5f25e21a0550df41af0c2e57639635a
|
||||
@@ -13,8 +13,8 @@ namespace BrewMonster.Assets.PerfectWorld.Scripts.UI.GamePlay
|
||||
{
|
||||
public class AUIImagePicture : MonoBehaviour
|
||||
{
|
||||
CECShortcut pSC;
|
||||
[Header("AUIImagePicture")]
|
||||
[SerializeField] CECShortcut pSC;
|
||||
[SerializeField] Button skillbutton;
|
||||
[SerializeField] protected Image skillImage;
|
||||
[SerializeField] GameObject borderImage;
|
||||
@@ -32,14 +32,16 @@ namespace BrewMonster.Assets.PerfectWorld.Scripts.UI.GamePlay
|
||||
if (skillbutton == null)
|
||||
{
|
||||
Debug.LogError("Skill Button is not assigned in AUIImagePicture");
|
||||
return;
|
||||
}
|
||||
skillbutton.onClick.AddListener(Execute);
|
||||
m_pParent = GetComponentInParent<AUIDialog>();
|
||||
}
|
||||
public void SetDataPtr(CECShortcut pvData, string strName)
|
||||
public void SetDataPtr(CECShortcut pvData, string strName = null)
|
||||
{
|
||||
pSC = pvData;
|
||||
}
|
||||
public CECShortcut GetDataPtr() => pSC;
|
||||
public void Execute()
|
||||
{
|
||||
if (pSC != null)
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
//#define Applyforalicense
|
||||
|
||||
using BrewMonster.Assets.PerfectWorld.Scripts.UI.GamePlay;
|
||||
using BrewMonster.Network;
|
||||
using BrewMonster.Scripts;
|
||||
@@ -25,16 +27,17 @@ namespace BrewMonster
|
||||
/// Apply for a license remove later
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
|
||||
|
||||
|
||||
public bool UpdateShortcuts()
|
||||
{
|
||||
CECShortcut pSC;
|
||||
Image skillImage;
|
||||
CECSCSkill pSCSkill;
|
||||
int iIconFile, nMax;
|
||||
AUIImagePicture pCell;
|
||||
CECSkill pSkill = new CECSkill(-1, -1);
|
||||
AUIClockIcon pClock;
|
||||
|
||||
int iIconFile, nMax = 0;
|
||||
|
||||
int nCurPanel9 = GetCurPanel1();
|
||||
int nCurPanel8 = GetCurPanel2();
|
||||
@@ -44,7 +47,6 @@ namespace BrewMonster
|
||||
var a_pSCS = new List<CECShortcutSet>();
|
||||
var a_pszPanel = new List<string>();
|
||||
GetQuickBarNameAndSC(pHost, a_pszPanel, a_pSCS, nCurPanel9, nCurPanel8);
|
||||
|
||||
if (a_pSCS == null || a_pSCS.Count < 2)
|
||||
return false;
|
||||
|
||||
@@ -53,12 +55,28 @@ namespace BrewMonster
|
||||
if (a_pSCS[i] == null)
|
||||
continue;
|
||||
|
||||
/*CDlgQuickBar* pQuickBar = dynamic_cast<CDlgQuickBar*>(GetGameUIMan()->GetDialog(a_pszPanel[i]));
|
||||
if (!pQuickBar || !pQuickBar->IsShow()) continue;*/
|
||||
//*//*CDlgQuickBar* pQuickBar = dynamic_cast<CDlgQuickBar*>(GetGameUIMan()->GetDialog(a_pszPanel[i]));
|
||||
//if (!pQuickBar || !pQuickBar->IsShow()) continue;*//*
|
||||
#if LICENSE_VERSION
|
||||
|
||||
int slotIndex = 0;
|
||||
#endif
|
||||
|
||||
#if LICENSE_VERSION
|
||||
|
||||
for (int j = 0; j < a_pSCS.Count; j++)
|
||||
{
|
||||
#else
|
||||
int nSlots = Mathf.Min(a_pSCS[i].GetShortcutNum(), AUIImagePictureList.Count);
|
||||
for (int j = 0; j < nSlots; j++)
|
||||
{
|
||||
{
|
||||
#endif
|
||||
#if LICENSE_VERSION
|
||||
|
||||
pCell = AUIImagePictureList[slotIndex];
|
||||
#else
|
||||
pCell = AUIImagePictureList[j];
|
||||
#endif
|
||||
pSC = a_pSCS[i].GetShortcut(j);
|
||||
pClock = pCell.GetClockIcon();
|
||||
pClock.SetProgressRange(0, 1);
|
||||
@@ -67,13 +85,12 @@ namespace BrewMonster
|
||||
{
|
||||
if (pSC.GetType() == (int)CECShortcut.ShortcutType.SCT_SKILL)
|
||||
{
|
||||
iIconFile = (int)EC_GAMEUI_ICONS.ICONS_SKILL;
|
||||
pSCSkill = (CECSCSkill)pSC;
|
||||
pSkill = pSCSkill.GetSkill();
|
||||
if (false/*m_bDelGoblinSkillSC && GNET::ElementSkill::IsGoblinSkill(pSkill->GetSkillID())*/)
|
||||
{
|
||||
/* a_pSCS[i]->SetShortcut(j, NULL);
|
||||
pSC = NULL;*/
|
||||
/* a_pSCS[i]->SetShortcut(j, NULL);
|
||||
pSC = NULL;*/
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -81,14 +98,14 @@ namespace BrewMonster
|
||||
{
|
||||
if (ElementSkill.IsGoblinSkill((uint)pSkill.GetSkillID()))
|
||||
{
|
||||
/* if (pHostGoblin && !pHostGoblin->CheckSkillCastCondition(pSkill))
|
||||
{
|
||||
pCell->SetColor(A3DCOLORRGB(255, 255, 255));
|
||||
}
|
||||
else
|
||||
{
|
||||
pCell->SetColor(A3DCOLORRGB(128, 128, 128));
|
||||
}*/
|
||||
/* if (pHostGoblin && !pHostGoblin->CheckSkillCastCondition(pSkill))
|
||||
{
|
||||
pCell->SetColor(A3DCOLORRGB(255, 255, 255));
|
||||
}
|
||||
else
|
||||
{
|
||||
pCell->SetColor(A3DCOLORRGB(128, 128, 128));
|
||||
}*/
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -102,8 +119,8 @@ namespace BrewMonster
|
||||
}
|
||||
}
|
||||
}
|
||||
/* else
|
||||
pClock.SetColor(A3DCOLORRGBA(0, 0, 0, 128));*/
|
||||
/*else
|
||||
pClock.SetColor(A3DCOLORRGBA(0, 0, 0, 128));*/
|
||||
if (pSkill != null && (pSkill.GetCoolingTime() > 0 ||
|
||||
pHost.GetPrepSkill() == pSkill))
|
||||
{
|
||||
@@ -199,7 +216,7 @@ namespace BrewMonster
|
||||
pClock->SetColor(A3DCOLORRGBA(0, 0, 0, 128));
|
||||
}
|
||||
}*/
|
||||
else if(pSC.GetType() == (int)CECShortcut.ShortcutType.SCT_ITEM)
|
||||
else if (pSC.GetType() == (int)CECShortcut.ShortcutType.SCT_ITEM)
|
||||
{
|
||||
iIconFile = (int)EC_GAMEUI_ICONS.ICONS_INVENTORY;
|
||||
pCell.SetColor(new Color(1f, 1f, 1f));
|
||||
@@ -211,7 +228,7 @@ namespace BrewMonster
|
||||
{
|
||||
int maxNullable = -1;
|
||||
int coolTime = pItem.GetCoolTime(out maxNullable);
|
||||
nMax = maxNullable > 0 ? maxNullable: 0;
|
||||
nMax = maxNullable > 0 ? maxNullable : 0;
|
||||
|
||||
if (coolTime > 0)
|
||||
{
|
||||
@@ -266,7 +283,7 @@ namespace BrewMonster
|
||||
// GetGameUIMan().SetCover(pCell, petIcon, EC_GAMEUI_ICONS.ICONS_INVENTORY);
|
||||
// }
|
||||
//}
|
||||
else if(pSC.GetType() == (int)CECShortcut.ShortcutType.SCT_AUTOFASHION)
|
||||
else if (pSC.GetType() == (int)CECShortcut.ShortcutType.SCT_AUTOFASHION)
|
||||
{
|
||||
iIconFile = (int)EC_GAMEUI_ICONS.ICONS_SUITE;
|
||||
|
||||
@@ -320,218 +337,22 @@ namespace BrewMonster
|
||||
|
||||
if (pSC != null)
|
||||
{
|
||||
pCell.SetDataPtr(pSC, "ptr_CECShortcut");
|
||||
#if LICENSE_VERSION
|
||||
slotIndex++;
|
||||
#endif
|
||||
if (pCell.GetDataPtr() == pSC)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
pCell.SetDataPtr(pSC);
|
||||
if (pSC.GetType() == (int)CECShortcut.ShortcutType.SCT_SKILLGRP)
|
||||
{
|
||||
/* EC_VIDEO_SETTING setting = GetGame()->GetConfigs()->GetVideoSettings();
|
||||
pCell->SetCover(GetGameUIMan()->m_pA2DSpriteIcons[CECGameUIMan::ICONS_SKILLGRP],
|
||||
setting.comboSkill[((CECSCSkillGrp*)pSC)->GetGroupIndex()].nIcon + 1);*/
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pSkill != null)
|
||||
{
|
||||
//BMLogger.Log("HoangDev: QuickBar Set Skill Icon: " + (uint)pSkill.GetSkillID() + " : " + ElementSkill.GetIcon((uint)pSkill.GetSkillID()));
|
||||
var nameskill = ElementSkill.GetIcon((uint)pSkill.GetSkillID());
|
||||
GetGameUIMan().SetCover(pCell, nameskill, EC_GAMEUI_ICONS.ICONS_SKILL);
|
||||
}
|
||||
/*af_GetFileTitle(pSC->GetIconFile(), strFile);
|
||||
strFile.MakeLower();
|
||||
pCell->SetCover(GetGameUIMan()->m_pA2DSpriteIcons[iIconFile],
|
||||
GetGameUIMan()->m_IconMap[iIconFile][strFile]);*/
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* pCell->SetCover(NULL, -1);
|
||||
pCell->SetText(_AL(""));
|
||||
pCell->SetDataPtr(NULL);
|
||||
pCell->SetColor(A3DCOLORRGB(255, 255, 255));*/
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/* public bool UpdateShortcuts()
|
||||
{
|
||||
CECShortcut pSC;
|
||||
Image skillImage;
|
||||
CECSCSkill pSCSkill;
|
||||
int iIconFile, nMax;
|
||||
AUIImagePicture pCell;
|
||||
CECSkill pSkill = new CECSkill(-1, -1);
|
||||
AUIClockIcon pClock;
|
||||
|
||||
|
||||
int nCurPanel9 = GetCurPanel1();
|
||||
int nCurPanel8 = GetCurPanel2();
|
||||
|
||||
CECHostPlayer pHost = EC_Game.GetGameRun().GetHostPlayer();
|
||||
if (pHost == null) return false;
|
||||
var a_pSCS = new List<CECShortcutSet>();
|
||||
var a_pszPanel = new List<string>();
|
||||
GetQuickBarNameAndSC(pHost, a_pszPanel, a_pSCS, nCurPanel9, nCurPanel8);
|
||||
|
||||
for (int i = 0; i <= 1*//*(int)a_pSCS.Count*//*; i++)
|
||||
{
|
||||
if (a_pSCS[i] == null)
|
||||
continue;
|
||||
|
||||
*//*CDlgQuickBar* pQuickBar = dynamic_cast<CDlgQuickBar*>(GetGameUIMan()->GetDialog(a_pszPanel[i]));
|
||||
if (!pQuickBar || !pQuickBar->IsShow()) continue;*//*
|
||||
|
||||
for (int j = 0; j < AUIImagePictureList.Count; j++)
|
||||
{
|
||||
pCell = AUIImagePictureList[j];
|
||||
pSC = a_pSCS[i].GetShortcut(j);
|
||||
pClock = pCell.GetClockIcon();
|
||||
pClock.SetProgressRange(0, 1);
|
||||
pClock.SetProgressPos(1);
|
||||
if (pSC != null)
|
||||
{
|
||||
if (pSC.GetType() == (int)CECShortcut.ShortcutType.SCT_SKILL)
|
||||
{
|
||||
iIconFile = (int)EC_GAMEUI_ICONS.ICONS_SKILL;
|
||||
pSCSkill = (CECSCSkill)pSC;
|
||||
pSkill = pSCSkill.GetSkill();
|
||||
if (false*//*m_bDelGoblinSkillSC && GNET::ElementSkill::IsGoblinSkill(pSkill->GetSkillID())*//*)
|
||||
{
|
||||
*//* a_pSCS[i]->SetShortcut(j, NULL);
|
||||
pSC = NULL;*//*
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pSkill != null && pSkill.ReadyToCast() && pHost.GetPrepSkill() != pSkill)
|
||||
{
|
||||
if (ElementSkill.IsGoblinSkill((uint)pSkill.GetSkillID()))
|
||||
{
|
||||
*//* if (pHostGoblin && !pHostGoblin->CheckSkillCastCondition(pSkill))
|
||||
{
|
||||
pCell->SetColor(A3DCOLORRGB(255, 255, 255));
|
||||
}
|
||||
else
|
||||
{
|
||||
pCell->SetColor(A3DCOLORRGB(128, 128, 128));
|
||||
}*//*
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pHost.CheckSkillCastCondition(pSkill) == 0)
|
||||
{
|
||||
//pCell.SetColor(A3DCOLORRGB(255, 255, 255));
|
||||
}
|
||||
else
|
||||
{
|
||||
//pCell.SetColor(A3DCOLORRGB(128, 128, 128));
|
||||
}
|
||||
}
|
||||
}
|
||||
*//* else
|
||||
pClock.SetColor(A3DCOLORRGBA(0, 0, 0, 128));*//*
|
||||
if (pSkill != null && (pSkill.GetCoolingTime() > 0 ||
|
||||
pHost.GetPrepSkill() == pSkill))
|
||||
{
|
||||
pClock.SetProgressRange(0, pSkill.GetCoolingTime());
|
||||
if (pHost.GetPrepSkill() == pSkill)
|
||||
{
|
||||
pClock.SetProgressPos(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
pClock.SetProgressPos(pSkill.GetCoolingTime() - pSkill.GetCoolingCnt());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*//*else if (pSC->GetType() == CECShortcut::SCT_ITEM)
|
||||
{
|
||||
iIconFile = CECGameUIMan::ICONS_INVENTORY;
|
||||
pCell->SetColor(A3DCOLORRGB(255, 255, 255));
|
||||
pSCItem = (CECSCItem*)pSC;
|
||||
pIvtr = GetHostPlayer()->GetPack(pSCItem->GetInventory());
|
||||
pItem = pIvtr->GetItem(pSCItem->GetIvtrSlot());
|
||||
if (pItem && pItem->GetCoolTime(&nMax) > 0)
|
||||
{
|
||||
pClock->SetProgressRange(0, nMax);
|
||||
pClock->SetProgressPos(nMax - pItem->GetCoolTime());
|
||||
pClock->SetColor(A3DCOLORRGBA(0, 0, 0, 128));
|
||||
}
|
||||
if (pSCItem->GetInventory() == IVTRTYPE_EQUIPPACK)
|
||||
pCell->SetColor(A3DCOLORRGBA(128, 128, 255, 128));
|
||||
}
|
||||
else if (pSC->GetType() == CECShortcut::SCT_PET)
|
||||
{
|
||||
pSCPet = (CECSCPet*)pSC;
|
||||
CECPetData* pPet = pPetCorral->GetPetData(pSCPet->GetPetIndex());
|
||||
iIconFile = CECGameUIMan::ICONS_INVENTORY;
|
||||
pCell->SetColor(A3DCOLORRGB(255, 255, 255));
|
||||
if (pPet)
|
||||
{
|
||||
// dead combat pet
|
||||
if ((pPet->GetClass() == GP_PET_CLASS_COMBAT || pPet->GetClass() == GP_PET_CLASS_EVOLUTION) && pPet->GetHPFactor() == 0.0f)
|
||||
{
|
||||
pCell->SetColor(A3DCOLORRGB(128, 128, 128));
|
||||
}
|
||||
// current active pet
|
||||
else if (pSCPet->IsActivePet())
|
||||
{
|
||||
pCell->SetColor(A3DCOLORRGB(255, 255, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (pSC->GetType() == CECShortcut::SCT_AUTOFASHION)
|
||||
{
|
||||
iIconFile = CECGameUIMan::ICONS_SUITE;
|
||||
fashionCoolTime = pHost->GetCoolTime(GP_CT_EQUIP_FASHION_ITEM, &fashionCoolTimeMax);
|
||||
pCell->SetColor(A3DCOLORRGB(255, 255, 255));
|
||||
if (fashionCoolTimeMax > 0)
|
||||
{
|
||||
pClock->SetProgressRange(0, fashionCoolTimeMax);
|
||||
pClock->SetProgressPos(fashionCoolTimeMax - fashionCoolTime);
|
||||
pClock->SetColor(A3DCOLORRGBA(0, 0, 0, 175));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
iIconFile = CECGameUIMan::ICONS_ACTION;
|
||||
if (pSC->GetType() == CECShortcut::SCT_COMMAND)
|
||||
{
|
||||
CECSCCommand* pCommandSC = (CECSCCommand*)pSC;
|
||||
if (GetHostPlayer()->IsInvisible())
|
||||
{
|
||||
if (pCommandSC->GetCommandID() == CECSCCommand::CMD_STARTTRADE ||
|
||||
pCommandSC->GetCommandID() == CECSCCommand::CMD_SELLBOOTH ||
|
||||
pCommandSC->GetCommandID() == CECSCCommand::CMD_BINDBUDDY)
|
||||
{
|
||||
pCell->SetColor(A3DCOLORRGB(128, 128, 128));
|
||||
}
|
||||
else
|
||||
{
|
||||
pCell->SetColor(A3DCOLORRGB(255, 255, 255));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pCell->SetColor(A3DCOLORRGB(255, 255, 255));
|
||||
}
|
||||
}
|
||||
|
||||
if (pSC->GetCoolTime(&nMax) > 0)
|
||||
{
|
||||
pClock->SetProgressRange(0, nMax);
|
||||
pClock->SetProgressPos(nMax - pSC->GetCoolTime());
|
||||
pClock->SetColor(A3DCOLORRGBA(0, 0, 0, 128));
|
||||
}
|
||||
}*//*
|
||||
if (pSC != null)
|
||||
{
|
||||
pCell.SetDataPtr(pSC, "ptr_CECShortcut");
|
||||
if (pSC.GetType() == (int)CECShortcut.ShortcutType.SCT_SKILLGRP)
|
||||
{
|
||||
*//* EC_VIDEO_SETTING setting = GetGame()->GetConfigs()->GetVideoSettings();
|
||||
pCell->SetCover(GetGameUIMan()->m_pA2DSpriteIcons[CECGameUIMan::ICONS_SKILLGRP],
|
||||
setting.comboSkill[((CECSCSkillGrp*)pSC)->GetGroupIndex()].nIcon + 1);*//*
|
||||
EC_VIDEO_SETTING setting = EC_Game.GetConfigs().GetVideoSettings();
|
||||
/* pCell.SetCover(GetGameUIMan()->m_pA2DSpriteIcons[CECGameUIMan::ICONS_SKILLGRP],
|
||||
setting.comboSkill[((CECSCSkillGrp)pSC).GetGroupIndex()].nIcon + 1);
|
||||
setting.comboSkill[((CECSCSkillGrp)pSC).GetGroupIndex()].nIcon + 1;*/
|
||||
// fix later now haven't skill group icon yet
|
||||
GetGameUIMan().SetCover(pCell, "unknown", EC_GAMEUI_ICONS.ICONS_SKILL);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -542,24 +363,24 @@ namespace BrewMonster
|
||||
var nameskill = ElementSkill.GetIcon((uint)pSkill.GetSkillID());
|
||||
GetGameUIMan().SetCover(pCell, nameskill, EC_GAMEUI_ICONS.ICONS_SKILL);
|
||||
}
|
||||
*//*af_GetFileTitle(pSC->GetIconFile(), strFile);
|
||||
strFile.MakeLower();
|
||||
pCell->SetCover(GetGameUIMan()->m_pA2DSpriteIcons[iIconFile],
|
||||
GetGameUIMan()->m_IconMap[iIconFile][strFile]);*//*
|
||||
/* af_GetFileTitle(pSC->GetIconFile(), strFile);
|
||||
strFile.MakeLower();
|
||||
pCell->SetCover(GetGameUIMan()->m_pA2DSpriteIcons[iIconFile],
|
||||
GetGameUIMan()->m_IconMap[iIconFile][strFile]); */
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*//* pCell->SetCover(NULL, -1);
|
||||
pCell->SetText(_AL(""));
|
||||
/* pCell->SetCover(NULL, -1);
|
||||
pCell->SetText(_AL(""));
|
||||
pCell->SetDataPtr(NULL);
|
||||
pCell->SetColor(A3DCOLORRGB(255, 255, 255));*//*
|
||||
pCell->SetColor(A3DCOLORRGB(255, 255, 255)); */
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}*/
|
||||
}
|
||||
private void GetQuickBarNameAndSC(CECHostPlayer pHost, List<string> pszPanel, List<CECShortcutSet> pSCS, int panel9, int panel8)
|
||||
{
|
||||
string dlgName;
|
||||
@@ -612,11 +433,11 @@ namespace BrewMonster
|
||||
pszPanel.Add(dlgName);
|
||||
}
|
||||
}
|
||||
private int GetCurPanel1()
|
||||
public int GetCurPanel1()
|
||||
{
|
||||
return m_nCurPanel1;
|
||||
}
|
||||
private int GetCurPanel2()
|
||||
public int GetCurPanel2()
|
||||
{
|
||||
return m_nCurPanel2;
|
||||
}
|
||||
|
||||
@@ -10,7 +10,9 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Unity.VisualScripting;
|
||||
using UnityEngine;
|
||||
using static UnityEngine.Rendering.DebugUI;
|
||||
|
||||
namespace BrewMonster.UI
|
||||
{
|
||||
@@ -23,6 +25,7 @@ namespace BrewMonster.UI
|
||||
private Dictionary<byte, (string, Sprite[])> m_IconMap;
|
||||
|
||||
private const string SKILL_ICONLIST_NAME = "iconlist_skill_multisprite";
|
||||
private const string ACTION_ICONLIST_NAME = "ActionIcon/iconlist_action_multisprite";
|
||||
|
||||
public static bool TALKPROC_IS_TERMINAL(uint id)
|
||||
{
|
||||
@@ -60,7 +63,24 @@ namespace BrewMonster.UI
|
||||
}
|
||||
m_pDlgNPC.PopupNPCDialog(pTalk);
|
||||
}
|
||||
|
||||
public CECShortcutSet GetSCSByDlg(int indexPanel)
|
||||
{
|
||||
CECHostPlayer pHost = CECGameRun.Instance.GetHostPlayer();
|
||||
CDlgQuickBar cDlgQuickBar = CECUIManager.Instance.GetCDlgQuickBar();
|
||||
CECShortcutSet pSCS = null;
|
||||
int index = (0);
|
||||
if (indexPanel == 1)
|
||||
{
|
||||
int panel = (index < 0 ? cDlgQuickBar.GetCurPanel1() : index) - 1;
|
||||
pSCS = pHost.GetShortcutSet1(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
int panel = (index < 0 ? cDlgQuickBar.GetCurPanel2() : index) - 1;
|
||||
pSCS = pHost.GetShortcutSet2(panel);
|
||||
}
|
||||
return pSCS;
|
||||
}
|
||||
// 弹出任务完成对话框(到达/离开地点等触发) // Popup task-finish dialog (reach/leave site, etc.)
|
||||
// C++: pTask->PopupTaskFinishDialog(taskId, &awardTalk); then OnUIDialogEnd() notifies server.
|
||||
public bool PopupTaskFinishDialog(uint taskId, talk_proc pTalk)
|
||||
@@ -146,9 +166,9 @@ namespace BrewMonster.UI
|
||||
m_pDlgTask = GetDialog(CECUIHelper.DlgTaskName).GetComponent<DlgTask>();
|
||||
m_pDlgTask.Show(false);
|
||||
|
||||
m_IconMap[(byte)EC_GAMEUI_ICONS.ICONS_SKILL] =("iconlist_skill_multisprite", Resources.LoadAll<Sprite>("iconlist_skill_multisprite"));
|
||||
m_IconMap[(byte)EC_GAMEUI_ICONS.ICONS_SKILL] = (SKILL_ICONLIST_NAME, Resources.LoadAll<Sprite>(SKILL_ICONLIST_NAME));
|
||||
m_IconMap[(byte)EC_GAMEUI_ICONS.ICONS_ACTION] = (ACTION_ICONLIST_NAME, Resources.LoadAll<Sprite>(ACTION_ICONLIST_NAME));
|
||||
}
|
||||
|
||||
public void SetCover(AUIImagePicture pImgPic, string nameImage, EC_GAMEUI_ICONS iCONS_SKILL)
|
||||
{
|
||||
pImgPic.SetImage(m_IconMap[(byte)iCONS_SKILL].Item2.FirstOrDefault(s => s.name == nameImage));
|
||||
@@ -176,7 +196,6 @@ namespace BrewMonster.UI
|
||||
}
|
||||
}
|
||||
public enum EC_GAMEUI_ICONS : byte
|
||||
|
||||
{
|
||||
ICONS_ACTION = 0,
|
||||
ICONS_SKILL,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using BrewMonster.Assets.PerfectWorld.Scripts.UI.GamePlay;
|
||||
using BrewMonster.Scripts.Skills;
|
||||
using BrewMonster.UI;
|
||||
using CSNetwork.GPDataType;
|
||||
@@ -18,6 +19,7 @@ namespace BrewMonster
|
||||
[SerializeField] private Image skillIcon;
|
||||
[SerializeField] private GameObject m_highlight;
|
||||
[SerializeField] private Button m_upgradeBtn;
|
||||
[SerializeField] private AUIImagePicture m_skillIconImgPic;
|
||||
|
||||
private int m_skillID;
|
||||
private int m_curLevel;
|
||||
@@ -135,20 +137,36 @@ namespace BrewMonster
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
string skillDsc;
|
||||
int reqLevel;
|
||||
int reqRealmLevel;
|
||||
if (enumSkillLearnedState.SKILL_NOT_LEARNED == learnedState)
|
||||
{
|
||||
skillIcon.color = Color.gray;
|
||||
/* skillDsc = model.GetSkillDescription(m_skillID, 1);
|
||||
reqLevel = GNET::ElementSkill::GetRequiredLevel(m_skillID, 1);
|
||||
reqRealmLevel = GNET::ElementSkill::GetRequiredRealmLevel(m_skillID, 1);*/
|
||||
skillDsc = model.GetSkillDescription(m_skillID, 1);
|
||||
reqLevel = ElementSkill.GetRequiredLevel((uint)m_skillID, 1);
|
||||
reqRealmLevel = ElementSkill.GetRequiredRealmLevel((uint)m_skillID, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
skillIcon.color = Color.white;
|
||||
/* skillDsc = model.GetSkillDescription(m_skillID, m_curLevel);
|
||||
reqLevel = GNET::ElementSkill::GetRequiredLevel(m_skillID, m_curLevel);
|
||||
reqRealmLevel = GNET::ElementSkill::GetRequiredRealmLevel(m_skillID, m_curLevel);*/
|
||||
skillDsc = model.GetSkillDescription(m_skillID, m_curLevel);
|
||||
reqLevel = ElementSkill.GetRequiredLevel((uint)m_skillID, m_curLevel);
|
||||
reqRealmLevel = ElementSkill.GetRequiredRealmLevel((uint)m_skillID, m_curLevel);
|
||||
}
|
||||
if (reqLevel == 0)
|
||||
{
|
||||
reqLevel = 1;
|
||||
}
|
||||
skillDsc += GPDataTypeHelper.ReplacePercentD(GetStringFromTable(11328), reqLevel);
|
||||
if (reqRealmLevel != 0)
|
||||
{
|
||||
skillDsc += GetStringFromTable(11401);
|
||||
skillDsc += GetGameUIMan().GetRealmName(reqRealmLevel);
|
||||
}
|
||||
|
||||
//m_skillIconImgPic.SetHint(skillDsc);
|
||||
|
||||
string skillName = model.GetSkillName(m_skillID);
|
||||
/* if (model.IsPassiveSkill(m_skillID))
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BrewMonster.Network;
|
||||
using BrewMonster.Scripts;
|
||||
using CSNetwork.Protocols;
|
||||
using CSNetwork.Protocols.RPCData;
|
||||
using TMPro;
|
||||
@@ -34,42 +35,23 @@ namespace BrewMonster.UI
|
||||
bool isDoneNPCRender = false;
|
||||
private SynchronizationContext context;
|
||||
public AudioClip loginBGM;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
var tech3CWrapper = Tech3CSDKWrapper.Instance;
|
||||
}
|
||||
|
||||
void Start()
|
||||
{
|
||||
AudioManager.Instance.PlayBGM(loginBGM, 1.5f);
|
||||
_loginButton.onClick.AddListener(OnLoginButtonClicked);
|
||||
context = SynchronizationContext.Current;
|
||||
|
||||
var world = SceneManager.GetSceneByName("a61");
|
||||
if (!world.IsValid() || !world.isLoaded)
|
||||
{
|
||||
SceneManager.LoadSceneAsync("a61", LoadSceneMode.Additive);
|
||||
}
|
||||
_usernameInputField.text = PlayerPrefs.GetString("username", "");
|
||||
_passwordInputField.text = PlayerPrefs.GetString("password", "");
|
||||
|
||||
ApplyLoginEntry(BrewMonster.Network.LogoutFlowState.ConsumeNextLoginEntry());
|
||||
}
|
||||
|
||||
|
||||
public void ApplyLoginEntry(BrewMonster.Network.LogoutFlowState.LoginEntryTarget entry)
|
||||
{
|
||||
_loginInProgress = false;
|
||||
if (_loginButton != null) _loginButton.interactable = true;
|
||||
|
||||
if (_usernameInputField != null) _usernameInputField.text = PlayerPrefs.GetString("username", "");
|
||||
if (_passwordInputField != null) _passwordInputField.text = PlayerPrefs.GetString("password", "");
|
||||
|
||||
if (_selectCharacterScreen != null)
|
||||
_selectCharacterScreen.gameObject.SetActive(false);
|
||||
|
||||
if (entry == BrewMonster.Network.LogoutFlowState.LoginEntryTarget.SelectRole)
|
||||
{
|
||||
// Only auto-login when we actually have saved creds.
|
||||
if (!string.IsNullOrEmpty(_usernameInputField.text) && !string.IsNullOrEmpty(_passwordInputField.text))
|
||||
{
|
||||
BMLogger.Log("[LoginScreenUI] Auto-login triggered (return-to-select-role).");
|
||||
OnLoginButtonClicked();
|
||||
}
|
||||
}
|
||||
Tech3CSDKWrapper.Instance.SetLoginCallback(OnLoginCallback);
|
||||
Tech3CSDKWrapper.Instance.SetLogoutCallback(OnLogoutCallback);
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
@@ -97,26 +79,16 @@ namespace BrewMonster.UI
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
Tech3CSDKWrapper.Instance.RemoveLoginCallback();
|
||||
Tech3CSDKWrapper.Instance.RemoveLogoutCallback();
|
||||
}
|
||||
|
||||
public async void OnLoginButtonClicked()
|
||||
{
|
||||
if (_loginInProgress)
|
||||
{
|
||||
BMLogger.LogWarning("[LoginScreenUI] Login already in progress (ignored click).");
|
||||
return;
|
||||
}
|
||||
_loginInProgress = true;
|
||||
if (_loginButton != null) _loginButton.interactable = false;
|
||||
|
||||
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();
|
||||
BMLogger.Log($"[LoginScreenUI] Connecting+login start user='{username}'");
|
||||
await UnityGameSession.Login(username, password, OnLoginComplete);
|
||||
Tech3CSDKWrapper.Instance.Login();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -325,5 +297,37 @@ namespace BrewMonster.UI
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
private async void OnLoginCallback(int errorCode, string userId, string password)
|
||||
{
|
||||
if (errorCode == 0)
|
||||
{
|
||||
BMLogger.Log($"Login success -- userId: {userId} - {password}");
|
||||
// UnityGameSession.SetConnectionInfo("103.182.22.52", 29000);
|
||||
UnityGameSession.SetConnectionInfo("103.51.120.195", 29000);
|
||||
PlayerPrefs.SetString("username", userId);
|
||||
PlayerPrefs.SetString("password", password);
|
||||
PlayerPrefs.Save();
|
||||
await UnityGameSession.Login(userId, password, OnLoginComplete);
|
||||
_selectCharacterScreen.gameObject.SetActive(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// if it failed, the userId will be the error message
|
||||
BMLogger.LogError($"Login failed -- errorCode: {errorCode}: {userId}");
|
||||
}
|
||||
}
|
||||
|
||||
private void OnLogoutCallback(int errorCode, string errorMessage)
|
||||
{
|
||||
if (errorCode == 0)
|
||||
{
|
||||
BMLogger.Log("Logout success");
|
||||
}
|
||||
else
|
||||
{
|
||||
BMLogger.LogError($"Logout failed -- errorCode: {errorCode}: {errorMessage}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
using Animancer;
|
||||
using BrewMonster.Assets.PerfectWorld.Scripts.UI.GamePlay;
|
||||
using BrewMonster.Network;
|
||||
using BrewMonster.UI;
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BrewMonster
|
||||
{
|
||||
public class CDlgSkillEdit : AUIDialog
|
||||
{
|
||||
int m_nIcon;
|
||||
|
||||
// Start is called once before the first execution of Update after the MonoBehaviour is created
|
||||
public override void Start()
|
||||
{
|
||||
m_nIcon = 1;
|
||||
}
|
||||
#if UNITY_EDITOR
|
||||
public override void Update()
|
||||
{
|
||||
if (Input.GetKeyDown(KeyCode.T))
|
||||
{
|
||||
OnShowDialog();
|
||||
OnCommandConfirm();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
public void OnShowDialog()
|
||||
{
|
||||
EC_VIDEO_SETTING setting = EC_Game.GetConfigs().GetVideoSettings();
|
||||
if (GetData() == 0)
|
||||
{
|
||||
for (uint i = 0; i < EC_ConfigConstants.EC_COMBOSKILL_NUM; i++)
|
||||
{
|
||||
if (setting.comboSkill[i].nIcon == 0)
|
||||
{
|
||||
SetData(i + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (GetData() == 0)
|
||||
{
|
||||
//Show(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
public void OnCommandConfirm()
|
||||
{
|
||||
EC_VIDEO_SETTING setting = EC_Game.GetConfigs().GetVideoSettings();
|
||||
setting.comboSkill[GetData() - 1].nIcon = (byte)m_nIcon;
|
||||
int i;
|
||||
int j = 0;
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
/* AString strName;
|
||||
strName.Format("Item_%d", i + 1);
|
||||
PAUIIMAGEPICTURE pImage = static_cast<PAUIIMAGEPICTURE>(GetDlgItem(strName));
|
||||
if (!pImage) break;*/
|
||||
|
||||
//CECSkill pSkill = (CECSkill)pImage.GetDataPtr("ptr_CECSkill");
|
||||
//int iType = pImage->GetData();
|
||||
if (true/*iType == 0 && pSkill != null*/)
|
||||
{
|
||||
setting.comboSkill[GetData() - 1].idSkill[j] = (short)(i +1) /*pSkill.GetSkillID()*/;
|
||||
j++;
|
||||
}
|
||||
else
|
||||
{
|
||||
//setting.comboSkill[GetData() - 1].idSkill[j] = -iType;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
EC_Game.GetConfigs().SetVideoSettings(setting);
|
||||
//Show(false);
|
||||
CECUIManager.Instance.m_pDlgSkillSubOther.UpdateComboSkill();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b46a84d2ff078524f974fb6d60019d8c
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f45408c4c89289d498475d0e1e1e5b7e
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
<application>
|
||||
<!--Used when Application Entry is set to Activity, otherwise remove this activity block-->
|
||||
<activity android:name="com.unity3d.player.UnityPlayerActivity"
|
||||
android:theme="@style/Tech3CTheme.LoginGame">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
<meta-data android:name="unityplayer.UnityActivity" android:value="true" />
|
||||
</activity>
|
||||
<!--Used when Application Entry is set to GameActivity, otherwise remove this activity block-->
|
||||
<activity android:name="com.unity3d.player.UnityPlayerGameActivity"
|
||||
android:theme="@style/BaseUnityGameActivityTheme">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
<meta-data android:name="unityplayer.UnityActivity" android:value="true" />
|
||||
<meta-data android:name="android.app.lib_name" android:value="game" />
|
||||
</activity>
|
||||
</application>
|
||||
</manifest>
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 11f5d7426047d6048a47d330b02103d9
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,13 @@
|
||||
plugins {
|
||||
// If you are changing the Android Gradle Plugin version, make sure it is compatible with the Gradle version preinstalled with Unity
|
||||
// See which Gradle version is preinstalled with Unity here https://docs.unity3d.com/Manual/android-gradle-overview.html
|
||||
// See official Gradle and Android Gradle Plugin compatibility table here https://developer.android.com/studio/releases/gradle-plugin#updating-gradle
|
||||
// To specify a custom Gradle version in Unity, go do "Preferences > External Tools", uncheck "Gradle Installed with Unity (recommended)" and specify a path to a custom Gradle version
|
||||
id 'com.android.application' version '7.4.2' apply false
|
||||
id 'com.android.library' version '7.4.2' apply false
|
||||
**BUILD_SCRIPT_DEPS**
|
||||
}
|
||||
|
||||
task clean(type: Delete) {
|
||||
delete rootProject.buildDir
|
||||
}
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d0c06c588e2a6442488a3542551fb243
|
||||
guid: 7736ab544ec5cab4a89af84ac45b5a75
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
@@ -0,0 +1,51 @@
|
||||
apply plugin: 'com.android.library'
|
||||
apply from: '../shared/keepUnitySymbols.gradle'
|
||||
**APPLY_PLUGINS**
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
implementation "androidx.appcompat:appcompat:1.6.1"
|
||||
implementation "com.google.android.material:material:1.11.0"
|
||||
**DEPS**}
|
||||
|
||||
android {
|
||||
ndkVersion "**NDKVERSION**"
|
||||
namespace "com.unity3d.player"
|
||||
ndkPath "**NDKPATH**"
|
||||
compileSdk **APIVERSION**
|
||||
buildToolsVersion '**BUILDTOOLS**'
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_11
|
||||
targetCompatibility JavaVersion.VERSION_11
|
||||
}
|
||||
|
||||
buildFeatures {
|
||||
viewBinding true
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
**DEFAULT_CONFIG_SETUP**
|
||||
minSdk **MINSDK**
|
||||
targetSdk **TARGETSDK**
|
||||
ndk {
|
||||
debugSymbolLevel **DEBUGSYMBOLLEVEL**
|
||||
abiFilters **ABIFILTERS**
|
||||
}
|
||||
versionCode **VERSIONCODE**
|
||||
versionName '**VERSIONNAME**'
|
||||
consumerProguardFiles 'proguard-unity.txt'**USER_PROGUARD**
|
||||
}
|
||||
|
||||
lint {
|
||||
abortOnError false
|
||||
}
|
||||
|
||||
androidResources {
|
||||
noCompress = **BUILTIN_NOCOMPRESS** + unityStreamingAssets.tokenize(', ')
|
||||
ignoreAssetsPattern = "!.svn:!.git:!.ds_store:!*.scc:!CVS:!thumbs.db:!picasa.ini:!*~"
|
||||
}**PACKAGING**
|
||||
}
|
||||
**IL_CPP_BUILD_SETUP**
|
||||
**SOURCE_BUILD_SETUP**
|
||||
**EXTERNAL_SOURCES**
|
||||
@@ -0,0 +1,47 @@
|
||||
apply plugin: 'com.android.library'
|
||||
**APPLY_PLUGINS**
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
implementation "androidx.appcompat:appcompat:1.6.1"
|
||||
implementation "com.google.android.material:material:1.11.0"
|
||||
**DEPS**}
|
||||
|
||||
android {
|
||||
namespace "com.unity3d.player"
|
||||
ndkPath "**NDKPATH**"
|
||||
compileSdkVersion **APIVERSION**
|
||||
buildToolsVersion '**BUILDTOOLS**'
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_11
|
||||
targetCompatibility JavaVersion.VERSION_11
|
||||
}
|
||||
|
||||
buildFeatures {
|
||||
viewBinding true
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion **MINSDKVERSION**
|
||||
targetSdkVersion **TARGETSDKVERSION**
|
||||
ndk {
|
||||
abiFilters **ABIFILTERS**
|
||||
}
|
||||
versionCode **VERSIONCODE**
|
||||
versionName '**VERSIONNAME**'
|
||||
consumerProguardFiles 'proguard-unity.txt'**USER_PROGUARD**
|
||||
}
|
||||
|
||||
lintOptions {
|
||||
abortOnError false
|
||||
}
|
||||
|
||||
aaptOptions {
|
||||
noCompress = **BUILTIN_NOCOMPRESS** + unityStreamingAssets.tokenize(', ')
|
||||
ignoreAssetsPattern = "!.svn:!.git:!.ds_store:!*.scc:!CVS:!thumbs.db:!picasa.ini:!*~"
|
||||
}**PACKAGING_OPTIONS**
|
||||
}
|
||||
**IL_CPP_BUILD_SETUP**
|
||||
**SOURCE_BUILD_SETUP**
|
||||
**EXTERNAL_SOURCES**
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f3bedb9070cd041a2bb8a27d9751aada
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 950fdc575e5b3b74ea1d3f1c60322d4f
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1660,7 +1660,7 @@ MonoBehaviour:
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_text: 10000000000000
|
||||
m_text: 0
|
||||
m_isRightToLeft: 0
|
||||
m_fontAsset: {fileID: 11400000, guid: 369c2e14814cc9a4b8e3ad4e37769134, type: 2}
|
||||
m_sharedMaterial: {fileID: 9092487103257209053, guid: 369c2e14814cc9a4b8e3ad4e37769134, type: 2}
|
||||
@@ -10577,6 +10577,7 @@ MonoBehaviour:
|
||||
m_BtnMerge: {fileID: 8208092408021918524}
|
||||
m_BtnCancel: {fileID: 4503836757578509720}
|
||||
khung_item: {fileID: 21300000, guid: a5366f3bce011c046902e39b6bd3a077, type: 3}
|
||||
itemInventoryRoot: {fileID: 7750009739432212686}
|
||||
--- !u!1 &5641506892578507279
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -14989,7 +14990,7 @@ MonoBehaviour:
|
||||
m_Calls:
|
||||
- m_Target: {fileID: 2206910701173095729}
|
||||
m_TargetAssemblyTypeName: BrewMonster.DlgInstall, Assembly-CSharp
|
||||
m_MethodName: CloseInstall
|
||||
m_MethodName: ResetInstallUI
|
||||
m_Mode: 1
|
||||
m_Arguments:
|
||||
m_ObjectArgument: {fileID: 0}
|
||||
|
||||
+567
-2640
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:def3c6a4f58ef9b5c9558210328e5b6f3ed11bfee5b577271ee43fa110616b82
|
||||
size 200521689
|
||||
oid sha256:95d6d825ffc45e6ba389d5e2baffd576d409d5718b1888331c763dfe2b9460e5
|
||||
size 200522636
|
||||
|
||||
@@ -7,8 +7,10 @@ using BrewMonster.UI;
|
||||
using CSNetwork;
|
||||
using CSNetwork.GPDataType;
|
||||
using CSNetwork.Protocols.RPCData;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Unity.Cinemachine;
|
||||
using UnityEngine;
|
||||
@@ -32,6 +34,8 @@ public partial class CECGameRun
|
||||
//[SerializeField] private Transform ground;
|
||||
CECHostPlayer hostPlayer;
|
||||
private CECWorld m_pWorld;
|
||||
int m_iGameState; // Game state
|
||||
|
||||
|
||||
protected CECUIManager m_pUIManager; // UI manager
|
||||
|
||||
@@ -108,7 +112,7 @@ public partial class CECGameRun
|
||||
if (_npcServerPrefab == null)
|
||||
{
|
||||
BMLogger.LogError("CECGameRun::LoadPrefabs, Failed to load _npcServerPrefab prefab.");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -277,7 +281,6 @@ public partial class CECGameRun
|
||||
/// <returns>True if loaded successfully / 加载成功返回true</returns>
|
||||
public bool LoadConfigsFromServer(byte[] pDataBuf, int iDataSize)
|
||||
{
|
||||
BMLogger.LogError("LoadConfigsFromServer ");
|
||||
const uint USERCFG_VERSION = 3;
|
||||
|
||||
if (pDataBuf == null || iDataSize == 0)
|
||||
@@ -305,7 +308,6 @@ public partial class CECGameRun
|
||||
dwRealLen = 0;
|
||||
}
|
||||
byte[] pData = pDataBuf;
|
||||
int dataOffset = offset;
|
||||
|
||||
if (dwVer >= 3)
|
||||
{
|
||||
@@ -348,32 +350,31 @@ public partial class CECGameRun
|
||||
}
|
||||
}
|
||||
//TODO: flow in update fix later
|
||||
Task.Run(() =>
|
||||
{
|
||||
GameSession.Context.Post(_ =>
|
||||
{
|
||||
if (m_pUIManager == null)
|
||||
{
|
||||
m_pUIManager = CECUIManager.Instance;
|
||||
}
|
||||
m_pUIManager.GetCDlgQuickBar().UpdateShortcuts();
|
||||
}, null);
|
||||
});
|
||||
|
||||
/* Task.Run(() =>
|
||||
{
|
||||
GameSession.Context.Post(_ =>
|
||||
{
|
||||
if (m_pUIManager == null)
|
||||
{
|
||||
m_pUIManager = CECUIManager.Instance;
|
||||
}
|
||||
m_pUIManager.GetCDlgQuickBar().UpdateShortcuts();
|
||||
}, null);
|
||||
});*/
|
||||
// TODO: Uncomment when UI manager is available
|
||||
// Load UI configs / 加载UI配置
|
||||
|
||||
CECGameUIMan pGameUI = m_pUIManager.GetInGameUIMan();
|
||||
/* if (pGameUI != null)
|
||||
{
|
||||
int iSize = dr.ReadInt();
|
||||
byte[] uiConfigData = dr.ReadData(iSize);
|
||||
if (!pGameUI.SetUserLayout(uiConfigData, iSize))
|
||||
{
|
||||
BMLogger.LogError("CECGameRun::LoadConfigsFromServer, Failed to set user layout");
|
||||
return false;
|
||||
}
|
||||
}*/
|
||||
if (pGameUI != null)
|
||||
{
|
||||
int iSize = dr.ReadInt();
|
||||
byte[] uiConfigData = dr.ReadData(iSize);
|
||||
/*if (!pGameUI.SetUserLayout(uiConfigData, iSize))
|
||||
{
|
||||
BMLogger.LogError("CECGameRun::LoadConfigsFromServer, Failed to set user layout");
|
||||
return false;
|
||||
}*/
|
||||
}
|
||||
|
||||
// Load user settings / 加载用户设置
|
||||
if (dwVer >= 2)
|
||||
@@ -381,11 +382,11 @@ public partial class CECGameRun
|
||||
// TODO: Uncomment when game configs are available
|
||||
int iSize = dr.ReadInt();
|
||||
byte[] settingsData = dr.ReadData(iSize);
|
||||
/* if (!EC_Game.GetConfigs().LoadUserConfigData(settingsData, iSize))
|
||||
{
|
||||
BMLogger.LogError("CECGameRun::LoadConfigsFromServer, Failed to load user config data");
|
||||
return false;
|
||||
}*/
|
||||
if (!EC_Game.GetConfigs().LoadUserConfigData(settingsData, iSize))
|
||||
{
|
||||
BMLogger.LogError("CECGameRun::LoadConfigsFromServer, Failed to load user config data");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (System.Exception e)
|
||||
@@ -705,4 +706,16 @@ public partial class CECGameRun
|
||||
{
|
||||
m_iDExpEndTime = endTime;
|
||||
}
|
||||
public int GetGameState() { return m_iGameState; }
|
||||
public void SaveConfigsToServer()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
public enum GameState
|
||||
|
||||
{
|
||||
GS_NONE = 0, // None
|
||||
GS_LOGIN, // Login in state
|
||||
GS_GAME, // In game
|
||||
};
|
||||
+696
-284
File diff suppressed because it is too large
Load Diff
@@ -4,6 +4,7 @@ using BrewMonster.UI;
|
||||
using CSNetwork;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using BrewMonster.Scripts.Managers;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityEngine.UIElements;
|
||||
@@ -25,6 +26,7 @@ public class CECUIManager : MonoSingleton<CECUIManager>
|
||||
|
||||
[SerializeField] private UnityEngine.UI.Button btnSecondClick;
|
||||
[SerializeField] CDlgQuickBar m_pDlgQuickBar1;
|
||||
public CDlgSkillSubOther m_pDlgSkillSubOther;
|
||||
CDlgMessageBox m_pDlgMessageBox;
|
||||
public CDlgSkillAction m_pDlgSkillAction;
|
||||
|
||||
@@ -107,7 +109,12 @@ public class CECUIManager : MonoSingleton<CECUIManager>
|
||||
var msgBox = GetInGameUIMan().GetDialog("DlgMessageBox") as CDlgMessageBox;
|
||||
if (msgBox != null)
|
||||
{
|
||||
msgBox.ShowMessageBox(title, message);
|
||||
msgBox.ShowMessageBox(new MessageBoxData()
|
||||
{
|
||||
Title = title,
|
||||
Message = message,
|
||||
MessageBoxType = MessageBoxType.YesButton
|
||||
});
|
||||
return msgBox;
|
||||
}
|
||||
else
|
||||
@@ -183,6 +190,25 @@ public class CECUIManager : MonoSingleton<CECUIManager>
|
||||
}
|
||||
|
||||
}
|
||||
else if(string.CompareOrdinal("Game_Disenchase",pDlg.GetName())==0 && DialogBoxCommandIDs.IDOK == iRetVal)
|
||||
{
|
||||
// PAUIDIALOG pMsgBox;
|
||||
var clearEmbeddedChipDlg = GetInGameUIMan().GetDialog("Game_Disenchase");
|
||||
// EC_IvtrItem pIvtr = (EC_IvtrItem)m_pDlgUninstall->m_pItema->GetDataPtr("ptr_CECIvtrItem");
|
||||
//
|
||||
// pSession.c2s_CmdNPCSevClearEmbeddedChip(
|
||||
// (WORD)m_pDlgUninstall->m_pItema->GetData(), pIvtr->GetTemplateID());
|
||||
//
|
||||
// m_pDlgUninstall->Show(false);
|
||||
// pHost->EndNPCService();
|
||||
// m_pCurNPCEssence = NULL;
|
||||
// m_pDlgInventory->Show(false);
|
||||
// pHost->GetPack(IVTRTYPE_PACK)->UnfreezeAllItems();
|
||||
//
|
||||
// MessageBox("", GetStringFromTable(228), MB_OK,
|
||||
// A3DCOLORRGBA(255, 255, 255, 160), &pMsgBox);
|
||||
// pMsgBox->SetLife(3);
|
||||
}
|
||||
}
|
||||
|
||||
private bool OnNewMessageBox(int iRetVal)
|
||||
|
||||
@@ -3,6 +3,7 @@ using BrewMonster.Network;
|
||||
using CSNetwork.GPDataType;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Runtime.InteropServices;
|
||||
@@ -68,6 +69,7 @@ public static class EC_Utility
|
||||
Marshal.FreeHGlobal(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
public static A3DVECTOR3 glb_DecompressDirH(byte byDir)
|
||||
{
|
||||
const float fInter = 360.0f / 256.0f;
|
||||
@@ -84,6 +86,27 @@ public static class EC_Utility
|
||||
{
|
||||
return new System.Numerics.Vector3(v.x, v.y, v.z);
|
||||
}
|
||||
public static byte glb_BuildRefuseBLSMask()
|
||||
{
|
||||
byte byMask = 0;
|
||||
|
||||
// const EC_GAME_SETTING &gs = g_pGame->GetConfigs()->GetGameSettings();
|
||||
var gs = EC_Game.GetConfigs().GetGameSettings();
|
||||
|
||||
if (gs.bBlsRefuse_Neutral)
|
||||
byMask |= (byte)REFUSE_BLESS_MASK.REFUSE_NEUTRAL_BLESS;
|
||||
|
||||
if (gs.bBlsRefuse_NonTeammate)
|
||||
byMask |= (byte)REFUSE_BLESS_MASK.REFUSE_NON_TEAMMATE_BLESS;
|
||||
|
||||
return byMask;
|
||||
}
|
||||
public static void Swap<T>(List<T> arr, int a, int b)
|
||||
{
|
||||
T tmp = arr[a];
|
||||
arr[a] = arr[b];
|
||||
arr[b] = tmp;
|
||||
}
|
||||
public static A3DVECTOR3 ToA3DVECTOR3(this UnityEngine.Vector3 v)
|
||||
{
|
||||
a3DVECTOR.Clear();
|
||||
@@ -148,20 +171,20 @@ public static class EC_Utility
|
||||
byte byMask = 0;
|
||||
CECConfigs pConfigs = EC_Game.GetConfigs();
|
||||
|
||||
/* if (pConfigs->GetGameSettings().bBls_NoRed)
|
||||
byMask |= GP_BLSMASK_NORED;
|
||||
/* if (pConfigs->GetGameSettings().bBls_NoRed)
|
||||
byMask |= GP_BLSMASK_NORED;
|
||||
|
||||
if (pConfigs->GetGameSettings().bBls_NoMafia)
|
||||
byMask |= GP_BLSMASK_NOMAFIA;
|
||||
if (pConfigs->GetGameSettings().bBls_NoMafia)
|
||||
byMask |= GP_BLSMASK_NOMAFIA;
|
||||
|
||||
if (pConfigs->GetGameSettings().bBls_Self)
|
||||
byMask |= GP_BLSMASK_SELF;
|
||||
if (pConfigs->GetGameSettings().bBls_Self)
|
||||
byMask |= GP_BLSMASK_SELF;
|
||||
|
||||
if (pConfigs->GetGameSettings().bBls_NoAlliance)
|
||||
byMask |= GP_BLSMASK_NOALLIANCE;
|
||||
if (pConfigs->GetGameSettings().bBls_NoAlliance)
|
||||
byMask |= GP_BLSMASK_NOALLIANCE;
|
||||
|
||||
if (pConfigs->GetGameSettings().bBls_NoForce)
|
||||
byMask |= GP_BLSMASK_NOFORCE;*/
|
||||
if (pConfigs->GetGameSettings().bBls_NoForce)
|
||||
byMask |= GP_BLSMASK_NOFORCE;*/
|
||||
|
||||
return byMask;
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ namespace BrewMonster
|
||||
"程序联入/金币效果.gfx", // RES_GFX_ITEMFLASH,
|
||||
"程序联入/鼠标悬浮.gfx", // RES_GFX_CURSORHOVER,
|
||||
"程序联入/目标被选中.gfx", // RES_GFX_SELECTED,
|
||||
"程序联入/目标被选中.gfx", // RES_GFX_SELECTED,
|
||||
"程序联入/海底飘尘.gfx", // RES_GFX_FLOATING_DUST,
|
||||
"程序联入/人物游动水圈.gfx", // RES_GFX_WATER_WAVE_STILL,
|
||||
"程序联入/人物游动水波.gfx", // RES_GFX_WATER_WAVE_MOVE,
|
||||
@@ -51,7 +52,73 @@ namespace BrewMonster
|
||||
"人物/通用/其它/境界提升.gfx",
|
||||
"策划联入/状态效果/斗气%d级.gfx",
|
||||
};
|
||||
|
||||
public static string res_IconFile(int n)
|
||||
{
|
||||
return l_aIconFiles[n];
|
||||
}
|
||||
|
||||
public static readonly string[] l_aIconFiles =
|
||||
{
|
||||
"打坐",
|
||||
"走跑转换",
|
||||
"普通攻击",
|
||||
"寻找目标",
|
||||
"协助攻击",
|
||||
|
||||
"邀请加入",
|
||||
"脱离队伍",
|
||||
"踢出队伍",
|
||||
"寻找队伍",
|
||||
"交易命令",
|
||||
|
||||
"摆摊卖",
|
||||
"摆摊买",
|
||||
"邀请加入",
|
||||
"飞行",
|
||||
"招手", // RES_ICON_CMD_EXP_WAVE,
|
||||
|
||||
"点头", // RES_ICON_CMD_EXP_NOD,
|
||||
"摇头", // RES_ICON_CMD_EXP_SHAKEHEAD,
|
||||
"耸肩膀", // RES_ICON_CMD_EXP_SHRUG,
|
||||
"大笑", // RES_ICON_CMD_EXP_LAUGH,
|
||||
"生气", // RES_ICON_CMD_EXP_ANGRY,
|
||||
|
||||
"晕倒", // RES_ICON_CMD_EXP_STUN,
|
||||
"沮丧", // RES_ICON_CMD_EXP_DEPRESSED,
|
||||
"飞吻", // RES_ICON_CMD_EXP_KISSHAND,
|
||||
"害羞", // RES_ICON_CMD_EXP_SHY,
|
||||
"抱拳", // RES_ICON_CMD_EXP_SALUTE,
|
||||
|
||||
"坐下", // RES_ICON_CMD_EXP_SITDOWN,
|
||||
"冲锋", // RES_ICON_CMD_EXP_ASSAULT,
|
||||
"思考", // RES_ICON_CMD_EXP_THINK,
|
||||
"挑衅", // RES_ICON_CMD_EXP_DEFIANCE,
|
||||
"胜利", // RES_ICON_CMD_EXP_VICTORY,
|
||||
|
||||
"伸懒腰", // RES_ICON_CMD_EXP_GAPE
|
||||
"亲吻", // RES_ICON_CMD_EXP_KISS
|
||||
"战斗", // RES_ICON_CMD_EXP_FIGHT,
|
||||
"攻击1", // RES_ICON_CMD_EXP_ATTACK1,
|
||||
"攻击2", // RES_ICON_CMD_EXP_ATTACK2,
|
||||
|
||||
"攻击3", // RES_ICON_CMD_EXP_ATTACK3,
|
||||
"攻击4", // RES_ICON_CMD_EXP_ATTACK4,
|
||||
"防御", // RES_ICON_CMD_EXP_DEFENCE,
|
||||
"摔倒", // RES_ICON_CMD_EXP_FALL,
|
||||
"倒地", // RES_ICON_CMD_EXP_FALLONGROUND,
|
||||
|
||||
"张望", // RES_ICON_CMD_EXP_LOOKAROUND,
|
||||
"舞蹈1", // RES_ICON_CMD_EXP_DANCE,
|
||||
"舞蹈2", // RES_ICON_CMD_EXP_FASHIONWEAPON
|
||||
"拾取", // RES_ICON_CMD_PICKUP
|
||||
"挖掘", // RES_ICON_CMD_GATHER
|
||||
"加速飞行", // RES_ICON_CMD_RUSHFLY
|
||||
|
||||
"相依相偎的动作", // RES_ICON_CMD_BINDBUDDY
|
||||
"亲亲密密的动作", // RES_ICON_CMD_TWOKISS
|
||||
"跳跃的动作1", // RES_ICON_CMD_JUMPTRICK,
|
||||
"跳跃的动作2", // RES_ICON_CMD_RUNTRICK,
|
||||
};
|
||||
public static string res_GFXFile(int n)
|
||||
{
|
||||
if (n < 0 || n >= l_aGFXFiles.Length)
|
||||
@@ -78,7 +145,7 @@ namespace BrewMonster
|
||||
NUM_RES_CURSOR,
|
||||
}
|
||||
|
||||
// GFX resource
|
||||
// GFX resource
|
||||
enum GfxResourceType
|
||||
{
|
||||
RES_GFX_LEVELUP = 0,
|
||||
@@ -113,11 +180,11 @@ namespace BrewMonster
|
||||
NUM_RES_GFX,
|
||||
};
|
||||
|
||||
// Sound resource
|
||||
// Sound resource
|
||||
|
||||
// Texture resource
|
||||
// Texture resource
|
||||
|
||||
// Shader resource
|
||||
// Shader resource
|
||||
enum ShaderResourceType
|
||||
{
|
||||
RES_SHD_HAIR = 0,
|
||||
@@ -134,8 +201,7 @@ namespace BrewMonster
|
||||
|
||||
NUM_RES_SHADER, // 10
|
||||
};
|
||||
|
||||
// Icon resource
|
||||
// Icon resource
|
||||
enum IconResourceType
|
||||
{
|
||||
RES_ICON_CMD_SITDOWN = 0,
|
||||
@@ -201,7 +267,7 @@ namespace BrewMonster
|
||||
NUM_RES_ICON,
|
||||
};
|
||||
|
||||
// Model resource
|
||||
// Model resource
|
||||
enum ModelResourceType
|
||||
{
|
||||
RES_MOD_GOLD = 0,
|
||||
@@ -266,7 +332,7 @@ namespace BrewMonster
|
||||
NUM_RES_MODEL,
|
||||
};
|
||||
|
||||
// model file for change shape 2
|
||||
// model file for change shape 2
|
||||
enum ResourceModelType
|
||||
{
|
||||
RES_MOD_CHANGESAHPE_NULL, // 0
|
||||
@@ -290,7 +356,7 @@ namespace BrewMonster
|
||||
RES_MOD_FORCHANGESAHPE_NUM,
|
||||
};
|
||||
|
||||
// Some unicode string resources
|
||||
// Some unicode string resources
|
||||
enum UnicodeStringResourceType
|
||||
{
|
||||
RES_FONT_TITLE = 0,
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 86378052e9798924e8ee14f4fa780f0f
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4c935d070fff35741adebc5424c4e02b
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2111256da5c2b2a469d98ce0f103cdb7
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,184 @@
|
||||
package vn.tech3c.sdk.unity;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import vn.tech3c.sdk.auth.callback.OnAuthCallback;
|
||||
import vn.tech3c.sdk.auth.controller.Tech3CIdController;
|
||||
import vn.tech3c.sdk.auth.entities.enums.LoginType;
|
||||
import vn.tech3c.sdk.auth.exceptions.Tech3CIdException;
|
||||
|
||||
import com.unity3d.player.UnityPlayer;
|
||||
|
||||
/**
|
||||
* Unity Bridge for Tech3C SDK
|
||||
* This class receives callbacks from Tech3C SDK and sends them to Unity via UnitySendMessage
|
||||
*/
|
||||
public class Tech3CUnityBridge implements OnAuthCallback {
|
||||
private static final String TAG = "Tech3CUnityBridge";
|
||||
private static final String UNITY_GAME_OBJECT = "Tech3CSDKBridge";
|
||||
|
||||
private static Tech3CUnityBridge instance;
|
||||
|
||||
private OnUnityAuthCallback unityAuthCallback;
|
||||
private OnUnityLogoutCallback unityLogoutCallback;
|
||||
private OnUnityUserInfoCallback unityUserInfoCallback;
|
||||
|
||||
// Singleton
|
||||
public static synchronized Tech3CUnityBridge getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new Tech3CUnityBridge();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
// Interfaces for Unity callbacks
|
||||
public interface OnUnityAuthCallback {
|
||||
void onAuthSuccess(String userId, String password, String accessToken, String refreshToken, LoginType loginType, long expiryTime);
|
||||
void onAuthCancelled();
|
||||
void onAuthError(int errorCode, String errorMessage);
|
||||
}
|
||||
|
||||
public interface OnUnityLogoutCallback {
|
||||
void onLogoutSuccess();
|
||||
void onLogoutError(int errorCode, String errorMessage);
|
||||
}
|
||||
|
||||
public interface OnUnityUserInfoCallback {
|
||||
void onUserInfoReceived(String userId, String username, String email, String phone);
|
||||
void onUserInfoCancelled();
|
||||
void onUserInfoError(int errorCode, String errorMessage);
|
||||
}
|
||||
|
||||
// Set callbacks
|
||||
public void setUnityAuthCallback(OnUnityAuthCallback callback) {
|
||||
this.unityAuthCallback = callback;
|
||||
}
|
||||
|
||||
public void setUnityLogoutCallback(OnUnityLogoutCallback callback) {
|
||||
this.unityLogoutCallback = callback;
|
||||
}
|
||||
|
||||
public void setUnityUserInfoCallback(OnUnityUserInfoCallback callback) {
|
||||
this.unityUserInfoCallback = callback;
|
||||
}
|
||||
|
||||
// Send message to Unity
|
||||
private void sendToUnity(String methodName, String message) {
|
||||
try {
|
||||
UnityPlayer.UnitySendMessage(UNITY_GAME_OBJECT, methodName, message);
|
||||
Log.d(TAG, "Sent to Unity: " + methodName + " - " + message);
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Error sending to Unity: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// ========== OnAuthCallback Implementation ==========
|
||||
|
||||
@Override
|
||||
public void onLoginSuccess(String userId, String password, String accessToken, String refreshToken, LoginType loginType, long expiryTime) {
|
||||
Log.d(TAG, "onLoginSuccess: " + userId);
|
||||
|
||||
// Send to Unity
|
||||
String message = userId + "|" + password + "|" + accessToken + "|" + refreshToken + "|" + loginType.name() + "|" + expiryTime;
|
||||
sendToUnity("OnAuthSuccess", message);
|
||||
|
||||
// Also call Unity callback if set
|
||||
if (unityAuthCallback != null) {
|
||||
unityAuthCallback.onAuthSuccess(userId, password, accessToken, refreshToken, loginType, expiryTime);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRegisterSuccess(String accessToken, String refreshToken, String userId, long expiryTime) {
|
||||
Log.d(TAG, "onRegisterSuccess: " + userId);
|
||||
|
||||
// Treat register success as auth success (password is empty for register)
|
||||
String message = userId + "|" + "" + "|" + accessToken + "|" + refreshToken + "|REGISTER|" + expiryTime;
|
||||
sendToUnity("OnAuthSuccess", message);
|
||||
|
||||
if (unityAuthCallback != null) {
|
||||
unityAuthCallback.onAuthSuccess(userId, "", accessToken, refreshToken, LoginType.ACCOUNT, expiryTime);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAuthCancelled() {
|
||||
Log.d(TAG, "onAuthCancelled");
|
||||
sendToUnity("OnAuthCancelled", "");
|
||||
|
||||
if (unityAuthCallback != null) {
|
||||
unityAuthCallback.onAuthCancelled();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAuthScreenOpened() {
|
||||
Log.d(TAG, "onAuthScreenOpened");
|
||||
// Optional: Send to Unity if needed
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Tech3CIdException exception) {
|
||||
Log.d(TAG, "onError: " + exception.getMessage());
|
||||
|
||||
String message = exception.getErrorCode() + "|" + exception.getMessage();
|
||||
sendToUnity("OnAuthError", message);
|
||||
|
||||
if (unityAuthCallback != null) {
|
||||
unityAuthCallback.onAuthError(exception.getErrorCode(), exception.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// ========== Additional Callback Methods ==========
|
||||
|
||||
public void onLogoutSuccess() {
|
||||
Log.d(TAG, "onLogoutSuccess");
|
||||
sendToUnity("OnLogoutSuccess", "");
|
||||
|
||||
if (unityLogoutCallback != null) {
|
||||
unityLogoutCallback.onLogoutSuccess();
|
||||
}
|
||||
}
|
||||
|
||||
public void onLogoutError(int errorCode, String errorMessage) {
|
||||
Log.d(TAG, "onLogoutError: " + errorMessage);
|
||||
|
||||
String message = errorCode + "|" + errorMessage;
|
||||
sendToUnity("OnLogoutError", message);
|
||||
|
||||
if (unityLogoutCallback != null) {
|
||||
unityLogoutCallback.onLogoutError(errorCode, errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
public void onUserInfoReceived(String userId, String username, String email, String phone) {
|
||||
Log.d(TAG, "onUserInfoReceived: " + userId);
|
||||
|
||||
String message = userId + "|" + username + "|" + email + "|" + phone;
|
||||
sendToUnity("OnUserInfoReceived", message);
|
||||
|
||||
if (unityUserInfoCallback != null) {
|
||||
unityUserInfoCallback.onUserInfoReceived(userId, username, email, phone);
|
||||
}
|
||||
}
|
||||
|
||||
public void onUserInfoCancelled() {
|
||||
Log.d(TAG, "onUserInfoCancelled");
|
||||
sendToUnity("OnUserInfoCancelled", "");
|
||||
|
||||
if (unityUserInfoCallback != null) {
|
||||
unityUserInfoCallback.onUserInfoCancelled();
|
||||
}
|
||||
}
|
||||
|
||||
public void onUserInfoError(int errorCode, String errorMessage) {
|
||||
Log.d(TAG, "onUserInfoError: " + errorMessage);
|
||||
|
||||
String message = errorCode + "|" + errorMessage;
|
||||
sendToUnity("OnUserInfoError", message);
|
||||
|
||||
if (unityUserInfoCallback != null) {
|
||||
unityUserInfoCallback.onUserInfoError(errorCode, errorMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e32ed25f4a2155a4f8106c56c82bb7fc
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 0
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
Android: Android
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 0
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
DefaultValueInitialized: true
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Binary file not shown.
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3385cda9ff7dcd74ebc47f50d2e8196c
|
||||
@@ -0,0 +1,2 @@
|
||||
android.useAndroidX=true
|
||||
android.enableJetifier=true
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5b51400b9b30374459987374d5fb2a0a
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,43 @@
|
||||
apply plugin: 'com.android.library'
|
||||
**APPLY_PLUGINS**
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
implementation "androidx.appcompat:appcompat:1.6.1"
|
||||
implementation "com.google.android.material:material:1.11.0"
|
||||
**DEPS**}
|
||||
|
||||
android {
|
||||
namespace "com.unity3d.player"
|
||||
ndkPath "**NDKPATH**"
|
||||
compileSdkVersion **APIVERSION**
|
||||
buildToolsVersion '**BUILDTOOLS**'
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_11
|
||||
targetCompatibility JavaVersion.VERSION_11
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion **MINSDKVERSION**
|
||||
targetSdkVersion **TARGETSDKVERSION**
|
||||
ndk {
|
||||
abiFilters **ABIFILTERS**
|
||||
}
|
||||
versionCode **VERSIONCODE**
|
||||
versionName '**VERSIONNAME**'
|
||||
consumerProguardFiles 'proguard-unity.txt'**USER_PROGUARD**
|
||||
}
|
||||
|
||||
lintOptions {
|
||||
abortOnError false
|
||||
}
|
||||
|
||||
aaptOptions {
|
||||
noCompress = **BUILTIN_NOCOMPRESS** + unityStreamingAssets.tokenize(', ')
|
||||
ignoreAssetsPattern = "!.svn:!.git:!.ds_store:!*.scc:!CVS:!thumbs.db:!picasa.ini:!*~"
|
||||
}**PACKAGING_OPTIONS**
|
||||
}
|
||||
**IL_CPP_BUILD_SETUP**
|
||||
**SOURCE_BUILD_SETUP**
|
||||
**EXTERNAL_SOURCES**
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 68ef4c077c6bfee47ad1aa16645a896d
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,30 @@
|
||||
#### Proguard class tech3c
|
||||
-keep public class vn.tech3c.sdk.auth.entities.* {
|
||||
public *;
|
||||
}
|
||||
-keep public class vn.tech3c.sdk.auth.entities.enums.* {
|
||||
public *;
|
||||
}
|
||||
-keep public class vn.tech3c.sdk.auth.entities.response.* {
|
||||
public *;
|
||||
}
|
||||
-keep public class vn.tech3c.sdk.auth.entities.request.* {
|
||||
public *;
|
||||
}
|
||||
|
||||
-keep public interface vn.tech3c.sdk.auth.** { *; }
|
||||
|
||||
-keep public class vn.tech3c.sdk.auth.controller.Tech3CIdController { public *;}
|
||||
-keep public class vn.tech3c.sdk.auth.exceptions.Tech3CIdException { public *;}
|
||||
|
||||
-keep public class vn.tech3c.sdk.auth.Tech3CIdAuthentication {
|
||||
public *;
|
||||
}
|
||||
|
||||
-keep public class vn.tech3c.sdk.auth.config.Tech3CIdConfig {
|
||||
public *;
|
||||
}
|
||||
|
||||
-keep public class vn.tech3c.sdk.example.Tech3CUnityBridge { public *;}
|
||||
-keep public class vn.tech3c.sdk.example.Tech3CUnityBridge$** { *; }
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0a1d44356c1df074d8cd78bee53cbafa
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user