quakec/source/client/main.qc

1178 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(cltime*weapon_bob_factor_x);
dampening_factor_y = 0.2*cos(cltime*weapon_bob_factor_y);
dampening_factor_z = 0.2*sin(cltime*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(cltime * weapon_bob_factor_x) + dampening_factor_x);
offset_y = 0.2 * (cos(cltime * weapon_bob_factor_y) + dampening_factor_y);
offset_z = weapon_bob_factor_z_coef * (sin(weapon_bob_factor_z*cltime + 0.5) + dampening_factor_z);
vector tempv;
tempv_x = 0.2 * (sin(cltime * weapon_bob_factor_x));
tempv_y = 0.2 * (cos(cltime * weapon_bob_factor_y));
tempv_z = weapon_bob_factor_z_coef * (sin(weapon_bob_factor_z*cltime + 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 || ads == 2)
{
vmodel_currentpos += (adsoffset * 0.15 * 128) * frametime;
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;
}
#define SCALE_CONSTANT 8
// 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((1 + SCALE_CONSTANT * getstatf(STAT_VIEWZOOM)) / (1 + SCALE_CONSTANT));
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;
}
}