cgmsv引擎论坛

 找回密码
 注册/Sign up
搜索
查看: 2383|回复: 1

[LUA] 自定义道具功能:宠物再生剧药(重加点)、宠物洗档剧药

[复制链接]

Rank: 2

发表于 2021-11-22 04:23:17 | 显示全部楼层 |阅读模式
本帖最后由 2bman 于 2021-11-22 04:26 编辑

依照之前承诺(物品“道具功能”、“特殊功能”全解析),这次来介绍如何使用Lua来扩展物品的自定义功能。

在魔力的道具中有“再生剧药”可以重置人物加点,然而却没有宠物版的再生剧药,如果宠物加错点就只能用重来的种子慢慢调整。
那有没有办法制作出一个宠物版的再生剧药呢?
这次我就利用Lua脚本来制作一个宠物版的再生剧药、以及重生和洗档剧药。

此文的示例及代码参考自cgmsv自带的 lua\Module\nofix\RebirthPet.lua 脚本,我做了一些修改与优化,如果懒得看示例可以下载完整版的附件。

首先,我们需要先注册道具的处理函数:
  1. Delegate.RegInit("PetRebirth_Init")
  2. function PetRebirth_Init()
  3.         --注册宠物再生剧药处理函数
  4.         NL.RegItemString(nil,"usePetRebirth","LUA_usePetRebirth")
  5.         --创建NPC,用于提供对话框
  6.         createPetRebirthNPC1()
  7.         createPetRebirthNPC2()
  8.         createPetRebirthNPC3()
  9. end
复制代码

我们注册一个名为 LUA_usePetRebirth 的处理函数,并使用 usePetRebirth 这个方法来处理,而在道具功能中即可使用此函数来激活我们自定义脚本功能。

在注册完函数后,我们创建了三个NPC,用于给我们的脚本提供对话框与交互处理。

NPC创建函数示例:
  1. function PetRebirth_initialize()
  2.         return true
  3. end
复制代码
  1. function createPetRebirthNPC1()
  2.         if (PetRebirthNPC1 == nil) then
  3.                 PetRebirthNPC1 = NL.CreateNpc(nil, "PetRebirth_initialize")
  4.                 Char.SetData(PetRebirthNPC1, %对象_形象%, 106089)    --%对象_形象%
  5.                 Char.SetData(PetRebirthNPC1, %对象_原形%, 106089)    --%对象_原形%
  6.                 Char.SetData(PetRebirthNPC1, %对象_地图%, 777)      --%对象_地图%
  7.                 Char.SetData(PetRebirthNPC1, %对象_X%, 30)          --%对象_X%
  8.                 Char.SetData(PetRebirthNPC1, %对象_Y%, 30)           --%对象_Y%
  9.                 Char.SetData(PetRebirthNPC1, %对象_方向%, %右下%)    --%对象_方向%, %右下%
  10.                 Char.SetData(PetRebirthNPC1, %对象_原名%, "宠物再生大师")    --%对象_原名%
  11.                 NLG.UpChar(PetRebirthNPC1)
  12.                 if (Char.SetTalkedEvent(nil, "PetRebirth1_Talked", PetRebirthNPC1) < 0) then
  13.                         print("PetRebirth1_Talked 注册事件失败。")
  14.                         return false
  15.                 end
  16.                 if (Char.SetWindowTalkedEvent(nil, "PetRebirth1_WindowTalked", PetRebirthNPC1) < 0) then
  17.                         print("PetRebirth1_WindowTalked 注册事件失败。")
  18.                         return false
  19.                 end
  20.         end
  21.         return true
  22. end
复制代码
PetRebirth_initialize 是 NL.CreateNpc 的回调函数,必须返回 true。
其他的设置可随意,最好将此NPC放到一个普通玩家无法访问的地图中去,因为我们只会在脚本中调用此NPC的功能。
之后我们为NPC注册 SetTalkedEvent 与 SetWindowTalkedEvent 事件,这两个事件是我们与NPC的对话与回调事件。

宠物再生剧药NPC的对话完整示例:
  1. function PetRebirth1_Talked(npc,player)
  2.         NLG.ShowWindowTalked(player,npc,0,12,0,"\n你想重新分配宠物点数吗?")
  3.         return
  4. end
