shithub: choc

Download patch

ref: 01b69307e00ee6c0a1366542b843f1495c79ea15
parent: afccf65a4e492befad0a0e6ba311fc1aa7659cc2
author: Thomas A. Birkel <capnclever@gmail.com>
date: Fri Oct 14 20:29:21 EDT 2016

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

--- a/src/heretic/d_main.c
+++ b/src/heretic/d_main.c
@@ -1031,6 +1031,14 @@
         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;
--- a/src/heretic/d_net.c
+++ b/src/heretic/d_net.c
@@ -115,10 +115,17 @@
     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 @@
     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 @@
     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
 
--- a/src/heretic/doomdef.h
+++ b/src/heretic/doomdef.h
@@ -527,6 +527,9 @@
 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;
 
--- a/src/heretic/g_game.c
+++ b/src/heretic/g_game.c
@@ -110,6 +110,8 @@
 
 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 @@
             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 @@
     }
     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,16 +1660,35 @@
 
 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)
     {
         // no more space
@@ -1673,6 +1714,10 @@
 {
     int i;
     int maxsize;
+
+    // If not recording a longtics demo, record in low res
+
+    lowres_turn = !longtics;
 
     G_InitNew(skill, episode, map);
     usergame = false;
--- a/src/hexen/d_net.c
+++ b/src/hexen/d_net.c
@@ -116,10 +116,17 @@
     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 @@
     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 @@
     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;
 
--- a/src/hexen/g_game.c
+++ b/src/hexen/g_game.c
@@ -93,6 +93,8 @@
 
 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 @@
         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 @@
     }
     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,16 +1813,35 @@
 
 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)
     {
         // no more space
@@ -1825,6 +1867,10 @@
 {
     int i;
     int maxsize;
+
+    // If not recording a longtics demo, record in low res
+
+    lowres_turn = !longtics;
 
     G_InitNew(skill, episode, map);
     usergame = false;
--- a/src/hexen/h2_main.c
+++ b/src/hexen/h2_main.c
@@ -676,6 +676,14 @@
         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;
--- a/src/hexen/h2def.h
+++ b/src/hexen/h2def.h
@@ -632,6 +632,9 @@
 
 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