挂机型外挂开发-脚本引擎

这里我们使用lua脚本引擎

lua的lib部分和dll就不给出了

主要给出接口的基类实现

unit LuaMain;

interface
uses
  windows,Classes,SysUtils,Lua,LuaLib,GD_Utils;


{$DEFINE LUA_DBG}

{$IFDEF LUA_DBG}
{$MESSAGE HINT '内部调试版本'}
{$ENDIF}
const
  ScriptCfg = 'Init.lua';


type
  _LuaCfg = Packed Record
    Lv:Byte;
    Account:String;
    Psw:String;
    LuaFile:String;
    SaveHp:Cardinal;   //保护血量
    ItemNum:Cardinal;  //物品数量
    ItemRes:Cardinal;  //物品资源ID
    Token:String;
    Mode:Integer;
  end;
  _MarkNode = Packed record
    Mark:String;
    Line:Cardinal;
  end;

  _MarkData = packed Record
    Count:Cardinal;
    MarkNode:array [0..200] of _MarkNode;
  End;

  _Exception = packed record
    Code:Integer;
    Str:String;
  end;

  FPrintf = Procedure (s: string; args: array of const);Stdcall;
{$M+}
type
  TScriptMain = class(TLua)
    private
       ScriptStr:TStringList;
       MarkData:_MarkData;

       procedure Printf(s: string; args: array of const);
       procedure WaitTime(n:Cardinal = 500);
       function GameMoveEx(x, y: Single;TryMax:Cardinal = 20): Bool;
    published     {脚本实现}
      {系统}
      function LoadCfg(L: lua_State):Integer;
      function LogOutput(L: lua_State):Integer;
      function GetLuaDir(L: lua_State):Integer;
      function Wait(L: lua_State):Integer;
      function GetSaveCfg(L: lua_State):Integer;

      function ReportState(L: lua_State):Integer;

      function GotoMark(L: lua_State): Integer;
      function SetMark(L: lua_State): Integer;
      {游戏功能}

       {保护}

      function SetProtect(L : lua_State):Integer;
    public
      LuaCfg:_LuaCfg;
      DoLine:Integer;  //当前执行行号
      //脚本执行结束标志
      RunOver:Bool;
      //脚本执行错误
      ErrorInfo:_Exception;
      constructor Create();

      //脚本引擎初始化
      Function InitScriptEngine(ScriptFile:String):Bool;

      Function DoScript():Integer;
  end;

{$M-}

 // Procedure ScriptThread();

implementation

{ TScriptMain }


procedure TScriptMain.Printf(s: string; args: array of const);
begin
  LogPrintf(S,Args);
end;

function TScriptMain.ReportState(L: lua_State): Integer;
begin
  {$i vmp_begin.inc}

  Result:=0;
  {$i vmp_end.inc}
end;



function TScriptMain.SetProtect(L: lua_State): Integer;
begin
  LuaCfg.SaveHp:=lua_tointeger(L,1);
  LuaCfg.ItemRes:=lua_tointeger(L,2);
  {$IFDEF LUA_DBG}
  Printf('设定保护->HP:%d RES:%X',[
  LuaCfg.SaveHp,LuaCfg.ItemRes
  ]);
  {$ENDIF}
  Result:=0;
end;

function TScriptMain.Wait(L: lua_State): Integer;
begin
  {$IFDEF LUA_DBG}
  Printf('等待:%d',[lua_tointeger(L,1)]);
  {$ENDIF}
 WaitTime(lua_tointeger(L,1));
 Result:=0;
end;


procedure TScriptMain.WaitTime(n:Cardinal = 500);
begin
  Sleep(n);
end;


constructor TScriptMain.Create;
begin
  inherited Create(False);
  {$i vmp_begin.inc}
  //*******************************************框架基本****************************//
  RegisterFunction('跳转标记','GotoMark');
  RegisterFunction('标记','SetMark');
  RegisterFunction('获取脚本目录', 'GetLuaDir');      //+
  RegisterFunction('日志', 'LogOutput');              //+
  RegisterFunction('等待', 'Wait');
  //*******************************************移动相关****************************//
  RegisterFunction('加载配置', 'LoadCfg');            //+  挂机过程中所有的配置
  RegisterFunction('设置保护', 'SetProtect');         //+

  //******************************************系统相关****************************//
  RegisterFunction('报告状态', 'ReportState');        //+  发送数据给控制台

  Dbgprint('Script Engine Load Over',[]);
  {$i vmp_end.inc}
end;



Function TScriptMain.GameMoveEx(x,y:Single;TryMax:Cardinal = 20):Bool;
var
  Long:Single;
  TryTime:Cardinal;
  TimeTick:Cardinal;
begin
  {$IFDEF LUA_DBG}
  Printf('移动 -> %.3f,%.3f',[x,y]);
  {$ENDIF}
 // game.GameMove(x,y);
  Sleep(2000);
