X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=cgame.c;h=86da9a53d8074849f5d6ee6981eb276349164949;hp=a8715c414904c03a42d335f24c0fd92cdc1ab05d;hb=823d8a2d16635f92223b991cb36ae0104fb6d88e;hpb=ff5947f97081e10c4ce112d4d51c2d1fa14ebba8 diff --git a/cgame.c b/cgame.c index a8715c41..86da9a53 100644 --- a/cgame.c +++ b/cgame.c @@ -1,19 +1,13 @@ +#include #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; @@ -21,19 +15,22 @@ typedef struct localentity_s vec3_t worldmaxs; vec3_t entitymins; vec3_t entitymaxs; + vec3_t lastimpactorigin; // updated by physics code, used by gib blood stains 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); + void (*touchnetwork)(struct localentity_s *self); cgdrawentity_t draw; } localentity_t; #define MAX_LOCALENTITIES 1024 static localentity_t *localentity; +// true if the entity is alive (not freed) +static unsigned char *localentityactive; +// time the entity was freed +static float *localentityfreetime; static cgphysentity_t *phys_entity; static int phys_entities; @@ -49,35 +46,38 @@ static void readvector(vec3_t v) static localentity_t *entspawn(void) { - int i; - localentity_t *l; + int i, best; + float bestfreetime; + bestfreetime = (float) (gametime + 100.0); + best = -1; for (i = 0;i < MAX_LOCALENTITIES;i++) { - l = localentity + i; - if (!l->active && l->freetime < gametime) + if (!localentityactive[i] && bestfreetime > localentityfreetime[i]) { - memset(l, 0, sizeof(*l)); - l->active = true; - return l; + bestfreetime = localentityfreetime[i]; + best = i; + if (bestfreetime < gametime) + break; } } - for (i = 0;i < MAX_LOCALENTITIES;i++) + if (best >= 0) { - l = localentity + i; - if (!l->active) - { - memset(l, 0, sizeof(*l)); - l->active = true; - return l; - } + memset(localentity + best, 0, sizeof(*localentity)); + localentityactive[best] = true; + return localentity + best; } return NULL; } static void entremove(localentity_t *e) { - memset(e, 0, sizeof(*e)); - e->freetime = gametime + 1; + int i; + i = (e - localentity) / sizeof(localentity_t); + if (i < 0 || i >= MAX_LOCALENTITIES) + return; // this should be an error + //memset(e, 0, sizeof(*e)); + localentityactive[i] = false; + localentityfreetime[i] = (float)gametime + 1.0f; } static void phys_setupphysentities(void) @@ -86,9 +86,9 @@ static void phys_setupphysentities(void) /* for (i = 0;i < MAX_LOCALENTITIES;i++) { - l = localentities + i; - if (l->active && l->solid) + if (localentityactive[i] && localentities[i].solid) { + l = localentities + i; } } */ @@ -100,12 +100,16 @@ static void phys_moveentities(void) localentity_t *l; for (i = 0;i < MAX_LOCALENTITIES;i++) { - l = localentity + i; - if (l->active) + if (localentityactive[i]) { + l = localentity + i; if (l->framethink) + { l->framethink(l); - if (l->active && l->draw.model) + if (!localentityactive[i]) + continue; + } + if (l->draw.model) CGVM_Draw_Entity(&l->draw); } } @@ -122,7 +126,7 @@ static void phys_update(localentity_t *e) vec3_t impactpos, impactnormal, end; int impactentnum; float t, f, frac, bounce; - t = frametime; + t = (float)frametime; if (t == 0) return; VectorMA(e->draw.angles, t, e->avelocity, e->draw.angles); @@ -133,13 +137,17 @@ static void phys_update(localentity_t *e) { 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->touchnetwork) + e->touchnetwork(e); + // FIXME: do some kind of touch code here if physentities get implemented + + VectorCopy(impactpos, e->lastimpactorigin); } if (e->airfrictionscale) @@ -179,7 +187,7 @@ static void explosiondebris_framethink(localentity_t *self) { if (gametime > self->dietime) { - self->draw.scale -= frametime * 3; + self->draw.scale -= (float)(frametime * 3.0); if (self->draw.scale < 0.05f) { entremove(self); @@ -189,6 +197,33 @@ static void explosiondebris_framethink(localentity_t *self) phys_update(self); } +static void gib_framethink(localentity_t *self) +{ + if (gametime > self->dietime) + { + self->draw.scale -= (float)frametime * 3.0f; + if (self->draw.scale < 0.05f) + { + entremove(self); + return; + } + } + /* + if (gametime > self->trailnexttime) + { + self->trailnexttime = gametime + 0.1f; + CGVM_BloodParticle(self->draw.origin, self->velocity); + } + */ + phys_update(self); +} + +static void gib_touchnetwork(localentity_t *self) +{ + if (VectorDistance2(self->draw.origin, self->lastimpactorigin) >= 5*5) + CGVM_Stain(self->draw.origin, 64, 64, 24, 24, 48, 192, 48, 48, 48); +} + static void net_explosion(unsigned char num) { int i; @@ -213,7 +248,7 @@ static void net_explosion(unsigned char num) 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->velocity[2] -= (float)cg_gravity * 0.1f; e->avelocity[0] = CGVM_RandomRange(0, 1440); e->avelocity[1] = CGVM_RandomRange(0, 1440); e->avelocity[2] = CGVM_RandomRange(0, 1440); @@ -234,20 +269,79 @@ static void net_explosion(unsigned char num) VectorSet(e->worldmaxs, 0, 0, -8); VectorSet(e->entitymins, -8, -8, -8); VectorSet(e->entitymaxs, 8, 8, 8); - e->bouncescale = 1.4; + e->bouncescale = 1.4f; e->gravityscale = 1; e->airfrictionscale = 1; e->framethink = explosiondebris_framethink; - e->dietime = time + 5; + e->dietime = (float)time + 5.0f; + } +} + +static void net_gibshower(unsigned char num) +{ + int i, count; + float r, velocityscale; + vec3_t org; + double time; + localentity_t *e; + // need the time to know when the gibs should fade + time = CGVM_Time(); + // read the network data + count = CGVM_MSG_ReadByte(); + velocityscale = (float)(CGVM_MSG_ReadByte() * 100); + readvector(org); + + for (i = 0;i < count;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, velocityscale, e->velocity); + e->velocity[2] -= (float)(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/gib1.mdl"); + else if (r < 2) + e->draw.model = CGVM_Model("progs/gib2.mdl"); + else + e->draw.model = CGVM_Model("progs/gib3.mdl"); + e->draw.alpha = 1; + e->draw.scale = 1; + e->draw.frame1 = 0; + e->draw.frame2 = 0; + e->draw.framelerp = 0; + e->draw.skinnum = 0; + 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.5; + e->gravityscale = 1; + e->airfrictionscale = 1; + e->framethink = gib_framethink; + e->touchnetwork = gib_touchnetwork; + e->dietime = (float)time + CGVM_RandomRange(3.0f, 5.0f); } } // called by engine void CG_Init(void) { - localentity = CGVM_Malloc(sizeof(localentity_t) * MAX_LOCALENTITIES); - phys_entity = CGVM_Malloc(sizeof(cgphysentity_t) * MAX_LOCALENTITIES); + localentity = CGVM_Malloc(sizeof(*localentity) * MAX_LOCALENTITIES); + localentityactive = CGVM_Malloc(sizeof(*localentityactive) * MAX_LOCALENTITIES); + localentityfreetime = CGVM_Malloc(sizeof(*localentityfreetime) * MAX_LOCALENTITIES); + phys_entity = CGVM_Malloc(sizeof(*phys_entity) * MAX_LOCALENTITIES); CGVM_RegisterNetworkCode(1, net_explosion); + CGVM_RegisterNetworkCode(2, net_gibshower); gametime = 0; }