]> git.rm.cloudns.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge branch 'master' into TimePath/gametypes/infection
authorTimePath <andrew.hardaker1995@gmail.com>
Sat, 12 Mar 2016 05:34:48 +0000 (16:34 +1100)
committerTimePath <andrew.hardaker1995@gmail.com>
Sat, 12 Mar 2016 05:59:47 +0000 (16:59 +1100)
1  2 
gamemodes.cfg
qcsrc/client/hud/panel/modicons.qc
qcsrc/common/mapinfo.qc
qcsrc/common/mapinfo.qh
qcsrc/menu/xonotic/util.qc
qcsrc/server/mutators/mutator/gamemode_infection.qc

diff --cc gamemodes.cfg
Simple merge
Simple merge
index 73bf7b7c652dc82f02b2b4b128640e0df35dd541,d853eeac3cc2fe690d164226c8757c096f61f280..92f3f1200d11b4b630adf8517a83be44c3e0e39c
@@@ -1150,10 -1143,10 +1150,10 @@@ float MapInfo_Get_ByName_NoFallbacks(st
        MapInfo_Cache_Store();
        if(MapInfo_Map_supportedGametypes != 0)
                return r;
-       LOG_TRACE("Map ", pFilename, " supports no game types, ignored\n");
+       LOG_MAPWARN("Map ", pFilename, " supports no game types, ignored\n");
        return 0;
  }
 -float MapInfo_Get_ByName(string pFilename, float pAllowGenerate, int pGametypeToSet)
 +float MapInfo_Get_ByName(string pFilename, bool pAllowGenerate, int pGametypeToSet)
  {
        float r = MapInfo_Get_ByName_NoFallbacks(pFilename, pAllowGenerate, pGametypeToSet);
  
Simple merge
Simple merge
index 3fb2a03c2fb66c9bc02a8736cbf6772ed41ae0c1,0000000000000000000000000000000000000000..80ff18ea437328e03949cd0a207c77253626a94b
mode 100644,000000..100644
--- /dev/null
@@@ -1,286 -1,0 +1,273 @@@
-       entity e;
-       FOR_EACH_PLAYER(e)
-       {
-               if (me.infectioncolor == e.infectioncolor_original)
-               {
-                       color_owner_green = sprintf("%s^2's", e.netname);
-                       color_owner_red = sprintf("%s^1's", e.netname);
-                       break;
-               }
-       }
 +#ifdef IMPLEMENTATION
 +
 +float autocvar_g_infection_round_timelimit;
 +float autocvar_g_infection_warmup;
 +int autocvar_g_infection_teams;
 +bool autocvar_g_infection_conversions;
 +
 +int infection_players_count;
 +
 +.int infectioncolor;
 +.int infectioncolor_original;
 +
 +const int INFECTIONTEAM_NONE = -1;
 +const int INFECTIONTEAM_UNDEFINED = -2;
 +
 +// safe team comparisons
 +#define INF_SAMETEAM(a, b) (a.infectioncolor == b.infectioncolor)
 +#define INF_DIFFTEAM(a, b) (a.infectioncolor != b.infectioncolor)
 +
 +void infection_SetColor(entity e, int _color)
 +{
 +      e.infectioncolor = _color;
 +      setcolor(e, (_color << 4) | _color);
 +}
 +
 +string color_owner_green, color_owner_red;
 +// find whose color a player is carrying, true if it's his own, otherwise set color_owner_* to the other owner
 +void infection_GetColorOwner(entity me)
 +{
 +      if (me.infectioncolor == me.infectioncolor_original)
 +      {
 +              color_owner_green = "^2your own";
 +              color_owner_red = "^1their own";
 +              return;
 +      }
-               entity e;
-               FOR_EACH_PLAYER(e)
-               {
++      FOREACH_CLIENT(IS_PLAYER(it) && me.infectioncolor == it.infectioncolor_original, {
++        color_owner_green = sprintf("%s^2's", it.netname);
++        color_owner_red = sprintf("%s^1's", it.netname);
++        break;
++      });
 +}
 +
 +void infection_Assign(bool late)
 +{
++    SELFPARAM();
 +      if (!late)
 +      {
 +              int infection_coloridx = 0;
-                               e.infectioncolor_original = infection_coloridx;
-                       infection_SetColor(e, infection_coloridx++ % bound(0, autocvar_g_infection_teams, 15));
-               }
++              FOREACH_CLIENT(IS_PLAYER(it), {
 +                      if (infection_coloridx < autocvar_g_infection_teams)  // Limit alphas
-               entity e;
-               FOR_EACH_PLAYER(e)
-               {
-                       if (e == self || IS_OBSERVER(e)) continue;
-                       if (!skip-- > 0) break;
-               }
-               dprintf("[INFECTION] copying %s's color\n", e.netname);
++                              it.infectioncolor_original = infection_coloridx;
++                      infection_SetColor(it, infection_coloridx++ % bound(0, autocvar_g_infection_teams, 15));
++              });
 +      }
 +      else
 +      {
 +              // Spawn too late, give player a random color
 +              int color = 15;
 +              int skip = rint(random() * (infection_players_count - 1));  // Ignore self
-               self.infectioncolor_original = INFECTIONTEAM_NONE;  // Can't win if player didn't spawn during the round delay
-               infection_SetColor(self, color);
++              entity e = NULL;
++              FOREACH_CLIENT(IS_PLAYER(it), {
++                      if (it == this || IS_OBSERVER(it)) continue;
++                      if (!skip-- > 0) {
++                          e = it;
++                break;
++                      }
++              });
++              LOG_DEBUGF("[INFECTION] copying %s's color", e.netname);
 +              color = e.infectioncolor;
-       entity e;
-       FOR_EACH_PLAYER(e)
-       {
++              this.infectioncolor_original = INFECTIONTEAM_NONE;  // Can't win if player didn't spawn during the round delay
++              infection_SetColor(this, color);
 +      }
 +}
 +
 +bool infection_CheckTeams()
 +{
 +      return infection_players_count > 1;
 +}
 +
 +bool infection_CheckWinner()
 +{
 +      if (infection_players_count <= 1) return false;                           // There can be no winner
 +
 +      if (0 < round_handler_GetEndTime() && round_handler_GetEndTime() <= time) // Round over
 +      {
 +              Send_Notification(NOTIF_ALL, world, MSG_CENTER, CENTER_ROUND_OVER);
 +              Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_ROUND_OVER);
 +              round_handler_Init(5, autocvar_g_infection_warmup, autocvar_g_infection_round_timelimit);
 +              return true;
 +      }
 +
 +      // Check if only one color remains
 +      int previnfectioncolor = -1;
 +      bool we_have_a_winner = true;  // until loop below proves us wrong
-               if (previnfectioncolor != -1 && previnfectioncolor != e.infectioncolor)
++      FOREACH_CLIENT(IS_PLAYER(it), {
 +              // All infection colors are the same if we have a winner
-               previnfectioncolor = e.infectioncolor;
-       }
++              if (previnfectioncolor != -1 && previnfectioncolor != it.infectioncolor)
 +              {
 +                      // In this case we still have more than one color alive
 +                      we_have_a_winner = false;
 +                      break;
 +              }
-       FOR_EACH_PLAYER(e)
-       {
-               if (e.infectioncolor == e.infectioncolor_original)
-               {
-                       UpdateFrags(e, 10);  // Bonus points
-                       Send_Notification(NOTIF_ALL, world, MSG_CENTER, CENTER_ROUND_PLAYER_WIN, e.netname);
-                       Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_ROUND_PLAYER_WIN, e.netname);
-               }
-       }
++              previnfectioncolor = it.infectioncolor;
++      });
 +
 +      if (!we_have_a_winner) return false;
 +
 +      // Who is it?
