diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000000..d6869adadc
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,25 @@
+# EditorConfig for Unity Project
+root = true
+
+[*]
+charset = utf-8
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+[*.cs]
+indent_style = space
+indent_size = 4
+end_of_line = crlf
+
+# Unity Editor Only Usage Analyzer
+# ERROR (màu đỏ) khi sử dụng code trong #if UNITY_EDITOR từ code không có directive
+dotnet_diagnostic.UNITY_EDITOR_ONLY_USAGE.severity = error
+
+# Các rule khác cho Unity
+dotnet_analyzer_diagnostic.category-Unity.severity = warning
+
+[*.{asmdef,asmref}]
+indent_size = 2
+
+[*.{json,md}]
+indent_size = 2
diff --git a/.gitignore b/.gitignore
index e947009f12..d6c6bb7a8c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -102,4 +102,4 @@ InitTestScene*.unity*
.idea
# AI Context
-claude.md
+
diff --git a/Assets/Analyzers.meta b/Assets/Analyzers.meta
new file mode 100644
index 0000000000..bc69ce053c
--- /dev/null
+++ b/Assets/Analyzers.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: d6389bfe41ba69e42991434d87c1319f
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Editor/AddAnalyzerPostprocessor.cs b/Assets/Editor/AddAnalyzerPostprocessor.cs
new file mode 100644
index 0000000000..1ff01a4e44
--- /dev/null
+++ b/Assets/Editor/AddAnalyzerPostprocessor.cs
@@ -0,0 +1,157 @@
+#if UNITY_EDITOR
+using System.IO;
+using UnityEditor;
+using UnityEngine;
+
+///
+/// Tự động thêm UnityEditorOnlyAnalyzer vào các .csproj files khi Unity generate chúng
+/// Analyzer phải ở project root, KHÔNG trong Assets/ để tránh Unity load như runtime assembly
+///
+public class AddAnalyzerPostprocessor : AssetPostprocessor
+{
+ private static string GetAnalyzerPath()
+ {
+ string projectRoot = Path.GetDirectoryName(Application.dataPath);
+ string analyzerPath = Path.Combine(projectRoot, "UnityEditorOnlyAnalyzer/bin/Release/netstandard2.0/UnityEditorOnlyAnalyzer.dll");
+ return Path.GetFullPath(analyzerPath);
+ }
+
+ ///
+ /// Unity gọi method này cho từng .csproj file được generate
+ /// Return content đã được modify - Unity sẽ ghi content này vào file
+ ///
+ public static string OnGeneratedCSProject(string path, string content)
+ {
+ string fileName = Path.GetFileName(path);
+
+ // Chỉ thêm vào các runtime assemblies, không thêm vào Editor assemblies
+ if (fileName != "Assembly-CSharp.csproj" && fileName != "Assembly-CSharp-firstpass.csproj")
+ {
+ return content;
+ }
+
+ // Kiểm tra xem đã có analyzer chưa
+ if (content.Contains("UnityEditorOnlyAnalyzer.dll"))
+ {
+ return content;
+ }
+
+ string analyzerPath = GetAnalyzerPath();
+
+ // Kiểm tra analyzer có tồn tại không
+ if (!File.Exists(analyzerPath))
+ {
+ Debug.LogWarning($"[UnityEditorOnlyAnalyzer] Analyzer not found at {analyzerPath}. " +
+ "Please build the analyzer first: cd UnityEditorOnlyAnalyzer && dotnet build -c Release");
+ return content;
+ }
+
+ // Bug fix 1: Tìm "" không có dấu cách ở đầu
+ int lastProjectTag = content.LastIndexOf("");
+ if (lastProjectTag < 0)
+ {
+ Debug.LogWarning($"[UnityEditorOnlyAnalyzer] Could not find tag in {fileName}");
+ return content;
+ }
+
+ // Bug fix 2: Không double-escape backslash trong XML - XML tự động escape
+ // Chỉ cần đảm bảo path có backslash đúng format Windows
+ string analyzerInclude = $@"
+
+
+";
+
+ string modifiedContent = content.Substring(0, lastProjectTag) + analyzerInclude;
+ Debug.Log($"[UnityEditorOnlyAnalyzer] ✅ Added analyzer to {fileName}");
+
+ return modifiedContent;
+ }
+
+ ///
+ /// Public method để menu item có thể gọi thủ công
+ ///
+ public static void AddAnalyzerToProjects()
+ {
+ // Trigger Unity regenerate .csproj files để OnGeneratedCSProject được gọi
+ UnityEditorInternal.InternalEditorUtility.OpenFileAtLineExternal("", 0);
+ AssetDatabase.Refresh();
+
+ // Cũng gọi fallback method để đảm bảo
+ OnGeneratedCSProjectFiles();
+ }
+
+ ///
+ /// Backup method: Unity gọi method này sau khi generate tất cả .csproj files
+ /// Chỉ dùng nếu OnGeneratedCSProject không hoạt động
+ ///
+ private static void OnGeneratedCSProjectFiles()
+ {
+ // Fallback: patch files sau khi đã được generate
+ string projectRoot = Path.GetDirectoryName(Application.dataPath);
+ string analyzerPath = GetAnalyzerPath();
+
+ if (!File.Exists(analyzerPath))
+ {
+ Debug.LogWarning($"[UnityEditorOnlyAnalyzer] Analyzer not found at {analyzerPath}. " +
+ "Please build the analyzer first: cd UnityEditorOnlyAnalyzer && dotnet build -c Release");
+ return;
+ }
+
+ string[] csprojFiles = Directory.GetFiles(projectRoot, "*.csproj", SearchOption.TopDirectoryOnly);
+ bool anyModified = false;
+
+ foreach (string csprojFile in csprojFiles)
+ {
+ string fileName = Path.GetFileName(csprojFile);
+ if (fileName == "Assembly-CSharp.csproj" || fileName == "Assembly-CSharp-firstpass.csproj")
+ {
+ string content = File.ReadAllText(csprojFile);
+
+ if (!content.Contains("UnityEditorOnlyAnalyzer.dll"))
+ {
+ // Bug fix: Tìm "" không có dấu cách
+ int lastProjectTag = content.LastIndexOf("");
+ if (lastProjectTag >= 0)
+ {
+ string analyzerInclude = $@"
+
+
+";
+
+ content = content.Substring(0, lastProjectTag) + analyzerInclude;
+ File.WriteAllText(csprojFile, content);
+ anyModified = true;
+ Debug.Log($"[UnityEditorOnlyAnalyzer] ✅ Added analyzer to {fileName} (fallback method)");
+ }
+ }
+ }
+ }
+
+ if (anyModified)
+ {
+ Debug.Log("[UnityEditorOnlyAnalyzer] ✅ Analyzer added to .csproj files! Please reload your IDE.");
+ }
+ }
+}
+
+///
+/// Menu item để trigger thủ công việc thêm analyzer
+///
+public class UnityEditorOnlyAnalyzerMenu
+{
+ [MenuItem("Tools/Unity Editor Only Analyzer/Add Analyzer to Projects")]
+ public static void AddAnalyzerManually()
+ {
+ AddAnalyzerPostprocessor.AddAnalyzerToProjects();
+ }
+
+ [MenuItem("Tools/Unity Editor Only Analyzer/Regenerate Project Files")]
+ public static void RegenerateProjectFiles()
+ {
+ // Trigger Unity regenerate .csproj files
+ UnityEditorInternal.InternalEditorUtility.OpenFileAtLineExternal("", 0);
+ AssetDatabase.Refresh();
+ Debug.Log("[UnityEditorOnlyAnalyzer] Project files regeneration triggered. Check Console for analyzer messages.");
+ }
+}
+#endif
diff --git a/Assets/Editor/AddAnalyzerPostprocessor.cs.meta b/Assets/Editor/AddAnalyzerPostprocessor.cs.meta
new file mode 100644
index 0000000000..bb0cd62190
--- /dev/null
+++ b/Assets/Editor/AddAnalyzerPostprocessor.cs.meta
@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: f4597c784f3bab545bcae652cd8541d9
\ No newline at end of file
diff --git a/Assets/ModelRenderer/Art/Gfx/gfx/策划联入/人物技能/击中/金钟罩击中.prefab b/Assets/ModelRenderer/Art/Gfx/gfx/策划联入/人物技能/击中/金钟罩击中.prefab
index 0b37cc7274..dcea6356d1 100644
--- a/Assets/ModelRenderer/Art/Gfx/gfx/策划联入/人物技能/击中/金钟罩击中.prefab
+++ b/Assets/ModelRenderer/Art/Gfx/gfx/策划联入/人物技能/击中/金钟罩击中.prefab
@@ -50,7 +50,7 @@ ParticleSystem:
ringBufferMode: 0
ringBufferLoopRange: {x: 0, y: 1}
emitterVelocityMode: 1
- looping: 1
+ looping: 0
prewarm: 0
playOnAwake: 1
useUnscaledTime: 0
@@ -4883,7 +4883,7 @@ ParticleSystem:
ringBufferMode: 0
ringBufferLoopRange: {x: 0, y: 1}
emitterVelocityMode: 1
- looping: 1
+ looping: 0
prewarm: 0
playOnAwake: 1
useUnscaledTime: 0
@@ -9774,7 +9774,7 @@ ParticleSystem:
ringBufferMode: 0
ringBufferLoopRange: {x: 0, y: 1}
emitterVelocityMode: 1
- looping: 1
+ looping: 0
prewarm: 0
playOnAwake: 1
useUnscaledTime: 0
diff --git a/Assets/ModelRenderer/Art/Models/models/weapons/人物/刀剑/双手双剑/子母剑/子母剑_右.prefab b/Assets/ModelRenderer/Art/Models/models/weapons/人物/刀剑/双手双剑/子母剑/子母剑_右.prefab
index a714c71c4e..66da39859d 100644
--- a/Assets/ModelRenderer/Art/Models/models/weapons/人物/刀剑/双手双剑/子母剑/子母剑_右.prefab
+++ b/Assets/ModelRenderer/Art/Models/models/weapons/人物/刀剑/双手双剑/子母剑/子母剑_右.prefab
@@ -26,13 +26,13 @@ Transform:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7683706845393114874}
serializedVersion: 2
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
+ m_LocalRotation: {x: 0, y: 0.7071068, z: 0, w: 0.7071068}
+ m_LocalPosition: {x: 0.365, y: -0.002, z: -0.002}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+ m_LocalEulerAnglesHint: {x: 0, y: 90, z: 0}
--- !u!33 &2133889840078759797
MeshFilter:
m_ObjectHideFlags: 0
diff --git a/Assets/ModelRenderer/Art/Models/models/weapons/人物/刀剑/双手双剑/子母剑/子母剑_左.prefab b/Assets/ModelRenderer/Art/Models/models/weapons/人物/刀剑/双手双剑/子母剑/子母剑_左.prefab
index 6a2822b6ee..6954966b5d 100644
--- a/Assets/ModelRenderer/Art/Models/models/weapons/人物/刀剑/双手双剑/子母剑/子母剑_左.prefab
+++ b/Assets/ModelRenderer/Art/Models/models/weapons/人物/刀剑/双手双剑/子母剑/子母剑_左.prefab
@@ -26,13 +26,13 @@ Transform:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1062321236472470772}
serializedVersion: 2
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
+ m_LocalRotation: {x: 0, y: 0.7071068, z: 0, w: 0.7071068}
+ m_LocalPosition: {x: 0.365, y: -0.002, z: -0.002}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+ m_LocalEulerAnglesHint: {x: 0, y: 90, z: 0}
--- !u!33 &3655013707296471465
MeshFilter:
m_ObjectHideFlags: 0
diff --git a/Assets/ModelRenderer/Art/Models/models/weapons/人物/斧锤/双手双斧/闪华斧/闪华斧.prefab b/Assets/ModelRenderer/Art/Models/models/weapons/人物/斧锤/双手双斧/闪华斧/闪华斧.prefab
index 29ca14ed5c..adb24198a2 100644
--- a/Assets/ModelRenderer/Art/Models/models/weapons/人物/斧锤/双手双斧/闪华斧/闪华斧.prefab
+++ b/Assets/ModelRenderer/Art/Models/models/weapons/人物/斧锤/双手双斧/闪华斧/闪华斧.prefab
@@ -26,13 +26,13 @@ Transform:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3330708356810309571}
serializedVersion: 2
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
+ m_LocalRotation: {x: 0, y: 0.7071068, z: 0, w: 0.7071068}
+ m_LocalPosition: {x: 0.388, y: -0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+ m_LocalEulerAnglesHint: {x: 0, y: 90, z: 0}
--- !u!33 &666975227472843166
MeshFilter:
m_ObjectHideFlags: 0
diff --git a/Assets/PerfectWorld/Prefab/UI/MessageBox.prefab b/Assets/PerfectWorld/Prefab/UI/MessageBox.prefab
index ac34a8df7b..824b9eab6e 100644
--- a/Assets/PerfectWorld/Prefab/UI/MessageBox.prefab
+++ b/Assets/PerfectWorld/Prefab/UI/MessageBox.prefab
@@ -620,7 +620,7 @@ GameObject:
- component: {fileID: 8250962023850685786}
- component: {fileID: 7766051278568089760}
m_Layer: 5
- m_Name: ButtonOk
+ m_Name: ButtonYes
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
@@ -927,7 +927,7 @@ MonoBehaviour:
imageProgress: {fileID: 0}
titleText: {fileID: 5031655611580643013}
messageText: {fileID: 7448521238108099750}
- okButton: {fileID: 7766051278568089760}
+ _yesButton: {fileID: 7766051278568089760}
_noButton: {fileID: 7010901635634620631}
_closeButton: {fileID: 482550456836939169}
--- !u!1 &5664175764923475105
diff --git a/Assets/PerfectWorld/Prefab/UI/PlayerOptionPopup.prefab b/Assets/PerfectWorld/Prefab/UI/PlayerOptionPopup.prefab
index d432d82ba0..c71763bd99 100644
--- a/Assets/PerfectWorld/Prefab/UI/PlayerOptionPopup.prefab
+++ b/Assets/PerfectWorld/Prefab/UI/PlayerOptionPopup.prefab
@@ -509,7 +509,7 @@ MonoBehaviour:
m_PressedTrigger: Pressed
m_SelectedTrigger: Selected
m_DisabledTrigger: Disabled
- m_Interactable: 0
+ m_Interactable: 1
m_TargetGraphic: {fileID: 3492245093881047436}
m_OnClick:
m_PersistentCalls:
diff --git a/Assets/PerfectWorld/Prefab/UIManager.prefab b/Assets/PerfectWorld/Prefab/UIManager.prefab
index b445272f96..7dead6e323 100644
--- a/Assets/PerfectWorld/Prefab/UIManager.prefab
+++ b/Assets/PerfectWorld/Prefab/UIManager.prefab
@@ -774,6 +774,96 @@ MonoBehaviour:
m_hasFontAssetChanged: 0
m_baseMaterial: {fileID: 0}
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
+--- !u!1 &613919380239545636
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 7289690895179691343}
+ - component: {fileID: 690144092504553638}
+ - component: {fileID: 8175991538683025488}
+ - component: {fileID: 7195446286131223763}
+ m_Layer: 5
+ m_Name: Background
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!224 &7289690895179691343
+RectTransform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 613919380239545636}
+ 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: 5747822187000379196}
+ m_Father: {fileID: 5798497331256291745}
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+ m_AnchorMin: {x: 0, y: 1}
+ m_AnchorMax: {x: 0, y: 1}
+ m_AnchoredPosition: {x: 10, y: -10}
+ m_SizeDelta: {x: 20, y: 20}
+ m_Pivot: {x: 0.5, y: 0.5}
+--- !u!222 &690144092504553638
+CanvasRenderer:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 613919380239545636}
+ m_CullTransparentMesh: 1
+--- !u!114 &8175991538683025488
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 613919380239545636}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
+ m_Material: {fileID: 0}
+ m_Color: {r: 1, g: 1, b: 1, a: 1}
+ m_RaycastTarget: 1
+ m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+ m_Maskable: 1
+ m_OnCullStateChanged:
+ m_PersistentCalls:
+ m_Calls: []
+ m_Sprite: {fileID: 10913, guid: 0000000000000000f000000000000000, type: 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 &7195446286131223763
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 613919380239545636}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: 31a19414c41e5ae4aae2af33fee712f6, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
+ m_ShowMaskGraphic: 1
--- !u!1 &649076494997171084
GameObject:
m_ObjectHideFlags: 0
@@ -910,6 +1000,168 @@ MonoBehaviour:
m_hasFontAssetChanged: 0
m_baseMaterial: {fileID: 0}
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
+--- !u!1 &659277667126742134
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 1505082503590519222}
+ - component: {fileID: 2952576131963749004}
+ - component: {fileID: 3464748071021900582}
+ - component: {fileID: 2027788820829355354}
+ m_Layer: 5
+ m_Name: Panel (1)
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!224 &1505082503590519222
+RectTransform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 659277667126742134}
+ 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: 5798497331256291745}
+ m_Father: {fileID: 2907261990866691440}
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+ m_AnchorMin: {x: 0, y: 1}
+ m_AnchorMax: {x: 0, y: 1}
+ m_AnchoredPosition: {x: 133.1923, y: -138.03845}
+ m_SizeDelta: {x: 0, y: 11}
+ m_Pivot: {x: 0, y: 0.5}
+--- !u!222 &2952576131963749004
+CanvasRenderer:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 659277667126742134}
+ m_CullTransparentMesh: 1
+--- !u!114 &3464748071021900582
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 659277667126742134}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: 30649d3a9faa99c48a7b1166b86bf2a0, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
+ m_Padding:
+ m_Left: 0
+ m_Right: 0
+ m_Top: 0
+ m_Bottom: 0
+ m_ChildAlignment: 0
+ m_Spacing: 25
+ m_ChildForceExpandWidth: 1
+ m_ChildForceExpandHeight: 1
+ m_ChildControlWidth: 0
+ m_ChildControlHeight: 0
+ m_ChildScaleWidth: 0
+ m_ChildScaleHeight: 0
+ m_ReverseArrangement: 0
+--- !u!114 &2027788820829355354
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 659277667126742134}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: 3245ec927659c4140ac4f8d17403cc18, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
+ m_HorizontalFit: 2
+ m_VerticalFit: 0
+--- !u!1 &706528413708330951
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 5196010413898095880}
+ - component: {fileID: 6965363531247653623}
+ - component: {fileID: 6091427522402735754}
+ m_Layer: 0
+ m_Name: WarningIcon
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!224 &5196010413898095880
+RectTransform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 706528413708330951}
+ 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: 3233441867675090637}
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+ m_AnchorMin: {x: 0, y: 1}
+ m_AnchorMax: {x: 0, y: 1}
+ m_AnchoredPosition: {x: 95.5, y: -30}
+ m_SizeDelta: {x: 191, y: 60}
+ m_Pivot: {x: 0.5, y: 0.5}
+--- !u!222 &6965363531247653623
+CanvasRenderer:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 706528413708330951}
+ m_CullTransparentMesh: 1
+--- !u!114 &6091427522402735754
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 706528413708330951}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
+ m_Material: {fileID: 0}
+ m_Color: {r: 1, g: 1, b: 1, a: 1}
+ m_RaycastTarget: 0
+ m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+ m_Maskable: 1
+ m_OnCullStateChanged:
+ m_PersistentCalls:
+ m_Calls: []
+ m_Sprite: {fileID: 21300000, guid: b2f1cd3ee517556479672deef3004b2d, type: 3}
+ m_Type: 0
+ m_PreserveAspect: 0
+ m_FillCenter: 1
+ m_FillMethod: 4
+ m_FillAmount: 1
+ m_FillClockwise: 1
+ m_FillOrigin: 0
+ m_UseSpriteMesh: 0
+ m_PixelsPerUnitMultiplier: 1
--- !u!1 &806379414455135824
GameObject:
m_ObjectHideFlags: 0
@@ -2292,14 +2544,13 @@ RectTransform:
- {fileID: 9056141770234008732}
- {fileID: 6541409353547558602}
- {fileID: 2907261990866691440}
+ - {fileID: 5196010413898095880}
- {fileID: 3483809415181351540}
- {fileID: 7451658084820611230}
- {fileID: 7749074831901819156}
- {fileID: 5949267495910746152}
- - {fileID: 4633732041680916750}
- - {fileID: 3045057319077202999}
- - {fileID: 1801315025016986229}
- - {fileID: 6551985120193569788}
+ - {fileID: 9121369084142034904}
+ - {fileID: 1416757586547742942}
m_Father: {fileID: 2780428059708698453}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
@@ -2683,144 +2934,6 @@ MonoBehaviour:
m_hasFontAssetChanged: 0
m_baseMaterial: {fileID: 0}
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
---- !u!1 &2697130145581150145
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 4003332200156938686}
- - component: {fileID: 4074076591324235108}
- - component: {fileID: 5717971096408508686}
- m_Layer: 0
- m_Name: Text (TMP)
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!224 &4003332200156938686
-RectTransform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 2697130145581150145}
- 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: 3045057319077202999}
- 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 &4074076591324235108
-CanvasRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 2697130145581150145}
- m_CullTransparentMesh: 1
---- !u!114 &5717971096408508686
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 2697130145581150145}
- 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: 'TeamList
-
-'
- 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: 4281479730
- m_fontColor: {r: 0.19607843, g: 0.19607843, b: 0.19607843, 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: 21.28
- m_fontSizeBase: 21.28
- m_fontWeight: 400
- m_enableAutoSizing: 0
- m_fontSizeMin: 18
- m_fontSizeMax: 72
- m_fontStyle: 1
- m_HorizontalAlignment: 2
- m_VerticalAlignment: 512
- m_textAlignment: 65535
- m_characterSpacing: 0
- m_wordSpacing: 0
- m_lineSpacing: 0
- m_lineSpacingMax: 0
- m_paragraphSpacing: 0
- m_charWidthMaxAdj: 0
- m_TextWrappingMode: 1
- m_wordWrappingRatios: 0.4
- m_overflowMode: 0
- m_linkedTextComponent: {fileID: 0}
- parentLinkedComponent: {fileID: 0}
- m_enableKerning: 0
- m_ActiveFontFeatures: 6e72656b
- m_enableExtraPadding: 0
- checkPaddingRequired: 0
- m_isRichText: 1
- m_EmojiFallbackSupport: 1
- m_parseCtrlCharacters: 1
- m_isOrthographic: 1
- m_isCullingEnabled: 0
- m_horizontalMapping: 0
- m_verticalMapping: 0
- m_uvLineOffset: 0
- m_geometrySortingOrder: 0
- m_IsTextObjectScaleStatic: 0
- m_VertexBufferAutoSizeReduction: 0
- m_useMaxVisibleDescender: 1
- m_pageToDisplay: 1
- m_margin: {x: 0, y: 0, z: 0, w: 0}
- m_isUsingLegacyAnimationComponent: 0
- m_isVolumetricText: 0
- m_hasFontAssetChanged: 0
- m_baseMaterial: {fileID: 0}
- m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
--- !u!1 &2776183232214485049
GameObject:
m_ObjectHideFlags: 0
@@ -3759,7 +3872,81 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
inputField: {fileID: 9217902013627304316}
- sendButton: {fileID: 0}
+--- !u!1 &3409671269413610538
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 1850256271896360758}
+ - component: {fileID: 1625775608542215426}
+ - component: {fileID: 3281637513634336494}
+ m_Layer: 5
+ m_Name: Checkmark
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!224 &1850256271896360758
+RectTransform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 3409671269413610538}
+ 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: 8192498249288210842}
+ 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: 0}
+ m_SizeDelta: {x: 20, y: 20}
+ m_Pivot: {x: 0.5, y: 0.5}
+--- !u!222 &1625775608542215426
+CanvasRenderer:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 3409671269413610538}
+ m_CullTransparentMesh: 1
+--- !u!114 &3281637513634336494
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 3409671269413610538}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
+ m_Material: {fileID: 0}
+ m_Color: {r: 1, g: 1, b: 1, a: 1}
+ m_RaycastTarget: 1
+ m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+ m_Maskable: 1
+ m_OnCullStateChanged:
+ m_PersistentCalls:
+ m_Calls: []
+ m_Sprite: {fileID: -2152444580018807177, guid: 7c25a5fa6c0f21a4293b99a5a43b5441, type: 3}
+ m_Type: 0
+ m_PreserveAspect: 0
+ m_FillCenter: 1
+ m_FillMethod: 4
+ m_FillAmount: 1
+ m_FillClockwise: 1
+ m_FillOrigin: 0
+ m_UseSpriteMesh: 0
+ m_PixelsPerUnitMultiplier: 1
--- !u!1 &3640198580623993119
GameObject:
m_ObjectHideFlags: 0
@@ -4476,6 +4663,96 @@ MonoBehaviour:
m_PersistentCalls:
m_Calls: []
m_IsOn: 1
+--- !u!1 &4566977944242119824
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 8192498249288210842}
+ - component: {fileID: 3842594147762699738}
+ - component: {fileID: 4927233417060385840}
+ - component: {fileID: 5022165723285944668}
+ m_Layer: 5
+ m_Name: Background
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!224 &8192498249288210842
+RectTransform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 4566977944242119824}
+ 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: 1850256271896360758}
+ m_Father: {fileID: 3773110008012193810}
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+ m_AnchorMin: {x: 0, y: 1}
+ m_AnchorMax: {x: 0, y: 1}
+ m_AnchoredPosition: {x: 10, y: -10}
+ m_SizeDelta: {x: 20, y: 20}
+ m_Pivot: {x: 0.5, y: 0.5}
+--- !u!222 &3842594147762699738
+CanvasRenderer:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 4566977944242119824}
+ m_CullTransparentMesh: 1
+--- !u!114 &4927233417060385840
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 4566977944242119824}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
+ m_Material: {fileID: 0}
+ m_Color: {r: 1, g: 1, b: 1, a: 1}
+ m_RaycastTarget: 1
+ m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+ m_Maskable: 1
+ m_OnCullStateChanged:
+ m_PersistentCalls:
+ m_Calls: []
+ m_Sprite: {fileID: 10913, guid: 0000000000000000f000000000000000, type: 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 &5022165723285944668
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 4566977944242119824}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: 31a19414c41e5ae4aae2af33fee712f6, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
+ m_ShowMaskGraphic: 1
--- !u!1 &4656111575523843201
GameObject:
m_ObjectHideFlags: 0
@@ -4612,6 +4889,91 @@ MonoBehaviour:
m_hasFontAssetChanged: 0
m_baseMaterial: {fileID: 0}
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
+--- !u!1 &4870054906152145333
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 5798497331256291745}
+ - component: {fileID: 3469126208788821280}
+ m_Layer: 5
+ m_Name: BuffIconTemplate
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!224 &5798497331256291745
+RectTransform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 4870054906152145333}
+ 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: 7289690895179691343}
+ m_Father: {fileID: 1505082503590519222}
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+ m_AnchorMin: {x: 0, y: 0}
+ m_AnchorMax: {x: 0, y: 0}
+ m_AnchoredPosition: {x: 0, y: 0}
+ m_SizeDelta: {x: 20, y: 20}
+ m_Pivot: {x: 0.5, y: 0.5}
+--- !u!114 &3469126208788821280
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 4870054906152145333}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: 9085046f02f69544eb97fd06b6048fe2, 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: 0
+ m_TargetGraphic: {fileID: 8175991538683025488}
+ toggleTransition: 1
+ graphic: {fileID: 886384831200045356}
+ m_Group: {fileID: 0}
+ onValueChanged:
+ m_PersistentCalls:
+ m_Calls: []
+ m_IsOn: 1
--- !u!1 &5137013593162142802
GameObject:
m_ObjectHideFlags: 0
@@ -4939,6 +5301,91 @@ MonoBehaviour:
m_OnClick:
m_PersistentCalls:
m_Calls: []
+--- !u!1 &5417864904386168706
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 3773110008012193810}
+ - component: {fileID: 8469410254513498276}
+ m_Layer: 5
+ m_Name: BuffIconTemplate
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!224 &3773110008012193810
+RectTransform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 5417864904386168706}
+ 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: 8192498249288210842}
+ m_Father: {fileID: 5191021986578083479}
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+ m_AnchorMin: {x: 0, y: 0}
+ m_AnchorMax: {x: 0, y: 0}
+ m_AnchoredPosition: {x: 0, y: 0}
+ m_SizeDelta: {x: 20, y: 20}
+ m_Pivot: {x: 0.5, y: 0.5}
+--- !u!114 &8469410254513498276
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 5417864904386168706}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: 9085046f02f69544eb97fd06b6048fe2, 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: 0
+ m_TargetGraphic: {fileID: 4927233417060385840}
+ toggleTransition: 1
+ graphic: {fileID: 3281637513634336494}
+ m_Group: {fileID: 0}
+ onValueChanged:
+ m_PersistentCalls:
+ m_Calls: []
+ m_IsOn: 1
--- !u!1 &5490291313877083687
GameObject:
m_ObjectHideFlags: 0
@@ -5686,144 +6133,6 @@ MonoBehaviour:
m_hasFontAssetChanged: 0
m_baseMaterial: {fileID: 0}
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
---- !u!1 &5804481939490819770
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 3896779004240998762}
- - component: {fileID: 432590474551140442}
- - component: {fileID: 3984354575793935746}
- m_Layer: 0
- m_Name: Text (TMP)
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!224 &3896779004240998762
-RectTransform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 5804481939490819770}
- 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: 4633732041680916750}
- 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 &432590474551140442
-CanvasRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 5804481939490819770}
- m_CullTransparentMesh: 1
---- !u!114 &3984354575793935746
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 5804481939490819770}
- 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: 'TeamList
-
-'
- 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: 4281479730
- m_fontColor: {r: 0.19607843, g: 0.19607843, b: 0.19607843, 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: 21.28
- m_fontSizeBase: 21.28
- m_fontWeight: 400
- m_enableAutoSizing: 0
- m_fontSizeMin: 18
- m_fontSizeMax: 72
- m_fontStyle: 1
- m_HorizontalAlignment: 2
- m_VerticalAlignment: 512
- m_textAlignment: 65535
- m_characterSpacing: 0
- m_wordSpacing: 0
- m_lineSpacing: 0
- m_lineSpacingMax: 0
- m_paragraphSpacing: 0
- m_charWidthMaxAdj: 0
- m_TextWrappingMode: 1
- m_wordWrappingRatios: 0.4
- m_overflowMode: 0
- m_linkedTextComponent: {fileID: 0}
- parentLinkedComponent: {fileID: 0}
- m_enableKerning: 0
- m_ActiveFontFeatures: 6e72656b
- m_enableExtraPadding: 0
- checkPaddingRequired: 0
- m_isRichText: 1
- m_EmojiFallbackSupport: 1
- m_parseCtrlCharacters: 1
- m_isOrthographic: 1
- m_isCullingEnabled: 0
- m_horizontalMapping: 0
- m_verticalMapping: 0
- m_uvLineOffset: 0
- m_geometrySortingOrder: 0
- m_IsTextObjectScaleStatic: 0
- m_VertexBufferAutoSizeReduction: 0
- m_useMaxVisibleDescender: 1
- m_pageToDisplay: 1
- m_margin: {x: 0, y: 0, z: 0, w: 0}
- m_isUsingLegacyAnimationComponent: 0
- m_isVolumetricText: 0
- m_hasFontAssetChanged: 0
- m_baseMaterial: {fileID: 0}
- m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
--- !u!1 &5885931642767984348
GameObject:
m_ObjectHideFlags: 0
@@ -6333,139 +6642,6 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
m_ShowMaskGraphic: 1
---- !u!1 &6325511248940727398
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 3045057319077202999}
- - component: {fileID: 162626341667579305}
- - component: {fileID: 8499852562167418146}
- - component: {fileID: 1152087078303231916}
- m_Layer: 0
- m_Name: team_list_btn
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!224 &3045057319077202999
-RectTransform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 6325511248940727398}
- 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: 4003332200156938686}
- m_Father: {fileID: 3233441867675090637}
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
- m_AnchorMin: {x: 0, y: 0.5}
- m_AnchorMax: {x: 0, y: 0.5}
- m_AnchoredPosition: {x: 63.289795, y: 128.1304}
- m_SizeDelta: {x: 101.855, y: 57.3622}
- m_Pivot: {x: 0.5, y: 0.5}
---- !u!222 &162626341667579305
-CanvasRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 6325511248940727398}
- m_CullTransparentMesh: 1
---- !u!114 &8499852562167418146
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 6325511248940727398}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_Material: {fileID: 0}
- m_Color: {r: 1, g: 1, b: 1, a: 1}
- m_RaycastTarget: 1
- m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
- m_Maskable: 1
- m_OnCullStateChanged:
- m_PersistentCalls:
- m_Calls: []
- m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0}
- m_Type: 1
- m_PreserveAspect: 0
- m_FillCenter: 1
- m_FillMethod: 4
- m_FillAmount: 1
- m_FillClockwise: 1
- m_FillOrigin: 0
- m_UseSpriteMesh: 0
- m_PixelsPerUnitMultiplier: 1
---- !u!114 &1152087078303231916
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 6325511248940727398}
- 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: 8499852562167418146}
- m_OnClick:
- m_PersistentCalls:
- m_Calls:
- - m_Target: {fileID: 1890210201668811196}
- m_TargetAssemblyTypeName: CECUIManager, Assembly-CSharp
- m_MethodName: ShowUI
- m_Mode: 5
- m_Arguments:
- m_ObjectArgument: {fileID: 0}
- m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
- m_IntArgument: 0
- m_FloatArgument: 0
- m_StringArgument: Win_TeamMain
- m_BoolArgument: 0
- m_CallState: 2
--- !u!1 &6470418459643444397
GameObject:
m_ObjectHideFlags: 0
@@ -6722,7 +6898,7 @@ MonoBehaviour:
m_hasFontAssetChanged: 0
m_baseMaterial: {fileID: 0}
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
---- !u!1 &6647846787028180792
+--- !u!1 &6631939314334477079
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
@@ -6730,55 +6906,53 @@ GameObject:
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- - component: {fileID: 4633732041680916750}
- - component: {fileID: 1947094226586639141}
- - component: {fileID: 3855216381802363264}
- - component: {fileID: 2959558982813704450}
+ - component: {fileID: 4956381234499428555}
+ - component: {fileID: 1356460769230622399}
+ - component: {fileID: 9053880274918013220}
m_Layer: 0
- m_Name: team_list_btn
+ m_Name: Text (TMP)
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
---- !u!224 &4633732041680916750
+--- !u!224 &4956381234499428555
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 6647846787028180792}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+ m_GameObject: {fileID: 6631939314334477079}
+ 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: 3896779004240998762}
- m_Father: {fileID: 3233441867675090637}
+ m_Children: []
+ m_Father: {fileID: 9121369084142034904}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
- m_AnchorMin: {x: 0, y: 0.5}
- m_AnchorMax: {x: 0, y: 0.5}
- m_AnchoredPosition: {x: 63.289795, y: 128.1304}
- m_SizeDelta: {x: 101.855, y: 57.3622}
+ 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 &1947094226586639141
+--- !u!222 &1356460769230622399
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 6647846787028180792}
+ m_GameObject: {fileID: 6631939314334477079}
m_CullTransparentMesh: 1
---- !u!114 &3855216381802363264
+--- !u!114 &9053880274918013220
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 6647846787028180792}
+ m_GameObject: {fileID: 6631939314334477079}
m_Enabled: 1
m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
+ m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
@@ -6789,60 +6963,79 @@ MonoBehaviour:
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
- m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0}
- m_Type: 1
- m_PreserveAspect: 0
- m_FillCenter: 1
- m_FillMethod: 4
- m_FillAmount: 1
- m_FillClockwise: 1
- m_FillOrigin: 0
- m_UseSpriteMesh: 0
- m_PixelsPerUnitMultiplier: 1
---- !u!114 &2959558982813704450
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 6647846787028180792}
- 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: 3855216381802363264}
- m_OnClick:
- m_PersistentCalls:
- m_Calls: []
+ m_text: 'TeamList
+
+'
+ 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: 4281479730
+ m_fontColor: {r: 0.19607843, g: 0.19607843, b: 0.19607843, 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: 21.28
+ m_fontSizeBase: 21.28
+ m_fontWeight: 400
+ m_enableAutoSizing: 0
+ m_fontSizeMin: 18
+ m_fontSizeMax: 72
+ m_fontStyle: 1
+ m_HorizontalAlignment: 2
+ m_VerticalAlignment: 512
+ m_textAlignment: 65535
+ m_characterSpacing: 0
+ m_wordSpacing: 0
+ m_lineSpacing: 0
+ m_lineSpacingMax: 0
+ m_paragraphSpacing: 0
+ m_charWidthMaxAdj: 0
+ m_TextWrappingMode: 1
+ m_wordWrappingRatios: 0.4
+ m_overflowMode: 0
+ m_linkedTextComponent: {fileID: 0}
+ parentLinkedComponent: {fileID: 0}
+ m_enableKerning: 0
+ m_ActiveFontFeatures: 6e72656b
+ m_enableExtraPadding: 0
+ checkPaddingRequired: 0
+ m_isRichText: 1
+ m_EmojiFallbackSupport: 1
+ m_parseCtrlCharacters: 1
+ m_isOrthographic: 1
+ m_isCullingEnabled: 0
+ m_horizontalMapping: 0
+ m_verticalMapping: 0
+ m_uvLineOffset: 0
+ m_geometrySortingOrder: 0
+ m_IsTextObjectScaleStatic: 0
+ m_VertexBufferAutoSizeReduction: 0
+ m_useMaxVisibleDescender: 1
+ m_pageToDisplay: 1
+ m_margin: {x: 0, y: 0, z: 0, w: 0}
+ m_isUsingLegacyAnimationComponent: 0
+ m_isVolumetricText: 0
+ m_hasFontAssetChanged: 0
+ m_baseMaterial: {fileID: 0}
+ m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
--- !u!1 &6749548056585646144
GameObject:
m_ObjectHideFlags: 0
@@ -6918,6 +7111,127 @@ MonoBehaviour:
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
+--- !u!1 &6949335809637514808
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 9121369084142034904}
+ - component: {fileID: 3863452661654338700}
+ - component: {fileID: 2508677705417309257}
+ - component: {fileID: 540188344648694736}
+ m_Layer: 0
+ m_Name: team_list_btn
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!224 &9121369084142034904
+RectTransform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 6949335809637514808}
+ 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: 4956381234499428555}
+ m_Father: {fileID: 3233441867675090637}
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+ m_AnchorMin: {x: 0, y: 0.5}
+ m_AnchorMax: {x: 0, y: 0.5}
+ m_AnchoredPosition: {x: 63.289795, y: 128.1304}
+ m_SizeDelta: {x: 101.855, y: 57.3622}
+ m_Pivot: {x: 0.5, y: 0.5}
+--- !u!222 &3863452661654338700
+CanvasRenderer:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 6949335809637514808}
+ m_CullTransparentMesh: 1
+--- !u!114 &2508677705417309257
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 6949335809637514808}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
+ m_Material: {fileID: 0}
+ m_Color: {r: 1, g: 1, b: 1, a: 1}
+ m_RaycastTarget: 1
+ m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+ m_Maskable: 1
+ m_OnCullStateChanged:
+ m_PersistentCalls:
+ m_Calls: []
+ m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0}
+ m_Type: 1
+ m_PreserveAspect: 0
+ m_FillCenter: 1
+ m_FillMethod: 4
+ m_FillAmount: 1
+ m_FillClockwise: 1
+ m_FillOrigin: 0
+ m_UseSpriteMesh: 0
+ m_PixelsPerUnitMultiplier: 1
+--- !u!114 &540188344648694736
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 6949335809637514808}
+ 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: 2508677705417309257}
+ m_OnClick:
+ m_PersistentCalls:
+ m_Calls: []
--- !u!1 &6950113420985123515
GameObject:
m_ObjectHideFlags: 0
@@ -7271,7 +7585,7 @@ MonoBehaviour:
_btnTask: {fileID: 8640845703001841192}
_btnInvntory: {fileID: 7124460838393469068}
_btnTeam: {fileID: 6273023266110177064}
- _btnTeamList: {fileID: 2959558982813704450}
+ _btnTeamList: {fileID: 540188344648694736}
--- !u!1 &7329846701007506760
GameObject:
m_ObjectHideFlags: 0
@@ -7701,6 +8015,81 @@ MonoBehaviour:
serializedVersion: 2
m_Bits: 64
_target: {x: 0, y: 0, z: 0}
+--- !u!1 &7770570364241053217
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 5747822187000379196}
+ - component: {fileID: 4010750841144926585}
+ - component: {fileID: 886384831200045356}
+ m_Layer: 5
+ m_Name: Checkmark
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!224 &5747822187000379196
+RectTransform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 7770570364241053217}
+ 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: 7289690895179691343}
+ 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: 0}
+ m_SizeDelta: {x: 20, y: 20}
+ m_Pivot: {x: 0.5, y: 0.5}
+--- !u!222 &4010750841144926585
+CanvasRenderer:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 7770570364241053217}
+ m_CullTransparentMesh: 1
+--- !u!114 &886384831200045356
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 7770570364241053217}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
+ m_Material: {fileID: 0}
+ m_Color: {r: 1, g: 1, b: 1, a: 1}
+ m_RaycastTarget: 1
+ m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+ m_Maskable: 1
+ m_OnCullStateChanged:
+ m_PersistentCalls:
+ m_Calls: []
+ m_Sprite: {fileID: -2152444580018807177, guid: 7c25a5fa6c0f21a4293b99a5a43b5441, type: 3}
+ m_Type: 0
+ m_PreserveAspect: 0
+ m_FillCenter: 1
+ m_FillMethod: 4
+ m_FillAmount: 1
+ m_FillClockwise: 1
+ m_FillOrigin: 0
+ m_UseSpriteMesh: 0
+ m_PixelsPerUnitMultiplier: 1
--- !u!1 &7786113674810984593
GameObject:
m_ObjectHideFlags: 0
@@ -8236,6 +8625,93 @@ MonoBehaviour:
m_bShowAll2: 0
m_nDisplayPanels1: 0
m_nDisplayPanels2: 0
+--- !u!1 &8599704669003951618
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 5191021986578083479}
+ - component: {fileID: 7969492018491211435}
+ - component: {fileID: 6619954850633260582}
+ - component: {fileID: 8157700299204431448}
+ m_Layer: 5
+ m_Name: Panel (1)
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!224 &5191021986578083479
+RectTransform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 8599704669003951618}
+ 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: 3773110008012193810}
+ m_Father: {fileID: 2907261990866691440}
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+ m_AnchorMin: {x: 0, y: 1}
+ m_AnchorMax: {x: 0, y: 1}
+ m_AnchoredPosition: {x: 133.1923, y: -138.03845}
+ m_SizeDelta: {x: 0, y: 11}
+ m_Pivot: {x: 0, y: 0.5}
+--- !u!222 &7969492018491211435
+CanvasRenderer:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 8599704669003951618}
+ m_CullTransparentMesh: 1
+--- !u!114 &6619954850633260582
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 8599704669003951618}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: 30649d3a9faa99c48a7b1166b86bf2a0, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
+ m_Padding:
+ m_Left: 0
+ m_Right: 0
+ m_Top: 0
+ m_Bottom: 0
+ m_ChildAlignment: 0
+ m_Spacing: 25
+ m_ChildForceExpandWidth: 1
+ m_ChildForceExpandHeight: 1
+ m_ChildControlWidth: 0
+ m_ChildControlHeight: 0
+ m_ChildScaleWidth: 0
+ m_ChildScaleHeight: 0
+ m_ReverseArrangement: 0
+--- !u!114 &8157700299204431448
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 8599704669003951618}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: 3245ec927659c4140ac4f8d17403cc18, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
+ m_HorizontalFit: 2
+ m_VerticalFit: 0
--- !u!1 &8644839137304674498
GameObject:
m_ObjectHideFlags: 0
@@ -14037,236 +14513,6 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: a9e669c5ab4137449aacd686ed4d5d9f, type: 3}
m_Name:
m_EditorClassIdentifier:
---- !u!1001 &7164061422049248145
-PrefabInstance:
- m_ObjectHideFlags: 0
- serializedVersion: 2
- m_Modification:
- serializedVersion: 3
- m_TransformParent: {fileID: 3233441867675090637}
- m_Modifications:
- - target: {fileID: 1177418169026887077, guid: c3fe60ca49d530e4a9d03e185154c4f5, type: 3}
- propertyPath: m_AnchorMax.y
- value: 1
- objectReference: {fileID: 0}
- - target: {fileID: 1177418169026887077, guid: c3fe60ca49d530e4a9d03e185154c4f5, type: 3}
- propertyPath: m_AnchorMin.y
- value: 1
- objectReference: {fileID: 0}
- - target: {fileID: 1177418169026887077, guid: c3fe60ca49d530e4a9d03e185154c4f5, type: 3}
- propertyPath: m_AnchoredPosition.x
- value: 536.6
- objectReference: {fileID: 0}
- - target: {fileID: 1177418169026887077, guid: c3fe60ca49d530e4a9d03e185154c4f5, type: 3}
- propertyPath: m_AnchoredPosition.y
- value: -40
- objectReference: {fileID: 0}
- - target: {fileID: 2114068002568865089, guid: c3fe60ca49d530e4a9d03e185154c4f5, type: 3}
- propertyPath: m_SizeDelta.x
- value: 636.60004
- objectReference: {fileID: 0}
- - target: {fileID: 2193345427363373405, guid: c3fe60ca49d530e4a9d03e185154c4f5, type: 3}
- propertyPath: m_AnchorMax.y
- value: 1
- objectReference: {fileID: 0}
- - target: {fileID: 2193345427363373405, guid: c3fe60ca49d530e4a9d03e185154c4f5, type: 3}
- propertyPath: m_AnchorMin.y
- value: 1
- objectReference: {fileID: 0}
- - target: {fileID: 2193345427363373405, guid: c3fe60ca49d530e4a9d03e185154c4f5, type: 3}
- propertyPath: m_AnchoredPosition.x
- value: 327.54254
- objectReference: {fileID: 0}
- - target: {fileID: 2193345427363373405, guid: c3fe60ca49d530e4a9d03e185154c4f5, type: 3}
- propertyPath: m_AnchoredPosition.y
- value: -40.55655
- objectReference: {fileID: 0}
- - target: {fileID: 4145150215317037165, guid: c3fe60ca49d530e4a9d03e185154c4f5, type: 3}
- propertyPath: m_Pivot.x
- value: 0.5
- objectReference: {fileID: 0}
- - target: {fileID: 4145150215317037165, guid: c3fe60ca49d530e4a9d03e185154c4f5, type: 3}
- propertyPath: m_Pivot.y
- value: 0.5
- objectReference: {fileID: 0}
- - target: {fileID: 4145150215317037165, guid: c3fe60ca49d530e4a9d03e185154c4f5, type: 3}
- propertyPath: m_AnchorMax.x
- value: 1
- objectReference: {fileID: 0}
- - target: {fileID: 4145150215317037165, guid: c3fe60ca49d530e4a9d03e185154c4f5, type: 3}
- propertyPath: m_AnchorMax.y
- value: 1
- objectReference: {fileID: 0}
- - target: {fileID: 4145150215317037165, guid: c3fe60ca49d530e4a9d03e185154c4f5, type: 3}
- propertyPath: m_AnchorMin.x
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 4145150215317037165, guid: c3fe60ca49d530e4a9d03e185154c4f5, type: 3}
- propertyPath: m_AnchorMin.y
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 4145150215317037165, guid: c3fe60ca49d530e4a9d03e185154c4f5, type: 3}
- propertyPath: m_SizeDelta.x
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 4145150215317037165, guid: c3fe60ca49d530e4a9d03e185154c4f5, type: 3}
- propertyPath: m_SizeDelta.y
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 4145150215317037165, guid: c3fe60ca49d530e4a9d03e185154c4f5, type: 3}
- propertyPath: m_LocalPosition.x
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 4145150215317037165, guid: c3fe60ca49d530e4a9d03e185154c4f5, type: 3}
- propertyPath: m_LocalPosition.y
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 4145150215317037165, guid: c3fe60ca49d530e4a9d03e185154c4f5, type: 3}
- propertyPath: m_LocalPosition.z
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 4145150215317037165, guid: c3fe60ca49d530e4a9d03e185154c4f5, type: 3}
- propertyPath: m_LocalRotation.w
- value: 1
- objectReference: {fileID: 0}
- - target: {fileID: 4145150215317037165, guid: c3fe60ca49d530e4a9d03e185154c4f5, type: 3}
- propertyPath: m_LocalRotation.x
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 4145150215317037165, guid: c3fe60ca49d530e4a9d03e185154c4f5, type: 3}
- propertyPath: m_LocalRotation.y
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 4145150215317037165, guid: c3fe60ca49d530e4a9d03e185154c4f5, type: 3}
- propertyPath: m_LocalRotation.z
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 4145150215317037165, guid: c3fe60ca49d530e4a9d03e185154c4f5, type: 3}
- propertyPath: m_AnchoredPosition.x
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 4145150215317037165, guid: c3fe60ca49d530e4a9d03e185154c4f5, type: 3}
- propertyPath: m_AnchoredPosition.y
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 4145150215317037165, guid: c3fe60ca49d530e4a9d03e185154c4f5, type: 3}
- propertyPath: m_LocalEulerAnglesHint.x
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 4145150215317037165, guid: c3fe60ca49d530e4a9d03e185154c4f5, type: 3}
- propertyPath: m_LocalEulerAnglesHint.y
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 4145150215317037165, guid: c3fe60ca49d530e4a9d03e185154c4f5, type: 3}
- propertyPath: m_LocalEulerAnglesHint.z
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 5391320483290769481, guid: c3fe60ca49d530e4a9d03e185154c4f5, type: 3}
- propertyPath: m_AnchorMax.y
- value: 1
- objectReference: {fileID: 0}
- - target: {fileID: 5391320483290769481, guid: c3fe60ca49d530e4a9d03e185154c4f5, type: 3}
- propertyPath: m_AnchorMin.y
- value: 1
- objectReference: {fileID: 0}
- - target: {fileID: 5391320483290769481, guid: c3fe60ca49d530e4a9d03e185154c4f5, type: 3}
- propertyPath: m_AnchoredPosition.x
- value: 318.3
- objectReference: {fileID: 0}
- - target: {fileID: 5391320483290769481, guid: c3fe60ca49d530e4a9d03e185154c4f5, type: 3}
- propertyPath: m_AnchoredPosition.y
- value: -40
- objectReference: {fileID: 0}
- - target: {fileID: 6089726915740343573, guid: c3fe60ca49d530e4a9d03e185154c4f5, type: 3}
- propertyPath: m_SizeDelta.y
- value: 117
- objectReference: {fileID: 0}
- - target: {fileID: 6417814924206042159, guid: c3fe60ca49d530e4a9d03e185154c4f5, type: 3}
- propertyPath: m_AnchorMax.y
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 6417814924206042159, guid: c3fe60ca49d530e4a9d03e185154c4f5, type: 3}
- propertyPath: m_AnchorMin.y
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 6417814924206042159, guid: c3fe60ca49d530e4a9d03e185154c4f5, type: 3}
- propertyPath: m_AnchoredPosition.x
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 6417814924206042159, guid: c3fe60ca49d530e4a9d03e185154c4f5, type: 3}
- propertyPath: m_AnchoredPosition.y
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 6739367966453075612, guid: c3fe60ca49d530e4a9d03e185154c4f5, type: 3}
- propertyPath: m_AnchorMax.y
- value: 1
- objectReference: {fileID: 0}
- - target: {fileID: 6739367966453075612, guid: c3fe60ca49d530e4a9d03e185154c4f5, type: 3}
- propertyPath: m_AnchorMin.y
- value: 1
- objectReference: {fileID: 0}
- - target: {fileID: 6739367966453075612, guid: c3fe60ca49d530e4a9d03e185154c4f5, type: 3}
- propertyPath: m_AnchoredPosition.x
- value: 100
- objectReference: {fileID: 0}
- - target: {fileID: 6739367966453075612, guid: c3fe60ca49d530e4a9d03e185154c4f5, type: 3}
- propertyPath: m_AnchoredPosition.y
- value: -40
- objectReference: {fileID: 0}
- - target: {fileID: 6826604567124609485, guid: c3fe60ca49d530e4a9d03e185154c4f5, type: 3}
- propertyPath: m_SizeDelta.x
- value: 655.0851
- objectReference: {fileID: 0}
- - target: {fileID: 7412700196827410432, guid: c3fe60ca49d530e4a9d03e185154c4f5, type: 3}
- propertyPath: m_AnchorMax.y
- value: 1
- objectReference: {fileID: 0}
- - target: {fileID: 7412700196827410432, guid: c3fe60ca49d530e4a9d03e185154c4f5, type: 3}
- propertyPath: m_AnchorMin.y
- value: 1
- objectReference: {fileID: 0}
- - target: {fileID: 7412700196827410432, guid: c3fe60ca49d530e4a9d03e185154c4f5, type: 3}
- propertyPath: m_AnchoredPosition.x
- value: 112.28085
- objectReference: {fileID: 0}
- - target: {fileID: 7412700196827410432, guid: c3fe60ca49d530e4a9d03e185154c4f5, type: 3}
- propertyPath: m_AnchoredPosition.y
- value: -40.55655
- objectReference: {fileID: 0}
- - target: {fileID: 7959803810568030828, guid: c3fe60ca49d530e4a9d03e185154c4f5, type: 3}
- propertyPath: m_Name
- value: DlgFriendList
- objectReference: {fileID: 0}
- - target: {fileID: 7959803810568030828, guid: c3fe60ca49d530e4a9d03e185154c4f5, type: 3}
- propertyPath: m_IsActive
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 8453814530783954666, guid: c3fe60ca49d530e4a9d03e185154c4f5, type: 3}
- propertyPath: m_AnchorMax.y
- value: 1
- objectReference: {fileID: 0}
- - target: {fileID: 8453814530783954666, guid: c3fe60ca49d530e4a9d03e185154c4f5, type: 3}
- propertyPath: m_AnchorMin.y
- value: 1
- objectReference: {fileID: 0}
- - target: {fileID: 8453814530783954666, guid: c3fe60ca49d530e4a9d03e185154c4f5, type: 3}
- propertyPath: m_AnchoredPosition.x
- value: 542.80426
- objectReference: {fileID: 0}
- - target: {fileID: 8453814530783954666, guid: c3fe60ca49d530e4a9d03e185154c4f5, type: 3}
- propertyPath: m_AnchoredPosition.y
- value: -40.55655
- objectReference: {fileID: 0}
- m_RemovedComponents: []
- m_RemovedGameObjects: []
- m_AddedGameObjects: []
- m_AddedComponents: []
- m_SourcePrefab: {fileID: 100100000, guid: c3fe60ca49d530e4a9d03e185154c4f5, type: 3}
---- !u!224 &6551985120193569788 stripped
-RectTransform:
- m_CorrespondingSourceObject: {fileID: 4145150215317037165, guid: c3fe60ca49d530e4a9d03e185154c4f5, type: 3}
- m_PrefabInstance: {fileID: 7164061422049248145}
- m_PrefabAsset: {fileID: 0}
--- !u!1001 &7509275976277896982
PrefabInstance:
m_ObjectHideFlags: 0
@@ -14482,6 +14728,116 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 67fd391520cbfd44f84a1c6bb57673c0, type: 3}
m_Name:
m_EditorClassIdentifier:
+--- !u!1001 &8152930184191170387
+PrefabInstance:
+ m_ObjectHideFlags: 0
+ serializedVersion: 2
+ m_Modification:
+ serializedVersion: 3
+ m_TransformParent: {fileID: 3233441867675090637}
+ m_Modifications:
+ - target: {fileID: 7101142292773392269, guid: 2060bbc2e61f6db4590ab041243b6294, type: 3}
+ propertyPath: m_Pivot.x
+ value: 0.5
+ objectReference: {fileID: 0}
+ - target: {fileID: 7101142292773392269, guid: 2060bbc2e61f6db4590ab041243b6294, type: 3}
+ propertyPath: m_Pivot.y
+ value: 0.5
+ objectReference: {fileID: 0}
+ - target: {fileID: 7101142292773392269, guid: 2060bbc2e61f6db4590ab041243b6294, type: 3}
+ propertyPath: m_AnchorMax.x
+ value: 1
+ objectReference: {fileID: 0}
+ - target: {fileID: 7101142292773392269, guid: 2060bbc2e61f6db4590ab041243b6294, type: 3}
+ propertyPath: m_AnchorMax.y
+ value: 1
+ objectReference: {fileID: 0}
+ - target: {fileID: 7101142292773392269, guid: 2060bbc2e61f6db4590ab041243b6294, type: 3}
+ propertyPath: m_AnchorMin.x
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 7101142292773392269, guid: 2060bbc2e61f6db4590ab041243b6294, type: 3}
+ propertyPath: m_AnchorMin.y
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 7101142292773392269, guid: 2060bbc2e61f6db4590ab041243b6294, type: 3}
+ propertyPath: m_SizeDelta.x
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 7101142292773392269, guid: 2060bbc2e61f6db4590ab041243b6294, type: 3}
+ propertyPath: m_SizeDelta.y
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 7101142292773392269, guid: 2060bbc2e61f6db4590ab041243b6294, type: 3}
+ propertyPath: m_LocalPosition.x
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 7101142292773392269, guid: 2060bbc2e61f6db4590ab041243b6294, type: 3}
+ propertyPath: m_LocalPosition.y
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 7101142292773392269, guid: 2060bbc2e61f6db4590ab041243b6294, type: 3}
+ propertyPath: m_LocalPosition.z
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 7101142292773392269, guid: 2060bbc2e61f6db4590ab041243b6294, type: 3}
+ propertyPath: m_LocalRotation.w
+ value: 1
+ objectReference: {fileID: 0}
+ - target: {fileID: 7101142292773392269, guid: 2060bbc2e61f6db4590ab041243b6294, type: 3}
+ propertyPath: m_LocalRotation.x
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 7101142292773392269, guid: 2060bbc2e61f6db4590ab041243b6294, type: 3}
+ propertyPath: m_LocalRotation.y
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 7101142292773392269, guid: 2060bbc2e61f6db4590ab041243b6294, type: 3}
+ propertyPath: m_LocalRotation.z
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 7101142292773392269, guid: 2060bbc2e61f6db4590ab041243b6294, type: 3}
+ propertyPath: m_AnchoredPosition.x
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 7101142292773392269, guid: 2060bbc2e61f6db4590ab041243b6294, type: 3}
+ propertyPath: m_AnchoredPosition.y
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 7101142292773392269, guid: 2060bbc2e61f6db4590ab041243b6294, type: 3}
+ propertyPath: m_LocalEulerAnglesHint.x
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 7101142292773392269, guid: 2060bbc2e61f6db4590ab041243b6294, type: 3}
+ propertyPath: m_LocalEulerAnglesHint.y
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 7101142292773392269, guid: 2060bbc2e61f6db4590ab041243b6294, type: 3}
+ propertyPath: m_LocalEulerAnglesHint.z
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 7292124547459743165, guid: 2060bbc2e61f6db4590ab041243b6294, type: 3}
+ propertyPath: m_SizeDelta.x
+ value: 6.26355
+ objectReference: {fileID: 0}
+ - target: {fileID: 9152579472324007262, guid: 2060bbc2e61f6db4590ab041243b6294, type: 3}
+ propertyPath: m_Name
+ value: Win_TeamMain
+ objectReference: {fileID: 0}
+ - target: {fileID: 9152579472324007262, guid: 2060bbc2e61f6db4590ab041243b6294, type: 3}
+ propertyPath: m_IsActive
+ value: 0
+ objectReference: {fileID: 0}
+ m_RemovedComponents: []
+ m_RemovedGameObjects: []
+ m_AddedGameObjects: []
+ m_AddedComponents: []
+ m_SourcePrefab: {fileID: 100100000, guid: 2060bbc2e61f6db4590ab041243b6294, type: 3}
+--- !u!224 &1416757586547742942 stripped
+RectTransform:
+ m_CorrespondingSourceObject: {fileID: 7101142292773392269, guid: 2060bbc2e61f6db4590ab041243b6294, type: 3}
+ m_PrefabInstance: {fileID: 8152930184191170387}
+ m_PrefabAsset: {fileID: 0}
--- !u!1001 &8244659259478137406
PrefabInstance:
m_ObjectHideFlags: 0
@@ -15144,6 +15500,10 @@ PrefabInstance:
propertyPath: m_Name
value: HUDPlayer
objectReference: {fileID: 0}
+ - target: {fileID: 4823752405346273106, guid: 76408ccdbeb4c654291462fcff24a8c5, type: 3}
+ propertyPath: m_IsActive
+ value: 1
+ objectReference: {fileID: 0}
- target: {fileID: 5335503683694560306, guid: 76408ccdbeb4c654291462fcff24a8c5, type: 3}
propertyPath: m_Type
value: 3
@@ -15281,15 +15641,21 @@ PrefabInstance:
m_AddedGameObjects:
- targetCorrespondingSourceObject: {fileID: 6806681442789174374, guid: 76408ccdbeb4c654291462fcff24a8c5, type: 3}
insertIndex: 7
- addedObject: {fileID: 494610354563246192}
+ addedObject: {fileID: 1505082503590519222}
- targetCorrespondingSourceObject: {fileID: 6806681442789174374, guid: 76408ccdbeb4c654291462fcff24a8c5, type: 3}
insertIndex: 8
- addedObject: {fileID: 2090006027067688671}
+ addedObject: {fileID: 5191021986578083479}
- targetCorrespondingSourceObject: {fileID: 6806681442789174374, guid: 76408ccdbeb4c654291462fcff24a8c5, type: 3}
insertIndex: 9
- addedObject: {fileID: 5264098290850076161}
+ addedObject: {fileID: 494610354563246192}
- targetCorrespondingSourceObject: {fileID: 6806681442789174374, guid: 76408ccdbeb4c654291462fcff24a8c5, type: 3}
insertIndex: 10
+ addedObject: {fileID: 2090006027067688671}
+ - targetCorrespondingSourceObject: {fileID: 6806681442789174374, guid: 76408ccdbeb4c654291462fcff24a8c5, type: 3}
+ insertIndex: 11
+ addedObject: {fileID: 5264098290850076161}
+ - targetCorrespondingSourceObject: {fileID: 6806681442789174374, guid: 76408ccdbeb4c654291462fcff24a8c5, type: 3}
+ insertIndex: 12
addedObject: {fileID: 6421830357984996457}
m_AddedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: 76408ccdbeb4c654291462fcff24a8c5, type: 3}
@@ -15309,116 +15675,6 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3}
m_Name:
m_EditorClassIdentifier:
---- !u!1001 &8823639301883745784
-PrefabInstance:
- m_ObjectHideFlags: 0
- serializedVersion: 2
- m_Modification:
- serializedVersion: 3
- m_TransformParent: {fileID: 3233441867675090637}
- m_Modifications:
- - target: {fileID: 7101142292773392269, guid: 2060bbc2e61f6db4590ab041243b6294, type: 3}
- propertyPath: m_Pivot.x
- value: 0.5
- objectReference: {fileID: 0}
- - target: {fileID: 7101142292773392269, guid: 2060bbc2e61f6db4590ab041243b6294, type: 3}
- propertyPath: m_Pivot.y
- value: 0.5
- objectReference: {fileID: 0}
- - target: {fileID: 7101142292773392269, guid: 2060bbc2e61f6db4590ab041243b6294, type: 3}
- propertyPath: m_AnchorMax.x
- value: 1
- objectReference: {fileID: 0}
- - target: {fileID: 7101142292773392269, guid: 2060bbc2e61f6db4590ab041243b6294, type: 3}
- propertyPath: m_AnchorMax.y
- value: 1
- objectReference: {fileID: 0}
- - target: {fileID: 7101142292773392269, guid: 2060bbc2e61f6db4590ab041243b6294, type: 3}
- propertyPath: m_AnchorMin.x
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 7101142292773392269, guid: 2060bbc2e61f6db4590ab041243b6294, type: 3}
- propertyPath: m_AnchorMin.y
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 7101142292773392269, guid: 2060bbc2e61f6db4590ab041243b6294, type: 3}
- propertyPath: m_SizeDelta.x
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 7101142292773392269, guid: 2060bbc2e61f6db4590ab041243b6294, type: 3}
- propertyPath: m_SizeDelta.y
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 7101142292773392269, guid: 2060bbc2e61f6db4590ab041243b6294, type: 3}
- propertyPath: m_LocalPosition.x
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 7101142292773392269, guid: 2060bbc2e61f6db4590ab041243b6294, type: 3}
- propertyPath: m_LocalPosition.y
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 7101142292773392269, guid: 2060bbc2e61f6db4590ab041243b6294, type: 3}
- propertyPath: m_LocalPosition.z
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 7101142292773392269, guid: 2060bbc2e61f6db4590ab041243b6294, type: 3}
- propertyPath: m_LocalRotation.w
- value: 1
- objectReference: {fileID: 0}
- - target: {fileID: 7101142292773392269, guid: 2060bbc2e61f6db4590ab041243b6294, type: 3}
- propertyPath: m_LocalRotation.x
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 7101142292773392269, guid: 2060bbc2e61f6db4590ab041243b6294, type: 3}
- propertyPath: m_LocalRotation.y
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 7101142292773392269, guid: 2060bbc2e61f6db4590ab041243b6294, type: 3}
- propertyPath: m_LocalRotation.z
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 7101142292773392269, guid: 2060bbc2e61f6db4590ab041243b6294, type: 3}
- propertyPath: m_AnchoredPosition.x
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 7101142292773392269, guid: 2060bbc2e61f6db4590ab041243b6294, type: 3}
- propertyPath: m_AnchoredPosition.y
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 7101142292773392269, guid: 2060bbc2e61f6db4590ab041243b6294, type: 3}
- propertyPath: m_LocalEulerAnglesHint.x
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 7101142292773392269, guid: 2060bbc2e61f6db4590ab041243b6294, type: 3}
- propertyPath: m_LocalEulerAnglesHint.y
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 7101142292773392269, guid: 2060bbc2e61f6db4590ab041243b6294, type: 3}
- propertyPath: m_LocalEulerAnglesHint.z
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 7292124547459743165, guid: 2060bbc2e61f6db4590ab041243b6294, type: 3}
- propertyPath: m_SizeDelta.x
- value: 6.26355
- objectReference: {fileID: 0}
- - target: {fileID: 9152579472324007262, guid: 2060bbc2e61f6db4590ab041243b6294, type: 3}
- propertyPath: m_Name
- value: Win_TeamMain
- objectReference: {fileID: 0}
- - target: {fileID: 9152579472324007262, guid: 2060bbc2e61f6db4590ab041243b6294, type: 3}
- propertyPath: m_IsActive
- value: 0
- objectReference: {fileID: 0}
- m_RemovedComponents: []
- m_RemovedGameObjects: []
- m_AddedGameObjects: []
- m_AddedComponents: []
- m_SourcePrefab: {fileID: 100100000, guid: 2060bbc2e61f6db4590ab041243b6294, type: 3}
---- !u!224 &1801315025016986229 stripped
-RectTransform:
- m_CorrespondingSourceObject: {fileID: 7101142292773392269, guid: 2060bbc2e61f6db4590ab041243b6294, type: 3}
- m_PrefabInstance: {fileID: 8823639301883745784}
- m_PrefabAsset: {fileID: 0}
--- !u!1001 &8966214373927126746
PrefabInstance:
m_ObjectHideFlags: 0
diff --git a/Assets/PerfectWorld/Scene/Bootstrap.unity b/Assets/PerfectWorld/Scene/Bootstrap.unity
index 4dd1dfe017..db4113e554 100644
--- a/Assets/PerfectWorld/Scene/Bootstrap.unity
+++ b/Assets/PerfectWorld/Scene/Bootstrap.unity
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:0dd087950038db412bdd07208e3e3dc407a2da4ebecc8fbd49ad2246197aecdb
-size 314447
+oid sha256:47ff1377fe87865c1bdada70b8f6fee638a20879f70b84b40d62fb978aee203e
+size 325051
diff --git a/Assets/PerfectWorld/Scene/LoginScene.unity b/Assets/PerfectWorld/Scene/LoginScene.unity
index 639ee865aa..41fd65b332 100644
--- a/Assets/PerfectWorld/Scene/LoginScene.unity
+++ b/Assets/PerfectWorld/Scene/LoginScene.unity
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:8c97935b0995b6688065daf1645d0f26e8b964dd5bf92b6cd66c37c5f97b5586
-size 104077
+oid sha256:4b854fd255462f21d3b44d27526138345930a673f5c74cd2c1ca261ebd834048
+size 106212
diff --git a/Assets/PerfectWorld/Scripts/Chat.meta b/Assets/PerfectWorld/Scripts/Chat.meta
new file mode 100644
index 0000000000..f50f9c0813
--- /dev/null
+++ b/Assets/PerfectWorld/Scripts/Chat.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 2f24d310ca7b52342ab8380890ad8c0b
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/PerfectWorld/Scripts/Chat/CECPateText.cs b/Assets/PerfectWorld/Scripts/Chat/CECPateText.cs
new file mode 100644
index 0000000000..d7a5c6fbd5
--- /dev/null
+++ b/Assets/PerfectWorld/Scripts/Chat/CECPateText.cs
@@ -0,0 +1,239 @@
+using System.Collections.Generic;
+using BrewMonster.Network;
+using BrewMonster.Scripts.Managers;
+using BrewMonster.UI;
+using UnityEngine;
+
+namespace BrewMonster.Scripts.Chat
+{
+ public class CECPateText
+ {
+ protected List m_aTextStrs;
+ //protected List<> m_aEmotions;
+ //protected List- m_aItems;
+ //protected EditBoxItemSet m_ItemSet;
+
+ // Text item type
+ public enum ETextType
+ {
+ TYPE_TEXT = 0,
+ TYPE_EMOTION,
+ TYPE_BOOTHNAME,
+ }
+
+ // Text item
+ public struct ITEM
+ {
+ public int iType; // Text type
+ public int iIndex; // Index of item
+ public int iExtX; // Extent
+ public int iExtY;
+
+ public int iLine;
+
+ //A3DCOLOR clItem;
+ public Color clItem;
+ };
+
+ public int SetText(string szText,
+ bool bIncEmotion,
+ out string pstrTextConverted,
+ bool bEllipsis = true,
+ EC_IvtrItem pIvtrItem = null)
+ {
+ // Clear old content
+ Clear();
+
+ pstrTextConverted = null;
+
+ if (string.IsNullOrEmpty(szText))
+ return 0;
+
+ CECGameUIMan pGameUI =
+ EC_Game.GetGameRun().GetUIManager().GetInGameUIMan();
+
+ /*string str = pGameUI.AUI_FilterEditboxItem(
+ szText,
+ CECGameUIMan.AUI_EditboxItemMaskFilter(1 << (int)enumEICoord)
+ );
+
+ string strName;
+ A3DCOLOR clrName;
+
+ pGameUI.TransformNameColor(pIvtrItem, out strName, out clrName);
+
+ str = UnmarshalEditBoxText(str, m_ItemsSet, 0, strName, clrName);
+
+ szText = str;
+ pstrTextConverted = str;
+
+ int iAddedChar = 0;
+
+ if (!bIncEmotion)
+ {
+ int iLen = szText.Length;
+
+ if (iLen > m_iMaxLineLen)
+ {
+ string sub = szText.Substring(0, m_iMaxLineLen);
+
+ if (bEllipsis)
+ sub += "...";
+
+ CreateTextItem(sub, -1, 0);
+
+ iAddedChar = m_iMaxLineLen;
+ }
+ else
+ {
+ CreateTextItem(szText, -1, 0);
+ iAddedChar = iLen;
+ }
+ }
+ else
+ {
+ int i = 0;
+ int iStart = 0;
+ int iEnd = 0;
+ int iLenCnt = 0;
+
+ bool bTooLong = false;
+ int iLine = 0;
+
+ while (i < szText.Length)
+ {
+ char ch = szText[i];
+
+ if (IsEditboxItemCode(ch))
+ {
+ if (iEnd > iStart)
+ CreateTextItem(szText.Substring(iStart, iEnd - iStart), -1, iLine);
+
+ EditBoxItemBase pItem = m_ItemsSet.GetItemByChar(ch);
+
+ if (pItem != null)
+ {
+ if (pItem.GetType() == enumEIEmotion)
+ {
+ int nSet = 0;
+ int nIndex = 0;
+
+ UnmarshalEmotionInfo(pItem.GetInfo(), out nSet, out nIndex);
+
+ CreateEmotionItem(nSet, nIndex, iLine);
+
+ iLenCnt += 2;
+ }
+ else
+ {
+ string szName = pItem.GetName();
+
+ CreateTextItem(szName, -1, iLine, pItem.GetColor());
+
+ iLenCnt += szName.Length;
+ }
+ }
+
+ i++;
+ iStart = i;
+ iEnd = i;
+
+ goto CheckLength;
+ }
+
+ iEnd++;
+ i++;
+ iLenCnt++;
+
+ CheckLength:
+
+ if (iLenCnt > m_iMaxLineLen)
+ {
+ if (iLine + 1 >= m_iMaxLines)
+ {
+ bTooLong = true;
+ break;
+ }
+
+ if (iEnd > iStart)
+ CreateTextItem(szText.Substring(iStart, iEnd - iStart), -1, iLine);
+
+ iStart = i;
+ iLine++;
+ iLenCnt = 0;
+ }
+ }
+
+ iAddedChar = i;
+
+ if (iEnd > iStart)
+ {
+ if (bTooLong)
+ {
+ string strEnd = szText.Substring(iStart, iEnd - iStart);
+
+ if (bEllipsis)
+ strEnd += "...";
+
+ CreateTextItem(strEnd, -1, iLine);
+ }
+ else
+ {
+ CreateTextItem(szText.Substring(iStart, iEnd - iStart), -1, iLine);
+ }
+ }
+ else if (bTooLong)
+ {
+ if (bEllipsis)
+ CreateTextItem("...", -1, iLine);
+ }
+ }
+
+ // Calculate extent
+
+ m_iExtX = 0;
+ m_iExtY = 0;
+
+ int iLineExtX = 0;
+ int iLastLine = 0;
+
+ for (int i = 0; i < m_aItems.GetSize(); i++)
+ {
+ ITEM item = m_aItems[i];
+
+ if (item.iLine != iLastLine)
+ {
+ iLastLine = item.iLine;
+
+ if (m_iExtX < iLineExtX)
+ m_iExtX = iLineExtX;
+
+ iLineExtX = item.iExtX;
+ }
+ else
+ {
+ iLineExtX += item.iExtX;
+ }
+
+ if (m_iExtY < item.iExtY)
+ m_iExtY = item.iExtY;
+ }
+
+ m_iLines = iLastLine + 1;
+
+ if (m_iExtX < iLineExtX)
+ m_iExtX = iLineExtX;*/
+ //return iAddedChar;
+
+ return 0;
+ }
+
+ public void Clear()
+ {
+ m_aTextStrs.Clear();
+ /*m_aEmotions.Clear();
+ m_aItems.Clear();
+ m_ItemsSet.Clear();*/
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/PerfectWorld/Scripts/Chat/CECPateText.cs.meta b/Assets/PerfectWorld/Scripts/Chat/CECPateText.cs.meta
new file mode 100644
index 0000000000..b9484999d0
--- /dev/null
+++ b/Assets/PerfectWorld/Scripts/Chat/CECPateText.cs.meta
@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: f6eb4b59e25704044a88b0055abb0e99
\ No newline at end of file
diff --git a/Assets/PerfectWorld/Scripts/Chat/CECPlayer.cs b/Assets/PerfectWorld/Scripts/Chat/CECPlayer.cs
new file mode 100644
index 0000000000..83780b3d6c
--- /dev/null
+++ b/Assets/PerfectWorld/Scripts/Chat/CECPlayer.cs
@@ -0,0 +1,26 @@
+using BrewMonster.Scripts.Managers;
+using CSNetwork;
+
+namespace BrewMonster.Scripts.Chat
+{
+ public abstract partial class CECPlayer : CECObject
+ {
+ private CECPateText m_pPateLastWords1;
+ private CECPateText m_pPateLastWords2;
+ private CECCounter m_strLastSayCnt;
+
+ // Set last said words
+ public void SetLastSaidWords(string szWords, int nEmotionSet, EC_IvtrItem pItem)
+ {
+ if (m_pPateLastWords1 == null || m_pPateLastWords2 == null)
+ return;
+
+ string str = AUICommon.FilterEmotionSet(szWords, nEmotionSet);
+ szWords = str;
+
+ m_pPateLastWords1.SetText(szWords, true , out var newStr,true, pItem);
+ m_pPateLastWords2.Clear();
+ m_strLastSayCnt.Reset();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/PerfectWorld/Scripts/Chat/CECPlayer.cs.meta b/Assets/PerfectWorld/Scripts/Chat/CECPlayer.cs.meta
new file mode 100644
index 0000000000..26eed1206d
--- /dev/null
+++ b/Assets/PerfectWorld/Scripts/Chat/CECPlayer.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 2c109cbbaf8d4ce19a93990a5f5883f6
+timeCreated: 1772699598
\ No newline at end of file
diff --git a/Assets/PerfectWorld/Scripts/Chat/CHAT_S2C.cs b/Assets/PerfectWorld/Scripts/Chat/CHAT_S2C.cs
new file mode 100644
index 0000000000..07dbde0aed
--- /dev/null
+++ b/Assets/PerfectWorld/Scripts/Chat/CHAT_S2C.cs
@@ -0,0 +1,254 @@
+using System;
+using System.Buffers.Binary;
+using System.Runtime.InteropServices;
+using BrewMonster.Network;
+using BrewMonster.Scripts.Managers;
+using CSNetwork;
+using CSNetwork.GPDataType;
+
+namespace BrewMonster.Scripts.Chat
+{
+ struct chat_policy_parameter
+ {
+ short cmd_id;
+
+ int parameter_mask;
+ //if(parameter_mask & CHAT_PARAMETER_ROLEID) 1 int insert here
+ //if(parameter_mask & CHAT_PARAMETER_LOCALVAL0) 1 int insert here
+ //if(parameter_m ask & CHAT_PARAMETER_LOCALVAL1) 1 int insert here
+ //if(parameter_mask & CHAT_PARAMETER_LOCALVAL2) 1 int insert here
+ };
+
+ public struct chat_item_base
+ {
+ public short cmd_id;
+ }
+
+ public struct chat_equip_item
+ {
+ public short cmd_id;
+ public char where;
+ public short index;
+ }
+
+ struct chat_generalcard_collection
+ {
+ public short cmd_id;
+ public int card_id;
+ };
+
+ public static class CHAT_S2C
+ {
+ public struct chat_equip_item
+ {
+ public short cmd_id;
+ public int type;
+ public int expire_date;
+ public int proc_type;
+ public ushort content_length;
+ public byte[] content;
+
+ public int LenghtHeader()
+ {
+ return Marshal.SizeOf() + (Marshal.SizeOf() * 3) + Marshal.SizeOf();
+ }
+ }
+
+ public enum EChatS2CCommand : short
+ {
+ CHAT_EQUIP_ITEM,
+ CHAT_GENERALCARD_COLLECTION,
+ CHAT_POLICYCHAT_PARAMETER,
+ }
+
+ public static EC_IvtrItem CreateChatItem(Octets data)
+ {
+ EC_IvtrItem pIvtrItem = null;
+ if (data.Size > 0)
+ {
+ chat_item_base pInfo = GPDataTypeHelper.FromBytes(data.ByteArray);
+ if (pInfo.cmd_id == (short)EChatS2CCommand.CHAT_EQUIP_ITEM)
+ {
+ chat_equip_item pItemInfo = default;
+ var sz = pItemInfo.LenghtHeader();
+
+ if (data.Size >= sz && sz + pItemInfo.content_length == data.Size)
+ {
+ if (pItemInfo.cmd_id == (short)EChatS2CCommand.CHAT_EQUIP_ITEM)
+ {
+ pIvtrItem = EC_IvtrItem.CreateItem(pItemInfo.type, pItemInfo.expire_date, 1);
+ if (pIvtrItem != null)
+ {
+ pIvtrItem.SetProcType(pItemInfo.proc_type);
+ pIvtrItem.SetItemInfo(pItemInfo.content, pItemInfo.content_length);
+ }
+ }
+ }
+ }
+ else if (pInfo.cmd_id == (short)EChatS2CCommand.CHAT_GENERALCARD_COLLECTION)
+ {
+ chat_generalcard_collection pItemInfo =
+ GPDataTypeHelper.FromBytes(data.ByteArray);
+ if (data.Size > Marshal.SizeOf())
+ {
+ if (pItemInfo.cmd_id == (short)EChatS2CCommand.CHAT_GENERALCARD_COLLECTION)
+ {
+ pIvtrItem = EC_IvtrItem.CreateItem(pItemInfo.card_id, 0, 1);
+ if (pIvtrItem != null)
+ {
+ pIvtrItem.GetDetailDataFromLocal();
+ }
+ }
+ }
+ }
+ }
+
+ return pIvtrItem;
+ }
+
+ [System.Flags]
+ public enum ChatParameterMask
+ {
+ CHAT_PARAMETER_ROLEID = 0x00000001,
+ CHAT_PARAMETER_LOCALVAL0 = 0x00000002,
+ CHAT_PARAMETER_LOCALVAL1 = 0x00000004,
+ CHAT_PARAMETER_LOCALVAL2 = 0x00000008
+ }
+
+ public class PolicyChatParameter
+ {
+ public int role_id = -1;
+ public string name = string.Empty;
+ public ChatParameterMask parameter_mask = 0;
+
+ private int localval_0 = -1;
+ private int localval_1 = -1;
+ private int localval_2 = -1;
+
+ EC_Game g_pGame;
+
+ public bool HasRoleID()
+ {
+ return (parameter_mask & ChatParameterMask.CHAT_PARAMETER_ROLEID) != 0;
+ }
+
+ public bool HasLocalValue(int valueNum)
+ {
+ switch (valueNum)
+ {
+ case 0:
+ return (parameter_mask & ChatParameterMask.CHAT_PARAMETER_LOCALVAL0) != 0;
+ case 1:
+ return (parameter_mask & ChatParameterMask.CHAT_PARAMETER_LOCALVAL1) != 0;
+ case 2:
+ return (parameter_mask & ChatParameterMask.CHAT_PARAMETER_LOCALVAL2) != 0;
+ default:
+ return false;
+ }
+ }
+
+ public void GetNameFromServer()
+ {
+ if (role_id != -1 && HasRoleID())
+ {
+ int[] arr = new int[1] { role_id };
+ UnityGameSession.Instance.GameSession.CmdCache.SendGetPlayerBriefInfo(1, arr, 1);
+ }
+ }
+
+ public void SetLocalValue(int localValue, int id)
+ {
+ switch (id)
+ {
+ case 0:
+ localval_0 = localValue;
+ parameter_mask |= ChatParameterMask.CHAT_PARAMETER_LOCALVAL0;
+ break;
+ case 1:
+ localval_1 = localValue;
+ parameter_mask |= ChatParameterMask.CHAT_PARAMETER_LOCALVAL1;
+ break;
+ case 2:
+ localval_2 = localValue;
+ parameter_mask |= ChatParameterMask.CHAT_PARAMETER_LOCALVAL2;
+ break;
+ }
+ }
+
+ public bool TryGetLocalValue(int localVariableID, out int localVariable)
+ {
+ localVariable = -1;
+
+ if (!HasLocalValue(localVariableID))
+ return false;
+
+ switch (localVariableID)
+ {
+ case 0: localVariable = localval_0; break;
+ case 1: localVariable = localval_1; break;
+ case 2: localVariable = localval_2; break;
+ }
+
+ return true;
+ }
+
+ public bool IsNameReady()
+ {
+ return HasRoleID() ? !string.IsNullOrEmpty(name) : true;
+ }
+ }
+
+ public static PolicyChatParameter CreatPolicyChatParameter(Octets data)
+ {
+ PolicyChatParameter result = null;
+ if (data.Size >= Marshal.SizeOf(typeof(chat_item_base)))
+ {
+ chat_item_base pInfo = GPDataTypeHelper.FromBytes(data.ByteArray);
+ if (pInfo.cmd_id == (short)EChatS2CCommand.CHAT_POLICYCHAT_PARAMETER)
+ {
+ if (data.Size >= Marshal.SizeOf(typeof(chat_policy_parameter)))
+ {
+ Byte pData = GPDataTypeHelper.FromBytes(data.ByteArray,
+ Marshal.SizeOf(typeof(chat_policy_parameter)));
+ result = new PolicyChatParameter();
+ // Todo: Check logic
+ result.parameter_mask =
+ GPDataTypeHelper.FromBytes(data.ByteArray, sizeof(short));
+ /*int paraMask = result.parameter_mask;
+ if (paraMask & ChatParameterMask.CHAT_PARAMETER_ROLEID){
+ if (pData + sizeof(int) > data.end()){
+ return null;
+ }
+ result->SetRoleId(*(int*)pData);
+ pData += sizeof(int);
+ }
+ if (paraMask & ChatParameterMask.CHAT_PARAMETER_LOCALVAL0){
+ if (pData + sizeof(int) > data.end()){
+ return null;
+ }
+ result->SetLocaValue(*(int*)pData, 0);
+ pData += sizeof(int);
+ }
+ if (paraMask & ChatParameterMask.CHAT_PARAMETER_LOCALVAL1){
+ if (pData + sizeof(int) > data.end()){
+ return null;
+ }
+ result.SetLocaValue((int)pData, 1);
+ pData += sizeof(int);
+ }
+ if (paraMask & ChatParameterMask.CHAT_PARAMETER_LOCALVAL2){
+ if (pData + sizeof(int) > data.end()){
+ return null;
+ }
+ // Check logic
+ result.SetLocalValue((int)pData, 2);
+ pData += sizeof(int);
+ }*/
+ }
+ }
+ }
+
+ return result;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/PerfectWorld/Scripts/Chat/CHAT_S2C.cs.meta b/Assets/PerfectWorld/Scripts/Chat/CHAT_S2C.cs.meta
new file mode 100644
index 0000000000..48a8790ff9
--- /dev/null
+++ b/Assets/PerfectWorld/Scripts/Chat/CHAT_S2C.cs.meta
@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: f7564fa8d29f58c40a1aa0425fc0c046
\ No newline at end of file
diff --git a/Assets/PerfectWorld/Scripts/Chat/Chat_GameSession.cs b/Assets/PerfectWorld/Scripts/Chat/Chat_GameSession.cs
new file mode 100644
index 0000000000..84fce2a20f
--- /dev/null
+++ b/Assets/PerfectWorld/Scripts/Chat/Chat_GameSession.cs
@@ -0,0 +1,243 @@
+using System;
+using System.Collections.Generic;
+using BrewMonster.Network;
+using BrewMonster.Scripts.UI;
+using CSNetwork.GPDataType;
+using CSNetwork.Protocols;
+
+namespace BrewMonster.Scripts.Chat
+{
+ public static class Chat_GameSession
+ {
+ private static List m_aPendingProtocols = new();
+ private static List m_aPendingPlayers = new();
+
+ public static void AddElemForPendingProtocols(Protocol p)
+ {
+ m_aPendingProtocols.Add(p);
+ }
+
+ // Add one player's id to a buffer in order to get his name later
+ public static void AddChatPlayerID(int id)
+ {
+ if (EC_Game.GetGameRun().GetPlayerName(id, false) != null)
+ {
+ m_aPendingPlayers.Add(id);
+ }
+ }
+
+ public static bool ShouldBlockByLevel(chatmessage p)
+ {
+ int levelBlock = EC_Game.GetConfigs().GetBlackListSettings().levelBlock;
+ if (p.Srclevel > 0 && p.Srclevel < levelBlock)
+ {
+ if ((ChatChannel)p.Channel is ChatChannel.GP_CHAT_LOCAL
+ or ChatChannel.GP_CHAT_WHISPER
+ or ChatChannel.GP_CHAT_TRADE)
+ {
+ if (!EC_Game.GetGameRun().GetHostPlayer().IsOmitBlocking(p.Srcroleid))
+ {
+ // should be filted by level
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ public static bool PolicyResolver(Protocol pProtocol, chatmessage p, ref string strTemp)
+ {
+ if (IsPolicyChat(p))
+ {
+ // Todo: check logic
+ CHAT_S2C.PolicyChatParameter pPolicyChatPara = CHAT_S2C.CreatPolicyChatParameter(p.Data);
+ if (pPolicyChatPara != null && p.Data.Size > 0)
+ {
+ strTemp = ("???");
+ }
+ else
+ {
+ if (pPolicyChatPara != null && !pPolicyChatPara.IsNameReady())
+ {
+ pPolicyChatPara.GetNameFromServer();
+ m_aPendingProtocols.Add(pProtocol);
+ return false;
+ }
+
+ strTemp = CECUIHelper.PolicySpecialCharReplace(strTemp, pPolicyChatPara);
+ if (CanFormatCoordText(p))
+ {
+ //strTemp = CECUIHelper.FormatCoordText(strTemp);
+ }
+ }
+ //int strLen = strTemp.GetLength();
+ //wcsncpy(szMsg, strTemp, strLen);
+ //szMsg[strLen] = 0;
+ }
+ else
+ {
+ //AUI_ConvertChatString(strTemp, szMsg, false);
+ }
+
+ return true;
+ }
+
+ /*private void AUI_ConvertChatString(string pszChat, string pszConv, bool bName)
+ {
+ int i, nLen = 0;
+ if (pszChat != null || pszConv != null)
+ return;
+
+ pszConv[0] = 0;
+ for( i = 0; i < (int)a_strlen(pszChat); i++ )
+ {
+ if( pszChat[i] == '^' )
+ {
+ pszConv[nLen] = '^';
+ pszConv[nLen + 1] = '^';
+ nLen += 2;
+ }
+ else if( pszChat[i] == '&' )
+ {
+ pszConv[nLen] = '^';
+ pszConv[nLen + 1] = '&';
+ nLen += 2;
+ }
+ else
+ {
+ pszConv[nLen] = pszChat[i];
+ nLen++;
+ }
+ }
+ pszConv[nLen] = 0;
+ }*/
+
+ private static bool IsPolicyChat(chatmessage p)
+ {
+ bool bOK = false;
+ switch (p.Channel)
+ {
+ case (byte)ChatChannel.GP_CHAT_LOCAL: // ÃæÏò¸Ã NPC ¿É¼ûÓòÖÐËùÓÐÍæ¼Ò
+ if (p.Srcroleid == 0 || // £¨²ßÂÔº°»°Öбê¼Ç $A £©
+ ISNPCID(p.Srcroleid))
+ {
+ // £¨²ßÂÔº°»°ÖÐÎÞ±ê¼Ç £©
+ bOK = true;
+ }
+
+ break;
+ case (byte)ChatChannel.GP_CHAT_BATTLE: // ÃæÏò³ÇÕ½¸±±¾Ö¸¶¨ÕóÓª»òÈ«²¿Íæ¼Òº°»°£¨²ßÂÔº°»°Öбê¼Ç $F¡¢$T £©
+ if (p.Srcroleid == 0)
+ {
+ // Ϊ·ÀÒÔºóÓб仯£¬Ôö¼Ó´ËÅжÏ
+ bOK = true;
+ }
+
+ break;
+ case (byte)ChatChannel.GP_CHAT_BROADCAST: // ÃæÏòÈ«ÌåÔÚÏßÍæ¼Ò£¨²ßÂÔº°»°Öбê¼Ç $S £©
+ if (p.Srcroleid == 0)
+ {
+ bOK = true;
+ }
+
+ break;
+ case (byte)ChatChannel.GP_CHAT_INSTANCE
+ : // ÃæÏò¸±±¾ÖÐÍæ¼Ò£¨²ßÂÔº°»°Öбê¼Ç $I £©£¨ $X ±ê¼Çʱ p->srcroleid == 1£¬´Ëʱֻ³öÏÖÔÚÆÁÄ»ÖÐÑ룩
+ if (p.Srcroleid == 0 || p.Srcroleid == 1)
+ {
+ bOK = true;
+ }
+
+ break;
+ }
+
+ return bOK;
+ }
+
+ static bool ISNPCID(int id)
+ {
+ uint uid = (uint)id;
+ return (uid & 0x80000000) != 0 &&
+ (uid & 0x40000000) == 0;
+ }
+
+ static bool CanFormatCoordText(chatmessage p)
+ {
+ bool bOK = false;
+ switch (p.Channel)
+ {
+ case (byte)ChatChannel.GP_CHAT_LOCAL: // ÃæÏò¸Ã NPC ¿É¼ûÓòÖÐËùÓÐÍæ¼Ò
+ if (p.Srcroleid == 0 || // £¨²ßÂÔº°»°Öбê¼Ç $A £©
+ ISNPCID(p.Srcroleid))
+ {
+ // £¨²ßÂÔº°»°ÖÐÎÞ±ê¼Ç £©
+ bOK = true;
+ }
+
+ break;
+ case (byte)ChatChannel.GP_CHAT_BATTLE: // ÃæÏò³ÇÕ½¸±±¾Ö¸¶¨ÕóÓª»òÈ«²¿Íæ¼Òº°»°£¨²ßÂÔº°»°Öбê¼Ç $F¡¢$T £©
+ if (p.Srcroleid == 0)
+ {
+ // Ϊ·ÀÒÔºóÓб仯£¬Ôö¼Ó´ËÅжÏ
+ bOK = true;
+ }
+
+ break;
+ case (byte)ChatChannel.GP_CHAT_BROADCAST: // ÃæÏòÈ«ÌåÔÚÏßÍæ¼Ò£¨²ßÂÔº°»°Öбê¼Ç $S £©
+ if (p.Srcroleid == 0)
+ {
+ bOK = true;
+ }
+
+ break;
+ case (byte)ChatChannel.GP_CHAT_INSTANCE: //p->srcroleid == 1 ʱ²»½øÐÐ×ø±êµÄÌæ»»
+ if (p.Srcroleid == 0)
+ {
+ bOK = true;
+ }
+
+ break;
+ }
+
+ return bOK;
+ }
+
+ public class AUICTranslate
+ {
+ protected string m_AString = string.Empty;
+ protected string m_AWString = string.Empty;
+
+ public AUICTranslate()
+ {
+ }
+
+ public string Translate(string str)
+ {
+ // In original C++ this likely performs UI charset translation.
+ // Here we simply return the same string or store it.
+ m_AString = str;
+ return m_AString;
+ }
+
+ public string Translate(ReadOnlySpan str)
+ {
+ m_AWString = new string(str);
+ return m_AWString;
+ }
+
+ public string ReverseTranslate(string str)
+ {
+ // Reverse translation placeholder
+ m_AString = str;
+ return m_AString;
+ }
+
+ public string ReverseTranslate(ReadOnlySpan str)
+ {
+ m_AWString = new string(str);
+ return m_AWString;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/PerfectWorld/Scripts/Chat/Chat_GameSession.cs.meta b/Assets/PerfectWorld/Scripts/Chat/Chat_GameSession.cs.meta
new file mode 100644
index 0000000000..e9f0f60376
--- /dev/null
+++ b/Assets/PerfectWorld/Scripts/Chat/Chat_GameSession.cs.meta
@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: 7c774ca3c7d345e4ea0fbb7397bf1d88
\ No newline at end of file
diff --git a/Assets/PerfectWorld/Scripts/Chat/Chat_Helper.cs b/Assets/PerfectWorld/Scripts/Chat/Chat_Helper.cs
new file mode 100644
index 0000000000..678b0d3f6b
--- /dev/null
+++ b/Assets/PerfectWorld/Scripts/Chat/Chat_Helper.cs
@@ -0,0 +1,17 @@
+using UnityEngine;
+
+namespace BrewMonster.Scripts.Chat
+{
+ public static class Chat_Helper
+ {
+ public static Color32 ToColor32(uint c)
+ {
+ byte a = (byte)((c >> 24) & 0xFF);
+ byte r = (byte)((c >> 16) & 0xFF);
+ byte g = (byte)((c >> 8) & 0xFF);
+ byte b = (byte)(c & 0xFF);
+
+ return new Color32(r, g, b, a);
+ }
+ }
+}
diff --git a/Assets/PerfectWorld/Scripts/Chat/Chat_Helper.cs.meta b/Assets/PerfectWorld/Scripts/Chat/Chat_Helper.cs.meta
new file mode 100644
index 0000000000..5cea223658
--- /dev/null
+++ b/Assets/PerfectWorld/Scripts/Chat/Chat_Helper.cs.meta
@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: 5ef4426a7625eb74aa802808e2223421
\ No newline at end of file
diff --git a/Assets/PerfectWorld/Scripts/Chat/UI.meta b/Assets/PerfectWorld/Scripts/Chat/UI.meta
new file mode 100644
index 0000000000..5b95658c75
--- /dev/null
+++ b/Assets/PerfectWorld/Scripts/Chat/UI.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 3d2c00e6fd97fce4c8061a0c54327a5f
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/PerfectWorld/Scripts/Chat/UI/ChatMessageView.cs b/Assets/PerfectWorld/Scripts/Chat/UI/ChatMessageView.cs
new file mode 100644
index 0000000000..6397bb2b6d
--- /dev/null
+++ b/Assets/PerfectWorld/Scripts/Chat/UI/ChatMessageView.cs
@@ -0,0 +1,15 @@
+using TMPro;
+using UnityEngine;
+
+namespace BrewMonster.Scripts.ChatUI
+{
+ public class ChatMessageView : MonoBehaviour
+ {
+ public TextMeshProUGUI messageText;
+
+ public void Bind(string message)
+ {
+ messageText.text = message;
+ }
+ }
+}
diff --git a/Assets/PerfectWorld/Scripts/Chat/UI/ChatMessageView.cs.meta b/Assets/PerfectWorld/Scripts/Chat/UI/ChatMessageView.cs.meta
new file mode 100644
index 0000000000..96290dd492
--- /dev/null
+++ b/Assets/PerfectWorld/Scripts/Chat/UI/ChatMessageView.cs.meta
@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: 179d32c667fc2f641bdcb7afb18046b9
\ No newline at end of file
diff --git a/Assets/PerfectWorld/Scripts/Chat/UI/ChatPanelUI.cs b/Assets/PerfectWorld/Scripts/Chat/UI/ChatPanelUI.cs
new file mode 100644
index 0000000000..b40a8bf148
--- /dev/null
+++ b/Assets/PerfectWorld/Scripts/Chat/UI/ChatPanelUI.cs
@@ -0,0 +1,177 @@
+using System;
+using System.Collections.Generic;
+using CSNetwork;
+using UnityEngine;
+using UnityEngine.Pool;
+using UnityEngine.UI;
+
+namespace BrewMonster.Scripts.ChatUI
+{
+ public class ChatPanelUI : MonoBehaviour
+ {
+ [Header("UI")] public ScrollRect scrollRect;
+ public GameObject chatPanelUIGO;
+ public RectTransform content;
+ public ChatMessageView messagePrefab;
+ //public GameObject newMessageIndicator;
+
+ [Header("Config")] public int maxVisibleMessages = 30;
+ public int maxStoredMessages = 2000;
+
+ private List _messages = new();
+ private List _visibleViews = new();
+
+ private ObjectPool _pool;
+
+ private bool _userAtBottom = true;
+
+ void Awake()
+ {
+ EventBus.Subscribe(OnChatMessageReceived);
+ _pool = new ObjectPool(
+ CreateItem,
+ OnGetItem,
+ OnReleaseItem,
+ OnDestroyItem,
+ false,
+ 10,
+ 100
+ );
+
+ scrollRect.onValueChanged.AddListener(OnScrollChanged);
+ }
+
+ private void OnDestroy()
+ {
+ EventBus.Unsubscribe(OnChatMessageReceived);
+ }
+
+ private void OnChatMessageReceived(GameSession.ChatMessageEvent x)
+ {
+ ChatThreadDispatcher.Instance.Post(() =>
+ {
+ AddMessage(x.context);
+ });
+ }
+
+ ChatMessageView CreateItem()
+ {
+ var item = Instantiate(messagePrefab);
+ item.transform.SetParent(content, false);
+ return item;
+ }
+
+ void OnGetItem(ChatMessageView item)
+ {
+ item.gameObject.SetActive(true);
+ }
+
+ void OnReleaseItem(ChatMessageView item)
+ {
+ item.gameObject.SetActive(false);
+ }
+
+ void OnDestroyItem(ChatMessageView item)
+ {
+ Destroy(item.gameObject);
+ }
+
+ void OnScrollChanged(Vector2 pos)
+ {
+ _userAtBottom = scrollRect.verticalNormalizedPosition <= 0.001f;
+
+ if (_userAtBottom)
+ {
+ //newMessageIndicator.SetActive(false);
+ }
+ }
+
+ bool IsAtBottom()
+ {
+ return scrollRect.verticalNormalizedPosition <= 0.001f;
+ }
+
+ public void AddMessage(string msg)
+ {
+ _messages.Add(msg);
+
+ if (_messages.Count > maxStoredMessages)
+ _messages.RemoveAt(0);
+
+ if (!chatPanelUIGO.activeSelf)
+ return;
+
+ AddMessageView(msg);
+
+ if (_userAtBottom)
+ ScrollToBottom();
+ }
+
+ void AddMessageView(string msg)
+ {
+ var view = _pool.Get();
+ view.transform.SetParent(content, false);
+ view.transform.SetAsLastSibling();
+ view.Bind(msg);
+
+ _visibleViews.Add(view);
+
+ if (_visibleViews.Count > maxVisibleMessages)
+ {
+ var old = _visibleViews[0];
+ _visibleViews.RemoveAt(0);
+ _pool.Release(old);
+ }
+
+ Canvas.ForceUpdateCanvases();
+ }
+
+ void RefreshVisible()
+ {
+ foreach (var view in _visibleViews)
+ _pool.Release(view);
+
+ _visibleViews.Clear();
+
+ int start = Mathf.Max(0, _messages.Count - maxVisibleMessages);
+
+ for (int i = start; i < _messages.Count; i++)
+ {
+ var view = _pool.Get();
+ view.transform.SetParent(content, false);
+ view.transform.SetAsLastSibling();
+ view.Bind(_messages[i]);
+
+ _visibleViews.Add(view);
+ }
+
+ Canvas.ForceUpdateCanvases();
+ ScrollToBottom();
+ }
+
+ public void ScrollToBottom()
+ {
+ Canvas.ForceUpdateCanvases();
+ scrollRect.verticalNormalizedPosition = 0f;
+ //newMessageIndicator.SetActive(false);
+ }
+
+ public void ClearChat()
+ {
+ foreach (var view in _visibleViews)
+ _pool.Release(view);
+
+ _visibleViews.Clear();
+ _messages.Clear();
+ }
+
+ public void OnHandlerChatButton()
+ {
+ bool open = !chatPanelUIGO.activeSelf;
+ chatPanelUIGO.SetActive(open);
+
+ if (open)
+ RefreshVisible();
+ }
+ }
+}
diff --git a/Assets/PerfectWorld/Scripts/Chat/UI/ChatPanelUI.cs.meta b/Assets/PerfectWorld/Scripts/Chat/UI/ChatPanelUI.cs.meta
new file mode 100644
index 0000000000..8c8314a16a
--- /dev/null
+++ b/Assets/PerfectWorld/Scripts/Chat/UI/ChatPanelUI.cs.meta
@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: 5790dcd71bafcec4697f10b5366bec2c
\ No newline at end of file
diff --git a/Assets/PerfectWorld/Scripts/Chat/UI/ChatThreadDispatcher.cs b/Assets/PerfectWorld/Scripts/Chat/UI/ChatThreadDispatcher.cs
new file mode 100644
index 0000000000..4714f62af9
--- /dev/null
+++ b/Assets/PerfectWorld/Scripts/Chat/UI/ChatThreadDispatcher.cs
@@ -0,0 +1,47 @@
+using System;
+using System.Collections.Concurrent;
+using UnityEngine;
+
+namespace BrewMonster.Scripts.ChatUI
+{
+ ///
+ /// Responsible for switching chat messages from background threads to Unity main thread.
+ /// Only handles chat related actions.
+ ///
+ public class ChatThreadDispatcher : MonoSingleton
+ {
+ private static readonly ConcurrentQueue _queue = new ConcurrentQueue();
+
+ protected override void Awake()
+ {
+ base.Awake();
+ DontDestroyOnLoad(gameObject);
+ }
+
+ ///
+ /// Called from ANY thread (network thread safe)
+ ///
+ public void Post(Action action)
+ {
+ if (action == null)
+ return;
+
+ _queue.Enqueue(action);
+ }
+
+ private void Update()
+ {
+ while (_queue.TryDequeue(out var action))
+ {
+ try
+ {
+ action?.Invoke();
+ }
+ catch (Exception e)
+ {
+ Debug.LogError($"ChatThreadDispatcher error: {e}");
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/PerfectWorld/Scripts/Chat/UI/ChatThreadDispatcher.cs.meta b/Assets/PerfectWorld/Scripts/Chat/UI/ChatThreadDispatcher.cs.meta
new file mode 100644
index 0000000000..1c00a8022a
--- /dev/null
+++ b/Assets/PerfectWorld/Scripts/Chat/UI/ChatThreadDispatcher.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 00392315a7ee47e7a9527eda504fb312
+timeCreated: 1773310087
\ No newline at end of file
diff --git a/Assets/PerfectWorld/Scripts/Common/EC_C2SCmdCache.cs b/Assets/PerfectWorld/Scripts/Common/EC_C2SCmdCache.cs
index dc659560ff..1a0901486b 100644
--- a/Assets/PerfectWorld/Scripts/Common/EC_C2SCmdCache.cs
+++ b/Assets/PerfectWorld/Scripts/Common/EC_C2SCmdCache.cs
@@ -270,7 +270,7 @@ namespace BrewMonster.Common
{
m_UseItemCmdList.Clear();
- // C2S ʱ
+ // ���� C2S �����ʱ��
m_CounterMap[(int)CommandID.USE_ITEM].Reset(true);
m_EnterSanctuaryList.Clear();
@@ -280,7 +280,7 @@ namespace BrewMonster.Common
m_PresentInfoList.Clear();
m_CounterMap[(int)CommandID.PLAYER_GIVE_PRESENT].Reset(true);
- // Эʱ
+ // ����Э���ʱ��
m_GetPlayerBriefInfoList.Clear();
m_CounterMap2[(int)ProtocolType.PROTOCOL_GETPLAYERBRIEFINFO].Reset(true);
@@ -377,13 +377,13 @@ namespace BrewMonster.Common
getplayerbriefinfo p = m_GetPlayerBriefInfoList[0];
if (p.Playerlist.Count != 0)
{
- // ȡһidЭ
+ // ��ȡ��һ�����id�������������Э��
getplayerbriefinfo temp = p;
temp.Playerlist.Clear();
temp.Playerlist.Add(p.Playerlist[0]);
UnityGameSession.Instance.GameSession.SendProtocol(temp);
- // б
+ // ��������
p.Playerlist.Remove(p.Playerlist[0]);
}
@@ -670,12 +670,12 @@ namespace BrewMonster.Common
}
// Send protocols ...
- void SendGetPlayerBriefInfo(int iNumPlayer, int[] aIDs, int iReason)
+ public void SendGetPlayerBriefInfo(int iNumPlayer, int[] aIDs, int iReason)
{
if (iNumPlayer == 0 || aIDs == null || aIDs.Length == 0)
return;
- // 1.ϲӵб
+ // 1.�ϲ���ӵ��б�
getplayerbriefinfo p = new getplayerbriefinfo();
p.Roleid = EC_Game.GetGameRun().GetHostPlayer().GetCharacterID();
p.Reason = (byte)iReason;
@@ -687,7 +687,7 @@ namespace BrewMonster.Common
if (p.Playerlist.Count > 0)
m_GetPlayerBriefInfoList.Add(p);
- // 2.鲢
+ // 2.��鲢����
SendCachedGetPlayerBriefInfo();
}
diff --git a/Assets/PerfectWorld/Scripts/DebugCommandMenu/DlgConsole.cs b/Assets/PerfectWorld/Scripts/DebugCommandMenu/DlgConsole.cs
index d2db270052..e7768b4ab5 100644
--- a/Assets/PerfectWorld/Scripts/DebugCommandMenu/DlgConsole.cs
+++ b/Assets/PerfectWorld/Scripts/DebugCommandMenu/DlgConsole.cs
@@ -124,3 +124,5 @@ namespace BrewMonster.Scripts
}
}
}
+/// d 2000 la kn
+/// d 1988 + so tien
diff --git a/Assets/PerfectWorld/Scripts/GameData/EC_RoleType.cs b/Assets/PerfectWorld/Scripts/GameData/EC_RoleType.cs
index 665c65cbe3..8aa9ea705f 100644
--- a/Assets/PerfectWorld/Scripts/GameData/EC_RoleType.cs
+++ b/Assets/PerfectWorld/Scripts/GameData/EC_RoleType.cs
@@ -4,6 +4,11 @@ using UnityEngine;
public static class GameConstants
{
public static int NUM_MAGICCLASS = 5;
+ public static int ARMOR_RUIN_SPEED = -25;
+ public static int WEAPON_RUIN_SPEED = -2;
+ public static float PLAYER_PRICE_SCALE = 1.0f;
+ public static int ENDURANCE_SCALE = 100;
+
}
public struct ROLEBASICPROP
diff --git a/Assets/PerfectWorld/Scripts/Inventory/EC_IvtrType.cs b/Assets/PerfectWorld/Scripts/Inventory/EC_IvtrType.cs
index 2f7240ff90..5e4f43354d 100644
--- a/Assets/PerfectWorld/Scripts/Inventory/EC_IvtrType.cs
+++ b/Assets/PerfectWorld/Scripts/Inventory/EC_IvtrType.cs
@@ -2,10 +2,6 @@ namespace BrewMonster.Scripts
{
public class InventoryConst
{
- // Equipment endurance scale
- public const int ENDURANCE_SCALE = 100;
- // NUM_MAGICCLASS
- public const int NUM_MAGICCLASS = 5;
// Index of item in equipment inventory
public const int EQUIPIVTR_WEAPON = 0;
public const int EQUIPIVTR_HEAD = 1;
diff --git a/Assets/PerfectWorld/Scripts/MainFiles/EC_Game.cs b/Assets/PerfectWorld/Scripts/MainFiles/EC_Game.cs
index 7bd5336355..d9ea7b5505 100644
--- a/Assets/PerfectWorld/Scripts/MainFiles/EC_Game.cs
+++ b/Assets/PerfectWorld/Scripts/MainFiles/EC_Game.cs
@@ -316,8 +316,8 @@ namespace BrewMonster.Network
}
public static void update_require_data(ref prerequisition require)
{
- require.durability *= BrewMonster.Scripts.InventoryConst.ENDURANCE_SCALE;
- require.max_durability *= BrewMonster.Scripts.InventoryConst.ENDURANCE_SCALE;
+ require.durability *= GameConstants.ENDURANCE_SCALE;
+ require.max_durability *= GameConstants.ENDURANCE_SCALE;
}
public static void set_to_classid(DATA_TYPE type, byte[] data, int major_type)
{
diff --git a/Assets/PerfectWorld/Scripts/Managers/A3DSkillGfxMan.cs b/Assets/PerfectWorld/Scripts/Managers/A3DSkillGfxMan.cs
index 93f8d6a1ac..d19c956ff4 100644
--- a/Assets/PerfectWorld/Scripts/Managers/A3DSkillGfxMan.cs
+++ b/Assets/PerfectWorld/Scripts/Managers/A3DSkillGfxMan.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@@ -146,6 +146,7 @@ namespace BrewMonster
pEvent.SetDelay(dwDelayTime);
pEvent.SetReverse(bReverse);
pEvent.SetParam(param);
+ BMLogger.LogError("[HoangDev] bTraceTarget=" + bTraceTarget);
pEvent.SetTraceTarget(bTraceTarget);
pEvent.SetModifier(dwModifier);
pEvent.SetIsCluster(bCluster);
@@ -503,4 +504,4 @@ namespace BrewMonster
public bool bGfxDisableCamShake;
public bool bHostECMCreatedByGfx;
};
-}
\ No newline at end of file
+}
diff --git a/Assets/PerfectWorld/Scripts/Managers/CECSkillGfxMan.cs b/Assets/PerfectWorld/Scripts/Managers/CECSkillGfxMan.cs
index 9a94bab79b..ae0675bbb2 100644
--- a/Assets/PerfectWorld/Scripts/Managers/CECSkillGfxMan.cs
+++ b/Assets/PerfectWorld/Scripts/Managers/CECSkillGfxMan.cs
@@ -271,7 +271,6 @@ namespace BrewMonster
if (m_enumState == GfxSkillEventState.enumHit && m_bTraceTarget)
{
UpdateHitGfxTransform();
-
// Check if hit GFX has been destroyed (3 second lifetime) or target is destroyed
// 检查命中特效是否已被销毁(3秒生命周期)或目标是否已销毁
if (m_hitGfxInstance == null || (!m_bTargetExist && m_nTargetID != 0))
@@ -296,7 +295,26 @@ namespace BrewMonster
protected override void HitTarget(Vector3 vTarget)
{
base.HitTarget(vTarget);
- DestroyFlyGfx();
+
+ // Only destroy fly GFX if NOT tracing target
+ // If tracing target, fly GFX will be cleaned up when buff expires
+ // 只有在不跟踪目标时才销毁飞行特效
+ // 如果跟踪目标,飞行特效将在buff过期时清理
+ if (!m_bTraceTarget)
+ {
+ DestroyFlyGfx();
+ }
+ else
+ {
+ // If fly GFX exists and m_bTraceTarget is true, add to tracking list
+ // 如果飞行特效存在且m_bTraceTarget为true,添加到跟踪列表
+ if (m_flyGfxInstance != null)
+ {
+ SkillGfxMan.InstanceSub?.AddTraceTargetGfx(m_flyGfxInstance, 0); // Skill ID not available, use 0
+ BMLogger.Log($"[TRACE_TARGET_GFX] HitTarget: Added fly GFX to trace target list (m_bTraceTarget=true)");
+ }
+ }
+
SpawnHitGfx(vTarget);
// TODO Phase 2: Special hit effects (rune, critical, nullity)
@@ -333,6 +351,13 @@ namespace BrewMonster
m_flyGfxInstance = GameObject.Instantiate(prefab, pos, prefab.transform.rotation);
+ // If m_bTraceTarget is true, add to tracking list when spawned
+ // 如果m_bTraceTarget为true,在生成时添加到跟踪列表
+ if (m_bTraceTarget)
+ {
+ SkillGfxMan.InstanceSub?.AddTraceTargetGfx(m_flyGfxInstance, 0); // Skill ID not available, use 0
+ BMLogger.Log($"[TRACE_TARGET_GFX] SpawnFlyGfx: Added fly GFX to trace target list (m_bTraceTarget=true)");
+ }
}
///
@@ -401,7 +426,8 @@ namespace BrewMonster
// 这与C++逻辑匹配:当投射物击中地面(无目标)时使用m_szHitGrndGfx
bool bTargetExists = m_bTargetExist && m_nTargetID != 0;
GameObject prefab = bTargetExists ? m_pComposer.GetHitGFX() : m_pComposer.GetHitGrdGFX();
- BMLogger.LogError("HitGfx : " + m_pComposer.hitGfxName);
+ //BMLogger.LogError("bTargetExists : " + bTargetExists);
+ //BMLogger.LogError("HitGfx : " + m_pComposer.hitGfxName);
if (prefab == null)
{
@@ -429,9 +455,21 @@ namespace BrewMonster
m_hitGfxInstance = GameObject.Instantiate(prefab, vTarget, prefab.transform.rotation);
- // Destroy hit GFX after 3 seconds (unless m_bTraceTarget is true, then it follows target until destroyed)
- // 3秒后销毁命中特效(除非m_bTraceTarget为true,否则它会跟随目标直到被销毁)
- //GameObject.Destroy(m_hitGfxInstance, 3.0f);
+ // If m_bTraceTarget is true, add to tracking list (don't auto-destroy)
+ // 如果m_bTraceTarget为true,添加到跟踪列表(不自动销毁)
+ if (m_bTraceTarget)
+ {
+ SkillGfxMan.InstanceSub?.AddTraceTargetGfx(m_hitGfxInstance, 0); // Skill ID not available, use 0
+ //BMLogger.Log($"[TRACE_TARGET_GFX] SpawnHitGfx: Added hit GFX to trace target list (m_bTraceTarget=true)");
+ }
+ else
+ {
+ // Destroy hit GFX after 5 seconds (unless m_bTraceTarget is true, then it follows target until destroyed)
+ // 5秒后销毁命中特效(除非m_bTraceTarget为true,否则它会跟随目标直到被销毁)
+ //HIT_GFX_MAX_TIMESPAN 5000
+ //BMLogger.Log($"[TRACE_TARGET_GFX] SpawnHitGfx: GameObject.Destroy(m_hitGfxInstance, 5.0f);");
+ GameObject.Destroy(m_hitGfxInstance, 5.0f);
+ }
}
///
@@ -440,10 +478,28 @@ namespace BrewMonster
///
public new void Resume()
{
- DestroyFlyGfx();
- // Hit GFX is auto-destroyed by Unity's Destroy timer, don't null it here
- // 命中特效由Unity的Destroy计时器自动销毁,不在此处置null
- m_hitGfxInstance = null;
+ // Don't destroy GFX if it's in trace target list
+ // It will be cleaned up when buff expires
+ // 如果GFX在跟踪目标列表中,不要销毁它
+ // 它将在buff过期时清理
+ if (m_flyGfxInstance != null)
+ {
+ if (SkillGfxMan.InstanceSub != null && !SkillGfxMan.InstanceSub.IsTraceTargetGfx(m_flyGfxInstance))
+ {
+ DestroyFlyGfx();
+ }
+ }
+
+ if (m_hitGfxInstance != null)
+ {
+ if (SkillGfxMan.InstanceSub != null && !SkillGfxMan.InstanceSub.IsTraceTargetGfx(m_hitGfxInstance))
+ {
+ // Hit GFX is auto-destroyed by Unity's Destroy timer, don't null it here
+ // 命中特效由Unity的Destroy计时器自动销毁,不在此处置null
+ m_hitGfxInstance = null;
+ }
+ }
+
base.Resume();
}
@@ -878,6 +934,13 @@ namespace BrewMonster
protected EC_ManPlayer m_pPlayerMan;
protected CECNPCMan m_pNPCMan;
+ // Track GFX instances that have m_bTraceTarget = true
+ // These are typically buff-related trail effects that persist until buff expires
+ // 跟踪具有m_bTraceTarget = true的GFX实例
+ // 这些通常是持续到buff结束的buff相关轨迹效果
+ private List m_TraceTargetGfxList = new List();
+ private Dictionary m_TraceTargetGfxSkillMap = new Dictionary();
+
public SkillGfxMan(CECGameRun pGameRun)
{
m_EventLst = new LinkedList();
@@ -971,6 +1034,110 @@ namespace BrewMonster
{
m_FreeLst[i].Clear();
}
+
+ // Clean up trace target GFX
+ // 清理跟踪目标GFX
+ RemoveAllTraceTargetGfx();
+ }
+
+ ///
+ /// Add a GFX instance to trace target tracking list
+ /// 将GFX实例添加到跟踪目标跟踪列表
+ ///
+ public void AddTraceTargetGfx(GameObject gfxInstance, int skillId)
+ {
+ if (gfxInstance == null) return;
+
+ if (!m_TraceTargetGfxList.Contains(gfxInstance))
+ {
+ m_TraceTargetGfxList.Add(gfxInstance);
+ m_TraceTargetGfxSkillMap[gfxInstance] = skillId;
+
+ BMLogger.Log($"[TRACE_TARGET_GFX] Added GFX for skill {skillId}, total tracked: {m_TraceTargetGfxList.Count}");
+ }
+ }
+
+ ///
+ /// Remove all trace target GFX (called when buff states update)
+ /// 移除所有跟踪目标GFX(在buff状态更新时调用)
+ ///
+ public void RemoveAllTraceTargetGfx()
+ {
+ BMLogger.Log($"[TRACE_TARGET_GFX] Removing {m_TraceTargetGfxList.Count} trace target GFX");
+
+ foreach (GameObject gfx in m_TraceTargetGfxList)
+ {
+ if (gfx != null)
+ {
+ GameObject.Destroy(gfx);
+ }
+ }
+
+ m_TraceTargetGfxList.Clear();
+ m_TraceTargetGfxSkillMap.Clear();
+ }
+
+ ///
+ /// Remove trace target GFX for specific skill
+ /// 移除特定技能的跟踪目标GFX
+ ///
+ public void RemoveTraceTargetGfxForSkill(int skillId)
+ {
+ List toRemove = new List();
+
+ foreach (var kvp in m_TraceTargetGfxSkillMap)
+ {
+ if (kvp.Value == skillId)
+ {
+ toRemove.Add(kvp.Key);
+ }
+ }
+
+ foreach (GameObject gfx in toRemove)
+ {
+ if (gfx != null)
+ {
+ GameObject.Destroy(gfx);
+ }
+ m_TraceTargetGfxList.Remove(gfx);
+ m_TraceTargetGfxSkillMap.Remove(gfx);
+ }
+
+ if (toRemove.Count > 0)
+ {
+ BMLogger.Log($"[TRACE_TARGET_GFX] Removed {toRemove.Count} GFX for skill {skillId}");
+ }
+ }
+
+ ///
+ /// Check if a GFX instance is tracked as trace target GFX
+ /// 检查GFX实例是否被跟踪为跟踪目标GFX
+ ///
+ public bool IsTraceTargetGfx(GameObject gfx)
+ {
+ return m_TraceTargetGfxList.Contains(gfx);
+ }
+
+ ///
+ /// Clean up null references (GFX destroyed elsewhere)
+ /// 清理空引用(在其他地方销毁的GFX)
+ ///
+ public void CleanupTraceTargetGfx()
+ {
+ m_TraceTargetGfxList.RemoveAll(gfx => gfx == null);
+
+ List nullKeys = new List();
+ foreach (var kvp in m_TraceTargetGfxSkillMap)
+ {
+ if (kvp.Key == null)
+ {
+ nullKeys.Add(kvp.Key);
+ }
+ }
+ foreach (var key in nullKeys)
+ {
+ m_TraceTargetGfxSkillMap.Remove(key);
+ }
}
///
diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_Faction.cs b/Assets/PerfectWorld/Scripts/Managers/EC_Faction.cs
index 54a576234a..01bff104af 100644
--- a/Assets/PerfectWorld/Scripts/Managers/EC_Faction.cs
+++ b/Assets/PerfectWorld/Scripts/Managers/EC_Faction.cs
@@ -12,13 +12,17 @@ namespace BrewMonster
public int m_nLev;
public int m_nMemNum;
- public int GetLevel() { return m_nLev; }
+ public int GetLevel()
+ {
+ return m_nLev;
+ }
}
public class CECFactionMan
{
Dictionary m_FactionMap;
public List m_alliance = new List();
+
public Faction_Info GetFaction(uint uId, bool bRequestFromServer)
{
if (!m_FactionMap.TryGetValue(uId, out var it))
@@ -30,6 +34,7 @@ namespace BrewMonster
return it;
}
+
public bool IsFactionAlliance(int fid)
{
if (fid == 0)
@@ -43,5 +48,35 @@ namespace BrewMonster
return false;
}
+
+ private Dictionary m_MemMap;
+
+ public Faction_Mem_Info GetMember(int roleId)
+ {
+ if (m_MemMap.TryGetValue(roleId, out var member))
+ return member;
+
+ return null;
+ }
+ }
+
+ public class Faction_Mem_Info
+ {
+ public int RoleId { get; set; }
+ public int FRoleId { get; set; }
+ public int Level { get; set; }
+ public int Profession { get; set; }
+ public byte OnlineStatus { get; set; }
+ public byte Gender { get; set; }
+ public int LoginTime { get; set; }
+ public string Name { get; set; } = string.Empty;
+ public string NickName { get; set; } = string.Empty;
+ public int Contrib { get; set; }
+ public bool DelayExpel { get; set; }
+ public uint ExpelEndTime { get; set; }
+ public int Reputation { get; set; }
+ public int ReincarnationTimes { get; set; }
+
+ public bool IsOnline => OnlineStatus != 0;
}
}
diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_Friend.cs b/Assets/PerfectWorld/Scripts/Managers/EC_Friend.cs
new file mode 100644
index 0000000000..f48abf62e3
--- /dev/null
+++ b/Assets/PerfectWorld/Scripts/Managers/EC_Friend.cs
@@ -0,0 +1,251 @@
+using System.Collections.Generic;
+using BrewMonster.Network;
+
+namespace BrewMonster
+{
+ public class CECFriendMan
+ {
+ // =========================
+ // Nested Types
+ // =========================
+
+ public struct Friend
+ {
+ public int Id;
+ public int Profession;
+ public int GroupId;
+ public byte Status;
+ public int Level;
+ public int AreaId;
+ public string Name;
+
+ public bool IsGameOnline() => IsGameOnline(Status);
+ public bool IsGTOnline() => IsGTOnline(Status);
+
+ public static bool IsGameOnline(byte s)
+ {
+ // TODO: implement đúng theo logic C++
+ return (s & 0x01) != 0;
+ }
+
+ public static bool IsGTOnline(byte s)
+ {
+ // TODO: implement đúng theo logic C++
+ return (s & 0x02) != 0;
+ }
+ }
+
+ public class FRIEND_EX
+ {
+ public bool NewFriendPlaceHolder;
+ public int Uid;
+ public int Rid;
+ public int Level;
+ public long LastLoginTime;
+ public long UpdateTime;
+ public int ReincarnationCount;
+ public string Remarks = string.Empty;
+ }
+
+ public class SEND_INFO
+ {
+ public int Rid;
+ public long SendMailTime;
+ }
+
+ public class GROUP
+ {
+ public string Name = string.Empty;
+ public int GroupId;
+ public uint Color; // nếu dùng Unity thì có thể đổi sang Color
+
+ public List Friends = new();
+ }
+
+ public class MESSAGE
+ {
+ public string SenderName = string.Empty;
+ public int SenderId;
+ public string MessageText = string.Empty;
+ public byte Flag;
+ }
+
+ // =========================
+ // Fields
+ // =========================
+
+ private List m_Groups = new();
+ private Dictionary m_FriendTable = new();
+ private List m_OfflineMsgs = new();
+ private List m_FriendEx = new();
+ private List m_SendInfo = new();
+
+ // =========================
+ // Operations
+ // =========================
+
+ public bool CheckInit() => m_Groups.Count > 0;
+
+ public Friend AddFriend(int id, int profession, int groupId, byte status, string name)
+ {
+ var friend = new Friend
+ {
+ Id = id,
+ Profession = profession,
+ GroupId = groupId,
+ Status = status,
+ Name = name
+ };
+
+ m_FriendTable[id] = friend;
+
+ var group = GetGroupByID(groupId);
+ group?.Friends.Add(friend);
+ if (friend.IsGameOnline())
+ {
+ // Todo: Check again
+ EC_Game.GetGameRun().AddPlayerName(id, name);
+ }
+
+ return friend;
+ }
+
+ public void RemoveFriend(int idFriend)
+ {
+ if (!m_FriendTable.TryGetValue(idFriend, out var friend))
+ return;
+
+ m_FriendTable.Remove(idFriend);
+
+ var group = GetGroupByID(friend.GroupId);
+ group?.Friends.Remove(friend);
+ }
+
+ public void RemoveAllFriends()
+ {
+ m_FriendTable.Clear();
+ foreach (var group in m_Groups)
+ group.Friends.Clear();
+ }
+
+ public void ChangeFriendStatus(int idFriend, byte status)
+ {
+ if (m_FriendTable.TryGetValue(idFriend, out var friend))
+ friend.Status = status;
+ }
+
+ public void ChangeFriendGroup(int idFriend, int newGroupId)
+ {
+ if (!m_FriendTable.TryGetValue(idFriend, out var friend))
+ return;
+
+ var oldGroup = GetGroupByID(friend.GroupId);
+ oldGroup?.Friends.Remove(friend);
+
+ friend.GroupId = newGroupId;
+
+ var newGroup = GetGroupByID(newGroupId);
+ newGroup?.Friends.Add(friend);
+ }
+
+ public Friend? GetFriendByID(int idFriend)
+ {
+ m_FriendTable.TryGetValue(idFriend, out var friend);
+ return friend;
+ }
+
+ public Friend? GetFriendByName(string name)
+ {
+ foreach (var friend in m_FriendTable.Values)
+ {
+ if (friend.Name == name)
+ return friend;
+ }
+
+ return null;
+ }
+
+ public void SetFriendLevel(int idFriend, int level)
+ {
+ if (m_FriendTable.TryGetValue(idFriend, out var friend))
+ friend.Level = level;
+ }
+
+ public void SetFriendArea(int idFriend, int areaId)
+ {
+ if (m_FriendTable.TryGetValue(idFriend, out var friend))
+ friend.AreaId = areaId;
+ }
+
+ // =========================
+ // Group Operations
+ // =========================
+
+ public bool AddGroup(int idGroup, string name)
+ {
+ if (GetGroupByID(idGroup) != null)
+ return false;
+
+ m_Groups.Add(new GROUP
+ {
+ GroupId = idGroup,
+ Name = name
+ });
+
+ return true;
+ }
+
+ public void RemoveGroup(int idGroup)
+ {
+ m_Groups.RemoveAll(g => g.GroupId == idGroup);
+ }
+
+ public void ChangeGroupName(int idGroup, string name)
+ {
+ var group = GetGroupByID(idGroup);
+ if (group != null)
+ group.Name = name;
+ }
+
+ public void SetGroupColor(int idGroup, uint color)
+ {
+ var group = GetGroupByID(idGroup);
+ if (group != null)
+ group.Color = color;
+ }
+
+ public int GetGroupNum() => m_Groups.Count;
+
+ public GROUP? GetGroupByIndex(int index)
+ {
+ if (index < 0 || index >= m_Groups.Count)
+ return null;
+
+ return m_Groups[index];
+ }
+
+ public GROUP? GetGroupByID(int id)
+ {
+ return m_Groups.Find(g => g.GroupId == id);
+ }
+
+ // =========================
+ // Offline Messages
+ // =========================
+
+ public int GetOfflineMsgNum() => m_OfflineMsgs.Count;
+
+ public MESSAGE? GetOfflineMsg(int index)
+ {
+ if (index < 0 || index >= m_OfflineMsgs.Count)
+ return null;
+
+ return m_OfflineMsgs[index];
+ }
+
+ public void RemoveAllOfflineMsgs()
+ {
+ m_OfflineMsgs.Clear();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_Friend.cs.meta b/Assets/PerfectWorld/Scripts/Managers/EC_Friend.cs.meta
new file mode 100644
index 0000000000..45f5f08f51
--- /dev/null
+++ b/Assets/PerfectWorld/Scripts/Managers/EC_Friend.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: b5aa739db9534099a9eead426912429c
+timeCreated: 1772089238
\ No newline at end of file
diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkMove.cs b/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkMove.cs
index ad6a54d52b..1603aad83f 100644
--- a/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkMove.cs
+++ b/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkMove.cs
@@ -1349,11 +1349,12 @@ namespace BrewMonster.Scripts
string message = $"Cannot find path to target position.\nPlease move manually to target location.\n\nMap Coordinates: ({mapX}, {mapZ}, ↑{mapY})";
string messageCN = $"无法找到到目标位置的路径。\n请手动移动到目标位置。\n\n地图坐标: ({mapX}, {mapZ}, ↑{mapY})";
- CECUIManager.Instance.ShowMessageBox(
- "Path Not Found", // 路径未找到
- message, // English message with map coordinates
- BrewMonster.MessageBoxType.YesButton
- );
+ // CECUIManager.Instance.ShowMessageBox(
+ // "Path Not Found", // 路径未找到
+ // message, // English message with map coordinates
+ // BrewMonster.MessageBoxType.YesButton
+ // );
+ CECUIManager.Instance.ShowMessageBoxYes("Path Not Found", message, null, null);
}
else
{
diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_Inventory.cs b/Assets/PerfectWorld/Scripts/Managers/EC_Inventory.cs
index 5e020ab927..7d113a8309 100644
--- a/Assets/PerfectWorld/Scripts/Managers/EC_Inventory.cs
+++ b/Assets/PerfectWorld/Scripts/Managers/EC_Inventory.cs
@@ -11,7 +11,8 @@ namespace BrewMonster.Scripts.Managers
public class EC_Inventory
{
// ===== Instance-based inventory (per-pack) =====
-
+ public static int IVTRTYPE_CLIENT_GENERALCARD_PACK = 1024; // �ͻ��˱��ذ����� ���ڿ���ͼ��Ҫ����ѻ�ÿ���ͨ�����췢�͡�Ϊ��ͳһ�������촰�ڵ���Ʒ�����ӱ��ذ�����
+
// Item array: index is slot, null means empty.
private EC_IvtrItem[] m_aItems = Array.Empty();
@@ -27,12 +28,6 @@ namespace BrewMonster.Scripts.Managers
IVTRTYPE_GENERALCARD_BOX = 7; // ���ư���
};
- // ע�� IVTRTYPE_CLIENT_GENERALCARD_PACK ö��ֵ���ܺ������ Inventory type ֵ�ظ�����
- public static class IVTRTYPE_PACK_CLIENT_GENERALCAR
- {
- public const int IVTRTYPE_CLIENT_GENERALCARD_PACK = 1024; // �ͻ��˱��ذ����� ���ڿ���ͼ��Ҫ����ѻ�ÿ���ͨ�����췢�͡�Ϊ��ͳһ�������촰�ڵ���Ʒ�����ӱ��ذ�����
- };
-
public EC_Inventory()
{
}
diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/CECIvtrWeapon.cs b/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/CECIvtrWeapon.cs
index 6c4ef2cabd..f2f1f55b28 100644
--- a/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/CECIvtrWeapon.cs
+++ b/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/CECIvtrWeapon.cs
@@ -201,8 +201,8 @@ namespace PerfectWorld.Scripts.Managers
StrengthReq = m_pDBEssence.require_strength;
AgilityReq = m_pDBEssence.require_agility;
ReputationReq = m_pDBEssence.require_reputation;
- CurEndurance = m_pDBEssence.durability_min * ENDURANCE_SCALE;
- MaxEndurance = m_pDBEssence.durability_min * ENDURANCE_SCALE;
+ CurEndurance = m_pDBEssence.durability_min * GameConstants.ENDURANCE_SCALE;
+ MaxEndurance = m_pDBEssence.durability_min * GameConstants.ENDURANCE_SCALE;
}
// Get item icon file name
public override string GetIconFile()
diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrArmor.cs b/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrArmor.cs
index db680f2a08..4938df1c5c 100644
--- a/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrArmor.cs
+++ b/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrArmor.cs
@@ -207,8 +207,8 @@ namespace PerfectWorld.Scripts.Managers
StrengthReq = m_pDBEssence.require_strength;
AgilityReq = m_pDBEssence.require_agility;
ReputationReq = m_pDBEssence.require_reputation;
- CurEndurance = m_pDBEssence.durability_min * ENDURANCE_SCALE;
- MaxEndurance = m_pDBEssence.durability_min * ENDURANCE_SCALE;
+ CurEndurance = m_pDBEssence.durability_min * GameConstants.ENDURANCE_SCALE;
+ MaxEndurance = m_pDBEssence.durability_min * GameConstants.ENDURANCE_SCALE;
}
// Get item icon file name
public override string GetIconFile()
diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrDecoration.cs b/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrDecoration.cs
index ad175bdd60..b805e5b45d 100644
--- a/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrDecoration.cs
+++ b/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrDecoration.cs
@@ -174,8 +174,8 @@ namespace PerfectWorld.Scripts.Managers
StrengthReq = 0;
AgilityReq = 0;
ReputationReq = m_pDBEssence.require_reputation;
- CurEndurance = m_pDBEssence.durability_min * ENDURANCE_SCALE;
- MaxEndurance = m_pDBEssence.durability_min * ENDURANCE_SCALE;
+ CurEndurance = m_pDBEssence.durability_min * GameConstants.ENDURANCE_SCALE;
+ MaxEndurance = m_pDBEssence.durability_min * GameConstants.ENDURANCE_SCALE;
}
public override string GetIconFile()
{
diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrEquip.cs b/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrEquip.cs
index 1ee7462d39..c3df0b8b5d 100644
--- a/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrEquip.cs
+++ b/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrEquip.cs
@@ -14,7 +14,6 @@ using System.Text.RegularExpressions;
using System.Reflection;
using BrewMonster.Scripts.Managers;
using BrewMonster.Scripts;
-
namespace PerfectWorld.Scripts.Managers
{
///
@@ -161,9 +160,6 @@ namespace PerfectWorld.Scripts.Managers
// Scale Types
public const int SCALE_SELL = 1;
- // Endurance Scale
- public const int ENDURANCE_SCALE = 100;
-
#endregion
#region Public Fields
@@ -925,7 +921,7 @@ namespace PerfectWorld.Scripts.Managers
///
public static int VisualizeEndurance(int v)
{
- return (v + ENDURANCE_SCALE - 1) / ENDURANCE_SCALE;
+ return (v + GameConstants.ENDURANCE_SCALE - 1) / GameConstants.ENDURANCE_SCALE;
}
///
diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrType.cs b/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrType.cs
index 663d1d1ff5..306ebb5dd3 100644
--- a/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrType.cs
+++ b/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrType.cs
@@ -115,8 +115,8 @@ namespace BrewMonster.Scripts.Managers
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++)
+ resistance = new int[GameConstants.NUM_MAGICCLASS];
+ for (int i = 0; i < GameConstants.NUM_MAGICCLASS; i++)
{
resistance[i] = dr.ReadInt();
}
@@ -132,13 +132,13 @@ namespace BrewMonster.Scripts.Managers
public int[] resistance;
public IVTR_ESSENCE_ARMOR(byte[] data)
{
- resistance = new int[InventoryConst.NUM_MAGICCLASS];
+ resistance = new int[GameConstants.NUM_MAGICCLASS];
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 < GameConstants.NUM_MAGICCLASS; i++)
{
resistance[i] = dr.ReadInt();
}
diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_ManPlayer.cs b/Assets/PerfectWorld/Scripts/Managers/EC_ManPlayer.cs
index 370dc5ff35..940057abac 100644
--- a/Assets/PerfectWorld/Scripts/Managers/EC_ManPlayer.cs
+++ b/Assets/PerfectWorld/Scripts/Managers/EC_ManPlayer.cs
@@ -69,6 +69,7 @@ namespace PerfectWorld.Scripts.Managers
case EC_MsgDef.MSG_PM_PLAYERFLY:
case EC_MsgDef.MSG_PM_PLAYERMOUNT:
case EC_MsgDef.MSG_PM_PLAYERCHGSHAPE:
+ case EC_MsgDef.MSG_PM_PLAYERSKILLRESULT:
TransmitMessage(Msg);
break;
case EC_MsgDef.MSG_PM_PLAYERDIED:
@@ -141,14 +142,22 @@ namespace PerfectWorld.Scripts.Managers
if (host != null && cid == host.GetCharacterID())
{
- host.ProcessMessage(Msg);
+ // Call OnMsgPlayerExtState directly instead of ProcessMessage
+ // ProcessMessage doesn't handle MSG_PM_PLAYEREXTSTATE
+ // 直接调用OnMsgPlayerExtState而不是ProcessMessage
+ // ProcessMessage不处理MSG_PM_PLAYEREXTSTATE
+ host.OnMsgPlayerExtState(Msg);
}
else
{
EC_ElsePlayer elsePlayer = SeekOutElsePlayer(cid);
if (elsePlayer != null)
{
- elsePlayer.ProcessMessage(Msg);
+ // Call OnMsgPlayerExtState directly instead of ProcessMessage
+ // ProcessMessage doesn't handle MSG_PM_PLAYEREXTSTATE
+ // 直接调用OnMsgPlayerExtState而不是ProcessMessage
+ // ProcessMessage不处理MSG_PM_PLAYEREXTSTATE
+ elsePlayer.OnMsgPlayerExtState(Msg);
}
if (Convert.ToInt32(Msg.dwParam2) == CommandID.ICON_STATE_NOTIFY && host != null && host.GetTeam() != null)
@@ -735,6 +744,9 @@ namespace PerfectWorld.Scripts.Managers
case EC_MsgDef.MSG_PM_PLAYERCHGSHAPE:
cid = (GPDataTypeHelper.FromBytes((byte[])Msg.dwParam1)).idPlayer;
break;
+ case EC_MsgDef.MSG_PM_PLAYERSKILLRESULT:
+ cid = GPDataTypeHelper.FromBytes((byte[])Msg.dwParam1).attacker_id;
+ break;
default:
System.Diagnostics.Debug.Assert(false, "Unknown message");
return false;
@@ -917,4 +929,4 @@ namespace PerfectWorld.Scripts.Managers
public CECModel pFlyNviagteModel;
//CECPlayer::EquipsLoadResult EquipResult;
};
-}
\ No newline at end of file
+}
diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_Object.cs b/Assets/PerfectWorld/Scripts/Managers/EC_Object.cs
index e622efd239..95f9c347d2 100644
--- a/Assets/PerfectWorld/Scripts/Managers/EC_Object.cs
+++ b/Assets/PerfectWorld/Scripts/Managers/EC_Object.cs
@@ -13,9 +13,8 @@ using UnityEngine;
//
///////////////////////////////////////////////////////////////////////////
-public class CECObject : MonoBehaviour
+public partial class CECObject : MonoBehaviour
{
-
protected static int ALPHA_HASH = Shader.PropertyToID("_Alpha");
protected Quaternion targetRotation;
protected Quaternion startRotation; // Store starting rotation for Slerp
diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_RoleTypes.cs b/Assets/PerfectWorld/Scripts/Managers/EC_RoleTypes.cs
index 94779620d3..88288c73b2 100644
--- a/Assets/PerfectWorld/Scripts/Managers/EC_RoleTypes.cs
+++ b/Assets/PerfectWorld/Scripts/Managers/EC_RoleTypes.cs
@@ -231,8 +231,7 @@ namespace BrewMonster.Scripts
{
// Constants
public const int EC_MAXNOPKLEVEL = 0; // The maximum no PK level
- public const float EC_TABSEL_DIST = 60.0f; // Distance of TAB selection
- public const int NUM_MAGICCLASS = 5;
+ public const float EC_TABSEL_DIST = 60.0f;
public const int NUM_ESBYTE = (int)(ExtendState.NUM_EXTSTATE + 31) >> 5;
// Helper methods for bit manipulation (equivalent to the C++ inline functions)
diff --git a/Assets/PerfectWorld/Scripts/Move/CECPlayer.cs b/Assets/PerfectWorld/Scripts/Move/CECPlayer.cs
index 2f50b604d3..70942446f6 100644
--- a/Assets/PerfectWorld/Scripts/Move/CECPlayer.cs
+++ b/Assets/PerfectWorld/Scripts/Move/CECPlayer.cs
@@ -36,6 +36,11 @@ namespace BrewMonster
[SerializeField] internal INFO m_PlayerInfo;
public CECModel m_pPlayerCECModel;
protected GameObject m_pPlayerModel => m_pPlayerCECModel.m_pPlayerModel;
+ public bool IsPlayerModelReady
+ {
+ get;
+ protected set;
+ }
protected float rotationSpeed = 5;
internal int m_iMoveMode; // Player's move mode
[SerializeField] internal int m_idSelTarget;
@@ -331,6 +336,9 @@ namespace BrewMonster
m_pModels[(int)PLAYERMODEL_TYPE.PLAYERMODEL_MAJOR] = m_pPlayerModel;
m_iShape = 0;
+ // Set the player model ready flag
+ IsPlayerModelReady = true;
+
// Update visual components after model is set (with delay to ensure NamedAnimancerComponent is available)
// 设置模型后更新视觉组件(延迟以确保NamedAnimancerComponent可用)
StartCoroutine(UpdateVisualComponentsDelayed());
@@ -741,6 +749,15 @@ namespace BrewMonster
public virtual void SetNewExtendStates(int unknown, uint[] states, int count)
{
// TODO: Implement appearance or physics change
+
+ // Remove all trace target GFX when buff states change
+ // This ensures buff-related trail effects are cleaned up when buffs expire
+ // 当buff状态改变时移除所有跟踪目标GFX
+ // 这确保buff相关的轨迹效果在buff过期时被清理
+ if (SkillGfxMan.InstanceSub != null)
+ {
+ SkillGfxMan.InstanceSub.RemoveAllTraceTargetGfx();
+ }
}
public virtual void SetUpPlayer()
@@ -2202,7 +2219,45 @@ namespace BrewMonster
}
}
}
+ protected void OnMsgEnchantResult(ECMSG msg)
+ {
+ // 从消息中获取cmd_enchant_result结构 // Get cmd_enchant_result structure from message
+ cmd_enchant_result pCmd = GPDataTypeHelper.FromBytes((byte[])msg.dwParam1);
+ // 初始化掩码为全1 // Initialize mask to all 1s
+ uint mask = 0xFFFFFFFF;
+
+ // 如果目标不是主机玩家且当前不是主机玩家,则过滤会引起气泡文本的修饰符
+ // We should filter out these things that will cause bubble texts
+ CECHostPlayer pHost = EC_ManMessageMono.Instance.GetECManPlayer.GetHostPlayer();
+ if (pCmd.target != pHost.GetCharacterID() && !IsHostPlayer())
+ {
+ mask &= (uint)(MOD.MOD_PHYSIC_ATTACK_RUNE | MOD.MOD_MAGIC_ATTACK_RUNE |
+ MOD.MOD_CRITICAL_STRIKE | MOD.MOD_ENCHANT_FAILED);
+ }
+
+ // 获取修饰符 // Get modifier
+ uint dwModifier = (uint)pCmd.attack_flag;
+
+ // 获取技能类型 // Get skill type
+ int nDamage = -2; // 默认为-2,不会引起受伤动作 // Default to -2, will not cause wounded action
+
+ if (ElementSkill.GetType((uint)pCmd.skill) == (byte)skill_type.TYPE_ATTACK)
+ {
+ // 只有攻击技能会引起受伤动作,伤害值为-1 // Only attack skill will cause wounded action, when damage is -1
+ nDamage = -1;
+ }
+ else
+ {
+ // 其他技能不会引起受伤动作,伤害值设为-2 // Other skills will not cause wounded action, so we set damage to -2
+ nDamage = -2;
+ }
+
+ // 播放攻击效果 // Play attack effect
+ int attackTime = 0;
+ PlayAttackEffect(pCmd.target, pCmd.skill, pCmd.level, nDamage,
+ dwModifier & mask, 0, ref attackTime, pCmd.section);
+ }
// 判断是否在飞行 / Check if flying
public bool IsFlying()
{
diff --git a/Assets/PerfectWorld/Scripts/NPC/CECNPC.cs b/Assets/PerfectWorld/Scripts/NPC/CECNPC.cs
index eecf3cb4d8..13bc6471e2 100644
--- a/Assets/PerfectWorld/Scripts/NPC/CECNPC.cs
+++ b/Assets/PerfectWorld/Scripts/NPC/CECNPC.cs
@@ -6,6 +6,7 @@ using CSNetwork.GPDataType;
using ModelRenderer.Scripts.Common;
using System;
using System.Threading.Tasks;
+using BrewMonster.Scripts.Chat;
using UnityEngine;
public class CECNPC : CECObject
@@ -469,7 +470,7 @@ public class CECNPC : CECObject
{
return m_pNPCModelPolicy.PlayAttackAction(nAttackSpeed, attackevent);
}
- void NPCTurnFaceTo(int idTarget, float dwTime = 0.3f)
+ public void NPCTurnFaceTo(int idTarget, float dwTime = 0.3f)
{
if (IsDirFixed())
{
@@ -1602,6 +1603,34 @@ public class CECNPC : CECObject
// Get NPC name color
public virtual uint GetNameColor() { return 0xffffff00; }
+
+ CECPateText m_pPateLastWords1;
+ CECPateText m_pPateLastWords2;
+ public void SetLastSaidWords(string words, int timeShow = -1)
+ {
+ if (m_pPateLastWords1 == null)
+ {
+ m_pPateLastWords1 = new CECPateText();
+ }
+
+ if (m_pPateLastWords2 == null)
+ {
+ m_pPateLastWords2 = new CECPateText();
+ }
+
+ if (words == null)
+ return;
+
+ int len1 = m_pPateLastWords1.SetText(words, true, out string strWords, false, null);
+
+ /*
+ if (len1 < strWords.Length)
+ m_pPateLastWords2.SetText(strWords.Substring(len1), true, true);
+ else
+ m_pPateLastWords2.Clear();
+
+ m_iLastSayCnt = timeShow > 0 ? timeShow : 20000;*/
+ }
///
/// Get NPC's CECModel instance
diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/AUICommon.cs b/Assets/PerfectWorld/Scripts/Network/CSNetwork/AUICommon.cs
index 9bb345d99f..cb9e652961 100644
--- a/Assets/PerfectWorld/Scripts/Network/CSNetwork/AUICommon.cs
+++ b/Assets/PerfectWorld/Scripts/Network/CSNetwork/AUICommon.cs
@@ -1,12 +1,34 @@
-using System;
+using System;
using System.Collections.Generic;
+using System.Linq;
using System.Text;
+using CSNetwork;
namespace CSNetwork
{
public static class AUICommon
{
- public static void AUI_ConvertChatString(string pszChat, char[] pszConv, bool bName)
+ public const char AUICOMMON_ITEM_CODE_START = (char)0xE000;
+ public const char AUICOMMON_ITEM_CODE_END = (char)0xE3FF;
+ public const int AUIMANAGER_MAX_EMOTIONGROUPS = 32;
+
+ public const int MAX_EDITBOX_ITEM_NUM =
+ AUICOMMON_ITEM_CODE_END - AUICOMMON_ITEM_CODE_START + 1;
+
+ public const int MAXNUM_CUSTOM_ITEM = 255;
+
+ public enum EditboxItemType
+ {
+ enumEIEmotion = 0,
+ enumEIIvtrlItem,
+ enumEICoord,
+ enumEIImage,
+ enumEIScriptItem,
+ enumEICustom,
+ enumEINum = enumEICustom + MAXNUM_CUSTOM_ITEM
+ }
+
+ public static void AUI_ConvertChatString(ref string pszChat, ref char[] pszConv, bool bName)
{
if (string.IsNullOrEmpty(pszChat) || pszConv == null)
return;
@@ -49,5 +71,782 @@ namespace CSNetwork
pszConv[nLen] = '\0';
}
+ public static string FilterEmotionSet(string szText, int nEmotionSet)
+ {
+ EditBoxItemsSet itemsSet = new EditBoxItemsSet();
+
+ string strOrgText = UnmarshalEditBoxText(szText, itemsSet);
+
+ int nCount = itemsSet.GetItemCount();
+
+ if (nCount == 0)
+ return szText;
+
+ var it = itemsSet.GetItemIterator();
+
+ for (int i = 0; i < nCount; i++)
+ {
+ EditBoxItemBase pItem = it.Current.Value;
+
+ if (pItem.GetType() == EditboxItemType.enumEIEmotion)
+ {
+ int nSet = 0;
+ int nIndex = 0;
+
+ UnmarshalEmotionInfo(pItem.GetInfo(), ref nSet, ref nIndex);
+
+ pItem.SetInfo(MarshalEmotionInfo(nEmotionSet, nIndex));
+ }
+
+ it.MoveNext();
+ }
+
+ return MarshalEditBoxText(strOrgText, itemsSet);
+ }
+
+ public static string MarshalEmotionInfo(int nEmotionSet, int nIndex)
+ {
+ return nEmotionSet.ToString() + ":" + nIndex.ToString();
+ }
+
+ public static void UnmarshalEmotionInfo(string szText, ref int nEmotionSet, ref int nIndex)
+ {
+ if (string.IsNullOrEmpty(szText))
+ return;
+
+ var parts = szText.Split(':');
+
+ if (parts.Length >= 2)
+ {
+ int.TryParse(parts[0], out nEmotionSet);
+ int.TryParse(parts[1], out nIndex);
+ }
+
+ // a_ClampFloor(nEmotionSet, 0);
+ if (nEmotionSet < 0)
+ nEmotionSet = 0;
+
+ // a_ClampFloor(nIndex, 0);
+ if (nIndex < 0)
+ nIndex = 0;
+
+ if (nEmotionSet >= AUIMANAGER_MAX_EMOTIONGROUPS)
+ nEmotionSet = 0;
+ }
+
+ public static string MarshalEditBoxText(string text, EditBoxItemsSet itemsSet)
+ {
+ var sb = new StringBuilder(text.Length * 2);
+
+ int start = 0;
+
+ for (int i = 0; i < text.Length; i++)
+ {
+ char ch = text[i];
+
+ if (IsEditboxItemCode(ch))
+ {
+ sb.Append(text, start, i - start + 1);
+
+ var item = itemsSet.GetItemByChar(ch);
+ if (item != null)
+ sb.Append(item.Serialize());
+
+ start = i + 1;
+ }
+ }
+
+ if (start < text.Length)
+ sb.Append(text, start, text.Length - start);
+
+ return sb.ToString();
+ }
+
+ public static bool IsEditboxItemCode(char ch)
+ {
+ return ch >= AUICOMMON_ITEM_CODE_START && ch <= AUICOMMON_ITEM_CODE_END;
+ }
+
+ public static string UnmarshalEditBoxText(string szText, EditBoxItemsSet itemsSet)
+ {
+ return UnmarshalEditBoxText(
+ szText,
+ itemsSet,
+ 0,
+ null,
+ 0,
+ 0,
+ null,
+ 0,
+ false,
+ false,
+ 0
+ );
+ }
+
+ public static string UnmarshalEditBoxText(
+ string? sztext,
+ EditBoxItemsSet itemsSet,
+ int msgIndex,
+ string ivtrItem,
+ uint clIvtrItem,
+ int itemMask,
+ EditboxScriptItem[]? scriptItems,
+ int scriptItemCount,
+ bool underLine,
+ bool sameColor,
+ uint clUnderLine)
+ {
+ if (sztext == null)
+ return "";
+
+ var scriptInfo = new AUI_UNMARSH_SCRIPTITEM_INFO
+ {
+ ScriptItems = scriptItems,
+ ScriptItemCount = scriptItemCount
+ };
+
+ var underlineInfo = new AUI_UNMARSH_UNDERLINE_INFO
+ {
+ UnderLine = underLine,
+ SameColor = sameColor,
+ UnderLineColor = clUnderLine
+ };
+
+ return UnmarshalEditBoxTextEx(
+ sztext,
+ itemsSet,
+ msgIndex,
+ ivtrItem,
+ clIvtrItem,
+ itemMask,
+ scriptInfo,
+ underlineInfo
+ );
+ }
+
+ public static string UnmarshalEditBoxTextEx(
+ string text,
+ EditBoxItemsSet itemsSet,
+ int msgIndex,
+ string ivtrItem,
+ uint clIvtrItem,
+ int itemMask,
+ AUI_UNMARSH_SCRIPTITEM_INFO? scriptInfo,
+ AUI_UNMARSH_UNDERLINE_INFO? underlineInfo)
+ {
+ if (text == null)
+ return "";
+
+ int start = 0;
+ int i = 0;
+ int curScriptIndex = 0;
+
+ var sb = new StringBuilder();
+
+ while (i < text.Length)
+ {
+ char ch = text[i];
+
+ if (IsEditboxItemCode(ch))
+ {
+ if (i > start)
+ sb.Append(text, start, i - start);
+
+ i++;
+
+ EditBoxItemBase? item = EditBoxItemBase.Unserialize(text, ref i);
+ start = i;
+
+ if (item != null)
+ {
+ if ((itemMask & (1 << (int)item.GetType())) != 0)
+ {
+ char newChar = itemsSet.AppendItem(item);
+
+ if (newChar != '\0')
+ {
+ sb.Append(newChar);
+
+ item.SetMsgIndex(msgIndex);
+
+ if (underlineInfo != null)
+ {
+ item.SetUnderLine(
+ underlineInfo.UnderLine,
+ underlineInfo.SameColor,
+ underlineInfo.UnderLineColor);
+ }
+
+ switch (item.GetType())
+ {
+ case EditboxItemType.enumEIIvtrlItem:
+
+ item.SetName(ivtrItem);
+ item.SetColor(clIvtrItem);
+ break;
+
+ case EditboxItemType.enumEIScriptItem:
+
+ if (scriptInfo != null &&
+ curScriptIndex < scriptInfo.ScriptItemCount)
+ {
+ var sItem = scriptInfo.ScriptItems![curScriptIndex];
+
+ item.SetName(sItem.Name);
+ item.SetColor(sItem.Color);
+
+ var data = sItem.Name;
+ if (data != null)
+ item.SetExtraData(sItem.Data, sItem.GetDataSize());
+
+ curScriptIndex++;
+ }
+
+ break;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ i++;
+ }
+ }
+
+ if (i > start)
+ sb.Append(text, start, i - start);
+
+ return sb.ToString();
+ }
+
+ ///
+ /// Chuyển đổi định dạng printf (C-style: %s, %d) sang string.Format (C#-style: {0}, {1})
+ ///
+ public static string ConvertPrintfToCSharpFormat(string format)
+ {
+ if (string.IsNullOrEmpty(format)) return "";
+
+ StringBuilder sb = new StringBuilder();
+ int argIndex = 0;
+ for (int i = 0; i < format.Length; i++)
+ {
+ if (format[i] == '%' && i + 1 < format.Length)
+ {
+ char next = format[i + 1];
+ if (next == '%') // Trường hợp %% -> %
+ {
+ sb.Append('%');
+ i++;
+ }
+ else
+ {
+ sb.Append('{').Append(argIndex++).Append('}');
+
+ i++;
+ // Nhảy qua các ký tự định dạng (ví dụ: %02d, %ls, %f)
+ while (i < format.Length && (char.IsDigit(format[i]) || format[i] == '.' || format[i] == 'l' || format[i] == 'u' || format[i] == 'd' || format[i] == 's' || format[i] == 'f' || format[i] == 'x'))
+ {
+ // Nếu gặp ký tự kết thúc định dạng (s, d, f, ...) thì dừng lại sau ký tự đó
+ char c = format[i];
+ if (c == 's' || c == 'd' || c == 'f' || c == 'u' || c == 'x' || c == 'g')
+ {
+ // i++; // Đã ở đúng vị trí để vòng lặp cha thực hiện i++ tiếp theo
+ break;
+ }
+ i++;
+ }
+ }
+ }
+ else
+ {
+ sb.Append(format[i]);
+ }
+ }
+ return sb.ToString();
+ }
}
-}
\ No newline at end of file
+}
+
+public class AUI_UNMARSH_SCRIPTITEM_INFO
+{
+ public EditboxScriptItem[]? ScriptItems;
+ public int ScriptItemCount;
+}
+
+public class AUI_UNMARSH_UNDERLINE_INFO
+{
+ public bool UnderLine;
+ public bool SameColor;
+ public uint UnderLineColor;
+}
+
+public class EditBoxItemsSet
+{
+ const char AUICOMMON_ITEM_CODE_START = '\u0001';
+ const char AUICOMMON_ITEM_CODE_END = '\u0010';
+ protected Dictionary m_Items = new();
+ protected int[] m_ItemsCount = new int[(int)AUICommon.EditboxItemType.enumEINum];
+ protected char m_cNextItemChar;
+
+ public EditBoxItemsSet()
+ {
+ Array.Clear(m_ItemsCount, 0, m_ItemsCount.Length);
+ m_cNextItemChar = AUICommon.AUICOMMON_ITEM_CODE_START;
+ }
+
+ public EditBoxItemsSet(EditBoxItemsSet itemsset)
+ {
+ this.Assign(itemsset);
+ }
+
+ public void Assign(EditBoxItemsSet src)
+ {
+ m_Items.Clear();
+
+ foreach (var kv in src.m_Items)
+ {
+ m_Items[kv.Key] = new EditBoxItemBase(kv.Value);
+ }
+
+ Array.Copy(src.m_ItemsCount, m_ItemsCount, m_ItemsCount.Length);
+ m_cNextItemChar = src.m_cNextItemChar;
+ }
+
+ public void Release()
+ {
+ m_Items.Clear();
+
+ Array.Clear(m_ItemsCount, 0, m_ItemsCount.Length);
+
+ m_cNextItemChar = AUICommon.AUICOMMON_ITEM_CODE_START;
+ }
+
+ public int GetItemCount()
+ {
+ return m_Items.Count;
+ }
+
+ public Dictionary.Enumerator GetItemIterator()
+ {
+ return m_Items.GetEnumerator();
+ }
+
+ public EditBoxItemBase? GetItemByChar(char ch)
+ {
+ if (!IsEditboxItemCode(ch))
+ throw new Exception("Invalid editbox item char");
+
+ if (m_Items.TryGetValue(ch, out var item))
+ return item;
+
+ return null;
+ }
+
+ public bool IsEditboxItemCode(char ch)
+ {
+ return ch >= AUICOMMON_ITEM_CODE_START && ch <= AUICOMMON_ITEM_CODE_END;
+ }
+
+ public int GetItemCountByType(AUICommon.EditboxItemType type)
+ {
+ return m_ItemsCount[(int)type];
+ }
+
+ public void DelItemByChar(char ch)
+ {
+ if (m_Items.TryGetValue(ch, out var item))
+ {
+ m_ItemsCount[(int)item.GetType()]--;
+ m_Items.Remove(ch);
+ }
+ }
+
+ public char AppendItem(EditBoxItemBase pItem)
+ {
+ if (m_Items.Count >= AUICommon.MAX_EDITBOX_ITEM_NUM)
+ return '\0';
+
+ char cur = m_cNextItemChar;
+
+ do
+ {
+ if (m_Items.ContainsKey(m_cNextItemChar))
+ {
+ m_cNextItemChar = EditboxGetNextChar(m_cNextItemChar);
+ }
+ else
+ {
+ m_Items[m_cNextItemChar] = pItem;
+ m_ItemsCount[(int)pItem.GetType()]++;
+
+ char ret = m_cNextItemChar;
+ m_cNextItemChar = EditboxGetNextChar(m_cNextItemChar);
+
+ return ret;
+ }
+ } while (m_cNextItemChar != cur);
+
+ return '\0';
+ }
+
+ public char EditboxGetNextChar(char cur)
+ {
+ if (cur >= AUICOMMON_ITEM_CODE_END)
+ return AUICOMMON_ITEM_CODE_START;
+ else
+ return (char)(cur + 1);
+ }
+
+ public char AppendItem(AUICommon.EditboxItemType type, uint cl, string szName, string szInfo)
+ {
+ // Implement theo logic C++ gốc
+ throw new NotImplementedException();
+ }
+
+ public int GetTotalExtraDataSize()
+ {
+ int sz = 0;
+
+ foreach (var item in m_Items.Values)
+ {
+ sz += item.GetExtraDataSize();
+ }
+
+ return sz;
+ }
+}
+
+public class EditBoxItemBase
+{
+ protected AUICommon.EditboxItemType m_type;
+ protected uint m_dwColor;
+ protected string m_strName = "";
+ protected string m_strInfo = "";
+
+ protected int m_nMsgIndex;
+ protected int m_nImageIndex;
+ protected int m_nImageFrame;
+ protected float m_fImageScale;
+
+ protected byte[]? m_pExtraData;
+ protected int m_uExtraDataSize;
+
+ protected bool m_bUnderLine;
+ protected bool m_bSameColor;
+ protected uint m_dwUnderLineColor;
+
+ protected static EditBoxItemBase?[] m_mapCustomType = new EditBoxItemBase[AUICommon.MAXNUM_CUSTOM_ITEM];
+
+ public EditBoxItemBase(AUICommon.EditboxItemType type)
+ {
+ m_type = type;
+ m_dwColor = 0xffffffff;
+
+ m_nMsgIndex = 0;
+ m_nImageIndex = 0;
+ m_nImageFrame = 0;
+ m_fImageScale = 1.0f;
+
+ m_bUnderLine = false;
+ m_bSameColor = true;
+ m_dwUnderLineColor = 0;
+
+ RegisterCustomType(type);
+ }
+
+ public EditBoxItemBase(EditBoxItemBase src)
+ {
+ Assign(src);
+ }
+
+ public bool UnserializeContent(string text, ref int index)
+ {
+ int szNext;
+ int szEnd = text.IndexOf("<", index);
+
+ if (szEnd == -1)
+ return false;
+
+ if (m_type == AUICommon.EditboxItemType.enumEICoord)
+ {
+ szNext = szEnd + 1;
+
+ if (!TryParseInt(text, szNext, out int color))
+ return false;
+
+ SetColor((uint)color);
+
+ szEnd = text.IndexOf("><", szNext);
+ if (szEnd == -1) return false;
+
+ szNext = szEnd + 2;
+
+ if (!TryParseInt(text, szNext, out int underline))
+ return false;
+
+ m_bUnderLine = underline != 0;
+
+ szEnd = text.IndexOf("><", szNext);
+ if (szEnd == -1) return false;
+
+ szNext = szEnd + 2;
+
+ if (!TryParseInt(text, szNext, out int underlineColor))
+ return false;
+
+ m_dwUnderLineColor = (uint)underlineColor;
+
+ szEnd = text.IndexOf("><", szNext);
+ if (szEnd == -1) return false;
+
+ m_bSameColor = (m_dwUnderLineColor == m_dwColor);
+
+ szNext = szEnd + 2;
+
+ szEnd = text.IndexOf("><", szNext);
+ if (szEnd == -1) return false;
+
+ SetName(text.Substring(szNext, szEnd - szNext));
+
+ szEnd += 1;
+ }
+ else if (m_type == AUICommon.EditboxItemType.enumEIImage)
+ {
+ szNext = szEnd + 1;
+
+ if (!TryParseUInt(text, szNext, out uint color))
+ return false;
+
+ SetColor(color);
+
+ szEnd = text.IndexOf("><", szNext);
+ if (szEnd == -1) return false;
+
+ szNext = szEnd + 2;
+
+ if (!TryParseInt(text, szNext, out int imageIndex))
+ return false;
+
+ SetImageIndex(imageIndex);
+
+ szEnd = text.IndexOf("><", szNext);
+ if (szEnd == -1) return false;
+
+ szNext = szEnd + 2;
+
+ if (!TryParseInt(text, szNext, out int frame))
+ return false;
+
+ SetImageFrame(frame);
+
+ szEnd = text.IndexOf("><", szNext);
+ if (szEnd == -1) return false;
+
+ szNext = szEnd + 2;
+
+ if (!float.TryParse(text.Substring(szNext), out float f))
+ return false;
+
+ SetImageScale(f);
+
+ szEnd = text.IndexOf("><", szNext);
+ if (szEnd == -1) return false;
+
+ szEnd += 1;
+ }
+ else if (m_type == AUICommon.EditboxItemType.enumEIEmotion)
+ {
+ SetName("W");
+ }
+
+ szNext = szEnd + 1;
+
+ szEnd = text.IndexOf('>', szNext);
+
+ if (szEnd == -1)
+ return false;
+
+ SetInfo(text.Substring(szNext, szEnd - szNext));
+
+ index = szEnd + 1;
+
+ return true;
+ }
+
+ private bool TryParseInt(string text, int start, out int value)
+ {
+ int end = start;
+
+ while (end < text.Length && char.IsDigit(text[end]))
+ end++;
+
+ return int.TryParse(text.Substring(start, end - start), out value);
+ }
+
+ private bool TryParseUInt(string text, int start, out uint value)
+ {
+ int end = start;
+
+ while (end < text.Length && char.IsDigit(text[end]))
+ end++;
+
+ return uint.TryParse(text.Substring(start, end - start), out value);
+ }
+
+ protected void RegisterCustomType(AUICommon.EditboxItemType type)
+ {
+ if (type >= AUICommon.EditboxItemType.enumEICustom &&
+ type < AUICommon.EditboxItemType.enumEINum)
+ {
+ int index = (int)type - (int)AUICommon.EditboxItemType.enumEICustom;
+
+ if (m_mapCustomType[index] == null)
+ m_mapCustomType[index] = this;
+ }
+ }
+
+ protected virtual EditBoxItemBase Create()
+ {
+ return new EditBoxItemBase(m_type);
+ }
+
+ protected static EditBoxItemBase? GetCustomItemFromType(AUICommon.EditboxItemType type)
+ {
+ if (type >= AUICommon.EditboxItemType.enumEICustom &&
+ type < AUICommon.EditboxItemType.enumEINum)
+ {
+ return m_mapCustomType[(int)type - (int)AUICommon.EditboxItemType.enumEICustom];
+ }
+
+ return null;
+ }
+
+ public uint GetColor() => m_dwColor;
+ public AUICommon.EditboxItemType GetType() => m_type;
+ public string GetName() => m_strName;
+ public string GetInfo() => m_strInfo;
+ public int GetMsgIndex() => m_nMsgIndex;
+ public int GetImageIndex() => m_nImageIndex;
+ public int GetImageFrame() => m_nImageFrame;
+ public float GetImageScale() => m_fImageScale;
+ public bool GetUnderLine() => m_bUnderLine;
+ public bool GetSameColor() => m_bSameColor;
+ public uint GetUnderLineColor() => m_dwUnderLineColor;
+
+ public void SetColor(uint cl) => m_dwColor = cl;
+ public void SetName(string name) => m_strName = name;
+ public void SetInfo(string info) => m_strInfo = info;
+ public void SetMsgIndex(int n) => m_nMsgIndex = n;
+ public void SetImageIndex(int n) => m_nImageIndex = n;
+ public void SetImageFrame(int n) => m_nImageFrame = n;
+ public void SetImageScale(float f) => m_fImageScale = f;
+
+ public byte[]? GetExtraData() => m_pExtraData;
+ public int GetExtraDataSize() => m_uExtraDataSize;
+
+ public void SetUnderLine(bool underline, bool sameColor = true, uint underlineColor = 0)
+ {
+ m_bUnderLine = underline;
+ m_bSameColor = sameColor;
+ m_dwUnderLineColor = underlineColor;
+ }
+
+ public void SetExtraData(byte[] data, int size)
+ {
+ m_pExtraData = new byte[size];
+ Array.Copy(data, 0, m_pExtraData, 0, size);
+ m_uExtraDataSize = size;
+ }
+
+ public virtual string Serialize()
+ {
+ return "";
+ }
+
+ public static EditBoxItemBase Unserialize(string text, ref int index)
+ {
+ int start = text.IndexOf('<', index);
+ if (start == -1)
+ return null;
+
+ start++;
+
+ int endType = text.IndexOf('>', start);
+ if (endType == -1)
+ return null;
+
+ string typeStr = text.Substring(start, endType - start);
+
+ if (!int.TryParse(typeStr, out int type))
+ return null;
+
+ if (type < 0 || type >= (int)AUICommon.EditboxItemType.enumEINum)
+ return null;
+
+ index = endType + 1;
+
+ EditBoxItemBase pItem = EditBoxItemBase.GetCustomItemFromType((AUICommon.EditboxItemType)type);
+
+ EditBoxItemBase pItemNew;
+
+ if (pItem == null)
+ {
+ pItemNew = new EditBoxItemBase((AUICommon.EditboxItemType)type);
+ }
+ else
+ {
+ pItemNew = pItem.Create();
+ }
+
+ if (!pItemNew.UnserializeContent(text, ref index))
+ {
+ return null;
+ }
+
+ return pItemNew;
+ }
+
+ public void Assign(EditBoxItemBase src)
+ {
+ m_type = src.m_type;
+ m_dwColor = src.m_dwColor;
+ m_strName = src.m_strName;
+ m_strInfo = src.m_strInfo;
+
+ m_nMsgIndex = src.m_nMsgIndex;
+ m_nImageIndex = src.m_nImageIndex;
+ m_nImageFrame = src.m_nImageFrame;
+ m_fImageScale = src.m_fImageScale;
+
+ if (src.m_pExtraData != null)
+ {
+ SetExtraData(src.m_pExtraData, src.m_uExtraDataSize);
+ }
+ else
+ {
+ m_pExtraData = null;
+ m_uExtraDataSize = 0;
+ }
+
+ RegisterCustomType(m_type);
+ }
+}
+
+public class EditboxScriptItem
+{
+ public string Name { get; set; } = "";
+ public uint Color { get; set; }
+ public byte[]? Data { get; private set; }
+
+ public void SetData(byte[] data)
+ {
+ Data = data.ToArray(); // deep copy
+ }
+
+ public int GetDataSize()
+ {
+ return Data?.Length ?? 0;
+ }
+}
diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/C2SCommand/C2SCommandFactory.cs b/Assets/PerfectWorld/Scripts/Network/CSNetwork/C2SCommand/C2SCommandFactory.cs
index 6f544b78f2..aaa747621a 100644
--- a/Assets/PerfectWorld/Scripts/Network/CSNetwork/C2SCommand/C2SCommandFactory.cs
+++ b/Assets/PerfectWorld/Scripts/Network/CSNetwork/C2SCommand/C2SCommandFactory.cs
@@ -381,7 +381,7 @@ namespace CSNetwork.C2SCommand
public static Octets CreateGetOtherEquipCmd(int iNumID, int[] aIDs)
{
var cmd = new CMD_GetOtherEquip { size = (ushort)iNumID, idList = aIDs };
- return SerializeCommand(CommandID.GET_OTHER_EQUIP, cmd);
+ return SerializeCommand(CommandID.GET_OTHER_EQUIP, cmd, false);
}
/// Create C2S GET_OTHER_EQUIP_DETAIL command (view other player profile/equip). Sends cmd + roleId only (4-byte body).
diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/GPDataType.cs b/Assets/PerfectWorld/Scripts/Network/CSNetwork/GPDataType.cs
index e70d330201..2092498f76 100644
--- a/Assets/PerfectWorld/Scripts/Network/CSNetwork/GPDataType.cs
+++ b/Assets/PerfectWorld/Scripts/Network/CSNetwork/GPDataType.cs
@@ -1539,6 +1539,18 @@ namespace CSNetwork.GPDataType
public byte section;
};
[StructLayout(LayoutKind.Sequential, Pack = 1)]
+ public struct cmd_host_skill_attacked
+ {
+ public int idAttacker;
+ public int idSkill;
+ public int iDamage;
+ public byte cEquipment; // The equipment which is mangled, ��λ������ι����Dz���Ӧ�ñ��ɫ
+
+ public int attack_flag; //��Ǹù����Ƿ��й����Ż����ͷ����Ż������ػ�����
+ public byte speed; //�����ٶ� speed * 50 ms
+ public byte section; // skill section
+ };
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct cmd_matter_info_list
{
public ushort count;
@@ -1800,6 +1812,46 @@ namespace CSNetwork.GPDataType
Marshal.FreeHGlobal(ptr);
}
}
+
+ ///
+ /// Convert data become byte array (Demo)
+ ///
+ /// Marshal.SizeOf()
+ /// Max size data
+ /// Removes the number of leading bytes
+ /// Remove the last byte count
+ ///
+ public static byte[] ContentBytes(int dataTypeLenght, int totalSize, int lenghtHeaderIgnore, int lenghtLastIgnore = 0)
+ {
+ int dataLength = totalSize - (lenghtHeaderIgnore + lenghtLastIgnore);
+ if(dataLength <= 0) throw new ArgumentException("Buffer không đủ dữ liệu");
+ byte[] dataContent = new byte[dataLength];
+ int offset = dataTypeLenght;
+
+ for (int i = 0; i < dataLength; i++)
+ {
+ dataContent[i] = FromBytes(dataContent, offset);
+ offset += dataTypeLenght;
+ }
+ return dataContent;
+ }
+
+ public static byte[] ContentBytes(int totalSize, int lenghtHeaderIgnore, int lenghtLastIgnore = 0)
+ {
+ int dataLength = totalSize - (lenghtHeaderIgnore + lenghtLastIgnore);
+ if(dataLength <= 0) throw new ArgumentException("Buffer không đủ dữ liệu");
+ byte[] dataContent = new byte[dataLength];
+ int dataTypeSize = Marshal.SizeOf();
+ int offset = dataTypeSize;
+
+ for (int i = 0; i < dataLength; i++)
+ {
+ dataContent[i] = FromBytes(dataContent, offset);
+ offset += dataTypeSize;
+ }
+ return dataContent;
+ }
+
/// Parse variable-length cmd_team_member_data from buffer. Returns (header, data[]) and bytes consumed.
public static (cmd_team_member_data_header header, cmd_team_member_data_MEMBER[] data) ParseTeamMemberData(byte[] data, int startIndex = 0)
{
diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/GameSession.cs b/Assets/PerfectWorld/Scripts/Network/CSNetwork/GameSession.cs
index dba6c7c1c8..327035dcbd 100644
--- a/Assets/PerfectWorld/Scripts/Network/CSNetwork/GameSession.cs
+++ b/Assets/PerfectWorld/Scripts/Network/CSNetwork/GameSession.cs
@@ -14,9 +14,15 @@ using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
+using BrewMonster.PerfectWorld.Scripts.UI;
+using BrewMonster.Scripts;
+using BrewMonster.Scripts.Chat;
+using BrewMonster.Scripts.Managers;
+using BrewMonster.Scripts.UI;
using BrewMonster.Scripts;
using BrewMonster.Scripts.Managers;
using UnityEngine;
+using CECPlayer = BrewMonster.CECPlayer;
using CommandID = CSNetwork.GPDataType.CommandID;
namespace CSNetwork
@@ -51,6 +57,15 @@ namespace CSNetwork
/// Raised when server sends PROTOCOL_PLAYERLOGOUT(69).
public event Action PlayerLogoutReceived;
+ ///
+ /// Raised when server sends RPC_ADDFRIENDRQST(204) — another player wants to add you as friend.
+ /// Args: xid (RPC transaction id), srcroleid, askerName.
+ ///
+ public event Action FriendRequestReceived;
+
+ /// Raised when server sends PROTOCOL_ADDFRIEND_RE(203). Args: retcode (0=success), message.
+ public event Action AddFriendResultReceived;
+
/// Raised when the underlying network disconnects.
public event Action Disconnected;
@@ -253,7 +268,7 @@ namespace CSNetwork
Debug.Log($"[GameSession] Creating role - UserID: {_currentUserId}, Localsid: {_localsid}, Profession: {roleInfo.occupation}, Gender: {roleInfo.gender}");
Debug.Log($"[GameSession] RoleInfo details - Name size: {roleInfo.name?.Size ?? 0}, Equipment count: {roleInfo.equipment?.Count ?? 0}, Custom data size: {roleInfo.custom_data?.Size ?? 0}, Race: {roleInfo.race}");
-
+
// Log first few bytes of custom_data for debugging
if (roleInfo.custom_data != null && roleInfo.custom_data.Size > 0)
{
@@ -262,7 +277,7 @@ namespace CSNetwork
string hexPreview = BitConverter.ToString(customDataPreview).Replace("-", " ");
Debug.Log($"[GameSession] Custom_data preview (first 16 bytes): {hexPreview}");
}
-
+
Debug.Log($"[GameSession] Sending createrole protocol (Type: {createRoleProtocol.Type})");
SendProtocol(createRoleProtocol);
}
@@ -325,7 +340,7 @@ namespace CSNetwork
// Initialize custom data exactly as C++ does: memset to 0, then set specific values
// This matches C++ LoadDefaultCustomizeData behavior
roleInfo.custom_data = CreateDefaultCustomizeData(profession, gender);
-
+
// Initialize other empty custom data fields
roleInfo.custom_status = new Octets();
roleInfo.charactermode = new Octets();
@@ -364,31 +379,31 @@ namespace CSNetwork
const int CUSTOMIZE_DATA_SIZE = 176; // Match server expectation (176 bytes from response)
const uint CUSTOMIZE_DATA_VERSION = 0x10007001; // CUSTOMIZE_DATA_VERSION from C++
byte[] customDataBytes = new byte[CUSTOMIZE_DATA_SIZE];
-
+
// Step 1: memset to 0 (already done by new byte[])
-
+
// Step 2: Set dwVersion at offset 0-3 (little-endian)
byte[] versionBytes = BitConverter.GetBytes(CUSTOMIZE_DATA_VERSION);
Array.Copy(versionBytes, 0, customDataBytes, 0, 4);
-
+
// Step 3: FACE_CUSTOMIZEDATA at offset 4-87 is already zero (84 bytes)
// (In C++ this would be loaded from INI, but for now we use zeros)
-
+
// Step 4: bodyID at offset 88-89 is already zero (2 bytes)
// Note: There might be 2 bytes padding here if struct is 4-byte aligned
-
- // Step 5: Set colorBody to 0xffffffff
+
+ // Step 5: Set colorBody to 0xffffffff
// Try offset 90 first (no padding), if that doesn't work try 92 (with padding)
byte[] colorBodyBytes = BitConverter.GetBytes(0xffffffffu);
Array.Copy(colorBodyBytes, 0, customDataBytes, 90, 4); // Try 90 first
-
+
// Step 6: Set all 6 scale fields to 128
// Try offset 94 first (no padding), if that doesn't work try 96 (with padding)
for (int i = 94; i < 100; i++)
{
customDataBytes[i] = 128;
}
-
+
return new Octets(customDataBytes);
}
@@ -531,7 +546,6 @@ namespace CSNetwork
private void OnProtocolReceived(Protocol protocol)
{
_logger.Log(LogType.Debug, $"Received protocol: {protocol.GetType().Name} (Type: {protocol.Type})");
- BMLogger.Log($"Received protocol: {protocol.GetType().Name} (Type: {protocol.Type})");
if (protocol is null)
return;
@@ -569,6 +583,9 @@ namespace CSNetwork
case ProtocolType.PROTOCOL_CHATMESSAGE:
OnPrtcChatMessage(protocol, false);
break;
+ case ProtocolType.PROTOCOL_WORLDCHAT:
+ OnPrtcWorldChat(protocol, false);
+ break;
case ProtocolType.PROTOCOL_PLAYERBASEINFO_RE:
OnPrtcPlayerBaseInfoRe(protocol);
break;
@@ -587,6 +604,14 @@ namespace CSNetwork
}
break;
+ case ProtocolType.RPC_ADDFRIENDRQST:
+ OnAddFriendRqst((addfriendrqst)protocol);
+ break;
+
+ case ProtocolType.PROTOCOL_ADDFRIEND_RE:
+ OnAddFriendRe((addfriend_re)protocol);
+ break;
+
default:
_logger.Log(LogType.Warning, $"Received unhandled protocol type: {protocol.GetPType()}");
break;
@@ -601,6 +626,49 @@ namespace CSNetwork
// PostToUnityContext(() => PlayerLogoutReceived?.Invoke(protocol));
}
+ private void OnAddFriendRqst(addfriendrqst p)
+ {
+ string askerName = "";
+ if (p.Srcname != null && p.Srcname.Size > 0)
+ askerName = System.Text.Encoding.Unicode.GetString(p.Srcname.ToArray(), 0, p.Srcname.Size);
+ // Forward xid + srcroleid + name to Unity layer so it can answer via Friend_AddResponse(xid, agree)
+ PostToUnityContext(() => FriendRequestReceived?.Invoke(p.Xid, p.Srcroleid, askerName));
+ }
+
+ private void OnAddFriendRe(addfriend_re p)
+ {
+ string friendName = "";
+ if (p.info?.name != null && p.info.name.Size > 0)
+ friendName = System.Text.Encoding.Unicode.GetString(p.info.name.ToArray(), 0, p.info.name.Size);
+ string msg = p.retcode == 0
+ ? $"Add friend success: {friendName}"
+ : $"Add friend failed: {GetAddFriendRetcodeMessage(p.retcode)}";
+ if (p.retcode == 0)
+ {
+ Friend_GetList();
+ }
+
+ PostToUnityContext(() => AddFriendResultReceived?.Invoke(p.retcode, msg));
+ }
+
+ /// FS_ERR server retcodes for addfriend_re.
+ private static string GetAddFriendRetcodeMessage(byte retcode)
+ {
+ switch (retcode)
+ {
+ case 0: return "Success";
+ case 1: return "Player is offline";
+ case 2: return "Request was refused";
+ case 3: return "Timeout";
+ case 4: return "No remaining space";
+ case 5: return "Not found";
+ case 6: return "Invalid parameter";
+ case 7: return "Duplicate entry";
+ case 8: return "Friend list has not been retrieved yet";
+ default: return $"retcode={retcode}";
+ }
+ }
+
// void CECGameSession::OnPrtcPlayerLogout(GNET::Protocol* pProtocol)
// {
// using namespace GNET;
@@ -989,7 +1057,7 @@ namespace CSNetwork
}
else if (pCmd.iMessage == 133 || pCmd.iMessage == 134)
{
- // deal failed
+ // deal failed
//pGameRun.PostMessage(MSG_HST_BUY_SELL_FAIL, MAN_PLAYER, 0, (DWORD)pDataBuf, pCmdHeader.cmd);
}
else if (pCmd.iMessage == 158)
@@ -1115,6 +1183,9 @@ namespace CSNetwork
case CommandID.HOST_SKILL_ATTACK_RESULT:
EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_SKILLRESULT, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader);
break;
+ case CommandID.HOST_SKILL_ATTACKED:
+ EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_SKILLATTACKED, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader);
+ break;
case CommandID.CHANGE_FACE_START:
case CommandID.CHANGE_FACE_END:
EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_CHANGEFACE, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader, dwDataSize);
@@ -1300,6 +1371,16 @@ namespace CSNetwork
case CommandID.LEAVE_SANCTUARY:
EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_SANCTUARY, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader);
break;
+ case CommandID.OBJECT_SKILL_ATTACK_RESULT:
+ {
+ cmd_object_skill_attack_result pCmd = GPDataTypeHelper.FromBytes ((byte[])pDataBuf);
+ if (ISPLAYERID(pCmd.attacker_id))
+ EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERSKILLRESULT, MANAGER_INDEX.MAN_PLAYER, -1,pDataBuf, pCmdHeader);
+ else if (ISNPCID(pCmd.attacker_id))
+ EC_ManMessage.PostMessage(EC_MsgDef.MSG_NM_NPCSKILLRESULT, MANAGER_INDEX.MAN_NPC, 0, pDataBuf, pCmdHeader);
+
+ break;
+ }
default:
#if UNITY_EDITOR
if (isDebug)
@@ -1326,7 +1407,7 @@ namespace CSNetwork
private void HandleCreateRoleResponse(createrole_re protocol)
{
Debug.Log($"[GameSession] HandleCreateRoleResponse - result: {protocol.result}, roleid: {protocol.roleid}");
-
+
if (protocol.result != (int)ErrCode.ERR_SUCCESS)
{
string errorMsg = $"Create role failed with result code: {protocol.result} (ERR_SUCCESS = {(int)ErrCode.ERR_SUCCESS})";
@@ -1347,7 +1428,7 @@ namespace CSNetwork
private void HandleErrorInfo(errorinfo protocol)
{
Debug.LogError($"[GameSession] Server error - Errcode: {protocol.Errcode}");
-
+
// If we're waiting for create role response and get an error, fail the callback
if (_createRoleCallback != null)
{
@@ -1639,8 +1720,8 @@ namespace CSNetwork
g.Data = C2SCommandFactory.CreatePlayerLogoutCmd(outType);
SendProtocol(g, complete);
}
-
-
+
+
public void c2s_SendCmdStopMove(in Vector3 vDest, float fSpeed, int iMoveMode,
byte byDir, ushort wStamp, int iTime)
{
@@ -1657,17 +1738,94 @@ namespace CSNetwork
gamedatasend.Data = C2SCommandFactory.CreateNakeCmd(C2SCommand.CommandID.ENTER_PK_PROTECTED);
SendProtocol(gamedatasend);
}
+
+ public const int SUPER_FAR_CRY_EMOTION_SET = 6;
+ ///
+ /// Convert string become byte (Encoding.Unicode trong .NET = UTF-16 LE)
+ ///
+ /// Data type: enum, Chanel chat
+ /// Text send to server
+ ///
+ ///
public void SendChatData(byte cChannel, in string szMsg, int iPack, int iSlot)
{
- publicchat publicChat = new publicchat();
- publicChat.Channel = cChannel;
- publicChat.Roleid = m_iCharID;
+ if (string.IsNullOrEmpty(szMsg))
+ return;
+
+ publicchat p = new publicchat();
+ p.Channel = cChannel;
+ p.Roleid = m_iCharID;
+ if (iPack == EC_Inventory.IVTRTYPE_CLIENT_GENERALCARD_PACK)
+ {
+ CECHostPlayer pHost = EC_Game.GetGameRun().GetHostPlayer();
+ EC_Inventory clientPack =
+ pHost != null ? pHost.GetPack(EC_Inventory.IVTRTYPE_CLIENT_GENERALCARD_PACK) : null;
+
+ if (pHost != null && clientPack != null)
+ {
+ EC_IvtrItem pCard = clientPack.GetItem(iSlot);
+
+ if (pCard != null)
+ {
+ short cmd = (short)CHAT_S2C.EChatS2CCommand.CHAT_GENERALCARD_COLLECTION;
+ int cardId = pCard.GetTemplateID();
+
+ byte[] bytes = new byte[6];
+
+ BitConverter.GetBytes(cmd).CopyTo(bytes, 0);
+ BitConverter.GetBytes(cardId).CopyTo(bytes, 2);
+ p.Data.Replace(bytes);
+ }
+ }
+ }
+ else if (iPack >= 0 && iSlot >= 0)
+ {
+ byte[] bytes = new byte[5];
+
+ short cmd = (short)CHAT_S2C.EChatS2CCommand.CHAT_EQUIP_ITEM;
+ short index = (short)iSlot;
+ byte where = (byte)iPack;
+
+ BitConverter.GetBytes(cmd).CopyTo(bytes, 0);
+ bytes[2] = where;
+ BitConverter.GetBytes(index).CopyTo(bytes, 3);
+ p.Data.Replace(bytes);
+ }
byte[] unicodeBytes = Encoding.Unicode.GetBytes(szMsg);
- publicChat.Msg.Replace(unicodeBytes);
- _logger.Log(LogType.Warning, $"HoangDev : publicChat {publicChat}");
- SendProtocol(publicChat);
+ p.Msg.Replace(unicodeBytes);
+ SendProtocol(p);
+
+ if (cChannel is (byte)ChatChannel.GP_CHAT_LOCAL
+ or (byte)ChatChannel.GP_CHAT_FARCRY
+ or (byte)ChatChannel.GP_CHAT_SUPERFARCRY
+ or (byte)ChatChannel.GP_CHAT_BATTLE
+ or (byte)ChatChannel.GP_CHAT_COUNTRY) {
+ CECHostPlayer pHost = EC_Game.GetGameRun().GetHostPlayer();
+ //int nEmotionSet = pHost.GetCurEmotionSet();
+ int nEmotionSet = 0;
+ string strMsg = szMsg;
+ if (cChannel == (byte)ChatChannel.GP_CHAT_SUPERFARCRY)
+ {
+ if (strMsg.Length > 8)
+ {
+ strMsg = strMsg.Substring(0, strMsg.Length - 8);
+ }
+ nEmotionSet = SUPER_FAR_CRY_EMOTION_SET;
+ }
+
+ EC_IvtrItem pItem = null;
+ if (iPack >= 0 && iSlot >= 0) {
+ EC_Inventory pPack = pHost.GetPack(iPack);
+ if (pPack != null) {
+ pItem = pPack.GetItem(iSlot);
+ }
+ }
+ EventBus.PublishChannel(pHost.GetCharacterID(), new EventChatMessageOnTopPlayer(pHost.GetCharacterID(), szMsg));
+ EventBus.Publish(new ChatMessageEvent(szMsg, p.Channel));
+ }
}
+
public void LoadConfigData()
{
getuiconfig p = new getuiconfig();
@@ -1682,7 +1840,7 @@ namespace CSNetwork
public void SaveConfigData(byte[] pBuf, int len)
{
BMLogger.Log($"[MH] Session.SaveConfigData | len={len}");
-
+
if (pBuf == null || len <= 0) return;
var p = new setuiconfig();
p.Roleid = m_iCharID;
@@ -1690,7 +1848,7 @@ namespace CSNetwork
byte[] slice = new byte[len];
Buffer.BlockCopy(pBuf, 0, slice, 0, len);
p.Ui_config = new Octets(slice);
-
+
// return;
SendProtocol(p);
}
@@ -1700,23 +1858,226 @@ namespace CSNetwork
m_iCharID = iCharID;
}
- private void OnPrtcChatMessage(Protocol pProtocol, bool bCalledagain)
+ private bool OnPrtcWorldChat(Protocol pProtocol, bool bCalledagain)
{
+ worldchat p = (worldchat)pProtocol;
+ /*if (p.Channel == (byte)ChatChannel.GP_CHAT_FARCRY && p.Roleid == 24)
+ {
+ OnTaskChatMessage(p.Msg.RawBuffer, p.Msg.Size);
+ return true;
+ }*/
+
+ // TODO: Porting logic OnPrtcWorldChat hoàn chỉnh từ C++ if needed
+ Debug.Log("[Cuong] OnPrtcWorldChat");
+ return true;
+ }
+
+ /*private void OnTaskChatMessage(byte[] pBuf, int sz)
+ {
+ ... logic ẩn ...
+ }*/
+
+ private bool OnBattleChatMessage(chatmessage p, List pPendingFactions)
+ {
+ // Tương đương OnBattleChatMessage trong C++
+ // Hiện tại đơn giản hóa việc hiển thị, thực tế cần parse nội dung Battle cụ thể
+ Debug.Log($"[Battle Chat] RoleID: {p.Srcroleid}");
+ return true;
+ }
+
+ private bool OnFortressChatMessage(chatmessage p, List pPendingFactions)
+ {
+ // Tương đương OnFortressChatMessage trong C++
+ Debug.Log($"[Fortress Chat] RoleID: {p.Srcroleid}");
+ return true;
+ }
+
+ private bool OnKingChatMessage(chatmessage p, bool bGetPlayerName = true)
+ {
+ // Tương đương OnKingChatMessage trong C++
+ Debug.Log($"[King Chat] RoleID: {p.Srcroleid}");
+ return true;
+ }
+
+ private void OnFactionPVPChatMessage(chatmessage p)
+ {
+ // Tương đương OnFactionPVPChatMessage trong C++
+ Debug.Log($"[FactionPVP Chat] RoleID: {p.Srcroleid}");
+ }
+
+ private bool OnPrtcChatMessage(Protocol pProtocol, bool bCalledagain)
+ {
+ CECGameUIMan pGameUI = EC_Game.GetGameRun().GetUIManager().GetInGameUIMan();
+
chatmessage p = (chatmessage)pProtocol;
+ //var channel = (ChatChannel)p.Channel;
+ Debug.Log("[Cuong] reciver chat channel: " + p.Channel);
- string strTemp = System.Text.Encoding.Unicode.GetString(p.Msg.ToArray(), 0, p.Msg.Length);
+ if (Chat_GameSession.ShouldBlockByLevel(p))
+ {
+ Debug.Log("[Cuong] 1");
+ return true;
+ }
- _logger.Log(LogType.Warning, $"HoangDev : OnPrtcChatMessage :{strTemp}");
- EventBus.Publish(new ChatMessageEvent(strTemp));
+ EC_IvtrItem pItem = CHAT_S2C.CreateChatItem(p.Data);
+
+ string szMsg = null;
+ string strTemp = Encoding.Unicode.GetString(p.Msg.ToArray(), 0, p.Msg.Length);
+ string strMsgOrigion = strTemp;
+ // Todo: Show Text on Ui Game
+ //strTemp = pGameUI.FilterInvalidTags(strTemp, pItem==NULL);
+ /*if (!Chat_GameSession.PolicyResolver(pProtocol, p, ref strTemp))
+ {
+ Debug.Log("[Cuong] 2");
+ return false;
+ }
+
+ if (Chat_GameSession.HanldeGPChatSystem(p, bCalledagain))
+ {
+ Debug.Log("[Cuong] 3");
+ }*/
+
+ if (p.Channel is (byte)ChatChannel.GP_CHAT_BROADCAST
+ or (byte)ChatChannel.GP_CHAT_SYSTEM || p.Srcroleid == 0)
+ {
+ if (p.Channel == (byte)ChatChannel.GP_CHAT_SYSTEM && p.Srcroleid > 0)
+ {
+ switch (p.Srcroleid)
+ {
+ case 1: case 2: case 3: case 4: case 6: case 7: // Battle Message
+ if (!bCalledagain)
+ {
+ List pending = new List();
+ if (!OnBattleChatMessage(p, pending))
+ {
+ // Handle pending faction info
+ return false;
+ }
+ }
+ break;
+ case 18: case 19: case 20: case 21: case 22: // Auction Message
+ // pGameUI.AddSysAuctionMessage(...)
+ Debug.Log("[Auction] " + strTemp);
+ EventBus.Publish(new ChatMessageEvent(strTemp, p.Channel));
+ break;
+ case 24: // Task Message
+ // OnTaskChatMessage(p.Data.RawBuffer, p.Data.Size);
+ break;
+ case 29: case 30: case 31: case 32: case 33: case 34:
+ case 35: case 36: case 37: case 38: case 39: case 40:
+ case 41: case 42: case 43: case 45: // Fortress Message
+ OnFortressChatMessage(p, null);
+ break;
+ case 46: case 47: case 48: case 49: // Country Battle
+ // OnCountryChatMessage(p);
+ break;
+ case 50: case 51: case 52: case 53: case 54:
+ case 55: case 56: case 57: case 58: case 59: // King Chat
+ OnKingChatMessage(p);
+ break;
+ case 60: case 61: case 62: case 63: case 64: // Faction PVP
+ OnFactionPVPChatMessage(p);
+ break;
+ }
+ }
+ else
+ {
+ Debug.Log("[Cuong] 5");
+ EventBus.Publish(new ChatMessageEvent(strTemp, p.Channel));
+ }
+ }else if (p.Channel == (byte)ChatChannel.GP_CHAT_INSTANCE && p.Srcroleid == 1)
+ {
+ Debug.Log("[Cuong] 6");
+ // Chat_GameSession.AUICTranslate trans;
+ // EC_Game.GetGameRun().GetUIManager().GetInGameUIMan().AddHeartBeatHint(trans.Translate(szMsg ));
+ }
+ else
+ {
+ Debug.Log("[Cuong] Other");
+ CECStringTab pStrTab = EC_Game.GetFixedMsgs();
+
+ if (ISPLAYERID(p.Srcroleid))
+ {
+ string szName = EC_Game.GetGameRun().GetPlayerName(p.Srcroleid, false);
+ if (string.IsNullOrEmpty(strTemp))
+ {
+ Debug.Log("[Cuong] Other 0");
+ if (!bCalledagain)
+ {
+ Chat_GameSession.AddElemForPendingProtocols(pProtocol);
+ Chat_GameSession.AddChatPlayerID(p.Srcroleid);
+ }
+ return false;
+ }
+ else
+ {
+ Debug.Log("[Cuong] Other 1");
+ char[] szText = new char[80];
+ AUICommon.AUI_ConvertChatString(ref szName,ref szText, false);
+
+ string fmt = AUICommon.ConvertPrintfToCSharpFormat(pStrTab.GetWideString((int)FixedMsg.FIXMSG_CHAT));
+ string str = string.Format(
+ fmt,
+ szName,
+ strTemp
+ );
+ // Convert to EventBus
+ /*EC_Game.GetGameRun().AddChatMessage(strTemp, p.Channel, p.Srcroleid,
+ null, 0, p.Emotion, null, strMsgOrigion);*/
+ EventBus.Publish(new ChatMessageEvent(str, p.Channel));
+ // Set player's last said words
+ CECPlayer pPlayer = EC_Game.GetGameRun().GetWorld().GetPlayerMan().GetPlayer(p.Srcroleid);
+ if (pPlayer != null)
+ {
+ EventBus.PublishChannel(p.Srcroleid, new EventChatMessageOnTopPlayer(p.Srcroleid, strTemp));
+ //pPlayer.SetLastSaidWords(strTemp, p.Emotion);
+ }
+ }
+ }
+ else if(ISNPCID(p.Srcroleid))
+ {
+ Debug.Log("[Cuong] ISNPCID " + strTemp);
+ CECNPC pNPC = EC_Game.GetGameRun().GetWorld().GetNPCMan().GetNPC(p.Srcroleid);
+
+ if (pNPC != null)
+ {
+ string str;
+ string template = AUICommon.ConvertPrintfToCSharpFormat(pStrTab.GetWideString((int)FixedMsg.FIXMSG_CHAT2));
+
+ string message = string.Format(
+ template,
+ pNPC.GetName(),
+ strTemp
+ );
+
+ EC_Game.GetGameRun().AddChatMessage(
+ message,
+ p.Channel,
+ p.Srcroleid,
+ null,
+ 0,
+ p.Emotion
+ );
+ EventBus.Publish(new ChatMessageEvent(message));
+
+ CECUIHelper.RemoveNameFlagFromNPCChat(strTemp, out szMsg);
+
+ pNPC.SetLastSaidWords(szMsg);
+ }
+ }
+ }
+ return true;
}
public struct ChatMessageEvent
{
public string context;
+ public byte channel;
- public ChatMessageEvent(string context)
+ public ChatMessageEvent(string context, byte channel = 0)
{
this.context = context;
+ this.channel = channel;
}
}
public void OnPrtcGetConfigRe(Protocol pProtocol)
@@ -1733,7 +2094,7 @@ namespace CSNetwork
EC_Game.GetConfigs().ApplyUserSetting();
}
- // Now, Get config data request is sent after all host initial data ready.
+ // Now, Get config data request is sent after all host initial data ready.
// so when we receive this reply, we can do some last work before game
// really starts. Maybe it's not the best place to do these work, but
// now we do it here.
@@ -1744,7 +2105,7 @@ namespace CSNetwork
pGameUI.EnableUI(true);
// Get referral name for adding friend or other display
- //TODO: a Hung lam phan select role info di
+ //TODO: a Hung lam phan select role info di
/* RoleInfo info = EC_Game.GetGameRun().GetSelectedRoleInfo();
if (info.referrer_role > 0)
GetPlayerBriefInfo(1, info.referrer_role, 2);*/
@@ -1765,7 +2126,7 @@ namespace CSNetwork
CECMCDownload::GetInstance().SendGetDownloadOK();*/
}
}
-
+
private void OnPrtcSetConfigRe(Protocol pProtocol)
{
SetUIConfig_Re p = (SetUIConfig_Re)pProtocol;
@@ -1775,12 +2136,12 @@ namespace CSNetwork
if (CECGameRun.Instance != null)
{
TestLogoutLogic.Instance.WasClientSendLogoutMessage = true;
-
+
CECGameRun.Instance.GetPendingLogOut().TriggerAll();
CECGameRun.Instance.GetPendingLogOut().Clear();
}
}
-
+
private void OnPrtcPlayerBaseInfoRe(Protocol pProtocol)
{
playerbaseinfo_re p = (playerbaseinfo_re)pProtocol;
@@ -1898,7 +2259,7 @@ namespace CSNetwork
BYTE* pBuf = (BYTE*)a_malloctemp(iSize);
if (!pBuf)
return;
-
+
((cmd_header*)pBuf)->cmd = C2S::GET_OTHER_EQUIP;
cmd_get_other_equip* pCmd = (cmd_get_other_equip*)(pBuf + sizeof (cmd_header));
@@ -1915,7 +2276,7 @@ namespace CSNetwork
var idlist = new int[iNumSend];
for (int i=0; i < iNumSend; i++)
idlist[i] = aIDs[iCount+i];
-
+
gamedatasend gamedatasend = new gamedatasend();
gamedatasend.Data = C2SCommandFactory.CreateGetOtherEquipCmd(iNumID, idlist);
SendProtocol(gamedatasend);
@@ -2031,7 +2392,7 @@ namespace CSNetwork
gamedatasend.Data = C2SCommandFactory.CreateNakeCmd(C2SCommand.CommandID.STAND_UP);
SendProtocol(gamedatasend);
}
-
+
public void c2s_SendCmdAutoTeamSetGoal(int type, int goal_id, int op)
{
gamedatasend gamedatasend = new gamedatasend();
@@ -2074,6 +2435,43 @@ namespace CSNetwork
SendProtocol(g);
}
+ /// Send PROTOCOL_ADDFRIEND(202). Port of CECGameSession::friend_Add(idPlayer, szName).
+ public void Friend_Add(int idPlayer, string name)
+ {
+ var p = new addfriend();
+ p.Srcroleid = m_iCharID;
+ p.Dstroleid = idPlayer;
+ if (!string.IsNullOrEmpty(name))
+ p.Dstname = new Octets(System.Text.Encoding.Unicode.GetBytes(name));
+ else
+ p.Dstname = new Octets();
+ p.Srclsid = (int)_localsid;
+ SendProtocol(p);
+ }
+
+ ///
+ /// Send RPC_ADDFRIENDRQST(204) response. Port of CECGameSession::friend_AddResponse(dwHandle, bAgree).
+ /// Answer to received friend request: xid from request, agree = true (0) or false (69).
+ /// Matches GNET Rpc XID: low bit = is_request; response must clear that bit.
+ ///
+ public void Friend_AddResponse(uint xid, bool agree)
+ {
+ const byte ERR_TRADE_AGREE = 0;
+ const byte ERR_TRADE_REFUSE = 69;
+ uint responseXid = xid & 0x7FFFFFFFu; // clear request bit, keep count
+ var p = new addfriendrqstres(responseXid, agree ? ERR_TRADE_AGREE : ERR_TRADE_REFUSE);
+ SendProtocol(p);
+ }
+
+ /// Send PROTOCOL_GETFRIENDS(206). Port of CECGameSession::friend_GetList().
+ public void Friend_GetList()
+ {
+ var p = new getfriends();
+ p.Roleid = m_iCharID;
+ p.Localsid = (int)_localsid;
+ SendProtocol(p);
+ }
+
public void c2s_SendCmdTeamKickMember(int idMember)
{
var g = new gamedatasend();
@@ -2082,7 +2480,7 @@ namespace CSNetwork
}
public void c2s_SendCmdTeamLeaveParty()
- {
+ {
var g = new gamedatasend();
g.Data = C2SCommandFactory.CreateTeamLeavePartyCommand();
SendProtocol(g);
@@ -2119,9 +2517,9 @@ namespace CSNetwork
public void c2s_CmdGoto(float x, float y, float z)
{
- c2s_SendCmdGoto(x, y, z);
+ c2s_SendCmdGoto(x, y, z);
}
-
+
// Send C2S::GOTO command data
void c2s_SendCmdGoto(float x, float y, float z)
{
@@ -2248,7 +2646,7 @@ namespace CSNetwork
gamedatasend.Data = C2SCommandFactory.CreateNPCSevRestorePetCmd(iPetIdx);
SendProtocol(gamedatasend);
}
-
+
// Cross-server get in (C++: c2s_CmdNPCSevCrossServerGetIn) — TODO: implement C2S packet when needed
public void c2s_CmdNPCSevCrossServerGetIn()
{
@@ -2260,6 +2658,6 @@ namespace CSNetwork
{
// TODO: C2SCommandFactory.CreateNPCSevCrossServerGetOutCmd() and SendProtocol
}
-
+
}
-}
\ No newline at end of file
+}
diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/OctetsStream.cs b/Assets/PerfectWorld/Scripts/Network/CSNetwork/OctetsStream.cs
index 5e9d7affe4..24402c1b0b 100644
--- a/Assets/PerfectWorld/Scripts/Network/CSNetwork/OctetsStream.cs
+++ b/Assets/PerfectWorld/Scripts/Network/CSNetwork/OctetsStream.cs
@@ -109,6 +109,23 @@ namespace CSNetwork
_position += 4;
}
+ /// Write int32 in little-endian (for GNET protocol compatibility with C++ client/server).
+ public void WriteInt32LE(int value)
+ {
+ var bytes = BitConverter.GetBytes(value);
+ _octets.Insert(_position, bytes);
+ _position += 4;
+ }
+
+ /// Read int32 in little-endian (for GNET protocol compatibility with C++ client/server).
+ public int ReadInt32LE()
+ {
+ if (_position + 4 > _octets.Length)
+ throw new IndexOutOfRangeException("Attempt to read beyond the end of the stream.");
+ var bytes = ReadBytes(4);
+ return BitConverter.ToInt32(bytes, 0);
+ }
+
public void Write(float value)
{
var bytes = BitConverter.GetBytes(value);
diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/addfriend_re.cs b/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/addfriend_re.cs
new file mode 100644
index 0000000000..778976ce52
--- /dev/null
+++ b/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/addfriend_re.cs
@@ -0,0 +1,43 @@
+using CSNetwork.Protocols.RPCData;
+
+namespace CSNetwork.Protocols
+{
+ /// PROTOCOL_ADDFRIEND_RE(203). Port of GNET::AddFriend_Re (inl/addfriend_re).
+ public class addfriend_re : Protocol
+ {
+ public byte retcode { get; set; }
+ public GFriendInfo info { get; set; }
+ public uint srclsid { get; set; }
+
+ public addfriend_re() : base(ProtocolType.PROTOCOL_ADDFRIEND_RE)
+ {
+ info = new GFriendInfo();
+ }
+
+ public override Protocol Clone() => new addfriend_re
+ {
+ retcode = retcode,
+ info = info != null ? new GFriendInfo { rid = info.rid, cls = info.cls, gid = info.gid, name = new Octets(info.name?.ToArray() ?? System.Array.Empty()) } : new GFriendInfo(),
+ srclsid = srclsid
+ };
+
+ public override void Marshal(OctetsStream os)
+ {
+ os.Write(retcode);
+ if (info != null) info.Marshal(os); else new GFriendInfo().Marshal(os);
+ os.Write(srclsid);
+ }
+
+ public override void Unmarshal(OctetsStream os)
+ {
+ retcode = os.ReadByte();
+ info = new GFriendInfo();
+ info.Unmarshal(os);
+ srclsid = os.ReadUInt32();
+ }
+
+ public override int PriorPolicy() => 1;
+
+ public override bool SizePolicy(int size) => size <= 128;
+ }
+}
diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/addfriend_re.cs.meta b/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/addfriend_re.cs.meta
new file mode 100644
index 0000000000..8c52d27971
--- /dev/null
+++ b/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/addfriend_re.cs.meta
@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: 158e35cf46fa51a4cba4fa7485fdb534
\ No newline at end of file
diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/addfriendrqst.cs b/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/addfriendrqst.cs
new file mode 100644
index 0000000000..a52735a7ae
--- /dev/null
+++ b/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/addfriendrqst.cs
@@ -0,0 +1,47 @@
+using System;
+
+namespace CSNetwork.Protocols
+{
+ /// RPC_ADDFRIENDRQST(204). Port of GNET AddFriendRqst (argument + xid). Server notifies target of friend request. Body: xid (4) + AddFriendRqstArg.
+ public class addfriendrqst : Protocol
+ {
+ /// RPC transaction id; must be sent back in addfriendrqstres so server can match the response.
+ public uint Xid { get; set; }
+ public int Srcroleid { get; set; }
+ public Octets Srcname { get; set; }
+ public uint Dstlsid { get; set; }
+
+ public addfriendrqst() : base(ProtocolType.RPC_ADDFRIENDRQST)
+ {
+ Srcname = new Octets();
+ }
+
+ public override Protocol Clone() => new addfriendrqst
+ {
+ Xid = Xid,
+ Srcroleid = Srcroleid,
+ Srcname = new Octets(Srcname.ToArray()),
+ Dstlsid = Dstlsid
+ };
+
+ public override void Marshal(OctetsStream os)
+ {
+ os.Write(Xid);
+ os.Write(Srcroleid);
+ os.Write(Srcname);
+ os.Write(Dstlsid);
+ }
+
+ public override void Unmarshal(OctetsStream os)
+ {
+ Xid = os.ReadUInt32();
+ Srcroleid = os.ReadInt32();
+ Srcname = os.ReadOctets();
+ Dstlsid = os.ReadUInt32();
+ }
+
+ public override int PriorPolicy() => 1;
+
+ public override bool SizePolicy(int size) => size <= 256;
+ }
+}
diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/addfriendrqst.cs.meta b/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/addfriendrqst.cs.meta
new file mode 100644
index 0000000000..d935487cb5
--- /dev/null
+++ b/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/addfriendrqst.cs.meta
@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: bf82fc1afd675674588f017b6f9e0621
\ No newline at end of file
diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/addfriendrqstres.cs b/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/addfriendrqstres.cs
new file mode 100644
index 0000000000..77836886de
--- /dev/null
+++ b/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/addfriendrqstres.cs
@@ -0,0 +1,44 @@
+using System;
+
+namespace CSNetwork.Protocols
+{
+ ///
+ /// RPC_ADDFRIENDRQST(204) response. Port of GNET Rpc marshal (xid + AddFriendRqstRes).
+ /// Client sends this to answer a friend request: retcode 0 = agree, 69 = refuse (ERR_TRADE_AGREE / ERR_TRADE_REFUSE).
+ ///
+ public class addfriendrqstres : Protocol
+ {
+ /// RPC transaction id from the received addfriendrqst; server uses it to match the response.
+ public uint Xid { get; set; }
+ /// 0 = ERR_TRADE_AGREE (accept), 69 = ERR_TRADE_REFUSE (decline).
+ public byte retcode { get; set; }
+
+ public addfriendrqstres() : base(ProtocolType.RPC_ADDFRIENDRQST)
+ {
+ }
+
+ public addfriendrqstres(uint xid, byte retcode) : base(ProtocolType.RPC_ADDFRIENDRQST)
+ {
+ Xid = xid;
+ this.retcode = retcode;
+ }
+
+ public override Protocol Clone() => new addfriendrqstres(Xid, retcode);
+
+ public override void Marshal(OctetsStream os)
+ {
+ os.Write(Xid);
+ os.Write(retcode);
+ }
+
+ public override void Unmarshal(OctetsStream os)
+ {
+ Xid = os.ReadUInt32();
+ retcode = os.ReadByte();
+ }
+
+ public override int PriorPolicy() => 1;
+
+ public override bool SizePolicy(int size) => size <= 64;
+ }
+}
diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/addfriendrqstres.cs.meta b/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/addfriendrqstres.cs.meta
new file mode 100644
index 0000000000..6391223f99
--- /dev/null
+++ b/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/addfriendrqstres.cs.meta
@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: 80bb3b37b64736040a16d67848d9f953
\ No newline at end of file
diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/friendextlist.cs b/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/friendextlist.cs
index 30c038650e..1f05c3502c 100644
--- a/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/friendextlist.cs
+++ b/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/friendextlist.cs
@@ -1,11 +1,14 @@
using System;
using System.Collections.Generic;
+using CSNetwork.Protocols.RPCData;
namespace CSNetwork.Protocols
{
public class friendextlist : Protocol
{
public int Roleid { get; set; }
+ public List ExtraInfo { get; set; } = new List();
+ public List SendInfo { get; set; } = new List();
public int Localsid { get; set; }
public friendextlist() : base(ProtocolType.PROTOCOL_FRIENDEXTLIST)
@@ -16,18 +19,26 @@ namespace CSNetwork.Protocols
public override Protocol Clone() => new friendextlist
{
Roleid = Roleid,
+ ExtraInfo = new List(ExtraInfo ?? new List()),
+ SendInfo = new List(SendInfo ?? new List()),
Localsid = Localsid
};
public override void Marshal(OctetsStream os)
{
os.Write(Roleid);
+ os.WriteList(ExtraInfo ?? new List());
+ os.WriteList(SendInfo ?? new List());
os.Write(Localsid);
}
public override void Unmarshal(OctetsStream os)
{
Roleid = os.ReadInt32();
+ ExtraInfo = new List();
+ os.ReadList(ExtraInfo);
+ SendInfo = new List();
+ os.ReadList(SendInfo);
Localsid = os.ReadInt32();
}
diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/getfriends_re.cs b/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/getfriends_re.cs
new file mode 100644
index 0000000000..56ecc4febc
--- /dev/null
+++ b/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/getfriends_re.cs
@@ -0,0 +1,61 @@
+using System;
+using System.Collections.Generic;
+using CSNetwork.Protocols.RPCData;
+
+namespace CSNetwork.Protocols
+{
+ /// PROTOCOL_GETFRIENDS_RE(207). Server response to getfriends(206).
+ public class getfriends_re : Protocol
+ {
+ public int Roleid { get; set; }
+ public List Groups { get; set; } = new List();
+ public List Friends { get; set; } = new List();
+ public List Status { get; set; } = new List();
+ public int Localsid { get; set; }
+
+ public getfriends_re() : base(ProtocolType.PROTOCOL_GETFRIENDS_RE)
+ {
+ }
+
+ public override Protocol Clone() => new getfriends_re
+ {
+ Roleid = Roleid,
+ Groups = new List(Groups ?? new List()),
+ Friends = new List(Friends ?? new List()),
+ Status = new List(Status ?? new List()),
+ Localsid = Localsid
+ };
+
+ public override void Marshal(OctetsStream os)
+ {
+ os.Write(Roleid);
+ os.WriteList(Groups ?? new List());
+ os.WriteList(Friends ?? new List());
+ os.WriteCompactUInt((uint)(Status?.Count ?? 0));
+ if (Status != null)
+ {
+ for (int i = 0; i < Status.Count; i++)
+ os.Write(Status[i]);
+ }
+ os.Write(Localsid);
+ }
+
+ public override void Unmarshal(OctetsStream os)
+ {
+ Roleid = os.ReadInt32();
+ Groups = new List();
+ os.ReadList(Groups);
+ Friends = new List();
+ os.ReadList(Friends);
+ uint sc = os.ReadCompactUInt();
+ Status = new List((int)sc);
+ for (int i = 0; i < sc; i++)
+ Status.Add(os.ReadByte());
+ Localsid = os.ReadInt32();
+ }
+
+ public override int PriorPolicy() => 1;
+
+ public override bool SizePolicy(int size) => size <= 8192;
+ }
+}
diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/getfriends_re.cs.meta b/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/getfriends_re.cs.meta
new file mode 100644
index 0000000000..2deea0dd28
--- /dev/null
+++ b/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/getfriends_re.cs.meta
@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: bd80f916689adb4488d055af7d1f0465
\ No newline at end of file
diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/rpcdata/GFriendExtInfo.cs b/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/rpcdata/GFriendExtInfo.cs
new file mode 100644
index 0000000000..203e96eff6
--- /dev/null
+++ b/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/rpcdata/GFriendExtInfo.cs
@@ -0,0 +1,51 @@
+namespace CSNetwork.Protocols.RPCData
+{
+ /// Port of GNET::GFriendExtInfo (rpcdata/gfriendextinfo).
+ public class GFriendExtInfo : IMarshallable
+ {
+ public int uid;
+ public int rid;
+ public int level;
+ public int last_logintime;
+ public int update_time;
+ public byte reincarnation_times;
+ public Octets remarks;
+ public short reserved1;
+ public int reserved2;
+ public int reserved3;
+
+ public GFriendExtInfo()
+ {
+ remarks = new Octets();
+ }
+
+ public void Marshal(OctetsStream os)
+ {
+ os.Write(uid);
+ os.Write(rid);
+ os.Write(level);
+ os.Write(last_logintime);
+ os.Write(update_time);
+ os.Write(reincarnation_times);
+ os.Write(remarks ?? new Octets());
+ os.Write(reserved1);
+ os.Write(reserved2);
+ os.Write(reserved3);
+ }
+
+ public void Unmarshal(OctetsStream os)
+ {
+ uid = os.ReadInt32();
+ rid = os.ReadInt32();
+ level = os.ReadInt32();
+ last_logintime = os.ReadInt32();
+ update_time = os.ReadInt32();
+ reincarnation_times = os.ReadByte();
+ remarks = os.ReadOctets();
+ reserved1 = os.ReadInt16();
+ reserved2 = os.ReadInt32();
+ reserved3 = os.ReadInt32();
+ }
+ }
+}
+
diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/rpcdata/GFriendExtInfo.cs.meta b/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/rpcdata/GFriendExtInfo.cs.meta
new file mode 100644
index 0000000000..3ce1c12b2c
--- /dev/null
+++ b/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/rpcdata/GFriendExtInfo.cs.meta
@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: cbd227cebee40b0438f44b5a52f47459
\ No newline at end of file
diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/rpcdata/GFriendInfo.cs b/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/rpcdata/GFriendInfo.cs
new file mode 100644
index 0000000000..c592b4b9f8
--- /dev/null
+++ b/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/rpcdata/GFriendInfo.cs
@@ -0,0 +1,32 @@
+namespace CSNetwork.Protocols.RPCData
+{
+ /// Port of GNET::GFriendInfo (rpcdata/gfriendinfo).
+ public class GFriendInfo : IMarshallable
+ {
+ public int rid;
+ public byte cls;
+ public byte gid;
+ public Octets name;
+
+ public GFriendInfo()
+ {
+ name = new Octets();
+ }
+
+ public void Marshal(OctetsStream os)
+ {
+ os.Write(rid);
+ os.Write(cls);
+ os.Write(gid);
+ os.Write(name ?? new Octets());
+ }
+
+ public void Unmarshal(OctetsStream os)
+ {
+ rid = os.ReadInt32();
+ cls = os.ReadByte();
+ gid = os.ReadByte();
+ name = os.ReadOctets();
+ }
+ }
+}
diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/rpcdata/GFriendInfo.cs.meta b/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/rpcdata/GFriendInfo.cs.meta
new file mode 100644
index 0000000000..0a4b947df7
--- /dev/null
+++ b/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/rpcdata/GFriendInfo.cs.meta
@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: a0bf31ab9d8853a479215aa7e1fa5e94
\ No newline at end of file
diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/rpcdata/GGroupInfo.cs b/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/rpcdata/GGroupInfo.cs
new file mode 100644
index 0000000000..e04ffdfdd5
--- /dev/null
+++ b/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/rpcdata/GGroupInfo.cs
@@ -0,0 +1,27 @@
+namespace CSNetwork.Protocols.RPCData
+{
+ /// Port of GNET::GGroupInfo (rpcdata/ggroupinfo).
+ public class GGroupInfo : IMarshallable
+ {
+ public byte gid;
+ public Octets name;
+
+ public GGroupInfo()
+ {
+ name = new Octets();
+ }
+
+ public void Marshal(OctetsStream os)
+ {
+ os.Write(gid);
+ os.Write(name ?? new Octets());
+ }
+
+ public void Unmarshal(OctetsStream os)
+ {
+ gid = os.ReadByte();
+ name = os.ReadOctets();
+ }
+ }
+}
+
diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/rpcdata/GGroupInfo.cs.meta b/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/rpcdata/GGroupInfo.cs.meta
new file mode 100644
index 0000000000..03cb0beee3
--- /dev/null
+++ b/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/rpcdata/GGroupInfo.cs.meta
@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: 14af8f8307d31b94585bf4526fcdc1b1
\ No newline at end of file
diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/rpcdata/GSendAUMailRecord.cs b/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/rpcdata/GSendAUMailRecord.cs
new file mode 100644
index 0000000000..ebdf64d2c0
--- /dev/null
+++ b/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/rpcdata/GSendAUMailRecord.cs
@@ -0,0 +1,22 @@
+namespace CSNetwork.Protocols.RPCData
+{
+ /// Port of GNET::GSendAUMailRecord (rpcdata/gsendaumailrecord).
+ public class GSendAUMailRecord : IMarshallable
+ {
+ public int rid;
+ public int sendmail_time;
+
+ public void Marshal(OctetsStream os)
+ {
+ os.Write(rid);
+ os.Write(sendmail_time);
+ }
+
+ public void Unmarshal(OctetsStream os)
+ {
+ rid = os.ReadInt32();
+ sendmail_time = os.ReadInt32();
+ }
+ }
+}
+
diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/rpcdata/GSendAUMailRecord.cs.meta b/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/rpcdata/GSendAUMailRecord.cs.meta
new file mode 100644
index 0000000000..72df71bfd2
--- /dev/null
+++ b/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/rpcdata/GSendAUMailRecord.cs.meta
@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: c573cfeb052d9f840891d71dfbaecd6a
\ No newline at end of file
diff --git a/Assets/PerfectWorld/Scripts/Network/UnityGameSession.cs b/Assets/PerfectWorld/Scripts/Network/UnityGameSession.cs
index ddf8312fb7..e2ddc41577 100644
--- a/Assets/PerfectWorld/Scripts/Network/UnityGameSession.cs
+++ b/Assets/PerfectWorld/Scripts/Network/UnityGameSession.cs
@@ -163,6 +163,9 @@ namespace BrewMonster.Network
{
BaseSecurity.Initizalize();
ProtocolFactory.RegisterAllProtocols();
+ // Type 204 is used for both addfriendrqst (server→client request) and addfriendrqstres (client→server response).
+ // Client only receives addfriendrqst; ensure decode uses it so we don't get InvalidCastException.
+ Protocol.Register((uint)ProtocolType.RPC_ADDFRIENDRQST);
_gameSession = new GameSession();
#if UNITY_EDITOR
var path = Application.dataPath.Substring(0, Application.dataPath.LastIndexOf("Assets"));
@@ -173,7 +176,9 @@ namespace BrewMonster.Network
// Subscribe to unexpected disconnects
_gameSession.Disconnected += OnUnexpectedDisconnect;
-
+ _gameSession.FriendRequestReceived += OnFriendRequestReceived;
+ _gameSession.AddFriendResultReceived += OnAddFriendResultReceived;
+
_isInitialized = true;
DontDestroyOnLoad(gameObject);
@@ -184,6 +189,8 @@ namespace BrewMonster.Network
// Tell LoginScene what to show next.
LogoutFlowState.NextLoginEntry = entryTarget;
_gameSession.Disconnected -= OnUnexpectedDisconnect;
+ _gameSession.FriendRequestReceived -= OnFriendRequestReceived;
+ _gameSession.AddFriendResultReceived -= OnAddFriendResultReceived;
EC_ManMessageMono.Instance.CECNPCMan.Release();
if (clearSavedCreds)
@@ -632,6 +639,20 @@ namespace BrewMonster.Network
{
Instance._gameSession.c2s_SendCmdDuelReply(accept, idInviter);
}
+ /// Send PROTOCOL_ADDFRIEND(202). Port of CECGameSession::friend_Add.
+ public static void Friend_Add(int idPlayer, string name)
+ {
+ Instance._gameSession.Friend_Add(idPlayer, name ?? "");
+ }
+ /// Send PROTOCOL_GETFRIENDS(206). Port of CECGameSession::friend_GetList().
+ public static void Friend_GetList()
+ {
+ Instance._gameSession.Friend_GetList();
+ }
+ public static void Friend_AddResponse(uint xid, bool agree)
+ {
+ Instance._gameSession.Friend_AddResponse(xid, agree);
+ }
public static void c2s_CmdTeamKickMember(int idMember)
{
Instance._gameSession.c2s_SendCmdTeamKickMember(idMember);
@@ -712,6 +733,26 @@ namespace BrewMonster.Network
///
/// Handles unexpected server disconnections. Shows a message box and returns to login.
///
+ private void OnFriendRequestReceived(uint xid, int srcroleid, string askerName)
+ {
+ string name = string.IsNullOrEmpty(askerName) ? ("Player " + srcroleid) : askerName;
+ CECUIManager.Instance?.ShowMessageBoxYesAndNo(
+ title: "Friend Request",
+ message: $"{name} wants to add you as a friend.",
+ dlg: null,
+ onClickedYes: () => Friend_AddResponse(xid, agree: true),
+ onClickedNo: () => Friend_AddResponse(xid, agree: false));
+ }
+
+ private void OnAddFriendResultReceived(byte retcode, string message)
+ {
+ CECUIManager.Instance?.ShowMessageBoxYes(
+ title: retcode == 0 ? "Friend added" : "Add friend failed",
+ message: message,
+ dlg: null,
+ null);
+ }
+
private void OnUnexpectedDisconnect()
{
// If this was an intentional disconnect (logout), skip UI
@@ -722,16 +763,13 @@ namespace BrewMonster.Network
}
// Show disconnect message box
- CECUIManager.Instance?.ShowMessageBox(
- title: "Disconnected",
- message: "Connection to the server has been lost.",
- messageBoxType: MessageBoxType.YesButton,
- onClickedYes: () =>
+ CECUIManager.Instance?.ShowMessageBoxYes("Disconnected", "Connection to the server has been lost.", null,
+ () =>
{
// Return to login screen
LogoutAccount();
- }
- );
+ });
+
}
public static void c2s_CmdGoto(float x, float y, float z)
diff --git a/Assets/PerfectWorld/Scripts/Players/EC_ElsePlayer.cs b/Assets/PerfectWorld/Scripts/Players/EC_ElsePlayer.cs
index 25fdf4a58b..f9878ddd59 100644
--- a/Assets/PerfectWorld/Scripts/Players/EC_ElsePlayer.cs
+++ b/Assets/PerfectWorld/Scripts/Players/EC_ElsePlayer.cs
@@ -2,6 +2,7 @@ using BrewMonster;
using BrewMonster.Managers;
using BrewMonster.Network;
using BrewMonster.Scripts;
+using BrewMonster.Scripts.Skills;
using CSNetwork;
using CSNetwork.GPDataType;
using CSNetwork.Protocols;
@@ -452,13 +453,51 @@ namespace BrewMonster
case EC_MsgDef.MSG_PM_PLAYERBASEINFO: OnMsgPlayerBaseInfo(Msg); break;
case EC_MsgDef.MSG_PM_PLAYEREQUIPDATA: OnMsgPlayerEquipData(Msg); break;
case EC_MsgDef.MSG_PM_PLAYERATKRESULT: OnMsgPlayerAtkResult(Msg); break;
+ case EC_MsgDef.MSG_PM_CASTSKILL: OnMsgPlayerCastSkill(Msg); break;
+ case EC_MsgDef.MSG_PM_ENCHANTRESULT: OnMsgEnchantResult(Msg); break;
case EC_MsgDef.MSG_PM_PLAYERDOEMOTE: OnMsgPlayerDoEmote(Msg); break;
+ case EC_MsgDef.MSG_PM_PLAYERSKILLRESULT: OnMsgPlayerSkillResult(Msg); break;
case EC_MsgDef.MSG_PM_PLAYERGATHER: OnMsgPlayerGather(Msg); break;
case EC_MsgDef.MSG_PM_PLAYERMOUNT: OnMsgPlayerMount(Msg); break;
}
return true;
}
+ ///
+ /// Handles skill attack result messages for else players.
+ ///
+ /// This method is called when the server sends MSG_PM_PLAYERSKILLRESULT (OBJECT_SKILL_ATTACK_RESULT).
+ /// Unlike OnMsgPlayerAtkResult which handles melee attacks, this handles skill attacks specifically.
+ ///
+ /// Flow:
+ /// 1. Parse cmd_object_skill_attack_result (includes skill_id directly)
+ /// 2. Face target
+ /// 3. Call PlayAttackEffect with skill_id from command (triggers GFX system)
+ /// 4. Enter fight state if skill is attack or curse type
+ ///
+ /// C++ equivalent: CECElsePlayer::OnMsgPlayerSkillResult (EC_ElsePlayer.cpp:1787)
+ ///
+ private void OnMsgPlayerSkillResult(ECMSG Msg)
+ {
+ cmd_object_skill_attack_result pCmd = GPDataTypeHelper.FromBytes((byte[])Msg.dwParam1);
+
+ // Face to target
+ TurnFaceTo(pCmd.target_id);
+
+ // Call PlayAttackEffect with skill_id directly from command (like C++ does)
+ // Unlike OnMsgPlayerAtkResult, we get skill_id from the command structure, not from m_pCurSkill
+ int attackTime = int.MinValue;
+ PlayAttackEffect(pCmd.target_id, pCmd.skill_id, 0, -1,
+ (uint)pCmd.attack_flag, pCmd.speed * 50, ref attackTime, pCmd.section);
+
+ // Check skill type and enter fight state if needed (matching C++ logic)
+ byte skillType = ElementSkill.GetType((uint)pCmd.skill_id);
+ if (skillType == (byte)skill_type.TYPE_ATTACK || skillType == (byte)skill_type.TYPE_CURSE)
+ {
+ EnterFightState();
+ }
+ }
+
public void HandleRevive(short sReviveType, A3DVECTOR3 pos)
{
SetServerPos(pos);
@@ -494,7 +533,7 @@ namespace BrewMonster
}
}
- public void OnMsgPlayerEquipData(ECMSG Msg)
+ public async void OnMsgPlayerEquipData(ECMSG Msg)
{
// using namespace S2C;
@@ -528,12 +567,32 @@ namespace BrewMonster
}
// // Change equipment
- ChangeEquipments(bReset, crc, iAddMask, iDelMask, aAdded);
+ // ChangeEquipments(bReset, crc, iAddMask, iDelMask, aAdded);
+ await QueueChangeEquipments(bReset, crc, iAddMask, iDelMask, aAdded);
}
+ private async UniTask QueueChangeEquipments(bool bReset, int crc, long iAddMask, long iDelMask, int[] aAddedEquip)
+ {
+ while (!IsPlayerModelReady)
+ {
+ await UniTask.DelayFrame(1);
+ }
+ ChangeEquipments(bReset, crc, iAddMask, iDelMask, aAddedEquip);
+ }
+
+ ///
+ /// Handles attack result messages for else players (both melee and skill attacks).
+ ///
+ /// For skill attacks:
+ /// - Uses m_pCurSkill (set in OnMsgPlayerCastSkill) to get skill ID
+ /// - Calls PlayAttackEffect with skill ID, which triggers GFX system
+ /// - GFX system (A3DSkillGfxComposerMan) spawns effects at hook positions
+ ///
+ /// For melee attacks:
+ /// - idSkill is 0, triggers normal melee attack work
+ ///
void OnMsgPlayerAtkResult(ECMSG Msg)
{
-
cmd_object_atk_result pCmd = GPDataTypeHelper.FromBytes((byte[])Msg.dwParam1);
//ASSERT(pCmd && pCmd.attacker_id == m_PlayerInfo.cid);
@@ -542,16 +601,142 @@ namespace BrewMonster
// TO DO: fix later
int attackTime = int.MinValue;
- PlayAttackEffect(pCmd.target_id, 0, 0, -1, (uint)pCmd.attack_flag, pCmd.speed* 50, ref attackTime);
+ PlayAttackEffect(pCmd.target_id, 0, 0, -1, (uint)pCmd.attack_flag, pCmd.speed * 50, ref attackTime);
+ BMLogger.Log($"[ELSEPLAYER_SKILL_FLOW] PlayAttackEffect: Complete, attackTime={attackTime}");
- if (!m_pEPWorkMan.FindWork(CECEPWorkMan.Work_type.WT_NORMAL, CECEPWork.EP_work_ID.WORK_HACKOBJECT)){
- m_pEPWorkMan.StartNormalWork(new CECEPWorkMelee(m_pEPWorkMan, pCmd.target_id));
- }
+ if (!m_pEPWorkMan.FindWork(CECEPWorkMan.Work_type.WT_NORMAL, CECEPWork.EP_work_ID.WORK_HACKOBJECT))
+ {
+ m_pEPWorkMan.StartNormalWork(new CECEPWorkMelee(m_pEPWorkMan, pCmd.target_id));
+ }
// Enter fight state
EnterFightState();
}
-
+
+ ///
+ /// Handles skill casting messages from server for else players.
+ ///
+ /// Flow:
+ /// 1. Server sends OBJECT_CAST_SKILL -> This handler plays cast animation
+ /// 2. Server sends SKILL_PERFORM -> Skill execution begins (for durative skills)
+ /// 3. Server sends attack result -> OnMsgPlayerAtkResult triggers PlayAttackEffect
+ /// 4. PlayAttackEffect -> CECAttacksMan.AddSkillAttack -> GFX system spawns effects
+ /// 5. Server sends SKILL_INTERRUPTED -> Clears casting state (if interrupted)
+ ///
+ /// Note: Else players don't maintain skill lists, so we create temporary CECSkill objects
+ /// for tracking purposes only. The actual skill data comes from ElementSkill static methods.
+ ///
+ private void OnMsgPlayerCastSkill(ECMSG Msg)
+ {
+ int commandID = Convert.ToInt32(Msg.dwParam2);
+
+ switch (commandID)
+ {
+ case CommandID.OBJECT_CAST_SKILL:
+ {
+ cmd_object_cast_skill pCmd =
+ GPDataTypeHelper.FromBytes((byte[])Msg.dwParam1);
+
+ // Get skill object (else players don't have skill lists, so we create a temporary skill reference)
+ // For else players, we mainly need the skill ID for animation purposes
+ int skillID = pCmd.skill;
+
+ // Store current skill target
+ m_idCurSkillTarget = pCmd.target;
+
+ // Face the target
+ TurnFaceTo(pCmd.target);
+
+ // Play skill cast animation
+ PlaySkillCastAction(skillID);
+
+ // Create a temporary skill object for tracking (if needed)
+ // Note: Else players don't maintain skill lists like host player does
+ // We create a minimal skill object just for the current cast
+ if (m_pCurSkill == null || m_pCurSkill.GetSkillID() != skillID)
+ {
+ // Create a temporary skill object with level 1 (we don't know the actual level)
+ m_pCurSkill = new CECSkill(skillID, 1);
+ }
+
+ // Enter fight state
+ EnterFightState();
+
+ break;
+ }
+ case CommandID.OBJECT_CAST_INSTANT_SKILL:
+ {
+ cmd_object_cast_instant_skill pCmd =
+ GPDataTypeHelper.FromBytes((byte[])Msg.dwParam1);
+
+ int skillID = pCmd.skill;
+
+ m_idCurSkillTarget = pCmd.target;
+
+ TurnFaceTo(pCmd.target);
+ PlaySkillCastAction(skillID);
+
+ if (m_pCurSkill == null || m_pCurSkill.GetSkillID() != skillID)
+ {
+ m_pCurSkill = new CECSkill(skillID, 1);
+ }
+
+ EnterFightState();
+ break;
+ }
+ case CommandID.OBJECT_CAST_POS_SKILL:
+ {
+ cmd_object_cast_pos_skill pCmd =
+ GPDataTypeHelper.FromBytes((byte[])Msg.dwParam1);
+
+ int skillID = pCmd.skill;
+
+ // For position-based skills, target is the position, not an object
+ // We still play the cast animation
+ PlaySkillCastAction(skillID);
+
+ if (m_pCurSkill == null || m_pCurSkill.GetSkillID() != skillID)
+ {
+ m_pCurSkill = new CECSkill(skillID, 1);
+ }
+
+ EnterFightState();
+ break;
+ }
+ case CommandID.SKILL_PERFORM:
+ {
+ // Skill perform - the skill has finished casting and is being executed
+ // For else players, we keep m_pCurSkill until attack result is received
+ // This allows PlayAttackEffect to use the skill information
+ // Durative skills (channeling) will continue until interrupted
+ if (m_pCurSkill != null && m_pCurSkill.IsDurative())
+ {
+ // For durative skills, we keep the skill active
+ // It will be cleared when SKILL_INTERRUPTED is received
+ }
+ break;
+ }
+ case CommandID.SKILL_INTERRUPTED:
+ {
+ // Skill was interrupted, clear current skill
+ cmd_skill_interrupted pCmd =
+ GPDataTypeHelper.FromBytes((byte[])Msg.dwParam1);
+
+ if (m_pCurSkill != null)
+ {
+ StopSkillCastAction();
+ m_pCurSkill = null;
+ }
+ m_idCurSkillTarget = 0;
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ }
+
private async void LoadAppearGfx()
{
if (!m_pAppearGFX && m_iAppearFlag == (int)PlayerAppearFlag.APPEAR_ENTERWORLD)
@@ -809,6 +994,7 @@ namespace BrewMonster
m_iGender = iGender;
m_bBaseInfoReady = true;
SetPlayerName(szName ?? "");
+ EC_Game.GetGameRun().AddPlayerName(m_PlayerInfo.cid, szName, true);
}
// Level up
public void LevelUp()
diff --git a/Assets/PerfectWorld/Scripts/Skills/SkillStubs1/skill77.cs b/Assets/PerfectWorld/Scripts/Skills/SkillStubs1/skill77.cs
index cae168e840..1d40e59f34 100644
--- a/Assets/PerfectWorld/Scripts/Skills/SkillStubs1/skill77.cs
+++ b/Assets/PerfectWorld/Scripts/Skills/SkillStubs1/skill77.cs
@@ -120,7 +120,6 @@ namespace BrewMonster
m_AttFlyMode = (GfxAttackMode)0;
m_AttHitMode = (GfxAttackMode)0;
m_dwFlyTime = 200;
- m_bTraceTarget = true;
m_FlyClusterCount = 1;
m_FlyClusterInterval = 0;
m_HitClusterCount = 1;
diff --git a/Assets/PerfectWorld/Scripts/UI/CDlgMessageBox.cs b/Assets/PerfectWorld/Scripts/UI/CDlgMessageBox.cs
index 6e6d17c54b..80a16c67bc 100644
--- a/Assets/PerfectWorld/Scripts/UI/CDlgMessageBox.cs
+++ b/Assets/PerfectWorld/Scripts/UI/CDlgMessageBox.cs
@@ -1,8 +1,9 @@
-using System;
+using System;
using BrewMonster.UI;
using PerfectWorld.Scripts.Common;
using UnityEngine;
using TMPro;
+using UnityEngine.Serialization;
using UnityEngine.UI;
using static CECUIManager;
@@ -27,16 +28,19 @@ namespace BrewMonster
{
[SerializeField] private TMP_Text titleText;
[SerializeField] private TMP_Text messageText;
- [SerializeField] private Button okButton;
+ [SerializeField] private Button _yesButton;
[SerializeField] private Button _noButton;
[SerializeField] private Button _closeButton;
+ private Action _onClickedYesBtn;
+ private Action _onClickedNoBtn;
+
private MessageBoxData _messageData;
public override void OnEnable()
{
base.OnEnable();
- okButton.onClick.AddListener(OnOkClicked);
+ _yesButton.onClick.AddListener(OnYesClicked);
_noButton.onClick.AddListener(OnNoClicked);
_closeButton.onClick.AddListener(OnCloseClicked);
@@ -44,59 +48,135 @@ namespace BrewMonster
public override void OnDisable()
{
- okButton.onClick.RemoveListener(OnOkClicked);
+ _yesButton.onClick.RemoveListener(OnYesClicked);
_noButton.onClick.RemoveListener(OnNoClicked);
_closeButton.onClick.RemoveListener(OnCloseClicked);
}
#region Button Events
- private void OnOkClicked()
+ private void OnYesClicked()
{
EventBus.Publish(new MessageBoxEvent(1,_messageData.Dlg));
- _messageData.OnClickedYes?.Invoke();
+ _onClickedYesBtn?.Invoke();
Show(false);
}
private void OnNoClicked()
{
EventBus.Publish(new MessageBoxEvent(0,_messageData.Dlg));
_messageData.OnClickedNo?.Invoke();
+ _onClickedNoBtn?.Invoke();
Show(false);
}
private void OnCloseClicked()
{
// treat the close button as OK button
- OnOkClicked();
+ OnYesClicked();
}
#endregion
- public void ShowMessageBox(MessageBoxData messageBoxData)
+ // public void ShowMessageBox(MessageBoxData messageBoxData)
+ // {
+ // _messageData = messageBoxData;
+ // messageBoxData.Message = EC_TextFormatter.FormatForTextMeshPro(messageBoxData.Message);
+ // SetName(string.IsNullOrEmpty(messageBoxData.Title) ? "" : messageBoxData.Title);
+ // messageText.text = string.IsNullOrEmpty(messageBoxData.Message) ? "" : messageBoxData.Message;
+ //
+ // _yesButton.gameObject.SetActive(false);
+ // _noButton.gameObject.SetActive(false);
+ // switch (_messageData.MessageBoxType)
+ // {
+ // case MessageBoxType.YesButton:
+ // _yesButton.gameObject.SetActive(true);
+ // break;
+ // case MessageBoxType.NoButton:
+ // _noButton.gameObject.SetActive(true);
+ // break;
+ // case MessageBoxType.BothYesNoButton:
+ // _yesButton.gameObject.SetActive(true);
+ // _noButton.gameObject.SetActive(true);
+ // break;
+ // }
+ // Show(true);
+ // }
+
+ ///
+ /// message with title and message only
+ ///
+ ///
+ ///
+ ///
+ public void ShowMessageBoxGeneral(string title, string message, AUIDialog dlg)
{
- _messageData = messageBoxData;
- // messageBoxData.Message = messageBoxData.Message?
- // .Replace("\r\n", "\n")
- // .Replace("\r", "\n");
- messageBoxData.Message = EC_TextFormatter.FormatForTextMeshPro(messageBoxData.Message);
- SetName(string.IsNullOrEmpty(messageBoxData.Title) ? "" : messageBoxData.Title);
- messageText.text = string.IsNullOrEmpty(messageBoxData.Message) ? "" : messageBoxData.Message;
-
- okButton.gameObject.SetActive(false);
+ _onClickedYesBtn = null;
+ _onClickedYesBtn = null;
+ string formattedMessage = EC_TextFormatter.FormatForTextMeshPro(message);
+ SetName(string.IsNullOrEmpty(title) ? "" : title);
+ messageText.text = string.IsNullOrEmpty(formattedMessage) ? "" : formattedMessage;
_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;
- }
+ _yesButton.gameObject.SetActive(true);
Show(true);
+ transform.SetAsLastSibling();
+ }
+
+ ///
+ /// message with yes button only
+ ///
+ ///
+ ///
+ ///
+ ///
+ public void ShowMessageBoxYes(string title, string message, AUIDialog dlg, Action onClickedYes)
+ {
+ _onClickedYesBtn = onClickedYes;
+ string formattedMessage = EC_TextFormatter.FormatForTextMeshPro(message);
+ SetName(string.IsNullOrEmpty(title) ? "" : title);
+ messageText.text = string.IsNullOrEmpty(formattedMessage) ? "" : formattedMessage;
+ _noButton.gameObject.SetActive(false);
+ _yesButton.gameObject.SetActive(true);
+ Show(true);
+ transform.SetAsLastSibling();
+ }
+
+ ///
+ /// message with no button only
+ ///
+ ///
+ ///
+ ///
+ ///
+ public void ShowMessageBoxNo(string title, string message, AUIDialog dlg, Action onClickedNo)
+ {
+ _onClickedNoBtn = onClickedNo;
+ string formattedMessage = EC_TextFormatter.FormatForTextMeshPro(message);
+ SetName(string.IsNullOrEmpty(title) ? "" : title);
+ messageText.text = string.IsNullOrEmpty(formattedMessage) ? "" : formattedMessage;
+ _yesButton.gameObject.SetActive(false);
+ _noButton.gameObject.SetActive(true);
+ Show(true);
+ transform.SetAsLastSibling();
+ }
+
+ ///
+ /// message with yes and no button
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public void ShowMessageBoxYesAndNo(string title, string message, AUIDialog dlg, Action onClickedYes, Action onClickedNo)
+ {
+ _onClickedYesBtn = onClickedYes;
+ _onClickedNoBtn = onClickedNo;
+ string formattedMessage = EC_TextFormatter.FormatForTextMeshPro(message);
+ SetName(string.IsNullOrEmpty(title) ? "" : title);
+ messageText.text = string.IsNullOrEmpty(formattedMessage) ? "" : formattedMessage;
+ _yesButton.gameObject.SetActive(true);
+ _noButton.gameObject.SetActive(true);
+ Show(true);
+ transform.SetAsLastSibling();
}
}
}
diff --git a/Assets/PerfectWorld/Scripts/UI/Dialogs/DlgInstall.cs b/Assets/PerfectWorld/Scripts/UI/Dialogs/DlgInstall.cs
index 64879f884f..32890746ec 100644
--- a/Assets/PerfectWorld/Scripts/UI/Dialogs/DlgInstall.cs
+++ b/Assets/PerfectWorld/Scripts/UI/Dialogs/DlgInstall.cs
@@ -1,4 +1,4 @@
-using BrewMonster.Network;
+using BrewMonster.Network;
using BrewMonster.Scripts.Managers;
using BrewMonster.UI;
using PerfectWorld.Scripts.Managers;
@@ -37,12 +37,13 @@ namespace BrewMonster
[Header("Buttons and Money")]
[SerializeField]
private TextMeshProUGUI m_TxtMoney;
+ [SerializeField] private Button m_useItem;
[SerializeField] private Button m_BtnMergeOrReset;
[SerializeField] private Button m_BtnCancel;
[SerializeField] private Button m_BtnClose;
[SerializeField] private Sprite khung_item;
- [SerializeField] private Transform itemInventoryRoot;
+ [SerializeField] private GameObject itemInventoryRoot;
private EC_IvtrItem m_SelectedEquip;
private EC_IvtrItem m_SelectedMaterial;
@@ -58,31 +59,14 @@ namespace BrewMonster
public override void Awake()
{
base.Awake();
- RegisterDrop(m_SlotFirstParent, OnDropEquip);
RegisterClick(m_SlotFirstParent, OnClickEquipSlot);
if (m_Mode == InstallMode.Enchase && m_SlotSecondParent != null)
{
- RegisterDrop(m_SlotSecondParent, OnDropMaterial);
RegisterClick(m_SlotSecondParent, 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();
@@ -91,6 +75,7 @@ namespace BrewMonster
m_BtnMergeOrReset.onClick.AddListener(OnClickedMergeOrReset);
m_BtnCancel.onClick.AddListener(OnCommandCancel);
m_BtnClose.onClick.AddListener(OnCommandCancel);
+ m_useItem.onClick.AddListener(OnUseItemClicked);
m_install_price = -1;
if (m_SlotSecondParent != null)
m_SlotSecondParent.gameObject.SetActive(m_Mode == InstallMode.Enchase);
@@ -104,6 +89,7 @@ namespace BrewMonster
m_BtnMergeOrReset.onClick.RemoveListener(OnClickedMergeOrReset);
m_BtnCancel.onClick.RemoveListener(OnCommandCancel);
m_BtnClose.onClick.RemoveListener(OnCommandCancel);
+ m_useItem.onClick.RemoveListener(OnUseItemClicked);
}
private void RestoreInventoryColors()
@@ -147,23 +133,6 @@ namespace BrewMonster
return list[slot];
}
- private void RegisterDrop(Transform target, Action callback)
- {
- var trigger = target.GetComponent();
- if (trigger == null)
- trigger = target.gameObject.AddComponent();
-
- trigger.triggers.Clear();
-
- var entry = new EventTrigger.Entry
- {
- eventID = EventTriggerType.Drop
- };
- entry.callback.AddListener((data) => { callback((PointerEventData)data); });
-
- trigger.triggers.Add(entry);
- }
-
private void RegisterClick(Transform target, Action callback)
{
if (target == null) return;
@@ -199,117 +168,6 @@ namespace BrewMonster
}
}
- private EC_IvtrItem GetItemFromDrag(PointerEventData eventData)
- {
- if (eventData.pointerDrag == null)
- return null;
-
- var btn = eventData.pointerDrag.GetComponent