]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge branch 'master' into Lyberta/TeamplayOverhaul
authorLyberta <lyberta@lyberta.net>
Fri, 27 Apr 2018 09:22:48 +0000 (12:22 +0300)
committerLyberta <lyberta@lyberta.net>
Fri, 27 Apr 2018 09:22:48 +0000 (12:22 +0300)
1  2 
qcsrc/common/t_items.qc
qcsrc/server/client.qc
qcsrc/server/defs.qh
qcsrc/server/mutators/events.qh

diff --combined qcsrc/common/t_items.qc
index 8019e897b1f1ba244b4528771ae6c0f1a996c48d,039d27da351f284a3766d9684a6bbf2c45838b72..2f6b2151fe5829c8ee00f7bd92f7b4cdbae93e38
@@@ -151,6 -151,16 +151,16 @@@ void ItemRemove(entity this
        strfree(this.mdl);
  }
  
+ HashMap ENT_CLIENT_ITEM_simple;
+ STATIC_INIT(ENT_CLIENT_ITEM_simple)
+ {
+       HM_NEW(ENT_CLIENT_ITEM_simple);
+ }
+ SHUTDOWN(ENT_CLIENT_ITEM_simple)
+ {
+       HM_DELETE(ENT_CLIENT_ITEM_simple);
+ }
  NET_HANDLE(ENT_CLIENT_ITEM, bool isnew)
  {
      int sf = ReadByte();
  
                strfree(this.mdl);
  
-         this.mdl = "";
          string _fn = ReadString();
          this.item_simple = false; // reset it!
  
              string _fn2 = substring(_fn, 0 , strlen(_fn) -4);
              this.item_simple = true;
  
-             if(fexists(strcat(_fn2, autocvar_cl_simpleitems_postfix, ".md3")))
-                 this.mdl = strzone(strcat(_fn2, autocvar_cl_simpleitems_postfix, ".md3"));
-             else if(fexists(strcat(_fn2, autocvar_cl_simpleitems_postfix, ".dpm")))
-                 this.mdl = strzone(strcat(_fn2, autocvar_cl_simpleitems_postfix, ".dpm"));
-             else if(fexists(strcat(_fn2, autocvar_cl_simpleitems_postfix, ".iqm")))
-                 this.mdl = strzone(strcat(_fn2, autocvar_cl_simpleitems_postfix, ".iqm"));
-             else if(fexists(strcat(_fn2, autocvar_cl_simpleitems_postfix, ".mdl")))
-                 this.mdl = strzone(strcat(_fn2, autocvar_cl_simpleitems_postfix, ".mdl"));
-             else
-             {
-                 this.item_simple = false;
-                 LOG_TRACE("Simple item requested for ", _fn, " but no model exists for it");
-             }
+                       #define extensions(x) \
+                               x(md3) \
+                               x(dpm) \
+                               x(iqm) \
+                               x(mdl) \
+                               /**/
+                       #define tryext(ext) { \
+                               string s = strcat(_fn2, autocvar_cl_simpleitems_postfix, "." #ext); \
+                               string cached = HM_gets(ENT_CLIENT_ITEM_simple, s); \
+                               if (cached == "") { \
+                                       HM_sets(ENT_CLIENT_ITEM_simple, s, cached = fexists(s) ? "1" : "0"); \
+                               } \
+                               if (cached != "0") { \
+                                       strcpy(this.mdl, s); \
+                                       break; \
+                               } \
+                       }
+                       do {
+                               extensions(tryext);
+                               this.item_simple = false;
+                 LOG_TRACEF("Simple item requested for %s but no model exists for it", _fn);
+                       } while (0);
+                       #undef tryext
+                       #undef extensions
          }
  
          if(!this.item_simple)
-             this.mdl = strzone(_fn);
+             strcpy(this.mdl, _fn);
  
          if(this.mdl == "")
-             LOG_TRACE("^1WARNING!^7 this.mdl is unset for item ", this.classname, ", tell tZork about this!");
+             LOG_WARNF("this.mdl is unset for item %s", this.classname);
  
          precache_model(this.mdl);
          _setmodel(this, this.mdl);
