Add support for top/bottom color on players and viewmodels.

Fix func_breakable's sound shader from precaching non existing sounds.
This commit is contained in:
Marco Cawthorne 2021-05-20 16:01:07 +02:00
parent 3b36834b93
commit 09528c2944
8 changed files with 362 additions and 212 deletions

View File

@ -33,6 +33,45 @@ If the compiler isn't found it will ask you to build them.
For best results, symlink the desired scripts into your home directory's bin folder.
The scripts are designed to be aware of their actual location in the filesystem.
## Dependencies
Rough list of dependencies for the average Linux system.
On some systems the names may slightly differ. These should be correct for OpenSUSE.
### Engine
* subversion
* gmake
* gcc
* mesa-libGL-devel
* libgnutls-devel
* libopenal-devel
* libX11-devel
* libXcursor-devel
* libXrandr-devel
* libSDL2-devel (only if you pass BUILD_SDL2=1 to build_engine.sh)
For WinNT and Darwin systems it's recommended you use the SDL2 backend, but native backends
may be available in FTEQW.
The X development packages are obviously only a requirement for when you do not compile an SDL2 build on a UNIX-like system.
### FFMPEG Plugin
* ffmpeg-4-libavformat-devel
* ffmpeg-4-libswscale-devel
You want this plugin if you want playback of a variety of media formats, including video decoding.
### Worldspawn Level Editor
* cmake
* gcc-c++
* gtk2-devel
* gtkglext-devel
* libxml2-devel
* libjpeg8-devel
* minizip-devel
This is the only component that requires a C++ compiler.
## Support
Join us on irc.vera-visions.com and chat if you're interested in using this in production.
**All this is provided to you for free as-is otherwise.**

View File

@ -23,7 +23,7 @@ enumflags
PLAYER_ORIGIN_Z,
PLAYER_ANGLES_X,
PLAYER_ANGLES_Y,
PLAYER_ANGLES_Z,
PLAYER_COLORMAP,
PLAYER_VELOCITY,
PLAYER_VELOCITY_Z,
PLAYER_FLAGS,

View File

