天堂2单机论坛

 找回密码
 立即注册
查看: 5735|回复: 10

[l2jtw]关于任务的编写提示

[复制链接]
  • TA的每日心情
    郁闷
    2022-5-30 11:17
  • 签到天数: 20 天

    [LV.4]偶尔看看III

    277

    主题

    387

    帖子

    7万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    73795
    发表于 2020-10-6 17:23:22 | 显示全部楼层 |阅读模式
    一.创建任务目录
    在...\data\jscript\quests上创建一个目录
    二.把任务目录加入到目录列表
    任务列表文件在...\data\jscript\quests下的__init__.py
    用记事本打开可以看到
    复制代码

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



    格式:
    复制代码

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


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

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



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

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


    复制代码

    1. 1.#Items
    2. 2.HEAD_OF_SHADITH_ID = 7235
    3. 3.TOTEM_OF_VALOR_ID = 7219



    4. #NPCs
    5. KADAN_ZU_KETRA_ID = 8370
    复制代码


    尽量使用这种方法,不过,如果你的技术高超的话可以用其他语句/方法.
    所以尽量使你的PY文件更容易读会更好些.
    =帮助任务判别的方法
    复制代码
    1. 1.def getCount(st) : // st是指QuestState
    2. 2.return st.getQuestItemsCount(FANGS_ITEM_ID)
    复制代码





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


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





    这个功能是用来结束任务,用来回收任务道具和给予道具
    =====
    复制代码
    1. 1.def check(st) :
    2. 2.if getCount(st) >= 4 : // 任务道具4个以上
    3. 3. completed(st)
    4. 4.return
    复制代码




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





    任务是由 python class 所构成的,它是由 java class 延伸出来的。
    在这裡我们用了一个任务触发的方法 (onEvent)。
    在 def __init__(self,id,name,descr) 裡的定义:
    代码:
    1. self // 关於任务
    2. id // 任务在客户端的编号代码
    3. name // 任务名称,必须与L2jserver的任务名称相同
    4. descr // 任务描述,会在客户端显示出来
    复制代码



    而 def onEvent (self,event,st) 裡的定义:
    代码:
    1. self // 关於目前这个任务
    2. event // 一个字串的定义,可以被java?#123;式触发
    3. st // QuestState的状态,可以提供玩家目前任务进行的资讯
    复制代码



    5. 说明 onEvent 的方法
    代码:
    1. id = st.getState()
    复制代码



    我们将玩家目前任务进行的状态数值宣告,它会被存入 id 。
    接著我们检查任务的状态,并且使任务状态转移到新的状态。
    代码:
    1. if id == CREATED : st.setState(STARTED)
    复制代码



    如果玩家触发了任务,状态为 (state CREATED) ,那麼任务状态
    将转移至 (state STARTED) 。
    代码:
    1. elif id == COMPLETED: pass
    复制代码



    如果玩家已经完成任务,那我们在这就不处理它。
    代码:
    1. elif id == STARTED : check(st)
    复制代码



    如果玩家仍然在任务进行中,那麼我们呼叫
    我们之前所宣告的功能,来检查任务道具数量。
    代码:
    1. def check(st) :
    2. if getCount(st) >= 4 : // 任务道具4个以上
    3. completed(st)
    4. return
    复制代码



    如果玩家身上的道具数量足够的话,那任务状态
    就直接进入结束状态 (state COMPLETED) 。
    在这个范例中,我们并没有检查 (event) 的状态,因为
    所有的 (Event) 的发生状态都是经由与 NPC 对话所发生的
    ,所以 (onEvent) 被呼叫的话,一定是玩家与 NPC 对话。
    6. 宣告任务状态
    代码:
    1. QUEST = Quest(201,"Tutorial", "Tutorial quest")
    2. CREATED = State('Start', QUEST)
    3. STARTED = State('Started', QUEST)
    4. COMPLETED = State('Completed', QUEST)
    复制代码



    每一个状态都连结一个对话 (html) ,所以当状态发生时,
    都会显示一个对话:
    状态 (CREATED) 发生时,出现 start.htm
    状态 (STARTED) 发生时,出现 started.htm
    状态 (COMPLETED) 发生时,出现 Completed.htm
    代码:
    1. QUEST.setInitialState(CREATED)
    2. QUEST.addStartNpc(7056) // 任务触发 NPC
    复制代码



    现在我们要为这个任务宣告触发状态及任务触发 NPC 。
    代码:
    1. <a action="bypass -h npc_%objectId%_Quest">任务</a>
    复制代码



    在触发 NPC 的 html 裡要有这段连结来触发任务。
    7. 宣告任务道具掉落
    代码:
    1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
    复制代码



    设定玩家在 (STARTED) 状态时,任务道具掉落、机率及猎杀的怪物。
    8. 任务编写完成
    代码:
    复制代码
    1. 1.import sys
    2. 2.from net.sf.l2j.gameserver.model.quest import State
    3. 3.from net.sf.l2j.gameserver.model.quest import QuestState
    4. 4.from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
    5. 5.
    6. 6.
    7. 7.KELTIR_NPC_ID = 12082
    8. 8.FANGS_ITEM_ID = 1859
    9. 9.DROP_RATE = 500000
    10. 10.WORLD_MAP_ITEM_ID = 1665
    11. 11.
    12. 12.
    13. 13.def getCount(st) :
    14. 14.return st.getQuestItemsCount(FANGS_ITEM_ID)
    15. 15.
    16. 16.def completed(st) :
    17. 17.st.setState(COMPLETED)
    18. 18.st.clearQuestDrops()
    19. 19.st.takeItems(FANGS_ITEM_ID,-1)
    20. 20.st.giveItems(WORLD_MAP_ITEM_ID,1)
    21. 21.st.exitQuest(False)
    22. 22.return
    23. 23.
    24. 24.def check(st) :
    25. 25.if getCount(st) >= 4 :
    26. 26. completed(st)
    27. 27.return
    28. 28.
    29. 29.class Quest (JQuest):
    30. 30.
    31. 31.def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    32. 32.
    33. 33.def onEvent (self,event,st):
    34. 34. id = st.getState()
    35. 35. if id == CREATED : st.setState(STARTED)
    36. 36. elif id == COMPLETED: pass
    37. 37. elif id == STARTED : check(st)
    38. 38. return
    39. 39.
    40. 40.QUEST = Quest(201,"Tutorial", "Tutorial quest")
    41. 41.CREATED = State('Start', QUEST)
    42. 42.STARTED = State('Started', QUEST)
    43. 43.COMPLETED = State('Completed', QUEST)
    44. 44.
    45. 45.QUEST.setInitialState(CREATED)
    46. 46.QUEST.addStartNpc(7056)
    47. 47.
    48. 48.STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
    49. 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 功能
    代码:
    1. STARTED.addKillId(KELTIR_NPC_ID)
    复制代码



    我们再加入在 STARTED 状态之下,猎杀任务怪物后,呼叫 onKill 功能。
    代码:
    1. class Quest (JQuest):
    2. ...
    3. def onKill (self,npcId,st):
    4. if npcId == KELTIR_NPC_ID:
    5. n = getCount(st)
    6. if n == 0:
    7. return "Chat0.htm"
    8. elif n == 1:
    9. return "Chat1.htm"
    10. elif n >= 4:
    11. return "Chat4.htm"
    12. return "Collected "+str(n)+" of 4 fangs"
    13. return
    复制代码



    onKill 的定义:
    代码:
    1. self // 关於任务
    2. npcID // 被猎杀的怪物 ID
    3. st // 玩家目前的任务状态 (QuestState)
    复制代码



    代码:
    1. n = getCount(st)
    复制代码



    检查玩家身上的任务道具。
    代码:
    1. if n == 0:
    2. return "Chat0.htm"
    复制代码



    如果玩家身上没有任务道具,则会显示 Chat0.htm 。
    代码:
    1. elif n == 1:
    2. return "Chat1.htm"
    复制代码



    如果玩家身上只有1个任务道具或是不足4个时,则显示 Chat1.htm 。
    代码:
    1. elif n >= 4:
    2. return "Chat4.htm"
    复制代码



    如果玩家身上已经有4个任务道具时,则显示 Chat4.htm 。
    经由 onEvent、onTalk 和 onKill 而 return 的字串值,结尾是 .htm 时
    L2j server 就会将它显示在客户端,让玩家知道。
    在此范例中:
    代码:
    1. Chat0.htm 的内容可能是"快去猎杀怪物吧......等等"
    2. Chat1.htm 的内容可能是"你只有一个任务道具.......等等"
    3. Chat4.htm 的内容可能是"任务完成,回去找 NPC 吧.....等等"
    复制代码



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



    代码:
    1. return "<html><body>任务完成,回去找NPC吧</body></html>"
    复制代码



    以上两个都会被 L2j server 所接受。
    如果 return 的字串值不是以上两种,而我们想用系统来让客户端显示。
    代码:
    1. return "Collected "+str(n)+" of 4 fangs"
    复制代码



    这样客户端就以系统通知玩家"收集了N个任务道具\"。
    不过我们现在这个范例的 onKill 功能,有些问题,它会一直重复显示
    Chat0.htm、Chat1.htm、Chat4.htm,我们现在只想要它出现一
    次就可以,如何达成这个目的呢?
    代码:
    1. def onKill (self,npcId,st):
    2. if npcId == KELTIR_NPC_ID:
    3. n = getCount(st)
    4. if n == 0:
    5. if st.get('chat0') == None :
    6. st.set("chat0", "true")
    7. return "Chat0.htm"
    8. elif n == 1:
    9. if st.get('chat1') == None :
    10. st.set("chat1", "true")
    11. return "Chat1.htm"
    12. elif n >= 4:
    13. return "Chat4.htm"
    14. return "Collected "+str(n)+" of 4 fangs"
    15. return
    复制代码



    我们可以用变数来达成,每一个任务都会储存字串值在资料库裡当作变数,
    在这个范例我们使用 set 、 get 和 unset 来设定变数。
    代码:
    1. if n == 0:
    2. if st.get('chat0') == None :
    复制代码



    当玩家没有任务道具时(n==0),我们得到 (get) "chat0" 这个变数,当
    第一次 onKill 被呼叫时,系统并没有这个变数,所以系统返回 None 值,
    显示 Chat0.htm 。
    代码:
    1. if n == 0:
    2. if st.get('chat0') == None :
    3. st.set("chat0", "true") // 系统取得变数
    4. return "Chat0.htm"
    复制代码



    当我们猎杀任务怪物(未掉落任务道具)时,系统会经由 st.set("chat0", "true")
    返回 true ,这个范例中系统返回 None 才会显示 Chat0.htm ,所以现在
    系统不会显示 Chat0.htm。
    代码:
    1. return "Collected "+str(n)+" of 4 fangs"
    复制代码



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





    以上就是我们写出来的任务.
    以上文章是引用了L2JTW的root写"Jython Quest 任務編寫:在此感谢ROOT
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2022-12-12 17:58
  • 签到天数: 4 天

    [LV.2]偶尔看看I

    4

    主题

    94

    帖子

    208

    积分

    中级会员

    Rank: 3Rank: 3

    积分
    208
    发表于 2020-11-7 15:13:19 | 显示全部楼层
    感谢分享
    回复

    使用道具 举报

  • TA的每日心情

    2024-11-8 14:11
  • 签到天数: 72 天

    [LV.6]常住居民II

    2

    主题

    330

    帖子

    433

    积分

    中级会员

    Rank: 3Rank: 3

    积分
    433
    发表于 2020-11-12 16:31:30 | 显示全部楼层
    好东西啊  值得学习一下哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈!!!!
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2021-6-7 07:27
  • 签到天数: 52 天

    [LV.5]常住居民I

    4

    主题

    145

    帖子

    336

    积分

    中级会员

    Rank: 3Rank: 3

    积分
    336
    发表于 2021-2-23 15:50:04 | 显示全部楼层
    感谢分享,对我来说有点难度了
    回复

    使用道具 举报

  • TA的每日心情
    慵懒
    2025-3-14 23:33
  • 签到天数: 355 天

    [LV.8]以坛为家I

    5

    主题

    445

    帖子

    2158

    积分

    金牌会员

    Rank: 6Rank: 6

    积分
    2158
    发表于 2021-10-24 18:49:13 | 显示全部楼层
    现在都直接上JAVA
    回复

    使用道具 举报

  • TA的每日心情
    擦汗
    2023-7-29 00:03
  • 签到天数: 864 天

    [LV.10]以坛为家III

    4

    主题

    5131

    帖子

    1万

    积分

    VIP会员

    Rank: 8Rank: 8

    积分
    14777
    发表于 2021-10-25 05:44:53 | 显示全部楼层
    感谢楼主分享
    回复

    使用道具 举报

  • TA的每日心情
    擦汗
    2022-4-26 17:05
  • 签到天数: 2 天

    [LV.1]初来乍到

    0

    主题

    32

    帖子

    50

    积分

    正式会员

    Rank: 2

    积分
    50
    发表于 2022-5-24 11:20:14 | 显示全部楼层
    有点难度了
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2025-2-14 21:41
  • 签到天数: 189 天

    [LV.7]常住居民III

    14

    主题

    257

    帖子

    2018

    积分

    金牌会员

    Rank: 6Rank: 6

    积分
    2018
    发表于 2022-8-19 12:30:28 | 显示全部楼层
    GANXIFENX
    回复

    使用道具 举报

  • TA的每日心情
    郁闷
    2024-11-4 17:09
  • 签到天数: 38 天

    [LV.5]常住居民I

    0

    主题

    59

    帖子

    146

    积分

    正式会员

    Rank: 2

    积分
    146
    发表于 2022-8-24 00:14:54 | 显示全部楼层
    有點難度
    回复

    使用道具 举报

  • TA的每日心情
    擦汗
    2023-7-29 00:03
  • 签到天数: 864 天

    [LV.10]以坛为家III

    4

    主题

    5131

    帖子

    1万

    积分

    VIP会员

    Rank: 8Rank: 8

    积分
    14777
    发表于 2022-8-24 05:52:30 | 显示全部楼层
    感谢楼主分享
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|Archiver|手机版|监狱|天堂2单机论坛 ( 粤ICP备20030366号 )

    GMT+8, 2025-5-1 03:49 , Processed in 0.061296 second(s), 21 queries .

    Powered by Discuz! X3.4

    © 2001-2023 Discuz! Team.

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