fteqw/engine/client/p_classic.c

1088 lines
26 KiB
C
Raw Normal View History

/*
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 included (GNU.txt) 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.
*/
#include "quakedef.h"
#ifdef PSET_CLASSIC
#include "glquake.h"
#include "shader.h"
#include "renderque.h"
#define POLYS
typedef enum {
DODGY,
ROCKET_TRAIL,
ALT_ROCKET_TRAIL,
BLOOD_TRAIL,
GRENADE_TRAIL,
BIG_BLOOD_TRAIL,
TRACER1_TRAIL,
TRACER2_TRAIL,
VOOR_TRAIL,
BRIGHTFIELD_POINT,
BLOBEXPLOSION_POINT,
LAVASPLASH_POINT,
EXPLOSION_POINT,
TELEPORTSPLASH_POINT,
MUZZLEFLASH_POINT,
EFFECTTYPE_MAX
} effect_type_t;
typedef struct cparticle_s
{
avec3_t org;
float die;
avec3_t vel;
float ramp;
enum
{
pt_static,
pt_fire,
pt_explode,
pt_explode2,
pt_blob,
pt_blob2,
pt_grav,
pt_slowgrav,
pt_oneframe
} type;
unsigned int rgb;
struct cparticle_s *next;
} cparticle_t;
#define DEFAULT_NUM_PARTICLES 2048
#define ABSOLUTE_MIN_PARTICLES 512
#define ABSOLUTE_MAX_PARTICLES 8192
static int r_numparticles;
static cparticle_t *particles, *fte_restrict active_particles, *free_particles;
extern cvar_t r_part_density, r_part_classic_expgrav;
static unsigned int particleframe;
extern qbyte default_quakepal[]; /*for ramps more than anything else*/
static int ramp1[8] = {0x6f, 0x6d, 0x6b, 0x69, 0x67, 0x65, 0x63, 0x61};
static int ramp2[8] = {0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x68, 0x66};
static int ramp3[8] = {0x6d, 0x6b, 6, 5, 4, 3};
#define qpal(q) ((default_quakepal[(q)*3+0]<<0) | (default_quakepal[(q)*3+1]<<8) | (default_quakepal[(q)*3+2]<<16))
#ifndef POLYS
#define BUFFERVERTS 2048*3
static vecV_t classicverts[BUFFERVERTS];
static union c
{
byte_vec4_t b;
unsigned int i;
} classiccolours[BUFFERVERTS];
static vec2_t classictexcoords[BUFFERVERTS];
static index_t classicindexes[BUFFERVERTS];
rewrote ban code, merging bans+nonbans+cuffs+mute+cripple+deaf+lagged+vip. added timeouts. new penalties have no dedicated command. use the addip command for it. maplist command now generates links. implemented skin objects for q3. added a csqc builtin for it. also supports compositing skins. playing demos inside zips/pk3s/paks should now work. bumped default rate cvar. added cl_transfer to attempt to connect to a new server without disconnecting first. rewrote fog command. alpha and mindist arguments are now supported. fog change also happens over a short time period. added new args to the showpic console command. can now create clickable items for touchscreen/absmouse users. fixed menus to properly support right-aligned text. this finally fixes variable-width fonts. rewrote console tab completion suggestions display. now clickable links. strings obtained from qc are now marked as const. this has required quite a few added consts all over the place. probably crappy attempt at adding joypad support to the sdl port. no idea if it works. changed key bind event code. buttons now track which event they should trigger when released, instead of being the same one the whole time. this allows +forward etc clickable buttons on screen. Also simplified modifier keys - they no longer trigger random events when pressing the modifier key itself. Right modifiers can now be bound separately from left modifiers. Right will use left's binding if not otherwise bound. Bind assumes left if there's no prefix. multiplayer->setup->network menu no longer crashes. added rgb colours to the translation view (but not to the colour-changing keys). added modelviewer command to view models. added menu_mods menu to switch mods in a more friendly way. will be shown by default if multiple manifests exist in the binarydir. clamped classic tracer density. scrag particles no longer look quite so buggy. added ifdefs to facilitate a potential winrt port. the engine should now have no extra dependencies, but still needs system code+audio drivers to be written. if it can't set a renderer, it'll now try to use *every* renderer until it finds one that works. added experimental mapcluster server mode (that console command). New maps will be started up as required. rewrote skeletal blending code a bit. added cylinder geomtypes. fix cfg_save writing to the wrong path bug. VFS_CLOSE now returns a boolean. false means there was some sort of fatal error (either crc when reading was bad, or the write got corrupted or something). Typically ignorable, depends how robust you want to be. win32 tls code now supports running as a server. added connect tls://address support, as well as equivalent sv_addport support. exposed basic model loading api to plugins. d3d11 backend now optionally supports tessellation hlsl. no suitable hlsl provided by default. !!tess to enable. attempted to add gamma ramp support for d3d11. added support for shader blobs to speed up load times. r_shaderblobs 1 to enable. almost vital for d3d11. added vid_srgb cvar. shadowless lights are no longer disabled if shadows are not supported. attempt to add support for touchscreens in win7/8. Wrote gimmicky lua support, using lua instead of ssqc. define VM_LUA to enable. updated saved game code. can again load saved games from vanilla-like engines. changed scale clamping. 0.0001 should no longer appear as 1. changed default mintic from 0.03 to 0.013 to match vanilla qw. I don't know why it was at 0.03. probably a typo. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4623 fc73d0e0-1445-4013-8a0c-d673dee63da5
2014-03-30 09:55:06 +01:00
static mesh_t classicmesh;
#endif
static shader_t *classicshader;
//obtains an index for the name, even if it is unknown (one can be loaded after. will only fail if the effect limit is reached)
//technically this function is not meant to fail often, but thats fine so long as the other functions are meant to safely reject invalid effect numbers.
rewrote ban code, merging bans+nonbans+cuffs+mute+cripple+deaf+lagged+vip. added timeouts. new penalties have no dedicated command. use the addip command for it. maplist command now generates links. implemented skin objects for q3. added a csqc builtin for it. also supports compositing skins. playing demos inside zips/pk3s/paks should now work. bumped default rate cvar. added cl_transfer to attempt to connect to a new server without disconnecting first. rewrote fog command. alpha and mindist arguments are now supported. fog change also happens over a short time period. added new args to the showpic console command. can now create clickable items for touchscreen/absmouse users. fixed menus to properly support right-aligned text. this finally fixes variable-width fonts. rewrote console tab completion suggestions display. now clickable links. strings obtained from qc are now marked as const. this has required quite a few added consts all over the place. probably crappy attempt at adding joypad support to the sdl port. no idea if it works. changed key bind event code. buttons now track which event they should trigger when released, instead of being the same one the whole time. this allows +forward etc clickable buttons on screen. Also simplified modifier keys - they no longer trigger random events when pressing the modifier key itself. Right modifiers can now be bound separately from left modifiers. Right will use left's binding if not otherwise bound. Bind assumes left if there's no prefix. multiplayer->setup->network menu no longer crashes. added rgb colours to the translation view (but not to the colour-changing keys). added modelviewer command to view models. added menu_mods menu to switch mods in a more friendly way. will be shown by default if multiple manifests exist in the binarydir. clamped classic tracer density. scrag particles no longer look quite so buggy. added ifdefs to facilitate a potential winrt port. the engine should now have no extra dependencies, but still needs system code+audio drivers to be written. if it can't set a renderer, it'll now try to use *every* renderer until it finds one that works. added experimental mapcluster server mode (that console command). New maps will be started up as required. rewrote skeletal blending code a bit. added cylinder geomtypes. fix cfg_save writing to the wrong path bug. VFS_CLOSE now returns a boolean. false means there was some sort of fatal error (either crc when reading was bad, or the write got corrupted or something). Typically ignorable, depends how robust you want to be. win32 tls code now supports running as a server. added connect tls://address support, as well as equivalent sv_addport support. exposed basic model loading api to plugins. d3d11 backend now optionally supports tessellation hlsl. no suitable hlsl provided by default. !!tess to enable. attempted to add gamma ramp support for d3d11. added support for shader blobs to speed up load times. r_shaderblobs 1 to enable. almost vital for d3d11. added vid_srgb cvar. shadowless lights are no longer disabled if shadows are not supported. attempt to add support for touchscreens in win7/8. Wrote gimmicky lua support, using lua instead of ssqc. define VM_LUA to enable. updated saved game code. can again load saved games from vanilla-like engines. changed scale clamping. 0.0001 should no longer appear as 1. changed default mintic from 0.03 to 0.013 to match vanilla qw. I don't know why it was at 0.03. probably a typo. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4623 fc73d0e0-1445-4013-8a0c-d673dee63da5
2014-03-30 09:55:06 +01:00
static int PClassic_FindParticleType(const char *name)
{
if (!stricmp("tr_rocket", name))
return ROCKET_TRAIL;
if (!stricmp("tr_altrocket", name))
return ALT_ROCKET_TRAIL;
if (!stricmp("tr_slightblood", name))
return BLOOD_TRAIL;
if (!stricmp("tr_grenade", name))
return GRENADE_TRAIL;
if (!stricmp("tr_blood", name))
return BIG_BLOOD_TRAIL;
if (!stricmp("tr_wizspike", name))
return TRACER1_TRAIL;
if (!stricmp("tr_knightspike", name))
return TRACER2_TRAIL;
if (!stricmp("tr_vorespike", name))
return VOOR_TRAIL;
if (!stricmp("te_tarexplosion", name))
return BLOBEXPLOSION_POINT;
if (!stricmp("te_lavasplash", name))
return LAVASPLASH_POINT;
if (!stricmp("te_explosion", name))
return EXPLOSION_POINT;
if (!stricmp("te_teleport", name))
return TELEPORTSPLASH_POINT;
if (!stricmp("te_muzzleflash", name))
return MUZZLEFLASH_POINT;
if (!stricmp("ef_brightfield", name))
return BRIGHTFIELD_POINT;
return P_INVALID;
}
rewrote ban code, merging bans+nonbans+cuffs+mute+cripple+deaf+lagged+vip. added timeouts. new penalties have no dedicated command. use the addip command for it. maplist command now generates links. implemented skin objects for q3. added a csqc builtin for it. also supports compositing skins. playing demos inside zips/pk3s/paks should now work. bumped default rate cvar. added cl_transfer to attempt to connect to a new server without disconnecting first. rewrote fog command. alpha and mindist arguments are now supported. fog change also happens over a short time period. added new args to the showpic console command. can now create clickable items for touchscreen/absmouse users. fixed menus to properly support right-aligned text. this finally fixes variable-width fonts. rewrote console tab completion suggestions display. now clickable links. strings obtained from qc are now marked as const. this has required quite a few added consts all over the place. probably crappy attempt at adding joypad support to the sdl port. no idea if it works. changed key bind event code. buttons now track which event they should trigger when released, instead of being the same one the whole time. this allows +forward etc clickable buttons on screen. Also simplified modifier keys - they no longer trigger random events when pressing the modifier key itself. Right modifiers can now be bound separately from left modifiers. Right will use left's binding if not otherwise bound. Bind assumes left if there's no prefix. multiplayer->setup->network menu no longer crashes. added rgb colours to the translation view (but not to the colour-changing keys). added modelviewer command to view models. added menu_mods menu to switch mods in a more friendly way. will be shown by default if multiple manifests exist in the binarydir. clamped classic tracer density. scrag particles no longer look quite so buggy. added ifdefs to facilitate a potential winrt port. the engine should now have no extra dependencies, but still needs system code+audio drivers to be written. if it can't set a renderer, it'll now try to use *every* renderer until it finds one that works. added experimental mapcluster server mode (that console command). New maps will be started up as required. rewrote skeletal blending code a bit. added cylinder geomtypes. fix cfg_save writing to the wrong path bug. VFS_CLOSE now returns a boolean. false means there was some sort of fatal error (either crc when reading was bad, or the write got corrupted or something). Typically ignorable, depends how robust you want to be. win32 tls code now supports running as a server. added connect tls://address support, as well as equivalent sv_addport support. exposed basic model loading api to plugins. d3d11 backend now optionally supports tessellation hlsl. no suitable hlsl provided by default. !!tess to enable. attempted to add gamma ramp support for d3d11. added support for shader blobs to speed up load times. r_shaderblobs 1 to enable. almost vital for d3d11. added vid_srgb cvar. shadowless lights are no longer disabled if shadows are not supported. attempt to add support for touchscreens in win7/8. Wrote gimmicky lua support, using lua instead of ssqc. define VM_LUA to enable. updated saved game code. can again load saved games from vanilla-like engines. changed scale clamping. 0.0001 should no longer appear as 1. changed default mintic from 0.03 to 0.013 to match vanilla qw. I don't know why it was at 0.03. probably a typo. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4623 fc73d0e0-1445-4013-8a0c-d673dee63da5
2014-03-30 09:55:06 +01:00
static qboolean PClassic_Query(int type, int body, char *outstr, int outstrlen)
{
char *n = NULL;
switch(type)
{
case ROCKET_TRAIL:
n = "tr_rocket";
break;
case ALT_ROCKET_TRAIL:
n = "tr_altrocket";
break;
case BLOOD_TRAIL:
n = "tr_slightblood";
break;
case GRENADE_TRAIL:
n = "tr_grenade";
break;
case BIG_BLOOD_TRAIL:
n = "tr_blood";
break;
case TRACER1_TRAIL:
n = "tr_wizspike";
break;
case TRACER2_TRAIL:
n = "tr_knightspike";
break;
case VOOR_TRAIL:
n = "tr_vorespike";
break;
case BLOBEXPLOSION_POINT:
n = "te_tarexplosion";
break;
case LAVASPLASH_POINT:
n = "te_lavasplash";
break;
case EXPLOSION_POINT:
n = "te_explosion";
break;
case TELEPORTSPLASH_POINT:
n = "te_teleport";
break;
case BRIGHTFIELD_POINT:
n = "ef_brightfield";
break;
}
if (!n)
return false;
if (body == 0)
{
Q_strncpyz(outstr, n, outstrlen);
return true;
}
return false;
}
//a convienience function.
static int PClassic_RunParticleEffectTypeString (vec3_t org, vec3_t dir, float count, char *name)
{
int efnum = P_FindParticleType(name);
return P_RunParticleEffectState(org, dir, count, efnum, NULL);
}
//DP extension: add particles within a box that look like rain or snow.
static void PClassic_RunParticleWeather(vec3_t minb, vec3_t maxb, vec3_t dir, float count, int colour, char *efname)
{
}
//DP extension: add particles within a box.
static void PClassic_RunParticleCube(int ptype, vec3_t minb, vec3_t maxb, vec3_t dir_min, vec3_t dir_max, float count, int colour, qboolean gravity, float jitter)
{
}
//hexen2 support: add particles flying out from a point with a randomized speed
static void PClassic_RunParticleEffect2 (vec3_t org, vec3_t dmin, vec3_t dmax, int color, int effect, int count)
{
}
//hexen2 support: add particles within a box.
static void PClassic_RunParticleEffect3 (vec3_t org, vec3_t box, int color, int effect, int count)
{
}
//hexen2 support: add particles around the spot in a radius. no idea what the 'effect' field is.
static void PClassic_RunParticleEffect4 (vec3_t org, float radius, int color, int effect, int count)
{
}
//this function is used as a fallback in case a trail effect is unknown.
static void PClassic_ParticleTrailIndex (vec3_t start, vec3_t end, int color, int crnd, trailstate_t **tsk)
{
}
//this function is called to tell the particle system about surfaces that might emit particles at map startup.
static void PClassic_EmitSkyEffectTris(model_t *mod, msurface_t *fa, int ptype)
{
}
//the one-time initialisation function, called no mater which renderer is active.
static qboolean PClassic_InitParticles (void)
{
int i;
if ((i = COM_CheckParm ("-particles")) && i + 1 < com_argc)
{
r_numparticles = (int) (Q_atoi(com_argv[i + 1]));
r_numparticles = bound(ABSOLUTE_MIN_PARTICLES, r_numparticles, ABSOLUTE_MAX_PARTICLES);
}
else
{
r_numparticles = DEFAULT_NUM_PARTICLES;
}
particles = (cparticle_t *) BZ_Malloc (r_numparticles * sizeof(cparticle_t));
#ifndef POLYS
for (i = 0; i < BUFFERVERTS; i += 3)
{
classictexcoords[i+1][0] = 1;
classictexcoords[i+2][1] = 1;
classicindexes[i+0] = i+0;
classicindexes[i+1] = i+1;
classicindexes[i+2] = i+2;
}
classicmesh.xyz_array = classicverts;
classicmesh.st_array = classictexcoords;
classicmesh.colors4b_array = (byte_vec4_t*)classiccolours;
classicmesh.indexes = classicindexes;
#endif
classicshader = R_RegisterShader("particles_classic", SUF_NONE,
"{\n"
"program defaultsprite\n"
"nomipmaps\n"
"surfaceparm nodlight\n"
"{\n"
"if r_part_classic_square\n"
"map classicparticle_square\n"
"else\n"
"map classicparticle\n"
"endif\n"
"rgbgen vertex\n"
"alphagen vertex\n"
"blendfunc blend\n"
"}\n"
"}\n"
);
return true;
}
static void PClassic_ShutdownParticles(void)
{
BZ_Free(particles);
particles = NULL;
}
// a classic trailstate is really just a float stored in a pointer variable...
// assuming float alignment/size is more strict than pointer
static float Classic_GetLeftover(trailstate_t **tsk)
{
float *f = (float *)tsk;
if (!f)
return 0;
return *f;
}
static void Classic_SetLeftover(trailstate_t **tsk, float leftover)
{
float *f = (float *)tsk;
if (f)
*f = leftover;
}
//called when an entity is removed from the world, taking its trailstate with it.
static void PClassic_DelinkTrailstate(trailstate_t **tsk)
{
*tsk = NULL;
}
//wipes all the particles ready for the next map.
static void PClassic_ClearParticles (void)
{
int i;
free_particles = &particles[0];
active_particles = NULL;
for (i = 0;i < r_numparticles; i++)
particles[i].next = &particles[i+1];
particles[r_numparticles - 1].next = NULL;
}
//some particles (brightfield) must last only one frame
static void PClassic_ClearPerFrame(void)
{
if (particleframe != -1 && particleframe != cl_framecount)
{
cparticle_t **link, *kill;
for (link = &active_particles; *link; )
{
if ((*link)->type == pt_oneframe)
{
kill = *link;
*link = kill->next;
kill->next = free_particles;
free_particles = kill;
}
else
link = &(*link)->next;
}
}
}
//draws all the active particles.
static void PClassic_DrawParticles(void)
{
cparticle_t *p, *kill;
int i;
float time2, time3, time1, dvel, frametime, grav;
vec3_t up, right;
float dist, scale, r_partscale=0;
#ifdef POLYS
scenetris_t *scenetri;
#else
union c usecolours;
#endif
static float oldtime;
RSpeedMark();
if (!active_particles)
{
oldtime = cl.time;
return;
}
if (particleframe != -1 && particleframe != cl_framecount)
{
PClassic_ClearPerFrame();
particleframe = -1;
}
if (r_refdef.useperspective)
r_partscale = 0.004 * tan (r_refdef.fov_x * (M_PI / 180) * 0.5f);
else
r_partscale = 0;
VectorScale (vup, 1.5, up);
VectorScale (vright, 1.5, right);
frametime = cl.time - oldtime;
oldtime = cl.time;
frametime = bound(0, frametime, 1);
if (cl.paused || r_secondaryview || r_refdef.recurse)
frametime = 0;
time3 = frametime * 15;
time2 = frametime * 10; // 15;
time1 = frametime * 5;
grav = frametime * 800 * 0.05;
dvel = 4 * frametime;
#ifdef POLYS
// if (cl_numstris && cl_stris[cl_numstris-1].shader == classicshader && cl_stris[cl_numstris-1].numvert + 8 <= MAX_INDICIES)
// scenetri = &cl_stris[cl_numstris-1];
// else
{
if (cl_numstris == cl_maxstris)
{
cl_maxstris+=8;
cl_stris = BZ_Realloc(cl_stris, sizeof(*cl_stris)*cl_maxstris);
}
scenetri = &cl_stris[cl_numstris++];
scenetri->shader = classicshader;
------------------------------------------------------------------------ r4169 | acceptthis | 2013-01-17 08:55:12 +0000 (Thu, 17 Jan 2013) | 31 lines removed MAX_VISEDICTS limit. PEXT2_REPLACEMENTDELTAS tweaked, now has 4 million entity limit. still not enabled by default. TE_BEAM now maps to a separate TEQW_BEAM to avoid conflicts with QW. added android multitouch emulation for windows/rawinput (in_simulatemultitouch). split topcolor/bottomcolor from scoreboard, for dp's colormap|1024 feature. now using utf-8 for windows consoles. qcc warnings/errors now give clickable console links for quick+easy editing. disabled menutint when the currently active item changes contrast or gamma (for OneManClan). Added support for drawfont/drawfontscale. tweaked the qcvm a little to reduce the number of pointers. .doll file loading. still experimental and will likely crash. requires csqc active, even if its a dummy progs. this will be fixed in time. Still other things that need cleaning up. windows: gl_font "?" shows the standard windows font-selection dialog, and can be used to select windows fonts. not all work. and you probably don't want to use windings. fixed splitscreen support when playing mvds. added mini-scoreboards to splitscreen. editor/debugger now shows asm if there's no linenumber info. also, pressing f1 for help shows the shortcuts. Added support for .framegroups files for psk(psa) and iqm formats. True support for ezquake's colour codes. Mutually exclusive with background colours. path command output slightly more readable. added support for digest_hex (MD4, SHA1, CRC16). skingroups now colourmap correctly. Fix terrain colour hints, and litdata from the wrong bsp. fix ftp dual-homed issue. support epsv command, and enable ipv6 (eprt still not supported). remove d3d11 compilation from the makefile. the required headers are not provided by mingw, and are not available to the build bot, so don't bother. fix v *= v.x and similar opcodes. fteqcc: fixed support for áéíóú type chars in names. utf-8 files now properly supported (even with the utf-8 bom/identifier). utf-16 also supported. fteqcc: fixed '#if 1 == 3 && 4' parsing. fteqcc: -Werror acts on the warning, rather than as a separate error. Line numbers are thus more readable. fteqcc: copyright message now includes compile date instead. fteqccgui: the treeview control is now coloured depending on whether there were warnings/errors in the last compile. fteqccgui: the output window is now focused and scrolls down as compilation progresses. pr_dumpplatform command dumps out some pragmas to convert more serious warnings to errors. This is to avoid the infamous 'fteqcc sucks cos my code sucks' issue. rewrote prespawn/modelist/soundlist code. server tracks progress now. ------------------------------------------------------------------------ git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4167 fc73d0e0-1445-4013-8a0c-d673dee63da5
2013-03-12 22:29:40 +00:00
scenetri->flags = BEF_NODLIGHT|BEF_NOSHADOWS;
scenetri->firstidx = cl_numstrisidx;
scenetri->firstvert = cl_numstrisvert;
scenetri->numvert = 0;
scenetri->numidx = 0;
}
#endif
while(1)
{
kill = active_particles;
if (kill && kill->die < cl.time)
{
active_particles = kill->next;
kill->next = free_particles;
free_particles = kill;
continue;
}
break;
}
for (p = active_particles; p ; p = p->next)
{
while (1)
{
kill = p->next;
if (kill && kill->die < cl.time)
{
p->next = kill->next;
kill->next = free_particles;
free_particles = kill;
continue;
}
break;
}
// hack a scale up to keep particles from disapearing
dist = (p->org[0] - r_origin[0]) * vpn[0] + (p->org[1] - r_origin[1]) * vpn[1] + (p->org[2] - r_origin[2]) * vpn[2];
scale = 1 + dist * r_partscale;
#ifdef POLYS
if (cl_numstrisvert+3 > cl_maxstrisvert)
{
cl_maxstrisvert+=1024*3;
cl_strisvertv = BZ_Realloc(cl_strisvertv, sizeof(*cl_strisvertv)*cl_maxstrisvert);
cl_strisvertt = BZ_Realloc(cl_strisvertt, sizeof(*cl_strisvertt)*cl_maxstrisvert);
cl_strisvertc = BZ_Realloc(cl_strisvertc, sizeof(*cl_strisvertc)*cl_maxstrisvert);
}
// Vector4Set(cl_strisvertc[cl_numstrisvert+0],1,1,1,1);
// Vector4Set(cl_strisvertc[cl_numstrisvert+1],1,1,1,1);
// Vector4Set(cl_strisvertc[cl_numstrisvert+2],1,1,1,1);
Vector4Set(cl_strisvertc[cl_numstrisvert+0], ((p->rgb&0xff)>>0)/256.0, ((p->rgb&0xff00)>>8)/256.0, ((p->rgb&0xff0000)>>16)/256.0, ((p->type == pt_fire)?((6 - p->ramp) *0.166666):1.0));
Vector4Copy(cl_strisvertc[cl_numstrisvert+0], cl_strisvertc[cl_numstrisvert+1]);
Vector4Copy(cl_strisvertc[cl_numstrisvert+0], cl_strisvertc[cl_numstrisvert+2]);
Vector2Set(cl_strisvertt[cl_numstrisvert+0], 0, 0);
Vector2Set(cl_strisvertt[cl_numstrisvert+1], 1, 0);
Vector2Set(cl_strisvertt[cl_numstrisvert+2], 0, 1);
VectorCopy(p->org, cl_strisvertv[cl_numstrisvert+0]);
VectorMA(p->org, scale, up, cl_strisvertv[cl_numstrisvert+1]);
VectorMA(p->org, scale, right, cl_strisvertv[cl_numstrisvert+2]);
if (cl_numstrisidx+3 > cl_maxstrisidx)
{
cl_maxstrisidx += 1024*3;
cl_strisidx = BZ_Realloc(cl_strisidx, sizeof(*cl_strisidx)*cl_maxstrisidx);
}
cl_strisidx[cl_numstrisidx++] = (cl_numstrisvert - scenetri->firstvert) + 0;
cl_strisidx[cl_numstrisidx++] = (cl_numstrisvert - scenetri->firstvert) + 1;
cl_strisidx[cl_numstrisidx++] = (cl_numstrisvert - scenetri->firstvert) + 2;
cl_numstrisvert += 3;
scenetri->numvert += 3;
scenetri->numidx += 3;
#else
if (classicmesh.numvertexes >= BUFFERVERTS-3)
{
classicmesh.numindexes = classicmesh.numvertexes;
BE_DrawMesh_Single(classicshader, &classicmesh, NULL, &classicshader->defaulttextures, 0);
classicmesh.numvertexes = 0;
}
usecolours.i = p->rgb;
if (p->type == pt_fire)
usecolours.b[3] = 255 * (6 - p->ramp) / 6;
else
usecolours.b[3] = 255;
classiccolours[classicmesh.numvertexes].i = usecolours.i;
VectorCopy(p->org, classicverts[classicmesh.numvertexes]);
classicmesh.numvertexes++;
classiccolours[classicmesh.numvertexes].i = usecolours.i;
VectorMA(p->org, scale, up, classicverts[classicmesh.numvertexes]);
classicmesh.numvertexes++;
classiccolours[classicmesh.numvertexes].i = usecolours.i;
VectorMA(p->org, scale, right, classicverts[classicmesh.numvertexes]);
classicmesh.numvertexes++;
#endif
p->org[0] += p->vel[0] * frametime;
p->org[1] += p->vel[1] * frametime;
p->org[2] += p->vel[2] * frametime;
switch (p->type)
{
case pt_oneframe:
case pt_static:
break;
case pt_fire:
p->ramp += time1;
if (p->ramp >= 6)
p->die = -1;
else
p->rgb = qpal(ramp3[(int) p->ramp]);
p->vel[2] += grav;
break;
case pt_explode:
p->ramp += time2;
if (p->ramp >=8)
p->die = -1;
else
p->rgb = qpal(ramp1[(int) p->ramp]);
for (i = 0; i < 3; i++)
p->vel[i] += p->vel[i] * dvel;
p->vel[2] -= grav*r_part_classic_expgrav.value;
break;
case pt_explode2:
p->ramp += time3;
if (p->ramp >=8)
p->die = -1;
else
p->rgb = qpal(ramp2[(int) p->ramp]);
for (i = 0; i < 3; i++)
p->vel[i] -= p->vel[i] * frametime;
p->vel[2] -= grav*r_part_classic_expgrav.value;
break;
case pt_blob:
for (i = 0; i < 3; i++)
p->vel[i] += p->vel[i] * dvel;
p->vel[2] -= grav;
break;
case pt_blob2:
for (i = 0; i < 2; i++)
p->vel[i] -= p->vel[i] * dvel;
p->vel[2] -= grav;
break;
case pt_slowgrav:
case pt_grav:
p->vel[2] -= grav;
break;
}
}
#ifndef POLYS
if (classicmesh.numvertexes)
{
classicmesh.numindexes = classicmesh.numvertexes;
BE_DrawMesh_Single(classicshader, &classicmesh, NULL, &classicshader->defaulttextures, 0);
classicmesh.numvertexes = 0;
}
#endif
RSpeedEnd(RSPEED_PARTICLESDRAW);
}
static void Classic_ParticleExplosion (vec3_t org)
{
int i, j;
cparticle_t *p;
int count;
count = 1024 * r_part_density.value;
for (i = 0; i < count; i++)
{
if (!free_particles)
return;
p = free_particles;
free_particles = p->next;
p->next = active_particles;
active_particles = p;
p->die = cl.time + 5;
p->rgb = d_8to24rgbtable[ramp1[0]];
p->ramp = rand() & 3;
if (i & 1)
{
p->type = pt_explode;
for (j = 0; j < 3; j++)
{
p->org[j] = org[j] + ((rand() % 32) - 16);
p->vel[j] = (rand() % 512) - 256;
}
}
else
{
p->type = pt_explode2;
for (j = 0; j < 3; j++)
{
p->org[j] = org[j] + ((rand() % 32) - 16);
p->vel[j] = (rand()%512) - 256;
}
}
}
}
static void Classic_BlobExplosion (vec3_t org)
{
int i, j;
cparticle_t *p;
int count;
count = 1024 * r_part_density.value;
for (i = 0; i < count; i++)
{
if (!free_particles)
return;
p = free_particles;
free_particles = p->next;
p->next = active_particles;
active_particles = p;
p->die = cl.time + 1 + (rand() & 8) * 0.05;
if (i & 1)
{
p->type = pt_blob;
p->rgb = d_8to24rgbtable[66 + rand() % 6];
for (j = 0; j < 3; j++)
{
p->org[j] = org[j] + ((rand() % 32) - 16);
p->vel[j] = (rand() % 512) - 256;
}
}
else
{
p->type = pt_blob2;
p->rgb = d_8to24rgbtable[150 + rand() % 6];
for (j = 0; j < 3; j++)
{
p->org[j] = org[j] + ((rand() % 32) - 16);
p->vel[j] = (rand() % 512) - 256;
}
}
}
}
static void Classic_RunParticleEffect (vec3_t org, vec3_t dir, int color, int count)
{
int i, j, scale;
cparticle_t *p;
if (!dir)
dir = vec3_origin;
scale = (count > 130) ? 3 : (count > 20) ? 2 : 1;
count *= r_part_density.value;
for (i = 0; i < count; i++)
{
if (!free_particles)
return;
p = free_particles;
free_particles = p->next;
p->next = active_particles;
active_particles = p;
p->die = cl.time + 0.1 * (rand() % 5);
p->rgb = d_8to24rgbtable[(color & ~7) + (rand() & 7)];
p->type = pt_grav;
for (j = 0; j < 3; j++)
{
p->org[j] = org[j] + scale * ((rand() & 15) - 8);
p->vel[j] = dir[j] * 15;
}
}
}
static void Classic_LavaSplash (vec3_t org)
{
int i, j, k;
cparticle_t *p;
float vel;
vec3_t dir;
for (i = -16; i < 16; i++)
{
for (j = -16; j < 16; j++)
{
for (k = 0; k < 1; k++)
{
if (!free_particles)
return;
p = free_particles;
free_particles = p->next;
p->next = active_particles;
active_particles = p;
p->die = cl.time + 2 + (rand() & 31) * 0.02;
p->rgb = d_8to24rgbtable[224 + (rand() & 7)];
p->type = pt_grav;
dir[0] = j * 8 + (rand() & 7);
dir[1] = i * 8 + (rand() & 7);
dir[2] = 256;
p->org[0] = org[0] + dir[0];
p->org[1] = org[1] + dir[1];
p->org[2] = org[2] + (rand() & 63);
VectorNormalizeFast (dir);
vel = 50 + (rand() & 63);
VectorScale (dir, vel, p->vel);
}
}
}
}
static void Classic_TeleportSplash (vec3_t org)
{
int i, j, k;
cparticle_t *p;
float vel;
vec3_t dir;
int st = 4 / r_part_density.value;
if (st == 0)
st = 1;
for (i = -16; i < 16; i += st)
{
for (j = -16; j < 16; j += st)
{
for (k = -24; k < 32; k += st)
{
if (!free_particles)
return;
p = free_particles;
free_particles = p->next;
p->next = active_particles;
active_particles = p;
p->die = cl.time + 0.2 + (rand() & 7) * 0.02;
p->rgb = d_8to24rgbtable[7 + (rand() & 7)];
p->type = pt_grav;
dir[0] = j * 8;
dir[1] = i * 8;
dir[2] = k * 8;
p->org[0] = org[0] + i + (rand() & 3);
p->org[1] = org[1] + j + (rand() & 3);
p->org[2] = org[2] + k + (rand() & 3);
VectorNormalizeFast (dir);
vel = 50 + (rand() & 63);
VectorScale (dir, vel, p->vel);
}
}
}
}
#define NUMVERTEXNORMALS 162
//vec3_t avelocity = {23, 7, 3};
//float partstep = 0.01;
//float timescale = 0.01;
static vec3_t avelocities[NUMVERTEXNORMALS];
static void Classic_BrightField (vec3_t org)
{
extern float r_avertexnormals[NUMVERTEXNORMALS][3];
float beamlength = 16;
int count;
int i;
cparticle_t *p;
float angle;
float sr, sp, sy, cr, cp, cy;
vec3_t forward;
float dist;
PClassic_ClearPerFrame();
particleframe = cl_framecount;
dist = 64;
count = 50;
if (!avelocities[0][0])
{
for (i=0 ; i<NUMVERTEXNORMALS*3 ; i++)
avelocities[0][i] = (rand()&255) * 0.01;
}
for (i=0 ; i<NUMVERTEXNORMALS ; i++)
{
if (!free_particles)
return;
p = free_particles;
free_particles = p->next;
p->next = active_particles;
active_particles = p;
angle = cl.time * avelocities[i][0];
sy = sin(angle);
cy = cos(angle);
angle = cl.time * avelocities[i][1];
sp = sin(angle);
cp = cos(angle);
angle = cl.time * avelocities[i][2];
sr = sin(angle);
cr = cos(angle);
forward[0] = cp*cy;
forward[1] = cp*sy;
forward[2] = -sp;
p->die = cl.time;// + 0.01;
p->rgb = d_8to24rgbtable[0x6f];
p->type = pt_oneframe;
p->org[0] = org[0] + r_avertexnormals[i][0]*dist + forward[0]*beamlength;
p->org[1] = org[1] + r_avertexnormals[i][1]*dist + forward[1]*beamlength;
p->org[2] = org[2] + r_avertexnormals[i][2]*dist + forward[2]*beamlength;
}
}
//svc_tempentity support: this is the function that handles 'special' point effects.
//use the trail state so fast/slow frames keep the correct particle counts on certain every-frame effects
static int PClassic_RunParticleEffectState (vec3_t org, vec3_t dir, float count, int typenum, trailstate_t **tsk)
{
switch(typenum)
{
case BRIGHTFIELD_POINT:
Classic_BrightField(org);
break;
case BLOBEXPLOSION_POINT:
Classic_BlobExplosion(org);
break;
case LAVASPLASH_POINT:
Classic_LavaSplash(org);
break;
case EXPLOSION_POINT:
Classic_ParticleExplosion(org);
break;
case TELEPORTSPLASH_POINT:
Classic_TeleportSplash(org);
break;
case MUZZLEFLASH_POINT:
{
dlight_t *dl = CL_AllocDlight (0);
if (dir)
VectorCopy(dir, dl->axis[0]);
else
VectorSet(dir, 0, 0, 1);
VectorVectors(dl->axis[0], dl->axis[1], dl->axis[2]);
VectorInverse(dl->axis[1]);
if (dir)
VectorMA (org, 15, dl->axis[0], dl->origin);
else
VectorCopy (org, dl->origin);
dl->radius = 200 + (rand()&31);
dl->minlight = 32;
dl->die = cl.time + 0.1;
dl->color[0] = 1.5;
dl->color[1] = 1.3;
dl->color[2] = 1.0;
dl->channelfade[0] = 1.5;
dl->channelfade[1] = 0.75;
dl->channelfade[2] = 0.375;
dl->decay = 1000;
#ifdef RTLIGHTS
dl->lightcolourscales[2] = 4;
#endif
}
break;
default:
return 1;
}
return 0;
}
static float Classic_ParticleTrail (vec3_t start, vec3_t end, float leftover, effect_type_t type)
{
vec3_t point, delta, dir;
float len, rlen, scale;
int i, j, num_particles;
cparticle_t *p;
static int tracercount;
if (type >= BRIGHTFIELD_POINT)
{
PClassic_RunParticleEffectState(end, vec3_origin, 1, type, NULL);
return 0;
}
VectorCopy (start, point);
VectorSubtract (end, start, delta);
if (!(len = VectorLength (delta)))
goto done;
VectorScale(delta, 1 / len, dir); //unit vector in direction of trail
VectorMA(point, -leftover, dir, point);
len += leftover;
rlen = len;
switch (type)
{
case ALT_ROCKET_TRAIL:
scale = 1.5; break;
case BLOOD_TRAIL:
scale = 6; break;
default:
scale = 3; break;
rewrote ban code, merging bans+nonbans+cuffs+mute+cripple+deaf+lagged+vip. added timeouts. new penalties have no dedicated command. use the addip command for it. maplist command now generates links. implemented skin objects for q3. added a csqc builtin for it. also supports compositing skins. playing demos inside zips/pk3s/paks should now work. bumped default rate cvar. added cl_transfer to attempt to connect to a new server without disconnecting first. rewrote fog command. alpha and mindist arguments are now supported. fog change also happens over a short time period. added new args to the showpic console command. can now create clickable items for touchscreen/absmouse users. fixed menus to properly support right-aligned text. this finally fixes variable-width fonts. rewrote console tab completion suggestions display. now clickable links. strings obtained from qc are now marked as const. this has required quite a few added consts all over the place. probably crappy attempt at adding joypad support to the sdl port. no idea if it works. changed key bind event code. buttons now track which event they should trigger when released, instead of being the same one the whole time. this allows +forward etc clickable buttons on screen. Also simplified modifier keys - they no longer trigger random events when pressing the modifier key itself. Right modifiers can now be bound separately from left modifiers. Right will use left's binding if not otherwise bound. Bind assumes left if there's no prefix. multiplayer->setup->network menu no longer crashes. added rgb colours to the translation view (but not to the colour-changing keys). added modelviewer command to view models. added menu_mods menu to switch mods in a more friendly way. will be shown by default if multiple manifests exist in the binarydir. clamped classic tracer density. scrag particles no longer look quite so buggy. added ifdefs to facilitate a potential winrt port. the engine should now have no extra dependencies, but still needs system code+audio drivers to be written. if it can't set a renderer, it'll now try to use *every* renderer until it finds one that works. added experimental mapcluster server mode (that console command). New maps will be started up as required. rewrote skeletal blending code a bit. added cylinder geomtypes. fix cfg_save writing to the wrong path bug. VFS_CLOSE now returns a boolean. false means there was some sort of fatal error (either crc when reading was bad, or the write got corrupted or something). Typically ignorable, depends how robust you want to be. win32 tls code now supports running as a server. added connect tls://address support, as well as equivalent sv_addport support. exposed basic model loading api to plugins. d3d11 backend now optionally supports tessellation hlsl. no suitable hlsl provided by default. !!tess to enable. attempted to add gamma ramp support for d3d11. added support for shader blobs to speed up load times. r_shaderblobs 1 to enable. almost vital for d3d11. added vid_srgb cvar. shadowless lights are no longer disabled if shadows are not supported. attempt to add support for touchscreens in win7/8. Wrote gimmicky lua support, using lua instead of ssqc. define VM_LUA to enable. updated saved game code. can again load saved games from vanilla-like engines. changed scale clamping. 0.0001 should no longer appear as 1. changed default mintic from 0.03 to 0.013 to match vanilla qw. I don't know why it was at 0.03. probably a typo. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4623 fc73d0e0-1445-4013-8a0c-d673dee63da5
2014-03-30 09:55:06 +01:00
case TRACER1_TRAIL:
case TRACER2_TRAIL:
scale = (r_part_density.value < 0.5)?6*r_part_density.value:3;
break;
}
scale /= r_part_density.value;
VectorScale (dir, scale, dir);
len /= scale;
leftover = rlen - ((int)(len) * scale);
num_particles = (int) len;
for (i = 0; i < num_particles && free_particles; i++)
{
p = free_particles;
free_particles = p->next;
p->next = active_particles;
active_particles = p;
VectorClear (p->vel);
p->die = cl.time + 2;
switch(type)
{
case GRENADE_TRAIL:
p->ramp = (rand() & 3) + 2;
p->rgb = d_8to24rgbtable[ramp3[(int) p->ramp]];
p->type = pt_fire;
for (j = 0; j < 3; j++)
p->org[j] = point[j] + ((rand() % 6) - 3);
break;
case BLOOD_TRAIL:
p->type = pt_slowgrav;
p->rgb = d_8to24rgbtable[67 + (rand() & 3)];
for (j = 0; j < 3; j++)
p->org[j] = point[j] + ((rand() % 6) - 3);
break;
case BIG_BLOOD_TRAIL:
p->type = pt_slowgrav;
p->rgb = d_8to24rgbtable[67 + (rand() & 3)];
for (j = 0; j < 3; j++)
p->org[j] = point[j] + ((rand() % 6) - 3);
break;
case TRACER1_TRAIL:
case TRACER2_TRAIL:
p->die = cl.time + 0.5;
p->type = pt_static;
if (type == TRACER1_TRAIL)
p->rgb = d_8to24rgbtable[52 + ((tracercount & 4) << 1)];
else
p->rgb = d_8to24rgbtable[230 + ((tracercount & 4) << 1)];
tracercount++;
VectorCopy (point, p->org);
if (tracercount & 1)
{
p->vel[0] = 90 * dir[1];
p->vel[1] = 90 * -dir[0];
}
else
{
p->vel[0] = 90 * -dir[1];
p->vel[1] = 90 * dir[0];
}
break;
case VOOR_TRAIL:
p->rgb = d_8to24rgbtable[9 * 16 + 8 + (rand() & 3)];
p->type = pt_static;
p->die = cl.time + 0.3;
for (j = 0; j < 3; j++)
p->org[j] = point[j] + ((rand() & 15) - 8);
break;
case ALT_ROCKET_TRAIL:
p->ramp = (rand() & 3);
p->rgb = d_8to24rgbtable[ramp3[(int) p->ramp]];
p->type = pt_fire;
for (j = 0; j < 3; j++)
p->org[j] = point[j] + ((rand() % 6) - 3);
break;
case ROCKET_TRAIL:
default:
p->ramp = (rand() & 3);
p->rgb = d_8to24rgbtable[ramp3[(int) p->ramp]];
p->type = pt_fire;
for (j = 0; j < 3; j++)
p->org[j] = point[j] + ((rand() % 6) - 3);
break;
}
VectorAdd (point, dir, point);
}
done:
return leftover;
}
//builds a trail from here to there. The trail state can be used to remember how far you got last frame.
static int PClassic_ParticleTrail (vec3_t startpos, vec3_t end, int type, int dlkey, vec3_t dlaxis[3], trailstate_t **tsk)
{
float leftover;
if (type == P_INVALID)
return 1;
leftover = Classic_ParticleTrail(startpos, end, Classic_GetLeftover(tsk), type);
Classic_SetLeftover(tsk, leftover);
return 0;
}
//svc_particle support: add X particles with the given colour, velocity, and aproximate origin.
static void PClassic_RunParticleEffect (vec3_t org, vec3_t dir, int color, int count)
{
Classic_RunParticleEffect(org, dir, color, count);
}
particleengine_t pe_classic =
{
"Classic",
NULL,
PClassic_FindParticleType,
PClassic_Query,
PClassic_RunParticleEffectTypeString,
PClassic_ParticleTrail,
PClassic_RunParticleEffectState,
PClassic_RunParticleWeather,
PClassic_RunParticleCube,
PClassic_RunParticleEffect,
PClassic_RunParticleEffect2,
PClassic_RunParticleEffect3,
PClassic_RunParticleEffect4,
PClassic_ParticleTrailIndex,
PClassic_EmitSkyEffectTris,
PClassic_InitParticles,
PClassic_ShutdownParticles,
PClassic_DelinkTrailstate,
PClassic_ClearParticles,
PClassic_DrawParticles
};
#endif