got rid of buildnumber.c and buildnum program, now uses builddate.c (touched each...
authorlordhavoc <lordhavoc@d7cf8633-e32d-0410-b094-e92efae38249>
Thu, 31 Jan 2002 16:41:59 +0000 (16:41 +0000)
committerlordhavoc <lordhavoc@d7cf8633-e32d-0410-b094-e92efae38249>
Thu, 31 Jan 2002 16:41:59 +0000 (16:41 +0000)
clientside TraceLine can now hit brush model entities (TraceLine_ScanForBModels updates list of entities to check)
added *highly experimental* clientside gamecode (currently embedded in the engine, just trying things out) which currently doesn't do anything really
made CL_RelinkEntities only called when the client is connected and there is a world model
added fractalnoisequick (variant of fractalnoise that does not allocate/free a temporary buffer, and to achieve this does not use the range remapping)
added stainmap effects (stained lightmaps), which will probably soon replace decals
spark showers now pay attention to the velocity in the TE_SPARKSHOWER packet (if the mod uses this), bullet impacts still have no velocity
added TE_PLASMABURN (combination of TE_SMALLFLASH and a stain on the walls)
added svc_cgame (DO NOT USE THIS, EXPERIMENTAL, but so is the cgame code itself)
Cmd_TokenizeString now uses a fixed size buffer instead of many little allocations (speedup by not having Z_Malloc/Z_Free happening constantly)
cvar code tries very hard to avoid reallocating string now
va() function now uses a cycling set of 8 string buffers to try to avoid conflicts
console logging no longer uses va()
reduced default mesh buffer size from 21760 triangles to 4096 (transparent triangles are costly enough it's not a good idea to exceed this anyway)
texture management code now uses 3 memory pools to give better memory reports according to type of data
R_UpdateTexture has better memory behavior on non-procedural textures now (replaces inputtexels if it has not been uploaded yet, otherwise just uploads it directly)
added -developer commandline option (which is rather hacky) to force developer on for entire startup process, to get logging before the configs are read
decals stick to brush model entities now
stains stick to embedded bmodels (ones that are part of the map, not ones instanced from outside like ammo boxes)
skingroups above 0 are not automatically precached now (if you have a lot of mods installed in your id1 directory, they tend to not use all the skins, which is wasteful)
starting a new game (from the singleplayer menu) forces deathmatch and coop to 0 now
lightmaps are precached again (can't remember why I ever disabled this)
changed VectorSet's parameter order to be more consistent with other vector ops
removed a duplicate registration of the vid_mouse cvar (in vid_glx.c)

git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@1452 d7cf8633-e32d-0410-b094-e92efae38249

44 files changed:
builddate.c [new file with mode: 0644]
buildnum/buildnum.c [deleted file]
buildnum/makefile [deleted file]
buildnumber.c [deleted file]
cg_math.h [new file with mode: 0644]
cgame.c [new file with mode: 0644]
cgame_api.h [new file with mode: 0644]
cgamevm.c [new file with mode: 0644]
cgamevm.h [new file with mode: 0644]
chase.c
cl_decals.c
cl_main.c
cl_parse.c
cl_particles.c
cl_tent.c
client.h
cmd.c
common.c
console.c
cvar.c
fractalnoise.c
gl_backend.c
gl_rsurf.c
gl_textures.c
host.c
host_cmd.c
makefile
mathlib.c
mathlib.h
menu.c
model_alias.c
model_brush.c
model_brush.h
pr_cmds.c
protocol.h
quakedef.h
r_explosion.c
r_light.c
render.h
sv_main.c
sys_shared.c
vid_glx.c
view.c
zone.c

diff --git a/builddate.c b/builddate.c
new file mode 100644 (file)
index 0000000..c20120b
--- /dev/null
@@ -0,0 +1,2 @@
+
+char *buildstring = __TIME__ " " __DATE__;
diff --git a/buildnum/buildnum.c b/buildnum/buildnum.c
deleted file mode 100644 (file)
index 18e0d61..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-// LordHavoc: wait for a key press so the window doesn't disappear immediately
-#if _DEBUG && WIN32
-#define ERROR fprintf(stderr, "press any key\n");getchar();return -1;
-#else
-#define ERROR return -1;
-#endif
-
-// version template:
-#define BUILDNUMBER 1
-
-int main(int argc, char **argv)
-{
-       FILE *file;
-       unsigned int insize, outsize, sizedifference, inbuildsize, outbuildsize, writtensize;
-       unsigned char *data, *in, *out, *buildstring, *endofbuildstring, outbuildstring[32];
-       int inbuildnumber, outbuildnumber, remainder;
-       if (argc != 2)
-       {
-               fprintf(stderr, "usage: buildnum <filename.c or .h>\npurpose: increments build number in version string for darkplaces engine\n");
-               ERROR
-       }
-
-       file = fopen(argv[1], "rb");
-       if (!file)
-       {
-               fprintf(stderr, "buildnum: unable to open file \"%s\" for reading\n", argv[1]);
-               ERROR
-       }
-
-       fseek(file, 0, SEEK_END);
-       insize = ftell(file);
-       data = calloc(1, insize+20);
-       fseek(file, 0, SEEK_SET);
-       if (fread(data, 1, insize, file) < insize)
-       {
-               fprintf(stderr, "buildnum: unable to read file \"%s\"\n", argv[1]);
-               ERROR
-       }
-       fclose(file);
-       buildstring = strstr(data, "#define BUILDNUMBER ");
-       if (!buildstring)
-       {
-               fprintf(stderr, "buildnum: unable to find \"#define BUILDNUMBER \"\n");
-               ERROR
-       }
-       buildstring += strlen("#define BUILDNUMBER ");
-       endofbuildstring = buildstring;
-       while (*endofbuildstring && *endofbuildstring != '\r' && *endofbuildstring != '\n')
-               endofbuildstring++;
-       inbuildnumber = atoi(buildstring);
-       outbuildnumber = inbuildnumber + 1;
-       printf("incrementing build number %d to %d\n", inbuildnumber, outbuildnumber);
-       sprintf(outbuildstring, "%d", outbuildnumber);
-       inbuildsize = endofbuildstring - buildstring;
-       outbuildsize = strlen(outbuildstring);
-       sizedifference = outbuildsize-inbuildsize;
-       remainder = (data + insize) - buildstring;
-       outsize = insize + sizedifference;
-       memmove(buildstring + sizedifference, buildstring, remainder);
-       in = outbuildstring;
-       out = buildstring;
-       while (*in)
-               *out++ = *in++;
-
-       file = fopen(argv[1], "wb");
-       if (!file)
-       {
-               fprintf(stderr, "buildnum: unable to open file \"%s\" for writing\n", argv[1]);
-               ERROR
-       }
-
-       writtensize = fwrite(data, 1, outsize, file);
-       fclose(file);
-       if (writtensize < outsize)
-       {
-               fprintf(stderr, "buildnum: error writing file \"%s\", emergency code trying to save to buildnum.dmp\n", argv[1]);
-               file = fopen("buildnum.dmp", "wb");
-               if (!file)
-               {
-                       fprintf(stderr, "buildnum: unable to open file for writing\n");
-                       ERROR
-               }
-
-               writtensize = fwrite(data, 1, outsize, file);
-               fclose(file);
-               if (writtensize < outsize)
-               {
-                       fprintf(stderr, "buildnum: error writing emergency dump file!\n");
-                       ERROR
-               }
-       }
-
-       return 0;
-}
-
diff --git a/buildnum/makefile b/buildnum/makefile
deleted file mode 100644 (file)
index cd4a1db..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-all: buildnum
-
-.c.o:
-       gcc -Wall -c $*.c
-
-buildnum: buildnum.o
-       gcc -o $@ $^
-
-clean:
-       -rm -f buildnum.o buildnum *.d
-
-.PHONY: clean
-
--include *.d
diff --git a/buildnumber.c b/buildnumber.c
deleted file mode 100644 (file)
index dd203dc..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-
-#define BUILDNUMBER 1060
-
-int buildnumber = BUILDNUMBER;
diff --git a/cg_math.h b/cg_math.h
new file mode 100644 (file)
index 0000000..e7921e8
--- /dev/null
+++ b/cg_math.h
@@ -0,0 +1,101 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// mathlib.h
+
+#ifndef CG_MATH_H
+#define CG_MATH_H
+
+
+#ifndef true
+#define true 1
+#define false 0
+#endif
+
+#ifndef M_PI
+#define M_PI           3.14159265358979323846  // matches value in gcc v2 math.h
+#endif
+
+typedef float vec_t;
+typedef vec_t vec2_t[2];
+typedef vec_t vec3_t[3];
+typedef vec_t vec4_t[4];
+typedef vec_t vec5_t[5];
+typedef vec_t vec6_t[6];
+typedef vec_t vec7_t[7];
+typedef vec_t vec8_t[8];
+struct mplane_s;
+extern vec3_t vec3_origin;
+
+#define nanmask (255<<23)
+#define        IS_NAN(x) (((*(int *)&x)&nanmask)==nanmask)
+
+#define bound(min,num,max) (num >= min ? (num < max ? num : max) : min)
+
+#ifndef min
+#define min(A,B) (A < B ? A : B)
+#define max(A,B) (A > B ? A : B)
+#endif
+
+#define lhrandom(MIN,MAX) ((rand() & 32767) * (((MAX)-(MIN)) * (1.0f / 32767.0f)) + (MIN))
+
+#define DEG2RAD(a) ((a) * ((float) M_PI / 180.0f))
+#define RAD2DEG(a) ((a) * (180.0f / (float) M_PI))
+#define ANGLEMOD(a) (((int) ((a) * (65536.0f / 360.0f)) & 65535) * (360.0f / 65536.0f))
+
+#define VectorNegate(a,b) ((b)[0]=-((a)[0]),(b)[1]=-((a)[1]),(b)[2]=-((a)[2]))
+#define VectorSet(a,b,c,d) ((a)[0]=(b),(a)[1]=(c),(a)[2]=(d))
+#define VectorClear(a) ((a)[0]=(a)[1]=(a)[2]=0)
+#define DotProduct(a,b) ((a)[0]*(b)[0]+(a)[1]*(b)[1]+(a)[2]*(b)[2])
+#define VectorSubtract(a,b,c) ((c)[0]=(a)[0]-(b)[0],(c)[1]=(a)[1]-(b)[1],(c)[2]=(a)[2]-(b)[2])
+#define VectorAdd(a,b,c) ((c)[0]=(a)[0]+(b)[0],(c)[1]=(a)[1]+(b)[1],(c)[2]=(a)[2]+(b)[2])
+#define VectorCopy(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2])
+#define CrossProduct(a,b,c) ((c)[0]=(a)[1]*(b)[2]-(a)[2]*(b)[1],(c)[1]=(a)[2]*(b)[0]-(a)[0]*(b)[2],(c)[2]=(a)[0]*(b)[1]-(a)[1]*(b)[0])
+#define VectorNormalize(v) {float ilength = 1.0f / (float) sqrt(DotProduct(v,v));v[0] *= ilength;v[1] *= ilength;v[2] *= ilength;}
+#define VectorNormalize2(v,dest) {float ilength = 1.0f / (float) sqrt(DotProduct(v,v));dest[0] = v[0] * ilength;dest[1] = v[1] * ilength;dest[2] = v[2] * ilength;}
+#define VectorNormalizeDouble(v) {double ilength = 1.0 / (float) sqrt(DotProduct(v,v));v[0] *= ilength;v[1] *= ilength;v[2] *= ilength;}
+#define VectorDistance2(a, b) (((a)[0] - (b)[0]) * ((a)[0] - (b)[0]) + ((a)[1] - (b)[1]) * ((a)[1] - (b)[1]) + ((a)[2] - (b)[2]) * ((a)[2] - (b)[2]))
+#define VectorDistance(a, b) (sqrt(VectorDistance2(a,b)))
+#define VectorLength(a) sqrt(DotProduct(a, a))
+#define VectorScale(in, scale, out) ((out)[0] = (in)[0] * (scale),(out)[1] = (in)[1] * (scale),(out)[2] = (in)[2] * (scale))
+#define VectorCompare(a,b) (((a)[0]==(b)[0])&&((a)[1]==(b)[1])&&((a)[2]==(b)[2]))
+#define VectorMA(a, scale, b, c) ((c)[0] = (a)[0] + (scale) * (b)[0],(c)[1] = (a)[1] + (scale) * (b)[1],(c)[2] = (a)[2] + (scale) * (b)[2])
+#define VectorNormalizeFast(_v)\
+{\
+       float _y, _number;\
+       _number = DotProduct(_v, _v);\
+       if (_number != 0.0)\
+       {\
+               *((long *)&_y) = 0x5f3759df - ((* (long *) &_number) >> 1);\
+               _y = _y * (1.5f - (_number * 0.5f * _y * _y));\
+               VectorScale(_v, _y, _v);\
+       }\
+}
+#define VectorRandom(v) {do{(v)[0] = CGVM_RandomRange(-1, 1);(v)[1] = CGVM_RandomRange(-1, 1);(v)[2] = CGVM_RandomRange(-1, 1);}while(DotProduct(v, v) > 1);}
+
+void AngleVectors (vec3_t angles, vec3_t forward, vec3_t right, vec3_t up);
+// LordHavoc: proper matrix version of AngleVectors
+void AngleVectorsFLU (vec3_t angles, vec3_t forward, vec3_t left, vec3_t up);
+// LordHavoc: builds a [3][4] matrix
+void AngleMatrix (vec3_t angles, vec3_t translate, vec_t matrix[][4]);
+
+// LordHavoc: like AngleVectors, but taking a forward vector instead of angles, useful!
+void VectorVectors(const vec3_t forward, vec3_t right, vec3_t up);
+
+#endif
diff --git a/cgame.c b/cgame.c
new file mode 100644 (file)
index 0000000..a8715c4
--- /dev/null
+++ b/cgame.c
@@ -0,0 +1,262 @@
+
+#include "cgame_api.h"
+#include "cg_math.h"
+
+
+#ifndef NULL
+#define NULL ((void *)0)
+#endif
+
+static double gametime, frametime;
+
+struct localentity_s;
+typedef struct localentity_s
+{
+       int active; // true if the entity is alive (not freed)
+       float freetime; // time this entity was freed
+       float dietime;
+       vec3_t velocity;
+       vec3_t avelocity;
+       vec3_t worldmins;
+       vec3_t worldmaxs;
+       vec3_t entitymins;
+       vec3_t entitymaxs;
+       float bouncescale;
+       float airfrictionscale;
+       float gravityscale;
+       void (*framethink)(struct localentity_s *e);
+       //int solid;
+       //void (*touch)(struct localentity_s *self, struct localentity_s *other);
+       //void (*touchnetwork)(struct *localentity_s *self);
+       cgdrawentity_t draw;
+}
+localentity_t;
+
+#define MAX_LOCALENTITIES 1024
+static localentity_t *localentity;
+
+static cgphysentity_t *phys_entity;
+static int phys_entities;
+
+static float cg_gravity;
+
+static void readvector(vec3_t v)
+{
+       v[0] = CGVM_MSG_ReadFloat();
+       v[1] = CGVM_MSG_ReadFloat();
+       v[2] = CGVM_MSG_ReadFloat();
+}
+
+static localentity_t *entspawn(void)
+{
+       int i;
+       localentity_t *l;
+       for (i = 0;i < MAX_LOCALENTITIES;i++)
+       {
+               l = localentity + i;
+               if (!l->active && l->freetime < gametime)
+               {
+                       memset(l, 0, sizeof(*l));
+                       l->active = true;
+                       return l;
+               }
+       }
+       for (i = 0;i < MAX_LOCALENTITIES;i++)
+       {
+               l = localentity + i;
+               if (!l->active)
+               {
+                       memset(l, 0, sizeof(*l));
+                       l->active = true;
+                       return l;
+               }
+       }
+       return NULL;
+}
+
+static void entremove(localentity_t *e)
+{
+       memset(e, 0, sizeof(*e));
+       e->freetime = gametime + 1;
+}
+
+static void phys_setupphysentities(void)
+{
+       phys_entities = 0;
+       /*
+       for (i = 0;i < MAX_LOCALENTITIES;i++)
+       {
+               l = localentities + i;
+               if (l->active && l->solid)
+               {
+               }
+       }
+       */
+}
+
+static void phys_moveentities(void)
+{
+       int i;
+       localentity_t *l;
+       for (i = 0;i < MAX_LOCALENTITIES;i++)
+       {
+               l = localentity + i;
+               if (l->active)
+               {
+                       if (l->framethink)
+                               l->framethink(l);
+                       if (l->active && l->draw.model)
+                               CGVM_Draw_Entity(&l->draw);
+               }
+       }
+}
+
+static void phys_updateentities(void)
+{
+       phys_setupphysentities();
+       phys_moveentities();
+}
+
+static void phys_update(localentity_t *e)
+{
+       vec3_t impactpos, impactnormal, end;
+       int impactentnum;
+       float t, f, frac, bounce;
+       t = frametime;
+       if (t == 0)
+               return;
+       VectorMA(e->draw.angles, t, e->avelocity, e->draw.angles);
+       VectorMA(e->draw.origin, t, e->velocity, end);
+       frac = CGVM_TracePhysics(e->draw.origin, end, e->worldmins, e->worldmaxs, e->entitymins, e->entitymaxs, phys_entity, phys_entities, impactpos, impactnormal, &impactentnum);
+       VectorCopy(impactpos, e->draw.origin);
+       if (frac < 1)
+       {
+               bounce = DotProduct(e->velocity, impactnormal) * -e->bouncescale;
+               VectorMA(e->velocity, bounce, impactnormal, e->velocity);
+               // FIXME: do some kind of touch code here if physentities get implemented
+
+               if (impactnormal[2] >= 0.7 && DotProduct(e->velocity, e->velocity) < 100*100)
+               {
+                       VectorClear(e->velocity);
+                       VectorClear(e->avelocity);
+               }
+       }
+
+       if (e->airfrictionscale)
+       {
+               if (DotProduct(e->velocity, e->velocity) < 10*10)
+               {
+                       VectorClear(e->velocity);
+                       VectorClear(e->avelocity);
+               }
+               else
+               {
+                       f = 1 - (t * e->airfrictionscale);
+                       if (f > 0)
+                       {
+                               VectorScale(e->velocity, f, e->velocity);
+                               if (DotProduct(e->avelocity, e->avelocity) < 10*10)
+                               {
+                                       VectorClear(e->avelocity);
+                               }
+                               else
+                               {
+                                       VectorScale(e->avelocity, f, e->avelocity);
+                               }
+                       }
+                       else
+                       {
+                               VectorClear(e->velocity);
+                               VectorClear(e->avelocity);
+                       }
+               }
+       }
+       if (e->gravityscale)
+               e->velocity[2] += cg_gravity * e->gravityscale * t;
+}
+
+static void explosiondebris_framethink(localentity_t *self)
+{
+       if (gametime > self->dietime)
+       {
+               self->draw.scale -= frametime * 3;
+               if (self->draw.scale < 0.05f)
+               {
+                       entremove(self);
+                       return;
+               }
+       }
+       phys_update(self);
+}
+
+static void net_explosion(unsigned char num)
+{
+       int i;
+       float r;
+       vec3_t org;
+       double time;
+       localentity_t *e;
+       // need the time to know when the rubble should fade
+       time = CGVM_Time();
+       // read the network data
+       readvector(org);
+
+       for (i = 0;i < 40;i++)
+       {
+               e = entspawn();
+               if (!e)
+                       return;
+
+               VectorCopy(org, e->draw.origin);
+               e->draw.angles[0] = CGVM_RandomRange(0, 360);
+               e->draw.angles[1] = CGVM_RandomRange(0, 360);
+               e->draw.angles[2] = CGVM_RandomRange(0, 360);
+               VectorRandom(e->velocity);
+               VectorScale(e->velocity, 300, e->velocity);
+               e->velocity[2] -= cg_gravity * 0.1;
+               e->avelocity[0] = CGVM_RandomRange(0, 1440);
+               e->avelocity[1] = CGVM_RandomRange(0, 1440);
+               e->avelocity[2] = CGVM_RandomRange(0, 1440);
+               r = CGVM_RandomRange(0, 3);
+               if (r < 1)
+                       e->draw.model = CGVM_Model("progs/rubble1.mdl");
+               else if (r < 2)
+                       e->draw.model = CGVM_Model("progs/rubble2.mdl");
+               else
+                       e->draw.model = CGVM_Model("progs/rubble3.mdl");
+               e->draw.alpha = 1;
+               e->draw.scale = 1;
+               e->draw.frame1 = 0;
+               e->draw.frame2 = 0;
+               e->draw.framelerp = 0;
+               e->draw.skinnum = 5;
+               VectorSet(e->worldmins, 0, 0, -8);
+               VectorSet(e->worldmaxs, 0, 0, -8);
+               VectorSet(e->entitymins, -8, -8, -8);
+               VectorSet(e->entitymaxs, 8, 8, 8);
+               e->bouncescale = 1.4;
+               e->gravityscale = 1;
+               e->airfrictionscale = 1;
+               e->framethink = explosiondebris_framethink;
+               e->dietime = time + 5;
+       }
+}
+
+// called by engine
+void CG_Init(void)
+{
+       localentity = CGVM_Malloc(sizeof(localentity_t) * MAX_LOCALENTITIES);
+       phys_entity = CGVM_Malloc(sizeof(cgphysentity_t) * MAX_LOCALENTITIES);
+       CGVM_RegisterNetworkCode(1, net_explosion);
+       gametime = 0;
+}
+
+// called by engine
+void CG_Frame(double time)
+{
+       cg_gravity = -CGVM_GetCvarFloat("sv_gravity");
+       frametime = time - gametime;
+       gametime = time;
+       phys_updateentities();
+}
+
diff --git a/cgame_api.h b/cgame_api.h
new file mode 100644 (file)
index 0000000..a061818
--- /dev/null
@@ -0,0 +1,67 @@
+
+#ifndef CGAME_API_H
+#define CGAME_API_H
+
+// the CG state is reset quite harshly each time the client
+// connects/disconnects (to enforce the idea of cgame dying between levels),
+// and the Pre/PostNetworkFrame functions are only called while connected
+// (this does mean that all memory is freed, Init will be called again, etc)
+
+typedef struct cgdrawentity_s
+{
+       float origin[3];
+       float angles[3];
+       float alpha;
+       float scale;
+       int model; // index gotten from engine using CGVM_Model
+       int frame1;
+       int frame2;
+       float framelerp;
+       int skinnum;
+}
+cgdrawentity_t;
+
+typedef struct cgdrawlight_s
+{
+       float origin[3];
+       float light[3];
+}
+cgdrawlight_t;
+
+typedef struct cgphysentity_s
+{
+       int entnum; // reported by tracing, for use by cgame code
+       int padding; // unused
+       float mins[3];
+       float maxs[3];
+}
+cgphysentity_t;
+
+// engine functions the CG code can call
+void CGVM_RegisterNetworkCode(const unsigned char num, void (*netcode)(unsigned char num));
+unsigned char CGVM_MSG_ReadByte(void);
+short CGVM_MSG_ReadShort(void);
+int CGVM_MSG_ReadLong(void);
+float CGVM_MSG_ReadFloat(void);
+float CGVM_MSG_ReadCoord(void);
+float CGVM_MSG_ReadAngle(void);
+float CGVM_MSG_ReadPreciseAngle(void);
+void CGVM_Draw_Entity(const cgdrawentity_t *e);
+void CGVM_Draw_Light(const cgdrawlight_t *l);
+void *CGVM_Malloc(const int size);
+void CGVM_Free(void *mem);
+float CGVM_RandomRange(const float r1, const float r2);
+float CGVM_TracePhysics(const float *start, const float *end, const float *worldmins, const float *worldmaxs, const float *entitymins, const float *entitymaxs, const cgphysentity_t *physentities, const int numphysentities, float *impactpos, float *impactnormal, int *impactentnum);
+float CGVM_GetCvarFloat(const char *name);
+int CGVM_GetCvarInt(const char *name);
+char *CGVM_GetCvarString(const char *name);
+double CGVM_Time(void);
+int CGVM_Model(const char *name);
+// more will be added
+
+// engine called functions
+void CG_Init(void);
+void CG_Frame(double time);
+// more might be added
+
+#endif
diff --git a/cgamevm.c b/cgamevm.c
new file mode 100644 (file)
index 0000000..d11642e
--- /dev/null
+++ b/cgamevm.c
@@ -0,0 +1,269 @@
+
+#include "quakedef.h"
+#include "cgame_api.h"
+
+#define CGVM_RENDERENTITIES 1024
+
+static entity_render_t cgvm_renderentities[CGVM_RENDERENTITIES];
+static int cgvm_renderentity;
+
+static mempool_t *cgvm_mempool;
+
+static void (*cgvm_networkcode[256])(unsigned char num);
+
+static byte *cgvm_netbuffer;
+static int cgvm_netbufferlength;
+static int cgvm_netbufferpos;
+
+#define MAX_CGVM_MODELS 128
+#define MAX_CGVM_MODELNAME 32
+static char cgvm_modelname[MAX_CGVM_MODELS][MAX_CGVM_MODELNAME];
+static model_t *cgvm_model[MAX_CGVM_MODELS];
+
+void CL_CGVM_Init(void)
+{
+       cgvm_mempool = Mem_AllocPool("CGVM");
+}
+
+void CL_CGVM_Clear(void)
+{
+       Mem_EmptyPool(cgvm_mempool);
+       memset(cgvm_networkcode, 0, sizeof(cgvm_networkcode));
+       memset(cgvm_modelname, 0, sizeof(cgvm_modelname));
+       memset(cgvm_model, 0, sizeof(cgvm_model));
+}
+
+void CL_CGVM_Frame(void)
+{
+       cgvm_renderentity = 0;
+       CG_Frame(cl.time); // API call
+}
+
+// starts the cgame code
+void CL_CGVM_Start(void)
+{
+       CL_CGVM_Clear();
+       CG_Init(); // API call
+}
+
+void CL_CGVM_ParseNetwork(byte *netbuffer, int length)
+{
+       int num;
+       cgvm_netbuffer = netbuffer;
+       cgvm_netbufferlength = length;
+       cgvm_netbufferpos = 0;
+       while (cgvm_netbufferpos < cgvm_netbufferlength)
+       {
+               num = CGVM_MSG_ReadByte();
+               if (cgvm_networkcode[num])
+                       cgvm_networkcode[num](num);
+               else
+                       Host_Error("CL_CGVM_ParseNetwork: unregistered network code %i", num);
+       }
+}
+
+
+
+
+
+
+
+
+void CGVM_RegisterNetworkCode(const unsigned char num, void (*netcode)(unsigned char num))
+{
+       if (cgvm_networkcode[num])
+               Host_Error("CGVM_RegisterNetworkCode: value %i already registered", num);
+       cgvm_networkcode[num] = netcode;
+}
+
+unsigned char CGVM_MSG_ReadByte(void)
+{
+       if (cgvm_netbufferpos < cgvm_netbufferlength)
+               return cgvm_netbuffer[cgvm_netbufferpos++];
+       else
+               return 0;
+}
+
+short CGVM_MSG_ReadShort(void)
+{
+       int num;
+       num = CGVM_MSG_ReadByte() | (CGVM_MSG_ReadByte() << 8);
+       return num;
+}
+
+int CGVM_MSG_ReadLong(void)
+{
+       int num;
+       num = CGVM_MSG_ReadByte() | (CGVM_MSG_ReadByte() << 8) | (CGVM_MSG_ReadByte() << 16) | (CGVM_MSG_ReadByte() << 24);
+       return num;
+}
+
+float CGVM_MSG_ReadFloat(void)
+{
+       unsigned int num;
+       num = CGVM_MSG_ReadByte() | (CGVM_MSG_ReadByte() << 8) | (CGVM_MSG_ReadByte() << 16) | (CGVM_MSG_ReadByte() << 24);
+       return *((float *)&num);
+}
+
+float CGVM_MSG_ReadCoord(void)
+{
+       return CGVM_MSG_ReadFloat();
+}
+
+float CGVM_MSG_ReadAngle(void)
+{
+       return CGVM_MSG_ReadByte() * 360.0f / 256.0f;
+}
+
+float CGVM_MSG_ReadPreciseAngle(void)
+{
+       return ((unsigned short)CGVM_MSG_ReadShort()) * 360.0f / 65536.0f;
+}
+
+void CGVM_Draw_Entity(const cgdrawentity_t *e)
+{
+       entity_render_t *r;
+       //Con_Printf("CGVM_Draw_Entity: origin %f %f %f angles %f %f %f alpha %f scale %f model %i frame1 %i frame2 %i framelerp %f skinnum %i\n", e->origin[0], e->origin[1], e->origin[2], e->angles[0], e->angles[1], e->angles[2], e->alpha, e->scale, e->model, e->frame1, e->frame2, e->framelerp, e->skinnum);
+
+       if (!e->model)
+               return;
+
+       if (cgvm_renderentity >= CGVM_RENDERENTITIES
+        || r_refdef.numentities >= MAX_VISEDICTS)
+               return;
+
+       r = cgvm_renderentities + cgvm_renderentity;
+       VectorCopy(e->origin, r->origin);
+       VectorCopy(e->angles, r->angles);
+       r->alpha = e->alpha;
+       r->scale = e->scale;
+       if (e->model < 0 || e->model >= MAX_CGVM_MODELS || !cgvm_model[e->model])
+       {
+               Con_Printf("CGVM_Draw_Entity: invalid model index %i\n", e->model);
+               return;
+       }
+       r->model = cgvm_model[e->model]; //Mod_ForName(e->model, false, false, false);
+       /*
+       if (!r->model)
+       {
+               Con_Printf("CGVM_Draw_Entity: unable to find model \"%s\"");
+               return;
+       }
+       */
+
+       r->frame = e->frame2;
+       // FIXME: support colormapping?
+       r->colormap = -1;
+       // FIXME: support effects?
+       r->effects = 0;
+       r->skinnum = e->skinnum;
+       // FIXME: any flags worth setting?
+       r->flags = 0;
+
+       r->frame1 = e->frame1;
+       r->frame2 = e->frame2;
+       r->framelerp = e->framelerp;
+       r->frame1time = 0;
+       r->frame2time = 0;
+
+       r_refdef.entities[r_refdef.numentities++] = r;
+
+       cgvm_renderentity++;
+}
+
+void CGVM_Draw_Light(const cgdrawlight_t *l)
+{
+       CL_AllocDlight(NULL, (float *) l->origin, 1, l->light[0], l->light[1], l->light[2], 0, 0);
+}
+
+void *CGVM_Malloc(const int size)
+{
+       return Mem_Alloc(cgvm_mempool, size);
+}
+
+void CGVM_Free(void *mem)
+{
+       return Mem_Free(mem);
+}
+
+float CGVM_RandomRange(const float r1, const float r2)
+{
+       return lhrandom(r1, r2);
+}
+
+float CGVM_TracePhysics(const float *start, const float *end, const float *worldmins, const float *worldmaxs, const float *entitymins, const float *entitymaxs, const cgphysentity_t *physentities, const int numphysentities, float *impactpos, float *impactnormal, int *impactentnum)
+{
+       float frac;
+       vec3_t start2, end2, middle;
+       // FIXME: do tracing agains network entities and physentities here
+       // placeholder world only code assuming 0 size
+       middle[0] = (worldmins[0] + worldmaxs[0]) * 0.5f;
+       middle[1] = (worldmins[1] + worldmaxs[1]) * 0.5f;
+       middle[2] = (worldmins[2] + worldmaxs[2]) * 0.5f;
+       VectorAdd(start, middle, start2);
+       VectorAdd(end, middle, end2);
+       frac = TraceLine((float *)start2, (float *)end2, impactpos, impactnormal, 0, true);
+       VectorSubtract(impactpos, middle, impactpos);
+       //VectorCopy(end, impactpos);
+       //VectorClear(impactnormal);
+       *impactentnum = -1;
+       return frac;
+}
+
+char *CGVM_GetCvarString(const char *name)
+{
+       cvar_t *cvar;
+       cvar = Cvar_FindVar((char *)name);
+       if (cvar)
+               return cvar->string;
+       else
+               return 0;
+}
+
+float CGVM_GetCvarFloat(const char *name)
+{
+       cvar_t *cvar;
+       cvar = Cvar_FindVar((char *)name);
+       if (cvar)
+               return cvar->value;
+       else
+               return 0;
+}
+
+int CGVM_GetCvarInt(const char *name)
+{
+       cvar_t *cvar;
+       cvar = Cvar_FindVar((char *)name);
+       if (cvar)
+               return cvar->integer;
+       else
+               return 0;
+}
+
+double CGVM_Time(void)
+{
+       return cl.time;
+}
+
+int CGVM_Model(const char *name)
+{
+       int i;
+       model_t *model;
+       if (strlen(name) > (MAX_CGVM_MODELNAME - 1))
+               return 0;
+       for (i = 1;i < MAX_CGVM_MODELS;i++)
+       {
+               if (!cgvm_modelname[i][0])
+                       break;
+               if (!strcmp(name, cgvm_modelname[i]))
+                       return i;
+       }
+       if (i >= MAX_CGVM_MODELS)
+               return 0;
+       model = Mod_ForName((char *)name, false, false, false);
+       if (!model)
+               return 0;
+       strcpy(cgvm_modelname[i], name);
+       cgvm_model[i] = model;
+       return i;
+}
diff --git a/cgamevm.h b/cgamevm.h
new file mode 100644 (file)
index 0000000..d572730
--- /dev/null
+++ b/cgamevm.h
@@ -0,0 +1,11 @@
+
+#ifndef CGAMEVM_H
+#define CGAMEVM_H
+
+void CL_CGVM_Init(void);
+void CL_CGVM_Clear(void);
+void CL_CGVM_Frame(void);
+void CL_CGVM_Start(void);
+void CL_CGVM_ParseNetwork(byte *netbuffer, int length);
+
+#endif
\ No newline at end of file
diff --git a/chase.c b/chase.c
index 1b6e78e..e383ab6 100644 (file)
--- a/chase.c
+++ b/chase.c
@@ -40,8 +40,53 @@ void Chase_Reset (void)
 
 int traceline_endcontents;
 
-float TraceLine (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal, int contents)
+static entity_render_t *traceline_entity[MAX_EDICTS];
+static int traceline_entities;
+
+// builds list of entities for TraceLine to check later
+void TraceLine_ScanForBModels(void)
+{
+       int i;
+       entity_render_t *ent;
+       model_t *model;
+       traceline_entities = 0;
+       for (i = 1;i < MAX_EDICTS;i++)
+       {
+               ent = &cl_entities[i].render;
+               model = ent->model;
+               // look for embedded brush models only
+               if (model && model->name[0] == '*')
+               {
+                       // this does nothing for * models currently...
+                       //Mod_CheckLoaded(model);
+                       if (model->type == mod_brush)
+                       {
+                               traceline_entity[traceline_entities++] = ent;
+                               if (ent->angles[0] || ent->angles[2])
+                               {
+                                       // pitch or roll
+                                       VectorAdd(ent->origin, model->rotatedmins, ent->mins);
+                                       VectorAdd(ent->origin, model->rotatedmaxs, ent->maxs);
+                               }
+                               else if (ent->angles[1])
+                               {
+                                       // yaw
+                                       VectorAdd(ent->origin, model->yawmins, ent->mins);
+                                       VectorAdd(ent->origin, model->yawmaxs, ent->maxs);
+                               }
+                               else
+                               {
+                                       VectorAdd(ent->origin, model->normalmins, ent->mins);
+                                       VectorAdd(ent->origin, model->normalmaxs, ent->maxs);
+                               }
+                       }
+               }
+       }
+}
+
+float TraceLine (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal, int contents, int hitbmodels)
 {
+       float maxfrac;
        trace_t trace;
 
 // FIXME: broken, fix it
@@ -63,7 +108,59 @@ float TraceLine (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal, int con
        if (normal)
                VectorCopy (trace.plane.normal, normal);
        traceline_endcontents = trace.endcontents;
-       return trace.fraction;
+       maxfrac = trace.fraction;
+
+       if (hitbmodels && traceline_entities)
+       {
+               int n;
+               entity_render_t *ent;
+               vec3_t start2, end2, tracemins, tracemaxs;
+               tracemins[0] = min(start[0], end[0]);
+               tracemaxs[0] = max(start[0], end[0]);
+               tracemins[1] = min(start[1], end[1]);
+               tracemaxs[1] = max(start[1], end[1]);
+               tracemins[2] = min(start[2], end[2]);
+               tracemaxs[2] = max(start[2], end[2]);
+
+               // look for embedded bmodels
+               for (n = 0;n < traceline_entities;n++)
+               {
+                       ent = traceline_entity[n];
+                       if (ent->mins[0] > tracemaxs[0] || ent->maxs[0] < tracemins[0]
+                        || ent->mins[1] > tracemaxs[1] || ent->maxs[1] < tracemins[1]
+                        || ent->mins[2] > tracemaxs[2] || ent->maxs[2] < tracemins[2])
+                               continue;
+
+                       softwaretransformforentity(ent);
+                       softwareuntransform(start, start2);
+                       softwareuntransform(end, end2);
+
+                       memset (&trace, 0, sizeof(trace));
+                       VectorCopy (end2, trace.endpos);
+                       trace.fraction = 1;
+                       trace.startcontents = contents;
+                       VectorCopy(start2, RecursiveHullCheckInfo.start);
+                       VectorSubtract(end2, start2, RecursiveHullCheckInfo.dist);
+                       RecursiveHullCheckInfo.hull = ent->model->hulls;
+                       RecursiveHullCheckInfo.trace = &trace;
+                       SV_RecursiveHullCheck (ent->model->hulls->firstclipnode, 0, 1, start2, end2);
+
+                       if (trace.allsolid || trace.startsolid || trace.fraction < maxfrac)
+                       {
+                               maxfrac = trace.fraction;
+                               if (impact)
+                               {
+                                       softwaretransform(trace.endpos, impact);
+                               }
+                               if (normal)
+                               {
+                                       softwaretransformdirection(trace.plane.normal, normal);
+                               }
+                               traceline_endcontents = trace.endcontents;
+                       }
+               }
+       }
+       return maxfrac;
 }
 
 void Chase_Update (void)
@@ -81,7 +178,7 @@ void Chase_Update (void)
        chase_dest[1] = r_refdef.vieworg[1] + forward[1] * dist;
        chase_dest[2] = r_refdef.vieworg[2] + forward[2] * dist + chase_up.value;
 
-       TraceLine (r_refdef.vieworg, chase_dest, stop, normal, 0);
+       TraceLine (r_refdef.vieworg, chase_dest, stop, normal, 0, true);
        chase_dest[0] = stop[0] + forward[0] * 8 + normal[0] * 4;
        chase_dest[1] = stop[1] + forward[1] * 8 + normal[1] * 4;
        chase_dest[2] = stop[2] + forward[2] * 8 + normal[2] * 4;
index 5bea3de..54f53a9 100644 (file)
@@ -174,7 +174,7 @@ void CL_Decal(vec3_t origin, int tex, float scale, float red, float green, float
                        {
                                softwaretransformforentity(decalent);
                                softwareuntransform(origin, decalorg);
-                               CL_RecursiveDecalSurface (decalmodel->nodes);
+                               CL_RecursiveDecalSurface (decalmodel->nodes + decalmodel->hulls[0].firstclipnode);
                        }
                }
        }
index 4c1cad5..f78a191 100644 (file)
--- a/cl_main.c
+++ b/cl_main.c
@@ -116,6 +116,8 @@ void CL_ClearState (void)
                ClearStateToDefault(&cl_entities[i].state_previous);
                ClearStateToDefault(&cl_entities[i].state_current);
        }
+
+       CL_CGVM_Clear();
 }
 
 void CL_LerpUpdate(entity_t *e)
@@ -502,7 +504,7 @@ static void CL_RelinkNetworkEntities()
                                v2[0] = v[0] * 18 + neworg[0];
                                v2[1] = v[1] * 18 + neworg[1];
                                v2[2] = v[2] * 18 + neworg[2] + 16;
-                               TraceLine(neworg, v2, v, NULL, 0);
+                               TraceLine(neworg, v2, v, NULL, 0, true);
 
                                CL_AllocDlight (NULL, v, 100, 1, 1, 1, 0, 0.1);
                        }
