游戏开发论坛

 找回密码
 立即注册
搜索
查看: 2824|回复: 5

转: MMORPG任务系统设计

[复制链接]

4

主题

16

帖子

16

积分

新手上路

Rank: 1

积分
16
发表于 2006-7-11 12:12:00 | 显示全部楼层 |阅读模式
转自我自己的blog:http://blog.csdn.net/yanonsoftware,希望大家多交流:)

  最近一直在思考MMORPG的任务系统的设计。以下是需要达到的几个设计目标:
1.       任务逻辑与程序逻辑完全脱离;
2.       服务器端程序和客户端程序提供有限的功能之后,可以由脚本程序员完成任务编写;
3.       必须方便任务的更新。
当然,任务系统的具体实现受策划案的影响很大,我这里只是空想的一个一般的实现方案:
<场景编辑>:
场景数据文件和任务相关的主要是NPC和调查触发器(例如调查一个石碑)。当玩家与NPC谈话,或者调查某个物品时,需要开启某个特定的任务。某个对象可以开启哪些任务,以及开启任务的条件需要事先编辑到场景数据文件中。任务条件也可以写入任务脚本文件中。
<服务器端>:
1.       每个角色身上保存(最多)N个任务体(WOW是20个),任务体应该包括任务名称或编号,以及几个任务变量(供任务脚本使用,个数依策划而定,但不可太多);
2.       每个任务存储一个脚本文件,当游戏中特定的事件发生时,首先应该查询场景数据,看是否开启一个新的任务,然后逐个通知现有任务的脚本,每个任务的脚本来执行各自独立的任务逻辑,例如有某个任务脚本文件为Quest_001.script如下:
OnTalkNpc(string npcid)
{
if(npcid == “张三”)
{
     if(GetQuestVar(0) >= 10)//杀够了
     {
       ShowDlg(“你这么快就杀了10只老虎?很厉害!”);
       IncPlayExp(1250);//经验奖励
     }
    else
       ShowDlg(“你好啊!”); //向客户端发送命令,显示对话框
   }
}
OnKillMonster(int monsterID)
{
if(monsterID == 1000123)//是任务指定的怪物
  {
     IncQuestVar(0);//修改任务变量
}
}
3.       因为大部分任务是只能执行一次的,所以服务器还需要记录此角色完成了哪些任务。
<客户端>:
可以查询视野中对象可能开启哪些任务,玩家是否满足条件来给出一些提示,例如头顶放一个叹号;
当玩家与NPC对话或者调查某个物品时,发送通知给服务器;
接收服务器的消息,更新任务显示信息。

以一个典型的任务为例:玩家与张三谈话触发任务,杀十只老虎,回来交任务可以得到1250点经验。

4

主题

16

帖子

16

积分

新手上路

Rank: 1

积分
16
 楼主| 发表于 2006-7-11 12:17:00 | 显示全部楼层

Re:转: MMORPG任务系统设计

有个图没有贴上来,完整版本可以访问我的blog。http://blog.csdn.net/yanonsoftware

9

主题

45

帖子

49

积分

注册会员

Rank: 2

积分
49
发表于 2006-7-12 15:05:00 | 显示全部楼层

有兴趣找我交流

设计和实现过MMORPG任务系统,完成了任务/脚本系统的设计和实现。
QQ596149759,加注明游戏开发

4

主题

16

帖子

16

积分

新手上路

Rank: 1

积分
16
 楼主| 发表于 2006-7-12 16:46:00 | 显示全部楼层

Re: 有兴趣找我交流

ricyangliu: 有兴趣找我交流

设计和实现过MMORPG任务系统,完成了任务/脚本系统的设计和实现。
QQ596149759,加注明游戏开发


有什么经验可以写一下贴出来。我的想法有什么不好的,请指出。:)

0

主题

9

帖子

9

积分

新手上路

Rank: 1

积分
9
发表于 2006-7-13 17:29:00 | 显示全部楼层

Re:转: MMORPG任务系统设计


