2015年4月—2024年4月,论坛已建立9周年,欢迎加入QQ群讨论:419848937

关于任务的编写提示

主要是游戏中一些经典任务、游戏资料的科普.
回复
头像
hagcse
Mr.GL
Mr.GL
帖子: 151
注册时间: 2018-02-25 15:50

关于任务的编写提示

帖子 hagcse » 2018-03-10 15:38

一.创建任务目录
在...\data\jscript\quests上创建一个目录
二.把任务目录加入到目录列表
任务列表文件在...\data\jscript\quests下的__init__.py
用记事本打开可以看到

复制代码
1.'1_LettersOfLove1',
2.'2_WhatWomenWant1',
3.'3_ReleaseDarkelfElder1',
4.'4_LongLiveLordOfFlame',
5.'5_MinersFavor',
6.'6_StepIntoTheFuture',
7.'7_ATripBegins',
8.'8_AnAdventureBegins',
9.'9_IntoTheCityOfHumans',
10.'10_IntoTheWorld',
11.'19_GoToThePastureland',
12.'32_AnObviousLie',
13.'33_MakeAPairOfDressShoes',
14.'34_InSearchOfClothes',
15.'35_FindGlitteringJewelry',
16.'36_MakeASewingKit',
17.'37_PleaseMakeMeFormalWear',
18.'39_RedEyedInvaders',
19.'42_HelpTheUncle',
20.'43_HelpTheSister',
21.'44_HelpTheSon',
22.'45_ToTalkingIsland',
23.'46_OnceMoreInTheArmsOfTheMotherTree',
24.'47_IntoTheDarkForest',
25.'48_ToTheImmortalPlateau',
26.'49_TheRoadHome',
27.'101_SwordOfSolidarityQuest',
28.'102_FungusFever',
29.'103_SpiritOfCraftsman',
30.'104_SpiritOfMirror',
31.'105_SkirmishWithOrcs',
32.'106_ForgottenTruth',





格式:
复制代码
1.'目录名',
2.添加在__all__ = [
3.]
4.print ""
5.print "importing quests ..."
6.from data.jscript.quests import *
7.
8.print"... done"



之间
.
任务列表部分完成.
=三.任务__init__.py编写
__init__.py文件头数据
利用这些语句执行任务的JAVAclass

复制代码
1.print "importing quests: 607: Prove your courage!"
2.import sys
3.from net.sf.l2j.gameserver.model.quest import State
4.from net.sf.l2j.gameserver.model.quest import QuestState
5.from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest





'Class QuestJython'是任务信息
'Class State'任务中每一阶段的状态
'QuestState'相关玩家进行任务的状态/信息
基本上都要执行这些语句
==================================
任务相关NPC/道具等等

例如

复制代码
1.KELTIR_NPC_ID = 12082 // 任務NPC
2.FANGS_ITEM_ID = 1859 // 任務道具
3.DROP_RATE = 500000 // 任務道具掉落率
4.WORLD_MAP_ITEM_ID = 1665 // 任務獎勵 ,



复制代码
1.#Items
2.HEAD_OF_SHADITH_ID = 7235
3.TOTEM_OF_VALOR_ID = 7219



#NPCs
KADAN_ZU_KETRA_ID = 8370
尽量使用这种方法,不过,如果你的技术高超的话可以用其他语句/方法.
所以尽量使你的PY文件更容易读会更好些.
=帮助任务判别的方法

复制代码
1.def getCount(st) : // st是指QuestState
2.return st.getQuestItemsCount(FANGS_ITEM_ID)




注意例如FANGS_ITEM_ID是变量来的,必须在上面定义
例如FANGS_ITEM_ID = 15205
就是任务道具为15205
=上面是任务系统在玩家在执行任务中,检查/增加/减少人一些功能语句




复制代码
1.def completed(st) : // st是指QuestState
2.st.setState(COMPLETED) // ?#93;任务完成状态
3.st.clearQuestDrops()
4.st.takeItems(FANGS_ITEM_ID,-1) // 将任务道具回收
5.st.giveItems(WORLD_MAP_ITEM_ID,1) // 给予玩家任务奖励
6.st.exitQuest(False) // 此任务不能重复执行
7.return