@@@ -626,18 -645,14 +645,18 @@@ float adjust_respawntime(float normal_r
                return normal_respawntime;
        }
  
 -      CheckAllowedTeams(NULL);
 -      GetTeamCounts(NULL);
 +      entity balance = TeamBalance_CheckAllowedTeams(NULL);
 +      TeamBalance_GetTeamCounts(balance, NULL);
        int players = 0;
 -      if (c1 != -1) players += c1;
 -      if (c2 != -1) players += c2;
 -      if (c3 != -1) players += c3;
 -      if (c4 != -1) players += c4;
 -
 +      for (int i = 1; i <= NUM_TEAMS; ++i)
 +      {
 +              if (TeamBalance_IsTeamAllowed(balance, i))
 +              {
 +                      players += TeamBalance_GetNumberOfPlayers(balance, i);
 +              }
 +      }
 +      TeamBalance_Destroy(balance);
 +      
        if (players >= 2) {
                return normal_respawntime * (r / (players + o) + l);
        } else {
diff --combined qcsrc/server/client.qc
index ea53a6a4e809c56ac40dc1e7b28f969202f24cb7,d374876d0456441bc59fdf69fe683a643bb8d42a..097a9ad358329dbe138e33c4224e6290cf0c566e
@@@ -282,8 -282,10 +282,8 @@@ void PutObserverInServer(entity this
        if (mutator_returnvalue) {
            // mutator prevents resetting teams+score
        } else {
 -              int oldteam = this.team;
 -              this.team = -1;  // move this as it is needed to log the player spectating in eventlog
 -              MUTATOR_CALLHOOK(Player_ChangedTeam, this, oldteam, this.team);
 -        this.frags = FRAGS_SPECTATOR;
 +              Player_SetTeamIndex(this, -1);
 +              this.frags = FRAGS_SPECTATOR;
          PlayerScore_Clear(this);  // clear scores when needed
      }
  
                        Send_Notification(NOTIF_ONE_ONLY, this, MSG_INFO, INFO_CHAT_NOSPECTATORS);
  
                if(!CS(this).just_joined)
 -                      LogTeamchange(this.playerid, -1, 4);
 +                      LogTeamchange(this.playerid, -1, TEAM_CHANGE_SPECTATOR);
                else
                        CS(this).just_joined = false;
        }
@@@ -514,7 -516,7 +514,7 @@@ void PutPlayerInServer(entity this
        accuracy_resend(this);
  
        if (this.team < 0)
 -              JoinBestTeam(this, true);
 +              TeamBalance_JoinBestTeam(this, true);
  
        entity spot = SelectSpawnPoint(this, false);
        if (!spot) {
@@@ -901,7 -903,7 +901,7 @@@ void ClientKill_Now_TeamChange(entity t
  {
        if(this.killindicator_teamchange == -1)
        {
 -              JoinBestTeam( this, true );
 +              TeamBalance_JoinBestTeam(this, true);
        }
        else if(this.killindicator_teamchange == -2)
        {
@@@ -1159,76 -1161,6 +1159,76 @@@ void ClientPreConnect(entity this
  }
  #endif
  
 +string GetClientVersionMessage(entity this)
 +{
 +      if (CS(this).version_mismatch) {
 +              if(CS(this).version < autocvar_gameversion) {
 +                      return strcat("This is Xonotic ", autocvar_g_xonoticversion,
 +                              "\n^3Your client version is outdated.\n\n\n### YOU WON'T BE ABLE TO PLAY ON THIS SERVER ###\n\n\nPlease update!!!^8");
 +              } else {
 +                      return strcat("This is Xonotic ", autocvar_g_xonoticversion,
 +                              "\n^3This server is using an outdated Xonotic version.\n\n\n ### THIS SERVER IS INCOMPATIBLE AND THUS YOU CANNOT JOIN ###.^8");
 +              }
 +      } else {
 +              return strcat("Welcome to Xonotic ", autocvar_g_xonoticversion);
 +      }
 +}
 +
 +string getwelcomemessage(entity this)
 +{
 +      MUTATOR_CALLHOOK(BuildMutatorsPrettyString, "");
 +      string modifications = M_ARGV(0, string);
 +
 +      if(g_weaponarena)
 +      {
 +              if(g_weaponarena_random)
 +                      modifications = strcat(modifications, ", ", ftos(g_weaponarena_random), " of ", g_weaponarena_list, " Arena");
 +              else
 +                      modifications = strcat(modifications, ", ", g_weaponarena_list, " Arena");
 +      }
 +      else if(cvar("g_balance_blaster_weaponstartoverride") == 0)
 +              modifications = strcat(modifications, ", No start weapons");
 +      if(cvar("sv_gravity") < stof(cvar_defstring("sv_gravity")))
 +              modifications = strcat(modifications, ", Low gravity");
 +      if(g_weapon_stay && !g_cts)
 +              modifications = strcat(modifications, ", Weapons stay");
 +      if(g_jetpack)
 +              modifications = strcat(modifications, ", Jet pack");
 +      if(autocvar_g_powerups == 0)
 +              modifications = strcat(modifications, ", No powerups");
 +      if(autocvar_g_powerups > 0)
 +              modifications = strcat(modifications, ", Powerups");
 +      modifications = substring(modifications, 2, strlen(modifications) - 2);
 +
 +      string versionmessage = GetClientVersionMessage(this);
 +      string s = strcat(versionmessage, "^8\n^8\nmatch type is ^1", gamemode_name, "^8\n");
 +
 +      if(modifications != "")
 +              s = strcat(s, "^8\nactive modifications: ^3", modifications, "^8\n");
 +
 +      if(cache_lastmutatormsg != autocvar_g_mutatormsg)
 +      {
 +              strcpy(cache_lastmutatormsg, autocvar_g_mutatormsg);
 +              strcpy(cache_mutatormsg, cache_lastmutatormsg);
 +      }
 +
 +      if (cache_mutatormsg != "") {
 +              s = strcat(s, "\n\n^8special gameplay tips: ^7", cache_mutatormsg);
 +      }
 +
 +      string mutator_msg = "";
 +      MUTATOR_CALLHOOK(BuildGameplayTipsString, mutator_msg);
 +      mutator_msg = M_ARGV(0, string);
 +
 +      s = strcat(s, mutator_msg); // trust that the mutator will do proper formatting
 +
 +      string motd = autocvar_sv_motd;
 +      if (motd != "") {
 +              s = strcat(s, "\n\n^8MOTD: ^7", strreplace("\\n", "\n", motd));
 +      }
 +      return s;
 +}
 +
  /**
  =============
  ClientConnect
@@@ -1284,7 -1216,7 +1284,7 @@@ void ClientConnect(entity this
  
        int playerid_save = this.playerid;
        this.playerid = 0; // silent
 -      JoinBestTeam(this, false); // if the team number is valid, keep it
 +      TeamBalance_JoinBestTeam(this, false); // if the team number is valid, keep it
        this.playerid = playerid_save;
  
        if (autocvar_sv_spectate || autocvar_g_campaign || this.team_forced < 0) {
        if (autocvar_sv_eventlog)
                GameLogEcho(strcat(":join:", ftos(this.playerid), ":", ftos(etof(this)), ":", ((IS_REAL_CLIENT(this)) ? this.netaddress : "bot"), ":", playername(this, false)));
  
 -      LogTeamchange(this.playerid, this.team, 1);
 +      LogTeamchange(this.playerid, this.team, TEAM_CHANGE_CONNECT);
  
        CS(this).just_joined = true;  // stop spamming the eventlog with additional lines when the client connects
  
        // notify about available teams
        if (teamplay)
        {
 -              CheckAllowedTeams(this);
 -              int t = 0;
 -              if (c1 >= 0) t |= BIT(0);
 -              if (c2 >= 0) t |= BIT(1);
 -              if (c3 >= 0) t |= BIT(2);
 -              if (c4 >= 0) t |= BIT(3);
 +              entity balance = TeamBalance_CheckAllowedTeams(this);
 +              int t = TeamBalance_GetAllowedTeams(balance);
 +              TeamBalance_Destroy(balance);
                stuffcmd(this, sprintf("set _teams_available %d\n", t));
        }
        else
@@@ -1561,7 -1496,7 +1561,7 @@@ void player_powerups(entity this
        Fire_ApplyDamage(this);
        Fire_ApplyEffect(this);
  
-       if (!g_instagib)
+       if (!autocvar_g_instagib)
        {
                if (this.items & ITEM_Strength.m_itemid)
                {
@@@ -2075,7 -2010,7 +2075,7 @@@ void Join(entity this
  
        if(!this.team_selected)
        if(autocvar_g_campaign || autocvar_g_balance_teams)
 -              JoinBestTeam(this, true);
 +              TeamBalance_JoinBestTeam(this, true);
  
        if(autocvar_g_campaign)
                campaign_bots_may_start = true;
  
        if(IS_PLAYER(this))
        if(teamplay && this.team != -1)
 -              Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(this.team, INFO_JOIN_PLAY_TEAM), this.netname);
 +      {
 +              //Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(this.team, INFO_JOIN_PLAY_TEAM), this.netname);
 +      }
        else
                Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_JOIN_PLAY, this.netname);
        this.team_selected = false;
diff --combined qcsrc/server/defs.qh
index 03428b12b45ef00b67bf49a5090dae8958a68088,e005d0ca844eca9c9bcbfd0b15db6dd27ad820d2..9a01a79660e78dfd796e1fe6935ede8a8c9edf8b
@@@ -7,7 -7,7 +7,7 @@@
  
  // Globals
  
- float g_footsteps, g_grappling_hook, g_instagib;
+ float g_footsteps, g_grappling_hook;
  float g_warmup_allguns;
  float g_warmup_allow_timeout;
  float warmup_stage;
@@@ -27,6 -27,8 +27,6 @@@ float bots_would_leave
  void UpdateFrags(entity player, int f);
  .float totalfrags;
  
 -float team1_score, team2_score, team3_score, team4_score;
 -
  // flag set on worldspawn so that the code knows if it is dedicated or not
  float server_is_dedicated;
  
@@@ -229,6 -231,8 +229,6 @@@ void Damage (entity targ, entity inflic
  // WEAPONTODO
  #define DMG_NOWEP (weaponentities[0])
  
 -float lockteams;
 -
  float sv_maxidle;
  float sv_maxidle_spectatorsareidle;
  int sv_maxidle_slots;
index 9fbedfac4c18e6f171adcc82a577dff140620040,240f8fc25fac301033bee840e7bfcd1ce8cd0198..0757cdcf8a985d4cd124417cc055dea8570805d9
@@@ -129,51 -129,40 +129,51 @@@ MUTATOR_HOOKABLE(GiveFragsForKill, EV_G
  /** called when the match ends */
  MUTATOR_HOOKABLE(MatchEnd, EV_NO_ARGS);
  
 -/** allows adjusting allowed teams */
 -#define EV_CheckAllowedTeams(i, o) \
 +/** Allows adjusting allowed teams. Return true to use the bitmask value and set
 + * non-empty string to use team entity name. Both behaviors can be active at the
 + * same time and will stack allowed teams.
 + */
 +#define EV_TeamBalance_CheckAllowedTeams(i, o) \
      /** mask of teams      */ i(float, MUTATOR_ARGV_0_float) \
      /**/                      o(float, MUTATOR_ARGV_0_float) \
      /** team entity name   */ i(string, MUTATOR_ARGV_1_string) \
      /**/                      o(string, MUTATOR_ARGV_1_string) \
      /** player checked     */ i(entity, MUTATOR_ARGV_2_entity) \
      /**/
 -MUTATOR_HOOKABLE(CheckAllowedTeams, EV_CheckAllowedTeams);
 +MUTATOR_HOOKABLE(TeamBalance_CheckAllowedTeams,
 +      EV_TeamBalance_CheckAllowedTeams);
  
  /** return true to manually override team counts */
 -MUTATOR_HOOKABLE(GetTeamCounts, EV_NO_ARGS);
 +MUTATOR_HOOKABLE(TeamBalance_GetTeamCounts, EV_NO_ARGS);
  
 -/** allow overriding of team counts */
 -#define EV_GetTeamCount(i, o) \
 -    /** team to count                   */ i(float, MUTATOR_ARGV_0_float) \
 +/** allows overriding of team counts */
 +#define EV_TeamBalance_GetTeamCount(i, o) \
 +    /** team index to count             */ i(float, MUTATOR_ARGV_0_float) \
      /** player to ignore                */ i(entity, MUTATOR_ARGV_1_entity) \
 -    /** number of players in a team     */ i(float, MUTATOR_ARGV_2_float) \
 -    /**/                                   o(float, MUTATOR_ARGV_2_float) \
 -    /** number of bots in a team        */ i(float, MUTATOR_ARGV_3_float) \
 -    /**/                                   o(float, MUTATOR_ARGV_3_float) \
 -    /** lowest scoring human in a team  */ i(entity, MUTATOR_ARGV_4_entity) \
 -    /**/                                   o(entity, MUTATOR_ARGV_4_entity) \
 -    /** lowest scoring bot in a team    */ i(entity, MUTATOR_ARGV_5_entity) \
 -    /**/                                   o(entity, MUTATOR_ARGV_5_entity) \
 -    /**/
 -MUTATOR_HOOKABLE(GetTeamCount, EV_GetTeamCount);
 -
 -/** allows overriding best teams */
 -#define EV_FindBestTeams(i, o) \
 +    /** number of players in a team     */ o(float, MUTATOR_ARGV_2_float) \
 +    /** number of bots in a team        */ o(float, MUTATOR_ARGV_3_float) \
 +    /**/
 +MUTATOR_HOOKABLE(TeamBalance_GetTeamCount, EV_TeamBalance_GetTeamCount);
 +
 +/** allows overriding the teams that will make the game most balanced if the
 + *  player joins any of them.
 + */
 +#define EV_TeamBalance_FindBestTeams(i, o) \
      /** player checked   */ i(entity, MUTATOR_ARGV_0_entity) \
      /** bitmask of teams */ o(float, MUTATOR_ARGV_1_float) \
      /**/
 -MUTATOR_HOOKABLE(FindBestTeams, EV_FindBestTeams);
 +MUTATOR_HOOKABLE(TeamBalance_FindBestTeams, EV_TeamBalance_FindBestTeams);
 +
 +/** Called during autobalance. Return true to override the player that will be
 +switched. */
 +#define EV_TeamBalance_GetPlayerForTeamSwitch(i, o) \
 +    /** source team index      */ i(int, MUTATOR_ARGV_0_int) \
 +    /** destination team index */ i(int, MUTATOR_ARGV_1_int) \
 +    /** is looking for bot     */ i(bool, MUTATOR_ARGV_2_bool) \
 +    /** player to switch       */ o(entity, MUTATOR_ARGV_3_entity) \
 +    /**/
 +MUTATOR_HOOKABLE(TeamBalance_GetPlayerForTeamSwitch,
 +      EV_TeamBalance_GetPlayerForTeamSwitch);
  
  /** copies variables for spectating "spectatee" to "this" */
  #define EV_SpectateCopy(i, o) \
@@@ -1019,9 -1008,9 +1019,9 @@@ MUTATOR_HOOKABLE(MonsterModel, EV_Monst
   * Called before player changes their team. Return true to block team change.
   */
  #define EV_Player_ChangeTeam(i, o) \
 -    /** player */         i(entity, MUTATOR_ARGV_0_entity) \
 -      /** current team */   i(float, MUTATOR_ARGV_1_float) \
 -      /** new team */       i(float, MUTATOR_ARGV_2_float) \
 +    /** player */             i(entity, MUTATOR_ARGV_0_entity) \
 +    /** current team index */ i(float, MUTATOR_ARGV_1_float) \
 +    /** new team index */     i(float, MUTATOR_ARGV_2_float) \
      /**/
  MUTATOR_HOOKABLE(Player_ChangeTeam, EV_Player_ChangeTeam);
  
   * Called after player has changed their team.
   */
  #define EV_Player_ChangedTeam(i, o) \
 -    /** player */         i(entity, MUTATOR_ARGV_0_entity) \
 -      /** old team */       i(float, MUTATOR_ARGV_1_float) \
 -      /** current team */   i(float, MUTATOR_ARGV_2_float) \
 +    /** player */             i(entity, MUTATOR_ARGV_0_entity) \
 +    /** old team index */     i(float, MUTATOR_ARGV_1_float) \
 +    /** current team index */ i(float, MUTATOR_ARGV_2_float) \
      /**/
  MUTATOR_HOOKABLE(Player_ChangedTeam, EV_Player_ChangedTeam);
  
@@@ -1117,6 -1106,13 +1117,13 @@@ MUTATOR_HOOKABLE(Item_ScheduleRespawn, 
      /**/
  MUTATOR_HOOKABLE(PlayerPhysics_UpdateStats, EV_PlayerPhysics_UpdateStats);
  
+ /** called after physics stats are set on a player, allows post-initialization modifications */
+ #define EV_PlayerPhysics_PostUpdateStats(i, o) \
+     /** player */             i(entity, MUTATOR_ARGV_0_entity) \
+     /** maxspeed_mod */       i(float, MUTATOR_ARGV_1_float) \
+     /**/
+ MUTATOR_HOOKABLE(PlayerPhysics_PostUpdateStats, EV_PlayerPhysics_PostUpdateStats);
  /** return true to use your own aim target (or none at all) */
  #define EV_HavocBot_Aim(i, o) \
      /** bot */ i(entity, MUTATOR_ARGV_0_entity) \