设为首页收藏本站|繁體中文

Project1

 找回密码
 注册会员
搜索
查看: 25282|回复: 91
打印 上一主题 下一主题

[RMVA发布] [教程向]VA任务系统

[复制链接]

Lv3.寻梦者

梦石
0
星屑
3298
在线时间
1120 小时
注册时间
2009-4-15
帖子
815
跳转到指定楼层
1
发表于 2015-3-27 13:51:23 | 只看该作者 |只看大图 回帖奖励 |正序浏览 |阅读模式

加入我们,或者,欢迎回来。

您需要 登录 才可以下载或查看,没有帐号?注册会员

x
本帖最后由 tan12345 于 2015-7-7 19:14 编辑

大家好,我是tan12345

今天给大家带来的是个教程(神马,不是任务系统吗?呵呵…… )

由于我是新人,所以肯请各位大神高抬贵手,点击右上角的关闭按钮退出浏览器(都是大神了, 凑什么热闹?)
本教程也不是写给菜鸟看的,需要一定的脚本基础,如果你是菜鸟,请拉到最下方,下载附件,那里有成品( 算你识相,下载完附件我就闪~)

说到任务系统,在66论坛里我知道的用的比较多的有2个,1个是https://rpg.blue/thread-216707-1-1.html(后面好几个版本有些是按这个来改的),另1个是https://rpg.blue/thread-358534-1-1.html(很不错的一个系统)
既然有了这2个任务系统,我为什么要还要任务系统教程呢?(因为我想装逼
因为第1个系统有几个瑕疵:
1.当任务大于14个的时候,任务名就是一片空白(不好直接改源代码,需要重写列表那个窗口类),具体看https://rpg.blue/forum.php?mod=v ... p;extra=#pid2592838
2.不好实现杀怪数(可以用怪物掉落来实现,但是需要占用怪物掉落物)
第2个系统是很不错的系统,让我不满的地方:外国人写的(你能再无聊点吗?),和横版战斗系统不兼容杀怪数,具体看https://rpg.blue/thread-375622-1-1.html

好了,言归正传,开始教程:
第1步:脚本思路。思路很简单,就是设定任务,实现任务的接取、完成,绘制界面。(这也叫思路
首先,我们来设定任务。任务一般包含几个元素:任务名,任务描述,任务奖励。我们可以扩展点,在VA判定一个任务是否完成往往是通过开关、变量、杀敌数、持有物品等方式来判定的,于是我们的任务系统还可以包括任务完成条件,再扩展一点,连接取任务的条件都可以写在设定里面,嗯,最后,加个任务是否可以完成,差不多了。(教程,像人物委托人之类的大同小异,大家可以把自己需要的元素添加上去,本教程列举这么多)。于是,我们的任务设定格式如下:
[任务名,任务描述,任务奖励,任务接取条件,任务完成条件,是否可重复接取标志]

我们一个一个来分析:
任务名:没什么好讲的,字符串
任务描述:嗯,我们肯定希望自己的任务描述能像VA默认对话框那样支持显示变量的值啊、改变颜色啊等等的功能,这个可以有,但是综合起来,任务描述还是一个字符串,只不过这个字符串需要解析变量等字段而已
任务奖励:任务的奖励可以是物品、武器、金钱、经验、其他等等东西,而且可以同时存在(即可以金钱+经验的方式作为奖励),该怎么设定好呢?其实,这些奖励也是有规则的,规则就是:奖励类型+奖励内容+奖励数量,例如奖励3个1号物品,奖励2把7号防具等等,so,我们可以给不同的奖励做个标记用以区分,同时还要记录奖励的内容和数量,所以我给任务奖励这个东西设定了一个规则:用一个数组来表示奖励,数组规则:[任务奖励标识,任务奖励标识id,任务奖励数量],任务奖励标识用来区分奖励内容的,比如奖励物品我们可以用i来表示,武器用w来表示,金钱用g来表示等等,大家可以自己设定。任务奖励标识id是指奖励的id,比如奖励武器,那么是几号武器?3号武器那id就等于3,5号物品?那id就等于5,类似金钱、经验这种没有id的,我们可以统一用0表示;最后那个任务奖励数量,代表的是……我还是举例吧,比如奖励5把武器,那么任务奖励数量就是5,这个不用我多说?(特殊的,如果用了特殊脚本来实现的奖励,比如第二货币之类的,我们可以给这类奖励设定一个遵循[任务奖励标识,任务奖励标识id,任务奖励数量]的规则,大家可以想想如何规划这种特殊奖励),当多个这样的奖励组合在一起时,其实就是一个多维数组。
任务接取条件:一般任务接取条件在VA的设定里也很简单:队伍持有某些物品、队长等级到了xxxx、某些开关打开或关闭、变量等于某个值等等等等,这类设定其实和上面的任务奖励类似,毕竟他们也遵循[任务奖励标识,任务奖励标识id,任务奖励数量]这个规则,只不过这个规则变成了[接取条件标识,条件标识id,条件要求数量],多个条件同时达成则代表这是1个多维数组(还不理解的童鞋可以查看下面的代码)
任务完成条件:这个其实和任务接取条件一样,最多就多一个:杀死某某怪物xx只……所以他的设定和上面一样……我不多废话。
任务是否可重复接取:这个可以用多种方式来判断,我习惯用数字0、1来判定,所以这里设定为0不可重复,1可以重复。
接下来是代码实现设定:老规矩,我们可以把设定放在module里(为什么要放在module里而不是放在class里?因为……这个问题不属于本贴内容,楼主拒绝回答
然后,既然是任务,肯定不止一个,所以我们可以在module里先设定一个空数组,然后每个任务就是对应1个数组的内容。
最后,我们的设定部分代码如下:
RUBY 代码复制
  1. module Tan_task
  2.  
  3.   #任务列表
  4.   Tan_task_list = []  
  5.  
  6.   #任务格式设定如下:
  7.   #Tan_task_list[id] = ["任务名","任务描述",[任务奖励数组],[任务接取条件数组],[任务完成条件数组],是否可重复接取标志]
  8.  
  9.   #例如:
  10.   #1号任务内容如下:
  11.   Tan_task_list[1] = [
  12.     "测试",             #任务名
  13.  
  14.     #任务描述
  15.     "描述",             #任务描述
  16.  
  17.     #任务奖励
  18.     #第1位代表奖励类型,0金钱,1武器,2防具,3物品,5经验值,9其他
  19.     #第2位代表奖励的id,如果没有id,则统一0(金钱、经验值、其他都是没有id的)
  20.     #第3位代表奖励数值。
  21.     #例如:[0,0,100]金钱100,[1,99,2]99号武器2把,[5,0,1000]经验值1000(不显示升级),[5,1,1000]经验值1000(显示升级)
  22.     #例如:[2,3,1]3号防具1个,[3,5,7]5号物品7个,[9,0,"$game_party.add_actor(33)"]33号人物入队
  23.     [],#如果没有奖励,则[]
  24.  
  25.     #任务接取条件
  26.     #第1位代表条件类型,l领队等级,i持有物品,s开关打开,v变量值,q前置任务,g金钱
  27.     #第2位代表条件类型的id,如果没有id,则统一0(领队等级、前置任务、金钱是没有id的)
  28.     #第3位代表条件数值。
  29.     #例如:["l",0,10]领队要求10级,["i",6,3]持有3个6号物品,["s",7,true]7号开关打开
  30.     #例如:["v",5,10]5号变量等于10,["g",0,3]持有3金钱,["q",0,3]完成3号任务
  31.     [],#如果没有条件,则[]
  32.  
  33.     #任务完成条件
  34.     #第1位代表条件类型,l领队等级,i持有物品,s开关打开,v变量值,q前置任务,g金钱,e杀敌数
  35.     #第2位代表条件类型的id,如果没有id,则统一0(领队等级、前置任务、金钱是没有id的)
  36.     #第3位代表条件数值。
  37.     #例如:["l",0,10]领队要求10级,["i",6,3]持有3个6号物品,["s",7,true]7号开关打开
  38.     #例如:["v",5,10]5号变量等于10,["g",0,3]持有3金钱,["q",0,3]完成3号任务,["e",7,10]杀死10个7号敌人
  39.     [],#如果没有条件,则[]
  40.  
  41.     #该任务完成后是否可重复接取,0不可重复,1可重复
  42.     0
  43.   ]
  44.  
  45.   Tan_task_list[2] = [
  46.     "任务2",
  47.     "要求队长达到10级,杀死史莱姆3只。",
  48.     [],
  49.     [],
  50.     [["l",0,10],["e",1,3]],
  51.     0
  52.   ]
  53. end

大家不一定要按照我的格式写,大家可以自己拓展想象,写程序最重要的是思路,一旦思路成型,实现代码其实是很简单的事情。

好了,设定完成,让我喘口气,呼,写教程真累,早知道我直接上传自己写的任务系统一了百了……(叫你装比
接下来是实现,任务系统包含任务的接取、完成,其实这只是表面的,暗地里还有任务是否可以接取、任务是否可以完成,我们来探讨下这些内容怎么写。
首先,这些东西应该放在哪呢?像任务系统,在VA这个系统里,我认为应该放到人物队伍这个类(即class Game_Party或者也叫$game_party),很简单,任务是一个队伍的任务,不是1个人的,不是敌人的,他和队伍金钱这个概念一样,属于队伍,也需要存放在队伍里,通过队伍这个类,来存放哪些任务完成了,哪些任务接取了(通俗点讲,我把这个称为任务状态,任务状态分为未接取、已接取或进行中、可交付、已完成,归根结底,就3种状态:未接取,接取了没交付,已完成),我用0、1、2这3个数字分别代替3种状态,于是,我们可以在class Game_Party下面新增1个字段,这个字段就是专门记录所有任务的状态的,这个字段在$game_party初始化时统一设为0。
代码如下:
RUBY 代码复制
  1. class Game_Party < Game_Unit
  2.  
  3.   attr_reader :tan_task_state   #任务状态数组
  4.  
  5.   #--------------------------------------------------------------------------
  6.   # ● 初始化对象(alias重写)
  7.   #--------------------------------------------------------------------------
  8.   alias tan_task_game_party_init initialize
  9.   def initialize
  10.     tan_task_game_party_init
  11.     @tan_task_state = [0] * Tan_task::Tan_task_list.size
  12.   end
  13. end


然后是任务接取,任务的接取也很简单:判定任务是否可接取,如果可接取,接取他,如果不可接取,返回。
我们先讲任务是否可接取,第id号任务是否可接取我们可以通过判断tan_task_state[id]的值,以及该id号任务所需的条件来进行判定,如果tan_task_state[id]的值为0,可以接取,如果满足id号任务的接取条件,可以接取,再细化思路,如下:
return false if @tan_task_state[id] != 0#任务状态不为0,代表任务已完成或进行中,不可接取
return true if Tan_task::Tan_task_list[id][3].size == 0#任务接取条件这个数组如果是空,代表接取这个任务不需要条件,否则
re = 0#设定一个临时变量,如果我们达到了接取条件,不动,如果我们有1个任务接取条件没达成,这个变量自加1,最后判定这个变量是不是0,如果不是0,表示我们还有没有达成条件的地方,不能接取任务,否则,可以接取任务
这部分代码如下:
RUBY 代码复制
  1. #--------------------------------------------------------------------------
  2.   # ● 判定任务是否可接取
  3.   #--------------------------------------------------------------------------
  4.   def can_accept_the_tan_task?(id)
  5.     return false if @tan_task_state[id] != 0
  6.     return true if Tan_task::Tan_task_list[id][3].size == 0
  7.     re = 0
  8.     Tan_task::Tan_task_list[id][3].each {|q|
  9.       case q[0]
  10.       when "l"#等级条件
  11.         re += 1 if leader.level <= q[2].to_i
  12.       when "i"#持有物品
  13.         re += 1 if item_number($data_items[q[1].to_i]) <= q[2].to_i
  14.       when "g"#金钱
  15.         re += 1 if gold <= q[2].to_i
  16.       when "q"#前置任务
  17.         re += 1 if @tan_task_state[q[2].to_i] != 2
  18.       when "s"#开关状态
  19.         re += 1 if $game_switches[q[1].to_i] != q[2]
  20.       when "v"#变量值是否等于指定值
  21.         re += 1 if $game_variables[q[1].to_i].to_s != q[2].to_s
  22.       end
  23.     }
  24.     return false if re != 0
  25.     return true
  26.   end


好了,判定任务是否可接取也好了,然后就是任务的接取:如果任务可接取,接取他,同时tan_task_state[id]的值变成1,代表任务已接取。(在这里,我把任务的判定和任务的接取分开了,没写在一个方法里,需要的时候2个方法一起出现就好)

接下来,任务的交付,同样的,任务的交付其实和任务的接取思路是一样的:判定任务是否可交付,如果可交付,交付他,如果不可交付,返回。(本段内容因为大量重复以上内容,所以我厚颜无耻的说,这是你们的作业,大家可以自己想想这个怎么写,啊哈哈哈哈

接下来是重点:杀敌数。
首先是思路:老规矩,杀敌数其实也属于队伍这个类记录的东西,因为在VA里,战斗是2个队伍之间的事情,我方队伍和敌方队伍。同时,在任务系统里,可能不同的2个任务都需要杀同1个怪,或者1个任务杀多种怪,而且有可能任务1我们做到一半了然后去接的任务2,所以,我们要分开记录不同任务里要杀的不同的怪。先分析一下,我们需要区分的东西:任务号,杀怪id,需要杀的数量,以及当前已杀的数量,大家可以自行思考下该如何表达这4个元素,要方便寻找,又要方便更新。
我的做法是,使用哈希表,因为哈希表的结构是{A => B},我可以将任务号+下划线+杀怪id来做成A,[杀怪id,已杀数量]来做成B(我的做法不是最好的,这样设定只是为了杀怪时方便对比,大家可以想想怎样设定更好),这样,在接取到需要杀怪的任务时,就向哈希表添加一个"qid_eid"=>[eid,0],然后在战斗胜利时,遍历eid,如果有要杀的怪,[eid,0]后面就增加相应数量,当某个任务要杀的某个怪物[eid,xx]中xx>=任务设定的数量时,代表杀够了。
那么,现在问题来了(挖掘机技术哪家强 ),我们如何在战斗胜利时记录杀怪?我们回想一下,战斗胜利要结算什么?结算物品掉落,那我们能不能把杀怪数也在那一起结算?可以。为什么要放在物品掉落那里计算?因为物品掉落在战斗过程中只结算一次(你也不希望杀1个怪算多次击杀数吧)。
于是,这部分的相关代码如下:
RUBY 代码复制
  1. class Game_Party < Game_Unit
  2.  
  3.   attr_accessor :tan_task_enemy_kill_number   #记录杀敌数
  4.  
  5.   #--------------------------------------------------------------------------
  6.   # ● 初始化对象(alias重写),初始化杀怪数
  7.   #--------------------------------------------------------------------------
  8.   alias tan_task_game_party_init initialize
  9.   def initialize
  10.     tan_task_game_party_init
  11.     @tan_task_enemy_kill_number = {}
  12.   end
  13.  
  14.   #--------------------------------------------------------------------------
  15.   # ● 接取任务接任务时,如果有要记录杀怪数量的,杀怪数那个哈希表就添加一个"qid_eid"=>[eid,0]
  16.   #--------------------------------------------------------------------------
  17.   def accept_the_tan_task(id)
  18.     Tan_task::Tan_task_list[id][4].each {|q|
  19.       case q[0]
  20.       when "e"#杀敌数
  21.         t = id.to_s + "_" + q[1].to_s
  22.         @tan_task_enemy_kill_number[t] = [q[1].to_i,0]
  23.       end
  24.     }
  25.   end
  26.   #--------------------------------------------------------------------------
  27.   # ● 完成任务时,如果有要记录杀怪数量的,杀怪数那个哈希表就将对应的"qid_eid"=>[eid,xx]删除掉
  28.   #--------------------------------------------------------------------------
  29.   def finish_the_tan_task(id)
  30.     Tan_task::Tan_task_list[id][4].each {|q|
  31.       case q[0]
  32.       when "e"#杀敌数
  33.         t = id.to_s + "_" + q[1].to_s
  34.         @tan_task_enemy_kill_number.delete(t)
  35.       end
  36.     }
  37.   end
  38.   #--------------------------------------------------------------------------
  39.   # ● 判定任务是否可交付
  40.   #--------------------------------------------------------------------------
  41.   def can_finish_the_tan_task?(id)
  42.     return false if @tan_task_state[id] != 1
  43.     return true if Tan_task::Tan_task_list[id][4].size == 0
  44.     re = 0
  45.     Tan_task::Tan_task_list[id][4].each {|q|
  46.       case q[0]
  47.       when "e"#指定杀敌数
  48.         t = id.to_s + "_" + q[1].to_s
  49.         re += 1 if @tan_task_enemy_kill_number[t][1] < q[2].to_i
  50.       end
  51.     }
  52.     return false if re != 0
  53.     return true
  54.   end
  55.  
  56. #记录杀敌数
  57. class Game_Troop < Game_Unit
  58.   #--------------------------------------------------------------------------
  59.   # ● 计算杀敌数,其实就是遍历敌人队列和杀敌数哈希表,将
  60.   #--------------------------------------------------------------------------
  61.   def tan_task_kill_number
  62.     dead_members.each {|enemy|
  63.       $game_party.tan_task_enemy_kill_number.each_value{|knum| knum[1] += 1 if knum[0].to_i == enemy.enemy_id}
  64.     }
  65.   end
  66.   #--------------------------------------------------------------------------
  67.   # ● 生成物品数组(alias重写),将计算杀敌数的方法放到这里,在掉落物里计算杀敌数
  68.   #--------------------------------------------------------------------------
  69.   alias tan_task_game_troop_make_drop_items make_drop_items
  70.   def make_drop_items
  71.     tan_task_kill_number
  72.     return tan_task_game_troop_make_drop_items
  73.   end
  74. end

好了,任务系统的核心基本已经设定完毕,剩下的就是界面的制作,界面的实现本帖没有(你这不是坑爹吗?),论坛里关于界面的制作其实很多,所以我不多说。
本贴子主要教大家实现任务系统的思路、设定、核心,至于界面,大家可以自由发挥,欢迎大家一起探讨其他系统的实现(战斗系统、宠物系统、技能树系统、光环等等等等)。
最后,放上成品: VA任务系统.rar (1.43 MB, 下载次数: 1279, 售价: 10 星屑)

评分

参与人数 1星屑 +120 收起 理由
莫言别离 + 120 好用

查看全部评分

Lv1.梦旅人

梦石
0
星屑
64
在线时间
5 小时
注册时间
2019-3-10
帖子
4
62
发表于 2023-7-21 21:52:00 | 只看该作者
我使用這個腳本進行修改,追加任務的部分不會顯示物品扣除
是哪個部分需要另外寫腳本嗎?

点评

对。  发表于 2023-7-22 10:58
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
62
在线时间
6 小时
注册时间
2021-8-20
帖子
3
61
发表于 2021-8-21 19:06:44 | 只看该作者
谢谢分享
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
40
在线时间
20 小时
注册时间
2019-6-26
帖子
19
60
发表于 2020-4-5 00:18:17 | 只看该作者
研究一下
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
160
在线时间
19 小时
注册时间
2018-12-19
帖子
14
59
发表于 2018-12-25 02:11:06 | 只看该作者
童话chan 发表于 2015-6-18 18:01
非常感谢大大的指导!我按照任务奖励的脚本格式加了段放弃任务的功能,测试可以使用,真的很感谢!
其实 ...

对不起……这么久了来挖坟着实抱歉!请问一下你的那个交付任务调用脚本扣除对应物品是怎么做到的,我用了好像没有办法做到,是加了什么语句吗?
All for one.
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
41
在线时间
5 小时
注册时间
2018-12-8
帖子
1
58
发表于 2018-12-17 19:48:36 | 只看该作者
谢谢大佬
回复 支持 反对

使用道具 举报

Lv3.寻梦者

梦石
0
星屑
1883
在线时间
157 小时
注册时间
2016-1-29
帖子
267
57
发表于 2018-11-26 17:17:55 | 只看该作者
大神 我设置了 e 336 10 就是336号怪打10只 为什么接任务就崩溃啊!
回复 支持 反对

使用道具 举报

Lv3.寻梦者

梦石
0
星屑
1883
在线时间
157 小时
注册时间
2016-1-29
帖子
267
56
发表于 2018-11-26 16:36:56 | 只看该作者
大神 怎么在任务界面记录杀敌数啊?
回复 支持 反对

使用道具 举报

Lv3.寻梦者

梦石
0
星屑
1167
在线时间
78 小时
注册时间
2011-3-13
帖子
11
55
发表于 2018-9-29 21:08:41 | 只看该作者
  Tan_task_list[3]为什么只有 2、3、5才有用,其他的无任务
回复 支持 反对

使用道具 举报

Lv2.观梦者

梦石
0
星屑
812
在线时间
136 小时
注册时间
2018-2-5
帖子
17
54
发表于 2018-2-8 01:47:04 | 只看该作者
找了几个VA任务脚本,要么和其他脚本冲突要么用不了,终于找到一个能用的了,感谢楼主
矛盾着的对立面又统一又斗争,从而推动事物的发展;事物是螺旋上升的。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

拿上你的纸笔,建造一个属于你的梦想世界,加入吧。
 注册会员
找回密码

站长信箱:[email protected]|手机版|小黑屋|无图版|Project1游戏制作

GMT+8, 2024-11-24 10:16

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

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