]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/mutators/mutator/gamemode_cts.qc
Purge self from the damage/death mutator hooks
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / mutators / mutator / gamemode_cts.qc
index 064031153cd2a6974e6f95ce5a8b2045b4800ffa..65376b78d8bf896951768ce28af26a12dae063af 100644 (file)
@@ -1,4 +1,5 @@
-#include "../../race.qh"
+#include "gamemode_cts.qh"
+#include <server/race.qh>
 
 #ifndef GAMEMODE_CTS_H
 #define GAMEMODE_CTS_H
@@ -7,14 +8,15 @@ void cts_Initialize();
 
 REGISTER_MUTATOR(cts, false)
 {
-       g_race_qualifying = true;
-       independent_players = 1;
-       SetLimits(0, 0, 0, -1);
-
        MUTATOR_ONADD
        {
                if (time > 1) // game loads at time 1
                        error("This is a game type and it cannot be added at runtime.");
+
+               g_race_qualifying = true;
+               independent_players = 1;
+               SetLimits(0, 0, autocvar_timelimit_override, -1);
+
                cts_Initialize();
        }
 
@@ -43,37 +45,32 @@ const float SP_CTS_FASTEST = 6;
 
 #ifdef IMPLEMENTATION
 
-#include "../../race.qh"
+#include <server/race.qh>
 
 float autocvar_g_cts_finish_kill_delay;
 bool autocvar_g_cts_selfdamage;
 
 // legacy bot roles
 .float race_checkpoint;
-void havocbot_role_cts()
-{SELFPARAM();
-       if(self.deadflag != DEAD_NO)
+void havocbot_role_cts(entity this)
+{
+       if(IS_DEAD(this))
                return;
 
-       entity e;
-       if (self.bot_strategytime < time)
+       if (this.bot_strategytime < time)
        {
-               self.bot_strategytime = time + autocvar_bot_ai_strategyinterval;
-               navigation_goalrating_start();
+               this.bot_strategytime = time + autocvar_bot_ai_strategyinterval;
+               navigation_goalrating_start(this);
 
-               for(e = world; (e = find(e, classname, "trigger_race_checkpoint")) != world; )
+               FOREACH_ENTITY_CLASS("trigger_race_checkpoint", true,
                {
-                       if(e.cnt == self.race_checkpoint)
-                       {
-                               navigation_routerating(e, 1000000, 5000);
-                       }
-                       else if(self.race_checkpoint == -1)
-                       {
-                               navigation_routerating(e, 1000000, 5000);
-                       }
-               }
+                       if(it.cnt == this.race_checkpoint)
+                               navigation_routerating(this, it, 1000000, 5000);
+                       else if(this.race_checkpoint == -1)
+                               navigation_routerating(this, it, 1000000, 5000);
+               });
 
-               navigation_goalrating_end();
+               navigation_goalrating_end(this);
        }
 }
 
@@ -99,11 +96,12 @@ void cts_EventLog(string mode, entity actor) // use an alias for easy changing a
                GameLogEcho(strcat(":cts:", mode, ":", ((actor != world) ? (strcat(":", ftos(actor.playerid))) : "")));
 }
 
