]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/sv_main.qc
Merge branch 'marin-t/fix' into 'master'
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / sv_main.qc
index 87430a93eff4502037e10c52e8dd511f820e1852..6b5b19d79ec8a60d141da4248e547b8deaca1480 100644 (file)
@@ -2,14 +2,16 @@
 
 #include "anticheat.qh"
 #include "g_hook.qh"
+#include "g_damage.qh"
 #include "g_world.qh"
 
 #include "bot/api.qh"
 
 #include "command/common.qh"
 
-#include "mutators/_mod.qh"
+#include <server/mutators/_mod.qh>
 #include "weapons/csqcprojectile.qh"
+#include <server/compat/quake3.qh>
 
 #include "../common/constants.qh"
 #include "../common/deathtypes/all.qh"
@@ -18,6 +20,7 @@
 #include "../common/util.qh"
 
 #include "../common/vehicles/all.qh"
+#include <common/monsters/sv_monsters.qh>
 #include <common/weapons/_all.qh>
 
 #include "../lib/csqcmodel/sv_model.qh"
 #include "../lib/warpzone/common.qh"
 #include "../lib/warpzone/server.qh"
 
-.float lastground;
-.int state;
-
 void CreatureFrame_hotliquids(entity this)
 {
-       if (this.dmgtime < time)
+       if (this.dmgtime >= time)
        {
-               this.dmgtime = time + autocvar_g_balance_contents_damagerate;
+               return;
+       }
 
-               if (this.flags & FL_PROJECTILE)
-               {
-                       if (this.watertype == CONTENT_LAVA)
-                               Damage (this, NULL, NULL, 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, NULL, NULL, autocvar_g_balance_contents_projectiledamage * autocvar_g_balance_contents_damagerate * this.waterlevel, DEATH_SLIME.m_id, this.origin, '0 0 0');
-               }
-               else
+       this.dmgtime = time + autocvar_g_balance_contents_damagerate;
+
+       if (this.flags & FL_PROJECTILE)
+       {
+               if (this.watertype == CONTENT_LAVA)
+                       Damage (this, NULL, NULL, autocvar_g_balance_contents_projectiledamage * autocvar_g_balance_contents_damagerate * this.waterlevel, DEATH_LAVA.m_id, DMG_NOWEP, this.origin, '0 0 0');
+               else if (this.watertype == CONTENT_SLIME)
+                       Damage (this, NULL, NULL, autocvar_g_balance_contents_projectiledamage * autocvar_g_balance_contents_damagerate * this.waterlevel, DEATH_SLIME.m_id, DMG_NOWEP, this.origin, '0 0 0');
+       }
+       else
+       {
+               if (this.watertype == CONTENT_LAVA)
                {
-                       if (this.watertype == CONTENT_LAVA)
+                       if (this.watersound_finished < time)
                        {
-                               if (this.watersound_finished < time)
-                               {
-                                       this.watersound_finished = time + 0.5;
-                                       sound (this, CH_PLAYER_SINGLE, SND_LAVA, VOL_BASE, ATTEN_NORM);
-                               }
-                               Damage (this, NULL, NULL, 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, NULL, autocvar_g_balance_contents_playerdamage_lava_burn * this.waterlevel, autocvar_g_balance_contents_playerdamage_lava_burn_time * this.waterlevel, DEATH_LAVA.m_id);
+                               this.watersound_finished = time + 0.5;
+                               sound (this, CH_PLAYER_SINGLE, SND_LAVA, VOL_BASE, ATTEN_NORM);
                        }
-                       else if (this.watertype == CONTENT_SLIME)
+                       Damage (this, NULL, NULL, autocvar_g_balance_contents_playerdamage_lava * autocvar_g_balance_contents_damagerate * this.waterlevel, DEATH_LAVA.m_id, DMG_NOWEP, this.origin, '0 0 0');
+                       if(autocvar_g_balance_contents_playerdamage_lava_burn)
+                               Fire_AddDamage(this, NULL, autocvar_g_balance_contents_playerdamage_lava_burn * this.waterlevel, autocvar_g_balance_contents_playerdamage_lava_burn_time * this.waterlevel, DEATH_LAVA.m_id);
+               }
+               else if (this.watertype == CONTENT_SLIME)
+               {
+                       if (this.watersound_finished < time)
                        {
-                               if (this.watersound_finished < time)
-                               {
-                                       this.watersound_finished = time + 0.5;
-                                       sound (this, CH_PLAYER_SINGLE, SND_SLIME, VOL_BASE, ATTEN_NORM);
-                               }
-                               Damage (this, NULL, NULL, autocvar_g_balance_contents_playerdamage_slime * autocvar_g_balance_contents_damagerate * this.waterlevel, DEATH_SLIME.m_id, this.origin, '0 0 0');
+                               this.watersound_finished = time + 0.5;
+                               sound (this, CH_PLAYER_SINGLE, SND_SLIME, VOL_BASE, ATTEN_NORM);
                        }
+                       Damage (this, NULL, NULL, autocvar_g_balance_contents_playerdamage_slime * autocvar_g_balance_contents_damagerate * this.waterlevel, DEATH_SLIME.m_id, DMG_NOWEP, this.origin, '0 0 0');
                }
        }
 }
