设为首页
收藏本站
切换到宽版
官网
论坛
资格申请
更新日志
游戏体验
热搜
活动
交友
discuz
登录
|
VV Engine 官方中心
»
论坛
›
引擎交流
›
引擎教程
›
组队系统是 VV 引擎最小的社交模块,但细节里藏着不少门 ...
返回列表
发新帖
查看:
24
|
回复:
2
组队系统是 VV 引擎最小的社交模块,但细节里藏着不少门道
[复制链接]
13674307070
13674307070
当前离线
积分
1301
30
主题
72
回帖
1301
积分
金牌会员
金牌会员, 积分 1301, 距离下一级还需 1699 积分
金牌会员, 积分 1301, 距离下一级还需 1699 积分
积分
1301
发消息
发表于 2026-8-20 08:34:04
|
显示全部楼层
|
阅读模式
一、触发体系:生命周期拆得比行会还细
组队系统的触发有十个,比行会系统还多两个。看起来奇怪 —— 组队功能比行会简单,触发怎么反而更多?
仔细看就明白了:组队的生命周期节点拆得更细。
行会的触发是按操作分的 —— 创建、加入、退出、解散,每个操作前后各一个。组队的触发除了创建、加入、退出前后各一个之外,还多了 "邀请" 这个独立节点,以及 "添加成员"" 删除成员 "两个和加入退出不完全等同的节点,再加上一个组队专属的" 杀怪 " 触发。
逐个来看。
创建前
OnStartGroup,玩家发起创建队伍的时候触发。这个触发的示例代码很有意思 —— 里面演示了如何阻止创建:判断等级不够,提示玩家,然后调用 creategroupfail 打断。注释里还特别提到,23.08.30 之前的版本需要调用 TXT 命令 callscriptex(actor,"creategroupfail") 来打断,之后的版本可以直接调 Lua 函数。
这个细节说明两件事:第一,创建组队是可以被脚本拦截的,和行会的 Before 系列一样;第二,引擎在迭代过程中把原来需要走 TXT 命令的操作逐步改成了原生 Lua 接口,这是一个持续完善的过程。实际用的时候要注意版本差异,老版本可能还得走 TXT 命令。
邀请
这个触发的文档有个小问题 —— 标题写的触发名是 OnGroupCreate,但代码示例里的函数名是 OnInviteGroup。两个名字对不上。这种文档和实际不一致的情况在开发中很常见,实际用的时候要以引擎实际触发的函数名为准,最好写个测试函数打个日志确认一下,不要光看文档。
邀请触发带两个参数:邀请人和被邀请人。这是组队系统里少有的带两个玩家对象的触发,因为邀请本身就是两个人之间的交互。你可以在这里判断邀请人有没有权限、被邀请人是不是在黑名单里、两个人是不是在同一个地图,不满足就阻止邀请。
加入前和加入后
, OnBeforeJoinGroup 和 OnJoinGroup,都是只带一个玩家对象。这两个触发和行会的加入前后逻辑一样 ——Before 管拦截,After 管后续处理。比如加入后给个组队 buff、发个欢迎提示,都写在 After 里。
离开前和离开后
, OnBeforeLeaveGroup 和 OnLeaveGroup。这里有个设计细节:离开后的触发多了一个 groupowner 参数,告诉你队长是谁。其他触发大多只有玩家自己的对象,唯独离开后带了队长对象。
为什么?我的理解是:玩家离开队伍之后,他自己已经不在队伍里了,这时候如果想给队长发个通知(比如 "某某退出了队伍"),或者处理队长相关的逻辑(比如退队后扣除队长的什么状态),就需要知道队长是谁。如果不带这个参数,玩家退队后就拿不到队伍信息了,因为他已经不是队员,调 getgroupmember 也拿不到。
这个参数设计很贴心,考虑到了 "退队后还需要和原队伍交互" 的场景。
添加成员和删除成员
, OnAddGroupMember 和 OnDelGroupMember。这两个触发和加入退出看起来重复,其实不完全一样。加入退出是玩家主动行为的触发,添加删除可能是队长操作的结果 —— 比如队长邀请一个人,对方同意后,系统执行 "添加成员" 这个动作,这时候触发 OnAddGroupMember。队长踢人,系统执行 "删除成员",触发 OnDelGroupMember。
这两个触发的存在,意味着组队的人员变动不管是主动还是被动,都有对应的通知点。做组队相关的逻辑(比如组队 buff 的添加和移除),挂在这两个触发上比挂在加入退出上更准确 —— 因为不管什么原因导致的人员变化,都会走添加删除。
组队杀怪
OnGroupKillMon,这是组队系统最有价值的一个触发。当队伍中的成员杀死怪物时触发,带玩家对象和怪物名字。这个触发是做组队经验分配、组队掉落分配、组队任务进度的核心。
比如做 "组队击杀 100 只白野猪" 的任务,就挂在这个触发上,每次触发判断怪物名字是不是白野猪,然后给队伍里所有人加进度。做组队经验加成,也是在这里算经验然后分配给每个队员。
这个触发只带了杀怪的那个玩家和怪物名字,没有带整个队伍列表。如果要给所有队员发奖励,需要自己调 getgroupmember 拿队伍列表,然后遍历处理。这个设计是合理的 —— 触发只提供最核心的信息,队伍列表需要的时候自己去拿,避免每次触发都传一整个列表浪费性能。
二、接口设计:极简到只有四个
组队系统的接口只有四个,是所有模块里最少的。
创建队伍
creategroup,就一个玩家对象参数,调用就创建。没有人数上限参数,没有分配模式参数,没有队伍名称参数。创建出来的队伍就是引擎默认的配置。
添加队员
addgroupmember,传玩家对象和组员的 UserId。注意这里用的是 UserId,不是玩家对象。
删除队员
delgroupmember 同样用 UserId。
为什么添加删除用 UserId 而不是玩家对象?我的理解是:组队的成员管理本质上是按身份标识来操作的,UserId 是玩家的唯一身份标识,比玩家对象更稳定。玩家对象可能因为下线、重连而变化,但 UserId 是不变的。而且 UserId 可以持久化存储,做离线组队、队伍数据保存的时候更方便。
但这也带来一个问题:你要添加或删除队员,得先拿到对方的 UserId。如果只有玩家对象,需要先调 getbaseinfo 之类的接口去查 UserId,多一步操作。而且 UserId 是字符串类型,传的时候注意不要传成数字。
获取队员列表
getgroupmember,传玩家对象,返回队员列表的 table。这个接口是组队系统最常用的接口 —— 做组队 buff 要遍历队员,做组队经验分配要遍历队员,做组队传送要遍历队员,基本所有组队相关的批量操作都要先拿列表。
四个接口,覆盖了组队最核心的操作:建队、加人、踢人、查人。但也仅此而已。
组队系统里很多常见功能,接口里是没有的 —— 比如设置队伍人数上限、切换物品分配模式(自由拾取 / 轮流拾取 / 队长分配)、转让队长、开启 / 关闭自动接受邀请、设置队伍密码。这些功能要么走传统 TXT 脚本命令,要么引擎内置了但没暴露 Lua 接口,要么根本不支持。
这个 "接口极少" 的特点,其实反映了组队系统在整个引擎中的定位 —— 它是一个基础的、轻量的社交模块,引擎只提供最核心的组队机制,复杂的组队玩法(比如组队副本、组队竞技场、组队经验加成规则)全部交给脚本层去实现。
这种定位有好有坏。好处是组队系统足够简单,不会出什么复杂的 bug,引擎底层稳定。坏处是做复杂组队玩法的时候,很多东西要自己模拟 —— 比如想做 "队伍人数越多经验加成越高",引擎没有内置,你得自己在 OnGroupKillMon 里算人数、算加成、发经验。想做 "队长分配模式",引擎没有,你得自己拦截拾取事件,然后根据队伍设置决定物品给谁。
所以用组队系统的时候,心态要摆正:
引擎给你的是一个 "能组在一起" 的基础框架,所有玩法层面的东西都要自己做。
不要指望引擎内置了经验分配、掉落分配这些东西,大概率没有。
三、组队战斗:最有价值的联动点
组队系统和战斗系统的联动,主要就靠 OnGroupKillMon 这一个触发。但这一个触发,能撑起几乎所有组队战斗玩法。
最基础的用法是组队经验分配。玩家组队杀怪,经验怎么分?引擎没有内置分配规则,你得自己写。在 OnGroupKillMon 里,拿到杀怪玩家和怪物名字,然后调 getgroupmember 拿队伍列表,根据人数平均分配经验,或者按等级加权分配,或者队长拿大头队员拿小头,规则完全由你定。
组队掉落分配也是类似。怪物死了掉东西,谁来捡?如果要做 "队伍拾取" 模式,需要在怪物掉落的触发里判断击杀者有没有队伍,然后根据队伍的分配规则决定物品归属。这个逻辑引擎没有内置,要自己组合怪物掉落触发和组队接口来实现。
组队任务进度是另一个高频场景。"队伍中任意一人击杀怪物,所有队员任务进度 + 1",就在 OnGroupKillMon 里判断怪物名字,然后遍历队员列表,每个人都加进度。反过来 "必须队伍所有人都在附近才算组队击杀",也在这里做距离判断,不在附近的不加进度。
组队 buff 的管理也和这个触发有关。比如 "组队时每 10 秒回 1% 血量",不能在杀怪触发里做(不杀怪就不触发),得用定时器或者其他触发。但 "组队击杀怪物时给全队加一个临时攻击力 buff",就可以在 OnGroupKillMon 里做。
这里有个心得:
OnGroupKillMon 触发的是 "队伍成员杀死怪物",不是 "队伍中的怪物被杀死"
。也就是说,只有队伍里的人拿到了击杀归属,才会触发。如果怪物是被队伍外的人抢了最后一刀,这个触发不会触发。做组队任务的时候要注意这一点 —— 如果任务要求 "组队参与击杀" 而不是 "组队获得击杀",光靠这个触发可能不够,还需要结合怪物伤害记录来判断。
另外,这个触发带的是怪物名字,不是怪物对象。如果你需要怪物的更多信息(比如等级、血量、坐标),光靠名字拿不到。大部分场景下名字够用了 —— 判断是什么怪物、对应多少经验、掉什么东西,按名字查配置表就行。但如果要做 "根据怪物剩余血量决定经验加成" 这种逻辑,就需要在怪物死亡的其他触发里记录信息,然后在组队杀怪触发里关联使用。
四、几个实际使用中的心得和坑
把组队系统过完,结合实际开发场景,总结几个心得和容易踩的坑。
第一,触发名和文档可能对不上。
邀请组队那个触发,文档标题写的是 OnGroupCreate,代码示例写的是 OnInviteGroup,两个名字不一样。这种情况不要猜,写个空函数打日志测试一下,确认引擎实际调用的是哪个名字。猜错了的话,触发函数永远不会被调用,你还以为是逻辑有问题,查半天查不出来。
第二,创建组队的打断方式有版本差异。
OnStartGroup 里阻止创建,新版本直接调 creategroupfail,老版本要走 callscriptex(actor,"creategroupfail") 调用 TXT 命令。如果你的版本比较老,直接调 Lua 函数可能不生效。用之前先确认版本,或者两种方式都写上做兼容。
第三,添加删除队员用的是 UserId,不是玩家对象。
addgroupmember 和 delgroupmember 的第二个参数是字符串类型的 UserId。如果你传了玩家对象,或者传了数字类型的 ID,可能会操作失败。用之前先把 UserId 转成字符串,而且要确认你拿到的是 UserId 而不是其他什么 ID(比如角色 ID、账号 ID,这些可能不一样)。
第四,退队后拿不到队伍信息,所以 OnLeaveGroup 带了队长参数。
如果你需要在玩家退队后做和原队伍相关的处理(比如通知队长、扣除队伍状态),用触发参数里的 groupowner,不要试图自己去查 —— 玩家退队后已经不在队伍里了, getgroupmember 拿不到他的队伍。
第五,组队接口极少,很多功能要自己实现。
人数上限、分配模式、队长转让、组队经验、组队掉落,这些常见功能引擎都没有内置接口。做组队玩法之前,先列清楚你需要哪些功能,哪些引擎有、哪些要自己写,心里有底再动手。不要做到一半发现 "原来引擎没有这个功能",再想 workaround 就被动了。
第六,getgroupmember 返回的是 table,用之前先判空。
玩家没有队伍的时候,这个接口返回什么文档没说,可能是 nil 也可能是空 table。用之前先判断一下是不是有效的 table,再遍历。直接对 nil 做 ipairs 会报错。
第七,组队杀怪触发只带杀怪者和怪物名,要给全队发东西自己遍历。
OnGroupKillMon 不会自动给所有队员发经验或奖励,它只是告诉你 "队伍里有人杀了一只怪"。后续的分配、通知、奖励,全部要你自己拿队员列表然后循环处理。这个触发是起点,不是终点。
第八,人员变动的逻辑优先挂在添加删除触发上。
OnAddGroupMember 和 OnDelGroupMember 是所有人员变动的统一出口 —— 不管是主动加入、被邀请加入、被踢、主动退,最终都会走添加或删除。把组队 buff 的添加移除、队伍人数变化的处理挂在这两个触发上,比分别挂在加入退出上更全面,不会漏。
回复
举报
13674307070
13674307070
当前离线
积分
1301
30
主题
72
回帖
1301
积分
金牌会员
金牌会员, 积分 1301, 距离下一级还需 1699 积分
金牌会员, 积分 1301, 距离下一级还需 1699 积分
积分
1301
发消息
楼主
发表于 2026-8-20 08:34:49
|
显示全部楼层
挠头的500贡献
回复
举报
13674307070
13674307070
当前离线
积分
1301
30
主题
72
回帖
1301
积分
金牌会员
金牌会员, 积分 1301, 距离下一级还需 1699 积分
金牌会员, 积分 1301, 距离下一级还需 1699 积分
积分
1301
发消息
楼主
发表于 2026-8-21 08:24:06
|
显示全部楼层
挠头的500贡献
回复
举报
返回列表
发新帖
高级模式
B
Color
Image
Link
Quote
Code
Smilies
您需要登录后才可以回帖
登录
|
立即注册
本版积分规则
发表回复
回帖后跳转到最后一页
浏览过的版块
素材分享
快速回复
返回顶部
返回列表