implemented PRYDON_CLIENTCURSOR extension (clientside mouse pointer that feeds back...
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Wed, 1 Dec 2004 05:39:03 +0000 (05:39 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Wed, 1 Dec 2004 05:39:03 +0000 (05:39 +0000)
added DP_BUTTONUSE extension (+use/-use button)
added DP_BUTTONCHAT extension (true while input is not focused on the game)
reimplemented DP_ENT_COLORMOD extension due to popular request, and changed its definition to allow colors above '1 1 1' for brightening effects
implemented PROTOCOL_DARKPLACES6 protocol, featuring delta compression of ammo counts and other properties (using generic svc_updatestat and svc_updatestatubyte messages), precaching models and sounds during the game (svc_precache).
removed cmd parameter from a lot of input code (now uses cl.cmd. instead of cmd->)
added sv_gameplayfix_setmodelrealbox to allow disabling of the setmodel real model bounding box on alias models (may improve mod compatibility if set to 0, thus performing a setsize (self, '-16 -16 -16', '16 16 16') instead of the real alias model box).
added SV_ModelIndex and SV_SoundIndex functions to clean up the server's precaching and model lookup processes (code reduction/maintenance reduction).
changed sv.model_precache and sv.sound_precache to be real char arrays rather than pointers, so precache names no longer need to be constants as they're now copied.
added some modelindex bounds checks to a few pieces of code.
the dpfields array is now sorted and matches the supported fields list (added the missing ones).
client now acknowledges the last 3 frames in each input packet to reduce packet loss issues.
renamed clc_ackentities to clc_ackframe as it is now used for compressing stats as well as entities in PROTOCOL_DARKPLACES6, this also means it always produces a packet for every frame even if there's no changed entities (or room under the rate limit for that matter)
PROTOCOL_DARKPLACES5 and 6 now perform a non-harmful serverside packetlog reset (marking all packets as lost) if the packetlog fills up, this should eliminate choked-to-death cases where the client lost everything for a few seconds.
MAX_CL_STATS expanded from 32 to 256 (just incase more stats are added, this prevents protocol breakage on too many unknown extra stats)
fixed a bug with the worst case rtlight rendering (the color array was disabled, oops).
some cl.* fields converted to cl.stats elements (STAT_ITEMS for instance) to accomodate the PROTOCOL_DARKPLACES6 stats updates

git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@4801 d7cf8633-e32d-0410-b094-e92efae38249

30 files changed:
cl_collision.c
cl_input.c
cl_main.c
cl_parse.c
client.h
common.c
gl_draw.c
gl_models.c
gl_rsurf.c
host.c
host_cmd.c
input.h
pr_cmds.c
pr_edict.c
progs.h
protocol.c
protocol.h
quakedef.h
r_shadow.c
r_sprites.c
sbar.c
server.h
sv_main.c
sv_user.c
vid_glx.c
vid_null.c
vid_sdl.c
vid_shared.c
vid_wgl.c
view.c

index c2f2eaa..bc88832 100644 (file)
@@ -143,8 +143,9 @@ float CL_SelectTraceLine(const vec3_t start, const vec3_t end, vec3_t impact, ve
                ent = &cl_entities[n].render;
                if (!ent->model || !ent->model->TraceBox)
                        continue;
-               //if (((ent->model->type != mod_brushq1 && ent->model->type != mod_brushq2 && ent->model->type != mod_brushq3) || ent->alpha < 1) && !(cl_entities[n].state_current.effects & EF_SELECTABLE))
-               //      continue;
+               // if transparent and not selectable, skip entity
+               if (!(cl_entities[n].state_current.effects & EF_SELECTABLE) && (ent->alpha < 1 || (ent->effects & (EF_ADDITIVE | EF_NODEPTHTEST))))
+                       continue;
                if (ent->mins[0] > tracemaxs[0] || ent->maxs[0] < tracemins[0]
                 || ent->mins[1] > tracemaxs[1] || ent->maxs[1] < tracemins[1]
                 || ent->mins[2] > tracemaxs[2] || ent->maxs[2] < tracemins[2])
index 610bd30..a9694dd 100644 (file)
@@ -49,7 +49,7 @@ state bit 2 is edge triggered on the down to up transition
 kbutton_t      in_mlook, in_klook;
 kbutton_t      in_left, in_right, in_forward, in_back;
 kbutton_t      in_lookup, in_lookdown, in_moveleft, in_moveright;
-kbutton_t      in_strafe, in_speed, in_jump, in_attack;
+kbutton_t      in_strafe, in_speed, in_jump, in_attack, in_use;
 kbutton_t      in_up, in_down;
 // LordHavoc: added 6 new buttons
 kbutton_t      in_button3, in_button4, in_button5, in_button6, in_button7, in_button8;
@@ -156,6 +156,9 @@ void IN_StrafeUp(void) {KeyUp(&in_strafe);}
 void IN_AttackDown(void) {KeyDown(&in_attack);}
 void IN_AttackUp(void) {KeyUp(&in_attack);}
 
+void IN_UseDown(void) {KeyDown(&in_use);}
+void IN_UseUp(void) {KeyUp(&in_use);}
+
 // LordHavoc: added 6 new buttons
 void IN_Button3Down(void) {KeyDown(&in_button3);}
 void IN_Button3Up(void) {KeyUp(&in_button3);}
@@ -305,31 +308,35 @@ CL_BaseMove
 Send the intended movement message to the server
 ================
 */
-void CL_BaseMove (usercmd_t *cmd)
+void CL_BaseMove (void)
 {
+       vec3_t temp;
        if (cls.signon != SIGNONS)
                return;
 
        CL_AdjustAngles ();
 
-       memset (cmd, 0, sizeof(*cmd));
+       // PRYDON_CLIENTCURSOR needs to survive basemove resets
+       VectorCopy (cl.cmd.cursor_screen, temp);
+       memset (&cl.cmd, 0, sizeof(cl.cmd));
+       VectorCopy (temp, cl.cmd.cursor_screen);
 
        if (in_strafe.state & 1)
        {
-               cmd->sidemove += cl_sidespeed.value * CL_KeyState (&in_right);
-               cmd->sidemove -= cl_sidespeed.value * CL_KeyState (&in_left);
+               cl.cmd.sidemove += cl_sidespeed.value * CL_KeyState (&in_right);
+               cl.cmd.sidemove -= cl_sidespeed.value * CL_KeyState (&in_left);
        }
 
-       cmd->sidemove += cl_sidespeed.value * CL_KeyState (&in_moveright);
-       cmd->sidemove -= cl_sidespeed.value * CL_KeyState (&in_moveleft);
+       cl.cmd.sidemove += cl_sidespeed.value * CL_KeyState (&in_moveright);
+       cl.cmd.sidemove -= cl_sidespeed.value * CL_KeyState (&in_moveleft);
 
-       cmd->upmove += cl_upspeed.value * CL_KeyState (&in_up);
-       cmd->upmove -= cl_upspeed.value * CL_KeyState (&in_down);
+       cl.cmd.upmove += cl_upspeed.value * CL_KeyState (&in_up);
+       cl.cmd.upmove -= cl_upspeed.value * CL_KeyState (&in_down);
 
        if (! (in_klook.state & 1) )
        {
-               cmd->forwardmove += cl_forwardspeed.value * CL_KeyState (&in_forward);
-               cmd->forwardmove -= cl_backspeed.value * CL_KeyState (&in_back);
+               cl.cmd.forwardmove += cl_forwardspeed.value * CL_KeyState (&in_forward);
+               cl.cmd.forwardmove -= cl_backspeed.value * CL_KeyState (&in_back);
        }
 
 //
@@ -337,20 +344,71 @@ void CL_BaseMove (usercmd_t *cmd)
 //
        if (in_speed.state & 1)
        {
-               cmd->forwardmove *= cl_movespeedkey.value;
-               cmd->sidemove *= cl_movespeedkey.value;
-               cmd->upmove *= cl_movespeedkey.value;
+               cl.cmd.forwardmove *= cl_movespeedkey.value;
+               cl.cmd.sidemove *= cl_movespeedkey.value;
+               cl.cmd.upmove *= cl_movespeedkey.value;
        }
 }
 
 
+#include "cl_collision.h"
+
+void CL_UpdatePrydonCursor(void)
+{
+       vec3_t temp, scale;
+
+       if (!cl_prydoncursor.integer)
+               VectorClear(cl.cmd.cursor_screen);
+
+       /*
+       if (cl.cmd.cursor_screen[0] < -1)
+       {
+               cl.viewangles[YAW] -= m_yaw.value * (cl.cmd.cursor_screen[0] - -1) * vid.realwidth * sensitivity.value * cl.viewzoom;
+               cl.cmd.cursor_screen[0] = -1;
+       }
+       if (cl.cmd.cursor_screen[0] > 1)
+       {
+               cl.viewangles[YAW] -= m_yaw.value * (cl.cmd.cursor_screen[0] - 1) * vid.realwidth * sensitivity.value * cl.viewzoom;
+               cl.cmd.cursor_screen[0] = 1;
+       }
+       if (cl.cmd.cursor_screen[1] < -1)
+       {
+               cl.viewangles[PITCH] += m_pitch.value * (cl.cmd.cursor_screen[1] - -1) * vid.realheight * sensitivity.value * cl.viewzoom;
+               cl.cmd.cursor_screen[1] = -1;
+       }
+       if (cl.cmd.cursor_screen[1] > 1)
+       {
+               cl.viewangles[PITCH] += m_pitch.value * (cl.cmd.cursor_screen[1] - 1) * vid.realheight * sensitivity.value * cl.viewzoom;
+               cl.cmd.cursor_screen[1] = 1;
+       }
+       */
+       cl.cmd.cursor_screen[0] = bound(-1, cl.cmd.cursor_screen[0], 1);
+       cl.cmd.cursor_screen[1] = bound(-1, cl.cmd.cursor_screen[1], 1);
+       cl.cmd.cursor_screen[2] = 1;
+
+       scale[0] = -tan(r_refdef.fov_x * M_PI / 360.0);
+       scale[1] = -tan(r_refdef.fov_y * M_PI / 360.0);
+       scale[2] = 1;
+
+       // trace distance
+       VectorScale(scale, 1000000, scale);
+
+       // FIXME: use something other than renderer variables here
+       // (but they need to match)
+       VectorCopy(r_vieworigin, cl.cmd.cursor_start);
+       VectorSet(temp, cl.cmd.cursor_screen[2] * scale[2], cl.cmd.cursor_screen[0] * scale[0], cl.cmd.cursor_screen[1] * scale[1]);
+       Matrix4x4_Transform(&r_view_matrix, temp, cl.cmd.cursor_end);
+       cl.cmd.cursor_fraction = CL_SelectTraceLine(cl.cmd.cursor_start, cl.cmd.cursor_end, cl.cmd.cursor_impact, cl.cmd.cursor_normal, &cl.cmd.cursor_entitynumber);
+       // makes sparks where cursor is
+       //CL_SparkShower(cl.cmd.cursor_impact, cl.cmd.cursor_normal, 5, 0);
+}
 
 /*
 ==============
 CL_SendMove
 ==============
 */
-void CL_SendMove(usercmd_t *cmd)
+void CL_SendMove(void)
 {
        int i;
        int bits;
@@ -359,9 +417,11 @@ void CL_SendMove(usercmd_t *cmd)
        static double lastmovetime;
        static float forwardmove, sidemove, upmove, total; // accumulation
 
-       forwardmove += cmd->forwardmove;
-       sidemove += cmd->sidemove;
-       upmove += cmd->upmove;
+       CL_UpdatePrydonCursor();
+
+       forwardmove += cl.cmd.forwardmove;
+       sidemove += cl.cmd.sidemove;
+       upmove += cl.cmd.upmove;
        total++;
        // LordHavoc: cap outgoing movement messages to sys_ticrate
        if (!cl.islocalgame && (realtime - lastmovetime < sys_ticrate.value))
@@ -378,8 +438,6 @@ void CL_SendMove(usercmd_t *cmd)
        buf.cursize = 0;
        buf.data = data;
 
-       cl.cmd = *cmd;
-
        // send the movement message
        MSG_WriteByte (&buf, clc_move);
 
@@ -395,7 +453,7 @@ void CL_SendMove(usercmd_t *cmd)
                for (i = 0;i < 3;i++)
                        MSG_WriteAngle32f (&buf, cl.viewangles[i]);
        }
-       else if (cl.protocol == PROTOCOL_DARKPLACES1 || cl.protocol == PROTOCOL_DARKPLACES4 || cl.protocol == PROTOCOL_DARKPLACES5)
+       else if (cl.protocol == PROTOCOL_DARKPLACES1 || cl.protocol == PROTOCOL_DARKPLACES4 || cl.protocol == PROTOCOL_DARKPLACES5 || cl.protocol == PROTOCOL_DARKPLACES6)
        {
                for (i = 0;i < 3;i++)
                        MSG_WriteAngle16i (&buf, cl.viewangles[i]);
@@ -411,28 +469,58 @@ void CL_SendMove(usercmd_t *cmd)
        // send button bits
        bits = 0;
 
-       // LordHavoc: added 6 new buttons
-       if (in_attack.state  & 3) bits |=   1;in_attack.state  &= ~2;
-       if (in_jump.state    & 3) bits |=   2;in_jump.state    &= ~2;
-       if (in_button3.state & 3) bits |=   4;in_button3.state &= ~2;
-       if (in_button4.state & 3) bits |=   8;in_button4.state &= ~2;
-       if (in_button5.state & 3) bits |=  16;in_button5.state &= ~2;
-       if (in_button6.state & 3) bits |=  32;in_button6.state &= ~2;
-       if (in_button7.state & 3) bits |=  64;in_button7.state &= ~2;
-       if (in_button8.state & 3) bits |= 128;in_button8.state &= ~2;
-
-       MSG_WriteByte (&buf, bits);
+       // LordHavoc: added 13 new buttons and chat button
+       if (in_attack.state   & 3) bits |=   1;in_attack.state  &= ~2;
+       if (in_jump.state     & 3) bits |=   2;in_jump.state    &= ~2;
+       if (in_button3.state  & 3) bits |=   4;in_button3.state &= ~2;
+       if (in_button4.state  & 3) bits |=   8;in_button4.state &= ~2;
+       if (in_button5.state  & 3) bits |=  16;in_button5.state &= ~2;
+       if (in_button6.state  & 3) bits |=  32;in_button6.state &= ~2;
+       if (in_button7.state  & 3) bits |=  64;in_button7.state &= ~2;
+       if (in_button8.state  & 3) bits |= 128;in_button8.state &= ~2;
+       if (in_use.state      & 3) bits |= 256;in_use.state     &= ~2;
+       if (key_dest != key_game || key_consoleactive) bits |= 512;
+       if (cl_prydoncursor.integer) bits |= 1024;
+       // button bits 11-31 unused currently
+       if (cl.cmd.cursor_screen[0] <= -1) bits |= 8;
+       if (cl.cmd.cursor_screen[0] >=  1) bits |= 16;
+       if (cl.cmd.cursor_screen[1] <= -1) bits |= 32;
+       if (cl.cmd.cursor_screen[1] >=  1) bits |= 64;
+
+       if (cl.protocol == PROTOCOL_DARKPLACES6)
+               MSG_WriteLong (&buf, bits);
+       else
+               MSG_WriteByte (&buf, bits);
 
        MSG_WriteByte (&buf, in_impulse);
        in_impulse = 0;
 
-       // FIXME: should ack latest 3 frames perhaps?
-       if (cl.latestframenum > 0)
+       // PRYDON_CLIENTCURSOR
+       if (cl.protocol == PROTOCOL_DARKPLACES6)
+       {
+               // 30 bytes
+               MSG_WriteShort (&buf, cl.cmd.cursor_screen[0] * 32767.0f);
+               MSG_WriteShort (&buf, cl.cmd.cursor_screen[1] * 32767.0f);
+               MSG_WriteFloat (&buf, cl.cmd.cursor_start[0]);
+               MSG_WriteFloat (&buf, cl.cmd.cursor_start[1]);
+               MSG_WriteFloat (&buf, cl.cmd.cursor_start[2]);
+               MSG_WriteFloat (&buf, cl.cmd.cursor_impact[0]);
+               MSG_WriteFloat (&buf, cl.cmd.cursor_impact[1]);
+               MSG_WriteFloat (&buf, cl.cmd.cursor_impact[2]);
+               MSG_WriteShort (&buf, cl.cmd.cursor_entitynumber);
+       }
+
+       // ack the last few frame numbers
+       // (redundent to improve handling of client->server packet loss)
+       if (cl.latestframenums[LATESTFRAMENUMS-1] > 0)
        {
                if (developer_networkentities.integer >= 1)
-                       Con_Printf("send clc_ackentities %i\n", cl.latestframenum);
-               MSG_WriteByte(&buf, clc_ackentities);
-               MSG_WriteLong(&buf, cl.latestframenum);
+                       Con_Printf("send clc_ackframe %i\n", cl.latestframenums[LATESTFRAMENUMS-1]);
+               for (i = 0;i < LATESTFRAMENUMS;i++)
+               {
+                       MSG_WriteByte(&buf, clc_ackframe);
+                       MSG_WriteLong(&buf, cl.latestframenums[i]);
+               }
        }
 
        // deliver the message
@@ -492,6 +580,10 @@ void CL_InitInput (void)
        Cmd_AddCommand ("+mlook", IN_MLookDown);
        Cmd_AddCommand ("-mlook", IN_MLookUp);
 
+       // LordHavoc: added use button
+       Cmd_AddCommand ("+use", IN_UseDown);
+       Cmd_AddCommand ("-use", IN_UseUp);
+
        // LordHavoc: added 6 new buttons
        Cmd_AddCommand ("+button3", IN_Button3Down);
        Cmd_AddCommand ("-button3", IN_Button3Up);
index 75d0d0e..2898df6 100644 (file)
--- a/cl_main.c
+++ b/cl_main.c
@@ -61,6 +61,8 @@ cvar_t cl_beams_lightatend = {CVAR_SAVE, "cl_beams_lightatend", "0"};
 
 cvar_t cl_noplayershadow = {CVAR_SAVE, "cl_noplayershadow", "0"};
 
+cvar_t cl_prydoncursor = {0, "cl_prydoncursor", "0"};
+
 mempool_t *cl_refdef_mempool;
 mempool_t *cl_entities_mempool;
 
@@ -390,6 +392,7 @@ entity_t *CL_NewTempEntity(void)
        ent->render.colormap = -1; // no special coloring
        ent->render.scale = 1;
        ent->render.alpha = 1;
+       VectorSet(ent->render.colormod, 1, 1, 1);
        return ent;
 }
 
@@ -530,6 +533,7 @@ void CL_LinkNetworkEntity(entity_t *e)
                else
                        e->render.colormap = -1; // no special coloring
                e->render.skinnum = e->state_current.skin;
+               VectorScale(e->state_current.colormod, (1.0f / 32.0f), e->render.colormod);
                if (e->render.flags & RENDER_VIEWMODEL)
                {
                        if (!r_drawviewmodel.integer || chase_active.integer || envmap)
@@ -610,6 +614,8 @@ void CL_LinkNetworkEntity(entity_t *e)
                        // transfer certain model flags to effects
                        if (e->render.model->flags2 & EF_FULLBRIGHT)
                                e->render.effects |= EF_FULLBRIGHT;
+                       if (cl_prydoncursor.integer && (e->render.effects & EF_SELECTABLE) && cl.cmd.cursor_entitynumber == e - cl_entities)
+                               VectorScale(e->render.colormod, 2, e->render.colormod);
                }
 
                // animation lerp
@@ -886,6 +892,7 @@ void CL_RelinkWorld(void)
        ent->render.flags = RENDER_SHADOW;
        if (!r_fullbright.integer)
                ent->render.flags |= RENDER_LIGHT;
+       VectorSet(ent->render.colormod, 1, 1, 1);
 }
 
 static void CL_RelinkStaticEntities(void)
@@ -905,6 +912,7 @@ static void CL_RelinkStaticEntities(void)
                // hide player shadow during intermission or nehahra movie
                if (!(e->render.effects & EF_NOSHADOW) && !(e->render.flags & RENDER_TRANSPARENT))
                        e->render.flags |= RENDER_SHADOW;
+               VectorSet(e->render.colormod, 1, 1, 1);
                R_LerpAnimation(&e->render);
                r_refdef.entities[r_refdef.numentities++] = &e->render;
        }
@@ -931,7 +939,7 @@ static void CL_RelinkNetworkEntities(void)
        ent->state_current.flags = RENDER_VIEWMODEL;
        if (cl.stats[STAT_HEALTH] <= 0 || cl.intermission)
                ent->state_current.modelindex = 0;
-       else if (cl.items & IT_INVISIBILITY)
+       else if (cl.stats[STAT_ITEMS] & IT_INVISIBILITY)
        {
                if (gamemode == GAME_TRANSFUSION)
                        ent->state_current.alpha = 128;
@@ -998,6 +1006,7 @@ static void CL_RelinkEffects(void)
                                ent->render.frame = ent->render.frame2;
                                ent->render.colormap = -1; // no special coloring
                                ent->render.alpha = 1;
+                               VectorSet(ent->render.colormod, 1, 1, 1);
 
                                Matrix4x4_CreateFromQuakeEntity(&ent->render.matrix, e->origin[0], e->origin[1], e->origin[2], 0, 0, 0, 1);
                                Matrix4x4_Invert_Simple(&ent->render.inversematrix, &ent->render.matrix);
@@ -1198,10 +1207,10 @@ int CL_ReadFromServer(void)
 CL_SendCmd
 =================
 */
-void CL_SendCmd(usercmd_t *cmd)
+void CL_SendCmd(void)
 {
        if (cls.signon == SIGNONS)
-               CL_SendMove(cmd);
+               CL_SendMove();
 
        if (cls.demoplayback)
        {
@@ -1350,6 +1359,8 @@ void CL_Init (void)
        Cvar_RegisterVariable(&cl_beams_lightatend);
        Cvar_RegisterVariable(&cl_noplayershadow);
 
+       Cvar_RegisterVariable(&cl_prydoncursor);
+
        if (gamemode == GAME_NETHERWORLD)
        {
                Cvar_RegisterVariable (&cl_playermodel); 
index 54aa593..0e67fe3 100644 (file)
@@ -83,7 +83,7 @@ char *svc_strings[128] =
        "", // 48
        "", // 49
        "svc_cgame", //                         50              // [short] length [bytes] data
-       "svc_unusedlh1", //                     51              // unused
+       "svc_updatestatubyte", //                       51              // [byte] stat [byte] value
        "svc_effect", //                        52              // [vector] org [byte] modelindex [byte] startframe [byte] framecount [byte] framerate
        "svc_effect2", //                       53              // [vector] org [short] modelindex [short] startframe [byte] framecount [byte] framerate
        "svc_sound2", //                        54              // short soundindex instead of byte
@@ -332,9 +332,9 @@ void CL_ParseServerInfo (void)
        // hack for unmarked Nehahra movie demos which had a custom protocol
        if (i == PROTOCOL_QUAKE && cls.demoplayback && demo_nehahra.integer)
                i = PROTOCOL_NEHAHRAMOVIE;
-       if (i != PROTOCOL_QUAKE && i != PROTOCOL_DARKPLACES1 && i != PROTOCOL_DARKPLACES2 && i != PROTOCOL_DARKPLACES3 && i != PROTOCOL_DARKPLACES4 && i != PROTOCOL_DARKPLACES5 && i != PROTOCOL_NEHAHRAMOVIE)
+       if (i != PROTOCOL_QUAKE && i != PROTOCOL_DARKPLACES1 && i != PROTOCOL_DARKPLACES2 && i != PROTOCOL_DARKPLACES3 && i != PROTOCOL_DARKPLACES4 && i != PROTOCOL_DARKPLACES5 && i != PROTOCOL_DARKPLACES6 && i != PROTOCOL_NEHAHRAMOVIE)
        {
-               Host_Error("CL_ParseServerInfo: Server is protocol %i, not %i (Quake), %i (DP1), %i (DP2), %i (DP3), %i (DP4), %i (DP5), or %i (Nehahra movie)", i, PROTOCOL_QUAKE, PROTOCOL_DARKPLACES1, PROTOCOL_DARKPLACES2, PROTOCOL_DARKPLACES3, PROTOCOL_DARKPLACES4, PROTOCOL_DARKPLACES5, PROTOCOL_NEHAHRAMOVIE);
+               Host_Error("CL_ParseServerInfo: Server is protocol %i, not %i (Quake), %i (DP1), %i (DP2), %i (DP3), %i (DP4), %i (DP5), %i (DP6), or %i (Nehahra movie)", i, PROTOCOL_QUAKE, PROTOCOL_DARKPLACES1, PROTOCOL_DARKPLACES2, PROTOCOL_DARKPLACES3, PROTOCOL_DARKPLACES4, PROTOCOL_DARKPLACES5, PROTOCOL_DARKPLACES6, PROTOCOL_NEHAHRAMOVIE);
                return;
        }
        cl.protocol = i;
@@ -592,6 +592,25 @@ void CL_ParseClientdata (int bits)
 {
        int i, j;
 
+       VectorCopy (cl.mvelocity[0], cl.mvelocity[1]);
+
+       if (cl.protocol != PROTOCOL_DARKPLACES6)
+       {
+               cl.stats[STAT_VIEWHEIGHT] = DEFAULT_VIEWHEIGHT;
+               cl.stats[STAT_ITEMS] = 0;
+               cl.stats[STAT_VIEWZOOM] = 255;
+       }
+       cl.idealpitch = 0;
+       cl.punchangle[0] = 0;
+       cl.punchangle[1] = 0;
+       cl.punchangle[2] = 0;
+       cl.punchvector[0] = 0;
+       cl.punchvector[1] = 0;
+       cl.punchvector[2] = 0;
+       cl.mvelocity[0][0] = 0;
+       cl.mvelocity[0][1] = 0;
+       cl.mvelocity[0][2] = 0;
+
        bits &= 0xFFFF;
        if (bits & SU_EXTEND1)
                bits |= (MSG_ReadByte() << 16);
@@ -599,85 +618,63 @@ void CL_ParseClientdata (int bits)
                bits |= (MSG_ReadByte() << 24);
 
        if (bits & SU_VIEWHEIGHT)
-               cl.viewheight = MSG_ReadChar ();
-       else
-               cl.viewheight = DEFAULT_VIEWHEIGHT;
+               cl.stats[STAT_VIEWHEIGHT] = MSG_ReadChar ();
 
        if (bits & SU_IDEALPITCH)
                cl.idealpitch = MSG_ReadChar ();
-       else
-               cl.idealpitch = 0;
 
-       VectorCopy (cl.mvelocity[0], cl.mvelocity[1]);
        for (i = 0;i < 3;i++)
        {
                if (bits & (SU_PUNCH1<<i) )
                {
-                       if (cl.protocol == PROTOCOL_DARKPLACES1 || cl.protocol == PROTOCOL_DARKPLACES2 || cl.protocol == PROTOCOL_DARKPLACES3 || cl.protocol == PROTOCOL_DARKPLACES4 || cl.protocol == PROTOCOL_DARKPLACES5)
+                       if (cl.protocol == PROTOCOL_DARKPLACES1 || cl.protocol == PROTOCOL_DARKPLACES2 || cl.protocol == PROTOCOL_DARKPLACES3 || cl.protocol == PROTOCOL_DARKPLACES4 || cl.protocol == PROTOCOL_DARKPLACES5 || cl.protocol == PROTOCOL_DARKPLACES6)
                                cl.punchangle[i] = MSG_ReadAngle16i();
                        else if (cl.protocol == PROTOCOL_QUAKE || cl.protocol == PROTOCOL_NEHAHRAMOVIE)
                                cl.punchangle[i] = MSG_ReadChar();
                        else
                                Host_Error("CL_ParseClientData: unknown cl.protocol %i\n", cl.protocol);
                }
-               else
-                       cl.punchangle[i] = 0;
                if (bits & (SU_PUNCHVEC1<<i))
                {
                        if (cl.protocol == PROTOCOL_DARKPLACES1 || cl.protocol == PROTOCOL_DARKPLACES2 || cl.protocol == PROTOCOL_DARKPLACES3 || cl.protocol == PROTOCOL_DARKPLACES4)
                                cl.punchvector[i] = MSG_ReadCoord16i();
-                       else if (cl.protocol == PROTOCOL_DARKPLACES5)
+                       else if (cl.protocol == PROTOCOL_DARKPLACES5 || cl.protocol == PROTOCOL_DARKPLACES6)
                                cl.punchvector[i] = MSG_ReadCoord32f();
                        else
                                Host_Error("CL_ParseClientData: unknown cl.protocol %i\n", cl.protocol);
                }
-               else
-                       cl.punchvector[i] = 0;
                if (bits & (SU_VELOCITY1<<i) )
                {
                        if (cl.protocol == PROTOCOL_QUAKE || cl.protocol == PROTOCOL_NEHAHRAMOVIE || cl.protocol == PROTOCOL_DARKPLACES1 || cl.protocol == PROTOCOL_DARKPLACES2 || cl.protocol == PROTOCOL_DARKPLACES3 || cl.protocol == PROTOCOL_DARKPLACES4)
                                cl.mvelocity[0][i] = MSG_ReadChar()*16;
-                       else if (cl.protocol == PROTOCOL_DARKPLACES5)
+                       else if (cl.protocol == PROTOCOL_DARKPLACES5 || cl.protocol == PROTOCOL_DARKPLACES6)
                                cl.mvelocity[0][i] = MSG_ReadCoord32f();
                        else
                                Host_Error("CL_ParseClientData: unknown cl.protocol %i\n", cl.protocol);
                }
-               else
-                       cl.mvelocity[0][i] = 0;
        }
 
-       i = MSG_ReadLong ();
-       if (cl.items != i)
-       {       // set flash times
-               for (j=0 ; j<32 ; j++)
-                       if ( (i & (1<<j)) && !(cl.items & (1<<j)))
-                               cl.item_gettime[j] = cl.time;
-               cl.items = i;
-       }
+       if (bits & SU_ITEMS)
+               cl.stats[STAT_ITEMS] = MSG_ReadLong ();
 
        cl.onground = (bits & SU_ONGROUND) != 0;
        cl.inwater = (bits & SU_INWATER) != 0;
 
-       if (cl.protocol == PROTOCOL_DARKPLACES5)
+       if (cl.protocol == PROTOCOL_DARKPLACES6)
+       {
+       }
+       else if (cl.protocol == PROTOCOL_DARKPLACES5)
        {
                cl.stats[STAT_WEAPONFRAME] = (bits & SU_WEAPONFRAME) ? MSG_ReadShort() : 0;
                cl.stats[STAT_ARMOR] = (bits & SU_ARMOR) ? MSG_ReadShort() : 0;
                cl.stats[STAT_WEAPON] = (bits & SU_WEAPON) ? MSG_ReadShort() : 0;
                cl.stats[STAT_HEALTH] = MSG_ReadShort();
                cl.stats[STAT_AMMO] = MSG_ReadShort();
-
                cl.stats[STAT_SHELLS] = MSG_ReadShort();
                cl.stats[STAT_NAILS] = MSG_ReadShort();
                cl.stats[STAT_ROCKETS] = MSG_ReadShort();
                cl.stats[STAT_CELLS] = MSG_ReadShort();
-               //cl.stats[STAT_GENERIC1] = MSG_ReadShort();
-               //cl.stats[STAT_GENERIC2] = MSG_ReadShort();
-               //cl.stats[STAT_GENERIC3] = MSG_ReadShort();
-               //cl.stats[STAT_GENERIC4] = MSG_ReadShort();
-               //cl.stats[STAT_GENERIC5] = MSG_ReadShort();
-               //cl.stats[STAT_GENERIC6] = MSG_ReadShort();
-
-               i = (unsigned short) MSG_ReadShort ();
+               cl.stats[STAT_ACTIVEWEAPON] = (unsigned short) MSG_ReadShort ();
        }
        else
        {
@@ -686,38 +683,41 @@ void CL_ParseClientdata (int bits)
                cl.stats[STAT_WEAPON] = (bits & SU_WEAPON) ? MSG_ReadByte() : 0;
                cl.stats[STAT_HEALTH] = MSG_ReadShort();
                cl.stats[STAT_AMMO] = MSG_ReadByte();
-       
                cl.stats[STAT_SHELLS] = MSG_ReadByte();
                cl.stats[STAT_NAILS] = MSG_ReadByte();
                cl.stats[STAT_ROCKETS] = MSG_ReadByte();
                cl.stats[STAT_CELLS] = MSG_ReadByte();
-
-               i = MSG_ReadByte ();
-               if (gamemode == GAME_HIPNOTIC || gamemode == GAME_ROGUE)
-                       i = (1<<i);
+               if (gamemode == GAME_HIPNOTIC || gamemode == GAME_ROGUE || gamemode == GAME_NEXUIZ)
+                       cl.stats[STAT_ACTIVEWEAPON] = (1<<MSG_ReadByte ());
+               else
+                       cl.stats[STAT_ACTIVEWEAPON] = MSG_ReadByte ();
        }
 
-       // GAME_NEXUIZ hud needs weapon change time
-       // GAME_NEXUIZ uses a bit number as it's STAT_ACTIVEWEAPON, not a bitfield
-       // like other modes
-       if (cl.stats[STAT_ACTIVEWEAPON] != i)
-               cl.weapontime = cl.time;
-       cl.stats[STAT_ACTIVEWEAPON] = i;
-
-       cl.viewzoomold = cl.viewzoomnew; // for interpolation
        if (bits & SU_VIEWZOOM)
        {
-               if (cl.protocol == PROTOCOL_DARKPLACES5)
-                       i = (unsigned short) MSG_ReadShort();
+               if (cl.protocol == PROTOCOL_DARKPLACES5 || cl.protocol == PROTOCOL_DARKPLACES6)
+                       cl.stats[STAT_VIEWZOOM] = (unsigned short) MSG_ReadShort();
                else
-                       i = MSG_ReadByte();
-               if (i < 2)
-                       i = 2;
-               cl.viewzoomnew = (float) i * (1.0f / 255.0f);
+                       cl.stats[STAT_VIEWZOOM] = MSG_ReadByte();
        }
-       else
-               cl.viewzoomnew = 1;
 
+       // check for important changes
+
+       // set flash times
+       if (cl.olditems != cl.stats[STAT_ITEMS])
+               for (j = 0;j < 32;j++)
+                       if ((cl.stats[STAT_ITEMS] & (1<<j)) && !(cl.olditems & (1<<j)))
+                               cl.item_gettime[j] = cl.time;
+       cl.olditems = cl.stats[STAT_ITEMS];
+
+       // GAME_NEXUIZ hud needs weapon change time
+       if (cl.activeweapon != cl.stats[STAT_ACTIVEWEAPON])
+               cl.weapontime = cl.time;
+       cl.activeweapon = cl.stats[STAT_ACTIVEWEAPON];
+
+       // viewzoom interpolation
+       cl.viewzoomold = cl.viewzoomnew;
+       cl.viewzoomnew = (float) max(cl.stats[STAT_VIEWZOOM], 2) * (1.0f / 255.0f);
 }
 
 /*
@@ -1428,8 +1428,8 @@ void CL_ParseServerMessage(void)
                        // hack for unmarked Nehahra movie demos which had a custom protocol
                        if (i == PROTOCOL_QUAKE && cls.demoplayback && demo_nehahra.integer)
                                i = PROTOCOL_NEHAHRAMOVIE;
-                       if (i != PROTOCOL_QUAKE && i != PROTOCOL_DARKPLACES1 && i != PROTOCOL_DARKPLACES2 && i != PROTOCOL_DARKPLACES3 && i != PROTOCOL_DARKPLACES4 && i != PROTOCOL_DARKPLACES5 && i != PROTOCOL_NEHAHRAMOVIE)
-                               Host_Error("CL_ParseServerMessage: Server is protocol %i, not %i (Quake), %i (DP1), %i (DP2), %i (DP3), %i (DP4), %i (DP5), or %i (Nehahra movie)", i, PROTOCOL_QUAKE, PROTOCOL_DARKPLACES1, PROTOCOL_DARKPLACES2, PROTOCOL_DARKPLACES3, PROTOCOL_DARKPLACES4, PROTOCOL_DARKPLACES5, PROTOCOL_NEHAHRAMOVIE);
+                       if (i != PROTOCOL_QUAKE && i != PROTOCOL_DARKPLACES1 && i != PROTOCOL_DARKPLACES2 && i != PROTOCOL_DARKPLACES3 && i != PROTOCOL_DARKPLACES4 && i != PROTOCOL_DARKPLACES5 && i != PROTOCOL_DARKPLACES6 && i != PROTOCOL_NEHAHRAMOVIE)
+                               Host_Error("CL_ParseServerMessage: Server is protocol %i, not %i (Quake), %i (DP1), %i (DP2), %i (DP3), %i (DP4), %i (DP5), %i (DP6), or %i (Nehahra movie)", i, PROTOCOL_QUAKE, PROTOCOL_DARKPLACES1, PROTOCOL_DARKPLACES2, PROTOCOL_DARKPLACES3, PROTOCOL_DARKPLACES4, PROTOCOL_DARKPLACES5, PROTOCOL_DARKPLACES6, PROTOCOL_NEHAHRAMOVIE);
                        cl.protocol = i;
                        break;
 
@@ -1488,8 +1488,43 @@ void CL_ParseServerMessage(void)
                        CL_ParseStartSoundPacket(false);
                        break;
 
-               case svc_sound2:
-                       CL_ParseStartSoundPacket(true);
+               case svc_precache:
+                       if (cl.protocol == PROTOCOL_DARKPLACES1 || cl.protocol == PROTOCOL_DARKPLACES2 || cl.protocol == PROTOCOL_DARKPLACES3)
+                       {
+                               // was svc_sound2 in protocols 1, 2, 3, removed in 4, 5, changed to svc_precache in 6
+                               CL_ParseStartSoundPacket(true);
+                       }
+                       else
+                       {
+                               int i = (unsigned short)MSG_ReadShort();
+                               char *s = MSG_ReadString();
+                               if (i < 32768)
+                               {
+                                       if (i >= 1 && i < MAX_MODELS)
+                                       {
+                                               model_t *model = Mod_ForName(s, false, false, i == 1);
+                                               if (!model)
+                                                       Con_Printf("svc_precache: Mod_ForName(\"%s\") failed\n", s);
+                                               cl.model_precache[i] = model;
+                                       }
+                                       else
+                                               Con_Printf("svc_precache: index %i outside range %i...%i\n", i, 1, MAX_MODELS);
+                               }
+                               else
+                               {
+                                       i -= 32768;
+                                       if (i >= 1 && i < MAX_SOUNDS)
+                                       {
+                                               sfx_t *sfx = S_PrecacheSound (s, true, false);
+                                               // FIXME: SFXFLAG_SERVEROSUND should be set on the sfx
+                                               if (!sfx)
+                                                       Con_Printf("svc_precache: S_PrecacheSound(\"%s\") failed\n", s);
+                                               cl.sound_precache[i] = sfx;
+                                       }
+                                       else
+                                               Con_Printf("svc_precache: index %i outside range %i...%i\n", i, 1, MAX_SOUNDS);
+                               }
+                       }
                        break;
 
                case svc_stopsound:
@@ -1584,6 +1619,13 @@ void CL_ParseServerMessage(void)
                        cl.stats[i] = MSG_ReadLong ();
                        break;
 
+               case svc_updatestatubyte:
+                       i = MSG_ReadByte ();
+                       if (i < 0 || i >= MAX_CL_STATS)
+                               Host_Error ("svc_updatestat: %i is invalid", i);
+                       cl.stats[i] = MSG_ReadByte ();
+                       break;
+
                case svc_spawnstaticsound:
                        CL_ParseStaticSound (false);
                        break;
@@ -1676,7 +1718,7 @@ void CL_ParseServerMessage(void)
                                EntityFrame_CL_ReadFrame();
                        else if (cl.protocol == PROTOCOL_DARKPLACES4)
                                EntityFrame4_CL_ReadFrame();
-                       else if (cl.protocol == PROTOCOL_DARKPLACES5)
+                       else if (cl.protocol == PROTOCOL_DARKPLACES5 || cl.protocol == PROTOCOL_DARKPLACES6)
                                EntityFrame5_CL_ReadFrame();
                        else
                                Host_Error("CL_ParseServerMessage: svc_entities: unknown cl.protocol %i\n", cl.protocol);
index 45dc560..b3272d1 100644 (file)
--- a/client.h
+++ b/client.h
@@ -255,6 +255,9 @@ typedef struct entity_render_s
        // render flags
        int flags;
 
+       // colormod tinting of models
+       float colormod[3];
+
        // interpolated animation
 
        // frame that the model is interpolating from
@@ -337,6 +340,14 @@ typedef struct
        float   forwardmove;
        float   sidemove;
        float   upmove;
+
+       vec3_t  cursor_screen;
+       vec3_t  cursor_start;
+       vec3_t  cursor_end;
+       vec3_t  cursor_impact;
+       vec3_t  cursor_normal;
+       vec_t   cursor_fraction;
+       int             cursor_entitynumber;
 } usercmd_t;
 
 typedef struct
@@ -456,16 +467,18 @@ typedef struct
        // send a clc_nop periodically until connected
        float sendnoptime;
 
-       // last command sent to the server
+       // current input to send to the server
        usercmd_t cmd;
 
 // information for local display
        // health, etc
        int stats[MAX_CL_STATS];
-       // inventory bit flags
-       int items;
+       // last known inventory bit flags, for blinking
+       int olditems;
        // cl.time of acquiring item, for blinking
        float item_gettime[32];
+       // last known STAT_ACTIVEWEAPON
+       int activeweapon;
        // cl.time of changing STAT_ACTIVEWEAPON
        float weapontime;
        // use pain anim frame if cl.time < this
@@ -503,7 +516,6 @@ typedef struct
        float driftmove;
        double laststop;
 
-       float viewheight;
        // local amount for smoothing stepups
        //float crouch;
 
@@ -569,8 +581,9 @@ typedef struct
        int protocol;
 
        // entity database stuff
-       // latest received entity frame number
-       int latestframenum;
+       // latest received entity frame numbers
+#define LATESTFRAMENUMS 3
+       int latestframenums[LATESTFRAMENUMS];
        entityframe_database_t *entitydatabase;
        entityframe4_database_t *entitydatabase4;
 }
@@ -625,6 +638,8 @@ extern cvar_t cl_explosions_lifetime;
 extern cvar_t cl_stainmaps;
 extern cvar_t cl_stainmapsclearonload;
 
+extern cvar_t cl_prydoncursor;
+
 // these are updated by CL_ClearState
 extern int cl_num_entities;
 extern int cl_num_static_entities;
@@ -682,8 +697,8 @@ extern      kbutton_t       in_strafe;
 extern         kbutton_t       in_speed;
 
 void CL_InitInput (void);
-void CL_SendCmd (usercmd_t *cmd);
-void CL_SendMove (usercmd_t *cmd);
+void CL_SendCmd (void);
+void CL_SendMove (void);
 
 void CL_ValidateState(entity_state_t *s);
 void CL_MoveLerpEntityStates(entity_t *ent);
@@ -700,8 +715,8 @@ void CL_ClearState (void);
 
 
 int  CL_ReadFromServer (void);
-void CL_WriteToServer (usercmd_t *cmd);
-void CL_BaseMove (usercmd_t *cmd);
+void CL_WriteToServer (void);
+void CL_BaseMove (void);
 
 
 float CL_KeyState (kbutton_t *key);
index 6f8065a..75c7ae9 100644 (file)
--- a/common.c
+++ b/common.c
@@ -273,9 +273,9 @@ void MSG_WriteCoord32f (sizebuf_t *sb, float f)
 
 void MSG_WriteCoord (sizebuf_t *sb, float f, int protocol)
 {
-       if (protocol == PROTOCOL_QUAKE)
+       if (protocol == PROTOCOL_QUAKE || protocol == PROTOCOL_NEHAHRAMOVIE)
                MSG_WriteCoord13i (sb, f);
-       else if (protocol == PROTOCOL_DARKPLACES1 || protocol == PROTOCOL_DARKPLACES5)
+       else if (protocol == PROTOCOL_DARKPLACES1 || protocol == PROTOCOL_DARKPLACES5 || protocol == PROTOCOL_DARKPLACES6)
                MSG_WriteCoord32f (sb, f);
        else if (protocol == PROTOCOL_DARKPLACES2 || protocol == PROTOCOL_DARKPLACES3 || protocol == PROTOCOL_DARKPLACES4)
                MSG_WriteCoord16i (sb, f);
@@ -314,7 +314,7 @@ void MSG_WriteAngle32f (sizebuf_t *sb, float f)
 
 void MSG_WriteAngle (sizebuf_t *sb, float f, int protocol)
 {
-       if (protocol == PROTOCOL_DARKPLACES5)
+       if (protocol == PROTOCOL_DARKPLACES5 || protocol == PROTOCOL_DARKPLACES6)
                MSG_WriteAngle16i (sb, f);
        else
                MSG_WriteAngle8i (sb, f);
@@ -445,9 +445,9 @@ float MSG_ReadCoord32f (void)
 
 float MSG_ReadCoord (int protocol)
 {
-       if (protocol == PROTOCOL_QUAKE || protocol == 250)
+       if (protocol == PROTOCOL_QUAKE || protocol == PROTOCOL_NEHAHRAMOVIE)
                return MSG_ReadCoord13i();
-       else if (protocol == PROTOCOL_DARKPLACES1 || protocol == PROTOCOL_DARKPLACES5)
+       else if (protocol == PROTOCOL_DARKPLACES1 || protocol == PROTOCOL_DARKPLACES5 || protocol == PROTOCOL_DARKPLACES6)
                return MSG_ReadCoord32f();
        else if (protocol == PROTOCOL_DARKPLACES2 || protocol == PROTOCOL_DARKPLACES3 || protocol == PROTOCOL_DARKPLACES4)
                return MSG_ReadCoord16i();
@@ -480,7 +480,7 @@ float MSG_ReadAngle32f (void)
 
 float MSG_ReadAngle (int protocol)
 {
-       if (protocol == PROTOCOL_DARKPLACES5)
+       if (protocol == PROTOCOL_DARKPLACES5 || protocol == PROTOCOL_DARKPLACES6)
                return MSG_ReadAngle16i ();
        else
                return MSG_ReadAngle8i ();
index 336912a..e63b7d4 100644 (file)
--- a/gl_draw.c
+++ b/gl_draw.c
@@ -308,6 +308,8 @@ cachepic_t  *Draw_CachePic (char *path)
                pic->tex = draw_generateconchars();
        if (pic->tex == NULL && !strcmp(path, "ui/mousepointer.tga"))
                pic->tex = draw_generatemousepointer();
+       if (pic->tex == NULL && !strcmp(path, "gfx/prydoncursor001.tga"))
+               pic->tex = draw_generatemousepointer();
        if (pic->tex == NULL && !strcmp(path, "gfx/crosshair1.tga"))
                pic->tex = draw_generatecrosshair(0);
        if (pic->tex == NULL && !strcmp(path, "gfx/crosshair2.tga"))
index 5bd5f03..1b2b134 100644 (file)
@@ -144,6 +144,9 @@ void R_DrawAliasModelCallback (const void *calldata1, int calldata2)
                        }
                        else
                                tint[0] = tint[1] = tint[2] = 1;
+                       tint[0] *= ent->colormod[0];
+                       tint[1] *= ent->colormod[1];
+                       tint[2] *= ent->colormod[2];
                        if (!fullbright && !(ent->flags & RENDER_TRANSPARENT))
                                colorscale *= r_lightmapintensity;
                        colorscale *= ifog;
index 72d3974..720f5c7 100644 (file)
@@ -832,7 +832,7 @@ static void RSurfShader_Transparent_Callback(const void *calldata1, int calldata
        base = fullbright ? 2.0f : r_ambient.value * (1.0f / 64.0f);
        if (surf->flags & SURF_DRAWTURB)
                base *= 0.5f;
-       if ((surf->flags & SURF_DRAWTURB) && gl_textureshader && r_watershader.value && !fogenabled && fullbright)
+       if ((surf->flags & SURF_DRAWTURB) && gl_textureshader && r_watershader.value && !fogenabled && fullbright && ent->colormod[0] == 1 && ent->colormod[1] == 1 && ent->colormod[2] == 1)
        {
                // NVIDIA Geforce3 distortion texture shader on water
                GL_Color(1, 1, 1, currentalpha);
@@ -882,7 +882,7 @@ static void RSurfShader_Transparent_Callback(const void *calldata1, int calldata
                        m.texrgbscale[0] = 4;
                        colorscale *= 0.25f;
                }
-               R_FillColors(varray_color4f, surf->mesh.num_vertices, base, base, base, currentalpha);
+               R_FillColors(varray_color4f, surf->mesh.num_vertices, base * ent->colormod[0], base * ent->colormod[1], base * ent->colormod[2], currentalpha);
                if (!fullbright)
                {
                        if (surf->dlightframe == r_framecount)
@@ -963,7 +963,7 @@ static void RSurfShader_OpaqueWall_Pass_BaseCombine_TextureLightmapDetailGlow(co
                m.tex[3] = R_GetTexture(texture->skin.glow);
                m.texcombinergb[3] = GL_ADD;
        }
-       GL_Color(r_lightmapintensity, r_lightmapintensity, r_lightmapintensity, 1);
+       GL_Color(r_lightmapintensity * ent->colormod[0], r_lightmapintensity * ent->colormod[1], r_lightmapintensity * ent->colormod[2], 1);
 
        while((surf = *surfchain++) != NULL)
        {
@@ -998,7 +998,7 @@ static void RSurfShader_OpaqueWall_Pass_BaseCombine_TextureLightmapDetail(const
        m.texrgbscale[1] = 2;
        m.tex[2] = R_GetTexture(texture->skin.detail);
        m.texrgbscale[2] = 2;
-       GL_Color(r_lightmapintensity, r_lightmapintensity, r_lightmapintensity, 1);
+       GL_Color(r_lightmapintensity * ent->colormod[0], r_lightmapintensity * ent->colormod[1], r_lightmapintensity * ent->colormod[2], 1);
 
        while((surf = *surfchain++) != NULL)
        {
@@ -1030,7 +1030,7 @@ static void RSurfShader_OpaqueWall_Pass_BaseCombine_TextureLightmap(const entity
        m.tex[0] = R_GetTexture(texture->skin.base);
        m.tex[1] = R_GetTexture((**surfchain).lightmaptexture);
        m.texrgbscale[1] = 2;
-       GL_Color(r_lightmapintensity, r_lightmapintensity, r_lightmapintensity, 1);
+       GL_Color(r_lightmapintensity * ent->colormod[0], r_lightmapintensity * ent->colormod[1], r_lightmapintensity * ent->colormod[2], 1);
        while((surf = *surfchain++) != NULL)
        {
                if (surf->visframe == r_framecount)
@@ -1058,9 +1058,9 @@ static void RSurfShader_OpaqueWall_Pass_BaseTexture(const entity_render_t *ent,
        GL_BlendFunc(GL_ONE, GL_ZERO);
        m.tex[0] = R_GetTexture(texture->skin.base);
        if (ent->flags & RENDER_LIGHT)
-               GL_Color(r_lightmapintensity, r_lightmapintensity, r_lightmapintensity, 1);
+               GL_Color(r_lightmapintensity * ent->colormod[0], r_lightmapintensity * ent->colormod[1], r_lightmapintensity * ent->colormod[2], 1);
        else
-               GL_Color(1, 1, 1, 1);
+               GL_Color(ent->colormod[0], ent->colormod[1], ent->colormod[2], 1);
        while((surf = *surfchain++) != NULL)
        {
                if (surf->visframe == r_framecount)
@@ -1111,7 +1111,7 @@ static void RSurfShader_OpaqueWall_Pass_BaseAmbient(const entity_render_t *ent,
        GL_DepthMask(false);
        GL_DepthTest(true);
        m.tex[0] = R_GetTexture(texture->skin.base);
-       GL_Color(r_ambient.value * (1.0f / 128.0f), r_ambient.value * (1.0f / 128.0f), r_ambient.value * (1.0f / 128.0f), 1);
+       GL_Color(r_ambient.value * (1.0f / 128.0f) * ent->colormod[0], r_ambient.value * (1.0f / 128.0f) * ent->colormod[1], r_ambient.value * (1.0f / 128.0f) * ent->colormod[2], 1);
        while((surf = *surfchain++) != NULL)
        {
                if (surf->visframe == r_framecount)
@@ -1948,20 +1948,20 @@ void R_Q3BSP_DrawFace_TransparentCallback(const void *voident, int facenumber)
                {
                        m.tex[1] = R_GetTexture(face->lightmaptexture);
                        m.pointer_texcoord[1] = face->data_texcoordlightmap2f;
-                       GL_Color(1, 1, 1, ent->alpha);
+                       GL_Color(ent->colormod[0], ent->colormod[1], ent->colormod[2], ent->alpha);
                }
                else
                {
-                       if (ent->alpha == 1)
+                       if (ent->colormod[0] == 1 && ent->colormod[1] == 1 && ent->colormod[2] == 1 && ent->alpha == 1)
                                m.pointer_color = face->data_color4f;
                        else
                        {
                                int i;
                                for (i = 0;i < face->num_vertices;i++)
                                {
-                                       varray_color4f[i*4+0] = face->data_color4f[i*4+0];
-                                       varray_color4f[i*4+1] = face->data_color4f[i*4+1];
-                                       varray_color4f[i*4+2] = face->data_color4f[i*4+2];
+                                       varray_color4f[i*4+0] = face->data_color4f[i*4+0] * ent->colormod[0];
+                                       varray_color4f[i*4+1] = face->data_color4f[i*4+1] * ent->colormod[1];
+                                       varray_color4f[i*4+2] = face->data_color4f[i*4+2] * ent->colormod[2];
                                        varray_color4f[i*4+3] = face->data_color4f[i*4+3] * ent->alpha;
                                }
                                m.pointer_color = varray_color4f;
@@ -1973,9 +1973,9 @@ void R_Q3BSP_DrawFace_TransparentCallback(const void *voident, int facenumber)
                int i;
                for (i = 0;i < face->num_vertices;i++)
                {
-                       varray_color4f[i*4+0] = face->data_color4f[i*4+0] * 2.0f;
-                       varray_color4f[i*4+1] = face->data_color4f[i*4+1] * 2.0f;
-                       varray_color4f[i*4+2] = face->data_color4f[i*4+2] * 2.0f;
+                       varray_color4f[i*4+0] = face->data_color4f[i*4+0] * ent->colormod[0] * 2.0f;
+                       varray_color4f[i*4+1] = face->data_color4f[i*4+1] * ent->colormod[1] * 2.0f;
+                       varray_color4f[i*4+2] = face->data_color4f[i*4+2] * ent->colormod[2] * 2.0f;
                        varray_color4f[i*4+3] = face->data_color4f[i*4+3] * ent->alpha;
                }
                m.pointer_color = varray_color4f;
@@ -2139,7 +2139,7 @@ void R_Q3BSP_DrawFaceList(entity_render_t *ent, q3mtexture_t *t, int texturenumf
                GL_DepthMask(true);
                GL_DepthTest(true);
                GL_BlendFunc(GL_ONE, GL_ZERO);
-               GL_Color(1, 1, 1, 1);
+               GL_Color(ent->colormod[0], ent->colormod[1], ent->colormod[2], 1);
                if (t->textureflags & Q3TEXTUREFLAG_TWOSIDED)
                        qglDisable(GL_CULL_FACE);
                memset(&m, 0, sizeof(m));
@@ -2156,6 +2156,7 @@ void R_Q3BSP_DrawFaceList(entity_render_t *ent, q3mtexture_t *t, int texturenumf
                }
                if (t->skin.glow)
                {
+                       GL_Color(1, 1, 1, 1);
                        GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
                        GL_DepthMask(false);
                        m.tex[0] = R_GetTexture(t->skin.glow);
@@ -2210,19 +2211,19 @@ void R_Q3BSP_DrawFaceList(entity_render_t *ent, q3mtexture_t *t, int texturenumf
                        m.texrgbscale[1] = 2;
                        if (face->lightmaptexture)
                        {
-                               GL_Color(r_lightmapintensity, r_lightmapintensity, r_lightmapintensity, 1);
+                               GL_Color(r_lightmapintensity * ent->colormod[0], r_lightmapintensity * ent->colormod[1], r_lightmapintensity * ent->colormod[2], 1);
                                m.pointer_color = NULL;
                        }
-                       else if (r_lightmapintensity == 1)
+                       else if (r_lightmapintensity == 1 && ent->colormod[0] == 1 && ent->colormod[1] == 1 && ent->colormod[2] == 1)
                                m.pointer_color = face->data_color4f;
                        else
                        {
                                m.pointer_color = varray_color4f;
                                for (i = 0;i < face->num_vertices;i++)
                                {
-                                       varray_color4f[i*4+0] = face->data_color4f[i*4+0] * r_lightmapintensity;
-                                       varray_color4f[i*4+1] = face->data_color4f[i*4+1] * r_lightmapintensity;
-                                       varray_color4f[i*4+2] = face->data_color4f[i*4+2] * r_lightmapintensity;
+                                       varray_color4f[i*4+0] = face->data_color4f[i*4+0] * ent->colormod[0] * r_lightmapintensity;
+                                       varray_color4f[i*4+1] = face->data_color4f[i*4+1] * ent->colormod[1] * r_lightmapintensity;
+                                       varray_color4f[i*4+2] = face->data_color4f[i*4+2] * ent->colormod[2] * r_lightmapintensity;
                                        varray_color4f[i*4+3] = face->data_color4f[i*4+3];
                                }
                        }
@@ -2257,7 +2258,7 @@ void R_Q3BSP_DrawFaceList(entity_render_t *ent, q3mtexture_t *t, int texturenumf
                }
                GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
                GL_DepthMask(false);
-               GL_Color(r_lightmapintensity, r_lightmapintensity, r_lightmapintensity, 1);
+               GL_Color(r_lightmapintensity * ent->colormod[0], r_lightmapintensity * ent->colormod[1], r_lightmapintensity * ent->colormod[2], 1);
                memset(&m, 0, sizeof(m));
                m.tex[0] = R_GetTexture(t->skin.base);
                for (texturefaceindex = 0;texturefaceindex < texturenumfaces;texturefaceindex++)
@@ -2275,7 +2276,7 @@ void R_Q3BSP_DrawFaceList(entity_render_t *ent, q3mtexture_t *t, int texturenumf
        {
                GL_BlendFunc(GL_ONE, GL_ONE);
                GL_DepthMask(false);
-               GL_Color(r_ambient.value * (1.0f / 128.0f), r_ambient.value * (1.0f / 128.0f), r_ambient.value * (1.0f / 128.0f), 1);
+               GL_Color(r_ambient.value * (1.0f / 128.0f) * ent->colormod[0], r_ambient.value * (1.0f / 128.0f) * ent->colormod[1], r_ambient.value * (1.0f / 128.0f) * ent->colormod[2], 1);
                memset(&m, 0, sizeof(m));
                m.tex[0] = R_GetTexture(t->skin.base);
                for (texturefaceindex = 0;texturefaceindex < texturenumfaces;texturefaceindex++)
diff --git a/host.c b/host.c
index 8d9d9f5..49cc616 100644 (file)
--- a/host.c
+++ b/host.c
@@ -737,7 +737,6 @@ void _Host_Frame (float time)
        static double time2 = 0;
        static double time3 = 0;
        int pass1, pass2, pass3;
-       usercmd_t cmd; // Used for receiving input
 
        if (setjmp(host_abortserver))
                return;                 // something bad happened, or the server disconnected
@@ -758,14 +757,14 @@ void _Host_Frame (float time)
        IN_Commands();
 
        // Collect input into cmd
-       IN_ProcessMove(&cmd);
+       IN_ProcessMove();
 
        // process console commands
        Cbuf_Execute();
 
        // if running the server locally, make intentions now
        if (cls.state == ca_connected && sv.active)
-               CL_SendCmd(&cmd);
+               CL_SendCmd();
 
 //-------------------
 //
@@ -795,7 +794,7 @@ void _Host_Frame (float time)
                // if running the server remotely, send intentions now after
                // the incoming messages have been read
                if (!sv.active)
-                       CL_SendCmd(&cmd);
+                       CL_SendCmd();
                CL_ReadFromServer();
        }
 
index d3fcd5f..8a616af 100644 (file)
@@ -75,6 +75,7 @@ void Host_Status_f (void)
                case PROTOCOL_DARKPLACES3: protocolname = "PROTOCOL_DARKPLACES3";break;
                case PROTOCOL_DARKPLACES4: protocolname = "PROTOCOL_DARKPLACES4";break;
                case PROTOCOL_DARKPLACES5: protocolname = "PROTOCOL_DARKPLACES5";break;
+               case PROTOCOL_DARKPLACES6: protocolname = "PROTOCOL_DARKPLACES6";break;
                default: protocolname = "PROTOCOL_UNKNOWN";break;
        }
        print ("protocol: %i (%s)\n", sv.protocol, protocolname);
@@ -1133,6 +1134,7 @@ void Host_Spawn_f (void)
        client_t *client;
        func_t RestoreGame;
        mfunction_t *f;
+       int stats[MAX_CL_STATS];
 
        if (cmd_source == src_command)
        {
@@ -1247,7 +1249,7 @@ void Host_Spawn_f (void)
        MSG_WriteAngle (&host_client->message, host_client->edict->v->angles[1], sv.protocol);
        MSG_WriteAngle (&host_client->message, 0, sv.protocol);
 
-       SV_WriteClientdataToMessage (host_client->edict, &host_client->message);
+       SV_WriteClientdataToMessage (host_client, host_client->edict, &host_client->message, stats);
 
        MSG_WriteByte (&host_client->message, svc_signonnum);
        MSG_WriteByte (&host_client->message, 3);
diff --git a/input.h b/input.h
index f48aa9c..8572a95 100644 (file)
--- a/input.h
+++ b/input.h
@@ -34,15 +34,15 @@ void IN_Commands (void);
 // oportunity for devices to stick commands on the script buffer
 
 // AK added to allow mouse movement for the menu
-void IN_ProcessMove(usercmd_t *cmd);
+void IN_ProcessMove(void);
 
-void IN_Move (usercmd_t *cmd);
+void IN_Move (void);
 // add additional movement on top of the keyboard move cmd
 
 void IN_PreMove(void);
 void IN_PostMove(void);
 
-void IN_Mouse(usercmd_t *cmd, float mx, float my);
+void IN_Mouse(float mx, float my);
 
 void IN_ClearStates (void);
 // restores all button and position states to defaults
index ddf9d45..5214f33 100644 (file)
--- a/pr_cmds.c
+++ b/pr_cmds.c
@@ -70,6 +70,8 @@ void PF_VarString(int first, char *out, int outlength)
 }
 
 char *ENGINE_EXTENSIONS =
+"DP_BUTTONCHAT "
+"DP_BUTTONUSE "
 "DP_CL_LOADSKY "
 "DP_CON_SET "
 "DP_CON_SETA "
@@ -165,6 +167,7 @@ char *ENGINE_EXTENSIONS =
 "NEH_CMD_PLAY2 "
 "NEH_RESTOREGAME "
 "NXQ_GFX_LETTERBOX "
+"PRYDON_CLIENTCURSOR "
 "TENEBRAE_GFX_DLIGHTS "
 "TW_SV_STEPCONTROL "
 ;
@@ -351,10 +354,10 @@ PF_setmodel
 setmodel(entity, model)
 =================
 */
+static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
 void PF_setmodel (void)
 {
        edict_t *e;
-       char    *m, **check;
        model_t *mod;
        int             i;
 
@@ -363,24 +366,19 @@ void PF_setmodel (void)
                PF_WARNING("setmodel: can not modify world entity\n");
        if (e->e->free)
                PF_WARNING("setmodel: can not modify free entity\n");
-       m = G_STRING(OFS_PARM1);
-
-// check to see if model was properly precached
-       for (i=0, check = sv.model_precache ; *check ; i++, check++)
-               if (!strcmp(*check, m))
-                       break;
-
-       if (!*check)
-               PF_WARNING(va("setmodel: no precache for model \"%s\"\n", m));
-
-
-       e->v->model = PR_SetString(*check);
+       i = SV_ModelIndex(G_STRING(OFS_PARM1), 1);
+       e->v->model = PR_SetString(sv.model_precache[i]);
        e->v->modelindex = i;
 
-       mod = sv.models[ (int)e->v->modelindex];
+       mod = sv.models[i];
 
        if (mod)
-               SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
+       {
+               if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
+                       SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
+               else
+                       SetMinMaxSize (e, quakemins, quakemaxs, true);
+       }
        else
                SetMinMaxSize (e, vec3_origin, vec3_origin, true);
 }
@@ -626,7 +624,6 @@ PF_ambientsound
 */
 void PF_ambientsound (void)
 {
-       char            **check;
        char            *samp;
        float           *pos;
        float           vol, attenuation;
@@ -638,15 +635,9 @@ void PF_ambientsound (void)
        attenuation = G_FLOAT(OFS_PARM3);
 
 // check to see if samp was properly precached
-       for (soundnum=0, check = sv.sound_precache ; *check ; check++, soundnum++)
-               if (!strcmp(*check,samp))
-                       break;
-
-       if (!*check)
-       {
-               Con_Printf("no precache: %s\n", samp);
+       soundnum = SV_SoundIndex(samp, 1);
+       if (!soundnum)
                return;
-       }
 
        large = false;
        if (soundnum >= 256)
@@ -1356,59 +1347,17 @@ void PF_precache_file (void)
        G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
 }
 
+
 void PF_precache_sound (void)
 {
-       char    *s;
-       int             i;
-       int             limit = (sv.protocol == PROTOCOL_QUAKE ? 256 : MAX_SOUNDS);
-
-       if (sv.state != ss_loading)
-               PF_ERROR("PF_Precache_*: Precache can only be done in spawn functions");
-
-       s = G_STRING(OFS_PARM0);
+       SV_SoundIndex(G_STRING(OFS_PARM0), 2);
        G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
-       PR_CheckEmptyString (s);
-
-       for (i=0 ; i<limit ; i++)
-       {
-               if (!sv.sound_precache[i])
-               {
-                       sv.sound_precache[i] = s;
-                       return;
-               }
-               if (!strcmp(sv.sound_precache[i], s))
-                       return;
-       }
-       PF_ERROR("PF_precache_sound: overflow");
 }
 
 void PF_precache_model (void)
 {
-       char    *s;
-       int             i;
-       int             limit = (sv.protocol == PROTOCOL_QUAKE ? 256 : MAX_MODELS);
-
-       if (sv.state != ss_loading)
-               PF_ERROR("PF_Precache_*: Precache can only be done in spawn functions");
-
-       s = G_STRING(OFS_PARM0);
-       if (sv.worldmodel->brush.ishlbsp && ((!s) || (!s[0])))
-               return;
+       SV_ModelIndex(G_STRING(OFS_PARM0), 2);
        G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
-       PR_CheckEmptyString (s);
-
-       for (i = 0;i < limit;i++)
-       {
-               if (!sv.model_precache[i])
-               {
-                       sv.model_precache[i] = s;
-                       sv.models[i] = Mod_ForName (s, true, false, false);
-                       return;
-               }
-               if (!strcmp(sv.model_precache[i], s))
-                       return;
-       }
-       PF_ERROR("PF_precache_model: overflow");
 }
 
 
@@ -2250,8 +2199,8 @@ void PF_effect (void)
        if (!s || !s[0])
                PF_WARNING("effect: no model specified\n");
 
-       i = SV_ModelIndex(s);
-       if (i < 0)
+       i = SV_ModelIndex(s, 1);
+       if (!i)
                PF_WARNING("effect: model not precached\n");
        SV_StartEffect(G_VECTOR(OFS_PARM0), i, G_FLOAT(OFS_PARM2), G_FLOAT(OFS_PARM3), G_FLOAT(OFS_PARM4));
 }
@@ -3145,7 +3094,10 @@ int SV_GetTagIndex (edict_t *e, char *tagname)
        int tagindex, i;
        model_t *model;
 
-       model = sv.models[(int)e->v->modelindex];
+       i = e->v->modelindex;
+       if (i < 1 || i >= MAX_MODELS)
+               return -1;
+       model = sv.models[i];
 
        tagindex = -1;
        if (model->data_overridetagnamesforskin && (unsigned int)e->v->skin < (unsigned int)model->numskins && model->data_overridetagnamesforskin[(unsigned int)e->v->skin].num_overridetagnames)
@@ -3233,14 +3185,18 @@ int SV_GetTagMatrix (matrix4x4_t *out, edict_t *ent, int tagindex)
                {
                        attachent = EDICT_NUM(val->edict); // to this it entity our entity is attached
                        val = GETEDICTFIELDVALUE(ent, eval_tag_index);
-                       if (val->_float) 
-                       {// got tagname on parent entity attachment tag via tag_index (and got it's matrix)
+                       Matrix4x4_CreateIdentity(&attachmatrix);
+                       if (val->_float >= 1 && attachent->v->modelindex >= 1 && attachent->v->modelindex < MAX_MODELS)
+                       {
                                model = sv.models[(int)attachent->v->modelindex];
-                               reqtag = (val->_float - 1) + attachent->v->frame*model->alias.aliasnum_tags;
-                               Matrix4x4_Copy(&attachmatrix, &model->alias.aliasdata_tags[reqtag].matrix);
+                               if (val->_float < model->alias.aliasnum_tags)
+                               {
+                                       // got tagname on parent entity attachment tag via tag_index (and got it's matrix)
+                                       model = sv.models[(int)attachent->v->modelindex];
+                                       reqtag = (val->_float - 1) + attachent->v->frame*model->alias.aliasnum_tags;
+                                       Matrix4x4_Copy(&attachmatrix, &model->alias.aliasdata_tags[reqtag].matrix);
+                               }
                        }
-                       else
-                               Matrix4x4_CreateIdentity(&attachmatrix);
 
                        // apply transformation by child entity matrix
                        val = GETEDICTFIELDVALUE(ent, eval_scale);
@@ -3264,7 +3220,7 @@ int SV_GetTagMatrix (matrix4x4_t *out, edict_t *ent, int tagindex)
                        attachloop += 1;
                        if (attachloop > 255) // prevent runaway looping
                                return 5;
-               } 
+               }
                while ((val = GETEDICTFIELDVALUE(ent, eval_tag_entity)) && val->edict);
        }
 
index bbfd1e4..3e20a98 100644 (file)
@@ -92,6 +92,8 @@ int eval_button5;
 int eval_button6;
 int eval_button7;
 int eval_button8;
+int eval_buttonuse;
+int eval_buttonchat;
 int eval_glow_size;
 int eval_glow_trail;
 int eval_glow_color;
@@ -126,6 +128,12 @@ int eval_light_lev;
 int eval_color;
 int eval_style;
 int eval_pflags;
+int eval_cursor_active;
+int eval_cursor_screen;
+int eval_cursor_trace_start;
+int eval_cursor_trace_endpos;
+int eval_cursor_trace_ent;
+int eval_colormod;
 
 mfunction_t *SV_PlayerPhysicsQC;
 mfunction_t *EndFrameQC;
@@ -150,6 +158,8 @@ void FindEdictFieldOffsets(void)
        eval_button6 = FindFieldOffset("button6");
        eval_button7 = FindFieldOffset("button7");
        eval_button8 = FindFieldOffset("button8");
+       eval_buttonuse = FindFieldOffset("buttonuse");
+       eval_buttonchat = FindFieldOffset("buttonchat");
        eval_glow_size = FindFieldOffset("glow_size");
        eval_glow_trail = FindFieldOffset("glow_trail");
        eval_glow_color = FindFieldOffset("glow_color");
@@ -184,6 +194,12 @@ void FindEdictFieldOffsets(void)
        eval_color = FindFieldOffset("color");
        eval_style = FindFieldOffset("style");
        eval_pflags = FindFieldOffset("pflags");
+       eval_cursor_active = FindFieldOffset("cursor_active");
+       eval_cursor_screen = FindFieldOffset("cursor_screen");
+       eval_cursor_trace_start = FindFieldOffset("cursor_trace_start");
+       eval_cursor_trace_endpos = FindFieldOffset("cursor_trace_endpos");
+       eval_cursor_trace_ent = FindFieldOffset("cursor_trace_ent");
+       eval_colormod = FindFieldOffset("colormod");
 
        // LordHavoc: allowing QuakeC to override the player movement code
        SV_PlayerPhysicsQC = ED_FindFunction ("SV_PlayerPhysics");
@@ -1205,46 +1221,55 @@ dpfield_t;
 
 dpfield_t dpfields[] =
 {
-       {ev_float, "gravity"},
+       {ev_entity, "cursor_trace_ent"},
+       {ev_entity, "drawonlytoclient"},
+       {ev_entity, "exteriormodeltoclient"},
+       {ev_entity, "nodrawtoclient"},
+       {ev_entity, "tag_entity"},
+       {ev_entity, "viewmodelforclient"},
+       {ev_float, "alpha"},
+       {ev_float, "ammo_cells1"},
+       {ev_float, "ammo_lava_nails"},
+       {ev_float, "ammo_multi_rockets"},
+       {ev_float, "ammo_nails1"},
+       {ev_float, "ammo_plasma"},
+       {ev_float, "ammo_rockets1"},
+       {ev_float, "ammo_shells1"},
        {ev_float, "button3"},
        {ev_float, "button4"},
        {ev_float, "button5"},
        {ev_float, "button6"},
        {ev_float, "button7"},
        {ev_float, "button8"},
+       {ev_float, "buttonchat"},
+       {ev_float, "buttonuse"},
+       {ev_float, "clientcolors"},
+       {ev_float, "cursor_active"},
+       {ev_float, "fullbright"},
+       {ev_float, "glow_color"},
        {ev_float, "glow_size"},
        {ev_float, "glow_trail"},
-       {ev_float, "glow_color"},
-       {ev_float, "items2"},
-       {ev_float, "scale"},
-       {ev_float, "alpha"},
-       {ev_float, "renderamt"},
-       {ev_float, "rendermode"},
-       {ev_float, "fullbright"},
-       {ev_float, "ammo_shells1"},
-       {ev_float, "ammo_nails1"},
-       {ev_float, "ammo_lava_nails"},
-       {ev_float, "ammo_rockets1"},
-       {ev_float, "ammo_multi_rockets"},
-       {ev_float, "ammo_cells1"},
-       {ev_float, "ammo_plasma"},
+       {ev_float, "gravity"},
        {ev_float, "idealpitch"},
-       {ev_float, "pitch_speed"},
-       {ev_entity, "viewmodelforclient"},
-       {ev_entity, "nodrawtoclient"},
-       {ev_entity, "exteriormodeltoclient"},
-       {ev_entity, "drawonlytoclient"},
+       {ev_float, "items2"},
+       {ev_float, "light_lev"},
+       {ev_float, "pflags"},
        {ev_float, "ping"},
-       {ev_vector, "movement"},
+       {ev_float, "pitch_speed"},
        {ev_float, "pmodel"},
-       {ev_vector, "punchvector"},
-       {ev_float, "clientcolors"},
-       {ev_entity, "tag_entity"},
+       {ev_float, "renderamt"}, // HalfLife support
+       {ev_float, "rendermode"}, // HalfLife support
+       {ev_float, "scale"},
+       {ev_float, "style"},
        {ev_float, "tag_index"},
-       {ev_float, "light_lev"},
+       {ev_float, "viewzoom"},
        {ev_vector, "color"},
-       {ev_float, "style"},
-       {ev_float, "pflags"}
+       {ev_vector, "colormod"},
+       {ev_vector, "cursor_screen"},
+       {ev_vector, "cursor_trace_endpos"},
+       {ev_vector, "cursor_trace_start"},
+       {ev_vector, "movement"},
+       {ev_vector, "punchvector"}
 };
 
 /*
diff --git a/progs.h b/progs.h
index 99cf61f..8e717d3 100644 (file)
--- a/progs.h
+++ b/progs.h
@@ -89,6 +89,8 @@ extern int eval_button5;
 extern int eval_button6;
 extern int eval_button7;
 extern int eval_button8;
+extern int eval_buttonuse;
+extern int eval_buttonchat;
 extern int eval_glow_size;
 extern int eval_glow_trail;
 extern int eval_glow_color;
@@ -123,6 +125,12 @@ extern int eval_light_lev;
 extern int eval_color;
 extern int eval_style;
 extern int eval_pflags;
+extern int eval_cursor_active;
+extern int eval_cursor_screen;
+extern int eval_cursor_trace_start;
+extern int eval_cursor_trace_endpos;
+extern int eval_cursor_trace_ent;
+extern int eval_colormod;
 
 #define GETEDICTFIELDVALUE(ed, fieldoffset) (fieldoffset ? (eval_t *)((qbyte *)ed->v + fieldoffset) : NULL)
 
index b537147..c044a8d 100644 (file)
@@ -30,9 +30,9 @@ entity_state_t defaultstate =
        254,//unsigned char glowcolor;
        0,//unsigned char flags;
        0,//unsigned char tagindex;
-       255,//unsigned char colormod;
+       {32, 32, 32},//unsigned char colormod[3];
        // padding to a multiple of 8 bytes (to align the double time)
-       {0,0,0,0}//unsigned char unused[4]; // !
+       {0,0}//unsigned char unused[2]; // !
 };
 
 // keep track of quake entities because they need to be killed if they get stale
@@ -100,7 +100,7 @@ void EntityFrameQuake_ReadEntity(int bits)
        if (bits & U_EFFECTS2)  s.effects = (s.effects & 0x00FF) | (MSG_ReadByte() << 8);
        if (bits & U_GLOWSIZE)  s.glowsize = MSG_ReadByte();
        if (bits & U_GLOWCOLOR) s.glowcolor = MSG_ReadByte();
-       if (bits & U_COLORMOD)  s.colormod = MSG_ReadByte();
+       if (bits & U_COLORMOD)  {int c = MSG_ReadByte();s.colormod[0] = (qbyte)(((c >> 5) & 7) * (32.0f / 7.0f));s.colormod[1] = (qbyte)(((c >> 2) & 7) * (32.0f / 7.0f));s.colormod[2] = (qbyte)((c & 3) * (32.0f / 3.0f));}
        if (bits & U_GLOWTRAIL) s.flags |= RENDER_GLOWTRAIL;
        if (bits & U_FRAME2)    s.frame = (s.frame & 0x00FF) | (MSG_ReadByte() << 8);
        if (bits & U_MODEL2)    s.modelindex = (s.modelindex & 0x00FF) | (MSG_ReadByte() << 8);
@@ -278,7 +278,7 @@ void EntityFrameQuake_WriteFrame(sizebuf_t *msg, int numstates, const entity_sta
                if (bits & U_EFFECTS2)          MSG_WriteByte(&buf, s->effects >> 8);
                if (bits & U_GLOWSIZE)          MSG_WriteByte(&buf, s->glowsize);
                if (bits & U_GLOWCOLOR)         MSG_WriteByte(&buf, s->glowcolor);
-               if (bits & U_COLORMOD)          MSG_WriteByte(&buf, s->colormod);
+               if (bits & U_COLORMOD)          {int c = ((int)bound(0, s->colormod[0] * (7.0f / 32.0f), 7) << 5) | ((int)bound(0, s->colormod[0] * (7.0f / 32.0f), 7) << 2) | ((int)bound(0, s->colormod[0] * (3.0f / 32.0f), 3) << 0);MSG_WriteByte(&buf, c);}
                if (bits & U_FRAME2)            MSG_WriteByte(&buf, s->frame >> 8);
                if (bits & U_MODEL2)            MSG_WriteByte(&buf, s->modelindex >> 8);
 
@@ -385,7 +385,7 @@ void EntityState_WriteFields(const entity_state_t *ent, sizebuf_t *msg, unsigned
                if (bits & E_ORIGIN3)
                        MSG_WriteCoord16i(msg, ent->origin[2]);
        }
-       else if (sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4 || sv.protocol == PROTOCOL_DARKPLACES5)
+       else if (sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4 || sv.protocol == PROTOCOL_DARKPLACES5 || sv.protocol == PROTOCOL_DARKPLACES6)
        {
                // LordHavoc: have to write flags first, as they can modify protocol
                if (bits & E_FLAGS)
@@ -409,7 +409,7 @@ void EntityState_WriteFields(const entity_state_t *ent, sizebuf_t *msg, unsigned
                                MSG_WriteCoord32f(msg, ent->origin[2]);
                }
        }
-       if (sv.protocol == PROTOCOL_DARKPLACES5 && !(ent->flags & RENDER_LOWPRECISION))
+       if ((sv.protocol == PROTOCOL_DARKPLACES5 || sv.protocol == PROTOCOL_DARKPLACES6) && !(ent->flags & RENDER_LOWPRECISION))
        {
                if (bits & E_ANGLE1)
                        MSG_WriteAngle16i(msg, ent->angles[0]);
@@ -525,7 +525,7 @@ void EntityState_ReadFields(entity_state_t *e, unsigned int bits)
                if (bits & E_ORIGIN3)
                        e->origin[2] = MSG_ReadCoord16i();
        }
-       else if (cl.protocol == PROTOCOL_DARKPLACES1 || cl.protocol == PROTOCOL_DARKPLACES3 || cl.protocol == PROTOCOL_DARKPLACES4 || cl.protocol == PROTOCOL_DARKPLACES5)
+       else if (cl.protocol == PROTOCOL_DARKPLACES1 || cl.protocol == PROTOCOL_DARKPLACES3 || cl.protocol == PROTOCOL_DARKPLACES4 || cl.protocol == PROTOCOL_DARKPLACES5 || cl.protocol == PROTOCOL_DARKPLACES6)
        {
                if (bits & E_FLAGS)
                        e->flags = MSG_ReadByte();
@@ -550,7 +550,7 @@ void EntityState_ReadFields(entity_state_t *e, unsigned int bits)
        }
        else
                Host_Error("EntityState_ReadFields: unknown cl.protocol %i\n", cl.protocol);
-       if (cl.protocol == PROTOCOL_DARKPLACES5 && !(e->flags & RENDER_LOWPRECISION))
+       if ((cl.protocol == PROTOCOL_DARKPLACES5 || cl.protocol == PROTOCOL_DARKPLACES6) && !(e->flags & RENDER_LOWPRECISION))
        {
                if (bits & E_ANGLE1)
                        e->angles[0] = MSG_ReadAngle16i();
@@ -861,7 +861,9 @@ void EntityFrame_CL_ReadFrame(void)
        // read the frame header info
        f->time = cl.mtime[0];
        number = MSG_ReadLong();
-       cl.latestframenum = f->framenum = MSG_ReadLong();
+       for (i = 0;i < LATESTFRAMENUMS-1;i++)
+               cl.latestframenums[i] = cl.latestframenums[i+1];
+       cl.latestframenums[LATESTFRAMENUMS-1] = f->framenum = MSG_ReadLong();
        f->eye[0] = MSG_ReadFloat();
        f->eye[1] = MSG_ReadFloat();
        f->eye[2] = MSG_ReadFloat();
@@ -1118,7 +1120,9 @@ void EntityFrame4_CL_ReadFrame(void)
        // read the number of the frame this refers to
        referenceframenum = MSG_ReadLong();
        // read the number of this frame
-       cl.latestframenum = framenum = MSG_ReadLong();
+       for (i = 0;i < LATESTFRAMENUMS-1;i++)
+               cl.latestframenums[i] = cl.latestframenums[i+1];
+       cl.latestframenums[LATESTFRAMENUMS-1] = framenum = MSG_ReadLong();
        // read the start number
        enumber = (unsigned short) MSG_ReadShort();
        if (developer_networkentities.integer >= 1)
@@ -1519,6 +1523,12 @@ void EntityState5_WriteUpdate(int number, const entity_state_t *s, int changedbi
                        MSG_WriteByte(msg, s->glowsize);
                        MSG_WriteByte(msg, s->glowcolor);
                }
+               if (bits & E5_COLORMOD)
+               {
+                       MSG_WriteByte(msg, s->colormod[0]);
+                       MSG_WriteByte(msg, s->colormod[1]);
+                       MSG_WriteByte(msg, s->colormod[2]);
+               }
        }
 }
 
@@ -1623,6 +1633,12 @@ void EntityState5_ReadUpdate(entity_state_t *s)
                s->glowsize = MSG_ReadByte();
                s->glowcolor = MSG_ReadByte();
        }
+       if (bits & E5_COLORMOD)
+       {
+               s->colormod[0] = MSG_ReadByte();
+               s->colormod[1] = MSG_ReadByte();
+               s->colormod[2] = MSG_ReadByte();
+       }
 
 
        if (developer_networkentities.integer >= 2)
@@ -1674,6 +1690,8 @@ void EntityState5_ReadUpdate(entity_state_t *s)
                        Con_Printf(" E5_LIGHT %i:%i:%i:%i %i:%i", s->light[0], s->light[1], s->light[2], s->light[3], s->lightstyle, s->lightpflags);
                if (bits & E5_GLOW)
                        Con_Printf(" E5_GLOW %i:%i", s->glowsize * 4, s->glowcolor);
+               if (bits & E5_COLORMOD)
+                       Con_Printf(" E5_COLORMOD %f:%f:%f", s->colormod[0] / 32.0f, s->colormod[1] / 32.0f, s->colormod[2] / 32.0f);
                Con_Print("\n");
        }
 }
@@ -1711,6 +1729,8 @@ int EntityState5_DeltaBits(const entity_state_t *o, const entity_state_t *n)
                        bits |= E5_LIGHT;
                if (o->glowsize != n->glowsize || o->glowcolor != n->glowcolor)
                        bits |= E5_GLOW;
+               if (o->colormod[0] != n->colormod[0] || o->colormod[1] != n->colormod[1] || o->colormod[2] != n->colormod[2])
+                       bits |= E5_COLORMOD;
        }
        else
                if (o->active)
@@ -1720,11 +1740,13 @@ int EntityState5_DeltaBits(const entity_state_t *o, const entity_state_t *n)
 
 void EntityFrame5_CL_ReadFrame(void)
 {
-       int n, enumber;
+       int i, n, enumber;
        entity_t *ent;
        entity_state_t *s;
        // read the number of this frame to echo back in next input packet
-       cl.latestframenum = MSG_ReadLong();
+       for (i = 0;i < LATESTFRAMENUMS-1;i++)
+               cl.latestframenums[i] = cl.latestframenums[i+1];
+       cl.latestframenums[LATESTFRAMENUMS-1] = MSG_ReadLong();
        // read entity numbers until we find a 0x8000
        // (which would be remove world entity, but is actually a terminator)
        while ((n = (unsigned short)MSG_ReadShort()) != 0x8000 && !msg_badread)
@@ -1766,23 +1788,16 @@ void EntityFrame5_CL_ReadFrame(void)
        }
 }
 
-void EntityFrame5_AckFrame(entityframe5_database_t *d, int framenum, int viewentnum)
+void EntityFrame5_LostFrame(entityframe5_database_t *d, int framenum, int viewentnum)
 {
        int i, j, k, l, bits;
        entityframe5_changestate_t *s, *s2;
        entityframe5_packetlog_t *p, *p2;
-       // scan for packets made obsolete by this ack
+       qbyte statsdeltabits[(MAX_CL_STATS+7)/8]; 
+       // scan for packets that were lost
        for (i = 0, p = d->packetlog;i < ENTITYFRAME5_MAXPACKETLOGS;i++, p++)
        {
-               // skip packets that are empty or in the future
-               if (p->packetnumber == 0 || p->packetnumber > framenum)
-                       continue;
-               // if the packetnumber matches it is deleted without any processing 
-               // (since it was received).
-               // if the packet number is less than this ack it was lost and its
-               // important information will be repeated in this update if it is not
-               // already obsolete due to a later update.
-               if (p->packetnumber < framenum)
+               if (p->packetnumber && p->packetnumber <= framenum)
                {
                        // packet was lost - merge deltabits into the main array so they
                        // will be re-sent, but only if there is no newer update of that
@@ -1797,7 +1812,7 @@ void EntityFrame5_AckFrame(entityframe5_database_t *d, int framenum, int viewent
                                {
                                        if (p2->packetnumber > framenum)
                                        {
-                                               for (l = 0, s2 = p2->states;l < p2->numstates;l++, p2++)
+                                               for (l = 0, s2 = p2->states;l < p2->numstates;l++, s2++)
                                                {
                                                        if (s2->number == s->number)
                                                        {
@@ -1815,16 +1830,37 @@ void EntityFrame5_AckFrame(entityframe5_database_t *d, int framenum, int viewent
                                        d->priorities[s->number] = EntityState5_Priority(d, d->states + viewentnum, d->states + s->number, d->deltabits[s->number], d->latestframenum - d->updateframenum[s->number]);
                                }
                        }
+                       // mark lost stats
+                       for (j = 0;j < MAX_CL_STATS;j++)
+                       {
+                               for (l = 0;l < (MAX_CL_STATS+7)/8;l++)
+                                       statsdeltabits[l] = p->statsdeltabits[l] & ~d->statsdeltabits[l];
+                               for (k = 0, p2 = d->packetlog;k < ENTITYFRAME5_MAXPACKETLOGS;k++, p2++)
+                                       if (p2->packetnumber > framenum)
+                                               for (l = 0;l < (MAX_CL_STATS+7)/8;l++)
+                                                       statsdeltabits[l] = p->statsdeltabits[l] & ~p2->statsdeltabits[l];
+                               for (l = 0;l < (MAX_CL_STATS+7)/8;l++)
+                                       d->statsdeltabits[l] |= statsdeltabits[l];
+                       }
+                       // delete this packet log as it is now obsolete
+                       p->packetnumber = 0;
                }
-               // delete this packet log as it is now obsolete
-               p->packetnumber = 0;
        }
 }
 
+void EntityFrame5_AckFrame(entityframe5_database_t *d, int framenum)
+{
+       int i;
+       // scan for packets made obsolete by this ack and delete them
+       for (i = 0;i < ENTITYFRAME5_MAXPACKETLOGS;i++)
+               if (d->packetlog[i].packetnumber <= framenum)
+                       d->packetlog[i].packetnumber = 0;
+}
+
 int entityframe5_prioritychaincounts[E5_PROTOCOL_PRIORITYLEVELS];
 unsigned short entityframe5_prioritychains[E5_PROTOCOL_PRIORITYLEVELS][ENTITYFRAME5_MAXSTATES];
 
-void EntityFrame5_WriteFrame(sizebuf_t *msg, entityframe5_database_t *d, int numstates, const entity_state_t *states, int viewentnum)
+void EntityFrame5_WriteFrame(sizebuf_t *msg, entityframe5_database_t *d, int numstates, const entity_state_t *states, int viewentnum, int *stats)
 {
        const entity_state_t *n;
        int i, num, l, framenum, packetlognumber, priority;
@@ -1834,11 +1870,32 @@ void EntityFrame5_WriteFrame(sizebuf_t *msg, entityframe5_database_t *d, int num
 
        framenum = d->latestframenum + 1;
 
+       // if packet log is full, mark all frames as lost, this will cause
+       // it to send the lost data again
+       for (packetlognumber = 0;packetlognumber < ENTITYFRAME5_MAXPACKETLOGS;packetlognumber++)
+               if (d->packetlog[packetlognumber].packetnumber == 0)
+                       break;
+       if (packetlognumber == ENTITYFRAME5_MAXPACKETLOGS)
+       {
+               EntityFrame5_LostFrame(d, framenum, viewentnum);
+               packetlognumber = 0;
+       }
+
        // prepare the buffer
        memset(&buf, 0, sizeof(buf));
        buf.data = data;
        buf.maxsize = sizeof(data);
 
+       // detect changes in stats
+       for (i = 0;i < MAX_CL_STATS;i++)
+       {
+               if (d->stats[i] != stats[i])
+               {
+                       d->statsdeltabits[i>>3] |= (1<<(i&7));
+                       d->stats[i] = stats[i];
+               }
+       }
+
        // detect changes in states
        num = 0;
        for (i = 0, n = states;i < numstates;i++, n++)
@@ -1898,52 +1955,64 @@ void EntityFrame5_WriteFrame(sizebuf_t *msg, entityframe5_database_t *d, int num
                }
        }
 
-       // return early if there are no entities to send this time
-       if (l == 0)
-               return;
-
+       // add packetlog entry
+       packetlog = d->packetlog + packetlognumber;
+       packetlog->packetnumber = framenum;
+       packetlog->numstates = 0;
+       // write stat updates
+       if (sv.protocol == PROTOCOL_DARKPLACES6)
+       {
+               for (i = 0;i < MAX_CL_STATS;i++)
+               {
+                       if (d->statsdeltabits[i>>3] & (1<<(i&7)))
+                       {
+                               d->statsdeltabits[i>>3] &= ~(1<<(i&7));
+                               packetlog->statsdeltabits[i>>3] |= (1<<(i&7));
+                               if (d->stats[i] >= 0 && d->stats[i] < 256)
+                               {
+                                       MSG_WriteByte(msg, svc_updatestatubyte);
+                                       MSG_WriteByte(msg, i);
+                                       MSG_WriteByte(msg, d->stats[i]);
+                               }
+                               else
+                               {
+                                       MSG_WriteByte(msg, svc_updatestat);
+                                       MSG_WriteByte(msg, i);
+                                       MSG_WriteLong(msg, d->stats[i]);
+                               }
+                       }
+               }
+       }
+       // write state updates
        d->latestframenum = framenum;
        MSG_WriteByte(msg, svc_entities);
        MSG_WriteLong(msg, framenum);
-
-       // if packet log is full, an empty update is still written
-       // (otherwise the client might have nothing to ack to remove packetlogs)
-       for (packetlognumber = 0, packetlog = d->packetlog;packetlognumber < ENTITYFRAME5_MAXPACKETLOGS;packetlognumber++, packetlog++)
-               if (packetlog->packetnumber == 0)
-                       break;
-       if (packetlognumber < ENTITYFRAME5_MAXPACKETLOGS)
+       for (priority = E5_PROTOCOL_PRIORITYLEVELS - 1;priority >= 0 && packetlog->numstates < ENTITYFRAME5_MAXSTATES;priority--)
        {
-               // write to packet and log
-               packetlog->packetnumber = framenum;
-               packetlog->numstates = 0;
-               for (priority = E5_PROTOCOL_PRIORITYLEVELS - 1;priority >= 0 && packetlog->numstates < ENTITYFRAME5_MAXSTATES;priority--)
+               for (i = 0;i < entityframe5_prioritychaincounts[priority] && packetlog->numstates < ENTITYFRAME5_MAXSTATES;i++)
                {
-                       for (i = 0;i < entityframe5_prioritychaincounts[priority] && packetlog->numstates < ENTITYFRAME5_MAXSTATES;i++)
-                       {
-                               num = entityframe5_prioritychains[priority][i];
-                               n = d->states + num;
-                               if (d->deltabits[num] & E5_FULLUPDATE)
-                                       d->deltabits[num] = E5_FULLUPDATE | EntityState5_DeltaBits(&defaultstate, n);
-                               buf.cursize = 0;
-                               EntityState5_WriteUpdate(num, n, d->deltabits[num], &buf);
-                               // if the entity won't fit, try the next one
-                               if (msg->cursize + buf.cursize + 2 > msg->maxsize)
-                                       continue;
-                               // write entity to the packet
-                               SZ_Write(msg, buf.data, buf.cursize);
-                               // mark age on entity for prioritization
-                               d->updateframenum[num] = framenum;
-                               // log entity so deltabits can be restored later if lost
-                               packetlog->states[packetlog->numstates].number = num;
-                               packetlog->states[packetlog->numstates].bits = d->deltabits[num];
-                               packetlog->numstates++;
-                               // clear deltabits and priority so it won't be sent again
-                               d->deltabits[num] = 0;
-                               d->priorities[num] = 0;
-                       }
+                       num = entityframe5_prioritychains[priority][i];
+                       n = d->states + num;
+                       if (d->deltabits[num] & E5_FULLUPDATE)
+                               d->deltabits[num] = E5_FULLUPDATE | EntityState5_DeltaBits(&defaultstate, n);
+                       buf.cursize = 0;
+                       EntityState5_WriteUpdate(num, n, d->deltabits[num], &buf);
+                       // if the entity won't fit, try the next one
+                       if (msg->cursize + buf.cursize + 2 > msg->maxsize)
+                               continue;
+                       // write entity to the packet
+                       SZ_Write(msg, buf.data, buf.cursize);
+                       // mark age on entity for prioritization
+                       d->updateframenum[num] = framenum;
+                       // log entity so deltabits can be restored later if lost
+                       packetlog->states[packetlog->numstates].number = num;
+                       packetlog->states[packetlog->numstates].bits = d->deltabits[num];
+                       packetlog->numstates++;
+                       // clear deltabits and priority so it won't be sent again
+                       d->deltabits[num] = 0;
+                       d->priorities[num] = 0;
                }
        }
-
        MSG_WriteShort(msg, 0x8000);
 }
 
index c0e96df..398cf83 100644 (file)
@@ -42,6 +42,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 // entityframe5 protocol
 #define PROTOCOL_DARKPLACES5 3502
+#define PROTOCOL_DARKPLACES6 3503
 
 // model effects
 #define        EF_ROCKET       1                       // leave a trail
@@ -70,6 +71,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #define EF_STARDUST                            2048    // LordHavoc: showering sparks
 #define EF_NOSHADOW                            4096    // LordHavoc: does not cast a shadow
 #define EF_NODEPTHTEST                 8192    // LordHavoc: shows through walls
+#define EF_SELECTABLE                  16384   // LordHavoc: highlights when PRYDON_CLIENTCURSOR mouse is over it
 
 #define EF_STEP                                        0x80000000 // internal client use only - present on MOVETYPE_STEP entities, not QC accessible (too many bits)
 
@@ -107,7 +109,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #define U_EFFECTS2             (1<<19) // 1 byte, this is .effects & 0xFF00 (second byte)
 #define U_GLOWSIZE             (1<<20) // 1 byte, encoding is float/4.0, unsigned, not sent if 0
 #define U_GLOWCOLOR            (1<<21) // 1 byte, palette index, default is 254 (white), this IS used for darklight (allowing colored darklight), however the particles from a darklight are always black, not sent if default value (even if glowsize or glowtrail is set)
-// LordHavoc: colormod feature has been removed, because no one used it
 #define U_COLORMOD             (1<<22) // 1 byte, 3 bit red, 3 bit green, 2 bit blue, this lets you tint an object artifically, so you could make a red rocket, or a blue fiend...
 #define U_EXTEND2              (1<<23) // another byte to follow
 // LordHavoc: second extend byte
@@ -236,10 +237,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 // LordHavoc: my svc_ range, 50-59
 #define svc_cgame                      50              // [short] length [bytes] data
-#define svc_unusedlh1          51
+#define svc_updatestatubyte    51              // [byte] stat [byte] value
 #define svc_effect                     52              // [vector] org [byte] modelindex [byte] startframe [byte] framecount [byte] framerate
 #define svc_effect2                    53              // [vector] org [short] modelindex [short] startframe [byte] framecount [byte] framerate
-#define        svc_sound2                      54              // short soundindex instead of byte
+#define        svc_sound2                      54              // (obsolete in DP6 and later) short soundindex instead of byte
+#define        svc_precache            54              // [short] precacheindex [string] filename, precacheindex is + 0 for modelindex and +32768 for soundindex
 #define        svc_spawnbaseline2      55              // short modelindex instead of byte
 #define svc_spawnstatic2       56              // short modelindex instead of byte
 #define svc_entities           57              // [int] deltaframe [int] thisframe [float vector] eye [variable length] entitydata
@@ -256,7 +258,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #define        clc_stringcmd   4               // [string] message
 
 // LordHavoc: my clc_ range, 50-59
-#define clc_ackentities        50              // [int] framenumber
+#define clc_ackframe   50              // [int] framenumber
 #define clc_unusedlh1  51
 #define clc_unusedlh2  52
 #define clc_unusedlh3  53
@@ -357,9 +359,9 @@ typedef struct
        unsigned char glowcolor;
        unsigned char flags;
        unsigned char tagindex;
-       unsigned char colormod;
+       unsigned char colormod[3];
        // padding to a multiple of 8 bytes (to align the double time)
-       unsigned char unused[4];
+       unsigned char unused[2];
 }
 entity_state_t;
 
@@ -669,8 +671,8 @@ void EntityFrame4_CL_ReadFrame(void);
 #define E5_EFFECTS32 (1<<20)
 // flag
 #define E5_FRAME16 (1<<21)
-// unused
-#define E5_UNUSED22 (1<<22)
+// byte[3] = s->colormod[0], s->colormod[1], s->colormod[2]
+#define E5_COLORMOD (1<<22)
 // bits >= (1<<24)
 #define E5_EXTEND3 (1<<23)
 
@@ -706,6 +708,7 @@ typedef struct entityframe5_packetlog_s
        int packetnumber;
        int numstates;
        entityframe5_changestate_t states[ENTITYFRAME5_MAXSTATES];
+       qbyte statsdeltabits[(MAX_CL_STATS+7)/8];
 }
 entityframe5_packetlog_t;
 
@@ -733,6 +736,10 @@ typedef struct entityframe5_database_s
        // (derived from states)
        qbyte visiblebits[(MAX_EDICTS+7)/8];
 
+       // delta compression of stats
+       qbyte statsdeltabits[(MAX_CL_STATS+7)/8];
+       int stats[MAX_CL_STATS];
+
        // old notes
 
        // this is used to decide which changestates to set each frame
@@ -755,8 +762,9 @@ int EntityState5_Priority(entityframe5_database_t *d, entity_state_t *view, enti
 void EntityState5_WriteUpdate(int number, const entity_state_t *s, int changedbits, sizebuf_t *msg);
 int EntityState5_DeltaBitsForState(entity_state_t *o, entity_state_t *n);
 void EntityFrame5_CL_ReadFrame(void);
-void EntityFrame5_AckFrame(entityframe5_database_t *d, int framenum, int viewentnum);
-void EntityFrame5_WriteFrame(sizebuf_t *msg, entityframe5_database_t *d, int numstates, const entity_state_t *states, int viewentnum);
+void EntityFrame5_LostFrame(entityframe5_database_t *d, int framenum, int viewentnum);
+void EntityFrame5_AckFrame(entityframe5_database_t *d, int framenum);
+void EntityFrame5_WriteFrame(sizebuf_t *msg, entityframe5_database_t *d, int numstates, const entity_state_t *states, int viewentnum, int *stats);
 
 extern cvar_t developer_networkentities;
 
index 2f8866d..fe85c4e 100644 (file)
@@ -67,7 +67,7 @@ extern char *buildstring;
 //
 // stats are integers communicated to the client by the server
 //
-#define        MAX_CL_STATS            32
+#define        MAX_CL_STATS            256
 #define        STAT_HEALTH                     0
 #define        STAT_FRAGS                      1
 #define        STAT_WEAPON                     2
@@ -83,6 +83,11 @@ extern char *buildstring;
 #define        STAT_TOTALMONSTERS      12
 #define        STAT_SECRETS            13              // bumped on client side by svc_foundsecret
 #define        STAT_MONSTERS           14              // bumped by svc_killedmonster
+#define STAT_ITEMS                     15 // FTE, DP
+#define STAT_VIEWHEIGHT                16 // FTE, DP
+//#define STAT_TIME                    17 // FTE
+//#define STAT_VIEW2           20 // FTE
+#define STAT_VIEWZOOM          21 // DP
 
 // stock defines
 
index 5a01184..70e4aab 100644 (file)
@@ -1533,15 +1533,15 @@ void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements
                        GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 0);
                        GL_BlendFunc(GL_DST_ALPHA, GL_ONE);
                        VectorScale(lightcolor, colorscale, color2);
+                       GL_LockArrays(0, numverts);
                        for (renders = 0;renders < 64 && (color2[0] > 0 || color2[1] > 0 || color2[2] > 0);renders++, color2[0]--, color2[1]--, color2[2]--)
                        {
                                GL_Color(bound(0, color2[0], 1), bound(0, color2[1], 1), bound(0, color2[2], 1), 1);
-                               GL_LockArrays(0, numverts);
                                R_Mesh_Draw(numverts, numtriangles, elements);
-                               GL_LockArrays(0, 0);
                                c_rt_lightmeshes++;
                                c_rt_lighttris += numtriangles;
                        }
+                       GL_LockArrays(0, 0);
                }
                if (diffusescale)
                {
@@ -1809,15 +1809,15 @@ void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements
                        GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 0);
                        GL_BlendFunc(GL_DST_ALPHA, GL_ONE);
                        VectorScale(lightcolor, colorscale, color2);
+                       GL_LockArrays(0, numverts);
                        for (renders = 0;renders < 64 && (color2[0] > 0 || color2[1] > 0 || color2[2] > 0);renders++, color2[0]--, color2[1]--, color2[2]--)
                        {
                                GL_Color(bound(0, color2[0], 1), bound(0, color2[1], 1), bound(0, color2[2], 1), 1);
-                               GL_LockArrays(0, numverts);
                                R_Mesh_Draw(numverts, numtriangles, elements);
-                               GL_LockArrays(0, 0);
                                c_rt_lightmeshes++;
                                c_rt_lighttris += numtriangles;
                        }
+                       GL_LockArrays(0, 0);
                }
                if (specularscale && (r_shadow_gloss.integer >= 2 || (r_shadow_gloss.integer >= 1 && glosstexture != r_shadow_blankglosstexture)))
                {
@@ -2034,20 +2034,20 @@ void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements
 #endif
                                        }
                                }
+                               R_Mesh_State(&m);
+                               GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 0);
+                               GL_BlendFunc(GL_DST_ALPHA, GL_ONE);
+                               VectorScale(lightcolor, colorscale, color2);
+                               GL_LockArrays(0, numverts);
+                               for (renders = 0;renders < 64 && (color2[0] > 0 || color2[1] > 0 || color2[2] > 0);renders++, color2[0]--, color2[1]--, color2[2]--)
+                               {
+                                       GL_Color(bound(0, color2[0], 1), bound(0, color2[1], 1), bound(0, color2[2], 1), 1);
+                                       R_Mesh_Draw(numverts, numtriangles, elements);
+                                       c_rt_lightmeshes++;
+                                       c_rt_lighttris += numtriangles;
+                               }
+                               GL_LockArrays(0, 0);
                        }
-                       R_Mesh_State(&m);
-                       GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 0);
-                       GL_BlendFunc(GL_DST_ALPHA, GL_ONE);
-                       VectorScale(lightcolor, colorscale, color2);
-                       GL_LockArrays(0, numverts);
-                       for (renders = 0;renders < 64 && (color2[0] > 0 || color2[1] > 0 || color2[2] > 0);renders++, color2[0]--, color2[1]--, color2[2]--)
-                       {
-                               GL_Color(bound(0, color2[0], 1), bound(0, color2[1], 1), bound(0, color2[2], 1), 1);
-                               R_Mesh_Draw(numverts, numtriangles, elements);
-                               c_rt_lightmeshes++;
-                               c_rt_lighttris += numtriangles;
-                       }
-                       GL_LockArrays(0, 0);
                }
        }
        else
@@ -2084,6 +2084,10 @@ void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements
 #endif
                                }
                        }
+                       if (r_textureunits.integer >= 3)
+                               m.pointer_color = NULL;
+                       else
+                               m.pointer_color = varray_color4f;
                        R_Mesh_State(&m);
                        for (renders = 0;renders < 64 && (color2[0] > 0 || color2[1] > 0 || color2[2] > 0);renders++, color2[0]--, color2[1]--, color2[2]--)
                        {
@@ -2091,20 +2095,11 @@ void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements
                                color[1] = bound(0, color2[1], 1);
                                color[2] = bound(0, color2[2], 1);
                                if (r_textureunits.integer >= 3)
-                               {
                                        GL_Color(color[0], color[1], color[2], 1);
-                                       m.pointer_color = NULL;
-                               }
                                else if (r_textureunits.integer >= 2)
-                               {
                                        R_Shadow_VertexNoShadingWithZAttenuation(numverts, vertex3f, color, matrix_modeltolight);
-                                       m.pointer_color = varray_color4f;
-                               }
                                else
-                               {
                                        R_Shadow_VertexNoShadingWithXYZAttenuation(numverts, vertex3f, color, matrix_modeltolight);
-                                       m.pointer_color = varray_color4f;
-                               }
                                GL_LockArrays(0, numverts);
                                R_Mesh_Draw(numverts, numtriangles, elements);
                                GL_LockArrays(0, 0);
@@ -2487,6 +2482,9 @@ void R_DrawRTLight(rtlight_t *rtlight, int visiblevolumes)
                ent = &cl_entities[0].render;
                if (ent->model && ent->model->DrawLight && (ent->flags & RENDER_LIGHT))
                {
+                       lightcolor2[0] = lightcolor[0] * ent->colormod[0] * ent->alpha;
+                       lightcolor2[1] = lightcolor[1] * ent->colormod[1] * ent->alpha;
+                       lightcolor2[2] = lightcolor[2] * ent->colormod[2] * ent->alpha;
                        Matrix4x4_Transform(&ent->inversematrix, rtlight->shadoworigin, relativelightorigin);
                        Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, relativeeyeorigin);
                        Matrix4x4_Concat(&matrix_modeltolight, &rtlight->matrix_worldtolight, &ent->matrix);
@@ -2496,10 +2494,10 @@ void R_DrawRTLight(rtlight_t *rtlight, int visiblevolumes)
                        {
                                R_Mesh_Matrix(&ent->matrix);
                                for (mesh = rtlight->static_meshchain_light;mesh;mesh = mesh->next)
-                                       R_Shadow_RenderLighting(mesh->numverts, mesh->numtriangles, mesh->element3i, mesh->vertex3f, mesh->svector3f, mesh->tvector3f, mesh->normal3f, mesh->texcoord2f, relativelightorigin, relativeeyeorigin, lightcolor, &matrix_modeltolight, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz, mesh->map_diffuse, mesh->map_normal, mesh->map_specular, cubemaptexture, rtlight->ambientscale, rtlight->diffusescale, rtlight->specularscale);
+                                       R_Shadow_RenderLighting(mesh->numverts, mesh->numtriangles, mesh->element3i, mesh->vertex3f, mesh->svector3f, mesh->tvector3f, mesh->normal3f, mesh->texcoord2f, relativelightorigin, relativeeyeorigin, lightcolor2, &matrix_modeltolight, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz, mesh->map_diffuse, mesh->map_normal, mesh->map_specular, cubemaptexture, rtlight->ambientscale, rtlight->diffusescale, rtlight->specularscale);
                        }
                        else
-                               ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, rtlight->radius, lightcolor, &matrix_modeltolight, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz, cubemaptexture, rtlight->ambientscale, rtlight->diffusescale, rtlight->specularscale, numsurfaces, surfacelist);
+                               ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, rtlight->radius, lightcolor2, &matrix_modeltolight, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz, cubemaptexture, rtlight->ambientscale, rtlight->diffusescale, rtlight->specularscale, numsurfaces, surfacelist);
                }
                if (r_drawentities.integer)
                {
@@ -2510,7 +2508,9 @@ void R_DrawRTLight(rtlight_t *rtlight, int visiblevolumes)
                                // transparent meshes are deferred for later
                                if (ent->visframe == r_framecount && BoxesOverlap(ent->mins, ent->maxs, cullmins, cullmaxs) && ent->model && ent->model->DrawLight && (ent->flags & (RENDER_LIGHT | RENDER_TRANSPARENT)) == RENDER_LIGHT)
                                {
-                                       VectorScale(lightcolor, ent->alpha, lightcolor2);
+                                       lightcolor2[0] = lightcolor[0] * ent->colormod[0] * ent->alpha;
+                                       lightcolor2[1] = lightcolor[1] * ent->colormod[1] * ent->alpha;
+                                       lightcolor2[2] = lightcolor[2] * ent->colormod[2] * ent->alpha;
                                        Matrix4x4_Transform(&ent->inversematrix, rtlight->shadoworigin, relativelightorigin);
                                        Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, relativeeyeorigin);
                                        Matrix4x4_Concat(&matrix_modeltolight, &rtlight->matrix_worldtolight, &ent->matrix);
index 9868ff4..cf6048d 100644 (file)
@@ -98,6 +98,9 @@ void R_DrawSpriteModelCallback(const void *calldata1, int calldata2)
                R_CompleteLightPoint(color, diffusecolor, diffusenormal, ent->origin, true, NULL);
                VectorMA(color, 0.5f, diffusecolor, color);
        }
+       color[0] *= ent->colormod[0];
+       color[1] *= ent->colormod[1];
+       color[2] *= ent->colormod[2];
 
        if (fogenabled)
        {
diff --git a/sbar.c b/sbar.c
index 09c43cb..02e3f6c 100644 (file)
--- a/sbar.c
+++ b/sbar.c
@@ -549,7 +549,7 @@ void Sbar_DrawInventory (void)
        // weapons
        for (i=0 ; i<7 ; i++)
        {
-               if (cl.items & (IT_SHOTGUN<<i) )
+               if (cl.stats[STAT_ITEMS] & (IT_SHOTGUN<<i) )
                {
                        time = cl.item_gettime[i];
                        flashon = (int)((cl.time - time)*10);
@@ -574,7 +574,7 @@ void Sbar_DrawInventory (void)
                int grenadeflashing=0;
                for (i=0 ; i<4 ; i++)
                {
-                       if (cl.items & (1<<hipweapons[i]) )
+                       if (cl.stats[STAT_ITEMS] & (1<<hipweapons[i]) )
                        {
                                time = cl.item_gettime[hipweapons[i]];
                                flashon = (int)((cl.time - time)*10);
@@ -591,7 +591,7 @@ void Sbar_DrawInventory (void)
                                // check grenade launcher
                                if (i==2)
                                {
-                                       if (cl.items & HIT_PROXIMITY_GUN)
+                                       if (cl.stats[STAT_ITEMS] & HIT_PROXIMITY_GUN)
                                        {
                                                if (flashon)
                                                {
@@ -602,7 +602,7 @@ void Sbar_DrawInventory (void)
                                }
                                else if (i==3)
                                {
-                                       if (cl.items & (IT_SHOTGUN<<4))
+                                       if (cl.stats[STAT_ITEMS] & (IT_SHOTGUN<<4))
                                        {
                                                if (!grenadeflashing)
                                                        Sbar_DrawPic (96, -16, hsb_weapons[flashon][3]);
@@ -639,7 +639,7 @@ void Sbar_DrawInventory (void)
 
        // items
        for (i=0 ; i<6 ; i++)
-               if (cl.items & (1<<(17+i)))
+               if (cl.stats[STAT_ITEMS] & (1<<(17+i)))
                {
                        //MED 01/04/97 changed keys
                        if (gamemode != GAME_HIPNOTIC || (i>1))
@@ -651,7 +651,7 @@ void Sbar_DrawInventory (void)
        if (gamemode == GAME_HIPNOTIC)
        {
                for (i=0 ; i<2 ; i++)
-                       if (cl.items & (1<<(24+i)))
+                       if (cl.stats[STAT_ITEMS] & (1<<(24+i)))
                                Sbar_DrawPic (288 + i*16, -16, hsb_items[i]);
        }
 
@@ -659,14 +659,14 @@ void Sbar_DrawInventory (void)
        {
                // new rogue items
                for (i=0 ; i<2 ; i++)
-                       if (cl.items & (1<<(29+i)))
+                       if (cl.stats[STAT_ITEMS] & (1<<(29+i)))
                                Sbar_DrawPic (288 + i*16, -16, rsb_items[i]);
        }
        else
        {
                // sigils
                for (i=0 ; i<4 ; i++)
-                       if (cl.items & (1<<(28+i)))
+                       if (cl.stats[STAT_ITEMS] & (1<<(28+i)))
                                Sbar_DrawPic (320-32 + i*8, -16, sb_sigil[i]);
        }
 }
@@ -772,13 +772,13 @@ void Sbar_DrawFace (void)
        }
 // PGM 01/19/97 - team color drawing
 
-       if ( (cl.items & (IT_INVISIBILITY | IT_INVULNERABILITY) ) == (IT_INVISIBILITY | IT_INVULNERABILITY) )
+       if ( (cl.stats[STAT_ITEMS] & (IT_INVISIBILITY | IT_INVULNERABILITY) ) == (IT_INVISIBILITY | IT_INVULNERABILITY) )
                Sbar_DrawPic (112, 0, sb_face_invis_invuln);
-       else if (cl.items & IT_QUAD)
+       else if (cl.stats[STAT_ITEMS] & IT_QUAD)
                Sbar_DrawPic (112, 0, sb_face_quad );
-       else if (cl.items & IT_INVISIBILITY)
+       else if (cl.stats[STAT_ITEMS] & IT_INVISIBILITY)
                Sbar_DrawPic (112, 0, sb_face_invis );
-       else if (cl.items & IT_INVULNERABILITY)
+       else if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
                Sbar_DrawPic (112, 0, sb_face_invuln);
        else
        {
@@ -909,11 +909,11 @@ void Sbar_Draw (void)
                        // armor
                        if (cl.stats[STAT_ARMOR])
                        {
-                               if (cl.items & IT_ARMOR3)
+                               if (cl.stats[STAT_ITEMS] & IT_ARMOR3)
                                        Sbar_DrawPic(0, 0, somsb_armor[2]);
-                               else if (cl.items & IT_ARMOR2)
+                               else if (cl.stats[STAT_ITEMS] & IT_ARMOR2)
                                        Sbar_DrawPic(0, 0, somsb_armor[1]);
-                               else if (cl.items & IT_ARMOR1)
+                               else if (cl.stats[STAT_ITEMS] & IT_ARMOR1)
                                        Sbar_DrawPic(0, 0, somsb_armor[0]);
                                Sbar_DrawNum(24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
                        }
@@ -923,13 +923,13 @@ void Sbar_Draw (void)
                        Sbar_DrawNum(24, 24, cl.stats[STAT_HEALTH], 3, cl.stats[STAT_HEALTH] <= 25);
 
                        // ammo icon
-                       if (cl.items & IT_SHELLS)
+                       if (cl.stats[STAT_ITEMS] & IT_SHELLS)
                                Sbar_DrawPic(0, 48, somsb_ammo[0]);
-                       else if (cl.items & IT_NAILS)
+                       else if (cl.stats[STAT_ITEMS] & IT_NAILS)
                                Sbar_DrawPic(0, 48, somsb_ammo[1]);
-                       else if (cl.items & IT_ROCKETS)
+                       else if (cl.stats[STAT_ITEMS] & IT_ROCKETS)
                                Sbar_DrawPic(0, 48, somsb_ammo[2]);
-                       else if (cl.items & IT_CELLS)
+                       else if (cl.stats[STAT_ITEMS] & IT_CELLS)
                                Sbar_DrawPic(0, 48, somsb_ammo[3]);
                        Sbar_DrawNum(24, 48, cl.stats[STAT_AMMO], 3, false);
                        if (cl.stats[STAT_SHELLS])
@@ -959,12 +959,12 @@ void Sbar_Draw (void)
                                fade *= fade;
                                for (i = 0; i < 8;i++)
                                {
-                                       if (!(cl.items & (1 << i)))
+                                       if (!(cl.stats[STAT_ITEMS] & (1 << i)))
                                                continue;
                                        Sbar_DrawWeapon(i + 1, fade, ((1<<i) == cl.stats[STAT_ACTIVEWEAPON]));
                                }
                        
-                               if((cl.items & (1<<12)))
+                               if((cl.stats[STAT_ITEMS] & (1<<12)))
                                        Sbar_DrawWeapon(0, fade, (cl.stats[STAT_ACTIVEWEAPON] == (1<<12)));
                        }
 
@@ -977,7 +977,7 @@ void Sbar_Draw (void)
                                Sbar_DrawAlphaPic (0, 0, sb_sbar_minimal, sbar_alpha_fg.value);
 
                        // special items
-                       if (cl.items & IT_INVULNERABILITY)
+                       if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
                        {
                                Sbar_DrawNum (36, 0, 666, 3, 1);
                                Sbar_DrawPic (0, 0, sb_disc);
@@ -997,13 +997,13 @@ void Sbar_Draw (void)
                        // AK dont draw ammo for the laser
                        if(cl.stats[STAT_ACTIVEWEAPON] != 12)
                        {
-                               if (cl.items & NEX_IT_SHELLS)
+                               if (cl.stats[STAT_ITEMS] & NEX_IT_SHELLS)
                                        Sbar_DrawPic (519, 0, sb_ammo[0]);
-                               else if (cl.items & NEX_IT_BULLETS)
+                               else if (cl.stats[STAT_ITEMS] & NEX_IT_BULLETS)
                                        Sbar_DrawPic (519, 0, sb_ammo[1]);
-                               else if (cl.items & NEX_IT_ROCKETS)
+                               else if (cl.stats[STAT_ITEMS] & NEX_IT_ROCKETS)
                                        Sbar_DrawPic (519, 0, sb_ammo[2]);
-                               else if (cl.items & NEX_IT_CELLS)
+                               else if (cl.stats[STAT_ITEMS] & NEX_IT_CELLS)
                                        Sbar_DrawPic (519, 0, sb_ammo[3]);
 
                                if(cl.stats[STAT_AMMO] <= 10)
@@ -1050,15 +1050,15 @@ void Sbar_Draw (void)
                        //MED 01/04/97 moved keys here so they would not be overwritten
                        if (gamemode == GAME_HIPNOTIC)
                        {
-                               if (cl.items & IT_KEY1)
+                               if (cl.stats[STAT_ITEMS] & IT_KEY1)
                                        Sbar_DrawPic (209, 3, sb_items[0]);
-                               if (cl.items & IT_KEY2)
+                               if (cl.stats[STAT_ITEMS] & IT_KEY2)
                                        Sbar_DrawPic (209, 12, sb_items[1]);
                        }
                        // armor
                        if (gamemode != GAME_GOODVSBAD2)
                        {
-                               if (cl.items & IT_INVULNERABILITY)
+                               if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
                                {
                                        Sbar_DrawNum (24, 0, 666, 3, 1);
                                        Sbar_DrawPic (0, 0, sb_disc);
@@ -1068,21 +1068,21 @@ void Sbar_Draw (void)
                                        if (gamemode == GAME_ROGUE)
                                        {
                                                Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
-                                               if (cl.items & RIT_ARMOR3)
+                                               if (cl.stats[STAT_ITEMS] & RIT_ARMOR3)
                                                        Sbar_DrawPic (0, 0, sb_armor[2]);
-                                               else if (cl.items & RIT_ARMOR2)
+                                               else if (cl.stats[STAT_ITEMS] & RIT_ARMOR2)
                                                        Sbar_DrawPic (0, 0, sb_armor[1]);
-                                               else if (cl.items & RIT_ARMOR1)
+                                               else if (cl.stats[STAT_ITEMS] & RIT_ARMOR1)
                                                        Sbar_DrawPic (0, 0, sb_armor[0]);
                                        }
                                        else
                                        {
                                                Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
-                                               if (cl.items & IT_ARMOR3)
+                                               if (cl.stats[STAT_ITEMS] & IT_ARMOR3)
                                                        Sbar_DrawPic (0, 0, sb_armor[2]);
-                                               else if (cl.items & IT_ARMOR2)
+                                               else if (cl.stats[STAT_ITEMS] & IT_ARMOR2)
                                                        Sbar_DrawPic (0, 0, sb_armor[1]);
-                                               else if (cl.items & IT_ARMOR1)
+                                               else if (cl.stats[STAT_ITEMS] & IT_ARMOR1)
                                                        Sbar_DrawPic (0, 0, sb_armor[0]);
                                        }
                                }
@@ -1097,30 +1097,30 @@ void Sbar_Draw (void)
                        // ammo icon
                        if (gamemode == GAME_ROGUE)
                        {
-                               if (cl.items & RIT_SHELLS)
+                               if (cl.stats[STAT_ITEMS] & RIT_SHELLS)
                                        Sbar_DrawPic (224, 0, sb_ammo[0]);
-                               else if (cl.items & RIT_NAILS)
+                               else if (cl.stats[STAT_ITEMS] & RIT_NAILS)
                                        Sbar_DrawPic (224, 0, sb_ammo[1]);
-                               else if (cl.items & RIT_ROCKETS)
+                               else if (cl.stats[STAT_ITEMS] & RIT_ROCKETS)
                                        Sbar_DrawPic (224, 0, sb_ammo[2]);
-                               else if (cl.items & RIT_CELLS)
+                               else if (cl.stats[STAT_ITEMS] & RIT_CELLS)
                                        Sbar_DrawPic (224, 0, sb_ammo[3]);
-                               else if (cl.items & RIT_LAVA_NAILS)
+                               else if (cl.stats[STAT_ITEMS] & RIT_LAVA_NAILS)
                                        Sbar_DrawPic (224, 0, rsb_ammo[0]);
-                               else if (cl.items & RIT_PLASMA_AMMO)
+                               else if (cl.stats[STAT_ITEMS] & RIT_PLASMA_AMMO)
                                        Sbar_DrawPic (224, 0, rsb_ammo[1]);
-                               else if (cl.items & RIT_MULTI_ROCKETS)
+                               else if (cl.stats[STAT_ITEMS] & RIT_MULTI_ROCKETS)
                                        Sbar_DrawPic (224, 0, rsb_ammo[2]);
                        }
                        else
                        {
-                               if (cl.items & IT_SHELLS)
+                               if (cl.stats[STAT_ITEMS] & IT_SHELLS)
                                        Sbar_DrawPic (224, 0, sb_ammo[0]);
-                               else if (cl.items & IT_NAILS)
+                               else if (cl.stats[STAT_ITEMS] & IT_NAILS)
                                        Sbar_DrawPic (224, 0, sb_ammo[1]);
-                               else if (cl.items & IT_ROCKETS)
+                               else if (cl.stats[STAT_ITEMS] & IT_ROCKETS)
                                        Sbar_DrawPic (224, 0, sb_ammo[2]);
-                               else if (cl.items & IT_CELLS)
+                               else if (cl.stats[STAT_ITEMS] & IT_CELLS)
                                        Sbar_DrawPic (224, 0, sb_ammo[3]);
                        }
 
@@ -1140,6 +1140,9 @@ void Sbar_Draw (void)
        Sbar_ShowFPS();
 
        R_Draw2DCrosshair();
+
+       if (cl_prydoncursor.integer)
+               DrawQ_Pic((cl.cmd.cursor_screen[0] + 1) * 0.5 * vid.conwidth, (cl.cmd.cursor_screen[1] + 1) * 0.5 * vid.conheight, va("gfx/prydoncursor%03i.lmp", cl_prydoncursor.integer), 0, 0, 1, 1, 1, 1, 0);
 }
 
 //=============================================================================
index d369777..f42c67e 100644 (file)
--- a/server.h
+++ b/server.h
@@ -69,10 +69,14 @@ typedef struct
        char modelname[64];
        struct model_s *worldmodel;
        // NULL terminated
-       char *model_precache[MAX_MODELS];
+       // LordHavoc: precaches are now MAX_QPATH rather than a pointer
+       // updated by SV_ModelIndex
+       char model_precache[MAX_MODELS][MAX_QPATH];
        struct model_s *models[MAX_MODELS];
        // NULL terminated
-       char *sound_precache[MAX_SOUNDS];
+       // LordHavoc: precaches are now MAX_QPATH rather than a pointer
+       // updated by SV_SoundIndex
+       char sound_precache[MAX_SOUNDS][MAX_QPATH];
        char *lightstyles[MAX_LIGHTSTYLES];
        int num_edicts;
        int max_edicts;
@@ -163,6 +167,9 @@ typedef struct client_s
        // prevent animated names
        float nametime;
 
+       // latest received clc_ackframe (used to detect packet loss)
+       int latestframenum;
+
        entityframe_database_t *entitydatabase;
        entityframe4_database_t *entitydatabase4;
        entityframe5_database_t *entitydatabase5;
@@ -267,6 +274,7 @@ extern cvar_t sv_gameplayfix_noairborncorpse;
 extern cvar_t sv_gameplayfix_stepdown;
 extern cvar_t sv_gameplayfix_stepwhilejumping;
 extern cvar_t sv_gameplayfix_swiminbmodels;
+extern cvar_t sv_gameplayfix_setmodelrealbox;
 
 extern mempool_t *sv_clients_mempool;
 extern mempool_t *sv_edicts_mempool;
@@ -296,7 +304,12 @@ void SV_ClearDatagram (void);
 
 void SV_ReadClientMessage(void);
 
-int SV_ModelIndex (const char *name);
+// precachemode values:
+// 0 = fail if not precached,
+// 1 = warn if not found and precache if possible
+// 2 = precache
+int SV_ModelIndex(char *s, int precachemode);
+int SV_SoundIndex(char *s, int precachemode);
 
 void SV_SetIdealPitch (void);
 
@@ -315,7 +328,7 @@ qboolean SV_PlayerCheckGround (edict_t *ent);
 qboolean SV_CheckBottom (edict_t *ent);
 qboolean SV_movestep (edict_t *ent, vec3_t move, qboolean relink);
 
-void SV_WriteClientdataToMessage (edict_t *ent, sizebuf_t *msg);
+void SV_WriteClientdataToMessage (client_t *client, edict_t *ent, sizebuf_t *msg, int *stats);
 
 void SV_MoveToGoal (void);
 
index a1dab00..999be85 100644 (file)
--- a/sv_main.c
+++ b/sv_main.c
@@ -22,8 +22,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #include "quakedef.h"
 
 // select which protocol to host, by name
-// this is named the same as PROTOCOL_DARKPLACES5 for example, minus the PROTOCOL_ prefix
-cvar_t sv_protocolname = {0, "sv_protocolname", "DARKPLACES5"};
+// this is named the same as PROTOCOL_DARKPLACES6 for example, minus the PROTOCOL_ prefix
+cvar_t sv_protocolname = {0, "sv_protocolname", "DARKPLACES6"};
 cvar_t sv_ratelimitlocalplayer = {0, "sv_ratelimitlocalplayer", "0"};
 cvar_t sv_maxrate = {CVAR_SAVE | CVAR_NOTIFY, "sv_maxrate", "10000"};
 
@@ -39,12 +39,11 @@ cvar_t sv_gameplayfix_noairborncorpse = {0, "sv_gameplayfix_noairborncorpse", "1
 cvar_t sv_gameplayfix_stepdown = {0, "sv_gameplayfix_stepdown", "1"};
 cvar_t sv_gameplayfix_stepwhilejumping = {0, "sv_gameplayfix_stepwhilejumping", "1"};
 cvar_t sv_gameplayfix_swiminbmodels = {0, "sv_gameplayfix_swiminbmodels", "1"};
+cvar_t sv_gameplayfix_setmodelrealbox = {0, "sv_gameplayfix_setmodelrealbox", "1"};
 
 server_t sv;
 server_static_t svs;
 
-static char localmodels[MAX_MODELS][5];                        // inline model names for precache
-
 mempool_t *sv_edicts_mempool = NULL;
 
 //============================================================================
@@ -60,8 +59,6 @@ SV_Init
 */
 void SV_Init (void)
 {
-       int i;
-
        Cmd_AddCommand("sv_saveentfile", SV_SaveEntFile_f);
        Cvar_RegisterVariable (&sv_maxvelocity);
        Cvar_RegisterVariable (&sv_gravity);
@@ -83,6 +80,7 @@ void SV_Init (void)
        Cvar_RegisterVariable (&sv_gameplayfix_stepdown);
        Cvar_RegisterVariable (&sv_gameplayfix_stepwhilejumping);
        Cvar_RegisterVariable (&sv_gameplayfix_swiminbmodels);
+       Cvar_RegisterVariable (&sv_gameplayfix_setmodelrealbox);
        Cvar_RegisterVariable (&sv_protocolname);
        Cvar_RegisterVariable (&sv_ratelimitlocalplayer);
        Cvar_RegisterVariable (&sv_maxrate);
@@ -90,9 +88,6 @@ void SV_Init (void)
        SV_Phys_Init();
        SV_World_Init();
 
-       for (i = 0;i < MAX_MODELS;i++)
-               sprintf (localmodels[i], "*%i", i);
-
        sv_edicts_mempool = Mem_AllocPool("server edicts", 0, NULL);
 }
 
@@ -108,6 +103,7 @@ static void SV_SaveEntFile_f(void)
        FS_WriteFile(va("%s.ent", basename), sv.worldmodel->brush.entities, strlen(sv.worldmodel->brush.entities));
 }
 
+
 /*
 =============================================================================
 
@@ -215,15 +211,9 @@ void SV_StartSound (edict_t *entity, int channel, char *sample, int volume, floa
                return;
 
 // find precache number for sound
-       for (sound_num=1 ; sound_num<MAX_SOUNDS && sv.sound_precache[sound_num] ; sound_num++)
-               if (!strcmp(sample, sv.sound_precache[sound_num]))
-                       break;
-
-       if ( sound_num == MAX_SOUNDS || !sv.sound_precache[sound_num] )
-       {
-               Con_Printf("SV_StartSound: %s not precached\n", sample);
+       sound_num = SV_SoundIndex(sample, 1);
+       if (!sound_num)
                return;
-       }
 
        ent = NUM_FOR_EDICT(entity);
 
@@ -277,8 +267,8 @@ This will be sent on the initial connection and upon each server load.
 */
 void SV_SendServerinfo (client_t *client)
 {
-       char                    **s;
-       char                    message[128];
+       int i;
+       char message[128];
 
        // edicts get reallocated on level changes, so we need to update it here
        client->edict = EDICT_NUM((client - svs.clients) + 1);
@@ -287,8 +277,6 @@ void SV_SendServerinfo (client_t *client)
        // client info that normally requires networking
        if (!client->netconnection)
        {
-               int i;
-
                // set up the edict
                ED_ClearEdict(client->edict);
 
@@ -306,6 +294,7 @@ void SV_SendServerinfo (client_t *client)
        }
 
        // LordHavoc: clear entityframe tracking
+       client->latestframenum = 0;
 
        if (client->entitydatabase)
                EntityFrame_FreeDatabase(client->entitydatabase);
@@ -318,7 +307,7 @@ void SV_SendServerinfo (client_t *client)
                client->entitydatabase = EntityFrame_AllocDatabase(sv_clients_mempool);
        if (sv.protocol == PROTOCOL_DARKPLACES4)
                client->entitydatabase4 = EntityFrame4_AllocDatabase(sv_clients_mempool);
-       if (sv.protocol == PROTOCOL_DARKPLACES5)
+       if (sv.protocol == PROTOCOL_DARKPLACES5 || sv.protocol == PROTOCOL_DARKPLACES6)
                client->entitydatabase5 = EntityFrame5_AllocDatabase(sv_clients_mempool);
 
        MSG_WriteByte (&client->message, svc_print);
@@ -336,12 +325,12 @@ void SV_SendServerinfo (client_t *client)
 
        MSG_WriteString (&client->message,PR_GetString(sv.edicts->v->message));
 
-       for (s = sv.model_precache+1 ; *s ; s++)
-               MSG_WriteString (&client->message, *s);
+       for (i = 1;i < MAX_MODELS && sv.model_precache[i][0];i++)
+               MSG_WriteString (&client->message, sv.model_precache[i]);
        MSG_WriteByte (&client->message, 0);
 
-       for (s = sv.sound_precache+1 ; *s ; s++)
-               MSG_WriteString (&client->message, *s);
+       for (i = 1;i < MAX_SOUNDS && sv.sound_precache[i][0];i++)
+               MSG_WriteString (&client->message, sv.sound_precache[i]);
        MSG_WriteByte (&client->message, 0);
 
 // send music
@@ -655,9 +644,12 @@ void SV_MarkWriteEntityStateToClient(entity_state_t *s)
                        if (sententities[s->tagentity] != sententitiesmark)
                                return;
                }
+               // skip invalid modelindexes to avoid crashes
+               else if (s->modelindex >= MAX_MODELS)
+                       return;
                // always send world submodels, they don't generate much traffic
                // except in PROTOCOL_QUAKE where they hog bandwidth like crazy
-               else if ((!(isbmodel = (model = sv.models[s->modelindex]) != NULL && model->name[0] == '*') && !(s->effects & EF_NODEPTHTEST)) || sv.protocol == PROTOCOL_QUAKE)
+               else if (!(s->effects & EF_NODEPTHTEST) && (sv.protocol == PROTOCOL_QUAKE || !(isbmodel = (model = sv.models[s->modelindex]) != NULL && model->name[0] == '*')))
                {
                        Mod_CheckLoaded(model);
                        // entity has survived every check so far, check if visible
@@ -752,7 +744,7 @@ void SV_MarkWriteEntityStateToClient(entity_state_t *s)
 
 entity_state_t sendstates[MAX_EDICTS]; 
 
-void SV_WriteEntitiesToClient(client_t *client, edict_t *clent, sizebuf_t *msg)
+void SV_WriteEntitiesToClient(client_t *client, edict_t *clent, sizebuf_t *msg, int *stats)
 {
        int i, numsendstates;
        entity_state_t *s;
@@ -800,7 +792,7 @@ void SV_WriteEntitiesToClient(client_t *client, edict_t *clent, sizebuf_t *msg)
                Con_Printf("client \"%s\" entities: %d total, %d visible, %d culled by: %d pvs %d trace\n", client->name, sv_writeentitiestoclient_totalentities, sv_writeentitiestoclient_visibleentities, sv_writeentitiestoclient_culled_pvs + sv_writeentitiestoclient_culled_trace, sv_writeentitiestoclient_culled_pvs, sv_writeentitiestoclient_culled_trace);
 
        if (client->entitydatabase5)
-               EntityFrame5_WriteFrame(msg, client->entitydatabase5, numsendstates, sendstates, client - svs.clients + 1);
+               EntityFrame5_WriteFrame(msg, client->entitydatabase5, numsendstates, sendstates, client - svs.clients + 1, stats);
        else if (client->entitydatabase4)
                EntityFrame4_WriteFrame(msg, client->entitydatabase4, numsendstates, sendstates);
        else if (client->entitydatabase)
@@ -831,7 +823,7 @@ SV_WriteClientdataToMessage
 
 ==================
 */
-void SV_WriteClientdataToMessage (edict_t *ent, sizebuf_t *msg)
+void SV_WriteClientdataToMessage (client_t *client, edict_t *ent, sizebuf_t *msg, int *stats)
 {
        int             bits;
        int             i;
@@ -840,6 +832,7 @@ void SV_WriteClientdataToMessage (edict_t *ent, sizebuf_t *msg)
        eval_t  *val;
        vec3_t  punchvector;
        qbyte   viewzoom;
+       int             weaponmodelindex;
 
 //
 // send a damage message
@@ -871,78 +864,91 @@ void SV_WriteClientdataToMessage (edict_t *ent, sizebuf_t *msg)
                ent->v->fixangle = 0;
        }
 
-       bits = 0;
-
-       if (ent->v->view_ofs[2] != DEFAULT_VIEWHEIGHT)
-               bits |= SU_VIEWHEIGHT;
-
-       if (ent->v->idealpitch)
-               bits |= SU_IDEALPITCH;
-
-// stuff the sigil bits into the high bits of items for sbar, or else
-// mix in items2
+       // stuff the sigil bits into the high bits of items for sbar, or else
+       // mix in items2
        val = GETEDICTFIELDVALUE(ent, eval_items2);
-
        if (val)
                items = (int)ent->v->items | ((int)val->_float << 23);
        else
                items = (int)ent->v->items | ((int)pr_global_struct->serverflags << 28);
 
-       bits |= SU_ITEMS;
-
-       if ( (int)ent->v->flags & FL_ONGROUND)
-               bits |= SU_ONGROUND;
-
-       if ( ent->v->waterlevel >= 2)
-               bits |= SU_INWATER;
-
-       // PROTOCOL_DARKPLACES
        VectorClear(punchvector);
        if ((val = GETEDICTFIELDVALUE(ent, eval_punchvector)))
                VectorCopy(val->vector, punchvector);
 
-       i = 255;
-       if ((val = GETEDICTFIELDVALUE(ent, eval_viewzoom)))
+       weaponmodelindex = SV_ModelIndex(PR_GetString(ent->v->weaponmodel), 1);
+       if (!weaponmodelindex)
        {
-               i = val->_float * 255.0f;
-               if (i == 0)
-                       i = 255;
-               else
-                       i = bound(0, i, 65535);
+               Con_DPrintf("weaponmodel \"%s\" not precached\n", PR_GetString(ent->v->weaponmodel));
+               weaponmodelindex = 0;
        }
-       viewzoom = i;
 
-       // FIXME: which protocols support this?  does PROTOCOL_DARKPLACES3 support viewzoom?
-       if (sv.protocol == PROTOCOL_DARKPLACES4 || sv.protocol == PROTOCOL_DARKPLACES5)
-               if (viewzoom != 255)
-                       bits |= SU_VIEWZOOM;
+       viewzoom = 255;
+       if ((val = GETEDICTFIELDVALUE(ent, eval_viewzoom)))
+               viewzoom = val->_float * 255.0f;
+       if (viewzoom == 0)
+               viewzoom = 255;
+
+       bits = 0;
+
+       if ((int)ent->v->flags & FL_ONGROUND)
+               bits |= SU_ONGROUND;
+       if (ent->v->waterlevel >= 2)
+               bits |= SU_INWATER;
+       if (ent->v->idealpitch)
+               bits |= SU_IDEALPITCH;
 
        for (i=0 ; i<3 ; i++)
        {
                if (ent->v->punchangle[i])
                        bits |= (SU_PUNCH1<<i);
-               if (sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4 || sv.protocol == PROTOCOL_DARKPLACES5)
+               if (sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4 || sv.protocol == PROTOCOL_DARKPLACES5 || sv.protocol == PROTOCOL_DARKPLACES6)
                        if (punchvector[i])
                                bits |= (SU_PUNCHVEC1<<i);
                if (ent->v->velocity[i])
                        bits |= (SU_VELOCITY1<<i);
        }
 
-       if (ent->v->weaponframe)
-               bits |= SU_WEAPONFRAME;
-
-       if (ent->v->armorvalue)
-               bits |= SU_ARMOR;
-
-       bits |= SU_WEAPON;
+       memset(stats, 0, sizeof(int[MAX_CL_STATS]));
+       stats[STAT_VIEWHEIGHT] = ent->v->view_ofs[2];
+       stats[STAT_ITEMS] = items;
+       stats[STAT_WEAPONFRAME] = ent->v->weaponframe;
+       stats[STAT_ARMOR] = ent->v->armorvalue;
+       stats[STAT_WEAPON] = weaponmodelindex;
+       stats[STAT_HEALTH] = ent->v->health;
+       stats[STAT_AMMO] = ent->v->currentammo;
+       stats[STAT_SHELLS] = ent->v->ammo_shells;
+       stats[STAT_NAILS] = ent->v->ammo_nails;
+       stats[STAT_ROCKETS] = ent->v->ammo_rockets;
+       stats[STAT_CELLS] = ent->v->ammo_cells;
+       stats[STAT_ACTIVEWEAPON] = ent->v->weapon;
+       stats[STAT_VIEWZOOM] = viewzoom;
+       // the QC bumps these itself by sending svc_'s, so we have to keep them
+       // zero or they'll be corrected by the engine
+       //stats[STAT_TOTALSECRETS] = pr_global_struct->total_secrets;
+       //stats[STAT_TOTALMONSTERS] = pr_global_struct->total_monsters;
+       //stats[STAT_SECRETS] = pr_global_struct->found_secrets;
+       //stats[STAT_MONSTERS] = pr_global_struct->killed_monsters;
+
+       if (sv.protocol != PROTOCOL_DARKPLACES6)
+       {
+               if (stats[STAT_VIEWHEIGHT] != DEFAULT_VIEWHEIGHT) bits |= SU_VIEWHEIGHT;
+               bits |= SU_ITEMS;
+               if (stats[STAT_WEAPONFRAME]) bits |= SU_WEAPONFRAME;
+               if (stats[STAT_ARMOR]) bits |= SU_ARMOR;
+               bits |= SU_WEAPON;
+               // FIXME: which protocols support this?  does PROTOCOL_DARKPLACES3 support viewzoom?
+               if (sv.protocol == PROTOCOL_DARKPLACES4 || sv.protocol == PROTOCOL_DARKPLACES5)
+                       if (viewzoom != 255)
+                               bits |= SU_VIEWZOOM;
+       }
 
        if (bits >= 65536)
                bits |= SU_EXTEND1;
        if (bits >= 16777216)
                bits |= SU_EXTEND2;
 
-// send the data
-
+       // send the data
        MSG_WriteByte (msg, svc_clientdata);
        MSG_WriteShort (msg, bits);
        if (bits & SU_EXTEND1)
@@ -951,7 +957,7 @@ void SV_WriteClientdataToMessage (edict_t *ent, sizebuf_t *msg)
                MSG_WriteByte(msg, bits >> 24);
 
        if (bits & SU_VIEWHEIGHT)
-               MSG_WriteChar (msg, ent->v->view_ofs[2]);
+               MSG_WriteChar (msg, stats[STAT_VIEWHEIGHT]);
 
        if (bits & SU_IDEALPITCH)
                MSG_WriteChar (msg, ent->v->idealpitch);
@@ -962,16 +968,16 @@ void SV_WriteClientdataToMessage (edict_t *ent, sizebuf_t *msg)
                {
                        if (sv.protocol == PROTOCOL_QUAKE)
                                MSG_WriteChar(msg, ent->v->punchangle[i]);
-                       else if (sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4 || sv.protocol == PROTOCOL_DARKPLACES5)
+                       else if (sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4 || sv.protocol == PROTOCOL_DARKPLACES5 || sv.protocol == PROTOCOL_DARKPLACES6)
                                MSG_WriteAngle16i(msg, ent->v->punchangle[i]);
                }
-               if (sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4 || sv.protocol == PROTOCOL_DARKPLACES5)
+               if (sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4 || sv.protocol == PROTOCOL_DARKPLACES5 || sv.protocol == PROTOCOL_DARKPLACES6)
                {
                        if (bits & (SU_PUNCHVEC1<<i))
                        {
                                if (sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4)
                                        MSG_WriteCoord16i(msg, punchvector[i]);
-                               else if (sv.protocol == PROTOCOL_DARKPLACES5)
+                               else if (sv.protocol == PROTOCOL_DARKPLACES5 || sv.protocol == PROTOCOL_DARKPLACES6)
                                        MSG_WriteCoord32f(msg, punchvector[i]);
                        }
                }
@@ -979,92 +985,61 @@ void SV_WriteClientdataToMessage (edict_t *ent, sizebuf_t *msg)
                {
                        if (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4)
                                MSG_WriteChar(msg, ent->v->velocity[i] * (1.0f / 16.0f));
-                       else if (sv.protocol == PROTOCOL_DARKPLACES5)
+                       else if (sv.protocol == PROTOCOL_DARKPLACES5 || sv.protocol == PROTOCOL_DARKPLACES6)
                                MSG_WriteCoord32f(msg, ent->v->velocity[i]);
                }
        }
 
-// [always sent]       if (bits & SU_ITEMS)
-       MSG_WriteLong (msg, items);
+       if (bits & SU_ITEMS)
+               MSG_WriteLong (msg, stats[STAT_ITEMS]);
 
        if (sv.protocol == PROTOCOL_DARKPLACES5)
        {
                if (bits & SU_WEAPONFRAME)
-                       MSG_WriteShort (msg, ent->v->weaponframe);
+                       MSG_WriteShort (msg, stats[STAT_WEAPONFRAME]);
                if (bits & SU_ARMOR)
-                       MSG_WriteShort (msg, ent->v->armorvalue);
+                       MSG_WriteShort (msg, stats[STAT_ARMOR]);
                if (bits & SU_WEAPON)
-               {
-                       i = SV_ModelIndex(PR_GetString(ent->v->weaponmodel));
-                       if (i < 0)
-                       {
-                               Con_DPrintf("weaponmodel \"%s\" not precached\n", PR_GetString(ent->v->weaponmodel));
-                               i = 0;
-                       }
-                       MSG_WriteShort (msg, i);
-               }
-
-               MSG_WriteShort (msg, ent->v->health);
-               MSG_WriteShort (msg, ent->v->currentammo);
-               MSG_WriteShort (msg, ent->v->ammo_shells);
-               MSG_WriteShort (msg, ent->v->ammo_nails);
-               MSG_WriteShort (msg, ent->v->ammo_rockets);
-               MSG_WriteShort (msg, ent->v->ammo_cells);
-
-               MSG_WriteShort (msg, ent->v->weapon);
-       
+                       MSG_WriteShort (msg, stats[STAT_WEAPON]);
+               MSG_WriteShort (msg, stats[STAT_HEALTH]);
+               MSG_WriteShort (msg, stats[STAT_AMMO]);
+               MSG_WriteShort (msg, stats[STAT_SHELLS]);
+               MSG_WriteShort (msg, stats[STAT_NAILS]);
+               MSG_WriteShort (msg, stats[STAT_ROCKETS]);
+               MSG_WriteShort (msg, stats[STAT_CELLS]);
+               MSG_WriteShort (msg, stats[STAT_ACTIVEWEAPON]);
                if (bits & SU_VIEWZOOM)
-                       MSG_WriteShort (msg, viewzoom);
+                       MSG_WriteShort (msg, min(stats[STAT_VIEWZOOM], 65535));
        }
-       else
+       else if (sv.protocol != PROTOCOL_DARKPLACES6)
        {
                if (bits & SU_WEAPONFRAME)
-                       MSG_WriteByte (msg, ent->v->weaponframe);
+                       MSG_WriteByte (msg, stats[STAT_WEAPONFRAME]);
                if (bits & SU_ARMOR)
-                       MSG_WriteByte (msg, ent->v->armorvalue);
+                       MSG_WriteByte (msg, stats[STAT_ARMOR]);
                if (bits & SU_WEAPON)
-               {
-                       i = SV_ModelIndex(PR_GetString(ent->v->weaponmodel));
-                       if (i < 0)
-                       {
-                               Con_DPrintf("weaponmodel \"%s\" not precached\n", PR_GetString(ent->v->weaponmodel));
-                               i = 0;
-                       }
-                       MSG_WriteByte (msg, i);
-               }
-
-               MSG_WriteShort (msg, ent->v->health);
-               MSG_WriteByte (msg, ent->v->currentammo);
-               MSG_WriteByte (msg, ent->v->ammo_shells);
-               MSG_WriteByte (msg, ent->v->ammo_nails);
-               MSG_WriteByte (msg, ent->v->ammo_rockets);
-               MSG_WriteByte (msg, ent->v->ammo_cells);
-
+                       MSG_WriteByte (msg, stats[STAT_WEAPON]);
+               MSG_WriteShort (msg, stats[STAT_HEALTH]);
+               MSG_WriteByte (msg, stats[STAT_AMMO]);
+               MSG_WriteByte (msg, stats[STAT_SHELLS]);
+               MSG_WriteByte (msg, stats[STAT_NAILS]);
+               MSG_WriteByte (msg, stats[STAT_ROCKETS]);
+               MSG_WriteByte (msg, stats[STAT_CELLS]);
                if (gamemode == GAME_HIPNOTIC || gamemode == GAME_ROGUE || gamemode == GAME_NEXUIZ)
                {
-                       for(i=0;i<32;i++)
-                       {
-                               if ( ((int)ent->v->weapon) & (1<<i) )
-                               {
-                                       MSG_WriteByte (msg, i);
+                       for (i = 0;i < 32;i++)
+                               if (stats[STAT_WEAPON] & (1<<i))
                                        break;
-                               }
-                       }
+                       MSG_WriteByte (msg, i);
                }
                else
-               {
-                       MSG_WriteByte (msg, ent->v->weapon);
-               }
-       
+                       MSG_WriteByte (msg, stats[STAT_WEAPON]);
                if (bits & SU_VIEWZOOM)
                {
                        if (sv.protocol == PROTOCOL_DARKPLACES4)
-                       {
-                               viewzoom = min(viewzoom, 255);
-                               MSG_WriteByte (msg, viewzoom);
-                       }
-                       else if (sv.protocol == PROTOCOL_DARKPLACES5)
-                               MSG_WriteShort (msg, viewzoom);
+                               MSG_WriteByte (msg, min(stats[STAT_VIEWZOOM], 255));
+                       else if (sv.protocol == PROTOCOL_DARKPLACES5 || sv.protocol == PROTOCOL_DARKPLACES6)
+                               MSG_WriteShort (msg, min(stats[STAT_VIEWZOOM], 65535));
                }
        }
 }
@@ -1079,6 +1054,7 @@ qboolean SV_SendClientDatagram (client_t *client)
 {
        int rate, maxrate, maxsize, maxsize2;
        sizebuf_t msg;
+       int stats[MAX_CL_STATS];
 
        if (LHNETADDRESS_GetAddressType(&host_client->netconnection->peeraddress) == LHNETADDRESSTYPE_LOOP && !sv_ratelimitlocalplayer.integer)
        {
@@ -1086,7 +1062,7 @@ qboolean SV_SendClientDatagram (client_t *client)
                maxsize = sizeof(sv_sendclientdatagram_buf);
                maxsize2 = sizeof(sv_sendclientdatagram_buf);
        }
-       else if (sv.protocol == PROTOCOL_DARKPLACES5)
+       else if (sv.protocol == PROTOCOL_DARKPLACES5 || sv.protocol == PROTOCOL_DARKPLACES6)
        {
                // PROTOCOL_DARKPLACES5 supports packet size limiting of updates
                maxrate = bound(NET_MINRATE, sv_maxrate.integer, NET_MAXRATE);
@@ -1115,9 +1091,8 @@ qboolean SV_SendClientDatagram (client_t *client)
        MSG_WriteFloat (&msg, sv.time);
 
        // add the client specific data to the datagram
-       SV_WriteClientdataToMessage (client->edict, &msg);
-
-       SV_WriteEntitiesToClient (client, client->edict, &msg);
+       SV_WriteClientdataToMessage (client, client->edict, &msg, stats);
+       SV_WriteEntitiesToClient (client, client->edict, &msg, stats);
 
        // expand packet size to allow effects to go over the rate limit
        // (dropping them is FAR too ugly)
@@ -1323,22 +1298,111 @@ SV_ModelIndex
 
 ================
 */
-int SV_ModelIndex (const char *name)
+int SV_ModelIndex(char *s, int precachemode)
 {
-       int i;
-
-       if (!name || !name[0])
+       int i, limit = (sv.protocol == PROTOCOL_QUAKE ? 256 : MAX_MODELS);
+       char filename[MAX_QPATH];
+       if (!s || !*s)
                return 0;
-
-       for (i=0 ; i<MAX_MODELS && sv.model_precache[i] ; i++)
-               if (!strcmp(sv.model_precache[i], name))
+       // testing
+       //if (precachemode == 2)
+       //      return 0;
+       strlcpy(filename, s, sizeof(filename));
+       for (i = 2;i < limit;i++)
+       {
+               if (!sv.model_precache[i][0])
+               {
+                       if (precachemode)
+                       {
+                               if (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4 || sv.protocol == PROTOCOL_DARKPLACES5)
+                               {
+                                       // not able to precache during game
+                                       if (precachemode == 2 && sv.state != ss_loading)
+                                       {
+                                               Con_Printf("SV_ModelIndex(\"%s\"): precache_model can only be done in spawn functions\n", filename);
+                                               return 0;
+                                       }
+                               }
+                               else
+                               {
+                                       // able to precache during game
+                                       if (precachemode == 1)
+                                               Con_Printf("SV_ModelIndex(\"%s\"): not precached (fix your code), precaching anyway\n", filename);
+                                       strlcpy(sv.model_precache[i], filename, sizeof(sv.model_precache[i]));
+                                       sv.models[i] = Mod_ForName (sv.model_precache[i], true, false, false);
+                                       if (sv.state != ss_loading)
+                                       {
+                                               MSG_WriteByte(&sv.reliable_datagram, svc_precache);
+                                               MSG_WriteShort(&sv.reliable_datagram, i);
+                                               MSG_WriteString(&sv.reliable_datagram, filename);
+                                       }
+                                       return i;
+                               }
+                       }
+                       Con_Printf("SV_ModelIndex(\"%s\"): not precached\n", filename);
+                       return 0;
+               }
+               if (!strcmp(sv.model_precache[i], filename))
                        return i;
-       if (i==MAX_MODELS || !sv.model_precache[i])
+       }
+       if (precachemode)
+               Con_Printf("SV_ModelIndex(\"%s\"): i == MAX_MODELS\n", filename);
+       else
+               Con_Printf("SV_ModelIndex(\"%s\"): not precached\n", filename);
+       return 0;
+}
+
+/*
+================
+SV_SoundIndex
+
+================
+*/
+int SV_SoundIndex(char *s, int precachemode)
+{
+       int i, limit = (sv.protocol == PROTOCOL_QUAKE ? 256 : MAX_SOUNDS);
+       char filename[MAX_QPATH];
+       if (!s || !*s)
+               return 0;
+       strlcpy(filename, s, sizeof(filename));
+       for (i = 1;i < limit;i++)
        {
-               Con_DPrintf ("SV_ModelIndex: model %s not precached", name);
-               return -1;
+               if (!sv.sound_precache[i][0])
+               {
+                       if (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4 || sv.protocol == PROTOCOL_DARKPLACES5)
+                       {
+                               // not able to precache during game
+                               if (precachemode == 2 && sv.state != ss_loading)
+                               {
+                                       Con_Printf("SV_SoundIndex(\"%s\"): precache_sound can only be done in spawn functions\n", filename);
+                                       return 0;
+                               }
+                       }
+                       else
+                       {
+                               // able to precache during game
+                               if (precachemode)
+                               {
+                                       if (precachemode == 1)
+                                               Con_Printf("SV_SoundIndex(\"%s\"): not precached (fix your code), precaching anyway\n", filename);
+                                       strlcpy(sv.sound_precache[i], filename, sizeof(sv.sound_precache[i]));
+                                       MSG_WriteByte(&sv.reliable_datagram, svc_precache);
+                                       MSG_WriteShort(&sv.reliable_datagram, i + 32768);
+                                       MSG_WriteString(&sv.reliable_datagram, filename);
+                                       return i;
+                               }
+                       }
+                       Con_Printf("SV_SoundIndex(\"%s\"): not precached\n", filename);
+                       return 0;
+               }
+               if (!strcmp(sv.sound_precache[i], filename))
+                       return i;
        }
-       return i;
+       if (precachemode)
+               Con_Printf("SV_SoundIndex(\"%s\"): i == MAX_SOUNDS\n", filename);
+       else
+               Con_Printf("SV_SoundIndex(\"%s\"): not precached\n", filename);
+       return 0;
 }
 
 /*
@@ -1374,10 +1438,7 @@ void SV_CreateBaseline (void)
                if (entnum > 0 && entnum <= svs.maxclients)
                {
                        svent->e->baseline.colormap = entnum;
-                       i = SV_ModelIndex("progs/player.mdl");
-                       if (i < 0)
-                               i = 0;
-                       svent->e->baseline.modelindex = i;
+                       svent->e->baseline.modelindex = SV_ModelIndex("progs/player.mdl", 1);
                }
                else
                {
@@ -1576,47 +1637,30 @@ void SV_SpawnServer (const char *server)
 
        strlcpy (sv.name, server, sizeof (sv.name));
 
-       // FIXME: cvar
+       sv.netquakecompatible = false;
        if (!strcasecmp(sv_protocolname.string, "QUAKE"))
        {
                sv.protocol = PROTOCOL_QUAKE;
                sv.netquakecompatible = true;
        }
        else if (!strcasecmp(sv_protocolname.string, "QUAKEDP"))
-       {
                sv.protocol = PROTOCOL_QUAKE;
-               sv.netquakecompatible = false;
-       }
        else if (!strcasecmp(sv_protocolname.string, "DARKPLACES1"))
-       {
                sv.protocol = PROTOCOL_DARKPLACES1;
-               sv.netquakecompatible = false;
-       }
        else if (!strcasecmp(sv_protocolname.string, "DARKPLACES2"))
-       {
                sv.protocol = PROTOCOL_DARKPLACES2;
-               sv.netquakecompatible = false;
-       }
        else if (!strcasecmp(sv_protocolname.string, "DARKPLACES3"))
-       {
                sv.protocol = PROTOCOL_DARKPLACES3;
-               sv.netquakecompatible = false;
-       }
        else if (!strcasecmp(sv_protocolname.string, "DARKPLACES4"))
-       {
                sv.protocol = PROTOCOL_DARKPLACES4;
-               sv.netquakecompatible = false;
-       }
        else if (!strcasecmp(sv_protocolname.string, "DARKPLACES5"))
-       {
                sv.protocol = PROTOCOL_DARKPLACES5;
-               sv.netquakecompatible = false;
-       }
+       else if (!strcasecmp(sv_protocolname.string, "DARKPLACES6"))
+               sv.protocol = PROTOCOL_DARKPLACES6;
        else
        {
-               sv.protocol = PROTOCOL_DARKPLACES5;
-               sv.netquakecompatible = false;
-               Con_Printf("Unknown sv_protocolname \"%s\", valid values are QUAKE, QUAKEDP, DARKPLACES1, DARKPLACES2, DARKPLACES3, DARKPLACES4, DARKPLACES5, falling back to DARKPLACES5 protocol\n", sv_protocolname.string);
+               sv.protocol = PROTOCOL_DARKPLACES6;
+               Con_Printf("Unknown sv_protocolname \"%s\", valid values are QUAKE, QUAKEDP, DARKPLACES1, DARKPLACES2, DARKPLACES3, DARKPLACES4, DARKPLACES5, DARKPLACES6, falling back to DARKPLACES6 protocol\n", sv_protocolname.string);
        }
 
 // load progs to get entity field count
@@ -1681,14 +1725,14 @@ void SV_SpawnServer (const char *server)
 //
        SV_ClearWorld ();
 
-       sv.sound_precache[0] = "";
+       strlcpy(sv.sound_precache[0], "", sizeof(sv.sound_precache[0]));
 
-       sv.model_precache[0] = "";
-       sv.model_precache[1] = sv.modelname;
+       strlcpy(sv.model_precache[0], "", sizeof(sv.model_precache[0]));
+       strlcpy(sv.model_precache[1], sv.modelname, sizeof(sv.model_precache[1]));
        for (i = 1;i < sv.worldmodel->brush.numsubmodels;i++)
        {
-               sv.model_precache[i+1] = localmodels[i];
-               sv.models[i+1] = Mod_ForName (localmodels[i], false, false, false);
+               snprintf(sv.model_precache[i+1], sizeof(sv.model_precache[i+1]), "*%i", i);
+               sv.models[i+1] = Mod_ForName (sv.model_precache[i+1], false, false, false);
        }
 
 //
index a2057f0..77102a6 100644 (file)
--- a/sv_user.c
+++ b/sv_user.c
@@ -630,7 +630,7 @@ void SV_ReadClientMove (usercmd_t *move)
                        angle[i] = MSG_ReadAngle8i();
                else if (sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3)
                        angle[i] = MSG_ReadAngle32f();
-               else if (sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES4 || sv.protocol == PROTOCOL_DARKPLACES5)
+               else if (sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES4 || sv.protocol == PROTOCOL_DARKPLACES5 || sv.protocol == PROTOCOL_DARKPLACES6)
                        angle[i] = MSG_ReadAngle16i();
                if (msg_badread) Con_Printf("SV_ReadClientMessage: badread at %s:%i\n", __FILE__, __LINE__);
        }
@@ -653,7 +653,10 @@ void SV_ReadClientMove (usercmd_t *move)
        }
 
        // read buttons
-       bits = MSG_ReadByte ();
+       if (sv.protocol == PROTOCOL_DARKPLACES6)
+               bits = MSG_ReadLong ();
+       else
+               bits = MSG_ReadByte ();
        if (msg_badread) Con_Printf("SV_ReadClientMessage: badread at %s:%i\n", __FILE__, __LINE__);
        host_client->edict->v->button0 = bits & 1;
        host_client->edict->v->button2 = (bits & 2)>>1;
@@ -664,11 +667,50 @@ void SV_ReadClientMove (usercmd_t *move)
        if ((val = GETEDICTFIELDVALUE(host_client->edict, eval_button6))) val->_float = ((bits >> 5) & 1);
        if ((val = GETEDICTFIELDVALUE(host_client->edict, eval_button7))) val->_float = ((bits >> 6) & 1);
        if ((val = GETEDICTFIELDVALUE(host_client->edict, eval_button8))) val->_float = ((bits >> 7) & 1);
+       if ((val = GETEDICTFIELDVALUE(host_client->edict, eval_buttonuse))) val->_float = ((bits >> 8) & 1);
+       if ((val = GETEDICTFIELDVALUE(host_client->edict, eval_buttonchat))) val->_float = ((bits >> 9) & 1);
+       if ((val = GETEDICTFIELDVALUE(host_client->edict, eval_cursor_active))) val->_float = ((bits >> 10) & 1);
 
        i = MSG_ReadByte ();
        if (msg_badread) Con_Printf("SV_ReadClientMessage: badread at %s:%i\n", __FILE__, __LINE__);
        if (i)
                host_client->edict->v->impulse = i;
+
+       // PRYDON_CLIENTCURSOR
+       if (sv.protocol == PROTOCOL_DARKPLACES6)
+       {
+               // 30 bytes
+               move->cursor_screen[0] = MSG_ReadShort() * (1.0f / 32767.0f);
+               move->cursor_screen[1] = MSG_ReadShort() * (1.0f / 32767.0f);
+               move->cursor_start[0] = MSG_ReadFloat();
+               move->cursor_start[1] = MSG_ReadFloat();
+               move->cursor_start[2] = MSG_ReadFloat();
+               move->cursor_impact[0] = MSG_ReadFloat();
+               move->cursor_impact[1] = MSG_ReadFloat();
+               move->cursor_impact[2] = MSG_ReadFloat();
+               move->cursor_entitynumber = MSG_ReadShort();
+               if (msg_badread) Con_Printf("SV_ReadClientMessage: badread at %s:%i\n", __FILE__, __LINE__);
+       }
+       if ((val = GETEDICTFIELDVALUE(host_client->edict, eval_cursor_screen))) VectorCopy(move->cursor_screen, val->vector);
+       if ((val = GETEDICTFIELDVALUE(host_client->edict, eval_cursor_trace_start))) VectorCopy(move->cursor_start, val->vector);
+       if ((val = GETEDICTFIELDVALUE(host_client->edict, eval_cursor_trace_endpos))) VectorCopy(move->cursor_impact, val->vector);
+       if ((val = GETEDICTFIELDVALUE(host_client->edict, eval_cursor_trace_ent))) val->edict = EDICT_TO_PROG(EDICT_NUM(move->cursor_entitynumber));
+}
+
+void SV_FrameLost(int framenum)
+{
+       if (host_client->entitydatabase5)
+               EntityFrame5_LostFrame(host_client->entitydatabase5, framenum, host_client - svs.clients + 1);
+}
+
+void SV_FrameAck(int framenum)
+{
+       if (host_client->entitydatabase)
+               EntityFrame_AckFrame(host_client->entitydatabase, framenum);
+       else if (host_client->entitydatabase4)
+               EntityFrame4_AckFrame(host_client->entitydatabase4, framenum, true);
+       else if (host_client->entitydatabase5)
+               EntityFrame5_AckFrame(host_client->entitydatabase5, framenum);
 }
 
 /*
@@ -757,18 +799,20 @@ void SV_ReadClientMessage(void)
                        SV_ReadClientMove (&host_client->cmd);
                        break;
 
-               case clc_ackentities:
+               case clc_ackframe:
                        if (msg_badread) Con_Printf("SV_ReadClientMessage: badread at %s:%i\n", __FILE__, __LINE__);
                        num = MSG_ReadLong();
                        if (msg_badread) Con_Printf("SV_ReadClientMessage: badread at %s:%i\n", __FILE__, __LINE__);
                        if (developer_networkentities.integer >= 1)
-                               Con_Printf("recv clc_ackentities %i\n", num);
-                       if (host_client->entitydatabase)
-                               EntityFrame_AckFrame(host_client->entitydatabase, num);
-                       else if (host_client->entitydatabase4)
-                               EntityFrame4_AckFrame(host_client->entitydatabase4, num, true);
-                       else if (host_client->entitydatabase5)
-                               EntityFrame5_AckFrame(host_client->entitydatabase5, num, host_client - svs.clients + 1);
+                               Con_Printf("recv clc_ackframe %i\n", num);
+                       if (host_client->latestframenum < num)
+                       {
+                               int i;
+                               for (i = host_client->latestframenum + 1;i < num;i++)
+                                       SV_FrameLost(i);
+                               SV_FrameAck(num);
+                               host_client->latestframenum = num;
+                       }
                        break;
                }
        }
index a96e3f9..46ccdb2 100644 (file)
--- a/vid_glx.c
+++ b/vid_glx.c
@@ -889,10 +889,10 @@ void IN_Commands (void)
 {
 }
 
-void IN_Move (usercmd_t *cmd)
+void IN_Move (void)
 {
        if (mouse_avail)
-               IN_Mouse(cmd, mouse_x, mouse_y);
+               IN_Mouse(mouse_x, mouse_y);
        mouse_x = 0;
        mouse_y = 0;
 }
index 32003e0..7daea1e 100644 (file)
@@ -102,6 +102,6 @@ void IN_Commands(void)
 {
 }
 
-void IN_Move(usercmd_t *cmd)
+void IN_Move(void)
 {
 }
index 3acdc47..4dc4d13 100644 (file)
--- a/vid_sdl.c
+++ b/vid_sdl.c
@@ -218,22 +218,22 @@ void IN_Commands (void)
 {
 }
 
-static void IN_MouseMove (usercmd_t *cmd)
+static void IN_MouseMove (void)
 {
        int x, y;
 
        if( !vid_usingmouse ) {
-               IN_Mouse( cmd, 0, 0 );
+               IN_Mouse( 0, 0 );
                return;
        }
 
        SDL_GetRelativeMouseState( &x, &y );
-       IN_Mouse( cmd, x, y );
+       IN_Mouse( x, y );
 }
 
-void IN_Move( usercmd_t *cmd )
+void IN_Move( void )
 {
-       IN_MouseMove( cmd );    
+       IN_MouseMove(); 
 }
 
 static void IN_Init( void )
index aecaaa8..76cc73d 100644 (file)
@@ -732,23 +732,23 @@ void IN_PostMove(void)
 IN_DoMove
 ===========
 */
-void IN_ProcessMove(usercmd_t *cmd)
+void IN_ProcessMove(void)
 {
        // get basic movement from keyboard
-       CL_BaseMove(cmd);
+       CL_BaseMove();
 
        // OS independent code
        IN_PreMove();
 
        // allow mice or other external controllers to add to the move
-       IN_Move(cmd);
+       IN_Move();
 
        // OS independent code
        IN_PostMove();
 }
 
 
-void IN_Mouse(usercmd_t *cmd, float mx, float my)
+void IN_Mouse(float mx, float my)
 {
        int mouselook = (in_mlook.state & 1) || freelook.integer;
        float mouse_x, mouse_y;
@@ -776,13 +776,21 @@ void IN_Mouse(usercmd_t *cmd, float mx, float my)
        if(!in_client_mouse)
                return;
 
+       if (cl_prydoncursor.integer)
+       {
+               cl.cmd.cursor_screen[0] += mouse_x / vid.realwidth;
+               cl.cmd.cursor_screen[1] += mouse_y / vid.realheight;
+               V_StopPitchDrift();
+               return;
+       }
+
        // LordHavoc: viewzoom affects mouse sensitivity for sniping
        mouse_x *= sensitivity.value * cl.viewzoom;
        mouse_y *= sensitivity.value * cl.viewzoom;
 
        // Add mouse X/Y movement to cmd
        if ((in_strafe.state & 1) || (lookstrafe.integer && mouselook))
-               cmd->sidemove += m_side.value * mouse_x;
+               cl.cmd.sidemove += m_side.value * mouse_x;
        else
                cl.viewangles[YAW] -= m_yaw.value * mouse_x;
 
@@ -794,9 +802,9 @@ void IN_Mouse(usercmd_t *cmd, float mx, float my)
        else
        {
                if ((in_strafe.state & 1) && noclip_anglehack)
-                       cmd->upmove -= m_forward.value * mouse_y;
+                       cl.cmd.upmove -= m_forward.value * mouse_y;
                else
-                       cmd->forwardmove -= m_forward.value * mouse_y;
+                       cl.cmd.forwardmove -= m_forward.value * mouse_y;
        }
 }
 
index 4649e67..c6e0ff7 100644 (file)
--- a/vid_wgl.c
+++ b/vid_wgl.c
@@ -259,7 +259,7 @@ static DIDATAFORMAT df = {
 // forward-referenced functions
 void IN_StartupJoystick (void);
 void Joy_AdvancedUpdate_f (void);
-void IN_JoyMove (usercmd_t *cmd);
+void IN_JoyMove (void);
 void IN_StartupMouse (void);
 
 /*
@@ -1344,7 +1344,7 @@ void IN_MouseEvent (int mstate)
 IN_MouseMove
 ===========
 */
-void IN_MouseMove (usercmd_t *cmd)
+void IN_MouseMove (void)
 {
        int                                     i, mx, my;
        DIDEVICEOBJECTDATA      od;
@@ -1355,7 +1355,7 @@ void IN_MouseMove (usercmd_t *cmd)
        {
                GetCursorPos (&current_pos);
                //ui_mouseupdate(current_pos.x - window_x, current_pos.y - window_y);
-               IN_Mouse( cmd, 0, 0 );
+               IN_Mouse( 0, 0 );
                return;
        }
 
@@ -1442,7 +1442,7 @@ void IN_MouseMove (usercmd_t *cmd)
                my = current_pos.y - window_center_y;
        }
 
-       IN_Mouse(cmd, mx, my);
+       IN_Mouse(mx, my);
 
        // if the mouse has moved, force it to the center, so there's room to move
        if (!dinput && (mx || my))
@@ -1455,12 +1455,12 @@ void IN_MouseMove (usercmd_t *cmd)
 IN_Move
 ===========
 */
-void IN_Move (usercmd_t *cmd)
+void IN_Move (void)
 {
        if (vid_activewindow && !vid_hidden)
        {
-               IN_MouseMove (cmd);
-               IN_JoyMove (cmd);
+               IN_MouseMove ();
+               IN_JoyMove ();
        }
 }
 
@@ -1753,7 +1753,7 @@ qboolean IN_ReadJoystick (void)
 IN_JoyMove
 ===========
 */
-void IN_JoyMove (usercmd_t *cmd)
+void IN_JoyMove (void)
 {
        float   speed, aspeed;
        float   fAxisValue, fTemp;
@@ -1848,7 +1848,7 @@ void IN_JoyMove (usercmd_t *cmd)
                                // user wants forward control to be forward control
                                if (fabs(fAxisValue) > joy_forwardthreshold.value)
                                {
-                                       cmd->forwardmove += (fAxisValue * joy_forwardsensitivity.value) * speed * cl_forwardspeed.value;
+                                       cl.cmd.forwardmove += (fAxisValue * joy_forwardsensitivity.value) * speed * cl_forwardspeed.value;
                                }
                        }
                        break;
@@ -1856,7 +1856,7 @@ void IN_JoyMove (usercmd_t *cmd)
                case AxisSide:
                        if (fabs(fAxisValue) > joy_sidethreshold.value)
                        {
-                               cmd->sidemove += (fAxisValue * joy_sidesensitivity.value) * speed * cl_sidespeed.value;
+                               cl.cmd.sidemove += (fAxisValue * joy_sidesensitivity.value) * speed * cl_sidespeed.value;
                        }
                        break;
 
@@ -1866,7 +1866,7 @@ void IN_JoyMove (usercmd_t *cmd)
                                // user wants turn control to become side control
                                if (fabs(fAxisValue) > joy_sidethreshold.value)
                                {
-                                       cmd->sidemove -= (fAxisValue * joy_sidesensitivity.value) * speed * cl_sidespeed.value;
+                                       cl.cmd.sidemove -= (fAxisValue * joy_sidesensitivity.value) * speed * cl_sidespeed.value;
                                }
                        }
                        else
diff --git a/view.c b/view.c
index 060464a..de0bf4d 100644 (file)
--- a/view.c
+++ b/view.c
@@ -397,7 +397,7 @@ void V_CalcRefdef (void)
                                }
                                // origin
                                VectorAdd(vieworg, cl.punchvector, vieworg);
-                               vieworg[2] += cl.viewheight;
+                               vieworg[2] += cl.stats[STAT_VIEWHEIGHT];
                                if (cl.stats[STAT_HEALTH] > 0 && cl_bob.value && cl_bobcycle.value)
                                {
                                        double bob, cycle;
@@ -482,28 +482,28 @@ void V_CalcViewBlend(void)
 
                if (gamemode != GAME_TRANSFUSION)
                {
-                       if (cl.items & IT_QUAD)
+                       if (cl.stats[STAT_ITEMS] & IT_QUAD)
                        {
                                cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 0;
                                cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 0;
                                cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 255;
                                cl.cshifts[CSHIFT_POWERUP].percent = 30;
                        }
-                       else if (cl.items & IT_SUIT)
+                       else if (cl.stats[STAT_ITEMS] & IT_SUIT)
                        {
                                cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 0;
                                cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 255;
                                cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 0;
                                cl.cshifts[CSHIFT_POWERUP].percent = 20;
                        }
-                       else if (cl.items & IT_INVISIBILITY)
+                       else if (cl.stats[STAT_ITEMS] & IT_INVISIBILITY)
                        {
                                cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 100;
                                cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 100;
                                cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 100;
                                cl.cshifts[CSHIFT_POWERUP].percent = 100;
                        }
-                       else if (cl.items & IT_INVULNERABILITY)
+                       else if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
                        {
                                cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 255;
                                cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 255;