@@ -88,45 +90,48 @@ void CreatureFrame_Liquids(entity this)
                        this.dmgtime = 0;
                }
                this.air_finished = time + 12;
-               this.dmg = 2;
        }
 }
 
 void CreatureFrame_FallDamage(entity this)
 {
-       if(!IS_VEHICLE(this) && !(this.flags & FL_PROJECTILE)) // vehicles don't get falling damage
-       if(this.velocity || this.oldvelocity) // moving or has moved
+       if(IS_VEHICLE(this) || (this.flags & FL_PROJECTILE))
+               return; // vehicles and projectiles don't receive fall damage
+       if(!(this.velocity || this.oldvelocity))
+               return; // if the entity hasn't moved and isn't moving, then don't do anything
+
+       // check for falling damage
+       float velocity_len = vlen(this.velocity);
+       bool have_hook = false;
+       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
        {
-               // check for falling damage
-               float velocity_len = vlen(this.velocity);
-               bool have_hook = false;
-               for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+           .entity weaponentity = weaponentities[slot];
+           if(this.(weaponentity).hook && this.(weaponentity).hook.state)
            {
-               .entity weaponentity = weaponentities[slot];
-               if(this.(weaponentity).hook && this.(weaponentity).hook.state)
-               {
-                       have_hook = true;
-                       break;
-               }
+               have_hook = true;
+               break;
            }
-               if(!have_hook)
-               {
-                       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, NULL, NULL, dm, DEATH_FALL.m_id, this.origin, '0 0 0');
-               }
-
-               if(autocvar_g_maxspeed > 0 && velocity_len > autocvar_g_maxspeed)
-                       Damage (this, NULL, NULL, 100000, DEATH_SHOOTING_STAR.m_id, this.origin, '0 0 0');
        }
