Автобаланг игроков по "Скиллу"

hanson

Участник
Сообщения
303
Реакции
15
Здравствуйте.

Хочу обратиться к программистам и предлажить такую идею. В паблике существует куча автобалансировки команда по кол-ву, но я еще не видел автобаланса, который бы балансировал команды по скиллу (кол-во фрагов или кэф у/с).

Если не ошибаюсь, такой баланс написать не сложно. Прошу написать такой автобаланс для паблика либо для меня за оплату.

Как я себе представляю этот автобаланс. В логи записываются кол-во убийств и смертей, далее расчитывается кэф например 20 убийств 10 смертей, кэф 2. И после этого плагин должен перекидывать игроков, чтобы средний кэф в командах были как можно ближе ( 3,11 и 3,08). Тем самым в обеих командых будет одинаковое кол-во и нормальных и криворуких игроков.

Как вам идея?
 

AlmazON

Не путать с самим yand3xmail
Сообщения
5,099
Реакции
2,755
чтобы средний кэф в командах были как можно ближе ( 3,11 и 3,08).
Если не ошибаюсь, такой баланс написать не сложно
Ошибаешься. Это уже мудрёно будет. Перекидывать самых результативных игроков - ещё одно, но кидать ещё и именно тех, чтобы общие коэффициенты выровнялись - уже думать надо.
Можно конечно и тупо кучу циклов наделать) Оффтоп
 

R1KO

fuck society
Сообщения
9,457
Реакции
7,786
  • Команда форума
  • #3
Ну не 2 а 2.0 прийдется работать с дробными числами. А фраги и киллы записывать не в логи, а в память.
 

hanson

Участник
Сообщения
303
Реакции
15
AlmazON, R1KO, а если перекидывать самых результативных игроков, это будет сложно в реализации?
 

R1KO

fuck society
Сообщения
9,457
Реакции
7,786
  • Команда форума
  • #5
hanson, сложность в посчете среднего коэффициента
 

hanson

Участник
Сообщения
303
Реакции
15
R1KO, хорошо, не по кэфу. Как тогда можно это сделать? Чтобы действительно выбл баланс между командами.

Можно ли сделать так: менять местами самых плохих и сымых результативных игроков.

Т:
петька 10-9
саша 0-5
петя 0-11

СТ:
вася 50-1
леша 25-0
маша


То есть: счет Т (15:28) СТ. За СТ кидать последних из команды Т (саша, петя). За Т кидать первых из команды СТ (вася, леша). Надеюсь понятно объяснил=)
 

Reiko1231

AlexTheRegent
Сообщения
508
Реакции
1,335
Баланс по к\д не такой и сложный.
Шаг 1. Собрать в два массива айди игроков и их к\д.
Шаг 2. Отсортировать массив к\д по уменьшению и в паре с ним айди игроков (для сохранения соответствия).
Шаг 3. В переменную записать к\д первого игрока. Оставить его в своей команде. Перемещать в противоположную команду игроков, отнимая от к\д первого игрока, пока значение не станет <= 0. Перемещать игроков в команду к 1 игроку, пока к\д не станет > 0. И так до конца массива.
Сразу видна ошибка в такой балансировке - для перемещения в 1 команду условие >, в то время как 2 команды <=, что приведет к тому, что все игроки с к\д, близким к нулю, будут перемещены в одну команду, тем самым создавая дисбаланс по количеству. Вероятное решение проблемы - на каждое второе перемещение в одну и ту же команду подряд добавлять в противоположную одного игрока снизу массива.
Второй проблемой такой балансировки будет частое перебрасывание игроков из одной команды в другую, особенно для тех, кто в конце списка (небольшие к\д).
Набросок кода без этого решения под спойлером. Может быть позже доделаю с добавлением игрока снизу, но это тоже надо обдумать.

C-подобный:
public OnPluginStart() 
{
	HookEvent("round_start", Ev_RoundStart, EventHookMode_Pre);
}

