From 0aed9f9d49f034aad7d8856db00fe42f3303826d Mon Sep 17 00:00:00 2001 From: FGSFDSFGS Date: Wed, 22 Jun 2016 23:30:02 +0300 Subject: [PATCH] can load map scripts from wads now Conflicts: build.bat src/game/g_scriptprocs.pas src/game/g_scripts.pas --- build.bat | 4 + src/game/g_map.pas | 22 +++- src/game/g_scriptprocs.pas | 37 ++++++ src/game/g_scripts.pas | 236 +++++++++++++++++++++++++++++++++++++ src/shared/MAPDEF.pas | 5 +- src/shared/mapstructio.inc | 7 ++ 6 files changed, 306 insertions(+), 5 deletions(-) create mode 100644 src/game/g_scriptprocs.pas create mode 100644 src/game/g_scripts.pas diff --git a/build.bat b/build.bat index b58fbd9..0d39603 100644 --- a/build.bat +++ b/build.bat @@ -1,5 +1,9 @@ @echo off cd "./src/game" fpc -dUSE_FMOD -MDELPHI -O2 -Fi../lib/vampimg -Fi../lib/vampimg/JpegLib -Fi../lib/vampimg/ZLib -Fu../lib/vampimg -Fu../lib/vampimg/JpegLib -Fu../lib/vampimg/ZLib -FE../../bin -FU../../tmp Doom2DF.dpr +<<<<<<< HEAD cd ".." +======= +cd "../.." +>>>>>>> 32fab4b... can load map scripts from wads now pause \ No newline at end of file diff --git a/src/game/g_map.pas b/src/game/g_map.pas index 6c35e4e..cb934b8 100644 --- a/src/game/g_map.pas +++ b/src/game/g_map.pas @@ -133,7 +133,7 @@ uses GL, GLExt, g_weapons, g_game, g_sound, e_sound, CONFIG, g_options, MAPREADER, g_triggers, g_player, MAPDEF, Math, g_monsters, g_saveload, g_language, g_netmsg, - utils, sfs, + utils, sfs, g_scripts, ImagingTypes, Imaging, ImagingUtility, ImagingGif, ImagingNetworkGraphics; @@ -907,9 +907,10 @@ var DoorPanel: Integer; ShotPanel: Integer; end; - FileName, mapResName, s, TexName: String; - Data: Pointer; - Len: Integer; + FileName, mapResName, s, TexName, ScrStr: String; + Data, ScrText: Pointer; + ScrEnd: PByte; + Len, ScrLen: Integer; ok, isAnim, trigRef: Boolean; CurTex, ntn: Integer; begin @@ -940,6 +941,19 @@ begin WAD.Free(); Exit; end; + + // try to load the map script + g_Scripts_Reset(RESET_MAP); + ScrText := nil; + ScrLen := 0; + if WAD.GetResource('SCRIPTS/'+mapResName, ScrText, ScrLen) then + begin + g_Console_Add('SCRIPT: Found script for this map. Loading...'); + SetString(ScrStr, ScrText, ScrLen); + g_Scripts_Load(ScrStr); + FreeMem(ScrText); + end; + WAD.Free(); // Çàãðóçêà êàðòû: diff --git a/src/game/g_scriptprocs.pas b/src/game/g_scriptprocs.pas new file mode 100644 index 0000000..082346e --- /dev/null +++ b/src/game/g_scriptprocs.pas @@ -0,0 +1,37 @@ +(* Copyright (C) DooM 2D:Forever Developers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + *) +{$MODE DELPHI} +unit g_scriptprocs; + +interface + +uses + g_scripts; + +function SP_Lua_ConPrint(L: PScriptContext): Integer; cdecl; + +implementation + +uses + lua, g_console; + +function SP_Lua_ConPrint(L: PScriptContext): Integer; cdecl; +begin + g_Console_Add(lua_tostring(L, -1)); + Result := 0; +end; + +end. diff --git a/src/game/g_scripts.pas b/src/game/g_scripts.pas new file mode 100644 index 0000000..43fe3af --- /dev/null +++ b/src/game/g_scripts.pas @@ -0,0 +1,236 @@ +(* Copyright (C) DooM 2D:Forever Developers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + *) +{$MODE DELPHI} +unit g_scripts; + +interface + +uses + lua, lualib, lauxlib; + +const + // reset levels + RESET_ALL = 0; + RESET_SRV = 1; + RESET_WAD = 2; + RESET_MAP = 3; + +type + PScriptContext = Plua_State; + PScriptProc = lua_CFunction; + +var + gScriptCtx: PScriptContext = nil; + gScriptInit: Boolean = False; + +function g_Scripts_Init(): Boolean; +procedure g_Scripts_Reset(What: Integer); +function g_Scripts_ProcExec(PName: string; const Args: array of const): Integer; +function g_Scripts_ProcExists(PName: string): Boolean; +function g_Scripts_ProcInstall(PName: string; PPtr: PScriptProc): Boolean; +function g_Scripts_Load(Text: string): Boolean; +procedure g_Scripts_Free(); + +implementation + +uses + SysUtils, g_console, g_scriptprocs; + +type + POpenFunc = function(L: Plua_State): LongBool; cdecl; + TLuaReg = record + name: PAnsiChar; + func: POpenFunc; + end; + +const + LUA_LIBS: array [0..3] of TLuaReg = ( + (name: ''; func: luaopen_base), + (name: LUA_TABLIBNAME; func: luaopen_table), + (name: LUA_STRLINAME; func: luaopen_string), // STRLINAME is actually a typo in fpc's lua module + (name: LUA_MATHLIBNAME; func: luaopen_math) + ); + +function LuaInstallGameFuncs(): Boolean; +begin + Result := False; + + if not g_Scripts_ProcInstall('conprint', SP_Lua_ConPrint) then Exit; + + Result := True; +end; + +function g_Scripts_Init(): Boolean; +var + i: Integer; +begin + Result := False; + if gScriptInit then Exit; + + gScriptCtx := luaL_newstate(); + if gScriptCtx = nil then Exit; + + // don't open all the libs + for i := 0 to High(LUA_LIBS) do + begin + //lua_pushcfunction(gScriptCtx, LUA_LIBS[i].func); + lua_pushstring(gScriptCtx, LUA_LIBS[i].name); + //lua_call(gScriptCtx, 1, 0); + LUA_LIBS[i].func(gScriptCtx); + end; + + // create a table for game-related functions + lua_newtable(gScriptCtx); + lua_setglobal(gScriptCtx, 'game'); + + // create game-related tables + g_Scripts_Reset(RESET_ALL); + + gScriptInit := True; + // try to install game-related shit + if not LuaInstallGameFuncs() then + begin + g_Console_Add('SCRIPT: Could not init game callbacks'); + lua_close(gScriptCtx); + gScriptCtx := nil; + gScriptInit := False; + Exit; + end; + + Result := True; +end; + +// TODO: maybe actually put some fields into these? +procedure g_Scripts_Reset(What: Integer); +begin + if not gScriptInit then Exit; + if What in [RESET_ALL, RESET_SRV] then + begin + lua_newtable(gScriptCtx); + lua_setglobal(gScriptCtx, 'srv'); + end; + if What in [RESET_ALL, RESET_WAD] then + begin + lua_newtable(gScriptCtx); + lua_setglobal(gScriptCtx, 'wad'); + end; + if What in [RESET_ALL, RESET_MAP] then + begin + lua_newtable(gScriptCtx); + lua_setglobal(gScriptCtx, 'map'); + end; +end; + +function g_Scripts_ProcInstall(PName: string; PPtr: PScriptProc): Boolean; +begin + Result := False; + if not gScriptInit then Exit; + + if g_Scripts_ProcExists(PName) then + begin + g_Console_Add('SCRIPT: ProcInstall(' + PName + '): function already exists'); + Exit; + end; + + lua_getglobal(gScriptCtx, 'game'); + lua_pushstring(gScriptCtx, PName); + lua_pushcfunction(gScriptCtx, PPtr); + lua_settable(gScriptCtx, -3); + lua_setglobal(gScriptCtx, 'game'); + + Result := True; +end; + +function g_Scripts_ProcExists(PName: string): Boolean; +begin + Result := False; + if not gScriptInit then Exit; + + lua_getglobal(gScriptCtx, 'game'); + lua_pushstring(gScriptCtx, PName); + lua_gettable(gScriptCtx, -2); + + if lua_isfunction(gScriptCtx, -1) then + Result := True; +end; + +function g_Scripts_ProcExec(PName: string; const Args: array of const): Integer; +var + i: Integer; +begin + Result := -255; + if not gScriptInit then Exit; + + lua_getglobal(gScriptCtx, 'game'); + lua_pushstring(gScriptCtx, PName); + lua_gettable(gScriptCtx, -2); + if not lua_isfunction(gScriptCtx, -1) then + begin + g_Console_Add('SCRIPT: ProcExec(' + PName + ') error: no such function'); + Exit; + end; + + for i := 0 to High(Args) do + with Args[i] do + begin + case VType of + vtInteger: lua_pushinteger(gScriptCtx, vInteger); + vtBoolean: lua_pushboolean(gScriptCtx, vBoolean); + vtString: lua_pushstring(gScriptCtx, vString^); + vtAnsiString: lua_pushstring(gScriptCtx, PAnsiString(vAnsiString)^); + vtExtended: lua_pushnumber(gScriptCtx, vExtended^); + end; + end; + + if lua_pcall(gScriptCtx, Length(Args), 1, 0) <> 0 then + begin + g_Console_Add('SCRIPT: ProcExec(' + PName + ') error: ' + lua_tostring(gScriptCtx, -1)); + Exit; + end; + + if not lua_isnumber(gScriptCtx, -1) then + begin + g_Console_Add('SCRIPT: ProcExec(' + PName + ') error: return value is not a number'); + Exit; + end; + + Result := lua_tointeger(gScriptCtx, -1); + lua_pop(gScriptCtx, 1); +end; + +function g_Scripts_Load(Text: string): Boolean; +begin + Result := False; + if not gScriptInit then Exit; + + if lua_dostring(gScriptCtx, PChar(Text)) <> 0 then + begin + g_Console_Add('SCRIPT: Load() error: ' + lua_tostring(gScriptCtx, -1)); + Exit; + end; + + Result := True; +end; + +procedure g_Scripts_Free(); +begin + if not gScriptInit then Exit; + lua_close(gScriptCtx); + gScriptInit := False; + gScriptCtx := nil; +end; + +end. diff --git a/src/shared/MAPDEF.pas b/src/shared/MAPDEF.pas index 9fd1bec..3f84387 100644 --- a/src/shared/MAPDEF.pas +++ b/src/shared/MAPDEF.pas @@ -160,7 +160,8 @@ const TRIGGER_HEALTH = 26; TRIGGER_SHOT = 27; TRIGGER_EFFECT = 28; - TRIGGER_MAX = 28; + TRIGGER_SCRIPT = 29; + TRIGGER_MAX = 29; TRIGGER_SHOT_PISTOL = 0; TRIGGER_SHOT_BULLET = 1; @@ -330,6 +331,8 @@ type FXSpreadR: Byte; FXSpreadU: Byte; FXSpreadD: Byte); + TRIGGER_SCRIPT: (SCRProc: Char64; + SCRArg: Integer); end; {$INCLUDE mapstructsizes.inc} diff --git a/src/shared/mapstructio.inc b/src/shared/mapstructio.inc index 3e9763b..ae432b9 100644 --- a/src/shared/mapstructio.inc +++ b/src/shared/mapstructio.inc @@ -229,6 +229,12 @@ procedure mb_Read_TriggerData (var tr: TTriggerData; ttype: Integer; const buf; getBytesAt(tr.FXSpreadD, buf, 15, 1); end; + procedure xreadScript (); + begin + getBytesAt(tr.SCRProc, buf, 0, 64); + getIntAt(tr.SCRArg, buf, 64); + end; + begin if (bufsize < 104) then raise Exception.Create('invalid buffer size in mb_Read_TriggerData'); if (ttype = TRIGGER_EXIT) then begin xreadExit(); exit; end; @@ -259,6 +265,7 @@ begin if (ttype = TRIGGER_HEALTH) then begin xreadHealth(); exit; end; if (ttype = TRIGGER_SHOT) then begin xreadShot(); exit; end; if (ttype = TRIGGER_EFFECT) then begin xreadEffect(); exit; end; + if (ttype = TRIGGER_SCRIPT) then begin xreadScript(); exit; end; raise Exception.Create('invalid trigger type in mb_Read_TriggerData'); end; -- 2.29.2