commit 01b69307e00ee6c0a1366542b843f1495c79ea15
Author: Thomas A. Birkel <capnclever@gmail.com>
AuthorDate: Sat Oct 15 00:29:21 2016 -0400
Commit: Thomas A. Birkel <capnclever@gmail.com>
CommitDate: Sat Oct 15 00:29:21 2016 -0400
Add longtics and lowres_turn feature to Heretic/Hexen
Allow demos to be recorded and played back assuming 16-bit resolution
in player turns, similar to Doom's 1.91 hack. Unlike Doom, -longtics must
also be specified using -playdemo and -timedemo.
Also fixes a network consistency bug caused by some but not all players
recording a demo.
Partial implementation of #432
---
src/heretic/d_main.c | 8 ++++++++
src/heretic/d_net.c | 16 ++++++++++++++--
src/heretic/doomdef.h | 3 +++
src/heretic/g_game.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++---
src/hexen/d_net.c | 17 +++++++++++++++--
src/hexen/g_game.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++---
src/hexen/h2_main.c | 8 ++++++++
src/hexen/h2def.h | 3 +++
8 files changed, 148 insertions(+), 10 deletions(-)
diff --git a/src/heretic/d_main.c b/src/heretic/d_main.c
index 3c88de2c..71dc626c 100644
--- a/src/heretic/d_main.c
+++ b/src/heretic/d_main.c
@@ -1031,6 +1031,14 @@ void D_DoomMain(void)
printf("Playing demo %s.\n", file);
}
+ //!
+ // @category demo
+ //
+ // Record a high turning resolution demo.
+ //
+
+ longtics = M_CheckParm("-longtics") != 0;
+
if (W_CheckNumForName(DEH_String("E2M1")) == -1)
{
gamemode = shareware;
diff --git a/src/heretic/d_net.c b/src/heretic/d_net.c
index 517df0cd..28e7afaf 100644
--- a/src/heretic/d_net.c
+++ b/src/heretic/d_net.c
@@ -115,10 +115,17 @@ static void LoadGameSettings(net_gamesettings_t *settings)
startmap = settings->map;
startskill = settings->skill;
// TODO startloadgame = settings->loadgame;
+ lowres_turn = settings->lowres_turn;
nomonsters = settings->nomonsters;
respawnparm = settings->respawn_monsters;
consoleplayer = settings->consoleplayer;
+ if (lowres_turn)
+ {
+ printf("NOTE: Turning resolution is reduced; this is probably "
+ "because there is a client recording a Vanilla demo.\n");
+ }
+
for (i = 0; i < MAXPLAYERS; ++i)
{
playeringame[i] = i < settings->num_players;
@@ -142,7 +149,9 @@ static void SaveGameSettings(net_gamesettings_t *settings)
settings->nomonsters = nomonsters;
settings->respawn_monsters = respawnparm;
settings->timelimit = 0;
- settings->lowres_turn = false;
+
+ settings->lowres_turn = M_CheckParm("-record") > 0
+ && M_CheckParm("-longtics") == 0;
}
static void InitConnectData(net_connect_data_t *connect_data)
@@ -159,7 +168,10 @@ static void InitConnectData(net_connect_data_t *connect_data)
connect_data->gamemode = gamemode;
connect_data->gamemission = heretic;
- connect_data->lowres_turn = false;
+ // Are we recording a demo? Possibly set lowres turn mode
+
+ connect_data->lowres_turn = M_CheckParm("-record") > 0
+ && M_CheckParm("-longtics") == 0;
// Read checksums of our WAD directory and dehacked information
diff --git a/src/heretic/doomdef.h b/src/heretic/doomdef.h
index afb11b69..eeb91c21 100644
--- a/src/heretic/doomdef.h
+++ b/src/heretic/doomdef.h
@@ -527,6 +527,9 @@ extern boolean DebugSound; // debug flag for displaying sound info
extern int GetWeaponAmmo[NUMWEAPONS];
extern boolean demorecording;
+extern boolean lowres_turn; // Truncate angleturn in ticcmds to nearest 256.
+ // Used when recording Vanilla demos in netgames.
+extern boolean longtics; // specifies 16-bit angleturn resolution in demos
extern boolean demoplayback;
extern int skytexture;
diff --git a/src/heretic/g_game.c b/src/heretic/g_game.c
index 1b6a951a..ab10460f 100644
--- a/src/heretic/g_game.c
+++ b/src/heretic/g_game.c
@@ -110,6 +110,8 @@ int mouseSensitivity;
char demoname[32];
boolean demorecording;
+boolean longtics;
+boolean lowres_turn;
boolean demoplayback;
byte *demobuffer, *demo_p, *demoend;
boolean singledemo; // quit after playing a demo from cmdline
@@ -622,6 +624,14 @@ void G_BuildTiccmd(ticcmd_t *cmd, int maketic)
BT_SPECIAL | BTS_SAVEGAME | (savegameslot << BTS_SAVESHIFT);
}
+ // low-res turning
+
+ if (lowres_turn)
+ {
+ // truncate angleturn to the nearest 256 boundary
+ // for recording demos with single byte values for turn
+ cmd->angleturn &= 0xff00;
+ }
}
@@ -1630,7 +1640,19 @@ void G_ReadDemoTiccmd(ticcmd_t * cmd)
}
cmd->forwardmove = ((signed char) *demo_p++);
cmd->sidemove = ((signed char) *demo_p++);
- cmd->angleturn = ((unsigned char) *demo_p++) << 8;
+
+ // If this is a longtics demo, read back in higher resolution
+
+ if (longtics)
+ {
+ cmd->angleturn = *demo_p++;
+ cmd->angleturn |= (*demo_p++) << 8;
+ }
+ else
+ {
+ cmd->angleturn = ((unsigned char) *demo_p++) << 8;
+ }
+
cmd->buttons = (unsigned char) *demo_p++;
cmd->lookfly = (unsigned char) *demo_p++;
cmd->arti = (unsigned char) *demo_p++;
@@ -1638,15 +1660,34 @@ void G_ReadDemoTiccmd(ticcmd_t * cmd)
void G_WriteDemoTiccmd(ticcmd_t * cmd)
{
+ byte *demo_start;
+
if (gamekeydown[key_demo_quit]) // press to end demo recording
G_CheckDemoStatus();
+
+ demo_start = demo_p;
+
*demo_p++ = cmd->forwardmove;
*demo_p++ = cmd->sidemove;
- *demo_p++ = cmd->angleturn >> 8;
+
+ // If this is a longtics demo, record in higher resolution
+
+ if (longtics)
+ {
+ *demo_p++ = (cmd->angleturn & 0xff);
+ *demo_p++ = (cmd->angleturn >> 8) & 0xff;
+ }
+ else
+ {
+ *demo_p++ = cmd->angleturn >> 8;
+ }
+
*demo_p++ = cmd->buttons;
*demo_p++ = cmd->lookfly;
*demo_p++ = cmd->arti;
- demo_p -= 6;
+
+ // reset demo pointer back
+ demo_p = demo_start;
if (demo_p > demoend - 16)
{
@@ -1674,6 +1715,10 @@ void G_RecordDemo(skill_t skill, int numplayers, int episode, int map,
int i;
int maxsize;
+ // If not recording a longtics demo, record in low res
+
+ lowres_turn = !longtics;
+
G_InitNew(skill, episode, map);
usergame = false;
M_StringCopy(demoname, name, sizeof(demoname));
diff --git a/src/hexen/d_net.c b/src/hexen/d_net.c
index bd0e8b21..0c292cc8 100644
--- a/src/hexen/d_net.c
+++ b/src/hexen/d_net.c
@@ -116,10 +116,17 @@ static void LoadGameSettings(net_gamesettings_t *settings)
startmap = settings->map;
startskill = settings->skill;
// TODO startloadgame = settings->loadgame;
+ lowres_turn = settings->lowres_turn;
nomonsters = settings->nomonsters;
respawnparm = settings->respawn_monsters;
consoleplayer = settings->consoleplayer;
+ if (lowres_turn)
+ {
+ printf("NOTE: Turning resolution is reduced; this is probably "
+ "because there is a client recording a Vanilla demo.\n");
+ }
+
for (i=0; i<maxplayers; ++i)
{
playeringame[i] = i < settings->num_players;
@@ -154,7 +161,9 @@ static void SaveGameSettings(net_gamesettings_t *settings)
settings->nomonsters = nomonsters;
settings->respawn_monsters = respawnparm;
settings->timelimit = 0;
- settings->lowres_turn = false;
+
+ settings->lowres_turn = M_CheckParm("-record") > 0
+ && M_CheckParm("-longtics") == 0;
}
static void InitConnectData(net_connect_data_t *connect_data)
@@ -170,7 +179,11 @@ static void InitConnectData(net_connect_data_t *connect_data)
connect_data->gamemode = gamemode;
connect_data->gamemission = hexen;
- connect_data->lowres_turn = false;
+ // Are we recording a demo? Possibly set lowres turn mode
+
+ connect_data->lowres_turn = M_CheckParm("-record") > 0
+ && M_CheckParm("-longtics") == 0;
+
connect_data->drone = false;
connect_data->max_players = maxplayers;
diff --git a/src/hexen/g_game.c b/src/hexen/g_game.c
index bda707d1..c01776c6 100644
--- a/src/hexen/g_game.c
+++ b/src/hexen/g_game.c
@@ -93,6 +93,8 @@ int levelstarttic; // gametic at level start
char demoname[32];
boolean demorecording;
+boolean longtics;
+boolean lowres_turn;
boolean demoplayback;
byte *demobuffer, *demo_p, *demoend;
boolean singledemo; // quit after playing a demo from cmdline
@@ -622,6 +624,15 @@ void G_BuildTiccmd(ticcmd_t *cmd, int maketic)
cmd->buttons =
BT_SPECIAL | BTS_SAVEGAME | (savegameslot << BTS_SAVESHIFT);
}
+
+ // low-res turning
+
+ if (lowres_turn)
+ {
+ // truncate angleturn to the nearest 256 boundary
+ // for recording demos with single byte values for turn
+ cmd->angleturn &= 0xff00;
+ }
}
@@ -1782,7 +1793,19 @@ void G_ReadDemoTiccmd(ticcmd_t * cmd)
}
cmd->forwardmove = ((signed char) *demo_p++);
cmd->sidemove = ((signed char) *demo_p++);
- cmd->angleturn = ((unsigned char) *demo_p++) << 8;
+
+ // If this is a longtics demo, read back in higher resolution
+
+ if (longtics)
+ {
+ cmd->angleturn = *demo_p++;
+ cmd->angleturn |= (*demo_p++) << 8;
+ }
+ else
+ {
+ cmd->angleturn = ((unsigned char) *demo_p++) << 8;
+ }
+
cmd->buttons = (unsigned char) *demo_p++;
cmd->lookfly = (unsigned char) *demo_p++;
cmd->arti = (unsigned char) *demo_p++;
@@ -1790,15 +1813,34 @@ void G_ReadDemoTiccmd(ticcmd_t * cmd)
void G_WriteDemoTiccmd(ticcmd_t * cmd)
{
+ byte *demo_start;
+
if (gamekeydown[key_demo_quit]) // press to end demo recording
G_CheckDemoStatus();
+
+ demo_start = demo_p;
+
*demo_p++ = cmd->forwardmove;
*demo_p++ = cmd->sidemove;
- *demo_p++ = cmd->angleturn >> 8;
+
+ // If this is a longtics demo, record in higher resolution
+
+ if (longtics)
+ {
+ *demo_p++ = (cmd->angleturn & 0xff);
+ *demo_p++ = (cmd->angleturn >> 8) & 0xff;
+ }
+ else
+ {
+ *demo_p++ = cmd->angleturn >> 8;
+ }
+
*demo_p++ = cmd->buttons;
*demo_p++ = cmd->lookfly;
*demo_p++ = cmd->arti;
- demo_p -= 6;
+
+ // reset demo pointer back
+ demo_p = demo_start;
if (demo_p > demoend - 16)
{
@@ -1826,6 +1868,10 @@ void G_RecordDemo(skill_t skill, int numplayers, int episode, int map,
int i;
int maxsize;
+ // If not recording a longtics demo, record in low res
+
+ lowres_turn = !longtics;
+
G_InitNew(skill, episode, map);
usergame = false;
M_StringCopy(demoname, name, sizeof(demoname));
diff --git a/src/hexen/h2_main.c b/src/hexen/h2_main.c
index 3fa16a34..1e2c0af6 100644
--- a/src/hexen/h2_main.c
+++ b/src/hexen/h2_main.c
@@ -676,6 +676,14 @@ static void HandleArgs(void)
ST_Message("Playing demo %s.\n", myargv[p+1]);
}
+ //!
+ // @category demo
+ //
+ // Record a high turning resolution demo.
+ //
+
+ longtics = M_CheckParm("-longtics") != 0;
+
if (M_ParmExists("-testcontrols"))
{
autostart = true;
diff --git a/src/hexen/h2def.h b/src/hexen/h2def.h
index 9c1e76bc..aa84e430 100644
--- a/src/hexen/h2def.h
+++ b/src/hexen/h2def.h
@@ -632,6 +632,9 @@ extern player_t players[MAXPLAYERS];
extern boolean DebugSound; // debug flag for displaying sound info
+extern boolean lowres_turn; // Truncate angleturn in ticcmds to nearest 256.
+ // Used when recording Vanilla demos in netgames.
+extern boolean longtics; // specifies 16-bit angleturn resolution in demos
extern boolean demoplayback;
extern int maxzone; // Maximum chunk allocated for zone heap