]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/sv_main.qc
Merge branch 'master' into terencehill/hud_fixes
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / sv_main.qc
index a7dfb96775d8d272b13a1acf6e4f104b75a3f936..df1e1e61217b7b87dc0002c9ce13e37a1e3272bb 100644 (file)
@@ -1,3 +1,4 @@
+#include "sv_main.qh"
 
 #include "anticheat.qh"
 #include "g_hook.qh"
 .float lastground;
 .int state;
 
-void CreatureFrame ()
-{SELFPARAM();
-       float dm;
-
-       for(entity e = world; (e = findfloat(e, damagedbycontents, true)); )
+void CreatureFrame_hotliquids(entity this)
+{
+       if (this.dmgtime < time)
        {
-               setself(e);
-               if (self.movetype == MOVETYPE_NOCLIP) { continue; }
-
-               float vehic = IS_VEHICLE(self);
-               float projectile = (self.flags & FL_PROJECTILE);
-               float monster = IS_MONSTER(self);
+               this.dmgtime = time + autocvar_g_balance_contents_damagerate;
 
-               if (self.watertype <= CONTENT_WATER && self.waterlevel > 0) // workaround a retarded bug made by id software :P (yes, it's that old of a bug)
+               if (this.flags & FL_PROJECTILE)
                {
-                       if (!(self.flags & FL_INWATER))
-                       {
-                               self.flags |= FL_INWATER;
-                               self.dmgtime = 0;
-                       }
-
-                       if(!vehic && !projectile && !monster) // vehicles, monsters and projectiles don't drown
+                       if (this.watertype == CONTENT_LAVA)
+                               Damage (this, world, world, autocvar_g_balance_contents_projectiledamage * autocvar_g_balance_contents_damagerate * this.waterlevel, DEATH_LAVA.m_id, this.origin, '0 0 0');
+                       else if (this.watertype == CONTENT_SLIME)
+                               Damage (this, world, world, autocvar_g_balance_contents_projectiledamage * autocvar_g_balance_contents_damagerate * this.waterlevel, DEATH_SLIME.m_id, this.origin, '0 0 0');
+               }
+               else
+               {
+                       if (this.watertype == CONTENT_LAVA)
                        {
-                               if (self.waterlevel != WATERLEVEL_SUBMERGED)
+                               if (this.watersound_finished < time)
                                {
-                                       if(self.air_finished < time)
-                                               PlayerSound(playersound_gasp, CH_PLAYER, VOICETYPE_PLAYERSOUND);
-                                       self.air_finished = time + autocvar_g_balance_contents_drowndelay;
-                                       self.dmg = 2;
-                               }
-                               else if (self.air_finished < time)
-                               {       // drown!
-                                       if (!self.deadflag)
-                                       if (self.pain_finished < time)
-                                       {
-                                               Damage (self, world, world, autocvar_g_balance_contents_playerdamage_drowning * autocvar_g_balance_contents_damagerate, DEATH_DROWN.m_id, self.origin, '0 0 0');
-                                               self.pain_finished = time + 0.5;
-                                       }
+                                       this.watersound_finished = time + 0.5;
+                                       sound (this, CH_PLAYER_SINGLE, SND_LAVA, VOL_BASE, ATTEN_NORM);
                                }
+                               Damage (this, world, world, autocvar_g_balance_contents_playerdamage_lava * autocvar_g_balance_contents_damagerate * this.waterlevel, DEATH_LAVA.m_id, this.origin, '0 0 0');
+                               if(autocvar_g_balance_contents_playerdamage_lava_burn)
+                                       Fire_AddDamage(this, world, autocvar_g_balance_contents_playerdamage_lava_burn * this.waterlevel, autocvar_g_balance_contents_playerdamage_lava_burn_time * this.waterlevel, DEATH_LAVA.m_id);
                        }
-
-                       if (self.dmgtime < time)
+                       else if (this.watertype == CONTENT_SLIME)
                        {
-                               self.dmgtime = time + autocvar_g_balance_contents_damagerate;
-
-                               if (projectile)
+                               if (this.watersound_finished < time)
                                {
-                                       if (self.watertype == CONTENT_LAVA)
-                                       {
-                                               Damage (self, world, world, autocvar_g_balance_contents_projectiledamage * autocvar_g_balance_contents_damagerate * self.waterlevel, DEATH_LAVA.m_id, self.origin, '0 0 0');
-                                       }
-                                       else if (self.watertype == CONTENT_SLIME)
-                                       {
-                                               Damage (self, world, world, autocvar_g_balance_contents_projectiledamage * autocvar_g_balance_contents_damagerate * self.waterlevel, DEATH_SLIME.m_id, self.origin, '0 0 0');
-                                       }
-                               }
-                               else
-                               {
-                                       if (self.watertype == CONTENT_LAVA)
-                                       {
-                                               if (self.watersound_finished < time)
-                                               {
-                                                       self.watersound_finished = time + 0.5;
-                                                       sound (self, CH_PLAYER_SINGLE, SND_LAVA, VOL_BASE, ATTEN_NORM);
-                                               }
-                                               Damage (self, world, world, autocvar_g_balance_contents_playerdamage_lava * autocvar_g_balance_contents_damagerate * self.waterlevel, DEATH_LAVA.m_id, self.origin, '0 0 0');
-                                               if(autocvar_g_balance_contents_playerdamage_lava_burn)
-                                                       Fire_AddDamage(self, world, autocvar_g_balance_contents_playerdamage_lava_burn * self.waterlevel, autocvar_g_balance_contents_playerdamage_lava_burn_time * self.waterlevel, DEATH_LAVA.m_id);
-                                       }
-                                       else if (self.watertype == CONTENT_SLIME)
-                                       {
-                                               if (self.watersound_finished < time)
-                                               {
-                                                       self.watersound_finished = time + 0.5;
-                                                       sound (self, CH_PLAYER_SINGLE, SND_SLIME, VOL_BASE, ATTEN_NORM);
-                                               }
-                                               Damage (self, world, world, autocvar_g_balance_contents_playerdamage_slime * autocvar_g_balance_contents_damagerate * self.waterlevel, DEATH_SLIME.m_id, self.origin, '0 0 0');
-                                       }
+                                       this.watersound_finished = time + 0.5;
+                                       sound (this, CH_PLAYER_SINGLE, SND_SLIME, VOL_BASE, ATTEN_NORM);
                                }
+                               Damage (this, world, world, autocvar_g_balance_contents_playerdamage_slime * autocvar_g_balance_contents_damagerate * this.waterlevel, DEATH_SLIME.m_id, this.origin, '0 0 0');
                        }
                }
-               else
+       }
+}
+
+void CreatureFrame_Liquids(entity this)
+{
+       if (this.watertype <= CONTENT_WATER && this.waterlevel > 0) // workaround a retarded bug made by id software :P (yes, it's that old of a bug)
+       {
+               if (!(this.flags & FL_INWATER))
                {
-                       if (self.flags & FL_INWATER)
-                       {
-                               // play leave water sound
-                               self.flags &= ~FL_INWATER;
-                               self.dmgtime = 0;
-                       }
-                       self.air_finished = time + 12;
-                       self.dmg = 2;
+                       this.flags |= FL_INWATER;
+                       this.dmgtime = 0;
                }
 
-               if(!vehic && !projectile) // vehicles don't get falling damage
+               CreatureFrame_hotliquids(this);
+       }
+       else
+       {
+               if (this.flags & FL_INWATER)
                {
-                       // check for falling damage
-                       float velocity_len = vlen(self.velocity);
-                       if(!self.hook.state)
-                       {
-                               dm = vlen(self.oldvelocity) - velocity_len; // dm is now the velocity DECREASE. Velocity INCREASE should never cause a sound or any damage.
-                               if (self.deadflag)
-                                       dm = (dm - autocvar_g_balance_falldamage_deadminspeed) * autocvar_g_balance_falldamage_factor;
-                               else
-                                       dm = min((dm - autocvar_g_balance_falldamage_minspeed) * autocvar_g_balance_falldamage_factor, autocvar_g_balance_falldamage_maxdamage);
-                               if (dm > 0)
-                                       Damage (self, world, world, dm, DEATH_FALL.m_id, self.origin, '0 0 0');
-                       }
+                       // play leave water sound
+                       this.flags &= ~FL_INWATER;
+                       this.dmgtime = 0;
+               }
+               this.air_finished = time + 12;
+               this.dmg = 2;
+       }
+}
 
-                       if(autocvar_g_maxspeed > 0 && velocity_len > autocvar_g_maxspeed)
-                               Damage (self, world, world, 100000, DEATH_SHOOTING_STAR.m_id, self.origin, '0 0 0');
-                       // play stupid sounds
-                       if (g_footsteps)
-                       if (!gameover)
-                       if (self.flags & FL_ONGROUND)
-                       if (!self.crouch)
-                       if (velocity_len > autocvar_sv_maxspeed * 0.6)
-                       if (!self.deadflag)
-                       if (time < self.lastground + 0.2)
-                       {
-                               if((time > self.nextstep) || (time < (self.nextstep - 10.0)))
-                               {
-                                       self.nextstep = time + 0.3 + random() * 0.1;
-                                       trace_dphitq3surfaceflags = 0;
-                                       tracebox(self.origin, self.mins, self.maxs, self.origin - '0 0 1', MOVE_NOMONSTERS, self);
-                                       /*
-                                       if(trace_fraction == 1)
-                                               dprint("nohit\n");
-                                       else
-                                               dprint(ftos(trace_dphitq3surfaceflags), "\n");
-                                       */
-                                       if (!(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOSTEPS))
-                                       {
-                                               if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_METALSTEPS)
-                                                       GlobalSound(GS_STEP_METAL, CH_PLAYER, VOICETYPE_PLAYERSOUND);
-                                               else
-                                                       GlobalSound(GS_STEP, CH_PLAYER, VOICETYPE_PLAYERSOUND);
-                                       }
-                               }
-                       }
+void CreatureFrame_FallDamage(entity this)
+{
+       if(!IS_VEHICLE(this) && !(this.flags & FL_PROJECTILE)) // vehicles don't get falling damage
+       {
+               // check for falling damage
+               float velocity_len = vlen(this.velocity);
+               if(!this.hook.state)
+               {
+                       float dm = vlen(this.oldvelocity) - velocity_len; // dm is now the velocity DECREASE. Velocity INCREASE should never cause a sound or any damage.
+                       if (IS_DEAD(this))
+                               dm = (dm - autocvar_g_balance_falldamage_deadminspeed) * autocvar_g_balance_falldamage_factor;
+                       else
+                               dm = min((dm - autocvar_g_balance_falldamage_minspeed) * autocvar_g_balance_falldamage_factor, autocvar_g_balance_falldamage_maxdamage);
+                       if (dm > 0)
+                               Damage (this, world, world, dm, DEATH_FALL.m_id, this.origin, '0 0 0');
                }
 
-        self.oldvelocity = self.velocity;
+               if(autocvar_g_maxspeed > 0 && velocity_len > autocvar_g_maxspeed)
+                       Damage (this, world, world, 100000, DEATH_SHOOTING_STAR.m_id, this.origin, '0 0 0');
        }
-       setself(this);
 }
 
