Установка минимальных уровней

Тема в разделе "Общего назначения", создана пользователем Flame, 4 мар 2014.

  1. Flame

    Flame -Заслуженый кодер форума-

    SetMinLevelMut - новая реализация
    Внимательно прочтите замечания к мутатору!

    Итак,
    Мутатор выставляет уровни игрокам, при этом сам кач не затрагивается
    То есть, например, игроку выставляется 6 снайпер и он играет с возможностями 6 уровня, но при этом для 7 снайпера ему надо пройти расстояние от 0 до 7 уровня целиком.

    Зачем это надо - читайте в реализации старой версии мутатора

    Настройки:
    Код:
    [SetMinLevelMut.SetMinLevelMut]
    MinLevelList=(PlayerName="Flame",Hash="76561198051378449",Levels=(6,4,2,4,2,5,3))
    
    PlayerName - Имя игрока (просто для удобства)
    Hash - Хэш игрока, которому мы выставляем уровни
    Levels - Динамический массив уровней перков. При этом если у вас на сервере есть дополнительные перки - ничего страшного.
    Достаточно просто продолжить массив. Массив составляется согласно значениям PerkIndex в SRVet* классах.
    То есть по умолчанию порядок такой: Медик,Сапп,Снайпер,Командо,Берс,Фаер,Подрыв

    Код:
    Код:
    class SetMinLevelMut extends Mutator config(SetMinLevelMut);
    
    struct MinLevelStruct
    {
        var config string PlayerName;
        var config string Hash;
        var config array<byte> Levels; //Массив с уровнями перков. Может быть сколько угодно перков и соотв. уровней
    };
    var config array<MinLevelStruct> MinLevelList;
    
    function PostBeginPlay()
    {
        SaveConfig();
    }
    
    //PlayerChangedClass - стандартная функция класса Mutator, но она в кф не используется.
    //Чего бы не поиспользовать. Для этого поправим код ServerStStats.ServerSelectPerk и вызовем эту функцию там при смене перка
    function PlayerChangedClass(Controller aPlayer)
    {
        SetMinLevelFromList(PlayerController(aPlayer));
        if(NextMutator != None)
            NextMutator.PlayerChangedClass(aPlayer);
    }
    
    function SetMinLevelFromList(PlayerController PC)
    {
        local KFPlayerReplicationInfo KFPRI;
        local byte currentPerkIndex;
        local int i,j;
        local string Hash;
        local ClientPerkRepLink ST;
    
        KFPRI = KFPlayerReplicationInfo(PC.PlayerReplicationInfo);
        if(KFPRI==none || KFPRI.ClientVeteranSkill==none)
            return;
        Hash=PC.GetPlayerIDHash();
        for(i=0;i<MinLevelList.Length;i++)
        {
            if(MinLevelList[i].Hash~=Hash)
            {
                currentPerkIndex=KFPRI.ClientVeteranSkill.default.PerkIndex;
                ST = Class'ClientPerkRepLink'.Static.FindStats(PC);
                if(currentPerkIndex<MinLevelList[i].Levels.Length)
                {
                    //Выставляем текущий перк в соотв. с данными массива
                    KFPRI.ClientVeteranSkillLevel=Max(KFPRI.ClientVeteranSkillLevel,MinLevelList[i].Levels[currentPerkIndex]);
                    //Отрисуем правильное отображение перков в GUI
                    //Внимание! Если у вас массив Perks в ServerPerks.ini не синхронен с PerkIndex в
                    //SRVet* классах - закомментируйте этот код, иначе будет неправильное отображение уровней
                    //Или поправьте массив Perks (следующий порядок: Медик,Сапп,Снайпер,Командо,Берс,Фаер,Подрыв)
                    for(j=0;j<MinLevelList[i].Levels.Length;j++)
                        ST.CachePerks[j].CurrentLevel=Max(ST.CachePerks[j].CurrentLevel-1,MinLevelList[i].Levels[j])+1;
                    //
                }
            }
        }
    }
    
    defaultproperties
    {
        //Мы используем массив уровней перков
        //Напоминание: Медик,Сапп,Снайпер,Командо,Берс,Фаер,Подрыв
        MinLevelList(0)=(PlayerName="Flame",Hash="76561198051378449",Levels=(6,4,2,4,2,5,3))
        GroupName="KF-SetMinLevel"
        FriendlyName="SetMinLevel"
        Description="Set Minimum Level"
    }
    

    Ссылка 1 или Ссылка 2
    SetMinLevelMut.SetMinLevelMut

    Замечание 1:
    Данная версия мутатора работает только с SP. Чтобы мутатор заработал надо поправить код ServerStStats.ServerSelectPerk
    Добавьте после строчки
    Код:
    KFPlayerReplicationInfo(PlayerOwner.PlayerReplicationInfo).ClientVeteranSkillLevel = Rep.CachePerks[i].CurrentLevel-1;
    
    Строчку
    Код:
    Level.Game.BaseMutator.PlayerChangedClass(PlayerOwner);
    
    Замечание 2: Кроме того, что в этой реализации можно прописывать уровни для любого количества перков, данная реализация ещё и отрисовывает выставленные уровни в списке перков.
    [​IMG]
    Но для этого надо, чтобы в массиве Perks в ServerPerks.ini был тот же порядок перков "Медик,Сапп,Снайпер,Командо,Берс,Фаер,Подрыв"
    В противном случае закомментируйте или удалите строки
    Код:
    for(j=0;j<MinLevelList[i].Levels.Length;j++)
        ST.CachePerks[j].CurrentLevel=Max(ST.CachePerks[j].CurrentLevel-1,MinLevelList[i].Levels[j])+1;
    
    Старая реализация:
    Описание:
    Иногда бывают такие ситуации, когда есть смысл поставить определённым людям стартовый уровень выше базового. Без изменения самой статистики кача.
    Допустим человеку надоело играть на каком-то сервере и хочется перейти на другой, но очень уж не хочется качаться с нуля.
    Иногда есть смысл пойти навстречу игроку, особенно если есть хорошие связи с админами его предыдущего сервера и можно проверить его перки (ну и требования к качу более-менее совпадают).

    Данный простенький мутатор позволяет зафиксировать ему начальные уровни выше базовых, но при этом качаться он будет с 0.
    То есть уровень у него может быть установлен сразу 6, например, но чтобы ему получить 7 уровень - ему придётся прокачать перк с 0 до 7.
    Таким образом будет достигнут какой-никакой, а компромисс.
    Настройки вынесены в ini и они достаточно простые
    Код:
    [SetMinLevelMut.SetMinLevelMut]
    TimerPeriod=3.000000
    MinLevelList=(Hash="76561111111111111",bLevel=10,mLevel=9,spLevel=8,cmLevel=7,dmLevel=6,fLevel=5,ssLevel=4)
    
    Здесь TimerPeriod - период таймера, который проверяет не пора ли поменять уровень,
    а каждый элемент массива MinLevelList представляет из себя структуру, которая содержит Hash игрока и настройки для минимального уровня для всех перков.
    Описание остальных элементов структуры
    bLevel - Berserker Level
    mLevel - FieldMedic Level
    spLevel - SupportSpec Level
    cmLevel - Commando Level
    dmLevel - Demolitions Level
    fLevel - FireBug Level
    ssLevel - Sharpshooter Level
    Код:
    Код:
    class SetMinLevelMut extends Mutator config(SetMinLevelMut);
    
    struct MinLevelStruct
    {
        var() config string Hash;
        var() config int bLevel;
        var() config int mLevel;
        var() config int spLevel;
        var() config int cmLevel;
        var() config int dmLevel;
        var() config int fLevel;
        var() config int ssLevel;
    };
    var config array<MinLevelStruct> MinLevelList;
    var config float TimerPeriod;
    
    function PostBeginPlay()
    {
        SaveConfig();
        SetTimer(TimerPeriod, true);
    }
    
    function Timer()
    {
        local Controller C;
        for( C = Level.ControllerList; C != None; C = C.nextController )
        {
            if    (
                    C.IsA('PlayerController')
                    &&    C.PlayerReplicationInfo!=none
                    &&    C.PlayerReplicationInfo.PlayerID>0
                )
            {
                SetMinLevelFromList(PlayerController(C));
            }
        }
    
    }
    
    function SetMinLevelFromList(PlayerController PC)
    {
        local int i;
        local KFPlayerReplicationInfo KFPRI;
        local string Hash;
        KFPRI = KFPlayerReplicationInfo(PC.PlayerReplicationInfo);
        Hash=PC.GetPlayerIDHash();
        for(i=0;i<MinLevelList.Length;i++)
        {
            if(Hash~=MinLevelList[I].Hash)
            {
                if(InStr(Caps(string(KFPRI.ClientVeteranSkill.Name)),Caps("VetBerserker"))>=0)
                    KFPRI.ClientVeteranSkillLevel=Max(KFPRI.ClientVeteranSkillLevel,MinLevelList[I].bLevel);
                else if(InStr(Caps(string(KFPRI.ClientVeteranSkill.Name)),Caps("VetFieldMedic"))>=0)
                    KFPRI.ClientVeteranSkillLevel=Max(KFPRI.ClientVeteranSkillLevel,MinLevelList[I].mLevel);
                else if(InStr(Caps(string(KFPRI.ClientVeteranSkill.Name)),Caps("VetFirebug"))>=0)
                    KFPRI.ClientVeteranSkillLevel=Max(KFPRI.ClientVeteranSkillLevel,MinLevelList[I].fLevel);
                else if(InStr(Caps(string(KFPRI.ClientVeteranSkill.Name)),Caps("VetSharpshooter"))>=0)
                    KFPRI.ClientVeteranSkillLevel=Max(KFPRI.ClientVeteranSkillLevel,MinLevelList[I].ssLevel);
                else if(InStr(Caps(string(KFPRI.ClientVeteranSkill.Name)),Caps("VetSupportSpec"))>=0)
                    KFPRI.ClientVeteranSkillLevel=Max(KFPRI.ClientVeteranSkillLevel,MinLevelList[I].spLevel);
                else if(InStr(Caps(string(KFPRI.ClientVeteranSkill.Name)),Caps("VetCommando"))>=0)
                    KFPRI.ClientVeteranSkillLevel=Max(KFPRI.ClientVeteranSkillLevel,MinLevelList[I].cmLevel);
                else if(InStr(Caps(string(KFPRI.ClientVeteranSkill.Name)),Caps("VetDemolitions"))>=0)
                    KFPRI.ClientVeteranSkillLevel=Max(KFPRI.ClientVeteranSkillLevel,MinLevelList[I].dmLevel);
                if(PC.Pawn!=None) KFHumanPawn(PC.Pawn).VeterancyChanged();
            }
        }
    }
    
    defaultproperties
    {
        TimerPeriod=4.0
        bAddToServerPackages=True
        GroupName="KF-SetMinLevel"
        FriendlyName="SetMinLevel"
        Description="Set Minimum Level"
    }
    
    Ссылка 1 или Ссылка 2
    SetMinLevelMut.SetMinLevelMut

    Замечание:
    Так как изменение уровней происходит в таймере, то возможно, что игрок будет появляться с базовыми минимальными уровнями и без перковых пушек. Ну тут можно посоветовать, либо ставить маленький период таймера (но тогда фиг знает насколько мутатор будет напрягать сервак), либо отказаться от идеи настраивать каждый перк и править тогда Stat.Rep.MinimumLevel в функции ServerPerksMut.SetServerPerks.
    Ну или можно просто отлавливать создание контроллеров или тел в CheckReplacement. Сейчас накидаю, пожалуй, ещё и такую версию.
    Собственно вот она.
    Код:
    Код:
    class SetMinLevelMut extends Mutator config(SetMinLevelMut);
    
    struct MinLevelStruct
    {
        var() config string Hash;
        var() config int bLevel;
        var() config int mLevel;
        var() config int spLevel;
        var() config int cmLevel;
        var() config int dmLevel;
        var() config int fLevel;
        var() config int ssLevel;
    };
    var config array<MinLevelStruct> MinLevelList;
    var config float TimerPeriod;
    var array<KFHumanPawn> PendingPlayers;
    var float NextCheckNChangeLevelTime;
    
    function PostBeginPlay()
    {
        SaveConfig();
        SetTimer(TimerPeriod, true);
    }
    
    function bool CheckReplacement(Actor Other, out byte bSuperRelevant)
    {
        if( KFHumanPawn(Other)!=None )
        {
            PendingPlayers[PendingPlayers.Length] = KFHumanPawn(Other);
            SetTimer(0.1,false);
        }
        return true;
    }
    
    function Tick(float delta)
    {
        local Controller C;
        if(Level.TimeSeconds>NextCheckNChangeLevelTime)
        {
            for( C = Level.ControllerList; C != None; C = C.nextController )
            {
                if    (
                        C.IsA('PlayerController')
                        &&    C.PlayerReplicationInfo!=none
                        &&    C.PlayerReplicationInfo.PlayerID>0
                    )
                {
                    SetMinLevelFromList(PlayerController(C));
                }
            }
            NextCheckNChangeLevelTime=Level.TimeSeconds + TimerPeriod;
        }
        Super.Tick(delta);
    }
    
    function Timer()
    {
        local int i;
        local KFHumanPawn cPawn;
        for(i=PendingPlayers.Length-1;i>=0;--i)
        {
            cPawn=PendingPlayers[I];
            if    (
                    cPawn.PlayerReplicationInfo!=none
                    &&    cPawn.PlayerReplicationInfo.PlayerID>0
                )
            {
                SetMinLevelFromList(PlayerController(cPawn.Controller));
            }
        }
        PendingPlayers.Length = 0;
    }
    
    function SetMinLevelFromList(PlayerController PC)
    {
        local int i;
        local KFPlayerReplicationInfo KFPRI;
        local string Hash;
        KFPRI = KFPlayerReplicationInfo(PC.PlayerReplicationInfo);
        if(KFPRI==none || KFPRI.ClientVeteranSkill==none) return;
        Hash=PC.GetPlayerIDHash();
        for(i=0;i<MinLevelList.Length;i++)
        {
            if(Hash~=MinLevelList[I].Hash)
            {
                if(InStr(Caps(string(KFPRI.ClientVeteranSkill.Name)),Caps("VetBerserker"))>=0)
                    KFPRI.ClientVeteranSkillLevel=Max(KFPRI.ClientVeteranSkillLevel,MinLevelList[I].bLevel);
                else if(InStr(Caps(string(KFPRI.ClientVeteranSkill.Name)),Caps("VetFieldMedic"))>=0)
                    KFPRI.ClientVeteranSkillLevel=Max(KFPRI.ClientVeteranSkillLevel,MinLevelList[I].mLevel);
                else if(InStr(Caps(string(KFPRI.ClientVeteranSkill.Name)),Caps("VetFirebug"))>=0)
                    KFPRI.ClientVeteranSkillLevel=Max(KFPRI.ClientVeteranSkillLevel,MinLevelList[I].fLevel);
                else if(InStr(Caps(string(KFPRI.ClientVeteranSkill.Name)),Caps("VetSharpshooter"))>=0)
                    KFPRI.ClientVeteranSkillLevel=Max(KFPRI.ClientVeteranSkillLevel,MinLevelList[I].ssLevel);
                else if(InStr(Caps(string(KFPRI.ClientVeteranSkill.Name)),Caps("VetSupportSpec"))>=0)
                    KFPRI.ClientVeteranSkillLevel=Max(KFPRI.ClientVeteranSkillLevel,MinLevelList[I].spLevel);
                else if(InStr(Caps(string(KFPRI.ClientVeteranSkill.Name)),Caps("VetCommando"))>=0)
                    KFPRI.ClientVeteranSkillLevel=Max(KFPRI.ClientVeteranSkillLevel,MinLevelList[I].cmLevel);
                else if(InStr(Caps(string(KFPRI.ClientVeteranSkill.Name)),Caps("VetDemolitions"))>=0)
                    KFPRI.ClientVeteranSkillLevel=Max(KFPRI.ClientVeteranSkillLevel,MinLevelList[I].dmLevel);
                if(PC.Pawn!=None) KFHumanPawn(PC.Pawn).VeterancyChanged();
            }
        }
    }
    
    defaultproperties
    {
        TimerPeriod=4.0
        MinLevelList(0)=(Hash="76561198051378449",bLevel=10)
        bAddToServerPackages=True
        GroupName="KF-SetMinLevel"
        FriendlyName="SetMinLevel"
        Description="Set Minimum Level"
    }
    
    Ссылка 1 или Ссылка 2

    Замечание 2:
    Благодарите ВАНО )
    Он меня пинал периодически, чтобы я не забывал про этот мут, и вот дошли руки )
    Кому я там что обещал - тож напоминайте )
     
    Последнее редактирование: 2 окт 2016
    kok-s, denfil777, Фрэгл и 8 другим нравится это.
  2. Dr_Killjoy

    Dr_Killjoy Заблокированные

    Просто улёт. Мне даже в голову не приходило что эту фишку можно таким простым способом реализовать.
     
  3. Винни

    Винни Мододел

    Отличная работа :thumbsup: 5+
     
  4. BAHO

    BAHO Fresh Meat

    Пол года пинал ВАНО :D
    Еще раз благодарю :)
     
    denfil777 нравится это.
  5. ЛОХМАТЫЙ

    ЛОХМАТЫЙ •*´¨`*•.,¸¸,.•*´¨`*•.,¸¸,.•*´¨`*•

    Есть несколько серверов, на которых играют перками разных уровней.
    "Кадет", "Капитан" и т.д. (да-да, Proton Ascending)
    На "Кадете" могут играть не выше 8-го уровня.
    9-й и выше - кикает. И ещё может кикнуть при выпадении в !rtd 13-го уровня.

    Какими средствами можно срезать "лишний" уровень ?
    Т.е. заходи хоть 255-м уровнем, но максимальный у тебя будет, скажем, 6-й, со всеми бонусами 6-го. При этом как идёт.
    (само собой, что ограничение должно быть настраиваемым,
    но в данном случае, имхо, лучше урезать именно ниже максимально допустимого :wink: )

    Вроде, этот мутатор близок, но не совсем то.
    Мне просто любопытно, насколько это сложно технически.
     
  6. Flame

    Flame -Заслуженый кодер форума-

    Это просто. Если надо сделаю и такую версию. Если не забуду )
     
    ЛОХМАТЫЙ нравится это.
  7. ЛОХМАТЫЙ

    ЛОХМАТЫЙ •*´¨`*•.,¸¸,.•*´¨`*•.,¸¸,.•*´¨`*•

    Я подозреваю, что даже можно (в смысле - несложно и разумно) сделать "два в одном" как раз для таких групп серверов - с разными уровнями перков и общей базой.

    Не могу сказать, надо или нет - Протон пока не в курсе моих коварных замыслов и интриг :rolleyes:
    Может, на "Карантинах" пригодилось бы.
     
  8. AitherKill

    AitherKill Солдат

    Новайса то теперь нет , теперь только 1 основной будет... хотя все еще может случиться.
     
  9. Stein

    Stein Солдат

    а как допустим сделать всем уровень выше принудительно в качестве бонуса в праздники например?
     
  10. gall87

    gall87 Капо

    В сервер конфиге(Точней в ServerPerks.ini)
    MinPerksLevel=14
     
  11. Flame

    Flame -Заслуженый кодер форума-

    Как я уже писал - я в ближайшее время намерен поправить все свои старые мутаторы и статьи
    Ну и добавить новые)
    Когда я накнулся на данный мутатор - его реализация произвела на меня очень тягостное впечатление)
    Но в то же время я не слишком представлял, как его поправить, чтобы изменения были существенные и выглядело бы это симпатично

    Чем были плохи прошлые реализации?
    1 реализация тупо бегала в таймер каждые N секунд и легко могла проскочить смену перка и игрок заспавнился бы с неправильными пушками
    2 реализация позволяла в самом начале игры избежать проблемы 1 реализации, а дальше опять циклические проверки (на этот раз уже в тике)
    Полистал я класс Mutator и наткнулся на функцию PlayerChangedClass, в нашем случае она не используется и я решил её присвоить себе)
    А для этого мне надо было вмешаться в ServerPerks чуть-чуть. А именно в ту функцию, которая и вызывается при смене перка
    Функцию ServerSelectPerk
    Я и вмешался. И, кстати, этот вызов функции мутатора при смене класса вам ещё кучу раз пригодится, если будете править свой сервак)

    В общем я прямо прусь от этой реализации - я молодец))
    Ссылка на первый пост с поправленным мутатором
     
    w.a.l нравится это.