public Ev_RoundStart(Handle:hEvent, const String:sEvName[], bool:bDontBroadcast)
{
	decl Float:fArray[MaxClients], Float:fDifference, bool:bTeam, iArray[MaxClients], iSize;
	
	// собираем массив из игроков и их индексов
	iSize = 0;
	for ( new i = 1; i <= MaxClients; ++i ) {
		if ( IsClientInGame(i) && GetClientTeam(i) > 1 ) {
			fArray[iSize] = GetEntProp(i, Prop_Data, "m_iFrags") / float(GetEntProp(i, Prop_Data, "m_iDeaths"));
			iArray[iSize++] = i;
		}
	}
	
	// сортировка методом пузырьков
	for ( new i = 0; i < iSize; ++i ) {
		for ( new j = i; j < iSize; ++j ) {
			if ( fArray[j] > fArray[i] ) {
				fDifference = fArray[i];
				fArray[i] = fArray[j];
				fArray[j] = fDifference;
				
				iArray[i] = iArray[i] + iArray[j];
				iArray[j] = iArray[i] - iArray[j];
				iArray[i] = iArray[i] - iArray[j];
			}
		}
	}
	
	// сама балансировка
	bTeam = (GetClientTeam(iArray[0]) == CS_TEAM_CT)?true:false;
	fDifference = fArray[0];
	for ( new i = 1; i < iSize; ++i ) {
		if ( fDifference>0 ) {
			CS_SwitchTeam(iArray[i], bTeam?2:3);
			CS_RespawnPlayer(iArray[i]);
			fDifference -= fArray[i];
		}
		else {
			CS_SwitchTeam(iArray[i], bTeam?3:2);
			CS_RespawnPlayer(iArray[i]);
			fDifference += fArray[i];
		}
	}
}
 

hanson

Участник
Сообщения
303
Реакции
15
Второй проблемой такой балансировки будет частое перебрасывание игроков из одной команды в другую, особенно для тех, кто в конце списка (небольшие к\д).
А если указать допустимую разницу например равной 2, или 3, или еще какой-то другой, чтбы было комфортно играть. Кстати можно ведь сделать чтобы перемещение игроков было только при определенной разнице в победах команд. Допустим это значение равно 5, тогда, если счет межну комадама 10-14-баланс не производится, если счет 10-18 балансировка работает. Также, как вариант, не производить балансировку каждый раунд, а только раз в n-раундов.

Добавлено через 10 часов 17 минут
Reiko1231, а вот такой еще вариант, четь проще.
Если разница в счете команд больше N, то за проигрывающую команду кидаем топового игрока из выигрывающей, а в выигрывающую кидаем самого худшего игрока из проигрывающей. То есть меняем местами первого в выигрывающей и последнего в проигрывающей.
 
Последнее редактирование:

AleksandrM3

Участник
Сообщения
137
Реакции
2
привет не реализовывал данный плагин? если нет, то можешь написать?

Баланс по к\д не такой и сложный.
Шаг 1. Собрать в два массива айди игроков и их к\д.
Шаг 2. Отсортировать массив к\д по уменьшению и в паре с ним айди игроков (для сохранения соответствия).
Шаг 3. В переменную записать к\д первого игрока. Оставить его в своей команде. Перемещать в противоположную команду игроков, отнимая от к\д первого игрока, пока значение не станет <= 0. Перемещать игроков в команду к 1 игроку, пока к\д не станет > 0. И так до конца массива.
Сразу видна ошибка в такой балансировке - для перемещения в 1 команду условие >, в то время как 2 команды <=, что приведет к тому, что все игроки с к\д, близким к нулю, будут перемещены в одну команду, тем самым создавая дисбаланс по количеству. Вероятное решение проблемы - на каждое второе перемещение в одну и ту же команду подряд добавлять в противоположную одного игрока снизу массива.
Второй проблемой такой балансировки будет частое перебрасывание игроков из одной команды в другую, особенно для тех, кто в конце списка (небольшие к\д).
Набросок кода без этого решения под спойлером. Может быть позже доделаю с добавлением игрока снизу, но это тоже надо обдумать.

C-подобный:
public OnPluginStart()
{
    HookEvent("round_start", Ev_RoundStart, EventHookMode_Pre);
}

public Ev_RoundStart(Handle:hEvent, const String:sEvName[], bool:bDontBroadcast)
{
    decl Float:fArray[MaxClients], Float:fDifference, bool:bTeam, iArray[MaxClients], iSize;
   
    // собираем массив из игроков и их индексов
    iSize = 0;
    for ( new i = 1; i <= MaxClients; ++i ) {
        if ( IsClientInGame(i) && GetClientTeam(i) > 1 ) {
            fArray[iSize] = GetEntProp(i, Prop_Data, "m_iFrags") / float(GetEntProp(i, Prop_Data, "m_iDeaths"));
            iArray[iSize++] = i;
        }
    }
   
    // сортировка методом пузырьков
    for ( new i = 0; i < iSize; ++i ) {
        for ( new j = i; j < iSize; ++j ) {
            if ( fArray[j] > fArray[i] ) {
                fDifference = fArray[i];
                fArray[i] = fArray[j];
                fArray[j] = fDifference;
               
                iArray[i] = iArray[i] + iArray[j];
                iArray[j] = iArray[i] - iArray[j];
                iArray[i] = iArray[i] - iArray[j];
            }
        }
    }
   
    // сама балансировка
    bTeam = (GetClientTeam(iArray[0]) == CS_TEAM_CT)?true:false;
    fDifference = fArray[0];
    for ( new i = 1; i < iSize; ++i ) {
        if ( fDifference>0 ) {
            CS_SwitchTeam(iArray[i], bTeam?2:3);
            CS_RespawnPlayer(iArray[i]);
            fDifference -= fArray[i];
        }
        else {
            CS_SwitchTeam(iArray[i], bTeam?3:2);
            CS_RespawnPlayer(iArray[i]);
            fDifference += fArray[i];
        }
    }
}
 

