13674307070 发表于 2026-8-21 07:59:30

宠物系统是 VV 引擎最庞大的伙伴体系

一、配置体系:三张表撑起整个宠物系统
宠物系统不是光靠接口就能跑的,它的底层是三张配置表。理解了这三张表的关系,就理解了宠物系统的设计根基。

第一张是怪物表 cfg_monster.xls。宠物本质上是一种特殊的怪物,所以宠物的基础数据(名字、外形、血量、攻击、防御)都存在怪物表里。但宠物不是普通怪物,它有严格的类型要求 ——race 必须是 156、RaceImg 必须是 19,而且 Custommonster 字段必须填至少一种攻击形式。

这个限制说明宠物走的是 "自定义怪物" 的路线。普通怪物的 AI 和行为是引擎内置的,而自定义怪物(race=156)的行为可以通过 cfg_monattack.xls 来配置,包括攻击方式、技能、特效等。宠物需要更灵活的行为控制(比如跟随主人、协助攻击、拾取物品),所以必须用自定义怪物类型。

第二张是宠物等级表 cfg_petlevel.xls。这张表定义了宠物每一级的经验需求和属性成长。宠物升级不是引擎自动算的,而是根据这张表的配置来 —— 多少经验升一级,升级后加多少血多少攻多少防,全部在表里配。

这张表的存在让宠物的成长完全可配置。不同版本可以有不同的宠物成长曲线 —— 有的版本宠物升级快属性低,有的版本升级慢属性高,全部通过改表实现,不需要改代码。而且不同宠物可以有不同的成长配置,做多种宠物的时候很灵活。

第三张是自定义怪物表 cfg_monattack.xls。这张表配置自定义怪物的攻击表现 —— 攻击方式、技能 ID、伤害范围、冷却时间、特效等。宠物的攻击行为就是通过这张表来定义的,你可以给宠物配置普通攻击、技能攻击、甚至多种攻击方式轮换。

这张表和 addpetskill / delpetskill 接口配合使用 —— 接口可以给宠物动态增加或删除攻击表现 ID,也就是给宠物学技能或者忘技能。这样宠物的攻击方式不是固定的,可以通过游戏内的玩法(比如宠物技能书)来改变。

三张表的关系是:怪物表定义宠物 "是什么"(基础属性和外形),等级表定义宠物 "怎么成长"(经验和属性增长),攻击表定义宠物 "怎么打"(攻击方式和技能)。三张表配合,再加上接口层的动态操作,构成了完整的宠物系统。

这里有个重要的心得:做宠物系统之前先把配置表配好,接口只是操作配置的手段。很多人一开始就盯着接口看,忽略了配置表,结果发现很多功能(比如宠物升级、宠物攻击)接口里没有,其实是在配置表里。接口管的是动态操作(创建、召唤、加属性、学技能),静态配置(基础属性、成长曲线、攻击方式)全部在表里。

二、生命周期:从蛋到宠物,从宠物到蛋
宠物的生命周期比英雄复杂得多,因为它多了一个 "蛋" 的形态。宠物可以是一只活的伙伴,也可以是一个放在背包里的道具,两种形态可以互相转换。

宠物蛋是宠物的道具形态,物品类型是 StdMode=201,Anicount 字段填对应怪物表里宠物的 IDX。也就是说,一个宠物蛋物品通过 Anicount 字段关联到怪物表里的某个宠物配置,双击蛋就能孵化出对应的宠物。

宠物蛋不只是一个 "孵化凭证",它还能保存宠物的状态。 GetPetEggInfo 和 SetPetEggInfo 可以读写宠物蛋里的等级、HP、MP、EXP。这意味着宠物变成蛋之后,它的等级和经验不会丢失,下次孵化出来还是原来的等级。这个设计很重要 —— 玩家辛苦练的宠物,收起来变成蛋,再放出来还是原来的样子,不会重置。

usepetitem 是使用宠物蛋的触发,玩家双击蛋的时候触发。你可以在这里做自定义逻辑 —— 比如检查玩家宠物栏是否满了、检查是否满足孵化条件、播放孵化动画等。

获得宠物有两种方式。方式一是双击宠物蛋孵化,方式二是用 CreatePet 接口直接创建,传怪物名称和等级。两种方式最终都会触发 getnewpet 触发 —— 这个触发在获得宠物时触发,而且玩家上线首次加载宠物时也会触发。