@@ -750,14 +752,13 @@ static void CL_RelinkEffects()
 
 void CL_RelinkEntities (void)
 {
-       r_refdef.numentities = 0;
-
        CL_LerpPlayerVelocity();
        CL_RelinkNetworkEntities();
+       TraceLine_ScanForBModels();
        CL_RelinkEffects();
        CL_MoveParticles();
        CL_UpdateDecals();
-       CL_UpdateTEnts ();
+       CL_UpdateTEnts();
 }
 
 
@@ -796,7 +797,14 @@ int CL_ReadFromServer (void)
        if (netshown)
                Con_Printf ("\n");
 
-       CL_RelinkEntities ();
+       r_refdef.numentities = 0;
+       if (cls.state == ca_connected && cl.worldmodel)
+       {
+               CL_RelinkEntities ();
+
+               // run cgame code (which can add more entities)
+               CL_CGVM_Frame();
+       }
 
 //
 // bring the links up to date
@@ -980,4 +988,5 @@ void CL_Init (void)
        CL_Particles_Init();
        CL_Decals_Init();
        CL_Screen_Init();
+       CL_CGVM_Init();
 }
index d8d7702..82f7f90 100644 (file)
@@ -481,6 +481,10 @@ void CL_ParseServerInfo (void)
 
        Mem_CheckSentinelsGlobal();
 
