From ec819cf4e494a06e365389569e1f1cca5a5c660d Mon Sep 17 00:00:00 2001 From: Marco Hladik Date: Wed, 1 Apr 2020 20:55:05 +0200 Subject: [PATCH] Shuffled a lot of Decal code around so gibs can now spawn blood, etc. --- src/gs-entbase/client.src | 1 + src/gs-entbase/decals.h | 55 +++++++++++++++++++++ src/gs-entbase/server.src | 1 + src/gs-entbase/server/infodecal.cpp | 67 ++++---------------------- src/gs-entbase/server/monstermaker.cpp | 2 +- src/shared/decals.c | 51 +++++++++++++++++++- src/shared/effects.c | 15 ++++++ 7 files changed, 132 insertions(+), 60 deletions(-) create mode 100644 src/gs-entbase/decals.h diff --git a/src/gs-entbase/client.src b/src/gs-entbase/client.src index b909dca6..47f16195 100644 --- a/src/gs-entbase/client.src +++ b/src/gs-entbase/client.src @@ -4,6 +4,7 @@ #includelist baseentity.h +decals.h materials.h client/baseentity.cpp client/env_cubemap.cpp diff --git a/src/gs-entbase/decals.h b/src/gs-entbase/decals.h new file mode 100644 index 00000000..8e7ff9f3 --- /dev/null +++ b/src/gs-entbase/decals.h @@ -0,0 +1,55 @@ +typedef struct { + float fraction; + vector normal; + vector endpos; +} traced_t; + +traced_t g_tracedDecal; + +void +decal_pickwall(entity dself, vector vpos) +{ + traced_t tmp[6]; + float frac = 1.0f; + + g_tracedDecal.fraction = 1.0f; + g_tracedDecal.endpos = [0,0,0]; + g_tracedDecal.normal = [0,0,0]; + + /* unrolled, trace against walls in all 6 directions */ + makevectors([0, 0, 0]); + traceline(vpos + (v_forward * -1), vpos + (v_forward * 128), 1, dself); + tmp[0].fraction = trace_fraction; + tmp[0].normal = trace_plane_normal; + tmp[0].endpos = trace_endpos; + traceline(vpos + (v_forward * 1), vpos + (v_forward * -128), 1, dself); + tmp[1].fraction = trace_fraction; + tmp[1].normal = trace_plane_normal; + tmp[1].endpos = trace_endpos; + traceline(vpos + (v_right * -1), vpos + (v_right * 128), 1, dself); + tmp[2].fraction = trace_fraction; + tmp[2].normal = trace_plane_normal; + tmp[2].endpos = trace_endpos; + traceline(vpos + (v_right * 1), vpos + (v_right * -128), 1, dself); + tmp[3].fraction = trace_fraction; + tmp[3].normal = trace_plane_normal; + tmp[3].endpos = trace_endpos; + traceline(vpos + (v_up * -1), vpos + (v_up * 128), 1, dself); + tmp[4].fraction = trace_fraction; + tmp[4].normal = trace_plane_normal; + tmp[4].endpos = trace_endpos; + traceline(vpos + (v_up * 1), vpos + (v_up * -128), 1, dself); + tmp[5].fraction = trace_fraction; + tmp[5].normal = trace_plane_normal; + tmp[5].endpos = trace_endpos; + + /* pick whatever wall is closest */ + for (int i = 0; i < 6; i++) { + if ( tmp[i].fraction < frac ) { + frac = tmp[i].fraction; + g_tracedDecal.fraction = tmp[i].fraction; + g_tracedDecal.endpos = tmp[i].endpos; + g_tracedDecal.normal = tmp[i].normal; + } + } +} diff --git a/src/gs-entbase/server.src b/src/gs-entbase/server.src index 3b10200f..c513fc80 100644 --- a/src/gs-entbase/server.src +++ b/src/gs-entbase/server.src @@ -4,6 +4,7 @@ #includelist baseentity.h +decals.h materials.h server/defs.h server/baseentity.cpp diff --git a/src/gs-entbase/server/infodecal.cpp b/src/gs-entbase/server/infodecal.cpp index a3e1d9cd..ba130982 100644 --- a/src/gs-entbase/server/infodecal.cpp +++ b/src/gs-entbase/server/infodecal.cpp @@ -28,12 +28,6 @@ The texture will be aligned along the surface texture normals. * but not angles. So we have to figure them out ourselves. */ .string texture; -typedef struct { - float fraction; - vector normal; - vector endpos; -} traced_t; - float infodecal_send(entity pvsent, float cflags) { WriteByte(MSG_ENTITY, ENT_DECAL); @@ -49,13 +43,6 @@ float infodecal_send(entity pvsent, float cflags) void infodecal(void) { - traced_t tmp[6]; - int i = 0; - int b = 0; - float frac = 1.0f; - vector endpos = [0,0,0]; - vector vpos = self.origin; - #ifdef WASTES remove(self); return; @@ -84,47 +71,9 @@ void infodecal(void) /* Some maps have everything set to full-on uppercase */ self.texture = strtolower(self.texture); - - /*self.origin[0] = rint(self.origin[0]); - self.origin[1] = rint(self.origin[1]); - self.origin[2] = rint(self.origin[2]);*/ + decal_pickwall(self, self.origin); - /* Unrolled because I'm lazy */ - makevectors([0, 0, 0]); - traceline(vpos + (v_forward * -1), vpos + (v_forward * 128), 1, self); - tmp[0].fraction = trace_fraction; - tmp[0].normal = trace_plane_normal; - tmp[0].endpos = trace_endpos; - traceline(vpos + (v_forward * 1), vpos + (v_forward * -128), 1, self); - tmp[1].fraction = trace_fraction; - tmp[1].normal = trace_plane_normal; - tmp[1].endpos = trace_endpos; - traceline(vpos + (v_right * -1), vpos + (v_right * 128), 1, self); - tmp[2].fraction = trace_fraction; - tmp[2].normal = trace_plane_normal; - tmp[2].endpos = trace_endpos; - traceline(vpos + (v_right * 1), vpos + (v_right * -128), 1, self); - tmp[3].fraction = trace_fraction; - tmp[3].normal = trace_plane_normal; - tmp[3].endpos = trace_endpos; - traceline(vpos + (v_up * -1), vpos + (v_up * 128), 1, self); - tmp[4].fraction = trace_fraction; - tmp[4].normal = trace_plane_normal; - tmp[4].endpos = trace_endpos; - traceline(vpos + (v_up * 1), vpos + (v_up * -128), 1, self); - tmp[5].fraction = trace_fraction; - tmp[5].normal = trace_plane_normal; - tmp[5].endpos = trace_endpos; - - for (i = 0; i < 6; i++) { - if ( tmp[i].fraction < frac ) { - frac = tmp[i].fraction; - endpos = tmp[i].endpos; - b = i; - } - } - - if (frac == 1.0f) { + if (g_tracedDecal.fraction == 1.0f) { dprint(sprintf("infodecal tracing failed at %v\n", self.origin)); if (self.classname != "tempdecal") { @@ -133,19 +82,21 @@ void infodecal(void) return; } + self.origin = g_tracedDecal.endpos; + /* FIXME: more universal check? */ - if (getsurfacetexture(trace_ent, getsurfacenearpoint(trace_ent, endpos)) == "sky") { + if (getsurfacetexture(trace_ent, getsurfacenearpoint(trace_ent, g_tracedDecal.endpos)) == "sky") { return; } - makevectors(vectoangles(tmp[b].endpos - self.origin )); - vector cpl = v_forward - (v_forward * tmp[b].normal) * tmp[b].normal; + makevectors(vectoangles(g_tracedDecal.endpos - self.origin )); + vector cpl = v_forward - (v_forward * g_tracedDecal.normal) * g_tracedDecal.normal; - if (tmp[b].normal[2] == 0) { + if (g_tracedDecal.normal[2] == 0) { cpl = [0, 0, 1]; } - self.angles = vectoangles(cpl, tmp[b].normal); + self.angles = vectoangles(cpl, g_tracedDecal.normal); self.solid = SOLID_NOT; self.pvsflags = PVSF_NOREMOVE | PVSF_IGNOREPVS; self.SendEntity = infodecal_send; diff --git a/src/gs-entbase/server/monstermaker.cpp b/src/gs-entbase/server/monstermaker.cpp index 124a0dac..7e8df02c 100644 --- a/src/gs-entbase/server/monstermaker.cpp +++ b/src/gs-entbase/server/monstermaker.cpp @@ -116,7 +116,7 @@ monstermaker::Spawner(void) } /* too many alive at a time */ - if ((m_iMaxChildren > 0) && c >= m_iMaxChildren) || (m_flDelay == 0 && c >= 1)) { + if ((m_iMaxChildren > 0 && c >= m_iMaxChildren) || (m_flDelay == 0 && c >= 1)) { nextthink = time + m_flDelay; return; } diff --git a/src/shared/decals.c b/src/shared/decals.c index 1943ebe5..b804b2a1 100644 --- a/src/shared/decals.c +++ b/src/shared/decals.c @@ -151,7 +151,6 @@ void Decals_PlaceGauss(vector pos) decal.nextthink = time /*+ 0.1f*/; #endif } - #ifdef CSQC class decal @@ -231,4 +230,54 @@ void Decal_Parse(void) new.predraw = Decal_PreDraw; new.drawmask = MASK_ENGINE; } + +/* this is like Decal_Parse, but better */ +void +Decals_Place(vector org, string dname) +{ + decal new; + + new = spawn(decal); + decal_pickwall(new, org); + + /* we never hit any wall. */ + if (g_tracedDecal.fraction == 1.0f) { + dprint(sprintf("infodecal tracing failed at %v\n", org)); + remove(new); + return; + } + + new.origin = g_tracedDecal.endpos; + + /* FIXME: more universal check? */ + if (getsurfacetexture(trace_ent, getsurfacenearpoint(trace_ent, g_tracedDecal.endpos)) == "sky") { + return; + } + + makevectors(vectoangles(g_tracedDecal.endpos - self.origin )); + vector cpl = v_forward - (v_forward * g_tracedDecal.normal) * g_tracedDecal.normal; + + if (g_tracedDecal.normal[2] == 0) { + cpl = [0, 0, 1]; + } + + new.angles = vectoangles(cpl, g_tracedDecal.normal); + new.m_strTexture = dname; + + new.size = drawgetimagesize(new.m_strTexture); + + if (serverkeyfloat("*bspversion") == 30) { + Decal_MakeShader(new); + } + + makevectors(new.angles); + float surf = getsurfacenearpoint(world, new.origin); + vector s_dir = getsurfacepointattribute(world, surf, 0, SPA_S_AXIS); + vector t_dir = getsurfacepointattribute(world, surf, 0, SPA_T_AXIS); + new.mins = v_up / new.size[0]; + new.maxs = t_dir / new.size[1]; + new.color = getlight(new.origin) / 255; + new.predraw = Decal_PreDraw; + new.drawmask = MASK_ENGINE; +} #endif diff --git a/src/shared/effects.c b/src/shared/effects.c index 3c76e6a1..19beba42 100755 --- a/src/shared/effects.c +++ b/src/shared/effects.c @@ -99,6 +99,10 @@ Effect_GibHuman(vector pos) static void Gib_Remove(void) { remove(self); } + static void Gib_Touch(void) + { + Decals_Place(self.origin, sprintf("{blood%d", floor(random(1,9)))); + } for (int i = 0; i < 5; i++) { vector vel; @@ -110,9 +114,12 @@ Effect_GibHuman(vector pos) setmodel(gibb, g_hgibs[i]); setorigin(gibb, pos); gibb.movetype = MOVETYPE_BOUNCE; + gibb.solid = SOLID_BBOX; + setsize(gibb, [0,0,0], [0,0,0]); gibb.velocity = vel; gibb.avelocity = vectoangles(gibb.velocity); gibb.think = Gib_Remove; + gibb.touch = Gib_Touch; gibb.nextthink = time + 5.0f; gibb.drawmask = MASK_ENGINE; } @@ -164,6 +171,11 @@ void Effect_CreateBlood(vector pos, vector color) { msg_entity = self; multicast(pos, MULTICAST_PVS); #else + static void Blood_Touch(void) + { + Decals_Place(self.origin, sprintf("{blood%d", floor(random(1,9)))); + } + env_sprite eBlood = spawn(env_sprite); setorigin(eBlood, pos); setmodel(eBlood, "sprites/bloodspray.spr"); @@ -192,6 +204,9 @@ void Effect_CreateBlood(vector pos, vector color) { ePart.framerate = 15; ePart.nextthink = time + 0.1f; ePart.velocity = randomvec() * 64; + ePart.touch = Blood_Touch; + ePart.solid = SOLID_BBOX; + setsize(ePart, [0,0,0], [0,0,0]); } #endif }