пересылка обьекта

Тема в разделе "Кодинг", создана пользователем idpro2, 4 дек 2016.

Метки:
  1. idpro2

    idpro2 Соучастник

    Доброго времени!
    задался следующим вопросом - как передать специальный обьект внутрь BroadcastLocalizedMessage (метод для вывода HUD сообщения на экране у игрока)

    Обычно вызов BroadcastLocalizedMessage выглядит примерно так:
    Код:
    BroadcastLocalizedMessage(class'LocalMessageTest', , CtrlOne.PlayerReplicationInfo, CtrlTwo.PlayerReplicationInfo);
    Где первый параметр - класс унаследованный от LocalMessage, остальные параметры передают PlayerReplicationInfo, и последний параметр - опциональный обьект (который и нужен)

    Сам класс LocalMessageTest:

    Код:
    class LocalMessageTest extends LocalMessage;
    
    static function string GetString(optional int Switch, optional PlayerReplicationInfo RelatedPRI_1, optional PlayerReplicationInfo RelatedPRI_2, optional Object OptionalObject)
    {
        local string S;
        local MyObject MO;
       
        MO = MyObject(OptionalObject);
       
        if (MO == None)
            return "none";
       
        S = MO.Message;
       
        default.Lifetime = MO.Lifetime;
       
        return S;
    }
    
    defaultproperties
    {
        Lifetime=15
        DrawColor=(R=255,G=255,B=255)
        PosY=0.450000
    }
    
    И сам опциональный обьект (не уверен что я его сделал правильно):

    Код:
    class MyObject extends Object;
    
    var int Lifetime;
    var string Message;
    
    defaultproperties
    {
        Lifetime=33
        Message="Test12345"
    }
    Помогите пожалуйста разобраться, как правильно сделать этот опциональный обьект, который можно будет создать/заполнить и передать извне в BroadcastLocalizedMessage
    Хочу в итоге добиться типа такого:

    Код:
    local MyObject MO;
    
    MO.Message = "To show";
    MO.Lifetime = 25;
    
    BroadcastLocalizedMessage(class'LocalMessageTest', , , ,MO);
     
  2. Flame

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

    idpro2 нравится это.
  3. idpro2

    idpro2 Соучастник

    Спасибо! Изучил :)

    Но все-равно не выходит(

    Я нашел статейку по Localmessage - https://wiki.beyondunreal.com/Legacy:Using_LocalMessages
    Там пишут мол опциональный обьект должен уже существовать у всех игроков прежде чем его можно отсылать, если я все правильно понял.

    По коду выше у меня всегда выдает "MO is none", т.е. обьект не приходит

    Пробовал делать так:

    Код:
    local MyObject MO;
    
    MO = new class'MyObject';
    MO.Lifetime = 10;
    MO.R = 0;
    MO.G = 255;
    MO.B = 0;
    MO.PosY = 0.200000;
    MO.Message = txt;
    BroadcastLocalizedMessage(class'LocalMessageTest', , , , MO);
     
  4. gall87

    gall87 Капо

    ну в слотмашин мутаторе было что то похожее, глянь там
     
  5. gall87

    gall87 Капо

    ну как пример, мы выиграли банку блевотины в рулетке!Карта вызывает сообшение и эффект!
    static function float ExecuteCard( Pawn Target )
    {
    Target.TakeDamage(30,None,Target.Location,vect(0,0,0),Class'DamTypeVomit');
    PlayerController(Target.Controller).ReceiveLocalizedMessage(Class'ToxicMessage');
    return 0;
    }

    defaultproperties
    {
    CardMaterial=Texture'KillingFloorHUD.Achievements.Achievement_4'
    }

    class ToxicMessage extends LocalMessage;

    var localized string Message;

    static function string GetString(
    optional int Switch,
    optional PlayerReplicationInfo RelatedPRI_1,
    optional PlayerReplicationInfo RelatedPRI_2,
    optional Object OptionalObject )
    {
    return Default.Message;
    }

    defaultproperties
    {
    Message="Уххх... Плохое чувство..."
    bIsUnique=True
    bFadeMessage=True
    Lifetime=4
    DrawColor=(B=0,R=0)
    StackMode=SM_Down
    PosY=0.800000
    }
     
  6. Flame

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

    Не. Тут не передаётся объект)
    Ближе к ночи напишу что-нибудь о этой теме
     
    idpro2 нравится это.
  7. idpro2

    idpro2 Соучастник

    gall87, спасибо за помощь, но к сожалению это не то, суть темы немного в другом
     
  8. Flame

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

    Так. Всё руки не дойдут.
    Я тебе сейчас так скажу по примеру какого-то моего мутатора.
    Смотри как я сделал:
    Код:
    class PatHPLeftObject extends Actor;
    var int Damage;
    var string PlayerName;
    replication
    {
        reliable if(bNetDirty && Role == Role_Authority)
            Damage,PlayerName;
    }
    
    То есть не буквально воспринял мысль - что надо именно объект
    Actor этож тоже Object - я и передал класс унаследованный от Actor
    А Actor чем хорош? Правильно - там можно делать репликацию.
    С передачей этого объекта обычно одна беда - передаётся он на сервере, а используется на клиенте
    Правда не знаю успеет ли произойти репликация - сейчас лень думать. В моём мутаторе все нормально в этом плане)
    В общем может поможет. Сам гляну завтра
     
  9. Flame

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

    Так. Держи мутатор.
    Мутатор выводит в начале волны сообщения игрокам, если они упомянуты в ini.
    Используем объект для передачи данных. У разных игроков - разные сообщения.
    Зашёл вот под двумя аккаунтами
    [​IMG]
    [​IMG]
    Там в комментариях вроде всё расписал.
    Код:
    Код:
    class MessageMut extends Mutator config(MessageMut);
    
    struct MessageStruct
    {
        var config string Hash;
        var config string PlayerName;
        var config string Message;
    };
    var config array<MessageStruct> Messages;
    
    var bool bMessageSent;
    var bool bMessageCreated;
    
    //Запускаем таймер
    function PostBeginPlay()
    {
        SaveConfig();
        SetTimer(0.5,true);
    }
    
    //В таймере отлавливаем начало волны. Если началась волна, то на 1 этапе мы создаём объекты в if(!bMessageCreated)
    //Для каждого игрока создаются разные сообщения
    //После этого даём мутатору время на репликацию этих сообщений на клиент
    //В следующем вызове таймера мы выполняем рассылку сообщений игрокам
    function Timer()
    {
        local bool bWaveInProgress;
        bWaveInProgress=bool(Level.Game.GetPropertyText("bWaveInProgress"));
        if(!bWaveInProgress)
            return;
        //1 этап
        if(!bMessageCreated)
        {
            CreateMessage();
            bMessageCreated = true;
            return;
        }
        //2 этап
        if(bMessageCreated && !bMessageSent)
        {
            SendMessage();
            bMessageSent = true;
        }
        //Больше нам мутатор не нужен - удаляем его
        if(bMessageSent)
            Destroy();
    }
    
    //В данной функции для всех игроков создаётся объект в котором содержится сообщение
    function CreateMessage()
    {
        local Controller C;
        for(C=Level.ControllerList;C!=none;C=C.NextController)
        {
            if(PlayerController(C)!=none && C.PlayerReplicationInfo!=none && C.PlayerReplicationInfo.PlayerID>0)
                CreateObject(PlayerController(C));
        }
    }
    
    //Создаём объект MyObject. Получаем в функции GetMessageIndexFromList индекс сообщения для данного игрока из ини файла
    //Прописываем значение полей для atObject
    //Цепляем этот объект прямо к PlayerController игрока. Просто для удобства. Можно запомнить какой объект соотв. какому игроку любым другим способом.
    function CreateObject(PlayerController PC)
    {
        local int N;
        local MyObject atObject;
    
        N=GetMessageIndexFromList(PC);
        if(N<0)
            return;
    
        atObject=Spawn(class'MyObject');
        atObject.PlayerName=Messages[N].PlayerName;
        atObject.Message=Messages[N].Message;
        PC.Attached[PC.Attached.Length]=atObject;
    }
    
    //Функция тащит индекс нужного элемента массива. Сравнение идёт по хэшу прописанному в ини файле
    function int GetMessageIndexFromList(PlayerController PC)
    {
        local string Hash;
        local int i;
        Hash=PC.GetPlayerIDHash();
        for(i=0;i<Messages.Length;i++)
        {
            if(Hash~=Messages[i].Hash)
                return i;
        }
        return -1;
    }
    
    //Функция отсылает сообщение игрокам. GetObjectIndex позволяет нам получить именно нужный нам объект MyObject из массива Attached
    //Вообще говоря по умолчанию этот массив содержит только наш объект. И можно просто прописать N=0, но мало ли. Перестрахуемся
    function SendMessage()
    {
        local Controller C;
        local PlayerController PC;
        local Actor atObject;
        local int N;
        for(C=Level.ControllerList;C!=none;C=C.NextController)
        {
            if(PlayerController(C)!=none && C.PlayerReplicationInfo!=none && C.PlayerReplicationInfo.PlayerID>0)
            {
                PC=PlayerController(C);
                N=GetObjectIndex(PC);
                if(N>=0)
                    atObject=PC.Attached[N];
                PC.ReceiveLocalizedMessage(class'MyMessage',0,,,atObject);
            }
        }
    }
    //Функция получает индекс MyObject объекта среди всех присоединённых объектов
    function int GetObjectIndex(PlayerController PC)
    {
        local int i;
        for(i=0;i<PC.Attached.Length;i++)
        {
            if(PC.Attached[i].IsA('MyObject'))
                return i;
        }
        return -1;
    }
    
    defaultproperties
    {
        Messages(0)=(Hash="76561198051378449",PlayerName="Flame",Message="Happy Birthday")
        bAddToServerPackages=true
        GroupName="KF-Message"
        FriendlyName="MessageMut"
        Description="MessageMut"
    }
    
    Код:
    class MyMessage extends CriticalEventPlus
        abstract;
    
    var(Message) localized string InfoText[2];
    
    static function string GetString(
        optional int Switch,
        optional PlayerReplicationInfo RelatedPRI_1,
        optional PlayerReplicationInfo RelatedPRI_2,
        optional Object OptionalObject
        )
    {
        //Если объект передан и если длина сообщения не 0 - отправляем сообщение в формате Имя: Сообщение
        if(MyObject(OptionalObject)!=none && Len(MyObject(OptionalObject).Message)>0)
            return MyObject(OptionalObject).PlayerName$":"@MyObject(OptionalObject).Message;
        //Иначе идёт обычный вызов
        return Default.InfoText[Switch];
    }
    
    defaultproperties
    {
        InfoText(0)="Hi"
        bIsUnique=False
        Lifetime=20
        DrawColor=(R=245,G=10,B=69)
        DrawPivot=DP_UpperLeft
        StackMode=SM_Down
        PosX=0.300000
        PosY=0.300000
    }
    
    Код:
    class MyObject extends Actor;
    
    var string Message,PlayerName;
    
    replication
    {
        reliable if(bNetDirty && Role == Role_Authority)
            Message,PlayerName;
    }
    
    defaultproperties
    {
        //Важно
        bAlwaysRelevant=True
    }
    

    Ссылка
     
    idpro2 и Essence нравится это.
  10. idpro2

    idpro2 Соучастник

    Flame, спасибо!
    Реально ли сделать тоже самое через LocalMessage а не CriticalEventPlus, если допустим нужно опционально установить цвет сообщения и другие свойства из defaultproperties в LocalMessage?
    У меня просто не срабатывает в таком случае, даже обьект не передается.
    Вот мой код:

    Код:
    // функция в которой устанавливаем параметры и отсылаем игрокам
    
    static function SendToPlayers()
    {
        local LocalMessageObject LMO;
        LMO = Spawn(class'LocalMessageObject');
        LMO.Lifetime = 3;
        LMO.R = 255;
        LMO.G = 255;
        LMO.B = 0;
        LMO.PosY = 0.500000;
        LMO.Message = PlayerName @ "receive bonus";
        BroadcastLocalizedMessage(class'LocalMessageEx', 0, , , LMO);
    }
    
    // обьект который будет отослан
    
    class LocalMessageObject extends Actor;
    
    var string Message;
    var byte R, G, B;
    var float PosY;
    var int Lifetime;
    var bool bFade;
    
    replication
    {
        reliable if (bNetDirty && Role == Role_Authority)
            Message,
            R, G, B,
            PosY,
            Lifetime,
            bFade;
    }
    
    defaultproperties
    {
        bAlwaysRelevant=True
    }
    
    // сам класс-наследник LocalMessage который проверяет опциональный обьект и отправляет сообщения
    
    class LocalMessageEx extends LocalMessage;
    
    var(Message) localized string DefaultText[2];
    
    static function string GetString(
        optional int Switch, 
        optional PlayerReplicationInfo RelatedPRI_1, 
        optional PlayerReplicationInfo RelatedPRI_2, 
        optional Object OptionalObject)
    {
        local LocalMessageObject LMO;
       
        if (LocalMessageObject(OptionalObject) == none)
        {
            return default.DefaultText[Switch];
        }
       
        LMO = LocalMessageObject(OptionalObject);
       
        if (LMO.Lifetime > 0)
            default.Lifetime = LMO.Lifetime;
       
        default.DrawColor.R = LMO.R;
        default.DrawColor.G = LMO.G;
        default.DrawColor.B = LMO.B;
       
        default.PosY = LMO.PosY;
       
        default.bFadeMessage = LMO.bFade;
       
        return LMO.Message;
    }
    
    defaultproperties
    {
        DefaultText(0)="Test"
        Lifetime=5
        DrawColor=(R=255,G=0,B=0)
        PosY=0.50000
        bFadeMessage=True
    }
    
     
  11. idpro2

    idpro2 Соучастник

    Вопрос еще актуален. Заранее спасибо
     
  12. idpro2

    idpro2 Соучастник

    ап, очень прошу подсказать
     
  13. Flame

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

    Подскажу, чуть позже
    Чтобы ускорить это - мог бы уже давно сделать какой-то мутатор, который можно запустить, убедиться, что не работает и поправить)
    Мне же лень самому эт писать)
     
  14. sindzi

    sindzi Соучастник

    Привет
    Пробовал у себя внедрить в SP тоже самое
    Обьект не передается
    Также не понятно что такое PC.Attached и зачем это нужно
    Кто нибудь может помочь разобратся что не так?
     
  15. Essence

    Essence Солдат

    Так в мутаторе есть комментарии к коду.
    Attached - это массив присоединенных к PlayerController объектов.
     
    sindzi нравится это.
  16. sindzi

    sindzi Соучастник

    Интересует следующее
    Можно ли как-то просто передать обычную строку в LocalMessage без этих всех махинаций с аттачментом и так далее.
    Конечная цель вызвать сообщение как-то так

    Код:
    BroadcastLocalizedMessage(class'LocalMessageEx', , , , "Hello WOrld");
    И чтобы на экране вывело "Hello WOrld"
     
  17. Essence

    Essence Солдат

    Ну, так как функция GetString в LocalMessage является статической, то мы можем использовать либо дефолтные значения, либо входные параметры.
    Если не устраивает создание объектов, можно использовать кастомный PlayerReplicationInfo для передачи строки.
     
  18. sindzi

    sindzi Соучастник

    Спасибо за варианты
    я пробовал создавать свой PRI и передавать внутрь, но не передается (обьект RelatedPRI всегда none)
    Код:
    local PlayerReplicationInfo MyPRI;
    MyPRI = Spawn(class'PlayerReplicationInfo');
    MyPRI.PlayerName = 'Hello WOrld';
    PC.ReceiveLocalizedMessage(class'LocalMessageX', , MyPRI);
    
    Код:
    static function string GetString(
        optional int Switch,
        optional PlayerReplicationInfo RelatedPRI_1,
        optional PlayerReplicationInfo RelatedPRI_2,
        optional Object OptionalObject)
    {
        if (RelatedPRI_1 != none)
        {
            if (RelatedPRI_1.PlayerName != "")
            {
                return RelatedPRI_1.PlayerName;
            }
    
            return "RelatedPRI_1 != none";
        }
    
        return default.Message[Switch];
    }
    Может я не правильно создаю/передаю такие обькты?
     
  19. Essence

    Essence Солдат

    Создаём класс SRPlayerReplicationInfo. Для удобства будем хранить его в ServerPerks. Содержимое файла:

    Код:
    class SRPlayerReplicationInfo extends KFPlayerReplicationInfo;
    
    var string Message;
    
    replication
    {
        reliable if(bNetDirty && Role==Role_Authority)
            Message;
    }

    Заменяем PlayerReplicationInfoClass на кастомный. Для этого в ServerPerksMut.uc в функции CheckReplacement добавим такой код:

    Код:
    function bool CheckReplacement(Actor Other, out byte bSuperRelevant)
    {
        ...
        if(Controller(Other)!=None)
            Controller(Other).PlayerReplicationInfoClass=Class'SRPlayerReplicationInfo';
        ...
    }

    Отлично, кастомный PlayerReplicationInfo у нас есть. Идём далее. Я накидал мутатор, при спавне игрока у него высвечивается соответствующее сообщение.

    Код:
    class MsgMut extends Mutator config(MsgMut);
    
    struct MessageStruct
    {
        var config string PlayerID;
        var config string PlayerName;
        var config string Message;
    };
    var config array<MessageStruct> Messages;
    var array<PlayerController> PendingPlayers;
    
    function PostBeginPlay()
    {
        SaveConfig();
    }
    
    function bool CheckReplacement(Actor Other, out byte bSuperRelevant)
    {
        if(PlayerController(Other)!=None)
        {
            PendingPlayers[PendingPlayers.Length]=PlayerController(Other);
            SetTimer(0.1, False);
        }
        Return True;
    }
    
    function Timer()
    {
        local SRPlayerReplicationInfo SRPRI;
        local PlayerController PC;
        local string Hash;
        local int i,n;
        for(i=PendingPlayers.Length-1; i>=0; i--)
        {
            PC=PendingPlayers[i];
            if(PC!=None && PC.PlayerReplicationInfo!=None && PC.PlayerReplicationInfo.PlayerID>0)
            {
                Hash=PC.GetPlayerIDHash();
                SRPRI=SRPlayerReplicationInfo(PC.PlayerReplicationInfo);
                for(n=0; n<Messages.Length; n++) if(SRPRI!=None && Messages[n].PlayerID~=Hash) SRPRI.Message=Messages[n].Message;
            }
        }
        PendingPlayers.Length=0;
    }
    
    function ModifyPlayer(Pawn P)
    {
        Super.ModifyPlayer(P);
        SendMessage(P);
    }
    
    function SendMessage(Pawn P)
    {
        if(P!=None && P.PlayerReplicationInfo!=None) P.ReceiveLocalizedMessage(Class'MyMsg',,P.PlayerReplicationInfo);
    }
    
    defaultproperties
    {
        Messages(0)=(PlayerID="76561198051378449",PlayerName="Flame",Message="Happy Birthday")
        GroupName="KF-MsgMut"
        FriendlyName="MsgMut"
        Description="Message Mut"
    }

    Собственно, сам LocalMessage.

    Код:
    class MyMsg extends LocalMessage;
    
    static function string GetString(optional int Switch, optional PlayerReplicationInfo RelatedPRI_1, optional PlayerReplicationInfo RelatedPRI_2, optional Object OptionalObject)
    {
        local string Message;
        if(RelatedPRI_1!=None && SRPlayerReplicationInfo(RelatedPRI_1)!=None && SRPlayerReplicationInfo(RelatedPRI_1).Message!="")
            Message=RelatedPRI_1.PlayerName$":"@SRPlayerReplicationInfo(RelatedPRI_1).Message;
        Return Message;
    }
    
    defaultproperties
    {
         bIsUnique=True
         bFadeMessage=True
         Lifetime=6
         DrawColor=(B=0,R=0)
         PosY=0.100000
    }

    Скриншот:
    [​IMG]

    Ссылка на SP 7.5 вместе с мутатором:
    SP With MsgMut
     
    mantis, RaideN- и sindzi нравится это.
  20. sindzi

    sindzi Соучастник

    спасибо вам большое и низкий поклон!