//  Long:=A2B(Role.info.x,Role.info.y,x,y);
  TryTime:=0;
  Result:=True;
  TimeTick:=GetTickCount();
  while Long > 30 do
    begin
    
    {  if Role.MoveState = 0 then
        begin
          TimeTick:=GetTickCount();
          Inc(TryTime);
          game.GameMove(x,y);
          Sleep(2000);
          {$IFDEF LUA_DBG}
         // Printf('移动修正调用 重试:%d 距离目标:%.3f',[TryTime,Long]);     }
         // {$ENDIF}
       // end;
      if  TryTime > TryMax then
        begin
          Result:=False;
          Break;
        end;
      if (GetTickCount - TimeTick) > (60 * 1000) then
        begin
          TimeTick:=GetTickCount();
          Inc(TryTime);
          //game.GameMove(x,y);
          {$IFDEF LUA_DBG}
          Printf('移动超时调用 重试:%d 距离目标:%.3f',[TryTime,Long]);
          {$ENDIF}
        end;
      WaitTime(2000);
    //  Long:=A2B(Role.info.x,Role.info.y,x,y);
    end;
  {$IFDEF LUA_DBG}
  //Printf('移动结束 耗时:%d',[GetTickCount - CountTick]);
  {$ENDIF}
end;




function TScriptMain.LoadCfg(L: lua_State): Integer;
begin
  {$i vmp_begin.inc}
  lua_getglobal(L,'g_Hp');                 // 保护血量
  lua_getglobal(L,'g_Acc');                // 账号
  lua_getglobal(L,'g_Psw');                // 密码
  lua_getglobal(L,'g_Token');              // 令牌
  lua_getglobal(L,'g_Num');                // 血瓶数量
  lua_getglobal(L,'g_Res');                // 血瓶资源ID
  lua_getglobal(L,'g_Lv');                 // 需求等级
  lua_getglobal(L,'g_Lua');                // 脚本文件
  lua_getglobal(L,'g_IsRichang');          // 是否日常脚本

  LuaCfg.SaveHp:= lua_tointeger(L,1);
  LuaCfg.Account:= lua_tostring(L,2);
  LuaCfg.Psw:= lua_tostring(L,3);
  LuaCfg.Token:= lua_tostring(L,4);
  LuaCfg.ItemNum := lua_tointeger(L,5);
  LuaCfg.ItemRes := lua_tointeger(L,6);
  LuaCfg.Lv:= lua_tointeger(L,7);
  LuaCfg.IsRichang:= lua_toboolean(L,9);
  Result:=0;
  {$i vmp_end.inc}
end;

function TScriptMain.LogOutput(L: lua_State): Integer;
begin
  {$i vmp_begin.inc}
  LogPrintf('%s',[lua_tostring(L,1)]);
  Printf('%s',[lua_tostring(L,1)]);
  Result:=0;
  {$i vmp_end.inc}
end;


function TScriptMain.GetLuaDir(L: lua_State): Integer;
begin
  //lua_pushstring(L,PChar(g_LuaDir));
  Result:=1;
end;

function TScriptMain.GetSaveCfg(L: lua_State): Integer;
begin
  lua_pushinteger(L,LuaCfg.ItemRes);
  lua_pushinteger(L,LuaCfg.ItemNum);
  Result:=2;
end;

function TScriptMain.GotoMark(L: lua_State): Integer;
var
  i,Tmp:Integer;
  Str:String;
begin
  Str:=Lua_tostring(L,1);
  Tmp:=DoLine;
  if MarkData.Count > 0 then
    begin
      for i := 0 to MarkData.Count - 1 do
        begin
          if MarkData.MarkNode[i].Mark = Str then
            begin
              DoLine:=MarkData.MarkNode[i].Line;
              Break;
            end;
        end;
    end;

  if DoLine = Tmp then
    begin
      ErrorInfo.Code := -1;
      ErrorInfo.Str := '标签未找到';
    end;
  Result:=0;
end;

function TScriptMain.SetMark(L: lua_State): Integer;
var
  Str:String;
begin
  Str:=Lua_tostring(L,1);
  MarkData.MarkNode[MarkData.Count].Mark := Str;
  MarkData.MarkNode[MarkData.Count].Line := DoLine;
  inc(MarkData.Count);
  Result:=0;
end;


function TScriptMain.InitScriptEngine(ScriptFile:String): Bool;
begin
  try
    ZeroMemory(@MarkData,SizeOf(_MarkData));
    ScriptStr.LoadFromFile(ScriptFile);
    DoLine:=0;
    ErrorInfo.Code:=0;
    RunOver:=False;
    Result:=True;
  except
    Result:=False;
  end;
end;

function TScriptMain.DoScript: Integer;
var
  Str:string;
begin
  Str:=ScriptStr[DoLine];
  Inc(DoLine);
  if Length(Trim(Str)) <> 0 then
    begin
      Result:=DoString(Str);
    end
  else
    Result:=0;
  if DoLine >= ScriptStr.Count  then RunOver:=True;
end;
end.
我们可以继承这个脚本基类扩展

unit UGameScript;

interface
uses
  Windows,LuaMain,LuaLib;

type
  TGameScript = class(TScriptMain)
    published
      function NpcTalk(L: lua_State):Integer;
    public
      constructor Create();
  end;

implementation
uses
  GD_Utils;
{ TGameScript }

constructor TGameScript.Create;
begin
  inherited;
  
  RegisterFunction('对话','NpcTalk');
end;

function TGameScript.NpcTalk(L: lua_State): Integer;
begin
  Dbgprint('NpcTalk',[]);
  Result:=0;
end;

end.



  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值