]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - sv_main.c
Remove the CONFIG_CD macro, and enable faketracks unconditionally.
[xonotic/darkplaces.git] / sv_main.c
index b6e3b3f1fc6b8485259acf81c14f0be32f8c90ec..0b81820b51e708b395756505ee4d600dc79b5e59 100644 (file)
--- a/sv_main.c
+++ b/sv_main.c
@@ -81,6 +81,8 @@ cvar_t sv_cullentities_trace = {0, "sv_cullentities_trace", "0", "somewhat slow
 cvar_t sv_cullentities_trace_delay = {0, "sv_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
 cvar_t sv_cullentities_trace_delay_players = {0, "sv_cullentities_trace_delay_players", "0.2", "number of seconds until the entity gets actually culled if it is a player entity"};
 cvar_t sv_cullentities_trace_enlarge = {0, "sv_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
+cvar_t sv_cullentities_trace_expand = { 0, "sv_cullentities_trace_expand", "0", "box is expanded by this many units for entity culling" };
+cvar_t sv_cullentities_trace_eyejitter = {0, "sv_cullentities_trace_eyejitter", "16", "jitter the eye by this much for each trace"};
 cvar_t sv_cullentities_trace_prediction = {0, "sv_cullentities_trace_prediction", "1", "also trace from the predicted player position"};
 cvar_t sv_cullentities_trace_prediction_time = {0, "sv_cullentities_trace_prediction_time", "0.2", "how many seconds of prediction to use"};
 cvar_t sv_cullentities_trace_entityocclusion = {0, "sv_cullentities_trace_entityocclusion", "0", "also check if doors and other bsp models are in the way"};
@@ -493,6 +495,8 @@ void SV_Init (void)
        Cvar_RegisterVariable (&sv_cullentities_trace_delay);
        Cvar_RegisterVariable (&sv_cullentities_trace_delay_players);
        Cvar_RegisterVariable (&sv_cullentities_trace_enlarge);
+       Cvar_RegisterVariable (&sv_cullentities_trace_expand);
+       Cvar_RegisterVariable (&sv_cullentities_trace_eyejitter);
        Cvar_RegisterVariable (&sv_cullentities_trace_entityocclusion);
        Cvar_RegisterVariable (&sv_cullentities_trace_prediction);
        Cvar_RegisterVariable (&sv_cullentities_trace_prediction_time);
@@ -710,7 +714,7 @@ Larger attenuations will drop off.  (max 4 attenuation)
 
 ==================
 */
-void SV_StartSound (prvm_edict_t *entity, int channel, const char *sample, int volume, float attenuation, qboolean reliable, float speed)
+void SV_StartSound (prvm_edict_t *entity, int channel, const char *sample, int nvolume, float attenuation, qboolean reliable, float speed)
 {
        prvm_prog_t *prog = SVVM_prog;
        sizebuf_t *dest;
@@ -718,9 +722,9 @@ void SV_StartSound (prvm_edict_t *entity, int channel, const char *sample, int v
 
        dest = (reliable ? &sv.reliable_datagram : &sv.datagram);
 
-       if (volume < 0 || volume > 255)
+       if (nvolume < 0 || nvolume > 255)
        {
-               Con_Printf ("SV_StartSound: volume = %i\n", volume);
+               Con_Printf ("SV_StartSound: volume = %i\n", nvolume);
                return;
        }
 
@@ -750,7 +754,7 @@ void SV_StartSound (prvm_edict_t *entity, int channel, const char *sample, int v
 
        speed4000 = (int)floor(speed * 4000.0f + 0.5f);
        field_mask = 0;
-       if (volume != DEFAULT_SOUND_PACKET_VOLUME)
+       if (nvolume != DEFAULT_SOUND_PACKET_VOLUME)
                field_mask |= SND_VOLUME;
        if (attenuation != DEFAULT_SOUND_PACKET_ATTENUATION)
                field_mask |= SND_ATTENUATION;
@@ -765,7 +769,7 @@ void SV_StartSound (prvm_edict_t *entity, int channel, const char *sample, int v
        MSG_WriteByte (dest, svc_sound);
        MSG_WriteByte (dest, field_mask);
        if (field_mask & SND_VOLUME)
-               MSG_WriteByte (dest, volume);
+               MSG_WriteByte (dest, nvolume);
        if (field_mask & SND_ATTENUATION)
                MSG_WriteByte (dest, (int)(attenuation*64));
        if (field_mask & SND_SPEEDUSHORT4000)
@@ -802,13 +806,13 @@ function, therefore the check for it is omitted.
 
 ==================
 */
-void SV_StartPointSound (vec3_t origin, const char *sample, int volume, float attenuation, float speed)
+void SV_StartPointSound (vec3_t origin, const char *sample, int nvolume, float attenuation, float speed)
 {
        int sound_num, field_mask, i, speed4000;
 
-       if (volume < 0 || volume > 255)
+       if (nvolume < 0 || nvolume > 255)
        {
-               Con_Printf ("SV_StartPointSound: volume = %i\n", volume);
+               Con_Printf ("SV_StartPointSound: volume = %i\n", nvolume);
                return;
        }
 
@@ -828,7 +832,7 @@ void SV_StartPointSound (vec3_t origin, const char *sample, int volume, float at
 
        speed4000 = (int)(speed * 40.0f);
        field_mask = 0;
-       if (volume != DEFAULT_SOUND_PACKET_VOLUME)
+       if (nvolume != DEFAULT_SOUND_PACKET_VOLUME)
                field_mask |= SND_VOLUME;
        if (attenuation != DEFAULT_SOUND_PACKET_ATTENUATION)
                field_mask |= SND_ATTENUATION;
@@ -841,7 +845,7 @@ void SV_StartPointSound (vec3_t origin, const char *sample, int volume, float at
        MSG_WriteByte (&sv.datagram, svc_sound);
        MSG_WriteByte (&sv.datagram, field_mask);
        if (field_mask & SND_VOLUME)
-               MSG_WriteByte (&sv.datagram, volume);
+               MSG_WriteByte (&sv.datagram, nvolume);
        if (field_mask & SND_ATTENUATION)
                MSG_WriteByte (&sv.datagram, (int)(attenuation*64));
        if (field_mask & SND_SPEEDUSHORT4000)
@@ -939,13 +943,13 @@ void SV_SendServerinfo (client_t *client)
        {
                char demofile[MAX_OSPATH];
                char ipaddress[MAX_QPATH];
-               size_t i;
+               size_t j;
 
                // start a new demo file
                LHNETADDRESS_ToString(&(client->netconnection->peeraddress), ipaddress, sizeof(ipaddress), true);
-               for(i = 0; ipaddress[i]; ++i)
-                       if(!isalnum(ipaddress[i]))
-                               ipaddress[i] = '-';
+               for(j = 0; ipaddress[j]; ++j)
+                       if(!isalnum(ipaddress[j]))
+                               ipaddress[j] = '-';
                dpsnprintf (demofile, sizeof(demofile), "%s_%s_%d_%s.dem", Sys_TimeString (sv_autodemo_perclient_nameformat.string), sv.worldbasename, PRVM_NUM_FOR_EDICT(client->edict), ipaddress);
 
                SV_StartDemoRecording(client, demofile, -1);
@@ -964,14 +968,14 @@ void SV_SendServerinfo (client_t *client)
 
                if(client->sv_demo_file != NULL)
                {
-                       int i;
+                       int k;
                        static char buf[NET_MAXMESSAGE];
                        sizebuf_t sb;
 
                        sb.data = (unsigned char *) buf;
                        sb.maxsize = sizeof(buf);
-                       i = 0;
-                       while(MakeDownloadPacket(sv.csqc_progname, svs.csqc_progdata, sv.csqc_progsize, sv.csqc_progcrc, i++, &sb, sv.protocol))
+                       k = 0;
+                       while(MakeDownloadPacket(sv.csqc_progname, svs.csqc_progdata, sv.csqc_progsize, sv.csqc_progcrc, k++, &sb, sv.protocol))
                                SV_WriteDemoMessage(client, &sb, false);
                }
 
@@ -1485,12 +1489,14 @@ static void SV_PrepareEntitiesForSending(void)
 
 #define MAX_LINEOFSIGHTTRACES 64
 
-qboolean SV_CanSeeBox(int numtraces, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
+qboolean SV_CanSeeBox(int numtraces, vec_t eyejitter, vec_t enlarge, vec_t entboxexpand, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
 {
        prvm_prog_t *prog = SVVM_prog;
        float pitchsign;
        float alpha;
        float starttransformed[3], endtransformed[3];
+       float boxminstransformed[3], boxmaxstransformed[3];
+       float localboxcenter[3], localboxextents[3], localboxmins[3], localboxmaxs[3];
        int blocked = 0;
        int traceindex;
        int originalnumtouchedicts;
@@ -1500,27 +1506,35 @@ qboolean SV_CanSeeBox(int numtraces, vec_t enlarge, vec3_t eye, vec3_t entboxmin
        dp_model_t *model;
        prvm_edict_t *touch;
        static prvm_edict_t *touchedicts[MAX_EDICTS];
+       vec3_t eyemins, eyemaxs, start;
        vec3_t boxmins, boxmaxs;
        vec3_t clipboxmins, clipboxmaxs;
        vec3_t endpoints[MAX_LINEOFSIGHTTRACES];
 
        numtraces = min(numtraces, MAX_LINEOFSIGHTTRACES);
 
+       // jitter the eye location within this box
+       eyemins[0] = eye[0] - eyejitter;
+       eyemaxs[0] = eye[0] + eyejitter;
+       eyemins[1] = eye[1] - eyejitter;
+       eyemaxs[1] = eye[1] + eyejitter;
+       eyemins[2] = eye[2] - eyejitter;
+       eyemaxs[2] = eye[2] + eyejitter;
        // expand the box a little
-       boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
-       boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
-       boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
-       boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
-       boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
-       boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
+       boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0] - entboxexpand;
+       boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0] + entboxexpand;
+       boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1] - entboxexpand;
+       boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1] + entboxexpand;
+       boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2] - entboxexpand;
+       boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2] + entboxexpand;
 
        VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, endpoints[0]);
        for (traceindex = 1;traceindex < numtraces;traceindex++)
                VectorSet(endpoints[traceindex], lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
 
        // calculate sweep box for the entire swarm of traces
-       VectorCopy(eye, clipboxmins);
-       VectorCopy(eye, clipboxmaxs);
+       VectorCopy(eyemins, clipboxmins);
+       VectorCopy(eyemaxs, clipboxmaxs);
        for (traceindex = 0;traceindex < numtraces;traceindex++)
        {
                clipboxmins[0] = min(clipboxmins[0], endpoints[traceindex][0]);
@@ -1566,9 +1580,10 @@ qboolean SV_CanSeeBox(int numtraces, vec_t enlarge, vec3_t eye, vec3_t entboxmin
 
        for (traceindex = 0;traceindex < numtraces;traceindex++)
        {
+               VectorSet(start, lhrandom(eyemins[0], eyemaxs[0]), lhrandom(eyemins[1], eyemaxs[1]), lhrandom(eyemins[2], eyemaxs[2]));
                // check world occlusion
                if (sv.worldmodel && sv.worldmodel->brush.TraceLineOfSight)
-                       if (!sv.worldmodel->brush.TraceLineOfSight(sv.worldmodel, eye, endpoints[traceindex]))
+                       if (!sv.worldmodel->brush.TraceLineOfSight(sv.worldmodel, start, endpoints[traceindex], boxmins, boxmaxs))
                                continue;
                for (touchindex = 0;touchindex < numtouchedicts;touchindex++)
                {
@@ -1581,9 +1596,22 @@ qboolean SV_CanSeeBox(int numtraces, vec_t enlarge, vec3_t eye, vec3_t entboxmin
                                Matrix4x4_CreateFromQuakeEntity(&matrix, PRVM_serveredictvector(touch, origin)[0], PRVM_serveredictvector(touch, origin)[1], PRVM_serveredictvector(touch, origin)[2], pitchsign * PRVM_serveredictvector(touch, angles)[0], PRVM_serveredictvector(touch, angles)[1], PRVM_serveredictvector(touch, angles)[2], 1);
                                Matrix4x4_Invert_Simple(&imatrix, &matrix);
                                // see if the ray hits this entity
-                               Matrix4x4_Transform(&imatrix, eye, starttransformed);
+                               Matrix4x4_Transform(&imatrix, start, starttransformed);
                                Matrix4x4_Transform(&imatrix, endpoints[traceindex], endtransformed);
-                               if (!model->brush.TraceLineOfSight(model, starttransformed, endtransformed))
+                               Matrix4x4_Transform(&imatrix, boxmins, boxminstransformed);
+                               Matrix4x4_Transform(&imatrix, boxmaxs, boxmaxstransformed);
+                               // transform the AABB to local space
+                               VectorMAM(0.5f, boxminstransformed, 0.5f, boxmaxstransformed, localboxcenter);
+                               localboxextents[0] = fabs(boxmaxstransformed[0] - localboxcenter[0]);
+                               localboxextents[1] = fabs(boxmaxstransformed[1] - localboxcenter[1]);
+                               localboxextents[2] = fabs(boxmaxstransformed[2] - localboxcenter[2]);
+                               localboxmins[0] = localboxcenter[0] - localboxextents[0];
+                               localboxmins[1] = localboxcenter[1] - localboxextents[1];
+                               localboxmins[2] = localboxcenter[2] - localboxextents[2];
+                               localboxmaxs[0] = localboxcenter[0] + localboxextents[0];
+                               localboxmaxs[1] = localboxcenter[1] + localboxextents[1];
+                               localboxmaxs[2] = localboxcenter[2] + localboxextents[2];
+                               if (!model->brush.TraceLineOfSight(model, starttransformed, endtransformed, localboxmins, localboxmaxs))
                                {
                                        blocked++;
                                        break;
@@ -1703,7 +1731,7 @@ static void SV_MarkWriteEntityStateToClient(entity_state_t *s)
                                {
                                        int eyeindex;
                                        for (eyeindex = 0;eyeindex < sv.writeentitiestoclient_numeyes;eyeindex++)
-                                               if(SV_CanSeeBox(samples, enlarge, sv.writeentitiestoclient_eyes[eyeindex], ed->priv.server->cullmins, ed->priv.server->cullmaxs))
+                                               if(SV_CanSeeBox(samples, sv_cullentities_trace_eyejitter.value, enlarge, sv_cullentities_trace_expand.value, sv.writeentitiestoclient_eyes[eyeindex], ed->priv.server->cullmins, ed->priv.server->cullmaxs))
                                                        break;
                                        if(eyeindex < sv.writeentitiestoclient_numeyes)
                                                svs.clients[sv.writeentitiestoclient_clientnumber].visibletime[s->number] =
@@ -1786,7 +1814,7 @@ static void SV_AddCameraEyes(void)
                for(k = 0; k < sv.writeentitiestoclient_numeyes; ++k)
                if(eye_levels[k] <= MAX_EYE_RECURSION)
                {
-                       if(SV_CanSeeBox(sv_cullentities_trace_samples.integer, sv_cullentities_trace_enlarge.value, sv.writeentitiestoclient_eyes[k], mi, ma))
+                       if(SV_CanSeeBox(sv_cullentities_trace_samples.integer, sv_cullentities_trace_eyejitter.value, sv_cullentities_trace_enlarge.value, sv_cullentities_trace_expand.value, sv.writeentitiestoclient_eyes[k], mi, ma))
                        {
                                eye_levels[sv.writeentitiestoclient_numeyes] = eye_levels[k] + 1;
                                VectorCopy(camera_origins[j], sv.writeentitiestoclient_eyes[sv.writeentitiestoclient_numeyes]);
@@ -1847,7 +1875,7 @@ static void SV_WriteEntitiesToClient(client_t *client, prvm_edict_t *clent, size
                vec_t predtime = bound(0, host_client->ping, sv_cullentities_trace_prediction_time.value);
                vec3_t predeye;
                VectorMA(eye, predtime, PRVM_serveredictvector(camera, velocity), predeye);
-               if (SV_CanSeeBox(1, 0, eye, predeye, predeye))
+               if (SV_CanSeeBox(1, 0, 0, 0, eye, predeye, predeye))
                {
                        VectorCopy(predeye, sv.writeentitiestoclient_eyes[sv.writeentitiestoclient_numeyes]);
                        sv.writeentitiestoclient_numeyes++;
@@ -3500,6 +3528,9 @@ void SV_SpawnServer (const char *server)
                SV_Physics ();
        }
 
+       // Once all init frames have been run, we consider svqc code fully initialized.
+       prog->inittime = realtime;
+
        if (cls.state == ca_dedicated)
                Mod_PurgeUnused();
 
@@ -3882,7 +3913,7 @@ static void SV_VM_Setup(void)
 //             PRVM_ED_FindGlobalOffset_FromStruct(globalvars_t, SetChangeParms);
        }
        else
-               Con_DPrintf("%s: %s system vars have been modified (CRC %i != engine %i), will not load in other engines", prog->name, sv_progs.string, prog->progs_crc, PROGHEADER_CRC);
+               Con_DPrintf("%s: %s system vars have been modified (CRC %i != engine %i), will not load in other engines\n", prog->name, sv_progs.string, prog->progs_crc, PROGHEADER_CRC);
 
        // OP_STATE is always supported on server because we add fields/globals for it
        prog->flag |= PRVM_OP_STATE;