From 8e99bc00821807e9842c1f319f8f4236d8c2b50a Mon Sep 17 00:00:00 2001
From: REDACTED
Date: Mon, 12 Dec 2016 08:43:46 -0500
Subject: [PATCH] [Intermediate Fix] This commit represents Eduke32
 03052016_1149 on my server, this does not yet contain the new packet code, it
 is still not a great experience online but it fixes some of the most serious
 bugs; I also made it so that the client does not run the code that it
 shouldn't, so that the packet code can do its work when it's done.

---
 build/include/build.h |    3 +-
 eduke32.sln           |    7 +-
 eduke32.vcxproj       |    3 +
 source/actors.c       | 1555 +++++++++++++++++++++++++++++++++++++------------
 source/astub.c        |    2 +-
 source/game.c         |  127 +++-
 source/gameexec.c     |  448 ++++++++++----
 source/gameexec.h     |    5 +
 source/namesdyn.c     |    2 +-
 source/net.c          |   27 +-
 source/net.h          |    4 +-
 source/player.c       |  421 ++++++++-----
 source/player.h       |   31 +-
 source/premap.c       |    2 +-
 source/sector.c       |  115 ++--
 15 files changed, 2041 insertions(+), 711 deletions(-)

diff --git a/build/include/build.h b/build/include/build.h
index ba0357c..75d5de3 100644
--- a/build/include/build.h
+++ b/build/include/build.h
@@ -685,7 +685,7 @@ EXTERN int16_t headsectbunch[2][YAX_MAXBUNCHES], nextsectbunch[2][MAXSECTORS];
 
 EXTERN int32_t Numsprites;
 EXTERN int16_t numsectors, numwalls;
-EXTERN char display_mirror;
+EXTERN char display_mirror; //[75] set only for the duration of G_DoSpriteAnimations, then set right back again.
 // totalclocklock: the totalclock value that is backed up once on each
 // drawrooms() and is used for animateoffs().
 EXTERN int32_t totalclock, totalclocklock;
@@ -1166,6 +1166,7 @@ int32_t    krand(void);
 int32_t   ksqrt(uint32_t num);
 int32_t   __fastcall getangle(int32_t xvect, int32_t yvect);
 
+// sum of squares
 FORCE_INLINE uint32_t uhypsq(int32_t dx, int32_t dy)
 {
     return (uint32_t)dx*dx + (uint32_t)dy*dy;
diff --git a/eduke32.sln b/eduke32.sln
index 2df04d3..d4a0a1f 100644
--- a/eduke32.sln
+++ b/eduke32.sln
@@ -1,14 +1,11 @@
 ﻿
 Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 14
-VisualStudioVersion = 14.0.23107.0
+# Visual Studio 2013
+VisualStudioVersion = 12.0.40629.0
 MinimumVisualStudioVersion = 10.0.40219.1
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "eduke32", "eduke32.vcxproj", "{8E7A6179-0B72-4073-8A4C-E8682D481DAE}"
 EndProject
 Global
-	GlobalSection(Performance) = preSolution
-		HasPerformanceSessions = true
-	EndGlobalSection
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		SDLDebug|Win32 = SDLDebug|Win32
 		SDLDebug|x64 = SDLDebug|x64
diff --git a/eduke32.vcxproj b/eduke32.vcxproj
index a5d4491..9fb723e 100644
--- a/eduke32.vcxproj
+++ b/eduke32.vcxproj
@@ -99,6 +99,9 @@
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release-SDL|x64'">
     <IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);build\include;source\jmact;source\jaudiolib\include;source\enet\include;</IncludePath>
   </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug-SDL|Win32'">
+    <LibraryPath>$(DXSDK_DIR)\Lib\x86;$(LibraryPath)</LibraryPath>
+  </PropertyGroup>
   <ItemGroup>
     <ClInclude Include="build\include\a.h" />
     <ClInclude Include="build\include\baselayer.h" />
diff --git a/source/actors.c b/source/actors.c
index 8c2db0e..843c736 100644
--- a/source/actors.c
+++ b/source/actors.c
@@ -20,6 +20,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
 //-------------------------------------------------------------------------
 
+static int NET_75_CHECK = 0;
+
 #define actors_c_
 
 #include "duke3d.h"
@@ -35,7 +37,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 extern int32_t g_numEnvSoundsPlaying;
 extern int32_t g_noEnemies;
 