-       if (!IS_PLAYER(self)) return true;  // Wasn't playing
++      FOREACH_CLIENT(IS_PLAYER(it) && it.infectioncolor == it.infectioncolor_original, {
++        UpdateFrags(it, 10);  // Bonus points
++        Send_Notification(NOTIF_ALL, world, MSG_CENTER, CENTER_ROUND_PLAYER_WIN, it.netname);
++        Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_ROUND_PLAYER_WIN, it.netname);
++      });
 +
 +      round_handler_Init(5, autocvar_g_infection_warmup, autocvar_g_infection_round_timelimit);
 +      return true;
 +}
 +
 +void infection_RoundStart()
 +{
 +      infection_Assign(false);
 +      infection_CheckWinner();
 +}
 +
 +MUTATOR_HOOKFUNCTION(inf, PlayerDies)
 +{
 +      infection_CheckWinner();
 +      return true;
 +}
 +
 +bool inf_RemovePlayer();
 +MUTATOR_HOOKFUNCTION(inf, MakePlayerObserver)
 +{
 +      return inf_RemovePlayer();
 +}
 +MUTATOR_HOOKFUNCTION(inf, ClientDisconnect)
 +{
 +      return inf_RemovePlayer();
 +}
 +bool inf_RemovePlayer()
 +{
-       self.infectioncolor_original = INFECTIONTEAM_UNDEFINED;
++    SELFPARAM();
++      if (!IS_PLAYER(this)) return true;  // Wasn't playing
 +
 +      infection_players_count--;
 +
-       entity e;
-       FOR_EACH_PLAYER(e)
-       {
-               if (e.infectioncolor == self.infectioncolor_original)
-               {
-                       e.infectioncolor_original = self.infectioncolor;
-                       centerprint(e, "^2You are now an alpha.\n");
-                       break;
-               }
-       }
++      this.infectioncolor_original = INFECTIONTEAM_UNDEFINED;
 +
 +      // Grant alpha status to next of kin
-       if (self.infectioncolor_original != INFECTIONTEAM_UNDEFINED) return true;  // Wasn't observing
++      FOREACH_CLIENT(IS_PLAYER(it) && it.infectioncolor == this.infectioncolor_original, {
++        it.infectioncolor_original = this.infectioncolor;
++        centerprint(it, "^2You are now an alpha.\n");
++        break;
++      });
 +
 +      infection_CheckWinner();
 +      return true;
 +}
 +
 +MUTATOR_HOOKFUNCTION(inf, PlayerSpawn)
 +{
-               entity e;
-               FOR_EACH_PLAYER(e)                    // check other players...
-               {
-                       if (INF_SAMETEAM(e, frag_target)) // And see if they have our original infection color
-                       {  // If so, remove it, our infection color has now "died out" from this round and we can not win anymore.
-                               // The attacker will "summon" all of our previously fragged targets, and also us.
-                               centerprint(e, sprintf("^1Your alpha ^7%s^1 was infected by ^7%s^1 with ^7%s^1 color.\n",
-                                       frag_target.netname, frag_attacker.netname, color_owner_red));
-                               infection_SetColor(e, frag_attacker.infectioncolor);
-                               frag_score++;
-                       }
-               }
++    SELFPARAM();
++      if (this.infectioncolor_original != INFECTIONTEAM_UNDEFINED) return true;  // Wasn't observing
 +      infection_players_count++;
 +
 +      infection_Assign(true);
 +
 +      return true;
 +}
 +
 +MUTATOR_HOOKFUNCTION(inf, GiveFragsForKill, CBC_ORDER_FIRST)
 +{
 +      frag_score = 0;
 +      infection_GetColorOwner(frag_attacker);
 +      // If this is the first time we die... (our infectioncolor remained unchanged)
 +      if (autocvar_g_infection_conversions && frag_target.infectioncolor == frag_target.infectioncolor_original)
 +      {
-       if (IS_PLAYER(self))
++          // check other players and see if they have our original infection color
++              FOREACH_CLIENT(IS_PLAYER(it) && INF_SAMETEAM(it, frag_target), {
++            // If so, remove it, our infection color has now "died out" from this round and we can not win anymore.
++            // The attacker will "summon" all of our previously fragged targets, and also us.
++            centerprint(it, sprintf("^1Your alpha ^7%s^1 was infected by ^7%s^1 with ^7%s^1 color.\n",
++                frag_target.netname, frag_attacker.netname, color_owner_red));
++            infection_SetColor(it, frag_attacker.infectioncolor);
++            frag_score++;
++              });
 +      }
 +      else
 +      {
 +              infection_SetColor(frag_target, frag_attacker.infectioncolor);
 +              frag_score++;
 +      }
 +
 +      string target = frag_target.netname, attacker = frag_attacker.netname;
 +
 +      centerprint(frag_attacker, sprintf("^2You infected ^7%s^2 with ^7%s^2 color.\n", target, color_owner_green));
 +      centerprint(frag_target, sprintf("^1You were infected by ^7%s^1 with ^7%s^1 color.\n", attacker, color_owner_red));
 +
 +      bprint(sprintf("^7%s^1 was infected by ^7%s^1 with ^7%s^1 color.\n", frag_target.netname, attacker,
 +              color_owner_red));
 +
 +      return true;
 +}
 +
 +MUTATOR_HOOKFUNCTION(inf, PlayerPreThink, CBC_ORDER_FIRST)
 +{
-               infection_SetColor(self, round_handler_IsRoundStarted()
-                       ? self.infectioncolor : 15
-                                 );
++    SELFPARAM();
++      if (IS_PLAYER(this))
 +      {
 +              // Prevent cheating by changing player colors
-       return INF_SAMETEAM(checkentity, self);
++              infection_SetColor(this, round_handler_IsRoundStarted()
++                      ? this.infectioncolor
++                      : 15);
 +      }
 +      return true;
 +}
 +
 +MUTATOR_HOOKFUNCTION(inf, PlayerDamage_Calculate)
 +{
 +      if (IS_PLAYER(frag_attacker)                    // Allow environment damage
 +          && frag_attacker != frag_target             // Allow self damage
 +          && INF_SAMETEAM(frag_attacker, frag_target) // Block friendly fire
 +         )
 +      {
 +              frag_damage = 0;
 +              frag_force = '0 0 0';
 +      }
 +      return false;
 +}
 +
 +MUTATOR_HOOKFUNCTION(inf, BotShouldAttack)
 +{
-       self.infectioncolor_original = INFECTIONTEAM_UNDEFINED;
-       stuffcmd(self, "settemp cl_forceplayercolors 0\n");
++    SELFPARAM();
++      return INF_SAMETEAM(checkentity, this);
 +}
 +
 +MUTATOR_HOOKFUNCTION(inf, ClientConnect)
 +{
++    SELFPARAM();
++      this.infectioncolor_original = INFECTIONTEAM_UNDEFINED;
++      stuffcmd(this, "settemp cl_forceplayercolors 0\n");
 +
 +      return false;
 +}
 +
 +REGISTER_MUTATOR(inf, false)
 +{
 +      MUTATOR_ONADD
 +      {
 +              if (time > 1)  // game loads at time 1
 +                      error("This is a game type and it cannot be added at runtime.");
 +              infection_players_count = 0;
 +              round_handler_Spawn(infection_CheckTeams, infection_CheckWinner, infection_RoundStart);
 +              round_handler_Init(5, autocvar_g_infection_warmup, autocvar_g_infection_round_timelimit);
 +      }
 +
 +      MUTATOR_ONROLLBACK_OR_REMOVE
 +      {
 +              // we actually cannot roll back inf_Initialize here
 +              // BUT: we don't need to! If this gets called, adding always
 +              // succeeds.
 +      }
 +
 +      MUTATOR_ONREMOVE
 +      {
 +              print("This is a game type and it cannot be removed at runtime.");
 +              return -1;
 +      }
 +
 +      return 0;
 +}
 +
 +#endif