复制代码
  1. function PetRebirth1_WindowTalked(npc,player,_seqno,_select,_data)
  2.         if (_select==8) then
  3.                 --NLG.ShowWindowTalked(player,npc,0,1,11,"已取消操作。")
  4.                 return
  5.         end
  6.         local tab={}
  7.         if (_seqno==0) then
  8.                 for t = 1,5 do
  9.                         local PetIndex = Char.GetPet(player,t-1)
  10.                         if (PetIndex>0) then
  11.                                 tab[t] = "Lv."..Char.GetData(PetIndex, %对象_等级%).." "..Char.GetData(PetIndex, %对象_原名%)
  12.                         else
  13.                                 tab[t] = "无宠物"
  14.                         end
  15.                 end        
  16.                 NLG.ShowWindowTalked(player,npc,2,2,1,
  17.                         "2\n请选择宠物:\n"..
  18.                         "\n       "..tab[1]..
  19.                         "\n       "..tab[2]..
  20.                         "\n       "..tab[3]..
  21.                         "\n       "..tab[4]..
  22.                         "\n       "..tab[5]
  23.                 )
  24.         end
  25.         
  26.         if (_seqno==1) then
  27.                 local petinx=Char.GetPet(player,tonumber(_data)-1)
  28.                 if (petinx<0) then
  29.                         --NLG.ShowWindowTalked(player,npc,0,1,11,"无效的宠物索引")
  30.                         return
  31.                 elseif (Char.GetData(petinx,%对象_等级%)==1) then
  32.                         NLG.ShowWindowTalked(player,npc,0,1,11,"1级宠物没必要还原!")
  33.                 elseif (Char.HaveItem(player,PetRebirthID1) < 0) then
  34.                         NLG.ShowWindowTalked(player,npc,0,1,11,"抱歉,你没有宠物再生剧药!")
  35.                 elseif (petinx>=0 and Char.GetData(petinx,%对象_等级%)>1) then
  36.                         Char.DelItem(player,PetRebirthID1,1)
  37.                         repetlevel(player, petinx)
  38.                         NLG.SystemMessage(player,"你的宠物 "..Char.GetData(petinx,%对象_名字%).." 点数已重置!")
  39.                 end
  40.         end
  41. end
复制代码
  1. function repetlevel(pid, petid)
  2.         local petlvl = Char.GetData(petid,%对象_等级%)
  3.         local exps = 0
  4.         exps = Char.GetData(petid,%对象_经验%) --宠物的额外经验
  5.         for i = petlvl,2,-1 do
  6.                 exps = exps + Char.GetLevelExp(i)
  7.         end
  8.         
  9.         Pet.ReBirth(pid, petid)
  10.         Char.SetData(petid,%对象_经验%,exps)
  11.         Pet.UpPet(pid, petid)
  12. end
复制代码
PetRebirth1_Talked 是我们与NPC首次对话时显示的窗体,我们不需要过多关心它,只需要为它设置好窗体样式即可,主要的回调参数都在 PetRebirth1_WindowTalked 之中。

PetRebirth1_WindowTalked 的参数 _select 是玩家所选择的按钮,如果为8表示点了否,则不对接下来的代码做处理。
_seqno 是玩家选择按钮的序号,玩家点选了列出的宠物之后,就会返回一个大于0的 _seqno 给函数。
最后我们从玩家的宠物序列中找到目标宠物,对目标宠物进行“重生”。
但在这里有一个问题:如果我们直接让宠物重生,再设置宠物的等级,此宠物并不会进行成长,同时也不会得到升级的BP。
为此,我们需要为宠物设置足够等级的经验值,才能让宠物得到BP点。
然而又出现了一个新问题,如何才能获取到指定等级的经验值数量呢?
我通过研究发现,魔力的宠物在升级后,会重置当前等级与升级所需要的经验值,也就是经验值不会随着等级而累加。
脚本内置方法中的 Char.GetLevelExp 虽然可以获得升级所需要的经验,但是这个经验是指“等级-1”升级到“等级”所需要的经验值。
为此,我专门写了一个 repetlevel 方法来解决升级到指定等级需要累加经验的过程。
设置完经验后,我们再将宠物的封包发送给玩家,这样玩家就可以重新给宠物加点,同时也不会改变宠物的等级与档次。

宠物重生剧药、宠物洗档剧药也是类似的原理,只需要根据需求改写 PetRebirth_WindowTalked 的回调事件即可。


