Generalising Lua Conditions

Announcements, support questions, and discussion for the Dialogue System.
Post Reply
User avatar
rykaan
Posts: 75
Joined: Tue Feb 11, 2020 6:22 am

Generalising Lua Conditions

Post by rykaan »

Hi Tony,

I'm trying to remove the requirement to enter the names of my characters, when using Lua to look up their actor names via a string. So at the moment If I want to run a function from Lua to check a condition it looks a little like this in the Lua Conditions section of the Dialogue System Trigger: IsPassive("Monster_Name");

This is simply to look up "Monster_Name" in actors then get a component on that actor's GameObject and check a bool. I want to just be able to run the Lua code without needing the name each time to greatly reduce errors down the line. So I added some code when interacting with the collider to change a variable in the Dialogue Manager to the name of the monster. Then I can use the variable in the function: IsPassive() directly.

Problem is it's throwing out a bunch of errors despite the Debug.Log giving me the monster name correctly. All (I think) I've changed is the source of the string referring to the actor's name. But it doesn't seem to like it. I've got an image below of what I've done.
string source change issue.jpg
string source change issue.jpg (727.39 KiB) Viewed 510 times
I expect there is a much better way to do what I am attempting, but I'm surprised this didn't work. Any idea where I'm going wrong? I've included the exceptions I'm getting in the image.

Cheers,
Rob
User avatar
Tony Li
Posts: 22049
Joined: Thu Jul 18, 2013 1:27 pm

Re: Generalising Lua Conditions

Post by Tony Li »

Hi Rob,

For line 84 to work, the scene must have a GameObject with a Dialogue Actor whose Actor dropdown is set to "Spuggie".

Instead of that, what about using the built-in variables? (See Special Variables.)

For example, you might be able to use:

Code: Select all

IsPassive(Variable["Conversant"])
Or you can check the actual conversant GameObject in your IsPassive() method:

Code: Select all

bool IsPassive()
{
    if (DialogueManager.currentConversant == null)
    { // No conversant GameObject. Handle gracefully by returning false.
        return false;
    }
    
    var detectionStatusScript = DialogueManager.currentConversant.GetComponent<DetectionStatusScript>();
    
    if (detectionStatusScript == null)
    { // Conversant doesn't have a DetectionStatusScript. Handle gracefully by returning false.
        return false;
    }
    
    return (detectionStatusScript.detectionStatus == 0) || (detectionStatusScript.detectionStatus == 6);
}
User avatar
rykaan
Posts: 75
Joined: Tue Feb 11, 2020 6:22 am

Re: Generalising Lua Conditions

Post by rykaan »

Hi Tony,

Thanks for the reply. The dialogue actor seemed to be set correctly, it wasn't changed between switching the code out. I've added a screenshot below.

spuggie actor.jpg
spuggie actor.jpg (499.57 KiB) Viewed 505 times

Is there a problem with using these special variables if the conversation hasn't actually started yet though? I was under the impression that using 'conversant' etc wouldn't work if I hadn't yet started a conversation. So it wouldn't be a good choice if I'm trying to determine if to start the conversation or not. I seem to get an Object reference exception when using it in place of the characters name in the original code.

Cheers for the help with this,
Rob
User avatar
Tony Li
Posts: 22049
Joined: Thu Jul 18, 2013 1:27 pm

Re: Generalising Lua Conditions

Post by Tony Li »

Hi Rob,
rykaan wrote: Tue Feb 02, 2021 6:40 amIs there a problem with using these special variables if the conversation hasn't actually started yet though?
Yes. The DialogueManager.currentActor/currentConversant C# properties and the Variable["Actor"]/Variable["Conversant"] Lua variables are set when the conversation starts. So they're not valid before the conversation starts.

I assumed you were going to use IsPassive() within a conversation. Are you planning to use it outside a conversation, such as in the Conditions section of a Dialogue System Trigger to check if the conversation should run in the first place?

If so, you can use SequencerTools.FindSpecifier(string actorName, bool onlyActiveObjects). Example:

Code: Select all

string monsterName = DialogueLua.GetVariable("Current Actor Name").asString;
GameObject monster = SequencerTools.FindSpecifier(monsterName, true);
This method looks up a GameObject by actor name. If a GameObject with a Dialogue Actor has registered itself with that actor name, the method will return that GameObject. Otherwise it will return the GameObject whose GameObject name matches the actor's name.