+       CL_CGVM_Start();
+
+       Mem_CheckSentinelsGlobal();
+
        noclip_anglehack = false;               // noclip is turned off at start
 }
 
@@ -919,6 +923,8 @@ void CL_ParseEffect2 (void)
 
 #define SHOWNET(x) if(cl_shownet.integer==2)Con_Printf ("%3i:%s\n", msg_readcount-1, x);
 
+static byte cgamenetbuffer[65536];
+
 /*
 =====================
 CL_ParseServerMessage
@@ -985,7 +991,7 @@ void CL_ParseServerMessage (void)
                        temp = "<unknown>";
                        cmdlogname[cmdindex] = temp;
                }
-       
+
                // other commands
                switch (cmd)
                {
@@ -1012,23 +1018,23 @@ void CL_ParseServerMessage (void)
                                Host_Error ("CL_ParseServerMessage: Illegible server message\n");
                        }
                        break;
-                       
+
                case svc_nop:
 //                     Con_Printf ("svc_nop\n");
                        break;
-                       
+
                case svc_time:
                        // handle old protocols which do not have entity update ranges
                        entitiesupdated = true;
                        cl.mtime[1] = cl.mtime[0];
-                       cl.mtime[0] = MSG_ReadFloat ();                 
+                       cl.mtime[0] = MSG_ReadFloat ();
                        break;
 
                case svc_clientdata:
                        i = MSG_ReadShort ();
                        CL_ParseClientdata (i);
                        break;
-               
+
                case svc_version:
                        i = MSG_ReadLong ();
                        if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION && i != 250)
@@ -1047,11 +1053,11 @@ void CL_ParseServerMessage (void)
                case svc_print:
                        Con_Printf ("%s", MSG_ReadString ());
                        break;
-                       
+
                case svc_centerprint:
                        SCR_CenterPrint (MSG_ReadString ());
                        break;
-                       
+
                case svc_stufftext:
                        Cbuf_AddText (MSG_ReadString ());
                        break;
@@ -1082,7 +1088,7 @@ void CL_ParseServerMessage (void)
                        cl_lightstyle[i].map[MAX_STYLESTRING - 1] = 0;
                        cl_lightstyle[i].length = strlen(cl_lightstyle[i].map);
                        break;
-                       
+
                case svc_sound:
                        CL_ParseStartSoundPacket(false);
                        break;
@@ -1102,7 +1108,7 @@ void CL_ParseServerMessage (void)
                                Host_Error ("CL_ParseServerMessage: svc_updatename >= MAX_SCOREBOARD");
                        strcpy (cl.scores[i].name, MSG_ReadString ());
                        break;
-                       
+
                case svc_updatefrags:
                        i = MSG_ReadByte ();
                        if (i >= cl.maxclients)
@@ -1179,7 +1185,7 @@ void CL_ParseServerMessage (void)
                                Host_Error ("svc_updatestat: %i is invalid", i);
                        cl.stats[i] = MSG_ReadLong ();
                        break;
-                       
+
                case svc_spawnstaticsound:
                        CL_ParseStaticSound (false);
                        break;
@@ -1229,6 +1235,25 @@ void CL_ParseServerMessage (void)
                case svc_skybox:
                        R_SetSkyBox(MSG_ReadString());
                        break;
+               case svc_cgame:
+                       {
+                               int length;
+                               length = (int) ((unsigned short) MSG_ReadShort());
+                               /*
+                               if (cgamenetbuffersize < length)
+                               {
+                                       cgamenetbuffersize = length;
+                                       if (cgamenetbuffer)
+                                               Mem_Free(cgamenetbuffer);
+                                       cgamenetbuffer = Mem_Alloc(cgamenetbuffersize);
+                               }
+                               */
+                               for (i = 0;i < length;i++)
+                                       cgamenetbuffer[i] = MSG_ReadByte();
+                               if (!msg_badread)
+                                       CL_CGVM_ParseNetwork(cgamenetbuffer, length);
+                       }
+                       break;
                }
        }
 
