Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision

Target

Select target project
  • STJr/SRB2
  • Sryder/SRB2
  • wolfy852/SRB2
  • Alpha2244/SRB2
  • Inuyasha/SRB2
  • yoshibot/SRB2
  • TehRealSalt/SRB2
  • PrisimaTF/SRB2
  • Hatninja/SRB2
  • SteelT/SRB2
  • james/SRB2
  • ShaderWraith/SRB2
  • SinnamonLat/SRB2
  • mazmazz_/SRB2
  • filpAM/SRB2
  • chaoloveicemdboy/SRB2
  • Whooa21/SRB2
  • Machturne/SRB2
  • Golden/SRB2
  • Tatsuru/SRB2
  • Snu/SRB2
  • Zwip-Zwap_Zapony/SRB2
  • fickleheart/SRB2
  • alphaRexJames/SRB2
  • JJK/SRB2
  • diskpoppy/SRB2
  • Hannu_Hanhi/SRB2
  • ZipperQR/SRB2
  • kays/SRB2
  • spherallic/SRB2
  • Zippy_Zolton/SRB2
  • namiishere/SRB2
  • Ors/SRB2
  • SMS_Alfredo/SRB2
  • sonic_edge/SRB2
  • lavla/SRB2
  • ashi/SRB2
  • X.organic/SRB2
  • Fafabis/SRB2
  • Meziu/SRB2
  • v-rob/SRB2
  • tertu/SRB2
  • bitten2up/SRB2
  • flarn2006/SRB2
  • Krabs/SRB2
  • clairebun/SRB2
  • Lactozilla/SRB2
  • thehackstack/SRB2
  • Spice/SRB2
  • win8linux/SRB2
  • JohnFrostFox/SRB2
  • talktoneon726/SRB2
  • Wane/SRB2
  • Lamibe/SRB2
  • spectrumuk2/srb-2
  • nerdyminer18/srb-2
  • 256nil/SRB2
  • ARJr/SRB2
  • Alam/SRB2
  • Zenya/srb-2-marathon-demos
  • Acelite/srb-2-archivedmodifications
  • MIDIMan/SRB2
  • Lach/SRB2
  • Frostiikin/bounce-tweaks
  • Jaden/SRB2
  • Tyron/SRB2
  • Astronight/SRB2
  • Mari0shi06/SRB2
  • aiire/SRB2
  • Galactice/SRB2
  • srb2-ports/srb2-dreamcast
  • sdasdas/SRB2
  • chreas/srb-2-vr
  • StarManiaKG/the-story-of-sinically-rocketing-and-botching-the-2nd
  • LoganAir/SRB2
  • NepDisk/srb-2
  • alufolie91/SRB2
  • Felicia.iso/SRB2
  • twi/SRB2
  • BarrelsOFun/SRB2
  • Speed2411/SRB2
  • Leather_Realms/SRB2
  • Ayemar/SRB2
  • Acelite/SRB2
  • VladDoc/SRB2
  • kaldrum/model-features
  • strawberryfox417/SRB2
  • Lugent/SRB2
  • Rem/SRB2
  • Refrag/SRB2
  • Henry_3230/srb-3230
  • TehPuertoRicanSpartan2/tprs-srb2
  • Leminn/srb-2-marathon-stuff
  • chromaticpipe2/SRB2
  • MiguelGustavo15/SRB2
  • Maru/srb-2-tests
  • SilicDev/SRB2
  • UnmatchedBracket/SRB2
  • HybridDog/SRB2
  • xordspar0/SRB2
  • jsjhbewfhh/SRB2
  • Fancy2209/SRB2
  • Lorsoen/SRB2
  • shindoukin/SRB2
  • GamerOfDays/SRB2
  • Craftyawesome/SRB2
  • tenshi-tensai-tennoji/SRB2
  • Scarfdudebalder/SRB2
  • luigi-budd/srb-2-fix-interplag-lockon
  • mskluesner/SRB2
  • johnpetersa19/SRB2
  • Pheazant/SRB2
  • chromaticpipe2/srb2classic
  • romoney5/SRB2
  • PAS/SRB2Classic
  • BlueStaggo/SRB2
  • Jisk/srb-2-beef-jerky