function  doAction(bTalk,nSelectID,nSelectItemID)       --nSelectID为用户点击按钮的ID,nSelectItemID为用户选择奖励
        local lMissionflag=200; --npc任务标记变量
        TaskObject:setLvL(45);
        TaskObject:setID(lMissionflag);
        local nSelectitem={22,33,435}; --给玩家选择的任务奖励物品(22.33.435这些是对应的任务奖励物品ID)
        bAlreadHave = false;
        --循环获得任务是否有这个任务
        for  i=0,19 do
                if  DestObject:GetUpdataFlag(UNIT_FIELD_TASK        +i*8) != lMissionFalg  then
                        bAlreadHave = true;
                        break;
                end
        end
        if  bAlreadHave  then
                -- 如果是获取物品的任务检查所需要条件(例如需要20件3143的物品)如果是直接对话完成任务的
                lNumsItem = DestObject:GetNumsItem(3143);
                if lNumsItem < 20 then
                        Send(DestObject, ?, 2);
                        if  bTalk then
                                Send("Open Finish Mission Windows",lMissionflag);--打开任务结束对话窗口显示对应任务
                        end
                        return false;
                end

                if  bTalk then
                        Send("Open Finish Mission Windows",lMissionflag);    --打开任务结束对话窗口显示对应任务
                        Send("Enable Over Button");         --将完成任务那个按钮设置为可点击的默认为不可以
                        if nSelectID=0 then        --当用户点击了完成任务按钮
                                --如果任务奖励有要给东西则这边要进行以下判断这边是相应任务奖励处理
                                if  (DestObject:getUpdateFlag(CONTAINER_FIELD_NUM_SLOTS)<3)  then  --背包的空格数不够奖励道具的数量
                                        MessageShow("背包满");
                                end
                                --如果是有选择奖励道具任务的
                                if nSelectItemID >0 then
                                        DestObject:addItem(NewItemObject,nSelectitem[nSelectItemID]);
                                end
                                else
                                        MessageShow(“请选择道具”);
                                end
                                --没有选择的
                                DestObject:addItem(NewItemObject, I_SLOT_DEFALUT);--将对应的奖励放入背包
                                --其他奖励
                                DestObject:addItem(NewItemObject, I_SLOT_DEFALUT);  --将默认的奖励物品放入背包
                                DestObject:setUpdateIntValue(PLAYER_FIELD_COINAGE,+1000);  --增加玩家金钱
                                DestObject:setUpdateIntValue(PLAYER_FIELD_XP,+10000);  --增加玩家经验
                                DestObjecteleteTask(lMissionflag);
                                send(.....) --更新客户端信息
                                CloseWindow(); --关闭窗口
                                return false;
                        end
                        return false;
                end
                Send(SrcObject,?,1);
                retrun true;
        else                       
                -- 做过这个任务了
                if  DestObject:GetHistroyTaskFlag(lMissionflag)  then
                        return  false;                               
                end
                if  DestObject:GetUpdataFlag(PLAYER_FIELD_EXT_LEVEL)<39   then        --当等级超过限制任务不存在(这边假设任务等级为45)
                        return false;
                end
                if DestObject:GetUpdataFlag(PLAYER_FIELD_EXT_LEVEL)<42 then
                        Send(DestObject, !, 2);
                        return false;
                end       

                if  bTalk then
                        Send("Open Open Mission Windows",lMissionflag);--打开任务接受对话窗口显示对应任务
                        if
                        if nSelectID=0 then        --当用户点击了接受任务按钮
                                --这边是接受响应任务相应任务处理
                                --如果接受任务有给东西则要加下面判断
                                if  (DestObject:getUpdateFlag(CONTAINER_FIELD_NUM_SLOTS)<2)  then                --背包如果满
                                        MessageShow("背包满");
                                        return false;
                                end
                                if  DestObject:GetCurrentNumsOfTask()==20  then  --当任务已经20条  
                                        MessageShow("任务已经满");  
                                        return false;
                                end
                                --增加玩家任务
                                DestObject:CreateNewTask();
                                DestObject:AddTask(lMissionflag);
                                --往玩家背包加相应任务道具
                                DestObject:addItem(NewItemObject, I_SLOT_DEFALUT);
                                CloseWindow(); --关闭窗口
                                return false;
                        end
                        return false;
                end
                Send(DestObject, !, 1);
                return true;
        end
end


