TL中使用Lua脚本的过程 脚本中的Timer过程

1.首先在c++源码中添加需要注册到Lua的函数

INT LuaFnSetTimer(Lua_State* L)
{
LUA_ENTER_FUNCTION

SceneID_t sceneId = Lua_ValueToNumber(L,1);
ObjID_t selfId = Lua_ValueToNumber(L,2);
ScriptID_t scriptId = Lua_ValueToNumber(L,3);
const CHAR* funcName = Lua_ValueToString(L,4);
INT tickTime = Lua_ValueToNumber(L,5);

BEGINHUMANDEFINE(“LuaFnSetTimer”)
if(pHuman->GetUseTimerCount() < pHuman->GetMaxTimerCount())
{
INT sceneTimerIndex = pScene->GetSceneTimer()->GetTimer();
AssertEx(sceneTimerIndex>=0 && sceneTimerIndex < g_Config.m_ConfigInfo.m_MaxTimerCount,”No Timer resource for allocate”);

if(sceneTimerIndex>=0 && sceneTimerIndex < g_Config.m_ConfigInfo.m_MaxTimerCount)
{
pHuman->AddTimer(sceneTimerIndex);
pScene->GetSceneTimer()->StartTheTimer(sceneTimerIndex,selfId,scriptId,funcName,tickTime);

Lua_PushNumber(L,sceneTimerIndex);
return 1;
}
}
ENDHUMANDEFINE

RETURNFALSE

LUA_LEAVE_FUNCTION
RETURNFALSE
}

2.然后将函数注册进Lua中

// 定义Lua注册通用的函数指针

typedef INT (*FuncProto)(Lua_State * L);

// 定义工具结构

struct _Str2Func
{
CHAR* funcname;
FuncProto proto;
};

// 像这样定义中间结构

struct _Str2Func functbl[] =
{
{“AddEventList”,FuncProto(LuaFnAddNumText)},
{“GetMission”, FuncProto(LuaFnGetMission)},

{“CityMoveTo”, FuncProto(LuaFnCityMoveTo)},
};
}

// 像这样进行 使用FireFox的Lua引擎进行 函数注册

for(INT i=0; i<sizeof(LuaFnTbl::functbl)/sizeof(_Str2Func); i++)
{
mLua.RegisterFunction(LuaFnTbl::functbl[i].funcname,(VOID*)(LuaFnTbl::functbl[i].proto));
}

 

3.开始使用定时器

// 然后脚本设置一个定时器 5个参数见函数定义 需要传人函数名

LuaFnSetTimer(1,2,3,4,5);

4.定时器实现

// 调用服务器中的定时器 以下是定义

class CMyTimer
{
private:
UINT m_uTickTerm;
UINT m_uTickOld;

public:
BOOL m_bOper;

public:
CMyTimer()
{
CleanUp() ;
}

BOOL IsSetTimer( ){ return m_bOper ; }

VOID SetTermTime( UINT uTerm ){ m_uTickTerm =uTerm; }
UINT GetTermTime( ){ return m_uTickTerm ; }

UINT GetTickOldTime( ){ return m_uTickOld; }

VOID CleanUp( )
{
m_uTickTerm = 0 ;
m_bOper = FALSE ;
m_uTickOld = 0 ;
}

VOID BeginTimer(UINT uTerm, UINT uNow)
{
m_bOper = TRUE;
m_uTickTerm =uTerm;
m_uTickOld =uNow;
}

BOOL CountingTimer(UINT uNow)
{
if(!m_bOper)
return FALSE;

UINT uNew =uNow;

if(uNew<m_uTickOld+m_uTickTerm )
return FALSE;

m_uTickOld =uNew;

return TRUE;
}
UINT GetLeaveTime(UINT uNow)//剩余时间;
{
if(!CountingTimer(uNow))
{
return m_uTickTerm+m_uTickOld-uNow;
}
return 0;
}
};

// 场景定时器

=================
class SceneTimer
{
public:
CMyTimer   mRefeshTimer;
#define FuncNameLen 32

typedef struct  _MyTimers
{
CHAR scriptFuncName[FuncNameLen];

INT selfId;
INT scriptId;

CMyTimer timer;
}MyTimer;

MyTimer* m_pTimers;
MyTimer* head;
INT index;
INT maxCount;
Scene* m_pScene;

//仅测试
#if _DEBUG
INT m_currentUse;
#endif
SceneTimer();

~SceneTimer();

VOID CleanUp() ;

BOOL IsInit()
{
if( m_pScene==NULL ) return FALSE ;
else return TRUE ;
};

VOID CreateTimer(INT maxCount,Scene* pScene);

VOID InitOne(INT i);

INT GetTimer();

VOID StartTheTimer(INT sceneTimerIndex,INT selfId,INT scriptId,const CHAR* funcName,INT tickTime);

VOID FreeTimer(INT index);

BOOL CheckTimer(INT index);

VOID OnTimer(UINT uTime);

Scene* GetScene()
{
return m_pScene;
}
};

 

//每个场景有一个线程来做处理  *备注 每个:”=====->”  都表示进入下一个函数调用
// 以下给出调用过程

VOID SceneThread::run( )===== ->

BOOL ret = m_apScene[i]->Tick( ) ; =====->

ret = HeartBeat( ) ;===== ->

m_pSceneTimers->OnTimer(uTime);->检查定时器是否触发<-=====–>

GetScene()->GetLuaInterface()->ExeScript_DDDD(
m_pTimers[i].scriptId,
m_pTimers[i].scriptFuncName,
(INT)GetScene()->SceneID(),
(INT)m_pTimers[i].selfId,
(INT)i,
(INT)0 ) ; =====->

1.依据数据组装出函数名

2.return ExeFile_DDDD(filename,funcnameX,Param0,Param1,Param2,Param3,bLoad);=====->

bRet = mLua.CallFunction( funcname, 1, “dddd”, Param0, Param1, Param2, Param3 ) ;

到这里一个定时器就过程就算完成