[转]天龙八部服务器端Lua脚本系统

摘要:
struct_ Str2Funcfunctbl[]={{“AddEventList”,FuncProto},{“GetMission”,Func Proto},{”GetMissionCount“,FuncProto},{”SetMissionByIndex“,Func proto},{“AddMission”、FuncProto}、{”AddMissionEx“、Funcprotoo}、{“SetMissionEvent”、Func Proto},…};这些C++函数在以下头文件中实现:#include“LuaFnTbl_Mission.h”#include”LuaFnTbl_Misc.h“#include”Lua FnTbl_Ability.h“#include”luaFnTb1_Attr.h“#contain”Lua-FnTbl_Pet.h“#包含”LuaF nTbl_Batch.h“#包含”Lua F nTbl_Shop.h“#包括”LuaFnTbl_Pet Placard.h“#包括”Lua fnTbl_Scene.h“#包含“LuaF tTbl_Team.h”#包含这是一个很好的例子“LuaFnTbl_DoAction.h”#include“LuaF nTbl_Relation.h”#include“Lua FnTbl_Guild.h”#包括“Lua F nTbl_City.h”这些函数不是函数的真正实现。真正的实现代码在场景、对象和其他地方。BinPublicDataScript。dat是一个索引,它存储脚本ID和相应的脚本文件名。所有SFileData都与SFileDataLink连接。

一、Lua脚本功能接口

1. LuaInterface.h/.cpp声明和实现LuaInterface。

LuaInterface成员如下:

//脚本引擎

FoxLuaScriptmLua ;

//注册器

LuaCFuncRegistermFuncRegister;

//场景关联

Scene*mOwner;

//已经读取的脚本表

IDTablem_ScriptTable ;

主要方法:

VOIDInit(Scene* pScene);//完成Lua脚本环境的初始化和C导出函数的注册

Scene* GetOwner();

执行Lua脚本C++接口,提供多达8个参数支持。

INTExeScript( ScriptID_t scriptid, CHAR* funcname ) ;

INTExeScript_D( ScriptID_t scriptid, CHAR* funcname, INT Param0 ) ;

INTExeScript_DD( ScriptID_t scriptid, CHAR* funcname, INT Param0, INT Param1 ) ;

INTExeScript_DDD( ScriptID_t scriptid, CHAR* funcname, INT Param0, INT Param1, INT Param2 ) ;

INTExeScript_DDDD( ScriptID_t scriptid, CHAR* funcname, INT Param0, INT Param1, INT Param2, INT Param3 ) ;

LuaInterface::Init里面会初始化mLua引擎,注册C++提供给Lua脚本的函数(LuaCFuncRegister),并加载ScriptGlobal.lua脚本。

2. LuaCFuncRegister.cpp里面对所有导出到Lua的C++函数进行注册。

struct _Str2Func functbl[] =

{

{"AddEventList",FuncProto(LuaFnAddNumText)},

{"GetMission", FuncProto(LuaFnGetMission)},

{"GetMissionCount", FuncProto(LuaFnGetMissionCount)},

{"SetMissionByIndex", FuncProto(LuaFnSetMissionByIndex)},

{"AddMission", FuncProto(LuaFnAddMission)},

{"AddMissionEx", FuncProto(LuaFnAddMissionEx)},

{"SetMissionEvent", FuncProto(LuaFnSetMissionEvent)},

...

};

这些C++函数的实现是在下列头文件中进行的:

#include "LuaFnTbl_Mission.h"

#include "LuaFnTbl_Misc.h"

#include "LuaFnTbl_Ability.h"

#include "LuaFnTbl_Attr.h"

#include "LuaFnTbl_Pet.h"

#include "LuaFnTbl_Battle.h"

#include "LuaFnTbl_Shop.h"

#include "LuaFnTbl_PetPlacard.h"

#include "LuaFnTbl_Scene.h"

#include "LuaFnTbl_Team.h"