Reiko1231

AlexTheRegent
Сообщения
508
Реакции
1,335
@Djgadzilla,
надо добавить #include <cstrike> на первую строку. вот так
C-подобный:
#include <cstrike>

public OnPluginStart()
{
   HookEvent("round_start", Ev_RoundStart, EventHookMode_Pre);
}

public Ev_RoundStart(Handle:hEvent, const String:sEvName[], bool:bDontBroadcast)
{
   decl Float:fArray[MaxClients], Float:fDifference, bool:bTeam, iArray[MaxClients], iSize;
 
   // собираем массив из игроков и их индексов
   iSize = 0;
   for ( new i = 1; i <= MaxClients; ++i ) {
       if ( IsClientInGame(i) && GetClientTeam(i) > 1 ) {
           fArray[iSize] = GetEntProp(i, Prop_Data, "m_iFrags") / float(GetEntProp(i, Prop_Data, "m_iDeaths"));
           iArray[iSize++] = i;
       }
   }
 
   // сортировка методом пузырьков
   for ( new i = 0; i < iSize; ++i ) {
       for ( new j = i; j < iSize; ++j ) {
           if ( fArray[j] > fArray[i] ) {
               fDifference = fArray[i];
               fArray[i] = fArray[j];
               fArray[j] = fDifference;
             
               iArray[i] = iArray[i] + iArray[j];
               iArray[j] = iArray[i] - iArray[j];
               iArray[i] = iArray[i] - iArray[j];
           }
       }
   }
 
   // сама балансировка
   bTeam = (GetClientTeam(iArray[0]) == CS_TEAM_CT)?true:false;
   fDifference = fArray[0];
   for ( new i = 1; i < iSize; ++i ) {
       if ( fDifference>0 ) {
           CS_SwitchTeam(iArray[i], bTeam?2:3);
           CS_RespawnPlayer(iArray[i]);
           fDifference -= fArray[i];
       }
       else {
           CS_SwitchTeam(iArray[i], bTeam?3:2);
           CS_RespawnPlayer(iArray[i]);
           fDifference += fArray[i];
       }
   }
}
у меня этот код скомпилировался.
 

Djgadzilla

Участник
Сообщения
14
Реакции
0
@Djgadzilla,
надо добавить #include <cstrike> на первую строку. вот так
C-подобный:
#include <cstrike>

public OnPluginStart()
{
   HookEvent("round_start", Ev_RoundStart, EventHookMode_Pre);
}

public Ev_RoundStart(Handle:hEvent, const String:sEvName[], bool:bDontBroadcast)
{
   decl Float:fArray[MaxClients], Float:fDifference, bool:bTeam, iArray[MaxClients], iSize;
 
   // собираем массив из игроков и их индексов
   iSize = 0;
   for ( new i = 1; i <= MaxClients; ++i ) {
       if ( IsClientInGame(i) && GetClientTeam(i) > 1 ) {
           fArray[iSize] = GetEntProp(i, Prop_Data, "m_iFrags") / float(GetEntProp(i, Prop_Data, "m_iDeaths"));
           iArray[iSize++] = i;
       }
   }
 
   // сортировка методом пузырьков
   for ( new i = 0; i < iSize; ++i ) {
       for ( new j = i; j < iSize; ++j ) {
           if ( fArray[j] > fArray[i] ) {
               fDifference = fArray[i];
               fArray[i] = fArray[j];
               fArray[j] = fDifference;
            
               iArray[i] = iArray[i] + iArray[j];
               iArray[j] = iArray[i] - iArray[j];
               iArray[i] = iArray[i] - iArray[j];
           }
       }
   }
 
   // сама балансировка
   bTeam = (GetClientTeam(iArray[0]) == CS_TEAM_CT)?true:false;
   fDifference = fArray[0];
   for ( new i = 1; i < iSize; ++i ) {
       if ( fDifference>0 ) {
           CS_SwitchTeam(iArray[i], bTeam?2:3);
           CS_RespawnPlayer(iArray[i]);
           fDifference -= fArray[i];
       }
       else {
           CS_SwitchTeam(iArray[i], bTeam?3:2);
           CS_RespawnPlayer(iArray[i]);
           fDifference += fArray[i];
       }
   }
}
у меня этот код скомпилировался.

Спасибо!
Сейчас все нормально будем тестить)
 
Сверху Снизу