]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - sv_main.c
fix two crashes that divVerent found and fixed but didn't commit
[xonotic/darkplaces.git] / sv_main.c
index d8e232d1fc567e3d4bd8fa2a4fe4fdd1dd2e8396..0e19f3a08deda151f3d12422a0cf2308bcf1f732 100644 (file)
--- a/sv_main.c
+++ b/sv_main.c
@@ -120,6 +120,10 @@ cvar_t sv_gameplayfix_nostepmoveonsteepslopes = {0, "sv_gameplayfix_nostepmoveon
 cvar_t sv_gameplayfix_swiminbmodels = {0, "sv_gameplayfix_swiminbmodels", "1", "causes pointcontents (used to determine if you are in a liquid) to check bmodel entities as well as the world model, so you can swim around in (possibly moving) water bmodel entities"};
 cvar_t sv_gameplayfix_upwardvelocityclearsongroundflag = {0, "sv_gameplayfix_upwardvelocityclearsongroundflag", "1", "prevents monsters, items, and most other objects from being stuck to the floor when pushed around by damage, and other situations in mods"};
 cvar_t sv_gameplayfix_downtracesupportsongroundflag = {0, "sv_gameplayfix_downtracesupportsongroundflag", "1", "prevents very short moves from clearing onground (which may make the player stick to the floor at high netfps)"};
+cvar_t sv_gameplayfix_q1bsptracelinereportstexture = {0, "sv_gameplayfix_q1bsptracelinereportstexture", "1", "enables mods to get accurate trace_texture results on q1bsp by using a surface-hitting traceline implementation rather than the standard solidbsp method, q3bsp always reports texture accurately"};
+cvar_t sv_gameplayfix_unstickplayers = {0, "sv_gameplayfix_unstickplayers", "1", "big hack to try and fix the rare case of MOVETYPE_WALK entities getting stuck in the world clipping hull."};
+cvar_t sv_gameplayfix_unstickentities = {0, "sv_gameplayfix_unstickentities", "1", "hack to check if entities are crossing world collision hull and try to move them to the right position"};
+cvar_t sv_gameplayfix_fixedcheckwatertransition = {0, "sv_gameplayfix_fixedcheckwatertransition", "1", "fix two very stupid bugs in SV_CheckWaterTransition when watertype is CONTENTS_EMPTY (the bugs causes waterlevel to be 1 on first frame, -1 on second frame - the fix makes it 0 on both frames)"};
 cvar_t sv_gravity = {CVAR_NOTIFY, "sv_gravity","800", "how fast you fall (512 = roughly earth gravity)"};
 cvar_t sv_idealpitchscale = {0, "sv_idealpitchscale","0.8", "how much to look up/down slopes and stairs when not using freelook"};
 cvar_t sv_jumpstep = {CVAR_NOTIFY, "sv_jumpstep", "0", "whether you can step up while jumping (sv_gameplayfix_stepwhilejumping must also be 1)"};
@@ -147,6 +151,7 @@ cvar_t sv_warsowbunny_topspeed = {0, "sv_warsowbunny_topspeed", "925", "soft spe
 cvar_t sv_warsowbunny_turnaccel = {0, "sv_warsowbunny_turnaccel", "0", "max sharpness of turns (also master switch for the sv_warsowbunny_* mode; set this to 9 to enable)"};
 cvar_t sv_warsowbunny_backtosideratio = {0, "sv_warsowbunny_backtosideratio", "0.8", "lower values make it easier to change direction without losing speed; the drawback is \"understeering\" in sharp turns"};
 cvar_t sv_onlycsqcnetworking = {0, "sv_onlycsqcnetworking", "0", "disables legacy entity networking code for higher performance (except on clients, which can still be legacy)"};
+cvar_t sv_areadebug = {0, "sv_areadebug", "0", "disables physics culling for debugging purposes (only for development)"};
 cvar_t sys_ticrate = {CVAR_SAVE, "sys_ticrate","0.0138889", "how long a server frame is in seconds, 0.05 is 20fps server rate, 0.1 is 10fps (can not be set higher than 0.1), 0 runs as many server frames as possible (makes games against bots a little smoother, overwhelms network players), 0.0138889 matches QuakeWorld physics"};
 cvar_t teamplay = {CVAR_NOTIFY, "teamplay","0", "teamplay mode, values depend on mod but typically 0 = no teams, 1 = no team damage no self damage, 2 = team damage and self damage, some mods support 3 = no team damage but can damage self"};
 cvar_t timelimit = {CVAR_NOTIFY, "timelimit","0", "ends level at this time (in minutes)"};
@@ -425,6 +430,7 @@ void SV_Init (void)
        extern cvar_t csqc_progname;    //[515]: csqc crc check and right csprogs name according to progs.dat
        extern cvar_t csqc_progcrc;
        extern cvar_t csqc_progsize;
+       extern cvar_t csqc_usedemoprogs;
 
        Cvar_RegisterVariable(&sv_worldmessage);
        Cvar_RegisterVariable(&sv_worldname);
@@ -434,6 +440,7 @@ void SV_Init (void)
        Cvar_RegisterVariable (&csqc_progname);
        Cvar_RegisterVariable (&csqc_progcrc);
        Cvar_RegisterVariable (&csqc_progsize);
+       Cvar_RegisterVariable (&csqc_usedemoprogs);
 
        Cmd_AddCommand("sv_saveentfile", SV_SaveEntFile_f, "save map entities to .ent file (to allow external editing)");
        Cmd_AddCommand("sv_areastats", SV_AreaStats_f, "prints statistics on entity culling during collision traces");
@@ -521,6 +528,10 @@ void SV_Init (void)
        Cvar_RegisterVariable (&sv_gameplayfix_swiminbmodels);
        Cvar_RegisterVariable (&sv_gameplayfix_upwardvelocityclearsongroundflag);
        Cvar_RegisterVariable (&sv_gameplayfix_downtracesupportsongroundflag);
+       Cvar_RegisterVariable (&sv_gameplayfix_q1bsptracelinereportstexture);
+       Cvar_RegisterVariable (&sv_gameplayfix_unstickplayers);
+       Cvar_RegisterVariable (&sv_gameplayfix_unstickentities);
+       Cvar_RegisterVariable (&sv_gameplayfix_fixedcheckwatertransition);
        Cvar_RegisterVariable (&sv_gravity);
        Cvar_RegisterVariable (&sv_idealpitchscale);
        Cvar_RegisterVariable (&sv_jumpstep);
@@ -548,6 +559,7 @@ void SV_Init (void)
        Cvar_RegisterVariable (&sv_warsowbunny_turnaccel);
        Cvar_RegisterVariable (&sv_warsowbunny_backtosideratio);
        Cvar_RegisterVariable (&sv_onlycsqcnetworking);
+       Cvar_RegisterVariable (&sv_areadebug);
        Cvar_RegisterVariable (&sys_ticrate);
        Cvar_RegisterVariable (&teamplay);
        Cvar_RegisterVariable (&timelimit);
@@ -691,9 +703,12 @@ Larger attenuations will drop off.  (max 4 attenuation)
 
 ==================
 */
-void SV_StartSound (prvm_edict_t *entity, int channel, const char *sample, int volume, float attenuation)
+void SV_StartSound (prvm_edict_t *entity, int channel, const char *sample, int volume, float attenuation, qboolean reliable, float speed)
 {
-       int sound_num, field_mask, i, ent;
+       sizebuf_t *dest;
+       int sound_num, field_mask, i, ent, speed4000;
+
+       dest = (reliable ? &sv.reliable_datagram : &sv.datagram);
 
        if (volume < 0 || volume > 255)
        {
@@ -707,12 +722,14 @@ void SV_StartSound (prvm_edict_t *entity, int channel, const char *sample, int v
                return;
        }
 
-       if (channel < 0 || channel > 7)
+       if (!IS_CHAN(channel))
        {
                Con_Printf ("SV_StartSound: channel = %i\n", channel);
                return;
        }
 
+       channel = CHAN_ENGINE2NET(channel);
+
        if (sv.datagram.cursize > MAX_PACKETFRAGMENT-21)
                return;
 
@@ -723,37 +740,45 @@ void SV_StartSound (prvm_edict_t *entity, int channel, const char *sample, int v
 
        ent = PRVM_NUM_FOR_EDICT(entity);
 
+       speed4000 = (int)floor(speed * 4000.0f + 0.5f);
        field_mask = 0;
        if (volume != DEFAULT_SOUND_PACKET_VOLUME)
                field_mask |= SND_VOLUME;
        if (attenuation != DEFAULT_SOUND_PACKET_ATTENUATION)
                field_mask |= SND_ATTENUATION;
-       if (ent >= 8192)
+       if (speed4000 && speed4000 != 4000)
+               field_mask |= SND_SPEEDUSHORT4000;
+       if (ent >= 8192 || channel < 0 || channel > 7)
                field_mask |= SND_LARGEENTITY;
-       if (sound_num >= 256 || channel >= 8)
+       if (sound_num >= 256)
                field_mask |= SND_LARGESOUND;
 
 // directed messages go only to the entity they are targeted on
-       MSG_WriteByte (&sv.datagram, svc_sound);
-       MSG_WriteByte (&sv.datagram, field_mask);
+       MSG_WriteByte (dest, svc_sound);
+       MSG_WriteByte (dest, field_mask);
        if (field_mask & SND_VOLUME)
-               MSG_WriteByte (&sv.datagram, volume);
+               MSG_WriteByte (dest, volume);
        if (field_mask & SND_ATTENUATION)
-               MSG_WriteByte (&sv.datagram, (int)(attenuation*64));
+               MSG_WriteByte (dest, (int)(attenuation*64));
+       if (field_mask & SND_SPEEDUSHORT4000)
+               MSG_WriteShort (dest, speed4000);
        if (field_mask & SND_LARGEENTITY)
        {
-               MSG_WriteShort (&sv.datagram, ent);
-               MSG_WriteByte (&sv.datagram, channel);
+               MSG_WriteShort (dest, ent);
+               MSG_WriteChar (dest, channel);
        }
        else
-               MSG_WriteShort (&sv.datagram, (ent<<3) | channel);
+               MSG_WriteShort (dest, (ent<<3) | channel);
        if ((field_mask & SND_LARGESOUND) || sv.protocol == PROTOCOL_NEHAHRABJP2)
-               MSG_WriteShort (&sv.datagram, sound_num);
+               MSG_WriteShort (dest, sound_num);
        else
-               MSG_WriteByte (&sv.datagram, sound_num);
+               MSG_WriteByte (dest, sound_num);
        for (i = 0;i < 3;i++)
-               MSG_WriteCoord (&sv.datagram, PRVM_serveredictvector(entity, origin)[i]+0.5*(PRVM_serveredictvector(entity, mins)[i]+PRVM_serveredictvector(entity, maxs)[i]), sv.protocol);
-       SV_FlushBroadcastMessages();
+               MSG_WriteCoord (dest, PRVM_serveredictvector(entity, origin)[i]+0.5*(PRVM_serveredictvector(entity, mins)[i]+PRVM_serveredictvector(entity, maxs)[i]), sv.protocol);
+
+       // TODO do we have to do anything here when dest is &sv.reliable_datagram?
+       if(!reliable)
+               SV_FlushBroadcastMessages();
 }
 
 /*
@@ -769,9 +794,9 @@ function, therefore the check for it is omitted.
 
 ==================
 */
-void SV_StartPointSound (vec3_t origin, const char *sample, int volume, float attenuation)
+void SV_StartPointSound (vec3_t origin, const char *sample, int volume, float attenuation, float speed)
 {
-       int sound_num, field_mask, i;
+       int sound_num, field_mask, i, speed4000;
 
        if (volume < 0 || volume > 255)
        {
@@ -793,6 +818,7 @@ void SV_StartPointSound (vec3_t origin, const char *sample, int volume, float at
        if (!sound_num)
                return;
 
+       speed4000 = (int)(speed * 40.0f);
        field_mask = 0;
        if (volume != DEFAULT_SOUND_PACKET_VOLUME)
                field_mask |= SND_VOLUME;
@@ -800,6 +826,8 @@ void SV_StartPointSound (vec3_t origin, const char *sample, int volume, float at
                field_mask |= SND_ATTENUATION;
        if (sound_num >= 256)
                field_mask |= SND_LARGESOUND;
+       if (speed4000 && speed4000 != 4000)
+               field_mask |= SND_SPEEDUSHORT4000;
 
 // directed messages go only to the entity they are targeted on
        MSG_WriteByte (&sv.datagram, svc_sound);
@@ -808,6 +836,8 @@ void SV_StartPointSound (vec3_t origin, const char *sample, int volume, float at
                MSG_WriteByte (&sv.datagram, volume);
        if (field_mask & SND_ATTENUATION)
                MSG_WriteByte (&sv.datagram, (int)(attenuation*64));
+       if (field_mask & SND_SPEEDUSHORT4000)
+               MSG_WriteShort (&sv.datagram, speed4000);
        // Always write entnum 0 for the world entity
        MSG_WriteShort (&sv.datagram, (0<<3) | 0);
        if (field_mask & SND_LARGESOUND)
@@ -1238,6 +1268,7 @@ static qboolean SV_PrepareEntityForSending (prvm_edict_t *ent, entity_state_t *c
        cs->tagentity = PRVM_serveredictedict(ent, tag_entity);
        cs->tagindex = (unsigned char)PRVM_serveredictfloat(ent, tag_index);
        cs->glowsize = glowsize;
+       cs->traileffectnum = PRVM_serveredictfloat(ent, traileffectnum);
 
        // don't need to init cs->colormod because the defaultstate did that for us
        //cs->colormod[0] = cs->colormod[1] = cs->colormod[2] = 32;
@@ -1484,7 +1515,7 @@ qboolean SV_CanSeeBox(int numtraces, vec_t enlarge, vec3_t eye, vec3_t entboxmin
 
        // get the list of entities in the sweep box
        if (sv_cullentities_trace_entityocclusion.integer)
-               numtouchedicts = World_EntitiesInBox(&sv.world, clipboxmins, clipboxmaxs, MAX_EDICTS, touchedicts);
+               numtouchedicts = SV_EntitiesInBox(clipboxmins, clipboxmaxs, MAX_EDICTS, touchedicts);
        if (numtouchedicts > MAX_EDICTS)
        {
                // this never happens
@@ -1951,7 +1982,10 @@ void SV_WriteClientdataToMessage (client_t *client, prvm_edict_t *ent, sizebuf_t
 
        // stuff the sigil bits into the high bits of items for sbar, or else
        // mix in items2
-       if (gamemode == GAME_HIPNOTIC || gamemode == GAME_ROGUE)
+       // LordHavoc: detecting items2 turned out to be tricky, check if the field
+       // was forcefully declared, we want to override serverflags if it was
+       // declared by the qc intentionally, but not if we added it in the engine.
+       if (prog->fieldoffsets.items2 < (int)(prog->numfielddefs - SV_REQGLOBALS))
                items = (int)PRVM_serveredictfloat(ent, items) | ((int)PRVM_serveredictfloat(ent, items2) << 23);
        else
                items = (int)PRVM_serveredictfloat(ent, items) | ((int)PRVM_serverglobalfloat(serverflags) << 28);