Как правильно отсортировать лучшего/худшего игрока команды?

Сообщения
42
Реакции
32
Всем привет!
Я еще совсем зеленый в скриптинге, пробую написать примитивный балансер.
Суть: в начале каждого раунда проверяются обе команды, надо взять лучшего по фрагам из выигрывающей команды и худшего из проигрывающей, и поменять их местами. Пробовал заюзать SortCustom2D, но так и не понял как ею правильно воспользоваться. Добавил комменты в коде. Прошу помощи у знающих!

В будущем планирую добавить всякие проверки, например, чтобы не каждый раунд балансило, а если будет разница в счёте команд, например - 5, итп... Пока на это не обращайте внимания)

Код:
#include <amxmodx>
#include <cstrike>

// PREPARE DATA
enum _:Teams {
  TeamTT = 1,
  TeamCT
}

const MAXPLAYERS = 32;

new g_iPlayerKills[MAXPLAYERS + 1];
new g_eTeamScore[Teams + 1];
new g_iMaxPlayers;

// PLUGIN INIT
public plugin_init() {
  register_plugin("test", "1.0", "test");
 
  register_event("DeathMsg", "EventDeath", "a");
  register_event("TeamScore", "EventScore", "a");
  register_event("HLTV", "EventNewRound", "a", "1=0", "2=0");
 
  g_iMaxPlayers = get_maxplayers();
}

// PUBLIC FUNCTIONS
public EventDeath() {
  new iKiller = read_data(1);
  g_iPlayerKills[iKiller]++;
}

public EventScore() {
  new szTeam[1];
  read_data(1, szTeam, 1);

  if(szTeam[0] == 'C') g_eTeamScore[TeamCT] = read_data(2);
  else g_eTeamScore[TeamTT] = read_data(2);
}

public EventNewRound() {
  new iBestPlayer, iWorstPlayer;

  GetActualPlayers(iBestPlayer, iWorstPlayer);
 
  // Тут нужно свапнуть - ЛУЧШЕГО игрока с ВЫИГРЫВАЮЩЕЙ команды на ХУДШЕГО игрока с ПРОИГРЫВАЮЩЕЙ команды
  // Например, выигрывают Терры, - лучший игрок это Тер, перевести его за КТ, а худшего с команды КТ за Терров
  // Ну тут просто свап команды игрока, а все проверки в функции ---> GetActualPlayers()
  server_print( "Best Player ID=%d", iBestPlayer);
  server_print( "Worst Player ID=%d", iWorstPlayer);
}

GetActualPlayers(&iBestPlayer, &iWorstPlayer) {
  new iPlayersKills[Teams + 1][MAXPLAYERS];

  for(new id = 1; id <= g_iMaxPlayers; id++) {
    if(!is_user_connected(id)) continue;

    switch(cs_get_user_team(id)) {
      case CS_TEAM_CT: {
        iPlayersKills[TeamCT][id] = g_iPlayerKills[id];
      }
      case CS_TEAM_T: {
        iPlayersKills[TeamTT][id] = g_iPlayerKills[id];
      }
      default: continue;
    }
  }

  // Надо проверить какая команда сейчас выигрывает
  // Взять лучшего игрока из выигрывающей команды
  // Взять худшего игрока из проигрывающей команды
  // Записать этих двух в переменные
  // Но тут я запутался...
  if(g_eTeamScore[TeamCT] > g_eTeamScore[TeamTT]) {
    SortCustom2D(_:iPlayersKills, sizeof(iPlayersKills) , "SortCompare");
    iBestPlayer = _:iPlayersKills[TeamCT][0];
    iWorstPlayer = _:iPlayersKills[TeamTT][0];
  } else {
    SortCustom2D(_:iPlayersKills, sizeof(iPlayersKills) , "SortCompare");
    iBestPlayer = _:iPlayersKills[TeamTT][0];
    iWorstPlayer = _:iPlayersKills[TeamCT][0];
  }
}

public SortCompare(Float:elem1[], Float:elem2[]) {
  if(elem1[1] > elem2[1]) {
    return -1;
  }
  else if(elem1[1] < elem2[1]) {
    return 1;
  }
  return 0;
}
 
