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

Тема в разделе "Программирование / Скриптинг", создана пользователем hanson, 14 май 2015.

  1. hanson

    hanson

    Сообщения:
    303
    Симпатии:
    15
    Здравствуйте.

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

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

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

    Как вам идея?
     
  2. AlmazON

    AlmazON деревянный © yand3xmail

    Сообщения:
    4.563
    Симпатии:
    1.988
    Ошибаешься. Это уже мудрёно будет. Перекидывать самых результативных игроков - ещё одно, но кидать ещё и именно тех, чтобы общие коэффициенты выровнялись - уже думать надо.
    Можно конечно и тупо кучу циклов наделать) Оффтоп
     
  3. R1KO

    R1KO Супер-модератор

    Сообщения:
    6.000
    Симпатии:
    2.992
    Ну не 2 а 2.0 прийдется работать с дробными числами. А фраги и киллы записывать не в логи, а в память.
     
  4. hanson

    hanson

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

    R1KO Супер-модератор

    Сообщения:
    6.000
    Симпатии:
    2.992
    hanson, сложность в посчете среднего коэффициента
     
  6. hanson

    hanson

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

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

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

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


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

    Reiko1231 AlexTheRegent

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

    Код:
    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];
    		}
    	}
    }
     
    Andy Freeman и san911 нравится это.
  8. hanson

    hanson

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

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