Summon pawns for convo

This script tries to summon all pawns needed for a convo, in case they're not close enough. It goes in a [custom player class](/docs/guides/custom-characters/).

Author: Artifechs

MyPlayerCharacter.uc

function bool StartConversation(
    Actor InvokeActor, 
    EInvokeMethod InvokeMethod, 
    optional Conversation Con,
    optional bool bAvoidState,
    optional bool bForcePlay
    )
{
    local ConEvent Event;
    local ConEventSpeech EventSpeech;
    local ScriptedPawn aScriptedPawn;
    local Rotator HelpRotator;
    local int Radius;

    // Only try this trick if the player frobbed an NPC
    if(InvokeMethod == IM_Frob)
    {
        if(Con == None)
        {
            Con = GetActiveConversation(InvokeActor, InvokeMethod);
        }

        // Set maximum radius and initialize the rotator
        Radius = 128;
        HelpRotator = Rotation;

        // Loop all SpeechEvents in the convo to find their actors
        Event = Con.EventList;

        while(Event != None)
        {
            EventSpeech = ConEventSpeech(Event);

            if(EventSpeech != None)
            {
                foreach AllActors(class'ScriptedPawn', aScriptedPawn)
                {
                    if(aScriptedPawn.BindName != EventSpeech.SpeakerName && aScriptedPawn.BindName != EventSpeech.SpeakingToName)
                        continue;

                    // We don't need to summon anyone with the same BindName
                    if(aScriptedPawn.BindName == InvokeActor.BindName)
                        continue;

                    // Make sure the next actor is placed somewhere new
                    HelpRotator.Yaw += 4096;

                    if(
                        aScriptedPawn != None &&
                        aScriptedPawn != Self &&
                        VSize(aScriptedPawn.Location - Location) > 300
                    )
                    {
                        // Place the actor within a min/max radius of the player
                        while(Radius > 32 && !aScriptedPawn.SetLocation(Location + Normal(Vector(HelpRotator)) * Radius))
                        {
                            HelpRotator.Yaw += 4096;
                            Radius -= 16;
                        }

                        aScriptedPawn.LookAtActor(Self, true, false, true, 0, 0.5);
                        aScriptedPawn.GoToState('Conversation');
                    }
                }
            }

            Event = Event.NextEvent;
        }
    }

    return Super.StartConversation(InvokeActor, InvokeMethod, Con, bAvoidState, bForcePlay);
}