"上线首次加载也触发" 这个细节很重要。它意味着 getnewpet 不只是 "新获得宠物" 的时候触发,每次玩家上线宠物加载时也会触发。所以在这个触发里写逻辑的时候要注意区分是 "新获得" 还是 "上线加载"—— 如果逻辑只应该在新获得时执行(比如给新手奖励),就要加判断,不然玩家每次上线都会触发一次。

召唤和收回用 RecallPet 和 DismissPet,和英雄的召唤收回类似,但多了一个序号参数 —— 因为玩家可以有多个宠物,需要指定召唤哪一个。传 - 1 表示当前宠物。文档里说如果宠物不存在或已经召唤出,系统会自动提示,不需要自己判断。

死亡和复活是宠物生命周期的重要环节。宠物死亡触发 petdie,死亡后宠物不会消失,而是进入死亡状态,需要用 realivepet 复活,复活后再用 RecallPet 召唤出来。复活可以指定复活后的 HP 量,支持绝对值和百分比两种方式。

这种 "死亡后需要复活再召唤" 的设计,增加了宠物的维护成本 —— 宠物死了不是放个技能就活,得先复活再召唤。做宠物复活道具、宠物治疗 NPC 的时候,就是围绕这个流程来的。

变蛋用 PetToEgg,把宠物收回变成宠物蛋物品存入背包。文档里特别注明 "如背包满则删除宠物"—— 这个坑要注意,玩家背包满了点收回宠物,宠物可能直接没了。实际使用的时候最好在变蛋前先检查背包空间,或者给玩家提示,避免宠物丢失。变蛋触发 pettoitem。

删除用 DelPet,删掉指定序号的宠物。删除是不可逆的,和英雄删除一样要加确认。

宠物的生命周期看下来,最核心的特点是蛋和宠物两种形态的转换。这个设计让宠物更像是一个 "可携带可交易的物品"—— 玩家可以把宠物变成蛋交易给别人,别人孵化后就是一只有等级有经验的成品宠物。这种可交易性是英雄系统没有的,也是宠物系统经济价值的基础。

三、多宠物管理:序号、当前宠物、自动补齐
和英雄系统 "一个玩家只能有一个英雄" 不同,宠物系统支持一个玩家拥有多个宠物。这就引入了多宠物管理的问题。

序号是宠物的身份标识,从 0 开始。玩家拥有的第一只宠物是 0 号,第二只是 1 号,依此类推。大部分宠物接口都带序号参数,指定操作哪一只宠物。传 - 1 表示操作 "当前宠物"。

当前宠物是一个很重要的概念。玩家虽然可以有多只宠物,但同时只能有一只 "当前宠物"—— 被召唤出来战斗的那只。 GetPet 传 - 1 就是获取当前宠物对象, RecallPet 传 - 1 就是召唤当前宠物。当前宠物的切换应该是通过界面操作的(玩家在宠物面板里选择哪只作为当前),脚本层可以通过序号来指定操作。

自动补齐是多宠物管理的一个细节。文档里说,删除一个序号的宠物后,后面的序号自动补齐。比如有 5 只宠物(0-4),删除 3 号后,原来的 4 号变成 3 号。这个设计意味着宠物序号不是固定的 —— 删除操作会导致后面的宠物序号前移。

这个细节很重要,实际开发中要注意:不要把宠物序号存下来当固定标识用,因为删除操作会改变序号。如果需要唯一标识一只宠物,应该用宠物对象或者宠物的其他唯一属性,而不是序号。序号只是 "当前宠物列表中的位置",不是宠物的永久 ID。

GetPetCount 获取宠物数量,配合序号可以遍历所有宠物。做宠物面板、批量操作的时候用。

多宠物管理的设计虽然简单(就是序号 + 当前宠物),但自动补齐这个细节容易被忽略。做宠物相关的存储和逻辑的时候,要意识到序号是可变的,不要依赖序号做持久化标识。

四、宠物装备:属性附加式的特殊装备系统
宠物也能穿装备,但宠物的装备系统和人物 / 英雄的装备系统完全不同。

人物和英雄有标准的装备栏 —— 武器、衣服、头盔、项链、戒指、手镯,每个位置一件装备,穿脱就是物品在背包和装备栏之间移动。