index ce100de..61a66e1 100644 (file)
@@ -321,14 +321,14 @@ CL_ParticleExplosion
 */
 void CL_ParticleExplosion (vec3_t org, int smoke)
 {
-       int i, j;
-       float f;
-       vec3_t v, end, ang;
-       byte noise1[32*32], noise2[32*32];
-
-       VectorClear(end); // hush MSVC
        if (cl_particles.integer && cl_particles_explosions.integer)
        {
+               int i, j;
+               float f;
+               vec3_t v, end, ang;
+               byte noise1[32*32], noise2[32*32];
+
+               VectorClear(end); // hush MSVC
                i = Mod_PointInLeaf(org, cl.worldmodel)->contents;
                if (i == CONTENTS_SLIME || i == CONTENTS_WATER)
                {
@@ -336,15 +336,15 @@ void CL_ParticleExplosion (vec3_t org, int smoke)
                                particle(pt_bubble, PARTICLE_BILLBOARD, 0xFFFFFF, tex_bubble, false, true, 2, 2, 255, 9999, 1.5, org[0] + lhrandom(-16, 16), org[1] + lhrandom(-16, 16), org[2] + lhrandom(-16, 16), lhrandom(-96, 96), lhrandom(-96, 96), lhrandom(-96, 96), 0, 0, 0, 0, 0, 0);
 
                        ang[2] = lhrandom(0, 360);
-                       fractalnoise(noise1, 32, 4);
-                       fractalnoise(noise2, 32, 8);
+                       fractalnoisequick(noise1, 32, 4);
+                       fractalnoisequick(noise2, 32, 8);
                        for (i = 0;i < 32;i++)
                        {
                                for (j = 0;j < 32;j++)
                                {
                                        VectorRandom(v);
                                        VectorMA(org, 16, v, v);
-                                       TraceLine(org, v, end, NULL, 0);
+                                       TraceLine(org, v, end, NULL, 0, true);
                                        ang[0] = (j + 0.5f) * (360.0f / 32.0f);
                                        ang[1] = (i + 0.5f) * (360.0f / 32.0f);
                                        AngleVectors(ang, v, NULL, NULL);
@@ -359,15 +359,15 @@ void CL_ParticleExplosion (vec3_t org, int smoke)
                else
                {
                        ang[2] = lhrandom(0, 360);
-                       fractalnoise(noise1, 32, 4);
-                       fractalnoise(noise2, 32, 8);
+                       fractalnoisequick(noise1, 32, 4);
+                       fractalnoisequick(noise2, 32, 8);
                        for (i = 0;i < 32;i++)
                        {
                                for (j = 0;j < 32;j++)
                                {
                                        VectorRandom(v);
                                        VectorMA(org, 16, v, v);
-                                       TraceLine(org, v, end, NULL, 0);
+                                       TraceLine(org, v, end, NULL, 0, true);
                                        ang[0] = (j + 0.5f) * (360.0f / 32.0f);
                                        ang[1] = (i + 0.5f) * (360.0f / 32.0f);
                                        AngleVectors(ang, v, NULL, NULL);
@@ -385,6 +385,7 @@ void CL_ParticleExplosion (vec3_t org, int smoke)
        }
        else
                R_NewExplosion(org);
+       R_Stain(org, 96, 80, 80, 80, 128, 176, 176, 176, 128);
 }
 
 /*
@@ -413,6 +414,7 @@ void CL_BlobExplosion (vec3_t org)
        int                     i;
        if (!cl_particles.integer) return;
 
+       R_Stain(org, 96, 96, 64, 96, 128, 160, 128, 160, 128);
        for (i = 0;i < 256;i++)
                particle(pt_blob , PARTICLE_BILLBOARD, particlepalette[ 66+(rand()%6)], tex_particle, false, true, 4, 4, 255, 9999, 0, org[0] + lhrandom(-16, 16), org[1] + lhrandom(-16, 16), org[2] + lhrandom(-16, 16), lhrandom(-4, 4), lhrandom(-4, 4), lhrandom(-128, 128), 0, 0, 0, 0, 0, 0);
        for (i = 0;i < 256;i++)
@@ -448,6 +450,7 @@ void CL_SparkShower (vec3_t org, vec3_t dir, int count)
 {
        if (!cl_particles.integer) return;
 
+       R_Stain(org, 32, 96, 96, 96, 32, 128, 128, 128, 32);
        CL_Decal(org, tex_bullethole[rand()&7], 16 * cl_particles_size.value, 0, 0, 0, 1);
 
        // smoke puff
@@ -458,10 +461,17 @@ void CL_SparkShower (vec3_t org, vec3_t dir, int count)
        {
                // sparks
                while(count--)
-                       particle(pt_spark, PARTICLE_BILLBOARD, particlepalette[0x68 + (rand() & 7)], tex_particle, false, true, 1, 1, lhrandom(0, 255), 9999, 1.5, org[0], org[1], org[2], lhrandom(-64, 64), lhrandom(-64, 64), lhrandom(0, 128), 512.0f, 0, 0, 0, 0.2f, 0);
+                       particle(pt_spark, PARTICLE_BILLBOARD, particlepalette[0x68 + (rand() & 7)], tex_particle, false, true, 1, 1, lhrandom(0, 255), 9999, 1.5, org[0], org[1], org[2], lhrandom(-64, 64) + dir[0], lhrandom(-64, 64) + dir[1], lhrandom(0, 128) + dir[2], 512.0f, 0, 0, 0, 0.2f, 0);
        }
 }
 
+void CL_PlasmaBurn (vec3_t org)
+{
+       if (!cl_particles.integer) return;
+
+       R_Stain(org, 48, 96, 96, 96, 48, 128, 128, 128, 48);
+}
+
 void CL_BloodPuff (vec3_t org, vec3_t vel, int count)
 {
        // bloodcount is used to accumulate counts too small to cause a blood particle
@@ -809,8 +819,8 @@ void CL_MoveParticles (void)
 {
        particle_t *p;
        renderparticle_t *r;
-       int i, activeparticles, maxparticle, j, a, b, pressureused = false;
-       float gravity, dvel, frametime, f, dist, normal[3], v[3], org[3], o[3];
+       int i, activeparticles, maxparticle, j, a, pressureused = false;
+       float gravity, dvel, frametime, f, dist, normal[3], v[3], org[3];
 
        // LordHavoc: early out condition
        if (!cl_numparticles)
@@ -846,11 +856,13 @@ void CL_MoveParticles (void)
                VectorCopy(p->org, org);
                if (p->bounce)
                {
-                       if (TraceLine(p->oldorg, p->org, v, normal, 0) < 1)
+                       if (TraceLine(p->oldorg, p->org, v, normal, 0, true) < 1)
                        {
                                VectorCopy(v, p->org);
                                if (p->bounce < 0)
                                {
+                                       // assume it's blood (lame, but...)
+                                       R_Stain(v, 48, 64, 24, 24, 48, 192, 48, 48, 48);
                                        CL_Decal(v, p->tex, p->scalex * cl_particles_size.value, p->color[0] * (1.0f / 255.0f), p->color[1] * (1.0f / 255.0f), p->color[2] * (1.0f / 255.0f), p->alpha * (1.0f / 255.0f));
                                        p->die = -1;
                                        freeparticles[j++] = p;
@@ -930,7 +942,7 @@ void CL_MoveParticles (void)
                                        p->vel[2] = 96;
                                        break;
                                default: // CONTENTS_SOLID and any others
-                                       TraceLine(p->oldorg, p->org, v, normal, 0);
+                                       TraceLine(p->oldorg, p->org, v, normal, 0, true);
                                        VectorCopy(v, p->org);
                                        p->tex = tex_smoke[rand()&7];
                                        p->orientation = PARTICLE_BILLBOARD;
@@ -1064,18 +1076,23 @@ void CL_MoveParticles (void)
                                p->die = -1;
                        break;
                case pt_rain:
+                       a = Mod_PointInLeaf(p->org, cl.worldmodel)->contents;
+                       if (a != CONTENTS_EMPTY && a != CONTENTS_SKY)
+                               p->die = -1;
+                       /*
                        f = 0;
                        b = Mod_PointInLeaf(p->oldorg, cl.worldmodel)->contents;
                        VectorCopy(p->oldorg, o);
                        while (f < 1)
                        {
                                a = b;
-                               f = TraceLine(o, p->org, v, normal, a);
+                               f = TraceLine(o, p->org, v, normal, a, true);
                                b = traceline_endcontents;
                                if (f < 1 && b != CONTENTS_EMPTY && b != CONTENTS_SKY)
                                {
+                                       #if 1
                                        p->die = -1;
-                                       /*
+                                       #else
                                        p->die = cl.time + 1000;
                                        p->vel[0] = p->vel[1] = p->vel[2] = 0;
                                        VectorCopy(v, p->org);
@@ -1101,9 +1118,11 @@ void CL_MoveParticles (void)
                                                p->scaley = 8;
                                                break;
                                        }
-                                       */
+                                       #endif
+                                       break;
                                }
                        }
+                       */
                        break;
                        /*
                case pt_raindropsplash:
index 42f342b..387a64c 100644 (file)
--- a/cl_tent.c
+++ b/cl_tent.c
@@ -121,18 +121,21 @@ void CL_ParseTEnt (void)
        {
        case TE_WIZSPIKE:                       // spike hitting wall
                MSG_ReadVector(pos);
+               Mod_FindNonSolidLocation(pos, cl.worldmodel);
                CL_RunParticleEffect (pos, vec3_origin, 20, 30);
                S_StartSound (-1, 0, cl_sfx_wizhit, pos, 1, 1);
                break;
-               
+
        case TE_KNIGHTSPIKE:                    // spike hitting wall
                MSG_ReadVector(pos);
+               Mod_FindNonSolidLocation(pos, cl.worldmodel);
                CL_RunParticleEffect (pos, vec3_origin, 226, 20);
                S_StartSound (-1, 0, cl_sfx_knighthit, pos, 1, 1);
                break;
-               
+
        case TE_SPIKE:                  // spike hitting wall
                MSG_ReadVector(pos);
+               Mod_FindNonSolidLocation(pos, cl.worldmodel);
                // LordHavoc: changed to spark shower
                CL_SparkShower(pos, vec3_origin, 15);
                //CL_RunParticleEffect (pos, vec3_origin, 0, 10);
@@ -151,6 +154,7 @@ void CL_ParseTEnt (void)
                break;
        case TE_SPIKEQUAD:                      // quad spike hitting wall
                MSG_ReadVector(pos);
+               Mod_FindNonSolidLocation(pos, cl.worldmodel);
                // LordHavoc: changed to spark shower
                CL_SparkShower(pos, vec3_origin, 15);
                //CL_RunParticleEffect (pos, vec3_origin, 0, 10);
@@ -171,6 +175,7 @@ void CL_ParseTEnt (void)
                break;
        case TE_SUPERSPIKE:                     // super spike hitting wall
                MSG_ReadVector(pos);
+               Mod_FindNonSolidLocation(pos, cl.worldmodel);
                // LordHavoc: changed to dust shower
                CL_SparkShower(pos, vec3_origin, 30);
                //CL_RunParticleEffect (pos, vec3_origin, 0, 20);
@@ -189,6 +194,7 @@ void CL_ParseTEnt (void)
                break;
        case TE_SUPERSPIKEQUAD:                 // quad super spike hitting wall
                MSG_ReadVector(pos);
+               Mod_FindNonSolidLocation(pos, cl.worldmodel);
                // LordHavoc: changed to dust shower
                CL_SparkShower(pos, vec3_origin, 30);
                //CL_RunParticleEffect (pos, vec3_origin, 0, 20);
@@ -225,8 +231,15 @@ void CL_ParseTEnt (void)
                dir[1] = MSG_ReadChar ();
                dir[2] = MSG_ReadChar ();
                count = MSG_ReadByte (); // amount of particles
+               Mod_FindNonSolidLocation(pos, cl.worldmodel);
                CL_SparkShower(pos, dir, count);
                break;
+       case TE_PLASMABURN:
+               MSG_ReadVector(pos);
+               Mod_FindNonSolidLocation(pos, cl.worldmodel);
+               CL_AllocDlight (NULL, pos, 200, 1, 1, 1, 1000, 0.2);
+               CL_PlasmaBurn(pos);
+               break;
                // LordHavoc: added for improved gore
        case TE_BLOODSHOWER:    // vaporized body
                MSG_ReadVector(pos); // mins
@@ -266,6 +279,7 @@ void CL_ParseTEnt (void)
 
        case TE_GUNSHOT:                        // bullet hitting wall
                MSG_ReadVector(pos);
+               Mod_FindNonSolidLocation(pos, cl.worldmodel);
                // LordHavoc: changed to dust shower
                CL_SparkShower(pos, vec3_origin, 15);
                //CL_RunParticleEffect (pos, vec3_origin, 0, 20);
@@ -273,6 +287,7 @@ void CL_ParseTEnt (void)
 
        case TE_GUNSHOTQUAD:                    // quad bullet hitting wall
                MSG_ReadVector(pos);
+               Mod_FindNonSolidLocation(pos, cl.worldmodel);
                CL_SparkShower(pos, vec3_origin, 15);
                CL_AllocDlight (NULL, pos, 200, 0.1f, 0.1f, 1.0f, 1000, 0.2);
                break;
@@ -393,20 +408,20 @@ void CL_ParseTEnt (void)
                CL_ParseBeam (Mod_ForName(MSG_ReadString(), true, false, false));
                break;
 
-       case TE_LAVASPLASH:     
+       case TE_LAVASPLASH:
                pos[0] = MSG_ReadCoord ();
                pos[1] = MSG_ReadCoord ();
                pos[2] = MSG_ReadCoord ();
                CL_LavaSplash (pos);
                break;
-       
+
        case TE_TELEPORT:
                pos[0] = MSG_ReadCoord ();
                pos[1] = MSG_ReadCoord ();
                pos[2] = MSG_ReadCoord ();
                CL_TeleportSplash (pos);
                break;
-               
+
        case TE_EXPLOSION2:                             // color mapped explosion
                MSG_ReadVector(pos);
                Mod_FindNonSolidLocation(pos, cl.worldmodel);
@@ -418,7 +433,7 @@ void CL_ParseTEnt (void)
                CL_AllocDlight (NULL, pos, 350, tempcolor[0] * (1.0f / 255.0f), tempcolor[1] * (1.0f / 255.0f), tempcolor[2] * (1.0f / 255.0f), 700, 0.5);
                S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
                break;
-               
+
        default:
                Host_Error ("CL_ParseTEnt: bad type %d", type);
        }
index c0db055..e7ce7b1 100644 (file)
--- a/client.h
+++ b/client.h
@@ -448,6 +448,7 @@ void CL_RunParticleEffect (vec3_t org, vec3_t dir, int color, int count);
 void CL_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent);
 void CL_RocketTrail2 (vec3_t start, vec3_t end, int color, entity_t *ent);
 void CL_SparkShower (vec3_t org, vec3_t dir, int count);
+void CL_PlasmaBurn (vec3_t org);
 void CL_BloodPuff (vec3_t org, vec3_t vel, int count);
 void CL_FlameCube (vec3_t mins, vec3_t maxs, int count);
 void CL_Flames (vec3_t org, vec3_t vel, int count);
@@ -488,7 +489,9 @@ void CL_Decal(vec3_t origin, int tex, float scale, float red, float green, float
 // if contents is not zero, it will impact on content changes
 // (leafs matching contents are considered empty, others are solid)
 extern int traceline_endcontents; // set by TraceLine
-float TraceLine (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal, int contents);
+// need to call this sometime before using TraceLine with hitbmodels
+void TraceLine_ScanForBModels(void);
+float TraceLine (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal, int contents, int hitbmodels);
 
 #include "cl_screen.h"
 
@@ -527,3 +530,5 @@ refdef_t;
 refdef_t r_refdef;
 
 extern mempool_t *cl_refdef_mempool;
+
+#include "cgamevm.h"
diff --git a/cmd.c b/cmd.c
index 293155d..a9da1b0 100644 (file)
--- a/cmd.c
+++ b/cmd.c
@@ -510,6 +510,11 @@ char       *Cmd_Args (void)
 }
 
 
+#if 1
+#define CMD_TOKENIZELENGTH 4096
+char cmd_tokenizebuffer[CMD_TOKENIZELENGTH];
+#endif
+
 /*
 ============
 Cmd_TokenizeString
@@ -519,11 +524,16 @@ Parses the given string into command line tokens.
 */
 static void Cmd_TokenizeString (char *text)
 {
-       int             i;
-
+       int l;
+#ifdef CMD_TOKENIZELENGTH
+       int pos;
+       pos = 0;
+#else
+       int i;
 // clear the args from the last string
        for (i=0 ; i<cmd_argc ; i++)
                Z_Free (cmd_argv[i]);
+#endif
 
        cmd_argc = 0;
        cmd_args = NULL;
@@ -554,7 +564,15 @@ static void Cmd_TokenizeString (char *text)
 
                if (cmd_argc < MAX_ARGS)
                {
-                       cmd_argv[cmd_argc] = Z_Malloc (strlen(com_token)+1);
+                       l = strlen(com_token) + 1;
+#ifdef CMD_TOKENIZELENGTH
+                       if (pos + l > CMD_TOKENIZELENGTH)
+                               Sys_Error("Cmd_TokenizeString: ran out of %i character buffer space for command arguements\n", CMD_TOKENIZELENGTH);
+                       cmd_argv[cmd_argc] = cmd_tokenizebuffer + pos;
+                       pos += l;
+#else
+                       cmd_argv[cmd_argc] = Z_Malloc (l);
+#endif
                        strcpy (cmd_argv[cmd_argc], com_token);
                        cmd_argc++;
                }
index 2711267..404d73e 100644 (file)
--- a/common.c
+++ b/common.c
@@ -1243,14 +1243,18 @@ FIXME: make this buffer size safe someday
 */
 char    *va(char *format, ...)
 {
-       va_list         argptr;
-       static char             string[1024];
-       
+       va_list argptr;
+       // LordHavoc: now cycles through 8 buffers to avoid problems in most cases
+       static char string[8][1024], *s;
+       static int stringindex = 0;
+
+       s = string[stringindex];
+       stringindex = (stringindex + 1) & 7;
        va_start (argptr, format);
-       vsprintf (string, format,argptr);
+       vsprintf (s, format,argptr);
        va_end (argptr);
 
-       return string;  
+       return s;
 }
 
 
@@ -1258,7 +1262,7 @@ char    *va(char *format, ...)
 int     memsearch (byte *start, int count, int search)
 {
        int             i;
-       
+
        for (i=0 ; i<count ; i++)
                if (start[i] == search)
                        return i;
index e99181e..c5332a9 100644 (file)
--- a/console.c
+++ b/console.c
@@ -240,7 +240,7 @@ void Con_Init (void)
        memset (con_text, ' ', CON_TEXTSIZE);
        con_linewidth = -1;
        Con_CheckResize ();
-       
+
        Con_Printf ("Console initialized.\n");
 
 //
@@ -390,27 +390,32 @@ void Con_Printf (char *fmt, ...)
        va_list         argptr;
        char            msg[MAXPRINTMSG];
 //     static qboolean inupdate;
-       
+
        va_start (argptr,fmt);
        vsprintf (msg,fmt,argptr);
        va_end (argptr);
-       
+
 // also echo to debugging console
        Sys_Printf ("%s", msg);
 
 // log all messages to file
        if (con_debuglog)
-               Con_DebugLog(va("%s/qconsole.log",com_gamedir), "%s", msg);
+       {
+               // can't use va() here because it might overwrite other important things
+               char logname[MAX_OSPATH];
+               sprintf(logname, "%s/qconsole.log", com_gamedir);
+               Con_DebugLog(logname, "%s", msg);
+       }
 
        if (!con_initialized)
                return;
-               
+
        if (cls.state == ca_dedicated)
                return;         // no graphics mode
 
 // write it to the scrollable buffer
        Con_Print (msg);
-       
+
 // update the screen if the console is displayed
        // LordHavoc: I don't think there's a real need for this
        /*
diff --git a/cvar.c b/cvar.c
index bee89d9..25ad142 100644 (file)
--- a/cvar.c
+++ b/cvar.c
@@ -172,10 +172,17 @@ void Cvar_Set (char *var_name, char *value)
        }
 
        changed = strcmp(var->string, value);
+       // LordHavoc: don't reallocate when there is no change
+       if (!changed)
+               return;
 
-       Z_Free (var->string);   // free the old value string
+       // LordHavoc: don't reallocate when the buffer is the same size
+       if (!var->string || strlen(var->string) != strlen(value))
+       {
+               Z_Free (var->string);   // free the old value string
 
-       var->string = Z_Malloc (strlen(value)+1);
+               var->string = Z_Malloc (strlen(value)+1);
+       }
        strcpy (var->string, value);
        var->value = atof (var->string);
        var->integer = (int) var->value;
index 31b140d..ad9d91e 100644 (file)
@@ -63,3 +63,50 @@ void fractalnoise(byte *noise, int size, int startgrid)
        Mem_Free(noisebuf);
 #undef n
 }
+
+// unnormalized, used for explosions mainly, does not allocate/free memory (hence the name quick)
+void fractalnoisequick(byte *noise, int size, int startgrid)
+{
+       int x, y, g, g2, amplitude, size1 = size - 1, sizepower, gridpower;
+#define n(x,y) noise[((y)&size1)*size+((x)&size1)]
+
+       for (sizepower = 0;(1 << sizepower) < size;sizepower++);
+       if (size != (1 << sizepower))
+               Sys_Error("fractalnoise: size must be power of 2\n");
+
+       for (gridpower = 0;(1 << gridpower) < startgrid;gridpower++);
+       if (startgrid != (1 << gridpower))
+               Sys_Error("fractalnoise: grid must be power of 2\n");
+
+       startgrid = bound(0, startgrid, size);
+
+       amplitude = 255; // this gets halved before use
+       memset(noise, 0, size*size);
+
+       for (g2 = startgrid;g2;g2 >>= 1)
+       {
+               // brownian motion (at every smaller level there is random behavior)
+               amplitude >>= 1;
+               for (y = 0;y < size;y += g2)
+                       for (x = 0;x < size;x += g2)
+                               n(x,y) += (rand()&amplitude);
+
+               g = g2 >> 1;
+               if (g)
+               {
+                       // subdivide, diamond-square algorythm (really this has little to do with squares)
+                       // diamond
+                       for (y = 0;y < size;y += g2)
+                               for (x = 0;x < size;x += g2)
+                                       n(x+g,y+g) = (byte) (((int) n(x,y) + (int) n(x+g2,y) + (int) n(x,y+g2) + (int) n(x+g2,y+g2)) >> 2);
+                       // square
+                       for (y = 0;y < size;y += g2)
+                               for (x = 0;x < size;x += g2)
+                               {
+                                       n(x+g,y) = (byte) (((int) n(x,y) + (int) n(x+g2,y) + (int) n(x+g,y-g) + (int) n(x+g,y+g)) >> 2);
+                                       n(x,y+g) = (byte) (((int) n(x,y) + (int) n(x,y+g2) + (int) n(x-g,y+g) + (int) n(x+g,y+g)) >> 2);
+                               }
+               }
+       }
+#undef n
+}
index 21eafef..cf86ac6 100644 (file)
@@ -6,7 +6,8 @@ static int max_batch;
 static int max_verts; // always max_meshs * 3
 #define TRANSDEPTHRES 4096
 
-static cvar_t gl_mesh_maxtriangles = {0, "gl_mesh_maxtriangles", "21760"};
+//static cvar_t gl_mesh_maxtriangles = {0, "gl_mesh_maxtriangles", "21760"};
+static cvar_t gl_mesh_maxtriangles = {0, "gl_mesh_maxtriangles", "4096"};
 static cvar_t gl_mesh_batchtriangles = {0, "gl_mesh_batchtriangles", "1024"};
 static cvar_t gl_mesh_merge = {0, "gl_mesh_merge", "1"};
 static cvar_t gl_mesh_floatcolors = {0, "gl_mesh_floatcolors", "1"};
@@ -84,6 +85,7 @@ static buf_bcolor_t *buf_transbcolor;
 static buf_texcoord_t *buf_transtexcoord[MAX_TEXTUREUNITS];
 
 static mempool_t *gl_backend_mempool;
+static int resizingbuffers = false;
 
 static void gl_backend_start(void)
 {
@@ -91,7 +93,8 @@ static void gl_backend_start(void)
 
        max_verts = max_meshs * 3;
 
-       gl_backend_mempool = Mem_AllocPool("GL_Backend");
+       if (!gl_backend_mempool)
+               gl_backend_mempool = Mem_AllocPool("GL_Backend");
 
 #define BACKENDALLOC(var, count, sizeofstruct)\
        {\
@@ -134,7 +137,7 @@ static void gl_backend_start(void)
 
 static void gl_backend_shutdown(void)
 {
-       int i;
+       //int i;
        /*
 #define BACKENDFREE(var)\
        if (var)\
@@ -143,6 +146,7 @@ static void gl_backend_shutdown(void)
                var = NULL;\
        }
        */
+       /*
 #define BACKENDFREE(var) var = NULL;
 
        BACKENDFREE(buf_mesh)
@@ -163,8 +167,12 @@ static void gl_backend_shutdown(void)
                BACKENDFREE(buf_texcoord[i])
                BACKENDFREE(buf_transtexcoord[i])
        }
+       */
 
-       Mem_FreePool(&gl_backend_mempool);
+       if (resizingbuffers)
+               Mem_EmptyPool(gl_backend_mempool);
+       else
+               Mem_FreePool(&gl_backend_mempool);
 
        backendunits = 0;
        backendactive = false;
@@ -191,8 +199,10 @@ static void gl_backend_bufferchanges(int init)
 
                if (!init)
                {
+                       resizingbuffers = true;
                        gl_backend_shutdown();
                        gl_backend_start();
+                       resizingbuffers = false;
                }
        }
 }
index 2b777f2..d1d45ab 100644 (file)
@@ -45,8 +45,18 @@ static void gl_surf_newmap(void)
 {
 }
 
+static int dlightdivtable[32768];
+
 void GL_Surf_Init(void)
 {
+       int i;
+       if (!dlightdivtable[1])
+       {
+               dlightdivtable[0] = 4194304;
+               for (i = 1;i < 32768;i++)
+                       dlightdivtable[i] = 4194304 / (i << 7);
+       }
+
        Cvar_RegisterVariable(&r_ambient);
        Cvar_RegisterVariable(&r_vertexsurfaces);
        Cvar_RegisterVariable(&r_dlightmap);
@@ -56,8 +66,6 @@ void GL_Surf_Init(void)
        R_RegisterModule("GL_Surf", gl_surf_start, gl_surf_shutdown, gl_surf_newmap);
 }
 
-static int dlightdivtable[32768];
-
 static int R_AddDynamicLights (msurface_t *surf)
 {
        int         sdtable[256], lnum, td, maxdist, maxdist2, maxdist3, i, s, t, smax, tmax, smax3, red, green, blue, lit, dist2, impacts, impactt, subtract;
@@ -74,13 +82,6 @@ static int R_AddDynamicLights (msurface_t *surf)
 
        lit = false;
 
-       if (!dlightdivtable[1])
-       {
-               dlightdivtable[0] = 4194304;
-               for (s = 1; s < 32768; s++)
-                       dlightdivtable[s] = 4194304 / (s << 7);
-       }
-
        smax = (surf->extents[0] >> 4) + 1;
        tmax = (surf->extents[1] >> 4) + 1;
 
@@ -94,7 +95,8 @@ static int R_AddDynamicLights (msurface_t *surf)
                dist = DotProduct (local, surf->plane->normal) - surf->plane->dist;
 
                // for comparisons to minimum acceptable light
-               maxdist = (int) r_dlight[lnum].cullradius2;
+               // compensate for LIGHTOFFSET
+               maxdist = (int) r_dlight[lnum].cullradius2 + LIGHTOFFSET;
 
                // already clamped, skip this
                // clamp radius to avoid exceeding 32768 entry division table
@@ -164,6 +166,183 @@ static int R_AddDynamicLights (msurface_t *surf)
        return lit;
 }
 
+void R_StainNode (mnode_t *node, model_t *model, vec3_t origin, float radius, int icolor[8])
+{
+       float ndist;
+       msurface_t *surf, *endsurf;
+       int sdtable[256], td, maxdist, maxdist2, maxdist3, i, s, t, smax, tmax, smax3, dist2, impacts, impactt, subtract, a, stained, cr, cg, cb, ca, ratio;
+       byte *bl;
+       vec3_t impact;
+       // LordHavoc: use 64bit integer...  shame it's not very standardized...
+#if _MSC_VER || __BORLANDC__
+       __int64     k;
+#else
+       long long   k;
+#endif
+
+
+       // for comparisons to minimum acceptable light
+       // compensate for 4096 offset
+       maxdist = radius * radius + 4096;
+
+       // clamp radius to avoid exceeding 32768 entry division table
+       if (maxdist > 4194304)
+               maxdist = 4194304;
+
+       subtract = (int) ((1.0f / maxdist) * 4194304.0f);
+
+loc0:
+       if (node->contents < 0)
+               return;
+       ndist = PlaneDiff(origin, node->plane);
+       if (ndist > radius)
+       {
+               node = node->children[0];
+               goto loc0;
+       }
+       if (ndist < -radius)
+       {
+               node = node->children[1];
+               goto loc0;
+       }
+
+       dist2 = ndist * ndist;
+       dist2 += 4096.0f;
+       if (dist2 < maxdist)
+       {
+               maxdist3 = maxdist - dist2;
+
+               impact[0] = origin[0] - node->plane->normal[0] * ndist;
+               impact[1] = origin[1] - node->plane->normal[1] * ndist;
+               impact[2] = origin[2] - node->plane->normal[2] * ndist;
+
+               for (surf = model->surfaces + node->firstsurface, endsurf = surf + node->numsurfaces;surf < endsurf;surf++)
+               {
+                       if (surf->stainsamples)
+                       {
+                               smax = (surf->extents[0] >> 4) + 1;
+                               tmax = (surf->extents[1] >> 4) + 1;
+
+                               impacts = DotProduct (impact, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3] - surf->texturemins[0];
+                               impactt = DotProduct (impact, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3] - surf->texturemins[1];
+
+                               s = bound(0, impacts, smax * 16) - impacts;
+                               t = bound(0, impactt, tmax * 16) - impactt;
+                               i = s * s + t * t + dist2;
+                               if (i > maxdist)
+                                       continue;
+
+                               // reduce calculations
+                               for (s = 0, i = impacts; s < smax; s++, i -= 16)
+                                       sdtable[s] = i * i + dist2;
+
+                               // convert to 8.8 blocklights format
+                               bl = surf->stainsamples;
+                               smax3 = smax * 3;
+                               stained = false;
+
+                               i = impactt;
+                               for (t = 0;t < tmax;t++, i -= 16)
+                               {
+                                       td = i * i;
+                                       // make sure some part of it is visible on this line
+                                       if (td < maxdist3)
+                                       {
+                                               maxdist2 = maxdist - td;
+                                               for (s = 0;s < smax;s++)
+                                               {
+                                                       if (sdtable[s] < maxdist2)
+                                                       {
+                                                               k = dlightdivtable[(sdtable[s] + td) >> 7] - subtract;
+                                                               if (k > 0)
+                                                               {
+                                                                       ratio = rand() & 255;
+                                                                       ca = (((icolor[7] - icolor[3]) * ratio) >> 8) + icolor[3];
+                                                                       a = (ca * k) >> 8;
+                                                                       if (a > 0)
+                                                                       {
+                                                                               a = bound(0, a, 256);
+                                                                               cr = (((icolor[4] - icolor[0]) * ratio) >> 8) + icolor[0];
+                                                                               cg = (((icolor[5] - icolor[1]) * ratio) >> 8) + icolor[1];
+                                                                               cb = (((icolor[6] - icolor[2]) * ratio) >> 8) + icolor[2];
+                                                                               bl[0] = (byte) ((((cr - (int) bl[0]) * a) >> 8) + (int) bl[0]);
+                                                                               bl[1] = (byte) ((((cg - (int) bl[1]) * a) >> 8) + (int) bl[1]);
+                                                                               bl[2] = (byte) ((((cb - (int) bl[2]) * a) >> 8) + (int) bl[2]);
+                                                                               stained = true;
+                                                                       }
+                                                               }
+                                                       }
+                                                       bl += 3;
+                                               }
+                                       }
+                                       else // skip line
+                                               bl += smax3;
+                               }
+                               // force lightmap upload
+                               if (stained)
+                                       surf->cached_dlight = true;
+                       }
+               }
+       }
+
+       if (node->children[0]->contents >= 0)
+       {
+               if (node->children[1]->contents >= 0)
+               {
+                       R_StainNode(node->children[0], model, origin, radius, icolor);
+                       node = node->children[1];
+                       goto loc0;
+               }
+               else
+               {
+                       node = node->children[0];
+                       goto loc0;
+               }
+       }
+       else if (node->children[1]->contents >= 0)
+       {
+               node = node->children[1];
+               goto loc0;
+       }
+}
+
+void R_Stain (vec3_t origin, float radius, int cr1, int cg1, int cb1, int ca1, int cr2, int cg2, int cb2, int ca2)
+{
+       int n, icolor[8];
+       entity_render_t *ent;
+       model_t *model;
+       vec3_t org;
+       icolor[0] = cr1;
+       icolor[1] = cg1;
+       icolor[2] = cb1;
+       icolor[3] = ca1;
+       icolor[4] = cr2;
+       icolor[5] = cg2;
+       icolor[6] = cb2;
+       icolor[7] = ca2;
+
+       model = cl.worldmodel;
+       softwaretransformidentity();
+       R_StainNode(model->nodes + model->hulls[0].firstclipnode, model, origin, radius, icolor);
+
+       // look for embedded bmodels
+       for (n = 1;n < MAX_EDICTS;n++)
+       {
+               ent = &cl_entities[n].render;
+               model = ent->model;
+               if (model && model->name[0] == '*')
+               {
+                       Mod_CheckLoaded(model);
+                       if (model->type == mod_brush)
+                       {
+                               softwaretransformforentity(ent);
+                               softwareuntransform(origin, org);
+                               R_StainNode(model->nodes + model->hulls[0].firstclipnode, model, org, radius, icolor);
+                       }
+               }
+       }
+}
+
 /*
 ===============
 R_BuildLightMap
@@ -174,7 +353,7 @@ Combine and scale multiple lightmaps into the 8.8 format in blocklights
 static void R_BuildLightMap (msurface_t *surf, int dlightchanged)
 {
        int             smax, tmax, i, j, size, size3, shift, scale, maps, *bl, stride, l;
-       byte    *lightmap, *out;
+       byte    *lightmap, *out, *stain;
 
        // update cached lighting info
        surf->cached_dlight = 0;
@@ -231,6 +410,12 @@ static void R_BuildLightMap (msurface_t *surf, int dlightchanged)
                                        *bl++ += *lightmap++ * scale;
        }
 
+       stain = surf->stainsamples;
+       if (stain)
+               for (bl = blocklights, i = 0;i < size3;i++)
+                       if (stain[i] < 255)
+                               bl[i] = (bl[i] * stain[i]) >> 8;
+
        bl = blocklights;
        out = templight;
        // deal with lightmap brightness scale
index 52c0da5..03da518 100644 (file)
@@ -1,8 +1,8 @@
 #include "quakedef.h"
 
-cvar_t r_max_size = {0, "r_max_size", "2048"};
-cvar_t r_max_scrapsize = {0, "r_max_scrapsize", "1024"};
-cvar_t r_picmip = {0, "r_picmip", "0"};
+cvar_t r_max_size = {CVAR_SAVE, "r_max_size", "2048"};
+cvar_t r_max_scrapsize = {CVAR_SAVE, "r_max_scrapsize", "256"};
+cvar_t r_picmip = {CVAR_SAVE, "r_picmip", "0"};
 cvar_t r_lerpimages = {CVAR_SAVE, "r_lerpimages", "1"};
 cvar_t r_precachetextures = {CVAR_SAVE, "r_precachetextures", "1"};
 
@@ -11,6 +11,8 @@ int           gl_filter_mag = GL_LINEAR;
 
 
 static mempool_t *texturemempool;
+static mempool_t *texturedatamempool;
+static mempool_t *textureprocessingmempool;
 
 // note: this must not conflict with TEXF_ flags in r_textures.h
 // cleared when a texture is uploaded
@@ -289,6 +291,8 @@ void R_FreeTexturePool(rtexturepool_t **rtexturepool)
                Host_Error("R_FreeTexturePool: pool not linked\n");
        while (pool->gltchain)
                R_FreeTexture(pool->gltchain);
+       if (pool->imagechain)
+               Sys_Error("R_FreeTexturePool: not all images freed\n");
        Mem_Free(pool);
 }
 
@@ -458,7 +462,9 @@ static void r_textures_start(void)
        // use the largest scrap texture size we can (not sure if this is really a good idea)
        for (block_size = 1;block_size < realmaxsize && block_size < r_max_scrapsize.integer;block_size <<= 1);
 
-       texturemempool = Mem_AllocPool("Textures");
+       texturemempool = Mem_AllocPool("Texture Info");
+       texturedatamempool = Mem_AllocPool("Texture Storage (not yet uploaded)");
+       textureprocessingmempool = Mem_AllocPool("Texture Processing Buffers");
        gltexnuminuse = Mem_Alloc(texturemempool, MAX_GLTEXTURES);
        //memset(gltexnuminuse, 0, MAX_GLTEXTURES);
 }
@@ -490,6 +496,8 @@ static void r_textures_shutdown(void)
        texturebuffer = NULL;
        gltexnuminuse = NULL;
        Mem_FreePool(&texturemempool);
+       Mem_FreePool(&texturedatamempool);
+       Mem_FreePool(&textureprocessingmempool);
 }
 
 static void r_textures_newmap(void)
@@ -585,8 +593,8 @@ static void R_ResampleTexture (void *indata, int inwidth, int inheight, void *ou
                if (resamplerow2)
                        Mem_Free(resamplerow2);
                resamplerowsize = outwidth*4;
-               resamplerow1 = Mem_Alloc(texturemempool, resamplerowsize);
-               resamplerow2 = Mem_Alloc(texturemempool, resamplerowsize);
+               resamplerow1 = Mem_Alloc(textureprocessingmempool, resamplerowsize);
+               resamplerow2 = Mem_Alloc(textureprocessingmempool, resamplerowsize);
        }
 #define row1 resamplerow1
 #define row2 resamplerow2
@@ -1000,14 +1008,15 @@ static void R_Upload(gltexture_t *glt, byte *data)
                                Mem_Free(resizebuffer);
                        if (colorconvertbuffer)
                                Mem_Free(colorconvertbuffer);
-                       resizebuffer = Mem_Alloc(texturemempool, resizebuffersize);
-                       colorconvertbuffer = Mem_Alloc(texturemempool, resizebuffersize);
+                       resizebuffer = Mem_Alloc(textureprocessingmempool, resizebuffersize);
+                       colorconvertbuffer = Mem_Alloc(textureprocessingmempool, resizebuffersize);
                        if (!resizebuffer || !colorconvertbuffer)
                                Host_Error("R_Upload: out of memory\n");
                }
 
                if (glt->image->flags & GLTEXF_UPLOAD)
                {
+                       Con_DPrintf("uploaded new fragments image\n");
                        glt->image->flags &= ~GLTEXF_UPLOAD;
                        memset(resizebuffer, 255, glt->image->width * glt->image->height * glt->image->bytesperpixel);
                        glTexImage2D (GL_TEXTURE_2D, 0, glt->image->glinternalformat, glt->image->width, glt->image->height, 0, glt->image->glformat, GL_UNSIGNED_BYTE, resizebuffer);
@@ -1049,8 +1058,8 @@ static void R_Upload(gltexture_t *glt, byte *data)
                        Mem_Free(resizebuffer);
                if (colorconvertbuffer)
                        Mem_Free(colorconvertbuffer);
-               resizebuffer = Mem_Alloc(texturemempool, resizebuffersize);
-               colorconvertbuffer = Mem_Alloc(texturemempool, resizebuffersize);
+               resizebuffer = Mem_Alloc(textureprocessingmempool, resizebuffersize);
+               colorconvertbuffer = Mem_Alloc(textureprocessingmempool, resizebuffersize);
                if (!resizebuffer || !colorconvertbuffer)
                        Host_Error("R_Upload: out of memory\n");
        }
@@ -1244,7 +1253,7 @@ static void R_UploadTexture (gltexture_t *glt)
                                if (texturebuffer)
                                        Mem_Free(texturebuffer);
                                texturebuffersize = glt->width * glt->height * glt->textype->inputbytesperpixel;
-                               texturebuffer = Mem_Alloc(texturemempool, texturebuffersize);
+                               texturebuffer = Mem_Alloc(textureprocessingmempool, texturebuffersize);
                        }
 
                        glt->generate(texturebuffer, glt->width, glt->height, (void *)glt->proceduraldata, glt->proceduraldatasize);
@@ -1287,7 +1296,7 @@ static gltexture_t *R_SetupTexture(gltexturepool_t *pool, char *identifier, int
 
        if (data)
        {
-               glt->inputtexels = Mem_Alloc(texturemempool, glt->width * glt->height * texinfo->inputbytesperpixel);
+               glt->inputtexels = Mem_Alloc(texturedatamempool, glt->width * glt->height * texinfo->inputbytesperpixel);
                if (glt->inputtexels == NULL)
                        Sys_Error("R_SetupTexture: out of memory\n");
                memcpy(glt->inputtexels, data, glt->width * glt->height * texinfo->inputbytesperpixel);
@@ -1391,7 +1400,10 @@ rtexture_t *R_LoadTexture (rtexturepool_t *rtexturepool, char *identifier, int w
        if (identifier && (glt = R_FindTexture(pool, identifier)))
        {
                if (crc == glt->crc && width == glt->width && height == glt->height && texinfo == glt->textype && ((flags ^ glt->flags) & TEXF_IMPORTANTBITS) == 0 && ((flags ^ glt->flags) & GLTEXF_IMPORTANTBITS) == 0)
+               {
+                       Con_Printf("R_LoadTexture: exact match with existing texture %s\n", identifier);
                        return (rtexture_t *)glt; // exact match, use existing
+               }
                Con_Printf("R_LoadTexture: cache mismatch on %s, replacing old texture\n", identifier);
                R_FreeTexture(glt);
        }
@@ -1425,7 +1437,10 @@ rtexture_t *R_ProceduralTexture (rtexturepool_t *rtexturepool, char *identifier,
        if (identifier && (glt = R_FindTexture(pool, identifier)))
        {
                if (width == glt->width && height == glt->height && texinfo == glt->textype && ((flags ^ glt->flags) & TEXF_IMPORTANTBITS) == 0 && ((flags ^ glt->flags) & GLTEXF_IMPORTANTBITS) == 0)
+               {
+                       Con_Printf("R_LoadTexture: exact match with existing texture %s\n", identifier);
                        return (rtexture_t *)glt; // exact match, use existing
+               }
                Con_DPrintf("R_LoadTexture: cache mismatch, replacing old texture\n");
                R_FreeTexture(glt);
        }
@@ -1538,16 +1553,23 @@ void R_UpdateTexture(rtexture_t *rt, byte *data)
        if (data == NULL)
                Host_Error("R_UpdateTexture: no data supplied\n");
        glt = (gltexture_t *)rt;
+       /*
        if (!(glt->flags & GLTEXF_PROCEDURAL))
        {
                if (glt->inputtexels == NULL)
                {
-                       glt->inputtexels = Mem_Alloc(texturemempool, glt->width * glt->height * glt->textype->inputbytesperpixel);
+                       glt->inputtexels = Mem_Alloc(texturedatamempool, glt->width * glt->height * glt->textype->inputbytesperpixel);
                        if (glt->inputtexels == NULL)
                                Host_Error("R_UpdateTexture: ran out of memory\n");
                }
                memcpy(glt->inputtexels, data, glt->width * glt->height * glt->textype->inputbytesperpixel);
        }
        R_Upload(glt, data);
+       */
+       // if it has not been uploaded yet, update the data that will be used when it is
+       if (glt->inputtexels)
+               memcpy(glt->inputtexels, data, glt->width * glt->height * glt->textype->inputbytesperpixel);
+       else
+               R_Upload(glt, data);
 }
 
diff --git a/host.c b/host.c
index 7dbd632..d4a0d4d 100644 (file)
--- a/host.c
+++ b/host.c
@@ -44,9 +44,7 @@ double                realtime;                               // without any filtering or bounding
 double         oldrealtime;                    // last frame run
 int                    host_framecount;
 
-double         sv_frametime;
-
-int                    minimum_memory;
+int                    forcedeveloper;                 // used for -developer commandline parameter, hacky hacky
 
 client_t       *host_client;                   // current client
 
@@ -248,6 +246,8 @@ void Host_InitLocal (void)
        Cvar_RegisterVariable (&noexit);
        Cvar_RegisterVariable (&skill);
        Cvar_RegisterVariable (&developer);
+       if (forcedeveloper) // make it real now that the cvar is registered
+               Cvar_SetValue("developer", 1);
        Cvar_RegisterVariable (&deathmatch);
        Cvar_RegisterVariable (&coop);
 
@@ -783,6 +783,13 @@ void Host_Init (void)
 {
        com_argc = host_parms.argc;
        com_argv = host_parms.argv;
+       // FIXME: this is evil, but possibly temporary
+       if (COM_CheckParm("-developer"))
+       {
+               forcedeveloper = true;
+               developer.integer = 1;
+               developer.value = 1;
+       }
 
        Memory_Init ();
        Cmd_Init ();
index cd5b852..226b1f1 100644 (file)
@@ -78,7 +78,7 @@ void Host_Status_f (void)
                print = SV_ClientPrintf;
 
        print ("host:    %s\n", Cvar_VariableString ("hostname"));
-       print ("version: %s build %i\n", gamename, buildnumber);
+       print ("version: %s build %s\n", gamename, buildstring);
        if (tcpipAvailable)
                print ("tcp/ip:  %s\n", my_tcpip_address);
        if (ipxAvailable)
@@ -714,8 +714,7 @@ void Host_Name_f (void)
        
 void Host_Version_f (void)
 {
-       Con_Printf ("Version: %s build %i\n", gamename, buildnumber);
-       Con_Printf ("Exe: "__TIME__" "__DATE__"\n");
+       Con_Printf ("Version: %s build %s\n", gamename, buildstring);
 }
 
 void Host_Say(qboolean teamonly)
index a49a543..92b73af 100644 (file)
--- a/makefile
+++ b/makefile
@@ -9,7 +9,7 @@ SOUNDLIB=-lasound
 #SND=snd_oss.o
 #SOUNDLIB=
 
-OBJECTS= buildnumber.o cd_linux.o chase.o cl_demo.o cl_input.o cl_main.o cl_parse.o cl_tent.o cmd.o common.o console.o crc.o cvar.o fractalnoise.o gl_draw.o r_sky.o gl_rmain.o gl_rsurf.o gl_screen.o host.o host_cmd.o image.o keys.o mathlib.o menu.o model_alias.o model_brush.o model_shared.o model_sprite.o net_bsd.o net_udp.o net_dgrm.o net_loop.o net_main.o pr_cmds.o pr_edict.o pr_exec.o r_light.o r_particles.o r_explosion.o sbar.o snd_dma.o snd_mem.o snd_mix.o $(SND) sv_main.o sv_move.o sv_phys.o sv_user.o sv_light.o sys_linux.o transform.o view.o wad.o world.o zone.o vid_shared.o palette.o r_crosshairs.o gl_textures.o gl_models.o r_sprites.o r_modules.o r_explosion.o r_lerpanim.o r_decals.o protocol.o quakeio.o r_clip.o ui.o portals.o sys_shared.o cl_light.o gl_backend.o cl_particles.o cl_decals.o cl_screen.o
+OBJECTS= builddate.o cd_linux.o chase.o cl_demo.o cl_input.o cl_main.o cl_parse.o cl_tent.o cmd.o common.o console.o crc.o cvar.o fractalnoise.o gl_draw.o r_sky.o gl_rmain.o gl_rsurf.o gl_screen.o host.o host_cmd.o image.o keys.o mathlib.o menu.o model_alias.o model_brush.o model_shared.o model_sprite.o net_bsd.o net_udp.o net_dgrm.o net_loop.o net_main.o pr_cmds.o pr_edict.o pr_exec.o r_light.o r_particles.o r_explosion.o sbar.o snd_dma.o snd_mem.o snd_mix.o $(SND) sv_main.o sv_move.o sv_phys.o sv_user.o sv_light.o sys_linux.o transform.o view.o wad.o world.o zone.o vid_shared.o palette.o r_crosshairs.o gl_textures.o gl_models.o r_sprites.o r_modules.o r_explosion.o r_lerpanim.o r_decals.o protocol.o quakeio.o r_clip.o ui.o portals.o sys_shared.o cl_light.o gl_backend.o cl_particles.o cl_decals.o cl_screen.o cgamevm.o cgame.o
 
 #K6/athlon optimizations
 CPUOPTIMIZATIONS=-march=k6
@@ -17,32 +17,34 @@ CPUOPTIMIZATIONS=-march=k6
 #CPUOPTIMIZATIONS=-march=i686
 
 #use this line for profiling
-PROFILEOPTION=-pg -g
-NOPROFILEOPTIMIZATIONS=
+#PROFILEOPTION=-pg -g
+#NOPROFILEOPTIMIZATIONS=
 #use this line for no profiling
 #PROFILEOPTION=
 #NOPROFILEOPTIMIZATIONS=-fomit-frame-pointer
+#use these lines for debugging without profiling
+PROFILEOPTION=
+NOPROFILEOPTIMIZATIONS=
 
 #note:
 #the -Werror can be removed to compile even if there are warnings,
 #this is used to ensure that all released versions are free of warnings.
 
 #normal compile
-OPTIMIZATIONS= -O6 -ffast-math -funroll-loops $(NOPROFILEOPTIMIZATIONS) -fexpensive-optimizations $(CPUOPTIMIZATIONS)
-CFLAGS= -MD -Wall -Werror -I/usr/X11R6/include -I/usr/include/glide $(OPTIMIZATIONS) $(PROFILEOPTION)
+#OPTIMIZATIONS= -O6 -ffast-math -funroll-loops $(NOPROFILEOPTIMIZATIONS) -fexpensive-optimizations $(CPUOPTIMIZATIONS)
+#CFLAGS= -MD -Wall -Werror -I/usr/X11R6/include -I/usr/include/glide $(OPTIMIZATIONS) $(PROFILEOPTION)
 #debug compile
-#OPTIMIZATIONS= -O -g
-#CFLAGS= -MD -Wall -Werror -I/usr/X11R6/include -ggdb $(OPTIMIZATIONS) $(PROFILEOPTION)
+OPTIMIZATIONS=
+CFLAGS= -MD -Wall -Werror -I/usr/X11R6/include -ggdb $(OPTIMIZATIONS) $(PROFILEOPTION)
 
 LDFLAGS= -L/usr/X11R6/lib -lm -lX11 -lXext -lXIE -lXxf86dga -lXxf86vm -lGL -ldl $(SOUNDLIB) $(PROFILEOPTION)
 
-#most people can't build the -3dfx version (-3dfx version needs some updates for new mesa)
-all: buildnum darkplaces-glx
-#all: darkplaces-glx darkplaces-3dfx
+#if you don't need the -3dfx version, use this line
+all: builddate darkplaces-glx
+#all: builddate darkplaces-glx darkplaces-3dfx
 
-buildnum:
-       make -C buildnum
-       buildnum/buildnum buildnumber.c
+builddate:
+       touch builddate.c
 
 .c.o:
        gcc $(CFLAGS) -c $*.c
@@ -55,10 +57,8 @@ darkplaces-3dfx: $(OBJECTS) in_svgalib.o vid_3dfxsvga.o
 
 
 clean:
-       -make -C buildnum clean
-       -rm -f darkplaces-glx darkplaces-3dfx
-       -rm -f vid_glx.o in_svgalib.o vid_3dfxsvga.o $(OBJECTS) *.d
+       -rm -f darkplaces-glx darkplaces-3dfx vid_glx.o in_svgalib.o vid_3dfxsvga.o $(OBJECTS) *.d
 
-.PHONY: clean buildnum
+.PHONY: clean builddate
 
 -include *.d
index ab50923..8f73d5e 100644 (file)
--- a/mathlib.c
+++ b/mathlib.c
@@ -8,7 +8,7 @@ of the License, or (at your option) any later version.
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
 See the GNU General Public License for more details.
 
@@ -25,7 +25,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 void Sys_Error (char *error, ...);
 
 vec3_t vec3_origin = {0,0,0};
-int nanmask = 255<<23;
 float ixtable[4096];
 
 /*-----------------------------------------------------------------*/
@@ -58,7 +57,7 @@ float m_bytenormals[NUMVERTEXNORMALS][3] =
 {0.864188, 0.442863, 0.238856}, {0.688191, 0.587785, 0.425325}, 
 {0.809017, 0.309017, 0.500000}, {0.681718, 0.147621, 0.716567}, 
 {0.587785, 0.425325, 0.688191}, {0.955423, 0.295242, 0.000000}, 
-{1.000000, 0.000000, 0.000000}, {0.951056, 0.162460, 0.262866}, 
+{1.000000, 0.000000, 0.000000}, {0.951056, 0.162460, 0.262866},
 {0.850651, -0.525731, 0.000000}, {0.955423, -0.295242, 0.000000}, 
 {0.864188, -0.442863, 0.238856}, {0.951056, -0.162460, 0.262866}, 
 {0.809017, -0.309017, 0.500000}, {0.681718, -0.147621, 0.716567},
@@ -90,7 +89,7 @@ float m_bytenormals[NUMVERTEXNORMALS][3] =
 {0.500000, -0.809017, 0.309017}, {0.716567, -0.681718, 0.147621}, 
 {0.525731, -0.850651, 0.000000}, {-0.238856, -0.864188, -0.442863}, 
 {-0.500000, -0.809017, -0.309017}, {-0.262866, -0.951056, -0.162460}, 
-{-0.850651, -0.525731, 0.000000}, {-0.716567, -0.681718, -0.147621}, 
+{-0.850651, -0.525731, 0.000000}, {-0.716567, -0.681718, -0.147621},
 {-0.716567, -0.681718, 0.147621}, {-0.525731, -0.850651, 0.000000}, 
 {-0.500000, -0.809017, 0.309017}, {-0.238856, -0.864188, 0.442863},
 {-0.262866, -0.951056, 0.162460}, {-0.864188, -0.442863, 0.238856}, 
@@ -283,11 +282,6 @@ void PerpendicularVector( vec3_t dst, const vec3_t src )
 }
 
 
-#ifdef _WIN32
-#pragma optimize( "", off )
-#endif
-
-
 // LordHavoc: like AngleVectors, but taking a forward vector instead of angles, useful!
 void VectorVectors(const vec3_t forward, vec3_t right, vec3_t up)
 {
@@ -499,10 +493,6 @@ void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point,
 #endif
 }
 
-#ifdef _WIN32
-#pragma optimize( "", on )
-#endif
-
 /*-----------------------------------------------------------------*/
 
 
index f04b67a..d3e3753 100644 (file)
--- a/mathlib.h
+++ b/mathlib.h
@@ -34,7 +34,7 @@ typedef vec_t vec8_t[8];
 struct mplane_s;
 extern vec3_t vec3_origin;
 
-extern int nanmask;
+#define nanmask (255<<23)
 #define        IS_NAN(x) (((*(int *)&x)&nanmask)==nanmask)
 
 #define bound(min,num,max) (num >= min ? (num < max ? num : max) : min)
@@ -51,7 +51,7 @@ extern int nanmask;
 #define ANGLEMOD(a) (((int) ((a) * (65536.0f / 360.0f)) & 65535) * (360.0f / 65536.0f))
 
 #define VectorNegate(a,b) ((b)[0]=-((a)[0]),(b)[1]=-((a)[1]),(b)[2]=-((a)[2]))
-#define VectorSet(a,b,c,d) ((d)[0]=(a),(d)[1]=(b),(d)[2]=(c))
+#define VectorSet(a,b,c,d) ((a)[0]=(b),(a)[1]=(c),(a)[2]=(d))
 #define VectorClear(a) ((a)[0]=(a)[1]=(a)[2]=0)
 #define DotProduct(a,b) ((a)[0]*(b)[0]+(a)[1]*(b)[1]+(a)[2]*(b)[2])
 #define VectorSubtract(a,b,c) ((c)[0]=(a)[0]-(b)[0],(c)[1]=(a)[1]-(b)[1],(c)[2]=(a)[2]-(b)[2])
diff --git a/menu.c b/menu.c
index f1fc133..0f42d57 100644 (file)
--- a/menu.c
+++ b/menu.c
@@ -673,6 +673,8 @@ void M_SinglePlayer_Key (int key)
                        if (sv.active)
                                Cbuf_AddText ("disconnect\n");
                        Cbuf_AddText ("maxplayers 1\n");
+                       Cbuf_AddText ("deathmatch 0\n");
+                       Cbuf_AddText ("coop 0\n");
                        if (gamemode == GAME_NEHAHRA)
                                Cbuf_AddText ("map nehstart\n");
                        else
index 793299d..5c09eeb 100644 (file)
@@ -216,18 +216,18 @@ static rtexture_t *GL_SkinSplit(byte *in, byte *out, int width, int height, int
                return NULL;
 }
 
-static void Mod_LoadSkin (char *basename, byte *skindata, byte *skintemp, int width, int height, skinframe_t *skinframe)
+static void Mod_LoadSkin (char *basename, byte *skindata, byte *skintemp, int width, int height, skinframe_t *skinframe, int precache)
 {
-       skinframe->base   = loadtextureimagewithmask(loadmodel->texturepool, va("%s_normal", basename), 0, 0, false, r_mipskins.integer, true);
+       skinframe->base   = loadtextureimagewithmask(loadmodel->texturepool, va("%s_normal", basename), 0, 0, false, r_mipskins.integer, precache);
        skinframe->fog    = image_masktex;
        skinframe->pants  = NULL;
        skinframe->shirt  = NULL;
-       skinframe->glow   = loadtextureimage(loadmodel->texturepool, va("%s_glow"  , basename), 0, 0, false, r_mipskins.integer, true);
+       skinframe->glow   = loadtextureimage(loadmodel->texturepool, va("%s_glow"  , basename), 0, 0, false, r_mipskins.integer, precache);
        skinframe->merged = NULL;
        if (skinframe->base)
        {
-               skinframe->pants  = loadtextureimage(loadmodel->texturepool, va("%s_pants" , basename), 0, 0, false, r_mipskins.integer, true);
-               skinframe->shirt  = loadtextureimage(loadmodel->texturepool, va("%s_shirt" , basename), 0, 0, false, r_mipskins.integer, true);
+               skinframe->pants  = loadtextureimage(loadmodel->texturepool, va("%s_pants" , basename), 0, 0, false, r_mipskins.integer, precache);
+               skinframe->shirt  = loadtextureimage(loadmodel->texturepool, va("%s_shirt" , basename), 0, 0, false, r_mipskins.integer, precache);
        }
        else
        {
@@ -237,14 +237,14 @@ static void Mod_LoadSkin (char *basename, byte *skindata, byte *skintemp, int wi
                {
                        skinframe->pants  = GL_SkinSplitShirt(skindata, skintemp, width, height, 0x0040, va("%s_pants", basename), false); // pants
                        skinframe->shirt  = GL_SkinSplitShirt(skindata, skintemp, width, height, 0x0002, va("%s_shirt", basename), false); // shirt
-                       skinframe->glow   = GL_SkinSplit     (skindata, skintemp, width, height, 0xC000, va("%s_glow", basename), true); // glow
+                       skinframe->glow   = GL_SkinSplit     (skindata, skintemp, width, height, 0xC000, va("%s_glow", basename), precache); // glow
                        if (skinframe->pants || skinframe->shirt)
                        {
                                skinframe->base   = GL_SkinSplit (skindata, skintemp, width, height, 0x3FBD, va("%s_normal", basename), false); // normal (no special colors)
-                               skinframe->merged = GL_SkinSplit (skindata, skintemp, width, height, 0x3FFF, va("%s_body", basename), true); // body (normal + pants + shirt, but not glow)
+                               skinframe->merged = GL_SkinSplit (skindata, skintemp, width, height, 0x3FFF, va("%s_body", basename), precache); // body (normal + pants + shirt, but not glow)
                        }
                        else
-                               skinframe->base   = GL_SkinSplit (skindata, skintemp, width, height, 0x3FFF, va("%s_base", basename), true); // no special colors
+                               skinframe->base   = GL_SkinSplit (skindata, skintemp, width, height, 0x3FFF, va("%s_base", basename), precache); // no special colors
                        // quake model skins don't have alpha
                        skinframe->fog = NULL;
                }
@@ -401,7 +401,7 @@ void Mod_LoadAliasModel (model_t *mod, void *buffer)
                                sprintf (name, "%s_%i_%i", loadmodel->name, i, j);
                        else
                                sprintf (name, "%s_%i", loadmodel->name, i);
-                       Mod_LoadSkin(name, (byte *)datapointer, skintemp, skinwidth, skinheight, loadmodel->skinframes + totalskins);
+                       Mod_LoadSkin(name, (byte *)datapointer, skintemp, skinwidth, skinheight, loadmodel->skinframes + totalskins, i == 0);
                        datapointer += skinwidth * skinheight;
                        totalskins++;
                }
index eecc655..ca010f0 100644 (file)
@@ -1064,12 +1064,12 @@ void Mod_GenerateLightmappedMesh (msurface_t *surf)
        if (r_miplightmaps.integer)
        {
                surf->lightmaptexturestride = (surf->extents[0]>>4)+1;
-               surf->lightmaptexture = R_ProceduralTexture(loadmodel->texturepool, NULL, surf->lightmaptexturestride, (surf->extents[1]>>4)+1, loadmodel->lightmaprgba ? TEXTYPE_RGBA : TEXTYPE_RGB, TEXF_MIPMAP/* | TEXF_PRECACHE*/, NULL, NULL, 0);
+               surf->lightmaptexture = R_ProceduralTexture(loadmodel->texturepool, NULL, surf->lightmaptexturestride, (surf->extents[1]>>4)+1, loadmodel->lightmaprgba ? TEXTYPE_RGBA : TEXTYPE_RGB, TEXF_MIPMAP | TEXF_PRECACHE, NULL, NULL, 0);
        }
        else
        {
                surf->lightmaptexturestride = R_CompatibleFragmentWidth((surf->extents[0]>>4)+1, loadmodel->lightmaprgba ? TEXTYPE_RGBA : TEXTYPE_RGB, 0);
-               surf->lightmaptexture = R_ProceduralTexture(loadmodel->texturepool, NULL, surf->lightmaptexturestride, (surf->extents[1]>>4)+1, loadmodel->lightmaprgba ? TEXTYPE_RGBA : TEXTYPE_RGB, TEXF_FRAGMENT/* | TEXF_PRECACHE*/, NULL, NULL, 0);
+               surf->lightmaptexture = R_ProceduralTexture(loadmodel->texturepool, NULL, surf->lightmaptexturestride, (surf->extents[1]>>4)+1, loadmodel->lightmaprgba ? TEXTYPE_RGBA : TEXTYPE_RGB, TEXF_FRAGMENT | TEXF_PRECACHE, NULL, NULL, 0);
        }
 //     surf->lightmaptexture = R_LoadTexture(loadmodel->texturepool, va("lightmap%08x", lightmapnum), surf->lightmaptexturestride, (surf->extents[1]>>4)+1, NULL, loadmodel->lightmaprgba ? TEXTYPE_RGBA : TEXTYPE_RGB, TEXF_FRAGMENT | TEXF_PRECACHE);
 //     surf->lightmaptexture = R_LoadTexture(loadmodel->texturepool, va("lightmap%08x", lightmapnum), surf->lightmaptexturestride, (surf->extents[1]>>4)+1, NULL, loadmodel->lightmaprgba ? TEXTYPE_RGBA : TEXTYPE_RGB, TEXF_PRECACHE);
@@ -1182,8 +1182,7 @@ static void Mod_LoadFaces (lump_t *l)
 {
        dface_t         *in;
        msurface_t      *out;
-       int                     i, count, surfnum;
-       int                     planenum, side;
+       int                     i, count, surfnum, planenum, side, ssize, tsize;
 
        in = (void *)(mod_base + l->fileofs);
        if (l->filelen % sizeof(*in))
@@ -1220,6 +1219,9 @@ static void Mod_LoadFaces (lump_t *l)
 
                CalcSurfaceExtents (out);
 
+               ssize = (out->extents[0] >> 4) + 1;
+               tsize = (out->extents[1] >> 4) + 1;
+
                // lighting info
                for (i = 0;i < MAXLIGHTMAPS;i++)
                        out->styles[i] = in->styles[i];
@@ -1272,15 +1274,22 @@ static void Mod_LoadFaces (lump_t *l)
                        out->samples = NULL;
                        Mod_GenerateVertexMesh(out);
                }
-               else if (out->extents[0] < r_vertexsurfacesthreshold.integer && out->extents[1] < r_vertexsurfacesthreshold.integer)
-               {
-                       out->shader = &Cshader_wall_vertex;
-                       Mod_GenerateVertexLitMesh(out);
-               }
                else
                {
-                       out->shader = &Cshader_wall_lightmap;
-                       Mod_GenerateLightmappedMesh(out);
+                       // stainmap for permanent marks on walls
+                       out->stainsamples = Mem_Alloc(loadmodel->mempool, ssize * tsize * 3);
+                       // clear to white
+                       memset(out->stainsamples, 255, ssize * tsize * 3);
+                       if (out->extents[0] < r_vertexsurfacesthreshold.integer && out->extents[1] < r_vertexsurfacesthreshold.integer)
+                       {
+                               out->shader = &Cshader_wall_vertex;
+                               Mod_GenerateVertexLitMesh(out);
+                       }
+                       else
+                       {
+                               out->shader = &Cshader_wall_lightmap;
+                               Mod_GenerateLightmappedMesh(out);
+                       }
                }
        }
 }
@@ -1991,8 +2000,8 @@ static void Mod_FinalizePortals(void)
        endleaf = leaf + loadmodel->numleafs;
        for (;leaf < endleaf;leaf++)
        {
-               VectorSet( 2000000000,  2000000000,  2000000000, leaf->mins);
-               VectorSet(-2000000000, -2000000000, -2000000000, leaf->maxs);
+               VectorSet(leaf->mins,  2000000000,  2000000000,  2000000000);
+               VectorSet(leaf->maxs, -2000000000, -2000000000, -2000000000);
        }
        p = portalchain;
        while(p)
index fc79e4c..21c6a7e 100644 (file)
@@ -144,6 +144,8 @@ typedef struct msurface_s
        byte            styles[MAXLIGHTMAPS];
        // RGB lighting data [numstyles][height][width][3]
        byte            *samples;
+       // stain to apply on lightmap (soot/dirt/blood/whatever)
+       byte            *stainsamples;
 
        // these fields are generated during model loading
        // the lightmap texture fragment to use on the surface
index 38364cc..9bafca0 100644 (file)
--- a/pr_cmds.c
+++ b/pr_cmds.c
@@ -254,7 +254,7 @@ void SetMinMaxSize (edict_t *e, float *min, float *max, qboolean rotate)
                angles = e->v.angles;
                
                a = angles[1]/180 * M_PI;
-               
+
                xvector[0] = cos(a);
                xvector[1] = sin(a);
                yvector[0] = -sin(a);
@@ -1342,7 +1342,7 @@ void PF_precache_model (void)
        
        if (sv.state != ss_loading)
                PR_RunError ("PF_Precache_*: Precache can only be done in spawn functions");
-               
+
        s = G_STRING(OFS_PARM0);
        if (sv.worldmodel->ishlbsp && ((!s) || (!s[0])))
                return;
@@ -2538,6 +2538,15 @@ void PF_te_beam (void)
        MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
 }
 
+void PF_te_plasmaburn (void)
+{
+       MSG_WriteByte(&sv.datagram, svc_temp_entity);
+       MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
+}
+
 void PF_Fixme (void)
 {
        PR_RunError ("unimplemented builtin"); // LordHavoc: was misspelled (bulitin)
@@ -2636,7 +2645,7 @@ PF_precache_file,
 PF_setspawnparms,
 
 PF_Fixme,                              // #79 LordHavoc: dunno who owns 79-89, so these are just padding
-PF_Fixme,                              // #80 
+PF_Fixme,                              // #80
 PF_Fixme,                              // #81
 PF_Fixme,                              // #82
 PF_Fixme,                              // #83
@@ -2695,6 +2704,7 @@ PF_te_lightning2,         // #429
 PF_te_lightning3,              // #430
 PF_te_beam,                            // #431
 PF_vectorvectors,              // #432
+PF_te_plasmaburn,              // #433
 };
 
 builtin_t *pr_builtins = pr_builtin;
index 639221e..d3b25a8 100644 (file)
@@ -202,8 +202,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #define        svc_hidelmp                     36              // [string] slotname
 #define        svc_skybox                      37              // [string] skyname
 
-#define svc_unusedlh1
-#define svc_fog                                51              // unfinished
+#define svc_cgame                      50              // [short] length [bytes] data
+#define svc_fog                                51              // unfinished and obsolete
 #define svc_effect                     52              // [vector] org [byte] modelindex [byte] startframe [byte] framecount [byte] framerate
 #define svc_effect2                    53              // [vector] org [short] modelindex [short] startframe [byte] framecount [byte] framerate
 #define        svc_sound2                      54              // short soundindex instead of byte
@@ -265,6 +265,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #define TE_SMALLFLASH          72 // [vector] origin
 #define TE_CUSTOMFLASH         73 // [vector] origin [byte] radius / 8 - 1 [byte] lifetime / 256 - 1 [byte] red [byte] green [byte] blue
 #define TE_FLAMEJET                    74 // [vector] origin [vector] velocity [byte] count
+#define TE_PLASMABURN          75 // [vector] origin
 
 #define RENDER_STEP 1
 #define RENDER_GLOWTRAIL 2
index 8b1cec0..85760ab 100644 (file)
@@ -21,7 +21,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 #define QUAKE_GAME // as opposed to utilities
 
-extern int buildnumber;
+extern char *buildstring;
 
 #if !defined BYTE_DEFINED
 typedef unsigned char          byte;
@@ -294,6 +294,7 @@ void Chase_Reset (void);
 void Chase_Update (void);
 
 void fractalnoise(unsigned char *noise, int size, int startgrid);
+void fractalnoisequick(byte *noise, int size, int startgrid);
 
 #include "palette.h"
 #include "image.h"
index d7504a2..6922bb6 100644 (file)
@@ -170,7 +170,7 @@ void R_NewExplosion(vec3_t org)
        int i, j;
        float dist;
        byte noise[EXPLOSIONGRID*EXPLOSIONGRID];
-       fractalnoise(noise, EXPLOSIONGRID, 4);
+       fractalnoisequick(noise, EXPLOSIONGRID, 4);
        for (i = 0;i < MAX_EXPLOSIONS;i++)
        {
                if (explosion[i].alpha <= 0.0f)
@@ -207,7 +207,7 @@ void R_NewExplosion(vec3_t org)
                }
                VectorRandom(v);
                VectorMA(org, EXPLOSIONGASSTARTRADIUS, v, v);
-               TraceLine(org, v, explosiongas[i].origin, NULL, 0);
+               TraceLine(org, v, explosiongas[i].origin, NULL, 0, true);
                VectorRandom(v);
                VectorScale(v, EXPLOSIONGASSTARTVELOCITY, explosiongas[i].velocity);
                explosiongas[i].pressure = j * GASDENSITY_SCALER;
@@ -351,7 +351,7 @@ void R_MoveExplosion(explosion_t *e/*, explosiongas_t **list, explosiongas_t **l
                        VectorMA(e->vert[i], frametime, e->vertvel[i], end);
                        if (r_explosionclip.integer)
                        {
-                               if (TraceLine(e->vert[i], end, impact, normal, 0) < 1)
+                               if (TraceLine(e->vert[i], end, impact, normal, 0, true) < 1)
                                {
                                        // clip velocity against the wall
                                        dot = DotProduct(e->vertvel[i], normal) * -1.125f;
@@ -397,7 +397,7 @@ void R_MoveExplosionGas(explosiongas_t *e, explosiongas_t **list, explosiongas_t
                {
                        float f, dot;
                        vec3_t impact, normal;
-                       f = TraceLine(e->origin, end, impact, normal, 0);
+                       f = TraceLine(e->origin, end, impact, normal, 0, true);
                        VectorCopy(impact, e->origin);
                        if (f < 1)
                        {
index 9ec152a..26d1de2 100644 (file)
--- a/r_light.c
+++ b/r_light.c
@@ -180,7 +180,7 @@ void R_DrawCoronas(void)
                {
                        // trace to a point just barely closer to the eye
                        VectorSubtract(rd->origin, vpn, diff);
-                       if (TraceLine(r_origin, diff, NULL, NULL, 0) == 1)
+                       if (TraceLine(r_origin, diff, NULL, NULL, 0, true) == 1)
                        {
                                scale = 1.0f / 65536.0f;//64.0f / (dist * dist + 1024.0f);
                                m.cr = rd->light[0] * scale;
@@ -269,7 +269,7 @@ loc0:
        }
 
 // mark the polygons
-       surf = cl.worldmodel->surfaces + node->firstsurface;
+       surf = currentrenderentity->model->surfaces + node->firstsurface;
        for (i=0 ; i<node->numsurfaces ; i++, surf++)
        {
                int d, impacts, impactt;
index febe3ca..ea393f0 100644 (file)
--- a/render.h
+++ b/render.h
@@ -192,3 +192,6 @@ extern particletexture_t particletexture[MAX_PARTICLETEXTURES][2];
 void R_TimeReport(char *name);
 void R_TimeReport_Start(void);
 void R_TimeReport_End(void);
+
+// r_stain
+void R_Stain (vec3_t origin, float radius, int cr1, int cg1, int cb1, int ca1, int cr2, int cg2, int cb2, int ca2);
index ddf57d3..07eafd2 100644 (file)
--- a/sv_main.c
+++ b/sv_main.c
@@ -237,7 +237,7 @@ void SV_SendServerinfo (client_t *client)
        char                    message[2048];
 
        MSG_WriteByte (&client->message, svc_print);
-       sprintf (message, "\002\nServer: %s build %i (progs %i crc)", gamename, buildnumber, pr_crc);
+       sprintf (message, "\002\nServer: %s build %s (progs %i crc)", gamename, buildstring, pr_crc);
        MSG_WriteString (&client->message,message);
 
        MSG_WriteByte (&client->message, svc_serverinfo);
index c4c539d..e7b4a81 100644 (file)
@@ -112,11 +112,11 @@ char engineversion[40];
 void Sys_Shared_EarlyInit(void)
 {
 #if defined(__linux__)
-       sprintf (engineversion, "%s Linux GL build %3i", gamename, buildnumber);
+       sprintf (engineversion, "%s Linux GL build %s", gamename, buildstring);
 #elif defined(WIN32)
-       sprintf (engineversion, "%s Windows GL build %3i", gamename, buildnumber);
+       sprintf (engineversion, "%s Windows GL build %s", gamename, buildstring);
 #else
-       sprintf (engineversion, "%s Unknown GL build %3i", gamename, buildnumber);
+       sprintf (engineversion, "%s Unknown GL build %s", gamename, buildstring);
 #endif
 
        if (COM_CheckParm("-nostdout"))
index 3735592..035e701 100644 (file)
--- a/vid_glx.c
+++ b/vid_glx.c
@@ -636,7 +636,6 @@ void VID_Init(void)
        qboolean fullscreen = true;
        int MajorVersion, MinorVersion;
 
-       Cvar_RegisterVariable (&vid_mouse);
        Cvar_RegisterVariable (&vid_dga);
        Cvar_RegisterVariable (&vid_dga_mouseaccel);
        Cvar_RegisterVariable (&m_filter);
diff --git a/view.c b/view.c
index e9ea505..0dd0676 100644 (file)
--- a/view.c
+++ b/view.c
@@ -489,6 +489,9 @@ void V_CalcRefdef (void)
        float           bob;
        float           side;
 
+       if (cls.state != ca_connected || !cl.worldmodel)
+               return;
+
        // ent is the player model (visible when out of body)
        ent = &cl_entities[cl.viewentity];
        // view is the weapon model (only visible from inside body)
diff --git a/zone.c b/zone.c
index 92f04a0..dd8074c 100644 (file)
--- a/zone.c
+++ b/zone.c
@@ -32,6 +32,7 @@ void *_Mem_Alloc(mempool_t *pool, int size, char *filename, int fileline)
                return NULL;
        if (pool == NULL)
                Sys_Error("Mem_Alloc: pool == NULL (alloc at %s:%i)", filename, fileline);
+       Con_DPrintf("Mem_Alloc: pool %s, file %s:%i, size %i bytes\n", pool->name, filename, fileline, size);
        pool->totalsize += size;
        if (size < 4096)
        {
@@ -124,6 +125,7 @@ void _Mem_Free(void *data, char *filename, int fileline)
        if (*((int *)((long) mem + sizeof(memheader_t) + mem->size)) != MEMHEADER_SENTINEL)
                Sys_Error("Mem_Free: trashed header sentinel 2 (alloc at %s:%i, free at %s:%i)", mem->filename, mem->fileline, filename, fileline);
        pool = mem->pool;
+       Con_DPrintf("Mem_Free: pool %s, alloc %s:%i, free %s:%i, size %i bytes\n", pool->name, mem->filename, mem->fileline, filename, fileline, mem->size);
        for (memchainpointer = &pool->chain;*memchainpointer;memchainpointer = &(*memchainpointer)->chain)
        {
                if (*memchainpointer == mem)