-- 单条任务npc,只有接任务
function  doAction(bTalk,nSelectID,nSelectItemID)
        local lMissionflag=200 --npc任务标记变量       
        TaskObject:setID(lMissionflag);
        -- 做过这个任务了
        if  DestObject:GetHistroyTaskFlag(lMission) then
                return  false;                               
        end
        if DestObject:GetUpdataFlag(PLAYER_FIELD_EXT_LEVEL) >55  then        --当等级超过限制任务不存在(这边假设任务等级为45)
                return false;
        end
        if DestObject:GetUpdataFlag(PLAYER_FIELD_EXT_LEVEL)<40 then
                Send(DestObject, !, 2);
                return false;
        end
        if  bTalk then
                Send("Open Open Mission Windows",lMissionflag);--打开任务接受对话窗口显示对应任务
                if nSelectID=0 then        --当用户点击了接受任务按钮
                        --这边是接受响应任务相应任务处理
                        --如果接受任务有给东西则要加下面判断
                        if  (DestObject:GetUpdataFlag(背包当前使用格数)+1)<DestObject:GetUpdataFlag(背包总格数)  then                --背包如果满
                                MessageShow("背包满");
                        end
                        if  DestObject:getMissions()=20  then  --当任务已经20条  
                                MessageShow("任务已经满");  
                                return false;
                        end
                        --增加玩家任务
                        DestObject:CreateNewTask();
                        DestObject:AddTask(lMissionflag);
                        --往玩家背包加相应任务道具
                        DestObject:addItem(NewItemObject, I_SLOT_BOOT);
                        CloseWindow(); --关闭窗口
                        return false;
                end
                return false;
        end
        if DestObject:GetUpdataFlag(PLAYER_FIELD_EXT_LEVEL)<51 then
                Send(DestObject, !, 1);
        end
        return true;
        end
end


-- 单条任务npc,只有交任务
function  doAction(bTalk,nSelectID,nSelectItemID)
        local lMissionflag=200 --npc任务标记变量
        bAlreadHave = false;
        --循环获得任务是否有这个任务
        for  i=0,19 do
                if  DestObject:GetUpdataFlag(PLAYER_FIELD_QUEST_LOG_1_1+i*3) != lMissionFalg  then
                        bAlreadHave = true;
                        break;
                end
        end
        if  bAlreadHave  then
                -- 如果是获取物品的任务检查所需要条件(例如需要20件3143的物品)如果是直接对话完成任务的
                lNumsItem = DestObject:GetNumsItem(3143);
                if lNumsItem < 20 then
                        Send(DestObject, ?, 2);
                        if  bTalk then
                                Send("Open Finish Mission Windows",lMissionflag);--打开任务结束对话窗口显示对应任务
                        end
                        return false;
                end
                Send(DestObject,?,1);
                if  bTalk then
                        Send("Open Finish Mission Windows",lMissionflag);--打开任务结束对话窗口显示对应任务
                        Send("Enable Over Button");--将完成任务那个按钮设置为可点击的默认为不可以
                        if nSelectID=0 then        --当用户点击了完成任务按钮
                                --如果任务奖励有要给东西则这边要进行以下判断这边是相应任务奖励处理
                                if  (DestObject:getUpdateFlag(CONTAINER_FIELD_NUM_SLOTS)<3)  then  --背包的空格数不够奖励道具的数量
                                        MessageShow("背包满");
                                end
                                DestObject:addItem(NewItemObject, I_SLOT_DEFALUT);--将对应的奖励放入背包
                                --其他奖励
                                DestObject:addItem(NewItemObject, I_SLOT_DEFALUT);  --将默认的奖励物品放入背包
                                DestObject:setUpdateIntValue(PLAYER_FIELD_COINAGE,+1000);  --增加玩家金钱
                                DestObject:setUpdateIntValue(PLAYER_FIELD_XP,+10000);  --增加玩家经验
                                DestObject:DeleteTask(lMissionflag);
                                send(.....) --更新客户端信息
                                CloseWindow(); --关闭窗口
                                return false;
                        end
                        return false;
                end
                retrun true;                       
        end
end


