Kexikus

Making a NPC leave an area

Recommended Posts

So, I'm trying to force an NPC to leave a module by going through the same door the player goes through when changing the module.

But since that door is locked at that time, I want the NPC to open the door and close it once he went through it.

 

I managed to open the door, close the door, lock it and to force the NPC to go somewhere but no matter what I do, he does not go through the open! door even when the coordinates set are behind the door. Is there something I'm missing?

 

Here's the (probably pretty bad) script I have so far:

void main(){

  object oNPC=GetObjectByTag("kor33b_belaya");

  float x=88.44;
  float y=-5.2;
  float z=53.51;                        

  int bRun=TRUE;
  vector vExit=Vector(x,y,z);
  location lExit=Location(vExit,0.0f);

  object oDoor = GetObjectByTag("k33b_dor_academy", 0);

  SetLocked(oDoor, FALSE);
  AssignCommand (oDoor,ActionWait(0.0));
  AssignCommand (oDoor,ActionOpenDoor(oDoor));

  ActionDoCommand(SetCommandable(TRUE,oNPC));
  AssignCommand (oNPC,ActionForceMoveToLocation(lExit,bRun));
  AssignCommand (oNPC,ActionDoCommand(AssignCommand(oDoor,ActionCloseDoor(oDoor))));
  AssignCommand (oNPC,ActionDoCommand(SetLocked(oDoor,TRUE)));  
  AssignCommand (oNPC,ActionDoCommand(DestroyObject(oNPC)));

}

Any help would be great :D

Share this post


Link to post
Share on other sites

So, I'm trying to force an NPC to leave a module by going through the same door the player goes through when changing the module.

But since that door is locked at that time, I want the NPC to open the door and close it once he went through it.

 

I managed to open the door, close the door, lock it and to force the NPC to go somewhere but no matter what I do, he does not go through the open! door even when the coordinates set are behind the door. Is there something I'm missing?

 

Here's the (probably pretty bad) script I have so far:

void main(){

  object oNPC=GetObjectByTag("kor33b_belaya");

  float x=88.44;
  float y=-5.2;
  float z=53.51;                        

  int bRun=TRUE;
  vector vExit=Vector(x,y,z);
  location lExit=Location(vExit,0.0f);

  object oDoor = GetObjectByTag("k33b_dor_academy", 0);

  SetLocked(oDoor, FALSE);
  AssignCommand (oDoor,ActionWait(0.0));
  AssignCommand (oDoor,ActionOpenDoor(oDoor));

  ActionDoCommand(SetCommandable(TRUE,oNPC));
  AssignCommand (oNPC,ActionForceMoveToLocation(lExit,bRun));
  AssignCommand (oNPC,ActionDoCommand(AssignCommand(oDoor,ActionCloseDoor(oDoor))));
  AssignCommand (oNPC,ActionDoCommand(SetLocked(oDoor,TRUE)));  
  AssignCommand (oNPC,ActionDoCommand(DestroyObject(oNPC)));

}
Any help would be great :D

 

 

 

Perhaps this might work?

 

void main(){

 

object oNPC=GetObjectByTag("kor33b_belaya");

 

float x=88.44;

float y=-5.2;

float z=53.51;

 

int bRun=TRUE;

vector vExit=Vector(x,y,z);

location lExit=Location(vExit,0.0f);

 

object oDoor = GetObjectByTag("k33b_dor_academy", 0);

 

SetLocked(oDoor, FALSE);

AssignCommand (oDoor,ActionOpenDoor(oDoor));

 

SetCommandable(TRUE,oNPC);

DelayCommand(2.0, AssignCommand (oNPC,ActionForceMoveToLocation(lExit,bRun)));

DelayCommand(10.0, AssignCommand(oDoor,ActionCloseDoor(oDoor)));

DelayCommand(11.5, SetLocked(oDoor,TRUE));

DelayCommand(12.0, DestroyObject(oNPC));

 

}

 

EDIT: If that above doesn't work, examine this: http://www.lucasforums.com/showpost.php?p=2791878&postcount=15

Share this post


Link to post
Share on other sites

That doesn't work either.

I have the feeling that the NPC can't go through the door for some reason even though it's open, because no matter how I edit the coordinates to be behind the door, the NPC will always stop right in front of it.

 

So, my guess would be that the script is basically working and either I'm too dumb to enter the right coordinates or there is something blocking the NPC from going through that door...

 

