和人说话:那些菜单到底是什么

菜单是一张表,不是一种状态

交互菜单是从每个角色自己的一张行表里搭出来的,按固定顺序过两道条件 (RoleInteract.GetNpcInteracts):

所以「他给我写了信,可这里什么都没有」永远是三种情况之一:这个角色身上没有这类行、隐藏条件 此刻为真,或者显示条件不成立。游戏从不说是哪一种。第三种里有一部分,行上带了一段锁的说明。

为什么这个人有劫杀,那个人只有切磋

不是随机的,但也不是你从人身上看得出来的:这份菜单是写出来的,不是推出来的。

真正按规则走的只有四条,全在 NpcInteract.GetNpcInteractsByNpcID 的那一长串判断里:

选项 什么时候有
劫杀 只对随机生成的角色;随机角色里 NT_RANDOM_NOJUEDOU(不接受决斗的那一类)连劫杀也没有
比斗 代码里同样只放行随机角色,但任何表里、任何人身上都没有这一类型的行——这道门后面什么都没有
挑战侠云录 只在对方在榜上、且排在你前面时
抓捕 只在对方是悬赏目标时
结缘、结义、对饮 小孩身上不给

其余的都是一条一条写死的:

切磋和挑战不是同一种打法

两者最后都对对方调 SetCanBeWin(),所以谁都杀不死对方。区别在你自己身上,而且就一行:

public void EnterCompareState(...)  { m_PlayerEntity.SetCanBeWin(); StartCoroutine(RobCompareRoutine(...)); }
public void EnterTiaoZhanState(...) {                               StartCoroutine(TiaoZhanRoutine(...)); }

切磋给你上了保护,挑战没有——输了就是死。

奖励两者是一样的,这点很容易看错,因为 OnQieCuoFinished 有两个调用处,只有一处提到挑战:

// NpcController.LeaveCompare —— 没打到倒下就结束的那种
if (pkResult && !IsSpecialQieCuoEventNpc(guid) && !m_TiaoZhanByPlayer)  OnQieCuoFinished(...);

// NpcController.Dead —— 对方真的倒下了
if (m_Entity.m_CompareWithPlayer && !IsSpecialQieCuoEventNpc(guid))     OnQieCuoFinished(...);

挑战同时置上了 m_CompareWithPlayer 和 m_TiaoZhanByPlayer,所以第二处对它照样触发,该给的一分 不少:对败者好感+8、道德+5、悬赏结算,以及按对方境界档次发的门派代币。第一处那个 !m_TiaoZhanByPlayer 是防止发两遍,不是不发。

掉落那条差别也是假的。SetCanBeWin 落到 EnterHostileRed(canDead: false),所以挑战里的对手和切磋 里的一样,m_CanDead = false,根本死不了。掉落那段写的是 !m_CompareWithPlayer || (m_TiaoZhanByPlayer && !pkResult),后半句要求对方真的死掉,而这个标记 正好不许他死——在挑战里这条分支永远走不到。

切磋 挑战
对方会死 不会 不会
你会死 不会 会
尸体掉落 没有 没有——那条分支到不了
好感+8、道德+5、悬赏结算、门派代币 有 有
打完之后你的气血内力 输了回满,赢了原样 同左

最后一行是游戏自己的:PlayerController.OnDead 在你被人打倒时把你回满,赢了回满的是对手。修改器的 「切磋赢了也回满血」开关(默认开启)让赢了也一样回满。

打起来只有一行不一样,但打之前两者几乎没有关系,而挑战的价值就在这里:

Handle_IT_TATAKAIYI(切磋) Handle_IT_TiaoZhan(挑战)
消耗对方15精力 要,不够就不给打 不看
会被拒绝 会——按战力差掷骰,对方胆识越高越容易答应 从不
开打之前 一段等待思考的随机对话、一个 NpcChatView、两个 NpcAutoChatViewXSY(5001006、5001009)、答应或拒绝的台词,然后烧香行礼和3-2-1 什么都没有——收齐对手直接进 EnterTiaoZhanState
对手几个 一个 一个。处理函数确实会把这一行 paramString 里的id都收进来,但355行写的全是这个人自己的id,列表里同一个人出现两次,打起来还是一对一

所以挑战是「快、不会被拒」的那一种,选它是有理由的:拿一条命的风险,换掉一段还可能以拒绝收场的 过场。修改器的 FastQieCuo 会把切磋那段过场删掉,差距就只剩拒绝掷骰了——而那个骰子只对随机生成 的角色掷,具名角色一律答应。

这件事之所以还能忍,是因为你几乎没得选:两者是发给两批互不重合的人的,实际上是面前这个人决定 你能打哪一种——而只给挑战的那些人,用同样的报酬让你多担一条命,菜单上一个字都不提。 - 角色可以把默认行关掉,而实际上关的是御者。 group == -1 的那一行不是菜单里的一项,而是 一条关于菜单的指令:paramString 写 0 就把全部默认行抹掉,写用 | 隔开的若干个行id,就 把这几行挑掉。全游戏58个角色带这一行:46个是御者和船夫,被告知不要提供厨事/对饮/对弈/巧取; 7个写的行id是构建函数根本不查的;1个去掉拜师和结缘;1个去掉大部分默认行,而那个人的打斗项本来 就已被排除;2个算命先生把全部关掉。没有一个是把切磋、挑战或劫杀从本该有的人身上拿走的。

所以两个看起来一样的人菜单不一样,就是有人替他们一个一个写过。F键能打开的11,596个具名角色里, 带三种打斗项任意一种的是599个,其余都没有。挑战是355行一人一行,切磋只通过那142行到达具名角色, 劫杀通过210行。切磋和挑战同时都有的9个人,是9个一模一样的太初弟子。修改器的「对任何人都可切磋」 和「对任何人都可挑战」两个开关(默认关闭)给每个没有的人补上一行;它对经济意味着什么,写在 修改器指南里。

两个第二层

你最先看到的那三四个按钮(交谈、交互、交易、行为)是一排按钮。点其中一个,打开的是不同类型 的东西:

这两种都由同一个调用RoleInteract.ActivateInteracts(true)收回去,界面自己的背景板第一次被 按下时接的就是它。只还原其中一边的做法,在你走另一条路之前看起来都是好的。

点交谈会把菜单关掉

InteractWithNpc只对一小串类型保住交互状态(赠送、传送、情分索要、厨事、巧取、谈论、地会), 其余一律调DisableInteract,交谈也在其中。所以聊完之后后面没有菜单可以退回去。你选下去的那 一刻,游戏就把它撤了。

送礼的选择界面是另一个视图,它的退出键是离开

选择界面是InteractOther,它的容我再想想调的是RoleInteract.DisableInteract,直接退出整段 对话。你悬停时描述那件道具的那一栏又是第三个视图,挂在选择界面的一个字段上——所以只把选择 界面藏掉,会留一整页道具文字盖在场景上。

交互菜单画在哪里

这个菜单画在世界HUD的窗体里面,不自己开一个面板,所以任何按「最上层窗体」来判断的东西,都会在 你正站着对话的时候得出「没有面板打开」的结论。