foxygit / doom Log in
commit 3ac445e219bbfd2caa252a3896d65c8555bcf9d8
Author:     Simon Howard <fraggle@gmail.com>
AuthorDate: Sun Mar 23 02:08:23 2014 -0400
Commit:     Simon Howard <fraggle@gmail.com>
CommitDate: Sun Mar 23 02:08:23 2014 -0400

    doom: Emulate 'no fog on spawn west' Vanilla bug.

    A deathmatch player spawning facing directly west does not see the
    normal teleport fog (or hear it). This is because of an angle that
    should be unsigned but is actually signed. Import PrBoom's code to
    emulate this bug. This fixes #186.
---
 src/doom/g_game.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 65 insertions(+), 10 deletions(-)

diff --git a/src/doom/g_game.c b/src/doom/g_game.c
index a36267ca..6ceb1cbb 100644
--- a/src/doom/g_game.c
+++ b/src/doom/g_game.c
@@ -1093,7 +1093,6 @@ G_CheckSpot
     fixed_t		x;
     fixed_t		y;
     subsector_t*	ss;
-    unsigned		an;
     mobj_t*		mo;
     int			i;

@@ -1118,15 +1117,71 @@ G_CheckSpot
 	P_RemoveMobj (bodyque[bodyqueslot%BODYQUESIZE]);
     bodyque[bodyqueslot%BODYQUESIZE] = players[playernum].mo;
     bodyqueslot++;
-
-    // spawn a teleport fog
-    ss = R_PointInSubsector (x,y);
-    an = ( ANG45 * (((unsigned int) mthing->angle)/45) ) >> ANGLETOFINESHIFT;
-
-    mo = P_SpawnMobj (x+20*finecosine[an], y+20*finesine[an]
-		      , ss->sector->floorheight
-		      , MT_TFOG);
-
+
+    // spawn a teleport fog
+    ss = R_PointInSubsector (x,y);
+
+
+    // The code in the released source looks like this:
+    //
+    //    an = ( ANG45 * (((unsigned int) mthing->angle)/45) )
+    //         >> ANGLETOFINESHIFT;
+    //    mo = P_SpawnMobj (x+20*finecosine[an], y+20*finesine[an]
+    //                     , ss->sector->floorheight
+    //                     , MT_TFOG);
+    //
+    // But 'an' can be a signed value in the DOS version. This means that
+    // we get a negative index and the lookups into finecosine/finesine
+    // end up dereferencing values in finetangent[].
+    // A player spawning on a deathmatch start facing directly west spawns
+    // "silently" with no spawn fog. Emulate this.
+    //
+    // This code is imported from PrBoom+.
+
+    {
+        fixed_t xa, ya;
+        signed int an;
+
+        an = (ANG45 * ((signed int) mthing->angle / 45));
+        // Right-shifting a negative signed integer is implementation-defined,
+        // so divide instead.
+        an /= 1 << ANGLETOFINESHIFT;
+
+        switch (an)
+        {
+            case -4096:
+                xa = finetangent[2048];    // finecosine[-4096]
+                ya = finetangent[0];       // finesine[-4096]
+                break;
+            case -3072:
+                xa = finetangent[3072];    // finecosine[-3072]
+                ya = finetangent[1024];    // finesine[-3072]
+                break;
+            case -2048:
+                xa = finesine[0];          // finecosine[-2048]
+                ya = finetangent[2048];    // finesine[-2048]
+                break;
+            case -1024:
+                xa = finesine[1024];       // finecosine[-1024]
+                ya = finetangent[3072];    // finesine[-1024]
+                break;
+            case 0:
+            case 1024:
+            case 2048:
+            case 3072:
+            case 4096:
+                xa = finecosine[an];
+                ya = finesine[an];
+                break;
+            default:
+                I_Error("G_CheckSpot: unexpected angle %d\n", an);
+                xa = ya = 0;
+                break;
+        }
+        mo = P_SpawnMobj(x + 20 * xa, y + 20 * ya,
+                         ss->sector->floorheight, MT_TFOG);
+    }
+
     if (players[consoleplayer].viewz != 1)
 	S_StartSound (mo, sfx_telept);	// don't start sound on first frame