--- /dev/null
+
+char *buildstring = __TIME__ " " __DATE__;
+++ /dev/null
-
-#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;
-}
-
+++ /dev/null
-all: buildnum
-
-.c.o:
- gcc -Wall -c $*.c
-
-buildnum: buildnum.o
- gcc -o $@ $^
-
-clean:
- -rm -f buildnum.o buildnum *.d
-
-.PHONY: clean
-
--include *.d
+++ /dev/null
-
-#define BUILDNUMBER 1060
-
-int buildnumber = BUILDNUMBER;
--- /dev/null
+/*
+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
--- /dev/null
+
+#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();
+}
+
--- /dev/null
+
+#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
--- /dev/null
+
+#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;
+}
--- /dev/null
+
+#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
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
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)
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;
{
softwaretransformforentity(decalent);
softwareuntransform(origin, decalorg);
- CL_RecursiveDecalSurface (decalmodel->nodes);
+ CL_RecursiveDecalSurface (decalmodel->nodes + decalmodel->hulls[0].firstclipnode);
}
}
}
ClearStateToDefault(&cl_entities[i].state_previous);
ClearStateToDefault(&cl_entities[i].state_current);
}
+
+ CL_CGVM_Clear();
}
void CL_LerpUpdate(entity_t *e)
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);
}
void CL_RelinkEntities (void)
{
- r_refdef.numentities = 0;
-
CL_LerpPlayerVelocity();
CL_RelinkNetworkEntities();
+ TraceLine_ScanForBModels();
CL_RelinkEffects();
CL_MoveParticles();
CL_UpdateDecals();
- CL_UpdateTEnts ();
+ CL_UpdateTEnts();
}
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
CL_Particles_Init();
CL_Decals_Init();
CL_Screen_Init();
+ CL_CGVM_Init();
}
Mem_CheckSentinelsGlobal();
+ CL_CGVM_Start();
+
+ Mem_CheckSentinelsGlobal();
+
noclip_anglehack = false; // noclip is turned off at start
}
#define SHOWNET(x) if(cl_shownet.integer==2)Con_Printf ("%3i:%s\n", msg_readcount-1, x);
+static byte cgamenetbuffer[65536];
+
/*
=====================
CL_ParseServerMessage
temp = "<unknown>";
cmdlogname[cmdindex] = temp;
}
-
+
// other commands
switch (cmd)
{
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)
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;
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;
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)
Host_Error ("svc_updatestat: %i is invalid", i);
cl.stats[i] = MSG_ReadLong ();
break;
-
+
case svc_spawnstaticsound:
CL_ParseStaticSound (false);
break;
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;
}
}
*/
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)
{
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);
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);
}
else
R_NewExplosion(org);
+ R_Stain(org, 96, 80, 80, 80, 128, 176, 176, 176, 128);
}
/*
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++)
{
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
{
// 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
{
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)
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;
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;
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);
p->scaley = 8;
break;
}
- */
+ #endif
+ break;
}
}
+ */
break;
/*
case pt_raindropsplash:
{
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);
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);
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);
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);
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
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);
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;
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);
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);
}
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);
// 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"
refdef_t r_refdef;
extern mempool_t *cl_refdef_mempool;
+
+#include "cgamevm.h"
}
+#if 1
+#define CMD_TOKENIZELENGTH 4096
+char cmd_tokenizebuffer[CMD_TOKENIZELENGTH];
+#endif
+
/*
============
Cmd_TokenizeString
*/
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;
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++;
}
*/
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;
}
int memsearch (byte *start, int count, int search)
{
int i;
-
+
for (i=0 ; i<count ; i++)
if (start[i] == search)
return i;
memset (con_text, ' ', CON_TEXTSIZE);
con_linewidth = -1;
Con_CheckResize ();
-
+
Con_Printf ("Console initialized.\n");
//
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
/*
}
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;
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()&litude);
+
+ 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
+}
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"};
static buf_texcoord_t *buf_transtexcoord[MAX_TEXTUREUNITS];
static mempool_t *gl_backend_mempool;
+static int resizingbuffers = false;
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)\
{\
static void gl_backend_shutdown(void)
{
- int i;
+ //int i;
/*
#define BACKENDFREE(var)\
if (var)\
var = NULL;\
}
*/
+ /*
#define BACKENDFREE(var) var = NULL;
BACKENDFREE(buf_mesh)
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;
if (!init)
{
+ resizingbuffers = true;
gl_backend_shutdown();
gl_backend_start();
+ resizingbuffers = false;
}
}
}
{
}
+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);
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;
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;
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
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
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;
*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
#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"};
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
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);
}
// 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);
}
texturebuffer = NULL;
gltexnuminuse = NULL;
Mem_FreePool(&texturemempool);
+ Mem_FreePool(&texturedatamempool);
+ Mem_FreePool(&textureprocessingmempool);
}
static void r_textures_newmap(void)
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
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);
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 (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);
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);
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);
}
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);
}
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);
}
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
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);
{
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 ();
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)
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)
#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
#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
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
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.
void Sys_Error (char *error, ...);
vec3_t vec3_origin = {0,0,0};
-int nanmask = 255<<23;
float ixtable[4096];
/*-----------------------------------------------------------------*/
{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},
{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},
}
-#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)
{
#endif
}
-#ifdef _WIN32
-#pragma optimize( "", on )
-#endif
-
/*-----------------------------------------------------------------*/
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)
#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])
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
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
{
{
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;
}
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++;
}
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);
{
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))
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];
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);
+ }
}
}
}
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)
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
angles = e->v.angles;
a = angles[1]/180 * M_PI;
-
+
xvector[0] = cos(a);
xvector[1] = sin(a);
yvector[0] = -sin(a);
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;
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)
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
PF_te_lightning3, // #430
PF_te_beam, // #431
PF_vectorvectors, // #432
+PF_te_plasmaburn, // #433
};
builtin_t *pr_builtins = pr_builtin;
#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
#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
#define QUAKE_GAME // as opposed to utilities
-extern int buildnumber;
+extern char *buildstring;
#if !defined BYTE_DEFINED
typedef unsigned char byte;
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"
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)
}
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;
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;
{
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)
{
{
// 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;
}
// 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;
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);
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);
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"))
qboolean fullscreen = true;
int MajorVersion, MinorVersion;
- Cvar_RegisterVariable (&vid_mouse);
Cvar_RegisterVariable (&vid_dga);
Cvar_RegisterVariable (&vid_dga_mouseaccel);
Cvar_RegisterVariable (&m_filter);
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)
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)
{
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)