From 86cb53733158006e811537e6214b56500ea14a47 Mon Sep 17 00:00:00 2001 From: div0 Date: Thu, 28 Aug 2008 13:23:46 +0000 Subject: [PATCH] zoom: do it entirely client side git-svn-id: svn://svn.icculus.org/nexuiz/trunk@4221 f962a42d-fe04-0410-a3ab-8c8b0445ebaa --- data/qcsrc/client/Main.qc | 35 ++++++++++++++++--- data/qcsrc/client/View.qc | 64 ++++++++++++++++++++++++++++++++++ data/qcsrc/client/main.qh | 7 ++++ data/qcsrc/client/sbar.qc | 1 - data/qcsrc/common/constants.qh | 1 + data/qcsrc/server/cl_client.qc | 57 ++++-------------------------- 6 files changed, 108 insertions(+), 57 deletions(-) diff --git a/data/qcsrc/client/Main.qc b/data/qcsrc/client/Main.qc index 739aa2977..30958102c 100644 --- a/data/qcsrc/client/Main.qc +++ b/data/qcsrc/client/Main.qc @@ -67,6 +67,11 @@ void CSQC_Init(void) registercmd("sbar_columns_set"); registercmd("sbar_columns_help"); + registercmd("+button3"); + registercmd("-button3"); + registercmd("+button4"); + registercmd("-button4"); + registercvar("sbar_usecsqc", "1"); registercvar("sbar_columns", "default", CVAR_SAVE); @@ -197,6 +202,7 @@ void PostInit(void) // CSQC_ConsoleCommand : Used to parse commands in the console that have been registered with the "registercmd" function // Return value should be 1 if CSQC handled the command, otherwise return 0 to have the engine handle it. +float button_zoom; void Cmd_Sbar_SetFields(float); void Cmd_Sbar_Help(float); float CSQC_ConsoleCommand(string strMessage) @@ -210,11 +216,19 @@ float CSQC_ConsoleCommand(string strMessage) local string strCmd; strCmd = argv(0); - /*if(strCmd == "ctf_menu") { - ctf_menu_show(); - nReturn = true; - } else*/ - if(strCmd == "ons_map") { + if(strCmd == "+button4") { // zoom + button_zoom = 1; + return true; + } else if(strCmd == "-button4") { // zoom + button_zoom = 0; + return true; + } else if(strCmd == "+button3") { // secondary + button_attack2 = 1; + return false; + } else if(strCmd == "-button3") { // secondary + button_attack2 = 0; + return false; + } else if(strCmd == "ons_map") { Cmd_ons_map(); return true; } else if(strCmd == "sbar_columns_set") { @@ -600,6 +614,7 @@ void Net_ReadInit() { csqc_revision = ReadShort(); maxclients = ReadByte(); + minstagib = ReadByte(); CSQC_CheckRevision(); } @@ -723,6 +738,12 @@ void Net_ReadSpectating() spectatee_status = newspectatee_status; } +void Net_ReadSpawn() +{ + zoomin_effect = 1; + current_viewzoom = 0.6; +} + // CSQC_Parse_TempEntity : Handles all temporary entity network data in the CSQC layer. // You must ALWAYS first acquire the temporary ID, which is sent as a byte. // Return value should be 1 if CSQC handled the temporary entity, otherwise return 0 to have the engine process the event. @@ -769,6 +790,10 @@ float CSQC_Parse_TempEntity() Net_GrapplingHook(); bHandled = true; break; + case TE_CSQC_SPAWN: // TE_BEAM + Net_ReadSpawn(); + bHandled = true; + break; default: // No special logic for this temporary entity; return 0 so the engine can handle it bHandled = false; diff --git a/data/qcsrc/client/View.qc b/data/qcsrc/client/View.qc index f262cf9cd..72c143b98 100644 --- a/data/qcsrc/client/View.qc +++ b/data/qcsrc/client/View.qc @@ -2,6 +2,68 @@ float drawtime; +float tan(float x) +{ + return sin(x) / cos(x); +} +float atan2(float y, float x) +{ + vector v; + v = '1 0 0' * x + '0 1 0' * y; + v = vectoangles(v); + return v_y * 0.01745329251994329576; +} + +vector GetCurrentFov() +{ + float zoomspeed, zoomfactor, zoomdir; + + zoomfactor = cvar("cl_zoomfactor"); + if(zoomfactor < 1 || zoomfactor > 16) + zoomfactor = 2.5; + zoomspeed = cvar("cl_zoomspeed"); + if(zoomspeed >= 0) + if(zoomspeed < 0.5 || zoomspeed > 16) + zoomspeed = 3.5; + + zoomdir = button_zoom; + if(activeweapon == 7 && !minstagib) + zoomdir += button_attack2; + + if(zoomdir) + zoomin_effect = 0; + + if(zoomin_effect) + { + current_viewzoom = min(1, current_viewzoom + drawframetime); + } + else + { + if(zoomspeed < 0) // instant zoom + { + if(zoomdir) + current_viewzoom = 1 / zoomfactor; + else + current_viewzoom = 1; + } + else + { + if(zoomdir) + current_viewzoom = 1 / bound(1, 1 / current_viewzoom + drawframetime * zoomspeed * (zoomfactor - 1), zoomfactor); + else + current_viewzoom = bound(1 / zoomfactor, current_viewzoom + drawframetime * zoomspeed * (1 - 1 / zoomfactor), 1); + } + } + + float frustumx, frustumy, fovx, fovy; + frustumy = tan(cvar("fov") * 0.00872664625997164788) * 0.75 * current_viewzoom; + frustumx = frustumy * cvar("vid_width") / cvar("vid_height") / cvar("vid_pixelheight"); + fovx = atan2(frustumx, 1) / 0.00872664625997164788; + fovy = atan2(frustumy, 1) / 0.00872664625997164788; + + return '1 0 0' * fovx + '0 1 0' * fovy; +} + void CSQC_common_hud(void); void CSQC_kh_hud(void); @@ -37,6 +99,8 @@ void CSQC_UpdateView(void) // Assign Standard Viewflags // Draw the World (and sky) R_SetView(VF_DRAWWORLD, 1); + + R_SetView(VF_FOV, GetCurrentFov()); // Draw the Crosshair R_SetView(VF_DRAWCROSSHAIR, !Sbar_WouldDrawScoreboard()); diff --git a/data/qcsrc/client/main.qh b/data/qcsrc/client/main.qh index 2021c2b13..93220afad 100644 --- a/data/qcsrc/client/main.qh +++ b/data/qcsrc/client/main.qh @@ -113,3 +113,10 @@ entity teamslots[17]; // 17 teams (including "spectator team") .void(void) draw; float drawframetime; vector view_origin, view_angles, view_forward, view_right, view_up; + +float button_zoom; +float button_attack2; +float activeweapon; +float minstagib; +float current_viewzoom; +float zoomin_effect; diff --git a/data/qcsrc/client/sbar.qc b/data/qcsrc/client/sbar.qc index b4a7f0592..e125fc4cd 100644 --- a/data/qcsrc/client/sbar.qc +++ b/data/qcsrc/client/sbar.qc @@ -1,6 +1,5 @@ float last_weapon; -float activeweapon; float weapontime; float sb_lines; // still don't know what to do with that NOTE: check dp's sbar.c to see what that should be diff --git a/data/qcsrc/common/constants.qh b/data/qcsrc/common/constants.qh index de6c01770..342988224 100644 --- a/data/qcsrc/common/constants.qh +++ b/data/qcsrc/common/constants.qh @@ -197,6 +197,7 @@ const float TE_CSQC_SCORESINFO = 108; const float TE_CSQC_RACE = 109; const float TE_CSQC_FORCESCOREBOARD = 110; const float TE_CSQC_SPECTATING = 111; +const float TE_CSQC_SPAWN = 112; const float STAT_KH_KEYS = 32; const float STAT_CTF_STATE = 33; diff --git a/data/qcsrc/server/cl_client.qc b/data/qcsrc/server/cl_client.qc index ad39b7b3b..f3a73a21b 100644 --- a/data/qcsrc/server/cl_client.qc +++ b/data/qcsrc/server/cl_client.qc @@ -473,7 +473,6 @@ void PutObserverInServer (void) self.punchvector = '0 0 0'; self.oldvelocity = self.velocity; self.customizeentityforclient = Client_customizeentityforclient; - self.viewzoom = 1; self.wantswelcomemessage = 1; if(g_arena) @@ -680,8 +679,11 @@ void PutClientInServer (void) self.punchvector = '0 0 0'; self.oldvelocity = self.velocity; - self.viewzoom = 0.6; - self.has_zoomed = 0; + msg_entity = self; + WRITESPECTATABLE_MSG_ONE({ + WriteByte(MSG_ONE, SVC_TEMPENTITY); + WriteByte(MSG_ONE, TE_CSQC_SPAWN); + }); self.customizeentityforclient = Client_customizeentityforclient; @@ -772,6 +774,7 @@ void SendCSQCInfo(void) WriteByte(MSG_ONE, TE_CSQC_INIT); WriteShort(MSG_ONE, CSQC_REVISION); WriteByte(MSG_ONE, maxclients); + WriteByte(MSG_ONE, g_minstagib); } /* @@ -1668,7 +1671,6 @@ void SpectateCopy(entity spectatee) { self.punchangle = spectatee.punchangle; self.view_ofs = spectatee.view_ofs; self.v_angle = spectatee.v_angle; - self.viewzoom = spectatee.viewzoom; self.velocity = spectatee.velocity; self.dmg_take = spectatee.dmg_take; self.dmg_save = spectatee.dmg_save; @@ -2119,53 +2121,6 @@ void PlayerPreThink (void) W_WeaponFrame(); - { - float zoomfactor, zoomspeed, zoomdir; - zoomfactor = self.cvar_cl_zoomfactor; - if(zoomfactor < 1 || zoomfactor > 16) - zoomfactor = 2.5; - zoomspeed = self.cvar_cl_zoomspeed; - if(zoomspeed >= 0) // < 0 is instant zoom - if(zoomspeed < 0.5 || zoomspeed > 16) - zoomspeed = 3.5; - - zoomdir = self.BUTTON_ZOOM; - if(self.BUTTON_ATCK2) - if(self.weapon == WEP_NEX) - if(!g_minstagib) - zoomdir = 1; - - if(zoomdir) - self.has_zoomed = 1; - - if(self.has_zoomed) - { - if(zoomspeed <= 0) // instant zoom - { - if(zoomdir) - self.viewzoom = 1 / zoomfactor; - else - self.viewzoom = 1; - } - else - { - // geometric zoom would be: - // self.viewzoom = bound(1 / zoomfactor, self.viewzoom * pow(zoomfactor, (zoomdir ? -1 : 1) * frametime * zoomspeed), 1); - // however, testing showed that arithmetic/harmonic zoom works better - if(zoomdir) - // self.viewzoom = 1 / bound(1, 1 / self.viewzoom + (zoomdir ? 1 : -1) * frametime * zoomspeed * (zoomfactor - 1), zoomfactor); - // zoom in = arithmetic: 1x, 2x, 3x, 4x, ..., 8x - self.viewzoom = 1 / bound(1, 1 / self.viewzoom + frametime * zoomspeed * (zoomfactor - 1), zoomfactor); - else - // self.viewzoom = bound(1 / zoomfactor, self.viewzoom + (zoomdir ? -1 : 1) * frametime * zoomspeed * (1 - 1 / zoomfactor), 1); - // zoom out = harmonic: 8/1x, 8/2x, 8/3x, 8/4x, ..., 8/8x - self.viewzoom = bound(1 / zoomfactor, self.viewzoom + frametime * zoomspeed * (1 - 1 / zoomfactor), 1); - } - } - else - self.viewzoom = min(1, self.viewzoom + frametime); // spawn zoom-in - } - player_powerups(); player_regen(); player_anim(); -- 2.39.2