Merge pull request 'feature/character_info' (#167) from feature/character_info into develop
Reviewed-on: https://git.pthub.vn/Unity/perfect-world-unity/pulls/167
This commit is contained in:
@@ -1208,7 +1208,7 @@ MonoBehaviour:
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_text: Invite
|
||||
m_text: "Th\xE1ch \u0111\u1EA5u\n"
|
||||
m_isRightToLeft: 0
|
||||
m_fontAsset: {fileID: 11400000, guid: 369c2e14814cc9a4b8e3ad4e37769134, type: 2}
|
||||
m_sharedMaterial: {fileID: 9092487103257209053, guid: 369c2e14814cc9a4b8e3ad4e37769134, type: 2}
|
||||
|
||||
@@ -262,10 +262,14 @@ namespace BrewMonster
|
||||
// 为了保证追踪到目标后能正常攻击,这里在必要时主动选中目标。
|
||||
// Server select-target ack can arrive later than the trace touch moment, which would
|
||||
// make this block forever. Ensure we select the traced target before attacking.
|
||||
// In duel: don't overwrite selection if player explicitly chose another target.
|
||||
bool duelPlayerChoseOther = m_pHost.IsInDuel() && m_pHost.GetDuelOpponentId() == m_iObjectId
|
||||
&& m_pHost.m_idSelTarget != 0 && m_pHost.m_idSelTarget != m_iObjectId;
|
||||
if (m_iObjectId != m_pHost.m_idSelTarget)
|
||||
{
|
||||
UnityGameSession.c2s_CmdSelectTarget(m_iObjectId);
|
||||
m_pHost.m_idSelTarget = m_iObjectId;
|
||||
if (!duelPlayerChoseOther)
|
||||
m_pHost.m_idSelTarget = m_iObjectId;
|
||||
}
|
||||
if (m_pHost.AttackableJudge(m_iObjectId, m_bForceAttack) == 1)
|
||||
{
|
||||
@@ -381,10 +385,14 @@ namespace BrewMonster
|
||||
{
|
||||
// 同 NPC:追踪触碰可能早于服务器选中目标同步,需主动选中以避免攻击不触发。
|
||||
// Same as NPC: trace touch can happen before server selection ack; proactively select.
|
||||
// In duel: don't overwrite selection if player explicitly chose another target.
|
||||
bool duelPlayerChoseOther = m_pHost.IsInDuel() && m_pHost.GetDuelOpponentId() == m_iObjectId
|
||||
&& m_pHost.m_idSelTarget != 0 && m_pHost.m_idSelTarget != m_iObjectId;
|
||||
if (m_iObjectId != m_pHost.m_idSelTarget)
|
||||
{
|
||||
UnityGameSession.c2s_CmdSelectTarget(m_iObjectId);
|
||||
m_pHost.m_idSelTarget = m_iObjectId;
|
||||
if (!duelPlayerChoseOther)
|
||||
m_pHost.m_idSelTarget = m_iObjectId;
|
||||
}
|
||||
// Duel: always send PVP/force mask when target is duel opponent so server accepts the attack
|
||||
bool bUseForceAttack = m_bForceAttack || (m_pHost.IsInDuel() && m_iObjectId == m_pHost.GetDuelOpponentId());
|
||||
|
||||
@@ -407,8 +407,10 @@ namespace BrewMonster
|
||||
// Trace a object / Trace a object
|
||||
if (iTraceReason == CECHPWorkTrace.Trace_reason.TRACE_ATTACK)
|
||||
{
|
||||
// So CanDo(CANDO_MELEE) passes: it requires m_idSelTarget set to the attack target
|
||||
m_idSelTarget = idTraceTarget;
|
||||
// So CanDo(CANDO_MELEE) passes and target HUD updates (e.g. duel opponent)
|
||||
SetSelectedTarget(idTraceTarget);
|
||||
// Sync selected target to server so attack is not rejected (wrong target / too far)
|
||||
UnityGameSession.c2s_CmdSelectTarget(idTraceTarget);
|
||||
if (!CanDo(ActionCanDo.CANDO_MELEE))
|
||||
return;
|
||||
// When attacking duel opponent, send force/PVP so server accepts (origin: duel = attack but not kill)
|
||||
@@ -448,6 +450,8 @@ namespace BrewMonster
|
||||
if (idSelTarget != 0 && m_idSelTarget != idSelTarget)
|
||||
{
|
||||
m_idUCSelTarget = idSelTarget;
|
||||
// Update local selection and HUD first so first click changes target (e.g. in duel); then sync to server
|
||||
SetSelectedTarget(m_idUCSelTarget);
|
||||
SelectTarget(m_idUCSelTarget);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,13 +38,12 @@ namespace PerfectWorld.Scripts.Managers
|
||||
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);
|
||||
var gameUI = EC_Game.GetGameRun()?.GetUIManager()?.GetInGameUIMan();
|
||||
if (gameUI != null)
|
||||
{
|
||||
var dlg = gameUI.GetDialog("DlgDuelInvite");
|
||||
var showMethod = dlg?.GetType().GetMethod("ShowForDuelInvite", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance, null, new[] { typeof(int) }, null);
|
||||
showMethod?.Invoke(dlg, new object[] { inviterId });
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -824,10 +824,14 @@ namespace CSNetwork.C2SCommand
|
||||
return SerializeCommand(CommandID.DUEL_REQUEST, new cmd_team_new_member { idMember = idTarget });
|
||||
}
|
||||
|
||||
/// <summary>C2S: accept (true) or reject (false) duel from inviter.</summary>
|
||||
/// <summary>C2S: accept (true) or reject (false) duel from inviter. Origin: [cmd][who:4][param:4] — who=inviter id, param=0 accept / non-zero reject.</summary>
|
||||
public static Octets CreateDuelReplyCommand(bool accept, int idInviter)
|
||||
{
|
||||
return SerializeCommand(CommandID.DUEL_REPLY, new cmd_duel_reply { accept = accept ? 1 : 0, idInviter = idInviter });
|
||||
var octets = new Octets();
|
||||
WriteBasicValue(octets, (ushort)CommandID.DUEL_REPLY);
|
||||
WriteBasicValue(octets, idInviter); // who
|
||||
WriteBasicValue(octets, accept ? 0 : 1); // param: 0 = accept, non-zero = reject reason
|
||||
return octets;
|
||||
}
|
||||
|
||||
public static Octets CreateTeamKickMemberCommand(int idMember)
|
||||
|
||||
@@ -2188,12 +2188,12 @@ namespace CSNetwork.GPDataType
|
||||
public int idMember;
|
||||
}
|
||||
|
||||
/// <summary>C2S duel reply: accept (1) / reject (0) and inviter character id.</summary>
|
||||
/// <summary>C2S duel reply (origin: who = inviter id, param = 0 accept / non-zero reject reason).</summary>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct cmd_duel_reply
|
||||
{
|
||||
public int accept; // 1 = accept, 0 = reject
|
||||
public int idInviter;
|
||||
public int who; // inviter character id (who sent the duel request)
|
||||
public int param; // 0 = accept (同意), non-zero = reject reason (拒绝原因)
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
|
||||
@@ -1106,6 +1106,9 @@ namespace BrewMonster
|
||||
{
|
||||
var data = (byte[])Msg.dwParam1;
|
||||
cmd_select_target pCmd = GPDataTypeHelper.FromBytes<cmd_select_target>(data);
|
||||
// In duel: don't let server force selection back to duel opponent when player chose another target
|
||||
if (IsInDuel() && pCmd.idTarget == m_pvp.idDuelOpp && m_idSelTarget != 0 && m_idSelTarget != m_pvp.idDuelOpp)
|
||||
return;
|
||||
m_idSelTarget = pCmd.idTarget;
|
||||
m_idUCSelTarget = 0;
|
||||
}
|
||||
@@ -1895,7 +1898,6 @@ namespace BrewMonster
|
||||
|
||||
public bool SelectTarget(int idTarget)
|
||||
{
|
||||
//BMLogger.LogError("HoangDev: HostPlayer SelectTarget");
|
||||
bool bRet = false;
|
||||
bool canDo = CanDo(ActionCanDo.CANDO_CHANGESELECT);
|
||||
bool canselect = CanSelectTarget(idTarget);
|
||||
@@ -2374,7 +2376,23 @@ namespace BrewMonster
|
||||
}
|
||||
public void SetSelectedTarget(int id)
|
||||
{
|
||||
if (m_idSelTarget != id)
|
||||
EventBus.Publish(new CECHostPlayer.TargetHUDClearEvent());
|
||||
m_idSelTarget = id;
|
||||
// In duel, when player selects a different target, cancel trace work so it doesn't overwrite selection on touch
|
||||
if (IsInDuel() && id != 0 && id != m_pvp.idDuelOpp)
|
||||
m_pWorkMan?.FinishRunningWork(CECHPWork.Host_work_ID.WORK_TRACEOBJECT);
|
||||
// When selecting another player, publish NPCINFO so target HUD shows (server doesn't resend base info on select)
|
||||
if (id != 0 && id != GetCharacterID() && GPDataTypeHelper.ISPLAYERID(id))
|
||||
{
|
||||
var elsePlayer = EC_ManMessageMono.Instance?.GetECManPlayer?.GetPlayer(id) as EC_ElsePlayer;
|
||||
if (elsePlayer != null && elsePlayer.m_bBaseInfoReady)
|
||||
{
|
||||
string name = elsePlayer.GetName();
|
||||
if (!string.IsNullOrEmpty(name))
|
||||
EventBus.Publish(new CECHostPlayer.NPCINFO(name, 100, 100, id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public new int GetSelectedTarget()
|
||||
|
||||
@@ -112,6 +112,9 @@ public class CECUIManager : MonoSingleton<CECUIManager>
|
||||
|
||||
private void ShowUINPC(CECHostPlayer.NPCINFO obj)
|
||||
{
|
||||
var host = EC_Game.GetGameRun()?.GetHostPlayer();
|
||||
if (host != null && host.GetSelectedTarget() != obj.IDNPC)
|
||||
return;
|
||||
npsUI.gameObject.SetActive(true);
|
||||
string hpText = obj.MaxHealth > 0 ? $"{obj.CurrentHealth}/{obj.MaxHealth}" : "-/-";
|
||||
npsUI.SetText(hpText, obj.Name ?? "", "");
|
||||
|
||||
Reference in New Issue
Block a user