这个功能是用来结束任务,用来回收任务道具和给予道具
=====

复制代码
1.def check(st) :
2.if getCount(st) >= 4 : // 任务道具4个以上
3. completed(st)
4.return



这段代码是用来确认玩家身上的道具数量,从而使任务结束.
=================================
四.任务本身
代码:
复制代码
1.class Quest (JQuest):
2.
3.def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
4.
5.def onEvent (self,event,st):
6. id = st.getState()
7. if id == CREATED : st.setState(STARTED)
8. elif id == COMPLETED: pass
9. elif id == STARTED : check(st)
10. return





任务是由 python class 所构成的,它是由 java class 延伸出来的。
在这裡我们用了一个任务触发的方法 (onEvent)。

在 def __init__(self,id,name,descr) 裡的定义:

代码:

self // 关於任务
id // 任务在客户端的编号代码
name // 任务名称,必须与L2jserver的任务名称相同
descr // 任务描述,会在客户端显示出来



而 def onEvent (self,event,st) 裡的定义:

代码:

self // 关於目前这个任务
event // 一个字串的定义,可以被java?#123;式触发
st // QuestState的状态,可以提供玩家目前任务进行的资讯



5. 说明 onEvent 的方法

代码:

id = st.getState()



我们将玩家目前任务进行的状态数值宣告,它会被存入 id 。

接著我们检查任务的状态,并且使任务状态转移到新的状态。

代码:

if id == CREATED : st.setState(STARTED)



如果玩家触发了任务,状态为 (state CREATED) ,那麼任务状态
将转移至 (state STARTED) 。

代码:

elif id == COMPLETED: pass



如果玩家已经完成任务,那我们在这就不处理它。

代码:

elif id == STARTED : check(st)



如果玩家仍然在任务进行中,那麼我们呼叫
我们之前所宣告的功能,来检查任务道具数量。

代码:

def check(st) :
if getCount(st) >= 4 : // 任务道具4个以上
completed(st)
return



如果玩家身上的道具数量足够的话,那任务状态
就直接进入结束状态 (state COMPLETED) 。

在这个范例中,我们并没有检查 (event) 的状态,因为
所有的 (Event) 的发生状态都是经由与 NPC 对话所发生的
,所以 (onEvent) 被呼叫的话,一定是玩家与 NPC 对话。

6. 宣告任务状态

代码:

QUEST = Quest(201,"Tutorial", "Tutorial quest")
CREATED = State('Start', QUEST)
STARTED = State('Started', QUEST)
COMPLETED = State('Completed', QUEST)



每一个状态都连结一个对话 (html) ,所以当状态发生时,
都会显示一个对话:
状态 (CREATED) 发生时,出现 start.htm
状态 (STARTED) 发生时,出现 started.htm
状态 (COMPLETED) 发生时,出现 Completed.htm

代码:

QUEST.setInitialState(CREATED)
QUEST.addStartNpc(7056) // 任务触发 NPC



现在我们要为这个任务宣告触发状态及任务触发 NPC 。

代码:

<a action="bypass -h npc_%objectId%_Quest">任务</a>


在触发 NPC 的 html 裡要有这段连结来触发任务。

7. 宣告任务道具掉落

代码:

STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)



设定玩家在 (STARTED) 状态时,任务道具掉落、机率及猎杀的怪物。

8. 任务编写完成

代码:
复制代码
1.import sys
2.from net.sf.l2j.gameserver.model.quest import State
3.from net.sf.l2j.gameserver.model.quest import QuestState
4.from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
5.
6.
7.KELTIR_NPC_ID = 12082
8.FANGS_ITEM_ID = 1859
9.DROP_RATE = 500000
10.WORLD_MAP_ITEM_ID = 1665
11.
12.
13.def getCount(st) :
14.return st.getQuestItemsCount(FANGS_ITEM_ID)
15.
16.def completed(st) :
17.st.setState(COMPLETED)
18.st.clearQuestDrops()
19.st.takeItems(FANGS_ITEM_ID,-1)
20.st.giveItems(WORLD_MAP_ITEM_ID,1)
21.st.exitQuest(False)
22.return
23.
24.def check(st) :
25.if getCount(st) >= 4 :
26. completed(st)
27.return
28.
29.class Quest (JQuest):
30.
31.def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
32.
33.def onEvent (self,event,st):
34. id = st.getState()
35. if id == CREATED : st.setState(STARTED)
36. elif id == COMPLETED: pass
37. elif id == STARTED : check(st)
38. return
39.
40.QUEST = Quest(201,"Tutorial", "Tutorial quest")
41.CREATED = State('Start', QUEST)
42.STARTED = State('Started', QUEST)
43.COMPLETED = State('Completed', QUEST)
44.
45.QUEST.setInitialState(CREATED)
46.QUEST.addStartNpc(7056)
47.
48.STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
49.