--多条任务npc (例如该npc有两条任务)并且尽量让玩家可能先做的任务写到前面
function  doTalk(bTalk)
        local lMissionflag1=200 ;--npc任务标记1变量
        TaskObject1:setID(lMissionflag1);
        local lMissionflag2=201 ;--npc任务标记2变量
        TaskObject2:setID(lMissionflag2);
        bAlreadHave1 = false;
        bAlreadHave2 = false;

        --循环获得任务是否有这个任务
        for  i=0,19 do
                if  DestObject:GetUpdataFlag(PLAYER_FIELD_QUEST_LOG_1_1+i*3) != lMissionFalg1  then
                        bAlreadHave1 = true;
                end
                if  DestObject:GetUpdataFlag(PLAYER_FIELD_QUEST_LOG_1_1+i*3) != lMissionFalg2  then
                        bAlreadHave2 = true;
                end
        end
        if  bAlreadHave1  then
                -- 如果是获取物品的任务检查所需要条件(例如需要20件3143的物品)如果是直接对话完成任务的
                lNumsItem = DestObject:GetNumsItem(3143);
                if lNumsItem < 20 then
                        Send(DestObject, ?, 2);
                        if  bTalk then
                                AddMissionItem(DestObject, ?, 2);       --往任务列表里面加入灰色问号这个未完成任务
                        end
                        return false;
                end
                Send(DestObject,?,1);
                if  bTalk then
                        AddMissionItem(DestObject,?,1);     --往任务列表里面加入黄色问号这个已完成任务
                        if
                else
                        return true;                --如果不是对话的则直接显示?,不用再对下面2的进行判断了
                end
        else                       
                -- 做过这个任务了
                if  DestObject:GetHistroyTaskFlag(lMissionflag1) == true then
                        return  false;                               
                end
                if DestObject:GetUpdataFlag(PLAYER_FIELD_EXT_LEVEL) >55  then        --当等级超过限制任务不存在(这边假设任务等级为45)
                        return false;
                end
                if DestObject:GetUpdataFlag(PLAYER_FIELD_EXT_LEVEL)<40 then
                        Send(DestObject, !, 2);
                        return false;
                end
                Send(DestObject, !, 1);
                if  bTalk then
                        AddMissionItem(DestObject, !, 1);     --往任务列表里面加入黄色问号这个已完成任务
                end
        end
       
        if  bAlreadHave2  then
                -- 如果是获取物品的任务检查所需要条件(例如需要20件3143的物品)如果是直接对话完成任务的
                lNumsItem = DestObject:GetNumsItem(3143);
                if lNumsItem < 20 then
                        Send(DestObject, ?, 2);
                        if  bTalk then
                                AddMissionItem(DestObject, ?, 2);       --往任务列表里面加入灰色问号这个未完成任务
                        end
                        return false;
                end
                Send(DestObject,?,1);
                if  bTalk then
                        AddMissionItem(DestObject,?,1);     --往任务列表里面加入黄色问号这个已完成任务
                else
                        return true;                --如果不是对话的则直接显示?,不用再对下面的进行判断了
                end
        else                       
                -- 做过这个任务了
                if  DestObject:GetHistroyTaskFlag(lMissionflag2) == true then
                        return  false;                               
                end
                if DestObject:GetUpdataFlag(PLAYER_FIELD_EXT_LEVEL) >55  then        --当等级超过限制任务不存在(这边假设任务等级为45)
                        return false;
                end
                if DestObject:GetUpdataFlag(PLAYER_FIELD_EXT_LEVEL)<40 then
                        Send(DestObject, !, 2);
                        return false;
                end
                Send(DestObject, !, 1);
                if  bTalk then
                        AddMissionItem(DestObject, !, 1);     --往任务列表里面加入黄色问号这个已完成任务
                end
        end
        Send("Open Selection Dialog");
end


--可重复做任务的npc  (例如捐布npc)
function  doTalk(bTalk )
        local lMissionflag=1000;
        Send(DestObject, ?, 3);
        if  bTalk then
                Send("Open Mission Window",lMissionflag);
        end
end

