Dynamic dialogs in multiplayer

I want to create a dialog that can be accessed by multiple PC at the same time (without having the “is too busy to talk right now”).

This dialog should work for placeable and creatures alike.

In order to achieve that, I tried the following :

  • create a copy of the speakee
  • hide the copy (thanks to nwnx_visibility)
  • start dialogue between the PC and the copy
  • destroy the copy (at the end of the dialogue)

It works as expected but now I have multiple issues :

  • The portrait of the dialogue is empty and the name is “UNKNOWN SPEAKER”
  • It doesn’t work for creatures since the OnConversation isn’t doing what I expected and there is no similar events like “OnUsed” for placeables.

So, to sum-up, I have the following question :

  • Is creating “invisible copies” the way to go, or am I missing something ?
  • How to show portrait and name of invisible object to PC in a conversation ?
  • How to start a conversation between a creature and a PC dynamically (in which event, since OnConversation isn’t working as expected) ?

I think you’re on the right lines, but, from memory, there’s a timing issue.

Rather than copy the original, then make it invisible, I spawn a new object from a template with an invisible appearance and the desired name / portrait. Then I use AssignCommand to make the new object start the conversation.

The subtle difference is that in the very brief time it takes for the action queue to open, the name and portrait seem to get initialised correctly.

For creatures, OnConversation can be scripted to do almost anything - by all means post the code snippet that’s not working, I’m sure we can help.

Thanks a lot, it is working now !

It was indeed a timing issue, I had to had 0.2s delay in order for the portrait to show up correctly.

Here is the code snippet if anyone is having running into the same issue :slight_smile:

void DDIAG__StartDialog(object oPC, object oSpeakee, int bPrivate = FALSE, int bPlayHello = TRUE, string sScript = "") {
    string sRealScript = sScript;
    if (sRealScript == "") sRealScript = GetTag(oSpeakee) + "_ddiag"; // Search a script with _ddiag suffix is none is provided

    object oSpeakeeCopy = CreateObject(OBJECT_TYPE_PLACEABLE, "placeable_invisi", GetLocation(oSpeakee)); // placeable with appearance type "invisible"
    SetName(oSpeakeeCopy, GetName(oSpeakee));
    SetPortraitResRef(oSpeakeeCopy, GetPortraitResRef(oSpeakee));

    // These are just for my own dynamic dialog, but it can work with a usual static dialog
    SetLocalString(oSpeakeeCopy, DDIAG__SCRIPT_HANDLER_VARNAME, sRealScript);
    SetLocalObject(oSpeakeeCopy, DDIAG__PC_VARNAME, oPC);
    SetLocalObject(oSpeakeeCopy, DDIAG__SPEAKEE_VARNAME, oSpeakee);

    AssignCommand(oSpeakeeCopy, DelayCommand(0.2f, ActionStartConversation(oPC, "ddiag", bPrivate, bPlayHello))); // The 0.2s delay is necessary for Portrait and Name to initialise on oSpeakeeCopy
}