-int32_t otherp;
+int32_t otherp; //[75] set only in G_MovePlayers to P_FindOtherPlayer (one STAT_PLAYER at a time), then it runs A_Execute
 
 int32_t G_SetInterpolation(int32_t * const posptr)
 {
@@ -106,8 +108,10 @@ static inline int32_t G_WallSpriteDist(const twalltype *wal, const spritetype *s
 
 void A_RadiusDamage(int32_t i, int32_t r, int32_t hp1, int32_t hp2, int32_t hp3, int32_t hp4)
 {
-    int32_t d, q, stati;
-    const spritetype *const s = &sprite[i];
+    int32_t d, //[75] distance to thing we may have hit
+			q, 
+			stati;
+    const spritetype *const s = &sprite[i]; //[75] sprite DOING damage
 
     static const int32_t statlist[] = {
         STAT_DEFAULT, STAT_ACTOR, STAT_STANDABLE,
@@ -190,14 +194,14 @@ SKIPWALLCHECK:
 
     q = -(16<<8) + (krand()&((32<<8)-1));
 
-    for (stati=0; stati < ARRAY_SSIZE(statlist); stati++)
+    for (stati=0; stati < ARRAY_SSIZE(statlist); stati++) 
     {
-        int32_t j = headspritestat[statlist[stati]];
+        int32_t j = headspritestat[statlist[stati]]; // [75] sprite id possibly hit
 
         while (j >= 0)
         {
             const int32_t nextj = nextspritestat[j];
-            spritetype *const sj = &sprite[j];
+            spritetype *const sj = &sprite[j]; //[75] sprite possibly hit, sprite struct of a sprite whose stat is processed by this function (see statlist)
 
             // DEFAULT, ZOMBIEACTOR, MISC
             if (stati == 0 || stati >= 5 || AFLAMABLE(sj->picnum))
@@ -223,9 +227,9 @@ SKIPWALLCHECK:
                     continue;
                 }
 
-                if (sj->picnum == APLAYER) sj->z -= PHEIGHT;
+                if (sj->picnum == APLAYER) sj->z -= PHEIGHT; //[75] shift player up to calculate player distance from s
                 d = dist(s, sj);
-                if (sj->picnum == APLAYER) sj->z += PHEIGHT;
+                if (sj->picnum == APLAYER) sj->z += PHEIGHT; //[75] shift player down immediately after calculating player distance from s
 
                 if (d < r && cansee(sj->x, sj->y, sj->z-(8<<8), sj->sectnum, s->x, s->y, s->z-(12<<8), s->sectnum))
                 {
@@ -282,7 +286,7 @@ SKIPWALLCHECK:
                     if (sj->picnum != RADIUSEXPLOSION &&
                             s->owner >= 0 && sprite[s->owner].statnum < MAXSTATUS)
                     {
-                        if (sj->picnum == APLAYER)
+                        if (sj->picnum == APLAYER) //[75] immediately take the player out of camera view if they are hit, but not RADIUSEXPLOSION? (invisible dummy weapon representing all radius attacks?)
                         {
                             DukePlayer_t *ps = g_player[P_GetP(sj)].ps;
 
@@ -609,8 +613,14 @@ void A_DeleteSprite(int32_t s)
     deletesprite(s);
 }
 
+//[75]: for clients this function exits immediately
 void A_AddToDeleteQueue(int32_t i)
 {
+	if(g_netClient) //[75] clients should not add sprites to the deletion queue
+	{
+		return;
+	}
+
     if (g_spriteDeleteQueueSize == 0)
     {
         A_DeleteSprite(i);
@@ -993,7 +1003,7 @@ int32_t A_IncurDamage(int32_t sn)
         return -1;
     }
 
-    if (targ->picnum == APLAYER)
+    if (targ->picnum == APLAYER) //[75] incur damage to players
     {
         const int p = P_GetP(targ);
 
@@ -1015,7 +1025,7 @@ int32_t A_IncurDamage(int32_t sn)
 
             g_player[p].ps->wackedbyactor = ow;
 
-            if (sprite[ow].picnum == APLAYER && p != P_Get(ow))
+            if (sprite[ow].picnum == APLAYER && p != P_Get(ow)) //[75] set ps->frag_ps (i.e., who killed this player)
                 g_player[p].ps->frag_ps = P_Get(ow);
 
             dmg->owner = g_player[p].ps->i;
@@ -1114,7 +1124,16 @@ void A_MoveDummyPlayers(void)
         if (ps->on_crane >= 0 || (psectnum >= 0 && sector[psectnum].lotag != ST_1_ABOVE_WATER) || sprite[ps->i].extra <= 0)
         {
             ps->dummyplayersprite = -1;
-            KILLIT(i);
+
+			if(!g_netClient) //Clients should not delete their dummy sprite, just go to BOLT
+			{
+				KILLIT(i);
+			}
+			else
+			{
+				goto BOLT;
+			}
+
         }
         else
         {
@@ -1159,6 +1178,17 @@ ACTOR_STATIC void G_MovePlayers(void)
         spritetype *const s = &sprite[i];
         DukePlayer_t *const p = g_player[P_GetP(s)].ps;
 
+		// [75] since all spawns are given a player sprite at map load,
+		// and will fill spaces in the nextspritestat array as STAT_PLAYERs, 
+		// we need to stop this function from looking at the health of players that aren't
+		// actually in the game. 
+
+		if(sprite[i].yvel > (numplayers - 1))
+		{
+			i = nexti;
+			continue;
+		}
+
         if (s->owner >= 0)
         {
             if (p->newowner >= 0)  //Looking thru the camera
@@ -1171,7 +1201,7 @@ ACTOR_STATIC void G_MovePlayers(void)
             }
             else
             {
-                int32_t otherx;
+                int32_t otherx; //[75] distance to otherp
 #ifdef YAX_ENABLE
                 // TROR water submerge/emerge
                 const int32_t psect=s->sectnum, slotag=sector[psect].lotag;
@@ -1196,7 +1226,7 @@ ACTOR_STATIC void G_MovePlayers(void)
                 if (g_netServer || ud.multimode > 1)
                     otherp = P_FindOtherPlayer(P_GetP(s), &otherx);
                 else
-                {
+                { //[75] in single player, otherp is just this sprite's player
                     otherp = P_GetP(s);
                     otherx = 0;
                 }
@@ -1232,7 +1262,12 @@ ACTOR_STATIC void G_MovePlayers(void)
 
                     if (ud.god == 0)
                         if (G_CheckForSpaceCeiling(s->sectnum) || G_CheckForSpaceFloor(s->sectnum))
-                            P_QuickKill(p);
+						{
+							if(!g_netClient) // [75] Clients should not kill players on a space ceiling
+							{
+								P_QuickKill(p);
+							}
+						}
                 }
                 else
                 {
@@ -1255,7 +1290,16 @@ ACTOR_STATIC void G_MovePlayers(void)
         else
         {
             if (p->holoduke_on == -1)
-                KILLIT(i);
+			{
+				if(!g_netClient) // [75] Clients should not delete holodukes, just go to bolt
+				{
+					KILLIT(i);
+				}
+				else
+				{
+					goto BOLT;
+				}
+			}
 
             Bmemcpy(&actor[i].bpos, s, sizeof(vec3_t));
             s->cstat = 0;
@@ -1282,7 +1326,12 @@ ACTOR_STATIC void G_MovePlayers(void)
             {
                 s->xvel = 128;
                 s->ang = p->ang;
-                s->extra++;
+
+				if(!g_netClient) // [75] Clients should not regenerate a holoduke's health
+				{
+					s->extra++;
+				}
+
                 A_SetSprite(i,CLIPMASK0);
             }
             else
@@ -1290,6 +1339,7 @@ ACTOR_STATIC void G_MovePlayers(void)
                 s->ang = 2047-p->ang;
                 setsprite(i,(vec3_t *)s);
             }
+			
         }
 
         if (sector[s->sectnum].ceilingstat&1)
@@ -1314,6 +1364,11 @@ ACTOR_STATIC void G_MoveFX(void)
         switch (DYNAMICTILEMAP(s->picnum))
         {
         case RESPAWN__STATIC:
+			if(g_netClient) //[75] Clients should not delete or handle RESPAWN_STATIC
+			{
+				break;
+			}
+
             if (sprite[i].extra == 66)
             {
                 /*int32_t j =*/ A_Spawn(i,SHT);
@@ -1457,34 +1512,41 @@ ACTOR_STATIC void G_MoveFallers(void)
 
             s->z -= (16<<8);
             T2 = s->ang;
-            if ((j = A_IncurDamage(i)) >= 0)
-            {
-                if (j == FIREEXT || j == RPG || j == RADIUSEXPLOSION || j == SEENINE || j == OOZFILTER)
-                {
-                    if (s->extra <= 0)
-                    {
-                        T1 = 1;
 
-                        for (SPRITES_OF(STAT_FALLER, j))
-                        {
-                            if (sprite[j].hitag == SHT)
-                            {
-                                actor[j].t_data[0] = 1;
-                                sprite[j].cstat &= (65535-64);
-                                if (sprite[j].picnum == CEILINGSTEAM || sprite[j].picnum == STEAM)
-                                    sprite[j].cstat |= 32768;
-                            }
-                        }
-                    }
-                }
-                else
-                {
-                    actor[i].extra = 0;
-                    s->extra = oextra;
-                }
-            }
-            s->ang = T2;
-            s->z += (16<<8);
+			if(!g_netClient) // [75] for right now, clients can't even effect a STAT_FALLER's health (decorative destructable objects)
+			{
+				if ((j = A_IncurDamage(i)) >= 0)
+				{
+					if (j == FIREEXT || j == RPG || j == RADIUSEXPLOSION || j == SEENINE || j == OOZFILTER)
+					{
+						if (s->extra <= 0)
+						{
+							T1 = 1;
+
+							for (SPRITES_OF(STAT_FALLER, j))
+							{
+								if (sprite[j].hitag == SHT)
+								{
+									actor[j].t_data[0] = 1;
+									sprite[j].cstat &= (65535-64);
+									if (sprite[j].picnum == CEILINGSTEAM || sprite[j].picnum == STEAM)
+										sprite[j].cstat |= 32768;
+								}
+							}
+						}
+					}
+					else
+					{
+					
+							actor[i].extra = 0;
+							s->extra = oextra;
+					
+					}
+				}
+				s->ang = T2;
+				s->z += (16<<8);
+
+			}
         }
         else if (T1 == 1)
         {
@@ -1526,9 +1588,12 @@ ACTOR_STATIC void G_MoveFallers(void)
                 }
                 if ((sector[sect].floorz-s->z) < (16<<8))
                 {
-                    int32_t j = 1+(krand()&7);
-                    for (x=0; x<j; x++) RANDOMSCRAP;
-                    KILLIT(i);
+					if(!g_netClient) // [75] For right now, clients should not spawn random scrap from destructable objects
+					{
+						int32_t j = 1+(krand()&7);
+						for (x=0; x<j; x++) RANDOMSCRAP;
+						KILLIT(i);
+					}
                 }
             }
         }
@@ -1552,7 +1617,16 @@ ACTOR_STATIC void G_MoveStandables(void)
         const int32_t sect = s->sectnum;
 
         if (sect < 0)
-            KILLIT(i);
+		{
+			if(!g_netClient) //[75] clients should not delete STAT_STANDABLES outside of any sector
+			{
+				KILLIT(i);
+			}
+			else
+			{
+				goto BOLT;
+			}
+		}
 
         // Rotation-fixed sprites in rotating sectors already have bpos* updated.
         if ((t[7]&(0xffff0000))!=ROTFIXSPR_MAGIC)
@@ -1712,15 +1786,18 @@ ACTOR_STATIC void G_MoveStandables(void)
             {
                 int32_t p = A_FindPlayer(s, NULL);
 
-                if (A_IncurDamage(i) >= 0)
-                {
-                    if (s->owner == -2)
-                        if (g_player[p].ps->on_crane == i)
-                            g_player[p].ps->on_crane = -1;
-                    s->owner = -1;
-                    s->picnum = CRANE;
-                    goto BOLT;
-                }
+				if(!g_netClient) //[75] Clients should not incur damage with cranes
+				{
+					if (A_IncurDamage(i) >= 0)
+					{
+						if (s->owner == -2)
+							if (g_player[p].ps->on_crane == i)
+								g_player[p].ps->on_crane = -1;
+						s->owner = -1;
+						s->picnum = CRANE;
+						goto BOLT;
+					}
+				}
 
                 if (s->owner >= 0)
                 {
@@ -1790,18 +1867,48 @@ ACTOR_STATIC void G_MoveStandables(void)
                 else
                 {
                     if (s->shade < 64) s->shade++;
-                    else KILLIT(i);
+                    else 
+					{
+						if(!g_netClient) // [75] Clients should not delete fully "shaded" burnt objects
+						{
+							KILLIT(i);
+						}
+						else
+						{
+							goto BOLT;
+						}
+					}
                 }
 
                 j = s->xrepeat-(krand()&7);
+
                 if (j < 10)
-                    KILLIT(i);
+				{
+					if(!g_netClient) //[75] Clients should not delete fully shrunk (x) burnt objects
+					{
+						KILLIT(i);
+					}
+					else
+					{
+						goto BOLT;
+					}
+				}
 
                 s->xrepeat = j;
 
                 j = s->yrepeat-(krand()&7);
+
                 if (j < 4)
-                    KILLIT(i);
+				{
+					if(!g_netClient) //[75] Clients should not delete fully shrunk (y) burnt objects
+					{
+						KILLIT(i);
+					}
+					else
+					{
+						goto BOLT;
+					}
+				}
 
                 s->yrepeat = j;
             }
@@ -1838,7 +1945,14 @@ ACTOR_STATIC void G_MoveStandables(void)
 
                 if (T3 == 8)
                 {
-                    for (j=0; j<5; j++) RANDOMSCRAP;
+					if(!g_netClient) // [75] For right now, clients should not spawn debris from tripbombs
+					{
+						for (j=0; j<5; j++) 
+						{
+							RANDOMSCRAP;
+						}
+					}
+
                     x = s->extra;
                     A_RadiusDamage(i, g_tripbombBlastRadius, x>>2,x>>1,x-(x>>2),x);
 
@@ -1854,22 +1968,29 @@ ACTOR_STATIC void G_MoveStandables(void)
                             sprite[j].xrepeat = sprite[j].yrepeat = 0;
                     }
 
-                    KILLIT(i);
+					if(!g_netClient) // [75] For right now, clients should not delete tripbombs
+					{
+						KILLIT(i);
+					} //(clients goto bolt)
+					
                 }
                 goto BOLT;
             }
             else
             {
-                const int32_t oextra = s->extra;
-                s->extra = 1;
-                l = s->ang;
-                if (A_IncurDamage(i) >= 0)
-                {
-                    actor[i].t_data[6] = 3;
-                    T3 = 16;
-                }
-                s->extra = oextra;
-                s->ang = l;
+				if(!g_netClient) // [75] Clients should not handle inflicting damage with tripbombs
+				{
+					const int32_t oextra = s->extra;
+					s->extra = 1;
+					l = s->ang;
+					if (A_IncurDamage(i) >= 0)
+					{
+						actor[i].t_data[6] = 3;
+						T3 = 16;
+					}
+					s->extra = oextra;
+					s->ang = l;
+				}
             }
 
             switch (T1)
@@ -1983,6 +2104,11 @@ ACTOR_STATIC void G_MoveStandables(void)
 
         if (s->picnum >= CRACK1 && s->picnum <= CRACK4)
         {
+			if(g_netClient) // [75] Clients should not handle CRACK*
+			{
+				goto BOLT;
+			}
+			
             if (s->hitag > 0)
             {
                 int32_t k;
@@ -2026,6 +2152,11 @@ ACTOR_STATIC void G_MoveStandables(void)
         {
             int32_t k;
 
+			if(g_netClient) // [75] Clients should not handle FIREEXT
+			{
+				goto BOLT;
+			}
+
             if (A_IncurDamage(i) < 0)
                 goto BOLT;
 
@@ -2066,6 +2197,11 @@ ACTOR_STATIC void G_MoveStandables(void)
 
         if (s->picnum == OOZFILTER || s->picnum == SEENINE || s->picnum == SEENINEDEAD || s->picnum == SEENINEDEAD+1)
         {
+			if(g_netClient) // [75] clients should not handle OOZFILTER, SEENINE, SEENINEDEAD*
+			{
+				goto BOLT;
+			}
+
             if (s->shade != -32 && s->shade != -33)
             {
                 if (s->xrepeat)
@@ -2208,7 +2344,11 @@ DETONATE:
                         }
                     }
 
-                    KILLIT(i);
+					if(!g_netClient) // [75] Clients should not delete MASTERSWITCH sprites
+					{
+						KILLIT(i);
+					}//(clients goto BOLT)
+					
                 }
             }
             goto BOLT;
@@ -2227,7 +2367,16 @@ DETONATE:
         case VIEWSCREEN2__STATIC:
 
             if (s->xrepeat == 0)
-                KILLIT(i);
+			{
+				if(!g_netClient) // [75] Clients should not delete fully shrunk VIEWSCREEN* sprites
+				{
+					KILLIT(i);
+				}
+				else
+				{
+					goto BOLT;
+				}
+			}
 
             {
                 const int32_t p = A_FindPlayer(s, &x);
@@ -2255,7 +2404,9 @@ DETONATE:
 
         case TRASH__STATIC:
 
-            if (s->xvel == 0) s->xvel = 1;
+            if (s->xvel == 0) 
+				s->xvel = 1;
+
             if (A_SetSprite(i, CLIPMASK0))
             {
                 A_Fall(i);
@@ -2263,7 +2414,19 @@ DETONATE:
                 if ((s->xvel) < 48)
                     s->xvel += (krand()&3);
             }
-            else KILLIT(i);
+            else 
+			{
+				if(!g_netClient) // [75] Clients should not delete TRASH__STATIC
+				{
+					KILLIT(i);
+				}
+				else
+				{
+					goto BOLT;
+				}
+			}
+
+
             break;
 
         case SIDEBOLT1__STATIC:
@@ -2382,7 +2545,14 @@ CLEAR_THE_BOLT:
 
                     if (sprite[s->owner].picnum != WATERDRIP)
                     {
-                        KILLIT(i);
+						if(!g_netClient) //[75] Clients should not delete WATERDRIP_STATIC
+						{
+							 KILLIT(i);
+						}
+						else
+						{
+							goto BOLT;
+						}
                     }
                     else
                     {
@@ -2484,6 +2654,12 @@ CLEAR_THE_BOLT:
         case CANWITHSOMETHING3__STATIC:
         case CANWITHSOMETHING4__STATIC:
             A_Fall(i);
+
+			if(g_netClient) // [75] Clients should not handle CANWITHSOMETHING*_STATIC
+			{
+				goto BOLT;
+			}
+
             if (A_IncurDamage(i) >= 0)
             {
                 A_PlaySound(VENT_BUST,i);
@@ -2844,7 +3020,7 @@ ACTOR_STATIC void Proj_MoveCustom(int32_t i)
 
                 A_DamageObject(j, i);
 
-                if (sprite[j].picnum == APLAYER)
+                if (sprite[j].picnum == APLAYER) //[75] projectile hit player
                 {
                     int32_t p = P_Get(j);
 
@@ -2954,7 +3130,17 @@ ACTOR_STATIC void G_MoveWeapons(void)
         vec3_t davect;
 
         if (s->sectnum < 0)
-            KILLIT(i);
+		{
+			if(!g_netClient) // [75] clients should not delete sprites that are outside of the map, just go to bolt
+			{
+				KILLIT(i);
+			}
+
+			else
+			{
+				goto BOLT;
+			}
+		}
 
         Bmemcpy(&actor[i].bpos, s, sizeof(vec3_t));
 
@@ -2970,22 +3156,36 @@ ACTOR_STATIC void G_MoveWeapons(void)
         {
         case RADIUSEXPLOSION__STATIC:
         case KNEE__STATIC:
-            KILLIT(i);
+			if(!g_netClient) // [75] clients should not delete KNEE projectiles
+			{
+				KILLIT(i);
+			}
+			else
+			{
+				goto BOLT;
+			}
 
         case FREEZEBLAST__STATIC:
             if (s->yvel < 1 || s->extra < 2 || (s->xvel|s->zvel) == 0)
             {
-                j = A_Spawn(i,TRANSPORTERSTAR);
-                sprite[j].pal = 1;
-                sprite[j].xrepeat = 32;
-                sprite[j].yrepeat = 32;
-                KILLIT(i);
+				if(!g_netClient) // [75] FREEZEBLAST_STATIC: clients should just go to bolt instead of spawning effects / deleting the bolt
+				{
+					j = A_Spawn(i,TRANSPORTERSTAR);
+					sprite[j].pal = 1;
+					sprite[j].xrepeat = 32;
+					sprite[j].yrepeat = 32;
+					KILLIT(i);
+				}
+				else
+				{
+					goto BOLT;
+				}
             }
         case SHRINKSPARK__STATIC:
         case RPG__STATIC:
-        case FIRELASER__STATIC:
+        case FIRELASER__STATIC: // trooper projectile
         case SPIT__STATIC:
-        case COOLEXPLOSION1__STATIC:
+        case COOLEXPLOSION1__STATIC: // octobrain projectile
 
             if (s->picnum == COOLEXPLOSION1)
                 if (!S_CheckSoundPlaying(i,WIERDSHOT_FLY))
@@ -3004,12 +3204,15 @@ ACTOR_STATIC void G_MoveWeapons(void)
 
             A_GetZLimits(i);
 
-            if (s->picnum == RPG && actor[i].picnum != BOSS2 && s->xrepeat >= 10 &&
-                    sector[s->sectnum].lotag != ST_2_UNDERWATER && g_scriptVersion >= 13)
-            {
-                j = A_Spawn(i,SMALLSMOKE);
-                sprite[j].z += (1<<8);
-            }
+			if(!g_netClient) // [75] For right now clients don't spawn smoke for RPG projectiles
+			{
+				if (s->picnum == RPG && actor[i].picnum != BOSS2 && s->xrepeat >= 10 &&
+						sector[s->sectnum].lotag != ST_2_UNDERWATER && g_scriptVersion >= 13)
+				{
+					j = A_Spawn(i,SMALLSMOKE);
+					sprite[j].z += (1<<8);
+				}
+			}
 
             {
                 vec3_t tmpvect;
@@ -3018,7 +3221,7 @@ ACTOR_STATIC void G_MoveWeapons(void)
                 tmpvect.y = (k*(sintable[s->ang&2047]))>>14;
                 tmpvect.z = ll;
                 j = A_MoveSprite(i,&tmpvect, CLIPMASK1);
-            }
+            } // note: j is now clipmove retval
 
 
             if (s->picnum == RPG && (unsigned)s->yvel < MAXSPRITES)  // RPG_YVEL
@@ -3028,58 +3231,73 @@ ACTOR_STATIC void G_MoveWeapons(void)
             actor[i].movflag = j;
 
             if (s->sectnum < 0)
-                KILLIT(i);
+			{
+				if(!g_netClient) // [75] clients should not delete explosion sprites that are outside of any sector. Just go to bolt.
+				{
+					KILLIT(i);
+				}
+				else
+				{
+					goto BOLT;
+				}
+			}
 
             if ((j&49152) != 49152 && s->picnum != FREEZEBLAST)
                 G_WeaponHitCeilingOrFloor(i, s, &j);
 
             if (s->picnum == FIRELASER)
             {
-                for (k=-3; k<2; k++)
-                {
-                    x = A_InsertSprite(s->sectnum,
-                                       s->x+((k*sintable[(s->ang+512)&2047])>>9),
-                                       s->y+((k*sintable[s->ang&2047])>>9),
-                                       s->z+((k*ksgn(s->zvel))*klabs(s->zvel/24)),FIRELASER,-40+(k<<2),
-                                       s->xrepeat,s->yrepeat,0,0,0,s->owner,5);
-
-                    sprite[x].cstat = 128;
-                    sprite[x].pal = s->pal;
-                }
-            }
-            else if (s->picnum == SPIT)
+				if(!g_netClient) // [75] for right now clients should not spawn the FIRELASER trail behind trooper shots
+				{
+					for (k=-3; k<2; k++)
+					{
+						x = A_InsertSprite(s->sectnum,
+										   s->x+((k*sintable[(s->ang+512)&2047])>>9),
+										   s->y+((k*sintable[s->ang&2047])>>9),
+										   s->z+((k*ksgn(s->zvel))*klabs(s->zvel/24)),FIRELASER,-40+(k<<2),
+										   s->xrepeat,s->yrepeat,0,0,0,s->owner,5);
+
+						sprite[x].cstat = 128; // half submerged???
+						sprite[x].pal = s->pal;
+					}
+				}
+            }
+            else if (s->picnum == SPIT) 
                 if (s->zvel < 6144)
                     s->zvel += g_spriteGravity-112;
 
-            if (j != 0)
+            if (j != 0) // if this projectile hit something
             {
                 if (s->picnum == COOLEXPLOSION1)
                 {
-                    if ((j&49152) == 49152 && sprite[j&(MAXSPRITES-1)].picnum != APLAYER)
+                    if ((j&49152) == 49152 && sprite[j&(MAXSPRITES-1)].picnum != APLAYER) //[75] octobrain projectile hit something but did not hit player
                         goto COOLEXPLOSION;
                     s->xvel = 0;
                     s->zvel = 0;
                 }
 
-                switch (j&49152)
+                switch (j&49152) // did this projectile hit a sprite or wall?
                 {
-                case 49152:
+                case 49152: // it hit a sprite
                     j &= (MAXSPRITES-1);
 
                     if (s->picnum == FREEZEBLAST && sprite[j].pal == 1)
-                        if (A_CheckEnemySprite(&sprite[j]) || sprite[j].picnum == APLAYER)
+                        if (A_CheckEnemySprite(&sprite[j]) || sprite[j].picnum == APLAYER) //[75] freezeblast hit enemy or player
                         {
-                            j = A_Spawn(i, TRANSPORTERSTAR);
-                            sprite[j].pal = 1;
-                            sprite[j].xrepeat = 32;
-                            sprite[j].yrepeat = 32;
-
-                            KILLIT(i);
+							if(!g_netClient) // [75] for right now, clients don't spawn freeze effects immediately after freezing an enemy
+							{
+								j = A_Spawn(i, TRANSPORTERSTAR);
+								sprite[j].pal = 1;
+								sprite[j].xrepeat = 32;
+								sprite[j].yrepeat = 32;
+
+								KILLIT(i);
+							}
                         }
 
                         A_DamageObject(j, i);
 
-                        if (sprite[j].picnum == APLAYER)
+                        if (sprite[j].picnum == APLAYER) //[75] weapon hit player
                         {
                             int32_t p = P_Get(j);
                             A_PlaySound(PISTOL_BODYHIT, j);
@@ -3089,7 +3307,7 @@ ACTOR_STATIC void G_MoveWeapons(void)
                         }
                         break;
 
-                case 32768:
+                case 32768: // it hit a wall
                     j &= (MAXWALLS-1);
 
                     if (s->picnum != RPG && s->picnum != FREEZEBLAST && s->picnum != SPIT &&
@@ -3097,7 +3315,12 @@ ACTOR_STATIC void G_MoveWeapons(void)
                     {
                         Proj_BounceOffWall(s, j);
                         s->owner = i;
-                        A_Spawn(i, TRANSPORTERSTAR);
+
+						if(!g_netClient) // [75] for right now, clients should not spawn the transporter star bounce effect; note that only the shrink ray seems to spawn this
+						{
+							A_Spawn(i, TRANSPORTERSTAR);
+						}
+
                         goto BOLT;
                     }
                     else
@@ -3123,7 +3346,16 @@ ACTOR_STATIC void G_MoveWeapons(void)
                     setsprite(i, &davect);
 
                     if (Proj_MaybeDamageCF(s))
-                        KILLIT(i);
+					{
+						if(!g_netClient) // [75] Clients should not delete projectiles that hit a floor or ceiling, just go to bolt
+						{
+							KILLIT(i);
+						}
+						else
+						{
+							goto BOLT;
+						}
+					}
 
                     if (s->picnum == FREEZEBLAST)
                     {
@@ -3144,7 +3376,7 @@ ACTOR_STATIC void G_MoveWeapons(void)
                         goto BOLT;
                     }
                     break;
-                default:
+                default: 
                     break;
                 }
 
@@ -3157,6 +3389,11 @@ ACTOR_STATIC void G_MoveWeapons(void)
                     break;
 
                 case RPG__STATIC:
+					if(g_netClient) // [75] clients should not spawn an RPG projectile's explosion or do the damage from that
+					{
+						break;
+					}
+
                     k = A_Spawn(i, EXPLOSION2);
                     A_PlaySound(RPG_EXPLODE, k);
                     Bmemcpy(&sprite[k], &davect, sizeof(vec3_t));
@@ -3190,12 +3427,23 @@ ACTOR_STATIC void G_MoveWeapons(void)
                     break;
 
                 case SHRINKSPARK__STATIC:
+					if(g_netClient) // [75] Clients should not spawn shrinker explosion or do damage
+					{
+						break;
+					}
+
                     A_Spawn(i, SHRINKEREXPLOSION);
                     A_PlaySound(SHRINKER_HIT, i);
                     A_RadiusDamage(i, g_shrinkerBlastRadius, 0, 0, 0, 0);
                     break;
 
                 default:
+
+					if(g_netClient) // [75] clients should not spawn explosions for other projectiles either.
+					{
+						break;
+					}
+
                     k = A_Spawn(i, EXPLOSION2);
                     sprite[k].xrepeat = sprite[k].yrepeat = s->xrepeat>>1;
                     if ((j&49152) == 16384)
@@ -3209,8 +3457,15 @@ ACTOR_STATIC void G_MoveWeapons(void)
                     break;
                 }
 
-                if (s->picnum != COOLEXPLOSION1)
-                    KILLIT(i);
+				if(!g_netClient) // [75] Clients should not delete non-coolexplosion projectiles that just detonated, just goto bolt
+				{
+					if (s->picnum != COOLEXPLOSION1)
+						KILLIT(i);
+				}
+				else
+				{
+					goto BOLT;
+				}
             }
 
             if (s->picnum == COOLEXPLOSION1)
@@ -3218,20 +3473,36 @@ ACTOR_STATIC void G_MoveWeapons(void)
 COOLEXPLOSION:
                 s->shade++;
                 if (s->shade >= 40)
-                    KILLIT(i);
+				{
+					if(!g_netClient) // [75] Clients should not delete COOLEXPLOSION sprites if their shade increase is "done", just goto BOLT
+					{
+						KILLIT(i);
+					}
+					else
+					{
+						goto BOLT;
+					}
+				}
             }
             else if (s->picnum == RPG && sector[s->sectnum].lotag == ST_2_UNDERWATER && s->xrepeat >= 10 && rnd(140))
-                A_Spawn(i,WATERBUBBLE);
+			{
+				if(!g_netClient) // [75] for right now, clients don't spawn water bubble trails from the RPG projectile
+				{
+					A_Spawn(i,WATERBUBBLE);
+				}
+			}
 
             goto BOLT;
 
         case SHOTSPARK1__STATIC:
             if (!G_HaveActor(sprite[i].picnum))
                 goto BOLT;
+
             {
                 int32_t p = A_FindPlayer(s,&x);
                 A_Execute(i,p,x);
             }
+
             goto BOLT;
         }
 BOLT:
@@ -3320,14 +3591,24 @@ static void P_FinishWaterChange(int32_t j, DukePlayer_t *ps, int32_t sectlotag,
     P_UpdateScreenPal(ps);
 
     if ((krand()&255) < 32)
-        A_Spawn(j, WATERSPLASH2);
+	{
+		if(!g_netClient) // [75] For right now, clients should not spawn their own water splashes
+		{
+			 A_Spawn(j, WATERSPLASH2);
+		}
+	}
 
     if (sectlotag == ST_1_ABOVE_WATER)
+	{
         for (l = 0; l < 9; l++)
         {
-            int32_t q = A_Spawn(ps->i,WATERBUBBLE);
-            sprite[q].z += krand()&16383;
+			if(!g_netClient) // [75] For right now, clients should not spawn their own water bubbles
+			{
+				int32_t q = A_Spawn(ps->i,WATERBUBBLE);
+				sprite[q].z += krand()&16383;
+			}
         }
+	}
 }
 
 // Check prevention of teleportation *when alive*. For example, commanders and
@@ -3348,8 +3629,8 @@ ACTOR_STATIC void G_MoveTransports(void)
 
     while (i >= 0)
     {
-        const int32_t sect = SECT;
-        const int32_t sectlotag = sector[sect].lotag;
+        const int32_t sect = SECT; // sector the transport is in
+        const int32_t sectlotag = sector[sect].lotag; 
 
         const int32_t nexti = nextspritestat[i];
         int32_t j, k;
@@ -3385,16 +3666,30 @@ ACTOR_STATIC void G_MoveTransports(void)
                         {
                             if (sprite[i].pal == 0)
                             {
-                                A_Spawn(i,TRANSPORTERBEAM);
+								if(!g_netClient) // [75] for right now, clients should not spawn the teleporter effect
+								{
+									 A_Spawn(i,TRANSPORTERBEAM);
+								}
+
                                 A_PlaySound(TELEPORTER,i);
                             }
 
                             for (TRAVERSE_CONNECT(k))
+							{
                                 if (g_player[k].ps->cursectnum == sprite[OW].sectnum)
                                 {
-                                    g_player[k].ps->frag_ps = p;
-                                    sprite[g_player[k].ps->i].extra = 0;
+									if(!g_netClient) // [75] Clients should not handle telefrags
+									{
+										g_player[k].ps->frag_ps = p;
+										sprite[g_player[k].ps->i].extra = 0;
+									}
                                 }
+							} // note: k is now number of players
+
+							if(g_netClient) // [75] set k to -1 because client's don't spawn teleporter effects
+							{
+								k = -1;
+							}
 
                             ps->ang = sprite[OW].ang;
 
@@ -3405,6 +3700,8 @@ ACTOR_STATIC void G_MoveTransports(void)
                                 ps->transporter_hold = 13;
                             }
 
+							NET_75_CHECK++; // this code may need to be adjusted if the clients incorrectly predict teleportation
+
                             ps->bobpos.x = ps->opos.x = ps->pos.x = sprite[OW].x;
                             ps->bobpos.y = ps->opos.y = ps->pos.y = sprite[OW].y;
                             ps->opos.z = ps->pos.z = sprite[OW].z-PHEIGHT;
@@ -3414,8 +3711,12 @@ ACTOR_STATIC void G_MoveTransports(void)
 
                             if (sprite[i].pal == 0)
                             {
-                                k = A_Spawn(OW,TRANSPORTERBEAM);
-                                A_PlaySound(TELEPORTER,k);
+								if(!g_netClient) // [75] clients should not spawn teleporter effects at the destination either.
+								{
+									k = A_Spawn(OW,TRANSPORTERBEAM);
+									A_PlaySound(TELEPORTER,k); // clients can't play sound at destination because clients didn't spawn that sprite
+								}
+                               
                             }
 
                             break;
@@ -3538,21 +3839,24 @@ ACTOR_STATIC void G_MoveTransports(void)
 //                                break;
 
                             if (sectlotag > 0)
-                            {
+                            { // [75] k in this block is the id of the spawned watersplash
                                 // Water SE7 teleportation.
                                 const int32_t osect = sprite[OW].sectnum;
 
                                 Bassert(sectlotag==ST_1_ABOVE_WATER || sectlotag==ST_2_UNDERWATER);
 
-                                k = A_Spawn(j,WATERSPLASH2);
-                                if (sectlotag == ST_1_ABOVE_WATER && sprite[j].statnum == STAT_PROJECTILE)
-                                {
-                                    sprite[k].xvel = sprite[j].xvel>>1;
-                                    sprite[k].ang = sprite[j].ang;
-                                    A_SetSprite(k,CLIPMASK0);
-                                }
+								if(!g_netClient) // [75] For right now clients should not spawn their own watersplash
+								{
+
+									k = A_Spawn(j,WATERSPLASH2);
+									if (sectlotag == ST_1_ABOVE_WATER && sprite[j].statnum == STAT_PROJECTILE)
+									{
+										sprite[k].xvel = sprite[j].xvel>>1;
+										sprite[k].ang = sprite[j].ang;
+										A_SetSprite(k,CLIPMASK0);
+									}
+								}
 
-                                //
                                 actor[j].lasttransport = totalclock + (TICSPERFRAME<<2);
 
                                 sprite[j].x += (sprite[OW].x-SX);
@@ -3565,7 +3869,7 @@ ACTOR_STATIC void G_MoveTransports(void)
                                 changespritesect(j, sprite[OW].sectnum);
                             }
                             else if (Bassert(sectlotag==0), 1)
-                            {
+                            { // [75] k in this block is the id of the spawned TRANSPORTERBEAM sprite
                                 // Non-water SE7 teleportation.
 
                                 if (onfloorz)
@@ -3582,11 +3886,14 @@ ACTOR_STATIC void G_MoveTransports(void)
 
                                         if (sprite[i].pal == 0)
                                         {
-                                            k = A_Spawn(i,TRANSPORTERBEAM);
-                                            A_PlaySound(TELEPORTER,k);
-
-                                            k = A_Spawn(OW,TRANSPORTERBEAM);
-                                            A_PlaySound(TELEPORTER,k);
+											if(!g_netClient) // [75] For right now, clients should not spawn their own teleporter effects
+											{
+												k = A_Spawn(i,TRANSPORTERBEAM);
+												A_PlaySound(TELEPORTER,k);
+
+												k = A_Spawn(OW,TRANSPORTERBEAM);
+												A_PlaySound(TELEPORTER,k);
+											}
                                         }
 
                                         if (sprite[OW].owner != OW)
@@ -3658,7 +3965,16 @@ ACTOR_STATIC void G_MoveActors(void)
         int32_t *const t = actor[i].t_data;
 
         if (s->xrepeat == 0 || sect < 0 || sect >= MAXSECTORS)
-            KILLIT(i);
+		{
+			if(!g_netClient) // [75] Clients should not delete actors that are outside of the map, just goto bolt
+			{
+				KILLIT(i);
+			}
+			else
+			{
+				goto BOLT;
+			}
+		}
 
         Bmemcpy(&actor[i].bpos, s, sizeof(vec3_t));
 
@@ -3678,36 +3994,43 @@ ACTOR_STATIC void G_MoveActors(void)
                 {
                     t[0] = 0;
                     s->cstat = 128+257+16;
-                    s->extra = 1;
+
+					if(!g_netClient) // [75] Clients should not modify TARGETs' health
+					{
+						 s->extra = 1;
+					}
                 }
             }
             else
             {
-                if (A_IncurDamage(i) >= 0)
-                {
-                    int32_t k = 1;
-
-                    s->cstat = 32+128;
-
-                    for (SPRITES_OF(STAT_ACTOR, j))
-                    {
-                        if (sprite[j].lotag == s->lotag && sprite[j].picnum == s->picnum)
-                        {
-                            if ((sprite[j].hitag!=0) ^ ((sprite[j].cstat&32)!=0))
-                            {
-                                k = 0;
-                                break;
-                            }
-                        }
-                    }
-
-                    if (k == 1)
-                    {
-                        G_OperateActivators(s->lotag,-1);
-                        G_OperateForceFields(i,s->lotag);
-                        G_OperateMasterSwitches(s->lotag);
-                    }
-                }
+				if(!g_netClient) // [75] Clients should not operate target activators
+				{
+					if (A_IncurDamage(i) >= 0)
+					{
+						int32_t k = 1;
+
+						s->cstat = 32+128;
+
+						for (SPRITES_OF(STAT_ACTOR, j))
+						{
+							if (sprite[j].lotag == s->lotag && sprite[j].picnum == s->picnum)
+							{
+								if ((sprite[j].hitag!=0) ^ ((sprite[j].cstat&32)!=0))
+								{
+									k = 0;
+									break;
+								}
+							}
+						}
+
+						if (k == 1)
+						{
+							G_OperateActivators(s->lotag,-1);
+							G_OperateForceFields(i,s->lotag);
+							G_OperateMasterSwitches(s->lotag);
+						}
+					}
+				}
             }
             goto BOLT;
 
@@ -3715,7 +4038,16 @@ ACTOR_STATIC void G_MoveActors(void)
         case RESPAWNMARKERYELLOW__STATIC:
         case RESPAWNMARKERGREEN__STATIC:
             if (++T1 > g_itemRespawnTime)
-                KILLIT(i);
+			{
+				if(!g_netClient) // [75] for right now, clients should not remove respawn markers
+				{
+					 KILLIT(i);
+				}
+				else
+				{
+					goto BOLT;
+				}
+			}
 
             if (T1 >= (g_itemRespawnTime>>1) && T1 < ((g_itemRespawnTime>>1)+(g_itemRespawnTime>>2)))
                 PN = RESPAWNMARKERYELLOW;
@@ -3735,12 +4067,33 @@ ACTOR_STATIC void G_MoveActors(void)
             if (t[0] > (GAMETICSPERSEC*8))
             {
                 S_PlaySound(RPG_EXPLODE);
-                for (j=0; j<32; j++) RANDOMSCRAP;
+                for (j=0; j<32; j++) 
+				{
+					if(!g_netClient) //[75] For right now, Clients should not spawn scrap when a helicopter / duke car explodes
+					{
+						RANDOMSCRAP;
+					}
+				}
+
                 g_earthquakeTime = 16;
-                KILLIT(i);
+
+				if(!g_netClient) //[75] For right now, Clients should not delete duke cars / helicopters, just goto BOLT
+				{
+					KILLIT(i);
+				}
+				else
+				{
+					goto BOLT;
+				}
             }
             else if ((t[0]&3) == 0)
-                A_Spawn(i,EXPLOSION2);
+			{
+				if(!g_netClient) // [75] For right now, Clients should not spawn explosion trails for duke cars/helicopters
+				{
+					A_Spawn(i,EXPLOSION2);
+				}
+
+			}
             A_SetSprite(i,CLIPMASK0);
             break;
 
@@ -3756,7 +4109,14 @@ ACTOR_STATIC void G_MoveActors(void)
                 T1++;
                 if (T1 > 1)
                 {
-                    KILLIT(i);
+					if(!g_netClient) //[75] for right now, clients should not delete rats
+					{
+						KILLIT(i);
+					}
+					else
+					{
+						goto BOLT;
+					}
                 }
                 else s->ang = (krand()&2047);
             }
@@ -3770,8 +4130,20 @@ ACTOR_STATIC void G_MoveActors(void)
             if (s->xvel)
             {
                 for (SPRITES_OF(STAT_DEFAULT, j))
+				{
                     if (sprite[j].picnum == POCKET && ldist(&sprite[j],s) < 52)
-                        KILLIT(i);
+					{
+						if(!g_netClient) // [75] for right now, clients should not delete pool balls that fall into pockets
+						{
+							 KILLIT(i);
+						}
+						else
+						{
+							goto BOLT;
+						}
+
+					}
+				}
 
                 j = clipmove((vec3_t *)s,&s->sectnum,
                              (((s->xvel*(sintable[(s->ang+512)&2047]))>>14)*TICSPERFRAME)<<11,
@@ -3855,6 +4227,7 @@ ACTOR_STATIC void G_MoveActors(void)
                 s->yvel = 1;
 
                 for (l=512; l<(2048-512); l+= 128)
+				{
                     for (j=0; j<2048; j += 128)
                     {
                         int32_t k = A_Spawn(i,FORCESPHERE);
@@ -3865,6 +4238,7 @@ ACTOR_STATIC void G_MoveActors(void)
                         sprite[k].xvel = sintable[(l+512)&2047]>>9;
                         sprite[k].owner = i;
                     }
+				}
             }
 
             if (t[3] > 0)
@@ -3876,7 +4250,16 @@ ACTOR_STATIC void G_MoveActors(void)
                     s->z = sector[sect].floorz;
                 t[3]--;
                 if (t[3] == 0)
-                    KILLIT(i);
+				{				
+					if(!g_netClient) // [75] Clients should not delete FORCESPHEREs
+					{
+						 KILLIT(i);
+					}
+					else
+					{
+						goto BOLT;
+					}
+				}
             }
             else if (t[2] > 10)
             {
@@ -3934,25 +4317,34 @@ ACTOR_STATIC void G_MoveActors(void)
                 }
                 else if (g_noEnemies == 2) s->cstat = 257;
             }
-            if (A_IncurDamage(i) >= 0)
-            {
-                if (s->extra < 0 && t[0] != -1)
-                {
-                    t[0] = -1;
-                    s->extra = 0;
-                }
 
-                A_PlaySound(RECO_PAIN,i);
-                RANDOMSCRAP;
-            }
+			if(!g_netClient) //[75] Clients should not handle damaging recons or spawning scrap
+			{
+				if (A_IncurDamage(i) >= 0)
+				{
+					if (s->extra < 0 && t[0] != -1)
+					{
+						t[0] = -1;
+						s->extra = 0;
+					}
+
+					A_PlaySound(RECO_PAIN,i);
+					RANDOMSCRAP;
+				}
+			}
 
             if (t[0] == -1)
             {
                 s->z += 1024;
                 t[2]++;
 
-                if ((t[2]&3) == 0)
-                    A_Spawn(i,EXPLOSION2);
+				if(!g_netClient) // [75] For right now, clients should not handle spawning explosions for the recon self destruct
+				{
+					if ((t[2]&3) == 0)
+					{
+						A_Spawn(i,EXPLOSION2);
+					}
+				}
 
                 A_GetZLimits(i);
                 s->ang += 96;
@@ -3961,16 +4353,22 @@ ACTOR_STATIC void G_MoveActors(void)
 
                 if (!j || s->z > actor[i].floorz)
                 {
-                    for (l=0; l<16; l++)
-                        RANDOMSCRAP;
-                    j = A_Spawn(i,EXPLOSION2);
-                    A_PlaySound(LASERTRIP_EXPLODE,j);
-                    A_Spawn(i,PIGCOP);
-                    g_player[myconnectindex].ps->actors_killed++;
-                    KILLIT(i);
-                }
+					if(!g_netClient) // [75] Clients should not handle a spawning scrap, spawning the recon's explosion, deletion of the recon, or pig cop spawning
+					{
+						for (l=0; l<16; l++)
+						{
+							RANDOMSCRAP;
+						}
+						j = A_Spawn(i,EXPLOSION2);
+						A_PlaySound(LASERTRIP_EXPLODE,j);					
+						A_Spawn(i,PIGCOP);
+						g_player[myconnectindex].ps->actors_killed++;
+						KILLIT(i); 
+					}
+                } //[75] note that clients must goto BOLT
                 goto BOLT;
             }
+
             else
             {
                 if (s->z > actor[i].floorz-(48<<8))
@@ -3992,7 +4390,12 @@ ACTOR_STATIC void G_MoveActors(void)
                     int32_t a = s->ang;
                     s->ang = actor[i].tempang;
                     A_PlaySound(RECO_ATTACK,i);
-                    A_Shoot(i,FIRELASER);
+
+					if(!g_netClient) // [75] Clients should not cause RECONs to shoot lasers, play the sound though.
+					{
+						 A_Shoot(i,FIRELASER);
+					}
+
                     s->ang = a;
                 }
                 if (t[2] > (GAMETICSPERSEC*3) || !cansee(s->x,s->y,s->z-(16<<8),s->sectnum, ps->pos.x,ps->pos.y,ps->pos.z,ps->cursectnum))
@@ -4026,7 +4429,11 @@ ACTOR_STATIC void G_MoveActors(void)
                     else if ((t[2]&15) == 0)
                     {
                         A_PlaySound(RECO_ATTACK,i);
-                        A_Shoot(i,FIRELASER);
+
+						if(!g_netClient) // [75] Clients should not cause RECONs to shoot lasers, play the sound though. (#2)
+						{
+							 A_Shoot(i,FIRELASER);
+						}
                     }
                 }
                 s->ang += G_GetAngleDelta(s->ang,getangle(ps->pos.x-s->x,ps->pos.y-s->y))>>2;
@@ -4088,8 +4495,18 @@ ACTOR_STATIC void G_MoveActors(void)
                         s->hitag = j = actor[i].t_data[5];
                         s->owner = A_FindLocator(j,-1);
                         j = s->owner;
+
                         if (j == -1)
-                            KILLIT(i);
+						{
+							if(!g_netClient) // [75] Clients should not delete RECONs
+							{
+								 KILLIT(i);
+							}
+							else
+							{
+								goto BOLT;
+							}
+						}
                     }
                     else s->hitag++;
                 }
@@ -4150,7 +4567,16 @@ ACTOR_STATIC void G_MoveActors(void)
             t[1]+=128;
 
             if (sector[sect].floorstat&1)
-                KILLIT(i);
+			{
+				if(!g_netClient) //[75] Clients should not delete GREENSLIME on parallax floors
+				{
+					 KILLIT(i);
+				}
+				else
+				{
+					goto BOLT;
+				}
+			}
 
             p = A_FindPlayer(s,&x);
             ps = g_player[p].ps;
@@ -4180,23 +4606,27 @@ ACTOR_STATIC void G_MoveActors(void)
                 s->picnum = GREENSLIME+2;
                 s->extra = 1;
                 s->pal = 1;
-                if ((j = A_IncurDamage(i)) >= 0)
-                {
-                    if (j == FREEZEBLAST) goto BOLT;
-                    for (j=16; j >= 0 ; j--)
-                    {
-                        int32_t k = A_InsertSprite(SECT,SX,SY,SZ,GLASSPIECES+(j%3),-32,36,36,krand()&2047,32+(krand()&63),1024-(krand()&1023),i,5);
-                        sprite[k].pal = 1;
-                    }
-                    A_PlaySound(GLASS_BREAKING,i);
-                    KILLIT(i);
-                }
-                else if (x < 1024 && ps->quick_kick == 0)
-                {
-                    j = G_GetAngleDelta(ps->ang,getangle(SX-ps->pos.x,SY-ps->pos.y));
-                    if (j > -128 && j < 128)
-                        ps->quick_kick = 14;
-                }
+
+				if(!g_netClient) //[75] Clients should not handle GREENSLIME freezing deaths
+				{
+					if ((j = A_IncurDamage(i)) >= 0)
+					{
+						if (j == FREEZEBLAST) goto BOLT;
+						for (j=16; j >= 0 ; j--)
+						{
+							int32_t k = A_InsertSprite(SECT,SX,SY,SZ,GLASSPIECES+(j%3),-32,36,36,krand()&2047,32+(krand()&63),1024-(krand()&1023),i,5);
+							sprite[k].pal = 1;
+						}
+						A_PlaySound(GLASS_BREAKING,i);
+						KILLIT(i);
+					}
+					else if (x < 1024 && ps->quick_kick == 0)
+					{
+						j = G_GetAngleDelta(ps->ang,getangle(SX-ps->pos.x,SY-ps->pos.y));
+						if (j > -128 && j < 128)
+							ps->quick_kick = 14;
+					}
+				}
 
                 goto BOLT;
             }
@@ -4239,7 +4669,15 @@ ACTOR_STATIC void G_MoveActors(void)
                         t[0] = -3;
                         if (ps->somethingonplayer == i)
                             ps->somethingonplayer = -1;
-                        KILLIT(i);
+
+						if(!g_netClient) // [75] Clients should not delete GREENSLIME that is on the player
+						{
+							KILLIT(i);
+						}
+						else
+						{
+							goto BOLT;
+						}
                     }
 
                 s->z = ps->pos.z+ps->pyoff-t[2]+(8<<8);
@@ -4299,36 +4737,39 @@ ACTOR_STATIC void G_MoveActors(void)
                 }
             }
 
-            if ((j = A_IncurDamage(i)) >= 0)
-            {
-                A_PlaySound(SLIM_DYING,i);
-
-                ps->actors_killed ++;
-                if (ps->somethingonplayer == i)
-                    ps->somethingonplayer = -1;
-
-                if (j == FREEZEBLAST)
-                {
-                    A_PlaySound(SOMETHINGFROZE,i);
-                    t[0] = -5 ;
-                    t[3] = 0 ;
-                    goto BOLT;
-                }
-
-                if ((krand()&255) < 32)
-                {
-                    j = A_Spawn(i,BLOODPOOL);
-                    sprite[j].pal = 0;
-                }
-
-                for (x=0; x<8; x++)
-                {
-                    j = A_InsertSprite(sect,s->x,s->y,s->z-(8<<8),SCRAP3+(krand()&3),-8,48,48,krand()&2047,(krand()&63)+64,-(krand()&4095)-(s->zvel>>2),i,5);
-                    sprite[j].pal = 6;
-                }
-                t[0] = -3;
-                KILLIT(i);
-            }
+			if(!g_netClient) //[75] Clients should not handle GREENSLIME being killed by players
+			{
+				if ((j = A_IncurDamage(i)) >= 0)
+				{
+					A_PlaySound(SLIM_DYING,i);
+
+					ps->actors_killed ++;
+					if (ps->somethingonplayer == i)
+						ps->somethingonplayer = -1;
+
+					if (j == FREEZEBLAST)
+					{
+						A_PlaySound(SOMETHINGFROZE,i);
+						t[0] = -5 ;
+						t[3] = 0 ;
+						goto BOLT;
+					}
+
+					if ((krand()&255) < 32)
+					{
+						j = A_Spawn(i,BLOODPOOL);
+						sprite[j].pal = 0;
+					}
+
+					for (x=0; x<8; x++)
+					{
+						j = A_InsertSprite(sect,s->x,s->y,s->z-(8<<8),SCRAP3+(krand()&3),-8,48,48,krand()&2047,(krand()&63)+64,-(krand()&4095)-(s->zvel>>2),i,5);
+						sprite[j].pal = 6;
+					}
+					t[0] = -3;
+					KILLIT(i);
+				}
+			}
             // All weap
             if (t[0] == -1) //Shrinking down
             {
@@ -4383,6 +4824,8 @@ ACTOR_STATIC void G_MoveActors(void)
                             // to decrease the maximum kill count by one.
                             if (sprite[t[5]].extra > 0)
                                 g_player[myconnectindex].ps->max_actors_killed--;
+
+							NET_75_CHECK++; // watch out for slimers eating another enemy's effect on max kill count
                         }
                     }
                 }
@@ -4512,8 +4955,13 @@ ACTOR_STATIC void G_MoveActors(void)
         if (s->xvel != 0)
         case MORTER__STATIC:
         {
-            j = A_Spawn(i,(PLUTOPAK?FRAMEEFFECT1:FRAMEEFFECT1_13));
-            actor[j].t_data[0] = 3;
+			if(!g_netClient) // [75] For now, clients should not spawn frameeffect
+			{
+				j = A_Spawn(i,(PLUTOPAK?FRAMEEFFECT1:FRAMEEFFECT1_13));
+				actor[j].t_data[0] = 3;
+
+				// [75] WARNING: j for clients is invalid at this point
+			}
         }
             /* fall-through */
         case HEAVYHBOMB__STATIC:
@@ -4541,14 +4989,17 @@ ACTOR_STATIC void G_MoveActors(void)
 
             if (t[3] == 0)
             {
-                if (A_IncurDamage(i) >= 0)
-                {
-                    t[3] = 1;
-                    t[2] = 0;
-                    l = 0;
-                    s->xvel = 0;
-                    goto DETONATEB;
-                }
+				if(!g_netClient) // [75] Clients should not apply damage from pipebombs
+				{
+					if (A_IncurDamage(i) >= 0)
+					{
+						t[3] = 1;
+						t[2] = 0;
+						l = 0;
+						s->xvel = 0;
+						goto DETONATEB;
+					}
+				}
             }
 
             if (s->picnum != BOUNCEMINE)
@@ -4588,7 +5039,11 @@ ACTOR_STATIC void G_MoveActors(void)
                 if (t[5] == 0)
                 {
                     t[5] = 1;
-                    A_Spawn(i,WATERSPLASH2);
+
+					if(!g_netClient) // [75] for right now, clients should not spawn WATERSPLASH
+					{
+						 A_Spawn(i,WATERSPLASH2);
+					}
                 }
             }
             else t[5] = 0;
@@ -4602,7 +5057,7 @@ ACTOR_STATIC void G_MoveActors(void)
                 goto DETONATEB;
             }
 
