]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge branch 'master' into terencehill/ft_autorevive_progress
authorterencehill <piuntn@gmail.com>
Fri, 12 Jun 2020 20:12:04 +0000 (22:12 +0200)
committerterencehill <piuntn@gmail.com>
Fri, 12 Jun 2020 20:12:04 +0000 (22:12 +0200)
1  2 
gamemodes-server.cfg
qcsrc/common/gamemodes/gamemode/freezetag/sv_freezetag.qc
qcsrc/common/gamemodes/gamemode/freezetag/sv_freezetag.qh
qcsrc/server/g_damage.qc
qcsrc/server/player.qc

diff --combined gamemodes-server.cfg
index d5eb85d649c63a5aceb34186c9338f5b1e03333b,b1631b2333f56e6ba6ad1d9290fd89f0f77cddb8..fba19aabae067407635f874fe69ece0aae11a4c7
@@@ -29,7 -29,9 +29,9 @@@ alias sv_hook_gamestart_k
  alias sv_hook_gamestart_ft
  alias sv_hook_gamestart_inv
  alias sv_hook_gamestart_duel
- alias sv_hook_gamerestart
+ // there is currently no hook for when the match is restarted
+ // see sv_hook_readyrestart for previous uses of this hook
+ //alias sv_hook_gamerestart
  alias sv_hook_gameend
  
  
@@@ -74,7 -76,7 +76,7 @@@ alias sv_vote_gametype_hook_due
  // ===========
  // this means that timelimit can be overidden globally and fraglimit can be overidden for each game mode: DM/TDM, Domination, CTF, and Runematch.
  set leadlimit 0
- set leadlimit_and_fraglimit 0 "if set, leadlimit is ANDed with fraglimit (otherwise ORed)"
+ set leadlimit_and_fraglimit 0 "both leadlimit AND fraglimit must be reached"
  set timelimit_override -1     "Time limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
  set fraglimit_override -1     "Frag limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
  set leadlimit_override -1     "Lead limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
@@@ -245,6 -247,8 +247,8 @@@ set g_ctf_flag_return_dropped 100 "auto
  set g_ctf_flag_return_damage 0 "allow the flag to be damaged, reducing time needed to automatically return to base"
  set g_ctf_flag_return_damage_delay 0 "how much time the flag takes to automatically return to base if it falls into lava/slime/trigger hurt"
  set g_ctf_flag_return_when_unreachable 1 "automatically return the flag if it falls into lava/slime/trigger hurt"
+ set g_ctf_flag_waypoint 1 "show a waypoint at the flag for easy discovery and directions"
+ set g_ctf_flag_waypoint_maxdistance 0 "maximum distance from a flag from which their waypoint is shown, a value of 0 means no limit"
  set g_ctf_flagcarrier_auto_helpme_damage 100 "automatically place a helpme notification on flag carrier waypointsprite if they get hit and their health dips below this value"
  set g_ctf_flagcarrier_auto_helpme_time 2 "antispam time for the helpme notification"
  set g_ctf_flagcarrier_selfdamagefactor 1
@@@ -307,7 -311,7 +311,7 @@@ set g_ctf_flag_neutral_model "models/ct
  set g_ctf_flag_neutral_skin 4
  set g_ctf_flag_glowtrails 1
  set g_ctf_fullbrightflags 0
- set g_ctf_dynamiclights 0
+ set g_ctf_dynamiclights 0 "flags (not flag carriers) cast light of their team's colour"
  
  set g_ctf_ignore_frags 0      "1: regular frags give no points"
  exec ctfscoring-samual.cfg
@@@ -368,10 -372,6 +372,10 @@@ set g_freezetag_revive_extra_size 100 "
  set g_freezetag_revive_nade 1 "Enable reviving from own nade explosion"
  set g_freezetag_revive_nade_health 40 "Amount of health player has if they revived from their own nade explosion"
  set g_freezetag_round_timelimit 360 "round time limit in seconds"
 +set g_freezetag_revive_auto 1 "automatically revive frozen players after some time (g_freezetag_frozen_maxtime)"
 +set g_freezetag_revive_auto_progress 1 "start the automatic reviving progress as soon as the player gets frozen"
 +set g_freezetag_revive_auto_reducible 1 "reduce auto-revival time when frozen players are hit by enemies; if cvar value is negative reduce time even when they are hit by teammates"
 +set g_freezetag_revive_auto_reducible_forcefactor 0.025 "hit force to time reduction conversion factor"
  set g_freezetag_frozen_maxtime 60 "frozen players will be automatically unfrozen after this time in seconds"
  set g_freezetag_teams_override 0
  set g_freezetag_team_spawns 0 "when 1, players spawn from the team spawnpoints of the map, if any"
