]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/mutators/gamemode_freezetag.qc
Merge remote branch 'origin/master' into fruitiex/balance
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / mutators / gamemode_freezetag.qc
index a1cc9deb6c6b0ed39e1f4707b56912797f8e9de5..f8d45f0424265f2823912edd65576f76a1f11373 100644 (file)
@@ -2,6 +2,7 @@ void freezetag_Initialize()
 {
        precache_model("models/ice/ice.md3");
        warmup = time + autocvar_g_start_delay + autocvar_g_freezetag_warmup;
+       ScoreRules_freezetag();
 }
 
 void freezetag_CheckWinner()
@@ -22,6 +23,7 @@ void freezetag_CheckWinner()
 
        entity e, winner;
        string teamname;
+       winner = world;
 
        FOR_EACH_PLAYER(e)
        {
@@ -34,7 +36,6 @@ void freezetag_CheckWinner()
 
        if(winner != world) // just in case a winner wasn't found
        {
-               TeamScore_AddToTeam(winner.team, ST_SCORE, +1);
                if(winner.team == COLOR_TEAM1)
                        teamname = "^1Red Team";
                else if(winner.team == COLOR_TEAM2)
@@ -47,18 +48,22 @@ void freezetag_CheckWinner()
                        centerprint(e, strcat(teamname, "^5 wins the round, all other teams were frozen.\n"));
                }
                bprint(teamname, "^5 wins the round since all the other teams were frozen.\n");
+               TeamScore_AddToTeam(winner.team, ST_SCORE, +1);
        }
 
        next_round = time + 5;
 }
 
+// this is needed to allow the player to turn his view around (fixangle can't
+// be used to freeze his view, as that also changes the angles), while not
+// turning that ice object with the player
 void freezetag_Ice_Think()
 {
        setorigin(self, self.owner.origin - '0 0 16');
        self.nextthink = time;
 }
 
-void freezetag_Freeze()
+void freezetag_Freeze(entity attacker)
 {
        self.freezetag_frozen = 1;
 
@@ -71,7 +76,11 @@ void freezetag_Freeze()
        ice.frame = floor(random() * 21); // ice model has 20 different looking frames
        setmodel(ice, "models/ice/ice.md3");
 
-       self.movement = '0 0 0';
+       entity oldself;
+       oldself = self;
+       self = ice;
+       freezetag_Ice_Think();
+       self = oldself;
 
        // add waypoint
        WaypointSprite_Spawn("freezetag_frozen", 0, 0, self, '0 0 64', world, self.team, self, waypointsprite_attached, TRUE);
@@ -79,9 +88,27 @@ void freezetag_Freeze()
        {
                WaypointSprite_UpdateTeamRadar(self.waypointsprite_attached, RADARICON_WAYPOINT, '0.25 0.90 1');
        }
+
+       if(attacker == self)
+       {
+               // you froze your own dumb self
+               // counted as "suicide" already
+               PlayerScore_Add(self, SP_SCORE, -1);
+       }
+       else if(attacker.classname == "player")
+       {
+               // got frozen by an enemy
+               // counted as "kill" and "death" already
+               PlayerScore_Add(self, SP_SCORE, -1);
+               PlayerScore_Add(attacker, SP_SCORE, +1);
+       }
+       else
+       {
+               // nothing - got frozen by the game type rules themselves
+       }
 }
 
-void freezetag_Unfreeze()
+void freezetag_Unfreeze(entity attacker)
 {
        self.freezetag_frozen = 0;
 
@@ -116,7 +143,7 @@ MUTATOR_HOOKFUNCTION(freezetag_RemovePlayer)
        if(totalspawned > 2) // only check for winners if we had more than two players (one of them left, don't let the other player win just because of that)
                freezetag_CheckWinner();
 
-       freezetag_Unfreeze();
+       freezetag_Unfreeze(world);
 
        return 1;
 }
@@ -135,7 +162,7 @@ MUTATOR_HOOKFUNCTION(freezetag_PlayerDies)
                        --pinkalive;
                --totalalive;
 
-        freezetag_Freeze();
+        freezetag_Freeze(frag_attacker);
        }
 
     if(frag_attacker.classname == STR_PLAYER)
@@ -163,7 +190,7 @@ MUTATOR_HOOKFUNCTION(freezetag_PlayerDies)
 
 MUTATOR_HOOKFUNCTION(freezetag_PlayerSpawn)
 {
-    freezetag_Unfreeze(); // start by making sure that all ice blocks are removed
+    freezetag_Unfreeze(world); // start by making sure that all ice blocks are removed
 
        if(totalspawned == 1 && time > game_starttime) // only one player active on server, start a new match immediately
        if(!next_round && warmup && (time < warmup - autocvar_g_freezetag_warmup || time > warmup)) // not awaiting next round
@@ -174,7 +201,7 @@ MUTATOR_HOOKFUNCTION(freezetag_PlayerSpawn)
        if(warmup && time > warmup) // spawn too late, freeze player
        {
                centerprint(self, "^1You spawned after the round started, you'll spawn as frozen.\n");
-               freezetag_Freeze();
+               freezetag_Freeze(world);
        }
 
        return 1;
@@ -217,11 +244,33 @@ MUTATOR_HOOKFUNCTION(freezetag_PlayerPreThink)
             self.freezetag_revive_progress = (time - self.freezetag_beginrevive_time) / autocvar_g_freezetag_revive_time;
             if(time - self.freezetag_beginrevive_time >= autocvar_g_freezetag_revive_time)
             {
-                freezetag_Unfreeze();
+                freezetag_Unfreeze(self);
+               
+               // EVERY team mate nearby gets a point (even if multiple!)
+               float n;
+               FOR_EACH_PLAYER(other) if(self != other)
+               {
+                       if(other.freezetag_frozen == 0)
+                       {
+                               if(other.team == self.team)
+                               {
+                                       teammate_nearby = boxesoverlap(self.absmin - revive_extra_size, self.absmax + revive_extra_size, other.absmin, other.absmax);
+                                       if(teammate_nearby)
+                                       {
+                                               PlayerScore_Add(other, SP_FREEZETAG_REVIVALS, +1);
+                                               PlayerScore_Add(other, SP_SCORE, +1);
+                                               ++n;
+                                       }
+                               }
+                       }
+               }
 
-                centerprint(self, strcat("^5You were revived by ^7", other.netname, ".\n"));
-                centerprint(other, strcat("^5You revived ^7", self.netname, ".\n"));
-                bprint("^7", other.netname, "^5 revived ^7", self.netname, ".\n");
+               if(n > 1)
+                       centerprint(self, strcat("^5You were revived by ^7", other.netname, "^5 et al.\n"));
+               else
+                       centerprint(self, strcat("^5You were revived by ^7", other.netname, "^5.\n"));
+                centerprint(other, strcat("^5You revived ^7", self.netname, "^5.\n"));
+                bprint("^7", other.netname, "^5 revived ^7", self.netname, "^5.\n");
 
                 self.freezetag_beginrevive_time = -9999;
                 self.freezetag_revive_progress = 0;
@@ -253,7 +302,10 @@ MUTATOR_HOOKFUNCTION(freezetag_PlayerPreThink)
 MUTATOR_HOOKFUNCTION(freezetag_PlayerPhysics)
 {
        if(self.freezetag_frozen)
+       {
                self.movement = '0 0 0';
+               self.disableclientprediction = 1;
+       }
        return 1;
 }