这个任务已经完成,并可以在伺服器上执行了。
我们来说明一下这个任务的流程:

I. 玩家向 NPC (ID 7056) 对话并触发任务,此时任务的状态
为 CREATED ,同时显示对话 Start.htm 。

II. 而 Start.htm 会呼叫 (onEvent) 这个功能,使得任务的状态
转变为 STARTED ,同时显示对话 Started.htm 。

III. 在 STARTED 的状态下,会使任务怪物掉落任务道具。
在这个状态下,玩家也许会回去找 NPC 对话,此时 (onEvent)
功能会被再呼叫,在这个状态下, check(st) 功能会检查玩家
身上是否有足够的任务道具,如果没有足够的任务道具,会再
次出现 Started.htm 。如果玩家有足够的道具, check(st) 会
将任务状态转换至 COMPLETED 的状态,收回玩家身上的任务
道具,并给予玩家奖励,而同时会出现对话 Completed.htm 。

以上这个任务只用了 onEvent 这个功能,其实还有另外两个功能
尚未使用到, onTalk 和 onKill ,这两个功能类似 onEvent,
使用时机不同而已。

在以上的范例中,我们并没有宣告 onTalk or onKill 这两种功能,
所以整个任务的流程都是使用 onEvent 这个功能。
onEvent 功能和这两个功能不同的地方是, onTalk or onKill 是针对
在任务中玩家与NPC对话或是猎杀任务怪物死亡后呼叫的功能。

9. 加入 onKill 功能

代码:

STARTED.addKillId(KELTIR_NPC_ID)


我们再加入在 STARTED 状态之下,猎杀任务怪物后,呼叫 onKill 功能。

代码:

class Quest (JQuest):
...
def onKill (self,npcId,st):
if npcId == KELTIR_NPC_ID:
n = getCount(st)
if n == 0:
return "Chat0.htm"
elif n == 1:
return "Chat1.htm"
elif n >= 4:
return "Chat4.htm"
return "Collected "+str(n)+" of 4 fangs"
return



onKill 的定义:

代码:

self // 关於任务
npcID // 被猎杀的怪物 ID
st // 玩家目前的任务状态 (QuestState)



代码:

n = getCount(st)



检查玩家身上的任务道具。

代码:

if n == 0:
return "Chat0.htm"


如果玩家身上没有任务道具,则会显示 Chat0.htm 。

代码:

elif n == 1:
return "Chat1.htm"


如果玩家身上只有1个任务道具或是不足4个时,则显示 Chat1.htm 。

代码:

elif n >= 4:
return "Chat4.htm"


如果玩家身上已经有4个任务道具时,则显示 Chat4.htm 。

经由 onEvent、onTalk 和 onKill 而 return 的字串值,结尾是 .htm 时
L2j server 就会将它显示在客户端,让玩家知道。

在此范例中:

代码:

Chat0.htm 的内容可能是\"快去猎杀怪物吧......等等"
Chat1.htm 的内容可能是\"你只有一个任务道具.......等等"
Chat4.htm 的内容可能是\"任务完成,回去找 NPC 吧.....等等"



当然经由 onEvent、onTalk 和 onKill 而 return 的字串值不一定要是
.htm 结尾,也可以开头用 <html> 的语法来达成同样的目的。

代码:

return "Chat4.htm"



代码:

return "<html><body>任务完成,回去找NPC吧</body></html>"



以上两个都会被 L2j server 所接受。

如果 return 的字串值不是以上两种,而我们想用系统来让客户端显示。

代码:

return "Collected "+str(n)+" of 4 fangs"



这样客户端就以系统通知玩家"收集了N个任务道具\"。

