mirror of
https://github.com/nzp-team/quakec.git
synced 2024-11-26 22:02:20 +00:00
12a2633738
Adds proper gun recoil to FTE, as well as moves spread calculation to be relative to crosshairs. CSQC's crosshair values are now accurate to World at War as well. Weapons are also much more precise ADS, so the Kar is more viable. Shotguns also no longer reduce spread when ADS, in parity with World at War :^)
1183 lines
31 KiB
C++
1183 lines
31 KiB
C++
/*
|
|
client/main.qc
|
|
|
|
main csqc code
|
|
|
|
Copyright (C) 2021 NZ:P Team
|
|
|
|
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 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:
|
|
|
|
Free Software Foundation, Inc.
|
|
59 Temple Place - Suite 330
|
|
Boston, MA 02111-1307, USA
|
|
|
|
*/
|
|
|
|
void() ToggleMenu =
|
|
{
|
|
if(serverkey("constate") != "disconnected")
|
|
{
|
|
if (player_count == 0)
|
|
localcmd("cmd pause\n");
|
|
if(in_menu == MENU_NONE)
|
|
{
|
|
in_menu = MENU_PAUSE;
|
|
time_in_menu = 0;
|
|
local float i;
|
|
for(i = 0; i < BUTTONS_COUNT; i++)
|
|
{
|
|
buttons[i].active = 1;
|
|
}
|
|
setcursormode(TRUE, cvar_string("cl_cursor"), __NULL__, cvar("cl_cursor_scale"));
|
|
}
|
|
else
|
|
{
|
|
in_menu = MENU_NONE;
|
|
setcursormode(FALSE);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
in_menu = MENU_MAIN;
|
|
time_in_menu = 0;
|
|
setcursormode(TRUE, cvar_string("cl_cursor"), __NULL__, cvar("cl_cursor_scale"));
|
|
}
|
|
}
|
|
|
|
noref void(float apiver, string enginename, float enginever) CSQC_Init =
|
|
{
|
|
setwindowcaption("Nazi Zombies: Portable");
|
|
|
|
precache_sound("sounds/menu/enter.wav");
|
|
precache_sound("sounds/menu/navigate.wav");
|
|
|
|
registercommand("togglemenu");
|
|
registercommand("startwalk");
|
|
registercommand("stopwalk");
|
|
registercommand("promptjoin");
|
|
registercommand("showscores");
|
|
|
|
cvar_set("sv_cheats", ftos(1));
|
|
autocvar(r_viewmodel_default_fov, 70);
|
|
|
|
// Runtime check if we're running this in WebASM/WebGL.
|
|
if (cvar_string("sys_platform") == "Web")
|
|
platform_is_web = true;
|
|
else
|
|
platform_is_web = false;
|
|
|
|
//print("CSQC Started\n");
|
|
dummy = spawn();
|
|
if(serverkey("constate") == "disconnected")
|
|
ToggleMenu();
|
|
//bgpos = 0;
|
|
|
|
// default button binds
|
|
|
|
buttonBind[0] = "+forward";
|
|
buttonBind[1] = "+back";
|
|
buttonBind[2] = "+moveleft";
|
|
buttonBind[3] = "+moveright";
|
|
buttonBind[4] = "impulse 10";
|
|
buttonBind[5] = "+sprint";
|
|
buttonBind[6] = "impulse 30";
|
|
buttonBind[7] = "impulse 110";
|
|
buttonBind[8] = "impulse 111";
|
|
buttonBind[9] = "+button7";
|
|
buttonBind[10] = "+button5";
|
|
buttonBind[11] = "+button6";
|
|
buttonBind[12] = "+button3";
|
|
buttonBind[13] = "impulse 25";
|
|
|
|
// intialize screen resolutions
|
|
|
|
// default/current width and height
|
|
active_swidth = cvar("vid_width");
|
|
active_sheight = cvar("vid_height");
|
|
fullscreenval = cvar("vid_fullscreen");
|
|
|
|
// 5:4
|
|
screen_width_54[0] = 1280;
|
|
screen_height_54[0] = 1024;
|
|
//4:3
|
|
screen_width_43[0] = 640;
|
|
screen_height_43[0] = 480;
|
|
screen_width_43[1] = 800;
|
|
screen_height_43[1] = 600;
|
|
screen_width_43[2] = 1024;
|
|
screen_height_43[2] = 768;
|
|
//16:10
|
|
screen_width_1610[0] = 1280;
|
|
screen_height_1610[0] = 800;
|
|
screen_width_1610[1] = 1440;
|
|
screen_height_1610[1] = 900;
|
|
screen_width_1610[2] = 1680;
|
|
screen_height_1610[2] = 1050;
|
|
screen_width_1610[3] = 1920;
|
|
screen_height_1610[3] = 1200;
|
|
screen_width_1610[4] = 2560;
|
|
screen_height_1610[4] = 1600;
|
|
//16:9
|
|
screen_width_169[0] = 640;
|
|
screen_height_169[0] = 360;
|
|
screen_width_169[1] = 1280;
|
|
screen_height_169[1] = 720;
|
|
screen_width_169[2] = 1360;
|
|
screen_height_169[2] = 768;
|
|
screen_width_169[3] = 1366;
|
|
screen_height_169[3] = 768;
|
|
screen_width_169[4] = 1536;
|
|
screen_height_169[4] = 864;
|
|
screen_width_169[5] = 1600;
|
|
screen_height_169[5] = 900;
|
|
screen_width_169[6] = 1920;
|
|
screen_height_169[6] = 1080;
|
|
screen_width_169[7] = 2048;
|
|
screen_height_169[7] = 1152;
|
|
screen_width_169[8] = 2560;
|
|
screen_height_169[8] = 1440;
|
|
screen_width_169[9] = 3840;
|
|
screen_height_169[9] = 2160;
|
|
//21:9
|
|
screen_width_219[0] = 2560;
|
|
screen_height_219[0] = 1080;
|
|
screen_width_219[1] = 3440;
|
|
screen_height_219[1] = 1440;
|
|
|
|
// cvars for custom settings
|
|
cvar_set("cl_adsmode", "0");
|
|
cvar_set("cl_cinematic", "0");
|
|
cvar_set("nzp_particles", "1");
|
|
cvar_set("nzp_decals", "1");
|
|
|
|
// per-channel volume
|
|
cvar_set("snd_channel1volume", "1");
|
|
cvar_set("snd_channel2volume", "1");
|
|
cvar_set("snd_channel3volume", "1");
|
|
cvar_set("snd_channel4volume", "1");
|
|
cvar_set("snd_channel5volume", "1");
|
|
cvar_set("snd_channel6volume", "1");
|
|
|
|
// force nearest filtering for hud elements to avoid blur
|
|
cvar_set("gl_texturemode2d", "gl_nearest");
|
|
cvar_set("r_font_linear", "0");
|
|
|
|
// force build date text in menu
|
|
cvar_set("cl_showbuildtime", "1");
|
|
|
|
// retrieve custom maps
|
|
Customs_Get();
|
|
|
|
//
|
|
// get the build date
|
|
//
|
|
float file = fopen("version.txt", FILE_READ);
|
|
|
|
if (file != -1) {
|
|
build_datetime = fgets(file);
|
|
fclose(file);
|
|
}
|
|
};
|
|
|
|
noref void() CSQC_WorldLoaded =
|
|
{
|
|
//precache_model("models/weapons/mg/mzl.iqm");
|
|
//precache_model("models/blood.iqm");
|
|
|
|
if(!player)
|
|
player = edict_num(player_localnum);
|
|
if(!vmodel)
|
|
vmodel = spawn();
|
|
if(!v2model)
|
|
v2model = spawn();
|
|
if(!mzlflash)
|
|
mzlflash = spawn();
|
|
|
|
v2model.renderflags = vmodel.renderflags = RF_VIEWMODEL;
|
|
v2model.origin = vmodel.origin = '24 -12 -18';
|
|
v2model_targetpos = v2model_currentpos = v2model.origin = vmodel_targetpos = vmodel_currentpos = vmodel.origin;
|
|
v2model_velocity = vmodel_velocity = '0 0 0';
|
|
//v2model_muzzleoffset = vmodel_muzzleoffset = '48 -1 2';
|
|
setmodel(vmodel,"");
|
|
setmodel(v2model,"");
|
|
mzlflash.renderflags = vmodel.renderflags;
|
|
mzlflash.origin = vmodel.origin + vmodel_muzzleoffset;
|
|
|
|
playerpoints[1] = -1;
|
|
playerpoints[2] = -1;
|
|
playerpoints[3] = -1;
|
|
|
|
Achievement_Init();
|
|
|
|
// Dummy so that our other point particles work!
|
|
pointparticles(particleeffectnum("weapons.impact_decal"), '0 0 0', '0 0 0', 1);
|
|
pointparticles(particleeffectnum("muzzle.muzzle_part0"), '0 0 0', '0 0 0', 1);
|
|
|
|
huddir = "gfx/hud/";
|
|
};
|
|
|
|
// This is from COW lol!
|
|
#define ADS_THOMPSON '-3 +5.80 +4.52'
|
|
|
|
/*vector adsOffset;
|
|
float adsAmount;
|
|
float adsDir;*/
|
|
vector weapon_bob_factor;
|
|
float weapon_bob_factor_z_coef;
|
|
vector dampening_factor;
|
|
float vaccel;
|
|
float vzaccel;
|
|
void() Update_Vmodel =
|
|
{
|
|
local vector offset, adsoffset;
|
|
local vector dir;
|
|
local float ads;
|
|
|
|
if (cvar("r_drawviewmodel") == FALSE) {
|
|
vmodel.origin = '-10000 -10000 -10000';
|
|
return;
|
|
}
|
|
|
|
//Walk bob
|
|
if (getstatf(STAT_WEAPONZOOM)) { //ADS bob
|
|
weapon_bob_factor = '0 0 0';
|
|
dampening_factor = weapon_bob_factor;
|
|
weapon_bob_factor_z_coef = 0;
|
|
} else if (K_FORWARDDOWN || K_BACKDOWN || K_LEFTDOWN || K_RIGHTDOWN && !getstatf(STAT_WEAPONZOOM)) {
|
|
weapon_bob_factor_x = 8;
|
|
weapon_bob_factor_y = 8;
|
|
weapon_bob_factor_z = 13.4;
|
|
weapon_bob_factor_z_coef = 0.2;
|
|
|
|
dampening_factor_x = 0.2*sin(time*weapon_bob_factor_x);
|
|
dampening_factor_y = 0.2*cos(time*weapon_bob_factor_y);
|
|
dampening_factor_z = 0.2*sin(time*weapon_bob_factor_z);
|
|
} else if (!getstatf(STAT_WEAPONZOOM)){ //Still bob
|
|
|
|
// Naievil -- stupid ass calcs...
|
|
// Basically we have a dampening factor per offset and we have to decrease it back down to zero
|
|
// Problem is that we may be going in postive OR negative direction?
|
|
// Better solution: use fabs() lol
|
|
if (dampening_factor_x > 0 && sin(time*weapon_bob_factor_x) > 0) {
|
|
if ((dampening_factor_x - 0.00000068* sin(time*weapon_bob_factor_x)) < 0)
|
|
dampening_factor_x -= (0.00000068 - dampening_factor_x*sin(time*weapon_bob_factor_x));
|
|
else
|
|
dampening_factor_x -= 0.00000068* sin(time*weapon_bob_factor_x);
|
|
|
|
} else if (dampening_factor_x < 0 && sin(time*weapon_bob_factor_x) < 0) {
|
|
if ((dampening_factor_x + 0.00000068* sin(time*weapon_bob_factor_x)) > 0)
|
|
dampening_factor_x += (0.00000068 - dampening_factor_x*sin(time*weapon_bob_factor_x));
|
|
else
|
|
dampening_factor_x += 0.00000068* sin(time*weapon_bob_factor_x);
|
|
} else {
|
|
weapon_bob_factor_x = 1.2;
|
|
}
|
|
|
|
if (weapon_bob_factor_x - 0.00000068 < 1.2)
|
|
weapon_bob_factor_x = 1.2;
|
|
else
|
|
weapon_bob_factor_x -= 0.00000068;
|
|
|
|
|
|
if (dampening_factor_y > 0 && cos(time*weapon_bob_factor_y) > 0) {
|
|
if ((dampening_factor_y - 0.00000065* cos(time*weapon_bob_factor_y)) < 0)
|
|
dampening_factor_y -= (0.00000065 - dampening_factor_y*cos(time*weapon_bob_factor_y));
|
|
else
|
|
dampening_factor_y -= 0.00000065* cos(time*weapon_bob_factor_y);
|
|
|
|
} else if (dampening_factor_y < 0 && cos(time*weapon_bob_factor_y) < 0) {
|
|
if ((dampening_factor_y + 0.00000065* cos(time*weapon_bob_factor_y)) > 0)
|
|
dampening_factor_y += (0.00000065 - dampening_factor_y*cos(time*weapon_bob_factor_y));
|
|
else
|
|
dampening_factor_y += 0.00000065* cos(time*weapon_bob_factor_y);
|
|
} else {
|
|
weapon_bob_factor_y = 1.5;
|
|
}
|
|
|
|
|
|
if (weapon_bob_factor_y - 0.00000065 < 1.5)
|
|
weapon_bob_factor_y = 1.5;
|
|
else
|
|
weapon_bob_factor_y -= 0.00000065;
|
|
|
|
if (dampening_factor_z > 0 && sin(time*weapon_bob_factor_z) > 0) {
|
|
if ((dampening_factor_z - 0.00000123* sin(time*weapon_bob_factor_z)) < 0)
|
|
dampening_factor_z -= (0.00000123 - dampening_factor_z*sin(time*weapon_bob_factor_z));
|
|
else
|
|
dampening_factor_z -= 0.00000123* sin(time*weapon_bob_factor_z);
|
|
|
|
} else if (dampening_factor_z <= 0 && sin(time*weapon_bob_factor_z) < 0) {
|
|
if ((dampening_factor_z + 0.00000123* sin(time*weapon_bob_factor_z)) > 0)
|
|
dampening_factor_z += (0.00000123 - dampening_factor_z*sin(time*weapon_bob_factor_z));
|
|
else
|
|
dampening_factor_z += 0.00000123* sin(time*weapon_bob_factor_z);
|
|
} else {
|
|
weapon_bob_factor_z = 1.1;
|
|
}
|
|
|
|
if (weapon_bob_factor_z - 0.00000123 < 1.1)
|
|
weapon_bob_factor_z = 1.1;
|
|
else
|
|
weapon_bob_factor_z -= 0.00000123;
|
|
|
|
if (weapon_bob_factor_z_coef <= 0.1)
|
|
weapon_bob_factor_z_coef = 0.1;
|
|
else
|
|
weapon_bob_factor_z_coef -= 0.0000001*sin(time*weapon_bob_factor_z);
|
|
}
|
|
|
|
offset_x = 0.2 * (sin(time * weapon_bob_factor_x) + dampening_factor_x);
|
|
offset_y = 0.2 * (cos(time * weapon_bob_factor_y) + dampening_factor_y);
|
|
offset_z = weapon_bob_factor_z_coef * (sin(weapon_bob_factor_z*time + 0.5) + dampening_factor_z);
|
|
|
|
vector tempv;
|
|
tempv_x = 0.2 * (sin(time * weapon_bob_factor_x));
|
|
tempv_y = 0.2 * (cos(time * weapon_bob_factor_y));
|
|
tempv_z = weapon_bob_factor_z_coef * (sin(weapon_bob_factor_z*time + 0.5));
|
|
|
|
dir = vmodel_targetpos - vmodel_currentpos;
|
|
if(vlen(dir) < (0.15 * 128 * frametime))
|
|
vmodel_currentpos = vmodel_targetpos;
|
|
else
|
|
vmodel_currentpos += (dir * 0.15 * 128) * frametime;
|
|
|
|
|
|
if(vlen(vmodel.angles) < (0.1 * 128 * frametime))
|
|
vmodel.angles = '0 0 0';
|
|
else
|
|
vmodel.angles += (-vmodel.angles * 0.2 * 128) * frametime;
|
|
|
|
vmodel_currentpos += (vmodel_velocity * 128) * frametime;
|
|
vmodel_velocity *= 1 - frametime * 30;
|
|
|
|
vmodel.angles += (vmodel_avelocity * 128) * frametime;
|
|
vmodel_avelocity *= 1 - frametime * 30;
|
|
|
|
adsoffset = GetWeaponADSPos(weapon);
|
|
|
|
ads = getstatf(STAT_WEAPONZOOM); //get the zoomtoggle value
|
|
if(ads == 1)
|
|
{
|
|
vmodel_currentpos += (adsoffset * 0.15 * 128) * frametime;
|
|
vmodel_currentpos += offset*0.025;
|
|
vmodel.origin = vmodel_currentpos + adsoffset;
|
|
}
|
|
else if (ads == 2)
|
|
{
|
|
vmodel_currentpos += (adsoffset * 0.15 * 128) * frametime;
|
|
vmodel_currentpos += offset*0.025;
|
|
vmodel.origin = vmodel_currentpos + adsoffset;
|
|
}
|
|
else
|
|
{
|
|
switch(getstatf(STAT_PLAYERSTANCE)) {
|
|
case 2:
|
|
break;
|
|
case 1:
|
|
vmodel_currentpos = '0 0.6 -0.3';
|
|
break;
|
|
case 0:
|
|
vmodel_currentpos = '1.5 0.6 -0.3';
|
|
break;
|
|
default: break;
|
|
}
|
|
vmodel.origin = vmodel_currentpos + offset;
|
|
|
|
vmodel.origin_y += vaccel;
|
|
vmodel.origin_z += vzaccel;
|
|
|
|
if (in_menu != MENU_NONE)
|
|
return;
|
|
|
|
if (K_LEFTDOWN) {
|
|
vaccel -= 0.01;
|
|
if (vaccel < -0.8)
|
|
vaccel = -0.8;
|
|
} else if (K_RIGHTDOWN) {
|
|
vaccel += 0.01;
|
|
if (vaccel > 0.8)
|
|
vaccel = 0.8;
|
|
} else if (vaccel != 0) {
|
|
if (vaccel > 0)
|
|
vaccel -= 0.01;
|
|
else
|
|
vaccel += 0.01;
|
|
}
|
|
|
|
//black ops -0.01 till -0.6 (looks better)
|
|
if (K_BACKDOWN || K_FORWARDDOWN) {
|
|
vzaccel -= 0.01;
|
|
|
|
if (vzaccel < -0.6)
|
|
vzaccel = -0.6;
|
|
} else if (vzaccel != 0) {
|
|
if (vzaccel > 0)
|
|
vzaccel -= 0.02;
|
|
else
|
|
vzaccel += 0.02;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
if(weapon == 1)
|
|
{
|
|
if(mzlflash.scale < 1)
|
|
mzlflash.scale += (10 * random()) * frametime;
|
|
}
|
|
else if(weapon == 2)
|
|
{
|
|
if(mzlflash.scale < 1.5)
|
|
mzlflash.scale += (20 * random()) * frametime;
|
|
}
|
|
mzlflash.origin = vmodel.origin + vmodel_muzzleoffset;
|
|
mzlflash.alpha -= (0.15 * 100) * frametime;
|
|
if(mzlflash.alpha < 0.1)
|
|
mzlflash.alpha = 0.01;
|
|
}
|
|
|
|
noref void(float isnew) CSQC_Ent_Update =
|
|
{
|
|
if(isnew)
|
|
addentity(self);
|
|
}
|
|
|
|
float(__inout vector v) VectorNormalize =
|
|
{
|
|
float length = sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
|
|
|
|
if (length)
|
|
{
|
|
float ilength = 1 / length;
|
|
v[0] *= ilength;
|
|
v[1] *= ilength;
|
|
v[2] *= ilength;
|
|
}
|
|
|
|
return length;
|
|
}
|
|
|
|
void() DropRecoilKick =
|
|
{
|
|
float len;
|
|
|
|
if (crosshair_spread_time > time)
|
|
return;
|
|
|
|
len = VectorNormalize(gun_kick);
|
|
|
|
len = len - frametime*5;
|
|
if (len < 0)
|
|
len = 0;
|
|
|
|
gun_kick[0] *= len;
|
|
gun_kick[1] *= len;
|
|
gun_kick[2] *= len;
|
|
}
|
|
|
|
// CALLED EVERY CLIENT RENDER FRAME
|
|
float pap_flash_alternate;
|
|
noref void(float width, float height, float menushown) CSQC_UpdateView =
|
|
{
|
|
//clear and update our global screen resolution vars
|
|
clearscene();
|
|
g_width = width;
|
|
g_height = height;
|
|
|
|
// camang is controlled by our punchangles
|
|
camang = getproperty(VF_ANGLES);
|
|
|
|
//disable quake status bar and quake crosshair
|
|
setviewprop(VF_DRAWENGINESBAR, 0);
|
|
setviewprop(VF_DRAWCROSSHAIR, 0);
|
|
|
|
setsensitivityscaler(getstatf(STAT_VIEWZOOM)*getstatf(STAT_VIEWZOOM));
|
|
setviewprop(VF_AFOV, autocvar(fov,90)*getstatf(STAT_VIEWZOOM));
|
|
|
|
cvar_set("r_viewmodel_fov", ftos(cvar("r_viewmodel_default_fov")*getstatf(STAT_VIEWZOOM)));
|
|
|
|
|
|
//autoadd entities received from servers for drawing
|
|
addentities(MASK_ENGINE);
|
|
|
|
//do viewmodel manipulation, purely cosmetic stuff
|
|
if(vmodel)
|
|
{
|
|
Update_Vmodel();
|
|
local vector vorg;
|
|
local vector vang;
|
|
vorg = getviewprop(VF_ORIGIN);
|
|
vang = getviewprop(VF_ANGLES);
|
|
//vmodel.origin += vorg;
|
|
//vmodel.angles += vang;
|
|
addentity(vmodel);
|
|
addentity(v2model);
|
|
//vmodel.origin -= vorg;
|
|
//vmodel.angles -= vang;
|
|
//addentity(vmodel);
|
|
float weaponframe, weapon2frame;
|
|
weaponframe = getstatf(STAT_WEAPONFRAME);
|
|
|
|
float duration = getstatf(STAT_WEAPONDURATION);
|
|
|
|
if (!duration) {
|
|
duration = 0.1;
|
|
}
|
|
|
|
if (curweaponframe != weaponframe) {
|
|
interpolating = TRUE;
|
|
vmodel.lerpfrac = 0;
|
|
oldweaponframe = curweaponframe;
|
|
curweaponframe = weaponframe;
|
|
}
|
|
|
|
if (interpolating == TRUE) {
|
|
vmodel.lerpfrac += frametime * (1/duration);
|
|
|
|
if (vmodel.lerpfrac >= 1.0) {
|
|
oldweaponframe = curweaponframe;
|
|
vmodel.lerpfrac = 0;
|
|
interpolating = FALSE;
|
|
}
|
|
|
|
}
|
|
vmodel.frame = oldweaponframe;
|
|
vmodel.frame2 = curweaponframe;
|
|
|
|
if (IsDualWeapon(getstatf(STAT_ACTIVEWEAPON))) {
|
|
float duration2 = getstatf(STAT_WEAPON2DURATION);
|
|
if (!duration2) {
|
|
duration2 = 0.1;
|
|
}
|
|
weapon2frame = getstatf(STAT_WEAPON2FRAME);
|
|
if (curweapon2frame != weapon2frame) {
|
|
interpolating2 = TRUE;
|
|
v2model.lerpfrac = 0;
|
|
oldweapon2frame = curweapon2frame;
|
|
curweapon2frame = weapon2frame;
|
|
}
|
|
|
|
if (interpolating2 == TRUE) {
|
|
v2model.lerpfrac += frametime * (1/duration2);
|
|
|
|
if (v2model.lerpfrac >= 1.0) {
|
|
oldweapon2frame = curweapon2frame;
|
|
v2model.lerpfrac = 0;
|
|
interpolating2 = FALSE;
|
|
}
|
|
|
|
}
|
|
|
|
v2model.frame = oldweapon2frame;
|
|
v2model.frame2 = curweapon2frame;
|
|
|
|
} else {
|
|
//v2model.frame = getstatf(STAT_WEAPON2FRAME);
|
|
v2model.lerpfrac = vmodel.lerpfrac;
|
|
v2model.frame = oldweaponframe;
|
|
v2model.frame2 = curweaponframe;
|
|
}
|
|
v2model.angles = vmodel.angles;
|
|
v2model.origin = vmodel.origin;
|
|
if(mzlflash.alpha > 0.09)
|
|
{
|
|
makevectors(view_angles);
|
|
local vector offset = vmodel.origin + vmodel_muzzleoffset;
|
|
local vector muzzlepos;
|
|
muzzlepos = getviewprop(VF_ORIGIN);
|
|
muzzlepos += v_forward * offset_x;
|
|
muzzlepos -= v_right * offset_y;
|
|
muzzlepos += v_up * (offset_z + 6);
|
|
|
|
if (cvar("r_drawviewmodel")) {
|
|
if (IsPapWeapon(getstatf(STAT_ACTIVEWEAPON))) {
|
|
if (pap_flash_alternate)
|
|
dynamiclight_add(muzzlepos, 128 * mzlflash.alpha, '0.7 0 0' * mzlflash.alpha);
|
|
else
|
|
dynamiclight_add(muzzlepos, 128 * mzlflash.alpha, '0 0 0.7' * mzlflash.alpha);
|
|
|
|
pap_flash_alternate = !pap_flash_alternate;
|
|
}
|
|
else
|
|
dynamiclight_add(muzzlepos, 128 * mzlflash.alpha, '1.2 0.7 0.2' * mzlflash.alpha);
|
|
|
|
addentity(mzlflash);
|
|
}
|
|
}
|
|
}
|
|
|
|
//deltalisten makes engine call the "add_outline" func for each entity with the set model every frame
|
|
/*deltalisten("models/mg_ammo.iqm", add_outline, 0);
|
|
deltalisten("models/weapons/mg/mg.iqm", add_outline, 0);
|
|
deltalisten("models/weapons/pistol/pistol.iqm", add_outline, 0);*/
|
|
//deltalisten("models/humanoid_simplerig.iqm", add_outline, 0);
|
|
|
|
DropRecoilKick();
|
|
|
|
camang[0] += gun_kick[0];
|
|
camang[1] += gun_kick[1];
|
|
camang[2] += gun_kick[2];
|
|
|
|
setviewprop(VF_ANGLES, camang);
|
|
|
|
//does what you think it does
|
|
renderscene();
|
|
|
|
if(in_menu)
|
|
{
|
|
//in menu.qc
|
|
Draw_Menu();
|
|
}
|
|
else
|
|
{
|
|
HUD_Draw(g_width, g_height);
|
|
}
|
|
if(serverkey("constate") != "active" && serverkey("disconnected"))
|
|
{
|
|
drawfill('0 0 0', [width, height, 0], '0.2 0.4 0.7', 1, 0);
|
|
drawstring([width/2 - 60, height/2, 0], "Loading...", [16,16,0],[1,1,1],1,0);
|
|
}
|
|
};
|
|
|
|
noref float(string cmd) CSQC_ConsoleCommand =
|
|
{
|
|
//self = theplayer;
|
|
//if (!self)
|
|
// return FALSE;
|
|
|
|
tokenize(cmd);
|
|
switch(argv(0))
|
|
{
|
|
case "togglemenu":
|
|
ToggleMenu();
|
|
return TRUE;
|
|
break;
|
|
case "map":
|
|
return FALSE;
|
|
break;
|
|
case "startwalk":
|
|
walk = TRUE;
|
|
return FALSE;
|
|
case "stopwalk":
|
|
walk = FALSE;
|
|
return FALSE;
|
|
case "promptjoin":
|
|
menu_join();
|
|
return TRUE;
|
|
case "showscores":
|
|
if (score_show)
|
|
score_show = FALSE;
|
|
else
|
|
score_show = TRUE;
|
|
return TRUE;
|
|
break;
|
|
default:
|
|
return FALSE;
|
|
}
|
|
return FALSE;
|
|
};
|
|
//**********************************************************************//
|
|
// Input_Movecheck //
|
|
// //
|
|
// Called at InputEvent and allows to set var if key is at that state //
|
|
// NOTE: ALL movekeys are called in order to prevent unsetting keys //
|
|
//**********************************************************************//
|
|
|
|
void(float scanx, float setval) Input_Movecheck =
|
|
{
|
|
tokenize(findkeysforcommand("+moveleft"));
|
|
if (scanx == stof(argv(0)))
|
|
K_LEFTDOWN = setval;
|
|
|
|
tokenize(findkeysforcommand("+moveright"));
|
|
if (scanx == stof(argv(0)))
|
|
K_RIGHTDOWN = setval;
|
|
|
|
tokenize(findkeysforcommand("+forward"));
|
|
if (scanx == stof(argv(0)))
|
|
K_FORWARDDOWN = setval;
|
|
|
|
tokenize(findkeysforcommand("+back"));
|
|
if (scanx == stof(argv(0)))
|
|
K_BACKDOWN = setval;
|
|
}
|
|
|
|
void(float button, string key) setToBind =
|
|
{
|
|
local string fullbind, unbind, oldkey;
|
|
local string btn;
|
|
editBind[button] = FALSE;
|
|
|
|
btn = buttonBind[button];
|
|
|
|
tokenize(findkeysforcommand(btn));
|
|
oldkey = keynumtostring(stof(argv(0)));
|
|
|
|
unbind = strcat("bind ", oldkey, " null\n");
|
|
fullbind = strcat("bind ", key, " \"", btn, "\"\n");
|
|
|
|
localcmd(unbind);
|
|
localcmd(fullbind);
|
|
}
|
|
|
|
noref float(float evtype, float scanx, float chary, float devid) CSQC_InputEvent =
|
|
{
|
|
switch(evtype)
|
|
{
|
|
case IE_KEYDOWN:
|
|
if(in_menu != MENU_NONE)
|
|
{
|
|
if(scanx == K_MOUSE1) {
|
|
Menu_Click(0);
|
|
|
|
if (in_menu == MENU_CUSTOMS)
|
|
Menu_Click_Custom();
|
|
return TRUE;
|
|
} else if (scanx == K_MOUSE2) {
|
|
Menu_Click(1);
|
|
return TRUE;
|
|
}
|
|
|
|
if (in_menu == MENU_CSETTINGS) {
|
|
for (int i = 0; i < MAX_BINDS; i += 1) {
|
|
if (editBind[i] == TRUE)
|
|
setToBind(i, keynumtostring(scanx));
|
|
}
|
|
}
|
|
|
|
// Controller Menu Navigation
|
|
if (scanx == K_JOY2) {
|
|
GPActive[0] = TRUE;
|
|
}
|
|
|
|
if (scanx == K_JOY4) {
|
|
GPActive[1] = TRUE;
|
|
}
|
|
|
|
if (scanx == K_JOY1) {
|
|
GPActive[2] = TRUE;
|
|
}
|
|
|
|
}
|
|
|
|
Input_Movecheck(scanx, 1);
|
|
|
|
return FALSE;
|
|
case IE_KEYUP:
|
|
|
|
// Controller Menu Navigation
|
|
if(in_menu != MENU_NONE) {
|
|
if (scanx == K_JOY2) {
|
|
GPActive[0] = FALSE;
|
|
}
|
|
|
|
if (scanx == K_JOY4) {
|
|
GPActive[1] = FALSE;
|
|
}
|
|
|
|
if (scanx == K_JOY1) {
|
|
GPActive[2] = FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
Input_Movecheck(scanx, 0);
|
|
|
|
return FALSE;
|
|
case IE_MOUSEDELTA:
|
|
return FALSE;
|
|
case IE_MOUSEABS:
|
|
//if(devid != 0 && devid != 1)
|
|
// return FALSE;
|
|
cursor_pos_x = scanx;
|
|
cursor_pos_y = chary;
|
|
return FALSE;
|
|
}
|
|
return FALSE;
|
|
};
|
|
|
|
noref void() CSQC_Input_Frame =
|
|
{
|
|
if(walk)
|
|
{
|
|
input_movevalues *= 0.5;
|
|
}
|
|
|
|
input_angles = getproperty(VF_ANGLES);
|
|
}
|
|
|
|
float() tracerthink =
|
|
{
|
|
//makevectors(self.angles);
|
|
local vector cross1 = normalize(crossproduct( getviewprop(VF_ORIGIN) - self.targetpos, self.targetpos - self.origin));
|
|
local vector cross2 = normalize(crossproduct( getviewprop(VF_ORIGIN) - self.origin, self.targetpos - self.origin));
|
|
R_BeginPolygon("tracers/mg");
|
|
|
|
R_PolygonVertex(self.origin + cross2, '0 1 0', '1 1 1', self.alpha - 0.6);
|
|
R_PolygonVertex(self.origin - cross2, '0 0 0', '1 1 1', self.alpha - 0.6);
|
|
R_PolygonVertex(self.targetpos - cross1, '1 0 0', '1 1 1', self.alpha);
|
|
|
|
R_PolygonVertex(self.targetpos + cross1, '1 1 0', '1 1 1', self.alpha);
|
|
R_PolygonVertex(self.origin + cross2, '0 1 0', '1 1 1', self.alpha - 0.6);
|
|
R_PolygonVertex(self.targetpos - cross1, '1 0 0', '1 1 1', self.alpha);
|
|
|
|
/*R_PolygonVertex(self.origin + v_right, '0 1 0', '1 1 1', self.alpha - 0.4);
|
|
R_PolygonVertex(self.origin - v_right, '0 0 0', '1 1 1', self.alpha - 0.4);
|
|
R_PolygonVertex(self.targetpos - v_right, '1 0 0', '1 1 1', self.alpha);
|
|
|
|
R_PolygonVertex(self.targetpos + v_right, '1 1 0', '1 1 1', self.alpha);
|
|
R_PolygonVertex(self.origin + v_right, '0 1 0', '1 1 1', self.alpha - 0.4);
|
|
R_PolygonVertex(self.targetpos - v_right, '1 0 0', '1 1 1', self.alpha);*/
|
|
|
|
|
|
R_EndPolygon();
|
|
|
|
self.alpha -= (frametime * self.rate);
|
|
if(self.alpha <= 0)
|
|
remove(self);
|
|
|
|
return 0;
|
|
}
|
|
|
|
float() alphafade =
|
|
{
|
|
|
|
self.alpha -= (frametime * 3);
|
|
self.scale += (frametime * 9);
|
|
if(self.alpha <= 0.05)
|
|
remove(self);
|
|
|
|
local vector cross1 = 10 * self.scale * normalize(crossproduct( getviewprop(VF_ORIGIN) - self.origin + self.targetpos * self.scale, self.targetpos * self.scale));
|
|
local vector cross2 = 10 * self.scale * normalize(crossproduct( getviewprop(VF_ORIGIN) - self.origin, self.targetpos * self.scale));
|
|
R_BeginPolygon("bloodsplat2");
|
|
|
|
R_PolygonVertex(self.origin + cross2, '0 1 0', '1 1 1', self.alpha);
|
|
R_PolygonVertex(self.origin - cross2, '0 0 0', '1 1 1', self.alpha);
|
|
R_PolygonVertex(self.origin + (self.targetpos*self.scale*18) - cross1, '1 0 0', '1 1 1', self.alpha);
|
|
|
|
R_PolygonVertex(self.origin + (self.targetpos*self.scale*18) + cross1, '1 1 0', '1 1 1', self.alpha);
|
|
R_PolygonVertex(self.origin + cross2, '0 1 0', '1 1 1', self.alpha);
|
|
R_PolygonVertex(self.origin + (self.targetpos*self.scale*18) - cross1, '1 0 0', '1 1 1', self.alpha);
|
|
|
|
R_EndPolygon();
|
|
|
|
return 0;
|
|
}
|
|
|
|
noref void() CSQC_Parse_Event =
|
|
{
|
|
local float first = readbyte();
|
|
|
|
switch (first) {
|
|
case EVENT_PISTOLFIRE:
|
|
local float entnum, traceent, side;
|
|
local vector pos, norm;
|
|
entnum = readentitynum();
|
|
side = readfloat();
|
|
pos_x = readcoord();
|
|
pos_y = readcoord();
|
|
pos_z = readcoord();
|
|
norm_x = readcoord();
|
|
norm_y = readcoord();
|
|
norm_z = readcoord();
|
|
|
|
traceent = readentitynum();
|
|
|
|
if(entnum == player_localentnum)
|
|
{
|
|
makevectors(view_angles);
|
|
local vector offset = vmodel.origin + vmodel_muzzleoffset;
|
|
local vector muzzlepos;
|
|
muzzlepos = getviewprop(VF_ORIGIN);
|
|
|
|
local vector muzzle_offset = GetWeaponFlash_Offset(getstatf(STAT_ACTIVEWEAPON))/1000;
|
|
|
|
// ADS offset
|
|
if(getstatf(STAT_WEAPONZOOM) == 1)
|
|
{
|
|
muzzle_offset += GetWeaponADSPos(weapon);
|
|
muzzle_offset[0] -= 2;
|
|
}
|
|
|
|
// Firing from the left? Flip x-axis for muzzleflash
|
|
if (side == 0 && IsDualWeapon(getstatf(STAT_ACTIVEWEAPON)))
|
|
muzzle_offset[0] = -muzzle_offset[0];
|
|
|
|
muzzlepos += v_forward * muzzle_offset_z;
|
|
muzzlepos += v_right * muzzle_offset_x;
|
|
muzzlepos += v_up * muzzle_offset_y;
|
|
mzlflash.alpha = 1;
|
|
|
|
if (cvar("nzp_particles") && cvar("r_drawviewmodel")) {
|
|
float index = rint(random() * 2);
|
|
if (IsPapWeapon(getstatf(STAT_ACTIVEWEAPON)))
|
|
pointparticles(particleeffectnum(strcat("muzzle.muzzle_pap_part", ftos(index))), muzzlepos, norm*24, 1);
|
|
else
|
|
pointparticles(particleeffectnum(strcat("muzzle.muzzle_part", ftos(index))), muzzlepos, norm*24, 1);
|
|
}
|
|
}
|
|
|
|
if(traceent == 0 && GetFiretype(getstatf(STAT_ACTIVEWEAPON)) != 3)
|
|
{
|
|
if (cvar("nzp_particles"))
|
|
pointparticles(particleeffectnum("weapons.impact"), pos, norm*24, 1);
|
|
|
|
if (cvar("nzp_decals"))
|
|
pointparticles(particleeffectnum("weapons.impact_decal"), pos, '0 0 0', 1);
|
|
}
|
|
else
|
|
{
|
|
local vector entorg;
|
|
entorg = getentity(traceent, GE_ORIGIN);
|
|
norm = (norm * 0.25) + (normalize(pos - (entorg + '0 0 12')) * 0.75);
|
|
local entity splat = spawn();
|
|
splat.drawmask = 1;
|
|
splat.alpha = 1;
|
|
splat.scale = 0.05;
|
|
splat.angles = [random()*360, random()*360, random()*360];
|
|
splat.targetpos = norm * 1.5;
|
|
splat.predraw = alphafade;
|
|
}
|
|
break;
|
|
case EVENT_WEAPONRECOIL:
|
|
local vector rec;
|
|
rec_x = readcoord()/5;
|
|
rec_y = readcoord()/5;
|
|
rec_z = readcoord()/5;
|
|
|
|
gun_kick += rec;
|
|
break;
|
|
case EVENT_EXPLOSION:
|
|
local vector org;
|
|
org_x = readcoord();
|
|
org_y = readcoord();
|
|
org_z = readcoord();
|
|
|
|
if (cvar("nzp_decals"))
|
|
pointparticles(particleeffectnum("weapons.explode"), org, '0 0 0', 1);
|
|
break;
|
|
case EVENT_BLOOD:
|
|
local vector loc;
|
|
|
|
loc_x = readcoord();
|
|
loc_y = readcoord();
|
|
loc_z = readcoord();
|
|
|
|
if (cvar("nzp_particles"))
|
|
pointparticles(particleeffectnum("blood.blood_particle"), loc, '0 0 0', 1);
|
|
break;
|
|
case EVENT_WEAPONCHANGE:
|
|
local float to;
|
|
to = readbyte();
|
|
setmodel(vmodel,GetWeaponModel(to, FALSE));
|
|
|
|
if (to == W_KAR_SCOPE && vmodel.model == "models/weapons/kar/v_kar.mdl") {
|
|
setmodel(v2model,"models/weapons/kar/v_karscope.mdl");
|
|
} else {
|
|
setmodel(v2model,"");
|
|
}
|
|
|
|
v2model.origin = vmodel.origin = '0 0 0';
|
|
v2model.angles = vmodel.angles = '-60 0 0';
|
|
v2model_currentpos = vmodel_currentpos = vmodel.origin + '0 0 -24';
|
|
v2model_targetpos = vmodel_targetpos = vmodel.origin;
|
|
v2model_muzzleoffset = vmodel_muzzleoffset = '12 0 1';
|
|
weapon = to;
|
|
|
|
HUD_Change_time = time + 6;
|
|
break;
|
|
case EVENT_UPDATEVMODEL:
|
|
local string new;
|
|
local float skin2;
|
|
new = readstring();
|
|
setmodel(vmodel,new);
|
|
vmodel.skin = readbyte();
|
|
break;
|
|
case EVENT_UPDATEV2MODEL:
|
|
local string new2;
|
|
new2 = readstring();
|
|
setmodel(v2model,new2);
|
|
v2model.skin = readbyte();
|
|
break;
|
|
case EVENT_USEPRINT:
|
|
useprint_type = readbyte();
|
|
useprint_cost = readshort();
|
|
useprint_weapon = readbyte();
|
|
|
|
useprint_time = time + 0.1;
|
|
break;
|
|
|
|
case EVENT_NEWROUND:
|
|
rounds = readbyte();
|
|
HUD_Change_time = time + 6;
|
|
break;
|
|
case EVENT_SETROUND:
|
|
rounds = readbyte();
|
|
break;
|
|
case EVENT_PERK:
|
|
float newperks;
|
|
|
|
newperks = readlong();
|
|
|
|
UpdatePerks(newperks);
|
|
break;
|
|
case EVENT_UPDATE:
|
|
float updatetype = readbyte();
|
|
float var_1 = readbyte();
|
|
float var_2 = readbyte();
|
|
float var_3 = readbyte();
|
|
|
|
switch (updatetype)
|
|
{
|
|
case 1:
|
|
HUD_Change_time = time + var_1;
|
|
break;
|
|
case 2:
|
|
rounds_change = var_1;
|
|
break;
|
|
case 3:
|
|
if (Hitmark_time < time)
|
|
Hitmark_time = time + 0.2;
|
|
break;
|
|
case 4:
|
|
zoom_2_time = time + 0.20;
|
|
break;
|
|
case 5:
|
|
crosshair_spread_time = time + 70/getWeaponRecoilReturn(getstatf(STAT_ACTIVEWEAPON));
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case EVENT_BROADCAST:
|
|
broadcast_time = readbyte();
|
|
broadcast_type = readbyte();
|
|
broadcast_string = readstring();
|
|
break;
|
|
case EVENT_REVIVECHANGE:
|
|
float revivechange_id = readbyte();
|
|
float state = readbyte();
|
|
revive_icons[revivechange_id].state = state;
|
|
break;
|
|
case EVENT_REVIVEON:
|
|
float reviveon_id = readbyte();
|
|
revive_icons[reviveon_id].org[0] = readcoord();
|
|
revive_icons[reviveon_id].org[1] = readcoord();
|
|
revive_icons[reviveon_id].org[2] = readcoord();
|
|
revive_icons[reviveon_id].state = 1;
|
|
revive_icons[reviveon_id].draw = true;
|
|
active_revive_icons++;
|
|
break;
|
|
case EVENT_REVIVEOFF:
|
|
float reviveoff_id = readbyte();
|
|
revive_icons[reviveoff_id].org[0] = 0;
|
|
revive_icons[reviveoff_id].org[1] = 0;
|
|
revive_icons[reviveoff_id].org[2] = 0;
|
|
revive_icons[reviveoff_id].state = 0;
|
|
revive_icons[reviveoff_id].timer = 0;
|
|
revive_icons[reviveoff_id].draw = false;
|
|
active_revive_icons--;
|
|
break;
|
|
case EVENT_POINTUPDATE:
|
|
float playernum = readbyte();
|
|
float temppoints = readlong();
|
|
RegisterPointChange(readlong(), playernum);
|
|
float tempkills = readlong();
|
|
string tempname = readstring();
|
|
|
|
switch(playernum) {
|
|
case 1: playerpoints[0] = temppoints; playerkills[0] = tempkills; playernames[0] = tempname; break;
|
|
case 2: playerpoints[1] = temppoints; playerkills[1] = tempkills; playernames[1] = tempname; break;
|
|
case 3: playerpoints[2] = temppoints; playerkills[2] = tempkills; playernames[2] = tempname; break;
|
|
case 4: playerpoints[3] = temppoints; playerkills[3] = tempkills; playernames[3] = tempname; break;
|
|
}
|
|
break;
|
|
case EVENT_BLACKOUT:
|
|
fade_time = readbyte();
|
|
fade_type = readbyte();
|
|
break;
|
|
case EVENT_PUNCHANGLE:
|
|
vector changetest;
|
|
changetest_x = readcoord();
|
|
changetest_y = readcoord();
|
|
changetest_z = readcoord();
|
|
break;
|
|
case EVENT_SCROLLTEXT:
|
|
scrolltext = readstring();
|
|
stext = TRUE;
|
|
break;
|
|
case EVENT_WORLDDATA:
|
|
chaptertitle = readstring();
|
|
location = readstring();
|
|
date = readstring();
|
|
person = readstring();
|
|
|
|
if (chaptertitle == "")
|
|
chaptertitle = "'Nazi Zombies'";
|
|
break;
|
|
case EVENT_ACHIEVEMENT:
|
|
float ach = readbyte();
|
|
|
|
if (achievements[ach].unlocked == true)
|
|
return;
|
|
Achievement_Unlock(ach);
|
|
break;
|
|
case EVENT_ACHIEVEMENTPROGRESS:
|
|
float id = readbyte();
|
|
float pg = readfloat();
|
|
|
|
if (achievements[id].unlocked == true)
|
|
return;
|
|
|
|
Achievement_UpdateProgress(id, pg);
|
|
break;
|
|
case EVENT_PLAYERUPDATE:
|
|
player_count = readbyte();
|
|
break;
|
|
case EVENT_WEAPONUPDATE:
|
|
float wepnum = readbyte();
|
|
string wepname = readstring();
|
|
string wvmodel = readstring();
|
|
float mag = readbyte();
|
|
float reserve = readbyte();
|
|
vector cads = stov(readstring());
|
|
float cmin = readbyte();
|
|
float cmax = readbyte();
|
|
vector flash = stov(readstring());
|
|
float flashsize = readbyte();
|
|
string v2 = readstring();
|
|
float isd = readbyte();
|
|
/*W_CUSTOMNAME[wepnum] = wepname;
|
|
W_CVMODEL[wepnum] = wvmodel;
|
|
W_CMAG[wepnum] = mag;
|
|
W_CRESERVE[wepnum] = reserve;
|
|
W_CCROSSMIN[wepnum] = cmin;
|
|
W_CCROSSMAX[wepnum] = cmax;
|
|
W_CADS[wepnum] = cads;
|
|
W_CFLASHSIZE[wepnum] = flashsize;
|
|
W_CVMODEL2[wepnum] = v2;
|
|
W_CDUAL[wepnum] = isd;*/
|
|
break;
|
|
case EVENT_HUDUPDATE:
|
|
/*string temps;
|
|
float tempf;
|
|
G_HUD = readstring();
|
|
G_HUDHOR = readbyte();
|
|
|
|
if (G_HUD != "")
|
|
huddir = strcat("gfx/hud/", G_HUD, "/");*/
|
|
break;
|
|
}
|
|
}
|