-            if (sprite[s->owner].picnum == APLAYER)
+            if (sprite[s->owner].picnum == APLAYER) // [75] set l to player index in G_MoveActors
                 l = P_Get(s->owner);
             else l = -1;
 
@@ -4677,13 +5132,16 @@ DETONATEB:
                         break;
                     }
 
-                    A_RadiusDamage(i, m,x>>2,x>>1,x-(x>>2),x);
-                    j = A_Spawn(i,EXPLOSION2);
-                    A_PlaySound(PIPEBOMB_EXPLODE,j);
-                    if (s->zvel == 0)
-                        A_Spawn(i,EXPLOSION2BOT);
-                    for (x=0; x<8; x++)
-                        RANDOMSCRAP;
+					if(!g_netClient) //[75] Clients should not do bomb explosions or spawn scrap
+					{
+						A_RadiusDamage(i, m,x>>2,x>>1,x-(x>>2),x);
+						j = A_Spawn(i,EXPLOSION2);
+						A_PlaySound(PIPEBOMB_EXPLODE,j);
+						if (s->zvel == 0)
+							A_Spawn(i,EXPLOSION2BOT);
+						for (x=0; x<8; x++)
+							RANDOMSCRAP;
+					}
                 }
 
                 if (s->yrepeat)
@@ -4696,12 +5154,24 @@ DETONATEB:
                 {
                     if (s->owner != i || ud.respawn_items == 0)
                     {
-                        KILLIT(i);
+						if(!g_netClient) // [75] Clients should not delete bombs
+						{
+							KILLIT(i);
+						}
+						else
+						{
+							goto BOLT;
+						}
                     }
                     else
                     {
                         t[2] = g_itemRespawnTime;
-                        A_Spawn(i,RESPAWNMARKERRED);
+
+						if(!g_netClient) // [75] Clients should not spawn bomb respawn markers for pipebombs (pickup sprites?)
+						{
+							A_Spawn(i,RESPAWNMARKERRED);
+						}
+
                         s->cstat = 32768;
                         s->yrepeat = 9;
                         goto BOLT;
@@ -4739,12 +5209,25 @@ DETONATEB:
                         {
                             if (s->owner == i && (GametypeFlags[ud.coop] & GAMETYPE_WEAPSTAY))
                                 goto BOLT;
-                            KILLIT(i);
+
+							if(!g_netClient) // [75] Clients should not delete pipebomb pickup sprites on pickup
+							{
+								KILLIT(i);
+							}
+							else
+							{
+								goto BOLT;
+							}
                         }
                         else
                         {
                             t[2] = g_itemRespawnTime;
-                            A_Spawn(i,RESPAWNMARKERRED);
+
+							if(!g_netClient) //[75] Clients should not spawn respawn markers for pipebomb pickups
+							{
+								A_Spawn(i,RESPAWNMARKERRED);
+							}
+
                             s->cstat = 32768;
                         }
                     }
@@ -4833,12 +5316,15 @@ DETONATEB:
                 switch (t[1])
                 {
                 case 3:
-                    //Turn on all of those flashing sectoreffector.
-                    A_RadiusDamage(i, 4096,
-                                   g_impactDamage<<2,
-                                   g_impactDamage<<2,
-                                   g_impactDamage<<2,
-                                   g_impactDamage<<2);
+					if(!g_netClient) // [75] Clients should not run REACTOR RadiusDamage
+					{
+						//Turn on all of those flashing sectoreffector.
+						A_RadiusDamage(i, 4096,
+									   g_impactDamage<<2,
+									   g_impactDamage<<2,
+									   g_impactDamage<<2,
+									   g_impactDamage<<2);
+					}
 
                     for (SPRITES_OF(STAT_STANDABLE, j))
                     {
@@ -4853,31 +5339,46 @@ DETONATEB:
                 case 7:
                 case 10:
                 case 15:
+					if(g_netClient) // [75] Clients should not delete sprites around a reactor
+					{
+						break;
+					}
+
                     for (SPRITES_OF_SECT(sect, j))
+					{
                         if (j != i)
                         {
                             A_DeleteSprite(j);
                             break;
                         }
+					}
 
                     break;
-                }
+                } // end switch t[1]
 
-                for (x=0; x<16; x++)
-                    RANDOMSCRAP;
+				if(!g_netClient) //[75] Clients should not spawn scrap for a reactor
+				{
+					for (x=0; x<16; x++)
+					{
+						RANDOMSCRAP;
+					}
+				}
 
                 s->z = t[4];
                 t[4] = 0;
             }
             else
             {
-                if (A_IncurDamage(i) >= 0)
-                {
-                    for (x=0; x<32; x++)
-                        RANDOMSCRAP;
-                    if (s->extra < 0)
-                        t[1] = 1;
-                }
+				if(!g_netClient) // [75] Clients should not do damage to a reactor or spawn scrap
+				{
+					if (A_IncurDamage(i) >= 0)
+					{
+						for (x=0; x<32; x++)
+							RANDOMSCRAP;
+						if (s->extra < 0)
+							t[1] = 1;
+					}
+				}
             }
             goto BOLT;
         }
@@ -4889,13 +5390,16 @@ DETONATEB:
                 t[1]+=8;
                 if (g_damageCameras)
                 {
-                    if (A_IncurDamage(i) >= 0)
-                    {
-                        t[0] = 1; // static
-                        s->cstat = 32768;
-                        for (x=0; x<5; x++) RANDOMSCRAP;
-                        goto BOLT;
-                    }
+					if(!g_netClient) //[75] Clients should not do damage to cameras
+					{
+						if (A_IncurDamage(i) >= 0)
+						{
+							t[0] = 1; // static
+							s->cstat = 32768;
+							for (x=0; x<5; x++) RANDOMSCRAP;
+							goto BOLT;
+						}
+					}
                 }
 
                 if (s->hitag > 0)
@@ -4957,7 +5461,16 @@ ACTOR_STATIC void G_MoveMisc(void)  // STATNUM 5
         int32_t switchpicnum;
 
         if (sect < 0 || s->xrepeat == 0)
-            KILLIT(i);
+		{
+			if(!g_netClient) //Clients should not delete STAT_MISC sprites that are outside of the map or shrunken to oblivion
+			{
+				 KILLIT(i);
+			}
+			else
+			{
+				goto BOLT;
+			}
+		}
 
         Bmemcpy(&actor[i].bpos, s, sizeof(vec3_t));
 