宠物没有装备格子。文档里明确说了 "宠物没有装备格子,可以用命令获取宠物身上装备清单,显示到面板"。宠物穿装备用 pettakeon,传装备名称(多个用 #分隔),这个接口 "不会增加物品,仅将物品的属性添加到宠物身上,并保存到数据库"。

这句话的意思是:宠物穿装备不是把物品从背包移到装备栏,而是直接把装备的属性附加到宠物身上,物品本身不消耗(或者说引擎内部处理了)。脱装备用 pettakeoff,"不扣减物品,仅扣减宠物身上对应装备属性"。传 - 1 表示脱下全部装备。

这种 "属性附加式" 的装备系统,和人物的 "物品移动式" 装备系统有本质区别。宠物装备更像是给宠物加一组属性 buff,而不是真的穿了一件物品。这样设计的好处是简单 —— 不需要为宠物设计装备栏 UI,不需要处理物品在背包和装备栏之间的移动,只需要记录宠物身上附加了哪些装备的属性。

但限制也很明显:文档里说了 "宠物穿戴装备只支持装备表里的装备,自定义属性、套装等装备不支持"。也就是说,宠物只能穿标准装备,那些带自定义词条、套装效果的特殊装备,宠物穿了也不会生效。这是因为宠物装备是属性附加式的,只能附加装备表中的基础属性,自定义属性和套装效果需要更复杂的计算,宠物系统没有支持。

getpetbodyitem 可以获取宠物身上的装备列表,用来显示到面板上。因为宠物没有装备格子,所以需要这个接口来告诉前端宠物穿了什么,前端自己做展示。

宠物装备系统的设计思路是:用最简单的方式实现最核心的需求(宠物能穿装备加属性),放弃复杂的功能(自定义属性、套装、装备栏 UI)。这种取舍在宠物系统里很常见 —— 毕竟宠物是辅助角色,不需要和人物一样复杂的装备系统,够用就行。

实际开发中的心得:宠物装备的穿脱要自己做 UI 和逻辑,因为引擎没有给宠物装备栏。你需要做一个宠物装备面板,展示宠物身上的装备(通过 getpetbodyitem 获取),处理穿脱操作(调用 pettakeon / pettakeoff),还要处理物品的消耗和返还(因为接口不处理物品,你需要自己扣物品和还物品)。这部分工作量不小,不要以为引擎全包了。

五、战斗体系:攻击、受伤、伤害修改、攻击表现
宠物的战斗体系是宠物系统最复杂的部分,有六个触发和一组接口来支撑。

宠物攻击有两个触发。 attackbypet 是宠物攻击时触发,带玩家对象、宠物序号、目标对象、技能 ID、是否主目标。这个触发是通知性的 —— 告诉你宠物攻击了,你可以做记录、统计、特效等,但不能改变攻击结果。

attackdamagepet 是宠物攻击伤害前触发,这个更重要 —— 它带伤害值,而且有返回值,可以修改伤害。你在这个触发里计算新的伤害,return 回去,引擎就用你修改后的伤害。做宠物伤害加成、宠物暴击、宠物特殊伤害效果的时候,就是在这个触发里处理。

宠物被攻击也有两个触发。 struckdamagepet 是宠物被攻击前触发,和攻击伤害前对应 —— 带伤害值,有返回值,可以修改宠物受到的伤害。做宠物减伤、宠物护盾、宠物特殊防御效果的时候用这个。

struckofpet 是宠物被物理攻击触发, magicstruckofpet 是宠物被魔法攻击触发。这两个是通知性的触发,告诉你宠物被什么类型的攻击打中了,可以做特效、记录、反伤等逻辑,但不能改变伤害。

六个战斗触发的分工很清晰:伤害前触发(attackdamagepet、struckdamagepet)管伤害计算,可以改数值;攻击 / 被攻击触发(attackbypet、struckofpet、magicstruckofpet)管事件通知,做特效和记录。 这种 "计算和通知分离" 的设计很合理,伤害计算的归计算,事件通知的归通知,不会混在一起。

攻击表现是宠物战斗的另一个维度。宠物的攻击方式不是固定的,通过 addpetskill 和 delpetskill 可以动态增加或删除攻击表现 ID,攻击表现配置在 cfg_monattack.xls 里。这意味着宠物可以 "学技能"—— 给宠物增加一个攻击表现 ID,宠物就多了一种攻击方式;删除就忘了。

攻击表现和普通攻击的区别是:普通攻击是宠物基础的平 A,攻击表现是配置好的特殊攻击(可能带技能、特效、特殊伤害范围)。做宠物技能系统的时候,就是围绕 addpetskill / delpetskill 来做 —— 宠物学技能书就 add,遗忘就 del。

setpetatkefftype 设置宠物飘字特效,让宠物攻击时显示特定的伤害数字样式。做宠物品质区分的时候用 —— 高级宠物攻击飘字更炫酷。

宠物战斗体系看下来,设计思路是:引擎管基础战斗逻辑(宠物 AI、攻击判定、基础伤害计算),脚本通过触发管伤害修饰和事件响应,通过攻击表现接口管技能学习。 这种分层设计让宠物战斗既有基础保障,又有足够的自定义空间。

六、行为模式与特殊开关:五种模式加一堆布尔开关
宠物的行为控制比英雄丰富得多,不只是攻击 / 跟随 / 休息三种模式,还有一堆特殊开关。

五种模式用 setpetmode 设置:模式 1 是跟随不攻击,模式 2 是主动攻击,模式 3 是被动(被攻击时才设定目标),模式 4 是休息,模式 5 是协助攻击(优先攻击主人目标)。

比英雄的三种模式多了 "被动" 和 "协助攻击" 两种。被动模式适合不想让宠物乱引怪的场景 —— 宠物不主动打,只有被打了才反击。协助攻击模式是最智能的 —— 宠物不自己选目标,而是打主人正在打的目标,这样不会出现 "主人打 A 宠物打 B" 的尴尬情况。

文档里有个重要说明:设置宠物模式是针对所有宠物同时生效的,如果主人有宝宝,则宝宝同步生效。也就是说, setpetmode 不是只改某一只宠物的模式,而是改玩家所有宠物的模式,而且连英雄(宝宝)也一起改。这个设计简化了操作 —— 玩家切换模式时所有伙伴一起变,不需要一只只改。但也要注意,如果你只想改某一只宠物的模式,这个接口做不到,它是全局生效的。

特殊开关是一堆布尔型的设置,通过 SetPetInfo / GetPetInfo 来操作,或者有独立接口:

PetNoEntity 设置宠物无实体模式 —— 宠物变成半透明的灵体状态,可能无法被攻击也无法攻击(具体效果要看引擎实现)。做幽灵宠物、灵魂宠物的时候用。

PetNoAttack 设置宠物是否攻击 —— 关掉之后宠物不攻击,只跟随。做纯观赏宠物、纯拾取宠物的时候用。

GetPetInfo / SetPetInfo 里还有更多开关:是否开启拾取、是否开启吸取、是否开启瞬移拾取、拾取范围、吸取范围、拾取速度、瞬移间隔、吃药间隔、召唤间隔、是否允许攻击、是否怪物不攻击宠物、是否宠物不受任何攻击、是否受宝宝休息控制、无实体透明度。

这些开关加起来有二十多个,覆盖了宠物行为的方方面面。其中拾取相关的开关是宠物系统特有的 —— 宠物可以帮主人拾取物品、拾取货币、吸取经验 / 血量,甚至瞬移拾取。这些功能让宠物不只是战斗伙伴,还是生活助手。

AddPetPickupMoneyList 和 ClearPetPickupMoneyList 管理宠物拾取货币列表 —— 可以指定宠物拾取哪些货币,不是所有货币都捡。做宠物自动捡元宝的时候用这个。

宠物的行为控制体系看下来,特点是模式管大方向,开关管细节。五种模式决定宠物的基本行为策略,二十多个开关精细控制每一个行为细节。这种设计既简单(大部分玩家只用模式切换)又灵活(高级玩家可以微调每个开关)。

七、成长体系:等级、经验、转生、属性
宠物的成长和人物类似,有等级、经验、转生、属性,但接口更丰富。

等级和经验有独立接口也有统一接口。 petlevel 设置宠物等级,支持加减等于,还能区分普通等级和转生等级(lType 参数:0 是等级,1 是转生等级)。 petexp 设置宠物经验,支持加减等于。

GetPetInfo / SetPetInfo 也能读写等级和经验(Type=1 是等级,Type=4 是经验),还有 HP、MP、防御、魔御、移动速度、攻击速度等属性。两套接口功能有重叠,独立接口( petlevel / petexp )更直观,统一接口( GetPetInfo / SetPetInfo )能一次操作更多属性。

属性有专门的自定义属性系统。 addpetattlist 增加宠物属性,和人物系统的 addattrlist 类似 —— 传属性组名、操作符、属性字符串。 delpetattlist 清除宠物属性,可以按组清除也可以全部清除。

这个自定义属性系统让宠物的属性扩展不受限制 —— 基础属性(攻防血)在配置表里,特殊属性(暴击、闪避、伤害加成)可以通过自定义属性动态添加。做宠物装备、宠物 buff、宠物培养系统的时候,都是往自定义属性里加。

转生通过 petlevel 的 lType=1 来设置, petlevelup 触发里也带了转生等级参数。宠物转生应该是提升宠物属性上限或者解锁特殊能力的玩法,和人物转生类似。

外观用 SetPetAppr 改变,传怪物外观 ID,传 0 还原。做宠物进化、宠物幻化、宠物皮肤的时候用 —— 宠物等级到了一定程度换个更酷的外形,或者给宠物买皮肤。

置换用 petmon,只置换宠物的基础属性(形象、怪物表配置),原宠物的其他属性全部保留,包括序号。这个接口的应用场景是宠物进化或变异 —— 宠物还是那只宠物(序号不变、等级不变、经验不变),但基础形象和属性变成了另一种怪物。做宠物进化树的时候用这个,比删除重建好,因为不会丢失宠物的等级和经验。

宠物成长体系看下来,和人物成长体系思路一致,但接口更分散 —— 等级经验有独立接口,属性有自定义属性系统,外观有单独接口,置换有单独接口。这种分散设计的好处是每个功能独立清晰,坏处是接口数量多,需要记哪个功能用哪个接口。

八、几个实际使用中的心得和坑
把宠物系统过完,结合传奇类游戏的开发经验,总结几个心得和容易踩的坑。

第一,宠物序号是可变的,不要当固定标识用。 删除宠物后后面的序号自动补齐,所以序号会变。需要唯一标识宠物的时候,用宠物对象或者其他唯一属性,不要用序号。做宠物相关的持久化存储时也要注意这一点。

第二,PetToEgg 背包满会删除宠物,一定要先检查背包空间。 文档明确说了 "如背包满则删除宠物",这是一个会导致玩家宠物丢失的严重问题。在变蛋操作前一定要检查背包是否有空间,没有就提示玩家清理背包,不要直接调 PetToEgg。

第三,getnewpet 上线也会触发,注意区分新获得和上线加载。 如果你在这个触发里做 "新获得宠物奖励",玩家每次上线都会领到,因为上线加载宠物也会触发。加判断条件区分两种情况,或者把只应该执行一次的逻辑放到别的地方。

第四,宠物装备不支持自定义属性和套装,不要给宠物穿特殊装备。 文档明确说了只支持装备表里的基础装备,自定义属性、套装效果不生效。如果你的版本有大量自定义词条装备,宠物装备系统的价值会大打折扣,可能需要自己做一套宠物装备逻辑。

第五,setpetmode 是全局生效的,所有宠物和宝宝一起变。 不要以为它只改某一只宠物的模式,它改的是玩家所有伙伴的模式。如果需要单只宠物独立模式,这个接口做不到。

第六,宠物的基础配置在表里,不要在接口里找。 宠物的基础属性、成长曲线、攻击方式都在三张配置表里(怪物表、等级表、攻击表),接口只管动态操作。做宠物系统之前先把表配好,不然很多功能跑不起来。

第七,宠物不支持跨服,做跨服玩法时注意。 文档明确说了宠物目前不支持跨服,玩家跨服的时候宠物可能无法跟随或者数据异常。做跨服活动、跨服战场的时候要考虑宠物的处理 —— 是跨服前强制收回,还是跨服期间宠物不可用,要有明确的策略。

第八,伤害修改触发的返回值要注意类型。 attackdamagepet 和 struckdamagepet 都有返回值,返回修改后的伤害。要确保返回的是整数,不要返回 nil 或者字符串,不然引擎可能用默认伤害或者报错。

第九,宠物复活后要再召唤。 realivepet 只是复活,复活后宠物还是收回状态,需要再调 RecallPet 才能放出来。做宠物复活道具的时候,复活后自动召唤,体验才好,不然玩家复活了发现宠物还没出来,会困惑。

第十,GetPet 没宠物时的返回值要确认。 文档没明确说没宠物时返回什么,可能是 nil 也可能是字符串 "0"(和英雄系统类似)。用之前先测试确认,判断的时候做好兼容处理,不要假设返回值。


13674307070 发表于 2026-8-21 08:25:19

挠头的贡献

jqqcz 发表于 2026-8-25 16:43:17

你是在干什么?

jqqcz 发表于 2026-8-25 16:56:37

看着不错啊你写的

70259636 发表于 2026-8-27 22:18:30

6666666666

70259636 发表于 3 天前

:D:D:D:D:D:D:D:D

hi8 发表于 前天 21:36

需要自己写宠物?
页: [1]
查看完整版本: 宠物系统是 VV 引擎最庞大的伙伴体系