#include "LuaFnTbl_DoAction.h"

#include "LuaFnTbl_Relation.h"

#include "LuaFnTbl_Guild.h"

#include "LuaFnTbl_City.h"

这些函数并不是功能的真正实现地方,真正的实现代码在Scene、Obj_Human等地方。这里只是集中转调而已。

3. 注册完成后,在Lua脚本中就可以使用类似AddMission接口调用C++里面功能。

二、Lua脚本位置

所有脚本在BinPublicDataScript子目录中。

BinPublicDataScript.dat是索引,里面保存了ScriptID和对应的脚本文件名。如:

888888=scene.lua

888889=mail.lua

888890=player_login.lua

...

脚本ID是6位的。

三、脚本索引的初始化

每个场景都会进行脚本初始化,具体是在Scene::Load里面,在在m_pLuaInterface初始化之后。

m_pLuaInterface->Init(this);

if( !m_pScriptFileMgr->IsInit() )

{

m_pScriptFileMgr->Init( FILE_SCRIPT, FALSE);

}

Log::SaveLog( SERVER_LOGFILE, "Load ../Public/Data/script.dat OK!" );

m_pScriptFileMgr->Init将"888888=scene.lua"拆开,保存ID和文件名到SFileData里面。所有的SFileData用SFileDataLink串起来。

四、脚本加载和调用

每个脚本的调用都是通过INT LuaFnCallScriptFunction(Lua_State* L);来进行的。该函数是一个C++函数,脚本里面调用名是CallScriptFunction,注册如下:

{"CallScriptFunction", FuncProto(LuaFnCallScriptFunction)},

LuaFnCallScriptFunction的实现在文件LuaFnTbl_Misc.h里。

可以看到在,此函数:

l 把SFileData添加到pScene->GetLuaInterface()->m_ScriptTable表里面;

pSFileData = pScene->GetLuaInterface()->GetOwner()->GetScriptFileMgr()->GetFileData(scriptId);

pScene->GetLuaInterface()->m_ScriptTable.Add( scriptId, pSFileData ) ;

l 然后加载脚本;

pScene->GetLuaInterface()->mLua.Load( const_cast<CHAR*>(filename) ) ;

l 最后调用脚本。

五、典型脚本的结构

ScriptDef.h,定义了一些脚本接口函数,如OnDefaultEvent,对于脚本805007,就是:

function x805007_OnDefaultEvent( sceneId, selfId,targetId );

有一些调用没有在这里定义宏,直接写在C++代码里面,如OnScenePlayerLogin

#defineDEF_EVENT_ENTRY_FUNC_NAME("OnDefaultEvent")//脚本进入函数

#defineDEF_ON_KILL_OBJECT_FUNC_NAME("OnKillObject")

#defineDEF_ON_ITEM_CHANGED_FUNC_NAME("OnItemChanged")

#defineDEF_ON_PET_CHANGED_FUNC_NAME("OnPetChanged")

#defineDEF_ON_ENTER_AREA_FUNC_NAME("OnEnterArea")

#defineDEF_ON_LEAVE_AREA_FUNC_NAME("OnLeaveArea")

#defineDEF_EVENT_ON_TIMER("OnTimer")

#defineDEF_MISSION_ACCEPT("OnMissionAccept")//接受任务

#defineDEF_MISSION_ABANDON("OnAbandon")//放弃任务

#defineDEF_MISSION_REFUSE("OnMissionRefuse")// 拒绝接受任务

#defineDEF_MISSION_SUBMIT("OnMissionSubmit")//任务完成后,提交任务

#defineDEF_MISSION_CHECK("OnMissionCheck")//任务完成条件检查

#defineDEF_MISSION_CONTINUE("OnMissionContinue")//任务没完成,继续

六、样例分析

大理NPC赵天师脚本分析

脚本名:Scriptobjdaliodali_xinshoutian.lua,汗,居然叫这个名字,找了半天,一般的命名都是拼音。