@@ -4975,8 +5488,8 @@ ACTOR_STATIC void G_MoveMisc(void)  // STATNUM 5
             actor[i].floorz = s->z = getflorzofslope(s->sectnum,s->x,s->y);
         else switch (DYNAMICTILEMAP(switchpicnum))
             {
-            case APLAYER__STATIC:
-                s->cstat = 32768;
+            case APLAYER__STATIC: //[75] set player invisible (?)
+                s->cstat = 32768; // [75] invisible
                 goto BOLT;
             case NEON1__STATIC:
             case NEON2__STATIC:
@@ -5073,7 +5586,16 @@ ACTOR_STATIC void G_MoveMisc(void)  // STATNUM 5
                 if (t[0] == 1)
                 {
                     if (sector[sect].lotag != ST_1_ABOVE_WATER && sector[sect].lotag != ST_2_UNDERWATER)
-                        KILLIT(i);
+					{
+						if(!g_netClient) // [75] Clients should not delete water splashes, just goto bolt
+						{
+							KILLIT(i);
+						}
+						else
+						{
+							goto BOLT;
+						}
+					}
                     /*
                     else
                     {
@@ -5091,7 +5613,13 @@ ACTOR_STATIC void G_MoveMisc(void)  // STATNUM 5
                     t[1]++;  // WATERSPLASH_T2
                 }
                 if (t[1] == 5)
-                    A_DeleteSprite(i);
+				{
+					if(!g_netClient) // [75] Clients should not delete water splashes (#2)
+					{
+						A_DeleteSprite(i);
+					}
+
+				}
                 goto BOLT;
 
             case FRAMEEFFECT1_13__STATIC:
@@ -5104,7 +5632,14 @@ ACTOR_STATIC void G_MoveMisc(void)  // STATNUM 5
 
                     if (t[0] > 7)
                     {
-                        KILLIT(i);
+						if(!g_netClient) // [75] clients should not delete FRAMEEFFECT
+						{
+							KILLIT(i);
+						}
+						else
+						{
+							goto BOLT;
+						}
                     }
                     else if (t[0] > 4)
                         s->cstat |= 512+2;
@@ -5127,12 +5662,25 @@ ACTOR_STATIC void G_MoveMisc(void)  // STATNUM 5
             }
 
             case FIRELASER__STATIC:
+				if(g_netClient) // [75] clients should not set projectile damage / delete projectiles
+				{
+					break;
+				}
+
                 if (s->extra != 5)
                     s->extra = 5;
                 else KILLIT(i);
                 break;
+
             case TONGUE__STATIC:
-                KILLIT(i);
+				if(!g_netClient) // [75] clients should not delete TONGUE
+				{
+					KILLIT(i);
+				}
+				else
+				{
+					goto BOLT;
+				}
 
             case MONEY__STATIC:
             case MAIL__STATIC:
@@ -5157,7 +5705,17 @@ ACTOR_STATIC void G_MoveMisc(void)  // STATNUM 5
                     setsprite(i,(vec3_t *)s);
 
                 if (s->sectnum == -1)
-                    KILLIT(i);
+				{
+					if(!g_netClient) // [75] Clients should not delete MONEY, MAIL, or PAPER that's outside of the map
+					{
+						KILLIT(i);
+					}
+					else
+					{
+						goto BOLT;
+					}
+				}
+
                 l = getflorzofslope(s->sectnum,s->x,s->y);
 
                 if (s->z > l)
@@ -5200,7 +5758,16 @@ ACTOR_STATIC void G_MoveMisc(void)  // STATNUM 5
                 else s->xvel = 0;
 
                 if (++t[5] == (30*10))
-                    KILLIT(i);
+				{
+					if(!g_netClient) // [75] Clients for right now should not delete various gibs
+					{
+						KILLIT(i);
+					}
+					else
+					{
+						goto BOLT;
+					}
+				}
 
                 if (s->zvel > 1024 && s->zvel < 1280)
                 {
@@ -5209,7 +5776,17 @@ ACTOR_STATIC void G_MoveMisc(void)  // STATNUM 5
                 }
 
                 getzsofslope(sect,s->x,s->y,&x,&l);
-                if (x == l || sect < 0 || sect >= MAXSECTORS) KILLIT(i);
+                if (x == l || sect < 0 || sect >= MAXSECTORS) 
+				{
+					if(!g_netClient) // [75] Clients for right now should not delete various gibs #2
+					{
+						KILLIT(i);
+					}
+					else
+					{
+						goto BOLT;
+					}
+				}
 
                 if (s->z < l-(2<<8))
                 {
@@ -5251,10 +5828,28 @@ ACTOR_STATIC void G_MoveMisc(void)  // STATNUM 5
                     if (t[2] == 0)
                     {
                         if (s->sectnum == -1)
-                            KILLIT(i);
+						{
+							if(!g_netClient) // [75] Clients for right now should not delete various gibs #3
+							{
+								 KILLIT(i);
+							}
+							else
+							{
+								goto BOLT;
+							}
+						}
 
                         if ((sector[s->sectnum].floorstat&2))
-                            KILLIT(i);
+						{
+							if(!g_netClient) // [75] Clients for right now should not delete various gibs #4
+							{
+								KILLIT(i);
+							}
+							else
+							{
+								goto BOLT;
+							}
+						}
 
                         t[2]++;
                     }
@@ -5269,7 +5864,16 @@ ACTOR_STATIC void G_MoveMisc(void)  // STATNUM 5
                         if ((t[1]&3) == 0 && t[0] < 7)
                             t[0]++;
                         if (t[1] > 20)
-                            KILLIT(i);
+						{
+							if(!g_netClient) // [75] Clients for right now should not delete various gibs #5
+							{
+								KILLIT(i);
+							}
+							else
+							{
+								goto BOLT;
+							}
+						}
                     }
                     else
                     {
@@ -5292,7 +5896,14 @@ ACTOR_STATIC void G_MoveMisc(void)  // STATNUM 5
                     t[0] = 1;
                     if (sector[sect].floorstat&2)
                     {
-                        KILLIT(i);
+						if(!g_netClient) // [75] for right now, clients should not delete puke/blood pools
+						{
+							KILLIT(i);
+						}
+						else
+						{
+							goto BOLT;
+						}
                     }
                     else A_AddToDeleteQueue(i);
                 }
@@ -5390,7 +6001,16 @@ ACTOR_STATIC void G_MoveMisc(void)  // STATNUM 5
                 A_SetSprite(i,CLIPMASK0);
 
                 if (sect < 0 || (sector[sect].floorz + 256) < s->z)
-                    KILLIT(i);
+				{
+					if(!g_netClient) // [75] For right now, clients should not delete shell / shotgunshell sprites
+					{
+						KILLIT(i);
+					}
+					else
+					{
+						goto BOLT;
+					}
+				}
 
                 if (sector[sect].lotag == ST_2_UNDERWATER)
                 {
@@ -5431,8 +6051,18 @@ ACTOR_STATIC void G_MoveMisc(void)  // STATNUM 5
                 A_Fall(i);
 
                 if (s->zvel > 4096) s->zvel = 4096;
+
                 if (sect < 0)
-                    KILLIT(i);
+				{
+					if(!g_netClient) // [75] for right now, clients should not delete glass pieces
+					{
+						KILLIT(i);
+					}
+					else
+					{
+						goto BOLT;
+					}
+				}
 
                 if (s->z == actor[i].floorz-(ZOFFSET) && t[0] < 3)
                 {
@@ -5446,7 +6076,16 @@ ACTOR_STATIC void G_MoveMisc(void)  // STATNUM 5
                     t[0]++;//Number of bounces
                 }
                 else if (t[0] == 3)
-                    KILLIT(i);
+				{
+					if(!g_netClient) //[75] for right now, clients should not delete glass pieces #2
+					{
+						KILLIT(i);
+					}
+					else
+					{
+						goto BOLT;
+					}
+				}
 
                 if (s->xvel > 0)
                 {
@@ -5508,7 +6147,14 @@ ACTOR_STATIC void G_MoveMisc(void)  // STATNUM 5
                     sprite[j].hitag = sprite[j].lotag = 0;
                 }
 
-                KILLIT(i);
+				if(!g_netClient) // [75] for right now, clients should not delete scrap
+				{
+					KILLIT(i);
+				}
+				else
+				{
+					goto BOLT;
+				}
             }
             goto BOLT;
         }
@@ -5559,6 +6205,7 @@ static void HandleSE31(int32_t i, int32_t setfloorzp, int32_t zref, int32_t t2va
 }
 
 // s: SE sprite
+// [75] : Note, this function is set to have clients not kill the player 
 static void MaybeTrainKillPlayer(const spritetype *s, int32_t dosetopos)
 {
     int32_t p;
@@ -5586,7 +6233,11 @@ static void MaybeTrainKillPlayer(const spritetype *s, int32_t dosetopos)
                 ps->cursectnum = s->sectnum;
 
                 setsprite(ps->i,(vec3_t const *)s);
-                P_QuickKill(ps);
+
+				if(!g_netClient) //[75] clients should not kill players with subway cars
+				{
+					 P_QuickKill(ps);
+				}
             }
         }
     }
@@ -5597,6 +6248,7 @@ static void MaybeTrainKillEnemies(int32_t i, int32_t numguts)
 {
     int32_t j = headspritesect[sprite[OW].sectnum];
 
+
     while (j >= 0)
     {
         const int32_t nextj = nextspritesect[j];
@@ -5606,12 +6258,16 @@ static void MaybeTrainKillEnemies(int32_t i, int32_t numguts)
             int16_t k = sprite[j].sectnum;
 
             updatesector(sprite[j].x,sprite[j].y,&k);
-            if (k == sprite[i].sectnum)
-            {
-                A_DoGutsDir(j,JIBS6,numguts);
-                A_PlaySound(SQUISHED,j);
-                A_DeleteSprite(j);
-            }
+
+			if(!g_netClient) // [75] Clients should not do the actual sprite deletion or guts spawning when a train hits an enemy
+			{
+				if (k == sprite[i].sectnum)
+				{
+					A_DoGutsDir(j,JIBS6,numguts);
+					A_PlaySound(SQUISHED,j);
+					A_DeleteSprite(j);
+				}
+			}
         }
 
         j = nextj;
@@ -5624,6 +6280,8 @@ ACTOR_STATIC void G_MoveEffectors(void)   //STATNUM 3
     int32_t q=0, j, k, l, m, x;
     int32_t i = headspritestat[STAT_EFFECTOR];
 
+	NET_75_CHECK++; // verify: should effector actions be server only?
+
     while (i >= 0)
     {
         const int32_t nexti = nextspritestat[i];
@@ -5652,7 +6310,16 @@ ACTOR_STATIC void G_MoveEffectors(void)   //STATNUM 3
             j = s->owner;
 
             if (sprite[j].lotag == UINT16_MAX)
-                KILLIT(i);
+			{
+				if(!g_netClient) // clients should not delete STAT_EFFECTORS with a lotag of UINT16_MAX
+				{
+				    KILLIT(i);
+				}
+				else
+				{
+					goto BOLT;
+				}
+			}
 
             q = sc->extra>>3;
             l = 0;
@@ -5719,7 +6386,17 @@ ACTOR_STATIC void G_MoveEffectors(void)   //STATNUM 3
             else
             {
                 if (actor[j].t_data[0] == 0) break;
-                if (actor[j].t_data[0] == 2) KILLIT(i);
+                if (actor[j].t_data[0] == 2) 
+				{
+					if(!g_netClient) //[75] Clients should not delete STAT_EFFECTORs (ROTATING_SECTOR) if owner t_data[0] == 2
+					{
+						KILLIT(i);
+					}
+					else
+					{
+						goto BOLT;
+					}
+				}
 
                 if (sprite[j].ang > 1024)
                     l = -1;
@@ -5765,6 +6442,8 @@ ACTOR_STATIC void G_MoveEffectors(void)   //STATNUM 3
 
                 for (SPRITES_OF_SECT(s->sectnum, p))
                 {
+					NET_75_CHECK++; // [75] watch for rotating sector sprite interpolation for players
+
                     // KEEPINSYNC1
                     if (sprite[p].statnum != STAT_EFFECTOR && sprite[p].statnum != STAT_PROJECTILE)
                         if (sprite[p].picnum != LASERLINE)
@@ -5798,6 +6477,8 @@ ACTOR_STATIC void G_MoveEffectors(void)   //STATNUM 3
                     if (sprite[p].statnum != STAT_EFFECTOR && sprite[p].statnum != STAT_PROJECTILE)
                         if (sprite[p].picnum != LASERLINE)
                         {
+							NET_75_CHECK++; // [75] watch for rotating sector sprite interpolation for players
+
                             if (sprite[p].picnum == APLAYER && sprite[p].owner >= 0)
                                 continue;
 
@@ -5922,7 +6603,11 @@ ACTOR_STATIC void G_MoveEffectors(void)   //STATNUM 3
                         {
                             j = s->ang;
                             s->ang = getangle(s->x-g_player[p].ps->pos.x,s->y-g_player[p].ps->pos.y);
-                            A_Shoot(i,RPG);
+
+							if(!g_netClient) //[75] Clients' subway cars should not shoot RPG missiles (?)
+							{
+								A_Shoot(i,RPG);
+							}
                             s->ang = j;
                         }
                     }
@@ -6210,7 +6895,15 @@ ACTOR_STATIC void G_MoveEffectors(void)   //STATNUM 3
                 {
                     t[0] = -1; //Stop the quake
                     t[4] = -1;
-                    KILLIT(i);
+
+					if(!g_netClient) // [75] clients should not delete their earthquake SEs, just goto Bolt
+					{
+						 KILLIT(i);
+					}
+					else
+					{
+						goto BOLT;
+					}
                 }
                 else
                 {
@@ -6233,6 +6926,8 @@ ACTOR_STATIC void G_MoveEffectors(void)   //STATNUM 3
                 {
                     DukePlayer_t *const ps = g_player[p].ps;
 
+					NET_75_CHECK++; // [75] If client view gets jittery during an earthquake the effects may need to be clientside only
+
                     if (ps->cursectnum == s->sectnum && ps->on_ground)
                     {
                         ps->pos.x += m;
@@ -6356,7 +7051,16 @@ ACTOR_STATIC void G_MoveEffectors(void)   //STATNUM 3
             }
 
             if (t[4])
-                KILLIT(i);
+			{
+				if(!g_netClient) // [75] clients for right now should not delete RANDOM_LIGHTS SEs, just goto BOLT
+				{
+					KILLIT(i);
+				}
+				else
+				{
+					goto BOLT;
+				}
+			}
 
             break;
         }
@@ -6371,7 +7075,12 @@ ACTOR_STATIC void G_MoveEffectors(void)   //STATNUM 3
             {
                 j = s->ang;
                 s->ang = getangle(s->x-ps->pos.x,s->y-ps->pos.y);
-                A_Shoot(i,FIRELASER);
+
+				if(!g_netClient) // [75] Clients' SE_5 (BOSS) should not shoot lasers
+				{
+					 A_Shoot(i,FIRELASER);
+				}
+
                 s->ang = j;
             }
 
@@ -6427,14 +7136,17 @@ ACTOR_STATIC void G_MoveEffectors(void)   //STATNUM 3
                 sc->ceilingshade = 0;
             }
 
-            if (A_IncurDamage(i) >= 0)
-            {
-                if (++t[3] == 5)
-                {
-                    s->zvel += 1024;
-                    P_DoQuote(QUOTE_WASTED, g_player[myconnectindex].ps);
-                }
-            }
+			if(!g_netClient)  // [75] Clients' SE_5 (BOSS) should not call A_IncurDamage
+			{
+				if (A_IncurDamage(i) >= 0)
+				{
+					if (++t[3] == 5)
+					{
+						s->zvel += 1024;
+						P_DoQuote(QUOTE_WASTED, g_player[myconnectindex].ps);
+					}
+				}
+			}
 
             s->z += s->zvel;
             sc->ceilingz += s->zvel;
@@ -6455,7 +7167,16 @@ ACTOR_STATIC void G_MoveEffectors(void)   //STATNUM 3
             {
                 actor[i].t_data[4]++;
                 if (actor[i].t_data[4] > 8)
-                    KILLIT(i);
+				{
+					if(!g_netClient) //[75] Clients should not delete their SE_8 or SE_9 (up/down open_door_lights)
+					{
+						KILLIT(i);
+					}
+					else
+					{
+						goto BOLT;
+					}
+				}
                 j = 1;
             }
             else j = GetAnimationGoal(&sc->ceilingz);
@@ -6633,7 +7354,16 @@ ACTOR_STATIC void G_MoveEffectors(void)   //STATNUM 3
                 }
 
                 if (t[3] == 1)
-                    KILLIT(i);
+				{
+					if(!g_netClient) // [75] Clients should not delete their SE12s (SE_12_LIGHT_SWITCH)
+					{
+						 KILLIT(i);
+					}
+					else
+					{
+						goto BOLT;
+					}
+				}
             }
             if (t[0] == 1)   //Lights flickering on
             {
@@ -6749,7 +7479,16 @@ ACTOR_STATIC void G_MoveEffectors(void)   //STATNUM 3
                 }
                 t[2]++;
                 if (t[2] > 256)
-                    KILLIT(i);
+				{
+					if(!g_netClient) // [75] Clients should not delete their own SE13s (EXPLOSIVE)
+					{
+						KILLIT(i);
+					}
+					else
+					{
+						goto BOLT;
+					}
+				}
             }
 
 
@@ -6810,7 +7549,16 @@ ACTOR_STATIC void G_MoveEffectors(void)   //STATNUM 3
                 }
 
                 if (j == -1)
-                    KILLIT(i);
+				{
+					if(!g_netClient) // [75] Clients should not delete their own SE_16_REACTORs
+					{
+						KILLIT(i);
+					}
+					else
+					{
+						goto BOLT;
+					}
+				}
 
                 s->shade = 1;
             }
@@ -6947,7 +7695,15 @@ ACTOR_STATIC void G_MoveEffectors(void)   //STATNUM 3
                         if (sc->ceilingz <= t[1])
                         {
                             sc->ceilingz = t[1];
-                            KILLIT(i);
+
+							if(!g_netClient) // [75] clients should not delete their own SE18 (INCREMENTAL_SECTOR_RISE_FALL) if sc->ceilingz <= t[1]
+							{
+								KILLIT(i);
+							}
+							else
+							{
+								goto BOLT;
+							}
                         }
                     }
                     else
@@ -6970,7 +7726,16 @@ ACTOR_STATIC void G_MoveEffectors(void)   //STATNUM 3
                         if (sc->floorz >= t[1])
                         {
                             sc->floorz = t[1];
-                            KILLIT(i);
+
+							if(!g_netClient) // [75] clients should not delete their own SE18 (INCREMENTAL_SECTOR_RISE_FALL) if sc->floorz <= t[1]
+							{
+								 KILLIT(i);
+							}
+							else
+							{
+								goto BOLT;
+							}
+
                         }
                     }
                 }
@@ -6982,7 +7747,15 @@ ACTOR_STATIC void G_MoveEffectors(void)   //STATNUM 3
                         if (sc->ceilingz >= s->z)
                         {
                             sc->ceilingz = s->z;
-                            KILLIT(i);
+
+							if(!g_netClient) // [75] Clients should not delete their own SE18 (INCREMENTAL_SECTOR_RISE_FALL) if sc->ceilingz >= s->z
+							{
+								KILLIT(i);
+							}
+							else
+							{
+								goto BOLT;
+							}
                         }
                     }
                     else
@@ -7005,7 +7778,15 @@ ACTOR_STATIC void G_MoveEffectors(void)   //STATNUM 3
                         if (sc->floorz <= s->z)
                         {
                             sc->floorz = s->z;
-                            KILLIT(i);
+
+							if(!g_netClient) // [75] Clients should not delete their own SE18 (INCREMENTAL_SECTOR_RISE_FALL) if sc->floorz <= s->z
+							{
+								KILLIT(i);
+							}
+							else
+							{
+								goto BOLT;
+							}
                         }
                     }
                 }
@@ -7061,7 +7842,14 @@ ACTOR_STATIC void G_MoveEffectors(void)   //STATNUM 3
                         }
                     }
 
-                    KILLIT(i);
+					if(!g_netClient) //[75] Clients should not delete their own SE19 (EXPLOSION_LOWERS_CEILING)
+					{
+						KILLIT(i);
+					}
+					else
+					{
+						goto BOLT;
+					}
                 }
             }
             else //Not hit yet
@@ -7197,7 +7985,15 @@ ACTOR_STATIC void G_MoveEffectors(void)   //STATNUM 3
                 if (klabs(*zptr-s->z) < 1024)
                 {
                     *zptr = s->z;
-                    KILLIT(i); //All done   // SE_21_KILLIT, see sector.c
+
+					if(!g_netClient) // [75] Clients should not delete their own SE_21_DROP_FLOOR
+					{
+						 KILLIT(i); //All done   // SE_21_KILLIT, see sector.c
+					}
+					else
+					{
+						goto BOLT;
+					}
                 }
             }
             else sc->extra--;
@@ -7422,6 +8218,8 @@ ACTOR_STATIC void G_MoveEffectors(void)   //STATNUM 3
             int32_t p;
             DukePlayer_t *ps;
 
+			NET_75_CHECK++; // SE_27_DEMO_CAM: may be worth expanding this?
+
             if (ud.recstat == 0 || !ud.democams) break;
 
             actor[i].tempang = s->ang;
@@ -7534,7 +8332,11 @@ ACTOR_STATIC void G_MoveEffectors(void)   //STATNUM 3
                                 DukePlayer_t *ps;
 
                                 sprite[j].cstat &= 32767;
-                                A_Spawn(j,SMALLSMOKE);
+
+								if(!g_netClient) // [75] for right now, clients should not spawn SMALLSMOKE with SE_28 (lightning)
+								{
+									 A_Spawn(j,SMALLSMOKE);
+								}
 
                                 p = A_FindPlayer(s, NULL);
                                 ps = g_player[p].ps;
@@ -7659,11 +8461,22 @@ ACTOR_STATIC void G_MoveEffectors(void)   //STATNUM 3
             break;
 
         case SE_33_QUAKE_DEBRIS:
+			if(g_netClient) //[75] For right now, Clients should not run SE_33_QUAKE_DEBRIS
+			{
+				break;
+			}
+
             if (g_earthquakeTime > 0 && (krand()&7) == 0)
                 RANDOMSCRAP;
             break;
 
         case SE_36_PROJ_SHOOTER:
+			if(g_netClient) //[75] For right now, clients should not run SE_36_PROJ_SHOOTER
+			{
+				break;
+			}
+
+
             if (t[0])
             {
                 if (t[0] == 1)
@@ -7698,12 +8511,28 @@ ACTOR_STATIC void G_MoveEffectors(void)   //STATNUM 3
             {
                 wal->cstat &= (128+32+8+4+2);
                 if (wal->nextwall >= 0)
+				{
                     wall[wal->nextwall].cstat &= (128+32+8+4+2);
-                KILLIT(i);
+				}
+
+				if(!g_netClient) //[75] For right now, clients should not delete SE_128 (What is SE 128?)
+				{
+					KILLIT(i);
+				}
+				else
+				{
+					goto BOLT;
+				}
+
             }
             break;
 
         case SE_130:
+			if(g_netClient) // [75] Clients should not run SE_130 (don't know what it is but it spawns stuff)
+			{
+				break;
+			}
+
             if (t[0] > 80)
             {
                 KILLIT(i);
@@ -7724,6 +8553,11 @@ ACTOR_STATIC void G_MoveEffectors(void)   //STATNUM 3
             break;
 
         case SE_131:
+			if(g_netClient) // [75] Clients should not run SE_131 (don't know what it is but it spawns stuff)
+			{
+				break;
+			}
+
             if (t[0] > 40)
             {
                 KILLIT(i);
@@ -8162,16 +8996,17 @@ static void A_DoLight(int32_t i, int32_t smoothratio)
                 s->y += y;
             }
             break;
-        case APLAYER__STATIC:
+        case APLAYER__STATIC: //[75] do weapon glowing / muzzle flash lights (OPENGL only)
         {
-            int const snum = sprite[i].yvel;
-            DukePlayer_t *p = g_player[snum].ps;
+            int const snum = sprite[i].yvel; // [75] player index / from yvel
+            DukePlayer_t *p = g_player[snum].ps; // [75] player struct from sprite yvel
 
             if (!(PWEAPON(snum, p->curr_weapon, Flags) & WEAPON_NOVISIBLE) && p->kickback_pic && P_WeaponState(snum, 0))
             {
                 spritetype *s = &sprite[p->i];
                 int32_t x = ((sintable[(s->ang + 512) & 2047]) >> 7), y = ((sintable[(s->ang) & 2047]) >> 7);
 
+				//[75] temporarly shift the player, stick a light on them for the gun flash, then shift them right back again
                 s->x += x;
                 s->y += y;
 
@@ -8182,7 +9017,7 @@ static void A_DoLight(int32_t i, int32_t smoothratio)
                 s->y -= y;
             }
 
-            if (PWEAPON(snum, p->curr_weapon, Flags) & WEAPON_GLOWS)
+            if (PWEAPON(snum, p->curr_weapon, Flags) & WEAPON_GLOWS) //[75] shrinker / expander pulse lights
             {
                 if (p->kickback_pic == 0)
                 {
diff --git a/source/astub.c b/source/astub.c
index 7bb5176..0ca8f23 100644
--- a/source/astub.c
+++ b/source/astub.c
@@ -10502,7 +10502,7 @@ void ExtAnalyzeSprites(int32_t ourx, int32_t oury, int32_t oura, int32_t smoothr
             if (frames==0) frames = 10;
         case ROTATEGUN :
         case CAMERA1:
-        case APLAYER :
+        case APLAYER : 
             if (frames==0) frames=1;
         case GREENSLIME :
         case PIGCOPSTAYPUT :
diff --git a/source/game.c b/source/game.c
index 28c8824..47e07eb 100644
--- a/source/game.c
+++ b/source/game.c
@@ -22,6 +22,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 #define game_c_
 
+
+
 #include "duke3d.h"
 #include "compat.h"
 #include "renderlayer.h"
@@ -69,6 +71,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 # endif
 #endif /* _WIN32 */
 
+static int32_t NET_75_CHECK = 0;
+
 const char* AppProperName = "EDuke32";
 const char* AppTechnicalName = "eduke32";
 
@@ -498,7 +502,10 @@ static void G_PrintCoords(int32_t snum)
     const int32_t x = 250;
     int32_t y = 16;
 
+	// player structure
     const DukePlayer_t *ps = g_player[snum].ps;
+
+	// sector the player is in
     const int32_t sectnum = ps->cursectnum;
 
     if ((GametypeFlags[ud.coop] & GAMETYPE_FRAGBAR))
@@ -2710,7 +2717,13 @@ static spritesmooth_t NullSprSmooth;
 int32_t A_InsertSprite(int16_t whatsect,int32_t s_x,int32_t s_y,int32_t s_z,int16_t s_pn,int8_t s_s,
                        uint8_t s_xr,uint8_t s_yr,int16_t s_a,int16_t s_ve,int16_t s_zv,int16_t s_ow,int16_t s_ss)
 {
+	NET_75_CHECK++; //[75] Temporarily bypassed net sprites vs client sprites
+
+	//note that bypassing Net_InsertSprite completely and using insertsprite made the client behave much more smoothly!
+
+
     int32_t i = Net_IsRelevantStat(s_ss) ? Net_InsertSprite(whatsect, s_ss) : insertsprite(whatsect, s_ss);
+	//int32_t i = insertsprite(whatsect, s_ss);
 
     if (EDUKE32_PREDICT_FALSE(i) < 0)
     {
@@ -3427,7 +3440,7 @@ int32_t A_Spawn(int32_t j, int32_t pn)
             break;
 
         case DUKELYINGDEAD__STATIC:
-            if (j >= 0 && sprite[j].picnum == APLAYER)
+            if (j >= 0 && sprite[j].picnum == APLAYER) //[75] spawn DUKELYINGDEAD, set x/y repeat to spawner's x/yrepeat
             {
                 sp->xrepeat = sprite[j].xrepeat;
                 sp->yrepeat = sprite[j].yrepeat;
@@ -3610,7 +3623,7 @@ int32_t A_Spawn(int32_t j, int32_t pn)
             changespritestat(i, STAT_DUMMYPLAYER);
             break;
 
-        case APLAYER__STATIC:
+        case APLAYER__STATIC: //[75] make player sprites intended as spawns invisible, make them STAT_MISC in single player, otherwise STAT_PLAYER
             sp->xrepeat = sp->yrepeat = 0;
             sp->cstat = 32768;
             if ((!g_netServer && ud.multimode < 2) ||
@@ -4891,7 +4904,10 @@ static inline void G_DoEventAnimSprites(int32_t j)
 
 void G_DoSpriteAnimations(int32_t ourx, int32_t oury, int32_t oura, int32_t smoothratio)
 {
-    int32_t j, k, p;
+    int32_t j, // spritesortcnt index
+			k, 
+			p;
+
     intptr_t l;
 
     if (spritesortcnt == 0)
@@ -5020,13 +5036,13 @@ void G_DoSpriteAnimations(int32_t ourx, int32_t oury, int32_t oura, int32_t smoo
         int32_t switchpic;
         int32_t curframe;
 #if !defined LUNATIC
-        int32_t scrofs_action;
+        int32_t scrofs_action; //[75] C-CON only, AC_ACTION_ID of current tsprite's "real sprite"
 #else
         int32_t startframe, viewtype;
 #endif
         //is the perfect time to animate sprites
-        tspritetype *const t = &tsprite[j];
-        const int32_t i = t->owner;
+        tspritetype *const t = &tsprite[j]; // [75] current tsprite in spritesortcnt
+        const int32_t i = t->owner; // [75] owner of current tsprite in spritesortcnt (i.e., "real sprite" index into sprite[] or actor[])
         // XXX: what's up with the (i < 0) check?
         // NOTE: not const spritetype because set at SET_SPRITE_NOT_TSPRITE (see below).
         tspritetype *const s = (i < 0) ? &tsprite[j] : (tspritetype *)&sprite[i];
@@ -5048,29 +5064,51 @@ void G_DoSpriteAnimations(int32_t ourx, int32_t oury, int32_t oura, int32_t smoo
 
         Bassert(i >= 0);
 
-        const DukePlayer_t *const ps = (s->statnum != STAT_ACTOR && s->picnum == APLAYER && s->owner >= 0) ? g_player[P_GetP((const spritetype *)s)].ps : NULL;
+        const DukePlayer_t *const ps = 
+			(s->statnum != STAT_ACTOR && s->picnum == APLAYER && s->owner >= 0) 
+				? 
+					g_player[P_GetP((const spritetype *)s)].ps 	: 
+					NULL;
+
         if (ps && ps->newowner == -1)
         {
             t->x -= mulscale16(65536-smoothratio,ps->pos.x-ps->opos.x);
             t->y -= mulscale16(65536-smoothratio,ps->pos.y-ps->opos.y);
+
+			NET_75_CHECK++; // (What the heck?) players can crouch and "walk under" a player corpse, but only until the player respawns.
+			
+			if(ps->dead_flag)
+			{
+				// PHEIGHT is  (38<<8), which is too low
+				t->z += (22<<8); //[75] (2/27/2016) Experimentally determined, the player corpse sprite's on the ground with this offset
+				
+			}			
+
+			/*OLD CODE
+			[75] the problem with this code is that ps->opos.z is getting clobbered, if you look carefully when this code is enabled (and my code above is disabled)
+			you can see the player sprite very briefly flickering down to where it's supposed to be. Also it's not even the right height for the corpse when the player is dead but not respawned.
+
             // dirty hack
             if (ps->dead_flag) t->z = ps->opos.z;
             t->z += mulscale16(smoothratio,ps->pos.z-ps->opos.z) -
-                (ps->dead_flag ? 0 : PHEIGHT) + PHEIGHT;
-        }
+                (ps->dead_flag ? 0 : PHEIGHT) + PHEIGHT; //[75] PHEIGHT is too low!
+
+			*/
+		}
         else if ((s->statnum == STAT_DEFAULT && s->picnum != CRANEPOLE) || s->statnum == STAT_PLAYER ||
                  s->statnum == STAT_STANDABLE || s->statnum == STAT_PROJECTILE || s->statnum == STAT_MISC || s->statnum == STAT_ACTOR)
         {
             t->x -= mulscale16(65536-smoothratio,s->x-actor[i].bpos.x);
             t->y -= mulscale16(65536-smoothratio,s->y-actor[i].bpos.y);
-            t->z -= mulscale16(65536-smoothratio,s->z-actor[i].bpos.z);
+
+			t->z -= mulscale16(65536-smoothratio,s->z-actor[i].bpos.z);
         }
 
         const int32_t sect = s->sectnum;
 
         curframe = AC_CURFRAME(actor[i].t_data);
 #if !defined LUNATIC
-        scrofs_action = AC_ACTION_ID(actor[i].t_data);
+        scrofs_action = AC_ACTION_ID(actor[i].t_data); 
 #else
         startframe = actor[i].ac.startframe;
         viewtype = actor[i].ac.viewtype;
@@ -5086,7 +5124,10 @@ void G_DoSpriteAnimations(int32_t ourx, int32_t oury, int32_t oura, int32_t smoo
         switch (DYNAMICTILEMAP(switchpic))
         {
         case DUKELYINGDEAD__STATIC:
-            t->z += (24<<8);
+
+			// if I do this the sprite is deleted because the previous t += PHEIGHT puts it too low
+			t->z += (24<<8);
+
             break;
         case BLOODPOOL__STATIC:
         case FOOTPRINTS__STATIC:
@@ -5231,7 +5272,7 @@ void G_DoSpriteAnimations(int32_t ourx, int32_t oury, int32_t oura, int32_t smoo
 
             break;
 
-        case APLAYER__STATIC:
+        case APLAYER__STATIC: //[75] do ps->over shoulder, draw weapons over player's head, do model rotation, do viewscreen sprites, set player invisible w/ polymer shadow, get player angle sprite, get player underwater sprite, 
             p = P_GetP((const spritetype *)s);
 
             if (t->pal == 1) t->z -= (18<<8);
@@ -5271,6 +5312,7 @@ void G_DoSpriteAnimations(int32_t ourx, int32_t oury, int32_t oura, int32_t smoo
 
             if ((g_netServer || ud.multimode > 1) && (display_mirror || screenpeek != p || s->owner == -1))
             {
+				//[75] draw weapon sprites above players' heads if the setting is enabled
                 if (ud.showweapons && sprite[g_player[p].ps->i].extra > 0 && g_player[p].ps->curr_weapon > 0
                         && spritesortcnt < MAXSPRITESONSCREEN)
                 {
@@ -5334,13 +5376,13 @@ void G_DoSpriteAnimations(int32_t ourx, int32_t oury, int32_t oura, int32_t smoo
                 if (getrendermode() >= REND_POLYMOST && usemodels && md_tilehasmodel(s->picnum,t->pal) >= 0 && !(spriteext[i].flags&SPREXT_NOTMD))
                 {
                     k = 0;
-                    t->cstat &= ~4;
+                    t->cstat &= ~4; // [75] don't flip sprite x, we're using models
                 }
                 else
 #endif
-                    k = getofs_viewtype5(s, t, oura, 0);
+                    k = getofs_viewtype5(s, t, oura, 0); // [75] get player sprite angle frame
 
-                if (sector[s->sectnum].lotag == ST_2_UNDERWATER) k += 1795-1405;
+                if (sector[s->sectnum].lotag == ST_2_UNDERWATER) k += 1795-1405; //[75] switch to swimming frame
                 else if ((actor[i].floorz-s->z) > (64<<8)) k += 60;
 
                 t->picnum += k;
@@ -5358,6 +5400,11 @@ void G_DoSpriteAnimations(int32_t ourx, int32_t oury, int32_t oura, int32_t smoo
                 else s->yoffset=0;
             }
 
+			NET_75_CHECK++; // WARNING: "display APLAYER sprites with action PSTAND when viewed through a camera".
+
+			// note that this was present even in DOS Duke, g_player is new, used to be ps[MAXPLAYERS]
+			// note that execPtr moved to g_tile[], used to be just an array of pointers, actionscrptptr
+
             if (g_player[p].ps->newowner > -1)
             {
                 // Display APLAYER sprites with action PSTAND when viewed through
@@ -5371,12 +5418,15 @@ void G_DoSpriteAnimations(int32_t ourx, int32_t oury, int32_t oura, int32_t smoo
                 curframe = 0;
             }
 
+			NET_75_CHECK++; // this code sets the player's own sprite from its own view to invisible / invisible but casting plymer shadow
+
             if (ud.camerasprite == -1 && g_player[p].ps->newowner == -1)
                 if (s->owner >= 0 && display_mirror == 0 && g_player[p].ps->over_shoulder_on == 0)
                     if ((!g_netServer && ud.multimode < 2) || ((g_netServer || ud.multimode > 1) && p == screenpeek))
                     {
+						
                         if (getrendermode() == REND_POLYMER)
-                            t->cstat |= 16384;
+                            t->cstat |= 16384; //[75] invisible but still casts a polymer shadow.
                         else
                         {
                             t->owner = -1;
@@ -8347,7 +8397,7 @@ void G_UpdatePlayerFromMenu(void)
     if (numplayers > 1)
     {
         Net_SendClientInfo();
-        if (sprite[g_player[myconnectindex].ps->i].picnum == APLAYER && sprite[g_player[myconnectindex].ps->i].pal != 1)
+        if (sprite[g_player[myconnectindex].ps->i].picnum == APLAYER && sprite[g_player[myconnectindex].ps->i].pal != 1) // [75] set player sprite's color to g_player[myconnectindex].pcolor
             sprite[g_player[myconnectindex].ps->i].pal = g_player[myconnectindex].pcolor;
     }
     else
@@ -9223,11 +9273,12 @@ int32_t G_DoMoveThings(void)
                 sprite[g_player[i].ps->holoduke_on].cstat ^= 256;
 
         if ((hit.sprite >= 0) && !(g_player[myconnectindex].ps->gm & MODE_MENU) &&
-                sprite[hit.sprite].picnum == APLAYER)
+                sprite[hit.sprite].picnum == APLAYER) //[75] display player name when hovering over
         {
             const int32_t snum = P_Get(hit.sprite);
+			const int16_t cIsInvisible = (sprite[hit.sprite].cstat & 32768); //[75] need to add this in so that the engine doesn't display the player name over spawn locations
 
-            if (snum != screenpeek && g_player[snum].ps->dead_flag == 0)
+            if (snum != screenpeek && g_player[snum].ps->dead_flag == 0 && !cIsInvisible)
             {
                 if (p->fta == 0 || p->ftq == QUOTE_RESERVED3)
                 {
@@ -9295,15 +9346,21 @@ int32_t G_DoMoveThings(void)
 
     for (TRAVERSE_CONNECT(i))
     {
-        if (g_player[i].sync->extbits&(1<<6))
-        {
-            g_player[i].ps->team = g_player[i].pteam;
-            if (GametypeFlags[ud.coop] & GAMETYPE_TDM)
-            {
-                actor[g_player[i].ps->i].picnum = APLAYERTOP;
-                P_QuickKill(g_player[i].ps);
-            }
-        }
+		if(!g_netClient) // [75] client should not handle killing players for team game setup (?)
+		{
+			if (g_player[i].sync->extbits&(1<<6))
+			{
+				g_player[i].ps->team = g_player[i].pteam;
+				if (GametypeFlags[ud.coop] & GAMETYPE_TDM)
+				{
+					actor[g_player[i].ps->i].picnum = APLAYERTOP;
+
+					P_QuickKill(g_player[i].ps);
+				
+				}
+			}
+		}
+
         if (GametypeFlags[ud.coop] & GAMETYPE_TDM)
             g_player[i].ps->palookup = g_player[i].pcolor = G_GetTeamPalette(g_player[i].ps->team);
 
@@ -10187,12 +10244,18 @@ void vglass(int32_t x,int32_t y,short a,short wn,short n)
 }
 #endif
 
+//[75] note that the client exits out of this function immediately
 void A_SpawnWallGlass(int32_t i,int32_t wallnum,int32_t n)
 {
     int32_t j, xv, yv, z, x1, y1;
     int16_t sect;
     int32_t a;
 
+	if(g_netClient) // [75] Clients for right now should not spawn broken glass shards
+	{
+		return;
+	}
+
     sect = -1;
 
     if (wallnum < 0)
@@ -10246,12 +10309,18 @@ void A_SpawnGlass(int32_t i,int32_t n)
     }
 }
 
+//[75] Note: clients exit out of this function immediately
 void A_SpawnCeilingGlass(int32_t i,int32_t sectnum,int32_t n)
 {
     int32_t j, xv, yv, z, x1, y1, a,s;
     int32_t startwall = sector[sectnum].wallptr;
     int32_t endwall = startwall+sector[sectnum].wallnum;
 
+	if(g_netClient) //[75] Clients should not spawn ceiling glass
+	{
+		return;
+	}
+
     for (s=startwall; s<(endwall-1); s++)
     {
         x1 = wall[s].x;
diff --git a/source/gameexec.c b/source/gameexec.c
index 5d04dc3..b562531 100644
--- a/source/gameexec.c
+++ b/source/gameexec.c
@@ -20,6 +20,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
 //-------------------------------------------------------------------------
 
+static int NET_75_CHECK = 0;
 
 #include "duke3d.h"
 #include <time.h>
@@ -156,6 +157,8 @@ FORCE_INLINE int32_t VM_EventCommon_(int32_t iEventID, int32_t iActor, int32_t i
 FORCE_INLINE int32_t VM_EventCommon_(const int32_t iEventID, const int32_t iActor, const int32_t iPlayer,
                                      const int32_t lDist, int32_t iReturn)
 {
+	NET_75_CHECK++; // Clients need to know whether their motion should be canceled, server needs to execute "script", client can't wait for the server
+
     // this is initialized first thing because iActor, iPlayer, lDist, etc are already right there on the stack
     // from the function call
     const vmstate_t tempvm = { iActor, iPlayer, lDist, &actor[(unsigned)iActor].t_data[0],
@@ -196,8 +199,11 @@ FORCE_INLINE int32_t VM_EventCommon_(const int32_t iEventID, const int32_t iActo
 
     VM_Execute(1);
 
-    if (vm.g_flags & VM_KILL)
-        VM_DeleteSprite(vm.g_i, vm.g_p);
+	if(!g_netClient) //[75] clients should not delete sprites in VM_EventCommon_
+	{
+		if (vm.g_flags & VM_KILL)
+			VM_DeleteSprite(vm.g_i, vm.g_p);
+	}
 
     // this needs to happen after VM_DeleteSprite() because VM_DeleteSprite()
     // can trigger additional events
@@ -239,7 +245,7 @@ static int32_t VM_CheckSquished(void)
 {
     sectortype const * const sc = &sector[vm.g_sp->sectnum];
 
-    if (sc->lotag == ST_23_SWINGING_DOOR || EDUKE32_PREDICT_FALSE(vm.g_sp->picnum == APLAYER && ud.noclip))
+    if (sc->lotag == ST_23_SWINGING_DOOR || EDUKE32_PREDICT_FALSE(vm.g_sp->picnum == APLAYER && ud.noclip)) // [75] don't squish with swinging doors or noclipped players
         return 0;
 
     {
@@ -431,7 +437,7 @@ void A_GetZLimits(int32_t iActor)
             s->xvel = -256;  // SLIDE_ABOVE_ENEMY
             A_SetSprite(iActor, CLIPMASK0);
         }
-        else if (s->statnum == STAT_PROJECTILE && hitspr->picnum == APLAYER && s->owner==florhit)
+        else if (s->statnum == STAT_PROJECTILE && hitspr->picnum == APLAYER && s->owner==florhit) //[75] if projectile hit player, set ceiling and floor z of player actor to sector ceiling and floor
         {
             actor[iActor].ceilingz = sector[s->sectnum].ceilingz;
             actor[iActor].floorz   = sector[s->sectnum].floorz;
@@ -505,6 +511,7 @@ int32_t G_GetAngleDelta(int32_t a,int32_t na)
     return (na-a);
 }
 
+//[75] clients only execute part of this
 GAMEEXEC_STATIC void VM_AlterAng(int32_t movflags)
 {
     const int32_t ticselapsed = (AC_COUNT(vm.g_t))&31;
@@ -521,9 +528,17 @@ GAMEEXEC_STATIC void VM_AlterAng(int32_t movflags)
 
     moveptr = script + AC_MOVE_ID(vm.g_t);
 
+	NET_75_CHECK++; // verify that it's ok for the beginning of VM_AlterAng to run (if g_sp->zvel < 648)
+
     vm.g_sp->xvel += (moveptr[0] - vm.g_sp->xvel)/5;
     if (vm.g_sp->zvel < 648)
         vm.g_sp->zvel += ((moveptr[1]<<4) - vm.g_sp->zvel)/5;
+
+	if(g_netClient) // [75] Clients only do very basic movements, exit early out of VM_AlterAng
+	{
+		return;
+	}
+
 #else
     vm.g_sp->xvel += (actor[vm.g_i].mv.hvel - vm.g_sp->xvel)/5;
     if (vm.g_sp->zvel < 648)
@@ -657,7 +672,10 @@ GAMEEXEC_STATIC void VM_Move(void)
     const int32_t movflags = /*(*movflagsptr==-1) ? 0 :*/ *movflagsptr;
     const int32_t deadflag = (A_CheckEnemySprite(vm.g_sp) && vm.g_sp->extra <= 0);
 
-    AC_COUNT(vm.g_t)++;
+	NET_75_CHECK++;  //[75] having clients not increment their own AC_COUNT makes sprite movements much laggier but does not fix the animation problems
+
+	AC_COUNT(vm.g_t)++;
+	
 
     if (AC_MOVE_ID(vm.g_t) == 0 || movflags == 0)
     {
@@ -674,26 +692,42 @@ GAMEEXEC_STATIC void VM_Move(void)
         goto dead;
 
     if (movflags&face_player)
-        VM_FacePlayer(2);
+	{
+		if(!g_netClient) // [75] Clients don't execute VM_FacePlayer [note: Zand made this server side]
+		{
+			VM_FacePlayer(2);
+		}
+	}
 
     if (movflags&spin)
         vm.g_sp->ang += sintable[((AC_COUNT(vm.g_t)<<3)&2047)]>>6;
 
     if (movflags&face_player_slow)
-        VM_FacePlayer(4);
+	{
+		if(!g_netClient)	// [75] Clients don't execute VM_FacePlayer slow either
+		{
+			VM_FacePlayer(4);
+		}
+	}
 
     if ((movflags&jumptoplayer_bits) == jumptoplayer_bits)
     {
-        if (AC_COUNT(vm.g_t) < 16)
-            vm.g_sp->zvel -= (sintable[(512+(AC_COUNT(vm.g_t)<<4))&2047]>>5);
+		if(!g_netClient) // [75] Clients don't execute jump to player
+		{
+			if (AC_COUNT(vm.g_t) < 16)
+				vm.g_sp->zvel -= (sintable[(512+(AC_COUNT(vm.g_t)<<4))&2047]>>5);
+		}
     }
 
     if (movflags&face_player_smart)
     {
-        int32_t newx = vm.g_pp->pos.x + (vm.g_pp->vel.x/768);
-        int32_t newy = vm.g_pp->pos.y + (vm.g_pp->vel.y/768);
-        int32_t goalang = getangle(newx-vm.g_sp->x,newy-vm.g_sp->y);
-        VM_AddAngle(2, goalang);
+		if(!g_netClient) // [75] Clients don't execute face_player_smart
+		{
+			int32_t newx = vm.g_pp->pos.x + (vm.g_pp->vel.x/768);
+			int32_t newy = vm.g_pp->pos.y + (vm.g_pp->vel.y/768);
+			int32_t goalang = getangle(newx-vm.g_sp->x,newy-vm.g_sp->y);
+			VM_AddAngle(2, goalang);
+		}
     }
 
 dead:
@@ -715,7 +749,12 @@ dead:
 #endif
 
     if (movflags&dodgebullet && !deadflag)
-        A_Dodge(vm.g_sp);
+	{
+		if(!g_netClient) //[75] clients don't execute A_Dodge
+		{
+		  A_Dodge(vm.g_sp);
+		}
+	}
 
     if (vm.g_sp->picnum != APLAYER)
         VM_AlterAng(movflags);
@@ -730,6 +769,8 @@ dead:
         int32_t daxvel = vm.g_sp->xvel;
         int32_t angdif = vm.g_sp->ang;
 
+		NET_75_CHECK++; // [75] Verify: is hard coded behavior for COMMANDER, DRONE, ORGANTIC OK to run on clients?
+
         if (badguyp && vm.g_sp->picnum != ROTATEGUN)
         {
             if ((vm.g_sp->picnum == DRONE || vm.g_sp->picnum == COMMANDER) && vm.g_sp->extra > 0)
@@ -1389,7 +1430,11 @@ skip_check:
         }
 
         case CON_IFHITWEAPON:
-            VM_CONDITIONAL(A_IncurDamage(vm.g_i) >= 0);
+			if(!g_netClient) //[75] clients should not run CON_IFHITWEAPON, just assume it's false
+			{
+				 VM_CONDITIONAL(A_IncurDamage(vm.g_i) >= 0);
+			}
+           
             continue;
 
         case CON_IFSQUISHED:
@@ -1402,6 +1447,13 @@ skip_check:
 
         case CON_AI:
             insptr++;
+
+			if(g_netClient) //[75] for right now, clients should not run CON_AI
+			{
+				insptr++;
+				continue;
+			}
+
             //Following changed to use pointersizes
             AC_AI_ID(vm.g_t) = *insptr++; // Ai
 
@@ -1422,8 +1474,13 @@ skip_check:
 
         case CON_ACTION:
             insptr++;
-            AC_ACTION_COUNT(vm.g_t) = AC_CURFRAME(vm.g_t) = 0;
-            AC_ACTION_ID(vm.g_t) = *insptr++;
+
+			//[75] there are significant benefits to having clients run CON_ACTION, it's nice 
+			// for decorative actors.
+		
+			AC_ACTION_COUNT(vm.g_t) = AC_CURFRAME(vm.g_t) = 0;
+			AC_ACTION_ID(vm.g_t) = *insptr++;		
+			
             continue;
 
         case CON_IFPLAYERSL:
@@ -1444,12 +1501,29 @@ skip_check:
 
         case CON_ADDSTRENGTH:
             insptr++;
-            vm.g_sp->extra += *insptr++;
+
+			if(!g_netClient) // [75] Clients should not run CON_AddStrength
+			{
+				vm.g_sp->extra += *insptr++;
+			}
+			else
+			{
+				insptr++;
+			}
             continue;
 
         case CON_STRENGTH:
             insptr++;
-            vm.g_sp->extra = *insptr++;
+
+			if(!g_netClient) // [75] Clients should not run CON_STRENGTH
+			{
+				vm.g_sp->extra = *insptr++;
+			}
+			else
+			{
+				insptr++;
+			}
+
             continue;
 
         case CON_IFGOTWEAPONCE:
@@ -1493,7 +1567,11 @@ skip_check:
         case CON_TOSSWEAPON:
             insptr++;
             // NOTE: assumes that current actor is APLAYER
-            P_DropWeapon(P_GetP(vm.g_sp));
+
+			if(!g_netClient) // [75] Clients should not run CON_TOSSWEAPON
+			{
+				P_DropWeapon(P_GetP(vm.g_sp));
+			}
             continue;
 
         case CON_MIKESND:
@@ -1510,6 +1588,8 @@ skip_check:
         case CON_PKICK:
             insptr++;
 
+			NET_75_CHECK++; // bizarre otherp quick kick handling, why is it setting other players' ps->quick_kick?
+
             if ((g_netServer || ud.multimode > 1) && vm.g_sp->picnum == APLAYER)
             {
                 if (g_player[otherp].ps->quick_kick == 0)
@@ -1544,7 +1624,16 @@ skip_check:
 
         case CON_SHOOT:
             insptr++;
-            A_Shoot(vm.g_i,*insptr++);
+
+			if(!g_netClient) //[75] Clients should not run CON_SHOOT
+			{
+				A_Shoot(vm.g_i,*insptr++);
+			}
+			else
+			{
+				insptr++;
+			}
+
             continue;
 
         case CON_SOUNDONCE:
@@ -1702,12 +1791,30 @@ skip_check:
 
         case CON_MONEY:
             insptr++;
-            A_SpawnMultiple(vm.g_i, MONEY, *insptr++);
+
+			if(!g_netClient) // [75] For right now, Clients should not spawn money
+			{
+				A_SpawnMultiple(vm.g_i, MONEY, *insptr++);
+			}
+			else
+			{
+				insptr++;
+			}
+
             continue;
 
         case CON_MAIL:
             insptr++;
-            A_SpawnMultiple(vm.g_i, MAIL, *insptr++);
+
+			if(!g_netClient) //[75] For right now, Clients should not spawn mail
+			{
+				A_SpawnMultiple(vm.g_i, MAIL, *insptr++);
+			}
+			else
+			{
+				insptr++;
+			}
+
             continue;
 
         case CON_SLEEPTIME:
@@ -1717,18 +1824,43 @@ skip_check:
 
         case CON_PAPER:
             insptr++;
-            A_SpawnMultiple(vm.g_i, PAPER, *insptr++);
+
+			if(!g_netClient) //[75] Clients should not spawn paper
+			{
+				A_SpawnMultiple(vm.g_i, PAPER, *insptr++);
+			}
+			else
+			{
+				insptr++;
+			}
+
             continue;
 
         case CON_ADDKILLS:
             insptr++;
-            ps->actors_killed += *insptr++;
-            actor[vm.g_i].actorstayput = -1;
+
+			if(!g_netClient) //[75] Clients should not run ADDKILLS
+			{
+				ps->actors_killed += *insptr++;
+				actor[vm.g_i].actorstayput = -1;
+			}
+			else
+			{
+				insptr++;
+			}
             continue;
 
         case CON_LOTSOFGLASS:
             insptr++;
-            A_SpawnGlass(vm.g_i,*insptr++);
+
+			if(!g_netClient) //[75] For right now, clients should not run CON_LOTSOFGLASS
+			{
+				 A_SpawnGlass(vm.g_i,*insptr++);
+			}
+			else
+			{
+				insptr++;
+			}
             continue;
 
         case CON_KILLIT:
@@ -1761,6 +1893,7 @@ skip_check:
         case CON_ADDPHEALTH:
             insptr++;
 
+			if(!g_netClient) //[75] Clients should not run CON_ADDPHEALTH
             {
                 if (ps->newowner >= 0)
                     G_ClearCameraView(ps);
@@ -1921,7 +2054,12 @@ skip_check:
 
         case CON_INSERTSPRITEQ:
             insptr++;
-            A_AddToDeleteQueue(vm.g_i);
+
+			if(!g_netClient) //[75] clients should not run CON_INSERTSPRITEQ
+			{
+				A_AddToDeleteQueue(vm.g_i);
+			}
+
             continue;
 
         case CON_QSTRLEN:
@@ -2268,6 +2406,11 @@ skip_check:
                         Bstrcpy(ScriptQuotes[i],ScriptQuotes[j]);
                     break;
                 case CON_CHANGESPRITESECT:
+					if(g_netClient) //[75] Clients should not run CON_CHANGESPRITESECT
+					{
+						break;
+					}
+
                     if (EDUKE32_PREDICT_FALSE((unsigned)i >= MAXSPRITES))
                     {
                         CON_ERRPRINTF("Invalid sprite %d\n", i);
@@ -2294,6 +2437,11 @@ nullquote:
                 int32_t i = Gv_GetVarX(*insptr++);
                 int32_t j = Gv_GetVarX(*insptr++);
 
+				if(g_netClient) //[75] clients should not run CON_CHANGESPRITESTAT
+				{
+					continue;
+				}
+
                 if (EDUKE32_PREDICT_FALSE((unsigned)i >= MAXSPRITES))
                 {
                     CON_ERRPRINTF("Invalid sprite: %d\n", i);
@@ -2575,6 +2723,12 @@ nullquote:
             {
                 int const lIn = Gv_GetVarX(*insptr++);
 
+				if(g_netClient) // [75] clients should not run ESPAWNVAR, EQSPAWNVAR, or QSPAWNVAR
+				{
+					continue;
+				}
+
+
                 if (EDUKE32_PREDICT_FALSE((unsigned)vm.g_sp->sectnum >= (unsigned)numsectors))
                 {
                     CON_ERRPRINTF("Invalid sector %d\n", TrackerCast(vm.g_sp->sectnum));
@@ -2612,6 +2766,12 @@ nullquote:
                     continue;
                 }
 
+				if(g_netClient) // [75] clients should not run ESPAWN, EQSPAWN, or QSPAWN
+				{
+					insptr++;
+					continue;
+				}
+
                 int const j = A_Spawn(vm.g_i,*insptr++);
 
                 switch (tw)
@@ -2635,6 +2795,12 @@ nullquote:
         case CON_ZSHOOT:
             insptr++;
             {
+				if(g_netClient) // [75] clients should not run ESHOOT, EZSHOOT, or ZSHOOT
+				{
+					insptr++;
+					continue;
+				}
+
                 // NOTE: (int16_t) cast because we want to exclude that
                 // SHOOT_HARDCODED_ZVEL is passed.
                 int const zvel = (tw == CON_ESHOOT) ?
@@ -2658,6 +2824,12 @@ nullquote:
         case CON_ESHOOTVAR:
             insptr++;
             {
+				if(g_netClient) // [75] clients should not run SHOOTVAR or ESHOOTVAR
+				{
+					insptr++;
+					continue;
+				}
+
                 int j = Gv_GetVarX(*insptr++);
 
                 if (EDUKE32_PREDICT_FALSE((unsigned)vm.g_sp->sectnum >= (unsigned)numsectors))
@@ -2678,6 +2850,12 @@ nullquote:
         case CON_ZSHOOTVAR:
             insptr++;
             {
+				if(g_netClient) // [75] clients should not run CON_EZSHOOTVAR or CON_ZSHOOTVAR
+				{
+					insptr++;
+					continue;
+				}
+
                 int const zvel = (int16_t)Gv_GetVarX(*insptr++);
                 int j = Gv_GetVarX(*insptr++);
 
@@ -3343,6 +3521,13 @@ nullquote:
 
         case CON_SPAWN:
             insptr++;
+
+			if(g_netClient) // [75] clients should not run CON_SPAWN
+			{
+				insptr++;
+				continue;
+			}
+
             if ((unsigned)vm.g_sp->sectnum >= MAXSECTORS)
             {
                 CON_ERRPRINTF("Invalid sector %d\n", TrackerCast(vm.g_sp->sectnum));
@@ -3364,7 +3549,12 @@ nullquote:
 
         case CON_IFACTION:
             insptr++;
-            VM_CONDITIONAL(AC_ACTION_ID(vm.g_t) == *insptr);
+
+			if(!g_netClient) //[75] (testing) disable clients running CON_IFACTION
+			{
+				VM_CONDITIONAL(AC_ACTION_ID(vm.g_t) == *insptr);
+			}
+
             continue;
 
         case CON_IFACTIONCOUNT:
@@ -3383,23 +3573,28 @@ nullquote:
                 int32_t dnum = *insptr++;
                 int32_t s, l, j;
 
-                if ((unsigned)vm.g_sp->sectnum < MAXSECTORS)
-                    for (j=(*insptr)-1; j>=0; j--)
-                    {
-                        if (vm.g_sp->picnum == BLIMP && dnum == SCRAP1)
-                            s = 0;
-                        else s = (krand()%3);
-
-                        l = A_InsertSprite(vm.g_sp->sectnum,
-                                           vm.g_sp->x+(krand()&255)-128,vm.g_sp->y+(krand()&255)-128,vm.g_sp->z-(8<<8)-(krand()&8191),
-                                           dnum+s,vm.g_sp->shade,32+(krand()&15),32+(krand()&15),
-                                           krand()&2047,(krand()&127)+32,
-                                           -(krand()&2047),vm.g_i,5);
-                        if (vm.g_sp->picnum == BLIMP && dnum == SCRAP1)
-                            sprite[l].yvel = BlimpSpawnSprites[j%14];
-                        else sprite[l].yvel = -1;
-                        sprite[l].pal = vm.g_sp->pal;
-                    }
+				if(!g_netClient) // [75] clients should not run CON_DEBRIS
+				{
+					if ((unsigned)vm.g_sp->sectnum < MAXSECTORS)
+					{
+						for (j=(*insptr)-1; j>=0; j--)
+						{
+							if (vm.g_sp->picnum == BLIMP && dnum == SCRAP1)
+								s = 0;
+							else s = (krand()%3);
+
+							l = A_InsertSprite(vm.g_sp->sectnum,
+											   vm.g_sp->x+(krand()&255)-128,vm.g_sp->y+(krand()&255)-128,vm.g_sp->z-(8<<8)-(krand()&8191),
+											   dnum+s,vm.g_sp->shade,32+(krand()&15),32+(krand()&15),
+											   krand()&2047,(krand()&127)+32,
+											   -(krand()&2047),vm.g_i,5);
+							if (vm.g_sp->picnum == BLIMP && dnum == SCRAP1)
+								sprite[l].yvel = BlimpSpawnSprites[j%14];
+							else sprite[l].yvel = -1;
+							sprite[l].pal = vm.g_sp->pal;
+						}
+					}
+				}
                 insptr++;
             }
             continue;
@@ -3572,12 +3767,21 @@ nullquote:
             {
                 int32_t params[5];
                 Gv_GetManyVars(5, params);
+
+				if(g_netClient) // [75] clients should not run CON_HITRADIUSVAR
+				{
+					continue;
+				}
+
                 A_RadiusDamage(vm.g_i, params[0], params[1], params[2], params[3], params[4]);
             }
             continue;
 
         case CON_HITRADIUS:
-            A_RadiusDamage(vm.g_i,*(insptr+1),*(insptr+2),*(insptr+3),*(insptr+4),*(insptr+5));
+			if(!g_netClient) // [75] Clients should not run CON_HITRADIUS
+			{
+				 A_RadiusDamage(vm.g_i,*(insptr+1),*(insptr+2),*(insptr+3),*(insptr+4),*(insptr+5));
+			}
             insptr += 6;
             continue;
 
@@ -3626,7 +3830,10 @@ nullquote:
             continue;
 
         case CON_GUTS:
-            A_DoGuts(vm.g_i,*(insptr+1),*(insptr+2));
+			if(!g_netClient) // [75] Clients should not run CON_GUTS
+			{
+				 A_DoGuts(vm.g_i,*(insptr+1),*(insptr+2));
+			}
             insptr += 3;
             continue;
 
@@ -5474,6 +5681,9 @@ finish_qsprintf:
 
         case CON_PSTOMP:
             insptr++;
+
+			NET_75_CHECK++; // [75] Make sure that infinite stomp loop is resolved for CON_PSTOMP
+
             if (ps->knee_incs == 0 && sprite[ps->i].xrepeat >= 40)
                 if (cansee(vm.g_sp->x, vm.g_sp->y, vm.g_sp->z - (4 << 8), vm.g_sp->sectnum, ps->pos.x,
                            ps->pos.y, ps->pos.z + (16 << 8), sprite[ps->i].sectnum))
@@ -5677,7 +5887,11 @@ void A_LoadActor(int32_t iActor)
 
     if ((unsigned)vm.g_sp->sectnum >= MAXSECTORS)
     {
-        A_DeleteSprite(vm.g_i);
+		if(!g_netClient) //[75] Clients in A_LoadActor should not delete sprites that are outside of any sector
+		{
+			 A_DeleteSprite(vm.g_i);
+		}
+
         return;
     }
 
@@ -5686,7 +5900,12 @@ void A_LoadActor(int32_t iActor)
     insptr = NULL;
 
     if (vm.g_flags & VM_KILL)
-        A_DeleteSprite(vm.g_i);
+	{
+		if(!g_netClient) //[75] Clients in A_LoadActor should not A_DeleteSprite s that are dead
+		{
+			A_DeleteSprite(vm.g_i);
+		}
+	}
 }
 #endif
 
@@ -5715,10 +5934,13 @@ void A_Execute(int32_t iActor, int32_t iPlayer, int32_t lDist)
 
     if (EDUKE32_PREDICT_FALSE((unsigned)vm.g_sp->sectnum >= MAXSECTORS))
     {
-        if (A_CheckEnemySprite(vm.g_sp))
-            vm.g_pp->actors_killed++;
+		if(!g_netClient) //[75] Clients should not delete sprites that are outside of any sector in A_Execute
+		{
+			if (A_CheckEnemySprite(vm.g_sp))
+				vm.g_pp->actors_killed++;
 
-        A_DeleteSprite(vm.g_i);
+			A_DeleteSprite(vm.g_i);
+		}
         return;
     }
 
@@ -5726,62 +5948,73 @@ void A_Execute(int32_t iActor, int32_t iPlayer, int32_t lDist)
     actionofs = AC_ACTION_ID(vm.g_t);
     actionptr = (actionofs != 0 && actionofs + 4u < (unsigned)g_scriptSize) ? &script[actionofs] : NULL;
 
-    if (actionptr != NULL)
+	NET_75_CHECK++; // having clients advance count and curframe works OK but it's jerky, it's very obvious that the client is getting ahead of the server a bit
+
+	if (actionptr != NULL)
 #endif
-    {
+	{
 #if !defined LUNATIC
-        const int32_t action_frames = actionptr[1];
-        const int32_t action_incval = actionptr[3];
-        const int32_t action_delay = actionptr[4];
+		const int32_t action_frames = actionptr[1];
+		const int32_t action_incval = actionptr[3];
+		const int32_t action_delay = actionptr[4];
 #else
-        const int32_t action_frames = actor[vm.g_i].ac.numframes;
-        const int32_t action_incval = actor[vm.g_i].ac.incval;
-        const int32_t action_delay = actor[vm.g_i].ac.delay;
+		const int32_t action_frames = actor[vm.g_i].ac.numframes;
+		const int32_t action_incval = actor[vm.g_i].ac.incval;
+		const int32_t action_delay = actor[vm.g_i].ac.delay;
 #endif
-        uint16_t *actionticsptr = &AC_ACTIONTICS(vm.g_sp, &actor[vm.g_i]);
-        *actionticsptr += TICSPERFRAME;
-
-        if (*actionticsptr > action_delay)
-        {
-            *actionticsptr = 0;
-            AC_ACTION_COUNT(vm.g_t)++;
-            AC_CURFRAME(vm.g_t) += action_incval;
-        }
-
-        if (klabs(AC_CURFRAME(vm.g_t)) >= klabs(action_frames * action_incval))
-            AC_CURFRAME(vm.g_t) = 0;
-    }
+		uint16_t *actionticsptr = &AC_ACTIONTICS(vm.g_sp, &actor[vm.g_i]);
+		*actionticsptr += TICSPERFRAME;
+
+		if (*actionticsptr > action_delay)
+		{
+			*actionticsptr = 0;
+			AC_ACTION_COUNT(vm.g_t)++;
+			AC_CURFRAME(vm.g_t) += action_incval;
+		}
+
+		if (klabs(AC_CURFRAME(vm.g_t)) >= klabs(action_frames * action_incval))
+			AC_CURFRAME(vm.g_t) = 0;
+	}
+
+	if(!g_netClient) //[75] clients should not run VM_Execute on the execptr of g_sp
+	{
+	#ifdef LUNATIC
+		const int32_t picnum = vm.g_sp->picnum;
+
+		if (L_IsInitialized(&g_ElState) && El_HaveActor(picnum))
+		{
+			double t = gethiticks();
+
+			killit = (El_CallActor(&g_ElState, picnum, iActor, iPlayer, lDist)==1);
+
+			t = gethiticks()-t;
+			g_actorTotalMs[picnum] += t;
+			g_actorMinMs[picnum] = min(g_actorMinMs[picnum], t);
+			g_actorMaxMs[picnum] = max(g_actorMaxMs[picnum], t);
+			g_actorCalls[picnum]++;
+		}
+	#else
+		insptr = 4 + (g_tile[vm.g_sp->picnum].execPtr);
+		VM_Execute(1);
+	}
+
+	
 
-#ifdef LUNATIC
-    const int32_t picnum = vm.g_sp->picnum;
-
-    if (L_IsInitialized(&g_ElState) && El_HaveActor(picnum))
-    {
-        double t = gethiticks();
-
-        killit = (El_CallActor(&g_ElState, picnum, iActor, iPlayer, lDist)==1);
-
-        t = gethiticks()-t;
-        g_actorTotalMs[picnum] += t;
-        g_actorMinMs[picnum] = min(g_actorMinMs[picnum], t);
-        g_actorMaxMs[picnum] = max(g_actorMaxMs[picnum], t);
-        g_actorCalls[picnum]++;
-    }
-#else
-    insptr = 4 + (g_tile[vm.g_sp->picnum].execPtr);
-    VM_Execute(1);
     insptr = NULL;
 #endif
 
-#ifdef LUNATIC
-    if (killit)
-#else
-    if (vm.g_flags & VM_KILL)
-#endif
-    {
-        VM_DeleteSprite(iActor, iPlayer);
-        return;
-    }
+	if(!g_netClient) //[75] Clients should not delete sprites in A_Execute
+	{
+	#ifdef LUNATIC
+		if (killit)
+	#else
+		if (vm.g_flags & VM_KILL)
+	#endif
+		{
+			VM_DeleteSprite(iActor, iPlayer);
+			return;
+		}
+	}
 
     VM_Move();
 
@@ -5821,7 +6054,12 @@ void A_Execute(int32_t iActor, int32_t iPlayer, int32_t lDist)
         return;
 
     if (A_CheckSpriteFlags(vm.g_i, SFLAG_USEACTIVATOR) && sector[vm.g_sp->sectnum].lotag & 16384)
-        changespritestat(vm.g_i, STAT_ZOMBIEACTOR);
+	{
+		if(!g_netClient) // [75] Clients should not change sprite stat to STAT_ZOMBIEACTOR if an activator is used
+		{
+			 changespritestat(vm.g_i, STAT_ZOMBIEACTOR);
+		}
+	}
     else if (actor[vm.g_i].timetosleep > 1)
         actor[vm.g_i].timetosleep--;
     else if (actor[vm.g_i].timetosleep == 1)
@@ -5829,7 +6067,11 @@ void A_Execute(int32_t iActor, int32_t iPlayer, int32_t lDist)
         // hack for 1.3D fire sprites
         if (EDUKE32_PREDICT_FALSE(g_scriptVersion == 13 && (vm.g_sp->picnum == FIRE || vm.g_sp->picnum == FIRE2)))
             return;
-        changespritestat(vm.g_i, STAT_ZOMBIEACTOR);
+
+		if(!g_netClient) // [75] Clients should not change sprite stat to STAT_ZOMBIEACTOR if timetosleep==1
+		{
+			changespritestat(vm.g_i, STAT_ZOMBIEACTOR);
+		}
     }
 }
 
diff --git a/source/gameexec.h b/source/gameexec.h
index c6a8ef8..130cc50 100644
--- a/source/gameexec.h
+++ b/source/gameexec.h
@@ -63,6 +63,11 @@ int32_t VM_OnEvent_(int32_t iEventID, int32_t iActor, int32_t iPlayer);
 
 static inline int32_t VM_HaveEvent(int32_t iEventID)
 {
+	if(g_netClient) //[75] temporary: Clients bypass VM_HaveEvent
+	{
+		return 0;
+	}
+
 #ifdef LUNATIC
     return L_IsInitialized(&g_ElState) && El_HaveEvent(iEventID);
 #else
diff --git a/source/namesdyn.c b/source/namesdyn.c
index 4337f57..96a220e 100644
--- a/source/namesdyn.c
+++ b/source/namesdyn.c
@@ -1014,7 +1014,7 @@ int32_t SHRINKSPARK = SHRINKSPARK__STATIC;
 int32_t TONGUE = TONGUE__STATIC;
 int32_t MORTER = MORTER__STATIC;
 int32_t SHRINKEREXPLOSION = SHRINKEREXPLOSION__STATIC;
-int32_t RADIUSEXPLOSION = RADIUSEXPLOSION__STATIC;
+int32_t RADIUSEXPLOSION = RADIUSEXPLOSION__STATIC; 
 int32_t FORCERIPPLE = FORCERIPPLE__STATIC;
 int32_t LIZTROOP = LIZTROOP__STATIC;
 int32_t LIZTROOPRUNNING = LIZTROOPRUNNING__STATIC;
diff --git a/source/net.c b/source/net.c
index 20b3c0b..1ef027d 100644
--- a/source/net.c
+++ b/source/net.c
@@ -43,6 +43,8 @@ int32_t g_networkMode = NET_CLIENT;
 int32_t g_netIndex = 2;
 newgame_t pendingnewgame;
 
+int32_t NET_75_CHECK = 0;
+
 #ifdef NETCODE_DISABLE
 void faketimerhandler(void) {}
 #else
@@ -1359,9 +1361,22 @@ int32_t Net_ActorsAreDifferent(netactor_t *actor1, netactor_t *actor2)
         actor1->sprite.picnum	!= actor2->sprite.picnum ||
         //actor1->sprite.shade	!= actor2->sprite.shade ||
         actor1->sprite.xrepeat	!= actor2->sprite.xrepeat ||
-        actor1->sprite.yrepeat	!= actor2->sprite.yrepeat;// ||
-        //actor1->sprite.ang	!= actor2->sprite.ang ||
-
+        actor1->sprite.yrepeat	!= actor2->sprite.yrepeat ||
+
+		//[75] added t_data so that the animations work properly
+		// until I finish the packet code
+
+		actor1->t_data[0]		!= actor2->t_data[0]	||
+		actor1->t_data[1]		!= actor2->t_data[1]	||
+		actor1->t_data[2]		!= actor2->t_data[2]	||
+		actor1->t_data[3]		!= actor2->t_data[3]	||
+		actor1->t_data[4]		!= actor2->t_data[4]	||
+		actor1->t_data[5]		!= actor2->t_data[5]	||
+		actor1->t_data[6]		!= actor2->t_data[6]	||
+		actor1->t_data[7]		!= actor2->t_data[7]	||
+		actor1->t_data[8]		!= actor2->t_data[8]	||
+		actor1->t_data[9]		!= actor2->t_data[9];
+		
     nonStandableDiff =
         actor1->sprite.x		!= actor2->sprite.x ||
         actor1->sprite.y		!= actor2->sprite.y ||
@@ -1377,6 +1392,9 @@ int32_t Net_ActorsAreDifferent(netactor_t *actor1, netactor_t *actor2)
 
 int32_t Net_IsRelevantSprite(int32_t i)
 {
+	NET_75_CHECK++; // temporary testing
+	return 1;
+
     if (g_netServer == NULL && g_netClient == NULL)
     {
         return 0;
@@ -1393,7 +1411,7 @@ int32_t Net_IsRelevantSprite(int32_t i)
 
 int32_t Net_IsRelevantStat(int32_t stat)
 {
-    int32_t statIndex;
+	int32_t statIndex;
 
     if (g_netServer == NULL && g_netClient == NULL)
     {
@@ -2256,4 +2274,5 @@ void Net_ReceiveMapVoteCancel(uint8_t *pbuf)
     voting = -1;
 }
 
+
 #endif  // !defined NETCODE_DISABLE
diff --git a/source/net.h b/source/net.h
index fe28e88..808ee9e 100644
--- a/source/net.h
+++ b/source/net.h
@@ -106,7 +106,7 @@ enum netmode_t
     NET_DEDICATED_SERVER
 };
 
-#define NETMAXACTORS 1024
+#define NETMAXACTORS MAXSPRITES //  [75] formerly 1024
 
 #pragma pack(push,1)
 typedef struct
@@ -128,8 +128,6 @@ typedef struct
 
 } netmapdiff_t;
 
-extern netmapstate_t  *g_multiMapState[MAXPLAYERS];
-extern netmapstate_t  *g_multiMapRevisions[NET_REVISIONS];
 #pragma pack(pop)
 
 #pragma pack(push,1)
diff --git a/source/player.c b/source/player.c
index b3b72e7..820cd51 100644
--- a/source/player.c
+++ b/source/player.c
@@ -20,6 +20,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
 //-------------------------------------------------------------------------
 
+static int NET_75_CHECK = 0;
+
 #include "duke3d.h"
 #include "demo.h"
 #include "enet/enet.h"
@@ -3219,7 +3221,12 @@ static int32_t P_DoCounters(int32_t snum)
         p->last_quick_kick = p->quick_kick+1;
 
         if (--p->quick_kick == 8)
-            A_Shoot(p->i,KNEE);
+		{
+			if(!g_netClient) //[75] Clients should not run A_Shoot for the "mighty boot" aka quick kick
+			{
+				 A_Shoot(p->i,KNEE);
+			}
+		}
     }
     else if (p->last_quick_kick > 0) p->last_quick_kick--;
 
@@ -3658,7 +3665,7 @@ static int32_t P_CheckFloorDamage(DukePlayer_t *p, int32_t tex)
     return 0;
 }
 
-
+//[75] get closest player index to player index p, d is distance to closest player
 int32_t P_FindOtherPlayer(int32_t p, int32_t *d)
 {
     int32_t j, closest_player = p;
@@ -3848,9 +3855,9 @@ int32_t P_WeaponState(int32_t snum, int32_t reset)
 static void P_ProcessWeapon(int32_t snum)
 {
     DukePlayer_t *const p = g_player[snum].ps;
-    uint8_t *const kb = &p->kickback_pic;
+    uint8_t *const kb = &p->kickback_pic; // Kickback Pic: current animation frame of weapon
     const int32_t shrunk = (sprite[p->i].yrepeat < 32);
-    uint32_t sb_snum = g_player[snum].sync->bits;
+    uint32_t sb_snum = g_player[snum].sync->bits; // player sync bits
     int32_t i, j, k;
 
     switch (p->weapon_pos)
@@ -3967,7 +3974,7 @@ static void P_ProcessWeapon(int32_t snum)
         else
         {
             P_SetWeaponGamevars(snum, p);
-
+			// [75] this is actually OK for clients because it just plays sounds
             if (VM_OnEvent(EVENT_FIRE, p->i, snum) == 0)
             {
                 // this event is deprecated
@@ -4187,6 +4194,8 @@ static void P_ProcessWeapon(int32_t snum)
                     }
 
                     P_SetWeaponGamevars(snum, p);
+
+					//[75] it's OK for clients to run this since their sprite is an APLAYER
                     A_Shoot(p->i, PWEAPON(snum, p->curr_weapon, Shoots));
                 }
             }
@@ -4233,7 +4242,12 @@ static void P_ProcessWeapon(int32_t snum)
                     A_PlaySound(PWEAPON(snum, p->curr_weapon, Sound2Sound),p->i);
 
             if (*kb == PWEAPON(snum, p->curr_weapon, SpawnTime))
-                P_DoWeaponSpawn(snum);
+			{
+				if(!g_netClient) // [75] clients should not run P_DoWeaponSpawn
+				{
+					 P_DoWeaponSpawn(snum);
+				}
+			}
 
             if ((*kb) >= PWEAPON(snum, p->curr_weapon, TotalTime))
             {
@@ -4293,38 +4307,49 @@ static void P_ProcessWeapon(int32_t snum)
             else if (*kb >= PWEAPON(snum, p->curr_weapon, FireDelay) && (*kb) < PWEAPON(snum, p->curr_weapon, TotalTime) &&
                 ((PWEAPON(snum, p->curr_weapon, WorksLike) == KNEE_WEAPON) ? 1 : p->ammo_amount[p->curr_weapon] > 0))
             {
-                int const reset = (TEST_SYNC_KEY(sb_snum, SK_FIRE) == 0 && PWEAPON(snum, p->curr_weapon, Flags) & WEAPON_RESET);
-
-                switch (P_WeaponState(snum, reset))
-                {
-                case WS_FIRE_AND_SPAWN:
-                    P_FireWeapon(snum);
-                    P_DoWeaponSpawn(snum);
-
-                    if (reset) *kb = 0;
-                    else if (PWEAPON(snum, p->curr_weapon, Flags) & WEAPON_RESET &&
-                        (*kb) > PWEAPON(snum, p->curr_weapon, TotalTime) - PWEAPON(snum, p->curr_weapon, HoldDelay))
-                        *kb = (TEST_SYNC_KEY(sb_snum, SK_FIRE)) ? 1 : 0;
-                    break;
-                case WS_FIRE:
-                    P_FireWeapon(snum);
-
-                    if (reset) *kb = 0;
-                    else if (PWEAPON(snum, p->curr_weapon, Flags) & WEAPON_RESET &&
-                        (*kb) > PWEAPON(snum, p->curr_weapon, TotalTime) - PWEAPON(snum, p->curr_weapon, HoldDelay))
-                        *kb = (TEST_SYNC_KEY(sb_snum, SK_FIRE)) ? 1 : 0;
-                    break;
-                default: break;
-                }
+				if(!g_netClient) // [75] Clients should not shoot or spawn.
+				{
+					int const reset = (TEST_SYNC_KEY(sb_snum, SK_FIRE) == 0 && PWEAPON(snum, p->curr_weapon, Flags) & WEAPON_RESET);
+
+					switch (P_WeaponState(snum, reset))
+					{
+					case WS_FIRE_AND_SPAWN:
+						P_FireWeapon(snum);
+						P_DoWeaponSpawn(snum);
+					
+
+						if (reset) *kb = 0;
+						else if (PWEAPON(snum, p->curr_weapon, Flags) & WEAPON_RESET &&
+							(*kb) > PWEAPON(snum, p->curr_weapon, TotalTime) - PWEAPON(snum, p->curr_weapon, HoldDelay))
+							*kb = (TEST_SYNC_KEY(sb_snum, SK_FIRE)) ? 1 : 0;
+						break;
+					case WS_FIRE:
+						P_FireWeapon(snum);
+
+						if (reset) *kb = 0;
+						else if (PWEAPON(snum, p->curr_weapon, Flags) & WEAPON_RESET &&
+							(*kb) > PWEAPON(snum, p->curr_weapon, TotalTime) - PWEAPON(snum, p->curr_weapon, HoldDelay))
+							*kb = (TEST_SYNC_KEY(sb_snum, SK_FIRE)) ? 1 : 0;
+						break;
+					default: break;
+					}
+				}
             }
+			
         }
     }
 }
 
+//[75] NOTE: Clients exit out of this immediately
 void P_EndLevel(void)
 {
     int32_t i;
 
+	if(g_netClient) //[75] clients should never run P_EndLevel
+	{
+		return;
+	}
+
     for (TRAVERSE_CONNECT(i))
         g_player[i].ps->gm = MODE_EOL;
 
@@ -4348,6 +4373,7 @@ static int32_t P_DoFist(DukePlayer_t *p)
 
     if (++p->fist_incs == 28)
     {
+		NET_75_CHECK++; //[75] multi level demos?
         if (ud.recstat == 1) G_CloseDemoWrite();
         S_PlaySound(PIPEBOMB_EXPLODE);
 
@@ -4370,7 +4396,7 @@ static int32_t P_DoFist(DukePlayer_t *p)
         }
         else
         {
-            P_EndLevel();
+			P_EndLevel();			
         }
 
         p->fist_incs = 0;
@@ -4430,41 +4456,53 @@ void P_UpdatePosWhenViewingCam(DukePlayer_t *p)
     p->rotscrnang = 0;
 }
 
+
+
 void P_ProcessInput(int32_t snum)
 {
-    DukePlayer_t *const p = g_player[snum].ps;
-    spritetype *const s = &sprite[p->i];
+    DukePlayer_t *const p = g_player[snum].ps; // DukePlayer_t structure
+    spritetype *const s = &sprite[p->i]; // player sprite
 
-    uint32_t sb_snum = g_player[snum].sync->bits;
+	
+    uint32_t sb_snum = g_player[snum].sync->bits; // player sync bits
 
-    int32_t j, i, k, doubvel = TICSPERFRAME, shrunk;
+    int32_t j, i, k, 
+			doubvel = TICSPERFRAME, // init to TICSPERFRAME
+			shrunk;
     int32_t fz, cz, hz, lz, truefdist, x, y, psectlotag;
     const uint8_t *const kb = &p->kickback_pic;
     int16_t tempsect;
 
+	NET_75_CHECK++; //[75] Check:  playerquitflag in clients / server OK?
     if (g_player[snum].playerquitflag == 0)
         return;
 
-    p->player_par++;
+    p->player_par++;	
+	
+	VM_OnEvent(EVENT_PROCESSINPUT, p->i, snum);	
 
-    VM_OnEvent(EVENT_PROCESSINPUT, p->i, snum);
+	if(!g_netClient) //[75] no cheats for clients, client's shouldn't do the killing either
+	{
+		if (p->cheat_phase > 0) sb_snum = 0;
 
-    if (p->cheat_phase > 0) sb_snum = 0;
+		if (p->cursectnum == -1)
+		{
+			if (s->extra > 0 && ud.noclip == 0)
+			{
+				P_QuickKill(p);
+				A_PlaySound(SQUISHED,p->i);
+			}
+			p->cursectnum = 0;
+		}
 
-    if (p->cursectnum == -1)
-    {
-        if (s->extra > 0 && ud.noclip == 0)
-        {
-            P_QuickKill(p);
-            A_PlaySound(SQUISHED,p->i);
-        }
-        p->cursectnum = 0;
-    }
+	}
 
     psectlotag = sector[p->cursectnum].lotag;
     p->spritebridge = p->sbs = 0;
 
     shrunk = (s->yrepeat < 32);
+
+	
     getzrange((vec3_t *)p,p->cursectnum,&cz,&hz,&fz,&lz,163L,CLIPMASK0);
 
 #ifdef YAX_ENABLE
@@ -4479,12 +4517,16 @@ void P_ProcessInput(int32_t snum)
     if ((lz&49152) == 16384 && psectlotag == 1 && truefdist > PHEIGHT+(16<<8))
         psectlotag = 0;
 
+
+	NET_75_CHECK++;	//[75] Check: OK for client to set player actor floor / ceiling z?
+
     actor[p->i].floorz = fz;
     actor[p->i].ceilingz = cz;
 
     p->ohoriz = p->horiz;
     p->ohorizoff = p->horizoff;
 
+	
     // calculates automatic view angle for playing without a mouse
     if (p->aim_mode == 0 && p->on_ground && psectlotag != ST_2_UNDERWATER && (sector[p->cursectnum].floorstat&2))
     {
@@ -4502,6 +4544,7 @@ void P_ProcessInput(int32_t snum)
         }
     }
 
+
     if (p->horizoff > 0) p->horizoff -= ((p->horizoff>>3)+1);
     else if (p->horizoff < 0) p->horizoff += (((-p->horizoff)>>3)+1);
 
@@ -4519,6 +4562,9 @@ void P_ProcessInput(int32_t snum)
     if (lz >= 0 && (lz&49152) == 49152)
     {
         j = lz&(MAXSPRITES-1);
+		
+		
+		NET_75_CHECK++; //Check: are there desyncs caused by p->sbs/spritebridge? 
 
         if ((sprite[j].cstat&33) == 33 || (sprite[j].cstat&17) == 17 ||
                 clipshape_idx_for_sprite(&sprite[j], -1) >= 0)
@@ -4531,10 +4577,12 @@ void P_ProcessInput(int32_t snum)
                 p->spritebridge = 1;
                 p->sbs = j;
             }
-        }
+        }		
         else if (A_CheckEnemySprite(&sprite[j]) && sprite[j].xrepeat > 24 && klabs(s->z-sprite[j].z) < (84<<8))
         {
-            // TX: I think this is what makes the player slide off enemies... might
+			NET_75_CHECK++; //Check: are there desyncs caused by clients sliding off enemies?
+
+            //TX: I think this is what makes the player slide off enemies... might
             // be a good sprite flag to add later.
             // Helix: there's also SLIDE_ABOVE_ENEMY.
             j = getangle(sprite[j].x-p->pos.x,sprite[j].y-p->pos.y);
@@ -4543,19 +4591,24 @@ void P_ProcessInput(int32_t snum)
         }
     }
 
-    if (s->extra > 0)
-        P_IncurDamage(p);
-    else
-    {
-        s->extra = 0;
-        p->inv_amount[GET_SHIELD] = 0;
-    }
+	if(!g_netClient) //[75] clients should not do damage to themselves
+	{
+		if (s->extra > 0)
+			P_IncurDamage(p);
+		else
+		{
+			s->extra = 0;
+			p->inv_amount[GET_SHIELD] = 0;
+		}
+	}
 
+	NET_75_CHECK++; // [75] p->last_extra set by client OK?
     p->last_extra = s->extra;
 
     if (p->loogcnt > 0) p->loogcnt--;
     else p->loogcnt = 0;
 
+	
     if (p->fist_incs && P_DoFist(p)) return;
 
     if (p->timebeforeexit > 1 && p->last_extra > 0)
@@ -4578,7 +4631,7 @@ void P_ProcessInput(int32_t snum)
         }
     }
 
-    if (p->pals.f > 0)
+    if (p->pals.f > 0) // palette intensity?
     {
 #if !defined LUNATIC
         p->pals.f--;
@@ -4617,11 +4670,12 @@ void P_ProcessInput(int32_t snum)
 
     if (s->extra <= 0)
     {
+		NET_75_CHECK++; // May cause the demo to close if a single client is in a dedicated server on death.
         if (ud.recstat == 1 && (!g_netServer && ud.multimode < 2))
             G_CloseDemoWrite();
 
-        if ((numplayers < 2 || g_netServer) && p->dead_flag == 0)
-            P_FragPlayer(snum);
+		if ((numplayers < 2 || g_netServer) && p->dead_flag == 0)
+			P_FragPlayer(snum);	
 
         if (psectlotag == ST_2_UNDERWATER)
         {
@@ -4660,6 +4714,7 @@ void P_ProcessInput(int32_t snum)
         return;
     }
 
+	NET_75_CHECK++; // (paranoid) verify clients can't hack past trasnporter hold
     if (p->transporter_hold > 0)
     {
         p->transporter_hold--;
@@ -4680,6 +4735,7 @@ void P_ProcessInput(int32_t snum)
         return;
     }
 
+	//[75] note: look left / look right spring
     p->rotscrnang -= (p->rotscrnang>>1);
 
     if (p->rotscrnang && !(p->rotscrnang>>1))
@@ -4692,6 +4748,8 @@ void P_ProcessInput(int32_t snum)
 
     if (TEST_SYNC_KEY(sb_snum, SK_LOOK_LEFT))
     {
+		NET_75_CHECK++; // VM_OnEvent Worry: [SK_LOOK_LEFT] Client should not execute script but server can't get back in time to say whether it should be cancelled or not
+
         // look_left
         if (VM_OnEvent(EVENT_LOOKLEFT,p->i,snum) == 0)
         {
@@ -4702,6 +4760,8 @@ void P_ProcessInput(int32_t snum)
 
     if (TEST_SYNC_KEY(sb_snum, SK_LOOK_RIGHT))
     {
+		NET_75_CHECK++; // VM_OnEvent Worry: [SK_LOOK_RIGHT] Client should not execute script but server can't get back in time to say whether it should be cancelled or not
+
         // look_right
         if (VM_OnEvent(EVENT_LOOKRIGHT,p->i,snum) == 0)
         {
@@ -4710,6 +4770,8 @@ void P_ProcessInput(int32_t snum)
         }
     }
 
+	NET_75_CHECK++; // Make sure server is not relying on client for on_crane.
+
     if (p->on_crane >= 0)
         goto HORIZONLY;
 
@@ -4747,6 +4809,7 @@ void P_ProcessInput(int32_t snum)
     p->bobpos.y = p->pos.y;
 
     p->opos.z = p->pos.z;
+
     p->opyoff = p->pyoff;
     p->oang = p->ang;
 
@@ -4762,7 +4825,7 @@ void P_ProcessInput(int32_t snum)
 
     if (psectlotag == ST_2_UNDERWATER)
     {
-        // under water
+        NET_75_CHECK++; // Server uses jumping_counter to decide when players should stop jumpinmg and start falling
         p->jumping_counter = 0;
 
         p->pycount += 32;
@@ -4772,8 +4835,12 @@ void P_ProcessInput(int32_t snum)
         if (!A_CheckSoundPlaying(p->i,DUKE_UNDERWATER))
             A_PlaySound(DUKE_UNDERWATER,p->i);
 
+
+
         if (TEST_SYNC_KEY(sb_snum, SK_JUMP))
         {
+			NET_75_CHECK++; // VM_OnEvent Worry: [EVENT_SWIMUP] Client should not execute script but server can't get back in time to say whether it should be cancelled or not
+
             if (VM_OnEvent(EVENT_SWIMUP,p->i,snum) == 0)
             {
                 // jump
@@ -4781,9 +4848,11 @@ void P_ProcessInput(int32_t snum)
                 p->vel.z -= 348;
                 if (p->vel.z < -(256*6)) p->vel.z = -(256*6);
             }
-        }
+        }		
         else if (TEST_SYNC_KEY(sb_snum, SK_CROUCH))
         {
+			NET_75_CHECK++; // VM_OnEvent Worry: [EVENT_SWIMDOWN] Client should not execute script but server can't get back in time to say whether it should be cancelled or not
+
             if (VM_OnEvent(EVENT_SWIMDOWN,p->i,snum) == 0)
             {
                 // crouch
@@ -4794,6 +4863,7 @@ void P_ProcessInput(int32_t snum)
         }
         else
         {
+			// [75] if not pressing any keys and underwater, slow the player down on the z axis to a stop
             // normal view
             if (p->vel.z < 0)
             {
@@ -4854,12 +4924,14 @@ void P_ProcessInput(int32_t snum)
         else if (p->jetpack_on == 11 && !A_CheckSoundPlaying(p->i,DUKE_JETPACK_IDLE))
             A_PlaySound(DUKE_JETPACK_IDLE,p->i);
 
+		// [75] j = amount to descend or ascend (depends on shrinked state) if the user hits crouch / jump
         if (shrunk) j = 512;
         else j = 2048;
 
         if (TEST_SYNC_KEY(sb_snum, SK_JUMP))         //A (soar high)
         {
-            // jump
+            NET_75_CHECK++; // VM_OnEvent Worry: [EVENT_SOARUP] Client should not execute script but server can't get back in time to say whether it should be cancelled or not
+
             if (VM_OnEvent(EVENT_SOARUP,p->i,snum) == 0)
             {
                 p->pos.z -= j;
@@ -4869,7 +4941,8 @@ void P_ProcessInput(int32_t snum)
 
         if (TEST_SYNC_KEY(sb_snum, SK_CROUCH))   //Z (soar low)
         {
-            // crouch
+			NET_75_CHECK++; // VM_OnEvent Worry: [EVENT_SOARDOWN] Client should not execute script but server can't get back in time to say whether it should be cancelled or not
+
             if (VM_OnEvent(EVENT_SOARDOWN,p->i,snum) == 0)
             {
                 p->pos.z += j;
@@ -4877,6 +4950,7 @@ void P_ProcessInput(int32_t snum)
             }
         }
 
+		//[75] k is underwater bobbing amount, changes based on whether the player is shrunk
         if (shrunk == 0 && (psectlotag == 0 || psectlotag == ST_2_UNDERWATER)) k = 32;
         else k = 16;
 
@@ -4897,6 +4971,8 @@ void P_ProcessInput(int32_t snum)
 
         if (psectlotag == ST_1_ABOVE_WATER && p->spritebridge == 0)
         {
+			// [75] don't bob up and down if you're shrunk (just wondering, why?)
+			//		i is now view height of player on "above water" sector, it's lower if the player is shrunk
             if (shrunk == 0)
             {
                 i = 34;
@@ -4924,47 +5000,55 @@ void P_ProcessInput(int32_t snum)
             }
         }
         else
-        {
-            if (p->footprintcount > 0 && p->on_ground)
-                if (p->cursectnum >= 0 && (sector[p->cursectnum].floorstat&2) != 2)
-                {
-                    for (j=headspritesect[p->cursectnum]; j>=0; j=nextspritesect[j])
-                        if (sprite[j].picnum == FOOTPRINTS || sprite[j].picnum == FOOTPRINTS2 ||
-                                sprite[j].picnum == FOOTPRINTS3 || sprite[j].picnum == FOOTPRINTS4)
-                            if (klabs(sprite[j].x-p->pos.x) < 384 && klabs(sprite[j].y-p->pos.y) < 384)
-                                break;
-
-                    if (j < 0)
-                    {
-                        if (p->cursectnum >= 0 && sector[p->cursectnum].lotag == 0 && sector[p->cursectnum].hitag == 0)
-#ifdef YAX_ENABLE
-                            if (yax_getbunch(p->cursectnum, YAX_FLOOR) < 0 || (sector[p->cursectnum].floorstat&512))
-#endif
-                        {
-                            switch (krand()&3)
-                            {
-                            case 0:
-                                j = A_Spawn(p->i,FOOTPRINTS);
-                                break;
-                            case 1:
-                                j = A_Spawn(p->i,FOOTPRINTS2);
-                                break;
-                            case 2:
-                                j = A_Spawn(p->i,FOOTPRINTS3);
-                                break;
-                            default:
-                                j = A_Spawn(p->i,FOOTPRINTS4);
-                                break;
-                            }
-                            sprite[j].pal = p->footprintpal;
-                            sprite[j].shade = p->footprintshade;
-                            p->footprintcount--;
-                        }
-                    }
-                }
-        }
-
-        if (p->pos.z < (fz-(i<<8)))  //falling
+        {//[75] not underwater and not above water
+
+			NET_75_CHECK++; // [minor] for right now clients don't spawn footprints but clientside footprints are very possible
+
+			if(!g_netClient) // [75] clients don't spawn their own footprints (for now)
+			{
+				if (p->footprintcount > 0 && p->on_ground)
+				{
+					if (p->cursectnum >= 0 && (sector[p->cursectnum].floorstat&2) != 2) // [75] don't spawn footprints on sloped floors
+					{
+						for (j=headspritesect[p->cursectnum]; j>=0; j=nextspritesect[j])
+							if (sprite[j].picnum == FOOTPRINTS || sprite[j].picnum == FOOTPRINTS2 ||
+									sprite[j].picnum == FOOTPRINTS3 || sprite[j].picnum == FOOTPRINTS4)
+								if (klabs(sprite[j].x-p->pos.x) < 384 && klabs(sprite[j].y-p->pos.y) < 384)
+									break;
+
+						if (j < 0)
+						{
+							if (p->cursectnum >= 0 && sector[p->cursectnum].lotag == 0 && sector[p->cursectnum].hitag == 0)
+	#ifdef YAX_ENABLE
+								if (yax_getbunch(p->cursectnum, YAX_FLOOR) < 0 || (sector[p->cursectnum].floorstat&512))
+	#endif
+							{
+								switch (krand()&3)
+								{
+								case 0:
+									j = A_Spawn(p->i,FOOTPRINTS);
+									break;
+								case 1:
+									j = A_Spawn(p->i,FOOTPRINTS2);
+									break;
+								case 2:
+									j = A_Spawn(p->i,FOOTPRINTS3);
+									break;
+								default:
+									j = A_Spawn(p->i,FOOTPRINTS4);
+									break;
+								}
+								sprite[j].pal = p->footprintpal;
+								sprite[j].shade = p->footprintshade;
+								p->footprintcount--;
+							}
+						}
+					}
+				}
+			}
+        }
+		// [75] at this point i is the player's view height above ground (compensating for shrinking, above water, under water)
+        if (p->pos.z < (fz-(i<<8)))  //falling [75] note: long distance or short distance
         {
             // not jumping or crouching
 
@@ -4973,6 +5057,8 @@ void P_ProcessInput(int32_t snum)
                 p->pos.z = fz-(i<<8);
             else
             {
+				NET_75_CHECK++; //Falling code: verify that setting on_ground, falling_counter is OK for the client to do
+
                 p->on_ground = 0;
                 p->vel.z += (g_spriteGravity+80); // (TICSPERFRAME<<6);
                 if (p->vel.z >= (4096+2048)) p->vel.z = (4096+2048);
@@ -4990,7 +5076,7 @@ void P_ProcessInput(int32_t snum)
                 if ((p->pos.z+p->vel.z) >= (fz-(i<<8)) && p->cursectnum >= 0)   // hit the ground
                     if (sector[p->cursectnum].lotag != ST_1_ABOVE_WATER)
                     {
-                        if (p->falling_counter > 62)
+                        if (!g_netClient && p->falling_counter > 62) // [75] clients should not run P_QuickKill
                             P_QuickKill(p);
                         else if (p->falling_counter > 9)
                         {
@@ -5017,7 +5103,7 @@ void P_ProcessInput(int32_t snum)
             }
         }
         else
-        {
+        { // [75] at this point i is still the player's view height above ground (compensating for shrinking, above water, under water)
             p->falling_counter = 0;
 
             if (p->scream_voice > FX_Ok)
@@ -5057,6 +5143,7 @@ void P_ProcessInput(int32_t snum)
             if (TEST_SYNC_KEY(sb_snum, SK_CROUCH))
             {
                 // crouching
+				NET_75_CHECK++; // VM_OnEvent Worry: [EVENT_CROUCH] Client should not execute script: set so that client does not actually jump and waits for server?
                 if (VM_OnEvent(EVENT_CROUCH,p->i,snum) == 0)
                 {
                     p->pos.z += (2048+768);
@@ -5072,6 +5159,7 @@ void P_ProcessInput(int32_t snum)
                 if (p->jumping_counter == 0)
                     if ((fz-cz) > (56<<8))
                     {
+						NET_75_CHECK++; // VM_OnEvent Worry: [EVENT_JUMP] Client should not execute script: set so that client does not actually crouch and waits for server?
                         if (VM_OnEvent(EVENT_JUMP,p->i,snum) == 0)
                         {
                             p->jumping_counter = 1;
@@ -5161,7 +5249,11 @@ void P_ProcessInput(int32_t snum)
                     A_PlaySound(DUKE_LONGTERM_PAIN,p->i);
 
                 P_PalFrom(p, 32, 0,8,0);
-                s->extra--;
+
+				if(!g_netClient) // [75] purple lava: client should not hurt itself
+				{
+					s->extra--;
+				}
             }
         }
 
@@ -5177,6 +5269,8 @@ void P_ProcessInput(int32_t snum)
         }
     }
 
+	NET_75_CHECK++; // VM_OnEvent Worry: [EVENT_MOVEFORWARD/Backward/StrafeLeft/Right/TurnLeftRight] Client should not execute script but server can't get back in time to say whether it should be cancelled or not
+
     if (g_player[snum].sync->extbits&(1))
         VM_OnEvent(EVENT_MOVEFORWARD,p->i,snum);
 
@@ -5196,7 +5290,7 @@ void P_ProcessInput(int32_t snum)
         VM_OnEvent(EVENT_TURNRIGHT,p->i,snum);
 
     if (p->vel.x || p->vel.y || g_player[snum].sync->fvel || g_player[snum].sync->svel)
-    {
+    {//[75] terrain walking sounds
         p->crack_time = 777;
 
         k = sintable[p->bobcounter&2047]>>12;
@@ -5244,11 +5338,12 @@ void P_ProcessInput(int32_t snum)
 
         j = 0;
 
+		// slow down the player if shrunk or underwater
         if (psectlotag == ST_2_UNDERWATER)
             j = 0x1400;
         else if (p->on_ground && (TEST_SYNC_KEY(sb_snum, SK_CROUCH) || (*kb > 10 && PWEAPON(snum, p->curr_weapon, WorksLike) == KNEE_WEAPON)))
             j = 0x2000;
-
+		
         p->vel.x = mulscale16(p->vel.x, p->runspeed - j);
         p->vel.y = mulscale16(p->vel.y, p->runspeed - j);
 
@@ -5274,6 +5369,7 @@ HORIZONLY:
     if (p->cursectnum >= 0 && sector[p->cursectnum].lotag == ST_2_UNDERWATER) k = 0;
     else k = 1;
 
+	NET_75_CHECK++; // [NOTE] look around here for ideas for Spectator mode
     if (ud.noclip)
     {
         p->pos.x += p->vel.x>>14;
@@ -5333,8 +5429,10 @@ HORIZONLY:
     // RBG***
 
     p->pos.z += PHEIGHT;
-    actor[p->i].bpos = *(vec3_t *)&sprite[p->i];
-    setsprite(p->i,(vec3_t *)&p->pos.x);
+
+	actor[p->i].bpos = *(vec3_t *)&sprite[p->i];
+	setsprite(p->i,(vec3_t *)&p->pos.x);
+
     p->pos.z -= PHEIGHT;
 
     // ST_2_UNDERWATER
@@ -5349,7 +5447,11 @@ HORIZONLY:
             if ((unsigned)sec->hitag < MAXSPRITES && sprite[sec->hitag].xvel
                     && actor[sec->hitag].t_data[0] == 0)
             {
-                P_QuickKill(p);
+				if(!g_netClient) // [75] clients should not kill themselves if a train runs into them
+				{
+					 P_QuickKill(p);
+				}
+
                 return;
             }
         }
@@ -5360,8 +5462,9 @@ HORIZONLY:
         if (!A_CheckSoundPlaying(p->i,DUKE_ONWATER))
             A_PlaySound(DUKE_ONWATER,p->i);
 
-    if (p->cursectnum >=0 && p->cursectnum != s->sectnum)
-        changespritesect(p->i, p->cursectnum);
+
+	if (p->cursectnum >=0 && p->cursectnum != s->sectnum)
+		changespritesect(p->i, p->cursectnum);
 
     if (p->cursectnum >= 0 && ud.noclip == 0)
     {
@@ -5374,7 +5477,10 @@ HORIZONLY:
                 G_ActivateBySector(s->sectnum,p->i);
             if (j)
             {
-                P_QuickKill(p);
+				if(!g_netClient) // [75] clients should not kill themselves if pushmove fails. The server might get them straightened out.
+				{
+					P_QuickKill(p);
+				}
                 return;
             }
         }
@@ -5382,6 +5488,8 @@ HORIZONLY:
             G_ActivateBySector(p->cursectnum,p->i);
     }
 
+	NET_75_CHECK++; // VM_OnEvent Worry: [EVENT_CENTER_VIEW/LOOK_UP/LOOK_DOWN/AIM_UP/AIM_DOWN] Client should not execute script but server can't get back in time to say whether it should be cancelled or not
+
     i = 0;
     if (TEST_SYNC_KEY(sb_snum, SK_CENTER_VIEW) || p->hard_landing)
         if (VM_OnEvent(EVENT_RETURNTOCENTER,p->i,snum) == 0)
@@ -5480,46 +5588,51 @@ HORIZONLY:
             p->holster_weapon = 0;
             p->weapon_pos = klabs(p->weapon_pos);
 
-            if (p->actorsqu >= 0 && sprite[p->actorsqu].statnum != MAXSTATUS && dist(&sprite[p->i],&sprite[p->actorsqu]) < 1400)
-            {
-                A_DoGuts(p->actorsqu,JIBS6,7);
-                A_Spawn(p->actorsqu,BLOODPOOL);
-                A_PlaySound(SQUISHED,p->actorsqu);
-
-                switch (DYNAMICTILEMAP(sprite[p->actorsqu].picnum))
-                {
-                case FEM1__STATIC:
-                case FEM2__STATIC:
-                case FEM3__STATIC:
-                case FEM4__STATIC:
-                case FEM5__STATIC:
-                case FEM6__STATIC:
-                case FEM7__STATIC:
-                case FEM8__STATIC:
-                case FEM9__STATIC:
-                case FEM10__STATIC:
-                case PODFEM1__STATIC:
-                case NAKED1__STATIC:
-                case STATUE__STATIC:
-                    if (sprite[p->actorsqu].yvel)
-                        G_OperateRespawns(sprite[p->actorsqu].yvel);
-                    A_DeleteSprite(p->actorsqu);
-                    break;
-                case APLAYER__STATIC:
-                {
-                    int32_t snum = P_Get(p->actorsqu);
-                    P_QuickKill(g_player[snum].ps);
-                    g_player[snum].ps->frag_ps = snum;
-                    break;
-                }
-                default:
-                    if (A_CheckEnemySprite(&sprite[p->actorsqu]))
-                        p->actors_killed++;
-                    A_DeleteSprite(p->actorsqu);
-                    break;
-                }
-            }
-            p->actorsqu = -1;
+			if(!g_netClient) // [75] clients should not spawn gib sprites for FEM*, etc., clients should not kill the players they step on, clients should not delete the sprite they squished.
+			{
+
+				if (p->actorsqu >= 0 && sprite[p->actorsqu].statnum != MAXSTATUS && dist(&sprite[p->i],&sprite[p->actorsqu]) < 1400)
+				{
+					A_DoGuts(p->actorsqu,JIBS6,7);
+					A_Spawn(p->actorsqu,BLOODPOOL);
+					A_PlaySound(SQUISHED,p->actorsqu);
+
+					switch (DYNAMICTILEMAP(sprite[p->actorsqu].picnum))
+					{
+					case FEM1__STATIC:
+					case FEM2__STATIC:
+					case FEM3__STATIC:
+					case FEM4__STATIC:
+					case FEM5__STATIC:
+					case FEM6__STATIC:
+					case FEM7__STATIC:
+					case FEM8__STATIC:
+					case FEM9__STATIC:
+					case FEM10__STATIC:
+					case PODFEM1__STATIC:
+					case NAKED1__STATIC:
+					case STATUE__STATIC:
+						if (sprite[p->actorsqu].yvel)
+							G_OperateRespawns(sprite[p->actorsqu].yvel);
+						A_DeleteSprite(p->actorsqu);
+						break;
+					case APLAYER__STATIC: //[75] kill players that are shrunk and stepped on
+					{
+						int32_t snum = P_Get(p->actorsqu);
+						P_QuickKill(g_player[snum].ps);
+						g_player[snum].ps->frag_ps = snum;
+						break;
+					}
+					default:
+						if (A_CheckEnemySprite(&sprite[p->actorsqu]))
+							p->actors_killed++;
+						A_DeleteSprite(p->actorsqu);
+						break;
+					}
+				}				
+			}
+
+			p->actorsqu = -1;
         }
         else if (p->actorsqu >= 0)
             p->ang += G_GetAngleDelta(p->ang,getangle(sprite[p->actorsqu].x-p->pos.x,sprite[p->actorsqu].y-p->pos.y))>>2;
diff --git a/source/player.h b/source/player.h
index 29f9ab0..6debcaf 100644
--- a/source/player.h
+++ b/source/player.h
@@ -173,12 +173,16 @@ typedef struct {
 // TODO: rearrange this if the opportunity arises!
 // KEEPINSYNC lunatic/defs.ilua
 typedef struct {
-    vec3_t pos, opos, vel, npos;
+    vec3_t	pos, 
+			opos, 
+			vel, //[75] z used for crouch/jump
+			npos;
     vec2_t bobpos, fric;
     int32_t truefz, truecz, player_par;
     int32_t randomflamex, exitx, exity;
     int32_t runspeed, max_player_health, max_shield_amount;
-    int32_t autostep, autostep_sbw;
+    int32_t autostep, // max step height
+			autostep_sbw; // above water sector or sprite bridge step height
 
     uint32_t interface_toggle_flag;
 #ifdef LUNATIC
@@ -195,21 +199,29 @@ typedef struct {
 
     int16_t ang, oang, angvel, cursectnum, look_ang, last_extra, subweapon;
     int16_t max_ammo_amount[MAX_WEAPONS], ammo_amount[MAX_WEAPONS], inv_amount[GET_MAX];
-    int16_t wackedbyactor, pyoff, opyoff;
+    int16_t wackedbyactor, 
+			pyoff, // player y view offset
+			opyoff;
+
+    int16_t horiz,  //look up / down angle: A value of 100 equates to looking straight ahead; 299 is looking all the way up and -99 is looking all the way down. 
+			horizoff, 
+			ohoriz, 
+			ohorizoff;
 
-    int16_t horiz, horizoff, ohoriz, ohorizoff;
     int16_t newowner, jumping_counter, airleft;
     int16_t fta, ftq, access_wallnum, access_spritenum;
     int16_t got_access, weapon_ang, visibility;
     int16_t somethingonplayer, on_crane, i, one_parallax_sectnum;
-    int16_t random_club_frame, one_eighty_count;
+    int16_t random_club_frame, //glow for the shrinker/expander
+			one_eighty_count;
     int16_t dummyplayersprite, extra_extra8;
     int16_t actorsqu, timebeforeexit, customexitsound, last_pissed_time;
 
     int16_t weaprecs[MAX_WEAPONS], weapon_sway, crack_time, bobcounter;
 
     int16_t orotscrnang, rotscrnang, dead_flag;   // JBF 20031220: added orotscrnang
-    int16_t holoduke_on, pycount;
+    int16_t holoduke_on, 
+			pycount; // sine factor for bobbing
     int16_t transporter_hold;
 
     uint8_t max_secret_rooms, secret_rooms;
@@ -217,7 +229,8 @@ typedef struct {
     uint8_t frag, fraggedself, quick_kick, last_quick_kick;
     uint8_t return_to_center, reloading, weapreccnt;
     uint8_t aim_mode, auto_aim, weaponswitch, movement_lock, team;
-    uint8_t tipincs, hbomb_hold_delay, frag_ps, kickback_pic;
+    uint8_t tipincs, hbomb_hold_delay, frag_ps, 
+			kickback_pic; // current animation frame of weapon
 
     uint8_t gm, on_warping_sector, footprintcount, hurt_delay;
     uint8_t hbomb_on, jumping_toggle, rapid_fire_hold, on_ground;
@@ -411,7 +424,7 @@ static inline void P_SetWeaponGamevars(int32_t snum, const DukePlayer_t *p)
 }
 #endif
 
-// Get the player index given an APLAYER sprite pointer.
+// Get the player index given an APLAYER sprite pointer. Warning: returns 0 if there's a problem with the yvel of this sprite.
 static inline int32_t P_GetP(const spritetype *spr)
 {
 #if 0  // unprotected player index retrieval
@@ -431,7 +444,7 @@ static inline int32_t P_GetP(const spritetype *spr)
 #endif
 }
 
-// Get the player index given an APLAYER sprite index.
+// Get the player index given an APLAYER sprite index. Warning: returns 0 if there's a problem with the yvel of this sprite.
 static inline int32_t P_Get(int32_t spritenum)
 {
     return P_GetP(&sprite[spritenum]);
diff --git a/source/premap.c b/source/premap.c
index 05eb723..04ee81c 100644
--- a/source/premap.c
+++ b/source/premap.c
@@ -147,7 +147,7 @@ static void G_CacheSpriteNum(int32_t i)
         for (j=LIZMANHEAD1; j<LIZMANLEG1+3; j++) tloadtile(j,1);
         maxc = 80;
         break;
-    case APLAYER__STATIC:
+    case APLAYER__STATIC: //[75] Cache player sprites only if multiplayer
         maxc = 0;
         if ((g_netServer || ud.multimode > 1))
         {
diff --git a/source/sector.c b/source/sector.c
index 576ac02..4b2ce27 100644
--- a/source/sector.c
+++ b/source/sector.c
@@ -20,6 +20,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
 //-------------------------------------------------------------------------
 
+static int NET_75_CHECK = 0;
+
 #define sector_c_
 
 #include "duke3d.h"
@@ -536,6 +538,8 @@ void G_OperateSectors(int32_t sn, int32_t ii)
     int32_t i;
     sectortype *const sptr = &sector[sn];
 
+	NET_75_CHECK++; // the server might need to run this function by itself; I'm hoping that the world updates will give the clients enough information to predict this properly
+
     switch (sptr->lotag&(0xffff-49152))
     {
     case ST_30_ROTATE_RISE_BRIDGE:
@@ -978,10 +982,16 @@ REDODOOR:
     }
 }
 
+//[75] for clients, this function returns immediately.
 void G_OperateRespawns(int32_t low)
 {
     int32_t i, nexti;
 
+	if(g_netClient) //[75] clients should not run G_OperateRespawns
+	{
+		return;
+	}
+
     for (SPRITES_OF_STAT_SAFE(STAT_FX, i, nexti))
     {
         spritetype *respr = &sprite[i];
@@ -1865,6 +1875,7 @@ int32_t Sect_DamageCeilingOrFloor(int32_t floorp, int32_t sn)
 }
 
 // hard coded props... :(
+// [75] note: the client exits out of this almost immediately
 void A_DamageObject(int32_t i,int32_t sn)
 {
     int16_t j;
@@ -2865,36 +2876,41 @@ CHECKINV1:
 
         if (p->newowner == -1 && TEST_SYNC_KEY(sb_snum, SK_JETPACK))
         {
-            if (VM_OnEvent(EVENT_USEJETPACK,g_player[snum].ps->i,snum) == 0)
-            {
-                if (p->inv_amount[GET_JETPACK] > 0)
-                {
-                    p->jetpack_on = !p->jetpack_on;
-                    if (p->jetpack_on)
-                    {
-                        p->inven_icon = ICON_JETPACK;
-                        if (p->scream_voice > FX_Ok)
-                        {
-                            FX_StopSound(p->scream_voice);
-                            p->scream_voice = -1;
-                        }
-
-                        A_PlaySound(DUKE_JETPACK_ON,p->i);
-
-                        P_DoQuote(QUOTE_JETPACK_ON,p);
-                    }
-                    else
-                    {
-                        p->hard_landing = 0;
-                        p->vel.z = 0;
-                        A_PlaySound(DUKE_JETPACK_OFF,p->i);
-                        S_StopEnvSound(DUKE_JETPACK_IDLE,p->i);
-                        S_StopEnvSound(DUKE_JETPACK_ON,p->i);
-                        P_DoQuote(QUOTE_JETPACK_OFF,p);
-                    }
-                }
-                else P_DoQuote(QUOTE_JETPACK_NOT_FOUND,p);
-            }
+			NET_75_CHECK++; // [75] TEST: Jetpack got confused once between client and server, server thought it was on, client thought it was off and vice versa
+
+			if(!g_netClient) // [75] Clients should not toggle jetpack on / off
+			{
+				if (VM_OnEvent(EVENT_USEJETPACK,g_player[snum].ps->i,snum) == 0)
+				{
+					if (p->inv_amount[GET_JETPACK] > 0)
+					{
+						p->jetpack_on = !p->jetpack_on;
+						if (p->jetpack_on)
+						{
+							p->inven_icon = ICON_JETPACK;
+							if (p->scream_voice > FX_Ok)
+							{
+								FX_StopSound(p->scream_voice);
+								p->scream_voice = -1;
+							}
+
+							A_PlaySound(DUKE_JETPACK_ON,p->i);
+
+							P_DoQuote(QUOTE_JETPACK_ON,p);
+						}
+						else
+						{
+							p->hard_landing = 0;
+							p->vel.z = 0;
+							A_PlaySound(DUKE_JETPACK_OFF,p->i);
+							S_StopEnvSound(DUKE_JETPACK_IDLE,p->i);
+							S_StopEnvSound(DUKE_JETPACK_ON,p->i);
+							P_DoQuote(QUOTE_JETPACK_OFF,p);
+						}
+					}
+					else P_DoQuote(QUOTE_JETPACK_NOT_FOUND,p);
+				}
+			}
         }
 
         if (TEST_SYNC_KEY(sb_snum, SK_TURNAROUND) && p->one_eighty_count == 0)
@@ -3129,13 +3145,17 @@ void P_CheckSectors(int32_t snum)
                         p->holster_weapon = 1;
                         p->weapon_pos = -1;
                     }
-                    if (sprite[p->i].extra <= (p->max_player_health-(p->max_player_health/10)))
-                    {
-                        sprite[p->i].extra += p->max_player_health/10;
-                        p->last_extra = sprite[p->i].extra;
-                    }
-                    else if (sprite[p->i].extra < p->max_player_health)
-                        sprite[p->i].extra = p->max_player_health;
+
+					if(!g_netClient) // [75] toilets: players should not modify their own health
+					{
+						if (sprite[p->i].extra <= (p->max_player_health-(p->max_player_health/10)))
+						{
+							sprite[p->i].extra += p->max_player_health/10;
+							p->last_extra = sprite[p->i].extra;
+						}
+						else if (sprite[p->i].extra < p->max_player_health)
+							sprite[p->i].extra = p->max_player_health;
+					}
                 }
                 else if (!A_CheckSoundPlaying(neartagsprite,FLUSH_TOILET))
                     A_PlaySound(FLUSH_TOILET,neartagsprite);
@@ -3143,6 +3163,11 @@ void P_CheckSectors(int32_t snum)
 
             case NUKEBUTTON__STATIC:
             {
+				if(g_netClient) // [75] clients can't do anything with the nukebutton
+				{
+					return;
+				}
+
                 int16_t j;
 
                 P_FindWall(p, &j);
@@ -3175,7 +3200,11 @@ void P_CheckSectors(int32_t snum)
 
                     if (sprite[p->i].extra < p->max_player_health)
                     {
-                        sprite[p->i].extra++;
+						if(!g_netClient) //[75] water fountain: Clients should not modify their own health.
+						{
+							sprite[p->i].extra++;
+						}
+
                         A_PlaySound(DUKE_DRINKING,p->i);
                     }
                 }
@@ -3183,7 +3212,11 @@ void P_CheckSectors(int32_t snum)
 
             case PLUG__STATIC:
                 A_PlaySound(SHORT_CIRCUIT,p->i);
-                sprite[p->i].extra -= 2+(krand()&3);
+
+				if(!g_netClient) // [75] plugs: clients should not modify their own health
+				{
+					 sprite[p->i].extra -= 2+(krand()&3);
+				}
 
                 P_PalFrom(p, 32, 48,48,64);
                 break;
@@ -3195,6 +3228,8 @@ void P_CheckSectors(int32_t snum)
                 {
                     if (PN == CAMERA1 && SP == 0 && sprite[neartagsprite].hitag == SLT)
                     {
+						NET_75_CHECK++; // If pressing use on the VIEWSCREEN: Watch out for that old glitch where players would come out of cameras / could "walk out" of cameras.
+
                         sprite[i].yvel = 1;  // Using this camera
                         A_PlaySound(MONITOR_ACTIVE,p->i);
 
@@ -3220,7 +3255,7 @@ void P_CheckSectors(int32_t snum)
 
                 G_ClearCameras(p);
                 return;
-            }  // switch
+            }  // switch (type of sprite we're pressing use on)
         }
 
         if (TEST_SYNC_KEY(g_player[snum].sync->bits, SK_OPEN) == 0)
-- 
2.7.4.1.g5468f9e