Сообщения
673
Реакции
242
Помог
11 раз(а)
Попробуй с
Код:
SortIntegers(int, size, Sort_Ascending)
SortIntegers(int, size, Sort_Descending)
 
Сообщения
42
Реакции
32
Limbooc, мне двумерный массив надо отсортировать, а это для одномерного же? И как потом связать отсортированный массив с id игрока и его командой?
 
Сообщения
673
Реакции
242
Помог
11 раз(а)
szawesome, а зачем двумерный массив тебе? в данной реализации можно обойтись без него
 
Сообщения
141
Реакции
201
Помог
5 раз(а)
123
 
Последнее редактирование:
Сообщения
42
Реакции
32
Limbooc, а как без двумерного обойтись? Я не понимаю как возвратить ID игрока с такого массива. Вместо ID возвращает его кол-во убийств. Вот код как пытался сделать. Оставил комменты на 71 строчке

Код:
#include <amxmodx>
#include <cstrike>

// PREPARE DATA
enum _:Teams {
  TeamTT = 1,
  TeamCT
}

const MAXPLAYERS = 32;

new g_iPlayerKills[MAXPLAYERS + 1];
new g_eTeamScore[Teams + 1];
new g_iMaxPlayers;

// PLUGIN INIT
public plugin_init() {
  register_plugin("test", "1.0", "test");
 
  register_event("DeathMsg", "EventDeath", "a");
  register_event("TeamScore", "EventScore", "a");
  register_event("HLTV", "EventNewRound", "a", "1=0", "2=0");
 
  g_iMaxPlayers = get_maxplayers();
}

// PUBLIC FUNCTIONS
public EventDeath() {
  new iKiller = read_data(1);
  g_iPlayerKills[iKiller]++;
}

public EventScore() {
  new szTeam[1];
  read_data(1, szTeam, 1);

  if(szTeam[0] == 'C') g_eTeamScore[TeamCT] = read_data(2);
  else g_eTeamScore[TeamTT] = read_data(2);
}

public EventNewRound() {
  new iBestPlayer, iWorstPlayer;

  GetActualPlayers(iBestPlayer, iWorstPlayer);
 
  server_print("Best Player %n", iBestPlayer);
  server_print("Worst Player %n", iWorstPlayer);
}

GetActualPlayers(&iBestPlayer, &iWorstPlayer) {
  new iCTPlayersKills[MAXPLAYERS + 1];
  new iTTPlayersKills[MAXPLAYERS + 1];

  for(new id = 1; id <= g_iMaxPlayers; id++) {
    if(!is_user_connected(id)) continue;

    switch(cs_get_user_team(id)) {
      case CS_TEAM_CT: {
        iCTPlayersKills[id] = g_iPlayerKills[id];
      }
      case CS_TEAM_T: {
        iTTPlayersKills[id] = g_iPlayerKills[id];
      }
      default: continue;
    }
  }

  if(g_eTeamScore[TeamCT] > g_eTeamScore[TeamTT]) {
    SortIntegers(iCTPlayersKills, sizeof(iCTPlayersKills), Sort_Descending);
    SortIntegers(iTTPlayersKills, sizeof(iTTPlayersKills), Sort_Ascending);
    iBestPlayer = iCTPlayersKills[0]; // возвращает не ID игрока, а его кол-во его убийств. Нужно возвратить ID игрока
    iWorstPlayer = iTTPlayersKills[0]; // возвращает не ID игрока, а его кол-во его убийств. Нужно возвратить ID игрока
  } else {
    SortIntegers(iTTPlayersKills, sizeof(iTTPlayersKills), Sort_Descending);
    SortIntegers(iCTPlayersKills, sizeof(iCTPlayersKills), Sort_Ascending);
    iBestPlayer = iTTPlayersKills[0]; // возвращает не ID игрока, а его кол-во его убийств. Нужно возвратить ID игрока
    iWorstPlayer = iCTPlayersKills[0]; // возвращает не ID игрока, а его кол-во его убийств. Нужно возвратить ID игрока
  }
}
16 Апр 2021
juice, чтобы получить лучшего и худшего игроков. Если можно без сортировки, подскажи пожалуйста как
 