+void KillIndicator_Think(entity this);
 void CTS_ClientKill(entity e) // silent version of ClientKill, used when player finishes a CTS run. Useful to prevent cheating by running back to the start line and starting out with more speed
 {
     e.killindicator = spawn();
     e.killindicator.owner = e;
-    e.killindicator.think = KillIndicator_Think;
+    setthink(e.killindicator, KillIndicator_Think);
     e.killindicator.nextthink = time + (e.lip) * 0.05;
     e.killindicator.cnt = ceil(autocvar_g_cts_finish_kill_delay);
     e.killindicator.health = 1; // this is used to indicate that it should be silent
@@ -191,17 +189,15 @@ MUTATOR_HOOKFUNCTION(cts, reset_map_global)
        race_ClearRecords();
        PlayerScore_Sort(race_place, 0, 1, 0);
 
-       entity e;
-       FOR_EACH_CLIENT(e)
-       {
-               if(e.race_place)
+       FOREACH_CLIENT(true, LAMBDA(
+               if(it.race_place)
                {
-                       s = PlayerScore_Add(e, SP_RACE_FASTEST, 0);
+                       s = PlayerScore_Add(it, SP_RACE_FASTEST, 0);
                        if(!s)
-                               e.race_place = 0;
+                               it.race_place = 0;
                }
-               cts_EventLog(ftos(e.race_place), e);
-       }
+               cts_EventLog(ftos(it.race_place), it);
+       ));
 
        if(g_race_qualifying == 2)
        {
@@ -216,19 +212,9 @@ MUTATOR_HOOKFUNCTION(cts, reset_map_global)
        return false;
 }
 
-MUTATOR_HOOKFUNCTION(cts, PlayerPreThink)
-{SELFPARAM();
-       if(IS_SPEC(self) || IS_OBSERVER(self))
-       if(g_race_qualifying)
-       if(msg_entity.enemy.race_laptime)
-               race_SendNextCheckpoint(msg_entity.enemy, 1);
-
-       return false;
-}
-
 MUTATOR_HOOKFUNCTION(cts, ClientConnect)
 {SELFPARAM();
-       race_PreparePlayer();
+       race_PreparePlayer(this);
        self.race_checkpoint = -1;
 
        if(IS_REAL_CLIENT(self))
@@ -260,46 +246,53 @@ MUTATOR_HOOKFUNCTION(cts, MakePlayerObserver)
        else
                self.frags = FRAGS_SPECTATOR;
 
-       race_PreparePlayer();
+       race_PreparePlayer(this);
        self.race_checkpoint = -1;
 
        return false;
 }
 
 MUTATOR_HOOKFUNCTION(cts, PlayerSpawn)
-{SELFPARAM();
+{
+       entity player = M_ARGV(0, entity);
+       entity spawn_spot = M_ARGV(1, entity);
+
        if(spawn_spot.target == "")
                // Emergency: this wasn't a real spawnpoint. Can this ever happen?
-               race_PreparePlayer();
+               race_PreparePlayer(player);
 
        // if we need to respawn, do it right
-       self.race_respawn_checkpoint = self.race_checkpoint;
-       self.race_respawn_spotref = spawn_spot;
+       player.race_respawn_checkpoint = player.race_checkpoint;
+       player.race_respawn_spotref = spawn_spot;
 
-       self.race_place = 0;
+       player.race_place = 0;
 
        return false;
 }
 
 MUTATOR_HOOKFUNCTION(cts, PutClientInServer)
-{SELFPARAM();
-       if(IS_PLAYER(self))
+{
+       entity player = M_ARGV(0, entity);
+
+       if(IS_PLAYER(player))
        if(!gameover)
        {
-               if(self.killcount == -666 /* initial spawn */ || g_race_qualifying) // spawn
-                       race_PreparePlayer();
+               if(player.killcount == FRAGS_SPECTATOR /* initial spawn */ || g_race_qualifying) // spawn
+                       race_PreparePlayer(player);
                else // respawn
-                       race_RetractPlayer();
+                       race_RetractPlayer(player);
 
-               race_AbandonRaceCheck(self);
+               race_AbandonRaceCheck(player);
        }
        return false;
 }
 
 MUTATOR_HOOKFUNCTION(cts, PlayerDies)
-{SELFPARAM();
-       self.respawn_flags |= RESPAWN_FORCE;
-       race_AbandonRaceCheck(self);
+{
+       entity frag_target = M_ARGV(2, entity);
+       
+       frag_target.respawn_flags |= RESPAWN_FORCE;
+       race_AbandonRaceCheck(frag_target);
        return false;
 }
 
@@ -368,9 +361,17 @@ MUTATOR_HOOKFUNCTION(cts, FilterItem)
 
 MUTATOR_HOOKFUNCTION(cts, PlayerDamage_Calculate)
 {
+       entity frag_attacker = M_ARGV(1, entity);
+       entity frag_target = M_ARGV(2, entity);
+       float frag_deathtype = M_ARGV(3, float);
+       float frag_damage = M_ARGV(4, float);
+
        if(frag_target == frag_attacker || frag_deathtype == DEATH_FALL.m_id)
        if(!autocvar_g_cts_selfdamage)
+       {
                frag_damage = 0;
+               M_ARGV(4, float) = frag_damage;
+       }
 
        return false;
 }
@@ -380,13 +381,6 @@ MUTATOR_HOOKFUNCTION(cts, ForbidPlayerScore_Clear)
        return true; // in CTS, you don't lose score by observing
 }
 
-MUTATOR_HOOKFUNCTION(cts, SetModname)
-{
-       g_cloaked = 1; // always enable cloak in CTS
-
-       return false;
-}
-
 MUTATOR_HOOKFUNCTION(cts, GetRecords)
 {
        for(int i = record_page * 200; i < MapInfo_count && i < record_page * 200 + 200; ++i)
@@ -406,8 +400,10 @@ MUTATOR_HOOKFUNCTION(cts, GetRecords)
        return false;
 }
 
+void ClientKill_Now();
 MUTATOR_HOOKFUNCTION(cts, ClientKill)
 {
+    SELFPARAM();
        ret_float = 0;
 
        if(self.killindicator && self.killindicator.health == 1) // self.killindicator.health == 1 means that the kill indicator was spawned by CTS_ClientKill
@@ -424,7 +420,7 @@ MUTATOR_HOOKFUNCTION(cts, ClientKill)
 MUTATOR_HOOKFUNCTION(cts, Race_FinalCheckpoint)
 {
        if(autocvar_g_cts_finish_kill_delay)
-               CTS_ClientKill(self);
+               CTS_ClientKill(race_player);
 
        return false;
 }
@@ -437,7 +433,7 @@ MUTATOR_HOOKFUNCTION(cts, FixClientCvars)
 
 MUTATOR_HOOKFUNCTION(cts, WantWeapon)
 {
-       ret_float = (want_weaponinfo.weapon == WEP_SHOTGUN.m_id);
+       ret_float = (want_weaponinfo == WEP_SHOTGUN);
        want_mutatorblocked = true;
        return true;
 }