DEADSOFTWARE

can load map scripts from wads now
authorFGSFDSFGS <derp.primus@gmail.com>
Wed, 22 Jun 2016 20:30:02 +0000 (23:30 +0300)
committerFGSFDSFGS <derp.primus@gmail.com>
Tue, 28 Jun 2016 18:47:23 +0000 (21:47 +0300)
Conflicts:
build.bat
src/game/g_scriptprocs.pas
src/game/g_scripts.pas

build.bat
src/game/g_map.pas
src/game/g_scriptprocs.pas [new file with mode: 0644]
src/game/g_scripts.pas [new file with mode: 0644]
src/shared/MAPDEF.pas
src/shared/mapstructio.inc

index b58fbd9e47ad13a2cf8c7befb62029babb315e10..0d39603d338ea8ad319410b8765c88078aacd410 100644 (file)
--- 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
index 6c35e4e00af20320d07888af5b21590dbd3ae7a0..cb934b81705666abe9dcd89ace6d7ae251fa47cb 100644 (file)
@@ -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 (file)
index 0000000..082346e
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+ *)
+{$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 (file)
index 0000000..43fe3af
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+ *)
+{$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.
index 9fd1becc1060410fa9a2d69d17653a5c4bf38ab0..3f843872a2f3cdd8825b9268e254232d35a251a5 100644 (file)
@@ -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}
index 3e9763be912be89a1be453e99a71a024973bcf91..ae432b9614f0a857f524af2fa522be8b06d8d2fa 100644 (file)
@@ -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;