不过我们现在这个范例的 onKill 功能,有些问题,它会一直重复显示
Chat0.htm、Chat1.htm、Chat4.htm,我们现在只想要它出现一
次就可以,如何达成这个目的呢?

代码:

def onKill (self,npcId,st):
if npcId == KELTIR_NPC_ID:
n = getCount(st)
if n == 0:
if st.get('chat0') == None :
st.set("chat0", "true")
return "Chat0.htm"
elif n == 1:
if st.get('chat1') == None :
st.set("chat1", "true")
return "Chat1.htm"
elif n >= 4:
return "Chat4.htm"
return "Collected "+str(n)+" of 4 fangs"
return



我们可以用变数来达成,每一个任务都会储存字串值在资料库裡当作变数,
在这个范例我们使用 set 、 get 和 unset 来设定变数。

代码:

if n == 0:
if st.get('chat0') == None :



当玩家没有任务道具时(n==0),我们得到 (get) "chat0" 这个变数,当
第一次 onKill 被呼叫时,系统并没有这个变数,所以系统返回 None 值,
显示 Chat0.htm 。

代码:

if n == 0:
if st.get('chat0') == None :
st.set("chat0", "true") // 系统取得变数
return "Chat0.htm"



当我们猎杀任务怪物(未掉落任务道具)时,系统会经由 st.set("chat0", "true")
返回 true ,这个范例中系统返回 None 才会显示 Chat0.htm ,所以现在
系统不会显示 Chat0.htm。

代码:

return "Collected "+str(n)+" of 4 fangs"



因为我们还有经由系统通知玩家,所以会显示"收集了N个任务道具\"。

10. 任务全貌

代码:
复制代码
1.import sys
2.from net.sf.l2j.gameserver.model.quest import State
3.from net.sf.l2j.gameserver.model.quest import QuestState
4.from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
5.
6.
7.KELTIR_NPC_ID = 12082
8.FANGS_ITEM_ID = 1859
9.DROP_RATE = 500000
10.
11.WORLD_MAP_ITEM_ID = 1665
12.
13.
14.def getCount(st) :
15.return st.getQuestItemsCount(FANGS_ITEM_ID)
16.
17.def completed(st) :
18.st.setState(COMPLETED)
19.st.clearQuestDrops()
20.st.takeItems(FANGS_ITEM_ID,-1)
21.st.giveItems(WORLD_MAP_ITEM_ID,1)
22.st.exitQuest(False)
23.return
24.
25.def check(st) :
26.if getCount(st) >= 4 :
27. completed(st)
28.return
29.
30.class Quest (JQuest):
31.
32.def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
33.
34.def onEvent (self,event,st):
35. id = st.getState()
36. if id == CREATED : st.setState(STARTED)
37. elif id == COMPLETED: pass
38. elif id == STARTED : check(st)
39. return
40.
41.def onKill (self,npcId,st):
42. if npcId == KELTIR_NPC_ID:
43. n = getCount(st)
44. if n == 0:
45. if st.get('chat0') == None :
46. st.set("chat0", "true")
47. return "Chat0.htm"
48. elif n == 1:
49. if st.get('chat1') == None :
50. st.set("chat1", "true")
51. return "Chat1.htm"
52. elif n >= 4:
53. return "Chat4.htm"
54. return "Collect "+str(n)+" of 4 fangs"
55. return
56.
57.QUEST = Quest(201, "Tutorial", "Tutorial quest")
58.CREATED = State('Start', QUEST)
59.STARTED = State('Started', QUEST)
60.COMPLETED = State('Completed', QUEST)
61.
62.QUEST.setInitialState(CREATED)
63.QUEST.addStartNpc(7056)
64.QUEST.addStartNpc(7012)
65.QUEST.addStartNpc(7009)
66.QUEST.addStartNpc(7011)
67.
68.STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
69.STARTED.addKillId(KELTIR_NPC_ID)
70.STARTED.addTalkId(7056)
71.STARTED.addTalkId(7012)
72.STARTED.addTalkId(7009)
73.STARTED.addTalkId(7011)





以上就是我们写出来的任务.

以上文章是引用了L2JW的root写"Jython Quest 任務編寫:在此感谢ROOT
图片

回复