Edit: Checked your link and made some tests and it seems like the issue is that the door is not fully opened when the NPC starts moving, resulting in the behavior I described.

Share this post


Link to post
Share on other sites

Then add another vector that is in front of the door and start by moving the NPC to that vector instead. Then, change the DelayCommand for moving the NPC from 2.0 to 4.0. If that doesn't help, let us know.

Share this post


Link to post
Share on other sites

Thanks for the tip but I already managed to do it :)

 

Here's the script that worked in the end:

void main(){

object oNPC=GetObjectByTag("kor33b_belaya");

float x=88.44;
float y=-5.2;
float z=58.51;

int bRun=FALSE;
vector vExit=Vector(x,y,z);
location lExit=Location(vExit,0.0f);

object oDoor = GetObjectByTag("k33b_dor_academy", 0);

ActionPauseConversation();

SetLocked(oDoor, FALSE);
DelayCommand(4.0, AssignCommand (oDoor,ActionOpenDoor(oDoor)));

SetCommandable(TRUE,oNPC);
DelayCommand(0.0, AssignCommand (oNPC,ActionForceMoveToLocation(lExit,bRun)));
DelayCommand(7.0, AssignCommand (oNPC,ActionForceMoveToLocation(lExit,bRun)));
DelayCommand(8.5, AssignCommand(oDoor,ActionCloseDoor(oDoor)));
DelayCommand(8.5, SetLocked(oDoor,TRUE));
DelayCommand(11.0, DestroyObject(oNPC));

DelayCommand(3.5, ActionResumeConversation());

}

I also paused the conversation for 3.5 seconds to stop the player from cheating himself through a door that's supposed to be locked^^

 

But I have two new and somewhat related questions:

 

Is there a way to stack commands? What I mean is that for example, the first command forces an NPC to walk somewhere and the second one does something else. Is there a way to make it so that the second one is triggered only after the first command is done, i.e. the NPC has walked to his destination.

 

And the second question is: How do I make it so that a dialogue is triggered once the player is near enough?

Share this post


Link to post
Share on other sites

I assume the NPC 'jumps' past the door? Since from what I know if a door is opened inside a conversation, only after the conversation is over and the real game starts does the game stops blocking at that specific section.

 

An extremely cheatery work-around would be to open the door before the conversation, then close it during the conversation, then do the regular "open/close" stuff as regular.

(This is pretty much how the Atris door scene is done)

Share this post


Link to post
Share on other sites

I assume the NPC 'jumps' past the door? Since from what I know if a door is opened inside a conversation, only after the conversation is over and the real game starts does the game stops blocking at that specific section.

 

An extremely cheatery work-around would be to open the door before the conversation, then close it during the conversation, then do the regular "open/close" stuff as regular.

(This is pretty much how the Atris door scene is done)

 

No, she just stops right infront of the door. But as I said, I managed to "fix" it.

Share this post


Link to post
Share on other sites

To answer your second question, the best way to "trigger" a conversation based on proximity is to add a trigger, which will point to a script, which will look something like this:

