diff --git a/src/d_clisrv.h b/src/d_clisrv.h
index a906758f..dd1aaf4e 100644
--- a/src/d_clisrv.h
+++ b/src/d_clisrv.h
@@ -429,9 +429,9 @@ extern doomdata_t *netbuffer;
extern consvar_t cv_playbackspeed;
-#define BASEPACKETSIZE ((size_t)&(((doomdata_t *)0)->u))
-#define FILETXHEADER ((size_t)((filetx_pak *)0)->data)
-#define BASESERVERTICSSIZE ((size_t)&(((doomdata_t *)0)->u.serverpak.cmds[0]))
+#define BASEPACKETSIZE offsetof(doomdata_t, u)
+#define FILETXHEADER offsetof(filetx_pak, data)
+#define BASESERVERTICSSIZE offsetof(doomdata_t, u.serverpak.cmds[0])
#define KICK_MSG_GO_AWAY 1
#define KICK_MSG_CON_FAIL 2
diff --git a/src/d_netcmd.c b/src/d_netcmd.c
index 2e2a2d2a..9adba8e7 100644
--- a/src/d_netcmd.c
+++ b/src/d_netcmd.c
@@ -697,6 +697,10 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_moveaxis2);
CV_RegisterVar(&cv_lookaxis);
CV_RegisterVar(&cv_lookaxis2);
+ CV_RegisterVar(&cv_jumpaxis);
+ CV_RegisterVar(&cv_jumpaxis2);
+ CV_RegisterVar(&cv_spinaxis);
+ CV_RegisterVar(&cv_spinaxis2);
CV_RegisterVar(&cv_fireaxis);
CV_RegisterVar(&cv_fireaxis2);
CV_RegisterVar(&cv_firenaxis);
diff --git a/src/dehacked.c b/src/dehacked.c
index 333c6ceb..3972cd17 100644
--- a/src/dehacked.c
+++ b/src/dehacked.c
@@ -1248,6 +1248,18 @@ static void readlevelheader(MYFILE *f, INT32 num)
deh_warning("Level header %d: invalid bonus type number %d", num, i);
}
+ else if (fastcmp(word, "SAVEOVERRIDE"))
+ {
+ if (fastcmp(word2, "DEFAULT")) i = SAVE_DEFAULT;
+ else if (fastcmp(word2, "ALWAYS")) i = SAVE_ALWAYS;
+ else if (fastcmp(word2, "NEVER")) i = SAVE_NEVER;
+
+ if (i >= SAVE_NEVER && i <= SAVE_ALWAYS)
+ mapheaderinfo[num-1]->saveoverride = (SINT8)i;
+ else
+ deh_warning("Level header %d: invalid save override number %d", num, i);
+ }
+
else if (fastcmp(word, "LEVELFLAGS"))
mapheaderinfo[num-1]->levelflags = (UINT8)i;
else if (fastcmp(word, "MENUFLAGS"))
@@ -7074,6 +7086,11 @@ struct {
{"LF2_NIGHTSATTACK",LF2_NIGHTSATTACK},
{"LF2_NOVISITNEEDED",LF2_NOVISITNEEDED},
+ // Save override
+ {"SAVE_NEVER",SAVE_NEVER},
+ {"SAVE_DEFAULT",SAVE_DEFAULT},
+ {"SAVE_ALWAYS",SAVE_ALWAYS},
+
// NiGHTS grades
{"GRADE_F",GRADE_F},
{"GRADE_E",GRADE_E},
diff --git a/src/doomstat.h b/src/doomstat.h
index 7b4aa264..d37ae440 100644
--- a/src/doomstat.h
+++ b/src/doomstat.h
@@ -234,6 +234,7 @@ typedef struct
SINT8 unlockrequired; ///< Is an unlockable required to play this level? -1 if no.
UINT8 levelselect; ///< Is this map available in the level select? If so, which map list is it available in?
SINT8 bonustype; ///< What type of bonus does this level have? (-1 for null.)
+ SINT8 saveoverride; ///< Set how the game is allowed to save (1 for always, -1 for never, 0 is 2.1 default)
UINT8 levelflags; ///< LF_flags: merged eight booleans into one UINT8 for space, see below
UINT8 menuflags; ///< LF2_flags: options that affect record attack / nights mode menus
@@ -261,6 +262,11 @@ typedef struct
#define LF2_NIGHTSATTACK 8 ///< Show this map in NiGHTS mode menu
#define LF2_NOVISITNEEDED 16 ///< Available in time attack/nights mode without visiting the level
+// Save override
+#define SAVE_NEVER -1
+#define SAVE_DEFAULT 0
+#define SAVE_ALWAYS 1
+
extern mapheader_t* mapheaderinfo[NUMMAPS];
enum TypeOfLevel
diff --git a/src/f_finale.c b/src/f_finale.c
index 484a0afe..fa6d6dba 100644
--- a/src/f_finale.c
+++ b/src/f_finale.c
@@ -1082,11 +1082,14 @@ static const char *credits[] = {
"Bill \"Tets\" Reed",
"",
"\1Special Thanks",
- "Doom Legacy Project",
"iD Software",
- "Alex \"MistaED\" Fuller",
+ "Doom Legacy Project",
"FreeDoom Project", // Used some of the mancubus and rocket launcher sprites for Brak
+ "Alex \"MistaED\" Fuller",
+ "Pascal \"CodeImp\" vd Heiden", // Doom Builder developer
"Randi Heit ()", // For their MSPaint sprite that we nicked
+ "Simon \"sirjuddington\" Judd", // SLADE developer
+
"",
"\1Produced By",
"Sonic Team Junior",
diff --git a/src/g_game.c b/src/g_game.c
index 2f2ac043..93e7c15a 100644
--- a/src/g_game.c
+++ b/src/g_game.c
@@ -406,6 +406,8 @@ typedef enum
AXISLOOK,
AXISSTRAFE,
AXISDEAD, //Axises that don't want deadzones
+ AXISJUMP,
+ AXISSPIN,
AXISFIRE,
AXISFIRENORMAL,
} axis_input_e;
@@ -415,6 +417,8 @@ consvar_t cv_turnaxis = {"joyaxis_turn", "LStick.X", CV_SAVE, joyaxis_cons_t, NU
consvar_t cv_moveaxis = {"joyaxis_move", "LStick.Y", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_sideaxis = {"joyaxis_side", "RStick.X", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_lookaxis = {"joyaxis_look", "RStick.Y", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
+consvar_t cv_jumpaxis = {"joyaxis_jump", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
+consvar_t cv_spinaxis = {"joyaxis_spin", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_fireaxis = {"joyaxis_fire", "LAnalog", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_firenaxis = {"joyaxis_firenormal", "RAnalog", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
#else
@@ -441,6 +445,8 @@ consvar_t cv_lookaxis = {"joyaxis_look", "Y-Axis", CV_SAVE, joyaxis_cons_t, NULL
consvar_t cv_lookaxis = {"joyaxis_look", "Y-Rudder-", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
#endif
#endif
+consvar_t cv_jumpaxis = {"joyaxis_jump", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
+consvar_t cv_spinaxis = {"joyaxis_spin", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_fireaxis = {"joyaxis_fire", "Z-Axis-", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_firenaxis = {"joyaxis_firenormal", "Z-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
#endif
@@ -450,6 +456,8 @@ consvar_t cv_turnaxis2 = {"joyaxis2_turn", "LStick.X", CV_SAVE, joyaxis_cons_t,
consvar_t cv_moveaxis2 = {"joyaxis2_move", "LStick.Y", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_sideaxis2 = {"joyaxis2_side", "RStick.X", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_lookaxis2 = {"joyaxis2_look", "RStick.Y", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
+consvar_t cv_jumpaxis2 = {"joyaxis2_jump", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
+consvar_t cv_spinaxis2 = {"joyaxis2_spin", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_fireaxis2 = {"joyaxis2_fire", "LAnalog", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_firenaxis2 = {"joyaxis2_firenormal", "RAnalog", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
#else
@@ -468,6 +476,8 @@ consvar_t cv_sideaxis2 = {"joyaxis2_side", "X-Axis", CV_SAVE, joyaxis_cons_t, NU
#ifndef _XBOX
consvar_t cv_lookaxis2 = {"joyaxis2_look", "Y-Rudder-", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
#endif
+consvar_t cv_jumpaxis2 = {"joyaxis2_jump", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
+consvar_t cv_spinaxis2 = {"joyaxis2_spin", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_fireaxis2 = {"joyaxis2_fire", "Z-Axis-", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_firenaxis2 = {"joyaxis2_firenormal", "Z-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
#endif
@@ -835,6 +845,12 @@ static INT32 JoyAxis(axis_input_e axissel)
case AXISSTRAFE:
axisval = cv_sideaxis.value;
break;
+ case AXISJUMP:
+ axisval = cv_jumpaxis.value;
+ break;
+ case AXISSPIN:
+ axisval = cv_spinaxis.value;
+ break;
case AXISFIRE:
axisval = cv_fireaxis.value;
break;
@@ -912,6 +928,12 @@ static INT32 Joy2Axis(axis_input_e axissel)
case AXISSTRAFE:
axisval = cv_sideaxis2.value;
break;
+ case AXISJUMP:
+ axisval = cv_jumpaxis2.value;
+ break;
+ case AXISSPIN:
+ axisval = cv_spinaxis2.value;
+ break;
case AXISFIRE:
axisval = cv_fireaxis2.value;
break;
@@ -1157,7 +1179,8 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics)
cmd->buttons |= BT_CUSTOM3;
// use with any button/key
- if (PLAYER1INPUTDOWN(gc_use))
+ axis = JoyAxis(AXISSPIN);
+ if (PLAYER1INPUTDOWN(gc_use) || (cv_usejoystick.value && axis > 0))
cmd->buttons |= BT_USE;
// Camera Controls
@@ -1179,7 +1202,8 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics)
resetdown = false;
// jump button
- if (PLAYER1INPUTDOWN(gc_jump))
+ axis = JoyAxis(AXISJUMP);
+ if (PLAYER1INPUTDOWN(gc_jump) || (cv_usejoystick.value && axis > 0))
cmd->buttons |= BT_JUMP;
// player aiming shit, ahhhh...
@@ -1454,7 +1478,8 @@ void G_BuildTiccmd2(ticcmd_t *cmd, INT32 realtics)
cmd->buttons |= BT_CUSTOM3;
// use with any button/key
- if (PLAYER2INPUTDOWN(gc_use))
+ axis = Joy2Axis(AXISSPIN);
+ if (PLAYER2INPUTDOWN(gc_use) || (cv_usejoystick2.value && axis > 0))
cmd->buttons |= BT_USE;
// Camera Controls
@@ -1476,7 +1501,8 @@ void G_BuildTiccmd2(ticcmd_t *cmd, INT32 realtics)
resetdown = false;
// jump button
- if (PLAYER2INPUTDOWN(gc_jump))
+ axis = Joy2Axis(AXISJUMP);
+ if (PLAYER2INPUTDOWN(gc_jump) || (cv_usejoystick2.value && axis > 0))
cmd->buttons |= BT_JUMP;
// player aiming shit, ahhhh...
@@ -1616,11 +1642,6 @@ static void Analog_OnChange(void)
// cameras are not initialized at this point
- if (leveltime > 1)
- CV_SetValue(&cv_cam_dist, 128);
- if (cv_analog.value || demoplayback)
- CV_SetValue(&cv_cam_dist, 192);
-
if (!cv_chasecam.value && cv_analog.value) {
CV_SetValue(&cv_analog, 0);
return;
@@ -1636,11 +1657,6 @@ static void Analog2_OnChange(void)
// cameras are not initialized at this point
- if (leveltime > 1)
- CV_SetValue(&cv_cam2_dist, 128);
- if (cv_analog2.value)
- CV_SetValue(&cv_cam2_dist, 192);
-
if (!cv_chasecam2.value && cv_analog2.value) {
CV_SetValue(&cv_analog2, 0);
return;
diff --git a/src/g_game.h b/src/g_game.h
index 46a5bbb3..5259eacb 100644
--- a/src/g_game.h
+++ b/src/g_game.h
@@ -60,8 +60,8 @@ extern consvar_t cv_invertmouse, cv_alwaysfreelook, cv_chasefreelook, cv_mousemo
extern consvar_t cv_invertmouse2, cv_alwaysfreelook2, cv_chasefreelook2, cv_mousemove2;
extern consvar_t cv_useranalog, cv_useranalog2;
extern consvar_t cv_analog, cv_analog2;
-extern consvar_t cv_sideaxis,cv_turnaxis,cv_moveaxis,cv_lookaxis,cv_fireaxis,cv_firenaxis;
-extern consvar_t cv_sideaxis2,cv_turnaxis2,cv_moveaxis2,cv_lookaxis2,cv_fireaxis2,cv_firenaxis2;
+extern consvar_t cv_sideaxis,cv_turnaxis,cv_moveaxis,cv_lookaxis,cv_jumpaxis,cv_spinaxis,cv_fireaxis,cv_firenaxis;
+extern consvar_t cv_sideaxis2,cv_turnaxis2,cv_moveaxis2,cv_lookaxis2,cv_jumpaxis2,cv_spinaxis2,cv_fireaxis2,cv_firenaxis2;
extern consvar_t cv_ghost_bestscore, cv_ghost_besttime, cv_ghost_bestrings, cv_ghost_last, cv_ghost_guest;
// mouseaiming (looking up/down with the mouse or keyboard)
diff --git a/src/g_input.c b/src/g_input.c
index 44d9f2b2..95664e2d 100644
--- a/src/g_input.c
+++ b/src/g_input.c
@@ -1165,7 +1165,9 @@ void G_Controldefault(void)
gamecontrol[gc_turnleft ][0] = KEY_LEFTARROW;
gamecontrol[gc_turnright ][0] = KEY_RIGHTARROW;
gamecontrol[gc_weaponnext ][0] = 'e';
+ gamecontrol[gc_weaponnext ][1] = KEY_JOY1+1; // B
gamecontrol[gc_weaponprev ][0] = 'q';
+ gamecontrol[gc_weaponprev ][1] = KEY_JOY1+2; // X
gamecontrol[gc_wepslot1 ][0] = '1';
gamecontrol[gc_wepslot2 ][0] = '2';
gamecontrol[gc_wepslot3 ][0] = '3';
@@ -1180,24 +1182,45 @@ void G_Controldefault(void)
gamecontrol[gc_fire ][1] = KEY_MOUSE1+0;
gamecontrol[gc_firenormal ][0] = 'c';
gamecontrol[gc_tossflag ][0] = '\'';
+ gamecontrol[gc_tossflag ][1] = KEY_JOY1+0; // A
gamecontrol[gc_use ][0] = KEY_LSHIFT;
+ gamecontrol[gc_use ][1] = KEY_JOY1+4; // LB
gamecontrol[gc_camtoggle ][0] = 'v';
+ gamecontrol[gc_camtoggle ][1] = KEY_HAT1+0; // D-Pad Up
gamecontrol[gc_camleft ][0] = '[';
gamecontrol[gc_camright ][0] = ']';
gamecontrol[gc_camreset ][0] = 'r';
+ gamecontrol[gc_camreset ][1] = KEY_JOY1+3; // Y
gamecontrol[gc_lookup ][0] = KEY_UPARROW;
gamecontrol[gc_lookdown ][0] = KEY_DOWNARROW;
gamecontrol[gc_centerview ][0] = KEY_END;
gamecontrol[gc_talkkey ][0] = 't';
+ gamecontrol[gc_talkkey ][1] = KEY_HAT1+2; // D-Pad Left
gamecontrol[gc_teamkey ][0] = 'y';
gamecontrol[gc_scores ][0] = KEY_TAB;
+ gamecontrol[gc_scores ][1] = KEY_HAT1+3; // D-Pad Right
gamecontrol[gc_jump ][0] = KEY_SPACE;
+ gamecontrol[gc_jump ][1] = KEY_JOY1+5; // RB
gamecontrol[gc_console ][0] = KEY_CONSOLE;
gamecontrol[gc_pause ][0] = 'p';
+ gamecontrol[gc_pause ][1] = KEY_JOY1+6; // Back
gamecontrol[gc_screenshot ][0] = KEY_F8;
+ gamecontrol[gc_screenshot ][1] = KEY_HAT1+1; // D-Pad Down
gamecontrol[gc_recordgif ][0] = KEY_F9;
gamecontrol[gc_viewpoint ][0] = KEY_F12;
gamecontrol[gc_systemmenu ][0] = KEY_JOY1+7; // Start
+ gamecontrolbis[gc_weaponnext][0] = KEY_2JOY1+1; // B
+ gamecontrolbis[gc_weaponprev][0] = KEY_2JOY1+2; // X
+ gamecontrolbis[gc_tossflag ][0] = KEY_2JOY1+0; // A
+ gamecontrolbis[gc_use ][0] = KEY_2JOY1+4; // LB
+ gamecontrolbis[gc_camreset ][0] = KEY_2JOY1+3; // Y
+ gamecontrolbis[gc_jump ][0] = KEY_2JOY1+5; // RB
+ //gamecontrolbis[gc_pause ][0] = KEY_2JOY1+6; // Back
+ //gamecontrolbis[gc_systemmenu][0] = KEY_2JOY1+7; // Start
+ gamecontrolbis[gc_camtoggle ][0] = KEY_2HAT1+0; // D-Pad Up
+ gamecontrolbis[gc_screenshot][0] = KEY_2HAT1+1; // D-Pad Down
+ //gamecontrolbis[gc_talkkey ][0] = KEY_2HAT1+2; // D-Pad Left
+ //gamecontrolbis[gc_scores ][0] = KEY_2HAT1+3; // D-Pad Right
#ifdef WMINPUT
gamecontrol[gc_forward ][0] = KEY_JOY1+02; //UP
gamecontrol[gc_backward ][0] = KEY_JOY1+03; //DOWN
diff --git a/src/lua_baselib.c b/src/lua_baselib.c
index 6ae4ad8c..fd83cf95 100644
--- a/src/lua_baselib.c
+++ b/src/lua_baselib.c
@@ -1727,6 +1727,25 @@ static int lib_rSetPlayerSkin(lua_State *L)
return 0;
}
+// R_DATA
+////////////
+
+static int lib_rCheckTextureNumForName(lua_State *L)
+{
+ const char *name = luaL_checkstring(L, 1);
+ //HUDSAFE
+ lua_pushinteger(L, R_CheckTextureNumForName(name));
+ return 1;
+}
+
+static int lib_rTextureNumForName(lua_State *L)
+{
+ const char *name = luaL_checkstring(L, 1);
+ //HUDSAFE
+ lua_pushinteger(L, R_TextureNumForName(name));
+ return 1;
+}
+
// S_SOUND
////////////
@@ -1947,28 +1966,45 @@ static int lib_gDoReborn(lua_State *L)
return 0;
}
-static int lib_gExitLevel(lua_State *L)
+// Another Lua function that doesn't actually exist!
+// Sets nextmapoverride & skipstats without instantly ending the level, for instances where other sources should be exiting the level, like normal signposts.
+static int lib_gSetCustomExitVars(lua_State *L)
{
int n = lua_gettop(L); // Num arguments
NOHUD
// LUA EXTENSION: Custom exit like support
// Supported:
- // G_ExitLevel(); [no modifications]
- // G_ExitLevel(int) [nextmap override only]
- // G_ExitLevel(bool) [skipstats only]
- // G_ExitLevel(int, bool) [both of the above]
+ // G_SetCustomExitVars(); [reset to defaults]
+ // G_SetCustomExitVars(int) [nextmap override only]
+ // G_SetCustomExitVars(bool) [skipstats only]
+ // G_SetCustomExitVars(int, bool) [both of the above]
if (n >= 1)
{
if (lua_isnumber(L, 1) || n >= 2)
{
nextmapoverride = (INT16)luaL_checknumber(L, 1);
- lua_pop(L, 1); // pop nextmapoverride; skipstats now 1 if available
+ lua_remove(L, 1); // remove nextmapoverride; skipstats now 1 if available
}
skipstats = lua_optboolean(L, 1);
}
+ else
+ {
+ nextmapoverride = 0;
+ skipstats = false;
+ }
// ---
+ return 0;
+}
+
+static int lib_gExitLevel(lua_State *L)
+{
+ int n = lua_gettop(L); // Num arguments
+ NOHUD
+ // Moved this bit to G_SetCustomExitVars
+ if (n >= 1) // Don't run the reset to defaults option
+ lib_gSetCustomExitVars(L);
G_ExitLevel();
return 0;
}
@@ -2217,6 +2253,10 @@ static luaL_Reg lib[] = {
{"R_Frame2Char",lib_rFrame2Char},
{"R_SetPlayerSkin",lib_rSetPlayerSkin},
+ // r_data
+ {"R_CheckTextureNumForName",lib_rCheckTextureNumForName},
+ {"R_TextureNumForName",lib_rTextureNumForName},
+
// s_sound
{"S_StartSound",lib_sStartSound},
{"S_StartSoundAtVolume",lib_sStartSoundAtVolume},
@@ -2231,6 +2271,7 @@ static luaL_Reg lib[] = {
// g_game
{"G_BuildMapName",lib_gBuildMapName},
{"G_DoReborn",lib_gDoReborn},
+ {"G_SetCustomExitVars",lib_gSetCustomExitVars},
{"G_ExitLevel",lib_gExitLevel},
{"G_IsSpecialStage",lib_gIsSpecialStage},
{"G_GametypeUsesLives",lib_gGametypeUsesLives},
diff --git a/src/lua_maplib.c b/src/lua_maplib.c
index efe9e6f4..1f2414ba 100644
--- a/src/lua_maplib.c
+++ b/src/lua_maplib.c
@@ -795,16 +795,16 @@ static int side_set(lua_State *L)
side->rowoffset = luaL_checkfixed(L, 3);
break;
case side_toptexture:
- side->toptexture = luaL_checkinteger(L, 3);
+ side->toptexture = luaL_checkinteger(L, 3);
break;
case side_bottomtexture:
- side->bottomtexture = luaL_checkinteger(L, 3);
+ side->bottomtexture = luaL_checkinteger(L, 3);
break;
case side_midtexture:
- side->midtexture = luaL_checkinteger(L, 3);
+ side->midtexture = luaL_checkinteger(L, 3);
break;
case side_repeatcnt:
- side->repeatcnt = luaL_checkinteger(L, 3);
+ side->repeatcnt = luaL_checkinteger(L, 3);
break;
}
return 0;
@@ -1090,6 +1090,7 @@ static int ffloor_get(lua_State *L)
{
ffloor_t *ffloor = *((ffloor_t **)luaL_checkudata(L, 1, META_FFLOOR));
enum ffloor_e field = luaL_checkoption(L, 2, ffloor_opt[0], ffloor_opt);
+ INT16 i;
if (!ffloor)
{
@@ -1109,11 +1110,11 @@ static int ffloor_get(lua_State *L)
lua_pushfixed(L, *ffloor->topheight);
return 1;
case ffloor_toppic: { // toppic
- levelflat_t *levelflat;
- INT16 i;
- for (i = 0, levelflat = levelflats; i != *ffloor->toppic; i++, levelflat++)
- ;
- lua_pushlstring(L, levelflat->name, 8);
+ levelflat_t *levelflat = &levelflats[*ffloor->toppic];
+ for (i = 0; i < 8; i++)
+ if (!levelflat->name[i])
+ break;
+ lua_pushlstring(L, levelflat->name, i);
return 1;
}
case ffloor_toplightlevel:
@@ -1123,11 +1124,11 @@ static int ffloor_get(lua_State *L)
lua_pushfixed(L, *ffloor->bottomheight);
return 1;
case ffloor_bottompic: { // bottompic
- levelflat_t *levelflat;
- INT16 i;
- for (i = 0, levelflat = levelflats; i != *ffloor->bottompic; i++, levelflat++)
- ;
- lua_pushlstring(L, levelflat->name, 8);
+ levelflat_t *levelflat = &levelflats[*ffloor->bottompic];
+ for (i = 0; i < 8; i++)
+ if (!levelflat->name[i])
+ break;
+ lua_pushlstring(L, levelflat->name, i);
return 1;
}
#ifdef ESLOPE
@@ -1504,6 +1505,8 @@ static int mapheaderinfo_get(lua_State *L)
lua_pushinteger(L, header->levelselect);
else if (fastcmp(field,"bonustype"))
lua_pushinteger(L, header->bonustype);
+ else if (fastcmp(field,"saveoverride"))
+ lua_pushinteger(L, header->saveoverride);
else if (fastcmp(field,"levelflags"))
lua_pushinteger(L, header->levelflags);
else if (fastcmp(field,"menuflags"))
diff --git a/src/m_menu.c b/src/m_menu.c
index acc52f51..8daeba2c 100644
--- a/src/m_menu.c
+++ b/src/m_menu.c
@@ -1089,25 +1089,29 @@ static menuitem_t OP_Joystick1Menu[] =
{IT_STRING | IT_CVAR, NULL, "Axis For Moving" , &cv_moveaxis , 40},
{IT_STRING | IT_CVAR, NULL, "Axis For Strafe" , &cv_sideaxis , 50},
{IT_STRING | IT_CVAR, NULL, "Axis For Looking" , &cv_lookaxis , 60},
- {IT_STRING | IT_CVAR, NULL, "Axis For Firing" , &cv_fireaxis , 70},
- {IT_STRING | IT_CVAR, NULL, "Axis For NFiring" , &cv_firenaxis , 80},
+ {IT_STRING | IT_CVAR, NULL, "Axis For Jumping" , &cv_jumpaxis , 70},
+ {IT_STRING | IT_CVAR, NULL, "Axis For Spinning" , &cv_spinaxis , 80},
+ {IT_STRING | IT_CVAR, NULL, "Axis For Firing" , &cv_fireaxis , 90},
+ {IT_STRING | IT_CVAR, NULL, "Axis For NFiring" , &cv_firenaxis , 100},
- {IT_STRING | IT_CVAR, NULL, "First-Person Vert-Look", &cv_alwaysfreelook, 100},
- {IT_STRING | IT_CVAR, NULL, "Third-Person Vert-Look", &cv_chasefreelook, 110},
+ {IT_STRING | IT_CVAR, NULL, "First-Person Vert-Look", &cv_alwaysfreelook, 120},
+ {IT_STRING | IT_CVAR, NULL, "Third-Person Vert-Look", &cv_chasefreelook, 130},
};
static menuitem_t OP_Joystick2Menu[] =
{
- {IT_STRING | IT_CALL, NULL, "Select Joystick...", M_Setup2PJoystickMenu, 10},
- {IT_STRING | IT_CVAR, NULL, "Axis For Turning" , &cv_turnaxis2 , 30},
- {IT_STRING | IT_CVAR, NULL, "Axis For Moving" , &cv_moveaxis2 , 40},
- {IT_STRING | IT_CVAR, NULL, "Axis For Strafe" , &cv_sideaxis2 , 50},
- {IT_STRING | IT_CVAR, NULL, "Axis For Looking" , &cv_lookaxis2 , 60},
- {IT_STRING | IT_CVAR, NULL, "Axis For Firing" , &cv_fireaxis2 , 70},
- {IT_STRING | IT_CVAR, NULL, "Axis For NFiring" , &cv_firenaxis2 , 80},
+ {IT_STRING | IT_CALL, NULL, "Select Joystick...", M_Setup2PJoystickMenu, 10},
+ {IT_STRING | IT_CVAR, NULL, "Axis For Turning" , &cv_turnaxis2 , 30},
+ {IT_STRING | IT_CVAR, NULL, "Axis For Moving" , &cv_moveaxis2 , 40},
+ {IT_STRING | IT_CVAR, NULL, "Axis For Strafe" , &cv_sideaxis2 , 50},
+ {IT_STRING | IT_CVAR, NULL, "Axis For Looking" , &cv_lookaxis2 , 60},
+ {IT_STRING | IT_CVAR, NULL, "Axis For Jumping" , &cv_jumpaxis2 , 70},
+ {IT_STRING | IT_CVAR, NULL, "Axis For Spinning" , &cv_spinaxis2 , 80},
+ {IT_STRING | IT_CVAR, NULL, "Axis For Firing" , &cv_fireaxis2 , 90},
+ {IT_STRING | IT_CVAR, NULL, "Axis For NFiring" , &cv_firenaxis2 , 100},
- {IT_STRING | IT_CVAR, NULL, "First-Person Vert-Look", &cv_alwaysfreelook2, 100},
- {IT_STRING | IT_CVAR, NULL, "Third-Person Vert-Look", &cv_chasefreelook2, 110},
+ {IT_STRING | IT_CVAR, NULL, "First-Person Vert-Look", &cv_alwaysfreelook2,120},
+ {IT_STRING | IT_CVAR, NULL, "Third-Person Vert-Look", &cv_chasefreelook2, 130},
};
static menuitem_t OP_JoystickSetMenu[] =
diff --git a/src/p_setup.c b/src/p_setup.c
index 2e568800..4e66bebb 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -219,6 +219,8 @@ static void P_ClearSingleMapHeaderInfo(INT16 i)
mapheaderinfo[num]->levelselect = 0;
DEH_WriteUndoline("BONUSTYPE", va("%d", mapheaderinfo[num]->bonustype), UNDO_NONE);
mapheaderinfo[num]->bonustype = 0;
+ DEH_WriteUndoline("SAVEOVERRIDE", va("%d", mapheaderinfo[num]->saveoverride), UNDO_NONE);
+ mapheaderinfo[num]->saveoverride = SAVE_DEFAULT;
DEH_WriteUndoline("LEVELFLAGS", va("%d", mapheaderinfo[num]->levelflags), UNDO_NONE);
mapheaderinfo[num]->levelflags = 0;
DEH_WriteUndoline("MENUFLAGS", va("%d", mapheaderinfo[num]->menuflags), UNDO_NONE);
@@ -380,30 +382,26 @@ static inline void P_LoadVertexes(lumpnum_t lumpnum)
Z_Free(data);
}
-
-//
-// Computes the line length in fracunits, the OpenGL render needs this
-//
-
/** Computes the length of a seg in fracunits.
- * This is needed for splats.
*
* \param seg Seg to compute length for.
* \return Length in fracunits.
*/
fixed_t P_SegLength(seg_t *seg)
{
- fixed_t dx, dy;
-
- // make a vector (start at origin)
- dx = seg->v2->x - seg->v1->x;
- dy = seg->v2->y - seg->v1->y;
-
- return FixedHypot(dx, dy);
+ INT64 dx = (seg->v2->x - seg->v1->x)>>1;
+ INT64 dy = (seg->v2->y - seg->v1->y)>>1;
+ return FixedHypot(dx, dy)<<1;
}
#ifdef HWRENDER
-static inline float P_SegLengthf(seg_t *seg)
+/** Computes the length of a seg as a float.
+ * This is needed for OpenGL.
+ *
+ * \param seg Seg to compute length for.
+ * \return Length as a float.
+ */
+static inline float P_SegLengthFloat(seg_t *seg)
{
float dx, dy;
@@ -439,11 +437,11 @@ static void P_LoadRawSegs(UINT8 *data, size_t i)
li->v1 = &vertexes[SHORT(ml->v1)];
li->v2 = &vertexes[SHORT(ml->v2)];
-#ifdef HWRENDER // not win32 only 19990829 by Kin
- // used for the hardware render
- if (rendermode != render_soft && rendermode != render_none)
+ li->length = P_SegLength(li);
+#ifdef HWRENDER
+ if (rendermode == render_opengl)
{
- li->flength = P_SegLengthf(li);
+ li->flength = P_SegLengthFloat(li);
//Hurdler: 04/12/2000: for now, only used in hardware mode
li->lightmaps = NULL; // list of static lightmap for this seg
}
@@ -2626,6 +2624,28 @@ static void P_SetupCamera(void)
}
}
+static boolean P_CanSave(void)
+{
+ // Saving is completely ignored under these conditions:
+ if ((cursaveslot < 0) // Playing without saving
+ || (!modifiedgame || savemoddata) // Game is modified
+ || (netgame || multiplayer) // Not in single-player
+ || (demoplayback || demorecording || metalrecording) // Currently in demo
+ || (players[consoleplayer].lives <= 0) // Completely dead
+ || (modeattacking || ultimatemode || G_IsSpecialStage(gamemap))) // Specialized instances
+ return false;
+
+ if (mapheaderinfo[gamemap-1]->saveoverride == SAVE_ALWAYS)
+ return true; // Saving should ALWAYS happen!
+ else if (mapheaderinfo[gamemap-1]->saveoverride == SAVE_NEVER)
+ return false; // Saving should NEVER happen!
+
+ // Default condition: In a non-hidden map, at the beginning of a zone or on a completed save-file, and not on save reload.
+ return (!(mapheaderinfo[gamemap-1]->menuflags & LF2_HIDEINMENU)
+ && (mapheaderinfo[gamemap-1]->actnum < 2 || gamecomplete)
+ && (gamemap != lastmapsaved));
+}
+
/** Loads a level from a lump or external wad.
*
* \param skipprecip If true, don't spawn precipitation.
@@ -2689,8 +2709,9 @@ boolean P_SetupLevel(boolean skipprecip)
if (!dedicated)
{
- if (!cv_cam_speed.changed)
- CV_Set(&cv_cam_speed, cv_cam_speed.defaultvalue);
+ // Salt: CV_ClearChangedFlags() messes with your settings :(
+ /*if (!cv_cam_speed.changed)
+ CV_Set(&cv_cam_speed, cv_cam_speed.defaultvalue);*/
if (!cv_chasecam.changed)
CV_SetValue(&cv_chasecam, chase);
@@ -3025,20 +3046,22 @@ boolean P_SetupLevel(boolean skipprecip)
{
P_SetupCamera();
- if (!cv_cam_height.changed)
+ // Salt: CV_ClearChangedFlags() messes with your settings :(
+ /*if (!cv_cam_height.changed)
CV_Set(&cv_cam_height, cv_cam_height.defaultvalue);
if (!cv_cam_dist.changed)
CV_Set(&cv_cam_dist, cv_cam_dist.defaultvalue);
- if (!cv_cam_rotate.changed)
- CV_Set(&cv_cam_rotate, cv_cam_rotate.defaultvalue);
-
if (!cv_cam2_height.changed)
CV_Set(&cv_cam2_height, cv_cam2_height.defaultvalue);
if (!cv_cam2_dist.changed)
- CV_Set(&cv_cam2_dist, cv_cam2_dist.defaultvalue);
+ CV_Set(&cv_cam2_dist, cv_cam2_dist.defaultvalue);*/
+
+ // Though, I don't think anyone would care about cam_rotate being reset back to the only value that makes sense :P
+ if (!cv_cam_rotate.changed)
+ CV_Set(&cv_cam_rotate, cv_cam_rotate.defaultvalue);
if (!cv_cam2_rotate.changed)
CV_Set(&cv_cam2_rotate, cv_cam2_rotate.defaultvalue);
@@ -3103,10 +3126,7 @@ boolean P_SetupLevel(boolean skipprecip)
P_RunCachedActions();
- if (!(netgame || multiplayer || demoplayback || demorecording || metalrecording || modeattacking || players[consoleplayer].lives <= 0)
- && (!modifiedgame || savemoddata) && cursaveslot >= 0 && !ultimatemode
- && !(mapheaderinfo[gamemap-1]->menuflags & LF2_HIDEINMENU)
- && (!G_IsSpecialStage(gamemap)) && gamemap != lastmapsaved && (mapheaderinfo[gamemap-1]->actnum < 2 || gamecomplete))
+ if (P_CanSave())
G_SaveGame((UINT32)cursaveslot);
if (savedata.lives > 0)
diff --git a/src/p_user.c b/src/p_user.c
index 90616754..a27e571e 100644
--- a/src/p_user.c
+++ b/src/p_user.c
@@ -7781,18 +7781,18 @@ static CV_PossibleValue_t CV_CamSpeed[] = {{0, "MIN"}, {1*FRACUNIT, "MAX"}, {0,
static CV_PossibleValue_t rotation_cons_t[] = {{1, "MIN"}, {45, "MAX"}, {0, NULL}};
static CV_PossibleValue_t CV_CamRotate[] = {{-720, "MIN"}, {720, "MAX"}, {0, NULL}};
-consvar_t cv_cam_dist = {"cam_dist", "128", CV_FLOAT, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
-consvar_t cv_cam_height = {"cam_height", "20", CV_FLOAT, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
+consvar_t cv_cam_dist = {"cam_dist", "160", CV_FLOAT|CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
+consvar_t cv_cam_height = {"cam_height", "25", CV_FLOAT|CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_cam_still = {"cam_still", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
-consvar_t cv_cam_speed = {"cam_speed", "0.25", CV_FLOAT, CV_CamSpeed, NULL, 0, NULL, NULL, 0, 0, NULL};
+consvar_t cv_cam_speed = {"cam_speed", "0.3", CV_FLOAT|CV_SAVE, CV_CamSpeed, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_cam_rotate = {"cam_rotate", "0", CV_CALL|CV_NOINIT, CV_CamRotate, CV_CamRotate_OnChange, 0, NULL, NULL, 0, 0, NULL};
-consvar_t cv_cam_rotspeed = {"cam_rotspeed", "10", 0, rotation_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
-consvar_t cv_cam2_dist = {"cam2_dist", "128", CV_FLOAT, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
-consvar_t cv_cam2_height = {"cam2_height", "20", CV_FLOAT, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
+consvar_t cv_cam_rotspeed = {"cam_rotspeed", "10", CV_SAVE, rotation_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
+consvar_t cv_cam2_dist = {"cam2_dist", "160", CV_FLOAT|CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
+consvar_t cv_cam2_height = {"cam2_height", "25", CV_FLOAT|CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_cam2_still = {"cam2_still", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
-consvar_t cv_cam2_speed = {"cam2_speed", "0.25", CV_FLOAT, CV_CamSpeed, NULL, 0, NULL, NULL, 0, 0, NULL};
+consvar_t cv_cam2_speed = {"cam2_speed", "0.3", CV_FLOAT|CV_SAVE, CV_CamSpeed, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_cam2_rotate = {"cam2_rotate", "0", CV_CALL|CV_NOINIT, CV_CamRotate, CV_CamRotate2_OnChange, 0, NULL, NULL, 0, 0, NULL};
-consvar_t cv_cam2_rotspeed = {"cam2_rotspeed", "10", 0, rotation_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
+consvar_t cv_cam2_rotspeed = {"cam2_rotspeed", "10", CV_SAVE, rotation_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
fixed_t t_cam_dist = -42;
fixed_t t_cam_height = -42;
@@ -8048,6 +8048,20 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
{
dist = camdist;
+ // x1.5 dist for splitscreen
+ if (splitscreen)
+ {
+ dist = FixedMul(dist, 3*FRACUNIT/2);
+ camheight = FixedMul(camheight, 3*FRACUNIT/2);
+ }
+
+ // x1.2 dist for analog
+ if (P_AnalogMove(player))
+ {
+ dist = FixedMul(dist, 6*FRACUNIT/5);
+ camheight = FixedMul(camheight, 6*FRACUNIT/5);
+ }
+
if (player->climbing || player->exiting || player->playerstate == PST_DEAD || (player->pflags & (PF_MACESPIN|PF_ITEMHANG|PF_ROPEHANG)))
dist <<= 1;
}
@@ -8719,9 +8733,14 @@ void P_PlayerThink(player_t *player)
if (player->flashcount)
player->flashcount--;
- // By the time P_MoveChaseCamera is called, this might be zero. Do not do it here.
- //if (player->awayviewtics)
- // player->awayviewtics--;
+ // Re-fixed by Jimita (11-12-2018)
+ if (player->awayviewtics)
+ {
+ player->awayviewtics--;
+ if (!player->awayviewtics)
+ player->awayviewtics = -1;
+ // The timer might've reached zero, but we'll run the remote view camera anyway by setting it to -1.
+ }
/// \note do this in the cheat code
if (player->pflags & PF_NOCLIP)
@@ -9499,8 +9518,8 @@ void P_PlayerAfterThink(player_t *player)
}
}
- if (player->awayviewtics)
- player->awayviewtics--;
+ if (player->awayviewtics < 0)
+ player->awayviewtics = 0;
// spectator invisibility and nogravity.
if ((netgame || multiplayer) && player->spectator)
diff --git a/src/r_bsp.c b/src/r_bsp.c
index a41c6403..cae66844 100644
--- a/src/r_bsp.c
+++ b/src/r_bsp.c
@@ -403,17 +403,17 @@ static void R_AddLine(seg_t *line)
{
INT32 x1, x2;
angle_t angle1, angle2, span, tspan;
- static sector_t tempsec; // ceiling/water hack
+ static sector_t tempsec;
+
+ portalline = false;
if (line->polyseg && !(line->polyseg->flags & POF_RENDERSIDES))
return;
+ // big room fix
+ angle1 = R_PointToAngleEx(viewx, viewy, line->v1->x, line->v1->y);
+ angle2 = R_PointToAngleEx(viewx, viewy, line->v2->x, line->v2->y);
curline = line;
- portalline = false;
-
- // OPTIMIZE: quickly reject orthogonal back sides.
- angle1 = R_PointToAngle(line->v1->x, line->v1->y);
- angle2 = R_PointToAngle(line->v2->x, line->v2->y);
// Clip to view edges.
span = angle1 - angle2;
@@ -592,69 +592,35 @@ INT32 checkcoord[12][4] =
{2, 1, 3, 0}
};
-static boolean R_CheckBBox(fixed_t *bspcoord)
+static boolean R_CheckBBox(const fixed_t *bspcoord)
{
- INT32 boxpos, sx1, sx2;
- fixed_t px1, py1, px2, py2;
- angle_t angle1, angle2, span, tspan;
+ angle_t angle1, angle2;
+ INT32 sx1, sx2, boxpos;
+ const INT32* check;
cliprange_t *start;
// Find the corners of the box that define the edges from current viewpoint.
- if (viewx <= bspcoord[BOXLEFT])
- boxpos = 0;
- else if (viewx < bspcoord[BOXRIGHT])
- boxpos = 1;
- else
- boxpos = 2;
-
- if (viewy >= bspcoord[BOXTOP])
- boxpos |= 0;
- else if (viewy > bspcoord[BOXBOTTOM])
- boxpos |= 1<<2;
- else
- boxpos |= 2<<2;
-
- if (boxpos == 5)
+ if ((boxpos = (viewx <= bspcoord[BOXLEFT] ? 0 : viewx < bspcoord[BOXRIGHT] ? 1 : 2) + (viewy >= bspcoord[BOXTOP] ? 0 : viewy > bspcoord[BOXBOTTOM] ? 4 : 8)) == 5)
return true;
- px1 = bspcoord[checkcoord[boxpos][0]];
- py1 = bspcoord[checkcoord[boxpos][1]];
- px2 = bspcoord[checkcoord[boxpos][2]];
- py2 = bspcoord[checkcoord[boxpos][3]];
+ check = checkcoord[boxpos];
- // check clip list for an open space
- angle1 = R_PointToAngle2(viewx>>1, viewy>>1, px1>>1, py1>>1) - viewangle;
- angle2 = R_PointToAngle2(viewx>>1, viewy>>1, px2>>1, py2>>1) - viewangle;
+ // big room fix
+ angle1 = R_PointToAngleEx(viewx, viewy, bspcoord[check[0]], bspcoord[check[1]]) - viewangle;
+ angle2 = R_PointToAngleEx(viewx, viewy, bspcoord[check[2]], bspcoord[check[3]]) - viewangle;
- span = angle1 - angle2;
-
- // Sitting on a line?
- if (span >= ANGLE_180)
- return true;
-
- tspan = angle1 + clipangle;
-
- if (tspan > doubleclipangle)
+ if ((signed)angle1 < (signed)angle2)
{
- tspan -= doubleclipangle;
-
- // Totally off the left edge?
- if (tspan >= span)
- return false;
-
- angle1 = clipangle;
+ if ((angle1 >= ANGLE_180) && (angle1 < ANGLE_270))
+ angle1 = ANGLE_180-1;
+ else
+ angle2 = -ANGLE_180;
}
- tspan = clipangle - angle2;
- if (tspan > doubleclipangle)
- {
- tspan -= doubleclipangle;
- // Totally off the left edge?
- if (tspan >= span)
- return false;
-
- angle2 = -(signed)clipangle;
- }
+ if ((signed)angle2 >= (signed)clipangle) return false;
+ if ((signed)angle1 <= -(signed)clipangle) return false;
+ if ((signed)angle1 >= (signed)clipangle) angle1 = clipangle;
+ if ((signed)angle2 <= -(signed)clipangle) angle2 = 0-clipangle;
// Find the first clippost that touches the source post (adjacent pixels are touching).
angle1 = (angle1+ANGLE_90)>>ANGLETOFINESHIFT;
@@ -663,9 +629,7 @@ static boolean R_CheckBBox(fixed_t *bspcoord)
sx2 = viewangletox[angle2];
// Does not cross a pixel.
- if (sx1 == sx2)
- return false;
- sx2--;
+ if (sx1 >= sx2) return false;
start = solidsegs;
while (start->last < sx2)
diff --git a/src/r_defs.h b/src/r_defs.h
index b936c7e7..1cb4e081 100644
--- a/src/r_defs.h
+++ b/src/r_defs.h
@@ -573,6 +573,7 @@ typedef struct seg_s
sector_t *frontsector;
sector_t *backsector;
+ fixed_t length; // precalculated seg length
#ifdef HWRENDER
// new pointers so that AdjustSegs doesn't mess with v1/v2
void *pv1; // polyvertex_t
diff --git a/src/r_main.c b/src/r_main.c
index 2b0fbc39..94945af5 100644
--- a/src/r_main.c
+++ b/src/r_main.c
@@ -355,6 +355,29 @@ fixed_t R_PointToDist(fixed_t x, fixed_t y)
return R_PointToDist2(viewx, viewy, x, y);
}
+angle_t R_PointToAngleEx(INT32 x2, INT32 y2, INT32 x1, INT32 y1)
+{
+ INT64 dx = x1-x2;
+ INT64 dy = y1-y2;
+ if (dx < INT32_MIN || dx > INT32_MAX || dy < INT32_MIN || dy > INT32_MAX)
+ {
+ x1 = (int)(dx / 2 + x2);
+ y1 = (int)(dy / 2 + y2);
+ }
+ return (y1 -= y2, (x1 -= x2) || y1) ?
+ x1 >= 0 ?
+ y1 >= 0 ?
+ (x1 > y1) ? tantoangle[SlopeDivEx(y1,x1)] : // octant 0
+ ANGLE_90-tantoangle[SlopeDivEx(x1,y1)] : // octant 1
+ x1 > (y1 = -y1) ? 0-tantoangle[SlopeDivEx(y1,x1)] : // octant 8
+ ANGLE_270+tantoangle[SlopeDivEx(x1,y1)] : // octant 7
+ y1 >= 0 ? (x1 = -x1) > y1 ? ANGLE_180-tantoangle[SlopeDivEx(y1,x1)] : // octant 3
+ ANGLE_90 + tantoangle[SlopeDivEx(x1,y1)] : // octant 2
+ (x1 = -x1) > (y1 = -y1) ? ANGLE_180+tantoangle[SlopeDivEx(y1,x1)] : // octant 4
+ ANGLE_270-tantoangle[SlopeDivEx(x1,y1)] : // octant 5
+ 0;
+}
+
//
// R_ScaleFromGlobalAngle
// Returns the texture mapping scale for the current line (horizontal span)
diff --git a/src/r_main.h b/src/r_main.h
index 81fa13de..6ae5aa22 100644
--- a/src/r_main.h
+++ b/src/r_main.h
@@ -58,6 +58,7 @@ INT32 R_PointOnSide(fixed_t x, fixed_t y, node_t *node);
INT32 R_PointOnSegSide(fixed_t x, fixed_t y, seg_t *line);
angle_t R_PointToAngle(fixed_t x, fixed_t y);
angle_t R_PointToAngle2(fixed_t px2, fixed_t py2, fixed_t px1, fixed_t py1);
+angle_t R_PointToAngleEx(INT32 x2, INT32 y2, INT32 x1, INT32 y1);
fixed_t R_PointToDist(fixed_t x, fixed_t y);
fixed_t R_PointToDist2(fixed_t px2, fixed_t py2, fixed_t px1, fixed_t py1);
diff --git a/src/r_segs.c b/src/r_segs.c
index 1637ce90..6d6ba1ef 100644
--- a/src/r_segs.c
+++ b/src/r_segs.c
@@ -1647,6 +1647,23 @@ static void R_RenderSegLoop (void)
}
}
+// Uses precalculated seg->length
+static INT64 R_CalcSegDist(seg_t* seg, INT64 x2, INT64 y2)
+{
+ if (!seg->linedef->dy)
+ return llabs(y2 - seg->v1->y);
+ else if (!seg->linedef->dx)
+ return llabs(x2 - seg->v1->x);
+ else
+ {
+ INT64 dx = (seg->v2->x)-(seg->v1->x);
+ INT64 dy = (seg->v2->y)-(seg->v1->y);
+ INT64 vdx = x2-(seg->v1->x);
+ INT64 vdy = y2-(seg->v1->y);
+ return ((dy*vdx)-(dx*vdy))/(seg->length);
+ }
+}
+
//
// R_StoreWallRange
// A wall segment will be drawn
@@ -1657,6 +1674,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
fixed_t hyp;
fixed_t sineval;
angle_t distangle, offsetangle;
+ boolean longboi;
#ifndef ESLOPE
fixed_t vtop;
#endif
@@ -1702,10 +1720,15 @@ void R_StoreWallRange(INT32 start, INT32 stop)
offsetangle = ANGLE_90;
distangle = ANGLE_90 - offsetangle;
- hyp = R_PointToDist (curline->v1->x, curline->v1->y);
sineval = FINESINE(distangle>>ANGLETOFINESHIFT);
- rw_distance = FixedMul (hyp, sineval);
+ hyp = R_PointToDist(curline->v1->x, curline->v1->y);
+ rw_distance = FixedMul(hyp, sineval);
+ longboi = (hyp >= INT32_MAX);
+
+ // big room fix
+ if (longboi)
+ rw_distance = (fixed_t)R_CalcSegDist(curline,viewx,viewy);
ds_p->x1 = rw_x = start;
ds_p->x2 = stop;
@@ -2562,8 +2585,18 @@ void R_StoreWallRange(INT32 start, INT32 stop)
if (offsetangle > ANGLE_90)
offsetangle = ANGLE_90;
- sineval = FINESINE(offsetangle >>ANGLETOFINESHIFT);
- rw_offset = FixedMul (hyp, sineval);
+ sineval = FINESINE(offsetangle>>ANGLETOFINESHIFT);
+ rw_offset = FixedMul(hyp, sineval);
+
+ // big room fix
+ if (longboi)
+ {
+ INT64 dx = (curline->v2->x)-(curline->v1->x);
+ INT64 dy = (curline->v2->y)-(curline->v1->y);
+ INT64 vdx = viewx-(curline->v1->x);
+ INT64 vdy = viewy-(curline->v1->y);
+ rw_offset = ((dx*vdx-dy*vdy))/(curline->length);
+ }
if (rw_normalangle-rw_angle1 < ANGLE_180)
rw_offset = -rw_offset;
diff --git a/src/r_things.h b/src/r_things.h
index e4a5f426..6614e0aa 100644
--- a/src/r_things.h
+++ b/src/r_things.h
@@ -219,6 +219,7 @@ FUNCMATH FUNCINLINE static ATTRINLINE char R_Frame2Char(UINT8 frame)
FUNCMATH FUNCINLINE static ATTRINLINE UINT8 R_Char2Frame(char cn)
{
#if 1 // 2.1 compat
+ if (cn == '+') return '\\' - 'A'; // PK3 can't use backslash, so use + instead
return cn - 'A';
#else
if (cn >= 'A' && cn <= 'Z') return cn - 'A';
diff --git a/src/sdl/Srb2SDL-vc10.vcxproj b/src/sdl/Srb2SDL-vc10.vcxproj
index 3e4a9ebb..00ed0db3 100644
--- a/src/sdl/Srb2SDL-vc10.vcxproj
+++ b/src/sdl/Srb2SDL-vc10.vcxproj
@@ -297,7 +297,7 @@
-
+
diff --git a/src/tables.c b/src/tables.c
index d4e0e5df..7d513707 100644
--- a/src/tables.c
+++ b/src/tables.c
@@ -37,6 +37,15 @@ unsigned SlopeDiv(unsigned num, unsigned den)
return ans <= SLOPERANGE ? ans : SLOPERANGE;
}
+UINT64 SlopeDivEx(unsigned int num, unsigned int den)
+{
+ UINT64 ans;
+ if (den < 512)
+ return SLOPERANGE;
+ ans = ((UINT64)num<<3)/(den>>8);
+ return ans <= SLOPERANGE ? ans : SLOPERANGE;
+}
+
fixed_t AngleFixed(angle_t af)
{
angle_t wa = ANGLE_180;
diff --git a/src/tables.h b/src/tables.h
index 1ea49a62..e82b147d 100644
--- a/src/tables.h
+++ b/src/tables.h
@@ -83,6 +83,8 @@ extern angle_t tantoangle[SLOPERANGE+1];
// Utility function, called by R_PointToAngle.
FUNCMATH unsigned SlopeDiv(unsigned num, unsigned den);
+// Only called by R_PointToAngleEx
+UINT64 SlopeDivEx(unsigned int num, unsigned int den);
// 360 - angle_t(ANGLE_45) = ANGLE_315
FUNCMATH FUNCINLINE static ATTRINLINE angle_t InvAngle(angle_t a)
diff --git a/src/win32/Srb2win-vc10.vcxproj b/src/win32/Srb2win-vc10.vcxproj
index 5bfa29b8..ed6b46b8 100644
--- a/src/win32/Srb2win-vc10.vcxproj
+++ b/src/win32/Srb2win-vc10.vcxproj
@@ -132,7 +132,7 @@
-
+