Игрок с наименьшим кол-вом очков CS:GO

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

  1. denj

    denj

    Сообщения:
    30
    Симпатии:
    0
    Подскажите как правильно получить индекс игрока с наименьшим количеством очков:dntknw:
     
  2. denj

    denj

    Сообщения:
    30
    Симпатии:
    0
    Спасибо за ответ, но что-то не получается.
    Попробую объяснить задачу подробнее: нужно в конце каждого раунда получать в переменную worstplayer индекс игрока у которого меньше всех очков и говорить что-то вроде PrintToChatAll("Худший игрок на сервере %N", worstplayer)
     
  3. denj

    denj

    Сообщения:
    30
    Симпатии:
    0
    Пишел "Худший игрок на сервере Console":-D
     
  4. denj

    denj

    Сообщения:
    30
    Симпатии:
    0
    Сам делал так (язык изучаю только второй день, так что не бейте)
    PHP:
            new score[MaxClients];
            new 
    cur_players;
            for (new 
    1<= MaxClientsi++) // цикл будет заносит в массив список очков
            
    {
                if (
    IsClientInGame(i))
                {
                    
    score[i] = CS_GetClientContributionScore(i); //получаем список очков в масив score[]
                    
    cur_players++;
                }
            }
            
    SortIntegers(score[1], cur_playersSort_Ascending); //сортируем
            
    for (new 1<= MaxClientsi++)
            {
                if (
    IsClientInGame(i))
                {
                    if (
    CS_GetClientContributionScore(i) == score[1]) //ищем игрока с наименьшим кол-вом очков
                    
    {
                        
    PrintToChatAll("Худший игрок на сервере %N"i
                    }
                }
            }
    Так вроде работало, но в какой-то момент, происходил баг и массив score[] сдвигался на 1 шаг, т.е. score[1] становилось 0 всегда, а score[2] показывало то, что раньше показывало score[1] как-то так
     
  5. AlmazON

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

    Сообщения:
    4.528
    Симпатии:
    1.974
    Индекс игрока может записываться в сам массив, но не является верным показателем размерности его заполнения (если только сервер не полон):
    PHP:
    score[cur_players++] = CS_GetClientContributionScore(i);
    Ну и дальше массив должен быть вписан верно.
    По твоей схеме где-то так:
    PHP:
            decl score[MaxClients];
            new 
    cur_players;
            for (new 
    1<= MaxClientsi++) // цикл будет заносит в массив список очков
            
    {
                if (
    IsClientInGame(i))
                {
                    
    score[cur_players++] = CS_GetClientContributionScore(i); //получаем список очков в масив score[]
                
    }
            }
            
    SortIntegers(scorecur_playersSort_Ascending); //сортируем
            
    for (new 1<= MaxClientsi++)
            {
                if (
    IsClientInGame(i))
                {
                    if (
    CS_GetClientContributionScore(i) == score[0]) //ищем игрока с наименьшим кол-вом очков
                    
    {
                        
    PrintToChatAll("Худший игрок на сервере %N"i);
                        break;
                    }
                }
            } 
     
    denj нравится это.
  6. denj

    denj

    Сообщения:
    30
    Симпатии:
    0

    Спасибо большое! Пока что работает, но опять же я так и не понял, почему при старом коде массив иногда сбивался на 1 шаг?:blush2:
     
  7. AlmazON

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

    Сообщения:
    4.528
    Симпатии:
    1.974
    Поскольку у тебя new score[MaxClients];, то весь массив по умолчанию наполнен (инициализирован) нулями. Так вот один из этих нулей и уходит почти постоянно в score[1]:
    Так как ты неправильно засчитал его валидным игроком.
     
    denj нравится это.
  8. denj

    denj

    Сообщения:
    30
    Симпатии:
    0
    А не подскажешь теперь как сделать так, чтобы раунд не заканчивался, пока у нескольких игроков минимальный счет? Т.е. раундтайм закончился, но раунд должен продолжаться до момента, когда только один из игроков будет иметь минимальный счет?
     
  9. AlmazON

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

    Сообщения:
    4.528
    Симпатии:
    1.974
    Для блокировки при наступлении конца раунда:
    PHP:
    #include <cstrike>

    public Action:CS_OnTerminateRound(&Float:delay, &CSRoundEndReason:reason)
    {
       if(
    g_bBlock) return Plugin_Handled;
       return 
    Plugin_Continue;
    }
    Где g_bBlock - "сигнальная" bool переменная. Должна содержать true, когда худших игроков несколько.
    Далее отлавливаешь событие смерти и проверяешь счёт игроков. Так до тех пор, пока неудачливый игрок не останется один, после чего сам вызываешь конец раунда через натив CS_TerminateRound(Float:delay, CSRoundEndReason:reason, bool:blockhook = false);.
    Возможно, вызывать и не понадобится - зависит от настроек игры (с CS:GO не знаком).
     
    denj нравится это.
  10. denj

    denj

    Сообщения:
    30
    Симпатии:
    0
    Можно подробнее про натив, что это?)
     
  11. Reiko1231

    Reiko1231 AlexTheRegent

    Сообщения:
    237
    Симпатии:
    569
    Лучший способ для поиска худшего игрока - один цикл. Решение с сортировкой хуже, т.к. всё равно требуется один цикл по всем игрокам с целью получения их счета.
    Код:
    #include <cstrike>
    
    new bool:	g_bBlockRoundEnd;
    
    public OnPluginStart() 
    {
    	HookEvent("player_death", 	Ev_PlayerDeath);
    	HookEvent("round_start", 	Ev_RoundStart);
    }
    
    GetWorstPlayer()
    {
    	new iWorstScore = 9999, iWorstPlayer;
    	for ( new i = 1; i <= MaxClients; ++i ) {
    		if ( IsClientInGame(i) && GetClientTeam() > 1 ) {
    			new iScore = CS_GetClientContributionScore(i);
    			if ( iWorstScore > iScore ) {
    				iWorstScore = iScore;
    				iWorstPlayer = i;
    			}
    			else if ( iWorstScore == iScore ) {
    				iWorstPlayer = 0;
    			}
    		}
    	}
    	return iWorstPlayer;
    }
    
    public Ev_RoundStart(Handle:hEvent, const String:sEvName[], bool:bSilent)
    {
    	g_bBlockRoundEnd = true;
    }
    
    public Ev_PlayerDeath(Handle:hEvent, const String:sEvName[], bool:bSilent)
    {
    	new iWorstPlayer = GetWorstPlayer();
    	if ( iWorstPlayer ) {
    		PrintToChatAll("Худший игрок: %N", iWorstPlayer);
    		g_bBlockRoundEnd = false;
    	}
    }
    
    public Action:CS_OnTerminateRound(&Float:delay, &CSRoundEndReason:reason)
    {
    	return g_bBlockRoundEnd?Plugin_Handled:Plugin_Continue;
    }
    CS_OnTerminateRound - вызывается во время завершения раунда. Plugin_Continue - разрешить завершение, используя задержку и причину из входных аргументов, Plugin_Handled и выше - заблокировать завершение раунда. Будет вызываться до тех пор, пока в конце концов все плагины, использующие его, не вернут через него Plugin_Continue;
     
    denj нравится это.
  12. AlmazON

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

    Сообщения:
    4.528
    Симпатии:
    1.974
    Натив (native) - прямая внутренняя функция, уже предусмотренная в приложениях SourcePawn.
    В нашем случае, это принудительный вызов конца раунда в играх cstrike (CS_TerminateRound).
     
    denj нравится это.
  13. denj

    denj

    Сообщения:
    30
    Симпатии:
    0
    Большое спасибо за разъяснение. Но если использую твой код, то он просто спамит в чат во время раунда:dntknw:
     
  14. Reiko1231

    Reiko1231 AlexTheRegent

    Сообщения:
    237
    Симпатии:
    569
    Это набросок кода, так как я не понимаю, зачем нужно останавливать раунд до тех пор, пока один из игроков не станет худшим. Ведь все игроки будут мертвы, а значит как кто-то станет хуже? В коде я набросал скелет, который содержит в себе функцию поиска худшего игрока и механизм остановки раунда, дальше его нужно модифицировать, как тебе нужно. Сейчас то там идет поиск худшего игрока сразу, т.к. нет проверки на то, сколько игроков осталось в живых, поэтому при каждой смерти ищется худший игрок, если такой есть. Кстати, я допустил небольшую опечатку - GetClientTeam() > 1 нужно заменить на GetClientTeam(i) > 1.

    P.S. И да, возможно придется вручную вызывать CS_TerminateRound(). Данная функция аналогична форварду, только является функцией.
     
    Последнее редактирование: 7 июн 2015
    denj нравится это.
  15. denj

    denj

    Сообщения:
    30
    Симпатии:
    0
    Теперь встал вопрос как искать худшего игрока и среди отключившихся, т.к. когда матч запущен, то после отключения клиента его статистика где-то сохраняется.
     
  16. denj

    denj

    Сообщения:
    30
    Симпатии:
    0
    массив обновляется при любой смерти на сервере.
    А если убрать IsClientInGame, то в консоле пишет ошибку связанную с CS_GetClientContributionScore и все перестает работать)

    Добавлено через 1 час 18 минут
    Кто-нибудь знает где хранится статистика отключившегося игрока?
     
    Последнее редактирование: 7 июн 2015
  17. AlmazON

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

    Сообщения:
    4.528
    Симпатии:
    1.974
    Лучше сохраняй всё в глобальный массив перед отключением игрока, а то и после каждой смерти, если итак задействуешь там подсчёт.