void main() {
  object oNPC = GetObjectByTag("tag_of_npc");
  object oTrig = GetObjectByTag("tag_of_trigger");
  string sDialog = "name_of_dlg";
  AssignCommand(GetFirstPC(), ActionStartConversation(oNPC, sDialog);
  DestroyObject(oTrig, 1.0);
}

Obviously, you'd replace everything in quotations with the appropriate info, leaving the quotation marks.

 

What this will (should) do is fire the dialog once you walk into the trigger, then it will destroy the trigger, preventing the game from trying to fire the dialog again.

Share this post


Link to post
Share on other sites

To answer your second question, the best way to "trigger" a conversation based on proximity is to add a trigger, which will point to a script, which will look something like this:

void main() {
  object oNPC = GetObjectByTag("tag_of_npc");
  object oTrig = GetObjectByTag("tag_of_trigger");
  string sDialog = "name_of_dlg";
  AssignCommand(GetFirstPC(), ActionStartConversation(oNPC, sDialog);
  DestroyObject(oTrig, 1.0);
}

Obviously, you'd replace everything in quotations with the appropriate info.

 

What this will (should) do is fire the dialog once you walk into the trigger, then it will destroy the trigger, preventing the game from trying to fire the dialog again.

 

Oh, that's the part I forgot! :D

 

I walked him through triggers this morning in the chat, but I forgot to do the DestroyObject part in the script...

Share this post


Link to post
Share on other sites

To answer your second question, the best way to "trigger" a conversation based on proximity is to add a trigger, which will point to a script, which will look something like this:

void main() {
  object oNPC = GetObjectByTag("tag_of_npc");
  object oTrig = GetObjectByTag("tag_of_trigger");
  string sDialog = "name_of_dlg";
  AssignCommand(GetFirstPC(), ActionStartConversation(oNPC, sDialog);
  DestroyObject(oTrig, 1.0);
}

Obviously, you'd replace everything in quotations with the appropriate info, leaving the quotation marks.

 

What this will (should) do is fire the dialog once you walk into the trigger, then it will destroy the trigger, preventing the game from trying to fire the dialog again.

 

Oh, that's the part I forgot! :D

 

I walked him through triggers this morning in the chat, but I forgot to do the DestroyObject part in the script...

 

Thanks, both of you :)

 

I haven't had the time to try the trigger but I was wondering if it wouldn't trigger the conversation everytime you go there. But with that additional part of the script I should be able to make it work.

Share this post


Link to post
Share on other sites

OE rather doesn't destroy the trigger, but rather adds a local to it, then checks if it's already set. If not, trigger is available.

Very handy if you want to use the same trigger for multiple events (like say, the exit trigger in Dxun's Mandalorian Camp or the EH enter trigger on Nar Shaddaa).

Share this post


Link to post
Share on other sites

Hmm, I have a question there, regarding how the game works: does that work, moving an NPC through a door into another module? I.e. after the creature left the module, does it appear in the target module when the PC then also moves through the door?

 

Or do you need to fake that, by creating a copy of the creature in the target module (either statically, or from a script)?

 

Somewhat relatedly, does GetObjectByTag() (and similar functions) work for objects outside the current module? I.e. if the PC is in module Foo1, and there's a module Foo2 with an object Bar2 in it, can I call, while inside Foo1, GetObjectByTag("Bar2") and have it return the object inside Foo2? I've always assumed that doesn't work; is that assumption correct?

Share this post


Link to post
Share on other sites

OE rather doesn't destroy the trigger, but rather adds a local to it, then checks if it's already set. If not, trigger is available.

Very handy if you want to use the same trigger for multiple events (like say, the exit trigger in Dxun's Mandalorian Camp or the EH enter trigger on Nar Shaddaa).

Yeah, K1 does that too. I believe it's UT_GetTrapTriggered or something like that from the k_inc_generic or k_inc_utility.

 

Hmm, I have a question there, regarding how the game works: does that work, moving an NPC through a door into another module? I.e. after the creature left the module, does it appear in the target module when the PC then also moves through the door?

 

Or do you need to fake that, by creating a copy of the creature in the target module (either statically, or from a script)?

 

Somewhat relatedly, does GetObjectByTag() (and similar functions) work for objects outside the current module? I.e. if the PC is in module Foo1, and there's a module Foo2 with an object Bar2 in it, can I call, while inside Foo1, GetObjectByTag("Bar2") and have it return the object inside Foo2? I've always assumed that doesn't work; is that assumption correct?

 

The KotOR games operate only on the loaded level, so faking it is very necessary. That should also answer your second question.

Share this post


Link to post
Share on other sites

The KotOR games operate only on the loaded level, so faking it is very necessary. That should also answer your second question.

Okay, thanks. So those assumptions I made (based on my more in-depth knowledge of NWN) are correct, then. :D

Share this post


Link to post
Share on other sites

GetObjectByTag() can, however, access objects in BIF files or the Override folder, if an object isn't made more specific in the GIT files (the way waypoints are).

Share this post


Link to post
Share on other sites

Wait, what? Does that mean that GetObjectByTag() reads all object template files (.ut?) the game has access to, and checks their tags?

 

EDIT: And since GetObjectByTag() returns an object, does it mean it creates an object according to the template?

Share this post


Link to post
Share on other sites

A slight misunderstanding, I believe. The GetObjectByTag() function can only be used in a module and only on the objects spawned in the module.

 

The CreateObject function, however, can use files from the Override, the module, and the BIF archives, in that order.

Share this post


Link to post
Share on other sites

Ah, okay, that would make more sense, yes (and again matches that huge list of mine with unverified assumptions :P). Thanks.

Share this post


Link to post
Share on other sites

A slight misunderstanding, I believe. The GetObjectByTag() function can only be used in a module and only on the objects spawned in the module.

 

The CreateObject function, however, can use files from the Override, the module, and the BIF archives, in that order.

 

Oops. CreateObject() is what I meant. My bad.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.