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 1b6e78ed2bb57337b5d653ed31938fcc49d33597..e383ab61656b65b3a9146fcd00f5702fd14234a9 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 5bea3dec6ae0bbbd40b6834a69dd65828ee0e42c..54f53a9baa51007e2a75020b524290eb50364acc 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 4c1cad58a96e0455001bf5abf5216bd80fd7b6b2..f78a191979b5293db3ef52a394e7a5c7cbe27a18 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 d8d7702c20ef7f17b3d1293eed5b448092fec738..82f7f90b3370a112ebd655a058d6dc1160c65043 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 ce100de35fca33cb7f6ca43ff5a951ec97673ac4..61a66e17e14c1fe07e6af09aced49e903e7e0a43 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 42f342b011d25ecdf87f96d0dcf35b2130fd9313..387a64cb8f9ce7e0e08c52a4266775e92ef6e8ee 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 c0db0554e373213dd7a5d3f29a64daa453f6711c..e7ce7b15622de67e90986235518dc02fab9c8b38 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 293155d62de244a1eb3ffefcd2fc500b2cabc065..a9da1b0d38fa0fe3c5cbeb024e4d03d0fdcf52af 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 27112675c830b572a56a29fac0749925330a2000..404d73ef52276edd29e04d72f55de03f0c3cbbe6 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 e99181e93e3f826ce27a8018852223efca509667..c5332a9931c76cdbf7cd371eed190e021ea93bf7 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 bee89d929f1aeaf6b7992ed7ac190cbbd846d9f1..25ad1421f93ea6526602fec2aa57f14b50d398dd 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 31b140d518972459b866a85687df6722d056efa3..ad9d91ed4a0ab1b0a4bf7a396483c3047f8bc987 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 21eafef82983246423b9158eeeea7172ca4c7525..cf86ac63f6fb6a135f8996314f9ee45ff2b08dcd 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 2b777f24b2dc3662b6b5eeb51011e5e2542fb968..d1d45ab6a8511fc3ea830d48361154555a1a26d9 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 52c0da5907456bc625e7672d5daddb5f9bf64ac4..03da518289523bb67f696147485b7fa810f31fea 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 7dbd63209d15c5ab299f708f15044f182bddac83..d4a0d4d10167c191f5dbae297a21f78f05841f4c 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 cd5b852182641cb56d5179a3ba6281f6686da657..226b1f13c60516348b1b288bfe3bf3f3158d5b8f 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 a49a543edcd28e40c4d8bc4f0f068ca9181cecda..92b73afa59d2355f3c3d944c2274fbf497e4af84 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 ab50923c26b6c4c1ba9169839cac44a4d35e90ae..8f73d5eab2476072ebb21ede62645bfab358a93d 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 f04b67a7a419b587a81a5690e3f210ecbaa8eae1..d3e3753f6de4c28e4ffe3831519bc6a8621228b1 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 f1fc133170be41677517adac7682189203932615..0f42d5776dfe926d9fb0e9b2644a66aeb7f2c4c7 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 793299d8a5616a3821c8469cc85885bead2e6513..5c09eeb4413ab17cf9f5551756abf39f7f61fee8 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 eecc655e3d80346657d852859aa51034ce10a36c..ca010f055da445d62c8ff9e5bb8d792b82c24053 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 fc79e4c0c6b3bd0b5188549b09a431b2c8cf5f80..21c6a7ee7ef15929e4e98753887fc089c177dccb 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 38364ccbb321f2ace8bb6b9dd8458b0a66b99503..9bafca0bcda5346640ac9519b6fb944a00dccc91 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 639221ec84fd6787d7700d5beab2515b145f5b34..d3b25a8e9486c5d669253b8f799436dcc9273a6a 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 8b1cec02d0b8b9207db284b08e87b0b73ecd5fe8..85760abad582bb32b6c2029c71990b0c9bba651e 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 d7504a29edc76532ee6bed957cb3b3a3b54a306a..6922bb6e5c9b348c235507d76ac19319b5494f71 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 9ec152afa1975531dc0f2fb4a7cd89dbeb99bedc..26d1de22bfca8317f2ec7ab64a3e62c7e45f7c55 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 febe3caf728f3564852f076b96fd576eea3d75e7..ea393f0cbc1ab78afbc5945ef13613065c2693df 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 ddf57d3ee9059de44bd3381d0a4112fcb4f70e68..07eafd203c8b70c507878be5e6189b275eaf8427 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 c4c539d96f3b1f783130fc60eb7f3332713ad533..e7b4a810c86b3d35dcd652a9e82ae03393293d7c 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 3735592e734189133b9620dec6aa3838c879fb67..035e70141b507348c051e102aec917bb1e8962a4 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 e9ea505b6c7a5fc6e235139d94555158939245a4..0dd0676909fbdf4884b5ee1872049b3622e61531 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 92f04a0bcbdaaac582861289ae226939c5391808..dd8074c192b280023688f37ffd2884d5b4e93718 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)