I don't know if this is helpful or not, but you can also use DialogueManager.instance.FindActorTransformFromConversation() to find the GameObject that would be associated with a conversation's actor or conversant. Example:

Code: Select all

Transform actor = DialogueManager.instance.FindActorTransformFromConversation("My Conv", "Actor");
Transform conversant = DialogueManager.instance.FindActorTransformFromConversation("My Conv", "Conversant");
User avatar
rykaan
Posts: 75
Joined: Tue Feb 11, 2020 6:22 am

Re: Generalising Lua Conditions

Post by rykaan »

Hi Tony,

My apologies, I should have been more clear when I posed my original question what I was aiming to do. This conversation should only trigger if the monster is in a passive state (i.e. hasn't noticed the player at all). I've just tried your suggestion of using the sequencer tools find specifier method but it doesn't seem to find anything, returning null. I'll just post the whole sequence and hopefully something reveals itself.

This is where the variable is set:

Code: Select all

hit = CharacterFacingMethods.PlayerInteractionRaycast(
            (heightOffset * verticalOffsetCancelling), widthOffset,
            transform.position, npcBase.facing, (raycastLength + verticalRayLengthModifier), layerMask);
        if (hit != false)
        {
            DialogueLua.SetVariable("Current Actor Name", hit.collider.gameObject.ToString());
            Debug.Log("Current Actor Name: " + DialogueLua.GetVariable("Current Actor Name").AsString);
        }
This happens before sending an OnUse event to the monster, where it checks if brother is using a deadly weapon and then if the monster is passive. Notice that I'm sending the name of the GameObject as the string, so it seems unlikely that when looking up the gameObjects name that the name would be incorrect.
spuggie lua.jpg
spuggie lua.jpg (49.59 KiB) Viewed 493 times
The MyLUAFunctions IsPassive method triggers, looks at the variable of the monster name, reads the string correctly but then doesn't seem to be able to look up the actor or gameObject from it.

Code: Select all

public static bool IsPassive()
    {
        string monsterName = DialogueLua.GetVariable("Current Actor Name").AsString;
        GameObject monster = SequencerTools.FindSpecifier(monsterName, true);
        Debug.Log("LUA Passive script: " + DialogueLua.GetVariable("Current Actor Name").AsString);
        Debug.Log(monster);
        DetectionStatusScript detectionStatusScript = monster.GetComponent<DetectionStatusScript>();
        print(monsterName + " Detection Status = " + detectionStatusScript.detectionStatus);
        if (detectionStatusScript.detectionStatus == 0 ||
            detectionStatusScript.detectionStatus == 6)
        {
            return true;
        }
        else
        {
            return false;
        }
Is there some reason that the variable may have additional syntax at all that means it doesn't find the actor correctly?
actor name lua error.jpg
actor name lua error.jpg (146.63 KiB) Viewed 493 times
You can see in the error log where the string is being passed along, but then the error ocurrs at the point when the actor name is searched for. Whereas when I sent the name as a string directly from the Dialogue System Trigger it didn't have the issue.

Cheers,
Rob
User avatar
Tony Li
Posts: 22049
Joined: Thu Jul 18, 2013 1:27 pm

Re: Generalising Lua Conditions

Post by Tony Li »

Change this:

Code: Select all

DialogueLua.SetVariable("Current Actor Name", hit.collider.gameObject.ToString());
to this:

Code: Select all

DialogueLua.SetVariable("Current Actor Name", hit.collider.gameObject.name);
The original line stores the string "Spuggie (GameObject)".

The second line stores the actual GameObject name, "Spuggie".
User avatar
rykaan
Posts: 75
Joined: Tue Feb 11, 2020 6:22 am

Re: Generalising Lua Conditions

Post by rykaan »

Gah! That did it. This can be so finicky sometimes. Thanks for your patience, it turned out to be a very simple fix again. Getting a few more ways to do the search could prove very helpful anyways.

Cheers!
Rob.
User avatar
Tony Li
Posts: 22049
Joined: Thu Jul 18, 2013 1:27 pm

Re: Generalising Lua Conditions

Post by Tony Li »

Alright, glad it's working! :-)
Post Reply