From: Mario Date: Sun, 12 Mar 2017 03:13:00 +0000 (+1000) Subject: Merge branch 'master' into Mario/killsound X-Git-Tag: xonotic-v0.8.2~69^2~2 X-Git-Url: https://de.git.xonotic.org/?p=xonotic%2Fxonotic-data.pk3dir.git;a=commitdiff_plain;h=905ec2fbd2b610eeb2591cdddbf71ce24b7bb3ab;hp=-c Merge branch 'master' into Mario/killsound --- 905ec2fbd2b610eeb2591cdddbf71ce24b7bb3ab diff --combined qcsrc/client/view.qc index 4165da32ad,104405b397..65df30fd89 --- a/qcsrc/client/view.qc +++ b/qcsrc/client/view.qc @@@ -283,9 -283,11 +283,11 @@@ void viewmodel_animate(entity this .float weapon_eta_last; .float weapon_switchdelay; + .string name_last; + void viewmodel_draw(entity this) { - if(!activeweapon || !autocvar_r_drawviewmodel) + if(!this.activeweapon || !autocvar_r_drawviewmodel) return; int mask = (intermission || (STAT(HEALTH) <= 0) || autocvar_chase_active) ? 0 : MASK_NORMAL; float a = this.alpha; @@@ -294,9 -296,9 +296,9 @@@ if (invehicle) a = -1; else if (wasinvehicle) a = 1; wasinvehicle = invehicle; - Weapon wep = activeweapon; + Weapon wep = this.activeweapon; int c = entcs_GetClientColors(current_player); - vector g = weaponentity_glowmod(wep, NULL, c); + vector g = weaponentity_glowmod(wep, NULL, c, this); entity me = CSQCModel_server2csqc(player_localentnum - 1); int fx = ((me.csqcmodel_effects & EFMASK_CHEAP) | EF_NODEPTHTEST) @@@ -311,21 -313,20 +313,20 @@@ CSQCModel_Effects_Apply(e); } { - static string name_last; string name = wep.mdl; string newname = wep.wr_viewmodel(wep, this); if(newname) name = newname; - bool swap = name != name_last; + bool swap = name != this.name_last; // if (swap) { - name_last = name; + this.name_last = name; CL_WeaponEntity_SetModel(this, name, swap); this.viewmodel_origin = this.origin; this.viewmodel_angles = this.angles; } anim_update(this); - if (!this.animstate_override && !this.animstate_looping) + if ((!this.animstate_override && !this.animstate_looping) || time > this.animstate_endtime) anim_set(this, this.anim_idle, true, false, false); } float f = 0; // 0..1; 0: fully active @@@ -358,9 -359,9 +359,9 @@@ setorigin(this, this.origin); } - entity viewmodel; STATIC_INIT(viewmodel) { - viewmodel = new(viewmodel); + for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot) + viewmodels[slot] = new(viewmodel); } void Porto_Draw(entity this); @@@ -373,65 -374,70 +374,70 @@@ STATIC_INIT(Porto } const int polyline_length = 16; - vector polyline[polyline_length]; + .vector polyline[polyline_length]; void Porto_Draw(entity this) { - if (activeweapon != WEP_PORTO) return; - if (spectatee_status) return; - if (WEP_CVAR(porto, secondary)) return; - if (intermission == 1) return; - if (intermission == 2) return; - if (STAT(HEALTH) <= 0) return; - - vector pos = view_origin; - vector dir = view_forward; - if (angles_held_status) - { - makevectors(angles_held); - dir = v_forward; - } - - polyline[0] = pos; - - int portal_number = 0, portal1_idx = 1, portal_max = 2; - int n = 1 + 2; // 2 lines == 3 points - for (int idx = 0; idx < n && idx < polyline_length - 1; ) + for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot) { - traceline(pos, pos + 65536 * dir, true, this); - dir = reflect(dir, trace_plane_normal); - pos = trace_endpos; - polyline[++idx] = pos; - if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_SLICK || trace_dphitcontents & DPCONTENTS_PLAYERCLIP) + entity wepent = viewmodels[slot]; + + if (wepent.activeweapon != WEP_PORTO) continue; + if (spectatee_status) continue; + if (WEP_CVAR(porto, secondary)) continue; + if (intermission == 1) continue; + if (intermission == 2) continue; + if (STAT(HEALTH) <= 0) continue; + + vector pos = view_origin; + vector dir = view_forward; + if (wepent.angles_held_status) { - n += 1; - continue; + makevectors(wepent.angles_held); + dir = v_forward; } - if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT) - { - n = max(2, idx); - break; - } - // check size + + wepent.polyline[0] = pos; + + int portal_number = 0, portal1_idx = 1, portal_max = 2; + int n = 1 + 2; // 2 lines == 3 points + for (int idx = 0; idx < n && idx < polyline_length - 1; ) { - vector ang = vectoangles2(trace_plane_normal, dir); - ang.x = -ang.x; - makevectors(ang); - if (!CheckWireframeBox(this, pos - 48 * v_right - 48 * v_up + 16 * v_forward, 96 * v_right, 96 * v_up, 96 * v_forward)) + traceline(pos, pos + 65536 * dir, true, this); + dir = reflect(dir, trace_plane_normal); + pos = trace_endpos; + wepent.polyline[++idx] = pos; + if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_SLICK || trace_dphitcontents & DPCONTENTS_PLAYERCLIP) + { + n += 1; + continue; + } + if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT) { n = max(2, idx); break; } + // check size + { + vector ang = vectoangles2(trace_plane_normal, dir); + ang.x = -ang.x; + makevectors(ang); + if (!CheckWireframeBox(this, pos - 48 * v_right - 48 * v_up + 16 * v_forward, 96 * v_right, 96 * v_up, 96 * v_forward)) + { + n = max(2, idx); + break; + } + } + portal_number += 1; + if (portal_number >= portal_max) break; + if (portal_number == 1) portal1_idx = idx; + } + for (int idx = 0; idx < n - 1; ++idx) + { + vector p = wepent.polyline[idx], q = wepent.polyline[idx + 1]; + if (idx == 0) p -= view_up * 16; // line from player + vector rgb = (idx < portal1_idx) ? '1 0 0' : '0 0 1'; + Draw_CylindricLine(p, q, 4, "", 1, 0, rgb, 0.5, DRAWFLAG_NORMAL, view_origin); } - portal_number += 1; - if (portal_number >= portal_max) break; - if (portal_number == 1) portal1_idx = idx; - } - for (int idx = 0; idx < n - 1; ++idx) - { - vector p = polyline[idx], q = polyline[idx + 1]; - if (idx == 0) p -= view_up * 16; // line from player - vector rgb = (idx < portal1_idx) ? '1 0 0' : '0 0 1'; - Draw_CylindricLine(p, q, 4, "", 1, 0, rgb, 0.5, DRAWFLAG_NORMAL, view_origin); } } @@@ -453,10 -459,17 +459,17 @@@ vector GetCurrentFov(float fov zoomspeed = 3.5; zoomdir = button_zoom; + if(hud == HUD_NORMAL && !spectatee_status) - if(switchweapon == activeweapon) - if((activeweapon == WEP_VORTEX && !WEP_CVAR(vortex, secondary)) || (activeweapon == WEP_RIFLE && !WEP_CVAR(rifle, secondary))) // do NOT use switchweapon here - zoomdir += button_attack2; + { + for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot) + { + entity wepent = viewmodels[slot]; + if(wepent.switchweapon == wepent.activeweapon) + if((wepent.activeweapon == WEP_VORTEX && !WEP_CVAR(vortex, secondary)) || (wepent.activeweapon == WEP_RIFLE && !WEP_CVAR(rifle, secondary))) // do NOT use switchweapon here + zoomdir += button_attack2; + } + } if(spectatee_status > 0 || isdemo()) { if(spectatorbutton_zoom) @@@ -509,7 -522,7 +522,7 @@@ current_zoomfraction = (current_viewzoom - 1) / (1/zoomfactor - 1); if(zoomsensitivity < 1) - setsensitivityscale(pow(current_viewzoom, 1 - zoomsensitivity)); + setsensitivityscale(current_viewzoom ** (1 - zoomsensitivity)); else setsensitivityscale(1); @@@ -623,7 -636,7 +636,7 @@@ float EnemyHitCheck( return SHOTTYPE_HITENEMY; } - float TrueAimCheck() + float TrueAimCheck(entity wepent) { float nudge = 1; // added to traceline target and subtracted from result TOOD(divVerent): do we still need this? Doesn't the engine do this now for us? vector vecs, trueaimpoint, w_shotorg; @@@ -636,7 -649,7 +649,7 @@@ ta = trueaim; mv = MOVE_NOMONSTERS; - switch(activeweapon) // WEAPONTODO + switch(wepent.activeweapon) // WEAPONTODO { case WEP_TUBA: // no aim case WEP_PORTO: // shoots from eye @@@ -653,7 -666,7 +666,7 @@@ mv = MOVE_NORMAL; if(zoomscript_caught) { - tracebox(view_origin, '0 0 0', '0 0 0', view_origin + view_forward * MAX_SHOT_DISTANCE, mv, ta); + tracebox(view_origin, '0 0 0', '0 0 0', view_origin + view_forward * max_shot_distance, mv, ta); return EnemyHitCheck(); } break; @@@ -679,7 -692,7 +692,7 @@@ vecs = decompressShotOrigin(STAT(SHOTORG)); - traceline(traceorigin, traceorigin + view_forward * MAX_SHOT_DISTANCE, mv, ta); + traceline(traceorigin, traceorigin + view_forward * max_shot_distance, mv, ta); trueaimpoint = trace_endpos; if(vdist((trueaimpoint - traceorigin), <, g_trueaim_minrange)) @@@ -719,7 -732,6 +732,6 @@@ float camera_mode const float CAMERA_FREE = 1; const float CAMERA_CHASE = 2; float reticle_type; - string reticle_image; string NextFrameCommand; vector freeze_org, freeze_ang; @@@ -747,7 -759,7 +759,7 @@@ bool WantEventchase(entity this { if(autocvar_cl_orthoview) return false; - if(STAT(GAMEOVER) || intermission) + if(STAT(GAME_STOPPED) || intermission) return true; if(this.viewloc) return true; @@@ -811,9 -823,18 +823,18 @@@ void HitSound( { // varying sound pitch + bool have_arc = false; + for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot) + { + entity wepent = viewmodels[slot]; + + if(wepent.activeweapon == WEP_ARC) + have_arc = true; + } + static float hitsound_time_prev = 0; // HACK: the only way to get the arc to sound consistent with pitch shift is to ignore cl_hitsound_antispam_time - float arc_hack = activeweapon == WEP_ARC && autocvar_cl_hitsound >= 2; + bool arc_hack = have_arc && autocvar_cl_hitsound >= 2; if (arc_hack || COMPARE_INCREASING(time, hitsound_time_prev) > autocvar_cl_hitsound_antispam_time) { if (autocvar_cl_hitsound && unaccounted_damage) @@@ -854,14 -875,6 +875,14 @@@ sound(NULL, CH_INFO, SND_TYPEHIT, VOL_BASE, ATTN_NONE); typehit_time_prev = typehit_time; } + + static float kill_time_prev = 0; + float kill_time = STAT(KILL_TIME); + if (COMPARE_INCREASING(kill_time, kill_time_prev) > autocvar_cl_hitsound_antispam_time) + { + sound(NULL, CH_INFO, SND_KILL, VOL_BASE, ATTN_NONE); + kill_time_prev = kill_time; + } } vector crosshair_getcolor(entity this, float health_stat) @@@ -948,7 -961,7 +969,7 @@@ void HUD_Crosshair(entity this { float f, i, j; vector v; - if(!scoreboard_active && !camera_active && intermission != 2 && !STAT(GAMEOVER) && + if(!scoreboard_active && !camera_active && intermission != 2 && !STAT(GAME_STOPPED) && spectatee_status != -1 && !csqcplayer.viewloc && !MUTATOR_CALLHOOK(DrawCrosshair) && !HUD_MinigameMenu_IsOpened() ) { @@@ -980,13 -993,14 +1001,14 @@@ float shottype; // wcross_origin = '0.5 0 0' * vid_conwidth + '0 0.5 0' * vid_conheight; - wcross_origin = project_3d_to_2d(view_origin + MAX_SHOT_DISTANCE * view_forward); + wcross_origin = project_3d_to_2d(view_origin + max_shot_distance * view_forward); wcross_origin.z = 0; if(autocvar_crosshair_hittest) { vector wcross_oldorigin; + entity thiswep = viewmodels[0]; // TODO: unhardcode wcross_oldorigin = wcross_origin; - shottype = TrueAimCheck(); + shottype = TrueAimCheck(thiswep); if(shottype == SHOTTYPE_HITWORLD) { v = wcross_origin - wcross_oldorigin; @@@ -1008,7 -1022,8 +1030,8 @@@ entity e = WEP_Null; if(autocvar_crosshair_per_weapon || (autocvar_crosshair_color_special == 1)) { - e = switchingweapon; + entity wepent = viewmodels[0]; // TODO: unhardcode + e = wepent.switchingweapon; if(e) { if(autocvar_crosshair_per_weapon) @@@ -1153,10 -1168,6 +1176,6 @@@ weapon_clipload = STAT(WEAPON_CLIPLOAD); weapon_clipsize = STAT(WEAPON_CLIPSIZE); - float ok_ammo_charge, ok_ammo_chargepool; - ok_ammo_charge = STAT(OK_AMMO_CHARGE); - ok_ammo_chargepool = STAT(OK_AMMO_CHARGEPOOL); - float vortex_charge, vortex_chargepool; vortex_charge = STAT(VORTEX_CHARGE); vortex_chargepool = STAT(VORTEX_CHARGEPOOL); @@@ -1166,9 -1177,10 +1185,10 @@@ if(vortex_charge_movingavg == 0) // this should only happen if we have just loaded up the game vortex_charge_movingavg = vortex_charge; + entity wepent = viewmodels[0]; // TODO: unhardcode // handle the values - if (autocvar_crosshair_ring && activeweapon == WEP_VORTEX && vortex_charge && autocvar_crosshair_ring_vortex) // ring around crosshair representing velocity-dependent damage for the vortex + if (autocvar_crosshair_ring && wepent.activeweapon == WEP_VORTEX && vortex_charge && autocvar_crosshair_ring_vortex) // ring around crosshair representing velocity-dependent damage for the vortex { if (vortex_chargepool || use_vortex_chargepool) { use_vortex_chargepool = 1; @@@ -1188,27 -1200,20 +1208,20 @@@ ring_rgb = wcross_color; ring_image = "gfx/crosshair_ring_nexgun.tga"; } - else if (autocvar_crosshair_ring && activeweapon == WEP_MINE_LAYER && WEP_CVAR(minelayer, limit) && autocvar_crosshair_ring_minelayer) + else if (autocvar_crosshair_ring && wepent.activeweapon == WEP_MINE_LAYER && WEP_CVAR(minelayer, limit) && autocvar_crosshair_ring_minelayer) { ring_value = bound(0, STAT(LAYED_MINES) / WEP_CVAR(minelayer, limit), 1); // if you later need to use the count of bullets in another place, then add a float for it. For now, no need to. ring_alpha = autocvar_crosshair_ring_minelayer_alpha; ring_rgb = wcross_color; ring_image = "gfx/crosshair_ring.tga"; } - else if (activeweapon == WEP_HAGAR && STAT(HAGAR_LOAD) && autocvar_crosshair_ring_hagar) + else if (wepent.activeweapon == WEP_HAGAR && STAT(HAGAR_LOAD) && autocvar_crosshair_ring_hagar) { ring_value = bound(0, STAT(HAGAR_LOAD) / WEP_CVAR_SEC(hagar, load_max), 1); ring_alpha = autocvar_crosshair_ring_hagar_alpha; ring_rgb = wcross_color; ring_image = "gfx/crosshair_ring.tga"; } - else if (ok_ammo_charge) - { - ring_value = ok_ammo_chargepool; - ring_alpha = autocvar_crosshair_ring_reload_alpha; - ring_rgb = wcross_color; - ring_image = "gfx/crosshair_ring.tga"; - } else if(autocvar_crosshair_ring_reload && weapon_clipsize) // forces there to be only an ammo ring { ring_value = bound(0, weapon_clipload / weapon_clipsize, 1); @@@ -1218,12 -1223,12 +1231,12 @@@ // Note: This is to stop Taoki from complaining that the image doesn't match all potential balances. // if a new image for another weapon is added, add the code (and its respective file/value) here - if ((activeweapon == WEP_RIFLE) && (weapon_clipsize == 80)) + if ((wepent.activeweapon == WEP_RIFLE) && (weapon_clipsize == 80)) ring_image = "gfx/crosshair_ring_rifle.tga"; else ring_image = "gfx/crosshair_ring.tga"; } - else if ( autocvar_crosshair_ring && autocvar_crosshair_ring_arc && arc_heat && activeweapon == WEP_ARC ) + else if ( autocvar_crosshair_ring && autocvar_crosshair_ring_arc && arc_heat && wepent.activeweapon == WEP_ARC ) { ring_value = arc_heat; ring_alpha = (1-arc_heat)*autocvar_crosshair_ring_arc_cold_alpha + @@@ -1712,7 -1717,8 +1725,8 @@@ void CSQC_UpdateView(entity this, floa // run viewmodel_draw before updating view_angles to the angles calculated by WarpZone_FixView // viewmodel_draw needs to use the view_angles set by the engine on every CSQC_UpdateView call - viewmodel_draw(viewmodel); + for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot) + viewmodel_draw(viewmodels[slot]); // Render the Scene view_origin = getpropertyvec(VF_ORIGIN); @@@ -1729,7 -1735,7 +1743,7 @@@ t = (time - blurtest_time0) / (blurtest_time1 - blurtest_time0); r = t * blurtest_radius; - f = 1 / pow(t, blurtest_power) - 1; + f = 1 / (t ** blurtest_power) - 1; cvar_set("r_glsl_postprocess", "1"); cvar_set("r_glsl_postprocess_uservec1", strcat(ftos(r), " ", ftos(f), " 0 0")); @@@ -1790,39 -1796,36 +1804,36 @@@ ColorTranslateMode = autocvar_cl_stripcolorcodes; - // currently switching-to weapon (for crosshair) - switchingweapon = Weapons_from(STAT(SWITCHINGWEAPON)); - - // actually active weapon (for zoom) - activeweapon = Weapons_from(STAT(ACTIVEWEAPON)); - - switchweapon = Weapons_from(STAT(SWITCHWEAPON)); - - if(last_switchweapon != switchweapon) + for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot) { - weapontime = time; - last_switchweapon = switchweapon; - if(button_zoom && autocvar_cl_unpress_zoom_on_weapon_switch) + entity wepent = viewmodels[slot]; + + if(wepent.last_switchweapon != wepent.switchweapon) { - localcmd("-zoom\n"); - button_zoom = false; + weapontime = time; + wepent.last_switchweapon = wepent.switchweapon; + if(slot == 0 && button_zoom && autocvar_cl_unpress_zoom_on_weapon_switch) + { + localcmd("-zoom\n"); + button_zoom = false; + } + if(slot == 0 && autocvar_cl_unpress_attack_on_weapon_switch) + { + localcmd("-fire\n"); + localcmd("-fire2\n"); + button_attack2 = false; + } } - if(autocvar_cl_unpress_attack_on_weapon_switch) + if(wepent.last_activeweapon != wepent.activeweapon) { - localcmd("-fire\n"); - localcmd("-fire2\n"); - button_attack2 = false; - } - } - if(last_activeweapon != activeweapon) - { - last_activeweapon = activeweapon; + wepent.last_activeweapon = wepent.activeweapon; - e = activeweapon; - if(e.netname != "") - localcmd(strcat("\ncl_hook_activeweapon ", e.netname), "\n"); - else - localcmd("\ncl_hook_activeweapon none\n"); + e = wepent.activeweapon; + if(e.netname != "") + localcmd(strcat("\ncl_hook_activeweapon ", e.netname), "\n"); + else if(slot == 0) + localcmd("\ncl_hook_activeweapon none\n"); + } } // ALWAYS Clear Current Scene First @@@ -1950,7 -1953,20 +1961,20 @@@ if(autocvar_cl_reticle) { - Weapon wep = activeweapon; + string reticle_image = string_null; + bool wep_zoomed = false; + for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot) + { + entity wepe = viewmodels[slot]; + Weapon wep = wepe.activeweapon; + if(wep != WEP_Null && wep.wr_zoom) + { + bool do_zoom = wep.wr_zoom(wep, NULL); + if(!reticle_image && wep.w_reticle && wep.w_reticle != "") + reticle_image = wep.w_reticle; + wep_zoomed += do_zoom; + } + } // Draw the aiming reticle for weapons that use it // reticle_type is changed to the item we are zooming / aiming with, to decide which reticle to use // It must be a persisted float for fading out to work properly (you let go of the zoom button for @@@ -1960,9 -1976,9 +1984,9 @@@ // no zoom reticle while dead reticle_type = 0; } - else if(wep.wr_zoomreticle(wep) && autocvar_cl_reticle_weapon) + else if(wep_zoomed && autocvar_cl_reticle_weapon) { - if(reticle_image != "") { reticle_type = 2; } + if(reticle_image) { reticle_type = 2; } else { reticle_type = 0; } } else if(button_zoom || zoomscript_caught) @@@ -1998,7 -2014,7 +2022,7 @@@ switch(reticle_type) { case 1: drawpic(reticle_pos, "gfx/reticle_normal", reticle_size, '1 1 1', f * autocvar_cl_reticle_normal_alpha, DRAWFLAG_NORMAL); break; - case 2: drawpic(reticle_pos, reticle_image, reticle_size, '1 1 1', f * autocvar_cl_reticle_weapon_alpha, DRAWFLAG_NORMAL); break; + case 2: if(reticle_image) drawpic(reticle_pos, reticle_image, reticle_size, '1 1 1', f * autocvar_cl_reticle_weapon_alpha, DRAWFLAG_NORMAL); break; } } } diff --combined qcsrc/common/stats.qh index edfa47fd41,afde743241..44efee885e --- a/qcsrc/common/stats.qh +++ b/qcsrc/common/stats.qh @@@ -55,18 -55,12 +55,12 @@@ REGISTER_STAT(PL_CROUCH_MAX, vector REGISTER_STAT(KH_KEYS, int) - /** weapon requested to switch to; next WANTED weapon (for HUD) */ - REGISTER_STAT(SWITCHWEAPON, int) - /** weapon currently being switched to (is copied from switchweapon once switch is possible) */ - REGISTER_STAT(SWITCHINGWEAPON, int) - REGISTER_STAT(WEAPON_NEXTTHINK, float) #ifdef SVQC - SPECTATE_COPYFIELD(_STAT(WEAPON_NEXTTHINK)) float W_WeaponRateFactor(entity this); - float gameover; + float game_stopped; #endif REGISTER_STAT(WEAPONRATEFACTOR, float, W_WeaponRateFactor(this)) - REGISTER_STAT(GAMEOVER, int, gameover) + REGISTER_STAT(GAME_STOPPED, int, game_stopped) REGISTER_STAT(GAMESTARTTIME, float) REGISTER_STAT(STRENGTH_FINISHED, float) REGISTER_STAT(INVINCIBLE_FINISHED, float) @@@ -115,8 -109,6 +109,6 @@@ REGISTER_STAT(NADE_BONUS_SCORE, float REGISTER_STAT(HEALING_ORB, float) REGISTER_STAT(HEALING_ORB_ALPHA, float) REGISTER_STAT(PLASMA, int) - REGISTER_STAT(OK_AMMO_CHARGE, float) - REGISTER_STAT(OK_AMMO_CHARGEPOOL, float) REGISTER_STAT(FROZEN, int) REGISTER_STAT(REVIVE_PROGRESS, float) REGISTER_STAT(ROUNDLOST, int) @@@ -126,8 -118,12 +118,13 @@@ REGISTER_STAT(CAPTURE_PROGRESS, float REGISTER_STAT(ENTRAP_ORB, float) REGISTER_STAT(ENTRAP_ORB_ALPHA, float) REGISTER_STAT(ITEMSTIME, int, autocvar_sv_itemstime) +REGISTER_STAT(KILL_TIME, float) + #ifdef SVQC + bool autocvar_g_ctf_leaderboard; + #endif + REGISTER_STAT(CTF_SHOWLEADERBOARD, bool, autocvar_g_ctf_leaderboard) + #ifdef SVQC int autocvar_g_multijump; float autocvar_g_multijump_add; @@@ -218,22 -214,26 +215,26 @@@ float autocvar_sv_dodging_ramp_time float autocvar_sv_dodging_up_speed; bool autocvar_sv_dodging_wall_dodging; bool autocvar_sv_dodging_air_dodging; + float autocvar_sv_dodging_maxspeed = 450; #endif + #if 0 REGISTER_STAT(DODGING, int, g_dodging) REGISTER_STAT(DODGING_DELAY, float, autocvar_sv_dodging_delay) REGISTER_STAT(DODGING_DISTANCE_THRESHOLD, float, autocvar_sv_dodging_wall_distance_threshold) - REGISTER_STAT(DODGING_FROZEN, int, autocvar_sv_dodging_frozen) REGISTER_STAT(DODGING_FROZEN_NO_DOUBLETAP, int, autocvar_sv_dodging_frozen_doubletap) REGISTER_STAT(DODGING_HEIGHT_THRESHOLD, float, autocvar_sv_dodging_height_threshold) REGISTER_STAT(DODGING_HORIZ_SPEED, float, autocvar_sv_dodging_horiz_speed) REGISTER_STAT(DODGING_HORIZ_SPEED_FROZEN, float, autocvar_sv_dodging_horiz_speed_frozen) REGISTER_STAT(DODGING_RAMP_TIME, float, autocvar_sv_dodging_ramp_time) - /** cvar loopback */ - REGISTER_STAT(DODGING_TIMEOUT, float) REGISTER_STAT(DODGING_UP_SPEED, float, autocvar_sv_dodging_up_speed) REGISTER_STAT(DODGING_WALL, bool, autocvar_sv_dodging_wall_dodging) REGISTER_STAT(DODGING_AIR, bool, autocvar_sv_dodging_air_dodging) + REGISTER_STAT(DODGING_MAXSPEED, float, autocvar_sv_dodging_maxspeed) + #endif + /** cvar loopback */ + REGISTER_STAT(DODGING_FROZEN, int, autocvar_sv_dodging_frozen) + REGISTER_STAT(DODGING_TIMEOUT, float) REGISTER_STAT(JETPACK_ACCEL_SIDE, float, autocvar_g_jetpack_acceleration_side) REGISTER_STAT(JETPACK_ACCEL_UP, float, autocvar_g_jetpack_acceleration_up) diff --combined qcsrc/server/defs.qh index f719d60c25,3f1867758d..ccb361ea69 --- a/qcsrc/server/defs.qh +++ b/qcsrc/server/defs.qh @@@ -47,8 -47,6 +47,6 @@@ float server_is_dedicated .float pain_frame; //" .float crouch; // Crouching or not? - .float strength_finished = _STAT(STRENGTH_FINISHED); - .float invincible_finished = _STAT(INVINCIBLE_FINISHED); .float superweapons_finished = _STAT(SUPERWEAPONS_FINISHED); .float cnt; // used in too many places @@@ -96,7 -94,7 +94,7 @@@ const float MAX_DAMAGEEXTRARADIUS = 16 .float dmgtime; .float killcount; -.float damage_dealt, typehitsound; +.float damage_dealt, typehitsound, killsound; .float watersound_finished; .float iscreature; @@@ -116,7 -114,7 +114,7 @@@ // WEAPONTODO .float autoswitch; - bool client_hasweapon(entity this, Weapon wpn, float andammo, bool complain); + bool client_hasweapon(entity this, Weapon wpn, .entity weaponentity, float andammo, bool complain); void w_clear(Weapon thiswep, entity actor, .entity weaponentity, int fire); void w_ready(Weapon thiswep, entity actor, .entity weaponentity, int fire); // VorteX: standalone think for weapons, so normal think on weaponentity can be reserved by weaponflashes (which needs update even player dies) @@@ -208,7 -206,7 +206,7 @@@ float bot_waypoints_for_items #else #define ATTACK_FINISHED_FOR(ent, w, slot) ((ent).attack_finished_single[slot]) #endif - #define ATTACK_FINISHED(ent, slot) ATTACK_FINISHED_FOR(ent, PS(ent).m_weapon.m_id, slot) + #define ATTACK_FINISHED(ent, slot) ATTACK_FINISHED_FOR(ent, ent.(weaponentity).m_weapon.m_id, slot) // assault game mode: Which team is attacking in this round? float assault_attacker_team; @@@ -319,7 -317,6 +317,7 @@@ string matchid .float hit_time = _STAT(HIT_TIME); .float typehit_time = _STAT(TYPEHIT_TIME); +.float kill_time = _STAT(KILL_TIME); .float damage_dealt_total = _STAT(DAMAGE_DEALT_TOTAL); @@@ -378,7 -375,6 +376,6 @@@ const float ACTIVE_TOGGLE = 3 .float team_forced; // can be a team number to force a team, or 0 for default action, or -1 for forced spectator .float player_blocked; - .float weapon_blocked; // weapon use disabled .float revive_progress = _STAT(REVIVE_PROGRESS); .float revival_time; // time at which player was last revived diff --combined qcsrc/server/g_damage.qc index ab487eac20,a8f365cbc2..7f5ffaf79b --- a/qcsrc/server/g_damage.qc +++ b/qcsrc/server/g_damage.qc @@@ -33,7 -33,7 +33,7 @@@ void UpdateFrags(entity player, int f void GiveFrags (entity attacker, entity targ, float f, int deathtype) { // TODO route through PlayerScores instead - if(gameover) return; + if(game_stopped) return; if(f < 0) { @@@ -58,13 -58,15 +58,15 @@@ PlayerScore_Add(targ, SP_DEATHS, 1); + .entity weaponentity = weaponentities[0]; // TODO: unhardcode + if(targ != attacker) // not for suicides if(g_weaponarena_random) { // after a frag, exchange the current weapon (or the culprit, if detectable) by a new random weapon Weapon culprit = DEATH_WEAPONOF(deathtype); - if(!culprit) culprit = PS(attacker).m_weapon; - else if(!(attacker.weapons & (culprit.m_wepset))) culprit = PS(attacker).m_weapon; + if(!culprit) culprit = attacker.(weaponentity).m_weapon; + else if(!(attacker.weapons & (culprit.m_wepset))) culprit = attacker.(weaponentity).m_weapon; if(g_weaponarena_random_with_blaster && culprit == WEP_BLASTER) // WEAPONTODO: Shouldn't this be in a mutator? { @@@ -97,8 -99,8 +99,8 @@@ } // after a frag, choose another random weapon set - if (!(attacker.weapons & WepSet_FromWeapon(PS(attacker).m_weapon))) - W_SwitchWeapon_Force(attacker, w_getbestweapon(attacker)); + if (!(attacker.weapons & WepSet_FromWeapon(attacker.(weaponentity).m_weapon))) + W_SwitchWeapon_Force(attacker, w_getbestweapon(attacker, weaponentity), weaponentity); } // FIXME fix the mess this is (we have REAL points now!) @@@ -115,12 -117,15 +117,15 @@@ string AppendItemcodes(string s, entity player) { - int w = PS(player).m_weapon.m_id; - //if(w == 0) - // w = player.switchweapon; - if(w == 0) - w = player.cnt; // previous weapon! - s = strcat(s, ftos(w)); + for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot) + { + .entity weaponentity = weaponentities[slot]; + int w = player.(weaponentity).m_weapon.m_id; + if(w == 0) + w = player.(weaponentity).cnt; // previous weapon + if(w != 0 || slot == 0) + s = strcat(s, ftos(w)); + } if(time < player.strength_finished) s = strcat(s, "S"); if(time < player.invincible_finished) @@@ -370,8 -375,6 +375,8 @@@ void Obituary(entity attacker, entity i attacker.taunt_soundtime = time + 1; attacker.killcount = attacker.killcount + 1; + attacker.killsound += 1; + #define SPREE_ITEM(counta,countb,center,normal,gentle) \ case counta: \ { \ @@@ -558,9 -561,17 +563,17 @@@ void Freeze (entity targ, float freeze_ Ice_Think(ice); - RemoveGrapplingHook(targ); + RemoveGrapplingHooks(targ); - FOREACH_CLIENT(IS_PLAYER(it) && it.hook.aiment == targ, LAMBDA(RemoveGrapplingHook(it))); + FOREACH_CLIENT(IS_PLAYER(it), + { + for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot) + { + .entity weaponentity = weaponentities[slot]; + if(it.(weaponentity).hook.aiment == targ) + RemoveHook(it.(weaponentity).hook); + } + }); // add waypoint if(show_waypoint) @@@ -587,7 -598,15 +600,15 @@@ void Unfreeze (entity targ WaypointSprite_Kill(targ.waypointsprite_attached); - FOREACH_CLIENT(IS_PLAYER(it) && it.hook.aiment == targ, LAMBDA(RemoveGrapplingHook(it))); + FOREACH_CLIENT(IS_PLAYER(it), + { + for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot) + { + .entity weaponentity = weaponentities[slot]; + if(it.(weaponentity).hook.aiment == targ) + RemoveHook(it.(weaponentity).hook); + } + }); // remove the ice block if(targ.iceblock) @@@ -604,7 -623,7 +625,7 @@@ void Damage (entity targ, entity inflic mirrordamage = 0; mirrorforce = 0; - if (gameover || targ.killcount == FRAGS_SPECTATOR) + if (game_stopped || targ.killcount == FRAGS_SPECTATOR) return; damage_targ = targ; @@@ -612,12 -631,6 +633,6 @@@ damage_attacker = attacker; attacker_save = attacker; - if(IS_PLAYER(targ)) - if(targ.hook) - if(targ.hook.aiment) - if(targ.hook.aiment == attacker) - RemoveGrapplingHook(targ); // STOP THAT, you parasite! - // special rule: gravity bomb does not hit team mates (other than for disconnecting the hook) if(DEATH_ISWEAPON(deathtype, WEP_HOOK) || DEATH_ISWEAPON(deathtype, WEP_TUBA)) { @@@ -715,11 -728,21 +730,21 @@@ } // should this be changed at all? If so, in what way? - MUTATOR_CALLHOOK(PlayerDamage_Calculate, inflictor, attacker, targ, deathtype, damage, mirrordamage, force); + MUTATOR_CALLHOOK(Damage_Calculate, inflictor, attacker, targ, deathtype, damage, mirrordamage, force); damage = M_ARGV(4, float); mirrordamage = M_ARGV(5, float); force = M_ARGV(6, vector); + if(IS_PLAYER(targ) && damage > 0 && attacker) + { + for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot) + { + .entity weaponentity = weaponentities[slot]; + if(targ.(weaponentity).hook && targ.(weaponentity).hook.aiment == attacker) + RemoveHook(targ.(weaponentity).hook); + } + } + if(STAT(FROZEN, targ)) if(deathtype != DEATH_HURTTRIGGER.m_id && deathtype != DEATH_TEAMCHANGE.m_id && deathtype != DEATH_AUTOTEAMCHANGE.m_id) { @@@ -1006,7 -1029,7 +1031,7 @@@ float RadiusDamageForSource (entity inf LOG_INFOF("THROUGHFLOOR: D=%f F=%f max(dD)=1/%f max(dF)=1/%f", finaldmg, vlen(force), mininv_d, mininv_f); - total = 0.25 * pow(max(mininv_f, mininv_d), 2); + total = 0.25 * (max(mininv_f, mininv_d) ** 2); if(autocvar_g_throughfloor_debug) LOG_INFOF(" steps=%f", total); diff --combined qcsrc/server/g_world.qc index 2acc67a6e9,2e7ae5fa75..71c731a308 --- a/qcsrc/server/g_world.qc +++ b/qcsrc/server/g_world.qc @@@ -227,9 -227,11 +227,11 @@@ void cvar_changes_init( BADCVAR("sys_specialcharactertranslation"); BADCVAR("timeformat"); BADCVAR("timestamps"); + BADCVAR("g_require_stats"); BADPREFIX("developer_"); BADPREFIX("g_ban_"); BADPREFIX("g_banned_list"); + BADPREFIX("g_require_stats_"); BADPREFIX("g_chat_flood_"); BADPREFIX("g_ghost_items"); BADPREFIX("g_playerstats_"); @@@ -251,17 -253,22 +253,22 @@@ // mapinfo BADCVAR("fraglimit"); + BADCVAR("g_arena"); BADCVAR("g_assault"); BADCVAR("g_ca"); BADCVAR("g_ca_teams"); + BADCVAR("g_conquest"); BADCVAR("g_ctf"); BADCVAR("g_cts"); + BADCVAR("g_dotc"); BADCVAR("g_dm"); BADCVAR("g_domination"); BADCVAR("g_domination_default_teams"); BADCVAR("g_freezetag"); BADCVAR("g_freezetag_teams"); BADCVAR("g_invasion_teams"); + BADCVAR("g_jailbreak"); + BADCVAR("g_jailbreak_teams"); BADCVAR("g_keepaway"); BADCVAR("g_keyhunt"); BADCVAR("g_keyhunt_teams"); @@@ -272,12 -279,15 +279,15 @@@ BADCVAR("g_race_laps_limit"); BADCVAR("g_race_qualifying_timelimit"); BADCVAR("g_race_qualifying_timelimit_override"); + BADCVAR("g_snafu"); BADCVAR("g_tdm"); BADCVAR("g_tdm_teams"); + BADCVAR("g_vip"); BADCVAR("leadlimit"); BADCVAR("nextmap"); BADCVAR("teamplay"); BADCVAR("timelimit"); + BADCVAR("g_mapinfo_ignore_warnings"); // long BADCVAR("hostname"); @@@ -307,6 -317,8 +317,8 @@@ BADCVAR("gameversion"); BADCVAR("g_allow_oldvortexbeam"); BADCVAR("g_balance_kill_delay"); + BADCVAR("g_buffs_pickup_anyway"); + BADCVAR("g_buffs_randomize"); BADCVAR("g_campcheck_distance"); BADCVAR("g_ca_point_leadlimit"); BADCVAR("g_ca_point_limit"); @@@ -319,11 -331,14 +331,14 @@@ BADCVAR("g_freezetag_point_limit"); BADCVAR("g_hats"); BADCVAR("g_invasion_point_limit"); + BADCVAR("g_jump_grunt"); BADCVAR("g_keyhunt_point_leadlimit"); + BADCVAR("g_maplist_selectrandom"); BADCVAR("g_nexball_goalleadlimit"); BADCVAR("g_new_toys_use_pickupsound"); BADCVAR("g_physics_predictall"); BADCVAR("g_piggyback"); + BADCVAR("g_playerclip_collisions"); BADCVAR("g_tdm_point_leadlimit"); BADCVAR("g_tdm_point_limit"); BADCVAR("leadlimit_and_fraglimit"); @@@ -336,6 -351,7 +351,7 @@@ BADCVAR("sv_precacheplayermodels"); BADCVAR("sv_stepheight"); BADCVAR("sv_timeout"); + BADCVAR("sv_weapons_modeloverride"); BADPREFIX("crypto_"); BADPREFIX("gameversion_"); BADPREFIX("g_chat_"); @@@ -400,6 -416,7 +416,7 @@@ BADCVAR("g_nexball_goallimit"); BADCVAR("g_norecoil"); BADCVAR("g_physics_clientselect"); + BADCVAR("g_pinata"); BADCVAR("g_powerups"); BADCVAR("g_spawnshieldtime"); BADCVAR("g_start_delay"); @@@ -1137,7 -1154,7 +1154,7 @@@ float(float exponent) MaplistMethod_Shu string newlist; // now reinsert this at another position - insertpos = pow(random(), 1 / exponent); // ]0, 1] + insertpos = (random() ** (1 / exponent)); // ]0, 1] insertpos = insertpos * (Map_Count - 1); // ]0, Map_Count - 1] insertpos = ceil(insertpos) + 1; // {2, 3, 4, ..., Map_Count} LOG_TRACE("SHUFFLE: insert pos = ", ftos(insertpos)); @@@ -1447,11 -1464,11 +1464,11 @@@ void DumpStats(float final s = strcat(s, "spectator:"); if(to_console) - LOG_INFO(s, it.netname, "\n"); + LOG_INFO(s, playername(it, false), "\n"); if(to_eventlog) - GameLogEcho(strcat(s, ftos(it.playerid), ":", it.netname)); + GameLogEcho(strcat(s, ftos(it.playerid), ":", playername(it, false))); if(to_file) - fputs(file, strcat(s, it.netname, "\n")); + fputs(file, strcat(s, playername(it, false), "\n")); )); if(teamplay) @@@ -1528,9 -1545,8 +1545,8 @@@ only called if a time or frag limit ha */ void NextLevel() { - gameover = true; - - intermission_running = 1; + game_stopped = true; + intermission_running = 1; // game over // enforce a wait time before allowing changelevel if(player_count > 0) @@@ -1565,7 -1581,7 +1581,7 @@@ FOREACH_CLIENT(IS_PLAYER(it), LAMBDA( FixIntermissionClient(it); if(it.winning) - bprint(it.netname, " ^7wins.\n"); + bprint(playername(it, false), " ^7wins.\n"); )); target_music_kill(); @@@ -1587,7 -1603,7 +1603,7 @@@ Exit deathmatch games upon condition */ void CheckRules_Player(entity this) { - if (gameover) // someone else quit the game already + if (game_stopped) // someone else quit the game already return; if(!IS_DEAD(this)) @@@ -2030,7 -2046,9 +2046,9 @@@ void Physics_Frame( if(IS_CLIENT(it) || it.classname == "" || it.move_movetype == MOVETYPE_PUSH || it.move_movetype == MOVETYPE_FAKEPUSH || it.move_movetype == MOVETYPE_PHYSICS) continue; - set_movetype(it, it.move_movetype); + //set_movetype(it, it.move_movetype); + // inline the set_movetype function, since this is called a lot + it.movetype = (it.move_qcphysics) ? MOVETYPE_NONE : it.move_movetype; if(it.move_movetype == MOVETYPE_NONE) continue; @@@ -2068,8 -2086,6 +2086,8 @@@ void EndFrame( entity e = IS_SPEC(it) ? it.enemy : it; if (e.typehitsound) { it.typehit_time = time; + } else if (e.killsound) { + it.kill_time = time; } else if (e.damage_dealt) { it.hit_time = time; it.damage_dealt_total += ceil(e.damage_dealt); @@@ -2084,17 -2100,12 +2102,13 @@@ FOREACH_CLIENT(true, { it.typehitsound = false; it.damage_dealt = 0; + it.killsound = false; antilag_record(it, CS(it), altime); }); IL_EACH(g_monsters, true, { antilag_record(it, it, altime); }); - FOREACH_CLIENT(PS(it), { - PlayerState s = PS(it); - s.ps_push(s, it); - }); systems_update(); IL_ENDFRAME(); } @@@ -2167,7 -2178,7 +2181,7 @@@ void RestoreGame( void Shutdown() { - gameover = 2; + game_stopped = 2; if(world_initialized > 0) {