Description: Avoid double-counting rotfish
Author: David Banks <amoebae@gmail.com>
Bug: https://sourceforge.net/p/quakespasm/bugs/7/

--- a/Quake/pr_edict.c
+++ b/Quake/pr_edict.c
@@ -82,6 +82,7 @@
 cvar_t	saved2 = {"saved2", "0", CVAR_ARCHIVE};
 cvar_t	saved3 = {"saved3", "0", CVAR_ARCHIVE};
 cvar_t	saved4 = {"saved4", "0", CVAR_ARCHIVE};
+extern cvar_t sv_fishfix;
 
 /*
 =================
@@ -973,6 +974,8 @@
 	dfunction_t	*func;
 	edict_t		*ent = NULL;
 	int		inhibit = 0;
+	int oldcount;
+	sv.fish_counted = false;
 
 	pr_global_struct->time = sv.time;
 
@@ -1034,7 +1037,20 @@
 		}
 
 		pr_global_struct->self = EDICT_TO_PROG(ent);
+
+		if (!sv.fish_counted && sv_fishfix.value && !strcmp(PR_GetString(func->s_name), "monster_fish"))
+		{
+			oldcount = pr_global_struct->total_monsters;
+		}
+		else oldcount = -1;
+
 		PR_ExecuteProgram (func - pr_functions);
+
+		if (oldcount != -1)
+		{
+			if (pr_global_struct->total_monsters > oldcount)
+				sv.fish_counted = true;
+		}
 	}
 
 	Con_DPrintf ("%i entities inhibited\n", inhibit);
@@ -1224,6 +1240,10 @@
 	}
 }
 
+const char *PR_GetFunctionName(int num) {
+	return PR_GetString(pr_functions[num].s_name);
+}
+
 int PR_SetEngineString (const char *s)
 {
 	int		i;
--- a/Quake/progs.h
+++ b/Quake/progs.h
@@ -74,6 +74,7 @@
 void PR_LoadProgs (void);
 
 const char *PR_GetString (int num);
+const char *PR_GetFunctionName (int num);
 int PR_SetEngineString (const char *s);
 int PR_AllocString (int bufferlength, char **ptr);
 
--- a/Quake/server.h
+++ b/Quake/server.h
@@ -75,6 +75,7 @@
 
 	unsigned	protocol; //johnfitz
 	unsigned	protocolflags;
+	int		fish_counted;
 } server_t;
 
 
--- a/Quake/sv_main.c
+++ b/Quake/sv_main.c
@@ -86,6 +86,7 @@
 	extern	cvar_t	sv_idealpitchscale;
 	extern	cvar_t	sv_aim;
 	extern	cvar_t	sv_altnoclip; //johnfitz
+	extern  cvar_t  sv_fishfix;
 
 	sv.edicts = NULL; // ericw -- sv.edicts switched to use malloc()
 
@@ -104,6 +105,7 @@
 	Cvar_RegisterVariable (&sv_nostep);
 	Cvar_RegisterVariable (&sv_freezenonclients);
 	Cvar_RegisterVariable (&sv_altnoclip); //johnfitz
+	Cvar_RegisterVariable (&sv_fishfix);
 
 	Cmd_AddCommand ("sv_protocol", &SV_Protocol_f); //johnfitz
 
--- a/Quake/sv_phys.c
+++ b/Quake/sv_phys.c
@@ -47,7 +47,7 @@
 cvar_t	sv_maxvelocity = {"sv_maxvelocity","2000",CVAR_NONE};
 cvar_t	sv_nostep = {"sv_nostep","0",CVAR_NONE};
 cvar_t	sv_freezenonclients = {"sv_freezenonclients","0",CVAR_NONE};
-
+cvar_t	sv_fishfix = {"sv_fishfix", "1", CVAR_ARCHIVE};
 
 #define	MOVE_EPSILON	0.01
 
@@ -125,6 +125,7 @@
 	float	thinktime;
 	float	oldframe; //johnfitz
 	int		i; //johnfitz
+	int oldcount;
 
 	thinktime = ent->v.nextthink;
 	if (thinktime <= 0 || thinktime > sv.time + host_frametime)
@@ -141,8 +142,30 @@
 	pr_global_struct->time = thinktime;
 	pr_global_struct->self = EDICT_TO_PROG(ent);
 	pr_global_struct->other = EDICT_TO_PROG(sv.edicts);
+
+	if ((sv.time == 1.0) && sv_fishfix.value && sv.fish_counted &&
+	    !strcmp(PR_GetString(ent->v.classname), "monster_fish") &&
+	    !strcmp(PR_GetFunctionName(ent->v.think), "swimmonster_start_go"))
+	{
+		oldcount = pr_global_struct->total_monsters;
+	}
+	else oldcount = -1;
+
 	PR_ExecuteProgram (ent->v.think);
 
+	if (oldcount != -1)
+	{
+		if (pr_global_struct->total_monsters - oldcount == 1)
+		{
+			pr_global_struct->total_monsters -= 1;
+			if (sv.fish_counted == 1)
+			{
+				Con_Printf ("Detected fish-count bug in progs.dat; monster count has been adjusted\n");
+				sv.fish_counted++;
+			}
+		}
+	}
+
 //johnfitz -- PROTOCOL_FITZQUAKE
 //capture interval to nextthink here and send it to client for better
 //lerp timing, but only if interval is not 0.1 (which client assumes)
