Forcing how PC moves when clicking on an NPC?

I have a tavern where the innkeeper is standing behind the bar counter. It is totally possible to talk to him by standing on the other side, but more often than not, if you click on him, the PC always seem to prefer going around the bar counter to talk to him. Would it be possible, through scripting perhaps, to force the PC to go in front of the counter when initializing a dialog? Maybe put something in OnConversationScript of the character? Or maybe this is hardcoded and impossible?

well,

try an invisible* blocking object behind the counter, where the PC usually ends up at ā€¦ this might be enough to force pathfinding to use the spot in front of the counter.

or ā€¦

EDIT: dang this next isnā€™t as straightforward as I thought itā€™d be ā€“ the PC runs up to the NPC before the OnConversation event fires.

dialog with an NPC can (indeed) be ā€œinitializedā€ in the NPCā€™s OnConversation event script (default: ā€˜nw_c2_default4ā€™). I suppose a custom handler could be written that checks if the PCSpeaker is close enough. Put a waypoint in front of the counter. If the PC isnā€™t close enough, script the PC to move to the waypoint and start the dialog:

AssignCommand(oPC, ActionMoveToObject())
AssignCommand(oPC, ActionStartConversation())

I think you can get the PC w/ GetLastSpeaker() ā€¦ no doubt thereā€™d be frustrations to work through but i believe itā€™s possible.

Ā 
* it doesnā€™t have to be invisible ā€¦ a chest or whatever that has collision

1 Like

after mucking around with this for a while

i get the impression that NPCs really donā€™t like to have dialog over a table ā€¦ (unless the PC is already standing right there)

I did, however, wire up a trigger that stops the PC and makes the NPC bark ā€œhey, stay out from behind the bar.ā€ And then, although I see this as optional, forces the PC to walk out in front of the bar and restarts the dialog.

i tend to think itā€™s enough to just stop the PC with an NPC bark ā€“ it gets the point across, and player can either then choose to continue behind the bar or walk out in front of the bar and try again ā€¦

So you donā€™t think this would work then? You tried it?

I put a couple barrels down y. When i clicked on the NPC, my PC just stood there ~20m away and the dialog started.

this is my test setup


the barrels were placed diagonally out from the corner of the table, so PC couldnā€™t enter the trigger

and hereā€™s a vid of the trigger in action ā€¦
https://drive.google.com/file/d/1JT9O3NpOuXz_wffRBx4AMboq2hdullH7/view?usp=sharing

why not use the conversation distance setting in the campaign editor? drawback is, you have to convert your module into a campaign to use it and it works on every dialogue. soz uses a value of 20.

Well, I think Iā€™ll skip that then, since I donā€™t want to convert to campaign.

Ok, Iā€™ll test a bit myself then, kevL_s.

I tried with just doing walkmesh cutter behind the counter and that worked pretty well. However, now the conversation begins, or may begin, when the PC and the innkeeper are pretty far from each other, and that looks kind of odd, like theyā€™re standing shouting to each other for no apparent reason.

I got an idea think Iā€™ll try: Maybe one can write a conditional at the top node of the dialog, and if the PC isnā€™t close enough, to move the PC in place to start the conversation?

Hmm. I tried this but my PC wonā€™t move. I placed the first script below on the first node on conditions, and the second script on the second node on actions - of the conversation of the innkeeperā€™s conversation, so that the last node has the move-script.
Then below that I put the ā€œrealā€ conversation so to speak.

int StartingConditional()
{

object oPC = GetPCSpeaker();
object oInnkeeper = GetNearestObjectByTag("taw_innk",oPC);

if(GetDistanceToObject(oPC) >4.0f)
{
return TRUE;
}

else
{
return FALSE;
}

}
void main()
{
	
object oPC = GetPCSpeaker();
object oWP = GetNearestObjectByTag("d_inkwp",oPC);
object oInnkeeper = GetNearestObjectByTag("taw_innk",oPC);

AssignCommand(oPC, ActionMoveToObject(oWP));
AssignCommand(oPC, ActionStartConversation(oInnkeeper));

}

I tried changing oPC to GetFirstPC also but with the same result. The dialog just goes through a neverending loop since the PC wonā€™t move.

your reply gave me the notion to go back to the OnConversation handler.

// 'oc_bartender'
/*
    OnConversation script for innkeeper.
*/

const string TAG_WAYPOINT = "d_inkwp";
const float  DEFAULT_DIST_DIALOG = 2.f;

void BeginDialog(object oSpeaker);


// OBJECT_SELF is innkeeper
void main()
{
    object oPc = GetLastSpeaker();

    if (GetDistanceToObject(oPc) > DEFAULT_DIST_DIALOG)
    {
        AssignCommand(oPc, ClearAllActions());

        object oWaypoint = GetNearestObjectByTag(TAG_WAYPOINT);
        AssignCommand(oPc, ActionMoveToObject(oWaypoint, TRUE, 0.f));

        object oSpeaker = OBJECT_SELF; // req'd - do not put OBJECT_SELF directly into the next call
        AssignCommand(oPc, ActionDoCommand(BeginDialog(oSpeaker)));
    }
    else // standard start conversation ->
    {
        ClearAllActions();
        BeginConversation();
    }
}


// OBJECT_SELF is pc here
void BeginDialog(object oSpeaker)
{
    ClearAllActions();
    SetFacingPoint(GetPosition(oSpeaker));

    object oPc = OBJECT_SELF; // req'd - do not put OBJECT_SELF directly into the next calls

    AssignCommand(oSpeaker, ClearAllActions());
    AssignCommand(oSpeaker, SetFacingPoint(GetPosition(oPc)));

    AssignCommand(oSpeaker, ActionStartConversation(oPc));
}

The dialog has nothing special in its events. The innkeeper doesnā€™t say hello (unless PC is already close enough). If the PC is farther than ~15 meters away, player gets an ā€˜object is too far away to talk toā€™ message.

it looks/plays really quite good here ā€¦

Ā 
edit: make sure that the distance between the innkeeper and the waypoint is kept less than DEFAULT_DIST_DIALOG

edit2: all this relies on the innkeeper being ā€œtrappedā€ behind the walkmesh-cutter

2 Likes

Just tried out your script ingame. It worked flawlessly! Thank you so much!

I still donā€™t understand why my second script didnā€™t work though. Maybe it has something to do with float range in ActionMoveToObject?
By the way, I do not fully understand what you mean by ā€œdo not put OBJECT_SELF directly into the next call/callsā€

Edit: I tried it in my other inn as well (Iā€™ve got two in this module) and it worked splendidly there as well. Iā€™m suprised how pleased I am to see the PC speaking to the bartender/innkeeper without running around the counter. I donā€™t think I realized how much this has annoyed me before. So again, kevL_s, thank you for all your help!

i donā€™t know either. The only thing that stands out is that this

AssignCommand(oPC, ActionStartConversation(oInnkeeper));

is usually

AssignCommand(oInnkeeper, ActionStartConversation(oPC));

but it could be, you know, just dialog intricacies

Because those next calls are being Assigned to a different actor ā€¦

eg. This would pass ā€˜oPcā€™ (the assignee) into the BeginDialog() funct. (instead of ā€˜oSpeakerā€™)

AssignCommand(oPc, ActionDoCommand(BeginDialog(OBJECT_SELF)));

i did ā€¦ Pc always runs behind the counter and i think ā€œyou j*rkā€ ā€¦ so yeh, itā€™s a neat little fix/workaround i guess  :)

3 Likes

+1

1 Like