--限时杀指定怪物任务
function  doAction(bTalk,nSelectID,nSelectItemID)       --nSelectID为用户点击按钮的ID,nSelectItemID为用户选择奖励
       
        local lMissionflag=200; --npc任务标记变量
        TaskObject:setID(lMissionflag);
        local nSelectitem={22,33,435}; --给玩家选择的任务奖励物品(22.33.435这些是对应的任务奖励物品ID)
        bAlreadHave = false;
        --循环获得任务是否有这个任务
        for  i=0,19 do
                if  DestObject:GetUpdataFlag(UNIT_FIELD_TASK        +i*8) != lMissionFalg  then
                        bAlreadHave = true;
                        break;
                end
        end
        if  bAlreadHave  then
                -- 判断任务
                local ltime = DestObject:getTimerLimit();
                local lNum1=TaskObject:getCurrnetNumsOfMonst(狼,疯狂的狼);
                local lNum2=TaskObject:getCurrnetNumsOfMonst(狼,饥饿的狼);
                if (ltime ==0 and lNum1<20 ) and lNum2<20 then
                        Send(DestObject, ?, 2);
                        if  bTalk then
                                Send("Open Finish Mission Windows",lMissionflag);--打开任务结束对话窗口显示对应任务
                        end
                        return false;
                end
                if  bTalk then
                        Send("Open Finish Mission Windows",lMissionflag);    --打开任务结束对话窗口显示对应任务
                        Send("Enable Over Button");         --将完成任务那个按钮设置为可点击的默认为不可以
                        if nSelectID=0 then        --当用户点击了完成任务按钮
                                --如果任务奖励有要给东西则这边要进行以下判断这边是相应任务奖励处理
                                if  (DestObject:getUpdateFlag(CONTAINER_FIELD_NUM_SLOTS)<3)  then  --背包的空格数不够奖励道具的数量
                                        MessageShow("背包满");
                                end

                                DestObject:addItem(NewItemObject, nSelectItemID);--将对应的奖励放入背包
                                --其他奖励
                                DestObject:addItem(NewItemObject, I_SLOT_BOOT);  --将默认的奖励物品放入背包
                                DestObject:setUpdateIntValue(PLAYER_FIELD_COINAGE,+1000);  --增加玩家金钱
                                DestObject:setUpdateIntValue(PLAYER_FIELD_XP,+10000);  --增加玩家经验
                                DestObject:DeleteTask(lMissionflag);
                                send(.....) --更新客户端信息
                                CloseWindow(); --关闭窗口
                                return false;
                        end
                        return false;
                end
                Send(SrcObject,?,1);
                retrun true;
        else                       
                -- 做过这个任务了
                if  DestObject:GetHistroyTaskFlag(lMissionflag)  then
                        return  false;                               
                end
                if  DestObject:GetUpdataFlag(PLAYER_FIELD_EXT_LEVEL)<39  then        --当等级超过限制任务不存在(这边假设任务等级为45)
                        return false;
                end
                if DestObject:GetUpdataFlag(PLAYER_FIELD_EXT_LEVEL)<42 then
                        Send(DestObject, !, 2);
                        return false;
                end       
               
                if  bTalk then
                        Send("Open Open Mission Windows",lMissionflag);--打开任务接受对话窗口显示对应任务
                        if nSelectID=0 then        --当用户点击了接受任务按钮
                                --这边是接受响应任务相应任务处理
                                --如果接受任务有给东西则要加下面判断
                                if  (DestObject:getUpdateFlag(CONTAINER_FIELD_NUM_SLOTS)<2)  then                --背包如果满
                                        MessageShow("背包满");
                                        return false;
                                end
                                if  DestObject:GetCurrentNumsOfTask()==20  then  --当任务已经20条  
                                        MessageShow("任务已经满");  
                                        return false;
                                end
                                --增加玩家任务
                                DestObject:CreateNewTask();
                                DestObject:AddTask(lMissionflag);
                               
                                TaskObject:setTimerLimit(300);
                                TaskObject:setMonstQueryInfo(1,狼,疯狂的狼,20); --该任务要杀两种狼,参数(在该任务的位置,主类型,具体品种,数量)
                                TaskObject:setMonstQueryInfo(2,狼,饥饿的狼,20);
                               
                                --往玩家背包加相应任务道具
                                DestObject:addItem(NewItemObject, I_SLOT_BOOT);
                                CloseWindow(); --关闭窗口
                                return false;
                        end
                        return false;
                end
                if DestObject:GetUpdataFlag(PLAYER_FIELD_EXT_LEVEL)<51 then
                        Send(DestObject, !, 1);
                end
                return true;
        end
end

0

主题

9

帖子

9

积分

新手上路

Rank: 1

积分
9
发表于 2006-7-13 17:31:00 | 显示全部楼层

Re:转: MMORPG任务系统设计

任务系统的触发分为很多种上面只是几种,用lua写的
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2026-1-24 23:07

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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