@ -1,200 +1,210 @@
!!ver 130
!!permu FRAMEBLEND
!!permu SKELETAL
!!permu FOG
!!samps diffuse reflectcube
!!cvardf gl_affinemodels=0
!!cvardf gl_ldr=1
!!cvardf gl_halflambert=1
!!cvardf gl_mono=0
!!cvardf gl_kdither=0
!!cvardf gl_stipplealpha=0
!!permu FAKESHADOWS
!!cvardf r_glsl_pcf
!!samps =FAKESHADOWS shadowmap
!!cvardf r_skipDiffuse
#include "sys/defs.h"
#include "sys/fog.h"
#if gl_affinemodels == 1
#define affine noperspective
#else
#define affine
#endif
#ifdef REFLECTCUBE
varying vec3 eyevector;
varying mat3 invsurface;
#endif
#ifdef FAKESHADOWS
varying vec4 vtexprojcoord;
#endif
affine varying vec2 tex_c;
varying vec3 light;
#ifdef VERTEX_SHADER
#include "sys/skeletal.h"
float lambert( vec3 normal, vec3 dir ) {
return dot( normal, dir );
}
float halflambert( vec3 normal, vec3 dir ) {
return ( dot( normal, dir ) * 0.5 ) + 0.5;
}
#ifdef CHROME
/* Rotate Light Vector */
vec3 rlv(vec3 axis, vec3 origin, vec3 lightpoint)
{
vec3 offs;
vec3 result;
offs[0] = lightpoint[0] - origin[0];
offs[1] = lightpoint[1] - origin[1];
offs[2] = lightpoint[2] - origin[2];
result[0] = dot(offs[0], axis[0]);
result[1] = dot(offs[1], axis[1]);
result[2] = dot(offs[2], axis[2]);
return result;
}
#endif
void main ()
{
vec3 n, s, t, w;
gl_Position = skeletaltransform_wnst(w,n,s,t);
tex_c = v_texcoord;
#if gl_halflambert==1
light = e_light_ambient + (e_light_mul * halflambert(n, e_light_dir));
#else
light = e_light_ambient + (e_light_mul * lambert(n, e_light_dir));
#endif
light *= e_lmscale.r;
#if gl_ldr==1
light *= 0.75;
#endif
#ifdef CHROME
vec3 rorg = rlv(vec3(0,0,0), w, e_light_dir);
vec3 viewc = normalize(rorg - w);
float d = dot(n, viewc);
vec3 reflected;
reflected.x = n.x * 2.0 * d - viewc.x;
reflected.y = n.y * 2.0 * d - viewc.y;
reflected.z = n.z * 2.0 * d - viewc.z;
tex_c.x = 0.5 + reflected.y * 0.5;
tex_c.y = 0.5 - reflected.z * 0.5;
#endif
#ifdef REFLECTCUBE
invsurface[0] = v_svector;
invsurface[1] = v_tvector;
invsurface[2] = v_normal;
vec3 eyeminusvertex = e_eyepos - v_position.xyz;
eyevector.x = dot( eyeminusvertex, v_svector.xyz );
eyevector.y = dot( eyeminusvertex, v_tvector.xyz );
eyevector.z = dot( eyeminusvertex, v_normal.xyz );
#endif
}
#endif
#ifdef FRAGMENT_SHADER
#include "sys/pcf.h"
vec4 kernel_dither(sampler2D targ, vec2 texc)
{
int x = int(mod(gl_FragCoord.x, 2.0));
int y = int(mod(gl_FragCoord.y, 2.0));
int index = x + y * 2;
vec2 coord_ofs;
vec2 size;
size.x = 1.0 / textureSize(targ, 0).x;
size.y = 1.0 / textureSize(targ, 0).y;
if (index == 0)
coord_ofs = vec2(0.25f, 0.0f);
else if (index == 1)
coord_ofs = vec2(0.50f, 0.75f);
else if (index == 2)
coord_ofs = vec2(0.75f, 0.50f);
else if (index == 3)
coord_ofs = vec2(0.00f, 0.25f);
return texture2D(targ, texc + coord_ofs * size);
}
void main ()
{
vec4 diffuse_f;
#if r_skipDiffuse==1
diffuse_f = vec4(1.0, 1.0, 1.0, 1.0);
#else
#if gl_kdither==1
diffuse_f = kernel_dither(s_diffuse, tex_c);
#else
diffuse_f = texture2D(s_diffuse, tex_c);
#endif
#endif
diffuse_f.rgb *= light;
#ifdef REFLECTCUBE
vec3 cube_c;
vec4 out_f = vec4( 1.0, 1.0, 1.0, 1.0 );
cube_c = reflect( normalize( -eyevector ), vec3( 0, 0, 1 ) );
cube_c = cube_c.x * invsurface[0] + cube_c.y * invsurface[1] + cube_c.z * invsurface[2];
cube_c = ( m_model * vec4( cube_c.xyz, 0.0 ) ).xyz;
out_f.rgb = mix( textureCube( s_reflectcube, cube_c ).rgb, diffuse_f.rgb, diffuse_f.a );
diffuse_f = out_f;
#endif
diffuse_f *= e_colourident;
#if gl_stipplealpha==1
float alpha = e_colourident.a;
int x = int(mod(gl_FragCoord.x, 2.0));
int y = int(mod(gl_FragCoord.y, 2.0));
if (alpha <= 0.0) {
discard;
} else if (alpha <= 0.25) {
diffuse_f.a = 1.0f;
if (x + y == 2)
discard;
if (x + y == 1)
discard;
} else if (alpha <= 0.5) {
diffuse_f.a = 1.0f;
if (x + y == 2)
discard;
if (x + y == 0)
discard;
} else if (alpha < 1.0) {
diffuse_f.a = 1.0f;
if (x + y == 2)
discard;
}
#endif
#if gl_mono==1
float bw = (diffuse_f.r + diffuse_f.g + diffuse_f.b) / 3.0;
diffuse_f.rgb = vec3(bw, bw, bw);
#endif
#ifdef FAKESHADOWS
diffuse_f.rgb *= ShadowmapFilter(s_shadowmap, vtexprojcoord);
#endif
gl_FragColor = fog4(diffuse_f);
}
#endif
!!ver 130
!!permu FRAMEBLEND
!!permu SKELETAL
!!permu UPPERLOWER
!!permu FOG
!!samps diffuse reflectcube upper lower
!!cvardf gl_affinemodels=0
!!cvardf gl_ldr=1
!!cvardf gl_halflambert=1
!!cvardf gl_mono=0
!!cvardf gl_kdither=0
!!cvardf gl_stipplealpha=0
!!permu FAKESHADOWS
!!cvardf r_glsl_pcf
!!samps =FAKESHADOWS shadowmap
!!cvardf r_skipDiffuse
#include "sys/defs.h"
#include "sys/fog.h"
#if gl_affinemodels == 1
#define affine noperspective
#else
#define affine
#endif
#ifdef REFLECTCUBE
varying vec3 eyevector;
varying mat3 invsurface;
#endif
#ifdef FAKESHADOWS
varying vec4 vtexprojcoord;
#endif
affine varying vec2 tex_c;
varying vec3 light;
#ifdef VERTEX_SHADER
#include "sys/skeletal.h"
float lambert( vec3 normal, vec3 dir ) {
return dot( normal, dir );
}
float halflambert( vec3 normal, vec3 dir ) {
return ( dot( normal, dir ) * 0.5 ) + 0.5;
}
#ifdef CHROME
/* Rotate Light Vector */
vec3 rlv(vec3 axis, vec3 origin, vec3 lightpoint)
{
vec3 offs;
vec3 result;
offs[0] = lightpoint[0] - origin[0];
offs[1] = lightpoint[1] - origin[1];
offs[2] = lightpoint[2] - origin[2];
result[0] = dot(offs[0], axis[0]);
result[1] = dot(offs[1], axis[1]);
result[2] = dot(offs[2], axis[2]);
return result;
}
#endif
void main ()
{
vec3 n, s, t, w;
gl_Position = skeletaltransform_wnst(w,n,s,t);
tex_c = v_texcoord;
#if gl_halflambert==1
light = e_light_ambient + (e_light_mul * halflambert(n, e_light_dir));
#else
light = e_light_ambient + (e_light_mul * lambert(n, e_light_dir));
#endif
light *= e_lmscale.r;
#if gl_ldr==1
light *= 0.75;
#endif
#ifdef CHROME
vec3 rorg = rlv(vec3(0,0,0), w, e_light_dir);
vec3 viewc = normalize(rorg - w);
float d = dot(n, viewc);
vec3 reflected;
reflected.x = n.x * 2.0 * d - viewc.x;
reflected.y = n.y * 2.0 * d - viewc.y;
reflected.z = n.z * 2.0 * d - viewc.z;
tex_c.x = 0.5 + reflected.y * 0.5;
tex_c.y = 0.5 - reflected.z * 0.5;
#endif
#ifdef REFLECTCUBE
invsurface[0] = v_svector;
invsurface[1] = v_tvector;
invsurface[2] = v_normal;
vec3 eyeminusvertex = e_eyepos - v_position.xyz;
eyevector.x = dot( eyeminusvertex, v_svector.xyz );
eyevector.y = dot( eyeminusvertex, v_tvector.xyz );
eyevector.z = dot( eyeminusvertex, v_normal.xyz );
#endif
}
#endif
#ifdef FRAGMENT_SHADER
#include "sys/pcf.h"
vec4 kernel_dither(sampler2D targ, vec2 texc)
{
int x = int(mod(gl_FragCoord.x, 2.0));
int y = int(mod(gl_FragCoord.y, 2.0));
int index = x + y * 2;
vec2 coord_ofs;
vec2 size;
size.x = 1.0 / textureSize(targ, 0).x;
size.y = 1.0 / textureSize(targ, 0).y;
if (index == 0)
coord_ofs = vec2(0.25f, 0.0f);
else if (index == 1)
coord_ofs = vec2(0.50f, 0.75f);
else if (index == 2)
coord_ofs = vec2(0.75f, 0.50f);
else if (index == 3)
coord_ofs = vec2(0.00f, 0.25f);
return texture2D(targ, texc + coord_ofs * size);
}
void main ()
{
vec4 diffuse_f;
#if r_skipDiffuse==1
diffuse_f = vec4(1.0, 1.0, 1.0, 1.0);
#else
#if gl_kdither==1
diffuse_f = kernel_dither(s_diffuse, tex_c);
#else
diffuse_f = texture2D(s_diffuse, tex_c);
#endif
#endif
#ifdef UPPER
vec4 uc = texture2D(s_upper, tex_c);
diffuse_f.rgb += uc.rgb*e_uppercolour*uc.a;
#endif
#ifdef LOWER
vec4 lc = texture2D(s_lower, tex_c);
diffuse_f.rgb += lc.rgb*e_lowercolour*lc.a;
#endif
diffuse_f.rgb *= light;
#ifdef REFLECTCUBE
vec3 cube_c;
vec4 out_f = vec4( 1.0, 1.0, 1.0, 1.0 );
cube_c = reflect( normalize( -eyevector ), vec3( 0, 0, 1 ) );
cube_c = cube_c.x * invsurface[0] + cube_c.y * invsurface[1] + cube_c.z * invsurface[2];
cube_c = ( m_model * vec4( cube_c.xyz, 0.0 ) ).xyz;
out_f.rgb = mix( textureCube( s_reflectcube, cube_c ).rgb, diffuse_f.rgb, diffuse_f.a );
diffuse_f = out_f;
#endif
diffuse_f *= e_colourident;
#if gl_stipplealpha==1
float alpha = e_colourident.a;
int x = int(mod(gl_FragCoord.x, 2.0));
int y = int(mod(gl_FragCoord.y, 2.0));
if (alpha <= 0.0) {
discard;
} else if (alpha <= 0.25) {
diffuse_f.a = 1.0f;
if (x + y == 2)
discard;
if (x + y == 1)
discard;
} else if (alpha <= 0.5) {
diffuse_f.a = 1.0f;
if (x + y == 2)
discard;
if (x + y == 0)
discard;
} else if (alpha < 1.0) {
diffuse_f.a = 1.0f;
if (x + y == 2)
discard;
}
#endif
#if gl_mono==1
float bw = (diffuse_f.r + diffuse_f.g + diffuse_f.b) / 3.0;
diffuse_f.rgb = vec3(bw, bw, bw);
#endif
#ifdef FAKESHADOWS
diffuse_f.rgb *= ShadowmapFilter(s_shadowmap, vtexprojcoord);
#endif
gl_FragColor = fog4(diffuse_f);
}
#endif