Сообщения
225
Реакции
90
Помог
1 раз(а)
чтобы получить лучшего и худшего игроков. Если можно без сортировки, подскажи пожалуйста как
Циклом по массиву пройтись и взять максимальный и минимальный элемент
 
Сообщения
673
Реакции
242
Помог
11 раз(а)
szawesome, так засунь айди игрока а там уже через g_iPlayerKills[id]
 
Сообщения
42
Реакции
32
Спасибо за советы, но без примеров не получилось сделать. Еще на моменте компиляции получал ошибки. Буду пробовать еще. Но сумел с SortCustom2D сделать рабочую версию, правда много недочетов. Уже заметил что не все случаи рассмотрены в SortDesc()

Код:
#include <amxmodx>
#include <cstrike>

// PREPARE DATA
enum _:Teams {
  TeamTT = 1,
  TeamCT
}

const MAXPLAYERS = 32;

new g_iPlayerKills[MAXPLAYERS + 1];
new g_eTeamScore[Teams + 1];
new g_iMaxPlayers;

// PLUGIN INIT
public plugin_init() {
  register_plugin("test", "1.0", "test");
 
  register_event("DeathMsg", "EventDeath", "a");
  register_event("TeamScore", "EventScore", "a");
  register_event("HLTV", "EventNewRound", "a", "1=0", "2=0");
 
  g_iMaxPlayers = get_maxplayers();
}

// PUBLIC FUNCTIONS
public EventDeath() {
  new iKiller = read_data(1);
  g_iPlayerKills[iKiller]++;
}

public EventScore() {
  new szTeam[1];
  read_data(1, szTeam, 1);

  if(szTeam[0] == 'C') g_eTeamScore[TeamCT] = read_data(2);
  else g_eTeamScore[TeamTT] = read_data(2);
}

public EventNewRound() {
  new iBestPlayer, iWorstPlayer;

  GetActualPlayers(iBestPlayer, iWorstPlayer);
 
  server_print("Best player: %n", iBestPlayer);
  server_print("Worst player: %n", iWorstPlayer);
}

GetActualPlayers(&iBestPlayer, &iWorstPlayer) {
  enum _:pKillsKey {
    pId = 0,
    pKills
  }
  new iCTPlayersKills[MAXPLAYERS + 1][pKillsKey];
  new iTTPlayersKills[MAXPLAYERS + 1][pKillsKey];

  new iCTNum, iTTNum;

  for(new id = 1; id <= g_iMaxPlayers; id++) {
    if(!is_user_connected(id)) continue;

    switch(cs_get_user_team(id)) {
      case CS_TEAM_CT: {
        iCTNum++
        iCTPlayersKills[id][pId] = id;
        iCTPlayersKills[id][pKills] = g_iPlayerKills[id];
      }
      case CS_TEAM_T: {
        iTTNum++
        iTTPlayersKills[id][pId] = id;
        iTTPlayersKills[id][pKills] = g_iPlayerKills[id];
      }
      default: continue;
    }
  }

  SortCustom2D(_:iCTPlayersKills, sizeof(iCTPlayersKills) , "SortDesc");
  SortCustom2D(_:iTTPlayersKills, sizeof(iTTPlayersKills) , "SortDesc");

  if(g_eTeamScore[TeamCT] > g_eTeamScore[TeamTT]) {
    iBestPlayer = _:iCTPlayersKills[0][pId];
    iWorstPlayer = _:iTTPlayersKills[iTTNum-1][pId];
  } else {
    iBestPlayer = _:iTTPlayersKills[0][pId];
    iWorstPlayer = _:iCTPlayersKills[iCTNum-1][pId];
  }
}

public SortDesc(Float:elem1[], Float:elem2[]) {
  if(elem1[1] > elem2[1]) {
    return -1;
  } else if(elem1[1] < elem2[1]) {
    return 1;
  }
  return 0;
}
 

Пользователи, просматривающие эту тему

Сейчас на форуме нет ни одного пользователя.
Сверху Снизу