nuclide/Source/shared/decals.c
Marco Hladik 75bed53adc Client: We're now reading skyname and setting the skybox (with fallback) in CSQC. Much rejoice
Added item_suit and item_longjump... they do not do anything interesting yet.
Decals: Added glass break decals upon impact
Damage: Brush-entity radius damage should to work better now
Also seperated the weapons table from generic weapon entry functions. This should make maintaining mods easier
Fixed references from sv_clientslots to sv_playerslots. My brain gets confused between the Quake games at this point. I blame FTE
Fixed sprite animation cycle length check. It attempted to play one more frame than any sprite ever has. Needs more heavy testing?
2019-03-14 20:13:02 +01:00

179 lines
3.6 KiB
C

/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
#include "decals.h"
#define DECALS_MAX 30
#ifdef SSQC
entity g_decals;
void Decals_Init(void)
{
entity nextdecal = spawn();
g_decals = nextdecal;
for (int i = 0; i <= DECALS_MAX; i++) {
nextdecal.classname = "tempdecal";
nextdecal.owner = spawn();
if (i == DECALS_MAX) {
nextdecal.owner = g_decals;
} else {
nextdecal = nextdecal.owner;
}
}
}
entity Decals_Next(vector pos)
{
entity ret = g_decals;
g_decals = g_decals.owner;
/* Check for a tempdecal within a radius of 8 units and overwrite that one
* instead */
for (entity b = world; (b = find(b, ::classname, "tempdecal"));) {
if (vlen(b.origin - pos) < 8) {
return b;
}
}
return ret;
}
#endif
void Decals_PlaceSmall(vector pos)
{
#ifdef CSQC
// TODO
#else
entity decal = Decals_Next(pos);
setorigin(decal, pos);
decal.texture = sprintf("{shot%d", floor(random(1,6)));
decal.think = infodecal;
decal.nextthink = time /*+ 0.1f*/;
#endif
}
void Decals_PlaceBig(vector pos)
{
#ifdef CSQC
// TODO
#else
entity decal = Decals_Next(pos);
setorigin(decal, pos);
decal.texture = sprintf("{bigshot%d", floor(random(1,6)));
decal.think = infodecal;
decal.nextthink = time /*+ 0.1f*/;
#endif
}
void Decals_PlaceGlass(vector pos)
{
#ifdef CSQC
// TODO
#else
entity decal = Decals_Next(pos);
setorigin(decal, pos);
decal.texture = sprintf("{break%d", floor(random(1,4)));
decal.think = infodecal;
decal.nextthink = time /*+ 0.1f*/;
#endif
}
void Decals_PlaceScorch(vector pos)
{
#ifdef CSQC
// TODO
#else
entity decal = Decals_Next(pos);
setorigin(decal, pos);
decal.texture = sprintf("{scorch%d", floor(random(1,4)));
decal.think = infodecal;
decal.nextthink = time /*+ 0.1f*/;
#endif
}
#ifdef CSQC
const string g_decalshader = \
"{\n" \
"polygonOffset\n" \
"{\n" \
"clampmap %s\n" \
"rgbgen vertex\n" \
"blendfunc GL_ZERO GL_SRC_COLOR\n" \
"}\n" \
"}";
const string g_decalshader_add = \
"{\n" \
"polygonOffset\n" \
"{\n" \
"clampmap %s\n" \
"rgbgen vertex\n" \
"blendfunc add\n" \
"}\n" \
"}";
float Decal_PreDraw(void)
{
adddecal(self.classname, self.origin, self.mins, self.maxs, self.color, 1.0f);
addentity(self);
return PREDRAW_NEXT;
}
void Decal_Parse(void)
{
string decalname = "";
string decalshader = "";
self.origin[0] = readcoord();
self.origin[1] = readcoord();
self.origin[2] = readcoord();
self.angles[0] = readcoord();
self.angles[1] = readcoord();
self.angles[2] = readcoord();
self.classname = readstring();
self.color = [1,1,1];
for (int i = 0; i < g_decalwad.length; i++) {
if (self.classname == g_decalwad[i].name) {
self.color[0] = (g_decalwad[i].color[0] / 255);
self.color[1] = (g_decalwad[i].color[1] / 255);
self.color[2] = (g_decalwad[i].color[2] / 255);
self.style = g_decalwad[i].flags;
break;
}
}
self.size = drawgetimagesize(self.classname);
if (serverkeyfloat("*bspversion") == 30) {
decalname = sprintf("decal_%s", self.classname);
if (self.style & DFLAG_ADDITIVE) {
decalshader = sprintf(g_decalshader_add, self.classname);
} else {
decalshader = sprintf(g_decalshader, self.classname);
}
shaderforname(decalname, decalshader);
self.classname = decalname;
}
makevectors(self.angles);
float surf = getsurfacenearpoint(world, self.origin);
vector s_dir = getsurfacepointattribute(world, surf, 0, SPA_S_AXIS);
vector t_dir = getsurfacepointattribute(world, surf, 0, SPA_T_AXIS);
self.mins = v_up / self.size[0];
self.maxs = t_dir / self.size[1];
self.predraw = Decal_PreDraw;
self.drawmask = MASK_ENGINE;
}
#endif