index 8e9f06a099d32ae4fac91292c0a889d013594530,360dc7a4ea8bb1f15ca4274c6ad2225a9625cf75..2a931fa975f8931b7b6759e5b7a4500033e93d91
@@@ -130,7 -130,7 +130,7 @@@ bool freezetag_CheckWinner(
        {
                Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, APP_TEAM_NUM(winner_team, CENTER_ROUND_TEAM_WIN));
                Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(winner_team, INFO_ROUND_TEAM_WIN));
-               TeamScore_AddToTeam(winner_team, ST_SCORE, +1);
+               TeamScore_AddToTeam(winner_team, ST_FT_ROUNDS, +1);
        }
        else if(winner_team == -1)
        {
@@@ -198,8 -198,7 +198,8 @@@ void freezetag_Freeze(entity targ, enti
        if(STAT(FROZEN, targ))
                return;
  
 -      if(autocvar_g_freezetag_frozen_maxtime > 0)
 +      targ.freezetag_frozen_time = time;
 +      if (autocvar_g_freezetag_revive_auto && autocvar_g_freezetag_frozen_maxtime > 0)
                targ.freezetag_frozen_timeout = time + autocvar_g_freezetag_frozen_maxtime;
  
        Freeze(targ, 0, FROZEN_NORMAL, true);
@@@ -367,6 -366,9 +367,9 @@@ MUTATOR_HOOKFUNCTION(ft, PlayerDies
                return true;
        }
  
+       frag_target.respawn_time = time + 1;
+       frag_target.respawn_flags |= RESPAWN_FORCE;
        // Cases DEATH_TEAMCHANGE and DEATH_AUTOTEAMCHANGE are needed to fix a bug whe
        // you succeed changing team through the menu: you both really die (gibbing) and get frozen
        if(ITEM_DAMAGE_NEEDKILL(frag_deathtype)
@@@ -455,30 -457,6 +458,30 @@@ MUTATOR_HOOKFUNCTION(ft, Unfreeze
        targ.freezetag_frozen_timeout = 0;
  }
  
 +MUTATOR_HOOKFUNCTION(ft, Damage_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);
 +      vector frag_force = M_ARGV(6, vector);
 +
 +      if (STAT(FROZEN, frag_target) == FROZEN_NORMAL && autocvar_g_freezetag_revive_auto_reducible
 +              && autocvar_g_freezetag_frozen_maxtime > 0 && autocvar_g_freezetag_revive_auto)
 +      {
 +              float t = 0;
 +              if ((autocvar_g_freezetag_revive_auto_reducible > 0 || DIFF_TEAM(frag_attacker, frag_target))
 +                      && frag_target.freezetag_frozen_timeout > time)
 +              {
 +                      if (fabs(autocvar_g_freezetag_revive_auto_reducible) == 1)
 +                              t = vlen(frag_force) * autocvar_g_freezetag_revive_auto_reducible_forcefactor;
 +                      frag_target.freezetag_frozen_timeout -= t;
 +                      if (frag_target.freezetag_frozen_timeout < time)
 +                              frag_target.freezetag_frozen_timeout = time;
 +              }
 +      }
 +}
 +
  #ifdef IS_REVIVING
        #undef IS_REVIVING
  #endif
@@@ -497,66 -475,59 +500,68 @@@ MUTATOR_HOOKFUNCTION(ft, PlayerPreThink
        if(!round_handler_IsRoundStarted())
                return true;
  
-       int n;
        entity player = M_ARGV(0, entity);
        //if (STAT(FROZEN, player) == FROZEN_NORMAL)
        //if(player.freezetag_frozen_timeout > 0 && time < player.freezetag_frozen_timeout)
                //player.iceblock.alpha = ICE_MIN_ALPHA + (ICE_MAX_ALPHA - ICE_MIN_ALPHA) * (player.freezetag_frozen_timeout - time) / (player.freezetag_frozen_timeout - player.freezetag_frozen_time);
  
+       if (!(frametime && IS_PLAYER(player)))
+               return true;
        entity reviving_players_last = NULL;
        entity reviving_players_first = NULL;
  
-       if(player.freezetag_frozen_timeout > 0 && time >= player.freezetag_frozen_timeout)
-               n = -1;
-       else
-       {
-               n = 0;
-               vector revive_extra_size = '1 1 1' * autocvar_g_freezetag_revive_extra_size;
-               FOREACH_CLIENT(IS_PLAYER(it) && IS_REVIVING(player, it, revive_extra_size), {
-                       if (reviving_players_last)
-                               reviving_players_last.chain = it;
-                       reviving_players_last = it;
-                       if (!reviving_players_first)
-                               reviving_players_first = it;
-                       ++n;
-               });
+       int n = 0;
+       vector revive_extra_size = '1 1 1' * autocvar_g_freezetag_revive_extra_size;
+       FOREACH_CLIENT(IS_PLAYER(it) && IS_REVIVING(player, it, revive_extra_size), {
                if (reviving_players_last)
-                       reviving_players_last.chain = NULL;
-       }
+                       reviving_players_last.chain = it;
+               reviving_players_last = it;
+               if (!reviving_players_first)
+                       reviving_players_first = it;
+               ++n;
+       });
+       if (reviving_players_last)
+               reviving_players_last.chain = NULL;
+       // allow normal revival during automatic revival
+       // (not allowing it IS_REVIVING should check freezetag_frozen_timeout too)
+       if (!n && player.freezetag_frozen_timeout > 0 && time >= player.freezetag_frozen_timeout)
+               n = -1;
  
 +      float base_progress = 0;
 +      if  (STAT(FROZEN, player) == FROZEN_NORMAL && autocvar_g_freezetag_revive_auto
 +              && autocvar_g_freezetag_frozen_maxtime > 0 && autocvar_g_freezetag_revive_auto_progress)
 +      {
 +              // NOTE if auto-revival is in progress, manual revive speed is reduced so that it always takes the same amount of time
 +              base_progress = bound(0, (1 - (player.freezetag_frozen_timeout - time) / autocvar_g_freezetag_frozen_maxtime), 1);
 +      }
 +
        if (!n) // no teammate nearby
        {
                if (STAT(FROZEN, player) == FROZEN_NORMAL)
                {
 -                      STAT(REVIVE_PROGRESS, player) = bound(0, STAT(REVIVE_PROGRESS, player) - frametime * autocvar_g_freezetag_revive_clearspeed, 1);
 +                      STAT(REVIVE_PROGRESS, player) = bound(base_progress, STAT(REVIVE_PROGRESS, player) - frametime * autocvar_g_freezetag_revive_clearspeed * (1 - base_progress), 1);
                        SetResourceExplicit(player, RES_HEALTH, max(1, STAT(REVIVE_PROGRESS, player) * ((warmup_stage) ? warmup_start_health : start_health)));
                }
                else if (!STAT(FROZEN, player))
 -                      STAT(REVIVE_PROGRESS, player) = 0; // thawing nobody
 +                      STAT(REVIVE_PROGRESS, player) = base_progress; // thawing nobody
        }
        else if (STAT(FROZEN, player) == FROZEN_NORMAL) // OK, there is at least one teammate reviving us
        {
 -              STAT(REVIVE_PROGRESS, player) = bound(0, STAT(REVIVE_PROGRESS, player) + frametime * max(1/60, autocvar_g_freezetag_revive_speed), 1);
 +              STAT(REVIVE_PROGRESS, player) = bound(base_progress, STAT(REVIVE_PROGRESS, player) + frametime * max(1/60, autocvar_g_freezetag_revive_speed * (1 - base_progress)), 1);
                SetResourceExplicit(player, RES_HEALTH, max(1, STAT(REVIVE_PROGRESS, player) * ((warmup_stage) ? warmup_start_health : start_health)));
  
                if(STAT(REVIVE_PROGRESS, player) >= 1)
                {
 +                      float frozen_time = time - player.freezetag_frozen_time;
                        Unfreeze(player, false);
                        freezetag_count_alive_players();
  
                        if(n == -1)
                        {
 -                              Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_FREEZETAG_AUTO_REVIVED, autocvar_g_freezetag_frozen_maxtime);
 -                              Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_FREEZETAG_AUTO_REVIVED, player.netname, autocvar_g_freezetag_frozen_maxtime);
 +                              Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_FREEZETAG_AUTO_REVIVED, frozen_time);
 +                              Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_FREEZETAG_AUTO_REVIVED, player.netname, frozen_time);
                                return true;
                        }
  
@@@ -651,6 -622,12 +656,12 @@@ MUTATOR_HOOKFUNCTION(ft, SV_ParseServer
        return false;
  }
  
+ MUTATOR_HOOKFUNCTION(ft, Scores_CountFragsRemaining)
+ {
+       // announce remaining frags
+       return true;
+ }
  void freezetag_Initialize()
  {
        freezetag_teams = autocvar_g_freezetag_teams_override;
  
        freezetag_teams = BITS(bound(2, freezetag_teams, 4));
        GameRules_scoring(freezetag_teams, SFL_SORT_PRIO_PRIMARY, SFL_SORT_PRIO_PRIMARY, {
+               field_team(ST_FT_ROUNDS, "rounds", SFL_SORT_PRIO_PRIMARY);
                field(SP_FREEZETAG_REVIVALS, "revivals", 0);
        });
  
index b187b3802dabfb99655160b669940ea1e29d5423,b77318ca2e808d8929caa9996e184e293b3b6be5..43ceede6ee8d384c2d16d897ffabf2ab5f4e7068
@@@ -8,6 -8,8 +8,8 @@@ int autocvar_g_freezetag_point_leadlimi
  bool autocvar_g_freezetag_team_spawns;
  string autocvar_g_freezetag_weaponarena = "most_available";
  
+ const int ST_FT_ROUNDS = 1;
  void freezetag_Initialize();
  
  REGISTER_MUTATOR(ft, false)
@@@ -31,10 -33,6 +33,10 @@@ const float ICE_MAX_ALPHA = 1
  const float ICE_MIN_ALPHA = 0.1;
  float freezetag_teams;
  
 +bool autocvar_g_freezetag_revive_auto = 1;
 +int autocvar_g_freezetag_revive_auto_progress = 1;
 +int autocvar_g_freezetag_revive_auto_reducible;
 +float autocvar_g_freezetag_revive_auto_reducible_forcefactor;
  float autocvar_g_freezetag_revive_extra_size;
  float autocvar_g_freezetag_revive_speed;
  bool autocvar_g_freezetag_revive_nade;
diff --combined qcsrc/server/g_damage.qc
index d375baa440d41328f318fa8ccfa307757daea696,e5363db7738fd9a79b5206fbcaa0262110350a49..106198f5f731e63b85c44df636a739b5da43f189
@@@ -85,9 -85,9 +85,9 @@@ string AppendItemcodes(string s, entit
                if(w != 0 || slot == 0)
                        s = strcat(s, ftos(w));
        }
-       if(time < player.strength_finished)
+       if(time < STAT(STRENGTH_FINISHED, player))
                s = strcat(s, "S");
-       if(time < player.invincible_finished)
+       if(time < STAT(INVINCIBLE_FINISHED, player))
                s = strcat(s, "I");
        if(PHYS_INPUT_BUTTON_CHAT(player))
                s = strcat(s, "T");
@@@ -129,7 -129,7 +129,7 @@@ void Obituary_SpecialDeath
                return;
        }
  
-       entity deathent = Deathtypes_from(deathtype - DT_FIRST);
+       entity deathent = REGISTRY_GET(Deathtypes, deathtype - DT_FIRST);
        if (!deathent)
        {
                backtrace("Obituary_SpecialDeath: Could not find deathtype entity!\n");
@@@ -199,9 -199,9 +199,9 @@@ float Obituary_WeaponDeath
        else
        {
                LOG_TRACEF(
-                       "Obituary_WeaponDeath(): ^1Deathtype ^7(%d)^1 has no notification for weapon %d!\n",
+                       "Obituary_WeaponDeath(): ^1Deathtype ^7(%d)^1 has no notification for weapon %s!\n",
                        deathtype,
-                       death_weapon
+                       death_weapon.netname
                );
        }
  
@@@ -610,7 -610,7 +610,7 @@@ void Damage(entity targ, entity inflict
                                damage = 0;
                                force = '0 0 0';
                        }
 -                      else if(SAME_TEAM(attacker, targ))
 +                      else if(!STAT(FROZEN, targ) && SAME_TEAM(attacker, targ))
                        {
                                if(autocvar_teamplay_mode == 1)
                                        damage = 0;
                    }
                }
  
-               if(deathtype != DEATH_HURTTRIGGER.m_id && deathtype != DEATH_TEAMCHANGE.m_id && deathtype != DEATH_AUTOTEAMCHANGE.m_id && STAT(FROZEN, targ))
+               if(STAT(FROZEN, targ) && !ITEM_DAMAGE_NEEDKILL(deathtype)
+                       && deathtype != DEATH_TEAMCHANGE.m_id && deathtype != DEATH_AUTOTEAMCHANGE.m_id)
                {
                        if(autocvar_g_frozen_revive_falldamage > 0 && deathtype == DEATH_FALL.m_id && damage >= autocvar_g_frozen_revive_falldamage)
                        {
                        force *= autocvar_g_frozen_force;
                }
  
-               if(IS_PLAYER(targ) && STAT(FROZEN, targ) && deathtype == DEATH_HURTTRIGGER.m_id && !autocvar_g_frozen_damage_trigger)
+               if(IS_PLAYER(targ) && STAT(FROZEN, targ)
+                       && ITEM_DAMAGE_NEEDKILL(deathtype) && !autocvar_g_frozen_damage_trigger)
                {
                        Send_Effect(EFFECT_TELEPORT, targ.origin, '0 0 0', 1);
  
-                       entity spot = SelectSpawnPoint (targ, false);
+                       entity spot = SelectSpawnPoint(targ, false);
                        if(spot)
                        {
                                damage = 0;
  
                        if(IS_PLAYER(victim) || (IS_TURRET(victim) && victim.active == ACTIVE_ACTIVE) || IS_MONSTER(victim) || MUTATOR_CALLHOOK(PlayHitsound, victim, attacker))
                        {
 -                              if(DIFF_TEAM(victim, attacker) && !STAT(FROZEN, victim))
 +                              if (DIFF_TEAM(victim, attacker))
                                {
                                        if(damage > 0)
                                        {
                                                }
                                        }
                                }
 -                              else if(IS_PLAYER(attacker))
 +                              else if (IS_PLAYER(attacker) && !STAT(FROZEN, victim)) // same team
                                {
 -                                      // if enemy gets frozen in this frame and receives other damage don't
 -                                      // play the typehitsound e.g. when hit by multiple bullets of the shotgun
 -                                      if (deathtype != DEATH_FIRE.m_id && (!STAT(FROZEN, victim) || time > victim.freeze_time))
 +                                      if (deathtype != DEATH_FIRE.m_id)
                                        {
                                                attacker.typehitsound += 1;
                                        }
diff --combined qcsrc/server/player.qc
index 8dffbc8ba61fb96bbbe7572a21be2e08b26b3e85,e5a8f47f90f859908e0ba951776cbd71a3bbf854..62822f6f05e2631d19ea7bd0e2dc8e2af147b268
@@@ -369,7 -369,7 +369,7 @@@ void PlayerDamage(entity this, entity i
  
        if(attacker == this)
        {
-               // don't reset pushltime for this damage as it may be an attempt to
+               // don't reset pushltime for self damage as it may be an attempt to
                // escape a lava pit or similar
                //this.pushltime = 0;
                this.istypefrag = 0;
        if (take > 100)
                Violence_GibSplash_At(hitloc, force * -0.2, 3, 1, this, attacker);
  
 -      if (time >= this.spawnshieldtime || autocvar_g_spawnshield_blockdamage < 1)
 +      if ((time >= this.spawnshieldtime || autocvar_g_spawnshield_blockdamage < 1)
 +              && !STAT(FROZEN, this))
        {
                if (!(this.flags & FL_GODMODE))
                {
  
                        float realdmg = damage - excess;
                        if (this != attacker && realdmg)
+                       if (!(round_handler_IsActive() && !round_handler_IsRoundStarted()) && time >= game_starttime)
                        {
                                if (IS_PLAYER(attacker) && DIFF_TEAM(attacker, this)) {
                                        GameRules_scoring_add(attacker, DMG, realdmg);
        bool valid_damage_for_weaponstats = false;
        Weapon awep = WEP_Null;
  
+       if (!(round_handler_IsActive() && !round_handler_IsRoundStarted()) && time >= game_starttime)
        if(vbot || IS_REAL_CLIENT(this))
        if(abot || IS_REAL_CLIENT(attacker))
        if(attacker && this != attacker)
 -      if(DIFF_TEAM(this, attacker))
 +      if (DIFF_TEAM(this, attacker) && (!STAT(FROZEN, this) || this.freeze_time > time))
        {
                if(DEATH_ISSPECIAL(deathtype))
                        awep = attacker.(weaponentity).m_weapon;
                valid_damage_for_weaponstats = true;
        }
  
 -      dh = dh - max(GetResource(this, RES_HEALTH), 0);
 -      da = da - max(GetResource(this, RES_ARMOR), 0);
 +      dh -= max(GetResource(this, RES_HEALTH), 0); // health difference
 +      da -= max(GetResource(this, RES_ARMOR), 0); // armor difference
        if(valid_damage_for_weaponstats)
        {
                WeaponStats_LogDamage(awep.m_id, abot, this.(weaponentity).m_weapon.m_id, vbot, dh + da);