View File

@ -53,7 +53,6 @@ func_breakable.impact_cinder
sample debris/concrete1.wav
sample debris/concrete2.wav
sample debris/concrete3.wav
sample debris/concrete4.wav
}
func_breakable.impact_concrete
@ -68,5 +67,4 @@ func_breakable.impact_rock
sample debris/concrete1.wav
sample debris/concrete2.wav
sample debris/concrete3.wav
sample debris/concrete4.wav
}

View File

@ -170,6 +170,7 @@ View_DrawViewModel(void)
makevectors(view_angles);
m_eViewModel.angles = view_angles;
m_eViewModel.colormap = pSeat->m_ePlayer.colormap;
// Give the gun a tilt effect like in old HL/CS versions
if (autocvar_v_bobclassic == 1) {

View File

@ -20,6 +20,8 @@ CMainButton cz_btnAdvanced;
CTextBox cz_tbNetname;
CPictureSwitch cz_psSpray;
CPictureSwitch cz_psModel;
CSlider cz_sldTopcolor;
CSlider cz_sldBottomcolor;
string *g_models;
int g_modelcount;
@ -77,6 +79,82 @@ cz_cbSprayChanged(void)
localcmd(sprintf("setinfoblob spray %s\n", mdl));
}
vector hsv2rgb(float h, float s, float v)
{
float i,f,p,q,t;
vector col = [0,0,0];
h = max(0.0, min(360.0, h));
s = max(0.0, min(100.0, s));
v = max(0.0, min(100.0, v));
s /= 100;
v /= 100;
if (s == 0) {
col[0] = col[1] = col[2] = rint(v*255);
return col;
}
h /= 60;
i = floor(h);
f = h - i;
p = v * (1 - s);
q = v * (1 - s * f);
t = v * (1 - s * (1 - f));
switch (i) {
case 0:
col[0] = rint(255*v);
col[1] = rint(255*t);
col[2] = rint(255*p);
break;
case 1:
col[0] = rint(255*q);
col[1] = rint(255*v);
col[2] = rint(255*p);
break;
case 2:
col[0] = rint(255*p);
col[1] = rint(255*v);
col[2] = rint(255*t);
break;
case 3:
col[0] = rint(255*p);
col[1] = rint(255*q);
col[2] = rint(255*v);
break;
case 4:
col[0] = rint(255*t);
col[1] = rint(255*p);
col[2] = rint(255*v);
break;
default: // case 5:
col[0] = rint(255*v);
col[1] = rint(255*p);
col[2] = rint(255*q);
}
return col;
}
void
cz_sldTopcolorChanged(float val)
{
vector x = hsv2rgb(val * 360, 100, 100);
float id = x[2] + (x[1] << 8) + (x[0] << 16);
cvar_set("topcolor", sprintf("0x%x", id));
localcmd(sprintf("seta _cl_topcolor %f\n", val));
}
void
cz_sldBottomcolorChanged(float val)
{
vector x = hsv2rgb(val * 360, 100, 100);
float id = x[2] + (x[1] << 8) + (x[0] << 16);
cvar_set("bottomcolor", sprintf("0x%x", id));
localcmd(sprintf("seta _cl_bottomcolor %f\n", val));
}
void
menu_customize_init(void)
{
@ -136,6 +214,19 @@ menu_customize_init(void)
cz_tbNetname.SetPos(212,160);
cz_tbNetname.SetText(cvar_string("name"));
Widget_Add(fn_customize, cz_tbNetname);
cz_sldTopcolor = spawn(CSlider);
cz_sldTopcolor.SetPos(420,400);
cz_sldTopcolor.SetValue(cvar("_cl_topcolor"));
cz_sldTopcolor.SetCallback(cz_sldTopcolorChanged);
Widget_Add(fn_customize, cz_sldTopcolor);
cz_sldBottomcolor = spawn(CSlider);
cz_sldBottomcolor.SetPos(420,420);
cz_sldBottomcolor.SetValue(cvar("_cl_bottomcolor"));
cz_sldBottomcolor.SetCallback(cz_sldBottomcolorChanged);
Widget_Add(fn_customize, cz_sldBottomcolor);
if (games[gameinfo_current].nosprays == 0) {
cz_psSpray = spawn(CPictureSwitch);
@ -171,9 +262,16 @@ menu_customize_draw(void)
WLabel_Static(212, 140, m_reslbl[IDS_PLAYERINFO_NAME], 14, 14, [1,1,1],
1.0f, 0, font_arial);
if (games[gameinfo_current].nomodels == 0)
WLabel_Static(410, 140, sprintf(m_reslbl[IDS_MODEL_NAME], cvar_string("_cl_playermodel")), 14, 14, [1,1,1],
1.0f, 0, font_arial);
if (games[gameinfo_current].nomodels == 0) {
WLabel_Static(410, 140, sprintf(m_reslbl[IDS_MODEL_NAME], cvar_string("_cl_playermodel")), 14, 14, [1,1,1],
1.0f, 0, font_arial);
vector t, b;
t = hsv2rgb(cvar("_cl_topcolor") * 360, 100, 100) / 255;
b = hsv2rgb(cvar("_cl_bottomcolor") * 360, 100, 100) / 255;
drawfill([g_menuofs[0] + 414,g_menuofs[1] + 346], [64,12], t, 0.75f);
drawfill([g_menuofs[0] + 510,g_menuofs[1] + 346], [64,12], b, 0.75f);
}
if (games[gameinfo_current].nosprays == 0)
WLabel_Static(212, 203, m_reslbl[IDS_PROFILE_LOGO], 14, 14, [1,1,1],

View File

@ -41,6 +41,7 @@ base_player
PREDICTED_VECTOR_N(origin);
PREDICTED_VECTOR_N(velocity);
PREDICTED_VECTOR_N(angles);
PREDICTED_FLOAT_N(colormap);
PREDICTED_FLOAT_N(flags);
PREDICTED_FLOAT_N(gflags);
PREDICTED_FLOAT(viewzoom);

View File

@ -52,8 +52,8 @@ base_player::ReceiveEntity(float new, float fl)
pitch = readfloat();
if (fl & PLAYER_ANGLES_Y)
angles[1] = readfloat();
if (fl & PLAYER_ANGLES_Z)
angles[2] = readfloat();
if (fl & PLAYER_COLORMAP)
colormap = readfloat();
if (fl & PLAYER_VELOCITY) {
velocity[0] = readcoord();
@ -106,6 +106,7 @@ base_player::PredictPreFrame(void)
SAVE_STATE(modelindex);
SAVE_STATE(origin);
SAVE_STATE(angles);
SAVE_STATE(colormap);
SAVE_STATE(velocity);
SAVE_STATE(flags);
SAVE_STATE(gflags);
@ -142,6 +143,7 @@ base_player::PredictPostFrame(void)
ROLL_BACK(modelindex);
ROLL_BACK(origin);
ROLL_BACK(angles);
ROLL_BACK(colormap);
ROLL_BACK(velocity);
ROLL_BACK(flags);
ROLL_BACK(gflags);
@ -193,8 +195,8 @@ base_player::EvaluateEntity(void)
if (VEC_CHANGED(angles, 1))
SendFlags |= PLAYER_ANGLES_Y;
if (VEC_CHANGED(angles, 2))
SendFlags |= PLAYER_ANGLES_Z;
if (ATTR_CHANGED(colormap))
SendFlags |= PLAYER_COLORMAP;
if (VEC_CHANGED(velocity, 0))
SendFlags |= PLAYER_VELOCITY;
@ -232,6 +234,7 @@ base_player::EvaluateEntity(void)
SAVE_STATE(modelindex);
SAVE_STATE(origin);
SAVE_STATE(angles);
SAVE_STATE(colormap);
SAVE_STATE(velocity);
SAVE_STATE(flags);
SAVE_STATE(gflags);
@ -281,8 +284,8 @@ base_player::SendEntity(entity ePEnt, float fChanged)
WriteFloat(MSG_ENTITY, v_angle[0]);
if (fChanged & PLAYER_ANGLES_Y)
WriteFloat(MSG_ENTITY, angles[1]);
if (fChanged & PLAYER_ANGLES_Z)
WriteFloat(MSG_ENTITY, angles[2]);
if (fChanged & PLAYER_COLORMAP)
WriteFloat(MSG_ENTITY, colormap);
/* similar as with origin, we separate x/y from z */
if (fChanged & PLAYER_VELOCITY) {