117 results
Select Git revision
Show changes
Commits on Source (101)
...@@ -266,6 +266,7 @@ if(${SRB2_CONFIG_HAVE_BLUA}) ...@@ -266,6 +266,7 @@ if(${SRB2_CONFIG_HAVE_BLUA})
blua/lfunc.c blua/lfunc.c
blua/lgc.c blua/lgc.c
blua/linit.c blua/linit.c
blua/liolib.c
blua/llex.c blua/llex.c
blua/lmem.c blua/lmem.c
blua/lobject.c blua/lobject.c
......
...@@ -18,6 +18,7 @@ OBJS:=$(OBJS) \ ...@@ -18,6 +18,7 @@ OBJS:=$(OBJS) \
$(OBJDIR)/ldo.o \ $(OBJDIR)/ldo.o \
$(OBJDIR)/lfunc.o \ $(OBJDIR)/lfunc.o \
$(OBJDIR)/linit.o \ $(OBJDIR)/linit.o \
$(OBJDIR)/liolib.o \
$(OBJDIR)/llex.o \ $(OBJDIR)/llex.o \
$(OBJDIR)/lmem.o \ $(OBJDIR)/lmem.o \
$(OBJDIR)/lobject.o \ $(OBJDIR)/lobject.o \
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
static const luaL_Reg lualibs[] = { static const luaL_Reg lualibs[] = {
{"", luaopen_base}, {"", luaopen_base},
{LUA_TABLIBNAME, luaopen_table}, {LUA_TABLIBNAME, luaopen_table},
{LUA_IOLIBNAME, luaopen_io},
{LUA_STRLIBNAME, luaopen_string}, {LUA_STRLIBNAME, luaopen_string},
{NULL, NULL} {NULL, NULL}
}; };
......
/*
** $Id: liolib.c,v 2.73.1.3 2008/01/18 17:47:43 roberto Exp $
** Standard I/O (and system) library
** See Copyright Notice in lua.h
*/
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define liolib_c
#define LUA_LIB
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
#include "../i_system.h"
#include "../doomdef.h"
#include "../m_misc.h"
#define IO_INPUT 1
#define IO_OUTPUT 2
#define FILELIMIT 1024*1024 // Size limit for reading/writing files
static const char *const fnames[] = {"input", "output"};
static const char *whitelist[] = { // Allow scripters to write files of these types to SRB2's folder
".txt",
".sav2",
".cfg",
".png",
".bmp"
};
static int pushresult (lua_State *L, int i, const char *filename) {
int en = errno; /* calls to Lua API may change this value */
if (i) {
lua_pushboolean(L, 1);
return 1;
}
else {
lua_pushnil(L);
if (filename)
lua_pushfstring(L, "%s: %s", filename, strerror(en));
else
lua_pushfstring(L, "%s", strerror(en));
lua_pushinteger(L, en);
return 3;
}
}
static void fileerror (lua_State *L, int arg, const char *filename) {
lua_pushfstring(L, "%s: %s", filename, strerror(errno));
luaL_argerror(L, arg, lua_tostring(L, -1));
}
#define tofilep(L) ((FILE **)luaL_checkudata(L, 1, LUA_FILEHANDLE))
static int io_type (lua_State *L) {
void *ud;
luaL_checkany(L, 1);
ud = lua_touserdata(L, 1);
lua_getfield(L, LUA_REGISTRYINDEX, LUA_FILEHANDLE);
if (ud == NULL || !lua_getmetatable(L, 1) || !lua_rawequal(L, -2, -1))
lua_pushnil(L); /* not a file */
else if (*((FILE **)ud) == NULL)
lua_pushliteral(L, "closed file");
else
lua_pushliteral(L, "file");
return 1;
}
static FILE *tofile (lua_State *L) {
FILE **f = tofilep(L);
if (*f == NULL)
luaL_error(L, "attempt to use a closed file");
return *f;
}
/*
** When creating file handles, always creates a `closed' file handle
** before opening the actual file; so, if there is a memory error, the
** file is not left opened.
*/
static FILE **newfile (lua_State *L) {
FILE **pf = (FILE **)lua_newuserdata(L, sizeof(FILE *));
*pf = NULL; /* file handle is currently `closed' */
luaL_getmetatable(L, LUA_FILEHANDLE);
lua_setmetatable(L, -2);
return pf;
}
/*
** function to (not) close the standard files stdin, stdout, and stderr
*/
static int io_noclose (lua_State *L) {
lua_pushnil(L);
lua_pushliteral(L, "cannot close standard file");
return 2;
}
/*
** function to close regular files
*/
static int io_fclose (lua_State *L) {
FILE **p = tofilep(L);
int ok = (fclose(*p) == 0);
*p = NULL;
return pushresult(L, ok, NULL);
}
static int aux_close (lua_State *L) {
lua_getfenv(L, 1);
lua_getfield(L, -1, "__close");
return (lua_tocfunction(L, -1))(L);
}
static int io_close (lua_State *L) {
if (lua_isnone(L, 1))
lua_rawgeti(L, LUA_ENVIRONINDEX, IO_OUTPUT);
tofile(L); /* make sure argument is a file */
return aux_close(L);
}
static int io_gc (lua_State *L) {
FILE *f = *tofilep(L);
/* ignore closed files */
if (f != NULL)
aux_close(L);
return 0;
}
static int io_tostring (lua_State *L) {
FILE *f = *tofilep(L);
if (f == NULL)
lua_pushliteral(L, "file (closed)");
else
lua_pushfstring(L, "file (%p)", f);
return 1;
}
static int StartsWith(const char *a, const char *b) // this is wolfs being lazy yet again
{
if(strncmp(a, b, strlen(b)) == 0) return 1;
return 0;
}
static int io_open (lua_State *L) {
const char *Cfilename = luaL_checkstring(L, 1);
char *filename = strdup(Cfilename);
int pass = 0;
size_t i;
int length = strlen(filename) - 1;
char *splitter, *splitter2;
char* destFilename;
const char *mode;
FILE **pf;
for (i = 0; i < (sizeof (whitelist) / sizeof(const char *)); i++)
{
if (!stricmp(&filename[length - (strlen(whitelist[i]) - 1)], whitelist[i]))
{
pass = 1;
break;
}
}
if (strstr(filename, "..") || strchr(filename, ':') || StartsWith(filename, "\\")
|| StartsWith(filename, "/") || strchr(filename, '%') || !pass)
{
luaL_error(L,"access denied to %s", filename);
return pushresult(L,0,filename);
}
I_mkdir("luafiles", 0755);
splitter = strdup(filename);
while ((splitter = strchr(splitter, '/')))
{
*splitter = 0;
I_mkdir(va("luafiles"PATHSEP"%s", filename), 0755);
*splitter = '/';
splitter++;
}
splitter2 = strdup(filename);
while ((splitter2 = strchr(splitter2, '\\')))
{
*splitter2 = 0;
I_mkdir(va("luafiles"PATHSEP"%s", filename), 0755);
*splitter2 = '\\';
splitter2++;
}
destFilename = va("luafiles"PATHSEP"%s", filename);
filename = destFilename;
mode = luaL_optstring(L, 2, "r");
pf = newfile(L);
*pf = fopen(filename, mode);
free(splitter);
free(splitter2);
return (*pf == NULL) ? pushresult(L, 0, filename) : 1;
}
static int io_tmpfile (lua_State *L) {
FILE **pf = newfile(L);
*pf = tmpfile();
return (*pf == NULL) ? pushresult(L, 0, NULL) : 1;
}
static FILE *getiofile (lua_State *L, int findex) {
FILE *f;
lua_rawgeti(L, LUA_ENVIRONINDEX, findex);
f = *(FILE **)lua_touserdata(L, -1);
if (f == NULL)
luaL_error(L, "standard %s file is closed", fnames[findex - 1]);
return f;
}
static int g_iofile (lua_State *L, int f, const char *mode) {
if (!lua_isnoneornil(L, 1)) {
const char *filename = lua_tostring(L, 1);
if (filename) {
FILE **pf = newfile(L);
*pf = fopen(filename, mode);
if (*pf == NULL)
fileerror(L, 1, filename);
}
else {
tofile(L); /* check that it's a valid file handle */
lua_pushvalue(L, 1);
}
lua_rawseti(L, LUA_ENVIRONINDEX, f);
}
/* return current value */
lua_rawgeti(L, LUA_ENVIRONINDEX, f);
return 1;
}
static int io_input (lua_State *L) {
return g_iofile(L, IO_INPUT, "r");
}
static int io_output (lua_State *L) {
return g_iofile(L, IO_OUTPUT, "w");
}
static int io_readline (lua_State *L);
static void aux_lines (lua_State *L, int idx, int toclose) {
lua_pushvalue(L, idx);
lua_pushboolean(L, toclose); /* close/not close file when finished */
lua_pushcclosure(L, io_readline, 2);
}
static int f_lines (lua_State *L) {
tofile(L); /* check that it's a valid file handle */
aux_lines(L, 1, 0);
return 1;
}
static int io_lines (lua_State *L) {
if (lua_isnoneornil(L, 1)) { /* no arguments? */
/* will iterate over default input */
lua_rawgeti(L, LUA_ENVIRONINDEX, IO_INPUT);
return f_lines(L);
}
else {
const char *filename = luaL_checkstring(L, 1);
FILE **pf = newfile(L);
*pf = fopen(filename, "r");
if (*pf == NULL)
fileerror(L, 1, filename);
aux_lines(L, lua_gettop(L), 1);
return 1;
}
}
/*
** {======================================================
** READ
** =======================================================
*/
static int read_number (lua_State *L, FILE *f) {
lua_Number d;
if (fscanf(f, LUA_NUMBER_SCAN, &d) == 1) {
lua_pushnumber(L, d);
return 1;
}
else return 0; /* read fails */
}
static int test_eof (lua_State *L, FILE *f) {
int c = getc(f);
ungetc(c, f);
lua_pushlstring(L, NULL, 0);
return (c != EOF);
}
static int read_line (lua_State *L, FILE *f) {
luaL_Buffer b;
luaL_buffinit(L, &b);
for (;;) {
size_t l;
char *p = luaL_prepbuffer(&b);
if (fgets(p, LUAL_BUFFERSIZE, f) == NULL) { /* eof? */
luaL_pushresult(&b); /* close buffer */
return (lua_objlen(L, -1) > 0); /* check whether read something */
}
l = strlen(p);
if (l == 0 || p[l-1] != '\n')
luaL_addsize(&b, l);
else {
luaL_addsize(&b, l - 1); /* do not include `eol' */
luaL_pushresult(&b); /* close buffer */
return 1; /* read at least an `eol' */
}
}
}
static int read_chars (lua_State *L, FILE *f, size_t n) {
size_t rlen; /* how much to read */
size_t nr; /* number of chars actually read */
luaL_Buffer b;
luaL_buffinit(L, &b);
rlen = LUAL_BUFFERSIZE; /* try to read that much each time */
do {
char *p = luaL_prepbuffer(&b);
if (rlen > n) rlen = n; /* cannot read more than asked */
nr = fread(p, sizeof(char), rlen, f);
luaL_addsize(&b, nr);
n -= nr; /* still have to read `n' chars */
} while (n > 0 && nr == rlen); /* until end of count or eof */
luaL_pushresult(&b); /* close buffer */
return (n == 0 || lua_objlen(L, -1) > 0);
}
static int g_read (lua_State *L, FILE *f, int first) {
int nargs = lua_gettop(L) - 1;
int success;
int n;
clearerr(f);
if (nargs == 0) { /* no arguments? */
success = read_line(L, f);
n = first+1; /* to return 1 result */
}
else { /* ensure stack space for all results and for auxlib's buffer */
luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments");
success = 1;
for (n = first; nargs-- && success; n++) {
if (lua_type(L, n) == LUA_TNUMBER) {
size_t l = (size_t)lua_tointeger(L, n);
success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l);
}
else {
const char *p = lua_tostring(L, n);
luaL_argcheck(L, p && p[0] == '*', n, "invalid option");
switch (p[1]) {
case 'n': /* number */
success = read_number(L, f);
break;
case 'l': /* line */
success = read_line(L, f);
break;
case 'a': /* file */
read_chars(L, f, ~((size_t)0)); /* read MAX_SIZE_T chars */
success = 1; /* always success */
break;
default:
return luaL_argerror(L, n, "invalid format");
}
}
}
}
if (ferror(f))
return pushresult(L, 0, NULL);
if (!success) {
lua_pop(L, 1); /* remove last result */
lua_pushnil(L); /* push nil instead */
}
return n - first;
}
static int io_read (lua_State *L) {
return g_read(L, getiofile(L, IO_INPUT), 1);
}
static int f_read (lua_State *L) {
return g_read(L, tofile(L), 2);
}
static int io_readline (lua_State *L) {
FILE *f = *(FILE **)lua_touserdata(L, lua_upvalueindex(1));
int sucess;
if (f == NULL) /* file is already closed? */
luaL_error(L, "file is already closed");
sucess = read_line(L, f);
if (ferror(f))
return luaL_error(L, "%s", strerror(errno));
if (sucess) return 1;
else { /* EOF */
if (lua_toboolean(L, lua_upvalueindex(2))) { /* generator created file? */
lua_settop(L, 0);
lua_pushvalue(L, lua_upvalueindex(1));
aux_close(L); /* close it */
}
return 0;
}
}
/* }====================================================== */
static int g_write (lua_State *L, FILE *f, int arg) {
int nargs = lua_gettop(L) - 1;
int status = 1;
size_t count = 0;
for (; nargs--; arg++) {
if (lua_type(L, arg) == LUA_TNUMBER) {
/* optimization: could be done exactly as for strings */
status = status &&
fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0;
}
else {
size_t l;
const char *s = luaL_checklstring(L, arg, &l);
count += l;
if (ftell(f) + l > FILELIMIT)
{
luaL_error(L,"write limit bypassed in file. Changes have been discarded.");
break;
}
status = status && (fwrite(s, sizeof(char), l, f) == l);
}
}
return pushresult(L, status, NULL);
}
static int io_write (lua_State *L) {
return g_write(L, getiofile(L, IO_OUTPUT), 1);
}
static int f_write (lua_State *L) {
return g_write(L, tofile(L), 2);
}
static int f_seek (lua_State *L) {
static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END};
static const char *const modenames[] = {"set", "cur", "end", NULL};
FILE *f = tofile(L);
int op = luaL_checkoption(L, 2, "cur", modenames);
long offset = luaL_optlong(L, 3, 0);
op = fseek(f, offset, mode[op]);
if (op)
return pushresult(L, 0, NULL); /* error */
else {
lua_pushinteger(L, ftell(f));
return 1;
}
}
static int f_setvbuf (lua_State *L) {
static const int mode[] = {_IONBF, _IOFBF, _IOLBF};
static const char *const modenames[] = {"no", "full", "line", NULL};
FILE *f = tofile(L);
int op = luaL_checkoption(L, 2, NULL, modenames);
lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE);
int res = setvbuf(f, NULL, mode[op], sz);
return pushresult(L, res == 0, NULL);
}
static int io_flush (lua_State *L) {
return pushresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL);
}
static int f_flush (lua_State *L) {
return pushresult(L, fflush(tofile(L)) == 0, NULL);
}
static const luaL_Reg iolib[] = {
{"close", io_close},
{"flush", io_flush},
{"input", io_input},
{"lines", io_lines},
{"open", io_open},
{"output", io_output},
{"read", io_read},
{"tmpfile", io_tmpfile},
{"type", io_type},
{"write", io_write},
{NULL, NULL}
};
static const luaL_Reg flib[] = {
{"close", io_close},
{"flush", f_flush},
{"lines", f_lines},
{"read", f_read},
{"seek", f_seek},
{"setvbuf", f_setvbuf},
{"write", f_write},
{"__gc", io_gc},
{"__tostring", io_tostring},
{NULL, NULL}
};
static void createmeta (lua_State *L) {
luaL_newmetatable(L, LUA_FILEHANDLE); /* create metatable for file handles */
lua_pushvalue(L, -1); /* push metatable */
lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */
luaL_register(L, NULL, flib); /* file methods */
}
static void createstdfile (lua_State *L, FILE *f, int k, const char *fname) {
*newfile(L) = f;
if (k > 0) {
lua_pushvalue(L, -1);
lua_rawseti(L, LUA_ENVIRONINDEX, k);
}
lua_pushvalue(L, -2); /* copy environment */
lua_setfenv(L, -2); /* set it */
lua_setfield(L, -3, fname);
}
static void newfenv (lua_State *L, lua_CFunction cls) {
lua_createtable(L, 0, 1);
lua_pushcfunction(L, cls);
lua_setfield(L, -2, "__close");
}
LUALIB_API int luaopen_io (lua_State *L) {
createmeta(L);
/* create (private) environment (with fields IO_INPUT, IO_OUTPUT, __close) */
newfenv(L, io_fclose);
lua_replace(L, LUA_ENVIRONINDEX);
/* open library */
luaL_register(L, LUA_IOLIBNAME, iolib);
/* create (and set) default files */
newfenv(L, io_noclose); /* close function for default files */
createstdfile(L, stdin, IO_INPUT, "stdin");
createstdfile(L, stdout, IO_OUTPUT, "stdout");
createstdfile(L, stderr, 0, "stderr");
lua_pop(L, 1); /* pop environment for default files */
return 1;
}
...@@ -21,6 +21,9 @@ LUALIB_API int (luaopen_base) (lua_State *L); ...@@ -21,6 +21,9 @@ LUALIB_API int (luaopen_base) (lua_State *L);
#define LUA_TABLIBNAME "table" #define LUA_TABLIBNAME "table"
LUALIB_API int (luaopen_table) (lua_State *L); LUALIB_API int (luaopen_table) (lua_State *L);
#define LUA_IOLIBNAME "io"
LUALIB_API int (luaopen_io) (lua_State *L);
#define LUA_STRLIBNAME "string" #define LUA_STRLIBNAME "string"
LUALIB_API int (luaopen_string) (lua_State *L); LUALIB_API int (luaopen_string) (lua_State *L);
......
...@@ -2222,7 +2222,8 @@ static void Command_connect(void) ...@@ -2222,7 +2222,8 @@ static void Command_connect(void)
CONS_Printf(M_GetText( CONS_Printf(M_GetText(
"Connect <serveraddress> (port): connect to a server\n" "Connect <serveraddress> (port): connect to a server\n"
"Connect ANY: connect to the first lan server found\n" "Connect ANY: connect to the first lan server found\n"
"Connect SELF: connect to your own server.\n")); "Connect SELF: connect to your own server.\n"
"Connect HOST <map> <gametype>: "));
return; return;
} }
...@@ -2237,7 +2238,79 @@ static void Command_connect(void) ...@@ -2237,7 +2238,79 @@ static void Command_connect(void)
server = false; server = false;
if (!stricmp(COM_Argv(1), "self")) // mirmiru RedEnchilada: host a game from connect
if (!stricmp(COM_Argv(1), "HOST"))
{
const char *mapname;
INT32 newmapnum;
INT32 j, newgametype = INT32_MAX;
if (COM_Argc() != 4)
{
CONS_Printf("Command must be of form \"Connect"
" HOST <MAPxx> <gametype>\".\n");
return;
}
// Get map number from name
mapname = COM_Argv(2);
// internal wad lump always: map command doesn't support external files as in doom legacy
if (W_CheckNumForName(mapname) == LUMPERROR)
{
CONS_Alert(CONS_ERROR, M_GetText("Internal game level '%s' not found\n"), mapname);
return;
}
if (strlen(mapname) != 5
|| (newmapnum = M_MapNumber(mapname[3], mapname[4])) == 0)
{
CONS_Alert(CONS_ERROR, M_GetText("Invalid level name %s\n"), mapname);
return;
}
// Get gametype
for (j = 0; gametype_cons_t[j].strvalue; j++)
if (!strcasecmp(gametype_cons_t[j].strvalue, COM_Argv(3)))
{
// Don't do any variable setting here. Wait until you get your
// map packet first to avoid sending the same info twice!
newgametype = gametype_cons_t[j].value;
break;
}
if (!gametype_cons_t[j].strvalue) // reached end of the list with no match
{
// assume they gave us a gametype number, which is okay too
for (j = 0; gametype_cons_t[j].strvalue != NULL; j++)
{
if (atoi(COM_Argv(3)) == gametype_cons_t[j].value)
{
newgametype = gametype_cons_t[j].value;
break;
}
}
}
#if 0 // gametype will never equal INT32_MAX
if (gametype == INT32_MAX)
{
CONS_Alert(CONS_ERROR, M_GetText("Invalid gametype %s\n"), COM_Argv(3));
return;
}
#endif
// Goodbye, we're off to host a server
CV_SetValue(&cv_nextmap, newmapnum);
CV_SetValue(&cv_newgametype, newgametype);
server = true;
M_StartServer(0);
return;
}
else if (!stricmp(COM_Argv(1), "self"))
{ {
servernode = 0; servernode = 0;
server = true; server = true;
......
...@@ -302,7 +302,7 @@ static void D_Display(void) ...@@ -302,7 +302,7 @@ static void D_Display(void)
if (rendermode != render_none) if (rendermode != render_none)
{ {
// Fade to black first // Fade to black first
if (gamestate != GS_LEVEL // fades to black on its own timing, always if (!(gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction)) // fades to black on its own timing, always
&& wipedefs[wipedefindex] != UINT8_MAX) && wipedefs[wipedefindex] != UINT8_MAX)
{ {
F_WipeStartScreen(); F_WipeStartScreen();
...@@ -318,6 +318,12 @@ static void D_Display(void) ...@@ -318,6 +318,12 @@ static void D_Display(void)
// do buffered drawing // do buffered drawing
switch (gamestate) switch (gamestate)
{ {
case GS_TITLESCREEN:
if (!titlemapinaction) {
F_TitleScreenDrawer();
break;
}
// Intentional fall-through
case GS_LEVEL: case GS_LEVEL:
if (!gametic) if (!gametic)
break; break;
...@@ -366,10 +372,6 @@ static void D_Display(void) ...@@ -366,10 +372,6 @@ static void D_Display(void)
HU_Drawer(); HU_Drawer();
break; break;
case GS_TITLESCREEN:
F_TitleScreenDrawer();
break;
case GS_WAITINGPLAYERS: case GS_WAITINGPLAYERS:
// The clientconnect drawer is independent... // The clientconnect drawer is independent...
case GS_DEDICATEDSERVER: case GS_DEDICATEDSERVER:
...@@ -379,9 +381,10 @@ static void D_Display(void) ...@@ -379,9 +381,10 @@ static void D_Display(void)
// clean up border stuff // clean up border stuff
// see if the border needs to be initially drawn // see if the border needs to be initially drawn
if (gamestate == GS_LEVEL) if (gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction))
{ {
// draw the view directly // draw the view directly
if (!automapactive && !dedicated && cv_renderview.value) if (!automapactive && !dedicated && cv_renderview.value)
{ {
if (players[displayplayer].mo || players[displayplayer].playerstate == PST_DEAD) if (players[displayplayer].mo || players[displayplayer].playerstate == PST_DEAD)
...@@ -436,9 +439,13 @@ static void D_Display(void) ...@@ -436,9 +439,13 @@ static void D_Display(void)
lastdraw = false; lastdraw = false;
} }
ST_Drawer(); if (gamestate == GS_LEVEL)
{
HU_Drawer(); ST_Drawer();
HU_Drawer();
}
else
F_TitleScreenDrawer();
} }
// change gamma if needed // change gamma if needed
...@@ -482,8 +489,19 @@ static void D_Display(void) ...@@ -482,8 +489,19 @@ static void D_Display(void)
if (rendermode != render_none) if (rendermode != render_none)
{ {
F_WipeEndScreen(); // miru: we can use the mapheaderinfo to change the forced wipe the instant the map loads
F_RunWipe(wipedefs[wipedefindex], gamestate != GS_TIMEATTACK); if (mapheaderinfo[gamemap-1] && mapheaderinfo[gamemap-1]->postlevelwipe && mapheaderinfo[gamemap-1]->postlevelwipe < 100)
{
F_WipeStartScreen();
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, mapheaderinfo[gamemap-1]->wipecolor);
F_WipeEndScreen();
F_RunWipe(mapheaderinfo[gamemap-1]->postlevelwipe, gamestate != GS_TIMEATTACK);
}
else
{
F_WipeEndScreen();
F_RunWipe(wipedefs[wipedefindex], gamestate != GS_TIMEATTACK);
}
} }
} }
...@@ -1323,6 +1341,22 @@ void D_SRB2Main(void) ...@@ -1323,6 +1341,22 @@ void D_SRB2Main(void)
ultimatemode = true; ultimatemode = true;
} }
// rei/miru: bootmap (Idea: starts the game on a predefined map)
if (bootmap && !(M_CheckParm("-warp") && M_IsNextParm()))
{
pstartmap = bootmap;
if (pstartmap < 1 || pstartmap > NUMMAPS)
I_Error("Cannot warp to map %d (out of range)\n", pstartmap);
else
{
//if (!M_CheckParm("-server"))
//G_SetGameModified(true);
autostart = true;
}
}
//CONS_Printf("BOOT_MAP: %d\n", bootmap);
if (autostart || netgame || M_CheckParm("+connect") || M_CheckParm("-connect")) if (autostart || netgame || M_CheckParm("+connect") || M_CheckParm("-connect"))
{ {
gameaction = ga_nothing; gameaction = ga_nothing;
......
...@@ -3816,6 +3816,8 @@ static void Command_Displayplayer_f(void) ...@@ -3816,6 +3816,8 @@ static void Command_Displayplayer_f(void)
CONS_Printf(M_GetText("Displayplayer is %d\n"), displayplayer); CONS_Printf(M_GetText("Displayplayer is %d\n"), displayplayer);
} }
#include "dehacked.h"
#include "fastcmp.h"
static void Command_Tunes_f(void) static void Command_Tunes_f(void)
{ {
const char *tunearg; const char *tunearg;
......
...@@ -427,6 +427,9 @@ typedef struct player_s ...@@ -427,6 +427,9 @@ typedef struct player_s
INT32 awayviewtics; INT32 awayviewtics;
angle_t awayviewaiming; // Used for cut-away view angle_t awayviewaiming; // Used for cut-away view
// miru: let's add stuff to player struct!
angle_t viewrollangle; // Roll angle (software)
boolean spectator; boolean spectator;
UINT8 bot; UINT8 bot;
......
...@@ -1321,6 +1321,20 @@ static void readlevelheader(MYFILE *f, INT32 num) ...@@ -1321,6 +1321,20 @@ static void readlevelheader(MYFILE *f, INT32 num)
else else
mapheaderinfo[num-1]->menuflags &= ~LF2_NOVISITNEEDED; mapheaderinfo[num-1]->menuflags &= ~LF2_NOVISITNEEDED;
} }
// miru: we can build custom map header words here
else if (fastcmp(word, "LEVELWIPE"))
{
mapheaderinfo[num-1]->levelwipe = (UINT8)i;
}
else if (fastcmp(word, "POSTLEVELWIPE"))
{
mapheaderinfo[num-1]->postlevelwipe = (UINT8)i;
}
else if (fastcmp(word, "WIPECOLOR"))
{
mapheaderinfo[num-1]->wipecolor = (UINT8)i;
}
else else
deh_warning("Level header %d: unknown word '%s'", num, word); deh_warning("Level header %d: unknown word '%s'", num, word);
} }
...@@ -3004,6 +3018,25 @@ static void readmaincfg(MYFILE *f) ...@@ -3004,6 +3018,25 @@ static void readmaincfg(MYFILE *f)
DEH_WriteUndoline(word, va("%d", looptitle), UNDO_NONE); DEH_WriteUndoline(word, va("%d", looptitle), UNDO_NONE);
looptitle = (boolean)(value || word2[0] == 'T' || word2[0] == 'Y'); looptitle = (boolean)(value || word2[0] == 'T' || word2[0] == 'Y');
} }
else if (fastcmp(word, "TITLEMAP"))
{
// Support using the actual map name,
// i.e., Level AB, Level FZ, etc.
// Convert to map number
if (word2[0] >= 'A' && word2[0] <= 'Z')
value = M_MapNumber(word2[0], word2[1]);
else
value = get_number(word2);
DEH_WriteUndoline(word, va("%d", titlemap), UNDO_NONE);
titlemap = (INT16)value;
}
else if (fastcmp(word, "HIDETITLEPICS"))
{
DEH_WriteUndoline(word, va("%d", hidetitlepics), UNDO_NONE);
hidetitlepics = (boolean)(value || word2[0] == 'T' || word2[0] == 'Y');
}
else if (fastcmp(word, "TITLESCROLLSPEED")) else if (fastcmp(word, "TITLESCROLLSPEED"))
{ {
DEH_WriteUndoline(word, va("%d", titlescrollspeed), UNDO_NONE); DEH_WriteUndoline(word, va("%d", titlescrollspeed), UNDO_NONE);
...@@ -3083,6 +3116,22 @@ static void readmaincfg(MYFILE *f) ...@@ -3083,6 +3116,22 @@ static void readmaincfg(MYFILE *f)
DEH_WriteUndoline(word, customversionstring, UNDO_NONE); DEH_WriteUndoline(word, customversionstring, UNDO_NONE);
strlcpy(customversionstring, word2, sizeof (customversionstring)); strlcpy(customversionstring, word2, sizeof (customversionstring));
} }
else if (fastcmp(word, "BOOTMAP"))
{
// rei/miru: bootmap definition for maincfg
// Support using the actual map name,
// i.e., Level AB, Level FZ, etc.
// Convert to map number
if (word2[0] >= 'A' && word2[0] <= 'Z')
value = M_MapNumber(word2[0], word2[1]);
else
value = get_number(word2);
DEH_WriteUndoline(word, va("%d", bootmap), UNDO_NONE);
bootmap = (INT16)value;
}
else else
deh_warning("Maincfg: unknown word '%s'", word); deh_warning("Maincfg: unknown word '%s'", word);
} }
...@@ -6642,7 +6691,7 @@ static const char *const MOBJFLAG_LIST[] = { ...@@ -6642,7 +6691,7 @@ static const char *const MOBJFLAG_LIST[] = {
"SHOOTABLE", "SHOOTABLE",
"NOSECTOR", "NOSECTOR",
"NOBLOCKMAP", "NOBLOCKMAP",
"AMBUSH", "PAPERCOLLISION",
"PUSHABLE", "PUSHABLE",
"BOSS", "BOSS",
"SPAWNCEILING", "SPAWNCEILING",
...@@ -6700,6 +6749,7 @@ static const char *const MOBJFLAG2_LIST[] = { ...@@ -6700,6 +6749,7 @@ static const char *const MOBJFLAG2_LIST[] = {
"BOSSNOTRAP", // No Egg Trap after boss "BOSSNOTRAP", // No Egg Trap after boss
"BOSSFLEE", // Boss is fleeing! "BOSSFLEE", // Boss is fleeing!
"BOSSDEAD", // Boss is dead! (Not necessarily fleeing, if a fleeing point doesn't exist.) "BOSSDEAD", // Boss is dead! (Not necessarily fleeing, if a fleeing point doesn't exist.)
"AMBUSH", // Alternate behaviour typically set by MTF_AMBUSH
NULL NULL
}; };
...@@ -6992,6 +7042,7 @@ struct { ...@@ -6992,6 +7042,7 @@ struct {
// Frame settings // Frame settings
{"FF_FRAMEMASK",FF_FRAMEMASK}, {"FF_FRAMEMASK",FF_FRAMEMASK},
{"FF_PAPERSPRITE",FF_PAPERSPRITE},
{"FF_ANIMATE",FF_ANIMATE}, {"FF_ANIMATE",FF_ANIMATE},
{"FF_FULLBRIGHT",FF_FULLBRIGHT}, {"FF_FULLBRIGHT",FF_FULLBRIGHT},
{"FF_TRANSMASK",FF_TRANSMASK}, {"FF_TRANSMASK",FF_TRANSMASK},
......
...@@ -149,10 +149,10 @@ extern FILE *logstream; ...@@ -149,10 +149,10 @@ extern FILE *logstream;
// most interface strings are ignored in development mode. // most interface strings are ignored in development mode.
// we use comprevision and compbranch instead. // we use comprevision and compbranch instead.
#else #else
#define VERSION 201 // Game version #define VERSION 100 // Game version
#define SUBVERSION 17 // more precise version number #define SUBVERSION 0 // more precise version number
#define VERSIONSTRING "v2.1.17" #define VERSIONSTRING "PlusC v1.0"
#define VERSIONSTRINGW L"v2.1.17" #define VERSIONSTRINGW L"PlusC v1.0"
// Hey! If you change this, add 1 to the MODVERSION below! // Hey! If you change this, add 1 to the MODVERSION below!
// Otherwise we can't force updates! // Otherwise we can't force updates!
#endif #endif
...@@ -208,13 +208,13 @@ extern FILE *logstream; ...@@ -208,13 +208,13 @@ extern FILE *logstream;
// The Modification ID; must be obtained from Inuyasha ( http://mb.srb2.org/private.php?do=newpm&u=2604 ). // The Modification ID; must be obtained from Inuyasha ( http://mb.srb2.org/private.php?do=newpm&u=2604 ).
// DO NOT try to set this otherwise, or your modification will be unplayable through the Master Server. // DO NOT try to set this otherwise, or your modification will be unplayable through the Master Server.
// "12" is the default mod ID for version 2.1 // "12" is the default mod ID for version 2.1
#define MODID 12 #define MODID 15
// The Modification Version, starting from 1. Do not follow your version string for this, // The Modification Version, starting from 1. Do not follow your version string for this,
// it's only for detection of the version the player is using so the MS can alert them of an update. // it's only for detection of the version the player is using so the MS can alert them of an update.
// Only set it higher, not lower, obviously. // Only set it higher, not lower, obviously.
// Note that we use this to help keep internal testing in check; this is why v2.1.0 is not version "1". // Note that we use this to help keep internal testing in check; this is why v2.1.0 is not version "1".
#define MODVERSION 22 #define MODVERSION 1
// ========================================================================= // =========================================================================
......
...@@ -124,6 +124,12 @@ extern INT16 spstage_start; ...@@ -124,6 +124,12 @@ extern INT16 spstage_start;
extern INT16 sstage_start; extern INT16 sstage_start;
extern INT16 sstage_end; extern INT16 sstage_end;
extern INT16 bootmap; // rei/miru: bootmap for loading a map on startup (skips intro+title)
//extern INT16 returnTobootmap; // rei/miru: return to bootmap when attempting to go to the REAL title?
extern INT16 titlemap;
extern boolean hidetitlepics;
extern boolean looptitle; extern boolean looptitle;
extern boolean useNightsSS; extern boolean useNightsSS;
...@@ -245,6 +251,11 @@ typedef struct ...@@ -245,6 +251,11 @@ typedef struct
UINT8 numGradedMares; ///< Internal. For grade support. UINT8 numGradedMares; ///< Internal. For grade support.
nightsgrades_t *grades; ///< NiGHTS grades. Allocated dynamically for space reasons. Be careful. nightsgrades_t *grades; ///< NiGHTS grades. Allocated dynamically for space reasons. Be careful.
// miru: to use custom mapheaderinfo options, we need to add them to the struct first
UINT8 levelwipe;
UINT8 postlevelwipe;
UINT8 wipecolor;
// Lua stuff. // Lua stuff.
// (This is not ifdeffed so the map header structure can stay identical, just in case.) // (This is not ifdeffed so the map header structure can stay identical, just in case.)
UINT8 numCustomOptions; ///< Internal. For Lua custom value support. UINT8 numCustomOptions; ///< Internal. For Lua custom value support.
......
...@@ -259,7 +259,10 @@ typedef enum ...@@ -259,7 +259,10 @@ typedef enum
postimg_water, postimg_water,
postimg_motion, postimg_motion,
postimg_flip, postimg_flip,
postimg_heat postimg_heat,
// miru: more postimg definitions
postimg_roll
} postimg_t; } postimg_t;
typedef UINT32 lumpnum_t; // 16 : 16 unsigned long (wad num: lump num) typedef UINT32 lumpnum_t; // 16 : 16 unsigned long (wad num: lump num)
......
...@@ -31,11 +31,14 @@ ...@@ -31,11 +31,14 @@
#include "m_random.h" #include "m_random.h"
#include "y_inter.h" #include "y_inter.h"
#include "m_cond.h" #include "m_cond.h"
#include "p_local.h"
#include "p_setup.h"
// Stage of animation: // Stage of animation:
// 0 = text, 1 = art screen // 0 = text, 1 = art screen
static INT32 finalecount; static INT32 finalecount;
INT32 titlescrollspeed = 80; INT32 titlescrollspeed = 80;
boolean titlemapinaction = false;
static INT32 timetonext; // Delay between screen changes static INT32 timetonext; // Delay between screen changes
static INT32 continuetime; // Short delay when continuing static INT32 continuetime; // Short delay when continuing
...@@ -999,7 +1002,7 @@ static const char *credits[] = { ...@@ -999,7 +1002,7 @@ static const char *credits[] = {
"", "",
"\1Sprite Artists", "\1Sprite Artists",
"Odi \"Iceman404\" Atunzu", "Odi \"Iceman404\" Atunzu",
"Victor \"VAdaPEGA\" Ara\x1Fjo", // Arajo -- sorry for our limited font! D: "Victor \"VAdaPEGA\" Ara\x1Fjo", // Araújo -- sorry for our limited font! D:
"Jim \"MotorRoach\" DeMello", "Jim \"MotorRoach\" DeMello",
"Desmond \"Blade\" DesJardins", "Desmond \"Blade\" DesJardins",
"Sherman \"CoatRack\" DesJardins", "Sherman \"CoatRack\" DesJardins",
...@@ -1421,13 +1424,32 @@ void F_StartTitleScreen(void) ...@@ -1421,13 +1424,32 @@ void F_StartTitleScreen(void)
finalecount = 0; finalecount = 0;
else else
wipegamestate = GS_TITLESCREEN; wipegamestate = GS_TITLESCREEN;
if (titlemap)
{
titlemapinaction = true;
gamemap = titlemap;
if (!mapheaderinfo[gamemap-1])
P_AllocMapHeader(gamemap-1);
G_DoLoadLevel(true);
players[displayplayer].playerstate = PST_DEAD; // Don't spawn the player in dummy (I'm still a filthy cheater)
camera.subsector = NULL; // toast is filthy too
//CON_ClearHUD();
}
else
{
titlemapinaction = false;
gamemap = 1; // g_game.c
CON_ClearHUD();
}
G_SetGamestate(GS_TITLESCREEN); G_SetGamestate(GS_TITLESCREEN);
CON_ClearHUD();
// IWAD dependent stuff. // IWAD dependent stuff.
S_ChangeMusicInternal("titles", looptitle); S_ChangeMusicInternal("titles", looptitle);
animtimer = 0; animtimer = 0;
demoDelayLeft = demoDelayTime; demoDelayLeft = demoDelayTime;
...@@ -1457,12 +1479,17 @@ void F_TitleScreenDrawer(void) ...@@ -1457,12 +1479,17 @@ void F_TitleScreenDrawer(void)
return; // We likely came here from retrying. Don't do a damn thing. return; // We likely came here from retrying. Don't do a damn thing.
// Draw that sky! // Draw that sky!
F_SkyScroll(titlescrollspeed); if (!titlemapinaction)
F_SkyScroll(titlescrollspeed);
// Don't draw outside of the title screewn, or if the patch isn't there. // Don't draw outside of the title screewn, or if the patch isn't there.
if (!ttwing || (gamestate != GS_TITLESCREEN && gamestate != GS_WAITINGPLAYERS)) if (!ttwing || (gamestate != GS_TITLESCREEN && gamestate != GS_WAITINGPLAYERS))
return; return;
// rei|miru: use title pics?
if (hidetitlepics)
return;
V_DrawScaledPatch(30, 14, 0, ttwing); V_DrawScaledPatch(30, 14, 0, ttwing);
if (finalecount < 57) if (finalecount < 57)
...@@ -1511,6 +1538,13 @@ void F_TitleScreenTicker(boolean run) ...@@ -1511,6 +1538,13 @@ void F_TitleScreenTicker(boolean run)
if (gameaction != ga_nothing || gamestate != GS_TITLESCREEN) if (gameaction != ga_nothing || gamestate != GS_TITLESCREEN)
return; return;
// Do a lil' camera spin if a title map is loaded.
if (titlemapinaction) {
camera.x = camera.y = camera.height = camera.aiming = 0;
camera.z = 128*FRACUNIT;
camera.angle += titlescrollspeed;
}
// no demos to play? or, are they disabled? // no demos to play? or, are they disabled?
if (!cv_rollingdemos.value || !numDemos) if (!cv_rollingdemos.value || !numDemos)
return; return;
......
...@@ -61,6 +61,7 @@ void F_ContinueTicker(void); ...@@ -61,6 +61,7 @@ void F_ContinueTicker(void);
void F_ContinueDrawer(void); void F_ContinueDrawer(void);
extern INT32 titlescrollspeed; extern INT32 titlescrollspeed;
extern boolean titlemapinaction;
// //
// WIPE // WIPE
......
...@@ -119,6 +119,12 @@ INT16 spstage_start; ...@@ -119,6 +119,12 @@ INT16 spstage_start;
INT16 sstage_start; INT16 sstage_start;
INT16 sstage_end; INT16 sstage_end;
INT16 bootmap; // rei/miru: bootmap for loading a map on startup (skips intro+title)
//INT16 returnTobootmap; // rei/miru: return to bootmap when attempting to go to the REAL title?
INT16 titlemap = 0;
boolean hidetitlepics = false;
boolean looptitle = false; boolean looptitle = false;
boolean useNightsSS = false; boolean useNightsSS = false;
...@@ -1984,6 +1990,7 @@ void G_Ticker(boolean run) ...@@ -1984,6 +1990,7 @@ void G_Ticker(boolean run)
break; break;
case GS_TITLESCREEN: case GS_TITLESCREEN:
if (titlemapinaction) P_Ticker(run); // then intentionally fall through
case GS_WAITINGPLAYERS: case GS_WAITINGPLAYERS:
F_TitleScreenTicker(run); F_TitleScreenTicker(run);
break; break;
...@@ -5674,3 +5681,48 @@ INT32 G_TicsToMilliseconds(tic_t tics) ...@@ -5674,3 +5681,48 @@ INT32 G_TicsToMilliseconds(tic_t tics)
return (INT32)((tics%TICRATE) * (1000.00f/TICRATE)); return (INT32)((tics%TICRATE) * (1000.00f/TICRATE));
} }
//miru: change the displayed player
// player - player to forward the function to
// displayNumber - the player number (node) to view
// setAllDisplays - set all displays to the player number/node specified
void G_SetDisplayPlayer(player_t *player, INT32 displayNumber, boolean setAllDisplays)
{
//TODO: fix black flashes when touching controls (this has to do with
//((cmd->forwardmove || cmd->sidemove || cmd->buttons) && displayplayer != consoleplayer) )
//TODO: proper implementation for using player node instead of -1 (unsure how)
if (gamestate == GS_LEVEL)
{
// no, not for non-sp
if (!netgame)
displayplayer = consoleplayer;
else
{
// the player has to exist or you just get a bleeding display
if (playeringame[displayNumber] || (players[displayplayer].spectator && player == &players[displayplayer]))
{
// switch the display number locally
if (P_IsLocalPlayer(player) && displayplayer == consoleplayer)
{
displayplayer = displayNumber;
}
// or force all
else if (setAllDisplays == true)
{
displayplayer = displayNumber;
}
// tell who's the view
//CONS_Printf(M_GetText("Viewpoint: %s\n"), player_names[displayplayer]);
}
// Setting as -1 resets your view to normal
else if (displayNumber == -1 && P_IsLocalPlayer(player)
&& displayplayer != consoleplayer)
displayplayer = consoleplayer;
else
{
// or do...nothing
//CONS_Printf("Player doesn't exist (or viewing self).\n");
}
}
}
}
...@@ -216,4 +216,6 @@ FUNCMATH INT32 G_TicsToMilliseconds(tic_t tics); ...@@ -216,4 +216,6 @@ FUNCMATH INT32 G_TicsToMilliseconds(tic_t tics);
// Don't split up TOL handling // Don't split up TOL handling
INT16 G_TOLFlag(INT32 pgametype); INT16 G_TOLFlag(INT32 pgametype);
void G_SetDisplayPlayer(player_t *player, INT32 displayNumber, boolean setAllDisplays);
#endif #endif
...@@ -762,8 +762,10 @@ void HWR_WallLighting(FOutVector *wlVerts) ...@@ -762,8 +762,10 @@ void HWR_WallLighting(FOutVector *wlVerts)
#ifdef DL_HIGH_QUALITY #ifdef DL_HIGH_QUALITY
Surf.FlatColor.s.alpha = (UINT8)((1-dist_p2d/DL_SQRRADIUS(j))*Surf.FlatColor.s.alpha); Surf.FlatColor.s.alpha = (UINT8)((1-dist_p2d/DL_SQRRADIUS(j))*Surf.FlatColor.s.alpha);
#endif #endif
if ((!dynlights->mo[j]) || (dynlights->mo[j]->thinker.function.acp1 != (actionf_p1)P_MobjThinker))
continue;
if (!dynlights->mo[j]->state) if (!dynlights->mo[j]->state)
return; continue;
// next state is null so fade out with alpha // next state is null so fade out with alpha
if (dynlights->mo[j]->state->nextstate == S_NULL) if (dynlights->mo[j]->state->nextstate == S_NULL)
Surf.FlatColor.s.alpha = (UINT8)(((float)dynlights->mo[j]->tics/(float)dynlights->mo[j]->state->tics)*Surf.FlatColor.s.alpha); Surf.FlatColor.s.alpha = (UINT8)(((float)dynlights->mo[j]->tics/(float)dynlights->mo[j]->state->tics)*Surf.FlatColor.s.alpha);
...@@ -825,8 +827,10 @@ void HWR_PlaneLighting(FOutVector *clVerts, int nrClipVerts) ...@@ -825,8 +827,10 @@ void HWR_PlaneLighting(FOutVector *clVerts, int nrClipVerts)
#ifdef DL_HIGH_QUALITY #ifdef DL_HIGH_QUALITY
Surf.FlatColor.s.alpha = (unsigned char)((1 - dist_p2d/DL_SQRRADIUS(j))*Surf.FlatColor.s.alpha); Surf.FlatColor.s.alpha = (unsigned char)((1 - dist_p2d/DL_SQRRADIUS(j))*Surf.FlatColor.s.alpha);
#endif #endif
if ((!dynlights->mo[j]) || (dynlights->mo[j]->thinker.function.acp1 != (actionf_p1)P_MobjThinker))
continue;
if (!dynlights->mo[j]->state) if (!dynlights->mo[j]->state)
return; continue;
// next state is null so fade out with alpha // next state is null so fade out with alpha
if ((dynlights->mo[j]->state->nextstate == S_NULL)) if ((dynlights->mo[j]->state->nextstate == S_NULL))
Surf.FlatColor.s.alpha = (unsigned char)(((float)dynlights->mo[j]->tics/(float)dynlights->mo[j]->state->tics)*Surf.FlatColor.s.alpha); Surf.FlatColor.s.alpha = (unsigned char)(((float)dynlights->mo[j]->tics/(float)dynlights->mo[j]->state->tics)*Surf.FlatColor.s.alpha);
...@@ -1232,12 +1236,37 @@ static void HWR_CheckSubsector(size_t num, fixed_t *bbox) ...@@ -1232,12 +1236,37 @@ static void HWR_CheckSubsector(size_t num, fixed_t *bbox)
} }
//Hurdler: The goal of this function is to walk through all the bsp starting
// on the top.
// We need to do that to know all the lights in the map and all the walls
static void HWR_ComputeLightMapsInBSPNode(int bspnum, fixed_t *bbox)
{
if (bspnum & NF_SUBSECTOR) // Found a subsector?
{
if (bspnum == -1)
HWR_CheckSubsector(0, bbox); // probably unecessary: see boris' comment in hw_bsp
else
HWR_CheckSubsector(bspnum&(~NF_SUBSECTOR), bbox);
return;
}
HWR_ComputeLightMapsInBSPNode(nodes[bspnum].children[0], nodes[bspnum].bbox[0]);
HWR_ComputeLightMapsInBSPNode(nodes[bspnum].children[1], nodes[bspnum].bbox[1]);
}
#endif
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
// Hurdler: this adds lights by mobj. // Hurdler: this adds lights by mobj.
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
static void HWR_AddMobjLights(mobj_t *thing) static void HWR_AddMobjLights(mobj_t *thing)
{ {
if (t_lspr[thing->sprite]->type & CORONA_SPR) if (!cv_drawdist.value || P_AproxDistance(thing->x-viewx, thing->y-viewy) < cv_drawdist.value*FRACUNIT)
if (!(thing->flags2 & MF2_DEBRIS) && (thing->sprite != SPR_PLAY ||
(thing->player && thing->player->powers[pw_super])))
if ((t_lspr[thing->sprite]->type&DYNLIGHT_SPR)
&& ((t_lspr[thing->sprite]->type != LIGHT_SPR) || cv_grstaticlighting.value)
&& (dynlights->nb < DL_MAX_LIGHT)
&& thing->state)
{ {
LIGHT_POS(dynlights->nb).x = FIXED_TO_FLOAT(thing->x); LIGHT_POS(dynlights->nb).x = FIXED_TO_FLOAT(thing->x);
LIGHT_POS(dynlights->nb).y = FIXED_TO_FLOAT(thing->z) + t_lspr[thing->sprite]->light_yoffset; LIGHT_POS(dynlights->nb).y = FIXED_TO_FLOAT(thing->z) + t_lspr[thing->sprite]->light_yoffset;
...@@ -1245,30 +1274,15 @@ static void HWR_AddMobjLights(mobj_t *thing) ...@@ -1245,30 +1274,15 @@ static void HWR_AddMobjLights(mobj_t *thing)
dynlights->p_lspr[dynlights->nb] = t_lspr[thing->sprite]; dynlights->p_lspr[dynlights->nb] = t_lspr[thing->sprite];
P_SetTarget(&dynlights->mo[dynlights->nb], thing);
dynlights->nb++; dynlights->nb++;
if (dynlights->nb > DL_MAX_LIGHT) if (dynlights->nb > DL_MAX_LIGHT)
dynlights->nb = DL_MAX_LIGHT; dynlights->nb = DL_MAX_LIGHT;
} }
} }
//Hurdler: The goal of this function is to walk through all the bsp starting void HWR_SearchLightsInMobjs(void)
// on the top.
// We need to do that to know all the lights in the map and all the walls
static void HWR_ComputeLightMapsInBSPNode(int bspnum, fixed_t *bbox)
{
if (bspnum & NF_SUBSECTOR) // Found a subsector?
{
if (bspnum == -1)
HWR_CheckSubsector(0, bbox); // probably unecessary: see boris' comment in hw_bsp
else
HWR_CheckSubsector(bspnum&(~NF_SUBSECTOR), bbox);
return;
}
HWR_ComputeLightMapsInBSPNode(nodes[bspnum].children[0], nodes[bspnum].bbox[0]);
HWR_ComputeLightMapsInBSPNode(nodes[bspnum].children[1], nodes[bspnum].bbox[1]);
}
static void HWR_SearchLightsInMobjs(void)
{ {
thinker_t * th; thinker_t * th;
//mobj_t * mobj; //mobj_t * mobj;
...@@ -1279,9 +1293,15 @@ static void HWR_SearchLightsInMobjs(void) ...@@ -1279,9 +1293,15 @@ static void HWR_SearchLightsInMobjs(void)
// a mobj ? // a mobj ?
if (th->function.acp1 == (actionf_p1)P_MobjThinker) if (th->function.acp1 == (actionf_p1)P_MobjThinker)
HWR_AddMobjLights((mobj_t *)th); HWR_AddMobjLights((mobj_t *)th);
if (dynlights->nb == DL_MAX_LIGHT)
{
CONS_Printf("light limit exceeded\n");
return;
}
} }
} }
#endif
// //
// HWR_CreateStaticLightmaps() // HWR_CreateStaticLightmaps()
......
...@@ -36,6 +36,8 @@ void HWR_WallLighting(FOutVector *wlVerts); ...@@ -36,6 +36,8 @@ void HWR_WallLighting(FOutVector *wlVerts);
void HWR_ResetLights(void); void HWR_ResetLights(void);
void HWR_SetLights(int viewnumber); void HWR_SetLights(int viewnumber);
void HWR_SearchLightsInMobjs(void);
#ifdef NEWCORONAS #ifdef NEWCORONAS
void HWR_DrawCoronas(void); void HWR_DrawCoronas(void);
#else #else
......
...@@ -4246,7 +4246,7 @@ static void HWR_DrawSprite(gr_vissprite_t *spr) ...@@ -4246,7 +4246,7 @@ static void HWR_DrawSprite(gr_vissprite_t *spr)
gpatch = W_CachePatchNum(spr->patchlumpnum, PU_CACHE); gpatch = W_CachePatchNum(spr->patchlumpnum, PU_CACHE);
#ifdef ALAM_LIGHTING #if 0 //#ifdef ALAM_LIGHTING
if (!(spr->mobj->flags2 & MF2_DEBRIS) && (spr->mobj->sprite != SPR_PLAY || if (!(spr->mobj->flags2 & MF2_DEBRIS) && (spr->mobj->sprite != SPR_PLAY ||
(spr->mobj->player && spr->mobj->player->powers[pw_super]))) (spr->mobj->player && spr->mobj->player->powers[pw_super])))
HWR_DL_AddLight(spr, gpatch); HWR_DL_AddLight(spr, gpatch);
...@@ -5107,6 +5107,7 @@ static void HWR_ProjectSprite(mobj_t *thing) ...@@ -5107,6 +5107,7 @@ static void HWR_ProjectSprite(mobj_t *thing)
rot = thing->frame&FF_FRAMEMASK; rot = thing->frame&FF_FRAMEMASK;
thing->state->sprite = thing->sprite; thing->state->sprite = thing->sprite;
thing->state->frame = thing->frame; thing->state->frame = thing->frame;
sprdef = &sprites[thing->sprite]; //Yellow: sprdef now updates rotations to fix the crash
} }
sprframe = &sprdef->spriteframes[rot]; sprframe = &sprdef->spriteframes[rot];
...@@ -5116,22 +5117,29 @@ static void HWR_ProjectSprite(mobj_t *thing) ...@@ -5116,22 +5117,29 @@ static void HWR_ProjectSprite(mobj_t *thing)
I_Error("sprframes NULL for sprite %d\n", thing->sprite); I_Error("sprframes NULL for sprite %d\n", thing->sprite);
#endif #endif
if (sprframe->rotate) if (sprframe->rotate == SRF_SINGLE)
{
// choose a different rotation based on player view
ang = R_PointToAngle(thing->x, thing->y); // uses viewx,viewy
rot = (ang-thing->angle+ANGLE_202h)>>29;
//Fab: lumpid is the index for spritewidth,spriteoffset... tables
lumpoff = sprframe->lumpid[rot];
flip = sprframe->flip & (1<<rot);
}
else
{ {
// use single rotation for all views // use single rotation for all views
rot = 0; //Fab: for vis->patch below rot = 0; //Fab: for vis->patch below
lumpoff = sprframe->lumpid[0]; //Fab: see note above lumpoff = sprframe->lumpid[0]; //Fab: see note above
flip = sprframe->flip; // Will only be 0x00 or 0xFF flip = sprframe->flip; // Will only be 0x00 or 0xFF
} }
else
{
// choose a different rotation based on player view
ang = R_PointToAngle (thing->x, thing->y) - thing->angle;
if ((ang < ANGLE_180) && (sprframe->rotate & SRF_RIGHT)) // See from right
rot = 6; // F7 slot
else if ((ang >= ANGLE_180) && (sprframe->rotate & SRF_LEFT)) // See from left
rot = 2; // F3 slot
else // Normal behaviour
rot = (ang+ANGLE_202h)>>29;
//Fab: lumpid is the index for spritewidth,spriteoffset... tables
lumpoff = sprframe->lumpid[rot];
flip = sprframe->flip & (1<<rot);
}
if (thing->skin && ((skin_t *)thing->skin)->flags & SF_HIRES) if (thing->skin && ((skin_t *)thing->skin)->flags & SF_HIRES)
this_scale = this_scale * FIXED_TO_FLOAT(((skin_t *)thing->skin)->highresscale); this_scale = this_scale * FIXED_TO_FLOAT(((skin_t *)thing->skin)->highresscale);
...@@ -5599,6 +5607,12 @@ if (0) ...@@ -5599,6 +5607,12 @@ if (0)
validcount++; validcount++;
#ifdef ALAM_LIGHTING
//14/11/99: Hurdler: moved here because it doesn't work with
// subsector, see other comments;
HWR_ResetLights();
HWR_SearchLightsInMobjs();
#endif
HWR_RenderBSPNode((INT32)numnodes-1); HWR_RenderBSPNode((INT32)numnodes-1);
// Make a viewangle int so we can render things based on mouselook // Make a viewangle int so we can render things based on mouselook
...@@ -5634,7 +5648,7 @@ if (0) ...@@ -5634,7 +5648,7 @@ if (0)
#ifdef ALAM_LIGHTING #ifdef ALAM_LIGHTING
//14/11/99: Hurdler: moved here because it doesn't work with //14/11/99: Hurdler: moved here because it doesn't work with
// subsector, see other comments; // subsector, see other comments;
HWR_ResetLights(); //HWR_ResetLights();
#endif #endif
// Draw MD2 and sprites // Draw MD2 and sprites
...@@ -5829,6 +5843,13 @@ if (0) ...@@ -5829,6 +5843,13 @@ if (0)
validcount++; validcount++;
#ifdef ALAM_LIGHTING
//14/11/99: Hurdler: moved here because it doesn't work with
// subsector, see other comments;
HWR_ResetLights();
HWR_SearchLightsInMobjs();
#endif
HWR_RenderBSPNode((INT32)numnodes-1); HWR_RenderBSPNode((INT32)numnodes-1);
// Make a viewangle int so we can render things based on mouselook // Make a viewangle int so we can render things based on mouselook
...@@ -5861,12 +5882,6 @@ if (0) ...@@ -5861,12 +5882,6 @@ if (0)
// Check for new console commands. // Check for new console commands.
NetUpdate(); NetUpdate();
#ifdef ALAM_LIGHTING
//14/11/99: Hurdler: moved here because it doesn't work with
// subsector, see other comments;
HWR_ResetLights();
#endif
// Draw MD2 and sprites // Draw MD2 and sprites
#ifdef SORTING #ifdef SORTING
HWR_SortVisSprites(); HWR_SortVisSprites();
......