赞 | 2 |
VIP | 15 |
好人卡 | 41 |
积分 | 33 |
经验 | 128560 |
最后登录 | 2024-4-2 |
在线时间 | 1120 小时 |
Lv3.寻梦者
- 梦石
- 0
- 星屑
- 3298
- 在线时间
- 1120 小时
- 注册时间
- 2009-4-15
- 帖子
- 815
|
加入我们,或者,欢迎回来。
您需要 登录 才可以下载或查看,没有帐号?注册会员
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个数组的内容。
最后,我们的设定部分代码如下:
module Tan_task #任务列表 Tan_task_list = [] #任务格式设定如下: #Tan_task_list[id] = ["任务名","任务描述",[任务奖励数组],[任务接取条件数组],[任务完成条件数组],是否可重复接取标志] #例如: #1号任务内容如下: Tan_task_list[1] = [ "测试", #任务名 #任务描述 "描述", #任务描述 #任务奖励 #第1位代表奖励类型,0金钱,1武器,2防具,3物品,5经验值,9其他 #第2位代表奖励的id,如果没有id,则统一0(金钱、经验值、其他都是没有id的) #第3位代表奖励数值。 #例如:[0,0,100]金钱100,[1,99,2]99号武器2把,[5,0,1000]经验值1000(不显示升级),[5,1,1000]经验值1000(显示升级) #例如:[2,3,1]3号防具1个,[3,5,7]5号物品7个,[9,0,"$game_party.add_actor(33)"]33号人物入队 [],#如果没有奖励,则[] #任务接取条件 #第1位代表条件类型,l领队等级,i持有物品,s开关打开,v变量值,q前置任务,g金钱 #第2位代表条件类型的id,如果没有id,则统一0(领队等级、前置任务、金钱是没有id的) #第3位代表条件数值。 #例如:["l",0,10]领队要求10级,["i",6,3]持有3个6号物品,["s",7,true]7号开关打开 #例如:["v",5,10]5号变量等于10,["g",0,3]持有3金钱,["q",0,3]完成3号任务 [],#如果没有条件,则[] #任务完成条件 #第1位代表条件类型,l领队等级,i持有物品,s开关打开,v变量值,q前置任务,g金钱,e杀敌数 #第2位代表条件类型的id,如果没有id,则统一0(领队等级、前置任务、金钱是没有id的) #第3位代表条件数值。 #例如:["l",0,10]领队要求10级,["i",6,3]持有3个6号物品,["s",7,true]7号开关打开 #例如:["v",5,10]5号变量等于10,["g",0,3]持有3金钱,["q",0,3]完成3号任务,["e",7,10]杀死10个7号敌人 [],#如果没有条件,则[] #该任务完成后是否可重复接取,0不可重复,1可重复 0 ] Tan_task_list[2] = [ "任务2", "要求队长达到10级,杀死史莱姆3只。", [], [], [["l",0,10],["e",1,3]], 0 ] end
module Tan_task
#任务列表
Tan_task_list = []
#任务格式设定如下:
#Tan_task_list[id] = ["任务名","任务描述",[任务奖励数组],[任务接取条件数组],[任务完成条件数组],是否可重复接取标志]
#例如:
#1号任务内容如下:
Tan_task_list[1] = [
"测试", #任务名
#任务描述
"描述", #任务描述
#任务奖励
#第1位代表奖励类型,0金钱,1武器,2防具,3物品,5经验值,9其他
#第2位代表奖励的id,如果没有id,则统一0(金钱、经验值、其他都是没有id的)
#第3位代表奖励数值。
#例如:[0,0,100]金钱100,[1,99,2]99号武器2把,[5,0,1000]经验值1000(不显示升级),[5,1,1000]经验值1000(显示升级)
#例如:[2,3,1]3号防具1个,[3,5,7]5号物品7个,[9,0,"$game_party.add_actor(33)"]33号人物入队
[],#如果没有奖励,则[]
#任务接取条件
#第1位代表条件类型,l领队等级,i持有物品,s开关打开,v变量值,q前置任务,g金钱
#第2位代表条件类型的id,如果没有id,则统一0(领队等级、前置任务、金钱是没有id的)
#第3位代表条件数值。
#例如:["l",0,10]领队要求10级,["i",6,3]持有3个6号物品,["s",7,true]7号开关打开
#例如:["v",5,10]5号变量等于10,["g",0,3]持有3金钱,["q",0,3]完成3号任务
[],#如果没有条件,则[]
#任务完成条件
#第1位代表条件类型,l领队等级,i持有物品,s开关打开,v变量值,q前置任务,g金钱,e杀敌数
#第2位代表条件类型的id,如果没有id,则统一0(领队等级、前置任务、金钱是没有id的)
#第3位代表条件数值。
#例如:["l",0,10]领队要求10级,["i",6,3]持有3个6号物品,["s",7,true]7号开关打开
#例如:["v",5,10]5号变量等于10,["g",0,3]持有3金钱,["q",0,3]完成3号任务,["e",7,10]杀死10个7号敌人
[],#如果没有条件,则[]
#该任务完成后是否可重复接取,0不可重复,1可重复
0
]
Tan_task_list[2] = [
"任务2",
"要求队长达到10级,杀死史莱姆3只。",
[],
[],
[["l",0,10],["e",1,3]],
0
]
end
大家不一定要按照我的格式写,大家可以自己拓展想象,写程序最重要的是思路,一旦思路成型,实现代码其实是很简单的事情。
好了,设定完成,让我喘口气,呼,写教程真累,早知道我直接上传自己写的任务系统一了百了……(叫你装比)
接下来是实现,任务系统包含任务的接取、完成,其实这只是表面的,暗地里还有任务是否可以接取、任务是否可以完成,我们来探讨下这些内容怎么写。
首先,这些东西应该放在哪呢?像任务系统,在VA这个系统里,我认为应该放到人物队伍这个类(即class Game_Party或者也叫$game_party),很简单,任务是一个队伍的任务,不是1个人的,不是敌人的,他和队伍金钱这个概念一样,属于队伍,也需要存放在队伍里,通过队伍这个类,来存放哪些任务完成了,哪些任务接取了(通俗点讲,我把这个称为任务状态,任务状态分为未接取、已接取或进行中、可交付、已完成,归根结底,就3种状态:未接取,接取了没交付,已完成),我用0、1、2这3个数字分别代替3种状态,于是,我们可以在class Game_Party下面新增1个字段,这个字段就是专门记录所有任务的状态的,这个字段在$game_party初始化时统一设为0。
代码如下:
class Game_Party < Game_Unit attr_reader :tan_task_state #任务状态数组 #-------------------------------------------------------------------------- # ● 初始化对象(alias重写) #-------------------------------------------------------------------------- alias tan_task_game_party_init initialize def initialize tan_task_game_party_init @tan_task_state = [0] * Tan_task::Tan_task_list.size end end
class Game_Party < Game_Unit
attr_reader :tan_task_state #任务状态数组
#--------------------------------------------------------------------------
# ● 初始化对象(alias重写)
#--------------------------------------------------------------------------
alias tan_task_game_party_init initialize
def initialize
tan_task_game_party_init
@tan_task_state = [0] * Tan_task::Tan_task_list.size
end
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,表示我们还有没有达成条件的地方,不能接取任务,否则,可以接取任务
这部分代码如下:
#-------------------------------------------------------------------------- # ● 判定任务是否可接取 #-------------------------------------------------------------------------- def can_accept_the_tan_task?(id) return false if @tan_task_state[id] != 0 return true if Tan_task::Tan_task_list[id][3].size == 0 re = 0 Tan_task::Tan_task_list[id][3].each {|q| case q[0] when "l"#等级条件 re += 1 if leader.level <= q[2].to_i when "i"#持有物品 re += 1 if item_number($data_items[q[1].to_i]) <= q[2].to_i when "g"#金钱 re += 1 if gold <= q[2].to_i when "q"#前置任务 re += 1 if @tan_task_state[q[2].to_i] != 2 when "s"#开关状态 re += 1 if $game_switches[q[1].to_i] != q[2] when "v"#变量值是否等于指定值 re += 1 if $game_variables[q[1].to_i].to_s != q[2].to_s end } return false if re != 0 return true end
#--------------------------------------------------------------------------
# ● 判定任务是否可接取
#--------------------------------------------------------------------------
def can_accept_the_tan_task?(id)
return false if @tan_task_state[id] != 0
return true if Tan_task::Tan_task_list[id][3].size == 0
re = 0
Tan_task::Tan_task_list[id][3].each {|q|
case q[0]
when "l"#等级条件
re += 1 if leader.level <= q[2].to_i
when "i"#持有物品
re += 1 if item_number($data_items[q[1].to_i]) <= q[2].to_i
when "g"#金钱
re += 1 if gold <= q[2].to_i
when "q"#前置任务
re += 1 if @tan_task_state[q[2].to_i] != 2
when "s"#开关状态
re += 1 if $game_switches[q[1].to_i] != q[2]
when "v"#变量值是否等于指定值
re += 1 if $game_variables[q[1].to_i].to_s != q[2].to_s
end
}
return false if re != 0
return true
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个怪算多次击杀数吧)。
于是,这部分的相关代码如下:
class Game_Party < Game_Unit attr_accessor :tan_task_enemy_kill_number #记录杀敌数 #-------------------------------------------------------------------------- # ● 初始化对象(alias重写),初始化杀怪数 #-------------------------------------------------------------------------- alias tan_task_game_party_init initialize def initialize tan_task_game_party_init @tan_task_enemy_kill_number = {} end #-------------------------------------------------------------------------- # ● 接取任务接任务时,如果有要记录杀怪数量的,杀怪数那个哈希表就添加一个"qid_eid"=>[eid,0] #-------------------------------------------------------------------------- def accept_the_tan_task(id) Tan_task::Tan_task_list[id][4].each {|q| case q[0] when "e"#杀敌数 t = id.to_s + "_" + q[1].to_s @tan_task_enemy_kill_number[t] = [q[1].to_i,0] end } end #-------------------------------------------------------------------------- # ● 完成任务时,如果有要记录杀怪数量的,杀怪数那个哈希表就将对应的"qid_eid"=>[eid,xx]删除掉 #-------------------------------------------------------------------------- def finish_the_tan_task(id) Tan_task::Tan_task_list[id][4].each {|q| case q[0] when "e"#杀敌数 t = id.to_s + "_" + q[1].to_s @tan_task_enemy_kill_number.delete(t) end } end #-------------------------------------------------------------------------- # ● 判定任务是否可交付 #-------------------------------------------------------------------------- def can_finish_the_tan_task?(id) return false if @tan_task_state[id] != 1 return true if Tan_task::Tan_task_list[id][4].size == 0 re = 0 Tan_task::Tan_task_list[id][4].each {|q| case q[0] when "e"#指定杀敌数 t = id.to_s + "_" + q[1].to_s re += 1 if @tan_task_enemy_kill_number[t][1] < q[2].to_i end } return false if re != 0 return true end #记录杀敌数 class Game_Troop < Game_Unit #-------------------------------------------------------------------------- # ● 计算杀敌数,其实就是遍历敌人队列和杀敌数哈希表,将 #-------------------------------------------------------------------------- def tan_task_kill_number dead_members.each {|enemy| $game_party.tan_task_enemy_kill_number.each_value{|knum| knum[1] += 1 if knum[0].to_i == enemy.enemy_id} } end #-------------------------------------------------------------------------- # ● 生成物品数组(alias重写),将计算杀敌数的方法放到这里,在掉落物里计算杀敌数 #-------------------------------------------------------------------------- alias tan_task_game_troop_make_drop_items make_drop_items def make_drop_items tan_task_kill_number return tan_task_game_troop_make_drop_items end end
class Game_Party < Game_Unit
attr_accessor :tan_task_enemy_kill_number #记录杀敌数
#--------------------------------------------------------------------------
# ● 初始化对象(alias重写),初始化杀怪数
#--------------------------------------------------------------------------
alias tan_task_game_party_init initialize
def initialize
tan_task_game_party_init
@tan_task_enemy_kill_number = {}
end
#--------------------------------------------------------------------------
# ● 接取任务接任务时,如果有要记录杀怪数量的,杀怪数那个哈希表就添加一个"qid_eid"=>[eid,0]
#--------------------------------------------------------------------------
def accept_the_tan_task(id)
Tan_task::Tan_task_list[id][4].each {|q|
case q[0]
when "e"#杀敌数
t = id.to_s + "_" + q[1].to_s
@tan_task_enemy_kill_number[t] = [q[1].to_i,0]
end
}
end
#--------------------------------------------------------------------------
# ● 完成任务时,如果有要记录杀怪数量的,杀怪数那个哈希表就将对应的"qid_eid"=>[eid,xx]删除掉
#--------------------------------------------------------------------------
def finish_the_tan_task(id)
Tan_task::Tan_task_list[id][4].each {|q|
case q[0]
when "e"#杀敌数
t = id.to_s + "_" + q[1].to_s
@tan_task_enemy_kill_number.delete(t)
end
}
end
#--------------------------------------------------------------------------
# ● 判定任务是否可交付
#--------------------------------------------------------------------------
def can_finish_the_tan_task?(id)
return false if @tan_task_state[id] != 1
return true if Tan_task::Tan_task_list[id][4].size == 0
re = 0
Tan_task::Tan_task_list[id][4].each {|q|
case q[0]
when "e"#指定杀敌数
t = id.to_s + "_" + q[1].to_s
re += 1 if @tan_task_enemy_kill_number[t][1] < q[2].to_i
end
}
return false if re != 0
return true
end
#记录杀敌数
class Game_Troop < Game_Unit
#--------------------------------------------------------------------------
# ● 计算杀敌数,其实就是遍历敌人队列和杀敌数哈希表,将
#--------------------------------------------------------------------------
def tan_task_kill_number
dead_members.each {|enemy|
$game_party.tan_task_enemy_kill_number.each_value{|knum| knum[1] += 1 if knum[0].to_i == enemy.enemy_id}
}
end
#--------------------------------------------------------------------------
# ● 生成物品数组(alias重写),将计算杀敌数的方法放到这里,在掉落物里计算杀敌数
#--------------------------------------------------------------------------
alias tan_task_game_troop_make_drop_items make_drop_items
def make_drop_items
tan_task_kill_number
return tan_task_game_troop_make_drop_items
end
end
好了,任务系统的核心基本已经设定完毕,剩下的就是界面的制作,界面的实现本帖没有(你这不是坑爹吗?),论坛里关于界面的制作其实很多,所以我不多说。
本贴子主要教大家实现任务系统的思路、设定、核心,至于界面,大家可以自由发挥,欢迎大家一起探讨其他系统的实现(战斗系统、宠物系统、技能树系统、光环等等等等)。
最后,放上成品:
VA任务系统.rar
(1.43 MB, 下载次数: 1279, 售价: 10 星屑)
|
评分
-
查看全部评分
|