最后,就是 usePetRebirth 的处理函数激活示例了:
  1. function usePetRebirth(player,target,slot)
  2.         -- 根据物品ID调用NPC对话
  3.         local iteminx = Char.GetItemIndex(player,slot)
  4.         local itemid = Item.GetData(iteminx,%道具_ID%)
  5.         if itemid == 80000 then
  6.                 PetRebirth1_Talked(PetRebirthNPC1,player)
  7.         elseif itemid == 80001 then
  8.                 PetRebirth2_Talked(PetRebirthNPC2,player)
  9.         elseif itemid == 80002 then
  10.                 PetRebirth3_Talked(PetRebirthNPC3,player)
  11.         else
  12.                 NLG.SystemMessage(player,"无法识别道具")
  13.         end
  14. end
复制代码
当用户双击了使用 LUA_usePetRebirth 作为功能的道具时,就会激活 usePetRebirth 这个函数。
我将宠物再生剧药设为80000、重生剧药设为80001、洗档剧药设为80002,函数会根据道具的ID打开不同的NPC对话框,然后再根据回调事件执行不同的命令。




如有建议或疑问请留言。




补充内容 (2021-11-28 01:40):
_seqno 的描述是错误的,其值来自于对话框设定的数值,这个数值可以由脚本自己决定,也是唯一可以给回调函数传递参数的方法。

ClsoPetRebirth.zip

2.53 KB, 下载次数: 0, 下载积分: 金币 -1

评分

参与人数 1金币 +2 收起 理由
Zack + 2 原创技术贴

查看全部评分

Rank: 2

 楼主| 发表于 2021-11-22 04:54:24 | 显示全部楼层
重新分配点数的函数忘记加野生宠物判定了,请自行修改:

  1. function PetRebirth1_WindowTalked(npc,player,_seqno,_select,_data)
  2.         if (_select==8) then
  3.                 --NLG.ShowWindowTalked(player,npc,0,1,11,"已取消操作。")
  4.                 return
  5.         end
  6.         local tab={}
  7.         if (_seqno==0) then
  8.                 for t = 1,5 do
  9.                         local PetIndex = Char.GetPet(player,t-1)
  10.                         if (PetIndex>0) then
  11.                                 tab[t] = "Lv."..Char.GetData(PetIndex, %对象_等级%).." "..Char.GetData(PetIndex, %对象_原名%)
  12.                         else
  13.                                 tab[t] = "无宠物"
  14.                         end
  15.                 end       
  16.                 NLG.ShowWindowTalked(player,npc,2,2,1,
  17.                         "2\n请选择宠物:\n"..
  18.                         "\n       "..tab[1]..
  19.                         "\n       "..tab[2]..
  20.                         "\n       "..tab[3]..
  21.                         "\n       "..tab[4]..
  22.                         "\n       "..tab[5]
  23.                 )
  24.         end
  25.        
  26.         if (_seqno==1) then
  27.                 local petinx=Char.GetPet(player,tonumber(_data)-1)
  28.                 if (petinx<0) then
  29.                         --NLG.ShowWindowTalked(player,npc,0,1,11,"无效的宠物索引")
  30.                         return
  31.                 elseif (Char.GetData(petinx,%对象_等级%)==1) then
  32.                         NLG.ShowWindowTalked(player,npc,0,1,11,"1级宠物没必要还原!")
  33.                 elseif (Char.GetData(petinx,%宠物_获取时等级%) ~= 1) then
  34.                         NLG.ShowWindowTalked(player,npc,0,1,11,"抱歉,该宠物非1级捕获,无法重生!")
  35.                 elseif (Char.HaveItem(player,PetRebirthID1) < 0) then
  36.                         NLG.ShowWindowTalked(player,npc,0,1,11,"抱歉,你没有宠物再生剧药!")
  37.                 elseif (petinx>=0 and Char.GetData(petinx,%对象_等级%)>1) then
  38.                         Char.DelItem(player,PetRebirthID1,1)
  39.                         repetlevel(player, petinx)
  40.                         NLG.SystemMessage(player,"你的宠物 "..Char.GetData(petinx,%对象_名字%).." 点数已重置!")
  41.                 end
  42.         end
  43. end
复制代码
您需要登录后才可以回帖 登录 | 注册/Sign up

本版积分规则

手机版|cgmsv引擎论坛

GMT+8, 2024-11-21 21:47 , Processed in 0.183217 second(s), 10 queries , Gzip On, MemCached On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表