+       if(!have_hook)
+       {
+               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, NULL, NULL, dm, DEATH_FALL.m_id, DMG_NOWEP, this.origin, '0 0 0');
+       }
+
+       if(autocvar_g_maxspeed > 0 && velocity_len > autocvar_g_maxspeed)
+               Damage (this, NULL, NULL, 100000, DEATH_SHOOTING_STAR.m_id, DMG_NOWEP, this.origin, '0 0 0');
 }
 
 void CreatureFrame_All()
 {
+       if(game_stopped || time < game_starttime)
+               return;
+
        IL_EACH(g_damagedbycontents, it.damagedbycontents,
        {
                if (it.move_movetype == MOVETYPE_NOCLIP) continue;
@@ -163,7 +168,6 @@ Called before each frame by the server
 bool game_delay_last;
 
 bool autocvar_sv_autopause = false;
-float RedirectionThink();
 void systems_update();
 void sys_phys_update(entity this, float dt);
 void StartFrame()
@@ -217,8 +221,6 @@ void StartFrame()
        if (timeout_status == TIMEOUT_LEADTIME) // just before the timeout (when timeout_status will be TIMEOUT_ACTIVE)
                orig_slowmo = autocvar_slowmo; // slowmo will be restored after the timeout
 
-       skill = autocvar_skill;
-
        // detect when the pre-game countdown (if any) has ended and the game has started
        bool game_delay = (time < game_starttime);
        if (autocvar_sv_eventlog && game_delay_last && !game_delay)
@@ -246,76 +248,86 @@ void StartFrame()
 .float anglejitter;
 .string gametypefilter;
 .string cvarfilter;
-bool DoesQ3ARemoveThisEntity(entity this);
+
+/**
+ * Evaluate an expression of the form: [+ | -]? [var[op]val | [op]var | val | var] ...
+ * +: all must match. this is the default
+ * -: one must NOT match
+ *
+ * var>x
+ * var<x
+ * var>=x
+ * var<=x
+ * var==x
+ * var!=x
+ * var===x
+ * var!==x
+ */
+bool expr_evaluate(string s)
+{
+    bool ret = false;
+    if (str2chr(s, 0) == '+') {
+        s = substring(s, 1, -1);
+    } else if (str2chr(s, 0) == '-') {
+        ret = true;
+        s = substring(s, 1, -1);
+    }
+    bool expr_fail = false;
+    for (int i = 0, n = tokenize_console(s); i < n; ++i) {
+        int o;
+        string k, v;
+        s = argv(i);
+        #define X(expr) \
+            if (expr) \
+                continue; \
+            expr_fail = true; \
+            break;
+
+        #define BINOP(op, len, expr) \
+            if ((o = strstrofs(s, op, 0)) >= 0) { \
+                k = substring(s, 0, o); \
+                v = substring(s, o + len, -1); \
+                X(expr); \
+            }
+        BINOP(">=", 2, cvar(k) >= stof(v));
+        BINOP("<=", 2, cvar(k) <= stof(v));
+        BINOP(">",  1, cvar(k) >  stof(v));
+        BINOP("<",  1, cvar(k) <  stof(v));
+        BINOP("==", 2, cvar(k) == stof(v));
+        BINOP("!=", 2, cvar(k) != stof(v));
+        BINOP("===", 3, cvar_string(k) == v);
+        BINOP("!==", 3, cvar_string(k) != v);
+        {
+            k = s;
+            bool b = true;
+            if (str2chr(k, 0) == '!') {
+                k = substring(s, 1, -1);
+                b = false;
+            }
+            float f = stof(k);
+            bool isnum = ftos(f) == k;
+            X(boolean(isnum ? f : cvar(k)) == b);
+        }
+        #undef BINOP
+        #undef X
+    }
+    if (!expr_fail) {
+        ret = !ret;
+    }
+    // now ret is true if we want to keep the item, and false if we want to get rid of it
+    return ret;
+}
+
 void SV_OnEntityPreSpawnFunction(entity this)
 {
-       __spawnfunc_expecting = true;
-       __spawnfunc_expect = this;
        if (this)
        if (this.gametypefilter != "")
        if (!isGametypeInFilter(MapInfo_LoadedGametype, teamplay, have_team_spawns, this.gametypefilter))
        {
                goto cleanup;
        }
-       if (this.cvarfilter != "") {
-               bool inv = false;
-
-               string s = this.cvarfilter;
-               if (str2chr(s, 0) == '+') {
-                       s = substring(s, 1, -1);
-               } else if(str2chr(s, 0) == '-') {
-                       inv = true;
-                       s = substring(s, 1, -1);
-               }
-
-        bool cvar_fail = false;
-               for (int i = 0, n = tokenize_console(s); i < n; ++i) {
-                   int o;
-            string k, v;
-                       s = argv(i);
-                       // syntax:
-                       // var>x
-                       // var<x
-                       // var>=x
-                       // var<=x
-                       // var==x
-                       // var!=x
-                       // var===x
-                       // var!==x
-                       #define X(expr) \
-                           if (expr) { \
-                    continue; \
-                } else { \
-                    cvar_fail = true; \
-                    break; \
-                }
-                       #define BINOP(op, len, expr) \
-                           if ((o = strstrofs(s, op, 0)) >= 0) { \
-                    k = substring(s, 0, o); \
-                    v = substring(s, o + len, -1); \
-                    X(expr); \
-                }
-            BINOP(">=", 2, cvar(k) >= stof(v));
-            BINOP("<=", 2, cvar(k) <= stof(v));
-            BINOP(">",  1, cvar(k) >  stof(v));
-            BINOP("<",  1, cvar(k) <  stof(v));
-            BINOP("==", 2, cvar(k) == stof(v));
-            BINOP("!=", 2, cvar(k) != stof(v));
-            // fixme: did these two ever work?
-            BINOP("===", 2, cvar_string(k) == v);
-            BINOP("!==", 2, cvar_string(k) != v);
-            if (str2chr(s, 0) == '!') { k = substring(s, 1, -1); X(!cvar(k)); }
-            { k = s; X(cvar(k)); }
-                       #undef BINOP
-                       #undef X
-               }
-               if (!cvar_fail) {
-                   inv = !inv;
-               }
-               // now inv is true if we want to keep the item, and false if we want to get rid of it
-               if (!inv) {
-                       goto cleanup;
-               }
+       if (this.cvarfilter != "" && !expr_evaluate(this.cvarfilter)) {
+        goto cleanup;
        }
 
        if (DoesQ3ARemoveThisEntity(this)) {
@@ -348,23 +360,29 @@ void SV_OnEntityPreSpawnFunction(entity this)
        }
        return;
 LABEL(cleanup)
-    builtin_remove(this);
-    __spawnfunc_expecting = false;
+    delete(this);
 }
 
 void WarpZone_PostInitialize_Callback()
 {
        // create waypoint links for warpzones
+       entity tracetest_ent = spawn();
+       setsize(tracetest_ent, PL_MIN_CONST, PL_MAX_CONST);
+       tracetest_ent.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_PLAYERCLIP | DPCONTENTS_BOTCLIP;
        //for(entity e = warpzone_first; e; e = e.warpzone_next)
        for(entity e = NULL; (e = find(e, classname, "trigger_warpzone")); )
-       {
-               vector src, dst;
-               src = (e.absmin + e.absmax) * 0.5;
-               makevectors(e.warpzone_angles);
-               src = src + ((e.warpzone_origin - src) * v_forward) * v_forward + 16 * v_right;
-               dst = (e.enemy.absmin + e.enemy.absmax) * 0.5;
-               makevectors(e.enemy.warpzone_angles);
-               dst = dst + ((e.enemy.warpzone_origin - dst) * v_forward) * v_forward - 16 * v_right;
-               waypoint_spawnforteleporter_v(e, src, dst, 0);
-       }
+               waypoint_spawnforteleporter_wz(e, tracetest_ent);
+       delete(tracetest_ent);
+}
+
+/*
+==================
+main
+
+unused but required by the engine
+==================
+*/
+void main ()
+{
+
 }