]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge branch 'master' into Lyberta/TeamplayOverhaul
authorLyberta <lyberta@lyberta.net>
Wed, 4 Apr 2018 16:44:14 +0000 (19:44 +0300)
committerLyberta <lyberta@lyberta.net>
Wed, 4 Apr 2018 16:44:14 +0000 (19:44 +0300)
1  2 
qcsrc/common/t_items.qc
qcsrc/server/defs.qh
qcsrc/server/mutators/events.qh
qcsrc/server/mutators/mutator/gamemode_assault.qc
qcsrc/server/mutators/mutator/gamemode_invasion.qc

diff --combined qcsrc/common/t_items.qc
index 4ce8c8104bb11656586fad6332c26c3f6e00261d,02a0dc171cc34723e95e7671fde5504b80da47e0..9ab49e7fd0514b1d81c6e7818fc136e332918620
@@@ -628,18 -628,14 +628,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 {
@@@ -667,8 -663,6 +667,6 @@@ void Item_ScheduleRespawn(entity e
  AUTOCVAR(g_pickup_respawntime_initial_random, int, 1,
        "For items that don't start spawned: 0: spawn after their normal respawntime; 1: spawn after `random * respawntime` with the *same* random; 2: same as 1 but each item has separate random");
  
- float shared_random;
- STATIC_INIT(shared_random) { shared_random = random(); }
  void Item_ScheduleInitialRespawn(entity e)
  {
        Item_Show(e, 0);
                // range: respawntime .. respawntime + respawntimejitter
                spawn_in = e.respawntime + random() * e.respawntimejitter;
        }
-       else if (autocvar_g_pickup_respawntime_initial_random == 1)
+       else
        {
+               float rnd;
+               if (autocvar_g_pickup_respawntime_initial_random == 1)
+               {
+                       static float shared_random = 0;
+                       // NOTE this code works only if items are scheduled at the same time (normal case)
+                       // NOTE2 random() can't return exactly 1 so this check always work as intended
+                       if (!shared_random || floor(time) > shared_random)
+                               shared_random = floor(time) + random();
+                       rnd = shared_random - floor(time);
+               }
+               else
+                       rnd = random();
                // range:
                // if respawntime >= ITEM_RESPAWN_TICKS: ITEM_RESPAWN_TICKS .. respawntime + respawntimejitter
                // else: 0 .. ITEM_RESPAWN_TICKS
                // this is to prevent powerups spawning unexpectedly without waypoints
-               spawn_in = ITEM_RESPAWN_TICKS + shared_random * (e.respawntime + e.respawntimejitter - ITEM_RESPAWN_TICKS);
-       }
-       else
-       {
-               // range: same as 1
-               spawn_in = ITEM_RESPAWN_TICKS + random() * (e.respawntime + e.respawntimejitter - ITEM_RESPAWN_TICKS);
+               spawn_in = ITEM_RESPAWN_TICKS + rnd * (e.respawntime + e.respawntimejitter - ITEM_RESPAWN_TICKS);
        }
  
        Item_ScheduleRespawnIn(e, max(0, game_starttime - time) + ((e.respawntimestart) ? e.respawntimestart : spawn_in));
diff --combined qcsrc/server/defs.qh
index 5befffee4558164437c881ab0194d020adf6897b,f85d6e2b6f22ae53ff521c4e52668c635f5dd5f4..03428b12b45ef00b67bf49a5090dae8958a68088
@@@ -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;
  
@@@ -180,8 -182,6 +180,6 @@@ float default_weapon_alpha
  
  string gamemode_name;
  
- float startitem_failed;
  string W_Apply_Weaponreplace(string in);
  
  void FixIntermissionClient(entity e);
@@@ -231,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;
@@@ -404,67 -406,43 +402,43 @@@ const int MIF_GUIDED_CONFUSABLE = MIF_G
  .WepSet dual_weapons;
  
  IntrusiveList g_monsters;
- STATIC_INIT(g_monsters) { g_monsters = IL_NEW(); }
  IntrusiveList g_waypoints;
- STATIC_INIT(g_waypoints) { g_waypoints = IL_NEW(); }
  IntrusiveList g_vehicles;
- STATIC_INIT(g_vehicles) { g_vehicles = IL_NEW(); }
  IntrusiveList g_turrets;
- STATIC_INIT(g_turrets) { g_turrets = IL_NEW(); }
  IntrusiveList g_mines;
- STATIC_INIT(g_mines) { g_mines = IL_NEW(); }
  IntrusiveList g_projectiles;
- STATIC_INIT(g_projectiles) { g_projectiles = IL_NEW(); }
  IntrusiveList g_items;
- STATIC_INIT(g_items) { g_items = IL_NEW(); }
  IntrusiveList g_initforplayer;
- STATIC_INIT(g_initforplayer) { g_initforplayer = IL_NEW(); }
  IntrusiveList g_clones;
- STATIC_INIT(g_clones) { g_clones = IL_NEW(); }
- IntrusiveList g_assault_destructibles;
- STATIC_INIT(g_assault_destructibles) { g_assault_destructibles = IL_NEW(); }
- IntrusiveList g_assault_objectivedecreasers;
- STATIC_INIT(g_assault_objectivedecreasers) { g_assault_objectivedecreasers = IL_NEW(); }
- IntrusiveList g_assault_objectives;
- STATIC_INIT(g_assault_objectives) { g_assault_objectives = IL_NEW(); }
  IntrusiveList g_spawnpoints;
- STATIC_INIT(g_spawnpoints) { g_spawnpoints = IL_NEW(); }
  IntrusiveList g_bot_targets;
- STATIC_INIT(g_bot_targets) { g_bot_targets = IL_NEW(); }
  IntrusiveList g_bot_dodge;
- STATIC_INIT(g_bot_dodge) { g_bot_dodge = IL_NEW(); }
  IntrusiveList g_damagedbycontents;
- STATIC_INIT(g_damagedbycontents) { g_damagedbycontents = IL_NEW(); }
  IntrusiveList g_railgunhit;
- STATIC_INIT(g_railgunhit) { g_railgunhit = IL_NEW(); }
  IntrusiveList g_ladders;
- STATIC_INIT(g_ladders) { g_ladders = IL_NEW(); }
  IntrusiveList g_locations;
- STATIC_INIT(g_locations) { g_locations = IL_NEW(); }
  IntrusiveList g_saved_team;
- STATIC_INIT(g_saved_team) { g_saved_team = IL_NEW(); }
  IntrusiveList g_monster_targets;
- STATIC_INIT(g_monster_targets) { g_monster_targets = IL_NEW(); }
  IntrusiveList g_pathlib_nodes;
- STATIC_INIT(g_pathlib_nodes) { g_pathlib_nodes = IL_NEW(); }
+ STATIC_INIT(defs)
+ {
+       g_monsters = IL_NEW();
+       g_waypoints = IL_NEW();
+       g_vehicles = IL_NEW();
+       g_turrets = IL_NEW();
+       g_mines = IL_NEW();
+       g_projectiles = IL_NEW();
+       g_items = IL_NEW();
+       g_initforplayer = IL_NEW();
+       g_clones = IL_NEW();
+       g_spawnpoints = IL_NEW();
+       g_bot_targets = IL_NEW();
+       g_bot_dodge = IL_NEW();
+       g_damagedbycontents = IL_NEW();
+       g_railgunhit = IL_NEW();
+       g_ladders = IL_NEW();
+       g_locations = IL_NEW();
+       g_saved_team = IL_NEW();
+       g_monster_targets = IL_NEW();
+       g_pathlib_nodes = IL_NEW();
+ }
index 37910cd28ff5dcba8fe6287f6ace004e66a56804,0d801ec22e2f811c3cc4ecf72cc50933987c83bf..df7113bd6749717e629467d124c248b98327ca7e
@@@ -3,6 -3,9 +3,9 @@@
  #include <common/mutators/base.qh>
  
  // register all possible hooks here
+  
+ // to use a hook, first register your mutator using REGISTER_MUTATOR
+ // then create your function using MUTATOR_HOOKFUNCTION
  
  /** called when a player becomes observer, after shared setup */
  #define EV_MakePlayerObserver(i, o) \
@@@ -126,26 -129,22 +129,26 @@@ 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) \
 +#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) \
      /** lowest scoring bot in a team    */ i(entity, MUTATOR_ARGV_5_entity) \
      /**/                                   o(entity, MUTATOR_ARGV_5_entity) \
      /**/
 -MUTATOR_HOOKABLE(GetTeamCount, EV_GetTeamCount);
 +MUTATOR_HOOKABLE(TeamBalance_GetTeamCount, EV_TeamBalance_GetTeamCount);
  
 -/** allows overriding best teams */
 -#define EV_FindBestTeams(i, o) \
 +/** 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);
  
  /** copies variables for spectating "spectatee" to "this" */
  #define EV_SpectateCopy(i, o) \
@@@ -235,6 -232,14 +238,14 @@@ MUTATOR_HOOKABLE(SetStartItems, EV_NO_A
      /**/
  MUTATOR_HOOKABLE(CustomizeWaypoint, EV_CustomizeWaypoint);
  
+ /** Check if items having the given definition are allowed to spawn.
+  *  Return true to disallow spawning.
+  */
+ #define EV_FilterItemDefinition(i, o) \
+     /** item        */ i(entity, MUTATOR_ARGV_0_entity) \
+     /**/
+ MUTATOR_HOOKABLE(FilterItemDefinition, EV_FilterItemDefinition);
  /**
   * checks if the current item may be spawned (.items and .weapons may be read and written to, as well as the ammo_ fields)
   * return error to request removal
@@@ -968,9 -973,9 +979,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);
  
index f3f104197efd744193dfc7a16d7335907784bd90,d43dc99993adb3474c5cce5baed9baa8cb4d87f7..2e703d1a8c3320756d6edd1a2ab0366f8fd74e78
@@@ -5,6 -5,16 +5,16 @@@
  .entity sprite;
  #define AS_ROUND_DELAY 5
  
+ IntrusiveList g_assault_destructibles;
+ IntrusiveList g_assault_objectivedecreasers;
+ IntrusiveList g_assault_objectives;
+ STATIC_INIT(g_assault)
+ {
+       g_assault_destructibles = IL_NEW();
+       g_assault_objectivedecreasers = IL_NEW();
+       g_assault_objectives = IL_NEW();
+ }
  // random functions
  void assault_objective_use(entity this, entity actor, entity trigger)
  {
@@@ -576,10 -586,10 +586,10 @@@ MUTATOR_HOOKFUNCTION(as, PlayHitsound
        return (frag_victim.classname == "func_assault_destructible");
  }
  
 -MUTATOR_HOOKFUNCTION(as, CheckAllowedTeams)
 +MUTATOR_HOOKFUNCTION(as, TeamBalance_CheckAllowedTeams)
  {
        // assault always has 2 teams
 -      c1 = c2 = 0;
 +      M_ARGV(0, float) = BIT(0) | BIT(1);
        return true;
  }
  
index 575fa308de182e3078e777187c9060fbf96fcb79,777b1b1e97f68bbed062d9f05dcc888523d2a079..a69ad0fc4cd7043acb407469f2c9c73134000c19
@@@ -6,13 -6,14 +6,14 @@@
  #include <server/teamplay.qh>
  
  IntrusiveList g_invasion_roundends;
- STATIC_INIT(g_invasion_roundends) { g_invasion_roundends = IL_NEW(); }
  IntrusiveList g_invasion_waves;
- STATIC_INIT(g_invasion_waves) { g_invasion_waves = IL_NEW(); }
  IntrusiveList g_invasion_spawns;
- STATIC_INIT(g_invasion_spawns) { g_invasion_spawns = IL_NEW(); }
+ STATIC_INIT(g_invasion)
+ {
+       g_invasion_roundends = IL_NEW();
+       g_invasion_waves = IL_NEW();
+       g_invasion_spawns = IL_NEW();
+ }
  
  float autocvar_g_invasion_round_timelimit;
  float autocvar_g_invasion_spawnpoint_spawn_delay;
@@@ -546,10 -547,9 +547,10 @@@ MUTATOR_HOOKFUNCTION(inv, CheckRules_Wo
        return true;
  }
  
 -MUTATOR_HOOKFUNCTION(inv, CheckAllowedTeams, CBC_ORDER_EXCLUSIVE)
 +MUTATOR_HOOKFUNCTION(inv, TeamBalance_CheckAllowedTeams, CBC_ORDER_EXCLUSIVE)
  {
        M_ARGV(0, float) = invasion_teams;
 +      return true;
  }
  
  MUTATOR_HOOKFUNCTION(inv, AllowMobButcher)
  
  void invasion_ScoreRules(int inv_teams)
  {
 -      if(inv_teams) { CheckAllowedTeams(NULL); }
 +      //if(inv_teams) { CheckAllowedTeams(NULL); } // Another bug?
        GameRules_score_enabled(false);
        GameRules_scoring(inv_teams, 0, 0, {
            if (inv_teams) {