]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge branch 'Mario/lms_pickup_items' into 'master'
authorMario <mario.mario@y7mail.com>
Thu, 9 Dec 2021 05:47:55 +0000 (05:47 +0000)
committerMario <mario.mario@y7mail.com>
Thu, 9 Dec 2021 05:47:55 +0000 (05:47 +0000)
Merge branch Mario/lms_pickup_items (XXS merge request)

See merge request xonotic/xonotic-data.pk3dir!934

1  2 
qcsrc/common/gamemodes/gamemode/lms/sv_lms.qc

index b603a2bd81da44054a4006056ad080fc9cc2349a,db5282466c3dd37809f7fdee1e4e1e98aed52ff5..8f545955caefc20137883d1d15f9c066ec610eb5
@@@ -36,12 -36,9 +36,12 @@@ void ClearWinners()
  // limit.
  int WinningCondition_LMS()
  {
 +      if (warmup_stage || time <= game_starttime)
 +              return WINNING_NO;
 +
        entity first_player = NULL;
        int totalplayers = 0;
 -      FOREACH_CLIENT(IS_PLAYER(it) && it.frags != FRAGS_PLAYER_OUT_OF_GAME, {
 +      FOREACH_CLIENT(IS_PLAYER(it) && it.frags == FRAGS_PLAYER, {
                if (!totalplayers)
                        first_player = it;
                ++totalplayers;
                                // a winner!
                                // and assign him his first place
                                GameRules_scoring_add(first_player, LMS_RANK, 1);
 -                              if(warmup_stage)
 -                                      return WINNING_NO;
 -                              else
 -                                      return WINNING_YES;
 +                              return WINNING_YES;
                        }
                }
        }
@@@ -123,25 -123,9 +123,25 @@@ MUTATOR_HOOKFUNCTION(lms, reset_map_glo
  MUTATOR_HOOKFUNCTION(lms, reset_map_players)
  {
        FOREACH_CLIENT(true, {
 +              if (it.frags == FRAGS_PLAYER_OUT_OF_GAME)
 +              {
 +                      // players who forfeited (rank >= 256) become spectators
 +                      if (it.lms_spectate_warning == 2)
 +                              it.frags = FRAGS_SPECTATOR;
 +                      else
 +                              it.frags = FRAGS_PLAYER;
 +              }
 +
 +              CS(it).killcount = 0;
 +              it.lmsplayer = 0;
 +              it.lms_spectate_warning = 0;
 +              GameRules_scoring_add(it, LMS_RANK, -GameRules_scoring_add(it, LMS_RANK, 0));
 +              GameRules_scoring_add(it, LMS_LIVES, -GameRules_scoring_add(it, LMS_LIVES, 0));
 +
 +              if (it.frags != FRAGS_PLAYER)
 +                      continue;
 +
                TRANSMUTE(Player, it);
 -              it.frags = FRAGS_PLAYER;
 -              GameRules_scoring_add(it, LMS_LIVES, LMS_NewPlayerLives());
                PutClientInServer(it);
        });
  }
@@@ -154,84 -138,36 +154,84 @@@ MUTATOR_HOOKFUNCTION(lms, ReadLevelCvar
        sv_ready_restart_after_countdown = 0;
  }
  
 +// returns true if player is added to the game
 +bool lms_AddPlayer(entity player)
 +{
 +      if (!player.lmsplayer)
 +      {
 +              int lives = GameRules_scoring_add(player, LMS_LIVES, LMS_NewPlayerLives());
 +              if(lives <= 0)
 +                      return false;
 +              player.lmsplayer = 2; // temp value indicating player has just joined the game (but not spawned yet)
 +      }
 +      if (warmup_stage || time <= game_starttime)
 +      {
 +              if(player.lms_spectate_warning)
 +              {
 +                      player.lms_spectate_warning = 0;
 +                      GameRules_scoring_add(player, LMS_RANK, -GameRules_scoring_add(player, LMS_RANK, 0));
 +                      int lives = GameRules_scoring_add(player, LMS_LIVES, 0);
 +                      if(lives <= 0)
 +                              GameRules_scoring_add(player, LMS_LIVES, LMS_NewPlayerLives());
 +              }
 +      }
 +      else
 +      {
 +              if(GameRules_scoring_add(player, LMS_LIVES, 0) <= 0)
 +              {
 +                      Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_LMS_NOLIVES);
 +                      return false;
 +              }
 +      }
 +      return true;
 +}
 +
  MUTATOR_HOOKFUNCTION(lms, PutClientInServer)
  {
        entity player = M_ARGV(0, entity);
 -
 -      if(player.frags == FRAGS_SPECTATOR)
 -              TRANSMUTE(Observer, player);
 -      else
 +      if (!warmup_stage && (IS_BOT_CLIENT(player) || CS(player).jointime != time))
        {
 -              float tl = GameRules_scoring_add(player, LMS_LIVES, 0);
 -              if(tl < lms_lowest_lives)
 -                      lms_lowest_lives = tl;
 -              if(tl <= 0)
 +              if (GameRules_scoring_add(player, LMS_RANK, 0) || !lms_AddPlayer(player))
                        TRANSMUTE(Observer, player);
 -              if(warmup_stage)
 -                      GameRules_scoring_add(player, LMS_RANK, -GameRules_scoring_add(player, LMS_RANK, 0));
        }
  }
  
 -MUTATOR_HOOKFUNCTION(lms, ForbidSpawn)
 +MUTATOR_HOOKFUNCTION(lms, PlayerSpawn)
  {
        entity player = M_ARGV(0, entity);
  
 -      if(warmup_stage)
 -              return false;
 -      if(player.frags == FRAGS_SPECTATOR || GameRules_scoring_add(player, LMS_LIVES, 0) <= 0)
 -      {
 -              Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_LMS_NOLIVES);
 +      if (warmup_stage || time < game_starttime)
                return true;
 +
 +      if (player.lmsplayer == 2) // just joined the game
 +      {
 +              // spawn player with the same amount of health / armor
 +              // as the least healthy player with the least number of lives
 +              int pl_lives = GameRules_scoring_add(player, LMS_LIVES, 0);
 +              float min_health = start_health;
 +              float min_armorvalue = start_armorvalue;
 +              FOREACH_CLIENT(it != player && IS_PLAYER(it) && !IS_DEAD(it) && GameRules_scoring_add(it, LMS_LIVES, 0) == pl_lives, {
 +                      if (GetResource(it, RES_HEALTH) < min_health)
 +                              min_health = GetResource(it, RES_HEALTH);
 +                      if (GetResource(it, RES_ARMOR) < min_armorvalue)
 +                              min_armorvalue = GetResource(it, RES_ARMOR);
 +              });
 +              if (min_health != start_health)
 +                      SetResource(player, RES_HEALTH, max(1, min_health));
 +              if (min_armorvalue != start_armorvalue)
 +                      SetResource(player, RES_ARMOR, min_armorvalue);
 +              player.lmsplayer = 1;
        }
 -      return false;
 +}
 +
 +MUTATOR_HOOKFUNCTION(lms, ForbidSpawn)
 +{
 +      entity player = M_ARGV(0, entity);
 +
 +      if (warmup_stage || lms_AddPlayer(player))
 +              return false;
 +
 +      return true;
  }
  
  MUTATOR_HOOKFUNCTION(lms, PlayerDies)
  
  void lms_RemovePlayer(entity player)
  {
 -      static int quitters = 0;
 +      if (warmup_stage || time < game_starttime)
 +              return;
 +
        float player_rank = GameRules_scoring_add(player, LMS_RANK, 0);
        if (!player_rank)
        {
                {
                        player.frags = FRAGS_PLAYER_OUT_OF_GAME;
                        int pl_cnt = 0;
 -                      FOREACH_CLIENT(IS_PLAYER(it) && it.frags != FRAGS_PLAYER_OUT_OF_GAME, {
 +                      FOREACH_CLIENT(IS_PLAYER(it) && it.frags == FRAGS_PLAYER, {
                                pl_cnt++;
                        });
                        GameRules_scoring_add(player, LMS_RANK, pl_cnt + 1);
                }
                else
                {
 +                      int min_forfeiter_rank = 665; // different from 666
                        FOREACH_CLIENT(true, {
 +                              // update rank of other players that were eliminated
                                if (it.frags == FRAGS_PLAYER_OUT_OF_GAME)
                                {
                                        float it_rank = GameRules_scoring_add(it, LMS_RANK, 0);
                                        if (it_rank > player_rank && it_rank <= 256)
                                                GameRules_scoring_add(it, LMS_RANK, -1);
 +                                      if (it_rank > 256 && it_rank <= min_forfeiter_rank)
 +                                              min_forfeiter_rank = it_rank - 1;
                                }
                                else if (it.frags != FRAGS_SPECTATOR)
                                {
                                                lms_lowest_lives = tl;
                                }
                        });
 -                      GameRules_scoring_add(player, LMS_RANK, 665 - quitters); // different from 666
 +                      GameRules_scoring_add(player, LMS_RANK, min_forfeiter_rank);
                        if(!warmup_stage)
 -                      {
                                GameRules_scoring_add(player, LMS_LIVES, -GameRules_scoring_add(player, LMS_LIVES, 0));
 -                              ++quitters;
 -                      }
                        player.frags = FRAGS_PLAYER_OUT_OF_GAME;
                        TRANSMUTE(Observer, player);
                }
@@@ -310,38 -243,36 +310,38 @@@ MUTATOR_HOOKFUNCTION(lms, ClientDisconn
        player.lms_spectate_warning = 3;
  
        lms_RemovePlayer(player);
 +      player.lmsplayer = 0;
  }
  
  MUTATOR_HOOKFUNCTION(lms, MakePlayerObserver)
  {
        entity player = M_ARGV(0, entity);
 +      bool is_forced = M_ARGV(1, bool);
  
        if (!IS_PLAYER(player))
                return true;
  
 -      lms_RemovePlayer(player);
 -      return true;  // prevent team reset
 -}
 -
 -MUTATOR_HOOKFUNCTION(lms, ClientConnect)
 -{
 -      entity player = M_ARGV(0, entity);
 -
 -      if(GameRules_scoring_add(player, LMS_LIVES, LMS_NewPlayerLives()) <= 0)
 +      if (warmup_stage || time <= game_starttime)
        {
 -              GameRules_scoring_add(player, LMS_RANK, 666); // mark as forced spectator for the hud code
 +              GameRules_scoring_add(player, LMS_LIVES, -GameRules_scoring_add(player, LMS_LIVES, 0));
                player.frags = FRAGS_SPECTATOR;
 +              TRANSMUTE(Observer, player);
 +              player.lmsplayer = 0;
        }
 +      else
 +      {
 +              if (is_forced)
 +                      player.lms_spectate_warning = 2;
 +              if (!GameRules_scoring_add(player, LMS_RANK, 0))
 +                      lms_RemovePlayer(player);
 +      }
 +      return true;  // prevent team reset
  }
  
 -// FIXME LMS doesn't allow clients to spectate due to its particular implementation
 -MUTATOR_HOOKFUNCTION(lms, AutoJoinOnConnection)
 +MUTATOR_HOOKFUNCTION(lms, ClientConnect)
  {
 -      if(autocvar_g_campaign)
 -              return false;
 -      return true;
 +      entity player = M_ARGV(0, entity);
 +      player.frags = FRAGS_SPECTATOR;
  }
  
  MUTATOR_HOOKFUNCTION(lms, PlayerPreThink)
@@@ -369,7 -300,7 +369,7 @@@ MUTATOR_HOOKFUNCTION(lms, GiveFragsForK
  {
        entity frag_target = M_ARGV(1, entity);
  
 -      if (!warmup_stage)
 +      if (!warmup_stage && time > game_starttime)
        {
                // remove a life
                int tl = GameRules_scoring_add(frag_target, LMS_LIVES, -1);
                if(tl <= 0)
                {
                        int pl_cnt = 0;
 -                      FOREACH_CLIENT(IS_PLAYER(it) && it.frags != FRAGS_PLAYER_OUT_OF_GAME, {
 +                      FOREACH_CLIENT(IS_PLAYER(it) && it.frags == FRAGS_PLAYER, {
                                pl_cnt++;
                        });
                        frag_target.frags = FRAGS_PLAYER_OUT_OF_GAME;
  MUTATOR_HOOKFUNCTION(lms, SetStartItems)
  {
        start_items &= ~(IT_UNLIMITED_AMMO | IT_UNLIMITED_SUPERWEAPONS);
 +      if(!cvar("g_use_ammunition"))
 +              start_items |= IT_UNLIMITED_AMMO;
 +
        start_health       = warmup_start_health       = cvar("g_lms_start_health");
        start_armorvalue   = warmup_start_armorvalue   = cvar("g_lms_start_armor");
        start_ammo_shells  = warmup_start_ammo_shells  = cvar("g_lms_start_ammo_shells");
@@@ -420,7 -348,7 +420,7 @@@ MUTATOR_HOOKFUNCTION(lms, FilterItemDef
        {
                return false;
        }
-       return true;
+       return (autocvar_g_pickup_items <= 0); // only allow items if explicitly enabled
  }
  
  void lms_extralife(entity this)
@@@ -470,8 -398,7 +470,8 @@@ MUTATOR_HOOKFUNCTION(lms, ItemTouch
  MUTATOR_HOOKFUNCTION(lms, Bot_FixCount, CBC_ORDER_EXCLUSIVE)
  {
        FOREACH_CLIENT(IS_REAL_CLIENT(it), {
 -              ++M_ARGV(0, int); // activerealplayers
 +              if (it.lmsplayer && it.lms_spectate_warning < 2)
 +                      ++M_ARGV(0, int); // activerealplayers
                ++M_ARGV(1, int); // realplayers
        });
  
@@@ -482,7 -409,7 +482,7 @@@ MUTATOR_HOOKFUNCTION(lms, ClientCommand
  {
        entity player = M_ARGV(0, entity);
  
 -      if(warmup_stage || player.lms_spectate_warning)
 +      if(warmup_stage || time < game_starttime || player.lms_spectate_warning)
        {
                // for the forfeit message...
                player.lms_spectate_warning = 2;
@@@ -513,9 -440,7 +513,9 @@@ MUTATOR_HOOKFUNCTION(lms, SetWeaponAren
  
  MUTATOR_HOOKFUNCTION(lms, GetPlayerStatus)
  {
 -      return true;
 +      entity player = M_ARGV(0, entity);
 +
 +      return boolean(player.lmsplayer);
  }
  
  MUTATOR_HOOKFUNCTION(lms, AddPlayerScore)