交互菜单是从每个角色自己的一张行表里搭出来的,按固定顺序过两道条件
(RoleInteract.GetNpcInteracts):
condition2命中时把这一行藏起来。condition必须命中,这一行才会出现。所以「他给我写了信,可这里什么都没有」永远是三种情况之一:这个角色身上没有这类行、隐藏条件 此刻为真,或者显示条件不成立。游戏从不说是哪一种。第三种里有一部分,行上带了一段锁的说明。
不是随机的,但也不是你从人身上看得出来的:这份菜单是写出来的,不是推出来的。
真正按规则走的只有四条,全在 NpcInteract.GetNpcInteractsByNpcID 的那一长串判断里:
| 选项 | 什么时候有 |
|---|---|
| 劫杀 | 只对随机生成的角色;随机角色里 NT_RANDOM_NOJUEDOU(不接受决斗的那一类)连劫杀也没有 |
| 比斗 | 代码里同样只放行随机角色,但任何表里、任何人身上都没有这一类型的行——这道门后面什么都没有 |
| 挑战侠云录 | 只在对方在榜上、且排在你前面时 |
| 抓捕 | 只在对方是悬赏目标时 |
| 结缘、结义、对饮 | 小孩身上不给 |
其余的都是一条一条写死的:
param0 == 1,这个标记只放行随机生成的角色。有名有姓的人要有切磋,得他自己
身上另写一行——全游戏有142个人是这么写的。而且这条规则在处理函数里还会再查一遍:
Handle_IT_TATAKAIYI 先数这个人自己的切磋行,具名角色一行都没有时,只给一句套话(5000117)
就返回,不开打、不掷骰。Handle_IT_ROB 对劫杀同样——而且是在先发了+30胆识之后才拒绝。所以
单纯把默认行放出来,得到的是一个会拒绝你的按钮;修改器的「对任何人都可切磋」是另外注入一行,
走的是委托要求切磋某人时游戏自己的那条路(CheckNpsIsNeedQieCuo)。这一行也会落到自己的队友
身上,而原版切磋在队友身上跑不起来:两个单位能不能互相出手由 UnitController.IsHostile 决定,
同队的两个人它只看队伍表,不看切磋涂上的敌对色——于是队友拔着兵器站着,谁也打不着谁,F菜单又跳过
正在切磋的人,只剩走开12米这一条出路。修改器让切磋期间你们两个互为敌对,并挡住
NpcController.OnDead 把这次击倒记成队友阵亡(它本来会在走到切磋的胜负分支之前就这么做)。
劫杀另有210个具名角色自带一行。npc_interact 里355行 IT_TiaoZhan,一人一行,其中只有4行带条件——谁肯接你的挑战,是
当初一个个定下来的。但那只手是有偏好的,而且跟直觉相反:这355人里带门派/流派的占64%(全体有名
角色是17%),带称号的占38%(全体7%),在侠云录上的只有5个,而带门派职位记录(menpaiinfo)
的是0个。全游戏有44个人有门派职位——MenPaiMenType 里的外门、内门、关门、亲传、掌门——这44人
和355人一个都不重合。也就是说:挑战是给没有门派职务的知名散人准备的(荒冢剑魔、青莲狂客、
白玉京魁首这一类),凡是在门派里有位置的,都走门派自己那套系统。两者最后都对对方调 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的窗体里面,不自己开一个面板,所以任何按「最上层窗体」来判断的东西,都会在 你正站着对话的时候得出「没有面板打开」的结论。