Вопросы к кодерам и мододелам

Тема в разделе "Игровое редактирование", создана пользователем Фрэгл, 20 ноя 2011.

  1. 2/5

    2/5 Соучастник

    Добавь в SRPlayerReplicationInfo такой код
    Код:
    simulated function PostBeginPlay()
    {
        local bool bCustomView;
        if(Role<Role_Authority)
        {
            bCustomView=bool(class'SRMySettings'.static.Get("bCustomView"));
            SendSettingsToServer("bEnhancedShoulderView",string(int(bCustomView)));
            bEnhancedShoulderView=bCustomView;
        }
        Super.PostBeginPlay();
    }
    
    Ну или поправь, если у тебя уже есть PostBeginPlay
     
    Последнее редактирование: 8 окт 2016
    RaideN111 нравится это.
  2. Essence

    Essence Бандит

    Мда... Очень корявенько я код повырезал.
    SRPlayerReplicationInfo буду использовать в отдельной вкладке и в SRVeterancyTypes.
    Надо всё-таки потом выделить под эти реализации отдельную тему.
    Они имеют широкое применение.
    Большое спасибо за помощь.
    Как всегда выручаешь :)
     
  3. Essence

    Essence Бандит

    Есть ещё 3 вопросика:
    1) Реально ли отследить кол-во вылеченных игроков (ну и разумеется, сохранять это значение в инишке)?
    2) Как сделать так, чтобы сообщение после выполнения условия высветилось только 1 раз?
    А то у меня получается, что условие постоянно выполняется, соответственно я получаю кучу спама.)

    upd.

    3) Как в PatDamageStoreRules добавить массив SRPRI (нужно для суммирования текущего урона)? Пробовал по разному, ничего не выходит. Остановился пока на этом варианте:
    Код:
    var array<SRPlayerReplicationInfo> PlayerList;
    ...
    function bool CheckReplacement(Actor Other, out byte bSuperRelevant)
    {
        if (Other.IsA('SRPlayerReplicationInfo'))
        {
            PlayerList[PlayerList.Length] = SRPlayerReplicationInfo(Other);
        }
        if(PlayerController(Other)!=None)
        {
            PendingPlayers[PendingPlayers.Length] = PlayerController(Other);
            SetTimer(0.1,false);
        }
        return true;
    }
    Код:
    function int NetDamage( int OriginalDamage, int Damage, Pawn Injured, Pawn InstigatedBy, vector HitLocation, out vector Momentum, class<DamageType> DamageType )
    {
        local SRPlayerReplicationInfo SRPRI;
        local PlayerController PC;
        local int tmpDamage, i, sum;
        if(Injured==None || InstigatedBy==None)
        {
            if ( NextGameRules != None)
                return NextGameRules.NetDamage(OriginalDamage, Damage, injured, instigatedBy, HitLocation, Momentum, DamageType);
            return Damage;
        }
        if    (
                (Injured.IsA('ZombieBoss') || Injured.IsA('HardPat'))
                &&    InstigatedBy.IsA('KFHumanPawn')
                &&    InstigatedBy!=none
                &&    InstigatedBy.Controller.IsA('PlayerController')
                &&    Damage>0
            )
        {
            PC = PlayerController(instigatedBy.Controller);
            if(PC!=None)
                SRPRI = SRPlayerReplicationInfo(PC.PlayerReplicationInfo);
    
            if(PC==None || SRPRI==None)
            {
                if(NextGameRules != None)  
                    return NextGameRules.NetDamage(OriginalDamage, Damage, injured, instigatedBy, HitLocation, Momentum, DamageType);
                return Damage;
            }
            //Получаем уже нанесённый ранее урон
            tmpDamage=int(InstigatedBy.PlayerReplicationInfo.GetPropertyText("PatDamage"));
            //Суммируем текущий урон всех игроков
            for(i=0;i<mut.PlayerList.Length;i++)
            {
                sum+=mut.PlayerList[i].DamPat;
                if(sum>100)
                {
                    BroadcastLocalizedMessage(Class'Message',,SRPRI);
                    ...
                }
                else
                {
                    ...
                }
            }
            //Добавляем к нему новый урон и сохраняем в переменной SRPlayerReplicationInfo.PatDamage
            InstigatedBy.PlayerReplicationInfo.SetPropertyText("PatDamage",string(tmpDamage+Damage));
            //Добавляем текущий урон и сохраняем в переменной SRPlayerReplicationInfo.DamPat
            SRPRI.DamPat += Damage;
            //Выводим сообщение
            PlayerController(InstigatedBy.Controller).ClientMessage("DamageToPat"@tmpDamage+Damage);
        }
        if ( NextGameRules != None )
            return NextGameRules.NetDamage( OriginalDamage, Damage,injured,instigatedBy,HitLocation,Momentum,DamageType );
        return Damage;
    }
     
    Последнее редактирование: 9 окт 2016
  4. Flame

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

    1. Добавь урон (можешь 0) к мед пушкам (допиши DamageType к HealingProjectile и похожим классам) и отслеживай урон с этими типами урона в GameRules.NetDamage
    Редактировать сами Projectile классы как ты понимаешь не обязательно
    Код:
    class'KFMod.HealingProjectile'.defaults.MyDamageType="СвойТипУрона"
    
    2. Вообще не понял этот пункт

    3. Не понял нахрена тебе это тащить из мутатора то? Чем цикл по всем игрокам плох
    Код:
    for( C = Level.ControllerList; C != None; C = C.nextController )
    {
        if(C.IsA('PlayerController') && C.PlayerReplicationInfo.PlayerID>0)
            sum+=int(C.PlayerReplicationInfo.GetPropertyText("PatDamage"));
    }
    
    Ты что вообще хочешь то? )
     
  5. Essence

    Essence Бандит

    То есть в первом случае код в GameRules.NetDamage будет примерно такой?
    Код:
        if(Injured.IsA('KFHumanPawn') && InstigatedBy.IsA('KFHumanPawn') && InstigatedBy!=None && InstigatedBy.Controller.IsA('PlayerController') && DamageType.Name == 'DamTypeHeal' && Damage>0)
        SRPRI.HealedPlayers++;
    А, ну да, цикл по игрокам тут как раз подходит. Чот забыл про него.
    Я ввёл новую переменную DamPat, отвечающую за текущий урон, нанесённый Патрику за карту. Пихаю в SRPRI.
    Потом я хочу суммировать её значение у всех игроков, и в зависимости от количества нанесённого урона, удваивать его, например.
    То есть, допустим, нанесли игроки 10к урона Патрику. Потом последующий урон по нему будет удваиваться.
    Тут как раз я хочу ещё и выводить сообщение о подобной фиче.
    Но после каждого выстрела по Патрику, сообщение вновь появляется.
    Вот я и хочу, чтобы оно высветилось только один раз при выполнении условия.
     
    Последнее редактирование: 10 окт 2016
  6. Flame

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

    Ну введи какую-нибудь глобальную переменную bMessageSent
    if(!bMessageSent) - делаем броадкаст и bMessageSent=true
     
    Essence нравится это.
  7. Essence

    Essence Бандит

    Доброго времени суток.
    Подскажите, где можно найти код, который помог бы мне сделать возвращение оружия после смерти игрока при возрождении (Сдох с топором, с ним и возродился, не взирая на то, что в AddDefaultInventory SRVet класса, например, прописан меч).
    Я так понял, эт в ModifyPawn делать нужно?
     
  8. Flame

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

    Можно ModifyPawn, можно отлавливать в CheckReplacement'е создание KFHumanPawn

    Цепляешь GameRules, отслеживаешь смерть игрока, заносишь в массив (ну например массив структур, где структура содержит PlayerID или Hash и массив Inventory)
    И при возрождении вручаешь всё это обратно.

    Правда тут вопрос - что делать со стандартным спавном пушек.
    Может так оказаться, что стандартный + сохранённый больше веса, который потянет игрок. Ну можно при создании удалить Inventory и заново его наполнить сохранёнными пушками. Либо как-то вмешиваться в раздачу базовых пушек (в SRVet* или в AddInventory или ещё где)

    Не получится - я накидаю. Пинай
     
  9. Essence

    Essence Бандит

    Решил через ModifyPawn попробовать (Не знаю, красивой ли выйдет такая реализация, но мне легче будет начать именно так).
    Я только врубился как удалить Inventory у игрока.
    Код:
    class SpawnWeaponMut extends Mutator;
    
    struct PlayersStruct
    {
        var string PlayerID;
        var array<Inventory> Inv;
    };
    
    var array<PlayersStruct> PlayersList;
    
    function ModifyPawn(Pawn Other)
    {
        local KFHumanPawn KFHP;
        KFHP=KFHumanPawn(Other);
        KFHP.DeleteInventory;
    }
    
    defaultproperties
    {
        bAddToServerPackages=True
        GroupName="KF-SpawnWeapon"
        FriendlyName="SpawnWeaponMut"
        Description="Spawn Weapon For Players"
    }
    А как запомнить его пухи и вручить обратно не догоняю.
    И как отследить смерть игрока. Типа:
    Код:
    if(KFHP.Health==0)
    {
        Запоминаем Inventory и заносим в массив
    }
    else
    {
        KFHP.DeleteInventory;
        Из массива вручаем Inventory обратно
    }
     
    Последнее редактирование: 15 окт 2016
  10. Flame

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

    Не
    В GameRules есть функция PreventDeath - она вызывается, когда какой-то Pawn помирает
    Там отлавливаешь смерть, сохраняешь шмотки, а потом их вручаешь

    А впрочем вот. Накидал мутатор
     
    Essence нравится это.
  11. Essence

    Essence Бандит

    Я эту функцию буквально переводил - "предотвратить смерть"... Поэтому чот засомневался в её использовании.
    За комментарии в коде спасибо, теперь понял, что к чему.
    В принципе, половину сам мог написать, если б больше посидел за этим делом.
    Вопрос только ещё один есть
    Код:
            //Чтобы после игрока на земле ничего не валялось
            Killed.Weapon.Destroy();
    С мутатором DropAllWeapon конфликтовать не будет?
     
  12. Flame

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

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

    А так - ну конфликтовать то не будет
    Просто будет в куче валяться на 1 пушку меньше нормы - убери эту строчку, если ты всё скидываешь
     
  13. Essence

    Essence Бандит

    А как быть со шприцом?
    Код:
    defaultproperties
    {
         DamageMax=1.000000
         DamageType=Class'lhPerksMut.DamTypeHeal'
    }
    Не прокатит.
     
  14. Flame

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

    Не знаю как со шприцом - думать надо. Возможно придётся ServerStStats использовать и там отлавливать лечение. В AddHealDamage. Сам вчера с этим столкнулся, когда задумывался о переделке своего мутатора о N кратном бонусе на кач.

    Ну можешь для шприца свой фаер класс подсунуть, в котором счётчик есть
    Тут можешь поглядеть, как я заменял fire класс (newSyringeFire)
     
  15. Essence

    Essence Бандит

    Я как раз newSyringeFire и использую. Сделал так, что он наследует InstantFire, а не WeaponFire.
    Скомпилировалось, но толком не тестил.

    Я вот над чем завис. С условиями беда что-то. Есть такой код:
    Код:
            if(Pickup.Name=='BinachiPickup' && SRPRI.KilledPats<25 && SRPRI.SuppDam<25000000
                                       && KFPRI.ClientVeteranSkill.Name!='SRVetSupportSpec')
            {
                return false;
            }
    По идее: "Если это дробовик такой-то, и убито 25 патриархов, и нанесено 25м дамага, и выбранный перк не техник, то пушку купить нельзя".
    Только вот получается так, что коммандосом, например, купить дробовик я могу при 50 убитых патриков и 30м набитого дамага. То есть несостыковочка получается. Если использовать 2 оператора || после пикапа, то купить вообще нельзя будет. Запутался я чот.
     
  16. Flame

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

    Ты мне лучше скажи как надо то?)
    И куда ты этот код прикручиваешь
    И на будущее, если не знаешь эту фишку (закон Моргана)
    Код:
    Отрицание(a && b)=Отрицание(a) || Отрицание (b)
    
    То есть если путаешься создать логическое выражение в одну строну, попробуй в другую
    Например, в функции есть код
    Код:
    if( a && b && c && d && e)
    {
       что-то делаем
    }
    
    А тебе надо написать наоборот - условие выхода из функции, если это условие не выполнено
    Код:
    if( !a || !b || !c || !d || !e)
    {
       выходим
    }
    
    Ладно. Чот я по-моему только усложнил всё)) Так какое ты условие то хочешь?
     
  17. Flame

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

    Допустим в другую сторону твоё высказывание такое:

    Если пушка это BinachiPickup, игрок убил 25 патриков, игрок нанёс 25м урона саппом и игрок является саппом -> позволить купить пушку
    Обратное будет какое?
    Правильно, такое
    Код:
            if    (
                    Pickup.Name!='BinachiPickup'
                    ||    SRPRI.KilledPats<25
                    ||    SRPRI.SuppDam<25000000
                    ||    KFPRI.ClientVeteranSkill.Name!='SRVetSupportSpec'
                )
            {
                return false;
            }
    
    Что в общем то и так очевидно. Что такое || - это или, это максимум из всех выражений.
    Если есть хоть один true - мы вылетаем. А условия у нас как раз отрицание всех необходимых условий )
     
  18. Essence

    Essence Бандит

    В AllowWeaponInTrader этот код пихаю.
    Хочу, чтобы ствол мог купить только техник, который убил 25 патриархов и нанёс 25м урона саппом.
    У меня было подобным образом:

    Код:
            if(Pickup.Name=='BinachiPickup' && (SRPRI.KilledPats<25 || SRPRI.SuppDam<25000000 || KFPRI.ClientVeteranSkill.Name!='SRVetSupportSpec'))
            {
                return false;
            }
    Оружие нельзя было купить.
    Сейчас попробую твой вариант выше.

    Вообще, отталкивался от этого примера:

    Код:
            if(Pickup.Name=='NinjaCrossbowPickup' && (KFPRI.ClientVeteranSkill.Name!='SRVetBerserker'
            || KFPRI.ClientVeteranSkillLevel<30))
            {
                return false;
            }
    UPD. Большое спасибо. Всё заработало как надо.
     
    Последнее редактирование: 26 окт 2016
  19. Flame

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

    Точно? А то я чот задумался тут - а не нагнал ли я тебе. У меня то не так написано и работает же)
    Как пример. Ща подумаю ещё))
    Код:
        else if    (
                    (
                        Pickup.Name=='shPtrdPickup'
                    )
                    &&
                    (
                        (
                            InStr(Caps(string(KFPRI.ClientVeteranSkill.Name)),Caps("VetSharpshooter"))<0
                        )
                        ||    KFPRI.ClientVeteranSkillLevel<13
                    )
                )
        {
            return false;
        }
    
     
  20. Essence

    Essence Бандит

    Ну я бегло тестил. Смотрю чот не так, иду исправлять)
    Попробую все варианты протестировать, отпишусь, скорее всего, на выходных.