+void CreatureFrame_All()
+{
+       FOREACH_ENTITY_FLOAT(damagedbycontents, true, LAMBDA(
+               if(it.movetype == MOVETYPE_NOCLIP) continue;
+               CreatureFrame_Liquids(it);
+               CreatureFrame_FallDamage(it);
+               it.oldvelocity = it.velocity;
+       ));
+}
+
+void Pause_TryPause(bool ispaused)
+{
+       int n = 0;
+       FOREACH_CLIENT(IS_PLAYER(it) && IS_REAL_CLIENT(it), LAMBDA(
+               if (PHYS_INPUT_BUTTON_CHAT(it) != ispaused) return;
+               ++n;
+       ));
+       if (!n) return;
+       setpause(ispaused);
+}
+
+void SV_PausedTic(float elapsedtime)
+{
+       if (!server_is_dedicated) Pause_TryPause(false);
+}
 
 /*
 =============
@@ -186,11 +152,17 @@ Called before each frame by the server
 float game_delay;
 float game_delay_last;
 
+bool autocvar_sv_autopause = true;
 float RedirectionThink();
+void PM_Main(Client this);
 void StartFrame()
 {
-       SELFPARAM();
+    // TODO: if move is more than 50ms, split it into two moves (this matches QWSV behavior and the client prediction)
+    FOREACH_ENTITY_CLASS(STR_PLAYER, IS_FAKE_CLIENT(it), PM_Main(it));
+    FOREACH_ENTITY_CLASS(STR_PLAYER, IS_FAKE_CLIENT(it), WITH(entity, self, it, PlayerPreThink()));
+
        execute_next_frame();
+       if (autocvar_sv_autopause && !server_is_dedicated) Pause_TryPause(true);
 
        remove = remove_unsafely; // not during spawning!
        serverprevtime = servertime;
@@ -204,14 +176,12 @@ void StartFrame()
                LOG_INFO("CEFC time: ", ftos(t * 1000), "ms; ");
                int c_seeing = 0;
                int c_seen = 0;
-               entity cl;
-               FOR_EACH_CLIENT(cl)
-               {
-                       if(IS_REAL_CLIENT(cl))
+               FOREACH_CLIENT(true, LAMBDA(
+                       if(IS_REAL_CLIENT(it))
                                ++c_seeing;
-                       if(IS_PLAYER(cl))
+                       if(IS_PLAYER(it))
                                ++c_seen;
-               }
+               ));
                LOG_INFO("CEFC calls per second: ", ftos(c_seeing * (c_seen - 1) / t), "; ");
                LOG_INFO("CEFC 100% load at: ", ftos(solve_quadratic(t, -t, -1) * '0 1 0'), "\n");
 
@@ -220,8 +190,7 @@ void StartFrame()
        }
 #endif
 
-       for(entity e = world; (e = findfloat(e, csqcprojectile_clientanimate, 1)); )
-               CSQCProjectile_Check(e);
+       FOREACH_ENTITY_FLOAT(csqcprojectile_clientanimate, true, LAMBDA(CSQCProjectile_Check(it)));
 
        if(RedirectionThink())
                return;
@@ -248,14 +217,10 @@ void StartFrame()
 
        game_delay_last = game_delay;
 
-       CreatureFrame();
+       CreatureFrame_All();
        CheckRules_World();
 
-       // if in warmup stage and limit for warmup is hit start match
-       if(warmup_stage)
-       if(!gameover)
-       if((g_warmup_limit > 0 && time >= g_warmup_limit)
-        || (g_warmup_limit == 0 && autocvar_timelimit != 0 && time >= autocvar_timelimit * 60))
+       if(warmup_stage && !gameover && warmup_limit > 0 && time >= warmup_limit)
        {
                ReadyRestart();
                return;
@@ -264,13 +229,9 @@ void StartFrame()
        bot_serverframe();
        anticheat_startframe();
        MUTATOR_CALLHOOK(SV_StartFrame);
-       {
-        entity e;
-        FOR_EACH_CLIENT(e)
-        {
-            GlobalStats_update(e);
-        }
-    }
+
+    FOREACH_CLIENT(true, LAMBDA(GlobalStats_update(it)));
+    FOREACH_ENTITY_CLASS(STR_PLAYER, IS_FAKE_CLIENT(it), WITH(entity, self, it, PlayerPostThink()));
 }
 
 .vector originjitter;
@@ -281,6 +242,7 @@ void StartFrame()
 float DoesQ3ARemoveThisEntity();
 void SV_OnEntityPreSpawnFunction()
 {SELFPARAM();
+       __spawnfunc_expect = this;
        if (self)
        if (self.gametypefilter != "")
        if (!isGametypeInFilter(MapInfo_LoadedGametype, teamplay, have_team_spawns, self.gametypefilter))
@@ -388,7 +350,7 @@ void SV_OnEntityPreSpawnFunction()
                        }
                }
                inv = !inv;
-:cvar_fail
+LABEL(cvar_fail)
                // now inv is 1 if we want to keep the item, and 0 if we want to get rid of it
                if (!inv)
                {