--赵天师

--脚本号

x002030_g_scriptId = 002030

--所拥有的事件ID列表

x002030_g_eventList={210200,210204,210205,210208,210210,210212,210213,210214,210216,210217,210220,210223, 210224, 210225, 210229, 210230, 210232, 210238, 210239, 210237, 210240, 200080, 200083, 200086, 200091, 200094,200095,210241,050022}

一般情况,每个event对于一个任务,也是一段脚本实现的。210200对于:

;大理城新手指导任务

210200=eventdaliedali_zhidao_0200.lua

--找人任务

--赵天师寻找蒲良

NPC脚本触发接口函数是xxx_OnDefaultEvent,在AI_HumanPushCommand_DefaultEvent里面触发。

ORESULT PushCommand_DefaultEvent( ObjID_t idNPC );

pCharacter->getScene()->GetLuaInterface()->ExeScript_DDD(

idScript,

DEF_EVENT_ENTRY_FUNC_NAME,

(INT)pCharacter->getScene()->SceneID(),

(INT)pCharacter->GetID(),

(INT)pNPC->GetID() ) ;

免责声明:文章转载自《[转]天龙八部服务器端Lua脚本系统》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇如何给iOS安装包IPA注入一个动态库文件?U盘启动时无USB-HDD选项的解决方案下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

PCL几种采样方法

(1)下采样  Downsampling 一般下采样是通过构造一个三维体素栅格,然后在每个体素内用体素内的所有点的重心近似显示体素中的其他点,这样体素内所有点就用一个重心点来表示,进行下采样的来达到滤波的效果,这样就大大的减少了数据量,特别是在配准,曲面重建等工作之前作为预处理,可以很好的提高程序的运行速度, #include <pcl/io/pcd...

lua 的 os.date os.time

lua 的 os.date 跟 shell的 date 功能一样强大。 关于的时间的概念梳理: 1. 格林威治时间GMT时间是我们平时使用的时间,世界各地的时间不一样是因为时区不一样,国内基本统一使用的北京时间, 时区是东八区。http://www.24timemap.com/ 所以世界在同一时刻的时间是不一致的。 2. UTC时间 是 世界标准时间/原子...

Golang中使用lua进行扩展

前言 最近在项目中需要使用lua进行扩展,发现github上有一个用golang编写的lua虚拟机,名字叫做gopher-lua.使用后发现还不错,借此分享给大家. 数据类型 lua中的数据类型与golang中的数据类型对应关系作者已经在文档中说明,值得注意的是类型是以L开头的,类型的名称是以LT开头的.golang中的数据转换为lua中的数据就必须转...

OpenLDAP 安装及配置 笔记

首先下载 OpenLdap(Ldap服务器) 和 LdapAdmin(客户端) 两个软件 OpenLDAPforWindows_2.4.39.part1.rar OpenLDAPforWindows_2.4.39.part2.rar OpenLDAPforWindows_2.4.39.part3.rar LdapAdmin1.1.rar ---------...

C/C++读取时间的方法

【摘要】本文介绍C/C++下获取日历时间的方法,区别于JAVA语言的方便,C/C++标准库好像并没有一次性得到具有可读性的HH:MM:SS的方法,本文介绍常用的三步法得出具有可读性的时间,并且介绍了纳秒和微秒的时间获取。 1、对于C语言,需包含的头文件: 1 #include <sys/time.h> 2、获取日期需要先获取日历时间,即1970...

预处理命令

C++提供的预处理功能主要有以下3种 1、宏定义 2、文件包含 3、条件编译 为了与一般C++语句相区别,这些命令以符号#开头,而且末尾不包含分号 宏定义 用#define命令将一个指定的标识符(即宏名)来代表一个字符串。定义宏的作用一般是用一个短的名字代笔一个长的字符串。它的一般形式 #define标识符字符串 在C语言中用#define定义符号常量,...