diff --git a/Assets/PerfectWorld/Prefab/UI/Teamate.prefab b/Assets/PerfectWorld/Prefab/UI/Teamate.prefab index bca1e95cfb..be386da4b5 100644 --- a/Assets/PerfectWorld/Prefab/UI/Teamate.prefab +++ b/Assets/PerfectWorld/Prefab/UI/Teamate.prefab @@ -1427,6 +1427,7 @@ RectTransform: - {fileID: 6747937870382540800} - {fileID: 9145156114905100934} - {fileID: 1392280977313824629} + - {fileID: 7829150308709081067} m_Father: {fileID: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} @@ -1484,6 +1485,8 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 52c15f7b28624ef4697b1f7eb3a0d17c, type: 3} m_Name: m_EditorClassIdentifier: + skillNameText: {fileID: 0} + imageProgress: {fileID: 0} Content_Teammates: {fileID: 2702288869473602435} TeammateItemPrefab: {fileID: 5014101816795320943, guid: ef1af109634dbf44da065d64dc30fa38, type: 3} Content_Nearby: {fileID: 4562375036863719405} @@ -6166,6 +6169,138 @@ MonoBehaviour: m_ChildScaleWidth: 0 m_ChildScaleHeight: 0 m_ReverseArrangement: 0 +--- !u!1 &7140757019260147103 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 7829150308709081067} + - component: {fileID: 615136352827836387} + - component: {fileID: 3391660217384508209} + - component: {fileID: 4321133568498195476} + m_Layer: 5 + m_Name: close_btn + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &7829150308709081067 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7140757019260147103} + 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: 7364890917756710219} + 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: 426.97388, y: 272.67} + m_SizeDelta: {x: 30.682, y: 31.93} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &615136352827836387 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7140757019260147103} + m_CullTransparentMesh: 1 +--- !u!114 &3391660217384508209 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7140757019260147103} + 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: 21300000, guid: fb2f2f58be45f6e4890e85cc00b0bcc9, type: 3} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!114 &4321133568498195476 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7140757019260147103} + 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: 3391660217384508209} + m_OnClick: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 2452003196178065293} + m_TargetAssemblyTypeName: UnityEngine.GameObject, UnityEngine + m_MethodName: SetActive + m_Mode: 6 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 --- !u!1 &7172228088205297695 GameObject: m_ObjectHideFlags: 0 @@ -8448,7 +8583,7 @@ PrefabInstance: objectReference: {fileID: 0} - target: {fileID: 2128182273890188768, guid: df9492e8a45f4b047bf5ffedaf2921ab, type: 3} propertyPath: m_AnchorMax.y - value: 0 + value: 1 objectReference: {fileID: 0} - target: {fileID: 2128182273890188768, guid: df9492e8a45f4b047bf5ffedaf2921ab, type: 3} propertyPath: m_AnchorMin.x @@ -8456,15 +8591,15 @@ PrefabInstance: objectReference: {fileID: 0} - target: {fileID: 2128182273890188768, guid: df9492e8a45f4b047bf5ffedaf2921ab, type: 3} propertyPath: m_AnchorMin.y - value: 0 + value: 1 objectReference: {fileID: 0} - target: {fileID: 2128182273890188768, guid: df9492e8a45f4b047bf5ffedaf2921ab, type: 3} propertyPath: m_SizeDelta.x - value: 0 + value: 300 objectReference: {fileID: 0} - target: {fileID: 2128182273890188768, guid: df9492e8a45f4b047bf5ffedaf2921ab, type: 3} propertyPath: m_SizeDelta.y - value: 0 + value: 60 objectReference: {fileID: 0} - target: {fileID: 2128182273890188768, guid: df9492e8a45f4b047bf5ffedaf2921ab, type: 3} propertyPath: m_LocalPosition.x @@ -8496,11 +8631,11 @@ PrefabInstance: objectReference: {fileID: 0} - target: {fileID: 2128182273890188768, guid: df9492e8a45f4b047bf5ffedaf2921ab, type: 3} propertyPath: m_AnchoredPosition.x - value: 0 + value: 154 objectReference: {fileID: 0} - target: {fileID: 2128182273890188768, guid: df9492e8a45f4b047bf5ffedaf2921ab, type: 3} propertyPath: m_AnchoredPosition.y - value: 0 + value: -35 objectReference: {fileID: 0} - target: {fileID: 2128182273890188768, guid: df9492e8a45f4b047bf5ffedaf2921ab, type: 3} propertyPath: m_LocalEulerAnglesHint.x @@ -8522,6 +8657,10 @@ PrefabInstance: propertyPath: m_Name value: team_item objectReference: {fileID: 0} + - target: {fileID: 8777891425110263910, guid: df9492e8a45f4b047bf5ffedaf2921ab, type: 3} + propertyPath: m_IsActive + value: 0 + objectReference: {fileID: 0} m_RemovedComponents: [] m_RemovedGameObjects: [] m_AddedGameObjects: [] diff --git a/Assets/PerfectWorld/Scene/Bootstrap.unity b/Assets/PerfectWorld/Scene/Bootstrap.unity index 6ef985d281..35a895d61b 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:84e412b6f5e36bb93f0b17ced95c929c8773b7ed9d513f792a0f4664d78b7014 -size 282581 +oid sha256:57bb52418b44eb7e3e333915973057be091b0826983b641ceb05263b4dffe2e4 +size 287382 diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_ManPlayer.cs b/Assets/PerfectWorld/Scripts/Managers/EC_ManPlayer.cs index f387e0a2ca..707a76639d 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_ManPlayer.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_ManPlayer.cs @@ -33,18 +33,6 @@ namespace PerfectWorld.Scripts.Managers { if (CECGameRun.Instance == null) return true; if (CECGameRun.Instance.GetHostPlayer() == null) return true; - // Duel invite: show accept/reject popup (origin uses MSG_PM_DUELOPT with command DUEL_RECV_REQUEST = 214) - // dwParam2 is ushort (pCmdHeader from GameSession); use Convert to avoid InvalidCastException when unboxing - if ((int)Msg.dwMsg == EC_MsgDef.MSG_PM_DUELOPT && Convert.ToInt32(Msg.dwParam2) == CommandID.DUEL_RECV_REQUEST && Msg.dwParam1 is byte[] pDataBuf && pDataBuf.Length >= 4) - { - int inviterId = BitConverter.ToInt32(pDataBuf, 0); - CECUIManager.Instance?.ShowMessageBox( - title: "", - message: "You have received a duel request. Do you accept?", - messageBoxType: MessageBoxType.BothYesNoButton, - onClickedYes: () => UnityGameSession.c2s_CmdDuelReply(true, inviterId), - onClickedNo: () => UnityGameSession.c2s_CmdDuelReply(false, inviterId)); - } CECGameRun.Instance.GetHostPlayer().ProcessMessage(Msg); } else if (Msg.iSubID < 0) diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/C2SCommand/C2SCommandFactory.cs b/Assets/PerfectWorld/Scripts/Network/CSNetwork/C2SCommand/C2SCommandFactory.cs index b4e93c6fac..6082666510 100644 --- a/Assets/PerfectWorld/Scripts/Network/CSNetwork/C2SCommand/C2SCommandFactory.cs +++ b/Assets/PerfectWorld/Scripts/Network/CSNetwork/C2SCommand/C2SCommandFactory.cs @@ -818,6 +818,18 @@ namespace CSNetwork.C2SCommand return SerializeCommand(CommandID.TEAM_INVITE, new cmd_team_new_member { idMember = idPlayer }); } + /// C2S: accept team invite from leader. idLeader = who sent the invite, team_seq = invite sequence from TEAM_LEADER_INVITE. + public static Octets CreateTeamAgreeInviteCommand(int idLeader, int team_seq) + { + return SerializeCommand(CommandID.TEAM_AGREE_INVITE, new cmd_team_agree_invite { idLeader = idLeader, team_seq = team_seq }); + } + + /// C2S: reject team invite from leader. + public static Octets CreateTeamRejectInviteCommand(int idLeader) + { + return SerializeCommand(CommandID.TEAM_REJECT_INVITE, new cmd_team_reject_invite { idLeader = idLeader }); + } + /// C2S: request duel with target player (same payload shape as team invite). public static Octets CreateDuelRequestCommand(int idTarget) { diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/GPDataType.cs b/Assets/PerfectWorld/Scripts/Network/CSNetwork/GPDataType.cs index 2fcbaa4fc5..67ca8d2495 100644 --- a/Assets/PerfectWorld/Scripts/Network/CSNetwork/GPDataType.cs +++ b/Assets/PerfectWorld/Scripts/Network/CSNetwork/GPDataType.cs @@ -2208,6 +2208,21 @@ namespace CSNetwork.GPDataType public int idMember; } + /// C2S: accept team invite. idLeader = who sent the invite, team_seq = invite sequence. + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct cmd_team_agree_invite + { + public int idLeader; + public int team_seq; + } + + /// C2S: reject team invite. idLeader = who sent the invite. + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct cmd_team_reject_invite + { + public int idLeader; + } + /// C2S duel reply (origin: who = inviter id, param = 0 accept / non-zero reject reason). [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct cmd_duel_reply diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/GameSession.cs b/Assets/PerfectWorld/Scripts/Network/CSNetwork/GameSession.cs index 2cd0e8486d..073a93dabf 100644 --- a/Assets/PerfectWorld/Scripts/Network/CSNetwork/GameSession.cs +++ b/Assets/PerfectWorld/Scripts/Network/CSNetwork/GameSession.cs @@ -840,6 +840,9 @@ namespace CSNetwork case CommandID.TEAM_MEMBER_DATA: EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_TEAMMEMBERDATA, (int)MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); break; + case CommandID.TEAM_LEADER_INVITE: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_TEAMINVITE, (int)MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); + break; case CommandID.TEAM_MEMBER_LEAVE: EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_LEAVETEAM, (int)MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader); break; @@ -1863,6 +1866,20 @@ namespace CSNetwork SendProtocol(g); } + public void c2s_SendCmdTeamAgreeInvite(int idLeader, int team_seq) + { + var g = new gamedatasend(); + g.Data = C2SCommandFactory.CreateTeamAgreeInviteCommand(idLeader, team_seq); + SendProtocol(g); + } + + public void c2s_SendCmdTeamRejectInvite(int idLeader) + { + var g = new gamedatasend(); + g.Data = C2SCommandFactory.CreateTeamRejectInviteCommand(idLeader); + SendProtocol(g); + } + public void c2s_SendCmdDuelRequest(int idTarget) { var g = new gamedatasend(); diff --git a/Assets/PerfectWorld/Scripts/Network/UnityGameSession.cs b/Assets/PerfectWorld/Scripts/Network/UnityGameSession.cs index 2ea519aff2..6d4da53a7c 100644 --- a/Assets/PerfectWorld/Scripts/Network/UnityGameSession.cs +++ b/Assets/PerfectWorld/Scripts/Network/UnityGameSession.cs @@ -599,6 +599,14 @@ namespace BrewMonster.Network { Instance._gameSession.c2s_SendCmdTeamInvite(idPlayer); } + public static void c2s_CmdTeamAgreeInvite(int idLeader, int team_seq) + { + Instance._gameSession.c2s_SendCmdTeamAgreeInvite(idLeader, team_seq); + } + public static void c2s_CmdTeamRejectInvite(int idLeader) + { + Instance._gameSession.c2s_SendCmdTeamRejectInvite(idLeader); + } public static void c2s_CmdDuelRequest(int idTarget) { Instance._gameSession.c2s_SendCmdDuelRequest(idTarget); diff --git a/Assets/Scenes/a61.unity.meta b/Assets/Scenes/a61.unity.meta new file mode 100644 index 0000000000..9897459ab1 --- /dev/null +++ b/Assets/Scenes/a61.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 2099d0c0fdfc641509729652b0ed485f +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/CECHostPlayer.cs b/Assets/Scripts/CECHostPlayer.cs index 63405d1aee..cede52a8c3 100644 --- a/Assets/Scripts/CECHostPlayer.cs +++ b/Assets/Scripts/CECHostPlayer.cs @@ -608,6 +608,7 @@ namespace BrewMonster case EC_MsgDef.MSG_HST_JOINTEAM: OnMsgHstJoinTeam(Msg); break; case EC_MsgDef.MSG_HST_LEAVETEAM: OnMsgHstLeaveTeam(Msg); break; case EC_MsgDef.MSG_HST_NEWTEAMMEM: OnMsgHstNewTeamMem(Msg); break; + case EC_MsgDef.MSG_HST_TEAMINVITE: OnMsgHstTeamInvite(Msg); break; case EC_MsgDef.MSG_HST_TEAMMEMBERDATA: OnMsgHstTeamMemberData(Msg); break; case EC_MsgDef.MSG_PM_DUELOPT: OnMsgHstDuelOpt(Msg); break; case EC_MsgDef.MSG_HST_CLEARTESSERA: OnMsgHstClearTessera(Msg); break; @@ -653,6 +654,18 @@ namespace BrewMonster idOpp = BitConverter.ToInt32(data, 0); switch (cmdId) { + case CommandID.DUEL_RECV_REQUEST: + // Duel invite: show accept/reject popup (origin MSG_PM_DUELOPT with command DUEL_RECV_REQUEST = 214) + if (idOpp != 0) + { + CECUIManager.Instance?.ShowMessageBox( + title: "", + message: "You have received a duel request. Do you accept?", + messageBoxType: MessageBoxType.BothYesNoButton, + onClickedYes: () => UnityGameSession.c2s_CmdDuelReply(true, idOpp), + onClickedNo: () => UnityGameSession.c2s_CmdDuelReply(false, idOpp)); + } + break; case CommandID.DUEL_PREPARE: m_pvp.iDuelState = Duel_state.DUEL_ST_PREPARE; m_pvp.idDuelOpp = idOpp; @@ -683,6 +696,32 @@ namespace BrewMonster } } + /// Host received a team invite (MSG_HST_TEAMINVITE). Payload is cmd_team_leader_invite: idLeader, seq, pickFlag. Shows accept/reject message box and sends reply. + private void OnMsgHstTeamInvite(ECMSG Msg) + { + byte[] data = Msg.dwParam1 as byte[]; + int idLeader = 0; + int team_seq = 0; + if (data != null && data.Length >= 8) + { + idLeader = BitConverter.ToInt32(data, 0); + team_seq = BitConverter.ToInt32(data, 4); + } + else if (data != null && data.Length >= 4) + { + idLeader = BitConverter.ToInt32(data, 0); + } + if (idLeader == 0) + return; + int seqCapture = team_seq; + CECUIManager.Instance?.ShowMessageBox( + title: "", + message: "You have received a team invite. Do you accept?", + messageBoxType: MessageBoxType.BothYesNoButton, + onClickedYes: () => UnityGameSession.c2s_CmdTeamAgreeInvite(idLeader, seqCapture), + onClickedNo: () => UnityGameSession.c2s_CmdTeamRejectInvite(idLeader)); + } + /// Called when MSG_PM_PLAYERDUELOPT (229) is received; server may send duel start to both participants. If host is one of the two ids, set duel state. public void OnMsgPlayerDuelStart(byte[] data) {